
org.jetbrains.kotlin.ir.backend.js.JsLoweringPhases.kt Maven / Gradle / Ivy
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.*
import org.jetbrains.kotlin.backend.common.lower.*
import org.jetbrains.kotlin.backend.common.lower.inline.FunctionInlining
import org.jetbrains.kotlin.backend.common.phaser.*
import org.jetbrains.kotlin.ir.backend.js.lower.*
import org.jetbrains.kotlin.ir.backend.js.lower.calls.CallsLowering
import org.jetbrains.kotlin.ir.backend.js.lower.coroutines.JsSuspendFunctionsLowering
import org.jetbrains.kotlin.ir.backend.js.lower.inline.RemoveInlineFunctionsWithReifiedTypeParametersLowering
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
private fun DeclarationContainerLoweringPass.runOnFilesPostfix(files: Iterable) = files.forEach { runOnFilePostfix(it) }
private fun ClassLoweringPass.runOnFilesPostfix(moduleFragment: IrModuleFragment) = moduleFragment.files.forEach { runOnFilePostfix(it) }
private fun validationCallback(context: JsIrBackendContext, module: IrModuleFragment) {
val validatorConfig = IrValidatorConfig(
abortOnError = true,
ensureAllNodesAreDifferent = true,
checkTypes = false,
checkDescriptors = false
)
module.accept(IrValidator(context, validatorConfig), null)
module.accept(CheckDeclarationParentsVisitor, null)
}
val validationAction = makeVerifyAction(::validationCallback)
private fun makeJsModulePhase(
lowering: (JsIrBackendContext) -> FileLoweringPass,
name: String,
description: String,
prerequisite: Set = emptySet()
) = makeIrModulePhase(lowering, name, description, prerequisite, actions = setOf(validationAction, defaultDumper))
private fun makeCustomJsModulePhase(
op: (JsIrBackendContext, IrModuleFragment) -> Unit,
description: String,
name: String,
prerequisite: Set = emptySet()
) = namedIrModulePhase(
name,
description,
prerequisite,
actions = setOf(defaultDumper, validationAction),
nlevels = 0,
lower = object : SameTypeCompilerPhase {
override fun invoke(
phaseConfig: PhaseConfig,
phaserState: PhaserState,
context: JsIrBackendContext,
input: IrModuleFragment
): IrModuleFragment {
op(context, input)
return input
}
}
)
private val validateIrBeforeLowering = makeCustomJsModulePhase(
{ context, module -> validationCallback(context, module) },
name = "ValidateIrBeforeLowering",
description = "Validate IR before lowering"
)
private val validateIrAfterLowering = makeCustomJsModulePhase(
{ context, module -> validationCallback(context, module) },
name = "ValidateIrAfterLowering",
description = "Validate IR after lowering"
)
private val expectDeclarationsRemovingPhase = makeJsModulePhase(
::ExpectDeclarationsRemoveLowering,
name = "ExpectDeclarationsRemoving",
description = "Remove expect declaration from module fragment"
)
private val lateinitLoweringPhase = makeJsModulePhase(
::LateinitLowering,
name = "LateinitLowering",
description = "Insert checks for lateinit field references"
)
private val stripTypeAliasDeclarationsPhase = makeJsModulePhase(
{ StripTypeAliasDeclarationsLowering() },
name = "StripTypeAliasDeclarations",
description = "Strip typealias declarations"
)
// TODO make all lambda-related stuff work with IrFunctionExpression and drop this phase
private val provisionalFunctionExpressionPhase = makeJsModulePhase(
{ ProvisionalFunctionExpressionLowering() },
name = "FunctionExpression",
description = "Transform IrFunctionExpression to a local function reference"
)
private val arrayConstructorPhase = makeJsModulePhase(
::ArrayConstructorLowering,
name = "ArrayConstructor",
description = "Transform `Array(size) { index -> value }` into a loop"
)
private val functionInliningPhase = makeCustomJsModulePhase(
{ context, module ->
FunctionInlining(context).inline(module)
module.patchDeclarationParents()
},
name = "FunctionInliningPhase",
description = "Perform function inlining",
prerequisite = setOf(expectDeclarationsRemovingPhase)
)
private val removeInlineFunctionsWithReifiedTypeParametersLoweringPhase = makeJsModulePhase(
{ RemoveInlineFunctionsWithReifiedTypeParametersLowering() },
name = "RemoveInlineFunctionsWithReifiedTypeParametersLowering",
description = "Remove Inline functions with reified parameters from context",
prerequisite = setOf(functionInliningPhase)
)
private val throwableSuccessorsLoweringPhase = makeJsModulePhase(
::ThrowableLowering,
name = "ThrowableLowering",
description = "Link kotlin.Throwable and JavaScript Error together to provide proper interop between language and platform exceptions"
)
private val tailrecLoweringPhase = makeJsModulePhase(
::TailrecLowering,
name = "TailrecLowering",
description = "Replace `tailrec` callsites with equivalent loop"
)
private val enumClassConstructorLoweringPhase = makeJsModulePhase(
::EnumClassConstructorLowering,
name = "EnumClassConstructorLowering",
description = "Transform Enum Class into regular Class"
)
private val enumClassLoweringPhase = makeJsModulePhase(
::EnumClassLowering,
name = "EnumClassLowering",
description = "Transform Enum Class into regular Class",
prerequisite = setOf(enumClassConstructorLoweringPhase)
)
private val enumUsageLoweringPhase = makeJsModulePhase(
::EnumUsageLowering,
name = "EnumUsageLowering",
description = "Replace enum access with invocation of corresponding function",
prerequisite = setOf(enumClassLoweringPhase)
)
private val sharedVariablesLoweringPhase = makeJsModulePhase(
::SharedVariablesLowering,
name = "SharedVariablesLowering",
description = "Box captured mutable variables"
)
private val returnableBlockLoweringPhase = makeJsModulePhase(
::ReturnableBlockLowering,
name = "ReturnableBlockLowering",
description = "Replace returnable block with do-while loop",
prerequisite = setOf(functionInliningPhase)
)
private val localDelegatedPropertiesLoweringPhase = makeJsModulePhase(
{ LocalDelegatedPropertiesLowering() },
name = "LocalDelegatedPropertiesLowering",
description = "Transform Local Delegated properties"
)
private val localDeclarationsLoweringPhase = makeJsModulePhase(
::LocalDeclarationsLowering,
name = "LocalDeclarationsLowering",
description = "Move local declarations into nearest declaration container",
prerequisite = setOf(sharedVariablesLoweringPhase, localDelegatedPropertiesLoweringPhase)
)
private val localClassExtractionPhase = makeJsModulePhase(
::LocalClassPopupLowering,
name = "LocalClassExtractionPhase",
description = "Move local declarations into nearest declaration container",
prerequisite = setOf(localDeclarationsLoweringPhase)
)
private val innerClassesLoweringPhase = makeJsModulePhase(
::InnerClassesLowering,
name = "InnerClassesLowering",
description = "Capture outer this reference to inner class"
)
private val innerClassConstructorCallsLoweringPhase = makeJsModulePhase(
::InnerClassConstructorCallsLowering,
name = "InnerClassConstructorCallsLowering",
description = "Replace inner class constructor invocation"
)
private val suspendFunctionsLoweringPhase = makeJsModulePhase(
::JsSuspendFunctionsLowering,
name = "SuspendFunctionsLowering",
description = "Transform suspend functions into CoroutineImpl instance and build state machine"
)
private val privateMembersLoweringPhase = makeJsModulePhase(
::PrivateMembersLowering,
name = "PrivateMembersLowering",
description = "Extract private members from classes"
)
private val callableReferenceLoweringPhase = makeJsModulePhase(
::CallableReferenceLowering,
name = "CallableReferenceLowering",
description = "Handle callable references",
prerequisite = setOf(
suspendFunctionsLoweringPhase,
localDeclarationsLoweringPhase,
localDelegatedPropertiesLoweringPhase,
privateMembersLoweringPhase
)
)
private val defaultArgumentStubGeneratorPhase = makeJsModulePhase(
::JsDefaultArgumentStubGenerator,
name = "DefaultArgumentStubGenerator",
description = "Generate synthetic stubs for functions with default parameter values"
)
private val defaultParameterInjectorPhase = makeJsModulePhase(
{ context -> DefaultParameterInjector(context, skipExternalMethods = true) },
name = "DefaultParameterInjector",
description = "Replace callsite with default parameters with corresponding stub function",
prerequisite = setOf(callableReferenceLoweringPhase, innerClassesLoweringPhase)
)
private val defaultParameterCleanerPhase = makeJsModulePhase(
::DefaultParameterCleaner,
name = "DefaultParameterCleaner",
description = "Clean default parameters up"
)
private val jsDefaultCallbackGeneratorPhase = makeJsModulePhase(
::JsDefaultCallbackGenerator,
name = "JsDefaultCallbackGenerator",
description = "Build binding for super calls with default parameters"
)
private val varargLoweringPhase = makeJsModulePhase(
::VarargLowering,
name = "VarargLowering",
description = "Lower vararg arguments",
prerequisite = setOf(callableReferenceLoweringPhase)
)
private val propertiesLoweringPhase = makeJsModulePhase(
{ context -> PropertiesLowering(context, skipExternalProperties = true, generateAnnotationFields = true) },
name = "PropertiesLowering",
description = "Move fields and accessors out from its property"
)
private val primaryConstructorLoweringPhase = makeJsModulePhase(
::PrimaryConstructorLowering,
name = "PrimaryConstructorLowering",
description = "Creates primary constructor if it doesn't exist",
prerequisite = setOf(enumClassConstructorLoweringPhase)
)
private val initializersLoweringPhase = makeCustomJsModulePhase(
{ context, module -> InitializersLowering(context, JsLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER, false).lower(module) },
name = "InitializersLowering",
description = "Merge init block and field initializers into [primary] constructor",
prerequisite = setOf(enumClassConstructorLoweringPhase, primaryConstructorLoweringPhase)
)
private val multipleCatchesLoweringPhase = makeJsModulePhase(
::MultipleCatchesLowering,
name = "MultipleCatchesLowering",
description = "Replace multiple catches with single one"
)
private val bridgesConstructionPhase = makeJsModulePhase(
::BridgesConstruction,
name = "BridgesConstruction",
description = "Generate bridges",
prerequisite = setOf(suspendFunctionsLoweringPhase)
)
private val typeOperatorLoweringPhase = makeJsModulePhase(
::TypeOperatorLowering,
name = "TypeOperatorLowering",
description = "Lower IrTypeOperator with corresponding logic",
prerequisite = setOf(bridgesConstructionPhase, removeInlineFunctionsWithReifiedTypeParametersLoweringPhase)
)
private val secondaryConstructorLoweringPhase = makeJsModulePhase(
::SecondaryConstructorLowering,
name = "SecondaryConstructorLoweringPhase",
description = "Generate static functions for each secondary constructor",
prerequisite = setOf(innerClassesLoweringPhase)
)
private val secondaryFactoryInjectorLoweringPhase = makeJsModulePhase(
::SecondaryFactoryInjectorLowering,
name = "SecondaryFactoryInjectorLoweringPhase",
description = "Replace usage of secondary constructor with corresponding static function",
prerequisite = setOf(innerClassesLoweringPhase)
)
private val inlineClassLoweringPhase = makeCustomJsModulePhase(
{ context, module ->
InlineClassLowering(context).run {
inlineClassDeclarationLowering.runOnFilesPostfix(module)
inlineClassUsageLowering.lower(module)
}
},
name = "InlineClassLowering",
description = "Handle inline classes"
)
private val autoboxingTransformerPhase = makeJsModulePhase(
::AutoboxingTransformer,
name = "AutoboxingTransformer",
description = "Insert box/unbox intrinsics"
)
private val blockDecomposerLoweringPhase = makeCustomJsModulePhase(
{ context, module ->
JsBlockDecomposerLowering(context).lower(module)
module.patchDeclarationParents()
},
name = "BlockDecomposerLowering",
description = "Transform statement-like-expression nodes into pure-statement to make it easily transform into JS",
prerequisite = setOf(typeOperatorLoweringPhase, suspendFunctionsLoweringPhase)
)
private val classReferenceLoweringPhase = makeJsModulePhase(
::ClassReferenceLowering,
name = "ClassReferenceLowering",
description = "Handle class references"
)
private val primitiveCompanionLoweringPhase = makeJsModulePhase(
::PrimitiveCompanionLowering,
name = "PrimitiveCompanionLowering",
description = "Replace common companion object access with platform one"
)
private val constLoweringPhase = makeJsModulePhase(
::ConstLowering,
name = "ConstLowering",
description = "Wrap Long and Char constants into constructor invocation"
)
private val callsLoweringPhase = makeJsModulePhase(
::CallsLowering,
name = "CallsLowering",
description = "Handle intrinsics"
)
private val testGenerationPhase = makeJsModulePhase(
::TestGenerator,
name = "TestGenerationLowering",
description = "Generate invocations to kotlin.test suite and test functions"
)
private val staticMembersLoweringPhase = makeJsModulePhase(
::StaticMembersLowering,
name = "StaticMembersLowering",
description = "Move static member declarations to top-level"
)
private val objectDeclarationLoweringPhase = makeCustomJsModulePhase(
{ context, module -> ObjectDeclarationLowering(context, context.objectToGetInstanceFunction).lower(module) },
name = "ObjectDeclarationLowering",
description = "Create lazy object instance generator functions"
)
private val objectUsageLoweringPhase = makeCustomJsModulePhase(
{ context, module -> ObjectUsageLowering(context, context.objectToGetInstanceFunction).lower(module) },
name = "ObjectUsageLowering",
description = "Transform IrGetObjectValue into instance generator call"
)
val jsPhases = namedIrModulePhase(
name = "IrModuleLowering",
description = "IR module lowering",
lower = validateIrBeforeLowering then
testGenerationPhase then
expectDeclarationsRemovingPhase then
stripTypeAliasDeclarationsPhase then
arrayConstructorPhase then
functionInliningPhase then
provisionalFunctionExpressionPhase then
lateinitLoweringPhase then
tailrecLoweringPhase then
enumClassConstructorLoweringPhase then
sharedVariablesLoweringPhase then
localDelegatedPropertiesLoweringPhase then
localDeclarationsLoweringPhase then
localClassExtractionPhase then
innerClassesLoweringPhase then
innerClassConstructorCallsLoweringPhase then
propertiesLoweringPhase then
primaryConstructorLoweringPhase then
initializersLoweringPhase then
// Common prefix ends
enumClassLoweringPhase then
enumUsageLoweringPhase then
suspendFunctionsLoweringPhase then
returnableBlockLoweringPhase then
privateMembersLoweringPhase then
callableReferenceLoweringPhase then
defaultArgumentStubGeneratorPhase then
defaultParameterInjectorPhase then
defaultParameterCleanerPhase then
jsDefaultCallbackGeneratorPhase then
removeInlineFunctionsWithReifiedTypeParametersLoweringPhase then
throwableSuccessorsLoweringPhase then
varargLoweringPhase then
multipleCatchesLoweringPhase then
bridgesConstructionPhase then
typeOperatorLoweringPhase then
secondaryConstructorLoweringPhase then
secondaryFactoryInjectorLoweringPhase then
classReferenceLoweringPhase then
inlineClassLoweringPhase then
autoboxingTransformerPhase then
blockDecomposerLoweringPhase then
primitiveCompanionLoweringPhase then
constLoweringPhase then
objectDeclarationLoweringPhase then
objectUsageLoweringPhase then
callsLoweringPhase then
validateIrAfterLowering
)
© 2015 - 2025 Weber Informatics LLC | Privacy Policy