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 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)