From a4e1416ad0d27b9f7fb3538ae5a85e10819be1e5 Mon Sep 17 00:00:00 2001 From: Alexey Stepanov Date: Tue, 23 Aug 2016 09:46:33 +0300 Subject: [PATCH] translator: rewrite assignment for primitive nullable types --- .../kotlinnative/translator/BlockCodegen.kt | 21 +++++++--- .../translator/llvm/LLVMBuilder.kt | 5 ++- .../translator/llvm/generators.kt | 42 ++++++++++--------- 3 files changed, 41 insertions(+), 27 deletions(-) diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt index 5d0c92195c8..abf51a4a5cd 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt @@ -849,8 +849,16 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va return result } + val result = firstOp as LLVMVariable - val sourceArgument = if (result.pointer == secondOp.pointer + 1) secondOp else secondNativeOp + val sourceArgument: LLVMSingleValue + if (secondOp.type!!.isPrimitive() && (secondOp.pointer == 0) && (firstOp.pointer == 2)) { + sourceArgument = codeBuilder.getNewVariable(secondOp.type!!, 1) + codeBuilder.allocStaticVar(sourceArgument, true) + codeBuilder.storeVariable(sourceArgument, secondOp) + } else { + sourceArgument = if (result.pointer == secondOp.pointer + 1) secondOp else secondNativeOp + } codeBuilder.storeVariable(result, sourceArgument) codeBuilder.addComment("end variable assignment") return result @@ -1036,26 +1044,27 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va } private fun evaluateValExpression(element: KtProperty, scopeDepth: Int): LLVMVariable? { + val variable = state.bindingContext.get(BindingContext.VARIABLE, element)!! val identifier = variable.name.toString() val assignExpression = evaluateExpression(element.delegateExpressionOrInitializer, scopeDepth) - val expectedExpressionType = LLVMMapStandardType(variable.type, state) + val expectedExpressionType = LLVMInstanceOfStandardType("", variable.type, state = state) val assignExpressionType = assignExpression?.type - val isPrimitive = LLVMMapStandardType(variable.type, state) !is LLVMReferred + val primitivePointer = LLVMMapStandardType(variable.type, state) !is LLVMReferred when (assignExpression) { null, is LLVMVariable -> { - val allocVar = variableManager.receiveVariable(identifier, expectedExpressionType, LLVMRegisterScope(), pointer = - if (isPrimitive) 0 else 1) + val allocVar = variableManager.receiveVariable(identifier, expectedExpressionType.type, LLVMRegisterScope(), pointer = + expectedExpressionType.pointer) codeBuilder.allocStackVar(allocVar) allocVar.pointer++ allocVar.kotlinName = identifier variableManager.addVariable(identifier, allocVar, scopeDepth) if (assignExpression != null) { - if ((isPrimitive) && (assignExpression.type is LLVMReferenceType)) { + if ((primitivePointer) && (assignExpression.type is LLVMReferenceType)) { throw UnexpectedException(element.text) } addPrimitiveBinaryOperation(KtTokens.EQ, null, allocVar, assignExpression) 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 58113dcfc30..8edad5b59b2 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt @@ -76,8 +76,9 @@ class LLVMBuilder(val arm: Boolean = false) { var result = value while (argument.pointer < result.pointer) { - result = getNewVariable(argument.type, pointer = result.pointer - 1) - loadVariable(result, value as LLVMVariable) + val currentArgument = getNewVariable(result.type!!, pointer = result.pointer - 1) + loadVariable(currentArgument, result as LLVMVariable) + result = currentArgument } when (value.type) { 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 9440ff9e870..06fe826f0a9 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/generators.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/generators.kt @@ -15,26 +15,30 @@ fun LLVMFunctionDescriptor(name: String, argTypes: List?, returnTy "${s.getType()} ${if (s.type is LLVMReferenceType && !(s.type as LLVMReferenceType).byRef) "byval" else ""} %${s.label}" }?.joinToString()}) #0" -fun LLVMInstanceOfStandardType(name: String, type: KotlinType, scope: LLVMScope = LLVMRegisterScope(), state: TranslationState): LLVMVariable = when { - type.isFunctionTypeOrSubtype -> LLVMVariable(name, LLVMFunctionType(type, state), name, scope, pointer = 1) - type.toString() == "Boolean" -> LLVMVariable(name, LLVMBooleanType(), name, scope) - type.toString() == "Byte" -> LLVMVariable(name, LLVMByteType(), name, scope) - type.toString() == "Char" -> LLVMVariable(name, LLVMCharType(), name, scope) - type.toString() == "Short" -> LLVMVariable(name, LLVMShortType(), name, scope) - type.toString() == "Int" -> LLVMVariable(name, LLVMIntType(), name, scope) - type.toString() == "Long" -> LLVMVariable(name, LLVMLongType(), name, scope) - type.toString() == "Float" -> LLVMVariable(name, LLVMFloatType(), name, scope) - type.toString() == "Double" -> LLVMVariable(name, LLVMDoubleType(), name, scope) - type.toString() == "String" -> LLVMVariable(name, LLVMStringType(0), name, scope) - type.nameIfStandardType.toString() == "Nothing" -> LLVMVariable(name, LLVMNullType(), name, scope) - type.isUnit() -> LLVMVariable("", LLVMVoidType(), name, scope) - type.isMarkedNullable -> LLVMVariable(name, LLVMReferenceType(type.toString().dropLast(1), prefix = "class"), name, scope, pointer = 1) - else -> { - val refType = state.classes[type.toString()]?.type ?: LLVMReferenceType(type.toString(), align = state.pointerAlign, prefix = "class") +fun LLVMInstanceOfStandardType(name: String, type: KotlinType, scope: LLVMScope = LLVMRegisterScope(), state: TranslationState): LLVMVariable { + val typeName = type.toString().dropLastWhile { it == '?' } + val pointerMark = if (type.toString().last() == '?') 1 else 0 + return when { + type.isFunctionTypeOrSubtype -> LLVMVariable(name, LLVMFunctionType(type, state), name, scope, pointer = 1) + typeName == "Boolean" -> LLVMVariable(name, LLVMBooleanType(), name, scope, pointerMark) + typeName == "Byte" -> LLVMVariable(name, LLVMByteType(), name, scope, pointerMark) + typeName == "Char" -> LLVMVariable(name, LLVMCharType(), name, scope, pointerMark) + typeName == "Short" -> LLVMVariable(name, LLVMShortType(), name, scope, pointerMark) + typeName == "Int" -> LLVMVariable(name, LLVMIntType(), name, scope, pointerMark) + typeName == "Long" -> LLVMVariable(name, LLVMLongType(), name, scope, pointerMark) + typeName == "Float" -> LLVMVariable(name, LLVMFloatType(), name, scope, pointerMark) + typeName == "Double" -> LLVMVariable(name, LLVMDoubleType(), name, scope, pointerMark) + typeName == "String" -> LLVMVariable(name, LLVMStringType(0), name, scope, pointerMark) + type.nameIfStandardType.toString() == "Nothing" -> LLVMVariable(name, LLVMNullType(), name, scope) + type.isUnit() -> LLVMVariable("", LLVMVoidType(), name, scope) + type.isMarkedNullable -> LLVMVariable(name, LLVMReferenceType(typeName, prefix = "class"), name, scope, pointer = pointerMark) + else -> { + val refType = state.classes[type.toString()]?.type ?: LLVMReferenceType(typeName, align = state.pointerAlign, prefix = "class") - val result = LLVMVariable(name, refType, name, scope, pointer = 1) - refType.location.addAll(type.getSubtypesPredicate().toString().split(".").dropLast(1)) - result + val result = LLVMVariable(name, refType, name, scope, pointer = 1) + refType.location.addAll(type.getSubtypesPredicate().toString().split(".").dropLast(1)) + result + } } }