Use runtime bitcode to get size of primitive types
As an alternative to explicitly setting type size in konan.properties or backend code we can "ask" LLVM about it. Unfortunately, there is no Clang/LLVM API for it, so we use a trivial workaround: Create dumb function in runtime code, and then extract info about return type size using LLVM.
This commit is contained in:
committed by
TeamCityServer
parent
790fea635d
commit
9b1498abad
+23
@@ -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)
|
||||
|
||||
+5
-1
@@ -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
|
||||
|
||||
+7
-53
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user