diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt index 4a3bc9523a3..caa40536ecd 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt @@ -58,6 +58,7 @@ import kotlin.properties.Delegates internal class KonanIr(context: Context, irModule: IrModuleFragment): Ir(context, irModule) { val propertiesWithBackingFields = mutableSetOf() + val classesDelegatedBackingFields = mutableMapOf>() val originalModuleIndex = ModuleIndex(irModule) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/NewIrUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/NewIrUtils.kt index ee7bd6ca98e..0f304b0abf0 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/NewIrUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/NewIrUtils.kt @@ -102,7 +102,7 @@ val IrProperty.konanBackingField: IrField? this.endOffset, IrDeclarationOrigin.PROPERTY_BACKING_FIELD, backingFieldDescriptor, - this.getter!!.returnType // TODO: this copies the behaviour found in backing field descriptor creation, but both are incorrect for property delegation. + this.getter!!.returnType ).also { it.parent = this.parent } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt index d87b3c340e2..61d70bbbb04 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmDeclarations.kt @@ -139,10 +139,7 @@ private fun Context.getDeclaredFields(classDescriptor: ClassDescriptor): List): LLVMTypeRef { - val fieldTypes = fields.map { - @Suppress("DEPRECATION") - getLLVMType(if (it.isDelegate) context.irBuiltIns.anyNType else it.type) - } + val fieldTypes = fields.map { getLLVMType(it.type) } val classType = LLVMStructCreateNamed(LLVMGetModuleContext(context.llvmModule), name)!! diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/BackingFieldVisitor.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/BackingFieldVisitor.kt index 257ae19088b..f5ecfe9b883 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/BackingFieldVisitor.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/BackingFieldVisitor.kt @@ -17,8 +17,13 @@ package org.jetbrains.kotlin.backend.konan.serialization import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrField +import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrProperty +import org.jetbrains.kotlin.ir.util.parentAsClass import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid @@ -29,12 +34,24 @@ internal class BackingFieldVisitor(val context: Context) : IrElementVisitorVoid } override fun visitProperty(declaration: IrProperty) { - if (declaration.backingField == null) return - assert(declaration.backingField!!.descriptor - == declaration.descriptor || declaration.isDelegated) + if (declaration.isDelegated) { + val irClass = declaration.parent as? IrClass + val list = irClass?.let { context.ir.classesDelegatedBackingFields.getOrPut(irClass.descriptor) { mutableListOf() } } + list?.add(declaration.backingField!!.descriptor) + } + if (declaration.backingField == null || declaration.isDelegated) return + assert(declaration.backingField!!.descriptor == declaration.descriptor) context.ir.propertiesWithBackingFields.add(declaration.descriptor) } + + override fun visitClass(declaration: IrClass) { + declaration.declarations.filterIsInstance().forEach { + val list = context.ir.classesDelegatedBackingFields.getOrPut(declaration.descriptor) { mutableListOf() } + list.add(it.descriptor) + } + super.visitClass(declaration) + } } internal fun markBackingFields(context: Context) { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanDescriptorSerializer.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanDescriptorSerializer.kt index 4bd625a5ed7..37bbf2bcac5 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanDescriptorSerializer.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanDescriptorSerializer.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.serialization import org.jetbrains.kotlin.backend.common.onlyIf +import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.descriptors.needsSerializedIr import org.jetbrains.kotlin.backend.konan.serialization.IrAwareExtension import org.jetbrains.kotlin.backend.konan.serialization.KonanStringTable @@ -54,6 +55,7 @@ import java.io.ByteArrayOutputStream import java.util.* class KonanDescriptorSerializer private constructor( + private val context: Context, private val containingDeclaration: DeclarationDescriptor?, private val typeParameters: Interner, private val extension: SerializerExtension, @@ -64,7 +66,7 @@ class KonanDescriptorSerializer private constructor( private val contractSerializer = ContractSerializer() fun createChildSerializer(descriptor: DeclarationDescriptor): KonanDescriptorSerializer = - KonanDescriptorSerializer(descriptor, Interner(typeParameters), extension, typeTable, versionRequirementTable, + KonanDescriptorSerializer(context, descriptor, Interner(typeParameters), extension, typeTable, versionRequirementTable, serializeTypeTableToFunction = false) val stringTable: DescriptorAwareStringTable @@ -124,6 +126,10 @@ class KonanDescriptorSerializer private constructor( } } + context.ir.classesDelegatedBackingFields[classDescriptor]?.forEach { + builder.addProperty(propertyProto(it)) + } + val nestedClassifiers = sort(DescriptorUtils.getAllDescriptors(classDescriptor.unsubstitutedInnerClassesScope)) for (descriptor in nestedClassifiers) { if (descriptor is TypeAliasDescriptor) { @@ -735,29 +741,30 @@ class KonanDescriptorSerializer private constructor( companion object { @JvmStatic - fun createTopLevel(extension: SerializerExtension): KonanDescriptorSerializer { - return KonanDescriptorSerializer(null, Interner(), extension, MutableTypeTable(), MutableVersionRequirementTable(), + internal fun createTopLevel(context: Context, extension: SerializerExtension): KonanDescriptorSerializer { + return KonanDescriptorSerializer(context, null, Interner(), extension, MutableTypeTable(), MutableVersionRequirementTable(), serializeTypeTableToFunction = false) } @JvmStatic - fun createForLambda(extension: SerializerExtension): KonanDescriptorSerializer { - return KonanDescriptorSerializer(null, Interner(), extension, MutableTypeTable(), MutableVersionRequirementTable(), + internal fun createForLambda(context: Context, extension: SerializerExtension): KonanDescriptorSerializer { + return KonanDescriptorSerializer(context, null, Interner(), extension, MutableTypeTable(), MutableVersionRequirementTable(), serializeTypeTableToFunction = true) } @JvmStatic - fun create(descriptor: ClassDescriptor, extension: SerializerExtension): KonanDescriptorSerializer { + internal fun create(context: Context, descriptor: ClassDescriptor, extension: SerializerExtension): KonanDescriptorSerializer { val container = descriptor.containingDeclaration val parentSerializer = if (container is ClassDescriptor) - create(container, extension) + create(context, container, extension) else - createTopLevel(extension) + createTopLevel(context, extension) // Calculate type parameter ids for the outer class beforehand, as it would've had happened if we were always // serializing outer classes before nested classes. // Otherwise our interner can get wrong ids because we may serialize classes in any order. val serializer = KonanDescriptorSerializer( + context, descriptor, Interner(parentSerializer.typeParameters), parentSerializer.extension, diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializationUtil.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializationUtil.kt index 00bdfbab4dd..06914eff121 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializationUtil.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializationUtil.kt @@ -144,7 +144,7 @@ internal fun deserializeModule(languageVersionSettings: LanguageVersionSettings, internal class KonanSerializationUtil(val context: Context, metadataVersion: BinaryVersion) { val serializerExtension = KonanSerializerExtension(context, metadataVersion) - val topSerializer = KonanDescriptorSerializer.createTopLevel(serializerExtension) + val topSerializer = KonanDescriptorSerializer.createTopLevel(context, serializerExtension) var classSerializer: KonanDescriptorSerializer = topSerializer fun serializeClass(packageName: FqName, @@ -155,7 +155,7 @@ internal class KonanSerializationUtil(val context: Context, metadataVersion: Bin // TODO: this is to filter out object{}. Change me. if (classDescriptor.isExported()) - classSerializer = KonanDescriptorSerializer.create(classDescriptor, serializerExtension) + classSerializer = KonanDescriptorSerializer.create(context, classDescriptor, serializerExtension) val classProto = classSerializer.classProto(classDescriptor).build() ?: error("Class not serialized: $classDescriptor")