[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
@@ -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
}