[K/N][IR][codegen] Introduced NativeGenerationState
This commit is contained in:
+1
-1
@@ -31,7 +31,7 @@ internal class BitcodeCompiler(val context: Context) {
|
||||
.execute()
|
||||
|
||||
private fun temporary(name: String, suffix: String): String =
|
||||
context.config.tempFiles.create(name, suffix).absolutePath
|
||||
context.generationState.tempFiles.create(name, suffix).absolutePath
|
||||
|
||||
private fun targetTool(tool: String, vararg arg: String) {
|
||||
val absoluteToolName = if (platform.configurables is AppleConfigurables) {
|
||||
|
||||
+4
-4
@@ -174,7 +174,7 @@ internal fun initializeCachedBoxes(context: Context) {
|
||||
val rangeEnd = "${cache.name}_RANGE_TO"
|
||||
initCache(cache, context, cacheName, rangeStart, rangeEnd,
|
||||
declareOnly = !context.shouldDefineCachedBoxes
|
||||
).also { context.llvm.boxCacheGlobals[cache] = it }
|
||||
).also { context.generationState.llvm.boxCacheGlobals[cache] = it }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,9 +185,9 @@ private fun initCache(cache: BoxCache, context: Context, cacheName: String,
|
||||
rangeStartName: String, rangeEndName: String, declareOnly: Boolean) : StaticData.Global {
|
||||
|
||||
val kotlinType = context.irBuiltIns.getKotlinClass(cache)
|
||||
val staticData = context.llvm.staticData
|
||||
val staticData = context.generationState.llvm.staticData
|
||||
val llvmType = staticData.getLLVMType(kotlinType.defaultType)
|
||||
val llvmBoxType = structType(context.llvm.runtime.objHeaderType, llvmType)
|
||||
val llvmBoxType = structType(context.generationState.llvm.runtime.objHeaderType, llvmType)
|
||||
val (start, end) = context.config.target.getBoxCacheRange(cache)
|
||||
|
||||
return if (declareOnly) {
|
||||
@@ -227,7 +227,7 @@ internal fun IrConstantPrimitive.toBoxCacheValue(context: Context): ConstValue?
|
||||
}
|
||||
val (start, end) = context.config.target.getBoxCacheRange(cacheType)
|
||||
return if (value in start..end) {
|
||||
context.llvm.boxCacheGlobals[cacheType]?.pointer?.getElementPtr(value.toInt() - start)?.getElementPtr(0)
|
||||
context.generationState.llvm.boxCacheGlobals[cacheType]?.pointer?.getElementPtr(value.toInt() - start)?.getElementPtr(0)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
+4
-4
@@ -245,7 +245,7 @@ private class ExportedElement(val kind: ElementKind,
|
||||
// Produce type getter.
|
||||
val getTypeFunction = addLlvmFunctionWithDefaultAttributes(
|
||||
context,
|
||||
context.llvmModule!!,
|
||||
llvm.module,
|
||||
"${cname}_type",
|
||||
owner.kGetTypeFuncType
|
||||
)
|
||||
@@ -830,7 +830,7 @@ internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVi
|
||||
val exportedSymbols = mutableListOf<String>()
|
||||
|
||||
private fun makeGlobalStruct(top: ExportedElementScope) {
|
||||
val headerFile = context.config.outputFiles.cAdapterHeader
|
||||
val headerFile = context.generationState.outputFiles.cAdapterHeader
|
||||
outputStreamWriter = headerFile.printWriter()
|
||||
|
||||
val exportedSymbol = "${prefix}_symbols"
|
||||
@@ -915,7 +915,7 @@ internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVi
|
||||
outputStreamWriter.close()
|
||||
println("Produced library API in ${prefix}_api.h")
|
||||
|
||||
outputStreamWriter = context.config.tempFiles
|
||||
outputStreamWriter = context.generationState.tempFiles
|
||||
.cAdapterCpp
|
||||
.printWriter()
|
||||
|
||||
@@ -1055,7 +1055,7 @@ internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVi
|
||||
outputStreamWriter.close()
|
||||
|
||||
if (context.config.target.family == Family.MINGW) {
|
||||
outputStreamWriter = context.config.outputFiles
|
||||
outputStreamWriter = context.generationState.outputFiles
|
||||
.cAdapterDef
|
||||
.printWriter()
|
||||
output("EXPORTS")
|
||||
|
||||
+14
-11
@@ -21,6 +21,7 @@ private fun LLVMValueRef.isLLVMBuiltin(): Boolean {
|
||||
|
||||
|
||||
private class CallsChecker(val context: Context, goodFunctions: List<String>) {
|
||||
private val llvm = context.generationState.llvm
|
||||
private val goodFunctionsExact = goodFunctions.filterNot { it.endsWith("*") }.toSet()
|
||||
private val goodFunctionsByPrefix = goodFunctions.filter { it.endsWith("*") }.map { it.substring(0, it.length - 1) }.sorted()
|
||||
|
||||
@@ -33,23 +34,23 @@ private class CallsChecker(val context: Context, goodFunctions: List<String>) {
|
||||
}
|
||||
|
||||
private fun moduleFunction(name: String) =
|
||||
LLVMGetNamedFunction(context.llvmModule, name) ?: throw IllegalStateException("$name function is not available")
|
||||
LLVMGetNamedFunction(llvm.module, name) ?: throw IllegalStateException("$name function is not available")
|
||||
|
||||
val getMethodImpl = context.llvm.externalFunction(LlvmFunctionProto(
|
||||
val getMethodImpl = llvm.externalFunction(LlvmFunctionProto(
|
||||
"class_getMethodImplementation",
|
||||
LlvmRetType(pointerType(functionType(voidType, false))),
|
||||
listOf(LlvmParamType(int8TypePtr), LlvmParamType(int8TypePtr)),
|
||||
origin = context.stdlibModule.llvmSymbolOrigin)
|
||||
)
|
||||
|
||||
val getClass = context.llvm.externalFunction(LlvmFunctionProto(
|
||||
val getClass = llvm.externalFunction(LlvmFunctionProto(
|
||||
"object_getClass",
|
||||
LlvmRetType(int8TypePtr),
|
||||
listOf(LlvmParamType(int8TypePtr)),
|
||||
origin = context.stdlibModule.llvmSymbolOrigin)
|
||||
)
|
||||
|
||||
val getSuperClass = context.llvm.externalFunction(LlvmFunctionProto(
|
||||
val getSuperClass = llvm.externalFunction(LlvmFunctionProto(
|
||||
"class_getSuperclass",
|
||||
LlvmRetType(int8TypePtr),
|
||||
listOf(LlvmParamType(int8TypePtr)),
|
||||
@@ -140,8 +141,8 @@ private class CallsChecker(val context: Context, goodFunctions: List<String>) {
|
||||
}
|
||||
}
|
||||
}
|
||||
val callSiteDescriptionLlvm = context.llvm.staticData.cStringLiteral(callSiteDescription).llvm
|
||||
val calledNameLlvm = if (calledName == null) LLVMConstNull(int8TypePtr) else context.llvm.staticData.cStringLiteral(calledName).llvm
|
||||
val callSiteDescriptionLlvm = llvm.staticData.cStringLiteral(callSiteDescription).llvm
|
||||
val calledNameLlvm = if (calledName == null) LLVMConstNull(int8TypePtr) else llvm.staticData.cStringLiteral(calledName).llvm
|
||||
LLVMBuildCall(builder, checkerFunction, listOf(callSiteDescriptionLlvm, calledNameLlvm, calledPtrLlvm).toCValues(), 3, "")
|
||||
}
|
||||
LLVMDisposeBuilder(builder)
|
||||
@@ -164,10 +165,11 @@ private const val functionListGlobal = "Kotlin_callsCheckerKnownFunctions"
|
||||
private const val functionListSizeGlobal = "Kotlin_callsCheckerKnownFunctionsCount"
|
||||
|
||||
internal fun checkLlvmModuleExternalCalls(context: Context) {
|
||||
val staticData = context.llvm.staticData
|
||||
val llvm = context.generationState.llvm
|
||||
val staticData = llvm.staticData
|
||||
|
||||
|
||||
val ignoredFunctions = (context.llvm.runtimeAnnotationMap["no_external_calls_check"] ?: emptyList())
|
||||
val ignoredFunctions = (llvm.runtimeAnnotationMap["no_external_calls_check"] ?: emptyList())
|
||||
|
||||
val goodFunctions = staticData.getGlobal("Kotlin_callsCheckerGoodFunctionNames")?.getInitializer()?.run {
|
||||
getOperands(this).map {
|
||||
@@ -176,7 +178,7 @@ internal fun checkLlvmModuleExternalCalls(context: Context) {
|
||||
} ?: emptyList()
|
||||
|
||||
val checker = CallsChecker(context, goodFunctions)
|
||||
getFunctions(context.llvmModule!!)
|
||||
getFunctions(llvm.module)
|
||||
.filter { !it.isExternalFunction() && it !in ignoredFunctions }
|
||||
.forEach(checker::processFunction)
|
||||
// otherwise optimiser can inline it
|
||||
@@ -187,9 +189,10 @@ internal fun checkLlvmModuleExternalCalls(context: Context) {
|
||||
|
||||
// this should be a separate pass, to handle DCE correctly
|
||||
internal fun addFunctionsListSymbolForChecker(context: Context) {
|
||||
val staticData = context.llvm.staticData
|
||||
val llvm = context.generationState.llvm
|
||||
val staticData = llvm.staticData
|
||||
|
||||
val functions = getFunctions(context.llvmModule!!)
|
||||
val functions = getFunctions(llvm.module)
|
||||
.filter { !it.isExternalFunction() }
|
||||
.map { constPointer(it).bitcast(int8TypePtr) }
|
||||
.toList()
|
||||
|
||||
+18
-20
@@ -78,23 +78,22 @@ internal fun llvmIrDumpCallback(state: ActionState, module: IrModuleFragment, co
|
||||
if (state.beforeOrAfter == BeforeOrAfter.AFTER && state.phase.name in context.configuration.getList(KonanConfigKeys.SAVE_LLVM_IR)) {
|
||||
val moduleName: String = memScoped {
|
||||
val sizeVar = alloc<size_tVar>()
|
||||
LLVMGetModuleIdentifier(context.llvmModule, sizeVar.ptr)!!.toKStringFromUtf8()
|
||||
LLVMGetModuleIdentifier(context.generationState.llvm.module, sizeVar.ptr)!!.toKStringFromUtf8()
|
||||
}
|
||||
val output = context.config.tempFiles.create("$moduleName.${state.phase.name}", ".ll")
|
||||
if (LLVMPrintModuleToFile(context.llvmModule, output.absolutePath, null) != 0) {
|
||||
val output = context.generationState.tempFiles.create("$moduleName.${state.phase.name}", ".ll")
|
||||
if (LLVMPrintModuleToFile(context.generationState.llvm.module, output.absolutePath, null) != 0) {
|
||||
error("Can't dump LLVM IR to ${output.absolutePath}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun produceCStubs(context: Context) {
|
||||
val llvmModule = context.llvmModule!!
|
||||
context.cStubsManager.compile(
|
||||
context.generationState.cStubsManager.compile(
|
||||
context.config.clang,
|
||||
context.messageCollector,
|
||||
context.inVerbosePhase
|
||||
).forEach {
|
||||
parseAndLinkBitcodeFile(context, llvmModule, it.absolutePath)
|
||||
parseAndLinkBitcodeFile(context, context.generationState.llvm.module, it.absolutePath)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,7 +114,7 @@ private data class LlvmModules(
|
||||
private fun collectLlvmModules(context: Context, generatedBitcodeFiles: List<String>): LlvmModules {
|
||||
val config = context.config
|
||||
|
||||
val (bitcodePartOfStdlib, bitcodeLibraries) = context.llvm.bitcodeToLink
|
||||
val (bitcodePartOfStdlib, bitcodeLibraries) = context.generationState.llvm.bitcodeToLink
|
||||
.partition { it.isStdlib && context.producedLlvmModuleContainsStdlib }
|
||||
.toList()
|
||||
.map { libraries ->
|
||||
@@ -124,7 +123,7 @@ private fun collectLlvmModules(context: Context, generatedBitcodeFiles: List<Str
|
||||
|
||||
val nativeLibraries = config.nativeLibraries + config.launcherNativeLibraries
|
||||
.takeIf { config.produce == CompilerOutputKind.PROGRAM }.orEmpty()
|
||||
val additionalBitcodeFilesToLink = context.llvm.additionalProducedBitcodeFiles
|
||||
val additionalBitcodeFilesToLink = context.generationState.llvm.additionalProducedBitcodeFiles
|
||||
val exceptionsSupportNativeLibrary = listOf(config.exceptionsSupportNativeLibrary)
|
||||
.takeIf { config.produce == CompilerOutputKind.DYNAMIC_CACHE }.orEmpty()
|
||||
val additionalBitcodeFiles = nativeLibraries +
|
||||
@@ -160,9 +159,8 @@ private fun linkAllDependencies(context: Context, generatedBitcodeFiles: List<St
|
||||
// TODO: Possibly slow, maybe to a separate phase?
|
||||
val optimizedRuntimeModules = RuntimeLinkageStrategy.pick(context, runtimeModules).run()
|
||||
|
||||
val llvmModule = context.llvmModule!!
|
||||
(optimizedRuntimeModules + additionalModules).forEach {
|
||||
val failed = llvmLinkModules2(context, llvmModule, it)
|
||||
val failed = llvmLinkModules2(context, context.generationState.llvm.module, it)
|
||||
if (failed != 0) {
|
||||
error("Failed to link ${it.getName()}")
|
||||
}
|
||||
@@ -173,7 +171,7 @@ private fun insertAliasToEntryPoint(context: Context) {
|
||||
val nomain = context.config.configuration.get(KonanConfigKeys.NOMAIN) ?: false
|
||||
if (context.config.produce != CompilerOutputKind.PROGRAM || nomain)
|
||||
return
|
||||
val module = context.llvmModule
|
||||
val module = context.generationState.llvm.module
|
||||
val entryPointName = context.config.entryPointName
|
||||
val entryPoint = LLVMGetNamedFunction(module, entryPointName)
|
||||
?: error("Module doesn't contain `$entryPointName`")
|
||||
@@ -182,7 +180,7 @@ private fun insertAliasToEntryPoint(context: Context) {
|
||||
|
||||
internal fun linkBitcodeDependencies(context: Context) {
|
||||
val config = context.config.configuration
|
||||
val tempFiles = context.config.tempFiles
|
||||
val tempFiles = context.generationState.tempFiles
|
||||
val produce = config.get(KonanConfigKeys.PRODUCE)
|
||||
|
||||
val generatedBitcodeFiles =
|
||||
@@ -194,7 +192,7 @@ internal fun linkBitcodeDependencies(context: Context) {
|
||||
listOf(tempFiles.cAdapterBitcodeName)
|
||||
} else emptyList()
|
||||
if (produce == CompilerOutputKind.FRAMEWORK && context.config.produceStaticFramework) {
|
||||
embedAppleLinkerOptionsToBitcode(context.llvm, context.config)
|
||||
embedAppleLinkerOptionsToBitcode(context.generationState.llvm, context.config)
|
||||
}
|
||||
linkAllDependencies(context, generatedBitcodeFiles)
|
||||
|
||||
@@ -203,7 +201,7 @@ internal fun linkBitcodeDependencies(context: Context) {
|
||||
internal fun produceOutput(context: Context) {
|
||||
|
||||
val config = context.config.configuration
|
||||
val tempFiles = context.config.tempFiles
|
||||
val tempFiles = context.generationState.tempFiles
|
||||
val produce = context.config.produce
|
||||
if (produce == CompilerOutputKind.FRAMEWORK) {
|
||||
context.objCExport.produceFrameworkInterface()
|
||||
@@ -224,11 +222,11 @@ internal fun produceOutput(context: Context) {
|
||||
// Insert `_main` after pipeline so we won't worry about optimizations
|
||||
// corrupting entry point.
|
||||
insertAliasToEntryPoint(context)
|
||||
LLVMWriteBitcodeToFile(context.llvmModule!!, output)
|
||||
LLVMWriteBitcodeToFile(context.generationState.llvm.module, output)
|
||||
}
|
||||
CompilerOutputKind.LIBRARY -> {
|
||||
val nopack = config.getBoolean(KonanConfigKeys.NOPACK)
|
||||
val output = context.config.outputFiles.klibOutputFileName(!nopack)
|
||||
val output = context.generationState.outputFiles.klibOutputFileName(!nopack)
|
||||
val libraryName = context.config.moduleId
|
||||
val shortLibraryName = context.config.shortModuleName
|
||||
val neededLibraries = context.librariesWithDependencies
|
||||
@@ -248,7 +246,7 @@ internal fun produceOutput(context: Context) {
|
||||
val manifestProperties = context.config.manifestProperties
|
||||
|
||||
if (!nopack) {
|
||||
val suffix = context.config.outputFiles.produce.suffix(target)
|
||||
val suffix = context.config.produce.suffix(target)
|
||||
if (!output.endsWith(suffix)) {
|
||||
error("please specify correct output: packed: ${!nopack}, $output$suffix")
|
||||
}
|
||||
@@ -272,9 +270,9 @@ internal fun produceOutput(context: Context) {
|
||||
context.bitcodeFileName = library.mainBitcodeFileName
|
||||
}
|
||||
CompilerOutputKind.BITCODE -> {
|
||||
val output = context.config.outputFile
|
||||
val output = context.generationState.outputFile
|
||||
context.bitcodeFileName = output
|
||||
LLVMWriteBitcodeToFile(context.llvmModule!!, output)
|
||||
LLVMWriteBitcodeToFile(context.generationState.llvm.module, output)
|
||||
}
|
||||
CompilerOutputKind.PRELIMINARY_CACHE -> {}
|
||||
}
|
||||
@@ -309,5 +307,5 @@ private fun embedAppleLinkerOptionsToBitcode(llvm: Llvm, config: KonanConfig) {
|
||||
val optionsToEmbed = findEmbeddableOptions(config.platform.configurables.linkerKonanFlags) +
|
||||
llvm.allNativeDependencies.flatMap { findEmbeddableOptions(it.linkerOpts) }
|
||||
|
||||
embedLlvmLinkOptions(llvm.llvmModule, optionsToEmbed)
|
||||
embedLlvmLinkOptions(llvm.module, optionsToEmbed)
|
||||
}
|
||||
|
||||
+25
-87
@@ -5,29 +5,30 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import llvm.*
|
||||
import llvm.LLVMTypeRef
|
||||
import org.jetbrains.kotlin.backend.common.DefaultDelegateFactory
|
||||
import org.jetbrains.kotlin.backend.common.DefaultMapping
|
||||
import org.jetbrains.kotlin.backend.common.LoggingContext
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.BridgeDirections
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.ClassLayoutBuilder
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.GlobalHierarchyAnalysisResult
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.deepPrint
|
||||
import org.jetbrains.kotlin.backend.konan.ir.KonanIr
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.CodegenClassMetadata
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.Lifetime
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.coverage.CoverageManager
|
||||
import org.jetbrains.kotlin.backend.konan.lower.*
|
||||
import org.jetbrains.kotlin.backend.konan.lower.BridgesSupport
|
||||
import org.jetbrains.kotlin.backend.konan.lower.EnumsSupport
|
||||
import org.jetbrains.kotlin.backend.konan.lower.InlineFunctionsSupport
|
||||
import org.jetbrains.kotlin.backend.konan.lower.InnerClassesSupport
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport
|
||||
import org.jetbrains.kotlin.backend.konan.optimizations.DevirtualizationAnalysis
|
||||
import org.jetbrains.kotlin.backend.konan.optimizations.ExternalModulesDFG
|
||||
import org.jetbrains.kotlin.backend.konan.optimizations.ModuleDFG
|
||||
import org.jetbrains.kotlin.backend.konan.serialization.KonanIrLinker
|
||||
import org.jetbrains.kotlin.backend.konan.serialization.SerializedClassFields
|
||||
import org.jetbrains.kotlin.backend.konan.serialization.SerializedInlineFunctionReference
|
||||
import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
@@ -36,15 +37,13 @@ import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrTypeSystemContext
|
||||
import org.jetbrains.kotlin.ir.types.IrTypeSystemContextImpl
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibraryLayout
|
||||
import org.jetbrains.kotlin.konan.target.Architecture
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.konan.target.needSmallBinary
|
||||
import org.jetbrains.kotlin.library.SerializedIrModule
|
||||
import org.jetbrains.kotlin.library.SerializedMetadata
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
@@ -54,8 +53,6 @@ import java.lang.System.out
|
||||
import kotlin.LazyThreadSafetyMode.PUBLICATION
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
internal class InlineFunctionOriginInfo(val irFunction: IrFunction, val irFile: IrFile, val startOffset: Int, val endOffset: Int)
|
||||
|
||||
internal class NativeMapping : DefaultMapping() {
|
||||
data class BridgeKey(val target: IrSimpleFunction, val bridgeDirections: BridgeDirections)
|
||||
|
||||
@@ -65,7 +62,6 @@ internal class NativeMapping : DefaultMapping() {
|
||||
val enumEntriesMaps = mutableMapOf<IrClass, Map<Name, LoweredEnumEntryDescription>>()
|
||||
val bridges = mutableMapOf<BridgeKey, IrSimpleFunction>()
|
||||
val notLoweredInlineFunctions = mutableMapOf<IrFunctionSymbol, IrFunction>()
|
||||
val loweredInlineFunctions = mutableMapOf<IrFunction, InlineFunctionOriginInfo>()
|
||||
val companionObjectCacheAccessors = DefaultDelegateFactory.newDeclarationToDeclarationMapping<IrClass, IrSimpleFunction>()
|
||||
val outerThisCacheAccessors = DefaultDelegateFactory.newDeclarationToDeclarationMapping<IrClass, IrSimpleFunction>()
|
||||
val lateinitPropertyCacheAccessors = DefaultDelegateFactory.newDeclarationToDeclarationMapping<IrProperty, IrSimpleFunction>()
|
||||
@@ -95,6 +91,12 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
|
||||
|
||||
override val optimizeLoopsOverUnsignedArrays = true
|
||||
|
||||
lateinit var generationState: NativeGenerationState
|
||||
|
||||
fun disposeGenerationState() {
|
||||
if (::generationState.isInitialized) generationState.dispose()
|
||||
}
|
||||
|
||||
val phaseConfig = config.phaseConfig
|
||||
|
||||
private val packageScope by lazy { builtIns.builtInsModule.getPackage(KonanFqNames.internalPackageName).memberScope }
|
||||
@@ -143,21 +145,6 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
|
||||
lazyValues[member] = newValue
|
||||
}
|
||||
|
||||
val localClassNames = mutableMapOf<IrAttributeContainer, String>()
|
||||
|
||||
fun getLocalClassName(container: IrAttributeContainer): String? = localClassNames[container.attributeOwnerId]
|
||||
|
||||
fun putLocalClassName(container: IrAttributeContainer, name: String) {
|
||||
localClassNames[container.attributeOwnerId] = name
|
||||
}
|
||||
|
||||
fun copyLocalClassName(source: IrAttributeContainer, destination: IrAttributeContainer) {
|
||||
getLocalClassName(source)?.let { name -> putLocalClassName(destination, name) }
|
||||
}
|
||||
|
||||
/* test suite class -> test function names */
|
||||
val testCasesToDump = mutableMapOf<ClassId, MutableCollection<String>>()
|
||||
|
||||
val reflectionTypes: KonanReflectionTypes by lazy(PUBLICATION) {
|
||||
KonanReflectionTypes(moduleDescriptor)
|
||||
}
|
||||
@@ -225,49 +212,12 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
|
||||
InteropBuiltIns(this.builtIns)
|
||||
}
|
||||
|
||||
var llvmModule: LLVMModuleRef? = null
|
||||
set(module) {
|
||||
field = module!!
|
||||
|
||||
llvm = Llvm(this, module)
|
||||
debugInfo = DebugInfo(this)
|
||||
}
|
||||
|
||||
lateinit var runtime: Runtime
|
||||
|
||||
private var runtimeDisposed = false
|
||||
|
||||
fun disposeRuntime() {
|
||||
if (runtimeDisposed) return
|
||||
if (::runtime.isInitialized) {
|
||||
LLVMDisposeTargetData(runtime.targetData)
|
||||
LLVMDisposeModule(runtime.llvmModule)
|
||||
}
|
||||
runtimeDisposed = true
|
||||
}
|
||||
|
||||
lateinit var llvmImports: LlvmImports
|
||||
lateinit var llvm: Llvm
|
||||
lateinit var llvmDeclarations: LlvmDeclarations
|
||||
lateinit var bitcodeFileName: String
|
||||
lateinit var library: KonanLibraryLayout
|
||||
|
||||
var llvmDisposed = false
|
||||
val coverage by lazy { CoverageManager(this) }
|
||||
|
||||
fun disposeLlvm() {
|
||||
if (llvmDisposed) return
|
||||
if (::debugInfo.isInitialized)
|
||||
LLVMDisposeDIBuilder(debugInfo.builder)
|
||||
if (llvmModule != null)
|
||||
LLVMDisposeModule(llvmModule)
|
||||
llvmDisposed = true
|
||||
}
|
||||
|
||||
var cStubsManager = CStubsManager(config.target)
|
||||
|
||||
val coverage = CoverageManager(this)
|
||||
|
||||
protected fun separator(title: String) {
|
||||
fun separator(title: String) {
|
||||
println("\n\n--- ${title} ----------------------\n")
|
||||
}
|
||||
|
||||
@@ -290,14 +240,13 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
|
||||
}
|
||||
|
||||
fun verifyBitCode() {
|
||||
if (llvmModule == null) return
|
||||
verifyModule(llvmModule!!)
|
||||
if (::generationState.isInitialized)
|
||||
generationState.verifyBitCode()
|
||||
}
|
||||
|
||||
fun printBitCode() {
|
||||
if (llvmModule == null) return
|
||||
separator("BitCode:")
|
||||
LLVMDumpModule(llvmModule!!)
|
||||
if (::generationState.isInitialized)
|
||||
generationState.printBitCode()
|
||||
}
|
||||
|
||||
fun verify() {
|
||||
@@ -342,11 +291,9 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
|
||||
}
|
||||
}
|
||||
|
||||
lateinit var debugInfo: DebugInfo
|
||||
var moduleDFG: ModuleDFG? = null
|
||||
var externalModulesDFG: ExternalModulesDFG? = null
|
||||
lateinit var lifetimes: MutableMap<IrElement, Lifetime>
|
||||
lateinit var codegenVisitor: CodeGeneratorVisitor
|
||||
val lifetimes = mutableMapOf<IrElement, Lifetime>()
|
||||
var devirtualizationAnalysisResult: DevirtualizationAnalysis.AnalysisResult? = null
|
||||
|
||||
var referencedFunctions: Set<IrFunction>? = null
|
||||
@@ -368,15 +315,6 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
|
||||
|
||||
lateinit var irLinker: KonanIrLinker
|
||||
|
||||
val inlineFunctionBodies = mutableListOf<SerializedInlineFunctionReference>()
|
||||
|
||||
val classFields = mutableListOf<SerializedClassFields>()
|
||||
|
||||
val calledFromExportedInlineFunctions = mutableSetOf<IrFunction>()
|
||||
val constructedFromExportedInlineFunctions = mutableSetOf<IrClass>()
|
||||
|
||||
val enumEntriesMaps = mutableMapOf<IrClass, Map<Name, LoweredEnumEntryDescription>>()
|
||||
|
||||
val targetAbiInfo: TargetAbiInfo by lazy {
|
||||
when {
|
||||
config.target == KonanTarget.MINGW_X64 -> {
|
||||
|
||||
+10
-23
@@ -23,16 +23,14 @@ import org.jetbrains.kotlin.konan.library.KonanLibrary
|
||||
import org.jetbrains.kotlin.konan.properties.loadProperties
|
||||
import org.jetbrains.kotlin.konan.target.*
|
||||
import org.jetbrains.kotlin.konan.util.KonanHomeProvider
|
||||
import org.jetbrains.kotlin.konan.util.visibleName
|
||||
import org.jetbrains.kotlin.library.KotlinLibrary
|
||||
import org.jetbrains.kotlin.library.resolver.TopologicalLibraryOrder
|
||||
import org.jetbrains.kotlin.util.removeSuffixIfPresent
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
|
||||
class KonanConfig(val project: Project, val configuration: CompilerConfiguration) {
|
||||
|
||||
fun dispose() {
|
||||
tempFiles.dispose()
|
||||
}
|
||||
|
||||
internal val distribution = run {
|
||||
val overridenProperties = mutableMapOf<String, String>().apply {
|
||||
configuration.get(KonanConfigKeys.OVERRIDE_KONAN_PROPERTIES)?.let(this::putAll)
|
||||
@@ -417,32 +415,21 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
||||
get() = configuration.get(KonanConfigKeys.MAKE_PER_FILE_CACHE) == true
|
||||
&& configuration.get(KonanConfigKeys.BATCHED_PER_FILE_CACHE_BUILD) != false
|
||||
|
||||
lateinit var outputFiles: OutputFiles
|
||||
|
||||
lateinit var tempFiles: TempFiles
|
||||
|
||||
init {
|
||||
recreateOutputFiles(producePerFileCache)
|
||||
}
|
||||
|
||||
fun recreateOutputFiles(explicitlyProducePerFileCache: Boolean) {
|
||||
val outputPath = configuration.get(KonanConfigKeys.OUTPUT) ?: cacheSupport.tryGetImplicitOutput(explicitlyProducePerFileCache)
|
||||
outputFiles = OutputFiles(outputPath, target, produce, explicitlyProducePerFileCache)
|
||||
tempFiles = TempFiles(outputFiles.outputName, configuration.get(KonanConfigKeys.TEMPORARY_FILES_DIR))
|
||||
|
||||
println("ZZZ: ${outputFiles.outputName}")
|
||||
}
|
||||
|
||||
val outputFile get() = outputFiles.mainFileName
|
||||
val outputPath get() = configuration.get(KonanConfigKeys.OUTPUT)?.removeSuffixIfPresent(produce.suffix(target)) ?: produce.visibleName
|
||||
|
||||
private val implicitModuleName: String
|
||||
get() = if (produce.isCache) outputFiles.cacheFileName else File(outputFiles.outputName).name
|
||||
get() = cacheSupport.libraryToCache?.let {
|
||||
if (configuration.get(KonanConfigKeys.MAKE_PER_FILE_CACHE) == true)
|
||||
CachedLibraries.getPerFileCachedLibraryName(it.klib)
|
||||
else
|
||||
CachedLibraries.getCachedLibraryName(it.klib)
|
||||
}
|
||||
?: File(outputPath).name
|
||||
|
||||
val infoArgsOnly = (configuration.kotlinSourceRoots.isEmpty()
|
||||
&& configuration[KonanConfigKeys.INCLUDED_LIBRARIES].isNullOrEmpty()
|
||||
&& configuration[KonanConfigKeys.EXPORTED_LIBRARIES].isNullOrEmpty()
|
||||
&& libraryToCache == null)
|
||||
|| (producePerFileCache && outputFiles.mainFile.exists)
|
||||
|
||||
/**
|
||||
* Do not compile binary when compiling framework.
|
||||
|
||||
+3
-10
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.backend.common.phaser.CompilerPhase
|
||||
import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel
|
||||
import org.jetbrains.kotlin.backend.common.serialization.codedInputStream
|
||||
import org.jetbrains.kotlin.backend.common.serialization.proto.IrFile
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.tryDisposeLLVMContext
|
||||
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
@@ -64,12 +63,8 @@ class KonanDriver(val project: Project, val environment: KotlinCoreEnvironment,
|
||||
}
|
||||
|
||||
private fun KonanConfig.runTopLevelPhases() {
|
||||
try {
|
||||
ensureModuleName(this)
|
||||
runTopLevelPhases(this, environment)
|
||||
} finally {
|
||||
dispose()
|
||||
}
|
||||
ensureModuleName(this)
|
||||
runTopLevelPhases(this, environment)
|
||||
}
|
||||
|
||||
private fun ensureModuleName(config: KonanConfig) {
|
||||
@@ -107,9 +102,7 @@ private fun runTopLevelPhases(konanConfig: KonanConfig, environment: KotlinCoreE
|
||||
try {
|
||||
toplevelPhase.cast<CompilerPhase<Context, Unit, Unit>>().invokeToplevel(context.phaseConfig, context, Unit)
|
||||
} finally {
|
||||
context.disposeLlvm()
|
||||
context.disposeRuntime()
|
||||
tryDisposeLLVMContext()
|
||||
context.disposeGenerationState()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+18
-16
@@ -36,9 +36,9 @@ internal fun determineLinkerOutput(context: Context): LinkerOutputKind =
|
||||
|
||||
internal class CacheStorage(val context: Context) {
|
||||
private val isPreliminaryCache = context.config.produce == CompilerOutputKind.PRELIMINARY_CACHE
|
||||
private val outputFiles = context.generationState.outputFiles
|
||||
|
||||
fun renameOutput() {
|
||||
val outputFiles = context.config.outputFiles
|
||||
// For caches the output file is a directory. It might be created by someone else,
|
||||
// we have to delete it in order for the next renaming operation to succeed.
|
||||
// TODO: what if the directory is not empty?
|
||||
@@ -48,7 +48,7 @@ internal class CacheStorage(val context: Context) {
|
||||
}
|
||||
|
||||
fun saveAdditionalCacheInfo() {
|
||||
context.config.outputFiles.prepareTempDirectories()
|
||||
outputFiles.prepareTempDirectories()
|
||||
if (!isPreliminaryCache)
|
||||
saveCacheBitcodeDependencies()
|
||||
if (isPreliminaryCache || !context.config.producePerFileCache || context.config.produceBatchedPerFileCache) {
|
||||
@@ -62,20 +62,20 @@ internal class CacheStorage(val context: Context) {
|
||||
.getFullList(TopologicalLibraryOrder)
|
||||
.filter {
|
||||
require(it is KonanLibrary)
|
||||
context.llvmImports.bitcodeIsUsed(it)
|
||||
context.generationState.llvmImports.bitcodeIsUsed(it)
|
||||
&& it != context.config.cacheSupport.libraryToCache?.klib // Skip loops.
|
||||
}.cast<List<KonanLibrary>>()
|
||||
context.config.outputFiles.bitcodeDependenciesFile!!.writeLines(bitcodeDependencies.map { it.uniqueName })
|
||||
outputFiles.bitcodeDependenciesFile!!.writeLines(bitcodeDependencies.map { it.uniqueName })
|
||||
}
|
||||
|
||||
private fun saveInlineFunctionBodies() {
|
||||
context.config.outputFiles.inlineFunctionBodiesFile!!.writeBytes(
|
||||
InlineFunctionBodyReferenceSerializer.serialize(context.inlineFunctionBodies))
|
||||
outputFiles.inlineFunctionBodiesFile!!.writeBytes(
|
||||
InlineFunctionBodyReferenceSerializer.serialize(context.generationState.inlineFunctionBodies))
|
||||
}
|
||||
|
||||
private fun saveClassFields() {
|
||||
context.config.outputFiles.classFieldsFile!!.writeBytes(
|
||||
ClassFieldsSerializer.serialize(context.classFields))
|
||||
outputFiles.classFieldsFile!!.writeBytes(
|
||||
ClassFieldsSerializer.serialize(context.generationState.classFields))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,13 +91,13 @@ internal class Linker(val context: Context) {
|
||||
private val debug = context.config.debug || context.config.lightDebug
|
||||
|
||||
fun link(objectFiles: List<ObjectFile>) {
|
||||
val nativeDependencies = context.llvm.nativeDependenciesToLink
|
||||
val nativeDependencies = context.generationState.llvm.nativeDependenciesToLink
|
||||
|
||||
val includedBinariesLibraries = context.config.libraryToCache?.let { listOf(it.klib) }
|
||||
?: nativeDependencies.filterNot { context.config.cachedLibraries.isLibraryCached(it) }
|
||||
val includedBinaries = includedBinariesLibraries.map { (it as? KonanLibrary)?.includedPaths.orEmpty() }.flatten()
|
||||
|
||||
val libraryProvidedLinkerFlags = context.llvm.allNativeDependencies.map { it.linkerOpts }.flatten()
|
||||
val libraryProvidedLinkerFlags = context.generationState.llvm.allNativeDependencies.map { it.linkerOpts }.flatten()
|
||||
|
||||
runLinker(objectFiles, includedBinaries, libraryProvidedLinkerFlags)
|
||||
}
|
||||
@@ -122,6 +122,8 @@ internal class Linker(val context: Context) {
|
||||
private fun runLinker(objectFiles: List<ObjectFile>,
|
||||
includedBinaries: List<String>,
|
||||
libraryProvidedLinkerFlags: List<String>): ExecutableFile? {
|
||||
val outputFiles = context.generationState.outputFiles
|
||||
|
||||
val additionalLinkerArgs: List<String>
|
||||
val executable: String
|
||||
|
||||
@@ -129,15 +131,15 @@ internal class Linker(val context: Context) {
|
||||
additionalLinkerArgs = if (target.family.isAppleFamily) {
|
||||
when (context.config.produce) {
|
||||
CompilerOutputKind.DYNAMIC_CACHE ->
|
||||
listOf("-install_name", context.config.outputFiles.dynamicCacheInstallName)
|
||||
listOf("-install_name", outputFiles.dynamicCacheInstallName)
|
||||
else -> listOf("-dead_strip")
|
||||
}
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
executable = context.config.outputFiles.nativeBinaryFile
|
||||
executable = outputFiles.nativeBinaryFile
|
||||
} else {
|
||||
val framework = File(context.config.outputFile)
|
||||
val framework = File(context.generationState.outputFile)
|
||||
val dylibName = framework.name.removeSuffix(".framework")
|
||||
val dylibRelativePath = when (target.family) {
|
||||
Family.IOS,
|
||||
@@ -171,7 +173,7 @@ internal class Linker(val context: Context) {
|
||||
optimize = optimize,
|
||||
debug = debug,
|
||||
kind = linkerOutput,
|
||||
outputDsymBundle = context.config.outputFiles.symbolicInfoFile,
|
||||
outputDsymBundle = outputFiles.symbolicInfoFile,
|
||||
needsProfileLibrary = needsProfileLibrary,
|
||||
mimallocEnabled = mimallocEnabled,
|
||||
sanitizer = context.config.sanitizer
|
||||
@@ -216,7 +218,7 @@ internal class Linker(val context: Context) {
|
||||
LinkerInput(objectFiles, CachesToLink(emptyList(), caches.dynamic), emptyList(), cachingInvolved)
|
||||
}
|
||||
shouldPerformPreLink(caches, linkerOutputKind) -> {
|
||||
val preLinkResult = context.config.tempFiles.create("withStaticCaches", ".o").absolutePath
|
||||
val preLinkResult = context.generationState.tempFiles.create("withStaticCaches", ".o").absolutePath
|
||||
val preLinkCommands = linker.preLinkCommands(objectFiles + caches.static, preLinkResult)
|
||||
LinkerInput(listOf(preLinkResult), CachesToLink(emptyList(), caches.dynamic), preLinkCommands, cachingInvolved)
|
||||
}
|
||||
@@ -238,7 +240,7 @@ private fun determineCachesToLink(context: Context): CachesToLink {
|
||||
val staticCaches = mutableListOf<String>()
|
||||
val dynamicCaches = mutableListOf<String>()
|
||||
|
||||
context.llvm.allCachedBitcodeDependencies.forEach { library ->
|
||||
context.generationState.llvm.allCachedBitcodeDependencies.forEach { library ->
|
||||
val currentBinaryContainsLibrary = context.llvmModuleSpecification.containsLibrary(library)
|
||||
val cache = context.config.cachedLibraries.getLibraryCache(library)
|
||||
?: error("Library $library is expected to be cached")
|
||||
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.DWARF
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.DebugInfo
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.Llvm
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.LlvmDeclarations
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.llvmContext
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.tryDisposeLLVMContext
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.verifyModule
|
||||
import org.jetbrains.kotlin.backend.konan.serialization.SerializedClassFields
|
||||
import org.jetbrains.kotlin.backend.konan.serialization.SerializedInlineFunctionReference
|
||||
import org.jetbrains.kotlin.ir.declarations.IrAttributeContainer
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.konan.TempFiles
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
|
||||
internal class InlineFunctionOriginInfo(val irFunction: IrFunction, val irFile: IrFile, val startOffset: Int, val endOffset: Int)
|
||||
|
||||
internal class NativeGenerationState(private val context: Context) {
|
||||
private val config = context.config
|
||||
|
||||
private val explicitlyProducePerFileCache = config.producePerFileCache && !config.produceBatchedPerFileCache
|
||||
private val outputPath = config.cacheSupport.tryGetImplicitOutput(explicitlyProducePerFileCache) ?: config.outputPath
|
||||
val outputFiles = OutputFiles(outputPath, config.target, config.produce, explicitlyProducePerFileCache)
|
||||
val tempFiles = run {
|
||||
val pathToTempDir = config.configuration.get(KonanConfigKeys.TEMPORARY_FILES_DIR)?.let {
|
||||
val singleFileStrategy = config.cacheSupport.libraryToCache?.strategy as? CacheDeserializationStrategy.SingleFile
|
||||
if (singleFileStrategy == null)
|
||||
it
|
||||
else File(it, CacheSupport.cacheFileId(singleFileStrategy.fqName, singleFileStrategy.filePath)).path
|
||||
}
|
||||
TempFiles(outputFiles.outputName, pathToTempDir)
|
||||
}
|
||||
val outputFile = outputFiles.mainFileName
|
||||
|
||||
val inlineFunctionBodies = mutableListOf<SerializedInlineFunctionReference>()
|
||||
val classFields = mutableListOf<SerializedClassFields>()
|
||||
val calledFromExportedInlineFunctions = mutableSetOf<IrFunction>()
|
||||
val constructedFromExportedInlineFunctions = mutableSetOf<IrClass>()
|
||||
val loweredInlineFunctions = mutableMapOf<IrFunction, InlineFunctionOriginInfo>()
|
||||
|
||||
private val localClassNames = mutableMapOf<IrAttributeContainer, String>()
|
||||
fun getLocalClassName(container: IrAttributeContainer): String? = localClassNames[container.attributeOwnerId]
|
||||
fun putLocalClassName(container: IrAttributeContainer, name: String) {
|
||||
localClassNames[container.attributeOwnerId] = name
|
||||
}
|
||||
fun copyLocalClassName(source: IrAttributeContainer, destination: IrAttributeContainer) {
|
||||
getLocalClassName(source)?.let { name -> putLocalClassName(destination, name) }
|
||||
}
|
||||
|
||||
/* test suite class -> test function names */
|
||||
val testCasesToDump = mutableMapOf<ClassId, MutableCollection<String>>()
|
||||
|
||||
init {
|
||||
llvmContext = LLVMContextCreate()!!
|
||||
}
|
||||
|
||||
private val runtimeDelegate = lazy { Runtime(config.distribution.compilerInterface(config.target)) }
|
||||
private val llvmDelegate = lazy { Llvm(context, LLVMModuleCreateWithNameInContext("out", llvmContext)!!) }
|
||||
private val debugInfoDelegate = lazy {
|
||||
DebugInfo(context).also {
|
||||
it.builder = LLVMCreateDIBuilder(llvm.module)
|
||||
// we don't split path to filename and directory to provide enough level uniquely for dsymutil to avoid symbol
|
||||
// clashing, which happens on linking with libraries produced from intercepting sources.
|
||||
val filePath = outputFile.toFileAndFolder(context).path()
|
||||
it.compilationUnit = if (context.shouldContainLocationDebugInfo()) DICreateCompilationUnit(
|
||||
builder = it.builder,
|
||||
lang = DWARF.language(config),
|
||||
File = filePath,
|
||||
dir = "",
|
||||
producer = DWARF.producer,
|
||||
isOptimized = 0,
|
||||
flags = "",
|
||||
rv = DWARF.runtimeVersion(config)
|
||||
).cast()
|
||||
else null
|
||||
}
|
||||
}
|
||||
|
||||
val llvmImports = Llvm.ImportsImpl(context)
|
||||
val runtime by runtimeDelegate
|
||||
val llvm by llvmDelegate
|
||||
val debugInfo by debugInfoDelegate
|
||||
val cStubsManager = CStubsManager(config.target)
|
||||
lateinit var llvmDeclarations: LlvmDeclarations
|
||||
|
||||
fun verifyBitCode() {
|
||||
if (!llvmDelegate.isInitialized()) return
|
||||
verifyModule(llvm.module)
|
||||
}
|
||||
|
||||
fun printBitCode() {
|
||||
if (!llvmDelegate.isInitialized()) return
|
||||
context.separator("BitCode:")
|
||||
LLVMDumpModule(llvm.module)
|
||||
}
|
||||
|
||||
private var isDisposed = false
|
||||
fun dispose() {
|
||||
if (isDisposed) return
|
||||
|
||||
if (debugInfoDelegate.isInitialized()) {
|
||||
LLVMDisposeDIBuilder(debugInfo.builder)
|
||||
}
|
||||
if (llvmDelegate.isInitialized()) {
|
||||
LLVMDisposeModule(llvm.module)
|
||||
}
|
||||
if (runtimeDelegate.isInitialized()) {
|
||||
LLVMDisposeTargetData(runtime.targetData)
|
||||
LLVMDisposeModule(runtime.llvmModule)
|
||||
}
|
||||
tryDisposeLLVMContext()
|
||||
tempFiles.dispose()
|
||||
|
||||
isDisposed = true
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -89,7 +89,7 @@ private fun tryGetInlineThreshold(context: Context): Int? {
|
||||
internal fun createLTOPipelineConfigForRuntime(context: Context): LlvmPipelineConfig {
|
||||
val configurables: Configurables = context.config.platform.configurables
|
||||
return LlvmPipelineConfig(
|
||||
context.llvm.targetTriple,
|
||||
context.generationState.llvm.targetTriple,
|
||||
getCpuModel(context),
|
||||
getCpuFeatures(context),
|
||||
LlvmOptimizationLevel.AGGRESSIVE,
|
||||
@@ -160,7 +160,7 @@ internal fun createLTOFinalPipelineConfig(context: Context): LlvmPipelineConfig
|
||||
}
|
||||
|
||||
return LlvmPipelineConfig(
|
||||
context.llvm.targetTriple,
|
||||
context.generationState.llvm.targetTriple,
|
||||
cpuModel,
|
||||
cpuFeatures,
|
||||
optimizationLevel,
|
||||
|
||||
+1
-3
@@ -17,13 +17,11 @@ import kotlin.random.Random
|
||||
/**
|
||||
* Creates and stores terminal compiler outputs.
|
||||
*/
|
||||
class OutputFiles(outputPath: String?, target: KonanTarget, val produce: CompilerOutputKind, val producePerFileCache: Boolean) {
|
||||
class OutputFiles(val outputName: String, target: KonanTarget, val produce: CompilerOutputKind, val producePerFileCache: Boolean) {
|
||||
|
||||
private val prefix = produce.prefix(target)
|
||||
private val suffix = produce.suffix(target)
|
||||
|
||||
val outputName = outputPath?.removeSuffixIfPresent(suffix) ?: produce.visibleName
|
||||
|
||||
fun klibOutputFileName(isPacked: Boolean): String =
|
||||
if (isPacked) "$outputName$suffix" else outputName
|
||||
|
||||
|
||||
+30
-18
@@ -18,7 +18,6 @@ import org.jetbrains.kotlin.backend.konan.lower.ExpectToActualDefaultValueCopier
|
||||
import org.jetbrains.kotlin.backend.konan.lower.SamSuperTypesChecker
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport
|
||||
import org.jetbrains.kotlin.backend.konan.serialization.*
|
||||
import org.jetbrains.kotlin.builtins.FunctionInterfacePackageFragment
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
@@ -347,7 +346,6 @@ internal val umbrellaCompilation = NamedCompilerPhase(
|
||||
// Pretend we're about to create a single file cache.
|
||||
context.config.cacheSupport.libraryToCache!!.strategy =
|
||||
CacheDeserializationStrategy.SingleFile(file.path, file.fqName.asString())
|
||||
context.config.recreateOutputFiles(explicitlyProducePerFileCache = false)
|
||||
|
||||
module.files += file
|
||||
if (context.shouldDefineFunctionClasses)
|
||||
@@ -357,15 +355,6 @@ internal val umbrellaCompilation = NamedCompilerPhase(
|
||||
|
||||
module.files.clear()
|
||||
context.irModule!!.files.clear() // [dependenciesLowerPhase] puts all files to [context.irModule] for codegen.
|
||||
|
||||
context.inlineFunctionBodies.clear()
|
||||
context.classFields.clear()
|
||||
context.calledFromExportedInlineFunctions.clear()
|
||||
context.constructedFromExportedInlineFunctions.clear()
|
||||
context.localClassNames.clear()
|
||||
context.testCasesToDump.clear()
|
||||
context.mapping.loweredInlineFunctions.clear()
|
||||
context.cStubsManager = CStubsManager(context.config.target)
|
||||
}
|
||||
|
||||
module.files += files
|
||||
@@ -382,11 +371,11 @@ internal val dumpTestsPhase = makeCustomPhase<Context, IrModuleFragment>(
|
||||
if (!testDumpFile.exists)
|
||||
testDumpFile.createNew()
|
||||
|
||||
if (context.testCasesToDump.isEmpty())
|
||||
if (context.generationState.testCasesToDump.isEmpty())
|
||||
return@makeCustomPhase
|
||||
|
||||
testDumpFile.appendLines(
|
||||
context.testCasesToDump
|
||||
context.generationState.testCasesToDump
|
||||
.flatMap { (suiteClassId, functionNames) ->
|
||||
val suiteName = suiteClassId.asString()
|
||||
functionNames.asSequence().map { "$suiteName:$it" }
|
||||
@@ -418,8 +407,7 @@ internal val entryPointPhase = makeCustomPhase<Context, IrModuleFragment>(
|
||||
internal val bitcodePhase = NamedCompilerPhase(
|
||||
name = "Bitcode",
|
||||
description = "LLVM Bitcode generation",
|
||||
lower = contextLLVMSetupPhase then
|
||||
returnsInsertionPhase then
|
||||
lower = returnsInsertionPhase then
|
||||
buildDFGPhase then
|
||||
devirtualizationAnalysisPhase then
|
||||
dcePhase then
|
||||
@@ -467,10 +455,30 @@ private val backendCodegen = NamedCompilerPhase(
|
||||
bitcodePostprocessingPhase
|
||||
)
|
||||
|
||||
internal val createGenerationStatePhase = namedUnitPhase(
|
||||
name = "CreateGenerationState",
|
||||
description = "Create generation state",
|
||||
lower = object : CompilerPhase<Context, Unit, Unit> {
|
||||
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<Unit>, context: Context, input: Unit) {
|
||||
context.generationState = NativeGenerationState(context)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
internal val disposeGenerationStatePhase = namedUnitPhase(
|
||||
name = "DisposeGenerationState",
|
||||
description = "Dispose generation state",
|
||||
lower = object : CompilerPhase<Context, Unit, Unit> {
|
||||
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<Unit>, context: Context, input: Unit) {
|
||||
context.disposeGenerationState()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
private val entireBackend = NamedCompilerPhase(
|
||||
name = "EntireBackend",
|
||||
description = "Entire backend",
|
||||
lower = createLLVMImportsPhase then
|
||||
lower = createGenerationStatePhase then
|
||||
buildAdditionalCacheInfoPhase then
|
||||
takeFromContext { it.irModule!! } then
|
||||
specialBackendChecksPhase then
|
||||
@@ -478,10 +486,10 @@ private val entireBackend = NamedCompilerPhase(
|
||||
unitSink() then
|
||||
saveAdditionalCacheInfoPhase then
|
||||
produceOutputPhase then
|
||||
disposeLLVMPhase then
|
||||
objectFilesPhase then
|
||||
linkerPhase then
|
||||
finalizeCachePhase
|
||||
finalizeCachePhase then
|
||||
disposeGenerationStatePhase
|
||||
)
|
||||
|
||||
private val middleEnd = NamedCompilerPhase(
|
||||
@@ -547,6 +555,10 @@ internal fun PhaseConfig.konanPhasesConfig(config: KonanConfig) {
|
||||
disableUnless(rewriteExternalCallsCheckerGlobals, getBoolean(KonanConfigKeys.CHECK_EXTERNAL_CALLS))
|
||||
disableUnless(stringConcatenationTypeNarrowingPhase, config.optimizationsEnabled)
|
||||
disableUnless(optimizeTLSDataLoadsPhase, config.optimizationsEnabled)
|
||||
if (!config.debug && !config.lightDebug) {
|
||||
disable(generateDebugInfoHeaderPhase)
|
||||
disable(finalizeDebugInfoPhase)
|
||||
}
|
||||
if (!config.involvesLinkStage) {
|
||||
disable(bitcodePostprocessingPhase)
|
||||
disable(linkBitcodeDependenciesPhase)
|
||||
|
||||
+1
-1
@@ -423,7 +423,7 @@ internal class ClassLayoutBuilder(val irClass: IrClass, val context: Context) {
|
||||
declaredFields
|
||||
else
|
||||
declaredFields.sortedByDescending {
|
||||
with(context.llvm) { LLVMStoreSizeOfType(runtime.targetData, getLLVMType(it.type)) }
|
||||
with(context.generationState.llvm) { LLVMStoreSizeOfType(runtime.targetData, getLLVMType(it.type)) }
|
||||
}
|
||||
|
||||
val superFieldsCount = 1 /* First field is ObjHeader */ + superFields.size
|
||||
|
||||
+5
-77
@@ -6,7 +6,6 @@
|
||||
package org.jetbrains.kotlin.backend.konan.llvm
|
||||
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.common.LoggingContext
|
||||
import org.jetbrains.kotlin.backend.common.phaser.CompilerPhase
|
||||
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
|
||||
import org.jetbrains.kotlin.backend.common.phaser.PhaserState
|
||||
@@ -23,77 +22,12 @@ import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.*
|
||||
import org.jetbrains.kotlin.konan.target.Architecture
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
|
||||
internal val contextLLVMSetupPhase = makeKonanModuleOpPhase(
|
||||
name = "ContextLLVMSetup",
|
||||
description = "Set up Context for LLVM Bitcode generation",
|
||||
op = { context, _ ->
|
||||
// Note that we don't set module target explicitly.
|
||||
// It is determined by the target of runtime.bc
|
||||
// (see Llvm class in ContextUtils)
|
||||
// Which in turn is determined by the clang flags
|
||||
// used to compile runtime.bc.
|
||||
// TODO
|
||||
llvmContext = LLVMContextCreate()!!
|
||||
context.llvmDisposed = false
|
||||
|
||||
context.runtime = Runtime(context.config.distribution.compilerInterface(context.config.target))
|
||||
|
||||
val llvmModule = LLVMModuleCreateWithNameInContext("out", llvmContext)!!
|
||||
context.llvmModule = llvmModule
|
||||
context.debugInfo.builder = LLVMCreateDIBuilder(llvmModule)
|
||||
|
||||
// we don't split path to filename and directory to provide enough level uniquely for dsymutil to avoid symbol
|
||||
// clashing, which happens on linking with libraries produced from intercepting sources.
|
||||
val filePath = context.config.outputFile.toFileAndFolder(context).path()
|
||||
|
||||
context.debugInfo.compilationUnit = if (context.shouldContainLocationDebugInfo()) DICreateCompilationUnit(
|
||||
builder = context.debugInfo.builder,
|
||||
lang = DWARF.language(context.config),
|
||||
File = filePath,
|
||||
dir = "",
|
||||
producer = DWARF.producer,
|
||||
isOptimized = 0,
|
||||
flags = "",
|
||||
rv = DWARF.runtimeVersion(context.config)).cast()
|
||||
else null
|
||||
}
|
||||
)
|
||||
|
||||
internal val createLLVMDeclarationsPhase = makeKonanModuleOpPhase(
|
||||
name = "CreateLLVMDeclarations",
|
||||
description = "Map IR declarations to LLVM",
|
||||
prerequisite = setOf(contextLLVMSetupPhase),
|
||||
op = { context, _ ->
|
||||
context.llvmDeclarations = createLlvmDeclarations(context)
|
||||
context.lifetimes = mutableMapOf()
|
||||
context.codegenVisitor = CodeGeneratorVisitor(context, context.lifetimes)
|
||||
}
|
||||
)
|
||||
|
||||
internal val createLLVMImportsPhase = namedUnitPhase(
|
||||
name = "CreateLLVMImoorts",
|
||||
description = "Create LLVM imports",
|
||||
lower = object : CompilerPhase<Context, Unit, Unit> {
|
||||
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<Unit>, context: Context, input: Unit) {
|
||||
context.llvmImports = Llvm.ImportsImpl(context)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
internal val disposeLLVMPhase = namedUnitPhase(
|
||||
name = "DisposeLLVM",
|
||||
description = "Dispose LLVM",
|
||||
lower = object : CompilerPhase<Context, Unit, Unit> {
|
||||
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<Unit>, context: Context, input: Unit) {
|
||||
context.disposeLlvm()
|
||||
context.disposeRuntime()
|
||||
tryDisposeLLVMContext()
|
||||
}
|
||||
}
|
||||
op = { context, _ -> context.generationState.llvmDeclarations = createLlvmDeclarations(context) }
|
||||
)
|
||||
|
||||
internal val RTTIPhase = makeKonanModuleOpPhase(
|
||||
@@ -328,19 +262,13 @@ internal val localEscapeAnalysisPhase = makeKonanModuleOpPhase(
|
||||
internal val codegenPhase = makeKonanModuleOpPhase(
|
||||
name = "Codegen",
|
||||
description = "Code generation",
|
||||
op = { context, irModule ->
|
||||
irModule.acceptVoid(context.codegenVisitor)
|
||||
}
|
||||
op = { context, irModule -> irModule.acceptVoid(CodeGeneratorVisitor(context, context.lifetimes)) }
|
||||
)
|
||||
|
||||
internal val finalizeDebugInfoPhase = makeKonanModuleOpPhase(
|
||||
name = "FinalizeDebugInfo",
|
||||
description = "Finalize debug info",
|
||||
op = { context, _ ->
|
||||
if (context.shouldContainAnyDebugInfo()) {
|
||||
DIFinalize(context.debugInfo.builder)
|
||||
}
|
||||
}
|
||||
op = { context, _ -> DIFinalize(context.generationState.debugInfo.builder) }
|
||||
)
|
||||
|
||||
internal val cStubsPhase = makeKonanModuleOpPhase(
|
||||
@@ -374,7 +302,7 @@ internal val bitcodeOptimizationPhase = makeKonanModuleOpPhase(
|
||||
description = "Optimize bitcode",
|
||||
op = { context, _ ->
|
||||
val config = createLTOFinalPipelineConfig(context)
|
||||
LlvmOptimizationPipeline(config, context.llvmModule!!, context).use {
|
||||
LlvmOptimizationPipeline(config, context.generationState.llvm.module, context).use {
|
||||
it.run()
|
||||
}
|
||||
}
|
||||
@@ -407,7 +335,7 @@ internal val removeRedundantSafepointsPhase = makeKonanModuleOpPhase(
|
||||
description = "Remove function prologue safepoints inlined to another function",
|
||||
op = { context, _ ->
|
||||
RemoveRedundantSafepointsPass(context).runOnModule(
|
||||
module = context.llvmModule!!,
|
||||
module = context.generationState.llvm.module,
|
||||
isSafepointInliningAllowed = context.shouldInlineSafepoints()
|
||||
)
|
||||
}
|
||||
|
||||
+55
-53
@@ -54,6 +54,7 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
|
||||
fun llvmFunctionOrNull(function: IrFunction): LlvmCallable? =
|
||||
function.llvmFunctionOrNull
|
||||
|
||||
val llvmDeclarations = context.generationState.llvmDeclarations
|
||||
val intPtrType = LLVMIntPtrTypeInContext(llvmContext, llvmTargetData)!!
|
||||
internal val immOneIntPtrType = LLVMConstInt(intPtrType, 1, 1)!!
|
||||
internal val immThreeIntPtrType = LLVMConstInt(intPtrType, 3, 1)!!
|
||||
@@ -80,10 +81,10 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
|
||||
}
|
||||
|
||||
fun generateLocationInfo(locationInfo: LocationInfo): DILocationRef? = if (locationInfo.inlinedAt != null)
|
||||
LLVMCreateLocationInlinedAt(LLVMGetModuleContext(context.llvmModule), locationInfo.line, locationInfo.column,
|
||||
LLVMCreateLocationInlinedAt(LLVMGetModuleContext(llvm.module), locationInfo.line, locationInfo.column,
|
||||
locationInfo.scope, generateLocationInfo(locationInfo.inlinedAt))
|
||||
else
|
||||
LLVMCreateLocation(LLVMGetModuleContext(context.llvmModule), locationInfo.line, locationInfo.column, locationInfo.scope)
|
||||
LLVMCreateLocation(LLVMGetModuleContext(llvm.module), locationInfo.line, locationInfo.column, locationInfo.scope)
|
||||
|
||||
val objCDataGenerator = when {
|
||||
context.config.target.family.isAppleFamily -> ObjCDataGenerator(this)
|
||||
@@ -104,7 +105,7 @@ internal sealed class ExceptionHandler {
|
||||
kotlinException: LLVMValueRef
|
||||
): Unit = with(functionGenerationContext) {
|
||||
call(
|
||||
context.llvm.throwExceptionFunction,
|
||||
llvm.throwExceptionFunction,
|
||||
listOf(kotlinException),
|
||||
Lifetime.IRRELEVANT,
|
||||
this@ExceptionHandler
|
||||
@@ -201,7 +202,7 @@ internal inline fun generateFunction(
|
||||
): LLVMValueRef {
|
||||
val function = addLlvmFunctionWithDefaultAttributes(
|
||||
codegen.context,
|
||||
codegen.context.llvmModule!!,
|
||||
codegen.llvm.module,
|
||||
name,
|
||||
functionType
|
||||
)
|
||||
@@ -236,7 +237,7 @@ internal inline fun generateFunctionNoRuntime(
|
||||
): LLVMValueRef {
|
||||
val function = addLlvmFunctionWithDefaultAttributes(
|
||||
codegen.context,
|
||||
codegen.context.llvmModule!!,
|
||||
codegen.llvm.module,
|
||||
name,
|
||||
functionType
|
||||
)
|
||||
@@ -284,7 +285,7 @@ internal class StackLocalsManagerImpl(
|
||||
if (context.memoryModel == MemoryModel.EXPERIMENTAL) alloca(kObjHeaderPtr) else null
|
||||
|
||||
override fun alloc(irClass: IrClass, cleanFieldsExplicitly: Boolean): LLVMValueRef = with(functionGenerationContext) {
|
||||
val type = context.llvmDeclarations.forClass(irClass).bodyType
|
||||
val type = llvmDeclarations.forClass(irClass).bodyType
|
||||
val stackLocal = appendingTo(bbInitStackLocals) {
|
||||
val stackSlot = LLVMBuildAlloca(builder, type, "")!!
|
||||
|
||||
@@ -313,7 +314,7 @@ internal class StackLocalsManagerImpl(
|
||||
// Create new type or get already created.
|
||||
context.declaredLocalArrays.getOrPut(name) {
|
||||
val fieldTypes = listOf(kArrayHeader, LLVMArrayType(arrayToElementType[irClass.symbol]!!, count))
|
||||
val classType = LLVMStructCreateNamed(LLVMGetModuleContext(context.llvmModule), name)!!
|
||||
val classType = LLVMStructCreateNamed(LLVMGetModuleContext(llvm.module), name)!!
|
||||
LLVMStructSetBody(classType, fieldTypes.toCValues(), fieldTypes.size, 1)
|
||||
classType
|
||||
}
|
||||
@@ -367,9 +368,9 @@ internal class StackLocalsManagerImpl(
|
||||
private fun clean(stackLocal: StackLocal, refsOnly: Boolean) = with(functionGenerationContext) {
|
||||
if (stackLocal.isArray) {
|
||||
if (stackLocal.irClass.symbol == context.ir.symbols.array)
|
||||
call(context.llvm.zeroArrayRefsFunction, listOf(stackLocal.objHeaderPtr))
|
||||
call(llvm.zeroArrayRefsFunction, listOf(stackLocal.objHeaderPtr))
|
||||
} else {
|
||||
val type = context.llvmDeclarations.forClass(stackLocal.irClass).bodyType
|
||||
val type = llvmDeclarations.forClass(stackLocal.irClass).bodyType
|
||||
for (field in context.getLayoutBuilder(stackLocal.irClass).fields) {
|
||||
val fieldIndex = field.index
|
||||
val fieldType = LLVMStructGetTypeAtIndex(type, fieldIndex)!!
|
||||
@@ -379,7 +380,7 @@ internal class StackLocalsManagerImpl(
|
||||
if (refsOnly)
|
||||
storeHeapRef(kNullObjHeaderPtr, fieldPtr)
|
||||
else
|
||||
call(context.llvm.zeroHeapRefFunction, listOf(fieldPtr))
|
||||
call(llvm.zeroHeapRefFunction, listOf(fieldPtr))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -414,7 +415,7 @@ internal abstract class FunctionGenerationContextBuilder<T : FunctionGenerationC
|
||||
this(
|
||||
addLlvmFunctionWithDefaultAttributes(
|
||||
codegen.context,
|
||||
codegen.context.llvmModule!!,
|
||||
codegen.llvm.module,
|
||||
functionName,
|
||||
functionType
|
||||
),
|
||||
@@ -448,6 +449,7 @@ internal abstract class FunctionGenerationContext(
|
||||
)
|
||||
|
||||
override val context = codegen.context
|
||||
val llvmDeclarations = codegen.llvmDeclarations
|
||||
val vars = VariableManager(this)
|
||||
private val basicBlockToLastLocation = mutableMapOf<LLVMBasicBlockRef, LocationInfoRange>()
|
||||
|
||||
@@ -515,7 +517,7 @@ internal abstract class FunctionGenerationContext(
|
||||
init {
|
||||
irFunction?.let {
|
||||
if (!irFunction.isExported()) {
|
||||
if (!context.config.producePerFileCache || irFunction !in context.calledFromExportedInlineFunctions)
|
||||
if (!context.config.producePerFileCache || irFunction !in context.generationState.calledFromExportedInlineFunctions)
|
||||
LLVMSetLinkage(function, LLVMLinkage.LLVMInternalLinkage) // (Cannot do this before the function body is created)
|
||||
}
|
||||
}
|
||||
@@ -563,7 +565,7 @@ internal abstract class FunctionGenerationContext(
|
||||
val slotAddress = LLVMBuildAlloca(builder, type, name)!!
|
||||
variableLocation?.let {
|
||||
DIInsertDeclaration(
|
||||
builder = codegen.context.debugInfo.builder,
|
||||
builder = codegen.context.generationState.debugInfo.builder,
|
||||
value = slotAddress,
|
||||
localVariable = it.localVariable,
|
||||
location = it.location,
|
||||
@@ -623,19 +625,19 @@ internal abstract class FunctionGenerationContext(
|
||||
|
||||
fun freeze(value: LLVMValueRef, exceptionHandler: ExceptionHandler) {
|
||||
if (isObjectRef(value))
|
||||
call(context.llvm.freezeSubgraph, listOf(value), Lifetime.IRRELEVANT, exceptionHandler)
|
||||
call(llvm.freezeSubgraph, listOf(value), Lifetime.IRRELEVANT, exceptionHandler)
|
||||
}
|
||||
|
||||
fun checkGlobalsAccessible(exceptionHandler: ExceptionHandler) {
|
||||
if (context.memoryModel == MemoryModel.STRICT)
|
||||
call(context.llvm.checkGlobalsAccessible, emptyList(), Lifetime.IRRELEVANT, exceptionHandler)
|
||||
call(llvm.checkGlobalsAccessible, emptyList(), Lifetime.IRRELEVANT, exceptionHandler)
|
||||
}
|
||||
|
||||
private fun updateReturnRef(value: LLVMValueRef, address: LLVMValueRef) {
|
||||
if (context.memoryModel == MemoryModel.STRICT)
|
||||
store(value, address)
|
||||
else
|
||||
call(context.llvm.updateReturnRefFunction, listOf(address, value))
|
||||
call(llvm.updateReturnRefFunction, listOf(address, value))
|
||||
}
|
||||
|
||||
private fun updateRef(value: LLVMValueRef, address: LLVMValueRef, onStack: Boolean) {
|
||||
@@ -643,9 +645,9 @@ internal abstract class FunctionGenerationContext(
|
||||
if (context.memoryModel == MemoryModel.STRICT)
|
||||
store(value, address)
|
||||
else
|
||||
call(context.llvm.updateStackRefFunction, listOf(address, value))
|
||||
call(llvm.updateStackRefFunction, listOf(address, value))
|
||||
} else {
|
||||
call(context.llvm.updateHeapRefFunction, listOf(address, value))
|
||||
call(llvm.updateHeapRefFunction, listOf(address, value))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -659,8 +661,8 @@ internal abstract class FunctionGenerationContext(
|
||||
"Attempt to switch the thread state when runtime is forbidden"
|
||||
}
|
||||
when (state) {
|
||||
Native -> call(context.llvm.Kotlin_mm_switchThreadStateNative, emptyList())
|
||||
Runnable -> call(context.llvm.Kotlin_mm_switchThreadStateRunnable, emptyList())
|
||||
Native -> call(llvm.Kotlin_mm_switchThreadStateNative, emptyList())
|
||||
Runnable -> call(llvm.Kotlin_mm_switchThreadStateRunnable, emptyList())
|
||||
}.let {} // Force exhaustive.
|
||||
}
|
||||
|
||||
@@ -671,7 +673,7 @@ internal abstract class FunctionGenerationContext(
|
||||
}
|
||||
|
||||
fun memset(pointer: LLVMValueRef, value: Byte, size: Int, isVolatile: Boolean = false) =
|
||||
call(context.llvm.memsetFunction,
|
||||
call(llvm.memsetFunction,
|
||||
listOf(pointer,
|
||||
Int8(value).llvm,
|
||||
Int32(size).llvm,
|
||||
@@ -784,7 +786,7 @@ internal abstract class FunctionGenerationContext(
|
||||
}
|
||||
|
||||
fun allocInstance(typeInfo: LLVMValueRef, lifetime: Lifetime, resultSlot: LLVMValueRef?): LLVMValueRef =
|
||||
call(context.llvm.allocInstanceFunction, listOf(typeInfo), lifetime, resultSlot = resultSlot)
|
||||
call(llvm.allocInstanceFunction, listOf(typeInfo), lifetime, resultSlot = resultSlot)
|
||||
|
||||
fun allocInstance(irClass: IrClass, lifetime: Lifetime, stackLocalsManager: StackLocalsManager, resultSlot: LLVMValueRef?) =
|
||||
if (lifetime == Lifetime.STACK)
|
||||
@@ -806,13 +808,13 @@ internal abstract class FunctionGenerationContext(
|
||||
return if (lifetime == Lifetime.STACK) {
|
||||
stackLocalsManager.allocArray(irClass, count)
|
||||
} else {
|
||||
call(context.llvm.allocArrayFunction, listOf(typeInfo, count), lifetime, exceptionHandler, resultSlot = resultSlot)
|
||||
call(llvm.allocArrayFunction, listOf(typeInfo, count), lifetime, exceptionHandler, resultSlot = resultSlot)
|
||||
}
|
||||
}
|
||||
|
||||
fun unreachable(): LLVMValueRef? {
|
||||
if (context.config.debug) {
|
||||
call(context.llvm.llvmTrap, emptyList())
|
||||
call(llvm.llvmTrap, emptyList())
|
||||
}
|
||||
val res = LLVMBuildUnreachable(builder)
|
||||
currentPositionHolder.setAfterTerminator()
|
||||
@@ -913,7 +915,7 @@ internal abstract class FunctionGenerationContext(
|
||||
LLVMBuildExtractValue(builder, aggregate, index, name)!!
|
||||
|
||||
fun gxxLandingpad(numClauses: Int, name: String = "", switchThreadState: Boolean = false): LLVMValueRef {
|
||||
val personalityFunction = context.llvm.gxxPersonalityFunction.llvmValue
|
||||
val personalityFunction = llvm.gxxPersonalityFunction.llvmValue
|
||||
|
||||
// Type of `landingpad` instruction result (depends on personality function):
|
||||
val landingpadType = structType(int8TypePtr, int32Type)
|
||||
@@ -923,7 +925,7 @@ internal abstract class FunctionGenerationContext(
|
||||
if (switchThreadState) {
|
||||
switchThreadState(Runnable)
|
||||
}
|
||||
call(context.llvm.setCurrentFrameFunction, listOf(slotsPhi!!))
|
||||
call(llvm.setCurrentFrameFunction, listOf(slotsPhi!!))
|
||||
setCurrentFrameIsCalled = true
|
||||
|
||||
return landingpad
|
||||
@@ -957,7 +959,7 @@ internal abstract class FunctionGenerationContext(
|
||||
val typeId = extractValue(landingpad, 1)
|
||||
val isKotlinException = icmpEq(
|
||||
typeId,
|
||||
call(context.llvm.llvmEhTypeidFor, listOf(kotlinExceptionRtti.llvm))
|
||||
call(llvm.llvmEhTypeidFor, listOf(kotlinExceptionRtti.llvm))
|
||||
)
|
||||
|
||||
if (wrapExceptionMode) {
|
||||
@@ -968,7 +970,7 @@ internal abstract class FunctionGenerationContext(
|
||||
appendingTo(foreignExceptionBlock) {
|
||||
val isObjCException = icmpEq(
|
||||
typeId,
|
||||
call(context.llvm.llvmEhTypeidFor, listOf(objcNSExceptionRtti.llvm))
|
||||
call(llvm.llvmEhTypeidFor, listOf(objcNSExceptionRtti.llvm))
|
||||
)
|
||||
condBr(isObjCException, forwardNativeExceptionBlock, fatalForeignExceptionBlock)
|
||||
|
||||
@@ -1001,12 +1003,12 @@ internal abstract class FunctionGenerationContext(
|
||||
fun terminateWithCurrentException(landingpad: LLVMValueRef) {
|
||||
val exceptionRecord = extractValue(landingpad, 0)
|
||||
// So `std::terminate` is called from C++ catch block:
|
||||
call(context.llvm.cxaBeginCatchFunction, listOf(exceptionRecord))
|
||||
call(llvm.cxaBeginCatchFunction, listOf(exceptionRecord))
|
||||
terminate()
|
||||
}
|
||||
|
||||
fun terminate() {
|
||||
call(context.llvm.cxxStdTerminate, emptyList())
|
||||
call(llvm.cxxStdTerminate, emptyList())
|
||||
|
||||
// Note: unreachable instruction to be generated here, but debug information is improper in this case.
|
||||
val loopBlock = basicBlock("loop", position()?.start)
|
||||
@@ -1044,14 +1046,14 @@ internal abstract class FunctionGenerationContext(
|
||||
val exceptionRecord = extractValue(landingpadResult, 0, "er")
|
||||
|
||||
// __cxa_begin_catch returns pointer to C++ exception object.
|
||||
val beginCatch = context.llvm.cxaBeginCatchFunction
|
||||
val beginCatch = llvm.cxaBeginCatchFunction
|
||||
val exceptionRawPtr = call(beginCatch, listOf(exceptionRecord))
|
||||
|
||||
// Pointer to Kotlin exception object:
|
||||
val exceptionPtr = call(context.llvm.Kotlin_getExceptionObject, listOf(exceptionRawPtr), Lifetime.GLOBAL)
|
||||
val exceptionPtr = call(llvm.Kotlin_getExceptionObject, listOf(exceptionRawPtr), Lifetime.GLOBAL)
|
||||
|
||||
// __cxa_end_catch performs some C++ cleanup, including calling `ExceptionObjHolder` class destructor.
|
||||
val endCatch = context.llvm.cxaEndCatchFunction
|
||||
val endCatch = llvm.cxaEndCatchFunction
|
||||
call(endCatch, listOf())
|
||||
|
||||
return exceptionPtr
|
||||
@@ -1061,20 +1063,20 @@ internal abstract class FunctionGenerationContext(
|
||||
val exceptionRecord = extractValue(landingpadResult, 0, "er")
|
||||
|
||||
// __cxa_begin_catch returns pointer to C++ exception object.
|
||||
val exceptionRawPtr = call(context.llvm.cxaBeginCatchFunction, listOf(exceptionRecord))
|
||||
val exceptionRawPtr = call(llvm.cxaBeginCatchFunction, listOf(exceptionRecord))
|
||||
|
||||
// This will take care of ARC - need to be done in the catching scope, i.e. before __cxa_end_catch
|
||||
val exception = call(context.ir.symbols.createForeignException.owner.llvmFunction,
|
||||
listOf(exceptionRawPtr),
|
||||
Lifetime.GLOBAL, exceptionHandler)
|
||||
|
||||
call(context.llvm.cxaEndCatchFunction, listOf())
|
||||
call(llvm.cxaEndCatchFunction, listOf())
|
||||
return exception
|
||||
}
|
||||
|
||||
fun generateFrameCheck() {
|
||||
if (!context.shouldOptimize())
|
||||
call(context.llvm.checkCurrentFrameFunction, listOf(slotsPhi!!))
|
||||
call(llvm.checkCurrentFrameFunction, listOf(slotsPhi!!))
|
||||
}
|
||||
|
||||
inline fun ifThenElse(
|
||||
@@ -1196,7 +1198,7 @@ internal abstract class FunctionGenerationContext(
|
||||
}
|
||||
appendingTo(slowPathBB) {
|
||||
val actualInterfaceTableSize = sub(kImmInt32Zero, interfaceTableSize) // -interfaceTableSize
|
||||
val slowValue = call(context.llvm.lookupInterfaceTableRecord,
|
||||
val slowValue = call(llvm.lookupInterfaceTableRecord,
|
||||
listOf(interfaceTable, actualInterfaceTableSize, Int32(interfaceId).llvm))
|
||||
br(takeResBB)
|
||||
addPhiIncoming(resultPhi, currentBlock to slowValue)
|
||||
@@ -1209,7 +1211,7 @@ internal abstract class FunctionGenerationContext(
|
||||
assert(LLVMTypeOf(receiver) == codegen.kObjHeaderPtr)
|
||||
|
||||
val typeInfoPtr: LLVMValueRef = if (irFunction.getObjCMethodInfo() != null)
|
||||
call(context.llvm.getObjCKotlinTypeInfo, listOf(receiver))
|
||||
call(llvm.getObjCKotlinTypeInfo, listOf(receiver))
|
||||
else
|
||||
loadTypeInfo(receiver)
|
||||
|
||||
@@ -1286,10 +1288,10 @@ internal abstract class FunctionGenerationContext(
|
||||
// If thread local object is imported - access it via getter function.
|
||||
ObjectStorageKind.THREAD_LOCAL -> {
|
||||
val valueGetterName = irClass.threadLocalObjectStorageGetterSymbolName
|
||||
val valueGetterFunction = LLVMGetNamedFunction(context.llvmModule, valueGetterName)
|
||||
val valueGetterFunction = LLVMGetNamedFunction(llvm.module, valueGetterName)
|
||||
?: addLlvmFunctionWithDefaultAttributes(
|
||||
context,
|
||||
context.llvmModule!!,
|
||||
llvm.module,
|
||||
valueGetterName,
|
||||
functionType(kObjHeaderPtrPtr, false)
|
||||
)
|
||||
@@ -1311,7 +1313,7 @@ internal abstract class FunctionGenerationContext(
|
||||
}
|
||||
} else {
|
||||
// Local globals and thread locals storage info is stored in our map.
|
||||
val singleton = context.llvmDeclarations.forSingleton(irClass)
|
||||
val singleton = llvmDeclarations.forSingleton(irClass)
|
||||
val instanceAddress = singleton.instanceStorage
|
||||
instanceAddress.getAddress(this)
|
||||
}
|
||||
@@ -1319,14 +1321,14 @@ internal abstract class FunctionGenerationContext(
|
||||
when (storageKind) {
|
||||
ObjectStorageKind.SHARED ->
|
||||
// If current file used a shared object, make file's (de)initializer function deinit it.
|
||||
context.llvm.globalSharedObjects += objectPtr
|
||||
llvm.globalSharedObjects += objectPtr
|
||||
ObjectStorageKind.THREAD_LOCAL ->
|
||||
// If current file used locally defined TLS objects, make file's (de)initializer function
|
||||
// init and deinit TLS.
|
||||
// Note: for exported TLS objects a getter is generated in a file they're defined in. Which
|
||||
// adds TLS init and deinit to that file's (de)initializer function.
|
||||
if (!isExternal(irClass))
|
||||
context.llvm.fileUsesThreadLocalObjects = true
|
||||
llvm.fileUsesThreadLocalObjects = true
|
||||
ObjectStorageKind.PERMANENT -> { /* Do nothing, no need to free such an instance. */ }
|
||||
}
|
||||
|
||||
@@ -1346,9 +1348,9 @@ internal abstract class FunctionGenerationContext(
|
||||
val ctor = codegen.llvmFunction(defaultConstructor).llvmValue
|
||||
val initFunction =
|
||||
if (storageKind == ObjectStorageKind.SHARED && context.config.threadsAreAllowed) {
|
||||
context.llvm.initSingletonFunction
|
||||
llvm.initSingletonFunction
|
||||
} else {
|
||||
context.llvm.initThreadLocalSingleton
|
||||
llvm.initThreadLocalSingleton
|
||||
}
|
||||
val args = listOf(objectPtr, typeInfo, ctor)
|
||||
val newValue = call(initFunction, args, Lifetime.GLOBAL, exceptionHandler, resultSlot = resultSlot)
|
||||
@@ -1387,7 +1389,7 @@ internal abstract class FunctionGenerationContext(
|
||||
val name = irClass.descriptor.getExternalObjCMetaClassBinaryName()
|
||||
val objCClass = getObjCClass(name, llvmSymbolOrigin)
|
||||
|
||||
val getClass = context.llvm.externalFunction(LlvmFunctionProto(
|
||||
val getClass = llvm.externalFunction(LlvmFunctionProto(
|
||||
"object_getClass",
|
||||
LlvmRetType(int8TypePtr),
|
||||
listOf(LlvmParamType(int8TypePtr)),
|
||||
@@ -1411,7 +1413,7 @@ internal abstract class FunctionGenerationContext(
|
||||
|
||||
return this.ifThenElse(storedClassIsNotNull, storedClass) {
|
||||
call(
|
||||
context.llvm.createKotlinObjCClass,
|
||||
llvm.createKotlinObjCClass,
|
||||
listOf(classInfo),
|
||||
exceptionHandler = exceptionHandler
|
||||
)
|
||||
@@ -1420,7 +1422,7 @@ internal abstract class FunctionGenerationContext(
|
||||
}
|
||||
|
||||
fun getObjCClass(binaryName: String, llvmSymbolOrigin: CompiledKlibModuleOrigin): LLVMValueRef {
|
||||
context.llvm.imports.add(llvmSymbolOrigin)
|
||||
llvm.imports.add(llvmSymbolOrigin)
|
||||
return load(codegen.objCDataGenerator!!.genClassRef(binaryName).llvm)
|
||||
}
|
||||
|
||||
@@ -1470,7 +1472,7 @@ internal abstract class FunctionGenerationContext(
|
||||
val expr = longArrayOf(DwarfOp.DW_OP_plus_uconst.value,
|
||||
runtime.pointerSize * slot.toLong()).toCValues()
|
||||
DIInsertDeclaration(
|
||||
builder = codegen.context.debugInfo.builder,
|
||||
builder = codegen.context.generationState.debugInfo.builder,
|
||||
value = slots,
|
||||
localVariable = variable.localVariable,
|
||||
location = variable.location,
|
||||
@@ -1506,18 +1508,18 @@ internal abstract class FunctionGenerationContext(
|
||||
startLocation?.let { debugLocation(it, it) }
|
||||
if (needsRuntimeInit || switchToRunnable) {
|
||||
check(!forbidRuntime) { "Attempt to init runtime where runtime usage is forbidden" }
|
||||
call(context.llvm.initRuntimeIfNeeded, emptyList())
|
||||
call(llvm.initRuntimeIfNeeded, emptyList())
|
||||
}
|
||||
if (switchToRunnable) {
|
||||
switchThreadState(Runnable)
|
||||
}
|
||||
if (needSlots || needCleanupLandingpadAndLeaveFrame) {
|
||||
call(context.llvm.enterFrameFunction, listOf(slotsPhi!!, Int32(vars.skipSlots).llvm, Int32(slotCount).llvm))
|
||||
call(llvm.enterFrameFunction, listOf(slotsPhi!!, Int32(vars.skipSlots).llvm, Int32(slotCount).llvm))
|
||||
} else {
|
||||
check(!setCurrentFrameIsCalled)
|
||||
}
|
||||
if (context.memoryModel == MemoryModel.EXPERIMENTAL && !forbidRuntime) {
|
||||
call(context.llvm.Kotlin_mm_safePointFunctionPrologue, emptyList())
|
||||
call(llvm.Kotlin_mm_safePointFunctionPrologue, emptyList())
|
||||
}
|
||||
resetDebugLocation()
|
||||
br(entryBb)
|
||||
@@ -1711,7 +1713,7 @@ internal abstract class FunctionGenerationContext(
|
||||
private fun releaseVars() {
|
||||
if (needCleanupLandingpadAndLeaveFrame || needSlots) {
|
||||
check(!forbidRuntime) { "Attempt to leave a frame where runtime usage is forbidden" }
|
||||
call(context.llvm.leaveFrameFunction,
|
||||
call(llvm.leaveFrameFunction,
|
||||
listOf(slotsPhi!!, Int32(vars.skipSlots).llvm, Int32(slotCount).llvm))
|
||||
}
|
||||
if (!stackLocalsManager.isEmpty() && context.memoryModel != MemoryModel.EXPERIMENTAL) {
|
||||
|
||||
+23
-23
@@ -7,17 +7,14 @@ package org.jetbrains.kotlin.backend.konan.llvm
|
||||
|
||||
import kotlinx.cinterop.toKString
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.MangleConstant
|
||||
import org.jetbrains.kotlin.backend.konan.*
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.library.resolver.TopologicalLibraryOrder
|
||||
import org.jetbrains.kotlin.backend.konan.ir.llvmSymbolOrigin
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.KonanBinaryInterface.functionName
|
||||
import org.jetbrains.kotlin.descriptors.konan.CompiledKlibModuleOrigin
|
||||
import org.jetbrains.kotlin.descriptors.konan.CurrentKlibModuleOrigin
|
||||
import org.jetbrains.kotlin.descriptors.konan.DeserializedKlibModuleOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyFunction
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibrary
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
@@ -143,7 +140,7 @@ internal interface ContextUtils : RuntimeAware {
|
||||
val context: Context
|
||||
|
||||
override val runtime: Runtime
|
||||
get() = context.llvm.runtime
|
||||
get() = context.generationState.llvm.runtime
|
||||
|
||||
val argumentAbiInfo: TargetAbiInfo
|
||||
get() = context.targetAbiInfo
|
||||
@@ -156,8 +153,11 @@ internal interface ContextUtils : RuntimeAware {
|
||||
val llvmTargetData: LLVMTargetDataRef
|
||||
get() = runtime.targetData
|
||||
|
||||
val llvm: Llvm
|
||||
get() = context.generationState.llvm
|
||||
|
||||
val staticData: KotlinStaticData
|
||||
get() = context.llvm.staticData
|
||||
get() = context.generationState.llvm.staticData
|
||||
|
||||
/**
|
||||
* TODO: maybe it'd be better to replace with [IrDeclaration::isEffectivelyExternal()],
|
||||
@@ -190,10 +190,10 @@ internal interface ContextUtils : RuntimeAware {
|
||||
this.computePrivateSymbolName(containerName)
|
||||
}
|
||||
val proto = LlvmFunctionProto(this, symbolName, this@ContextUtils)
|
||||
context.llvm.externalFunction(proto)
|
||||
llvm.externalFunction(proto)
|
||||
}
|
||||
} else {
|
||||
context.llvmDeclarations.forFunctionOrNull(this)
|
||||
context.generationState.llvmDeclarations.forFunctionOrNull(this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ internal interface ContextUtils : RuntimeAware {
|
||||
constPointer(importGlobal(typeInfoSymbolName, runtime.typeInfoType,
|
||||
origin = this.llvmSymbolOrigin))
|
||||
} else {
|
||||
context.llvmDeclarations.forClass(this).typeInfo
|
||||
context.generationState.llvmDeclarations.forClass(this).typeInfo
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,10 +271,10 @@ internal class InitializersGenerationState {
|
||||
&& moduleGlobalInitializers.isEmpty() && moduleThreadLocalInitializers.isEmpty()
|
||||
}
|
||||
|
||||
internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) : RuntimeAware {
|
||||
internal class Llvm(val context: Context, val module: LLVMModuleRef) : RuntimeAware {
|
||||
|
||||
private fun importFunction(name: String, otherModule: LLVMModuleRef): LlvmCallable {
|
||||
if (LLVMGetNamedFunction(llvmModule, name) != null) {
|
||||
if (LLVMGetNamedFunction(module, name) != null) {
|
||||
throw IllegalArgumentException("function $name already exists")
|
||||
}
|
||||
|
||||
@@ -283,7 +283,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) : Runti
|
||||
val attributesCopier = LlvmFunctionAttributeProvider.copyFromExternal(externalFunction)
|
||||
|
||||
val functionType = getFunctionType(externalFunction)
|
||||
val function = LLVMAddFunction(llvmModule, name, functionType)!!
|
||||
val function = LLVMAddFunction(module, name, functionType)!!
|
||||
|
||||
attributesCopier.addFunctionAttributes(function)
|
||||
|
||||
@@ -291,13 +291,13 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) : Runti
|
||||
}
|
||||
|
||||
private fun importGlobal(name: String, otherModule: LLVMModuleRef): LLVMValueRef {
|
||||
if (LLVMGetNamedGlobal(llvmModule, name) != null) {
|
||||
if (LLVMGetNamedGlobal(module, name) != null) {
|
||||
throw IllegalArgumentException("global $name already exists")
|
||||
}
|
||||
|
||||
val externalGlobal = LLVMGetNamedGlobal(otherModule, name)!!
|
||||
val globalType = getGlobalType(externalGlobal)
|
||||
val global = LLVMAddGlobal(llvmModule, globalType, name)!!
|
||||
val global = LLVMAddGlobal(module, globalType, name)!!
|
||||
|
||||
return global
|
||||
}
|
||||
@@ -308,7 +308,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) : Runti
|
||||
}
|
||||
|
||||
private fun llvmIntrinsic(name: String, type: LLVMTypeRef, vararg attributes: String): LlvmCallable {
|
||||
val result = LLVMAddFunction(llvmModule, name, type)!!
|
||||
val result = LLVMAddFunction(module, name, type)!!
|
||||
attributes.forEach {
|
||||
val kindId = getLlvmAttributeKindId(it)
|
||||
addLlvmFunctionEnumAttribute(result, kindId)
|
||||
@@ -318,7 +318,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) : Runti
|
||||
|
||||
internal fun externalFunction(llvmFunctionProto: LlvmFunctionProto): LlvmCallable {
|
||||
this.imports.add(llvmFunctionProto.origin, onlyBitcode = llvmFunctionProto.independent)
|
||||
val found = LLVMGetNamedFunction(llvmModule, llvmFunctionProto.name)
|
||||
val found = LLVMGetNamedFunction(module, llvmFunctionProto.name)
|
||||
if (found != null) {
|
||||
assert(getFunctionType(found) == llvmFunctionProto.llvmFunctionType) {
|
||||
"Expected: ${LLVMPrintTypeToString(llvmFunctionProto.llvmFunctionType)!!.toKString()} " +
|
||||
@@ -327,13 +327,13 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) : Runti
|
||||
assert(LLVMGetLinkage(found) == LLVMLinkage.LLVMExternalLinkage)
|
||||
return LlvmCallable(found, llvmFunctionProto)
|
||||
} else {
|
||||
val function = addLlvmFunctionWithDefaultAttributes(context, llvmModule, llvmFunctionProto.name, llvmFunctionProto.llvmFunctionType)
|
||||
val function = addLlvmFunctionWithDefaultAttributes(context, module, llvmFunctionProto.name, llvmFunctionProto.llvmFunctionType)
|
||||
llvmFunctionProto.addFunctionAttributes(function)
|
||||
return LlvmCallable(function, llvmFunctionProto)
|
||||
}
|
||||
}
|
||||
|
||||
val imports get() = context.llvmImports
|
||||
val imports get() = context.generationState.llvmImports
|
||||
|
||||
class ImportsImpl(private val context: Context) : LlvmImports {
|
||||
|
||||
@@ -440,17 +440,17 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) : Runti
|
||||
|
||||
val additionalProducedBitcodeFiles = mutableListOf<String>()
|
||||
|
||||
val staticData = KotlinStaticData(context)
|
||||
val staticData = KotlinStaticData(context, module)
|
||||
|
||||
private val target = context.config.target
|
||||
|
||||
override val runtime get() = context.runtime
|
||||
override val runtime get() = context.generationState.runtime
|
||||
|
||||
val targetTriple = runtime.target
|
||||
|
||||
init {
|
||||
LLVMSetDataLayout(llvmModule, runtime.dataLayout)
|
||||
LLVMSetTarget(llvmModule, targetTriple)
|
||||
LLVMSetDataLayout(module, runtime.dataLayout)
|
||||
LLVMSetTarget(module, targetTriple)
|
||||
}
|
||||
|
||||
private fun importRtFunction(name: String) = importFunction(name, runtime.llvmModule)
|
||||
@@ -533,7 +533,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) : Runti
|
||||
var tlsCount = 0
|
||||
|
||||
val tlsKey by lazy {
|
||||
val global = LLVMAddGlobal(llvmModule, kInt8Ptr, "__KonanTlsKey")!!
|
||||
val global = LLVMAddGlobal(module, kInt8Ptr, "__KonanTlsKey")!!
|
||||
LLVMSetLinkage(global, LLVMLinkage.LLVMInternalLinkage)
|
||||
LLVMSetInitializer(global, LLVMConstNull(kInt8Ptr))
|
||||
global
|
||||
@@ -601,7 +601,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) : Runti
|
||||
val boxCacheGlobals = mutableMapOf<BoxCache, StaticData.Global>()
|
||||
|
||||
val runtimeAnnotationMap by lazy {
|
||||
context.llvm.staticData.getGlobal("llvm.global.annotations")
|
||||
staticData.getGlobal("llvm.global.annotations")
|
||||
?.getInitializer()
|
||||
?.let { getOperands(it) }
|
||||
?.groupBy(
|
||||
|
||||
+83
-82
@@ -72,14 +72,14 @@ internal class DebugInfo internal constructor(override val context: Context):Con
|
||||
var types = mutableMapOf<IrType, DITypeOpaqueRef>()
|
||||
|
||||
val llvmTypes = mapOf<IrType, LLVMTypeRef>(
|
||||
context.irBuiltIns.booleanType to context.llvm.llvmInt8,
|
||||
context.irBuiltIns.byteType to context.llvm.llvmInt8,
|
||||
context.irBuiltIns.charType to context.llvm.llvmInt16,
|
||||
context.irBuiltIns.shortType to context.llvm.llvmInt16,
|
||||
context.irBuiltIns.intType to context.llvm.llvmInt32,
|
||||
context.irBuiltIns.longType to context.llvm.llvmInt64,
|
||||
context.irBuiltIns.floatType to context.llvm.llvmFloat,
|
||||
context.irBuiltIns.doubleType to context.llvm.llvmDouble)
|
||||
context.irBuiltIns.booleanType to llvm.llvmInt8,
|
||||
context.irBuiltIns.byteType to llvm.llvmInt8,
|
||||
context.irBuiltIns.charType to llvm.llvmInt16,
|
||||
context.irBuiltIns.shortType to llvm.llvmInt16,
|
||||
context.irBuiltIns.intType to llvm.llvmInt32,
|
||||
context.irBuiltIns.longType to llvm.llvmInt64,
|
||||
context.irBuiltIns.floatType to llvm.llvmFloat,
|
||||
context.irBuiltIns.doubleType to llvm.llvmDouble)
|
||||
val llvmTypeSizes = llvmTypes.map { it.key to LLVMSizeOfTypeInBits(llvmTargetData, it.value) }.toMap()
|
||||
val llvmTypeAlignments = llvmTypes.map {it.key to LLVMPreferredAlignmentOfType(llvmTargetData, it.value)}.toMap()
|
||||
val otherLlvmType = LLVMPointerType(int64Type, 0)!!
|
||||
@@ -132,59 +132,58 @@ internal fun String?.toFileAndFolder(context: Context):FileAndFolder {
|
||||
}
|
||||
|
||||
internal fun generateDebugInfoHeader(context: Context) {
|
||||
if (context.shouldContainAnyDebugInfo()) {
|
||||
val path = context.config.outputFile
|
||||
.toFileAndFolder(context)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
context.debugInfo.module = DICreateModule(
|
||||
builder = context.debugInfo.builder,
|
||||
scope = null,
|
||||
name = path.path(),
|
||||
configurationMacro = "",
|
||||
includePath = "",
|
||||
iSysRoot = "")
|
||||
/* TODO: figure out what here 2 means:
|
||||
*
|
||||
* 0:b-backend-dwarf:minamoto@minamoto-osx(0)# cat /dev/null | clang -xc -S -emit-llvm -g -o - -
|
||||
* ; ModuleID = '-'
|
||||
* source_filename = "-"
|
||||
* target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
||||
* target triple = "x86_64-apple-macosx10.12.0"
|
||||
*
|
||||
* !llvm.dbg.cu = !{!0}
|
||||
* !llvm.module.flags = !{!3, !4, !5}
|
||||
* !llvm.ident = !{!6}
|
||||
*
|
||||
* !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "Apple LLVM version 8.0.0 (clang-800.0.38)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
|
||||
* !1 = !DIFile(filename: "-", directory: "/Users/minamoto/ws/.git-trees/backend-dwarf")
|
||||
* !2 = !{}
|
||||
* !3 = !{i32 2, !"Dwarf Version", i32 2} ; <-
|
||||
* !4 = !{i32 2, !"Debug Info Version", i32 700000003} ; <-
|
||||
* !5 = !{i32 1, !"PIC Level", i32 2}
|
||||
* !6 = !{!"Apple LLVM version 8.0.0 (clang-800.0.38)"}
|
||||
*/
|
||||
val llvmTwo = Int32(2).llvm
|
||||
val dwarfVersion = node(llvmTwo, DWARF.dwarfVersionMetaDataNodeName, Int32(DWARF.dwarfVersion(context.config)).llvm)
|
||||
val nodeDebugInfoVersion = node(llvmTwo, DWARF.dwarfDebugInfoMetaDataNodeName, Int32(DWARF.debugInfoVersion).llvm)
|
||||
val llvmModuleFlags = "llvm.module.flags"
|
||||
LLVMAddNamedMetadataOperand(context.llvmModule, llvmModuleFlags, dwarfVersion)
|
||||
LLVMAddNamedMetadataOperand(context.llvmModule, llvmModuleFlags, nodeDebugInfoVersion)
|
||||
val objHeaderType = DICreateStructType(
|
||||
refBuilder = context.debugInfo.builder,
|
||||
// TODO: here should be DIFile as scope.
|
||||
scope = null,
|
||||
name = "ObjHeader",
|
||||
file = null,
|
||||
lineNumber = 0,
|
||||
sizeInBits = 0,
|
||||
alignInBits = 0,
|
||||
flags = DWARF.flagsForwardDeclaration,
|
||||
derivedFrom = null,
|
||||
elements = null,
|
||||
elementsCount = 0,
|
||||
refPlace = null).cast<DITypeOpaqueRef>()
|
||||
context.debugInfo.objHeaderPointerType = dwarfPointerType(context, objHeaderType)
|
||||
}
|
||||
val debugInfo = context.generationState.debugInfo
|
||||
val module = context.generationState.llvm.module
|
||||
val path = context.generationState.outputFile.toFileAndFolder(context)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
debugInfo.module = DICreateModule(
|
||||
builder = debugInfo.builder,
|
||||
scope = null,
|
||||
name = path.path(),
|
||||
configurationMacro = "",
|
||||
includePath = "",
|
||||
iSysRoot = "")
|
||||
/* TODO: figure out what here 2 means:
|
||||
*
|
||||
* 0:b-backend-dwarf:minamoto@minamoto-osx(0)# cat /dev/null | clang -xc -S -emit-llvm -g -o - -
|
||||
* ; ModuleID = '-'
|
||||
* source_filename = "-"
|
||||
* target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
||||
* target triple = "x86_64-apple-macosx10.12.0"
|
||||
*
|
||||
* !llvm.dbg.cu = !{!0}
|
||||
* !llvm.module.flags = !{!3, !4, !5}
|
||||
* !llvm.ident = !{!6}
|
||||
*
|
||||
* !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "Apple LLVM version 8.0.0 (clang-800.0.38)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
|
||||
* !1 = !DIFile(filename: "-", directory: "/Users/minamoto/ws/.git-trees/backend-dwarf")
|
||||
* !2 = !{}
|
||||
* !3 = !{i32 2, !"Dwarf Version", i32 2} ; <-
|
||||
* !4 = !{i32 2, !"Debug Info Version", i32 700000003} ; <-
|
||||
* !5 = !{i32 1, !"PIC Level", i32 2}
|
||||
* !6 = !{!"Apple LLVM version 8.0.0 (clang-800.0.38)"}
|
||||
*/
|
||||
val llvmTwo = Int32(2).llvm
|
||||
val dwarfVersion = node(llvmTwo, DWARF.dwarfVersionMetaDataNodeName, Int32(DWARF.dwarfVersion(context.config)).llvm)
|
||||
val nodeDebugInfoVersion = node(llvmTwo, DWARF.dwarfDebugInfoMetaDataNodeName, Int32(DWARF.debugInfoVersion).llvm)
|
||||
val llvmModuleFlags = "llvm.module.flags"
|
||||
LLVMAddNamedMetadataOperand(module, llvmModuleFlags, dwarfVersion)
|
||||
LLVMAddNamedMetadataOperand(module, llvmModuleFlags, nodeDebugInfoVersion)
|
||||
val objHeaderType = DICreateStructType(
|
||||
refBuilder = debugInfo.builder,
|
||||
// TODO: here should be DIFile as scope.
|
||||
scope = null,
|
||||
name = "ObjHeader",
|
||||
file = null,
|
||||
lineNumber = 0,
|
||||
sizeInBits = 0,
|
||||
alignInBits = 0,
|
||||
flags = DWARF.flagsForwardDeclaration,
|
||||
derivedFrom = null,
|
||||
elements = null,
|
||||
elementsCount = 0,
|
||||
refPlace = null).cast<DITypeOpaqueRef>()
|
||||
debugInfo.objHeaderPointerType = dwarfPointerType(context, objHeaderType)
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@@ -193,7 +192,7 @@ internal fun IrType.dwarfType(context: Context, targetData: LLVMTargetDataRef):
|
||||
this.computePrimitiveBinaryTypeOrNull() != null -> return debugInfoBaseType(context, targetData, this.render(), llvmType(context), encoding().value.toInt())
|
||||
else -> {
|
||||
return when {
|
||||
classOrNull != null || this.isTypeParameter() -> context.debugInfo.objHeaderPointerType!!
|
||||
classOrNull != null || this.isTypeParameter() -> context.generationState.debugInfo.objHeaderPointerType!!
|
||||
else -> TODO("$this: Does this case really exist?")
|
||||
}
|
||||
}
|
||||
@@ -201,13 +200,13 @@ internal fun IrType.dwarfType(context: Context, targetData: LLVMTargetDataRef):
|
||||
}
|
||||
|
||||
internal fun IrType.diType(context: Context, llvmTargetData: LLVMTargetDataRef): DITypeOpaqueRef =
|
||||
context.debugInfo.types.getOrPut(this) {
|
||||
context.generationState.debugInfo.types.getOrPut(this) {
|
||||
dwarfType(context, llvmTargetData)
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun debugInfoBaseType(context:Context, targetData:LLVMTargetDataRef, typeName:String, type:LLVMTypeRef, encoding:Int) = DICreateBasicType(
|
||||
context.debugInfo.builder, typeName,
|
||||
context.generationState.debugInfo.builder, typeName,
|
||||
LLVMSizeOfTypeInBits(targetData, type),
|
||||
LLVMPreferredAlignmentOfType(targetData, type).toLong(), encoding) as DITypeOpaqueRef
|
||||
|
||||
@@ -217,21 +216,23 @@ internal val IrFunction.types:List<IrType>
|
||||
return listOf(returnType, *parameters.toTypedArray())
|
||||
}
|
||||
|
||||
internal fun IrType.size(context:Context) = context.debugInfo.llvmTypeSizes.getOrDefault(this, context.debugInfo.otherTypeSize)
|
||||
internal fun IrType.size(context:Context) = context.generationState.debugInfo.llvmTypeSizes.getOrDefault(this, context.generationState.debugInfo.otherTypeSize)
|
||||
|
||||
internal fun IrType.alignment(context:Context) = context.debugInfo.llvmTypeAlignments.getOrDefault(this, context.debugInfo.otherTypeAlignment).toLong()
|
||||
internal fun IrType.alignment(context:Context) = context.generationState.debugInfo.llvmTypeAlignments.getOrDefault(this, context.generationState.debugInfo.otherTypeAlignment).toLong()
|
||||
|
||||
internal fun IrType.llvmType(context:Context): LLVMTypeRef = context.debugInfo.llvmTypes.getOrElse(this) {
|
||||
when(computePrimitiveBinaryTypeOrNull()) {
|
||||
PrimitiveBinaryType.BOOLEAN -> context.llvm.llvmInt1
|
||||
PrimitiveBinaryType.BYTE -> context.llvm.llvmInt8
|
||||
PrimitiveBinaryType.SHORT -> context.llvm.llvmInt16
|
||||
PrimitiveBinaryType.INT -> context.llvm.llvmInt32
|
||||
PrimitiveBinaryType.LONG -> context.llvm.llvmInt64
|
||||
PrimitiveBinaryType.FLOAT -> context.llvm.llvmFloat
|
||||
PrimitiveBinaryType.DOUBLE -> context.llvm.llvmDouble
|
||||
PrimitiveBinaryType.VECTOR128 -> context.llvm.llvmVector128
|
||||
else -> context.debugInfo.otherLlvmType
|
||||
internal fun IrType.llvmType(context:Context): LLVMTypeRef = with(context.generationState) {
|
||||
debugInfo.llvmTypes.getOrElse(this@llvmType) {
|
||||
when(computePrimitiveBinaryTypeOrNull()) {
|
||||
PrimitiveBinaryType.BOOLEAN -> llvm.llvmInt1
|
||||
PrimitiveBinaryType.BYTE -> llvm.llvmInt8
|
||||
PrimitiveBinaryType.SHORT -> llvm.llvmInt16
|
||||
PrimitiveBinaryType.INT -> llvm.llvmInt32
|
||||
PrimitiveBinaryType.LONG -> llvm.llvmInt64
|
||||
PrimitiveBinaryType.FLOAT -> llvm.llvmFloat
|
||||
PrimitiveBinaryType.DOUBLE -> llvm.llvmDouble
|
||||
PrimitiveBinaryType.VECTOR128 -> llvm.llvmVector128
|
||||
else -> debugInfo.otherLlvmType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,7 +257,7 @@ internal fun IrFunction.subroutineType(context: Context, llvmTargetData: LLVMTar
|
||||
|
||||
internal fun subroutineType(context: Context, llvmTargetData: LLVMTargetDataRef, types: List<IrType>): DISubroutineTypeRef {
|
||||
return memScoped {
|
||||
DICreateSubroutineType(context.debugInfo.builder, allocArrayOf(
|
||||
DICreateSubroutineType(context.generationState.debugInfo.builder, allocArrayOf(
|
||||
types.map { it.diType(context, llvmTargetData) }),
|
||||
types.size)!!
|
||||
}
|
||||
@@ -264,24 +265,24 @@ internal fun subroutineType(context: Context, llvmTargetData: LLVMTargetDataRef,
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun dwarfPointerType(context: Context, type: DITypeOpaqueRef) =
|
||||
DICreatePointerType(context.debugInfo.builder, type) as DITypeOpaqueRef
|
||||
DICreatePointerType(context.generationState.debugInfo.builder, type) as DITypeOpaqueRef
|
||||
|
||||
internal fun setupBridgeDebugInfo(context: Context, function: LLVMValueRef): LocationInfo? {
|
||||
if (!context.shouldContainLocationDebugInfo()) {
|
||||
return null
|
||||
}
|
||||
|
||||
val file = context.debugInfo.compilerGeneratedFile
|
||||
val file = context.generationState.debugInfo.compilerGeneratedFile
|
||||
|
||||
// TODO: can we share the scope among all bridges?
|
||||
val scope: DIScopeOpaqueRef = DICreateFunction(
|
||||
builder = context.debugInfo.builder,
|
||||
builder = context.generationState.debugInfo.builder,
|
||||
scope = file.reinterpret(),
|
||||
name = function.name,
|
||||
linkageName = function.name,
|
||||
file = file,
|
||||
lineNo = 0,
|
||||
type = subroutineType(context, context.llvm.runtime.targetData, emptyList()), // TODO: use proper type.
|
||||
type = subroutineType(context, context.generationState.runtime.targetData, emptyList()), // TODO: use proper type.
|
||||
isLocal = 0,
|
||||
isDefinition = 1,
|
||||
scopeLine = 0
|
||||
|
||||
+6
-6
@@ -168,7 +168,7 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
|
||||
IntrinsicType.IMMUTABLE_BLOB -> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val arg = callSite.getValueArgument(0) as IrConst<String>
|
||||
context.llvm.staticData.createImmutableBlob(arg)
|
||||
codegen.llvm.staticData.createImmutableBlob(arg)
|
||||
}
|
||||
IntrinsicType.OBJC_GET_SELECTOR -> {
|
||||
val selector = (callSite.getValueArgument(0) as IrConst<*>).value as String
|
||||
@@ -422,7 +422,7 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
|
||||
|
||||
or(bitsWithPadding, preservedBits)
|
||||
}
|
||||
llvm.LLVMBuildStore(builder, bitsToStore, bitsWithPaddingPtr)!!.setUnaligned()
|
||||
LLVMBuildStore(builder, bitsToStore, bitsWithPaddingPtr)!!.setUnaligned()
|
||||
return codegen.theUnitInstanceRef.llvm
|
||||
}
|
||||
|
||||
@@ -460,14 +460,14 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
|
||||
val functionParameterTypes = listOf(LlvmParamType(int8TypePtr), LlvmParamType(int8TypePtr))
|
||||
|
||||
val libobjc = context.standardLlvmSymbolsOrigin
|
||||
val normalMessenger = context.llvm.externalFunction(LlvmFunctionProto(
|
||||
val normalMessenger = codegen.llvm.externalFunction(LlvmFunctionProto(
|
||||
"objc_msgSend$messengerNameSuffix",
|
||||
functionReturnType,
|
||||
functionParameterTypes,
|
||||
isVararg = true,
|
||||
origin = libobjc
|
||||
))
|
||||
val superMessenger = context.llvm.externalFunction(LlvmFunctionProto(
|
||||
val superMessenger = codegen.llvm.externalFunction(LlvmFunctionProto(
|
||||
"objc_msgSendSuper$messengerNameSuffix",
|
||||
functionReturnType,
|
||||
functionParameterTypes,
|
||||
@@ -491,13 +491,13 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
|
||||
assert (first.type == second.type) { "Types are different: '${llvmtype2string(first.type)}' and '${llvmtype2string(second.type)}'" }
|
||||
|
||||
return when (val typeKind = LLVMGetTypeKind(first.type)) {
|
||||
llvm.LLVMTypeKind.LLVMFloatTypeKind, llvm.LLVMTypeKind.LLVMDoubleTypeKind,
|
||||
LLVMTypeKind.LLVMFloatTypeKind, LLVMTypeKind.LLVMDoubleTypeKind,
|
||||
LLVMTypeKind.LLVMVectorTypeKind -> {
|
||||
// TODO LLVM API does not provide guarantee for LLVMIntTypeInContext availability for longer types; consider meaningful diag message instead of NPE
|
||||
val integerType = LLVMIntTypeInContext(llvmContext, first.type.sizeInBits())!!
|
||||
icmpEq(bitcast(integerType, first), bitcast(integerType, second))
|
||||
}
|
||||
llvm.LLVMTypeKind.LLVMIntegerTypeKind, llvm.LLVMTypeKind.LLVMPointerTypeKind -> icmpEq(first, second)
|
||||
LLVMTypeKind.LLVMIntegerTypeKind, LLVMTypeKind.LLVMPointerTypeKind -> icmpEq(first, second)
|
||||
else -> error(typeKind)
|
||||
}
|
||||
}
|
||||
|
||||
+108
-108
@@ -205,6 +205,9 @@ private interface CodeContext {
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrElement, Lifetime>) : IrElementVisitorVoid {
|
||||
private val llvm = context.generationState.llvm
|
||||
private val debugInfo: DebugInfo
|
||||
get() = context.generationState.debugInfo
|
||||
|
||||
val codegen = CodeGenerator(context)
|
||||
|
||||
@@ -343,12 +346,12 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
private fun FunctionGenerationContext.initThreadLocalField(irField: IrField) {
|
||||
val initializer = irField.initializer ?: return
|
||||
val address = context.llvmDeclarations.forStaticField(irField).storageAddressAccess.getAddress(this)
|
||||
val address = context.generationState.llvmDeclarations.forStaticField(irField).storageAddressAccess.getAddress(this)
|
||||
storeAny(evaluateExpression(initializer.expression), address, false)
|
||||
}
|
||||
|
||||
private fun FunctionGenerationContext.initGlobalField(irField: IrField) {
|
||||
val address = context.llvmDeclarations.forStaticField(irField).storageAddressAccess.getAddress(this)
|
||||
val address = context.generationState.llvmDeclarations.forStaticField(irField).storageAddressAccess.getAddress(this)
|
||||
val initialValue = if (irField.hasNonConstInitializer) {
|
||||
val initialization = evaluateExpression(irField.initializer!!.expression)
|
||||
if (irField.shouldBeFrozen(context))
|
||||
@@ -358,7 +361,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
null
|
||||
}
|
||||
if (irField.needsGCRegistration(context)) {
|
||||
call(context.llvm.initAndRegisterGlobalFunction, listOf(address, initialValue
|
||||
call(llvm.initAndRegisterGlobalFunction, listOf(address, initialValue
|
||||
?: kNullObjHeaderPtr))
|
||||
} else if (initialValue != null) {
|
||||
storeAny(initialValue, address, false)
|
||||
@@ -367,20 +370,20 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
private fun runAndProcessInitializers(konanLibrary: KotlinLibrary?, f: () -> Unit) {
|
||||
// TODO: collect those two in one place.
|
||||
context.llvm.fileUsesThreadLocalObjects = false
|
||||
context.llvm.globalSharedObjects.clear()
|
||||
llvm.fileUsesThreadLocalObjects = false
|
||||
llvm.globalSharedObjects.clear()
|
||||
|
||||
context.llvm.initializersGenerationState.reset()
|
||||
llvm.initializersGenerationState.reset()
|
||||
|
||||
f()
|
||||
|
||||
context.llvm.initializersGenerationState.globalInitFunction?.let { fileInitFunction ->
|
||||
llvm.initializersGenerationState.globalInitFunction?.let { fileInitFunction ->
|
||||
generateFunction(codegen, fileInitFunction, fileInitFunction.location(start = true), fileInitFunction.location(start = false)) {
|
||||
using(FunctionScope(fileInitFunction, this)) {
|
||||
val parameterScope = ParameterScope(fileInitFunction, functionGenerationContext)
|
||||
using(parameterScope) usingParameterScope@{
|
||||
using(VariableScope()) usingVariableScope@{
|
||||
context.llvm.initializersGenerationState.topLevelFields
|
||||
llvm.initializersGenerationState.topLevelFields
|
||||
.filter { it.storageKind(context) != FieldStorageKind.THREAD_LOCAL }
|
||||
.filterNot { it.shouldBeInitializedEagerly }
|
||||
.forEach { initGlobalField(it) }
|
||||
@@ -391,13 +394,13 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
}
|
||||
}
|
||||
|
||||
context.llvm.initializersGenerationState.threadLocalInitFunction?.let { fileInitFunction ->
|
||||
llvm.initializersGenerationState.threadLocalInitFunction?.let { fileInitFunction ->
|
||||
generateFunction(codegen, fileInitFunction, fileInitFunction.location(start = true), fileInitFunction.location(start = false)) {
|
||||
using(FunctionScope(fileInitFunction, this)) {
|
||||
val parameterScope = ParameterScope(fileInitFunction, functionGenerationContext)
|
||||
using(parameterScope) usingParameterScope@{
|
||||
using(VariableScope()) usingVariableScope@{
|
||||
context.llvm.initializersGenerationState.topLevelFields
|
||||
llvm.initializersGenerationState.topLevelFields
|
||||
.filter { it.storageKind(context) == FieldStorageKind.THREAD_LOCAL }
|
||||
.filterNot { it.shouldBeInitializedEagerly }
|
||||
.forEach { initThreadLocalField(it) }
|
||||
@@ -408,14 +411,14 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
}
|
||||
}
|
||||
|
||||
if (!context.llvm.fileUsesThreadLocalObjects && context.llvm.globalSharedObjects.isEmpty()
|
||||
&& context.llvm.initializersGenerationState.isEmpty()) {
|
||||
if (!llvm.fileUsesThreadLocalObjects && llvm.globalSharedObjects.isEmpty()
|
||||
&& llvm.initializersGenerationState.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
// Create global initialization records.
|
||||
val initNode = createInitNode(createInitBody())
|
||||
context.llvm.irStaticInitializers.add(IrStaticInitializer(konanLibrary, createInitCtor(initNode)))
|
||||
llvm.irStaticInitializers.add(IrStaticInitializer(konanLibrary, createInitCtor(initNode)))
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
@@ -441,8 +444,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
context.coverage.writeRegionInfo()
|
||||
overrideRuntimeGlobals()
|
||||
appendLlvmUsed("llvm.used", context.llvm.usedFunctions + context.llvm.usedGlobals)
|
||||
appendLlvmUsed("llvm.compiler.used", context.llvm.compilerUsedGlobals)
|
||||
appendLlvmUsed("llvm.used", llvm.usedFunctions + llvm.usedGlobals)
|
||||
appendLlvmUsed("llvm.compiler.used", llvm.compilerUsedGlobals)
|
||||
if (context.config.produce.isNativeLibrary) {
|
||||
appendCAdapters()
|
||||
}
|
||||
@@ -454,8 +457,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
val kVoidFuncType = functionType(voidType)
|
||||
val kNodeInitType = LLVMGetTypeByName(context.llvmModule, "struct.InitNode")!!
|
||||
val kMemoryStateType = LLVMGetTypeByName(context.llvmModule, "struct.MemoryState")!!
|
||||
val kNodeInitType = LLVMGetTypeByName(llvm.module, "struct.InitNode")!!
|
||||
val kMemoryStateType = LLVMGetTypeByName(llvm.module, "struct.MemoryState")!!
|
||||
val kInitFuncType = functionType(voidType, false, int32Type, pointerType(kMemoryStateType))
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
@@ -472,7 +475,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
private fun createInitBody(): LLVMValueRef {
|
||||
val initFunction = addLlvmFunctionWithDefaultAttributes(
|
||||
context,
|
||||
context.llvmModule!!,
|
||||
llvm.module,
|
||||
"",
|
||||
kInitFuncType
|
||||
)
|
||||
@@ -496,56 +499,55 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
// Globals initializers may contain accesses to objects, so visit them first.
|
||||
appendingTo(bbInit) {
|
||||
context.llvm.initializersGenerationState.topLevelFields
|
||||
llvm.initializersGenerationState.topLevelFields
|
||||
.filter { !context.useLazyFileInitializers() || it.shouldBeInitializedEagerly }
|
||||
.filterNot { it.storageKind(context) == FieldStorageKind.THREAD_LOCAL }
|
||||
.forEach { initGlobalField(it) }
|
||||
context.llvm.initializersGenerationState.moduleGlobalInitializers.forEach {
|
||||
llvm.initializersGenerationState.moduleGlobalInitializers.forEach {
|
||||
evaluateSimpleFunctionCall(it, emptyList(), Lifetime.IRRELEVANT)
|
||||
}
|
||||
ret(null)
|
||||
}
|
||||
|
||||
appendingTo(bbLocalInit) {
|
||||
context.llvm.initializersGenerationState.threadLocalInitState?.let {
|
||||
llvm.initializersGenerationState.threadLocalInitState?.let {
|
||||
val address = it.getAddress(functionGenerationContext)
|
||||
store(Int32(FILE_NOT_INITIALIZED).llvm, address)
|
||||
LLVMSetInitializer(address, Int32(FILE_NOT_INITIALIZED).llvm)
|
||||
}
|
||||
context.llvm.initializersGenerationState.topLevelFields
|
||||
llvm.initializersGenerationState.topLevelFields
|
||||
.filter { !context.useLazyFileInitializers() || it.shouldBeInitializedEagerly }
|
||||
.filter { it.storageKind(context) == FieldStorageKind.THREAD_LOCAL }
|
||||
.forEach { initThreadLocalField(it) }
|
||||
context.llvm.initializersGenerationState.moduleThreadLocalInitializers.forEach {
|
||||
llvm.initializersGenerationState.moduleThreadLocalInitializers.forEach {
|
||||
evaluateSimpleFunctionCall(it, emptyList(), Lifetime.IRRELEVANT, null)
|
||||
}
|
||||
ret(null)
|
||||
}
|
||||
|
||||
appendingTo(bbLocalAlloc) {
|
||||
if (context.llvm.tlsCount > 0) {
|
||||
if (llvm.tlsCount > 0) {
|
||||
val memory = LLVMGetParam(initFunction, 1)!!
|
||||
call(context.llvm.addTLSRecord, listOf(memory, context.llvm.tlsKey,
|
||||
Int32(context.llvm.tlsCount).llvm))
|
||||
call(llvm.addTLSRecord, listOf(memory, llvm.tlsKey, Int32(llvm.tlsCount).llvm))
|
||||
}
|
||||
ret(null)
|
||||
}
|
||||
|
||||
appendingTo(bbGlobalDeinit) {
|
||||
context.llvm.initializersGenerationState.topLevelFields
|
||||
llvm.initializersGenerationState.topLevelFields
|
||||
// Only if a subject for memory management.
|
||||
.forEach { irField ->
|
||||
if (irField.type.binaryTypeIsReference() && irField.storageKind(context) != FieldStorageKind.THREAD_LOCAL) {
|
||||
val address = context.llvmDeclarations.forStaticField(irField).storageAddressAccess.getAddress(
|
||||
val address = context.generationState.llvmDeclarations.forStaticField(irField).storageAddressAccess.getAddress(
|
||||
functionGenerationContext
|
||||
)
|
||||
storeHeapRef(codegen.kNullObjHeaderPtr, address)
|
||||
}
|
||||
}
|
||||
context.llvm.globalSharedObjects.forEach { address ->
|
||||
llvm.globalSharedObjects.forEach { address ->
|
||||
storeHeapRef(codegen.kNullObjHeaderPtr, address)
|
||||
}
|
||||
context.llvm.initializersGenerationState.globalInitState?.let {
|
||||
llvm.initializersGenerationState.globalInitState?.let {
|
||||
store(Int32(FILE_NOT_INITIALIZED).llvm, it)
|
||||
}
|
||||
ret(null)
|
||||
@@ -564,15 +566,14 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
// Create static object of class InitNode.
|
||||
val initNode = LLVMConstNamedStruct(kNodeInitType, argList, 2)!!
|
||||
// Create global variable with init record data.
|
||||
return context.llvm.staticData.placeGlobal(
|
||||
"init_node", constPointer(initNode), isExported = false).llvmGlobal
|
||||
return llvm.staticData.placeGlobal("init_node", constPointer(initNode), isExported = false).llvmGlobal
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun createInitCtor(initNodePtr: LLVMValueRef): LLVMValueRef {
|
||||
val ctorFunction = generateFunctionNoRuntime(codegen, kVoidFuncType, "") {
|
||||
call(context.llvm.appendToInitalizersTail, listOf(initNodePtr))
|
||||
call(llvm.appendToInitalizersTail, listOf(initNodePtr))
|
||||
ret(null)
|
||||
}
|
||||
LLVMSetLinkage(ctorFunction, LLVMLinkage.LLVMPrivateLinkage)
|
||||
@@ -784,14 +785,14 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
}
|
||||
|
||||
private fun getGlobalInitStateFor(file: IrFile): LLVMValueRef =
|
||||
context.llvm.initializersGenerationState.fileGlobalInitStates.getOrPut(file) {
|
||||
llvm.initializersGenerationState.fileGlobalInitStates.getOrPut(file) {
|
||||
codegen.addGlobal("state_global$${file.fileEntry.name}", int32Type, false).also {
|
||||
LLVMSetInitializer(it, Int32(FILE_NOT_INITIALIZED).llvm)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getThreadLocalInitStateFor(file: IrFile): AddressAccess =
|
||||
context.llvm.initializersGenerationState.fileThreadLocalInitStates.getOrPut(file) {
|
||||
llvm.initializersGenerationState.fileThreadLocalInitStates.getOrPut(file) {
|
||||
codegen.addKotlinThreadLocal("state_thread_local$${file.fileEntry.name}", int32Type)
|
||||
}
|
||||
|
||||
@@ -801,31 +802,31 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
val body = declaration.body
|
||||
|
||||
if (declaration.origin == DECLARATION_ORIGIN_FILE_GLOBAL_INITIALIZER) {
|
||||
require(context.llvm.initializersGenerationState.globalInitFunction == null) { "There can only be at most one global file initializer" }
|
||||
require(llvm.initializersGenerationState.globalInitFunction == null) { "There can only be at most one global file initializer" }
|
||||
require(body == null) { "The body of file initializer should be null" }
|
||||
require(declaration.valueParameters.isEmpty()) { "File initializer must be parameterless" }
|
||||
require(declaration.returnsUnit()) { "File initializer must return Unit" }
|
||||
context.llvm.initializersGenerationState.globalInitFunction = declaration
|
||||
context.llvm.initializersGenerationState.globalInitState = getGlobalInitStateFor(declaration.parent as IrFile)
|
||||
llvm.initializersGenerationState.globalInitFunction = declaration
|
||||
llvm.initializersGenerationState.globalInitState = getGlobalInitStateFor(declaration.parent as IrFile)
|
||||
}
|
||||
if (declaration.origin == DECLARATION_ORIGIN_FILE_THREAD_LOCAL_INITIALIZER
|
||||
|| declaration.origin == DECLARATION_ORIGIN_FILE_STANDALONE_THREAD_LOCAL_INITIALIZER) {
|
||||
require(context.llvm.initializersGenerationState.threadLocalInitFunction == null) { "There can only be at most one thread local file initializer" }
|
||||
require(llvm.initializersGenerationState.threadLocalInitFunction == null) { "There can only be at most one thread local file initializer" }
|
||||
require(body == null) { "The body of file initializer should be null" }
|
||||
require(declaration.valueParameters.isEmpty()) { "File initializer must be parameterless" }
|
||||
require(declaration.returnsUnit()) { "File initializer must return Unit" }
|
||||
context.llvm.initializersGenerationState.threadLocalInitFunction = declaration
|
||||
context.llvm.initializersGenerationState.threadLocalInitState = getThreadLocalInitStateFor(declaration.parent as IrFile)
|
||||
llvm.initializersGenerationState.threadLocalInitFunction = declaration
|
||||
llvm.initializersGenerationState.threadLocalInitState = getThreadLocalInitStateFor(declaration.parent as IrFile)
|
||||
}
|
||||
if (declaration.origin == DECLARATION_ORIGIN_MODULE_GLOBAL_INITIALIZER) {
|
||||
require(declaration.valueParameters.isEmpty()) { "Module initializer must be a parameterless function" }
|
||||
require(declaration.returnsUnit()) { "Module initializer must return Unit" }
|
||||
context.llvm.initializersGenerationState.moduleGlobalInitializers.add(declaration)
|
||||
llvm.initializersGenerationState.moduleGlobalInitializers.add(declaration)
|
||||
}
|
||||
if (declaration.origin == DECLARATION_ORIGIN_MODULE_THREAD_LOCAL_INITIALIZER) {
|
||||
require(declaration.valueParameters.isEmpty()) { "Module initializer must be a parameterless function" }
|
||||
require(declaration.returnsUnit()) { "Module initializer must return Unit" }
|
||||
context.llvm.initializersGenerationState.moduleThreadLocalInitializers.add(declaration)
|
||||
llvm.initializersGenerationState.moduleThreadLocalInitializers.add(declaration)
|
||||
}
|
||||
|
||||
if ((declaration as? IrSimpleFunction)?.modality == Modality.ABSTRACT
|
||||
@@ -851,7 +852,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
recordCoverage(body)
|
||||
if (declaration.isReifiedInline) {
|
||||
callDirect(context.ir.symbols.throwIllegalStateExceptionWithMessage.owner,
|
||||
listOf(context.llvm.staticData.kotlinStringLiteral(
|
||||
listOf(llvm.staticData.kotlinStringLiteral(
|
||||
"unsupported call of reified inlined function `${declaration.fqNameForIrSerialization}`").llvm),
|
||||
Lifetime.IRRELEVANT, null)
|
||||
return@usingVariableScope
|
||||
@@ -870,12 +871,11 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
|
||||
if (declaration.retainAnnotation(context.config.target)) {
|
||||
context.llvm.usedFunctions.add(codegen.llvmFunction(declaration).llvmValue)
|
||||
llvm.usedFunctions.add(codegen.llvmFunction(declaration).llvmValue)
|
||||
}
|
||||
|
||||
if (context.shouldVerifyBitCode())
|
||||
verifyModule(context.llvmModule!!,
|
||||
"${declaration.descriptor.containingDeclaration}::${ir2string(declaration)}")
|
||||
verifyModule(llvm.module, "${declaration.descriptor.containingDeclaration}::${ir2string(declaration)}")
|
||||
}
|
||||
|
||||
private fun IrFunction.location(start: Boolean) =
|
||||
@@ -904,13 +904,13 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
}
|
||||
|
||||
if (declaration.kind.isSingleton && !declaration.isUnit()) {
|
||||
val singleton = context.llvmDeclarations.forSingleton(declaration)
|
||||
val singleton = context.generationState.llvmDeclarations.forSingleton(declaration)
|
||||
val access = singleton.instanceStorage
|
||||
if (access is GlobalAddressAccess) {
|
||||
// Global objects are kept in a data segment and can be accessed by any module (if exported) and also
|
||||
// they need to be initialized statically.
|
||||
LLVMSetInitializer(access.getAddress(null), if (declaration.storageKind(context) == ObjectStorageKind.PERMANENT)
|
||||
context.llvm.staticData.createConstKotlinObject(declaration,
|
||||
llvm.staticData.createConstKotlinObject(declaration,
|
||||
*computeFields(declaration)).llvm else codegen.kNullObjHeaderPtr)
|
||||
} else {
|
||||
// Thread local objects are kept in a special map, so they need a getter function to be accessible
|
||||
@@ -928,7 +928,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
}
|
||||
// Getter uses TLS object, so need to ensure that this file's (de)initializer function
|
||||
// inits and deinits TLS.
|
||||
context.llvm.fileUsesThreadLocalObjects = true
|
||||
llvm.fileUsesThreadLocalObjects = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -955,7 +955,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
debugFieldDeclaration(declaration)
|
||||
if (context.needGlobalInit(declaration)) {
|
||||
val type = codegen.getLLVMType(declaration.type)
|
||||
val globalPropertyAccess = context.llvmDeclarations.forStaticField(declaration).storageAddressAccess
|
||||
val globalPropertyAccess = context.generationState.llvmDeclarations.forStaticField(declaration).storageAddressAccess
|
||||
val initializer = declaration.initializer?.expression
|
||||
val globalProperty = (globalPropertyAccess as? GlobalAddressAccess)?.getAddress(null)
|
||||
if (globalProperty != null) {
|
||||
@@ -966,7 +966,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
// (Cannot do this before the global is initialized).
|
||||
LLVMSetLinkage(globalProperty, LLVMLinkage.LLVMInternalLinkage)
|
||||
}
|
||||
context.llvm.initializersGenerationState.topLevelFields.add(declaration)
|
||||
llvm.initializersGenerationState.topLevelFields.add(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1384,7 +1384,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
functionGenerationContext.positionAtEnd(loopBody)
|
||||
if (context.memoryModel == MemoryModel.EXPERIMENTAL)
|
||||
call(context.llvm.Kotlin_mm_safePointWhileLoopBody, emptyList())
|
||||
call(llvm.Kotlin_mm_safePointWhileLoopBody, emptyList())
|
||||
loop.body?.generate()
|
||||
|
||||
functionGenerationContext.br(loopScope.loopCheck)
|
||||
@@ -1406,7 +1406,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
functionGenerationContext.positionAtEnd(loopBody)
|
||||
if (context.memoryModel == MemoryModel.EXPERIMENTAL)
|
||||
call(context.llvm.Kotlin_mm_safePointWhileLoopBody, emptyList())
|
||||
call(llvm.Kotlin_mm_safePointWhileLoopBody, emptyList())
|
||||
loop.body?.generate()
|
||||
functionGenerationContext.br(loopScope.loopCheck)
|
||||
|
||||
@@ -1453,7 +1453,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
val file = (currentCodeContext.fileScope() as FileScope).file.file()
|
||||
return when (element) {
|
||||
is IrVariable -> if (shouldGenerateDebugInfo(element)) debugInfoLocalVariableLocation(
|
||||
builder = context.debugInfo.builder,
|
||||
builder = debugInfo.builder,
|
||||
functionScope = locationInfo.scope,
|
||||
diType = element.type.diType(context, codegen.llvmTargetData),
|
||||
name = element.debugNameConversion(),
|
||||
@@ -1462,7 +1462,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
location = location)
|
||||
else null
|
||||
is IrValueParameter -> debugInfoParameterLocation(
|
||||
builder = context.debugInfo.builder,
|
||||
builder = debugInfo.builder,
|
||||
functionScope = locationInfo.scope,
|
||||
diType = element.type.diType(context, codegen.llvmTargetData),
|
||||
name = element.debugNameConversion(),
|
||||
@@ -1580,7 +1580,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
val dstFullClassName = dstClass.fqNameWhenAvailable?.toString() ?: dstClass.name.toString()
|
||||
callDirect(
|
||||
context.ir.symbols.throwTypeCastException.owner,
|
||||
listOf(srcArg, context.llvm.staticData.kotlinStringLiteral(dstFullClassName).llvm),
|
||||
listOf(srcArg, llvm.staticData.kotlinStringLiteral(dstFullClassName).llvm),
|
||||
Lifetime.GLOBAL,
|
||||
null
|
||||
)
|
||||
@@ -1645,11 +1645,11 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
val srcObjInfoPtr = functionGenerationContext.bitcast(codegen.kObjHeaderPtr, obj)
|
||||
|
||||
return if (!context.ghaEnabled()) {
|
||||
call(context.llvm.isInstanceFunction, listOf(srcObjInfoPtr, codegen.typeInfoValue(dstClass)))
|
||||
call(llvm.isInstanceFunction, listOf(srcObjInfoPtr, codegen.typeInfoValue(dstClass)))
|
||||
} else {
|
||||
val dstHierarchyInfo = context.getLayoutBuilder(dstClass).hierarchyInfo
|
||||
if (!dstClass.isInterface) {
|
||||
call(context.llvm.isInstanceOfClassFastFunction,
|
||||
call(llvm.isInstanceOfClassFastFunction,
|
||||
listOf(srcObjInfoPtr, Int32(dstHierarchyInfo.classIdLo).llvm, Int32(dstHierarchyInfo.classIdHi).llvm))
|
||||
} else {
|
||||
// Essentially: typeInfo.itable[place(interfaceId)].id == interfaceId
|
||||
@@ -1675,7 +1675,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
if (dstClass.isInterface) {
|
||||
val isMeta = if (dstClass.isObjCMetaClass()) kTrue else kFalse
|
||||
call(
|
||||
context.llvm.Kotlin_Interop_DoesObjectConformToProtocol,
|
||||
llvm.Kotlin_Interop_DoesObjectConformToProtocol,
|
||||
listOf(
|
||||
objCObject,
|
||||
genGetObjCProtocol(dstClass),
|
||||
@@ -1684,7 +1684,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
)
|
||||
} else {
|
||||
call(
|
||||
context.llvm.Kotlin_Interop_IsObjectKindOfClass,
|
||||
llvm.Kotlin_Interop_IsObjectKindOfClass,
|
||||
listOf(objCObject, genGetObjCClass(dstClass))
|
||||
)
|
||||
}.let {
|
||||
@@ -1701,7 +1701,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
listOf(LlvmParamType(int8TypePtr)),
|
||||
origin = context.standardLlvmSymbolsOrigin
|
||||
)
|
||||
val isClass = context.llvm.externalFunction(isClassProto)
|
||||
val isClass = llvm.externalFunction(isClassProto)
|
||||
call(isClass, listOf(objCObject)).let {
|
||||
functionGenerationContext.icmpNe(it, Int8(0).llvm)
|
||||
}
|
||||
@@ -1711,7 +1711,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
val protocolClass =
|
||||
functionGenerationContext.getObjCClass("Protocol", context.standardLlvmSymbolsOrigin)
|
||||
call(
|
||||
context.llvm.Kotlin_Interop_IsObjectKindOfClass,
|
||||
llvm.Kotlin_Interop_IsObjectKindOfClass,
|
||||
listOf(objCObject, protocolClass)
|
||||
)
|
||||
} else {
|
||||
@@ -1743,7 +1743,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
if (context.config.threadsAreAllowed && value.symbol.owner.isGlobalNonPrimitive(context)) {
|
||||
functionGenerationContext.checkGlobalsAccessible(currentCodeContext.exceptionHandler)
|
||||
}
|
||||
val ptr = context.llvmDeclarations.forStaticField(value.symbol.owner).storageAddressAccess.getAddress(
|
||||
val ptr = context.generationState.llvmDeclarations.forStaticField(value.symbol.owner).storageAddressAccess.getAddress(
|
||||
functionGenerationContext
|
||||
)
|
||||
functionGenerationContext.loadSlot(ptr, !value.symbol.owner.isFinal, resultSlot)
|
||||
@@ -1802,17 +1802,17 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
}
|
||||
val parentAsClass = value.symbol.owner.parentAsClass
|
||||
if (needMutationCheck(parentAsClass)) {
|
||||
functionGenerationContext.call(context.llvm.mutationCheck,
|
||||
functionGenerationContext.call(llvm.mutationCheck,
|
||||
listOf(functionGenerationContext.bitcast(codegen.kObjHeaderPtr, thisPtr)),
|
||||
Lifetime.IRRELEVANT, currentCodeContext.exceptionHandler)
|
||||
}
|
||||
if (needLifetimeConstraintsCheck(valueToAssign, parentAsClass)) {
|
||||
functionGenerationContext.call(context.llvm.checkLifetimesConstraint, listOf(thisPtr, valueToAssign))
|
||||
functionGenerationContext.call(llvm.checkLifetimesConstraint, listOf(thisPtr, valueToAssign))
|
||||
}
|
||||
functionGenerationContext.storeAny(valueToAssign, fieldPtrOfClass(thisPtr, value.symbol.owner), false)
|
||||
} else {
|
||||
assert(value.receiver == null)
|
||||
val globalAddress = context.llvmDeclarations.forStaticField(value.symbol.owner).storageAddressAccess.getAddress(
|
||||
val globalAddress = context.generationState.llvmDeclarations.forStaticField(value.symbol.owner).storageAddressAccess.getAddress(
|
||||
functionGenerationContext
|
||||
)
|
||||
if (context.config.threadsAreAllowed && value.symbol.owner.storageKind(context) == FieldStorageKind.GLOBAL)
|
||||
@@ -1833,7 +1833,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
private fun fieldPtrOfClass(thisPtr: LLVMValueRef, value: IrField): LLVMValueRef {
|
||||
val fieldInfo = context.llvmDeclarations.forField(value)
|
||||
val fieldInfo = context.generationState.llvmDeclarations.forField(value)
|
||||
|
||||
val typePtr = pointerType(fieldInfo.classBodyType)
|
||||
|
||||
@@ -1844,7 +1844,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
private fun evaluateStringConst(value: IrConst<String>) =
|
||||
context.llvm.staticData.kotlinStringLiteral(value.value)
|
||||
llvm.staticData.kotlinStringLiteral(value.value)
|
||||
|
||||
private fun evaluateConst(value: IrConst<*>): ConstValue {
|
||||
context.log{"evaluateConst : ${ir2string(value)}"}
|
||||
@@ -1900,7 +1900,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
require(codegen.getLLVMType(value.type) == codegen.kObjHeaderPtr) {
|
||||
"Can't wrap ${value.value.kind.asString} constant to type ${value.type.render()}"
|
||||
}
|
||||
value.toBoxCacheValue(context) ?: context.llvm.staticData.createConstKotlinObject(
|
||||
value.toBoxCacheValue(context) ?: llvm.staticData.createConstKotlinObject(
|
||||
constructedType.getClass()!!,
|
||||
evaluateConst(value.value)
|
||||
)
|
||||
@@ -1914,7 +1914,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
require(clazz.symbol == symbols.array || clazz.symbol in symbols.primitiveTypesToPrimitiveArrays.values) {
|
||||
"Statically initialized array should have array type"
|
||||
}
|
||||
context.llvm.staticData.createConstKotlinArray(
|
||||
llvm.staticData.createConstKotlinArray(
|
||||
value.type.getClass()!!,
|
||||
value.elements.map { evaluateConstantValue(it) }
|
||||
)
|
||||
@@ -1944,7 +1944,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()}" }
|
||||
context.llvm.staticData.createConstKotlinObject(
|
||||
llvm.staticData.createConstKotlinObject(
|
||||
constructedClass,
|
||||
*fields.toTypedArray()
|
||||
)
|
||||
@@ -1968,7 +1968,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
//-------------------------------------------------------------------------//
|
||||
private inner class ReturnableBlockScope(val returnableBlock: IrReturnableBlock, val resultSlot: LLVMValueRef?) :
|
||||
FileScope(returnableBlock.inlineFunctionSymbol?.owner?.let {
|
||||
context.mapping.loweredInlineFunctions[it]?.irFile ?: it.fileOrNull
|
||||
context.generationState.loweredInlineFunctions[it]?.irFile ?: it.fileOrNull
|
||||
}
|
||||
?: (currentCodeContext.fileScope() as? FileScope)?.file
|
||||
?: error("returnable block should belong to current file at least")) {
|
||||
@@ -1977,13 +1977,13 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
var resultPhi : LLVMValueRef? = null
|
||||
private val functionScope by lazy {
|
||||
returnableBlock.inlineFunctionSymbol?.owner?.let {
|
||||
it.scope(file().fileEntry.line(context.mapping.loweredInlineFunctions[it]?.startOffset ?: it.startOffset))
|
||||
it.scope(file().fileEntry.line(context.generationState.loweredInlineFunctions[it]?.startOffset ?: it.startOffset))
|
||||
}
|
||||
}
|
||||
|
||||
private fun getExit(): LLVMBasicBlockRef {
|
||||
val location = returnableBlock.inlineFunctionSymbol?.owner?.let {
|
||||
location(context.mapping.loweredInlineFunctions[it]?.endOffset ?: it.endOffset)
|
||||
location(context.generationState.loweredInlineFunctions[it]?.endOffset ?: it.endOffset)
|
||||
} ?: returnableBlock.statements.lastOrNull()?.let {
|
||||
location(it.endOffset)
|
||||
}
|
||||
@@ -2040,8 +2040,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
private val scope by lazy {
|
||||
if (!context.shouldContainLocationDebugInfo() || returnableBlock.startOffset == UNDEFINED_OFFSET)
|
||||
return@lazy null
|
||||
val lexicalBlockFile = DICreateLexicalBlockFile(context.debugInfo.builder, functionScope()!!.scope(), super.file.file())
|
||||
DICreateLexicalBlock(context.debugInfo.builder, lexicalBlockFile, super.file.file(), returnableBlock.startLine(), returnableBlock.startColumn())!!
|
||||
val lexicalBlockFile = DICreateLexicalBlockFile(debugInfo.builder, functionScope()!!.scope(), super.file.file())
|
||||
DICreateLexicalBlock(debugInfo.builder, lexicalBlockFile, super.file.file(), returnableBlock.startLine(), returnableBlock.startColumn())!!
|
||||
}
|
||||
|
||||
override fun scope() = scope
|
||||
@@ -2074,7 +2074,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
val members = mutableListOf<DIDerivedTypeRef>()
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val scope = if (isExported && context.shouldContainDebugInfo())
|
||||
context.debugInfo.objHeaderPointerType
|
||||
debugInfo.objHeaderPointerType
|
||||
else null
|
||||
override fun classScope(): CodeContext? = this
|
||||
}
|
||||
@@ -2197,7 +2197,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
scope.offsetInBits = alignTo(scope.offsetInBits, alignInBits)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
scope.members.add(DICreateMemberType(
|
||||
refBuilder = context.debugInfo.builder,
|
||||
refBuilder = debugInfo.builder,
|
||||
refScope = scope.scope as DIScopeOpaqueRef,
|
||||
name = expression.computeSymbolName(),
|
||||
file = irFile.file(),
|
||||
@@ -2213,9 +2213,9 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
private fun IrFile.file(): DIFileRef {
|
||||
return context.debugInfo.files.getOrPut(this.fileEntry.name) {
|
||||
return debugInfo.files.getOrPut(this.fileEntry.name) {
|
||||
val path = this.fileEntry.name.toFileAndFolder(context)
|
||||
DICreateFile(context.debugInfo.builder, path.file, path.folder)!!
|
||||
DICreateFile(debugInfo.builder, path.file, path.folder)!!
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2245,7 +2245,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
else
|
||||
codegen.llvmFunctionOrNull(this)?.llvmValue
|
||||
return if (!isReifiedInline && functionLlvmValue != null) {
|
||||
context.debugInfo.subprograms.getOrPut(functionLlvmValue) {
|
||||
debugInfo.subprograms.getOrPut(functionLlvmValue) {
|
||||
memScoped {
|
||||
val subroutineType = subroutineType(context, codegen.llvmTargetData)
|
||||
val llvmFunction = codegen.llvmFunction(this@scope).llvmValue
|
||||
@@ -2256,7 +2256,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
}
|
||||
} as DIScopeOpaqueRef
|
||||
} else {
|
||||
context.debugInfo.inlinedSubprograms.getOrPut(this) {
|
||||
debugInfo.inlinedSubprograms.getOrPut(this) {
|
||||
memScoped {
|
||||
val subroutineType = subroutineType(context, codegen.llvmTargetData)
|
||||
diFunctionScope(name.asString(), "<inlined-out:$name>", startLine, subroutineType)
|
||||
@@ -2268,7 +2268,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun LLVMValueRef.scope(startLine:Int, subroutineType: DISubroutineTypeRef): DIScopeOpaqueRef? {
|
||||
return context.debugInfo.subprograms.getOrPut(this) {
|
||||
return debugInfo.subprograms.getOrPut(this) {
|
||||
diFunctionScope(name!!, name!!, startLine, subroutineType).also {
|
||||
DIFunctionAddSubprogram(this@scope, it)
|
||||
}
|
||||
@@ -2277,8 +2277,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun diFunctionScope(name: String, linkageName: String, startLine: Int, subroutineType: DISubroutineTypeRef) = DICreateFunction(
|
||||
builder = context.debugInfo.builder,
|
||||
scope = context.debugInfo.compilationUnit,
|
||||
builder = debugInfo.builder,
|
||||
scope = debugInfo.compilationUnit,
|
||||
name = name,
|
||||
linkageName = linkageName,
|
||||
file = file().file(),
|
||||
@@ -2447,7 +2447,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
LLVMSetOrdering(state, LLVMAtomicOrdering.LLVMAtomicOrderingAcquire)
|
||||
condBr(icmpEq(state, Int32(FILE_INITIALIZED).llvm), bbExit, bbInit)
|
||||
positionAtEnd(bbInit)
|
||||
call(context.llvm.callInitGlobalPossiblyLock, listOf(statePtr, initializerPtr),
|
||||
call(llvm.callInitGlobalPossiblyLock, listOf(statePtr, initializerPtr),
|
||||
exceptionHandler = currentCodeContext.exceptionHandler)
|
||||
br(bbExit)
|
||||
positionAtEnd(bbExit)
|
||||
@@ -2474,7 +2474,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
positionAtEnd(bbCheckLocalState)
|
||||
condBr(icmpNe(load(localStatePtr), Int32(FILE_INITIALIZED).llvm), bbInit, bbExit)
|
||||
positionAtEnd(bbInit)
|
||||
call(context.llvm.callInitThreadLocal, listOf(globalStatePtr, localStatePtr, initializerPtr),
|
||||
call(llvm.callInitThreadLocal, listOf(globalStatePtr, localStatePtr, initializerPtr),
|
||||
exceptionHandler = currentCodeContext.exceptionHandler)
|
||||
br(bbExit)
|
||||
positionAtEnd(bbExit)
|
||||
@@ -2492,7 +2492,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
moveBlockAfterEntry(bbInit)
|
||||
condBr(icmpEq(load(statePtr), Int32(FILE_INITIALIZED).llvm), bbExit, bbInit)
|
||||
positionAtEnd(bbInit)
|
||||
call(context.llvm.callInitThreadLocal, listOf(kNullInt32Ptr, statePtr, initializerPtr),
|
||||
call(llvm.callInitThreadLocal, listOf(kNullInt32Ptr, statePtr, initializerPtr),
|
||||
exceptionHandler = currentCodeContext.exceptionHandler)
|
||||
br(bbExit)
|
||||
positionAtEnd(bbExit)
|
||||
@@ -2562,7 +2562,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
origin = irClass.llvmSymbolOrigin,
|
||||
independent = true // Protocol is header-only declaration.
|
||||
)
|
||||
val protocolGetter = context.llvm.externalFunction(protocolGetterProto)
|
||||
val protocolGetter = llvm.externalFunction(protocolGetterProto)
|
||||
|
||||
return call(protocolGetter, emptyList())
|
||||
}
|
||||
@@ -2733,9 +2733,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
private fun appendLlvmUsed(name: String, args: List<LLVMValueRef>) {
|
||||
if (args.isEmpty()) return
|
||||
|
||||
val argsCasted = args.map { it -> constPointer(it).bitcast(int8TypePtr) }
|
||||
val llvmUsedGlobal =
|
||||
context.llvm.staticData.placeGlobalArray(name, int8TypePtr, argsCasted)
|
||||
val argsCasted = args.map { constPointer(it).bitcast(int8TypePtr) }
|
||||
val llvmUsedGlobal = llvm.staticData.placeGlobalArray(name, int8TypePtr, argsCasted)
|
||||
|
||||
LLVMSetLinkage(llvmUsedGlobal.llvmGlobal, LLVMLinkage.LLVMAppendingLinkage)
|
||||
LLVMSetSection(llvmUsedGlobal.llvmGlobal, "llvm.metadata")
|
||||
@@ -2755,14 +2754,14 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
LLVMSetLinkage(initializer, LLVMLinkage.LLVMPrivateLinkage)
|
||||
|
||||
context.llvm.otherStaticInitializers += initializer
|
||||
llvm.otherStaticInitializers += initializer
|
||||
} else {
|
||||
context.llvmImports.add(context.standardLlvmSymbolsOrigin)
|
||||
context.generationState.llvmImports.add(context.standardLlvmSymbolsOrigin)
|
||||
// Define a strong runtime global. It'll overrule a weak global defined in a statically linked runtime.
|
||||
val global = context.llvm.staticData.placeGlobal(name, value, true)
|
||||
val global = llvm.staticData.placeGlobal(name, value, true)
|
||||
|
||||
if (context.llvmModuleSpecification.importsKotlinDeclarationsFromOtherObjectFiles()) {
|
||||
context.llvm.usedGlobals += global.llvmGlobal
|
||||
llvm.usedGlobals += global.llvmGlobal
|
||||
LLVMSetVisibility(global.llvmGlobal, LLVMVisibility.LLVMHiddenVisibility)
|
||||
}
|
||||
}
|
||||
@@ -2782,8 +2781,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
SourceInfoType.CORESYMBOLICATION -> "Kotlin_getSourceInfo_core_symbolication"
|
||||
}
|
||||
if (getSourceInfoFunctionName != null) {
|
||||
val getSourceInfoFunction = LLVMGetNamedFunction(context.llvmModule, getSourceInfoFunctionName)
|
||||
?: LLVMAddFunction(context.llvmModule, getSourceInfoFunctionName,
|
||||
val getSourceInfoFunction = LLVMGetNamedFunction(llvm.module, getSourceInfoFunctionName)
|
||||
?: LLVMAddFunction(llvm.module, getSourceInfoFunctionName,
|
||||
functionType(int32Type, false, int8TypePtr, int8TypePtr, int32Type))
|
||||
overrideRuntimeGlobal("Kotlin_getSourceInfo_Function", constValue(getSourceInfoFunction!!))
|
||||
}
|
||||
@@ -2827,13 +2826,13 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
//-------------------------------------------------------------------------//
|
||||
fun appendStaticInitializers() {
|
||||
// Note: the list of libraries is topologically sorted (in order for initializers to be called correctly).
|
||||
val libraries = (context.llvm.allBitcodeDependencies + listOf(null)/* Null for "current" non-library module */)
|
||||
val libraries = (llvm.allBitcodeDependencies + listOf(null)/* Null for "current" non-library module */)
|
||||
|
||||
val libraryToInitializers = libraries.associateWith {
|
||||
mutableListOf<LLVMValueRef>()
|
||||
}
|
||||
|
||||
context.llvm.irStaticInitializers.forEach {
|
||||
llvm.irStaticInitializers.forEach {
|
||||
val library = it.konanLibrary
|
||||
val initializers = libraryToInitializers[library]
|
||||
?: error("initializer for not included library ${library?.libraryFile}")
|
||||
@@ -2846,7 +2845,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
fun addCtorFunction(ctorName: String) =
|
||||
addLlvmFunctionWithDefaultAttributes(
|
||||
context,
|
||||
context.llvmModule!!,
|
||||
llvm.module,
|
||||
ctorName,
|
||||
kVoidFuncType
|
||||
).also { LLVMSetLinkage(it, LLVMLinkage.LLVMExternalLinkage) }
|
||||
@@ -2855,15 +2854,16 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
val initializers = libraryToInitializers.getValue(library)
|
||||
|
||||
val ctorName = when {
|
||||
library == null -> context.config.moduleId.moduleConstructorName
|
||||
// TODO: Try to not use moduleId.
|
||||
library == null -> (if (context.config.produce.isCache) context.generationState.outputFiles.cacheFileName else context.config.moduleId).moduleConstructorName
|
||||
library == context.config.libraryToCache?.klib
|
||||
&& context.config.producePerFileCache ->
|
||||
fileCtorName(library.uniqueName, context.config.outputFiles.perFileCacheFileName)
|
||||
fileCtorName(library.uniqueName, context.generationState.outputFiles.perFileCacheFileName)
|
||||
else -> library.moduleConstructorName
|
||||
}
|
||||
|
||||
if (library == null || context.llvmModuleSpecification.containsLibrary(library)) {
|
||||
val otherInitializers = context.llvm.otherStaticInitializers.takeIf { library == null }.orEmpty()
|
||||
val otherInitializers = llvm.otherStaticInitializers.takeIf { library == null }.orEmpty()
|
||||
|
||||
val ctorFunction = addCtorFunction(ctorName)
|
||||
appendStaticInitializers(ctorFunction, initializers + otherInitializers)
|
||||
@@ -2895,7 +2895,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
private fun appendStaticInitializers(ctorFunction: LLVMValueRef, initializers: List<LLVMValueRef>) {
|
||||
generateFunctionNoRuntime(codegen, ctorFunction) {
|
||||
val initGuardName = ctorFunction.name.orEmpty() + "_guard"
|
||||
val initGuard = LLVMAddGlobal(context.llvmModule, int32Type, initGuardName)
|
||||
val initGuard = LLVMAddGlobal(llvm.module, int32Type, initGuardName)
|
||||
LLVMSetInitializer(initGuard, kImmZero)
|
||||
LLVMSetLinkage(initGuard, LLVMLinkage.LLVMPrivateLinkage)
|
||||
val bbInited = basicBlock("inited", null)
|
||||
@@ -2935,7 +2935,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
LLVMSetLinkage(globalCtorFunction, LLVMLinkage.LLVMPrivateLinkage)
|
||||
|
||||
// Append initializers of global variables in "llvm.global_ctors" array.
|
||||
val globalCtors = context.llvm.staticData.placeGlobalArray("llvm.global_ctors", kCtorType,
|
||||
val globalCtors = llvm.staticData.placeGlobalArray("llvm.global_ctors", kCtorType,
|
||||
listOf(createGlobalCtor(globalCtorFunction)))
|
||||
LLVMSetLinkage(globalCtors.llvmGlobal, LLVMLinkage.LLVMAppendingLinkage)
|
||||
if (context.config.produce == CompilerOutputKind.PROGRAM) {
|
||||
@@ -2981,7 +2981,7 @@ internal class LocationInfo(val scope: DIScopeOpaqueRef,
|
||||
|
||||
internal fun Context.generateRuntimeConstantsModule() : LLVMModuleRef {
|
||||
val llvmModule = LLVMModuleCreateWithNameInContext("constants", llvmContext)!!
|
||||
LLVMSetDataLayout(llvmModule, llvm.runtime.dataLayout)
|
||||
LLVMSetDataLayout(llvmModule, generationState.runtime.dataLayout)
|
||||
val static = StaticData(llvmModule)
|
||||
|
||||
fun setRuntimeConstGlobal(name: String, value: ConstValue) {
|
||||
|
||||
+5
-5
@@ -20,7 +20,7 @@ internal class KotlinObjCClassInfoGenerator(override val context: Context) : Con
|
||||
fun generate(irClass: IrClass) {
|
||||
assert(irClass.isFinalClass)
|
||||
|
||||
val objCLLvmDeclarations = context.llvmDeclarations.forClass(irClass).objCDeclarations!!
|
||||
val objCLLvmDeclarations = context.generationState.llvmDeclarations.forClass(irClass).objCDeclarations!!
|
||||
|
||||
val instanceMethods = generateInstanceMethodDescs(irClass)
|
||||
|
||||
@@ -28,11 +28,11 @@ internal class KotlinObjCClassInfoGenerator(override val context: Context) : Con
|
||||
val classMethods = companionObject?.generateMethodDescs().orEmpty()
|
||||
|
||||
val superclassName = irClass.getSuperClassNotAny()!!.let {
|
||||
context.llvm.imports.add(it.llvmSymbolOrigin)
|
||||
llvm.imports.add(it.llvmSymbolOrigin)
|
||||
it.descriptor.getExternalObjCClassBinaryName()
|
||||
}
|
||||
val protocolNames = irClass.getSuperInterfaces().map {
|
||||
context.llvm.imports.add(it.llvmSymbolOrigin)
|
||||
llvm.imports.add(it.llvmSymbolOrigin)
|
||||
it.name.asString().removeSuffix("Protocol")
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ internal class KotlinObjCClassInfoGenerator(override val context: Context) : Con
|
||||
.distinctBy { it.selector }
|
||||
|
||||
allInitMethodsInfo.mapTo(this) {
|
||||
ObjCMethodDesc(it.selector, it.encoding, context.llvm.missingInitImp.llvmValue)
|
||||
ObjCMethodDesc(it.selector, it.encoding, llvm.missingInitImp.llvmValue)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,6 +164,6 @@ internal fun CodeGenerator.kotlinObjCClassInfo(irClass: IrClass): LLVMValueRef {
|
||||
origin = irClass.llvmSymbolOrigin
|
||||
)
|
||||
} else {
|
||||
context.llvmDeclarations.forClass(irClass).objCDeclarations!!.classInfoGlobal.llvmGlobal
|
||||
llvmDeclarations.forClass(irClass).objCDeclarations!!.classInfoGlobal.llvmGlobal
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -16,7 +16,7 @@ private fun ConstPointer.add(index: Int): ConstPointer {
|
||||
return constPointer(LLVMConstGEP(llvm, cValuesOf(Int32(index).llvm), 1)!!)
|
||||
}
|
||||
|
||||
internal class KotlinStaticData(override val context: Context) : ContextUtils, StaticData(context.llvmModule!!) {
|
||||
internal class KotlinStaticData(override val context: Context, module: LLVMModuleRef) : ContextUtils, StaticData(module) {
|
||||
private val stringLiterals = mutableMapOf<String, ConstPointer>()
|
||||
|
||||
// Must match OBJECT_TAG_PERMANENT_CONTAINER in C++.
|
||||
@@ -104,10 +104,10 @@ internal class KotlinStaticData(override val context: Context) : ContextUtils, S
|
||||
}
|
||||
return if (isExternal(descriptor)) {
|
||||
constPointer(importGlobal(
|
||||
kind.llvmName, context.llvm.runtime.objHeaderType, origin = descriptor.llvmSymbolOrigin
|
||||
kind.llvmName, runtime.objHeaderType, origin = descriptor.llvmSymbolOrigin
|
||||
))
|
||||
} else {
|
||||
context.llvmDeclarations.forUnique(kind).pointer
|
||||
context.generationState.llvmDeclarations.forUnique(kind).pointer
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+8
-8
@@ -84,11 +84,11 @@ private fun ContextUtils.createClassBodyType(name: String, fields: List<ClassLay
|
||||
val fieldTypes = listOf(runtime.objHeaderType) + fields.map { getLLVMType(it.type) }
|
||||
// TODO: consider adding synthetic ObjHeader field to Any.
|
||||
|
||||
val classType = LLVMStructCreateNamed(LLVMGetModuleContext(context.llvmModule), name)!!
|
||||
val classType = LLVMStructCreateNamed(LLVMGetModuleContext(llvm.module), name)!!
|
||||
|
||||
// LLVMStructSetBody expects the struct to be properly aligned and will insert padding accordingly. In our case
|
||||
// `allocInstance` returns 16x + 8 address, i.e. always misaligned for vector types. Workaround is to use packed struct.
|
||||
val hasBigAlignment = fields.any { LLVMABIAlignmentOfType(context.llvm.runtime.targetData, getLLVMType(it.type)) > 8 }
|
||||
val hasBigAlignment = fields.any { LLVMABIAlignmentOfType(runtime.targetData, getLLVMType(it.type)) > 8 }
|
||||
val packed = if (hasBigAlignment) 1 else 0
|
||||
LLVMStructSetBody(classType, fieldTypes.toCValues(), fieldTypes.size, packed)
|
||||
|
||||
@@ -191,7 +191,7 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
|
||||
typeInfoGlobal = staticData.createGlobal(typeInfoWithVtableType, typeInfoGlobalName, isExported = false)
|
||||
|
||||
val llvmTypeInfoPtr = LLVMAddAlias(context.llvmModule,
|
||||
val llvmTypeInfoPtr = LLVMAddAlias(llvm.module,
|
||||
kTypeInfoPtr,
|
||||
typeInfoGlobal.pointer.getElementPtr(0).llvm,
|
||||
typeInfoSymbolName)!!
|
||||
@@ -202,7 +202,7 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
throw IllegalArgumentException("Global '$typeInfoSymbolName' already exists")
|
||||
}
|
||||
} else {
|
||||
if (!context.config.producePerFileCache || declaration !in context.constructedFromExportedInlineFunctions)
|
||||
if (!context.config.producePerFileCache || declaration !in context.generationState.constructedFromExportedInlineFunctions)
|
||||
LLVMSetLinkage(llvmTypeInfoPtr, LLVMLinkage.LLVMInternalLinkage)
|
||||
}
|
||||
|
||||
@@ -296,7 +296,7 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
"kobjcclassinfo:$internalName"
|
||||
}
|
||||
val classInfoGlobal = staticData.createGlobal(
|
||||
context.llvm.runtime.kotlinObjCClassInfo,
|
||||
runtime.kotlinObjCClassInfo,
|
||||
classInfoSymbolName,
|
||||
isExported = isExported
|
||||
).apply {
|
||||
@@ -360,12 +360,12 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
|| declaration.annotations.hasAnnotation(RuntimeNames.cCall)) return
|
||||
|
||||
val proto = LlvmFunctionProto(declaration, declaration.computeSymbolName(), this)
|
||||
context.llvm.externalFunction(proto)
|
||||
llvm.externalFunction(proto)
|
||||
} else {
|
||||
val symbolName = if (declaration.isExported()) {
|
||||
declaration.computeSymbolName().also {
|
||||
if (declaration.name.asString() != "main") {
|
||||
assert(LLVMGetNamedFunction(context.llvm.llvmModule, it) == null) { it }
|
||||
assert(LLVMGetNamedFunction(llvm.module, it) == null) { it }
|
||||
} else {
|
||||
// As a workaround, allow `main` functions to clash because frontend accepts this.
|
||||
// See [OverloadResolver.isTopLevelMainInDifferentFiles] usage.
|
||||
@@ -384,7 +384,7 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
val proto = LlvmFunctionProto(declaration, symbolName, this)
|
||||
val llvmFunction = addLlvmFunctionWithDefaultAttributes(
|
||||
context,
|
||||
context.llvmModule!!,
|
||||
llvm.module,
|
||||
symbolName,
|
||||
proto.llvmFunctionType
|
||||
).also {
|
||||
|
||||
+10
-11
@@ -252,15 +252,14 @@ internal fun getGlobalType(ptrToGlobal: LLVMValueRef): LLVMTypeRef {
|
||||
|
||||
internal fun ContextUtils.addGlobal(name: String, type: LLVMTypeRef, isExported: Boolean): LLVMValueRef {
|
||||
if (isExported)
|
||||
assert(LLVMGetNamedGlobal(context.llvmModule, name) == null)
|
||||
return LLVMAddGlobal(context.llvmModule, type, name)!!
|
||||
assert(LLVMGetNamedGlobal(llvm.module, name) == null)
|
||||
return LLVMAddGlobal(llvm.module, type, name)!!
|
||||
}
|
||||
|
||||
internal fun ContextUtils.importGlobal(name: String, type: LLVMTypeRef, origin: CompiledKlibModuleOrigin): LLVMValueRef {
|
||||
llvm.imports.add(origin)
|
||||
|
||||
context.llvm.imports.add(origin)
|
||||
|
||||
val found = LLVMGetNamedGlobal(context.llvmModule, name)
|
||||
val found = LLVMGetNamedGlobal(llvm.module, name)
|
||||
return if (found != null) {
|
||||
assert (getGlobalType(found) == type)
|
||||
assert (LLVMGetInitializer(found) == null) { "$name is already declared in the current module" }
|
||||
@@ -282,26 +281,26 @@ internal class TLSAddressAccess(
|
||||
private val context: Context, private val index: Int): AddressAccess() {
|
||||
|
||||
override fun getAddress(generationContext: FunctionGenerationContext?): LLVMValueRef {
|
||||
return generationContext!!.call(context.llvm.lookupTLS,
|
||||
listOf(context.llvm.tlsKey, Int32(index).llvm))
|
||||
return generationContext!!.call(context.generationState.llvm.lookupTLS,
|
||||
listOf(context.generationState.llvm.tlsKey, Int32(index).llvm))
|
||||
}
|
||||
}
|
||||
|
||||
internal fun ContextUtils.addKotlinThreadLocal(name: String, type: LLVMTypeRef): AddressAccess {
|
||||
return if (isObjectType(type)) {
|
||||
val index = context.llvm.tlsCount++
|
||||
val index = llvm.tlsCount++
|
||||
TLSAddressAccess(context, index)
|
||||
} else {
|
||||
// TODO: This will break if Workers get decoupled from host threads.
|
||||
GlobalAddressAccess(LLVMAddGlobal(context.llvmModule, type, name)!!.also {
|
||||
LLVMSetThreadLocalMode(it, context.llvm.tlsMode)
|
||||
GlobalAddressAccess(LLVMAddGlobal(llvm.module, type, name)!!.also {
|
||||
LLVMSetThreadLocalMode(it, llvm.tlsMode)
|
||||
LLVMSetLinkage(it, LLVMLinkage.LLVMInternalLinkage)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
internal fun ContextUtils.addKotlinGlobal(name: String, type: LLVMTypeRef, isExported: Boolean): AddressAccess {
|
||||
return GlobalAddressAccess(LLVMAddGlobal(context.llvmModule, type, name)!!.also {
|
||||
return GlobalAddressAccess(LLVMAddGlobal(llvm.module, type, name)!!.also {
|
||||
if (!isExported)
|
||||
LLVMSetLinkage(it, LLVMLinkage.LLVMInternalLinkage)
|
||||
})
|
||||
|
||||
+6
-6
@@ -200,7 +200,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
|
||||
val className = irClass.fqNameForIrSerialization
|
||||
|
||||
val llvmDeclarations = context.llvmDeclarations.forClass(irClass)
|
||||
val llvmDeclarations = context.generationState.llvmDeclarations.forClass(irClass)
|
||||
|
||||
val bodyType = llvmDeclarations.bodyType
|
||||
|
||||
@@ -390,7 +390,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
private val debugOperations: ConstValue by lazy {
|
||||
if (debugRuntimeOrNull != null) {
|
||||
val external = LLVMGetNamedGlobal(debugRuntimeOrNull, "Konan_debugOperationsList")!!
|
||||
val local = LLVMAddGlobal(context.llvmModule, LLVMGetElementType(LLVMTypeOf(external)),"Konan_debugOperationsList")!!
|
||||
val local = LLVMAddGlobal(llvm.module, LLVMGetElementType(LLVMTypeOf(external)),"Konan_debugOperationsList")!!
|
||||
constPointer(LLVMConstBitCast(local, kInt8PtrPtr)!!)
|
||||
} else {
|
||||
Zero(kInt8PtrPtr)
|
||||
@@ -411,7 +411,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
return NullPointer(runtime.extendedTypeInfoType)
|
||||
|
||||
val className = irClass.fqNameForIrSerialization.toString()
|
||||
val llvmDeclarations = context.llvmDeclarations.forClass(irClass)
|
||||
val llvmDeclarations = context.generationState.llvmDeclarations.forClass(irClass)
|
||||
val bodyType = llvmDeclarations.bodyType
|
||||
val elementType = getElementType(irClass)
|
||||
|
||||
@@ -577,16 +577,16 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
|
||||
when {
|
||||
irClass.isAnonymousObject -> {
|
||||
relativeName = context.getLocalClassName(irClass)
|
||||
relativeName = context.generationState.getLocalClassName(irClass)
|
||||
flags = 0 // Forbid to use package and relative names in KClass.[simpleName|qualifiedName].
|
||||
}
|
||||
irClass.isLocal -> {
|
||||
relativeName = context.getLocalClassName(irClass)
|
||||
relativeName = context.generationState.getLocalClassName(irClass)
|
||||
flags = TF_REFLECTION_SHOW_REL_NAME // Only allow relative name to be used in KClass.simpleName.
|
||||
}
|
||||
isLoweredFunctionReference(irClass) -> {
|
||||
// TODO: might return null so use fallback here, to be fixed in KT-47194
|
||||
relativeName = context.getLocalClassName(irClass) ?: generateDefaultRelativeName(irClass)
|
||||
relativeName = context.generationState.getLocalClassName(irClass) ?: generateDefaultRelativeName(irClass)
|
||||
flags = 0 // Forbid to use package and relative names in KClass.[simpleName|qualifiedName].
|
||||
}
|
||||
else -> {
|
||||
|
||||
+3
-3
@@ -30,7 +30,7 @@ internal class CoverageManager(val context: Context) {
|
||||
private val llvmProfileFilenameGlobal = "__llvm_profile_filename"
|
||||
|
||||
private val defaultOutputFilePath: String by lazy {
|
||||
"${context.config.outputFile}.profraw"
|
||||
"${context.generationState.outputFile}.profraw"
|
||||
}
|
||||
|
||||
private val outputFileName: String =
|
||||
@@ -124,8 +124,8 @@ internal class CoverageManager(val context: Context) {
|
||||
internal fun runCoveragePass(context: Context) {
|
||||
if (!context.coverage.enabled) return
|
||||
val passManager = LLVMCreatePassManager()!!
|
||||
LLVMKotlinAddTargetLibraryInfoWrapperPass(passManager, context.llvm.targetTriple)
|
||||
LLVMKotlinAddTargetLibraryInfoWrapperPass(passManager, context.generationState.llvm.targetTriple)
|
||||
context.coverage.addLateLlvmPasses(passManager)
|
||||
LLVMRunPassManager(passManager, context.llvmModule)
|
||||
LLVMRunPassManager(passManager, context.generationState.llvm.module)
|
||||
LLVMDisposePassManager(passManager)
|
||||
}
|
||||
+1
-1
@@ -41,7 +41,7 @@ internal class LLVMCoverageInstrumentation(
|
||||
val numberOfRegions = Int32(functionRegions.regions.size).llvm
|
||||
val regionNumber = Int32(functionRegions.regionEnumeration.getValue(region)).llvm
|
||||
val args = listOf(functionNameGlobal, functionHash, numberOfRegions, regionNumber)
|
||||
callSitePlacer(LLVMInstrProfIncrement(context.llvmModule)!!, args)
|
||||
callSitePlacer(LLVMInstrProfIncrement(context.generationState.llvm.module)!!, args)
|
||||
}
|
||||
|
||||
// Each profiled function should have a global with its name in a specific format.
|
||||
|
||||
+5
-6
@@ -30,7 +30,7 @@ private fun LLVMCoverageRegion.populateFrom(region: Region, regionId: Int, files
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes all of the coverage information to the [org.jetbrains.kotlin.backend.konan.Context.llvmModule].
|
||||
* Writes all of the coverage information to the [org.jetbrains.kotlin.backend.konan.NativeGenerationState.llvm.module].
|
||||
* See http://llvm.org/docs/CoverageMappingFormat.html for the format description.
|
||||
*/
|
||||
internal class LLVMCoverageWriter(
|
||||
@@ -40,8 +40,7 @@ internal class LLVMCoverageWriter(
|
||||
fun write() {
|
||||
if (filesRegionsInfo.isEmpty()) return
|
||||
|
||||
val module = context.llvmModule
|
||||
?: error("LLVM module should be initialized.")
|
||||
val module = context.generationState.llvm.module
|
||||
val filesIndex = filesRegionsInfo.mapIndexed { index, fileRegionInfo -> fileRegionInfo.file to index }.toMap()
|
||||
|
||||
val coverageGlobal = memScoped {
|
||||
@@ -54,8 +53,8 @@ internal class LLVMCoverageWriter(
|
||||
fileIds.toCValues(), fileIds.size.signExtend(),
|
||||
regions.toCValues(), regions.size.signExtend())
|
||||
|
||||
val functionName = context.llvmDeclarations.forFunction(functionRegions.function).llvmValue.name
|
||||
val functionMappingRecord = LLVMAddFunctionMappingRecord(LLVMGetModuleContext(context.llvmModule),
|
||||
val functionName = context.generationState.llvmDeclarations.forFunction(functionRegions.function).llvmValue.name
|
||||
val functionMappingRecord = LLVMAddFunctionMappingRecord(LLVMGetModuleContext(context.generationState.llvm.module),
|
||||
functionName, functionRegions.structuralHash, functionCoverage)!!
|
||||
|
||||
Pair(functionMappingRecord, functionCoverage)
|
||||
@@ -70,6 +69,6 @@ internal class LLVMCoverageWriter(
|
||||
|
||||
retval
|
||||
}
|
||||
context.llvm.usedGlobals.add(coverageGlobal)
|
||||
context.generationState.llvm.usedGlobals.add(coverageGlobal)
|
||||
}
|
||||
}
|
||||
|
||||
+6
-5
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||
|
||||
internal open class ObjCCodeGenerator(val codegen: CodeGenerator) {
|
||||
val context = codegen.context
|
||||
val llvm = codegen.llvm
|
||||
|
||||
val dataGenerator = codegen.objCDataGenerator!!
|
||||
|
||||
@@ -26,7 +27,7 @@ internal open class ObjCCodeGenerator(val codegen: CodeGenerator) {
|
||||
}
|
||||
|
||||
private val objcMsgSend = constPointer(
|
||||
context.llvm.externalFunction(LlvmFunctionProto(
|
||||
llvm.externalFunction(LlvmFunctionProto(
|
||||
"objc_msgSend",
|
||||
LlvmRetType(int8TypePtr),
|
||||
listOf(LlvmParamType(int8TypePtr), LlvmParamType(int8TypePtr)),
|
||||
@@ -43,17 +44,17 @@ internal open class ObjCCodeGenerator(val codegen: CodeGenerator) {
|
||||
listOf(LlvmFunctionAttribute.NoUnwind),
|
||||
origin = context.stdlibModule.llvmSymbolOrigin
|
||||
)
|
||||
context.llvm.externalFunction(proto)
|
||||
llvm.externalFunction(proto)
|
||||
}
|
||||
|
||||
val objcAlloc = context.llvm.externalFunction(LlvmFunctionProto(
|
||||
val objcAlloc = llvm.externalFunction(LlvmFunctionProto(
|
||||
"objc_alloc",
|
||||
LlvmRetType(int8TypePtr),
|
||||
listOf(LlvmParamType(int8TypePtr)),
|
||||
origin = context.stdlibModule.llvmSymbolOrigin
|
||||
))
|
||||
|
||||
val objcAutoreleaseReturnValue = context.llvm.externalFunction(LlvmFunctionProto(
|
||||
val objcAutoreleaseReturnValue = llvm.externalFunction(LlvmFunctionProto(
|
||||
"llvm.objc.autoreleaseReturnValue",
|
||||
LlvmRetType(int8TypePtr),
|
||||
listOf(LlvmParamType(int8TypePtr)),
|
||||
@@ -61,7 +62,7 @@ internal open class ObjCCodeGenerator(val codegen: CodeGenerator) {
|
||||
origin = context.stdlibModule.llvmSymbolOrigin
|
||||
))
|
||||
|
||||
val objcRetainAutoreleasedReturnValue = context.llvm.externalFunction(LlvmFunctionProto(
|
||||
val objcRetainAutoreleasedReturnValue = llvm.externalFunction(LlvmFunctionProto(
|
||||
"llvm.objc.retainAutoreleasedReturnValue",
|
||||
LlvmRetType(int8TypePtr),
|
||||
listOf(LlvmParamType(int8TypePtr)),
|
||||
|
||||
+16
-15
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.descriptors.konan.CurrentKlibModuleOrigin
|
||||
internal class ObjCDataGenerator(val codegen: CodeGenerator) {
|
||||
|
||||
val context = codegen.context
|
||||
val llvm = codegen.llvm
|
||||
|
||||
fun finishModule() {
|
||||
addModuleClassList(
|
||||
@@ -39,7 +40,7 @@ internal class ObjCDataGenerator(val codegen: CodeGenerator) {
|
||||
global.setAlignment(codegen.runtime.pointerAlignment)
|
||||
global.setSection("__DATA,__objc_selrefs,literal_pointers,no_dead_strip")
|
||||
|
||||
context.llvm.compilerUsedGlobals += global.llvmGlobal
|
||||
llvm.compilerUsedGlobals += global.llvmGlobal
|
||||
|
||||
global.pointer
|
||||
}
|
||||
@@ -52,7 +53,7 @@ internal class ObjCDataGenerator(val codegen: CodeGenerator) {
|
||||
it.setAlignment(codegen.runtime.pointerAlignment)
|
||||
}
|
||||
|
||||
context.llvm.compilerUsedGlobals += global.pointer.llvm
|
||||
llvm.compilerUsedGlobals += global.pointer.llvm
|
||||
|
||||
global.pointer.bitcast(pointerType(int8TypePtr))
|
||||
}
|
||||
@@ -60,8 +61,8 @@ internal class ObjCDataGenerator(val codegen: CodeGenerator) {
|
||||
private val classObjectType = codegen.runtime.objCClassObjectType
|
||||
|
||||
fun exportClass(name: String) {
|
||||
context.llvm.usedGlobals += getClassGlobal(name, isMetaclass = false).llvm
|
||||
context.llvm.usedGlobals += getClassGlobal(name, isMetaclass = true).llvm
|
||||
llvm.usedGlobals += getClassGlobal(name, isMetaclass = false).llvm
|
||||
llvm.usedGlobals += getClassGlobal(name, isMetaclass = true).llvm
|
||||
}
|
||||
|
||||
private fun getClassGlobal(name: String, isMetaclass: Boolean): ConstPointer {
|
||||
@@ -74,7 +75,7 @@ internal class ObjCDataGenerator(val codegen: CodeGenerator) {
|
||||
val globalName = prefix + name
|
||||
|
||||
// TODO: refactor usages and use [Global] class.
|
||||
val llvmGlobal = LLVMGetNamedGlobal(context.llvmModule, globalName) ?:
|
||||
val llvmGlobal = LLVMGetNamedGlobal(llvm.module, globalName) ?:
|
||||
codegen.importGlobal(globalName, classObjectType, CurrentKlibModuleOrigin)
|
||||
|
||||
return constPointer(llvmGlobal)
|
||||
@@ -95,7 +96,7 @@ internal class ObjCDataGenerator(val codegen: CodeGenerator) {
|
||||
class Method(val selector: String, val encoding: String, val imp: ConstPointer)
|
||||
|
||||
fun emitClass(name: String, superName: String, instanceMethods: List<Method>) {
|
||||
val runtime = context.llvm.runtime
|
||||
val runtime = llvm.runtime
|
||||
|
||||
val classRoType = runtime.objCClassRoType
|
||||
val methodType = runtime.objCMethodType
|
||||
@@ -120,13 +121,13 @@ internal class ObjCDataGenerator(val codegen: CodeGenerator) {
|
||||
)
|
||||
|
||||
val globalName = "\u0001l_OBJC_\$_INSTANCE_METHODS_$name"
|
||||
val global = context.llvm.staticData.placeGlobal(globalName, methodList).also {
|
||||
val global = llvm.staticData.placeGlobal(globalName, methodList).also {
|
||||
it.setLinkage(LLVMLinkage.LLVMPrivateLinkage)
|
||||
it.setAlignment(runtime.pointerAlignment)
|
||||
it.setSection("__DATA, __objc_const")
|
||||
}
|
||||
|
||||
context.llvm.compilerUsedGlobals += global.llvmGlobal
|
||||
llvm.compilerUsedGlobals += global.llvmGlobal
|
||||
|
||||
return global.pointer.bitcast(pointerType(methodListType))
|
||||
}
|
||||
@@ -169,7 +170,7 @@ internal class ObjCDataGenerator(val codegen: CodeGenerator) {
|
||||
"\u0001l_OBJC_CLASS_RO_\$_"
|
||||
} + name
|
||||
|
||||
val roGlobal = context.llvm.staticData.placeGlobal(roLabel, roValue).also {
|
||||
val roGlobal = llvm.staticData.placeGlobal(roLabel, roValue).also {
|
||||
it.setLinkage(LLVMLinkage.LLVMPrivateLinkage)
|
||||
it.setAlignment(runtime.pointerAlignment)
|
||||
it.setSection("__DATA, __objc_const")
|
||||
@@ -200,7 +201,7 @@ internal class ObjCDataGenerator(val codegen: CodeGenerator) {
|
||||
LLVMSetSection(classGlobal.llvm, "__DATA, __objc_data")
|
||||
LLVMSetAlignment(classGlobal.llvm, LLVMABIAlignmentOfType(runtime.targetData, classObjectType))
|
||||
|
||||
context.llvm.usedGlobals.add(classGlobal.llvm)
|
||||
llvm.usedGlobals.add(classGlobal.llvm)
|
||||
|
||||
return classGlobal
|
||||
}
|
||||
@@ -227,7 +228,7 @@ internal class ObjCDataGenerator(val codegen: CodeGenerator) {
|
||||
private fun addModuleClassList(elements: List<ConstPointer>, name: String, section: String) {
|
||||
if (elements.isEmpty()) return
|
||||
|
||||
val global = context.llvm.staticData.placeGlobalArray(
|
||||
val global = llvm.staticData.placeGlobalArray(
|
||||
name,
|
||||
int8TypePtr,
|
||||
elements.map { it.bitcast(int8TypePtr) }
|
||||
@@ -235,14 +236,14 @@ internal class ObjCDataGenerator(val codegen: CodeGenerator) {
|
||||
|
||||
global.setAlignment(
|
||||
LLVMABIAlignmentOfType(
|
||||
context.llvm.runtime.targetData,
|
||||
llvm.runtime.targetData,
|
||||
LLVMGetInitializer(global.llvmGlobal)!!.type
|
||||
)
|
||||
)
|
||||
|
||||
global.setSection(section)
|
||||
|
||||
context.llvm.compilerUsedGlobals += global.llvmGlobal
|
||||
llvm.compilerUsedGlobals += global.llvmGlobal
|
||||
}
|
||||
|
||||
private val classNames = CStringLiteralsTable(classNameGenerator)
|
||||
@@ -256,8 +257,8 @@ internal class ObjCDataGenerator(val codegen: CodeGenerator) {
|
||||
private val literals = mutableMapOf<String, ConstPointer>()
|
||||
|
||||
fun get(value: String) = literals.getOrPut(value) {
|
||||
val globalPointer = generator.generate(context.llvmModule!!, value)
|
||||
context.llvm.compilerUsedGlobals += globalPointer.llvm
|
||||
val globalPointer = generator.generate(llvm.module, value)
|
||||
llvm.compilerUsedGlobals += globalPointer.llvm
|
||||
globalPointer.getElementPtr(0)
|
||||
}
|
||||
}
|
||||
|
||||
+11
-11
@@ -42,7 +42,7 @@ internal fun ObjCExportCodeGeneratorBase.generateBlockToKotlinFunctionConverter(
|
||||
thisRef
|
||||
}
|
||||
val blockPtr = callFromBridge(
|
||||
context.llvm.Kotlin_ObjCExport_GetAssociatedObject,
|
||||
llvm.Kotlin_ObjCExport_GetAssociatedObject,
|
||||
listOf(associatedObjectHolder)
|
||||
)
|
||||
|
||||
@@ -133,7 +133,7 @@ private fun FunctionGenerationContext.allocInstanceWithAssociatedObject(
|
||||
associatedObject: LLVMValueRef,
|
||||
resultLifetime: Lifetime
|
||||
): LLVMValueRef = call(
|
||||
context.llvm.Kotlin_ObjCExport_AllocInstanceWithAssociatedObject,
|
||||
llvm.Kotlin_ObjCExport_AllocInstanceWithAssociatedObject,
|
||||
listOf(typeInfo.llvm, associatedObject),
|
||||
resultLifetime
|
||||
)
|
||||
@@ -170,7 +170,7 @@ internal class BlockGenerator(private val codegen: CodeGenerator) {
|
||||
) {
|
||||
val blockPtr = bitcast(pointerType(blockLiteralType), param(0))
|
||||
val refHolder = structGep(blockPtr, 1)
|
||||
call(context.llvm.kRefSharedHolderDispose, listOf(refHolder))
|
||||
call(llvm.kRefSharedHolderDispose, listOf(refHolder))
|
||||
|
||||
ret(null)
|
||||
}.also {
|
||||
@@ -192,20 +192,20 @@ internal class BlockGenerator(private val codegen: CodeGenerator) {
|
||||
// so it is technically not necessary to check owner.
|
||||
// However this is not guaranteed by Objective-C runtime, so keep it suboptimal but reliable:
|
||||
val ref = call(
|
||||
context.llvm.kRefSharedHolderRef,
|
||||
llvm.kRefSharedHolderRef,
|
||||
listOf(srcRefHolder),
|
||||
exceptionHandler = ExceptionHandler.Caller,
|
||||
verbatim = true
|
||||
)
|
||||
|
||||
call(context.llvm.kRefSharedHolderInit, listOf(dstRefHolder, ref))
|
||||
call(llvm.kRefSharedHolderInit, listOf(dstRefHolder, ref))
|
||||
|
||||
ret(null)
|
||||
}.also {
|
||||
LLVMSetLinkage(it, LLVMLinkage.LLVMInternalLinkage)
|
||||
}
|
||||
|
||||
fun org.jetbrains.kotlin.backend.konan.Context.LongInt(value: Long) =
|
||||
fun CodeGenerator.LongInt(value: Long) =
|
||||
when (val longWidth = llvm.longTypeWidth) {
|
||||
32L -> Int32(value.toInt())
|
||||
64L -> Int64(value)
|
||||
@@ -231,8 +231,8 @@ internal class BlockGenerator(private val codegen: CodeGenerator) {
|
||||
}
|
||||
|
||||
return Struct(codegen.runtime.blockDescriptorType,
|
||||
codegen.context.LongInt(0L),
|
||||
codegen.context.LongInt(LLVMStoreSizeOfType(codegen.runtime.targetData, blockLiteralType)),
|
||||
codegen.LongInt(0L),
|
||||
codegen.LongInt(LLVMStoreSizeOfType(codegen.runtime.targetData, blockLiteralType)),
|
||||
constPointer(copyHelper),
|
||||
constPointer(disposeHelper),
|
||||
codegen.staticData.cStringLiteral(signature),
|
||||
@@ -251,7 +251,7 @@ internal class BlockGenerator(private val codegen: CodeGenerator) {
|
||||
}.generate {
|
||||
val blockPtr = bitcast(pointerType(blockLiteralType), param(0))
|
||||
val kotlinObject = call(
|
||||
context.llvm.kRefSharedHolderRef,
|
||||
llvm.kRefSharedHolderRef,
|
||||
listOf(structGep(blockPtr, 1)),
|
||||
exceptionHandler = ExceptionHandler.Caller,
|
||||
verbatim = true
|
||||
@@ -334,7 +334,7 @@ internal class BlockGenerator(private val codegen: CodeGenerator) {
|
||||
store(value, structGep(blockOnStackBase, index))
|
||||
}
|
||||
|
||||
call(context.llvm.kRefSharedHolderInitLocal, listOf(refHolder, kotlinRef))
|
||||
call(llvm.kRefSharedHolderInitLocal, listOf(refHolder, kotlinRef))
|
||||
|
||||
val copiedBlock = callFromBridge(retainBlock, listOf(bitcast(int8TypePtr, blockOnStack)))
|
||||
|
||||
@@ -353,5 +353,5 @@ private val ObjCExportCodeGeneratorBase.retainBlock: LlvmCallable
|
||||
listOf(LlvmParamType(int8TypePtr)),
|
||||
origin = CurrentKlibModuleOrigin
|
||||
)
|
||||
return context.llvm.externalFunction(functionProto)
|
||||
return llvm.externalFunction(functionProto)
|
||||
}
|
||||
+23
-23
@@ -218,7 +218,7 @@ internal open class ObjCExportCodeGeneratorBase(codegen: CodeGenerator) : ObjCCo
|
||||
val rttiGenerator = RTTIGenerator(context)
|
||||
|
||||
private val objcTerminate: LlvmCallable by lazy {
|
||||
context.llvm.externalFunction(LlvmFunctionProto(
|
||||
llvm.externalFunction(LlvmFunctionProto(
|
||||
"objc_terminate",
|
||||
LlvmRetType(voidType),
|
||||
functionAttributes = listOf(LlvmFunctionAttribute.NoUnwind),
|
||||
@@ -255,13 +255,13 @@ internal open class ObjCExportCodeGeneratorBase(codegen: CodeGenerator) : ObjCCo
|
||||
}
|
||||
|
||||
fun ObjCExportFunctionGenerationContext.kotlinReferenceToLocalObjC(value: LLVMValueRef) =
|
||||
callFromBridge(context.llvm.Kotlin_ObjCExport_refToLocalObjC, listOf(value))
|
||||
callFromBridge(llvm.Kotlin_ObjCExport_refToLocalObjC, listOf(value))
|
||||
|
||||
fun ObjCExportFunctionGenerationContext.kotlinReferenceToRetainedObjC(value: LLVMValueRef) =
|
||||
callFromBridge(context.llvm.Kotlin_ObjCExport_refToRetainedObjC, listOf(value))
|
||||
callFromBridge(llvm.Kotlin_ObjCExport_refToRetainedObjC, listOf(value))
|
||||
|
||||
fun ObjCExportFunctionGenerationContext.objCReferenceToKotlin(value: LLVMValueRef, resultLifetime: Lifetime) =
|
||||
callFromBridge(context.llvm.Kotlin_ObjCExport_refFromObjC, listOf(value), resultLifetime)
|
||||
callFromBridge(llvm.Kotlin_ObjCExport_refFromObjC, listOf(value), resultLifetime)
|
||||
|
||||
private val blockToKotlinFunctionConverterCache = mutableMapOf<BlockPointerBridge, LLVMValueRef>()
|
||||
|
||||
@@ -536,7 +536,7 @@ internal class ObjCExportCodeGenerator(
|
||||
|
||||
LLVMSetLinkage(initializer, LLVMLinkage.LLVMInternalLinkage)
|
||||
|
||||
context.llvm.otherStaticInitializers += initializer
|
||||
llvm.otherStaticInitializers += initializer
|
||||
}
|
||||
|
||||
private fun emitKt42254Hint() {
|
||||
@@ -551,7 +551,7 @@ internal class ObjCExportCodeGenerator(
|
||||
val name = "See https://youtrack.jetbrains.com/issue/KT-42254"
|
||||
val global = staticData.placeGlobal(name, Int8(0), isExported = true)
|
||||
|
||||
context.llvm.usedGlobals += global.llvmGlobal
|
||||
llvm.usedGlobals += global.llvmGlobal
|
||||
LLVMSetVisibility(global.llvmGlobal, LLVMVisibility.LLVMHiddenVisibility)
|
||||
}
|
||||
}
|
||||
@@ -693,13 +693,13 @@ private fun ObjCExportCodeGenerator.replaceExternalWeakOrCommonGlobal(
|
||||
val global = codegen.importGlobal(name, value.llvmType, origin)
|
||||
externalGlobalInitializers[global] = value
|
||||
} else {
|
||||
context.llvmImports.add(origin)
|
||||
context.generationState.llvmImports.add(origin)
|
||||
val global = staticData.placeGlobal(name, value, isExported = true)
|
||||
|
||||
if (context.llvmModuleSpecification.importsKotlinDeclarationsFromOtherObjectFiles()) {
|
||||
// Note: actually this is required only if global's weak/common definition is in another object file,
|
||||
// but it is simpler to do this for all globals, considering that all usages can't be removed by DCE anyway.
|
||||
context.llvm.usedGlobals += global.llvmGlobal
|
||||
llvm.usedGlobals += global.llvmGlobal
|
||||
LLVMSetVisibility(global.llvmGlobal, LLVMVisibility.LLVMHiddenVisibility)
|
||||
|
||||
// See also [emitKt42254Hint].
|
||||
@@ -733,7 +733,7 @@ private fun ObjCExportCodeGenerator.setObjCExportTypeInfo(
|
||||
|
||||
private fun ObjCExportCodeGeneratorBase.setOwnWritableTypeInfo(irClass: IrClass, writableTypeInfoValue: Struct) {
|
||||
require(!codegen.isExternal(irClass))
|
||||
val writeableTypeInfoGlobal = context.llvmDeclarations.forClass(irClass).writableTypeInfoGlobal!!
|
||||
val writeableTypeInfoGlobal = context.generationState.llvmDeclarations.forClass(irClass).writableTypeInfoGlobal!!
|
||||
writeableTypeInfoGlobal.setLinkage(LLVMLinkage.LLVMExternalLinkage)
|
||||
writeableTypeInfoGlobal.setInitializer(writableTypeInfoValue)
|
||||
}
|
||||
@@ -828,7 +828,7 @@ private fun ObjCExportCodeGenerator.generateContinuationToRetainedCompletionConv
|
||||
val resultArgument = objCReferenceToKotlin(arguments[0], Lifetime.ARGUMENT)
|
||||
val errorArgument = arguments[1]
|
||||
|
||||
callFromBridge(context.llvm.Kotlin_ObjCExport_resumeContinuation, listOf(continuation, resultArgument, errorArgument))
|
||||
callFromBridge(llvm.Kotlin_ObjCExport_resumeContinuation, listOf(continuation, resultArgument, errorArgument))
|
||||
ret(null)
|
||||
}
|
||||
}
|
||||
@@ -848,7 +848,7 @@ private fun ObjCExportCodeGenerator.generateUnitContinuationToRetainedCompletion
|
||||
codegen.theUnitInstanceRef.llvm
|
||||
}
|
||||
|
||||
callFromBridge(context.llvm.Kotlin_ObjCExport_resumeContinuation, listOf(continuation, resultArgument, errorArgument))
|
||||
callFromBridge(llvm.Kotlin_ObjCExport_resumeContinuation, listOf(continuation, resultArgument, errorArgument))
|
||||
ret(null)
|
||||
}
|
||||
}
|
||||
@@ -896,7 +896,7 @@ private fun ObjCExportBlockCodeGenerator.emitBlockToKotlinFunctionConverters() {
|
||||
private fun ObjCExportCodeGenerator.emitSpecialClassesConvertions() {
|
||||
setObjCExportTypeInfo(
|
||||
symbols.string.owner,
|
||||
constPointer(context.llvm.Kotlin_ObjCExport_CreateRetainedNSStringFromKString.llvmValue)
|
||||
constPointer(llvm.Kotlin_ObjCExport_CreateRetainedNSStringFromKString.llvmValue)
|
||||
)
|
||||
|
||||
emitCollectionConverters()
|
||||
@@ -906,7 +906,7 @@ private fun ObjCExportCodeGenerator.emitSpecialClassesConvertions() {
|
||||
|
||||
private fun ObjCExportCodeGenerator.emitCollectionConverters() {
|
||||
|
||||
fun importConverter(name: String): ConstPointer = constPointer(context.llvm.externalFunction(LlvmFunctionProto(
|
||||
fun importConverter(name: String): ConstPointer = constPointer(llvm.externalFunction(LlvmFunctionProto(
|
||||
name,
|
||||
kotlinToObjCFunctionType,
|
||||
origin = CurrentKlibModuleOrigin
|
||||
@@ -974,7 +974,7 @@ private inline fun ObjCExportCodeGenerator.generateObjCImpBy(
|
||||
private fun ObjCExportCodeGenerator.generateAbstractObjCImp(methodBridge: MethodBridge, baseMethod: IrFunction): LLVMValueRef =
|
||||
generateObjCImpBy(methodBridge, suffix = baseMethod.computeSymbolName()) {
|
||||
callFromBridge(
|
||||
context.llvm.Kotlin_ObjCExport_AbstractMethodCalled,
|
||||
llvm.Kotlin_ObjCExport_AbstractMethodCalled,
|
||||
listOf(param(0), param(1))
|
||||
)
|
||||
unreachable()
|
||||
@@ -996,7 +996,7 @@ private fun ObjCExportCodeGenerator.generateObjCImp(
|
||||
) { args, resultLifetime, exceptionHandler ->
|
||||
if (target is IrConstructor && target.constructedClass.isAbstract()) {
|
||||
callFromBridge(
|
||||
context.llvm.Kotlin_ObjCExport_AbstractClassConstructorCalled,
|
||||
llvm.Kotlin_ObjCExport_AbstractClassConstructorCalled,
|
||||
listOf(param(0), codegen.typeInfoValue(target.parent as IrClass))
|
||||
)
|
||||
}
|
||||
@@ -1060,9 +1060,9 @@ private fun ObjCExportCodeGenerator.generateObjCImp(
|
||||
|
||||
is MethodBridgeValueParameter.SuspendCompletion -> {
|
||||
val createContinuationArgument = if (paramBridge.useUnitCompletion) {
|
||||
context.llvm.Kotlin_ObjCExport_createUnitContinuationArgument
|
||||
llvm.Kotlin_ObjCExport_createUnitContinuationArgument
|
||||
} else {
|
||||
context.llvm.Kotlin_ObjCExport_createContinuationArgument
|
||||
llvm.Kotlin_ObjCExport_createContinuationArgument
|
||||
}
|
||||
callFromBridge(
|
||||
createContinuationArgument,
|
||||
@@ -1079,7 +1079,7 @@ private fun ObjCExportCodeGenerator.generateObjCImp(
|
||||
val exceptionHandler = when {
|
||||
errorOutPtr != null -> kotlinExceptionHandler { exception ->
|
||||
callFromBridge(
|
||||
context.llvm.Kotlin_ObjCExport_RethrowExceptionAsNSError,
|
||||
llvm.Kotlin_ObjCExport_RethrowExceptionAsNSError,
|
||||
listOf(exception, errorOutPtr!!, generateExceptionTypeInfoArray(baseMethod!!))
|
||||
)
|
||||
|
||||
@@ -1209,7 +1209,7 @@ private fun ObjCExportCodeGenerator.generateObjCImpForArrayConstructor(
|
||||
methodBridge: MethodBridge
|
||||
): LLVMValueRef = generateObjCImp(methodBridge, bridgeSuffix = target.computeSymbolName(), isDirect = true) { args, resultLifetime, exceptionHandler ->
|
||||
val arrayInstance = callFromBridge(
|
||||
context.llvm.allocArrayFunction,
|
||||
llvm.allocArrayFunction,
|
||||
listOf(target.constructedClass.llvmTypeInfoPtr, args.first()),
|
||||
resultLifetime = Lifetime.ARGUMENT
|
||||
)
|
||||
@@ -1336,7 +1336,7 @@ private fun ObjCExportCodeGenerator.generateKotlinToObjCBridge(
|
||||
fun rethrow() {
|
||||
val error = load(errorOutPtr!!)
|
||||
val exception = callFromBridge(
|
||||
context.llvm.Kotlin_ObjCExport_NSErrorAsException,
|
||||
llvm.Kotlin_ObjCExport_NSErrorAsException,
|
||||
listOf(error),
|
||||
resultLifetime = Lifetime.THROW
|
||||
)
|
||||
@@ -1887,7 +1887,7 @@ private fun ObjCExportCodeGenerator.createUnitInstanceAdapter(selector: String)
|
||||
// Note: generateObjCToKotlinSyntheticGetter switches to Runnable, which is probably not required here and thus suboptimal.
|
||||
initRuntimeIfNeeded() // For instance methods it gets called when allocating.
|
||||
|
||||
autoreleaseAndRet(callFromBridge(context.llvm.Kotlin_ObjCExport_convertUnitToRetained, listOf(codegen.theUnitInstanceRef.llvm)))
|
||||
autoreleaseAndRet(callFromBridge(llvm.Kotlin_ObjCExport_convertUnitToRetained, listOf(codegen.theUnitInstanceRef.llvm)))
|
||||
}
|
||||
|
||||
private fun ObjCExportCodeGenerator.createObjectInstanceAdapter(
|
||||
@@ -1942,7 +1942,7 @@ private fun ObjCExportCodeGenerator.createThrowableAsErrorAdapter(): ObjCExportC
|
||||
|
||||
val imp = generateObjCImpBy(methodBridge, suffix = "ThrowableAsError") {
|
||||
val exception = objCReferenceToKotlin(param(0), Lifetime.ARGUMENT)
|
||||
ret(callFromBridge(context.llvm.Kotlin_ObjCExport_WrapExceptionToNSError, listOf(exception)))
|
||||
ret(callFromBridge(llvm.Kotlin_ObjCExport_WrapExceptionToNSError, listOf(exception)))
|
||||
}
|
||||
|
||||
val selector = ObjCExportNamer.kotlinThrowableAsErrorMethodName
|
||||
@@ -2045,5 +2045,5 @@ private fun Context.is64BitNSInteger(): Boolean {
|
||||
require(configurables is AppleConfigurables) {
|
||||
"Target ${configurables.target} has no support for NSInteger type."
|
||||
}
|
||||
return llvm.nsIntegerTypeWidth == 64L
|
||||
return generationState.llvm.nsIntegerTypeWidth == 64L
|
||||
}
|
||||
|
||||
+6
-4
@@ -32,7 +32,7 @@ internal class CacheInfoBuilder(private val context: Context, private val module
|
||||
if (!declaration.isInterface && !declaration.isLocal
|
||||
&& declaration.isExported && declaration.origin != DECLARATION_ORIGIN_FUNCTION_CLASS
|
||||
) {
|
||||
context.classFields.add(buildClassFields(declaration, context.getLayoutBuilder(declaration).getDeclaredFields()))
|
||||
context.generationState.classFields.add(buildClassFields(declaration, context.getLayoutBuilder(declaration).getDeclaredFields()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ internal class CacheInfoBuilder(private val context: Context, private val module
|
||||
// as for functions - both their callees will be handled and inline bodies will be built for the top function.
|
||||
|
||||
if (!declaration.isFakeOverride && declaration.isInline && declaration.isExported) {
|
||||
context.inlineFunctionBodies.add(buildInlineFunctionReference(declaration))
|
||||
context.generationState.inlineFunctionBodies.add(buildInlineFunctionReference(declaration))
|
||||
trackCallees(declaration)
|
||||
}
|
||||
}
|
||||
@@ -64,8 +64,10 @@ internal class CacheInfoBuilder(private val context: Context, private val module
|
||||
|
||||
private fun processFunction(function: IrFunction) {
|
||||
if (function.getPackageFragment() !is IrExternalPackageFragment) {
|
||||
context.calledFromExportedInlineFunctions.add(function)
|
||||
(function as? IrConstructor)?.constructedClass?.let { context.constructedFromExportedInlineFunctions.add(it) }
|
||||
context.generationState.calledFromExportedInlineFunctions.add(function)
|
||||
(function as? IrConstructor)?.constructedClass?.let {
|
||||
context.generationState.constructedFromExportedInlineFunctions.add(it)
|
||||
}
|
||||
if (function.isInline && !function.isExported) {
|
||||
// An exported inline function calls a non-exported inline function:
|
||||
// should track its callees as well as it won't be handled by the main visitor.
|
||||
|
||||
+5
-4
@@ -199,6 +199,7 @@ internal class ExportCachesAbiVisitor(val context: Context) : FileLoweringPass,
|
||||
internal class ImportCachesAbiTransformer(val context: Context) : FileLoweringPass, IrElementTransformerVoid() {
|
||||
private val cachesAbiSupport = context.cachesAbiSupport
|
||||
private val enumsSupport = context.enumsSupport
|
||||
private val llvmImports = context.generationState.llvmImports
|
||||
|
||||
override fun lower(irFile: IrFile) {
|
||||
irFile.transformChildrenVoid(this)
|
||||
@@ -217,7 +218,7 @@ internal class ImportCachesAbiTransformer(val context: Context) : FileLoweringPa
|
||||
return expression
|
||||
}
|
||||
val accessor = cachesAbiSupport.getCompanionObjectAccessor(irClass)
|
||||
context.llvmImports.add(irClass.llvmSymbolOrigin)
|
||||
llvmImports.add(irClass.llvmSymbolOrigin)
|
||||
return irCall(expression.startOffset, expression.endOffset, accessor, emptyList())
|
||||
}
|
||||
|
||||
@@ -233,7 +234,7 @@ internal class ImportCachesAbiTransformer(val context: Context) : FileLoweringPa
|
||||
|
||||
irClass?.isInner == true && context.innerClassesSupport.getOuterThisField(irClass) == field -> {
|
||||
val accessor = cachesAbiSupport.getOuterThisAccessor(irClass)
|
||||
context.llvmImports.add(irClass.llvmSymbolOrigin)
|
||||
llvmImports.add(irClass.llvmSymbolOrigin)
|
||||
return irCall(expression.startOffset, expression.endOffset, accessor, emptyList()).apply {
|
||||
putValueArgument(0, expression.receiver)
|
||||
}
|
||||
@@ -241,7 +242,7 @@ internal class ImportCachesAbiTransformer(val context: Context) : FileLoweringPa
|
||||
|
||||
property?.isLateinit == true -> {
|
||||
val accessor = cachesAbiSupport.getLateinitPropertyAccessor(property)
|
||||
context.llvmImports.add(property.llvmSymbolOrigin)
|
||||
llvmImports.add(property.llvmSymbolOrigin)
|
||||
return irCall(expression.startOffset, expression.endOffset, accessor, emptyList()).apply {
|
||||
if (irClass != null)
|
||||
putValueArgument(0, expression.receiver)
|
||||
@@ -255,7 +256,7 @@ internal class ImportCachesAbiTransformer(val context: Context) : FileLoweringPa
|
||||
require(enumsSupport.getImplObject(enumClass) == irClass) { "Expected a enum's impl object: ${irClass.render()}" }
|
||||
require(field == enumsSupport.getValuesField(irClass)) { "Expected VALUES field: ${field.render()}" }
|
||||
val accessor = cachesAbiSupport.getEnumValuesAccessor(enumClass)
|
||||
context.llvmImports.add(enumClass.llvmSymbolOrigin)
|
||||
llvmImports.add(enumClass.llvmSymbolOrigin)
|
||||
return irCall(expression.startOffset, expression.endOffset, accessor, emptyList())
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -223,7 +223,7 @@ internal class FunctionReferenceLowering(val context: Context) : FileLoweringPas
|
||||
createParameterDeclarations()
|
||||
|
||||
// copy the generated name for IrClass, partially solves KT-47194
|
||||
context.copyLocalClassName(functionReference, this)
|
||||
context.generationState.copyLocalClassName(functionReference, this)
|
||||
}
|
||||
|
||||
private val functionReferenceThis = functionReferenceClass.thisReceiver!!
|
||||
|
||||
+4
-5
@@ -6,7 +6,6 @@
|
||||
package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.*
|
||||
import org.jetbrains.kotlin.backend.common.ir.*
|
||||
import org.jetbrains.kotlin.backend.common.lower.*
|
||||
import org.jetbrains.kotlin.backend.konan.*
|
||||
import org.jetbrains.kotlin.backend.konan.cgen.*
|
||||
@@ -98,11 +97,11 @@ private abstract class BaseInteropIrTransformer(private val context: Context) :
|
||||
}
|
||||
|
||||
override fun addC(lines: List<String>) {
|
||||
context.cStubsManager.addStub(location, lines, language)
|
||||
context.generationState.cStubsManager.addStub(location, lines, language)
|
||||
}
|
||||
|
||||
override fun getUniqueCName(prefix: String) =
|
||||
"$uniquePrefix${context.cStubsManager.getUniqueName(prefix)}"
|
||||
"$uniquePrefix${context.generationState.cStubsManager.getUniqueName(prefix)}"
|
||||
|
||||
override fun getUniqueKotlinFunctionReferenceClassName(prefix: String) =
|
||||
"$prefix${context.functionReferenceCount++}"
|
||||
@@ -538,7 +537,7 @@ private class InteropLoweringPart1(val context: Context) : BaseInteropIrTransfor
|
||||
): IrExpression = generateWithStubs(call) {
|
||||
if (method.parent !is IrClass) {
|
||||
// Category-provided.
|
||||
this@InteropLoweringPart1.context.llvmImports.add(method.llvmSymbolOrigin)
|
||||
this@InteropLoweringPart1.context.generationState.llvmImports.add(method.llvmSymbolOrigin)
|
||||
}
|
||||
|
||||
this.generateObjCCall(
|
||||
@@ -1002,7 +1001,7 @@ private class InteropTransformer(val context: Context, override val irFile: IrFi
|
||||
private fun generateCCall(expression: IrCall): IrExpression {
|
||||
val function = expression.symbol.owner
|
||||
|
||||
context.llvmImports.add(function.llvmSymbolOrigin)
|
||||
context.generationState.llvmImports.add(function.llvmSymbolOrigin)
|
||||
val exceptionMode = ForeignExceptionMode.byValue(
|
||||
function.konanLibrary?.manifestProperties?.getProperty(ForeignExceptionMode.manifestKey)
|
||||
)
|
||||
|
||||
+4
-6
@@ -15,10 +15,8 @@ import org.jetbrains.kotlin.ir.declarations.IrExternalPackageFragment
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.deepCopyWithVariables
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
internal class InlineFunctionsSupport(mapping: NativeMapping) {
|
||||
private val notLoweredInlineFunctions = mapping.notLoweredInlineFunctions
|
||||
@@ -43,12 +41,12 @@ internal class NativeInlineFunctionResolver(override val context: Context) : Def
|
||||
override fun getFunctionDeclaration(symbol: IrFunctionSymbol): IrFunction {
|
||||
val function = super.getFunctionDeclaration(symbol)
|
||||
|
||||
context.mapping.loweredInlineFunctions[function]?.let { return it.irFunction }
|
||||
context.generationState.loweredInlineFunctions[function]?.let { return it.irFunction }
|
||||
|
||||
val packageFragment = function.getPackageFragment()
|
||||
val (possiblyLoweredFunction, shouldLower) = if (packageFragment !is IrExternalPackageFragment) {
|
||||
context.inlineFunctionsSupport.getNonLoweredInlineFunction(function, copy = context.config.produceBatchedPerFileCache).also {
|
||||
context.mapping.loweredInlineFunctions[function] =
|
||||
context.generationState.loweredInlineFunctions[function] =
|
||||
InlineFunctionOriginInfo(it, packageFragment as IrFile, function.startOffset, function.endOffset)
|
||||
} to true
|
||||
} else {
|
||||
@@ -60,7 +58,7 @@ internal class NativeInlineFunctionResolver(override val context: Context) : Def
|
||||
"No IR and no cache for ${function.render()}"
|
||||
}
|
||||
val (shouldLower, deserializedInlineFunction) = moduleDeserializer.deserializeInlineFunction(function)
|
||||
context.mapping.loweredInlineFunctions[function] = deserializedInlineFunction
|
||||
context.generationState.loweredInlineFunctions[function] = deserializedInlineFunction
|
||||
function to shouldLower
|
||||
}
|
||||
|
||||
@@ -68,7 +66,7 @@ internal class NativeInlineFunctionResolver(override val context: Context) : Def
|
||||
|
||||
val body = possiblyLoweredFunction.body ?: return possiblyLoweredFunction
|
||||
|
||||
PreInlineLowering(context).lower(body, possiblyLoweredFunction, context.mapping.loweredInlineFunctions[function]!!.irFile)
|
||||
PreInlineLowering(context).lower(body, possiblyLoweredFunction, context.generationState.loweredInlineFunctions[function]!!.irFile)
|
||||
|
||||
ArrayConstructorLowering(context).lower(body, possiblyLoweredFunction)
|
||||
|
||||
|
||||
+1
-1
@@ -16,6 +16,6 @@ internal class NativeInventNamesForLocalClasses(val context: Context) : InventNa
|
||||
override fun sanitizeNameIfNeeded(name: String) = name
|
||||
|
||||
override fun putLocalClassName(declaration: IrAttributeContainer, localClassName: String) {
|
||||
context.putLocalClassName(declaration, localClassName)
|
||||
context.generationState.putLocalClassName(declaration, localClassName)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -642,7 +642,7 @@ internal class TestProcessor (val context: Context) {
|
||||
|
||||
fun recordFunction(suiteClassId: ClassId, function: TestFunction) {
|
||||
if (function.kind == FunctionKind.TEST)
|
||||
context.testCasesToDump.computeIfAbsent(suiteClassId) { mutableListOf() } += function.functionName
|
||||
context.generationState.testCasesToDump.computeIfAbsent(suiteClassId) { mutableListOf() } += function.functionName
|
||||
}
|
||||
|
||||
annotationCollector.topLevelFunctions.forEach { function ->
|
||||
|
||||
+2
-2
@@ -112,7 +112,7 @@ internal class ObjCExport(val context: Context, symbolTable: SymbolTable) {
|
||||
}
|
||||
|
||||
private fun produceFrameworkSpecific(headerLines: List<String>) {
|
||||
val framework = File(context.config.outputFile)
|
||||
val framework = File(context.generationState.outputFile)
|
||||
val frameworkContents = when(target.family) {
|
||||
Family.IOS,
|
||||
Family.WATCHOS,
|
||||
@@ -293,7 +293,7 @@ internal class ObjCExport(val context: Context, symbolTable: SymbolTable) {
|
||||
val result = Command(clangCommand).getResult(withErrors = true)
|
||||
|
||||
if (result.exitCode == 0) {
|
||||
context.llvm.additionalProducedBitcodeFiles += bitcode.absolutePath
|
||||
context.generationState.llvm.additionalProducedBitcodeFiles += bitcode.absolutePath
|
||||
} else {
|
||||
// Note: ignoring compile errors intentionally.
|
||||
// In this case resulting framework will likely be unusable due to compile errors when importing it.
|
||||
|
||||
+1
-2
@@ -16,7 +16,6 @@ import org.jetbrains.kotlin.backend.konan.llvm.Lifetime
|
||||
import org.jetbrains.kotlin.backend.konan.logMultiple
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import kotlin.math.min
|
||||
|
||||
private val DataFlowIR.Node.isAlloc
|
||||
get() = this is DataFlowIR.Node.NewObject || this is DataFlowIR.Node.AllocInstance
|
||||
@@ -642,7 +641,7 @@ internal object EscapeAnalysis {
|
||||
?: (node as? DataFlowIR.Node.Variable)
|
||||
?.values?.singleOrNull()?.let { arrayLengthOf(it.node) }
|
||||
|
||||
private val pointerSize = context.llvm.runtime.pointerSize
|
||||
private val pointerSize = context.generationState.runtime.pointerSize
|
||||
|
||||
private fun arrayItemSizeOf(irClass: IrClass): Int? = when (irClass.symbol) {
|
||||
symbols.array -> pointerSize
|
||||
|
||||
+2
-2
@@ -32,9 +32,9 @@ private fun process(function: LLVMValueRef, currentThreadTLV: LLVMValueRef) {
|
||||
}
|
||||
|
||||
internal fun removeMultipleThreadDataLoads(context: Context) {
|
||||
val currentThreadTLV = context.llvm.runtimeAnnotationMap["current_thread_tlv"]?.singleOrNull() ?: return
|
||||
val currentThreadTLV = context.generationState.llvm.runtimeAnnotationMap["current_thread_tlv"]?.singleOrNull() ?: return
|
||||
|
||||
getFunctions(context.llvmModule!!)
|
||||
getFunctions(context.generationState.llvm.module)
|
||||
.filter { it.name?.startsWith("kfun:") == true }
|
||||
.filterNot { LLVMIsDeclaration(it) == 1 }
|
||||
.forEach { process(it, currentThreadTLV) }
|
||||
|
||||
Reference in New Issue
Block a user