static void GenDeserializerCall(CodeGenContext ctx, ILGenerator il, Type type) { // We can call the Deserializer method directly for: // - Value types // - Array types // - Sealed types with static Deserializer method, as the method will handle null // Other reference types go through the DeserializesSwitch bool direct; if (type.IsValueType || type.IsArray) { direct = true; } else if (type.IsSealed && ctx.IsDynamic(type) == false) { direct = true; } else { direct = false; } var method = direct ? ctx.GetReaderMethodInfo(type) : ctx.DeserializerSwitchMethodInfo; il.EmitCall(OpCodes.Call, method, null); }
public void GenerateReaderMethod(Type type, CodeGenContext ctx, ILGenerator il) { var valueType = type.GetGenericArguments()[0]; var hasValueLocal = il.DeclareLocal(typeof(bool)); var valueLocal = il.DeclareLocal(valueType); var notNullLabel = il.DefineLabel(); var data = ctx.GetTypeDataForCall(valueType); // read array len il.Emit(OpCodes.Ldarg_1); // Stream il.Emit(OpCodes.Ldloca_S, hasValueLocal); // &hasValue il.Emit(OpCodes.Call, ctx.GetReaderMethodInfo(typeof(bool))); // if hasValue == 0, return null il.Emit(OpCodes.Ldloc_S, hasValueLocal); il.Emit(OpCodes.Brtrue_S, notNullLabel); il.Emit(OpCodes.Ldarg_2); // &value il.Emit(OpCodes.Initobj, type); il.Emit(OpCodes.Ret); // hasValue == 1 il.MarkLabel(notNullLabel); if (data.NeedsInstanceParameter) { il.Emit(OpCodes.Ldarg_0); // Serializer } il.Emit(OpCodes.Ldarg_1); // Stream il.Emit(OpCodes.Ldloca_S, valueLocal); il.Emit(OpCodes.Call, data.ReaderMethodInfo); il.Emit(OpCodes.Ldarg_2); // &value il.Emit(OpCodes.Ldloc_S, valueLocal); var constr = type.GetConstructor(new[] { valueType }); il.Emit(OpCodes.Newobj, constr); // new Nullable<T>(valueLocal) il.Emit(OpCodes.Stobj, type); // store to &value il.Emit(OpCodes.Ret); }
public void GenerateReaderMethod(Type type, CodeGenContext ctx, ILGenerator il) { var valueType = type.GetGenericArguments()[0]; var hasValueLocal = il.DeclareLocal(typeof(bool)); var valueLocal = il.DeclareLocal(valueType); var notNullLabel = il.DefineLabel(); var data = ctx.GetTypeDataForCall(valueType); // read array len il.Emit(OpCodes.Ldarg_1); // Stream il.Emit(OpCodes.Ldloca_S, hasValueLocal); // &hasValue il.Emit(OpCodes.Call, ctx.GetReaderMethodInfo(typeof(bool))); // if hasValue == 0, return null il.Emit(OpCodes.Ldloc_S, hasValueLocal); il.Emit(OpCodes.Brtrue_S, notNullLabel); il.Emit(OpCodes.Ldarg_2); // &value il.Emit(OpCodes.Initobj, type); il.Emit(OpCodes.Ret); // hasValue == 1 il.MarkLabel(notNullLabel); if (data.NeedsInstanceParameter) il.Emit(OpCodes.Ldarg_0); // Serializer il.Emit(OpCodes.Ldarg_1); // Stream il.Emit(OpCodes.Ldloca_S, valueLocal); il.Emit(OpCodes.Call, data.ReaderMethodInfo); il.Emit(OpCodes.Ldarg_2); // &value il.Emit(OpCodes.Ldloc_S, valueLocal); var constr = type.GetConstructor(new[] { valueType }); il.Emit(OpCodes.Newobj, constr); // new Nullable<T>(valueLocal) il.Emit(OpCodes.Stobj, type); // store to &value il.Emit(OpCodes.Ret); }
public static void GenDeserializerCall(CodeGenContext ctx, ILGenerator il, Type type) { // We can call the Deserializer method directly for: // - Value types // - Array types // - Sealed types with static Deserializer method, as the method will handle null // Other reference types go through the DeserializesSwitch bool direct; if (type.IsValueType || type.IsArray) direct = true; else if (type.IsSealed && ctx.IsGenerated(type) == false) direct = true; else direct = false; var method = direct ? ctx.GetReaderMethodInfo(type) : ctx.DeserializerSwitchMethodInfo; il.EmitCall(OpCodes.Call, method, null); }
public static void GenerateDeserializerSwitch(CodeGenContext ctx, ILGenerator il, IDictionary <Type, TypeData> map) { // arg0: stream, arg1: out object var idLocal = il.DeclareLocal(typeof(ushort)); // read typeID il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldloca_S, idLocal); il.EmitCall(OpCodes.Call, ctx.GetReaderMethodInfo(typeof(ushort)), null); // +1 for 0 (null) var jumpTable = new Label[map.Count + 1]; jumpTable[0] = il.DefineLabel(); foreach (var kvp in map) { jumpTable[kvp.Value.TypeID] = il.DefineLabel(); } il.Emit(OpCodes.Ldloc_S, idLocal); il.Emit(OpCodes.Switch, jumpTable); ConstructorInfo exceptionCtor = typeof(Exception).GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, new Type[0], null); il.Emit(OpCodes.Newobj, exceptionCtor); il.Emit(OpCodes.Throw); /* null case */ il.MarkLabel(jumpTable[0]); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldnull); il.Emit(OpCodes.Stind_Ref); il.Emit(OpCodes.Ret); /* cases for types */ foreach (var kvp in map) { var type = kvp.Key; var data = kvp.Value; il.MarkLabel(jumpTable[data.TypeID]); var local = il.DeclareLocal(type); // call deserializer for this typeID il.Emit(OpCodes.Ldarg_0); if (local.LocalIndex < 256) { il.Emit(OpCodes.Ldloca_S, local); } else { il.Emit(OpCodes.Ldloca, local); } il.EmitCall(OpCodes.Call, data.ReaderMethodInfo, null); // write result object to out object il.Emit(OpCodes.Ldarg_1); if (local.LocalIndex < 256) { il.Emit(OpCodes.Ldloc_S, local); } else { il.Emit(OpCodes.Ldloc, local); } if (type.IsValueType) { il.Emit(OpCodes.Box, type); } il.Emit(OpCodes.Stind_Ref); il.Emit(OpCodes.Ret); } }
static void GenDeserializerBodyForArray(CodeGenContext ctx, Type type, ILGenerator il) { var elemType = type.GetElementType(); var lenLocal = il.DeclareLocal(typeof(uint)); // read array len il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldloca_S, lenLocal); il.EmitCall(OpCodes.Call, ctx.GetReaderMethodInfo(typeof(uint)), null); var notNullLabel = il.DefineLabel(); /* if len == 0, return null */ il.Emit(OpCodes.Ldloc_S, lenLocal); il.Emit(OpCodes.Brtrue_S, notNullLabel); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldnull); il.Emit(OpCodes.Stind_Ref); il.Emit(OpCodes.Ret); il.MarkLabel(notNullLabel); var arrLocal = il.DeclareLocal(type); // create new array with len - 1 il.Emit(OpCodes.Ldloc_S, lenLocal); il.Emit(OpCodes.Ldc_I4_1); il.Emit(OpCodes.Sub); il.Emit(OpCodes.Newarr, elemType); il.Emit(OpCodes.Stloc_S, arrLocal); // declare i var idxLocal = il.DeclareLocal(typeof(int)); // i = 0 il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Stloc_S, idxLocal); var loopBodyLabel = il.DefineLabel(); var loopCheckLabel = il.DefineLabel(); il.Emit(OpCodes.Br_S, loopCheckLabel); // loop body il.MarkLabel(loopBodyLabel); // read element to arr[i] il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldloc_S, arrLocal); il.Emit(OpCodes.Ldloc_S, idxLocal); il.Emit(OpCodes.Ldelema, elemType); GenDeserializerCall(ctx, il, elemType); // i = i + 1 il.Emit(OpCodes.Ldloc_S, idxLocal); il.Emit(OpCodes.Ldc_I4_1); il.Emit(OpCodes.Add); il.Emit(OpCodes.Stloc_S, idxLocal); il.MarkLabel(loopCheckLabel); // loop condition il.Emit(OpCodes.Ldloc_S, idxLocal); il.Emit(OpCodes.Ldloc_S, arrLocal); il.Emit(OpCodes.Ldlen); il.Emit(OpCodes.Conv_I4); il.Emit(OpCodes.Clt); il.Emit(OpCodes.Brtrue_S, loopBodyLabel); // store new array to the out value il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldloc_S, arrLocal); il.Emit(OpCodes.Stind_Ref); il.Emit(OpCodes.Ret); }
public void GenerateReaderMethod(Type type, CodeGenContext ctx, ILGenerator il) { var elemType = type.GetElementType(); var lenLocal = il.DeclareLocal(typeof(uint)); // read array len il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldloca_S, lenLocal); il.Emit(OpCodes.Call, ctx.GetReaderMethodInfo(typeof(uint))); var notNullLabel = il.DefineLabel(); /* if len == 0, return null */ il.Emit(OpCodes.Ldloc_S, lenLocal); il.Emit(OpCodes.Brtrue_S, notNullLabel); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldnull); il.Emit(OpCodes.Stind_Ref); il.Emit(OpCodes.Ret); il.MarkLabel(notNullLabel); var arrLocal = il.DeclareLocal(type); // create new array with len - 1 il.Emit(OpCodes.Ldloc_S, lenLocal); il.Emit(OpCodes.Ldc_I4_1); il.Emit(OpCodes.Sub); il.Emit(OpCodes.Newarr, elemType); il.Emit(OpCodes.Stloc_S, arrLocal); // declare i var idxLocal = il.DeclareLocal(typeof(int)); // i = 0 il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Stloc_S, idxLocal); var loopBodyLabel = il.DefineLabel(); var loopCheckLabel = il.DefineLabel(); il.Emit(OpCodes.Br_S, loopCheckLabel); // loop body il.MarkLabel(loopBodyLabel); // read element to arr[i] var data = ctx.GetTypeDataForCall(elemType); if (data.NeedsInstanceParameter) il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldloc_S, arrLocal); il.Emit(OpCodes.Ldloc_S, idxLocal); il.Emit(OpCodes.Ldelema, elemType); il.Emit(OpCodes.Call, data.ReaderMethodInfo); // i = i + 1 il.Emit(OpCodes.Ldloc_S, idxLocal); il.Emit(OpCodes.Ldc_I4_1); il.Emit(OpCodes.Add); il.Emit(OpCodes.Stloc_S, idxLocal); il.MarkLabel(loopCheckLabel); // loop condition il.Emit(OpCodes.Ldloc_S, idxLocal); il.Emit(OpCodes.Ldloc_S, arrLocal); il.Emit(OpCodes.Ldlen); il.Emit(OpCodes.Conv_I4); il.Emit(OpCodes.Blt_S, loopBodyLabel); // store new array to the out value il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldloc_S, arrLocal); il.Emit(OpCodes.Stind_Ref); il.Emit(OpCodes.Ret); }
public static void GenerateDeserializerSwitch(CodeGenContext ctx, ILGenerator il, IDictionary<Type, TypeData> map) { // arg0: stream, arg1: out object, arg2: objList //-- D(il, "deser switch"); var idLocal_typeID = il.DeclareLocal(typeof(ushort)); var idLocal_caseID = il.DeclareLocal(typeof(ushort)); // read typeID il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldloca_S, idLocal_typeID); il.Emit(OpCodes.Ldarg_2); il.EmitCall(OpCodes.Call, ctx.GetReaderMethodInfo(typeof(ushort)), null); // get CaseID from TypeID var getCaseIDMethod = typeof(Serializer).GetMethod("GetCaseID", BindingFlags.NonPublic | BindingFlags.Static, null, new Type[] { typeof(ushort) }, null); il.Emit(OpCodes.Ldloc_S, idLocal_typeID); il.EmitCall(OpCodes.Call, getCaseIDMethod, null); il.Emit(OpCodes.Stloc_S, idLocal_caseID); // +1 for 0 (null) var jumpTable = new Label[map.Count + 1]; jumpTable[0] = il.DefineLabel(); foreach (var kvp in map) jumpTable[kvp.Value.CaseID] = il.DefineLabel(); il.Emit(OpCodes.Ldloc_S, idLocal_caseID); il.Emit(OpCodes.Switch, jumpTable); //-- D(il, "eihx"); ConstructorInfo exceptionCtor = typeof(Exception).GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, new Type[0], null); il.Emit(OpCodes.Newobj, exceptionCtor); il.Emit(OpCodes.Throw); /* null case */ il.MarkLabel(jumpTable[0]); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldnull); il.Emit(OpCodes.Stind_Ref); il.Emit(OpCodes.Ret); /* cases for types */ foreach (var kvp in map) { var type = kvp.Key; var data = kvp.Value; il.MarkLabel(jumpTable[data.CaseID]); var local = il.DeclareLocal(type); // call deserializer for this typeID il.Emit(OpCodes.Ldarg_0); if (local.LocalIndex < 256) il.Emit(OpCodes.Ldloca_S, local); else il.Emit(OpCodes.Ldloca, local); il.Emit(OpCodes.Ldarg_2); if (data.WriterMethodInfo.IsGenericMethodDefinition) { Debug.Assert(type.IsGenericType); var genArgs = type.GetGenericArguments(); il.EmitCall(OpCodes.Call, data.ReaderMethodInfo.MakeGenericMethod(genArgs), null); } else { il.EmitCall(OpCodes.Call, data.ReaderMethodInfo, null); } if (type == typeof(ObjectRef)) { // get Object by Ref and write found object to out object var getGetAt = typeof(ObjectList).GetMethod("GetAt", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(ObjectRef) }, null); var nullLabel = il.DefineLabel(); //==if(objList==null) goto nullLabel; il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Brfalse_S, nullLabel); //== value = objList.GetAt(obj.obj_ref); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldloc_S, local); il.EmitCall(OpCodes.Call, getGetAt, null); il.Emit(OpCodes.Stind_Ref); il.Emit(OpCodes.Ret); il.MarkLabel(nullLabel); //== value = null; il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldnull); il.Emit(OpCodes.Stind_Ref); } else { // write result object to out object il.Emit(OpCodes.Ldarg_1); if (local.LocalIndex < 256) il.Emit(OpCodes.Ldloc_S, local); else il.Emit(OpCodes.Ldloc, local); if (type.IsValueType) il.Emit(OpCodes.Box, type); il.Emit(OpCodes.Stind_Ref); } //-- D(il, "deser switch done"); il.Emit(OpCodes.Ret); } }
static void GenDeserializerCall(CodeGenContext ctx, ILGenerator il, Type type) { // We can call the Deserializer method directly for: // - Value types // - Array types // - Sealed types with static Deserializer method, as the method will handle null // Other reference types go through the DeserializesSwitch bool direct; if (type.IsValueType || type.IsArray) direct = true; else if (type.IsSealed && ctx.IsDynamic(type) == false) direct = true; else direct = false; #if GENERATE_SWITCH var method = direct ? ctx.GetReaderMethodInfo(type) : ctx.DeserializerSwitchMethodInfo; #else var method = direct ? ctx.GetReaderMethodInfo(type) : typeof(NetSerializer.Serializer).GetMethod("_DeserializerSwitch"); #endif il.EmitCall(OpCodes.Call, method, null); }
public void GenerateReaderMethod(Type obtype, CodeGenContext ctx, ILGenerator il) { var map = ctx.TypeMap; // arg0: Serializer, arg1: stream, arg2: out object var idLocal = il.DeclareLocal(typeof(ushort)); // read typeID il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldloca_S, idLocal); il.Emit(OpCodes.Call, ctx.GetReaderMethodInfo(typeof(ushort))); // +1 for 0 (null) var jumpTable = new Label[map.Count + 1]; jumpTable[0] = il.DefineLabel(); foreach (var kvp in map) jumpTable[kvp.Value.TypeID] = il.DefineLabel(); il.Emit(OpCodes.Ldloc_S, idLocal); il.Emit(OpCodes.Switch, jumpTable); il.Emit(OpCodes.Newobj, Helpers.ExceptionCtorInfo); il.Emit(OpCodes.Throw); /* null case */ il.MarkLabel(jumpTable[0]); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldnull); il.Emit(OpCodes.Stind_Ref); il.Emit(OpCodes.Ret); /* cases for types */ foreach (var kvp in map) { var type = kvp.Key; var data = kvp.Value; il.MarkLabel(jumpTable[data.TypeID]); var local = il.DeclareLocal(type); // call deserializer for this typeID if (data.NeedsInstanceParameter) il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); if (local.LocalIndex < 256) il.Emit(OpCodes.Ldloca_S, local); else il.Emit(OpCodes.Ldloca, local); il.Emit(OpCodes.Call, data.ReaderMethodInfo); // write result object to out object il.Emit(OpCodes.Ldarg_2); if (local.LocalIndex < 256) il.Emit(OpCodes.Ldloc_S, local); else il.Emit(OpCodes.Ldloc, local); if (type.IsValueType) il.Emit(OpCodes.Box, type); il.Emit(OpCodes.Stind_Ref); il.Emit(OpCodes.Ret); } }
public static void GenerateDeserializerSwitch(CodeGenContext ctx, ILGenerator il, IDictionary<Type, TypeData> map) { // arg0: stream, arg1: out object var idLocal = il.DeclareLocal(typeof(ushort)); // read typeID il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldloca_S, idLocal); il.EmitCall(OpCodes.Call, ctx.GetReaderMethodInfo(typeof(ushort)), null); // +1 for 0 (null) var jumpTable = new Label[map.Count + 1]; jumpTable[0] = il.DefineLabel(); foreach (var kvp in map) jumpTable[kvp.Value.TypeID] = il.DefineLabel(); il.Emit(OpCodes.Ldloc_S, idLocal); il.Emit(OpCodes.Switch, jumpTable); ConstructorInfo exceptionCtor = typeof(Exception).GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, new Type[0], null); il.Emit(OpCodes.Newobj, exceptionCtor); il.Emit(OpCodes.Throw); /* null case */ il.MarkLabel(jumpTable[0]); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldnull); il.Emit(OpCodes.Stind_Ref); il.Emit(OpCodes.Ret); /* cases for types */ foreach (var kvp in map) { var type = kvp.Key; var data = kvp.Value; il.MarkLabel(jumpTable[data.TypeID]); var local = il.DeclareLocal(type); // call deserializer for this typeID il.Emit(OpCodes.Ldarg_0); if (local.LocalIndex < 256) il.Emit(OpCodes.Ldloca_S, local); else il.Emit(OpCodes.Ldloca, local); il.EmitCall(OpCodes.Call, data.ReaderMethodInfo, null); // write result object to out object il.Emit(OpCodes.Ldarg_1); if (local.LocalIndex < 256) il.Emit(OpCodes.Ldloc_S, local); else il.Emit(OpCodes.Ldloc, local); if (type.IsValueType) il.Emit(OpCodes.Box, type); il.Emit(OpCodes.Stind_Ref); il.Emit(OpCodes.Ret); } }
public void GenerateReaderMethod(Type type, CodeGenContext ctx, ILGenerator il) { var elemType = type.GetElementType(); var lenLocal = il.DeclareLocal(typeof(uint)); // read array len il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldloca_S, lenLocal); il.Emit(OpCodes.Call, ctx.GetReaderMethodInfo(typeof(uint))); var notNullLabel = il.DefineLabel(); /* if len == 0, return null */ il.Emit(OpCodes.Ldloc_S, lenLocal); il.Emit(OpCodes.Brtrue_S, notNullLabel); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldnull); il.Emit(OpCodes.Stind_Ref); il.Emit(OpCodes.Ret); il.MarkLabel(notNullLabel); var arrLocal = il.DeclareLocal(type); // create new array with len - 1 il.Emit(OpCodes.Ldloc_S, lenLocal); il.Emit(OpCodes.Ldc_I4_1); il.Emit(OpCodes.Sub); il.Emit(OpCodes.Newarr, elemType); il.Emit(OpCodes.Stloc_S, arrLocal); // declare i var idxLocal = il.DeclareLocal(typeof(int)); // i = 0 il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Stloc_S, idxLocal); var loopBodyLabel = il.DefineLabel(); var loopCheckLabel = il.DefineLabel(); il.Emit(OpCodes.Br_S, loopCheckLabel); // loop body il.MarkLabel(loopBodyLabel); // read element to arr[i] var data = ctx.GetTypeDataForCall(elemType); if (data.NeedsInstanceParameter) { il.Emit(OpCodes.Ldarg_0); } il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldloc_S, arrLocal); il.Emit(OpCodes.Ldloc_S, idxLocal); il.Emit(OpCodes.Ldelema, elemType); il.Emit(OpCodes.Call, data.ReaderMethodInfo); // i = i + 1 il.Emit(OpCodes.Ldloc_S, idxLocal); il.Emit(OpCodes.Ldc_I4_1); il.Emit(OpCodes.Add); il.Emit(OpCodes.Stloc_S, idxLocal); il.MarkLabel(loopCheckLabel); // loop condition il.Emit(OpCodes.Ldloc_S, idxLocal); il.Emit(OpCodes.Ldloc_S, arrLocal); il.Emit(OpCodes.Ldlen); il.Emit(OpCodes.Conv_I4); il.Emit(OpCodes.Blt_S, loopBodyLabel); // store new array to the out value il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldloc_S, arrLocal); il.Emit(OpCodes.Stind_Ref); il.Emit(OpCodes.Ret); }
static void GenerateDeserializerSwitch(CodeGenContext ctx, ILGenerator il, IDictionary <Type, TypeData> map) { // arg0: stream, arg1: out object D(il, "deser switch"); var idLocal = il.DeclareLocal(typeof(ushort)); // read typeID il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldloca_S, idLocal); il.EmitCall(OpCodes.Call, ctx.GetReaderMethodInfo(typeof(ushort)), null); // +1 for 0 (null) var jumpTable = new Label[map.Count + 1]; jumpTable[0] = il.DefineLabel(); foreach (var kvp in map) { jumpTable[kvp.Value.TypeID] = il.DefineLabel(); } il.Emit(OpCodes.Ldloc_S, idLocal); il.Emit(OpCodes.Switch, jumpTable); D(il, "eihx"); //il.ThrowException(typeof(Exception)); /* null case */ il.MarkLabel(jumpTable[0]); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldnull); il.Emit(OpCodes.Stind_Ref); il.Emit(OpCodes.Ret); /* cases for types */ foreach (var kvp in map) { var type = kvp.Key; var data = kvp.Value; il.MarkLabel(jumpTable[data.TypeID]); var local = il.DeclareLocal(type); // call deserializer for this typeID il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldloca_S, local); if (data.WriterMethodInfo.IsGenericMethodDefinition) { Debug.Assert(type.IsGenericType); var genArgs = type.GetGenericArguments(); il.EmitCall(OpCodes.Call, data.ReaderMethodInfo.MakeGenericMethod(genArgs), null); } else { il.EmitCall(OpCodes.Call, data.ReaderMethodInfo, null); } // write result object to out object il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldloc_S, local); if (type.IsValueType) { il.Emit(OpCodes.Box, type); } il.Emit(OpCodes.Stind_Ref); D(il, "deser switch done"); il.Emit(OpCodes.Ret); } }
static void GenerateDeserializerSwitch(CodeGenContext ctx, ILGenerator il, IDictionary<Type, TypeData> map) { // arg0: stream, arg1: out object D(il, "deser switch"); var idLocal = il.DeclareLocal(typeof(ushort)); // read typeID il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldloca_S, idLocal); il.EmitCall(OpCodes.Call, ctx.GetReaderMethodInfo(typeof(ushort)), null); // +1 for 0 (null) var jumpTable = new Label[map.Count + 1]; jumpTable[0] = il.DefineLabel(); foreach (var kvp in map) jumpTable[kvp.Value.TypeID] = il.DefineLabel(); il.Emit(OpCodes.Ldloc_S, idLocal); il.Emit(OpCodes.Switch, jumpTable); D(il, "eihx"); //il.ThrowException(typeof(Exception)); /* null case */ il.MarkLabel(jumpTable[0]); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldnull); il.Emit(OpCodes.Stind_Ref); il.Emit(OpCodes.Ret); /* cases for types */ foreach (var kvp in map) { var type = kvp.Key; var data = kvp.Value; il.MarkLabel(jumpTable[data.TypeID]); var local = il.DeclareLocal(type); // call deserializer for this typeID il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldloca_S, local); if (data.WriterMethodInfo.IsGenericMethodDefinition) { Debug.Assert(type.IsGenericType); var genArgs = type.GetGenericArguments(); il.EmitCall(OpCodes.Call, data.ReaderMethodInfo.MakeGenericMethod(genArgs), null); } else { il.EmitCall(OpCodes.Call, data.ReaderMethodInfo, null); } // write result object to out object il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldloc_S, local); if (type.IsValueType) il.Emit(OpCodes.Box, type); il.Emit(OpCodes.Stind_Ref); D(il, "deser switch done"); il.Emit(OpCodes.Ret); } }
static void GenDeserializerBodyForArray(CodeGenContext ctx, Type type, ILGenerator il) { var elemType = type.GetElementType(); var lenLocal = il.DeclareLocal(typeof(uint)); // read array len il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldloca_S, lenLocal); il.Emit(OpCodes.Ldarg_2); il.EmitCall(OpCodes.Call, ctx.GetReaderMethodInfo(typeof(uint)), null); var notNullLabel = il.DefineLabel(); var dataLabel = il.DefineLabel(); var refLabel = il.DefineLabel(); /* if len == 0, return null */ il.Emit(OpCodes.Ldloc_S, lenLocal); il.Emit(OpCodes.Brtrue_S, notNullLabel); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldnull); il.Emit(OpCodes.Stind_Ref); il.Emit(OpCodes.Ret); il.MarkLabel(notNullLabel); var arrLocal = il.DeclareLocal(type); // create new array with len - 1 il.Emit(OpCodes.Ldloc_S, lenLocal); il.Emit(OpCodes.Ldc_I4_1); il.Emit(OpCodes.Sub); il.Emit(OpCodes.Newarr, elemType); il.Emit(OpCodes.Stloc_S, arrLocal); // declare i var idxLocal = il.DeclareLocal(typeof(int)); // i = 0 il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Stloc_S, idxLocal); var loopBodyLabel = il.DefineLabel(); var loopCheckLabel = il.DefineLabel(); il.Emit(OpCodes.Br_S, loopCheckLabel); // loop body il.MarkLabel(loopBodyLabel); // read element to arr[i] il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldloc_S, arrLocal); il.Emit(OpCodes.Ldloc_S, idxLocal); il.Emit(OpCodes.Ldelema, elemType); il.Emit(OpCodes.Ldarg_2); GenDeserializerCall(ctx, il, elemType); // i = i + 1 il.Emit(OpCodes.Ldloc_S, idxLocal); il.Emit(OpCodes.Ldc_I4_1); il.Emit(OpCodes.Add); il.Emit(OpCodes.Stloc_S, idxLocal); il.MarkLabel(loopCheckLabel); // loop condition il.Emit(OpCodes.Ldloc_S, idxLocal); il.Emit(OpCodes.Ldloc_S, arrLocal); il.Emit(OpCodes.Ldlen); il.Emit(OpCodes.Conv_I4); il.Emit(OpCodes.Clt); il.Emit(OpCodes.Brtrue_S, loopBodyLabel); // store new array to the out value il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldloc_S, arrLocal); il.Emit(OpCodes.Stind_Ref); Type objStackType = typeof(ObjectList); MethodInfo getAddMethod = objStackType.GetMethod("Add", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(object) }, null); var endLabel = il.DefineLabel(); //==if(objList==null) goto endLabel; il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Brfalse_S, endLabel); //== objList.Add(value); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldarg_1); il.EmitCall(OpCodes.Call, getAddMethod, null); il.MarkLabel(endLabel); il.Emit(OpCodes.Ret); }
void GenerateDynamic(Dictionary<Type, TypeData> map) { /* generate stubs */ foreach (var kvp in map) { var type = kvp.Key; var td = kvp.Value; if (!td.IsGenerated) continue; td.WriterMethodInfo = Helpers.GenerateDynamicSerializerStub(type); td.ReaderMethodInfo = Helpers.GenerateDynamicDeserializerStub(type); } var ctx = new CodeGenContext(map); /* generate bodies */ foreach (var kvp in map) { var type = kvp.Key; var td = kvp.Value; if (!td.IsGenerated) continue; var writerDm = (DynamicMethod)td.WriterMethodInfo; td.TypeSerializer.GenerateWriterMethod(type, ctx, writerDm.GetILGenerator()); var readerDm = (DynamicMethod)td.ReaderMethodInfo; td.TypeSerializer.GenerateReaderMethod(type, ctx, readerDm.GetILGenerator()); } var writer = (DynamicMethod)ctx.GetWriterMethodInfo(typeof(object)); var reader = (DynamicMethod)ctx.GetReaderMethodInfo(typeof(object)); m_serializerSwitch = (SerializerSwitch)writer.CreateDelegate(typeof(SerializerSwitch)); m_deserializerSwitch = (DeserializerSwitch)reader.CreateDelegate(typeof(DeserializerSwitch)); }