translator: constructors accept classes by ref
This commit is contained in:
@@ -1,33 +1,50 @@
|
||||
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1)
|
||||
declare i8* @malloc_static(i32)
|
||||
attributes #0 = { nounwind "stack-protector-buffer-size"="8" "target-cpu"="cortex-m3" "target-features"="+hwdiv,+strict-align" }
|
||||
%class.ComplexRef = type { i32, %class.Simple* }
|
||||
define void @ComplexRef(%class.ComplexRef* %classvariable.this, i32 %i, %class.Simple* %s) #0
|
||||
{
|
||||
%classvariable.this.addr = alloca %class.ComplexRef, align 4
|
||||
%i.addr = alloca i32, align 4
|
||||
store i32 %i, i32* %i.addr, align 4
|
||||
%var1 = load i32* %i.addr, align 4
|
||||
%var2 = getelementptr inbounds %class.ComplexRef* %classvariable.this.addr, i32 0, i32 0
|
||||
store i32 %var1, i32* %var2, align 4
|
||||
%var3 = getelementptr inbounds %class.ComplexRef* %classvariable.this.addr, i32 0, i32 1
|
||||
store %class.Simple* %s, %class.Simple** %var3, align 4
|
||||
%var4 = bitcast %class.ComplexRef* %classvariable.this to i8*
|
||||
%var5 = bitcast %class.ComplexRef* %classvariable.this.addr to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %var4, i8* %var5, i64 8, i32 4, i1 false)
|
||||
ret void
|
||||
}
|
||||
%class.Simple = type { i32 }
|
||||
define void @Simple(%class.Simple* %classvariable.this, i32 %i) #0
|
||||
{
|
||||
%classvariable.this.addr = alloca %class.Simple, align 4
|
||||
%i.addr = alloca i32, align 4
|
||||
store i32 %i, i32* %i.addr, align 4
|
||||
%var1 = load i32* %i.addr, align 4
|
||||
%var2 = getelementptr inbounds %class.Simple* %classvariable.this.addr, i32 0, i32 0
|
||||
store i32 %var1, i32* %var2, align 4
|
||||
%var3 = bitcast %class.Simple* %classvariable.this to i8*
|
||||
%var4 = bitcast %class.Simple* %classvariable.this.addr to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %var3, i8* %var4, i64 4, i32 4, i1 false)
|
||||
ret void
|
||||
}
|
||||
define void @a() #0
|
||||
{
|
||||
%var6 = load i32* %i.addr, align 4
|
||||
%var7 = getelementptr inbounds %class.Simple* %classvariable.this.addr, i32 0, i32 0
|
||||
store i32 %var6, i32* %var7, align 4
|
||||
%var8 = bitcast %class.Simple* %classvariable.this to i8*
|
||||
%var9 = bitcast %class.Simple* %classvariable.this.addr to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %var8, i8* %var9, i64 4, i32 4, i1 false)
|
||||
ret void
|
||||
}
|
||||
define void @kotlin_main() #0
|
||||
{
|
||||
%var6 = call i8* @malloc_static(i32 4)
|
||||
%var5 = bitcast i8* %var6 to %class.Simple*
|
||||
call void @Simple(%class.Simple* %var5, i32 5)
|
||||
%var11 = call i8* @malloc_static(i32 4)
|
||||
%var10 = bitcast i8* %var11 to %class.Simple*
|
||||
call void @Simple(%class.Simple* %var10, i32 5)
|
||||
%managed.s.1 = alloca %class.Simple, align 4
|
||||
%var7 = load %class.Simple* %var5, align 4
|
||||
store %class.Simple %var7, %class.Simple* %managed.s.1, align 4
|
||||
call void @a()
|
||||
%var12 = load %class.Simple* %var10, align 4
|
||||
store %class.Simple %var12, %class.Simple* %managed.s.1, align 4
|
||||
%var14 = call i8* @malloc_static(i32 4)
|
||||
%var13 = bitcast i8* %var14 to %class.ComplexRef*
|
||||
call void @ComplexRef(%class.ComplexRef* %var13, i32 1, %class.Simple* %managed.s.1)
|
||||
%managed.i.1 = alloca %class.ComplexRef, align 4
|
||||
%var15 = load %class.ComplexRef* %var13, align 4
|
||||
store %class.ComplexRef %var15, %class.ComplexRef* %managed.i.1, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ class ClassCodegen(val state: TranslationState, val variableManager: VariableMan
|
||||
if (!annotation) {
|
||||
for (field in parameterList) {
|
||||
val item = resolveType(field)
|
||||
item.offset = offset
|
||||
|
||||
fields.add(item)
|
||||
fieldsIndex[item.label] = item
|
||||
@@ -52,7 +53,7 @@ class ClassCodegen(val state: TranslationState, val variableManager: VariableMan
|
||||
}
|
||||
|
||||
generateStruct()
|
||||
generateDefaultConstructor()
|
||||
generatePrimaryConstructor()
|
||||
|
||||
for (declaration in clazz.declarations) {
|
||||
when (declaration) {
|
||||
@@ -75,7 +76,7 @@ class ClassCodegen(val state: TranslationState, val variableManager: VariableMan
|
||||
codeBuilder.createClass(name, fields)
|
||||
}
|
||||
|
||||
private fun generateDefaultConstructor() {
|
||||
private fun generatePrimaryConstructor() {
|
||||
val argFields = ArrayList<LLVMVariable>()
|
||||
val refType = type.makeClone() as LLVMReferenceType
|
||||
refType.addParam("sret")
|
||||
@@ -103,18 +104,30 @@ class ClassCodegen(val state: TranslationState, val variableManager: VariableMan
|
||||
codeBuilder.loadArgument(thisVariable, false)
|
||||
|
||||
fields.forEach {
|
||||
val loadVariable = LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope())
|
||||
codeBuilder.loadArgument(loadVariable)
|
||||
if (it.type !is LLVMReferenceType) {
|
||||
val loadVariable = LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope())
|
||||
codeBuilder.loadArgument(loadVariable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateAssignments() {
|
||||
fields.forEach {
|
||||
val argument = codeBuilder.getNewVariable(it.type)
|
||||
codeBuilder.loadVariable(argument, LLVMVariable("${it.label}.addr", it.type, scope = LLVMRegisterScope(), pointer = 1))
|
||||
val classField = codeBuilder.getNewVariable(it.type, pointer = 1)
|
||||
codeBuilder.loadClassField(classField, LLVMVariable("classvariable.this.addr", type, scope = LLVMRegisterScope(), pointer = 1), (it as LLVMClassVariable).offset)
|
||||
codeBuilder.storeVariable(classField, argument)
|
||||
when (it.type) {
|
||||
is LLVMReferenceType -> {
|
||||
val classField = codeBuilder.getNewVariable(it.type, pointer = it.pointer + 1)
|
||||
codeBuilder.loadClassField(classField, LLVMVariable("classvariable.this.addr", type, scope = LLVMRegisterScope(), pointer = 1), (it as LLVMClassVariable).offset)
|
||||
codeBuilder.storeVariable(classField, it)
|
||||
}
|
||||
else -> {
|
||||
val argument = codeBuilder.getNewVariable(it.type, it.pointer)
|
||||
codeBuilder.loadVariable(argument, LLVMVariable("${it.label}.addr", it.type, scope = LLVMRegisterScope(), pointer = it.pointer + 1))
|
||||
val classField = codeBuilder.getNewVariable(it.type, pointer = 1)
|
||||
codeBuilder.loadClassField(classField, LLVMVariable("classvariable.this.addr", type, scope = LLVMRegisterScope(), pointer = 1), (it as LLVMClassVariable).offset)
|
||||
codeBuilder.storeVariable(classField, argument)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,7 +148,9 @@ class ClassCodegen(val state: TranslationState, val variableManager: VariableMan
|
||||
val result = LLVMMapStandardType(field.name!!, ktType, LLVMRegisterScope())
|
||||
|
||||
if (result.type is LLVMReferenceType) {
|
||||
(result.type as LLVMReferenceType).prefix = "class"
|
||||
val type = result.type as LLVMReferenceType
|
||||
type.prefix = "class"
|
||||
type.byRef = true
|
||||
}
|
||||
|
||||
if (annotations.contains("Plain")) {
|
||||
|
||||
@@ -117,7 +117,7 @@ class LLVMBuilder(val arm: Boolean) {
|
||||
}
|
||||
|
||||
fun loadClassField(target: LLVMVariable, source: LLVMVariable, offset: Int) {
|
||||
val code = "$target = getelementptr inbounds ${source.type}* $source, i32 0, i32 $offset"
|
||||
val code = "$target = getelementptr inbounds ${source.getType()} $source, i32 0, i32 $offset"
|
||||
localCode.appendln(code)
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ class LLVMBuilder(val arm: Boolean) {
|
||||
}
|
||||
|
||||
fun storeVariable(target: LLVMVariable, source: LLVMSingleValue) {
|
||||
val code = "store ${source.type} $source, ${target.getType()} $target, align ${source.type?.align!!}"
|
||||
val code = "store ${source.getType()} $source, ${target.getType()} $target, align ${source.type?.align!!}"
|
||||
localCode.appendln(code)
|
||||
}
|
||||
|
||||
|
||||
@@ -3,4 +3,4 @@ package org.kotlinnative.translator.llvm
|
||||
import org.kotlinnative.translator.llvm.types.LLVMType
|
||||
|
||||
|
||||
class LLVMClassVariable(label: String, type: LLVMType, pointer: Int = 0, val offset: Int = 0) : LLVMVariable(label, type, pointer = pointer)
|
||||
class LLVMClassVariable(label: String, type: LLVMType, pointer: Int = 0, var offset: Int = 0) : LLVMVariable(label, type, pointer = pointer)
|
||||
|
||||
Reference in New Issue
Block a user