Move PSI to IR translation to separate file
This commit is contained in:
committed by
Sergey Bogolepov
parent
0fc0cb221e
commit
ea7117d9ab
+164
@@ -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<ModuleDescriptor>): Collection<ModuleDescriptor> {
|
||||||
|
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<DeclarationDescriptor, IrSymbol>()
|
||||||
|
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() }
|
||||||
|
}
|
||||||
+2
-135
@@ -143,142 +143,9 @@ internal val buildCExportsPhase = konanUnitPhase(
|
|||||||
)
|
)
|
||||||
|
|
||||||
internal val psiToIrPhase = konanUnitPhase(
|
internal val psiToIrPhase = konanUnitPhase(
|
||||||
op = {
|
op = { this.psiToIr(symbolTable!!) },
|
||||||
// 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<ModuleDescriptor>): Collection<ModuleDescriptor> {
|
|
||||||
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<DeclarationDescriptor, IrSymbol>()
|
|
||||||
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() }
|
|
||||||
},
|
|
||||||
name = "Psi2Ir",
|
name = "Psi2Ir",
|
||||||
description = "Psi to IR conversion",
|
description = "Psi to IR conversion and klib linkage",
|
||||||
prerequisite = setOf(createSymbolTablePhase)
|
prerequisite = setOf(createSymbolTablePhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user