Reputation: 6873
I want to create some dynamic method whcih has 2 cycles: in first some N values are pushed onto evaluation stack, in second - these N values are popped from stack. But CreateMethod throws InvalidProgramException. How I can realize what I want? My code is:
public static Action MakeSimpleAction()
{
var dm = new DynamicMethod("evil", typeof(void), new Type[] { }, true);
var il = dm.GetILGenerator(); Label startCycle;
il.DeclareLocal(typeof(int)); //i = 0
//Method 1: All is OK!
//il.Emit(OpCodes.Ldc_I4_0); //Push 0 onto evaluation stack
//il.Emit(OpCodes.Pop); //Pop value from evaluation stack
//il.Emit(OpCodes.Ret);
//Method 2: In cycles - throws an exception!
//First cycle: for (int i = 0; i < 5; i ++) Push(0);
il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Stloc_0); //i = 0
il.MarkLabel(startCycle = il.DefineLabel());
il.Emit(OpCodes.Ldc_I4_0); //Push 0 onto evaluation stack
il.Emit(OpCodes.Ldloc_0); //i ++
il.Emit(OpCodes.Ldc_I4_1);
il.Emit(OpCodes.Add);
il.Emit(OpCodes.Stloc_0);
//if i < 5 goto startCycle
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldc_I4_5);
il.Emit(OpCodes.Clt); //if i < 5
il.Emit(OpCodes.Brtrue_S, startCycle);
//Second cycle: for (int i = 0; i < 5; i ++) Pop();
il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Stloc_0); //i = 0
il.MarkLabel(startCycle = il.DefineLabel());
il.Emit(OpCodes.Pop); //Pop value from evaluation stack
il.Emit(OpCodes.Ldloc_0); //i ++
il.Emit(OpCodes.Ldc_I4_1);
il.Emit(OpCodes.Add);
il.Emit(OpCodes.Stloc_0);
//if i < 5 goto startCycle
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldc_I4_5);
il.Emit(OpCodes.Clt); //if i < 5
il.Emit(OpCodes.Brtrue_S, startCycle);
il.Emit(OpCodes.Ret);
//throw System.InvalidProgramException: 'Common Language Runtime detected an invalid program.'
return (Action)dm.CreateDelegate(typeof(Action));
}
Upvotes: 0
Views: 48