Пример #1
0
 public static void EmitSt(this ILGenerator il, Variable v) {
     switch (v.VarType) {
         case VariableType.Arg:
             EmitStarg(il, v);
             break;
         case VariableType.Local:
             EmitStloc(il, v);
             break;
         default:
             throw new ArgumentException();
     }
 }
Пример #2
0
        public static void EmitLdloc(this ILGenerator il, Variable v) {
            if (v.VarType != VariableType.Local)
                throw new ArgumentException();

            switch (v.Index) {
                case 0: il.Emit(OpCodes.Ldloc_0); return;
                case 1: il.Emit(OpCodes.Ldloc_1); return;
                case 2: il.Emit(OpCodes.Ldloc_2); return;
                case 3: il.Emit(OpCodes.Ldloc_3); return;
            }
            if (v.Index <= byte.MaxValue) {
                il.Emit(OpCodes.Ldloc_S, (byte)v.Index);
            } else if (v.Index <= short.MaxValue) {
                il.Emit(OpCodes.Ldloc, v.Index);
            } else {
                throw new FormatException();
            }
        }
Пример #3
0
		static void EmitPackArrayCode (MethodInfo mi, ILGenerator il, Type t, Variable var_writer, Variable var_obj, Variable var_loop, Func<Type, MethodInfo> lookupPackMethod)
		{
			Type et = t.GetElementType ();
			il.EmitLd (var_writer, var_obj);
			il.Emit (OpCodes.Ldlen);
			il.Emit (OpCodes.Call, typeof(MsgPackWriter).GetMethod("WriteArrayHeader", new Type[]{ typeof(int) }));

			Label beginLabel = il.DefineLabel ();
			Label exprLabel = il.DefineLabel ();

			// for-loop: init loop counter
			il.EmitLdc (0);
			il.EmitSt (var_loop);

			// jump
			il.Emit (OpCodes.Br_S, exprLabel);

			// mark begin-label
			il.MarkLabel (beginLabel);

			// write element
			EmitPackMemberValueCode (et, il, var_writer, var_obj, null, var_loop, t, mi, lookupPackMethod);

			// increment loop-counter
			il.EmitLd (var_loop);
			il.Emit (OpCodes.Ldc_I4_1);
			il.Emit (OpCodes.Add);
			il.EmitSt (var_loop);

			// mark expression label
			il.MarkLabel (exprLabel);

			// expression
			il.EmitLd (var_loop, var_obj);
			il.Emit (OpCodes.Ldlen);
			il.Emit (OpCodes.Blt_S, beginLabel);
		}
Пример #4
0
		static void EmitUnpackReadAndTypeCheckCode (ILGenerator il, Variable msgpackReader, MethodInfo typeCheckMethod, MethodInfo failedMethod, bool nullCheckAndReturn)
		{
			Label lblFailed = il.DefineLabel ();
			Label lblNullReturn = nullCheckAndReturn ? il.DefineLabel () : default(Label);
			Label lblPassed = il.DefineLabel ();
			il.EmitLd (msgpackReader);
			il.Emit (OpCodes.Call, typeof (MsgPackReader).GetMethod ("Read"));
			il.Emit (OpCodes.Brfalse_S, lblFailed);
			if (nullCheckAndReturn) {
				il.EmitLd (msgpackReader);
				il.Emit (OpCodes.Call, typeof (MsgPackReader).GetProperty ("Type").GetGetMethod ());
				il.EmitLdc ((int)TypePrefixes.Nil);
				il.Emit (OpCodes.Beq_S, lblNullReturn);
			}
			il.EmitLd (msgpackReader);
			il.Emit (OpCodes.Call, typeCheckMethod);
			il.Emit (OpCodes.Brtrue_S, lblPassed);
			il.Emit (OpCodes.Br, lblFailed);
			if (nullCheckAndReturn) {
				il.MarkLabel (lblNullReturn);
				il.Emit (OpCodes.Ldnull);
				il.Emit (OpCodes.Ret);
			}
			il.MarkLabel (lblFailed);
			il.Emit (OpCodes.Call, failedMethod);
			il.MarkLabel (lblPassed);
		}
Пример #5
0
		/// <param name="m">(optional)</param>
		/// <param name="elementIdx">(optional)</param>
		static void EmitPackMemberValueCode (Type type, ILGenerator il, Variable var_writer, Variable var_obj,
			MemberInfo m, Variable elementIdx, Type currentType, MethodInfo currentMethod, Func<Type, MethodInfo> lookupPackMethod)
		{
			MethodInfo mi;
			il.EmitLd (var_writer, var_obj);
			if (m != null)
				il.EmitLdMember (m);
			if (elementIdx != null) {
				il.EmitLd (elementIdx);
				il.Emit (OpCodes.Ldelem, type);
			}
			if (type.IsPrimitive) {
				mi = typeof(MsgPackWriter).GetMethod("Write", new Type[]{type});
			} else {
				if (currentType == type) {
					mi = currentMethod;
				} else {
					mi = lookupPackMethod (type);
				}
			}
			il.Emit (OpCodes.Call, mi);
		}
Пример #6
0
		public static void EmitStarg (this ILGenerator il, Variable v)
		{
			if (v.VarType != VariableType.Arg)
				throw new ArgumentException ();

			if (v.Index <= byte.MaxValue) {
				il.Emit (OpCodes.Starg_S, (byte)v.Index);
			} else if (v.Index <= short.MaxValue) {
				il.Emit (OpCodes.Starg, v.Index);
			} else {
				throw new FormatException ();
			}
		}
Пример #7
0
        /// <summary>
        /// Emits IL code to pack a Map based on IDictionary.
        /// </summary>
        /// <param name="currentMethod">Current method info.</param>
        /// <param name="gen">il buffer/generator</param>
        /// <param name="type">Current type</param>
        /// <param name="arg_writer">packer object</param>
        /// <param name="arg_obj">current object</param>
        /// <param name="lookupPackMethod">dictionary to look for methods</param>
        public static void EmitPackIL(MethodInfo currentMethod, ILGenerator gen, Type type, Variable arg_writer, Variable arg_obj, Func<Type, MethodInfo> lookupPackMethod)
        {
            Type keyType = type.GetGenericArguments()[0];
            Type valueType = type.GetGenericArguments()[1];
            Type keyValuePairType = typeof(KeyValuePair<,>).MakeGenericType(keyType, valueType);

            // Preparing Reflection instances
            MethodInfo getCount = typeof(ICollection<>).MakeGenericType(keyValuePairType).GetMethod(
                "get_Count",
                BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                null,
                new Type[]{
            },
                null
                );
            MethodInfo writeMapHeader = typeof(MsgPackWriter).GetMethod(
                "WriteMapHeader",
                BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                null,
                new Type[]{
            typeof(Int32)
            },
                null
                );
            MethodInfo getEnumerator = typeof(IEnumerable<>).MakeGenericType(keyValuePairType).GetMethod(
                "GetEnumerator",
                BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                null,
                new Type[]{
            },
                null
                );
            MethodInfo getCurrent = typeof(IEnumerator<>).MakeGenericType(keyValuePairType).GetMethod(
                "get_Current",
                BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                null,
                new Type[]{ },
                null
                );
            MethodInfo getKey = keyValuePairType.GetMethod(
                "get_Key",
                BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                null,
                new Type[]{ },
                null
                );

            MethodInfo getValue = keyValuePairType.GetMethod(
                "get_Value",
                BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                null,
                new Type[]{ },
                null
                );
            MethodInfo moveNext = typeof(IEnumerator).GetMethod(
                "MoveNext",
                BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                null,
                new Type[]{ },
                null
                );
            MethodInfo dispose = typeof(IDisposable).GetMethod(
                "Dispose",
                BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                null,
                new Type[]{ },
                null
                );

            // Preparing locals
            LocalBuilder keyValuepair = gen.DeclareLocal(keyValuePairType);
            LocalBuilder enumerator = gen.DeclareLocal(typeof(System.Collections.Generic.IEnumerator<>).MakeGenericType(keyValuePairType));
            Variable localValue = Variable.CreateLocal(gen.DeclareLocal(valueType));

            // Preparing labels
            Label getNext = gen.DefineLabel();
            Label work = gen.DefineLabel();
            Label end = gen.DefineLabel();
            Label endFinally = gen.DefineLabel();

            // Writing body
            gen.Emit(OpCodes.Ldarg_0);
            gen.Emit(OpCodes.Ldarg_1);
            gen.Emit(OpCodes.Callvirt, getCount);
            gen.Emit(OpCodes.Callvirt, writeMapHeader);
            gen.Emit(OpCodes.Ldarg_1);
            gen.Emit(OpCodes.Callvirt, getEnumerator);
            gen.Emit(OpCodes.Stloc_1);
            gen.BeginExceptionBlock();
            gen.Emit(OpCodes.Br_S, getNext);
            gen.MarkLabel(work);
            gen.Emit(OpCodes.Ldloc_1);
            gen.Emit(OpCodes.Callvirt, getCurrent);
            gen.Emit(OpCodes.Stloc_0);
            gen.Emit(OpCodes.Ldarg_0);
            gen.Emit(OpCodes.Ldloca_S, 0);
            gen.Emit(OpCodes.Call, getKey);
            EmitPack(gen, keyType, type, currentMethod, lookupPackMethod);
            gen.Emit(OpCodes.Ldarg_0);
            gen.Emit(OpCodes.Ldloca_S, 0);
            gen.Emit(OpCodes.Call, getValue);
            EmitPack(gen, valueType, type, currentMethod, lookupPackMethod);
            gen.MarkLabel(getNext);
            gen.Emit(OpCodes.Ldloc_1);
            gen.Emit(OpCodes.Callvirt, moveNext);
            gen.Emit(OpCodes.Brtrue_S, work);
            gen.Emit(OpCodes.Leave_S, end);
            gen.BeginFinallyBlock();
            gen.Emit(OpCodes.Ldloc_1);
            gen.Emit(OpCodes.Brfalse_S, endFinally);
            gen.Emit(OpCodes.Ldloc_1);
            gen.Emit(OpCodes.Callvirt, dispose);
            gen.MarkLabel(endFinally);
            gen.Emit(OpCodes.Endfinally);
            gen.EndExceptionBlock();
            gen.MarkLabel(end);
            gen.Emit(OpCodes.Ret); // <- Yep, I know there is a Ret in the calling function.
            // finished
        }