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