Support interface companion object lowering
This commit is contained in:
+41
-12
@@ -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) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user