From 420b9fdaa9a22e4b3f04a5da312258bc0358096f Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Fri, 24 Nov 2017 11:30:08 +0100 Subject: [PATCH] Support interface companion object lowering --- .../backend/jvm/lower/ObjectClassLowering.kt | 53 ++++++++++++++----- 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/ObjectClassLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/ObjectClassLowering.kt index e94105f52c3..f4f76e0a53c 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/ObjectClassLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/ObjectClassLowering.kt @@ -20,15 +20,19 @@ import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin -import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.* 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.IrDeclarationContainer +import org.jetbrains.kotlin.ir.declarations.IrField import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl +import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl +import org.jetbrains.kotlin.load.java.JvmAbi.isCompanionObjectInInterfaceNotIntrinsic class ObjectClassLowering(val context: JvmBackendContext) : IrElementTransformerVoidWithContext(), FileLoweringPass { @@ -46,22 +50,47 @@ class ObjectClassLowering(val context: JvmBackendContext) : IrElementTransformer } - fun process(irClass: IrClass) { + private fun process(irClass: IrClass) { if (irClass.descriptor.kind != ClassKind.OBJECT) return - val instanceFieldDescriptor = context.specialDescriptorsFactory.getFieldDescriptorForObjectInstance(irClass.descriptor) + val publicInstanceDescriptor = context.specialDescriptorsFactory.getFieldDescriptorForObjectInstance(irClass.descriptor) val constructor = irClass.descriptor.unsubstitutedPrimaryConstructor ?: throw AssertionError("Object should have a primary constructor: ${irClass.descriptor}") - val instanceInitializer = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, constructor) - val instanceField = IrFieldImpl( - UNDEFINED_OFFSET, UNDEFINED_OFFSET, JvmLoweredDeclarationOrigin.FIELD_FOR_OBJECT_INSTANCE, - instanceFieldDescriptor, - IrExpressionBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, instanceInitializer) - ) - - val instanceOwner = if (irClass.descriptor.isCompanionObject) parentScope!!.irElement as IrDeclarationContainer else irClass - pendingTransformations.add { instanceOwner.declarations.add(instanceField) } + val publicInstanceOwner = if (irClass.descriptor.isCompanionObject) parentScope!!.irElement as IrDeclarationContainer else irClass + if (isCompanionObjectInInterfaceNotIntrinsic(irClass.descriptor)) { + // TODO rename to $$INSTANCE + val privateInstance = publicInstanceDescriptor.copy(irClass.descriptor, Modality.FINAL, Visibilities.PROTECTED/*TODO package local*/, CallableMemberDescriptor.Kind.SYNTHESIZED, false) as PropertyDescriptor + privateInstance.name + val field = createInstanceFieldWithInitializer(privateInstance, constructor, irClass) + createFieldWithCustomInitializer( + publicInstanceDescriptor, + IrGetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, field.symbol), + publicInstanceOwner + ) + } else { + createInstanceFieldWithInitializer(publicInstanceDescriptor, constructor, publicInstanceOwner) + } } + + private fun createInstanceFieldWithInitializer( + instanceFieldDescriptor: PropertyDescriptor, + constructor: ClassConstructorDescriptor, + instanceOwner: IrDeclarationContainer + ): IrField = + createFieldWithCustomInitializer(instanceFieldDescriptor, IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, constructor), instanceOwner) + + private fun createFieldWithCustomInitializer( + instanceFieldDescriptor: PropertyDescriptor, + instanceInitializer: IrExpression, + instanceOwner: IrDeclarationContainer + ): IrField = + IrFieldImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, JvmLoweredDeclarationOrigin.FIELD_FOR_OBJECT_INSTANCE, + instanceFieldDescriptor, + IrExpressionBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, instanceInitializer) + ).also { + pendingTransformations.add { instanceOwner.declarations.add(it) } + } } \ No newline at end of file