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);
        }
Esempio n. 2
0
        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);
        }
Esempio n. 4
0
		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);
        }
Esempio n. 7
0
        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);
        }
Esempio n. 10
0
        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);
            }
        }
Esempio n. 12
0
        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);
        }
Esempio n. 13
0
        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);
            }
        }
Esempio n. 14
0
        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);
        }
Esempio n. 16
0
        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);
        }
Esempio n. 17
0
        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));
        }