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)
|
||||
|
||||
@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> {
|
||||
return HashMap<AnalysisFlag<*>, Any>().apply {
|
||||
put(AnalysisFlags.skipMetadataVersionCheck, skipMetadataVersionCheck)
|
||||
|
||||
@@ -53,6 +53,8 @@ fun <A : CommonCompilerArguments> CompilerConfiguration.setupCommonArguments(
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
@@ -72,6 +72,12 @@ object CommonConfigurationKeys {
|
||||
@JvmField
|
||||
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
|
||||
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 kotlin.system.measureTimeMillis
|
||||
|
||||
class PhaserState {
|
||||
val alreadyDone = mutableSetOf<AnyNamedPhase>()
|
||||
var depth = 0
|
||||
}
|
||||
class PhaserState<Data>(
|
||||
val alreadyDone: MutableSet<AnyNamedPhase> = mutableSetOf(),
|
||||
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
|
||||
val result = block()
|
||||
depth -= nlevels
|
||||
return result
|
||||
}
|
||||
|
||||
interface CompilerPhase<in Context : CommonBackendContext, in Input, out Output> {
|
||||
fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: Input): Output
|
||||
interface CompilerPhase<in Context : CommonBackendContext, 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(
|
||||
@@ -34,14 +42,18 @@ fun <Context: CommonBackendContext, Input, Output> CompilerPhase<Context, Input
|
||||
|
||||
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 description: String
|
||||
val prerequisite: Set<AnyNamedPhase> get() = emptySet()
|
||||
val preconditions: Set<Checker<Input>>
|
||||
val postconditions: Set<Checker<Output>>
|
||||
}
|
||||
|
||||
typealias AnyNamedPhase = NamedCompilerPhase<*, *, *>
|
||||
|
||||
enum class BeforeOrAfter { BEFORE, AFTER }
|
||||
|
||||
interface PhaseDumperVerifier<in Context : CommonBackendContext, Data> {
|
||||
@@ -53,13 +65,16 @@ abstract class AbstractNamedPhaseWrapper<in Context : CommonBackendContext, Inpu
|
||||
override val name: String,
|
||||
override val description: String,
|
||||
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> {
|
||||
abstract val inputDumperVerifier: PhaseDumperVerifier<Context, Input>
|
||||
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<*, *> &&
|
||||
this !in phaseConfig.enabled
|
||||
) {
|
||||
@@ -71,7 +86,7 @@ abstract class AbstractNamedPhaseWrapper<in Context : CommonBackendContext, Inpu
|
||||
|
||||
runBefore(phaseConfig, context, input)
|
||||
val output = runBody(phaseConfig, phaserState, context, input)
|
||||
runAfter(phaseConfig, context, output)
|
||||
runAfter(phaseConfig, phaserState, context, output)
|
||||
|
||||
phaserState.alreadyDone.add(this)
|
||||
|
||||
@@ -81,9 +96,12 @@ abstract class AbstractNamedPhaseWrapper<in Context : CommonBackendContext, Inpu
|
||||
private fun runBefore(phaseConfig: PhaseConfig, context: Context, input: Input) {
|
||||
checkAndRun(phaseConfig.toDumpStateBefore) { inputDumperVerifier.dump(this, context, input, BeforeOrAfter.BEFORE) }
|
||||
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) {
|
||||
runAndProfile(phaseConfig, phaserState, context, input)
|
||||
} 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.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
|
||||
val msec = measureTimeMillis {
|
||||
result = phaserState.downlevel(nlevels) {
|
||||
@@ -124,10 +150,15 @@ class SameTypeNamedPhaseWrapper<in Context : CommonBackendContext, Data>(
|
||||
name: String,
|
||||
description: String,
|
||||
prerequisite: Set<AnyNamedPhase>,
|
||||
nlevels: Int = 0,
|
||||
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>
|
||||
) : 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 outputDumperVerifier get() = dumperVerifier
|
||||
}
|
||||
|
||||
+171
-108
@@ -8,155 +8,218 @@ import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
|
||||
// Phase composition.
|
||||
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> {
|
||||
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: Input): Output =
|
||||
this@then.invoke(phaseConfig, phaserState, context, input).let { mid ->
|
||||
other.invoke(phaseConfig, phaserState, context, mid)
|
||||
}
|
||||
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<Input>, context: Context, input: Input): Output =
|
||||
this@then.invoke(phaseConfig, phaserState, context, input).let { 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) =
|
||||
this@then.getNamedSubphases(startDepth) + other.getNamedSubphases(startDepth)
|
||||
this@then.getNamedSubphases(startDepth) + other.getNamedSubphases(startDepth)
|
||||
|
||||
override val stickyPostconditions get() = other.stickyPostconditions
|
||||
}
|
||||
|
||||
fun <Context : CommonBackendContext> namedIrModulePhase(
|
||||
name: String,
|
||||
description: String,
|
||||
prerequisite: Set<AnyNamedPhase> = emptySet(),
|
||||
verify: (Context, IrModuleFragment) -> Unit = { _, _ -> },
|
||||
nlevels: Int = 1,
|
||||
lower: CompilerPhase<Context, IrModuleFragment, IrModuleFragment>
|
||||
) = SameTypeNamedPhaseWrapper(name, description, prerequisite, nlevels, lower, IrModuleDumperVerifier(verify))
|
||||
name: String,
|
||||
description: String,
|
||||
prerequisite: Set<AnyNamedPhase> = emptySet(),
|
||||
lower: CompilerPhase<Context, IrModuleFragment, IrModuleFragment>,
|
||||
preconditions: Set<Checker<IrModuleFragment>> = emptySet(),
|
||||
postconditions: Set<Checker<IrModuleFragment>> = emptySet(),
|
||||
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(
|
||||
name: String,
|
||||
description: String,
|
||||
prerequisite: Set<AnyNamedPhase> = emptySet(),
|
||||
verify: (Context, IrFile) -> Unit = { _, _ -> },
|
||||
nlevels: Int = 1,
|
||||
lower: CompilerPhase<Context, IrFile, IrFile>
|
||||
) = SameTypeNamedPhaseWrapper(name, description, prerequisite, nlevels, lower, IrFileDumperVerifier(verify))
|
||||
name: String,
|
||||
description: String,
|
||||
prerequisite: Set<AnyNamedPhase> = emptySet(),
|
||||
lower: CompilerPhase<Context, IrFile, IrFile>,
|
||||
preconditions: Set<Checker<IrFile>> = emptySet(),
|
||||
postconditions: Set<Checker<IrFile>> = emptySet(),
|
||||
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(
|
||||
name: String,
|
||||
description: String,
|
||||
prerequisite: Set<AnyNamedPhase> = emptySet(),
|
||||
nlevels: Int = 1,
|
||||
lower: CompilerPhase<Context, Unit, Unit>
|
||||
) = SameTypeNamedPhaseWrapper(name, description, prerequisite, nlevels, lower, EmptyDumperVerifier())
|
||||
name: String,
|
||||
description: String,
|
||||
prerequisite: Set<AnyNamedPhase> = emptySet(),
|
||||
nlevels: Int = 1,
|
||||
lower: CompilerPhase<Context, Unit, Unit>
|
||||
) = SameTypeNamedPhaseWrapper(
|
||||
name, description, prerequisite,
|
||||
lower = lower,
|
||||
nlevels = nlevels,
|
||||
dumperVerifier = EmptyDumperVerifier()
|
||||
)
|
||||
|
||||
fun <Context : CommonBackendContext> namedOpUnitPhase(
|
||||
name: String,
|
||||
description: String,
|
||||
prerequisite: Set<AnyNamedPhase>,
|
||||
op: Context.() -> Unit
|
||||
name: String,
|
||||
description: String,
|
||||
prerequisite: Set<AnyNamedPhase>,
|
||||
op: Context.() -> Unit
|
||||
) = namedUnitPhase(
|
||||
name, description, prerequisite,
|
||||
nlevels = 0,
|
||||
lower = object : SameTypeCompilerPhase<Context, Unit> {
|
||||
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: Unit) {
|
||||
context.op()
|
||||
}
|
||||
name, description, prerequisite,
|
||||
nlevels = 0,
|
||||
lower = object : SameTypeCompilerPhase<Context, Unit> {
|
||||
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<Unit>, context: Context, input: Unit) {
|
||||
context.op()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
fun <Context : CommonBackendContext> performByIrFile(
|
||||
name: String = "PerformByIrFile",
|
||||
description: String = "Perform phases by IrFile",
|
||||
prerequisite: Set<AnyNamedPhase> = emptySet(),
|
||||
verify: (Context, IrModuleFragment) -> Unit = { _, _ -> },
|
||||
lower: CompilerPhase<Context, IrFile, IrFile>
|
||||
name: String = "PerformByIrFile",
|
||||
description: String = "Perform phases by IrFile",
|
||||
prerequisite: Set<AnyNamedPhase> = emptySet(),
|
||||
preconditions: Set<Checker<IrModuleFragment>> = emptySet(),
|
||||
postconditions: Set<Checker<IrModuleFragment>> = emptySet(),
|
||||
stickyPostconditions: Set<Checker<IrModuleFragment>> = emptySet(),
|
||||
verify: (Context, IrModuleFragment) -> Unit = { _, _ -> },
|
||||
lower: CompilerPhase<Context, IrFile, IrFile>
|
||||
) = namedIrModulePhase(
|
||||
name, description, prerequisite, verify,
|
||||
nlevels = 1,
|
||||
lower = object : SameTypeCompilerPhase<Context, IrModuleFragment> {
|
||||
override fun invoke(
|
||||
phaseConfig: PhaseConfig,
|
||||
phaserState: PhaserState,
|
||||
context: Context,
|
||||
input: IrModuleFragment
|
||||
): IrModuleFragment {
|
||||
for (irFile in input.files) {
|
||||
lower.invoke(phaseConfig, phaserState, context, irFile)
|
||||
}
|
||||
|
||||
// TODO: no guarantee that module identity is preserved by `lower`
|
||||
return input
|
||||
name, description, prerequisite,
|
||||
preconditions = preconditions,
|
||||
postconditions = postconditions,
|
||||
stickyPostconditions = stickyPostconditions,
|
||||
verify = verify,
|
||||
nlevels = 1,
|
||||
lower = object : SameTypeCompilerPhase<Context, IrModuleFragment> {
|
||||
override fun invoke(
|
||||
phaseConfig: PhaseConfig,
|
||||
phaserState: PhaserState<IrModuleFragment>,
|
||||
context: Context,
|
||||
input: IrModuleFragment
|
||||
): IrModuleFragment {
|
||||
for (irFile in input.files) {
|
||||
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(
|
||||
lowering: (Context) -> FileLoweringPass,
|
||||
name: String,
|
||||
description: String,
|
||||
prerequisite: Set<AnyNamedPhase> = emptySet(),
|
||||
verify: (Context, IrFile) -> Unit = { _, _ -> }
|
||||
lowering: (Context) -> FileLoweringPass,
|
||||
name: String,
|
||||
description: String,
|
||||
prerequisite: Set<AnyNamedPhase> = emptySet(),
|
||||
preconditions: Set<Checker<IrFile>> = emptySet(),
|
||||
postconditions: Set<Checker<IrFile>> = emptySet(),
|
||||
stickyPostconditions: Set<Checker<IrFile>> = emptySet(),
|
||||
verify: (Context, IrFile) -> Unit = { _, _ -> }
|
||||
) = namedIrFilePhase(
|
||||
name, description, prerequisite, verify,
|
||||
nlevels = 0,
|
||||
lower = object : SameTypeCompilerPhase<Context, IrFile> {
|
||||
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: IrFile): IrFile {
|
||||
lowering(context).lower(input)
|
||||
return input
|
||||
}
|
||||
name, description, prerequisite,
|
||||
preconditions = preconditions,
|
||||
postconditions = postconditions,
|
||||
stickyPostconditions = stickyPostconditions,
|
||||
verify = verify,
|
||||
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(
|
||||
lowering: (Context) -> FileLoweringPass,
|
||||
name: String,
|
||||
description: String,
|
||||
prerequisite: Set<AnyNamedPhase> = emptySet(),
|
||||
verify: (Context, IrModuleFragment) -> Unit = { _, _ -> }
|
||||
lowering: (Context) -> FileLoweringPass,
|
||||
name: String,
|
||||
description: String,
|
||||
prerequisite: Set<AnyNamedPhase> = emptySet(),
|
||||
preconditions: Set<Checker<IrModuleFragment>> = emptySet(),
|
||||
postconditions: Set<Checker<IrModuleFragment>> = emptySet(),
|
||||
stickyPostconditions: Set<Checker<IrModuleFragment>> = emptySet(),
|
||||
verify: (Context, IrModuleFragment) -> Unit = { _, _ -> }
|
||||
) = namedIrModulePhase(
|
||||
name, description, prerequisite, verify,
|
||||
nlevels = 0,
|
||||
lower = object : SameTypeCompilerPhase<Context, IrModuleFragment> {
|
||||
override fun invoke(
|
||||
phaseConfig: PhaseConfig,
|
||||
phaserState: PhaserState,
|
||||
context: Context,
|
||||
input: IrModuleFragment
|
||||
): IrModuleFragment {
|
||||
lowering(context).lower(input)
|
||||
return input
|
||||
}
|
||||
name, description, prerequisite,
|
||||
preconditions=preconditions,
|
||||
postconditions = postconditions,
|
||||
stickyPostconditions = stickyPostconditions,
|
||||
verify = verify,
|
||||
nlevels = 0,
|
||||
lower = object : SameTypeCompilerPhase<Context, IrModuleFragment> {
|
||||
override fun invoke(
|
||||
phaseConfig: PhaseConfig,
|
||||
phaserState: PhaserState<IrModuleFragment>,
|
||||
context: Context,
|
||||
input: IrModuleFragment
|
||||
): IrModuleFragment {
|
||||
lowering(context).lower(input)
|
||||
return input
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
fun <Context : CommonBackendContext, Input> unitPhase(
|
||||
name: String,
|
||||
description: String,
|
||||
prerequisite: Set<AnyNamedPhase>,
|
||||
op: Context.() -> Unit
|
||||
name: String,
|
||||
description: String,
|
||||
prerequisite: Set<AnyNamedPhase>,
|
||||
preconditions: Set<Checker<Input>>,
|
||||
op: Context.() -> Unit
|
||||
) =
|
||||
object : AbstractNamedPhaseWrapper<Context, Input, Unit>(
|
||||
name, description, prerequisite,
|
||||
nlevels = 0,
|
||||
lower = object : CompilerPhase<Context, Input, Unit> {
|
||||
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: Input) {
|
||||
context.op()
|
||||
}
|
||||
}
|
||||
) {
|
||||
override val inputDumperVerifier = EmptyDumperVerifier<Context, Input>()
|
||||
override val outputDumperVerifier = EmptyDumperVerifier<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()
|
||||
}
|
||||
}
|
||||
) {
|
||||
override val inputDumperVerifier = EmptyDumperVerifier<Context, Input>()
|
||||
override val outputDumperVerifier = EmptyDumperVerifier<Context, 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
|
||||
fun <Context : CommonBackendContext, OldData, NewData> takeFromContext(op: (Context) -> NewData) =
|
||||
object : CompilerPhase<Context, OldData, NewData> {
|
||||
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: OldData) = op(context)
|
||||
}
|
||||
object : CompilerPhase<Context, OldData, NewData> {
|
||||
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<OldData>, context: Context, input: OldData) = op(context)
|
||||
}
|
||||
|
||||
fun <Context : CommonBackendContext, OldData, NewData> transform(op: (OldData) -> NewData) =
|
||||
object : CompilerPhase<Context, OldData, NewData> {
|
||||
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: OldData) = op(input)
|
||||
}
|
||||
object : CompilerPhase<Context, OldData, NewData> {
|
||||
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 checkConditions = config.getBoolean(CommonConfigurationKeys.CHECK_PHASE_CONDITIONS)
|
||||
val checkStickyConditions = config.getBoolean(CommonConfigurationKeys.CHECK_STICKY_CONDITIONS)
|
||||
|
||||
fun known(name: String): String {
|
||||
if (phases[name] == null) {
|
||||
|
||||
@@ -57,7 +57,7 @@ private fun makeCustomJsModulePhase(
|
||||
lower = object : SameTypeCompilerPhase<JsIrBackendContext, IrModuleFragment> {
|
||||
override fun invoke(
|
||||
phaseConfig: PhaseConfig,
|
||||
phaserState: PhaserState,
|
||||
phaserState: PhaserState<IrModuleFragment>,
|
||||
context: JsIrBackendContext,
|
||||
input: IrModuleFragment
|
||||
): IrModuleFragment {
|
||||
|
||||
@@ -26,7 +26,7 @@ import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
|
||||
private fun makePatchParentsPhase(number: Int) = namedIrFilePhase(
|
||||
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())
|
||||
return input
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user