Refactor AnnotationImplementationLowering
- Replaced UNDEFINED_OFFSET with SYNTHETIC_OFFSET, it's required by Native backend codegen - Fixed missing overridden symbols - Enforce adding fakeoverrides for members not overridden by backend - Support more points for platform customisation
This commit is contained in:
+114
-23
@@ -5,23 +5,28 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.lower.ANNOTATION_IMPLEMENTATION
|
||||
import org.jetbrains.kotlin.backend.common.lower.AnnotationImplementationLowering
|
||||
import org.jetbrains.kotlin.backend.common.lower.AnnotationImplementationTransformer
|
||||
import org.jetbrains.kotlin.backend.common.deepCopyWithVariables
|
||||
import org.jetbrains.kotlin.backend.common.ir.copyTo
|
||||
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.ir.createJvmIrBuilder
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.isInPublicInlineScope
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.javaClassReference
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.addFunction
|
||||
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.IrFunction
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrGetValue
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
@@ -48,7 +53,7 @@ class JvmAnnotationImplementationTransformer(val jvmContext: JvmBackendContext,
|
||||
return super.visitConstructorCall(expression)
|
||||
}
|
||||
|
||||
override fun IrType.kClassToJClassIfNeeded(): IrType = when {
|
||||
private fun IrType.kClassToJClassIfNeeded(): IrType = when {
|
||||
this.isKClass() -> jvmContext.ir.symbols.javaLangClass.starProjectedType
|
||||
this.isKClassArray() -> jvmContext.irBuiltIns.arrayClass.typeWith(
|
||||
jvmContext.ir.symbols.javaLangClass.starProjectedType
|
||||
@@ -71,20 +76,13 @@ class JvmAnnotationImplementationTransformer(val jvmContext: JvmBackendContext,
|
||||
}
|
||||
}
|
||||
|
||||
override fun generatedEquals(irBuilder: IrBlockBodyBuilder, type: IrType, arg1: IrExpression, arg2: IrExpression): IrExpression {
|
||||
return if (type.isArray() || type.isPrimitiveArray()) {
|
||||
val targetType = if (type.isPrimitiveArray()) type else jvmContext.ir.symbols.arrayOfAnyNType
|
||||
val requiredSymbol = jvmContext.ir.symbols.arraysClass.owner.findDeclaration<IrFunction> {
|
||||
it.name.asString() == "equals" && it.valueParameters.size == 2 && it.valueParameters.first().type == targetType
|
||||
}
|
||||
requireNotNull(requiredSymbol) { "Can't find Arrays.equals method for type ${targetType.render()}" }
|
||||
irBuilder.irCall(
|
||||
requiredSymbol.symbol
|
||||
).apply {
|
||||
putValueArgument(0, arg1)
|
||||
putValueArgument(1, arg2)
|
||||
}
|
||||
} else super.generatedEquals(irBuilder, type, arg1, arg2)
|
||||
override fun getArrayContentEqualsSymbol(type: IrType): IrFunctionSymbol {
|
||||
val targetType = if (type.isPrimitiveArray()) type else jvmContext.ir.symbols.arrayOfAnyNType
|
||||
val requiredSymbol = jvmContext.ir.symbols.arraysClass.owner.findDeclaration<IrFunction> {
|
||||
it.name.asString() == "equals" && it.valueParameters.size == 2 && it.valueParameters.first().type == targetType
|
||||
}
|
||||
requireNotNull(requiredSymbol) { "Can't find Arrays.equals method for type ${targetType.render()}" }
|
||||
return requiredSymbol.symbol
|
||||
}
|
||||
|
||||
override fun implementPlatformSpecificParts(annotationClass: IrClass, implClass: IrClass) {
|
||||
@@ -107,4 +105,97 @@ class JvmAnnotationImplementationTransformer(val jvmContext: JvmBackendContext,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun implementAnnotationPropertiesAndConstructor(
|
||||
implClass: IrClass,
|
||||
annotationClass: IrClass,
|
||||
generatedConstructor: IrConstructor
|
||||
) {
|
||||
val ctorBody = context.irFactory.createBlockBody(
|
||||
SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, listOf(
|
||||
IrDelegatingConstructorCallImpl(
|
||||
SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, context.irBuiltIns.unitType, context.irBuiltIns.anyClass.constructors.single(),
|
||||
typeArgumentsCount = 0, valueArgumentsCount = 0
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
generatedConstructor.body = ctorBody
|
||||
|
||||
annotationClass.getAnnotationProperties().forEach { property ->
|
||||
val propType = property.getter!!.returnType
|
||||
val propName = property.name
|
||||
val field = context.irFactory.buildField {
|
||||
startOffset = SYNTHETIC_OFFSET
|
||||
endOffset = SYNTHETIC_OFFSET
|
||||
name = propName
|
||||
type = propType
|
||||
origin = ANNOTATION_IMPLEMENTATION
|
||||
isFinal = true
|
||||
visibility = DescriptorVisibilities.PRIVATE
|
||||
}.also { it.parent = implClass }
|
||||
|
||||
val parameter = generatedConstructor.addValueParameter(propName.asString(), propType)
|
||||
// VALUE_FROM_PARAMETER
|
||||
val originalParameter = ((property.backingField?.initializer?.expression as? IrGetValue)?.symbol?.owner as? IrValueParameter)
|
||||
if (originalParameter?.defaultValue != null) {
|
||||
parameter.defaultValue = originalParameter.defaultValue!!.deepCopyWithVariables().also { it.transformChildrenVoid() }
|
||||
}
|
||||
|
||||
ctorBody.statements += IrSetFieldImpl(
|
||||
SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, field.symbol,
|
||||
IrGetValueImpl(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, implClass.thisReceiver!!.symbol),
|
||||
IrGetValueImpl(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, parameter.symbol),
|
||||
context.irBuiltIns.unitType,
|
||||
)
|
||||
|
||||
val prop = implClass.addProperty {
|
||||
startOffset = SYNTHETIC_OFFSET
|
||||
endOffset = SYNTHETIC_OFFSET
|
||||
name = propName
|
||||
isVar = false
|
||||
origin = ANNOTATION_IMPLEMENTATION
|
||||
}.apply {
|
||||
field.correspondingPropertySymbol = this.symbol
|
||||
backingField = field
|
||||
parent = implClass
|
||||
overriddenSymbols = listOf(property.symbol)
|
||||
}
|
||||
|
||||
prop.addGetter {
|
||||
startOffset = SYNTHETIC_OFFSET
|
||||
endOffset = SYNTHETIC_OFFSET
|
||||
name = propName // Annotation value getter should be named 'x', not 'getX'
|
||||
returnType = propType.kClassToJClassIfNeeded() // On JVM, annotation store j.l.Class even if declared with KClass
|
||||
origin = ANNOTATION_IMPLEMENTATION
|
||||
visibility = DescriptorVisibilities.PUBLIC
|
||||
modality = Modality.FINAL
|
||||
}.apply {
|
||||
correspondingPropertySymbol = prop.symbol
|
||||
dispatchReceiverParameter = implClass.thisReceiver!!.copyTo(this)
|
||||
body = context.createIrBuilder(symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody {
|
||||
var value: IrExpression = irGetField(irGet(dispatchReceiverParameter!!), field)
|
||||
if (propType.isKClass()) value = this.kClassExprToJClassIfNeeded(value)
|
||||
+irReturn(value)
|
||||
}
|
||||
overriddenSymbols = listOf(property.getter!!.symbol)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun generateFunctionBodies(
|
||||
annotationClass: IrClass,
|
||||
implClass: IrClass,
|
||||
eqFun: IrSimpleFunction,
|
||||
hcFun: IrSimpleFunction,
|
||||
toStringFun: IrSimpleFunction,
|
||||
generator: AnnotationImplementationMemberGenerator
|
||||
) {
|
||||
val properties = annotationClass.getAnnotationProperties()
|
||||
val implProperties = implClass.getAnnotationProperties()
|
||||
generator.generateEqualsUsingGetters(eqFun, annotationClass.defaultType, properties)
|
||||
generator.generateHashCodeMethod(hcFun, implProperties)
|
||||
generator.generateToStringMethod(toStringFun, implProperties)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user