From 39f2c3d7fb53075ede7f9551b659617ba00caff5 Mon Sep 17 00:00:00 2001 From: Alexander Gorshenev Date: Fri, 21 Apr 2017 18:38:06 +0300 Subject: [PATCH] Added support of inline properties. --- .../kotlin/backend/konan/descriptors/utils.kt | 27 +++++- .../serialization/IrDescriptorDeserializer.kt | 80 ++--------------- .../KonanDescriptorSerializer.kt | 7 +- .../backend/konan/serialization/KonanIr.proto | 2 +- .../konan/serialization/KonanLinkData.proto | 2 + .../serialization/KonanSerializerExtension.kt | 41 ++++++--- .../LocalDeclarationDeserializer.kt | 20 +++-- .../konan/serialization/ProtobufUtil.kt | 89 +++++++++++++++++++ .../konan/serialization/SerializeIr.kt | 41 ++++++--- .../konan/serialization/SerializerVisitor.kt | 15 ++-- .../kotlin/backend/konan/util/util.kt | 8 +- 11 files changed, 210 insertions(+), 122 deletions(-) create mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/ProtobufUtil.kt diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/utils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/utils.kt index 93ff220b9f1..9cb48f2e609 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/utils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/utils.kt @@ -16,9 +16,8 @@ package org.jetbrains.kotlin.backend.konan.descriptors -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.serialization.deserialization.descriptors.* import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.FqName @@ -58,4 +57,24 @@ fun DeclarationDescriptor.deepPrint() { internal val String.synthesizedName get() = Name.identifier(this.synthesizedString) -internal val String.synthesizedString get() = "\$$this" \ No newline at end of file +internal val String.synthesizedString get() = "\$$this" + + +internal val DeclarationDescriptor.propertyIfAccessor + get() = if (this is PropertyAccessorDescriptor) + this.correspondingProperty + else this + +internal val FunctionDescriptor.deserializedPropertyIfAccessor: DeserializedCallableMemberDescriptor + get() { + val member = this.propertyIfAccessor + if (member is DeserializedCallableMemberDescriptor) + return member + else + error("Unexpected deserializable callable descriptor") + } + +internal val DeclarationDescriptor.isDeserializableCallable + get () = (this.propertyIfAccessor is DeserializedCallableMemberDescriptor) + + diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/IrDescriptorDeserializer.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/IrDescriptorDeserializer.kt index cf82b4c578b..f8cc13ad9b6 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/IrDescriptorDeserializer.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/IrDescriptorDeserializer.kt @@ -20,7 +20,6 @@ import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.KonanIrDeserializationException import org.jetbrains.kotlin.backend.konan.descriptors.contributedMethods import org.jetbrains.kotlin.backend.konan.descriptors.isFunctionInvoke -import org.jetbrains.kotlin.backend.konan.llvm.symbolName import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.expressions.IrLoop @@ -33,99 +32,36 @@ import org.jetbrains.kotlin.serialization.KonanLinkData import org.jetbrains.kotlin.serialization.ProtoBuf import org.jetbrains.kotlin.serialization.deserialization.NameResolver import org.jetbrains.kotlin.serialization.deserialization.NameResolverImpl -import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassConstructorDescriptor -import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor -import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor +import org.jetbrains.kotlin.serialization.deserialization.descriptors.* import org.jetbrains.kotlin.types.KotlinType -fun newUniqId(index: Long): KonanLinkData.UniqId = - KonanLinkData.UniqId.newBuilder().setIndex(index).build() - -val ProtoBuf.Function.functionIndex: Long - get() = this.getExtension(KonanLinkData.functionIndex).index - -val ProtoBuf.Constructor.constructorIndex: Long - get() = this.getExtension(KonanLinkData.constructorIndex).index - -val ProtoBuf.Property.propertyIndex: Long - get() = this.getExtension(KonanLinkData.propertyIndex).index - - -fun ProtoBuf.Function.Builder.setFunctionIndex(index: Long) - = this.setExtension(KonanLinkData.functionIndex, newUniqId(index)) - -fun ProtoBuf.Constructor.Builder.setConstructorIndex(index: Long) - = this.setExtension(KonanLinkData.constructorIndex, newUniqId(index)) - -fun ProtoBuf.Property.Builder.setPropertyIndex(index: Long) - = this.setExtension(KonanLinkData.propertyIndex, newUniqId(index)) - -fun ProtoBuf.Class.Builder.setClassIndex(index: Long) - = this.setExtension(KonanLinkData.classIndex, newUniqId(index)) - - -val KonanIr.KotlinDescriptor.index: Long - get() = this.uniqId.index - -fun KonanIr.KotlinDescriptor.Builder.setIndex(index: Long) - = this.setUniqId(newUniqId(index)) - -val KonanIr.KotlinDescriptor.originalIndex: Long - get() = this.originalUniqId.index - -fun KonanIr.KotlinDescriptor.Builder.setOriginalIndex(index: Long) - = this.setOriginalUniqId(newUniqId(index)) - -val KonanIr.KotlinDescriptor.dispatchReceiverIndex: Long - get() = this.dispatchReceiverUniqId.index - -fun KonanIr.KotlinDescriptor.Builder.setDispatchReceiverIndex(index: Long) - = this.setDispatchReceiverUniqId(newUniqId(index)) - -val KonanIr.KotlinDescriptor.extensionReceiverIndex: Long - get() = this.extensionReceiverUniqId.index - -fun KonanIr.KotlinDescriptor.Builder.setExtensionReceiverIndex(index: Long) - = this.setExtensionReceiverUniqId(newUniqId(index)) - -internal fun printType(proto: ProtoBuf.Type) { - println("debug text: " + proto.getExtension(KonanLinkData.typeText)) -} - -internal fun printTypeTable(proto: ProtoBuf.TypeTable) { - proto.getTypeList().forEach { - printType(it) - } -} - internal fun DeclarationDescriptor.findPackage(): PackageFragmentDescriptor { return if (this is PackageFragmentDescriptor) this else this.containingDeclaration!!.findPackage() } -internal fun DeserializedSimpleFunctionDescriptor.nameTable(): ProtoBuf.QualifiedNameTable { +internal fun DeserializedMemberDescriptor.nameTable(): ProtoBuf.QualifiedNameTable { val pkg = this.findPackage() assert(pkg is KonanPackageFragment) return (pkg as KonanPackageFragment).proto.getNameTable() } -internal fun DeserializedSimpleFunctionDescriptor.nameResolver(): NameResolver { +internal fun DeserializedMemberDescriptor.nameResolver(): NameResolver { val pkg = this.findPackage() as KonanPackageFragment return NameResolverImpl(pkg.proto.getStringTable(), pkg.proto.getNameTable()) } - // This is the class that knowns how to deserialize // Kotlin descriptors and types for IR. internal class IrDescriptorDeserializer(val context: Context, - val rootFunction: DeserializedSimpleFunctionDescriptor, + val rootDescriptor: DeserializedCallableMemberDescriptor, val localDeserializer: LocalDeclarationDeserializer) { val loopIndex = mutableMapOf() - val nameResolver = rootFunction.nameResolver() as NameResolverImpl - val nameTable = rootFunction.nameTable() + val nameResolver = rootDescriptor.nameResolver() as NameResolverImpl + val nameTable = rootDescriptor.nameTable() val descriptorIndex = IrDeserializationDescriptorIndex(context.irBuiltIns).map fun deserializeKotlinType(proto: KonanIr.KotlinType): KotlinType { @@ -483,8 +419,8 @@ internal class IrDescriptorDeserializer(val context: Context, // copies for public descriptors if we know the substituted // descriptor is going to be the same. // But that's not a trivial thing to find out. - if (originalDescriptor == rootFunction) - return rootFunction + if (originalDescriptor == rootDescriptor) + return rootDescriptor return when (originalDescriptor) { is SimpleFunctionDescriptor -> 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 9064b75a481..bceeac2786b 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 @@ -229,7 +229,12 @@ class KonanDescriptorSerializer private constructor( builder.sinceKotlinInfo = writeSinceKotlinInfo(LanguageFeature.Coroutines) } - extension.serializeProperty(descriptor, builder) + if (extension is KonanSerializerExtension) { + extension.serializePropertyWithIR(descriptor, builder, {it -> typeId(it)}) + } else { + extension.serializeProperty(descriptor, builder) + } + return builder } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIr.proto b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIr.proto index 1a752bf1bb6..2f940a19bb2 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIr.proto +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIr.proto @@ -20,7 +20,7 @@ message KotlinDescriptor { RECEIVER = 7; ACCESSOR = 8; } - // TODO: Use the string table? + // TODO: Use the string table index. optional string name = 1; required Kind kind = 2; required UniqId uniq_id = 3; diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanLinkData.proto b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanLinkData.proto index e246d08daaf..1145838f9a4 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanLinkData.proto +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanLinkData.proto @@ -47,6 +47,8 @@ extend Property { optional int32 property_parent = 172; optional bool used_as_variable = 173; optional Annotation.Argument.Value compile_time_value = 174; + optional InlineIrBody inline_getter_ir_body = 175; + optional InlineIrBody inline_setter_ir_body = 176; } extend EnumEntry { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializerExtension.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializerExtension.kt index c662bcebd5a..8a941f078d1 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializerExtension.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializerExtension.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.backend.konan.serialization import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalClass import org.jetbrains.kotlin.backend.konan.descriptors.needsInlining +import org.jetbrains.kotlin.backend.konan.util.only import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.SourceElement import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl @@ -98,6 +99,18 @@ internal class KonanSerializerExtension(val context: Context, val util: KonanSer super.serializeClass(descriptor, proto) } + private fun serializeInlineBody(descriptor: FunctionDescriptor, typeSerializer: ((KotlinType)->Int)): KonanLinkData.InlineIrBody { + + val encodedIR = IrSerializer( + context, inlineDescriptorTable, stringTable, util, + typeSerializer, descriptor).serializeInlineBody() + + return KonanLinkData.InlineIrBody + .newBuilder() + .setEncodedIr(encodedIR) + .build() + } + override fun serializeFunction(descriptor: FunctionDescriptor, proto: ProtoBuf.Function.Builder) = serializeFunctionWithIR(descriptor, proto, null) fun serializeFunctionWithIR(descriptor: FunctionDescriptor, proto: ProtoBuf.Function.Builder, typeSerializer: ((KotlinType)->Int)?) { @@ -106,20 +119,11 @@ internal class KonanSerializerExtension(val context: Context, val util: KonanSer inlineDescriptorTable.indexByValue(descriptor)) val parentIndex = descriptor.parentFqNameIndex() proto.setExtension(KonanLinkData.functionParent, parentIndex) - if (descriptor.needsInlining) { - val encodedIR: String = IrSerializer( context, - inlineDescriptorTable, stringTable, util, typeSerializer!!, descriptor) - .serializeInlineBody() - - val inlineIrBody = KonanLinkData.InlineIrBody - .newBuilder() - .setEncodedIr(encodedIR) - .build() - - proto.setExtension(KonanLinkData.inlineIrBody, inlineIrBody) - + proto.setInlineIr( + serializeInlineBody(descriptor, typeSerializer!!)) } + super.serializeFunction(descriptor, proto) } @@ -129,8 +133,9 @@ internal class KonanSerializerExtension(val context: Context, val util: KonanSer private val backingFieldAnnotation = AnnotationDescriptorImpl( backingFieldClass, emptyMap(), SourceElement.NO_SOURCE) + override fun serializeProperty(descriptor: PropertyDescriptor, proto: ProtoBuf.Property.Builder) = serializePropertyWithIR(descriptor, proto, null) - override fun serializeProperty(descriptor: PropertyDescriptor, proto: ProtoBuf.Property.Builder) { + fun serializePropertyWithIR(descriptor: PropertyDescriptor, proto: ProtoBuf.Property.Builder, typeSerializer: ((KotlinType)->Int)?) { val parentIndex = descriptor.parentFqNameIndex() proto.setExtension(KonanLinkData.propertyParent, parentIndex) val variable = originalVariables[descriptor] @@ -144,6 +149,16 @@ internal class KonanSerializerExtension(val context: Context, val util: KonanSer inlineDescriptorTable.indexByValue(descriptor)) } + descriptor.getter?.only({needsInlining}) { + proto.setGetterIr( + serializeInlineBody(it, typeSerializer!!)) + } + + descriptor.setter?.only({needsInlining}) { + proto.setSetterIr( + serializeInlineBody(it, typeSerializer!!)) + } + super.serializeProperty(descriptor, proto) if (context.ir.propertiesWithBackingFields.contains(descriptor)) { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/LocalDeclarationDeserializer.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/LocalDeclarationDeserializer.kt index 07592e997bb..864b747855c 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/LocalDeclarationDeserializer.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/LocalDeclarationDeserializer.kt @@ -25,8 +25,7 @@ import org.jetbrains.kotlin.serialization.ProtoBuf.QualifiedNameTable.QualifiedN import org.jetbrains.kotlin.serialization.deserialization.MemberDeserializer import org.jetbrains.kotlin.serialization.deserialization.NameResolverImpl import org.jetbrains.kotlin.serialization.deserialization.TypeTable -import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor -import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor +import org.jetbrains.kotlin.serialization.deserialization.descriptors.* import org.jetbrains.kotlin.serialization.deserialization.descriptors.SinceKotlinInfoTable import org.jetbrains.kotlin.serialization.deserialization.findClassAcrossModuleDependencies import org.jetbrains.kotlin.types.KotlinType @@ -35,9 +34,9 @@ import org.jetbrains.kotlin.types.KotlinType // MemberDeserializer to deserialize descriptors declared in IR. // Consider merging it all to the very MemberDesereializer itself eventually. -class LocalDeclarationDeserializer(val rootFunction: FunctionDescriptor, val module: ModuleDescriptor) { +class LocalDeclarationDeserializer(val rootDescriptor: DeserializedCallableMemberDescriptor, val module: ModuleDescriptor) { - val pkg = rootFunction.getContainingDeclaration() as KonanPackageFragment + val pkg = rootDescriptor.getContainingDeclaration() as KonanPackageFragment init { assert(pkg is KonanPackageFragment) } @@ -49,8 +48,17 @@ class LocalDeclarationDeserializer(val rootFunction: FunctionDescriptor, val mod val context = components.createContext( pkg, nameResolver, typeTable, SinceKotlinInfoTable.EMPTY, null) - val typeParameterProtos = (rootFunction as DeserializedSimpleFunctionDescriptor).proto.typeParameterList - val childContext = context.childContext(rootFunction, typeParameterProtos, nameResolver, typeTable) + val typeParameterProtos = when (rootDescriptor) { + // These are two different typeParameterLists not + // having a common ancestor. + is DeserializedSimpleFunctionDescriptor + -> rootDescriptor.proto.typeParameterList + is DeserializedPropertyDescriptor + -> rootDescriptor.proto.typeParameterList + else -> error("Unexpected descriptor kind") + } + + val childContext = context.childContext(rootDescriptor, typeParameterProtos, nameResolver, typeTable) val typeDeserializer = childContext.typeDeserializer val memberDeserializer = MemberDeserializer(childContext) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/ProtobufUtil.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/ProtobufUtil.kt new file mode 100644 index 00000000000..e23063e4471 --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/ProtobufUtil.kt @@ -0,0 +1,89 @@ +package org.jetbrains.kotlin.backend.konan.serialization + +import org.jetbrains.kotlin.serialization.KonanIr +import org.jetbrains.kotlin.serialization.KonanLinkData +import org.jetbrains.kotlin.serialization.KonanLinkData.* +import org.jetbrains.kotlin.serialization.ProtoBuf + +fun newUniqId(index: Long): KonanLinkData.UniqId = + KonanLinkData.UniqId.newBuilder().setIndex(index).build() + +val ProtoBuf.Function.functionIndex: Long + get() = this.getExtension(KonanLinkData.functionIndex).index + +val ProtoBuf.Constructor.constructorIndex: Long + get() = this.getExtension(KonanLinkData.constructorIndex).index + +val ProtoBuf.Property.propertyIndex: Long + get() = this.getExtension(KonanLinkData.propertyIndex).index + + +fun ProtoBuf.Function.Builder.setFunctionIndex(index: Long) + = this.setExtension(KonanLinkData.functionIndex, newUniqId(index)) + +fun ProtoBuf.Constructor.Builder.setConstructorIndex(index: Long) + = this.setExtension(KonanLinkData.constructorIndex, newUniqId(index)) + +fun ProtoBuf.Property.Builder.setPropertyIndex(index: Long) + = this.setExtension(KonanLinkData.propertyIndex, newUniqId(index)) + +fun ProtoBuf.Class.Builder.setClassIndex(index: Long) + = this.setExtension(KonanLinkData.classIndex, newUniqId(index)) + +// ----------------------------------------------------------- + +val KonanIr.KotlinDescriptor.index: Long + get() = this.uniqId.index + +fun KonanIr.KotlinDescriptor.Builder.setIndex(index: Long) + = this.setUniqId(newUniqId(index)) + +val KonanIr.KotlinDescriptor.originalIndex: Long + get() = this.originalUniqId.index + +fun KonanIr.KotlinDescriptor.Builder.setOriginalIndex(index: Long) + = this.setOriginalUniqId(newUniqId(index)) + +val KonanIr.KotlinDescriptor.dispatchReceiverIndex: Long + get() = this.dispatchReceiverUniqId.index + +fun KonanIr.KotlinDescriptor.Builder.setDispatchReceiverIndex(index: Long) + = this.setDispatchReceiverUniqId(newUniqId(index)) + +val KonanIr.KotlinDescriptor.extensionReceiverIndex: Long + get() = this.extensionReceiverUniqId.index + +fun KonanIr.KotlinDescriptor.Builder.setExtensionReceiverIndex(index: Long) + = this.setExtensionReceiverUniqId(newUniqId(index)) + +// ----------------------------------------------------------- + +val ProtoBuf.Property.getterIr: InlineIrBody + get() = this.getExtension(inlineGetterIrBody) + +fun ProtoBuf.Property.Builder.setGetterIr(body: InlineIrBody): ProtoBuf.Property.Builder = + this.setExtension(inlineGetterIrBody, body) + +val ProtoBuf.Property.setterIr: InlineIrBody + get() = this.getExtension(inlineSetterIrBody) + +fun ProtoBuf.Property.Builder.setSetterIr(body: InlineIrBody): ProtoBuf.Property.Builder = + this.setExtension(inlineSetterIrBody, body) + +val ProtoBuf.Function.inlineIr: InlineIrBody + get() = this.getExtension(inlineIrBody) + +fun ProtoBuf.Function.Builder.setInlineIr(body: InlineIrBody): ProtoBuf.Function.Builder = + this.setExtension(inlineIrBody, body) + +internal fun printType(proto: ProtoBuf.Type) { + println("debug text: " + proto.getExtension(KonanLinkData.typeText)) +} + +internal fun printTypeTable(proto: ProtoBuf.TypeTable) { + proto.getTypeList().forEach { + printType(it) + } +} + + diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializeIr.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializeIr.kt index f18497ec54d..2bf69103f09 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializeIr.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializeIr.kt @@ -20,6 +20,7 @@ package org.jetbrains.kotlin.backend.konan.serialization import org.jetbrains.kotlin.backend.common.DeepCopyIrTreeWithDescriptors import org.jetbrains.kotlin.backend.common.ScopeWithIr import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.descriptors.* import org.jetbrains.kotlin.backend.konan.KonanIrDeserializationException import org.jetbrains.kotlin.backend.konan.ir.ir2string import org.jetbrains.kotlin.backend.konan.ir.ir2stringWhole @@ -41,7 +42,7 @@ import org.jetbrains.kotlin.serialization.KonanIr import org.jetbrains.kotlin.serialization.KonanIr.IrConst.ValueCase.* import org.jetbrains.kotlin.serialization.KonanIr.IrOperation.OperationCase.* import org.jetbrains.kotlin.serialization.KonanLinkData -import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor +import org.jetbrains.kotlin.serialization.deserialization.descriptors.* import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeProjectionImpl import org.jetbrains.kotlin.types.TypeSubstitutor @@ -572,15 +573,15 @@ internal class IrSerializer(val context: Context, // --------- Deserializer part ----------------------------- internal class IrDeserializer(val context: Context, - val rootFunction: DeserializedSimpleFunctionDescriptor) { + val rootFunction: FunctionDescriptor) { val loopIndex = mutableMapOf() - val localDeserializer = LocalDeclarationDeserializer(rootFunction, context.moduleDescriptor) + val rootMember = rootFunction.deserializedPropertyIfAccessor + val localDeserializer = LocalDeclarationDeserializer(rootMember, context.moduleDescriptor) val descriptorDeserializer = IrDescriptorDeserializer( - context, rootFunction, localDeserializer) - + context, rootMember, localDeserializer) fun deserializeKotlinType(proto: KonanIr.KotlinType) = descriptorDeserializer.deserializeKotlinType(proto) @@ -1047,7 +1048,7 @@ internal class IrDeserializer(val context: Context, // We run inline body deserializations after the public descriptor tree // deserialization is long gone. So we don't have the needed chain of // deserialization contexts available to take type parameters. - // So typeDeserializer introduces a brand new set of DeserializadTypeParameterDescriptor + // So typeDeserializer introduces a brand new set of DeserializadTypeParameterDescriptors // for the rootFunction. // This function takes the type parameters from the rootFunction descriptor // and substitutes them instead the deserialized ones. @@ -1058,9 +1059,12 @@ internal class IrDeserializer(val context: Context, val rootFunctionTypeParameters = descriptorDeserializer.localDeserializer.childContext.typeDeserializer.ownTypeParameters + val realTypeParameters = + rootFunction.deserializedPropertyIfAccessor.typeParameters + val substitutionContext = rootFunctionTypeParameters.mapIndexed{ index, param -> - Pair(param.typeConstructor, TypeProjectionImpl(rootFunction.typeParameters[index].defaultType)) + Pair(param.typeConstructor, TypeProjectionImpl(realTypeParameters[index].defaultType)) }.associate{ (key,value) -> key to value} @@ -1073,14 +1077,24 @@ internal class IrDeserializer(val context: Context, return copyFunctionDeclaration } - fun decodeDeclaration(): IrDeclaration { - val proto = rootFunction.proto - - if (!proto.hasExtension(KonanLinkData.inlineIrBody)) { - throw KonanIrDeserializationException("$rootFunction doesn't have ir serialized.") + val extractInlineProto: KonanLinkData.InlineIrBody + get() = when (rootFunction) { + is DeserializedSimpleFunctionDescriptor -> { + rootFunction.proto.inlineIr + } + is PropertyGetterDescriptor -> { + (rootMember as DeserializedPropertyDescriptor).proto.getterIr + } + is PropertySetterDescriptor -> { + (rootMember as DeserializedPropertyDescriptor).proto.setterIr + } + else -> error("Unexpected descriptor: rootFunction") } - val inlineProto = proto.getExtension(KonanLinkData.inlineIrBody) + fun decodeDeclaration(): IrDeclaration { + assert(rootFunction.isDeserializableCallable) + + val inlineProto = extractInlineProto val base64 = inlineProto.encodedIr val byteArray = base64Decode(base64) val irProto = KonanIr.IrDeclaration.parseFrom(byteArray, KonanSerializerProtocol.extensionRegistry) @@ -1091,4 +1105,3 @@ internal class IrDeserializer(val context: Context, return copyFunctionDeclaration } } - diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializerVisitor.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializerVisitor.kt index 1a0c513e5f7..cb42dc91898 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializerVisitor.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializerVisitor.kt @@ -18,9 +18,8 @@ package org.jetbrains.kotlin.backend.konan.ir import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor -import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.descriptors.DeclarationDescriptorVisitor +import org.jetbrains.kotlin.serialization.deserialization.descriptors.* +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns @@ -28,8 +27,7 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.backend.konan.descriptors.EmptyDescriptorVisitorVoid -import org.jetbrains.kotlin.backend.konan.descriptors.DeepVisitor -import org.jetbrains.kotlin.backend.konan.descriptors.needsInlining +import org.jetbrains.kotlin.backend.konan.descriptors.* import org.jetbrains.kotlin.backend.konan.serialization.* import org.jetbrains.kotlin.backend.konan.llvm.base64Encode import org.jetbrains.kotlin.backend.konan.llvm.base64Decode @@ -43,10 +41,7 @@ internal class DeserializerDriver(val context: Context) { internal fun deserializeInlineBody(descriptor: FunctionDescriptor): IrDeclaration? { if (!descriptor.needsInlining) return null - - if (descriptor !is DeserializedSimpleFunctionDescriptor) { - return null - } + if (!descriptor.isDeserializableCallable) return null var deserializedIr: IrDeclaration? = null PhaseManager(context).phase(KonanPhase.DESERIALIZER) { @@ -77,7 +72,7 @@ internal class DeserializerDriver(val context: Context) { inner class InlineBodyPrinter: EmptyDescriptorVisitorVoid() { override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, data: Unit): Boolean { - if (descriptor is DeserializedSimpleFunctionDescriptor) { + if (descriptor.isDeserializableCallable) { this@DeserializerDriver.deserializeInlineBody(descriptor) } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/util/util.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/util/util.kt index d03fceba95c..743c035b425 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/util/util.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/util/util.kt @@ -44,4 +44,10 @@ fun Collection.atMostOne(): T? { } } -inline fun Iterable.atMostOne(predicate: (T) -> Boolean): T? = this.filter(predicate).atMostOne() \ No newline at end of file +inline fun Iterable.atMostOne(predicate: (T) -> Boolean): T? = this.filter(predicate).atMostOne() + +fun T.only(condition: T.()->Boolean, then: (T)->Unit): T { + if (this.condition()) then(this) + return this +} +