diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BitcodeCompiler.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BitcodeCompiler.kt index 74433e56b19..238290d5b2c 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BitcodeCompiler.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/BitcodeCompiler.kt @@ -14,13 +14,13 @@ typealias ExecutableFile = String internal class BitcodeCompiler(val generationState: NativeGenerationState) { - private val context = generationState.context - private val platform = context.config.platform - private val optimize = context.shouldOptimize() - private val debug = context.config.debug + private val config = generationState.config + private val platform = config.platform + private val optimize = generationState.shouldOptimize() + private val debug = config.debug private val overrideClangOptions = - context.configuration.getList(KonanConfigKeys.OVERRIDE_CLANG_OPTIONS) + config.configuration.getList(KonanConfigKeys.OVERRIDE_CLANG_OPTIONS) private fun MutableList.addNonEmpty(elements: List) { addAll(elements.filter { it.isNotEmpty() }) @@ -28,7 +28,7 @@ internal class BitcodeCompiler(val generationState: NativeGenerationState) { private fun runTool(vararg command: String) = Command(*command) - .logWith(context::log) + .logWith(generationState::log) .execute() private fun temporary(name: String, suffix: String): String = @@ -68,8 +68,8 @@ internal class BitcodeCompiler(val generationState: NativeGenerationState) { debug -> configurables.clangDebugFlags else -> configurables.clangNooptFlags }) - addNonEmpty(BitcodeEmbedding.getClangOptions(context.config)) - addNonEmpty(configurables.currentRelocationMode(context).translateToClangCc1Flag()) + addNonEmpty(BitcodeEmbedding.getClangOptions(config)) + addNonEmpty(configurables.currentRelocationMode(generationState).translateToClangCc1Flag()) } if (configurables is AppleConfigurables) { targetTool("clang++", *flags.toTypedArray(), file, "-o", objectFile) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Boxing.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Boxing.kt index bc27b49b27d..b154f44731a 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Boxing.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Boxing.kt @@ -178,7 +178,7 @@ internal fun IrConstantPrimitive.toBoxCacheValue(generationState: NativeGenerati IrConstKind.Long -> value.value as Long else -> throw IllegalArgumentException("IrConst of kind ${value.kind} can't be converted to box cache") } - val (start, end) = generationState.context.config.target.getBoxCacheRange(cacheType) + val (start, end) = generationState.config.target.getBoxCacheRange(cacheType) return if (value in start..end) { generationState.llvm.let { llvm -> llvm.boxCacheGlobals[cacheType]?.pointer?.getElementPtr(llvm, value.toInt() - start)?.getElementPtr(llvm, 0) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt index 61da59030ab..6f39c440292 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt @@ -91,11 +91,10 @@ internal fun llvmIrDumpCallback(state: ActionState, module: IrModuleFragment, co } internal fun produceCStubs(generationState: NativeGenerationState) { - val context = generationState.context generationState.cStubsManager.compile( - context.config.clang, - context.messageCollector, - context.inVerbosePhase + generationState.config.clang, + generationState.messageCollector, + generationState.inVerbosePhase ).forEach { parseAndLinkBitcodeFile(generationState, generationState.llvm.module, it.absolutePath) } @@ -116,7 +115,7 @@ private data class LlvmModules( * - Everything else. */ private fun collectLlvmModules(generationState: NativeGenerationState, generatedBitcodeFiles: List): LlvmModules { - val config = generationState.context.config + val config = generationState.config val (bitcodePartOfStdlib, bitcodeLibraries) = generationState.llvm.bitcodeToLink .partition { it.isStdlib && generationState.producedLlvmModuleContainsStdlib } @@ -141,7 +140,7 @@ private fun collectLlvmModules(generationState: NativeGenerationState, generated fun parseBitcodeFiles(files: List): List = files.map { bitcodeFile -> val parsedModule = parseBitcodeFile(generationState.llvmContext, bitcodeFile) - if (!generationState.context.shouldUseDebugInfoFromNativeLibs()) { + if (!generationState.shouldUseDebugInfoFromNativeLibs()) { LLVMStripModuleDebugInfo(parsedModule) } parsedModule @@ -172,7 +171,7 @@ private fun linkAllDependencies(generationState: NativeGenerationState, generate } private fun insertAliasToEntryPoint(generationState: NativeGenerationState) { - val config = generationState.context.config + val config = generationState.config val nomain = config.configuration.get(KonanConfigKeys.NOMAIN) ?: false if (config.produce != CompilerOutputKind.PROGRAM || nomain) return @@ -184,7 +183,7 @@ private fun insertAliasToEntryPoint(generationState: NativeGenerationState) { } internal fun linkBitcodeDependencies(generationState: NativeGenerationState) { - val config = generationState.context.config + val config = generationState.config val tempFiles = generationState.tempFiles val produce = config.produce @@ -285,7 +284,7 @@ internal fun produceOutput(generationState: NativeGenerationState) { private fun parseAndLinkBitcodeFile(generationState: NativeGenerationState, llvmModule: LLVMModuleRef, path: String) { val parsedModule = parseBitcodeFile(generationState.llvmContext, path) - if (!generationState.context.shouldUseDebugInfoFromNativeLibs()) { + if (!generationState.shouldUseDebugInfoFromNativeLibs()) { LLVMStripModuleDebugInfo(parsedModule) } val failed = llvmLinkModules2(generationState, llvmModule, parsedModule) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt index 54af70fcf55..80d3fac65e4 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt @@ -103,6 +103,8 @@ internal class Context( override val optimizeLoopsOverUnsignedArrays = true + // TODO: Drop it to reduce code coupling and make it possible to have multiple + // generationStates at the same time. lateinit var generationState: NativeGenerationState fun disposeGenerationState() { diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Linker.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Linker.kt index fa7198336e0..ac33d555180 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Linker.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Linker.kt @@ -1,5 +1,6 @@ package org.jetbrains.kotlin.backend.konan +import org.jetbrains.kotlin.backend.konan.driver.PhaseContext import org.jetbrains.kotlin.backend.konan.serialization.ClassFieldsSerializer import org.jetbrains.kotlin.backend.konan.serialization.InlineFunctionBodyReferenceSerializer import org.jetbrains.kotlin.konan.KonanExternalToolFailure @@ -13,7 +14,7 @@ import org.jetbrains.kotlin.konan.target.presetName import org.jetbrains.kotlin.library.metadata.resolver.TopologicalLibraryOrder import org.jetbrains.kotlin.library.uniqueName -internal fun determineLinkerOutput(context: Context): LinkerOutputKind = +internal fun determineLinkerOutput(context: PhaseContext): LinkerOutputKind = when (context.config.produce) { CompilerOutputKind.FRAMEWORK -> { val staticFramework = context.config.produceStaticFramework @@ -37,7 +38,7 @@ internal fun determineLinkerOutput(context: Context): LinkerOutputKind = } internal class CacheStorage(val generationState: NativeGenerationState) { - private val config = generationState.context.config + private val config = generationState.config private val outputFiles = generationState.outputFiles fun renameOutput() { @@ -80,20 +81,19 @@ internal class CacheStorage(val generationState: NativeGenerationState) { // TODO: We have a Linker.kt file in the shared module. internal class Linker(val generationState: NativeGenerationState) { - private val context = generationState.context - private val platform = context.config.platform - private val config = context.config.configuration - private val linkerOutput = determineLinkerOutput(context) + private val config = generationState.config + private val platform = config.platform + private val linkerOutput = determineLinkerOutput(generationState) private val linker = platform.linker - private val target = context.config.target - private val optimize = context.shouldOptimize() - private val debug = context.config.debug || context.config.lightDebug + private val target = config.target + private val optimize = generationState.shouldOptimize() + private val debug = config.debug || config.lightDebug fun link(objectFiles: List) { val nativeDependencies = generationState.llvm.nativeDependenciesToLink - val includedBinariesLibraries = context.config.libraryToCache?.let { listOf(it.klib) } - ?: nativeDependencies.filterNot { context.config.cachedLibraries.isLibraryCached(it) } + val includedBinariesLibraries = config.libraryToCache?.let { listOf(it.klib) } + ?: nativeDependencies.filterNot { config.cachedLibraries.isLibraryCached(it) } val includedBinaries = includedBinariesLibraries.map { (it as? KonanLibrary)?.includedPaths.orEmpty() }.flatten() val libraryProvidedLinkerFlags = generationState.llvm.allNativeDependencies.map { it.linkerOpts }.flatten() @@ -126,9 +126,9 @@ internal class Linker(val generationState: NativeGenerationState) { val additionalLinkerArgs: List val executable: String - if (context.config.produce != CompilerOutputKind.FRAMEWORK) { + if (config.produce != CompilerOutputKind.FRAMEWORK) { additionalLinkerArgs = if (target.family.isAppleFamily) { - when (context.config.produce) { + when (config.produce) { CompilerOutputKind.DYNAMIC_CACHE -> listOf("-install_name", outputFiles.dynamicCacheInstallName) else -> listOf("-dead_strip") @@ -154,13 +154,13 @@ internal class Linker(val generationState: NativeGenerationState) { } val needsProfileLibrary = generationState.coverage.enabled - val mimallocEnabled = context.config.allocationMode == AllocationMode.MIMALLOC + val mimallocEnabled = config.allocationMode == AllocationMode.MIMALLOC val linkerInput = determineLinkerInput(objectFiles, linkerOutput) try { File(executable).delete() - val linkerArgs = asLinkerArgs(config.getNotNull(KonanConfigKeys.LINKER_ARGS)) + - BitcodeEmbedding.getLinkerOptions(context.config) + + val linkerArgs = asLinkerArgs(config.configuration.getNotNull(KonanConfigKeys.LINKER_ARGS)) + + BitcodeEmbedding.getLinkerOptions(config) + linkerInput.caches.dynamic + libraryProvidedLinkerFlags + additionalLinkerArgs @@ -175,10 +175,10 @@ internal class Linker(val generationState: NativeGenerationState) { outputDsymBundle = outputFiles.symbolicInfoFile, needsProfileLibrary = needsProfileLibrary, mimallocEnabled = mimallocEnabled, - sanitizer = context.config.sanitizer + sanitizer = config.sanitizer ) (linkerInput.preLinkCommands + finalOutputCommands).forEach { - it.logWith(context::log) + it.logWith(generationState::log) it.execute() } } catch (e: KonanExternalToolFailure) { @@ -192,7 +192,7 @@ internal class Linker(val generationState: NativeGenerationState) { Also, consider filing an issue with full Gradle log here: https://kotl.in/issue """.trimIndent() else "" - context.reportCompilationError("${e.toolName} invocation reported errors\n$extraUserInfo\n${e.message}") + generationState.reportCompilationError("${e.toolName} invocation reported errors\n$extraUserInfo\n${e.message}") } return executable } @@ -200,8 +200,8 @@ internal class Linker(val generationState: NativeGenerationState) { private fun shouldPerformPreLink(caches: CachesToLink, linkerOutputKind: LinkerOutputKind): Boolean { // Pre-link is only useful when producing static library. Otherwise its just a waste of time. val isStaticLibrary = linkerOutputKind == LinkerOutputKind.STATIC_LIBRARY && - context.config.isFinalBinary - val enabled = context.config.cacheSupport.preLinkCaches + config.isFinalBinary + val enabled = config.cacheSupport.preLinkCaches val nonEmptyCaches = caches.static.isNotEmpty() return isStaticLibrary && enabled && nonEmptyCaches } @@ -212,7 +212,7 @@ internal class Linker(val generationState: NativeGenerationState) { // we should detect cache usage early to report errors correctly. val cachingInvolved = caches.static.isNotEmpty() || caches.dynamic.isNotEmpty() return when { - context.config.produce == CompilerOutputKind.STATIC_CACHE -> { + config.produce == CompilerOutputKind.STATIC_CACHE -> { // Do not link static cache dependencies. LinkerInput(objectFiles, CachesToLink(emptyList(), caches.dynamic), emptyList(), cachingInvolved) } @@ -241,7 +241,7 @@ private fun determineCachesToLink(generationState: NativeGenerationState): Cache generationState.llvm.allCachedBitcodeDependencies.forEach { library -> val currentBinaryContainsLibrary = generationState.llvmModuleSpecification.containsLibrary(library) - val cache = generationState.context.config.cachedLibraries.getLibraryCache(library) + val cache = generationState.config.cachedLibraries.getLibraryCache(library) ?: error("Library $library is expected to be cached") // Consistency check. Generally guaranteed by implementation. diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/NativeGenerationState.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/NativeGenerationState.kt index a41fd3b014f..322c098d49c 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/NativeGenerationState.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/NativeGenerationState.kt @@ -45,6 +45,8 @@ internal class FileLowerState { internal class NativeGenerationState( config: KonanConfig, + // TODO: Get rid of this property completely once transition to the dynamic driver is complete. + // It will reduce code coupling and make it easier to create NativeGenerationState instances. val context: Context, val cacheDeserializationStrategy: CacheDeserializationStrategy? ) : BasicPhaseContext(config) { @@ -114,12 +116,17 @@ internal class NativeGenerationState( verifyModule(llvm.module) } + // TODO: Do we need this function? fun printBitCode() { if (!llvmDelegate.isInitialized()) return - context.separator("BitCode:") + separator("BitCode:") LLVMDumpModule(llvm.module) } + private fun separator(title: String) { + println("\n\n--- ${title} ----------------------\n") + } + private var isDisposed = false override fun dispose() { if (isDisposed) return diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/OptimizationPipeline.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/OptimizationPipeline.kt index 7d4379f4239..cd3059739da 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/OptimizationPipeline.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/OptimizationPipeline.kt @@ -3,6 +3,7 @@ package org.jetbrains.kotlin.backend.konan import kotlinx.cinterop.* import llvm.* import org.jetbrains.kotlin.backend.common.LoggingContext +import org.jetbrains.kotlin.backend.konan.driver.PhaseContext import org.jetbrains.kotlin.backend.konan.llvm.* import org.jetbrains.kotlin.konan.target.* import java.io.Closeable @@ -56,7 +57,7 @@ data class LlvmPipelineConfig( val sanitizer: SanitizerKind?, ) -private fun getCpuModel(context: Context): String { +private fun getCpuModel(context: PhaseContext): String { val target = context.config.target val configurables: Configurables = context.config.platform.configurables return configurables.targetCpu ?: run { @@ -65,10 +66,10 @@ private fun getCpuModel(context: Context): String { } } -private fun getCpuFeatures(context: Context): String = +private fun getCpuFeatures(context: PhaseContext): String = context.config.platform.configurables.targetCpuFeatures ?: "" -private fun tryGetInlineThreshold(context: Context): Int? { +private fun tryGetInlineThreshold(context: PhaseContext): Int? { val configurables: Configurables = context.config.platform.configurables return configurables.llvmInlineThreshold?.let { it.toIntOrNull() ?: run { @@ -87,22 +88,22 @@ private fun tryGetInlineThreshold(context: Context): Int? { * even in debug compilation. */ internal fun createLTOPipelineConfigForRuntime(generationState: NativeGenerationState): LlvmPipelineConfig { - val context = generationState.context - val configurables: Configurables = context.config.platform.configurables + val config = generationState.config + val configurables: Configurables = config.platform.configurables return LlvmPipelineConfig( generationState.llvm.targetTriple, - getCpuModel(context), - getCpuFeatures(context), + getCpuModel(generationState), + getCpuFeatures(generationState), LlvmOptimizationLevel.AGGRESSIVE, LlvmSizeLevel.NONE, LLVMCodeGenOptLevel.LLVMCodeGenLevelAggressive, - configurables.currentRelocationMode(context).translateToLlvmRelocMode(), + configurables.currentRelocationMode(generationState).translateToLlvmRelocMode(), LLVMCodeModel.LLVMCodeModelDefault, globalDce = false, internalize = false, objCPasses = configurables is AppleConfigurables, makeDeclarationsHidden = false, - inlineThreshold = tryGetInlineThreshold(context), + inlineThreshold = tryGetInlineThreshold(generationState), sanitizer = null ) } @@ -116,30 +117,30 @@ internal fun createLTOPipelineConfigForRuntime(generationState: NativeGeneration * but for release binaries we rely on "closed" world and enable a lot of optimizations. */ internal fun createLTOFinalPipelineConfig(generationState: NativeGenerationState): LlvmPipelineConfig { - val context = generationState.context - val target = context.config.target - val configurables: Configurables = context.config.platform.configurables - val cpuModel = getCpuModel(context) - val cpuFeatures = getCpuFeatures(context) + val config = generationState.config + val target = config.target + val configurables: Configurables = config.platform.configurables + val cpuModel = getCpuModel(generationState) + val cpuFeatures = getCpuFeatures(generationState) val optimizationLevel: LlvmOptimizationLevel = when { - context.shouldOptimize() -> LlvmOptimizationLevel.AGGRESSIVE - context.shouldContainDebugInfo() -> LlvmOptimizationLevel.NONE + generationState.shouldOptimize() -> LlvmOptimizationLevel.AGGRESSIVE + generationState.shouldContainDebugInfo() -> LlvmOptimizationLevel.NONE else -> LlvmOptimizationLevel.DEFAULT } val sizeLevel: LlvmSizeLevel = when { // We try to optimize code as much as possible on embedded targets. target is KonanTarget.ZEPHYR || target == KonanTarget.WASM32 -> LlvmSizeLevel.AGGRESSIVE - context.shouldOptimize() -> LlvmSizeLevel.NONE - context.shouldContainDebugInfo() -> LlvmSizeLevel.NONE + generationState.shouldOptimize() -> LlvmSizeLevel.NONE + generationState.shouldContainDebugInfo() -> LlvmSizeLevel.NONE else -> LlvmSizeLevel.NONE } val codegenOptimizationLevel: LLVMCodeGenOptLevel = when { - context.shouldOptimize() -> LLVMCodeGenOptLevel.LLVMCodeGenLevelAggressive - context.shouldContainDebugInfo() -> LLVMCodeGenOptLevel.LLVMCodeGenLevelNone + generationState.shouldOptimize() -> LLVMCodeGenOptLevel.LLVMCodeGenLevelAggressive + generationState.shouldContainDebugInfo() -> LLVMCodeGenOptLevel.LLVMCodeGenLevelNone else -> LLVMCodeGenOptLevel.LLVMCodeGenLevelDefault } - val relocMode: LLVMRelocMode = configurables.currentRelocationMode(context).translateToLlvmRelocMode() + val relocMode: LLVMRelocMode = configurables.currentRelocationMode(generationState).translateToLlvmRelocMode() val codeModel: LLVMCodeModel = LLVMCodeModel.LLVMCodeModelDefault val globalDce = true // Since we are in a "closed world" internalization can be safely used @@ -150,14 +151,14 @@ internal fun createLTOFinalPipelineConfig(generationState: NativeGenerationState // similar to DCE enabled by internalize but later: // // Important for binary size, workarounds references to undefined symbols from interop libraries. - val makeDeclarationsHidden = context.config.produce == CompilerOutputKind.STATIC_CACHE + val makeDeclarationsHidden = config.produce == CompilerOutputKind.STATIC_CACHE val objcPasses = configurables is AppleConfigurables // Null value means that LLVM should use default inliner params // for the provided optimization and size level. val inlineThreshold: Int? = when { - context.shouldOptimize() -> tryGetInlineThreshold(context) - context.shouldContainDebugInfo() -> null + generationState.shouldOptimize() -> tryGetInlineThreshold(generationState) + generationState.shouldContainDebugInfo() -> null else -> null } @@ -175,7 +176,7 @@ internal fun createLTOFinalPipelineConfig(generationState: NativeGenerationState makeDeclarationsHidden, objcPasses, inlineThreshold, - context.config.sanitizer + config.sanitizer ) } @@ -298,7 +299,7 @@ class LlvmOptimizationPipeline( } } -internal fun RelocationModeFlags.currentRelocationMode(context: Context): RelocationModeFlags.Mode = +internal fun RelocationModeFlags.currentRelocationMode(context: PhaseContext): RelocationModeFlags.Mode = when (determineLinkerOutput(context)) { LinkerOutputKind.DYNAMIC_LIBRARY -> dynamicLibraryRelocationMode LinkerOutputKind.STATIC_LIBRARY -> staticLibraryRelocationMode diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/RuntimeLinkageStrategy.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/RuntimeLinkageStrategy.kt index 83bad1b42c7..343d994d515 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/RuntimeLinkageStrategy.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/RuntimeLinkageStrategy.kt @@ -52,7 +52,7 @@ internal sealed class RuntimeLinkageStrategy { } } val config = createLTOPipelineConfigForRuntime(generationState) - LlvmOptimizationPipeline(config, runtimeModule, generationState.context).use { + LlvmOptimizationPipeline(config, runtimeModule, generationState).use { it.run() } return listOf(runtimeModule) @@ -64,7 +64,7 @@ internal sealed class RuntimeLinkageStrategy { * Choose runtime linkage strategy based on current compiler configuration and [BinaryOptions.linkRuntime]. */ internal fun pick(generationState: NativeGenerationState, runtimeLlvmModules: List): RuntimeLinkageStrategy { - val config = generationState.context.config + val config = generationState.config val binaryOption = config.configuration.get(BinaryOptions.linkRuntime) return when { binaryOption == RuntimeLinkageStrategyBinaryOption.Raw -> Raw(runtimeLlvmModules) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt index 83caeee2346..197a10a159c 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt @@ -92,7 +92,7 @@ internal val objCExportPhase = konanUnitPhase( objCExportedInterface = when { !config.target.family.isAppleFamily -> null config.produce != CompilerOutputKind.FRAMEWORK -> null - else -> produceObjCExportInterface(this) + else -> produceObjCExportInterface(this, this.moduleDescriptor, this.frontendServices) } objCExportCodeSpec = objCExportedInterface?.createCodeSpec(symbolTable!!) }, diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BitcodePhases.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BitcodePhases.kt index 0a5dfc3a49e..6477c0676bf 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BitcodePhases.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BitcodePhases.kt @@ -246,7 +246,12 @@ internal val codegenPhase = makeKonanModuleOpPhase( name = "Codegen", description = "Code generation", op = { context, irModule -> - context.generationState.objCExport = ObjCExport(context.generationState, context.objCExportedInterface, context.objCExportCodeSpec) + context.generationState.objCExport = ObjCExport( + context.generationState, + context.moduleDescriptor, + context.objCExportedInterface, + context.objCExportCodeSpec + ) irModule.acceptVoid(CodeGeneratorVisitor(context.generationState, context.lifetimes)) @@ -285,8 +290,9 @@ internal val bitcodeOptimizationPhase = makeKonanModuleOpPhase( name = "BitcodeOptimization", description = "Optimize bitcode", op = { context, _ -> + val generationState = context.generationState val config = createLTOFinalPipelineConfig(context.generationState) - LlvmOptimizationPipeline(config, context.generationState.llvm.module, context).use { + LlvmOptimizationPipeline(config, context.generationState.llvm.module, generationState).use { it.run() } } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DebugUtils.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DebugUtils.kt index 453048737ff..ec96f5856b2 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DebugUtils.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DebugUtils.kt @@ -267,7 +267,7 @@ internal fun String?.toFileAndFolder(config: KonanConfig): FileAndFolder { internal fun alignTo(value: Long, align: Long): Long = (value + align - 1) / align * align internal fun setupBridgeDebugInfo(generationState: NativeGenerationState, function: LLVMValueRef): LocationInfo? { - if (!generationState.context.shouldContainLocationDebugInfo()) { + if (!generationState.shouldContainLocationDebugInfo()) { return null } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index 38716c1ba8e..8fae48d7ac1 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -2918,8 +2918,7 @@ internal fun NativeGenerationState.generateRuntimeConstantsModule() : LLVMModule global.setLinkage(LLVMLinkage.LLVMExternalLinkage) } - val config = context.config - setRuntimeConstGlobal("Kotlin_needDebugInfo", llvm.constInt32(if (context.shouldContainDebugInfo()) 1 else 0)) + setRuntimeConstGlobal("Kotlin_needDebugInfo", llvm.constInt32(if (shouldContainDebugInfo()) 1 else 0)) setRuntimeConstGlobal("Kotlin_runtimeAssertsMode", llvm.constInt32(config.runtimeAssertsMode.value)) val runtimeLogs = config.runtimeLogs?.let { static.cStringLiteral(it) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/CoverageManager.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/CoverageManager.kt index 05cbe04ab2d..24283c52253 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/CoverageManager.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/coverage/CoverageManager.kt @@ -21,7 +21,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.module */ internal class CoverageManager(val generationState: NativeGenerationState) { private val context = generationState.context - private val config = context.config + private val config = generationState.config private val shouldCoverSources: Boolean = config.shouldCoverSources @@ -45,7 +45,7 @@ internal class CoverageManager(val generationState: NativeGenerationState) { init { if (enabled && !checkRestrictions()) { - context.reportCompilationError("Coverage is not supported for ${config.target}.") + generationState.reportCompilationError("Coverage is not supported for ${config.target}.") } } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/diagnosticReport.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/diagnosticReport.kt index bb59bd43c30..2f1a6820363 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/diagnosticReport.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/diagnosticReport.kt @@ -6,10 +6,11 @@ package org.jetbrains.kotlin.backend.konan.llvm import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.driver.PhaseContext import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity internal open class DefaultLlvmDiagnosticHandler( - private val context: Context, + private val context: PhaseContext, private val policy: Policy = Policy.Default ) : LlvmDiagnosticHandler { interface Policy { diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/linkModules.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/linkModules.kt index 973683d4c26..69389ec39e3 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/linkModules.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/linkModules.kt @@ -10,7 +10,7 @@ import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.NativeGenerationState internal fun llvmLinkModules2(generationState: NativeGenerationState, dest: LLVMModuleRef, src: LLVMModuleRef): LLVMBool { - val diagnosticHandler = DefaultLlvmDiagnosticHandler(generationState.context, object : DefaultLlvmDiagnosticHandler.Policy { + val diagnosticHandler = DefaultLlvmDiagnosticHandler(generationState, object : DefaultLlvmDiagnosticHandler.Policy { override fun suppressWarning(diagnostic: LlvmDiagnostic): Boolean { if (super.suppressWarning(diagnostic)) return true diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objc/linkObjC.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objc/linkObjC.kt index 8fc4225a2c0..8274f17b5b7 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objc/linkObjC.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objc/linkObjC.kt @@ -15,7 +15,7 @@ import org.jetbrains.kotlin.backend.konan.objcexport.NSNumberKind import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportNamer internal fun patchObjCRuntimeModule(generationState: NativeGenerationState): LLVMModuleRef? { - val config = generationState.context.config + val config = generationState.config if (!(config.isFinalBinary && config.target.family.isAppleFamily)) return null val patchBuilder = PatchBuilder(generationState.objCExport.namer) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt index b6af277243d..576279e6fdd 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt @@ -2078,7 +2078,7 @@ private val TypeBridge.objCEncoding: String get() = when (this) { } private fun NativeGenerationState.is64BitNSInteger(): Boolean { - val configurables = context.config.platform.configurables + val configurables = config.platform.configurables require(configurables is AppleConfigurables) { "Target ${configurables.target} has no support for NSInteger type." } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt index e2c96c69fae..edf289e75d1 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt @@ -7,11 +7,13 @@ package org.jetbrains.kotlin.backend.konan.objcexport import org.jetbrains.kotlin.backend.konan.* import org.jetbrains.kotlin.backend.konan.descriptors.isInterface +import org.jetbrains.kotlin.backend.konan.driver.PhaseContext import org.jetbrains.kotlin.backend.konan.llvm.CodeGenerator import org.jetbrains.kotlin.backend.konan.llvm.objcexport.ObjCExportBlockCodeGenerator import org.jetbrains.kotlin.backend.konan.llvm.objcexport.ObjCExportCodeGenerator import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.SourceFile import org.jetbrains.kotlin.konan.exec.Command import org.jetbrains.kotlin.konan.file.File @@ -27,10 +29,14 @@ internal class ObjCExportedInterface( val mapper: ObjCExportMapper ) -// TODO: Replace Context with a more lightweight class. -internal fun produceObjCExportInterface(context: Context): ObjCExportedInterface { - require(context.config.target.family.isAppleFamily) - require(context.config.produce == CompilerOutputKind.FRAMEWORK) +internal fun produceObjCExportInterface( + context: PhaseContext, + moduleDescriptor: ModuleDescriptor, + frontendServices: FrontendServices, +): ObjCExportedInterface { + val config = context.config + require(config.target.family.isAppleFamily) + require(config.produce == CompilerOutputKind.FRAMEWORK) val topLevelNamePrefix = context.objCExportTopLevelNamePrefix @@ -38,13 +44,13 @@ internal fun produceObjCExportInterface(context: Context): ObjCExportedInterface // Not possible yet, since ObjCExport translates the entire "world" API at once // and can't do this per-module, e.g. due to global name conflict resolution. - val unitSuspendFunctionExport = context.config.unitSuspendFunctionObjCExport - val mapper = ObjCExportMapper(context.frontendServices.deprecationResolver, unitSuspendFunctionExport = unitSuspendFunctionExport) - val moduleDescriptors = listOf(context.moduleDescriptor) + context.getExportedDependencies() - val objcGenerics = context.configuration.getBoolean(KonanConfigKeys.OBJC_GENERICS) + val unitSuspendFunctionExport = config.unitSuspendFunctionObjCExport + val mapper = ObjCExportMapper(frontendServices.deprecationResolver, unitSuspendFunctionExport = unitSuspendFunctionExport) + val moduleDescriptors = listOf(moduleDescriptor) + moduleDescriptor.getExportedDependencies(config) + val objcGenerics = config.configuration.getBoolean(KonanConfigKeys.OBJC_GENERICS) val namer = ObjCExportNamerImpl( moduleDescriptors.toSet(), - context.moduleDescriptor.builtIns, + moduleDescriptor.builtIns, mapper, topLevelNamePrefix, local = false, @@ -56,13 +62,14 @@ internal fun produceObjCExportInterface(context: Context): ObjCExportedInterface } internal class ObjCExport( - val generationState: NativeGenerationState, + private val generationState: NativeGenerationState, + private val moduleDescriptor: ModuleDescriptor, private val exportedInterface: ObjCExportedInterface?, private val codeSpec: ObjCExportCodeSpec? ) { - private val context = generationState.context - private val target get() = context.config.target - private val topLevelNamePrefix get() = context.objCExportTopLevelNamePrefix + private val config = generationState.config + private val target get() = config.target + private val topLevelNamePrefix get() = generationState.objCExportTopLevelNamePrefix lateinit var namer: ObjCExportNamer @@ -73,12 +80,12 @@ internal class ObjCExport( ObjCExportBlockCodeGenerator(codegen).generate() } - if (!context.config.isFinalBinary) return // TODO: emit RTTI to the same modules as classes belong to. + if (!config.isFinalBinary) return // TODO: emit RTTI to the same modules as classes belong to. - val mapper = exportedInterface?.mapper ?: ObjCExportMapper(unitSuspendFunctionExport = context.config.unitSuspendFunctionObjCExport) + val mapper = exportedInterface?.mapper ?: ObjCExportMapper(unitSuspendFunctionExport = config.unitSuspendFunctionObjCExport) namer = exportedInterface?.namer ?: ObjCExportNamerImpl( - setOf(codegen.context.moduleDescriptor), - context.moduleDescriptor.builtIns, + setOf(moduleDescriptor), + moduleDescriptor.builtIns, mapper, topLevelNamePrefix, local = false @@ -105,14 +112,14 @@ internal class ObjCExport( val frameworkDirectory = File(generationState.outputFile) val frameworkName = frameworkDirectory.name.removeSuffix(".framework") val frameworkBuilder = FrameworkBuilder( - context.config, - infoPListBuilder = InfoPListBuilder(context.config), + config, + infoPListBuilder = InfoPListBuilder(config), moduleMapBuilder = ModuleMapBuilder(), objCHeaderWriter = ObjCHeaderWriter(), mainPackageGuesser = MainPackageGuesser(), ) frameworkBuilder.build( - context.moduleDescriptor, + moduleDescriptor, frameworkDirectory, frameworkName, headerLines, @@ -145,7 +152,7 @@ internal class ObjCExport( val bitcode = createTempFile("protocols", ".bc").deleteOnExit() - val clangCommand = context.config.clang.clangC( + val clangCommand = config.clang.clangC( source.absolutePath, "-O2", "-emit-llvm", diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGeneratorImpl.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGeneratorImpl.kt index eab83c6ed65..0528ceb10c7 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGeneratorImpl.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGeneratorImpl.kt @@ -5,8 +5,8 @@ package org.jetbrains.kotlin.backend.konan.objcexport -import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.KonanConfigKeys +import org.jetbrains.kotlin.backend.konan.driver.PhaseContext import org.jetbrains.kotlin.backend.konan.reportCompilationWarning import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.MessageUtil @@ -17,7 +17,7 @@ import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.resolve.source.getPsi internal class ObjCExportHeaderGeneratorImpl( - val context: Context, + val context: PhaseContext, moduleDescriptors: List, mapper: ObjCExportMapper, namer: ObjCExportNamer, @@ -26,7 +26,7 @@ internal class ObjCExportHeaderGeneratorImpl( override val shouldExportKDoc = context.shouldExportKDoc() - private class ProblemCollector(val context: Context) : ObjCExportProblemCollector { + private class ProblemCollector(val context: PhaseContext) : ObjCExportProblemCollector { override fun reportWarning(text: String) { context.reportCompilationWarning(text) } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportNamer.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportNamer.kt index 044f7574ea3..a321ddd69bd 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportNamer.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportNamer.kt @@ -7,8 +7,11 @@ package org.jetbrains.kotlin.backend.konan.objcexport import org.jetbrains.kotlin.backend.common.serialization.findSourceFile import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.backend.konan.cKeywords import org.jetbrains.kotlin.backend.konan.descriptors.isArray import org.jetbrains.kotlin.backend.konan.descriptors.isInterface +import org.jetbrains.kotlin.backend.konan.driver.PhaseContext +import org.jetbrains.kotlin.descriptors.konan.isNativeStdlib import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.descriptors.* @@ -1040,7 +1043,7 @@ internal val ModuleDescriptor.objCExportAdditionalNamePrefix: String get() { return abbreviate(fullPrefix) } -internal val Context.objCExportTopLevelNamePrefix: String +internal val PhaseContext.objCExportTopLevelNamePrefix: String get() = abbreviate(config.fullExportedNamePrefix) fun abbreviate(name: String): String {