From 0d62143c20f4be7c1aa35f55a599e205aa6e0c19 Mon Sep 17 00:00:00 2001 From: Sergey Bogolepov <1580082+sbogolepov@users.noreply.github.com> Date: Wed, 26 Dec 2018 23:16:20 +0700 Subject: [PATCH] Move the rest of intrinsics under TypedIntrinsic annotation (#2500) * Create interface between codegen and intrinsics generator * No more @Intrinsic annotation --- .../kotlinx/cinterop/FunctionPointers.kt | 49 +- .../kotlin/kotlinx/cinterop/NativeMem.kt | 34 +- .../kotlin/kotlinx/cinterop/NativeTypes.kt | 46 +- .../kotlin/kotlinx/cinterop/NativeUtils.kt | 26 +- .../kotlin/kotlinx/cinterop/ObjectiveCImpl.kt | 2 +- .../kotlin/backend/konan/InteropUtils.kt | 23 - .../konan/descriptors/DescriptorUtils.kt | 4 - .../descriptors/LegacyDescriptorUtils.kt | 8 +- .../backend/konan/llvm/IntrinsicGenerator.kt | 168 +++++-- .../kotlin/backend/konan/llvm/IrToBitcode.kt | 73 ++- .../backend/konan/llvm/LlvmDeclarations.kt | 2 +- .../backend/konan/lower/InteropLowering.kt | 445 +++++++++--------- runtime/src/main/kotlin/kotlin/native/Blob.kt | 2 +- .../kotlin/kotlin/native/concurrent/Worker.kt | 3 + .../kotlin/native/internal/Coroutines.kt | 2 +- .../kotlin/native/internal/IntrinsicType.kt | 32 +- .../kotlin/native/internal/NativePtr.kt | 6 +- .../kotlin/native/internal/RuntimeUtils.kt | 2 +- 18 files changed, 498 insertions(+), 429 deletions(-) diff --git a/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/FunctionPointers.kt b/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/FunctionPointers.kt index 95e60c084f0..8cfa7db7f18 100644 --- a/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/FunctionPointers.kt +++ b/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/FunctionPointers.kt @@ -16,54 +16,55 @@ package kotlinx.cinterop -import kotlin.native.internal.Intrinsic +import kotlin.native.internal.TypedIntrinsic +import kotlin.native.internal.IntrinsicType import kotlin.native.internal.ExportForCompiler -@Intrinsic external operator fun CPointer R>>.invoke(): R +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(): R -@Intrinsic external operator fun CPointer R>>.invoke(p1: P1): R +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1): R -@Intrinsic external operator fun CPointer R>>.invoke(p1: P1, p2: P2): R +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2): R -@Intrinsic external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3): R +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3): R -@Intrinsic external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4): R +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4): R -@Intrinsic external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5): R +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5): R -@Intrinsic external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6): R +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6): R -@Intrinsic external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7): R +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7): R -@Intrinsic external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8): R +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8): R -@Intrinsic external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9): R +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9): R -@Intrinsic external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10): R +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10): R -@Intrinsic external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11): R +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11): R -@Intrinsic external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12): R +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12): R -@Intrinsic external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13): R +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13): R -@Intrinsic external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14): R +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14): R -@Intrinsic external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15): R +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15): R -@Intrinsic external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16): R +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16): R -@Intrinsic external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17): R +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17): R -@Intrinsic external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18): R +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18): R -@Intrinsic external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19): R +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19): R -@Intrinsic external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19, p20: P20): R +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19, p20: P20): R -@Intrinsic external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19, p20: P20, p21: P21): R +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19, p20: P20, p21: P21): R -@Intrinsic external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19, p20: P20, p21: P21, p22: P22): R +@TypedIntrinsic(IntrinsicType.INTEROP_FUNPTR_INVOKE) external operator fun CPointer R>>.invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19, p20: P20, p21: P21, p22: P22): R @ExportForCompiler private fun invokeImplUnitRet(ptr: COpaquePointer, vararg args: Any?): Unit = memScoped { diff --git a/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeMem.kt b/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeMem.kt index 71a5cc4efac..b87593f0cd9 100644 --- a/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeMem.kt +++ b/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeMem.kt @@ -26,32 +26,32 @@ internal inline val pointerSize: Int get() = getPointerSize() @PublishedApi -@TypedIntrinsic(IntrinsicType.GET_POINTER_SIZE) +@TypedIntrinsic(IntrinsicType.INTEROP_GET_POINTER_SIZE) internal external fun getPointerSize(): Int // TODO: do not use singleton because it leads to init-check on any access. @PublishedApi internal object nativeMemUtils { - @TypedIntrinsic(IntrinsicType.READ_PRIMITIVE) external fun getByte(mem: NativePointed): Byte - @TypedIntrinsic(IntrinsicType.WRITE_PRIMITIVE) external fun putByte(mem: NativePointed, value: Byte) + @TypedIntrinsic(IntrinsicType.INTEROP_READ_PRIMITIVE) external fun getByte(mem: NativePointed): Byte + @TypedIntrinsic(IntrinsicType.INTEROP_WRITE_PRIMITIVE) external fun putByte(mem: NativePointed, value: Byte) - @TypedIntrinsic(IntrinsicType.READ_PRIMITIVE) external fun getShort(mem: NativePointed): Short - @TypedIntrinsic(IntrinsicType.WRITE_PRIMITIVE) external fun putShort(mem: NativePointed, value: Short) + @TypedIntrinsic(IntrinsicType.INTEROP_READ_PRIMITIVE) external fun getShort(mem: NativePointed): Short + @TypedIntrinsic(IntrinsicType.INTEROP_WRITE_PRIMITIVE) external fun putShort(mem: NativePointed, value: Short) - @TypedIntrinsic(IntrinsicType.READ_PRIMITIVE) external fun getInt(mem: NativePointed): Int - @TypedIntrinsic(IntrinsicType.WRITE_PRIMITIVE) external fun putInt(mem: NativePointed, value: Int) + @TypedIntrinsic(IntrinsicType.INTEROP_READ_PRIMITIVE) external fun getInt(mem: NativePointed): Int + @TypedIntrinsic(IntrinsicType.INTEROP_WRITE_PRIMITIVE) external fun putInt(mem: NativePointed, value: Int) - @TypedIntrinsic(IntrinsicType.READ_PRIMITIVE) external fun getLong(mem: NativePointed): Long - @TypedIntrinsic(IntrinsicType.WRITE_PRIMITIVE) external fun putLong(mem: NativePointed, value: Long) + @TypedIntrinsic(IntrinsicType.INTEROP_READ_PRIMITIVE) external fun getLong(mem: NativePointed): Long + @TypedIntrinsic(IntrinsicType.INTEROP_WRITE_PRIMITIVE) external fun putLong(mem: NativePointed, value: Long) - @TypedIntrinsic(IntrinsicType.READ_PRIMITIVE) external fun getFloat(mem: NativePointed): Float - @TypedIntrinsic(IntrinsicType.WRITE_PRIMITIVE) external fun putFloat(mem: NativePointed, value: Float) + @TypedIntrinsic(IntrinsicType.INTEROP_READ_PRIMITIVE) external fun getFloat(mem: NativePointed): Float + @TypedIntrinsic(IntrinsicType.INTEROP_WRITE_PRIMITIVE) external fun putFloat(mem: NativePointed, value: Float) - @TypedIntrinsic(IntrinsicType.READ_PRIMITIVE) external fun getDouble(mem: NativePointed): Double - @TypedIntrinsic(IntrinsicType.WRITE_PRIMITIVE) external fun putDouble(mem: NativePointed, value: Double) + @TypedIntrinsic(IntrinsicType.INTEROP_READ_PRIMITIVE) external fun getDouble(mem: NativePointed): Double + @TypedIntrinsic(IntrinsicType.INTEROP_WRITE_PRIMITIVE) external fun putDouble(mem: NativePointed, value: Double) - @TypedIntrinsic(IntrinsicType.READ_PRIMITIVE) external fun getNativePtr(mem: NativePointed): NativePtr - @TypedIntrinsic(IntrinsicType.WRITE_PRIMITIVE) external fun putNativePtr(mem: NativePointed, value: NativePtr) + @TypedIntrinsic(IntrinsicType.INTEROP_READ_PRIMITIVE) external fun getNativePtr(mem: NativePointed): NativePtr + @TypedIntrinsic(IntrinsicType.INTEROP_WRITE_PRIMITIVE) external fun putNativePtr(mem: NativePointed, value: NativePtr) // TODO: optimize fun getByteArray(source: NativePointed, dest: ByteArray, length: Int) { @@ -154,7 +154,7 @@ private external fun malloc(size: Long, align: Int): NativePtr @SymbolName("Kotlin_interop_free") private external fun cfree(ptr: NativePtr) -@TypedIntrinsic(IntrinsicType.READ_BITS) +@TypedIntrinsic(IntrinsicType.INTEROP_READ_BITS) external fun readBits(ptr: NativePtr, offset: Long, size: Int, signed: Boolean): Long -@TypedIntrinsic(IntrinsicType.WRITE_BITS) +@TypedIntrinsic(IntrinsicType.INTEROP_WRITE_BITS) external fun writeBits(ptr: NativePtr, offset: Long, size: Int, value: Long) \ No newline at end of file diff --git a/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeTypes.kt b/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeTypes.kt index feafdefea42..3e4cf9b9667 100644 --- a/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeTypes.kt +++ b/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeTypes.kt @@ -62,48 +62,48 @@ internal fun CPointer<*>.cPointerToString() = "CPointer(raw=$rawValue)" * @param function must be *static*, i.e. an (unbound) reference to a Kotlin function or * a closure which doesn't capture any variable */ -@Intrinsic external fun staticCFunction(@VolatileLambda function: () -> R): CPointer R>> +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: () -> R): CPointer R>> -@Intrinsic external fun staticCFunction(@VolatileLambda function: (P1) -> R): CPointer R>> +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1) -> R): CPointer R>> -@Intrinsic external fun staticCFunction(@VolatileLambda function: (P1, P2) -> R): CPointer R>> +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2) -> R): CPointer R>> -@Intrinsic external fun staticCFunction(@VolatileLambda function: (P1, P2, P3) -> R): CPointer R>> +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3) -> R): CPointer R>> -@Intrinsic external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4) -> R): CPointer R>> +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4) -> R): CPointer R>> -@Intrinsic external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5) -> R): CPointer R>> +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5) -> R): CPointer R>> -@Intrinsic external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6) -> R): CPointer R>> +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6) -> R): CPointer R>> -@Intrinsic external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7) -> R): CPointer R>> +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7) -> R): CPointer R>> -@Intrinsic external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8) -> R): CPointer R>> +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8) -> R): CPointer R>> -@Intrinsic external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9) -> R): CPointer R>> +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9) -> R): CPointer R>> -@Intrinsic external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) -> R): CPointer R>> +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) -> R): CPointer R>> -@Intrinsic external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11) -> R): CPointer R>> +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11) -> R): CPointer R>> -@Intrinsic external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12) -> R): CPointer R>> +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12) -> R): CPointer R>> -@Intrinsic external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13) -> R): CPointer R>> +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13) -> R): CPointer R>> -@Intrinsic external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14) -> R): CPointer R>> +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14) -> R): CPointer R>> -@Intrinsic external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15) -> R): CPointer R>> +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15) -> R): CPointer R>> -@Intrinsic external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16) -> R): CPointer R>> +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16) -> R): CPointer R>> -@Intrinsic external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17) -> R): CPointer R>> +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17) -> R): CPointer R>> -@Intrinsic external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18) -> R): CPointer R>> +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18) -> R): CPointer R>> -@Intrinsic external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19) -> R): CPointer R>> +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19) -> R): CPointer R>> -@Intrinsic external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20) -> R): CPointer R>> +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20) -> R): CPointer R>> -@Intrinsic external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21) -> R): CPointer R>> +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21) -> R): CPointer R>> -@Intrinsic external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22) -> R): CPointer R>> \ No newline at end of file +@TypedIntrinsic(IntrinsicType.INTEROP_STATIC_C_FUNCTION) external fun staticCFunction(@VolatileLambda function: (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22) -> R): CPointer R>> \ No newline at end of file diff --git a/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeUtils.kt b/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeUtils.kt index b3df9278281..04e7c8806ab 100644 --- a/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeUtils.kt +++ b/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeUtils.kt @@ -17,33 +17,35 @@ package kotlinx.cinterop import kotlin.native.internal.Intrinsic +import kotlin.native.internal.TypedIntrinsic +import kotlin.native.internal.IntrinsicType internal fun decodeFromUtf8(bytes: ByteArray): String = bytes.stringFromUtf8() fun encodeToUtf8(str: String): ByteArray = str.toUtf8() -@Intrinsic +@TypedIntrinsic(IntrinsicType.INTEROP_BITS_TO_FLOAT) external fun bitsToFloat(bits: Int): Float -@Intrinsic +@TypedIntrinsic(IntrinsicType.INTEROP_BITS_TO_DOUBLE) external fun bitsToDouble(bits: Long): Double // TODO: deprecate. -@Intrinsic +@TypedIntrinsic(IntrinsicType.INTEROP_SIGN_EXTEND) external fun Number.signExtend(): R // TODO: deprecate. -@Intrinsic +@TypedIntrinsic(IntrinsicType.INTEROP_NARROW) external fun Number.narrow(): R -@Intrinsic external fun Byte.convert(): R -@Intrinsic external fun Short.convert(): R -@Intrinsic external fun Int.convert(): R -@Intrinsic external fun Long.convert(): R -@Intrinsic external fun UByte.convert(): R -@Intrinsic external fun UShort.convert(): R -@Intrinsic external fun UInt.convert(): R -@Intrinsic external fun ULong.convert(): R +@TypedIntrinsic(IntrinsicType.INTEROP_CONVERT) external fun Byte.convert(): R +@TypedIntrinsic(IntrinsicType.INTEROP_CONVERT) external fun Short.convert(): R +@TypedIntrinsic(IntrinsicType.INTEROP_CONVERT) external fun Int.convert(): R +@TypedIntrinsic(IntrinsicType.INTEROP_CONVERT) external fun Long.convert(): R +@TypedIntrinsic(IntrinsicType.INTEROP_CONVERT) external fun UByte.convert(): R +@TypedIntrinsic(IntrinsicType.INTEROP_CONVERT) external fun UShort.convert(): R +@TypedIntrinsic(IntrinsicType.INTEROP_CONVERT) external fun UInt.convert(): R +@TypedIntrinsic(IntrinsicType.INTEROP_CONVERT) external fun ULong.convert(): R @Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER, AnnotationTarget.FILE) @Retention(AnnotationRetention.SOURCE) diff --git a/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/ObjectiveCImpl.kt b/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/ObjectiveCImpl.kt index 79015a7a519..746fb19f07c 100644 --- a/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/ObjectiveCImpl.kt +++ b/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/ObjectiveCImpl.kt @@ -44,7 +44,7 @@ fun optional(): Nothing = throw RuntimeException("Do not call me!!!") "Add @OverrideInit to constructor to make it override Objective-C initializer", level = DeprecationLevel.WARNING ) -@kotlin.native.internal.Intrinsic +@TypedIntrinsic(IntrinsicType.OBJC_INIT_BY) external fun T.initBy(constructorCall: T): T @kotlin.native.internal.ExportForCompiler diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt index 222efce93ab..539605f9e13 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt @@ -54,33 +54,10 @@ internal class InteropBuiltIns(builtIns: KonanBuiltIns, vararg konanPrimitives: val typeOf = packageScope.getContributedFunctions("typeOf").single() - val bitsToFloat = packageScope.getContributedFunctions("bitsToFloat").single() - - val bitsToDouble = packageScope.getContributedFunctions("bitsToDouble").single() - - val staticCFunction = packageScope.getContributedFunctions("staticCFunction").toSet() - val concurrentPackageScope = builtIns.builtInsModule.getPackage(FqName("kotlin.native.concurrent")).memberScope - val executeFunction = concurrentPackageScope.getContributedClass("Worker") - .unsubstitutedMemberScope.getContributedFunctions("execute").single() - val executeImplFunction = concurrentPackageScope.getContributedFunctions("executeImpl").single() - val signExtend = packageScope.getContributedFunctions("signExtend").single() - - val narrow = packageScope.getContributedFunctions("narrow").single() - - val convert = packageScope.getContributedFunctions("convert").toSet() - - val cFunctionPointerInvokes = packageScope.getContributedFunctions(OperatorNameConventions.INVOKE.asString()) - .filter { - val extensionReceiverParameter = it.extensionReceiverParameter - it.isOperator && - extensionReceiverParameter != null && - TypeUtils.getClassDescriptor(extensionReceiverParameter.type) == cPointer - }.toSet() - private fun KonanBuiltIns.getUnsignedClass(unsignedType: UnsignedType): ClassDescriptor = this.builtInsModule.findClassAcrossModuleDependencies(unsignedType.classId)!! diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt index 511507a928f..2e35d37380d 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt @@ -76,10 +76,6 @@ internal fun IrSimpleFunction.resolveFakeOverride(): IrSimpleFunction { } // TODO: don't forget to remove descriptor access here. -internal val FunctionDescriptor.isIntrinsic: Boolean - get() = this.descriptor.isIntrinsic - -// TODO: Merge with `isIntrinsic` internal val FunctionDescriptor.isTypedIntrinsic: Boolean get() = this.descriptor.isTypedIntrinsic diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/LegacyDescriptorUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/LegacyDescriptorUtils.kt index 0f05f75d929..7a0afc0b6ad 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/LegacyDescriptorUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/LegacyDescriptorUtils.kt @@ -240,7 +240,6 @@ fun CallableMemberDescriptor.findSourceFile(): SourceFile { } internal val TypedIntrinsic = FqName("kotlin.native.internal.TypedIntrinsic") -private val intrinsicAnnotation = FqName("kotlin.native.internal.Intrinsic") private val symbolNameAnnotation = FqName("kotlin.native.SymbolName") private val objCMethodAnnotation = FqName("kotlinx.cinterop.ObjCMethod") private val frozenAnnotation = FqName("kotlin.native.internal.Frozen") @@ -251,9 +250,6 @@ internal val DeclarationDescriptor.isFrozen: Boolean // RTTI is used for non-reference type box or Objective-C object wrapper: && (!this.defaultType.binaryTypeIsReference() || this.isObjCClass())) -internal val FunctionDescriptor.isIntrinsic: Boolean - get() = this.annotations.hasAnnotation(intrinsicAnnotation) - internal val FunctionDescriptor.isTypedIntrinsic: Boolean get() = this.annotations.hasAnnotation(TypedIntrinsic) @@ -269,11 +265,9 @@ fun CallableMemberDescriptor.externalSymbolOrThrow(): String? { this.annotations.findAnnotation(symbolNameAnnotation)?.let { return getAnnotationValue(it)!! } - if (this.annotations.hasAnnotation(intrinsicAnnotation)) return null - if (this.annotations.hasAnnotation(objCMethodAnnotation)) return null if (this.annotations.hasAnnotation(TypedIntrinsic)) return null - throw Error("external function ${this} must have @TypedIntrinsic, @SymbolName, @Intrinsic or @ObjCMethod annotation") + throw Error("external function ${this} must have @TypedIntrinsic, @SymbolName or @ObjCMethod annotation") } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt index bde38762e5b..c8715c866ea 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt @@ -3,15 +3,16 @@ package org.jetbrains.kotlin.backend.konan.llvm import kotlinx.cinterop.cValuesOf import llvm.* import org.jetbrains.kotlin.backend.konan.descriptors.TypedIntrinsic +import org.jetbrains.kotlin.backend.konan.descriptors.isTypedIntrinsic import org.jetbrains.kotlin.backend.konan.reportCompilationError import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.expressions.IrCall -import org.jetbrains.kotlin.ir.expressions.IrVararg -import org.jetbrains.kotlin.ir.expressions.getTypeArgument +import org.jetbrains.kotlin.ir.declarations.IrConstructor +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.types.getClass import org.jetbrains.kotlin.name.Name -private enum class IntrinsicType { +internal enum class IntrinsicType { PLUS, MINUS, TIMES, @@ -49,46 +50,123 @@ private enum class IntrinsicType { OBJC_GET_MESSENGER_STRET, OBJC_GET_OBJC_CLASS, OBJC_GET_RECEIVER_OR_SUPER, + OBJC_INIT_BY, // Other GET_CLASS_TYPE_INFO, - READ_BITS, - WRITE_BITS, CREATE_UNINITIALIZED_INSTANCE, LIST_OF_INTERNAL, IDENTITY, + IMMUTABLE_BLOB, + INIT_INSTANCE, + // Coroutines GET_CONTINUATION, + RETURN_IF_SUSPEND, // Interop - READ_PRIMITIVE, - WRITE_PRIMITIVE, - GET_POINTER_SIZE, - NATIVE_PTR_TO_LONG, - NATIVE_PTR_PLUS_LONG, - GET_NATIVE_NULL_PTR + INTEROP_READ_BITS, + INTEROP_WRITE_BITS, + INTEROP_READ_PRIMITIVE, + INTEROP_WRITE_PRIMITIVE, + INTEROP_GET_POINTER_SIZE, + INTEROP_NATIVE_PTR_TO_LONG, + INTEROP_NATIVE_PTR_PLUS_LONG, + INTEROP_GET_NATIVE_NULL_PTR, + INTEROP_CONVERT, + INTEROP_BITS_TO_FLOAT, + INTEROP_BITS_TO_DOUBLE, + INTEROP_SIGN_EXTEND, + INTEROP_NARROW, + INTEROP_STATIC_C_FUNCTION, + INTEROP_FUNPTR_INVOKE, + // Worker + WORKER_EXECUTE } -internal class IntrinsicGenerator(private val codegen: CodeGenerator, - private val lifetimeCalculator: (IrElement) -> Lifetime, - private val continuationProvider: () -> LLVMValueRef, - private val exceptionHandlerProvider: () -> ExceptionHandler) { +// Explicit and single interface between Intrinsic Generator and IrToBitcode. +internal interface IntrinsicGeneratorEnvironment { + + val codegen: CodeGenerator + + val functionGenerationContext: FunctionGenerationContext + + val continuation: LLVMValueRef + + val exceptionHandler: ExceptionHandler + + fun calculateLifetime(element: IrElement): Lifetime + + fun evaluateCall(function: IrFunction, args: List, resultLifetime: Lifetime): LLVMValueRef + + fun evaluateExplicitArgs(expression: IrMemberAccessExpression): List + + fun evaluateExpression(value: IrExpression): LLVMValueRef +} + +internal fun tryGetIntrinsicType(callSite: IrFunctionAccessExpression): IntrinsicType? = + if (callSite.symbol.owner.isTypedIntrinsic) getIntrinsicType(callSite) else null + +private fun getIntrinsicType(callSite: IrFunctionAccessExpression): IntrinsicType { + val function = callSite.symbol.owner + val annotation = function.descriptor.annotations.findAnnotation(TypedIntrinsic)!! + val value = annotation.allValueArguments.getValue(Name.identifier("kind")).value as String + return IntrinsicType.valueOf(value) +} + +internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnvironment) { + + private val codegen = environment.codegen private val context = codegen.context private val IrCall.llvmReturnType: LLVMTypeRef get() = LLVMGetReturnType(codegen.getLlvmFunctionType(symbol.owner))!! - private fun getIntrinsicType(callSite: IrCall): IntrinsicType { + /** + * Some intrinsics have to be processed before evaluation of their arguments. + * So this method looks at [callSite] and if it is call to "special" intrinsic + * processes it. Otherwise it returns null. + */ + fun tryEvaluateSpecialCall(callSite: IrFunctionAccessExpression): LLVMValueRef? { val function = callSite.symbol.owner - val annotation = function.descriptor.annotations.findAnnotation(TypedIntrinsic)!! - val value = annotation.allValueArguments[Name.identifier("kind")]!!.value as String - return IntrinsicType.valueOf(value) + if (!function.isTypedIntrinsic) { + return null + } + val intrinsicType = getIntrinsicType(callSite) + return when (intrinsicType) { + IntrinsicType.IMMUTABLE_BLOB -> { + @Suppress("UNCHECKED_CAST") + val arg = callSite.getValueArgument(0) as IrConst + context.llvm.staticData.createImmutableBlob(arg) + } + IntrinsicType.OBJC_INIT_BY -> { + val receiver = environment.evaluateExpression(callSite.extensionReceiver!!) + val irConstructorCall = callSite.getValueArgument(0) as IrCall + val constructorDescriptor = irConstructorCall.symbol.owner as IrConstructor + val constructorArgs = environment.evaluateExplicitArgs(irConstructorCall) + val args = listOf(receiver) + constructorArgs + environment.evaluateCall(constructorDescriptor, args, Lifetime.IRRELEVANT) + receiver + } + IntrinsicType.INIT_INSTANCE -> { + val callee = callSite as IrCall + val initializer = callee.getValueArgument(1) as IrCall + val thiz = environment.evaluateExpression(callee.getValueArgument(0)!!) + environment.evaluateCall( + initializer.symbol.owner, + listOf(thiz) + environment.evaluateExplicitArgs(initializer), + environment.calculateLifetime(initializer) + ) + codegen.theUnitInstanceRef.llvm + } + else -> null + } } - fun evaluateCall(callSite: IrCall, args: List, generationContext: FunctionGenerationContext): LLVMValueRef = - generationContext.evaluateCall(callSite, args) + fun evaluateCall(callSite: IrCall, args: List): LLVMValueRef = + environment.functionGenerationContext.evaluateCall(callSite, args) // Assuming that we checked for `TypedIntrinsic` annotation presence. private fun FunctionGenerationContext.evaluateCall(callSite: IrCall, args: List): LLVMValueRef = - when (getIntrinsicType(callSite)) { + when (val intrinsicType = getIntrinsicType(callSite)) { IntrinsicType.PLUS -> emitPlus(args) IntrinsicType.MINUS -> emitMinus(args) IntrinsicType.TIMES -> emitTimes(args) @@ -126,22 +204,42 @@ internal class IntrinsicGenerator(private val codegen: CodeGenerator, IntrinsicType.OBJC_GET_OBJC_CLASS -> emitGetObjCClass(callSite) IntrinsicType.OBJC_GET_RECEIVER_OR_SUPER -> emitGetReceiverOrSuper(args) IntrinsicType.GET_CLASS_TYPE_INFO -> emitGetClassTypeInfo(callSite) - IntrinsicType.READ_BITS -> emitReadBits(args) - IntrinsicType.WRITE_BITS -> emitWriteBits(args) - IntrinsicType.READ_PRIMITIVE -> emitReadPrimitive(callSite, args) - IntrinsicType.WRITE_PRIMITIVE -> emitWritePrimitive(callSite, args) - IntrinsicType.GET_POINTER_SIZE -> emitGetPointerSize() + IntrinsicType.INTEROP_READ_BITS -> emitReadBits(args) + IntrinsicType.INTEROP_WRITE_BITS -> emitWriteBits(args) + IntrinsicType.INTEROP_READ_PRIMITIVE -> emitReadPrimitive(callSite, args) + IntrinsicType.INTEROP_WRITE_PRIMITIVE -> emitWritePrimitive(callSite, args) + IntrinsicType.INTEROP_GET_POINTER_SIZE -> emitGetPointerSize() IntrinsicType.CREATE_UNINITIALIZED_INSTANCE -> emitCreateUninitializedInstance(callSite) - IntrinsicType.NATIVE_PTR_TO_LONG -> emitNativePtrToLong(callSite, args) - IntrinsicType.NATIVE_PTR_PLUS_LONG -> emitNativePtrPlusLong(args) - IntrinsicType.GET_NATIVE_NULL_PTR -> emitGetNativeNullPtr() + IntrinsicType.INTEROP_NATIVE_PTR_TO_LONG -> emitNativePtrToLong(callSite, args) + IntrinsicType.INTEROP_NATIVE_PTR_PLUS_LONG -> emitNativePtrPlusLong(args) + IntrinsicType.INTEROP_GET_NATIVE_NULL_PTR -> emitGetNativeNullPtr() IntrinsicType.LIST_OF_INTERNAL -> emitListOfInternal(callSite, args) IntrinsicType.IDENTITY -> emitIdentity(args) IntrinsicType.GET_CONTINUATION -> emitGetContinuation() + IntrinsicType.RETURN_IF_SUSPEND, + IntrinsicType.INTEROP_BITS_TO_FLOAT, + IntrinsicType.INTEROP_BITS_TO_DOUBLE, + IntrinsicType.INTEROP_SIGN_EXTEND, + IntrinsicType.INTEROP_NARROW, + IntrinsicType.INTEROP_STATIC_C_FUNCTION, + IntrinsicType.INTEROP_FUNPTR_INVOKE, + IntrinsicType.INTEROP_CONVERT, + IntrinsicType.WORKER_EXECUTE -> + reportNonLoweredIntrinsic(intrinsicType) + IntrinsicType.INIT_INSTANCE, + IntrinsicType.OBJC_INIT_BY, + IntrinsicType.IMMUTABLE_BLOB -> + reportSpecialIntrinsic(intrinsicType) } + private fun reportSpecialIntrinsic(intrinsicType: IntrinsicType): Nothing = + context.reportCompilationError("$intrinsicType should be handled by `tryEvaluateSpecialCall`") + + private fun reportNonLoweredIntrinsic(intrinsicType: IntrinsicType): Nothing = + context.reportCompilationError("Intrinsic of type $intrinsicType should be handled by previos lowering phase") + private fun FunctionGenerationContext.emitGetContinuation(): LLVMValueRef = - continuationProvider() + environment.continuation private fun FunctionGenerationContext.emitIdentity(args: List): LLVMValueRef = args.single() @@ -181,7 +279,7 @@ internal class IntrinsicGenerator(private val codegen: CodeGenerator, val typeParameterT = context.ir.symbols.createUninitializedInstance.descriptor.typeParameters[0] val enumClass = callSite.getTypeArgument(typeParameterT)!! val enumIrClass = enumClass.getClass()!! - return allocInstance(enumIrClass, lifetimeCalculator(callSite)) + return allocInstance(enumIrClass, environment.calculateLifetime(callSite)) } private fun FunctionGenerationContext.emitGetPointerSize(): LLVMValueRef = @@ -320,7 +418,7 @@ internal class IntrinsicGenerator(private val codegen: CodeGenerator, private fun FunctionGenerationContext.emitGetObjCClass(callSite: IrCall): LLVMValueRef { val descriptor = callSite.descriptor.original val typeArgument = callSite.getTypeArgument(descriptor.typeParameters.single()) - return getObjCClass(typeArgument!!.getClass()!!, exceptionHandlerProvider()) + return getObjCClass(typeArgument!!.getClass()!!, environment.exceptionHandler) } private fun FunctionGenerationContext.emitObjCGetMessenger(args: List, isStret: Boolean): LLVMValueRef { @@ -477,7 +575,7 @@ internal class IntrinsicGenerator(private val codegen: CodeGenerator, private fun FunctionGenerationContext.emitThrowIfZero(divider: LLVMValueRef) { ifThen(icmpEq(divider, Zero(divider.type).llvm)) { val throwArithExc = codegen.llvmFunction(context.ir.symbols.throwArithmeticException.owner) - call(throwArithExc, emptyList(), Lifetime.GLOBAL, exceptionHandlerProvider()) + call(throwArithExc, emptyList(), Lifetime.GLOBAL, environment.exceptionHandler) unreachable() } } 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 072b1e51817..61fdc79803b 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 @@ -40,7 +40,6 @@ import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.konan.target.CompilerOutputKind import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.descriptorUtil.classId -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe private val threadLocalAnnotationFqName = FqName("kotlin.native.ThreadLocal") private val sharedAnnotationFqName = FqName("kotlin.native.SharedImmutable") @@ -297,9 +296,33 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map, resultLifetime: Lifetime): LLVMValueRef = + evaluateSimpleFunctionCall(function, args, resultLifetime) + + override fun evaluateExplicitArgs(expression: IrMemberAccessExpression): List = + this@CodeGeneratorVisitor.evaluateExplicitArgs(expression) + + override fun evaluateExpression(value: IrExpression): LLVMValueRef = + this@CodeGeneratorVisitor.evaluateExpression(value) + } + + private val intrinsicGenerator = IntrinsicGenerator(intrinsicGeneratorEnvironment) /** * Fake [CodeContext] that doesn't support any operation. @@ -1803,50 +1826,11 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map { - val receiver = evaluateExpression(expression.extensionReceiver!!) - val irConstructorCall = expression.getValueArgument(0) as IrCall - val constructorDescriptor = irConstructorCall.symbol.owner as ClassConstructorDescriptor - val constructorArgs = evaluateExplicitArgs(irConstructorCall) - val args = listOf(receiver) + constructorArgs - callDirect(constructorDescriptor, args, Lifetime.IRRELEVANT) - return receiver - } - - context.immutableBlobOf -> { - @Suppress("UNCHECKED_CAST") - val arg = expression.getValueArgument(0) as IrConst - return context.llvm.staticData.createImmutableBlob(arg) - } - - context.ir.symbols.initInstance.descriptor -> { - val callee = expression as IrCall - val initializer = callee.getValueArgument(1) as IrCall - val thiz = evaluateExpression(callee.getValueArgument(0)!!) - evaluateSimpleFunctionCall( - initializer.symbol.owner, - listOf(thiz) + evaluateExplicitArgs(initializer), - resultLifetime(initializer) - ) - return codegen.theUnitInstanceRef.llvm - } - } - } - - return null - } - //-------------------------------------------------------------------------// private fun evaluateCall(value: IrFunctionAccessExpression): LLVMValueRef { context.log{"evaluateCall : ${ir2string(value)}"} - evaluateSpecialIntrinsicCall(value)?.let { return it } + intrinsicGenerator.tryEvaluateSpecialCall(value)?.let { return it } val args = evaluateExplicitArgs(value) @@ -2103,8 +2087,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map intrinsicGenerator.evaluateCall(callee, args, functionGenerationContext) - function.isIntrinsic -> context.reportCompilationError("Unexpected @Intrinsic function: ${function.name.asString()}") + function.isTypedIntrinsic -> intrinsicGenerator.evaluateCall(callee, args) function.origin == IrDeclarationOrigin.IR_BUILTINS_STUB -> evaluateOperatorCall(callee, argsWithContinuationIfNeeded) function is ConstructorDescriptor -> evaluateConstructorCall(callee, argsWithContinuationIfNeeded) else -> evaluateSimpleFunctionCall(function, argsWithContinuationIfNeeded, resultLifetime, callee.superQualifierSymbol?.owner) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt index 618b34166eb..95b182a8938 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt @@ -398,7 +398,7 @@ private class DeclarationsGeneratorVisitor(override val context: Context) : } val llvmFunction = if (descriptor.isExternal) { - if (descriptor.isTypedIntrinsic || descriptor.isIntrinsic || descriptor.isObjCBridgeBased()) { + if (descriptor.isTypedIntrinsic || descriptor.isObjCBridgeBased()) { return } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InteropLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InteropLowering.kt index 94419a4fe24..40d4c6007f1 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InteropLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InteropLowering.kt @@ -16,6 +16,8 @@ import org.jetbrains.kotlin.backend.konan.descriptors.allOverriddenDescriptors import org.jetbrains.kotlin.backend.konan.descriptors.isInterface import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName import org.jetbrains.kotlin.backend.konan.irasdescriptors.* +import org.jetbrains.kotlin.backend.konan.llvm.IntrinsicType +import org.jetbrains.kotlin.backend.konan.llvm.tryGetIntrinsicType import org.jetbrains.kotlin.builtins.UnsignedTypes import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor @@ -774,235 +776,232 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB fun reportError(message: String): Nothing = context.reportCompilationError(message, irFile, expression) + val intrinsicType = tryGetIntrinsicType(expression) + + if (intrinsicType != null) { + return when (intrinsicType) { + IntrinsicType.INTEROP_BITS_TO_FLOAT -> { + val argument = expression.getValueArgument(0) + if (argument is IrConst<*> && argument.kind == IrConstKind.Int) { + val floatValue = kotlinx.cinterop.bitsToFloat(argument.value as Int) + builder.irFloat(floatValue) + } else { + expression + } + } + IntrinsicType.INTEROP_BITS_TO_DOUBLE -> { + val argument = expression.getValueArgument(0) + if (argument is IrConst<*> && argument.kind == IrConstKind.Long) { + val doubleValue = kotlinx.cinterop.bitsToDouble(argument.value as Long) + builder.irDouble(doubleValue) + } else { + expression + } + } + IntrinsicType.INTEROP_STATIC_C_FUNCTION -> { + val irCallableReference = unwrapStaticFunctionArgument(expression.getValueArgument(0)!!) + + if (irCallableReference == null || irCallableReference.getArguments().isNotEmpty()) { + context.reportCompilationError( + "${descriptor.fqNameSafe} must take an unbound, non-capturing function or lambda", + irFile, expression + ) + // TODO: should probably be reported during analysis. + } + + val targetSymbol = irCallableReference.symbol + val target = targetSymbol.owner + val signatureTypes = target.allParameters.map { it.type } + target.returnType + + signatureTypes.forEachIndexed { index, type -> + type.ensureSupportedInCallbacks( + isReturnType = (index == signatureTypes.lastIndex), + reportError = ::reportError + ) + } + + descriptor.typeParameters.forEachIndexed { index, typeParameterDescriptor -> + val typeArgument = expression.getTypeArgument(typeParameterDescriptor)!!.toKotlinType() + val signatureType = signatureTypes[index].toKotlinType() + if (typeArgument.constructor != signatureType.constructor || + typeArgument.isMarkedNullable != signatureType.isMarkedNullable) { + context.reportCompilationError( + "C function signature element mismatch: expected '$signatureType', got '$typeArgument'", + irFile, expression + ) + } + } + + IrFunctionReferenceImpl( + builder.startOffset, builder.endOffset, + expression.type, + targetSymbol, target.descriptor, + typeArgumentsCount = 0) + } + IntrinsicType.INTEROP_FUNPTR_INVOKE -> { + // Replace by `invokeImpl${type}Ret`: + + val returnType = + expression.getTypeArgument(descriptor.typeParameters.single { it.name.asString() == "R" })!! + + returnType.checkCTypeNullability(::reportError) + + val invokeImpl = symbols.interopInvokeImpls[returnType.getClass()?.descriptor] ?: + context.reportCompilationError( + "Invocation of C function pointer with return type '${returnType.toKotlinType()}' is not supported yet", + irFile, expression + ) + + builder.irCall(invokeImpl).apply { + putValueArgument(0, expression.extensionReceiver) + + val varargParameter = invokeImpl.owner.valueParameters[1] + val varargArgument = IrVarargImpl( + startOffset, endOffset, varargParameter.type, varargParameter.varargElementType!! + ).apply { + descriptor.valueParameters.forEach { + this.addElement(expression.getValueArgument(it)!!) + } + } + putValueArgument(varargParameter.index, varargArgument) + } + } + IntrinsicType.INTEROP_SIGN_EXTEND, IntrinsicType.INTEROP_NARROW -> { + + val integerTypePredicates = arrayOf( + IrType::isByte, IrType::isShort, IrType::isInt, IrType::isLong + ) + + val receiver = expression.extensionReceiver!! + val typeOperand = expression.getSingleTypeArgument() + val kotlinTypeOperand = typeOperand.toKotlinType() + + val receiverTypeIndex = integerTypePredicates.indexOfFirst { it(receiver.type) } + val typeOperandIndex = integerTypePredicates.indexOfFirst { it(typeOperand) } + + val receiverKotlinType = receiver.type.toKotlinType() + + if (receiverTypeIndex == -1) { + context.reportCompilationError("Receiver's type $receiverKotlinType is not an integer type", + irFile, receiver) + } + + if (typeOperandIndex == -1) { + context.reportCompilationError("Type argument $kotlinTypeOperand is not an integer type", + irFile, expression) + } + + when (intrinsicType) { + IntrinsicType.INTEROP_SIGN_EXTEND -> if (receiverTypeIndex > typeOperandIndex) { + context.reportCompilationError("unable to sign extend $receiverKotlinType to $kotlinTypeOperand", + irFile, expression) + } + + IntrinsicType.INTEROP_NARROW -> if (receiverTypeIndex < typeOperandIndex) { + context.reportCompilationError("unable to narrow $receiverKotlinType to $kotlinTypeOperand", + irFile, expression) + } + + else -> throw Error() + } + + val receiverClass = symbols.integerClasses.single { + receiver.type.isSubtypeOf(it.owner.defaultType) + } + val targetClass = symbols.integerClasses.single { + typeOperand.isSubtypeOf(it.owner.defaultType) + } + + val conversionSymbol = receiverClass.functions.single { + it.descriptor.name == Name.identifier("to${targetClass.owner.name}") + } + + builder.irCall(conversionSymbol).apply { + dispatchReceiver = receiver + } + } + IntrinsicType.INTEROP_CONVERT -> { + val integerClasses = symbols.allIntegerClasses + val typeOperand = expression.getTypeArgument(0)!! + val receiverType = expression.symbol.owner.extensionReceiverParameter!!.type + val source = receiverType.classifierOrFail as IrClassSymbol + assert(source in integerClasses) + + if (typeOperand is IrSimpleType && typeOperand.classifier in integerClasses && !typeOperand.hasQuestionMark) { + val target = typeOperand.classifier as IrClassSymbol + val valueToConvert = expression.extensionReceiver!! + + if (source in symbols.signedIntegerClasses && target in symbols.unsignedIntegerClasses) { + // Default Kotlin signed-to-unsigned widening integer conversions don't follow C rules. + val signedTarget = symbols.unsignedToSignedOfSameBitWidth[target]!! + val widened = builder.irConvertInteger(source, signedTarget, valueToConvert) + builder.irConvertInteger(signedTarget, target, widened) + } else { + builder.irConvertInteger(source, target, valueToConvert) + } + } else { + context.reportCompilationError( + "unable to convert ${receiverType.toKotlinType()} to ${typeOperand.toKotlinType()}", + irFile, + expression + ) + } + } + IntrinsicType.OBJC_INIT_BY -> { + val intrinsic = interop.objCObjectInitBy.name + + val argument = expression.getValueArgument(0)!! + val constructedClass = + ((argument as? IrCall)?.descriptor as? ClassConstructorDescriptor)?.constructedClass + + if (constructedClass == null) { + context.reportCompilationError("Argument of '$intrinsic' must be a constructor call", + irFile, argument) + } + + val extensionReceiver = expression.extensionReceiver!! + if (extensionReceiver !is IrGetValue || + extensionReceiver.descriptor != constructedClass.thisAsReceiverParameter) { + + context.reportCompilationError("Receiver of '$intrinsic' must be a 'this' of the constructed class", + irFile, extensionReceiver) + } + expression + } + IntrinsicType.WORKER_EXECUTE -> { + val irCallableReference = unwrapStaticFunctionArgument(expression.getValueArgument(2)!!) + + if (irCallableReference == null || irCallableReference.getArguments().isNotEmpty()) { + context.reportCompilationError( + "${descriptor.fqNameSafe} must take an unbound, non-capturing function or lambda", + irFile, expression + ) + } + + val targetSymbol = irCallableReference.symbol + val target = targetSymbol.descriptor + val jobPointer = IrFunctionReferenceImpl( + builder.startOffset, builder.endOffset, + symbols.executeImpl.owner.valueParameters[3].type, + targetSymbol, target, + typeArgumentsCount = 0) + + builder.irCall(symbols.executeImpl).apply { + putValueArgument(0, expression.dispatchReceiver) + putValueArgument(1, expression.getValueArgument(0)) + putValueArgument(2, expression.getValueArgument(1)) + putValueArgument(3, jobPointer) + } + } + else -> expression + } + } return when (descriptor) { interop.cPointerRawValue.getter -> // Replace by the intrinsic call to be handled by code generator: builder.irCall(symbols.interopCPointerGetRawValue).apply { extensionReceiver = expression.dispatchReceiver } - - interop.bitsToFloat -> { - val argument = expression.getValueArgument(0) - if (argument is IrConst<*> && argument.kind == IrConstKind.Int) { - val floatValue = kotlinx.cinterop.bitsToFloat(argument.value as Int) - builder.irFloat(floatValue) - } else { - expression - } - } - - interop.bitsToDouble -> { - val argument = expression.getValueArgument(0) - if (argument is IrConst<*> && argument.kind == IrConstKind.Long) { - val doubleValue = kotlinx.cinterop.bitsToDouble(argument.value as Long) - builder.irDouble(doubleValue) - } else { - expression - } - } - - in interop.staticCFunction -> { - val irCallableReference = unwrapStaticFunctionArgument(expression.getValueArgument(0)!!) - - if (irCallableReference == null || irCallableReference.getArguments().isNotEmpty()) { - context.reportCompilationError( - "${descriptor.fqNameSafe} must take an unbound, non-capturing function or lambda", - irFile, expression - ) - // TODO: should probably be reported during analysis. - } - - val targetSymbol = irCallableReference.symbol - val target = targetSymbol.owner - val signatureTypes = target.allParameters.map { it.type } + target.returnType - - signatureTypes.forEachIndexed { index, type -> - type.ensureSupportedInCallbacks( - isReturnType = (index == signatureTypes.lastIndex), - reportError = ::reportError - ) - } - - descriptor.typeParameters.forEachIndexed { index, typeParameterDescriptor -> - val typeArgument = expression.getTypeArgument(typeParameterDescriptor)!!.toKotlinType() - val signatureType = signatureTypes[index].toKotlinType() - if (typeArgument.constructor != signatureType.constructor || - typeArgument.isMarkedNullable != signatureType.isMarkedNullable) { - context.reportCompilationError( - "C function signature element mismatch: expected '$signatureType', got '$typeArgument'", - irFile, expression - ) - } - } - - IrFunctionReferenceImpl( - builder.startOffset, builder.endOffset, - expression.type, - targetSymbol, target.descriptor, - typeArgumentsCount = 0) - } - - interop.executeFunction -> { - val irCallableReference = unwrapStaticFunctionArgument(expression.getValueArgument(2)!!) - - if (irCallableReference == null || irCallableReference.getArguments().isNotEmpty()) { - context.reportCompilationError( - "${descriptor.fqNameSafe} must take an unbound, non-capturing function or lambda", - irFile, expression - ) - } - - val targetSymbol = irCallableReference.symbol - val target = targetSymbol.descriptor - val jobPointer = IrFunctionReferenceImpl( - builder.startOffset, builder.endOffset, - symbols.executeImpl.owner.valueParameters[3].type, - targetSymbol, target, - typeArgumentsCount = 0) - - builder.irCall(symbols.executeImpl).apply { - putValueArgument(0, expression.dispatchReceiver) - putValueArgument(1, expression.getValueArgument(0)) - putValueArgument(2, expression.getValueArgument(1)) - putValueArgument(3, jobPointer) - } - } - - interop.signExtend, interop.narrow -> { - - val integerTypePredicates = arrayOf( - IrType::isByte, IrType::isShort, IrType::isInt, IrType::isLong - ) - - val receiver = expression.extensionReceiver!! - val typeOperand = expression.getSingleTypeArgument() - val kotlinTypeOperand = typeOperand.toKotlinType() - - val receiverTypeIndex = integerTypePredicates.indexOfFirst { it(receiver.type) } - val typeOperandIndex = integerTypePredicates.indexOfFirst { it(typeOperand) } - - val receiverKotlinType = receiver.type.toKotlinType() - - if (receiverTypeIndex == -1) { - context.reportCompilationError("Receiver's type $receiverKotlinType is not an integer type", - irFile, receiver) - } - - if (typeOperandIndex == -1) { - context.reportCompilationError("Type argument $kotlinTypeOperand is not an integer type", - irFile, expression) - } - - when (descriptor) { - interop.signExtend -> if (receiverTypeIndex > typeOperandIndex) { - context.reportCompilationError("unable to sign extend $receiverKotlinType to $kotlinTypeOperand", - irFile, expression) - } - - interop.narrow -> if (receiverTypeIndex < typeOperandIndex) { - context.reportCompilationError("unable to narrow $receiverKotlinType to $kotlinTypeOperand", - irFile, expression) - } - - else -> throw Error() - } - - val receiverClass = symbols.integerClasses.single { - receiver.type.isSubtypeOf(it.owner.defaultType) - } - val targetClass = symbols.integerClasses.single { - typeOperand.isSubtypeOf(it.owner.defaultType) - } - - val conversionSymbol = receiverClass.functions.single { - it.descriptor.name == Name.identifier("to${targetClass.owner.name}") - } - - builder.irCall(conversionSymbol).apply { - dispatchReceiver = receiver - } - } - - in interop.convert -> { - val integerClasses = symbols.allIntegerClasses - val typeOperand = expression.getTypeArgument(0)!! - val receiverType = expression.symbol.owner.extensionReceiverParameter!!.type - val source = receiverType.classifierOrFail as IrClassSymbol - assert(source in integerClasses) - - if (typeOperand is IrSimpleType && typeOperand.classifier in integerClasses && !typeOperand.hasQuestionMark) { - val target = typeOperand.classifier as IrClassSymbol - val valueToConvert = expression.extensionReceiver!! - - if (source in symbols.signedIntegerClasses && target in symbols.unsignedIntegerClasses) { - // Default Kotlin signed-to-unsigned widening integer conversions don't follow C rules. - val signedTarget = symbols.unsignedToSignedOfSameBitWidth[target]!! - val widened = builder.irConvertInteger(source, signedTarget, valueToConvert) - builder.irConvertInteger(signedTarget, target, widened) - } else { - builder.irConvertInteger(source, target, valueToConvert) - } - } else { - context.reportCompilationError( - "unable to convert ${receiverType.toKotlinType()} to ${typeOperand.toKotlinType()}", - irFile, - expression - ) - } - } - - in interop.cFunctionPointerInvokes -> { - // Replace by `invokeImpl${type}Ret`: - - val returnType = - expression.getTypeArgument(descriptor.typeParameters.single { it.name.asString() == "R" })!! - - returnType.checkCTypeNullability(::reportError) - - val invokeImpl = symbols.interopInvokeImpls[returnType.getClass()?.descriptor] ?: - context.reportCompilationError( - "Invocation of C function pointer with return type '${returnType.toKotlinType()}' is not supported yet", - irFile, expression - ) - - builder.irCall(invokeImpl).apply { - putValueArgument(0, expression.extensionReceiver) - - val varargParameter = invokeImpl.owner.valueParameters[1] - val varargArgument = IrVarargImpl( - startOffset, endOffset, varargParameter.type, varargParameter.varargElementType!! - ).apply { - descriptor.valueParameters.forEach { - this.addElement(expression.getValueArgument(it)!!) - } - } - putValueArgument(varargParameter.index, varargArgument) - } - } - - interop.objCObjectInitBy -> { - val intrinsic = interop.objCObjectInitBy.name - - val argument = expression.getValueArgument(0)!! - val constructedClass = - ((argument as? IrCall)?.descriptor as? ClassConstructorDescriptor)?.constructedClass - - if (constructedClass == null) { - context.reportCompilationError("Argument of '$intrinsic' must be a constructor call", - irFile, argument) - } - - val extensionReceiver = expression.extensionReceiver!! - if (extensionReceiver !is IrGetValue || - extensionReceiver.descriptor != constructedClass.thisAsReceiverParameter) { - - context.reportCompilationError("Receiver of '$intrinsic' must be a 'this' of the constructed class", - irFile, extensionReceiver) - } - - expression - } - else -> expression } } diff --git a/runtime/src/main/kotlin/kotlin/native/Blob.kt b/runtime/src/main/kotlin/kotlin/native/Blob.kt index 5d3d11c5bac..d62ff3a9efe 100644 --- a/runtime/src/main/kotlin/kotlin/native/Blob.kt +++ b/runtime/src/main/kotlin/kotlin/native/Blob.kt @@ -82,5 +82,5 @@ private external fun ImmutableBlob.asCPointerImpl(offset: Int): kotlin.native.in * One element still represent one byte in the output data. * This is the only way to create ImmutableBlob for now. */ -@Intrinsic +@TypedIntrinsic(IntrinsicType.IMMUTABLE_BLOB) public external fun immutableBlobOf(vararg elements: Short): ImmutableBlob diff --git a/runtime/src/main/kotlin/kotlin/native/concurrent/Worker.kt b/runtime/src/main/kotlin/kotlin/native/concurrent/Worker.kt index d0b89aa3e98..fdc28fec892 100644 --- a/runtime/src/main/kotlin/kotlin/native/concurrent/Worker.kt +++ b/runtime/src/main/kotlin/kotlin/native/concurrent/Worker.kt @@ -8,6 +8,8 @@ package kotlin.native.concurrent import kotlin.native.internal.ExportForCppRuntime import kotlin.native.internal.Frozen import kotlin.native.internal.VolatileLambda +import kotlin.native.internal.IntrinsicType +import kotlin.native.internal.TypedIntrinsic import kotlinx.cinterop.* /** @@ -69,6 +71,7 @@ public inline class Worker @PublishedApi internal constructor(val id: Int) { * @return the future with the computation result of [job] */ @Suppress("UNUSED_PARAMETER") + @TypedIntrinsic(IntrinsicType.WORKER_EXECUTE) public fun execute(mode: TransferMode, producer: () -> T1, @VolatileLambda job: (T1) -> T2): Future = /* * This function is a magical operation, handled by lowering in the compiler, and replaced with call to diff --git a/runtime/src/main/kotlin/kotlin/native/internal/Coroutines.kt b/runtime/src/main/kotlin/kotlin/native/internal/Coroutines.kt index a8ad27dff86..e15e9196bc4 100644 --- a/runtime/src/main/kotlin/kotlin/native/internal/Coroutines.kt +++ b/runtime/src/main/kotlin/kotlin/native/internal/Coroutines.kt @@ -22,6 +22,6 @@ internal external fun getContinuation(): Continuation internal inline suspend fun getCoroutineContext(): CoroutineContext = getContinuation().context -@Intrinsic +@TypedIntrinsic(IntrinsicType.RETURN_IF_SUSPEND) @PublishedApi internal external suspend fun returnIfSuspended(@Suppress("UNUSED_PARAMETER") argument: Any?): T diff --git a/runtime/src/main/kotlin/kotlin/native/internal/IntrinsicType.kt b/runtime/src/main/kotlin/kotlin/native/internal/IntrinsicType.kt index f0bccce317b..95cf76be237 100644 --- a/runtime/src/main/kotlin/kotlin/native/internal/IntrinsicType.kt +++ b/runtime/src/main/kotlin/kotlin/native/internal/IntrinsicType.kt @@ -35,27 +35,43 @@ class IntrinsicType { const val REINTERPRET = "REINTERPRET" const val ARE_EQUAL_BY_VALUE = "ARE_EQUAL_BY_VALUE" const val IEEE_754_EQUALS = "IEEE_754_EQUALS" + // ObjC related stuff const val OBJC_GET_MESSENGER = "OBJC_GET_MESSENGER" const val OBJC_GET_MESSENGER_STRET = "OBJC_GET_MESSENGER_STRET" const val OBJC_GET_OBJC_CLASS = "OBJC_GET_OBJC_CLASS" const val OBJC_GET_RECEIVER_OR_SUPER = "OBJC_GET_RECEIVER_OR_SUPER" + const val OBJC_INIT_BY = "OBJC_INIT_BY" // Other const val GET_CLASS_TYPE_INFO = "GET_CLASS_TYPE_INFO" - const val READ_BITS = "READ_BITS" - const val WRITE_BITS = "WRITE_BITS" + const val INTEROP_READ_BITS = "INTEROP_READ_BITS" + const val INTEROP_WRITE_BITS = "INTEROP_WRITE_BITS" const val CREATE_UNINITIALIZED_INSTANCE = "CREATE_UNINITIALIZED_INSTANCE" const val LIST_OF_INTERNAL = "LIST_OF_INTERNAL" const val IDENTITY = "IDENTITY" + const val IMMUTABLE_BLOB = "IMMUTABLE_BLOB" + const val INIT_INSTANCE = "INIT_INSTANCE" + const val GET_CONTINUATION = "GET_CONTINUATION" + const val RETURN_IF_SUSPEND = "RETURN_IF_SUSPEND" // Interop - const val READ_PRIMITIVE = "READ_PRIMITIVE" - const val WRITE_PRIMITIVE = "WRITE_PRIMITIVE" - const val GET_POINTER_SIZE = "GET_POINTER_SIZE" - const val NATIVE_PTR_TO_LONG = "NATIVE_PTR_TO_LONG" - const val NATIVE_PTR_PLUS_LONG = "NATIVE_PTR_PLUS_LONG" - const val GET_NATIVE_NULL_PTR = "GET_NATIVE_NULL_PTR" + const val INTEROP_READ_PRIMITIVE = "INTEROP_READ_PRIMITIVE" + const val INTEROP_WRITE_PRIMITIVE = "INTEROP_WRITE_PRIMITIVE" + const val INTEROP_GET_POINTER_SIZE = "INTEROP_GET_POINTER_SIZE" + const val INTEROP_NATIVE_PTR_TO_LONG = "INTEROP_NATIVE_PTR_TO_LONG" + const val INTEROP_NATIVE_PTR_PLUS_LONG = "INTEROP_NATIVE_PTR_PLUS_LONG" + const val INTEROP_GET_NATIVE_NULL_PTR = "INTEROP_GET_NATIVE_NULL_PTR" + const val INTEROP_CONVERT = "INTEROP_CONVERT" + const val INTEROP_BITS_TO_FLOAT = "INTEROP_BITS_TO_FLOAT" + const val INTEROP_BITS_TO_DOUBLE = "INTEROP_BITS_TO_DOUBLE" + const val INTEROP_SIGN_EXTEND = "INTEROP_SIGN_EXTEND" + const val INTEROP_NARROW = "INTEROP_NARROW" + const val INTEROP_STATIC_C_FUNCTION = "INTEROP_STATIC_C_FUNCTION" + const val INTEROP_FUNPTR_INVOKE = "INTEROP_FUNPTR_INVOKE" + + // Worker + const val WORKER_EXECUTE = "WORKER_EXECUTE" } } \ No newline at end of file diff --git a/runtime/src/main/kotlin/kotlin/native/internal/NativePtr.kt b/runtime/src/main/kotlin/kotlin/native/internal/NativePtr.kt index 5bc5c975d88..79d656cb4c4 100644 --- a/runtime/src/main/kotlin/kotlin/native/internal/NativePtr.kt +++ b/runtime/src/main/kotlin/kotlin/native/internal/NativePtr.kt @@ -7,7 +7,7 @@ package kotlin.native.internal -@TypedIntrinsic(IntrinsicType.GET_NATIVE_NULL_PTR) +@TypedIntrinsic(IntrinsicType.INTEROP_GET_NATIVE_NULL_PTR) external fun getNativeNullPtr(): NativePtr class NativePtr @PublishedApi internal constructor(private val value: NonNullNativePtr?) { @@ -15,10 +15,10 @@ class NativePtr @PublishedApi internal constructor(private val value: NonNullNat val NULL = getNativeNullPtr() } - @TypedIntrinsic(IntrinsicType.NATIVE_PTR_PLUS_LONG) + @TypedIntrinsic(IntrinsicType.INTEROP_NATIVE_PTR_PLUS_LONG) external operator fun plus(offset: Long): NativePtr - @TypedIntrinsic(IntrinsicType.NATIVE_PTR_TO_LONG) + @TypedIntrinsic(IntrinsicType.INTEROP_NATIVE_PTR_TO_LONG) external fun toLong(): Long override fun equals(other: Any?) = (other is NativePtr) && kotlin.native.internal.areEqualByValue(this, other) diff --git a/runtime/src/main/kotlin/kotlin/native/internal/RuntimeUtils.kt b/runtime/src/main/kotlin/kotlin/native/internal/RuntimeUtils.kt index e905f6a7597..8f159552c25 100644 --- a/runtime/src/main/kotlin/kotlin/native/internal/RuntimeUtils.kt +++ b/runtime/src/main/kotlin/kotlin/native/internal/RuntimeUtils.kt @@ -120,7 +120,7 @@ fun > valuesForEnum(values: Array): Array { @TypedIntrinsic(IntrinsicType.CREATE_UNINITIALIZED_INSTANCE) internal external fun createUninitializedInstance(): T -@Intrinsic +@TypedIntrinsic(IntrinsicType.INIT_INSTANCE) internal external fun initInstance(thiz: Any, constructorCall: Any): Unit fun checkProgressionStep(step: Int) = if (step > 0) step else throw IllegalArgumentException("Step must be positive, was: $step.")