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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With