translator: add default constructors

This commit is contained in:
e5l
2016-07-12 18:14:25 +03:00
parent 08eeafa977
commit 6972a4d658
10 changed files with 101 additions and 49 deletions
@@ -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"
}
@@ -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"
}