[klib] Don't pass around metadata serialization closure

Pass the metadata serializer instance instead. This allows to further
reduce code duplication by introducing the common interface
`KlibSingleFileMetadataSerializer` for abstracting away K1 and K2
representation of a source file, as well as reusing
`Fir2KlibMetadataSerializer` across different backends.

KT-64392
This commit is contained in:
Sergej Jaskiewicz
2024-01-22 14:21:20 +01:00
committed by Space Team
parent 5a6f51e474
commit f39335b3f7
23 changed files with 388 additions and 406 deletions
@@ -92,7 +92,7 @@ internal fun PhaseContext.fir2Ir(
val diagnosticsReporter = DiagnosticReporterFactory.createPendingReporter()
val fir2IrConfiguration = Fir2IrConfiguration.forKlibCompilation(configuration, diagnosticsReporter)
val (irModuleFragment, components, pluginContext, irActualizedResult) = input.firResult.convertToIrAndActualize(
val actualizedResult = input.firResult.convertToIrAndActualize(
NativeFir2IrExtensions,
fir2IrConfiguration,
IrGenerationExtension.getInstances(config.project),
@@ -104,8 +104,8 @@ internal fun PhaseContext.fir2Ir(
).also {
(it.irModuleFragment.descriptor as? FirModuleDescriptor)?.let { it.allDependencyModules = librariesDescriptors }
}
assert(irModuleFragment.name.isSpecial) {
"`${irModuleFragment.name}` must be Name.special, since it's required by KlibMetadataModuleDescriptorFactoryImpl.createDescriptorOptionalBuiltIns()"
assert(actualizedResult.irModuleFragment.name.isSpecial) {
"`${actualizedResult.irModuleFragment.name}` must be Name.special, since it's required by KlibMetadataModuleDescriptorFactoryImpl.createDescriptorOptionalBuiltIns()"
}
@OptIn(DelicateDeclarationStorageApi::class)
@@ -116,8 +116,8 @@ internal fun PhaseContext.fir2Ir(
val fragment = (p.getPackageFragment() as? IrExternalPackageFragment) ?: return
add(fragment.packageFqName)
}
components.declarationStorage.forEachCachedDeclarationSymbol(::addExternalPackage)
components.classifierStorage.forEachCachedDeclarationSymbol(::addExternalPackage)
actualizedResult.components.declarationStorage.forEachCachedDeclarationSymbol(::addExternalPackage)
actualizedResult.components.classifierStorage.forEachCachedDeclarationSymbol(::addExternalPackage)
// These packages exist in all platform libraries, but can contain only synthetic declarations.
// These declarations are not really located in klib, so we don't need to depend on klib to use them.
@@ -135,7 +135,7 @@ internal fun PhaseContext.fir2Ir(
}
}
val symbols = createKonanSymbols(components, pluginContext)
val symbols = createKonanSymbols(actualizedResult.components, actualizedResult.pluginContext)
val renderDiagnosticNames = configuration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME)
FirDiagnosticsCompilerResultsReporter.reportToMessageCollector(diagnosticsReporter, messageCollector, renderDiagnosticNames)
@@ -144,7 +144,7 @@ internal fun PhaseContext.fir2Ir(
throw KonanCompilationException("Compilation failed: there were some diagnostics during fir2ir")
}
return Fir2IrOutput(input.firResult, symbols, irModuleFragment, components, pluginContext, irActualizedResult, usedLibraries)
return Fir2IrOutput(input.firResult, symbols, actualizedResult, usedLibraries)
}
private fun PhaseContext.createKonanSymbols(
@@ -11,23 +11,12 @@ import org.jetbrains.kotlin.backend.konan.driver.phases.SerializerOutput
import org.jetbrains.kotlin.backend.konan.serialization.KonanIrModuleSerializer
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.fir.reportToMessageCollector
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.backend.ConstValueProviderImpl
import org.jetbrains.kotlin.fir.backend.extractFirDeclarations
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.moduleData
import org.jetbrains.kotlin.fir.packageFqName
import org.jetbrains.kotlin.fir.pipeline.Fir2KlibMetadataSerializer
import org.jetbrains.kotlin.fir.pipeline.FirResult
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
import org.jetbrains.kotlin.fir.serialization.FirKLibSerializerExtension
import org.jetbrains.kotlin.fir.serialization.serializeSingleFirFile
import org.jetbrains.kotlin.konan.library.KonanLibrary
import org.jetbrains.kotlin.library.metadata.resolver.TopologicalLibraryOrder
import org.jetbrains.kotlin.utils.toMetadataVersion
internal fun PhaseContext.firSerializer(input: FirOutput): SerializerOutput? = when (input) {
!is FirOutput.Full -> null
@@ -44,35 +33,26 @@ internal fun PhaseContext.firSerializerBase(
produceHeaderKlib: Boolean = false,
): SerializerOutput {
val configuration = config.configuration
val sourceFiles = mutableListOf<KtSourceFile>()
val firFilesAndSessionsBySourceFile = mutableMapOf<KtSourceFile, Triple<FirFile, FirSession, ScopeSession>>()
for (firOutput in firResult.outputs) {
for (firFile in firOutput.fir) {
sourceFiles.add(firFile.sourceFile!!)
firFilesAndSessionsBySourceFile[firFile.sourceFile!!] = Triple(firFile, firOutput.session, firOutput.scopeSession)
}
}
val metadataVersion =
configuration.get(CommonConfigurationKeys.METADATA_VERSION)
?: configuration.languageVersionSettings.languageVersion.toMetadataVersion()
val usedResolvedLibraries = fir2IrOutput?.let {
config.resolvedLibraries.getFullResolvedList(TopologicalLibraryOrder).filter {
(!it.isDefault && !configuration.getBoolean(KonanConfigKeys.PURGE_USER_LIBS)) || it in fir2IrOutput.usedLibraries
}
}
val actualizedFirDeclarations = fir2IrOutput?.irActualizedResult?.actualizedExpectDeclarations?.extractFirDeclarations()
val irModuleFragment = fir2IrOutput?.fir2irActualizedResult?.irModuleFragment
val diagnosticReporter = DiagnosticReporterFactory.createPendingReporter()
val serializerOutput = serializeModuleIntoKlib(
moduleName = fir2IrOutput?.irModuleFragment?.descriptor?.name?.asString()
?: firResult.outputs.last().session.moduleData.name.asString(),
irModuleFragment = fir2IrOutput?.irModuleFragment,
moduleName = irModuleFragment?.name?.asString() ?: firResult.outputs.last().session.moduleData.name.asString(),
irModuleFragment = irModuleFragment,
configuration = configuration,
diagnosticReporter = diagnosticReporter,
sourceFiles = sourceFiles,
metadataSerializer = Fir2KlibMetadataSerializer(
configuration,
firResult.outputs,
fir2IrOutput?.fir2irActualizedResult,
exportKDoc = shouldExportKDoc(),
produceHeaderKlib = produceHeaderKlib,
),
compatibilityMode = CompatibilityMode.CURRENT,
cleanFiles = emptyList(),
dependencies = usedResolvedLibraries?.map { it.library as KonanLibrary }.orEmpty(),
@@ -95,30 +75,6 @@ internal fun PhaseContext.firSerializerBase(
shouldCheckSignaturesOnUniqueness = shouldCheckSignaturesOnUniqueness,
)
},
serializeFileMetadata = { ktSourceFile ->
val (firFile, originalSession, originalScopeSession) = firFilesAndSessionsBySourceFile[ktSourceFile]
?: error("cannot find FIR file by source file ${ktSourceFile.name} (${ktSourceFile.path})")
val session = fir2IrOutput?.components?.session ?: originalSession
val scopeSession = fir2IrOutput?.components?.scopeSession ?: originalScopeSession
val firProvider = fir2IrOutput?.components?.firProvider ?: originalSession.firProvider
serializeSingleFirFile(
firFile,
session,
scopeSession,
actualizedFirDeclarations,
FirKLibSerializerExtension(
session, firProvider, metadataVersion,
fir2IrOutput?.let {
ConstValueProviderImpl(fir2IrOutput.components)
},
allowErrorTypes = false,
exportKDoc = shouldExportKDoc(),
additionalMetadataProvider = fir2IrOutput?.components?.annotationsFromPluginRegistrar?.createAdditionalMetadataProvider()
),
configuration.languageVersionSettings,
produceHeaderKlib,
) to firFile.packageFqName
},
)
val renderDiagnosticNames = configuration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME)
diagnosticReporter.reportToMessageCollector(messageCollector, renderDiagnosticNames)
@@ -51,7 +51,7 @@ internal val K2SpecialBackendChecksPhase = createSimpleNamedCompilerPhase<PhaseC
"SpecialBackendChecks",
"Special backend checks",
) { context, input ->
val moduleFragment = input.irModuleFragment
val moduleFragment = input.fir2irActualizedResult.irModuleFragment
SpecialBackendChecksTraversal(
context,
input.symbols,
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.backend.konan.fir2Ir
import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
import org.jetbrains.kotlin.fir.backend.Fir2IrPluginContext
import org.jetbrains.kotlin.fir.pipeline.Fir2IrActualizedResult
import org.jetbrains.kotlin.fir.pipeline.FirResult
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary
@@ -20,10 +21,7 @@ import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary
internal data class Fir2IrOutput(
val firResult: FirResult,
val symbols: KonanSymbols,
val irModuleFragment: IrModuleFragment,
val components: Fir2IrComponents,
val pluginContext: Fir2IrPluginContext,
val irActualizedResult: IrActualizedResult?,
val fir2irActualizedResult: Fir2IrActualizedResult,
val usedLibraries: Set<KotlinResolvedLibrary>
)