[K/N] Run irText tests for K2/Native

^KT-58240
This commit is contained in:
Vladimir Sukharev
2023-08-16 14:40:45 +02:00
committed by Space Team
parent 0cfa721585
commit cd4c241fa3
14 changed files with 6122 additions and 14 deletions
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.fir.types.toSymbol
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.native.interop.ObjCMethodInfo
class FirNativeKotlinMangler : FirMangler() {
object FirNativeKotlinMangler : FirMangler() {
override fun getMangleComputer(mode: MangleMode, compatibleMode: Boolean): KotlinMangleComputer<FirDeclaration> {
return FirNativeKotlinMangleComputer(StringBuilder(256), mode)
}
@@ -1,6 +1,4 @@
// IGNORE_BACKEND_K2: JVM_IR
// IGNORE_BACKEND_K2: JS_IR
// IGNORE_BACKEND_K2: JS_IR_ES6
// IGNORE_BACKEND_K2: ANY
// !LANGUAGE: +MultiPlatformProjects
expect abstract class A protected constructor() {
@@ -3,6 +3,7 @@
// IGNORE_BACKEND_K1: ANY
// IGNORE_BACKEND_K2: JS_IR
// IGNORE_BACKEND_K2: JS_IR_ES6
// IGNORE_BACKEND_K2: NATIVE
// MODULE: lib
// FILE: lib.kt
@@ -1,6 +1,4 @@
// IGNORE_BACKEND_K2: JVM_IR
// IGNORE_BACKEND_K2: JS_IR
// IGNORE_BACKEND_K2: JS_IR_ES6
// IGNORE_BACKEND_K2: ANY
// !LANGUAGE: +MultiPlatformProjects
// SKIP_KLIB_TEST
+2 -3
View File
@@ -1,6 +1,5 @@
// IGNORE_BACKEND_K2: JVM_IR
// IGNORE_BACKEND_K2: JS_IR
// IGNORE_BACKEND_K2: JS_IR_ES6
// KT-53629: K2: repeated labels on statements are not supported or diagnostic is incorrect
// IGNORE_BACKEND_K2: ANY
inline fun foo() = false
fun run(x: Boolean, y: Boolean): String {
+1
View File
@@ -1,6 +1,7 @@
// WITH_STDLIB
// IGNORE_BACKEND_K2: JS_IR
// IGNORE_BACKEND_K2: JS_IR_ES6
// IGNORE_BACKEND_K2: NATIVE
open class ControlFlowInfo<K, V>(val map: Map<K, V>): Map<K, V> by map
@@ -154,8 +154,8 @@ sealed class IrBackendInput : ResultingArtifact.BackendInput<IrBackendInput>() {
}
// Actually, class won't be used as a real input for the Native backend during blackbox testing, since such testing is done via a different engine.
// In irText tests, this class is used only as Native-specific FIR2IR output to render and dump IR.
// So, no source files, icData, error flag, serialization lambda, etc are needed.
// In irText tests, this class is used only to hold Native-specific FIR2IR output (module fragments) to render and dump IR.
// So, other fields are actually not needed: source files, icData, error flag, serialization lambda, etc...
class NativeBackendInput(
override val irModuleFragment: IrModuleFragment,
override val dependentIrModuleFragments: List<IrModuleFragment>,
@@ -90,7 +90,7 @@ internal fun PhaseContext.fir2Ir(
IrGenerationExtension.getInstances(config.project),
signatureComposer = DescriptorSignatureComposerStub(KonanManglerDesc),
irMangler = KonanManglerIr,
firMangler = FirNativeKotlinMangler(),
firMangler = FirNativeKotlinMangler,
visibilityConverter = Fir2IrVisibilityConverter.Default,
kotlinBuiltIns = builtInsModule ?: DefaultBuiltIns.Instance,
actualizerTypeContextProvider = ::IrTypeSystemContextImpl,
@@ -99,7 +99,7 @@ internal fun PhaseContext.fir2Ir(
irModuleFragment.acceptVoid(
ManglerChecker(
KonanManglerIr,
Ir2FirManglerAdapter(FirNativeKotlinMangler()),
Ir2FirManglerAdapter(FirNativeKotlinMangler),
needsChecking = { false }, // FIXME(KT-60648): Re-enable
)
)
+1
View File
@@ -15,6 +15,7 @@ dependencies {
testImplementation(projectTests(":compiler:test-infrastructure"))
testImplementation(projectTests(":generators:test-generator"))
testImplementation(project(":compiler:ir.serialization.native"))
testImplementation(project(":compiler:fir:native"))
testImplementation(project(":native:kotlin-native-utils"))
testImplementation(project(":native:executors"))
testImplementation(project(":kotlin-util-klib-abi"))
@@ -18,6 +18,8 @@ import org.jetbrains.kotlin.konan.test.diagnostics.AbstractDiagnosticsNativeTest
import org.jetbrains.kotlin.konan.test.diagnostics.AbstractFirLightTreeNativeDiagnosticsTest
import org.jetbrains.kotlin.konan.test.diagnostics.AbstractFirPsiNativeDiagnosticsTest
import org.jetbrains.kotlin.konan.test.irtext.AbstractClassicNativeIrTextTest
import org.jetbrains.kotlin.konan.test.irtext.AbstractFirLightTreeNativeIrTextTest
import org.jetbrains.kotlin.konan.test.irtext.AbstractFirPsiNativeIrTextTest
import org.jetbrains.kotlin.test.TargetBackend
import org.jetbrains.kotlin.test.utils.CUSTOM_TEST_DATA_EXTENSION_PATTERN
import org.junit.jupiter.api.Tag
@@ -77,6 +79,12 @@ fun main() {
testClass<AbstractClassicNativeIrTextTest> {
model("ir/irText")
}
testClass<AbstractFirLightTreeNativeIrTextTest> {
model("ir/irText")
}
testClass<AbstractFirPsiNativeIrTextTest> {
model("ir/irText")
}
}
// Samples (how to utilize the abilities of new test infrastructure).
@@ -0,0 +1,202 @@
/*
* Copyright 2010-2023 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.konan.test
import org.jetbrains.kotlin.KtSourceFile
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
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.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.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
import org.jetbrains.kotlin.fir.backend.*
import org.jetbrains.kotlin.fir.backend.native.FirNativeKotlinMangler
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
import org.jetbrains.kotlin.fir.pipeline.ModuleCompilerAnalyzedOutput
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
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
import org.jetbrains.kotlin.test.backend.ir.IrBackendInput
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives
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.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
class Fir2IrNativeResultsConverter(
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)
lateinit var mainIrPart: IrModuleFragment
val dependentIrParts = mutableListOf<IrModuleFragment>()
val sourceFiles = mutableListOf<KtSourceFile>()
val firFilesAndComponentsBySourceFile = mutableMapOf<KtSourceFile, Pair<FirFile, Fir2IrComponents>>()
lateinit var mainPluginContext: IrPluginContext
var irBuiltIns: IrBuiltInsOverFir? = null
val commonMemberStorage = Fir2IrCommonMemberStorage(IdSignatureDescriptor(KonanManglerDesc), FirNativeKotlinMangler)
val diagnosticReporter = DiagnosticReporterFactory.createReporter()
for ((index, part) in inputArtifact.partsForDependsOnModules.withIndex()) {
val (irModuleFragment, components, pluginContext) =
part.firAnalyzerFacade.result.outputs.single().convertToNativeIr(
testServices,
module,
configuration,
diagnosticReporter,
commonMemberStorage,
irBuiltIns,
KonanManglerIr
)
irBuiltIns = components.irBuiltIns
mainPluginContext = pluginContext
if (index < inputArtifact.partsForDependsOnModules.size - 1) {
dependentIrParts.add(irModuleFragment)
} else {
mainIrPart = irModuleFragment
}
sourceFiles.addAll(part.firFiles.mapNotNull { it.value.sourceFile })
for (firFile in part.firFiles.values) {
firFilesAndComponentsBySourceFile[firFile.sourceFile!!] = firFile to components
}
}
val result = IrBackendInput.NativeBackendInput(
mainIrPart,
dependentIrParts,
mainPluginContext,
diagnosticReporter = diagnosticReporter,
descriptorMangler = commonMemberStorage.symbolTable.signaturer.mangler,
irMangler = KonanManglerIr,
firMangler = commonMemberStorage.firSignatureComposer.mangler,
fir2IrComponents = null,
)
return result
}
}
fun ModuleCompilerAnalyzedOutput.convertToNativeIr(
testServices: TestServices,
module: TestModule,
configuration: CompilerConfiguration,
diagnosticReporter: DiagnosticReporter,
commonMemberStorage: Fir2IrCommonMemberStorage,
irBuiltIns: IrBuiltInsOverFir?,
irMangler: KotlinMangler.IrMangler,
): Fir2IrResult {
// TODO: consider avoiding repeated libraries resolution
val libraries = resolveLibraries(configuration, getAllNativeDependenciesPaths(module, testServices))
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,
allowNonCachedDeclarations = false,
expectActualTracker = configuration[CommonConfigurationKeys.EXPECT_ACTUAL_TRACKER],
useIrFakeOverrideBuilder = configuration.getBoolean(CommonConfigurationKeys.USE_IR_FAKE_OVERRIDE_BUILDER),
)
return convertToIr(
Fir2IrExtensions.Default,
fir2IrConfiguration,
commonMemberStorage,
irBuiltIns,
irMangler,
Fir2IrVisibilityConverter.Default,
builtIns ?: DefaultBuiltIns.Instance, // TODO: consider passing externally,
::IrTypeSystemContextImpl
).also {
(it.irModuleFragment.descriptor as? FirModuleDescriptor)?.let { it.allDependencyModules = dependencies }
}
}
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 ->
// resolvedLibrary.library.libraryName in fact resolves to (modified) file path, which is confusing and maybe should be refactored
testServices.libraryProvider.getOrCreateStdlibByPath(resolvedLibrary.library.libraryName) {
// 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
}
@@ -0,0 +1,42 @@
/*
* Copyright 2010-2023 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.konan.test.irtext
import org.jetbrains.kotlin.konan.test.Fir2IrNativeResultsConverter
import org.jetbrains.kotlin.test.Constructor
import org.jetbrains.kotlin.test.FirParser
import org.jetbrains.kotlin.test.backend.ir.IrBackendInput
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.frontend.fir.FirFrontendFacade
import org.jetbrains.kotlin.test.frontend.fir.FirOutputArtifact
import org.jetbrains.kotlin.test.model.Frontend2BackendConverter
import org.jetbrains.kotlin.test.model.FrontendFacade
import org.jetbrains.kotlin.test.model.FrontendKind
import org.jetbrains.kotlin.test.model.FrontendKinds
import org.jetbrains.kotlin.test.runners.codegen.FirPsiCodegenTest
abstract class AbstractFirNativeIrTextTestBase(private val parser: FirParser) : AbstractNativeIrTextTestBase<FirOutputArtifact>() {
override val frontend: FrontendKind<*>
get() = FrontendKinds.FIR
override val frontendFacade: Constructor<FrontendFacade<FirOutputArtifact>>
get() = ::FirFrontendFacade
override val converter: Constructor<Frontend2BackendConverter<FirOutputArtifact, IrBackendInput>>
get() = ::Fir2IrNativeResultsConverter
override fun configure(builder: TestConfigurationBuilder) {
super.configure(builder)
with(builder) {
commonConfigurationForK2(parser)
}
}
}
open class AbstractFirLightTreeNativeIrTextTest : AbstractFirNativeIrTextTestBase(FirParser.LightTree)
@FirPsiCodegenTest
open class AbstractFirPsiNativeIrTextTest : AbstractFirNativeIrTextTestBase(FirParser.Psi)