[K/N][codegen] Moved llvmContext from global scope to generationState
This commit is contained in:
+6
-3
@@ -186,8 +186,9 @@ private fun initCache(cache: BoxCache, context: Context, cacheName: String,
|
||||
|
||||
val kotlinType = context.irBuiltIns.getKotlinClass(cache)
|
||||
val staticData = context.generationState.llvm.staticData
|
||||
val llvmType = staticData.getLLVMType(kotlinType.defaultType)
|
||||
val llvmBoxType = structType(context.generationState.llvm.runtime.objHeaderType, llvmType)
|
||||
val llvm = context.generationState.llvm
|
||||
val llvmType = kotlinType.defaultType.toLLVMType(llvm)
|
||||
val llvmBoxType = llvm.structType(llvm.runtime.objHeaderType, llvmType)
|
||||
val (start, end) = context.config.target.getBoxCacheRange(cache)
|
||||
|
||||
return if (declareOnly) {
|
||||
@@ -227,7 +228,9 @@ internal fun IrConstantPrimitive.toBoxCacheValue(context: Context): ConstValue?
|
||||
}
|
||||
val (start, end) = context.config.target.getBoxCacheRange(cacheType)
|
||||
return if (value in start..end) {
|
||||
context.generationState.llvm.boxCacheGlobals[cacheType]?.pointer?.getElementPtr(value.toInt() - start)?.getElementPtr(0)
|
||||
context.generationState.llvm.let { llvm ->
|
||||
llvm.boxCacheGlobals[cacheType]?.pointer?.getElementPtr(llvm, value.toInt() - start)?.getElementPtr(llvm, 0)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
+2
-2
@@ -249,8 +249,8 @@ private class ExportedElement(val kind: ElementKind,
|
||||
"${cname}_type",
|
||||
owner.kGetTypeFuncType
|
||||
)
|
||||
val builder = LLVMCreateBuilderInContext(llvmContext)!!
|
||||
val bb = LLVMAppendBasicBlockInContext(llvmContext, getTypeFunction, "")!!
|
||||
val builder = LLVMCreateBuilderInContext(llvm.llvmContext)!!
|
||||
val bb = LLVMAppendBasicBlockInContext(llvm.llvmContext, getTypeFunction, "")!!
|
||||
LLVMPositionBuilderAtEnd(builder, bb)
|
||||
LLVMBuildRet(builder, irClass.typeInfoPtr.llvm)
|
||||
LLVMDisposeBuilder(builder)
|
||||
|
||||
+21
-21
@@ -20,7 +20,7 @@ private fun LLVMValueRef.isLLVMBuiltin(): Boolean {
|
||||
}
|
||||
|
||||
|
||||
private class CallsChecker(val context: Context, goodFunctions: List<String>) {
|
||||
private class CallsChecker(context: Context, goodFunctions: List<String>) {
|
||||
private val llvm = context.generationState.llvm
|
||||
private val goodFunctionsExact = goodFunctions.filterNot { it.endsWith("*") }.toSet()
|
||||
private val goodFunctionsByPrefix = goodFunctions.filter { it.endsWith("*") }.map { it.substring(0, it.length - 1) }.sorted()
|
||||
@@ -38,22 +38,22 @@ private class CallsChecker(val context: Context, goodFunctions: List<String>) {
|
||||
|
||||
val getMethodImpl = llvm.externalFunction(LlvmFunctionProto(
|
||||
"class_getMethodImplementation",
|
||||
LlvmRetType(pointerType(functionType(voidType, false))),
|
||||
listOf(LlvmParamType(int8TypePtr), LlvmParamType(int8TypePtr)),
|
||||
LlvmRetType(pointerType(functionType(llvm.voidType, false))),
|
||||
listOf(LlvmParamType(llvm.int8PtrType), LlvmParamType(llvm.int8PtrType)),
|
||||
origin = context.stdlibModule.llvmSymbolOrigin)
|
||||
)
|
||||
|
||||
val getClass = llvm.externalFunction(LlvmFunctionProto(
|
||||
"object_getClass",
|
||||
LlvmRetType(int8TypePtr),
|
||||
listOf(LlvmParamType(int8TypePtr)),
|
||||
LlvmRetType(llvm.int8PtrType),
|
||||
listOf(LlvmParamType(llvm.int8PtrType)),
|
||||
origin = context.stdlibModule.llvmSymbolOrigin)
|
||||
)
|
||||
|
||||
val getSuperClass = llvm.externalFunction(LlvmFunctionProto(
|
||||
"class_getSuperclass",
|
||||
LlvmRetType(int8TypePtr),
|
||||
listOf(LlvmParamType(int8TypePtr)),
|
||||
LlvmRetType(llvm.int8PtrType),
|
||||
listOf(LlvmParamType(llvm.int8PtrType)),
|
||||
origin = context.stdlibModule.llvmSymbolOrigin)
|
||||
)
|
||||
|
||||
@@ -69,7 +69,7 @@ private class CallsChecker(val context: Context, goodFunctions: List<String>) {
|
||||
return when {
|
||||
LLVMIsAFunction(value) != null -> {
|
||||
val valueOrSpecial = value.takeIf { !it.isLLVMBuiltin() }
|
||||
?: LLVMConstIntToPtr(Int64(CALLED_LLVM_BUILTIN).llvm, int8TypePtr)!!
|
||||
?: LLVMConstIntToPtr(llvm.int64(CALLED_LLVM_BUILTIN), llvm.int8PtrType)!!
|
||||
ExternalCallInfo(value.name!!, valueOrSpecial).takeIf { value.isExternalFunction() }
|
||||
}
|
||||
LLVMIsACastInst(value) != null -> cleanCalledFunction(LLVMGetOperand(value, 0)!!)
|
||||
@@ -95,7 +95,7 @@ private class CallsChecker(val context: Context, goodFunctions: List<String>) {
|
||||
val calls = getInstructions(block)
|
||||
.filter { it.isFunctionCall() }
|
||||
.toList()
|
||||
val builder = LLVMCreateBuilderInContext(llvmContext)
|
||||
val builder = LLVMCreateBuilderInContext(llvm.llvmContext)
|
||||
|
||||
for (call in calls) {
|
||||
val calleeInfo = call.getPossiblyExternalCalledFunction() ?: continue
|
||||
@@ -111,13 +111,13 @@ private class CallsChecker(val context: Context, goodFunctions: List<String>) {
|
||||
if (LLVMGetNumArgOperands(call) < 2) continue
|
||||
callSiteDescription = "$functionName (over objc_msgSend)"
|
||||
calledName = null
|
||||
val firstArgI8Ptr = LLVMBuildBitCast(builder, LLVMGetArgOperand(call, 0), int8TypePtr, "")
|
||||
val firstArgI8Ptr = LLVMBuildBitCast(builder, LLVMGetArgOperand(call, 0), llvm.int8PtrType, "")
|
||||
val firstArgClassPtr = LLVMBuildCall(builder, getClass.llvmValue, listOf(firstArgI8Ptr).toCValues(), 1, "")
|
||||
val isNil = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntEQ, firstArgI8Ptr, LLVMConstNull(int8TypePtr), "")
|
||||
val isNil = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntEQ, firstArgI8Ptr, LLVMConstNull(llvm.int8PtrType), "")
|
||||
val selector = LLVMGetArgOperand(call, 1)
|
||||
val calledPtrLlvmIfNotNilFunPtr = LLVMBuildCall(builder, getMethodImpl.llvmValue, listOf(firstArgClassPtr, selector).toCValues(), 2, "")
|
||||
val calledPtrLlvmIfNotNil = LLVMBuildBitCast(builder, calledPtrLlvmIfNotNilFunPtr, int8TypePtr, "")
|
||||
val calledPtrLlvmIfNil = LLVMConstIntToPtr(Int64(MSG_SEND_TO_NULL).llvm, int8TypePtr)
|
||||
val calledPtrLlvmIfNotNil = LLVMBuildBitCast(builder, calledPtrLlvmIfNotNilFunPtr, llvm.int8PtrType, "")
|
||||
val calledPtrLlvmIfNil = LLVMConstIntToPtr(llvm.int64(MSG_SEND_TO_NULL), llvm.int8PtrType)
|
||||
calledPtrLlvm = LLVMBuildSelect(builder, isNil, calledPtrLlvmIfNil, calledPtrLlvmIfNotNil, "")
|
||||
}
|
||||
"objc_msgSendSuper2" -> {
|
||||
@@ -125,24 +125,24 @@ private class CallsChecker(val context: Context, goodFunctions: List<String>) {
|
||||
callSiteDescription = "$functionName (over objc_msgSendSuper2)"
|
||||
calledName = null
|
||||
val superStruct = LLVMGetArgOperand(call, 0)
|
||||
val superClassPtrPtr = LLVMBuildGEP(builder, superStruct, listOf(Int32(0).llvm, Int32(1).llvm).toCValues(), 2, "")
|
||||
val superClassPtrPtr = LLVMBuildGEP(builder, superStruct, listOf(llvm.int32(0), llvm.int32(1)).toCValues(), 2, "")
|
||||
val superClassPtr = LLVMBuildLoad(builder, superClassPtrPtr, "")
|
||||
val classPtr = LLVMBuildCall(builder, getSuperClass.llvmValue, listOf(superClassPtr).toCValues(), 1, "")
|
||||
val calledPtrLlvmFunPtr = LLVMBuildCall(builder, getMethodImpl.llvmValue, listOf(classPtr, LLVMGetArgOperand(call, 1)).toCValues(), 2, "")
|
||||
calledPtrLlvm = LLVMBuildBitCast(builder, calledPtrLlvmFunPtr, int8TypePtr, "")
|
||||
calledPtrLlvm = LLVMBuildBitCast(builder, calledPtrLlvmFunPtr, llvm.int8PtrType, "")
|
||||
}
|
||||
else -> {
|
||||
callSiteDescription = functionName
|
||||
calledName = calleeInfo.name
|
||||
calledPtrLlvm = when (val typeKind = LLVMGetTypeKind(calleeInfo.calledPtr.type)) {
|
||||
LLVMTypeKind.LLVMPointerTypeKind -> LLVMBuildBitCast(builder, calleeInfo.calledPtr, int8TypePtr, "")
|
||||
LLVMTypeKind.LLVMIntegerTypeKind -> LLVMBuildIntToPtr(builder, calleeInfo.calledPtr, int8TypePtr, "")
|
||||
LLVMTypeKind.LLVMPointerTypeKind -> LLVMBuildBitCast(builder, calleeInfo.calledPtr, llvm.int8PtrType, "")
|
||||
LLVMTypeKind.LLVMIntegerTypeKind -> LLVMBuildIntToPtr(builder, calleeInfo.calledPtr, llvm.int8PtrType, "")
|
||||
else -> TODO("Unsupported typeKind=${typeKind} of calledPtr=${llvm2string(calleeInfo.calledPtr)}")
|
||||
}
|
||||
}
|
||||
}
|
||||
val callSiteDescriptionLlvm = llvm.staticData.cStringLiteral(callSiteDescription).llvm
|
||||
val calledNameLlvm = if (calledName == null) LLVMConstNull(int8TypePtr) else llvm.staticData.cStringLiteral(calledName).llvm
|
||||
val calledNameLlvm = if (calledName == null) LLVMConstNull(llvm.int8PtrType) else llvm.staticData.cStringLiteral(calledName).llvm
|
||||
LLVMBuildCall(builder, checkerFunction, listOf(callSiteDescriptionLlvm, calledNameLlvm, calledPtrLlvm).toCValues(), 3, "")
|
||||
}
|
||||
LLVMDisposeBuilder(builder)
|
||||
@@ -194,14 +194,14 @@ internal fun addFunctionsListSymbolForChecker(context: Context) {
|
||||
|
||||
val functions = getFunctions(llvm.module)
|
||||
.filter { !it.isExternalFunction() }
|
||||
.map { constPointer(it).bitcast(int8TypePtr) }
|
||||
.map { constPointer(it).bitcast(llvm.int8PtrType) }
|
||||
.toList()
|
||||
val functionsArray = staticData.placeGlobalConstArray("", int8TypePtr, functions)
|
||||
val functionsArray = staticData.placeGlobalConstArray("", llvm.int8PtrType, functions)
|
||||
staticData.getGlobal(functionListGlobal)
|
||||
?.setInitializer(functionsArray)
|
||||
?: throw IllegalStateException("$functionListGlobal global not found")
|
||||
staticData.getGlobal(functionListSizeGlobal)
|
||||
?.setInitializer(Int32(functions.size))
|
||||
?.setInitializer(llvm.constInt32(functions.size))
|
||||
?: throw IllegalStateException("$functionListSizeGlobal global not found")
|
||||
context.verifyBitCode()
|
||||
}
|
||||
|
||||
+3
-3
@@ -137,7 +137,7 @@ private fun collectLlvmModules(context: Context, generatedBitcodeFiles: List<Str
|
||||
|
||||
|
||||
fun parseBitcodeFiles(files: List<String>): List<LLVMModuleRef> = files.map { bitcodeFile ->
|
||||
val parsedModule = parseBitcodeFile(bitcodeFile)
|
||||
val parsedModule = parseBitcodeFile(context.generationState.llvmContext, bitcodeFile)
|
||||
if (!context.shouldUseDebugInfoFromNativeLibs()) {
|
||||
LLVMStripModuleDebugInfo(parsedModule)
|
||||
}
|
||||
@@ -280,7 +280,7 @@ internal fun produceOutput(context: Context) {
|
||||
}
|
||||
|
||||
internal fun parseAndLinkBitcodeFile(context: Context, llvmModule: LLVMModuleRef, path: String) {
|
||||
val parsedModule = parseBitcodeFile(path)
|
||||
val parsedModule = parseBitcodeFile(context.generationState.llvmContext, path)
|
||||
if (!context.shouldUseDebugInfoFromNativeLibs()) {
|
||||
LLVMStripModuleDebugInfo(parsedModule)
|
||||
}
|
||||
@@ -308,5 +308,5 @@ private fun embedAppleLinkerOptionsToBitcode(llvm: Llvm, config: KonanConfig) {
|
||||
val optionsToEmbed = findEmbeddableOptions(config.platform.configurables.linkerKonanFlags) +
|
||||
llvm.allNativeDependencies.flatMap { findEmbeddableOptions(it.linkerOpts) }
|
||||
|
||||
embedLlvmLinkOptions(llvm.module, optionsToEmbed)
|
||||
embedLlvmLinkOptions(llvm.llvmContext, llvm.module, optionsToEmbed)
|
||||
}
|
||||
|
||||
+3
-8
@@ -10,8 +10,6 @@ import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.DebugInfo
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.Llvm
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.LlvmDeclarations
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.llvmContext
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.tryDisposeLLVMContext
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.verifyModule
|
||||
import org.jetbrains.kotlin.backend.konan.serialization.SerializedClassFields
|
||||
import org.jetbrains.kotlin.backend.konan.serialization.SerializedInlineFunctionReference
|
||||
@@ -56,14 +54,11 @@ internal class NativeGenerationState(private val context: Context) {
|
||||
getLocalClassName(source)?.let { name -> putLocalClassName(destination, name) }
|
||||
}
|
||||
|
||||
init {
|
||||
llvmContext = LLVMContextCreate()!!
|
||||
}
|
||||
|
||||
private val runtimeDelegate = lazy { Runtime(config.distribution.compilerInterface(config.target)) }
|
||||
private val runtimeDelegate = lazy { Runtime(llvmContext, config.distribution.compilerInterface(config.target)) }
|
||||
private val llvmDelegate = lazy { Llvm(context, LLVMModuleCreateWithNameInContext("out", llvmContext)!!) }
|
||||
private val debugInfoDelegate = lazy { DebugInfo(context) }
|
||||
|
||||
val llvmContext = LLVMContextCreate()!!
|
||||
val llvmImports = Llvm.ImportsImpl(context)
|
||||
val runtime by runtimeDelegate
|
||||
val llvm by llvmDelegate
|
||||
@@ -98,7 +93,7 @@ internal class NativeGenerationState(private val context: Context) {
|
||||
LLVMDisposeTargetData(runtime.targetData)
|
||||
LLVMDisposeModule(runtime.llvmModule)
|
||||
}
|
||||
tryDisposeLLVMContext()
|
||||
LLVMContextDispose(llvmContext)
|
||||
tempFiles.dispose()
|
||||
|
||||
isDisposed = true
|
||||
|
||||
+1
-3
@@ -7,9 +7,7 @@ package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import llvm.LLVMModuleCreateWithNameInContext
|
||||
import llvm.LLVMModuleRef
|
||||
import llvm.LLVMStripModuleDebugInfo
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.llvmContext
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.llvmLinkModules2
|
||||
|
||||
/**
|
||||
@@ -46,7 +44,7 @@ internal sealed class RuntimeLinkageStrategy {
|
||||
if (runtimeNativeLibraries.isEmpty()) {
|
||||
return emptyList()
|
||||
}
|
||||
val runtimeModule = LLVMModuleCreateWithNameInContext("runtime", llvmContext)!!
|
||||
val runtimeModule = LLVMModuleCreateWithNameInContext("runtime", context.generationState.llvmContext)!!
|
||||
runtimeNativeLibraries.forEach {
|
||||
val failed = llvmLinkModules2(context, runtimeModule, it)
|
||||
if (failed != 0) {
|
||||
|
||||
+2
-2
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.backend.common.lower.coroutines.getOrCreateFunctionW
|
||||
import org.jetbrains.kotlin.backend.konan.*
|
||||
import org.jetbrains.kotlin.backend.konan.ir.*
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.computeFunctionName
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.getLLVMType
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.toLLVMType
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.localHash
|
||||
import org.jetbrains.kotlin.backend.konan.lower.bridgeTarget
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
@@ -425,7 +425,7 @@ internal class ClassLayoutBuilder(val irClass: IrClass, val context: Context) {
|
||||
declaredFields
|
||||
else
|
||||
declaredFields.sortedByDescending {
|
||||
with(context.generationState.llvm) { LLVMStoreSizeOfType(runtime.targetData, getLLVMType(it.type)) }
|
||||
with(context.generationState.llvm) { LLVMStoreSizeOfType(runtime.targetData, it.type.toLLVMType(this)) }
|
||||
}
|
||||
|
||||
val superFieldsCount = 1 /* First field is ObjHeader */ + superFields.size
|
||||
|
||||
+49
-48
@@ -55,7 +55,7 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
|
||||
function.llvmFunctionOrNull
|
||||
|
||||
val llvmDeclarations = context.generationState.llvmDeclarations
|
||||
val intPtrType = LLVMIntPtrTypeInContext(llvmContext, llvmTargetData)!!
|
||||
val intPtrType = LLVMIntPtrTypeInContext(llvm.llvmContext, llvmTargetData)!!
|
||||
internal val immOneIntPtrType = LLVMConstInt(intPtrType, 1, 1)!!
|
||||
internal val immThreeIntPtrType = LLVMConstInt(intPtrType, 3, 1)!!
|
||||
// Keep in sync with OBJECT_TAG_MASK in C++.
|
||||
@@ -73,7 +73,6 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
|
||||
private fun countParams(fn: IrFunction) = LLVMCountParams(fn.llvmFunction.llvmValue)
|
||||
|
||||
fun functionEntryPointAddress(function: IrFunction) = function.entryPointAddress.llvm
|
||||
fun functionHash(function: IrFunction): LLVMValueRef = function.computeFunctionName().localHash.llvm
|
||||
|
||||
fun typeInfoForAllocation(constructedClass: IrClass): LLVMValueRef {
|
||||
assert(!constructedClass.isObjCClass())
|
||||
@@ -289,7 +288,7 @@ internal class StackLocalsManagerImpl(
|
||||
val stackLocal = appendingTo(bbInitStackLocals) {
|
||||
val stackSlot = LLVMBuildAlloca(builder, type, "")!!
|
||||
|
||||
memset(bitcast(kInt8Ptr, stackSlot), 0, LLVMSizeOfTypeInBits(codegen.llvmTargetData, type).toInt() / 8)
|
||||
memset(bitcast(llvm.int8PtrType, stackSlot), 0, LLVMSizeOfTypeInBits(codegen.llvmTargetData, type).toInt() / 8)
|
||||
|
||||
val objectHeader = structGep(stackSlot, 0, "objHeader")
|
||||
val typeInfo = codegen.typeInfoForAllocation(irClass)
|
||||
@@ -321,18 +320,20 @@ internal class StackLocalsManagerImpl(
|
||||
}
|
||||
|
||||
private val symbols = functionGenerationContext.context.ir.symbols
|
||||
private val llvm = functionGenerationContext.llvm
|
||||
|
||||
// TODO: find better place?
|
||||
private val arrayToElementType = mapOf(
|
||||
symbols.array to functionGenerationContext.kObjHeaderPtr,
|
||||
symbols.byteArray to int8Type,
|
||||
symbols.charArray to int16Type,
|
||||
symbols.string to int16Type,
|
||||
symbols.shortArray to int16Type,
|
||||
symbols.intArray to int32Type,
|
||||
symbols.longArray to int64Type,
|
||||
symbols.floatArray to floatType,
|
||||
symbols.doubleArray to doubleType,
|
||||
symbols.booleanArray to int8Type
|
||||
symbols.array to functionGenerationContext.kObjHeaderPtr,
|
||||
symbols.byteArray to llvm.int8Type,
|
||||
symbols.charArray to llvm.int16Type,
|
||||
symbols.string to llvm.int16Type,
|
||||
symbols.shortArray to llvm.int16Type,
|
||||
symbols.intArray to llvm.int32Type,
|
||||
symbols.longArray to llvm.int64Type,
|
||||
symbols.floatArray to llvm.floatType,
|
||||
symbols.doubleArray to llvm.doubleType,
|
||||
symbols.booleanArray to llvm.int8Type
|
||||
)
|
||||
|
||||
override fun allocArray(irClass: IrClass, count: LLVMValueRef) = with(functionGenerationContext) {
|
||||
@@ -347,7 +348,7 @@ internal class StackLocalsManagerImpl(
|
||||
val sizeField = structGep(arrayHeaderSlot, 1, "count_")
|
||||
store(count, sizeField)
|
||||
|
||||
memset(bitcast(kInt8Ptr, structGep(arraySlot, 1, "arrayBody")),
|
||||
memset(bitcast(llvm.int8PtrType, structGep(arraySlot, 1, "arrayBody")),
|
||||
0,
|
||||
constCount * LLVMSizeOfTypeInBits(codegen.llvmTargetData, arrayToElementType[irClass.symbol]).toInt() / 8
|
||||
)
|
||||
@@ -389,7 +390,7 @@ internal class StackLocalsManagerImpl(
|
||||
val bodySize = LLVMSizeOfTypeInBits(codegen.llvmTargetData, type).toInt() / 8
|
||||
val serviceInfoSize = runtime.pointerSize
|
||||
val serviceInfoSizeLlvm = LLVMConstInt(codegen.intPtrType, serviceInfoSize.toLong(), 1)!!
|
||||
val bodyWithSkippedServiceInfoPtr = intToPtr(add(bodyPtr, serviceInfoSizeLlvm), kInt8Ptr)
|
||||
val bodyWithSkippedServiceInfoPtr = intToPtr(add(bodyPtr, serviceInfoSizeLlvm), llvm.int8PtrType)
|
||||
memset(bodyWithSkippedServiceInfoPtr, 0, bodySize - serviceInfoSize)
|
||||
}
|
||||
}
|
||||
@@ -528,13 +529,13 @@ internal abstract class FunctionGenerationContext(
|
||||
}
|
||||
|
||||
protected fun basicBlockInFunction(name: String, locationInfo: LocationInfo?): LLVMBasicBlockRef {
|
||||
val bb = LLVMAppendBasicBlockInContext(llvmContext, function, name)!!
|
||||
val bb = LLVMAppendBasicBlockInContext(llvm.llvmContext, function, name)!!
|
||||
update(bb, locationInfo)
|
||||
return bb
|
||||
}
|
||||
|
||||
fun basicBlock(name: String = "label_", startLocationInfo: LocationInfo?, endLocationInfo: LocationInfo? = startLocationInfo): LLVMBasicBlockRef {
|
||||
val result = LLVMInsertBasicBlockInContext(llvmContext, this.currentBlock, name)!!
|
||||
val result = LLVMInsertBasicBlockInContext(llvm.llvmContext, this.currentBlock, name)!!
|
||||
update(result, startLocationInfo, endLocationInfo)
|
||||
LLVMMoveBasicBlockAfter(result, this.currentBlock)
|
||||
return result
|
||||
@@ -552,7 +553,7 @@ internal abstract class FunctionGenerationContext(
|
||||
fun alloca(type: LLVMTypeRef?, name: String = "", variableLocation: VariableDebugLocation? = null): LLVMValueRef {
|
||||
if (isObjectType(type!!)) {
|
||||
appendingTo(localsInitBb) {
|
||||
val slotAddress = gep(slotsPhi!!, Int32(slotCount).llvm, name)
|
||||
val slotAddress = gep(slotsPhi!!, llvm.int32(slotCount), name)
|
||||
variableLocation?.let {
|
||||
slotToVariableLocation[slotCount] = it
|
||||
}
|
||||
@@ -675,9 +676,9 @@ internal abstract class FunctionGenerationContext(
|
||||
fun memset(pointer: LLVMValueRef, value: Byte, size: Int, isVolatile: Boolean = false) =
|
||||
call(llvm.memsetFunction,
|
||||
listOf(pointer,
|
||||
Int8(value).llvm,
|
||||
Int32(size).llvm,
|
||||
Int1(isVolatile).llvm))
|
||||
llvm.int8(value),
|
||||
llvm.int32(size),
|
||||
llvm.int1(isVolatile)))
|
||||
|
||||
fun call(llvmCallable: LlvmCallable, args: List<LLVMValueRef>,
|
||||
resultLifetime: Lifetime = Lifetime.IRRELEVANT,
|
||||
@@ -918,7 +919,7 @@ internal abstract class FunctionGenerationContext(
|
||||
val personalityFunction = llvm.gxxPersonalityFunction.llvmValue
|
||||
|
||||
// Type of `landingpad` instruction result (depends on personality function):
|
||||
val landingpadType = structType(int8TypePtr, int32Type)
|
||||
val landingpadType = llvm.structType(llvm.int8PtrType, llvm.int32Type)
|
||||
|
||||
val landingpad = LLVMBuildLandingPad(builder, landingpadType, personalityFunction, numClauses, name)!!
|
||||
|
||||
@@ -951,7 +952,7 @@ internal abstract class FunctionGenerationContext(
|
||||
if (wrapExceptionMode) {
|
||||
LLVMAddClause(landingpad, objcNSExceptionRtti.llvm)
|
||||
}
|
||||
LLVMAddClause(landingpad, LLVMConstNull(kInt8Ptr))
|
||||
LLVMAddClause(landingpad, LLVMConstNull(llvm.int8PtrType))
|
||||
|
||||
val fatalForeignExceptionBlock = basicBlock("fatalForeignException", position()?.start)
|
||||
val forwardKotlinExceptionBlock = basicBlock("forwardKotlinException", position()?.start)
|
||||
@@ -1034,7 +1035,7 @@ internal abstract class FunctionGenerationContext(
|
||||
fun catchKotlinException(): LLVMValueRef {
|
||||
val landingpadResult = gxxLandingpad(numClauses = 1, name = "lp")
|
||||
|
||||
LLVMAddClause(landingpadResult, LLVMConstNull(kInt8Ptr))
|
||||
LLVMAddClause(landingpadResult, LLVMConstNull(llvm.int8PtrType))
|
||||
|
||||
// TODO: properly handle C++ exceptions: currently C++ exception can be thrown out from try-finally
|
||||
// bypassing the finally block.
|
||||
@@ -1173,7 +1174,7 @@ internal abstract class FunctionGenerationContext(
|
||||
|
||||
fun fastPath(): LLVMValueRef {
|
||||
// The fastest optimistic version.
|
||||
val interfaceTableIndex = and(interfaceTableSize, Int32(interfaceId).llvm)
|
||||
val interfaceTableIndex = and(interfaceTableSize, llvm.int32(interfaceId))
|
||||
return gep(interfaceTable, interfaceTableIndex)
|
||||
}
|
||||
|
||||
@@ -1188,7 +1189,7 @@ internal abstract class FunctionGenerationContext(
|
||||
val fastPathBB = basicBlock("fast_path", startLocationInfo)
|
||||
val slowPathBB = basicBlock("slow_path", startLocationInfo)
|
||||
val takeResBB = basicBlock("take_res", startLocationInfo)
|
||||
condBr(icmpGe(interfaceTableSize, kImmInt32Zero), fastPathBB, slowPathBB)
|
||||
condBr(icmpGe(interfaceTableSize, llvm.kImmInt32Zero), fastPathBB, slowPathBB)
|
||||
positionAtEnd(takeResBB)
|
||||
val resultPhi = phi(pointerType(runtime.interfaceTableRecordType))
|
||||
appendingTo(fastPathBB) {
|
||||
@@ -1197,9 +1198,9 @@ internal abstract class FunctionGenerationContext(
|
||||
addPhiIncoming(resultPhi, currentBlock to fastValue)
|
||||
}
|
||||
appendingTo(slowPathBB) {
|
||||
val actualInterfaceTableSize = sub(kImmInt32Zero, interfaceTableSize) // -interfaceTableSize
|
||||
val actualInterfaceTableSize = sub(llvm.kImmInt32Zero, interfaceTableSize) // -interfaceTableSize
|
||||
val slowValue = call(llvm.lookupInterfaceTableRecord,
|
||||
listOf(interfaceTable, actualInterfaceTableSize, Int32(interfaceId).llvm))
|
||||
listOf(interfaceTable, actualInterfaceTableSize, llvm.int32(interfaceId)))
|
||||
br(takeResBB)
|
||||
addPhiIncoming(resultPhi, currentBlock to slowValue)
|
||||
}
|
||||
@@ -1229,9 +1230,9 @@ internal abstract class FunctionGenerationContext(
|
||||
!owner.isInterface -> {
|
||||
// If this is a virtual method of the class - we can call via vtable.
|
||||
val index = context.getLayoutBuilder(owner).vtableIndex(anyMethod ?: irFunction)
|
||||
val vtablePlace = gep(typeInfoPtr, Int32(1).llvm) // typeInfoPtr + 1
|
||||
val vtable = bitcast(kInt8PtrPtr, vtablePlace)
|
||||
val slot = gep(vtable, Int32(index).llvm)
|
||||
val vtablePlace = gep(typeInfoPtr, llvm.int32(1)) // typeInfoPtr + 1
|
||||
val vtable = bitcast(llvm.int8PtrPtrType, vtablePlace)
|
||||
val slot = gep(vtable, llvm.int32(index))
|
||||
load(slot)
|
||||
}
|
||||
|
||||
@@ -1239,7 +1240,7 @@ internal abstract class FunctionGenerationContext(
|
||||
// Essentially: typeInfo.itable[place(interfaceId)].vtable[method]
|
||||
val itablePlace = context.getLayoutBuilder(owner).itablePlace(irFunction)
|
||||
val interfaceTableRecord = lookupInterfaceTableRecord(typeInfoPtr, itablePlace.interfaceId)
|
||||
load(gep(load(structGep(interfaceTableRecord, 2 /* vtable */)), Int32(itablePlace.methodIndex).llvm))
|
||||
load(gep(load(structGep(interfaceTableRecord, 2 /* vtable */)), llvm.int32(itablePlace.methodIndex)))
|
||||
}
|
||||
}
|
||||
val functionPtrType = pointerType(codegen.getLlvmFunctionType(irFunction))
|
||||
@@ -1303,7 +1304,7 @@ internal abstract class FunctionGenerationContext(
|
||||
|
||||
// If global object is imported - import it's storage directly.
|
||||
ObjectStorageKind.PERMANENT, ObjectStorageKind.SHARED -> {
|
||||
val llvmType = getLLVMType(irClass.defaultType)
|
||||
val llvmType = irClass.defaultType.toLLVMType(llvm)
|
||||
importGlobal(
|
||||
irClass.globalObjectStorageSymbolName,
|
||||
llvmType,
|
||||
@@ -1358,7 +1359,7 @@ internal abstract class FunctionGenerationContext(
|
||||
br(bbExit)
|
||||
|
||||
positionAtEnd(bbExit)
|
||||
val valuePhi = phi(codegen.getLLVMType(irClass.defaultType))
|
||||
val valuePhi = phi(irClass.defaultType.toLLVMType(llvm))
|
||||
addPhiIncoming(valuePhi, bbCurrent to objectVal, bbInitResult to newValue)
|
||||
|
||||
return valuePhi
|
||||
@@ -1372,7 +1373,7 @@ internal abstract class FunctionGenerationContext(
|
||||
val getterId = context.enumsSupport.enumEntriesMap(enumClass)[enumEntry.name]!!.getterId
|
||||
return call(
|
||||
context.enumsSupport.getValueGetter(enumClass).llvmFunction.llvmValue,
|
||||
listOf(Int32(getterId).llvm),
|
||||
listOf(llvm.int32(getterId)),
|
||||
Lifetime.GLOBAL,
|
||||
exceptionHandler
|
||||
)
|
||||
@@ -1391,8 +1392,8 @@ internal abstract class FunctionGenerationContext(
|
||||
|
||||
val getClass = llvm.externalFunction(LlvmFunctionProto(
|
||||
"object_getClass",
|
||||
LlvmRetType(int8TypePtr),
|
||||
listOf(LlvmParamType(int8TypePtr)),
|
||||
LlvmRetType(llvm.int8PtrType),
|
||||
listOf(LlvmParamType(llvm.int8PtrType)),
|
||||
origin = context.standardLlvmSymbolsOrigin
|
||||
))
|
||||
call(getClass, listOf(objCClass), exceptionHandler = exceptionHandler)
|
||||
@@ -1409,7 +1410,7 @@ internal abstract class FunctionGenerationContext(
|
||||
|
||||
val storedClass = this.load(classPointerGlobal)
|
||||
|
||||
val storedClassIsNotNull = this.icmpNe(storedClass, kNullInt8Ptr)
|
||||
val storedClassIsNotNull = this.icmpNe(storedClass, llvm.kNullInt8Ptr)
|
||||
|
||||
return this.ifThenElse(storedClassIsNotNull, storedClass) {
|
||||
call(
|
||||
@@ -1457,13 +1458,13 @@ internal abstract class FunctionGenerationContext(
|
||||
|
||||
appendingTo(prologueBb) {
|
||||
val slots = if (needSlotsPhi || needCleanupLandingpadAndLeaveFrame)
|
||||
LLVMBuildArrayAlloca(builder, kObjHeaderPtr, Int32(slotCount).llvm, "")!!
|
||||
LLVMBuildArrayAlloca(builder, kObjHeaderPtr, llvm.int32(slotCount), "")!!
|
||||
else
|
||||
kNullObjHeaderPtrPtr
|
||||
if (needSlots || needCleanupLandingpadAndLeaveFrame) {
|
||||
check(!forbidRuntime) { "Attempt to start a frame where runtime usage is forbidden" }
|
||||
// Zero-init slots.
|
||||
val slotsMem = bitcast(kInt8Ptr, slots)
|
||||
val slotsMem = bitcast(llvm.int8PtrType, slots)
|
||||
memset(slotsMem, 0, slotCount * codegen.runtime.pointerSize)
|
||||
}
|
||||
addPhiIncoming(slotsPhi!!, prologueBb to slots)
|
||||
@@ -1514,7 +1515,7 @@ internal abstract class FunctionGenerationContext(
|
||||
switchThreadState(Runnable)
|
||||
}
|
||||
if (needSlots || needCleanupLandingpadAndLeaveFrame) {
|
||||
call(llvm.enterFrameFunction, listOf(slotsPhi!!, Int32(vars.skipSlots).llvm, Int32(slotCount).llvm))
|
||||
call(llvm.enterFrameFunction, listOf(slotsPhi!!, llvm.int32(vars.skipSlots), llvm.int32(slotCount)))
|
||||
} else {
|
||||
check(!setCurrentFrameIsCalled)
|
||||
}
|
||||
@@ -1587,16 +1588,16 @@ internal abstract class FunctionGenerationContext(
|
||||
private val kotlinExceptionRtti: ConstPointer
|
||||
get() = constPointer(importGlobal(
|
||||
"_ZTI18ExceptionObjHolder", // typeinfo for ObjHolder
|
||||
int8TypePtr,
|
||||
llvm.int8PtrType,
|
||||
origin = context.stdlibModule.llvmSymbolOrigin
|
||||
)).bitcast(int8TypePtr)
|
||||
)).bitcast(llvm.int8PtrType)
|
||||
|
||||
private val objcNSExceptionRtti: ConstPointer by lazy {
|
||||
constPointer(importGlobal(
|
||||
"OBJC_EHTYPE_\$_NSException", // typeinfo for NSException*
|
||||
int8TypePtr,
|
||||
llvm.int8PtrType,
|
||||
origin = context.stdlibModule.llvmSymbolOrigin
|
||||
)).bitcast(int8TypePtr)
|
||||
)).bitcast(llvm.int8PtrType)
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
@@ -1607,7 +1608,7 @@ internal abstract class FunctionGenerationContext(
|
||||
* This class is introduced to workaround unreachable code handling.
|
||||
*/
|
||||
inner class PositionHolder {
|
||||
private val builder: LLVMBuilderRef = LLVMCreateBuilderInContext(llvmContext)!!
|
||||
private val builder: LLVMBuilderRef = LLVMCreateBuilderInContext(llvm.llvmContext)!!
|
||||
|
||||
|
||||
fun getBuilder(): LLVMBuilderRef {
|
||||
@@ -1714,7 +1715,7 @@ internal abstract class FunctionGenerationContext(
|
||||
if (needCleanupLandingpadAndLeaveFrame || needSlots) {
|
||||
check(!forbidRuntime) { "Attempt to leave a frame where runtime usage is forbidden" }
|
||||
call(llvm.leaveFrameFunction,
|
||||
listOf(slotsPhi!!, Int32(vars.skipSlots).llvm, Int32(slotCount).llvm))
|
||||
listOf(slotsPhi!!, llvm.int32(vars.skipSlots), llvm.int32(slotCount)))
|
||||
}
|
||||
if (!stackLocalsManager.isEmpty() && context.memoryModel != MemoryModel.EXPERIMENTAL) {
|
||||
stackLocalsManager.clean(refsOnly = true) // Only bother about not leaving any dangling references.
|
||||
@@ -1762,7 +1763,7 @@ internal class DefaultFunctionGenerationContext(
|
||||
override fun processReturns() {
|
||||
appendingTo(epilogueBb) {
|
||||
when {
|
||||
returnType == voidType -> {
|
||||
returnType == llvm.voidType -> {
|
||||
retVoid()
|
||||
}
|
||||
returns.isNotEmpty() -> {
|
||||
|
||||
+139
-83
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan.llvm
|
||||
|
||||
import kotlinx.cinterop.toCValues
|
||||
import kotlinx.cinterop.toKString
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.*
|
||||
@@ -20,8 +21,6 @@ import org.jetbrains.kotlin.konan.library.KonanLibrary
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.library.KotlinLibrary
|
||||
import org.jetbrains.kotlin.library.uniqueName
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
import kotlin.reflect.KProperty
|
||||
@@ -202,7 +201,7 @@ internal interface ContextUtils : RuntimeAware {
|
||||
*/
|
||||
val IrFunction.entryPointAddress: ConstPointer
|
||||
get() {
|
||||
val result = LLVMConstBitCast(this.llvmFunction.llvmValue, int8TypePtr)!!
|
||||
val result = LLVMConstBitCast(this.llvmFunction.llvmValue, llvm.int8PtrType)!!
|
||||
return constPointer(result)
|
||||
}
|
||||
|
||||
@@ -236,15 +235,6 @@ internal interface ContextUtils : RuntimeAware {
|
||||
*/
|
||||
internal fun stringAsBytes(str: String) = str.toByteArray(Charsets.UTF_8)
|
||||
|
||||
internal val String.localHash: LocalHash
|
||||
get() = LocalHash(localHash(stringAsBytes(this)))
|
||||
|
||||
internal val Name.localHash: LocalHash
|
||||
get() = this.toString().localHash
|
||||
|
||||
internal val FqName.localHash: LocalHash
|
||||
get() = this.toString().localHash
|
||||
|
||||
internal class InitializersGenerationState {
|
||||
val fileGlobalInitStates = mutableMapOf<IrFile, LLVMValueRef>()
|
||||
val fileThreadLocalInitStates = mutableMapOf<IrFile, AddressAccess>()
|
||||
@@ -271,7 +261,41 @@ internal class InitializersGenerationState {
|
||||
&& moduleGlobalInitializers.isEmpty() && moduleThreadLocalInitializers.isEmpty()
|
||||
}
|
||||
|
||||
internal class Llvm(val context: Context, val module: LLVMModuleRef) : RuntimeAware {
|
||||
internal class ConstInt1(llvm: Llvm, val value: Boolean) : ConstValue {
|
||||
override val llvm = LLVMConstInt(llvm.int1Type, if (value) 1 else 0, 1)!!
|
||||
}
|
||||
|
||||
internal class ConstInt8(llvm: Llvm, val value: Byte) : ConstValue {
|
||||
override val llvm = LLVMConstInt(llvm.int8Type, value.toLong(), 1)!!
|
||||
}
|
||||
|
||||
internal class ConstInt16(llvm: Llvm, val value: Short) : ConstValue {
|
||||
override val llvm = LLVMConstInt(llvm.int16Type, value.toLong(), 1)!!
|
||||
}
|
||||
|
||||
internal class ConstChar16(llvm: Llvm, val value: Char) : ConstValue {
|
||||
override val llvm = LLVMConstInt(llvm.int16Type, value.code.toLong(), 1)!!
|
||||
}
|
||||
|
||||
internal class ConstInt32(llvm: Llvm, val value: Int) : ConstValue {
|
||||
override val llvm = LLVMConstInt(llvm.int32Type, value.toLong(), 1)!!
|
||||
}
|
||||
|
||||
internal class ConstInt64(llvm: Llvm, val value: Long) : ConstValue {
|
||||
override val llvm = LLVMConstInt(llvm.int64Type, value, 1)!!
|
||||
}
|
||||
|
||||
internal class ConstFloat32(llvm: Llvm, val value: Float) : ConstValue {
|
||||
override val llvm = LLVMConstReal(llvm.floatType, value.toDouble())!!
|
||||
}
|
||||
|
||||
internal class ConstFloat64(llvm: Llvm, val value: Double) : ConstValue {
|
||||
override val llvm = LLVMConstReal(llvm.doubleType, value)!!
|
||||
}
|
||||
|
||||
@Suppress("FunctionName", "PropertyName", "PrivatePropertyName")
|
||||
internal class Llvm(private val context: Context, val module: LLVMModuleRef) : RuntimeAware {
|
||||
val llvmContext = context.generationState.llvmContext
|
||||
|
||||
private fun importFunction(name: String, otherModule: LLVMModuleRef): LlvmCallable {
|
||||
if (LLVMGetNamedFunction(module, name) != null) {
|
||||
@@ -303,7 +327,7 @@ internal class Llvm(val context: Context, val module: LLVMModuleRef) : RuntimeAw
|
||||
}
|
||||
|
||||
private fun importMemset(): LlvmCallable {
|
||||
val functionType = functionType(voidType, false, int8TypePtr, int8Type, int32Type, int1Type)
|
||||
val functionType = functionType(voidType, false, int8PtrType, int8Type, int32Type, int1Type)
|
||||
return llvmIntrinsic("llvm.memset.p0i8.i32", functionType)
|
||||
}
|
||||
|
||||
@@ -440,7 +464,7 @@ internal class Llvm(val context: Context, val module: LLVMModuleRef) : RuntimeAw
|
||||
|
||||
val additionalProducedBitcodeFiles = mutableListOf<String>()
|
||||
|
||||
val staticData = KotlinStaticData(context, module)
|
||||
val staticData = KotlinStaticData(context, this, module)
|
||||
|
||||
private val target = context.config.target
|
||||
|
||||
@@ -535,66 +559,6 @@ internal class Llvm(val context: Context, val module: LLVMModuleRef) : RuntimeAw
|
||||
}
|
||||
}
|
||||
|
||||
var tlsCount = 0
|
||||
|
||||
val tlsKey by lazy {
|
||||
val global = LLVMAddGlobal(module, kInt8Ptr, "__KonanTlsKey")!!
|
||||
LLVMSetLinkage(global, LLVMLinkage.LLVMInternalLinkage)
|
||||
LLVMSetInitializer(global, LLVMConstNull(kInt8Ptr))
|
||||
global
|
||||
}
|
||||
|
||||
private val personalityFunctionName = when (target) {
|
||||
KonanTarget.IOS_ARM32 -> "__gxx_personality_sj0"
|
||||
KonanTarget.MINGW_X64 -> "__gxx_personality_seh0"
|
||||
else -> "__gxx_personality_v0"
|
||||
}
|
||||
|
||||
val cxxStdTerminate = externalFunction(LlvmFunctionProto(
|
||||
"_ZSt9terminatev", // mangled C++ 'std::terminate'
|
||||
returnType = LlvmRetType(voidType),
|
||||
functionAttributes = listOf(LlvmFunctionAttribute.NoUnwind),
|
||||
origin = context.standardLlvmSymbolsOrigin
|
||||
))
|
||||
|
||||
val gxxPersonalityFunction = externalFunction(LlvmFunctionProto(
|
||||
personalityFunctionName,
|
||||
returnType = LlvmRetType(int32Type),
|
||||
functionAttributes = listOf(LlvmFunctionAttribute.NoUnwind),
|
||||
isVararg = true,
|
||||
origin = context.standardLlvmSymbolsOrigin
|
||||
))
|
||||
|
||||
val cxaBeginCatchFunction = externalFunction(LlvmFunctionProto(
|
||||
"__cxa_begin_catch",
|
||||
returnType = LlvmRetType(int8TypePtr),
|
||||
functionAttributes = listOf(LlvmFunctionAttribute.NoUnwind),
|
||||
parameterTypes = listOf(LlvmParamType(int8TypePtr)),
|
||||
origin = context.standardLlvmSymbolsOrigin
|
||||
))
|
||||
|
||||
val cxaEndCatchFunction = externalFunction(LlvmFunctionProto(
|
||||
"__cxa_end_catch",
|
||||
returnType = LlvmRetType(voidType),
|
||||
functionAttributes = listOf(LlvmFunctionAttribute.NoUnwind),
|
||||
origin = context.standardLlvmSymbolsOrigin
|
||||
))
|
||||
|
||||
val memsetFunction = importMemset()
|
||||
//val memcpyFunction = importMemcpy()
|
||||
|
||||
val llvmTrap = llvmIntrinsic(
|
||||
"llvm.trap",
|
||||
functionType(voidType, false),
|
||||
"cold", "noreturn", "nounwind"
|
||||
)
|
||||
|
||||
val llvmEhTypeidFor = llvmIntrinsic(
|
||||
"llvm.eh.typeid.for",
|
||||
functionType(int32Type, false, int8TypePtr),
|
||||
"nounwind", "readnone"
|
||||
)
|
||||
|
||||
val usedFunctions = mutableListOf<LLVMValueRef>()
|
||||
val usedGlobals = mutableListOf<LLVMValueRef>()
|
||||
val compilerUsedGlobals = mutableListOf<LLVMValueRef>()
|
||||
@@ -629,14 +593,106 @@ internal class Llvm(val context: Context, val module: LLVMModuleRef) : RuntimeAw
|
||||
}
|
||||
}
|
||||
|
||||
val llvmInt1 = int1Type
|
||||
val llvmInt8 = int8Type
|
||||
val llvmInt16 = int16Type
|
||||
val llvmInt32 = int32Type
|
||||
val llvmInt64 = int64Type
|
||||
val llvmFloat = floatType
|
||||
val llvmDouble = doubleType
|
||||
val llvmVector128 = vector128Type
|
||||
val int1Type = LLVMInt1TypeInContext(llvmContext)!!
|
||||
val int8Type = LLVMInt8TypeInContext(llvmContext)!!
|
||||
val int16Type = LLVMInt16TypeInContext(llvmContext)!!
|
||||
val int32Type = LLVMInt32TypeInContext(llvmContext)!!
|
||||
val int64Type = LLVMInt64TypeInContext(llvmContext)!!
|
||||
val floatType = LLVMFloatTypeInContext(llvmContext)!!
|
||||
val doubleType = LLVMDoubleTypeInContext(llvmContext)!!
|
||||
val vector128Type = LLVMVectorType(floatType, 4)!!
|
||||
val voidType = LLVMVoidTypeInContext(llvmContext)!!
|
||||
val int8PtrType = pointerType(int8Type)
|
||||
val int8PtrPtrType = pointerType(int8PtrType)
|
||||
|
||||
fun structType(vararg types: LLVMTypeRef): LLVMTypeRef = structType(types.toList())
|
||||
|
||||
fun struct(vararg elements: ConstValue) = Struct(structType(elements.map { it.llvmType }), *elements)
|
||||
|
||||
private fun structType(types: List<LLVMTypeRef>): LLVMTypeRef =
|
||||
LLVMStructTypeInContext(llvmContext, types.toCValues(), types.size, 0)!!
|
||||
|
||||
fun constInt1(value: Boolean) = ConstInt1(this, value)
|
||||
fun constInt8(value: Byte) = ConstInt8(this, value)
|
||||
fun constInt16(value: Short) = ConstInt16(this, value)
|
||||
fun constChar16(value: Char) = ConstChar16(this, value)
|
||||
fun constInt32(value: Int) = ConstInt32(this, value)
|
||||
fun constInt64(value: Long) = ConstInt64(this, value)
|
||||
fun constFloat32(value: Float) = ConstFloat32(this, value)
|
||||
fun constFloat64(value: Double) = ConstFloat64(this, value)
|
||||
|
||||
fun int1(value: Boolean): LLVMValueRef = constInt1(value).llvm
|
||||
fun int8(value: Byte): LLVMValueRef = constInt8(value).llvm
|
||||
fun int16(value: Short): LLVMValueRef = constInt16(value).llvm
|
||||
fun char16(value: Char): LLVMValueRef = constChar16(value).llvm
|
||||
fun int32(value: Int): LLVMValueRef = constInt32(value).llvm
|
||||
fun int64(value: Long): LLVMValueRef = constInt64(value).llvm
|
||||
fun float32(value: Float): LLVMValueRef = constFloat32(value).llvm
|
||||
fun float64(value: Double): LLVMValueRef = constFloat64(value).llvm
|
||||
|
||||
val kNullInt8Ptr by lazy { LLVMConstNull(int8PtrType)!! }
|
||||
val kNullInt32Ptr by lazy { LLVMConstNull(pointerType(int32Type))!! }
|
||||
val kImmInt32Zero by lazy { int32(0) }
|
||||
val kImmInt32One by lazy { int32(1) }
|
||||
|
||||
val memsetFunction = importMemset()
|
||||
|
||||
val llvmTrap = llvmIntrinsic(
|
||||
"llvm.trap",
|
||||
functionType(voidType, false),
|
||||
"cold", "noreturn", "nounwind"
|
||||
)
|
||||
|
||||
val llvmEhTypeidFor = llvmIntrinsic(
|
||||
"llvm.eh.typeid.for",
|
||||
functionType(int32Type, false, int8PtrType),
|
||||
"nounwind", "readnone"
|
||||
)
|
||||
|
||||
var tlsCount = 0
|
||||
|
||||
val tlsKey by lazy {
|
||||
val global = LLVMAddGlobal(module, int8PtrType, "__KonanTlsKey")!!
|
||||
LLVMSetLinkage(global, LLVMLinkage.LLVMInternalLinkage)
|
||||
LLVMSetInitializer(global, LLVMConstNull(int8PtrType))
|
||||
global
|
||||
}
|
||||
|
||||
private val personalityFunctionName = when (target) {
|
||||
KonanTarget.IOS_ARM32 -> "__gxx_personality_sj0"
|
||||
KonanTarget.MINGW_X64 -> "__gxx_personality_seh0"
|
||||
else -> "__gxx_personality_v0"
|
||||
}
|
||||
|
||||
val cxxStdTerminate = externalFunction(LlvmFunctionProto(
|
||||
"_ZSt9terminatev", // mangled C++ 'std::terminate'
|
||||
returnType = LlvmRetType(voidType),
|
||||
functionAttributes = listOf(LlvmFunctionAttribute.NoUnwind),
|
||||
origin = context.standardLlvmSymbolsOrigin
|
||||
))
|
||||
|
||||
val gxxPersonalityFunction = externalFunction(LlvmFunctionProto(
|
||||
personalityFunctionName,
|
||||
returnType = LlvmRetType(int32Type),
|
||||
functionAttributes = listOf(LlvmFunctionAttribute.NoUnwind),
|
||||
isVararg = true,
|
||||
origin = context.standardLlvmSymbolsOrigin
|
||||
))
|
||||
|
||||
val cxaBeginCatchFunction = externalFunction(LlvmFunctionProto(
|
||||
"__cxa_begin_catch",
|
||||
returnType = LlvmRetType(int8PtrType),
|
||||
functionAttributes = listOf(LlvmFunctionAttribute.NoUnwind),
|
||||
parameterTypes = listOf(LlvmParamType(int8PtrType)),
|
||||
origin = context.standardLlvmSymbolsOrigin
|
||||
))
|
||||
|
||||
val cxaEndCatchFunction = externalFunction(LlvmFunctionProto(
|
||||
"__cxa_end_catch",
|
||||
returnType = LlvmRetType(voidType),
|
||||
functionAttributes = listOf(LlvmFunctionAttribute.NoUnwind),
|
||||
origin = context.standardLlvmSymbolsOrigin
|
||||
))
|
||||
|
||||
private fun getSizeOfReturnTypeInBits(functionPointer: LLVMValueRef): Long {
|
||||
// LLVMGetElementType is called because we need to dereference a pointer to function.
|
||||
|
||||
+16
-22
@@ -7,37 +7,31 @@ package org.jetbrains.kotlin.backend.konan.llvm
|
||||
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.*
|
||||
import org.jetbrains.kotlin.backend.konan.optimizations.DataFlowIR
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.isNothing
|
||||
import org.jetbrains.kotlin.ir.types.isUnit
|
||||
|
||||
private fun RuntimeAware.getLlvmType(primitiveBinaryType: PrimitiveBinaryType?) = when (primitiveBinaryType) {
|
||||
null -> this.kObjHeaderPtr
|
||||
private fun PrimitiveBinaryType?.toLlvmType(llvm: Llvm) = when (this) {
|
||||
null -> llvm.kObjHeaderPtr
|
||||
|
||||
PrimitiveBinaryType.BOOLEAN -> int1Type
|
||||
PrimitiveBinaryType.BYTE -> int8Type
|
||||
PrimitiveBinaryType.SHORT -> int16Type
|
||||
PrimitiveBinaryType.INT -> int32Type
|
||||
PrimitiveBinaryType.LONG -> int64Type
|
||||
PrimitiveBinaryType.FLOAT -> floatType
|
||||
PrimitiveBinaryType.DOUBLE -> doubleType
|
||||
PrimitiveBinaryType.BOOLEAN -> llvm.int1Type
|
||||
PrimitiveBinaryType.BYTE -> llvm.int8Type
|
||||
PrimitiveBinaryType.SHORT -> llvm.int16Type
|
||||
PrimitiveBinaryType.INT -> llvm.int32Type
|
||||
PrimitiveBinaryType.LONG -> llvm.int64Type
|
||||
PrimitiveBinaryType.FLOAT -> llvm.floatType
|
||||
PrimitiveBinaryType.DOUBLE -> llvm.doubleType
|
||||
|
||||
PrimitiveBinaryType.VECTOR128 -> vector128Type
|
||||
PrimitiveBinaryType.POINTER -> int8TypePtr
|
||||
PrimitiveBinaryType.VECTOR128 -> llvm.vector128Type
|
||||
PrimitiveBinaryType.POINTER -> llvm.int8PtrType
|
||||
}
|
||||
|
||||
internal fun RuntimeAware.getLLVMType(type: IrType): LLVMTypeRef =
|
||||
runtime.calculatedLLVMTypes.getOrPut(type) { getLlvmType(type.computePrimitiveBinaryTypeOrNull()) }
|
||||
|
||||
internal fun RuntimeAware.getLLVMType(type: DataFlowIR.Type) =
|
||||
getLlvmType(type.primitiveBinaryType)
|
||||
internal fun IrType.toLLVMType(llvm: Llvm): LLVMTypeRef =
|
||||
llvm.runtime.calculatedLLVMTypes.getOrPut(this) { computePrimitiveBinaryTypeOrNull().toLlvmType(llvm) }
|
||||
|
||||
internal fun IrType.isVoidAsReturnType() = isUnit() || isNothing()
|
||||
|
||||
internal fun RuntimeAware.getLLVMReturnType(type: IrType): LLVMTypeRef {
|
||||
return when {
|
||||
type.isVoidAsReturnType() -> voidType
|
||||
else -> getLLVMType(type)
|
||||
}
|
||||
internal fun IrType.getLLVMReturnType(llvm: Llvm) = when {
|
||||
isVoidAsReturnType() -> llvm.voidType
|
||||
else -> toLLVMType(llvm)
|
||||
}
|
||||
|
||||
+23
-24
@@ -25,10 +25,6 @@ import org.jetbrains.kotlin.konan.file.File
|
||||
|
||||
internal object DWARF {
|
||||
val producer = "konanc ${CompilerVersion.CURRENT} / kotlin-compiler: ${KotlinVersion.CURRENT}"
|
||||
|
||||
/* TODO: from LLVM sources is unclear what runtimeVersion corresponds to term in terms of dwarf specification. */
|
||||
val dwarfVersionMetaDataNodeName get() = "Dwarf Version".mdString()
|
||||
val dwarfDebugInfoMetaDataNodeName get() = "Debug Info Version".mdString()
|
||||
const val debugInfoVersion = 3 /* TODO: configurable? */
|
||||
|
||||
/**
|
||||
@@ -110,9 +106,12 @@ internal class DebugInfo(override val context: Context) : ContextUtils {
|
||||
* !5 = !{i32 1, !"PIC Level", i32 2}
|
||||
* !6 = !{!"Apple LLVM version 8.0.0 (clang-800.0.38)"}
|
||||
*/
|
||||
val llvmTwo = Int32(2).llvm
|
||||
val dwarfVersion = node(llvmTwo, DWARF.dwarfVersionMetaDataNodeName, Int32(DWARF.dwarfVersion(config)).llvm)
|
||||
val nodeDebugInfoVersion = node(llvmTwo, DWARF.dwarfDebugInfoMetaDataNodeName, Int32(DWARF.debugInfoVersion).llvm)
|
||||
val llvmTwo = llvm.int32(2)
|
||||
/* TODO: from LLVM sources is unclear what runtimeVersion corresponds to term in terms of dwarf specification. */
|
||||
val dwarfVersionMetaDataNodeName = "Dwarf Version".mdString(llvm.llvmContext)
|
||||
val dwarfDebugInfoMetaDataNodeName = "Debug Info Version".mdString(llvm.llvmContext)
|
||||
val dwarfVersion = node(llvm.llvmContext, llvmTwo, dwarfVersionMetaDataNodeName, llvm.int32(DWARF.dwarfVersion(config)))
|
||||
val nodeDebugInfoVersion = node(llvm.llvmContext, llvmTwo, dwarfDebugInfoMetaDataNodeName, llvm.int32(DWARF.debugInfoVersion))
|
||||
val llvmModuleFlags = "llvm.module.flags"
|
||||
LLVMAddNamedMetadataOperand(llvm.module, llvmModuleFlags, dwarfVersion)
|
||||
LLVMAddNamedMetadataOperand(llvm.module, llvmModuleFlags, nodeDebugInfoVersion)
|
||||
@@ -142,17 +141,17 @@ internal class DebugInfo(override val context: Context) : ContextUtils {
|
||||
val types = mutableMapOf<IrType, DITypeOpaqueRef>()
|
||||
|
||||
private val llvmTypes = mapOf(
|
||||
context.irBuiltIns.booleanType to llvm.llvmInt8,
|
||||
context.irBuiltIns.byteType to llvm.llvmInt8,
|
||||
context.irBuiltIns.charType to llvm.llvmInt16,
|
||||
context.irBuiltIns.shortType to llvm.llvmInt16,
|
||||
context.irBuiltIns.intType to llvm.llvmInt32,
|
||||
context.irBuiltIns.longType to llvm.llvmInt64,
|
||||
context.irBuiltIns.floatType to llvm.llvmFloat,
|
||||
context.irBuiltIns.doubleType to llvm.llvmDouble)
|
||||
context.irBuiltIns.booleanType to llvm.int8Type,
|
||||
context.irBuiltIns.byteType to llvm.int8Type,
|
||||
context.irBuiltIns.charType to llvm.int16Type,
|
||||
context.irBuiltIns.shortType to llvm.int16Type,
|
||||
context.irBuiltIns.intType to llvm.int32Type,
|
||||
context.irBuiltIns.longType to llvm.int64Type,
|
||||
context.irBuiltIns.floatType to llvm.floatType,
|
||||
context.irBuiltIns.doubleType to llvm.doubleType)
|
||||
private val llvmTypeSizes = llvmTypes.map { it.key to LLVMSizeOfTypeInBits(llvmTargetData, it.value) }.toMap()
|
||||
private val llvmTypeAlignments = llvmTypes.map { it.key to LLVMPreferredAlignmentOfType(llvmTargetData, it.value) }.toMap()
|
||||
private val otherLlvmType = LLVMPointerType(int64Type, 0)!!
|
||||
private val otherLlvmType = LLVMPointerType(llvm.int64Type, 0)!!
|
||||
private val otherTypeSize = LLVMSizeOfTypeInBits(llvmTargetData, otherLlvmType)
|
||||
private val otherTypeAlignment = LLVMPreferredAlignmentOfType(llvmTargetData, otherLlvmType)
|
||||
|
||||
@@ -194,14 +193,14 @@ internal class DebugInfo(override val context: Context) : ContextUtils {
|
||||
|
||||
private fun IrType.llvmType(): LLVMTypeRef = llvmTypes.getOrElse(this@llvmType) {
|
||||
when (computePrimitiveBinaryTypeOrNull()) {
|
||||
PrimitiveBinaryType.BOOLEAN -> llvm.llvmInt1
|
||||
PrimitiveBinaryType.BYTE -> llvm.llvmInt8
|
||||
PrimitiveBinaryType.SHORT -> llvm.llvmInt16
|
||||
PrimitiveBinaryType.INT -> llvm.llvmInt32
|
||||
PrimitiveBinaryType.LONG -> llvm.llvmInt64
|
||||
PrimitiveBinaryType.FLOAT -> llvm.llvmFloat
|
||||
PrimitiveBinaryType.DOUBLE -> llvm.llvmDouble
|
||||
PrimitiveBinaryType.VECTOR128 -> llvm.llvmVector128
|
||||
PrimitiveBinaryType.BOOLEAN -> llvm.int1Type
|
||||
PrimitiveBinaryType.BYTE -> llvm.int8Type
|
||||
PrimitiveBinaryType.SHORT -> llvm.int16Type
|
||||
PrimitiveBinaryType.INT -> llvm.int32Type
|
||||
PrimitiveBinaryType.LONG -> llvm.int64Type
|
||||
PrimitiveBinaryType.FLOAT -> llvm.floatType
|
||||
PrimitiveBinaryType.DOUBLE -> llvm.doubleType
|
||||
PrimitiveBinaryType.VECTOR128 -> llvm.vector128Type
|
||||
else -> otherLlvmType
|
||||
}
|
||||
}
|
||||
|
||||
+1
-3
@@ -10,6 +10,4 @@ import org.jetbrains.kotlin.backend.common.serialization.cityHash64
|
||||
@OptIn(ExperimentalUnsignedTypes::class)
|
||||
internal fun localHash(data: ByteArray): Long {
|
||||
return cityHash64(data).toLong()
|
||||
}
|
||||
|
||||
internal class LocalHash(val value: Long) : ConstValue by Int64(value)
|
||||
}
|
||||
+38
-42
@@ -268,7 +268,7 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
|
||||
val typeArgument = constant.typeArguments[0]
|
||||
val typeArgumentClass = typeArgument.getClass()!!
|
||||
val typeInfo = codegen.typeInfoValue(typeArgumentClass)
|
||||
listOf(constPointer(typeInfo).bitcast(int8TypePtr))
|
||||
listOf(constPointer(typeInfo).bitcast(codegen.llvm.int8PtrType))
|
||||
}
|
||||
ConstantConstructorIntrinsicType.KTYPE_IMPL ->
|
||||
reportNonLoweredIntrinsic(intrinsicType)
|
||||
@@ -289,10 +289,10 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
|
||||
args.single()
|
||||
|
||||
private fun FunctionGenerationContext.emitIsExperimentalMM(): LLVMValueRef =
|
||||
Int1(context.memoryModel == MemoryModel.EXPERIMENTAL).llvm
|
||||
llvm.int1(context.memoryModel == MemoryModel.EXPERIMENTAL)
|
||||
|
||||
private fun FunctionGenerationContext.emitGetNativeNullPtr(): LLVMValueRef =
|
||||
kNullInt8Ptr
|
||||
llvm.kNullInt8Ptr
|
||||
|
||||
private fun FunctionGenerationContext.emitNativePtrPlusLong(args: List<LLVMValueRef>): LLVMValueRef =
|
||||
gep(args[0], args[1])
|
||||
@@ -315,7 +315,7 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
|
||||
}
|
||||
|
||||
private fun FunctionGenerationContext.emitGetPointerSize(): LLVMValueRef =
|
||||
Int32(LLVMPointerSize(codegen.llvmTargetData)).llvm
|
||||
llvm.int32(LLVMPointerSize(codegen.llvmTargetData))
|
||||
|
||||
private fun FunctionGenerationContext.emitReadPrimitive(callSite: IrCall, args: List<LLVMValueRef>): LLVMValueRef {
|
||||
val pointerType = pointerType(callSite.llvmReturnType)
|
||||
@@ -326,7 +326,7 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
|
||||
|
||||
private fun FunctionGenerationContext.emitWritePrimitive(callSite: IrCall, args: List<LLVMValueRef>): LLVMValueRef {
|
||||
val function = callSite.symbol.owner
|
||||
val pointerType = pointerType(codegen.getLLVMType(function.valueParameters.last().type))
|
||||
val pointerType = pointerType(function.valueParameters.last().type.toLLVMType(llvm))
|
||||
val rawPointer = args[1]
|
||||
val pointer = bitcast(pointerType, rawPointer)
|
||||
store(args[2], pointer)
|
||||
@@ -335,7 +335,7 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
|
||||
|
||||
private fun FunctionGenerationContext.emitReadBits(args: List<LLVMValueRef>): LLVMValueRef {
|
||||
val ptr = args[0]
|
||||
assert(ptr.type == int8TypePtr)
|
||||
assert(ptr.type == llvm.int8PtrType)
|
||||
|
||||
val offset = extractConstUnsignedInt(args[1])
|
||||
val size = extractConstUnsignedInt(args[2]).toInt()
|
||||
@@ -347,9 +347,9 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
|
||||
// Note: LLVM allows to read without padding tail up to byte boundary, but the result seems to be incorrect.
|
||||
|
||||
val bitsWithPaddingNum = prefixBitsNum + size + suffixBitsNum
|
||||
val bitsWithPaddingType = LLVMIntTypeInContext(llvmContext, bitsWithPaddingNum)!!
|
||||
val bitsWithPaddingType = LLVMIntTypeInContext(llvm.llvmContext, bitsWithPaddingNum)!!
|
||||
|
||||
val bitsWithPaddingPtr = bitcast(org.jetbrains.kotlin.backend.konan.llvm.pointerType(bitsWithPaddingType), gep(ptr, org.jetbrains.kotlin.backend.konan.llvm.Int64(offset / 8).llvm))
|
||||
val bitsWithPaddingPtr = bitcast(pointerType(bitsWithPaddingType), gep(ptr, llvm.int64(offset / 8)))
|
||||
val bitsWithPadding = load(bitsWithPaddingPtr).setUnaligned()
|
||||
|
||||
val bits = shr(
|
||||
@@ -358,28 +358,28 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
|
||||
)
|
||||
return when {
|
||||
bitsWithPaddingNum == 64 -> bits
|
||||
bitsWithPaddingNum > 64 -> trunc(bits, org.jetbrains.kotlin.backend.konan.llvm.int64Type)
|
||||
else -> ext(bits, org.jetbrains.kotlin.backend.konan.llvm.int64Type, signed)
|
||||
bitsWithPaddingNum > 64 -> trunc(bits, llvm.int64Type)
|
||||
else -> ext(bits, llvm.int64Type, signed)
|
||||
}
|
||||
}
|
||||
|
||||
private fun FunctionGenerationContext.emitWriteBits(args: List<LLVMValueRef>): LLVMValueRef {
|
||||
val ptr = args[0]
|
||||
assert(ptr.type == int8TypePtr)
|
||||
assert(ptr.type == llvm.int8PtrType)
|
||||
|
||||
val offset = extractConstUnsignedInt(args[1])
|
||||
val size = extractConstUnsignedInt(args[2]).toInt()
|
||||
|
||||
val value = args[3]
|
||||
assert(value.type == int64Type)
|
||||
assert(value.type == llvm.int64Type)
|
||||
|
||||
val bitsType = LLVMIntTypeInContext(llvmContext, size)!!
|
||||
val bitsType = LLVMIntTypeInContext(llvm.llvmContext, size)!!
|
||||
|
||||
val prefixBitsNum = (offset % 8).toInt()
|
||||
val suffixBitsNum = (8 - ((size + offset) % 8).toInt()) % 8
|
||||
|
||||
val bitsWithPaddingNum = prefixBitsNum + size + suffixBitsNum
|
||||
val bitsWithPaddingType = LLVMIntTypeInContext(llvmContext, bitsWithPaddingNum)!!
|
||||
val bitsWithPaddingType = LLVMIntTypeInContext(llvm.llvmContext, bitsWithPaddingNum)!!
|
||||
|
||||
// 0011111000:
|
||||
val discardBitsMask = LLVMConstShl(
|
||||
@@ -392,7 +392,7 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
|
||||
|
||||
val preservedBitsMask = LLVMConstNot(discardBitsMask)!!
|
||||
|
||||
val bitsWithPaddingPtr = bitcast(pointerType(bitsWithPaddingType), gep(ptr, Int64(offset / 8).llvm))
|
||||
val bitsWithPaddingPtr = bitcast(pointerType(bitsWithPaddingType), gep(ptr, llvm.int64(offset / 8)))
|
||||
|
||||
val bits = trunc(value, bitsType)
|
||||
|
||||
@@ -420,17 +420,13 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
|
||||
val receiver = args[0]
|
||||
val superClass = args[1]
|
||||
|
||||
val structType = structType(kInt8Ptr, kInt8Ptr)
|
||||
val structType = llvm.structType(llvm.int8PtrType, llvm.int8PtrType)
|
||||
val ptr = alloca(structType)
|
||||
store(receiver, LLVMBuildGEP(builder, ptr, cValuesOf(kImmZero, kImmZero), 2, "")!!)
|
||||
store(superClass, LLVMBuildGEP(builder, ptr, cValuesOf(kImmZero, kImmOne), 2, "")!!)
|
||||
return bitcast(int8TypePtr, ptr)
|
||||
store(receiver, LLVMBuildGEP(builder, ptr, cValuesOf(llvm.kImmInt32Zero, llvm.kImmInt32Zero), 2, "")!!)
|
||||
store(superClass, LLVMBuildGEP(builder, ptr, cValuesOf(llvm.kImmInt32Zero, llvm.kImmInt32One), 2, "")!!)
|
||||
return bitcast(llvm.int8PtrType, ptr)
|
||||
}
|
||||
|
||||
// TODO: Find better place for these guys.
|
||||
private val kImmZero = LLVMConstInt(int32Type, 0, 1)!!
|
||||
private val kImmOne = LLVMConstInt(int32Type, 1, 1)!!
|
||||
|
||||
private fun FunctionGenerationContext.emitGetObjCClass(callSite: IrCall): LLVMValueRef {
|
||||
val typeArgument = callSite.getTypeArgument(0)
|
||||
return getObjCClass(typeArgument!!.getClass()!!, environment.exceptionHandler)
|
||||
@@ -439,8 +435,8 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
|
||||
private fun FunctionGenerationContext.emitObjCGetMessenger(args: List<LLVMValueRef>, isStret: Boolean): LLVMValueRef {
|
||||
val messengerNameSuffix = if (isStret) "_stret" else ""
|
||||
|
||||
val functionReturnType = LlvmRetType(int8TypePtr)
|
||||
val functionParameterTypes = listOf(LlvmParamType(int8TypePtr), LlvmParamType(int8TypePtr))
|
||||
val functionReturnType = LlvmRetType(llvm.int8PtrType)
|
||||
val functionParameterTypes = listOf(LlvmParamType(llvm.int8PtrType), LlvmParamType(llvm.int8PtrType))
|
||||
|
||||
val libobjc = context.standardLlvmSymbolsOrigin
|
||||
val normalMessenger = codegen.llvm.externalFunction(LlvmFunctionProto(
|
||||
@@ -460,13 +456,13 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
|
||||
|
||||
val superClass = args.single()
|
||||
val messenger = LLVMBuildSelect(builder,
|
||||
If = icmpEq(superClass, kNullInt8Ptr),
|
||||
If = icmpEq(superClass, llvm.kNullInt8Ptr),
|
||||
Then = normalMessenger.llvmValue,
|
||||
Else = superMessenger.llvmValue,
|
||||
Name = ""
|
||||
)!!
|
||||
|
||||
return bitcast(int8TypePtr, messenger)
|
||||
return bitcast(llvm.int8PtrType, messenger)
|
||||
}
|
||||
|
||||
private fun FunctionGenerationContext.emitAreEqualByValue(args: List<LLVMValueRef>): LLVMValueRef {
|
||||
@@ -477,7 +473,7 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
|
||||
LLVMTypeKind.LLVMFloatTypeKind, LLVMTypeKind.LLVMDoubleTypeKind,
|
||||
LLVMTypeKind.LLVMVectorTypeKind -> {
|
||||
// TODO LLVM API does not provide guarantee for LLVMIntTypeInContext availability for longer types; consider meaningful diag message instead of NPE
|
||||
val integerType = LLVMIntTypeInContext(llvmContext, first.type.sizeInBits())!!
|
||||
val integerType = LLVMIntTypeInContext(llvm.llvmContext, first.type.sizeInBits())!!
|
||||
icmpEq(bitcast(integerType, first), bitcast(integerType, second))
|
||||
}
|
||||
LLVMTypeKind.LLVMIntegerTypeKind, LLVMTypeKind.LLVMPointerTypeKind -> icmpEq(first, second)
|
||||
@@ -508,7 +504,7 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
|
||||
) { "Invalid vector element type ${LLVMGetTypeKind(callSite.llvmReturnType)}"}
|
||||
|
||||
val elementCount = vectorSize / elementSize
|
||||
emitThrowIfOOB(index, Int32((elementCount)).llvm)
|
||||
emitThrowIfOOB(index, llvm.int32((elementCount)))
|
||||
|
||||
val targetType = LLVMVectorType(callSite.llvmReturnType, elementCount)!!
|
||||
return extractElement(
|
||||
@@ -554,11 +550,11 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
|
||||
|
||||
private fun FunctionGenerationContext.emitShift(op: LLVMOpcode, args: List<LLVMValueRef>): LLVMValueRef {
|
||||
val (first, second) = args
|
||||
val shift = if (first.type == int64Type) {
|
||||
val tmp = and(second, Int32(63).llvm)
|
||||
zext(tmp, int64Type)
|
||||
val shift = if (first.type == llvm.int64Type) {
|
||||
val tmp = and(second, llvm.int32(63))
|
||||
zext(tmp, llvm.int64Type)
|
||||
} else {
|
||||
and(second, Int32(31).llvm)
|
||||
and(second, llvm.int32(31))
|
||||
}
|
||||
return LLVMBuildBinOp(builder, op, first, shift, "")!!
|
||||
}
|
||||
@@ -722,8 +718,8 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
|
||||
val (first, second) = args
|
||||
val equal = icmpEq(first, second)
|
||||
val less = if (signed) icmpLt(first, second) else icmpULt(first, second)
|
||||
val tmp = select(less, Int32(-1).llvm, Int32(1).llvm)
|
||||
return select(equal, Int32(0).llvm, tmp)
|
||||
val tmp = select(less, llvm.int32(-1), llvm.int32(1))
|
||||
return select(equal, llvm.int32(0), tmp)
|
||||
}
|
||||
|
||||
private fun FunctionGenerationContext.emitSignedCompareTo(args: List<LLVMValueRef>) =
|
||||
@@ -732,13 +728,13 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
|
||||
private fun FunctionGenerationContext.emitUnsignedCompareTo(args: List<LLVMValueRef>) =
|
||||
emitCompareTo(args, signed = false)
|
||||
|
||||
private fun makeConstOfType(type: LLVMTypeRef, value: Int): LLVMValueRef = when (type) {
|
||||
int8Type -> Int8(value.toByte()).llvm
|
||||
int16Type -> Char16(value.toChar()).llvm
|
||||
int32Type -> Int32(value).llvm
|
||||
int64Type -> Int64(value.toLong()).llvm
|
||||
floatType -> Float32(value.toFloat()).llvm
|
||||
doubleType -> Float64(value.toDouble()).llvm
|
||||
private fun FunctionGenerationContext.makeConstOfType(type: LLVMTypeRef, value: Int): LLVMValueRef = when (type) {
|
||||
llvm.int8Type -> llvm.int8(value.toByte())
|
||||
llvm.int16Type -> llvm.char16(value.toChar())
|
||||
llvm.int32Type -> llvm.int32(value)
|
||||
llvm.int64Type -> llvm.int64(value.toLong())
|
||||
llvm.floatType -> llvm.float32(value.toFloat())
|
||||
llvm.doubleType -> llvm.float64(value.toDouble())
|
||||
else -> context.reportCompilationError("Unexpected primitive type: $type")
|
||||
}
|
||||
}
|
||||
+89
-94
@@ -454,10 +454,10 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
val kVoidFuncType = functionType(voidType)
|
||||
val kVoidFuncType = functionType(llvm.voidType)
|
||||
val kNodeInitType = LLVMGetTypeByName(llvm.module, "struct.InitNode")!!
|
||||
val kMemoryStateType = LLVMGetTypeByName(llvm.module, "struct.MemoryState")!!
|
||||
val kInitFuncType = functionType(voidType, false, int32Type, pointerType(kMemoryStateType))
|
||||
val kInitFuncType = functionType(llvm.voidType, false, llvm.int32Type, pointerType(kMemoryStateType))
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
@@ -489,10 +489,10 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
}
|
||||
|
||||
switch(LLVMGetParam(initFunction, 0)!!,
|
||||
listOf(Int32(INIT_GLOBALS).llvm to bbInit,
|
||||
Int32(INIT_THREAD_LOCAL_GLOBALS).llvm to bbLocalInit,
|
||||
Int32(ALLOC_THREAD_LOCAL_GLOBALS).llvm to bbLocalAlloc,
|
||||
Int32(DEINIT_GLOBALS).llvm to bbGlobalDeinit),
|
||||
listOf(llvm.int32(INIT_GLOBALS) to bbInit,
|
||||
llvm.int32(INIT_THREAD_LOCAL_GLOBALS) to bbLocalInit,
|
||||
llvm.int32(ALLOC_THREAD_LOCAL_GLOBALS) to bbLocalAlloc,
|
||||
llvm.int32(DEINIT_GLOBALS) to bbGlobalDeinit),
|
||||
bbDefault)
|
||||
|
||||
// Globals initializers may contain accesses to objects, so visit them first.
|
||||
@@ -510,8 +510,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
appendingTo(bbLocalInit) {
|
||||
llvm.initializersGenerationState.threadLocalInitState?.let {
|
||||
val address = it.getAddress(functionGenerationContext)
|
||||
store(Int32(FILE_NOT_INITIALIZED).llvm, address)
|
||||
LLVMSetInitializer(address, Int32(FILE_NOT_INITIALIZED).llvm)
|
||||
store(llvm.int32(FILE_NOT_INITIALIZED), address)
|
||||
LLVMSetInitializer(address, llvm.int32(FILE_NOT_INITIALIZED))
|
||||
}
|
||||
llvm.initializersGenerationState.topLevelFields
|
||||
.filter { !context.useLazyFileInitializers() || it.shouldBeInitializedEagerly }
|
||||
@@ -526,7 +526,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
appendingTo(bbLocalAlloc) {
|
||||
if (llvm.tlsCount > 0) {
|
||||
val memory = LLVMGetParam(initFunction, 1)!!
|
||||
call(llvm.addTLSRecord, listOf(memory, llvm.tlsKey, Int32(llvm.tlsCount).llvm))
|
||||
call(llvm.addTLSRecord, listOf(memory, llvm.tlsKey, llvm.int32(llvm.tlsCount)))
|
||||
}
|
||||
ret(null)
|
||||
}
|
||||
@@ -546,7 +546,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
storeHeapRef(codegen.kNullObjHeaderPtr, address)
|
||||
}
|
||||
llvm.initializersGenerationState.globalInitState?.let {
|
||||
store(Int32(FILE_NOT_INITIALIZED).llvm, it)
|
||||
store(llvm.int32(FILE_NOT_INITIALIZED), it)
|
||||
}
|
||||
ret(null)
|
||||
}
|
||||
@@ -777,21 +777,21 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
if (function == null) return emptyMap()
|
||||
return function.allParameters.mapIndexed { i, irParameter ->
|
||||
val parameter = codegen.param(function, i)
|
||||
assert(codegen.getLLVMType(irParameter.type) == parameter.type)
|
||||
assert(irParameter.type.toLLVMType(llvm) == parameter.type)
|
||||
irParameter to parameter
|
||||
}.toMap()
|
||||
}
|
||||
|
||||
private fun getGlobalInitStateFor(file: IrFile): LLVMValueRef =
|
||||
llvm.initializersGenerationState.fileGlobalInitStates.getOrPut(file) {
|
||||
codegen.addGlobal("state_global$${file.fileEntry.name}", int32Type, false).also {
|
||||
LLVMSetInitializer(it, Int32(FILE_NOT_INITIALIZED).llvm)
|
||||
codegen.addGlobal("state_global$${file.fileEntry.name}", llvm.int32Type, false).also {
|
||||
LLVMSetInitializer(it, llvm.int32(FILE_NOT_INITIALIZED))
|
||||
}
|
||||
}
|
||||
|
||||
private fun getThreadLocalInitStateFor(file: IrFile): AddressAccess =
|
||||
llvm.initializersGenerationState.fileThreadLocalInitStates.getOrPut(file) {
|
||||
codegen.addKotlinThreadLocal("state_thread_local$${file.fileEntry.name}", int32Type)
|
||||
codegen.addKotlinThreadLocal("state_thread_local$${file.fileEntry.name}", llvm.int32Type)
|
||||
}
|
||||
|
||||
override fun visitFunction(declaration: IrFunction) {
|
||||
@@ -952,7 +952,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
context.log{"visitField : ${ir2string(declaration)}"}
|
||||
debugFieldDeclaration(declaration)
|
||||
if (context.needGlobalInit(declaration)) {
|
||||
val type = codegen.getLLVMType(declaration.type)
|
||||
val type = declaration.type.toLLVMType(llvm)
|
||||
val globalPropertyAccess = context.generationState.llvmDeclarations.forStaticField(declaration).storageAddressAccess
|
||||
val initializer = declaration.initializer?.expression
|
||||
val globalProperty = (globalPropertyAccess as? GlobalAddressAccess)?.getAddress(null)
|
||||
@@ -1092,7 +1092,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
val valuePhi = if (type.isUnit()) {
|
||||
null
|
||||
} else {
|
||||
functionGenerationContext.phi(codegen.getLLVMType(type))
|
||||
functionGenerationContext.phi(type.toLLVMType(llvm))
|
||||
}
|
||||
|
||||
val result = ContinuationBlock(entry, valuePhi)
|
||||
@@ -1283,7 +1283,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
*/
|
||||
private inner class WhenEmittingContext(val expression: IrWhen, val lastBBOfWhenCases: LLVMBasicBlockRef) {
|
||||
val needsPhi = expression.branches.last().isUnconditional() && !expression.type.isUnit()
|
||||
val llvmType = codegen.getLLVMType(expression.type)
|
||||
val llvmType = expression.type.toLLVMType(llvm)
|
||||
|
||||
val bbExit = lazy {
|
||||
// bbExit must be positioned after all blocks of WHEN construct
|
||||
@@ -1540,8 +1540,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
assert(type.isPrimitiveInteger() || type.isUnsignedInteger())
|
||||
val result = evaluateExpression(value.argument)
|
||||
assert(value.argument.type.isInt())
|
||||
val llvmSrcType = codegen.getLLVMType(value.argument.type)
|
||||
val llvmDstType = codegen.getLLVMType(type)
|
||||
val llvmSrcType = value.argument.type.toLLVMType(llvm)
|
||||
val llvmDstType = type.toLLVMType(llvm)
|
||||
val srcWidth = LLVMGetIntTypeWidth(llvmSrcType)
|
||||
val dstWidth = LLVMGetIntTypeWidth(llvmDstType)
|
||||
return when {
|
||||
@@ -1583,7 +1583,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
null
|
||||
)
|
||||
} else {
|
||||
val dstTypeInfo = functionGenerationContext.bitcast(kInt8Ptr, codegen.typeInfoValue(dstClass))
|
||||
val dstTypeInfo = functionGenerationContext.bitcast(llvm.int8PtrType, codegen.typeInfoValue(dstClass))
|
||||
callDirect(
|
||||
context.ir.symbols.throwClassCastException.owner,
|
||||
listOf(srcArg, dstTypeInfo),
|
||||
@@ -1628,7 +1628,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
val bbInstanceOfResult = functionGenerationContext.currentBlock
|
||||
|
||||
functionGenerationContext.positionAtEnd(bbExit)
|
||||
val result = functionGenerationContext.phi(kBoolean)
|
||||
val result = functionGenerationContext.phi(llvm.int1Type)
|
||||
functionGenerationContext.addPhiIncoming(result, bbNull to resultNull, bbInstanceOfResult to resultInstanceOf)
|
||||
return result
|
||||
}
|
||||
@@ -1648,14 +1648,14 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
val dstHierarchyInfo = context.getLayoutBuilder(dstClass).hierarchyInfo
|
||||
if (!dstClass.isInterface) {
|
||||
call(llvm.isInstanceOfClassFastFunction,
|
||||
listOf(srcObjInfoPtr, Int32(dstHierarchyInfo.classIdLo).llvm, Int32(dstHierarchyInfo.classIdHi).llvm))
|
||||
listOf(srcObjInfoPtr, llvm.int32(dstHierarchyInfo.classIdLo), llvm.int32(dstHierarchyInfo.classIdHi)))
|
||||
} else {
|
||||
// Essentially: typeInfo.itable[place(interfaceId)].id == interfaceId
|
||||
val interfaceId = dstHierarchyInfo.interfaceId
|
||||
val typeInfo = functionGenerationContext.loadTypeInfo(srcObjInfoPtr)
|
||||
with(functionGenerationContext) {
|
||||
val interfaceTableRecord = lookupInterfaceTableRecord(typeInfo, interfaceId)
|
||||
icmpEq(load(structGep(interfaceTableRecord, 0 /* id */)), Int32(interfaceId).llvm)
|
||||
icmpEq(load(structGep(interfaceTableRecord, 0 /* id */)), llvm.int32(interfaceId))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1695,13 +1695,13 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
if (dstClass.isObjCMetaClass()) {
|
||||
val isClassProto = LlvmFunctionProto(
|
||||
"object_isClass",
|
||||
LlvmRetType(int8Type),
|
||||
listOf(LlvmParamType(int8TypePtr)),
|
||||
LlvmRetType(llvm.int8Type),
|
||||
listOf(LlvmParamType(llvm.int8PtrType)),
|
||||
origin = context.standardLlvmSymbolsOrigin
|
||||
)
|
||||
val isClass = llvm.externalFunction(isClassProto)
|
||||
call(isClass, listOf(objCObject)).let {
|
||||
functionGenerationContext.icmpNe(it, Int8(0).llvm)
|
||||
functionGenerationContext.icmpNe(it, llvm.int8(0))
|
||||
}
|
||||
} else if (dstClass.isObjCProtocolClass()) {
|
||||
// Note: it is not clear whether this class should be looked up this way.
|
||||
@@ -1848,22 +1848,18 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
context.log{"evaluateConst : ${ir2string(value)}"}
|
||||
/* This suppression against IrConst<String> */
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
when (value.kind) {
|
||||
IrConstKind.Null -> return constPointer(codegen.kNullObjHeaderPtr)
|
||||
IrConstKind.Boolean -> when (value.value) {
|
||||
true -> return Int1(true)
|
||||
false -> return Int1(false)
|
||||
}
|
||||
IrConstKind.Char -> return Char16(value.value as Char)
|
||||
IrConstKind.Byte -> return Int8(value.value as Byte)
|
||||
IrConstKind.Short -> return Int16(value.value as Short)
|
||||
IrConstKind.Int -> return Int32(value.value as Int)
|
||||
IrConstKind.Long -> return Int64(value.value as Long)
|
||||
IrConstKind.String -> return evaluateStringConst(value as IrConst<String>)
|
||||
IrConstKind.Float -> return Float32(value.value as Float)
|
||||
IrConstKind.Double -> return Float64(value.value as Double)
|
||||
return when (value.kind) {
|
||||
IrConstKind.Null -> constPointer(codegen.kNullObjHeaderPtr)
|
||||
IrConstKind.Boolean -> llvm.constInt1(value.value as Boolean)
|
||||
IrConstKind.Char -> llvm.constChar16(value.value as Char)
|
||||
IrConstKind.Byte -> llvm.constInt8(value.value as Byte)
|
||||
IrConstKind.Short -> llvm.constInt16(value.value as Short)
|
||||
IrConstKind.Int -> llvm.constInt32(value.value as Int)
|
||||
IrConstKind.Long -> llvm.constInt64(value.value as Long)
|
||||
IrConstKind.String -> evaluateStringConst(value as IrConst<String>)
|
||||
IrConstKind.Float -> llvm.constFloat32(value.value as Float)
|
||||
IrConstKind.Double -> llvm.constFloat64(value.value as Double)
|
||||
}
|
||||
TODO(ir2string(value))
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
@@ -1893,9 +1889,9 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
val constructedType = value.value.type
|
||||
if (context.ir.symbols.getTypeConversion(constructedType, value.type) != null) {
|
||||
if (value.value.kind == IrConstKind.Null) {
|
||||
Zero(codegen.getLLVMType(value.type))
|
||||
Zero(value.type.toLLVMType(llvm))
|
||||
} else {
|
||||
require(codegen.getLLVMType(value.type) == codegen.kObjHeaderPtr) {
|
||||
require(value.type.toLLVMType(llvm) == codegen.kObjHeaderPtr) {
|
||||
"Can't wrap ${value.value.kind.asString} constant to type ${value.type.render()}"
|
||||
}
|
||||
value.toBoxCacheValue(context) ?: llvm.staticData.createConstKotlinObject(
|
||||
@@ -1941,7 +1937,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
}
|
||||
}
|
||||
|
||||
require(codegen.getLLVMType(value.type) == codegen.kObjHeaderPtr) { "Constant object is not an object, but ${value.type.render()}" }
|
||||
require(value.type.toLLVMType(llvm) == codegen.kObjHeaderPtr) { "Constant object is not an object, but ${value.type.render()}" }
|
||||
llvm.staticData.createConstKotlinObject(
|
||||
constructedClass,
|
||||
*fields.toTypedArray()
|
||||
@@ -1993,7 +1989,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
if (resultPhi == null) {
|
||||
val bbCurrent = functionGenerationContext.currentBlock
|
||||
functionGenerationContext.positionAtEnd(getExit())
|
||||
resultPhi = functionGenerationContext.phi(codegen.getLLVMType(returnableBlock.type))
|
||||
resultPhi = functionGenerationContext.phi(returnableBlock.type.toLLVMType(llvm))
|
||||
functionGenerationContext.positionAtEnd(bbCurrent)
|
||||
}
|
||||
return resultPhi!!
|
||||
@@ -2102,7 +2098,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
return returnableBlockScope.resultPhi ?: if (value.type.isUnit()) {
|
||||
codegen.theUnitInstanceRef.llvm
|
||||
} else {
|
||||
LLVMGetUndef(codegen.getLLVMType(value.type))!!
|
||||
LLVMGetUndef(value.type.toLLVMType(llvm))!!
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2349,7 +2345,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
val resumePoints = mutableListOf<LLVMBasicBlockRef>()
|
||||
using (SuspendableExpressionScope(resumePoints)) {
|
||||
functionGenerationContext.condBr(functionGenerationContext.icmpEq(suspensionPointId, kNullInt8Ptr), bbStart, bbDispatch)
|
||||
functionGenerationContext.condBr(functionGenerationContext.icmpEq(suspensionPointId, llvm.kNullInt8Ptr), bbStart, bbDispatch)
|
||||
|
||||
functionGenerationContext.positionAtEnd(bbStart)
|
||||
val result = evaluateExpression(expression.result, resultSlot)
|
||||
@@ -2362,8 +2358,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
functionGenerationContext.unreachable()
|
||||
}
|
||||
|
||||
val cases = resumePoints.withIndex().map { Int32(it.index + 1).llvm to it.value }
|
||||
functionGenerationContext.switch(functionGenerationContext.ptrToInt(suspensionPointId, int32Type), cases, bbElse)
|
||||
val cases = resumePoints.withIndex().map { llvm.int32(it.index + 1) to it.value }
|
||||
functionGenerationContext.switch(functionGenerationContext.ptrToInt(suspensionPointId, llvm.int32Type), cases, bbElse)
|
||||
}
|
||||
}
|
||||
return result
|
||||
@@ -2378,7 +2374,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
return if (context.config.indirectBranchesAreAllowed)
|
||||
functionGenerationContext.blockAddress(bbResume)
|
||||
else
|
||||
functionGenerationContext.intToPtr(Int32(bbResumeId + 1).llvm, int8TypePtr)
|
||||
functionGenerationContext.intToPtr(llvm.int32(bbResumeId + 1), llvm.int8PtrType)
|
||||
}
|
||||
return super.genGetValue(value, resultSlot)
|
||||
}
|
||||
@@ -2407,7 +2403,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
private fun evaluateClassReference(classReference: IrClassReference): LLVMValueRef {
|
||||
val typeInfoPtr = codegen.typeInfoValue(classReference.symbol.owner as IrClass)
|
||||
return functionGenerationContext.bitcast(int8TypePtr, typeInfoPtr)
|
||||
return functionGenerationContext.bitcast(llvm.int8PtrType, typeInfoPtr)
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
@@ -2437,7 +2433,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
moveBlockAfterEntry(bbInit)
|
||||
val state = load(statePtr)
|
||||
LLVMSetOrdering(state, LLVMAtomicOrdering.LLVMAtomicOrderingAcquire)
|
||||
condBr(icmpEq(state, Int32(FILE_INITIALIZED).llvm), bbExit, bbInit)
|
||||
condBr(icmpEq(state, llvm.int32(FILE_INITIALIZED)), bbExit, bbInit)
|
||||
positionAtEnd(bbInit)
|
||||
call(llvm.callInitGlobalPossiblyLock, listOf(statePtr, initializerPtr),
|
||||
exceptionHandler = currentCodeContext.exceptionHandler)
|
||||
@@ -2462,9 +2458,9 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
LLVMSetVolatile(globalState, 1)
|
||||
// Make sure we're not in the middle of global initializer invocation -
|
||||
// thread locals can be initialized only after all shared globals have been initialized.
|
||||
condBr(icmpNe(globalState, Int32(FILE_INITIALIZED).llvm), bbExit, bbCheckLocalState)
|
||||
condBr(icmpNe(globalState, llvm.int32(FILE_INITIALIZED)), bbExit, bbCheckLocalState)
|
||||
positionAtEnd(bbCheckLocalState)
|
||||
condBr(icmpNe(load(localStatePtr), Int32(FILE_INITIALIZED).llvm), bbInit, bbExit)
|
||||
condBr(icmpNe(load(localStatePtr), llvm.int32(FILE_INITIALIZED)), bbInit, bbExit)
|
||||
positionAtEnd(bbInit)
|
||||
call(llvm.callInitThreadLocal, listOf(globalStatePtr, localStatePtr, initializerPtr),
|
||||
exceptionHandler = currentCodeContext.exceptionHandler)
|
||||
@@ -2482,9 +2478,9 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
val bbExit = basicBlock("label_continue", null)
|
||||
moveBlockAfterEntry(bbExit)
|
||||
moveBlockAfterEntry(bbInit)
|
||||
condBr(icmpEq(load(statePtr), Int32(FILE_INITIALIZED).llvm), bbExit, bbInit)
|
||||
condBr(icmpEq(load(statePtr), llvm.int32(FILE_INITIALIZED)), bbExit, bbInit)
|
||||
positionAtEnd(bbInit)
|
||||
call(llvm.callInitThreadLocal, listOf(kNullInt32Ptr, statePtr, initializerPtr),
|
||||
call(llvm.callInitThreadLocal, listOf(llvm.kNullInt32Ptr, statePtr, initializerPtr),
|
||||
exceptionHandler = currentCodeContext.exceptionHandler)
|
||||
br(bbExit)
|
||||
positionAtEnd(bbExit)
|
||||
@@ -2514,14 +2510,14 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
val constructedClass = callee.symbol.owner.constructedClass
|
||||
val thisValue = when {
|
||||
constructedClass.isArray -> {
|
||||
assert(args.isNotEmpty() && args[0].type == int32Type)
|
||||
assert(args.isNotEmpty() && args[0].type == llvm.int32Type)
|
||||
functionGenerationContext.allocArray(constructedClass, args[0],
|
||||
resultLifetime(callee), currentCodeContext.exceptionHandler, resultSlot = resultSlot)
|
||||
}
|
||||
constructedClass == context.ir.symbols.string.owner -> {
|
||||
// TODO: consider returning the empty string literal instead.
|
||||
assert(args.isEmpty())
|
||||
functionGenerationContext.allocArray(constructedClass, count = kImmZero,
|
||||
functionGenerationContext.allocArray(constructedClass, count = llvm.kImmInt32Zero,
|
||||
lifetime = resultLifetime(callee), exceptionHandler = currentCodeContext.exceptionHandler, resultSlot = resultSlot)
|
||||
}
|
||||
|
||||
@@ -2550,7 +2546,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
val protocolGetterName = annotation.getAnnotationStringValue("protocolGetter")
|
||||
val protocolGetterProto = LlvmFunctionProto(
|
||||
protocolGetterName,
|
||||
LlvmRetType(int8TypePtr),
|
||||
LlvmRetType(llvm.int8PtrType),
|
||||
origin = irClass.llvmSymbolOrigin,
|
||||
independent = true // Protocol is header-only declaration.
|
||||
)
|
||||
@@ -2560,10 +2556,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
private val kImmZero = Int32(0).llvm
|
||||
private val kImmOne = Int32(1).llvm
|
||||
private val kTrue = Int1(true).llvm
|
||||
private val kFalse = Int1(false).llvm
|
||||
private val kTrue = llvm.int1(true)
|
||||
private val kFalse = llvm.int1(false)
|
||||
|
||||
// TODO: Intrinsify?
|
||||
private fun evaluateOperatorCall(callee: IrCall, args: List<LLVMValueRef>): LLVMValueRef {
|
||||
@@ -2678,7 +2672,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
needsNativeThreadState -> functionGenerationContext.switchThreadState(ThreadState.Runnable)
|
||||
}
|
||||
|
||||
if (llvmCallable.returnType == voidType) {
|
||||
if (llvmCallable.returnType == llvm.voidType) {
|
||||
return codegen.theUnitInstanceRef.llvm
|
||||
}
|
||||
|
||||
@@ -2706,7 +2700,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
return codegen.theUnitInstanceRef.llvm
|
||||
}
|
||||
|
||||
val thisPtrArgType = codegen.getLLVMType(constructor.allParameters[0].type)
|
||||
val thisPtrArgType = constructor.allParameters[0].type.toLLVMType(llvm)
|
||||
val thisPtrArg = if (thisPtr.type == thisPtrArgType) {
|
||||
thisPtr
|
||||
} else {
|
||||
@@ -2723,8 +2717,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
private fun appendLlvmUsed(name: String, args: List<LLVMValueRef>) {
|
||||
if (args.isEmpty()) return
|
||||
|
||||
val argsCasted = args.map { constPointer(it).bitcast(int8TypePtr) }
|
||||
val llvmUsedGlobal = llvm.staticData.placeGlobalArray(name, int8TypePtr, argsCasted)
|
||||
val argsCasted = args.map { constPointer(it).bitcast(llvm.int8PtrType) }
|
||||
val llvmUsedGlobal = llvm.staticData.placeGlobalArray(name, llvm.int8PtrType, argsCasted)
|
||||
|
||||
LLVMSetLinkage(llvmUsedGlobal.llvmGlobal, LLVMLinkage.LLVMAppendingLinkage)
|
||||
LLVMSetSection(llvmUsedGlobal.llvmGlobal, "llvm.metadata")
|
||||
@@ -2737,7 +2731,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
// When some dynamic caches are used, we consider that stdlib is in the dynamic cache as well.
|
||||
// Runtime is linked into stdlib module only, so import runtime global from it.
|
||||
val global = codegen.importGlobal(name, value.llvmType, context.standardLlvmSymbolsOrigin)
|
||||
val initializer = generateFunctionNoRuntime(codegen, functionType(voidType, false), "") {
|
||||
val initializer = generateFunctionNoRuntime(codegen, functionType(llvm.voidType, false), "") {
|
||||
store(value.llvm, global)
|
||||
ret(null)
|
||||
}
|
||||
@@ -2761,10 +2755,10 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
if (!context.config.isFinalBinary)
|
||||
return
|
||||
|
||||
overrideRuntimeGlobal("Kotlin_destroyRuntimeMode", Int32(context.config.destroyRuntimeMode.value))
|
||||
overrideRuntimeGlobal("Kotlin_gcMarkSingleThreaded", Int32(if (context.config.gcMarkSingleThreaded) 1 else 0))
|
||||
overrideRuntimeGlobal("Kotlin_workerExceptionHandling", Int32(context.config.workerExceptionHandling.value))
|
||||
overrideRuntimeGlobal("Kotlin_suspendFunctionsFromAnyThreadFromObjC", Int32(if (context.config.suspendFunctionsFromAnyThreadFromObjC) 1 else 0))
|
||||
overrideRuntimeGlobal("Kotlin_destroyRuntimeMode", llvm.constInt32(context.config.destroyRuntimeMode.value))
|
||||
overrideRuntimeGlobal("Kotlin_gcMarkSingleThreaded", llvm.constInt32(if (context.config.gcMarkSingleThreaded) 1 else 0))
|
||||
overrideRuntimeGlobal("Kotlin_workerExceptionHandling", llvm.constInt32(context.config.workerExceptionHandling.value))
|
||||
overrideRuntimeGlobal("Kotlin_suspendFunctionsFromAnyThreadFromObjC", llvm.constInt32(if (context.config.suspendFunctionsFromAnyThreadFromObjC) 1 else 0))
|
||||
val getSourceInfoFunctionName = when (context.config.sourceInfoType) {
|
||||
SourceInfoType.NOOP -> null
|
||||
SourceInfoType.LIBBACKTRACE -> "Kotlin_getSourceInfo_libbacktrace"
|
||||
@@ -2773,23 +2767,23 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
if (getSourceInfoFunctionName != null) {
|
||||
val getSourceInfoFunction = LLVMGetNamedFunction(llvm.module, getSourceInfoFunctionName)
|
||||
?: LLVMAddFunction(llvm.module, getSourceInfoFunctionName,
|
||||
functionType(int32Type, false, int8TypePtr, int8TypePtr, int32Type))
|
||||
functionType(llvm.int32Type, false, llvm.int8PtrType, llvm.int8PtrType, llvm.int32Type))
|
||||
overrideRuntimeGlobal("Kotlin_getSourceInfo_Function", constValue(getSourceInfoFunction!!))
|
||||
}
|
||||
if (context.config.target.family == Family.ANDROID && context.config.produce == CompilerOutputKind.PROGRAM) {
|
||||
val configuration = context.config.configuration
|
||||
val programType = configuration.get(BinaryOptions.androidProgramType) ?: AndroidProgramType.Default
|
||||
overrideRuntimeGlobal("Kotlin_printToAndroidLogcat", Int32(if (programType.consolePrintsToLogcat) 1 else 0))
|
||||
overrideRuntimeGlobal("Kotlin_printToAndroidLogcat", llvm.constInt32(if (programType.consolePrintsToLogcat) 1 else 0))
|
||||
}
|
||||
overrideRuntimeGlobal("Kotlin_appStateTracking", Int32(context.config.appStateTracking.value))
|
||||
overrideRuntimeGlobal("Kotlin_mimallocUseDefaultOptions", Int32(if (context.config.mimallocUseDefaultOptions) 1 else 0))
|
||||
overrideRuntimeGlobal("Kotlin_mimallocUseCompaction", Int32(if (context.config.mimallocUseCompaction) 1 else 0))
|
||||
overrideRuntimeGlobal("Kotlin_appStateTracking", llvm.constInt32(context.config.appStateTracking.value))
|
||||
overrideRuntimeGlobal("Kotlin_mimallocUseDefaultOptions", llvm.constInt32(if (context.config.mimallocUseDefaultOptions) 1 else 0))
|
||||
overrideRuntimeGlobal("Kotlin_mimallocUseCompaction", llvm.constInt32(if (context.config.mimallocUseCompaction) 1 else 0))
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
// Create type { i32, void ()*, i8* }
|
||||
|
||||
val kCtorType = structType(int32Type, pointerType(kVoidFuncType), kInt8Ptr)
|
||||
val kCtorType = llvm.structType(llvm.int32Type, pointerType(kVoidFuncType), llvm.int8PtrType)
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
// Create object { i32, void ()*, i8* } { i32 1, void ()* @ctorFunction, i8* null }
|
||||
@@ -2800,15 +2794,15 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
// '.ctors' section instead of '.ctors.XXXXX', which can't be recognized by ld
|
||||
// when string table is too long.
|
||||
// More details: https://youtrack.jetbrains.com/issue/KT-39548
|
||||
Int32(65535).llvm
|
||||
llvm.int32(65535)
|
||||
// Note: this difference in priorities doesn't actually make initializers
|
||||
// platform-dependent, because handling priorities for initializers
|
||||
// from different object files is platform-dependent anyway.
|
||||
} else {
|
||||
kImmInt32One
|
||||
llvm.kImmInt32One
|
||||
}
|
||||
val data = kNullInt8Ptr
|
||||
val argList = cValuesOf(priority, ctorFunction, data)
|
||||
val data = llvm.kNullInt8Ptr
|
||||
val argList = cValuesOf(priority, ctorFunction, data)
|
||||
val ctorItem = LLVMConstNamedStruct(kCtorType, argList, 3)!!
|
||||
return constPointer(ctorItem)
|
||||
}
|
||||
@@ -2885,22 +2879,22 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
private fun appendStaticInitializers(ctorFunction: LLVMValueRef, initializers: List<LLVMValueRef>) {
|
||||
generateFunctionNoRuntime(codegen, ctorFunction) {
|
||||
val initGuardName = ctorFunction.name.orEmpty() + "_guard"
|
||||
val initGuard = LLVMAddGlobal(llvm.module, int32Type, initGuardName)
|
||||
LLVMSetInitializer(initGuard, kImmZero)
|
||||
val initGuard = LLVMAddGlobal(llvm.module, llvm.int32Type, initGuardName)
|
||||
LLVMSetInitializer(initGuard, llvm.kImmInt32Zero)
|
||||
LLVMSetLinkage(initGuard, LLVMLinkage.LLVMPrivateLinkage)
|
||||
val bbInited = basicBlock("inited", null)
|
||||
val bbNeedInit = basicBlock("need_init", null)
|
||||
|
||||
|
||||
val value = LLVMBuildLoad(builder, initGuard, "")!!
|
||||
condBr(icmpEq(value, kImmZero), bbNeedInit, bbInited)
|
||||
condBr(icmpEq(value, llvm.kImmInt32Zero), bbNeedInit, bbInited)
|
||||
|
||||
appendingTo(bbInited) {
|
||||
ret(null)
|
||||
}
|
||||
|
||||
appendingTo(bbNeedInit) {
|
||||
LLVMBuildStore(builder, kImmOne, initGuard)
|
||||
LLVMBuildStore(builder, llvm.kImmInt32One, initGuard)
|
||||
|
||||
// TODO: shall we put that into the try block?
|
||||
initializers.forEach {
|
||||
@@ -2970,9 +2964,10 @@ internal class LocationInfo(val scope: DIScopeOpaqueRef,
|
||||
val inlinedAt: LocationInfo? = null)
|
||||
|
||||
internal fun Context.generateRuntimeConstantsModule() : LLVMModuleRef {
|
||||
val llvmModule = LLVMModuleCreateWithNameInContext("constants", llvmContext)!!
|
||||
val llvm = generationState.llvm
|
||||
val llvmModule = LLVMModuleCreateWithNameInContext("constants", generationState.llvmContext)!!
|
||||
LLVMSetDataLayout(llvmModule, generationState.runtime.dataLayout)
|
||||
val static = StaticData(llvmModule)
|
||||
val static = StaticData(llvmModule, llvm)
|
||||
|
||||
fun setRuntimeConstGlobal(name: String, value: ConstValue) {
|
||||
val global = static.placeGlobal(name, value)
|
||||
@@ -2980,15 +2975,15 @@ internal fun Context.generateRuntimeConstantsModule() : LLVMModuleRef {
|
||||
global.setLinkage(LLVMLinkage.LLVMExternalLinkage)
|
||||
}
|
||||
|
||||
setRuntimeConstGlobal("Kotlin_needDebugInfo", Int32(if (shouldContainDebugInfo()) 1 else 0))
|
||||
setRuntimeConstGlobal("Kotlin_runtimeAssertsMode", Int32(config.runtimeAssertsMode.value))
|
||||
setRuntimeConstGlobal("Kotlin_needDebugInfo", llvm.constInt32(if (shouldContainDebugInfo()) 1 else 0))
|
||||
setRuntimeConstGlobal("Kotlin_runtimeAssertsMode", llvm.constInt32(config.runtimeAssertsMode.value))
|
||||
val runtimeLogs = config.runtimeLogs?.let {
|
||||
static.cStringLiteral(it)
|
||||
} ?: NullPointer(int8Type)
|
||||
} ?: NullPointer(llvm.int8Type)
|
||||
setRuntimeConstGlobal("Kotlin_runtimeLogs", runtimeLogs)
|
||||
setRuntimeConstGlobal("Kotlin_freezingEnabled", Int32(if (config.freezing.enableFreezeAtRuntime) 1 else 0))
|
||||
setRuntimeConstGlobal("Kotlin_freezingChecksEnabled", Int32(if (config.freezing.enableFreezeChecks) 1 else 0))
|
||||
setRuntimeConstGlobal("Kotlin_gcSchedulerType", Int32(config.gcSchedulerType.value))
|
||||
setRuntimeConstGlobal("Kotlin_freezingEnabled", llvm.constInt32(if (config.freezing.enableFreezeAtRuntime) 1 else 0))
|
||||
setRuntimeConstGlobal("Kotlin_freezingChecksEnabled", llvm.constInt32(if (config.freezing.enableFreezeChecks) 1 else 0))
|
||||
setRuntimeConstGlobal("Kotlin_gcSchedulerType", llvm.constInt32(config.gcSchedulerType.value))
|
||||
|
||||
return llvmModule
|
||||
}
|
||||
|
||||
+19
-19
@@ -39,37 +39,37 @@ internal class KotlinObjCClassInfoGenerator(override val context: Context) : Con
|
||||
val exportedClassName = selectExportedClassName(irClass)
|
||||
val className = exportedClassName ?: selectInternalClassName(irClass)
|
||||
|
||||
val classNameLiteral = className?.let { staticData.cStringLiteral(it) } ?: NullPointer(int8Type)
|
||||
val classNameLiteral = className?.let { staticData.cStringLiteral(it) } ?: NullPointer(llvm.int8Type)
|
||||
val info = Struct(runtime.kotlinObjCClassInfo,
|
||||
classNameLiteral,
|
||||
Int32(if (exportedClassName != null) 1 else 0),
|
||||
classNameLiteral,
|
||||
llvm.constInt32(if (exportedClassName != null) 1 else 0),
|
||||
|
||||
staticData.cStringLiteral(superclassName),
|
||||
staticData.placeGlobalConstArray("", int8TypePtr,
|
||||
protocolNames.map { staticData.cStringLiteral(it) } + NullPointer(int8Type)),
|
||||
staticData.cStringLiteral(superclassName),
|
||||
staticData.placeGlobalConstArray("", llvm.int8PtrType,
|
||||
protocolNames.map { staticData.cStringLiteral(it) } + NullPointer(llvm.int8Type)),
|
||||
|
||||
staticData.placeGlobalConstArray("", runtime.objCMethodDescription, instanceMethods),
|
||||
Int32(instanceMethods.size),
|
||||
staticData.placeGlobalConstArray("", runtime.objCMethodDescription, instanceMethods),
|
||||
llvm.constInt32(instanceMethods.size),
|
||||
|
||||
staticData.placeGlobalConstArray("", runtime.objCMethodDescription, classMethods),
|
||||
Int32(classMethods.size),
|
||||
staticData.placeGlobalConstArray("", runtime.objCMethodDescription, classMethods),
|
||||
llvm.constInt32(classMethods.size),
|
||||
|
||||
objCLLvmDeclarations.bodyOffsetGlobal.pointer,
|
||||
objCLLvmDeclarations.bodyOffsetGlobal.pointer,
|
||||
|
||||
irClass.typeInfoPtr,
|
||||
companionObject?.typeInfoPtr ?: NullPointer(runtime.typeInfoType),
|
||||
irClass.typeInfoPtr,
|
||||
companionObject?.typeInfoPtr ?: NullPointer(runtime.typeInfoType),
|
||||
|
||||
staticData.placeGlobal(
|
||||
staticData.placeGlobal(
|
||||
"kobjcclassptr:${irClass.fqNameForIrSerialization}#internal",
|
||||
NullPointer(int8Type)
|
||||
NullPointer(llvm.int8Type)
|
||||
).pointer,
|
||||
|
||||
generateClassDataImp(irClass)
|
||||
generateClassDataImp(irClass)
|
||||
)
|
||||
|
||||
objCLLvmDeclarations.classInfoGlobal.setInitializer(info)
|
||||
|
||||
objCLLvmDeclarations.bodyOffsetGlobal.setInitializer(Int32(0))
|
||||
objCLLvmDeclarations.bodyOffsetGlobal.setInitializer(llvm.constInt32(0))
|
||||
}
|
||||
|
||||
private fun IrClass.generateMethodDescs(): List<ObjCMethodDesc> = this.generateImpMethodDescs()
|
||||
@@ -105,7 +105,7 @@ internal class KotlinObjCClassInfoGenerator(override val context: Context) : Con
|
||||
null // Generate as anonymous.
|
||||
}
|
||||
|
||||
private val impType = pointerType(functionType(int8TypePtr, true, int8TypePtr, int8TypePtr))
|
||||
private val impType = pointerType(functionType(llvm.int8PtrType, true, llvm.int8PtrType, llvm.int8PtrType))
|
||||
|
||||
private inner class ObjCMethodDesc(
|
||||
val selector: String, val encoding: String, val impFunction: LLVMValueRef
|
||||
@@ -136,7 +136,7 @@ internal class KotlinObjCClassInfoGenerator(override val context: Context) : Con
|
||||
Zero(runtime.kotlinObjCClassData)
|
||||
).pointer
|
||||
|
||||
val functionType = functionType(classDataPointer.llvmType, false, int8TypePtr, int8TypePtr)
|
||||
val functionType = functionType(classDataPointer.llvmType, false, llvm.int8PtrType, llvm.int8PtrType)
|
||||
val functionName = "kobjcclassdataimp:${irClass.fqNameForIrSerialization}#internal"
|
||||
|
||||
val function = generateFunctionNoRuntime(codegen, functionType, functionName) {
|
||||
|
||||
+13
-13
@@ -12,17 +12,17 @@ import org.jetbrains.kotlin.backend.konan.ir.llvmSymbolOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConst
|
||||
|
||||
private fun ConstPointer.add(index: Int): ConstPointer {
|
||||
return constPointer(LLVMConstGEP(llvm, cValuesOf(Int32(index).llvm), 1)!!)
|
||||
private fun ConstPointer.add(index: LLVMValueRef): ConstPointer {
|
||||
return constPointer(LLVMConstGEP(llvm, cValuesOf(index), 1)!!)
|
||||
}
|
||||
|
||||
internal class KotlinStaticData(override val context: Context, module: LLVMModuleRef) : ContextUtils, StaticData(module) {
|
||||
internal class KotlinStaticData(override val context: Context, override val llvm: Llvm, module: LLVMModuleRef) : ContextUtils, StaticData(module, llvm) {
|
||||
private val stringLiterals = mutableMapOf<String, ConstPointer>()
|
||||
|
||||
// Must match OBJECT_TAG_PERMANENT_CONTAINER in C++.
|
||||
private fun permanentTag(typeInfo: ConstPointer): ConstPointer {
|
||||
// Only pointer arithmetic via GEP works on constant pointers in LLVM.
|
||||
return typeInfo.bitcast(int8TypePtr).add(1).bitcast(kTypeInfoPtr)
|
||||
return typeInfo.bitcast(llvm.int8PtrType).add(llvm.int32(1)).bitcast(kTypeInfoPtr)
|
||||
}
|
||||
|
||||
|
||||
@@ -32,13 +32,13 @@ internal class KotlinStaticData(override val context: Context, module: LLVMModul
|
||||
|
||||
private fun arrayHeader(typeInfo: ConstPointer, length: Int): Struct {
|
||||
assert(length >= 0)
|
||||
return Struct(runtime.arrayHeaderType, permanentTag(typeInfo), Int32(length))
|
||||
return Struct(runtime.arrayHeaderType, permanentTag(typeInfo), llvm.constInt32(length))
|
||||
}
|
||||
|
||||
private fun createRef(objHeaderPtr: ConstPointer) = objHeaderPtr.bitcast(kObjHeaderPtr)
|
||||
|
||||
private fun createKotlinStringLiteral(value: String): ConstPointer {
|
||||
val elements = value.toCharArray().map(::Char16)
|
||||
val elements = value.toCharArray().map(llvm::constChar16)
|
||||
val objRef = createConstKotlinArray(context.ir.symbols.string.owner, elements)
|
||||
return objRef
|
||||
}
|
||||
@@ -51,15 +51,15 @@ internal class KotlinStaticData(override val context: Context, module: LLVMModul
|
||||
fun createConstKotlinArray(arrayClass: IrClass, elements: List<ConstValue>): ConstPointer {
|
||||
val typeInfo = arrayClass.typeInfoPtr
|
||||
|
||||
val bodyElementType: LLVMTypeRef = elements.firstOrNull()?.llvmType ?: int8Type
|
||||
val bodyElementType: LLVMTypeRef = elements.firstOrNull()?.llvmType ?: llvm.int8Type
|
||||
// (use [0 x i8] as body if there are no elements)
|
||||
val arrayBody = ConstArray(bodyElementType, elements)
|
||||
|
||||
val compositeType = structType(runtime.arrayHeaderType, arrayBody.llvmType)
|
||||
val compositeType = llvm.structType(runtime.arrayHeaderType, arrayBody.llvmType)
|
||||
|
||||
val global = this.createGlobal(compositeType, "")
|
||||
|
||||
val objHeaderPtr = global.pointer.getElementPtr(0)
|
||||
val objHeaderPtr = global.pointer.getElementPtr(llvm, 0)
|
||||
val arrayHeader = arrayHeader(typeInfo, elements.size)
|
||||
|
||||
global.setInitializer(Struct(compositeType, arrayHeader, arrayBody))
|
||||
@@ -73,17 +73,17 @@ internal class KotlinStaticData(override val context: Context, module: LLVMModul
|
||||
val typeInfo = type.typeInfoPtr
|
||||
val objHeader = objHeader(typeInfo)
|
||||
|
||||
val global = this.placeGlobal("", Struct(objHeader, *fields))
|
||||
val global = this.placeGlobal("", llvm.struct(objHeader, *fields))
|
||||
global.setUnnamedAddr(true)
|
||||
global.setConstant(true)
|
||||
|
||||
val objHeaderPtr = global.pointer.getElementPtr(0)
|
||||
val objHeaderPtr = global.pointer.getElementPtr(llvm, 0)
|
||||
|
||||
return createRef(objHeaderPtr)
|
||||
}
|
||||
|
||||
fun createInitializer(type: IrClass, vararg fields: ConstValue): ConstValue =
|
||||
Struct(objHeader(type.typeInfoPtr), *fields)
|
||||
llvm.struct(objHeader(type.typeInfoPtr), *fields)
|
||||
|
||||
fun createUniqueInstance(
|
||||
kind: UniqueKind, bodyType: LLVMTypeRef, typeInfo: ConstPointer): ConstPointer {
|
||||
@@ -117,7 +117,7 @@ internal class KotlinStaticData(override val context: Context, module: LLVMModul
|
||||
* @param args data for constant creation.
|
||||
*/
|
||||
fun createImmutableBlob(value: IrConst<String>): LLVMValueRef {
|
||||
val args = value.value.map { Int8(it.code.toByte()).llvm }
|
||||
val args = value.value.map { llvm.int8(it.code.toByte()) }
|
||||
return createConstKotlinArray(context.ir.symbols.immutableBlob.owner, args)
|
||||
}
|
||||
}
|
||||
|
||||
+10
-10
@@ -81,14 +81,14 @@ internal class StaticFieldLlvmDeclarations(val storageAddressAccess: AddressAcce
|
||||
internal class UniqueLlvmDeclarations(val pointer: ConstPointer)
|
||||
|
||||
private fun ContextUtils.createClassBodyType(name: String, fields: List<ClassLayoutBuilder.FieldInfo>): LLVMTypeRef {
|
||||
val fieldTypes = listOf(runtime.objHeaderType) + fields.map { getLLVMType(it.type) }
|
||||
val fieldTypes = listOf(runtime.objHeaderType) + fields.map { it.type.toLLVMType(llvm) }
|
||||
// TODO: consider adding synthetic ObjHeader field to Any.
|
||||
|
||||
val classType = LLVMStructCreateNamed(LLVMGetModuleContext(llvm.module), name)!!
|
||||
|
||||
// LLVMStructSetBody expects the struct to be properly aligned and will insert padding accordingly. In our case
|
||||
// `allocInstance` returns 16x + 8 address, i.e. always misaligned for vector types. Workaround is to use packed struct.
|
||||
val hasBigAlignment = fields.any { LLVMABIAlignmentOfType(runtime.targetData, getLLVMType(it.type)) > 8 }
|
||||
val hasBigAlignment = fields.any { LLVMABIAlignmentOfType(runtime.targetData, it.type.toLLVMType(llvm)) > 8 }
|
||||
val packed = if (hasBigAlignment) 1 else 0
|
||||
LLVMStructSetBody(classType, fieldTypes.toCValues(), fieldTypes.size, packed)
|
||||
|
||||
@@ -184,16 +184,16 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
|
||||
val typeInfoGlobalName = "ktypeglobal:$internalName"
|
||||
|
||||
val typeInfoWithVtableType = structType(
|
||||
val typeInfoWithVtableType = llvm.structType(
|
||||
runtime.typeInfoType,
|
||||
LLVMArrayType(int8TypePtr, context.getLayoutBuilder(declaration).vtableEntries.size)!!
|
||||
LLVMArrayType(llvm.int8PtrType, context.getLayoutBuilder(declaration).vtableEntries.size)!!
|
||||
)
|
||||
|
||||
typeInfoGlobal = staticData.createGlobal(typeInfoWithVtableType, typeInfoGlobalName, isExported = false)
|
||||
|
||||
val llvmTypeInfoPtr = LLVMAddAlias(llvm.module,
|
||||
kTypeInfoPtr,
|
||||
typeInfoGlobal.pointer.getElementPtr(0).llvm,
|
||||
typeInfoGlobal.pointer.getElementPtr(llvm, 0).llvm,
|
||||
typeInfoSymbolName)!!
|
||||
|
||||
if (declaration.isExported()) {
|
||||
@@ -278,9 +278,9 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
"kobjref:" + qualifyInternalName(irClass)
|
||||
}
|
||||
val instanceAddress = if (threadLocal) {
|
||||
addKotlinThreadLocal(symbolName, getLLVMType(irClass.defaultType))
|
||||
addKotlinThreadLocal(symbolName, irClass.defaultType.toLLVMType(llvm))
|
||||
} else {
|
||||
addKotlinGlobal(symbolName, getLLVMType(irClass.defaultType), isExported)
|
||||
addKotlinGlobal(symbolName, irClass.defaultType.toLLVMType(llvm), isExported)
|
||||
}
|
||||
|
||||
return SingletonLlvmDeclarations(instanceAddress)
|
||||
@@ -303,7 +303,7 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
setConstant(true)
|
||||
}
|
||||
|
||||
val bodyOffsetGlobal = staticData.createGlobal(int32Type, "kobjcbodyoffs:$internalName")
|
||||
val bodyOffsetGlobal = staticData.createGlobal(llvm.int32Type, "kobjcbodyoffs:$internalName")
|
||||
|
||||
return KotlinObjCClassLlvmDeclarations(classInfoGlobal, bodyOffsetGlobal)
|
||||
}
|
||||
@@ -330,9 +330,9 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
// Fields are module-private, so we use internal name:
|
||||
val name = "kvar:" + qualifyInternalName(declaration)
|
||||
val storage = if (declaration.storageKind(context) == FieldStorageKind.THREAD_LOCAL) {
|
||||
addKotlinThreadLocal(name, getLLVMType(declaration.type))
|
||||
addKotlinThreadLocal(name, declaration.type.toLLVMType(llvm))
|
||||
} else {
|
||||
addKotlinGlobal(name, getLLVMType(declaration.type), isExported = false)
|
||||
addKotlinGlobal(name, declaration.type.toLLVMType(llvm), isExported = false)
|
||||
}
|
||||
|
||||
declaration.metadata = CodegenStaticFieldMetadata(
|
||||
|
||||
+3
-2
@@ -6,11 +6,12 @@
|
||||
package org.jetbrains.kotlin.backend.konan.llvm
|
||||
|
||||
import llvm.LLVMAddNamedMetadataOperand
|
||||
import llvm.LLVMContextRef
|
||||
import llvm.LLVMModuleRef
|
||||
|
||||
fun embedLlvmLinkOptions(module: LLVMModuleRef, options: List<List<String>>) {
|
||||
fun embedLlvmLinkOptions(llvmContext: LLVMContextRef, module: LLVMModuleRef, options: List<List<String>>) {
|
||||
options.forEach {
|
||||
val node = node(*it.map { it.mdString() }.toTypedArray())
|
||||
val node = node(llvmContext, *it.map { it.mdString(llvmContext) }.toTypedArray())
|
||||
LLVMAddNamedMetadataOperand(module, "llvm.linker.options", node)
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -25,7 +25,7 @@ typealias LlvmRetType = LlvmParamType
|
||||
internal fun ContextUtils.getLlvmFunctionParameterTypes(function: IrFunction): List<LlvmParamType> {
|
||||
val returnType = getLlvmFunctionReturnType(function).llvmType
|
||||
val paramTypes = ArrayList(function.allParameters.map {
|
||||
LlvmParamType(getLLVMType(it.type), argumentAbiInfo.defaultParameterAttributesForIrType(it.type))
|
||||
LlvmParamType(it.type.toLLVMType(llvm), argumentAbiInfo.defaultParameterAttributesForIrType(it.type))
|
||||
})
|
||||
require(!function.isSuspend) { "Suspend functions should be lowered out at this point"}
|
||||
if (isObjectType(returnType))
|
||||
@@ -36,10 +36,10 @@ internal fun ContextUtils.getLlvmFunctionParameterTypes(function: IrFunction): L
|
||||
|
||||
internal fun ContextUtils.getLlvmFunctionReturnType(function: IrFunction): LlvmRetType {
|
||||
val returnType = when {
|
||||
function is IrConstructor -> LlvmParamType(voidType)
|
||||
function.isSuspend -> error("Suspend functions should be lowered out at this point, but ${function.render()} is still here")
|
||||
function is IrConstructor -> LlvmParamType(llvm.voidType)
|
||||
function.isSuspend -> error("Suspend functions should be lowered out at this point, but ${function.render()} is still here")
|
||||
else -> LlvmParamType(
|
||||
getLLVMReturnType(function.returnType),
|
||||
function.returnType.getLLVMReturnType(llvm),
|
||||
argumentAbiInfo.defaultParameterAttributesForIrType(function.returnType)
|
||||
)
|
||||
}
|
||||
|
||||
+15
-109
@@ -10,31 +10,6 @@ import llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.descriptors.konan.CompiledKlibModuleOrigin
|
||||
|
||||
private val llvmContextHolder = ThreadLocal<LLVMContextRef>()
|
||||
internal var llvmContext: LLVMContextRef
|
||||
get() = llvmContextHolder.get()
|
||||
set(value) { llvmContextHolder.set(value) }
|
||||
|
||||
internal fun tryDisposeLLVMContext() {
|
||||
val llvmContext = llvmContextHolder.get()
|
||||
if (llvmContext != null)
|
||||
LLVMContextDispose(llvmContext)
|
||||
llvmContextHolder.remove()
|
||||
}
|
||||
|
||||
internal val LLVMTypeRef.context: LLVMContextRef
|
||||
get() = LLVMGetTypeContext(this)!!
|
||||
|
||||
internal val List<LLVMTypeRef>.context: LLVMContextRef
|
||||
get() {
|
||||
val context = this[0].context
|
||||
for (i in 1 until this.size)
|
||||
assert(this[i].context == context) {
|
||||
"Expected the same context for all types in a list"
|
||||
}
|
||||
return context
|
||||
}
|
||||
|
||||
internal val LLVMValueRef.type: LLVMTypeRef
|
||||
get() = LLVMTypeOf(this)!!
|
||||
|
||||
@@ -49,7 +24,7 @@ internal val ConstValue.llvmType: LLVMTypeRef
|
||||
get() = this.llvm.type
|
||||
|
||||
internal interface ConstPointer : ConstValue {
|
||||
fun getElementPtr(index: Int): ConstPointer = ConstGetElementPtr(this, index)
|
||||
fun getElementPtr(llvm: Llvm, index: Int): ConstPointer = ConstGetElementPtr(llvm, this, index)
|
||||
}
|
||||
|
||||
internal fun constPointer(value: LLVMValueRef) = object : ConstPointer {
|
||||
@@ -60,8 +35,8 @@ internal fun constPointer(value: LLVMValueRef) = object : ConstPointer {
|
||||
override val llvm = value
|
||||
}
|
||||
|
||||
private class ConstGetElementPtr(val pointer: ConstPointer, val index: Int) : ConstPointer {
|
||||
override val llvm = LLVMConstInBoundsGEP(pointer.llvm, cValuesOf(Int32(0).llvm, Int32(index).llvm), 2)!!
|
||||
private class ConstGetElementPtr(llvm: Llvm, pointer: ConstPointer, index: Int) : ConstPointer {
|
||||
override val llvm = LLVMConstInBoundsGEP(pointer.llvm, cValuesOf(llvm.int32(0), llvm.int32(index)), 2)!!
|
||||
// TODO: squash multiple GEPs
|
||||
}
|
||||
|
||||
@@ -82,8 +57,6 @@ internal open class Struct(val type: LLVMTypeRef?, val elements: List<ConstValue
|
||||
|
||||
constructor(type: LLVMTypeRef?, vararg elements: ConstValue?) : this(type, elements.toList())
|
||||
|
||||
constructor(vararg elements: ConstValue) : this(structType(elements.map { it.llvmType }), *elements)
|
||||
|
||||
override val llvm = LLVMConstNamedStruct(type, elements.mapIndexed { index, element ->
|
||||
val expectedType = LLVMStructGetTypeAtIndex(type, index)
|
||||
if (element == null) {
|
||||
@@ -103,50 +76,6 @@ internal open class Struct(val type: LLVMTypeRef?, val elements: List<ConstValue
|
||||
}
|
||||
}
|
||||
|
||||
internal val int1Type get() = LLVMInt1TypeInContext(llvmContext)!!
|
||||
internal val int8Type get() = LLVMInt8TypeInContext(llvmContext)!!
|
||||
internal val int16Type get() = LLVMInt16TypeInContext(llvmContext)!!
|
||||
internal val int32Type get() = LLVMInt32TypeInContext(llvmContext)!!
|
||||
internal val int64Type get() = LLVMInt64TypeInContext(llvmContext)!!
|
||||
internal val int8TypePtr get() = pointerType(int8Type)
|
||||
internal val floatType get() = LLVMFloatTypeInContext(llvmContext)!!
|
||||
internal val doubleType get() = LLVMDoubleTypeInContext(llvmContext)!!
|
||||
internal val vector128Type get() = LLVMVectorType(floatType, 4)!!
|
||||
|
||||
internal val voidType get() = LLVMVoidTypeInContext(llvmContext)!!
|
||||
|
||||
internal class Int1(val value: Boolean) : ConstValue {
|
||||
override val llvm = LLVMConstInt(int1Type, if (value) 1 else 0, 1)!!
|
||||
}
|
||||
|
||||
internal class Int8(val value: Byte) : ConstValue {
|
||||
override val llvm = LLVMConstInt(int8Type, value.toLong(), 1)!!
|
||||
}
|
||||
|
||||
internal class Int16(val value: Short) : ConstValue {
|
||||
override val llvm = LLVMConstInt(int16Type, value.toLong(), 1)!!
|
||||
}
|
||||
|
||||
internal class Char16(val value: Char) : ConstValue {
|
||||
override val llvm = LLVMConstInt(int16Type, value.code.toLong(), 1)!!
|
||||
}
|
||||
|
||||
internal class Int32(val value: Int) : ConstValue {
|
||||
override val llvm = LLVMConstInt(int32Type, value.toLong(), 1)!!
|
||||
}
|
||||
|
||||
internal class Int64(val value: Long) : ConstValue {
|
||||
override val llvm = LLVMConstInt(int64Type, value, 1)!!
|
||||
}
|
||||
|
||||
internal class Float32(val value: Float) : ConstValue {
|
||||
override val llvm = LLVMConstReal(floatType, value.toDouble())!!
|
||||
}
|
||||
|
||||
internal class Float64(val value: Double) : ConstValue {
|
||||
override val llvm = LLVMConstReal(doubleType, value)!!
|
||||
}
|
||||
|
||||
internal class Zero(val type: LLVMTypeRef) : ConstValue {
|
||||
override val llvm = LLVMConstNull(type)!!
|
||||
}
|
||||
@@ -177,31 +106,17 @@ internal val RuntimeAware.kArrayHeaderPtr: LLVMTypeRef
|
||||
get() = pointerType(kArrayHeader)
|
||||
internal val RuntimeAware.kTypeInfoPtr: LLVMTypeRef
|
||||
get() = pointerType(kTypeInfo)
|
||||
internal val kInt1 get() = int1Type
|
||||
internal val kBoolean get() = kInt1
|
||||
internal val kInt8Ptr get() = pointerType(int8Type)
|
||||
internal val kInt8PtrPtr get() = pointerType(kInt8Ptr)
|
||||
internal val kNullInt8Ptr get() = LLVMConstNull(kInt8Ptr)!!
|
||||
internal val kInt32Ptr get() = pointerType(int32Type)
|
||||
internal val kNullInt32Ptr get() = LLVMConstNull(kInt32Ptr)!!
|
||||
internal val kImmInt32Zero get() = Int32(0).llvm
|
||||
internal val kImmInt32One get() = Int32(1).llvm
|
||||
internal val ContextUtils.kNullObjHeaderPtr: LLVMValueRef
|
||||
get() = LLVMConstNull(this.kObjHeaderPtr)!!
|
||||
internal val ContextUtils.kNullObjHeaderPtrPtr: LLVMValueRef
|
||||
get() = LLVMConstNull(this.kObjHeaderPtrPtr)!!
|
||||
internal val RuntimeAware.kNullObjHeaderPtr: LLVMValueRef
|
||||
get() = LLVMConstNull(kObjHeaderPtr)!!
|
||||
internal val RuntimeAware.kNullObjHeaderPtrPtr: LLVMValueRef
|
||||
get() = LLVMConstNull(kObjHeaderPtrPtr)!!
|
||||
|
||||
// Nothing type has no values, but we do generate unreachable code and thus need some fake value:
|
||||
internal val ContextUtils.kNothingFakeValue: LLVMValueRef
|
||||
internal val RuntimeAware.kNothingFakeValue: LLVMValueRef
|
||||
get() = LLVMGetUndef(kObjHeaderPtr)!!
|
||||
|
||||
internal fun pointerType(pointeeType: LLVMTypeRef) = LLVMPointerType(pointeeType, 0)!!
|
||||
|
||||
internal fun structType(vararg types: LLVMTypeRef): LLVMTypeRef = structType(types.toList())
|
||||
|
||||
internal fun structType(types: List<LLVMTypeRef>): LLVMTypeRef =
|
||||
LLVMStructTypeInContext(llvmContext, types.toCValues(), types.size, 0)!!
|
||||
|
||||
internal fun ContextUtils.numParameters(functionType: LLVMTypeRef) : Int {
|
||||
// Note that type is usually function pointer, so we have to dereference it.
|
||||
return LLVMCountParamTypes(LLVMGetElementType(functionType))
|
||||
@@ -277,19 +192,17 @@ internal class GlobalAddressAccess(private val address: LLVMValueRef): AddressAc
|
||||
override fun getAddress(generationContext: FunctionGenerationContext?): LLVMValueRef = address
|
||||
}
|
||||
|
||||
internal class TLSAddressAccess(
|
||||
private val context: Context, private val index: Int): AddressAccess() {
|
||||
|
||||
internal class TLSAddressAccess(private val index: Int) : AddressAccess() {
|
||||
override fun getAddress(generationContext: FunctionGenerationContext?): LLVMValueRef {
|
||||
return generationContext!!.call(context.generationState.llvm.lookupTLS,
|
||||
listOf(context.generationState.llvm.tlsKey, Int32(index).llvm))
|
||||
val llvm = generationContext!!.llvm
|
||||
return generationContext.call(llvm.lookupTLS, listOf(llvm.tlsKey, llvm.int32(index)))
|
||||
}
|
||||
}
|
||||
|
||||
internal fun ContextUtils.addKotlinThreadLocal(name: String, type: LLVMTypeRef): AddressAccess {
|
||||
return if (isObjectType(type)) {
|
||||
val index = llvm.tlsCount++
|
||||
TLSAddressAccess(context, index)
|
||||
TLSAddressAccess(index)
|
||||
} else {
|
||||
// TODO: This will break if Workers get decoupled from host threads.
|
||||
GlobalAddressAccess(LLVMAddGlobal(llvm.module, type, name)!!.also {
|
||||
@@ -334,7 +247,7 @@ fun getStructElements(type: LLVMTypeRef): List<LLVMTypeRef> {
|
||||
}
|
||||
}
|
||||
|
||||
fun parseBitcodeFile(path: String): LLVMModuleRef = memScoped {
|
||||
fun parseBitcodeFile(llvmContext: LLVMContextRef, path: String): LLVMModuleRef = memScoped {
|
||||
val bufRef = alloc<LLVMMemoryBufferRefVar>()
|
||||
val errorRef = allocPointerTo<ByteVar>()
|
||||
|
||||
@@ -400,15 +313,8 @@ internal fun addLlvmFunctionAttribute(function: LLVMValueRef, attribute: LLVMAtt
|
||||
LLVMAddAttributeAtIndex(function, LLVMAttributeFunctionIndex, attribute)
|
||||
}
|
||||
|
||||
fun addFunctionSignext(function: LLVMValueRef, index: Int, type: LLVMTypeRef?) {
|
||||
if (type == int1Type || type == int8Type || type == int16Type) {
|
||||
val attribute = createLlvmEnumAttribute(LLVMGetTypeContext(function.type)!!, LlvmParameterAttribute.SignExt.asAttributeKindId())
|
||||
LLVMAddAttributeAtIndex(function, index, attribute)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun String.mdString() = LLVMMDStringInContext(llvmContext, this, this.length)!!
|
||||
internal fun node(vararg it:LLVMValueRef) = LLVMMDNodeInContext(llvmContext, it.toList().toCValues(), it.size)
|
||||
internal fun String.mdString(llvmContext: LLVMContextRef) = LLVMMDStringInContext(llvmContext, this, this.length)!!
|
||||
internal fun node(llvmContext: LLVMContextRef, vararg it: LLVMValueRef) = LLVMMDNodeInContext(llvmContext, it.toList().toCValues(), it.size)
|
||||
|
||||
internal fun LLVMValueRef.setUnaligned() = apply { LLVMSetAlignment(this, 1) }
|
||||
|
||||
|
||||
+64
-64
@@ -79,7 +79,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
return result
|
||||
}
|
||||
|
||||
inner class InterfaceTableRecord(id: Int32, vtableSize: Int32, vtable: ConstPointer?) :
|
||||
inner class InterfaceTableRecord(id: ConstInt32, vtableSize: ConstInt32, vtable: ConstPointer?) :
|
||||
Struct(runtime.interfaceTableRecordType, id, vtableSize, vtable)
|
||||
|
||||
private inner class TypeInfo(
|
||||
@@ -111,27 +111,27 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
// TODO: it used to be a single int32 ABI version,
|
||||
// but klib abi version is not an int anymore.
|
||||
// So now this field is just reserved to preserve the layout.
|
||||
Int32(0),
|
||||
llvm.constInt32(0),
|
||||
|
||||
Int32(size),
|
||||
llvm.constInt32(size),
|
||||
|
||||
superType,
|
||||
|
||||
objOffsets,
|
||||
Int32(objOffsetsCount),
|
||||
llvm.constInt32(objOffsetsCount),
|
||||
|
||||
interfaces,
|
||||
Int32(interfacesCount),
|
||||
llvm.constInt32(interfacesCount),
|
||||
|
||||
Int32(interfaceTableSize),
|
||||
llvm.constInt32(interfaceTableSize),
|
||||
interfaceTable,
|
||||
|
||||
kotlinStringLiteral(packageName),
|
||||
kotlinStringLiteral(relativeName),
|
||||
|
||||
Int32(flags),
|
||||
llvm.constInt32(flags),
|
||||
|
||||
Int32(classId),
|
||||
llvm.constInt32(classId),
|
||||
|
||||
*listOfNotNull(writableTypeInfo).toTypedArray(),
|
||||
|
||||
@@ -159,32 +159,32 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
}
|
||||
|
||||
private val arrayClasses = mapOf(
|
||||
IdSignatureValues.array to kObjHeaderPtr,
|
||||
primitiveArrayTypesSignatures[PrimitiveType.BYTE] to int8Type,
|
||||
primitiveArrayTypesSignatures[PrimitiveType.CHAR] to int16Type,
|
||||
primitiveArrayTypesSignatures[PrimitiveType.SHORT] to int16Type,
|
||||
primitiveArrayTypesSignatures[PrimitiveType.INT] to int32Type,
|
||||
primitiveArrayTypesSignatures[PrimitiveType.LONG] to int64Type,
|
||||
primitiveArrayTypesSignatures[PrimitiveType.FLOAT] to floatType,
|
||||
primitiveArrayTypesSignatures[PrimitiveType.DOUBLE] to doubleType,
|
||||
primitiveArrayTypesSignatures[PrimitiveType.BOOLEAN] to int8Type,
|
||||
IdSignatureValues.string to int16Type,
|
||||
getPublicSignature(KonanFqNames.packageName, "ImmutableBlob") to int8Type,
|
||||
getPublicSignature(KonanFqNames.internalPackageName, "NativePtrArray") to kInt8Ptr
|
||||
IdSignatureValues.array to llvm.kObjHeaderPtr,
|
||||
primitiveArrayTypesSignatures[PrimitiveType.BYTE] to llvm.int8Type,
|
||||
primitiveArrayTypesSignatures[PrimitiveType.CHAR] to llvm.int16Type,
|
||||
primitiveArrayTypesSignatures[PrimitiveType.SHORT] to llvm.int16Type,
|
||||
primitiveArrayTypesSignatures[PrimitiveType.INT] to llvm.int32Type,
|
||||
primitiveArrayTypesSignatures[PrimitiveType.LONG] to llvm.int64Type,
|
||||
primitiveArrayTypesSignatures[PrimitiveType.FLOAT] to llvm.floatType,
|
||||
primitiveArrayTypesSignatures[PrimitiveType.DOUBLE] to llvm.doubleType,
|
||||
primitiveArrayTypesSignatures[PrimitiveType.BOOLEAN] to llvm.int8Type,
|
||||
IdSignatureValues.string to llvm.int16Type,
|
||||
getPublicSignature(KonanFqNames.packageName, "ImmutableBlob") to llvm.int8Type,
|
||||
getPublicSignature(KonanFqNames.internalPackageName, "NativePtrArray") to llvm.int8PtrType
|
||||
)
|
||||
|
||||
// Keep in sync with Konan_RuntimeType.
|
||||
private val runtimeTypeMap = mapOf(
|
||||
kObjHeaderPtr to 1,
|
||||
int8Type to 2,
|
||||
int16Type to 3,
|
||||
int32Type to 4,
|
||||
int64Type to 5,
|
||||
floatType to 6,
|
||||
doubleType to 7,
|
||||
kInt8Ptr to 8,
|
||||
int1Type to 9,
|
||||
vector128Type to 10
|
||||
llvm.kObjHeaderPtr to 1,
|
||||
llvm.int8Type to 2,
|
||||
llvm.int16Type to 3,
|
||||
llvm.int32Type to 4,
|
||||
llvm.int64Type to 5,
|
||||
llvm.floatType to 6,
|
||||
llvm.doubleType to 7,
|
||||
llvm.int8PtrType to 8,
|
||||
llvm.int1Type to 9,
|
||||
llvm.vector128Type to 10
|
||||
)
|
||||
|
||||
private fun getElementType(irClass: IrClass): LLVMTypeRef? {
|
||||
@@ -226,7 +226,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
|
||||
val objOffsets = getObjOffsets(bodyType)
|
||||
|
||||
val objOffsetsPtr = staticData.placeGlobalConstArray("krefs:$className", int32Type, objOffsets)
|
||||
val objOffsetsPtr = staticData.placeGlobalConstArray("krefs:$className", llvm.int32Type, objOffsets)
|
||||
|
||||
val objOffsetsCount = if (irClass.descriptor == context.builtIns.array) {
|
||||
1 // To mark it as non-leaf.
|
||||
@@ -269,7 +269,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
typeInfo
|
||||
} else {
|
||||
val vtable = vtable(irClass)
|
||||
Struct(typeInfo, vtable)
|
||||
llvm.struct(typeInfo, vtable)
|
||||
}
|
||||
|
||||
typeInfoGlobal.setInitializer(typeInfoGlobalValue)
|
||||
@@ -285,9 +285,9 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
}
|
||||
}
|
||||
|
||||
private fun getObjOffsets(bodyType: LLVMTypeRef): List<Int32> =
|
||||
private fun getObjOffsets(bodyType: LLVMTypeRef): List<ConstInt32> =
|
||||
getIndicesOfObjectFields(bodyType).map { index ->
|
||||
Int32(LLVMOffsetOfElement(llvmTargetData, bodyType, index).toInt())
|
||||
llvm.constInt32(LLVMOffsetOfElement(llvmTargetData, bodyType, index).toInt())
|
||||
}
|
||||
|
||||
fun vtable(irClass: IrClass): ConstArray {
|
||||
@@ -295,12 +295,12 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
val vtableEntries = context.getLayoutBuilder(irClass).vtableEntries.map {
|
||||
val implementation = it.implementation
|
||||
if (implementation == null || implementation.isExternalObjCClassMethod() || context.referencedFunctions?.contains(implementation) == false) {
|
||||
NullPointer(int8Type)
|
||||
NullPointer(llvm.int8Type)
|
||||
} else {
|
||||
implementation.entryPointAddress
|
||||
}
|
||||
}
|
||||
return ConstArray(int8TypePtr, vtableEntries)
|
||||
return ConstArray(llvm.int8PtrType, vtableEntries)
|
||||
}
|
||||
|
||||
fun interfaceTableRecords(irClass: IrClass): Pair<List<InterfaceTableRecord>, Int> {
|
||||
@@ -368,20 +368,20 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
return interfaceTableSkeleton.map { iface ->
|
||||
val interfaceId = iface?.classId ?: 0
|
||||
InterfaceTableRecord(
|
||||
Int32(interfaceId),
|
||||
Int32(iface?.interfaceVTableEntries?.size ?: 0),
|
||||
llvm.constInt32(interfaceId),
|
||||
llvm.constInt32(iface?.interfaceVTableEntries?.size ?: 0),
|
||||
if (iface == null)
|
||||
NullPointer(kInt8Ptr)
|
||||
NullPointer(llvm.int8PtrType)
|
||||
else {
|
||||
val vtableEntries = iface.interfaceVTableEntries.map { ifaceFunction ->
|
||||
val impl = layoutBuilder.overridingOf(ifaceFunction)
|
||||
if (impl == null || context.referencedFunctions?.contains(impl) == false)
|
||||
NullPointer(int8Type)
|
||||
NullPointer(llvm.int8Type)
|
||||
else impl.entryPointAddress
|
||||
}
|
||||
|
||||
staticData.placeGlobalConstArray("kifacevtable:${className}_$interfaceId",
|
||||
kInt8Ptr, vtableEntries
|
||||
llvm.int8PtrType, vtableEntries
|
||||
)
|
||||
}
|
||||
)
|
||||
@@ -393,7 +393,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
|
||||
private val debugRuntimeOrNull: LLVMModuleRef? by lazy {
|
||||
context.config.runtimeNativeLibraries.singleOrNull { it.endsWith("debug.bc")}?.let {
|
||||
parseBitcodeFile(it)
|
||||
parseBitcodeFile(llvm.llvmContext, it)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,18 +401,18 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
if (debugRuntimeOrNull != null) {
|
||||
val external = LLVMGetNamedGlobal(debugRuntimeOrNull, "Konan_debugOperationsList")!!
|
||||
val local = LLVMAddGlobal(llvm.module, LLVMGetElementType(LLVMTypeOf(external)),"Konan_debugOperationsList")!!
|
||||
constPointer(LLVMConstBitCast(local, kInt8PtrPtr)!!)
|
||||
constPointer(LLVMConstBitCast(local, llvm.int8PtrPtrType)!!)
|
||||
} else {
|
||||
Zero(kInt8PtrPtr)
|
||||
Zero(llvm.int8PtrPtrType)
|
||||
}
|
||||
}
|
||||
|
||||
val debugOperationsSize: ConstValue by lazy {
|
||||
if (debugRuntimeOrNull != null) {
|
||||
val external = LLVMGetNamedGlobal(debugRuntimeOrNull, "Konan_debugOperationsList")!!
|
||||
Int32(LLVMGetArrayLength(LLVMGetElementType(LLVMTypeOf(external))))
|
||||
llvm.constInt32(LLVMGetArrayLength(LLVMGetElementType(LLVMTypeOf(external))))
|
||||
} else
|
||||
Int32(0)
|
||||
llvm.constInt32(0)
|
||||
}
|
||||
|
||||
private fun makeExtendedInfo(irClass: IrClass): ConstPointer {
|
||||
@@ -429,8 +429,8 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
// An array type.
|
||||
val runtimeElementType = mapRuntimeType(elementType)
|
||||
Struct(runtime.extendedTypeInfoType,
|
||||
Int32(-runtimeElementType),
|
||||
NullPointer(int32Type), NullPointer(int8Type), NullPointer(kInt8Ptr),
|
||||
llvm.constInt32(-runtimeElementType),
|
||||
NullPointer(llvm.int32Type), NullPointer(llvm.int8Type), NullPointer(llvm.int8PtrType),
|
||||
debugOperationsSize, debugOperations)
|
||||
} else {
|
||||
class FieldRecord(val offset: Int, val type: Int, val name: String)
|
||||
@@ -440,14 +440,14 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
mapRuntimeType(LLVMStructGetTypeAtIndex(bodyType, it.index)!!),
|
||||
it.name)
|
||||
}
|
||||
val offsetsPtr = staticData.placeGlobalConstArray("kextoff:$className", int32Type,
|
||||
fields.map { Int32(it.offset) })
|
||||
val typesPtr = staticData.placeGlobalConstArray("kexttype:$className", int8Type,
|
||||
fields.map { Int8(it.type.toByte()) })
|
||||
val namesPtr = staticData.placeGlobalConstArray("kextname:$className", kInt8Ptr,
|
||||
val offsetsPtr = staticData.placeGlobalConstArray("kextoff:$className", llvm.int32Type,
|
||||
fields.map { llvm.constInt32(it.offset) })
|
||||
val typesPtr = staticData.placeGlobalConstArray("kexttype:$className", llvm.int8Type,
|
||||
fields.map { llvm.constInt8(it.type.toByte()) })
|
||||
val namesPtr = staticData.placeGlobalConstArray("kextname:$className", llvm.int8PtrType,
|
||||
fields.map { staticData.placeCStringLiteral(it.name) })
|
||||
|
||||
Struct(runtime.extendedTypeInfoType, Int32(fields.size), offsetsPtr, typesPtr, namesPtr,
|
||||
Struct(runtime.extendedTypeInfoType, llvm.constInt32(fields.size), offsetsPtr, typesPtr, namesPtr,
|
||||
debugOperationsSize, debugOperations)
|
||||
|
||||
}
|
||||
@@ -518,7 +518,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
assert(superClass.declarations.all { it !is IrProperty && it !is IrField })
|
||||
|
||||
val objOffsets = getObjOffsets(bodyType)
|
||||
val objOffsetsPtr = staticData.placeGlobalConstArray("", int32Type, objOffsets)
|
||||
val objOffsetsPtr = staticData.placeGlobalConstArray("", llvm.int32Type, objOffsets)
|
||||
val objOffsetsCount = objOffsets.size
|
||||
|
||||
val writableTypeInfoType = runtime.writableTypeInfoType
|
||||
@@ -530,9 +530,9 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
.pointer
|
||||
}
|
||||
val vtable = vtable(superClass)
|
||||
val typeInfoWithVtableType = structType(runtime.typeInfoType, vtable.llvmType)
|
||||
val typeInfoWithVtableType = llvm.structType(runtime.typeInfoType, vtable.llvmType)
|
||||
val typeInfoWithVtableGlobal = staticData.createGlobal(typeInfoWithVtableType, "", isExported = false)
|
||||
val result = typeInfoWithVtableGlobal.pointer.getElementPtr(0)
|
||||
val result = typeInfoWithVtableGlobal.pointer.getElementPtr(llvm, 0)
|
||||
val typeHierarchyInfo = if (!context.ghaEnabled())
|
||||
ClassGlobalHierarchyInfo.DUMMY
|
||||
else
|
||||
@@ -543,20 +543,20 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
|
||||
val interfaceTable = interfaceTableSkeleton.map { layoutBuilder ->
|
||||
if (layoutBuilder == null) {
|
||||
InterfaceTableRecord(Int32(0), Int32(0), null)
|
||||
InterfaceTableRecord(llvm.constInt32(0), llvm.constInt32(0), null)
|
||||
} else {
|
||||
val vtableEntries = layoutBuilder.interfaceVTableEntries.map { methodImpls[it]!!.bitcast(int8TypePtr) }
|
||||
val interfaceVTable = staticData.placeGlobalArray("", kInt8Ptr, vtableEntries)
|
||||
val vtableEntries = layoutBuilder.interfaceVTableEntries.map { methodImpls[it]!!.bitcast(llvm.int8PtrType) }
|
||||
val interfaceVTable = staticData.placeGlobalArray("", llvm.int8PtrType, vtableEntries)
|
||||
InterfaceTableRecord(
|
||||
Int32(layoutBuilder.classId),
|
||||
Int32(layoutBuilder.interfaceVTableEntries.size),
|
||||
interfaceVTable.pointer.getElementPtr(0)
|
||||
llvm.constInt32(layoutBuilder.classId),
|
||||
llvm.constInt32(layoutBuilder.interfaceVTableEntries.size),
|
||||
interfaceVTable.pointer.getElementPtr(llvm, 0)
|
||||
)
|
||||
}
|
||||
}
|
||||
val interfaceTablePtr = staticData.placeGlobalConstArray("", runtime.interfaceTableRecordType, interfaceTable)
|
||||
|
||||
val typeInfoWithVtable = Struct(TypeInfo(
|
||||
val typeInfoWithVtable = llvm.struct(TypeInfo(
|
||||
selfPtr = result,
|
||||
extendedInfo = NullPointer(runtime.extendedTypeInfoType),
|
||||
size = size,
|
||||
|
||||
+2
-2
@@ -14,8 +14,8 @@ interface RuntimeAware {
|
||||
val runtime: Runtime
|
||||
}
|
||||
|
||||
class Runtime(bitcodeFile: String) {
|
||||
val llvmModule: LLVMModuleRef = parseBitcodeFile(bitcodeFile)
|
||||
class Runtime(llvmContext: LLVMContextRef, bitcodeFile: String) {
|
||||
val llvmModule: LLVMModuleRef = parseBitcodeFile(llvmContext, bitcodeFile)
|
||||
val calculatedLLVMTypes: MutableMap<IrType, LLVMTypeRef> = HashMap()
|
||||
val addedLLVMExternalFunctions: MutableMap<IrFunction, LlvmCallable> = HashMap()
|
||||
|
||||
|
||||
+4
-5
@@ -6,12 +6,11 @@
|
||||
package org.jetbrains.kotlin.backend.konan.llvm
|
||||
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
|
||||
/**
|
||||
* Provides utilities to create static data.
|
||||
*/
|
||||
internal open class StaticData(val module: LLVMModuleRef) {
|
||||
internal open class StaticData(val module: LLVMModuleRef, private val llvm: Llvm) {
|
||||
|
||||
/**
|
||||
* Represents the LLVM global variable.
|
||||
@@ -138,16 +137,16 @@ internal open class StaticData(val module: LLVMModuleRef) {
|
||||
if (elements.isNotEmpty() || isExported) {
|
||||
val global = placeGlobalArray(name, elemType, elements, isExported)
|
||||
global.setConstant(true)
|
||||
return global.pointer.getElementPtr(0)
|
||||
return global.pointer.getElementPtr(llvm, 0)
|
||||
} else {
|
||||
return NullPointer(elemType)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun placeCStringLiteral(value: String) : ConstPointer {
|
||||
val chars = value.toByteArray(Charsets.UTF_8).map { Int8(it) } + Int8(0)
|
||||
val chars = value.toByteArray(Charsets.UTF_8).map { llvm.constInt8(it) } + llvm.constInt8(0)
|
||||
|
||||
return placeGlobalConstArray("", int8Type, chars)
|
||||
return placeGlobalConstArray("", llvm.int8Type, chars)
|
||||
}
|
||||
|
||||
internal fun cStringLiteral(value: String) = cStringLiterals.getOrPut(value) { placeCStringLiteral(value) }
|
||||
|
||||
+2
-2
@@ -75,7 +75,7 @@ internal class VariableManager(val functionGenerationContext: FunctionGeneration
|
||||
"Could not find ${valueDeclaration.render()} in contextVariablesToIndex"
|
||||
}
|
||||
val index = variables.size
|
||||
val type = functionGenerationContext.getLLVMType(valueDeclaration.type)
|
||||
val type = valueDeclaration.type.toLLVMType(functionGenerationContext.llvm)
|
||||
val slot = functionGenerationContext.alloca(type, valueDeclaration.name.asString(), variableLocation)
|
||||
if (value != null)
|
||||
functionGenerationContext.storeAny(value, slot, true)
|
||||
@@ -88,7 +88,7 @@ internal class VariableManager(val functionGenerationContext: FunctionGeneration
|
||||
internal fun createParameterOnStack(valueDeclaration: IrValueDeclaration, variableLocation: VariableDebugLocation?): Int {
|
||||
assert(!contextVariablesToIndex.contains(valueDeclaration))
|
||||
val index = variables.size
|
||||
val type = functionGenerationContext.getLLVMType(valueDeclaration.type)
|
||||
val type = valueDeclaration.type.toLLVMType(functionGenerationContext.llvm)
|
||||
val slot = functionGenerationContext.alloca(
|
||||
type, "p-${valueDeclaration.name.asString()}", variableLocation)
|
||||
val isObject = functionGenerationContext.isObjectType(type)
|
||||
|
||||
+5
-5
@@ -25,7 +25,7 @@ internal class LLVMCoverageInstrumentation(
|
||||
|
||||
private val functionNameGlobal = createFunctionNameGlobal(functionRegions.function)
|
||||
|
||||
private val functionHash = Int64(functionRegions.structuralHash).llvm
|
||||
private val functionHash = llvm.int64(functionRegions.structuralHash)
|
||||
|
||||
// TODO: It's a great place for some debug output.
|
||||
fun instrumentIrElement(element: IrElement) {
|
||||
@@ -38,16 +38,16 @@ internal class LLVMCoverageInstrumentation(
|
||||
* See https://llvm.org/docs/LangRef.html#llvm-instrprof-increment-intrinsic
|
||||
*/
|
||||
private fun placeRegionIncrement(region: Region) {
|
||||
val numberOfRegions = Int32(functionRegions.regions.size).llvm
|
||||
val regionNumber = Int32(functionRegions.regionEnumeration.getValue(region)).llvm
|
||||
val numberOfRegions = llvm.int32(functionRegions.regions.size)
|
||||
val regionNumber = llvm.int32(functionRegions.regionEnumeration.getValue(region))
|
||||
val args = listOf(functionNameGlobal, functionHash, numberOfRegions, regionNumber)
|
||||
callSitePlacer(LLVMInstrProfIncrement(context.generationState.llvm.module)!!, args)
|
||||
callSitePlacer(LLVMInstrProfIncrement(llvm.module)!!, args)
|
||||
}
|
||||
|
||||
// Each profiled function should have a global with its name in a specific format.
|
||||
private fun createFunctionNameGlobal(function: IrFunction): LLVMValueRef {
|
||||
val name = function.llvmFunction.llvmValue.name
|
||||
val pgoFunctionName = LLVMCreatePGOFunctionNameVar(function.llvmFunction.llvmValue, name)!!
|
||||
return LLVMConstBitCast(pgoFunctionName, int8TypePtr)!!
|
||||
return LLVMConstBitCast(pgoFunctionName, llvm.int8PtrType)!!
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -42,33 +42,33 @@ internal interface LlvmDiagnosticHandler {
|
||||
fun handle(diagnostics: List<LlvmDiagnostic>)
|
||||
}
|
||||
|
||||
internal inline fun <R> withLlvmDiagnosticHandler(handler: LlvmDiagnosticHandler, block: () -> R): R {
|
||||
internal inline fun <R> withLlvmDiagnosticHandler(llvmContext: LLVMContextRef, handler: LlvmDiagnosticHandler, block: () -> R): R {
|
||||
val collector = LlvmDiagnosticCollector()
|
||||
return try {
|
||||
withLlvmDiagnosticCollector(collector, block)
|
||||
withLlvmDiagnosticCollector(llvmContext, collector, block)
|
||||
} finally {
|
||||
collector.flush(handler)
|
||||
}
|
||||
}
|
||||
|
||||
internal inline fun <R> withLlvmDiagnosticCollector(collector: LlvmDiagnosticCollector, block: () -> R): R {
|
||||
internal inline fun <R> withLlvmDiagnosticCollector(llvmContext: LLVMContextRef, collector: LlvmDiagnosticCollector, block: () -> R): R {
|
||||
val handler: LLVMDiagnosticHandler = staticCFunction { diagnostic, context ->
|
||||
context!!.asStableRef<LlvmDiagnosticCollector>().get().add(createLlvmDiagnostic(diagnostic))
|
||||
}
|
||||
val context = StableRef.create(collector)
|
||||
return try {
|
||||
withLlvmDiagnosticHandler(handler, context.asCPointer(), block)
|
||||
withLlvmDiagnosticHandler(llvmContext, handler, context.asCPointer(), block)
|
||||
} finally {
|
||||
context.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
internal inline fun <R> withLlvmDiagnosticHandler(
|
||||
llvmContext: LLVMContextRef,
|
||||
handler: LLVMDiagnosticHandler,
|
||||
context: COpaquePointer,
|
||||
block: () -> R
|
||||
): R {
|
||||
val llvmContext = llvmContext
|
||||
val currentHandler = LLVMContextGetDiagnosticHandler(llvmContext)
|
||||
val currentContext = LLVMContextGetDiagnosticContext(llvmContext)
|
||||
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ internal fun llvmLinkModules2(context: Context, dest: LLVMModuleRef, src: LLVMMo
|
||||
}
|
||||
})
|
||||
|
||||
return withLlvmDiagnosticHandler(diagnosticHandler) {
|
||||
return withLlvmDiagnosticHandler(context.generationState.llvmContext, diagnosticHandler) {
|
||||
LLVMLinkModules2(dest, src)
|
||||
}
|
||||
}
|
||||
|
||||
+11
-11
@@ -29,8 +29,8 @@ internal open class ObjCCodeGenerator(val codegen: CodeGenerator) {
|
||||
private val objcMsgSend = constPointer(
|
||||
llvm.externalFunction(LlvmFunctionProto(
|
||||
"objc_msgSend",
|
||||
LlvmRetType(int8TypePtr),
|
||||
listOf(LlvmParamType(int8TypePtr), LlvmParamType(int8TypePtr)),
|
||||
LlvmRetType(llvm.int8PtrType),
|
||||
listOf(LlvmParamType(llvm.int8PtrType), LlvmParamType(llvm.int8PtrType)),
|
||||
isVararg = true,
|
||||
origin = context.stdlibModule.llvmSymbolOrigin
|
||||
)).llvmValue
|
||||
@@ -39,8 +39,8 @@ internal open class ObjCCodeGenerator(val codegen: CodeGenerator) {
|
||||
val objcRelease = run {
|
||||
val proto = LlvmFunctionProto(
|
||||
"llvm.objc.release",
|
||||
LlvmRetType(voidType),
|
||||
listOf(LlvmParamType(int8TypePtr)),
|
||||
LlvmRetType(llvm.voidType),
|
||||
listOf(LlvmParamType(llvm.int8PtrType)),
|
||||
listOf(LlvmFunctionAttribute.NoUnwind),
|
||||
origin = context.stdlibModule.llvmSymbolOrigin
|
||||
)
|
||||
@@ -49,23 +49,23 @@ internal open class ObjCCodeGenerator(val codegen: CodeGenerator) {
|
||||
|
||||
val objcAlloc = llvm.externalFunction(LlvmFunctionProto(
|
||||
"objc_alloc",
|
||||
LlvmRetType(int8TypePtr),
|
||||
listOf(LlvmParamType(int8TypePtr)),
|
||||
LlvmRetType(llvm.int8PtrType),
|
||||
listOf(LlvmParamType(llvm.int8PtrType)),
|
||||
origin = context.stdlibModule.llvmSymbolOrigin
|
||||
))
|
||||
|
||||
val objcAutoreleaseReturnValue = llvm.externalFunction(LlvmFunctionProto(
|
||||
"llvm.objc.autoreleaseReturnValue",
|
||||
LlvmRetType(int8TypePtr),
|
||||
listOf(LlvmParamType(int8TypePtr)),
|
||||
LlvmRetType(llvm.int8PtrType),
|
||||
listOf(LlvmParamType(llvm.int8PtrType)),
|
||||
listOf(LlvmFunctionAttribute.NoUnwind),
|
||||
origin = context.stdlibModule.llvmSymbolOrigin
|
||||
))
|
||||
|
||||
val objcRetainAutoreleasedReturnValue = llvm.externalFunction(LlvmFunctionProto(
|
||||
"llvm.objc.retainAutoreleasedReturnValue",
|
||||
LlvmRetType(int8TypePtr),
|
||||
listOf(LlvmParamType(int8TypePtr)),
|
||||
LlvmRetType(llvm.int8PtrType),
|
||||
listOf(LlvmParamType(llvm.int8PtrType)),
|
||||
listOf(LlvmFunctionAttribute.NoUnwind),
|
||||
origin = context.stdlibModule.llvmSymbolOrigin
|
||||
))
|
||||
@@ -75,7 +75,7 @@ internal open class ObjCCodeGenerator(val codegen: CodeGenerator) {
|
||||
val asmString = codegen.context.config.target.getARCRetainAutoreleasedReturnValueMarker() ?: return@lazy null
|
||||
val asmStringBytes = asmString.toByteArray()
|
||||
LLVMGetInlineAsm(
|
||||
Ty = functionType(voidType, false),
|
||||
Ty = functionType(llvm.voidType, false),
|
||||
AsmString = asmStringBytes.toCValues(),
|
||||
AsmStringSize = asmStringBytes.size.signExtend(),
|
||||
Constraints = null,
|
||||
|
||||
+18
-18
@@ -55,7 +55,7 @@ internal class ObjCDataGenerator(val codegen: CodeGenerator) {
|
||||
|
||||
llvm.compilerUsedGlobals += global.pointer.llvm
|
||||
|
||||
global.pointer.bitcast(pointerType(int8TypePtr))
|
||||
global.pointer.bitcast(pointerType(llvm.int8PtrType))
|
||||
}
|
||||
|
||||
private val classObjectType = codegen.runtime.objCClassObjectType
|
||||
@@ -111,12 +111,12 @@ internal class ObjCDataGenerator(val codegen: CodeGenerator) {
|
||||
if (instanceMethods.isEmpty()) return NullPointer(methodListType)
|
||||
|
||||
val methodStructs = instanceMethods.map {
|
||||
Struct(methodType, selectors.get(it.selector), encodings.get(it.encoding), it.imp.bitcast(int8TypePtr))
|
||||
Struct(methodType, selectors.get(it.selector), encodings.get(it.encoding), it.imp.bitcast(llvm.int8PtrType))
|
||||
}
|
||||
|
||||
val methodList = Struct(
|
||||
Int32(LLVMABISizeOfType(codegen.llvmTargetData, methodType).toInt()),
|
||||
Int32(instanceMethods.size),
|
||||
val methodList = llvm.struct(
|
||||
llvm.constInt32(LLVMABISizeOfType(codegen.llvmTargetData, methodType).toInt()),
|
||||
llvm.constInt32(instanceMethods.size),
|
||||
ConstArray(methodType, methodStructs)
|
||||
)
|
||||
|
||||
@@ -151,15 +151,15 @@ internal class ObjCDataGenerator(val codegen: CodeGenerator) {
|
||||
|
||||
val fields = mutableListOf<ConstValue>()
|
||||
|
||||
fields += Int32(flags)
|
||||
fields += Int32(start)
|
||||
fields += Int32(size)
|
||||
fields += NullPointer(int8Type) // ivar layout name
|
||||
fields += llvm.constInt32(flags)
|
||||
fields += llvm.constInt32(start)
|
||||
fields += llvm.constInt32(size)
|
||||
fields += NullPointer(llvm.int8Type) // ivar layout name
|
||||
fields += classNameLiteral
|
||||
fields += if (isMetaclass) NullPointer(methodListType) else emitInstanceMethodList()
|
||||
fields += NullPointer(protocolListType)
|
||||
fields += NullPointer(ivarListType)
|
||||
fields += NullPointer(int8Type) // ivar layout
|
||||
fields += NullPointer(llvm.int8Type) // ivar layout
|
||||
fields += NullPointer(propListType)
|
||||
|
||||
val roValue = Struct(classRoType, fields)
|
||||
@@ -190,7 +190,7 @@ internal class ObjCDataGenerator(val codegen: CodeGenerator) {
|
||||
fields += isa
|
||||
fields += superClass
|
||||
fields += emptyCache
|
||||
val vtableEntryType = pointerType(functionType(int8TypePtr, false, int8TypePtr, int8TypePtr))
|
||||
val vtableEntryType = pointerType(functionType(llvm.int8PtrType, false, llvm.int8PtrType, llvm.int8PtrType))
|
||||
fields += NullPointer(vtableEntryType) // empty vtable
|
||||
fields += classRo
|
||||
|
||||
@@ -230,8 +230,8 @@ internal class ObjCDataGenerator(val codegen: CodeGenerator) {
|
||||
|
||||
val global = llvm.staticData.placeGlobalArray(
|
||||
name,
|
||||
int8TypePtr,
|
||||
elements.map { it.bitcast(int8TypePtr) }
|
||||
llvm.int8PtrType,
|
||||
elements.map { it.bitcast(llvm.int8PtrType) }
|
||||
)
|
||||
|
||||
global.setAlignment(
|
||||
@@ -257,9 +257,9 @@ internal class ObjCDataGenerator(val codegen: CodeGenerator) {
|
||||
private val literals = mutableMapOf<String, ConstPointer>()
|
||||
|
||||
fun get(value: String) = literals.getOrPut(value) {
|
||||
val globalPointer = generator.generate(llvm.module, value)
|
||||
val globalPointer = generator.generate(llvm.module, llvm, value)
|
||||
llvm.compilerUsedGlobals += globalPointer.llvm
|
||||
globalPointer.getElementPtr(0)
|
||||
globalPointer.getElementPtr(llvm, 0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,9 +275,9 @@ internal class ObjCDataGenerator(val codegen: CodeGenerator) {
|
||||
}
|
||||
|
||||
class CStringLiteralsGenerator(val label: String, val section: String) {
|
||||
fun generate(module: LLVMModuleRef, value: String): ConstPointer {
|
||||
val bytes = value.toByteArray(Charsets.UTF_8).map { Int8(it) } + Int8(0)
|
||||
val initializer = ConstArray(int8Type, bytes)
|
||||
fun generate(module: LLVMModuleRef, llvm: Llvm, value: String): ConstPointer {
|
||||
val bytes = value.toByteArray(Charsets.UTF_8).map { llvm.constInt8(it) } + llvm.constInt8(0)
|
||||
val initializer = ConstArray(llvm.int8Type, bytes)
|
||||
val llvmGlobal = LLVMAddGlobal(module, initializer.llvmType, label)!!
|
||||
LLVMSetInitializer(llvmGlobal, initializer.llvm)
|
||||
|
||||
|
||||
+9
-8
@@ -21,9 +21,9 @@ internal fun patchObjCRuntimeModule(context: Context): LLVMModuleRef? {
|
||||
patchBuilder.addObjCPatches()
|
||||
|
||||
val bitcodeFile = config.objCNativeLibrary
|
||||
val parsedModule = parseBitcodeFile(bitcodeFile)
|
||||
val parsedModule = parseBitcodeFile(context.generationState.llvmContext, bitcodeFile)
|
||||
|
||||
patchBuilder.buildAndApply(parsedModule)
|
||||
patchBuilder.buildAndApply(parsedModule, context.generationState.llvm)
|
||||
return parsedModule
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ private fun PatchBuilder.addObjCPatches() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun PatchBuilder.buildAndApply(llvmModule: LLVMModuleRef) {
|
||||
private fun PatchBuilder.buildAndApply(llvmModule: LLVMModuleRef, llvm: Llvm) {
|
||||
val nameToGlobalPatch = globalPatches.associateNonRepeatingBy { it.globalName }
|
||||
|
||||
val sectionToValueToLiteralPatch = literalPatches.groupBy { it.generator.section }
|
||||
@@ -156,7 +156,7 @@ private fun PatchBuilder.buildAndApply(llvmModule: LLVMModuleRef) {
|
||||
val value = getStringValue(initializer)
|
||||
val patch = valueToLiteralPatch[value]
|
||||
if (patch != null) {
|
||||
if (patch.newValue != value) patchLiteral(global, patch.generator, patch.newValue)
|
||||
if (patch.newValue != value) patchLiteral(global, llvm, patch.generator, patch.newValue)
|
||||
unusedPatches -= patch
|
||||
} else if (section == ObjCDataGenerator.classNameGenerator.section) {
|
||||
error("Objective-C class name literal is not patched: $value")
|
||||
@@ -199,16 +199,17 @@ private fun <T, K> List<T>.associateNonRepeatingBy(keySelector: (T) -> K): Map<K
|
||||
|
||||
private fun patchLiteral(
|
||||
global: LLVMValueRef,
|
||||
llvm: Llvm,
|
||||
generator: ObjCDataGenerator.CStringLiteralsGenerator,
|
||||
newValue: String
|
||||
) {
|
||||
val module = LLVMGetGlobalParent(global)!!
|
||||
|
||||
val newFirstCharPtr = generator.generate(module, newValue).getElementPtr(0).llvm
|
||||
val newFirstCharPtr = generator.generate(module, llvm, newValue).getElementPtr(llvm, 0).llvm
|
||||
|
||||
generateSequence(LLVMGetFirstUse(global), { LLVMGetNextUse(it) }).forEach { use ->
|
||||
val firstCharPtr = LLVMGetUser(use)!!.also {
|
||||
require(it.isFirstCharPtr(global)) {
|
||||
require(it.isFirstCharPtr(llvm, global)) {
|
||||
"Unexpected literal usage: ${llvm2string(it)}"
|
||||
}
|
||||
}
|
||||
@@ -216,8 +217,8 @@ private fun patchLiteral(
|
||||
}
|
||||
}
|
||||
|
||||
private fun LLVMValueRef.isFirstCharPtr(global: LLVMValueRef): Boolean =
|
||||
this.type == int8TypePtr &&
|
||||
private fun LLVMValueRef.isFirstCharPtr(llvm: Llvm, global: LLVMValueRef): Boolean =
|
||||
this.type == llvm.int8PtrType &&
|
||||
LLVMIsConstant(this) != 0 && LLVMGetConstOpcode(this) == LLVMOpcode.LLVMGetElementPtr
|
||||
&& LLVMGetNumOperands(this) == 3
|
||||
&& LLVMGetOperand(this, 0) == global
|
||||
|
||||
+29
-28
@@ -25,9 +25,9 @@ internal fun ObjCExportCodeGeneratorBase.generateBlockToKotlinFunctionConverter(
|
||||
val useSeparateHolder = bridge.returnsVoid
|
||||
|
||||
val bodyType = if (useSeparateHolder) {
|
||||
structType(codegen.kObjHeader, codegen.kObjHeaderPtr)
|
||||
llvm.structType(codegen.kObjHeader, codegen.kObjHeaderPtr)
|
||||
} else {
|
||||
structType(codegen.kObjHeader)
|
||||
llvm.structType(codegen.kObjHeader)
|
||||
}
|
||||
|
||||
val invokeImpl = functionGenerator(
|
||||
@@ -57,7 +57,7 @@ internal fun ObjCExportCodeGeneratorBase.generateBlockToKotlinFunctionConverter(
|
||||
// and switching the thread state back to `Runnable` on exceptional path is not required.
|
||||
val result = callAndMaybeRetainAutoreleased(
|
||||
invoke,
|
||||
bridge.blockType.blockInvokeLlvmType,
|
||||
bridge.blockType.toBlockInvokeLlvmType(llvm),
|
||||
listOf(blockPtr) + args,
|
||||
exceptionHandler = terminatingExceptionHandler,
|
||||
doRetain = !bridge.returnsVoid
|
||||
@@ -89,11 +89,11 @@ internal fun ObjCExportCodeGeneratorBase.generateBlockToKotlinFunctionConverter(
|
||||
immutable = true
|
||||
)
|
||||
return functionGenerator(
|
||||
LlvmFunctionSignature(LlvmRetType(codegen.kObjHeaderPtr), listOf(LlvmParamType(int8TypePtr), LlvmParamType(codegen.kObjHeaderPtrPtr))),
|
||||
LlvmFunctionSignature(LlvmRetType(codegen.kObjHeaderPtr), listOf(LlvmParamType(llvm.int8PtrType), LlvmParamType(codegen.kObjHeaderPtrPtr))),
|
||||
"convertBlock${bridge.nameSuffix}"
|
||||
).generate {
|
||||
val blockPtr = param(0)
|
||||
ifThen(icmpEq(blockPtr, kNullInt8Ptr)) {
|
||||
ifThen(icmpEq(blockPtr, llvm.kNullInt8Ptr)) {
|
||||
ret(kNullObjHeaderPtr)
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ private fun FunctionGenerationContext.loadBlockInvoke(
|
||||
): LLVMValueRef {
|
||||
val invokePtr = structGep(bitcast(pointerType(codegen.runtime.blockLiteralType), blockPtr), 3)
|
||||
|
||||
return bitcast(pointerType(bridge.blockType.blockInvokeLlvmType.llvmFunctionType), load(invokePtr))
|
||||
return bitcast(pointerType(bridge.blockType.toBlockInvokeLlvmType(llvm).llvmFunctionType), load(invokePtr))
|
||||
}
|
||||
|
||||
private fun FunctionGenerationContext.allocInstanceWithAssociatedObject(
|
||||
@@ -146,25 +146,26 @@ private val BlockPointerBridge.blockType: BlockType
|
||||
*/
|
||||
internal data class BlockType(val numberOfParameters: Int, val returnsVoid: Boolean)
|
||||
|
||||
private val BlockType.blockInvokeLlvmType: LlvmFunctionSignature
|
||||
get() = LlvmFunctionSignature(
|
||||
LlvmRetType(if (returnsVoid) voidType else int8TypePtr),
|
||||
(0..numberOfParameters).map { LlvmParamType(int8TypePtr) }
|
||||
)
|
||||
private fun BlockType.toBlockInvokeLlvmType(llvm: Llvm): LlvmFunctionSignature =
|
||||
LlvmFunctionSignature(
|
||||
LlvmRetType(if (returnsVoid) llvm.voidType else llvm.int8PtrType),
|
||||
(0..numberOfParameters).map { LlvmParamType(llvm.int8PtrType) }
|
||||
)
|
||||
|
||||
private val BlockPointerBridge.nameSuffix: String
|
||||
get() = numberOfParameters.toString() + if (returnsVoid) "V" else ""
|
||||
|
||||
internal class BlockGenerator(private val codegen: CodeGenerator) {
|
||||
private val llvm = codegen.llvm
|
||||
|
||||
private val blockLiteralType = structType(
|
||||
private val blockLiteralType = llvm.structType(
|
||||
codegen.runtime.blockLiteralType,
|
||||
codegen.runtime.kRefSharedHolderType
|
||||
)
|
||||
|
||||
val disposeHelper = generateFunction(
|
||||
codegen,
|
||||
functionType(voidType, false, int8TypePtr),
|
||||
functionType(llvm.voidType, false, llvm.int8PtrType),
|
||||
"blockDisposeHelper",
|
||||
switchToRunnable = true
|
||||
) {
|
||||
@@ -179,7 +180,7 @@ internal class BlockGenerator(private val codegen: CodeGenerator) {
|
||||
|
||||
val copyHelper = generateFunction(
|
||||
codegen,
|
||||
functionType(voidType, false, int8TypePtr, int8TypePtr),
|
||||
functionType(llvm.voidType, false, llvm.int8PtrType, llvm.int8PtrType),
|
||||
"blockCopyHelper"
|
||||
) {
|
||||
val dstBlockPtr = bitcast(pointerType(blockLiteralType), param(0))
|
||||
@@ -207,8 +208,8 @@ internal class BlockGenerator(private val codegen: CodeGenerator) {
|
||||
|
||||
fun CodeGenerator.LongInt(value: Long) =
|
||||
when (val longWidth = llvm.longTypeWidth) {
|
||||
32L -> Int32(value.toInt())
|
||||
64L -> Int64(value)
|
||||
32L -> llvm.constInt32(value.toInt())
|
||||
64L -> llvm.constInt64(value)
|
||||
else -> error("Unexpected width of long type: $longWidth")
|
||||
}
|
||||
|
||||
@@ -236,7 +237,7 @@ internal class BlockGenerator(private val codegen: CodeGenerator) {
|
||||
constPointer(copyHelper),
|
||||
constPointer(disposeHelper),
|
||||
codegen.staticData.cStringLiteral(signature),
|
||||
NullPointer(int8Type)
|
||||
NullPointer(llvm.int8Type)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -246,7 +247,7 @@ internal class BlockGenerator(private val codegen: CodeGenerator) {
|
||||
invokeName: String,
|
||||
genBody: ObjCExportFunctionGenerationContext.(LLVMValueRef, List<LLVMValueRef>) -> Unit
|
||||
): ConstPointer {
|
||||
val result = functionGenerator(blockType.blockInvokeLlvmType, invokeName) {
|
||||
val result = functionGenerator(blockType.toBlockInvokeLlvmType(llvm), invokeName) {
|
||||
switchToRunnable = true
|
||||
}.generate {
|
||||
val blockPtr = bitcast(pointerType(blockLiteralType), param(0))
|
||||
@@ -303,24 +304,24 @@ internal class BlockGenerator(private val codegen: CodeGenerator) {
|
||||
)
|
||||
|
||||
return functionGenerator(
|
||||
LlvmFunctionSignature(LlvmRetType(int8TypePtr), listOf(LlvmParamType(codegen.kObjHeaderPtr))),
|
||||
LlvmFunctionSignature(LlvmRetType(llvm.int8PtrType), listOf(LlvmParamType(codegen.kObjHeaderPtr))),
|
||||
convertName
|
||||
).generate {
|
||||
val kotlinRef = param(0)
|
||||
ifThen(icmpEq(kotlinRef, kNullObjHeaderPtr)) {
|
||||
ret(kNullInt8Ptr)
|
||||
ret(llvm.kNullInt8Ptr)
|
||||
}
|
||||
|
||||
val isa = codegen.importGlobal(
|
||||
"_NSConcreteStackBlock",
|
||||
int8TypePtr,
|
||||
llvm.int8PtrType,
|
||||
CurrentKlibModuleOrigin
|
||||
)
|
||||
|
||||
val flags = Int32((1 shl 25) or (1 shl 30) or (1 shl 31)).llvm
|
||||
val reserved = Int32(0).llvm
|
||||
val flags = llvm.int32((1 shl 25) or (1 shl 30) or (1 shl 31))
|
||||
val reserved = llvm.int32(0)
|
||||
|
||||
val invokeType = pointerType(functionType(voidType, true, int8TypePtr))
|
||||
val invokeType = pointerType(functionType(llvm.voidType, true, llvm.int8PtrType))
|
||||
val invoke = generateInvoke(blockType, invokeName, genBlockBody).bitcast(invokeType).llvm
|
||||
val descriptor = blockDescriptor.llvmGlobal
|
||||
|
||||
@@ -328,7 +329,7 @@ internal class BlockGenerator(private val codegen: CodeGenerator) {
|
||||
val blockOnStackBase = structGep(blockOnStack, 0)
|
||||
val refHolder = structGep(blockOnStack, 1)
|
||||
|
||||
listOf(bitcast(int8TypePtr, isa), flags, reserved, invoke, descriptor).forEachIndexed { index, value ->
|
||||
listOf(bitcast(llvm.int8PtrType, isa), flags, reserved, invoke, descriptor).forEachIndexed { index, value ->
|
||||
// Although value is actually on the stack, it's not in normal slot area, so we cannot handle it
|
||||
// as if it was on the stack.
|
||||
store(value, structGep(blockOnStackBase, index))
|
||||
@@ -336,7 +337,7 @@ internal class BlockGenerator(private val codegen: CodeGenerator) {
|
||||
|
||||
call(llvm.kRefSharedHolderInitLocal, listOf(refHolder, kotlinRef))
|
||||
|
||||
val copiedBlock = callFromBridge(retainBlock, listOf(bitcast(int8TypePtr, blockOnStack)))
|
||||
val copiedBlock = callFromBridge(retainBlock, listOf(bitcast(llvm.int8PtrType, blockOnStack)))
|
||||
|
||||
ret(copiedBlock)
|
||||
}.also {
|
||||
@@ -349,8 +350,8 @@ private val ObjCExportCodeGeneratorBase.retainBlock: LlvmCallable
|
||||
get() {
|
||||
val functionProto = LlvmFunctionProto(
|
||||
"objc_retainBlock",
|
||||
LlvmRetType(int8TypePtr),
|
||||
listOf(LlvmParamType(int8TypePtr)),
|
||||
LlvmRetType(llvm.int8PtrType),
|
||||
listOf(LlvmParamType(llvm.int8PtrType)),
|
||||
origin = CurrentKlibModuleOrigin
|
||||
)
|
||||
return llvm.externalFunction(functionProto)
|
||||
|
||||
+89
-84
@@ -39,9 +39,9 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi2ir.descriptors.IrBuiltInsOverDescriptors
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
|
||||
internal fun TypeBridge.makeNothing() = when (this) {
|
||||
is ReferenceBridge, is BlockPointerBridge -> kNullInt8Ptr
|
||||
is ValueTypeBridge -> LLVMConstNull(this.objCValueType.llvmType)!!
|
||||
internal fun TypeBridge.makeNothing(llvm: Llvm) = when (this) {
|
||||
is ReferenceBridge, is BlockPointerBridge -> llvm.kNullInt8Ptr
|
||||
is ValueTypeBridge -> LLVMConstNull(this.objCValueType.toLlvmType(llvm))!!
|
||||
}
|
||||
|
||||
internal class ObjCExportFunctionGenerationContext(
|
||||
@@ -219,7 +219,7 @@ internal open class ObjCExportCodeGeneratorBase(codegen: CodeGenerator) : ObjCCo
|
||||
private val objcTerminate: LlvmCallable by lazy {
|
||||
llvm.externalFunction(LlvmFunctionProto(
|
||||
"objc_terminate",
|
||||
LlvmRetType(voidType),
|
||||
LlvmRetType(llvm.voidType),
|
||||
functionAttributes = listOf(LlvmFunctionAttribute.NoUnwind),
|
||||
origin = CurrentKlibModuleOrigin
|
||||
))
|
||||
@@ -337,7 +337,7 @@ internal class ObjCExportCodeGenerator(
|
||||
|
||||
val objcMsgSendType = LlvmFunctionSignature(
|
||||
returnType,
|
||||
listOf(LlvmParamType(int8TypePtr), LlvmParamType(int8TypePtr)) + parameterTypes
|
||||
listOf(LlvmParamType(llvm.int8PtrType), LlvmParamType(llvm.int8PtrType)) + parameterTypes
|
||||
)
|
||||
return callFromBridge(msgSender(objcMsgSendType), listOf(receiver, genSelector(selector)) + args)
|
||||
}
|
||||
@@ -346,7 +346,7 @@ internal class ObjCExportCodeGenerator(
|
||||
value: LLVMValueRef,
|
||||
valueType: ObjCValueType
|
||||
): LLVMValueRef = when (valueType) {
|
||||
ObjCValueType.BOOL -> zext(value, int8Type) // TODO: zext behaviour may be strange on bit types.
|
||||
ObjCValueType.BOOL -> zext(value, llvm.int8Type) // TODO: zext behaviour may be strange on bit types.
|
||||
|
||||
ObjCValueType.UNICHAR,
|
||||
ObjCValueType.CHAR, ObjCValueType.SHORT, ObjCValueType.INT, ObjCValueType.LONG_LONG,
|
||||
@@ -359,7 +359,7 @@ internal class ObjCExportCodeGenerator(
|
||||
value: LLVMValueRef,
|
||||
valueType: ObjCValueType
|
||||
): LLVMValueRef = when (valueType) {
|
||||
ObjCValueType.BOOL -> icmpNe(value, Int8(0).llvm)
|
||||
ObjCValueType.BOOL -> icmpNe(value, llvm.int8(0))
|
||||
|
||||
ObjCValueType.UNICHAR,
|
||||
ObjCValueType.CHAR, ObjCValueType.SHORT, ObjCValueType.INT, ObjCValueType.LONG_LONG,
|
||||
@@ -519,7 +519,7 @@ internal class ObjCExportCodeGenerator(
|
||||
// Note: this globals replace runtime globals with weak linkage:
|
||||
val origin = context.standardLlvmSymbolsOrigin
|
||||
replaceExternalWeakOrCommonGlobal(prefix, sortedAdaptersPointer, origin)
|
||||
replaceExternalWeakOrCommonGlobal("${prefix}Num", Int32(sortedAdapters.size), origin)
|
||||
replaceExternalWeakOrCommonGlobal("${prefix}Num", llvm.constInt32(sortedAdapters.size), origin)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -528,9 +528,9 @@ internal class ObjCExportCodeGenerator(
|
||||
|
||||
if (context.llvmModuleSpecification.importsKotlinDeclarationsFromOtherSharedLibraries()) {
|
||||
replaceExternalWeakOrCommonGlobal(
|
||||
"Kotlin_ObjCExport_initTypeAdapters",
|
||||
Int1(true),
|
||||
context.standardLlvmSymbolsOrigin
|
||||
"Kotlin_ObjCExport_initTypeAdapters",
|
||||
llvm.constInt1(true),
|
||||
context.standardLlvmSymbolsOrigin
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -538,7 +538,7 @@ internal class ObjCExportCodeGenerator(
|
||||
private fun emitStaticInitializers() {
|
||||
if (externalGlobalInitializers.isEmpty()) return
|
||||
|
||||
val initializer = generateFunctionNoRuntime(codegen, functionType(voidType, false), "initObjCExportGlobals") {
|
||||
val initializer = generateFunctionNoRuntime(codegen, functionType(llvm.voidType, false), "initObjCExportGlobals") {
|
||||
externalGlobalInitializers.forEach { (global, value) ->
|
||||
store(value.llvm, global)
|
||||
}
|
||||
@@ -560,7 +560,7 @@ internal class ObjCExportCodeGenerator(
|
||||
// Adding a similar symbol that would explicitly hint to take a look at the YouTrack issue if reported.
|
||||
// Note: for some reason this symbol is reported as the last one, which is good for its purpose.
|
||||
val name = "See https://youtrack.jetbrains.com/issue/KT-42254"
|
||||
val global = staticData.placeGlobal(name, Int8(0), isExported = true)
|
||||
val global = staticData.placeGlobal(name, llvm.constInt8(0), isExported = true)
|
||||
|
||||
llvm.usedGlobals += global.llvmGlobal
|
||||
LLVMSetVisibility(global.llvmGlobal, LLVMVisibility.LLVMHiddenVisibility)
|
||||
@@ -588,7 +588,7 @@ internal class ObjCExportCodeGenerator(
|
||||
)
|
||||
|
||||
private fun emitSelectorsHolder() {
|
||||
val impType = functionType(voidType, false, int8TypePtr, int8TypePtr)
|
||||
val impType = functionType(llvm.voidType, false, llvm.int8PtrType, llvm.int8PtrType)
|
||||
val imp = generateFunctionNoRuntime(codegen, impType, "") {
|
||||
unreachable()
|
||||
}
|
||||
@@ -606,7 +606,7 @@ internal class ObjCExportCodeGenerator(
|
||||
)
|
||||
}
|
||||
|
||||
private val impType = pointerType(functionType(voidType, false))
|
||||
private val impType = pointerType(functionType(llvm.voidType, false))
|
||||
|
||||
internal val directMethodAdapters = mutableMapOf<DirectAdapterRequest, ObjCToKotlinMethodAdapter>()
|
||||
|
||||
@@ -632,10 +632,10 @@ internal class ObjCExportCodeGenerator(
|
||||
) : Struct(
|
||||
runtime.kotlinToObjCMethodAdapter,
|
||||
staticData.cStringLiteral(selector),
|
||||
Int32(itablePlace.interfaceId),
|
||||
Int32(itablePlace.itableSize),
|
||||
Int32(itablePlace.methodIndex),
|
||||
Int32(vtableIndex),
|
||||
llvm.constInt32(itablePlace.interfaceId),
|
||||
llvm.constInt32(itablePlace.itableSize),
|
||||
llvm.constInt32(itablePlace.methodIndex),
|
||||
llvm.constInt32(vtableIndex),
|
||||
kotlinImpl
|
||||
)
|
||||
|
||||
@@ -656,10 +656,10 @@ internal class ObjCExportCodeGenerator(
|
||||
typeInfo,
|
||||
|
||||
vtable,
|
||||
Int32(vtableSize),
|
||||
llvm.constInt32(vtableSize),
|
||||
|
||||
staticData.placeGlobalConstArray("", runtime.interfaceTableRecordType, itable),
|
||||
Int32(itableSize),
|
||||
llvm.constInt32(itableSize),
|
||||
|
||||
staticData.cStringLiteral(objCName),
|
||||
|
||||
@@ -668,28 +668,28 @@ internal class ObjCExportCodeGenerator(
|
||||
runtime.objCToKotlinMethodAdapter,
|
||||
directAdapters
|
||||
),
|
||||
Int32(directAdapters.size),
|
||||
llvm.constInt32(directAdapters.size),
|
||||
|
||||
staticData.placeGlobalConstArray(
|
||||
"",
|
||||
runtime.objCToKotlinMethodAdapter,
|
||||
classAdapters
|
||||
),
|
||||
Int32(classAdapters.size),
|
||||
llvm.constInt32(classAdapters.size),
|
||||
|
||||
staticData.placeGlobalConstArray(
|
||||
"",
|
||||
runtime.objCToKotlinMethodAdapter,
|
||||
virtualAdapters
|
||||
),
|
||||
Int32(virtualAdapters.size),
|
||||
llvm.constInt32(virtualAdapters.size),
|
||||
|
||||
staticData.placeGlobalConstArray(
|
||||
"",
|
||||
runtime.kotlinToObjCMethodAdapter,
|
||||
reverseAdapters
|
||||
),
|
||||
Int32(reverseAdapters.size)
|
||||
llvm.constInt32(reverseAdapters.size)
|
||||
)
|
||||
|
||||
}
|
||||
@@ -755,7 +755,7 @@ private fun ObjCExportCodeGeneratorBase.buildWritableTypeInfoValue(
|
||||
typeAdapter: ConstPointer? = null
|
||||
): Struct {
|
||||
if (convertToRetained != null) {
|
||||
val expectedType = pointerType(functionType(int8TypePtr, false, codegen.kObjHeaderPtr))
|
||||
val expectedType = pointerType(functionType(llvm.int8PtrType, false, codegen.kObjHeaderPtr))
|
||||
assert(convertToRetained.llvmType == expectedType) {
|
||||
"Expected: ${LLVMPrintTypeToString(expectedType)!!.toKString()} " +
|
||||
"found: ${LLVMPrintTypeToString(convertToRetained.llvmType)!!.toKString()}"
|
||||
@@ -763,7 +763,7 @@ private fun ObjCExportCodeGeneratorBase.buildWritableTypeInfoValue(
|
||||
}
|
||||
|
||||
val objCExportAddition = Struct(runtime.typeInfoObjCExportAddition,
|
||||
convertToRetained?.bitcast(int8TypePtr),
|
||||
convertToRetained?.bitcast(llvm.int8PtrType),
|
||||
objCClass,
|
||||
typeAdapter
|
||||
)
|
||||
@@ -773,10 +773,10 @@ private fun ObjCExportCodeGeneratorBase.buildWritableTypeInfoValue(
|
||||
}
|
||||
|
||||
private val ObjCExportCodeGenerator.kotlinToObjCFunctionType: LlvmFunctionSignature
|
||||
get() = LlvmFunctionSignature(LlvmRetType(int8TypePtr), listOf(LlvmParamType(codegen.kObjHeaderPtr)), isVararg = false)
|
||||
get() = LlvmFunctionSignature(LlvmRetType(llvm.int8PtrType), listOf(LlvmParamType(codegen.kObjHeaderPtr)), isVararg = false)
|
||||
|
||||
private val ObjCExportCodeGeneratorBase.objCToKotlinFunctionType: LLVMTypeRef
|
||||
get() = functionType(codegen.kObjHeaderPtr, false, int8TypePtr, codegen.kObjHeaderPtrPtr)
|
||||
get() = functionType(codegen.kObjHeaderPtr, false, llvm.int8PtrType, codegen.kObjHeaderPtrPtr)
|
||||
|
||||
private fun ObjCExportCodeGenerator.emitBoxConverters() {
|
||||
val irBuiltIns = context.irBuiltIns
|
||||
@@ -817,7 +817,7 @@ private fun ObjCExportCodeGenerator.emitBoxConverter(
|
||||
val nsNumberSubclass = genGetLinkedClass(namer.numberBoxName(boxClass.classId!!).binaryName)
|
||||
// We consider this function fast enough, so don't switch thread state to Native.
|
||||
val instance = callFromBridge(objcAlloc, listOf(nsNumberSubclass))
|
||||
val returnType = LlvmRetType(int8TypePtr)
|
||||
val returnType = LlvmRetType(llvm.int8PtrType)
|
||||
// We consider these methods fast enough, so don't switch thread state to Native.
|
||||
ret(genSendMessage(returnType, valueParameterTypes, instance, nsNumberInitSelector, value))
|
||||
}
|
||||
@@ -855,7 +855,7 @@ private fun ObjCExportCodeGenerator.generateUnitContinuationToRetainedCompletion
|
||||
check(arguments.size == 1)
|
||||
|
||||
val errorArgument = arguments[0]
|
||||
val resultArgument = ifThenElse(icmpNe(errorArgument, kNullInt8Ptr), kNullObjHeaderPtr) {
|
||||
val resultArgument = ifThenElse(icmpNe(errorArgument, llvm.kNullInt8Ptr), kNullObjHeaderPtr) {
|
||||
codegen.theUnitInstanceRef.llvm
|
||||
}
|
||||
|
||||
@@ -897,11 +897,11 @@ private fun ObjCExportBlockCodeGenerator.emitBlockToKotlinFunctionConverters() {
|
||||
"",
|
||||
pointerType(objCToKotlinFunctionType),
|
||||
converters
|
||||
).pointer.getElementPtr(0)
|
||||
).pointer.getElementPtr(llvm, 0)
|
||||
|
||||
// Note: defining globals declared in runtime.
|
||||
staticData.placeGlobal("Kotlin_ObjCExport_blockToFunctionConverters", ptr, isExported = true)
|
||||
staticData.placeGlobal("Kotlin_ObjCExport_blockToFunctionConverters_size", Int32(arityLimit), isExported = true)
|
||||
staticData.placeGlobal("Kotlin_ObjCExport_blockToFunctionConverters_size", llvm.constInt32(arityLimit), isExported = true)
|
||||
}
|
||||
|
||||
private fun ObjCExportCodeGenerator.emitSpecialClassesConvertions() {
|
||||
@@ -1098,7 +1098,7 @@ private fun ObjCExportCodeGenerator.generateObjCImp(
|
||||
!is MethodBridge.ReturnValue.WithError ->
|
||||
error("bridge with error parameter has unexpected return type: $returnType")
|
||||
|
||||
MethodBridge.ReturnValue.WithError.Success -> Int8(0).llvm // false
|
||||
MethodBridge.ReturnValue.WithError.Success -> llvm.int8(0) // false
|
||||
|
||||
is MethodBridge.ReturnValue.WithError.ZeroForError -> {
|
||||
if (returnType.successBridge == MethodBridge.ReturnValue.Instance.InitResult) {
|
||||
@@ -1136,10 +1136,10 @@ private fun ObjCExportCodeGenerator.generateObjCImp(
|
||||
MethodBridge.ReturnValue.Void -> null
|
||||
MethodBridge.ReturnValue.HashCode -> {
|
||||
val kotlinHashCode = targetResult!!
|
||||
if (codegen.context.is64BitNSInteger()) zext(kotlinHashCode, int64Type) else kotlinHashCode
|
||||
if (codegen.context.is64BitNSInteger()) zext(kotlinHashCode, llvm.int64Type) else kotlinHashCode
|
||||
}
|
||||
is MethodBridge.ReturnValue.Mapped -> if (LLVMTypeOf(targetResult!!) == voidType) {
|
||||
returnBridge.bridge.makeNothing()
|
||||
is MethodBridge.ReturnValue.Mapped -> if (LLVMTypeOf(targetResult!!) == llvm.voidType) {
|
||||
returnBridge.bridge.makeNothing(llvm)
|
||||
} else {
|
||||
when (returnBridge.bridge) {
|
||||
is ReferenceBridge -> return autoreleaseAndRet(kotlinReferenceToRetainedObjC(targetResult))
|
||||
@@ -1147,7 +1147,7 @@ private fun ObjCExportCodeGenerator.generateObjCImp(
|
||||
is ValueTypeBridge -> kotlinToObjC(targetResult, returnBridge.bridge.objCValueType)
|
||||
}
|
||||
}
|
||||
MethodBridge.ReturnValue.WithError.Success -> Int8(1).llvm // true
|
||||
MethodBridge.ReturnValue.WithError.Success -> llvm.int8(1) // true
|
||||
is MethodBridge.ReturnValue.WithError.ZeroForError -> return genReturnOnSuccess(returnBridge.successBridge)
|
||||
MethodBridge.ReturnValue.Instance.InitResult -> param(0)
|
||||
MethodBridge.ReturnValue.Instance.FactoryResult -> return autoreleaseAndRet(kotlinReferenceToRetainedObjC(targetResult!!)) // provided by [callKotlin]
|
||||
@@ -1261,8 +1261,8 @@ private fun ObjCExportCodeGenerator.generateKotlinToObjCBridge(
|
||||
expectedType = parameterToBase[parameter]!!.type,
|
||||
resultLifetime = Lifetime.ARGUMENT
|
||||
)
|
||||
if (LLVMTypeOf(kotlinValue) == voidType) {
|
||||
bridge.bridge.makeNothing()
|
||||
if (LLVMTypeOf(kotlinValue) == llvm.voidType) {
|
||||
bridge.bridge.makeNothing(llvm)
|
||||
} else {
|
||||
when (bridge.bridge) {
|
||||
is ReferenceBridge -> kotlinReferenceToRetainedObjC(kotlinValue).also { objCReferenceArgsToRelease += it }
|
||||
@@ -1293,8 +1293,8 @@ private fun ObjCExportCodeGenerator.generateKotlinToObjCBridge(
|
||||
error("Method is not instance and thus can't have bridge for overriding: $baseMethod")
|
||||
|
||||
MethodBridgeValueParameter.ErrorOutParameter ->
|
||||
alloca(int8TypePtr).also {
|
||||
store(kNullInt8Ptr, it)
|
||||
alloca(llvm.int8PtrType).also {
|
||||
store(llvm.kNullInt8Ptr, it)
|
||||
errorOutPtr = it
|
||||
}
|
||||
|
||||
@@ -1369,8 +1369,8 @@ private fun ObjCExportCodeGenerator.generateKotlinToObjCBridge(
|
||||
|
||||
MethodBridge.ReturnValue.HashCode -> {
|
||||
if (codegen.context.is64BitNSInteger()) {
|
||||
val low = trunc(targetResult, int32Type)
|
||||
val high = trunc(shr(targetResult, 32, signed = false), int32Type)
|
||||
val low = trunc(targetResult, llvm.int32Type)
|
||||
val high = trunc(shr(targetResult, 32, signed = false), llvm.int32Type)
|
||||
xor(low, high)
|
||||
} else {
|
||||
targetResult
|
||||
@@ -1382,7 +1382,7 @@ private fun ObjCExportCodeGenerator.generateKotlinToObjCBridge(
|
||||
}
|
||||
|
||||
MethodBridge.ReturnValue.WithError.Success -> {
|
||||
ifThen(icmpEq(targetResult, Int8(0).llvm)) {
|
||||
ifThen(icmpEq(targetResult, llvm.int8(0))) {
|
||||
check(!retainAutoreleasedTargetResult)
|
||||
rethrow()
|
||||
}
|
||||
@@ -1392,12 +1392,12 @@ private fun ObjCExportCodeGenerator.generateKotlinToObjCBridge(
|
||||
is MethodBridge.ReturnValue.WithError.ZeroForError -> {
|
||||
if (returnBridge.successMayBeZero) {
|
||||
val error = load(errorOutPtr!!)
|
||||
ifThen(icmpNe(error, kNullInt8Ptr)) {
|
||||
ifThen(icmpNe(error, llvm.kNullInt8Ptr)) {
|
||||
// error is not null, so targetResult should be null => no need for objc_release on it.
|
||||
rethrow()
|
||||
}
|
||||
} else {
|
||||
ifThen(icmpEq(targetResult, kNullInt8Ptr)) {
|
||||
ifThen(icmpEq(targetResult, llvm.kNullInt8Ptr)) {
|
||||
// targetResult is null => no need for objc_release on it.
|
||||
rethrow()
|
||||
}
|
||||
@@ -1506,7 +1506,7 @@ private fun ObjCExportCodeGenerator.createReverseAdapter(
|
||||
val kotlinToObjC = generateKotlinToObjCBridge(
|
||||
irFunction,
|
||||
baseMethod
|
||||
).bitcast(int8TypePtr)
|
||||
).bitcast(llvm.int8PtrType)
|
||||
|
||||
return KotlinToObjCMethodAdapter(selector,
|
||||
itablePlace ?: ClassLayoutBuilder.InterfaceTablePlace.INVALID,
|
||||
@@ -1698,7 +1698,7 @@ private fun ObjCExportCodeGenerator.createTypeAdapter(
|
||||
val vtable = if (!irClass.isInterface && !irClass.typeInfoHasVtableAttached) {
|
||||
staticData.placeGlobal("", rttiGenerator.vtable(irClass)).also {
|
||||
it.setConstant(true)
|
||||
}.pointer.getElementPtr(0)
|
||||
}.pointer.getElementPtr(llvm, 0)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
@@ -1830,7 +1830,7 @@ private fun ObjCExportCodeGenerator.nonOverridableAdapter(
|
||||
): ObjCExportCodeGenerator.KotlinToObjCMethodAdapter = KotlinToObjCMethodAdapter(
|
||||
selector,
|
||||
vtableIndex = if (hasSelectorAmbiguity) -2 else -1, // Describes the reason.
|
||||
kotlinImpl = NullPointer(int8Type),
|
||||
kotlinImpl = NullPointer(llvm.int8Type),
|
||||
itablePlace = ClassLayoutBuilder.InterfaceTablePlace.INVALID
|
||||
)
|
||||
|
||||
@@ -1966,52 +1966,57 @@ private fun ObjCExportCodeGenerator.createThrowableAsErrorAdapter(): ObjCExportC
|
||||
}
|
||||
|
||||
private fun objCFunctionType(context: Context, methodBridge: MethodBridge): LlvmFunctionSignature {
|
||||
val paramTypes = methodBridge.paramBridges.map { it.toLlvmParamType() }
|
||||
val paramTypes = methodBridge.paramBridges.map { it.toLlvmParamType(context.generationState.llvm) }
|
||||
val returnType = methodBridge.returnBridge.toLlvmRetType(context)
|
||||
return LlvmFunctionSignature(returnType, paramTypes, isVararg = false)
|
||||
}
|
||||
|
||||
private val ObjCValueType.llvmType: LLVMTypeRef get() = when (this) {
|
||||
ObjCValueType.BOOL -> int8Type
|
||||
ObjCValueType.UNICHAR -> int16Type
|
||||
ObjCValueType.CHAR -> int8Type
|
||||
ObjCValueType.SHORT -> int16Type
|
||||
ObjCValueType.INT -> int32Type
|
||||
ObjCValueType.LONG_LONG -> int64Type
|
||||
ObjCValueType.UNSIGNED_CHAR -> int8Type
|
||||
ObjCValueType.UNSIGNED_SHORT -> int16Type
|
||||
ObjCValueType.UNSIGNED_INT -> int32Type
|
||||
ObjCValueType.UNSIGNED_LONG_LONG -> int64Type
|
||||
ObjCValueType.FLOAT -> floatType
|
||||
ObjCValueType.DOUBLE -> doubleType
|
||||
ObjCValueType.POINTER -> kInt8Ptr
|
||||
private fun ObjCValueType.toLlvmType(llvm: Llvm): LLVMTypeRef = when (this) {
|
||||
ObjCValueType.BOOL -> llvm.int8Type
|
||||
ObjCValueType.UNICHAR -> llvm.int16Type
|
||||
ObjCValueType.CHAR -> llvm.int8Type
|
||||
ObjCValueType.SHORT -> llvm.int16Type
|
||||
ObjCValueType.INT -> llvm.int32Type
|
||||
ObjCValueType.LONG_LONG -> llvm.int64Type
|
||||
ObjCValueType.UNSIGNED_CHAR -> llvm.int8Type
|
||||
ObjCValueType.UNSIGNED_SHORT -> llvm.int16Type
|
||||
ObjCValueType.UNSIGNED_INT -> llvm.int32Type
|
||||
ObjCValueType.UNSIGNED_LONG_LONG -> llvm.int64Type
|
||||
ObjCValueType.FLOAT -> llvm.floatType
|
||||
ObjCValueType.DOUBLE -> llvm.doubleType
|
||||
ObjCValueType.POINTER -> llvm.int8PtrType
|
||||
}
|
||||
|
||||
private fun MethodBridgeParameter.toLlvmParamType(): LlvmParamType = when (this) {
|
||||
is MethodBridgeValueParameter.Mapped -> this.bridge.toLlvmParamType()
|
||||
is MethodBridgeReceiver -> ReferenceBridge.toLlvmParamType()
|
||||
MethodBridgeSelector -> LlvmParamType(int8TypePtr)
|
||||
MethodBridgeValueParameter.ErrorOutParameter -> LlvmParamType(pointerType(ReferenceBridge.toLlvmParamType().llvmType))
|
||||
is MethodBridgeValueParameter.SuspendCompletion -> LlvmParamType(int8TypePtr)
|
||||
private fun MethodBridgeParameter.toLlvmParamType(llvm: Llvm): LlvmParamType = when (this) {
|
||||
is MethodBridgeValueParameter.Mapped -> this.bridge.toLlvmParamType(llvm)
|
||||
is MethodBridgeReceiver -> ReferenceBridge.toLlvmParamType(llvm)
|
||||
MethodBridgeSelector -> LlvmParamType(llvm.int8PtrType)
|
||||
MethodBridgeValueParameter.ErrorOutParameter -> LlvmParamType(pointerType(ReferenceBridge.toLlvmParamType(llvm).llvmType))
|
||||
is MethodBridgeValueParameter.SuspendCompletion -> LlvmParamType(llvm.int8PtrType)
|
||||
}
|
||||
|
||||
private fun MethodBridge.ReturnValue.toLlvmRetType(
|
||||
context: Context
|
||||
): LlvmRetType = when (this) {
|
||||
MethodBridge.ReturnValue.Suspend,
|
||||
MethodBridge.ReturnValue.Void -> LlvmRetType(voidType)
|
||||
MethodBridge.ReturnValue.HashCode -> LlvmRetType(if (context.is64BitNSInteger()) int64Type else int32Type)
|
||||
is MethodBridge.ReturnValue.Mapped -> this.bridge.toLlvmParamType()
|
||||
MethodBridge.ReturnValue.WithError.Success -> ValueTypeBridge(ObjCValueType.BOOL).toLlvmParamType()
|
||||
): LlvmRetType {
|
||||
val llvm = context.generationState.llvm
|
||||
return when (this) {
|
||||
MethodBridge.ReturnValue.Suspend,
|
||||
MethodBridge.ReturnValue.Void -> LlvmRetType(llvm.voidType)
|
||||
|
||||
MethodBridge.ReturnValue.Instance.InitResult,
|
||||
MethodBridge.ReturnValue.Instance.FactoryResult -> ReferenceBridge.toLlvmParamType()
|
||||
is MethodBridge.ReturnValue.WithError.ZeroForError -> this.successBridge.toLlvmRetType(context)
|
||||
MethodBridge.ReturnValue.HashCode -> LlvmRetType(if (context.is64BitNSInteger()) llvm.int64Type else llvm.int32Type)
|
||||
is MethodBridge.ReturnValue.Mapped -> this.bridge.toLlvmParamType(llvm)
|
||||
MethodBridge.ReturnValue.WithError.Success -> ValueTypeBridge(ObjCValueType.BOOL).toLlvmParamType(llvm)
|
||||
|
||||
MethodBridge.ReturnValue.Instance.InitResult,
|
||||
MethodBridge.ReturnValue.Instance.FactoryResult -> ReferenceBridge.toLlvmParamType(llvm)
|
||||
|
||||
is MethodBridge.ReturnValue.WithError.ZeroForError -> this.successBridge.toLlvmRetType(context)
|
||||
}
|
||||
}
|
||||
|
||||
private fun TypeBridge.toLlvmParamType(): LlvmParamType = when (this) {
|
||||
is ReferenceBridge, is BlockPointerBridge -> LlvmParamType(int8TypePtr)
|
||||
is ValueTypeBridge -> LlvmParamType(this.objCValueType.llvmType, this.objCValueType.defaultParameterAttributes)
|
||||
private fun TypeBridge.toLlvmParamType(llvm: Llvm): LlvmParamType = when (this) {
|
||||
is ReferenceBridge, is BlockPointerBridge -> LlvmParamType(llvm.int8PtrType)
|
||||
is ValueTypeBridge -> LlvmParamType(this.objCValueType.toLlvmType(llvm), this.objCValueType.defaultParameterAttributes)
|
||||
}
|
||||
|
||||
internal fun ObjCExportCodeGenerator.getEncoding(methodBridge: MethodBridge): String {
|
||||
@@ -2021,7 +2026,7 @@ internal fun ObjCExportCodeGenerator.getEncoding(methodBridge: MethodBridge): St
|
||||
methodBridge.paramBridges.forEach {
|
||||
append(it.objCEncoding)
|
||||
append(paramOffset)
|
||||
paramOffset += LLVMStoreSizeOfType(runtime.targetData, it.toLlvmParamType().llvmType).toInt()
|
||||
paramOffset += LLVMStoreSizeOfType(runtime.targetData, it.toLlvmParamType(llvm).llvmType).toInt()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -496,7 +496,7 @@ internal object DataFlowIR {
|
||||
val placeToClassTable = true
|
||||
val symbolTableIndex = if (placeToClassTable) module.numberOfClasses++ else -1
|
||||
val type = if (irClass.isExported())
|
||||
Type.Public(name.localHash.value, privateTypeIndex++, isFinal, isAbstract, null,
|
||||
Type.Public(localHash(name.toByteArray()), privateTypeIndex++, isFinal, isAbstract, null,
|
||||
module, symbolTableIndex, irClass, takeName { name })
|
||||
else
|
||||
Type.Private(privateTypeIndex++, isFinal, isAbstract, null,
|
||||
@@ -618,7 +618,7 @@ internal object DataFlowIR {
|
||||
val escapesBitMask = (escapesAnnotation?.getValueArgument(0) as? IrConst<Int>)?.value
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val pointsToBitMask = (pointsToAnnotation?.getValueArgument(0) as? IrVararg)?.elements?.map { (it as IrConst<Int>).value }
|
||||
FunctionSymbol.External(name.localHash.value, attributes, it, takeName { name }, it.isExported()).apply {
|
||||
FunctionSymbol.External(localHash(name.toByteArray()), attributes, it, takeName { name }, it.isExported()).apply {
|
||||
escapes = escapesBitMask
|
||||
pointsTo = pointsToBitMask?.toIntArray()
|
||||
}
|
||||
@@ -637,7 +637,7 @@ internal object DataFlowIR {
|
||||
val symbolTableIndex = if (placeToFunctionsTable) module.numberOfFunctions++ else -1
|
||||
val frozen = it is IrConstructor && irClass!!.isFrozen(context)
|
||||
val functionSymbol = if (it.isExported())
|
||||
FunctionSymbol.Public(name.localHash.value, module, symbolTableIndex, attributes, it, bridgeTargetSymbol, takeName { name })
|
||||
FunctionSymbol.Public(localHash(name.toByteArray()), module, symbolTableIndex, attributes, it, bridgeTargetSymbol, takeName { name })
|
||||
else
|
||||
FunctionSymbol.Private(privateFunIndex++, module, symbolTableIndex, attributes, it, bridgeTargetSymbol, takeName { name })
|
||||
if (frozen) {
|
||||
|
||||
Reference in New Issue
Block a user