C # ILGenerator nop?

Im generating some IL with ILGenerator, here is my code:

DynamicMethod method = new DynamicMethod("test", null, Type.EmptyTypes); ILGenerator gen = method.GetILGenerator(); gen.Emit(OpCodes.Ldarg_0); gen.Emit(OpCodes.Ldarg_1); gen.Emit(OpCodes.Ldc_I4_S, 100); 

This generated this IL:

 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: ldc.i4.s 100 IL_0004: nop IL_0005: nop IL_0006: nop 

(I get the IL code from VS-Virtulizer named ILStream)

Where does the nops code come from? is there any way to get rid of them? Im trying to imitate some C # code and does not have 3 nops.

+6
c # cil
source share
2 answers

I solved the problem by translating int to value:

the code:

 private static bool IsBetween(int value, int min, int max) { return (value >= min && value <= max); } private static void WriteInt(ILGenerator gen, int value) { gen.Emit(OpCodes.Ldarg_1); if (IsBetween(value, sbyte.MinValue, sbyte.MaxValue)) { gen.Emit(OpCodes.Ldc_I4_S, (sbyte)value); } else if (IsBetween(value, byte.MinValue, byte.MaxValue)) { gen.Emit(OpCodes.Ldc_I4_S, (byte)value); } else if (IsBetween(value, short.MinValue, short.MaxValue)) { gen.Emit(OpCodes.Ldc_I4_S, (short)value); } else { gen.Emit(OpCodes.Ldc_I4_S, value); } } 
+3
source share

You are in the right direction to get rid of "nop" s:

When you provide an additional argument for calling Emit, always check the MSDN for the correct type of argument.

For OpCodes.Ldc_I4_S, MSDN declares:

ldc.i4.s is a more efficient encoding for pushing integers from -128 to 127 onto the stack> evaluation.

The following Emit method overload may use the ldc.i4.s opcode:

ILGenerator.Emit (OpCode, byte)

Thus, the second part of your code will have unpredictable results (besides these pesky nop) at runtime, since you are trying to load "int8" on the stack, but providing "int32" or "short", Value:

 else if (IsBetween(value, short.MinValue, short.MaxValue)) { gen.Emit(OpCodes.Ldc_I4_S, (short)value); } else { gen.Emit(OpCodes.Ldc_I4_S, value); } 

You should use Ldc_I4 instead of Ldc_I4_S if you want to correctly load int32 / short (or something larger than a byte) onto the stack. So your code should look like the one shown above:

 else { gen.Emit(OpCodes.Ldc_I4, value); } 

This is a wild hunch, but the three new ones that were generated should probably do something with extra bytes from your int32

Hope this helps ...

+8
source share

All Articles