[test] Introduce DeserializedIrBackend backend kind

We have `BackendKinds.IrBackend` for IR emitted by the frontend.

We need a different backend kind for IR deserialized from klibs.

We cannot use `BackendKinds.IrBackend` for that purpose, because we
cannot have two different `IrBackendInput` subclasses with the same
kind.

We need a different `IrBackendInput` subclass for deserialized IR
because the `IrBackendInput` for frontend-emitted IR contains some
properties like `sourceFiles` which don't make sense for
deserialized IR.

Since we now have two backend kinds for IR artifacts, we need to make
certain functions and classes in the test infrastructure generic
over backend kinds.

Note: the JsIrDeserializedFromKlibBackendInput class is not used
anywhere yet. We will use it in the coming commits.
This commit is contained in:
Sergej Jaskiewicz
2023-07-25 12:45:37 +02:00
committed by Space Team
parent 0521b63cb1
commit 2727163a63
15 changed files with 208 additions and 87 deletions
@@ -16,7 +16,11 @@ import org.jetbrains.kotlin.test.services.ModuleStructureExtractor
import org.jetbrains.kotlin.test.services.PreAnalysisHandler import org.jetbrains.kotlin.test.services.PreAnalysisHandler
import org.jetbrains.kotlin.test.services.TestServices import org.jetbrains.kotlin.test.services.TestServices
typealias Constructor<T> = (TestServices) -> T typealias Constructor<R> = (TestServices) -> R
typealias Constructor2<T, R> = (TestServices, T) -> R
typealias Constructor3<T1, T2, R> = (TestServices, T1, T2) -> R
abstract class TestConfiguration { abstract class TestConfiguration {
abstract val rootDisposable: Disposable abstract val rootDisposable: Disposable
@@ -44,11 +48,11 @@ abstract class TestConfiguration {
// ---------------------------- Utils ---------------------------- // ---------------------------- Utils ----------------------------
fun <T, R> ((TestServices, T) -> R).bind(value: T): Constructor<R> { fun <T, R> Constructor2<T, R>.bind(value: T): Constructor<R> {
return { this.invoke(it, value) } return { this.invoke(it, value) }
} }
fun <T1, T2, R> ((TestServices, T1, T2) -> R).bind(value1: T1, value2: T2): Constructor<R> { fun <T1, T2, R> Constructor3<T1, T2, R>.bind(value1: T1, value2: T2): Constructor<R> {
return { this.invoke(it, value1, value2) } return { this.invoke(it, value1, value2) }
} }
@@ -8,27 +8,41 @@ package org.jetbrains.kotlin.test
import org.jetbrains.kotlin.test.TestRunner.Companion.shouldRun import org.jetbrains.kotlin.test.TestRunner.Companion.shouldRun
import org.jetbrains.kotlin.test.model.* import org.jetbrains.kotlin.test.model.*
sealed class TestStep<I : ResultingArtifact<I>, O : ResultingArtifact<O>> { sealed class TestStep<InputArtifact, OutputArtifact>
abstract val inputArtifactKind: TestArtifactKind<I> where InputArtifact : ResultingArtifact<InputArtifact>,
OutputArtifact : ResultingArtifact<OutputArtifact> {
abstract val inputArtifactKind: TestArtifactKind<InputArtifact>
open fun shouldProcessModule(module: TestModule, inputArtifact: ResultingArtifact<*>): Boolean { open fun shouldProcessModule(module: TestModule, inputArtifact: ResultingArtifact<*>): Boolean {
return inputArtifact.kind == inputArtifactKind return inputArtifact.kind == inputArtifactKind
} }
abstract fun processModule(module: TestModule, inputArtifact: I, thereWereExceptionsOnPreviousSteps: Boolean): StepResult<out O> abstract fun processModule(
module: TestModule,
inputArtifact: InputArtifact,
thereWereExceptionsOnPreviousSteps: Boolean,
): StepResult<out OutputArtifact>
class FacadeStep<I : ResultingArtifact<I>, O : ResultingArtifact<O>>(val facade: AbstractTestFacade<I, O>) : TestStep<I, O>() { class FacadeStep<InputArtifact, OutputArtifact>(
override val inputArtifactKind: TestArtifactKind<I> val facade: AbstractTestFacade<InputArtifact, OutputArtifact>,
) : TestStep<InputArtifact, OutputArtifact>()
where InputArtifact : ResultingArtifact<InputArtifact>,
OutputArtifact : ResultingArtifact<OutputArtifact> {
override val inputArtifactKind: TestArtifactKind<InputArtifact>
get() = facade.inputKind get() = facade.inputKind
val outputArtifactKind: TestArtifactKind<O> val outputArtifactKind: TestArtifactKind<OutputArtifact>
get() = facade.outputKind get() = facade.outputKind
override fun shouldProcessModule(module: TestModule, inputArtifact: ResultingArtifact<*>): Boolean { override fun shouldProcessModule(module: TestModule, inputArtifact: ResultingArtifact<*>): Boolean {
return super.shouldProcessModule(module, inputArtifact) && facade.shouldRunAnalysis(module) return super.shouldProcessModule(module, inputArtifact) && facade.shouldRunAnalysis(module)
} }
override fun processModule(module: TestModule, inputArtifact: I, thereWereExceptionsOnPreviousSteps: Boolean): StepResult<out O> { override fun processModule(
module: TestModule,
inputArtifact: InputArtifact,
thereWereExceptionsOnPreviousSteps: Boolean,
): StepResult<out OutputArtifact> {
val outputArtifact = try { val outputArtifact = try {
facade.transform(module, inputArtifact) ?: return StepResult.NoArtifactFromFacade facade.transform(module, inputArtifact) ?: return StepResult.NoArtifactFromFacade
} catch (e: Throwable) { } catch (e: Throwable) {
@@ -39,17 +53,22 @@ sealed class TestStep<I : ResultingArtifact<I>, O : ResultingArtifact<O>> {
} }
} }
class HandlersStep<I : ResultingArtifact<I>>( class HandlersStep<InputArtifact : ResultingArtifact<InputArtifact>>(
override val inputArtifactKind: TestArtifactKind<I>, override val inputArtifactKind: TestArtifactKind<InputArtifact>,
val handlers: List<AnalysisHandler<I>> val handlers: List<AnalysisHandler<InputArtifact>>
) : TestStep<I, Nothing>() { ) : TestStep<InputArtifact, Nothing>() {
init { init {
require(handlers.all { it.artifactKind == inputArtifactKind }) for (handler in handlers) {
require(handler.artifactKind == inputArtifactKind) {
"Artifact kind mismatch. Artifact kind of each handler must match input artifact kind ($inputArtifactKind). " +
"In handler $handler artifact kind is ${handler.artifactKind}"
}
}
} }
override fun processModule( override fun processModule(
module: TestModule, module: TestModule,
inputArtifact: I, inputArtifact: InputArtifact,
thereWereExceptionsOnPreviousSteps: Boolean thereWereExceptionsOnPreviousSteps: Boolean
): StepResult.HandlersResult { ): StepResult.HandlersResult {
val exceptions = mutableListOf<WrappedException>() val exceptions = mutableListOf<WrappedException>()
@@ -69,15 +88,20 @@ sealed class TestStep<I : ResultingArtifact<I>, O : ResultingArtifact<O>> {
} }
} }
sealed class StepResult<O : ResultingArtifact<O>> { sealed class StepResult<OutputArtifact : ResultingArtifact<OutputArtifact>> {
class Artifact<O : ResultingArtifact<O>>(val outputArtifact: O) : StepResult<O>()
class ErrorFromFacade<O : ResultingArtifact<O>>(val exception: WrappedException) : StepResult<O>() class Artifact<OutputArtifact : ResultingArtifact<OutputArtifact>>(val outputArtifact: OutputArtifact) :
StepResult<OutputArtifact>()
class ErrorFromFacade<OutputArtifact : ResultingArtifact<OutputArtifact>>(val exception: WrappedException) :
StepResult<OutputArtifact>()
data class HandlersResult( data class HandlersResult(
val exceptionsFromHandlers: Collection<WrappedException>, val exceptionsFromHandlers: Collection<WrappedException>,
val shouldRunNextSteps: Boolean val shouldRunNextSteps: Boolean
) : StepResult<Nothing>() ) : StepResult<Nothing>()
object NoArtifactFromFacade : StepResult<Nothing>() data object NoArtifactFromFacade : StepResult<Nothing>()
} }
} }
@@ -8,38 +8,49 @@ package org.jetbrains.kotlin.test
import org.jetbrains.kotlin.test.model.* import org.jetbrains.kotlin.test.model.*
import org.jetbrains.kotlin.test.services.TestServices import org.jetbrains.kotlin.test.services.TestServices
sealed class TestStepBuilder<I : ResultingArtifact<I>, O : ResultingArtifact<O>> { sealed class TestStepBuilder<InputArtifact, OutputArtifact>
where InputArtifact : ResultingArtifact<InputArtifact>,
OutputArtifact : ResultingArtifact<OutputArtifact> {
@TestInfrastructureInternals @TestInfrastructureInternals
abstract fun createTestStep(testServices: TestServices): TestStep<I, O> abstract fun createTestStep(testServices: TestServices): TestStep<InputArtifact, OutputArtifact>
} }
class FacadeStepBuilder<I : ResultingArtifact<I>, O : ResultingArtifact<O>>( class FacadeStepBuilder<InputArtifact, OutputArtifact>(
val facade: Constructor<AbstractTestFacade<I, O>> val facade: Constructor<AbstractTestFacade<InputArtifact, OutputArtifact>>,
) : TestStepBuilder<I, O>() { ) : TestStepBuilder<InputArtifact, OutputArtifact>()
where InputArtifact : ResultingArtifact<InputArtifact>,
OutputArtifact : ResultingArtifact<OutputArtifact> {
@TestInfrastructureInternals @TestInfrastructureInternals
override fun createTestStep(testServices: TestServices): TestStep.FacadeStep<I, O> { override fun createTestStep(testServices: TestServices): TestStep.FacadeStep<InputArtifact, OutputArtifact> {
return TestStep.FacadeStep(facade.invoke(testServices)) return TestStep.FacadeStep(facade.invoke(testServices))
} }
} }
class HandlersStepBuilder<I : ResultingArtifact<I>>(val artifactKind: TestArtifactKind<I>) : TestStepBuilder<I, Nothing>() { class HandlersStepBuilder<InputArtifact, InputArtifactKind>(val artifactKind: InputArtifactKind) :
private val handlers: MutableList<Constructor<AnalysisHandler<I>>> = mutableListOf() TestStepBuilder<InputArtifact, Nothing>()
where InputArtifact : ResultingArtifact<InputArtifact>,
InputArtifactKind : TestArtifactKind<InputArtifact> {
private val handlers: MutableList<Constructor<AnalysisHandler<InputArtifact>>> = mutableListOf()
fun useHandlers(vararg constructor: Constructor<AnalysisHandler<I>>) { fun useHandlers(vararg constructor: Constructor<AnalysisHandler<InputArtifact>>) {
handlers += constructor handlers += constructor
} }
fun useHandlersAtFirst(vararg constructor: Constructor<AnalysisHandler<I>>) { fun useHandlers(vararg constructor: Constructor2<InputArtifactKind, AnalysisHandler<InputArtifact>>) {
constructor.mapTo(handlers) { it.bind(artifactKind) }
}
fun useHandlersAtFirst(vararg constructor: Constructor<AnalysisHandler<InputArtifact>>) {
handlers.addAll(0, constructor.toList()) handlers.addAll(0, constructor.toList())
} }
fun useHandlers(constructors: List<Constructor<AnalysisHandler<I>>>) { fun useHandlers(constructors: List<Constructor<AnalysisHandler<InputArtifact>>>) {
handlers += constructors handlers += constructors
} }
@TestInfrastructureInternals @TestInfrastructureInternals
override fun createTestStep(testServices: TestServices): TestStep.HandlersStep<I> { override fun createTestStep(testServices: TestServices): TestStep.HandlersStep<InputArtifact> {
return TestStep.HandlersStep(artifactKind, handlers.map { it.invoke(testServices) }) return TestStep.HandlersStep(artifactKind, handlers.map { it.invoke(testServices) })
} }
} }
@@ -35,16 +35,22 @@ class DependencyProviderImpl(
return testModulesByName[name] ?: assertions.fail { "Module $name is not defined" } return testModulesByName[name] ?: assertions.fail { "Module $name is not defined" }
} }
override fun <A : ResultingArtifact<A>> getArtifactSafe(module: TestModule, kind: TestArtifactKind<A>): A? { override fun <OutputArtifact : ResultingArtifact<OutputArtifact>> getArtifactSafe(
module: TestModule,
kind: TestArtifactKind<OutputArtifact>,
): OutputArtifact? {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
return artifactsByModule.getMap(module)[kind] as A? return artifactsByModule.getMap(module)[kind] as OutputArtifact?
} }
override fun <A : ResultingArtifact<A>> getArtifact(module: TestModule, kind: TestArtifactKind<A>): A { override fun <A : ResultingArtifact<A>> getArtifact(module: TestModule, kind: TestArtifactKind<A>): A {
return getArtifactSafe(module, kind) ?: error("Artifact with kind $kind is not registered for module ${module.name}") return getArtifactSafe(module, kind) ?: error("Artifact with kind $kind is not registered for module ${module.name}")
} }
fun <A : ResultingArtifact<A>> registerArtifact(module: TestModule, artifact: ResultingArtifact<A>) { fun <OutputArtifact : ResultingArtifact<OutputArtifact>> registerArtifact(
module: TestModule,
artifact: ResultingArtifact<OutputArtifact>,
) {
val kind = artifact.kind val kind = artifact.kind
val previousValue = artifactsByModule.getMap(module).put(kind, artifact) val previousValue = artifactsByModule.getMap(module).put(kind, artifact)
if (previousValue != null) error("Artifact with kind $kind already registered for module ${module.name}") if (previousValue != null) error("Artifact with kind $kind already registered for module ${module.name}")
@@ -7,11 +7,13 @@ package org.jetbrains.kotlin.test.backend.handlers
import org.jetbrains.kotlin.test.backend.ir.IrBackendInput import org.jetbrains.kotlin.test.backend.ir.IrBackendInput
import org.jetbrains.kotlin.test.model.BackendInputHandler import org.jetbrains.kotlin.test.model.BackendInputHandler
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.services.TestServices import org.jetbrains.kotlin.test.services.TestServices
abstract class AbstractIrHandler( abstract class AbstractIrHandler(
testServices: TestServices, testServices: TestServices,
artifactKind: BackendKind<IrBackendInput> = BackendKinds.IrBackend,
failureDisablesNextSteps: Boolean = false, failureDisablesNextSteps: Boolean = false,
doNotRunIfThereWerePreviousFailures: Boolean = false doNotRunIfThereWerePreviousFailures: Boolean = false
) : BackendInputHandler<IrBackendInput>(testServices, BackendKinds.IrBackend, failureDisablesNextSteps, doNotRunIfThereWerePreviousFailures) ) : BackendInputHandler<IrBackendInput>(testServices, artifactKind, failureDisablesNextSteps, doNotRunIfThereWerePreviousFailures)
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.DUMP_LOCAL_DEC
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.DUMP_SIGNATURES import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.DUMP_SIGNATURES
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.MUTE_SIGNATURE_COMPARISON_K2 import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.MUTE_SIGNATURE_COMPARISON_K2
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.SKIP_SIGNATURE_DUMP import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.SKIP_SIGNATURE_DUMP
import org.jetbrains.kotlin.test.model.BackendKind
import org.jetbrains.kotlin.test.model.FrontendKinds import org.jetbrains.kotlin.test.model.FrontendKinds
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
@@ -92,7 +93,10 @@ private const val CHECK_MARKER = "// CHECK"
* any backends, we print the actual mangled name and signature for this declaration. * any backends, we print the actual mangled name and signature for this declaration.
* - Otherwise, we print the parsed `// CHECK` block as is. * - Otherwise, we print the parsed `// CHECK` block as is.
*/ */
class IrMangledNameAndSignatureDumpHandler(testServices: TestServices) : AbstractIrHandler(testServices) { class IrMangledNameAndSignatureDumpHandler(
testServices: TestServices,
artifactKind: BackendKind<IrBackendInput>,
) : AbstractIrHandler(testServices, artifactKind) {
companion object { companion object {
const val DUMP_EXTENSION = "sig.kt.txt" const val DUMP_EXTENSION = "sig.kt.txt"
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.EXTERNAL_FILE
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.SKIP_KT_DUMP import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.SKIP_KT_DUMP
import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives
import org.jetbrains.kotlin.test.directives.model.DirectivesContainer import org.jetbrains.kotlin.test.directives.model.DirectivesContainer
import org.jetbrains.kotlin.test.model.BackendKind
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.test.services.moduleStructure import org.jetbrains.kotlin.test.services.moduleStructure
@@ -30,7 +31,10 @@ import org.jetbrains.kotlin.test.utils.withExtension
* This handler can be enabled by specifying the [DUMP_KT_IR] test directive, * This handler can be enabled by specifying the [DUMP_KT_IR] test directive,
* or disabled with the [SKIP_KT_DUMP] directive. * or disabled with the [SKIP_KT_DUMP] directive.
*/ */
class IrPrettyKotlinDumpHandler(testServices: TestServices) : AbstractIrHandler(testServices) { class IrPrettyKotlinDumpHandler(
testServices: TestServices,
artifactKind: BackendKind<IrBackendInput>,
) : AbstractIrHandler(testServices, artifactKind) {
companion object { companion object {
const val DUMP_EXTENSION = "kt.txt" const val DUMP_EXTENSION = "kt.txt"
} }
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.EXTERNAL_FILE
import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives
import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives.FIR_IDENTICAL import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives.FIR_IDENTICAL
import org.jetbrains.kotlin.test.directives.model.DirectivesContainer import org.jetbrains.kotlin.test.directives.model.DirectivesContainer
import org.jetbrains.kotlin.test.model.BackendKind
import org.jetbrains.kotlin.test.model.FrontendKinds import org.jetbrains.kotlin.test.model.FrontendKinds
import org.jetbrains.kotlin.test.model.TestFile import org.jetbrains.kotlin.test.model.TestFile
import org.jetbrains.kotlin.test.model.TestModule import org.jetbrains.kotlin.test.model.TestModule
@@ -31,7 +32,10 @@ import org.jetbrains.kotlin.test.utils.withExtension
import org.jetbrains.kotlin.test.utils.withSuffixAndExtension import org.jetbrains.kotlin.test.utils.withSuffixAndExtension
import java.io.File import java.io.File
class IrTextDumpHandler(testServices: TestServices) : AbstractIrHandler(testServices) { class IrTextDumpHandler(
testServices: TestServices,
artifactKind: BackendKind<IrBackendInput>,
) : AbstractIrHandler(testServices, artifactKind) {
companion object { companion object {
const val DUMP_EXTENSION = "ir.txt" const val DUMP_EXTENSION = "ir.txt"
@@ -14,11 +14,15 @@ import org.jetbrains.kotlin.test.backend.ir.IrBackendInput
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives import org.jetbrains.kotlin.test.directives.CodegenTestDirectives
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.EXTERNAL_FILE import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.EXTERNAL_FILE
import org.jetbrains.kotlin.test.directives.model.DirectivesContainer import org.jetbrains.kotlin.test.directives.model.DirectivesContainer
import org.jetbrains.kotlin.test.model.BackendKind
import org.jetbrains.kotlin.test.model.FrontendKinds import org.jetbrains.kotlin.test.model.FrontendKinds
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
class IrTreeVerifierHandler(testServices: TestServices) : AbstractIrHandler(testServices) { class IrTreeVerifierHandler(
testServices: TestServices,
artifactKind: BackendKind<IrBackendInput>,
) : AbstractIrHandler(testServices, artifactKind) {
override val directiveContainers: List<DirectivesContainer> override val directiveContainers: List<DirectivesContainer>
get() = listOf(CodegenTestDirectives) get() = listOf(CodegenTestDirectives)
@@ -18,12 +18,13 @@ import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.util.KotlinMangler import org.jetbrains.kotlin.ir.util.KotlinMangler
import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.ProtoBuf
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
// IR backend (JVM, JS, Native, Wasm) // IR backend (JVM, JS, Native, Wasm)
sealed class IrBackendInput : ResultingArtifact.BackendInput<IrBackendInput>() { sealed class IrBackendInput : ResultingArtifact.BackendInput<IrBackendInput>() {
override val kind: BackendKinds.IrBackend override val kind: BackendKind<IrBackendInput>
get() = BackendKinds.IrBackend get() = BackendKinds.IrBackend
abstract val irModuleFragment: IrModuleFragment abstract val irModuleFragment: IrModuleFragment
@@ -93,6 +94,22 @@ sealed class IrBackendInput : ResultingArtifact.BackendInput<IrBackendInput>() {
val serializeSingleFile: (KtSourceFile, IrActualizedResult?) -> ProtoBuf.PackageFragment, val serializeSingleFile: (KtSourceFile, IrActualizedResult?) -> ProtoBuf.PackageFragment,
) : IrBackendInput() ) : IrBackendInput()
data class JsIrDeserializedFromKlibBackendInput(
override val irModuleFragment: IrModuleFragment,
override val dependentIrModuleFragments: List<IrModuleFragment>,
override val irPluginContext: IrPluginContext,
override val diagnosticReporter: BaseDiagnosticsCollector,
override val descriptorMangler: KotlinMangler.DescriptorMangler,
override val irMangler: KotlinMangler.IrMangler,
override val firMangler: FirMangler?,
) : IrBackendInput() {
override val kind: BackendKind<IrBackendInput>
get() = BackendKinds.DeserializedIrBackend
override var irActualizerResult: IrActualizedResult? = null
}
class WasmBackendInput( class WasmBackendInput(
override val irModuleFragment: IrModuleFragment, override val irModuleFragment: IrModuleFragment,
override val dependentIrModuleFragments: List<IrModuleFragment>, override val dependentIrModuleFragments: List<IrModuleFragment>,
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.test.backend.classic.ClassicJvmBackendFacade
import org.jetbrains.kotlin.test.backend.ir.IrBackendInput import org.jetbrains.kotlin.test.backend.ir.IrBackendInput
import org.jetbrains.kotlin.test.backend.ir.JvmIrBackendFacade import org.jetbrains.kotlin.test.backend.ir.JvmIrBackendFacade
import org.jetbrains.kotlin.test.builders.CompilerStepsNames.CLASSIC_FRONTEND_HANDLERS_STEP_NAME import org.jetbrains.kotlin.test.builders.CompilerStepsNames.CLASSIC_FRONTEND_HANDLERS_STEP_NAME
import org.jetbrains.kotlin.test.builders.CompilerStepsNames.DESERIALIZED_IR_HANDLERS_STEP_NAME
import org.jetbrains.kotlin.test.builders.CompilerStepsNames.FIR_HANDLERS_STEP_NAME import org.jetbrains.kotlin.test.builders.CompilerStepsNames.FIR_HANDLERS_STEP_NAME
import org.jetbrains.kotlin.test.builders.CompilerStepsNames.JS_ARTIFACTS_HANDLERS_STEP_NAME import org.jetbrains.kotlin.test.builders.CompilerStepsNames.JS_ARTIFACTS_HANDLERS_STEP_NAME
import org.jetbrains.kotlin.test.builders.CompilerStepsNames.JVM_ARTIFACTS_HANDLERS_STEP_NAME import org.jetbrains.kotlin.test.builders.CompilerStepsNames.JVM_ARTIFACTS_HANDLERS_STEP_NAME
@@ -35,6 +36,7 @@ object CompilerStepsNames {
const val CONVERTER_STEP_NAME = "converter" const val CONVERTER_STEP_NAME = "converter"
const val RAW_IR_HANDLERS_STEP_NAME = "raw IR handlers" const val RAW_IR_HANDLERS_STEP_NAME = "raw IR handlers"
const val DESERIALIZED_IR_HANDLERS_STEP_NAME = "deserialized IR handlers"
const val JVM_BACKEND_STEP_NAME = "jvm backend" const val JVM_BACKEND_STEP_NAME = "jvm backend"
const val JVM_ARTIFACTS_HANDLERS_STEP_NAME = "jvm artifacts handlers" const val JVM_ARTIFACTS_HANDLERS_STEP_NAME = "jvm artifacts handlers"
@@ -78,86 +80,98 @@ fun TestConfigurationBuilder.jvmIrBackendStep() {
// use those ones to define new step // use those ones to define new step
inline fun TestConfigurationBuilder.classicFrontendHandlersStep( inline fun TestConfigurationBuilder.classicFrontendHandlersStep(
init: HandlersStepBuilder<ClassicFrontendOutputArtifact>.() -> Unit = {} init: HandlersStepBuilder<ClassicFrontendOutputArtifact, FrontendKinds.ClassicFrontend>.() -> Unit = {}
) { ) {
namedHandlersStep(CLASSIC_FRONTEND_HANDLERS_STEP_NAME, FrontendKinds.ClassicFrontend, init) namedHandlersStep(CLASSIC_FRONTEND_HANDLERS_STEP_NAME, FrontendKinds.ClassicFrontend, init)
} }
inline fun TestConfigurationBuilder.firHandlersStep( inline fun TestConfigurationBuilder.firHandlersStep(
init: HandlersStepBuilder<FirOutputArtifact>.() -> Unit = {} init: HandlersStepBuilder<FirOutputArtifact, FrontendKinds.FIR>.() -> Unit = {}
) { ) {
namedHandlersStep(FIR_HANDLERS_STEP_NAME, FrontendKinds.FIR, init) namedHandlersStep(FIR_HANDLERS_STEP_NAME, FrontendKinds.FIR, init)
} }
inline fun TestConfigurationBuilder.irHandlersStep( inline fun TestConfigurationBuilder.irHandlersStep(
init: HandlersStepBuilder<IrBackendInput>.() -> Unit = {} init: HandlersStepBuilder<IrBackendInput, BackendKinds.IrBackend>.() -> Unit = {}
) { ) {
namedHandlersStep(RAW_IR_HANDLERS_STEP_NAME, BackendKinds.IrBackend, init) namedHandlersStep(RAW_IR_HANDLERS_STEP_NAME, BackendKinds.IrBackend, init)
} }
inline fun TestConfigurationBuilder.deserializedIrHandlersStep(
init: HandlersStepBuilder<IrBackendInput, BackendKinds.DeserializedIrBackend>.() -> Unit = {}
) {
namedHandlersStep(DESERIALIZED_IR_HANDLERS_STEP_NAME, BackendKinds.DeserializedIrBackend, init)
}
inline fun TestConfigurationBuilder.jvmArtifactsHandlersStep( inline fun TestConfigurationBuilder.jvmArtifactsHandlersStep(
init: HandlersStepBuilder<BinaryArtifacts.Jvm>.() -> Unit = {} init: HandlersStepBuilder<BinaryArtifacts.Jvm, ArtifactKinds.Jvm>.() -> Unit = {}
) { ) {
namedHandlersStep(JVM_ARTIFACTS_HANDLERS_STEP_NAME, ArtifactKinds.Jvm, init) namedHandlersStep(JVM_ARTIFACTS_HANDLERS_STEP_NAME, ArtifactKinds.Jvm, init)
} }
inline fun TestConfigurationBuilder.jsArtifactsHandlersStep( inline fun TestConfigurationBuilder.jsArtifactsHandlersStep(
init: HandlersStepBuilder<BinaryArtifacts.Js>.() -> Unit = {} init: HandlersStepBuilder<BinaryArtifacts.Js, ArtifactKinds.Js>.() -> Unit = {}
) { ) {
namedHandlersStep(JS_ARTIFACTS_HANDLERS_STEP_NAME, ArtifactKinds.Js, init) namedHandlersStep(JS_ARTIFACTS_HANDLERS_STEP_NAME, ArtifactKinds.Js, init)
} }
inline fun TestConfigurationBuilder.wasmArtifactsHandlersStep( inline fun TestConfigurationBuilder.wasmArtifactsHandlersStep(
init: HandlersStepBuilder<BinaryArtifacts.Wasm>.() -> Unit = {} init: HandlersStepBuilder<BinaryArtifacts.Wasm, ArtifactKinds.Wasm>.() -> Unit = {}
) { ) {
namedHandlersStep(WASM_ARTIFACTS_HANDLERS_STEP_NAME, ArtifactKinds.Wasm, init) namedHandlersStep(WASM_ARTIFACTS_HANDLERS_STEP_NAME, ArtifactKinds.Wasm, init)
} }
inline fun TestConfigurationBuilder.klibArtifactsHandlersStep( inline fun TestConfigurationBuilder.klibArtifactsHandlersStep(
init: HandlersStepBuilder<BinaryArtifacts.KLib>.() -> Unit = {} init: HandlersStepBuilder<BinaryArtifacts.KLib, ArtifactKinds.KLib>.() -> Unit = {}
) { ) {
namedHandlersStep(KLIB_ARTIFACTS_HANDLERS_STEP_NAME, ArtifactKinds.KLib, init) namedHandlersStep(KLIB_ARTIFACTS_HANDLERS_STEP_NAME, ArtifactKinds.KLib, init)
} }
// and those ones to configure already defined step // and those ones to configure already defined step
inline fun TestConfigurationBuilder.configureClassicFrontendHandlersStep( inline fun TestConfigurationBuilder.configureClassicFrontendHandlersStep(
init: HandlersStepBuilder<ClassicFrontendOutputArtifact>.() -> Unit = {} init: HandlersStepBuilder<ClassicFrontendOutputArtifact, FrontendKinds.ClassicFrontend>.() -> Unit = {}
) { ) {
configureNamedHandlersStep(CLASSIC_FRONTEND_HANDLERS_STEP_NAME, FrontendKinds.ClassicFrontend, init) configureNamedHandlersStep(CLASSIC_FRONTEND_HANDLERS_STEP_NAME, FrontendKinds.ClassicFrontend, init)
} }
inline fun TestConfigurationBuilder.configureFirHandlersStep( inline fun TestConfigurationBuilder.configureFirHandlersStep(
init: HandlersStepBuilder<FirOutputArtifact>.() -> Unit = {} init: HandlersStepBuilder<FirOutputArtifact, FrontendKinds.FIR>.() -> Unit = {}
) { ) {
configureNamedHandlersStep(FIR_HANDLERS_STEP_NAME, FrontendKinds.FIR, init) configureNamedHandlersStep(FIR_HANDLERS_STEP_NAME, FrontendKinds.FIR, init)
} }
inline fun TestConfigurationBuilder.configureIrHandlersStep( inline fun TestConfigurationBuilder.configureIrHandlersStep(
init: HandlersStepBuilder<IrBackendInput>.() -> Unit = {} init: HandlersStepBuilder<IrBackendInput, BackendKinds.IrBackend>.() -> Unit = {}
) { ) {
configureNamedHandlersStep(RAW_IR_HANDLERS_STEP_NAME, BackendKinds.IrBackend, init) configureNamedHandlersStep(RAW_IR_HANDLERS_STEP_NAME, BackendKinds.IrBackend, init)
} }
inline fun TestConfigurationBuilder.configureDeserializedIrHandlersStep(
init: HandlersStepBuilder<IrBackendInput, BackendKinds.DeserializedIrBackend>.() -> Unit = {}
) {
configureNamedHandlersStep(DESERIALIZED_IR_HANDLERS_STEP_NAME, BackendKinds.DeserializedIrBackend, init)
}
inline fun TestConfigurationBuilder.configureJvmArtifactsHandlersStep( inline fun TestConfigurationBuilder.configureJvmArtifactsHandlersStep(
init: HandlersStepBuilder<BinaryArtifacts.Jvm>.() -> Unit = {} init: HandlersStepBuilder<BinaryArtifacts.Jvm, ArtifactKinds.Jvm>.() -> Unit = {}
) { ) {
configureNamedHandlersStep(JVM_ARTIFACTS_HANDLERS_STEP_NAME, ArtifactKinds.Jvm, init) configureNamedHandlersStep(JVM_ARTIFACTS_HANDLERS_STEP_NAME, ArtifactKinds.Jvm, init)
} }
inline fun TestConfigurationBuilder.configureJsArtifactsHandlersStep( inline fun TestConfigurationBuilder.configureJsArtifactsHandlersStep(
init: HandlersStepBuilder<BinaryArtifacts.Js>.() -> Unit = {} init: HandlersStepBuilder<BinaryArtifacts.Js, ArtifactKinds.Js>.() -> Unit = {}
) { ) {
configureNamedHandlersStep(JS_ARTIFACTS_HANDLERS_STEP_NAME, ArtifactKinds.Js, init) configureNamedHandlersStep(JS_ARTIFACTS_HANDLERS_STEP_NAME, ArtifactKinds.Js, init)
} }
inline fun TestConfigurationBuilder.configureWasmArtifactsHandlersStep( inline fun TestConfigurationBuilder.configureWasmArtifactsHandlersStep(
init: HandlersStepBuilder<BinaryArtifacts.Wasm>.() -> Unit = {} init: HandlersStepBuilder<BinaryArtifacts.Wasm, ArtifactKinds.Wasm>.() -> Unit = {}
) { ) {
configureNamedHandlersStep(WASM_ARTIFACTS_HANDLERS_STEP_NAME, ArtifactKinds.Wasm, init) configureNamedHandlersStep(WASM_ARTIFACTS_HANDLERS_STEP_NAME, ArtifactKinds.Wasm, init)
} }
inline fun TestConfigurationBuilder.configureKlibArtifactsHandlersStep( inline fun TestConfigurationBuilder.configureKlibArtifactsHandlersStep(
init: HandlersStepBuilder<BinaryArtifacts.KLib>.() -> Unit = {} init: HandlersStepBuilder<BinaryArtifacts.KLib, ArtifactKinds.KLib>.() -> Unit = {}
) { ) {
configureNamedHandlersStep(KLIB_ARTIFACTS_HANDLERS_STEP_NAME, ArtifactKinds.KLib, init) configureNamedHandlersStep(KLIB_ARTIFACTS_HANDLERS_STEP_NAME, ArtifactKinds.KLib, init)
} }
@@ -104,45 +104,52 @@ class TestConfigurationBuilder {
} }
} }
inline fun <I : ResultingArtifact<I>> handlersStep( inline fun <InputArtifact, InputArtifactKind> handlersStep(
artifactKind: TestArtifactKind<I>, artifactKind: InputArtifactKind,
init: HandlersStepBuilder<I>.() -> Unit init: HandlersStepBuilder<InputArtifact, InputArtifactKind>.() -> Unit,
): HandlersStepBuilder<I> { ): HandlersStepBuilder<InputArtifact, InputArtifactKind>
where InputArtifact : ResultingArtifact<InputArtifact>,
InputArtifactKind : TestArtifactKind<InputArtifact> {
return HandlersStepBuilder(artifactKind).also { return HandlersStepBuilder(artifactKind).also {
it.init() it.init()
steps += it steps += it
} }
} }
inline fun <I : ResultingArtifact<I>> namedHandlersStep( inline fun <InputArtifact, InputArtifactKind> namedHandlersStep(
name: String, name: String,
artifactKind: TestArtifactKind<I>, artifactKind: InputArtifactKind,
init: HandlersStepBuilder<I>.() -> Unit init: HandlersStepBuilder<InputArtifact, InputArtifactKind>.() -> Unit,
): HandlersStepBuilder<I> { ): HandlersStepBuilder<InputArtifact, InputArtifactKind>
val previouslyContainedStep = namedStepOfType<I>(name) where InputArtifact : ResultingArtifact<InputArtifact>,
if (previouslyContainedStep == null) { InputArtifactKind : TestArtifactKind<InputArtifact> {
val previouslyContainedStep = namedStepOfType<InputArtifact, InputArtifactKind>(name)
return if (previouslyContainedStep == null) {
val step = handlersStep(artifactKind, init) val step = handlersStep(artifactKind, init)
namedSteps[name] = step namedSteps[name] = step
return step step
} else { } else {
configureNamedHandlersStep(name, artifactKind, init) configureNamedHandlersStep(name, artifactKind, init)
return previouslyContainedStep previouslyContainedStep
} }
} }
inline fun <I : ResultingArtifact<I>> configureNamedHandlersStep( inline fun <InputArtifact, InputArtifactKind> configureNamedHandlersStep(
name: String, name: String,
artifactKind: TestArtifactKind<I>, artifactKind: InputArtifactKind,
init: HandlersStepBuilder<I>.() -> Unit init: HandlersStepBuilder<InputArtifact, InputArtifactKind>.() -> Unit
) { ) where InputArtifact : ResultingArtifact<InputArtifact>,
val step = namedStepOfType<I>(name) ?: error { "Step \"$name\" not found" } InputArtifactKind : TestArtifactKind<InputArtifact> {
val step = namedStepOfType<InputArtifact, InputArtifactKind>(name) ?: error { "Step \"$name\" not found" }
require(step.artifactKind == artifactKind) { "Step kind: ${step.artifactKind}, passed kind is $artifactKind" } require(step.artifactKind == artifactKind) { "Step kind: ${step.artifactKind}, passed kind is $artifactKind" }
step.apply(init) step.apply(init)
} }
fun <I : ResultingArtifact<I>> namedStepOfType(name: String): HandlersStepBuilder<I>? { fun <InputArtifact, InputArtifactKind> namedStepOfType(name: String): HandlersStepBuilder<InputArtifact, InputArtifactKind>?
where InputArtifact : ResultingArtifact<InputArtifact>,
InputArtifactKind : TestArtifactKind<InputArtifact> {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
return namedSteps[name] as HandlersStepBuilder<I>? return namedSteps[name] as HandlersStepBuilder<InputArtifact, InputArtifactKind>?
} }
fun useSourcePreprocessor(vararg preprocessors: Constructor<SourceFilePreprocessor>, needToPrepend: Boolean = false) { fun useSourcePreprocessor(vararg preprocessors: Constructor<SourceFilePreprocessor>, needToPrepend: Boolean = false) {
@@ -29,12 +29,22 @@ val FrontendKind<*>.isFir: Boolean
object BackendKinds { object BackendKinds {
object ClassicBackend : BackendKind<ClassicBackendInput>("ClassicBackend") object ClassicBackend : BackendKind<ClassicBackendInput>("ClassicBackend")
/**
* The artifact kind representing IR generated by the frontend.
*/
object IrBackend : BackendKind<IrBackendInput>("IrBackend") object IrBackend : BackendKind<IrBackendInput>("IrBackend")
/**
* The artifact kind representing IR deserialized from a klib.
*/
object DeserializedIrBackend : BackendKind<IrBackendInput>("DeserializedIrBackend")
fun fromString(string: String): BackendKind<*>? { fun fromString(string: String): BackendKind<*>? {
return when (string) { return when (string) {
"ClassicBackend" -> ClassicBackend "ClassicBackend" -> ClassicBackend
"IrBackend" -> IrBackend "IrBackend" -> IrBackend
"DeserializedIrBackend" -> DeserializedIrBackend
else -> null else -> null
} }
} }
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.test.TestJdkKind
import org.jetbrains.kotlin.test.backend.handlers.* import org.jetbrains.kotlin.test.backend.handlers.*
import org.jetbrains.kotlin.test.backend.ir.IrActualizerAndPluginsFacade import org.jetbrains.kotlin.test.backend.ir.IrActualizerAndPluginsFacade
import org.jetbrains.kotlin.test.backend.ir.IrBackendInput import org.jetbrains.kotlin.test.backend.ir.IrBackendInput
import org.jetbrains.kotlin.test.backend.ir.IrDiagnosticsHandler import org.jetbrains.kotlin.test.bind
import org.jetbrains.kotlin.test.builders.* import org.jetbrains.kotlin.test.builders.*
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives import org.jetbrains.kotlin.test.directives.CodegenTestDirectives
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.DUMP_SMAP import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.DUMP_SMAP
@@ -151,46 +151,51 @@ fun TestConfigurationBuilder.commonHandlersForCodegenTest() {
} }
} }
fun HandlersStepBuilder<IrBackendInput>.dumpHandlersForConverterStep() { fun <InputArtifactKind> HandlersStepBuilder<IrBackendInput, InputArtifactKind>.dumpHandlersForConverterStep()
useHandlers(::IrTreeVerifierHandler, ::IrTextDumpHandler, ::IrMangledNameAndSignatureDumpHandler) where InputArtifactKind : BackendKind<IrBackendInput> {
useHandlers(
::IrTreeVerifierHandler,
::IrTextDumpHandler,
::IrMangledNameAndSignatureDumpHandler,
)
} }
fun HandlersStepBuilder<BinaryArtifacts.Jvm>.dumpHandlersForBackendStep() { fun HandlersStepBuilder<BinaryArtifacts.Jvm, ArtifactKinds.Jvm>.dumpHandlersForBackendStep() {
useHandlers(::BytecodeListingHandler) useHandlers(::BytecodeListingHandler)
} }
fun HandlersStepBuilder<BinaryArtifacts.Jvm>.boxHandlersForBackendStep() { fun HandlersStepBuilder<BinaryArtifacts.Jvm, ArtifactKinds.Jvm>.boxHandlersForBackendStep() {
useHandlers(::JvmBoxRunner) useHandlers(::JvmBoxRunner)
} }
fun HandlersStepBuilder<BinaryArtifacts.Jvm>.steppingHandlersForBackendStep() { fun HandlersStepBuilder<BinaryArtifacts.Jvm, ArtifactKinds.Jvm>.steppingHandlersForBackendStep() {
useHandlers(::SteppingDebugRunner) useHandlers(::SteppingDebugRunner)
} }
fun HandlersStepBuilder<BinaryArtifacts.Jvm>.localVariableHandlersForBackendStep() { fun HandlersStepBuilder<BinaryArtifacts.Jvm, ArtifactKinds.Jvm>.localVariableHandlersForBackendStep() {
useHandlers(::LocalVariableDebugRunner) useHandlers(::LocalVariableDebugRunner)
} }
fun HandlersStepBuilder<ClassicFrontendOutputArtifact>.commonClassicFrontendHandlersForCodegenTest() { fun HandlersStepBuilder<ClassicFrontendOutputArtifact, FrontendKinds.ClassicFrontend>.commonClassicFrontendHandlersForCodegenTest() {
useHandlers( useHandlers(
::NoCompilationErrorsHandler, ::NoCompilationErrorsHandler,
) )
} }
fun HandlersStepBuilder<FirOutputArtifact>.commonFirHandlersForCodegenTest() { fun HandlersStepBuilder<FirOutputArtifact, FrontendKinds.FIR>.commonFirHandlersForCodegenTest() {
useHandlers( useHandlers(
::NoFirCompilationErrorsHandler, ::NoFirCompilationErrorsHandler,
) )
} }
fun HandlersStepBuilder<BinaryArtifacts.Jvm>.commonBackendHandlersForCodegenTest() { fun HandlersStepBuilder<BinaryArtifacts.Jvm, ArtifactKinds.Jvm>.commonBackendHandlersForCodegenTest() {
useHandlers( useHandlers(
::NoJvmSpecificCompilationErrorsHandler, ::NoJvmSpecificCompilationErrorsHandler,
::DxCheckerHandler, ::DxCheckerHandler,
) )
} }
fun HandlersStepBuilder<BinaryArtifacts.Jvm>.inlineHandlers() { fun HandlersStepBuilder<BinaryArtifacts.Jvm, ArtifactKinds.Jvm>.inlineHandlers() {
useHandlers( useHandlers(
::BytecodeInliningHandler, ::BytecodeInliningHandler,
::SMAPDumpHandler ::SMAPDumpHandler
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.parsing.parseBoolean
import org.jetbrains.kotlin.test.Constructor import org.jetbrains.kotlin.test.Constructor
import org.jetbrains.kotlin.test.TargetBackend import org.jetbrains.kotlin.test.TargetBackend
import org.jetbrains.kotlin.test.backend.ir.IrBackendInput import org.jetbrains.kotlin.test.backend.ir.IrBackendInput
import org.jetbrains.kotlin.test.bind
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.builders.configureJsArtifactsHandlersStep import org.jetbrains.kotlin.test.builders.configureJsArtifactsHandlersStep
import org.jetbrains.kotlin.test.builders.jsArtifactsHandlersStep import org.jetbrains.kotlin.test.builders.jsArtifactsHandlersStep
@@ -207,7 +208,9 @@ open class AbstractIrJsSteppingTest : AbstractJsIrTest(
} }
useAdditionalSourceProviders(::JsSteppingTestAdditionalSourceProvider) useAdditionalSourceProviders(::JsSteppingTestAdditionalSourceProvider)
jsArtifactsHandlersStep { jsArtifactsHandlersStep {
useHandlers({ JsDebugRunner(it, localVariables = false) }) useHandlers(
::JsDebugRunner.bind(false)
)
} }
} }
} }
@@ -223,7 +226,9 @@ open class AbstractIrJsLocalVariableTest : AbstractJsIrTest(
} }
useAdditionalSourceProviders(::JsSteppingTestAdditionalSourceProvider) useAdditionalSourceProviders(::JsSteppingTestAdditionalSourceProvider)
jsArtifactsHandlersStep { jsArtifactsHandlersStep {
useHandlers({ JsDebugRunner(it, localVariables = true) }) useHandlers(
::JsDebugRunner.bind(true)
)
} }
} }
} }