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)
|
||||
|
||||
@@ -24,9 +24,6 @@ import org.jetbrains.kotlin.ir.expressions.IrStatementOriginImpl
|
||||
interface JvmLoweredDeclarationOrigin : IrDeclarationOrigin {
|
||||
object CLASS_STATIC_INITIALIZER : IrDeclarationOriginImpl("CLASS_STATIC_INITIALIZER")
|
||||
object DEFAULT_IMPLS : IrDeclarationOriginImpl("DEFAULT_IMPL")
|
||||
object FIELD_FOR_ENUM_ENTRY : IrDeclarationOriginImpl("FIELD_FOR_ENUM_ENTRY")
|
||||
object FIELD_FOR_ENUM_VALUES : IrDeclarationOriginImpl("FIELD_FOR_ENUM_VALUES")
|
||||
object FIELD_FOR_OBJECT_INSTANCE : IrDeclarationOriginImpl("FIELD_FOR_OBJECT_INSTANCE")
|
||||
object FIELD_FOR_OUTER_THIS : IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS")
|
||||
object SYNTHETIC_ACCESSOR : IrDeclarationOriginImpl("SYNTHETIC_ACCESSOR")
|
||||
object TO_ARRAY : IrDeclarationOriginImpl("TO_ARRAY")
|
||||
|
||||
@@ -40,6 +40,7 @@ class JvmLower(val context: JvmBackendContext) {
|
||||
|
||||
LateinitLowering(context, true).lower(irFile)
|
||||
|
||||
MoveCompanionObjectFieldsLowering(context).runOnFilePostfix(irFile)
|
||||
ConstAndJvmFieldPropertiesLowering(context).lower(irFile)
|
||||
PropertiesLowering().lower(irFile)
|
||||
AnnotationLowering().runOnFilePostfix(irFile) //should be run before defaults lowering
|
||||
|
||||
+7
-3
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.kotlin.backend.jvm.codegen
|
||||
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmDescriptorWithExtraFlags
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||
@@ -159,7 +158,7 @@ open class ClassCodegen protected constructor(
|
||||
fieldSignature, null/*TODO support default values*/
|
||||
)
|
||||
|
||||
if (field.origin == JvmLoweredDeclarationOrigin.FIELD_FOR_ENUM_ENTRY) {
|
||||
if (field.origin == IrDeclarationOrigin.FIELD_FOR_ENUM_ENTRY) {
|
||||
AnnotationCodegen.forField(fv, this, typeMapper).genAnnotations(field.descriptor, null)
|
||||
} else {
|
||||
|
||||
@@ -254,7 +253,12 @@ fun MemberDescriptor.calculateCommonFlags(): Int {
|
||||
|
||||
private fun MemberDescriptor.calcModalityFlag(): Int {
|
||||
var flags = 0
|
||||
when (effectiveModality) {
|
||||
if (this is PropertyDescriptor) {
|
||||
// Modality for a field: set FINAL for vals
|
||||
if (!isVar && !isLateInit) {
|
||||
flags = flags.or(Opcodes.ACC_FINAL)
|
||||
}
|
||||
} else when (effectiveModality) {
|
||||
Modality.ABSTRACT -> {
|
||||
flags = flags.or(Opcodes.ACC_ABSTRACT)
|
||||
}
|
||||
|
||||
+2
-2
@@ -61,7 +61,7 @@ class JvmDeclarationFactory(
|
||||
IrFieldImpl(
|
||||
enumEntry.startOffset,
|
||||
enumEntry.endOffset,
|
||||
JvmLoweredDeclarationOrigin.FIELD_FOR_ENUM_ENTRY,
|
||||
IrDeclarationOrigin.FIELD_FOR_ENUM_ENTRY,
|
||||
symbol,
|
||||
type
|
||||
)
|
||||
@@ -181,7 +181,7 @@ class JvmDeclarationFactory(
|
||||
return IrFieldImpl(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
JvmLoweredDeclarationOrigin.FIELD_FOR_OBJECT_INSTANCE,
|
||||
IrDeclarationOrigin.FIELD_FOR_OBJECT_INSTANCE,
|
||||
symbol,
|
||||
singleton.defaultType
|
||||
)
|
||||
|
||||
+52
-26
@@ -5,30 +5,23 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.lower.irBlock
|
||||
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
|
||||
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyGetterDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConst
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetterCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrSetterCallImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||
import org.jetbrains.kotlin.ir.util.hasAnnotation
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi.JVM_FIELD_ANNOTATION_FQ_NAME
|
||||
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
|
||||
|
||||
class ConstAndJvmFieldPropertiesLowering(val context: JvmBackendContext) : IrElementTransformerVoid(), FileLoweringPass {
|
||||
|
||||
class ConstAndJvmFieldPropertiesLowering(val context: CommonBackendContext) : IrElementTransformerVoid(), FileLoweringPass {
|
||||
override fun lower(irFile: IrFile) {
|
||||
irFile.transformChildrenVoid(this)
|
||||
}
|
||||
@@ -43,7 +36,8 @@ class ConstAndJvmFieldPropertiesLowering(val context: JvmBackendContext) : IrEle
|
||||
}
|
||||
|
||||
override fun visitCall(expression: IrCall): IrExpression {
|
||||
val irProperty = (expression.symbol.owner as? IrSimpleFunction)?.correspondingProperty ?: return super.visitCall(expression)
|
||||
val irSimpleFunction = (expression.symbol.owner as? IrSimpleFunction) ?: return super.visitCall(expression)
|
||||
val irProperty = irSimpleFunction.correspondingProperty ?: return super.visitCall(expression)
|
||||
|
||||
if (irProperty.isConst) {
|
||||
(irProperty.backingField?.initializer?.expression as? IrConst<*>)?.let { return it }
|
||||
@@ -63,28 +57,60 @@ class ConstAndJvmFieldPropertiesLowering(val context: JvmBackendContext) : IrEle
|
||||
return super.visitCall(expression)
|
||||
}
|
||||
|
||||
private fun substituteSetter(irProperty: IrProperty, expression: IrCall): IrSetFieldImpl {
|
||||
return IrSetFieldImpl(
|
||||
private fun substituteSetter(irProperty: IrProperty, expression: IrCall): IrExpression {
|
||||
val backingField = irProperty.backingField!!
|
||||
val receiver = expression.dispatchReceiver?.let { super.visitExpression(it) }
|
||||
val setExpr = IrSetFieldImpl(
|
||||
expression.startOffset,
|
||||
expression.endOffset,
|
||||
irProperty.backingField!!.symbol,
|
||||
expression.dispatchReceiver,
|
||||
expression.getValueArgument(expression.symbol.owner.valueParameters.lastIndex)!!,
|
||||
backingField.symbol,
|
||||
receiver,
|
||||
super.visitExpression(expression.getValueArgument(expression.valueArgumentsCount - 1)!!),
|
||||
expression.type,
|
||||
expression.origin,
|
||||
expression.superQualifier?.let { context.ir.symbols.externalSymbolTable.referenceClass(it) }
|
||||
expression.superQualifierSymbol
|
||||
)
|
||||
return buildSubstitution(backingField.isStaticField(), setExpr, receiver)
|
||||
}
|
||||
|
||||
private fun substituteGetter(irProperty: IrProperty, expression: IrCall): IrExpression {
|
||||
return IrGetFieldImpl(
|
||||
val backingField = irProperty.backingField!!
|
||||
val receiver = expression.dispatchReceiver?.let { super.visitExpression(it) }
|
||||
val getExpr = IrGetFieldImpl(
|
||||
expression.startOffset,
|
||||
expression.endOffset,
|
||||
irProperty.backingField!!.symbol,
|
||||
backingField.symbol,
|
||||
expression.type,
|
||||
expression.dispatchReceiver,
|
||||
receiver,
|
||||
expression.origin,
|
||||
expression.superQualifier?.let { context.ir.symbols.externalSymbolTable.referenceClass(it) }
|
||||
expression.superQualifierSymbol
|
||||
)
|
||||
return buildSubstitution(backingField.isStaticField(), getExpr, receiver)
|
||||
}
|
||||
|
||||
private fun buildSubstitution(needBlock: Boolean, setOrGetExpr: IrFieldAccessExpression, receiver: IrExpression?): IrExpression {
|
||||
if (receiver != null && needBlock) {
|
||||
// Evaluate `dispatchReceiver` for the sake of its side effects, then return `setOrGetExpr`.
|
||||
return context.createIrBuilder(setOrGetExpr.symbol, setOrGetExpr.startOffset, setOrGetExpr.endOffset).irBlock(setOrGetExpr) {
|
||||
// `coerceToUnit()` is private in InsertImplicitCasts, have to reproduce it here
|
||||
val receiverVoid = IrTypeOperatorCallImpl(
|
||||
receiver.startOffset, receiver.endOffset,
|
||||
context.irBuiltIns.unitType,
|
||||
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT,
|
||||
context.irBuiltIns.unitType, context.irBuiltIns.unitType.classifierOrFail,
|
||||
receiver
|
||||
)
|
||||
|
||||
+receiverVoid
|
||||
setOrGetExpr.receiver = null
|
||||
+setOrGetExpr
|
||||
}
|
||||
} else {
|
||||
// Just `setOrGetExpr` (`dispatchReceiver` is evaluated as a subexpression thereof)
|
||||
return setOrGetExpr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Should probably be an utility function with a more direct implementation.
|
||||
private fun IrField.isStaticField() = (descriptor.dispatchReceiverParameter == null)
|
||||
|
||||
+1
-2
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.backend.jvm.lower
|
||||
import gnu.trove.TObjectIntHashMap
|
||||
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmPropertyDescriptorImpl
|
||||
import org.jetbrains.kotlin.backend.jvm.descriptors.createValueParameter
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
@@ -221,7 +220,7 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
||||
val irValuesInitializer = createSyntheticValuesFieldInitializerExpression()
|
||||
|
||||
return IrFieldImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, JvmLoweredDeclarationOrigin.FIELD_FOR_ENUM_VALUES,
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.FIELD_FOR_ENUM_VALUES,
|
||||
createSyntheticValuesFieldDescriptor(valuesArrayType),
|
||||
valuesArrayType.toIrType()!!,
|
||||
IrExpressionBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irValuesInitializer)
|
||||
|
||||
+2
-20
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.lower.irBlock
|
||||
import org.jetbrains.kotlin.backend.common.lower.replaceThisByStaticReference
|
||||
import org.jetbrains.kotlin.backend.common.runOnFilePostfix
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
@@ -156,26 +157,7 @@ private class SingletonObjectJvmStaticLowering(
|
||||
}
|
||||
|
||||
fun modifyBody(irFunction: IrFunction, irClass: IrClass, oldDispatchReceiverParameter: IrValueParameter) {
|
||||
irFunction.body = irFunction.body?.transform(ReplaceThisByStaticReference(context, irClass, oldDispatchReceiverParameter), null)
|
||||
}
|
||||
}
|
||||
|
||||
private class ReplaceThisByStaticReference(
|
||||
val context: JvmBackendContext,
|
||||
val irClass: IrClass,
|
||||
val oldThisReceiverParameter: IrValueParameter
|
||||
) : IrElementTransformer<Nothing?> {
|
||||
override fun visitGetValue(expression: IrGetValue, data: Nothing?): IrExpression {
|
||||
if (expression.symbol == oldThisReceiverParameter.symbol) {
|
||||
val instanceField = context.declarationFactory.getFieldForObjectInstance(irClass)
|
||||
return IrGetFieldImpl(
|
||||
expression.startOffset,
|
||||
expression.endOffset,
|
||||
instanceField.symbol,
|
||||
irClass.defaultType
|
||||
)
|
||||
}
|
||||
return super.visitGetValue(expression, data)
|
||||
irFunction.body = irFunction.body?.replaceThisByStaticReference(context, irClass, oldDispatchReceiverParameter)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+226
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedPropertyDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedVariableDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.lower.replaceThisByStaticReference
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrAnonymousInitializerImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrAnonymousInitializerSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.util.hasAnnotation
|
||||
import org.jetbrains.kotlin.ir.util.isInterface
|
||||
import org.jetbrains.kotlin.ir.util.isObject
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi.JVM_FIELD_ANNOTATION_FQ_NAME
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class MoveCompanionObjectFieldsLowering(val context: CommonBackendContext) : ClassLoweringPass {
|
||||
override fun lower(irClass: IrClass) {
|
||||
val fieldReplacementMap = mutableMapOf<IrFieldSymbol, IrFieldSymbol>()
|
||||
if (irClass.isObject && !irClass.isCompanion && irClass.visibility != Visibilities.LOCAL) {
|
||||
handleObject(irClass, fieldReplacementMap)
|
||||
} else {
|
||||
handleClass(irClass, fieldReplacementMap)
|
||||
}
|
||||
irClass.replaceFieldReferences(fieldReplacementMap)
|
||||
}
|
||||
|
||||
private fun handleObject(irObject: IrClass, fieldReplacementMap: MutableMap<IrFieldSymbol, IrFieldSymbol>) {
|
||||
irObject.declarations.replaceAll {
|
||||
when (it) {
|
||||
is IrProperty -> {
|
||||
// The field is not actually moved, just replaced by a static field
|
||||
movePropertyFieldToStaticParent(it, irObject, irObject, fieldReplacementMap)
|
||||
it
|
||||
}
|
||||
is IrAnonymousInitializer -> moveAnonymousInitializerToStaticParent(it, irObject, irObject)
|
||||
else -> it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleClass(irClass: IrClass, fieldReplacementMap: MutableMap<IrFieldSymbol, IrFieldSymbol>) {
|
||||
val companion = irClass.declarations.find {
|
||||
it is IrClass && it.isCompanion
|
||||
} as IrClass? ?: return
|
||||
if (irClass.isInterface && !companion.allFieldsAreJvmField()) return
|
||||
companion.declarations.forEach {
|
||||
when (it) {
|
||||
is IrProperty -> {
|
||||
val newField = movePropertyFieldToStaticParent(it, companion, irClass, fieldReplacementMap)
|
||||
if (newField != null) irClass.declarations.add(newField)
|
||||
}
|
||||
is IrAnonymousInitializer -> {
|
||||
val newInitializer = moveAnonymousInitializerToStaticParent(it, companion, irClass)
|
||||
irClass.declarations.add(newInitializer)
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
companion.declarations.removeAll { it is IrAnonymousInitializer }
|
||||
}
|
||||
|
||||
private fun IrClass.allFieldsAreJvmField() =
|
||||
declarations.filterIsInstance<IrProperty>()
|
||||
.mapNotNull { it.backingField }.all { it.hasAnnotation(JVM_FIELD_ANNOTATION_FQ_NAME) }
|
||||
|
||||
private fun movePropertyFieldToStaticParent(
|
||||
irProperty: IrProperty,
|
||||
propertyParent: IrClass,
|
||||
fieldParent: IrClass,
|
||||
fieldReplacementMap: MutableMap<IrFieldSymbol, IrFieldSymbol>
|
||||
): IrField? {
|
||||
if (irProperty.origin == IrDeclarationOrigin.FAKE_OVERRIDE) return null
|
||||
val oldField = irProperty.backingField ?: return null
|
||||
val newField = createStaticBackingField(oldField, propertyParent, fieldParent)
|
||||
|
||||
irProperty.backingField = newField
|
||||
|
||||
fieldReplacementMap[oldField.symbol] = newField.symbol
|
||||
|
||||
return newField
|
||||
}
|
||||
|
||||
private fun moveAnonymousInitializerToStaticParent(
|
||||
oldInitializer: IrAnonymousInitializer,
|
||||
oldParent: IrClass,
|
||||
newParent: IrClass
|
||||
): IrAnonymousInitializer =
|
||||
with(oldInitializer) {
|
||||
IrAnonymousInitializerImpl(
|
||||
startOffset, endOffset, origin, IrAnonymousInitializerSymbolImpl(newParent.descriptor),
|
||||
isStatic = true
|
||||
).apply {
|
||||
parent = newParent
|
||||
body = oldInitializer.body.transferToNewParent(oldParent, newParent)
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrBlockBody.transferToNewParent(oldParent: IrClass, newParent: IrClass): IrBlockBody {
|
||||
val objectInstanceField = context.declarationFactory.getFieldForObjectInstance(oldParent)
|
||||
return transform(
|
||||
data = null,
|
||||
transformer = object : IrElementTransformerVoid() {
|
||||
val variableMap = mutableMapOf<IrVariable, IrVariable>()
|
||||
|
||||
override fun visitVariable(declaration: IrVariable): IrStatement {
|
||||
val newDescriptor = WrappedVariableDescriptor(declaration.descriptor.annotations, declaration.descriptor.source)
|
||||
if (declaration.parent == oldParent) {
|
||||
val newVariable = IrVariableImpl(
|
||||
declaration.startOffset, declaration.endOffset,
|
||||
declaration.origin, IrVariableSymbolImpl(newDescriptor),
|
||||
declaration.name, declaration.type, declaration.isVar, declaration.isConst, declaration.isLateinit
|
||||
).apply {
|
||||
newDescriptor.bind(this)
|
||||
parent = newParent
|
||||
initializer = declaration.initializer
|
||||
}
|
||||
variableMap[declaration] = newVariable
|
||||
return super.visitVariable(newVariable)
|
||||
}
|
||||
return super.visitVariable(declaration)
|
||||
}
|
||||
|
||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||
if (expression.symbol.owner == oldParent.thisReceiver) {
|
||||
return IrGetFieldImpl(
|
||||
expression.startOffset, expression.endOffset,
|
||||
objectInstanceField.symbol,
|
||||
expression.type
|
||||
)
|
||||
}
|
||||
variableMap[expression.symbol.owner]?.let { newVariable ->
|
||||
return IrGetValueImpl(
|
||||
expression.startOffset, expression.endOffset,
|
||||
expression.type,
|
||||
newVariable.symbol,
|
||||
expression.origin
|
||||
)
|
||||
}
|
||||
return super.visitGetValue(expression)
|
||||
}
|
||||
}) as IrBlockBody
|
||||
}
|
||||
|
||||
private fun createStaticBackingField(oldField: IrField, propertyParent: IrClass, fieldParent: IrClass): IrField {
|
||||
val newName = if (fieldParent == propertyParent ||
|
||||
oldField.hasAnnotation(JVM_FIELD_ANNOTATION_FQ_NAME) ||
|
||||
oldField.correspondingProperty?.isConst == true
|
||||
)
|
||||
oldField.name
|
||||
else
|
||||
Name.identifier(oldField.name.toString() + "\$companion")
|
||||
val descriptor = WrappedPropertyDescriptor(oldField.descriptor.annotations, oldField.descriptor.source)
|
||||
val field = IrFieldImpl(
|
||||
oldField.startOffset, oldField.endOffset,
|
||||
IrDeclarationOrigin.PROPERTY_BACKING_FIELD,
|
||||
IrFieldSymbolImpl(descriptor),
|
||||
newName, oldField.type, oldField.visibility,
|
||||
isFinal = oldField.isFinal,
|
||||
isExternal = oldField.isExternal,
|
||||
isStatic = true
|
||||
).apply {
|
||||
descriptor.bind(this)
|
||||
parent = fieldParent
|
||||
oldField.annotations.mapTo(annotations) { it }
|
||||
}
|
||||
val oldInitializer = oldField.initializer
|
||||
if (oldInitializer != null) {
|
||||
field.initializer = oldInitializer.replaceThisByStaticReference(
|
||||
context,
|
||||
propertyParent,
|
||||
propertyParent.thisReceiver!!
|
||||
) as IrExpressionBody
|
||||
}
|
||||
|
||||
return field
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrElement.replaceFieldReferences(replacementMap: Map<IrFieldSymbol, IrFieldSymbol>) {
|
||||
transformChildrenVoid(FieldReplacer(replacementMap))
|
||||
}
|
||||
|
||||
private class FieldReplacer(val replacementMap: Map<IrFieldSymbol, IrFieldSymbol>) : IrElementTransformerVoid() {
|
||||
override fun visitGetField(expression: IrGetField): IrExpression =
|
||||
replacementMap[expression.symbol]?.let { newSymbol ->
|
||||
IrGetFieldImpl(
|
||||
expression.startOffset, expression.endOffset,
|
||||
newSymbol,
|
||||
expression.type,
|
||||
/* receiver = */ null,
|
||||
expression.origin,
|
||||
expression.superQualifierSymbol
|
||||
)
|
||||
} ?: super.visitGetField(expression)
|
||||
|
||||
override fun visitSetField(expression: IrSetField): IrExpression =
|
||||
replacementMap[expression.symbol]?.let { newSymbol ->
|
||||
IrSetFieldImpl(
|
||||
expression.startOffset, expression.endOffset,
|
||||
replacementMap[expression.symbol]!!,
|
||||
/* receiver = */ null,
|
||||
visitExpression(expression.value),
|
||||
expression.type,
|
||||
expression.origin,
|
||||
expression.superQualifierSymbol
|
||||
)
|
||||
} ?: super.visitSetField(expression)
|
||||
}
|
||||
+5
-8
@@ -8,15 +8,11 @@ package org.jetbrains.kotlin.backend.jvm.lower
|
||||
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.codegen.JvmCodegenUtil.isCompanionObjectInInterfaceNotIntrinsic
|
||||
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.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
@@ -24,7 +20,6 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.isObject
|
||||
@@ -80,7 +75,9 @@ class ObjectClassLowering(val context: JvmBackendContext) : IrElementTransformer
|
||||
}
|
||||
|
||||
publicInstanceField.parent = publicInstanceOwner
|
||||
pendingTransformations.add { publicInstanceOwner.declarations.add(publicInstanceField) }
|
||||
pendingTransformations.add {
|
||||
publicInstanceOwner.declarations.add(publicInstanceField)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createInstanceFieldWithInitializer(
|
||||
@@ -103,7 +100,7 @@ class ObjectClassLowering(val context: JvmBackendContext) : IrElementTransformer
|
||||
objectType: IrType
|
||||
): IrField =
|
||||
IrFieldImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, JvmLoweredDeclarationOrigin.FIELD_FOR_OBJECT_INSTANCE,
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.FIELD_FOR_OBJECT_INSTANCE,
|
||||
fieldSymbol, objectType
|
||||
).also {
|
||||
it.initializer = IrExpressionBodyImpl(instanceInitializer)
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.ir.symbols.IrAnonymousInitializerSymbol
|
||||
|
||||
interface IrAnonymousInitializer : IrSymbolDeclaration<IrAnonymousInitializerSymbol> {
|
||||
override val descriptor: ClassDescriptor // TODO special descriptor for anonymous initializer blocks
|
||||
val isStatic: Boolean
|
||||
|
||||
var body: IrBlockBody
|
||||
}
|
||||
|
||||
@@ -38,6 +38,10 @@ interface IrDeclarationOrigin {
|
||||
object IR_EXTERNAL_DECLARATION_STUB : IrDeclarationOriginImpl("IR_EXTERNAL_DECLARATION_STUB")
|
||||
object IR_BUILTINS_STUB : IrDeclarationOriginImpl("IR_BUILTINS_STUB")
|
||||
object BRIDGE : IrDeclarationOriginImpl("BRIDGE")
|
||||
|
||||
object FIELD_FOR_ENUM_ENTRY : IrDeclarationOriginImpl("FIELD_FOR_ENUM_ENTRY")
|
||||
object FIELD_FOR_ENUM_VALUES : IrDeclarationOriginImpl("FIELD_FOR_ENUM_VALUES")
|
||||
object FIELD_FOR_OBJECT_INSTANCE : IrDeclarationOriginImpl("FIELD_FOR_OBJECT_INSTANCE")
|
||||
}
|
||||
|
||||
abstract class IrDeclarationOriginImpl(val name: String) : IrDeclarationOrigin {
|
||||
|
||||
+8
-5
@@ -29,7 +29,8 @@ class IrAnonymousInitializerImpl(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
origin: IrDeclarationOrigin,
|
||||
override val symbol: IrAnonymousInitializerSymbol
|
||||
override val symbol: IrAnonymousInitializerSymbol,
|
||||
override val isStatic: Boolean = false
|
||||
) : IrDeclarationBase(startOffset, endOffset, origin),
|
||||
IrAnonymousInitializer {
|
||||
|
||||
@@ -37,17 +38,19 @@ class IrAnonymousInitializerImpl(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
origin: IrDeclarationOrigin,
|
||||
descriptor: ClassDescriptor
|
||||
descriptor: ClassDescriptor,
|
||||
isStatic: Boolean = false
|
||||
) :
|
||||
this(startOffset, endOffset, origin, IrAnonymousInitializerSymbolImpl(descriptor))
|
||||
this(startOffset, endOffset, origin, IrAnonymousInitializerSymbolImpl(descriptor), isStatic)
|
||||
|
||||
constructor(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
origin: IrDeclarationOrigin,
|
||||
descriptor: ClassDescriptor,
|
||||
body: IrBlockBody
|
||||
) : this(startOffset, endOffset, origin, descriptor) {
|
||||
body: IrBlockBody,
|
||||
isStatic: Boolean = false
|
||||
) : this(startOffset, endOffset, origin, descriptor, isStatic) {
|
||||
this.body = body
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class WithCompanion {
|
||||
companion object {
|
||||
var a = 0
|
||||
init {
|
||||
a++
|
||||
}
|
||||
@JvmField var b = a
|
||||
init {
|
||||
b++
|
||||
}
|
||||
val c = b
|
||||
}
|
||||
}
|
||||
|
||||
object Object {
|
||||
var a = 0
|
||||
init {
|
||||
a++
|
||||
}
|
||||
@JvmField var b = a
|
||||
init {
|
||||
b++
|
||||
}
|
||||
val c = b
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
assertEquals<Int>(2, WithCompanion.c, "Field WithCompanion.c")
|
||||
assertEquals<Int>(2, Object.c, "Field Object")
|
||||
return "OK"
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
// !LANGUAGE: +JvmFieldInInterface
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
|
||||
// FILE: Test.java
|
||||
|
||||
public class Test {
|
||||
public static String getField()
|
||||
{
|
||||
return new A().field;
|
||||
}
|
||||
public static String getCField()
|
||||
{
|
||||
return A.cfield;
|
||||
}
|
||||
public static String getObjectField()
|
||||
{
|
||||
return Object.field;
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: publicFieldJava.kt
|
||||
|
||||
class A {
|
||||
@JvmField public val field = "OK";
|
||||
|
||||
companion object {
|
||||
@JvmField public val cfield = "OK";
|
||||
}
|
||||
}
|
||||
|
||||
object Object {
|
||||
@JvmField public val field = "OK";
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
if (Test.getField() != "OK") return "fail 1: ${Test.getField()}"
|
||||
if (Test.getCField() != "OK") return "fail 2: ${Test.getCField()}"
|
||||
if (Test.getObjectField() != "OK") return "fail 3: ${Test.getObjectField()}"
|
||||
|
||||
return "OK"
|
||||
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||
// IGNORE_BACKEND: JS, NATIVE
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
object O {
|
||||
val mmmap = HashMap<String, Int>();
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
object A {
|
||||
val a = "OK"
|
||||
val b = A.a
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
class A(val result: String)
|
||||
|
||||
fun a(body: A.() -> String): String {
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
interface T
|
||||
|
||||
object Foo {
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
class Test {
|
||||
companion object {
|
||||
fun ok() = "OK"
|
||||
|
||||
Vendored
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
object Test {
|
||||
fun ok() = "OK"
|
||||
val x = run { Test.ok() }
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
class My {
|
||||
var my: String = "U"
|
||||
get() = { field }()
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||
// IGNORE_BACKEND: JS, NATIVE
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||
// IGNORE_BACKEND: JS, NATIVE
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||
// IGNORE_BACKEND: JS, NATIVE
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||
// IGNORE_BACKEND: JS, NATIVE
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||
// IGNORE_BACKEND: JS, NATIVE
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||
// IGNORE_BACKEND: JS, NATIVE
|
||||
|
||||
Vendored
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||
// IGNORE_BACKEND: JS, NATIVE
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||
// IGNORE_BACKEND: JS, NATIVE
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||
// IGNORE_BACKEND: JS, NATIVE
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
open class Bar<T>(val prop: String)
|
||||
class Foo {
|
||||
companion object : Bar<Foo>("OK") {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
open class Bar<T>(val prop: String)
|
||||
object Foo : Bar<Foo>("OK") {
|
||||
|
||||
|
||||
+10
@@ -13435,6 +13435,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/jvmField/constructorProperty.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("initializersOrder.kt")
|
||||
public void testInitializersOrder() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/jvmField/initializersOrder.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("interfaceCompanion.kt")
|
||||
public void testInterfaceCompanion() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/jvmField/interfaceCompanion.kt");
|
||||
@@ -13450,6 +13455,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/jvmField/publicField.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("publicFieldJava.kt")
|
||||
public void testPublicFieldJava() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/jvmField/publicFieldJava.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simpleMemberProperty.kt")
|
||||
public void testSimpleMemberProperty() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/jvmField/simpleMemberProperty.kt");
|
||||
|
||||
+10
@@ -13435,6 +13435,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/jvmField/constructorProperty.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("initializersOrder.kt")
|
||||
public void testInitializersOrder() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/jvmField/initializersOrder.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("interfaceCompanion.kt")
|
||||
public void testInterfaceCompanion() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/jvmField/interfaceCompanion.kt");
|
||||
@@ -13450,6 +13455,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/jvmField/publicField.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("publicFieldJava.kt")
|
||||
public void testPublicFieldJava() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/jvmField/publicFieldJava.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simpleMemberProperty.kt")
|
||||
public void testSimpleMemberProperty() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/jvmField/simpleMemberProperty.kt");
|
||||
|
||||
+10
@@ -13440,6 +13440,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/jvmField/constructorProperty.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("initializersOrder.kt")
|
||||
public void testInitializersOrder() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/jvmField/initializersOrder.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("interfaceCompanion.kt")
|
||||
public void testInterfaceCompanion() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/jvmField/interfaceCompanion.kt");
|
||||
@@ -13455,6 +13460,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/jvmField/publicField.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("publicFieldJava.kt")
|
||||
public void testPublicFieldJava() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/jvmField/publicFieldJava.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simpleMemberProperty.kt")
|
||||
public void testSimpleMemberProperty() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/jvmField/simpleMemberProperty.kt");
|
||||
|
||||
Reference in New Issue
Block a user