From 91035b692bea48f1a02b12c32f4bde0b4bbc4102 Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Tue, 8 Nov 2016 17:38:36 +0300 Subject: [PATCH] Add more console operations, nicer naming in natives. (#46) --- backend.native/tests/build.gradle | 8 +++- backend.native/tests/runtime/basic/hello0.kt | 3 +- backend.native/tests/runtime/basic/hello1.kt | 2 +- backend.native/tests/runtime/basic/hello3.kt | 3 ++ runtime/src/main/cpp/Natives.cpp | 44 ++++++++++++-------- runtime/src/main/cpp/Natives.h | 35 +++++++++------- runtime/src/main/kotlin/kotlin/Primitives.kt | 4 ++ runtime/src/main/kotlin/kotlin/io/Console.kt | 15 ++++++- 8 files changed, 75 insertions(+), 39 deletions(-) create mode 100644 backend.native/tests/runtime/basic/hello3.kt diff --git a/backend.native/tests/build.gradle b/backend.native/tests/build.gradle index dce9c14d502..17beb340c9a 100644 --- a/backend.native/tests/build.gradle +++ b/backend.native/tests/build.gradle @@ -153,7 +153,7 @@ task local_variable(type: UnitKonanTest) { } task hello0(type: RunKonanTest) { - goldValue = "Hello, world!" + goldValue = "Hello, world!\n" source = "runtime/basic/hello0.kt" } @@ -170,6 +170,12 @@ task hello2(type: RunKonanTest) { source = "runtime/basic/hello2.kt" } */ +/* TODO: enable, once can call toString() on Int. +task hello3(type: RunKonanTest) { + goldValue = "239" + source = "runtime/basic/hello3.kt" +} */ + task if_else(type: UnitKonanTest) { source = "codegen/branching/if_else.kt" } diff --git a/backend.native/tests/runtime/basic/hello0.kt b/backend.native/tests/runtime/basic/hello0.kt index 2b35e95c323..98315b19d44 100644 --- a/backend.native/tests/runtime/basic/hello0.kt +++ b/backend.native/tests/runtime/basic/hello0.kt @@ -1,4 +1,3 @@ -// TODO: remove kotlin_native.io once overrides are in place. fun main(args : Array) { - kotlin.io.print("Hello, world!") + println("Hello, world!") } diff --git a/backend.native/tests/runtime/basic/hello1.kt b/backend.native/tests/runtime/basic/hello1.kt index 389e2a8d72b..3cfdc82c5dc 100644 --- a/backend.native/tests/runtime/basic/hello1.kt +++ b/backend.native/tests/runtime/basic/hello1.kt @@ -1,4 +1,4 @@ // TODO: remove kotlin_native.io once overrides are in place. fun main(args : Array) { - kotlin.io.print(kotlin.io.readLine()) + print(readLine()) } diff --git a/backend.native/tests/runtime/basic/hello3.kt b/backend.native/tests/runtime/basic/hello3.kt new file mode 100644 index 00000000000..7eca8690cd0 --- /dev/null +++ b/backend.native/tests/runtime/basic/hello3.kt @@ -0,0 +1,3 @@ +fun main(args : Array) { + print(239) +} \ No newline at end of file diff --git a/runtime/src/main/cpp/Natives.cpp b/runtime/src/main/cpp/Natives.cpp index 83167ebf557..96081000afd 100644 --- a/runtime/src/main/cpp/Natives.cpp +++ b/runtime/src/main/cpp/Natives.cpp @@ -12,17 +12,17 @@ extern "C" { // Any.kt -KBool Kotlin_Any_equals(const ObjHeader* thiz, const ObjHeader* other) { +KBool Kotlin_Any_equals(KConstRef thiz, KConstRef other) { return thiz == other; } -KInt Kotlin_Any_hashCode(const ObjHeader* thiz) { +KInt Kotlin_Any_hashCode(KConstRef thiz) { // Here we will use different mechanism for stable hashcode, using meta-objects // if moving collector will be used. return reinterpret_cast(thiz); } -ArrayHeader* Kotlin_Any_toString(const ObjHeader* thiz) { +KString Kotlin_Any_toString(KConstRef thiz) { return nullptr; } @@ -141,13 +141,24 @@ KInt Kotlin_IntArray_getArrayLength(const ArrayHeader* array) { } // io/Console.kt -void Kotlin_io_Console_print(const ArrayHeader* array) { - RuntimeAssert(array->type_info() == theStringTypeInfo, "Must use a string"); +void Kotlin_io_Console_print(KString message) { + RuntimeAssert(message->type_info() == theStringTypeInfo, "Must use a string"); // TODO: system stdout must be aware about UTF-8. - write(STDOUT_FILENO, ByteArrayAddressOfElementAt(array, 0), array->count_); + write(STDOUT_FILENO, ByteArrayAddressOfElementAt(message, 0), message->count_); } -ArrayHeader* Kotlin_io_Console_readLine() { +void Kotlin_io_Console_println(KString message) { + RuntimeAssert(message->type_info() == theStringTypeInfo, "Must use a string"); + // TODO: system stdout must be aware about UTF-8. + write(STDOUT_FILENO, ByteArrayAddressOfElementAt(message, 0), message->count_); + Kotlin_io_Console_println0(); +} + +void Kotlin_io_Console_println0() { + write(STDOUT_FILENO, "\n", 1); +} + +KString Kotlin_io_Console_readLine() { char data[2048]; if (!fgets(data, sizeof(data) - 1, stdin)) { return nullptr; @@ -161,13 +172,13 @@ ArrayHeader* Kotlin_io_Console_readLine() { } // String.kt -KInt Kotlin_String_compareTo(const ArrayHeader* thiz, const ArrayHeader* other) { +KInt Kotlin_String_compareTo(KString thiz, KString other) { return memcmp(ByteArrayAddressOfElementAt(thiz, 0), ByteArrayAddressOfElementAt(other, 0), thiz->count_ < other->count_ ? thiz->count_ : other->count_); } -KChar Kotlin_String_get(const ArrayHeader* thiz, KInt index) { +KChar Kotlin_String_get(KString thiz, KInt index) { // TODO: support full UTF-8. if (static_cast(index) >= thiz->count_) { ThrowArrayIndexOutOfBoundsException(); @@ -175,11 +186,11 @@ KChar Kotlin_String_get(const ArrayHeader* thiz, KInt index) { return *ByteArrayAddressOfElementAt(thiz, index); } -KInt Kotlin_String_getStringLength(const ArrayHeader* thiz) { +KInt Kotlin_String_getStringLength(KString thiz) { return thiz->count_; } -ArrayHeader* Kotlin_String_fromUtf8Array(const ArrayHeader* array) { +KString Kotlin_String_fromUtf8Array(const ArrayHeader* array) { RuntimeAssert(array->type_info() == theByteArrayTypeInfo, "Must use a byte array"); uint32_t length = ArraySizeBytes(array); // TODO: support full UTF-8. @@ -191,8 +202,7 @@ ArrayHeader* Kotlin_String_fromUtf8Array(const ArrayHeader* array) { return result; } -ArrayHeader* Kotlin_String_plusImpl( - const ArrayHeader* thiz, const ArrayHeader* other) { +KString Kotlin_String_plusImpl(KString thiz, KString other) { // TODO: support UTF-8 RuntimeAssert(thiz->type_info() == theStringTypeInfo, "Must be a string"); RuntimeAssert(other->type_info() == theStringTypeInfo, "Must be a string"); @@ -210,8 +220,7 @@ ArrayHeader* Kotlin_String_plusImpl( return result; } -KBool Kotlin_String_equals( - const ArrayHeader* thiz, const ObjHeader* other) { +KBool Kotlin_String_equals(KString thiz, KConstRef other) { if (other == nullptr || other->type_info() != theStringTypeInfo) return 0; const ArrayHeader* otherString = reinterpret_cast(other); return thiz->count_ == otherString->count_ && @@ -220,14 +229,13 @@ KBool Kotlin_String_equals( thiz->count_) == 0; } -KInt Kotlin_String_hashCode(const ArrayHeader* thiz) { +KInt Kotlin_String_hashCode(KString thiz) { // TODO: consider caching strings hashes. // TODO: maybe use some simpler hashing algorithm? return CityHash64(ByteArrayAddressOfElementAt(thiz, 0), thiz->count_); } -KRef Kotlin_String_subSequence( - const ArrayHeader* thiz, KInt startIndex, KInt endIndex) { +KRef Kotlin_String_subSequence(KString thiz, KInt startIndex, KInt endIndex) { RuntimeAssert(false, "Unsupported operation"); return nullptr; } diff --git a/runtime/src/main/cpp/Natives.h b/runtime/src/main/cpp/Natives.h index 1ac38dad23b..fde5fbdfd38 100644 --- a/runtime/src/main/cpp/Natives.h +++ b/runtime/src/main/cpp/Natives.h @@ -11,6 +11,8 @@ typedef uint16_t KChar; typedef int32_t KInt; typedef ObjHeader* KRef; +typedef const ObjHeader* KConstRef; +typedef const ArrayHeader* KString; // Optimized versions not accessing type info. inline KByte* ByteArrayAddressOfElementAt(ArrayHeader* obj, KInt index) { @@ -52,9 +54,9 @@ extern "C" { #endif // Any.kt -KBool Kotlin_Any_equals(const ObjHeader* thiz, const ObjHeader* other); -KInt Kotlin_Any_hashCode(const ObjHeader* thiz); -ArrayHeader* Kotlin_Any_toString(const ObjHeader* thiz); +KBool Kotlin_Any_equals(KConstRef thiz, KConstRef other); +KInt Kotlin_Any_hashCode(KConstRef thiz); +KString Kotlin_Any_toString(KConstRef thiz); // Arrays.kt // TODO: those must be compiler intrinsics afterwards. @@ -79,20 +81,23 @@ void Kotlin_IntArray_set(ArrayHeader* thiz, KInt index, KInt value); KInt Kotlin_IntArray_getArrayLength(const ArrayHeader* thiz); // io/Console.kt -void Kotlin_io_Console_print(const ArrayHeader* thiz); -ArrayHeader* Kotlin_io_Console_readLine(); +void Kotlin_io_Console_print(KString message); +void Kotlin_io_Console_println(KString message); +void Kotlin_io_Console_println0(); +KString Kotlin_io_Console_readLine(); + +// Primitives.kt. +KString Kotlin_Int_toString(KInt value); // String.kt -KInt Kotlin_String_hashCode(const ArrayHeader* thiz); -KBool Kotlin_String_equals(const ArrayHeader* thiz, const ObjHeader* other); -KInt Kotlin_String_compareTo(const ArrayHeader* thiz, const ArrayHeader* other); -KChar Kotlin_String_get(const ArrayHeader* thiz, KInt index); -ArrayHeader* Kotlin_String_fromUtf8Array(const ArrayHeader* array); -ArrayHeader* Kotlin_String_plusImpl( - const ArrayHeader* thiz, const ArrayHeader* other); -KInt Kotlin_String_getStringLength(const ArrayHeader* thiz); -KRef Kotlin_String_subSequence( - const ArrayHeader* thiz, KInt startIndex, KInt endIndex); +KInt Kotlin_String_hashCode(KString thiz); +KBool Kotlin_String_equals(KString thiz, KConstRef other); +KInt Kotlin_String_compareTo(KString thiz, KString other); +KChar Kotlin_String_get(KString thiz, KInt index); +KString Kotlin_String_fromUtf8Array(const ArrayHeader* array); +KString Kotlin_String_plusImpl(KString thiz, KString other); +KInt Kotlin_String_getStringLength(KString thiz); +KRef Kotlin_String_subSequence(KString thiz, KInt startIndex, KInt endIndex); #ifdef __cplusplus } diff --git a/runtime/src/main/kotlin/kotlin/Primitives.kt b/runtime/src/main/kotlin/kotlin/Primitives.kt index d5ad12b3d22..2b28107c21a 100644 --- a/runtime/src/main/kotlin/kotlin/Primitives.kt +++ b/runtime/src/main/kotlin/kotlin/Primitives.kt @@ -144,6 +144,10 @@ public class Byte : Number(), Comparable { external public override fun toLong(): Long external public override fun toFloat(): Float external public override fun toDouble(): Double + + // Konan-specific. + @SymbolName("Kotlin_Int_toString") + external public override fun toString(): String } /** diff --git a/runtime/src/main/kotlin/kotlin/io/Console.kt b/runtime/src/main/kotlin/kotlin/io/Console.kt index 21ea74e1cf1..7114e90cab6 100644 --- a/runtime/src/main/kotlin/kotlin/io/Console.kt +++ b/runtime/src/main/kotlin/kotlin/io/Console.kt @@ -1,7 +1,18 @@ package kotlin.io @kotlin.SymbolName("Kotlin_io_Console_print") -external public fun print(message: kotlin.String) +external public fun print(message: String) + +/* +public fun print(message: Int) { + print(message.toString()) +} */ + +@kotlin.SymbolName("Kotlin_io_Console_println") +external public fun println(message: String) + +@kotlin.SymbolName("Kotlin_io_Console_println0") +external public fun println() @kotlin.SymbolName("Kotlin_io_Console_readLine") -external public fun readLine(): kotlin.String +external public fun readLine(): String