diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt new file mode 100644 index 00000000000..33c19ea6000 --- /dev/null +++ b/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt @@ -0,0 +1,81 @@ +package org.kotlinnative.translator + +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.psi.KtClass +import org.jetbrains.kotlin.psi.KtParameter +import org.jetbrains.kotlin.psi.KtUserType +import org.jetbrains.kotlin.resolve.BindingContext +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.LLVMVariable +import org.kotlinnative.translator.llvm.types.LLVMType +import org.kotlinnative.translator.llvm.types.parseLLVMType +import java.util.* + +class ClassCodegen(val state: TranslationState, val clazz: KtClass, val codeBuilder: LLVMBuilder) { + + var native = false + + fun generate() { + val descriptor = state.bindingContext.get(BindingContext.CLASS, clazz) ?: throw TranslationException() + + if (descriptor.kind == ClassKind.ANNOTATION_CLASS) { + return + } + + native = isNative(descriptor.annotations) + + generateBody() + } + + private fun generateBody() { + val name = clazz.name!! + val fields = getFields() + + codeBuilder.createClass(name, fields) + } + + private fun getFields(): List { + val fields = ArrayList() + val parameterList = clazz.getPrimaryConstructorParameterList()!!.parameters + var offset = 0 + + 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) + + offset++ + } + + return fields + } + + private fun getNativeType(field: KtParameter): LLVMType? { + for (annotation in field.annotationEntries) { + val annotationDescriptor = state.bindingContext.get(BindingContext.ANNOTATION, annotation) + val type = annotationDescriptor?.type.toString() + if (type == "Native") { + return parseLLVMType(annotationDescriptor!!.argumentValue("type").toString()) + } + } + + return null + } + + private fun isNative(annotations: Annotations?): Boolean { + annotations ?: return false + + for (i in annotations) { + if (i.type.toString() == "Native") { + return true + } + } + + return false + } + +} diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/FileTranslator.kt b/translator/src/main/kotlin/org/kotlinnative/translator/FileTranslator.kt index ea4288641ba..22801ebe1c8 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/FileTranslator.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/FileTranslator.kt @@ -1,5 +1,6 @@ package org.kotlinnative.translator +import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtNamedFunction import org.kotlinnative.translator.llvm.LLVMBuilder @@ -27,8 +28,12 @@ class FileTranslator(val state: TranslationState, val file: KtFile) { function.generate() } + is KtClass -> { + ClassCodegen(state, declaration, codeBuilder).generate() + } } } } } + diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt index b4cd1255653..3b04a1162f5 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt @@ -32,7 +32,7 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction } fun generate() { - if (generateDeclaration(function)) { + if (generateDeclaration()) { return } @@ -47,7 +47,7 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction codeBuilder.addEndExpression() } - private fun generateDeclaration(function: KtNamedFunction): Boolean { + private fun generateDeclaration(): Boolean { var external = false var keyword = function.firstChild @@ -179,7 +179,7 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction } private fun evaluateReturnInstruction(element: LeafPsiElement, scopeDepth: Int): LLVMVariable? { - var next = element.getNextSiblingIgnoringWhitespaceAndComments() + val next = element.getNextSiblingIgnoringWhitespaceAndComments() val retVar = evaluateExpression(next, scopeDepth) as LLVMVariable codeBuilder.addReturnOperator(retVar) diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/TranslationState.kt b/translator/src/main/kotlin/org/kotlinnative/translator/TranslationState.kt index 25ba4de6ab0..cb91155c99f 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/TranslationState.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/TranslationState.kt @@ -72,8 +72,8 @@ class TranslationState(sources: List, disposer: Disposable) { } override fun reportEnvironmentErrors() { - var files = environment.configuration.jvmClasspathRoots - var runtimes = files.map { it.canonicalFile }.filter { it.name == PathUtil.KOTLIN_JAVA_RUNTIME_JAR && it.exists() } + val files = environment.configuration.jvmClasspathRoots + val runtimes = files.map { it.canonicalFile }.filter { it.name == PathUtil.KOTLIN_JAVA_RUNTIME_JAR && it.exists() } collector.report(CompilerMessageSeverity.ERROR, runtimes.joinToString { it.path }, CompilerMessageLocation.NO_LOCATION) println(runtimes.joinToString { it.toString() }) } diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/VariableManager.kt b/translator/src/main/kotlin/org/kotlinnative/translator/VariableManager.kt index 3490a8d3a99..c37d8e81fd2 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/VariableManager.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/VariableManager.kt @@ -9,7 +9,7 @@ class VariableManager { private var globalVariableCollection = HashMap() fun getLLVMvalue(variableName: String): LLVMVariable? { - return fileVariableCollectionTree.get(variableName)?.peek()?.first ?: globalVariableCollection.get(variableName) + return fileVariableCollectionTree[variableName]?.peek()?.first ?: globalVariableCollection[variableName] } fun pullUpwardsLevel(level: Int) { diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt index ef8db9da1fc..572d9d1d7ed 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt @@ -41,10 +41,6 @@ class LLVMBuilder { return newVar } - fun addAssignment(llvmVariable: LLVMNode, assignExpression: LLVMNode) { - llvmCode.appendln("$llvmVariable = $assignExpression") - } - fun clean() { llvmCode = StringBuilder() } @@ -67,13 +63,13 @@ class LLVMBuilder { fun addVariableByRef(targetVariable: LLVMVariable, sourceVariable: LLVMVariable) { llvmCode.appendln("$sourceVariable = alloca ${sourceVariable.type}, align ${sourceVariable.type?.getAlign()}") - llvmCode.appendln("store ${targetVariable.type} $targetVariable, ${targetVariable.type}* ${sourceVariable}, align ${targetVariable.type?.getAlign()}") + llvmCode.appendln("store ${targetVariable.type} $targetVariable, ${targetVariable.type}* $sourceVariable, align ${targetVariable.type?.getAlign()}") } fun addVariableByValue(targetVariable: LLVMVariable, sourceVariable: LLVMVariable) { val tmp = getNewVariable(targetVariable.type) llvmCode.appendln("$tmp = alloca ${tmp.type}, align ${tmp.type?.getAlign()}") - llvmCode.appendln("store ${tmp.type} $sourceVariable, ${tmp.type}* ${tmp}, align ${tmp.type?.getAlign()}") + llvmCode.appendln("store ${tmp.type} $sourceVariable, ${tmp.type}* $tmp, align ${tmp.type?.getAlign()}") llvmCode.appendln("$targetVariable = load ${targetVariable.type}, ${targetVariable.type}* $tmp, align ${targetVariable.type?.getAlign()}") } @@ -83,9 +79,12 @@ class LLVMBuilder { return target } - override fun toString(): String { - return llvmCode.toString() + + fun createClass(name: String, fields: List) { + val code = "@class.$name = type { ${ fields.map { it.type }.joinToString() } }" + llvmCode.appendln(code) } + override fun toString() = llvmCode.toString() } \ No newline at end of file diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMCall.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMCall.kt index 53822c85ec2..19f1c1d0909 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMCall.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMCall.kt @@ -4,7 +4,6 @@ import org.kotlinnative.translator.llvm.types.LLVMType class LLVMCall(val returnType: LLVMType, val name: String, val arguments: List) : LLVMNode() { - override fun toString(): String { - return "call $returnType $name(${arguments.joinToString { "${it.type} ${it.label}" }})" - } + override fun toString(): String = + "call $returnType $name(${arguments.joinToString { "${it.type} ${it.label}" }})" } diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMClassVariable.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMClassVariable.kt new file mode 100644 index 00000000000..3763c79e6dd --- /dev/null +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMClassVariable.kt @@ -0,0 +1,6 @@ +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) diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMVariable.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMVariable.kt index c75276444b6..31962fcb005 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMVariable.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMVariable.kt @@ -2,7 +2,7 @@ package org.kotlinnative.translator.llvm import org.kotlinnative.translator.llvm.types.LLVMType -class LLVMVariable(val label: String, val type: LLVMType? = null, val kotlinName: String? = null) : LLVMNode() { +open class LLVMVariable(val label: String, val type: LLVMType? = null, val kotlinName: String? = null) : LLVMNode() { override fun toString(): String = label diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMCharType.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMCharType.kt new file mode 100644 index 00000000000..dab55442870 --- /dev/null +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMCharType.kt @@ -0,0 +1,7 @@ +package org.kotlinnative.translator.llvm.types + +class LLVMCharType() : LLVMType() { + + override fun toString(): String = "i8" + +} diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMShortType.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMShortType.kt new file mode 100644 index 00000000000..249a4bd7aed --- /dev/null +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMShortType.kt @@ -0,0 +1,7 @@ +package org.kotlinnative.translator.llvm.types + +class LLVMShortType() : LLVMType() { + + override fun toString(): String = "i16" + +} diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMType.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMType.kt index a778afa6039..fabc36c1db7 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMType.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMType.kt @@ -1,4 +1,4 @@ -package org.kotlinnative.translator.llvm.types; +package org.kotlinnative.translator.llvm.types import org.kotlinnative.translator.exceptions.TranslationException import org.kotlinnative.translator.exceptions.UnimplementedException @@ -11,11 +11,13 @@ abstract class LLVMType() { open fun operatorTimes(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression = throw UnimplementedException() open fun operatorMinus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression = throw UnimplementedException() - abstract fun getAlign(): Int + open fun getAlign(): Int = throw UnimplementedException() } fun parseLLVMType(type: String): LLVMType = when (type) { "i32" -> LLVMIntType() + "i16" -> LLVMShortType() + "i8" -> LLVMCharType() "Unit" -> LLVMVoidType() else -> throw TranslationException() }