translator: call fixes, constructors stub

This commit is contained in:
e5l
2016-07-12 14:07:25 +03:00
parent 1a76a916a6
commit 89e626c8f5
14 changed files with 103 additions and 73 deletions
@@ -10,48 +10,71 @@ import org.jetbrains.kotlin.resolve.annotations.argumentValue
import org.kotlinnative.translator.exceptions.TranslationException import org.kotlinnative.translator.exceptions.TranslationException
import org.kotlinnative.translator.llvm.LLVMBuilder 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.LLVMVariable import org.kotlinnative.translator.llvm.LLVMVariable
import org.kotlinnative.translator.llvm.types.LLVMType 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.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) {
var native = false val annotation: Boolean
val native: Boolean
val fields = ArrayList<LLVMVariable>()
val size: Int
fun generate() { init {
val descriptor = state.bindingContext.get(BindingContext.CLASS, clazz) ?: throw TranslationException() val descriptor = state.bindingContext.get(BindingContext.CLASS, clazz) ?: throw TranslationException()
val parameterList = clazz.getPrimaryConstructorParameterList()!!.parameters
if (descriptor.kind == ClassKind.ANNOTATION_CLASS) { var offset = 0
return var currentSize = 0
annotation = descriptor.kind == ClassKind.ANNOTATION_CLASS
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)
currentSize += type.size
offset++
}
} }
native = isNative(descriptor.annotations) native = isNative(descriptor.annotations)
size = currentSize
generateBody()
} }
private fun generateBody() { fun generate() {
if (annotation) {
return
}
generateStruct()
generateDefaultConstructor()
}
private fun generateStruct() {
val name = clazz.name!! val name = clazz.name!!
val fields = getFields()
codeBuilder.createClass(name, fields) codeBuilder.createClass(name, fields)
} }
private fun getFields(): List<LLVMVariable> { private fun generateDefaultConstructor() {
val fields = ArrayList<LLVMVariable>() codeBuilder.addLLVMCode(LLVMFunctionDescriptor(clazz.name!!, fields, LLVMVoidType()))
val parameterList = clazz.getPrimaryConstructorParameterList()!!.parameters
var offset = 0
for (field in parameterList) { codeBuilder.addStartExpression()
val type = getNativeType(field) ?: parseLLVMType((field.typeReference?.typeElement as KtUserType).referencedName!!) generateLoadArguments()
val field = LLVMClassVariable(field.name!!, type, offset) codeBuilder.addEndExpression()
fields.add(field) }
offset++ private fun generateLoadArguments() {
fields.forEach {
val loadVariable = LLVMVariable("%${it.label}", it.type, it.label)
codeBuilder.loadVariable(loadVariable)
} }
return fields
} }
private fun getNativeType(field: KtParameter): LLVMType? { private fun getNativeType(field: KtParameter): LLVMType? {
@@ -4,7 +4,6 @@ import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtNamedFunction import org.jetbrains.kotlin.psi.KtNamedFunction
import org.kotlinnative.translator.llvm.LLVMBuilder import org.kotlinnative.translator.llvm.LLVMBuilder
import org.kotlinnative.translator.utils.FunctionDescriptor
class FileTranslator(val state: TranslationState, val file: KtFile) { class FileTranslator(val state: TranslationState, val file: KtFile) {
@@ -21,18 +20,24 @@ class FileTranslator(val state: TranslationState, val file: KtFile) {
when (declaration) { when (declaration) {
is KtNamedFunction -> { is KtNamedFunction -> {
val function = FunctionCodegen(state, declaration, codeBuilder) val function = FunctionCodegen(state, declaration, codeBuilder)
state.functions.put(function.name, FunctionDescriptor( state.functions.put(function.name, function)
function.returnType,
function.args?.map { it.type }?.toList() ?: listOf()
))
function.generate()
} }
is KtClass -> { is KtClass -> {
ClassCodegen(state, declaration, codeBuilder).generate() val codegen = ClassCodegen(state, declaration, codeBuilder)
state.classes.put(declaration.name!!, codegen)
} }
} }
} }
for (clazz in state.classes.values) {
clazz.generate()
}
for (function in state.functions.values) {
function.generate()
}
} }
} }
@@ -11,7 +11,6 @@ import org.kotlinnative.translator.llvm.*
import org.kotlinnative.translator.llvm.types.LLVMIntType import org.kotlinnative.translator.llvm.types.LLVMIntType
import org.kotlinnative.translator.llvm.types.LLVMType import org.kotlinnative.translator.llvm.types.LLVMType
import org.kotlinnative.translator.llvm.types.LLVMVoidType import org.kotlinnative.translator.llvm.types.LLVMVoidType
import org.kotlinnative.translator.utils.FunctionArgument
import java.util.* import java.util.*
@@ -19,13 +18,13 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
var name = function.fqName.toString() var name = function.fqName.toString()
var returnType: LLVMType var returnType: LLVMType
var args: List<FunctionArgument>? var args: List<LLVMVariable>?
val variableManager = state.variableManager val variableManager = state.variableManager
init { init {
val descriptor = state.bindingContext.get(BindingContext.FUNCTION, function) val descriptor = state.bindingContext.get(BindingContext.FUNCTION, function)
args = descriptor?.valueParameters?.map { args = descriptor?.valueParameters?.map {
FunctionArgument(LLVMMapStandardType(it.type.toString()), it.name.toString()) LLVMVariable(it.name.toString(), LLVMMapStandardType(it.type.toString()))
} }
returnType = LLVMMapStandardType(descriptor?.returnType.toString()) returnType = LLVMMapStandardType(descriptor?.returnType.toString())
@@ -37,7 +36,7 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
} }
codeBuilder.addStartExpression() codeBuilder.addStartExpression()
generateLoadArguments(function) generateLoadArguments()
expressionWalker(function.bodyExpression) expressionWalker(function.bodyExpression)
if (returnType is LLVMVoidType) { if (returnType is LLVMVoidType) {
@@ -64,11 +63,11 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
return external return external
} }
private fun generateLoadArguments(function: KtNamedFunction) { private fun generateLoadArguments() {
args?.forEach { args?.forEach {
val loadVariable = LLVMVariable("%${it.name}", it.type, it.name, true) val loadVariable = LLVMVariable("%${it.label}", it.type, it.label, true)
codeBuilder.loadVariable(loadVariable) codeBuilder.loadVariable(loadVariable)
variableManager.addVariable(it.name, loadVariable, 2) variableManager.addVariable(it.label, loadVariable, 2)
} }
} }
@@ -107,14 +106,35 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
} }
private fun evaluateCallExpression(expr: KtCallExpression): LLVMNode? { private fun evaluateCallExpression(expr: KtCallExpression): LLVMNode? {
val function = expr.firstChild.firstChild.text
if (state.functions.containsKey(function)) {
return evaluteFunctionCallExpression(expr)
}
if (state.classes.containsKey(function)) {
return evaluteConstructorCallExpression(expr)
}
return null
}
private fun evaluteConstructorCallExpression(expr: KtCallExpression): LLVMNode? {
return null
}
private fun evaluteFunctionCallExpression(expr: KtCallExpression): LLVMNode? {
val function = expr.firstChild.firstChild val function = expr.firstChild.firstChild
val descriptor = state.functions[function.text] ?: return null val descriptor = state.functions[function.text] ?: return null
val names = parseArgList(expr val names = parseArgList(expr
.firstChild .firstChild
.getNextSiblingIgnoringWhitespaceAndComments() .getNextSiblingIgnoringWhitespaceAndComments()
?.firstChild) ?.firstChild)
return LLVMCall(descriptor.returnType, "@${function.text}", descriptor.argTypes.mapIndexed { i: Int, type: LLVMType -> LLVMVariable(names[i], type) }) return LLVMCall(descriptor.returnType, "@${function.text}", descriptor.args?.mapIndexed {
i: Int, variable: LLVMVariable -> LLVMVariable(names[i], variable.type)
} ?: listOf())
} }
private fun parseArgList(argumentList: PsiElement?): List<String> { private fun parseArgList(argumentList: PsiElement?): List<String> {
@@ -18,7 +18,6 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM
import org.jetbrains.kotlin.utils.PathUtil import org.jetbrains.kotlin.utils.PathUtil
import org.kotlinnative.translator.exceptions.TranslationException import org.kotlinnative.translator.exceptions.TranslationException
import org.kotlinnative.translator.utils.FunctionDescriptor
import java.util.* import java.util.*
@@ -26,7 +25,9 @@ class TranslationState(sources: List<String>, disposer: Disposable) {
val environment: KotlinCoreEnvironment val environment: KotlinCoreEnvironment
val bindingContext: BindingContext val bindingContext: BindingContext
var functions = HashMap<String, FunctionDescriptor>() var functions = HashMap<String, FunctionCodegen>()
var classes = HashMap<String, ClassCodegen>()
val variableManager = VariableManager() val variableManager = VariableManager()
init { init {
@@ -4,8 +4,7 @@ import org.kotlinnative.translator.llvm.types.LLVMType
open class LLVMVariable(val label: String, val type: LLVMType? = null, var kotlinName: String? = null, var pointer: Boolean = false) : LLVMNode() { open class LLVMVariable(val label: String, val type: LLVMType? = null, var kotlinName: String? = null, var pointer: Boolean = false) : LLVMNode() {
override fun toString(): String = label
fun getType(): String = type.toString() + if (pointer) "*" else "" fun getType(): String = type.toString() + if (pointer) "*" else ""
override fun toString(): String = label
} }
@@ -1,14 +1,13 @@
package org.kotlinnative.translator.llvm package org.kotlinnative.translator.llvm
import org.kotlinnative.translator.llvm.types.* import org.kotlinnative.translator.llvm.types.*
import org.kotlinnative.translator.utils.FunctionArgument
fun LLVMFunctionDescriptor(name: String, argTypes: List<FunctionArgument>?, 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: FunctionArgument -> argTypes?.mapIndexed { i: Int, s: LLVMVariable ->
"${s.type} %${s.name}" "${s.type} %${s.label}"
}?.joinToString() ?: ""})" }?.joinToString() })"
fun LLVMMapStandardType(type: String): LLVMType = when (type) { fun LLVMMapStandardType(type: String): LLVMType = when (type) {
"Int" -> LLVMIntType() "Int" -> LLVMIntType()
@@ -3,7 +3,7 @@ package org.kotlinnative.translator.llvm.types
class LLVMCharType() : LLVMType() { class LLVMCharType() : LLVMType() {
override fun toString(): String = "i8" override fun toString(): String = "i8"
override val align = 1 override val align = 1
override val size: Byte = 1
} }
@@ -18,7 +18,7 @@ class LLVMDoubleType() : LLVMType() {
override fun operatorPlus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression = override fun operatorPlus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression =
LLVMExpression(LLVMDoubleType(), "fadd double $firstOp, $secondOp") LLVMExpression(LLVMDoubleType(), "fadd double $firstOp, $secondOp")
override fun toString() = "double"
override val align = 8 override val align = 8
override val size: Byte = 8
override fun toString() = "double"
} }
@@ -18,8 +18,8 @@ class LLVMIntType() : LLVMType() {
override fun operatorPlus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression = override fun operatorPlus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression =
LLVMExpression(LLVMIntType(), "add nsw i32 $firstOp, $secondOp") LLVMExpression(LLVMIntType(), "add nsw i32 $firstOp, $secondOp")
override fun toString() = "i32"
override val align = 4 override val align = 4
override val size: Byte = 4
override fun toString() = "i32"
} }
@@ -1,22 +1,10 @@
package org.kotlinnative.translator.llvm.types package org.kotlinnative.translator.llvm.types
import org.kotlinnative.translator.llvm.LLVMExpression
import org.kotlinnative.translator.llvm.LLVMVariable
class LLVMReferenceType(val type: String) : LLVMType() { class LLVMReferenceType(val type: String) : LLVMType() {
override fun operatorTimes(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression {
throw UnsupportedOperationException("not implemented")
}
override fun operatorMinus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression { override val align = 4
throw UnsupportedOperationException("not implemented") override val size: Byte = 4
}
override fun operatorPlus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression {
throw UnsupportedOperationException("not implemented")
}
override fun toString() = type override fun toString() = type
override val align = -1
} }
@@ -2,7 +2,8 @@ package org.kotlinnative.translator.llvm.types
class LLVMShortType() : LLVMType() { class LLVMShortType() : LLVMType() {
override fun toString(): String = "i16" override val size: Byte = 2
override val align = 1 override val align = 1
override fun toString(): String = "i16"
} }
@@ -1,6 +1,5 @@
package org.kotlinnative.translator.llvm.types package org.kotlinnative.translator.llvm.types
import org.kotlinnative.translator.exceptions.TranslationException
import org.kotlinnative.translator.exceptions.UnimplementedException 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
@@ -12,6 +11,7 @@ abstract class LLVMType() {
open fun operatorMinus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression = throw UnimplementedException() open fun operatorMinus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression = throw UnimplementedException()
abstract val align: Int abstract val align: Int
abstract val size: Byte
} }
fun parseLLVMType(type: String): LLVMType = when (type) { fun parseLLVMType(type: String): LLVMType = when (type) {
@@ -19,5 +19,5 @@ fun parseLLVMType(type: String): LLVMType = when (type) {
"i16" -> LLVMShortType() "i16" -> LLVMShortType()
"i8" -> LLVMCharType() "i8" -> LLVMCharType()
"Unit" -> LLVMVoidType() "Unit" -> LLVMVoidType()
else -> throw TranslationException() else -> LLVMReferenceType(type)
} }
@@ -5,5 +5,6 @@ class LLVMVoidType() : LLVMType() {
override val align = 0 override val align = 0
override fun toString(): String = "void" override fun toString(): String = "void"
override val size: Byte = 0
} }
@@ -1,7 +0,0 @@
package org.kotlinnative.translator.utils
import org.kotlinnative.translator.llvm.types.LLVMType
data class FunctionArgument(val type: LLVMType, val name: String)
data class FunctionDescriptor(val returnType: LLVMType, val argTypes: List<LLVMType>)