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