IR: simplify phaser code a little
- merge NamedCompilerPhase, SameTypeNamedPhaseWrapper, AbstractNamedPhaseWrapper and inherit it from SameTypeCompilerPhase - inline some functions to simplify stacktraces - reformat and fix inspections
This commit is contained in:
+33
-71
@@ -18,8 +18,7 @@ class PhaserState<Data>(
|
||||
// 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, phaseCount, mutableSetOf())
|
||||
|
||||
|
||||
fun <R, D> PhaserState<D>.downlevel(nlevels: Int = 1, block: () -> R): R {
|
||||
inline fun <R, D> PhaserState<D>.downlevel(nlevels: Int, block: () -> R): R {
|
||||
depth += nlevels
|
||||
val result = block()
|
||||
depth -= nlevels
|
||||
@@ -35,28 +34,19 @@ interface CompilerPhase<in Context : CommonBackendContext, Input, Output> {
|
||||
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(
|
||||
phaseConfig: PhaseConfig,
|
||||
context: Context,
|
||||
input: Input
|
||||
): Output = invoke(phaseConfig, PhaserState(), context, input)
|
||||
|
||||
interface SameTypeCompilerPhase<in Context: CommonBackendContext, Data> : CompilerPhase<Context, Data, Data>
|
||||
interface SameTypeCompilerPhase<in Context : CommonBackendContext, Data> : CompilerPhase<Context, Data, Data>
|
||||
|
||||
// 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 description: String
|
||||
val prerequisite: Set<AnyNamedPhase> get() = emptySet()
|
||||
val preconditions: Set<Checker<Input>>
|
||||
val postconditions: Set<Checker<Output>>
|
||||
val actionsBefore: Set<Action<Input, Context>>
|
||||
val actionsAfter: Set<Action<Output, Context>>
|
||||
}
|
||||
typealias AnyNamedPhase = NamedCompilerPhase<*, *>
|
||||
|
||||
typealias AnyNamedPhase = NamedCompilerPhase<*, *, *>
|
||||
enum class BeforeOrAfter { BEFORE, AFTER }
|
||||
|
||||
data class ActionState(
|
||||
@@ -74,25 +64,20 @@ infix operator fun <Data, Context> Action<Data, Context>.plus(other: Action<Data
|
||||
other(phaseState, data, context)
|
||||
}
|
||||
|
||||
abstract class AbstractNamedPhaseWrapper<in Context : CommonBackendContext, Input, Output>(
|
||||
override val name: String,
|
||||
override val description: String,
|
||||
override val prerequisite: Set<AnyNamedPhase>,
|
||||
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(),
|
||||
override val actionsBefore: Set<Action<Input, Context>> = emptySet(),
|
||||
override val actionsAfter: Set<Action<Output, Context>> = emptySet(),
|
||||
class NamedCompilerPhase<in Context : CommonBackendContext, Data>(
|
||||
val name: String,
|
||||
val description: String,
|
||||
val prerequisite: Set<AnyNamedPhase>,
|
||||
private val lower: CompilerPhase<Context, Data, Data>,
|
||||
val preconditions: Set<Checker<Data>> = emptySet(),
|
||||
val postconditions: Set<Checker<Data>> = emptySet(),
|
||||
override val stickyPostconditions: Set<Checker<Data>> = emptySet(),
|
||||
private val actions: Set<Action<Data, Context>> = emptySet(),
|
||||
private val nlevels: Int = 0
|
||||
) : NamedCompilerPhase<Context, Input, Output> {
|
||||
|
||||
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<Input>, context: Context, input: Input): Output {
|
||||
if (this is SameTypeCompilerPhase<*, *> &&
|
||||
this !in phaseConfig.enabled
|
||||
) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return input as Output
|
||||
) : SameTypeCompilerPhase<Context, Data> {
|
||||
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<Data>, context: Context, input: Data): Data {
|
||||
if (this !in phaseConfig.enabled) {
|
||||
return input
|
||||
}
|
||||
|
||||
assert(phaserState.alreadyDone.containsAll(prerequisite)) {
|
||||
@@ -102,7 +87,13 @@ abstract class AbstractNamedPhaseWrapper<in Context : CommonBackendContext, Inpu
|
||||
context.inVerbosePhase = this in phaseConfig.verbose
|
||||
|
||||
runBefore(phaseConfig, phaserState, context, input)
|
||||
val output = runBody(phaseConfig, phaserState, context, input)
|
||||
val output = if (phaseConfig.needProfiling) {
|
||||
runAndProfile(phaseConfig, phaserState, context, input)
|
||||
} else {
|
||||
phaserState.downlevel(nlevels) {
|
||||
lower.invoke(phaseConfig, phaserState, context, input)
|
||||
}
|
||||
}
|
||||
runAfter(phaseConfig, phaserState, context, output)
|
||||
|
||||
phaserState.alreadyDone.add(this)
|
||||
@@ -111,41 +102,30 @@ abstract class AbstractNamedPhaseWrapper<in Context : CommonBackendContext, Inpu
|
||||
return output
|
||||
}
|
||||
|
||||
private fun runBefore(phaseConfig: PhaseConfig, phaserState: PhaserState<Input>, context: Context, input: Input) {
|
||||
private fun runBefore(phaseConfig: PhaseConfig, phaserState: PhaserState<Data>, context: Context, input: Data) {
|
||||
val state = ActionState(phaseConfig, this, phaserState.phaseCount, BeforeOrAfter.BEFORE)
|
||||
for (action in actionsBefore) action(state, input, context)
|
||||
for (action in actions) action(state, input, context)
|
||||
|
||||
if (phaseConfig.checkConditions) {
|
||||
for (pre in preconditions) pre(input)
|
||||
}
|
||||
}
|
||||
|
||||
private fun runBody(phaseConfig: PhaseConfig, phaserState: PhaserState<Input>, context: Context, input: Input): Output {
|
||||
return if (phaseConfig.needProfiling) {
|
||||
runAndProfile(phaseConfig, phaserState, context, input)
|
||||
} else {
|
||||
phaserState.downlevel(nlevels) {
|
||||
lower.invoke(phaseConfig, phaserState, context, input)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun runAfter(phaseConfig: PhaseConfig, phaserState: PhaserState<Input>, context: Context, output: Output) {
|
||||
private fun runAfter(phaseConfig: PhaseConfig, phaserState: PhaserState<Data>, context: Context, output: Data) {
|
||||
val state = ActionState(phaseConfig, this, phaserState.phaseCount, BeforeOrAfter.AFTER)
|
||||
for (action in actionsAfter) action(state, output, context)
|
||||
for (action in actions) action(state, output, context)
|
||||
|
||||
if (phaseConfig.checkConditions) {
|
||||
for (post in postconditions) post(output)
|
||||
for (post in stickyPostconditions) post(output)
|
||||
if (phaseConfig.checkStickyConditions && this is SameTypeCompilerPhase<*, *>) {
|
||||
@Suppress("UNCHECKED_CAST") val phaserStateO = phaserState as PhaserState<Output>
|
||||
for (post in phaserStateO.stickyPostconditions) post(output)
|
||||
if (phaseConfig.checkStickyConditions) {
|
||||
for (post in phaserState.stickyPostconditions) post(output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun runAndProfile(phaseConfig: PhaseConfig, phaserState: PhaserState<Input>, context: Context, source: Input): Output {
|
||||
var result: Output? = null
|
||||
private fun runAndProfile(phaseConfig: PhaseConfig, phaserState: PhaserState<Data>, context: Context, source: Data): Data {
|
||||
var result: Data? = null
|
||||
val msec = measureTimeMillis {
|
||||
result = phaserState.downlevel(nlevels) {
|
||||
lower.invoke(phaseConfig, phaserState, context, source)
|
||||
@@ -156,26 +136,8 @@ abstract class AbstractNamedPhaseWrapper<in Context : CommonBackendContext, Inpu
|
||||
return result!!
|
||||
}
|
||||
|
||||
private fun checkAndRun(set: Set<AnyNamedPhase>, block: () -> Unit) {
|
||||
if (this in set) block()
|
||||
}
|
||||
|
||||
override fun getNamedSubphases(startDepth: Int): List<Pair<Int, NamedCompilerPhase<*, *, *>>> =
|
||||
override fun getNamedSubphases(startDepth: Int): List<Pair<Int, NamedCompilerPhase<*, *>>> =
|
||||
listOf(startDepth to this) + lower.getNamedSubphases(startDepth + nlevels)
|
||||
|
||||
override fun toString() = "Compiler Phase @$name"
|
||||
}
|
||||
|
||||
class SameTypeNamedPhaseWrapper<in Context : CommonBackendContext, Data>(
|
||||
name: String,
|
||||
description: String,
|
||||
prerequisite: Set<AnyNamedPhase>,
|
||||
lower: CompilerPhase<Context, Data, Data>,
|
||||
preconditions: Set<Checker<Data>> = emptySet(),
|
||||
postconditions: Set<Checker<Data>> = emptySet(),
|
||||
stickyPostconditions: Set<Checker<Data>> = lower.stickyPostconditions,
|
||||
actions: Set<Action<Data, Context>> = emptySet(),
|
||||
nlevels: Int = 0
|
||||
) : AbstractNamedPhaseWrapper<Context, Data, Data>(
|
||||
name, description, prerequisite, lower, preconditions, postconditions, stickyPostconditions, actions, actions, nlevels
|
||||
), SameTypeCompilerPhase<Context, Data>
|
||||
|
||||
+9
-24
@@ -23,7 +23,7 @@ private class CompositePhase<Context : CommonBackendContext, Input, Output>(
|
||||
var result = phases.first().invoke(phaseConfig, currentState, context, input)
|
||||
for ((previous, next) in phases.zip(phases.drop(1))) {
|
||||
if (next !is SameTypeCompilerPhase<*, *>) {
|
||||
// Discard `stickyPostcoditions`, they are useless since data type is changing.
|
||||
// Discard `stickyPostconditions`, they are useless since data type is changing.
|
||||
currentState = currentState.changeType()
|
||||
}
|
||||
currentState.stickyPostconditions.addAll(previous.stickyPostconditions)
|
||||
@@ -58,7 +58,7 @@ fun <Context : CommonBackendContext> namedIrModulePhase(
|
||||
stickyPostconditions: Set<Checker<IrModuleFragment>> = lower.stickyPostconditions,
|
||||
actions: Set<Action<IrModuleFragment, Context>> = setOf(defaultDumper, validationAction),
|
||||
nlevels: Int = 1
|
||||
) = SameTypeNamedPhaseWrapper(
|
||||
) = NamedCompilerPhase(
|
||||
name,
|
||||
description,
|
||||
prerequisite,
|
||||
@@ -80,7 +80,7 @@ fun <Context : CommonBackendContext> namedIrFilePhase(
|
||||
stickyPostconditions: Set<Checker<IrFile>> = lower.stickyPostconditions,
|
||||
actions: Set<Action<IrFile, Context>> = setOf(defaultDumper, validationAction),
|
||||
nlevels: Int = 1
|
||||
) = SameTypeNamedPhaseWrapper(
|
||||
) = NamedCompilerPhase(
|
||||
name,
|
||||
description,
|
||||
prerequisite,
|
||||
@@ -102,7 +102,7 @@ fun <Context : CommonBackendContext, Element : IrElement> makeCustomPhase(
|
||||
stickyPostconditions: Set<Checker<Element>> = emptySet(),
|
||||
actions: Set<Action<Element, Context>> = setOf(defaultDumper, validationAction),
|
||||
nlevels: Int = 1
|
||||
) = SameTypeNamedPhaseWrapper(
|
||||
) = NamedCompilerPhase(
|
||||
name,
|
||||
description,
|
||||
prerequisite,
|
||||
@@ -130,12 +130,13 @@ fun <Context : CommonBackendContext> namedUnitPhase(
|
||||
prerequisite: Set<AnyNamedPhase> = emptySet(),
|
||||
nlevels: Int = 1,
|
||||
lower: CompilerPhase<Context, Unit, Unit>
|
||||
) = SameTypeNamedPhaseWrapper(
|
||||
) = NamedCompilerPhase(
|
||||
name, description, prerequisite,
|
||||
lower = lower,
|
||||
nlevels = nlevels
|
||||
)
|
||||
|
||||
@Suppress("unused") // Used in kotlin-native
|
||||
fun <Context : CommonBackendContext> namedOpUnitPhase(
|
||||
name: String,
|
||||
description: String,
|
||||
@@ -225,7 +226,7 @@ fun <Context : CommonBackendContext> makeIrModulePhase(
|
||||
actions: Set<Action<IrModuleFragment, Context>> = setOf(defaultDumper, validationAction)
|
||||
) = namedIrModulePhase(
|
||||
name, description, prerequisite,
|
||||
preconditions=preconditions,
|
||||
preconditions = preconditions,
|
||||
postconditions = postconditions,
|
||||
stickyPostconditions = stickyPostconditions,
|
||||
actions = actions,
|
||||
@@ -243,29 +244,13 @@ fun <Context : CommonBackendContext> makeIrModulePhase(
|
||||
}
|
||||
)
|
||||
|
||||
fun <Context : CommonBackendContext, Input> unitPhase(
|
||||
name: String,
|
||||
description: String,
|
||||
prerequisite: Set<AnyNamedPhase>,
|
||||
preconditions: Set<Checker<Input>>,
|
||||
op: Context.() -> Unit
|
||||
) =
|
||||
object : AbstractNamedPhaseWrapper<Context, Input, Unit>(
|
||||
name, description, prerequisite,
|
||||
preconditions = preconditions,
|
||||
nlevels = 0,
|
||||
lower = object : CompilerPhase<Context, Input, Unit> {
|
||||
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<Input>, context: Context, input: Input) {
|
||||
context.op()
|
||||
}
|
||||
}
|
||||
) {}
|
||||
|
||||
@Suppress("unused") // Used in kotlin-native
|
||||
fun <Context : CommonBackendContext, Input> unitSink() = object : CompilerPhase<Context, Input, Unit> {
|
||||
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<Input>, context: Context, input: Input) {}
|
||||
}
|
||||
|
||||
// Intermediate phases to change the object of transformations
|
||||
@Suppress("unused") // Used in kotlin-native
|
||||
fun <Context : CommonBackendContext, OldData, NewData> takeFromContext(op: (Context) -> NewData) =
|
||||
object : CompilerPhase<Context, OldData, NewData> {
|
||||
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<OldData>, context: Context, input: OldData) = op(context)
|
||||
|
||||
Reference in New Issue
Block a user