[PL] Fix: Don't run partial linkage on early stages when no external dependencies have been loaded yet

This commit is contained in:
Dmitriy Dolovov
2023-04-17 19:19:44 +02:00
committed by Space Team
parent 000cf47c21
commit 87125d0703
13 changed files with 44 additions and 24 deletions
@@ -71,7 +71,7 @@ open class IrPluginContextImpl constructor(
if (symbol.isBound) return symbol if (symbol.isBound) return symbol
linker.getDeclaration(symbol) linker.getDeclaration(symbol)
linker.postProcess() linker.postProcess(inOrAfterLinkageStep = false)
return symbol return symbol
} }
@@ -95,7 +95,7 @@ open class IrPluginContextImpl constructor(
symbols.forEach { if (!it.isBound) linker.getDeclaration(it) } symbols.forEach { if (!it.isBound) linker.getDeclaration(it) }
linker.postProcess() linker.postProcess(inOrAfterLinkageStep = false)
return symbols return symbols
} }
@@ -173,7 +173,7 @@ open class IrPluginContextImpl constructor(
moduleDescriptor: ModuleDescriptor moduleDescriptor: ModuleDescriptor
): IrSymbol? { ): IrSymbol? {
val symbol = linker.resolveBySignatureInModule(signature, kind, moduleDescriptor.name) val symbol = linker.resolveBySignatureInModule(signature, kind, moduleDescriptor.name)
linker.postProcess() linker.postProcess(inOrAfterLinkageStep = false)
return symbol return symbol
} }
} }
@@ -120,7 +120,7 @@ fun compileIr(
val irProviders = listOf(irLinker) val irProviders = listOf(irLinker)
ExternalDependenciesGenerator(symbolTable, irProviders).generateUnboundSymbolsAsDependencies() ExternalDependenciesGenerator(symbolTable, irProviders).generateUnboundSymbolsAsDependencies()
irLinker.postProcess() irLinker.postProcess(inOrAfterLinkageStep = true)
irLinker.checkNoUnboundSymbols(symbolTable, "at the end of IR linkage process") irLinker.checkNoUnboundSymbols(symbolTable, "at the end of IR linkage process")
allModules.forEach { module -> allModules.forEach { module ->
@@ -71,7 +71,7 @@ internal data class LoadedJsIr(
fun loadUnboundSymbols() { fun loadUnboundSymbols() {
signatureProvidersImpl.clear() signatureProvidersImpl.clear()
ExternalDependenciesGenerator(linker.symbolTable, listOf(linker)).generateUnboundSymbolsAsDependencies() ExternalDependenciesGenerator(linker.symbolTable, listOf(linker)).generateUnboundSymbolsAsDependencies()
linker.postProcess() linker.postProcess(inOrAfterLinkageStep = true)
linker.checkNoUnboundSymbols(linker.symbolTable, "at the end of IR linkage process") linker.checkNoUnboundSymbols(linker.symbolTable, "at the end of IR linkage process")
} }
} }
@@ -261,7 +261,7 @@ open class JvmIrCodegenFactory(
fragmentInfo = evaluatorFragmentInfoForPsi2Ir fragmentInfo = evaluatorFragmentInfoForPsi2Ir
) )
irLinker.postProcess() irLinker.postProcess(inOrAfterLinkageStep = true)
stubGenerator.unboundSymbolGeneration = true stubGenerator.unboundSymbolGeneration = true
@@ -73,7 +73,7 @@ fun compileToLoweredIr(
ExternalDependenciesGenerator(symbolTable, listOf(irLinker)).generateUnboundSymbolsAsDependencies() ExternalDependenciesGenerator(symbolTable, listOf(irLinker)).generateUnboundSymbolsAsDependencies()
allModules.forEach { it.patchDeclarationParents() } allModules.forEach { it.patchDeclarationParents() }
irLinker.postProcess() irLinker.postProcess(inOrAfterLinkageStep = true)
irLinker.checkNoUnboundSymbols(symbolTable, "at the end of IR linkage process") irLinker.checkNoUnboundSymbols(symbolTable, "at the end of IR linkage process")
for (module in allModules) for (module in allModules)
@@ -101,7 +101,7 @@ class Psi2IrTranslator(
moduleGenerator.generateUnboundSymbolsAsDependencies(irProviders) moduleGenerator.generateUnboundSymbolsAsDependencies(irProviders)
deserializers.forEach { it.postProcess() } deserializers.forEach { it.postProcess(inOrAfterLinkageStep = true) }
context.checkNoUnboundSymbols { "after generation of IR module ${irModule.name.asString()}" } context.checkNoUnboundSymbols { "after generation of IR module ${irModule.name.asString()}" }
postprocessingSteps.forEach { it.invoke(irModule) } postprocessingSteps.forEach { it.invoke(irModule) }
@@ -109,7 +109,7 @@ class Psi2IrTranslator(
// TODO: remove it once plugin API improved // TODO: remove it once plugin API improved
moduleGenerator.generateUnboundSymbolsAsDependencies(irProviders) moduleGenerator.generateUnboundSymbolsAsDependencies(irProviders)
deserializers.forEach { it.postProcess() } deserializers.forEach { it.postProcess(inOrAfterLinkageStep = true) }
context.checkNoUnboundSymbols { "after applying all post-processing steps for the generated IR module ${irModule.name.asString()}" } context.checkNoUnboundSymbols { "after applying all post-processing steps for the generated IR module ${irModule.name.asString()}" }
return irModule return irModule
@@ -27,5 +27,19 @@ interface IrDeserializer : IrProvider {
fun init(moduleFragment: IrModuleFragment?, extensions: Collection<IrLinkerExtension>) {} fun init(moduleFragment: IrModuleFragment?, extensions: Collection<IrLinkerExtension>) {}
fun resolveBySignatureInModule(signature: IdSignature, kind: TopLevelSymbolKind, moduleName: Name): IrSymbol fun resolveBySignatureInModule(signature: IdSignature, kind: TopLevelSymbolKind, moduleName: Name): IrSymbol
fun postProcess() {}
/**
* [postProcess] has two usages with different expectations:
* - IR plugin API: actualize expects/actuals, generate fake overrides
* - Linker(s): the same + run partial linkage
*
* In the future, this function should be split into several functions with different semantics for more precise use.
*/
@Deprecated(
"Use postProcess(inOrAfterLinkageStep) instead",
ReplaceWith("postProcess(inOrAfterLinkageStep = true)"),
DeprecationLevel.ERROR
)
fun postProcess() = postProcess(inOrAfterLinkageStep = true)
fun postProcess(inOrAfterLinkageStep: Boolean)
} }
@@ -204,21 +204,25 @@ abstract class KotlinIrLinker(
deserializersForModules.values.forEach { it.init() } deserializersForModules.values.forEach { it.init() }
} }
override fun postProcess() { override fun postProcess(inOrAfterLinkageStep: Boolean) {
// TODO: Expect/actual actualization should be fixed to cope with the situation when either expect or actual symbol is unbound. // TODO: Expect/actual actualization should be fixed to cope with the situation when either expect or actual symbol is unbound.
finalizeExpectActualLinker() finalizeExpectActualLinker()
// We have to exclude classifiers with unbound symbols in supertypes and in type parameter upper bounds from F.O. generation if (inOrAfterLinkageStep) {
// to avoid failing with `Symbol for <signature> is unbound` error or generating fake overrides with incorrect signatures. // We have to exclude classifiers with unbound symbols in supertypes and in type parameter upper bounds from F.O. generation
partialLinkageSupport.exploreClassifiers(fakeOverrideBuilder) // to avoid failing with `Symbol for <signature> is unbound` error or generating fake overrides with incorrect signatures.
partialLinkageSupport.exploreClassifiers(fakeOverrideBuilder)
}
// Fake override generator creates new IR declarations. This may have effect of binding for certain symbols. // Fake override generator creates new IR declarations. This may have effect of binding for certain symbols.
fakeOverrideBuilder.provideFakeOverrides() fakeOverrideBuilder.provideFakeOverrides()
triedToDeserializeDeclarationForSymbol.clear() triedToDeserializeDeclarationForSymbol.clear()
// Finally, generate stubs for the remaining unbound symbols and patch every usage of any unbound symbol inside the IR tree. if (inOrAfterLinkageStep) {
partialLinkageSupport.generateStubsAndPatchUsages(symbolTable) { // Finally, generate stubs for the remaining unbound symbols and patch every usage of any unbound symbol inside the IR tree.
deserializersForModules.values.asSequence().map { it.moduleFragment } partialLinkageSupport.generateStubsAndPatchUsages(symbolTable) {
deserializersForModules.values.asSequence().map { it.moduleFragment }
}
} }
// TODO: fix IrPluginContext to make it not produce additional external reference // TODO: fix IrPluginContext to make it not produce additional external reference
@@ -298,7 +298,7 @@ fun getIrModuleInfoForKlib(
irLinker.init(null, emptyList()) irLinker.init(null, emptyList())
ExternalDependenciesGenerator(symbolTable, listOf(irLinker)).generateUnboundSymbolsAsDependencies() ExternalDependenciesGenerator(symbolTable, listOf(irLinker)).generateUnboundSymbolsAsDependencies()
irLinker.postProcess() irLinker.postProcess(inOrAfterLinkageStep = true)
return IrModuleInfo( return IrModuleInfo(
moduleFragment, moduleFragment,
@@ -230,7 +230,7 @@ abstract class AbstractKlibIrTextTestCase : CodegenTestCase() {
val testModule = irLinker.deserializeIrModuleHeader(testDescriptor, klib, { DeserializationStrategy.ALL }) val testModule = irLinker.deserializeIrModuleHeader(testDescriptor, klib, { DeserializationStrategy.ALL })
irLinker.init(null, emptyList()) irLinker.init(null, emptyList())
ExternalDependenciesGenerator(symbolTable, listOf(irLinker)).generateUnboundSymbolsAsDependencies() ExternalDependenciesGenerator(symbolTable, listOf(irLinker)).generateUnboundSymbolsAsDependencies()
irLinker.postProcess() irLinker.postProcess(inOrAfterLinkageStep = true)
return testModule return testModule
} }
@@ -559,7 +559,7 @@ class GenerateIrRuntime {
ExternalDependenciesGenerator(symbolTable, listOf(jsLinker)) ExternalDependenciesGenerator(symbolTable, listOf(jsLinker))
.generateUnboundSymbolsAsDependencies() .generateUnboundSymbolsAsDependencies()
jsLinker.postProcess() jsLinker.postProcess(inOrAfterLinkageStep = true)
moduleFragment.patchDeclarationParents() moduleFragment.patchDeclarationParents()
@@ -585,7 +585,7 @@ class GenerateIrRuntime {
ExternalDependenciesGenerator(symbolTable, listOf(jsLinker)) ExternalDependenciesGenerator(symbolTable, listOf(jsLinker))
.generateUnboundSymbolsAsDependencies() .generateUnboundSymbolsAsDependencies()
jsLinker.postProcess() jsLinker.postProcess(inOrAfterLinkageStep = true)
moduleFragment.patchDeclarationParents() moduleFragment.patchDeclarationParents()
@@ -106,6 +106,8 @@ internal fun PsiToIrContext.psiToIr(
override fun resolveBySignatureInModule(signature: IdSignature, kind: IrDeserializer.TopLevelSymbolKind, moduleName: Name): IrSymbol { override fun resolveBySignatureInModule(signature: IdSignature, kind: IrDeserializer.TopLevelSymbolKind, moduleName: Name): IrSymbol {
error("Should not be called") error("Should not be called")
} }
override fun postProcess(inOrAfterLinkageStep: Boolean) = Unit
} }
} else { } else {
val exportedDependencies = (moduleDescriptor.getExportedDependencies(config) + libraryToCacheModule?.let { listOf(it) }.orEmpty()).distinct() val exportedDependencies = (moduleDescriptor.getExportedDependencies(config) + libraryToCacheModule?.let { listOf(it) }.orEmpty()).distinct()
@@ -224,7 +226,7 @@ internal fun PsiToIrContext.psiToIr(
expectDescriptorToSymbol = if (expectActualLinker) expectDescriptorToSymbol else null expectDescriptorToSymbol = if (expectActualLinker) expectDescriptorToSymbol else null
).toKonanModule() ).toKonanModule()
irDeserializer.postProcess() irDeserializer.postProcess(inOrAfterLinkageStep = true)
// Enable lazy IR genration for newly-created symbols inside BE // Enable lazy IR genration for newly-created symbols inside BE
stubGenerator.unboundSymbolGeneration = true stubGenerator.unboundSymbolGeneration = true
@@ -407,9 +407,9 @@ internal class KonanIrLinker(
} }
} }
override fun postProcess() { override fun postProcess(inOrAfterLinkageStep: Boolean) {
stubGenerator.unboundSymbolGeneration = true stubGenerator.unboundSymbolGeneration = true
super.postProcess() super.postProcess(inOrAfterLinkageStep)
} }
private val inlineFunctionFiles = mutableMapOf<IrExternalPackageFragment, IrFile>() private val inlineFunctionFiles = mutableMapOf<IrExternalPackageFragment, IrFile>()