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 native: Boolean
val fields = ArrayList<LLVMVariable>() val fields = ArrayList<LLVMVariable>()
val name = "%class.${clazz.name}" val name = "%class.${clazz.name}"
val constructorName = "@${clazz.name}"
val type: LLVMType = parseLLVMType(name) val type: LLVMType = parseLLVMType(name)
val size: Int val size: Int
@@ -66,7 +67,7 @@ class ClassCodegen(val state: TranslationState, val clazz: KtClass, val codeBuil
val refType = type.makeClone() as LLVMReferenceType val refType = type.makeClone() as LLVMReferenceType
refType.addParam("sret") refType.addParam("sret")
val thisField = LLVMVariable("instance", refType, clazz.name, true) val thisField = LLVMVariable("instance", refType, clazz.name, true)
argFields.add(thisField) argFields.add(thisField)
argFields.addAll(fields) argFields.addAll(fields)
@@ -95,16 +96,16 @@ class ClassCodegen(val state: TranslationState, val clazz: KtClass, val codeBuil
private fun generateAssignments() { private fun generateAssignments() {
fields.forEach { fields.forEach {
val argument = codeBuilder.getNewVariable(it.type) 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) 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) codeBuilder.storeVariable(classField, argument)
} }
} }
private fun generateReturn() { private fun generateReturn() {
val dst = LLVMVariable("%instance", type, "", true) val dst = LLVMVariable("%instance", type, pointer = true)
val src = LLVMVariable("%instance.addr", type, "", true) val src = LLVMVariable("%instance.addr", type, pointer = true)
val castedDst = codeBuilder.bitcast(dst, LLVMCharType()) val castedDst = codeBuilder.bitcast(dst, LLVMCharType())
val castedSrc = codeBuilder.bitcast(src, 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? { 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? { private fun evaluteFunctionCallExpression(expr: KtCallExpression): LLVMNode? {
@@ -132,7 +148,7 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
.getNextSiblingIgnoringWhitespaceAndComments() .getNextSiblingIgnoringWhitespaceAndComments()
?.firstChild) ?.firstChild)
return LLVMCall(descriptor.returnType, "@${function.text}", descriptor.args?.mapIndexed { return LLVMCall(descriptor.returnType, "@${descriptor.name}", descriptor.args?.mapIndexed {
i: Int, variable: LLVMVariable -> i: Int, variable: LLVMVariable ->
LLVMVariable(names[i], variable.type) LLVMVariable(names[i], variable.type)
} ?: listOf()) } ?: listOf())
@@ -201,6 +217,12 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
codeBuilder.addConstant(newVar, assignExpression) codeBuilder.addConstant(newVar, assignExpression)
variableManager.addVariable(identifier.text, newVar, scopeDepth) 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 -> { else -> {
codeBuilder.addAssignment(LLVMVariable("%${identifier!!.text}", null, identifier.text), assignExpression) codeBuilder.addAssignment(LLVMVariable("%${identifier!!.text}", null, identifier.text), assignExpression)
} }
@@ -8,6 +8,15 @@ class LLVMBuilder {
private var llvmCode: StringBuilder = StringBuilder() private var llvmCode: StringBuilder = StringBuilder()
private var variableCount = 0 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 { fun getNewVariable(type: LLVMType?, pointer: Boolean = false, kotlinName: String? = null): LLVMVariable {
variableCount++ variableCount++
return LLVMVariable("%var$variableCount", type, kotlinName = kotlinName, pointer = pointer) return LLVMVariable("%var$variableCount", type, kotlinName = kotlinName, pointer = pointer)
@@ -56,6 +65,7 @@ class LLVMBuilder {
fun clean() { fun clean() {
llvmCode = StringBuilder() llvmCode = StringBuilder()
initBuilder()
} }
fun addAssignment(llvmVariable: LLVMVariable, rhs: LLVMNode) { fun addAssignment(llvmVariable: LLVMVariable, rhs: LLVMNode) {
@@ -89,6 +99,10 @@ class LLVMBuilder {
llvmCode.appendln(code) 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) { fun addVariableByRef(targetVariable: LLVMVariable, sourceVariable: LLVMVariable, store: Boolean) {
llvmCode.appendln("$targetVariable = alloca ${sourceVariable.type}, align ${sourceVariable.type?.align}") 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() { class LLVMCall(val returnType: LLVMType, val name: String, val arguments: List<LLVMVariable>) : LLVMNode() {
override fun toString(): String = 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()