translator: plain classes and types

This commit is contained in:
e5l
2016-07-12 12:08:57 +03:00
parent 31c2937acc
commit b4df05a832
12 changed files with 126 additions and 20 deletions
@@ -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<LLVMVariable> {
val fields = ArrayList<LLVMVariable>()
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
}
}
@@ -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()
}
}
}
}
}
@@ -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)
@@ -72,8 +72,8 @@ class TranslationState(sources: List<String>, 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() })
}
@@ -9,7 +9,7 @@ class VariableManager {
private var globalVariableCollection = HashMap<String, LLVMVariable>()
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) {
@@ -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<LLVMVariable>) {
val code = "@class.$name = type { ${ fields.map { it.type }.joinToString() } }"
llvmCode.appendln(code)
}
override fun toString() = llvmCode.toString()
}
@@ -4,7 +4,6 @@ import org.kotlinnative.translator.llvm.types.LLVMType
class LLVMCall(val returnType: LLVMType, val name: String, val arguments: List<LLVMVariable>) : 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}" }})"
}
@@ -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)
@@ -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
@@ -0,0 +1,7 @@
package org.kotlinnative.translator.llvm.types
class LLVMCharType() : LLVMType() {
override fun toString(): String = "i8"
}
@@ -0,0 +1,7 @@
package org.kotlinnative.translator.llvm.types
class LLVMShortType() : LLVMType() {
override fun toString(): String = "i16"
}
@@ -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()
}