Initial support of enums in IR serialization.

This commit is contained in:
Alexander Gorshenev
2017-03-30 02:14:14 +03:00
committed by alexander-gorshenev
parent a368818863
commit aa7e3f40fd
3 changed files with 154 additions and 81 deletions
@@ -124,6 +124,7 @@ internal class IrDescriptorDeserializer(val context: Context,
KonanIr.KotlinDescriptor.Kind.VARIABLE -> KonanIr.KotlinDescriptor.Kind.VARIABLE ->
descriptorIndex[index]!! descriptorIndex[index]!!
KonanIr.KotlinDescriptor.Kind.CLASS,
KonanIr.KotlinDescriptor.Kind.CONSTRUCTOR, KonanIr.KotlinDescriptor.Kind.CONSTRUCTOR,
KonanIr.KotlinDescriptor.Kind.FUNCTION, KonanIr.KotlinDescriptor.Kind.FUNCTION,
KonanIr.KotlinDescriptor.Kind.ACCESSOR -> { KonanIr.KotlinDescriptor.Kind.ACCESSOR -> {
@@ -72,6 +72,13 @@ message IrBlock {
repeated IrStatement statement = 2; repeated IrStatement statement = 2;
} }
message MemberAccessCommon {
required TypeMap type_map = 3;
optional IrExpression dispatch_receiver = 5;
optional IrExpression extension_receiver = 6;
repeated IrExpression value_argument = 7;
}
message IrCall { message IrCall {
enum Primitive { enum Primitive {
NOT_PRIMITIVE = 1; NOT_PRIMITIVE = 1;
@@ -81,17 +88,13 @@ message IrCall {
} }
required Primitive kind = 1; required Primitive kind = 1;
required KotlinDescriptor descriptor = 2; required KotlinDescriptor descriptor = 2;
required TypeMap type_map = 3; required MemberAccessCommon member_access = 3;
optional KotlinDescriptor super = 4; optional KotlinDescriptor super = 4;
optional IrExpression dispatch_receiver = 5;
optional IrExpression extension_receiver = 6;
repeated IrExpression value_argument = 7;
} }
message IrCallableReference { message IrCallableReference {
required KotlinDescriptor descriptor = 1; required KotlinDescriptor descriptor = 1;
required TypeMap type_map = 2; required TypeMap type_map = 2;
//required int32 value_parameters_size = 3;
} }
message IrConst { message IrConst {
@@ -111,8 +114,17 @@ message IrConst {
message IrDelegatingConstructorCall { message IrDelegatingConstructorCall {
required KotlinDescriptor descriptor = 1; required KotlinDescriptor descriptor = 1;
required TypeMap type_map = 2; required MemberAccessCommon member_access = 3;
repeated IrExpression value_argument = 3; }
message IrEnumConstructorCall {
required KotlinDescriptor descriptor = 2;
required MemberAccessCommon member_access = 3;
}
message IrGetEnumValue {
required KotlinType type = 1;
required KotlinDescriptor descriptor = 2;
} }
message IrGetValue { message IrGetValue {
@@ -180,18 +192,21 @@ message IrOperation {
IrCallableReference callable_reference = 4; IrCallableReference callable_reference = 4;
IrConst const = 5; IrConst const = 5;
IrDelegatingConstructorCall delegating_constructor_call = 6; IrDelegatingConstructorCall delegating_constructor_call = 6;
IrGetValue get_value = 7; //IrEnumEntry enum_entry = 7;
IrGetObject get_object = 8; IrEnumConstructorCall enum_constructor_call = 8;
IrInstanceInitializerCall instance_initializer_call = 9; IrGetEnumValue get_enum_value = 9;
IrReturn return = 10; IrGetValue get_value = 10;
IrSetVariable set_variable = 11; IrGetObject get_object = 11;
IrStringConcat string_concat = 12; IrInstanceInitializerCall instance_initializer_call = 12;
IrThrow throw = 13; IrReturn return = 13;
IrTry try = 14; IrSetVariable set_variable = 14;
IrTypeOp type_op = 15; IrStringConcat string_concat = 15;
IrVararg vararg = 16; IrThrow throw = 16;
IrWhen when = 17; IrTry try = 17;
IrWhile while = 18; IrTypeOp type_op = 18;
IrVararg vararg = 19;
IrWhen when = 20;
IrWhile while = 21;
} }
} }
@@ -226,11 +241,16 @@ message IrClass {
repeated IrDeclaration member = 1; repeated IrDeclaration member = 1;
} }
message IrEnumEntry {
optional IrExpression initializer = 1;
}
message IrDeclarator { message IrDeclarator {
oneof symbol { oneof symbol {
IrVar variable = 1; IrVar variable = 1;
IrFunc function = 2; IrFunc function = 2;
IrClass ir_class = 3; IrClass ir_class = 3;
IrEnumEntry ir_enum_entry = 4;
} }
} }
@@ -28,9 +28,7 @@ import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
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.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.serialization.KonanIr import org.jetbrains.kotlin.serialization.KonanIr
@@ -88,6 +86,18 @@ internal class IrSerializer(val context: Context,
return proto.build() return proto.build()
} }
fun serializeTypeArguments(call: IrMemberAccessExpression): KonanIr.TypeMap {
val typeMap = mutableMapOf<TypeParameterDescriptor, KotlinType>()
call.descriptor.original.typeParameters.forEach {
val type = call.getTypeArgument(it)
if (type != null) typeMap.put(it, type)
}
return serializeTypeMap(typeMap)
}
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
fun serializeBlockBody(expression: IrBlockBody): KonanIr.IrBlockBody { fun serializeBlockBody(expression: IrBlockBody): KonanIr.IrBlockBody {
@@ -144,12 +154,8 @@ internal class IrSerializer(val context: Context,
} }
} }
fun serializeCall(call: IrCall): KonanIr.IrCall { fun serializeMemberAccessCommon(call: IrMemberAccessExpression): KonanIr.MemberAccessCommon {
val proto = KonanIr.IrCall.newBuilder() val proto = KonanIr.MemberAccessCommon.newBuilder()
proto.setKind(irCallToPrimitiveKind(call))
proto.setDescriptor(serializeDescriptor(call.descriptor))
if (call.extensionReceiver != null) { if (call.extensionReceiver != null) {
proto.setExtensionReceiver(serializeExpression(call.extensionReceiver!!)) proto.setExtensionReceiver(serializeExpression(call.extensionReceiver!!))
} }
@@ -157,22 +163,12 @@ internal class IrSerializer(val context: Context,
if (call.dispatchReceiver != null) { if (call.dispatchReceiver != null) {
proto.setDispatchReceiver(serializeExpression(call.dispatchReceiver!!)) proto.setDispatchReceiver(serializeExpression(call.dispatchReceiver!!))
} }
proto.setTypeMap(serializeTypeArguments(call))
if (call.superQualifier != null) {
proto.setSuper(serializeDescriptor(call.superQualifier!!))
}
val typeMap = mutableMapOf<TypeParameterDescriptor, KotlinType>()
call.descriptor.original.typeParameters.forEach {
val type = call.getTypeArgument(it)
if (type != null) typeMap.put(it, type)
}
proto.setTypeMap(serializeTypeMap(typeMap))
call.descriptor.valueParameters.forEach { call.descriptor.valueParameters.forEach {
val actual = call.getValueArgument(it.index) val actual = call.getValueArgument(it.index)
if (actual == null) { if (actual == null) {
// Am I observing an IR generation regtession? // Am I observing an IR generation regression?
// I see a lack of arg for an empty vararg, // I see a lack of arg for an empty vararg,
// rather than an empty vararg node. // rather than an empty vararg node.
assert(it.varargElementType != null) assert(it.varargElementType != null)
@@ -182,22 +178,26 @@ internal class IrSerializer(val context: Context,
proto.addValueArgument(argProto) proto.addValueArgument(argProto)
} }
} }
return proto.build()
}
fun serializeCall(call: IrCall): KonanIr.IrCall {
val proto = KonanIr.IrCall.newBuilder()
proto.setKind(irCallToPrimitiveKind(call))
proto.setDescriptor(serializeDescriptor(call.descriptor))
if (call.superQualifier != null) {
proto.setSuper(serializeDescriptor(call.superQualifier!!))
}
proto.setMemberAccess(serializeMemberAccessCommon(call))
return proto.build() return proto.build()
} }
fun serializeCallableReference(callable: IrCallableReference): KonanIr.IrCallableReference { fun serializeCallableReference(callable: IrCallableReference): KonanIr.IrCallableReference {
val proto = KonanIr.IrCallableReference.newBuilder() val proto = KonanIr.IrCallableReference.newBuilder()
.setDescriptor(serializeDescriptor(callable.descriptor)) .setDescriptor(serializeDescriptor(callable.descriptor))
.setTypeMap(serializeTypeArguments(callable))
val typeMap = mutableMapOf<TypeParameterDescriptor, KotlinType>()
callable.descriptor.original.typeParameters.forEach {
val type = callable.getTypeArgument(it)
if (type != null) {
typeMap.put(it, type)
}
}
proto.setTypeMap(serializeTypeMap(typeMap))
return proto.build() return proto.build()
} }
@@ -221,16 +221,22 @@ internal class IrSerializer(val context: Context,
fun serializeDelegatingConstructorCall(call: IrDelegatingConstructorCall): KonanIr.IrDelegatingConstructorCall { fun serializeDelegatingConstructorCall(call: IrDelegatingConstructorCall): KonanIr.IrDelegatingConstructorCall {
val proto = KonanIr.IrDelegatingConstructorCall.newBuilder() val proto = KonanIr.IrDelegatingConstructorCall.newBuilder()
.setDescriptor(serializeDescriptor(call.descriptor))
.setMemberAccess(serializeMemberAccessCommon(call))
return proto.build()
}
proto.setDescriptor(serializeDescriptor(call.descriptor)) fun serializeEnumConstructorCall(call: IrEnumConstructorCall): KonanIr.IrEnumConstructorCall {
val proto = KonanIr.IrEnumConstructorCall.newBuilder()
val typeMap = mutableMapOf<TypeParameterDescriptor, KotlinType>() .setDescriptor(serializeDescriptor(call.descriptor))
call.descriptor.original.typeParameters.forEach { .setMemberAccess(serializeMemberAccessCommon(call))
val type = call.getTypeArgument(it) return proto.build()
if (type != null) typeMap.put(it, type) }
}
proto.setTypeMap(serializeTypeMap(typeMap))
fun serializeGetEnumValue(expression: IrGetEnumValue): KonanIr.IrGetEnumValue {
val proto = KonanIr.IrGetEnumValue.newBuilder()
.setType(serializeKotlinType(expression.type))
.setDescriptor(serializeDescriptor(expression.descriptor))
return proto.build() return proto.build()
} }
@@ -385,6 +391,8 @@ internal class IrSerializer(val context: Context,
is IrDelegatingConstructorCall is IrDelegatingConstructorCall
-> operationProto.setDelegatingConstructorCall(serializeDelegatingConstructorCall(expression)) -> operationProto.setDelegatingConstructorCall(serializeDelegatingConstructorCall(expression))
is IrGetValue -> operationProto.setGetValue(serializeGetValue(expression)) is IrGetValue -> operationProto.setGetValue(serializeGetValue(expression))
is IrGetEnumValue
-> operationProto.setGetEnumValue(serializeGetEnumValue(expression))
is IrGetObjectValue is IrGetObjectValue
-> operationProto.setGetObject(serializeGetObject(expression)) -> operationProto.setGetObject(serializeGetObject(expression))
is IrInstanceInitializerCall is IrInstanceInitializerCall
@@ -454,6 +462,15 @@ internal class IrSerializer(val context: Context,
return proto.build() return proto.build()
} }
fun serializeIrEnumEntry(enumEntry: IrEnumEntry): KonanIr.IrEnumEntry {
val proto = KonanIr.IrEnumEntry.newBuilder()
val initializer = enumEntry.initializerExpression
if (initializer != null) {
proto.setInitializer(serializeExpression(initializer))
}
return proto.build()
}
fun serializeDeclaration(declaration: IrDeclaration): KonanIr.IrDeclaration { fun serializeDeclaration(declaration: IrDeclaration): KonanIr.IrDeclaration {
context.log("### serializing Declaration: ${ir2string(declaration)}") context.log("### serializing Declaration: ${ir2string(declaration)}")
@@ -489,6 +506,8 @@ internal class IrSerializer(val context: Context,
-> declarator.setVariable(serializeVariable(declaration)) -> declarator.setVariable(serializeVariable(declaration))
is IrClass is IrClass
-> declarator.setIrClass(serializeIrClass(declaration)) -> declarator.setIrClass(serializeIrClass(declaration))
is IrEnumEntry
-> declarator.setIrEnumEntry(serializeIrEnumEntry(declaration))
else else
-> { -> {
TODO("Declaration serialization not supported yet.") TODO("Declaration serialization not supported yet.")
@@ -610,14 +629,26 @@ internal class IrDeserializer(val context: Context,
return block return block
} }
fun deserializeMemberAccessCommon(access: IrMemberAccessExpression, descriptor: CallableDescriptor, proto: KonanIr.MemberAccessCommon) {
descriptor.valueParameters.mapIndexed { i, valueParameterDescriptor ->
access.putValueArgument(i, deserializeExpression(proto.getValueArgument(i)))
}
if (proto.hasDispatchReceiver()) {
access.dispatchReceiver = deserializeExpression(proto.dispatchReceiver)
}
if (proto.hasExtensionReceiver()) {
access.extensionReceiver = deserializeExpression(proto.extensionReceiver)
}
}
fun deserializeCall(proto: KonanIr.IrCall, start: Int, end: Int, type: KotlinType): IrCall { fun deserializeCall(proto: KonanIr.IrCall, start: Int, end: Int, type: KotlinType): IrCall {
val descriptor = deserializeDescriptor(proto.getDescriptor()) as CallableDescriptor val descriptor = deserializeDescriptor(proto.getDescriptor()) as CallableDescriptor
val typeArgs = deserializeTypeMap(descriptor, proto.getTypeMap())
val superDescriptor = if (proto.hasSuper()) { val superDescriptor = if (proto.hasSuper()) {
deserializeDescriptor(proto.getSuper()) as ClassDescriptor deserializeDescriptor(proto.getSuper()) as ClassDescriptor
} else null } else null
val typeArgs = deserializeTypeMap(descriptor, proto.memberAccess.getTypeMap())
val call: IrCall = when (proto.kind) { val call: IrCall = when (proto.kind) {
KonanIr.IrCall.Primitive.NOT_PRIMITIVE -> KonanIr.IrCall.Primitive.NOT_PRIMITIVE ->
// TODO: implement the last three args here. // TODO: implement the last three args here.
@@ -629,18 +660,7 @@ internal class IrDeserializer(val context: Context,
KonanIr.IrCall.Primitive.BINARY -> KonanIr.IrCall.Primitive.BINARY ->
IrBinaryPrimitiveImpl(start, end, null, descriptor) IrBinaryPrimitiveImpl(start, end, null, descriptor)
} }
deserializeMemberAccessCommon(call, descriptor, proto.memberAccess)
descriptor.valueParameters.mapIndexed { i, valueParameterDescriptor ->
call.putValueArgument(i, deserializeExpression(proto.getValueArgument(i)))
}
if (proto.hasDispatchReceiver()) {
call.dispatchReceiver = deserializeExpression(proto.dispatchReceiver)
}
if (proto.hasExtensionReceiver()) {
call.extensionReceiver = deserializeExpression(proto.extensionReceiver)
}
return call return call
} }
@@ -648,24 +668,32 @@ internal class IrDeserializer(val context: Context,
start: Int, end: Int, type: KotlinType): IrCallableReference { start: Int, end: Int, type: KotlinType): IrCallableReference {
val descriptor = deserializeDescriptor(proto.getDescriptor()) as CallableDescriptor val descriptor = deserializeDescriptor(proto.getDescriptor()) as CallableDescriptor
if (descriptor.typeParameters.isNotEmpty()) error("We can't deserialize typa arguments") //if (descriptor.typeParameters.isNotEmpty()) error("We can't deserialize typa arguments")
val typeMap = deserializeTypeMap(descriptor, proto.getTypeMap()) val typeMap = deserializeTypeMap(descriptor, proto.typeMap)
val callable = IrCallableReferenceImpl(start, end, type, descriptor, typeMap, null) val callable = IrCallableReferenceImpl(start, end, type, descriptor, typeMap, null)
//deserializeMemberAccessCommon(callable, descriptor, proto.memberAccess)
return callable return callable
} }
fun deserializeDelegatingConstructorCall(proto: KonanIr.IrDelegatingConstructorCall, start: Int, end: Int, type: KotlinType): IrDelegatingConstructorCall { fun deserializeDelegatingConstructorCall(proto: KonanIr.IrDelegatingConstructorCall, start: Int, end: Int, type: KotlinType): IrDelegatingConstructorCall {
val descriptor = deserializeDescriptor(proto.getDescriptor()) as ClassConstructorDescriptor val descriptor = deserializeDescriptor(proto.getDescriptor()) as ClassConstructorDescriptor
val typeArgs = deserializeTypeMap(descriptor, proto.getTypeMap()) val typeArgs = deserializeTypeMap(descriptor, proto.memberAccess.getTypeMap())
// TODO: implement the last three args here. // TODO: implement the last three args here.
val call = IrDelegatingConstructorCallImpl(start, end, descriptor, typeArgs) val call = IrDelegatingConstructorCallImpl(start, end, descriptor, typeArgs)
descriptor.valueParameters.mapIndexed { i, valueParameterDescriptor -> //descriptor.valueParameters.mapIndexed { i, valueParameterDescriptor ->
call.putValueArgument(i, deserializeExpression(proto.getValueArgument(i))) // call.putValueArgument(i, deserializeExpression(proto.getValueArgument(i)))
} //}
deserializeMemberAccessCommon(call, descriptor, proto.memberAccess)
return call
}
fun deserializeEnumConstructorCall(proto: KonanIr.IrEnumConstructorCall, start: Int, end: Int, type: KotlinType): IrEnumConstructorCall {
val descriptor = deserializeDescriptor(proto.getDescriptor()) as ClassConstructorDescriptor
//val typeArgs = deserializeTypeMap(descriptor, proto.memberAccess.getTypeMap())
val call = IrEnumConstructorCallImpl(start, end, descriptor)
deserializeMemberAccessCommon(call, descriptor, proto.memberAccess)
return call return call
} }
@@ -676,6 +704,14 @@ internal class IrDeserializer(val context: Context,
return IrGetValueImpl(start, end, descriptor, null) return IrGetValueImpl(start, end, descriptor, null)
} }
fun deserializeGetEnumValue(proto: KonanIr.IrGetEnumValue, start: Int, end: Int, type: KotlinType): IrGetEnumValue {
val type = deserializeKotlinType(proto.type)
val descriptor = deserializeDescriptor(proto.descriptor) as ClassDescriptor
// TODO: origin!
return IrGetEnumValueImpl(start, end, type, descriptor)
}
fun deserializeGetObject(proto: KonanIr.IrGetObject, start: Int, end: Int, type: KotlinType): IrGetObjectValue { fun deserializeGetObject(proto: KonanIr.IrGetObject, start: Int, end: Int, type: KotlinType): IrGetObjectValue {
val descriptor = deserializeDescriptor(proto.descriptor) as ClassDescriptor val descriptor = deserializeDescriptor(proto.descriptor) as ClassDescriptor
return IrGetObjectValueImpl(start, end, type, descriptor) return IrGetObjectValueImpl(start, end, type, descriptor)
@@ -836,6 +872,8 @@ internal class IrDeserializer(val context: Context,
-> return deserializeDelegatingConstructorCall(proto.getDelegatingConstructorCall(), start, end, type) -> return deserializeDelegatingConstructorCall(proto.getDelegatingConstructorCall(), start, end, type)
proto.hasGetValue() proto.hasGetValue()
-> return deserializeGetValue(proto.getGetValue(), start, end, type) -> return deserializeGetValue(proto.getGetValue(), start, end, type)
proto.hasGetEnumValue()
-> return deserializeGetEnumValue(proto.getGetEnumValue(), start, end, type)
proto.hasGetObject() proto.hasGetObject()
-> return deserializeGetObject(proto.getGetObject(), start, end, type) -> return deserializeGetObject(proto.getGetObject(), start, end, type)
proto.hasInstanceInitializerCall() proto.hasInstanceInitializerCall()
@@ -906,6 +944,17 @@ internal class IrDeserializer(val context: Context,
return variable return variable
} }
fun deserializeIrEnumEntry(proto: KonanIr.IrEnumEntry, descriptor: ClassDescriptor,
start: Int, end: Int, origin: IrDeclarationOrigin): IrEnumEntry {
val enumEntry = IrEnumEntryImpl(start, end, origin, descriptor)
// TODO: we need to pass down the enclosing declaration.
//enumEntry.correspondingClass = ???
enumEntry.initializerExpression = deserializeExpression(proto.initializer)
return enumEntry
}
fun deserializeDeclaration(proto: KonanIr.IrDeclaration): IrDeclaration { fun deserializeDeclaration(proto: KonanIr.IrDeclaration): IrDeclaration {
val descriptor = deserializeDescriptor(proto.descriptor) val descriptor = deserializeDescriptor(proto.descriptor)
@@ -917,14 +966,17 @@ internal class IrDeserializer(val context: Context,
val declaration = when { val declaration = when {
declarator.hasIrClass() declarator.hasIrClass()
-> deserializeIrClass(declarator.getIrClass(), -> deserializeIrClass(declarator.irClass,
descriptor as ClassDescriptor, start, end, origin) descriptor as ClassDescriptor, start, end, origin)
declarator.hasFunction() declarator.hasFunction()
-> deserializeIrFunction(declarator.getFunction(), -> deserializeIrFunction(declarator.function,
descriptor as FunctionDescriptor, start, end, origin) descriptor as FunctionDescriptor, start, end, origin)
declarator.hasVariable() declarator.hasVariable()
-> deserializeIrVariable(declarator.getVariable(), -> deserializeIrVariable(declarator.variable,
descriptor as VariableDescriptor, start, end, origin) descriptor as VariableDescriptor, start, end, origin)
declarator.hasIrEnumEntry()
-> deserializeIrEnumEntry(declarator.irEnumEntry,
descriptor as ClassDescriptor, start, end, origin)
else -> { else -> {
TODO("Declaration deserialization not implemented") TODO("Declaration deserialization not implemented")
} }