Added support for inline class members.

Inline constructors in particular.
This commit is contained in:
Alexander Gorshenev
2017-05-16 13:41:45 +03:00
committed by alexander-gorshenev
parent 2a246a9a3a
commit d4c34b29c1
13 changed files with 500 additions and 242 deletions
@@ -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<DeclarationDescriptor> {
var list = mutableListOf<DeclarationDescriptor>()
var current = this.containingDeclaration
while (current != null) {
list.add(current)
current = current.containingDeclaration
}
return list
}
internal fun DeclarationDescriptor.getMemberScope(): MemberScope {
val containingScope = when (this) {
@@ -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<DeclarationDescriptor> {
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<DeclarationDescriptor>,
descriptorProto: KonanIr.KotlinDescriptor):
DeserializedClassConstructorDescriptor {
val originalIndex = descriptorProto.originalIndex
return constructors.single {
it.uniqId == originalIndex
@@ -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)
@@ -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()
@@ -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;
}
}
@@ -25,6 +25,7 @@ extend Class {
extend Constructor {
repeated Annotation constructor_annotation = 170;
optional InlineIrBody inline_constructor_ir_body = 171;
}
extend Function {
@@ -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()
}
}
@@ -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<PropertyDescriptor, VariableDescriptor>()
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
@@ -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<DeclarationDescriptor> =
(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<Pair<DeserializationContext, MemberDeserializer>>()
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<ProtoBuf.TypeParameter>()
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)
@@ -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<KonanDescriptorSerializer>(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<PropertyDescriptor, VariableDescriptor>()
@@ -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<ProtoBuf.TypeParameter>
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")
}
@@ -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<IrLoop, Int>()
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<Int, IrLoop>()
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)
@@ -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)