Added support of inline properties.

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