diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt index eb947e5658d..aa62aa630ae 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt @@ -196,6 +196,48 @@ abstract class CommonCompilerArguments : CommonToolArguments() { ) var allowResultReturnType: Boolean by FreezableVar(false) + @Argument( + value = "-Xlist-phases", + description = "List backend phases" + ) + var listPhases: Boolean by FreezableVar(false) + + @Argument( + value = "-Xdisable-phases", + description = "Disable backend phases" + ) + var disablePhases: Array by FreezableVar(emptyArray()) + + @Argument( + value = "-Xverbose-phases", + description = "Be verbose while performing these backend phases" + ) + var verbosePhases: Array by FreezableVar(emptyArray()) + + @Argument( + value = "-Xphases-to-dump-before", + description = "Dump backend state before these phases" + ) + var phasesToDumpBefore: Array by FreezableVar(emptyArray()) + + @Argument( + value = "-Xphases-to-dump-after", + description = "Dump backend state after these phases" + ) + var phasesToDumpAfter: Array by FreezableVar(emptyArray()) + + @Argument( + value = "-Xphases-to-dump", + description = "Dump backend state both before and after these phases" + ) + var phasesToDump: Array by FreezableVar(emptyArray()) + + @Argument( + value = "-Xprofile-phases", + description = "Profile backend phases" + ) + var profilePhases: Boolean by FreezableVar(false) + open fun configureAnalysisFlags(collector: MessageCollector): MutableMap, Any> { return HashMap, Any>().apply { put(AnalysisFlags.skipMetadataVersionCheck, skipMetadataVersionCheck) diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.java b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.java index 2b5cc261649..cdb5925c469 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.java +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.java @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.cli.common; import com.intellij.openapi.Disposable; import com.intellij.openapi.util.Disposer; +import kotlin.collections.SetsKt; import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -160,6 +161,14 @@ public abstract class CLICompiler extends CLI } setupLanguageVersionSettings(configuration, arguments); + + configuration.put(CommonConfigurationKeys.LIST_PHASES, arguments.getListPhases()); + configuration.put(CommonConfigurationKeys.DISABLED_PHASES, SetsKt.setOf(arguments.getDisablePhases())); + configuration.put(CommonConfigurationKeys.VERBOSE_PHASES, SetsKt.setOf(arguments.getVerbosePhases())); + configuration.put(CommonConfigurationKeys.PHASES_TO_DUMP_STATE_BEFORE, SetsKt.setOf(arguments.getPhasesToDumpBefore())); + configuration.put(CommonConfigurationKeys.PHASES_TO_DUMP_STATE_AFTER, SetsKt.setOf(arguments.getPhasesToDumpAfter())); + configuration.put(CommonConfigurationKeys.PHASES_TO_DUMP_STATE, SetsKt.setOf(arguments.getPhasesToDump())); + configuration.put(CommonConfigurationKeys.PROFILE_PHASES, arguments.getProfilePhases()); } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/kotlin/config/CommonConfigurationKeys.kt b/compiler/frontend/src/org/jetbrains/kotlin/config/CommonConfigurationKeys.kt index d9f39f7a971..e439c0faa10 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/config/CommonConfigurationKeys.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/config/CommonConfigurationKeys.kt @@ -41,6 +41,27 @@ object CommonConfigurationKeys { @JvmField val METADATA_VERSION = CompilerConfigurationKey.create("metadata version") + + @JvmField + val LIST_PHASES = CompilerConfigurationKey.create("list names of backend phases") + + @JvmField + val DISABLED_PHASES = CompilerConfigurationKey.create>("disable backend phases") + + @JvmField + val PHASES_TO_DUMP_STATE_BEFORE = CompilerConfigurationKey.create>("backend phases where we dump compiler state before the phase") + + @JvmField + val PHASES_TO_DUMP_STATE_AFTER = CompilerConfigurationKey.create>("backend phases where we dump compiler state after the phase") + + @JvmField + val PHASES_TO_DUMP_STATE = CompilerConfigurationKey.create>("backend phases where we dump compiler state both before and after the phase") + + @JvmField + val VERBOSE_PHASES = CompilerConfigurationKey.create>("verbose backend phases") + + @JvmField + val PROFILE_PHASES = CompilerConfigurationKey.create("profile backend phase execution") } var CompilerConfiguration.languageVersionSettings: LanguageVersionSettings 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 new file mode 100644 index 00000000000..d52fafe4d8d --- /dev/null +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/CompilerPhase.kt @@ -0,0 +1,149 @@ +/* + * 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.declarations.IrFile + +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 + + init { + with(CommonConfigurationKeys) { + val beforeSet = phaseSetFromConfiguration(config, PHASES_TO_DUMP_STATE_BEFORE) + val afterSet = phaseSetFromConfiguration(config, PHASES_TO_DUMP_STATE_AFTER) + val bothSet = phaseSetFromConfiguration(config, PHASES_TO_DUMP_STATE) + toDumpStateBefore = beforeSet + bothSet + toDumpStateAfter = afterSet + bothSet + } + } + + 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 reportBefore(phase: CompilerPhase, depth: Int, context: Context, data: Data) + fun runBody(phase: CompilerPhase, context: Context, source: Data): Data + fun reportAfter(phase: CompilerPhase, depth: Int, context: Context, data: Data) +} + +/* We assume that `element` is being modified by each phase, retaining its identity in the process. */ +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.reportBefore(phase, depth, context, source) + val result = phaseRunner.runBody(phase, context, source) + phaseRunner.reportAfter(phase, depth, context, result) + return result + } +} + +fun makePhase( + loweringConstructor: (Context) -> FileLoweringPass, + 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: IrFile): IrFile { + loweringConstructor(context).lower(input) + return input + } +} + +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 +} + +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 +} \ 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 223791c5a27..bbef458830d 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 @@ -30,20 +30,28 @@ interface FileLoweringPass { fun lower(irFile: IrFile) } -interface ClassLoweringPass { +interface ClassLoweringPass : FileLoweringPass { fun lower(irClass: IrClass) + + override fun lower(irFile: IrFile) = runOnFilePostfix(irFile) } -interface DeclarationContainerLoweringPass { +interface DeclarationContainerLoweringPass : FileLoweringPass { fun lower(irDeclarationContainer: IrDeclarationContainer) + + override fun lower(irFile: IrFile) = runOnFilePostfix(irFile) } -interface FunctionLoweringPass { +interface FunctionLoweringPass : FileLoweringPass { fun lower(irFunction: IrFunction) + + override fun lower(irFile: IrFile) = runOnFilePostfix(irFile) } -interface BodyLoweringPass { +interface BodyLoweringPass : FileLoweringPass { fun lower(irBody: IrBody) + + override fun lower(irFile: IrFile) = runOnFilePostfix(irFile) } fun ClassLoweringPass.runOnFilePostfix(irFile: IrFile) { @@ -67,7 +75,7 @@ fun DeclarationContainerLoweringPass.asClassLoweringPass() = object : ClassLower fun DeclarationContainerLoweringPass.runOnFilePostfix(irFile: IrFile) { this.asClassLoweringPass().runOnFilePostfix(irFile) - this.lower(irFile) + this.lower(irFile as IrDeclarationContainer) } fun BodyLoweringPass.runOnFilePostfix(irFile: IrFile) { 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 b78cb6e26a1..8286affcc0b 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 @@ -5,10 +5,7 @@ package org.jetbrains.kotlin.backend.common.lower -import org.jetbrains.kotlin.backend.common.BodyLoweringPass -import org.jetbrains.kotlin.backend.common.CommonBackendContext -import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass -import org.jetbrains.kotlin.backend.common.FunctionLoweringPass +import org.jetbrains.kotlin.backend.common.* import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassConstructorDescriptor import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor import org.jetbrains.kotlin.backend.common.descriptors.WrappedValueParameterDescriptor @@ -39,6 +36,16 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.Name +fun makeDefaultArgumentStubPhase(skipInlineMethods: Boolean) = object : CompilerPhase { + override val name = "DefaultArgumentsStubGenerator" + override val description = "Generate synthetic stubs for functions with default parameter values" + + override fun invoke(context: CommonBackendContext, input: IrFile): IrFile { + DefaultArgumentStubGenerator(context, skipInlineMethods).lower(input) + return input + } +} + // TODO: fix expect/actual default parameters open class DefaultArgumentStubGenerator constructor(val context: CommonBackendContext, private val skipInlineMethods: Boolean = true) : 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 92ee7eb0157..86ba536a643 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 @@ -7,6 +7,7 @@ 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.CompilerPhase import org.jetbrains.kotlin.backend.common.ir.SetDeclarationsParentVisitor import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.Modality @@ -29,6 +30,17 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns +fun makeInitializersPhase(declarationOrigin: IrDeclarationOrigin, clinitNeeded: Boolean) = object : + CompilerPhase { + override val name = "Initializers" + override val description = "Handle initializer statements" + + override fun invoke(context: CommonBackendContext, input: IrFile): IrFile { + InitializersLowering(context, declarationOrigin, clinitNeeded).lower(input) + return input + } +} + object SYNTHESIZED_INIT_BLOCK: IrStatementOriginImpl("SYNTHESIZED_INIT_BLOCK") class InitializersLowering( 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 d302dfacdb6..e65489047fb 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,6 +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.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrConstructor @@ -26,6 +27,12 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import java.util.* +val InnerClassesPhase = makePhase( + ::InnerClassesLowering, + name = "InnerClasses", + description = "Move inner classes to toplevel" +) + class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass { override fun lower(irClass: IrClass) { InnerClassTransformer(irClass).lowerInnerClass() @@ -167,6 +174,12 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass { } } +val InnerClassConstructorCallsPhase = makePhase( + ::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 287f7205b41..79a8e393641 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,6 +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.builtins.functions.FunctionClassDescriptor import org.jetbrains.kotlin.builtins.getFunctionalClassKind import org.jetbrains.kotlin.descriptors.ClassDescriptor @@ -37,6 +38,12 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.types.KotlinType +val KCallableNamePropertyPhase = makePhase( + ::KCallableNamePropertyLowering, + name = "KCallableNameProperty", + description = "Replace name references for callables with constants" +) + 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 bdc555de91c..bdb985d237d 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,6 +17,7 @@ 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.ir.IrStatement import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET @@ -33,6 +34,16 @@ import org.jetbrains.kotlin.ir.util.resolveFakeOverride import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +fun makeLateinitPhase(generateParameterNameInAssertion: Boolean) = 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, generateParameterNameInAssertion).lower(input) + return input + } +} + class LateinitLowering( val context: CommonBackendContext, private val generateParameterNameInAssertion: Boolean = false @@ -130,4 +141,4 @@ class LateinitLowering( } private val throwErrorFunction = context.ir.symbols.ThrowUninitializedPropertyAccessException.owner -} \ No newline at end of file +} 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 1918c79675a..eac07b74067 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,6 +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.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl @@ -35,9 +36,24 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.name.NameUtils import org.jetbrains.kotlin.resolve.descriptorUtil.parents import java.util.* +val LocalDeclarationsPhase = makePhase( + ::LocalDeclarationsLowering, + name = "LocalDeclarations", + description = "Move local declarations to classes", + prerequisite = setOf(SharedVariablesPhase) +) + +val JvmLocalDeclarationsPhase = makePhase( + ::JvmLocalDeclarationsLowering, + name = "JvmLocalDeclarations", + description = "Move local declarations to classes", + prerequisite = setOf(SharedVariablesPhase) +) + interface LocalNameProvider { fun localName(descriptor: DeclarationDescriptor): String = descriptor.name.asString() @@ -55,7 +71,18 @@ val IrDeclaration.parents: Sequence object BOUND_VALUE_PARAMETER: IrDeclarationOriginImpl("BOUND_VALUE_PARAMETER") -class LocalDeclarationsLowering( +class JvmLocalDeclarationsLowering(context: BackendContext) : + LocalDeclarationsLowering( + context, + object : LocalNameProvider { + override fun localName(descriptor: DeclarationDescriptor): String = + NameUtils.sanitizeAsJavaIdentifier(super.localName(descriptor)) + }, + Visibilities.PUBLIC, //TODO properly figure out visibility + true + ) + +open class LocalDeclarationsLowering( val context: BackendContext, val localNameProvider: LocalNameProvider = LocalNameProvider.DEFAULT, val loweredConstructorVisibility: Visibility = Visibilities.PRIVATE, @@ -773,4 +800,4 @@ class LocalDeclarationsLowering( } } -} \ No newline at end of file +} 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 5faa3ea1b15..3c0998e47a8 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 @@ -5,7 +5,9 @@ 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.descriptors.ClassKind import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.* @@ -16,7 +18,15 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.utils.addIfNotNull import java.util.* -class PropertiesLowering : IrElementTransformerVoid(), FileLoweringPass { +val PropertiesPhase = makePhase( + ::PropertiesLowering, + name = "Properties", + description = "move fields and accessors for properties to their classes" +) + +class PropertiesLowering() : IrElementTransformerVoid(), FileLoweringPass { + constructor(@Suppress("UNUSED_PARAMETER") context: BackendContext) : this() + override fun lower(irFile: IrFile) { irFile.accept(this, null) } 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 32eb1dbfe19..e922855c1e4 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 @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.backend.common.lower import org.jetbrains.kotlin.backend.common.BackendContext import org.jetbrains.kotlin.backend.common.FunctionLoweringPass +import org.jetbrains.kotlin.backend.common.makePhase import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.IrDeclaration @@ -33,6 +34,12 @@ import org.jetbrains.kotlin.ir.util.dump import org.jetbrains.kotlin.ir.visitors.* import java.util.* +val SharedVariablesPhase = makePhase( + ::SharedVariablesLowering, + name = "SharedVariables", + description = "Transform shared variables" +) + class SharedVariablesLowering(val context: BackendContext) : FunctionLoweringPass { override fun lower(irFunction: IrFunction) { SharedVariablesTransformer(irFunction).lowerSharedVariables() 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 17f4fc619d8..4efb77bc7c4 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 @@ -27,6 +27,12 @@ import org.jetbrains.kotlin.ir.util.getArgumentsWithIr import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +val TailrecPhase = makePhase( + ::TailrecLowering, + name = "Tailrec", + description = "Handle tailrec calls" +) + /** * This pass lowers tail recursion calls in `tailrec` functions. * 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 228ff9cfc13..fc41fd280c9 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,12 +6,15 @@ 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.jvm.descriptors.JvmDeclarationFactory import org.jetbrains.kotlin.backend.jvm.descriptors.JvmSharedVariablesManager import org.jetbrains.kotlin.builtins.ReflectionTypes import org.jetbrains.kotlin.codegen.state.GenerationState +import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.NotFoundClasses @@ -44,6 +47,19 @@ class JvmBackendContext( override val ir = JvmIr(irModuleFragment, symbolTable) + val phases = CompilerPhases(jvmPhases, state.configuration) + + init { + if (state.configuration.get(CommonConfigurationKeys.LIST_PHASES) == true) { + phases.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)) } @@ -73,7 +89,9 @@ class JvmBackendContext( 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.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt index 25fbd9e61c8..3e97dd3f418 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,71 +16,85 @@ 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.IrFileEndPhase +import org.jetbrains.kotlin.backend.common.IrFileStartPhase import org.jetbrains.kotlin.backend.common.lower.* -import org.jetbrains.kotlin.backend.common.runOnFilePostfix import org.jetbrains.kotlin.backend.jvm.lower.* -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.util.PatchDeclarationParentsVisitor -import org.jetbrains.kotlin.ir.util.TypeTranslator import org.jetbrains.kotlin.ir.visitors.acceptVoid -import org.jetbrains.kotlin.name.NameUtils + +val jvmPhases = listOf( + IrFileStartPhase, + + JvmCoercionToUnitPhase, + FileClassPhase, + KCallableNamePropertyPhase, + + makeLateinitPhase(true), + + MoveCompanionObjectFieldsPhase, + ConstAndJvmFieldPropertiesPhase, + PropertiesPhase, + AnnotationPhase, + + makeDefaultArgumentStubPhase(false), + + InterfacePhase, + InterfaceDelegationPhase, + SharedVariablesPhase, + + makePatchParentsPhase(1), + + JvmLocalDeclarationsPhase, + CallableReferencePhase, + FunctionNVarargInvokePhase, + + InnerClassesPhase, + InnerClassConstructorCallsPhase, + + makePatchParentsPhase(2), + + EnumClassPhase, + ObjectClassPhase, + makeInitializersPhase(JvmLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER, true), + SingletonReferencesPhase, + SyntheticAccessorPhase, + BridgePhase, + JvmOverloadsAnnotationPhase, + JvmStaticAnnotationPhase, + StaticDefaultFunctionPhase, + + TailrecPhase, + ToArrayPhase, + + makePatchParentsPhase(3), + + IrFileEndPhase +) + +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() + + override fun invoke(context: BackendContext, input: IrFile): IrFile { + input.acceptVoid(PatchDeclarationParentsVisitor()) + return input + } +} class JvmLower(val context: JvmBackendContext) { fun lower(irFile: IrFile) { + var state = irFile // TODO run lowering passes as callbacks in bottom-up visitor - JvmCoercionToUnitPatcher(context).lower(irFile) - FileClassLowering(context).lower(irFile) - KCallableNamePropertyLowering(context).lower(irFile) - - LateinitLowering(context, true).lower(irFile) - - MoveCompanionObjectFieldsLowering(context).runOnFilePostfix(irFile) - ConstAndJvmFieldPropertiesLowering(context).lower(irFile) - PropertiesLowering().lower(irFile) - AnnotationLowering().runOnFilePostfix(irFile) //should be run before defaults lowering - - //Should be before interface lowering - DefaultArgumentStubGenerator(context, false).runOnFilePostfix(irFile) - - InterfaceLowering(context).runOnFilePostfix(irFile) - InterfaceDelegationLowering(context).runOnFilePostfix(irFile) - SharedVariablesLowering(context).runOnFilePostfix(irFile) - - irFile.acceptVoid(PatchDeclarationParentsVisitor()) - - LocalDeclarationsLowering( - context, - object : LocalNameProvider { - override fun localName(descriptor: DeclarationDescriptor): String = - NameUtils.sanitizeAsJavaIdentifier(super.localName(descriptor)) - }, - Visibilities.PUBLIC, //TODO properly figure out visibility - true - ).runOnFilePostfix(irFile) - CallableReferenceLowering(context).lower(irFile) - FunctionNVarargInvokeLowering(context).runOnFilePostfix(irFile) - - InnerClassesLowering(context).runOnFilePostfix(irFile) - InnerClassConstructorCallsLowering(context).runOnFilePostfix(irFile) - - irFile.acceptVoid(PatchDeclarationParentsVisitor()) - - EnumClassLowering(context).runOnFilePostfix(irFile) - //Should be before SyntheticAccessorLowering cause of synthetic accessor for companion constructor - ObjectClassLowering(context).lower(irFile) - InitializersLowering(context, JvmLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER, true).runOnFilePostfix(irFile) - SingletonReferencesLowering(context).runOnFilePostfix(irFile) - SyntheticAccessorLowering(context).lower(irFile) - BridgeLowering(context).runOnFilePostfix(irFile) - JvmOverloadsAnnotationLowering(context).runOnFilePostfix(irFile) - JvmStaticAnnotationLowering(context).lower(irFile) - StaticDefaultFunctionLowering(context.state).runOnFilePostfix(irFile) - - TailrecLowering(context).runOnFilePostfix(irFile) - ToArrayLowering(context).runOnFilePostfix(irFile) - - irFile.acceptVoid(PatchDeclarationParentsVisitor()) + + context.rootPhaseManager(irFile).apply { + for (jvmPhase in jvmPhases) { + state = phase(jvmPhase, context, state) + } + } } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLoweringPhase.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLoweringPhase.kt new file mode 100644 index 00000000000..ce93cd6df12 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLoweringPhase.kt @@ -0,0 +1,77 @@ +/* + * 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.* +import org.jetbrains.kotlin.config.CommonConfigurationKeys +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.name +import org.jetbrains.kotlin.ir.util.dump +import kotlin.system.measureTimeMillis + +enum class BeforeOrAfter { BEFORE, AFTER } + +object JvmPhaseRunner : PhaseRunner { + override fun reportBefore(phase: CompilerPhase, depth: Int, context: JvmBackendContext, data: IrFile) { + if (phase in context.phases.toDumpStateBefore) { + dumpFile(data, phase, BeforeOrAfter.BEFORE) + } + } + + override fun runBody(phase: CompilerPhase, context: JvmBackendContext, source: IrFile): IrFile { + val runner = when { + phase === IrFileStartPhase -> ::justRun + phase === IrFileEndPhase -> ::justRun + (context.state.configuration.get(CommonConfigurationKeys.PROFILE_PHASES) == true) -> ::runAndProfile + else -> ::justRun + } + + context.inVerbosePhase = (phase in context.phases.verbose) + + val result = runner(phase, context, source) + + context.inVerbosePhase = false + + return result + } + + override fun reportAfter(phase: CompilerPhase, depth: Int, context: JvmBackendContext, data: IrFile) { + if (phase in context.phases.toDumpStateAfter) { + dumpFile(data, phase, BeforeOrAfter.AFTER) + } + } +} + +private fun runAndProfile(phase: CompilerPhase, context: JvmBackendContext, source: IrFile): IrFile { + var result: IrFile = source + val msec = measureTimeMillis { result = phase.invoke(context, source) } + println("${phase.description}: $msec msec") + return result +} + +private fun justRun(phase: CompilerPhase, context: JvmBackendContext, source: IrFile) = + phase.invoke(context, source) + +private fun separator(title: String) { + println("\n\n--- $title ----------------------\n") +} + +private fun dumpFile(irFile: IrFile, phase: CompilerPhase, beforeOrAfter: BeforeOrAfter) { + // Exclude nonsensical combinations + if (phase === IrFileStartPhase && beforeOrAfter == BeforeOrAfter.AFTER) return + if (phase === IrFileEndPhase && beforeOrAfter == BeforeOrAfter.BEFORE) return + + val title = when (phase) { + IrFileStartPhase -> "IR for ${irFile.name} at the start of lowering process" + IrFileEndPhase -> "IR for ${irFile.name} at the end of lowering process" + else -> { + val beforeOrAfterStr = beforeOrAfter.name.toLowerCase() + "IR for ${irFile.name} $beforeOrAfterStr ${phase.description}" + } + } + separator(title) + println(irFile.dump()) +} \ 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 fef15a35b22..e6921e3e4dc 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 @@ -5,12 +5,21 @@ 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.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.util.isAnnotationClass -class AnnotationLowering : ClassLoweringPass { +val AnnotationPhase = makePhase( + ::AnnotationLowering, + name = "Annotation", + description = "Remove constructors from annotation classes" +) + +class AnnotationLowering() : ClassLoweringPass { + constructor(@Suppress("UNUSED_PARAMETER") context: BackendContext) : this() override fun lower(irClass: IrClass) { if (!irClass.isAnnotationClass) return 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 41fd0580635..12431e9b988 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 @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.backend.common.bridges.generateBridgesForFunctionDes 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.makePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.descriptors.DefaultImplsClassDescriptor import org.jetbrains.kotlin.backend.jvm.descriptors.JvmFunctionDescriptorImpl @@ -59,6 +60,12 @@ import org.jetbrains.org.objectweb.asm.Opcodes.* import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.commons.Method +val BridgePhase = makePhase( + ::BridgeLowering, + name = "Bridge", + description = "Generate bridges" +) + 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 2260457c0fb..7db3b88d138 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 @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext import org.jetbrains.kotlin.backend.common.descriptors.* import org.jetbrains.kotlin.backend.common.ir.createFakeOverrideDescriptor import org.jetbrains.kotlin.backend.common.lower.* +import org.jetbrains.kotlin.backend.common.makePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.codegen.isInlineCall import org.jetbrains.kotlin.backend.jvm.codegen.isInlineIrExpression @@ -59,6 +60,12 @@ import org.jetbrains.kotlin.types.Variance import org.jetbrains.org.objectweb.asm.Opcodes import org.jetbrains.org.objectweb.asm.Type +val CallableReferencePhase = makePhase( + ::CallableReferenceLowering, + name = "CallableReference", + description = "Handle callable references" +) + //Hack implementation to support CR java types in lower class CrIrType(val type: Type) : IrType { override val annotations = emptyList() 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 9aaf2deb965..db987aa9629 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,6 +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.codegen.JvmCodegenUtil import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.* @@ -21,6 +22,12 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.load.java.JvmAbi.JVM_FIELD_ANNOTATION_FQ_NAME import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor +val ConstAndJvmFieldPropertiesPhase = makePhase( + ::ConstAndJvmFieldPropertiesLowering, + name = "ConstAndJvmFieldProperties", + description = "Substitute calls to const and Jvm>Field properties with const/field access" +) + 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 eb56d734917..fab5f9b49bb 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,6 +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.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.descriptors.JvmPropertyDescriptorImpl import org.jetbrains.kotlin.backend.jvm.descriptors.createValueParameter @@ -32,6 +33,12 @@ import org.jetbrains.kotlin.types.* import org.jetbrains.org.objectweb.asm.Opcodes import java.util.* +val EnumClassPhase = makePhase( + ::EnumClassLowering, + name = "EnumClass", + description = "Handle enum classes" +) + 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 f34adbc8851..44a35beae86 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 @@ -18,6 +18,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.makePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality @@ -33,6 +34,12 @@ import org.jetbrains.kotlin.psi2ir.PsiSourceManager import org.jetbrains.kotlin.resolve.source.KotlinSourceElement import java.util.* +val FileClassPhase = makePhase( + ::FileClassLowering, + name = "FileClass", + description = "Put file level function and property declaration into a class" +) + class FileClassLowering(val context: JvmBackendContext) : FileLoweringPass { override fun lower(irFile: IrFile) { val classes = 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 d0208771687..157b7e8cdb3 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.makePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities @@ -29,6 +30,12 @@ import org.jetbrains.kotlin.ir.util.findDeclaration import org.jetbrains.kotlin.ir.util.isSubclassOf import org.jetbrains.kotlin.name.Name +val FunctionNVarargInvokePhase = makePhase( + ::FunctionNVarargInvokeLowering, + name = "FunctionNVarargInvoke", + description = "Handle invoke functions with large number of arguments" +) + class FunctionNVarargInvokeLowering(var context: JvmBackendContext) : ClassLoweringPass { override fun lower(irClass: IrClass) { 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 083a3f25533..45008b68ed8 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 @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.jvm.lower import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.CodegenUtil +import org.jetbrains.kotlin.backend.common.makePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredStatementOrigin import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface @@ -28,6 +29,11 @@ import org.jetbrains.kotlin.ir.util.createParameterDeclarations import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +val InterfaceDelegationPhase = makePhase( + ::InterfaceDelegationLowering, + name = "InterfaceDelegation", + description = "Delegate calls to interface members with default implementations to DefaultImpls" +) class InterfaceDelegationLowering(val context: JvmBackendContext) : IrElementTransformerVoid(), ClassLoweringPass { 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 fde9c5e0774..e7405fc29e2 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 @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.lower.DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER import org.jetbrains.kotlin.backend.common.lower.InitializersLowering.Companion.clinitName import org.jetbrains.kotlin.backend.common.lower.VariableRemapperDesc +import org.jetbrains.kotlin.backend.common.makePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.codegen.AsmUtil import org.jetbrains.kotlin.descriptors.* @@ -27,6 +28,12 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.org.objectweb.asm.Opcodes +val InterfacePhase = makePhase( + ::InterfaceLowering, + name = "Interface", + description = "Move default implementations of interface members to DefaultImpls class" +) + 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/JvmCoercionToUnitPatcher.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmCoercionToUnitPatcher.kt index 0ee45f04826..82df444f1c3 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 @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.jvm.lower import org.jetbrains.kotlin.backend.common.FileLoweringPass 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 @@ -16,6 +17,12 @@ import org.jetbrains.kotlin.ir.util.TypeTranslator import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.psi2ir.transformations.InsertImplicitCasts +val JvmCoercionToUnitPhase = makePhase( + ::JvmCoercionToUnitPatcher, + name = "JvmCoercionToUnit", + description = "Insert conversions to unit after IrCalls where needed" +) + class JvmCoercionToUnitPatcher(val context: JvmBackendContext) : InsertImplicitCasts( context.builtIns, context.irBuiltIns, @@ -34,4 +41,4 @@ class JvmCoercionToUnitPatcher(val context: JvmBackendContext) : return this } -} \ No newline at end of file +} 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 b6c0a77caae..738bc83329e 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,6 +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.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor @@ -34,6 +35,11 @@ import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue import org.jetbrains.kotlin.resolve.jvm.annotations.findJvmOverloadsAnnotation +val JvmOverloadsAnnotationPhase = makePhase( + ::JvmOverloadsAnnotationLowering, + name = "JvmOverloadsAnnotation", + description = "Handle JvmOverloads annotations" +) class JvmOverloadsAnnotationLowering(val context: JvmBackendContext) : ClassLoweringPass { 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 a9ca4e3f92b..84ebcf3d396 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,6 +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.runOnFilePostfix import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin @@ -29,13 +30,18 @@ import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl import org.jetbrains.kotlin.ir.types.classifierOrFail import org.jetbrains.kotlin.ir.util.* -import org.jetbrains.kotlin.ir.visitors.IrElementTransformer import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.annotations.JVM_STATIC_ANNOTATION_FQ_NAME import org.jetbrains.org.objectweb.asm.Opcodes +val JvmStaticAnnotationPhase = makePhase( + ::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. 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 50cd38b3e0a..45997c4d54e 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,6 +10,7 @@ import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.descriptors.WrappedPropertyDescriptor 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.descriptors.Visibilities import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement @@ -32,6 +33,12 @@ 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 +val MoveCompanionObjectFieldsPhase = makePhase( + ::MoveCompanionObjectFieldsLowering, + name = "MoveCompanionObjectFields", + description = "Move companion object fields to static fields of companion's owner" +) + class MoveCompanionObjectFieldsLowering(val context: CommonBackendContext) : ClassLoweringPass { override fun lower(irClass: IrClass) { val fieldReplacementMap = mutableMapOf() 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 a3d5d46a31e..a5eece17f13 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,6 +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.jvm.JvmBackendContext import org.jetbrains.kotlin.codegen.JvmCodegenUtil.isCompanionObjectInInterfaceNotIntrinsic import org.jetbrains.kotlin.descriptors.* @@ -24,6 +25,12 @@ import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.isObject +val ObjectClassPhase = makePhase( + ::ObjectClassLowering, + name = "ObjectClass", + description = "Handle object classes" +) + 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 10ed9136f83..800881e2643 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,6 +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.jvm.JvmBackendContext import org.jetbrains.kotlin.ir.expressions.IrBody import org.jetbrains.kotlin.ir.expressions.IrExpression @@ -15,6 +16,12 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +val SingletonReferencesPhase = makePhase( + ::SingletonReferencesLowering, + name = "SingletonReferences", + description = "Handle singleton references" +) + 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 756af251607..f468765169a 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 @@ -16,9 +16,10 @@ 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.lower.DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER -import org.jetbrains.kotlin.codegen.state.GenerationState +import org.jetbrains.kotlin.backend.common.makePhase import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.ir.IrStatement @@ -26,7 +27,15 @@ import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid -class StaticDefaultFunctionLowering(val state: GenerationState) : IrElementTransformerVoid(), ClassLoweringPass { +val StaticDefaultFunctionPhase = makePhase( + ::StaticDefaultFunctionLowering, + name = "StaticDefaultFunction", + description = "Generate static functions for default parameters" +) + +class StaticDefaultFunctionLowering() : IrElementTransformerVoid(), ClassLoweringPass { + constructor(@Suppress("UNUSED_PARAMETER") context: BackendContext) : this() + override fun lower(irClass: IrClass) { irClass.accept(this, null) 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 c0240c235f4..c6992d48460 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 @@ -5,10 +5,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.IrElementVisitorVoidWithContext -import org.jetbrains.kotlin.backend.common.ScopeWithIr +import org.jetbrains.kotlin.backend.common.* import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassConstructorDescriptor import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor import org.jetbrains.kotlin.backend.common.descriptors.WrappedValueParameterDescriptor @@ -39,6 +36,13 @@ import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.DescriptorUtils +val SyntheticAccessorPhase = makePhase( + ::SyntheticAccessorLowering, + name = "SyntheticAccessor", + description = "Introduce synthetic accessors", + prerequisite = setOf(ObjectClassPhase) +) + 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 cc87c543baa..f05d8e1313d 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,6 +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.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface @@ -42,6 +43,12 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperclassesWithoutAny import org.jetbrains.kotlin.types.Variance +val ToArrayPhase = makePhase( + ::ToArrayLowering, + name = "ToArray", + description = "Handle toArray functions" +) + class ToArrayLowering(private val context: JvmBackendContext) : ClassLoweringPass { override fun lower(irClass: IrClass) {