From b49c03de8bdaf797ed2fff2c4e6918d62ccb7a87 Mon Sep 17 00:00:00 2001 From: Alexey Stepanov Date: Fri, 22 Jul 2016 11:46:15 +0300 Subject: [PATCH] translator: add cast extensions, add float, long types, add support test order in tests, add Primitives in kotlib, fix extension function resolving --- translator/run_tests.sh | 4 +- .../translator/FunctionCodegen.kt | 2 +- .../translator/llvm/generators.kt | 9 ++- .../translator/llvm/types/LLVMFloatType.kt | 26 ++++++++ .../translator/llvm/types/LLVMLongType.kt | 64 +++++++++++++++++++ .../translator/llvm/types/LLVMType.kt | 2 + .../resources/kotlib/kotlin/Primitives.kt | 34 ++++++++++ .../resources/kotlib/linked/primitives_c.ll | 59 +++++++++++++++++ .../test/kotlin/tests/input/primitives_1.txt | 4 ++ .../test/kotlin/tests/kotlin/primitives_1.kt | 7 ++ 10 files changed, 205 insertions(+), 6 deletions(-) create mode 100644 translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMFloatType.kt create mode 100644 translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMLongType.kt create mode 100644 translator/src/main/resources/kotlib/kotlin/Primitives.kt create mode 100644 translator/src/main/resources/kotlib/linked/primitives_c.ll create mode 100644 translator/src/test/kotlin/tests/input/primitives_1.txt create mode 100644 translator/src/test/kotlin/tests/kotlin/primitives_1.kt diff --git a/translator/run_tests.sh b/translator/run_tests.sh index 8de2c1ebe87..e950eda7afd 100755 --- a/translator/run_tests.sh +++ b/translator/run_tests.sh @@ -7,7 +7,7 @@ fi DIRECTORY="src/test/kotlin/tests" MAIN="$DIRECTORY/linked/main.c" -for i in $( ls "$DIRECTORY/input"); do +for i in $( ls "$DIRECTORY/input" $1); do rm -f $DIRECTORY/linked/* TEST=`basename $i ".txt"` echo test: $TEST @@ -40,7 +40,7 @@ for i in $( ls "$DIRECTORY/input"); do java -jar build/libs/ast-kotlin-1.0-SNAPSHOT.jar $DIRECTORY/kotlin/$TEST.kt > $DIRECTORY/linked/$TEST.ll llvm-link-3.6 $DIRECTORY/linked/* > $DIRECTORY/linked/run.ll lli-3.6 $DIRECTORY/linked/run.ll - + exit done diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt index a2937975465..7da5879a173 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt @@ -97,7 +97,7 @@ class FunctionCodegen(override val state: TranslationState, val receiverType = receiverParameter.type val translatorType = LLVMMapStandardType(receiverType) - val extensionFunctionsOfThisType = state.extensionFunctions.getOrDefault(translatorType, HashMap()) + val extensionFunctionsOfThisType = state.extensionFunctions.getOrDefault(translatorType.toString(), HashMap()) extensionFunctionsOfThisType.put(name, this) state.extensionFunctions.put(translatorType.toString(), extensionFunctionsOfThisType) 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 1e1397ec8e7..b4e22e09719 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/generators.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/generators.kt @@ -14,11 +14,14 @@ fun LLVMFunctionDescriptor(name: String, argTypes: List?, returnTy fun LLVMInstanceOfStandardType(name: String, type: KotlinType, scope: LLVMScope = LLVMRegisterScope()): LLVMVariable = when { type.isFunctionTypeOrSubtype -> LLVMVariable(name, LLVMFunctionType(type), name, scope, pointer = 1) - type.toString() == "Int" -> LLVMVariable(name, LLVMIntType(), name, scope) - type.toString() == "Double" -> LLVMVariable(name, LLVMDoubleType(), name, scope) + 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() == "Boolean" -> LLVMVariable(name, LLVMBooleanType(), 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.isUnit() -> LLVMVariable("", LLVMVoidType(), name, scope) type.isMarkedNullable -> LLVMVariable(name, LLVMReferenceType(type.toString().dropLast(1)), name, scope, pointer = 1) else -> LLVMVariable(name, LLVMReferenceType(type.toString()), name, scope, pointer = 1) diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMFloatType.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMFloatType.kt new file mode 100644 index 00000000000..af4383e13cd --- /dev/null +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMFloatType.kt @@ -0,0 +1,26 @@ +package org.kotlinnative.translator.llvm.types + +import org.kotlinnative.translator.llvm.LLVMExpression +import org.kotlinnative.translator.llvm.LLVMSingleValue + + +class LLVMFloatType() : LLVMType() { + + //TODO switch by types: int + double = int + override fun operatorMinus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = + LLVMExpression(LLVMFloatType(), "fsub float i32 $firstOp, $secondOp") + + //TODO switch by types: int + double = int + override fun operatorTimes(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = + LLVMExpression(LLVMFloatType(), "fmul float i32 $firstOp, $secondOp") + + //TODO switch by types: int + double = int + override fun operatorPlus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = + LLVMExpression(LLVMFloatType(), "fadd float $firstOp, $secondOp") + + override val align = 4 + override var size: Int = 4 + override fun toString() = "float" + override val defaultValue = "0.0" + override fun isPrimitive() = true +} \ No newline at end of file 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 new file mode 100644 index 00000000000..4f90af84ce9 --- /dev/null +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMLongType.kt @@ -0,0 +1,64 @@ +package org.kotlinnative.translator.llvm.types + +import org.kotlinnative.translator.llvm.LLVMExpression +import org.kotlinnative.translator.llvm.LLVMSingleValue + + +class LLVMLongType() : LLVMType() { + + override fun operatorOr(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = + LLVMExpression(LLVMLongType(), "or i64 $firstOp, $secondOp") + + override fun operatorAnd(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = + LLVMExpression(LLVMLongType(), "and i64 $firstOp, $secondOp") + + override fun operatorXor(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = + LLVMExpression(LLVMLongType(), "xor i64 $firstOp, $secondOp") + + override fun operatorShl(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = + LLVMExpression(LLVMLongType(), "shl i64 $firstOp, $secondOp") + + override fun operatorShr(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = + LLVMExpression(LLVMLongType(), "ashr i64 $firstOp, $secondOp") + + override fun operatorUshr(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = + LLVMExpression(LLVMLongType(), "lshr i64 $firstOp, $secondOp") + + //TODO switch by types: int + double = int + override fun operatorMinus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = + LLVMExpression(LLVMLongType(), "sub nsw i64 $firstOp, $secondOp") + + //TODO switch by types: int + double = int + override fun operatorTimes(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = + LLVMExpression(LLVMLongType(), "mul nsw i64 $firstOp, $secondOp") + + //TODO switch by types: int + double = int + override fun operatorPlus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = + LLVMExpression(LLVMLongType(), "add nsw i64 $firstOp, $secondOp") + + 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 operatorLeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = + LLVMExpression(LLVMBooleanType(), "icmp sle i64 $firstOp, $secondOp") + + override fun operatorGeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = + LLVMExpression(LLVMBooleanType(), "icmp sge i64 $firstOp, $secondOp") + + override fun operatorEq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = + LLVMExpression(LLVMBooleanType(), "icmp eq i64 $firstOp, $secondOp") + + override fun operatorNeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = + LLVMExpression(LLVMBooleanType(), "icmp ne i64 $firstOp, $secondOp") + + override val align = 4 + override var size: Int = 8 + override val defaultValue = "0" + + override fun toString() = "i64" + override fun isPrimitive() = true +} \ No newline at end of file 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 455cb208874..41fda1792f6 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 @@ -32,11 +32,13 @@ abstract class LLVMType() : Cloneable { } fun parseLLVMType(type: String): LLVMType = when (type) { + "i64" -> LLVMLongType() "i32" -> LLVMIntType() "i16" -> LLVMShortType() "i8" -> LLVMCharType() "i1" -> LLVMBooleanType() "double" -> LLVMDoubleType() + "float" -> LLVMFloatType() "Unit" -> LLVMVoidType() else -> LLVMReferenceType(type) } diff --git a/translator/src/main/resources/kotlib/kotlin/Primitives.kt b/translator/src/main/resources/kotlib/kotlin/Primitives.kt new file mode 100644 index 00000000000..ff543fc7a3d --- /dev/null +++ b/translator/src/main/resources/kotlib/kotlin/Primitives.kt @@ -0,0 +1,34 @@ +external fun kotlinclib_intToByte(value: Int): Byte +external fun kotlinclib_intToChar(value: Int): Char +external fun kotlinclib_intToShort(value: Int): Short +external fun kotlinclib_intToLong(value: Int): Long +external fun kotlinclib_intToFloat(value: Int): Float +external fun kotlinclib_intToDouble(value: Int): Double + +fun Int.toByte(): Byte { + return kotlinclib_intToByte(this) +} + +fun Int.toInt(): Int { + return this +} + +fun Int.toChar(): Char { + return kotlinclib_intToChar(this) +} + +fun Int.toShort(): Short { + return kotlinclib_intToShort(this) +} + +fun Int.toLong(): Long { + return kotlinclib_intToLong(this) +} + +fun Int.toFloat(): Float { + return kotlinclib_intToFloat(this) +} + +fun Int.toDouble(): Double { + return kotlinclib_intToDouble(this) +} diff --git a/translator/src/main/resources/kotlib/linked/primitives_c.ll b/translator/src/main/resources/kotlib/linked/primitives_c.ll new file mode 100644 index 00000000000..5262af7bc5c --- /dev/null +++ b/translator/src/main/resources/kotlib/linked/primitives_c.ll @@ -0,0 +1,59 @@ +; ModuleID = 'primitives.c' +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-linux-gnu" + +; Function Attrs: nounwind uwtable +define signext i8 @kotlinclib_intToByte(i32 %value) #0 { + %1 = alloca i32, align 4 + store i32 %value, i32* %1, align 4 + %2 = load i32* %1, align 4 + %3 = trunc i32 %2 to i8 + ret i8 %3 +} + +; Function Attrs: nounwind uwtable +define signext i8 @kotlinclib_intToChar(i32 %value) #0 { + %1 = alloca i32, align 4 + store i32 %value, i32* %1, align 4 + %2 = load i32* %1, align 4 + %3 = trunc i32 %2 to i8 + ret i8 %3 +} + +; Function Attrs: nounwind uwtable +define signext i16 @kotlinclib_intToShort(i32 %value) #0 { + %1 = alloca i32, align 4 + store i32 %value, i32* %1, align 4 + %2 = load i32* %1, align 4 + %3 = trunc i32 %2 to i16 + ret i16 %3 +} + +; Function Attrs: nounwind uwtable +define i64 @kotlinclib_intToLong(i32 %value) #0 { + %1 = alloca i32, align 4 + store i32 %value, i32* %1, align 4 + %2 = load i32* %1, align 4 + %3 = sext i32 %2 to i64 + ret i64 %3 +} + +; Function Attrs: nounwind uwtable +define float @kotlinclib_intToFloat(i32 %value) #0 { + %1 = alloca i32, align 4 + store i32 %value, i32* %1, align 4 + %2 = load i32* %1, align 4 + %3 = sitofp i32 %2 to float + ret float %3 +} + +; Function Attrs: nounwind uwtable +define double @kotlinclib_intToDouble(i32 %value) #0 { + %1 = alloca i32, align 4 + store i32 %value, i32* %1, align 4 + %2 = load i32* %1, align 4 + %3 = sitofp i32 %2 to double + ret double %3 +} + +attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } diff --git a/translator/src/test/kotlin/tests/input/primitives_1.txt b/translator/src/test/kotlin/tests/input/primitives_1.txt new file mode 100644 index 00000000000..7b9976c4a8d --- /dev/null +++ b/translator/src/test/kotlin/tests/input/primitives_1.txt @@ -0,0 +1,4 @@ +testCastToInt(32) == 0 +testCastToInt(34) == 1 +testCastToByte(32) == 0 +testCastToByte(34) == 1 diff --git a/translator/src/test/kotlin/tests/kotlin/primitives_1.kt b/translator/src/test/kotlin/tests/kotlin/primitives_1.kt new file mode 100644 index 00000000000..a4551428c53 --- /dev/null +++ b/translator/src/test/kotlin/tests/kotlin/primitives_1.kt @@ -0,0 +1,7 @@ +fun testCastToByte(X : Byte): Boolean{ + return 34.toByte() == X +} + +fun testCastToInt(X : Int): Boolean{ + return 34.toInt() == X +}