Use symbols in IrGet/SetValue in EnumClassLowering
This commit is contained in:
+77
-55
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
|
||||
import org.jetbrains.kotlin.ir.util.dump
|
||||
import org.jetbrains.kotlin.ir.util.transform
|
||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||
@@ -78,14 +79,14 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
||||
|
||||
private inner class EnumClassTransformer(val irClass: IrClass) {
|
||||
private val enumEntryOrdinals = TObjectIntHashMap<ClassDescriptor>()
|
||||
private val loweredEnumConstructors = HashMap<ClassConstructorDescriptor, ClassConstructorDescriptor>()
|
||||
private val loweredEnumConstructorParameters = HashMap<ValueParameterDescriptor, ValueParameterDescriptor>()
|
||||
private val loweredEnumConstructors = HashMap<ClassConstructorDescriptor, IrConstructorImpl>()
|
||||
private val loweredEnumConstructorParameters = HashMap<ValueParameterDescriptor, IrValueParameter>()
|
||||
private val enumEntriesByField = HashMap<PropertyDescriptor, ClassDescriptor>()
|
||||
private val enumEntryFields = ArrayList<PropertyDescriptor>()
|
||||
private val enumEntryFields = ArrayList<IrField>()
|
||||
|
||||
private lateinit var valuesFieldDescriptor: PropertyDescriptor
|
||||
private lateinit var valuesFunctionDescriptor: FunctionDescriptor
|
||||
private lateinit var valueOfFunctionDescriptor: FunctionDescriptor
|
||||
private lateinit var valuesField: IrField
|
||||
private lateinit var valuesFunction: IrFunction
|
||||
private lateinit var valueOfFunction: IrFunction
|
||||
|
||||
fun run() {
|
||||
assignOrdinalsToEnumEntries()
|
||||
@@ -121,7 +122,13 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
||||
enumConstructor.startOffset, enumConstructor.endOffset, enumConstructor.origin,
|
||||
loweredConstructorDescriptor,
|
||||
enumConstructor.body!! // will be transformed later
|
||||
)
|
||||
).apply {
|
||||
createParameterDeclarations()
|
||||
loweredEnumConstructors[constructorDescriptor] = this
|
||||
constructorDescriptor.valueParameters.forEach {
|
||||
loweredEnumConstructorParameters[it] = valueParameters[2 + it.index]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun lowerEnumConstructor(constructorDescriptor: ClassConstructorDescriptor): ClassConstructorDescriptor {
|
||||
@@ -144,8 +151,6 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
||||
|
||||
loweredConstructorDescriptor.returnType = constructorDescriptor.returnType
|
||||
|
||||
loweredEnumConstructors[constructorDescriptor] = loweredConstructorDescriptor
|
||||
|
||||
return loweredConstructorDescriptor
|
||||
}
|
||||
|
||||
@@ -153,13 +158,11 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
||||
loweredConstructorDescriptor: ClassConstructorDescriptor,
|
||||
valueParameterDescriptor: ValueParameterDescriptor
|
||||
): ValueParameterDescriptor {
|
||||
val loweredValueParameterDescriptor = valueParameterDescriptor.copy(
|
||||
return valueParameterDescriptor.copy(
|
||||
loweredConstructorDescriptor,
|
||||
valueParameterDescriptor.name,
|
||||
valueParameterDescriptor.index + 2
|
||||
)
|
||||
loweredEnumConstructorParameters[valueParameterDescriptor] = loweredValueParameterDescriptor
|
||||
return loweredValueParameterDescriptor
|
||||
}
|
||||
|
||||
private fun lowerEnumEntries() {
|
||||
@@ -185,14 +188,14 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
||||
val fieldPropertyDescriptor = context.descriptorsFactory.getFieldDescriptorForEnumEntry(enumEntry.descriptor)
|
||||
|
||||
enumEntriesByField[fieldPropertyDescriptor] = enumEntry.descriptor
|
||||
enumEntryFields.add(fieldPropertyDescriptor)
|
||||
|
||||
val enumEntryInitializer = enumEntry.initializerExpression!!
|
||||
return IrFieldImpl(
|
||||
enumEntry.startOffset, enumEntry.endOffset, JvmLoweredDeclarationOrigin.FIELD_FOR_ENUM_ENTRY,
|
||||
fieldPropertyDescriptor,
|
||||
IrExpressionBodyImpl(enumEntryInitializer)
|
||||
)
|
||||
IrExpressionBodyImpl(enumEntry.initializerExpression!!)
|
||||
).also {
|
||||
enumEntryFields.add(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupSynthesizedEnumClassMembers() {
|
||||
@@ -200,39 +203,36 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
||||
|
||||
irClass.declarations.add(irField)
|
||||
|
||||
valuesFunctionDescriptor = findFunctionDescriptorForMemberWithSyntheticBodyKind(IrSyntheticBodyKind.ENUM_VALUES)
|
||||
valueOfFunctionDescriptor = findFunctionDescriptorForMemberWithSyntheticBodyKind(IrSyntheticBodyKind.ENUM_VALUEOF)
|
||||
valuesFunction = findFunctionDescriptorForMemberWithSyntheticBodyKind(IrSyntheticBodyKind.ENUM_VALUES)
|
||||
valueOfFunction = findFunctionDescriptorForMemberWithSyntheticBodyKind(IrSyntheticBodyKind.ENUM_VALUEOF)
|
||||
}
|
||||
|
||||
private fun findFunctionDescriptorForMemberWithSyntheticBodyKind(kind: IrSyntheticBodyKind): FunctionDescriptor =
|
||||
irClass.declarations
|
||||
private fun findFunctionDescriptorForMemberWithSyntheticBodyKind(kind: IrSyntheticBodyKind): IrFunction =
|
||||
irClass.declarations.asSequence().filterIsInstance<IrFunction>()
|
||||
.first {
|
||||
it is IrFunction &&
|
||||
it.body.let { body ->
|
||||
body is IrSyntheticBody && body.kind == kind
|
||||
}
|
||||
it.body.let { body ->
|
||||
body is IrSyntheticBody && body.kind == kind
|
||||
}
|
||||
}
|
||||
.descriptor as FunctionDescriptor
|
||||
|
||||
|
||||
private fun createSyntheticValuesFieldDeclaration(): IrFieldImpl {
|
||||
val valuesArrayType = context.builtIns.getArrayType(Variance.INVARIANT, irClass.descriptor.defaultType)
|
||||
valuesFieldDescriptor = createSyntheticValuesFieldDescriptor(valuesArrayType)
|
||||
|
||||
val irValuesInitializer = createSyntheticValuesFieldInitializerExpression()
|
||||
|
||||
return IrFieldImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, JvmLoweredDeclarationOrigin.FIELD_FOR_ENUM_VALUES,
|
||||
valuesFieldDescriptor,
|
||||
createSyntheticValuesFieldDescriptor(valuesArrayType),
|
||||
IrExpressionBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irValuesInitializer)
|
||||
)
|
||||
).also { valuesField = it }
|
||||
}
|
||||
|
||||
private fun createSyntheticValuesFieldInitializerExpression(): IrExpression =
|
||||
createArrayOfExpression(
|
||||
irClass.descriptor.defaultType,
|
||||
enumEntryFields.map { fieldDescriptor ->
|
||||
IrGetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, fieldDescriptor)
|
||||
enumEntryFields.map { irField ->
|
||||
IrGetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irField.symbol)
|
||||
})
|
||||
|
||||
private fun createSyntheticValuesFieldDescriptor(valuesArrayType: SimpleType): PropertyDescriptorImpl {
|
||||
@@ -250,29 +250,35 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
||||
irClass.transformChildrenVoid(EnumClassBodyTransformer())
|
||||
}
|
||||
|
||||
private inner class InEnumClassConstructor(val enumClassConstructor: ClassConstructorDescriptor) :
|
||||
private inner class InEnumClassConstructor(val irEnumConstructor: IrConstructor) :
|
||||
EnumConstructorCallTransformer {
|
||||
override fun transform(enumConstructorCall: IrEnumConstructorCall): IrExpression {
|
||||
val startOffset = enumConstructorCall.startOffset
|
||||
val endOffset = enumConstructorCall.endOffset
|
||||
val origin = enumConstructorCall.origin
|
||||
|
||||
val result = IrDelegatingConstructorCallImpl(startOffset, endOffset, enumConstructorCall.descriptor)
|
||||
val result = IrDelegatingConstructorCallImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
enumConstructorCall.symbol,
|
||||
enumConstructorCall.descriptor,
|
||||
enumConstructorCall.typeArgumentsCount
|
||||
)
|
||||
|
||||
assert(result.descriptor.valueParameters.size == 2) {
|
||||
"Enum(String, Int) constructor call expected:\n${result.dump()}"
|
||||
}
|
||||
|
||||
val nameParameter = enumClassConstructor.valueParameters.getOrElse(0) {
|
||||
throw AssertionError("No 'name' parameter in enum constructor: $enumClassConstructor")
|
||||
val nameParameter = irEnumConstructor.valueParameters.getOrElse(0) {
|
||||
throw AssertionError("No 'name' parameter in enum constructor: ${irEnumConstructor.dump()}")
|
||||
}
|
||||
|
||||
val ordinalParameter = enumClassConstructor.valueParameters.getOrElse(1) {
|
||||
throw AssertionError("No 'ordinal' parameter in enum constructor: $enumClassConstructor")
|
||||
val ordinalParameter = irEnumConstructor.valueParameters.getOrElse(1) {
|
||||
throw AssertionError("No 'ordinal' parameter in enum constructor: ${irEnumConstructor.dump()}")
|
||||
}
|
||||
|
||||
result.putValueArgument(0, IrGetValueImpl(startOffset, endOffset, nameParameter, origin))
|
||||
result.putValueArgument(1, IrGetValueImpl(startOffset, endOffset, ordinalParameter, origin))
|
||||
result.putValueArgument(0, IrGetValueImpl(startOffset, endOffset, nameParameter.symbol, origin))
|
||||
result.putValueArgument(1, IrGetValueImpl(startOffset, endOffset, ordinalParameter.symbol, origin))
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -286,10 +292,16 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
||||
throw AssertionError("Constructor called in enum entry initializer should've been lowered: $descriptor")
|
||||
}
|
||||
|
||||
val result = IrDelegatingConstructorCallImpl(startOffset, endOffset, loweredDelegatedConstructor)
|
||||
val result = IrDelegatingConstructorCallImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
loweredDelegatedConstructor.symbol,
|
||||
loweredDelegatedConstructor.descriptor,
|
||||
loweredDelegatedConstructor.typeParameters.size
|
||||
)
|
||||
|
||||
result.putValueArgument(0, IrGetValueImpl(startOffset, endOffset, enumClassConstructor.valueParameters[0]))
|
||||
result.putValueArgument(1, IrGetValueImpl(startOffset, endOffset, enumClassConstructor.valueParameters[1]))
|
||||
result.putValueArgument(0, IrGetValueImpl(startOffset, endOffset, irEnumConstructor.valueParameters[0].symbol))
|
||||
result.putValueArgument(1, IrGetValueImpl(startOffset, endOffset, irEnumConstructor.valueParameters[1].symbol))
|
||||
|
||||
descriptor.valueParameters.forEach { valueParameter ->
|
||||
val i = valueParameter.index
|
||||
@@ -333,18 +345,28 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
||||
abstract fun createConstructorCall(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
loweredConstructor: ClassConstructorDescriptor
|
||||
loweredConstructor: IrConstructor
|
||||
): IrMemberAccessExpression
|
||||
}
|
||||
|
||||
private inner class InEnumEntryClassConstructor(enumEntry: ClassDescriptor) : InEnumEntry(enumEntry) {
|
||||
override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: ClassConstructorDescriptor) =
|
||||
IrDelegatingConstructorCallImpl(startOffset, endOffset, loweredConstructor)
|
||||
override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructor) =
|
||||
IrDelegatingConstructorCallImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
loweredConstructor.symbol,
|
||||
loweredConstructor.descriptor,
|
||||
loweredConstructor.typeParameters.size
|
||||
)
|
||||
}
|
||||
|
||||
private inner class InEnumEntryInitializer(enumEntry: ClassDescriptor) : InEnumEntry(enumEntry) {
|
||||
override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: ClassConstructorDescriptor) =
|
||||
IrCallImpl(startOffset, endOffset, loweredConstructor)
|
||||
override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructor) =
|
||||
IrCallImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
loweredConstructor.symbol
|
||||
)
|
||||
}
|
||||
|
||||
private inner class EnumClassBodyTransformer : IrElementTransformerVoid() {
|
||||
@@ -380,7 +402,7 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
||||
enumConstructorCallTransformer = InEnumEntryClassConstructor(containingClass)
|
||||
} else if (containingClass.kind == ClassKind.ENUM_CLASS) {
|
||||
assert(enumConstructorCallTransformer == null) { "Nested enum entry initialization:\n${declaration.dump()}" }
|
||||
enumConstructorCallTransformer = InEnumClassConstructor(constructorDescriptor)
|
||||
enumConstructorCallTransformer = InEnumClassConstructor(declaration)
|
||||
}
|
||||
|
||||
val result = super.visitConstructor(declaration)
|
||||
@@ -419,7 +441,7 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||
val loweredParameter = loweredEnumConstructorParameters[expression.descriptor]
|
||||
return if (loweredParameter != null) {
|
||||
IrGetValueImpl(expression.startOffset, expression.endOffset, loweredParameter, expression.origin)
|
||||
IrGetValueImpl(expression.startOffset, expression.endOffset, loweredParameter.symbol, expression.origin)
|
||||
} else {
|
||||
expression
|
||||
}
|
||||
@@ -428,7 +450,7 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
||||
override fun visitSyntheticBody(body: IrSyntheticBody): IrBody {
|
||||
return when (body.kind) {
|
||||
IrSyntheticBodyKind.ENUM_VALUES ->
|
||||
createEnumValuesBody(valuesFieldDescriptor)
|
||||
createEnumValuesBody(valuesField)
|
||||
IrSyntheticBodyKind.ENUM_VALUEOF ->
|
||||
createEnumValueOfBody()
|
||||
else ->
|
||||
@@ -446,25 +468,25 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
||||
val irValueOfCall =
|
||||
IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, substitutedValueOf, mapOf(typeParameterT to enumClassType))
|
||||
irValueOfCall.putValueArgument(
|
||||
0, IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, valueOfFunctionDescriptor.valueParameters[0])
|
||||
0, IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, valueOfFunction.valueParameters[0].symbol)
|
||||
)
|
||||
|
||||
return IrBlockBodyImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
listOf(IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, valueOfFunctionDescriptor, irValueOfCall))
|
||||
listOf(IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, valueOfFunction.symbol, irValueOfCall))
|
||||
)
|
||||
}
|
||||
|
||||
private fun createEnumValuesBody(valuesFieldDescriptor: PropertyDescriptor): IrBody {
|
||||
val cloneFun = valuesFieldDescriptor.type.memberScope.findSingleFunction(Name.identifier("clone"))
|
||||
private fun createEnumValuesBody(valuesField: IrField): IrBody {
|
||||
val cloneFun = valuesField.type.memberScope.findSingleFunction(Name.identifier("clone"))
|
||||
|
||||
val irCloneValues = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, cloneFun).apply {
|
||||
dispatchReceiver = IrGetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, valuesFieldDescriptor)
|
||||
dispatchReceiver = IrGetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, valuesField.symbol)
|
||||
}
|
||||
|
||||
return IrBlockBodyImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
listOf(IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, valuesFunctionDescriptor, irCloneValues))
|
||||
listOf(IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, valuesFunction.symbol, irCloneValues))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user