JVM IR: introduce CodegenFactory.convertToIr
The steps of psi2ir and JVM backend need to be separated in the API because in case of cyclic module dependencies (which are allowed in JPS) psi2ir should be run first on all sources, and then JVM backend on each module separately. `CodegenFactory.convertToIr` does nothing in the old backend. Also, move the ignoreErrors to GenerationState for simplicity.
This commit is contained in:
@@ -16,15 +16,43 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.util.containers.MultiMap
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
|
||||
interface CodegenFactory {
|
||||
fun generateModule(state: GenerationState, files: Collection<KtFile>)
|
||||
fun convertToIr(input: IrConversionInput): BackendInput
|
||||
|
||||
fun generateModule(state: GenerationState, input: BackendInput)
|
||||
|
||||
class IrConversionInput(
|
||||
val project: Project,
|
||||
val files: Collection<KtFile>,
|
||||
val configuration: CompilerConfiguration,
|
||||
val module: ModuleDescriptor,
|
||||
val bindingContext: BindingContext,
|
||||
val languageVersionSettings: LanguageVersionSettings,
|
||||
val ignoreErrors: Boolean,
|
||||
) {
|
||||
companion object {
|
||||
fun fromGenerationState(state: GenerationState): IrConversionInput =
|
||||
with(state) {
|
||||
IrConversionInput(
|
||||
project, files, configuration, module, originalFrontendBindingContext, languageVersionSettings, ignoreErrors
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface BackendInput
|
||||
|
||||
companion object {
|
||||
fun doCheckCancelled(state: GenerationState) {
|
||||
@@ -36,11 +64,15 @@ interface CodegenFactory {
|
||||
}
|
||||
|
||||
object DefaultCodegenFactory : CodegenFactory {
|
||||
override fun generateModule(state: GenerationState, files: Collection<KtFile>) {
|
||||
object DummyOldBackendInput : CodegenFactory.BackendInput
|
||||
|
||||
override fun convertToIr(input: CodegenFactory.IrConversionInput): CodegenFactory.BackendInput = DummyOldBackendInput
|
||||
|
||||
override fun generateModule(state: GenerationState, input: CodegenFactory.BackendInput) {
|
||||
val filesInPackages = MultiMap<FqName, KtFile>()
|
||||
val filesInMultifileClasses = MultiMap<FqName, KtFile>()
|
||||
|
||||
for (file in files) {
|
||||
for (file in state.files) {
|
||||
val fileClassInfo = JvmFileClassUtil.getFileClassInfoNoResolve(file)
|
||||
|
||||
if (fileClassInfo.withJvmMultifileClass) {
|
||||
|
||||
@@ -32,7 +32,12 @@ public class KotlinCodegenFacade {
|
||||
|
||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
|
||||
|
||||
state.getCodegenFactory().generateModule(state, state.getFiles());
|
||||
CodegenFactory.IrConversionInput psi2irInput = CodegenFactory.IrConversionInput.Companion.fromGenerationState(state);
|
||||
CodegenFactory.BackendInput backendInput = state.getCodegenFactory().convertToIr(psi2irInput);
|
||||
|
||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
|
||||
|
||||
state.getCodegenFactory().generateModule(state, backendInput);
|
||||
|
||||
CodegenFactory.Companion.doCheckCancelled(state);
|
||||
state.getFactory().done();
|
||||
|
||||
@@ -67,9 +67,9 @@ class GenerationState private constructor(
|
||||
private val onIndependentPartCompilationEnd: GenerationStateEventCallback,
|
||||
wantsDiagnostics: Boolean,
|
||||
val jvmBackendClassResolver: JvmBackendClassResolver,
|
||||
val isIrBackend: Boolean
|
||||
val isIrBackend: Boolean,
|
||||
val ignoreErrors: Boolean,
|
||||
) {
|
||||
|
||||
class Builder(
|
||||
private val project: Project,
|
||||
private val builderFactory: ClassBuilderFactory,
|
||||
@@ -118,12 +118,16 @@ class GenerationState private constructor(
|
||||
fun isIrBackend(v: Boolean) =
|
||||
apply { isIrBackend = v }
|
||||
|
||||
var ignoreErrors: Boolean = false
|
||||
fun ignoreErrors(v: Boolean): Builder =
|
||||
apply { ignoreErrors = v }
|
||||
|
||||
fun build() =
|
||||
GenerationState(
|
||||
project, builderFactory, module, bindingContext, files, configuration,
|
||||
generateDeclaredClassFilter, codegenFactory, targetId,
|
||||
moduleName, outDirectory, onIndependentPartCompilationEnd, wantsDiagnostics,
|
||||
jvmBackendClassResolver, isIrBackend
|
||||
jvmBackendClassResolver, isIrBackend, ignoreErrors
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+18
-25
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
|
||||
import org.jetbrains.kotlin.ir.linkage.IrProvider
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
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
|
||||
@@ -45,7 +44,6 @@ open class JvmIrCodegenFactory(
|
||||
private val jvmGeneratorExtensions: JvmGeneratorExtensionsImpl = JvmGeneratorExtensionsImpl(configuration),
|
||||
) : CodegenFactory {
|
||||
data class JvmIrBackendInput(
|
||||
val state: GenerationState,
|
||||
val irModuleFragment: IrModuleFragment,
|
||||
val symbolTable: SymbolTable,
|
||||
val phaseConfig: PhaseConfig?,
|
||||
@@ -53,26 +51,20 @@ open class JvmIrCodegenFactory(
|
||||
val extensions: JvmGeneratorExtensionsImpl,
|
||||
val backendExtension: JvmBackendExtension,
|
||||
val notifyCodegenStart: () -> Unit,
|
||||
)
|
||||
) : CodegenFactory.BackendInput
|
||||
|
||||
override fun generateModule(state: GenerationState, files: Collection<KtFile>) {
|
||||
val input = convertToIr(state, files)
|
||||
doGenerateFilesInternal(input)
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun convertToIr(state: GenerationState, files: Collection<KtFile>, ignoreErrors: Boolean = false): JvmIrBackendInput {
|
||||
override fun convertToIr(input: CodegenFactory.IrConversionInput): JvmIrBackendInput {
|
||||
val (mangler, symbolTable) =
|
||||
if (externalSymbolTable != null) externalMangler!! to externalSymbolTable
|
||||
else {
|
||||
val mangler = JvmDescriptorMangler(MainFunctionDetector(state.bindingContext, state.languageVersionSettings))
|
||||
val mangler = JvmDescriptorMangler(MainFunctionDetector(input.bindingContext, input.languageVersionSettings))
|
||||
val symbolTable = SymbolTable(JvmIdSignatureDescriptor(mangler), IrFactoryImpl, JvmNameProvider)
|
||||
mangler to symbolTable
|
||||
}
|
||||
val psi2ir = Psi2IrTranslator(state.languageVersionSettings, Psi2IrConfiguration(ignoreErrors))
|
||||
val messageLogger = state.configuration[IrMessageLogger.IR_MESSAGE_LOGGER] ?: IrMessageLogger.None
|
||||
val psi2irContext = psi2ir.createGeneratorContext(state.module, state.bindingContext, symbolTable, jvmGeneratorExtensions)
|
||||
val pluginExtensions = IrGenerationExtension.getInstances(state.project)
|
||||
val psi2ir = Psi2IrTranslator(input.languageVersionSettings, Psi2IrConfiguration(input.ignoreErrors))
|
||||
val messageLogger = input.configuration[IrMessageLogger.IR_MESSAGE_LOGGER] ?: IrMessageLogger.None
|
||||
val psi2irContext = psi2ir.createGeneratorContext(input.module, input.bindingContext, symbolTable, jvmGeneratorExtensions)
|
||||
val pluginExtensions = IrGenerationExtension.getInstances(input.project)
|
||||
|
||||
val stubGenerator =
|
||||
DeclarationStubGeneratorImpl(psi2irContext.moduleDescriptor, symbolTable, psi2irContext.irBuiltIns, jvmGeneratorExtensions)
|
||||
@@ -111,7 +103,7 @@ open class JvmIrCodegenFactory(
|
||||
}
|
||||
}
|
||||
|
||||
SourceDeclarationsPreprocessor(psi2irContext).run(files)
|
||||
SourceDeclarationsPreprocessor(psi2irContext).run(input.files)
|
||||
|
||||
for (extension in pluginExtensions) {
|
||||
psi2ir.addPostprocessingStep { module ->
|
||||
@@ -143,7 +135,7 @@ open class JvmIrCodegenFactory(
|
||||
val irProviders = listOf(irLinker)
|
||||
|
||||
val irModuleFragment =
|
||||
psi2ir.generateModuleFragment(psi2irContext, files, irProviders, pluginExtensions, expectDescriptorToSymbol = null)
|
||||
psi2ir.generateModuleFragment(psi2irContext, input.files, irProviders, pluginExtensions, expectDescriptorToSymbol = null)
|
||||
irLinker.postProcess()
|
||||
|
||||
stubGenerator.unboundSymbolGeneration = true
|
||||
@@ -151,13 +143,12 @@ open class JvmIrCodegenFactory(
|
||||
// We need to compile all files we reference in Klibs
|
||||
irModuleFragment.files.addAll(dependencies.flatMap { it.files })
|
||||
|
||||
if (!state.configuration.getBoolean(JVMConfigurationKeys.DO_NOT_CLEAR_BINDING_CONTEXT)) {
|
||||
val originalBindingContext = state.originalFrontendBindingContext as? CleanableBindingContext
|
||||
?: error("BindingContext should be cleanable in JVM IR to avoid leaking memory: ${state.originalFrontendBindingContext}")
|
||||
if (!input.configuration.getBoolean(JVMConfigurationKeys.DO_NOT_CLEAR_BINDING_CONTEXT)) {
|
||||
val originalBindingContext = input.bindingContext as? CleanableBindingContext
|
||||
?: error("BindingContext should be cleanable in JVM IR to avoid leaking memory: ${input.bindingContext}")
|
||||
originalBindingContext.clear()
|
||||
}
|
||||
return JvmIrBackendInput(
|
||||
state,
|
||||
irModuleFragment,
|
||||
symbolTable,
|
||||
phaseConfig,
|
||||
@@ -177,8 +168,9 @@ open class JvmIrCodegenFactory(
|
||||
return result.toList()
|
||||
}
|
||||
|
||||
fun doGenerateFilesInternal(input: JvmIrBackendInput) {
|
||||
val (state, irModuleFragment, symbolTable, customPhaseConfig, irProviders, extensions, backendExtension, notifyCodegenStart) = input
|
||||
override fun generateModule(state: GenerationState, input: CodegenFactory.BackendInput) {
|
||||
val (irModuleFragment, symbolTable, customPhaseConfig, irProviders, extensions, backendExtension, notifyCodegenStart) =
|
||||
input as JvmIrBackendInput
|
||||
val irSerializer = if (state.configuration.getBoolean(JVMConfigurationKeys.SERIALIZE_IR))
|
||||
JvmIrSerializerImpl(state.configuration)
|
||||
else null
|
||||
@@ -208,9 +200,10 @@ open class JvmIrCodegenFactory(
|
||||
notifyCodegenStart: () -> Unit = {}
|
||||
) {
|
||||
val irProviders = configureBuiltInsAndGenerateIrProvidersInFrontendIRMode(irModuleFragment, symbolTable, extensions)
|
||||
doGenerateFilesInternal(
|
||||
generateModule(
|
||||
state,
|
||||
JvmIrBackendInput(
|
||||
state, irModuleFragment, symbolTable, phaseConfig, irProviders, extensions, backendExtension, notifyCodegenStart
|
||||
irModuleFragment, symbolTable, phaseConfig, irProviders, extensions, backendExtension, notifyCodegenStart
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -6,11 +6,13 @@
|
||||
package org.jetbrains.kotlin.test.backend.ir
|
||||
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.test.model.BackendKinds
|
||||
import org.jetbrains.kotlin.test.model.ResultingArtifact
|
||||
|
||||
// IR backend (JVM, JS, Native)
|
||||
data class IrBackendInput(
|
||||
val state: GenerationState,
|
||||
val backendInput: JvmIrCodegenFactory.JvmIrBackendInput
|
||||
) : ResultingArtifact.BackendInput<IrBackendInput>() {
|
||||
override val kind: BackendKinds.IrBackend
|
||||
|
||||
+2
-2
@@ -22,10 +22,10 @@ class JvmIrBackendFacade(
|
||||
module: TestModule,
|
||||
inputArtifact: IrBackendInput
|
||||
): BinaryArtifacts.Jvm? {
|
||||
val state = inputArtifact.backendInput.state
|
||||
val state = inputArtifact.state
|
||||
val codegenFactory = state.codegenFactory as JvmIrCodegenFactory
|
||||
try {
|
||||
codegenFactory.doGenerateFilesInternal(inputArtifact.backendInput)
|
||||
codegenFactory.generateModule(state, inputArtifact.backendInput)
|
||||
} catch (e: BackendException) {
|
||||
if (CodegenTestDirectives.IGNORE_ERRORS in module.directives) {
|
||||
return null
|
||||
|
||||
+3
-2
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.test.frontend.classic
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory
|
||||
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilderFactories
|
||||
import org.jetbrains.kotlin.codegen.CodegenFactory
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.test.backend.ir.IrBackendInput
|
||||
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives
|
||||
@@ -41,9 +42,9 @@ class ClassicFrontend2IrConverter(
|
||||
files, configuration
|
||||
).codegenFactory(codegenFactory)
|
||||
.isIrBackend(true)
|
||||
.ignoreErrors(CodegenTestDirectives.IGNORE_ERRORS in module.directives)
|
||||
.build()
|
||||
|
||||
val ignoreErrors = CodegenTestDirectives.IGNORE_ERRORS in module.directives
|
||||
return IrBackendInput(codegenFactory.convertToIr(state, files, ignoreErrors))
|
||||
return IrBackendInput(state, codegenFactory.convertToIr(CodegenFactory.IrConversionInput.fromGenerationState(state)))
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -75,8 +75,8 @@ class Fir2IrResultsConverter(
|
||||
val irProviders = codegenFactory.configureBuiltInsAndGenerateIrProvidersInFrontendIRMode(irModuleFragment, symbolTable, extensions)
|
||||
|
||||
return IrBackendInput(
|
||||
generationState,
|
||||
JvmIrCodegenFactory.JvmIrBackendInput(
|
||||
generationState,
|
||||
irModuleFragment,
|
||||
symbolTable,
|
||||
phaseConfig,
|
||||
|
||||
+5
-1
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.cli.common.messages.MessageCollectorBasedReporter
|
||||
import org.jetbrains.kotlin.cli.common.repl.LineId
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilderFactories
|
||||
import org.jetbrains.kotlin.codegen.CodegenFactory
|
||||
import org.jetbrains.kotlin.codegen.KotlinCodegenFacade
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
||||
@@ -200,7 +201,10 @@ open class KJvmReplCompilerBase<AnalyzerT : ReplCodeAnalyzerBase>(
|
||||
.codegenFactory(codegenFactory)
|
||||
.build()
|
||||
|
||||
generationState.codegenFactory.generateModule(generationState, generationState.files)
|
||||
codegenFactory.generateModule(
|
||||
generationState,
|
||||
codegenFactory.convertToIr(CodegenFactory.IrConversionInput.fromGenerationState(generationState)),
|
||||
)
|
||||
|
||||
return generationState
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user