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 package org.jetbrains.kotlin.backend.common
import org.jetbrains.kotlin.backend.common.ir.Ir 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.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
@@ -13,6 +14,7 @@ import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
interface LoggingContext { interface LoggingContext {
var inVerbosePhase: Boolean
fun log(message: () -> String) fun log(message: () -> String)
} }
@@ -28,4 +30,6 @@ interface CommonBackendContext : BackendContext, LoggingContext {
fun getInternalFunctions(name: String): List<FunctionDescriptor> fun getInternalFunctions(name: String): List<FunctionDescriptor>
fun report(element: IrElement?, irFile: IrFile?, message: String, isError: Boolean) 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 package org.jetbrains.kotlin.backend.common
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.*
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.expressions.IrBody import org.jetbrains.kotlin.ir.expressions.IrBody
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
@@ -54,6 +51,8 @@ interface BodyLoweringPass : FileLoweringPass {
override fun lower(irFile: IrFile) = runOnFilePostfix(irFile) override fun lower(irFile: IrFile) = runOnFilePostfix(irFile)
} }
fun FileLoweringPass.lower(moduleFragment: IrModuleFragment) = moduleFragment.files.forEach { lower(it) }
fun ClassLoweringPass.runOnFilePostfix(irFile: IrFile) { fun ClassLoweringPass.runOnFilePostfix(irFile: IrFile) {
irFile.acceptVoid(object : IrElementVisitorVoid { irFile.acceptVoid(object : IrElementVisitorVoid {
override fun visitElement(element: IrElement) { 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.copyTo
import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
import org.jetbrains.kotlin.backend.common.ir.ir2string 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.descriptors.Modality
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET 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.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name 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 // TODO: fix expect/actual default parameters
open class DefaultArgumentStubGenerator( 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.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.deepCopyWithWrappedDescriptors 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.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.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.* 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.IrBlockImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl 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.util.patchDeclarationParents
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid 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") 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( class InitializersLowering(
val context: CommonBackendContext, val context: CommonBackendContext,
val declarationOrigin: IrDeclarationOrigin, 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.BackendContext
import org.jetbrains.kotlin.backend.common.BodyLoweringPass import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.ClassLoweringPass 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.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrConstructor 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 org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import java.util.* import java.util.*
val innerClassesPhase = makeIrFilePhase(
::InnerClassesLowering,
name = "InnerClasses",
description = "Move inner classes to toplevel"
)
class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass { class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass {
override fun lower(irClass: IrClass) { override fun lower(irClass: IrClass) {
InnerClassTransformer(irClass).lowerInnerClass() 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 { class InnerClassConstructorCallsLowering(val context: BackendContext) : BodyLoweringPass {
override fun lower(irBody: IrBody) { override fun lower(irBody: IrBody) {
irBody.transformChildrenVoid(object : IrElementTransformerVoid() { 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.BackendContext
import org.jetbrains.kotlin.backend.common.FileLoweringPass 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.IrClass
import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrProperty 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.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid 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) { override fun lower(irFile: IrFile) {
irFile.transformChildrenVoid(KCallableNamePropertyTransformer(this)) irFile.transformChildrenVoid(KCallableNamePropertyTransformer(this))
} }
@@ -17,8 +17,8 @@
package org.jetbrains.kotlin.backend.common.lower package org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.CommonBackendContext 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.FileLoweringPass
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.* 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.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
fun makeLateinitPhase() = object : CompilerPhase<CommonBackendContext, IrFile> { val jvmLateinitPhase = makeIrFilePhase(
override val name = "Lateinit" ::LateinitLowering,
override val description = "Insert checks for lateinit field references" name = "Lateinit",
description = "Insert checks for lateinit field references"
override fun invoke(context: CommonBackendContext, input: IrFile): IrFile { )
LateinitLowering(context).lower(input)
return input
}
}
class LateinitLowering(val context: CommonBackendContext) : FileLoweringPass { class LateinitLowering(val context: CommonBackendContext) : FileLoweringPass {
override fun lower(irFile: IrFile) { 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.descriptors.*
import org.jetbrains.kotlin.backend.common.ir.copyTo import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom 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.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl 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.util.transformDeclarationsFlat
import org.jetbrains.kotlin.ir.visitors.* import org.jetbrains.kotlin.ir.visitors.*
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.NameUtils
import java.util.* 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 { interface LocalNameProvider {
fun localName(declaration: IrDeclarationWithName): String = fun localName(declaration: IrDeclarationWithName): String =
declaration.name.asString() 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.BackendContext
import org.jetbrains.kotlin.backend.common.FileLoweringPass 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.descriptors.ClassKind
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
@@ -18,6 +18,12 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
import java.util.* import java.util.*
val propertiesPhase = makeIrFilePhase(
::PropertiesLowering,
name = "Properties",
description = "Move fields and accessors for properties to their classes"
)
class PropertiesLowering() : IrElementTransformerVoid(), FileLoweringPass { class PropertiesLowering() : IrElementTransformerVoid(), FileLoweringPass {
constructor(@Suppress("UNUSED_PARAMETER") context: BackendContext) : this() constructor(@Suppress("UNUSED_PARAMETER") context: BackendContext) : this()
@@ -16,7 +16,9 @@
package org.jetbrains.kotlin.backend.common.lower 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.IrElement
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrDeclaration 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 org.jetbrains.kotlin.ir.visitors.*
import java.util.* import java.util.*
val sharedVariablesPhase = makeIrFilePhase(
::SharedVariablesLowering,
name = "SharedVariables",
description = "Transform shared variables"
)
object CoroutineIntrinsicLambdaOrigin : IrStatementOriginImpl("Coroutine intrinsic lambda") object CoroutineIntrinsicLambdaOrigin : IrStatementOriginImpl("Coroutine intrinsic lambda")
class SharedVariablesLowering(val context: BackendContext) : FunctionLoweringPass { class SharedVariablesLowering(val context: BackendContext) : FunctionLoweringPass {
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.backend.common.lower package org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.* 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.builders.*
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.* 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.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid 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. * 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 package org.jetbrains.kotlin.ir.backend.js
import org.jetbrains.kotlin.backend.common.CommonBackendContext 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.atMostOne
import org.jetbrains.kotlin.backend.common.descriptors.KnownPackageFragmentDescriptor import org.jetbrains.kotlin.backend.common.descriptors.KnownPackageFragmentDescriptor
import org.jetbrains.kotlin.backend.common.ir.Ir import org.jetbrains.kotlin.backend.common.ir.Ir
import org.jetbrains.kotlin.backend.common.ir.Symbols 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.backend.js.JsDeclarationFactory
import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
@@ -47,13 +47,14 @@ class JsIrBackendContext(
override val irBuiltIns: IrBuiltIns, override val irBuiltIns: IrBuiltIns,
val symbolTable: SymbolTable, val symbolTable: SymbolTable,
irModuleFragment: IrModuleFragment, irModuleFragment: IrModuleFragment,
val configuration: CompilerConfiguration, override val configuration: CompilerConfiguration,
val dependencies: List<IrModuleFragment> val dependencies: List<IrModuleFragment>
) : CommonBackendContext { ) : CommonBackendContext {
override val builtIns = module.builtIns 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 internalPackageFragmentDescriptor = KnownPackageFragmentDescriptor(builtIns.builtInsModule, FqName("kotlin.js.internal"))
val implicitDeclarationFile by lazy { val implicitDeclarationFile by lazy {
@@ -283,7 +284,7 @@ class JsIrBackendContext(
override fun log(message: () -> String) { override fun log(message: () -> String) {
/*TODO*/ /*TODO*/
print(message()) if (inVerbosePhase) print(message())
} }
override fun report(element: IrElement?, irFile: IrFile?, message: String, isError: Boolean) { 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.*
import org.jetbrains.kotlin.backend.common.lower.* 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.*
import org.jetbrains.kotlin.ir.backend.js.lower.calls.CallsLowering import org.jetbrains.kotlin.ir.backend.js.lower.calls.CallsLowering
import org.jetbrains.kotlin.ir.backend.js.lower.coroutines.CoroutineIntrinsicLowering 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.deepCopyWithSymbols
import org.jetbrains.kotlin.ir.util.patchDeclarationParents 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 DeclarationContainerLoweringPass.runOnFilesPostfix(files: Iterable<IrFile>) = files.forEach { runOnFilePostfix(it) }
private fun ClassLoweringPass.runOnFilesPostfix(moduleFragment: IrModuleFragment) = moduleFragment.files.forEach { runOnFilePostfix(it) } private fun ClassLoweringPass.runOnFilesPostfix(moduleFragment: IrModuleFragment) = moduleFragment.files.forEach { runOnFilePostfix(it) }
private fun validationCallback(context: JsIrBackendContext, module: IrModuleFragment) {
object IrModuleStartPhase : CompilerPhase<BackendContext, IrModuleFragment> { val validatorConfig = IrValidatorConfig(
override val name = "IrModuleFragment" abortOnError = true,
override val description = "State at start of IrModuleFragment lowering" ensureAllNodesAreDifferent = true,
override val prerequisite = emptySet() checkTypes = false,
override fun invoke(context: BackendContext, input: IrModuleFragment) = input checkDescriptors = false
)
module.accept(IrValidator(context, validatorConfig), null)
module.accept(CheckDeclarationParentsVisitor, null)
} }
private fun makeJsPhase( private fun makeJsModulePhase(
lowering: (JsIrBackendContext, IrModuleFragment) -> Unit, 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, description: String,
name: String, name: String,
prerequisite: Set<CompilerPhase<JsIrBackendContext, IrModuleFragment>> = emptySet() prerequisite: Set<AnyNamedPhase> = emptySet()
) = makePhase(lowering, description, name, prerequisite) ) = 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( private val moveBodilessDeclarationsToSeparatePlacePhase = makeJsModulePhase(
{ _, module -> MoveBodilessDeclarationsToSeparatePlace().lower(module) }, ::MoveBodilessDeclarationsToSeparatePlace,
name = "MoveBodilessDeclarationsToSeparatePlace", name = "MoveBodilessDeclarationsToSeparatePlace",
description = "Move `external` and `built-in` declarations into separate place to make the following lowerings do not care about them" description = "Move `external` and `built-in` declarations into separate place to make the following lowerings do not care about them"
) )
private val ExpectDeclarationsRemovingPhase = makeJsPhase( private val expectDeclarationsRemovingPhase = makeJsModulePhase(
{ context, module -> ExpectDeclarationsRemoving(context).lower(module) }, ::ExpectDeclarationsRemoving,
name = "ExpectDeclarationsRemoving", name = "ExpectDeclarationsRemoving",
description = "Remove expect declaration from module fragment" description = "Remove expect declaration from module fragment"
) )
private val CoroutineIntrinsicLoweringPhase = makeJsPhase( private val coroutineIntrinsicLoweringPhase = makeJsModulePhase(
{ context, module -> CoroutineIntrinsicLowering(context).lower(module) }, ::CoroutineIntrinsicLowering,
name = "CoroutineIntrinsicLowering", name = "CoroutineIntrinsicLowering",
description = "Replace common coroutine intrinsics with platform specific ones" description = "Replace common coroutine intrinsics with platform specific ones"
) )
private val ArrayInlineConstructorLoweringPhase = makeJsPhase( private val arrayInlineConstructorLoweringPhase = makeJsModulePhase(
{ context, module -> ArrayInlineConstructorLowering(context).lower(module) }, ::ArrayInlineConstructorLowering,
name = "ArrayInlineConstructorLowering", name = "ArrayInlineConstructorLowering",
description = "Replace array constructor with platform specific factory functions" description = "Replace array constructor with platform specific factory functions"
) )
private val LateinitLoweringPhase = makeJsPhase( private val lateinitLoweringPhase = makeJsModulePhase(
{ context, module -> LateinitLowering(context).lower(module) }, ::LateinitLowering,
name = "LateinitLowering", name = "LateinitLowering",
description = "Insert checks for lateinit field references" description = "Insert checks for lateinit field references"
) )
private val ModuleCopyingPhase = makeJsPhase( private val moduleCopyingPhase = makeCustomJsModulePhase(
{ context, module -> context.moduleFragmentCopy = module.deepCopyWithSymbols() }, { context, module -> context.moduleFragmentCopy = module.deepCopyWithSymbols() },
name = "ModuleCopying", name = "ModuleCopying",
description = "<Supposed to be removed> Copy current module to make it accessible from different one", 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 -> { context, module ->
FunctionInlining(context).inline(module) FunctionInlining(context).inline(module)
module.replaceUnboundSymbols(context) module.replaceUnboundSymbols(context)
@@ -87,190 +113,190 @@ private val FunctionInliningPhase = makeJsPhase(
}, },
name = "FunctionInliningPhase", name = "FunctionInliningPhase",
description = "Perform function inlining", description = "Perform function inlining",
prerequisite = setOf(ModuleCopyingPhase, LateinitLoweringPhase, ArrayInlineConstructorLoweringPhase, CoroutineIntrinsicLoweringPhase) prerequisite = setOf(moduleCopyingPhase, lateinitLoweringPhase, arrayInlineConstructorLoweringPhase, coroutineIntrinsicLoweringPhase)
) )
private val RemoveInlineFunctionsWithReifiedTypeParametersLoweringPhase = makeJsPhase( private val removeInlineFunctionsWithReifiedTypeParametersLoweringPhase = makeJsModulePhase(
{ _, module -> RemoveInlineFunctionsWithReifiedTypeParametersLowering().lower(module) }, { RemoveInlineFunctionsWithReifiedTypeParametersLowering() },
name = "RemoveInlineFunctionsWithReifiedTypeParametersLowering", name = "RemoveInlineFunctionsWithReifiedTypeParametersLowering",
description = "Remove Inline functions with reified parameters from context", description = "Remove Inline functions with reified parameters from context",
prerequisite = setOf(FunctionInliningPhase) prerequisite = setOf(functionInliningPhase)
) )
private val ThrowableSuccessorsLoweringPhase = makeJsPhase( private val throwableSuccessorsLoweringPhase = makeJsModulePhase(
{ context, module -> ThrowableSuccessorsLowering(context).lower(module) }, ::ThrowableSuccessorsLowering,
name = "ThrowableSuccessorsLowering", name = "ThrowableSuccessorsLowering",
description = "Link kotlin.Throwable and JavaScript Error together to provide proper interop between language and platform exceptions" description = "Link kotlin.Throwable and JavaScript Error together to provide proper interop between language and platform exceptions"
) )
private val TailrecLoweringPhase = makeJsPhase( private val tailrecLoweringPhase = makeJsModulePhase(
{ context, module -> TailrecLowering(context).lower(module) }, ::TailrecLowering,
name = "TailrecLowering", name = "TailrecLowering",
description = "Replace `tailrec` callsites with equivalent loop" description = "Replace `tailrec` callsites with equivalent loop"
) )
private val UnitMaterializationLoweringPhase = makeJsPhase( private val unitMaterializationLoweringPhase = makeJsModulePhase(
{ context, module -> UnitMaterializationLowering(context).lower(module) }, ::UnitMaterializationLowering,
name = "UnitMaterializationLowering", name = "UnitMaterializationLowering",
description = "Insert Unit object where it is supposed to be", description = "Insert Unit object where it is supposed to be",
prerequisite = setOf(TailrecLoweringPhase) prerequisite = setOf(tailrecLoweringPhase)
) )
private val EnumClassLoweringPhase = makeJsPhase( private val enumClassLoweringPhase = makeJsModulePhase(
{ context, module -> EnumClassLowering(context).lower(module) }, ::EnumClassLowering,
name = "EnumClassLowering", name = "EnumClassLowering",
description = "Transform Enum Class into regular Class" description = "Transform Enum Class into regular Class"
) )
private val EnumUsageLoweringPhase = makeJsPhase( private val enumUsageLoweringPhase = makeJsModulePhase(
{ context, module -> EnumUsageLowering(context).lower(module) }, ::EnumUsageLowering,
name = "EnumUsageLowering", name = "EnumUsageLowering",
description = "Replace enum access with invocation of corresponding function" description = "Replace enum access with invocation of corresponding function"
) )
private val SharedVariablesLoweringPhase = makeJsPhase( private val sharedVariablesLoweringPhase = makeJsModulePhase(
{ context, module -> SharedVariablesLowering(context).lower(module) }, ::SharedVariablesLowering,
name = "SharedVariablesLowering", name = "SharedVariablesLowering",
description = "Box captured mutable variables" description = "Box captured mutable variables"
) )
private val ReturnableBlockLoweringPhase = makeJsPhase( private val returnableBlockLoweringPhase = makeJsModulePhase(
{ context, module -> ReturnableBlockLowering(context).lower(module) }, ::ReturnableBlockLowering,
name = "ReturnableBlockLowering", name = "ReturnableBlockLowering",
description = "Replace returnable block with do-while loop", description = "Replace returnable block with do-while loop",
prerequisite = setOf(FunctionInliningPhase) prerequisite = setOf(functionInliningPhase)
) )
private val LocalDelegatedPropertiesLoweringPhase = makeJsPhase( private val localDelegatedPropertiesLoweringPhase = makeJsModulePhase(
{ _, module -> LocalDelegatedPropertiesLowering().lower(module) }, { LocalDelegatedPropertiesLowering() },
name = "LocalDelegatedPropertiesLowering", name = "LocalDelegatedPropertiesLowering",
description = "Transform Local Delegated properties" description = "Transform Local Delegated properties"
) )
private val LocalDeclarationsLoweringPhase = makeJsPhase( private val localDeclarationsLoweringPhase = makeJsModulePhase(
{ context, module -> LocalDeclarationsLowering(context).lower(module) }, ::LocalDeclarationsLowering,
name = "LocalDeclarationsLowering", name = "LocalDeclarationsLowering",
description = "Move local declarations into nearest declaration container", description = "Move local declarations into nearest declaration container",
prerequisite = setOf(SharedVariablesLoweringPhase) prerequisite = setOf(sharedVariablesLoweringPhase)
) )
private val InnerClassesLoweringPhase = makeJsPhase( private val innerClassesLoweringPhase = makeJsModulePhase(
{ context, module -> InnerClassesLowering(context).lower(module) }, ::InnerClassesLowering,
name = "InnerClassesLowering", name = "InnerClassesLowering",
description = "Capture outer this reference to inner class" description = "Capture outer this reference to inner class"
) )
private val InnerClassConstructorCallsLoweringPhase = makeJsPhase( private val innerClassConstructorCallsLoweringPhase = makeJsModulePhase(
{ context, module -> InnerClassConstructorCallsLowering(context).lower(module) }, ::InnerClassConstructorCallsLowering,
name = "InnerClassConstructorCallsLowering", name = "InnerClassConstructorCallsLowering",
description = "Replace inner class constructor invocation" description = "Replace inner class constructor invocation"
) )
private val SuspendFunctionsLoweringPhase = makeJsPhase( private val suspendFunctionsLoweringPhase = makeJsModulePhase(
{ context, module -> SuspendFunctionsLowering(context).lower(module) }, ::SuspendFunctionsLowering,
name = "SuspendFunctionsLowering", name = "SuspendFunctionsLowering",
description = "Transform suspend functions into CoroutineImpl instance and build state machine", description = "Transform suspend functions into CoroutineImpl instance and build state machine",
prerequisite = setOf(UnitMaterializationLoweringPhase, CoroutineIntrinsicLoweringPhase) prerequisite = setOf(unitMaterializationLoweringPhase, coroutineIntrinsicLoweringPhase)
) )
private val PrivateMembersLoweringPhase = makeJsPhase( private val privateMembersLoweringPhase = makeJsModulePhase(
{ context, module -> PrivateMembersLowering(context).lower(module) }, ::PrivateMembersLowering,
name = "PrivateMembersLowering", name = "PrivateMembersLowering",
description = "Extract private members from classes" description = "Extract private members from classes"
) )
private val CallableReferenceLoweringPhase = makeJsPhase( private val callableReferenceLoweringPhase = makeJsModulePhase(
{ context, module -> CallableReferenceLowering(context).lower(module) }, ::CallableReferenceLowering,
name = "CallableReferenceLowering", name = "CallableReferenceLowering",
description = "Handle callable references", description = "Handle callable references",
prerequisite = setOf( prerequisite = setOf(
SuspendFunctionsLoweringPhase, suspendFunctionsLoweringPhase,
LocalDeclarationsLoweringPhase, localDeclarationsLoweringPhase,
LocalDelegatedPropertiesLoweringPhase, localDelegatedPropertiesLoweringPhase,
PrivateMembersLoweringPhase privateMembersLoweringPhase
) )
) )
private val DefaultArgumentStubGeneratorPhase = makeJsPhase( private val defaultArgumentStubGeneratorPhase = makeJsModulePhase(
{ context, module -> JsDefaultArgumentStubGenerator(context).lower(module) }, ::JsDefaultArgumentStubGenerator,
name = "DefaultArgumentStubGenerator", name = "DefaultArgumentStubGenerator",
description = "Generate synthetic stubs for functions with default parameter values" description = "Generate synthetic stubs for functions with default parameter values"
) )
private val DefaultParameterInjectorPhase = makeJsPhase( private val defaultParameterInjectorPhase = makeJsModulePhase(
{ context, module -> DefaultParameterInjector(context).lower(module) }, ::DefaultParameterInjector,
name = "DefaultParameterInjector", name = "DefaultParameterInjector",
description = "Replace callsite with default parameters with corresponding stub function", description = "Replace callsite with default parameters with corresponding stub function",
prerequisite = setOf(CallableReferenceLoweringPhase, InnerClassesLoweringPhase) prerequisite = setOf(callableReferenceLoweringPhase, innerClassesLoweringPhase)
) )
private val DefaultParameterCleanerPhase = makeJsPhase( private val defaultParameterCleanerPhase = makeJsModulePhase(
{ context, module -> DefaultParameterCleaner(context).lower(module) }, ::DefaultParameterCleaner,
name = "DefaultParameterCleaner", name = "DefaultParameterCleaner",
description = "Clean default parameters up" description = "Clean default parameters up"
) )
private val JsDefaultCallbackGeneratorPhase = makeJsPhase( private val jsDefaultCallbackGeneratorPhase = makeJsModulePhase(
{ context, module -> JsDefaultCallbackGenerator(context).lower(module) }, ::JsDefaultCallbackGenerator,
name = "JsDefaultCallbackGenerator", name = "JsDefaultCallbackGenerator",
description = "Build binding for super calls with default parameters" description = "Build binding for super calls with default parameters"
) )
private val VarargLoweringPhase = makeJsPhase( private val varargLoweringPhase = makeJsModulePhase(
{ context, module -> VarargLowering(context).lower(module) }, ::VarargLowering,
name = "VarargLowering", name = "VarargLowering",
description = "Lower vararg arguments", description = "Lower vararg arguments",
prerequisite = setOf(CallableReferenceLoweringPhase) prerequisite = setOf(callableReferenceLoweringPhase)
) )
private val PropertiesLoweringPhase = makeJsPhase( private val propertiesLoweringPhase = makeJsModulePhase(
{ _, module -> PropertiesLowering().lower(module) }, { PropertiesLowering() },
name = "PropertiesLowering", name = "PropertiesLowering",
description = "Move fields and accessors out from its property" 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) }, { context, module -> InitializersLowering(context, JsLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER, false).lower(module) },
name = "InitializersLowering", name = "InitializersLowering",
description = "Merge init block and field initializers into [primary] constructor", description = "Merge init block and field initializers into [primary] constructor",
prerequisite = setOf(EnumClassLoweringPhase) prerequisite = setOf(enumClassLoweringPhase)
) )
private val MultipleCatchesLoweringPhase = makeJsPhase( private val multipleCatchesLoweringPhase = makeJsModulePhase(
{ context, module -> MultipleCatchesLowering(context).lower(module) }, ::MultipleCatchesLowering,
name = "MultipleCatchesLowering", name = "MultipleCatchesLowering",
description = "Replace multiple catches with single one" description = "Replace multiple catches with single one"
) )
private val BridgesConstructionPhase = makeJsPhase( private val bridgesConstructionPhase = makeJsModulePhase(
{ context, module -> BridgesConstruction(context).lower(module) }, ::BridgesConstruction,
name = "BridgesConstruction", name = "BridgesConstruction",
description = "Generate bridges", description = "Generate bridges",
prerequisite = setOf(SuspendFunctionsLoweringPhase) prerequisite = setOf(suspendFunctionsLoweringPhase)
) )
private val TypeOperatorLoweringPhase = makeJsPhase( private val typeOperatorLoweringPhase = makeJsModulePhase(
{ context, module -> TypeOperatorLowering(context).lower(module) }, ::TypeOperatorLowering,
name = "TypeOperatorLowering", name = "TypeOperatorLowering",
description = "Lower IrTypeOperator with corresponding logic", description = "Lower IrTypeOperator with corresponding logic",
prerequisite = setOf(BridgesConstructionPhase, RemoveInlineFunctionsWithReifiedTypeParametersLoweringPhase) prerequisite = setOf(bridgesConstructionPhase, removeInlineFunctionsWithReifiedTypeParametersLoweringPhase)
) )
private val SecondaryConstructorLoweringPhase = makeJsPhase( private val secondaryConstructorLoweringPhase = makeJsModulePhase(
{ context, module -> SecondaryConstructorLowering(context).lower(module) }, ::SecondaryConstructorLowering,
name = "SecondaryConstructorLoweringPhase", name = "SecondaryConstructorLoweringPhase",
description = "Generate static functions for each secondary constructor", description = "Generate static functions for each secondary constructor",
prerequisite = setOf(InnerClassesLoweringPhase) prerequisite = setOf(innerClassesLoweringPhase)
) )
private val SecondaryFactoryInjectorLoweringPhase = makeJsPhase( private val secondaryFactoryInjectorLoweringPhase = makeJsModulePhase(
{ context, module -> SecondaryFactoryInjectorLowering(context).lower(module) }, ::SecondaryFactoryInjectorLowering,
name = "SecondaryFactoryInjectorLoweringPhase", name = "SecondaryFactoryInjectorLoweringPhase",
description = "Replace usage of secondary constructor with corresponding static function", 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 -> { context, module ->
InlineClassLowering(context).run { InlineClassLowering(context).run {
inlineClassDeclarationLowering.runOnFilesPostfix(module) inlineClassDeclarationLowering.runOnFilesPostfix(module)
@@ -281,102 +307,95 @@ private val InlineClassLoweringPhase = makeJsPhase(
description = "Handle inline classes" description = "Handle inline classes"
) )
private val AutoboxingTransformerPhase = makeJsPhase( private val autoboxingTransformerPhase = makeJsModulePhase(
{ context, module -> AutoboxingTransformer(context).lower(module) }, ::AutoboxingTransformer,
name = "AutoboxingTransformer", name = "AutoboxingTransformer",
description = "Insert box/unbox intrinsics" description = "Insert box/unbox intrinsics"
) )
private val BlockDecomposerLoweringPhase = makeJsPhase( private val blockDecomposerLoweringPhase = makeCustomJsModulePhase(
{ context, module -> { context, module ->
BlockDecomposerLowering(context).lower(module) BlockDecomposerLowering(context).lower(module)
module.patchDeclarationParents() module.patchDeclarationParents()
}, },
name = "BlockDecomposerLowering", name = "BlockDecomposerLowering",
description = "Transform statement-like-expression nodes into pure-statement to make it easily transform into JS", 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( private val classReferenceLoweringPhase = makeJsModulePhase(
{ context, module -> ClassReferenceLowering(context).lower(module) }, ::ClassReferenceLowering,
name = "ClassReferenceLowering", name = "ClassReferenceLowering",
description = "Handle class references" description = "Handle class references"
) )
private val PrimitiveCompanionLoweringPhase = makeJsPhase( private val primitiveCompanionLoweringPhase = makeJsModulePhase(
{ context, module -> PrimitiveCompanionLowering(context).lower(module) }, ::PrimitiveCompanionLowering,
name = "PrimitiveCompanionLowering", name = "PrimitiveCompanionLowering",
description = "Replace common companion object access with platform one" description = "Replace common companion object access with platform one"
) )
private val ConstLoweringPhase = makeJsPhase( private val constLoweringPhase = makeJsModulePhase(
{ context, module -> ConstLowering(context).lower(module) }, ::ConstLowering,
name = "ConstLowering", name = "ConstLowering",
description = "Wrap Long and Char constants into constructor invocation" description = "Wrap Long and Char constants into constructor invocation"
) )
private val CallsLoweringPhase = makeJsPhase( private val callsLoweringPhase = makeJsModulePhase(
{ context, module -> CallsLowering(context).lower(module) }, ::CallsLowering,
name = "CallsLowering", name = "CallsLowering",
description = "Handle intrinsics" description = "Handle intrinsics"
) )
object IrModuleEndPhase : CompilerPhase<BackendContext, IrModuleFragment> { private val irToJsPhase = makeCustomJsModulePhase(
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(
{ context, module -> context.jsProgram = IrModuleToJsTransformer(context).let { module.accept(it, null) } }, { context, module -> context.jsProgram = IrModuleToJsTransformer(context).let { module.accept(it, null) } },
name = "IrModuleToJsTransformer", name = "IrModuleToJsTransformer",
description = "Generate JsAst from IrTree" description = "Generate JsAst from IrTree"
) )
val jsPhases = listOf( val jsPhases = namedIrModulePhase(
IrModuleStartPhase, name = "IrModuleLowering",
MoveBodilessDeclarationsToSeparatePlacePhase, description = "IR module lowering",
ExpectDeclarationsRemovingPhase, lower = moveBodilessDeclarationsToSeparatePlacePhase then
CoroutineIntrinsicLoweringPhase, expectDeclarationsRemovingPhase then
ArrayInlineConstructorLoweringPhase, coroutineIntrinsicLoweringPhase then
LateinitLoweringPhase, arrayInlineConstructorLoweringPhase then
ModuleCopyingPhase, lateinitLoweringPhase then
FunctionInliningPhase, moduleCopyingPhase then
RemoveInlineFunctionsWithReifiedTypeParametersLoweringPhase, functionInliningPhase then
ThrowableSuccessorsLoweringPhase, removeInlineFunctionsWithReifiedTypeParametersLoweringPhase then
TailrecLoweringPhase, throwableSuccessorsLoweringPhase then
UnitMaterializationLoweringPhase, tailrecLoweringPhase then
EnumClassLoweringPhase, unitMaterializationLoweringPhase then
EnumUsageLoweringPhase, enumClassLoweringPhase then
SharedVariablesLoweringPhase, enumUsageLoweringPhase then
ReturnableBlockLoweringPhase, sharedVariablesLoweringPhase then
LocalDelegatedPropertiesLoweringPhase, returnableBlockLoweringPhase then
LocalDeclarationsLoweringPhase, localDelegatedPropertiesLoweringPhase then
InnerClassesLoweringPhase, localDeclarationsLoweringPhase then
InnerClassConstructorCallsLoweringPhase, innerClassesLoweringPhase then
SuspendFunctionsLoweringPhase, innerClassConstructorCallsLoweringPhase then
PrivateMembersLoweringPhase, suspendFunctionsLoweringPhase then
CallableReferenceLoweringPhase, privateMembersLoweringPhase then
DefaultArgumentStubGeneratorPhase, callableReferenceLoweringPhase then
DefaultParameterInjectorPhase, defaultArgumentStubGeneratorPhase then
DefaultParameterCleanerPhase, defaultParameterInjectorPhase then
JsDefaultCallbackGeneratorPhase, defaultParameterCleanerPhase then
VarargLoweringPhase, jsDefaultCallbackGeneratorPhase then
PropertiesLoweringPhase, varargLoweringPhase then
InitializersLoweringPhase, propertiesLoweringPhase then
MultipleCatchesLoweringPhase, initializersLoweringPhase then
BridgesConstructionPhase, multipleCatchesLoweringPhase then
TypeOperatorLoweringPhase, bridgesConstructionPhase then
SecondaryConstructorLoweringPhase, typeOperatorLoweringPhase then
SecondaryFactoryInjectorLoweringPhase, secondaryConstructorLoweringPhase then
ClassReferenceLoweringPhase, secondaryFactoryInjectorLoweringPhase then
InlineClassLoweringPhase, classReferenceLoweringPhase then
AutoboxingTransformerPhase, inlineClassLoweringPhase then
BlockDecomposerLoweringPhase, autoboxingTransformerPhase then
PrimitiveCompanionLoweringPhase, blockDecomposerLoweringPhase then
ConstLoweringPhase, primitiveCompanionLoweringPhase then
CallsLoweringPhase, constLoweringPhase then
IrModuleEndPhase, callsLoweringPhase then
IrToJsPhase 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 package org.jetbrains.kotlin.ir.backend.js
import com.intellij.openapi.project.Project 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.CompilerConfiguration
import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
@@ -62,9 +62,7 @@ fun compile(
irDependencyModules irDependencyModules
) )
CompilerPhaseManager(context, context.phases, moduleFragment, JsPhaseRunner).run { jsPhases.invokeToplevel(context.phaseConfig, context, moduleFragment)
jsPhases.fold(data) { m, p -> phase(p, context, m) }
}
return Result(analysisResult.moduleDescriptor, context.jsProgram.toString(), context.moduleFragmentCopy) 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.backend.common.FileLoweringPass
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor 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.backend.js.lower.inline.addChild
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclaration 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.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
class MoveBodilessDeclarationsToSeparatePlace : FileLoweringPass { class MoveBodilessDeclarationsToSeparatePlace() : FileLoweringPass {
constructor(context: JsIrBackendContext) : this()
private val builtInClasses = listOf( private val builtInClasses = listOf(
"String", "String",
@@ -6,10 +6,9 @@
package org.jetbrains.kotlin.backend.jvm package org.jetbrains.kotlin.backend.jvm
import org.jetbrains.kotlin.backend.common.CommonBackendContext 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.Ir
import org.jetbrains.kotlin.backend.common.ir.Symbols 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.JvmDeclarationFactory
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmSharedVariablesManager import org.jetbrains.kotlin.backend.jvm.descriptors.JvmSharedVariablesManager
import org.jetbrains.kotlin.builtins.ReflectionTypes import org.jetbrains.kotlin.builtins.ReflectionTypes
@@ -47,19 +46,17 @@ class JvmBackendContext(
override val ir = JvmIr(irModuleFragment, symbolTable) 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 { init {
if (state.configuration.get(CommonConfigurationKeys.LIST_PHASES) == true) { 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 { private fun find(memberScope: MemberScope, className: String): ClassDescriptor {
return find(memberScope, Name.identifier(className)) return find(memberScope, Name.identifier(className))
} }
@@ -146,7 +143,7 @@ class JvmBackendContext(
override val coroutineSuspendedGetter: IrSimpleFunctionSymbol override val coroutineSuspendedGetter: IrSimpleFunctionSymbol
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates. 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( state.module.getPackage(FqName("kotlin")).memberScope.getContributedVariables(
Name.identifier("isInitialized"), NoLookupLocation.FROM_BACKEND Name.identifier("isInitialized"), NoLookupLocation.FROM_BACKEND
).single { ).single {
@@ -16,32 +16,78 @@
package org.jetbrains.kotlin.backend.jvm package org.jetbrains.kotlin.backend.jvm
import org.jetbrains.kotlin.backend.common.BackendContext import org.jetbrains.kotlin.backend.common.*
import org.jetbrains.kotlin.backend.common.CompilerPhase 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.declarations.IrFile
import org.jetbrains.kotlin.ir.util.PatchDeclarationParentsVisitor import org.jetbrains.kotlin.ir.util.PatchDeclarationParentsVisitor
import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid
fun makePatchParentsPhase(number: Int) = object : CompilerPhase<BackendContext, IrFile> { private fun makePatchParentsPhase(number: Int) = namedIrFilePhase(
override val name: String = "PatchParents$number" lower = object : SameTypeCompilerPhase<CommonBackendContext, IrFile> {
override val description: String = "Patch parent references in IrFile, pass $number" override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: CommonBackendContext, input: IrFile): IrFile {
override val prerequisite: Set<CompilerPhase<BackendContext, *>> = emptySet() 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 { internal val jvmPhases = namedIrFilePhase(
input.acceptVoid(PatchDeclarationParentsVisitor()) name = "IrLowering",
return input 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) { class JvmLower(val context: JvmBackendContext) {
fun lower(irFile: IrFile) { fun lower(irFile: IrFile) {
var state = irFile
// TODO run lowering passes as callbacks in bottom-up visitor // TODO run lowering passes as callbacks in bottom-up visitor
jvmPhases.invokeToplevel(context.phaseConfig, context, irFile)
context.rootPhaseManager(irFile).apply {
for (jvmPhase in jvmPhases) {
state = phase(jvmPhase, context, state)
}
}
} }
} }
@@ -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.BackendContext
import org.jetbrains.kotlin.backend.common.ClassLoweringPass 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.IrClass
import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.util.isAnnotationClass 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() constructor(@Suppress("UNUSED_PARAMETER") context: BackendContext) : this()
override fun lower(irClass: IrClass) { 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.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irBlockBody import org.jetbrains.kotlin.backend.common.lower.irBlockBody
import org.jetbrains.kotlin.backend.common.lower.irNot 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.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmFunctionDescriptorImpl 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.Type
import org.jetbrains.org.objectweb.asm.commons.Method 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 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.copyTo
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
import org.jetbrains.kotlin.backend.common.lower.* 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.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.codegen.isInlineIrExpression import org.jetbrains.kotlin.backend.jvm.codegen.isInlineIrExpression
@@ -51,8 +52,14 @@ class CrIrType(val type: Type) : IrType {
override val annotations = emptyList() override val annotations = emptyList()
} }
internal val callableReferencePhase = makeIrFilePhase(
::CallableReferenceLowering,
name = "CallableReference",
description = "Handle callable references"
)
//Originally was copied from K/Native //Originally was copied from K/Native
class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPass { internal class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPass {
private var functionReferenceCount = 0 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.FileLoweringPass
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irBlock 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.IrStatement
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.* 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.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.load.java.JvmAbi.JVM_FIELD_ANNOTATION_FQ_NAME 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) { override fun lower(irFile: IrFile) {
irFile.transformChildrenVoid(this) irFile.transformChildrenVoid(this)
} }
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.backend.jvm.lower
import gnu.trove.TObjectIntHashMap import gnu.trove.TObjectIntHashMap
import org.jetbrains.kotlin.backend.common.ClassLoweringPass 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.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmPropertyDescriptorImpl import org.jetbrains.kotlin.backend.jvm.descriptors.JvmPropertyDescriptorImpl
import org.jetbrains.kotlin.backend.jvm.descriptors.createValueParameter 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 org.jetbrains.org.objectweb.asm.Opcodes
import java.util.* 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) { override fun lower(irClass: IrClass) {
if (!irClass.isEnumClass) return 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.FileLoweringPass
import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassDescriptor import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassDescriptor
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor 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.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
@@ -34,7 +35,13 @@ import org.jetbrains.kotlin.psi2ir.PsiSourceManager
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
import java.util.* 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) { override fun lower(irFile: IrFile) {
val classes = ArrayList<IrClass>() val classes = ArrayList<IrClass>()
val fileClassMembers = ArrayList<IrDeclaration>() 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.descriptors.WrappedValueParameterDescriptor
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irIfThen 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.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.descriptors.Modality 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.ir.util.isSubclassOf
import org.jetbrains.kotlin.name.Name 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) { override fun lower(irClass: IrClass) {
val invokeFunctions = irClass.filterDeclarations<IrSimpleFunction> { it.name.toString() == "invoke" } 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.descriptors.WrappedSimpleFunctionDescriptor
import org.jetbrains.kotlin.backend.common.ir.copyParameterDeclarationsFrom import org.jetbrains.kotlin.backend.common.ir.copyParameterDeclarationsFrom
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder 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.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface 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.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name 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 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.ir.copyTypeParametersFrom
import org.jetbrains.kotlin.backend.common.lower.InitializersLowering.Companion.clinitName import org.jetbrains.kotlin.backend.common.lower.InitializersLowering.Companion.clinitName
import org.jetbrains.kotlin.backend.common.lower.VariableRemapper 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.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations 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.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name 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 val state = context.state
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.backend.jvm.lower package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass 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.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.codegen.intrinsics.Not import org.jetbrains.kotlin.codegen.intrinsics.Not
import org.jetbrains.kotlin.ir.IrStatement 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.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid 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 { class JvmBuiltinOptimizationLowering(val context: JvmBackendContext) : FileLoweringPass {
companion object { companion object {
@@ -6,8 +6,8 @@
package org.jetbrains.kotlin.backend.jvm.lower package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass 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.utils.isSubtypeOf
import org.jetbrains.kotlin.backend.common.makePhase
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.expressions.IrCall 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.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.psi2ir.transformations.InsertImplicitCasts 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) : class JvmCoercionToUnitPatcher(val context: JvmBackendContext) :
InsertImplicitCasts( InsertImplicitCasts(
context.builtIns, context.irBuiltIns, context.builtIns, context.irBuiltIns,
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.backend.jvm.lower package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.ClassLoweringPass 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.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor 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.calls.components.hasDefaultValue
import org.jetbrains.kotlin.resolve.jvm.annotations.findJvmOverloadsAnnotation 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) { override fun lower(irClass: IrClass) {
val functions = irClass.declarations.filterIsInstance<IrFunction>().filter { 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.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irBlock import org.jetbrains.kotlin.backend.common.lower.irBlock
import org.jetbrains.kotlin.backend.common.lower.replaceThisByStaticReference 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.common.runOnFilePostfix
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin 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.kotlin.resolve.annotations.JVM_STATIC_ANNOTATION_FQ_NAME
import org.jetbrains.org.objectweb.asm.Opcodes 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 * For @JvmStatic functions within companion objects of classes, we synthesize proxy static functions that redirect
* to the actual implementation. * to the actual implementation.
* For @JvmStatic functions within static objects, we make the actual function static and modify all call sites. * 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) { override fun lower(irFile: IrFile) {
CompanionObjectJvmStaticLowering(context).runOnFilePostfix(irFile) CompanionObjectJvmStaticLowering(context).runOnFilePostfix(irFile)
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.backend.jvm.lower package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass 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.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.expressions.* 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.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid 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) { override fun lower(irFile: IrFile) {
irFile.transformChildrenVoid(object : IrElementTransformerVoid() { 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.WrappedFieldDescriptor
import org.jetbrains.kotlin.backend.common.descriptors.WrappedVariableDescriptor import org.jetbrains.kotlin.backend.common.descriptors.WrappedVariableDescriptor
import org.jetbrains.kotlin.backend.common.lower.replaceThisByStaticReference 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.descriptors.Visibilities
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement 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.load.java.JvmAbi.JVM_FIELD_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.name.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) { override fun lower(irClass: IrClass) {
val fieldReplacementMap = mutableMapOf<IrFieldSymbol, IrFieldSymbol>() val fieldReplacementMap = mutableMapOf<IrFieldSymbol, IrFieldSymbol>()
if (irClass.isObject && !irClass.isCompanion && irClass.visibility != Visibilities.LOCAL) { 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.FileLoweringPass
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext 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.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.codegen.JvmCodegenUtil.isCompanionObjectInInterfaceNotIntrinsic import org.jetbrains.kotlin.codegen.JvmCodegenUtil.isCompanionObjectInInterfaceNotIntrinsic
import org.jetbrains.kotlin.descriptors.* 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.defaultType
import org.jetbrains.kotlin.ir.util.isObject 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>>() private var pendingTransformations = mutableListOf<Function0<Unit>>()
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.backend.jvm.lower package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.BodyLoweringPass 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.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.ir.expressions.IrBody import org.jetbrains.kotlin.ir.expressions.IrBody
import org.jetbrains.kotlin.ir.expressions.IrExpression 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.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid 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) { override fun lower(irBody: IrBody) {
irBody.transformChildrenVoid(this) 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.BackendContext
import org.jetbrains.kotlin.backend.common.ClassLoweringPass 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.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid 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() constructor(@Suppress("UNUSED_PARAMETER") context: BackendContext) : this()
override fun lower(irClass: IrClass) { override fun lower(irClass: IrClass) {
@@ -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.WrappedSimpleFunctionDescriptor
import org.jetbrains.kotlin.backend.common.descriptors.WrappedValueParameterDescriptor import org.jetbrains.kotlin.backend.common.descriptors.WrappedValueParameterDescriptor
import org.jetbrains.kotlin.backend.common.ir.* 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.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.intrinsics.receiverAndArgs 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.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils 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 pendingTransformations = mutableListOf<Function0<Unit>>()
private val inlinedLambdasCollector = InlinedLambdasCollector() 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.KnownClassDescriptor
import org.jetbrains.kotlin.backend.common.descriptors.KnownPackageFragmentDescriptor import org.jetbrains.kotlin.backend.common.descriptors.KnownPackageFragmentDescriptor
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder 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.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface 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.resolve.descriptorUtil.getAllSuperclassesWithoutAny
import org.jetbrains.kotlin.types.Variance 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) { override fun lower(irClass: IrClass) {
if (irClass.isJvmInterface) return if (irClass.isJvmInterface) return