diff --git a/car_llvmkot/kotlib/kotlin_main.ll b/car_llvmkot/kotlib/kotlin_main.ll index b562df0a884..b8bc562e3b2 100644 --- a/car_llvmkot/kotlib/kotlin_main.ll +++ b/car_llvmkot/kotlib/kotlin_main.ll @@ -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 } diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt index fa9479b1786..202bfbe770a 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt @@ -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() 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")) { diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt index bfc33772362..9f48ebbb23c 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt @@ -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) } diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMClassVariable.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMClassVariable.kt index fbb697f9616..ea47edc1a9c 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMClassVariable.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMClassVariable.kt @@ -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)