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 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 { internal fun DeclarationDescriptor.getMemberScope(): MemberScope {
val containingScope = when (this) { 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.KonanIrDeserializationException
import org.jetbrains.kotlin.backend.konan.descriptors.contributedMethods import org.jetbrains.kotlin.backend.konan.descriptors.contributedMethods
import org.jetbrains.kotlin.backend.konan.descriptors.isFunctionInvoke 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.backend.konan.llvm.isExported
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation 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.resolve.scopes.MemberScope
import org.jetbrains.kotlin.serialization.KonanIr import org.jetbrains.kotlin.serialization.KonanIr
import org.jetbrains.kotlin.serialization.KonanIr.KotlinDescriptor 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.KonanLinkData
import org.jetbrains.kotlin.serialization.ProtoBuf import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.NameResolver 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.serialization.deserialization.descriptors.*
import org.jetbrains.kotlin.types.* 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 { internal fun DeserializedMemberDescriptor.nameTable(): ProtoBuf.QualifiedNameTable {
val pkg = this.findPackage() val pkg = this.findPackage()
assert(pkg is KonanPackageFragment) assert(pkg is KonanPackageFragment)
return (pkg as KonanPackageFragment).proto.getNameTable() return (pkg as KonanPackageFragment).proto.getNameTable()
} }
internal fun DeserializedMemberDescriptor.nameResolver(): NameResolver { internal fun DeserializedMemberDescriptor.nameResolver(): NameResolver {
val pkg = this.findPackage() as KonanPackageFragment val pkg = this.findPackage() as KonanPackageFragment
return NameResolverImpl(pkg.proto.getStringTable(), pkg.proto.getNameTable()) return NameResolverImpl(pkg.proto.getStringTable(), pkg.proto.getNameTable())
@@ -68,9 +64,10 @@ internal class IrDescriptorDeserializer(val context: Context,
fun deserializeKotlinType(proto: KonanIr.KotlinType): KotlinType { fun deserializeKotlinType(proto: KonanIr.KotlinType): KotlinType {
val index = proto.getIndex() val index = proto.getIndex()
val text = proto.getDebugText() val text = proto.getDebugText()
val typeProto = localDeserializer.typeTable[index] val typeProto = localDeserializer.parentTypeTable[index]
val type = localDeserializer.deserializeInlineType(typeProto) 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) { val realType = if (proto.isCaptured) {
unpackCapturedType(type) unpackCapturedType(type)
@@ -80,26 +77,24 @@ internal class IrDescriptorDeserializer(val context: Context,
context.log{"### deserialized Kotlin Type index=$index, text=$text:\t$realType"} context.log{"### deserialized Kotlin Type index=$index, text=$text:\t$realType"}
return realType return realType
} }
fun deserializeLocalDeclaration(irProto: KonanIr.KotlinDescriptor): DeclarationDescriptor { fun deserializeLocalDeclaration(irProto: KonanIr.KotlinDescriptor): DeclarationDescriptor {
val localDeclarationProto = irProto.irLocalDeclaration.descriptor val localDeclarationProto = irProto.irLocalDeclaration.descriptor
when { val index = irProto.index
localDeclarationProto.hasFunction() -> { //val localDeserializer = LocalDeclarationDeserializer(parent)
val index = irProto.index val descriptor: DeclarationDescriptor = when(localDeclarationProto.descriptorCase) {
val descriptor = localDeserializer.deserializeFunction(irProto) FUNCTION ->
descriptorIndex.put(index, descriptor) localDeserializer.deserializeFunction(irProto)
return descriptor PROPERTY ->
} localDeserializer.deserializeProperty(irProto)
CLAZZ ->
localDeclarationProto.hasProperty() -> { localDeserializer.deserializeClass(irProto)
val index = irProto.index CONSTRUCTOR ->
val descriptor = localDeserializer.deserializeProperty(irProto) localDeserializer.deserializeConstructor(irProto)
descriptorIndex.put(index, descriptor)
return descriptor
}
// TODO
// localDclarationProto.hasClazz() ->
else -> TODO("Unexpected descriptor kind") else -> TODO("Unexpected descriptor kind")
} }
descriptorIndex.put(index, descriptor)
return descriptor
} }
// Either (a substitution of) a public 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.VALUE_PARAMETER,
KonanIr.KotlinDescriptor.Kind.TYPE_PARAMETER, KonanIr.KotlinDescriptor.Kind.TYPE_PARAMETER,
KonanIr.KotlinDescriptor.Kind.RECEIVER, 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 -> KonanIr.KotlinDescriptor.Kind.VARIABLE ->
descriptorIndex[index]!! descriptorIndex[index]!!
@@ -133,7 +132,6 @@ internal class IrDescriptorDeserializer(val context: Context,
fun deserializeDescriptor(proto: KonanIr.KotlinDescriptor): DeclarationDescriptor { fun deserializeDescriptor(proto: KonanIr.KotlinDescriptor): DeclarationDescriptor {
context.log{"### deserializeDescriptor ${proto.kind} ${proto.index}"} context.log{"### deserializeDescriptor ${proto.kind} ${proto.index}"}
val descriptor = if (proto.hasIrLocalDeclaration()) { val descriptor = if (proto.hasIrLocalDeclaration()) {
deserializeLocalDeclaration(proto) deserializeLocalDeclaration(proto)
} else } else
@@ -146,7 +144,7 @@ internal class IrDescriptorDeserializer(val context: Context,
// Now there are several descriptors that automatically // Now there are several descriptors that automatically
// recreated in addition to this one. Register them // recreated in addition to this one. Register them
// all too. // all too.
if (descriptor is FunctionDescriptor) { if (descriptor is FunctionDescriptor) {
registerParameterDescriptors(proto, descriptor) registerParameterDescriptors(proto, descriptor)
} }
@@ -307,7 +305,6 @@ internal class IrDescriptorDeserializer(val context: Context,
fun matchNameInParentScope(proto: KonanIr.KotlinDescriptor): Collection<DeclarationDescriptor> { fun matchNameInParentScope(proto: KonanIr.KotlinDescriptor): Collection<DeclarationDescriptor> {
val classOrPackage = proto.classOrPackage val classOrPackage = proto.classOrPackage
val name = proto.name val name = proto.name
when (proto.kind) { when (proto.kind) {
KotlinDescriptor.Kind.CLASS -> { KotlinDescriptor.Kind.CLASS -> {
val parentScope = val parentScope =
@@ -362,7 +359,6 @@ internal class IrDescriptorDeserializer(val context: Context,
constructors: Collection<DeclarationDescriptor>, constructors: Collection<DeclarationDescriptor>,
descriptorProto: KonanIr.KotlinDescriptor): descriptorProto: KonanIr.KotlinDescriptor):
DeserializedClassConstructorDescriptor { DeserializedClassConstructorDescriptor {
val originalIndex = descriptorProto.originalIndex val originalIndex = descriptorProto.originalIndex
return constructors.single { return constructors.single {
it.uniqId == originalIndex 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.Context
import org.jetbrains.kotlin.backend.konan.descriptors.* import org.jetbrains.kotlin.backend.konan.descriptors.*
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.serialization.KonanDescriptorSerializer
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptor import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptor
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
@@ -38,7 +39,7 @@ internal class IrDescriptorSerializer(
val context: Context, val context: Context,
val descriptorTable: DescriptorTable, val descriptorTable: DescriptorTable,
val stringTable: KonanStringTable, val stringTable: KonanStringTable,
var typeSerializer: ((KotlinType)->Int), val localDeclarationSerializer: LocalDeclarationSerializer,
var rootFunction: FunctionDescriptor) { var rootFunction: FunctionDescriptor) {
fun serializeKotlinType(type: KotlinType): KonanIr.KotlinType { fun serializeKotlinType(type: KotlinType): KonanIr.KotlinType {
@@ -48,7 +49,7 @@ internal class IrDescriptorSerializer(
} else { } else {
type type
} }
val index = typeSerializer(typeToSerialize) val index = localDeclarationSerializer.typeSerializer(typeToSerialize)
val proto = KonanIr.KotlinType.newBuilder() val proto = KonanIr.KotlinType.newBuilder()
.setIndex(index) .setIndex(index)
.setDebugText(type.toString()) .setDebugText(type.toString())
@@ -76,7 +77,9 @@ internal class IrDescriptorSerializer(
-> KonanIr.KotlinDescriptor.Kind.TYPE_PARAMETER -> KonanIr.KotlinDescriptor.Kind.TYPE_PARAMETER
is ReceiverParameterDescriptor is ReceiverParameterDescriptor
-> KonanIr.KotlinDescriptor.Kind.RECEIVER -> 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) { fun functionDescriptorSpecifics(descriptor: FunctionDescriptor, proto: KonanIr.KotlinDescriptor.Builder) {
@@ -89,7 +92,7 @@ internal class IrDescriptorSerializer(
// natural order of declaration. Otherwise // natural order of declaration. Otherwise
// they appear in the order of appearence in the // they appear in the order of appearence in the
// body of the function, and get wrong indices. // body of the function, and get wrong indices.
typeSerializer(it.defaultType) localDeclarationSerializer.typeSerializer(it.defaultType)
} }
descriptor.valueParameters.forEach { descriptor.valueParameters.forEach {
@@ -120,6 +123,7 @@ internal class IrDescriptorSerializer(
fun variableDescriptorSpecifics(descriptor: VariableDescriptor, proto: KonanIr.KotlinDescriptor.Builder) { fun variableDescriptorSpecifics(descriptor: VariableDescriptor, proto: KonanIr.KotlinDescriptor.Builder) {
proto.setType(serializeKotlinType(descriptor.type)) proto.setType(serializeKotlinType(descriptor.type))
} }
fun serializeDescriptor(descriptor: DeclarationDescriptor): KonanIr.KotlinDescriptor { fun serializeDescriptor(descriptor: DeclarationDescriptor): KonanIr.KotlinDescriptor {
@@ -145,7 +149,7 @@ internal class IrDescriptorSerializer(
context.log{"originalIndex = $originalIndex"} context.log{"originalIndex = $originalIndex"}
context.log{""} context.log{""}
val proto = KonanIr.KotlinDescriptor.newBuilder() val proto = KonanIr.KotlinDescriptor.newBuilder()
.setName(descriptor.name.asString()) .setName(descriptor.name.asString())
.setKind(kotlinDescriptorKind(descriptor)) .setKind(kotlinDescriptorKind(descriptor))
.setIndex(index) .setIndex(index)
@@ -54,7 +54,7 @@ class KonanDescriptorSerializer private constructor(
}.toByteArray() }.toByteArray()
} }
private fun createChildSerializer(descriptor: DeclarationDescriptor): KonanDescriptorSerializer = fun createChildSerializer(descriptor: DeclarationDescriptor): KonanDescriptorSerializer =
KonanDescriptorSerializer(descriptor, Interner(typeParameters), extension, typeTable, sinceKotlinInfoTable, KonanDescriptorSerializer(descriptor, Interner(typeParameters), extension, typeTable, sinceKotlinInfoTable,
serializeTypeTableToFunction = false) serializeTypeTableToFunction = false)
@@ -230,11 +230,11 @@ class KonanDescriptorSerializer private constructor(
if (extension is IrAwareExtension) { if (extension is IrAwareExtension) {
descriptor.getter?.onlyIf({needsSerializedIr}) { descriptor.getter?.onlyIf({needsSerializedIr}) {
extension.addGetterIR(builder, extension.addGetterIR(builder,
extension.serializeInlineBody(it, {it -> typeId(it)})) extension.serializeInlineBody(it, local))
} }
descriptor.setter?.onlyIf({needsSerializedIr}) { descriptor.setter?.onlyIf({needsSerializedIr}) {
extension.addSetterIR(builder, 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) extension.serializeFunction(descriptor, builder)
if (extension is IrAwareExtension if (extension is IrAwareExtension
&& descriptor.needsSerializedIr) { && descriptor.needsSerializedIr) {
extension.addFunctionIR(builder, extension.addFunctionIR(builder,
extension.serializeInlineBody(descriptor, {it -> typeId(it)})) extension.serializeInlineBody(descriptor, local))
} }
return builder return builder
@@ -324,6 +324,12 @@ class KonanDescriptorSerializer private constructor(
extension.serializeConstructor(descriptor, builder) extension.serializeConstructor(descriptor, builder)
if (extension is IrAwareExtension
&& descriptor.needsSerializedIr) {
extension.addConstructorIR(builder,
extension.serializeInlineBody(descriptor, local))
}
return builder return builder
} }
@@ -447,7 +453,10 @@ class KonanDescriptorSerializer private constructor(
return builder 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 { private fun type(type: KotlinType): ProtoBuf.Type.Builder {
val builder = ProtoBuf.Type.newBuilder() val builder = ProtoBuf.Type.newBuilder()
@@ -19,6 +19,7 @@ message KotlinDescriptor {
TYPE_PARAMETER = 6; TYPE_PARAMETER = 6;
RECEIVER = 7; RECEIVER = 7;
ACCESSOR = 8; ACCESSOR = 8;
PROPERTY = 9;
} }
// TODO: Use the string table index. // TODO: Use the string table index.
optional string name = 1; optional string name = 1;
@@ -150,6 +151,16 @@ message IrGetEnumValue {
required KotlinDescriptor descriptor = 2; 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 { message IrGetValue {
required KotlinDescriptor descriptor = 1; required KotlinDescriptor descriptor = 1;
} }
@@ -167,6 +178,11 @@ message IrReturn {
required IrExpression value = 2; required IrExpression value = 2;
} }
message IrSetField {
required FieldAccessCommon field_access = 1;
required IrExpression value = 2;
}
message IrSetVariable { message IrSetVariable {
required KotlinDescriptor descriptor = 1; required KotlinDescriptor descriptor = 1;
required IrExpression value = 2; required IrExpression value = 2;
@@ -220,18 +236,20 @@ message IrOperation {
IrDelegatingConstructorCall delegating_constructor_call = 7; IrDelegatingConstructorCall delegating_constructor_call = 7;
IrEnumConstructorCall enum_constructor_call = 8; IrEnumConstructorCall enum_constructor_call = 8;
IrGetEnumValue get_enum_value = 9; IrGetEnumValue get_enum_value = 9;
IrGetValue get_value = 10; IrGetField get_field = 10;
IrGetObject get_object = 11; IrGetValue get_value = 11;
IrInstanceInitializerCall instance_initializer_call = 12; IrGetObject get_object = 12;
IrReturn return = 13; IrInstanceInitializerCall instance_initializer_call = 13;
IrSetVariable set_variable = 14; IrReturn return = 14;
IrStringConcat string_concat = 15; IrSetField set_field = 15;
IrThrow throw = 16; IrSetVariable set_variable = 16;
IrTry try = 17; IrStringConcat string_concat = 17;
IrTypeOp type_op = 18; IrThrow throw = 18;
IrVararg vararg = 19; IrTry try = 19;
IrWhen when = 20; IrTypeOp type_op = 20;
IrWhile while = 21; IrVararg vararg = 21;
IrWhen when = 22;
IrWhile while = 23;
} }
} }
@@ -254,7 +272,7 @@ message IrExpression {
/* ------ Declarations --------------------------------------------- */ /* ------ Declarations --------------------------------------------- */
message IrFunc { message IrFunction {
message DefaultArgument { message DefaultArgument {
required int32 position = 1; required int32 position = 1;
required IrExpression value = 2; required IrExpression value = 2;
@@ -263,6 +281,16 @@ message IrFunc {
repeated DefaultArgument default_argument = 2; 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 { message IrVar {
optional IrExpression initializer = 1; optional IrExpression initializer = 1;
} }
@@ -281,9 +309,10 @@ message IrEnumEntry {
message IrDeclarator { message IrDeclarator {
oneof symbol { oneof symbol {
IrVar variable = 1; IrVar variable = 1;
IrFunc function = 2; IrFunction function = 2;
IrClass ir_class = 3; IrClass ir_class = 3;
IrEnumEntry ir_enum_entry = 4; IrEnumEntry ir_enum_entry = 4;
IrProperty ir_property = 5;
} }
} }
@@ -25,6 +25,7 @@ extend Class {
extend Constructor { extend Constructor {
repeated Annotation constructor_annotation = 170; repeated Annotation constructor_annotation = 170;
optional InlineIrBody inline_constructor_ir_body = 171;
} }
extend Function { 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.KonanBuiltIns
import org.jetbrains.kotlin.backend.konan.llvm.base64Decode import org.jetbrains.kotlin.backend.konan.llvm.base64Decode
import org.jetbrains.kotlin.backend.konan.llvm.base64Encode 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.CompilerConfiguration
import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.* 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.LocalVariableDescriptor
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl 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.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.serialization.KonanDescriptorSerializer import org.jetbrains.kotlin.serialization.KonanDescriptorSerializer
import org.jetbrains.kotlin.serialization.KonanIr
import org.jetbrains.kotlin.serialization.KonanLinkData import org.jetbrains.kotlin.serialization.KonanLinkData
import org.jetbrains.kotlin.serialization.ProtoBuf import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.* import org.jetbrains.kotlin.serialization.deserialization.*
@@ -55,6 +50,17 @@ import java.io.InputStream
import java.io.ByteArrayInputStream import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream 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 typealias Base64 = String
fun byteArrayToBase64(byteArray: ByteArray): Base64 { fun byteArrayToBase64(byteArray: ByteArray): Base64 {
@@ -150,25 +156,32 @@ internal fun deserializeModule(configuration: CompilerConfiguration,
internal class KonanSerializationUtil(val context: Context) { internal class KonanSerializationUtil(val context: Context) {
val serializerExtension = KonanSerializerExtension(context, this) val serializerExtension = KonanSerializerExtension(context)
val serializer = KonanDescriptorSerializer.createTopLevel(serializerExtension) val topSerializer = KonanDescriptorSerializer.createTopLevel(serializerExtension)
val typeSerializer: (KotlinType)->Int = { it -> serializer.typeId(it) } var classSerializer: KonanDescriptorSerializer = topSerializer
fun serializeClass(packageName: FqName, fun serializeClass(packageName: FqName,
builder: KonanLinkData.Classes.Builder, builder: KonanLinkData.Classes.Builder,
classDescriptor: ClassDescriptor) { classDescriptor: ClassDescriptor) {
val localSerializer = KonanDescriptorSerializer.create(classDescriptor, serializerExtension) val previousSerializer = classSerializer
val classProto = localSerializer.classProto(classDescriptor).build()
// 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") ?: error("Class not serialized: $classDescriptor")
builder.addClasses(classProto) builder.addClasses(classProto)
val index = localSerializer.stringTable.getFqNameIndex(classDescriptor) val index = classSerializer.stringTable.getFqNameIndex(classDescriptor)
builder.addClassName(index) builder.addClassName(index)
serializeClasses(packageName, builder, serializeClasses(packageName, builder,
classDescriptor.unsubstitutedInnerClassesScope classDescriptor.unsubstitutedInnerClassesScope
.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS)) .getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS))
classSerializer = previousSerializer
} }
fun serializeClasses(packageName: FqName, fun serializeClasses(packageName: FqName,
@@ -208,7 +221,7 @@ internal class KonanSerializationUtil(val context: Context) {
serializeClasses(fqName, classesBuilder, classifierDescriptors) serializeClasses(fqName, classesBuilder, classifierDescriptors)
val classesProto = classesBuilder.build() val classesProto = classesBuilder.build()
val packageProto = serializer.packagePartProto(fqName, members).build() val packageProto = topSerializer.packagePartProto(fqName, members).build()
?: error("Package fragments not serialized: $fragments") ?: error("Package fragments not serialized: $fragments")
val strings = serializerExtension.stringTable val strings = serializerExtension.stringTable
@@ -263,69 +276,5 @@ internal class KonanSerializationUtil(val context: Context) {
val library = byteArrayToBase64(libraryAsByteArray) val library = byteArrayToBase64(libraryAsByteArray)
return LinkData(library, fragments, fragmentNames) 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.serialization.*
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
internal class KonanSerializerExtension(val context: Context) :
internal class KonanSerializerExtension(val context: Context, val util: KonanSerializationUtil) :
KotlinSerializerExtensionBase(KonanSerializerProtocol), IrAwareExtension { KotlinSerializerExtensionBase(KonanSerializerProtocol), IrAwareExtension {
val inlineDescriptorTable = DescriptorTable(context.irBuiltIns) val inlineDescriptorTable = DescriptorTable(context.irBuiltIns)
val originalVariables = mutableMapOf<PropertyDescriptor, VariableDescriptor>()
override val stringTable = KonanStringTable() override val stringTable = KonanStringTable()
override fun shouldUseTypeTable(): Boolean = true 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) override fun addFunctionIR(proto: ProtoBuf.Function.Builder, serializedIR: String)
= proto.setInlineIr(inlineBody(serializedIR)) = 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) override fun addGetterIR(proto: ProtoBuf.Property.Builder, serializedIR: String)
= proto.setGetterIr(inlineBody(serializedIR)) = proto.setGetterIr(inlineBody(serializedIR))
override fun addSetterIR(proto: ProtoBuf.Property.Builder, serializedIR: String) override fun addSetterIR(proto: ProtoBuf.Property.Builder, serializedIR: String)
= proto.setSetterIr(inlineBody(serializedIR)) = proto.setSetterIr(inlineBody(serializedIR))
override fun serializeInlineBody(descriptor: FunctionDescriptor, typeSerializer: ((KotlinType)->Int)): String { override fun serializeInlineBody(descriptor: FunctionDescriptor, serializer: KonanDescriptorSerializer): String {
return IrSerializer( return IrSerializer(
context, inlineDescriptorTable, stringTable, util, context, inlineDescriptorTable, stringTable, serializer, descriptor).serializeInlineBody()
typeSerializer, descriptor).serializeInlineBody()
} }
} }
@@ -117,10 +117,12 @@ object KonanSerializerProtocol : SerializerExtensionProtocol(
internal interface IrAwareExtension { 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 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 addSetterIR(proto: ProtoBuf.Property.Builder, serializedIR: String): ProtoBuf.Property.Builder
fun addGetterIR(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 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.*
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.kotlin.serialization.Flags 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.KonanLinkData
import org.jetbrains.kotlin.serialization.ProtoBuf import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.ProtoBuf.QualifiedNameTable.QualifiedName import org.jetbrains.kotlin.serialization.ProtoBuf.QualifiedNameTable.QualifiedName
import org.jetbrains.kotlin.serialization.deserialization.MemberDeserializer import org.jetbrains.kotlin.serialization.deserialization.*
import org.jetbrains.kotlin.serialization.deserialization.NameResolverImpl
import org.jetbrains.kotlin.serialization.deserialization.TypeTable
import org.jetbrains.kotlin.serialization.deserialization.descriptors.* import org.jetbrains.kotlin.serialization.deserialization.descriptors.*
import org.jetbrains.kotlin.serialization.deserialization.descriptors.SinceKotlinInfoTable 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.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 // This class knows how to construct contexts for
// MemberDeserializer to deserialize descriptors declared in IR. // 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) { class LocalDeclarationDeserializer(val rootDescriptor: DeclarationDescriptor) {
val pkg = rootDescriptor.getContainingDeclaration() as KonanPackageFragment val tower: List<DeclarationDescriptor> =
(listOf(rootDescriptor) + rootDescriptor.allContainingDeclarations()).reversed()
init { 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 components = pkg.components
val nameResolver = NameResolverImpl(pkg.proto.getStringTable(), pkg.proto.getNameTable()) val nameTable = pkg.proto.nameTable
val nameTable = pkg.proto.getNameTable() val nameResolver = NameResolverImpl(pkg.proto.stringTable, nameTable)
val typeTable = TypeTable(pkg.proto.getPackage().getTypeTable())
val context = components.createContext( val contextStack = mutableListOf<Pair<DeserializationContext, MemberDeserializer>>()
pkg, nameResolver, typeTable, SinceKotlinInfoTable.EMPTY, null)
val typeParameterProtos = when (rootDescriptor) { init {
// These are two different typeParameterLists not parents.forEach{
// having a common ancestor. pushContext(it)
is DeserializedSimpleFunctionDescriptor }
-> rootDescriptor.proto.typeParameterList
is DeserializedPropertyDescriptor
-> rootDescriptor.proto.typeParameterList
else -> error("Unexpected descriptor kind")
} }
val childContext = context.childContext(rootDescriptor, typeParameterProtos, nameResolver, typeTable) val parentContext: DeserializationContext
val typeDeserializer = childContext.typeDeserializer 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 { fun deserializeInlineType(type: ProtoBuf.Type): KotlinType {
val result = typeDeserializer.type(type) val result = typeDeserializer.type(type)
return result 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 = 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 { fun deserializeConstructor(irProto: KonanIr.KotlinDescriptor): ConstructorDescriptor {
val proto = irProto.irLocalDeclaration.descriptor.constructor val proto = irProto.irLocalDeclaration.descriptor.constructor
val memberDeserializer = memberDeserializerByParentFqNameIndex(irProto.classOrPackage)
val isPrimary = !Flags.IS_SECONDARY.get(proto.flags) val isPrimary = !Flags.IS_SECONDARY.get(proto.flags)
val constructor = memberDeserializer.loadConstructor(proto, isPrimary) val constructor = memberDeserializer.loadConstructor(proto, isPrimary)
@@ -122,7 +130,7 @@ class LocalDeclarationDeserializer(val rootDescriptor: DeserializedCallableMembe
fun deserializeProperty(irProto: KonanIr.KotlinDescriptor): VariableDescriptor { fun deserializeProperty(irProto: KonanIr.KotlinDescriptor): VariableDescriptor {
val proto = irProto.irLocalDeclaration.descriptor.property val proto = irProto.irLocalDeclaration.descriptor.property
val property = memberDeserializer(irProto).loadProperty(proto) val property = memberDeserializer.loadProperty(proto)
return if (proto.getExtension(KonanLinkData.usedAsVariable)) { return if (proto.getExtension(KonanLinkData.usedAsVariable)) {
propertyToVariable(property) 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 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.KonanIr
import org.jetbrains.kotlin.serialization.KonanLinkData import org.jetbrains.kotlin.serialization.KonanLinkData
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 = fun ProtoBuf.Property.Builder.setSetterIr(body: InlineIrBody): ProtoBuf.Property.Builder =
this.setExtension(inlineSetterIrBody, body) 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 val ProtoBuf.Function.inlineIr: InlineIrBody
get() = this.getExtension(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.DeepCopyIrTreeWithDescriptors
import org.jetbrains.kotlin.backend.common.ScopeWithIr
import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.descriptors.* import org.jetbrains.kotlin.backend.konan.descriptors.deserializedPropertyIfAccessor
import org.jetbrains.kotlin.backend.konan.KonanIrDeserializationException import org.jetbrains.kotlin.backend.konan.descriptors.isDeserializableCallable
import org.jetbrains.kotlin.backend.konan.ir.ir2string import org.jetbrains.kotlin.backend.konan.ir.ir2string
import org.jetbrains.kotlin.backend.konan.ir.ir2stringWhole import org.jetbrains.kotlin.backend.konan.ir.ir2stringWhole
import org.jetbrains.kotlin.backend.konan.llvm.base64Decode 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.descriptors.*
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement 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.*
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin.DEFINED import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin.DEFINED
import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl 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.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.impl.createFunctionSymbol import org.jetbrains.kotlin.ir.symbols.impl.createFunctionSymbol
import org.jetbrains.kotlin.ir.util.createParameterDeclarations 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
import org.jetbrains.kotlin.serialization.KonanIr.IrConst.ValueCase.* import org.jetbrains.kotlin.serialization.KonanIr.IrConst.ValueCase.*
import org.jetbrains.kotlin.serialization.KonanIr.IrOperation.OperationCase.* import org.jetbrains.kotlin.serialization.KonanIr.IrOperation.OperationCase.*
import org.jetbrains.kotlin.serialization.KonanLinkData 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.KotlinType
import org.jetbrains.kotlin.types.TypeProjectionImpl import org.jetbrains.kotlin.types.TypeProjectionImpl
import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.types.TypeSubstitutor
@@ -53,14 +54,16 @@ import org.jetbrains.kotlin.types.TypeSubstitutor
internal class IrSerializer(val context: Context, internal class IrSerializer(val context: Context,
val descriptorTable: DescriptorTable, val descriptorTable: DescriptorTable,
val stringTable: KonanStringTable, val stringTable: KonanStringTable,
val util: KonanSerializationUtil, val rootFunctionSerializer: KonanDescriptorSerializer,
val typeSerializer: ((KotlinType)->Int),
var rootFunction: FunctionDescriptor) { var rootFunction: FunctionDescriptor) {
val loopIndex = mutableMapOf<IrLoop, Int>() val loopIndex = mutableMapOf<IrLoop, Int>()
var currentLoopIndex = 0 var currentLoopIndex = 0
val irDescriptorSerializer = IrDescriptorSerializer(context, val localDeclarationSerializer
descriptorTable, stringTable, typeSerializer, rootFunction) = LocalDeclarationSerializer(context, rootFunctionSerializer)
val irDescriptorSerializer
= IrDescriptorSerializer(context, descriptorTable,
stringTable, localDeclarationSerializer, rootFunction)
fun serializeInlineBody(): String { fun serializeInlineBody(): String {
val declaration = context.ir.originalModuleIndex.functions[rootFunction]!! val declaration = context.ir.originalModuleIndex.functions[rootFunction]!!
@@ -259,6 +262,24 @@ internal class IrSerializer(val context: Context,
return proto.build() 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 { fun serializeGetValue(expression: IrGetValue): KonanIr.IrGetValue {
val proto = KonanIr.IrGetValue.newBuilder() val proto = KonanIr.IrGetValue.newBuilder()
.setDescriptor(serializeDescriptor(expression.descriptor)) .setDescriptor(serializeDescriptor(expression.descriptor))
@@ -286,6 +307,13 @@ internal class IrSerializer(val context: Context,
return proto.build() 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 { fun serializeSetVariable(expression: IrSetVariable): KonanIr.IrSetVariable {
val proto = KonanIr.IrSetVariable.newBuilder() val proto = KonanIr.IrSetVariable.newBuilder()
.setDescriptor(serializeDescriptor(expression.descriptor)) .setDescriptor(serializeDescriptor(expression.descriptor))
@@ -420,6 +448,7 @@ internal class IrSerializer(val context: Context,
is IrContinue -> operationProto.setContinue(serializeContinue(expression)) is IrContinue -> operationProto.setContinue(serializeContinue(expression))
is IrDelegatingConstructorCall is IrDelegatingConstructorCall
-> operationProto.setDelegatingConstructorCall(serializeDelegatingConstructorCall(expression)) -> operationProto.setDelegatingConstructorCall(serializeDelegatingConstructorCall(expression))
is IrGetField -> operationProto.setGetField(serializeGetField(expression))
is IrGetValue -> operationProto.setGetValue(serializeGetValue(expression)) is IrGetValue -> operationProto.setGetValue(serializeGetValue(expression))
is IrGetEnumValue is IrGetEnumValue
-> operationProto.setGetEnumValue(serializeGetEnumValue(expression)) -> operationProto.setGetEnumValue(serializeGetEnumValue(expression))
@@ -428,6 +457,7 @@ internal class IrSerializer(val context: Context,
is IrInstanceInitializerCall is IrInstanceInitializerCall
-> operationProto.setInstanceInitializerCall(serializeInstanceInitializerCall(expression)) -> operationProto.setInstanceInitializerCall(serializeInstanceInitializerCall(expression))
is IrReturn -> operationProto.setReturn(serializeReturn(expression)) is IrReturn -> operationProto.setReturn(serializeReturn(expression))
is IrSetField -> operationProto.setSetField(serializeSetField(expression))
is IrSetVariable -> operationProto.setSetVariable(serializeSetVariable(expression)) is IrSetVariable -> operationProto.setSetVariable(serializeSetVariable(expression))
is IrStringConcatenation is IrStringConcatenation
-> operationProto.setStringConcat(serializeStringConcat(expression)) -> operationProto.setStringConcat(serializeStringConcat(expression))
@@ -467,15 +497,15 @@ internal class IrSerializer(val context: Context,
return proto.build() return proto.build()
} }
fun serializeFunction(function: IrFunction): KonanIr.IrFunc { fun serializeIrFunction(function: IrFunction): KonanIr.IrFunction {
val proto = KonanIr.IrFunc.newBuilder() val proto = KonanIr.IrFunction.newBuilder()
val body = function.body val body = function.body
if (body != null) proto.setBody(serializeStatement(body)) if (body != null) proto.setBody(serializeStatement(body))
function.descriptor.valueParameters.forEachIndexed { index, it -> function.descriptor.valueParameters.forEachIndexed { index, it ->
val default = function.getDefault(it) val default = function.getDefault(it)
if (default != null) { if (default != null) {
val pair = KonanIr.IrFunc.DefaultArgument.newBuilder() val pair = KonanIr.IrFunction.DefaultArgument.newBuilder()
pair.position = index pair.position = index
pair.value = serializeExpression(default.expression) pair.value = serializeExpression(default.expression)
proto.addDefaultArgument(pair) proto.addDefaultArgument(pair)
@@ -485,7 +515,33 @@ internal class IrSerializer(val context: Context,
return proto.build() 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 proto = KonanIr.IrVar.newBuilder()
val initializer = variable.initializer val initializer = variable.initializer
if (initializer != null) { if (initializer != null) {
@@ -496,6 +552,12 @@ internal class IrSerializer(val context: Context,
fun serializeIrClass(clazz: IrClass): KonanIr.IrClass { fun serializeIrClass(clazz: IrClass): KonanIr.IrClass {
val proto = KonanIr.IrClass.newBuilder() 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 val declarations = clazz.declarations
declarations.forEach { declarations.forEach {
val descriptor = it.descriptor val descriptor = it.descriptor
@@ -503,6 +565,7 @@ internal class IrSerializer(val context: Context,
proto.addMember(serializeDeclaration(it)) proto.addMember(serializeDeclaration(it))
} }
} }
*/
return proto.build() return proto.build()
} }
@@ -521,20 +584,49 @@ internal class IrSerializer(val context: Context,
context.log{"### serializing Declaration: ${ir2string(declaration)}"} context.log{"### serializing Declaration: ${ir2string(declaration)}"}
val descriptor = declaration.descriptor val descriptor = declaration.descriptor
if (descriptor != rootFunction &&
!(declaration is IrVariable)) {
localDeclarationSerializer.pushContext(descriptor)
}
var kotlinDescriptor = serializeDescriptor(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) { if (descriptor != rootFunction) {
val realDescriptor = util.serializeLocalDeclaration(descriptor)
val localDeclaration = KonanIr.LocalDeclaration val localDeclaration = KonanIr.LocalDeclaration
.newBuilder() .newBuilder()
.setDescriptor(realDescriptor) .setDescriptor(realDescriptor!!)
.build() .build()
kotlinDescriptor = kotlinDescriptor kotlinDescriptor = kotlinDescriptor
.toBuilder() .toBuilder()
.setIrLocalDeclaration(localDeclaration) .setIrLocalDeclaration(localDeclaration)
.build() .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) val coordinates = serializeCoordinates(declaration.startOffset, declaration.endOffset)
@@ -543,22 +635,6 @@ internal class IrSerializer(val context: Context,
.setDescriptor(kotlinDescriptor) .setDescriptor(kotlinDescriptor)
.setCoordinates(coordinates) .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) proto.setDeclarator(declarator)
@@ -583,7 +659,7 @@ internal class IrDeserializer(val context: Context,
val loopIndex = mutableMapOf<Int, IrLoop>() val loopIndex = mutableMapOf<Int, IrLoop>()
val rootMember = rootFunction.deserializedPropertyIfAccessor val rootMember = rootFunction.deserializedPropertyIfAccessor
val localDeserializer = LocalDeclarationDeserializer(rootMember, context.moduleDescriptor) val localDeserializer = LocalDeclarationDeserializer(rootMember)
val descriptorDeserializer = IrDescriptorDeserializer( val descriptorDeserializer = IrDescriptorDeserializer(
context, rootMember, localDeserializer) 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 return element
} }
@@ -967,7 +1043,7 @@ internal class IrDeserializer(val context: Context,
val operation = proto.getOperation() val operation = proto.getOperation()
val expression = deserializeOperation(operation, start, end, type) val expression = deserializeOperation(operation, start, end, type)
context.log{"Deserialized expression: ${ir2string(expression)}"} context.log{"### Deserialized expression: ${ir2string(expression)}"}
return 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 { start: Int, end: Int, origin: IrDeclarationOrigin): IrFunction {
val body = deserializeStatement(proto.getBody()) val body = deserializeStatement(proto.getBody())
@@ -1031,6 +1107,9 @@ internal class IrDeserializer(val context: Context,
val descriptor = deserializeDescriptor(proto.descriptor) val descriptor = deserializeDescriptor(proto.descriptor)
if (!(descriptor is VariableDescriptor) && descriptor != rootFunction)
localDeserializer.pushContext(descriptor)
val start = proto.getCoordinates().getStartOffset() val start = proto.getCoordinates().getStartOffset()
val end = proto.getCoordinates().getEndOffset() val end = proto.getCoordinates().getEndOffset()
val origin = DEFINED // TODO: retore the real origins val origin = DEFINED // TODO: retore the real origins
@@ -1053,7 +1132,10 @@ internal class IrDeserializer(val context: Context,
TODO("Declaration deserialization not implemented") 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 return declaration
} }
@@ -1068,8 +1150,9 @@ internal class IrDeserializer(val context: Context,
// I tried to copy over TypeDeserializaer, MemberDeserializer, // I tried to copy over TypeDeserializaer, MemberDeserializer,
// and the rest of what's needed, but it didn't work out. // and the rest of what's needed, but it didn't work out.
fun adaptDeserializedTypeParameters(declaration: IrDeclaration): IrDeclaration { fun adaptDeserializedTypeParameters(declaration: IrDeclaration): IrDeclaration {
val rootFunctionTypeParameters = val rootFunctionTypeParameters =
descriptorDeserializer.localDeserializer.childContext.typeDeserializer.ownTypeParameters localDeserializer.typeDeserializer.ownTypeParameters
val realTypeParameters = val realTypeParameters =
rootFunction.deserializedPropertyIfAccessor.typeParameters rootFunction.deserializedPropertyIfAccessor.typeParameters
@@ -1094,13 +1177,16 @@ internal class IrDeserializer(val context: Context,
is DeserializedSimpleFunctionDescriptor -> { is DeserializedSimpleFunctionDescriptor -> {
rootFunction.proto.inlineIr rootFunction.proto.inlineIr
} }
is DeserializedClassConstructorDescriptor -> {
rootFunction.proto.constructorIr
}
is PropertyGetterDescriptor -> { is PropertyGetterDescriptor -> {
(rootMember as DeserializedPropertyDescriptor).proto.getterIr (rootMember as DeserializedPropertyDescriptor).proto.getterIr
} }
is PropertySetterDescriptor -> { is PropertySetterDescriptor -> {
(rootMember as DeserializedPropertyDescriptor).proto.setterIr (rootMember as DeserializedPropertyDescriptor).proto.setterIr
} }
else -> error("Unexpected descriptor: rootFunction") else -> error("Unexpected descriptor: $rootFunction")
} }
fun decodeDeclaration(): IrDeclaration { fun decodeDeclaration(): IrDeclaration {
@@ -1110,7 +1196,7 @@ internal class IrDeserializer(val context: Context,
val base64 = inlineProto.encodedIr val base64 = inlineProto.encodedIr
val byteArray = base64Decode(base64) val byteArray = base64Decode(base64)
val irProto = KonanIr.IrDeclaration.parseFrom(byteArray, KonanSerializerProtocol.extensionRegistry) val irProto = KonanIr.IrDeclaration.parseFrom(byteArray, KonanSerializerProtocol.extensionRegistry)
val declaration = deserializeDeclaration(irProto) val declaration = deserializeDeclaration(irProto)
val copyFunctionDeclaration = adaptDeserializedTypeParameters(declaration) val copyFunctionDeclaration = adaptDeserializedTypeParameters(declaration)
@@ -32,8 +32,8 @@ internal fun NameResolverImpl.getDescriptorByFqNameIndex(
nameTable: ProtoBuf.QualifiedNameTable, nameTable: ProtoBuf.QualifiedNameTable,
fqNameIndex: Int): DeclarationDescriptor { fqNameIndex: Int): DeclarationDescriptor {
if (fqNameIndex == -1) return module.getPackage(FqName.ROOT)
val packageName = this.getPackageFqName(fqNameIndex) val packageName = this.getPackageFqName(fqNameIndex)
if (packageName.isRoot) return module.getPackage(FqName.ROOT)
// TODO: Here we are using internals of NameresolverImpl. // TODO: Here we are using internals of NameresolverImpl.
// Consider extending NameResolver. // Consider extending NameResolver.
val proto = nameTable.getQualifiedName(fqNameIndex) val proto = nameTable.getQualifiedName(fqNameIndex)