From 5fb10e68bdfa078c61106e2915c0affb5b1f0eb0 Mon Sep 17 00:00:00 2001 From: Alexey Stepanov Date: Mon, 8 Aug 2016 18:55:13 +0300 Subject: [PATCH] translator: add type detection and initializing on class variables --- .../kotlinnative/translator/BlockCodegen.kt | 9 +++++---- .../kotlinnative/translator/StructCodegen.kt | 20 +++++++++++++++++-- .../translator/llvm/types/LLVMStringType.kt | 15 ++++++++++++++ .../input/initialized_class_fields_1.txt | 1 + .../kotlin/initialized_class_fields_1.kt | 8 ++++++++ 5 files changed, 47 insertions(+), 6 deletions(-) create mode 100644 translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMStringType.kt create mode 100644 translator/src/test/kotlin/tests/input/initialized_class_fields_1.txt create mode 100644 translator/src/test/kotlin/tests/kotlin/initialized_class_fields_1.kt diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt index c0c8093b431..bb3e7ee6025 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt @@ -78,7 +78,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM executeWhileBlock(condition.firstChild as KtBinaryExpression, bodyExpression.firstChild, scopeDepth, checkConditionBeforeExecute = false) } - private fun evaluateExpression(expr: PsiElement?, scopeDepth: Int): LLVMSingleValue? { + fun evaluateExpression(expr: PsiElement?, scopeDepth: Int): LLVMSingleValue? { return when (expr) { is KtBinaryExpression -> evaluateBinaryExpression(expr, scopeDepth) is KtPostfixExpression -> evaluatePostfixExpression(expr, scopeDepth) @@ -191,6 +191,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM return evaluateClassScopedDotExpression(clazz, selectorExpr, scopeDepth) } + private fun evaluateExtensionExpression(receiver: KtExpression, selector: KtCallExpression, scopeDepth: Int): LLVMSingleValue? { val receiverType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, receiver) val standardType = LLVMMapStandardType(receiverType!!.type!!) @@ -229,7 +230,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM return result } - private fun evaluateMemberMethodOrField(receiver: LLVMVariable, selectorName: String, scopeDepth: Int, call: PsiElement): LLVMSingleValue? { + fun evaluateMemberMethodOrField(receiver: LLVMVariable, selectorName: String, scopeDepth: Int, call: PsiElement?): LLVMSingleValue? { val type = receiver.type as LLVMReferenceType val clazz = resolveClassOrObjectLocation(type) val field = clazz.fieldsIndex[selectorName] @@ -240,7 +241,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM return result } - val names = parseArgList(call as KtCallExpression, scopeDepth) + val names = parseArgList(call!! as KtCallExpression, scopeDepth) val typePath = type.location.joinToString(".") val types = if (names.size > 0) "_${names.joinToString(separator = "_", transform = { it.type!!.mangle() })}" else "" val methodName = "${if (typePath.length > 0) "$typePath." else ""}${clazz.structName}.${selectorName.substringBefore('(')}$types" @@ -486,7 +487,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM } } - private fun executeBinaryExpression(operator: IElementType, referenceName: KtSimpleNameExpression?, left: LLVMSingleValue, right: LLVMSingleValue) + fun executeBinaryExpression(operator: IElementType, referenceName: KtSimpleNameExpression?, left: LLVMSingleValue, right: LLVMSingleValue) = addPrimitiveBinaryOperation(operator, referenceName, left, right) private fun evaluateElvisOperator(expr: KtBinaryExpression, scopeDepth: Int): LLVMVariable { diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt index 0e131733b49..d3877fbcbd3 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt @@ -1,7 +1,9 @@ package org.kotlinnative.translator import com.intellij.psi.PsiElement +import jdk.nashorn.internal.ir.Block import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.types.KotlinType @@ -28,6 +30,7 @@ abstract class StructCodegen(open val state: TranslationState, val enumFields = HashMap() val constructorFields = ArrayList() + val initializedFields = HashMap() abstract val type: LLVMReferenceType abstract var size: Int @@ -64,11 +67,15 @@ abstract class StructCodegen(open val state: TranslationState, for (declaration in declarations) { when (declaration) { is KtProperty -> { - val ktType = state.bindingContext.get(BindingContext.TYPE, declaration.typeReference)!! + val ktType = state.bindingContext.get(BindingContext.TYPE, declaration.typeReference) + ?: state.bindingContext.get(BindingContext.VARIABLE, declaration)!!.type val field = resolveType(declaration, ktType) field.offset = offset offset++ + if ((declaration.initializer != null) && !(this is ObjectCodegen)){ + initializedFields.put(field, declaration.initializer!!) + } fields.add(field) fieldsIndex[field.label] = field size += field.type.size @@ -133,7 +140,6 @@ abstract class StructCodegen(open val state: TranslationState, } private fun generateLoadArguments(thisField: LLVMVariable) { - val thisVariable = LLVMVariable(thisField.label, thisField.type, thisField.label, LLVMRegisterScope(), pointer = 0) codeBuilder.loadArgument(thisVariable, false) @@ -163,6 +169,16 @@ abstract class StructCodegen(open val state: TranslationState, } } + + val blockCodegen = object : BlockCodegen(state, variableManager, codeBuilder) {} + val receiverThis = LLVMVariable("classvariable.this.addr", type, scope = LLVMRegisterScope(), pointer = 1) + for ((variable, initializer) in initializedFields) { + val left = blockCodegen.evaluateMemberMethodOrField(receiverThis, variable.label, blockCodegen.topLevel, call = null)!! + val right = blockCodegen.evaluateExpression(initializer, scopeDepth = blockCodegen.topLevel)!! + + blockCodegen.executeBinaryExpression(KtTokens.EQ, referenceName = null, left = left, right = right) + } + } private fun generateReturn() { diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMStringType.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMStringType.kt new file mode 100644 index 00000000000..bad22fe03e2 --- /dev/null +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMStringType.kt @@ -0,0 +1,15 @@ +/*package org.kotlinnative.translator.llvm.types + +class LLVMStringType(override val length: Int) : LLVMArray, LLVMType() { + + override var size: Int = 1 + override val align = 8 + override val defaultValue = "" + + override fun mangle() = "String" + + override fun basicType() = LLVMCharType() + override fun toString(): String = "i8*" + override fun fullType() = "[${length + 1} x i8]" +} +*/ \ No newline at end of file diff --git a/translator/src/test/kotlin/tests/input/initialized_class_fields_1.txt b/translator/src/test/kotlin/tests/input/initialized_class_fields_1.txt new file mode 100644 index 00000000000..b84e32f984d --- /dev/null +++ b/translator/src/test/kotlin/tests/input/initialized_class_fields_1.txt @@ -0,0 +1 @@ +initialized_class_fields_1() == 524 diff --git a/translator/src/test/kotlin/tests/kotlin/initialized_class_fields_1.kt b/translator/src/test/kotlin/tests/kotlin/initialized_class_fields_1.kt new file mode 100644 index 00000000000..7fd9f5e7010 --- /dev/null +++ b/translator/src/test/kotlin/tests/kotlin/initialized_class_fields_1.kt @@ -0,0 +1,8 @@ +class initialized_class_fields_1_class { + var pos: Int = 524 +} + +fun initialized_class_fields_1(): Int { + val instance = initialized_class_fields_1_class() + return instance.pos +} \ No newline at end of file