diff --git a/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt b/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt index c07068dabdc..5d728651c16 100644 --- a/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt +++ b/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt @@ -6,14 +6,12 @@ package org.jetbrains.kotlin.backend.jvm import org.jetbrains.kotlin.analyzer.hasJdkCapability -import org.jetbrains.kotlin.backend.common.CodegenUtil import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.common.extensions.IrPluginContextImpl import org.jetbrains.kotlin.backend.common.ir.BuiltinSymbolsBase import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig -import org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen +import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel import org.jetbrains.kotlin.backend.jvm.ir.getKtFile -import org.jetbrains.kotlin.backend.jvm.lower.MultifileFacadeFileEntry import org.jetbrains.kotlin.backend.jvm.serialization.JvmIdSignatureDescriptor import org.jetbrains.kotlin.codegen.CodegenFactory import org.jetbrains.kotlin.codegen.state.GenerationState @@ -25,7 +23,6 @@ import org.jetbrains.kotlin.idea.MainFunctionDetector import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmIrLinker import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmManglerDesc import org.jetbrains.kotlin.ir.builders.TranslationPluginContext -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.declarations.impl.IrFactoryImpl @@ -37,7 +34,6 @@ import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator import org.jetbrains.kotlin.psi2ir.generators.DeclarationStubGeneratorImpl -import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions import org.jetbrains.kotlin.psi2ir.generators.generateTypicalIrProviderList import org.jetbrains.kotlin.resolve.CleanableBindingContext @@ -182,37 +178,16 @@ open class JvmIrCodegenFactory( fun doGenerateFilesInternal(input: JvmIrBackendInput) { val (state, irModuleFragment, symbolTable, phaseConfig, irProviders, extensions, backendExtension, notifyCodegenStart) = input val context = JvmBackendContext( - state, irModuleFragment.irBuiltins, irModuleFragment, symbolTable, phaseConfig, extensions, backendExtension + state, irModuleFragment.irBuiltins, irModuleFragment, symbolTable, phaseConfig, extensions, backendExtension, + notifyCodegenStart ) /* JvmBackendContext creates new unbound symbols, have to resolve them. */ ExternalDependenciesGenerator(symbolTable, irProviders).generateUnboundSymbolsAsDependencies() context.state.factory.registerSourceFiles(irModuleFragment.files.map(IrFile::getKtFile)) - JvmLower(context).lower(irModuleFragment) + jvmPhases.invokeToplevel(phaseConfig, context, irModuleFragment) - notifyCodegenStart() - - for (generateMultifileFacade in listOf(true, false)) { - for (irFile in irModuleFragment.files) { - // 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 - val isMultifileFacade = irFile.fileEntry is MultifileFacadeFileEntry - if (isMultifileFacade != generateMultifileFacade) continue - - try { - 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() - } - } catch (e: Throwable) { - CodegenUtil.reportBackendException(e, "code generation", irFile.fileEntry.name) - } - } - } // TODO: split classes into groups connected by inline calls; call this after every group // and clear `JvmBackendContext.classCodegens` state.afterIndependentPart() @@ -224,7 +199,7 @@ open class JvmIrCodegenFactory( symbolTable: SymbolTable, extensions: JvmGeneratorExtensionsImpl, backendExtension: JvmBackendExtension, - notifyCodegenStart: () -> Unit + notifyCodegenStart: () -> Unit = {} ) { val irProviders = configureBuiltInsAndGenerateIrProvidersInFrontendIRMode(irModuleFragment, symbolTable, extensions) doGenerateFilesInternal( diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt index 8b9593bf902..775fe2f0d72 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt @@ -52,6 +52,7 @@ class JvmBackendContext( val phaseConfig: PhaseConfig, val generatorExtensions: JvmGeneratorExtensions, val backendExtension: JvmBackendExtension, + 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. diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt index 750c062f083..a9efad3802d 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.backend.common.lower.* import org.jetbrains.kotlin.backend.common.lower.loops.forLoopsPhase import org.jetbrains.kotlin.backend.common.lower.optimizations.foldConstantLoweringPhase import org.jetbrains.kotlin.backend.common.phaser.* +import org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen import org.jetbrains.kotlin.backend.jvm.codegen.shouldContainSuspendMarkers import org.jetbrains.kotlin.backend.jvm.lower.* import org.jetbrains.kotlin.descriptors.DescriptorVisibilities @@ -21,6 +22,7 @@ import org.jetbrains.kotlin.ir.symbols.IrValueSymbol import org.jetbrains.kotlin.ir.util.PatchDeclarationParentsVisitor import org.jetbrains.kotlin.ir.util.isAnonymousObject import org.jetbrains.kotlin.ir.util.parentAsClass +import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid @@ -273,6 +275,42 @@ private val kotlinNothingValueExceptionPhase = makeIrFilePhase( + op = { context, _ -> context.notifyCodegenStart() }, + name = "NotifyCodegenStart", + description = "Notify time measuring subsystem that code generation is being started", +) + +private fun codegenPhase(generateMultifileFacade: Boolean): NamedCompilerPhase { + val suffix = if (generateMultifileFacade) "MultifileFacades" else "Regular" + val descriptionSuffix = if (generateMultifileFacade) ", multifile facades" else ", regular files" + return performByIrFile( + name = "CodegenByIrFile$suffix", + description = "Code generation by IrFile$descriptionSuffix", + lower = listOf( + makeIrFilePhase( + { context -> + object : FileLoweringPass { + override fun lower(irFile: IrFile) { + val isMultifileFacade = irFile.fileEntry is MultifileFacadeFileEntry + if (isMultifileFacade != generateMultifileFacade) return + + 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() + } + } + } + }, + name = "Codegen$suffix", + description = "Code generation" + ) + ) + ) +} + private val jvmFilePhases = listOf( typeAliasAnnotationMethodsPhase, stripTypeAliasDeclarationsPhase, @@ -379,11 +417,10 @@ private val jvmFilePhases = listOf( makePatchParentsPhase(3) ) -val jvmPhases = NamedCompilerPhase( +private val jvmLoweringPhases = NamedCompilerPhase( name = "IrLowering", description = "IR lowering", nlevels = 1, - actions = setOf(defaultDumper, validationAction), lower = validateIrBeforeLowering then processOptionalAnnotationsPhase then expectDeclarationsRemovingPhase then @@ -398,9 +435,25 @@ val jvmPhases = NamedCompilerPhase( validateIrAfterLowering ) -class JvmLower(val context: JvmBackendContext) { - fun lower(irModuleFragment: IrModuleFragment) { - // TODO run lowering passes as callbacks in bottom-up visitor - jvmPhases.invokeToplevel(context.phaseConfig, context, irModuleFragment) - } -} +// 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( + name = "Codegen", + description = "Code generation", + nlevels = 1, + lower = codegenPhase(generateMultifileFacade = true) then + 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 +) + diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/Fir2IrResultsConverter.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/Fir2IrResultsConverter.kt index a928f233136..1314d46c86d 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/Fir2IrResultsConverter.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/Fir2IrResultsConverter.kt @@ -87,7 +87,8 @@ class Fir2IrResultsConverter( irProviders, extensions, FirJvmBackendExtension(inputArtifact.session, components), - ) {} + notifyCodegenStart = {}, + ) ) } }