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 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)
|
||||||
|
|||||||
Reference in New Issue
Block a user