Phaser: Implement dumper and verifier as general actions
This commit is contained in:
+12
@@ -238,6 +238,18 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
|
|||||||
)
|
)
|
||||||
var namesExcludedFromDumping: Array<String>? by FreezableVar(null)
|
var namesExcludedFromDumping: Array<String>? by FreezableVar(null)
|
||||||
|
|
||||||
|
@Argument(
|
||||||
|
value = "-Xdump-directory",
|
||||||
|
description = "Dump backend state into directory"
|
||||||
|
)
|
||||||
|
var dumpDirectory: String? by FreezableVar(null)
|
||||||
|
|
||||||
|
@Argument(
|
||||||
|
value = "-Xdump-fqname",
|
||||||
|
description = "FqName of declaration that should be dumped"
|
||||||
|
)
|
||||||
|
var dumpOnlyFqName: String? by FreezableVar(null)
|
||||||
|
|
||||||
@Argument(
|
@Argument(
|
||||||
value = "-Xphases-to-validate-before",
|
value = "-Xphases-to-validate-before",
|
||||||
description = "Validate backend state before these phases"
|
description = "Validate backend state before these phases"
|
||||||
|
|||||||
@@ -29,8 +29,9 @@ import org.jetbrains.kotlin.incremental.components.LookupTracker
|
|||||||
import org.jetbrains.kotlin.incremental.js.IncrementalDataProvider
|
import org.jetbrains.kotlin.incremental.js.IncrementalDataProvider
|
||||||
import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumer
|
import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumer
|
||||||
import org.jetbrains.kotlin.ir.backend.js.KlibModuleRef
|
import org.jetbrains.kotlin.ir.backend.js.KlibModuleRef
|
||||||
import org.jetbrains.kotlin.ir.backend.js.generateKLib
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.compile
|
import org.jetbrains.kotlin.ir.backend.js.compile
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.generateKLib
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.jsPhases
|
||||||
import org.jetbrains.kotlin.js.config.EcmaVersion
|
import org.jetbrains.kotlin.js.config.EcmaVersion
|
||||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||||
import org.jetbrains.kotlin.js.config.JsConfig
|
import org.jetbrains.kotlin.js.config.JsConfig
|
||||||
@@ -223,10 +224,13 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (produceKind == ProduceKind.JS || produceKind == ProduceKind.DEFAULT) {
|
if (produceKind == ProduceKind.JS || produceKind == ProduceKind.DEFAULT) {
|
||||||
|
val phaseConfig = createPhaseConfig(jsPhases, arguments, messageCollector)
|
||||||
|
|
||||||
val compiledModule = compile(
|
val compiledModule = compile(
|
||||||
project,
|
project,
|
||||||
sourcesFiles,
|
sourcesFiles,
|
||||||
configuration,
|
configuration,
|
||||||
|
phaseConfig,
|
||||||
immediateDependencies = dependencies,
|
immediateDependencies = dependencies,
|
||||||
allDependencies = dependencies,
|
allDependencies = dependencies,
|
||||||
friendDependencies = friendDependencies,
|
friendDependencies = friendDependencies,
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ fun createPhaseConfig(
|
|||||||
val bothDumpSet = phaseSetFromArguments(phases, arguments.phasesToDump, ::report)
|
val bothDumpSet = phaseSetFromArguments(phases, arguments.phasesToDump, ::report)
|
||||||
val toDumpStateBefore = beforeDumpSet + bothDumpSet
|
val toDumpStateBefore = beforeDumpSet + bothDumpSet
|
||||||
val toDumpStateAfter = afterDumpSet + bothDumpSet
|
val toDumpStateAfter = afterDumpSet + bothDumpSet
|
||||||
|
val dumpDirectory = arguments.dumpDirectory
|
||||||
|
val dumpOnlyFqName = arguments.dumpOnlyFqName
|
||||||
val beforeValidateSet = phaseSetFromArguments(phases, arguments.phasesToValidateBefore, ::report)
|
val beforeValidateSet = phaseSetFromArguments(phases, arguments.phasesToValidateBefore, ::report)
|
||||||
val afterValidateSet = phaseSetFromArguments(phases, arguments.phasesToValidateAfter, ::report)
|
val afterValidateSet = phaseSetFromArguments(phases, arguments.phasesToValidateAfter, ::report)
|
||||||
val bothValidateSet = phaseSetFromArguments(phases, arguments.phasesToValidate, ::report)
|
val bothValidateSet = phaseSetFromArguments(phases, arguments.phasesToValidate, ::report)
|
||||||
@@ -42,9 +44,20 @@ fun createPhaseConfig(
|
|||||||
val checkStickyConditions = arguments.checkStickyPhaseConditions
|
val checkStickyConditions = arguments.checkStickyPhaseConditions
|
||||||
|
|
||||||
return PhaseConfig(
|
return PhaseConfig(
|
||||||
compoundPhase, phases, enabled, verbose, toDumpStateBefore, toDumpStateAfter, toValidateStateBefore, toValidateStateAfter,
|
compoundPhase,
|
||||||
|
phases,
|
||||||
|
enabled,
|
||||||
|
verbose,
|
||||||
|
toDumpStateBefore,
|
||||||
|
toDumpStateAfter,
|
||||||
|
dumpDirectory,
|
||||||
|
dumpOnlyFqName,
|
||||||
|
toValidateStateBefore,
|
||||||
|
toValidateStateAfter,
|
||||||
namesOfElementsExcludedFromDumping,
|
namesOfElementsExcludedFromDumping,
|
||||||
needProfiling, checkConditions, checkStickyConditions
|
needProfiling,
|
||||||
|
checkConditions,
|
||||||
|
checkStickyConditions
|
||||||
).also {
|
).also {
|
||||||
if (arguments.listPhases) {
|
if (arguments.listPhases) {
|
||||||
it.list()
|
it.list()
|
||||||
|
|||||||
+33
-20
@@ -11,11 +11,12 @@ import kotlin.system.measureTimeMillis
|
|||||||
class PhaserState<Data>(
|
class PhaserState<Data>(
|
||||||
val alreadyDone: MutableSet<AnyNamedPhase> = mutableSetOf(),
|
val alreadyDone: MutableSet<AnyNamedPhase> = mutableSetOf(),
|
||||||
var depth: Int = 0,
|
var depth: Int = 0,
|
||||||
|
var phaseCount: Int = 0,
|
||||||
val stickyPostconditions: MutableSet<Checker<Data>> = mutableSetOf()
|
val stickyPostconditions: MutableSet<Checker<Data>> = mutableSetOf()
|
||||||
)
|
)
|
||||||
|
|
||||||
// Copy state, forgetting the sticky postconditions (which will not be applicable to the new type)
|
// 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 <Input, Output> PhaserState<Input>.changeType() = PhaserState<Output>(alreadyDone, depth, phaseCount, mutableSetOf())
|
||||||
|
|
||||||
|
|
||||||
fun <R, D> PhaserState<D>.downlevel(nlevels: Int = 1, block: () -> R): R {
|
fun <R, D> PhaserState<D>.downlevel(nlevels: Int = 1, block: () -> R): R {
|
||||||
@@ -51,15 +52,27 @@ interface NamedCompilerPhase<in Context : CommonBackendContext, Input, Output> :
|
|||||||
val prerequisite: Set<AnyNamedPhase> get() = emptySet()
|
val prerequisite: Set<AnyNamedPhase> get() = emptySet()
|
||||||
val preconditions: Set<Checker<Input>>
|
val preconditions: Set<Checker<Input>>
|
||||||
val postconditions: Set<Checker<Output>>
|
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 }
|
enum class BeforeOrAfter { BEFORE, AFTER }
|
||||||
|
|
||||||
interface PhaseDumperVerifier<in Context : CommonBackendContext, Data> {
|
data class ActionState(
|
||||||
fun dump(phase: AnyNamedPhase, phaseConfig: PhaseConfig, data: Data, beforeOrAfter: BeforeOrAfter)
|
val config: PhaseConfig,
|
||||||
fun verify(context: Context, data: Data)
|
val phase: AnyNamedPhase,
|
||||||
}
|
val phaseCount: Int,
|
||||||
|
val beforeOrAfter: BeforeOrAfter
|
||||||
|
)
|
||||||
|
|
||||||
|
typealias Action<Data, Context> = (ActionState, Data, Context) -> Unit
|
||||||
|
|
||||||
|
infix operator fun <Data, Context> Action<Data, Context>.plus(other: Action<Data, Context>): Action<Data, Context> =
|
||||||
|
{ phaseState, data, context ->
|
||||||
|
this(phaseState, data, context)
|
||||||
|
other(phaseState, data, context)
|
||||||
|
}
|
||||||
|
|
||||||
abstract class AbstractNamedPhaseWrapper<in Context : CommonBackendContext, Input, Output>(
|
abstract class AbstractNamedPhaseWrapper<in Context : CommonBackendContext, Input, Output>(
|
||||||
override val name: String,
|
override val name: String,
|
||||||
@@ -69,10 +82,10 @@ abstract class AbstractNamedPhaseWrapper<in Context : CommonBackendContext, Inpu
|
|||||||
override val preconditions: Set<Checker<Input>> = emptySet(),
|
override val preconditions: Set<Checker<Input>> = emptySet(),
|
||||||
override val postconditions: Set<Checker<Output>> = emptySet(),
|
override val postconditions: Set<Checker<Output>> = emptySet(),
|
||||||
override val stickyPostconditions: 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(),
|
||||||
private val nlevels: Int = 0
|
private val nlevels: Int = 0
|
||||||
) : NamedCompilerPhase<Context, Input, Output> {
|
) : NamedCompilerPhase<Context, Input, Output> {
|
||||||
abstract val inputDumperVerifier: PhaseDumperVerifier<Context, Input>
|
|
||||||
abstract val outputDumperVerifier: PhaseDumperVerifier<Context, Output>
|
|
||||||
|
|
||||||
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<Input>, 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<*, *> &&
|
||||||
@@ -88,18 +101,20 @@ abstract class AbstractNamedPhaseWrapper<in Context : CommonBackendContext, Inpu
|
|||||||
|
|
||||||
context.inVerbosePhase = this in phaseConfig.verbose
|
context.inVerbosePhase = this in phaseConfig.verbose
|
||||||
|
|
||||||
runBefore(phaseConfig, context, input)
|
runBefore(phaseConfig, phaserState, context, input)
|
||||||
val output = runBody(phaseConfig, phaserState, context, input)
|
val output = runBody(phaseConfig, phaserState, context, input)
|
||||||
runAfter(phaseConfig, phaserState, context, output)
|
runAfter(phaseConfig, phaserState, context, output)
|
||||||
|
|
||||||
phaserState.alreadyDone.add(this)
|
phaserState.alreadyDone.add(this)
|
||||||
|
phaserState.phaseCount++
|
||||||
|
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun runBefore(phaseConfig: PhaseConfig, context: Context, input: Input) {
|
private fun runBefore(phaseConfig: PhaseConfig, phaserState: PhaserState<Input>, context: Context, input: Input) {
|
||||||
checkAndRun(phaseConfig.toDumpStateBefore) { inputDumperVerifier.dump(this, phaseConfig, input, BeforeOrAfter.BEFORE) }
|
val state = ActionState(phaseConfig, this, phaserState.phaseCount, BeforeOrAfter.BEFORE)
|
||||||
checkAndRun(phaseConfig.toValidateStateBefore) { inputDumperVerifier.verify(context, input) }
|
for (action in actionsBefore) action(state, input, context)
|
||||||
|
|
||||||
if (phaseConfig.checkConditions) {
|
if (phaseConfig.checkConditions) {
|
||||||
for (pre in preconditions) pre(input)
|
for (pre in preconditions) pre(input)
|
||||||
}
|
}
|
||||||
@@ -116,8 +131,9 @@ abstract class AbstractNamedPhaseWrapper<in Context : CommonBackendContext, Inpu
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun runAfter(phaseConfig: PhaseConfig, phaserState: PhaserState<Input>, context: Context, output: Output) {
|
private fun runAfter(phaseConfig: PhaseConfig, phaserState: PhaserState<Input>, context: Context, output: Output) {
|
||||||
checkAndRun(phaseConfig.toDumpStateAfter) { outputDumperVerifier.dump(this, phaseConfig, output, BeforeOrAfter.AFTER) }
|
val state = ActionState(phaseConfig, this, phaserState.phaseCount, BeforeOrAfter.AFTER)
|
||||||
checkAndRun(phaseConfig.toValidateStateAfter) { outputDumperVerifier.verify(context, output) }
|
for (action in actionsAfter) action(state, output, context)
|
||||||
|
|
||||||
if (phaseConfig.checkConditions) {
|
if (phaseConfig.checkConditions) {
|
||||||
for (post in postconditions) post(output)
|
for (post in postconditions) post(output)
|
||||||
for (post in stickyPostconditions) post(output)
|
for (post in stickyPostconditions) post(output)
|
||||||
@@ -158,11 +174,8 @@ class SameTypeNamedPhaseWrapper<in Context : CommonBackendContext, Data>(
|
|||||||
preconditions: Set<Checker<Data>> = emptySet(),
|
preconditions: Set<Checker<Data>> = emptySet(),
|
||||||
postconditions: Set<Checker<Data>> = emptySet(),
|
postconditions: Set<Checker<Data>> = emptySet(),
|
||||||
stickyPostconditions: Set<Checker<Data>> = lower.stickyPostconditions,
|
stickyPostconditions: Set<Checker<Data>> = lower.stickyPostconditions,
|
||||||
nlevels: Int = 0,
|
actions: Set<Action<Data, Context>> = emptySet(),
|
||||||
val dumperVerifier: PhaseDumperVerifier<Context, Data>
|
nlevels: Int = 0
|
||||||
) : AbstractNamedPhaseWrapper<Context, Data, Data>(
|
) : AbstractNamedPhaseWrapper<Context, Data, Data>(
|
||||||
name, description, prerequisite, lower, preconditions, postconditions, stickyPostconditions, nlevels
|
name, description, prerequisite, lower, preconditions, postconditions, stickyPostconditions, actions, actions, nlevels
|
||||||
), SameTypeCompilerPhase<Context, Data> {
|
), SameTypeCompilerPhase<Context, Data>
|
||||||
override val inputDumperVerifier get() = dumperVerifier
|
|
||||||
override val outputDumperVerifier get() = dumperVerifier
|
|
||||||
}
|
|
||||||
|
|||||||
+99
-32
@@ -5,48 +5,115 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.common.phaser
|
package org.jetbrains.kotlin.backend.common.phaser
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.name
|
|
||||||
import org.jetbrains.kotlin.ir.util.dump
|
import org.jetbrains.kotlin.ir.util.dump
|
||||||
|
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
abstract class IrPhaseDumperVerifier<in Context : CommonBackendContext, Data : IrElement>(
|
private val IrElement.elementName: String
|
||||||
val verifier: (Context, Data) -> Unit
|
get() = when (this) {
|
||||||
) : PhaseDumperVerifier<Context, Data> {
|
is IrModuleFragment ->
|
||||||
abstract fun Data.getElementName(): String
|
this.name.asString()
|
||||||
|
|
||||||
// TODO: use a proper logger.
|
is IrFile ->
|
||||||
override fun dump(phase: AnyNamedPhase, phaseConfig: PhaseConfig, data: Data, beforeOrAfter: BeforeOrAfter) {
|
this.name
|
||||||
fun separator(title: String) = println("\n\n--- $title ----------------------\n")
|
|
||||||
|
|
||||||
if (!shouldBeDumped(phaseConfig, data)) return
|
else ->
|
||||||
|
this.toString()
|
||||||
val beforeOrAfterStr = beforeOrAfter.name.toLowerCase()
|
|
||||||
val title = "IR for ${data.getElementName()} $beforeOrAfterStr ${phase.description}"
|
|
||||||
separator(title)
|
|
||||||
println(data.dump())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun verify(context: Context, data: Data) = verifier(context, data)
|
private fun ActionState.isDumpNeeded() =
|
||||||
|
phase in when (beforeOrAfter) {
|
||||||
|
BeforeOrAfter.BEFORE -> config.toDumpStateBefore
|
||||||
|
BeforeOrAfter.AFTER -> config.toDumpStateAfter
|
||||||
|
}
|
||||||
|
|
||||||
private fun shouldBeDumped(phaseConfig: PhaseConfig, input: Data) =
|
private fun ActionState.isValidationNeeded() =
|
||||||
input.getElementName() !in phaseConfig.namesOfElementsExcludedFromDumping
|
phase in when (beforeOrAfter) {
|
||||||
|
BeforeOrAfter.BEFORE -> config.toValidateStateBefore
|
||||||
|
BeforeOrAfter.AFTER -> config.toValidateStateAfter
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <Data, Context> makeDumpAction(dumper: Action<Data, Context>): Action<Data, Context> =
|
||||||
|
{ phaseState, data, context ->
|
||||||
|
if (phaseState.isDumpNeeded())
|
||||||
|
dumper(phaseState, data, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <Data, Context> makeVerifyAction(verifier: (Context, Data) -> Unit): Action<Data, Context> =
|
||||||
|
{ phaseState, data, context ->
|
||||||
|
if (phaseState.isValidationNeeded())
|
||||||
|
verifier(context, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun dumpIrElement(actionState: ActionState, data: IrElement, context: Any?): String {
|
||||||
|
val beforeOrAfterStr = actionState.beforeOrAfter.name.toLowerCase()
|
||||||
|
|
||||||
|
var dumpText: String = ""
|
||||||
|
val elementName: String
|
||||||
|
|
||||||
|
val dumpOnlyFqName = actionState.config.dumpOnlyFqName
|
||||||
|
if (dumpOnlyFqName != null) {
|
||||||
|
elementName = dumpOnlyFqName
|
||||||
|
data.acceptVoid(object : IrElementVisitorVoid {
|
||||||
|
override fun visitElement(element: IrElement) {
|
||||||
|
element.acceptChildrenVoid(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitDeclaration(declaration: IrDeclaration) {
|
||||||
|
if (declaration is IrDeclarationWithName && FqName(dumpOnlyFqName) == declaration.fqNameWhenAvailable) {
|
||||||
|
dumpText += declaration.dump()
|
||||||
|
} else {
|
||||||
|
super.visitDeclaration(declaration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
elementName = data.elementName
|
||||||
|
dumpText = data.dump()
|
||||||
|
}
|
||||||
|
|
||||||
|
val title = "-- IR for $elementName $beforeOrAfterStr ${actionState.phase.description}\n"
|
||||||
|
return title + dumpText
|
||||||
}
|
}
|
||||||
|
|
||||||
class IrFileDumperVerifier<in Context : CommonBackendContext>(verifier: (Context, IrFile) -> Unit) :
|
typealias Dumper<Data, Context> = (ActionState, Data, Context) -> String?
|
||||||
IrPhaseDumperVerifier<Context, IrFile>(verifier) {
|
|
||||||
override fun IrFile.getElementName() = name
|
|
||||||
}
|
|
||||||
|
|
||||||
class IrModuleDumperVerifier<in Context : CommonBackendContext>(verifier: (Context, IrModuleFragment) -> Unit) :
|
fun <Data, Context> dumpToFile(
|
||||||
IrPhaseDumperVerifier<Context, IrModuleFragment>(verifier) {
|
fileExtension: String,
|
||||||
override fun IrModuleFragment.getElementName() = name.asString()
|
dumper: Dumper<Data, Context>
|
||||||
}
|
): Action<Data, Context> =
|
||||||
|
fun(actionState: ActionState, data: Data, context: Context) {
|
||||||
|
val directoryPath = actionState.config.dumpToDirectory ?: return
|
||||||
|
val dumpContent = dumper(actionState, data, context) ?: return
|
||||||
|
|
||||||
class EmptyDumperVerifier<in Context : CommonBackendContext, Data> : PhaseDumperVerifier<Context, Data> {
|
val directoryFile = File(directoryPath)
|
||||||
override fun dump(phase: AnyNamedPhase, phaseConfig: PhaseConfig, data: Data, beforeOrAfter: BeforeOrAfter) {}
|
if (!directoryFile.isDirectory)
|
||||||
override fun verify(context: Context, data: Data) {}
|
if (!directoryFile.mkdirs())
|
||||||
}
|
error("Can't create directory for IR dumps at $directoryPath")
|
||||||
|
|
||||||
|
// Make dump files in a directory sorted by ID
|
||||||
|
val phaseIdFormatted = "%02d".format(actionState.phaseCount)
|
||||||
|
|
||||||
|
val fileName = "${phaseIdFormatted}_${actionState.phase.name}.$fileExtension"
|
||||||
|
|
||||||
|
File(directoryFile, fileName).writeText(dumpContent)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <Data, Context> dumpToStdout(
|
||||||
|
dumper: Dumper<Data, Context>
|
||||||
|
): Action<Data, Context> =
|
||||||
|
fun(actionState: ActionState, data: Data, context: Context) {
|
||||||
|
if (actionState.config.dumpToDirectory != null) return
|
||||||
|
val dumpContent = dumper(actionState, data, context) ?: return
|
||||||
|
println("\n\n----------------------------------------------")
|
||||||
|
println(dumpContent)
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
val defaultDumper = makeDumpAction(dumpToStdout(::dumpIrElement) + dumpToFile("ir", ::dumpIrElement))
|
||||||
+14
-18
@@ -54,7 +54,7 @@ fun <Context : CommonBackendContext> namedIrModulePhase(
|
|||||||
preconditions: Set<Checker<IrModuleFragment>> = emptySet(),
|
preconditions: Set<Checker<IrModuleFragment>> = emptySet(),
|
||||||
postconditions: Set<Checker<IrModuleFragment>> = emptySet(),
|
postconditions: Set<Checker<IrModuleFragment>> = emptySet(),
|
||||||
stickyPostconditions: Set<Checker<IrModuleFragment>> = lower.stickyPostconditions,
|
stickyPostconditions: Set<Checker<IrModuleFragment>> = lower.stickyPostconditions,
|
||||||
verify: (Context, IrModuleFragment) -> Unit = { _, _ -> },
|
actions: Set<Action<IrModuleFragment, Context>> = setOf(defaultDumper),
|
||||||
nlevels: Int = 1
|
nlevels: Int = 1
|
||||||
) = SameTypeNamedPhaseWrapper(
|
) = SameTypeNamedPhaseWrapper(
|
||||||
name,
|
name,
|
||||||
@@ -64,8 +64,8 @@ fun <Context : CommonBackendContext> namedIrModulePhase(
|
|||||||
preconditions,
|
preconditions,
|
||||||
postconditions,
|
postconditions,
|
||||||
stickyPostconditions,
|
stickyPostconditions,
|
||||||
nlevels,
|
actions,
|
||||||
IrModuleDumperVerifier(verify)
|
nlevels
|
||||||
)
|
)
|
||||||
|
|
||||||
fun <Context : CommonBackendContext> namedIrFilePhase(
|
fun <Context : CommonBackendContext> namedIrFilePhase(
|
||||||
@@ -76,7 +76,7 @@ fun <Context : CommonBackendContext> namedIrFilePhase(
|
|||||||
preconditions: Set<Checker<IrFile>> = emptySet(),
|
preconditions: Set<Checker<IrFile>> = emptySet(),
|
||||||
postconditions: Set<Checker<IrFile>> = emptySet(),
|
postconditions: Set<Checker<IrFile>> = emptySet(),
|
||||||
stickyPostconditions: Set<Checker<IrFile>> = lower.stickyPostconditions,
|
stickyPostconditions: Set<Checker<IrFile>> = lower.stickyPostconditions,
|
||||||
verify: (Context, IrFile) -> Unit = { _, _ -> },
|
actions: Set<Action<IrFile, Context>> = setOf(defaultDumper),
|
||||||
nlevels: Int = 1
|
nlevels: Int = 1
|
||||||
) = SameTypeNamedPhaseWrapper(
|
) = SameTypeNamedPhaseWrapper(
|
||||||
name,
|
name,
|
||||||
@@ -86,8 +86,8 @@ fun <Context : CommonBackendContext> namedIrFilePhase(
|
|||||||
preconditions,
|
preconditions,
|
||||||
postconditions,
|
postconditions,
|
||||||
stickyPostconditions,
|
stickyPostconditions,
|
||||||
nlevels,
|
actions,
|
||||||
IrFileDumperVerifier(verify)
|
nlevels
|
||||||
)
|
)
|
||||||
|
|
||||||
fun <Context : CommonBackendContext> namedUnitPhase(
|
fun <Context : CommonBackendContext> namedUnitPhase(
|
||||||
@@ -99,8 +99,7 @@ fun <Context : CommonBackendContext> namedUnitPhase(
|
|||||||
) = SameTypeNamedPhaseWrapper(
|
) = SameTypeNamedPhaseWrapper(
|
||||||
name, description, prerequisite,
|
name, description, prerequisite,
|
||||||
lower = lower,
|
lower = lower,
|
||||||
nlevels = nlevels,
|
nlevels = nlevels
|
||||||
dumperVerifier = EmptyDumperVerifier()
|
|
||||||
)
|
)
|
||||||
|
|
||||||
fun <Context : CommonBackendContext> namedOpUnitPhase(
|
fun <Context : CommonBackendContext> namedOpUnitPhase(
|
||||||
@@ -125,14 +124,14 @@ fun <Context : CommonBackendContext> performByIrFile(
|
|||||||
preconditions: Set<Checker<IrModuleFragment>> = emptySet(),
|
preconditions: Set<Checker<IrModuleFragment>> = emptySet(),
|
||||||
postconditions: Set<Checker<IrModuleFragment>> = emptySet(),
|
postconditions: Set<Checker<IrModuleFragment>> = emptySet(),
|
||||||
stickyPostconditions: Set<Checker<IrModuleFragment>> = emptySet(),
|
stickyPostconditions: Set<Checker<IrModuleFragment>> = emptySet(),
|
||||||
verify: (Context, IrModuleFragment) -> Unit = { _, _ -> },
|
actions: Set<Action<IrModuleFragment, Context>> = setOf(defaultDumper),
|
||||||
lower: CompilerPhase<Context, IrFile, IrFile>
|
lower: CompilerPhase<Context, IrFile, IrFile>
|
||||||
) = namedIrModulePhase(
|
) = namedIrModulePhase(
|
||||||
name, description, prerequisite,
|
name, description, prerequisite,
|
||||||
preconditions = preconditions,
|
preconditions = preconditions,
|
||||||
postconditions = postconditions,
|
postconditions = postconditions,
|
||||||
stickyPostconditions = stickyPostconditions,
|
stickyPostconditions = stickyPostconditions,
|
||||||
verify = verify,
|
actions = actions,
|
||||||
nlevels = 1,
|
nlevels = 1,
|
||||||
lower = object : SameTypeCompilerPhase<Context, IrModuleFragment> {
|
lower = object : SameTypeCompilerPhase<Context, IrModuleFragment> {
|
||||||
override fun invoke(
|
override fun invoke(
|
||||||
@@ -161,13 +160,13 @@ fun <Context : CommonBackendContext> makeIrFilePhase(
|
|||||||
preconditions: Set<Checker<IrFile>> = emptySet(),
|
preconditions: Set<Checker<IrFile>> = emptySet(),
|
||||||
postconditions: Set<Checker<IrFile>> = emptySet(),
|
postconditions: Set<Checker<IrFile>> = emptySet(),
|
||||||
stickyPostconditions: Set<Checker<IrFile>> = emptySet(),
|
stickyPostconditions: Set<Checker<IrFile>> = emptySet(),
|
||||||
verify: (Context, IrFile) -> Unit = { _, _ -> }
|
actions: Set<Action<IrFile, Context>> = setOf(defaultDumper)
|
||||||
) = namedIrFilePhase(
|
) = namedIrFilePhase(
|
||||||
name, description, prerequisite,
|
name, description, prerequisite,
|
||||||
preconditions = preconditions,
|
preconditions = preconditions,
|
||||||
postconditions = postconditions,
|
postconditions = postconditions,
|
||||||
stickyPostconditions = stickyPostconditions,
|
stickyPostconditions = stickyPostconditions,
|
||||||
verify = verify,
|
actions = actions,
|
||||||
nlevels = 0,
|
nlevels = 0,
|
||||||
lower = object : SameTypeCompilerPhase<Context, IrFile> {
|
lower = object : SameTypeCompilerPhase<Context, IrFile> {
|
||||||
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<IrFile>, context: Context, input: IrFile): IrFile {
|
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<IrFile>, context: Context, input: IrFile): IrFile {
|
||||||
@@ -185,13 +184,13 @@ fun <Context : CommonBackendContext> makeIrModulePhase(
|
|||||||
preconditions: Set<Checker<IrModuleFragment>> = emptySet(),
|
preconditions: Set<Checker<IrModuleFragment>> = emptySet(),
|
||||||
postconditions: Set<Checker<IrModuleFragment>> = emptySet(),
|
postconditions: Set<Checker<IrModuleFragment>> = emptySet(),
|
||||||
stickyPostconditions: Set<Checker<IrModuleFragment>> = emptySet(),
|
stickyPostconditions: Set<Checker<IrModuleFragment>> = emptySet(),
|
||||||
verify: (Context, IrModuleFragment) -> Unit = { _, _ -> }
|
actions: Set<Action<IrModuleFragment, Context>> = setOf(defaultDumper)
|
||||||
) = namedIrModulePhase(
|
) = namedIrModulePhase(
|
||||||
name, description, prerequisite,
|
name, description, prerequisite,
|
||||||
preconditions=preconditions,
|
preconditions=preconditions,
|
||||||
postconditions = postconditions,
|
postconditions = postconditions,
|
||||||
stickyPostconditions = stickyPostconditions,
|
stickyPostconditions = stickyPostconditions,
|
||||||
verify = verify,
|
actions = actions,
|
||||||
nlevels = 0,
|
nlevels = 0,
|
||||||
lower = object : SameTypeCompilerPhase<Context, IrModuleFragment> {
|
lower = object : SameTypeCompilerPhase<Context, IrModuleFragment> {
|
||||||
override fun invoke(
|
override fun invoke(
|
||||||
@@ -222,10 +221,7 @@ fun <Context : CommonBackendContext, Input> unitPhase(
|
|||||||
context.op()
|
context.op()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
) {
|
) {}
|
||||||
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<Input>, context: Context, input: Input) {}
|
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<Input>, context: Context, input: Input) {}
|
||||||
|
|||||||
+2
@@ -19,6 +19,8 @@ class PhaseConfig(
|
|||||||
val verbose: Set<AnyNamedPhase> = emptySet(),
|
val verbose: Set<AnyNamedPhase> = emptySet(),
|
||||||
val toDumpStateBefore: Set<AnyNamedPhase> = emptySet(),
|
val toDumpStateBefore: Set<AnyNamedPhase> = emptySet(),
|
||||||
val toDumpStateAfter: Set<AnyNamedPhase> = emptySet(),
|
val toDumpStateAfter: Set<AnyNamedPhase> = emptySet(),
|
||||||
|
val dumpToDirectory: String? = null,
|
||||||
|
val dumpOnlyFqName: String? = null,
|
||||||
val toValidateStateBefore: Set<AnyNamedPhase> = emptySet(),
|
val toValidateStateBefore: Set<AnyNamedPhase> = emptySet(),
|
||||||
val toValidateStateAfter: Set<AnyNamedPhase> = emptySet(),
|
val toValidateStateAfter: Set<AnyNamedPhase> = emptySet(),
|
||||||
val namesOfElementsExcludedFromDumping: Set<String> = emptySet(),
|
val namesOfElementsExcludedFromDumping: Set<String> = emptySet(),
|
||||||
|
|||||||
@@ -33,12 +33,14 @@ private fun validationCallback(context: JsIrBackendContext, module: IrModuleFrag
|
|||||||
module.accept(CheckDeclarationParentsVisitor, null)
|
module.accept(CheckDeclarationParentsVisitor, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val validationAction = makeVerifyAction(::validationCallback)
|
||||||
|
|
||||||
private fun makeJsModulePhase(
|
private fun makeJsModulePhase(
|
||||||
lowering: (JsIrBackendContext) -> FileLoweringPass,
|
lowering: (JsIrBackendContext) -> FileLoweringPass,
|
||||||
name: String,
|
name: String,
|
||||||
description: String,
|
description: String,
|
||||||
prerequisite: Set<AnyNamedPhase> = emptySet()
|
prerequisite: Set<AnyNamedPhase> = emptySet()
|
||||||
) = makeIrModulePhase<JsIrBackendContext>(lowering, name, description, prerequisite, verify = ::validationCallback)
|
) = makeIrModulePhase<JsIrBackendContext>(lowering, name, description, prerequisite, actions = setOf(validationAction, defaultDumper))
|
||||||
|
|
||||||
private fun makeCustomJsModulePhase(
|
private fun makeCustomJsModulePhase(
|
||||||
op: (JsIrBackendContext, IrModuleFragment) -> Unit,
|
op: (JsIrBackendContext, IrModuleFragment) -> Unit,
|
||||||
@@ -49,7 +51,7 @@ private fun makeCustomJsModulePhase(
|
|||||||
name,
|
name,
|
||||||
description,
|
description,
|
||||||
prerequisite,
|
prerequisite,
|
||||||
verify = ::validationCallback,
|
actions = setOf(defaultDumper, validationAction),
|
||||||
nlevels = 0,
|
nlevels = 0,
|
||||||
lower = object : SameTypeCompilerPhase<JsIrBackendContext, IrModuleFragment> {
|
lower = object : SameTypeCompilerPhase<JsIrBackendContext, IrModuleFragment> {
|
||||||
override fun invoke(
|
override fun invoke(
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ fun compile(
|
|||||||
project: Project,
|
project: Project,
|
||||||
files: List<KtFile>,
|
files: List<KtFile>,
|
||||||
configuration: CompilerConfiguration,
|
configuration: CompilerConfiguration,
|
||||||
phaseConfig: PhaseConfig = PhaseConfig(jsPhases),
|
phaseConfig: PhaseConfig,
|
||||||
immediateDependencies: List<KlibModuleRef>,
|
immediateDependencies: List<KlibModuleRef>,
|
||||||
allDependencies: List<KlibModuleRef>,
|
allDependencies: List<KlibModuleRef>,
|
||||||
friendDependencies: List<KlibModuleRef>,
|
friendDependencies: List<KlibModuleRef>,
|
||||||
|
|||||||
+2
@@ -15,6 +15,8 @@ where advanced options include:
|
|||||||
-Xcoroutines={enable|warn|error}
|
-Xcoroutines={enable|warn|error}
|
||||||
Enable coroutines or report warnings or errors on declarations and use sites of 'suspend' modifier
|
Enable coroutines or report warnings or errors on declarations and use sites of 'suspend' modifier
|
||||||
-Xdisable-phases Disable backend phases
|
-Xdisable-phases Disable backend phases
|
||||||
|
-Xdump-directory Dump backend state into directory
|
||||||
|
-Xdump-fqname FqName of declaration that should be dumped
|
||||||
-Xdump-perf=<path> Dump detailed performance statistics to the specified file
|
-Xdump-perf=<path> Dump detailed performance statistics to the specified file
|
||||||
-Xeffect-system Enable experimental language feature: effect system
|
-Xeffect-system Enable experimental language feature: effect system
|
||||||
-Xexperimental=<fq.name> Enable and propagate usages of experimental API for marker annotation with the given fully qualified name
|
-Xexperimental=<fq.name> Enable and propagate usages of experimental API for marker annotation with the given fully qualified name
|
||||||
|
|||||||
+2
@@ -79,6 +79,8 @@ where advanced options include:
|
|||||||
-Xcoroutines={enable|warn|error}
|
-Xcoroutines={enable|warn|error}
|
||||||
Enable coroutines or report warnings or errors on declarations and use sites of 'suspend' modifier
|
Enable coroutines or report warnings or errors on declarations and use sites of 'suspend' modifier
|
||||||
-Xdisable-phases Disable backend phases
|
-Xdisable-phases Disable backend phases
|
||||||
|
-Xdump-directory Dump backend state into directory
|
||||||
|
-Xdump-fqname FqName of declaration that should be dumped
|
||||||
-Xdump-perf=<path> Dump detailed performance statistics to the specified file
|
-Xdump-perf=<path> Dump detailed performance statistics to the specified file
|
||||||
-Xeffect-system Enable experimental language feature: effect system
|
-Xeffect-system Enable experimental language feature: effect system
|
||||||
-Xexperimental=<fq.name> Enable and propagate usages of experimental API for marker annotation with the given fully qualified name
|
-Xexperimental=<fq.name> Enable and propagate usages of experimental API for marker annotation with the given fully qualified name
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.js.test
|
package org.jetbrains.kotlin.js.test
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
|
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
|
||||||
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
import org.jetbrains.kotlin.backend.common.phaser.toPhaseMap
|
||||||
import org.jetbrains.kotlin.ir.backend.js.KlibModuleRef
|
import org.jetbrains.kotlin.ir.backend.js.KlibModuleRef
|
||||||
import org.jetbrains.kotlin.ir.backend.js.compile
|
import org.jetbrains.kotlin.ir.backend.js.compile
|
||||||
import org.jetbrains.kotlin.ir.backend.js.generateKLib
|
import org.jetbrains.kotlin.ir.backend.js.generateKLib
|
||||||
@@ -90,11 +90,28 @@ abstract class BasicIrBoxTest(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isMainModule) {
|
if (isMainModule) {
|
||||||
|
val debugMode = false
|
||||||
|
|
||||||
|
val phaseConfig = if (debugMode) {
|
||||||
|
val allPhasesSet = jsPhases.toPhaseMap().values.toSet()
|
||||||
|
val dumpOutputDir = File(outputFile.parent, outputFile.nameWithoutExtension + "-irdump")
|
||||||
|
println("\n ------ Dumping phases to file://$dumpOutputDir")
|
||||||
|
PhaseConfig(
|
||||||
|
jsPhases,
|
||||||
|
dumpToDirectory = dumpOutputDir.path,
|
||||||
|
toDumpStateAfter = allPhasesSet,
|
||||||
|
toValidateStateAfter = allPhasesSet,
|
||||||
|
dumpOnlyFqName = null
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
PhaseConfig(jsPhases)
|
||||||
|
}
|
||||||
|
|
||||||
val jsCode = compile(
|
val jsCode = compile(
|
||||||
project = config.project,
|
project = config.project,
|
||||||
files = filesToCompile,
|
files = filesToCompile,
|
||||||
configuration = config.configuration,
|
configuration = config.configuration,
|
||||||
phaseConfig = config.configuration.get(CLIConfigurationKeys.PHASE_CONFIG) ?: PhaseConfig(jsPhases),
|
phaseConfig = phaseConfig,
|
||||||
immediateDependencies = dependencies,
|
immediateDependencies = dependencies,
|
||||||
allDependencies = allDependencies,
|
allDependencies = allDependencies,
|
||||||
friendDependencies = emptyList(),
|
friendDependencies = emptyList(),
|
||||||
|
|||||||
Reference in New Issue
Block a user