Emit IL Like C# Method IL But Get System.InvalidProgramException : Common Language Runtime detected an invalid program

1

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


c#
clr
emit
asked on Stack Overflow Sep 27, 2019 by Wei • edited Sep 27, 2019 by Wei

1 Answer

3

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).

answered on Stack Overflow Sep 27, 2019 by Mike Zboray

User contributions licensed under CC BY-SA 3.0