diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/extensions/IrPluginContextImpl.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/extensions/IrPluginContextImpl.kt index 86be0783fa8..56c5bdd8ff9 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/extensions/IrPluginContextImpl.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/extensions/IrPluginContextImpl.kt @@ -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 } } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt index 8e0f9e552e2..63d42ce9374 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt @@ -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 -> diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/JsIrLinkerLoader.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/JsIrLinkerLoader.kt index bc1b6299917..590420bbf5f 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/JsIrLinkerLoader.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/JsIrLinkerLoader.kt @@ -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") } } diff --git a/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt b/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt index 95a89a1fa21..827cdd96739 100644 --- a/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt +++ b/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt @@ -261,7 +261,7 @@ open class JvmIrCodegenFactory( fragmentInfo = evaluatorFragmentInfoForPsi2Ir ) - irLinker.postProcess() + irLinker.postProcess(inOrAfterLinkageStep = true) stubGenerator.unboundSymbolGeneration = true diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/compiler.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/compiler.kt index a9080e2c6d6..41a1227aea8 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/compiler.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/compiler.kt @@ -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) diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt index 028986d0b9a..88c628f272b 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt @@ -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 diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/linkage/IrDeserializer.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/linkage/IrDeserializer.kt index 015911d9dc8..a8cfc76dc60 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/linkage/IrDeserializer.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/linkage/IrDeserializer.kt @@ -27,5 +27,19 @@ interface IrDeserializer : IrProvider { fun init(moduleFragment: IrModuleFragment?, extensions: Collection) {} 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) } diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KotlinIrLinker.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KotlinIrLinker.kt index 18fb436f821..3fbe9b2a653 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KotlinIrLinker.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KotlinIrLinker.kt @@ -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 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 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 diff --git a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt index 264a619d7cd..3cc7f2438a2 100644 --- a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt +++ b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt @@ -298,7 +298,7 @@ fun getIrModuleInfoForKlib( irLinker.init(null, emptyList()) ExternalDependenciesGenerator(symbolTable, listOf(irLinker)).generateUnboundSymbolsAsDependencies() - irLinker.postProcess() + irLinker.postProcess(inOrAfterLinkageStep = true) return IrModuleInfo( moduleFragment, diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/klib/AbstractKlibIrTextTestCase.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/klib/AbstractKlibIrTextTestCase.kt index 35d8d741831..63bce3733b5 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/klib/AbstractKlibIrTextTestCase.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/klib/AbstractKlibIrTextTestCase.kt @@ -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 } diff --git a/js/js.tests/test/org/jetbrains/kotlin/benchmarks/GenerateIrRuntime.kt b/js/js.tests/test/org/jetbrains/kotlin/benchmarks/GenerateIrRuntime.kt index bf12ce519c5..2fa13c4f7df 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/benchmarks/GenerateIrRuntime.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/benchmarks/GenerateIrRuntime.kt @@ -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() diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/PsiToIr.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/PsiToIr.kt index 494d0b8e3d1..510e96bcfa1 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/PsiToIr.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/PsiToIr.kt @@ -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 diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt index 69fcbe913bb..089eb9ae596 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt @@ -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()