translator: class on stack allocation support

This commit is contained in:
e5l
2016-07-12 19:40:10 +03:00
parent bcba00d3b5
commit 4f85a7fc30
5 changed files with 51 additions and 8 deletions
@@ -21,6 +21,7 @@ class ClassCodegen(val state: TranslationState, val clazz: KtClass, val codeBuil
val native: Boolean
val fields = ArrayList<LLVMVariable>()
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())
@@ -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<LLVMVariable>()
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)
}
@@ -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}")
@@ -5,5 +5,5 @@ import org.kotlinnative.translator.llvm.types.LLVMType
class LLVMCall(val returnType: LLVMType, val name: String, val arguments: List<LLVMVariable>) : LLVMNode() {
override fun toString(): String =
"call $returnType $name(${arguments.joinToString { "${it.type} ${it.label}" }})"
"call $returnType $name(${arguments.joinToString { "${it.getType()} ${it.label}" }})"
}
@@ -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()