Support class companion object lowering

This commit is contained in:
Mikhael Bogdanov
2017-11-24 10:52:57 +01:00
parent 224adfabc5
commit 24336113a2
3 changed files with 31 additions and 8 deletions
@@ -47,7 +47,8 @@ class JvmLower(val context: JvmBackendContext) {
NameUtils.sanitizeAsJavaIdentifier(super.localName(descriptor))
}).runOnFilePostfix(irFile)
EnumClassLowering(context).runOnFilePostfix(irFile)
ObjectClassLowering(context).runOnFilePostfix(irFile)
//Should be before SyntheticAccessorLowering cause of synthetic accessor for companion constructor
ObjectClassLowering(context).lower(irFile)
InitializersLowering(context).runOnFilePostfix(irFile)
SingletonReferencesLowering(context).runOnFilePostfix(irFile)
SyntheticAccessorLowering(context).lower(irFile)
@@ -125,10 +125,12 @@ class SpecialDescriptorsFactory(
private fun createObjectInstanceFieldDescriptor(objectDescriptor: ClassDescriptor): PropertyDescriptor {
assert(objectDescriptor.kind == ClassKind.OBJECT) { "Should be an object: $objectDescriptor" }
val name = if (objectDescriptor.isCompanionObject) objectDescriptor.name else Name.identifier("INSTANCE")
val containingDeclaration = if (objectDescriptor.isCompanionObject) objectDescriptor.containingDeclaration else objectDescriptor
return PropertyDescriptorImpl.create(
objectDescriptor,
containingDeclaration,
Annotations.EMPTY, Modality.FINAL, Visibilities.PUBLIC, false,
Name.identifier("INSTANCE"),
name,
CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE, /* lateInit = */ false, /* isConst = */ false,
/* isExpect = */ false, /* isActual = */ false, /* isExternal = */ false, /* isDelegated = */ false
).initialize(objectDescriptor.defaultType)
@@ -16,32 +16,52 @@
package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
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.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.IrFile
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
class ObjectClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
override fun lower(irClass: IrClass) {
class ObjectClassLowering(val context: JvmBackendContext) : IrElementTransformerVoidWithContext(), FileLoweringPass {
private var pendingTransformations = mutableListOf<Function0<Unit>>()
override fun lower(irFile: IrFile) {
irFile.accept(this, null)
pendingTransformations.forEach { it() }
}
override fun visitClassNew(declaration: IrClass): IrStatement {
process(declaration)
return super.visitClassNew(declaration)
}
fun process(irClass: IrClass) {
if (irClass.descriptor.kind != ClassKind.OBJECT) return
val instanceFieldDescriptor = 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 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)
)
irClass.declarations.add(instanceField)
val instanceOwner = if (irClass.descriptor.isCompanionObject) parentScope!!.irElement as IrDeclarationContainer else irClass
pendingTransformations.add { instanceOwner.declarations.add(instanceField) }
}
}