remove unused code from IrLinker
diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/IrLinker.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/IrLinker.kt
index e649281..d9d8784 100644
--- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/IrLinker.kt
+++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/IrLinker.kt
@@ -1,12 +1,8 @@
 package org.jetbrains.kotlin.backend.konan
 
-import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
-import org.jetbrains.kotlin.backend.common.extensions.IrPluginContextImpl
-import org.jetbrains.kotlin.backend.common.linkage.IrDeserializer
 import org.jetbrains.kotlin.backend.common.linkage.issues.checkNoUnboundSymbols
 import org.jetbrains.kotlin.backend.common.linkage.partial.createPartialLinkageSupportForLinker
 import org.jetbrains.kotlin.backend.common.linkage.partial.partialLinkageConfig
-import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideChecker
 import org.jetbrains.kotlin.backend.common.serialization.DescriptorByIdSignatureFinderImpl
 import org.jetbrains.kotlin.backend.common.serialization.IrModuleDeserializer
 import org.jetbrains.kotlin.backend.konan.driver.phases.PsiToIrContext
@@ -21,21 +17,21 @@
 import org.jetbrains.kotlin.descriptors.ModuleDescriptor
 import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
 import org.jetbrains.kotlin.ir.declarations.DescriptorMetadataSource
+import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl
 import org.jetbrains.kotlin.ir.objcinterop.IrObjCOverridabilityCondition
-import org.jetbrains.kotlin.ir.symbols.IrSymbol
 import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator
-import org.jetbrains.kotlin.ir.util.IdSignature
+import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
 import org.jetbrains.kotlin.library.KotlinLibrary
 import org.jetbrains.kotlin.library.isHeader
 import org.jetbrains.kotlin.library.metadata.DeserializedKlibModuleOrigin
 import org.jetbrains.kotlin.library.metadata.KlibModuleOrigin
 import org.jetbrains.kotlin.library.metadata.impl.isForwardDeclarationModule
 import org.jetbrains.kotlin.library.uniqueName
-import org.jetbrains.kotlin.name.Name
 import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration
 import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
 import org.jetbrains.kotlin.psi2ir.descriptors.IrBuiltInsOverDescriptors
 import org.jetbrains.kotlin.psi2ir.generators.DeclarationStubGeneratorImpl
+import org.jetbrains.kotlin.psi2ir.generators.ModuleGenerator
 import org.jetbrains.kotlin.utils.DFS
 
 @OptIn(ObsoleteDescriptorBasedAPI::class)
@@ -43,7 +39,8 @@
         input: PsiToIrInput,
 ): PsiToIrOutput {
     val symbolTable = symbolTable!!
-    val (moduleDescriptor, environment, isProducingLibrary) = input
+    val (moduleDescriptor, _, isProducingLibrary) = input
+    require(!isProducingLibrary)
     // Translate AST to high level IR.
     val messageCollector = config.configuration.messageCollector
 
@@ -56,8 +53,6 @@
     )
     val generatorContext = translator.createGeneratorContext(moduleDescriptor, bindingContext, symbolTable)
 
-    val pluginExtensions = IrGenerationExtension.getInstances(config.project)
-
     val forwardDeclarationsModuleDescriptor = moduleDescriptor.allDependencyModules.firstOrNull { it.isForwardDeclarationModule }
 
     val libraryToCache = config.libraryToCache
@@ -68,8 +63,6 @@
     val stdlibIsCached = stdlibModule.konanLibrary?.let { config.cachedLibraries.isLibraryCached(it) } == true
     val stdlibIsBeingCached = libraryToCacheModule == stdlibModule
     require(!(stdlibIsCached && stdlibIsBeingCached)) { "The cache for stdlib is already built" }
-    val kFunctionImplIsBeingCached = stdlibIsBeingCached && libraryToCache?.strategy.containsKFunctionImpl
-    val shouldUseLazyFunctionClasses = (stdlibIsCached || stdlibIsBeingCached) && !kFunctionImplIsBeingCached
 
     val stubGenerator = DeclarationStubGeneratorImpl(
             moduleDescriptor, symbolTable,
@@ -79,10 +72,7 @@
     )
     val irBuiltInsOverDescriptors = generatorContext.irBuiltIns as IrBuiltInsOverDescriptors
     val functionIrClassFactory: KonanIrAbstractDescriptorBasedFunctionFactory =
-            if (shouldUseLazyFunctionClasses && config.lazyIrForCaches)
-                LazyIrFunctionFactory(symbolTable, stubGenerator, irBuiltInsOverDescriptors, reflectionTypes)
-            else
-                BuiltInFictitiousFunctionIrClassFactory(symbolTable, irBuiltInsOverDescriptors, reflectionTypes)
+            BuiltInFictitiousFunctionIrClassFactory(symbolTable, irBuiltInsOverDescriptors, reflectionTypes)
     irBuiltInsOverDescriptors.functionFactory = functionIrClassFactory
     val symbols = KonanSymbols(
             this,
@@ -90,167 +80,129 @@
             this.config.configuration
     )
 
-    val irDeserializer = if (isProducingLibrary) {
-        // Enable lazy IR generation for newly-created symbols inside BE
-        stubGenerator.unboundSymbolGeneration = true
+    val exportedDependencies = (moduleDescriptor.getExportedDependencies(config) + libraryToCacheModule?.let { listOf(it) }.orEmpty()).distinct()
+    val irProviderForCEnumsAndCStructs =
+            IrProviderForCEnumAndCStructStubs(generatorContext, symbols)
+    val cInteropModuleDeserializerFactory = KonanCInteropModuleDeserializerFactory(
+            cachedLibraries = config.cachedLibraries,
+            cenumsProvider = irProviderForCEnumsAndCStructs,
+            stubGenerator = stubGenerator,
+    )
 
-        object : IrDeserializer {
-            override fun getDeclaration(symbol: IrSymbol) = functionIrClassFactory.getDeclaration(symbol)
-                    ?: stubGenerator.getDeclaration(symbol)
+    val friendModules = config.resolvedLibraries.getFullList()
+            .filter { it.libraryFile in config.friendModuleFiles }
+            .map { it.uniqueName }
 
-            override fun resolveBySignatureInModule(signature: IdSignature, kind: IrDeserializer.TopLevelSymbolKind, moduleName: Name): IrSymbol {
-                error("Should not be called")
-            }
+    val friendModulesMap = (
+            listOf(moduleDescriptor.name.asStringStripSpecialMarkers()) +
+                    config.resolve.includedLibraries.map { it.uniqueName }
+            ).associateWith { friendModules }
 
-            override fun postProcess(inOrAfterLinkageStep: Boolean) = Unit
+    val linker = KonanIrLinker(
+            currentModule = moduleDescriptor,
+            messageCollector = messageCollector,
+            builtIns = generatorContext.irBuiltIns,
+            symbolTable = symbolTable,
+            friendModules = friendModulesMap,
+            forwardModuleDescriptor = forwardDeclarationsModuleDescriptor,
+            stubGenerator = stubGenerator,
+            cInteropModuleDeserializerFactory = cInteropModuleDeserializerFactory,
+            exportedDependencies = exportedDependencies,
+            partialLinkageSupport = createPartialLinkageSupportForLinker(
+                    partialLinkageConfig = partialLinkageConfig,
+                    builtIns = generatorContext.irBuiltIns,
+                    messageCollector = messageCollector
+            ),
+            libraryBeingCached = config.libraryToCache,
+            userVisibleIrModulesSupport = config.userVisibleIrModulesSupport,
+            externalOverridabilityConditions = listOf(IrObjCOverridabilityCondition)
+    )
+    // context.config.librariesWithDependencies could change at each iteration.
+    var dependenciesCount = 0
+    while (true) {
+        // context.config.librariesWithDependencies could change at each iteration.
+        val libsWithDeps = config.librariesWithDependencies().toSet()
+        val dependencies = moduleDescriptor.allDependencyModules.filter {
+            libsWithDeps.contains(it.konanLibrary)
         }
-    } else {
-        val exportedDependencies = (moduleDescriptor.getExportedDependencies(config) + libraryToCacheModule?.let { listOf(it) }.orEmpty()).distinct()
-        val irProviderForCEnumsAndCStructs =
-                IrProviderForCEnumAndCStructStubs(generatorContext, symbols)
-        val cInteropModuleDeserializerFactory = KonanCInteropModuleDeserializerFactory(
-                cachedLibraries = config.cachedLibraries,
-                cenumsProvider = irProviderForCEnumsAndCStructs,
-                stubGenerator = stubGenerator,
-        )
 
-        val friendModules = config.resolvedLibraries.getFullList()
-                .filter { it.libraryFile in config.friendModuleFiles }
-                .map { it.uniqueName }
-
-        val friendModulesMap = (
-                listOf(moduleDescriptor.name.asStringStripSpecialMarkers()) +
-                        config.resolve.includedLibraries.map { it.uniqueName }
-                ).associateWith { friendModules }
-
-        KonanIrLinker(
-                currentModule = moduleDescriptor,
-                messageCollector = messageCollector,
-                builtIns = generatorContext.irBuiltIns,
-                symbolTable = symbolTable,
-                friendModules = friendModulesMap,
-                forwardModuleDescriptor = forwardDeclarationsModuleDescriptor,
-                stubGenerator = stubGenerator,
-                cInteropModuleDeserializerFactory = cInteropModuleDeserializerFactory,
-                exportedDependencies = exportedDependencies,
-                partialLinkageSupport = createPartialLinkageSupportForLinker(
-                        partialLinkageConfig = partialLinkageConfig,
-                        builtIns = generatorContext.irBuiltIns,
-                        messageCollector = messageCollector
-                ),
-                libraryBeingCached = config.libraryToCache,
-                userVisibleIrModulesSupport = config.userVisibleIrModulesSupport,
-                externalOverridabilityConditions = listOf(IrObjCOverridabilityCondition)
-        ).also { linker ->
-
-            // context.config.librariesWithDependencies could change at each iteration.
-            var dependenciesCount = 0
-            while (true) {
-                // context.config.librariesWithDependencies could change at each iteration.
-                val libsWithDeps = config.librariesWithDependencies().toSet()
-                val dependencies = moduleDescriptor.allDependencyModules.filter {
-                    libsWithDeps.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) as? DeserializedKlibModuleOrigin)?.library
-                    val isFullyCachedLibrary = kotlinLibrary != null &&
-                            config.cachedLibraries.isLibraryCached(kotlinLibrary) && kotlinLibrary != config.libraryToCache?.klib
-                    if (isFullyCachedLibrary && kotlinLibrary?.isHeader == true)
-                        linker.deserializeHeadersWithInlineBodies(dependency, kotlinLibrary)
-                    else if (isProducingLibrary || isFullyCachedLibrary)
-                        linker.deserializeOnlyHeaderModule(dependency, kotlinLibrary)
-                    else
-                        linker.deserializeIrModuleHeader(dependency, kotlinLibrary, dependency.name.asString())
-                }
-                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.
-            if (libraryToCacheModule?.isFromCInteropLibrary() == true)
-                irProviderForCEnumsAndCStructs.referenceAllEnumsAndStructsFrom(libraryToCacheModule)
-
-            translator.addPostprocessingStep {
-                irProviderForCEnumsAndCStructs.generateBodies()
-            }
+        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) as? DeserializedKlibModuleOrigin)?.library
+            val isFullyCachedLibrary = kotlinLibrary != null &&
+                    config.cachedLibraries.isLibraryCached(kotlinLibrary) && kotlinLibrary != config.libraryToCache?.klib
+            if (isFullyCachedLibrary && kotlinLibrary.isHeader)
+                linker.deserializeHeadersWithInlineBodies(dependency, kotlinLibrary)
+            else if (isFullyCachedLibrary)
+                linker.deserializeOnlyHeaderModule(dependency, kotlinLibrary)
+            else
+                linker.deserializeIrModuleHeader(dependency, kotlinLibrary, dependency.name.asString())
+        }
+        if (dependencies.size == dependenciesCount) break
+        dependenciesCount = dependencies.size
     }
 
-    translator.addPostprocessingStep { module ->
-        val pluginContext = IrPluginContextImpl(
-                generatorContext.moduleDescriptor,
-                generatorContext.bindingContext,
-                generatorContext.languageVersionSettings,
-                generatorContext.symbolTable,
-                generatorContext.typeTranslator,
-                generatorContext.irBuiltIns,
-                linker = irDeserializer,
-                messageCollector = messageCollector
-        )
-        pluginExtensions.forEach { extension ->
-            extension.generate(module, pluginContext)
-        }
+    // We need to run `buildAllEnumsAndStructsFrom` before `generateModuleFragment` because it adds references to symbolTable
+    // that should be bound.
+    if (libraryToCacheModule?.isFromCInteropLibrary() == true)
+        irProviderForCEnumsAndCStructs.referenceAllEnumsAndStructsFrom(libraryToCacheModule)
+
+    val irProviders = listOf(linker)
+    val moduleGenerator = ModuleGenerator(generatorContext)
+    val irModule = IrModuleFragmentImpl(moduleGenerator.context.moduleDescriptor)
+    linker.init(irModule)
+    ExternalDependenciesGenerator(moduleGenerator.context.symbolTable, irProviders).generateUnboundSymbolsAsDependencies()
+    linker.postProcess(inOrAfterLinkageStep = true)
+    if (!partialLinkageConfig.isEnabled) {
+        messageCollector.checkNoUnboundSymbols(symbolTable, "after generation of IR module ${irModule.name.asString()}")
     }
+    irProviderForCEnumsAndCStructs.generateBodies()
+    val mainModule = irModule
 
-    val mainModule = translator.generateModuleFragment(generatorContext, environment.getSourceFiles(), listOf(irDeserializer))
-
-    irDeserializer.postProcess(inOrAfterLinkageStep = true)
+    linker.postProcess(inOrAfterLinkageStep = true)
 
     // Enable lazy IR genration for newly-created symbols inside BE
     stubGenerator.unboundSymbolGeneration = true
 
     messageCollector.checkNoUnboundSymbols(symbolTable, "at the end of IR linkage process")
 
-    val modules = if (isProducingLibrary) emptyMap() else (irDeserializer as KonanIrLinker).modules
-
-    if (config.configuration.getBoolean(KonanConfigKeys.FAKE_OVERRIDE_VALIDATOR)) {
-        val fakeOverrideChecker = FakeOverrideChecker(KonanManglerIr, KonanManglerDesc)
-        modules.values.forEach { fakeOverrideChecker.check(it) }
-    }
+    val modules = linker.modules
     // IR linker deserializes files in the order they lie on the disk, which might be inconvenient,
     // so to make the pipeline more deterministic, the files are to be sorted.
     // This concerns in the first place global initializers order for the eager initialization strategy,
     // where the files are being initialized in order one by one.
     modules.values.forEach { module -> module.files.sortBy { it.fileEntry.name } }
 
-    if (!isProducingLibrary) {
-        // TODO: find out what should be done in the new builtins/symbols about it
-        if (stdlibIsBeingCached) {
-            (functionIrClassFactory as? BuiltInFictitiousFunctionIrClassFactory)?.buildAllClasses()
-        }
-        (functionIrClassFactory as? BuiltInFictitiousFunctionIrClassFactory)?.module =
-                (modules.values + mainModule).single { it.descriptor == this.stdlibModule }
+    // TODO: find out what should be done in the new builtins/symbols about it
+    if (stdlibIsBeingCached) {
+        (functionIrClassFactory as? BuiltInFictitiousFunctionIrClassFactory)?.buildAllClasses()
     }
+    (functionIrClassFactory as? BuiltInFictitiousFunctionIrClassFactory)?.module =
+            (modules.values + mainModule).single { it.descriptor == this.stdlibModule }
 
     mainModule.files.forEach { it.metadata = DescriptorMetadataSource.File(listOf(mainModule.descriptor)) }
     modules.values.forEach { module ->
         module.files.forEach { it.metadata = DescriptorMetadataSource.File(listOf(module.descriptor)) }
     }
 
-    return if (isProducingLibrary) {
-        PsiToIrOutput.ForKlib(mainModule, generatorContext.irBuiltIns, symbols)
-    } else if (libraryToCache == null) {
-        PsiToIrOutput.ForBackend(modules, mainModule, generatorContext.irBuiltIns, symbols, symbolTable, irDeserializer as KonanIrLinker)
-    } else {
-        val libraryName = libraryToCache.klib.libraryName
-        val libraryModule = modules[libraryName] ?: error("No module for the library being cached: $libraryName")
-        PsiToIrOutput.ForBackend(
-                irModules = modules.filterKeys { it != libraryName },
-                irModule = libraryModule,
-                irBuiltIns = generatorContext.irBuiltIns,
-                symbols = symbols,
-                symbolTable = symbolTable,
-                irLinker = irDeserializer as KonanIrLinker
-        )
-    }
+    val libraryName = libraryToCache?.klib?.libraryName
+    return PsiToIrOutput.ForBackend(
+            irModules = modules.filterKeys { it != libraryName },
+            irModule = if (libraryName == null) {
+                mainModule
+            } else {
+                modules[libraryName] ?: error("No module for the library being cached: $libraryName")
+            },
+            irBuiltIns = generatorContext.irBuiltIns,
+            symbols = symbols,
+            symbolTable = symbolTable,
+            irLinker = linker
+    )
 }
 
 internal class KonanCInteropModuleDeserializerFactory(