From 720947facb7503732509d549229090481e9dba54 Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Fri, 11 Nov 2016 15:03:49 +0300 Subject: [PATCH] Alloc arrays, fix RTTI for Any (#49) --- .../kotlin/backend/konan/DescriptorUtils.kt | 17 ++ .../kotlin/backend/konan/llvm/Context.kt | 1 + .../kotlin/backend/konan/llvm/IrToBitcode.kt | 19 +- .../backend/konan/llvm/RTTIGenerator.kt | 20 +- backend.native/tests/build.gradle | 6 +- backend.native/tests/runtime/basic/array0.kt | 29 ++ runtime/src/main/cpp/Arrays.cpp | 268 ++++++++++++++++++ runtime/src/main/cpp/Memory.h | 6 +- runtime/src/main/cpp/Natives.cpp | 124 +------- runtime/src/main/cpp/Natives.h | 24 +- runtime/src/main/cpp/ToString.cpp | 2 +- runtime/src/main/cpp/Types.h | 6 +- runtime/src/main/kotlin/kotlin/Array.kt | 3 +- runtime/src/main/kotlin/kotlin/Arrays.kt | 113 +++++++- runtime/src/main/kotlin/kotlin/Primitives.kt | 18 +- 15 files changed, 492 insertions(+), 164 deletions(-) create mode 100644 backend.native/tests/runtime/basic/array0.kt create mode 100644 runtime/src/main/cpp/Arrays.cpp diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/DescriptorUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/DescriptorUtils.kt index 6fd84d6cc9b..2029698b5cc 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/DescriptorUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/DescriptorUtils.kt @@ -42,8 +42,25 @@ private val intrinsicTypes = setOf( "kotlin.Float", "kotlin.Double" ) +private val arrayTypes = setOf( + "kotlin.Array", + "kotlin.ByteArray", + "kotlin.CharArray", + "kotlin.ShortArray", + "kotlin.IntArray", + "kotlin.LongArray", + "kotlin.FloatArray", + "kotlin.DoubleArray", + "kotlin.BooleanArray" +) + internal val ClassDescriptor.isIntrinsic: Boolean get() = this.fqNameSafe.asString() in intrinsicTypes + +internal val ClassDescriptor.isArray: Boolean + get() = this.fqNameSafe.asString() in arrayTypes + + internal val ClassDescriptor.isInterface: Boolean get() = (this.kind == ClassKind.INTERFACE) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Context.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Context.kt index 77c11a760d8..06027b44d83 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Context.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Context.kt @@ -25,6 +25,7 @@ internal class Context(val irModule: IrModuleFragment, val runtime: Runtime, val private fun importRtFunction(name: String) = importFunction(name, runtime.llvmModule) val allocInstanceFunction = importRtFunction("AllocInstance") + val allocArrayFunction = importRtFunction("AllocArrayInstance") fun dispose() { LLVMDisposeBuilder(llvmBuilder) 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 d133af0ec23..f27f710063f 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 @@ -2,6 +2,7 @@ package org.jetbrains.kotlin.backend.konan.llvm import kotlin_native.interop.* import llvm.* +import org.jetbrains.kotlin.backend.konan.isArray import org.jetbrains.kotlin.backend.konan.isInterface import org.jetbrains.kotlin.backend.konan.isIntrinsic import org.jetbrains.kotlin.builtins.KotlinBuiltIns @@ -19,7 +20,6 @@ import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.name.Name - fun emitLLVM(module: IrModuleFragment, runtimeFile: String, outFile: String) { val llvmModule = LLVMModuleCreateWithName("out")!! // TODO: dispose val runtime = Runtime(runtimeFile) // TODO: dispose @@ -407,9 +407,20 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid private fun evaluateConstructorCall(variableName: String, callee: IrCall, args: MutableList): LLVMOpaqueValue? { logger.log("evaluateConstructorCall : $variableName = ${ir2string(callee)}") memScoped { - val params = allocNativeArrayOf(LLVMOpaqueValue, generator.typeInfoValue((callee.descriptor as ClassConstructorDescriptor).containingDeclaration), Int32(1).getLlvmValue()) - val thisValue = LLVMBuildCall(context.llvmBuilder, context.allocInstanceFunction, params[0], 2, variableName) - + val containingClass = (callee.descriptor as ClassConstructorDescriptor).containingDeclaration + val typeInfo = generator.typeInfoValue(containingClass) + val allocHint = Int32(1).getLlvmValue() + val thisValue = if (containingClass.isArray) { + assert(args.size == 1 && LLVMTypeOf(args[0]) == LLVMInt32Type()) + val size = args[0] + val params = allocNativeArrayOf(LLVMOpaqueValue, typeInfo, allocHint, size) + LLVMBuildCall( + context.llvmBuilder, context.allocArrayFunction, params[0], 3, variableName) + } else { + val params = allocNativeArrayOf(LLVMOpaqueValue, typeInfo, allocHint) + LLVMBuildCall( + context.llvmBuilder, context.allocInstanceFunction, params[0], 2, variableName) + } val constructorParams: MutableList = mutableListOf() constructorParams += thisValue constructorParams += args diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt index afff358e453..027f04eb539 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.OverridingUtil import org.jetbrains.kotlin.resolve.constants.StringValue import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe +import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny @@ -137,11 +138,16 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils { } private val arrayClasses = mapOf( - "kotlin.Array" to -pointerSize, - "kotlin.ByteArray" to -1, - "kotlin.CharArray" to -2, - "kotlin.IntArray" to -4, - "kotlin.String" to -1 + "kotlin.Array" to -pointerSize, + "kotlin.ByteArray" to -1, + "kotlin.CharArray" to -2, + "kotlin.ShortArray" to -2, + "kotlin.IntArray" to -4, + "kotlin.LongArray" to -8, + "kotlin.FloatArray" to -4, + "kotlin.DoubleArray" to -8, + "kotlin.BooleanArray" to -1, + "kotlin.String" to -1 ) private fun getInstanceSize(classType: LLVMOpaqueType?, className: FqName) : Int { @@ -160,7 +166,9 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils { val size = getInstanceSize(classType, className) - val superType = classDesc.getSuperClassOrAny().llvmTypeInfoPtr + val superTypeOrNull = classDesc.getSuperClassNotAny() + val superType = if (superTypeOrNull != null) superTypeOrNull.llvmTypeInfoPtr + else NullPointer(runtime.typeInfoType) val interfaces = classDesc.implementedInterfaces.map { it.llvmTypeInfoPtr } val interfacesPtr = staticData.placeGlobalConstArray("kintf:$className", diff --git a/backend.native/tests/build.gradle b/backend.native/tests/build.gradle index 0cfd584b8c8..2d8726ca131 100644 --- a/backend.native/tests/build.gradle +++ b/backend.native/tests/build.gradle @@ -186,12 +186,16 @@ 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 array0(type: RunKonanTest) { + goldValue = "5\n6\n7\n8\n9\n10\n11\n12\n13\n" + source = "runtime/basic/array0.kt" +} + task if_else(type: UnitKonanTest) { source = "codegen/branching/if_else.kt" } diff --git a/backend.native/tests/runtime/basic/array0.kt b/backend.native/tests/runtime/basic/array0.kt new file mode 100644 index 00000000000..b555959cbcd --- /dev/null +++ b/backend.native/tests/runtime/basic/array0.kt @@ -0,0 +1,29 @@ +fun main(args : Array) { + // Create instances of all array types. + val byteArray = ByteArray(5) + println(byteArray.size.toString()) + + val charArray = CharArray(6) + println(charArray.size.toString()) + + val shortArray = ShortArray(7) + println(shortArray.size.toString()) + + val intArray = IntArray(8) + println(intArray.size.toString()) + + val longArray = LongArray(9) + println(longArray.size.toString()) + + val floatArray = FloatArray(10) + println(floatArray.size.toString()) + + val doubleArray = FloatArray(11) + println(doubleArray.size.toString()) + + val booleanArray = BooleanArray(12) + println(booleanArray.size.toString()) + + val stringArray = Array(13) + println(stringArray.size.toString()) +} \ No newline at end of file diff --git a/runtime/src/main/cpp/Arrays.cpp b/runtime/src/main/cpp/Arrays.cpp new file mode 100644 index 00000000000..8c00460169b --- /dev/null +++ b/runtime/src/main/cpp/Arrays.cpp @@ -0,0 +1,268 @@ +#include +#include + +#include "Assert.h" +#include "Exceptions.h" +#include "Memory.h" +#include "Natives.h" +#include "Types.h" + +extern "C" { + +// TODO: those must be compiler intrinsics afterwards. + +// Array.kt +KRef Kotlin_Array_get(const ArrayHeader* obj, KInt index) { + if (static_cast(index) >= obj->count_) { + ThrowArrayIndexOutOfBoundsException(); + } + return *ArrayAddressOfElementAt(obj, index); +} + +void Kotlin_Array_set(ArrayHeader* obj, KInt index, KRef value) { + if (static_cast(index) >= obj->count_) { + ThrowArrayIndexOutOfBoundsException(); + } + *ArrayAddressOfElementAt(obj, index) = value; +} + +ArrayHeader* Kotlin_Array_clone(const ArrayHeader* array) { + ArrayHeader* result = ArrayContainer( + array->type_info(), array->count_).GetPlace(); + memcpy( + ArrayAddressOfElementAt(result, 0), + ArrayAddressOfElementAt(array, 0), + ArrayDataSizeBytes(array)); + return result; +} + +KInt Kotlin_Array_getArrayLength(const ArrayHeader* array) { + return array->count_; +} + +// Arrays.kt +KByte Kotlin_ByteArray_get(const ArrayHeader* obj, KInt index) { + if (static_cast(index) >= obj->count_) { + ThrowArrayIndexOutOfBoundsException(); + } + return *ByteArrayAddressOfElementAt(obj, index); +} + +void Kotlin_ByteArray_set(ArrayHeader* obj, KInt index, KByte value) { + if (static_cast(index) >= obj->count_) { + ThrowArrayIndexOutOfBoundsException(); + } + *ByteArrayAddressOfElementAt(obj, index) = value; +} + +ArrayHeader* Kotlin_ByteArray_clone(const ArrayHeader* array) { + ArrayHeader* result = ArrayContainer( + theByteArrayTypeInfo, array->count_).GetPlace(); + memcpy( + ByteArrayAddressOfElementAt(result, 0), + ByteArrayAddressOfElementAt(array, 0), + ArrayDataSizeBytes(array)); + return result; +} + +KInt Kotlin_ByteArray_getArrayLength(const ArrayHeader* array) { + return array->count_; +} + +KChar Kotlin_CharArray_get(const ArrayHeader* obj, KInt index) { + if (static_cast(index) >= obj->count_) { + ThrowArrayIndexOutOfBoundsException(); + } + return *PrimitiveArrayAddressOfElementAt(obj, index); +} + +void Kotlin_CharArray_set(ArrayHeader* obj, KInt index, KChar value) { + if (static_cast(index) >= obj->count_) { + ThrowArrayIndexOutOfBoundsException(); + } + *PrimitiveArrayAddressOfElementAt(obj, index) = value; +} + +ArrayHeader* Kotlin_CharArray_clone(const ArrayHeader* array) { + ArrayHeader* result = ArrayContainer( + theCharArrayTypeInfo, array->count_).GetPlace(); + memcpy( + ByteArrayAddressOfElementAt(result, 0), + ByteArrayAddressOfElementAt(array, 0), + ArrayDataSizeBytes(array)); + return result; +} + +KInt Kotlin_CharArray_getArrayLength(const ArrayHeader* array) { + return array->count_; +} + +KShort Kotlin_ShortArray_get(const ArrayHeader* obj, KInt index) { + if (static_cast(index) >= obj->count_) { + ThrowArrayIndexOutOfBoundsException(); + } + return *PrimitiveArrayAddressOfElementAt(obj, index); +} + +void Kotlin_ShortArray_set(ArrayHeader* obj, KInt index, KShort value) { + if (static_cast(index) >= obj->count_) { + ThrowArrayIndexOutOfBoundsException(); + } + *PrimitiveArrayAddressOfElementAt(obj, index) = value; +} + +ArrayHeader* Kotlin_ShortArray_clone(const ArrayHeader* array) { + ArrayHeader* result = ArrayContainer( + theShortArrayTypeInfo, array->count_).GetPlace(); + memcpy( + ByteArrayAddressOfElementAt(result, 0), + ByteArrayAddressOfElementAt(array, 0), + ArrayDataSizeBytes(array)); + return result; +} + +KInt Kotlin_ShortArray_getArrayLength(const ArrayHeader* array) { + return array->count_; +} + +KInt Kotlin_IntArray_get(const ArrayHeader* obj, KInt index) { + if (static_cast(index) >= obj->count_) { + ThrowArrayIndexOutOfBoundsException(); + } + return *PrimitiveArrayAddressOfElementAt(obj, index); +} + +void Kotlin_IntArray_set(ArrayHeader* obj, KInt index, KInt value) { + if (static_cast(index) >= obj->count_) { + ThrowArrayIndexOutOfBoundsException(); + } + *PrimitiveArrayAddressOfElementAt(obj, index) = value; +} + +ArrayHeader* Kotlin_IntArray_clone(const ArrayHeader* array) { + ArrayHeader* result = ArrayContainer( + theIntArrayTypeInfo, array->count_).GetPlace(); + memcpy( + ByteArrayAddressOfElementAt(result, 0), + ByteArrayAddressOfElementAt(array, 0), + ArrayDataSizeBytes(array)); + return result; +} + +KInt Kotlin_IntArray_getArrayLength(const ArrayHeader* array) { + return array->count_; +} + +KLong Kotlin_LongArray_get(const ArrayHeader* obj, KInt index) { + if (static_cast(index) >= obj->count_) { + ThrowArrayIndexOutOfBoundsException(); + } + return *PrimitiveArrayAddressOfElementAt(obj, index); +} + +void Kotlin_LongArray_set(ArrayHeader* obj, KInt index, KLong value) { + if (static_cast(index) >= obj->count_) { + ThrowArrayIndexOutOfBoundsException(); + } + *PrimitiveArrayAddressOfElementAt(obj, index) = value; +} + +ArrayHeader* Kotlin_LongArray_clone(const ArrayHeader* array) { + ArrayHeader* result = ArrayContainer( + theLongArrayTypeInfo, array->count_).GetPlace(); + memcpy( + ByteArrayAddressOfElementAt(result, 0), + ByteArrayAddressOfElementAt(array, 0), + ArrayDataSizeBytes(array)); + return result; +} + +KInt Kotlin_LongArray_getArrayLength(const ArrayHeader* array) { + return array->count_; +} + +KFloat Kotlin_FloatArray_get(const ArrayHeader* obj, KInt index) { + if (static_cast(index) >= obj->count_) { + ThrowArrayIndexOutOfBoundsException(); + } + return *PrimitiveArrayAddressOfElementAt(obj, index); +} + +void Kotlin_FloatArray_set(ArrayHeader* obj, KInt index, KFloat value) { + if (static_cast(index) >= obj->count_) { + ThrowArrayIndexOutOfBoundsException(); + } + *PrimitiveArrayAddressOfElementAt(obj, index) = value; +} + +ArrayHeader* Kotlin_FloatArray_clone(const ArrayHeader* array) { + ArrayHeader* result = ArrayContainer( + theFloatArrayTypeInfo, array->count_).GetPlace(); + memcpy( + ByteArrayAddressOfElementAt(result, 0), + ByteArrayAddressOfElementAt(array, 0), + ArrayDataSizeBytes(array)); + return result; +} + +KInt Kotlin_FloatArray_getArrayLength(const ArrayHeader* array) { + return array->count_; +} + +KDouble Kotlin_DoubleArray_get(const ArrayHeader* obj, KInt index) { + if (static_cast(index) >= obj->count_) { + ThrowArrayIndexOutOfBoundsException(); + } + return *PrimitiveArrayAddressOfElementAt(obj, index); +} + +void Kotlin_DoubleArray_set(ArrayHeader* obj, KInt index, KDouble value) { + if (static_cast(index) >= obj->count_) { + ThrowArrayIndexOutOfBoundsException(); + } + *PrimitiveArrayAddressOfElementAt(obj, index) = value; +} + +ArrayHeader* Kotlin_DoubleArray_clone(const ArrayHeader* array) { + ArrayHeader* result = ArrayContainer( + theDoubleArrayTypeInfo, array->count_).GetPlace(); + memcpy( + ByteArrayAddressOfElementAt(result, 0), + ByteArrayAddressOfElementAt(array, 0), + ArrayDataSizeBytes(array)); + return result; +} + +KInt Kotlin_DoubleArray_getArrayLength(const ArrayHeader* array) { + return array->count_; +} + +KBoolean Kotlin_BooleanArray_get(const ArrayHeader* obj, KInt index) { + if (static_cast(index) >= obj->count_) { + ThrowArrayIndexOutOfBoundsException(); + } + return *PrimitiveArrayAddressOfElementAt(obj, index); +} + +void Kotlin_BooleanArray_set(ArrayHeader* obj, KInt index, KBoolean value) { + if (static_cast(index) >= obj->count_) { + ThrowArrayIndexOutOfBoundsException(); + } + *PrimitiveArrayAddressOfElementAt(obj, index) = value; +} + +ArrayHeader* Kotlin_BooleanArray_clone(const ArrayHeader* array) { + ArrayHeader* result = ArrayContainer( + theBooleanArrayTypeInfo, array->count_).GetPlace(); + memcpy( + ByteArrayAddressOfElementAt(result, 0), + ByteArrayAddressOfElementAt(array, 0), + ArrayDataSizeBytes(array)); + return result; +} + +KInt Kotlin_BooleanArray_getArrayLength(const ArrayHeader* array) { + return array->count_; +} + +} // extern "C" diff --git a/runtime/src/main/cpp/Memory.h b/runtime/src/main/cpp/Memory.h index 0308a636292..5ef2b88552c 100644 --- a/runtime/src/main/cpp/Memory.h +++ b/runtime/src/main/cpp/Memory.h @@ -85,12 +85,11 @@ inline void* AddressOfElementAt(ArrayHeader* obj, int32_t index) { obj->type_info()->instanceSize_ * index; } -inline uint32_t ArraySizeBytes(const ArrayHeader* obj) { +inline uint32_t ArrayDataSizeBytes(const ArrayHeader* obj) { // Instance size is negative. return -obj->type_info()->instanceSize_ * obj->count_; } - // Those two operations are implemented by translator when storing references // to objects. inline void AddRef(ContainerHeader* header) { @@ -259,7 +258,8 @@ extern "C" { void InitMemory(); void* AllocInstance(const TypeInfo* type_info, PlacementHint hint); -void* AllocArrayInstance(const TypeInfo* type_info, PlacementHint hint, uint32_t elements); +void* AllocArrayInstance( + const TypeInfo* type_info, PlacementHint hint, uint32_t elements); int IsInstance(const ObjHeader* obj, const TypeInfo* type_info); #ifdef __cplusplus diff --git a/runtime/src/main/cpp/Natives.cpp b/runtime/src/main/cpp/Natives.cpp index 96081000afd..b7ea086b2d2 100644 --- a/runtime/src/main/cpp/Natives.cpp +++ b/runtime/src/main/cpp/Natives.cpp @@ -12,7 +12,7 @@ extern "C" { // Any.kt -KBool Kotlin_Any_equals(KConstRef thiz, KConstRef other) { +KBoolean Kotlin_Any_equals(KConstRef thiz, KConstRef other) { return thiz == other; } @@ -26,120 +26,6 @@ KString Kotlin_Any_toString(KConstRef thiz) { return nullptr; } -// Arrays.kt -// TODO: those must be compiler intrinsics afterwards. -KRef Kotlin_Array_get(const ArrayHeader* obj, KInt index) { - if (static_cast(index) >= obj->count_) { - ThrowArrayIndexOutOfBoundsException(); - } - return *ArrayAddressOfElementAt(obj, index); -} - -void Kotlin_Array_set(ArrayHeader* obj, KInt index, KRef value) { - if (static_cast(index) >= obj->count_) { - ThrowArrayIndexOutOfBoundsException(); - } - *ArrayAddressOfElementAt(obj, index) = value; -} - -ArrayHeader* Kotlin_Array_clone(const ArrayHeader* array) { - uint32_t length = ArraySizeBytes(array); - ArrayHeader* result = ArrayContainer(theArrayTypeInfo, length).GetPlace(); - memcpy( - ArrayAddressOfElementAt(result, 0), - ArrayAddressOfElementAt(array, 0), - length); - return result; -} - -KInt Kotlin_Array_getArrayLength(const ArrayHeader* array) { - return array->count_; -} - -KByte Kotlin_ByteArray_get(const ArrayHeader* obj, KInt index) { - if (static_cast(index) >= obj->count_) { - ThrowArrayIndexOutOfBoundsException(); - } - return *ByteArrayAddressOfElementAt(obj, index); -} - -void Kotlin_ByteArray_set(ArrayHeader* obj, KInt index, KByte value) { - if (static_cast(index) >= obj->count_) { - ThrowArrayIndexOutOfBoundsException(); - } - *ByteArrayAddressOfElementAt(obj, index) = value; -} - -ArrayHeader* Kotlin_ByteArray_clone(const ArrayHeader* array) { - uint32_t length = ArraySizeBytes(array); - ArrayHeader* result = ArrayContainer(theByteArrayTypeInfo, length).GetPlace(); - memcpy( - ByteArrayAddressOfElementAt(result, 0), - ByteArrayAddressOfElementAt(array, 0), - length); - return result; -} - -KInt Kotlin_ByteArray_getArrayLength(const ArrayHeader* array) { - return array->count_; -} - -KChar Kotlin_CharArray_get(const ArrayHeader* obj, KInt index) { - if (static_cast(index) >= obj->count_) { - ThrowArrayIndexOutOfBoundsException(); - } - return *CharArrayAddressOfElementAt(obj, index); -} - -void Kotlin_CharArray_set(ArrayHeader* obj, KInt index, KChar value) { - if (static_cast(index) >= obj->count_) { - ThrowArrayIndexOutOfBoundsException(); - } - *CharArrayAddressOfElementAt(obj, index) = value; -} - -ArrayHeader* Kotlin_CharArray_clone(const ArrayHeader* array) { - uint32_t length = ArraySizeBytes(array); - ArrayHeader* result = ArrayContainer(theCharArrayTypeInfo, length).GetPlace(); - memcpy( - CharArrayAddressOfElementAt(result, 0), - CharArrayAddressOfElementAt(array, 0), - length); - return result; -} - -KInt Kotlin_CharArray_getArrayLength(const ArrayHeader* array) { - return array->count_; -} - -KInt Kotlin_IntArray_get(const ArrayHeader* obj, KInt index) { - if (static_cast(index) >= obj->count_) { - ThrowArrayIndexOutOfBoundsException(); - } - return *IntArrayAddressOfElementAt(obj, index); -} - -void Kotlin_IntArray_set(ArrayHeader* obj, KInt index, KInt value) { - if (static_cast(index) >= obj->count_) { - ThrowArrayIndexOutOfBoundsException(); - } - *IntArrayAddressOfElementAt(obj, index) = value; -} - -ArrayHeader* Kotlin_IntArray_clone(const ArrayHeader* array) { - uint32_t length = ArraySizeBytes(array); - ArrayHeader* result = ArrayContainer(theIntArrayTypeInfo, length).GetPlace(); - memcpy( - IntArrayAddressOfElementAt(result, 0), - IntArrayAddressOfElementAt(array, 0), - length); - return result; -} - -KInt Kotlin_IntArray_getArrayLength(const ArrayHeader* array) { - return array->count_; -} - // io/Console.kt void Kotlin_io_Console_print(KString message) { RuntimeAssert(message->type_info() == theStringTypeInfo, "Must use a string"); @@ -192,13 +78,13 @@ KInt Kotlin_String_getStringLength(KString thiz) { 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. - ArrayHeader* result = ArrayContainer(theStringTypeInfo, length).GetPlace(); + ArrayHeader* result = ArrayContainer( + theStringTypeInfo, array->count_).GetPlace(); memcpy( ByteArrayAddressOfElementAt(result, 0), ByteArrayAddressOfElementAt(array, 0), - length); + ArrayDataSizeBytes(array)); return result; } @@ -220,7 +106,7 @@ KString Kotlin_String_plusImpl(KString thiz, KString other) { return result; } -KBool Kotlin_String_equals(KString thiz, KConstRef other) { +KBoolean 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_ && diff --git a/runtime/src/main/cpp/Natives.h b/runtime/src/main/cpp/Natives.h index bda14ffcc7e..a84b8bc4215 100644 --- a/runtime/src/main/cpp/Natives.h +++ b/runtime/src/main/cpp/Natives.h @@ -4,7 +4,7 @@ #include "Memory.h" #include "Types.h" -typedef uint8_t KBool; +typedef uint8_t KBoolean; typedef uint8_t KByte; typedef uint16_t KChar; // Note that it is signed. @@ -28,21 +28,15 @@ inline const KByte* ByteArrayAddressOfElementAt( return reinterpret_cast(obj + 1) + index; } -inline KChar* CharArrayAddressOfElementAt(ArrayHeader* obj, KInt index) { - return reinterpret_cast(obj + 1) + index; +template +inline T* PrimitiveArrayAddressOfElementAt(ArrayHeader* obj, KInt index) { + return reinterpret_cast(obj + 1) + index; } -inline const KChar* CharArrayAddressOfElementAt( +template +inline const T* PrimitiveArrayAddressOfElementAt( const ArrayHeader* obj, KInt index) { - return reinterpret_cast(obj + 1) + index; -} - -inline KInt* IntArrayAddressOfElementAt(ArrayHeader* obj, KInt index) { - return reinterpret_cast(obj + 1) + index; -} - -inline const KInt* IntArrayAddressOfElementAt(const ArrayHeader* obj, KInt index) { - return reinterpret_cast(obj + 1) + index; + return reinterpret_cast(obj + 1) + index; } inline KRef* ArrayAddressOfElementAt(ArrayHeader* obj, KInt index) { @@ -58,7 +52,7 @@ extern "C" { #endif // Any.kt -KBool Kotlin_Any_equals(KConstRef thiz, KConstRef other); +KBoolean Kotlin_Any_equals(KConstRef thiz, KConstRef other); KInt Kotlin_Any_hashCode(KConstRef thiz); KString Kotlin_Any_toString(KConstRef thiz); @@ -95,7 +89,7 @@ KString Kotlin_Int_toString(KInt value); // String.kt KInt Kotlin_String_hashCode(KString thiz); -KBool Kotlin_String_equals(KString thiz, KConstRef other); +KBoolean 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); diff --git a/runtime/src/main/cpp/ToString.cpp b/runtime/src/main/cpp/ToString.cpp index 8421e96c0da..3c331e3c5c0 100644 --- a/runtime/src/main/cpp/ToString.cpp +++ b/runtime/src/main/cpp/ToString.cpp @@ -67,7 +67,7 @@ KString Kotlin_Double_toString(KDouble value) { return makeString(cstring); } -KString Kotlin_Boolean_toString(KBool value) { +KString Kotlin_Boolean_toString(KBoolean value) { return makeString(value ? "true" : "false"); } diff --git a/runtime/src/main/cpp/Types.h b/runtime/src/main/cpp/Types.h index 3a274e63af6..a712fad2bcb 100644 --- a/runtime/src/main/cpp/Types.h +++ b/runtime/src/main/cpp/Types.h @@ -9,10 +9,14 @@ extern "C" { extern const TypeInfo* theAnyTypeInfo; extern const TypeInfo* theCloneableTypeInfo; -extern const TypeInfo* theArrayTypeInfo; extern const TypeInfo* theByteArrayTypeInfo; extern const TypeInfo* theCharArrayTypeInfo; +extern const TypeInfo* theShortArrayTypeInfo; extern const TypeInfo* theIntArrayTypeInfo; +extern const TypeInfo* theLongArrayTypeInfo; +extern const TypeInfo* theFloatArrayTypeInfo; +extern const TypeInfo* theDoubleArrayTypeInfo; +extern const TypeInfo* theBooleanArrayTypeInfo; extern const TypeInfo* theStringTypeInfo; #ifdef __cplusplus diff --git a/runtime/src/main/kotlin/kotlin/Array.kt b/runtime/src/main/kotlin/kotlin/Array.kt index 5b16a6df3c7..113d191d870 100644 --- a/runtime/src/main/kotlin/kotlin/Array.kt +++ b/runtime/src/main/kotlin/kotlin/Array.kt @@ -1,9 +1,10 @@ package kotlin +// TODO: remove that, as RTTI shall be per instantiation. @ExportTypeInfo("theArrayTypeInfo") class Array : Cloneable { // Constructors are handled with compiler magic. - private constructor() {} + public constructor(@Suppress("UNUSED_PARAMETER") size: Int) {} public val size: Int get() = getArrayLength() diff --git a/runtime/src/main/kotlin/kotlin/Arrays.kt b/runtime/src/main/kotlin/kotlin/Arrays.kt index 9eb10f14d60..4a03fe51528 100644 --- a/runtime/src/main/kotlin/kotlin/Arrays.kt +++ b/runtime/src/main/kotlin/kotlin/Arrays.kt @@ -3,7 +3,7 @@ package kotlin @ExportTypeInfo("theByteArrayTypeInfo") class ByteArray : Cloneable { // Constructors are handled with compiler magic. - private constructor() {} + public constructor(@Suppress("UNUSED_PARAMETER") size: Int) {} public val size: Int get() = getArrayLength() @@ -24,7 +24,7 @@ class ByteArray : Cloneable { @ExportTypeInfo("theCharArrayTypeInfo") class CharArray : Cloneable { // Constructors are handled with the compiler magic. - private constructor() {} + public constructor(@Suppress("UNUSED_PARAMETER") size: Int) {} public val size: Int get() = getArrayLength() @@ -42,10 +42,31 @@ class CharArray : Cloneable { external private fun getArrayLength(): Int } +@ExportTypeInfo("theShortArrayTypeInfo") +class ShortArray : Cloneable { + // Constructors are handled with the compiler magic. + public constructor(@Suppress("UNUSED_PARAMETER") size: Int) {} + + public val size: Int + get() = getArrayLength() + + @SymbolName("Kotlin_ShortArray_get") + external public operator fun get(index: Int): Short + + @SymbolName("Kotlin_ShortArray_set") + external public operator fun set(index: Int, value: Short): Unit + + @SymbolName("Kotlin_ShortArray_clone") + external public override fun clone(): Any + + @SymbolName("Kotlin_ShortArray_getArrayLength") + external private fun getArrayLength(): Int +} + @ExportTypeInfo("theIntArrayTypeInfo") class IntArray : Cloneable { // Constructors are handled with the compiler magic. - private constructor() {} + public constructor(@Suppress("UNUSED_PARAMETER") size: Int) {} public val size: Int get() = getArrayLength() @@ -54,11 +75,95 @@ class IntArray : Cloneable { external public operator fun get(index: Int): Char @SymbolName("Kotlin_IntArray_set") - external public operator fun set(index: Int, value: Char): Unit + external public operator fun set(index: Int, value: Int): Unit @SymbolName("Kotlin_IntArray_clone") external public override fun clone(): Any @SymbolName("Kotlin_IntArray_getArrayLength") external private fun getArrayLength(): Int +} + +@ExportTypeInfo("theLongArrayTypeInfo") +class LongArray : Cloneable { + // Constructors are handled with the compiler magic. + public constructor(@Suppress("UNUSED_PARAMETER") size: Int) {} + + public val size: Int + get() = getArrayLength() + + @SymbolName("Kotlin_LongArray_get") + external public operator fun get(index: Int): Char + + @SymbolName("Kotlin_LongArray_set") + external public operator fun set(index: Int, value: Long): Unit + + @SymbolName("Kotlin_LongArray_clone") + external public override fun clone(): Any + + @SymbolName("Kotlin_LongArray_getArrayLength") + external private fun getArrayLength(): Int +} + +@ExportTypeInfo("theFloatArrayTypeInfo") +class FloatArray : Cloneable { + // Constructors are handled with the compiler magic. + public constructor(@Suppress("UNUSED_PARAMETER") size: Int) {} + + public val size: Int + get() = getArrayLength() + + @SymbolName("Kotlin_FloatArray_get") + external public operator fun get(index: Int): Char + + @SymbolName("Kotlin_FloatArray_set") + external public operator fun set(index: Int, value: Float): Unit + + @SymbolName("Kotlin_FloatArray_clone") + external public override fun clone(): Any + + @SymbolName("Kotlin_FloatArray_getArrayLength") + external private fun getArrayLength(): Int +} + +@ExportTypeInfo("theDoubleArrayTypeInfo") +class DoubleArray : Cloneable { + // Constructors are handled with the compiler magic. + public constructor(@Suppress("UNUSED_PARAMETER") size: Int) {} + + public val size: Int + get() = getArrayLength() + + @SymbolName("Kotlin_DoubleArray_get") + external public operator fun get(index: Int): Char + + @SymbolName("Kotlin_DoubleArray_set") + external public operator fun set(index: Int, value: Double): Unit + + @SymbolName("Kotlin_DoubleArray_clone") + external public override fun clone(): Any + + @SymbolName("Kotlin_DoubleArray_getArrayLength") + external private fun getArrayLength(): Int +} + +@ExportTypeInfo("theBooleanArrayTypeInfo") +class BooleanArray : Cloneable { + // Constructors are handled with the compiler magic. + public constructor(@Suppress("UNUSED_PARAMETER") size: Int) {} + + public val size: Int + get() = getArrayLength() + + @SymbolName("Kotlin_BooleanArray_get") + external public operator fun get(index: Int): Char + + @SymbolName("Kotlin_BooleanArray_set") + external public operator fun set(index: Int, value: Boolean): Unit + + @SymbolName("Kotlin_BooleanArray_clone") + external public override fun clone(): Any + + @SymbolName("Kotlin_BooleanArray_getArrayLength") + external private fun getArrayLength(): Int } \ No newline at end of file diff --git a/runtime/src/main/kotlin/kotlin/Primitives.kt b/runtime/src/main/kotlin/kotlin/Primitives.kt index e11f03f5e20..f6b75e34dc8 100644 --- a/runtime/src/main/kotlin/kotlin/Primitives.kt +++ b/runtime/src/main/kotlin/kotlin/Primitives.kt @@ -841,12 +841,12 @@ public class Float : Number(), Comparable { /** * A constant holding the smallest *positive* nonzero value of Float. */ - //public val MIN_VALUE: Float + //public const val MIN_VALUE: Float /** * A constant holding the largest positive finite value of Float. */ - //public val MAX_VALUE: Float + //public const val MAX_VALUE: Float /** * A constant holding the positive infinity value of Float. @@ -856,12 +856,12 @@ public class Float : Number(), Comparable { /** * A constant holding the negative infinity value of Float. */ - //public val NEGATIVE_INFINITY: Float + //public const val NEGATIVE_INFINITY: Float /** * A constant holding the "not a number" value of Float. */ - //public val NaN: Float + //public const val NaN: Float } /** @@ -1045,27 +1045,27 @@ public class Double : Number(), Comparable { /** * A constant holding the smallest *positive* nonzero value of Double. */ - //public val MIN_VALUE: Double + //public const val MIN_VALUE: Double /** * A constant holding the largest positive finite value of Double. */ - //public val MAX_VALUE: Double + //public const val MAX_VALUE: Double /** * A constant holding the positive infinity value of Double. */ - // public val POSITIVE_INFINITY: Double + // public const val POSITIVE_INFINITY: Double /** * A constant holding the negative infinity value of Double. */ - // public val NEGATIVE_INFINITY: Double + // public const val NEGATIVE_INFINITY: Double /** * A constant holding the "not a number" value of Double. */ - // public val NaN: Double + // public const val NaN: Double } /**