[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
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.jvm.plugins.PluginCliParser import org.jetbrains.kotlin.cli.jvm.plugins.PluginCliParser
import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
import org.jetbrains.kotlin.fir.pipeline.Fir2KlibMetadataSerializer
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.js.IncrementalDataProvider import org.jetbrains.kotlin.incremental.js.IncrementalDataProvider
@@ -470,13 +471,6 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
sourceModule.getModuleDescriptor(it) sourceModule.getModuleDescriptor(it)
} }
val metadataSerializer =
KlibMetadataIncrementalSerializer(
environmentForJS.configuration,
sourceModule.project,
sourceModule.jsFrontEndResult.hasErrors
)
val diagnosticsReporter = DiagnosticReporterFactory.createPendingReporter() val diagnosticsReporter = DiagnosticReporterFactory.createPendingReporter()
generateKLib( generateKLib(
sourceModule, sourceModule,
@@ -486,10 +480,8 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
icData = icData, icData = icData,
moduleFragment = moduleFragment, moduleFragment = moduleFragment,
diagnosticReporter = diagnosticsReporter, diagnosticReporter = diagnosticsReporter,
builtInsPlatform = if (arguments.wasm) BuiltInsPlatform.WASM else BuiltInsPlatform.JS builtInsPlatform = if (arguments.wasm) BuiltInsPlatform.WASM else BuiltInsPlatform.JS,
) { file -> )
metadataSerializer.serializeScope(file, sourceModule.jsFrontEndResult.bindingContext, moduleFragment.descriptor)
}
val messageCollector = environmentForJS.configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) val messageCollector = environmentForJS.configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
reportCollectedDiagnostics(environmentForJS.configuration, diagnosticsReporter, messageCollector) reportCollectedDiagnostics(environmentForJS.configuration, diagnosticsReporter, messageCollector)
@@ -562,7 +554,16 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
// This happens because we check the next round before compilation errors. // This happens because we check the next round before compilation errors.
// Test reproducer: testFileWithConstantRemoved // Test reproducer: testFileWithConstantRemoved
// Issue: https://youtrack.jetbrains.com/issue/KT-58824/ // Issue: https://youtrack.jetbrains.com/issue/KT-58824/
if (shouldGoToNextIcRound(moduleStructure, analyzedOutput.output, fir2IrActualizedResult)) { val shouldGoToNextIcRound = shouldGoToNextIcRound(moduleStructure.compilerConfiguration) {
Fir2KlibMetadataSerializer(
moduleStructure.compilerConfiguration,
analyzedOutput.output,
fir2IrActualizedResult,
exportKDoc = false,
produceHeaderKlib = false,
)
}
if (shouldGoToNextIcRound) {
throw IncrementalNextRoundException() throw IncrementalNextRoundException()
} }
} }
@@ -22,13 +22,13 @@ import org.jetbrains.kotlin.diagnostics.impl.PendingDiagnosticsCollectorWithSupp
import org.jetbrains.kotlin.fir.BinaryModuleData import org.jetbrains.kotlin.fir.BinaryModuleData
import org.jetbrains.kotlin.fir.DependencyListForCliModule import org.jetbrains.kotlin.fir.DependencyListForCliModule
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.backend.* import org.jetbrains.kotlin.fir.backend.Fir2IrConfiguration
import org.jetbrains.kotlin.fir.backend.Fir2IrExtensions
import org.jetbrains.kotlin.fir.backend.Fir2IrVisibilityConverter
import org.jetbrains.kotlin.fir.backend.js.FirJsKotlinMangler import org.jetbrains.kotlin.fir.backend.js.FirJsKotlinMangler
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
import org.jetbrains.kotlin.fir.pipeline.* import org.jetbrains.kotlin.fir.pipeline.*
import org.jetbrains.kotlin.fir.serialization.FirKLibSerializerExtension
import org.jetbrains.kotlin.fir.serialization.serializeSingleFirFile
import org.jetbrains.kotlin.fir.session.KlibIcData import org.jetbrains.kotlin.fir.session.KlibIcData
import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.js.IncrementalDataProvider import org.jetbrains.kotlin.incremental.js.IncrementalDataProvider
@@ -41,16 +41,13 @@ import org.jetbrains.kotlin.js.resolve.JsPlatformAnalyzerServices
import org.jetbrains.kotlin.library.KotlinAbiVersion import org.jetbrains.kotlin.library.KotlinAbiVersion
import org.jetbrains.kotlin.library.impl.BuiltInsPlatform import org.jetbrains.kotlin.library.impl.BuiltInsPlatform
import org.jetbrains.kotlin.library.unresolvedDependencies import org.jetbrains.kotlin.library.unresolvedDependencies
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.js.JsPlatforms import org.jetbrains.kotlin.platform.js.JsPlatforms
import org.jetbrains.kotlin.platform.wasm.WasmPlatforms import org.jetbrains.kotlin.platform.wasm.WasmPlatforms
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.utils.metadataVersion
import org.jetbrains.kotlin.wasm.resolve.WasmJsPlatformAnalyzerServices import org.jetbrains.kotlin.wasm.resolve.WasmJsPlatformAnalyzerServices
import org.jetbrains.kotlin.wasm.resolve.WasmWasiPlatformAnalyzerServices import org.jetbrains.kotlin.wasm.resolve.WasmWasiPlatformAnalyzerServices
import java.io.File
import java.nio.file.Paths import java.nio.file.Paths
inline fun <F> compileModuleToAnalyzedFir( inline fun <F> compileModuleToAnalyzedFir(
@@ -253,50 +250,6 @@ fun transformFirToIr(
} }
} }
private class Fir2KlibSerializer(
moduleStructure: ModulesStructure,
private val firOutputs: List<ModuleCompilerAnalyzedOutput>,
private val fir2IrActualizedResult: Fir2IrActualizedResult
) {
private val firFilesAndSessionsBySourceFile = buildMap {
for (output in firOutputs) {
output.fir.forEach {
put(it.sourceFile!!, it)
}
}
}
private val actualizedExpectDeclarations by lazy {
fir2IrActualizedResult.irActualizedResult?.actualizedExpectDeclarations?.extractFirDeclarations()
}
private val metadataVersion = moduleStructure.compilerConfiguration.metadataVersion()
private val languageVersionSettings = moduleStructure.compilerConfiguration.languageVersionSettings
val sourceFiles: List<KtSourceFile> = firFilesAndSessionsBySourceFile.keys.toList()
fun serializeSingleFirFile(file: KtSourceFile): ProtoBuf.PackageFragment {
val firFile = firFilesAndSessionsBySourceFile[file]
?: error("cannot find FIR file by source file ${file.name} (${file.path})")
val components = fir2IrActualizedResult.components
return serializeSingleFirFile(
firFile,
components.session,
components.scopeSession,
actualizedExpectDeclarations,
FirKLibSerializerExtension(
components.session, components.firProvider, metadataVersion,
ConstValueProviderImpl(components),
allowErrorTypes = false, exportKDoc = false,
components.annotationsFromPluginRegistrar.createAdditionalMetadataProvider()
),
languageVersionSettings,
)
}
}
fun serializeFirKlib( fun serializeFirKlib(
moduleStructure: ModulesStructure, moduleStructure: ModulesStructure,
firOutputs: List<ModuleCompilerAnalyzedOutput>, firOutputs: List<ModuleCompilerAnalyzedOutput>,
@@ -308,14 +261,20 @@ fun serializeFirKlib(
jsOutputName: String?, jsOutputName: String?,
useWasmPlatform: Boolean, useWasmPlatform: Boolean,
) { ) {
val fir2KlibSerializer = Fir2KlibSerializer(moduleStructure, firOutputs, fir2IrActualizedResult) val fir2KlibMetadataSerializer = Fir2KlibMetadataSerializer(
val icData = moduleStructure.compilerConfiguration.incrementalDataProvider?.getSerializedData(fir2KlibSerializer.sourceFiles) moduleStructure.compilerConfiguration,
firOutputs,
fir2IrActualizedResult,
exportKDoc = false,
produceHeaderKlib = false,
)
val icData = moduleStructure.compilerConfiguration.incrementalDataProvider?.getSerializedData(fir2KlibMetadataSerializer.sourceFiles)
serializeModuleIntoKlib( serializeModuleIntoKlib(
moduleStructure.compilerConfiguration[CommonConfigurationKeys.MODULE_NAME]!!, moduleStructure.compilerConfiguration[CommonConfigurationKeys.MODULE_NAME]!!,
moduleStructure.compilerConfiguration, moduleStructure.compilerConfiguration,
diagnosticsReporter, diagnosticsReporter,
fir2KlibSerializer.sourceFiles, fir2KlibMetadataSerializer,
klibPath = outputKlibPath, klibPath = outputKlibPath,
moduleStructure.allDependencies, moduleStructure.allDependencies,
fir2IrActualizedResult.irModuleFragment, fir2IrActualizedResult.irModuleFragment,
@@ -325,27 +284,6 @@ fun serializeFirKlib(
containsErrorCode = messageCollector.hasErrors() || diagnosticsReporter.hasErrors, containsErrorCode = messageCollector.hasErrors() || diagnosticsReporter.hasErrors,
abiVersion = KotlinAbiVersion.CURRENT, // TODO get from test file data abiVersion = KotlinAbiVersion.CURRENT, // TODO get from test file data
jsOutputName = jsOutputName, jsOutputName = jsOutputName,
serializeSingleFile = fir2KlibSerializer::serializeSingleFirFile,
builtInsPlatform = if (useWasmPlatform) BuiltInsPlatform.WASM else BuiltInsPlatform.JS, builtInsPlatform = if (useWasmPlatform) BuiltInsPlatform.WASM else BuiltInsPlatform.JS,
) )
} }
fun shouldGoToNextIcRound(
moduleStructure: ModulesStructure,
firOutputs: List<ModuleCompilerAnalyzedOutput>,
fir2IrActualizedResult: Fir2IrActualizedResult
): Boolean {
val nextRoundChecker = moduleStructure.compilerConfiguration.get(JSConfigurationKeys.INCREMENTAL_NEXT_ROUND_CHECKER) ?: return false
val fir2KlibSerializer = Fir2KlibSerializer(moduleStructure, firOutputs, fir2IrActualizedResult)
for (ktFile in fir2KlibSerializer.sourceFiles) {
val packageFragment = fir2KlibSerializer.serializeSingleFirFile(ktFile)
// to minimize a number of IC rounds, we should inspect all proto for changes first,
// then go to a next round if needed, with all new dirty files
nextRoundChecker.checkProtoChanges(File(ktFile.path!!), packageFragment.toByteArray())
}
return nextRoundChecker.shouldGoToNextRound()
}
@@ -0,0 +1,103 @@
/*
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.pipeline
import org.jetbrains.kotlin.KtSourceFile
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibSingleFileMetadataSerializer
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.languageVersionSettings
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.packageFqName
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
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.library.metadata.KlibMetadataVersion
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.name.FqName
/**
* Responsible for serializing a FIR file metadata into a protobuf to be later written to a KLIB.
*/
class Fir2KlibMetadataSerializer(
compilerConfiguration: CompilerConfiguration,
private val firOutputs: List<ModuleCompilerAnalyzedOutput>,
private val fir2IrActualizedResult: Fir2IrActualizedResult?,
private val exportKDoc: Boolean,
private val produceHeaderKlib: Boolean,
) : KlibSingleFileMetadataSerializer<FirFile> {
private val firFilesAndSessions: Map<FirFile, Pair<FirSession, ScopeSession>> =
buildMap {
for (firOutput in firOutputs) {
for (firFile in firOutput.fir) {
put(firFile, firOutput.session to firOutput.scopeSession)
}
}
}
private val actualizedExpectDeclarations by lazy {
fir2IrActualizedResult?.irActualizedResult?.actualizedExpectDeclarations?.extractFirDeclarations()
}
private val languageVersionSettings = compilerConfiguration.languageVersionSettings
private val metadataVersion = compilerConfiguration.get(CommonConfigurationKeys.METADATA_VERSION) as? KlibMetadataVersion
?: KlibMetadataVersion.INSTANCE
/**
* The list of source files whose metadata is to be serialized.
*/
val sourceFiles: List<KtSourceFile> = firFilesAndSessions.keys.map { it.sourceFile!! }
override val numberOfSourceFiles: Int
get() = firFilesAndSessions.size
override fun serializeSingleFileMetadata(file: FirFile): ProtoBuf.PackageFragment {
val session: FirSession
val scopeSession: ScopeSession
val firProvider: FirProvider
val components = fir2IrActualizedResult?.components
if (components != null) {
session = components.session
scopeSession = components.scopeSession
firProvider = components.firProvider
} else {
val sessionAndScopeSession = firFilesAndSessions[file] ?: error("Missing FirSession and ScopeSession")
session = sessionAndScopeSession.first
scopeSession = sessionAndScopeSession.second
firProvider = session.firProvider
}
return serializeSingleFirFile(
file,
session,
scopeSession,
actualizedExpectDeclarations,
FirKLibSerializerExtension(
session,
firProvider,
metadataVersion,
components?.let(::ConstValueProviderImpl),
allowErrorTypes = false,
exportKDoc,
components?.annotationsFromPluginRegistrar?.createAdditionalMetadataProvider(),
),
languageVersionSettings,
produceHeaderKlib,
)
}
override fun forEachFile(block: (Int, FirFile, KtSourceFile, FqName) -> Unit) {
firFilesAndSessions.keys.forEachIndexed { i, firFile ->
block(i, firFile, firFile.sourceFile!!, firFile.packageFqName)
}
}
}
@@ -0,0 +1,35 @@
/*
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.serialization.metadata
import org.jetbrains.kotlin.KtSourceFile
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.name.FqName
/**
* Something capable of serializing the metadata of a source file to a protobuf message, one file at a time.
*/
interface KlibSingleFileMetadataSerializer<SourceFile> {
/**
* The number of source files whose metadata is to be serialized.
*/
val numberOfSourceFiles: Int
/**
* Serializes the metadata of a single source file to a protobuf message and returns the message.
*/
fun serializeSingleFileMetadata(file: SourceFile): ProtoBuf.PackageFragment
/**
* Iterates through each file whose metadata is to be serialized, providing an opportunity to call [serializeSingleFileMetadata]
* and perform additional processing of the serialized data.
*
* @param block A closure that accepts the index of the file in the list of source files, the source file, its corresponding
* [KtSourceFile], and the fully qualified name of the package containing the file.
*/
fun forEachFile(block: (Int, SourceFile, KtSourceFile, FqName) -> Unit)
}
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.KtIoFileSourceFile
import org.jetbrains.kotlin.KtPsiSourceFile import org.jetbrains.kotlin.KtPsiSourceFile
import org.jetbrains.kotlin.KtSourceFile import org.jetbrains.kotlin.KtSourceFile
import org.jetbrains.kotlin.KtVirtualFileSourceFile import org.jetbrains.kotlin.KtVirtualFileSourceFile
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibSingleFileMetadataSerializer
import org.jetbrains.kotlin.backend.common.serialization.metadata.serializeKlibHeader import org.jetbrains.kotlin.backend.common.serialization.metadata.serializeKlibHeader
import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
@@ -24,8 +25,6 @@ import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.library.SerializedIrFile import org.jetbrains.kotlin.library.SerializedIrFile
import org.jetbrains.kotlin.library.SerializedIrModule import org.jetbrains.kotlin.library.SerializedIrModule
import org.jetbrains.kotlin.library.SerializedMetadata import org.jetbrains.kotlin.library.SerializedMetadata
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.name.FqName
import java.io.File import java.io.File
/** /**
@@ -86,24 +85,22 @@ fun KtSourceFile.toIoFileOrNull(): File? = when (this) {
* @param irModuleFragment The IR to be serialized into the KLIB being produced, or `null` if this is going to be a metadata-only KLIB. * @param irModuleFragment The IR to be serialized into the KLIB being produced, or `null` if this is going to be a metadata-only KLIB.
* @param configuration Used to determine certain serialization parameters and enable/disable serialization diagnostics. * @param configuration Used to determine certain serialization parameters and enable/disable serialization diagnostics.
* @param diagnosticReporter Used for reporting serialization-time diagnostics, for example, about clashing IR signatures. * @param diagnosticReporter Used for reporting serialization-time diagnostics, for example, about clashing IR signatures.
* @param sourceFiles The source files from which the KLIB is being compiled. Used for serializing file metadata.
* @param compatibilityMode The information about KLIB ABI. * @param compatibilityMode The information about KLIB ABI.
* @param cleanFiles In the case of incremental compilation, the list of files that were not changed and therefore don't need to be * @param cleanFiles In the case of incremental compilation, the list of files that were not changed and therefore don't need to be
* serialized again. * serialized again.
* @param dependencies The list of KLIBs that the KLIB being produced depends on. * @param dependencies The list of KLIBs that the KLIB being produced depends on.
* @param createModuleSerializer Used for creating a backend-specific instance of [IrModuleSerializer]. * @param createModuleSerializer Used for creating a backend-specific instance of [IrModuleSerializer].
* @param serializeFileMetadata The name of this argument kind of speaks for itself. * @param metadataSerializer Something capable of serializing the metadata of the source files. See the corresponding interface KDoc.
* @param runKlibCheckers Additional checks to be run before serializing [irModuleFragment]. Can be used to report serialization-time * @param runKlibCheckers Additional checks to be run before serializing [irModuleFragment]. Can be used to report serialization-time
* diagnostics. * diagnostics.
* @param processCompiledFileData Called for each newly serialized file. Useful for incremental compilation. * @param processCompiledFileData Called for each newly serialized file. Useful for incremental compilation.
* @param processKlibHeader Called after serializing the KLIB header. Useful for incremental compilation. * @param processKlibHeader Called after serializing the KLIB header. Useful for incremental compilation.
*/ */
fun <Dependency : KotlinLibrary> serializeModuleIntoKlib( fun <Dependency : KotlinLibrary, SourceFile> serializeModuleIntoKlib(
moduleName: String, moduleName: String,
irModuleFragment: IrModuleFragment?, irModuleFragment: IrModuleFragment?,
configuration: CompilerConfiguration, configuration: CompilerConfiguration,
diagnosticReporter: DiagnosticReporter, diagnosticReporter: DiagnosticReporter,
sourceFiles: List<KtSourceFile>,
compatibilityMode: CompatibilityMode, compatibilityMode: CompatibilityMode,
cleanFiles: List<KotlinFileSerializedData>, cleanFiles: List<KotlinFileSerializedData>,
dependencies: List<Dependency>, dependencies: List<Dependency>,
@@ -116,14 +113,14 @@ fun <Dependency : KotlinLibrary> serializeModuleIntoKlib(
languageVersionSettings: LanguageVersionSettings, languageVersionSettings: LanguageVersionSettings,
shouldCheckSignaturesOnUniqueness: Boolean, shouldCheckSignaturesOnUniqueness: Boolean,
) -> IrModuleSerializer<*>, ) -> IrModuleSerializer<*>,
serializeFileMetadata: (KtSourceFile) -> Pair<ProtoBuf.PackageFragment, FqName>, metadataSerializer: KlibSingleFileMetadataSerializer<SourceFile>,
runKlibCheckers: (IrModuleFragment, IrDiagnosticReporter, CompilerConfiguration) -> Unit = { _, _, _ -> }, runKlibCheckers: (IrModuleFragment, IrDiagnosticReporter, CompilerConfiguration) -> Unit = { _, _, _ -> },
processCompiledFileData: ((File, KotlinFileSerializedData) -> Unit)? = null, processCompiledFileData: ((File, KotlinFileSerializedData) -> Unit)? = null,
processKlibHeader: (ByteArray) -> Unit = {}, processKlibHeader: (ByteArray) -> Unit = {},
): SerializerOutput<Dependency> { ): SerializerOutput<Dependency> {
if (irModuleFragment != null) { if (irModuleFragment != null) {
assert(sourceFiles.size == irModuleFragment.files.size) { assert(metadataSerializer.numberOfSourceFiles == irModuleFragment.files.size) {
"The number of source files (${sourceFiles.size}) does not match the number of IrFiles (${irModuleFragment.files.size})" "The number of source files (${metadataSerializer.numberOfSourceFiles}) does not match the number of IrFiles (${irModuleFragment.files.size})"
} }
} }
@@ -147,28 +144,31 @@ fun <Dependency : KotlinLibrary> serializeModuleIntoKlib(
val serializedFiles = serializedIr?.files?.toList() val serializedFiles = serializedIr?.files?.toList()
val compiledKotlinFiles = sourceFiles.mapIndexedTo(cleanFiles.toMutableList()) { i, ktSourceFile -> val compiledKotlinFiles = buildList {
val binaryFile = serializedFiles?.get(i)?.also { addAll(cleanFiles)
assert(ktSourceFile.path == it.path) { metadataSerializer.forEachFile { i, sourceFile, ktSourceFile, packageFqName ->
"""The Kt and Ir files are put in different order val binaryFile = serializedFiles?.get(i)?.also {
Kt: ${ktSourceFile.path} assert(ktSourceFile.path == it.path) {
Ir: ${it.path} """The Kt and Ir files are put in different order
""".trimMargin() Kt: ${ktSourceFile.path}
Ir: ${it.path}
""".trimMargin()
}
} }
} val protoBuf = metadataSerializer.serializeSingleFileMetadata(sourceFile)
val (packageFragment, fqName) = serializeFileMetadata(ktSourceFile) val metadata = protoBuf.toByteArray()
val metadata = packageFragment.toByteArray() val compiledKotlinFile = if (binaryFile == null)
val compiledKotlinFile = if (binaryFile == null) KotlinFileSerializedData(metadata, ktSourceFile.path, packageFqName.asString())
KotlinFileSerializedData(metadata, ktSourceFile.path, fqName.asString()) else
else KotlinFileSerializedData(metadata, binaryFile)
KotlinFileSerializedData(metadata, binaryFile)
if (processCompiledFileData != null) { if (processCompiledFileData != null) {
val ioFile = ktSourceFile.toIoFileOrNull() ?: error("No file found for source ${ktSourceFile.path}") val ioFile = ktSourceFile.toIoFileOrNull() ?: error("No file found for source ${ktSourceFile.path}")
processCompiledFileData(ioFile, compiledKotlinFile) processCompiledFileData(ioFile, compiledKotlinFile)
} }
compiledKotlinFile add(compiledKotlinFile)
}
} }
val header = serializeKlibHeader( val header = serializeKlibHeader(
@@ -6,21 +6,35 @@
package org.jetbrains.kotlin.ir.backend.js package org.jetbrains.kotlin.ir.backend.js
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.KtPsiSourceFile
import org.jetbrains.kotlin.KtSourceFile
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataSerializer import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataSerializer
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibSingleFileMetadataSerializer
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.library.metadata.KlibMetadataVersion import org.jetbrains.kotlin.library.metadata.KlibMetadataVersion
import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingContextUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.serialization.DescriptorSerializer import org.jetbrains.kotlin.serialization.DescriptorSerializer
// TODO: need a refactoring between IncrementalSerializer and MonolithicSerializer. // TODO: need a refactoring between IncrementalSerializer and MonolithicSerializer.
class KlibMetadataIncrementalSerializer( class KlibMetadataIncrementalSerializer(
private val ktFiles: List<KtFile>,
private val bindingContext: BindingContext,
private val moduleDescriptor: ModuleDescriptor,
languageVersionSettings: LanguageVersionSettings, languageVersionSettings: LanguageVersionSettings,
metadataVersion: KlibMetadataVersion, metadataVersion: KlibMetadataVersion,
project: Project, project: Project,
@@ -33,9 +47,54 @@ class KlibMetadataIncrementalSerializer(
exportKDoc = exportKDoc, exportKDoc = exportKDoc,
skipExpects = true, // Incremental compilation is not supposed to work when producing pure metadata (IR-less) KLIBs. skipExpects = true, // Incremental compilation is not supposed to work when producing pure metadata (IR-less) KLIBs.
allowErrorTypes = allowErrorTypes allowErrorTypes = allowErrorTypes
) { ), KlibSingleFileMetadataSerializer<KtFile> {
fun serializePackageFragment( constructor(
files: List<KtFile>,
configuration: CompilerConfiguration,
project: Project,
bindingContext: BindingContext,
moduleDescriptor: ModuleDescriptor,
allowErrorTypes: Boolean,
) : this(
ktFiles = files,
bindingContext = bindingContext,
moduleDescriptor = moduleDescriptor,
languageVersionSettings = configuration.languageVersionSettings,
metadataVersion = configuration.get(CommonConfigurationKeys.METADATA_VERSION) as? KlibMetadataVersion
?: KlibMetadataVersion.INSTANCE,
project = project,
exportKDoc = false,
allowErrorTypes = allowErrorTypes,
)
constructor(modulesStructure: ModulesStructure, moduleFragment: IrModuleFragment) : this(
(modulesStructure.mainModule as MainModule.SourceFiles).files,
modulesStructure.compilerConfiguration,
modulesStructure.project,
modulesStructure.jsFrontEndResult.bindingContext,
moduleFragment.descriptor,
modulesStructure.jsFrontEndResult.hasErrors,
)
override fun serializeSingleFileMetadata(file: KtFile): ProtoBuf.PackageFragment {
val memberScope = file.declarations.map { getDescriptorForElement(bindingContext, it) }
return serializePackageFragment(moduleDescriptor, memberScope, file.packageFqName)
}
override val numberOfSourceFiles: Int
get() = ktFiles.size
override fun forEachFile(block: (Int, KtFile, KtSourceFile, FqName) -> Unit) {
ktFiles.forEachIndexed { i, ktFile ->
block(i, ktFile, KtPsiSourceFile(ktFile), ktFile.packageFqName)
}
}
private fun getDescriptorForElement(context: BindingContext, element: PsiElement): DeclarationDescriptor =
BindingContextUtils.getNotNull(context, BindingContext.DECLARATION_TO_DESCRIPTOR, element)
private fun serializePackageFragment(
module: ModuleDescriptor, module: ModuleDescriptor,
scope: Collection<DeclarationDescriptor>, scope: Collection<DeclarationDescriptor>,
fqName: FqName fqName: FqName
@@ -6,9 +6,8 @@
package org.jetbrains.kotlin.ir.backend.js package org.jetbrains.kotlin.ir.backend.js
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VfsUtilCore import org.jetbrains.kotlin.KtPsiSourceFile
import com.intellij.psi.PsiElement import org.jetbrains.kotlin.KtSourceFile
import org.jetbrains.kotlin.*
import org.jetbrains.kotlin.analyzer.AbstractAnalyzerWithCompilerReport import org.jetbrains.kotlin.analyzer.AbstractAnalyzerWithCompilerReport
import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.analyzer.CompilationErrorException import org.jetbrains.kotlin.analyzer.CompilationErrorException
@@ -22,12 +21,12 @@ import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideChecker
import org.jetbrains.kotlin.backend.common.serialization.* import org.jetbrains.kotlin.backend.common.serialization.*
import org.jetbrains.kotlin.backend.common.serialization.mangle.ManglerChecker import org.jetbrains.kotlin.backend.common.serialization.mangle.ManglerChecker
import org.jetbrains.kotlin.backend.common.serialization.mangle.descriptor.Ir2DescriptorManglerAdapter import org.jetbrains.kotlin.backend.common.serialization.mangle.descriptor.Ir2DescriptorManglerAdapter
import org.jetbrains.kotlin.backend.common.serialization.metadata.* import org.jetbrains.kotlin.backend.common.serialization.metadata.DynamicTypeDeserializer
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibSingleFileMetadataSerializer
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureDescriptor import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureDescriptor
import org.jetbrains.kotlin.backend.common.toLogger import org.jetbrains.kotlin.backend.common.toLogger
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
@@ -55,8 +54,6 @@ import org.jetbrains.kotlin.library.impl.BuiltInsPlatform
import org.jetbrains.kotlin.library.impl.buildKotlinLibrary import org.jetbrains.kotlin.library.impl.buildKotlinLibrary
import org.jetbrains.kotlin.library.metadata.KlibMetadataFactories import org.jetbrains.kotlin.library.metadata.KlibMetadataFactories
import org.jetbrains.kotlin.library.metadata.KlibMetadataVersion import org.jetbrains.kotlin.library.metadata.KlibMetadataVersion
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.progress.IncrementalNextRoundException import org.jetbrains.kotlin.progress.IncrementalNextRoundException
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
@@ -66,7 +63,6 @@ import org.jetbrains.kotlin.psi2ir.descriptors.IrBuiltInsOverDescriptors
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
import org.jetbrains.kotlin.psi2ir.generators.TypeTranslatorImpl import org.jetbrains.kotlin.psi2ir.generators.TypeTranslatorImpl
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingContextUtils
import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.utils.DFS import org.jetbrains.kotlin.utils.DFS
@@ -94,9 +90,6 @@ val KotlinLibrary.serializedIrFileFingerprints: List<SerializedIrFileFingerprint
val KotlinLibrary.serializedKlibFingerprint: SerializedKlibFingerprint? val KotlinLibrary.serializedKlibFingerprint: SerializedKlibFingerprint?
get() = manifestProperties.getProperty(KLIB_PROPERTY_SERIALIZED_KLIB_FINGERPRINT)?.let { SerializedKlibFingerprint.fromString(it) } get() = manifestProperties.getProperty(KLIB_PROPERTY_SERIALIZED_KLIB_FINGERPRINT)?.let { SerializedKlibFingerprint.fromString(it) }
private val CompilerConfiguration.metadataVersion
get() = get(CommonConfigurationKeys.METADATA_VERSION) as? KlibMetadataVersion ?: KlibMetadataVersion.INSTANCE
internal val SerializedIrFile.fileMetadata: ByteArray internal val SerializedIrFile.fileMetadata: ByteArray
get() = backendSpecificMetadata ?: error("Expect file caches to have backendSpecificMetadata, but '$path' doesn't") get() = backendSpecificMetadata ?: error("Expect file caches to have backendSpecificMetadata, but '$path' doesn't")
@@ -110,9 +103,7 @@ fun generateKLib(
moduleFragment: IrModuleFragment, moduleFragment: IrModuleFragment,
diagnosticReporter: DiagnosticReporter, diagnosticReporter: DiagnosticReporter,
builtInsPlatform: BuiltInsPlatform = BuiltInsPlatform.JS, builtInsPlatform: BuiltInsPlatform = BuiltInsPlatform.JS,
serializeSingleFile: (KtSourceFile) -> ProtoBuf.PackageFragment
) { ) {
val files = (depsDescriptors.mainModule as MainModule.SourceFiles).files.map(::KtPsiSourceFile)
val configuration = depsDescriptors.compilerConfiguration val configuration = depsDescriptors.compilerConfiguration
val allDependencies = depsDescriptors.allDependencies val allDependencies = depsDescriptors.allDependencies
@@ -120,7 +111,7 @@ fun generateKLib(
configuration[CommonConfigurationKeys.MODULE_NAME]!!, configuration[CommonConfigurationKeys.MODULE_NAME]!!,
configuration, configuration,
diagnosticReporter, diagnosticReporter,
files, KlibMetadataIncrementalSerializer(depsDescriptors, moduleFragment),
outputKlibPath, outputKlibPath,
allDependencies, allDependencies,
moduleFragment, moduleFragment,
@@ -131,7 +122,6 @@ fun generateKLib(
abiVersion, abiVersion,
jsOutputName, jsOutputName,
builtInsPlatform, builtInsPlatform,
serializeSingleFile
) )
} }
@@ -521,8 +511,19 @@ class ModulesStructure(
val analysisResult = analyzer.analysisResult val analysisResult = analyzer.analysisResult
if (compilerConfiguration.getBoolean(CommonConfigurationKeys.INCREMENTAL_COMPILATION)) { if (compilerConfiguration.getBoolean(CommonConfigurationKeys.INCREMENTAL_COMPILATION)) {
/** can throw [IncrementalNextRoundException] */ val shouldGoToNextIcRound = shouldGoToNextIcRound(compilerConfiguration) {
compareMetadataAndGoToNextICRoundIfNeeded(analysisResult, compilerConfiguration, project, files, errorPolicy.allowErrors) KlibMetadataIncrementalSerializer(
files,
compilerConfiguration,
project,
analysisResult.bindingContext,
analysisResult.moduleDescriptor,
errorPolicy.allowErrors,
)
}
if (shouldGoToNextIcRound) {
throw IncrementalNextRoundException()
}
} }
var hasErrors = false var hasErrors = false
@@ -589,12 +590,6 @@ class ModulesStructure(
null // null in case compiling builtInModule itself null // null in case compiling builtInModule itself
} }
private fun getDescriptorForElement(
context: BindingContext,
element: PsiElement
): DeclarationDescriptor = BindingContextUtils.getNotNull(context, BindingContext.DECLARATION_TO_DESCRIPTOR, element)
private const val FILE_FINGERPRINTS_SEPARATOR = " " private const val FILE_FINGERPRINTS_SEPARATOR = " "
private fun List<SerializedIrFileFingerprint>.joinIrFileFingerprints(): String { private fun List<SerializedIrFileFingerprint>.joinIrFileFingerprints(): String {
@@ -609,7 +604,7 @@ fun serializeModuleIntoKlib(
moduleName: String, moduleName: String,
configuration: CompilerConfiguration, configuration: CompilerConfiguration,
diagnosticReporter: DiagnosticReporter, diagnosticReporter: DiagnosticReporter,
files: List<KtSourceFile>, metadataSerializer: KlibSingleFileMetadataSerializer<*>,
klibPath: String, klibPath: String,
dependencies: List<KotlinLibrary>, dependencies: List<KotlinLibrary>,
moduleFragment: IrModuleFragment, moduleFragment: IrModuleFragment,
@@ -620,7 +615,6 @@ fun serializeModuleIntoKlib(
abiVersion: KotlinAbiVersion, abiVersion: KotlinAbiVersion,
jsOutputName: String?, jsOutputName: String?,
builtInsPlatform: BuiltInsPlatform = BuiltInsPlatform.JS, builtInsPlatform: BuiltInsPlatform = BuiltInsPlatform.JS,
serializeSingleFile: (KtSourceFile) -> ProtoBuf.PackageFragment
) { ) {
val moduleExportedNames = moduleFragment.collectExportedNames() val moduleExportedNames = moduleFragment.collectExportedNames()
val incrementalResultsConsumer = configuration.get(JSConfigurationKeys.INCREMENTAL_RESULTS_CONSUMER) val incrementalResultsConsumer = configuration.get(JSConfigurationKeys.INCREMENTAL_RESULTS_CONSUMER)
@@ -630,7 +624,6 @@ fun serializeModuleIntoKlib(
irModuleFragment = moduleFragment, irModuleFragment = moduleFragment,
configuration = configuration, configuration = configuration,
diagnosticReporter = diagnosticReporter, diagnosticReporter = diagnosticReporter,
sourceFiles = files,
compatibilityMode = CompatibilityMode(abiVersion), compatibilityMode = CompatibilityMode(abiVersion),
cleanFiles = cleanFiles, cleanFiles = cleanFiles,
dependencies = dependencies, dependencies = dependencies,
@@ -653,7 +646,7 @@ fun serializeModuleIntoKlib(
shouldCheckSignaturesOnUniqueness, shouldCheckSignaturesOnUniqueness,
) { JsIrFileMetadata(moduleExportedNames[it]?.values?.toSmartList() ?: emptyList()) } ) { JsIrFileMetadata(moduleExportedNames[it]?.values?.toSmartList() ?: emptyList()) }
}, },
serializeFileMetadata = { serializeSingleFile(it) to FqName.ROOT }, metadataSerializer = metadataSerializer,
runKlibCheckers = { irModuleFragment, irDiagnosticReporter, compilerConfiguration -> runKlibCheckers = { irModuleFragment, irDiagnosticReporter, compilerConfiguration ->
if (builtInsPlatform == BuiltInsPlatform.JS) { if (builtInsPlatform == BuiltInsPlatform.JS) {
val cleanFilesIrData = cleanFiles.map { it.irData ?: error("Metadata-only KLIBs are not supported in Kotlin/JS") } val cleanFilesIrData = cleanFiles.map { it.irData ?: error("Metadata-only KLIBs are not supported in Kotlin/JS") }
@@ -725,54 +718,22 @@ const val KLIB_PROPERTY_JS_OUTPUT_NAME = "jsOutputName"
const val KLIB_PROPERTY_SERIALIZED_IR_FILE_FINGERPRINTS = "serializedIrFileFingerprints" const val KLIB_PROPERTY_SERIALIZED_IR_FILE_FINGERPRINTS = "serializedIrFileFingerprints"
const val KLIB_PROPERTY_SERIALIZED_KLIB_FINGERPRINT = "serializedKlibFingerprint" const val KLIB_PROPERTY_SERIALIZED_KLIB_FINGERPRINT = "serializedKlibFingerprint"
fun KlibMetadataIncrementalSerializer.serializeScope( fun <SourceFile> shouldGoToNextIcRound(
ktFile: KtFile, compilerConfiguration: CompilerConfiguration,
bindingContext: BindingContext, createMetadataSerializer: () -> KlibSingleFileMetadataSerializer<SourceFile>,
moduleDescriptor: ModuleDescriptor ): Boolean {
): ProtoBuf.PackageFragment { val nextRoundChecker = compilerConfiguration.get(JSConfigurationKeys.INCREMENTAL_NEXT_ROUND_CHECKER) ?: return false
val memberScope = ktFile.declarations.map { getDescriptorForElement(bindingContext, it) } createMetadataSerializer().run {
return serializePackageFragment(moduleDescriptor, memberScope, ktFile.packageFqName) forEachFile { _, sourceFile, ktSourceFile, _ ->
} val protoBuf = serializeSingleFileMetadata(sourceFile)
// to minimize the number of IC rounds, we should inspect all proto for changes first,
fun KlibMetadataIncrementalSerializer.serializeScope( // then go to the next round if needed, with all new dirty files
ktSourceFile: KtSourceFile, nextRoundChecker.checkProtoChanges(ktSourceFile.toIoFileOrNull()!!, protoBuf.toByteArray())
bindingContext: BindingContext, }
moduleDescriptor: ModuleDescriptor
): ProtoBuf.PackageFragment {
val ktFile = (ktSourceFile as KtPsiSourceFile).psiFile as KtFile
val memberScope = ktFile.declarations.map { getDescriptorForElement(bindingContext, it) }
return serializePackageFragment(moduleDescriptor, memberScope, ktFile.packageFqName)
}
private fun compareMetadataAndGoToNextICRoundIfNeeded(
analysisResult: AnalysisResult,
config: CompilerConfiguration,
project: Project,
files: List<KtFile>,
allowErrors: Boolean
) {
val nextRoundChecker = config.get(JSConfigurationKeys.INCREMENTAL_NEXT_ROUND_CHECKER) ?: return
val bindingContext = analysisResult.bindingContext
val serializer = KlibMetadataIncrementalSerializer(config, project, allowErrors)
for (ktFile in files) {
val packageFragment = serializer.serializeScope(ktFile, bindingContext, analysisResult.moduleDescriptor)
// to minimize a number of IC rounds, we should inspect all proto for changes first,
// then go to a next round if needed, with all new dirty files
nextRoundChecker.checkProtoChanges(VfsUtilCore.virtualToIoFile(ktFile.virtualFile), packageFragment.toByteArray())
} }
return nextRoundChecker.shouldGoToNextRound()
if (nextRoundChecker.shouldGoToNextRound()) throw IncrementalNextRoundException()
} }
fun KlibMetadataIncrementalSerializer(configuration: CompilerConfiguration, project: Project, allowErrors: Boolean) =
KlibMetadataIncrementalSerializer(
languageVersionSettings = configuration.languageVersionSettings,
metadataVersion = configuration.metadataVersion,
project = project,
exportKDoc = false,
allowErrorTypes = allowErrors
)
private fun Map<IrModuleFragment, KotlinLibrary>.getUniqueNameForEachFragment(): Map<IrModuleFragment, String> { private fun Map<IrModuleFragment, KotlinLibrary>.getUniqueNameForEachFragment(): Map<IrModuleFragment, String> {
return this.entries.mapNotNull { (moduleFragment, klib) -> return this.entries.mapNotNull { (moduleFragment, klib) ->
klib.jsOutputName?.let { moduleFragment to it } klib.jsOutputName?.let { moduleFragment to it }
@@ -8,13 +8,13 @@ package org.jetbrains.kotlin.test.backend.ir
import org.jetbrains.kotlin.KtSourceFile import org.jetbrains.kotlin.KtSourceFile
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.serialization.KotlinFileSerializedData import org.jetbrains.kotlin.backend.common.serialization.KotlinFileSerializedData
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibSingleFileMetadataSerializer
import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.diagnostics.impl.BaseDiagnosticsCollector import org.jetbrains.kotlin.diagnostics.impl.BaseDiagnosticsCollector
import org.jetbrains.kotlin.fir.backend.FirMangler import org.jetbrains.kotlin.fir.backend.FirMangler
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.util.KotlinMangler import org.jetbrains.kotlin.ir.util.KotlinMangler
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.test.model.BackendKind import org.jetbrains.kotlin.test.model.BackendKind
import org.jetbrains.kotlin.test.model.BackendKinds import org.jetbrains.kotlin.test.model.BackendKinds
import org.jetbrains.kotlin.test.model.ResultingArtifact import org.jetbrains.kotlin.test.model.ResultingArtifact
@@ -66,14 +66,13 @@ sealed class IrBackendInput : ResultingArtifact.BackendInput<IrBackendInput>() {
class JsIrBackendInput( class JsIrBackendInput(
override val irModuleFragment: IrModuleFragment, override val irModuleFragment: IrModuleFragment,
override val irPluginContext: IrPluginContext, override val irPluginContext: IrPluginContext,
val sourceFiles: List<KtSourceFile>,
val icData: List<KotlinFileSerializedData>, val icData: List<KotlinFileSerializedData>,
override val diagnosticReporter: BaseDiagnosticsCollector, override val diagnosticReporter: BaseDiagnosticsCollector,
val hasErrors: Boolean, val hasErrors: Boolean,
override val descriptorMangler: KotlinMangler.DescriptorMangler?, override val descriptorMangler: KotlinMangler.DescriptorMangler?,
override val irMangler: KotlinMangler.IrMangler, override val irMangler: KotlinMangler.IrMangler,
override val firMangler: FirMangler?, override val firMangler: FirMangler?,
val serializeSingleFile: (KtSourceFile) -> ProtoBuf.PackageFragment, val metadataSerializer: KlibSingleFileMetadataSerializer<*>,
) : IrBackendInput() ) : IrBackendInput()
data class JsIrDeserializedFromKlibBackendInput( data class JsIrDeserializedFromKlibBackendInput(
@@ -92,14 +91,13 @@ sealed class IrBackendInput : ResultingArtifact.BackendInput<IrBackendInput>() {
class WasmBackendInput( class WasmBackendInput(
override val irModuleFragment: IrModuleFragment, override val irModuleFragment: IrModuleFragment,
override val irPluginContext: IrPluginContext, override val irPluginContext: IrPluginContext,
val sourceFiles: List<KtSourceFile>,
val icData: List<KotlinFileSerializedData>, val icData: List<KotlinFileSerializedData>,
override val diagnosticReporter: BaseDiagnosticsCollector, override val diagnosticReporter: BaseDiagnosticsCollector,
val hasErrors: Boolean, val hasErrors: Boolean,
override val descriptorMangler: KotlinMangler.DescriptorMangler?, override val descriptorMangler: KotlinMangler.DescriptorMangler?,
override val irMangler: KotlinMangler.IrMangler, override val irMangler: KotlinMangler.IrMangler,
override val firMangler: FirMangler?, override val firMangler: FirMangler?,
val serializeSingleFile: (KtSourceFile) -> ProtoBuf.PackageFragment, val metadataSerializer: KlibSingleFileMetadataSerializer<*>,
) : IrBackendInput() ) : IrBackendInput()
class JvmIrBackendInput( class JvmIrBackendInput(
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.test.frontend.classic package org.jetbrains.kotlin.test.frontend.classic
import org.jetbrains.kotlin.KtPsiSourceFile
import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.js.klib.TopDownAnalyzerFacadeForJSIR import org.jetbrains.kotlin.cli.js.klib.TopDownAnalyzerFacadeForJSIR
@@ -105,21 +104,26 @@ class ClassicFrontend2IrConverter(
val errorPolicy = configuration.get(JSConfigurationKeys.ERROR_TOLERANCE_POLICY) ?: ErrorTolerancePolicy.DEFAULT val errorPolicy = configuration.get(JSConfigurationKeys.ERROR_TOLERANCE_POLICY) ?: ErrorTolerancePolicy.DEFAULT
val hasErrors = TopDownAnalyzerFacadeForJSIR.checkForErrors(sourceFiles, analysisResult.bindingContext, errorPolicy) val hasErrors = TopDownAnalyzerFacadeForJSIR.checkForErrors(sourceFiles, analysisResult.bindingContext, errorPolicy)
val metadataSerializer = KlibMetadataIncrementalSerializer(configuration, project, hasErrors) val metadataSerializer = KlibMetadataIncrementalSerializer(
sourceFiles,
configuration,
project,
analysisResult.bindingContext,
moduleFragment.descriptor,
hasErrors,
)
return IrBackendInput.JsIrBackendInput( return IrBackendInput.JsIrBackendInput(
moduleFragment, moduleFragment,
pluginContext, pluginContext,
sourceFiles.map(::KtPsiSourceFile),
icData, icData,
diagnosticReporter = DiagnosticReporterFactory.createReporter(), diagnosticReporter = DiagnosticReporterFactory.createReporter(),
hasErrors, hasErrors,
descriptorMangler = (pluginContext.symbolTable as SymbolTable).signaturer!!.mangler, descriptorMangler = (pluginContext.symbolTable as SymbolTable).signaturer!!.mangler,
irMangler = JsManglerIr, irMangler = JsManglerIr,
firMangler = null, firMangler = null,
) { file -> metadataSerializer = metadataSerializer,
metadataSerializer.serializeScope(file, analysisResult.bindingContext, moduleFragment.descriptor) )
}
} }
private fun transformToWasmIr(module: TestModule, inputArtifact: ClassicFrontendOutputArtifact): IrBackendInput { private fun transformToWasmIr(module: TestModule, inputArtifact: ClassicFrontendOutputArtifact): IrBackendInput {
@@ -147,20 +151,25 @@ class ClassicFrontend2IrConverter(
val errorPolicy = configuration.get(JSConfigurationKeys.ERROR_TOLERANCE_POLICY) ?: ErrorTolerancePolicy.DEFAULT val errorPolicy = configuration.get(JSConfigurationKeys.ERROR_TOLERANCE_POLICY) ?: ErrorTolerancePolicy.DEFAULT
val analyzerFacade = TopDownAnalyzerFacadeForWasm.facadeFor(configuration.get(JSConfigurationKeys.WASM_TARGET)) val analyzerFacade = TopDownAnalyzerFacadeForWasm.facadeFor(configuration.get(JSConfigurationKeys.WASM_TARGET))
val hasErrors = analyzerFacade.checkForErrors(sourceFiles, analysisResult.bindingContext, errorPolicy) val hasErrors = analyzerFacade.checkForErrors(sourceFiles, analysisResult.bindingContext, errorPolicy)
val metadataSerializer = KlibMetadataIncrementalSerializer(configuration, project, hasErrors) val metadataSerializer = KlibMetadataIncrementalSerializer(
sourceFiles,
configuration,
project,
analysisResult.bindingContext,
moduleFragment.descriptor,
hasErrors,
)
return IrBackendInput.WasmBackendInput( return IrBackendInput.WasmBackendInput(
moduleFragment, moduleFragment,
pluginContext, pluginContext,
sourceFiles.map(::KtPsiSourceFile),
icData, icData,
diagnosticReporter = DiagnosticReporterFactory.createReporter(), diagnosticReporter = DiagnosticReporterFactory.createReporter(),
hasErrors, hasErrors,
descriptorMangler = (pluginContext.symbolTable as SymbolTable).signaturer!!.mangler, descriptorMangler = (pluginContext.symbolTable as SymbolTable).signaturer!!.mangler,
irMangler = JsManglerIr, irMangler = JsManglerIr,
firMangler = null, firMangler = null,
) { file -> metadataSerializer = metadataSerializer,
metadataSerializer.serializeScope(file, analysisResult.bindingContext, moduleFragment.descriptor) )
}
} }
} }
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.test.frontend.fir package org.jetbrains.kotlin.test.frontend.fir
import org.jetbrains.kotlin.KtSourceFile
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.builtins.DefaultBuiltIns import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
@@ -17,12 +16,8 @@ import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
import org.jetbrains.kotlin.diagnostics.impl.BaseDiagnosticsCollector import org.jetbrains.kotlin.diagnostics.impl.BaseDiagnosticsCollector
import org.jetbrains.kotlin.fir.backend.* import org.jetbrains.kotlin.fir.backend.*
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
import org.jetbrains.kotlin.fir.pipeline.Fir2IrActualizedResult import org.jetbrains.kotlin.fir.pipeline.*
import org.jetbrains.kotlin.fir.pipeline.FirResult
import org.jetbrains.kotlin.fir.pipeline.ModuleCompilerAnalyzedOutput
import org.jetbrains.kotlin.fir.pipeline.convertToIrAndActualize
import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.ir.types.IrTypeSystemContextImpl import org.jetbrains.kotlin.ir.types.IrTypeSystemContextImpl
import org.jetbrains.kotlin.ir.util.KotlinMangler import org.jetbrains.kotlin.ir.util.KotlinMangler
@@ -74,8 +69,6 @@ abstract class AbstractFir2IrNonJvmResultsConverter(
inputArtifact: FirOutputArtifact inputArtifact: FirOutputArtifact
): IrBackendInput { ): IrBackendInput {
val compilerConfiguration = testServices.compilerConfigurationProvider.getCompilerConfiguration(module) val compilerConfiguration = testServices.compilerConfigurationProvider.getCompilerConfiguration(module)
val sourceFiles = mutableListOf<KtSourceFile>()
val firFilesAndComponentsBySourceFile = mutableMapOf<KtSourceFile, Pair<FirFile, Fir2IrComponents>>()
val irMangler = createIrMangler() val irMangler = createIrMangler()
val diagnosticReporter = DiagnosticReporterFactory.createReporter() val diagnosticReporter = DiagnosticReporterFactory.createReporter()
@@ -87,7 +80,8 @@ abstract class AbstractFir2IrNonJvmResultsConverter(
compilerConfiguration, compilerConfiguration,
diagnosticReporter, diagnosticReporter,
) )
val fir2irResult = inputArtifact.toFirResult().convertToIrAndActualize( val firResult = inputArtifact.toFirResult()
val fir2irResult = firResult.convertToIrAndActualize(
Fir2IrExtensions.Default, Fir2IrExtensions.Default,
fir2IrConfiguration, fir2IrConfiguration,
module.irGenerationExtensions(testServices), module.irGenerationExtensions(testServices),
@@ -96,16 +90,23 @@ abstract class AbstractFir2IrNonJvmResultsConverter(
Fir2IrVisibilityConverter.Default, Fir2IrVisibilityConverter.Default,
builtIns ?: DefaultBuiltIns.Instance, // TODO: consider passing externally, builtIns ?: DefaultBuiltIns.Instance, // TODO: consider passing externally,
::IrTypeSystemContextImpl ::IrTypeSystemContextImpl
) { firPart, irPart -> ).also {
sourceFiles.addAll(firPart.fir.mapNotNull { it.sourceFile })
for (firFile in firPart.fir) {
firFilesAndComponentsBySourceFile[firFile.sourceFile!!] = firFile to irPart.components
}
}.also {
(it.irModuleFragment.descriptor as? FirModuleDescriptor)?.let { it.allDependencyModules = dependencies } (it.irModuleFragment.descriptor as? FirModuleDescriptor)?.let { it.allDependencyModules = dependencies }
} }
return createBackendInput(compilerConfiguration, diagnosticReporter, inputArtifact, fir2irResult, firFilesAndComponentsBySourceFile, sourceFiles) return createBackendInput(
compilerConfiguration,
diagnosticReporter,
inputArtifact,
fir2irResult,
Fir2KlibMetadataSerializer(
compilerConfiguration,
firResult.outputs,
fir2irResult,
exportKDoc = false,
produceHeaderKlib = false,
),
)
} }
protected abstract fun createBackendInput( protected abstract fun createBackendInput(
@@ -113,8 +114,7 @@ abstract class AbstractFir2IrNonJvmResultsConverter(
diagnosticReporter: BaseDiagnosticsCollector, diagnosticReporter: BaseDiagnosticsCollector,
inputArtifact: FirOutputArtifact, inputArtifact: FirOutputArtifact,
fir2IrResult: Fir2IrActualizedResult, fir2IrResult: Fir2IrActualizedResult,
firFilesAndComponentsBySourceFile: Map<KtSourceFile, Pair<FirFile, Fir2IrComponents>>, fir2KlibMetadataSerializer: Fir2KlibMetadataSerializer,
sourceFiles: List<KtSourceFile>
): IrBackendInput ): IrBackendInput
private fun loadResolvedLibraries( private fun loadResolvedLibraries(
@@ -5,21 +5,15 @@
package org.jetbrains.kotlin.test.frontend.fir package org.jetbrains.kotlin.test.frontend.fir
import org.jetbrains.kotlin.KtSourceFile
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.serialization.KotlinFileSerializedData import org.jetbrains.kotlin.backend.common.serialization.KotlinFileSerializedData
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibSingleFileMetadataSerializer
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.diagnostics.impl.BaseDiagnosticsCollector import org.jetbrains.kotlin.diagnostics.impl.BaseDiagnosticsCollector
import org.jetbrains.kotlin.fir.backend.ConstValueProviderImpl
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
import org.jetbrains.kotlin.fir.backend.FirMangler import org.jetbrains.kotlin.fir.backend.FirMangler
import org.jetbrains.kotlin.fir.backend.extractFirDeclarations
import org.jetbrains.kotlin.fir.backend.js.FirJsKotlinMangler import org.jetbrains.kotlin.fir.backend.js.FirJsKotlinMangler
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.pipeline.Fir2IrActualizedResult import org.jetbrains.kotlin.fir.pipeline.Fir2IrActualizedResult
import org.jetbrains.kotlin.fir.serialization.FirKLibSerializerExtension import org.jetbrains.kotlin.fir.pipeline.Fir2KlibMetadataSerializer
import org.jetbrains.kotlin.fir.serialization.serializeSingleFirFile
import org.jetbrains.kotlin.ir.backend.js.JsFactories import org.jetbrains.kotlin.ir.backend.js.JsFactories
import org.jetbrains.kotlin.ir.backend.js.getSerializedData import org.jetbrains.kotlin.ir.backend.js.getSerializedData
import org.jetbrains.kotlin.ir.backend.js.incrementalDataProvider import org.jetbrains.kotlin.ir.backend.js.incrementalDataProvider
@@ -28,25 +22,22 @@ import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.util.KotlinMangler import org.jetbrains.kotlin.ir.util.KotlinMangler
import org.jetbrains.kotlin.library.metadata.KlibMetadataFactories import org.jetbrains.kotlin.library.metadata.KlibMetadataFactories
import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.test.backend.ir.IrBackendInput import org.jetbrains.kotlin.test.backend.ir.IrBackendInput
import org.jetbrains.kotlin.test.frontend.fir.handlers.firDiagnosticCollectorService import org.jetbrains.kotlin.test.frontend.fir.handlers.firDiagnosticCollectorService
import org.jetbrains.kotlin.test.model.TestModule import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestServices import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.utils.metadataVersion
abstract class Fir2IrJsWasmResultsConverter(testServices: TestServices) : AbstractFir2IrNonJvmResultsConverter(testServices) { abstract class Fir2IrJsWasmResultsConverter(testServices: TestServices) : AbstractFir2IrNonJvmResultsConverter(testServices) {
protected abstract val artifactFactory: ( protected abstract val artifactFactory: (
IrModuleFragment, IrModuleFragment,
IrPluginContext, IrPluginContext,
List<KtSourceFile>,
List<KotlinFileSerializedData>, List<KotlinFileSerializedData>,
BaseDiagnosticsCollector, BaseDiagnosticsCollector,
Boolean, Boolean,
KotlinMangler.DescriptorMangler?, KotlinMangler.DescriptorMangler?,
KotlinMangler.IrMangler, KotlinMangler.IrMangler,
FirMangler?, FirMangler?,
(KtSourceFile) -> ProtoBuf.PackageFragment KlibSingleFileMetadataSerializer<*>,
) -> IrBackendInput ) -> IrBackendInput
override fun createIrMangler(): KotlinMangler.IrMangler { override fun createIrMangler(): KotlinMangler.IrMangler {
@@ -65,46 +56,25 @@ abstract class Fir2IrJsWasmResultsConverter(testServices: TestServices) : Abstra
diagnosticReporter: BaseDiagnosticsCollector, diagnosticReporter: BaseDiagnosticsCollector,
inputArtifact: FirOutputArtifact, inputArtifact: FirOutputArtifact,
fir2IrResult: Fir2IrActualizedResult, fir2IrResult: Fir2IrActualizedResult,
firFilesAndComponentsBySourceFile: Map<KtSourceFile, Pair<FirFile, Fir2IrComponents>>, fir2KlibMetadataSerializer: Fir2KlibMetadataSerializer,
sourceFiles: List<KtSourceFile>,
): IrBackendInput { ): IrBackendInput {
val languageVersionSettings = compilerConfiguration.languageVersionSettings val manglers = fir2IrResult.components.manglers
val metadataVersion = compilerConfiguration.metadataVersion(languageVersionSettings.languageVersion)
val fir2IrComponents = fir2IrResult.components
val manglers = fir2IrComponents.manglers
return artifactFactory( return artifactFactory(
fir2IrResult.irModuleFragment, fir2IrResult.irModuleFragment,
fir2IrResult.pluginContext, fir2IrResult.pluginContext,
sourceFiles, compilerConfiguration.incrementalDataProvider?.getSerializedData(fir2KlibMetadataSerializer.sourceFiles) ?: emptyList(),
compilerConfiguration.incrementalDataProvider?.getSerializedData(sourceFiles) ?: emptyList(),
diagnosticReporter, diagnosticReporter,
testServices.firDiagnosticCollectorService.containsErrors(inputArtifact), testServices.firDiagnosticCollectorService.containsErrors(inputArtifact),
/*descriptorMangler = */null, /*descriptorMangler = */null,
manglers.irMangler, manglers.irMangler,
manglers.firMangler, manglers.firMangler,
) { file -> fir2KlibMetadataSerializer,
val (firFile, components) = firFilesAndComponentsBySourceFile[file] )
?: error("cannot find FIR file by source file ${file.name} (${file.path})")
val actualizedExpectDeclarations = fir2IrResult.irActualizedResult?.actualizedExpectDeclarations?.extractFirDeclarations()
serializeSingleFirFile(
firFile,
components.session,
components.scopeSession,
actualizedExpectDeclarations,
FirKLibSerializerExtension(
components.session, components.firProvider, metadataVersion,
ConstValueProviderImpl(components),
allowErrorTypes = false, exportKDoc = false,
components.annotationsFromPluginRegistrar.createAdditionalMetadataProvider()
),
languageVersionSettings,
)
}
} }
} }
class Fir2IrJsResultsConverter(testServices: TestServices) : Fir2IrJsWasmResultsConverter(testServices) { class Fir2IrJsResultsConverter(testServices: TestServices) : Fir2IrJsWasmResultsConverter(testServices) {
override val artifactFactory: (IrModuleFragment, IrPluginContext, List<KtSourceFile>, List<KotlinFileSerializedData>, BaseDiagnosticsCollector, Boolean, KotlinMangler.DescriptorMangler?, KotlinMangler.IrMangler, FirMangler?, (KtSourceFile) -> ProtoBuf.PackageFragment) -> IrBackendInput override val artifactFactory: (IrModuleFragment, IrPluginContext, List<KotlinFileSerializedData>, BaseDiagnosticsCollector, Boolean, KotlinMangler.DescriptorMangler?, KotlinMangler.IrMangler, FirMangler?, KlibSingleFileMetadataSerializer<*>) -> IrBackendInput
get() = IrBackendInput::JsIrBackendInput get() = IrBackendInput::JsIrBackendInput
override fun resolveLibraries(module: TestModule, compilerConfiguration: CompilerConfiguration): List<KotlinResolvedLibrary> { override fun resolveLibraries(module: TestModule, compilerConfiguration: CompilerConfiguration): List<KotlinResolvedLibrary> {
@@ -114,7 +84,7 @@ class Fir2IrJsResultsConverter(testServices: TestServices) : Fir2IrJsWasmResults
class Fir2IrWasmResultsConverter(testServices: TestServices) : Fir2IrJsWasmResultsConverter(testServices) { class Fir2IrWasmResultsConverter(testServices: TestServices) : Fir2IrJsWasmResultsConverter(testServices) {
override val artifactFactory: (IrModuleFragment, IrPluginContext, List<KtSourceFile>, List<KotlinFileSerializedData>, BaseDiagnosticsCollector, Boolean, KotlinMangler.DescriptorMangler?, KotlinMangler.IrMangler, FirMangler?, (KtSourceFile) -> ProtoBuf.PackageFragment) -> IrBackendInput override val artifactFactory: (IrModuleFragment, IrPluginContext, List<KotlinFileSerializedData>, BaseDiagnosticsCollector, Boolean, KotlinMangler.DescriptorMangler?, KotlinMangler.IrMangler, FirMangler?, KlibSingleFileMetadataSerializer<*>) -> IrBackendInput
get() = IrBackendInput::WasmBackendInput get() = IrBackendInput::WasmBackendInput
override fun resolveLibraries(module: TestModule, compilerConfiguration: CompilerConfiguration): List<KotlinResolvedLibrary> { override fun resolveLibraries(module: TestModule, compilerConfiguration: CompilerConfiguration): List<KotlinResolvedLibrary> {
@@ -5,10 +5,7 @@
package org.jetbrains.kotlin.klib package org.jetbrains.kotlin.klib
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import junit.framework.TestCase import junit.framework.TestCase
import org.jetbrains.kotlin.KtPsiSourceFile
import org.jetbrains.kotlin.backend.common.CommonKLibResolver import org.jetbrains.kotlin.backend.common.CommonKLibResolver
import org.jetbrains.kotlin.backend.common.linkage.issues.checkNoUnboundSymbols import org.jetbrains.kotlin.backend.common.linkage.issues.checkNoUnboundSymbols
import org.jetbrains.kotlin.backend.common.linkage.partial.PartialLinkageSupportForLinker import org.jetbrains.kotlin.backend.common.linkage.partial.PartialLinkageSupportForLinker
@@ -18,11 +15,8 @@ import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.codegen.CodegenTestCase import org.jetbrains.kotlin.codegen.CodegenTestCase
import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.components.LookupTracker
@@ -34,7 +28,6 @@ import org.jetbrains.kotlin.ir.backend.js.KlibMetadataIncrementalSerializer
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrLinker import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrLinker
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerDesc import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerDesc
import org.jetbrains.kotlin.ir.backend.js.serializeModuleIntoKlib import org.jetbrains.kotlin.ir.backend.js.serializeModuleIntoKlib
import org.jetbrains.kotlin.ir.backend.js.serializeScope
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
@@ -45,17 +38,13 @@ import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS
import org.jetbrains.kotlin.library.KotlinAbiVersion import org.jetbrains.kotlin.library.KotlinAbiVersion
import org.jetbrains.kotlin.library.KotlinLibrary import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.library.impl.BuiltInsPlatform import org.jetbrains.kotlin.library.impl.BuiltInsPlatform
import org.jetbrains.kotlin.library.metadata.KlibMetadataVersion
import org.jetbrains.kotlin.library.metadata.resolver.TopologicalLibraryOrder import org.jetbrains.kotlin.library.metadata.resolver.TopologicalLibraryOrder
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
import org.jetbrains.kotlin.psi2ir.descriptors.IrBuiltInsOverDescriptors import org.jetbrains.kotlin.psi2ir.descriptors.IrBuiltInsOverDescriptors
import org.jetbrains.kotlin.psi2ir.generators.TypeTranslatorImpl import org.jetbrains.kotlin.psi2ir.generators.TypeTranslatorImpl
import org.jetbrains.kotlin.resolve.AnalyzingUtils import org.jetbrains.kotlin.resolve.AnalyzingUtils
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingContextUtils
import org.jetbrains.kotlin.resolve.CompilerEnvironment import org.jetbrains.kotlin.resolve.CompilerEnvironment
import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.test.ConfigurationKind import org.jetbrains.kotlin.test.ConfigurationKind
@@ -119,42 +108,25 @@ abstract class AbstractKlibIrTextTestCase : CodegenTestCase() {
} }
} }
private fun klibMetadataIncrementalSerializer(configuration: CompilerConfiguration, project: Project, allowErrors: Boolean) =
KlibMetadataIncrementalSerializer(
languageVersionSettings = configuration.languageVersionSettings,
metadataVersion = KlibMetadataVersion.INSTANCE,
project = project,
exportKDoc = false,
allowErrorTypes = allowErrors
)
private fun getDescriptorForElement(
context: BindingContext,
element: PsiElement
): DeclarationDescriptor = BindingContextUtils.getNotNull(context, BindingContext.DECLARATION_TO_DESCRIPTOR, element)
private fun KlibMetadataIncrementalSerializer.serializeScope(
ktFile: KtFile,
bindingContext: BindingContext,
moduleDescriptor: ModuleDescriptor
): ProtoBuf.PackageFragment {
val memberScope = ktFile.declarations.map { getDescriptorForElement(bindingContext, it) }
return serializePackageFragment(moduleDescriptor, memberScope, ktFile.packageFqName)
}
private fun serializeModule( private fun serializeModule(
irModuleFragment: IrModuleFragment, irModuleFragment: IrModuleFragment,
bindingContext: BindingContext, bindingContext: BindingContext,
stdlib: KotlinLibrary, stdlib: KotlinLibrary,
containsErrorCode: Boolean, containsErrorCode: Boolean,
): String { ): String {
val metadataSerializer = klibMetadataIncrementalSerializer(myEnvironment.configuration, myEnvironment.project, containsErrorCode)
val klibDir = org.jetbrains.kotlin.konan.file.createTempDir("testKlib") val klibDir = org.jetbrains.kotlin.konan.file.createTempDir("testKlib")
serializeModuleIntoKlib( serializeModuleIntoKlib(
moduleName = MODULE_NAME, moduleName = MODULE_NAME,
configuration = myEnvironment.configuration, configuration = myEnvironment.configuration,
diagnosticReporter = DiagnosticReporterFactory.createPendingReporter(), diagnosticReporter = DiagnosticReporterFactory.createPendingReporter(),
files = myFiles.psiFiles.map(::KtPsiSourceFile), metadataSerializer = KlibMetadataIncrementalSerializer(
files = myFiles.psiFiles,
configuration = myEnvironment.configuration,
project = myEnvironment.project,
bindingContext = bindingContext,
moduleDescriptor = irModuleFragment.descriptor,
allowErrorTypes = containsErrorCode
),
klibPath = klibDir.canonicalPath, klibPath = klibDir.canonicalPath,
dependencies = listOf(stdlib), dependencies = listOf(stdlib),
moduleFragment = irModuleFragment, moduleFragment = irModuleFragment,
@@ -165,7 +137,6 @@ abstract class AbstractKlibIrTextTestCase : CodegenTestCase() {
abiVersion = KotlinAbiVersion.CURRENT, abiVersion = KotlinAbiVersion.CURRENT,
jsOutputName = null, jsOutputName = null,
builtInsPlatform = BuiltInsPlatform.JS, builtInsPlatform = BuiltInsPlatform.JS,
serializeSingleFile = { metadataSerializer.serializeScope(it, bindingContext, irModuleFragment.descriptor) }
) )
return klibDir.canonicalPath return klibDir.canonicalPath
} }
@@ -74,9 +74,6 @@ class FilePathsInKlibTest : CodegenTestCase() {
module.getModuleDescriptor(it) module.getModuleDescriptor(it)
} }
val metadataSerializer =
KlibMetadataIncrementalSerializer(module.compilerConfiguration, module.project, module.jsFrontEndResult.hasErrors)
val diagnosticReporter = DiagnosticReporterFactory.createPendingReporter() val diagnosticReporter = DiagnosticReporterFactory.createPendingReporter()
generateKLib( generateKLib(
module, module,
@@ -85,10 +82,8 @@ class FilePathsInKlibTest : CodegenTestCase() {
jsOutputName = MODULE_NAME, jsOutputName = MODULE_NAME,
icData = icData, icData = icData,
moduleFragment = moduleFragment, moduleFragment = moduleFragment,
diagnosticReporter = diagnosticReporter diagnosticReporter = diagnosticReporter,
) { file -> )
metadataSerializer.serializeScope(file, module.jsFrontEndResult.bindingContext, moduleFragment.descriptor)
}
} }
private fun setupEnvironment(): CompilerConfiguration { private fun setupEnvironment(): CompilerConfiguration {
@@ -12,7 +12,6 @@ import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.psi.PsiManager import com.intellij.psi.PsiManager
import org.jetbrains.kotlin.ir.KtDiagnosticReporterWithImplicitIrBasedContext import org.jetbrains.kotlin.ir.KtDiagnosticReporterWithImplicitIrBasedContext
import org.jetbrains.kotlin.KtPsiSourceFile
import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.backend.common.linkage.issues.checkNoUnboundSymbols import org.jetbrains.kotlin.backend.common.linkage.issues.checkNoUnboundSymbols
import org.jetbrains.kotlin.backend.common.linkage.partial.PartialLinkageSupportForLinker import org.jetbrains.kotlin.backend.common.linkage.partial.PartialLinkageSupportForLinker
@@ -485,7 +484,6 @@ class GenerateIrRuntime {
return psi2IrTranslator.generateModuleFragment(psi2IrContext, files, irProviders, emptyList()) return psi2IrTranslator.generateModuleFragment(psi2IrContext, files, irProviders, emptyList())
} }
@OptIn(ExperimentalPathApi::class)
private fun doSerializeModule( private fun doSerializeModule(
moduleFragment: IrModuleFragment, moduleFragment: IrModuleFragment,
bindingContext: BindingContext, bindingContext: BindingContext,
@@ -494,12 +492,19 @@ class GenerateIrRuntime {
): String { ): String {
val diagnosticReporter = DiagnosticReporterFactory.createPendingReporter() val diagnosticReporter = DiagnosticReporterFactory.createPendingReporter()
val tmpKlibDir = createTempDirectory().also { it.toFile().deleteOnExit() }.toString() val tmpKlibDir = createTempDirectory().also { it.toFile().deleteOnExit() }.toString()
val metadataSerializer = KlibMetadataIncrementalSerializer(configuration, project, false) val metadataSerializer = KlibMetadataIncrementalSerializer(
files,
configuration,
project,
bindingContext,
moduleFragment.descriptor,
allowErrorTypes = false,
)
serializeModuleIntoKlib( serializeModuleIntoKlib(
moduleName, moduleName,
configuration, configuration,
diagnosticReporter, diagnosticReporter,
files.map(::KtPsiSourceFile), metadataSerializer,
tmpKlibDir, tmpKlibDir,
emptyList(), emptyList(),
moduleFragment, moduleFragment,
@@ -507,10 +512,8 @@ class GenerateIrRuntime {
true, true,
perFile, perFile,
abiVersion = KotlinAbiVersion.CURRENT, abiVersion = KotlinAbiVersion.CURRENT,
jsOutputName = null jsOutputName = null,
) { file -> )
metadataSerializer.serializeScope(file, bindingContext, moduleFragment.descriptor)
}
return tmpKlibDir return tmpKlibDir
} }
@@ -106,10 +106,6 @@ abstract class IrAbstractInvalidationTest(
) { ) {
sourceModule.getModuleDescriptor(it) sourceModule.getModuleDescriptor(it)
} }
val metadataSerializer =
KlibMetadataIncrementalSerializer(configuration, sourceModule.project, sourceModule.jsFrontEndResult.hasErrors)
val diagnosticReporter = DiagnosticReporterFactory.createPendingReporter()
generateKLib( generateKLib(
sourceModule, sourceModule,
outputKlibFile.canonicalPath, outputKlibFile.canonicalPath,
@@ -117,9 +113,7 @@ abstract class IrAbstractInvalidationTest(
jsOutputName = moduleName, jsOutputName = moduleName,
icData = icData, icData = icData,
moduleFragment = moduleFragment, moduleFragment = moduleFragment,
diagnosticReporter = diagnosticReporter diagnosticReporter = DiagnosticReporterFactory.createPendingReporter(),
) { file -> )
metadataSerializer.serializeScope(file, sourceModule.jsFrontEndResult.bindingContext, moduleFragment.descriptor)
}
} }
} }
@@ -61,7 +61,7 @@ class FirJsKlibBackendFacade(
configuration[CommonConfigurationKeys.MODULE_NAME]!!, configuration[CommonConfigurationKeys.MODULE_NAME]!!,
configuration, configuration,
inputArtifact.diagnosticReporter, inputArtifact.diagnosticReporter,
inputArtifact.sourceFiles, inputArtifact.metadataSerializer,
klibPath = outputFile, klibPath = outputFile,
libraries.map { it.library }, libraries.map { it.library },
inputArtifact.irModuleFragment, inputArtifact.irModuleFragment,
@@ -71,9 +71,7 @@ class FirJsKlibBackendFacade(
containsErrorCode = inputArtifact.hasErrors, containsErrorCode = inputArtifact.hasErrors,
abiVersion = KotlinAbiVersion.CURRENT, // TODO get from test file data abiVersion = KotlinAbiVersion.CURRENT, // TODO get from test file data
jsOutputName = null jsOutputName = null
) { )
inputArtifact.serializeSingleFile(it)
}
} }
// TODO: consider avoiding repeated libraries resolution // TODO: consider avoiding repeated libraries resolution
@@ -51,7 +51,7 @@ class JsKlibBackendFacade(
configuration[CommonConfigurationKeys.MODULE_NAME]!!, configuration[CommonConfigurationKeys.MODULE_NAME]!!,
configuration, configuration,
inputArtifact.diagnosticReporter, inputArtifact.diagnosticReporter,
inputArtifact.sourceFiles, inputArtifact.metadataSerializer,
klibPath = outputFile, klibPath = outputFile,
JsEnvironmentConfigurator.getAllRecursiveLibrariesFor(module, testServices).keys.toList(), JsEnvironmentConfigurator.getAllRecursiveLibrariesFor(module, testServices).keys.toList(),
inputArtifact.irModuleFragment, inputArtifact.irModuleFragment,
@@ -61,9 +61,7 @@ class JsKlibBackendFacade(
containsErrorCode = inputArtifact.hasErrors, containsErrorCode = inputArtifact.hasErrors,
abiVersion = KotlinAbiVersion.CURRENT, // TODO get from test file data abiVersion = KotlinAbiVersion.CURRENT, // TODO get from test file data
jsOutputName = null jsOutputName = null
) { )
inputArtifact.serializeSingleFile(it)
}
} }
val dependencies = JsEnvironmentConfigurator.getAllRecursiveDependenciesFor(module, testServices).toList() val dependencies = JsEnvironmentConfigurator.getAllRecursiveDependenciesFor(module, testServices).toList()
@@ -92,7 +92,7 @@ internal fun PhaseContext.fir2Ir(
val diagnosticsReporter = DiagnosticReporterFactory.createPendingReporter() val diagnosticsReporter = DiagnosticReporterFactory.createPendingReporter()
val fir2IrConfiguration = Fir2IrConfiguration.forKlibCompilation(configuration, diagnosticsReporter) val fir2IrConfiguration = Fir2IrConfiguration.forKlibCompilation(configuration, diagnosticsReporter)
val (irModuleFragment, components, pluginContext, irActualizedResult) = input.firResult.convertToIrAndActualize( val actualizedResult = input.firResult.convertToIrAndActualize(
NativeFir2IrExtensions, NativeFir2IrExtensions,
fir2IrConfiguration, fir2IrConfiguration,
IrGenerationExtension.getInstances(config.project), IrGenerationExtension.getInstances(config.project),
@@ -104,8 +104,8 @@ internal fun PhaseContext.fir2Ir(
).also { ).also {
(it.irModuleFragment.descriptor as? FirModuleDescriptor)?.let { it.allDependencyModules = librariesDescriptors } (it.irModuleFragment.descriptor as? FirModuleDescriptor)?.let { it.allDependencyModules = librariesDescriptors }
} }
assert(irModuleFragment.name.isSpecial) { assert(actualizedResult.irModuleFragment.name.isSpecial) {
"`${irModuleFragment.name}` must be Name.special, since it's required by KlibMetadataModuleDescriptorFactoryImpl.createDescriptorOptionalBuiltIns()" "`${actualizedResult.irModuleFragment.name}` must be Name.special, since it's required by KlibMetadataModuleDescriptorFactoryImpl.createDescriptorOptionalBuiltIns()"
} }
@OptIn(DelicateDeclarationStorageApi::class) @OptIn(DelicateDeclarationStorageApi::class)
@@ -116,8 +116,8 @@ internal fun PhaseContext.fir2Ir(
val fragment = (p.getPackageFragment() as? IrExternalPackageFragment) ?: return val fragment = (p.getPackageFragment() as? IrExternalPackageFragment) ?: return
add(fragment.packageFqName) add(fragment.packageFqName)
} }
components.declarationStorage.forEachCachedDeclarationSymbol(::addExternalPackage) actualizedResult.components.declarationStorage.forEachCachedDeclarationSymbol(::addExternalPackage)
components.classifierStorage.forEachCachedDeclarationSymbol(::addExternalPackage) actualizedResult.components.classifierStorage.forEachCachedDeclarationSymbol(::addExternalPackage)
// These packages exist in all platform libraries, but can contain only synthetic declarations. // 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. // 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) val renderDiagnosticNames = configuration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME)
FirDiagnosticsCompilerResultsReporter.reportToMessageCollector(diagnosticsReporter, messageCollector, renderDiagnosticNames) FirDiagnosticsCompilerResultsReporter.reportToMessageCollector(diagnosticsReporter, messageCollector, renderDiagnosticNames)
@@ -144,7 +144,7 @@ internal fun PhaseContext.fir2Ir(
throw KonanCompilationException("Compilation failed: there were some diagnostics during 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( 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.backend.konan.serialization.KonanIrModuleSerializer
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.fir.reportToMessageCollector 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.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.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.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.konan.library.KonanLibrary
import org.jetbrains.kotlin.library.metadata.resolver.TopologicalLibraryOrder import org.jetbrains.kotlin.library.metadata.resolver.TopologicalLibraryOrder
import org.jetbrains.kotlin.utils.toMetadataVersion
internal fun PhaseContext.firSerializer(input: FirOutput): SerializerOutput? = when (input) { internal fun PhaseContext.firSerializer(input: FirOutput): SerializerOutput? = when (input) {
!is FirOutput.Full -> null !is FirOutput.Full -> null
@@ -44,35 +33,26 @@ internal fun PhaseContext.firSerializerBase(
produceHeaderKlib: Boolean = false, produceHeaderKlib: Boolean = false,
): SerializerOutput { ): SerializerOutput {
val configuration = config.configuration 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 { val usedResolvedLibraries = fir2IrOutput?.let {
config.resolvedLibraries.getFullResolvedList(TopologicalLibraryOrder).filter { config.resolvedLibraries.getFullResolvedList(TopologicalLibraryOrder).filter {
(!it.isDefault && !configuration.getBoolean(KonanConfigKeys.PURGE_USER_LIBS)) || it in fir2IrOutput.usedLibraries (!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 diagnosticReporter = DiagnosticReporterFactory.createPendingReporter()
val serializerOutput = serializeModuleIntoKlib( val serializerOutput = serializeModuleIntoKlib(
moduleName = fir2IrOutput?.irModuleFragment?.descriptor?.name?.asString() moduleName = irModuleFragment?.name?.asString() ?: firResult.outputs.last().session.moduleData.name.asString(),
?: firResult.outputs.last().session.moduleData.name.asString(), irModuleFragment = irModuleFragment,
irModuleFragment = fir2IrOutput?.irModuleFragment,
configuration = configuration, configuration = configuration,
diagnosticReporter = diagnosticReporter, diagnosticReporter = diagnosticReporter,
sourceFiles = sourceFiles, metadataSerializer = Fir2KlibMetadataSerializer(
configuration,
firResult.outputs,
fir2IrOutput?.fir2irActualizedResult,
exportKDoc = shouldExportKDoc(),
produceHeaderKlib = produceHeaderKlib,
),
compatibilityMode = CompatibilityMode.CURRENT, compatibilityMode = CompatibilityMode.CURRENT,
cleanFiles = emptyList(), cleanFiles = emptyList(),
dependencies = usedResolvedLibraries?.map { it.library as KonanLibrary }.orEmpty(), dependencies = usedResolvedLibraries?.map { it.library as KonanLibrary }.orEmpty(),
@@ -95,30 +75,6 @@ internal fun PhaseContext.firSerializerBase(
shouldCheckSignaturesOnUniqueness = shouldCheckSignaturesOnUniqueness, 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) val renderDiagnosticNames = configuration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME)
diagnosticReporter.reportToMessageCollector(messageCollector, renderDiagnosticNames) diagnosticReporter.reportToMessageCollector(messageCollector, renderDiagnosticNames)
@@ -51,7 +51,7 @@ internal val K2SpecialBackendChecksPhase = createSimpleNamedCompilerPhase<PhaseC
"SpecialBackendChecks", "SpecialBackendChecks",
"Special backend checks", "Special backend checks",
) { context, input -> ) { context, input ->
val moduleFragment = input.irModuleFragment val moduleFragment = input.fir2irActualizedResult.irModuleFragment
SpecialBackendChecksTraversal( SpecialBackendChecksTraversal(
context, context,
input.symbols, 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.backend.konan.ir.KonanSymbols
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
import org.jetbrains.kotlin.fir.backend.Fir2IrPluginContext 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.fir.pipeline.FirResult
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary
@@ -20,10 +21,7 @@ import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary
internal data class Fir2IrOutput( internal data class Fir2IrOutput(
val firResult: FirResult, val firResult: FirResult,
val symbols: KonanSymbols, val symbols: KonanSymbols,
val irModuleFragment: IrModuleFragment, val fir2irActualizedResult: Fir2IrActualizedResult,
val components: Fir2IrComponents,
val pluginContext: Fir2IrPluginContext,
val irActualizedResult: IrActualizedResult?,
val usedLibraries: Set<KotlinResolvedLibrary> val usedLibraries: Set<KotlinResolvedLibrary>
) )
@@ -5,17 +5,15 @@
package org.jetbrains.kotlin.konan.test package org.jetbrains.kotlin.konan.test
import org.jetbrains.kotlin.KtSourceFile
import org.jetbrains.kotlin.backend.common.serialization.metadata.DynamicTypeDeserializer import org.jetbrains.kotlin.backend.common.serialization.metadata.DynamicTypeDeserializer
import org.jetbrains.kotlin.backend.konan.serialization.KonanManglerIr import org.jetbrains.kotlin.backend.konan.serialization.KonanManglerIr
import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.diagnostics.impl.BaseDiagnosticsCollector import org.jetbrains.kotlin.diagnostics.impl.BaseDiagnosticsCollector
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
import org.jetbrains.kotlin.fir.backend.FirMangler import org.jetbrains.kotlin.fir.backend.FirMangler
import org.jetbrains.kotlin.fir.backend.native.FirNativeKotlinMangler import org.jetbrains.kotlin.fir.backend.native.FirNativeKotlinMangler
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.pipeline.Fir2IrActualizedResult import org.jetbrains.kotlin.fir.pipeline.Fir2IrActualizedResult
import org.jetbrains.kotlin.fir.pipeline.Fir2KlibMetadataSerializer
import org.jetbrains.kotlin.ir.util.KotlinMangler import org.jetbrains.kotlin.ir.util.KotlinMangler
import org.jetbrains.kotlin.library.metadata.KlibMetadataFactories import org.jetbrains.kotlin.library.metadata.KlibMetadataFactories
import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary
@@ -48,8 +46,7 @@ class Fir2IrNativeResultsConverter(testServices: TestServices) : AbstractFir2IrN
diagnosticReporter: BaseDiagnosticsCollector, diagnosticReporter: BaseDiagnosticsCollector,
inputArtifact: FirOutputArtifact, inputArtifact: FirOutputArtifact,
fir2IrResult: Fir2IrActualizedResult, fir2IrResult: Fir2IrActualizedResult,
firFilesAndComponentsBySourceFile: Map<KtSourceFile, Pair<FirFile, Fir2IrComponents>>, fir2KlibMetadataSerializer: Fir2KlibMetadataSerializer,
sourceFiles: List<KtSourceFile>,
): IrBackendInput { ): IrBackendInput {
val fir2IrComponents = fir2IrResult.components val fir2IrComponents = fir2IrResult.components
val manglers = fir2IrComponents.manglers val manglers = fir2IrComponents.manglers
@@ -61,7 +61,7 @@ class FirWasmKlibBackendFacade(
configuration[CommonConfigurationKeys.MODULE_NAME]!!, configuration[CommonConfigurationKeys.MODULE_NAME]!!,
configuration, configuration,
inputArtifact.diagnosticReporter, inputArtifact.diagnosticReporter,
inputArtifact.sourceFiles, inputArtifact.metadataSerializer,
klibPath = outputFile, klibPath = outputFile,
libraries.map { it.library }, libraries.map { it.library },
inputArtifact.irModuleFragment, inputArtifact.irModuleFragment,
@@ -71,9 +71,7 @@ class FirWasmKlibBackendFacade(
containsErrorCode = inputArtifact.hasErrors, containsErrorCode = inputArtifact.hasErrors,
abiVersion = KotlinAbiVersion.CURRENT, // TODO get from test file data abiVersion = KotlinAbiVersion.CURRENT, // TODO get from test file data
jsOutputName = null jsOutputName = null
) { )
inputArtifact.serializeSingleFile(it)
}
} }
// TODO: consider avoiding repeated libraries resolution // TODO: consider avoiding repeated libraries resolution