[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
linker.getDeclaration(symbol)
linker.postProcess()
linker.postProcess(inOrAfterLinkageStep = false)
return symbol
}
@@ -95,7 +95,7 @@ open class IrPluginContextImpl constructor(
symbols.forEach { if (!it.isBound) linker.getDeclaration(it) }
linker.postProcess()
linker.postProcess(inOrAfterLinkageStep = false)
return symbols
}
@@ -173,7 +173,7 @@ open class IrPluginContextImpl constructor(
moduleDescriptor: ModuleDescriptor
): IrSymbol? {
val symbol = linker.resolveBySignatureInModule(signature, kind, moduleDescriptor.name)
linker.postProcess()
linker.postProcess(inOrAfterLinkageStep = false)
return symbol
}
}
@@ -120,7 +120,7 @@ fun compileIr(
val irProviders = listOf(irLinker)
ExternalDependenciesGenerator(symbolTable, irProviders).generateUnboundSymbolsAsDependencies()
irLinker.postProcess()
irLinker.postProcess(inOrAfterLinkageStep = true)
irLinker.checkNoUnboundSymbols(symbolTable, "at the end of IR linkage process")
allModules.forEach { module ->
@@ -71,7 +71,7 @@ internal data class LoadedJsIr(
fun loadUnboundSymbols() {
signatureProvidersImpl.clear()
ExternalDependenciesGenerator(linker.symbolTable, listOf(linker)).generateUnboundSymbolsAsDependencies()
linker.postProcess()
linker.postProcess(inOrAfterLinkageStep = true)
linker.checkNoUnboundSymbols(linker.symbolTable, "at the end of IR linkage process")
}
}
@@ -261,7 +261,7 @@ open class JvmIrCodegenFactory(
fragmentInfo = evaluatorFragmentInfoForPsi2Ir
)
irLinker.postProcess()
irLinker.postProcess(inOrAfterLinkageStep = true)
stubGenerator.unboundSymbolGeneration = true
@@ -73,7 +73,7 @@ fun compileToLoweredIr(
ExternalDependenciesGenerator(symbolTable, listOf(irLinker)).generateUnboundSymbolsAsDependencies()
allModules.forEach { it.patchDeclarationParents() }
irLinker.postProcess()
irLinker.postProcess(inOrAfterLinkageStep = true)
irLinker.checkNoUnboundSymbols(symbolTable, "at the end of IR linkage process")
for (module in allModules)
@@ -101,7 +101,7 @@ class Psi2IrTranslator(
moduleGenerator.generateUnboundSymbolsAsDependencies(irProviders)
deserializers.forEach { it.postProcess() }
deserializers.forEach { it.postProcess(inOrAfterLinkageStep = true) }
context.checkNoUnboundSymbols { "after generation of IR module ${irModule.name.asString()}" }
postprocessingSteps.forEach { it.invoke(irModule) }
@@ -109,7 +109,7 @@ class Psi2IrTranslator(
// TODO: remove it once plugin API improved
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()}" }
return irModule
@@ -27,5 +27,19 @@ interface IrDeserializer : IrProvider {
fun init(moduleFragment: IrModuleFragment?, extensions: Collection<IrLinkerExtension>) {}
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() }
}
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.
finalizeExpectActualLinker()
// We have to exclude classifiers with unbound symbols in supertypes and in type parameter upper bounds from F.O. generation
// to avoid failing with `Symbol for <signature> is unbound` error or generating fake overrides with incorrect signatures.
partialLinkageSupport.exploreClassifiers(fakeOverrideBuilder)
if (inOrAfterLinkageStep) {
// We have to exclude classifiers with unbound symbols in supertypes and in type parameter upper bounds from F.O. generation
// 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.
fakeOverrideBuilder.provideFakeOverrides()
triedToDeserializeDeclarationForSymbol.clear()
// Finally, generate stubs for the remaining unbound symbols and patch every usage of any unbound symbol inside the IR tree.
partialLinkageSupport.generateStubsAndPatchUsages(symbolTable) {
deserializersForModules.values.asSequence().map { it.moduleFragment }
if (inOrAfterLinkageStep) {
// Finally, generate stubs for the remaining unbound symbols and patch every usage of any unbound symbol inside the IR tree.
partialLinkageSupport.generateStubsAndPatchUsages(symbolTable) {
deserializersForModules.values.asSequence().map { it.moduleFragment }
}
}
// TODO: fix IrPluginContext to make it not produce additional external reference
@@ -298,7 +298,7 @@ fun getIrModuleInfoForKlib(
irLinker.init(null, emptyList())
ExternalDependenciesGenerator(symbolTable, listOf(irLinker)).generateUnboundSymbolsAsDependencies()
irLinker.postProcess()
irLinker.postProcess(inOrAfterLinkageStep = true)
return IrModuleInfo(
moduleFragment,
@@ -230,7 +230,7 @@ abstract class AbstractKlibIrTextTestCase : CodegenTestCase() {
val testModule = irLinker.deserializeIrModuleHeader(testDescriptor, klib, { DeserializationStrategy.ALL })
irLinker.init(null, emptyList())
ExternalDependenciesGenerator(symbolTable, listOf(irLinker)).generateUnboundSymbolsAsDependencies()
irLinker.postProcess()
irLinker.postProcess(inOrAfterLinkageStep = true)
return testModule
}