translator: class on stack allocation support
This commit is contained in:
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user