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 ->
descriptorIndex[index]!!
KonanIr.KotlinDescriptor.Kind.CLASS,
KonanIr.KotlinDescriptor.Kind.CONSTRUCTOR,
KonanIr.KotlinDescriptor.Kind.FUNCTION,
KonanIr.KotlinDescriptor.Kind.ACCESSOR -> {
@@ -72,6 +72,13 @@ message IrBlock {
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 {
enum Primitive {
NOT_PRIMITIVE = 1;
@@ -81,17 +88,13 @@ message IrCall {
}
required Primitive kind = 1;
required KotlinDescriptor descriptor = 2;
required TypeMap type_map = 3;
required MemberAccessCommon member_access = 3;
optional KotlinDescriptor super = 4;
optional IrExpression dispatch_receiver = 5;
optional IrExpression extension_receiver = 6;
repeated IrExpression value_argument = 7;
}
message IrCallableReference {
required KotlinDescriptor descriptor = 1;
required TypeMap type_map = 2;
//required int32 value_parameters_size = 3;
}
message IrConst {
@@ -111,8 +114,17 @@ message IrConst {
message IrDelegatingConstructorCall {
required KotlinDescriptor descriptor = 1;
required TypeMap type_map = 2;
repeated IrExpression value_argument = 3;
required MemberAccessCommon member_access = 3;
}
message IrEnumConstructorCall {
required KotlinDescriptor descriptor = 2;
required MemberAccessCommon member_access = 3;
}
message IrGetEnumValue {
required KotlinType type = 1;
required KotlinDescriptor descriptor = 2;
}
message IrGetValue {
@@ -180,18 +192,21 @@ message IrOperation {
IrCallableReference callable_reference = 4;
IrConst const = 5;
IrDelegatingConstructorCall delegating_constructor_call = 6;
IrGetValue get_value = 7;
IrGetObject get_object = 8;
IrInstanceInitializerCall instance_initializer_call = 9;
IrReturn return = 10;
IrSetVariable set_variable = 11;
IrStringConcat string_concat = 12;
IrThrow throw = 13;
IrTry try = 14;
IrTypeOp type_op = 15;
IrVararg vararg = 16;
IrWhen when = 17;
IrWhile while = 18;
//IrEnumEntry enum_entry = 7;
IrEnumConstructorCall enum_constructor_call = 8;
IrGetEnumValue get_enum_value = 9;
IrGetValue get_value = 10;
IrGetObject get_object = 11;
IrInstanceInitializerCall instance_initializer_call = 12;
IrReturn return = 13;
IrSetVariable set_variable = 14;
IrStringConcat string_concat = 15;
IrThrow throw = 16;
IrTry try = 17;
IrTypeOp type_op = 18;
IrVararg vararg = 19;
IrWhen when = 20;
IrWhile while = 21;
}
}
@@ -226,11 +241,16 @@ message IrClass {
repeated IrDeclaration member = 1;
}
message IrEnumEntry {
optional IrExpression initializer = 1;
}
message IrDeclarator {
oneof symbol {
IrVar variable = 1;
IrFunc function = 2;
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.declarations.*
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin.DEFINED
import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
import org.jetbrains.kotlin.ir.declarations.impl.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.serialization.KonanIr
@@ -88,6 +86,18 @@ internal class IrSerializer(val context: Context,
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 {
@@ -144,12 +154,8 @@ internal class IrSerializer(val context: Context,
}
}
fun serializeCall(call: IrCall): KonanIr.IrCall {
val proto = KonanIr.IrCall.newBuilder()
proto.setKind(irCallToPrimitiveKind(call))
proto.setDescriptor(serializeDescriptor(call.descriptor))
fun serializeMemberAccessCommon(call: IrMemberAccessExpression): KonanIr.MemberAccessCommon {
val proto = KonanIr.MemberAccessCommon.newBuilder()
if (call.extensionReceiver != null) {
proto.setExtensionReceiver(serializeExpression(call.extensionReceiver!!))
}
@@ -157,22 +163,12 @@ internal class IrSerializer(val context: Context,
if (call.dispatchReceiver != null) {
proto.setDispatchReceiver(serializeExpression(call.dispatchReceiver!!))
}
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))
proto.setTypeMap(serializeTypeArguments(call))
call.descriptor.valueParameters.forEach {
val actual = call.getValueArgument(it.index)
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,
// rather than an empty vararg node.
assert(it.varargElementType != null)
@@ -182,22 +178,26 @@ internal class IrSerializer(val context: Context,
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()
}
fun serializeCallableReference(callable: IrCallableReference): KonanIr.IrCallableReference {
val proto = KonanIr.IrCallableReference.newBuilder()
.setDescriptor(serializeDescriptor(callable.descriptor))
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))
.setTypeMap(serializeTypeArguments(callable))
return proto.build()
}
@@ -221,16 +221,22 @@ internal class IrSerializer(val context: Context,
fun serializeDelegatingConstructorCall(call: IrDelegatingConstructorCall): KonanIr.IrDelegatingConstructorCall {
val proto = KonanIr.IrDelegatingConstructorCall.newBuilder()
.setDescriptor(serializeDescriptor(call.descriptor))
.setMemberAccess(serializeMemberAccessCommon(call))
return proto.build()
}
proto.setDescriptor(serializeDescriptor(call.descriptor))
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))
fun serializeEnumConstructorCall(call: IrEnumConstructorCall): KonanIr.IrEnumConstructorCall {
val proto = KonanIr.IrEnumConstructorCall.newBuilder()
.setDescriptor(serializeDescriptor(call.descriptor))
.setMemberAccess(serializeMemberAccessCommon(call))
return proto.build()
}
fun serializeGetEnumValue(expression: IrGetEnumValue): KonanIr.IrGetEnumValue {
val proto = KonanIr.IrGetEnumValue.newBuilder()
.setType(serializeKotlinType(expression.type))
.setDescriptor(serializeDescriptor(expression.descriptor))
return proto.build()
}
@@ -385,6 +391,8 @@ internal class IrSerializer(val context: Context,
is IrDelegatingConstructorCall
-> operationProto.setDelegatingConstructorCall(serializeDelegatingConstructorCall(expression))
is IrGetValue -> operationProto.setGetValue(serializeGetValue(expression))
is IrGetEnumValue
-> operationProto.setGetEnumValue(serializeGetEnumValue(expression))
is IrGetObjectValue
-> operationProto.setGetObject(serializeGetObject(expression))
is IrInstanceInitializerCall
@@ -454,6 +462,15 @@ internal class IrSerializer(val context: Context,
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 {
context.log("### serializing Declaration: ${ir2string(declaration)}")
@@ -489,6 +506,8 @@ internal class IrSerializer(val context: Context,
-> declarator.setVariable(serializeVariable(declaration))
is IrClass
-> declarator.setIrClass(serializeIrClass(declaration))
is IrEnumEntry
-> declarator.setIrEnumEntry(serializeIrEnumEntry(declaration))
else
-> {
TODO("Declaration serialization not supported yet.")
@@ -610,14 +629,26 @@ internal class IrDeserializer(val context: Context,
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 {
val descriptor = deserializeDescriptor(proto.getDescriptor()) as CallableDescriptor
val typeArgs = deserializeTypeMap(descriptor, proto.getTypeMap())
val superDescriptor = if (proto.hasSuper()) {
deserializeDescriptor(proto.getSuper()) as ClassDescriptor
} else null
val typeArgs = deserializeTypeMap(descriptor, proto.memberAccess.getTypeMap())
val call: IrCall = when (proto.kind) {
KonanIr.IrCall.Primitive.NOT_PRIMITIVE ->
// TODO: implement the last three args here.
@@ -629,18 +660,7 @@ internal class IrDeserializer(val context: Context,
KonanIr.IrCall.Primitive.BINARY ->
IrBinaryPrimitiveImpl(start, end, null, descriptor)
}
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)
}
deserializeMemberAccessCommon(call, descriptor, proto.memberAccess)
return call
}
@@ -648,24 +668,32 @@ internal class IrDeserializer(val context: Context,
start: Int, end: Int, type: KotlinType): IrCallableReference {
val descriptor = deserializeDescriptor(proto.getDescriptor()) as CallableDescriptor
if (descriptor.typeParameters.isNotEmpty()) error("We can't deserialize typa arguments")
val typeMap = deserializeTypeMap(descriptor, proto.getTypeMap())
//if (descriptor.typeParameters.isNotEmpty()) error("We can't deserialize typa arguments")
val typeMap = deserializeTypeMap(descriptor, proto.typeMap)
val callable = IrCallableReferenceImpl(start, end, type, descriptor, typeMap, null)
//deserializeMemberAccessCommon(callable, descriptor, proto.memberAccess)
return callable
}
fun deserializeDelegatingConstructorCall(proto: KonanIr.IrDelegatingConstructorCall, start: Int, end: Int, type: KotlinType): IrDelegatingConstructorCall {
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.
val call = IrDelegatingConstructorCallImpl(start, end, descriptor, typeArgs)
descriptor.valueParameters.mapIndexed { i, valueParameterDescriptor ->
call.putValueArgument(i, deserializeExpression(proto.getValueArgument(i)))
}
//descriptor.valueParameters.mapIndexed { i, valueParameterDescriptor ->
// 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
}
@@ -676,6 +704,14 @@ internal class IrDeserializer(val context: Context,
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 {
val descriptor = deserializeDescriptor(proto.descriptor) as ClassDescriptor
return IrGetObjectValueImpl(start, end, type, descriptor)
@@ -836,6 +872,8 @@ internal class IrDeserializer(val context: Context,
-> return deserializeDelegatingConstructorCall(proto.getDelegatingConstructorCall(), start, end, type)
proto.hasGetValue()
-> return deserializeGetValue(proto.getGetValue(), start, end, type)
proto.hasGetEnumValue()
-> return deserializeGetEnumValue(proto.getGetEnumValue(), start, end, type)
proto.hasGetObject()
-> return deserializeGetObject(proto.getGetObject(), start, end, type)
proto.hasInstanceInitializerCall()
@@ -906,6 +944,17 @@ internal class IrDeserializer(val context: Context,
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 {
val descriptor = deserializeDescriptor(proto.descriptor)
@@ -917,14 +966,17 @@ internal class IrDeserializer(val context: Context,
val declaration = when {
declarator.hasIrClass()
-> deserializeIrClass(declarator.getIrClass(),
-> deserializeIrClass(declarator.irClass,
descriptor as ClassDescriptor, start, end, origin)
declarator.hasFunction()
-> deserializeIrFunction(declarator.getFunction(),
-> deserializeIrFunction(declarator.function,
descriptor as FunctionDescriptor, start, end, origin)
declarator.hasVariable()
-> deserializeIrVariable(declarator.getVariable(),
-> deserializeIrVariable(declarator.variable,
descriptor as VariableDescriptor, start, end, origin)
declarator.hasIrEnumEntry()
-> deserializeIrEnumEntry(declarator.irEnumEntry,
descriptor as ClassDescriptor, start, end, origin)
else -> {
TODO("Declaration deserialization not implemented")
}