Use symbols in IrGet/SetValue in EnumClassLowering

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