Phaser: Implement dumper and verifier as general actions

This commit is contained in:
Svyatoslav Kuzmich
2019-05-13 15:19:23 +03:00
parent 0702b88bf3
commit b07690fccf
12 changed files with 208 additions and 78 deletions
@@ -238,6 +238,18 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
)
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(
value = "-Xphases-to-validate-before",
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.IncrementalResultsConsumer
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.generateKLib
import org.jetbrains.kotlin.ir.backend.js.jsPhases
import org.jetbrains.kotlin.js.config.EcmaVersion
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
import org.jetbrains.kotlin.js.config.JsConfig
@@ -223,10 +224,13 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
}
if (produceKind == ProduceKind.JS || produceKind == ProduceKind.DEFAULT) {
val phaseConfig = createPhaseConfig(jsPhases, arguments, messageCollector)
val compiledModule = compile(
project,
sourcesFiles,
configuration,
phaseConfig,
immediateDependencies = dependencies,
allDependencies = dependencies,
friendDependencies = friendDependencies,
@@ -29,6 +29,8 @@ fun createPhaseConfig(
val bothDumpSet = phaseSetFromArguments(phases, arguments.phasesToDump, ::report)
val toDumpStateBefore = beforeDumpSet + bothDumpSet
val toDumpStateAfter = afterDumpSet + bothDumpSet
val dumpDirectory = arguments.dumpDirectory
val dumpOnlyFqName = arguments.dumpOnlyFqName
val beforeValidateSet = phaseSetFromArguments(phases, arguments.phasesToValidateBefore, ::report)
val afterValidateSet = phaseSetFromArguments(phases, arguments.phasesToValidateAfter, ::report)
val bothValidateSet = phaseSetFromArguments(phases, arguments.phasesToValidate, ::report)
@@ -42,9 +44,20 @@ fun createPhaseConfig(
val checkStickyConditions = arguments.checkStickyPhaseConditions
return PhaseConfig(
compoundPhase, phases, enabled, verbose, toDumpStateBefore, toDumpStateAfter, toValidateStateBefore, toValidateStateAfter,
compoundPhase,
phases,
enabled,
verbose,
toDumpStateBefore,
toDumpStateAfter,
dumpDirectory,
dumpOnlyFqName,
toValidateStateBefore,
toValidateStateAfter,
namesOfElementsExcludedFromDumping,
needProfiling, checkConditions, checkStickyConditions
needProfiling,
checkConditions,
checkStickyConditions
).also {
if (arguments.listPhases) {
it.list()
@@ -11,11 +11,12 @@ import kotlin.system.measureTimeMillis
class PhaserState<Data>(
val alreadyDone: MutableSet<AnyNamedPhase> = mutableSetOf(),
var depth: Int = 0,
var phaseCount: Int = 0,
val stickyPostconditions: MutableSet<Checker<Data>> = mutableSetOf()
)
// 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 {
@@ -51,15 +52,27 @@ interface NamedCompilerPhase<in Context : CommonBackendContext, Input, Output> :
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<*, *, *>
enum class BeforeOrAfter { BEFORE, AFTER }
interface PhaseDumperVerifier<in Context : CommonBackendContext, Data> {
fun dump(phase: AnyNamedPhase, phaseConfig: PhaseConfig, data: Data, beforeOrAfter: BeforeOrAfter)
fun verify(context: Context, data: Data)
}
data class ActionState(
val config: PhaseConfig,
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>(
override val name: String,
@@ -69,10 +82,10 @@ abstract class AbstractNamedPhaseWrapper<in Context : CommonBackendContext, Inpu
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(),
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<Input>, context: Context, input: Input): Output {
if (this is SameTypeCompilerPhase<*, *> &&
@@ -88,18 +101,20 @@ abstract class AbstractNamedPhaseWrapper<in Context : CommonBackendContext, Inpu
context.inVerbosePhase = this in phaseConfig.verbose
runBefore(phaseConfig, context, input)
runBefore(phaseConfig, phaserState, context, input)
val output = runBody(phaseConfig, phaserState, context, input)
runAfter(phaseConfig, phaserState, context, output)
phaserState.alreadyDone.add(this)
phaserState.phaseCount++
return output
}
private fun runBefore(phaseConfig: PhaseConfig, context: Context, input: Input) {
checkAndRun(phaseConfig.toDumpStateBefore) { inputDumperVerifier.dump(this, phaseConfig, input, BeforeOrAfter.BEFORE) }
checkAndRun(phaseConfig.toValidateStateBefore) { inputDumperVerifier.verify(context, input) }
private fun runBefore(phaseConfig: PhaseConfig, phaserState: PhaserState<Input>, context: Context, input: Input) {
val state = ActionState(phaseConfig, this, phaserState.phaseCount, BeforeOrAfter.BEFORE)
for (action in actionsBefore) action(state, input, context)
if (phaseConfig.checkConditions) {
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) {
checkAndRun(phaseConfig.toDumpStateAfter) { outputDumperVerifier.dump(this, phaseConfig, output, BeforeOrAfter.AFTER) }
checkAndRun(phaseConfig.toValidateStateAfter) { outputDumperVerifier.verify(context, output) }
val state = ActionState(phaseConfig, this, phaserState.phaseCount, BeforeOrAfter.AFTER)
for (action in actionsAfter) action(state, output, context)
if (phaseConfig.checkConditions) {
for (post in postconditions) post(output)
for (post in stickyPostconditions) post(output)
@@ -158,11 +174,8 @@ class SameTypeNamedPhaseWrapper<in Context : CommonBackendContext, 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>
actions: Set<Action<Data, Context>> = emptySet(),
nlevels: Int = 0
) : 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
}
name, description, prerequisite, lower, preconditions, postconditions, stickyPostconditions, actions, actions, nlevels
), SameTypeCompilerPhase<Context, Data>
@@ -5,48 +5,115 @@
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.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.name
import org.jetbrains.kotlin.ir.declarations.*
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>(
val verifier: (Context, Data) -> Unit
) : PhaseDumperVerifier<Context, Data> {
abstract fun Data.getElementName(): String
private val IrElement.elementName: String
get() = when (this) {
is IrModuleFragment ->
this.name.asString()
// TODO: use a proper logger.
override fun dump(phase: AnyNamedPhase, phaseConfig: PhaseConfig, data: Data, beforeOrAfter: BeforeOrAfter) {
fun separator(title: String) = println("\n\n--- $title ----------------------\n")
is IrFile ->
this.name
if (!shouldBeDumped(phaseConfig, data)) return
val beforeOrAfterStr = beforeOrAfter.name.toLowerCase()
val title = "IR for ${data.getElementName()} $beforeOrAfterStr ${phase.description}"
separator(title)
println(data.dump())
else ->
this.toString()
}
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) =
input.getElementName() !in phaseConfig.namesOfElementsExcludedFromDumping
private fun ActionState.isValidationNeeded() =
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) :
IrPhaseDumperVerifier<Context, IrFile>(verifier) {
override fun IrFile.getElementName() = name
}
typealias Dumper<Data, Context> = (ActionState, Data, Context) -> String?
class IrModuleDumperVerifier<in Context : CommonBackendContext>(verifier: (Context, IrModuleFragment) -> Unit) :
IrPhaseDumperVerifier<Context, IrModuleFragment>(verifier) {
override fun IrModuleFragment.getElementName() = name.asString()
}
fun <Data, Context> dumpToFile(
fileExtension: String,
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> {
override fun dump(phase: AnyNamedPhase, phaseConfig: PhaseConfig, data: Data, beforeOrAfter: BeforeOrAfter) {}
override fun verify(context: Context, data: Data) {}
}
val directoryFile = File(directoryPath)
if (!directoryFile.isDirectory)
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))
@@ -54,7 +54,7 @@ fun <Context : CommonBackendContext> namedIrModulePhase(
preconditions: Set<Checker<IrModuleFragment>> = emptySet(),
postconditions: Set<Checker<IrModuleFragment>> = emptySet(),
stickyPostconditions: Set<Checker<IrModuleFragment>> = lower.stickyPostconditions,
verify: (Context, IrModuleFragment) -> Unit = { _, _ -> },
actions: Set<Action<IrModuleFragment, Context>> = setOf(defaultDumper),
nlevels: Int = 1
) = SameTypeNamedPhaseWrapper(
name,
@@ -64,8 +64,8 @@ fun <Context : CommonBackendContext> namedIrModulePhase(
preconditions,
postconditions,
stickyPostconditions,
nlevels,
IrModuleDumperVerifier(verify)
actions,
nlevels
)
fun <Context : CommonBackendContext> namedIrFilePhase(
@@ -76,7 +76,7 @@ fun <Context : CommonBackendContext> namedIrFilePhase(
preconditions: Set<Checker<IrFile>> = emptySet(),
postconditions: Set<Checker<IrFile>> = emptySet(),
stickyPostconditions: Set<Checker<IrFile>> = lower.stickyPostconditions,
verify: (Context, IrFile) -> Unit = { _, _ -> },
actions: Set<Action<IrFile, Context>> = setOf(defaultDumper),
nlevels: Int = 1
) = SameTypeNamedPhaseWrapper(
name,
@@ -86,8 +86,8 @@ fun <Context : CommonBackendContext> namedIrFilePhase(
preconditions,
postconditions,
stickyPostconditions,
nlevels,
IrFileDumperVerifier(verify)
actions,
nlevels
)
fun <Context : CommonBackendContext> namedUnitPhase(
@@ -99,8 +99,7 @@ fun <Context : CommonBackendContext> namedUnitPhase(
) = SameTypeNamedPhaseWrapper(
name, description, prerequisite,
lower = lower,
nlevels = nlevels,
dumperVerifier = EmptyDumperVerifier()
nlevels = nlevels
)
fun <Context : CommonBackendContext> namedOpUnitPhase(
@@ -125,14 +124,14 @@ fun <Context : CommonBackendContext> performByIrFile(
preconditions: Set<Checker<IrModuleFragment>> = emptySet(),
postconditions: 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>
) = namedIrModulePhase(
name, description, prerequisite,
preconditions = preconditions,
postconditions = postconditions,
stickyPostconditions = stickyPostconditions,
verify = verify,
actions = actions,
nlevels = 1,
lower = object : SameTypeCompilerPhase<Context, IrModuleFragment> {
override fun invoke(
@@ -161,13 +160,13 @@ fun <Context : CommonBackendContext> makeIrFilePhase(
preconditions: Set<Checker<IrFile>> = emptySet(),
postconditions: Set<Checker<IrFile>> = emptySet(),
stickyPostconditions: Set<Checker<IrFile>> = emptySet(),
verify: (Context, IrFile) -> Unit = { _, _ -> }
actions: Set<Action<IrFile, Context>> = setOf(defaultDumper)
) = namedIrFilePhase(
name, description, prerequisite,
preconditions = preconditions,
postconditions = postconditions,
stickyPostconditions = stickyPostconditions,
verify = verify,
actions = actions,
nlevels = 0,
lower = object : SameTypeCompilerPhase<Context, 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(),
postconditions: Set<Checker<IrModuleFragment>> = emptySet(),
stickyPostconditions: Set<Checker<IrModuleFragment>> = emptySet(),
verify: (Context, IrModuleFragment) -> Unit = { _, _ -> }
actions: Set<Action<IrModuleFragment, Context>> = setOf(defaultDumper)
) = namedIrModulePhase(
name, description, prerequisite,
preconditions=preconditions,
postconditions = postconditions,
stickyPostconditions = stickyPostconditions,
verify = verify,
actions = actions,
nlevels = 0,
lower = object : SameTypeCompilerPhase<Context, IrModuleFragment> {
override fun invoke(
@@ -222,10 +221,7 @@ fun <Context : CommonBackendContext, Input> unitPhase(
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<Input>, context: Context, input: Input) {}
@@ -19,6 +19,8 @@ class PhaseConfig(
val verbose: Set<AnyNamedPhase> = emptySet(),
val toDumpStateBefore: Set<AnyNamedPhase> = emptySet(),
val toDumpStateAfter: Set<AnyNamedPhase> = emptySet(),
val dumpToDirectory: String? = null,
val dumpOnlyFqName: String? = null,
val toValidateStateBefore: Set<AnyNamedPhase> = emptySet(),
val toValidateStateAfter: Set<AnyNamedPhase> = emptySet(),
val namesOfElementsExcludedFromDumping: Set<String> = emptySet(),
@@ -33,12 +33,14 @@ private fun validationCallback(context: JsIrBackendContext, module: IrModuleFrag
module.accept(CheckDeclarationParentsVisitor, null)
}
val validationAction = makeVerifyAction(::validationCallback)
private fun makeJsModulePhase(
lowering: (JsIrBackendContext) -> FileLoweringPass,
name: String,
description: String,
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(
op: (JsIrBackendContext, IrModuleFragment) -> Unit,
@@ -49,7 +51,7 @@ private fun makeCustomJsModulePhase(
name,
description,
prerequisite,
verify = ::validationCallback,
actions = setOf(defaultDumper, validationAction),
nlevels = 0,
lower = object : SameTypeCompilerPhase<JsIrBackendContext, IrModuleFragment> {
override fun invoke(
@@ -19,7 +19,7 @@ fun compile(
project: Project,
files: List<KtFile>,
configuration: CompilerConfiguration,
phaseConfig: PhaseConfig = PhaseConfig(jsPhases),
phaseConfig: PhaseConfig,
immediateDependencies: List<KlibModuleRef>,
allDependencies: List<KlibModuleRef>,
friendDependencies: List<KlibModuleRef>,
+2
View File
@@ -15,6 +15,8 @@ where advanced options include:
-Xcoroutines={enable|warn|error}
Enable coroutines or report warnings or errors on declarations and use sites of 'suspend' modifier
-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
-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
+2
View File
@@ -79,6 +79,8 @@ where advanced options include:
-Xcoroutines={enable|warn|error}
Enable coroutines or report warnings or errors on declarations and use sites of 'suspend' modifier
-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
-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
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.js.test
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.compile
import org.jetbrains.kotlin.ir.backend.js.generateKLib
@@ -90,11 +90,28 @@ abstract class BasicIrBoxTest(
}
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(
project = config.project,
files = filesToCompile,
configuration = config.configuration,
phaseConfig = config.configuration.get(CLIConfigurationKeys.PHASE_CONFIG) ?: PhaseConfig(jsPhases),
phaseConfig = phaseConfig,
immediateDependencies = dependencies,
allDependencies = allDependencies,
friendDependencies = emptyList(),