Creating an IL instruction with an inline argument using Mono.Cecil
.net, mono.cecil, mutation-testing
Solution
You have two kinds of opcodes here, `ldarg.0`, and `ldarg` (and its _s) variant.
The first one is a “macro” opcode, meaning that it's used to reduce the size of the code for typically used values.
If you need to modify the parameters of a method, I suggest you firs transform all macro opcodes to a complete form, this is done using the `SimplifyMacros()` extension method on `MethodBody` from the helper library Mono.Cecil.Rocks:
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Cecil.Rocks;
// ..
method.Body.SimplifyMacros();
When this is done, an existing `ldarg.0` instruction will now be `ldarg` with the correct operand, which is as you guessed, a `ParameterDefinition`.
With that in place, you can re-order the parameters, and create new instructions:
var il = method.Body.GetILProcessor();
var instruction = il.Create(OpCodes.Ldarg, aParameterDefinition);
il.InsertBefore(xxx, instruction);
When you're done, you can call the inverse of `SimplifyMacros()`, `OptimizeMacros()`, which will try to, well, optimize the opcodes into their macro form if possible.
One thing you'll have to take care of, is that the first argument of a instance method, the implicit “this”, is represented with the `method.Body.ThisParameter` special parameter which you won't find in the .Parameters collection of the method.
Problem
I'm playing with mutation testing at the moment. One of the mutations I'm looking at involves swapping parameters, for which I may need to swap, for example `Ldarg.0` and `Ldarg_S` with an operand indicating the index. The operand type for this is an inline arg, which in Mono.Cecil I believe requires me to create a properly instantiated `ParameterDefinition` to store the 32-bit int index. Does anyone have enough experience with Cecil to point me in the right direction of an easy way to create an `Instruction` instance with `OpCode` of `Ldarg_S` and an `Operand` of the appropriate type?