From ab1e334847d13c121428620814406e4e7598f49d Mon Sep 17 00:00:00 2001 From: Georgy Bronnikov Date: Mon, 10 Dec 2018 12:01:53 +0300 Subject: [PATCH] Reorganize phaser --- .../backend/common/CommonBackendContext.kt | 4 + .../kotlin/backend/common/CompilerPhase.kt | 229 ------------ .../jetbrains/kotlin/backend/common/Lower.kt | 7 +- .../lower/DefaultArgumentStubGenerator.kt | 7 + .../common/lower/InitializersLowering.kt | 18 +- .../common/lower/InnerClassesLowering.kt | 14 +- .../lower/KCallableNamePropertyLowering.kt | 10 +- .../backend/common/lower/LateinitLowering.kt | 16 +- .../common/lower/LocalDeclarationsLowering.kt | 15 +- .../common/lower/PropertiesLowering.kt | 8 +- .../common/lower/SharedVariablesLowering.kt | 10 +- .../backend/common/lower/TailrecLowering.kt | 7 + .../backend/common/phaser/CompilerPhase.kt | 133 +++++++ .../backend/common/phaser/DumperVerifier.kt | 48 +++ .../backend/common/phaser/PhaseBuilders.kt | 162 +++++++++ .../backend/common/phaser/PhaseConfig.kt | 81 +++++ .../ir/backend/js/JsIrBackendContext.kt | 9 +- .../kotlin/ir/backend/js/JsLoweringPhases.kt | 343 +++++++++--------- .../kotlin/ir/backend/js/JsPhaseRunner.kt | 32 -- .../kotlin/ir/backend/js/compiler.kt | 6 +- ...MoveBodilessDeclarationsToSeparatePlace.kt | 5 +- .../kotlin/backend/jvm/JvmBackendContext.kt | 17 +- .../jetbrains/kotlin/backend/jvm/JvmLower.kt | 82 ++++- .../kotlin/backend/jvm/JvmLoweringPhases.kt | 288 --------------- .../kotlin/backend/jvm/JvmPhaseRunner.kt | 19 - .../backend/jvm/lower/AnnotationLowering.kt | 10 +- .../backend/jvm/lower/BridgeLowering.kt | 9 +- .../jvm/lower/CallableReferenceLowering.kt | 9 +- .../ConstAndJvmFieldPropertiesLowering.kt | 10 +- .../backend/jvm/lower/EnumClassLowering.kt | 10 +- .../backend/jvm/lower/FileClassLowering.kt | 9 +- .../lower/FunctionNVarargInvokeLowering.kt | 9 +- .../jvm/lower/InterfaceDelegationLowering.kt | 10 +- .../backend/jvm/lower/InterfaceLowering.kt | 9 +- .../lower/JvmBuiltinOptimizationLowering.kt | 7 + .../jvm/lower/JvmCoercionToUnitPatcher.kt | 8 +- .../lower/JvmOverloadsAnnotationLowering.kt | 10 +- .../jvm/lower/JvmStaticAnnotationLowering.kt | 10 +- .../jvm/lower/JvmTypeOperatorLoweringPhase.kt | 9 +- .../MoveCompanionObjectFieldsLowering.kt | 10 +- .../backend/jvm/lower/ObjectClassLowering.kt | 10 +- .../jvm/lower/SingletonReferencesLowering.kt | 10 +- .../lower/StaticDefaultFunctionLowering.kt | 11 +- .../jvm/lower/SyntheticAccessorLowering.kt | 10 +- .../backend/jvm/lower/ToArrayLowering.kt | 10 +- 45 files changed, 937 insertions(+), 823 deletions(-) delete mode 100644 compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/CompilerPhase.kt create mode 100644 compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/phaser/CompilerPhase.kt create mode 100644 compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/phaser/DumperVerifier.kt create mode 100644 compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/phaser/PhaseBuilders.kt create mode 100644 compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/phaser/PhaseConfig.kt delete mode 100644 compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsPhaseRunner.kt delete mode 100644 compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLoweringPhases.kt delete mode 100644 compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmPhaseRunner.kt diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/CommonBackendContext.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/CommonBackendContext.kt index 58c02758702..06f8dd62d57 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/CommonBackendContext.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/CommonBackendContext.kt @@ -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 fun report(element: IrElement?, irFile: IrFile?, message: String, isError: Boolean) + + val configuration: CompilerConfiguration } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/CompilerPhase.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/CompilerPhase.kt deleted file mode 100644 index 72272ce9508..00000000000 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/CompilerPhase.kt +++ /dev/null @@ -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 { - val name: String - val description: String - val prerequisite: Set> - get() = emptySet() - - fun invoke(context: Context, input: Data): Data -} - -private typealias AnyPhase = CompilerPhase<*, *> - -class CompilerPhases(private val phaseList: List, config: CompilerConfiguration) { - - val phases = phaseList.associate { it.name to it } - - val enabled = computeEnabled(config) - val verbose = phaseSetFromConfiguration(config, CommonConfigurationKeys.VERBOSE_PHASES) - - val toDumpStateBefore: Set - val toDumpStateAfter: Set - - val toValidateStateBefore: Set - val toValidateStateAfter: Set - - 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 { - val phaseNames = config.get(key) ?: emptySet() - if ("ALL" in phaseNames) return phases.values.toSet() - return phaseNames.map { phases[it]!! }.toSet() - } -} - - -interface PhaseRunner { - fun runBefore(phase: CompilerPhase, depth: Int, context: Context, data: Data) - fun runBody(phase: CompilerPhase, context: Context, source: Data): Data - fun runAfter(phase: CompilerPhase, depth: Int, context: Context, data: Data) -} - -abstract class DefaultIrPhaseRunner(private val validator: (data: Data, context: Context) -> Unit = { _, _ -> }) : - PhaseRunner { - - enum class BeforeOrAfter { BEFORE, AFTER } - - abstract val startPhaseMarker: CompilerPhase - abstract val endPhaseMarker: CompilerPhase - - private var inVerbosePhase = false - - final override fun runBefore(phase: CompilerPhase, 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: 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, 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, set: Set, block: () -> Unit) { - if (phase in set) block() - } - - private fun dumpElement(input: Data, phase: CompilerPhase, 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: 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: Context, source: Data) = - phase.invoke(context, source) -} - -class CompilerPhaseManager( - val context: Context, - val phases: CompilerPhases, - val data: Data, - private val phaseRunner: PhaseRunner, - val parent: CompilerPhaseManager? = null -) { - val depth: Int = parent?.depth?.inc() ?: 0 - - private val previousPhases = mutableSetOf>() - - fun createChild( - newData: NewData, - newPhaseRunner: PhaseRunner - ) = 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: 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 makePhase( - lowering: (Context, Data) -> Unit, - description: String, - name: String, - prerequisite: Set> = emptySet() -) = object : CompilerPhase { - 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" -} \ No newline at end of file diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/Lower.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/Lower.kt index bbef458830d..12a1a782e18 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/Lower.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/Lower.kt @@ -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) { diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt index 7b06ae75753..6be43b1e8c4 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt @@ -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( diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InitializersLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InitializersLowering.kt index bf151552c13..8748107164e 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InitializersLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InitializersLowering.kt @@ -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, diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InnerClassesLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InnerClassesLowering.kt index f640df43aa8..0be13f545e6 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InnerClassesLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InnerClassesLowering.kt @@ -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() { diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/KCallableNamePropertyLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/KCallableNamePropertyLowering.kt index 4b8b5aef5c5..76853ad85f3 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/KCallableNamePropertyLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/KCallableNamePropertyLowering.kt @@ -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)) } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LateinitLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LateinitLowering.kt index 4bdd5cc62e8..2028ae41565 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LateinitLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LateinitLowering.kt @@ -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 { - 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) { diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt index e8b036f5369..e344389dc21 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt @@ -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() diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/PropertiesLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/PropertiesLowering.kt index dc089494e5f..a481261918c 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/PropertiesLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/PropertiesLowering.kt @@ -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() diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/SharedVariablesLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/SharedVariablesLowering.kt index 77ea77feb9c..c333ba99ed8 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/SharedVariablesLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/SharedVariablesLowering.kt @@ -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 { diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/TailrecLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/TailrecLowering.kt index 5030b937fd6..ea2eb498d91 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/TailrecLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/TailrecLowering.kt @@ -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. * diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/phaser/CompilerPhase.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/phaser/CompilerPhase.kt new file mode 100644 index 00000000000..c431ced6974 --- /dev/null +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/phaser/CompilerPhase.kt @@ -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() + var depth = 0 +} + +fun PhaserState.downlevel(nlevels: Int = 1, block: () -> R): R { + depth += nlevels + val result = block() + depth -= nlevels + return result +} + +interface CompilerPhase { + fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: Input): Output + + fun getNamedSubphases(startDepth: Int = 0): List>> = emptyList() +} + +fun CompilerPhase.invokeToplevel( + phaseConfig: PhaseConfig, + context: Context, + input: Input +): Output = invoke(phaseConfig, PhaserState(), context, input) + +interface SameTypeCompilerPhase : CompilerPhase + +interface NamedCompilerPhase : CompilerPhase { + val name: String + val description: String + val prerequisite: Set get() = emptySet() +} + +typealias AnyNamedPhase = NamedCompilerPhase<*, *, *> + +enum class BeforeOrAfter { BEFORE, AFTER } + +interface PhaseDumperVerifier { + fun dump(phase: AnyNamedPhase, context: Context, data: Data, beforeOrAfter: BeforeOrAfter) + fun verify(context: Context, data: Data) +} + +abstract class AbstractNamedPhaseWrapper( + override val name: String, + override val description: String, + override val prerequisite: Set, + private val nlevels: Int = 0, + private val lower: CompilerPhase +) : NamedCompilerPhase { + abstract val inputDumperVerifier: PhaseDumperVerifier + abstract val outputDumperVerifier: PhaseDumperVerifier + + 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, block: () -> Unit) { + if (this in set) block() + } + + override fun getNamedSubphases(startDepth: Int): List>> = + listOf(startDepth to this) + lower.getNamedSubphases(startDepth + nlevels) + + override fun toString() = "Compiler Phase @$name" +} + +class SameTypeNamedPhaseWrapper( + name: String, + description: String, + prerequisite: Set, + nlevels: Int = 0, + lower: CompilerPhase, + val dumperVerifier: PhaseDumperVerifier +) : AbstractNamedPhaseWrapper(name, description, prerequisite, nlevels, lower), SameTypeCompilerPhase { + override val inputDumperVerifier get() = dumperVerifier + override val outputDumperVerifier get() = dumperVerifier +} diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/phaser/DumperVerifier.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/phaser/DumperVerifier.kt new file mode 100644 index 00000000000..be110d79d2d --- /dev/null +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/phaser/DumperVerifier.kt @@ -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( + val verifier: (Context, Data) -> Unit +) : PhaseDumperVerifier { + 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(verifier: (Context, IrFile) -> Unit) : + IrPhaseDumperVerifier(verifier) { + override fun IrFile.getElementName() = name +} + +class IrModuleDumperVerifier(verifier: (Context, IrModuleFragment) -> Unit) : + IrPhaseDumperVerifier(verifier) { + override fun IrModuleFragment.getElementName() = name.asString() +} + +class EmptyDumperVerifier : PhaseDumperVerifier { + override fun dump(phase: AnyNamedPhase, context: Context, data: Data, beforeOrAfter: BeforeOrAfter) {} + override fun verify(context: Context, data: Data) {} +} + diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/phaser/PhaseBuilders.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/phaser/PhaseBuilders.kt new file mode 100644 index 00000000000..23b7f757bce --- /dev/null +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/phaser/PhaseBuilders.kt @@ -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 CompilerPhase.then( + other: CompilerPhase +) = object : CompilerPhase { + 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 namedIrModulePhase( + name: String, + description: String, + prerequisite: Set = emptySet(), + verify: (Context, IrModuleFragment) -> Unit = { _, _ -> }, + nlevels: Int = 1, + lower: CompilerPhase +) = SameTypeNamedPhaseWrapper(name, description, prerequisite, nlevels, lower, IrModuleDumperVerifier(verify)) + +fun namedIrFilePhase( + name: String, + description: String, + prerequisite: Set = emptySet(), + verify: (Context, IrFile) -> Unit = { _, _ -> }, + nlevels: Int = 1, + lower: CompilerPhase +) = SameTypeNamedPhaseWrapper(name, description, prerequisite, nlevels, lower, IrFileDumperVerifier(verify)) + +fun namedUnitPhase( + name: String, + description: String, + prerequisite: Set = emptySet(), + nlevels: Int = 1, + lower: CompilerPhase +) = SameTypeNamedPhaseWrapper(name, description, prerequisite, nlevels, lower, EmptyDumperVerifier()) + +fun namedOpUnitPhase( + name: String, + description: String, + prerequisite: Set, + op: Context.() -> Unit +) = namedUnitPhase( + name, description, prerequisite, + nlevels = 0, + lower = object : SameTypeCompilerPhase { + override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: Unit) { + context.op() + } + } +) + +fun performByIrFile( + name: String = "PerformByIrFile", + description: String = "Perform phases by IrFile", + prerequisite: Set = emptySet(), + verify: (Context, IrModuleFragment) -> Unit = { _, _ -> }, + lower: CompilerPhase +) = namedIrModulePhase( + name, description, prerequisite, verify, + nlevels = 1, + lower = object : SameTypeCompilerPhase { + 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 makeIrFilePhase( + lowering: (Context) -> FileLoweringPass, + name: String, + description: String, + prerequisite: Set = emptySet(), + verify: (Context, IrFile) -> Unit = { _, _ -> } +) = namedIrFilePhase( + name, description, prerequisite, verify, + nlevels = 0, + lower = object : SameTypeCompilerPhase { + override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: IrFile): IrFile { + lowering(context).lower(input) + return input + } + } +) + +fun makeIrModulePhase( + lowering: (Context) -> FileLoweringPass, + name: String, + description: String, + prerequisite: Set = emptySet(), + verify: (Context, IrModuleFragment) -> Unit = { _, _ -> } +) = namedIrModulePhase( + name, description, prerequisite, verify, + nlevels = 0, + lower = object : SameTypeCompilerPhase { + override fun invoke( + phaseConfig: PhaseConfig, + phaserState: PhaserState, + context: Context, + input: IrModuleFragment + ): IrModuleFragment { + lowering(context).lower(input) + return input + } + } +) + +fun unitPhase( + name: String, + description: String, + prerequisite: Set, + op: Context.() -> Unit +) = + object : AbstractNamedPhaseWrapper( + name, description, prerequisite, + nlevels = 0, + lower = object : CompilerPhase { + override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: Input) { + context.op() + } + } + ) { + override val inputDumperVerifier = EmptyDumperVerifier() + override val outputDumperVerifier = EmptyDumperVerifier() + } + +fun unitSink() = object : CompilerPhase { + override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: Input) {} +} + +// Intermediate phases to change the object of transformations +fun takeFromContext(op: (Context) -> NewData) = + object : CompilerPhase { + override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: OldData) = op(context) + } + +fun transform(op: (OldData) -> NewData) = + object : CompilerPhase { + override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: OldData) = op(input) + } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/phaser/PhaseConfig.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/phaser/PhaseConfig.kt new file mode 100644 index 00000000000..7079cd7a29d --- /dev/null +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/phaser/PhaseConfig.kt @@ -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 get() = enabledMut + + val verbose = phaseSetFromConfiguration(config, CommonConfigurationKeys.VERBOSE_PHASES) + val toDumpStateBefore: Set + + val toDumpStateAfter: Set + val toValidateStateBefore: Set + + val toValidateStateAfter: Set + + 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 { + 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) + } + } +} diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt index fb6b7bb1fe3..c2e89548701 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt @@ -6,11 +6,11 @@ package org.jetbrains.kotlin.ir.backend.js import org.jetbrains.kotlin.backend.common.CommonBackendContext -import org.jetbrains.kotlin.backend.common.CompilerPhases import org.jetbrains.kotlin.backend.common.atMostOne import org.jetbrains.kotlin.backend.common.descriptors.KnownPackageFragmentDescriptor import org.jetbrains.kotlin.backend.common.ir.Ir import org.jetbrains.kotlin.backend.common.ir.Symbols +import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig import org.jetbrains.kotlin.backend.js.JsDeclarationFactory import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.config.CompilerConfiguration @@ -47,13 +47,14 @@ class JsIrBackendContext( override val irBuiltIns: IrBuiltIns, val symbolTable: SymbolTable, irModuleFragment: IrModuleFragment, - val configuration: CompilerConfiguration, + override val configuration: CompilerConfiguration, val dependencies: List ) : CommonBackendContext { override val builtIns = module.builtIns - val phases = CompilerPhases(jsPhases, configuration) + val phaseConfig = PhaseConfig(jsPhases, configuration) + override var inVerbosePhase: Boolean = false val internalPackageFragmentDescriptor = KnownPackageFragmentDescriptor(builtIns.builtInsModule, FqName("kotlin.js.internal")) val implicitDeclarationFile by lazy { @@ -283,7 +284,7 @@ class JsIrBackendContext( override fun log(message: () -> String) { /*TODO*/ - print(message()) + if (inVerbosePhase) print(message()) } override fun report(element: IrElement?, irFile: IrFile?, message: String, isError: Boolean) { diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt index e93ced2137b..351b22b8cf7 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.ir.backend.js import org.jetbrains.kotlin.backend.common.* import org.jetbrains.kotlin.backend.common.lower.* +import org.jetbrains.kotlin.backend.common.phaser.* import org.jetbrains.kotlin.ir.backend.js.lower.* import org.jetbrains.kotlin.ir.backend.js.lower.calls.CallsLowering import org.jetbrains.kotlin.ir.backend.js.lower.coroutines.CoroutineIntrinsicLowering @@ -21,65 +22,90 @@ import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols import org.jetbrains.kotlin.ir.util.patchDeclarationParents -private fun FileLoweringPass.lower(moduleFragment: IrModuleFragment) = moduleFragment.files.forEach { lower(it) } - private fun DeclarationContainerLoweringPass.runOnFilesPostfix(files: Iterable) = files.forEach { runOnFilePostfix(it) } private fun ClassLoweringPass.runOnFilesPostfix(moduleFragment: IrModuleFragment) = moduleFragment.files.forEach { runOnFilePostfix(it) } - -object IrModuleStartPhase : CompilerPhase { - override val name = "IrModuleFragment" - override val description = "State at start of IrModuleFragment lowering" - override val prerequisite = emptySet() - override fun invoke(context: BackendContext, input: IrModuleFragment) = input +private fun validationCallback(context: JsIrBackendContext, module: IrModuleFragment) { + val validatorConfig = IrValidatorConfig( + abortOnError = true, + ensureAllNodesAreDifferent = true, + checkTypes = false, + checkDescriptors = false + ) + module.accept(IrValidator(context, validatorConfig), null) + module.accept(CheckDeclarationParentsVisitor, null) } -private fun makeJsPhase( - lowering: (JsIrBackendContext, IrModuleFragment) -> Unit, +private fun makeJsModulePhase( + lowering: (JsIrBackendContext) -> FileLoweringPass, + name: String, + description: String, + prerequisite: Set = emptySet() +) = makeIrModulePhase(lowering, name, description, prerequisite, verify = ::validationCallback) + +private fun makeCustomJsModulePhase( + op: (JsIrBackendContext, IrModuleFragment) -> Unit, description: String, name: String, - prerequisite: Set> = emptySet() -) = makePhase(lowering, description, name, prerequisite) + prerequisite: Set = emptySet() +) = namedIrModulePhase( + name, + description, + prerequisite, + verify = ::validationCallback, + nlevels = 0, + lower = object : SameTypeCompilerPhase { + override fun invoke( + phaseConfig: PhaseConfig, + phaserState: PhaserState, + context: JsIrBackendContext, + input: IrModuleFragment + ): IrModuleFragment { + op(context, input) + return input + } + } +) -private val MoveBodilessDeclarationsToSeparatePlacePhase = makeJsPhase( - { _, module -> MoveBodilessDeclarationsToSeparatePlace().lower(module) }, +private val moveBodilessDeclarationsToSeparatePlacePhase = makeJsModulePhase( + ::MoveBodilessDeclarationsToSeparatePlace, name = "MoveBodilessDeclarationsToSeparatePlace", description = "Move `external` and `built-in` declarations into separate place to make the following lowerings do not care about them" ) -private val ExpectDeclarationsRemovingPhase = makeJsPhase( - { context, module -> ExpectDeclarationsRemoving(context).lower(module) }, +private val expectDeclarationsRemovingPhase = makeJsModulePhase( + ::ExpectDeclarationsRemoving, name = "ExpectDeclarationsRemoving", description = "Remove expect declaration from module fragment" ) -private val CoroutineIntrinsicLoweringPhase = makeJsPhase( - { context, module -> CoroutineIntrinsicLowering(context).lower(module) }, +private val coroutineIntrinsicLoweringPhase = makeJsModulePhase( + ::CoroutineIntrinsicLowering, name = "CoroutineIntrinsicLowering", description = "Replace common coroutine intrinsics with platform specific ones" ) -private val ArrayInlineConstructorLoweringPhase = makeJsPhase( - { context, module -> ArrayInlineConstructorLowering(context).lower(module) }, +private val arrayInlineConstructorLoweringPhase = makeJsModulePhase( + ::ArrayInlineConstructorLowering, name = "ArrayInlineConstructorLowering", description = "Replace array constructor with platform specific factory functions" ) -private val LateinitLoweringPhase = makeJsPhase( - { context, module -> LateinitLowering(context).lower(module) }, +private val lateinitLoweringPhase = makeJsModulePhase( + ::LateinitLowering, name = "LateinitLowering", description = "Insert checks for lateinit field references" ) -private val ModuleCopyingPhase = makeJsPhase( +private val moduleCopyingPhase = makeCustomJsModulePhase( { context, module -> context.moduleFragmentCopy = module.deepCopyWithSymbols() }, name = "ModuleCopying", description = " Copy current module to make it accessible from different one", - prerequisite = setOf(LateinitLoweringPhase) + prerequisite = setOf(lateinitLoweringPhase) ) -private val FunctionInliningPhase = makeJsPhase( +private val functionInliningPhase = makeCustomJsModulePhase( { context, module -> FunctionInlining(context).inline(module) module.replaceUnboundSymbols(context) @@ -87,190 +113,190 @@ private val FunctionInliningPhase = makeJsPhase( }, name = "FunctionInliningPhase", description = "Perform function inlining", - prerequisite = setOf(ModuleCopyingPhase, LateinitLoweringPhase, ArrayInlineConstructorLoweringPhase, CoroutineIntrinsicLoweringPhase) + prerequisite = setOf(moduleCopyingPhase, lateinitLoweringPhase, arrayInlineConstructorLoweringPhase, coroutineIntrinsicLoweringPhase) ) -private val RemoveInlineFunctionsWithReifiedTypeParametersLoweringPhase = makeJsPhase( - { _, module -> RemoveInlineFunctionsWithReifiedTypeParametersLowering().lower(module) }, +private val removeInlineFunctionsWithReifiedTypeParametersLoweringPhase = makeJsModulePhase( + { RemoveInlineFunctionsWithReifiedTypeParametersLowering() }, name = "RemoveInlineFunctionsWithReifiedTypeParametersLowering", description = "Remove Inline functions with reified parameters from context", - prerequisite = setOf(FunctionInliningPhase) + prerequisite = setOf(functionInliningPhase) ) -private val ThrowableSuccessorsLoweringPhase = makeJsPhase( - { context, module -> ThrowableSuccessorsLowering(context).lower(module) }, +private val throwableSuccessorsLoweringPhase = makeJsModulePhase( + ::ThrowableSuccessorsLowering, name = "ThrowableSuccessorsLowering", description = "Link kotlin.Throwable and JavaScript Error together to provide proper interop between language and platform exceptions" ) -private val TailrecLoweringPhase = makeJsPhase( - { context, module -> TailrecLowering(context).lower(module) }, +private val tailrecLoweringPhase = makeJsModulePhase( + ::TailrecLowering, name = "TailrecLowering", description = "Replace `tailrec` callsites with equivalent loop" ) -private val UnitMaterializationLoweringPhase = makeJsPhase( - { context, module -> UnitMaterializationLowering(context).lower(module) }, +private val unitMaterializationLoweringPhase = makeJsModulePhase( + ::UnitMaterializationLowering, name = "UnitMaterializationLowering", description = "Insert Unit object where it is supposed to be", - prerequisite = setOf(TailrecLoweringPhase) + prerequisite = setOf(tailrecLoweringPhase) ) -private val EnumClassLoweringPhase = makeJsPhase( - { context, module -> EnumClassLowering(context).lower(module) }, +private val enumClassLoweringPhase = makeJsModulePhase( + ::EnumClassLowering, name = "EnumClassLowering", description = "Transform Enum Class into regular Class" ) -private val EnumUsageLoweringPhase = makeJsPhase( - { context, module -> EnumUsageLowering(context).lower(module) }, +private val enumUsageLoweringPhase = makeJsModulePhase( + ::EnumUsageLowering, name = "EnumUsageLowering", description = "Replace enum access with invocation of corresponding function" ) -private val SharedVariablesLoweringPhase = makeJsPhase( - { context, module -> SharedVariablesLowering(context).lower(module) }, +private val sharedVariablesLoweringPhase = makeJsModulePhase( + ::SharedVariablesLowering, name = "SharedVariablesLowering", description = "Box captured mutable variables" ) -private val ReturnableBlockLoweringPhase = makeJsPhase( - { context, module -> ReturnableBlockLowering(context).lower(module) }, +private val returnableBlockLoweringPhase = makeJsModulePhase( + ::ReturnableBlockLowering, name = "ReturnableBlockLowering", description = "Replace returnable block with do-while loop", - prerequisite = setOf(FunctionInliningPhase) + prerequisite = setOf(functionInliningPhase) ) -private val LocalDelegatedPropertiesLoweringPhase = makeJsPhase( - { _, module -> LocalDelegatedPropertiesLowering().lower(module) }, +private val localDelegatedPropertiesLoweringPhase = makeJsModulePhase( + { LocalDelegatedPropertiesLowering() }, name = "LocalDelegatedPropertiesLowering", description = "Transform Local Delegated properties" ) -private val LocalDeclarationsLoweringPhase = makeJsPhase( - { context, module -> LocalDeclarationsLowering(context).lower(module) }, +private val localDeclarationsLoweringPhase = makeJsModulePhase( + ::LocalDeclarationsLowering, name = "LocalDeclarationsLowering", description = "Move local declarations into nearest declaration container", - prerequisite = setOf(SharedVariablesLoweringPhase) + prerequisite = setOf(sharedVariablesLoweringPhase) ) -private val InnerClassesLoweringPhase = makeJsPhase( - { context, module -> InnerClassesLowering(context).lower(module) }, +private val innerClassesLoweringPhase = makeJsModulePhase( + ::InnerClassesLowering, name = "InnerClassesLowering", description = "Capture outer this reference to inner class" ) -private val InnerClassConstructorCallsLoweringPhase = makeJsPhase( - { context, module -> InnerClassConstructorCallsLowering(context).lower(module) }, +private val innerClassConstructorCallsLoweringPhase = makeJsModulePhase( + ::InnerClassConstructorCallsLowering, name = "InnerClassConstructorCallsLowering", description = "Replace inner class constructor invocation" ) -private val SuspendFunctionsLoweringPhase = makeJsPhase( - { context, module -> SuspendFunctionsLowering(context).lower(module) }, +private val suspendFunctionsLoweringPhase = makeJsModulePhase( + ::SuspendFunctionsLowering, name = "SuspendFunctionsLowering", description = "Transform suspend functions into CoroutineImpl instance and build state machine", - prerequisite = setOf(UnitMaterializationLoweringPhase, CoroutineIntrinsicLoweringPhase) + prerequisite = setOf(unitMaterializationLoweringPhase, coroutineIntrinsicLoweringPhase) ) -private val PrivateMembersLoweringPhase = makeJsPhase( - { context, module -> PrivateMembersLowering(context).lower(module) }, +private val privateMembersLoweringPhase = makeJsModulePhase( + ::PrivateMembersLowering, name = "PrivateMembersLowering", description = "Extract private members from classes" ) -private val CallableReferenceLoweringPhase = makeJsPhase( - { context, module -> CallableReferenceLowering(context).lower(module) }, +private val callableReferenceLoweringPhase = makeJsModulePhase( + ::CallableReferenceLowering, name = "CallableReferenceLowering", description = "Handle callable references", prerequisite = setOf( - SuspendFunctionsLoweringPhase, - LocalDeclarationsLoweringPhase, - LocalDelegatedPropertiesLoweringPhase, - PrivateMembersLoweringPhase + suspendFunctionsLoweringPhase, + localDeclarationsLoweringPhase, + localDelegatedPropertiesLoweringPhase, + privateMembersLoweringPhase ) ) -private val DefaultArgumentStubGeneratorPhase = makeJsPhase( - { context, module -> JsDefaultArgumentStubGenerator(context).lower(module) }, +private val defaultArgumentStubGeneratorPhase = makeJsModulePhase( + ::JsDefaultArgumentStubGenerator, name = "DefaultArgumentStubGenerator", description = "Generate synthetic stubs for functions with default parameter values" ) -private val DefaultParameterInjectorPhase = makeJsPhase( - { context, module -> DefaultParameterInjector(context).lower(module) }, +private val defaultParameterInjectorPhase = makeJsModulePhase( + ::DefaultParameterInjector, name = "DefaultParameterInjector", description = "Replace callsite with default parameters with corresponding stub function", - prerequisite = setOf(CallableReferenceLoweringPhase, InnerClassesLoweringPhase) + prerequisite = setOf(callableReferenceLoweringPhase, innerClassesLoweringPhase) ) -private val DefaultParameterCleanerPhase = makeJsPhase( - { context, module -> DefaultParameterCleaner(context).lower(module) }, +private val defaultParameterCleanerPhase = makeJsModulePhase( + ::DefaultParameterCleaner, name = "DefaultParameterCleaner", description = "Clean default parameters up" ) -private val JsDefaultCallbackGeneratorPhase = makeJsPhase( - { context, module -> JsDefaultCallbackGenerator(context).lower(module) }, +private val jsDefaultCallbackGeneratorPhase = makeJsModulePhase( + ::JsDefaultCallbackGenerator, name = "JsDefaultCallbackGenerator", description = "Build binding for super calls with default parameters" ) -private val VarargLoweringPhase = makeJsPhase( - { context, module -> VarargLowering(context).lower(module) }, +private val varargLoweringPhase = makeJsModulePhase( + ::VarargLowering, name = "VarargLowering", description = "Lower vararg arguments", - prerequisite = setOf(CallableReferenceLoweringPhase) + prerequisite = setOf(callableReferenceLoweringPhase) ) -private val PropertiesLoweringPhase = makeJsPhase( - { _, module -> PropertiesLowering().lower(module) }, +private val propertiesLoweringPhase = makeJsModulePhase( + { PropertiesLowering() }, name = "PropertiesLowering", description = "Move fields and accessors out from its property" ) -private val InitializersLoweringPhase = makeJsPhase( +private val initializersLoweringPhase = makeCustomJsModulePhase( { context, module -> InitializersLowering(context, JsLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER, false).lower(module) }, name = "InitializersLowering", description = "Merge init block and field initializers into [primary] constructor", - prerequisite = setOf(EnumClassLoweringPhase) + prerequisite = setOf(enumClassLoweringPhase) ) -private val MultipleCatchesLoweringPhase = makeJsPhase( - { context, module -> MultipleCatchesLowering(context).lower(module) }, +private val multipleCatchesLoweringPhase = makeJsModulePhase( + ::MultipleCatchesLowering, name = "MultipleCatchesLowering", description = "Replace multiple catches with single one" ) -private val BridgesConstructionPhase = makeJsPhase( - { context, module -> BridgesConstruction(context).lower(module) }, +private val bridgesConstructionPhase = makeJsModulePhase( + ::BridgesConstruction, name = "BridgesConstruction", description = "Generate bridges", - prerequisite = setOf(SuspendFunctionsLoweringPhase) + prerequisite = setOf(suspendFunctionsLoweringPhase) ) -private val TypeOperatorLoweringPhase = makeJsPhase( - { context, module -> TypeOperatorLowering(context).lower(module) }, +private val typeOperatorLoweringPhase = makeJsModulePhase( + ::TypeOperatorLowering, name = "TypeOperatorLowering", description = "Lower IrTypeOperator with corresponding logic", - prerequisite = setOf(BridgesConstructionPhase, RemoveInlineFunctionsWithReifiedTypeParametersLoweringPhase) + prerequisite = setOf(bridgesConstructionPhase, removeInlineFunctionsWithReifiedTypeParametersLoweringPhase) ) -private val SecondaryConstructorLoweringPhase = makeJsPhase( - { context, module -> SecondaryConstructorLowering(context).lower(module) }, +private val secondaryConstructorLoweringPhase = makeJsModulePhase( + ::SecondaryConstructorLowering, name = "SecondaryConstructorLoweringPhase", description = "Generate static functions for each secondary constructor", - prerequisite = setOf(InnerClassesLoweringPhase) + prerequisite = setOf(innerClassesLoweringPhase) ) -private val SecondaryFactoryInjectorLoweringPhase = makeJsPhase( - { context, module -> SecondaryFactoryInjectorLowering(context).lower(module) }, +private val secondaryFactoryInjectorLoweringPhase = makeJsModulePhase( + ::SecondaryFactoryInjectorLowering, name = "SecondaryFactoryInjectorLoweringPhase", description = "Replace usage of secondary constructor with corresponding static function", - prerequisite = setOf(InnerClassesLoweringPhase) + prerequisite = setOf(innerClassesLoweringPhase) ) -private val InlineClassLoweringPhase = makeJsPhase( +private val inlineClassLoweringPhase = makeCustomJsModulePhase( { context, module -> InlineClassLowering(context).run { inlineClassDeclarationLowering.runOnFilesPostfix(module) @@ -281,102 +307,95 @@ private val InlineClassLoweringPhase = makeJsPhase( description = "Handle inline classes" ) -private val AutoboxingTransformerPhase = makeJsPhase( - { context, module -> AutoboxingTransformer(context).lower(module) }, +private val autoboxingTransformerPhase = makeJsModulePhase( + ::AutoboxingTransformer, name = "AutoboxingTransformer", description = "Insert box/unbox intrinsics" ) -private val BlockDecomposerLoweringPhase = makeJsPhase( +private val blockDecomposerLoweringPhase = makeCustomJsModulePhase( { context, module -> BlockDecomposerLowering(context).lower(module) module.patchDeclarationParents() }, name = "BlockDecomposerLowering", description = "Transform statement-like-expression nodes into pure-statement to make it easily transform into JS", - prerequisite = setOf(TypeOperatorLoweringPhase, SuspendFunctionsLoweringPhase) + prerequisite = setOf(typeOperatorLoweringPhase, suspendFunctionsLoweringPhase) ) -private val ClassReferenceLoweringPhase = makeJsPhase( - { context, module -> ClassReferenceLowering(context).lower(module) }, +private val classReferenceLoweringPhase = makeJsModulePhase( + ::ClassReferenceLowering, name = "ClassReferenceLowering", description = "Handle class references" ) -private val PrimitiveCompanionLoweringPhase = makeJsPhase( - { context, module -> PrimitiveCompanionLowering(context).lower(module) }, +private val primitiveCompanionLoweringPhase = makeJsModulePhase( + ::PrimitiveCompanionLowering, name = "PrimitiveCompanionLowering", description = "Replace common companion object access with platform one" ) -private val ConstLoweringPhase = makeJsPhase( - { context, module -> ConstLowering(context).lower(module) }, +private val constLoweringPhase = makeJsModulePhase( + ::ConstLowering, name = "ConstLowering", description = "Wrap Long and Char constants into constructor invocation" ) -private val CallsLoweringPhase = makeJsPhase( - { context, module -> CallsLowering(context).lower(module) }, +private val callsLoweringPhase = makeJsModulePhase( + ::CallsLowering, name = "CallsLowering", description = "Handle intrinsics" ) -object IrModuleEndPhase : CompilerPhase { - override val name = "IrModuleFragment" - override val description = "State at end of IrModuleFragment lowering" - override val prerequisite = emptySet() - override fun invoke(context: BackendContext, input: IrModuleFragment) = input -} - -private val IrToJsPhase = makeJsPhase( +private val irToJsPhase = makeCustomJsModulePhase( { context, module -> context.jsProgram = IrModuleToJsTransformer(context).let { module.accept(it, null) } }, name = "IrModuleToJsTransformer", description = "Generate JsAst from IrTree" ) -val jsPhases = listOf( - IrModuleStartPhase, - MoveBodilessDeclarationsToSeparatePlacePhase, - ExpectDeclarationsRemovingPhase, - CoroutineIntrinsicLoweringPhase, - ArrayInlineConstructorLoweringPhase, - LateinitLoweringPhase, - ModuleCopyingPhase, - FunctionInliningPhase, - RemoveInlineFunctionsWithReifiedTypeParametersLoweringPhase, - ThrowableSuccessorsLoweringPhase, - TailrecLoweringPhase, - UnitMaterializationLoweringPhase, - EnumClassLoweringPhase, - EnumUsageLoweringPhase, - SharedVariablesLoweringPhase, - ReturnableBlockLoweringPhase, - LocalDelegatedPropertiesLoweringPhase, - LocalDeclarationsLoweringPhase, - InnerClassesLoweringPhase, - InnerClassConstructorCallsLoweringPhase, - SuspendFunctionsLoweringPhase, - PrivateMembersLoweringPhase, - CallableReferenceLoweringPhase, - DefaultArgumentStubGeneratorPhase, - DefaultParameterInjectorPhase, - DefaultParameterCleanerPhase, - JsDefaultCallbackGeneratorPhase, - VarargLoweringPhase, - PropertiesLoweringPhase, - InitializersLoweringPhase, - MultipleCatchesLoweringPhase, - BridgesConstructionPhase, - TypeOperatorLoweringPhase, - SecondaryConstructorLoweringPhase, - SecondaryFactoryInjectorLoweringPhase, - ClassReferenceLoweringPhase, - InlineClassLoweringPhase, - AutoboxingTransformerPhase, - BlockDecomposerLoweringPhase, - PrimitiveCompanionLoweringPhase, - ConstLoweringPhase, - CallsLoweringPhase, - IrModuleEndPhase, - IrToJsPhase -) +val jsPhases = namedIrModulePhase( + name = "IrModuleLowering", + description = "IR module lowering", + lower = moveBodilessDeclarationsToSeparatePlacePhase then + expectDeclarationsRemovingPhase then + coroutineIntrinsicLoweringPhase then + arrayInlineConstructorLoweringPhase then + lateinitLoweringPhase then + moduleCopyingPhase then + functionInliningPhase then + removeInlineFunctionsWithReifiedTypeParametersLoweringPhase then + throwableSuccessorsLoweringPhase then + tailrecLoweringPhase then + unitMaterializationLoweringPhase then + enumClassLoweringPhase then + enumUsageLoweringPhase then + sharedVariablesLoweringPhase then + returnableBlockLoweringPhase then + localDelegatedPropertiesLoweringPhase then + localDeclarationsLoweringPhase then + innerClassesLoweringPhase then + innerClassConstructorCallsLoweringPhase then + suspendFunctionsLoweringPhase then + privateMembersLoweringPhase then + callableReferenceLoweringPhase then + defaultArgumentStubGeneratorPhase then + defaultParameterInjectorPhase then + defaultParameterCleanerPhase then + jsDefaultCallbackGeneratorPhase then + varargLoweringPhase then + propertiesLoweringPhase then + initializersLoweringPhase then + multipleCatchesLoweringPhase then + bridgesConstructionPhase then + typeOperatorLoweringPhase then + secondaryConstructorLoweringPhase then + secondaryFactoryInjectorLoweringPhase then + classReferenceLoweringPhase then + inlineClassLoweringPhase then + autoboxingTransformerPhase then + blockDecomposerLoweringPhase then + primitiveCompanionLoweringPhase then + constLoweringPhase then + callsLoweringPhase then + irToJsPhase +) \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsPhaseRunner.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsPhaseRunner.kt deleted file mode 100644 index cf80f44752c..00000000000 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsPhaseRunner.kt +++ /dev/null @@ -1,32 +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.ir.backend.js - -import org.jetbrains.kotlin.backend.common.CheckDeclarationParentsVisitor -import org.jetbrains.kotlin.backend.common.DefaultIrPhaseRunner -import org.jetbrains.kotlin.backend.common.IrValidator -import org.jetbrains.kotlin.backend.common.IrValidatorConfig -import org.jetbrains.kotlin.ir.declarations.IrModuleFragment - -private fun validationCallback(module: IrModuleFragment, context: JsIrBackendContext) { - val validatorConfig = IrValidatorConfig( - abortOnError = true, - ensureAllNodesAreDifferent = true, - checkTypes = false, - checkDescriptors = false - ) - module.accept(IrValidator(context, validatorConfig), null) - module.accept(CheckDeclarationParentsVisitor, null) -} - -object JsPhaseRunner : DefaultIrPhaseRunner(::validationCallback) { - override val startPhaseMarker = IrModuleStartPhase - override val endPhaseMarker = IrModuleEndPhase - - override fun phases(context: JsIrBackendContext) = context.phases - override fun elementName(input: IrModuleFragment) = input.name.asString() - override fun configuration(context: JsIrBackendContext) = context.configuration -} \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt index 307163a0762..e8eddd4cea9 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt @@ -6,7 +6,7 @@ package org.jetbrains.kotlin.ir.backend.js import com.intellij.openapi.project.Project -import org.jetbrains.kotlin.backend.common.CompilerPhaseManager +import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.descriptors.ModuleDescriptor @@ -62,9 +62,7 @@ fun compile( irDependencyModules ) - CompilerPhaseManager(context, context.phases, moduleFragment, JsPhaseRunner).run { - jsPhases.fold(data) { m, p -> phase(p, context, m) } - } + jsPhases.invokeToplevel(context.phaseConfig, context, moduleFragment) return Result(analysisResult.moduleDescriptor, context.jsProgram.toString(), context.moduleFragmentCopy) } \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MoveBodilessDeclarationsToSeparatePlace.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MoveBodilessDeclarationsToSeparatePlace.kt index 9a6095774d6..a3efe669fe0 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MoveBodilessDeclarationsToSeparatePlace.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MoveBodilessDeclarationsToSeparatePlace.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.ir.backend.js.lower import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor +import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.lower.inline.addChild import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrDeclaration @@ -18,7 +19,9 @@ import org.jetbrains.kotlin.ir.util.isEffectivelyExternal import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -class MoveBodilessDeclarationsToSeparatePlace : FileLoweringPass { +class MoveBodilessDeclarationsToSeparatePlace() : FileLoweringPass { + + constructor(context: JsIrBackendContext) : this() private val builtInClasses = listOf( "String", diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt index cada69f681a..9c492cf5b90 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt @@ -6,10 +6,9 @@ package org.jetbrains.kotlin.backend.jvm import org.jetbrains.kotlin.backend.common.CommonBackendContext -import org.jetbrains.kotlin.backend.common.CompilerPhaseManager -import org.jetbrains.kotlin.backend.common.CompilerPhases import org.jetbrains.kotlin.backend.common.ir.Ir import org.jetbrains.kotlin.backend.common.ir.Symbols +import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig import org.jetbrains.kotlin.backend.jvm.descriptors.JvmDeclarationFactory import org.jetbrains.kotlin.backend.jvm.descriptors.JvmSharedVariablesManager import org.jetbrains.kotlin.builtins.ReflectionTypes @@ -47,19 +46,17 @@ class JvmBackendContext( override val ir = JvmIr(irModuleFragment, symbolTable) - val phases = CompilerPhases(jvmPhases, state.configuration) + val phaseConfig = PhaseConfig(jvmPhases, state.configuration) + override var inVerbosePhase: Boolean = false + + override val configuration get() = state.configuration init { if (state.configuration.get(CommonConfigurationKeys.LIST_PHASES) == true) { - phases.list() + phaseConfig.list() } } - var inVerbosePhase = false - - fun rootPhaseManager(irFile: IrFile) = CompilerPhaseManager(this, phases, irFile, JvmPhaseRunner) - - private fun find(memberScope: MemberScope, className: String): ClassDescriptor { return find(memberScope, Name.identifier(className)) } @@ -146,7 +143,7 @@ class JvmBackendContext( override val coroutineSuspendedGetter: IrSimpleFunctionSymbol get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates. - override val lateinitIsInitializedPropertyGetter= symbolTable.referenceSimpleFunction( + override val lateinitIsInitializedPropertyGetter = symbolTable.referenceSimpleFunction( state.module.getPackage(FqName("kotlin")).memberScope.getContributedVariables( Name.identifier("isInitialized"), NoLookupLocation.FROM_BACKEND ).single { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt index 5e11e498c43..0f8c9d9e396 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt @@ -16,32 +16,78 @@ package org.jetbrains.kotlin.backend.jvm -import org.jetbrains.kotlin.backend.common.BackendContext -import org.jetbrains.kotlin.backend.common.CompilerPhase +import org.jetbrains.kotlin.backend.common.* +import org.jetbrains.kotlin.backend.common.lower.* +import org.jetbrains.kotlin.backend.common.phaser.* +import org.jetbrains.kotlin.backend.jvm.lower.* import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.util.PatchDeclarationParentsVisitor import org.jetbrains.kotlin.ir.visitors.acceptVoid -fun makePatchParentsPhase(number: Int) = object : CompilerPhase { - override val name: String = "PatchParents$number" - override val description: String = "Patch parent references in IrFile, pass $number" - override val prerequisite: Set> = emptySet() +private fun makePatchParentsPhase(number: Int) = namedIrFilePhase( + lower = object : SameTypeCompilerPhase { + override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: CommonBackendContext, input: IrFile): IrFile { + input.acceptVoid(PatchDeclarationParentsVisitor()) + return input + } + }, + name = "PatchParents$number", + description = "Patch parent references in IrFile, pass $number", + nlevels = 0 +) - override fun invoke(context: BackendContext, input: IrFile): IrFile { - input.acceptVoid(PatchDeclarationParentsVisitor()) - return input - } -} +internal val jvmPhases = namedIrFilePhase( + name = "IrLowering", + description = "IR lowering", + lower = jvmCoercionToUnitPhase then + fileClassPhase then + kCallableNamePropertyPhase then + + jvmLateinitPhase then + + moveCompanionObjectFieldsPhase then + constAndJvmFieldPropertiesPhase then + propertiesPhase then + annotationPhase then + + jvmDefaultArgumentStubPhase then + + interfacePhase then + interfaceDelegationPhase then + sharedVariablesPhase then + + makePatchParentsPhase(1) then + + jvmLocalDeclarationsPhase then + callableReferencePhase then + functionNVarargInvokePhase then + + innerClassesPhase then + innerClassConstructorCallsPhase then + + makePatchParentsPhase(2) then + + enumClassPhase then + objectClassPhase then + makeInitializersPhase(JvmLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER, true) then + singletonReferencesPhase then + syntheticAccessorPhase then + bridgePhase then + jvmOverloadsAnnotationPhase then + jvmStaticAnnotationPhase then + staticDefaultFunctionPhase then + + tailrecPhase then + toArrayPhase then + jvmTypeOperatorLoweringPhase then + jvmBuiltinOptimizationLoweringPhase then + + makePatchParentsPhase(3) +) class JvmLower(val context: JvmBackendContext) { fun lower(irFile: IrFile) { - var state = irFile // TODO run lowering passes as callbacks in bottom-up visitor - - context.rootPhaseManager(irFile).apply { - for (jvmPhase in jvmPhases) { - state = phase(jvmPhase, context, state) - } - } + jvmPhases.invokeToplevel(context.phaseConfig, context, irFile) } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLoweringPhases.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLoweringPhases.kt deleted file mode 100644 index 8f3cf6013cb..00000000000 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLoweringPhases.kt +++ /dev/null @@ -1,288 +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.jvm - -import org.jetbrains.kotlin.backend.common.BackendContext -import org.jetbrains.kotlin.backend.common.CompilerPhase -import org.jetbrains.kotlin.backend.common.lower.* -import org.jetbrains.kotlin.backend.common.makePhase -import org.jetbrains.kotlin.backend.common.runOnFilePostfix -import org.jetbrains.kotlin.backend.jvm.lower.* -import org.jetbrains.kotlin.descriptors.Visibilities -import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName -import org.jetbrains.kotlin.ir.declarations.IrFile -import org.jetbrains.kotlin.name.NameUtils - -object IrFileStartPhase : CompilerPhase { - override val name = "IrFileStart" - override val description = "State at start of IrFile lowering" - override val prerequisite = emptySet() - override fun invoke(context: BackendContext, input: IrFile) = input -} - -private fun makeJvmPhase( - lowering: (JvmBackendContext, IrFile) -> Unit, - description: String, - name: String, - prerequisite: Set> = emptySet() -) = makePhase(lowering, description, name, prerequisite) - -private val JvmCoercionToUnitPhase = makeJvmPhase( - { context, file -> JvmCoercionToUnitPatcher(context).lower(file) }, - name = "JvmCoercionToUnit", - description = "Insert conversions to unit after IrCalls where needed" -) - -private val FileClassPhase = makeJvmPhase( - { context, file -> FileClassLowering(context).lower(file) }, - name = "FileClass", - description = "Put file level function and property declaration into a class" -) - -private val KCallableNamePropertyPhase = makeJvmPhase( - { context, file -> KCallableNamePropertyLowering(context).lower(file) }, - name = "KCallableNameProperty", - description = "Replace name references for callables with constants" -) - -private val LateinitPhase = makeJvmPhase( - { context, file -> LateinitLowering(context).lower(file) }, - name = "Lateinit", - description = "Insert checks for lateinit field references" -) - -private val MoveCompanionObjectFieldsPhase = makeJvmPhase( - { context, file -> MoveCompanionObjectFieldsLowering(context).runOnFilePostfix(file) }, - name = "MoveCompanionObjectFields", - description = "Move companion object fields to static fields of companion's owner" -) - - -private val ConstAndJvmFieldPropertiesPhase = makeJvmPhase( - { context, file -> ConstAndJvmFieldPropertiesLowering(context).lower(file) }, - name = "ConstAndJvmFieldProperties", - description = "Substitute calls to const and Jvm>Field properties with const/field access" -) - - -private val PropertiesPhase = makeJvmPhase( - { context, file -> PropertiesLowering(context).lower(file) }, - name = "Properties", - description = "move fields and accessors for properties to their classes" -) - - -private val AnnotationPhase = makeJvmPhase( - { _, file -> AnnotationLowering().lower(file) }, - name = "Annotation", - description = "Remove constructors from annotation classes" -) - -private val DefaultArgumentStubPhase = makeJvmPhase( - { context, file -> DefaultArgumentStubGenerator(context, false).lower(file) }, - name = "DefaultArgumentsStubGenerator", - description = "Generate synthetic stubs for functions with default parameter values" -) - -private val InterfacePhase = makeJvmPhase( - { context, file -> InterfaceLowering(context).lower(file) }, - name = "Interface", - description = "Move default implementations of interface members to DefaultImpls class" -) - -private val InterfaceDelegationPhase = makeJvmPhase( - { context, file -> InterfaceDelegationLowering(context).lower(file) }, - name = "InterfaceDelegation", - description = "Delegate calls to interface members with default implementations to DefaultImpls" -) - -private val SharedVariablesPhase = makeJvmPhase( - { context, file -> SharedVariablesLowering(context).lower(file) }, - name = "SharedVariables", - description = "Transform shared variables" -) - -private val LocalDeclarationsPhase = makeJvmPhase( - { context, data -> - LocalDeclarationsLowering(context, object : LocalNameProvider { - override fun localName(declaration: IrDeclarationWithName): String = - NameUtils.sanitizeAsJavaIdentifier(super.localName(declaration)) - }, Visibilities.PUBLIC, true).lower(data) - }, - name = "JvmLocalDeclarations", - description = "Move local declarations to classes", - prerequisite = setOf(SharedVariablesPhase) -) - -private val CallableReferencePhase = makeJvmPhase( - { context, file -> CallableReferenceLowering(context).lower(file) }, - name = "CallableReference", - description = "Handle callable references" -) - -private val FunctionNVarargInvokePhase = makeJvmPhase( - { context, file -> FunctionNVarargInvokeLowering(context).lower(file) }, - name = "FunctionNVarargInvoke", - description = "Handle invoke functions with large number of arguments" -) - - -private val InnerClassesPhase = makeJvmPhase( - { context, file -> InnerClassesLowering(context).lower(file) }, - name = "InnerClasses", - description = "Move inner classes to toplevel" -) - -private val InnerClassConstructorCallsPhase = makeJvmPhase( - { context, file -> InnerClassConstructorCallsLowering(context).lower(file) }, - name = "InnerClassConstructorCalls", - description = "Handle constructor calls for inner classes" -) - - -private val EnumClassPhase = makeJvmPhase( - { context, file -> EnumClassLowering(context).lower(file) }, - name = "EnumClass", - description = "Handle enum classes" -) - - -private val ObjectClassPhase = makeJvmPhase( - { context, file -> ObjectClassLowering(context).lower(file) }, - name = "ObjectClass", - description = "Handle object classes" -) - -private val InitializersPhase = makeJvmPhase( - { context, file -> InitializersLowering(context, JvmLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER, true).lower(file) }, - name = "Initializers", - description = "Handle initializer statements" -) - - -private val SingletonReferencesPhase = makeJvmPhase( - { context, file -> SingletonReferencesLowering(context).lower(file) }, - name = "SingletonReferences", - description = "Handle singleton references" -) - - -private val SyntheticAccessorPhase = makeJvmPhase( - { context, file -> SyntheticAccessorLowering(context).lower(file) }, - name = "SyntheticAccessor", - description = "Introduce synthetic accessors", - prerequisite = setOf(ObjectClassPhase) -) - -private val BridgePhase = makeJvmPhase( - { context, file -> BridgeLowering(context).lower(file) }, - name = "Bridge", - description = "Generate bridges" -) - -private val JvmOverloadsAnnotationPhase = makeJvmPhase( - { context, file -> JvmOverloadsAnnotationLowering(context).lower(file) }, - name = "JvmOverloadsAnnotation", - description = "Handle JvmOverloads annotations" -) - - -private val JvmStaticAnnotationPhase = makeJvmPhase( - { context, file -> JvmStaticAnnotationLowering(context).lower(file) }, - name = "JvmStaticAnnotation", - description = "Handle JvmStatic annotations" -) - - -private val StaticDefaultFunctionPhase = makeJvmPhase( - { _, file -> StaticDefaultFunctionLowering().lower(file) }, - name = "StaticDefaultFunction", - description = "Generate static functions for default parameters" -) - - -private val TailrecPhase = makeJvmPhase( - { context, file -> TailrecLowering(context).lower(file) }, - name = "Tailrec", - description = "Handle tailrec calls" -) - -private val ToArrayPhase = makeJvmPhase( - { context, file -> ToArrayLowering(context).lower(file) }, - name = "ToArray", - description = "Handle toArray functions" -) - -private val JvmTypeOperatorLowering = makeJvmPhase( - { context, file -> JvmTypeOperatorLowering(context).lower(file) }, - name = "JvmTypeOperatorLoweringPhase", - description = "Handle JVM-specific type operator lowerings" -) - - -private val JvmBuiltinOptimizationLowering = makeJvmPhase( - { context, file -> JvmBuiltinOptimizationLowering(context).lower(file) }, - name = "JvmBuiltinOptimizationLowering", - description = "Optimize builtin calls for JVM code generation" -) - -object IrFileEndPhase : CompilerPhase { - override val name = "IrFileEnd" - override val description = "State at end of IrFile lowering" - override val prerequisite = emptySet() - override fun invoke(context: BackendContext, input: IrFile) = input -} - -val jvmPhases = listOf( - IrFileStartPhase, - - JvmCoercionToUnitPhase, - FileClassPhase, - KCallableNamePropertyPhase, - - LateinitPhase, - - MoveCompanionObjectFieldsPhase, - ConstAndJvmFieldPropertiesPhase, - PropertiesPhase, - AnnotationPhase, - - DefaultArgumentStubPhase, - - InterfacePhase, - InterfaceDelegationPhase, - SharedVariablesPhase, - - makePatchParentsPhase(1), - - LocalDeclarationsPhase, - CallableReferencePhase, - FunctionNVarargInvokePhase, - - InnerClassesPhase, - InnerClassConstructorCallsPhase, - - makePatchParentsPhase(2), - - EnumClassPhase, - ObjectClassPhase, - InitializersPhase, - SingletonReferencesPhase, - SyntheticAccessorPhase, - BridgePhase, - JvmOverloadsAnnotationPhase, - JvmStaticAnnotationPhase, - StaticDefaultFunctionPhase, - - TailrecPhase, - ToArrayPhase, - JvmTypeOperatorLowering, - JvmBuiltinOptimizationLowering, - - makePatchParentsPhase(3), - - IrFileEndPhase -) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmPhaseRunner.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmPhaseRunner.kt deleted file mode 100644 index d8b9bb87180..00000000000 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmPhaseRunner.kt +++ /dev/null @@ -1,19 +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.jvm - -import org.jetbrains.kotlin.backend.common.DefaultIrPhaseRunner -import org.jetbrains.kotlin.ir.declarations.IrFile -import org.jetbrains.kotlin.ir.declarations.name - -object JvmPhaseRunner : DefaultIrPhaseRunner() { - override val startPhaseMarker = IrFileStartPhase - override val endPhaseMarker = IrFileEndPhase - - override fun phases(context: JvmBackendContext) = context.phases - override fun elementName(input: IrFile) = input.name - override fun configuration(context: JvmBackendContext) = context.state.configuration -} \ No newline at end of file diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/AnnotationLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/AnnotationLowering.kt index a6526ad3bd4..5b7e69dbe99 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/AnnotationLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/AnnotationLowering.kt @@ -7,12 +7,18 @@ package org.jetbrains.kotlin.backend.jvm.lower import org.jetbrains.kotlin.backend.common.BackendContext 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.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.util.isAnnotationClass -class AnnotationLowering() : ClassLoweringPass { +internal val annotationPhase = makeIrFilePhase( + ::AnnotationLowering, + name = "Annotation", + description = "Remove constructors from annotation classes" +) + +private class AnnotationLowering() : ClassLoweringPass { constructor(@Suppress("UNUSED_PARAMETER") context: BackendContext) : this() override fun lower(irClass: IrClass) { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/BridgeLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/BridgeLowering.kt index e2c03391c9c..cbfc39184e3 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/BridgeLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/BridgeLowering.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.common.bridges.findInterfaceImplementation import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.irBlockBody import org.jetbrains.kotlin.backend.common.lower.irNot +import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.descriptors.JvmFunctionDescriptorImpl @@ -55,7 +56,13 @@ import org.jetbrains.org.objectweb.asm.Opcodes.* import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.commons.Method -class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass { +internal val bridgePhase = makeIrFilePhase( + ::BridgeLowering, + name = "Bridge", + description = "Generate bridges" +) + +private class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass { private val state = context.state diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/CallableReferenceLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/CallableReferenceLowering.kt index c4556077bc0..5f98bbe6d44 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/CallableReferenceLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/CallableReferenceLowering.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.backend.common.descriptors.* import org.jetbrains.kotlin.backend.common.ir.copyTo import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor import org.jetbrains.kotlin.backend.common.lower.* +import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.codegen.isInlineIrExpression @@ -51,8 +52,14 @@ class CrIrType(val type: Type) : IrType { override val annotations = emptyList() } +internal val callableReferencePhase = makeIrFilePhase( + ::CallableReferenceLowering, + name = "CallableReference", + description = "Handle callable references" +) + //Originally was copied from K/Native -class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPass { +internal class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPass { private var functionReferenceCount = 0 diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/ConstAndJvmFieldPropertiesLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/ConstAndJvmFieldPropertiesLowering.kt index 572ed910db9..c084de22554 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/ConstAndJvmFieldPropertiesLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/ConstAndJvmFieldPropertiesLowering.kt @@ -9,7 +9,7 @@ import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.irBlock -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.* import org.jetbrains.kotlin.ir.expressions.* @@ -20,7 +20,13 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.load.java.JvmAbi.JVM_FIELD_ANNOTATION_FQ_NAME -class ConstAndJvmFieldPropertiesLowering(val context: CommonBackendContext) : IrElementTransformerVoid(), FileLoweringPass { +internal val constAndJvmFieldPropertiesPhase = makeIrFilePhase( + ::ConstAndJvmFieldPropertiesLowering, + name = "ConstAndJvmFieldProperties", + description = "Substitute calls to const and Jvm>Field properties with const/field access" +) + +private class ConstAndJvmFieldPropertiesLowering(val context: CommonBackendContext) : IrElementTransformerVoid(), FileLoweringPass { override fun lower(irFile: IrFile) { irFile.transformChildrenVoid(this) } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/EnumClassLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/EnumClassLowering.kt index e89031fcecc..18bc5bc8853 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/EnumClassLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/EnumClassLowering.kt @@ -7,7 +7,7 @@ package org.jetbrains.kotlin.backend.jvm.lower import gnu.trove.TObjectIntHashMap 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.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.descriptors.JvmPropertyDescriptorImpl import org.jetbrains.kotlin.backend.jvm.descriptors.createValueParameter @@ -33,7 +33,13 @@ import org.jetbrains.kotlin.types.* import org.jetbrains.org.objectweb.asm.Opcodes import java.util.* -class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass { +internal val enumClassPhase = makeIrFilePhase( + ::EnumClassLowering, + name = "EnumClass", + description = "Handle enum classes" +) + +private class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass { override fun lower(irClass: IrClass) { if (!irClass.isEnumClass) return diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FileClassLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FileClassLowering.kt index 3edd776c043..2455a4e4051 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FileClassLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FileClassLowering.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.backend.jvm.lower import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassDescriptor import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor +import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality @@ -34,7 +35,13 @@ import org.jetbrains.kotlin.psi2ir.PsiSourceManager import org.jetbrains.kotlin.resolve.source.KotlinSourceElement import java.util.* -class FileClassLowering(val context: JvmBackendContext) : FileLoweringPass { +internal val fileClassPhase = makeIrFilePhase( + ::FileClassLowering, + name = "FileClass", + description = "Put file level function and property declaration into a class" +) + +private class FileClassLowering(val context: JvmBackendContext) : FileLoweringPass { override fun lower(irFile: IrFile) { val classes = ArrayList() val fileClassMembers = ArrayList() diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionNVarargInvokeLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionNVarargInvokeLowering.kt index 21bf21b4384..f5870b0d709 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionNVarargInvokeLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionNVarargInvokeLowering.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDesc import org.jetbrains.kotlin.backend.common.descriptors.WrappedValueParameterDescriptor import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.irIfThen +import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.descriptors.Modality @@ -30,7 +31,13 @@ import org.jetbrains.kotlin.ir.util.findDeclaration import org.jetbrains.kotlin.ir.util.isSubclassOf import org.jetbrains.kotlin.name.Name -class FunctionNVarargInvokeLowering(var context: JvmBackendContext) : ClassLoweringPass { +internal val functionNVarargInvokePhase = makeIrFilePhase( + ::FunctionNVarargInvokeLowering, + name = "FunctionNVarargInvoke", + description = "Handle invoke functions with large number of arguments" +) + +private class FunctionNVarargInvokeLowering(var context: JvmBackendContext) : ClassLoweringPass { override fun lower(irClass: IrClass) { val invokeFunctions = irClass.filterDeclarations { it.name.toString() == "invoke" } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceDelegationLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceDelegationLowering.kt index 10b80c4c9f6..1dd200425d4 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceDelegationLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceDelegationLowering.kt @@ -9,6 +9,8 @@ import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor import org.jetbrains.kotlin.backend.common.ir.copyParameterDeclarationsFrom import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.common.CodegenUtil +import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface @@ -34,7 +36,13 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.Name -class InterfaceDelegationLowering(val context: JvmBackendContext) : IrElementTransformerVoid(), ClassLoweringPass { +internal val interfaceDelegationPhase = makeIrFilePhase( + ::InterfaceDelegationLowering, + name = "InterfaceDelegation", + description = "Delegate calls to interface members with default implementations to DefaultImpls" +) + +private class InterfaceDelegationLowering(val context: JvmBackendContext) : IrElementTransformerVoid(), ClassLoweringPass { val state: GenerationState = context.state diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceLowering.kt index a425959afb1..fbc7fb8d2d3 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceLowering.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.backend.common.ir.copyTo import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom import org.jetbrains.kotlin.backend.common.lower.InitializersLowering.Companion.clinitName import org.jetbrains.kotlin.backend.common.lower.VariableRemapper +import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations @@ -23,7 +24,13 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.Name -class InterfaceLowering(val context: JvmBackendContext) : IrElementTransformerVoid(), ClassLoweringPass { +internal val interfacePhase = makeIrFilePhase( + ::InterfaceLowering, + name = "Interface", + description = "Move default implementations of interface members to DefaultImpls class" +) + +private class InterfaceLowering(val context: JvmBackendContext) : IrElementTransformerVoid(), ClassLoweringPass { val state = context.state diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmBuiltinOptimizationLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmBuiltinOptimizationLowering.kt index e9387130c88..bfa3e77e948 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmBuiltinOptimizationLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmBuiltinOptimizationLowering.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.backend.jvm.lower import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.codegen.intrinsics.Not import org.jetbrains.kotlin.ir.IrStatement @@ -24,6 +25,12 @@ import org.jetbrains.kotlin.ir.util.isTrueConst import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +internal val jvmBuiltinOptimizationLoweringPhase = makeIrFilePhase( + ::JvmBuiltinOptimizationLowering, + name = "JvmBuiltinOptimizationLowering", + description = "Optimize builtin calls for JVM code generation" +) + class JvmBuiltinOptimizationLowering(val context: JvmBackendContext) : FileLoweringPass { companion object { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmCoercionToUnitPatcher.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmCoercionToUnitPatcher.kt index 23d354130ba..2221e8594b3 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmCoercionToUnitPatcher.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmCoercionToUnitPatcher.kt @@ -6,8 +6,8 @@ package org.jetbrains.kotlin.backend.jvm.lower import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.common.utils.isSubtypeOf -import org.jetbrains.kotlin.backend.common.makePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.expressions.IrCall @@ -18,6 +18,12 @@ import org.jetbrains.kotlin.ir.util.coerceToUnitIfNeeded import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.psi2ir.transformations.InsertImplicitCasts +internal val jvmCoercionToUnitPhase = makeIrFilePhase( + ::JvmCoercionToUnitPatcher, + name = "JvmCoercionToUnit", + description = "Insert conversions to unit after IrCalls where needed" +) + class JvmCoercionToUnitPatcher(val context: JvmBackendContext) : InsertImplicitCasts( context.builtIns, context.irBuiltIns, diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmOverloadsAnnotationLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmOverloadsAnnotationLowering.kt index 28682170366..508c9b6cfc3 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmOverloadsAnnotationLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmOverloadsAnnotationLowering.kt @@ -6,7 +6,7 @@ package org.jetbrains.kotlin.backend.jvm.lower 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.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor @@ -35,7 +35,13 @@ import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue import org.jetbrains.kotlin.resolve.jvm.annotations.findJvmOverloadsAnnotation -class JvmOverloadsAnnotationLowering(val context: JvmBackendContext) : ClassLoweringPass { +internal val jvmOverloadsAnnotationPhase = makeIrFilePhase( + ::JvmOverloadsAnnotationLowering, + name = "JvmOverloadsAnnotation", + description = "Handle JvmOverloads annotations" +) + +private class JvmOverloadsAnnotationLowering(val context: JvmBackendContext) : ClassLoweringPass { override fun lower(irClass: IrClass) { val functions = irClass.declarations.filterIsInstance().filter { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmStaticAnnotationLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmStaticAnnotationLowering.kt index f45b56fe11a..398e94b2d38 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmStaticAnnotationLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmStaticAnnotationLowering.kt @@ -10,7 +10,7 @@ import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.irBlock import org.jetbrains.kotlin.backend.common.lower.replaceThisByStaticReference -import org.jetbrains.kotlin.backend.common.makePhase +import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.common.runOnFilePostfix import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin @@ -36,12 +36,18 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.annotations.JVM_STATIC_ANNOTATION_FQ_NAME import org.jetbrains.org.objectweb.asm.Opcodes +internal val jvmStaticAnnotationPhase = makeIrFilePhase( + ::JvmStaticAnnotationLowering, + name = "JvmStaticAnnotation", + description = "Handle JvmStatic annotations" +) + /* * For @JvmStatic functions within companion objects of classes, we synthesize proxy static functions that redirect * to the actual implementation. * For @JvmStatic functions within static objects, we make the actual function static and modify all call sites. */ -class JvmStaticAnnotationLowering(val context: JvmBackendContext) : IrElementTransformerVoid(), FileLoweringPass { +private class JvmStaticAnnotationLowering(val context: JvmBackendContext) : IrElementTransformerVoid(), FileLoweringPass { override fun lower(irFile: IrFile) { CompanionObjectJvmStaticLowering(context).runOnFilePostfix(irFile) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmTypeOperatorLoweringPhase.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmTypeOperatorLoweringPhase.kt index e8815115ffe..f247a9510d9 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmTypeOperatorLoweringPhase.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmTypeOperatorLoweringPhase.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.backend.jvm.lower import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.expressions.* @@ -15,7 +16,13 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrElseBranchImpl import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid -class JvmTypeOperatorLowering(val context: JvmBackendContext) : FileLoweringPass { +internal val jvmTypeOperatorLoweringPhase = makeIrFilePhase( + ::JvmTypeOperatorLowering, + name = "JvmTypeOperatorLoweringPhase", + description = "Handle JVM-specific type operator lowerings" +) + +private class JvmTypeOperatorLowering(val context: JvmBackendContext) : FileLoweringPass { override fun lower(irFile: IrFile) { irFile.transformChildrenVoid(object : IrElementTransformerVoid() { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MoveCompanionObjectFieldsLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MoveCompanionObjectFieldsLowering.kt index 1300e33602a..2dd538055b0 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MoveCompanionObjectFieldsLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MoveCompanionObjectFieldsLowering.kt @@ -10,7 +10,7 @@ import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.descriptors.WrappedFieldDescriptor import org.jetbrains.kotlin.backend.common.descriptors.WrappedVariableDescriptor import org.jetbrains.kotlin.backend.common.lower.replaceThisByStaticReference -import org.jetbrains.kotlin.backend.common.makePhase +import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement @@ -33,7 +33,13 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.load.java.JvmAbi.JVM_FIELD_ANNOTATION_FQ_NAME import org.jetbrains.kotlin.name.Name -class MoveCompanionObjectFieldsLowering(val context: CommonBackendContext) : ClassLoweringPass { +internal val moveCompanionObjectFieldsPhase = makeIrFilePhase( + ::MoveCompanionObjectFieldsLowering, + name = "MoveCompanionObjectFields", + description = "Move companion object fields to static fields of companion's owner" +) + +private class MoveCompanionObjectFieldsLowering(val context: CommonBackendContext) : ClassLoweringPass { override fun lower(irClass: IrClass) { val fieldReplacementMap = mutableMapOf() if (irClass.isObject && !irClass.isCompanion && irClass.visibility != Visibilities.LOCAL) { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/ObjectClassLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/ObjectClassLowering.kt index 69bff5c9b01..3e9a702fb23 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/ObjectClassLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/ObjectClassLowering.kt @@ -7,7 +7,7 @@ package org.jetbrains.kotlin.backend.jvm.lower import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext -import org.jetbrains.kotlin.backend.common.makePhase +import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.codegen.JvmCodegenUtil.isCompanionObjectInInterfaceNotIntrinsic import org.jetbrains.kotlin.descriptors.* @@ -25,7 +25,13 @@ import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.isObject -class ObjectClassLowering(val context: JvmBackendContext) : IrElementTransformerVoidWithContext(), FileLoweringPass { +internal val objectClassPhase = makeIrFilePhase( + ::ObjectClassLowering, + name = "ObjectClass", + description = "Handle object classes" +) + +private class ObjectClassLowering(val context: JvmBackendContext) : IrElementTransformerVoidWithContext(), FileLoweringPass { private var pendingTransformations = mutableListOf>() diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SingletonReferencesLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SingletonReferencesLowering.kt index e727b83ff21..17b6bc3d462 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SingletonReferencesLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SingletonReferencesLowering.kt @@ -6,7 +6,7 @@ package org.jetbrains.kotlin.backend.jvm.lower import org.jetbrains.kotlin.backend.common.BodyLoweringPass -import org.jetbrains.kotlin.backend.common.makePhase +import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.ir.expressions.IrBody import org.jetbrains.kotlin.ir.expressions.IrExpression @@ -16,7 +16,13 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid -class SingletonReferencesLowering(val context: JvmBackendContext) : BodyLoweringPass, IrElementTransformerVoid() { +internal val singletonReferencesPhase = makeIrFilePhase( + ::SingletonReferencesLowering, + name = "SingletonReferences", + description = "Handle singleton references" +) + +private class SingletonReferencesLowering(val context: JvmBackendContext) : BodyLoweringPass, IrElementTransformerVoid() { override fun lower(irBody: IrBody) { irBody.transformChildrenVoid(this) } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/StaticDefaultFunctionLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/StaticDefaultFunctionLowering.kt index 060c09f0a51..6bc10989641 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/StaticDefaultFunctionLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/StaticDefaultFunctionLowering.kt @@ -18,13 +18,20 @@ package org.jetbrains.kotlin.backend.jvm.lower import org.jetbrains.kotlin.backend.common.BackendContext import org.jetbrains.kotlin.backend.common.ClassLoweringPass +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.IrDeclarationOrigin import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid -class StaticDefaultFunctionLowering() : IrElementTransformerVoid(), ClassLoweringPass { +internal val staticDefaultFunctionPhase = makeIrFilePhase( + ::StaticDefaultFunctionLowering, + name = "StaticDefaultFunction", + description = "Generate static functions for default parameters" +) + +private class StaticDefaultFunctionLowering() : IrElementTransformerVoid(), ClassLoweringPass { constructor(@Suppress("UNUSED_PARAMETER") context: BackendContext) : this() override fun lower(irClass: IrClass) { @@ -38,4 +45,4 @@ class StaticDefaultFunctionLowering() : IrElementTransformerVoid(), ClassLowerin super.visitFunction(declaration) } } -} +} \ No newline at end of file diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt index 20ff576603f..66edceab86a 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassConstructorDe import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor import org.jetbrains.kotlin.backend.common.descriptors.WrappedValueParameterDescriptor import org.jetbrains.kotlin.backend.common.ir.* +import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.intrinsics.receiverAndArgs @@ -37,7 +38,14 @@ import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.DescriptorUtils -class SyntheticAccessorLowering(val context: JvmBackendContext) : IrElementTransformerVoidWithContext(), FileLoweringPass { +internal val syntheticAccessorPhase = makeIrFilePhase( + ::SyntheticAccessorLowering, + name = "SyntheticAccessor", + description = "Introduce synthetic accessors", + prerequisite = setOf(objectClassPhase) +) + +private class SyntheticAccessorLowering(val context: JvmBackendContext) : IrElementTransformerVoidWithContext(), FileLoweringPass { private val pendingTransformations = mutableListOf>() private val inlinedLambdasCollector = InlinedLambdasCollector() diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/ToArrayLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/ToArrayLowering.kt index fc5c392af0d..0a6a9c462a0 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/ToArrayLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/ToArrayLowering.kt @@ -9,7 +9,7 @@ import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.descriptors.KnownClassDescriptor import org.jetbrains.kotlin.backend.common.descriptors.KnownPackageFragmentDescriptor import org.jetbrains.kotlin.backend.common.lower.createIrBuilder -import org.jetbrains.kotlin.backend.common.makePhase +import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface @@ -43,7 +43,13 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperclassesWithoutAny import org.jetbrains.kotlin.types.Variance -class ToArrayLowering(private val context: JvmBackendContext) : ClassLoweringPass { +internal val toArrayPhase = makeIrFilePhase( + ::ToArrayLowering, + name = "ToArray", + description = "Handle toArray functions" +) + +private class ToArrayLowering(private val context: JvmBackendContext) : ClassLoweringPass { override fun lower(irClass: IrClass) { if (irClass.isJvmInterface) return