diff --git a/backend.native/tests/build.gradle b/backend.native/tests/build.gradle index 0a442043d1b..4932cf27343 100644 --- a/backend.native/tests/build.gradle +++ b/backend.native/tests/build.gradle @@ -443,6 +443,11 @@ task interface0(type: RunKonanTest) { source = "runtime/basic/interface0.kt" } +task hash0(type: RunKonanTest) { + goldValue = "239\n0\n97\n1065353216\n1072693248\n1\n0\ntrue\ntrue\n" + source = "runtime/basic/hash0.kt" +} + task array_list1(type: RunKonanTest) { goldValue = "OK\n" source = "runtime/collections/array_list1.kt" diff --git a/backend.native/tests/runtime/basic/hash0.kt b/backend.native/tests/runtime/basic/hash0.kt new file mode 100644 index 00000000000..72c76a82284 --- /dev/null +++ b/backend.native/tests/runtime/basic/hash0.kt @@ -0,0 +1,18 @@ +fun main(args : Array) { + println(239.hashCode()) + println((-1L).hashCode()) + println('a'.hashCode()) + println(1.0f.hashCode()) + println(1.0.hashCode()) + println(true.hashCode()) + println(false.hashCode()) + println(Any().hashCode() != Any().hashCode()) + val a = CharArray(5) + a[0] = 'H' + a[1] = 'e' + a[2] = 'l' + a[3] = 'l' + a[4] = 'o' + // Note that it uses private Konan API. + println("Hello".hashCode() == fromCharArray(a, 0, 5).hashCode()) +} \ No newline at end of file diff --git a/runtime/src/main/cpp/Operator.cpp b/runtime/src/main/cpp/Operator.cpp index 72d8a552d21..95c89e2c1b7 100644 --- a/runtime/src/main/cpp/Operator.cpp +++ b/runtime/src/main/cpp/Operator.cpp @@ -248,8 +248,13 @@ KLong Kotlin_Long_dec (KLong a ) { return --a; } KLong Kotlin_Long_unaryPlus (KLong a ) { return +a; } KLong Kotlin_Long_unaryMinus (KLong a ) { return -a; } -KLong Kotlin_Long_xor_Long (KLong a, KLong b) { return a^b; } -KLong Kotlin_Long_ushr_Long (KLong a, KLong b) { return a >> b; } +KLong Kotlin_Long_xor_Long (KLong a, KLong b) { return a ^ b; } +KLong Kotlin_Long_shr_Int (KLong a, KInt b) { + return a >> b; +} +KLong Kotlin_Long_ushr_Int (KLong a, KInt b) { + return static_cast(a) >> b; +} KByte Kotlin_Long_toByte (KLong a ) { return a; } KShort Kotlin_Long_toShort (KLong a ) { return a; } @@ -314,6 +319,15 @@ KLong Kotlin_Float_toLong (KFloat a ) { return a; } KFloat Kotlin_Float_toFloat (KFloat a ) { return a; } KDouble Kotlin_Float_toDouble (KFloat a ) { return a; } +KInt Kotlin_Float_bits (KFloat a) { + union { + KFloat f; + KInt i; + } alias; + alias.f = a; + return alias.i; +} + //--- Double ------------------------------------------------------------------// KInt Kotlin_Double_compareTo_Byte (KDouble a, KByte b) { if (a == b) return 0; return (a < b) ? -1 : 1; } @@ -369,4 +383,14 @@ KInt Kotlin_Double_toInt (KDouble a ) { return a; } KLong Kotlin_Double_toLong (KDouble a ) { return a; } KFloat Kotlin_Double_toFloat (KDouble a ) { return a; } KDouble Kotlin_Double_toDouble (KDouble a ) { return a; } -} // extern "C" \ No newline at end of file + +KLong Kotlin_Double_bits (KDouble a) { + union { + KDouble d; + KLong l; + } alias; + alias.d = a; + return alias.l; +} + +} // extern "C" diff --git a/runtime/src/main/kotlin/kotlin/Boolean.kt b/runtime/src/main/kotlin/kotlin/Boolean.kt index d6aff94d668..41f76c900f2 100644 --- a/runtime/src/main/kotlin/kotlin/Boolean.kt +++ b/runtime/src/main/kotlin/kotlin/Boolean.kt @@ -35,4 +35,8 @@ public final class Boolean : Comparable { // Konan-specific. @SymbolName("Kotlin_Boolean_toString") external public override fun toString(): String + + public override fun hashCode(): Int { + return if (this) 1 else 0; + } } \ 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 006b37fe727..49a1af31824 100644 --- a/runtime/src/main/kotlin/kotlin/Char.kt +++ b/runtime/src/main/kotlin/kotlin/Char.kt @@ -94,5 +94,9 @@ public final class Char : Comparable { // Konan-specific. @SymbolName("Kotlin_Char_toString") external public override fun toString(): String + + public override fun hashCode(): Int { + return this.toInt(); + } } diff --git a/runtime/src/main/kotlin/kotlin/Primitives.kt b/runtime/src/main/kotlin/kotlin/Primitives.kt index 0593c9b580a..55fd5f8582c 100644 --- a/runtime/src/main/kotlin/kotlin/Primitives.kt +++ b/runtime/src/main/kotlin/kotlin/Primitives.kt @@ -203,6 +203,10 @@ public final class Byte : Number(), Comparable { // Konan-specific. @SymbolName("Kotlin_Byte_toString") external public override fun toString(): String + + public override fun hashCode(): Int { + return this.toInt() + } } /** @@ -408,6 +412,10 @@ public final class Short : Number(), Comparable { // Konan-specific. @SymbolName("Kotlin_Short_toString") external public override fun toString(): String + + public override fun hashCode(): Int { + return this.toInt() + } } /** @@ -635,6 +643,10 @@ public final class Int : Number(), Comparable { // Konan-specific. @SymbolName("Kotlin_Int_toString") external public override fun toString(): String + + public override fun hashCode(): Int { + return this + } } /** @@ -826,10 +838,10 @@ public final class Long : Number(), Comparable { @SymbolName("Kotlin_Long_shl_Long") external public infix fun shl(bitCount: Int): Long /** Shifts this value right by [bits], filling the leftmost bits with copies of the sign bit. */ - @SymbolName("Kotlin_Long_shr_Long") + @SymbolName("Kotlin_Long_shr_Int") external public infix fun shr(bitCount: Int): Long /** Shifts this value right by [bits], filling the leftmost bits with zeros. */ - @SymbolName("Kotlin_Long_ushr_Long") + @SymbolName("Kotlin_Long_ushr_Int") external public infix fun ushr(bitCount: Int): Long /** Performs a bitwise AND operation between the two values. */ @SymbolName("Kotlin_Long_and_Long") @@ -862,6 +874,10 @@ public final class Long : Number(), Comparable { // Konan-specific. @SymbolName("Kotlin_Long_toString") external public override fun toString(): String + + public override fun hashCode(): Int { + return ((this ushr 32) xor this).toInt() + } } /** @@ -1047,7 +1063,6 @@ public final class Float : Number(), Comparable { @SymbolName("Kotlin_Float_unaryMinus") external public operator fun unaryMinus(): Float - @SymbolName("Kotlin_Float_toByte") external public override fun toByte(): Byte @SymbolName("Kotlin_Float_toChar") @@ -1066,6 +1081,13 @@ public final class Float : Number(), Comparable { // Konan-specific. @SymbolName("Kotlin_Float_toString") external public override fun toString(): String + + public override fun hashCode(): Int { + return bits() + } + + @SymbolName("Kotlin_Float_bits") + external public fun bits(): Int } /** @@ -1270,4 +1292,11 @@ public final class Double : Number(), Comparable { // Konan-specific. @SymbolName("Kotlin_Double_toString") external public override fun toString(): String + + public override fun hashCode(): Int { + return bits().hashCode() + } + + @SymbolName("Kotlin_Double_bits") + external public fun bits(): Long }