Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.jetbrains.kotlin.backend.jvm.JvmLower.kt Maven / Gradle / Ivy
/*
* Copyright 2010-2020 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.backend.jvm
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.backend.common.lower.loops.forLoopsPhase
import org.jetbrains.kotlin.backend.common.lower.optimizations.foldConstantLoweringPhase
import org.jetbrains.kotlin.backend.common.phaser.*
import org.jetbrains.kotlin.backend.jvm.codegen.shouldContainSuspendMarkers
import org.jetbrains.kotlin.backend.jvm.lower.*
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
import org.jetbrains.kotlin.ir.util.PatchDeclarationParentsVisitor
import org.jetbrains.kotlin.ir.util.isAnonymousObject
import org.jetbrains.kotlin.ir.util.parentAsClass
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
import org.jetbrains.kotlin.name.NameUtils
private fun makePatchParentsPhase(number: Int): NamedCompilerPhase = makeIrFilePhase(
{ PatchDeclarationParents() },
name = "PatchParents$number",
description = "Patch parent references in IrFile, pass $number",
)
private class PatchDeclarationParents : FileLoweringPass {
override fun lower(irFile: IrFile) {
irFile.acceptVoid(PatchDeclarationParentsVisitor())
}
}
private val validateIrBeforeLowering = makeCustomPhase(
{ context, module -> validationCallback(context, module, checkProperties = true) },
name = "ValidateIrBeforeLowering",
description = "Validate IR before lowering"
)
private val validateIrAfterLowering = makeCustomPhase(
{ context, module -> validationCallback(context, module, checkProperties = true) },
name = "ValidateIrAfterLowering",
description = "Validate IR after lowering"
)
private val stripTypeAliasDeclarationsPhase = makeIrFilePhase(
{ StripTypeAliasDeclarationsLowering() },
name = "StripTypeAliasDeclarations",
description = "Strip typealias declarations"
)
// TODO make all lambda-related stuff work with IrFunctionExpression and drop this phase
private val provisionalFunctionExpressionPhase = makeIrFilePhase(
{ ProvisionalFunctionExpressionLowering() },
name = "FunctionExpression",
description = "Transform IrFunctionExpression to a local function reference"
)
private val arrayConstructorPhase = makeIrFilePhase(
::ArrayConstructorLowering,
name = "ArrayConstructor",
description = "Transform `Array(size) { index -> value }` into a loop"
)
private val expectDeclarationsRemovingPhase = makeIrModulePhase(
::ExpectDeclarationsRemoveLowering,
name = "ExpectDeclarationsRemoving",
description = "Remove expect declaration from module fragment"
)
private val lateinitNullableFieldsPhase = makeIrFilePhase(
::NullableFieldsForLateinitCreationLowering,
name = "LateinitNullableFields",
description = "Create nullable fields for lateinit properties"
)
private val lateinitDeclarationLoweringPhase = makeIrFilePhase(
::NullableFieldsDeclarationLowering,
name = "LateinitDeclarations",
description = "Reference nullable fields from properties and getters + insert checks"
)
private val lateinitUsageLoweringPhase = makeIrFilePhase(
::LateinitUsageLowering,
name = "LateinitUsage",
description = "Insert checks for lateinit field references"
)
internal val propertiesPhase = makeIrFilePhase(
::JvmPropertiesLowering,
name = "Properties",
description = "Move fields and accessors for properties to their classes, replace calls to default property accessors " +
"with field accesses, remove unused accessors and create synthetic methods for property annotations",
stickyPostconditions = setOf((PropertiesLowering)::checkNoProperties)
)
internal val localDeclarationsPhase = makeIrFilePhase(
{ context ->
LocalDeclarationsLowering(
context,
object : LocalNameProvider {
override fun localName(declaration: IrDeclarationWithName): String =
NameUtils.sanitizeAsJavaIdentifier(super.localName(declaration))
},
object : VisibilityPolicy {
override fun forClass(declaration: IrClass, inInlineFunctionScope: Boolean): DescriptorVisibility =
if (declaration.origin == JvmLoweredDeclarationOrigin.LAMBDA_IMPL ||
declaration.origin == JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL ||
declaration.origin == JvmLoweredDeclarationOrigin.GENERATED_PROPERTY_REFERENCE
) {
scopedVisibility(inInlineFunctionScope)
} else {
declaration.visibility
}
override fun forConstructor(declaration: IrConstructor, inInlineFunctionScope: Boolean): DescriptorVisibility =
if (declaration.parentAsClass.isAnonymousObject)
scopedVisibility(inInlineFunctionScope)
else
declaration.visibility
override fun forCapturedField(value: IrValueSymbol): DescriptorVisibility =
JavaDescriptorVisibilities.PACKAGE_VISIBILITY // avoid requiring a synthetic accessor for it
private fun scopedVisibility(inInlineFunctionScope: Boolean): DescriptorVisibility =
if (inInlineFunctionScope) DescriptorVisibilities.PUBLIC else JavaDescriptorVisibilities.PACKAGE_VISIBILITY
}
)
},
name = "JvmLocalDeclarations",
description = "Move local declarations to classes",
prerequisite = setOf(functionReferencePhase, sharedVariablesPhase)
)
private val jvmLocalClassExtractionPhase = makeIrFilePhase(
::JvmLocalClassPopupLowering,
name = "JvmLocalClassExtraction",
description = "Move local classes from field initializers and anonymous init blocks into the containing class"
)
private val computeStringTrimPhase = makeIrFilePhase(
{ context ->
if (context.state.canReplaceStdlibRuntimeApiBehavior)
StringTrimLowering(context)
else
FileLoweringPass.Empty
},
name = "StringTrimLowering",
description = "Compute trimIndent and trimMargin operations on constant strings"
)
private val defaultArgumentStubPhase = makeIrFilePhase(
::JvmDefaultArgumentStubGenerator,
name = "DefaultArgumentsStubGenerator",
description = "Generate synthetic stubs for functions with default parameter values",
prerequisite = setOf(localDeclarationsPhase)
)
private val defaultArgumentCleanerPhase = makeIrFilePhase(
{ context: JvmBackendContext -> DefaultParameterCleaner(context, replaceDefaultValuesWithStubs = true) },
name = "DefaultParameterCleaner",
description = "Replace default values arguments with stubs",
prerequisite = setOf(defaultArgumentStubPhase)
)
private val defaultArgumentInjectorPhase = makeIrFilePhase(
::JvmDefaultParameterInjector,
name = "DefaultParameterInjector",
description = "Transform calls with default arguments into calls to stubs",
prerequisite = setOf(functionReferencePhase, inlineCallableReferenceToLambdaPhase)
)
private val interfacePhase = makeIrFilePhase(
::InterfaceLowering,
name = "Interface",
description = "Move default implementations of interface members to DefaultImpls class",
prerequisite = setOf(defaultArgumentInjectorPhase)
)
private val innerClassesPhase = makeIrFilePhase(
{ context -> InnerClassesLowering(context, context.innerClassesSupport) },
name = "InnerClasses",
description = "Add 'outer this' fields to inner classes",
prerequisite = setOf(localDeclarationsPhase)
)
private val innerClassesMemberBodyPhase = makeIrFilePhase(
{ context -> InnerClassesMemberBodyLowering(context, context.innerClassesSupport) },
name = "InnerClassesMemberBody",
description = "Replace `this` with 'outer this' field references",
prerequisite = setOf(innerClassesPhase)
)
private val innerClassConstructorCallsPhase = makeIrFilePhase(
{ context -> InnerClassConstructorCallsLowering(context, context.innerClassesSupport) },
name = "InnerClassConstructorCalls",
description = "Handle constructor calls for inner classes"
)
private val staticInitializersPhase = makeIrFilePhase(
::StaticInitializersLowering,
name = "StaticInitializers",
description = "Move code from object init blocks and static field initializers to a new function"
)
private val initializersPhase = makeIrFilePhase(
::InitializersLowering,
name = "Initializers",
description = "Merge init blocks and field initializers into constructors",
// Depends on local class extraction, because otherwise local classes in initializers will be copied into each constructor.
prerequisite = setOf(jvmLocalClassExtractionPhase)
)
private val initializersCleanupPhase = makeIrFilePhase(
{ context ->
InitializersCleanupLowering(context) {
it.constantValue(context) == null && (!it.isStatic || it.correspondingPropertySymbol?.owner?.isConst != true)
}
},
name = "InitializersCleanup",
description = "Remove non-static anonymous initializers and non-constant non-static field init expressions",
stickyPostconditions = setOf(fun(irFile: IrFile) {
irFile.acceptVoid(object : IrElementVisitorVoid {
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer) {
error("No anonymous initializers should remain at this stage")
}
})
}),
prerequisite = setOf(initializersPhase)
)
private val returnableBlocksPhase = makeIrFilePhase(
::ReturnableBlockLowering,
name = "ReturnableBlock",
description = "Replace returnable blocks with do-while(false) loops",
prerequisite = setOf(arrayConstructorPhase, assertionPhase)
)
private val syntheticAccessorPhase = makeIrFilePhase(
::SyntheticAccessorLowering,
name = "SyntheticAccessor",
description = "Introduce synthetic accessors",
prerequisite = setOf(objectClassPhase, staticDefaultFunctionPhase, interfacePhase)
)
private val tailrecPhase = makeIrFilePhase(
::JvmTailrecLowering,
name = "Tailrec",
description = "Handle tailrec calls"
)
private val kotlinNothingValueExceptionPhase = makeIrFilePhase(
{ context -> KotlinNothingValueExceptionLowering(context) { it is IrFunction && !it.shouldContainSuspendMarkers() } },
name = "KotlinNothingValueException",
description = "Throw proper exception for calls returning value of type 'kotlin.Nothing'"
)
private val jvmFilePhases = listOf(
typeAliasAnnotationMethodsPhase,
stripTypeAliasDeclarationsPhase,
provisionalFunctionExpressionPhase,
jvmOverloadsAnnotationPhase,
mainMethodGenerationPhase,
inventNamesForLocalClassesPhase,
kCallableNamePropertyPhase,
annotationPhase,
polymorphicSignaturePhase,
varargPhase,
arrayConstructorPhase,
checkNotNullPhase,
lateinitNullableFieldsPhase,
lateinitDeclarationLoweringPhase,
lateinitUsageLoweringPhase,
moveOrCopyCompanionObjectFieldsPhase,
inlineCallableReferenceToLambdaPhase,
propertyReferencePhase,
constPhase,
propertiesPhase,
remapObjectFieldAccesses,
anonymousObjectSuperConstructorPhase,
tailrecPhase,
jvmStandardLibraryBuiltInsPhase,
rangeContainsLoweringPhase,
forLoopsPhase,
jvmInlineClassPhase,
sharedVariablesPhase,
makePatchParentsPhase(1),
enumWhenPhase,
singletonReferencesPhase,
functionReferencePhase,
singleAbstractMethodPhase,
assertionPhase,
returnableBlocksPhase,
localDeclarationsPhase,
jvmLocalClassExtractionPhase,
staticCallableReferencePhase,
jvmDefaultConstructorPhase,
flattenStringConcatenationPhase,
foldConstantLoweringPhase,
computeStringTrimPhase,
jvmStringConcatenationLowering,
defaultArgumentStubPhase,
defaultArgumentInjectorPhase,
defaultArgumentCleanerPhase,
interfacePhase,
inheritedDefaultMethodsOnClassesPhase,
interfaceSuperCallsPhase,
interfaceDefaultCallsPhase,
interfaceObjectCallsPhase,
tailCallOptimizationPhase,
addContinuationPhase,
innerClassesPhase,
innerClassesMemberBodyPhase,
innerClassConstructorCallsPhase,
makePatchParentsPhase(2),
enumClassPhase,
objectClassPhase,
staticInitializersPhase,
initializersPhase,
initializersCleanupPhase,
collectionStubMethodLowering,
functionNVarargBridgePhase,
jvmStaticAnnotationPhase,
staticDefaultFunctionPhase,
bridgePhase,
syntheticAccessorPhase,
jvmArgumentNullabilityAssertions,
toArrayPhase,
jvmOptimizationLoweringPhase,
ifNullExpressionsFusionPhase,
additionalClassAnnotationPhase,
typeOperatorLowering,
replaceKFunctionInvokeWithFunctionInvokePhase,
kotlinNothingValueExceptionPhase,
checkLocalNamesWithOldBackendPhase,
renameFieldsPhase,
fakeInliningLocalVariablesLowering,
makePatchParentsPhase(3)
)
val jvmPhases = NamedCompilerPhase(
name = "IrLowering",
description = "IR lowering",
nlevels = 1,
actions = setOf(defaultDumper, validationAction),
lower = validateIrBeforeLowering then
processOptionalAnnotationsPhase then
expectDeclarationsRemovingPhase then
fileClassPhase then
performByIrFile(lower = jvmFilePhases) then
generateMultifileFacadesPhase then
resolveInlineCallsPhase then
// should be last transformation
removeDeclarationsThatWouldBeInlined then
validateIrAfterLowering
)
class JvmLower(val context: JvmBackendContext) {
fun lower(irModuleFragment: IrModuleFragment) {
// TODO run lowering passes as callbacks in bottom-up visitor
jvmPhases.invokeToplevel(context.phaseConfig, context, irModuleFragment)
}
}