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(); } }
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(); } }
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); }
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); }
/// <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); }
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 (); } }
/// <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 }