Check pre- and postconditions on phases
This commit is contained in:
+12
@@ -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")
|
||||||
}
|
}
|
||||||
|
|||||||
+50
-19
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
+171
-108
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user