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.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 java.util.*
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 parameterList = clazz.getPrimaryConstructorParameterList()!!.parameters
if (descriptor.kind == ClassKind.ANNOTATION_CLASS) {
return
var offset = 0
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)
generateBody()
size = currentSize
}
private fun generateBody() {
fun generate() {
if (annotation) {
return
}
generateStruct()
generateDefaultConstructor()
}
private fun generateStruct() {
val name = clazz.name!!
val fields = getFields()
codeBuilder.createClass(name, fields)
}
private fun getFields(): List<LLVMVariable> {
val fields = ArrayList<LLVMVariable>()
val parameterList = clazz.getPrimaryConstructorParameterList()!!.parameters
var offset = 0
private fun generateDefaultConstructor() {
codeBuilder.addLLVMCode(LLVMFunctionDescriptor(clazz.name!!, fields, LLVMVoidType()))
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)
codeBuilder.addStartExpression()
generateLoadArguments()
codeBuilder.addEndExpression()
}
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? {
@@ -4,7 +4,6 @@ import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.kotlinnative.translator.llvm.LLVMBuilder
import org.kotlinnative.translator.utils.FunctionDescriptor
class FileTranslator(val state: TranslationState, val file: KtFile) {
@@ -21,18 +20,24 @@ class FileTranslator(val state: TranslationState, val file: KtFile) {
when (declaration) {
is KtNamedFunction -> {
val function = FunctionCodegen(state, declaration, codeBuilder)
state.functions.put(function.name, FunctionDescriptor(
function.returnType,
function.args?.map { it.type }?.toList() ?: listOf()
))
state.functions.put(function.name, function)
function.generate()
}
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.LLVMType
import org.kotlinnative.translator.llvm.types.LLVMVoidType
import org.kotlinnative.translator.utils.FunctionArgument
import java.util.*
@@ -19,13 +18,13 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
var name = function.fqName.toString()
var returnType: LLVMType
var args: List<FunctionArgument>?
var args: List<LLVMVariable>?
val variableManager = state.variableManager
init {
val descriptor = state.bindingContext.get(BindingContext.FUNCTION, function)
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())
@@ -37,7 +36,7 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
}
codeBuilder.addStartExpression()
generateLoadArguments(function)
generateLoadArguments()
expressionWalker(function.bodyExpression)
if (returnType is LLVMVoidType) {
@@ -64,11 +63,11 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
return external
}
private fun generateLoadArguments(function: KtNamedFunction) {
private fun generateLoadArguments() {
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)
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? {
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 descriptor = state.functions[function.text] ?: return null
val names = parseArgList(expr
.firstChild
.getNextSiblingIgnoringWhitespaceAndComments()
?.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> {
@@ -18,7 +18,6 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM
import org.jetbrains.kotlin.utils.PathUtil
import org.kotlinnative.translator.exceptions.TranslationException
import org.kotlinnative.translator.utils.FunctionDescriptor
import java.util.*
@@ -26,7 +25,9 @@ class TranslationState(sources: List<String>, disposer: Disposable) {
val environment: KotlinCoreEnvironment
val bindingContext: BindingContext
var functions = HashMap<String, FunctionDescriptor>()
var functions = HashMap<String, FunctionCodegen>()
var classes = HashMap<String, ClassCodegen>()
val variableManager = VariableManager()
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() {
override fun toString(): String = label
fun getType(): String = type.toString() + if (pointer) "*" else ""
override fun toString(): String = label
}
@@ -1,14 +1,13 @@
package org.kotlinnative.translator.llvm
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(${
argTypes?.mapIndexed { i: Int, s: FunctionArgument ->
"${s.type} %${s.name}"
}?.joinToString() ?: ""})"
argTypes?.mapIndexed { i: Int, s: LLVMVariable ->
"${s.type} %${s.label}"
}?.joinToString() })"
fun LLVMMapStandardType(type: String): LLVMType = when (type) {
"Int" -> LLVMIntType()
@@ -3,7 +3,7 @@ package org.kotlinnative.translator.llvm.types
class LLVMCharType() : LLVMType() {
override fun toString(): String = "i8"
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 =
LLVMExpression(LLVMDoubleType(), "fadd double $firstOp, $secondOp")
override fun toString() = "double"
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 =
LLVMExpression(LLVMIntType(), "add nsw i32 $firstOp, $secondOp")
override fun toString() = "i32"
override val align = 4
override val size: Byte = 4
override fun toString() = "i32"
}
@@ -1,22 +1,10 @@
package org.kotlinnative.translator.llvm.types
import org.kotlinnative.translator.llvm.LLVMExpression
import org.kotlinnative.translator.llvm.LLVMVariable
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 {
throw UnsupportedOperationException("not implemented")
}
override fun operatorPlus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression {
throw UnsupportedOperationException("not implemented")
}
override val align = 4
override val size: Byte = 4
override fun toString() = type
override val align = -1
}
@@ -2,7 +2,8 @@ package org.kotlinnative.translator.llvm.types
class LLVMShortType() : LLVMType() {
override fun toString(): String = "i16"
override val size: Byte = 2
override val align = 1
override fun toString(): String = "i16"
}
@@ -1,6 +1,5 @@
package org.kotlinnative.translator.llvm.types
import org.kotlinnative.translator.exceptions.TranslationException
import org.kotlinnative.translator.exceptions.UnimplementedException
import org.kotlinnative.translator.llvm.LLVMExpression
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()
abstract val align: Int
abstract val size: Byte
}
fun parseLLVMType(type: String): LLVMType = when (type) {
@@ -19,5 +19,5 @@ fun parseLLVMType(type: String): LLVMType = when (type) {
"i16" -> LLVMShortType()
"i8" -> LLVMCharType()
"Unit" -> LLVMVoidType()
else -> throw TranslationException()
else -> LLVMReferenceType(type)
}
@@ -5,5 +5,6 @@ class LLVMVoidType() : LLVMType() {
override val align = 0
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>)