JVM IR: move codegen out of the main phases
This is needed in order to be able to invoke lowerings and codegen separately, for cyclically dependent modules (KT-49575). A side effect is that the two codegen phases are no longer configurable via the phaser, i.e. absent in the -Xlist-phases and can't be disabled or made verbose.
This commit is contained in:
+6
-7
@@ -221,22 +221,21 @@ open class JvmIrCodegenFactory(
|
||||
)
|
||||
JvmIrSerializerImpl(state.configuration)
|
||||
else null
|
||||
val phases = prefixPhases?.then(jvmPhases) ?: jvmPhases
|
||||
val phases = prefixPhases?.then(jvmLoweringPhases) ?: jvmLoweringPhases
|
||||
val phaseConfig = customPhaseConfig ?: PhaseConfig(phases)
|
||||
val context = JvmBackendContext(
|
||||
state, irModuleFragment.irBuiltins, irModuleFragment, symbolTable, phaseConfig, extensions, backendExtension, irSerializer,
|
||||
notifyCodegenStart,
|
||||
)
|
||||
/* JvmBackendContext creates new unbound symbols, have to resolve them. */
|
||||
ExternalDependenciesGenerator(symbolTable, irProviders).generateUnboundSymbolsAsDependencies()
|
||||
|
||||
context.state.factory.registerSourceFiles(irModuleFragment.files.map(IrFile::getKtFile))
|
||||
|
||||
phases.invokeToplevel(
|
||||
phaseConfig,
|
||||
context,
|
||||
irModuleFragment
|
||||
)
|
||||
phases.invokeToplevel(phaseConfig, context, irModuleFragment)
|
||||
|
||||
notifyCodegenStart()
|
||||
|
||||
jvmCodegenPhases.invokeToplevel(phaseConfig, context, irModuleFragment)
|
||||
|
||||
// TODO: split classes into groups connected by inline calls; call this after every group
|
||||
// and clear `JvmBackendContext.classCodegens`
|
||||
|
||||
+24
-32
@@ -6,19 +6,16 @@
|
||||
package org.jetbrains.kotlin.backend.jvm
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.phaser.*
|
||||
import org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.backend.common.phaser.performByIrFile
|
||||
import org.jetbrains.kotlin.backend.common.phaser.then
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
|
||||
private val notifyCodegenStartPhase = makeCustomPhase<JvmBackendContext, IrModuleFragment>(
|
||||
op = { context, _ -> context.notifyCodegenStart() },
|
||||
name = "NotifyCodegenStart",
|
||||
description = "Notify time measuring subsystem that code generation is being started",
|
||||
)
|
||||
|
||||
private fun codegenPhase(generateMultifileFacade: Boolean): NamedCompilerPhase<JvmBackendContext, IrModuleFragment> {
|
||||
val suffix = if (generateMultifileFacade) "MultifileFacades" else "Regular"
|
||||
val descriptionSuffix = if (generateMultifileFacade) ", multifile facades" else ", regular files"
|
||||
@@ -28,21 +25,7 @@ private fun codegenPhase(generateMultifileFacade: Boolean): NamedCompilerPhase<J
|
||||
copyBeforeLowering = false,
|
||||
lower = listOf(
|
||||
makeIrFilePhase(
|
||||
{ context ->
|
||||
object : FileLoweringPass {
|
||||
override fun lower(irFile: IrFile) {
|
||||
val isMultifileFacade = irFile.fileEntry is MultifileFacadeFileEntry
|
||||
if (isMultifileFacade == generateMultifileFacade) {
|
||||
for (loweredClass in irFile.declarations) {
|
||||
if (loweredClass !is IrClass) {
|
||||
throw AssertionError("File-level declaration should be IrClass after JvmLower, got: " + loweredClass.render())
|
||||
}
|
||||
ClassCodegen.getOrCreate(loweredClass, context).generate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{ context -> FileCodegen(context, generateMultifileFacade) },
|
||||
name = "Codegen$suffix",
|
||||
description = "Code generation"
|
||||
)
|
||||
@@ -50,10 +33,24 @@ private fun codegenPhase(generateMultifileFacade: Boolean): NamedCompilerPhase<J
|
||||
)
|
||||
}
|
||||
|
||||
private class FileCodegen(private val context: JvmBackendContext, private val generateMultifileFacade: Boolean) : FileLoweringPass {
|
||||
override fun lower(irFile: IrFile) {
|
||||
val isMultifileFacade = irFile.fileEntry is MultifileFacadeFileEntry
|
||||
if (isMultifileFacade == generateMultifileFacade) {
|
||||
for (loweredClass in irFile.declarations) {
|
||||
if (loweredClass !is IrClass) {
|
||||
throw AssertionError("File-level declaration should be IrClass after JvmLower, got: " + loweredClass.render())
|
||||
}
|
||||
ClassCodegen.getOrCreate(loweredClass, context).generate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generate multifile facades first, to compute and store JVM signatures of const properties which are later used
|
||||
// when serializing metadata in the multifile parts.
|
||||
// TODO: consider dividing codegen itself into separate phases (bytecode generation, metadata serialization) to avoid this
|
||||
private val jvmCodegenPhases = NamedCompilerPhase(
|
||||
internal val jvmCodegenPhases = NamedCompilerPhase(
|
||||
name = "Codegen",
|
||||
description = "Code generation",
|
||||
nlevels = 1,
|
||||
@@ -61,12 +58,7 @@ private val jvmCodegenPhases = NamedCompilerPhase(
|
||||
codegenPhase(generateMultifileFacade = false)
|
||||
)
|
||||
|
||||
val jvmPhases = NamedCompilerPhase(
|
||||
name = "IrBackend",
|
||||
description = "IR Backend for JVM",
|
||||
nlevels = 1,
|
||||
actions = setOf(defaultDumper, validationAction),
|
||||
lower = jvmLoweringPhases then
|
||||
notifyCodegenStartPhase then
|
||||
jvmCodegenPhases
|
||||
)
|
||||
// This property is needed to avoid dependencies from "leaf" modules (cli, tests-common-new) on backend.jvm:lower.
|
||||
// It's used to create PhaseConfig and is the only thing needed from lowerings in the leaf modules.
|
||||
val jvmPhases: NamedCompilerPhase<JvmBackendContext, IrModuleFragment>
|
||||
get() = jvmLoweringPhases
|
||||
|
||||
@@ -390,6 +390,7 @@ val jvmLoweringPhases = NamedCompilerPhase(
|
||||
name = "IrLowering",
|
||||
description = "IR lowering",
|
||||
nlevels = 1,
|
||||
actions = setOf(defaultDumper, validationAction),
|
||||
lower = validateIrBeforeLowering then
|
||||
processOptionalAnnotationsPhase then
|
||||
expectDeclarationsRemovingPhase then
|
||||
|
||||
@@ -48,7 +48,6 @@ class JvmBackendContext(
|
||||
val generatorExtensions: JvmGeneratorExtensions,
|
||||
val backendExtension: JvmBackendExtension,
|
||||
val irSerializer: JvmIrSerializer?,
|
||||
val notifyCodegenStart: () -> Unit
|
||||
) : CommonBackendContext {
|
||||
// If the JVM fqname of a class differs from what is implied by its parent, e.g. if it's a file class
|
||||
// annotated with @JvmPackageName, the correct name is recorded here.
|
||||
|
||||
Reference in New Issue
Block a user