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.LLVMClassVariable
|
||||||
import org.kotlinnative.translator.llvm.LLVMFunctionDescriptor
|
import org.kotlinnative.translator.llvm.LLVMFunctionDescriptor
|
||||||
import org.kotlinnative.translator.llvm.LLVMVariable
|
import org.kotlinnative.translator.llvm.LLVMVariable
|
||||||
import org.kotlinnative.translator.llvm.types.LLVMType
|
import org.kotlinnative.translator.llvm.types.*
|
||||||
import org.kotlinnative.translator.llvm.types.LLVMVoidType
|
|
||||||
import org.kotlinnative.translator.llvm.types.parseLLVMType
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class ClassCodegen(val state: TranslationState, val clazz: KtClass, val codeBuilder: LLVMBuilder) {
|
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 annotation: Boolean
|
||||||
val native: Boolean
|
val native: Boolean
|
||||||
val fields = ArrayList<LLVMVariable>()
|
val fields = ArrayList<LLVMVariable>()
|
||||||
|
val name = "%class.${clazz.name}"
|
||||||
|
val type: LLVMType = parseLLVMType(name)
|
||||||
val size: Int
|
val size: Int
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@@ -35,8 +35,7 @@ class ClassCodegen(val state: TranslationState, val clazz: KtClass, val codeBuil
|
|||||||
if (!annotation) {
|
if (!annotation) {
|
||||||
for (field in parameterList) {
|
for (field in parameterList) {
|
||||||
val type = getNativeType(field) ?: parseLLVMType((field.typeReference?.typeElement as KtUserType).referencedName!!)
|
val type = getNativeType(field) ?: parseLLVMType((field.typeReference?.typeElement as KtUserType).referencedName!!)
|
||||||
val field = LLVMClassVariable(field.name!!, type, offset)
|
fields.add(LLVMClassVariable(field.name!!, type, offset))
|
||||||
fields.add(field)
|
|
||||||
|
|
||||||
currentSize += type.size
|
currentSize += type.size
|
||||||
offset++
|
offset++
|
||||||
@@ -63,20 +62,56 @@ class ClassCodegen(val state: TranslationState, val clazz: KtClass, val codeBuil
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun generateDefaultConstructor() {
|
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()
|
codeBuilder.addStartExpression()
|
||||||
generateLoadArguments()
|
generateLoadArguments(thisField)
|
||||||
|
generateAssignments()
|
||||||
|
generateReturn()
|
||||||
|
codeBuilder.addVoidReturn()
|
||||||
codeBuilder.addEndExpression()
|
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 {
|
fields.forEach {
|
||||||
val loadVariable = LLVMVariable("%${it.label}", it.type, it.label)
|
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? {
|
private fun getNativeType(field: KtParameter): LLVMType? {
|
||||||
for (annotation in field.annotationEntries) {
|
for (annotation in field.annotationEntries) {
|
||||||
val annotationDescriptor = state.bindingContext.get(BindingContext.ANNOTATION, annotation)
|
val annotationDescriptor = state.bindingContext.get(BindingContext.ANNOTATION, annotation)
|
||||||
|
|||||||
@@ -65,8 +65,8 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
|
|||||||
|
|
||||||
private fun generateLoadArguments() {
|
private fun generateLoadArguments() {
|
||||||
args?.forEach {
|
args?.forEach {
|
||||||
val loadVariable = LLVMVariable("%${it.label}", it.type, it.label, true)
|
val loadVariable = LLVMVariable("%${it.label}", it.type, it.label, false)
|
||||||
codeBuilder.loadVariable(loadVariable)
|
codeBuilder.loadArgument(loadVariable)
|
||||||
variableManager.addVariable(it.label, loadVariable, 2)
|
variableManager.addVariable(it.label, loadVariable, 2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class LLVMBuilder {
|
|||||||
|
|
||||||
fun getNewVariable(type: LLVMType?, pointer: Boolean = false): LLVMVariable {
|
fun getNewVariable(type: LLVMType?, pointer: Boolean = false): LLVMVariable {
|
||||||
variableCount++
|
variableCount++
|
||||||
return LLVMVariable("%var$variableCount", type, pointer = pointer)
|
return LLVMVariable("%var$variableCount", type, "", pointer)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addLLVMCode(code: String) {
|
fun addLLVMCode(code: String) {
|
||||||
@@ -32,7 +32,6 @@ class LLVMBuilder {
|
|||||||
KtTokens.PLUS -> firstOp.type!!.operatorPlus(newVar, firstOp, secondOp)
|
KtTokens.PLUS -> firstOp.type!!.operatorPlus(newVar, firstOp, secondOp)
|
||||||
KtTokens.MINUS -> firstOp.type!!.operatorMinus(newVar, firstOp, secondOp)
|
KtTokens.MINUS -> firstOp.type!!.operatorMinus(newVar, firstOp, secondOp)
|
||||||
KtTokens.MUL -> firstOp.type!!.operatorTimes(newVar, firstOp, secondOp)
|
KtTokens.MUL -> firstOp.type!!.operatorTimes(newVar, firstOp, secondOp)
|
||||||
KtTokens.EQ -> return moveVariableValue(secondOp, firstOp)
|
|
||||||
else -> throw UnsupportedOperationException("Unknown binary operator")
|
else -> throw UnsupportedOperationException("Unknown binary operator")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,21 +40,6 @@ class LLVMBuilder {
|
|||||||
return newVar
|
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() {
|
fun clean() {
|
||||||
llvmCode = StringBuilder()
|
llvmCode = StringBuilder()
|
||||||
}
|
}
|
||||||
@@ -72,17 +56,35 @@ class LLVMBuilder {
|
|||||||
llvmCode.appendln("ret void")
|
llvmCode.appendln("ret void")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadVariable(llvmVariable: LLVMVariable) {
|
fun loadArgument(llvmVariable: LLVMVariable, store: Boolean = true) {
|
||||||
addVariableByRef(llvmVariable, LLVMVariable("${llvmVariable.label}.addr", llvmVariable.type, llvmVariable.kotlinName, true))
|
addVariableByRef(LLVMVariable("${llvmVariable.label}.addr", llvmVariable.type, llvmVariable.kotlinName, true), llvmVariable, store)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addVariableByRef(targetVariable: LLVMVariable, sourceVariable: LLVMVariable) {
|
fun loadVariable(target: LLVMVariable, source: LLVMVariable) {
|
||||||
llvmCode.appendln("$sourceVariable = alloca ${sourceVariable.type}, align ${sourceVariable.type?.align}")
|
val code = "$target = load ${target.type}, ${source.getType()} $source, align ${target.type?.align!!}"
|
||||||
llvmCode.appendln("store ${sourceVariable.type} $targetVariable, ${targetVariable.getType()} $sourceVariable, align ${targetVariable.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) {
|
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("$tmp = alloca ${tmp.type}, align ${tmp.type?.align}")
|
||||||
llvmCode.appendln("store ${tmp.type} $sourceVariable, ${tmp.getType()} $tmp, 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 {
|
fun addConstant(sourceVariable: LLVMVariable): LLVMVariable {
|
||||||
val target = getNewVariable(sourceVariable.type, pointer = sourceVariable.pointer)
|
val target = getNewVariable(sourceVariable.type, sourceVariable.pointer)
|
||||||
addVariableByValue(target, sourceVariable)
|
addVariableByValue(target, sourceVariable)
|
||||||
return target
|
return target
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun createClass(name: String, fields: List<LLVMVariable>) {
|
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)
|
llvmCode.appendln(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString() = llvmCode.toString()
|
override fun toString() = llvmCode.toString()
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -3,4 +3,4 @@ package org.kotlinnative.translator.llvm
|
|||||||
import org.kotlinnative.translator.llvm.types.LLVMType
|
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) =
|
fun LLVMFunctionDescriptor(name: String, argTypes: List<LLVMVariable>?, returnType: LLVMType, declare: Boolean = false) =
|
||||||
"${if (declare) "declare" else "define"} $returnType @$name(${
|
"${if (declare) "declare" else "define"} $returnType @$name(${
|
||||||
argTypes?.mapIndexed { i: Int, s: LLVMVariable ->
|
argTypes?.mapIndexed { i: Int, s: LLVMVariable ->
|
||||||
"${s.type} %${s.label}"
|
"${s.getType()} %${s.label}"
|
||||||
}?.joinToString() })"
|
}?.joinToString() })"
|
||||||
|
|
||||||
fun LLVMMapStandardType(type: String): LLVMType = when (type) {
|
fun LLVMMapStandardType(type: String): LLVMType = when (type) {
|
||||||
|
|||||||
@@ -2,8 +2,7 @@ package org.kotlinnative.translator.llvm.types
|
|||||||
|
|
||||||
class LLVMCharType() : LLVMType() {
|
class LLVMCharType() : LLVMType() {
|
||||||
|
|
||||||
override fun toString(): String = "i8"
|
|
||||||
override val align = 1
|
override val align = 1
|
||||||
|
|
||||||
override val size: Byte = 1
|
override val size: Byte = 1
|
||||||
|
override fun toString(): String = "i8"
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-1
@@ -1,10 +1,16 @@
|
|||||||
package org.kotlinnative.translator.llvm.types
|
package org.kotlinnative.translator.llvm.types
|
||||||
|
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
class LLVMReferenceType(val type: String) : LLVMType() {
|
class LLVMReferenceType(val type: String) : LLVMType() {
|
||||||
|
|
||||||
override val align = 4
|
override val align = 4
|
||||||
override val size: Byte = 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() {
|
class LLVMShortType() : LLVMType() {
|
||||||
|
|
||||||
override val size: Byte = 2
|
override val size: Byte = 2
|
||||||
override val align = 1
|
override val align = 2
|
||||||
|
|
||||||
override fun toString(): String = "i16"
|
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.LLVMExpression
|
||||||
import org.kotlinnative.translator.llvm.LLVMVariable
|
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 operatorPlus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression = throw UnimplementedException()
|
||||||
open fun operatorTimes(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()
|
open fun operatorMinus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression = throw UnimplementedException()
|
||||||
|
|
||||||
|
fun makeClone() = clone()
|
||||||
|
|
||||||
abstract val align: Int
|
abstract val align: Int
|
||||||
abstract val size: Byte
|
abstract val size: Byte
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ package org.kotlinnative.translator.llvm.types
|
|||||||
class LLVMVoidType() : LLVMType() {
|
class LLVMVoidType() : LLVMType() {
|
||||||
|
|
||||||
override val align = 0
|
override val align = 0
|
||||||
|
|
||||||
override fun toString(): String = "void"
|
|
||||||
override val size: Byte = 0
|
override val size: Byte = 0
|
||||||
|
override fun toString(): String = "void"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user