[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
}
@@ -559,7 +559,7 @@ class GenerateIrRuntime {
ExternalDependenciesGenerator(symbolTable, listOf(jsLinker))
.generateUnboundSymbolsAsDependencies()
jsLinker.postProcess()
jsLinker.postProcess(inOrAfterLinkageStep = true)
moduleFragment.patchDeclarationParents()
@@ -585,7 +585,7 @@ class GenerateIrRuntime {
ExternalDependenciesGenerator(symbolTable, listOf(jsLinker))
.generateUnboundSymbolsAsDependencies()
jsLinker.postProcess()
jsLinker.postProcess(inOrAfterLinkageStep = true)
moduleFragment.patchDeclarationParents()
@@ -106,6 +106,8 @@ internal fun PsiToIrContext.psiToIr(
override fun resolveBySignatureInModule(signature: IdSignature, kind: IrDeserializer.TopLevelSymbolKind, moduleName: Name): IrSymbol {
error("Should not be called")
}
override fun postProcess(inOrAfterLinkageStep: Boolean) = Unit
}
} else {
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
).toKonanModule()
irDeserializer.postProcess()
irDeserializer.postProcess(inOrAfterLinkageStep = true)
// Enable lazy IR genration for newly-created symbols inside BE
stubGenerator.unboundSymbolGeneration = true
@@ -407,9 +407,9 @@ internal class KonanIrLinker(
}
}
override fun postProcess() {
override fun postProcess(inOrAfterLinkageStep: Boolean) {
stubGenerator.unboundSymbolGeneration = true
super.postProcess()
super.postProcess(inOrAfterLinkageStep)
}
private val inlineFunctionFiles = mutableMapOf<IrExternalPackageFragment, IrFile>()