translator: add global constants, default type value, codegen for KtProperty

This commit is contained in:
Alexey Stepanov
2016-07-14 10:51:25 +03:00
parent b7149c9341
commit 21d0e5f5ca
15 changed files with 68 additions and 6 deletions
@@ -3,6 +3,7 @@ package org.kotlinnative.translator
import org.jetbrains.kotlin.psi.KtClass 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.jetbrains.kotlin.psi.KtProperty
import org.kotlinnative.translator.llvm.LLVMBuilder import org.kotlinnative.translator.llvm.LLVMBuilder
class FileTranslator(val state: TranslationState, val file: KtFile) { class FileTranslator(val state: TranslationState, val file: KtFile) {
@@ -21,15 +22,22 @@ class FileTranslator(val state: TranslationState, val file: KtFile) {
is KtNamedFunction -> { is KtNamedFunction -> {
val function = FunctionCodegen(state, declaration, codeBuilder) val function = FunctionCodegen(state, declaration, codeBuilder)
state.functions.put(function.name, function) state.functions.put(function.name, function)
} }
is KtClass -> { is KtClass -> {
val codegen = ClassCodegen(state, declaration, codeBuilder) val codegen = ClassCodegen(state, declaration, codeBuilder)
state.classes.put(declaration.name!!, codegen) state.classes.put(declaration.name!!, codegen)
} }
is KtProperty -> {
val property = PropertyCodegen(state, declaration, codeBuilder)
state.properties.put(declaration.name!!, property)
}
} }
} }
for (property in state.properties.values) {
property.generate()
}
for (clazz in state.classes.values) { for (clazz in state.classes.values) {
clazz.generate() clazz.generate()
} }
@@ -311,13 +311,13 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
when (assignExpression) { when (assignExpression) {
is LLVMVariable -> { is LLVMVariable -> {
val allocVar = variableManager.getVariable(identifier!!.text, LLVMIntType(), pointer = true) val allocVar = variableManager.receiveVariable(identifier!!.text, LLVMIntType(), pointer = true)
codeBuilder.allocVar(allocVar) codeBuilder.allocVar(allocVar)
variableManager.addVariable(identifier.text, allocVar, scopeDepth) variableManager.addVariable(identifier.text, allocVar, scopeDepth)
codeBuilder.copyVariableValue(assignExpression, allocVar) codeBuilder.copyVariableValue(assignExpression, allocVar)
} }
is LLVMConstant -> { is LLVMConstant -> {
val newVar = variableManager.getVariable(identifier!!.text, LLVMIntType(), pointer = true) val newVar = variableManager.receiveVariable(identifier!!.text, LLVMIntType(), pointer = true)
codeBuilder.addConstant(newVar, assignExpression) codeBuilder.addConstant(newVar, assignExpression)
variableManager.addVariable(identifier.text, newVar, scopeDepth) variableManager.addVariable(identifier.text, newVar, scopeDepth)
@@ -0,0 +1,33 @@
package org.kotlinnative.translator
import org.jetbrains.kotlin.js.descriptorUtils.nameIfStandardType
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.resolve.BindingContext
import org.kotlinnative.translator.llvm.LLVMBuilder
import org.kotlinnative.translator.llvm.LLVMMapStandardType
import org.kotlinnative.translator.llvm.LLVMVariable
class PropertyCodegen(val state: TranslationState, val property: KtProperty, val codeBuilder: LLVMBuilder) {
private val variableManager = state.variableManager
companion object PropertyState {
}
fun generate() {
val varInfo = state.bindingContext.get(BindingContext.VARIABLE, property)?.compileTimeInitializer ?: return
val kotlinType = varInfo.type
val value = varInfo.value
//[TODO] compile time initizializer
if (kotlinType.nameIfStandardType != null) {
val variableType = LLVMMapStandardType(property.name ?: return, kotlinType).type
val variable = LLVMVariable("@" + property.name, variableType, property.name.toString(), pointer = true)
variableManager.addGlobalVariable(property.name.toString(), variable)
codeBuilder.declareGlovalVariable(variable, variableType.parseArg(value.toString()))
}
}
}
@@ -23,8 +23,9 @@ import java.util.*
class TranslationState(val environment: KotlinCoreEnvironment, val bindingContext: BindingContext, val arm: Boolean) { class TranslationState(val environment: KotlinCoreEnvironment, val bindingContext: BindingContext, val arm: Boolean) {
var functions = HashMap<String, FunctionCodegen>() var functions = HashMap<String, FunctionCodegen>()
var classes = HashMap<String, ClassCodegen>()
val variableManager = VariableManager() val variableManager = VariableManager()
var classes = HashMap<String, ClassCodegen>()
var properties = HashMap<String, PropertyCodegen>()
} }
fun parseAndAnalyze(sources: List<String>, disposer: Disposable, arm: Boolean = false): TranslationState { fun parseAndAnalyze(sources: List<String>, disposer: Disposable, arm: Boolean = false): TranslationState {
@@ -24,7 +24,11 @@ class VariableManager {
fileVariableCollectionTree.put(name, stack) fileVariableCollectionTree.put(name, stack)
} }
fun getVariable(name: String, type: LLVMType, pointer: Boolean): LLVMVariable { fun addGlobalVariable(name: String, variable: LLVMVariable) {
globalVariableCollection.put(name, variable)
}
fun receiveVariable(name: String, type: LLVMType, pointer: Boolean): LLVMVariable {
val ourVersion = variableVersion.getOrDefault(name, 0) + 1 val ourVersion = variableVersion.getOrDefault(name, 0) + 1
variableVersion.put(name, ourVersion) variableVersion.put(name, ourVersion)
@@ -152,6 +152,10 @@ class LLVMBuilder(val arm: Boolean) {
llvmCode.appendln("store ${allocVariable.type} $constantValue, ${allocVariable.getType()} $allocVariable, align ${allocVariable.type.align}") llvmCode.appendln("store ${allocVariable.type} $constantValue, ${allocVariable.getType()} $allocVariable, align ${allocVariable.type.align}")
} }
fun declareGlovalVariable(variable: LLVMVariable, defaultValue: String = variable.type.defaultValue) {
llvmCode.appendln("$variable = global ${variable.type} $defaultValue, align ${variable.type.align}")
}
fun loadAndGetVariable(source: LLVMVariable): LLVMVariable { fun loadAndGetVariable(source: LLVMVariable): LLVMVariable {
assert(!source.pointer) assert(!source.pointer)
val target = getNewVariable(source.type, source.pointer, source.kotlinName) val target = getNewVariable(source.type, source.pointer, source.kotlinName)
@@ -36,7 +36,7 @@ class LLVMBooleanType() : LLVMType() {
override fun operatorNeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = override fun operatorNeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMBooleanType(), "icmp ne i1 $firstOp, $secondOp") LLVMExpression(LLVMBooleanType(), "icmp ne i1 $firstOp, $secondOp")
override fun parseArg(inputArg: String) = when(inputArg.toLowerCase()){ override fun parseArg(inputArg: String) = when (inputArg.toLowerCase()) {
"true" -> "1" "true" -> "1"
"false" -> "0" "false" -> "0"
else -> throw IllegalArgumentException("Failed to parse boolean type") else -> throw IllegalArgumentException("Failed to parse boolean type")
@@ -44,6 +44,7 @@ class LLVMBooleanType() : LLVMType() {
override val align = 4 override val align = 4
override val size: Byte = 1 override val size: Byte = 1
override val defaultValue = "0"
override fun toString() = "i1" override fun toString() = "i1"
} }
@@ -25,4 +25,5 @@ class LLVMCharType() : LLVMType() {
override val align = 1 override val align = 1
override val size: Byte = 1 override val size: Byte = 1
override fun toString(): String = "i8" override fun toString(): String = "i8"
override val defaultValue = "0"
} }
@@ -21,4 +21,5 @@ class LLVMDoubleType() : LLVMType() {
override val align = 8 override val align = 8
override val size: Byte = 8 override val size: Byte = 8
override fun toString() = "double" override fun toString() = "double"
override val defaultValue = "0.0"
} }
@@ -5,6 +5,8 @@ import org.kotlinnative.translator.llvm.LLVMMapStandardType
import org.kotlinnative.translator.llvm.LLVMVariable import org.kotlinnative.translator.llvm.LLVMVariable
class LLVMFunctionType(type: KotlinType) : LLVMType() { class LLVMFunctionType(type: KotlinType) : LLVMType() {
override val defaultValue = throw UnsupportedOperationException()
override val align: Int = 4 override val align: Int = 4
override val size: Byte = 4 override val size: Byte = 4
@@ -39,6 +39,7 @@ class LLVMIntType() : LLVMType() {
override val align = 4 override val align = 4
override val size: Byte = 4 override val size: Byte = 4
override val defaultValue = "0"
override fun toString() = "i32" override fun toString() = "i32"
} }
@@ -4,6 +4,7 @@ import java.util.*
class LLVMReferenceType(val type: String, val prefix: String = "") : LLVMType() { class LLVMReferenceType(val type: String, val prefix: String = "") : LLVMType() {
override val defaultValue = throw UnsupportedOperationException()
override val align = 4 override val align = 4
override val size: Byte = 4 override val size: Byte = 4
override fun toString() = "%$prefix.$type" override fun toString() = "%$prefix.$type"
@@ -24,5 +24,7 @@ class LLVMShortType() : LLVMType() {
override val size: Byte = 2 override val size: Byte = 2
override val align = 2 override val align = 2
override val defaultValue = "0"
override fun toString(): String = "i16" override fun toString(): String = "i16"
} }
@@ -21,6 +21,7 @@ abstract class LLVMType() : Cloneable {
abstract val align: Int abstract val align: Int
abstract val size: Byte abstract val size: Byte
abstract val defaultValue: String
} }
fun parseLLVMType(type: String): LLVMType = when (type) { fun parseLLVMType(type: String): LLVMType = when (type) {
@@ -4,5 +4,7 @@ class LLVMVoidType() : LLVMType() {
override val align = 0 override val align = 0
override val size: Byte = 0 override val size: Byte = 0
override val defaultValue = throw UnsupportedOperationException()
override fun toString(): String = "void" override fun toString(): String = "void"
} }