MI3Guy
MI3Guy

Reputation: 317

Error in IL Code using Reflection.Emit

I am writing a compiler that is generating .NET IL. I am writing it on Linux Mint using C#/Mono.

There is issue with some code that I am generating using Reflection.Emit. Please excuse the horrible names in the generated code. Below is the relevant part of the output from monodis.

.method public static 
       default valuetype Argon.30 Argon.28313529 (valuetype Argon.35 A_0)  cil managed 
{
    // Method begins at RVA 0x215c
// Code size 73 (0x49)
.maxstack 10
.locals init (
    valuetype Argon.35  V_0,
    valuetype Argon.35  V_1)
IL_0000:  ldarg.0 
IL_0001:  stloc.0 
IL_0002:  ldloca.s 0
IL_0004:  ldc.i4.7 
IL_0005:  newobj instance void valuetype Argon.35::'.ctor'(int32)
IL_000a:  call instance valuetype Argon.35 valuetype Argon.35::'add'(valuetype Argon.35)
IL_000f:  stloc.0 
IL_0010:  ldloc.0 
IL_0011:  stloc.1 
IL_0012:  ldloca.s 1
IL_0014:  ldc.i4.2 
IL_0015:  newobj instance void valuetype Argon.35::'.ctor'(int32)
IL_001a:  call instance valuetype Argon.35 valuetype Argon.35::'sub'(valuetype Argon.35)
IL_001f:  stloc.0 
IL_0020:  ldsfld class Argon.747970655F30 Argon.747970655F30::'instance'
IL_0025:  call valuetype Argon.30 Argon.283129()
IL_002a:  pop 
IL_002b:  ldarg.0 
IL_002c:  call valuetype Argon.30 Argon.28313229(valuetype Argon.35)
IL_0031:  pop 
IL_0032:  ldstr " + 5 = "
IL_0037:  newobj instance void class Argon.32::'.ctor'(string)
IL_003c:  call valuetype Argon.30 Argon.28313129(class Argon.32)
IL_0041:  pop 
IL_0042:  ldloc.0 
IL_0043:  call valuetype Argon.30 Argon.28313229(valuetype Argon.35)
IL_0048:  ret 
} // end of global method Argon.28313529

When I run this in mono I get the following error.

System.InvalidProgramException: Invalid IL code in :Argon.28313529 (Argon.35): IL_0048: ret

There appears to be no issue running this under Microsoft .NET. As I understand, that is due to mono performing the checks before optimizations.

Also, a previous version of the code without the error is below.

.method public static 
       default valuetype Argon.30 Argon.28313529 (valuetype Argon.35 A_0)  cil managed 
{
    // Method begins at RVA 0x215c
// Code size 46 (0x2e)
.maxstack 6
.locals init (
    valuetype Argon.35  V_0)
IL_0000:  ldarg.0 
IL_0001:  stloc.0 
IL_0002:  ldloca.s 0
IL_0004:  ldc.i4.7 
IL_0005:  newobj instance void valuetype Argon.35::'.ctor'(int32)
IL_000a:  call instance valuetype Argon.35 valuetype Argon.35::'add'(valuetype Argon.35)
IL_000f:  stloc.0 
IL_0010:  ldarg.0 
IL_0011:  call valuetype Argon.30 Argon.28313229(valuetype Argon.35)
IL_0016:  pop 
IL_0017:  ldstr " + 5 = "
IL_001c:  newobj instance void class Argon.32::'.ctor'(string)
IL_0021:  call valuetype Argon.30 Argon.28313129(class Argon.32)
IL_0026:  pop 
IL_0027:  ldloc.0 
IL_0028:  call valuetype Argon.30 Argon.28313229(valuetype Argon.35)
IL_002d:  ret 
} // end of global method Argon.28313529

Upvotes: 1

Views: 520

Answers (2)

Hans Passant
Hans Passant

Reputation: 942508

The instruction at IL_0020 unbalances the stack, it should not have been emitted. This looks like a bug in your language parser. Equivalent to not reporting this kind of coding mistake:

class Example {
    Example instance;
    static void Method() { }
    void Bug() {
        instance.Method();    // CS0176
    }
}

Upvotes: 4

Iridium
Iridium

Reputation: 23731

Aren't you leaving the instance of Argon.747970655F30 put on the stack at IL_0020, in addition to the instance of Argon.30 returned by the instruction at IL_0043? That would leave 2 items on the stack when you ret, rather than one.

Upvotes: 4

Related Questions