From a05307724c1faf8f112d00d8416f8afb914fd7a9 Mon Sep 17 00:00:00 2001 From: Alexey Stepanov Date: Fri, 22 Jul 2016 15:20:27 +0300 Subject: [PATCH] translator: add prefix operators - increment, decrement --- .../kotlinnative/translator/BlockCodegen.kt | 39 +++++++++++++++++++ .../translator/ProjectTranslator.kt | 2 +- .../translator/llvm/types/LLVMIntType.kt | 11 ++++-- .../translator/llvm/types/LLVMLongType.kt | 6 +-- .../translator/llvm/types/LLVMType.kt | 2 + .../src/test/kotlin/tests/input/postfix_1.txt | 6 +++ .../src/test/kotlin/tests/kotlin/postfix_1.kt | 35 +++++++++++++++++ 7 files changed, 94 insertions(+), 7 deletions(-) create mode 100644 translator/src/test/kotlin/tests/input/postfix_1.txt create mode 100644 translator/src/test/kotlin/tests/kotlin/postfix_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 5f57df71ad4..9342d947e69 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt @@ -5,6 +5,7 @@ import com.intellij.psi.PsiWhiteSpace import com.intellij.psi.impl.source.tree.LeafPsiElement import com.intellij.psi.tree.IElementType import org.jetbrains.kotlin.KtNodeTypes +import org.jetbrains.kotlin.cfg.UnreachableCode import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getNextSiblingIgnoringWhitespaceAndComments @@ -54,6 +55,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM when (expr) { is KtBlockExpression -> expressionWalker(expr.firstChild, scopeDepth + 1) is KtProperty -> evaluateValExpression(expr, scopeDepth) + is KtPostfixExpression -> evaluatePostfixExpression(expr, scopeDepth) is KtBinaryExpression -> evaluateBinaryExpression(expr, scopeDepth) is KtCallExpression -> evaluateCallExpression(expr, scopeDepth) is KtDoWhileExpression -> evaluateDoWhileExpression(expr.firstChild, scopeDepth + 1) @@ -79,6 +81,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM private fun evaluateExpression(expr: PsiElement?, scopeDepth: Int): LLVMSingleValue? { return when (expr) { is KtBinaryExpression -> evaluateBinaryExpression(expr, scopeDepth) + is KtPostfixExpression -> evaluatePostfixExpression(expr, scopeDepth) is KtConstantExpression -> evaluateConstantExpression(expr) is KtCallExpression -> evaluateCallExpression(expr, scopeDepth) is KtWhenExpression -> evaluateWhenExpression(expr, scopeDepth) @@ -393,6 +396,42 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM return executeBinaryExpression(operator, expr.operationReference, left, right) } + private fun evaluatePostfixExpression(expr: KtPostfixExpression, scopeDepth: Int): LLVMSingleValue? { + val operator = expr.operationToken + + val left = evaluateExpression(expr.baseExpression, scopeDepth) ?: throw UnsupportedOperationException("Wrong binary exception") + + return executePostfixExpression(operator, expr.operationReference, left as LLVMVariable) + } + + private fun executePostfixExpression(operator: IElementType?, operationReference: KtSimpleNameExpression, left: LLVMVariable): LLVMSingleValue? + = addPrimitivePostfixOperation(operator, operationReference, left) + + private fun addPrimitivePostfixOperation(operator: IElementType?, operationReference: KtSimpleNameExpression, firstOp: LLVMVariable): LLVMSingleValue? { + val firstNativeOp = codeBuilder.receiveNativeValue(firstOp) + when (operator) { + KtTokens.PLUSPLUS, KtTokens.MINUSMINUS -> { + val oldValue = codeBuilder.getNewVariable(firstOp.type, firstOp.pointer) + codeBuilder.allocStackPointedVarAsValue(oldValue) + codeBuilder.copyVariable(firstOp, oldValue) + + val llvmExpression = when (operator) { + KtTokens.PLUSPLUS -> firstOp.type.operatorInc(firstNativeOp) + KtTokens.MINUSMINUS -> firstOp.type.operatorDec(firstNativeOp) + else -> throw IllegalAccessError() + } + + val resultOp = codeBuilder.getNewVariable(llvmExpression.variableType) + codeBuilder.addAssignment(resultOp, llvmExpression) + + codeBuilder.storeVariable(firstOp, resultOp) + return oldValue + } + else -> throw UnsupportedOperationException() + } + } + + private fun executeBinaryExpression(operator: IElementType, referenceName: KtSimpleNameExpression?, left: LLVMSingleValue, right: LLVMSingleValue) = addPrimitiveBinaryOperation(operator, referenceName, left, right) diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/ProjectTranslator.kt b/translator/src/main/kotlin/org/kotlinnative/translator/ProjectTranslator.kt index 52cb398aa5f..3ab8339d4e3 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/ProjectTranslator.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/ProjectTranslator.kt @@ -40,7 +40,7 @@ class ProjectTranslator(val files: List, val state: TranslationState) { } private fun generateProjectBody() { - with (state) { + with(state) { properties.values.map { it.generate() } objects.values.map { it.generate() } classes.values.map { it.generate() } diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMIntType.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMIntType.kt index 48bedb916d2..a0be2f1a0be 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMIntType.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMIntType.kt @@ -36,12 +36,17 @@ class LLVMIntType() : LLVMType() { override fun operatorPlus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = LLVMExpression(LLVMIntType(), "add nsw i32 $firstOp, $secondOp") + override fun operatorInc(firstOp: LLVMSingleValue): LLVMExpression = + LLVMExpression(LLVMIntType(), "add nsw i32 $firstOp, 1") + + override fun operatorDec(firstOp: LLVMSingleValue): LLVMExpression = + LLVMExpression(LLVMIntType(), "sub nsw i32 $firstOp, 1") + override fun operatorLt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = LLVMExpression(LLVMBooleanType(), "icmp slt i32 $firstOp, $secondOp") - override fun operatorGt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression { - return LLVMExpression(LLVMBooleanType(), "icmp sgt i32 $firstOp, $secondOp") - } + override fun operatorGt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = + LLVMExpression(LLVMBooleanType(), "icmp sgt i32 $firstOp, $secondOp") override fun operatorLeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = LLVMExpression(LLVMBooleanType(), "icmp sle i32 $firstOp, $secondOp") diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMLongType.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMLongType.kt index 1e39b2416b1..7fc150b540e 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMLongType.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMLongType.kt @@ -39,9 +39,9 @@ class LLVMLongType() : LLVMType() { override fun operatorLt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = LLVMExpression(LLVMBooleanType(), "icmp slt i64 $firstOp, $secondOp") - override fun operatorGt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression { - return LLVMExpression(LLVMBooleanType(), "icmp sgt i64 $firstOp, $secondOp") - } + override fun operatorGt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = + LLVMExpression(LLVMBooleanType(), "icmp sgt i64 $firstOp, $secondOp") + override fun operatorLeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = LLVMExpression(LLVMBooleanType(), "icmp sle i64 $firstOp, $secondOp") 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 1ada8daff3e..85575663bce 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 @@ -21,6 +21,8 @@ abstract class LLVMType() : Cloneable { open fun operatorShl(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException() open fun operatorShr(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException() open fun operatorUshr(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException() + open fun operatorInc(firstOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException() + open fun operatorDec(firstOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException() open fun parseArg(inputArg: String) = inputArg fun makeClone() = clone() diff --git a/translator/src/test/kotlin/tests/input/postfix_1.txt b/translator/src/test/kotlin/tests/input/postfix_1.txt new file mode 100644 index 00000000000..eca52ca3003 --- /dev/null +++ b/translator/src/test/kotlin/tests/input/postfix_1.txt @@ -0,0 +1,6 @@ +postfix_1_plus_before_Int(20) == 20 +postfix_1_plus_after_Int(20) == 21 +postfix_1_plus_inside_Int(20) == 21 +postfix_1_minus_before_Int(20) == 20 +postfix_1_minus_after_Int(20) == 19 +postfix_1_minus_inside_Int(20) == 19 diff --git a/translator/src/test/kotlin/tests/kotlin/postfix_1.kt b/translator/src/test/kotlin/tests/kotlin/postfix_1.kt new file mode 100644 index 00000000000..593be691da8 --- /dev/null +++ b/translator/src/test/kotlin/tests/kotlin/postfix_1.kt @@ -0,0 +1,35 @@ +fun postfix_1_plus_before(x: Int): Int { + var xx = x + val z = xx++ + return z +} + +fun postfix_1_plus_after(x: Int): Int { + var xx = x + val z = xx++ + return xx +} + +fun postfix_1_plus_inside(x: Int): Int { + var xx = x + xx++ + return xx +} + +fun postfix_1_minus_before(x: Int): Int { + var xx = x + val z = xx-- + return z +} + +fun postfix_1_minus_after(x: Int): Int { + var xx = x + val z = xx-- + return xx +} + +fun postfix_1_minus_inside(x: Int): Int { + var xx = x + xx-- + return xx +} \ No newline at end of file