Support interface companion object lowering

This commit is contained in:
Mikhael Bogdanov
2017-11-24 11:30:08 +01:00
parent 24336113a2
commit 420b9fdaa9
@@ -20,15 +20,19 @@ import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin 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.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer 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.IrFile
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl 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.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl 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 { 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 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 ?: val constructor = irClass.descriptor.unsubstitutedPrimaryConstructor ?:
throw AssertionError("Object should have a primary constructor: ${irClass.descriptor}") throw AssertionError("Object should have a primary constructor: ${irClass.descriptor}")
val instanceInitializer = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, constructor) val publicInstanceOwner = if (irClass.descriptor.isCompanionObject) parentScope!!.irElement as IrDeclarationContainer else irClass
val instanceField = IrFieldImpl( if (isCompanionObjectInInterfaceNotIntrinsic(irClass.descriptor)) {
UNDEFINED_OFFSET, UNDEFINED_OFFSET, JvmLoweredDeclarationOrigin.FIELD_FOR_OBJECT_INSTANCE, // TODO rename to $$INSTANCE
instanceFieldDescriptor, val privateInstance = publicInstanceDescriptor.copy(irClass.descriptor, Modality.FINAL, Visibilities.PROTECTED/*TODO package local*/, CallableMemberDescriptor.Kind.SYNTHESIZED, false) as PropertyDescriptor
IrExpressionBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, instanceInitializer) privateInstance.name
) val field = createInstanceFieldWithInitializer(privateInstance, constructor, irClass)
createFieldWithCustomInitializer(
val instanceOwner = if (irClass.descriptor.isCompanionObject) parentScope!!.irElement as IrDeclarationContainer else irClass publicInstanceDescriptor,
pendingTransformations.add { instanceOwner.declarations.add(instanceField) } 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) }
}
} }