From d4c34b29c1250c0342a5a66688a81e9148ee042a Mon Sep 17 00:00:00 2001 From: Alexander Gorshenev Date: Tue, 16 May 2017 13:41:45 +0300 Subject: [PATCH] Added support for inline class members. Inline constructors in particular. --- .../konan/descriptors/DescriptorUtils.kt | 14 ++ .../serialization/IrDescriptorDeserializer.kt | 52 +++--- .../serialization/IrDescriptorSerializer.kt | 14 +- .../KonanDescriptorSerializer.kt | 25 ++- .../backend/konan/serialization/KonanIr.proto | 57 ++++-- .../konan/serialization/KonanLinkData.proto | 1 + .../serialization/KonanSerializationUtil.kt | 103 +++-------- .../serialization/KonanSerializerExtension.kt | 16 +- .../LocalDeclarationDeserializer.kt | 128 ++++++------- .../LocalDeclarationSerializer.kt | 133 ++++++++++++++ .../konan/serialization/ProtobufUtil.kt | 27 +++ .../konan/serialization/SerializeIr.kt | 170 +++++++++++++----- .../konan/serialization/StringTableUtil.kt | 2 +- 13 files changed, 500 insertions(+), 242 deletions(-) create mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/LocalDeclarationSerializer.kt diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt index 44adb1e613d..81ede28b5de 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt @@ -296,6 +296,20 @@ internal fun FunctionDescriptor.bridgeDirectionsTo(overriddenDescriptor: Functio return ourDirections } +internal fun DeclarationDescriptor.findPackage(): PackageFragmentDescriptor { + return if (this is PackageFragmentDescriptor) this + else this.containingDeclaration!!.findPackage() +} + +internal fun DeclarationDescriptor.allContainingDeclarations(): List { + var list = mutableListOf() + var current = this.containingDeclaration + while (current != null) { + list.add(current) + current = current.containingDeclaration + } + return list +} internal fun DeclarationDescriptor.getMemberScope(): MemberScope { val containingScope = when (this) { 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 76c08cb297d..69402e46b8d 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,6 +20,7 @@ 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.descriptors.findPackage import org.jetbrains.kotlin.backend.konan.llvm.isExported import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.incremental.components.NoLookupLocation @@ -29,6 +30,7 @@ import org.jetbrains.kotlin.resolve.calls.tasks.createSynthesizedInvokes import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.serialization.KonanIr import org.jetbrains.kotlin.serialization.KonanIr.KotlinDescriptor +import org.jetbrains.kotlin.serialization.KonanIr.DeclarationDescriptor.DescriptorCase.* import org.jetbrains.kotlin.serialization.KonanLinkData import org.jetbrains.kotlin.serialization.ProtoBuf import org.jetbrains.kotlin.serialization.deserialization.NameResolver @@ -36,18 +38,12 @@ import org.jetbrains.kotlin.serialization.deserialization.NameResolverImpl import org.jetbrains.kotlin.serialization.deserialization.descriptors.* import org.jetbrains.kotlin.types.* -internal fun DeclarationDescriptor.findPackage(): PackageFragmentDescriptor { - return if (this is PackageFragmentDescriptor) this - else this.containingDeclaration!!.findPackage() -} - internal fun DeserializedMemberDescriptor.nameTable(): ProtoBuf.QualifiedNameTable { val pkg = this.findPackage() assert(pkg is KonanPackageFragment) return (pkg as KonanPackageFragment).proto.getNameTable() } - internal fun DeserializedMemberDescriptor.nameResolver(): NameResolver { val pkg = this.findPackage() as KonanPackageFragment return NameResolverImpl(pkg.proto.getStringTable(), pkg.proto.getNameTable()) @@ -68,9 +64,10 @@ internal class IrDescriptorDeserializer(val context: Context, fun deserializeKotlinType(proto: KonanIr.KotlinType): KotlinType { val index = proto.getIndex() val text = proto.getDebugText() - val typeProto = localDeserializer.typeTable[index] + val typeProto = localDeserializer.parentTypeTable[index] val type = localDeserializer.deserializeInlineType(typeProto) - if (type.isError) throw KonanIrDeserializationException("Could not deserialize KotlinType: $text $type") + if (type.isError) + throw KonanIrDeserializationException("Could not deserialize KotlinType: $text $type") val realType = if (proto.isCaptured) { unpackCapturedType(type) @@ -80,26 +77,24 @@ internal class IrDescriptorDeserializer(val context: Context, context.log{"### deserialized Kotlin Type index=$index, text=$text:\t$realType"} return realType } + fun deserializeLocalDeclaration(irProto: KonanIr.KotlinDescriptor): DeclarationDescriptor { val localDeclarationProto = irProto.irLocalDeclaration.descriptor - when { - localDeclarationProto.hasFunction() -> { - val index = irProto.index - val descriptor = localDeserializer.deserializeFunction(irProto) - descriptorIndex.put(index, descriptor) - return descriptor - } - - localDeclarationProto.hasProperty() -> { - val index = irProto.index - val descriptor = localDeserializer.deserializeProperty(irProto) - descriptorIndex.put(index, descriptor) - return descriptor - } - // TODO - // localDclarationProto.hasClazz() -> + val index = irProto.index + //val localDeserializer = LocalDeclarationDeserializer(parent) + val descriptor: DeclarationDescriptor = when(localDeclarationProto.descriptorCase) { + FUNCTION -> + localDeserializer.deserializeFunction(irProto) + PROPERTY -> + localDeserializer.deserializeProperty(irProto) + CLAZZ -> + localDeserializer.deserializeClass(irProto) + CONSTRUCTOR -> + localDeserializer.deserializeConstructor(irProto) else -> TODO("Unexpected descriptor kind") } + descriptorIndex.put(index, descriptor) + return descriptor } // Either (a substitution of) a public descriptor @@ -113,6 +108,10 @@ internal class IrDescriptorDeserializer(val context: Context, KonanIr.KotlinDescriptor.Kind.VALUE_PARAMETER, KonanIr.KotlinDescriptor.Kind.TYPE_PARAMETER, KonanIr.KotlinDescriptor.Kind.RECEIVER, + // Properties can only be found in local + // classes, so no need to look for them + // in the public descriptor tree. + KonanIr.KotlinDescriptor.Kind.PROPERTY, KonanIr.KotlinDescriptor.Kind.VARIABLE -> descriptorIndex[index]!! @@ -133,7 +132,6 @@ internal class IrDescriptorDeserializer(val context: Context, fun deserializeDescriptor(proto: KonanIr.KotlinDescriptor): DeclarationDescriptor { context.log{"### deserializeDescriptor ${proto.kind} ${proto.index}"} - val descriptor = if (proto.hasIrLocalDeclaration()) { deserializeLocalDeclaration(proto) } else @@ -146,7 +144,7 @@ internal class IrDescriptorDeserializer(val context: Context, // Now there are several descriptors that automatically // recreated in addition to this one. Register them // all too. - + if (descriptor is FunctionDescriptor) { registerParameterDescriptors(proto, descriptor) } @@ -307,7 +305,6 @@ internal class IrDescriptorDeserializer(val context: Context, fun matchNameInParentScope(proto: KonanIr.KotlinDescriptor): Collection { val classOrPackage = proto.classOrPackage val name = proto.name - when (proto.kind) { KotlinDescriptor.Kind.CLASS -> { val parentScope = @@ -362,7 +359,6 @@ internal class IrDescriptorDeserializer(val context: Context, constructors: Collection, descriptorProto: KonanIr.KotlinDescriptor): DeserializedClassConstructorDescriptor { - val originalIndex = descriptorProto.originalIndex return constructors.single { it.uniqId == originalIndex diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/IrDescriptorSerializer.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/IrDescriptorSerializer.kt index a420bf813f0..ef398e65bb0 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/IrDescriptorSerializer.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/IrDescriptorSerializer.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.* import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.serialization.KonanDescriptorSerializer import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptor import org.jetbrains.kotlin.resolve.DescriptorUtils @@ -38,7 +39,7 @@ internal class IrDescriptorSerializer( val context: Context, val descriptorTable: DescriptorTable, val stringTable: KonanStringTable, - var typeSerializer: ((KotlinType)->Int), + val localDeclarationSerializer: LocalDeclarationSerializer, var rootFunction: FunctionDescriptor) { fun serializeKotlinType(type: KotlinType): KonanIr.KotlinType { @@ -48,7 +49,7 @@ internal class IrDescriptorSerializer( } else { type } - val index = typeSerializer(typeToSerialize) + val index = localDeclarationSerializer.typeSerializer(typeToSerialize) val proto = KonanIr.KotlinType.newBuilder() .setIndex(index) .setDebugText(type.toString()) @@ -76,7 +77,9 @@ internal class IrDescriptorSerializer( -> KonanIr.KotlinDescriptor.Kind.TYPE_PARAMETER is ReceiverParameterDescriptor -> KonanIr.KotlinDescriptor.Kind.RECEIVER - else -> TODO("Unexpected local descriptor.") + is PropertyDescriptor + -> KonanIr.KotlinDescriptor.Kind.PROPERTY + else -> TODO("Unexpected local descriptor: $descriptor") } fun functionDescriptorSpecifics(descriptor: FunctionDescriptor, proto: KonanIr.KotlinDescriptor.Builder) { @@ -89,7 +92,7 @@ internal class IrDescriptorSerializer( // natural order of declaration. Otherwise // they appear in the order of appearence in the // body of the function, and get wrong indices. - typeSerializer(it.defaultType) + localDeclarationSerializer.typeSerializer(it.defaultType) } descriptor.valueParameters.forEach { @@ -120,6 +123,7 @@ internal class IrDescriptorSerializer( fun variableDescriptorSpecifics(descriptor: VariableDescriptor, proto: KonanIr.KotlinDescriptor.Builder) { proto.setType(serializeKotlinType(descriptor.type)) + } fun serializeDescriptor(descriptor: DeclarationDescriptor): KonanIr.KotlinDescriptor { @@ -145,7 +149,7 @@ internal class IrDescriptorSerializer( context.log{"originalIndex = $originalIndex"} context.log{""} - val proto = KonanIr.KotlinDescriptor.newBuilder() + val proto = KonanIr.KotlinDescriptor.newBuilder() .setName(descriptor.name.asString()) .setKind(kotlinDescriptorKind(descriptor)) .setIndex(index) 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 e12cf306b96..9df0be9c977 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 @@ -54,7 +54,7 @@ class KonanDescriptorSerializer private constructor( }.toByteArray() } - private fun createChildSerializer(descriptor: DeclarationDescriptor): KonanDescriptorSerializer = + fun createChildSerializer(descriptor: DeclarationDescriptor): KonanDescriptorSerializer = KonanDescriptorSerializer(descriptor, Interner(typeParameters), extension, typeTable, sinceKotlinInfoTable, serializeTypeTableToFunction = false) @@ -230,11 +230,11 @@ class KonanDescriptorSerializer private constructor( if (extension is IrAwareExtension) { descriptor.getter?.onlyIf({needsSerializedIr}) { extension.addGetterIR(builder, - extension.serializeInlineBody(it, {it -> typeId(it)})) + extension.serializeInlineBody(it, local)) } descriptor.setter?.onlyIf({needsSerializedIr}) { extension.addSetterIR(builder, - extension.serializeInlineBody(it, {it -> typeId(it)})) + extension.serializeInlineBody(it, local)) } } @@ -295,10 +295,10 @@ class KonanDescriptorSerializer private constructor( extension.serializeFunction(descriptor, builder) - if (extension is IrAwareExtension - && descriptor.needsSerializedIr) { - extension.addFunctionIR(builder, - extension.serializeInlineBody(descriptor, {it -> typeId(it)})) + if (extension is IrAwareExtension + && descriptor.needsSerializedIr) { + extension.addFunctionIR(builder, + extension.serializeInlineBody(descriptor, local)) } return builder @@ -324,6 +324,12 @@ class KonanDescriptorSerializer private constructor( extension.serializeConstructor(descriptor, builder) + if (extension is IrAwareExtension + && descriptor.needsSerializedIr) { + extension.addConstructorIR(builder, + extension.serializeInlineBody(descriptor, local)) + } + return builder } @@ -447,7 +453,10 @@ class KonanDescriptorSerializer private constructor( return builder } - public fun typeId(type: KotlinType): Int = typeTable[type(type)] + public fun typeId(type: KotlinType): Int { + val result = typeTable[type(type)] + return result + } private fun type(type: KotlinType): ProtoBuf.Type.Builder { val builder = ProtoBuf.Type.newBuilder() 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 22d70932516..86bbc11433a 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 @@ -19,6 +19,7 @@ message KotlinDescriptor { TYPE_PARAMETER = 6; RECEIVER = 7; ACCESSOR = 8; + PROPERTY = 9; } // TODO: Use the string table index. optional string name = 1; @@ -150,6 +151,16 @@ message IrGetEnumValue { required KotlinDescriptor descriptor = 2; } +message FieldAccessCommon { + required KotlinDescriptor descriptor = 1; + optional KotlinDescriptor super = 2; + required IrExpression reciever = 3; +} + +message IrGetField { + required FieldAccessCommon field_access = 1; +} + message IrGetValue { required KotlinDescriptor descriptor = 1; } @@ -167,6 +178,11 @@ message IrReturn { required IrExpression value = 2; } +message IrSetField { + required FieldAccessCommon field_access = 1; + required IrExpression value = 2; +} + message IrSetVariable { required KotlinDescriptor descriptor = 1; required IrExpression value = 2; @@ -220,18 +236,20 @@ message IrOperation { IrDelegatingConstructorCall delegating_constructor_call = 7; IrEnumConstructorCall enum_constructor_call = 8; IrGetEnumValue get_enum_value = 9; - IrGetValue get_value = 10; - IrGetObject get_object = 11; - IrInstanceInitializerCall instance_initializer_call = 12; - IrReturn return = 13; - IrSetVariable set_variable = 14; - IrStringConcat string_concat = 15; - IrThrow throw = 16; - IrTry try = 17; - IrTypeOp type_op = 18; - IrVararg vararg = 19; - IrWhen when = 20; - IrWhile while = 21; + IrGetField get_field = 10; + IrGetValue get_value = 11; + IrGetObject get_object = 12; + IrInstanceInitializerCall instance_initializer_call = 13; + IrReturn return = 14; + IrSetField set_field = 15; + IrSetVariable set_variable = 16; + IrStringConcat string_concat = 17; + IrThrow throw = 18; + IrTry try = 19; + IrTypeOp type_op = 20; + IrVararg vararg = 21; + IrWhen when = 22; + IrWhile while = 23; } } @@ -254,7 +272,7 @@ message IrExpression { /* ------ Declarations --------------------------------------------- */ -message IrFunc { +message IrFunction { message DefaultArgument { required int32 position = 1; required IrExpression value = 2; @@ -263,6 +281,16 @@ message IrFunc { repeated DefaultArgument default_argument = 2; } +message IrProperty { + message IrField { + required IrExpression initializer = 1; + } + required bool is_delegated = 1; + optional IrField backing_field = 2; + optional IrFunction getter = 3; + optional IrFunction setter = 4; +} + message IrVar { optional IrExpression initializer = 1; } @@ -281,9 +309,10 @@ message IrEnumEntry { message IrDeclarator { oneof symbol { IrVar variable = 1; - IrFunc function = 2; + IrFunction function = 2; IrClass ir_class = 3; IrEnumEntry ir_enum_entry = 4; + IrProperty ir_property = 5; } } 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 e35f8afcc23..e50020599a5 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 @@ -25,6 +25,7 @@ extend Class { extend Constructor { repeated Annotation constructor_annotation = 170; + optional InlineIrBody inline_constructor_ir_body = 171; } extend Function { 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 34e42feec82..bb1f9c89dfc 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 @@ -21,14 +21,10 @@ import org.jetbrains.kotlin.backend.konan.LinkData import org.jetbrains.kotlin.backend.konan.KonanBuiltIns import org.jetbrains.kotlin.backend.konan.llvm.base64Decode import org.jetbrains.kotlin.backend.konan.llvm.base64Encode +import org.jetbrains.kotlin.backend.konan.llvm.isExported import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DECLARATION -import org.jetbrains.kotlin.descriptors.Modality.FINAL -import org.jetbrains.kotlin.descriptors.SourceElement.NO_SOURCE -import org.jetbrains.kotlin.descriptors.Visibilities.INTERNAL -import org.jetbrains.kotlin.descriptors.annotations.Annotations.Companion.EMPTY import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl @@ -41,7 +37,6 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.serialization.KonanDescriptorSerializer -import org.jetbrains.kotlin.serialization.KonanIr import org.jetbrains.kotlin.serialization.KonanLinkData import org.jetbrains.kotlin.serialization.ProtoBuf import org.jetbrains.kotlin.serialization.deserialization.* @@ -55,6 +50,17 @@ import java.io.InputStream import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream +/* + * This is Konan specific part of public descriptor + * tree serialization and deserialization. + * + * It takes care of module and package fragment serializations. + * The lower level (classes and members) serializations are delegated + * to the KonanDescriptorSerializer class. + * The lower level deserializations are performed by the frontend + * with MemberDeserializer class. + */ + typealias Base64 = String fun byteArrayToBase64(byteArray: ByteArray): Base64 { @@ -150,25 +156,32 @@ internal fun deserializeModule(configuration: CompilerConfiguration, internal class KonanSerializationUtil(val context: Context) { - val serializerExtension = KonanSerializerExtension(context, this) - val serializer = KonanDescriptorSerializer.createTopLevel(serializerExtension) - val typeSerializer: (KotlinType)->Int = { it -> serializer.typeId(it) } + val serializerExtension = KonanSerializerExtension(context) + val topSerializer = KonanDescriptorSerializer.createTopLevel(serializerExtension) + var classSerializer: KonanDescriptorSerializer = topSerializer fun serializeClass(packageName: FqName, builder: KonanLinkData.Classes.Builder, classDescriptor: ClassDescriptor) { - val localSerializer = KonanDescriptorSerializer.create(classDescriptor, serializerExtension) - val classProto = localSerializer.classProto(classDescriptor).build() + val previousSerializer = classSerializer + + // TODO: this is to filter out object{}. Change me. + if (classDescriptor.isExported()) + classSerializer = KonanDescriptorSerializer.create(classDescriptor, serializerExtension) + + val classProto = classSerializer.classProto(classDescriptor).build() ?: error("Class not serialized: $classDescriptor") builder.addClasses(classProto) - val index = localSerializer.stringTable.getFqNameIndex(classDescriptor) + val index = classSerializer.stringTable.getFqNameIndex(classDescriptor) builder.addClassName(index) serializeClasses(packageName, builder, classDescriptor.unsubstitutedInnerClassesScope .getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS)) + + classSerializer = previousSerializer } fun serializeClasses(packageName: FqName, @@ -208,7 +221,7 @@ internal class KonanSerializationUtil(val context: Context) { serializeClasses(fqName, classesBuilder, classifierDescriptors) val classesProto = classesBuilder.build() - val packageProto = serializer.packagePartProto(fqName, members).build() + val packageProto = topSerializer.packagePartProto(fqName, members).build() ?: error("Package fragments not serialized: $fragments") val strings = serializerExtension.stringTable @@ -263,69 +276,5 @@ internal class KonanSerializationUtil(val context: Context) { val library = byteArrayToBase64(libraryAsByteArray) return LinkData(library, fragments, fragmentNames) } - - /* The section below is specific for IR serialization */ - - // TODO: We utilize DescriptorSerializer's property - // serialization to serialize variables for now. - // Need to negotiate the ability to deserialize - // variables with the big kotlin somehow. - fun variableAsProperty(variable: VariableDescriptor): PropertyDescriptor { - - val isDelegated = when (variable) { - is LocalVariableDescriptor -> variable.isDelegated - is IrTemporaryVariableDescriptor -> false - else -> error("Unexpected variable descriptor.") - } - - val property = PropertyDescriptorImpl.create( - variable.containingDeclaration, - EMPTY, - FINAL, - INTERNAL, - variable.isVar(), - variable.name, - DECLARATION, - NO_SOURCE, - false, false, false, false, false, - isDelegated) - - property.setType(variable.type, listOf(), null, null as KotlinType?) - - // TODO: transform the getter and the setter too. - property.initialize(null, null) - return property - } - - fun serializeLocalDeclaration(descriptor: DeclarationDescriptor): KonanIr.DeclarationDescriptor { - - val proto = KonanIr.DeclarationDescriptor.newBuilder() - - context.log{"### serializeLocalDeclaration: $descriptor"} - - when (descriptor) { - is FunctionDescriptor -> - proto.setFunction(serializer.functionProto(descriptor)) - - is PropertyDescriptor -> - proto.setProperty(serializer.propertyProto(descriptor)) - - is ClassDescriptor -> - proto.setClazz(serializer.classProto(descriptor)) - - is VariableDescriptor -> { - val property = variableAsProperty(descriptor) - serializerExtension.originalVariables.put(property, descriptor) - proto.setProperty(serializer.propertyProto(property)) - } - - else -> error("Unexpected descriptor kind: $descriptor") - } - - return proto.build() - } - - - } 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 df03bb7dc28..9790c0f1d76 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 @@ -24,12 +24,10 @@ import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite import org.jetbrains.kotlin.serialization.* import org.jetbrains.kotlin.types.KotlinType - -internal class KonanSerializerExtension(val context: Context, val util: KonanSerializationUtil) : +internal class KonanSerializerExtension(val context: Context) : KotlinSerializerExtensionBase(KonanSerializerProtocol), IrAwareExtension { val inlineDescriptorTable = DescriptorTable(context.irBuiltIns) - val originalVariables = mutableMapOf() override val stringTable = KonanStringTable() override fun shouldUseTypeTable(): Boolean = true @@ -85,17 +83,19 @@ internal class KonanSerializerExtension(val context: Context, val util: KonanSer override fun addFunctionIR(proto: ProtoBuf.Function.Builder, serializedIR: String) = proto.setInlineIr(inlineBody(serializedIR)) + override fun addConstructorIR(proto: ProtoBuf.Constructor.Builder, serializedIR: String) + = proto.setConstructorIr(inlineBody(serializedIR)) + override fun addGetterIR(proto: ProtoBuf.Property.Builder, serializedIR: String) = proto.setGetterIr(inlineBody(serializedIR)) override fun addSetterIR(proto: ProtoBuf.Property.Builder, serializedIR: String) = proto.setSetterIr(inlineBody(serializedIR)) - override fun serializeInlineBody(descriptor: FunctionDescriptor, typeSerializer: ((KotlinType)->Int)): String { + override fun serializeInlineBody(descriptor: FunctionDescriptor, serializer: KonanDescriptorSerializer): String { return IrSerializer( - context, inlineDescriptorTable, stringTable, util, - typeSerializer, descriptor).serializeInlineBody() + context, inlineDescriptorTable, stringTable, serializer, descriptor).serializeInlineBody() } } @@ -117,10 +117,12 @@ object KonanSerializerProtocol : SerializerExtensionProtocol( internal interface IrAwareExtension { - fun serializeInlineBody(descriptor: FunctionDescriptor, typeSerializer: ((KotlinType)->Int)): String + fun serializeInlineBody(descriptor: FunctionDescriptor, serializer: KonanDescriptorSerializer): String fun addFunctionIR(proto: ProtoBuf.Function.Builder, serializedIR: String): ProtoBuf.Function.Builder + fun addConstructorIR(proto: ProtoBuf.Constructor.Builder, serializedIR: String): ProtoBuf.Constructor.Builder + fun addSetterIR(proto: ProtoBuf.Property.Builder, serializedIR: String): ProtoBuf.Property.Builder fun addGetterIR(proto: ProtoBuf.Property.Builder, serializedIR: String): ProtoBuf.Property.Builder 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 2910a1a6bff..1eaba7c6054 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 @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.backend.konan.serialization +import org.jetbrains.kotlin.backend.konan.descriptors.allContainingDeclarations import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor import org.jetbrains.kotlin.serialization.Flags @@ -23,96 +24,103 @@ import org.jetbrains.kotlin.serialization.KonanIr import org.jetbrains.kotlin.serialization.KonanLinkData import org.jetbrains.kotlin.serialization.ProtoBuf import org.jetbrains.kotlin.serialization.ProtoBuf.QualifiedNameTable.QualifiedName -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.* 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 +import org.jetbrains.kotlin.backend.common.peek +import org.jetbrains.kotlin.backend.common.push +import org.jetbrains.kotlin.backend.common.pop // This class knows how to construct contexts for // MemberDeserializer to deserialize descriptors declared in IR. -// Consider merging it all to the very MemberDesereializer itself eventually. +// Eventually, these descriptors shall be reconstructed from IR declarations, +// or may be just go away completely. -class LocalDeclarationDeserializer(val rootDescriptor: DeserializedCallableMemberDescriptor, val module: ModuleDescriptor) { - - val pkg = rootDescriptor.getContainingDeclaration() as KonanPackageFragment +class LocalDeclarationDeserializer(val rootDescriptor: DeclarationDescriptor) { + + val tower: List = + (listOf(rootDescriptor) + rootDescriptor.allContainingDeclarations()).reversed() init { - assert(pkg is KonanPackageFragment) + assert(tower.first() is ModuleDescriptor) } + val parents = tower.drop(1) + val pkg = parents.first() as KonanPackageFragment val components = pkg.components - val nameResolver = NameResolverImpl(pkg.proto.getStringTable(), pkg.proto.getNameTable()) - val nameTable = pkg.proto.getNameTable() - val typeTable = TypeTable(pkg.proto.getPackage().getTypeTable()) - val context = components.createContext( - pkg, nameResolver, typeTable, SinceKotlinInfoTable.EMPTY, null) + val nameTable = pkg.proto.nameTable + val nameResolver = NameResolverImpl(pkg.proto.stringTable, nameTable) + + val contextStack = mutableListOf>() - 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") + init { + parents.forEach{ + pushContext(it) + } } - val childContext = context.childContext(rootDescriptor, typeParameterProtos, nameResolver, typeTable) - val typeDeserializer = childContext.typeDeserializer + val parentContext: DeserializationContext + get() = contextStack.peek()!!.first - val memberDeserializer = MemberDeserializer(childContext) + val parentTypeTable: TypeTable + get() = parentContext.typeTable + + val typeDeserializer: TypeDeserializer + get() = parentContext.typeDeserializer + + val memberDeserializer: MemberDeserializer + get() = contextStack.peek()!!.second + + fun newContext(descriptor: DeclarationDescriptor): DeserializationContext { + if (descriptor is KonanPackageFragment) { + val packageTypeTable = TypeTable(pkg.proto.getPackage().typeTable) + return components.createContext( + pkg, nameResolver, packageTypeTable, SinceKotlinInfoTable.EMPTY, null) + } + + // Only packages and classes have their type tables. + val typeTable = if (descriptor is DeserializedClassDescriptor) { + TypeTable(descriptor.classProto.typeTable) + } else { + parentTypeTable + } + + + val oldContext = contextStack.peek()!!.first + + return oldContext.childContext(descriptor, + descriptor.typeParameterProtos, nameResolver, typeTable) + } + + fun pushContext(descriptor: DeclarationDescriptor) { + val newContext = newContext(descriptor) + contextStack.push(Pair(newContext, MemberDeserializer(newContext))) + } + + fun popContext(descriptor: DeclarationDescriptor) { + assert(contextStack.peek()!!.first.containingDeclaration == descriptor) + contextStack.pop() + } fun deserializeInlineType(type: ProtoBuf.Type): KotlinType { + val result = typeDeserializer.type(type) return result } - fun getDescriptorByFqNameIndex(module: ModuleDescriptor, fqNameIndex: Int): DeclarationDescriptor { + fun deserializeClass(irProto: KonanIr.KotlinDescriptor): ClassDescriptor { + return DeserializedClassDescriptor(parentContext, irProto.irLocalDeclaration.descriptor.clazz, nameResolver, SourceElement.NO_SOURCE) - val packageName = nameResolver.getPackageFqName(fqNameIndex) - // Here we using internals of NameresolverImpl. - val proto = nameTable.getQualifiedName(fqNameIndex) - when (proto.kind) { - QualifiedName.Kind.CLASS, - QualifiedName.Kind.LOCAL -> - return module.findClassAcrossModuleDependencies(nameResolver.getClassId(fqNameIndex))!! - QualifiedName.Kind.PACKAGE -> - return module.getPackage(packageName) - else -> TODO("Unexpected descriptor kind.") - } - } - fun memberDeserializerByParentFqNameIndex(fqNameIndex: Int): MemberDeserializer { - - val parent = getDescriptorByFqNameIndex(module, fqNameIndex) - val typeParameters = if (parent is DeserializedClassDescriptor) { - parent.classProto.typeParameterList - } else listOf() - - val childContext = context.childContext(parent, typeParameters, nameResolver, typeTable) - return MemberDeserializer(childContext) - - } - - private fun memberDeserializer(irProto: KonanIr.KotlinDescriptor): MemberDeserializer { - return if (irProto.hasClassOrPackage()) { - memberDeserializerByParentFqNameIndex(irProto.classOrPackage) - } else { - // TODO: learn to take the containing IR declaration - this.memberDeserializer - } } fun deserializeFunction(irProto: KonanIr.KotlinDescriptor): FunctionDescriptor = - memberDeserializer(irProto).loadFunction(irProto.irLocalDeclaration.descriptor.function) + memberDeserializer.loadFunction(irProto.irLocalDeclaration.descriptor.function) fun deserializeConstructor(irProto: KonanIr.KotlinDescriptor): ConstructorDescriptor { val proto = irProto.irLocalDeclaration.descriptor.constructor - val memberDeserializer = memberDeserializerByParentFqNameIndex(irProto.classOrPackage) val isPrimary = !Flags.IS_SECONDARY.get(proto.flags) val constructor = memberDeserializer.loadConstructor(proto, isPrimary) @@ -122,7 +130,7 @@ class LocalDeclarationDeserializer(val rootDescriptor: DeserializedCallableMembe fun deserializeProperty(irProto: KonanIr.KotlinDescriptor): VariableDescriptor { val proto = irProto.irLocalDeclaration.descriptor.property - val property = memberDeserializer(irProto).loadProperty(proto) + val property = memberDeserializer.loadProperty(proto) return if (proto.getExtension(KonanLinkData.usedAsVariable)) { propertyToVariable(property) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/LocalDeclarationSerializer.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/LocalDeclarationSerializer.kt new file mode 100644 index 00000000000..fab1ce514c2 --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/LocalDeclarationSerializer.kt @@ -0,0 +1,133 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.backend.konan.serialization + +import org.jetbrains.kotlin.backend.common.peek +import org.jetbrains.kotlin.backend.common.pop +import org.jetbrains.kotlin.backend.common.push +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DECLARATION +import org.jetbrains.kotlin.descriptors.Modality.FINAL +import org.jetbrains.kotlin.descriptors.SourceElement.NO_SOURCE +import org.jetbrains.kotlin.descriptors.Visibilities.INTERNAL +import org.jetbrains.kotlin.descriptors.annotations.Annotations.Companion.EMPTY +import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor +import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl +import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptor +import org.jetbrains.kotlin.serialization.KonanDescriptorSerializer +import org.jetbrains.kotlin.serialization.KonanIr +import org.jetbrains.kotlin.types.KotlinType + +/* + * This class knows how to create KonanDescriptorSerializer + * invocations to serialize function local declaration descriptors. + * Those descriptors are not part of the public descriptor tree. + * + * We maintain the stack of the serializers because this class + * provides type serialization facility for all the types in IR. + * And class serialization is context specific. + */ + +internal class LocalDeclarationSerializer(val context: Context, val rootFunctionSerializer: KonanDescriptorSerializer) { + + private val contextStack = mutableListOf(rootFunctionSerializer) + + fun pushContext(descriptor: DeclarationDescriptor) { + val previousContext = contextStack.peek()!! + val newSerializer = previousContext.createChildSerializer(descriptor) + contextStack.push(newSerializer) + } + + fun popContext(descriptor: DeclarationDescriptor) { + contextStack.pop() + } + + val localSerializer + get() = contextStack.peek()!! + + val typeSerializer: ((KotlinType)->Int) + get() = {it -> localSerializer.typeId(it)} + + fun serializeLocalDeclaration(descriptor: DeclarationDescriptor): KonanIr.DeclarationDescriptor { + + val proto = KonanIr.DeclarationDescriptor.newBuilder() + + context.log{"### serializeLocalDeclaration: $descriptor"} + + val parent = descriptor.classOrPackage + + + when (descriptor) { + is ClassConstructorDescriptor -> + proto.setConstructor(localSerializer.constructorProto(descriptor)) + + is FunctionDescriptor -> + proto.setFunction(localSerializer.functionProto(descriptor)) + + is PropertyDescriptor -> + proto.setProperty(localSerializer.propertyProto(descriptor)) + + is ClassDescriptor -> + proto.setClazz(localSerializer.classProto(descriptor)) + + is VariableDescriptor -> { + val property = variableAsProperty(descriptor) + originalVariables.put(property, descriptor) + proto.setProperty(localSerializer.propertyProto(property)) + } + + else -> error("Unexpected descriptor kind: $descriptor") + } + + return proto.build() + } + + // TODO: We utilize DescriptorSerializer's property + // serialization to serialize variables for now. + // Need to introduce an extension protobuf message + // and serialize variables directly. + fun variableAsProperty(variable: VariableDescriptor): PropertyDescriptor { + + val isDelegated = when (variable) { + is LocalVariableDescriptor -> variable.isDelegated + is IrTemporaryVariableDescriptor -> false + else -> error("Unexpected variable descriptor.") + } + + val property = PropertyDescriptorImpl.create( + variable.containingDeclaration, + EMPTY, + FINAL, + INTERNAL, + variable.isVar(), + variable.name, + DECLARATION, + NO_SOURCE, + false, false, false, false, false, + isDelegated) + + property.setType(variable.type, listOf(), null, null as KotlinType?) + + // TODO: transform the getter and the setter too. + property.initialize(null, null) + return property + } +} + +val originalVariables = mutableMapOf() + 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 index 88324894f9e..398adddd1c0 100644 --- 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 @@ -1,5 +1,7 @@ package org.jetbrains.kotlin.backend.konan.serialization +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.serialization.deserialization.descriptors.* import org.jetbrains.kotlin.serialization.KonanIr import org.jetbrains.kotlin.serialization.KonanLinkData import org.jetbrains.kotlin.serialization.KonanLinkData.* @@ -48,6 +50,12 @@ val ProtoBuf.Property.setterIr: InlineIrBody fun ProtoBuf.Property.Builder.setSetterIr(body: InlineIrBody): ProtoBuf.Property.Builder = this.setExtension(inlineSetterIrBody, body) +val ProtoBuf.Constructor.constructorIr: InlineIrBody + get() = this.getExtension(inlineConstructorIrBody) + +fun ProtoBuf.Constructor.Builder.setConstructorIr(body: InlineIrBody): ProtoBuf.Constructor.Builder = + this.setExtension(inlineConstructorIrBody, body) + val ProtoBuf.Function.inlineIr: InlineIrBody get() = this.getExtension(inlineIrBody) @@ -74,4 +82,23 @@ internal fun printTypeTable(proto: ProtoBuf.TypeTable) { } } +// ----------------------------------------------------------- + +internal val DeclarationDescriptor.typeParameterProtos: List + get() = when (this) { + // These are different typeParameterLists not + // having a common ancestor. + is DeserializedSimpleFunctionDescriptor + -> this.proto.typeParameterList + is DeserializedPropertyDescriptor + -> this.proto.typeParameterList + is DeserializedClassDescriptor + -> this.classProto.typeParameterList + is DeserializedTypeAliasDescriptor + -> this.proto.typeParameterList + is DeserializedClassConstructorDescriptor + -> listOf() + else -> error("Unexpected descriptor kind: $this") + } + 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 33cb55464b8..76c6329a50d 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 @@ -18,10 +18,9 @@ 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.descriptors.deserializedPropertyIfAccessor +import org.jetbrains.kotlin.backend.konan.descriptors.isDeserializableCallable import org.jetbrains.kotlin.backend.konan.ir.ir2string import org.jetbrains.kotlin.backend.konan.ir.ir2stringWhole import org.jetbrains.kotlin.backend.konan.llvm.base64Decode @@ -29,7 +28,6 @@ import org.jetbrains.kotlin.backend.konan.llvm.base64Encode import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement -import org.jetbrains.kotlin.ir.builders.Scope import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin.DEFINED import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl @@ -40,11 +38,14 @@ import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.impl.createFunctionSymbol import org.jetbrains.kotlin.ir.util.createParameterDeclarations +import org.jetbrains.kotlin.serialization.KonanDescriptorSerializer 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.* +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.types.KotlinType import org.jetbrains.kotlin.types.TypeProjectionImpl import org.jetbrains.kotlin.types.TypeSubstitutor @@ -53,14 +54,16 @@ import org.jetbrains.kotlin.types.TypeSubstitutor internal class IrSerializer(val context: Context, val descriptorTable: DescriptorTable, val stringTable: KonanStringTable, - val util: KonanSerializationUtil, - val typeSerializer: ((KotlinType)->Int), + val rootFunctionSerializer: KonanDescriptorSerializer, var rootFunction: FunctionDescriptor) { val loopIndex = mutableMapOf() var currentLoopIndex = 0 - val irDescriptorSerializer = IrDescriptorSerializer(context, - descriptorTable, stringTable, typeSerializer, rootFunction) + val localDeclarationSerializer + = LocalDeclarationSerializer(context, rootFunctionSerializer) + val irDescriptorSerializer + = IrDescriptorSerializer(context, descriptorTable, + stringTable, localDeclarationSerializer, rootFunction) fun serializeInlineBody(): String { val declaration = context.ir.originalModuleIndex.functions[rootFunction]!! @@ -259,6 +262,24 @@ internal class IrSerializer(val context: Context, return proto.build() } + fun serializeFieldAccessCommon(expression: IrFieldAccessExpression): KonanIr.FieldAccessCommon { + val proto = KonanIr.FieldAccessCommon.newBuilder() + .setDescriptor(serializeDescriptor(expression.descriptor)) + val superQualifier = expression.superQualifier + if (superQualifier != null) + proto.setSuper(serializeDescriptor(superQualifier)) + val receiver = expression.receiver + if (receiver != null) + proto.setReciever(serializeExpression(receiver)) + return proto.build() + } + + fun serializeGetField(expression: IrGetField): KonanIr.IrGetField { + val proto = KonanIr.IrGetField.newBuilder() + .setFieldAccess(serializeFieldAccessCommon(expression)) + return proto.build() + } + fun serializeGetValue(expression: IrGetValue): KonanIr.IrGetValue { val proto = KonanIr.IrGetValue.newBuilder() .setDescriptor(serializeDescriptor(expression.descriptor)) @@ -286,6 +307,13 @@ internal class IrSerializer(val context: Context, return proto.build() } + fun serializeSetField(expression: IrSetField): KonanIr.IrSetField { + val proto = KonanIr.IrSetField.newBuilder() + .setFieldAccess(serializeFieldAccessCommon(expression)) + .setValue(serializeExpression(expression.value)) + return proto.build() + } + fun serializeSetVariable(expression: IrSetVariable): KonanIr.IrSetVariable { val proto = KonanIr.IrSetVariable.newBuilder() .setDescriptor(serializeDescriptor(expression.descriptor)) @@ -420,6 +448,7 @@ internal class IrSerializer(val context: Context, is IrContinue -> operationProto.setContinue(serializeContinue(expression)) is IrDelegatingConstructorCall -> operationProto.setDelegatingConstructorCall(serializeDelegatingConstructorCall(expression)) + is IrGetField -> operationProto.setGetField(serializeGetField(expression)) is IrGetValue -> operationProto.setGetValue(serializeGetValue(expression)) is IrGetEnumValue -> operationProto.setGetEnumValue(serializeGetEnumValue(expression)) @@ -428,6 +457,7 @@ internal class IrSerializer(val context: Context, is IrInstanceInitializerCall -> operationProto.setInstanceInitializerCall(serializeInstanceInitializerCall(expression)) is IrReturn -> operationProto.setReturn(serializeReturn(expression)) + is IrSetField -> operationProto.setSetField(serializeSetField(expression)) is IrSetVariable -> operationProto.setSetVariable(serializeSetVariable(expression)) is IrStringConcatenation -> operationProto.setStringConcat(serializeStringConcat(expression)) @@ -467,15 +497,15 @@ internal class IrSerializer(val context: Context, return proto.build() } - fun serializeFunction(function: IrFunction): KonanIr.IrFunc { - val proto = KonanIr.IrFunc.newBuilder() + fun serializeIrFunction(function: IrFunction): KonanIr.IrFunction { + val proto = KonanIr.IrFunction.newBuilder() val body = function.body if (body != null) proto.setBody(serializeStatement(body)) function.descriptor.valueParameters.forEachIndexed { index, it -> val default = function.getDefault(it) if (default != null) { - val pair = KonanIr.IrFunc.DefaultArgument.newBuilder() + val pair = KonanIr.IrFunction.DefaultArgument.newBuilder() pair.position = index pair.value = serializeExpression(default.expression) proto.addDefaultArgument(pair) @@ -485,7 +515,33 @@ internal class IrSerializer(val context: Context, return proto.build() } - fun serializeVariable(variable: IrVariable): KonanIr.IrVar { + fun serializeIrProperty(property: IrProperty): KonanIr.IrProperty { + val proto = KonanIr.IrProperty.newBuilder() + .setIsDelegated(property.isDelegated) + val backingField = property.backingField + val getter = property.getter + val setter = property.setter + if (backingField != null) + proto.setBackingField(serializeIrField(backingField)) + if (getter != null) + proto.setGetter(serializeIrFunction(getter)) + if (setter != null) + proto.setSetter(serializeIrFunction(setter)) + + return proto.build() + } + + fun serializeIrField(field: IrField): KonanIr.IrProperty.IrField { + val proto = KonanIr.IrProperty.IrField.newBuilder() + val field = field.initializer?.expression + if (field != null) { + proto.setInitializer( + serializeExpression(field)) + } + return proto.build() + } + + fun serializeIrVariable(variable: IrVariable): KonanIr.IrVar { val proto = KonanIr.IrVar.newBuilder() val initializer = variable.initializer if (initializer != null) { @@ -496,6 +552,12 @@ internal class IrSerializer(val context: Context, fun serializeIrClass(clazz: IrClass): KonanIr.IrClass { val proto = KonanIr.IrClass.newBuilder() + + // TODO: As of now we get here only for anonymous local objects. + // There is still some work needed to support them. + // Until it is done, let's pretend all IrClasses are empty. + // So that we don't have to deal with their type tables. + /* val declarations = clazz.declarations declarations.forEach { val descriptor = it.descriptor @@ -503,6 +565,7 @@ internal class IrSerializer(val context: Context, proto.addMember(serializeDeclaration(it)) } } + */ return proto.build() } @@ -521,20 +584,49 @@ internal class IrSerializer(val context: Context, context.log{"### serializing Declaration: ${ir2string(declaration)}"} val descriptor = declaration.descriptor + + if (descriptor != rootFunction && + !(declaration is IrVariable)) { + localDeclarationSerializer.pushContext(descriptor) + } + var kotlinDescriptor = serializeDescriptor(descriptor) + var realDescriptor: KonanIr.DeclarationDescriptor? = null + if (descriptor != rootFunction) { + realDescriptor = localDeclarationSerializer.serializeLocalDeclaration(descriptor) + } + val declarator = KonanIr.IrDeclarator.newBuilder() + + when (declaration) { + is IrFunction + -> declarator.setFunction(serializeIrFunction(declaration)) + is IrVariable + -> declarator.setVariable(serializeIrVariable(declaration)) + is IrClass + -> declarator.setIrClass(serializeIrClass(declaration)) + is IrEnumEntry + -> declarator.setIrEnumEntry(serializeIrEnumEntry(declaration)) + is IrProperty + -> declarator.setIrProperty(serializeIrProperty(declaration)) + else + -> { + TODO("Declaration serialization not supported yet: $declaration") + } + } + + if (!(declaration is IrVariable)) { + localDeclarationSerializer.popContext(descriptor) + } + if (descriptor != rootFunction) { - val realDescriptor = util.serializeLocalDeclaration(descriptor) val localDeclaration = KonanIr.LocalDeclaration .newBuilder() - .setDescriptor(realDescriptor) + .setDescriptor(realDescriptor!!) .build() kotlinDescriptor = kotlinDescriptor .toBuilder() .setIrLocalDeclaration(localDeclaration) .build() - } else if (descriptor is ClassDescriptor) { - // TODO - context.log{"Can't serialize local class declarations in inline functions yet"} } val coordinates = serializeCoordinates(declaration.startOffset, declaration.endOffset) @@ -543,22 +635,6 @@ internal class IrSerializer(val context: Context, .setDescriptor(kotlinDescriptor) .setCoordinates(coordinates) - val declarator = KonanIr.IrDeclarator.newBuilder() - - when (declaration) { - is IrFunction - -> declarator.setFunction(serializeFunction(declaration)) - is IrVariable - -> declarator.setVariable(serializeVariable(declaration)) - is IrClass - -> declarator.setIrClass(serializeIrClass(declaration)) - is IrEnumEntry - -> declarator.setIrEnumEntry(serializeIrEnumEntry(declaration)) - else - -> { - TODO("Declaration serialization not supported yet.") - } - } proto.setDeclarator(declarator) @@ -583,7 +659,7 @@ internal class IrDeserializer(val context: Context, val loopIndex = mutableMapOf() val rootMember = rootFunction.deserializedPropertyIfAccessor - val localDeserializer = LocalDeclarationDeserializer(rootMember, context.moduleDescriptor) + val localDeserializer = LocalDeclarationDeserializer(rootMember) val descriptorDeserializer = IrDescriptorDeserializer( context, rootMember, localDeserializer) @@ -656,7 +732,7 @@ internal class IrDeserializer(val context: Context, } } - context.log{"Deserialized statement: ${ir2string(element)}"} + context.log{"### Deserialized statement: ${ir2string(element)}"} return element } @@ -967,7 +1043,7 @@ internal class IrDeserializer(val context: Context, val operation = proto.getOperation() val expression = deserializeOperation(operation, start, end, type) - context.log{"Deserialized expression: ${ir2string(expression)}"} + context.log{"### Deserialized expression: ${ir2string(expression)}"} return expression } @@ -986,7 +1062,7 @@ internal class IrDeserializer(val context: Context, } - fun deserializeIrFunction(proto: KonanIr.IrFunc, descriptor: FunctionDescriptor, + fun deserializeIrFunction(proto: KonanIr.IrFunction, descriptor: FunctionDescriptor, start: Int, end: Int, origin: IrDeclarationOrigin): IrFunction { val body = deserializeStatement(proto.getBody()) @@ -1031,6 +1107,9 @@ internal class IrDeserializer(val context: Context, val descriptor = deserializeDescriptor(proto.descriptor) + if (!(descriptor is VariableDescriptor) && descriptor != rootFunction) + localDeserializer.pushContext(descriptor) + val start = proto.getCoordinates().getStartOffset() val end = proto.getCoordinates().getEndOffset() val origin = DEFINED // TODO: retore the real origins @@ -1053,7 +1132,10 @@ internal class IrDeserializer(val context: Context, TODO("Declaration deserialization not implemented") } } - context.log{"Deserialized declaration: ${ir2string(declaration)}"} + + if (!(descriptor is VariableDescriptor) && descriptor != rootFunction) + localDeserializer.popContext(descriptor) + context.log{"### Deserialized declaration: ${ir2string(declaration)}"} return declaration } @@ -1068,8 +1150,9 @@ internal class IrDeserializer(val context: Context, // I tried to copy over TypeDeserializaer, MemberDeserializer, // and the rest of what's needed, but it didn't work out. fun adaptDeserializedTypeParameters(declaration: IrDeclaration): IrDeclaration { + val rootFunctionTypeParameters = - descriptorDeserializer.localDeserializer.childContext.typeDeserializer.ownTypeParameters + localDeserializer.typeDeserializer.ownTypeParameters val realTypeParameters = rootFunction.deserializedPropertyIfAccessor.typeParameters @@ -1094,13 +1177,16 @@ internal class IrDeserializer(val context: Context, is DeserializedSimpleFunctionDescriptor -> { rootFunction.proto.inlineIr } + is DeserializedClassConstructorDescriptor -> { + rootFunction.proto.constructorIr + } is PropertyGetterDescriptor -> { (rootMember as DeserializedPropertyDescriptor).proto.getterIr } is PropertySetterDescriptor -> { (rootMember as DeserializedPropertyDescriptor).proto.setterIr } - else -> error("Unexpected descriptor: rootFunction") + else -> error("Unexpected descriptor: $rootFunction") } fun decodeDeclaration(): IrDeclaration { @@ -1110,7 +1196,7 @@ internal class IrDeserializer(val context: Context, val base64 = inlineProto.encodedIr val byteArray = base64Decode(base64) val irProto = KonanIr.IrDeclaration.parseFrom(byteArray, KonanSerializerProtocol.extensionRegistry) - val declaration = deserializeDeclaration(irProto) + val declaration = deserializeDeclaration(irProto) val copyFunctionDeclaration = adaptDeserializedTypeParameters(declaration) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/StringTableUtil.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/StringTableUtil.kt index 3ada7abe787..568a51d3111 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/StringTableUtil.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/StringTableUtil.kt @@ -32,8 +32,8 @@ internal fun NameResolverImpl.getDescriptorByFqNameIndex( nameTable: ProtoBuf.QualifiedNameTable, fqNameIndex: Int): DeclarationDescriptor { + if (fqNameIndex == -1) return module.getPackage(FqName.ROOT) val packageName = this.getPackageFqName(fqNameIndex) - if (packageName.isRoot) return module.getPackage(FqName.ROOT) // TODO: Here we are using internals of NameresolverImpl. // Consider extending NameResolver. val proto = nameTable.getQualifiedName(fqNameIndex)