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 a4275325f9b..b47335503e2 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 @@ -47,7 +47,6 @@ internal class NativeGenerationState( val dependenciesTracker: DependenciesTracker, val llvmModuleSpecification: LlvmModuleSpecification, val outputFiles: OutputFiles, - val tempFiles: TempFiles, val llvmModuleName: String, ) : BasicPhaseContext(config), BackendContextHolder, LlvmIrHolder { val outputFile = outputFiles.mainFileName diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/TopLevelPhases.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/TopLevelPhases.kt index 6ef07dca2af..2375a0002fb 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/TopLevelPhases.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/TopLevelPhases.kt @@ -8,9 +8,9 @@ package org.jetbrains.kotlin.backend.konan.driver.phases import org.jetbrains.kotlin.backend.konan.* import org.jetbrains.kotlin.backend.konan.driver.PhaseContext import org.jetbrains.kotlin.backend.konan.driver.PhaseEngine +import org.jetbrains.kotlin.backend.konan.driver.utilities.CExportFiles import org.jetbrains.kotlin.backend.konan.driver.utilities.createTempFiles import org.jetbrains.kotlin.backend.konan.ir.konanLibrary -import org.jetbrains.kotlin.backend.konan.llvm.getName import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrDeclaration @@ -65,14 +65,23 @@ internal fun PhaseEngine.runBackend(backendContext: Contex val outputFiles = OutputFiles(outputPath, config.target, config.produce) val generationState = NativeGenerationState(context.config, backendContext, fragment.cacheDeserializationStrategy, fragment.dependenciesTracker, fragment.llvmModuleSpecification, outputFiles, - tempFiles, llvmModuleName = "out" // TODO: Currently, all llvm modules are named as "out" which might lead to collisions. ) backendEngine.useContext(generationState) { generationStateEngine -> + val bitcodeFile = tempFiles.create(generationState.llvmModuleName, ".bc").javaFile() + val cExportFiles = if (config.produce.isNativeLibrary) { + CExportFiles( + cppAdapter = tempFiles.create("api", ".cpp").javaFile(), + bitcodeAdapter = tempFiles.create("api", ".bc").javaFile(), + header = outputFiles.cAdapterHeader.javaFile(), + def = if (config.target.family == Family.MINGW) outputFiles.cAdapterDef.javaFile() else null, + ) + } else null // TODO: Make this work if we first compile all the fragments and only after that run the link phases. - val it = generationStateEngine.compileModule(fragment.irModule) + generationStateEngine.compileModule(fragment.irModule, bitcodeFile, cExportFiles) // Split here - compileAndLink(it, it.outputFiles.mainFileName, it.outputFiles, it.temporaryFiles, isCoverageEnabled = false) + val moduleCompilationOutput = ModuleCompilationOutput(bitcodeFile, generationState.dependenciesTracker.collectResult()) + compileAndLink(moduleCompilationOutput, outputFiles.mainFileName, outputFiles, tempFiles, isCoverageEnabled = false) } } finally { tempFiles.dispose() @@ -152,10 +161,6 @@ private fun PhaseEngine.splitIntoFragments( internal data class ModuleCompilationOutput( val bitcodeFile: File, val dependenciesTrackingResult: DependenciesTrackingResult, - // Passing tempFiles and output files through this file looks silly and incorrect. - // TODO: Refactor these classes and remove them from here. - val temporaryFiles: TempFiles, - val outputFiles: OutputFiles, ) /** @@ -165,23 +170,19 @@ internal data class ModuleCompilationOutput( * 4. Optimizes it. * 5. Serializes it to a bitcode file. */ -internal fun PhaseEngine.compileModule(module: IrModuleFragment): ModuleCompilationOutput { +internal fun PhaseEngine.compileModule(module: IrModuleFragment, bitcodeFile: File, cExportFiles: CExportFiles?) { if (context.config.produce.isCache) { runPhase(BuildAdditionalCacheInfoPhase, module) } if (context.config.produce == CompilerOutputKind.PROGRAM) { runPhase(EntryPointPhase, module) } - runBackendCodegen(module) + runBackendCodegen(module, cExportFiles) runBitcodePostProcessing() if (context.config.produce.isCache) { runPhase(SaveAdditionalCacheInfoPhase) } - // TODO: Currently, all llvm modules are named as "out" which might lead to collisions. - val bitcodeFile = context.tempFiles.create(context.llvm.module.getName(), ".bc").javaFile() runPhase(WriteBitcodeFilePhase, WriteBitcodeFileInput(context.llvm.module, bitcodeFile)) - val dependenciesTrackingResult = context.dependenciesTracker.collectResult() - return ModuleCompilationOutput(bitcodeFile, dependenciesTrackingResult, context.tempFiles, context.outputFiles) } internal fun PhaseEngine.compileAndLink( @@ -227,7 +228,7 @@ internal fun PhaseEngine.compileAndLink( } -internal fun PhaseEngine.runBackendCodegen(module: IrModuleFragment) { +internal fun PhaseEngine.runBackendCodegen(module: IrModuleFragment, cExportFiles: CExportFiles?) { runAllLowerings(module) val dependenciesToCompile = findDependenciesToCompile() // TODO: KonanLibraryResolver.TopologicalLibraryOrder actually returns libraries in the reverse topological order. @@ -238,17 +239,16 @@ internal fun PhaseEngine.runBackendCodegen(module: IrModu mergeDependencies(module, dependenciesToCompile) runCodegen(module) val generatedBitcodeFiles = if (context.config.produce.isNativeLibrary) { - val cppAdapterFile = context.tempFiles.create("api", ".cpp").javaFile() - val bitcodeAdapterFile = context.tempFiles.create("api", ".bc").javaFile() + require(cExportFiles != null) val input = CExportGenerateApiInput( context.context.cAdapterExportedElements!!, - headerFile = context.outputFiles.cAdapterHeader.javaFile(), - defFile = if (context.config.target.family == Family.MINGW) context.outputFiles.cAdapterDef.javaFile() else null, - cppAdapterFile = cppAdapterFile + headerFile = cExportFiles.header, + defFile = cExportFiles.def, + cppAdapterFile = cExportFiles.cppAdapter ) runPhase(CExportGenerateApiPhase, input) - runPhase(CExportCompileAdapterPhase, CExportCompileAdapterInput(cppAdapterFile, bitcodeAdapterFile)) - listOf(bitcodeAdapterFile) + runPhase(CExportCompileAdapterPhase, CExportCompileAdapterInput(cExportFiles.cppAdapter, cExportFiles.bitcodeAdapter)) + listOf(cExportFiles.bitcodeAdapter) } else { emptyList() } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/utilities/FileManagement.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/utilities/FileManagement.kt index 793442cea3a..2a2d18b1f0b 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/utilities/FileManagement.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/utilities/FileManagement.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.konan.CacheSupport import org.jetbrains.kotlin.backend.konan.KonanConfig import org.jetbrains.kotlin.backend.konan.KonanConfigKeys import org.jetbrains.kotlin.konan.TempFiles +import java.io.File internal fun createTempFiles(config: KonanConfig, cacheDeserializationStrategy: CacheDeserializationStrategy?): TempFiles { val pathToTempDir = config.configuration.get(KonanConfigKeys.TEMPORARY_FILES_DIR)?.let { @@ -19,4 +20,17 @@ internal fun createTempFiles(config: KonanConfig, cacheDeserializationStrategy: else org.jetbrains.kotlin.konan.file.File(it, CacheSupport.cacheFileId(singleFileStrategy.fqName, singleFileStrategy.filePath)).path } return TempFiles(pathToTempDir) -} \ No newline at end of file +} + +/** + * Files that are generated only during compilation of C dynamic/static library. + * + * TODO: At some point this class and it usages can be generalized to all possible compiler outputs, + * so instead of OutputFiles we will create a series of classes for each specific compiler output kit. + */ +internal class CExportFiles( + val cppAdapter: File, + val bitcodeAdapter: File, + val header: File, + val def: File?, +) \ No newline at end of file