From ea7117d9aba92dfda8cb78a70c8d4d16e955a8aa Mon Sep 17 00:00:00 2001 From: Sergey Bogolepov Date: Tue, 1 Sep 2020 18:00:10 +0700 Subject: [PATCH] Move PSI to IR translation to separate file --- .../jetbrains/kotlin/backend/konan/PsiToIr.kt | 164 ++++++++++++++++++ .../kotlin/backend/konan/ToplevelPhases.kt | 137 +-------------- 2 files changed, 166 insertions(+), 135 deletions(-) create mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/PsiToIr.kt diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/PsiToIr.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/PsiToIr.kt new file mode 100644 index 00000000000..a16dfe69caf --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/PsiToIr.kt @@ -0,0 +1,164 @@ +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.backend.common.LoggingContext +import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension +import org.jetbrains.kotlin.backend.common.extensions.IrPluginContextImpl +import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideChecker +import org.jetbrains.kotlin.backend.common.serialization.mangle.ManglerChecker +import org.jetbrains.kotlin.backend.common.serialization.mangle.descriptor.Ir2DescriptorManglerAdapter +import org.jetbrains.kotlin.backend.konan.descriptors.isForwardDeclarationModule +import org.jetbrains.kotlin.backend.konan.descriptors.isFromInteropLibrary +import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary +import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols +import org.jetbrains.kotlin.backend.konan.ir.interop.IrProviderForCEnumAndCStructStubs +import org.jetbrains.kotlin.backend.konan.serialization.KonanIrLinker +import org.jetbrains.kotlin.backend.konan.serialization.KonanManglerDesc +import org.jetbrains.kotlin.backend.konan.serialization.KonanManglerIr +import org.jetbrains.kotlin.config.CommonConfigurationKeys +import org.jetbrains.kotlin.config.languageVersionSettings +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.descriptors.konan.DeserializedKlibModuleOrigin +import org.jetbrains.kotlin.descriptors.konan.KlibModuleOrigin +import org.jetbrains.kotlin.descriptors.konan.isNativeStdlib +import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator +import org.jetbrains.kotlin.ir.util.SymbolTable +import org.jetbrains.kotlin.ir.util.noUnboundLeft +import org.jetbrains.kotlin.ir.visitors.acceptVoid +import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration +import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator +import org.jetbrains.kotlin.utils.DFS + +internal fun Context.psiToIr(symbolTable: SymbolTable) { + // Translate AST to high level IR. + val expectActualLinker = config.configuration.get(CommonConfigurationKeys.EXPECT_ACTUAL_LINKER)?:false + + val translator = Psi2IrTranslator(config.configuration.languageVersionSettings, Psi2IrConfiguration(false)) + val generatorContext = translator.createGeneratorContext(moduleDescriptor, bindingContext, symbolTable) + + val pluginExtensions = IrGenerationExtension.getInstances(config.project) + + val forwardDeclarationsModuleDescriptor = moduleDescriptor.allDependencyModules.firstOrNull { it.isForwardDeclarationModule } + + val modulesWithoutDCE = moduleDescriptor.allDependencyModules + .filter { !llvmModuleSpecification.isFinal && llvmModuleSpecification.containsModule(it) } + + // Note: using [llvmModuleSpecification] since this phase produces IR for generating single LLVM module. + + val exportedDependencies = (getExportedDependencies() + modulesWithoutDCE).distinct() + val functionIrClassFactory = BuiltInFictitiousFunctionIrClassFactory( + symbolTable, generatorContext.irBuiltIns, reflectionTypes) + generatorContext.irBuiltIns.functionFactory = functionIrClassFactory + val stubGenerator = DeclarationStubGenerator( + moduleDescriptor, symbolTable, + config.configuration.languageVersionSettings + ) + val symbols = KonanSymbols(this, generatorContext.irBuiltIns, symbolTable, symbolTable.lazyWrapper, functionIrClassFactory) + + val irProviderForCEnumsAndCStructs = + IrProviderForCEnumAndCStructStubs(generatorContext, interopBuiltIns, symbols) + + val deserializeFakeOverrides = config.configuration.getBoolean(CommonConfigurationKeys.DESERIALIZE_FAKE_OVERRIDES) + + val linker = + KonanIrLinker( + moduleDescriptor, + functionIrClassFactory, + this as LoggingContext, + generatorContext.irBuiltIns, + symbolTable, + forwardDeclarationsModuleDescriptor, + stubGenerator, + irProviderForCEnumsAndCStructs, + exportedDependencies, + deserializeFakeOverrides + ) + + translator.addPostprocessingStep { module -> + val pluginContext = IrPluginContextImpl( + generatorContext.moduleDescriptor, + generatorContext.bindingContext, + generatorContext.languageVersionSettings, + generatorContext.symbolTable, + generatorContext.typeTranslator, + generatorContext.irBuiltIns, + linker = linker + ) + pluginExtensions.forEach { extension -> + extension.generate(module, pluginContext) + } + } + + var dependenciesCount = 0 + while (true) { + // context.config.librariesWithDependencies could change at each iteration. + val dependencies = moduleDescriptor.allDependencyModules.filter { + config.librariesWithDependencies(moduleDescriptor).contains(it.konanLibrary) + } + + fun sortDependencies(dependencies: List): Collection { + return DFS.topologicalOrder(dependencies) { + it.allDependencyModules + }.reversed() + } + + for (dependency in sortDependencies(dependencies).filter { it != moduleDescriptor }) { + val kotlinLibrary = dependency.getCapability(KlibModuleOrigin.CAPABILITY)?.let { + (it as? DeserializedKlibModuleOrigin)?.library + } + linker.deserializeIrModuleHeader(dependency, kotlinLibrary) + } + if (dependencies.size == dependenciesCount) break + dependenciesCount = dependencies.size + } + + // We need to run `buildAllEnumsAndStructsFrom` before `generateModuleFragment` because it adds references to symbolTable + // that should be bound. + modulesWithoutDCE + .filter(ModuleDescriptor::isFromInteropLibrary) + .forEach(irProviderForCEnumsAndCStructs::referenceAllEnumsAndStructsFrom) + + val irProviders = listOf(linker) + + expectDescriptorToSymbol = mutableMapOf() + val module = translator.generateModuleFragment( + generatorContext, + environment.getSourceFiles(), + irProviders, + pluginExtensions, + // TODO: This is a hack to allow platform libs to build in reasonable time. + // referenceExpectsForUsedActuals() appears to be quadratic in time because of + // how ExpectedActualResolver is implemented. + // Need to fix ExpectActualResolver to either cache expects or somehow reduce the member scope searches. + if (expectActualLinker) expectDescriptorToSymbol else null + ) + + linker.postProcess() + + if (this.stdlibModule in modulesWithoutDCE) { + functionIrClassFactory.buildAllClasses() + } + + // Enable lazy IR genration for newly-created symbols inside BE + stubGenerator.unboundSymbolGeneration = true + + symbolTable.noUnboundLeft("Unbound symbols left after linker") + + module.acceptVoid(ManglerChecker(KonanManglerIr, Ir2DescriptorManglerAdapter(KonanManglerDesc))) + if (!config.configuration.getBoolean(KonanConfigKeys.DISABLE_FAKE_OVERRIDE_VALIDATOR)) { + val fakeOverrideChecker = FakeOverrideChecker(KonanManglerIr, KonanManglerDesc) + linker.modules.values.forEach { fakeOverrideChecker.check(it) } + } + + irModule = module + + // Note: coupled with [shouldLower] below. + irModules = linker.modules.filterValues { llvmModuleSpecification.containsModule(it) } + + ir.symbols = symbols + + functionIrClassFactory.module = + (listOf(irModule!!) + linker.modules.values) + .single { it.descriptor.isNativeStdlib() } +} \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt index 4ee646401f1..bfdcf97a617 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt @@ -143,142 +143,9 @@ internal val buildCExportsPhase = konanUnitPhase( ) internal val psiToIrPhase = konanUnitPhase( - op = { - // Translate AST to high level IR. - val expectActualLinker = config.configuration.get(CommonConfigurationKeys.EXPECT_ACTUAL_LINKER)?:false - - val symbolTable = symbolTable!! - - val translator = Psi2IrTranslator(config.configuration.languageVersionSettings, Psi2IrConfiguration(false)) - val generatorContext = translator.createGeneratorContext(moduleDescriptor, bindingContext, symbolTable) - - val pluginExtensions = IrGenerationExtension.getInstances(config.project) - - val forwardDeclarationsModuleDescriptor = moduleDescriptor.allDependencyModules.firstOrNull { it.isForwardDeclarationModule } - - val modulesWithoutDCE = moduleDescriptor.allDependencyModules - .filter { !llvmModuleSpecification.isFinal && llvmModuleSpecification.containsModule(it) } - - // Note: using [llvmModuleSpecification] since this phase produces IR for generating single LLVM module. - - val exportedDependencies = (getExportedDependencies() + modulesWithoutDCE).distinct() - val functionIrClassFactory = BuiltInFictitiousFunctionIrClassFactory( - symbolTable, generatorContext.irBuiltIns, reflectionTypes) - generatorContext.irBuiltIns.functionFactory = functionIrClassFactory - val stubGenerator = DeclarationStubGenerator( - moduleDescriptor, symbolTable, - config.configuration.languageVersionSettings - ) - val symbols = KonanSymbols(this, generatorContext.irBuiltIns, symbolTable, symbolTable.lazyWrapper, functionIrClassFactory) - - val irProviderForCEnumsAndCStructs = - IrProviderForCEnumAndCStructStubs(generatorContext, interopBuiltIns, symbols) - - val deserializeFakeOverrides = config.configuration.getBoolean(CommonConfigurationKeys.DESERIALIZE_FAKE_OVERRIDES) - - val linker = - KonanIrLinker( - moduleDescriptor, - functionIrClassFactory, - this as LoggingContext, - generatorContext.irBuiltIns, - symbolTable, - forwardDeclarationsModuleDescriptor, - stubGenerator, - irProviderForCEnumsAndCStructs, - exportedDependencies, - deserializeFakeOverrides - ) - - translator.addPostprocessingStep { module -> - val pluginContext = IrPluginContextImpl( - generatorContext.moduleDescriptor, - generatorContext.bindingContext, - generatorContext.languageVersionSettings, - generatorContext.symbolTable, - generatorContext.typeTranslator, - generatorContext.irBuiltIns, - linker = linker - ) - pluginExtensions.forEach { extension -> - extension.generate(module, pluginContext) - } - } - - var dependenciesCount = 0 - while (true) { - // context.config.librariesWithDependencies could change at each iteration. - val dependencies = moduleDescriptor.allDependencyModules.filter { - config.librariesWithDependencies(moduleDescriptor).contains(it.konanLibrary) - } - - fun sortDependencies(dependencies: List): Collection { - return DFS.topologicalOrder(dependencies) { - it.allDependencyModules - }.reversed() - } - - for (dependency in sortDependencies(dependencies).filter { it != moduleDescriptor }) { - val kotlinLibrary = dependency.getCapability(KlibModuleOrigin.CAPABILITY)?.let { - (it as? DeserializedKlibModuleOrigin)?.library - } - linker.deserializeIrModuleHeader(dependency, kotlinLibrary) - } - if (dependencies.size == dependenciesCount) break - dependenciesCount = dependencies.size - } - - // We need to run `buildAllEnumsAndStructsFrom` before `generateModuleFragment` because it adds references to symbolTable - // that should be bound. - modulesWithoutDCE - .filter(ModuleDescriptor::isFromInteropLibrary) - .forEach(irProviderForCEnumsAndCStructs::referenceAllEnumsAndStructsFrom) - - val irProviders = listOf(linker) - - expectDescriptorToSymbol = mutableMapOf() - val module = translator.generateModuleFragment( - generatorContext, - environment.getSourceFiles(), - irProviders, - pluginExtensions, - // TODO: This is a hack to allow platform libs to build in reasonable time. - // referenceExpectsForUsedActuals() appears to be quadratic in time because of - // how ExpectedActualResolver is implemented. - // Need to fix ExpectActualResolver to either cache expects or somehow reduce the member scope searches. - if (expectActualLinker) expectDescriptorToSymbol else null - ) - - linker.postProcess() - - if (this.stdlibModule in modulesWithoutDCE) { - functionIrClassFactory.buildAllClasses() - } - - // Enable lazy IR genration for newly-created symbols inside BE - stubGenerator.unboundSymbolGeneration = true - - symbolTable.noUnboundLeft("Unbound symbols left after linker") - - module.acceptVoid(ManglerChecker(KonanManglerIr, Ir2DescriptorManglerAdapter(KonanManglerDesc))) - if (!config.configuration.getBoolean(KonanConfigKeys.DISABLE_FAKE_OVERRIDE_VALIDATOR)) { - val fakeOverrideChecker = FakeOverrideChecker(KonanManglerIr, KonanManglerDesc) - linker.modules.values.forEach { fakeOverrideChecker.check(it) } - } - - irModule = module - - // Note: coupled with [shouldLower] below. - irModules = linker.modules.filterValues { llvmModuleSpecification.containsModule(it) } - - ir.symbols = symbols - - functionIrClassFactory.module = - (listOf(irModule!!) + linker.modules.values) - .single { it.descriptor.isNativeStdlib() } - }, + op = { this.psiToIr(symbolTable!!) }, name = "Psi2Ir", - description = "Psi to IR conversion", + description = "Psi to IR conversion and klib linkage", prerequisite = setOf(createSymbolTablePhase) )