From dcd08d7cc564447ea770ea32c89b3aa9ce83c8f4 Mon Sep 17 00:00:00 2001 From: Alexey Stepanov Date: Tue, 30 Aug 2016 14:27:29 +0300 Subject: [PATCH] translator: escape calculating reference type location --- .../kotlinnative/translator/BlockCodegen.kt | 49 +++++++++---------- .../kotlinnative/translator/ClassCodegen.kt | 4 -- .../kotlinnative/translator/ObjectCodegen.kt | 6 +-- .../translator/llvm/generators.kt | 16 +++--- .../llvm/types/LLVMReferenceType.kt | 2 - 5 files changed, 31 insertions(+), 46 deletions(-) diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt index eb0afefcb4b..8d48e671172 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt @@ -4,7 +4,6 @@ import com.intellij.psi.PsiElement import com.intellij.psi.PsiWhiteSpace import com.intellij.psi.impl.source.tree.LeafPsiElement import com.intellij.psi.tree.IElementType -import org.jetbrains.kotlin.cfg.pseudocode.getSubtypesPredicate import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* @@ -195,7 +194,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va is KtPostfixExpression, is KtBinaryExpression -> evaluateExpression(receiverExpr, scopeDepth) as LLVMVariable is KtDotQualifiedExpression -> { - val codegen = resolveCodegenByName(receiverName, receiverName.split(".")) + val codegen = resolveCodegenByName(receiverName) if (codegen != null) null else evaluateExpression(receiverExpr, scopeDepth) as LLVMVariable } is KtNameReferenceExpression -> { @@ -307,22 +306,32 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va } private fun resolveClassOrObjectLocation(type: LLVMReferenceType): StructCodegen? { - if (type.location.size == 0) { - return state.classes[type.type] ?: state.objects[type.type] - } + val typeLocations = type.type.split('.') + val currentLocation = StringBuilder() + var codegen: ClassCodegen? = null + var currentIndex = 0 - var codegen = state.classes[type.location[0]] - var i = 1 - while (i < type.location.size) { - codegen = codegen?.nestedClasses?.get(type.location[i]) - i++ + do { + currentLocation.append((if (currentIndex > 0) "." else "") + typeLocations[currentIndex]) + if (state.classes.containsKey(currentLocation.toString())) { + codegen = state.classes[currentLocation.toString()] + } else if (state.objects.containsKey(currentLocation.toString())) { + return state.objects[currentLocation.toString()] + } + currentIndex++ + } while ((currentIndex < typeLocations.size) && (codegen == null)) + + while (currentIndex < typeLocations.size - 1) { + currentLocation.append('.' + typeLocations[currentIndex]) + currentIndex++ + codegen = codegen?.nestedClasses?.get(currentLocation.toString()) } if (codegen?.companionObjectCodegen != null && type.type == codegen?.companionObjectCodegen?.structName) { return codegen?.companionObjectCodegen!! } - return codegen?.nestedClasses?.get(type.type) + return if (codegen?.structName == type.type) codegen else codegen?.nestedClasses?.get(type.type) } fun evaluateArrayAccessExpression(expr: KtArrayAccessExpression, scope: Int): LLVMSingleValue? { @@ -407,26 +416,14 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va ?: 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 - val name = type?.constructor?.declarationDescriptor?.fqNameSafe?.asString() ?: throw UnexpectedException(expr.text) - return resolveCodegenByName(name, location) - + return resolveCodegenByName(name) } - private fun resolveCodegenByName(name: String, location: List): StructCodegen? { - val classType = LLVMReferenceType(name, prefix = "class") - var locationPrefix = "" - for (currentLocation in location.dropLast(1)) { - locationPrefix += (if (locationPrefix.length > 0) "." else "") + currentLocation - classType.location.add(locationPrefix) - } + private fun resolveCodegenByName(name: String): StructCodegen? = + resolveClassOrObjectLocation(LLVMReferenceType(name, prefix = "class")) - return resolveClassOrObjectLocation(classType) - } private fun evaluateCallExpression(expr: KtCallExpression, scopeDepth: Int, classScope: StructCodegen? = null, caller: LLVMVariable? = null): LLVMSingleValue? { var names = parseArgList(expr, scopeDepth) diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt index 4924fe66b01..cba10261acb 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt @@ -30,10 +30,6 @@ class ClassCodegen(state: TranslationState, init { type = LLVMReferenceType(structName, "class", align = TranslationState.pointerAlign, size = TranslationState.pointerSize, byRef = true) - if (parentCodegen != null) { - type.location.addAll(parentCodegen.type.location) - type.location.add(parentCodegen.structName) - } descriptor = state.bindingContext.get(BindingContext.CLASS, clazz) ?: throw TranslationException("Can't receive descriptor of class " + clazz.name) diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/ObjectCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/ObjectCodegen.kt index 4501dddbacc..627a1148471 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/ObjectCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/ObjectCodegen.kt @@ -20,11 +20,7 @@ class ObjectCodegen(state: TranslationState, init { type = LLVMReferenceType(structName, "class", align = TranslationState.pointerAlign, size = TranslationState.pointerSize, byRef = true) - if (parentCodegen != null) { - type.location.addAll(parentCodegen.type.location) - type.location.add(parentCodegen.structName) - } - primaryConstructorIndex = LLVMType.mangleFunctionArguments(emptyList()) + primaryConstructorIndex = LLVMType.mangleFunctionArguments(emptyList()) constructorFields.put(primaryConstructorIndex!!, arrayListOf()) } diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/generators.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/generators.kt index 572d48df4a1..d83bfef36fe 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/generators.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/generators.kt @@ -39,27 +39,25 @@ fun LLVMInstanceOfStandardType(name: String, type: KotlinType, scope: LLVMScope val refName = declarationDescriptor.fqNameSafe.asString() val refType = state.classes[type.toString()]?.type ?: LLVMReferenceType(refName, align = TranslationState.pointerAlign, prefix = "class") - val result = LLVMVariable(name, refType, name, scope, pointer = 1) - var currentPrefix = "" - for (currentLocation in type.getSubtypesPredicate().toString().split(".").dropLast(1)) { - currentPrefix += (if (currentPrefix.length > 0) "." else "") + currentLocation - refType.location.add(currentPrefix) - } - result + LLVMVariable(name, refType, name, scope, pointer = 1) } } } -fun LLVMMapStandardType(type: KotlinType, state: TranslationState): LLVMType = +fun LLVMMapStandardType(type: KotlinType, state: TranslationState) = LLVMInstanceOfStandardType("type", type, LLVMRegisterScope(), state).type fun String.addBeforeIfNotEmpty(add: String): String = if (this.length > 0) add + this else this - fun String.addAfterIfNotEmpty(add: String): String = if (this.length > 0) this + add else this +fun String.indexOfOrLast(str: Char, startIndex: Int = 0): Int { + val pos = this.indexOf(str, startIndex) + return if (pos < 0) this.length else pos +} + fun FqName.convertToNativeName(): String = this.asString().replace(".", "") \ No newline at end of file diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMReferenceType.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMReferenceType.kt index 79ffa42c7fc..0417366f92d 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMReferenceType.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMReferenceType.kt @@ -18,8 +18,6 @@ class LLVMReferenceType(val type: String, override fun toString() = "%$typename" - val location = ArrayList() - override fun operatorEq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) = LLVMExpression(LLVMBooleanType(), "icmp eq ${firstOp.getType()} $firstOp, ${if (secondOp.type is LLVMNullType) "null" else "$secondOp"}")