diff --git a/proto/runtime/src/main/kotlin/WireFormat.kt b/proto/runtime/src/main/kotlin/WireFormat.kt index de70a45d65f..d98ec546b5b 100644 --- a/proto/runtime/src/main/kotlin/WireFormat.kt +++ b/proto/runtime/src/main/kotlin/WireFormat.kt @@ -15,7 +15,7 @@ object WireFormat { val FIXED_64_BYTE_SIZE: Int = 8 fun getTagWireType(tag: Int): WireType { - return WireType.from ( (tag and TAG_TYPE_MASK).toByte()) + return WireType.from((tag and TAG_TYPE_MASK).toByte()) } fun getTagFieldNumber(tag: Int): Int { diff --git a/proto/runtime/src/main/kotlin/WireType.kt b/proto/runtime/src/main/kotlin/WireType.kt index 4b4478b0a8c..d01e9d550ab 100644 --- a/proto/runtime/src/main/kotlin/WireType.kt +++ b/proto/runtime/src/main/kotlin/WireType.kt @@ -15,7 +15,7 @@ enum class WireType(val id: Int) { UNDEFINED(6); // indicates error when parsing from Int companion object { - fun from (value: Byte): WireType { + fun from(value: Byte): WireType { return when (value) { 0.toByte() -> VARINT 1.toByte() -> FIX_64 @@ -27,4 +27,4 @@ enum class WireType(val id: Int) { } } } -} \ No newline at end of file +} diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt index 4a87f140965..7e89f40b14a 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert 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.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver import org.kotlinnative.translator.llvm.* import org.kotlinnative.translator.llvm.types.* @@ -206,27 +207,13 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va } } - val type = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, receiverExpr)?.type - ?: receiverExpr.getType(state.bindingContext) - ?: receiverExpr.getQualifiedExpressionForReceiver()?.getType(state.bindingContext) - - val path = type?.getSubtypesPredicate()?.toString()?.split(".") - val classReference = LLVMReferenceType(path?.last() ?: receiverName, "class") - - if (path != null) { - classReference.location.addAll(path.dropLast(1)) - } - - val clazz = resolveClassOrObjectLocation(classReference) ?: return evaluateExtensionExpression(receiverExpr, selectorExpr as KtCallExpression, scopeDepth) - return evaluateClassScopedDotExpression(clazz, selectorExpr, scopeDepth) + val clazz = resolveCodegen(receiverExpr) ?: return evaluateExtensionExpression(receiverExpr, selectorExpr as KtCallExpression, scopeDepth) + return evaluateClassScopedDotExpression(clazz, selectorExpr, scopeDepth, receiver) } 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!!) -// if (standardType is LLVMReferenceType) { -// standardType.location.addAll(receiverType.type!!.getSubtypesPredicate().toString().split(".").dropLast(1)) -// } val function = selector.firstChild.firstChild.text val names = parseArgList(selector, scopeDepth) @@ -244,23 +231,12 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va return evaluateFunctionCallExpression(LLVMVariable(extensionCodegen.fullName, extensionCodegen.returnType!!.type, scope = LLVMVariableScope()), args) } - private fun evaluateClassScopedDotExpression(clazz: StructCodegen, selector: KtExpression, scopeDepth: Int): LLVMSingleValue? = when (selector) { - is KtCallExpression -> evaluateCallExpression(selector, scopeDepth, clazz) + private fun evaluateClassScopedDotExpression(clazz: StructCodegen, selector: KtExpression, scopeDepth: Int, receiver: LLVMVariable? = null): LLVMSingleValue? = when (selector) { + is KtCallExpression -> evaluateCallExpression(selector, scopeDepth, clazz, caller = receiver) is KtReferenceExpression -> evaluateReferenceExpression(selector, scopeDepth, clazz) else -> throw UnsupportedOperationException() } - private fun evaluateNameReferenceExpression(expr: KtNameReferenceExpression, classScope: StructCodegen): 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[companionObject!!.fullName]!! - val result = codeBuilder.getNewVariable(field!!.type, pointer = 1) - - codeBuilder.loadClassField(result, receiver, field.offset) - return result - } - fun evaluateMemberMethodOrField(receiver: LLVMVariable, selectorName: String, scopeDepth: Int, call: PsiElement? = null): LLVMSingleValue? { val type = receiver.type as LLVMReferenceType val clazz = resolveClassOrObjectLocation(type) ?: throw UnexpectedException(type.toString()) @@ -272,7 +248,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va return result } - val names = parseArgList(call!! as KtCallExpression, scopeDepth) + (call as? KtCallExpression) ?: throw UnexpectedException("$receiver:$selectorName") + 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('(').trim()}$types" @@ -353,23 +330,42 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va private fun evaluateReferenceExpression(expr: KtReferenceExpression, scopeDepth: Int, classScope: StructCodegen? = null): LLVMSingleValue? = when { expr is KtArrayAccessExpression -> evaluateArrayAccessExpression(expr, scopeDepth + 1) - isEnumClassField(expr) -> resolveEnumClassField(expr) + isEnumClassField(expr, classScope) -> resolveEnumClassField(expr, classScope) + resolveContainingClass(expr) != null -> { + val clazz = resolveContainingClass(expr) + val receiver = if (clazz != null) variableManager[clazz.fullName] ?: variableManager["this"] else variableManager["this"] + evaluateMemberMethodOrField(receiver!!, expr.firstChild.text, topLevel) + } (expr is KtNameReferenceExpression) && (classScope != null) -> evaluateNameReferenceExpression(expr, classScope.parentCodegen!!) - resolveContainingClass(expr) != null -> evaluateMemberMethodOrField(variableManager["this"]!!, expr.firstChild.text, topLevel) else -> variableManager[expr.firstChild.text] } - private fun resolveEnumClassField(expr: KtReferenceExpression): LLVMSingleValue { - return resolveCodegen(expr)!!.enumFields[expr.text]!! + private fun evaluateNameReferenceExpression(expr: KtNameReferenceExpression, classScope: StructCodegen): LLVMSingleValue? { + val fieldName = state.bindingContext.get(BindingContext.REFERENCE_TARGET, expr)!!.name.toString() + val companionObject = (classScope as ClassCodegen).companionObjectCodegen ?: throw UnexpectedException(expr.text) + val field = companionObject.fieldsIndex[fieldName] + val receiver = variableManager[companionObject.fullName]!! + val result = codeBuilder.getNewVariable(field!!.type, pointer = 1) + + codeBuilder.loadClassField(result, receiver, field.offset) + return result } - private fun isEnumClassField(expr: KtReferenceExpression): Boolean { - val clazz = resolveCodegen(expr) ?: return false - return clazz.enumFields.containsKey(expr.text) - } + private fun resolveEnumClassField(expr: KtReferenceExpression, classScope: StructCodegen?): LLVMSingleValue = + (classScope ?: resolveCodegen(expr))!!.enumFields[expr.text]!! + + private fun isEnumClassField(expr: KtReferenceExpression, classScope: StructCodegen?): Boolean = + (classScope ?: resolveCodegen(expr))?.enumFields?.containsKey(expr.text) ?: false + + private fun resolveCodegen(expr: KtExpression): StructCodegen? { + val type = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, expr)?.type + ?: expr.getType(state.bindingContext) + ?: expr.getQualifiedExpressionForReceiver()?.getType(state.bindingContext) + + val location = type?.getSubtypesPredicate()?.toString()?.split(".") + ?: state.bindingContext.get(BindingContext.REFERENCE_TARGET, expr as KtReferenceExpression)?.fqNameSafe?.toString()?.split(".") + ?: return null - private fun resolveCodegen(expr: KtReferenceExpression): StructCodegen? { - val location = expr.getType(state.bindingContext)?.getSubtypesPredicate()?.toString()?.split(".") ?: return null val name = location.last() val classType = LLVMReferenceType(name, prefix = "class") @@ -378,7 +374,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va return resolveClassOrObjectLocation(classType) } - private fun evaluateCallExpression(expr: KtCallExpression, scopeDepth: Int, classScope: StructCodegen? = null): LLVMSingleValue? { + private fun evaluateCallExpression(expr: KtCallExpression, scopeDepth: Int, classScope: StructCodegen? = null, caller: LLVMVariable? = null): LLVMSingleValue? { val names = parseArgList(expr, scopeDepth) val name = expr.firstChild.firstChild.text val external = state.externalFunctions.containsKey(name) @@ -391,10 +387,10 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va return evaluateFunctionCallExpression(LLVMVariable(function, descriptor.returnType!!.type, scope = LLVMVariableScope()), args) } - if (state.classes.containsKey(name)) { - val descriptor = state.classes[name] ?: return null + if (state.classes.containsKey(name) || classScope?.structName == name) { + val descriptor = state.classes[name] ?: classScope ?: return null val args = loadArgsIfRequired(names, descriptor.constructorFields) - return evaluateConstructorCallExpression(LLVMVariable(name, descriptor.type, scope = LLVMVariableScope()), args) + return evaluateConstructorCallExpression(LLVMVariable(descriptor.fullName, descriptor.type, scope = LLVMVariableScope()), args) } val localFunction = variableManager[name] @@ -405,10 +401,9 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va } if (classScope != null) { - val classDescriptor = classScope.parentCodegen - val methodShortName = classDescriptor?.structName + "." + function - if (classDescriptor != null && classDescriptor.companionMethods.containsKey(methodShortName)) { - val descriptor = classDescriptor.companionMethods[methodShortName] ?: return null + val methodShortName = classScope.structName + "." + function + if (classScope != null && classScope.methods.containsKey(methodShortName)) { + val descriptor = classScope.methods[methodShortName] ?: return null val parentDescriptor = descriptor.parentCodegen!! val receiver = variableManager[parentDescriptor.fullName]!! val methodFullName = descriptor.name @@ -433,7 +428,17 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va if (containingClass != null) { val name = "${containingClass.fullName}.$function" val method = containingClass.methods[name]!! - val args = mutableListOf(variableManager["this"]!!) + val args = mutableListOf() + val leftName = (expr.context as? KtDotQualifiedExpression)?.receiverExpression?.text + + if (caller != null) { + args.add(caller) + } else if (variableManager[containingClass.fullName] != null) { + args.add(variableManager[containingClass.fullName]!!) + } else { + args.add(variableManager["this"]!!) + } + args.addAll(loadArgsIfRequired(names, method.args)) return evaluateFunctionCallExpression(LLVMVariable(method.fullName, method.returnType?.type ?: LLVMVoidType(), scope = LLVMVariableScope()), args) @@ -860,7 +865,10 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va codeBuilder.addUnconditionalJump(if (checkConditionBeforeExecute) conditionLabel else bodyLabel) codeBuilder.markWithLabel(conditionLabel) - val conditionResult = evaluateExpression(condition, scopeDepth + 1)!! + var conditionResult = evaluateExpression(condition, scopeDepth + 1)!! + while (conditionResult.pointer > 0) { + conditionResult = codeBuilder.loadAndGetVariable(conditionResult as LLVMVariable) + } codeBuilder.addCondition(conditionResult, bodyLabel, exitLabel) evaluateCodeBlock(bodyExpression, bodyLabel, conditionLabel, scopeDepth + 1) diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt index fb8731a95fa..1967f9dfdd6 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt @@ -84,19 +84,7 @@ class ClassCodegen(state: TranslationState, nestedClasses.forEach { x, classCodegen -> classCodegen.generate() } if (companionObjectCodegen != null) { - val companionObject = clazz.getCompanionObjects().first() - val companionObjectName = structName + "." + companionObject.name companionObjectCodegen!!.generate() - - for ((key, value) in companionObjectCodegen!!.methods) { - val methodName = key.removePrefix(companionObjectName + ".") - companionMethods.put(structName + "." + methodName, value) - } - companionFields.addAll(companionObjectCodegen!!.fields) - for (field in companionObjectCodegen!!.fields) { - companionFieldsSource.put(field.label, companionObjectCodegen!!) - } - companionFieldsIndex.putAll(companionObjectCodegen!!.fieldsIndex) } } diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt index df491d7dba6..06ffff3852a 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt @@ -37,6 +37,7 @@ class FunctionCodegen(state: TranslationState, returnType = LLVMInstanceOfStandardType("instance", descriptor.returnType!!) if (returnType!!.type is LLVMReferenceType) { (returnType!!.type as LLVMReferenceType).location.addAll(descriptor.returnType!!.getSubtypesPredicate().toString().split(".").dropLast(1)) + returnType!!.pointer = 2 } external = isExternal() name = "${function.fqName}${if (args.size > 0 && !external) "_${args.joinToString(separator = "_", transform = { it.type.mangle() })}" else ""}" diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt index 3b6cd8a6336..9f91a5bb95a 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt @@ -23,10 +23,6 @@ abstract class StructCodegen(val state: TranslationState, val fields = ArrayList() val fieldsIndex = HashMap() val nestedClasses = HashMap() - val companionMethods = HashMap() - val companionFields = ArrayList() - val companionFieldsIndex = HashMap() - val companionFieldsSource = HashMap() val enumFields = HashMap() val constructorFields = ArrayList() diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMType.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMType.kt index c288941ec56..af7f859bb38 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMType.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMType.kt @@ -3,7 +3,6 @@ package org.kotlinnative.translator.llvm.types import org.kotlinnative.translator.exceptions.UnimplementedException import org.kotlinnative.translator.llvm.LLVMExpression import org.kotlinnative.translator.llvm.LLVMSingleValue -import org.kotlinnative.translator.llvm.LLVMVariable abstract class LLVMType() : Cloneable { diff --git a/translator/src/test/kotlin/tests/input/enum_complex.txt b/translator/src/test/kotlin/tests/input/enum_complex.txt new file mode 100644 index 00000000000..4eea6541a24 --- /dev/null +++ b/translator/src/test/kotlin/tests/input/enum_complex.txt @@ -0,0 +1 @@ +enum_complex_test1() == 0 diff --git a/translator/src/test/kotlin/tests/kotlin/companion_object_1.kt b/translator/src/test/kotlin/tests/kotlin/companion_object_1.kt index 8e59c06d16a..e5f449ac530 100644 --- a/translator/src/test/kotlin/tests/kotlin/companion_object_1.kt +++ b/translator/src/test/kotlin/tests/kotlin/companion_object_1.kt @@ -1,5 +1,5 @@ class companion_object_1 { - companion object Factory { + companion object { val fieldCompanion: Int = 5790 fun create(): Int { diff --git a/translator/src/test/kotlin/tests/kotlin/companion_object_2.kt b/translator/src/test/kotlin/tests/kotlin/companion_object_2.kt index 752db07bb56..8e41a27e35f 100644 --- a/translator/src/test/kotlin/tests/kotlin/companion_object_2.kt +++ b/translator/src/test/kotlin/tests/kotlin/companion_object_2.kt @@ -1,5 +1,5 @@ class companion_object_2 { - companion object Factory { + companion object { var fieldCompanion: Int = 5790 fun create(): Int { diff --git a/translator/src/test/kotlin/tests/kotlin/enum_complex.kt b/translator/src/test/kotlin/tests/kotlin/enum_complex.kt new file mode 100644 index 00000000000..c75d4eaa13e --- /dev/null +++ b/translator/src/test/kotlin/tests/kotlin/enum_complex.kt @@ -0,0 +1,20 @@ + +class Holder() { + + enum class nested(val id: Int) { + FIRST(0), + SECOND(1), + THIRD(3); + + companion object { + fun functor(ord: Int): Int { + return nested.FIRST.id + } + } + } +} + +fun enum_complex_test1(): Int { + val h = Holder() + return 0 +}