From a8b2129bb96d9f4df0d81ced8d7ca3611dc1ef34 Mon Sep 17 00:00:00 2001 From: Alexey Stepanov Date: Wed, 10 Aug 2016 11:51:58 +0300 Subject: [PATCH] translator: fix bit operators with different arguments --- .../kotlinnative/translator/BlockCodegen.kt | 31 +++++++++++++++++-- .../translator/llvm/types/LLVMIntType.kt | 10 ++++++ .../translator/llvm/types/LLVMLongType.kt | 10 ++++++ .../translator/llvm/types/LLVMType.kt | 2 ++ .../different_type_binary_operator_1.txt | 3 ++ .../different_type_binary_operator_1.kt | 11 +++++++ 6 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 translator/src/test/kotlin/tests/input/different_type_binary_operator_1.txt create mode 100644 translator/src/test/kotlin/tests/kotlin/different_type_binary_operator_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 0575d771cb7..6ab550beaa7 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt @@ -594,9 +594,34 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va "or" -> firstNativeOp.type!!.operatorOr(firstNativeOp, secondNativeOp) "xor" -> firstNativeOp.type!!.operatorXor(firstNativeOp, secondNativeOp) "and" -> firstNativeOp.type!!.operatorAnd(firstNativeOp, secondNativeOp) - "shl" -> firstNativeOp.type!!.operatorShl(firstNativeOp, secondNativeOp) - "shr" -> firstNativeOp.type!!.operatorShr(firstNativeOp, secondNativeOp) - "ushr" -> firstNativeOp.type!!.operatorUshr(firstNativeOp, secondNativeOp) + "shl" -> { + var secondNativeOpWithRequiredType = secondNativeOp + if (firstNativeOp.type != secondNativeOp.type) { + val convertedExpression = firstNativeOp.type!!.convertFrom(secondNativeOp) + secondNativeOpWithRequiredType = codeBuilder.getNewVariable(convertedExpression.variableType) + codeBuilder.addAssignment(secondNativeOpWithRequiredType, convertedExpression) + } + firstNativeOp.type!!.operatorShl(firstNativeOp, secondNativeOpWithRequiredType) + } + "shr" -> { + var secondNativeOpWithRequiredType = secondNativeOp + if (firstNativeOp.type != secondNativeOp.type) { + val convertedExpression = firstNativeOp.type!!.convertFrom(secondNativeOp) + secondNativeOpWithRequiredType = codeBuilder.getNewVariable(convertedExpression.variableType) + codeBuilder.addAssignment(secondNativeOpWithRequiredType, convertedExpression) + } + firstNativeOp.type!!.operatorShr(firstNativeOp, secondNativeOpWithRequiredType) + } + "ushr" -> { + var secondNativeOpWithRequiredType = secondNativeOp + if (firstNativeOp.type != secondNativeOp.type) { + val convertedExpression = firstNativeOp.type!!.convertFrom(secondNativeOp) + secondNativeOpWithRequiredType = codeBuilder.getNewVariable(convertedExpression.variableType) + codeBuilder.addAssignment(secondNativeOpWithRequiredType, convertedExpression) + } + + firstNativeOp.type!!.operatorUshr(firstNativeOp, secondNativeOpWithRequiredType) + } "+=" -> { val llvmExpression = firstNativeOp.type!!.operatorPlus(firstNativeOp, secondNativeOp) val resultOp = codeBuilder.getNewVariable(llvmExpression.variableType) 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 a0be2f1a0be..6370743a6a7 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 @@ -1,7 +1,9 @@ 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 class LLVMIntType() : LLVMType() { @@ -60,6 +62,14 @@ class LLVMIntType() : LLVMType() { override fun operatorNeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = LLVMExpression(LLVMBooleanType(), "icmp ne i32 $firstOp, $secondOp") + override fun convertFrom(source: LLVMSingleValue): LLVMExpression = when (source.type!!) { + is LLVMBooleanType, + is LLVMByteType, + is LLVMCharType, + is LLVMShortType -> LLVMExpression(LLVMBooleanType(), " sext ${source.type} $source to i32") + else -> throw UnimplementedException() + } + override fun mangle() = "Int" override val align = 4 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 7fc150b540e..fe9797152ad 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 @@ -1,5 +1,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 @@ -55,6 +56,15 @@ class LLVMLongType() : LLVMType() { override fun operatorNeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = LLVMExpression(LLVMBooleanType(), "icmp ne i64 $firstOp, $secondOp") + override fun convertFrom(source: LLVMSingleValue): LLVMExpression = when (source.type!!) { + is LLVMBooleanType, + is LLVMByteType, + is LLVMCharType, + is LLVMShortType, + is LLVMIntType -> LLVMExpression(LLVMBooleanType(), " sext ${source.type} $source to i64") + else -> throw UnimplementedException() + } + override val align = 4 override var size: Int = 8 override val defaultValue = "0" 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 85575663bce..95bc4eaf77d 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,6 +3,7 @@ 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 { @@ -27,6 +28,7 @@ abstract class LLVMType() : Cloneable { fun makeClone() = clone() + open fun convertFrom(source: LLVMSingleValue): LLVMExpression = throw UnimplementedException() abstract fun mangle(): String abstract val align: Int diff --git a/translator/src/test/kotlin/tests/input/different_type_binary_operator_1.txt b/translator/src/test/kotlin/tests/input/different_type_binary_operator_1.txt new file mode 100644 index 00000000000..2e6342034ce --- /dev/null +++ b/translator/src/test/kotlin/tests/input/different_type_binary_operator_1.txt @@ -0,0 +1,3 @@ +different_type_binary_operator_1_shl_Int_Long(10, 5) == 5120 +different_type_binary_operator_1_shr_Int_Long(5, 5000) == 156 +different_type_binary_operator_1_ushr_Int_Long(5, 5000) == 156 diff --git a/translator/src/test/kotlin/tests/kotlin/different_type_binary_operator_1.kt b/translator/src/test/kotlin/tests/kotlin/different_type_binary_operator_1.kt new file mode 100644 index 00000000000..d7379034506 --- /dev/null +++ b/translator/src/test/kotlin/tests/kotlin/different_type_binary_operator_1.kt @@ -0,0 +1,11 @@ +fun different_type_binary_operator_1_shr(x: Int, y: Long): Long { + return y shr x +} + +fun different_type_binary_operator_1_shl(x: Int, y: Long): Long { + return y shl x +} + +fun different_type_binary_operator_1_ushr(x: Int, y: Long): Long { + return y ushr x +} \ No newline at end of file