[Test] Unify all fir2ir facades for non-jvm platforms

Setup of fir2ir for JS, Native and Wasm is very similar, so it makes
  sense to extract all common parts of it into common base facade
This commit is contained in:
Dmitriy Novozhilov
2023-11-21 12:50:28 +02:00
committed by Space Team
parent e38b25c278
commit 06af6adf4f
8 changed files with 275 additions and 386 deletions
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.ir.IrLock
import org.jetbrains.kotlin.ir.declarations.IrFactory
import org.jetbrains.kotlin.ir.linkage.IrProvider
import org.jetbrains.kotlin.ir.overrides.IrFakeOverrideBuilder
import org.jetbrains.kotlin.ir.util.KotlinMangler
import org.jetbrains.kotlin.ir.util.SymbolTable
interface Fir2IrComponents {
@@ -31,6 +32,8 @@ interface Fir2IrComponents {
val symbolTable: SymbolTable
val irBuiltIns: IrBuiltInsOverFir
val builtIns: Fir2IrBuiltIns
val manglers: Manglers
val irFactory: IrFactory
val irProviders: List<IrProvider>
val lock: IrLock
@@ -56,4 +59,10 @@ interface Fir2IrComponents {
val configuration: Fir2IrConfiguration
val annotationsFromPluginRegistrar: Fir2IrAnnotationsFromPluginRegistrar
interface Manglers {
val descriptorMangler: KotlinMangler.DescriptorMangler
val irMangler: KotlinMangler.IrMangler
val firMangler: FirMangler
}
}
@@ -68,4 +68,15 @@ class Fir2IrComponentsStorage(
override val lock: IrLock
get() = symbolTable.lock
override val manglers: Fir2IrComponents.Manglers = object : Fir2IrComponents.Manglers {
override val descriptorMangler: KotlinMangler.DescriptorMangler
get() = symbolTable.signaturer.mangler
override val irMangler: KotlinMangler.IrMangler
get() = irMangler
override val firMangler: FirMangler
get() = commonMemberStorage.firSignatureComposer.mangler
}
}
@@ -11,28 +11,25 @@ import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureDe
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
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.constant.EvaluatedConstTracker
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
import org.jetbrains.kotlin.diagnostics.impl.BaseDiagnosticsCollector
import org.jetbrains.kotlin.fir.backend.*
import org.jetbrains.kotlin.fir.backend.js.FirJsKotlinMangler
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
import org.jetbrains.kotlin.fir.pipeline.Fir2IrActualizedResult
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.fir.serialization.FirKLibSerializerExtension
import org.jetbrains.kotlin.fir.serialization.serializeSingleFirFile
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.ir.backend.js.JsFactories
import org.jetbrains.kotlin.ir.backend.js.getSerializedData
import org.jetbrains.kotlin.ir.backend.js.incrementalDataProvider
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerDesc
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerIr
import org.jetbrains.kotlin.ir.types.IrTypeSystemContextImpl
import org.jetbrains.kotlin.ir.util.KotlinMangler
import org.jetbrains.kotlin.library.metadata.KlibMetadataFactories
import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary
import org.jetbrains.kotlin.library.unresolvedDependencies
import org.jetbrains.kotlin.storage.LockBasedStorageManager
@@ -47,15 +44,20 @@ import org.jetbrains.kotlin.test.services.compilerConfigurationProvider
import org.jetbrains.kotlin.test.services.libraryProvider
import org.jetbrains.kotlin.utils.metadataVersion
class Fir2IrJsResultsConverter(
abstract class AbstractFir2IrNonJvmResultsConverter(
testServices: TestServices
) : Frontend2BackendConverter<FirOutputArtifact, IrBackendInput>(
testServices,
FrontendKinds.FIR,
BackendKinds.IrBackend
) {
protected abstract fun createDescriptorMangler(): KotlinMangler.DescriptorMangler
protected abstract fun createIrMangler(): KotlinMangler.IrMangler
protected abstract fun createFirMangler(): FirMangler
protected abstract fun resolveLibraries(module: TestModule, compilerConfiguration: CompilerConfiguration): List<KotlinResolvedLibrary>
protected abstract val klibFactories: KlibMetadataFactories
override fun transform(module: TestModule, inputArtifact: FirOutputArtifact): IrBackendInput? =
final override fun transform(module: TestModule, inputArtifact: FirOutputArtifact): IrBackendInput? =
try {
transformInternal(module, inputArtifact)
} catch (e: Throwable) {
@@ -66,21 +68,12 @@ class Fir2IrJsResultsConverter(
}
}
private fun transformInternal(
private fun createFir2IrConfiguration(
module: TestModule,
inputArtifact: FirOutputArtifact
): IrBackendInput {
val configuration = testServices.compilerConfigurationProvider.getCompilerConfiguration(module)
val sourceFiles = mutableListOf<KtSourceFile>()
val firFilesAndComponentsBySourceFile = mutableMapOf<KtSourceFile, Pair<FirFile, Fir2IrComponents>>()
val irMangler = JsManglerIr
val diagnosticReporter = DiagnosticReporterFactory.createReporter()
val libraries = resolveLibraries(configuration, getAllJsDependenciesPaths(module, testServices))
val (dependencies, builtIns) = loadResolvedLibraries(libraries, configuration.languageVersionSettings, testServices)
val fir2IrConfiguration = Fir2IrConfiguration(
configuration: CompilerConfiguration,
diagnosticReporter: BaseDiagnosticsCollector
): Fir2IrConfiguration {
return Fir2IrConfiguration(
languageVersionSettings = configuration.languageVersionSettings,
diagnosticReporter = diagnosticReporter,
linkViaSignatures = true,
@@ -91,14 +84,30 @@ class Fir2IrJsResultsConverter(
allowNonCachedDeclarations = false,
useIrFakeOverrideBuilder = module.shouldUseIrFakeOverrideBuilderInConvertToIr()
)
}
private fun transformInternal(
module: TestModule,
inputArtifact: FirOutputArtifact
): IrBackendInput {
val compilerConfiguration = testServices.compilerConfigurationProvider.getCompilerConfiguration(module)
val sourceFiles = mutableListOf<KtSourceFile>()
val firFilesAndComponentsBySourceFile = mutableMapOf<KtSourceFile, Pair<FirFile, Fir2IrComponents>>()
val irMangler = createIrMangler()
val diagnosticReporter = DiagnosticReporterFactory.createReporter()
val libraries = resolveLibraries(module, compilerConfiguration)
val (dependencies, builtIns) = loadResolvedLibraries(libraries, compilerConfiguration.languageVersionSettings, testServices)
val fir2IrConfiguration = createFir2IrConfiguration(module, compilerConfiguration, diagnosticReporter)
val fir2irResult = inputArtifact.toFirResult().convertToIrAndActualize(
Fir2IrExtensions.Default,
fir2IrConfiguration,
module.irGenerationExtensions(testServices),
IdSignatureDescriptor(JsManglerDesc),
JsManglerIr,
FirJsKotlinMangler(),
IdSignatureDescriptor(createDescriptorMangler()),
irMangler,
createFirMangler(),
Fir2IrVisibilityConverter.Default,
builtIns ?: DefaultBuiltIns.Instance, // TODO: consider passing externally,
::IrTypeSystemContextImpl
@@ -111,71 +120,52 @@ class Fir2IrJsResultsConverter(
(it.irModuleFragment.descriptor as? FirModuleDescriptor)?.let { it.allDependencyModules = dependencies }
}
val metadataVersion = configuration.metadataVersion(module.languageVersionSettings.languageVersion)
return createBackendInput(compilerConfiguration, diagnosticReporter, inputArtifact, fir2irResult, firFilesAndComponentsBySourceFile, sourceFiles)
}
return IrBackendInput.JsIrBackendInput(
fir2irResult.irModuleFragment,
fir2irResult.pluginContext,
sourceFiles,
configuration.incrementalDataProvider?.getSerializedData(sourceFiles) ?: emptyList(),
diagnosticReporter = diagnosticReporter,
hasErrors = inputArtifact.hasErrors,
descriptorMangler = fir2irResult.components.symbolTable.signaturer.mangler,
irMangler = irMangler,
firMangler = fir2irResult.components.signatureComposer.mangler,
) { file ->
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, metadataVersion,
ConstValueProviderImpl(components),
allowErrorTypes = false, exportKDoc = false,
components.annotationsFromPluginRegistrar.createMetadataAnnotationsProvider()
),
configuration.languageVersionSettings,
)
}
protected abstract fun createBackendInput(
compilerConfiguration: CompilerConfiguration,
diagnosticReporter: BaseDiagnosticsCollector,
inputArtifact: FirOutputArtifact,
fir2IrResult: Fir2IrActualizedResult,
firFilesAndComponentsBySourceFile: Map<KtSourceFile, Pair<FirFile, Fir2IrComponents>>,
sourceFiles: List<KtSourceFile>
): IrBackendInput
private fun loadResolvedLibraries(
resolvedLibraries: List<KotlinResolvedLibrary>,
languageVersionSettings: LanguageVersionSettings,
testServices: TestServices
): Pair<List<ModuleDescriptor>, KotlinBuiltIns?> {
var builtInsModule: KotlinBuiltIns? = null
val dependencies = mutableListOf<ModuleDescriptorImpl>()
return resolvedLibraries.map { resolvedLibrary ->
testServices.libraryProvider.getOrCreateStdlibByPath(resolvedLibrary.library.libraryFile.absolutePath) {
// TODO: check safety of the approach of creating a separate storage manager per library
val storageManager = LockBasedStorageManager("ModulesStructure")
val moduleDescriptor = klibFactories.DefaultDeserializedDescriptorFactory.createDescriptorOptionalBuiltIns(
resolvedLibrary.library,
languageVersionSettings,
storageManager,
builtInsModule,
packageAccessHandler = null,
lookupTracker = LookupTracker.DO_NOTHING
)
dependencies += moduleDescriptor
moduleDescriptor.setDependencies(ArrayList(dependencies))
Pair(moduleDescriptor, resolvedLibrary.library)
}.also {
val isBuiltIns = resolvedLibrary.library.unresolvedDependencies.isEmpty()
if (isBuiltIns) builtInsModule = it.builtIns
}
} to builtInsModule
}
}
private fun loadResolvedLibraries(
resolvedLibraries: List<KotlinResolvedLibrary>,
languageVersionSettings: LanguageVersionSettings,
testServices: TestServices
): Pair<List<ModuleDescriptor>, KotlinBuiltIns?> {
var builtInsModule: KotlinBuiltIns? = null
val dependencies = mutableListOf<ModuleDescriptorImpl>()
return resolvedLibraries.map { resolvedLibrary ->
testServices.libraryProvider.getOrCreateStdlibByPath(resolvedLibrary.library.libraryFile.absolutePath) {
// TODO: check safety of the approach of creating a separate storage manager per library
val storageManager = LockBasedStorageManager("ModulesStructure")
val moduleDescriptor = JsFactories.DefaultDeserializedDescriptorFactory.createDescriptorOptionalBuiltIns(
resolvedLibrary.library,
languageVersionSettings,
storageManager,
builtInsModule,
packageAccessHandler = null,
lookupTracker = LookupTracker.DO_NOTHING
)
dependencies += moduleDescriptor
moduleDescriptor.setDependencies(ArrayList(dependencies))
Pair(moduleDescriptor, resolvedLibrary.library)
}.also {
val isBuiltIns = resolvedLibrary.library.unresolvedDependencies.isEmpty()
if (isBuiltIns) builtInsModule = it.builtIns
}
} to builtInsModule
}
// TODO: move somewhere
fun TestModule.irGenerationExtensions(testServices: TestServices): Collection<IrGenerationExtension> {
return IrGenerationExtension.getInstances(testServices.compilerConfigurationProvider.getProject(this))
}
@@ -0,0 +1,127 @@
/*
* Copyright 2010-2020 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.test.frontend.fir
import org.jetbrains.kotlin.KtSourceFile
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.languageVersionSettings
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.extractFirDeclarations
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.serialization.FirKLibSerializerExtension
import org.jetbrains.kotlin.fir.serialization.serializeSingleFirFile
import org.jetbrains.kotlin.ir.backend.js.JsFactories
import org.jetbrains.kotlin.ir.backend.js.KotlinFileSerializedData
import org.jetbrains.kotlin.ir.backend.js.getSerializedData
import org.jetbrains.kotlin.ir.backend.js.incrementalDataProvider
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerDesc
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerIr
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.util.KotlinMangler
import org.jetbrains.kotlin.library.metadata.KlibMetadataFactories
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.model.TestModule
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.utils.metadataVersion
abstract class Fir2IrJsWasmResultsConverter(testServices: TestServices) : AbstractFir2IrNonJvmResultsConverter(testServices) {
protected abstract val artifactFactory: (
IrModuleFragment,
IrPluginContext,
List<KtSourceFile>,
List<KotlinFileSerializedData>,
BaseDiagnosticsCollector,
Boolean,
KotlinMangler.DescriptorMangler,
KotlinMangler.IrMangler,
FirMangler?,
(KtSourceFile) -> ProtoBuf.PackageFragment
) -> IrBackendInput
override fun createDescriptorMangler(): KotlinMangler.DescriptorMangler {
return JsManglerDesc
}
override fun createIrMangler(): KotlinMangler.IrMangler {
return JsManglerIr
}
override fun createFirMangler(): FirMangler {
return FirJsKotlinMangler()
}
override val klibFactories: KlibMetadataFactories
get() = JsFactories
override fun createBackendInput(
compilerConfiguration: CompilerConfiguration,
diagnosticReporter: BaseDiagnosticsCollector,
inputArtifact: FirOutputArtifact,
fir2IrResult: Fir2IrActualizedResult,
firFilesAndComponentsBySourceFile: Map<KtSourceFile, Pair<FirFile, Fir2IrComponents>>,
sourceFiles: List<KtSourceFile>,
): IrBackendInput {
val languageVersionSettings = compilerConfiguration.languageVersionSettings
val metadataVersion = compilerConfiguration.metadataVersion(languageVersionSettings.languageVersion)
val fir2IrComponents = fir2IrResult.components
val manglers = fir2IrComponents.manglers
return artifactFactory(
fir2IrResult.irModuleFragment,
fir2IrResult.pluginContext,
sourceFiles,
compilerConfiguration.incrementalDataProvider?.getSerializedData(sourceFiles) ?: emptyList(),
diagnosticReporter,
inputArtifact.hasErrors,
manglers.descriptorMangler,
manglers.irMangler,
manglers.firMangler,
) { file ->
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, metadataVersion,
ConstValueProviderImpl(components),
allowErrorTypes = false, exportKDoc = false,
components.annotationsFromPluginRegistrar.createMetadataAnnotationsProvider()
),
languageVersionSettings,
)
}
}
}
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
get() = IrBackendInput::JsIrBackendInput
override fun resolveLibraries(module: TestModule, compilerConfiguration: CompilerConfiguration): List<KotlinResolvedLibrary> {
return resolveLibraries(compilerConfiguration, getAllJsDependenciesPaths(module, 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
get() = IrBackendInput::WasmBackendInput
override fun resolveLibraries(module: TestModule, compilerConfiguration: CompilerConfiguration): List<KotlinResolvedLibrary> {
return resolveWasmLibraries(module, testServices, compilerConfiguration)
}
}
@@ -21,9 +21,10 @@ import org.jetbrains.kotlin.test.services.TestServices
* In multi-platform projects this option is passed to IrActualizer instead
* @see [IrActualizerAndPluginsFacade]
*/
fun TestModule.shouldUseIrFakeOverrideBuilderInConvertToIr() =
CodegenTestDirectives.ENABLE_IR_FAKE_OVERRIDE_GENERATION in directives &&
fun TestModule.shouldUseIrFakeOverrideBuilderInConvertToIr(): Boolean {
return CodegenTestDirectives.ENABLE_IR_FAKE_OVERRIDE_GENERATION in directives &&
!languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects)
}
class Fir2IrResultsConverter(
testServices: TestServices
@@ -1,178 +0,0 @@
/*
* Copyright 2010-2020 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.test.frontend.fir
import org.jetbrains.kotlin.KtSourceFile
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureDescriptor
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.constant.EvaluatedConstTracker
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
import org.jetbrains.kotlin.fir.backend.*
import org.jetbrains.kotlin.fir.backend.js.FirJsKotlinMangler
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
import org.jetbrains.kotlin.fir.pipeline.convertToIrAndActualize
import org.jetbrains.kotlin.fir.serialization.FirKLibSerializerExtension
import org.jetbrains.kotlin.fir.serialization.serializeSingleFirFile
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.ir.backend.js.JsFactories
import org.jetbrains.kotlin.ir.backend.js.getSerializedData
import org.jetbrains.kotlin.ir.backend.js.incrementalDataProvider
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerDesc
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerIr
import org.jetbrains.kotlin.ir.types.IrTypeSystemContextImpl
import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary
import org.jetbrains.kotlin.library.unresolvedDependencies
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.test.backend.ir.IrBackendInput
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives
import org.jetbrains.kotlin.test.model.BackendKinds
import org.jetbrains.kotlin.test.model.Frontend2BackendConverter
import org.jetbrains.kotlin.test.model.FrontendKinds
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.compilerConfigurationProvider
import org.jetbrains.kotlin.test.services.libraryProvider
import org.jetbrains.kotlin.utils.metadataVersion
class Fir2IrWasmResultsConverter(
testServices: TestServices
) : Frontend2BackendConverter<FirOutputArtifact, IrBackendInput>(
testServices,
FrontendKinds.FIR,
BackendKinds.IrBackend
) {
override fun transform(module: TestModule, inputArtifact: FirOutputArtifact): IrBackendInput? =
try {
transformInternal(module, inputArtifact)
} catch (e: Throwable) {
if (CodegenTestDirectives.IGNORE_FIR2IR_EXCEPTIONS_IF_FIR_CONTAINS_ERRORS in module.directives && inputArtifact.hasErrors) {
null
} else {
throw e
}
}
private fun transformInternal(
module: TestModule,
inputArtifact: FirOutputArtifact
): IrBackendInput {
val configuration = testServices.compilerConfigurationProvider.getCompilerConfiguration(module)
val sourceFiles = mutableListOf<KtSourceFile>()
val firFilesAndComponentsBySourceFile = mutableMapOf<KtSourceFile, Pair<FirFile, Fir2IrComponents>>()
val diagnosticReporter = DiagnosticReporterFactory.createReporter()
// TODO: consider avoiding repeated libraries resolution
val libraries = resolveWasmLibraries(module, testServices, configuration)
val (dependencies, builtIns) = loadResolvedLibraries(libraries, configuration.languageVersionSettings, testServices)
val fir2IrConfiguration = Fir2IrConfiguration(
languageVersionSettings = configuration.languageVersionSettings,
diagnosticReporter = diagnosticReporter,
linkViaSignatures = true,
evaluatedConstTracker = configuration
.putIfAbsent(CommonConfigurationKeys.EVALUATED_CONST_TRACKER, EvaluatedConstTracker.create()),
inlineConstTracker = null,
expectActualTracker = configuration[CommonConfigurationKeys.EXPECT_ACTUAL_TRACKER],
allowNonCachedDeclarations = false,
useIrFakeOverrideBuilder = module.shouldUseIrFakeOverrideBuilderInConvertToIr(),
)
val fir2irResult = inputArtifact.toFirResult().convertToIrAndActualize(
Fir2IrExtensions.Default,
fir2IrConfiguration,
module.irGenerationExtensions(testServices),
IdSignatureDescriptor(JsManglerDesc),
JsManglerIr,
FirJsKotlinMangler(),
Fir2IrVisibilityConverter.Default,
builtIns ?: DefaultBuiltIns.Instance, // TODO: consider passing externally,
::IrTypeSystemContextImpl
) { firPart, irPart ->
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 }
}
val commonMemberStorage = Fir2IrCommonMemberStorage(IdSignatureDescriptor(JsManglerDesc), FirJsKotlinMangler())
val metadataVersion = configuration.metadataVersion(module.languageVersionSettings.languageVersion)
return IrBackendInput.WasmBackendInput(
fir2irResult.irModuleFragment,
fir2irResult.pluginContext,
sourceFiles,
configuration.incrementalDataProvider?.getSerializedData(sourceFiles) ?: emptyList(),
diagnosticReporter = diagnosticReporter,
hasErrors = inputArtifact.hasErrors,
descriptorMangler = commonMemberStorage.symbolTable.signaturer.mangler,
irMangler = JsManglerIr,
firMangler = commonMemberStorage.firSignatureComposer.mangler,
) { file ->
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, metadataVersion,
ConstValueProviderImpl(components),
allowErrorTypes = false, exportKDoc = false,
additionalAnnotationsProvider = null,
),
configuration.languageVersionSettings,
)
}
}
}
private fun loadResolvedLibraries(
resolvedLibraries: List<KotlinResolvedLibrary>,
languageVersionSettings: LanguageVersionSettings,
testServices: TestServices
): Pair<List<ModuleDescriptor>, KotlinBuiltIns?> {
var builtInsModule: KotlinBuiltIns? = null
val dependencies = mutableListOf<ModuleDescriptorImpl>()
return resolvedLibraries.map { resolvedLibrary ->
testServices.libraryProvider.getOrCreateStdlibByPath(resolvedLibrary.library.libraryFile.absolutePath) {
// TODO: check safety of the approach of creating a separate storage manager per library
val storageManager = LockBasedStorageManager("ModulesStructure")
val moduleDescriptor = JsFactories.DefaultDeserializedDescriptorFactory.createDescriptorOptionalBuiltIns(
resolvedLibrary.library,
languageVersionSettings,
storageManager,
builtInsModule,
packageAccessHandler = null,
lookupTracker = LookupTracker.DO_NOTHING
)
dependencies += moduleDescriptor
moduleDescriptor.setDependencies(ArrayList(dependencies))
Pair(moduleDescriptor, resolvedLibrary.library)
}.also {
val isBuiltIns = resolvedLibrary.library.unresolvedDependencies.isEmpty()
if (isBuiltIns) builtInsModule = it.builtIns
}
} to builtInsModule
}
@@ -65,5 +65,6 @@ object TestFirJsSessionFactory {
)
}
fun getAllJsDependenciesPaths(module: TestModule, testServices: TestServices) =
JsEnvironmentConfigurator.getRuntimePathsForModule(module, testServices) + getTransitivesAndFriendsPaths(module, testServices)
fun getAllJsDependenciesPaths(module: TestModule, testServices: TestServices): List<String> {
return JsEnvironmentConfigurator.getRuntimePathsForModule(module, testServices) + getTransitivesAndFriendsPaths(module, testServices)
}
@@ -5,138 +5,66 @@
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.signature.IdSignatureDescriptor
import org.jetbrains.kotlin.backend.konan.serialization.KonanManglerDesc
import org.jetbrains.kotlin.backend.konan.serialization.KonanManglerIr
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.constant.EvaluatedConstTracker
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
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.config.CompilerConfiguration
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.native.FirNativeKotlinMangler
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
import org.jetbrains.kotlin.fir.pipeline.convertToIrAndActualize
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.ir.types.IrTypeSystemContextImpl
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.pipeline.Fir2IrActualizedResult
import org.jetbrains.kotlin.ir.util.KotlinMangler
import org.jetbrains.kotlin.library.metadata.KlibMetadataFactories
import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary
import org.jetbrains.kotlin.library.unresolvedDependencies
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.test.backend.ir.IrBackendInput
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives
import org.jetbrains.kotlin.test.frontend.fir.*
import org.jetbrains.kotlin.test.model.BackendKinds
import org.jetbrains.kotlin.test.model.Frontend2BackendConverter
import org.jetbrains.kotlin.test.model.FrontendKinds
import org.jetbrains.kotlin.test.frontend.fir.AbstractFir2IrNonJvmResultsConverter
import org.jetbrains.kotlin.test.frontend.fir.FirOutputArtifact
import org.jetbrains.kotlin.test.frontend.fir.getAllNativeDependenciesPaths
import org.jetbrains.kotlin.test.frontend.fir.resolveLibraries
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.compilerConfigurationProvider
import org.jetbrains.kotlin.test.services.libraryProvider
class Fir2IrNativeResultsConverter(
testServices: TestServices
) : Frontend2BackendConverter<FirOutputArtifact, IrBackendInput>(
testServices,
FrontendKinds.FIR,
BackendKinds.IrBackend
) {
class Fir2IrNativeResultsConverter(testServices: TestServices) : AbstractFir2IrNonJvmResultsConverter(testServices) {
override fun transform(module: TestModule, inputArtifact: FirOutputArtifact): IrBackendInput? =
try {
transformInternal(module, inputArtifact)
} catch (e: Throwable) {
if (CodegenTestDirectives.IGNORE_FIR2IR_EXCEPTIONS_IF_FIR_CONTAINS_ERRORS in module.directives && inputArtifact.hasErrors) {
null
} else {
throw e
}
}
override fun createDescriptorMangler(): KotlinMangler.DescriptorMangler {
return KonanManglerDesc
}
private fun transformInternal(
module: TestModule,
inputArtifact: FirOutputArtifact
override fun createIrMangler(): KotlinMangler.IrMangler {
return KonanManglerIr
}
override fun createFirMangler(): FirMangler {
return FirNativeKotlinMangler
}
override fun resolveLibraries(module: TestModule, compilerConfiguration: CompilerConfiguration): List<KotlinResolvedLibrary> {
return resolveLibraries(compilerConfiguration, getAllNativeDependenciesPaths(module, testServices))
}
override val klibFactories: KlibMetadataFactories = KlibMetadataFactories(::KonanBuiltIns, DynamicTypeDeserializer)
override fun createBackendInput(
compilerConfiguration: CompilerConfiguration,
diagnosticReporter: BaseDiagnosticsCollector,
inputArtifact: FirOutputArtifact,
fir2IrResult: Fir2IrActualizedResult,
firFilesAndComponentsBySourceFile: Map<KtSourceFile, Pair<FirFile, Fir2IrComponents>>,
sourceFiles: List<KtSourceFile>,
): IrBackendInput {
val configuration = testServices.compilerConfigurationProvider.getCompilerConfiguration(module)
val libraries = resolveLibraries(configuration, getAllNativeDependenciesPaths(module, testServices))
val (dependencies, builtIns) = loadResolvedLibraries(libraries, configuration.languageVersionSettings, testServices)
val diagnosticReporter = DiagnosticReporterFactory.createReporter()
val fir2IrConfiguration = Fir2IrConfiguration(
languageVersionSettings = configuration.languageVersionSettings,
diagnosticReporter = diagnosticReporter,
linkViaSignatures = true,
evaluatedConstTracker = configuration
.putIfAbsent(CommonConfigurationKeys.EVALUATED_CONST_TRACKER, EvaluatedConstTracker.create()),
inlineConstTracker = null,
allowNonCachedDeclarations = false,
expectActualTracker = configuration[CommonConfigurationKeys.EXPECT_ACTUAL_TRACKER],
useIrFakeOverrideBuilder = configuration.getBoolean(CommonConfigurationKeys.USE_IR_FAKE_OVERRIDE_BUILDER),
)
val fir2irResult = inputArtifact.toFirResult().convertToIrAndActualize(
Fir2IrExtensions.Default,
fir2IrConfiguration,
module.irGenerationExtensions(testServices),
IdSignatureDescriptor(KonanManglerDesc),
KonanManglerIr,
FirNativeKotlinMangler,
Fir2IrVisibilityConverter.Default,
builtIns ?: DefaultBuiltIns.Instance, // TODO: consider passing externally,
::IrTypeSystemContextImpl
).also {
(it.irModuleFragment.descriptor as? FirModuleDescriptor)?.let { it.allDependencyModules = dependencies }
}
val fir2IrComponents = fir2IrResult.components
val manglers = fir2IrComponents.manglers
return IrBackendInput.NativeBackendInput(
fir2irResult.irModuleFragment,
fir2irResult.pluginContext,
fir2IrResult.irModuleFragment,
fir2IrResult.pluginContext,
diagnosticReporter = diagnosticReporter,
descriptorMangler = fir2irResult.components.symbolTable.signaturer.mangler,
irMangler = KonanManglerIr,
firMangler = fir2irResult.components.signatureComposer.mangler,
descriptorMangler = manglers.descriptorMangler,
irMangler = manglers.irMangler,
firMangler = manglers.firMangler,
)
}
}
internal val KlibFactories = KlibMetadataFactories(::KonanBuiltIns, DynamicTypeDeserializer)
private fun loadResolvedLibraries(
resolvedLibraries: List<KotlinResolvedLibrary>,
languageVersionSettings: LanguageVersionSettings,
testServices: TestServices
): Pair<List<ModuleDescriptor>, KotlinBuiltIns?> {
var builtInsModule: KotlinBuiltIns? = null
val dependencies = mutableListOf<ModuleDescriptorImpl>()
return resolvedLibraries.map { resolvedLibrary ->
testServices.libraryProvider.getOrCreateStdlibByPath(resolvedLibrary.library.libraryFile.absolutePath) {
// TODO: check safety of the approach of creating a separate storage manager per library
val storageManager = LockBasedStorageManager("ModulesStructure")
val moduleDescriptor = KlibFactories.DefaultDeserializedDescriptorFactory.createDescriptorOptionalBuiltIns(
resolvedLibrary.library,
languageVersionSettings,
storageManager,
builtInsModule,
packageAccessHandler = null,
lookupTracker = LookupTracker.DO_NOTHING
)
dependencies += moduleDescriptor
moduleDescriptor.setDependencies(ArrayList(dependencies))
Pair(moduleDescriptor, resolvedLibrary.library)
}.also {
val isBuiltIns = resolvedLibrary.library.unresolvedDependencies.isEmpty()
if (isBuiltIns) builtInsModule = it.builtIns
}
} to builtInsModule
}