translator: add default constructors
This commit is contained in:
@@ -12,9 +12,7 @@ import org.kotlinnative.translator.llvm.LLVMBuilder
|
||||
import org.kotlinnative.translator.llvm.LLVMClassVariable
|
||||
import org.kotlinnative.translator.llvm.LLVMFunctionDescriptor
|
||||
import org.kotlinnative.translator.llvm.LLVMVariable
|
||||
import org.kotlinnative.translator.llvm.types.LLVMType
|
||||
import org.kotlinnative.translator.llvm.types.LLVMVoidType
|
||||
import org.kotlinnative.translator.llvm.types.parseLLVMType
|
||||
import org.kotlinnative.translator.llvm.types.*
|
||||
import java.util.*
|
||||
|
||||
class ClassCodegen(val state: TranslationState, val clazz: KtClass, val codeBuilder: LLVMBuilder) {
|
||||
@@ -22,6 +20,8 @@ class ClassCodegen(val state: TranslationState, val clazz: KtClass, val codeBuil
|
||||
val annotation: Boolean
|
||||
val native: Boolean
|
||||
val fields = ArrayList<LLVMVariable>()
|
||||
val name = "%class.${clazz.name}"
|
||||
val type: LLVMType = parseLLVMType(name)
|
||||
val size: Int
|
||||
|
||||
init {
|
||||
@@ -35,8 +35,7 @@ class ClassCodegen(val state: TranslationState, val clazz: KtClass, val codeBuil
|
||||
if (!annotation) {
|
||||
for (field in parameterList) {
|
||||
val type = getNativeType(field) ?: parseLLVMType((field.typeReference?.typeElement as KtUserType).referencedName!!)
|
||||
val field = LLVMClassVariable(field.name!!, type, offset)
|
||||
fields.add(field)
|
||||
fields.add(LLVMClassVariable(field.name!!, type, offset))
|
||||
|
||||
currentSize += type.size
|
||||
offset++
|
||||
@@ -63,20 +62,56 @@ class ClassCodegen(val state: TranslationState, val clazz: KtClass, val codeBuil
|
||||
}
|
||||
|
||||
private fun generateDefaultConstructor() {
|
||||
codeBuilder.addLLVMCode(LLVMFunctionDescriptor(clazz.name!!, fields, LLVMVoidType()))
|
||||
val argFields = ArrayList<LLVMVariable>()
|
||||
val refType = type.makeClone() as LLVMReferenceType
|
||||
refType.addParam("sret")
|
||||
|
||||
val thisField = LLVMVariable("instance", refType, clazz.name, true)
|
||||
|
||||
argFields.add(thisField)
|
||||
argFields.addAll(fields)
|
||||
|
||||
codeBuilder.addLLVMCode(LLVMFunctionDescriptor(clazz.name!!, argFields, LLVMVoidType()))
|
||||
|
||||
codeBuilder.addStartExpression()
|
||||
generateLoadArguments()
|
||||
generateLoadArguments(thisField)
|
||||
generateAssignments()
|
||||
generateReturn()
|
||||
codeBuilder.addVoidReturn()
|
||||
codeBuilder.addEndExpression()
|
||||
}
|
||||
|
||||
private fun generateLoadArguments() {
|
||||
private fun generateLoadArguments(thisField: LLVMVariable) {
|
||||
|
||||
val thisVariable = LLVMVariable("%${thisField.label}", thisField.type, thisField.label, true)
|
||||
codeBuilder.loadArgument(thisVariable, false)
|
||||
|
||||
fields.forEach {
|
||||
val loadVariable = LLVMVariable("%${it.label}", it.type, it.label)
|
||||
codeBuilder.loadVariable(loadVariable)
|
||||
codeBuilder.loadArgument(loadVariable)
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateAssignments() {
|
||||
fields.forEach {
|
||||
val argument = codeBuilder.getNewVariable(it.type)
|
||||
codeBuilder.loadVariable(argument, LLVMVariable("%${it.label}.addr", it.type, "", true))
|
||||
val classField = codeBuilder.getNewVariable(it.type, true)
|
||||
codeBuilder.loadClassField(classField, LLVMVariable("%instance.addr", type, "", 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 castedDst = codeBuilder.bitcast(dst, LLVMCharType())
|
||||
val castedSrc = codeBuilder.bitcast(src, LLVMCharType())
|
||||
|
||||
codeBuilder.memcpy(castedDst, castedSrc, size)
|
||||
}
|
||||
|
||||
private fun getNativeType(field: KtParameter): LLVMType? {
|
||||
for (annotation in field.annotationEntries) {
|
||||
val annotationDescriptor = state.bindingContext.get(BindingContext.ANNOTATION, annotation)
|
||||
|
||||
@@ -65,8 +65,8 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
|
||||
|
||||
private fun generateLoadArguments() {
|
||||
args?.forEach {
|
||||
val loadVariable = LLVMVariable("%${it.label}", it.type, it.label, true)
|
||||
codeBuilder.loadVariable(loadVariable)
|
||||
val loadVariable = LLVMVariable("%${it.label}", it.type, it.label, false)
|
||||
codeBuilder.loadArgument(loadVariable)
|
||||
variableManager.addVariable(it.label, loadVariable, 2)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ class LLVMBuilder {
|
||||
|
||||
fun getNewVariable(type: LLVMType?, pointer: Boolean = false): LLVMVariable {
|
||||
variableCount++
|
||||
return LLVMVariable("%var$variableCount", type, pointer = pointer)
|
||||
return LLVMVariable("%var$variableCount", type, "", pointer)
|
||||
}
|
||||
|
||||
fun addLLVMCode(code: String) {
|
||||
@@ -32,7 +32,6 @@ class LLVMBuilder {
|
||||
KtTokens.PLUS -> firstOp.type!!.operatorPlus(newVar, firstOp, secondOp)
|
||||
KtTokens.MINUS -> firstOp.type!!.operatorMinus(newVar, firstOp, secondOp)
|
||||
KtTokens.MUL -> firstOp.type!!.operatorTimes(newVar, firstOp, secondOp)
|
||||
KtTokens.EQ -> return moveVariableValue(secondOp, firstOp)
|
||||
else -> throw UnsupportedOperationException("Unknown binary operator")
|
||||
}
|
||||
|
||||
@@ -41,21 +40,6 @@ class LLVMBuilder {
|
||||
return newVar
|
||||
}
|
||||
|
||||
|
||||
private fun moveVariableValue(from: LLVMVariable, to: LLVMVariable): LLVMVariable {
|
||||
//%0 = load i32, i32* %y, align 4
|
||||
//store i32 %0, i32* %z, align 4
|
||||
//%1 = load i32, i32* %z, align 4
|
||||
llvmCode.appendln("VARIABLE from $from TO $to")
|
||||
/*
|
||||
val tmp1 = getNewVariable(from.type)
|
||||
val tmp2 = getNewVariable(to.type)
|
||||
llvmCode.appendln("$tmp1 = load ${tmp1.type}, ${tmp1.type}* $from, align ${tmp1.type?.align}")
|
||||
llvmCode.appendln("store ${tmp1.type} $tmp1, ${to.type}* $to, align ${to.type?.align}")
|
||||
llvmCode.appendln("$tmp2 = load ${tmp2.type}, ${tmp2.type}* $to, align ${to.type?.align}")*/
|
||||
return from
|
||||
}
|
||||
|
||||
fun clean() {
|
||||
llvmCode = StringBuilder()
|
||||
}
|
||||
@@ -72,17 +56,35 @@ class LLVMBuilder {
|
||||
llvmCode.appendln("ret void")
|
||||
}
|
||||
|
||||
fun loadVariable(llvmVariable: LLVMVariable) {
|
||||
addVariableByRef(llvmVariable, LLVMVariable("${llvmVariable.label}.addr", llvmVariable.type, llvmVariable.kotlinName, true))
|
||||
fun loadArgument(llvmVariable: LLVMVariable, store: Boolean = true) {
|
||||
addVariableByRef(LLVMVariable("${llvmVariable.label}.addr", llvmVariable.type, llvmVariable.kotlinName, true), llvmVariable, store)
|
||||
}
|
||||
|
||||
fun addVariableByRef(targetVariable: LLVMVariable, sourceVariable: LLVMVariable) {
|
||||
llvmCode.appendln("$sourceVariable = alloca ${sourceVariable.type}, align ${sourceVariable.type?.align}")
|
||||
llvmCode.appendln("store ${sourceVariable.type} $targetVariable, ${targetVariable.getType()} $sourceVariable, align ${targetVariable.type?.align}")
|
||||
fun loadVariable(target: LLVMVariable, source: LLVMVariable) {
|
||||
val code = "$target = load ${target.type}, ${source.getType()} $source, align ${target.type?.align!!}"
|
||||
llvmCode.appendln(code)
|
||||
}
|
||||
|
||||
fun loadClassField(target: LLVMVariable, source: LLVMVariable, offset: Int) {
|
||||
var code = "$target = getelementptr inbounds ${source.type}, ${source.type}* $source, i32 0, i32 $offset"
|
||||
llvmCode.appendln(code)
|
||||
}
|
||||
|
||||
fun storeVariable(target: LLVMVariable, source: LLVMVariable) {
|
||||
var code = "store ${source.type} $source, ${target.getType()} $target, align ${source.type?.align!!}"
|
||||
llvmCode.appendln(code)
|
||||
}
|
||||
|
||||
fun addVariableByRef(targetVariable: LLVMVariable, sourceVariable: LLVMVariable, store: Boolean) {
|
||||
llvmCode.appendln("$targetVariable = alloca ${sourceVariable.type}, align ${sourceVariable.type?.align}")
|
||||
|
||||
if (store) {
|
||||
llvmCode.appendln("store ${sourceVariable.getType()} $sourceVariable, ${targetVariable.getType()} $targetVariable, align ${targetVariable.type?.align}")
|
||||
}
|
||||
}
|
||||
|
||||
fun addVariableByValue(targetVariable: LLVMVariable, sourceVariable: LLVMVariable) {
|
||||
val tmp = getNewVariable(targetVariable.type, pointer = true)
|
||||
val tmp = getNewVariable(targetVariable.type, true)
|
||||
|
||||
llvmCode.appendln("$tmp = alloca ${tmp.type}, align ${tmp.type?.align}")
|
||||
llvmCode.appendln("store ${tmp.type} $sourceVariable, ${tmp.getType()} $tmp, align ${tmp.type?.align}")
|
||||
@@ -91,17 +93,28 @@ class LLVMBuilder {
|
||||
}
|
||||
|
||||
fun addConstant(sourceVariable: LLVMVariable): LLVMVariable {
|
||||
val target = getNewVariable(sourceVariable.type, pointer = sourceVariable.pointer)
|
||||
val target = getNewVariable(sourceVariable.type, sourceVariable.pointer)
|
||||
addVariableByValue(target, sourceVariable)
|
||||
return target
|
||||
}
|
||||
|
||||
|
||||
fun createClass(name: String, fields: List<LLVMVariable>) {
|
||||
val code = "@class.$name = type { ${fields.map { it.type }.joinToString()} }"
|
||||
val code = "%class.$name = type { ${fields.map { it.type }.joinToString()} }"
|
||||
llvmCode.appendln(code)
|
||||
}
|
||||
|
||||
fun bitcast(dst: LLVMVariable, llvmType: LLVMType): LLVMVariable {
|
||||
var empty = getNewVariable(llvmType, true)
|
||||
var code = "$empty = bitcast ${dst.getType()} $dst to $llvmType*"
|
||||
llvmCode.appendln(code)
|
||||
|
||||
return empty
|
||||
}
|
||||
|
||||
fun memcpy(castedDst: LLVMVariable, castedSrc: LLVMVariable, size: Int, align: Int = 4, volatile: Boolean = false) {
|
||||
var code = "call void @llvm.memcpy.p0i8.p0i8.i64(i8* $castedDst, i8* $castedSrc, i64 $size, i32 $align, i1 $volatile)"
|
||||
llvmCode.appendln(code)
|
||||
}
|
||||
|
||||
override fun toString() = llvmCode.toString()
|
||||
|
||||
}
|
||||
@@ -3,4 +3,4 @@ package org.kotlinnative.translator.llvm
|
||||
import org.kotlinnative.translator.llvm.types.LLVMType
|
||||
|
||||
|
||||
class LLVMClassVariable(label: String, type: LLVMType? = null, offset: Int = 0) : LLVMVariable(label, type)
|
||||
class LLVMClassVariable(label: String, type: LLVMType? = null, val offset: Int = 0) : LLVMVariable(label, type)
|
||||
|
||||
@@ -6,7 +6,7 @@ import org.kotlinnative.translator.llvm.types.*
|
||||
fun LLVMFunctionDescriptor(name: String, argTypes: List<LLVMVariable>?, returnType: LLVMType, declare: Boolean = false) =
|
||||
"${if (declare) "declare" else "define"} $returnType @$name(${
|
||||
argTypes?.mapIndexed { i: Int, s: LLVMVariable ->
|
||||
"${s.type} %${s.label}"
|
||||
"${s.getType()} %${s.label}"
|
||||
}?.joinToString() })"
|
||||
|
||||
fun LLVMMapStandardType(type: String): LLVMType = when (type) {
|
||||
|
||||
@@ -2,8 +2,7 @@ package org.kotlinnative.translator.llvm.types
|
||||
|
||||
class LLVMCharType() : LLVMType() {
|
||||
|
||||
override fun toString(): String = "i8"
|
||||
override val align = 1
|
||||
|
||||
override val size: Byte = 1
|
||||
override fun toString(): String = "i8"
|
||||
}
|
||||
|
||||
+7
-1
@@ -1,10 +1,16 @@
|
||||
package org.kotlinnative.translator.llvm.types
|
||||
|
||||
import java.util.*
|
||||
|
||||
class LLVMReferenceType(val type: String) : LLVMType() {
|
||||
|
||||
override val align = 4
|
||||
override val size: Byte = 4
|
||||
override fun toString() = "$type"
|
||||
|
||||
override fun toString() = type
|
||||
private val params = ArrayList<String>()
|
||||
|
||||
fun addParam(param: String) {
|
||||
params.add(param)
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package org.kotlinnative.translator.llvm.types
|
||||
class LLVMShortType() : LLVMType() {
|
||||
|
||||
override val size: Byte = 2
|
||||
override val align = 1
|
||||
|
||||
override val align = 2
|
||||
override fun toString(): String = "i16"
|
||||
}
|
||||
|
||||
@@ -4,12 +4,14 @@ import org.kotlinnative.translator.exceptions.UnimplementedException
|
||||
import org.kotlinnative.translator.llvm.LLVMExpression
|
||||
import org.kotlinnative.translator.llvm.LLVMVariable
|
||||
|
||||
abstract class LLVMType() {
|
||||
abstract class LLVMType() : Cloneable {
|
||||
|
||||
open fun operatorPlus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression = throw UnimplementedException()
|
||||
open fun operatorTimes(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression = throw UnimplementedException()
|
||||
open fun operatorMinus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression = throw UnimplementedException()
|
||||
|
||||
fun makeClone() = clone()
|
||||
|
||||
abstract val align: Int
|
||||
abstract val size: Byte
|
||||
}
|
||||
|
||||
@@ -3,8 +3,6 @@ package org.kotlinnative.translator.llvm.types
|
||||
class LLVMVoidType() : LLVMType() {
|
||||
|
||||
override val align = 0
|
||||
|
||||
override fun toString(): String = "void"
|
||||
override val size: Byte = 0
|
||||
|
||||
override fun toString(): String = "void"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user