From bb6c837f6bdf2d3cee830697ba37869145b8b3c1 Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Fri, 27 Apr 2018 11:25:05 +0200 Subject: [PATCH] Use symbols in IrGet/SetValue in EnumClassLowering --- .../backend/jvm/lower/EnumClassLowering.kt | 132 ++++++++++-------- 1 file changed, 77 insertions(+), 55 deletions(-) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/EnumClassLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/EnumClassLowering.kt index 5bba012af49..b5e4d0c1142 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/EnumClassLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/EnumClassLowering.kt @@ -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() - private val loweredEnumConstructors = HashMap() - private val loweredEnumConstructorParameters = HashMap() + private val loweredEnumConstructors = HashMap() + private val loweredEnumConstructorParameters = HashMap() private val enumEntriesByField = HashMap() - private val enumEntryFields = ArrayList() + private val enumEntryFields = ArrayList() - 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() .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)) ) } }