From 74a22ed4f9d0f4143aa146dd9ff8ca682509368b Mon Sep 17 00:00:00 2001 From: e5l Date: Thu, 21 Jul 2016 17:22:38 +0300 Subject: [PATCH] translator: reference reassignment, elvis operator, tests --- .../kotlinnative/translator/BlockCodegen.kt | 75 +++++++++---------- .../translator/llvm/LLVMBuilder.kt | 5 ++ .../src/test/kotlin/tests/input/elvis_1.txt | 2 + .../src/test/kotlin/tests/kotlin/elvis_1.kt | 16 ++++ 4 files changed, 59 insertions(+), 39 deletions(-) create mode 100644 translator/src/test/kotlin/tests/input/elvis_1.txt create mode 100644 translator/src/test/kotlin/tests/kotlin/elvis_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 b9cda9830d6..a93441c12b0 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt @@ -94,8 +94,11 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM val receiverName = expr.receiverExpression.text val selectorExpr = expr.selectorExpression!! - val receiver = variableManager.getLLVMvalue(receiverName) + var receiver = variableManager.getLLVMvalue(receiverName) if (receiver != null) { + if (receiver.pointer == 2) { + receiver = codeBuilder.loadAndGetVariable(receiver) + } return evaluateMemberMethodOrField(receiver, selectorExpr.text, scopeDepth, expr.lastChild) } @@ -110,7 +113,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM else -> throw UnsupportedOperationException() } - private fun evaluatenameReferenceExpression(expr: KtNameReferenceExpression, scopeDepth: Int, classScope: ClassCodegen? = null): LLVMSingleValue? { + private fun evaluateNameReferenceExpression(expr: KtNameReferenceExpression, scopeDepth: Int, classScope: ClassCodegen? = null): LLVMSingleValue? { val fieldName = state.bindingContext.get(BindingContext.REFERENCE_TARGET, expr)!!.name.toString() val field = classScope!!.companionFieldsIndex[fieldName] @@ -175,8 +178,8 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM 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, scopeDepth + 1, classScope) - else variableManager.getLLVMvalue(expr.firstChild.text) + else -> if ((expr is KtNameReferenceExpression) && (classScope != null)) evaluateNameReferenceExpression(expr, scopeDepth + 1, classScope) + else variableManager.getLLVMvalue(expr.firstChild.text) } private fun evaluateCallExpression(expr: KtCallExpression, scopeDepth: Int, classScope: ClassCodegen? = null): LLVMSingleValue? { @@ -275,12 +278,19 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM }).toList() private fun evaluateConstructorCallExpression(function: LLVMVariable, names: List): LLVMSingleValue? { + val store = codeBuilder.getNewVariable(function.type) + codeBuilder.allocStaticVar(store) + store.pointer++ + val result = codeBuilder.getNewVariable(function.type) + result.pointer++ codeBuilder.allocStaticVar(result) - result.pointer += 1 + result.pointer++ + + codeBuilder.storeVariable(result, store) val args = ArrayList() - args.add(result) + args.add(store) args.addAll(names) codeBuilder.addLLVMCode(LLVMCall( @@ -316,46 +326,38 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM return executeBinaryExpression(operator, expr.operationReference, left, right, scopeDepth) } - private fun executeBinaryExpression(operator: IElementType, referenceName: KtSimpleNameExpression?, left: LLVMSingleValue, right: LLVMSingleValue, scopeDepth: Int): LLVMVariable { - val result = addPrimitiveBinaryOperation(operator, referenceName, left, right) - - if (left.type is LLVMReferenceType && left.pointer > 0 && right.pointer > 0) { - variableManager.addVariable((left as LLVMVariable).kotlinName!!, result, scopeDepth) - } - - return result - } + private fun executeBinaryExpression(operator: IElementType, referenceName: KtSimpleNameExpression?, left: LLVMSingleValue, right: LLVMSingleValue, scopeDepth: Int) + = addPrimitiveBinaryOperation(operator, referenceName, left, right) private fun evaluateElvisOperator(expr: KtBinaryExpression, scopeDepth: Int): LLVMVariable { val left = evaluateExpression(expr.firstChild, scopeDepth) ?: throw UnsupportedOperationException("Wrong binary exception") - val condition = left.type!!.operatorEq(left, LLVMVariable("", LLVMNullType())) + val lptr = codeBuilder.loadAndGetVariable(left as LLVMVariable) + + val condition = lptr.type.operatorEq(lptr, LLVMVariable("", LLVMNullType())) val conditionResult = codeBuilder.getNewVariable(condition.variableType) codeBuilder.addAssignment(conditionResult, condition) - val elvisResult = codeBuilder.getNewVariable(left.type!!, pointer = left.pointer) - codeBuilder.allocStackVar(elvisResult) - elvisResult.pointer++ - val thenLabel = codeBuilder.getNewLabel(prefix = "elvis") val elseLabel = codeBuilder.getNewLabel(prefix = "elvis") val endLabel = codeBuilder.getNewLabel(prefix = "elvis") - codeBuilder.addCondition(conditionResult, thenLabel, elseLabel) + codeBuilder.addCondition(conditionResult, elseLabel, thenLabel) codeBuilder.markWithLabel(thenLabel) - codeBuilder.storeVariable(elvisResult, left) codeBuilder.addUnconditionalJump(endLabel) codeBuilder.markWithLabel(elseLabel) - val right = evaluateExpression(expr.lastChild, scopeDepth + 1) + var right = evaluateExpression(expr.lastChild, scopeDepth + 1) if (right != null) { - codeBuilder.storeVariable(elvisResult, right) + right = codeBuilder.loadAndGetVariable(right as LLVMVariable) + codeBuilder.storeVariable(left, right) } codeBuilder.addUnconditionalJump(endLabel) + codeBuilder.markWithLabel(endLabel) - return elvisResult + return left } private fun addPrimitiveBinaryOperation(operator: IElementType, referenceName: KtSimpleNameExpression?, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMVariable { @@ -371,7 +373,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM KtTokens.GTEQ -> firstOp.type!!.operatorGeq(firstNativeOp, secondNativeOp) KtTokens.EQEQ -> if (firstOp.type is LLVMReferenceType) - firstOp.type!!.operatorEq(firstOp, secondOp) + firstOp.type!!.operatorEq(firstNativeOp, secondOp) else firstOp.type!!.operatorEq(firstNativeOp, secondNativeOp) KtTokens.EXCLEQ -> firstOp.type!!.operatorNeq(firstNativeOp, secondNativeOp) @@ -385,10 +387,6 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM return result } - if (firstOp.type is LLVMReferenceType && firstOp.pointer > 0 && secondOp.pointer > 0) { - return secondOp as LLVMVariable - } - val result = firstOp as LLVMVariable codeBuilder.storeVariable(result, secondNativeOp) return result @@ -564,10 +562,6 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM return null } - private fun copyVariable(from: LLVMVariable, to: LLVMVariable) = when (from.type) { - is LLVMStringType -> codeBuilder.storeString(to, from, 0) - else -> codeBuilder.copyVariableValue(to, from) - } private fun evaluateValExpression(element: KtProperty, scopeDepth: Int): LLVMVariable? { val variable = state.bindingContext.get(BindingContext.VARIABLE, element)!! @@ -584,7 +578,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM allocVar.kotlinName = identifier variableManager.addVariable(identifier, allocVar, scopeDepth) - copyVariable(assignExpression, allocVar) + codeBuilder.copyVariable(assignExpression, allocVar) } else { assignExpression.kotlinName = identifier variableManager.addVariable(identifier, assignExpression, scopeDepth) @@ -601,9 +595,8 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM reference.pointer += 1 codeBuilder.storeNull(reference) - val result = codeBuilder.loadAndGetVariable(reference) - variableManager.addVariable(identifier, result, scopeDepth) + variableManager.addVariable(identifier, reference, scopeDepth) return null } @@ -620,12 +613,16 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM private fun evaluateReturnInstruction(element: PsiElement, scopeDepth: Int): LLVMVariable? { val next = element.getNextSiblingIgnoringWhitespaceAndComments() - val retVar = evaluateExpression(next, scopeDepth) + var retVar = evaluateExpression(next, scopeDepth) val type = retVar?.type ?: LLVMVoidType() when (type) { is LLVMReferenceType -> { - codeBuilder.storeVariable(returnType!!, retVar!!) + if (retVar!!.pointer == 2) { + retVar = codeBuilder.loadAndGetVariable(retVar as LLVMVariable) + } + + codeBuilder.storeVariable(returnType!!, retVar) codeBuilder.addAnyReturn(LLVMVoidType()) } is LLVMVoidType -> { 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 ed733d2cfe7..b8b1ef05957 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt @@ -147,6 +147,11 @@ class LLVMBuilder(val arm: Boolean) { localCode.appendln("store ${target.type} $from, ${target.getType()} $target, align ${from.type.align}") } + fun copyVariable(from: LLVMVariable, to: LLVMVariable) = when (from.type) { + is LLVMStringType -> storeString(to, from, 0) + else -> copyVariableValue(to, from) + } + fun loadArgument(llvmVariable: LLVMVariable, store: Boolean = true): LLVMVariable { val allocVar = LLVMVariable("${llvmVariable.label}.addr", llvmVariable.type, llvmVariable.kotlinName, LLVMRegisterScope(), pointer = llvmVariable.pointer + 1) addVariableByRef(allocVar, llvmVariable, store) diff --git a/translator/src/test/kotlin/tests/input/elvis_1.txt b/translator/src/test/kotlin/tests/input/elvis_1.txt new file mode 100644 index 00000000000..28283e311f7 --- /dev/null +++ b/translator/src/test/kotlin/tests/input/elvis_1.txt @@ -0,0 +1,2 @@ +elvis_test_1(0) == 0 +elvis_test_1(2) == 1 diff --git a/translator/src/test/kotlin/tests/kotlin/elvis_1.kt b/translator/src/test/kotlin/tests/kotlin/elvis_1.kt new file mode 100644 index 00000000000..fd04b91fee6 --- /dev/null +++ b/translator/src/test/kotlin/tests/kotlin/elvis_1.kt @@ -0,0 +1,16 @@ + +class MyClass(val i: Int) + +fun elvis_test_1(x: Int): Int { + var z: MyClass? = null + + if (x > 1) { + z = MyClass(1) + } else { + } + + val y = z ?: return 0 + return 1 +} + +