[K/N] Finish refactoring TempFiles usages
1. Introduce CExportFiles class This class aggregates all files that are created specifically for C export. Adding more such classes for other output kinds should help getting rid of OutputFiles class. 2. Remove NativeGenerationState.tempFiles Making NativeGenerationState (and compiler phases in general) unaware of files and their lifetime is necessary for making phases simpler and easier to compose.
This commit is contained in:
committed by
Space Team
parent
4fbddf1786
commit
f7d3312ad5
-1
@@ -47,7 +47,6 @@ internal class NativeGenerationState(
|
|||||||
val dependenciesTracker: DependenciesTracker,
|
val dependenciesTracker: DependenciesTracker,
|
||||||
val llvmModuleSpecification: LlvmModuleSpecification,
|
val llvmModuleSpecification: LlvmModuleSpecification,
|
||||||
val outputFiles: OutputFiles,
|
val outputFiles: OutputFiles,
|
||||||
val tempFiles: TempFiles,
|
|
||||||
val llvmModuleName: String,
|
val llvmModuleName: String,
|
||||||
) : BasicPhaseContext(config), BackendContextHolder<Context>, LlvmIrHolder {
|
) : BasicPhaseContext(config), BackendContextHolder<Context>, LlvmIrHolder {
|
||||||
val outputFile = outputFiles.mainFileName
|
val outputFile = outputFiles.mainFileName
|
||||||
|
|||||||
+22
-22
@@ -8,9 +8,9 @@ package org.jetbrains.kotlin.backend.konan.driver.phases
|
|||||||
import org.jetbrains.kotlin.backend.konan.*
|
import org.jetbrains.kotlin.backend.konan.*
|
||||||
import org.jetbrains.kotlin.backend.konan.driver.PhaseContext
|
import org.jetbrains.kotlin.backend.konan.driver.PhaseContext
|
||||||
import org.jetbrains.kotlin.backend.konan.driver.PhaseEngine
|
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.driver.utilities.createTempFiles
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.konanLibrary
|
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.cli.jvm.compiler.KotlinCoreEnvironment
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||||
@@ -65,14 +65,23 @@ internal fun <C : PhaseContext> PhaseEngine<C>.runBackend(backendContext: Contex
|
|||||||
val outputFiles = OutputFiles(outputPath, config.target, config.produce)
|
val outputFiles = OutputFiles(outputPath, config.target, config.produce)
|
||||||
val generationState = NativeGenerationState(context.config, backendContext,
|
val generationState = NativeGenerationState(context.config, backendContext,
|
||||||
fragment.cacheDeserializationStrategy, fragment.dependenciesTracker, fragment.llvmModuleSpecification, outputFiles,
|
fragment.cacheDeserializationStrategy, fragment.dependenciesTracker, fragment.llvmModuleSpecification, outputFiles,
|
||||||
tempFiles,
|
|
||||||
llvmModuleName = "out" // TODO: Currently, all llvm modules are named as "out" which might lead to collisions.
|
llvmModuleName = "out" // TODO: Currently, all llvm modules are named as "out" which might lead to collisions.
|
||||||
)
|
)
|
||||||
backendEngine.useContext(generationState) { generationStateEngine ->
|
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.
|
// 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
|
// 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 {
|
} finally {
|
||||||
tempFiles.dispose()
|
tempFiles.dispose()
|
||||||
@@ -152,10 +161,6 @@ private fun PhaseEngine<out Context>.splitIntoFragments(
|
|||||||
internal data class ModuleCompilationOutput(
|
internal data class ModuleCompilationOutput(
|
||||||
val bitcodeFile: File,
|
val bitcodeFile: File,
|
||||||
val dependenciesTrackingResult: DependenciesTrackingResult,
|
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.
|
* 4. Optimizes it.
|
||||||
* 5. Serializes it to a bitcode file.
|
* 5. Serializes it to a bitcode file.
|
||||||
*/
|
*/
|
||||||
internal fun PhaseEngine<NativeGenerationState>.compileModule(module: IrModuleFragment): ModuleCompilationOutput {
|
internal fun PhaseEngine<NativeGenerationState>.compileModule(module: IrModuleFragment, bitcodeFile: File, cExportFiles: CExportFiles?) {
|
||||||
if (context.config.produce.isCache) {
|
if (context.config.produce.isCache) {
|
||||||
runPhase(BuildAdditionalCacheInfoPhase, module)
|
runPhase(BuildAdditionalCacheInfoPhase, module)
|
||||||
}
|
}
|
||||||
if (context.config.produce == CompilerOutputKind.PROGRAM) {
|
if (context.config.produce == CompilerOutputKind.PROGRAM) {
|
||||||
runPhase(EntryPointPhase, module)
|
runPhase(EntryPointPhase, module)
|
||||||
}
|
}
|
||||||
runBackendCodegen(module)
|
runBackendCodegen(module, cExportFiles)
|
||||||
runBitcodePostProcessing()
|
runBitcodePostProcessing()
|
||||||
if (context.config.produce.isCache) {
|
if (context.config.produce.isCache) {
|
||||||
runPhase(SaveAdditionalCacheInfoPhase)
|
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))
|
runPhase(WriteBitcodeFilePhase, WriteBitcodeFileInput(context.llvm.module, bitcodeFile))
|
||||||
val dependenciesTrackingResult = context.dependenciesTracker.collectResult()
|
|
||||||
return ModuleCompilationOutput(bitcodeFile, dependenciesTrackingResult, context.tempFiles, context.outputFiles)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun <C : PhaseContext> PhaseEngine<C>.compileAndLink(
|
internal fun <C : PhaseContext> PhaseEngine<C>.compileAndLink(
|
||||||
@@ -227,7 +228,7 @@ internal fun <C : PhaseContext> PhaseEngine<C>.compileAndLink(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal fun PhaseEngine<NativeGenerationState>.runBackendCodegen(module: IrModuleFragment) {
|
internal fun PhaseEngine<NativeGenerationState>.runBackendCodegen(module: IrModuleFragment, cExportFiles: CExportFiles?) {
|
||||||
runAllLowerings(module)
|
runAllLowerings(module)
|
||||||
val dependenciesToCompile = findDependenciesToCompile()
|
val dependenciesToCompile = findDependenciesToCompile()
|
||||||
// TODO: KonanLibraryResolver.TopologicalLibraryOrder actually returns libraries in the reverse topological order.
|
// TODO: KonanLibraryResolver.TopologicalLibraryOrder actually returns libraries in the reverse topological order.
|
||||||
@@ -238,17 +239,16 @@ internal fun PhaseEngine<NativeGenerationState>.runBackendCodegen(module: IrModu
|
|||||||
mergeDependencies(module, dependenciesToCompile)
|
mergeDependencies(module, dependenciesToCompile)
|
||||||
runCodegen(module)
|
runCodegen(module)
|
||||||
val generatedBitcodeFiles = if (context.config.produce.isNativeLibrary) {
|
val generatedBitcodeFiles = if (context.config.produce.isNativeLibrary) {
|
||||||
val cppAdapterFile = context.tempFiles.create("api", ".cpp").javaFile()
|
require(cExportFiles != null)
|
||||||
val bitcodeAdapterFile = context.tempFiles.create("api", ".bc").javaFile()
|
|
||||||
val input = CExportGenerateApiInput(
|
val input = CExportGenerateApiInput(
|
||||||
context.context.cAdapterExportedElements!!,
|
context.context.cAdapterExportedElements!!,
|
||||||
headerFile = context.outputFiles.cAdapterHeader.javaFile(),
|
headerFile = cExportFiles.header,
|
||||||
defFile = if (context.config.target.family == Family.MINGW) context.outputFiles.cAdapterDef.javaFile() else null,
|
defFile = cExportFiles.def,
|
||||||
cppAdapterFile = cppAdapterFile
|
cppAdapterFile = cExportFiles.cppAdapter
|
||||||
)
|
)
|
||||||
runPhase(CExportGenerateApiPhase, input)
|
runPhase(CExportGenerateApiPhase, input)
|
||||||
runPhase(CExportCompileAdapterPhase, CExportCompileAdapterInput(cppAdapterFile, bitcodeAdapterFile))
|
runPhase(CExportCompileAdapterPhase, CExportCompileAdapterInput(cExportFiles.cppAdapter, cExportFiles.bitcodeAdapter))
|
||||||
listOf(bitcodeAdapterFile)
|
listOf(cExportFiles.bitcodeAdapter)
|
||||||
} else {
|
} else {
|
||||||
emptyList()
|
emptyList()
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-1
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.konan.CacheSupport
|
|||||||
import org.jetbrains.kotlin.backend.konan.KonanConfig
|
import org.jetbrains.kotlin.backend.konan.KonanConfig
|
||||||
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
|
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
|
||||||
import org.jetbrains.kotlin.konan.TempFiles
|
import org.jetbrains.kotlin.konan.TempFiles
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
internal fun createTempFiles(config: KonanConfig, cacheDeserializationStrategy: CacheDeserializationStrategy?): TempFiles {
|
internal fun createTempFiles(config: KonanConfig, cacheDeserializationStrategy: CacheDeserializationStrategy?): TempFiles {
|
||||||
val pathToTempDir = config.configuration.get(KonanConfigKeys.TEMPORARY_FILES_DIR)?.let {
|
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
|
else org.jetbrains.kotlin.konan.file.File(it, CacheSupport.cacheFileId(singleFileStrategy.fqName, singleFileStrategy.filePath)).path
|
||||||
}
|
}
|
||||||
return TempFiles(pathToTempDir)
|
return TempFiles(pathToTempDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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?,
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user