Emit IL Like C# Method IL But Get System.InvalidProgramException : Common Language Runtime detected an invalid program.
Example :
public static int BoolToInt(this bool input)
{
return input ? 1 : 0;
}
IL Code Is :
ExtensionDataGetter.BoolToInt:
IL_0000: nop
IL_0001: ldarg.0
IL_0002: brtrue.s IL_0007
IL_0004: ldc.i4.0
IL_0005: br.s IL_0008
IL_0007: ldc.i4.1
IL_0008: stloc.0
IL_0009: br.s IL_000B
IL_000B: ldloc.0
IL_000C: ret
I try using Emit IL to create this method :
class Program
{
static void Main(string[] args)
{
var result = CreateFunc()(true);
Console.WriteLine(result);
}
static Func<bool, int> CreateFunc()
{
var dm = new DynamicMethod("Test" + Guid.NewGuid().ToString(), typeof(int), new[] { typeof(bool) });
var il = dm.GetILGenerator();
il.Emit(OpCodes.Nop);
il.Emit(OpCodes.Ldarg_0);
var labelTrue = il.DefineLabel();
var labelStloc = il.DefineLabel();
var labelReturn = il.DefineLabel();
il.Emit(OpCodes.Brtrue_S, labelTrue);
il.Emit(OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Br_S, labelStloc);
il.MarkLabel(labelTrue);
il.Emit(OpCodes.Ldc_I4_1);
il.MarkLabel(labelStloc);
il.Emit(OpCodes.Stloc_0);
il.Emit(OpCodes.Br_S, labelReturn);
il.MarkLabel(labelReturn);
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ret);
var funcType = System.Linq.Expressions.Expression.GetFuncType(typeof(bool), typeof(int));
return (Func<bool, int>)dm.CreateDelegate(funcType);
}
}
But get below error
System.InvalidProgramException
HResult=0x8013153A
Message=Common Language Runtime detected an invalid program.
Source=<Cannot evaluate the exception source>
StackTrace:
<Cannot evaluate the exception stack trace>
I try to write a new version by my logic and it's work.
but it's IL not eqauls demo method's IL
using System;
using System.Reflection;
using System.Reflection.Emit;
class Program
{
static void Main(string[] args)
{
var func = CreateFunc();
Console.WriteLine(func(true));
Console.WriteLine(func(false));
}
static Func<bool, int> CreateFunc()
{
var dm = new DynamicMethod("Test" + Guid.NewGuid().ToString(), typeof(int), new[] { typeof(bool) });
var il = dm.GetILGenerator();
var labelTrue = il.DefineLabel();
il.Emit(OpCodes.Nop);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Brtrue_S, labelTrue);
il.Emit(OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Ret);
il.MarkLabel(labelTrue);
il.Emit(OpCodes.Ldc_I4_1);
il.Emit(OpCodes.Ret);
var funcType = System.Linq.Expressions.Expression.GetFuncType(typeof(bool), typeof(int));
return (Func<bool, int>)dm.CreateDelegate(funcType);
}
}
Since you are storing a value in a local variable with stloc.0, you need to declare it:
var il = dm.GetILGenerator();
il.DeclareLocal(typeof(int));
Your second version uses no locals so it does not have this issue.
The first version is what the compiler emits in debug mode, but in release mode it is more like your second example (except for the nop which is unnecessary).
User contributions licensed under CC BY-SA 3.0