Reputation: 317
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
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
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