translator: constructors accept classes by ref

This commit is contained in:
e5l
2016-07-18 17:10:47 +03:00
parent 445a19ec26
commit 90bb2998f6
4 changed files with 61 additions and 29 deletions
+33 -16
View File
@@ -1,33 +1,50 @@
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1) declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1)
declare i8* @malloc_static(i32) declare i8* @malloc_static(i32)
attributes #0 = { nounwind "stack-protector-buffer-size"="8" "target-cpu"="cortex-m3" "target-features"="+hwdiv,+strict-align" } 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 } %class.Simple = type { i32 }
define void @Simple(%class.Simple* %classvariable.this, i32 %i) #0 define void @Simple(%class.Simple* %classvariable.this, i32 %i) #0
{ {
%classvariable.this.addr = alloca %class.Simple, align 4 %classvariable.this.addr = alloca %class.Simple, align 4
%i.addr = alloca i32, align 4 %i.addr = alloca i32, align 4
store i32 %i, i32* %i.addr, align 4 store i32 %i, i32* %i.addr, align 4
%var1 = load i32* %i.addr, align 4 %var6 = load i32* %i.addr, align 4
%var2 = getelementptr inbounds %class.Simple* %classvariable.this.addr, i32 0, i32 0 %var7 = getelementptr inbounds %class.Simple* %classvariable.this.addr, i32 0, i32 0
store i32 %var1, i32* %var2, align 4 store i32 %var6, i32* %var7, align 4
%var3 = bitcast %class.Simple* %classvariable.this to i8* %var8 = bitcast %class.Simple* %classvariable.this to i8*
%var4 = bitcast %class.Simple* %classvariable.this.addr to i8* %var9 = 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) call void @llvm.memcpy.p0i8.p0i8.i64(i8* %var8, i8* %var9, i64 4, i32 4, i1 false)
ret void
}
define void @a() #0
{
ret void ret void
} }
define void @kotlin_main() #0 define void @kotlin_main() #0
{ {
%var6 = call i8* @malloc_static(i32 4) %var11 = call i8* @malloc_static(i32 4)
%var5 = bitcast i8* %var6 to %class.Simple* %var10 = bitcast i8* %var11 to %class.Simple*
call void @Simple(%class.Simple* %var5, i32 5) call void @Simple(%class.Simple* %var10, i32 5)
%managed.s.1 = alloca %class.Simple, align 4 %managed.s.1 = alloca %class.Simple, align 4
%var7 = load %class.Simple* %var5, align 4 %var12 = load %class.Simple* %var10, align 4
store %class.Simple %var7, %class.Simple* %managed.s.1, align 4 store %class.Simple %var12, %class.Simple* %managed.s.1, align 4
call void @a() %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 ret void
} }
@@ -34,6 +34,7 @@ class ClassCodegen(val state: TranslationState, val variableManager: VariableMan
if (!annotation) { if (!annotation) {
for (field in parameterList) { for (field in parameterList) {
val item = resolveType(field) val item = resolveType(field)
item.offset = offset
fields.add(item) fields.add(item)
fieldsIndex[item.label] = item fieldsIndex[item.label] = item
@@ -52,7 +53,7 @@ class ClassCodegen(val state: TranslationState, val variableManager: VariableMan
} }
generateStruct() generateStruct()
generateDefaultConstructor() generatePrimaryConstructor()
for (declaration in clazz.declarations) { for (declaration in clazz.declarations) {
when (declaration) { when (declaration) {
@@ -75,7 +76,7 @@ class ClassCodegen(val state: TranslationState, val variableManager: VariableMan
codeBuilder.createClass(name, fields) codeBuilder.createClass(name, fields)
} }
private fun generateDefaultConstructor() { private fun generatePrimaryConstructor() {
val argFields = ArrayList<LLVMVariable>() val argFields = ArrayList<LLVMVariable>()
val refType = type.makeClone() as LLVMReferenceType val refType = type.makeClone() as LLVMReferenceType
refType.addParam("sret") refType.addParam("sret")
@@ -103,18 +104,30 @@ class ClassCodegen(val state: TranslationState, val variableManager: VariableMan
codeBuilder.loadArgument(thisVariable, false) codeBuilder.loadArgument(thisVariable, false)
fields.forEach { fields.forEach {
val loadVariable = LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope()) if (it.type !is LLVMReferenceType) {
codeBuilder.loadArgument(loadVariable) val loadVariable = LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope())
codeBuilder.loadArgument(loadVariable)
}
} }
} }
private fun generateAssignments() { private fun generateAssignments() {
fields.forEach { fields.forEach {
val argument = codeBuilder.getNewVariable(it.type) when (it.type) {
codeBuilder.loadVariable(argument, LLVMVariable("${it.label}.addr", it.type, scope = LLVMRegisterScope(), pointer = 1)) is LLVMReferenceType -> {
val classField = codeBuilder.getNewVariable(it.type, pointer = 1) 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.loadClassField(classField, LLVMVariable("classvariable.this.addr", type, scope = LLVMRegisterScope(), pointer = 1), (it as LLVMClassVariable).offset)
codeBuilder.storeVariable(classField, argument) 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()) val result = LLVMMapStandardType(field.name!!, ktType, LLVMRegisterScope())
if (result.type is LLVMReferenceType) { 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")) { if (annotations.contains("Plain")) {
@@ -117,7 +117,7 @@ class LLVMBuilder(val arm: Boolean) {
} }
fun loadClassField(target: LLVMVariable, source: LLVMVariable, offset: Int) { 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) localCode.appendln(code)
} }
@@ -131,7 +131,7 @@ class LLVMBuilder(val arm: Boolean) {
} }
fun storeVariable(target: LLVMVariable, source: LLVMSingleValue) { 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) localCode.appendln(code)
} }
@@ -3,4 +3,4 @@ package org.kotlinnative.translator.llvm
import org.kotlinnative.translator.llvm.types.LLVMType 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)