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