ltrzesniewski / InlineIL.Fody

Inject arbitrary IL code at compile time.
MIT License
240 stars 17 forks source link

using ldarga.s makes compile error #1

Closed nthalpy closed 6 years ago

nthalpy commented 6 years ago

I was testing some stuffs on InlineIL.Fody, and I found that there are some problems on IL.Emit.Ldarga_S . After some tests, I found that using IL.Emit.Ldarga_S will always make some error.

This is my test code:

public void Foo(Object obj)
{
    IL.Emit.Ldarga_S(nameof(obj));
}
public void Bar(Object obj)
{
    IL.Emit.Ldarga(nameof(obj));
}

and emitted IL was (disassembled with ildasm):

.method public hidebysig instance void  Foo(object obj) cil managed
{
  // Code size       11 (0xb)
  .maxstack  1
  IL_0000:  ldstr      "InlineIL processing failed: Opcode ldarga.s expect"
  + "s an operand of type Int32 (in System.Void ILSniffets.Program::Foo(Syst"
  + "em.Object) at instruction IL_0006: call System.Void InlineIL.IL/Emit::L"
  + "darga_S(System.String))"
  IL_0005:  newobj     instance void [mscorlib]System.InvalidProgramException::.ctor(string)
  IL_000a:  throw
} // end of method Program::Foo

and

.method public hidebysig instance void  Bar(object obj) cil managed
{
  // Code size       5 (0x5)
  .maxstack  1
  IL_0000:  nop
  IL_0001:  ldarga.s   obj
  IL_0003:  nop
  IL_0004:  ret
} // end of method Program::Bar

According to the exception which method Foo throws, InlineIL expected Int32 typed operand after ldarga.s opcode, but as far as I know, ldargs.a opcode uses Unsigned Int8 typed operand. So I think there are some problem in code.

nthalpy commented 6 years ago

After some tests, I also found that using IL.Emit.Ldarg_S and IL.Emit.Starg_S makes errors. This two opcodes uses Unsigned Int8 typed operand too.

test code was:

public void Ldarg_S(Object obj)
{
    IL.Emit.Ldarg_S(nameof(obj));
}
public void Starg_S(Object obj)
{
    IL.Emit.Starg_S(nameof(obj));
}

and emitted IL was

.method public hidebysig instance void  Ldarg_S(object obj) cil managed
{
  // Code size       11 (0xb)
  .maxstack  1
  IL_0000:  ldstr      "InlineIL processing failed: Opcode ldarg.s expects"
  + " an operand of type Int32 (in System.Void ILSniffets.Program::Ldarg_S(S"
  + "ystem.Object) at instruction IL_0006: call System.Void InlineIL.IL/Emit"
  + "::Ldarg_S(System.String))"
  IL_0005:  newobj     instance void [mscorlib]System.InvalidProgramException::.ctor(string)
  IL_000a:  throw
} // end of method Program::Ldarg_S

and

.method public hidebysig instance void  Starg_S(object obj) cil managed
{
  // Code size       11 (0xb)
  .maxstack  1
  IL_0000:  ldstr      "InlineIL processing failed: Opcode starg.s expects"
  + " an operand of type Int32 (in System.Void ILSniffets.Program::Starg_S(S"
  + "ystem.Object) at instruction IL_0006: call System.Void InlineIL.IL/Emit"
  + "::Starg_S(System.String))"
  IL_0005:  newobj     instance void [mscorlib]System.InvalidProgramException::.ctor(string)
  IL_000a:  throw
} // end of method Program::Starg_S
ltrzesniewski commented 6 years ago

Thanks for the bug report!

Turns out I messed up a couple of operand types. This should be fixed in v0.6.1.

Also, please note that you can always use the long opcode forms. They will be converted to their short form when possible.

I'm actually wondering if I should remove the short forms altogether.