diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt index 5acba6c28e6..80e54052050 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt @@ -502,6 +502,9 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) { val Kotlin_ObjCExport_createContinuationArgument by lazyRtFunction val Kotlin_ObjCExport_resumeContinuation by lazyRtFunction + private val Kotlin_ObjCExport_NSIntegerTypeProvider by lazyRtFunction + private val Kotlin_longTypeProvider by lazyRtFunction + val Kotlin_mm_safePointFunctionEpilogue by lazyRtFunction val Kotlin_mm_safePointWhileLoopBody by lazyRtFunction val Kotlin_mm_safePointExceptionUnwind by lazyRtFunction @@ -593,6 +596,26 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) { val llvmFloat = floatType val llvmDouble = doubleType val llvmVector128 = vector128Type + + private fun getSizeOfReturnTypeInBits(functionPointer: LLVMValueRef): Long { + // LLVMGetElementType is called because we need to dereference a pointer to function. + val nsIntegerType = LLVMGetReturnType(LLVMGetElementType(functionPointer.type)) + return LLVMSizeOfTypeInBits(runtime.targetData, nsIntegerType) + } + + /** + * Width of NSInteger in bits. + */ + val nsIntegerTypeWidth: Long by lazy { + getSizeOfReturnTypeInBits(Kotlin_ObjCExport_NSIntegerTypeProvider) + } + + /** + * Width of C long type in bits. + */ + val longTypeWidth: Long by lazy { + getSizeOfReturnTypeInBits(Kotlin_longTypeProvider) + } } class IrStaticInitializer(val konanLibrary: KotlinLibrary?, val initializer: LLVMValueRef) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/BlockPointerSupport.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/BlockPointerSupport.kt index 0ca13e435dc..96064e047ca 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/BlockPointerSupport.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/BlockPointerSupport.kt @@ -194,7 +194,11 @@ internal class BlockGenerator(private val codegen: CodeGenerator) { } fun org.jetbrains.kotlin.backend.konan.Context.LongInt(value: Long) = - if (is64BitLong()) Int64(value) else Int32(value.toInt()) + when (val longWidth = llvm.longTypeWidth) { + 32L -> Int32(value.toInt()) + 64L -> Int64(value) + else -> error("Unexpected width of long type: $longWidth") + } private fun generateDescriptorForBlock(blockType: BlockType): ConstValue { val numberOfParameters = blockType.numberOfParameters diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt index 2d8a8caba37..55a808b2074 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt @@ -29,7 +29,7 @@ import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.* -import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.konan.target.AppleConfigurables import org.jetbrains.kotlin.konan.target.LinkerOutputKind import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.utils.DFS @@ -1669,56 +1669,10 @@ private val TypeBridge.objCEncoding: String get() = when (this) { is ValueTypeBridge -> this.objCValueType.encoding } -private fun Context.is64BitNSInteger(): Boolean = when (val target = this.config.target) { - KonanTarget.IOS_X64, - KonanTarget.IOS_ARM64, - KonanTarget.TVOS_ARM64, - KonanTarget.TVOS_X64, - KonanTarget.MACOS_X64, - KonanTarget.MACOS_ARM64, - KonanTarget.WATCHOS_X64 -> true - KonanTarget.WATCHOS_ARM64, - KonanTarget.WATCHOS_ARM32, - KonanTarget.WATCHOS_X86, - KonanTarget.IOS_ARM32 -> false - KonanTarget.ANDROID_X64, - KonanTarget.ANDROID_X86, - KonanTarget.ANDROID_ARM32, - KonanTarget.ANDROID_ARM64, - KonanTarget.LINUX_X64, - KonanTarget.MINGW_X86, - KonanTarget.MINGW_X64, - KonanTarget.LINUX_ARM64, - KonanTarget.LINUX_ARM32_HFP, - KonanTarget.LINUX_MIPS32, - KonanTarget.LINUX_MIPSEL32, - KonanTarget.WASM32, - is KonanTarget.ZEPHYR -> error("Target $target has no support for NSInteger type.") -} - -internal fun Context.is64BitLong(): Boolean = when (this.config.target) { - KonanTarget.IOS_X64, - KonanTarget.IOS_ARM64, - KonanTarget.TVOS_ARM64, - KonanTarget.TVOS_X64, - KonanTarget.ANDROID_X64, - KonanTarget.ANDROID_ARM64, - KonanTarget.LINUX_ARM64, - KonanTarget.MINGW_X64, - KonanTarget.LINUX_X64, - KonanTarget.MACOS_X64, - KonanTarget.MACOS_ARM64, - KonanTarget.WATCHOS_X64 -> true - KonanTarget.WATCHOS_ARM64, - KonanTarget.WATCHOS_ARM32, - KonanTarget.ANDROID_X86, - KonanTarget.ANDROID_ARM32, - KonanTarget.WATCHOS_X86, - KonanTarget.MINGW_X86, - KonanTarget.LINUX_ARM32_HFP, - KonanTarget.LINUX_MIPS32, - KonanTarget.LINUX_MIPSEL32, - KonanTarget.WASM32, - is KonanTarget.ZEPHYR, - KonanTarget.IOS_ARM32 -> false +private fun Context.is64BitNSInteger(): Boolean { + val configurables = this.config.platform.configurables + require(configurables is AppleConfigurables) { + "Target ${configurables.target} has no support for NSInteger type." + } + return llvm.nsIntegerTypeWidth == 64L } diff --git a/kotlin-native/runtime/src/main/cpp/ObjCExport.h b/kotlin-native/runtime/src/main/cpp/ObjCExport.h index 3ede22a3035..e2b637ba48e 100644 --- a/kotlin-native/runtime/src/main/cpp/ObjCExport.h +++ b/kotlin-native/runtime/src/main/cpp/ObjCExport.h @@ -39,6 +39,9 @@ extern "C" OBJ_GETTER(Kotlin_ObjCExport_refFromObjC, id obj); extern "C" id Kotlin_Interop_CreateNSStringFromKString(KRef str); extern "C" OBJ_GETTER(Kotlin_Interop_CreateKStringFromNSString, NSString* str); +/// Utility function that is used to determine NSInteger size in compile time. +extern "C" NSInteger Kotlin_ObjCExport_NSIntegerTypeProvider(); + #endif // KONAN_OBJC_INTEROP #endif // RUNTIME_OBJCEXPORT_H diff --git a/kotlin-native/runtime/src/main/cpp/ObjCExport.mm b/kotlin-native/runtime/src/main/cpp/ObjCExport.mm index 795d1a91b94..aca91e2a5ac 100644 --- a/kotlin-native/runtime/src/main/cpp/ObjCExport.mm +++ b/kotlin-native/runtime/src/main/cpp/ObjCExport.mm @@ -1090,6 +1090,10 @@ extern "C" void Kotlin_ObjCExport_AbstractMethodCalled(id self, SEL selector) { class_getName(object_getClass(self)), sel_getName(selector)]; } +extern "C" NSInteger Kotlin_ObjCExport_NSIntegerTypeProvider() { + return 0; +} + #else extern "C" ALWAYS_INLINE void* Kotlin_Interop_refToObjC(ObjHeader* obj) { diff --git a/kotlin-native/runtime/src/main/cpp/Types.cpp b/kotlin-native/runtime/src/main/cpp/Types.cpp index b7defd21d51..57a6762caef 100644 --- a/kotlin-native/runtime/src/main/cpp/Types.cpp +++ b/kotlin-native/runtime/src/main/cpp/Types.cpp @@ -108,4 +108,8 @@ KVector4f Kotlin_Vector4i32_of(KInt f0, KInt f1, KInt f2, KInt f3) { return (KVector4f)v4i; } +long Kotlin_longTypeProvider() { + return 0; +} + } // extern "C" diff --git a/kotlin-native/runtime/src/main/cpp/Types.h b/kotlin-native/runtime/src/main/cpp/Types.h index 64300cc0af1..bcdcdde20c4 100644 --- a/kotlin-native/runtime/src/main/cpp/Types.h +++ b/kotlin-native/runtime/src/main/cpp/Types.h @@ -124,6 +124,9 @@ void CheckCast(const ObjHeader* obj, const TypeInfo* type_info); KBoolean IsArray(KConstRef obj) RUNTIME_PURE; bool IsSubInterface(const TypeInfo* thiz, const TypeInfo* other) RUNTIME_PURE; +/// Utility function that is used to determine long type size in compile time. +long Kotlin_longTypeProvider(); + #ifdef __cplusplus } #endif