Move fields and init blocks of companions to their owners
This commit is contained in:
+8
-9
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.ReceiverParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
@@ -200,6 +201,7 @@ open class WrappedVariableDescriptor(
|
||||
|
||||
override fun getContainingDeclaration() = (owner.parent as IrFunction).descriptor
|
||||
override fun getType() = owner.type.toKotlinType()
|
||||
override fun getReturnType() = getType()
|
||||
override fun getName() = owner.name
|
||||
override fun isConst() = owner.isConst
|
||||
override fun isVar() = owner.isVar
|
||||
@@ -489,7 +491,7 @@ open class WrappedPropertyDescriptor(
|
||||
annotations: Annotations = Annotations.EMPTY,
|
||||
private val sourceElement: SourceElement = SourceElement.NO_SOURCE
|
||||
) : PropertyDescriptor, WrappedDeclarationDescriptor<IrField>(annotations) {
|
||||
override fun getModality() = if (owner.isFinal) Modality.FINAL else Modality.OPEN
|
||||
override fun getModality() = owner.correspondingProperty?.modality ?: Modality.FINAL
|
||||
|
||||
override fun setOverriddenDescriptors(overriddenDescriptors: MutableCollection<out CallableMemberDescriptor>) {
|
||||
TODO("not implemented")
|
||||
@@ -553,21 +555,18 @@ open class WrappedPropertyDescriptor(
|
||||
|
||||
override fun getType(): KotlinType = owner.type.toKotlinType()
|
||||
|
||||
override fun isVar() = owner.isFinal
|
||||
override fun isVar() = !owner.isFinal
|
||||
|
||||
override fun getDispatchReceiverParameter(): ReceiverParameterDescriptor? {
|
||||
TODO("not implemented")
|
||||
}
|
||||
override fun getDispatchReceiverParameter(): ReceiverParameterDescriptor? =
|
||||
if (owner.isStatic) null else (owner.parentAsClass.thisReceiver?.descriptor as ReceiverParameterDescriptor)
|
||||
|
||||
override fun isConst() = false
|
||||
|
||||
override fun getContainingDeclaration() = (owner.parent as IrSymbolOwner).symbol.descriptor
|
||||
|
||||
override fun isLateInit() = false
|
||||
override fun isLateInit() = owner.correspondingProperty?.isLateinit ?: false
|
||||
|
||||
override fun getExtensionReceiverParameter(): ReceiverParameterDescriptor? {
|
||||
TODO("not implemented")
|
||||
}
|
||||
override fun getExtensionReceiverParameter(): ReceiverParameterDescriptor? = owner.correspondingProperty?.descriptor?.extensionReceiverParameter
|
||||
|
||||
override fun isExternal() = owner.isExternal
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
||||
import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import java.io.StringWriter
|
||||
|
||||
@@ -303,3 +304,21 @@ fun IrType.remapTypeParameters(source: IrTypeParametersContainer, target: IrType
|
||||
else -> this
|
||||
}
|
||||
|
||||
/* Copied from K/N */
|
||||
fun IrDeclarationContainer.addChild(declaration: IrDeclaration) {
|
||||
this.declarations += declaration
|
||||
declaration.accept(SetDeclarationsParentVisitor, this)
|
||||
}
|
||||
|
||||
object SetDeclarationsParentVisitor : IrElementVisitor<Unit, IrDeclarationParent> {
|
||||
override fun visitElement(element: IrElement, data: IrDeclarationParent) {
|
||||
if (element !is IrDeclarationParent) {
|
||||
element.acceptChildren(this, data)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitDeclaration(declaration: IrDeclaration, data: IrDeclarationParent) {
|
||||
declaration.parent = data
|
||||
super.visitDeclaration(declaration, data)
|
||||
}
|
||||
}
|
||||
+90
-77
@@ -7,34 +7,29 @@ package org.jetbrains.kotlin.backend.common.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||
import org.jetbrains.kotlin.backend.common.ir.SetDeclarationsParentVisitor
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBlock
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrInstanceInitializerCall
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
|
||||
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import java.util.*
|
||||
|
||||
object SYNTHESIZED_INIT_BLOCK: IrStatementOriginImpl("SYNTHESIZED_INIT_BLOCK")
|
||||
|
||||
class InitializersLowering(
|
||||
val context: CommonBackendContext,
|
||||
@@ -42,83 +37,101 @@ class InitializersLowering(
|
||||
private val clinitNeeded: Boolean
|
||||
) : ClassLoweringPass {
|
||||
override fun lower(irClass: IrClass) {
|
||||
val classInitializersBuilder = ClassInitializersBuilder(irClass)
|
||||
irClass.acceptChildrenVoid(classInitializersBuilder)
|
||||
val instanceInitializerStatements = handleNonStatics(irClass)
|
||||
transformInstanceInitializerCallsInConstructors(irClass, instanceInitializerStatements)
|
||||
|
||||
classInitializersBuilder.transformInstanceInitializerCallsInConstructors(irClass)
|
||||
|
||||
if (clinitNeeded && classInitializersBuilder.staticInitializerStatements.isNotEmpty())
|
||||
classInitializersBuilder.createStaticInitializationMethod(irClass)
|
||||
val staticInitializerStatements = handleStatics(irClass)
|
||||
if (clinitNeeded && staticInitializerStatements.isNotEmpty())
|
||||
createStaticInitializationMethod(irClass, staticInitializerStatements)
|
||||
}
|
||||
|
||||
private inner class ClassInitializersBuilder(val irClass: IrClass) : IrElementVisitorVoid {
|
||||
val staticInitializerStatements = ArrayList<IrStatement>()
|
||||
fun handleNonStatics(irClass: IrClass) =
|
||||
irClass.declarations.filter {
|
||||
(it is IrField && !it.isStatic) || (it is IrAnonymousInitializer && !it.isStatic)
|
||||
}.mapNotNull { handleDeclaration(irClass, it) }
|
||||
|
||||
val instanceInitializerStatements = ArrayList<IrStatement>()
|
||||
fun handleStatics(irClass: IrClass) =
|
||||
// Hardcoded order of initializers
|
||||
(irClass.declarations.filter { it is IrField && it.origin == IrDeclarationOrigin.FIELD_FOR_ENUM_ENTRY } +
|
||||
irClass.declarations.filter { it is IrField && it.origin == IrDeclarationOrigin.FIELD_FOR_ENUM_VALUES } +
|
||||
irClass.declarations.filter { it is IrField && it.origin == IrDeclarationOrigin.FIELD_FOR_OBJECT_INSTANCE } +
|
||||
irClass.declarations.filter {
|
||||
(it is IrField && it.isStatic && it.origin !in listOf(
|
||||
IrDeclarationOrigin.FIELD_FOR_ENUM_ENTRY,
|
||||
IrDeclarationOrigin.FIELD_FOR_ENUM_VALUES,
|
||||
IrDeclarationOrigin.FIELD_FOR_OBJECT_INSTANCE
|
||||
)) || (it is IrAnonymousInitializer && it.isStatic)
|
||||
})
|
||||
.mapNotNull { handleDeclaration(irClass, it) }
|
||||
|
||||
override fun visitElement(element: IrElement) {
|
||||
// skip everything else
|
||||
}
|
||||
fun handleDeclaration(irClass: IrClass, declaration: IrDeclaration): IrStatement? = when(declaration) {
|
||||
is IrField -> handleField(irClass, declaration)
|
||||
is IrAnonymousInitializer -> handleAnonymousInitializer(declaration)
|
||||
else -> null
|
||||
}
|
||||
|
||||
override fun visitField(declaration: IrField) {
|
||||
val irFieldInitializer = declaration.initializer?.expression ?: return
|
||||
fun handleField(irClass: IrClass, declaration: IrField): IrStatement? {
|
||||
val irFieldInitializer = declaration.initializer?.expression ?: return null
|
||||
|
||||
val receiver =
|
||||
if (!declaration.isStatic) // TODO isStaticField
|
||||
IrGetValueImpl(
|
||||
irFieldInitializer.startOffset, irFieldInitializer.endOffset,
|
||||
irClass.thisReceiver!!.type, irClass.thisReceiver!!.symbol
|
||||
)
|
||||
else null
|
||||
val irSetField = IrSetFieldImpl(
|
||||
irFieldInitializer.startOffset, irFieldInitializer.endOffset,
|
||||
declaration.symbol,
|
||||
receiver,
|
||||
irFieldInitializer,
|
||||
context.irBuiltIns.unitType,
|
||||
null, null
|
||||
)
|
||||
|
||||
if (declaration.isStatic) {
|
||||
staticInitializerStatements.add(irSetField)
|
||||
} else {
|
||||
instanceInitializerStatements.add(irSetField)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer) {
|
||||
instanceInitializerStatements.addAll(declaration.body.statements)
|
||||
}
|
||||
|
||||
fun transformInstanceInitializerCallsInConstructors(irClass: IrClass) {
|
||||
irClass.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||
override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall): IrExpression {
|
||||
val copiedBlock = IrBlockImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.unitType, null, instanceInitializerStatements).copy(irClass) as IrBlock
|
||||
return IrBlockImpl(irClass.startOffset, irClass.endOffset, context.irBuiltIns.unitType, null, copiedBlock.statements)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun createStaticInitializationMethod(irClass: IrClass) {
|
||||
val staticInitializerDescriptor = SimpleFunctionDescriptorImpl.create(
|
||||
irClass.descriptor, Annotations.EMPTY, clinitName,
|
||||
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||
SourceElement.NO_SOURCE
|
||||
)
|
||||
staticInitializerDescriptor.initialize(
|
||||
null, null, emptyList(), emptyList(),
|
||||
irClass.descriptor.builtIns.unitType,
|
||||
Modality.FINAL, Visibilities.PUBLIC
|
||||
)
|
||||
irClass.declarations.add(
|
||||
IrFunctionImpl(
|
||||
irClass.startOffset, irClass.endOffset, declarationOrigin,
|
||||
staticInitializerDescriptor,
|
||||
IrBlockBodyImpl(irClass.startOffset, irClass.endOffset,
|
||||
staticInitializerStatements.map { it.copy(irClass) })
|
||||
val receiver =
|
||||
if (!declaration.isStatic) // TODO isStaticField
|
||||
IrGetValueImpl(
|
||||
irFieldInitializer.startOffset, irFieldInitializer.endOffset,
|
||||
irClass.thisReceiver!!.type, irClass.thisReceiver!!.symbol
|
||||
)
|
||||
)
|
||||
}
|
||||
else null
|
||||
return IrSetFieldImpl(
|
||||
irFieldInitializer.startOffset, irFieldInitializer.endOffset,
|
||||
declaration.symbol,
|
||||
receiver,
|
||||
irFieldInitializer,
|
||||
context.irBuiltIns.unitType,
|
||||
null, null
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
fun handleAnonymousInitializer(declaration: IrAnonymousInitializer): IrStatement = IrBlockImpl(
|
||||
declaration.startOffset, declaration.endOffset,
|
||||
context.irBuiltIns.unitType,
|
||||
SYNTHESIZED_INIT_BLOCK,
|
||||
declaration.body.statements
|
||||
)
|
||||
|
||||
fun transformInstanceInitializerCallsInConstructors(irClass: IrClass, instanceInitializerStatements: List<IrStatement>) {
|
||||
irClass.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||
override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall): IrExpression {
|
||||
val copiedBlock =
|
||||
IrBlockImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.unitType, null, instanceInitializerStatements).copy(
|
||||
irClass
|
||||
) as IrBlock
|
||||
return IrBlockImpl(irClass.startOffset, irClass.endOffset, context.irBuiltIns.unitType, null, copiedBlock.statements)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun createStaticInitializationMethod(irClass: IrClass, staticInitializerStatements: List<IrStatement>) {
|
||||
val staticInitializerDescriptor = SimpleFunctionDescriptorImpl.create(
|
||||
irClass.descriptor, Annotations.EMPTY, clinitName,
|
||||
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||
SourceElement.NO_SOURCE
|
||||
)
|
||||
staticInitializerDescriptor.initialize(
|
||||
null, null, emptyList(), emptyList(),
|
||||
irClass.descriptor.builtIns.unitType,
|
||||
Modality.FINAL, Visibilities.PUBLIC
|
||||
)
|
||||
irClass.declarations.add(
|
||||
IrFunctionImpl(
|
||||
irClass.startOffset, irClass.endOffset, declarationOrigin,
|
||||
staticInitializerDescriptor,
|
||||
IrBlockBodyImpl(irClass.startOffset, irClass.endOffset,
|
||||
staticInitializerStatements.map { it.copy(irClass) })
|
||||
).apply {
|
||||
returnType = context.irBuiltIns.unitType
|
||||
accept(SetDeclarationsParentVisitor, this)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
+30
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.backend.common.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.BackendContext
|
||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||
import org.jetbrains.kotlin.backend.common.atMostOne
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
@@ -33,6 +34,8 @@ import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
@@ -235,3 +238,30 @@ fun ParameterDescriptor.copyAsValueParameter(newOwner: CallableDescriptor, index
|
||||
)
|
||||
else -> throw Error("Unexpected parameter descriptor: $this")
|
||||
}
|
||||
|
||||
fun IrBody.replaceThisByStaticReference(
|
||||
context: CommonBackendContext,
|
||||
irClass: IrClass,
|
||||
oldThisReceiverParameter: IrValueParameter
|
||||
): IrBody =
|
||||
transform(ReplaceThisByStaticReference(context, irClass, oldThisReceiverParameter), null)
|
||||
|
||||
private class ReplaceThisByStaticReference(
|
||||
val context: CommonBackendContext,
|
||||
val irClass: IrClass,
|
||||
val oldThisReceiverParameter: IrValueParameter
|
||||
) : IrElementTransformer<Nothing?> {
|
||||
override fun visitGetValue(expression: IrGetValue, data: Nothing?): IrExpression {
|
||||
val irGetValue = expression
|
||||
if (irGetValue.symbol == oldThisReceiverParameter.symbol) {
|
||||
val instanceField = context.declarationFactory.getFieldForObjectInstance(irClass)
|
||||
return IrGetFieldImpl(
|
||||
expression.startOffset,
|
||||
expression.endOffset,
|
||||
instanceField.symbol,
|
||||
irClass.defaultType
|
||||
)
|
||||
}
|
||||
return super.visitGetValue(irGetValue, data)
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -36,7 +36,8 @@ class PropertiesLowering : IrElementTransformerVoid(), FileLoweringPass {
|
||||
private fun lowerProperty(declaration: IrDeclaration, kind: ClassKind): List<IrDeclaration>? =
|
||||
if (declaration is IrProperty)
|
||||
ArrayList<IrDeclaration>(3).apply {
|
||||
if (kind != ClassKind.ANNOTATION_CLASS) {
|
||||
// JvmFields in a companion object refer to companion's owners and should not be generated within companion.
|
||||
if (kind != ClassKind.ANNOTATION_CLASS && declaration.backingField?.parent == declaration.parent) {
|
||||
addIfNotNull(declaration.backingField)
|
||||
}
|
||||
addIfNotNull(declaration.getter)
|
||||
|
||||
Reference in New Issue
Block a user