diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index 00a95ded86f..d133af0ec23 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -353,15 +353,15 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid true -> return LLVMConstInt(LLVMInt1Type(), 1, 1) false -> return LLVMConstInt(LLVMInt1Type(), 0, 1) } - IrConstKind.Char -> TODO() + IrConstKind.Char -> return LLVMConstInt(LLVMInt16Type(), (value.value as Char).toLong(), 0) IrConstKind.Byte -> return LLVMConstInt(LLVMInt32Type(), (value.value as Byte).toLong(), 1) IrConstKind.Short -> return LLVMConstInt(LLVMInt32Type(), (value.value as Short).toLong(), 1) IrConstKind.Int -> return LLVMConstInt(LLVMInt32Type(), (value.value as Int).toLong(), 1) IrConstKind.Long -> return LLVMConstInt(LLVMInt64Type(), value.value as Long, 1) IrConstKind.String -> return context.staticData.createStringLiteral(value as IrConst).getLlvmValue() - IrConstKind.Float -> TODO() - IrConstKind.Double -> TODO() + IrConstKind.Float -> return LLVMConstRealOfString(LLVMFloatType(), (value.value as Float).toString()) + IrConstKind.Double -> return LLVMConstRealOfString(LLVMDoubleType(), (value.value as Double).toString()) } TODO() } diff --git a/backend.native/tests/build.gradle b/backend.native/tests/build.gradle index 21924a72ced..0cfd584b8c8 100644 --- a/backend.native/tests/build.gradle +++ b/backend.native/tests/build.gradle @@ -186,6 +186,12 @@ task hello3(type: RunKonanTest) { source = "runtime/basic/hello3.kt" } */ + +task tostring0(type: RunKonanTest) { + goldValue = "127\n255\n239\nA\n1122334455\n112233445566778899\n1E+27\n1E-300\ntrue\nfalse\n" + source = "runtime/basic/tostring0.kt" +} + task if_else(type: UnitKonanTest) { source = "codegen/branching/if_else.kt" } diff --git a/backend.native/tests/runtime/basic/tostring0.kt b/backend.native/tests/runtime/basic/tostring0.kt new file mode 100644 index 00000000000..8fbd8860efa --- /dev/null +++ b/backend.native/tests/runtime/basic/tostring0.kt @@ -0,0 +1,14 @@ +fun main(args : Array) { + println(127.toByte().toString()) + println(255.toByte().toString()) + println(239.toShort().toString()) + println('A'.toString()) + // println('Ё'.toString()) + // println('ト'.toString()) + println(1122334455.toString()) + println(112233445566778899.toString()) + println(1e27.toFloat().toString()) + println(1e-300.toDouble().toString()) + println(true.toString()) + println(false.toString()) +} \ No newline at end of file diff --git a/runtime/src/main/cpp/ToString.cpp b/runtime/src/main/cpp/ToString.cpp new file mode 100644 index 00000000000..8421e96c0da --- /dev/null +++ b/runtime/src/main/cpp/ToString.cpp @@ -0,0 +1,74 @@ +#include +#include + +#include "Assert.h" +#include "Exceptions.h" +#include "Memory.h" +#include "Natives.h" +#include "Types.h" + +namespace { + +KString makeString(const char* cstring) { + uint32_t length = strlen(cstring); + ArrayHeader* result = ArrayContainer( + theStringTypeInfo, length).GetPlace(); + memcpy( + ByteArrayAddressOfElementAt(result, 0), + cstring, + length); + return result; +} + +} // namespace + +extern "C" { + +KString Kotlin_Byte_toString(KByte value) { + char cstring[8]; + snprintf(cstring, sizeof(cstring), "%d", value); + return makeString(cstring); +} + +KString Kotlin_Char_toString(KChar value) { + char cstring[5]; + // TODO: support UTF-8. + snprintf(cstring, sizeof(cstring), "%c", value); + return makeString(cstring); +} + +KString Kotlin_Short_toString(KShort value) { + char cstring[8]; + snprintf(cstring, sizeof(cstring), "%d", value); + return makeString(cstring); +} + +KString Kotlin_Int_toString(KInt value) { + char cstring[16]; + snprintf(cstring, sizeof(cstring), "%d", value); + return makeString(cstring); +} + +KString Kotlin_Long_toString(KLong value) { + char cstring[32]; + snprintf(cstring, sizeof(cstring), "%lld", value); + return makeString(cstring); +} + +KString Kotlin_Float_toString(KFloat value) { + char cstring[32]; + snprintf(cstring, sizeof(cstring), "%G", value); + return makeString(cstring); +} + +KString Kotlin_Double_toString(KDouble value) { + char cstring[32]; + snprintf(cstring, sizeof(cstring), "%G", value); + return makeString(cstring); +} + +KString Kotlin_Boolean_toString(KBool value) { + return makeString(value ? "true" : "false"); +} + +} // extern "C" diff --git a/runtime/src/main/kotlin/kotlin/Boolean.kt b/runtime/src/main/kotlin/kotlin/Boolean.kt index fc048371793..b7768404738 100644 --- a/runtime/src/main/kotlin/kotlin/Boolean.kt +++ b/runtime/src/main/kotlin/kotlin/Boolean.kt @@ -26,4 +26,8 @@ public class Boolean : Comparable { external public infix fun xor(other: Boolean): Boolean external public override fun compareTo(other: Boolean): Int + + // Konan-specific. + @SymbolName("Kotlin_Boolean_toString") + external public override fun toString(): String } \ No newline at end of file diff --git a/runtime/src/main/kotlin/kotlin/Char.kt b/runtime/src/main/kotlin/kotlin/Char.kt index 301b3369e8c..a5452977654 100644 --- a/runtime/src/main/kotlin/kotlin/Char.kt +++ b/runtime/src/main/kotlin/kotlin/Char.kt @@ -76,5 +76,8 @@ public class Char : Comparable { public const val MAX_SURROGATE: Char = MAX_LOW_SURROGATE } + // Konan-specific. + @SymbolName("Kotlin_Char_toString") + external public override fun toString(): String } diff --git a/runtime/src/main/kotlin/kotlin/Primitives.kt b/runtime/src/main/kotlin/kotlin/Primitives.kt index a0eb66e935b..e11f03f5e20 100644 --- a/runtime/src/main/kotlin/kotlin/Primitives.kt +++ b/runtime/src/main/kotlin/kotlin/Primitives.kt @@ -193,7 +193,7 @@ public class Byte : Number(), Comparable { external public override fun toDouble(): Double // Konan-specific. - @SymbolName("Kotlin_Int_toString") + @SymbolName("Kotlin_Byte_toString") external public override fun toString(): String } @@ -388,6 +388,10 @@ public class Short : Number(), Comparable { external public override fun toFloat(): Float @SymbolName("Kotlin_Short_toDouble") external public override fun toDouble(): Double + + // Konan-specific. + @SymbolName("Kotlin_Short_toString") + external public override fun toString(): String } /** @@ -603,6 +607,10 @@ public class Int : Number(), Comparable { external public override fun toFloat(): Float @SymbolName("Kotlin_Int_toDouble") external public override fun toDouble(): Double + + // Konan-specific. + @SymbolName("Kotlin_Int_toString") + external public override fun toString(): String } /** @@ -818,6 +826,10 @@ public class Long : Number(), Comparable { external public override fun toFloat(): Float @SymbolName("Kotlin_Long_toDouble") external public override fun toDouble(): Double + + // Konan-specific. + @SymbolName("Kotlin_Long_toString") + external public override fun toString(): String } /** @@ -1018,6 +1030,10 @@ public class Float : Number(), Comparable { external public override fun toFloat(): Float @SymbolName("Kotlin_Float_toDouble") external public override fun toDouble(): Double + + // Konan-specific. + @SymbolName("Kotlin_Float_toString") + external public override fun toString(): String } /** @@ -1218,4 +1234,8 @@ public class Double : Number(), Comparable { external public override fun toFloat(): Float @SymbolName("Kotlin_Double_toDouble") external public override fun toDouble(): Double + + // Konan-specific. + @SymbolName("Kotlin_Double_toString") + external public override fun toString(): String }