diff --git a/translator/.idea/modules/ast-kotlin_test.iml b/translator/.idea/modules/ast-kotlin_test.iml
index 8717ed3e558..9dd3eef3c3e 100644
--- a/translator/.idea/modules/ast-kotlin_test.iml
+++ b/translator/.idea/modules/ast-kotlin_test.iml
@@ -10,7 +10,6 @@
-
diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt
index 455634e6ec9..c0c8093b431 100644
--- a/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt
+++ b/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getNextSiblingIgnoringWhitespaceAndComments
import org.jetbrains.kotlin.psi.psiUtil.siblings
import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.resolve.calls.callUtil.getType
import org.jetbrains.kotlin.resolve.calls.callUtil.getValueArgumentsInParentheses
import org.jetbrains.kotlin.resolve.constants.TypedCompileTimeConstant
import org.kotlinnative.translator.llvm.*
@@ -100,7 +101,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
}
private fun evaluateThisExpression(): LLVMSingleValue? {
- return variableManager.getLLVMvalue("this")
+ return variableManager.get("this")
}
fun evaluateStringTemplateExpression(expr: KtStringTemplateExpression): LLVMSingleValue? {
@@ -172,7 +173,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
var receiver = when (receiverExpr) {
is KtCallExpression,
is KtBinaryExpression -> evaluateExpression(receiverExpr, scopeDepth) as LLVMVariable
- else -> variableManager.getLLVMvalue(receiverName)
+ else -> variableManager.get(receiverName)
}
if (receiver != null) {
@@ -212,7 +213,6 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
}
private fun evaluateClassScopedDotExpression(clazz: ClassCodegen, selector: KtExpression, scopeDepth: Int): LLVMSingleValue? = when (selector) {
-
is KtCallExpression -> evaluateCallExpression(selector, scopeDepth, clazz)
is KtReferenceExpression -> evaluateReferenceExpression(selector, scopeDepth, clazz)
else -> throw UnsupportedOperationException()
@@ -221,12 +221,10 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
private fun evaluateNameReferenceExpression(expr: KtNameReferenceExpression, classScope: ClassCodegen? = null): LLVMSingleValue? {
val fieldName = state.bindingContext.get(BindingContext.REFERENCE_TARGET, expr)!!.name.toString()
val field = classScope!!.companionFieldsIndex[fieldName]
-
val companionObject = classScope.companionFieldsSource[fieldName]
-
- val receiver = variableManager.getLLVMvalue(companionObject!!.fullName)!!
-
+ val receiver = variableManager.get(companionObject!!.fullName)!!
val result = codeBuilder.getNewVariable(field!!.type, pointer = 1)
+
codeBuilder.loadClassField(result, receiver, field.offset)
return result
}
@@ -282,10 +280,22 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
return indexVariable
}
- private fun evaluateReferenceExpression(expr: KtReferenceExpression, scopeDepth: Int, classScope: ClassCodegen? = null): LLVMSingleValue? = when (expr) {
- is KtArrayAccessExpression -> evaluateArrayAccessExpression(expr, scopeDepth + 1)
- else -> if ((expr is KtNameReferenceExpression) && (classScope != null)) evaluateNameReferenceExpression(expr, classScope)
- else variableManager.getLLVMvalue(expr.firstChild.text)
+ private fun evaluateReferenceExpression(expr: KtReferenceExpression, scopeDepth: Int, classScope: ClassCodegen? = null): LLVMSingleValue? = when {
+ expr is KtArrayAccessExpression -> evaluateArrayAccessExpression(expr, scopeDepth + 1)
+ isEnumClassField(expr) -> resolveEnumClassField(expr)
+ (expr is KtNameReferenceExpression) && (classScope != null) -> evaluateNameReferenceExpression(expr, classScope)
+ else -> variableManager.get(expr.firstChild.text)
+ }
+
+ private fun resolveEnumClassField(expr: KtReferenceExpression): LLVMSingleValue {
+ val field = state.classes[expr.getType(state.bindingContext).toString()]!!.enumFields[expr.text]!!
+ return codeBuilder.loadAndGetVariable(codeBuilder.loadAndGetVariable(field))
+ }
+
+ private fun isEnumClassField(expr: KtReferenceExpression): Boolean {
+ val name = expr.getType(state.bindingContext)?.toString() ?: return false
+ val clazz = state.classes[name] ?: return false
+ return clazz.enumFields.containsKey(expr.text)
}
private fun evaluateCallExpression(expr: KtCallExpression, scopeDepth: Int, classScope: ClassCodegen? = null): LLVMSingleValue? {
@@ -308,7 +318,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
return evaluateConstructorCallExpression(LLVMVariable(name, descriptor.type, scope = LLVMVariableScope()), args)
}
- val localFunction = variableManager.getLLVMvalue(name)
+ val localFunction = variableManager.get(name)
if (localFunction != null) {
val type = localFunction.type as LLVMFunctionType
val args = loadArgsIfRequired(names, type.arguments)
@@ -321,7 +331,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
if (classDescriptor.companionMethods.containsKey(methodShortName)) {
val descriptor = classDescriptor.companionMethods[methodShortName] ?: return null
val parentDescriptor = descriptor.parentCodegen!!
- val receiver = variableManager.getLLVMvalue(parentDescriptor.fullName)!!
+ val receiver = variableManager.get(parentDescriptor.fullName)!!
val methodFullName = descriptor.name
val returnType = descriptor.returnType!!.type
@@ -613,7 +623,9 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
private fun evaluateWhenItem(item: KtWhenEntry, target: LLVMSingleValue, resultVariable: LLVMVariable, elseLabel: LLVMLabel, endLabel: LLVMLabel, isElse: Boolean, scopeDepth: Int) {
val successConditionsLabel = codeBuilder.getNewLabel(prefix = "when_condition_success")
var nextLabel = codeBuilder.getNewLabel(prefix = "when_condition_condition")
+
codeBuilder.addUnconditionalJump(nextLabel)
+
for (condition in item.conditions) {
codeBuilder.markWithLabel(nextLabel)
nextLabel = codeBuilder.getNewLabel(prefix = "when_condition_condition")
@@ -623,10 +635,12 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
codeBuilder.addCondition(conditionResult, successConditionsLabel, nextLabel)
}
+
codeBuilder.markWithLabel(nextLabel)
codeBuilder.addComment("last condition item")
codeBuilder.addUnconditionalJump(if (isElse) successConditionsLabel else elseLabel)
codeBuilder.markWithLabel(successConditionsLabel)
+
val successExpression = evaluateExpression(item.expression, scopeDepth + 1)
codeBuilder.storeVariable(resultVariable, successExpression ?: return)
codeBuilder.addUnconditionalJump(endLabel)
@@ -638,9 +652,11 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
val whenExpression = expr.subjectExpression
val kotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, expr)!!.type!!
val expressionType = LLVMMapStandardType(kotlinType)
+ if (state.classes.containsKey(kotlinType.toString())) {
+ (expressionType as LLVMReferenceType).prefix = "class"
+ }
val targetExpression = evaluateExpression(whenExpression, scopeDepth + 1)!!
-
val resultVariable = codeBuilder.getNewVariable(expressionType, pointer = 1)
codeBuilder.allocStackPointedVarAsValue(resultVariable)
diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt
index e81908a00b6..15d3529c9df 100644
--- a/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt
+++ b/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt
@@ -1,14 +1,11 @@
package org.kotlinnative.translator
-import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.resolve.BindingContext
import org.kotlinnative.translator.exceptions.TranslationException
import org.kotlinnative.translator.llvm.LLVMBuilder
-import org.kotlinnative.translator.llvm.LLVMClassVariable
-import org.kotlinnative.translator.llvm.types.LLVMEnumItemType
import org.kotlinnative.translator.llvm.types.LLVMReferenceType
class ClassCodegen(override val state: TranslationState,
@@ -20,6 +17,7 @@ class ClassCodegen(override val state: TranslationState,
StructCodegen(state, variableManager, clazz, state.bindingContext.get(BindingContext.CLASS, clazz) ?: throw TranslationException(), codeBuilder, parentCodegen) {
val annotation: Boolean
+ val enum: Boolean
override var size: Int = 0
override val structName: String = clazz.name!!
@@ -31,7 +29,9 @@ class ClassCodegen(override val state: TranslationState,
val parameterList = clazz.getPrimaryConstructorParameterList()?.parameters ?: listOf()
annotation = descriptor.kind == ClassKind.ANNOTATION_CLASS
- indexFields(descriptor, parameterList)
+ enum = descriptor.kind == ClassKind.ENUM_CLASS
+
+ indexFields(parameterList)
generateInnerFields(clazz.declarations)
if (parentCodegen != null) {
@@ -42,7 +42,7 @@ class ClassCodegen(override val state: TranslationState,
type.size = size
}
- private fun indexFields(descriptor: ClassDescriptor, parameters: MutableList) {
+ private fun indexFields(parameters: MutableList) {
if (annotation) {
return
}
@@ -56,18 +56,6 @@ class ClassCodegen(override val state: TranslationState,
fieldsIndex[item.label] = item
size += type.size
}
-
- when (descriptor.kind) {
- ClassKind.ENUM_CLASS -> {
- val item = LLVMClassVariable("enum_item", LLVMEnumItemType())
- item.offset = fields.size
- fields.add(item)
- fieldsIndex["enum_item"] = item
- size += type.size
- }
- else -> {
- }
- }
}
fun generate() {
diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/PropertyCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/PropertyCodegen.kt
index 78f50d0a2d4..57a8dd35953 100644
--- a/translator/src/main/kotlin/org/kotlinnative/translator/PropertyCodegen.kt
+++ b/translator/src/main/kotlin/org/kotlinnative/translator/PropertyCodegen.kt
@@ -20,7 +20,7 @@ class PropertyCodegen(val state: TranslationState, val variableManager: Variable
val variableType = LLVMInstanceOfStandardType(property.name ?: return, kotlinType).type
val variable = LLVMVariable(property.name.toString(), variableType, property.name.toString(), LLVMVariableScope(), pointer = 1)
variableManager.addGlobalVariable(property.name.toString(), variable)
- codeBuilder.declareGlobalVariable(variable, variableType.parseArg(value.toString()))
+ codeBuilder.defineGlobalVariable(variable, variableType.parseArg(value.toString()))
}
}
diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt
index 38ee6f1f2e9..0e131733b49 100644
--- a/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt
+++ b/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt
@@ -25,6 +25,7 @@ abstract class StructCodegen(open val state: TranslationState,
val companionFields = ArrayList()
val companionFieldsIndex = HashMap()
val companionFieldsSource = HashMap()
+ val enumFields = HashMap()
val constructorFields = ArrayList()
@@ -35,9 +36,9 @@ abstract class StructCodegen(open val state: TranslationState,
val fullName: String
get() = "${if (type.location.size > 0) "${type.location.joinToString(".")}." else ""}$structName"
-
fun generate(declarations: List) {
generateStruct()
+ generateEnumFields()
generatePrimaryConstructor()
for (declaration in declarations) {
@@ -72,6 +73,11 @@ abstract class StructCodegen(open val state: TranslationState,
fieldsIndex[field.label] = field
size += field.type.size
}
+ is KtEnumEntry -> {
+ val name = declaration.name!!
+ val field = LLVMVariable("class.$fullName.$name", type, scope = LLVMVariableScope(), pointer = 2)
+ enumFields.put(name, field)
+ }
is KtClass -> {
nestedClasses.put(declaration.name!!,
ClassCodegen(state,
@@ -83,6 +89,22 @@ abstract class StructCodegen(open val state: TranslationState,
}
}
+ private fun generateEnumFields() {
+ val enumEntries = classOrObject.declarations.filter { it is KtEnumEntry }
+
+ for (declaration in enumEntries) {
+ val name = declaration.name!!
+ val initializer = (declaration as KtEnumEntry).initializerList!!.initializers[0]
+ val arguments = (initializer as KtSuperTypeCallEntry).valueArguments.map { it.getArgumentExpression()!!.text }
+
+ val field = codeBuilder.getNewVariable(type, scope = LLVMVariableScope())
+ val enumField = enumFields[name]!!
+
+ codeBuilder.defineGlobalVariable(field, codeBuilder.makeStructInitializer(constructorFields, arguments))
+ codeBuilder.defineGlobalVariable(LLVMVariable(enumField.label, enumField.type, enumField.kotlinName, enumField.scope, enumField.pointer - 1), "$field")
+ }
+ }
+
private fun generateStruct() {
codeBuilder.createClass(fullName, fields)
}
diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/VariableManager.kt b/translator/src/main/kotlin/org/kotlinnative/translator/VariableManager.kt
index bce75e8fe11..489a434c8b7 100644
--- a/translator/src/main/kotlin/org/kotlinnative/translator/VariableManager.kt
+++ b/translator/src/main/kotlin/org/kotlinnative/translator/VariableManager.kt
@@ -10,7 +10,7 @@ class VariableManager(val globalVariableCollection: HashMap>>()
private var variableVersion = HashMap()
- fun getLLVMvalue(variableName: String): LLVMVariable? {
+ fun get(variableName: String): LLVMVariable? {
return fileVariableCollectionTree[variableName]?.peek()?.first ?: globalVariableCollection[variableName]
}
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 3f310df5967..cd2e6ae91ee 100644
--- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt
+++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt
@@ -1,7 +1,9 @@
package org.kotlinnative.translator.llvm
-import org.jetbrains.kotlin.psi.KtSimpleNameExpression
-import org.kotlinnative.translator.llvm.types.*
+import org.kotlinnative.translator.llvm.types.LLVMCharType
+import org.kotlinnative.translator.llvm.types.LLVMIntType
+import org.kotlinnative.translator.llvm.types.LLVMStringType
+import org.kotlinnative.translator.llvm.types.LLVMType
class LLVMBuilder(val arm: Boolean) {
private val POINTER_SIZE = 4
@@ -28,9 +30,9 @@ class LLVMBuilder(val arm: Boolean) {
}
}
- fun getNewVariable(type: LLVMType, pointer: Int = 0, kotlinName: String? = null): LLVMVariable {
+ fun getNewVariable(type: LLVMType, pointer: Int = 0, kotlinName: String? = null, scope: LLVMScope = LLVMRegisterScope()): LLVMVariable {
variableCount++
- return LLVMVariable("var$variableCount", type, kotlinName, LLVMRegisterScope(), pointer)
+ return LLVMVariable("var$variableCount", type, kotlinName, scope, pointer)
}
fun getNewLabel(scope: LLVMScope = LLVMRegisterScope(), prefix: String): LLVMLabel {
@@ -181,10 +183,13 @@ class LLVMBuilder(val arm: Boolean) {
localCode.appendln("store ${allocVariable.type} $constantValue, ${allocVariable.getType()} $allocVariable, align ${allocVariable.type.align}")
}
- fun declareGlobalVariable(variable: LLVMVariable, defaultValue: String = variable.type.defaultValue) {
- localCode.appendln("$variable = global ${variable.type} $defaultValue, align ${variable.type.align}")
+ fun defineGlobalVariable(variable: LLVMVariable, defaultValue: String = variable.type.defaultValue) {
+ localCode.appendln("$variable = global ${variable.getType()} $defaultValue, align ${variable.type.align}")
}
+ fun makeStructInitializer(args: List, values: List)
+ = "{ ${ args.mapIndexed { i: Int, variable: LLVMVariable -> "${variable.type} ${values[i]}" }.joinToString() } }"
+
fun loadAndGetVariable(source: LLVMVariable): LLVMVariable {
assert(source.pointer > 0)
val target = getNewVariable(source.type, source.pointer - 1, source.kotlinName)
diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMEnumItemType.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMEnumItemType.kt
deleted file mode 100644
index 76249978095..00000000000
--- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMEnumItemType.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.kotlinnative.translator.llvm.types
-
-
-class LLVMEnumItemType() : LLVMType() {
-
- override val align = 4
- override var size: Int = 4
- override val defaultValue = "0"
-
- override fun mangle() = "Enum"
-
- override fun toString() = "i32"
-}
\ No newline at end of file