[K/N] Refactor module splitting for backend
We want to extract tempFiles from NativeGenerationState. To do so, we need to move creation of NativeGenerationState from `splitIntoFragments` function and untie CacheLlvmModuleSpecification from NativeGenerationState
This commit is contained in:
committed by
Space Team
parent
eba1b4c388
commit
b7b85177a7
+4
-2
@@ -44,9 +44,11 @@ internal val NativeGenerationState.shouldDefineCachedBoxes: Boolean
|
|||||||
get() = producedLlvmModuleContainsStdlib &&
|
get() = producedLlvmModuleContainsStdlib &&
|
||||||
cacheDeserializationStrategy?.contains(KonanFqNames.internalPackageName, "Boxing.kt") != false
|
cacheDeserializationStrategy?.contains(KonanFqNames.internalPackageName, "Boxing.kt") != false
|
||||||
|
|
||||||
|
internal val CacheDeserializationStrategy?.containsRuntime: Boolean
|
||||||
|
get() = this?.contains(KonanFqNames.internalPackageName, "Runtime.kt") != false
|
||||||
|
|
||||||
internal val NativeGenerationState.shouldLinkRuntimeNativeLibraries: Boolean
|
internal val NativeGenerationState.shouldLinkRuntimeNativeLibraries: Boolean
|
||||||
get() = producedLlvmModuleContainsStdlib &&
|
get() = producedLlvmModuleContainsStdlib && cacheDeserializationStrategy.containsRuntime
|
||||||
cacheDeserializationStrategy?.contains(KonanFqNames.internalPackageName, "Runtime.kt") != false
|
|
||||||
|
|
||||||
val CompilerOutputKind.isCache: Boolean
|
val CompilerOutputKind.isCache: Boolean
|
||||||
get() = this == CompilerOutputKind.STATIC_CACHE || this == CompilerOutputKind.DYNAMIC_CACHE
|
get() = this == CompilerOutputKind.STATIC_CACHE || this == CompilerOutputKind.DYNAMIC_CACHE
|
||||||
|
|||||||
+4
-4
@@ -43,19 +43,19 @@ internal class DefaultLlvmModuleSpecification(cachedLibraries: CachedLibraries)
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal class CacheLlvmModuleSpecification(
|
internal class CacheLlvmModuleSpecification(
|
||||||
private val generationState: NativeGenerationState,
|
|
||||||
cachedLibraries: CachedLibraries,
|
cachedLibraries: CachedLibraries,
|
||||||
private val libraryToCache: PartialCacheInfo
|
private val libraryToCache: PartialCacheInfo,
|
||||||
|
private val containsStdlib: Boolean,
|
||||||
) : LlvmModuleSpecificationBase(cachedLibraries) {
|
) : LlvmModuleSpecificationBase(cachedLibraries) {
|
||||||
override val isFinal = false
|
override val isFinal = false
|
||||||
|
|
||||||
override fun containsLibrary(library: KotlinLibrary): Boolean = library == libraryToCache.klib
|
override fun containsLibrary(library: KotlinLibrary): Boolean = library == libraryToCache.klib
|
||||||
|
|
||||||
override fun containsDeclaration(declaration: IrDeclaration): Boolean {
|
override fun containsDeclaration(declaration: IrDeclaration): Boolean {
|
||||||
if (generationState.shouldDefineFunctionClasses && declaration.getPackageFragment().isFunctionInterfaceFile)
|
if (containsStdlib && libraryToCache.strategy.containsKFunctionImpl && declaration.getPackageFragment().isFunctionInterfaceFile)
|
||||||
return true
|
return true
|
||||||
if (!super.containsDeclaration(declaration)) return false
|
if (!super.containsDeclaration(declaration)) return false
|
||||||
return (generationState.cacheDeserializationStrategy as? CacheDeserializationStrategy.SingleFile)
|
return (libraryToCache.strategy as? CacheDeserializationStrategy.SingleFile)
|
||||||
?.filePath.let { it == null || it == declaration.fileOrNull?.path }
|
?.filePath.let { it == null || it == declaration.fileOrNull?.path }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-2
@@ -9,6 +9,7 @@ import llvm.*
|
|||||||
import org.jetbrains.kotlin.backend.konan.driver.BasicPhaseContext
|
import org.jetbrains.kotlin.backend.konan.driver.BasicPhaseContext
|
||||||
import org.jetbrains.kotlin.backend.konan.driver.utilities.BackendContextHolder
|
import org.jetbrains.kotlin.backend.konan.driver.utilities.BackendContextHolder
|
||||||
import org.jetbrains.kotlin.backend.konan.driver.utilities.LlvmIrHolder
|
import org.jetbrains.kotlin.backend.konan.driver.utilities.LlvmIrHolder
|
||||||
|
import org.jetbrains.kotlin.backend.konan.ir.konanLibrary
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.coverage.CoverageManager
|
import org.jetbrains.kotlin.backend.konan.llvm.coverage.CoverageManager
|
||||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport
|
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport
|
||||||
@@ -79,8 +80,11 @@ internal class NativeGenerationState(
|
|||||||
|
|
||||||
val llvmModuleSpecification by lazy {
|
val llvmModuleSpecification by lazy {
|
||||||
if (config.produce.isCache)
|
if (config.produce.isCache)
|
||||||
CacheLlvmModuleSpecification(this, config.cachedLibraries,
|
CacheLlvmModuleSpecification(
|
||||||
PartialCacheInfo(config.libraryToCache!!.klib, cacheDeserializationStrategy!!))
|
config.cachedLibraries,
|
||||||
|
PartialCacheInfo(config.libraryToCache!!.klib, cacheDeserializationStrategy!!),
|
||||||
|
containsStdlib = config.libraryToCache!!.klib == context.stdlibModule.konanLibrary
|
||||||
|
)
|
||||||
else DefaultLlvmModuleSpecification(config.cachedLibraries)
|
else DefaultLlvmModuleSpecification(config.cachedLibraries)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+56
-29
@@ -8,6 +8,7 @@ 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.ir.konanLibrary
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.getName
|
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
|
||||||
@@ -55,10 +56,13 @@ internal fun <C : PhaseContext> PhaseEngine<C>.runBackend(backendContext: Contex
|
|||||||
useContext(backendContext) { backendEngine ->
|
useContext(backendContext) { backendEngine ->
|
||||||
backendEngine.runPhase(functionsWithoutBoundCheck)
|
backendEngine.runPhase(functionsWithoutBoundCheck)
|
||||||
val fragments = backendEngine.splitIntoFragments(irModule)
|
val fragments = backendEngine.splitIntoFragments(irModule)
|
||||||
fragments.forEach { (generationState, fragment) ->
|
fragments.forEach { fragment ->
|
||||||
|
val generationState = NativeGenerationState(context.config, backendContext,
|
||||||
|
fragment.cacheDeserializationStrategy
|
||||||
|
)
|
||||||
backendEngine.useContext(generationState) { generationStateEngine ->
|
backendEngine.useContext(generationState) { generationStateEngine ->
|
||||||
// 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)
|
val it = generationStateEngine.compileModule(fragment.irModule)
|
||||||
// Split here
|
// Split here
|
||||||
compileAndLink(it, it.outputFiles.mainFileName, it.outputFiles, it.temporaryFiles, isCoverageEnabled = false)
|
compileAndLink(it, it.outputFiles.mainFileName, it.outputFiles, it.temporaryFiles, isCoverageEnabled = false)
|
||||||
}
|
}
|
||||||
@@ -74,41 +78,64 @@ private fun isReferencedByNativeRuntime(declarations: List<IrDeclaration>): Bool
|
|||||||
it is IrClass && isReferencedByNativeRuntime(it.declarations)
|
it is IrClass && isReferencedByNativeRuntime(it.declarations)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private data class BackendJobFragment(
|
||||||
|
val irModule: IrModuleFragment,
|
||||||
|
val cacheDeserializationStrategy: CacheDeserializationStrategy?,
|
||||||
|
val dependenciesTracker: DependenciesTracker,
|
||||||
|
val llvmModuleSpecification: LlvmModuleSpecification,
|
||||||
|
)
|
||||||
|
|
||||||
private fun PhaseEngine<out Context>.splitIntoFragments(
|
private fun PhaseEngine<out Context>.splitIntoFragments(
|
||||||
input: IrModuleFragment,
|
input: IrModuleFragment,
|
||||||
): Sequence<Pair<NativeGenerationState, IrModuleFragment>> = if (context.config.producePerFileCache) {
|
): Sequence<BackendJobFragment> {
|
||||||
val module = input
|
val config = context.config
|
||||||
val files = module.files.toList()
|
return if (context.config.producePerFileCache) {
|
||||||
val stdlibIsBeingCached = module.descriptor == context.stdlibModule
|
val files = input.files.toList()
|
||||||
val functionInterfaceFiles = files.takeIf { stdlibIsBeingCached }
|
val containsStdlib = config.libraryToCache!!.klib == context.stdlibModule.konanLibrary
|
||||||
?.filter { it.isFunctionInterfaceFile }.orEmpty()
|
|
||||||
val filesReferencedByNativeRuntime = files.takeIf { stdlibIsBeingCached }
|
|
||||||
?.filter { isReferencedByNativeRuntime(it.declarations) }.orEmpty()
|
|
||||||
|
|
||||||
files.asSequence().filter { !it.isFunctionInterfaceFile }.map { file ->
|
files.asSequence().filter { !it.isFunctionInterfaceFile }.map { file ->
|
||||||
val generationState = NativeGenerationState(
|
val cacheDeserializationStrategy = CacheDeserializationStrategy.SingleFile(file.path, file.fqName.asString())
|
||||||
context.config,
|
val llvmModuleSpecification = CacheLlvmModuleSpecification(
|
||||||
context,
|
config.cachedLibraries,
|
||||||
CacheDeserializationStrategy.SingleFile(file.path, file.fqName.asString())
|
PartialCacheInfo(config.libraryToCache!!.klib, cacheDeserializationStrategy),
|
||||||
)
|
containsStdlib = containsStdlib
|
||||||
val fragment = IrModuleFragmentImpl(input.descriptor, input.irBuiltins, listOf(file))
|
)
|
||||||
if (generationState.shouldDefineFunctionClasses)
|
val dependenciesTracker = DependenciesTrackerImpl(llvmModuleSpecification, context.config, context)
|
||||||
fragment.files += functionInterfaceFiles
|
val fragment = IrModuleFragmentImpl(input.descriptor, input.irBuiltins, listOf(file))
|
||||||
|
if (containsStdlib && cacheDeserializationStrategy.containsKFunctionImpl)
|
||||||
|
fragment.files += files.filter { it.isFunctionInterfaceFile }
|
||||||
|
|
||||||
if (generationState.shouldLinkRuntimeNativeLibraries) {
|
if (containsStdlib && cacheDeserializationStrategy.containsRuntime) {
|
||||||
filesReferencedByNativeRuntime.forEach {
|
files.filter { isReferencedByNativeRuntime(it.declarations) }
|
||||||
generationState.dependenciesTracker.add(it)
|
.forEach { dependenciesTracker.add(it) }
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fragment.files.filterIsInstance<IrFileImpl>().forEach {
|
fragment.files.filterIsInstance<IrFileImpl>().forEach {
|
||||||
it.module = fragment
|
it.module = fragment
|
||||||
|
}
|
||||||
|
BackendJobFragment(
|
||||||
|
fragment,
|
||||||
|
cacheDeserializationStrategy,
|
||||||
|
dependenciesTracker,
|
||||||
|
llvmModuleSpecification,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
generationState to fragment
|
} else {
|
||||||
|
val llvmModuleSpecification = if (config.produce.isCache) {
|
||||||
|
val containsStdlib = config.libraryToCache!!.klib == context.stdlibModule.konanLibrary
|
||||||
|
CacheLlvmModuleSpecification(config.cachedLibraries, context.config.libraryToCache!!, containsStdlib = containsStdlib)
|
||||||
|
} else {
|
||||||
|
DefaultLlvmModuleSpecification(config.cachedLibraries)
|
||||||
|
}
|
||||||
|
sequenceOf(
|
||||||
|
BackendJobFragment(
|
||||||
|
input,
|
||||||
|
context.config.libraryToCache?.strategy,
|
||||||
|
DependenciesTrackerImpl(llvmModuleSpecification, context.config, context),
|
||||||
|
llvmModuleSpecification
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
val nativeGenerationState = NativeGenerationState(context.config, context, context.config.libraryToCache?.strategy)
|
|
||||||
sequenceOf(nativeGenerationState to input)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal data class ModuleCompilationOutput(
|
internal data class ModuleCompilationOutput(
|
||||||
|
|||||||
Reference in New Issue
Block a user