luiscubal
luiscubal

Reputation: 25121

Help with InvalidProgramException (Invalid IL Code?)

I'm getting a weird bug in an assembly exported with System.Reflection.Emit with mono. When attempting to run my assembly, I get an InvalidProgramException: Invalid IL code.

monodis gives me this CIL result(which is consistent with what I export with Emit):

.method public static hidebysig 
       default void f_main (class [Pine.Core]Pine.Core.Function A_0, class [Pine.Core]Pine.Core.ValueList A_1)  cil managed 
{
    // Method begins at RVA 0x2144
    // Code size 26 (0x1a)
    .maxstack 4
    .locals init (
        class [Pine.Core]Pine.Core.Function V_0,
        class [Pine.Core]Pine.Core.IScope   V_1,
        class [Pine.Core]Pine.Core.ValueList    V_2,
        class [Pine.Core]Pine.Core.IScope   V_3)
    IL_0000:  ldarg.0 
    IL_0001:  stloc.0 
    IL_0002:  ldarg.1 
    IL_0003:  stloc.2 
    IL_0004:  ldloc.0 
    IL_0005:  ldftn instance class [Pine.Core]Pine.Core.IScope class [Pine.Core]Pine.Core.Function::get_Scope()
    IL_000b:  stloc.1 
    IL_000c:  ldloc.1 
    IL_000d:  newobj instance void class [Pine.Core]Pine.Core.BlockScope::'.ctor'(class [Pine.Core]Pine.Core.IScope)
    IL_0012:  stloc.3 
    IL_0013:  ldloc.2 
    IL_0014:  call instance void class [Pine.Core]Pine.Core.ValueList::Clear()
    IL_0019:  ret 
} // end of method PineType::f_main

The error happens in IL_000b: stloc.1 I have no idea why.

I tried to replace the stloc.1 by a pop instruction. When I do that the error happens in IL_0019: ret

I really don't know why this is behaving like this. Any ideas?

Additional Information:

Upvotes: 1

Views: 4456

Answers (1)

user530189
user530189

Reputation:

Edit: judging from the code, perhaps IL_0005 is meant to be a call/callvirt and not a ldftn? Perhaps the emitting is using the wrong opcode?

Local 1 is an IScope. ldftn pushes a function pointer (native int) onto the evaluation stack. The store instruction at IL_000b fails verifiability, as a native int is not verifier-assignable-to IScope.

As for your second problem, you've unbalanced the evaluation stack with the instruction at IL_0004. ldftn's stack transition is " ... -> ..., ftn". Meaning it doesn't take an evaluation stack argument, only the immediate metadata token. By changing IL_000b to a pop, you pop what ldftn pushed, but not what IL_0004 pushed.

What isn't clear to me is what you're attempting to do. You can't treat a single function pointer as an interface (which you could think of, conceptually at least, as a pointer to a v-table). You would need to instantiate a type that implements the interface. What you could do with the function pointer is create a delegate from it - Delegate has an (object, native int) overload for .ctor. That would be where I assume the object reference pushed by IL_0004 would come into play (first argument to this .ctor). You could, of course, calli the function pointer directly as well. As I am unfamiliar with this object model you're interacting with, I can't say what the right approach is.

Upvotes: 5

Related Questions