Reorganize phaser

This commit is contained in:
Georgy Bronnikov
2018-12-10 12:01:53 +03:00
parent 89c5549b0a
commit ab1e334847
45 changed files with 937 additions and 823 deletions
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.backend.common
import org.jetbrains.kotlin.backend.common.ir.Ir
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.ir.IrElement
@@ -13,6 +14,7 @@ import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.name.FqName
interface LoggingContext {
var inVerbosePhase: Boolean
fun log(message: () -> String)
}
@@ -28,4 +30,6 @@ interface CommonBackendContext : BackendContext, LoggingContext {
fun getInternalFunctions(name: String): List<FunctionDescriptor>
fun report(element: IrElement?, irFile: IrFile?, message: String, isError: Boolean)
val configuration: CompilerConfiguration
}
@@ -1,229 +0,0 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.CompilerConfigurationKey
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.util.dump
import kotlin.system.measureTimeMillis
interface CompilerPhase<in Context : BackendContext, Data> {
val name: String
val description: String
val prerequisite: Set<CompilerPhase<*, *>>
get() = emptySet()
fun invoke(context: Context, input: Data): Data
}
private typealias AnyPhase = CompilerPhase<*, *>
class CompilerPhases(private val phaseList: List<AnyPhase>, config: CompilerConfiguration) {
val phases = phaseList.associate { it.name to it }
val enabled = computeEnabled(config)
val verbose = phaseSetFromConfiguration(config, CommonConfigurationKeys.VERBOSE_PHASES)
val toDumpStateBefore: Set<AnyPhase>
val toDumpStateAfter: Set<AnyPhase>
val toValidateStateBefore: Set<AnyPhase>
val toValidateStateAfter: Set<AnyPhase>
init {
with(CommonConfigurationKeys) {
val beforeDumpSet = phaseSetFromConfiguration(config, PHASES_TO_DUMP_STATE_BEFORE)
val afterDumpSet = phaseSetFromConfiguration(config, PHASES_TO_DUMP_STATE_AFTER)
val bothDumpSet = phaseSetFromConfiguration(config, PHASES_TO_DUMP_STATE)
toDumpStateBefore = beforeDumpSet + bothDumpSet
toDumpStateAfter = afterDumpSet + bothDumpSet
val beforeValidateSet = phaseSetFromConfiguration(config, PHASES_TO_VALIDATE_BEFORE)
val afterValidateSet = phaseSetFromConfiguration(config, PHASES_TO_VALIDATE_AFTER)
val bothValidateSet = phaseSetFromConfiguration(config, PHASES_TO_VALIDATE)
toValidateStateBefore = beforeValidateSet + bothValidateSet
toValidateStateAfter = afterValidateSet + bothValidateSet
}
}
fun known(name: String): String {
if (phases[name] == null) {
error("Unknown phase: $name. Use -Xlist-phases to see the list of phases.")
}
return name
}
fun list() {
phaseList.forEach { phase ->
val enabled = if (phase in enabled) "(Enabled)" else ""
val verbose = if (phase in verbose) "(Verbose)" else ""
println(String.format("%1$-30s %2$-50s %3$-10s", "${phase.name}:", phase.description, "$enabled $verbose"))
}
}
private fun computeEnabled(config: CompilerConfiguration) =
with(CommonConfigurationKeys) {
val disabledPhases = phaseSetFromConfiguration(config, DISABLED_PHASES)
phases.values.toSet() - disabledPhases
}
private fun phaseSetFromConfiguration(config: CompilerConfiguration, key: CompilerConfigurationKey<Set<String>>): Set<AnyPhase> {
val phaseNames = config.get(key) ?: emptySet()
if ("ALL" in phaseNames) return phases.values.toSet()
return phaseNames.map { phases[it]!! }.toSet()
}
}
interface PhaseRunner<Context : BackendContext, Data> {
fun runBefore(phase: CompilerPhase<Context, Data>, depth: Int, context: Context, data: Data)
fun runBody(phase: CompilerPhase<Context, Data>, context: Context, source: Data): Data
fun runAfter(phase: CompilerPhase<Context, Data>, depth: Int, context: Context, data: Data)
}
abstract class DefaultIrPhaseRunner<Context : CommonBackendContext, Data : IrElement>(private val validator: (data: Data, context: Context) -> Unit = { _, _ -> }) :
PhaseRunner<Context, Data> {
enum class BeforeOrAfter { BEFORE, AFTER }
abstract val startPhaseMarker: CompilerPhase<Context, Data>
abstract val endPhaseMarker: CompilerPhase<Context, Data>
private var inVerbosePhase = false
final override fun runBefore(phase: CompilerPhase<Context, Data>, depth: Int, context: Context, data: Data) {
checkAndRun(phase, phases(context).toDumpStateBefore) { dumpElement(data, phase, context, BeforeOrAfter.BEFORE) }
checkAndRun(phase, phases(context).toValidateStateBefore) { validator(data, context) }
}
final override fun runBody(phase: CompilerPhase<Context, Data>, context: Context, source: Data): Data {
val runner = when {
phase === startPhaseMarker -> ::justRun
phase === endPhaseMarker -> ::justRun
needProfiling(context) -> ::runAndProfile
else -> ::justRun
}
inVerbosePhase = phase in phases(context).verbose
val result = runner(phase, context, source)
inVerbosePhase = false
return result
}
final override fun runAfter(phase: CompilerPhase<Context, Data>, depth: Int, context: Context, data: Data) {
checkAndRun(phase, phases(context).toDumpStateAfter) { dumpElement(data, phase, context, BeforeOrAfter.AFTER) }
checkAndRun(phase, phases(context).toValidateStateAfter) { validator(data, context) }
}
open fun separator(title: String) = println("\n\n--- $title ----------------------\n")
protected abstract fun phases(context: Context): CompilerPhases
protected abstract fun elementName(input: Data): String
protected abstract fun configuration(context: Context): CompilerConfiguration
private fun needProfiling(context: Context) = configuration(context).getBoolean(CommonConfigurationKeys.PROFILE_PHASES)
private fun shouldBeDumped(context: Context, input: Data) =
elementName(input) !in configuration(context).get(CommonConfigurationKeys.EXCLUDED_ELEMENTS_FROM_DUMPING, emptySet())
private fun checkAndRun(phase: CompilerPhase<Context, Data>, set: Set<AnyPhase>, block: () -> Unit) {
if (phase in set) block()
}
private fun dumpElement(input: Data, phase: CompilerPhase<Context, Data>, context: Context, beforeOrAfter: BeforeOrAfter) {
// Exclude nonsensical combinations
if (phase === startPhaseMarker && beforeOrAfter == BeforeOrAfter.AFTER) return
if (phase === endPhaseMarker && beforeOrAfter == BeforeOrAfter.BEFORE) return
if (!shouldBeDumped(context, input)) return
val title = when (phase) {
startPhaseMarker -> "IR for ${elementName(input)} at the start of lowering process"
endPhaseMarker -> "IR for ${elementName(input)} at the end of lowering process"
else -> {
val beforeOrAfterStr = beforeOrAfter.name.toLowerCase()
"IR for ${elementName(input)} $beforeOrAfterStr ${phase.description}"
}
}
separator(title)
println(input.dump())
}
private fun runAndProfile(phase: CompilerPhase<Context, Data>, context: Context, source: Data): Data {
var result: Data = source
val msec = measureTimeMillis { result = phase.invoke(context, source) }
println("${phase.description}: $msec msec")
return result
}
private fun justRun(phase: CompilerPhase<Context, Data>, context: Context, source: Data) =
phase.invoke(context, source)
}
class CompilerPhaseManager<Context : BackendContext, Data>(
val context: Context,
val phases: CompilerPhases,
val data: Data,
private val phaseRunner: PhaseRunner<Context, Data>,
val parent: CompilerPhaseManager<Context, *>? = null
) {
val depth: Int = parent?.depth?.inc() ?: 0
private val previousPhases = mutableSetOf<CompilerPhase<Context, Data>>()
fun <NewData> createChild(
newData: NewData,
newPhaseRunner: PhaseRunner<Context, NewData>
) = CompilerPhaseManager(
context, phases, newData, newPhaseRunner, parent = this
)
fun createChild() = createChild(data, phaseRunner)
private fun checkPrerequisite(phase: CompilerPhase<*, *>): Boolean =
previousPhases.contains(phase) || parent?.checkPrerequisite(phase) == true
fun phase(phase: CompilerPhase<Context, Data>, context: Context, source: Data): Data {
if (phase !in phases.enabled) return source
phase.prerequisite.forEach {
if (!checkPrerequisite(it))
throw Error("$phase requires $it")
}
previousPhases.add(phase)
phaseRunner.runBefore(phase, depth, context, source)
val result = phaseRunner.runBody(phase, context, source)
phaseRunner.runAfter(phase, depth, context, result)
return result
}
}
fun <Context : BackendContext, Data> makePhase(
lowering: (Context, Data) -> Unit,
description: String,
name: String,
prerequisite: Set<CompilerPhase<*, *>> = emptySet()
) = object : CompilerPhase<Context, Data> {
override val name = name
override val description = description
override val prerequisite = prerequisite
override fun invoke(context: Context, input: Data): Data {
lowering(context, input)
return input
}
override fun toString() = "Compiler Phase @$name"
}
@@ -17,10 +17,7 @@
package org.jetbrains.kotlin.backend.common
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrBody
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
@@ -54,6 +51,8 @@ interface BodyLoweringPass : FileLoweringPass {
override fun lower(irFile: IrFile) = runOnFilePostfix(irFile)
}
fun FileLoweringPass.lower(moduleFragment: IrModuleFragment) = moduleFragment.files.forEach { lower(it) }
fun ClassLoweringPass.runOnFilePostfix(irFile: IrFile) {
irFile.acceptVoid(object : IrElementVisitorVoid {
override fun visitElement(element: IrElement) {
@@ -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(
@@ -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,
@@ -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() {
@@ -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))
}
@@ -17,8 +17,8 @@
package org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.CompilerPhase
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.*
@@ -34,15 +34,11 @@ import org.jetbrains.kotlin.ir.util.resolveFakeOverride
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
fun makeLateinitPhase() = object : CompilerPhase<CommonBackendContext, IrFile> {
override val name = "Lateinit"
override val description = "Insert checks for lateinit field references"
override fun invoke(context: CommonBackendContext, input: IrFile): IrFile {
LateinitLowering(context).lower(input)
return input
}
}
val jvmLateinitPhase = makeIrFilePhase(
::LateinitLowering,
name = "Lateinit",
description = "Insert checks for lateinit field references"
)
class LateinitLowering(val context: CommonBackendContext) : FileLoweringPass {
override fun lower(irFile: IrFile) {
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass
import org.jetbrains.kotlin.backend.common.descriptors.*
import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
import org.jetbrains.kotlin.backend.common.makePhase
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
@@ -33,8 +33,21 @@ import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.ir.util.transformDeclarationsFlat
import org.jetbrains.kotlin.ir.visitors.*
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.NameUtils
import java.util.*
val jvmLocalDeclarationsPhase = makeIrFilePhase(
{ context ->
LocalDeclarationsLowering(context, object : LocalNameProvider {
override fun localName(declaration: IrDeclarationWithName): String =
NameUtils.sanitizeAsJavaIdentifier(super.localName(declaration))
}, Visibilities.PUBLIC, true)
},
name = "JvmLocalDeclarations",
description = "Move local declarations to classes",
prerequisite = setOf(sharedVariablesPhase)
)
interface LocalNameProvider {
fun localName(declaration: IrDeclarationWithName): String =
declaration.name.asString()
@@ -7,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()
@@ -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 {
@@ -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.
*
@@ -0,0 +1,133 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.phaser
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import kotlin.system.measureTimeMillis
class PhaserState {
val alreadyDone = mutableSetOf<AnyNamedPhase>()
var depth = 0
}
fun <R> PhaserState.downlevel(nlevels: Int = 1, block: () -> R): R {
depth += nlevels
val result = block()
depth -= nlevels
return result
}
interface CompilerPhase<in Context : CommonBackendContext, in Input, out Output> {
fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: Input): Output
fun getNamedSubphases(startDepth: Int = 0): List<Pair<Int, NamedCompilerPhase<*, *, *>>> = emptyList()
}
fun <Context: CommonBackendContext, Input, Output> CompilerPhase<Context, Input, Output>.invokeToplevel(
phaseConfig: PhaseConfig,
context: Context,
input: Input
): Output = invoke(phaseConfig, PhaserState(), context, input)
interface SameTypeCompilerPhase<in Context: CommonBackendContext, Data> : CompilerPhase<Context, Data, Data>
interface NamedCompilerPhase<in Context : CommonBackendContext, in Input, out Output> : CompilerPhase<Context, Input, Output> {
val name: String
val description: String
val prerequisite: Set<AnyNamedPhase> get() = emptySet()
}
typealias AnyNamedPhase = NamedCompilerPhase<*, *, *>
enum class BeforeOrAfter { BEFORE, AFTER }
interface PhaseDumperVerifier<in Context : CommonBackendContext, Data> {
fun dump(phase: AnyNamedPhase, context: Context, data: Data, beforeOrAfter: BeforeOrAfter)
fun verify(context: Context, data: Data)
}
abstract class AbstractNamedPhaseWrapper<in Context : CommonBackendContext, Input, Output>(
override val name: String,
override val description: String,
override val prerequisite: Set<AnyNamedPhase>,
private val nlevels: Int = 0,
private val lower: CompilerPhase<Context, Input, Output>
) : NamedCompilerPhase<Context, Input, Output> {
abstract val inputDumperVerifier: PhaseDumperVerifier<Context, Input>
abstract val outputDumperVerifier: PhaseDumperVerifier<Context, Output>
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: Input): Output {
if (this is SameTypeCompilerPhase<*, *> &&
this !in phaseConfig.enabled
) {
return input as Output
}
assert(phaserState.alreadyDone.containsAll(prerequisite))
context.inVerbosePhase = this in phaseConfig.verbose
runBefore(phaseConfig, context, input)
val output = runBody(phaseConfig, phaserState, context, input)
runAfter(phaseConfig, context, output)
phaserState.alreadyDone.add(this)
return output
}
private fun runBefore(phaseConfig: PhaseConfig, context: Context, input: Input) {
checkAndRun(phaseConfig.toDumpStateBefore) { inputDumperVerifier.dump(this, context, input, BeforeOrAfter.BEFORE) }
checkAndRun(phaseConfig.toValidateStateBefore) { inputDumperVerifier.verify(context, input) }
}
private fun runBody(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: Input): Output {
return if (phaseConfig.needProfiling) {
runAndProfile(phaseConfig, phaserState, context, input)
} else {
phaserState.downlevel(nlevels) {
lower.invoke(phaseConfig, phaserState, context, input)
}
}
}
private fun runAfter(phaseConfig: PhaseConfig, context: Context, output: Output) {
checkAndRun(phaseConfig.toDumpStateAfter) { outputDumperVerifier.dump(this, context, output, BeforeOrAfter.AFTER) }
checkAndRun(phaseConfig.toValidateStateAfter) { outputDumperVerifier.verify(context, output) }
}
private fun runAndProfile(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, source: Input): Output {
var result: Output? = null
val msec = measureTimeMillis {
result = phaserState.downlevel(nlevels) {
lower.invoke(phaseConfig, phaserState, context, source)
}
}
// TODO: use a proper logger
println("${"\t".repeat(phaserState.depth)}$description: $msec msec")
return result!!
}
private fun checkAndRun(set: Set<AnyNamedPhase>, block: () -> Unit) {
if (this in set) block()
}
override fun getNamedSubphases(startDepth: Int): List<Pair<Int, NamedCompilerPhase<*, *, *>>> =
listOf(startDepth to this) + lower.getNamedSubphases(startDepth + nlevels)
override fun toString() = "Compiler Phase @$name"
}
class SameTypeNamedPhaseWrapper<in Context : CommonBackendContext, Data>(
name: String,
description: String,
prerequisite: Set<AnyNamedPhase>,
nlevels: Int = 0,
lower: CompilerPhase<Context, Data, Data>,
val dumperVerifier: PhaseDumperVerifier<Context, Data>
) : AbstractNamedPhaseWrapper<Context, Data, Data>(name, description, prerequisite, nlevels, lower), SameTypeCompilerPhase<Context, Data> {
override val inputDumperVerifier get() = dumperVerifier
override val outputDumperVerifier get() = dumperVerifier
}
@@ -0,0 +1,48 @@
package org.jetbrains.kotlin.backend.common.phaser
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.name
import org.jetbrains.kotlin.ir.util.dump
abstract class IrPhaseDumperVerifier<in Context : CommonBackendContext, Data : IrElement>(
val verifier: (Context, Data) -> Unit
) : PhaseDumperVerifier<Context, Data> {
abstract fun Data.getElementName(): String
// TODO: use a proper logger.
override fun dump(phase: AnyNamedPhase, context: Context, data: Data, beforeOrAfter: BeforeOrAfter) {
fun separator(title: String) = println("\n\n--- $title ----------------------\n")
if (!shouldBeDumped(context, data)) return
val beforeOrAfterStr = beforeOrAfter.name.toLowerCase()
val title = "IR for ${data.getElementName()} $beforeOrAfterStr ${phase.description}"
separator(title)
println(data.dump())
}
override fun verify(context: Context, data: Data) = verifier(context, data)
private fun shouldBeDumped(context: Context, input: Data) =
input.getElementName() !in context.configuration.get(CommonConfigurationKeys.EXCLUDED_ELEMENTS_FROM_DUMPING, emptySet())
}
class IrFileDumperVerifier<in Context : CommonBackendContext>(verifier: (Context, IrFile) -> Unit) :
IrPhaseDumperVerifier<Context, IrFile>(verifier) {
override fun IrFile.getElementName() = name
}
class IrModuleDumperVerifier<in Context : CommonBackendContext>(verifier: (Context, IrModuleFragment) -> Unit) :
IrPhaseDumperVerifier<Context, IrModuleFragment>(verifier) {
override fun IrModuleFragment.getElementName() = name.asString()
}
class EmptyDumperVerifier<in Context : CommonBackendContext, Data> : PhaseDumperVerifier<Context, Data> {
override fun dump(phase: AnyNamedPhase, context: Context, data: Data, beforeOrAfter: BeforeOrAfter) {}
override fun verify(context: Context, data: Data) {}
}
@@ -0,0 +1,162 @@
package org.jetbrains.kotlin.backend.common.phaser
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
// Phase composition.
infix fun <Context : CommonBackendContext, Input, Mid, Output> CompilerPhase<Context, Input, Mid>.then(
other: CompilerPhase<Context, Mid, Output>
) = object : CompilerPhase<Context, Input, Output> {
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: Input): Output =
this@then.invoke(phaseConfig, phaserState, context, input).let { mid ->
other.invoke(phaseConfig, phaserState, context, mid)
}
override fun getNamedSubphases(startDepth: Int) =
this@then.getNamedSubphases(startDepth) + other.getNamedSubphases(startDepth)
}
fun <Context : CommonBackendContext> namedIrModulePhase(
name: String,
description: String,
prerequisite: Set<AnyNamedPhase> = emptySet(),
verify: (Context, IrModuleFragment) -> Unit = { _, _ -> },
nlevels: Int = 1,
lower: CompilerPhase<Context, IrModuleFragment, IrModuleFragment>
) = SameTypeNamedPhaseWrapper(name, description, prerequisite, nlevels, lower, IrModuleDumperVerifier(verify))
fun <Context : CommonBackendContext> namedIrFilePhase(
name: String,
description: String,
prerequisite: Set<AnyNamedPhase> = emptySet(),
verify: (Context, IrFile) -> Unit = { _, _ -> },
nlevels: Int = 1,
lower: CompilerPhase<Context, IrFile, IrFile>
) = SameTypeNamedPhaseWrapper(name, description, prerequisite, nlevels, lower, IrFileDumperVerifier(verify))
fun <Context : CommonBackendContext> namedUnitPhase(
name: String,
description: String,
prerequisite: Set<AnyNamedPhase> = emptySet(),
nlevels: Int = 1,
lower: CompilerPhase<Context, Unit, Unit>
) = SameTypeNamedPhaseWrapper(name, description, prerequisite, nlevels, lower, EmptyDumperVerifier())
fun <Context : CommonBackendContext> namedOpUnitPhase(
name: String,
description: String,
prerequisite: Set<AnyNamedPhase>,
op: Context.() -> Unit
) = namedUnitPhase(
name, description, prerequisite,
nlevels = 0,
lower = object : SameTypeCompilerPhase<Context, Unit> {
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: Unit) {
context.op()
}
}
)
fun <Context : CommonBackendContext> performByIrFile(
name: String = "PerformByIrFile",
description: String = "Perform phases by IrFile",
prerequisite: Set<AnyNamedPhase> = emptySet(),
verify: (Context, IrModuleFragment) -> Unit = { _, _ -> },
lower: CompilerPhase<Context, IrFile, IrFile>
) = namedIrModulePhase(
name, description, prerequisite, verify,
nlevels = 1,
lower = object : SameTypeCompilerPhase<Context, IrModuleFragment> {
override fun invoke(
phaseConfig: PhaseConfig,
phaserState: PhaserState,
context: Context,
input: IrModuleFragment
): IrModuleFragment {
for (irFile in input.files) {
lower.invoke(phaseConfig, phaserState, context, irFile)
}
// TODO: no guarantee that module identity is preserved by `lower`
return input
}
override fun getNamedSubphases(startDepth: Int) = lower.getNamedSubphases(startDepth)
}
)
fun <Context : CommonBackendContext> makeIrFilePhase(
lowering: (Context) -> FileLoweringPass,
name: String,
description: String,
prerequisite: Set<AnyNamedPhase> = emptySet(),
verify: (Context, IrFile) -> Unit = { _, _ -> }
) = namedIrFilePhase(
name, description, prerequisite, verify,
nlevels = 0,
lower = object : SameTypeCompilerPhase<Context, IrFile> {
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: IrFile): IrFile {
lowering(context).lower(input)
return input
}
}
)
fun <Context : CommonBackendContext> makeIrModulePhase(
lowering: (Context) -> FileLoweringPass,
name: String,
description: String,
prerequisite: Set<AnyNamedPhase> = emptySet(),
verify: (Context, IrModuleFragment) -> Unit = { _, _ -> }
) = namedIrModulePhase(
name, description, prerequisite, verify,
nlevels = 0,
lower = object : SameTypeCompilerPhase<Context, IrModuleFragment> {
override fun invoke(
phaseConfig: PhaseConfig,
phaserState: PhaserState,
context: Context,
input: IrModuleFragment
): IrModuleFragment {
lowering(context).lower(input)
return input
}
}
)
fun <Context : CommonBackendContext, Input> unitPhase(
name: String,
description: String,
prerequisite: Set<AnyNamedPhase>,
op: Context.() -> Unit
) =
object : AbstractNamedPhaseWrapper<Context, Input, Unit>(
name, description, prerequisite,
nlevels = 0,
lower = object : CompilerPhase<Context, Input, Unit> {
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: Input) {
context.op()
}
}
) {
override val inputDumperVerifier = EmptyDumperVerifier<Context, Input>()
override val outputDumperVerifier = EmptyDumperVerifier<Context, Unit>()
}
fun <Context : CommonBackendContext, Input> unitSink() = object : CompilerPhase<Context, Input, Unit> {
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: Input) {}
}
// Intermediate phases to change the object of transformations
fun <Context : CommonBackendContext, OldData, NewData> takeFromContext(op: (Context) -> NewData) =
object : CompilerPhase<Context, OldData, NewData> {
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: OldData) = op(context)
}
fun <Context : CommonBackendContext, OldData, NewData> transform(op: (OldData) -> NewData) =
object : CompilerPhase<Context, OldData, NewData> {
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, input: OldData) = op(input)
}
@@ -0,0 +1,81 @@
package org.jetbrains.kotlin.backend.common.phaser
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.CompilerConfigurationKey
class PhaseConfig(private val compoundPhase: CompilerPhase<*, *, *>, config: CompilerConfiguration) {
val phases = compoundPhase.getNamedSubphases().map { (_, phase) -> phase }.associate { it.name to it }
private val enabledMut = computeEnabled(config).toMutableSet()
val enabled: Set<AnyNamedPhase> get() = enabledMut
val verbose = phaseSetFromConfiguration(config, CommonConfigurationKeys.VERBOSE_PHASES)
val toDumpStateBefore: Set<AnyNamedPhase>
val toDumpStateAfter: Set<AnyNamedPhase>
val toValidateStateBefore: Set<AnyNamedPhase>
val toValidateStateAfter: Set<AnyNamedPhase>
init {
with(CommonConfigurationKeys) {
val beforeDumpSet = phaseSetFromConfiguration(config, PHASES_TO_DUMP_STATE_BEFORE)
val afterDumpSet = phaseSetFromConfiguration(config, PHASES_TO_DUMP_STATE_AFTER)
val bothDumpSet = phaseSetFromConfiguration(config, PHASES_TO_DUMP_STATE)
toDumpStateBefore = beforeDumpSet + bothDumpSet
toDumpStateAfter = afterDumpSet + bothDumpSet
val beforeValidateSet = phaseSetFromConfiguration(config, PHASES_TO_VALIDATE_BEFORE)
val afterValidateSet = phaseSetFromConfiguration(config, PHASES_TO_VALIDATE_AFTER)
val bothValidateSet = phaseSetFromConfiguration(config, PHASES_TO_VALIDATE)
toValidateStateBefore = beforeValidateSet + bothValidateSet
toValidateStateAfter = afterValidateSet + bothValidateSet
}
}
val needProfiling = config.getBoolean(CommonConfigurationKeys.PROFILE_PHASES)
fun known(name: String): String {
if (phases[name] == null) {
error("Unknown phase: $name. Use -Xlist-phases to see the list of phases.")
}
return name
}
fun list() {
compoundPhase.getNamedSubphases().forEach { (depth, phase) ->
val enabled = if (phase in enabled) "(Enabled)" else ""
val verbose = if (phase in verbose) "(Verbose)" else ""
println(String.format("%1$-50s %2$-50s %3$-10s", "${"\t".repeat(depth)}${phase.name}:", phase.description, "$enabled $verbose"))
}
}
private fun computeEnabled(config: CompilerConfiguration) =
with(CommonConfigurationKeys) {
val disabledPhases = phaseSetFromConfiguration(config, DISABLED_PHASES)
phases.values.toSet() - disabledPhases
}
private fun phaseSetFromConfiguration(config: CompilerConfiguration, key: CompilerConfigurationKey<Set<String>>): Set<AnyNamedPhase> {
val phaseNames = config.get(key) ?: emptySet()
if ("ALL" in phaseNames) return phases.values.toSet()
return phaseNames.map { phases[it]!! }.toSet()
}
fun enable(phase: AnyNamedPhase) {
enabledMut.add(phase)
}
fun disable(phase: AnyNamedPhase) {
enabledMut.remove(phase)
}
fun switch(phase: AnyNamedPhase, onOff: Boolean) {
if (onOff) {
enable(phase)
} else {
disable(phase)
}
}
}
@@ -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<IrModuleFragment>
) : 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) {
@@ -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<IrFile>) = files.forEach { runOnFilePostfix(it) }
private fun ClassLoweringPass.runOnFilesPostfix(moduleFragment: IrModuleFragment) = moduleFragment.files.forEach { runOnFilePostfix(it) }
object IrModuleStartPhase : CompilerPhase<BackendContext, IrModuleFragment> {
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<AnyNamedPhase> = emptySet()
) = makeIrModulePhase<JsIrBackendContext>(lowering, name, description, prerequisite, verify = ::validationCallback)
private fun makeCustomJsModulePhase(
op: (JsIrBackendContext, IrModuleFragment) -> Unit,
description: String,
name: String,
prerequisite: Set<CompilerPhase<JsIrBackendContext, IrModuleFragment>> = emptySet()
) = makePhase(lowering, description, name, prerequisite)
prerequisite: Set<AnyNamedPhase> = emptySet()
) = namedIrModulePhase(
name,
description,
prerequisite,
verify = ::validationCallback,
nlevels = 0,
lower = object : SameTypeCompilerPhase<JsIrBackendContext, IrModuleFragment> {
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 = "<Supposed to be removed> 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<BackendContext, IrModuleFragment> {
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
)
@@ -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<JsIrBackendContext, IrModuleFragment>(::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
}
@@ -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)
}
@@ -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",
@@ -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 {
@@ -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<BackendContext, IrFile> {
override val name: String = "PatchParents$number"
override val description: String = "Patch parent references in IrFile, pass $number"
override val prerequisite: Set<CompilerPhase<BackendContext, *>> = emptySet()
private fun makePatchParentsPhase(number: Int) = namedIrFilePhase(
lower = object : SameTypeCompilerPhase<CommonBackendContext, IrFile> {
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)
}
}
@@ -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<BackendContext, IrFile> {
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<CompilerPhase<JvmBackendContext, IrFile>> = 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<BackendContext, IrFile> {
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
)
@@ -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<JvmBackendContext, IrFile>() {
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
}
@@ -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) {
@@ -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
@@ -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
@@ -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)
}
@@ -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
@@ -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<IrClass>()
val fileClassMembers = ArrayList<IrDeclaration>()
@@ -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<IrSimpleFunction> { it.name.toString() == "invoke" }
@@ -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
@@ -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
@@ -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 {
@@ -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,
@@ -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<IrFunction>().filter {
@@ -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)
@@ -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() {
@@ -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<IrFieldSymbol, IrFieldSymbol>()
if (irClass.isObject && !irClass.isCompanion && irClass.visibility != Visibilities.LOCAL) {
@@ -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<Function0<Unit>>()
@@ -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)
}
@@ -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)
}
}
}
}
@@ -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<Function0<Unit>>()
private val inlinedLambdasCollector = InlinedLambdasCollector()
@@ -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