[K/N][codegen] Moved llvmContext from global scope to generationState

This commit is contained in:
Igor Chevdar
2022-09-02 22:26:41 +03:00
committed by Space Team
parent cb23dbb492
commit 4ac9e49abd
33 changed files with 699 additions and 751 deletions
@@ -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
}
@@ -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)
@@ -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()
}
@@ -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)
}
@@ -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
@@ -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) {
@@ -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
@@ -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() -> {
@@ -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.
@@ -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)
}
@@ -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
}
}
@@ -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)
}
@@ -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")
}
}
@@ -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
}
@@ -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) {
@@ -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)
}
}
@@ -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(
@@ -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)
}
}
@@ -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)
)
}
@@ -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) }
@@ -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,
@@ -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()
@@ -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) }
@@ -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)
@@ -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)!!
}
}
@@ -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)
@@ -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)
}
}
@@ -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,
@@ -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)
@@ -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
@@ -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)
@@ -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()
}
}
@@ -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) {