Reorganize phaser
This commit is contained in:
+4
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.backend.common
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ir.Ir
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
@@ -13,6 +14,7 @@ import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
interface LoggingContext {
|
||||
var inVerbosePhase: Boolean
|
||||
fun log(message: () -> String)
|
||||
}
|
||||
|
||||
@@ -28,4 +30,6 @@ interface CommonBackendContext : BackendContext, LoggingContext {
|
||||
fun getInternalFunctions(name: String): List<FunctionDescriptor>
|
||||
|
||||
fun report(element: IrElement?, irFile: IrFile?, message: String, isError: Boolean)
|
||||
|
||||
val configuration: CompilerConfiguration
|
||||
}
|
||||
|
||||
@@ -1,229 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.common
|
||||
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.CompilerConfigurationKey
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.util.dump
|
||||
import kotlin.system.measureTimeMillis
|
||||
|
||||
interface CompilerPhase<in Context : BackendContext, Data> {
|
||||
val name: String
|
||||
val description: String
|
||||
val prerequisite: Set<CompilerPhase<*, *>>
|
||||
get() = emptySet()
|
||||
|
||||
fun invoke(context: Context, input: Data): Data
|
||||
}
|
||||
|
||||
private typealias AnyPhase = CompilerPhase<*, *>
|
||||
|
||||
class CompilerPhases(private val phaseList: List<AnyPhase>, config: CompilerConfiguration) {
|
||||
|
||||
val phases = phaseList.associate { it.name to it }
|
||||
|
||||
val enabled = computeEnabled(config)
|
||||
val verbose = phaseSetFromConfiguration(config, CommonConfigurationKeys.VERBOSE_PHASES)
|
||||
|
||||
val toDumpStateBefore: Set<AnyPhase>
|
||||
val toDumpStateAfter: Set<AnyPhase>
|
||||
|
||||
val toValidateStateBefore: Set<AnyPhase>
|
||||
val toValidateStateAfter: Set<AnyPhase>
|
||||
|
||||
init {
|
||||
with(CommonConfigurationKeys) {
|
||||
val beforeDumpSet = phaseSetFromConfiguration(config, PHASES_TO_DUMP_STATE_BEFORE)
|
||||
val afterDumpSet = phaseSetFromConfiguration(config, PHASES_TO_DUMP_STATE_AFTER)
|
||||
val bothDumpSet = phaseSetFromConfiguration(config, PHASES_TO_DUMP_STATE)
|
||||
toDumpStateBefore = beforeDumpSet + bothDumpSet
|
||||
toDumpStateAfter = afterDumpSet + bothDumpSet
|
||||
val beforeValidateSet = phaseSetFromConfiguration(config, PHASES_TO_VALIDATE_BEFORE)
|
||||
val afterValidateSet = phaseSetFromConfiguration(config, PHASES_TO_VALIDATE_AFTER)
|
||||
val bothValidateSet = phaseSetFromConfiguration(config, PHASES_TO_VALIDATE)
|
||||
toValidateStateBefore = beforeValidateSet + bothValidateSet
|
||||
toValidateStateAfter = afterValidateSet + bothValidateSet
|
||||
}
|
||||
}
|
||||
|
||||
fun known(name: String): String {
|
||||
if (phases[name] == null) {
|
||||
error("Unknown phase: $name. Use -Xlist-phases to see the list of phases.")
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
fun list() {
|
||||
phaseList.forEach { phase ->
|
||||
val enabled = if (phase in enabled) "(Enabled)" else ""
|
||||
val verbose = if (phase in verbose) "(Verbose)" else ""
|
||||
|
||||
println(String.format("%1$-30s %2$-50s %3$-10s", "${phase.name}:", phase.description, "$enabled $verbose"))
|
||||
}
|
||||
}
|
||||
|
||||
private fun computeEnabled(config: CompilerConfiguration) =
|
||||
with(CommonConfigurationKeys) {
|
||||
val disabledPhases = phaseSetFromConfiguration(config, DISABLED_PHASES)
|
||||
phases.values.toSet() - disabledPhases
|
||||
}
|
||||
|
||||
private fun phaseSetFromConfiguration(config: CompilerConfiguration, key: CompilerConfigurationKey<Set<String>>): Set<AnyPhase> {
|
||||
val phaseNames = config.get(key) ?: emptySet()
|
||||
if ("ALL" in phaseNames) return phases.values.toSet()
|
||||
return phaseNames.map { phases[it]!! }.toSet()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
interface PhaseRunner<Context : BackendContext, Data> {
|
||||
fun runBefore(phase: CompilerPhase<Context, Data>, depth: Int, context: Context, data: Data)
|
||||
fun runBody(phase: CompilerPhase<Context, Data>, context: Context, source: Data): Data
|
||||
fun runAfter(phase: CompilerPhase<Context, Data>, depth: Int, context: Context, data: Data)
|
||||
}
|
||||
|
||||
abstract class DefaultIrPhaseRunner<Context : CommonBackendContext, Data : IrElement>(private val validator: (data: Data, context: Context) -> Unit = { _, _ -> }) :
|
||||
PhaseRunner<Context, Data> {
|
||||
|
||||
enum class BeforeOrAfter { BEFORE, AFTER }
|
||||
|
||||
abstract val startPhaseMarker: CompilerPhase<Context, Data>
|
||||
abstract val endPhaseMarker: CompilerPhase<Context, Data>
|
||||
|
||||
private var inVerbosePhase = false
|
||||
|
||||
final override fun runBefore(phase: CompilerPhase<Context, Data>, depth: Int, context: Context, data: Data) {
|
||||
checkAndRun(phase, phases(context).toDumpStateBefore) { dumpElement(data, phase, context, BeforeOrAfter.BEFORE) }
|
||||
checkAndRun(phase, phases(context).toValidateStateBefore) { validator(data, context) }
|
||||
}
|
||||
|
||||
final override fun runBody(phase: CompilerPhase<Context, Data>, context: Context, source: Data): Data {
|
||||
val runner = when {
|
||||
phase === startPhaseMarker -> ::justRun
|
||||
phase === endPhaseMarker -> ::justRun
|
||||
needProfiling(context) -> ::runAndProfile
|
||||
else -> ::justRun
|
||||
}
|
||||
|
||||
inVerbosePhase = phase in phases(context).verbose
|
||||
|
||||
val result = runner(phase, context, source)
|
||||
|
||||
inVerbosePhase = false
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
final override fun runAfter(phase: CompilerPhase<Context, Data>, depth: Int, context: Context, data: Data) {
|
||||
checkAndRun(phase, phases(context).toDumpStateAfter) { dumpElement(data, phase, context, BeforeOrAfter.AFTER) }
|
||||
checkAndRun(phase, phases(context).toValidateStateAfter) { validator(data, context) }
|
||||
}
|
||||
|
||||
open fun separator(title: String) = println("\n\n--- $title ----------------------\n")
|
||||
|
||||
protected abstract fun phases(context: Context): CompilerPhases
|
||||
protected abstract fun elementName(input: Data): String
|
||||
protected abstract fun configuration(context: Context): CompilerConfiguration
|
||||
|
||||
private fun needProfiling(context: Context) = configuration(context).getBoolean(CommonConfigurationKeys.PROFILE_PHASES)
|
||||
|
||||
private fun shouldBeDumped(context: Context, input: Data) =
|
||||
elementName(input) !in configuration(context).get(CommonConfigurationKeys.EXCLUDED_ELEMENTS_FROM_DUMPING, emptySet())
|
||||
|
||||
private fun checkAndRun(phase: CompilerPhase<Context, Data>, set: Set<AnyPhase>, block: () -> Unit) {
|
||||
if (phase in set) block()
|
||||
}
|
||||
|
||||
private fun dumpElement(input: Data, phase: CompilerPhase<Context, Data>, context: Context, beforeOrAfter: BeforeOrAfter) {
|
||||
// Exclude nonsensical combinations
|
||||
if (phase === startPhaseMarker && beforeOrAfter == BeforeOrAfter.AFTER) return
|
||||
if (phase === endPhaseMarker && beforeOrAfter == BeforeOrAfter.BEFORE) return
|
||||
|
||||
if (!shouldBeDumped(context, input)) return
|
||||
|
||||
val title = when (phase) {
|
||||
startPhaseMarker -> "IR for ${elementName(input)} at the start of lowering process"
|
||||
endPhaseMarker -> "IR for ${elementName(input)} at the end of lowering process"
|
||||
else -> {
|
||||
val beforeOrAfterStr = beforeOrAfter.name.toLowerCase()
|
||||
"IR for ${elementName(input)} $beforeOrAfterStr ${phase.description}"
|
||||
}
|
||||
}
|
||||
separator(title)
|
||||
println(input.dump())
|
||||
}
|
||||
|
||||
private fun runAndProfile(phase: CompilerPhase<Context, Data>, context: Context, source: Data): Data {
|
||||
var result: Data = source
|
||||
val msec = measureTimeMillis { result = phase.invoke(context, source) }
|
||||
println("${phase.description}: $msec msec")
|
||||
return result
|
||||
}
|
||||
|
||||
private fun justRun(phase: CompilerPhase<Context, Data>, context: Context, source: Data) =
|
||||
phase.invoke(context, source)
|
||||
}
|
||||
|
||||
class CompilerPhaseManager<Context : BackendContext, Data>(
|
||||
val context: Context,
|
||||
val phases: CompilerPhases,
|
||||
val data: Data,
|
||||
private val phaseRunner: PhaseRunner<Context, Data>,
|
||||
val parent: CompilerPhaseManager<Context, *>? = null
|
||||
) {
|
||||
val depth: Int = parent?.depth?.inc() ?: 0
|
||||
|
||||
private val previousPhases = mutableSetOf<CompilerPhase<Context, Data>>()
|
||||
|
||||
fun <NewData> createChild(
|
||||
newData: NewData,
|
||||
newPhaseRunner: PhaseRunner<Context, NewData>
|
||||
) = CompilerPhaseManager(
|
||||
context, phases, newData, newPhaseRunner, parent = this
|
||||
)
|
||||
|
||||
fun createChild() = createChild(data, phaseRunner)
|
||||
|
||||
private fun checkPrerequisite(phase: CompilerPhase<*, *>): Boolean =
|
||||
previousPhases.contains(phase) || parent?.checkPrerequisite(phase) == true
|
||||
|
||||
fun phase(phase: CompilerPhase<Context, Data>, context: Context, source: Data): Data {
|
||||
|
||||
if (phase !in phases.enabled) return source
|
||||
|
||||
phase.prerequisite.forEach {
|
||||
if (!checkPrerequisite(it))
|
||||
throw Error("$phase requires $it")
|
||||
}
|
||||
|
||||
previousPhases.add(phase)
|
||||
|
||||
phaseRunner.runBefore(phase, depth, context, source)
|
||||
val result = phaseRunner.runBody(phase, context, source)
|
||||
phaseRunner.runAfter(phase, depth, context, result)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
fun <Context : BackendContext, Data> makePhase(
|
||||
lowering: (Context, Data) -> Unit,
|
||||
description: String,
|
||||
name: String,
|
||||
prerequisite: Set<CompilerPhase<*, *>> = emptySet()
|
||||
) = object : CompilerPhase<Context, Data> {
|
||||
override val name = name
|
||||
override val description = description
|
||||
override val prerequisite = prerequisite
|
||||
|
||||
override fun invoke(context: Context, input: Data): Data {
|
||||
lowering(context, input)
|
||||
return input
|
||||
}
|
||||
|
||||
override fun toString() = "Compiler Phase @$name"
|
||||
}
|
||||
@@ -17,10 +17,7 @@
|
||||
package org.jetbrains.kotlin.backend.common
|
||||
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBody
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
@@ -54,6 +51,8 @@ interface BodyLoweringPass : FileLoweringPass {
|
||||
override fun lower(irFile: IrFile) = runOnFilePostfix(irFile)
|
||||
}
|
||||
|
||||
fun FileLoweringPass.lower(moduleFragment: IrModuleFragment) = moduleFragment.files.forEach { lower(it) }
|
||||
|
||||
fun ClassLoweringPass.runOnFilePostfix(irFile: IrFile) {
|
||||
irFile.acceptVoid(object : IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) {
|
||||
|
||||
+7
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.common.descriptors.*
|
||||
import org.jetbrains.kotlin.backend.common.ir.copyTo
|
||||
import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
|
||||
import org.jetbrains.kotlin.backend.common.ir.ir2string
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
@@ -31,6 +32,12 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
val jvmDefaultArgumentStubPhase = makeIrFilePhase(
|
||||
{ context -> DefaultArgumentStubGenerator(context, false) },
|
||||
name = "DefaultArgumentsStubGenerator",
|
||||
description = "Generate synthetic stubs for functions with default parameter values"
|
||||
)
|
||||
|
||||
// TODO: fix expect/actual default parameters
|
||||
|
||||
open class DefaultArgumentStubGenerator(
|
||||
|
||||
+11
-7
@@ -8,12 +8,14 @@ package org.jetbrains.kotlin.backend.common.lower
|
||||
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||
import org.jetbrains.kotlin.backend.common.deepCopyWithWrappedDescriptors
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.*
|
||||
import org.jetbrains.kotlin.backend.common.ir.SetDeclarationsParentVisitor
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
@@ -26,10 +28,6 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.util.DescriptorsRemapper
|
||||
import org.jetbrains.kotlin.ir.util.SymbolRenamer
|
||||
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
|
||||
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
@@ -38,6 +36,12 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
|
||||
object SYNTHESIZED_INIT_BLOCK: IrStatementOriginImpl("SYNTHESIZED_INIT_BLOCK")
|
||||
|
||||
fun makeInitializersPhase(origin: IrDeclarationOrigin, clinitNeeded: Boolean)= makeIrFilePhase(
|
||||
{ context -> InitializersLowering(context, origin, clinitNeeded) },
|
||||
name = "Initializers",
|
||||
description = "Handle initializer statements"
|
||||
)
|
||||
|
||||
class InitializersLowering(
|
||||
val context: CommonBackendContext,
|
||||
val declarationOrigin: IrDeclarationOrigin,
|
||||
|
||||
+13
-1
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.backend.common.lower
|
||||
import org.jetbrains.kotlin.backend.common.BackendContext
|
||||
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.makePhase
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||
@@ -28,6 +28,12 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import java.util.*
|
||||
|
||||
val innerClassesPhase = makeIrFilePhase(
|
||||
::InnerClassesLowering,
|
||||
name = "InnerClasses",
|
||||
description = "Move inner classes to toplevel"
|
||||
)
|
||||
|
||||
class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass {
|
||||
override fun lower(irClass: IrClass) {
|
||||
InnerClassTransformer(irClass).lowerInnerClass()
|
||||
@@ -169,6 +175,12 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass {
|
||||
}
|
||||
}
|
||||
|
||||
val innerClassConstructorCallsPhase = makeIrFilePhase(
|
||||
::InnerClassConstructorCallsLowering,
|
||||
name = "InnerClassConstructorCalls",
|
||||
description = "Handle constructor calls for inner classes"
|
||||
)
|
||||
|
||||
class InnerClassConstructorCallsLowering(val context: BackendContext) : BodyLoweringPass {
|
||||
override fun lower(irBody: IrBody) {
|
||||
irBody.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||
|
||||
+8
-2
@@ -18,7 +18,7 @@ package org.jetbrains.kotlin.backend.common.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.BackendContext
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.makePhase
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||
@@ -32,7 +32,13 @@ import org.jetbrains.kotlin.ir.util.isSubclassOf
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
|
||||
class KCallableNamePropertyLowering(val context: BackendContext) : FileLoweringPass {
|
||||
val kCallableNamePropertyPhase = makeIrFilePhase(
|
||||
::KCallableNamePropertyLowering,
|
||||
name = "KCallableNameProperty",
|
||||
description = "Replace name references for callables with constants"
|
||||
)
|
||||
|
||||
private class KCallableNamePropertyLowering(val context: BackendContext) : FileLoweringPass {
|
||||
override fun lower(irFile: IrFile) {
|
||||
irFile.transformChildrenVoid(KCallableNamePropertyTransformer(this))
|
||||
}
|
||||
|
||||
+6
-10
@@ -17,8 +17,8 @@
|
||||
package org.jetbrains.kotlin.backend.common.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||
import org.jetbrains.kotlin.backend.common.CompilerPhase
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
@@ -34,15 +34,11 @@ import org.jetbrains.kotlin.ir.util.resolveFakeOverride
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
|
||||
fun makeLateinitPhase() = object : CompilerPhase<CommonBackendContext, IrFile> {
|
||||
override val name = "Lateinit"
|
||||
override val description = "Insert checks for lateinit field references"
|
||||
|
||||
override fun invoke(context: CommonBackendContext, input: IrFile): IrFile {
|
||||
LateinitLowering(context).lower(input)
|
||||
return input
|
||||
}
|
||||
}
|
||||
val jvmLateinitPhase = makeIrFilePhase(
|
||||
::LateinitLowering,
|
||||
name = "Lateinit",
|
||||
description = "Insert checks for lateinit field references"
|
||||
)
|
||||
|
||||
class LateinitLowering(val context: CommonBackendContext) : FileLoweringPass {
|
||||
override fun lower(irFile: IrFile) {
|
||||
|
||||
+14
-1
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.*
|
||||
import org.jetbrains.kotlin.backend.common.ir.copyTo
|
||||
import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
|
||||
import org.jetbrains.kotlin.backend.common.makePhase
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
||||
@@ -33,8 +33,21 @@ import org.jetbrains.kotlin.ir.util.patchDeclarationParents
|
||||
import org.jetbrains.kotlin.ir.util.transformDeclarationsFlat
|
||||
import org.jetbrains.kotlin.ir.visitors.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.NameUtils
|
||||
import java.util.*
|
||||
|
||||
val jvmLocalDeclarationsPhase = makeIrFilePhase(
|
||||
{ context ->
|
||||
LocalDeclarationsLowering(context, object : LocalNameProvider {
|
||||
override fun localName(declaration: IrDeclarationWithName): String =
|
||||
NameUtils.sanitizeAsJavaIdentifier(super.localName(declaration))
|
||||
}, Visibilities.PUBLIC, true)
|
||||
},
|
||||
name = "JvmLocalDeclarations",
|
||||
description = "Move local declarations to classes",
|
||||
prerequisite = setOf(sharedVariablesPhase)
|
||||
)
|
||||
|
||||
interface LocalNameProvider {
|
||||
fun localName(declaration: IrDeclarationWithName): String =
|
||||
declaration.name.asString()
|
||||
|
||||
+7
-1
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.backend.common.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.BackendContext
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.makePhase
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
@@ -18,6 +18,12 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import java.util.*
|
||||
|
||||
val propertiesPhase = makeIrFilePhase(
|
||||
::PropertiesLowering,
|
||||
name = "Properties",
|
||||
description = "Move fields and accessors for properties to their classes"
|
||||
)
|
||||
|
||||
class PropertiesLowering() : IrElementTransformerVoid(), FileLoweringPass {
|
||||
constructor(@Suppress("UNUSED_PARAMETER") context: BackendContext) : this()
|
||||
|
||||
|
||||
+9
-1
@@ -16,7 +16,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.common.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.*
|
||||
import org.jetbrains.kotlin.backend.common.BackendContext
|
||||
import org.jetbrains.kotlin.backend.common.FunctionLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
@@ -30,6 +32,12 @@ import org.jetbrains.kotlin.ir.util.dump
|
||||
import org.jetbrains.kotlin.ir.visitors.*
|
||||
import java.util.*
|
||||
|
||||
val sharedVariablesPhase = makeIrFilePhase(
|
||||
::SharedVariablesLowering,
|
||||
name = "SharedVariables",
|
||||
description = "Transform shared variables"
|
||||
)
|
||||
|
||||
object CoroutineIntrinsicLambdaOrigin : IrStatementOriginImpl("Coroutine intrinsic lambda")
|
||||
|
||||
class SharedVariablesLowering(val context: BackendContext) : FunctionLoweringPass {
|
||||
|
||||
+7
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.backend.common.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.*
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
@@ -27,6 +28,12 @@ import org.jetbrains.kotlin.ir.util.getArgumentsWithIr
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
|
||||
val tailrecPhase = makeIrFilePhase(
|
||||
::TailrecLowering,
|
||||
name = "Tailrec",
|
||||
description = "Handle tailrec calls"
|
||||
)
|
||||
|
||||
/**
|
||||
* This pass lowers tail recursion calls in `tailrec` functions.
|
||||
*
|
||||
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
fun <R> PhaserState.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
|
||||
|
||||
fun getNamedSubphases(startDepth: Int = 0): List<Pair<Int, NamedCompilerPhase<*, *, *>>> = emptyList()
|
||||
}
|
||||
|
||||
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 NamedCompilerPhase<in Context : CommonBackendContext, in Input, out Output> : CompilerPhase<Context, Input, Output> {
|
||||
val name: String
|
||||
val description: String
|
||||
val prerequisite: Set<AnyNamedPhase> get() = emptySet()
|
||||
}
|
||||
|
||||
typealias AnyNamedPhase = NamedCompilerPhase<*, *, *>
|
||||
|
||||
enum class BeforeOrAfter { BEFORE, AFTER }
|
||||
|
||||
interface PhaseDumperVerifier<in Context : CommonBackendContext, Data> {
|
||||
fun dump(phase: AnyNamedPhase, context: Context, data: Data, beforeOrAfter: BeforeOrAfter)
|
||||
fun verify(context: Context, data: Data)
|
||||
}
|
||||
|
||||
abstract class AbstractNamedPhaseWrapper<in Context : CommonBackendContext, Input, Output>(
|
||||
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>
|
||||
) : 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 {
|
||||
if (this is SameTypeCompilerPhase<*, *> &&
|
||||
this !in phaseConfig.enabled
|
||||
) {
|
||||
return input as Output
|
||||
}
|
||||
|
||||
assert(phaserState.alreadyDone.containsAll(prerequisite))
|
||||
context.inVerbosePhase = this in phaseConfig.verbose
|
||||
|
||||
runBefore(phaseConfig, context, input)
|
||||
val output = runBody(phaseConfig, phaserState, context, input)
|
||||
runAfter(phaseConfig, context, output)
|
||||
|
||||
phaserState.alreadyDone.add(this)
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
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) }
|
||||
}
|
||||
|
||||
private fun runBody(phaseConfig: PhaseConfig, phaserState: PhaserState, 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, context: Context, output: Output) {
|
||||
checkAndRun(phaseConfig.toDumpStateAfter) { outputDumperVerifier.dump(this, context, output, BeforeOrAfter.AFTER) }
|
||||
checkAndRun(phaseConfig.toValidateStateAfter) { outputDumperVerifier.verify(context, output) }
|
||||
}
|
||||
|
||||
private fun runAndProfile(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, source: Input): Output {
|
||||
var result: Output? = null
|
||||
val msec = measureTimeMillis {
|
||||
result = phaserState.downlevel(nlevels) {
|
||||
lower.invoke(phaseConfig, phaserState, context, source)
|
||||
}
|
||||
}
|
||||
// TODO: use a proper logger
|
||||
println("${"\t".repeat(phaserState.depth)}$description: $msec msec")
|
||||
return result!!
|
||||
}
|
||||
|
||||
private fun checkAndRun(set: Set<AnyNamedPhase>, block: () -> Unit) {
|
||||
if (this in set) block()
|
||||
}
|
||||
|
||||
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>,
|
||||
nlevels: Int = 0,
|
||||
lower: CompilerPhase<Context, Data, Data>,
|
||||
val dumperVerifier: PhaseDumperVerifier<Context, Data>
|
||||
) : AbstractNamedPhaseWrapper<Context, Data, Data>(name, description, prerequisite, nlevels, lower), SameTypeCompilerPhase<Context, Data> {
|
||||
override val inputDumperVerifier get() = dumperVerifier
|
||||
override val outputDumperVerifier get() = dumperVerifier
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
package org.jetbrains.kotlin.backend.common.phaser
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
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.util.dump
|
||||
|
||||
abstract class IrPhaseDumperVerifier<in Context : CommonBackendContext, Data : IrElement>(
|
||||
val verifier: (Context, Data) -> Unit
|
||||
) : PhaseDumperVerifier<Context, Data> {
|
||||
abstract fun Data.getElementName(): String
|
||||
|
||||
// TODO: use a proper logger.
|
||||
override fun dump(phase: AnyNamedPhase, context: Context, data: Data, beforeOrAfter: BeforeOrAfter) {
|
||||
fun separator(title: String) = println("\n\n--- $title ----------------------\n")
|
||||
|
||||
if (!shouldBeDumped(context, data)) return
|
||||
|
||||
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 shouldBeDumped(context: Context, input: Data) =
|
||||
input.getElementName() !in context.configuration.get(CommonConfigurationKeys.EXCLUDED_ELEMENTS_FROM_DUMPING, emptySet())
|
||||
}
|
||||
|
||||
class IrFileDumperVerifier<in Context : CommonBackendContext>(verifier: (Context, IrFile) -> Unit) :
|
||||
IrPhaseDumperVerifier<Context, IrFile>(verifier) {
|
||||
override fun IrFile.getElementName() = name
|
||||
}
|
||||
|
||||
class IrModuleDumperVerifier<in Context : CommonBackendContext>(verifier: (Context, IrModuleFragment) -> Unit) :
|
||||
IrPhaseDumperVerifier<Context, IrModuleFragment>(verifier) {
|
||||
override fun IrModuleFragment.getElementName() = name.asString()
|
||||
}
|
||||
|
||||
class EmptyDumperVerifier<in Context : CommonBackendContext, Data> : PhaseDumperVerifier<Context, Data> {
|
||||
override fun dump(phase: AnyNamedPhase, context: Context, data: Data, beforeOrAfter: BeforeOrAfter) {}
|
||||
override fun verify(context: Context, data: Data) {}
|
||||
}
|
||||
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
package org.jetbrains.kotlin.backend.common.phaser
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.lower
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
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>
|
||||
) = 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 getNamedSubphases(startDepth: Int) =
|
||||
this@then.getNamedSubphases(startDepth) + other.getNamedSubphases(startDepth)
|
||||
}
|
||||
|
||||
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))
|
||||
|
||||
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))
|
||||
|
||||
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())
|
||||
|
||||
fun <Context : CommonBackendContext> namedOpUnitPhase(
|
||||
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()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
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>
|
||||
) = 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
|
||||
}
|
||||
|
||||
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 = { _, _ -> }
|
||||
) = 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
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
fun <Context : CommonBackendContext> makeIrModulePhase(
|
||||
lowering: (Context) -> FileLoweringPass,
|
||||
name: String,
|
||||
description: String,
|
||||
prerequisite: Set<AnyNamedPhase> = 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
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
fun <Context : CommonBackendContext, Input> unitPhase(
|
||||
name: String,
|
||||
description: String,
|
||||
prerequisite: Set<AnyNamedPhase>,
|
||||
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>()
|
||||
}
|
||||
|
||||
fun <Context : CommonBackendContext, Input> unitSink() = object : CompilerPhase<Context, Input, Unit> {
|
||||
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, 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)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
package org.jetbrains.kotlin.backend.common.phaser
|
||||
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.CompilerConfigurationKey
|
||||
|
||||
class PhaseConfig(private val compoundPhase: CompilerPhase<*, *, *>, config: CompilerConfiguration) {
|
||||
|
||||
val phases = compoundPhase.getNamedSubphases().map { (_, phase) -> phase }.associate { it.name to it }
|
||||
private val enabledMut = computeEnabled(config).toMutableSet()
|
||||
|
||||
val enabled: Set<AnyNamedPhase> get() = enabledMut
|
||||
|
||||
val verbose = phaseSetFromConfiguration(config, CommonConfigurationKeys.VERBOSE_PHASES)
|
||||
val toDumpStateBefore: Set<AnyNamedPhase>
|
||||
|
||||
val toDumpStateAfter: Set<AnyNamedPhase>
|
||||
val toValidateStateBefore: Set<AnyNamedPhase>
|
||||
|
||||
val toValidateStateAfter: Set<AnyNamedPhase>
|
||||
|
||||
init {
|
||||
with(CommonConfigurationKeys) {
|
||||
val beforeDumpSet = phaseSetFromConfiguration(config, PHASES_TO_DUMP_STATE_BEFORE)
|
||||
val afterDumpSet = phaseSetFromConfiguration(config, PHASES_TO_DUMP_STATE_AFTER)
|
||||
val bothDumpSet = phaseSetFromConfiguration(config, PHASES_TO_DUMP_STATE)
|
||||
toDumpStateBefore = beforeDumpSet + bothDumpSet
|
||||
toDumpStateAfter = afterDumpSet + bothDumpSet
|
||||
val beforeValidateSet = phaseSetFromConfiguration(config, PHASES_TO_VALIDATE_BEFORE)
|
||||
val afterValidateSet = phaseSetFromConfiguration(config, PHASES_TO_VALIDATE_AFTER)
|
||||
val bothValidateSet = phaseSetFromConfiguration(config, PHASES_TO_VALIDATE)
|
||||
toValidateStateBefore = beforeValidateSet + bothValidateSet
|
||||
toValidateStateAfter = afterValidateSet + bothValidateSet
|
||||
}
|
||||
}
|
||||
|
||||
val needProfiling = config.getBoolean(CommonConfigurationKeys.PROFILE_PHASES)
|
||||
|
||||
fun known(name: String): String {
|
||||
if (phases[name] == null) {
|
||||
error("Unknown phase: $name. Use -Xlist-phases to see the list of phases.")
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
fun list() {
|
||||
compoundPhase.getNamedSubphases().forEach { (depth, phase) ->
|
||||
val enabled = if (phase in enabled) "(Enabled)" else ""
|
||||
val verbose = if (phase in verbose) "(Verbose)" else ""
|
||||
|
||||
println(String.format("%1$-50s %2$-50s %3$-10s", "${"\t".repeat(depth)}${phase.name}:", phase.description, "$enabled $verbose"))
|
||||
}
|
||||
}
|
||||
|
||||
private fun computeEnabled(config: CompilerConfiguration) =
|
||||
with(CommonConfigurationKeys) {
|
||||
val disabledPhases = phaseSetFromConfiguration(config, DISABLED_PHASES)
|
||||
phases.values.toSet() - disabledPhases
|
||||
}
|
||||
|
||||
private fun phaseSetFromConfiguration(config: CompilerConfiguration, key: CompilerConfigurationKey<Set<String>>): Set<AnyNamedPhase> {
|
||||
val phaseNames = config.get(key) ?: emptySet()
|
||||
if ("ALL" in phaseNames) return phases.values.toSet()
|
||||
return phaseNames.map { phases[it]!! }.toSet()
|
||||
}
|
||||
|
||||
fun enable(phase: AnyNamedPhase) {
|
||||
enabledMut.add(phase)
|
||||
}
|
||||
|
||||
fun disable(phase: AnyNamedPhase) {
|
||||
enabledMut.remove(phase)
|
||||
}
|
||||
fun switch(phase: AnyNamedPhase, onOff: Boolean) {
|
||||
if (onOff) {
|
||||
enable(phase)
|
||||
} else {
|
||||
disable(phase)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user