IR: extract JvmPropertiesLowering out of PropertiesLowering
This commit is contained in:
+8
-69
@@ -5,103 +5,42 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.common.lower
|
package org.jetbrains.kotlin.backend.common.lower
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.BackendContext
|
|
||||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||||
import org.jetbrains.kotlin.backend.common.ir.copyTo
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
|
||||||
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.UNDEFINED_OFFSET
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
|
||||||
import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor
|
|
||||||
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.symbols.impl.IrSimpleFunctionSymbolImpl
|
|
||||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
|
||||||
import org.jetbrains.kotlin.ir.types.typeWith
|
|
||||||
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
|
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
|
||||||
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.utils.addIfNotNull
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class PropertiesLowering(
|
class PropertiesLowering : IrElementTransformerVoid(), FileLoweringPass {
|
||||||
private val context: BackendContext,
|
|
||||||
private val originOfSyntheticMethodForAnnotations: IrDeclarationOrigin? = null,
|
|
||||||
private val skipExternalProperties: Boolean = false,
|
|
||||||
private val generateAnnotationFields: Boolean = false,
|
|
||||||
private val computeSyntheticMethodName: ((IrProperty) -> String)? = null
|
|
||||||
) : IrElementTransformerVoid(), FileLoweringPass {
|
|
||||||
override fun lower(irFile: IrFile) {
|
override fun lower(irFile: IrFile) {
|
||||||
irFile.accept(this, null)
|
irFile.accept(this, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitFile(declaration: IrFile): IrFile {
|
override fun visitFile(declaration: IrFile): IrFile {
|
||||||
declaration.transformChildrenVoid(this)
|
declaration.transformChildrenVoid(this)
|
||||||
declaration.transformDeclarationsFlat { lowerProperty(it, ClassKind.CLASS) }
|
declaration.transformDeclarationsFlat { lowerProperty(it) }
|
||||||
return declaration
|
return declaration
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitClass(declaration: IrClass): IrStatement {
|
override fun visitClass(declaration: IrClass): IrStatement {
|
||||||
declaration.transformChildrenVoid(this)
|
declaration.transformChildrenVoid(this)
|
||||||
declaration.transformDeclarationsFlat { lowerProperty(it, declaration.kind) }
|
declaration.transformDeclarationsFlat { lowerProperty(it) }
|
||||||
return declaration
|
return declaration
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitScript(declaration: IrScript): IrStatement {
|
override fun visitScript(declaration: IrScript): IrStatement {
|
||||||
declaration.transformChildrenVoid(this)
|
declaration.transformChildrenVoid(this)
|
||||||
declaration.transformDeclarationsFlat { lowerProperty(it, ClassKind.CLASS) }
|
declaration.transformDeclarationsFlat { lowerProperty(it) }
|
||||||
return declaration
|
return declaration
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun lowerProperty(declaration: IrDeclaration, kind: ClassKind): List<IrDeclaration>? =
|
private fun lowerProperty(declaration: IrDeclaration): List<IrDeclaration>? =
|
||||||
if (declaration is IrProperty)
|
if (declaration is IrProperty && !declaration.isEffectivelyExternal())
|
||||||
if (skipExternalProperties && declaration.isEffectivelyExternal()) listOf(declaration) else {
|
listOfNotNull(declaration.backingField, declaration.getter, declaration.setter)
|
||||||
ArrayList<IrDeclaration>(4).apply {
|
else null
|
||||||
// JvmFields in a companion object refer to companion's owners and should not be generated within companion.
|
|
||||||
if (generateAnnotationFields || (kind != ClassKind.ANNOTATION_CLASS && declaration.backingField?.parent == declaration.parent)) {
|
|
||||||
addIfNotNull(declaration.backingField)
|
|
||||||
}
|
|
||||||
addIfNotNull(declaration.getter)
|
|
||||||
addIfNotNull(declaration.setter)
|
|
||||||
|
|
||||||
if (declaration.annotations.isNotEmpty() && originOfSyntheticMethodForAnnotations != null
|
|
||||||
&& computeSyntheticMethodName != null
|
|
||||||
) {
|
|
||||||
val methodName = computeSyntheticMethodName.invoke(declaration) // Workaround KT-4113
|
|
||||||
add(createSyntheticMethodForAnnotations(declaration, originOfSyntheticMethodForAnnotations, methodName))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
null
|
|
||||||
|
|
||||||
private fun createSyntheticMethodForAnnotations(declaration: IrProperty, origin: IrDeclarationOrigin, name: String): IrFunctionImpl {
|
|
||||||
val descriptor = WrappedSimpleFunctionDescriptor(declaration.descriptor.annotations)
|
|
||||||
val symbol = IrSimpleFunctionSymbolImpl(descriptor)
|
|
||||||
return IrFunctionImpl(
|
|
||||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, symbol, Name.identifier(name),
|
|
||||||
declaration.visibility, Modality.OPEN, context.irBuiltIns.unitType,
|
|
||||||
isInline = false, isExternal = false, isTailrec = false, isSuspend = false, isExpect = false, isFakeOverride = false,
|
|
||||||
isOperator = false
|
|
||||||
).apply {
|
|
||||||
descriptor.bind(this)
|
|
||||||
|
|
||||||
val extensionReceiver = declaration.getter?.extensionReceiverParameter
|
|
||||||
if (extensionReceiver != null) {
|
|
||||||
// Use raw type of extension receiver to avoid generic signature, which would be useless for this method.
|
|
||||||
extensionReceiverParameter = extensionReceiver.copyTo(this, type = extensionReceiver.type.classifierOrFail.typeWith())
|
|
||||||
}
|
|
||||||
|
|
||||||
body = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET)
|
|
||||||
|
|
||||||
annotations.addAll(declaration.annotations)
|
|
||||||
metadata = declaration.metadata
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun checkNoProperties(irFile: IrFile) {
|
fun checkNoProperties(irFile: IrFile) {
|
||||||
|
|||||||
@@ -268,7 +268,7 @@ private val varargLoweringPhase = makeJsModulePhase(
|
|||||||
)
|
)
|
||||||
|
|
||||||
private val propertiesLoweringPhase = makeJsModulePhase(
|
private val propertiesLoweringPhase = makeJsModulePhase(
|
||||||
{ context -> PropertiesLowering(context, skipExternalProperties = true, generateAnnotationFields = true) },
|
{ PropertiesLowering() },
|
||||||
name = "PropertiesLowering",
|
name = "PropertiesLowering",
|
||||||
description = "Move fields and accessors out from its property"
|
description = "Move fields and accessors out from its property"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.backend.common.lower.loops.forLoopsPhase
|
|||||||
import org.jetbrains.kotlin.backend.common.lower.optimizations.foldConstantLoweringPhase
|
import org.jetbrains.kotlin.backend.common.lower.optimizations.foldConstantLoweringPhase
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.*
|
import org.jetbrains.kotlin.backend.common.phaser.*
|
||||||
import org.jetbrains.kotlin.backend.jvm.lower.*
|
import org.jetbrains.kotlin.backend.jvm.lower.*
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.descriptors.Visibility
|
import org.jetbrains.kotlin.descriptors.Visibility
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
@@ -24,7 +23,6 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
|||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||||
import org.jetbrains.kotlin.load.java.JavaVisibilities
|
import org.jetbrains.kotlin.load.java.JavaVisibilities
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
|
||||||
import org.jetbrains.kotlin.name.NameUtils
|
import org.jetbrains.kotlin.name.NameUtils
|
||||||
|
|
||||||
private fun makePatchParentsPhase(number: Int) = namedIrFilePhase(
|
private fun makePatchParentsPhase(number: Int) = namedIrFilePhase(
|
||||||
@@ -87,22 +85,10 @@ private val lateinitPhase = makeIrFilePhase(
|
|||||||
description = "Insert checks for lateinit field references"
|
description = "Insert checks for lateinit field references"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val propertiesPhase = makeIrFilePhase<JvmBackendContext>(
|
private val propertiesPhase = makeIrFilePhase(
|
||||||
{ context ->
|
::JvmPropertiesLowering,
|
||||||
PropertiesLowering(context, JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS) { property ->
|
|
||||||
val baseName =
|
|
||||||
if (context.state.languageVersionSettings.supportsFeature(LanguageFeature.UseGetterNameForPropertyAnnotationsMethodOnJvm)) {
|
|
||||||
property.getter?.let { getter ->
|
|
||||||
context.methodSignatureMapper.mapFunctionName(getter)
|
|
||||||
} ?: JvmAbi.getterName(property.name.asString())
|
|
||||||
} else {
|
|
||||||
property.name.asString()
|
|
||||||
}
|
|
||||||
JvmAbi.getSyntheticMethodNameForAnnotatedProperty(baseName)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
name = "Properties",
|
name = "Properties",
|
||||||
description = "Move fields and accessors for properties to their classes",
|
description = "Move fields and accessors for properties to their classes, and create synthetic methods for property annotations",
|
||||||
stickyPostconditions = setOf((PropertiesLowering)::checkNoProperties)
|
stickyPostconditions = setOf((PropertiesLowering)::checkNoProperties)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+100
@@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* 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.lower
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||||
|
import org.jetbrains.kotlin.backend.common.ir.copyTo
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||||
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||||
|
import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||||
|
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||||
|
import org.jetbrains.kotlin.ir.types.typeWith
|
||||||
|
import org.jetbrains.kotlin.ir.util.transformDeclarationsFlat
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class JvmPropertiesLowering(private val context: JvmBackendContext) : IrElementTransformerVoid(), FileLoweringPass {
|
||||||
|
override fun lower(irFile: IrFile) {
|
||||||
|
irFile.accept(this, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitClass(declaration: IrClass): IrStatement {
|
||||||
|
declaration.transformChildrenVoid(this)
|
||||||
|
declaration.transformDeclarationsFlat { lowerProperty(it, declaration.kind) }
|
||||||
|
return declaration
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun lowerProperty(declaration: IrDeclaration, kind: ClassKind): List<IrDeclaration>? =
|
||||||
|
if (declaration is IrProperty)
|
||||||
|
ArrayList<IrDeclaration>(4).apply {
|
||||||
|
// JvmFields in a companion object refer to companion's owners and should not be generated within companion.
|
||||||
|
if (kind != ClassKind.ANNOTATION_CLASS && declaration.backingField?.parent == declaration.parent) {
|
||||||
|
addIfNotNull(declaration.backingField)
|
||||||
|
}
|
||||||
|
addIfNotNull(declaration.getter)
|
||||||
|
addIfNotNull(declaration.setter)
|
||||||
|
|
||||||
|
if (declaration.annotations.isNotEmpty()) {
|
||||||
|
add(createSyntheticMethodForAnnotations(declaration))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
null
|
||||||
|
|
||||||
|
private fun createSyntheticMethodForAnnotations(declaration: IrProperty): IrFunctionImpl {
|
||||||
|
val descriptor = WrappedSimpleFunctionDescriptor(declaration.descriptor.annotations)
|
||||||
|
val symbol = IrSimpleFunctionSymbolImpl(descriptor)
|
||||||
|
val name = computeSyntheticMethodName(declaration)
|
||||||
|
return IrFunctionImpl(
|
||||||
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET, JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS, symbol,
|
||||||
|
Name.identifier(name), declaration.visibility, Modality.OPEN, context.irBuiltIns.unitType,
|
||||||
|
isInline = false, isExternal = false, isTailrec = false, isSuspend = false, isExpect = false, isFakeOverride = false,
|
||||||
|
isOperator = false
|
||||||
|
).apply {
|
||||||
|
descriptor.bind(this)
|
||||||
|
|
||||||
|
val extensionReceiver = declaration.getter?.extensionReceiverParameter
|
||||||
|
if (extensionReceiver != null) {
|
||||||
|
// Use raw type of extension receiver to avoid generic signature, which would be useless for this method.
|
||||||
|
extensionReceiverParameter = extensionReceiver.copyTo(this, type = extensionReceiver.type.classifierOrFail.typeWith())
|
||||||
|
}
|
||||||
|
|
||||||
|
body = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET)
|
||||||
|
parent = declaration.parent
|
||||||
|
|
||||||
|
annotations.addAll(declaration.annotations)
|
||||||
|
metadata = declaration.metadata
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun computeSyntheticMethodName(property: IrProperty): String {
|
||||||
|
val baseName =
|
||||||
|
if (context.state.languageVersionSettings.supportsFeature(LanguageFeature.UseGetterNameForPropertyAnnotationsMethodOnJvm)) {
|
||||||
|
property.getter?.let { getter ->
|
||||||
|
context.methodSignatureMapper.mapFunctionName(getter)
|
||||||
|
} ?: JvmAbi.getterName(property.name.asString())
|
||||||
|
} else {
|
||||||
|
property.name.asString()
|
||||||
|
}
|
||||||
|
return JvmAbi.getSyntheticMethodNameForAnnotatedProperty(baseName)
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -190,7 +190,7 @@ private val defaultParameterCleanerPhase = makeWasmModulePhase(
|
|||||||
//)
|
//)
|
||||||
|
|
||||||
private val propertiesLoweringPhase = makeWasmModulePhase(
|
private val propertiesLoweringPhase = makeWasmModulePhase(
|
||||||
{ context -> PropertiesLowering(context, skipExternalProperties = true, generateAnnotationFields = true) },
|
{ PropertiesLowering() },
|
||||||
name = "PropertiesLowering",
|
name = "PropertiesLowering",
|
||||||
description = "Move fields and accessors out from its property"
|
description = "Move fields and accessors out from its property"
|
||||||
)
|
)
|
||||||
@@ -399,4 +399,4 @@ val wasmPhases = namedIrModulePhase<WasmBackendContext>(
|
|||||||
staticMembersLoweringPhase then
|
staticMembersLoweringPhase then
|
||||||
|
|
||||||
validateIrAfterLowering
|
validateIrAfterLowering
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user