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 package org.kotlinnative.translator
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
@@ -27,8 +28,12 @@ class FileTranslator(val state: TranslationState, val file: KtFile) {
function.generate() function.generate()
} }
is KtClass -> {
ClassCodegen(state, declaration, codeBuilder).generate()
}
} }
} }
} }
} }
@@ -32,7 +32,7 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
} }
fun generate() { fun generate() {
if (generateDeclaration(function)) { if (generateDeclaration()) {
return return
} }
@@ -47,7 +47,7 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
codeBuilder.addEndExpression() codeBuilder.addEndExpression()
} }
private fun generateDeclaration(function: KtNamedFunction): Boolean { private fun generateDeclaration(): Boolean {
var external = false var external = false
var keyword = function.firstChild var keyword = function.firstChild
@@ -179,7 +179,7 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
} }
private fun evaluateReturnInstruction(element: LeafPsiElement, scopeDepth: Int): LLVMVariable? { private fun evaluateReturnInstruction(element: LeafPsiElement, scopeDepth: Int): LLVMVariable? {
var next = element.getNextSiblingIgnoringWhitespaceAndComments() val next = element.getNextSiblingIgnoringWhitespaceAndComments()
val retVar = evaluateExpression(next, scopeDepth) as LLVMVariable val retVar = evaluateExpression(next, scopeDepth) as LLVMVariable
codeBuilder.addReturnOperator(retVar) codeBuilder.addReturnOperator(retVar)
@@ -72,8 +72,8 @@ class TranslationState(sources: List<String>, disposer: Disposable) {
} }
override fun reportEnvironmentErrors() { override fun reportEnvironmentErrors() {
var files = environment.configuration.jvmClasspathRoots val files = environment.configuration.jvmClasspathRoots
var runtimes = files.map { it.canonicalFile }.filter { it.name == PathUtil.KOTLIN_JAVA_RUNTIME_JAR && it.exists() } 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) collector.report(CompilerMessageSeverity.ERROR, runtimes.joinToString { it.path }, CompilerMessageLocation.NO_LOCATION)
println(runtimes.joinToString { it.toString() }) println(runtimes.joinToString { it.toString() })
} }
@@ -9,7 +9,7 @@ class VariableManager {
private var globalVariableCollection = HashMap<String, LLVMVariable>() private var globalVariableCollection = HashMap<String, LLVMVariable>()
fun getLLVMvalue(variableName: 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) { fun pullUpwardsLevel(level: Int) {
@@ -41,10 +41,6 @@ class LLVMBuilder {
return newVar return newVar
} }
fun addAssignment(llvmVariable: LLVMNode, assignExpression: LLVMNode) {
llvmCode.appendln("$llvmVariable = $assignExpression")
}
fun clean() { fun clean() {
llvmCode = StringBuilder() llvmCode = StringBuilder()
} }
@@ -67,13 +63,13 @@ class LLVMBuilder {
fun addVariableByRef(targetVariable: LLVMVariable, sourceVariable: LLVMVariable) { fun addVariableByRef(targetVariable: LLVMVariable, sourceVariable: LLVMVariable) {
llvmCode.appendln("$sourceVariable = alloca ${sourceVariable.type}, align ${sourceVariable.type?.getAlign()}") 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) { fun addVariableByValue(targetVariable: LLVMVariable, sourceVariable: LLVMVariable) {
val tmp = getNewVariable(targetVariable.type) val tmp = getNewVariable(targetVariable.type)
llvmCode.appendln("$tmp = alloca ${tmp.type}, align ${tmp.type?.getAlign()}") 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()}") llvmCode.appendln("$targetVariable = load ${targetVariable.type}, ${targetVariable.type}* $tmp, align ${targetVariable.type?.getAlign()}")
} }
@@ -83,9 +79,12 @@ class LLVMBuilder {
return target 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() { class LLVMCall(val returnType: LLVMType, val name: String, val arguments: List<LLVMVariable>) : LLVMNode() {
override fun toString(): String { override fun toString(): String =
return "call $returnType $name(${arguments.joinToString { "${it.type} ${it.label}" }})" "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 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 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.TranslationException
import org.kotlinnative.translator.exceptions.UnimplementedException 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 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()
abstract fun getAlign(): Int open fun getAlign(): Int = throw UnimplementedException()
} }
fun parseLLVMType(type: String): LLVMType = when (type) { fun parseLLVMType(type: String): LLVMType = when (type) {
"i32" -> LLVMIntType() "i32" -> LLVMIntType()
"i16" -> LLVMShortType()
"i8" -> LLVMCharType()
"Unit" -> LLVMVoidType() "Unit" -> LLVMVoidType()
else -> throw TranslationException() else -> throw TranslationException()
} }