[K/N][IR][codegen] Introduced NativeGenerationState

This commit is contained in:
Igor Chevdar
2022-08-17 17:36:42 +03:00
committed by Space
parent 77f24a22dd
commit 9250de42a5
42 changed files with 663 additions and 674 deletions
@@ -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) {
@@ -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
}
@@ -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")
@@ -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()
@@ -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)
}
@@ -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 -> {
@@ -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.
@@ -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()
}
}
}
@@ -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")
@@ -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
}
}
@@ -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,
@@ -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
@@ -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)
@@ -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
@@ -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()
)
}
@@ -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) {
@@ -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(
@@ -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
@@ -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)
}
}
@@ -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) {
@@ -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
}
}
@@ -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
}
}
@@ -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 {
@@ -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)
})
@@ -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 -> {
@@ -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)
}
@@ -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.
@@ -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)
}
}
@@ -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)),
@@ -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)
}
}
@@ -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)
}
@@ -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
}
@@ -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.
@@ -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())
}
@@ -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!!
@@ -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)
)
@@ -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)
@@ -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)
}
}
@@ -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 ->
@@ -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.
@@ -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
@@ -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) }