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, andldarg(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 onMethodBodyfrom the helper library Mono.Cecil.Rocks:When this is done, an existing
ldarg.0instruction will now beldargwith the correct operand, which is as you guessed, aParameterDefinition.With that in place, you can re-order the parameters, and create new instructions:
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.ThisParameterspecial parameter which you won’t find in the .Parameters collection of the method.