diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt index 1a1c91abb2c..9e38a2ab109 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt @@ -21,6 +21,7 @@ class ClassCodegen(val state: TranslationState, val clazz: KtClass, val codeBuil val native: Boolean val fields = ArrayList() val name = "%class.${clazz.name}" + val constructorName = "@${clazz.name}" val type: LLVMType = parseLLVMType(name) val size: Int @@ -66,7 +67,7 @@ class ClassCodegen(val state: TranslationState, val clazz: KtClass, val codeBuil val refType = type.makeClone() as LLVMReferenceType refType.addParam("sret") - val thisField = LLVMVariable("instance", refType, clazz.name, true) + val thisField = LLVMVariable("instance", refType, clazz.name, true) argFields.add(thisField) argFields.addAll(fields) @@ -95,16 +96,16 @@ class ClassCodegen(val state: TranslationState, val clazz: KtClass, val codeBuil private fun generateAssignments() { fields.forEach { val argument = codeBuilder.getNewVariable(it.type) - codeBuilder.loadVariable(argument, LLVMVariable("%${it.label}.addr", it.type, "", true)) + codeBuilder.loadVariable(argument, LLVMVariable("%${it.label}.addr", it.type, pointer = true)) val classField = codeBuilder.getNewVariable(it.type, true) - codeBuilder.loadClassField(classField, LLVMVariable("%instance.addr", type, "", true), (it as LLVMClassVariable).offset) + codeBuilder.loadClassField(classField, LLVMVariable("%instance.addr", type, pointer = true), (it as LLVMClassVariable).offset) codeBuilder.storeVariable(classField, argument) } } private fun generateReturn() { - val dst = LLVMVariable("%instance", type, "", true) - val src = LLVMVariable("%instance.addr", type, "", true) + val dst = LLVMVariable("%instance", type, pointer = true) + val src = LLVMVariable("%instance.addr", type, pointer = true) val castedDst = codeBuilder.bitcast(dst, LLVMCharType()) val castedSrc = codeBuilder.bitcast(src, LLVMCharType()) diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt index da4eb98f44a..fa75ea72e40 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt @@ -120,7 +120,23 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction } private fun evaluteConstructorCallExpression(expr: KtCallExpression): LLVMNode? { - return null + val function = expr.firstChild.firstChild + val descriptor = state.classes[function.text] ?: return null + val names = parseArgList(expr + .firstChild + .getNextSiblingIgnoringWhitespaceAndComments() + ?.firstChild).mapIndexed { i: Int, s: String -> + LLVMVariable(s, descriptor.fields[i].type, pointer = descriptor.fields[i].pointer) + }.toList() + + + return LLVMConstructorCall( + descriptor.type, fun(thisVar): LLVMCall { + val args = ArrayList() + args.add(thisVar) + args.addAll(names) + return LLVMCall(LLVMVoidType(), descriptor.constructorName, args) + }) } private fun evaluteFunctionCallExpression(expr: KtCallExpression): LLVMNode? { @@ -132,7 +148,7 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction .getNextSiblingIgnoringWhitespaceAndComments() ?.firstChild) - return LLVMCall(descriptor.returnType, "@${function.text}", descriptor.args?.mapIndexed { + return LLVMCall(descriptor.returnType, "@${descriptor.name}", descriptor.args?.mapIndexed { i: Int, variable: LLVMVariable -> LLVMVariable(names[i], variable.type) } ?: listOf()) @@ -201,6 +217,12 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction codeBuilder.addConstant(newVar, assignExpression) variableManager.addVariable(identifier.text, newVar, scopeDepth) } + is LLVMConstructorCall -> { + val result = LLVMVariable("%${identifier!!.text}", assignExpression.type) + codeBuilder.allocVar(result) + result.pointer = true + codeBuilder.addLLVMCode(assignExpression.call(result).toString()) + } else -> { codeBuilder.addAssignment(LLVMVariable("%${identifier!!.text}", null, identifier.text), assignExpression) } 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 9c0269ddda2..4dc213ae211 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt @@ -8,6 +8,15 @@ class LLVMBuilder { private var llvmCode: StringBuilder = StringBuilder() private var variableCount = 0 + init { + initBuilder() + } + + private fun initBuilder() { + val memcpy = "declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1)" + llvmCode.appendln(memcpy) + } + fun getNewVariable(type: LLVMType?, pointer: Boolean = false, kotlinName: String? = null): LLVMVariable { variableCount++ return LLVMVariable("%var$variableCount", type, kotlinName = kotlinName, pointer = pointer) @@ -56,6 +65,7 @@ class LLVMBuilder { fun clean() { llvmCode = StringBuilder() + initBuilder() } fun addAssignment(llvmVariable: LLVMVariable, rhs: LLVMNode) { @@ -89,6 +99,10 @@ class LLVMBuilder { llvmCode.appendln(code) } + fun allocVar(target: LLVMVariable) { + llvmCode.appendln("$target = alloca ${target.type}, align ${target.type?.align!!}") + } + fun addVariableByRef(targetVariable: LLVMVariable, sourceVariable: LLVMVariable, store: Boolean) { llvmCode.appendln("$targetVariable = alloca ${sourceVariable.type}, align ${sourceVariable.type?.align}") diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMCall.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMCall.kt index 19f1c1d0909..22b079dd599 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMCall.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMCall.kt @@ -5,5 +5,5 @@ import org.kotlinnative.translator.llvm.types.LLVMType class LLVMCall(val returnType: LLVMType, val name: String, val arguments: List) : LLVMNode() { override fun toString(): String = - "call $returnType $name(${arguments.joinToString { "${it.type} ${it.label}" }})" + "call $returnType $name(${arguments.joinToString { "${it.getType()} ${it.label}" }})" } diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMConstructorCall.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMConstructorCall.kt new file mode 100644 index 00000000000..2eff3826daa --- /dev/null +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMConstructorCall.kt @@ -0,0 +1,6 @@ +package org.kotlinnative.translator.llvm + +import org.kotlinnative.translator.llvm.types.LLVMType + +class LLVMConstructorCall(val type: LLVMType, val call: (LLVMVariable) -> LLVMCall) : LLVMNode() +