Check pre- and postconditions on phases

This commit is contained in:
Georgy Bronnikov
2019-02-15 06:43:46 +03:00
parent 48433110a4
commit da13d3288e
8 changed files with 245 additions and 129 deletions
@@ -238,6 +238,18 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
) )
var profilePhases: Boolean by FreezableVar(false) var profilePhases: Boolean by FreezableVar(false)
@Argument(
value = "-Xcheck-conditions",
description = "Check pre- and postconditions on phases"
)
var checkPhaseConditions: Boolean by FreezableVar(false)
@Argument(
value = "-Xcheck-sticky-conditions",
description = "Run sticky condition checks on subsequent phases as well. Implies -Xcheck-conditions"
)
var checkStickyConditions: Boolean by FreezableVar(false)
open fun configureAnalysisFlags(collector: MessageCollector): MutableMap<AnalysisFlag<*>, Any> { open fun configureAnalysisFlags(collector: MessageCollector): MutableMap<AnalysisFlag<*>, Any> {
return HashMap<AnalysisFlag<*>, Any>().apply { return HashMap<AnalysisFlag<*>, Any>().apply {
put(AnalysisFlags.skipMetadataVersionCheck, skipMetadataVersionCheck) put(AnalysisFlags.skipMetadataVersionCheck, skipMetadataVersionCheck)
@@ -53,6 +53,8 @@ fun <A : CommonCompilerArguments> CompilerConfiguration.setupCommonArguments(
} }
put(CommonConfigurationKeys.PROFILE_PHASES, arguments.profilePhases) put(CommonConfigurationKeys.PROFILE_PHASES, arguments.profilePhases)
put(CommonConfigurationKeys.CHECK_PHASE_CONDITIONS, arguments.checkPhaseConditions or arguments.checkStickyConditions)
put(CommonConfigurationKeys.CHECK_STICKY_CONDITIONS, arguments.checkStickyConditions)
} }
fun <A : CommonCompilerArguments> CompilerConfiguration.setupLanguageVersionSettings(arguments: A) { fun <A : CommonCompilerArguments> CompilerConfiguration.setupLanguageVersionSettings(arguments: A) {
@@ -72,6 +72,12 @@ object CommonConfigurationKeys {
@JvmField @JvmField
val PROFILE_PHASES = CompilerConfigurationKey.create<Boolean>("profile backend phase execution") val PROFILE_PHASES = CompilerConfigurationKey.create<Boolean>("profile backend phase execution")
@JvmField
val CHECK_PHASE_CONDITIONS = CompilerConfigurationKey.create<Boolean>("run pre- and postcondition checkers for phases")
@JvmField
val CHECK_STICKY_CONDITIONS = CompilerConfigurationKey.create<Boolean>("run sticky postcondition checkers on subsequent phases as well")
@JvmField @JvmField
val EXCLUDED_ELEMENTS_FROM_DUMPING = CompilerConfigurationKey.create<Set<String>>("lowering elements which shouldn't be dumped at all") val EXCLUDED_ELEMENTS_FROM_DUMPING = CompilerConfigurationKey.create<Set<String>>("lowering elements which shouldn't be dumped at all")
} }
@@ -8,22 +8,30 @@ package org.jetbrains.kotlin.backend.common.phaser
import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.CommonBackendContext
import kotlin.system.measureTimeMillis import kotlin.system.measureTimeMillis
class PhaserState { class PhaserState<Data>(
val alreadyDone = mutableSetOf<AnyNamedPhase>() val alreadyDone: MutableSet<AnyNamedPhase> = mutableSetOf(),
var depth = 0 var depth: Int = 0,
} val stickyPostconditions: MutableSet<Checker<Data>> = mutableSetOf()
)
fun <R> PhaserState.downlevel(nlevels: Int = 1, block: () -> R): R { // Copy state, forgetting the sticky postconditions (which will not be applicable to the new type)
fun <Input, Output> PhaserState<Input>.changeType() = PhaserState<Output>(alreadyDone, depth, mutableSetOf())
fun <R, D> PhaserState<D>.downlevel(nlevels: Int = 1, block: () -> R): R {
depth += nlevels depth += nlevels
val result = block() val result = block()
depth -= nlevels depth -= nlevels
return result return result
} }
interface CompilerPhase<in Context : CommonBackendContext, in Input, out Output> { interface CompilerPhase<in Context : CommonBackendContext, Input, Output> {
fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: Input): Output fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<Input>, context: Context, input: Input): Output
fun getNamedSubphases(startDepth: Int = 0): List<Pair<Int, NamedCompilerPhase<*, *, *>>> = emptyList() fun getNamedSubphases(startDepth: Int = 0): List<Pair<Int, AnyNamedPhase>> = emptyList()
// In phase trees, `stickyPostconditions` is inherited along the right edge to be used in `then`.
val stickyPostconditions: Set<Checker<Output>> get() = emptySet()
} }
fun <Context: CommonBackendContext, Input, Output> CompilerPhase<Context, Input, Output>.invokeToplevel( fun <Context: CommonBackendContext, Input, Output> CompilerPhase<Context, Input, Output>.invokeToplevel(
@@ -34,14 +42,18 @@ fun <Context: CommonBackendContext, Input, Output> CompilerPhase<Context, Input
interface SameTypeCompilerPhase<in Context: CommonBackendContext, Data> : CompilerPhase<Context, Data, Data> interface SameTypeCompilerPhase<in Context: CommonBackendContext, Data> : CompilerPhase<Context, Data, Data>
interface NamedCompilerPhase<in Context : CommonBackendContext, in Input, out Output> : CompilerPhase<Context, Input, Output> { // A failing checker should just throw an exception.
typealias Checker<Data> = (Data) -> Unit
interface NamedCompilerPhase<in Context : CommonBackendContext, Input, Output> : CompilerPhase<Context, Input, Output> {
val name: String val name: String
val description: String val description: String
val prerequisite: Set<AnyNamedPhase> get() = emptySet() val prerequisite: Set<AnyNamedPhase> get() = emptySet()
val preconditions: Set<Checker<Input>>
val postconditions: Set<Checker<Output>>
} }
typealias AnyNamedPhase = NamedCompilerPhase<*, *, *> typealias AnyNamedPhase = NamedCompilerPhase<*, *, *>
enum class BeforeOrAfter { BEFORE, AFTER } enum class BeforeOrAfter { BEFORE, AFTER }
interface PhaseDumperVerifier<in Context : CommonBackendContext, Data> { interface PhaseDumperVerifier<in Context : CommonBackendContext, Data> {
@@ -53,13 +65,16 @@ abstract class AbstractNamedPhaseWrapper<in Context : CommonBackendContext, Inpu
override val name: String, override val name: String,
override val description: String, override val description: String,
override val prerequisite: Set<AnyNamedPhase>, override val prerequisite: Set<AnyNamedPhase>,
private val nlevels: Int = 0, private val lower: CompilerPhase<Context, Input, Output>,
private val lower: CompilerPhase<Context, Input, Output> override val preconditions: Set<Checker<Input>> = emptySet(),
override val postconditions: Set<Checker<Output>> = emptySet(),
override val stickyPostconditions: Set<Checker<Output>> = emptySet(),
private val nlevels: Int = 0
) : NamedCompilerPhase<Context, Input, Output> { ) : NamedCompilerPhase<Context, Input, Output> {
abstract val inputDumperVerifier: PhaseDumperVerifier<Context, Input> abstract val inputDumperVerifier: PhaseDumperVerifier<Context, Input>
abstract val outputDumperVerifier: PhaseDumperVerifier<Context, Output> abstract val outputDumperVerifier: PhaseDumperVerifier<Context, Output>
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: Input): Output { override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<Input>, context: Context, input: Input): Output {
if (this is SameTypeCompilerPhase<*, *> && if (this is SameTypeCompilerPhase<*, *> &&
this !in phaseConfig.enabled this !in phaseConfig.enabled
) { ) {
@@ -71,7 +86,7 @@ abstract class AbstractNamedPhaseWrapper<in Context : CommonBackendContext, Inpu
runBefore(phaseConfig, context, input) runBefore(phaseConfig, context, input)
val output = runBody(phaseConfig, phaserState, context, input) val output = runBody(phaseConfig, phaserState, context, input)
runAfter(phaseConfig, context, output) runAfter(phaseConfig, phaserState, context, output)
phaserState.alreadyDone.add(this) phaserState.alreadyDone.add(this)
@@ -81,9 +96,12 @@ abstract class AbstractNamedPhaseWrapper<in Context : CommonBackendContext, Inpu
private fun runBefore(phaseConfig: PhaseConfig, context: Context, input: Input) { private fun runBefore(phaseConfig: PhaseConfig, context: Context, input: Input) {
checkAndRun(phaseConfig.toDumpStateBefore) { inputDumperVerifier.dump(this, context, input, BeforeOrAfter.BEFORE) } checkAndRun(phaseConfig.toDumpStateBefore) { inputDumperVerifier.dump(this, context, input, BeforeOrAfter.BEFORE) }
checkAndRun(phaseConfig.toValidateStateBefore) { inputDumperVerifier.verify(context, input) } checkAndRun(phaseConfig.toValidateStateBefore) { inputDumperVerifier.verify(context, input) }
if (phaseConfig.checkConditions) {
for (pre in preconditions) pre(input)
}
} }
private fun runBody(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: Input): Output { private fun runBody(phaseConfig: PhaseConfig, phaserState: PhaserState<Input>, context: Context, input: Input): Output {
return if (phaseConfig.needProfiling) { return if (phaseConfig.needProfiling) {
runAndProfile(phaseConfig, phaserState, context, input) runAndProfile(phaseConfig, phaserState, context, input)
} else { } else {
@@ -93,12 +111,20 @@ abstract class AbstractNamedPhaseWrapper<in Context : CommonBackendContext, Inpu
} }
} }
private fun runAfter(phaseConfig: PhaseConfig, context: Context, output: Output) { private fun runAfter(phaseConfig: PhaseConfig, phaserState: PhaserState<Input>, context: Context, output: Output) {
checkAndRun(phaseConfig.toDumpStateAfter) { outputDumperVerifier.dump(this, context, output, BeforeOrAfter.AFTER) } checkAndRun(phaseConfig.toDumpStateAfter) { outputDumperVerifier.dump(this, context, output, BeforeOrAfter.AFTER) }
checkAndRun(phaseConfig.toValidateStateAfter) { outputDumperVerifier.verify(context, output) } checkAndRun(phaseConfig.toValidateStateAfter) { outputDumperVerifier.verify(context, output) }
if (phaseConfig.checkConditions) {
for (post in postconditions) post(output)
for (post in stickyPostconditions) post(output)
if (phaseConfig.checkStickyConditions && this is SameTypeCompilerPhase<*, *>) {
val phaserStateO = phaserState as PhaserState<Output>
for (post in phaserStateO.stickyPostconditions) post(output)
}
}
} }
private fun runAndProfile(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, source: Input): Output { private fun runAndProfile(phaseConfig: PhaseConfig, phaserState: PhaserState<Input>, context: Context, source: Input): Output {
var result: Output? = null var result: Output? = null
val msec = measureTimeMillis { val msec = measureTimeMillis {
result = phaserState.downlevel(nlevels) { result = phaserState.downlevel(nlevels) {
@@ -124,10 +150,15 @@ class SameTypeNamedPhaseWrapper<in Context : CommonBackendContext, Data>(
name: String, name: String,
description: String, description: String,
prerequisite: Set<AnyNamedPhase>, prerequisite: Set<AnyNamedPhase>,
nlevels: Int = 0,
lower: CompilerPhase<Context, Data, Data>, lower: CompilerPhase<Context, Data, Data>,
preconditions: Set<Checker<Data>> = emptySet(),
postconditions: Set<Checker<Data>> = emptySet(),
stickyPostconditions: Set<Checker<Data>> = lower.stickyPostconditions,
nlevels: Int = 0,
val dumperVerifier: PhaseDumperVerifier<Context, Data> val dumperVerifier: PhaseDumperVerifier<Context, Data>
) : AbstractNamedPhaseWrapper<Context, Data, Data>(name, description, prerequisite, nlevels, lower), SameTypeCompilerPhase<Context, Data> { ) : AbstractNamedPhaseWrapper<Context, Data, Data>(
name, description, prerequisite, lower, preconditions, postconditions, stickyPostconditions, nlevels
), SameTypeCompilerPhase<Context, Data> {
override val inputDumperVerifier get() = dumperVerifier override val inputDumperVerifier get() = dumperVerifier
override val outputDumperVerifier get() = dumperVerifier override val outputDumperVerifier get() = dumperVerifier
} }
@@ -8,155 +8,218 @@ import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
// Phase composition. // Phase composition.
infix fun <Context : CommonBackendContext, Input, Mid, Output> CompilerPhase<Context, Input, Mid>.then( infix fun <Context : CommonBackendContext, Input, Mid, Output> CompilerPhase<Context, Input, Mid>.then(
other: CompilerPhase<Context, Mid, Output> other: CompilerPhase<Context, Mid, Output>
) = object : CompilerPhase<Context, Input, Output> { ) = object : CompilerPhase<Context, Input, Output> {
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: Input): Output = override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<Input>, context: Context, input: Input): Output =
this@then.invoke(phaseConfig, phaserState, context, input).let { mid -> this@then.invoke(phaseConfig, phaserState, context, input).let { mid ->
other.invoke(phaseConfig, phaserState, context, mid) val newPhaserState = if (other is SameTypeCompilerPhase<*, *>)
} // Keep `stickyPostconditions`.
phaserState as PhaserState<Mid>
else
// Discard `stickyPostcoditions`, they are useless since data type is changing.
phaserState.changeType()
newPhaserState.stickyPostconditions.addAll(this@then.stickyPostconditions)
other.invoke(phaseConfig, newPhaserState, context, mid)
}
override fun getNamedSubphases(startDepth: Int) = override fun getNamedSubphases(startDepth: Int) =
this@then.getNamedSubphases(startDepth) + other.getNamedSubphases(startDepth) this@then.getNamedSubphases(startDepth) + other.getNamedSubphases(startDepth)
override val stickyPostconditions get() = other.stickyPostconditions
} }
fun <Context : CommonBackendContext> namedIrModulePhase( fun <Context : CommonBackendContext> namedIrModulePhase(
name: String, name: String,
description: String, description: String,
prerequisite: Set<AnyNamedPhase> = emptySet(), prerequisite: Set<AnyNamedPhase> = emptySet(),
verify: (Context, IrModuleFragment) -> Unit = { _, _ -> }, lower: CompilerPhase<Context, IrModuleFragment, IrModuleFragment>,
nlevels: Int = 1, preconditions: Set<Checker<IrModuleFragment>> = emptySet(),
lower: CompilerPhase<Context, IrModuleFragment, IrModuleFragment> postconditions: Set<Checker<IrModuleFragment>> = emptySet(),
) = SameTypeNamedPhaseWrapper(name, description, prerequisite, nlevels, lower, IrModuleDumperVerifier(verify)) stickyPostconditions: Set<Checker<IrModuleFragment>> = lower.stickyPostconditions,
verify: (Context, IrModuleFragment) -> Unit = { _, _ -> },
nlevels: Int = 1
) = SameTypeNamedPhaseWrapper(
name,
description,
prerequisite,
lower,
preconditions,
postconditions,
stickyPostconditions,
nlevels,
IrModuleDumperVerifier(verify)
)
fun <Context : CommonBackendContext> namedIrFilePhase( fun <Context : CommonBackendContext> namedIrFilePhase(
name: String, name: String,
description: String, description: String,
prerequisite: Set<AnyNamedPhase> = emptySet(), prerequisite: Set<AnyNamedPhase> = emptySet(),
verify: (Context, IrFile) -> Unit = { _, _ -> }, lower: CompilerPhase<Context, IrFile, IrFile>,
nlevels: Int = 1, preconditions: Set<Checker<IrFile>> = emptySet(),
lower: CompilerPhase<Context, IrFile, IrFile> postconditions: Set<Checker<IrFile>> = emptySet(),
) = SameTypeNamedPhaseWrapper(name, description, prerequisite, nlevels, lower, IrFileDumperVerifier(verify)) stickyPostconditions: Set<Checker<IrFile>> = lower.stickyPostconditions,
verify: (Context, IrFile) -> Unit = { _, _ -> },
nlevels: Int = 1
) = SameTypeNamedPhaseWrapper(
name,
description,
prerequisite,
lower,
preconditions,
postconditions,
stickyPostconditions,
nlevels,
IrFileDumperVerifier(verify)
)
fun <Context : CommonBackendContext> namedUnitPhase( fun <Context : CommonBackendContext> namedUnitPhase(
name: String, name: String,
description: String, description: String,
prerequisite: Set<AnyNamedPhase> = emptySet(), prerequisite: Set<AnyNamedPhase> = emptySet(),
nlevels: Int = 1, nlevels: Int = 1,
lower: CompilerPhase<Context, Unit, Unit> lower: CompilerPhase<Context, Unit, Unit>
) = SameTypeNamedPhaseWrapper(name, description, prerequisite, nlevels, lower, EmptyDumperVerifier()) ) = SameTypeNamedPhaseWrapper(
name, description, prerequisite,
lower = lower,
nlevels = nlevels,
dumperVerifier = EmptyDumperVerifier()
)
fun <Context : CommonBackendContext> namedOpUnitPhase( fun <Context : CommonBackendContext> namedOpUnitPhase(
name: String, name: String,
description: String, description: String,
prerequisite: Set<AnyNamedPhase>, prerequisite: Set<AnyNamedPhase>,
op: Context.() -> Unit op: Context.() -> Unit
) = namedUnitPhase( ) = namedUnitPhase(
name, description, prerequisite, name, description, prerequisite,
nlevels = 0, nlevels = 0,
lower = object : SameTypeCompilerPhase<Context, Unit> { lower = object : SameTypeCompilerPhase<Context, Unit> {
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: Unit) { override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<Unit>, context: Context, input: Unit) {
context.op() context.op()
}
} }
}
) )
fun <Context : CommonBackendContext> performByIrFile( fun <Context : CommonBackendContext> performByIrFile(
name: String = "PerformByIrFile", name: String = "PerformByIrFile",
description: String = "Perform phases by IrFile", description: String = "Perform phases by IrFile",
prerequisite: Set<AnyNamedPhase> = emptySet(), prerequisite: Set<AnyNamedPhase> = emptySet(),
verify: (Context, IrModuleFragment) -> Unit = { _, _ -> }, preconditions: Set<Checker<IrModuleFragment>> = emptySet(),
lower: CompilerPhase<Context, IrFile, IrFile> postconditions: Set<Checker<IrModuleFragment>> = emptySet(),
stickyPostconditions: Set<Checker<IrModuleFragment>> = emptySet(),
verify: (Context, IrModuleFragment) -> Unit = { _, _ -> },
lower: CompilerPhase<Context, IrFile, IrFile>
) = namedIrModulePhase( ) = namedIrModulePhase(
name, description, prerequisite, verify, name, description, prerequisite,
nlevels = 1, preconditions = preconditions,
lower = object : SameTypeCompilerPhase<Context, IrModuleFragment> { postconditions = postconditions,
override fun invoke( stickyPostconditions = stickyPostconditions,
phaseConfig: PhaseConfig, verify = verify,
phaserState: PhaserState, nlevels = 1,
context: Context, lower = object : SameTypeCompilerPhase<Context, IrModuleFragment> {
input: IrModuleFragment override fun invoke(
): IrModuleFragment { phaseConfig: PhaseConfig,
for (irFile in input.files) { phaserState: PhaserState<IrModuleFragment>,
lower.invoke(phaseConfig, phaserState, context, irFile) context: Context,
} input: IrModuleFragment
): IrModuleFragment {
// TODO: no guarantee that module identity is preserved by `lower` for (irFile in input.files) {
return input lower.invoke(phaseConfig, phaserState.changeType(), context, irFile)
} }
override fun getNamedSubphases(startDepth: Int) = lower.getNamedSubphases(startDepth) // TODO: no guarantee that module identity is preserved by `lower`
return input
} }
override fun getNamedSubphases(startDepth: Int) = lower.getNamedSubphases(startDepth)
}
) )
fun <Context : CommonBackendContext> makeIrFilePhase( fun <Context : CommonBackendContext> makeIrFilePhase(
lowering: (Context) -> FileLoweringPass, lowering: (Context) -> FileLoweringPass,
name: String, name: String,
description: String, description: String,
prerequisite: Set<AnyNamedPhase> = emptySet(), prerequisite: Set<AnyNamedPhase> = emptySet(),
verify: (Context, IrFile) -> Unit = { _, _ -> } preconditions: Set<Checker<IrFile>> = emptySet(),
postconditions: Set<Checker<IrFile>> = emptySet(),
stickyPostconditions: Set<Checker<IrFile>> = emptySet(),
verify: (Context, IrFile) -> Unit = { _, _ -> }
) = namedIrFilePhase( ) = namedIrFilePhase(
name, description, prerequisite, verify, name, description, prerequisite,
nlevels = 0, preconditions = preconditions,
lower = object : SameTypeCompilerPhase<Context, IrFile> { postconditions = postconditions,
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: IrFile): IrFile { stickyPostconditions = stickyPostconditions,
lowering(context).lower(input) verify = verify,
return input nlevels = 0,
} lower = object : SameTypeCompilerPhase<Context, IrFile> {
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<IrFile>, context: Context, input: IrFile): IrFile {
lowering(context).lower(input)
return input
} }
}
) )
fun <Context : CommonBackendContext> makeIrModulePhase( fun <Context : CommonBackendContext> makeIrModulePhase(
lowering: (Context) -> FileLoweringPass, lowering: (Context) -> FileLoweringPass,
name: String, name: String,
description: String, description: String,
prerequisite: Set<AnyNamedPhase> = emptySet(), prerequisite: Set<AnyNamedPhase> = emptySet(),
verify: (Context, IrModuleFragment) -> Unit = { _, _ -> } preconditions: Set<Checker<IrModuleFragment>> = emptySet(),
postconditions: Set<Checker<IrModuleFragment>> = emptySet(),
stickyPostconditions: Set<Checker<IrModuleFragment>> = emptySet(),
verify: (Context, IrModuleFragment) -> Unit = { _, _ -> }
) = namedIrModulePhase( ) = namedIrModulePhase(
name, description, prerequisite, verify, name, description, prerequisite,
nlevels = 0, preconditions=preconditions,
lower = object : SameTypeCompilerPhase<Context, IrModuleFragment> { postconditions = postconditions,
override fun invoke( stickyPostconditions = stickyPostconditions,
phaseConfig: PhaseConfig, verify = verify,
phaserState: PhaserState, nlevels = 0,
context: Context, lower = object : SameTypeCompilerPhase<Context, IrModuleFragment> {
input: IrModuleFragment override fun invoke(
): IrModuleFragment { phaseConfig: PhaseConfig,
lowering(context).lower(input) phaserState: PhaserState<IrModuleFragment>,
return input context: Context,
} input: IrModuleFragment
): IrModuleFragment {
lowering(context).lower(input)
return input
} }
}
) )
fun <Context : CommonBackendContext, Input> unitPhase( fun <Context : CommonBackendContext, Input> unitPhase(
name: String, name: String,
description: String, description: String,
prerequisite: Set<AnyNamedPhase>, prerequisite: Set<AnyNamedPhase>,
op: Context.() -> Unit preconditions: Set<Checker<Input>>,
op: Context.() -> Unit
) = ) =
object : AbstractNamedPhaseWrapper<Context, Input, Unit>( object : AbstractNamedPhaseWrapper<Context, Input, Unit>(
name, description, prerequisite, name, description, prerequisite,
nlevels = 0, preconditions = preconditions,
lower = object : CompilerPhase<Context, Input, Unit> { nlevels = 0,
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: Input) { lower = object : CompilerPhase<Context, Input, Unit> {
context.op() override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<Input>, context: Context, input: Input) {
} context.op()
} }
) {
override val inputDumperVerifier = EmptyDumperVerifier<Context, Input>()
override val outputDumperVerifier = EmptyDumperVerifier<Context, Unit>()
} }
) {
override val inputDumperVerifier = EmptyDumperVerifier<Context, Input>()
override val outputDumperVerifier = EmptyDumperVerifier<Context, Unit>()
}
fun <Context : CommonBackendContext, Input> unitSink() = object : CompilerPhase<Context, Input, Unit> { fun <Context : CommonBackendContext, Input> unitSink() = object : CompilerPhase<Context, Input, Unit> {
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: Input) {} override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<Input>, context: Context, input: Input) {}
} }
// Intermediate phases to change the object of transformations // Intermediate phases to change the object of transformations
fun <Context : CommonBackendContext, OldData, NewData> takeFromContext(op: (Context) -> NewData) = fun <Context : CommonBackendContext, OldData, NewData> takeFromContext(op: (Context) -> NewData) =
object : CompilerPhase<Context, OldData, NewData> { object : CompilerPhase<Context, OldData, NewData> {
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: OldData) = op(context) override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<OldData>, context: Context, input: OldData) = op(context)
} }
fun <Context : CommonBackendContext, OldData, NewData> transform(op: (OldData) -> NewData) = fun <Context : CommonBackendContext, OldData, NewData> transform(op: (OldData) -> NewData) =
object : CompilerPhase<Context, OldData, NewData> { object : CompilerPhase<Context, OldData, NewData> {
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: OldData) = op(input) override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<OldData>, context: Context, input: OldData) = op(input)
} }
@@ -35,6 +35,8 @@ class PhaseConfig(private val compoundPhase: CompilerPhase<*, *, *>, config: Com
} }
val needProfiling = config.getBoolean(CommonConfigurationKeys.PROFILE_PHASES) val needProfiling = config.getBoolean(CommonConfigurationKeys.PROFILE_PHASES)
val checkConditions = config.getBoolean(CommonConfigurationKeys.CHECK_PHASE_CONDITIONS)
val checkStickyConditions = config.getBoolean(CommonConfigurationKeys.CHECK_STICKY_CONDITIONS)
fun known(name: String): String { fun known(name: String): String {
if (phases[name] == null) { if (phases[name] == null) {
@@ -57,7 +57,7 @@ private fun makeCustomJsModulePhase(
lower = object : SameTypeCompilerPhase<JsIrBackendContext, IrModuleFragment> { lower = object : SameTypeCompilerPhase<JsIrBackendContext, IrModuleFragment> {
override fun invoke( override fun invoke(
phaseConfig: PhaseConfig, phaseConfig: PhaseConfig,
phaserState: PhaserState, phaserState: PhaserState<IrModuleFragment>,
context: JsIrBackendContext, context: JsIrBackendContext,
input: IrModuleFragment input: IrModuleFragment
): IrModuleFragment { ): IrModuleFragment {
@@ -26,7 +26,7 @@ import org.jetbrains.kotlin.ir.visitors.acceptVoid
private fun makePatchParentsPhase(number: Int) = namedIrFilePhase( private fun makePatchParentsPhase(number: Int) = namedIrFilePhase(
lower = object : SameTypeCompilerPhase<CommonBackendContext, IrFile> { lower = object : SameTypeCompilerPhase<CommonBackendContext, IrFile> {
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: CommonBackendContext, input: IrFile): IrFile { override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<IrFile>, context: CommonBackendContext, input: IrFile): IrFile {
input.acceptVoid(PatchDeclarationParentsVisitor()) input.acceptVoid(PatchDeclarationParentsVisitor())
return input return input
} }