Hey Andriy,

There's code to do that in Mono.Cecil.Rocks,

You can call SimplifyMacros() to turn the short forms in the long
forms before modifying the code, and call OptimizeMacros afterwards.

Jb

On Fri, Nov 14, 2014 at 1:01 PM, Andriy Tylychko
<[email protected]> wrote:
> I'm looking for all assignments to a specific fields and replace them by a
> call to a generated method passing the field by ref. The problem is that
> existing short form instructions can be invalidated because now distance
> between the instruction and its target can be too long for short form. It's
> just an example, I believe any modification that makes byte code bigger can
> lead to this problem.
>
> The solution is to change short-form to long-form. It's not so simple is
> easier to resolve this problem in generic way. So I modified Cecil code
> writing. Please check it and point to any problems. Please fill free to
> incorporate it in Cecil (with any modification) if you think it's useful.
>
> Two new methods of CodeWriter are:
>
> bool CorrectInstructions()
> {
>     var instructions = body.Instructions;
>     var items = instructions.items;
>     var size = instructions.size;
>
>     var anythingChanged = false;
>     for (int i = 0; i < size; i++)
>     {
>         var instruction = items[i];
>         anythingChanged |= CorrectInstructionShortForm(instruction);
>     }
>
>     return anythingChanged;
> }
>
> bool CorrectInstructionShortForm(Instruction instruction)
> {
>     var opcode = instruction.OpCode;
>     var operand = instruction.operand;
>     switch (opcode.OperandType)
>     {
>         case OperandType.ShortInlineBrTarget:
>             var target = (Instruction)instruction.operand;
>             var offset = target.Offset - (instruction.Offset + opcode.Size +
> 1);
>             if (offset > sbyte.MaxValue)
>             {
>                 if (opcode != OpCodes.Leave_S)
>                 {
>                     const int diff = Code.Br - Code.Br_S;
>                     instruction.OpCode = new OpCode(opcode.Op1 << 0 |
> (opcode.Op2 + diff) << 8 | ((byte)opcode.Code + diff) << 16 |
> (byte)opcode.FlowControl << 24,
>                         (byte)OpCodeType.Macro << 0 |
> (byte)OperandType.InlineBrTarget << 8 | (byte)opcode.StackBehaviourPop << 16
> | (byte)opcode.StackBehaviourPush << 24);
>                 }
>                 else
>                 {
>                     instruction.OpCode = new OpCode(opcode.Op1 << 0 |
> (opcode.Op2 - 1) << 8 | ((byte)opcode.Code - 1) << 16 |
> (byte)opcode.FlowControl << 24,
>                         (byte)OpCodeType.Primitive << 0 |
> (byte)OperandType.InlineBrTarget << 8 | (byte)opcode.StackBehaviourPop << 16
> | (byte)opcode.StackBehaviourPush << 24);
>                 }
>             }
>             return true;
>         case OperandType.ShortInlineVar:
>             if (GetVariableIndex((VariableDefinition)operand) >
> byte.MaxValue)
>             {
>                 var op2Diff = OpCodes.Ldloc.Op2 - OpCodes.Ldloc_S.Op2;
>                 const int codeDiff = Code.Ldloc - Code.Ldloc_S;
>                 instruction.OpCode = new OpCode(0xfe << 0 | (opcode.Op2 +
> op2Diff) << 8 | ((byte)opcode.Code + codeDiff) << 16 |
> (byte)opcode.FlowControl << 24,
>                     (byte)OpCodeType.Primitive << 0 |
> (byte)OperandType.InlineVar << 8 | (byte)opcode.StackBehaviourPop << 16 |
> (byte)opcode.StackBehaviourPush << 24);
>             }
>             return true;
>         case OperandType.ShortInlineArg:
>             if (GetParameterIndex((ParameterDefinition)operand) >
> byte.MaxValue)
>             {
>                 var op2Diff = OpCodes.Ldloc.Op2 - OpCodes.Ldloc_S.Op2;
>                 const int codeDiff = Code.Ldloc - Code.Ldloc_S;
>                 instruction.OpCode = new OpCode(0xfe << 0 | (opcode.Op2 +
> op2Diff) << 8 | ((byte)opcode.Code + codeDiff) << 16 |
> (byte)opcode.FlowControl << 24,
>                     (byte)OpCodeType.Primitive << 0 |
> (byte)OperandType.InlineArg << 8 | (byte)opcode.StackBehaviourPop << 16 |
> (byte)opcode.StackBehaviourPush << 24);
>             }
>             return true;
>         default:
>             return false;
>     }
> }
>
>
> and the usage is:
>
> void WriteResolvedMethodBody (MethodDefinition method)
> {
>     body = method.Body;
>     ComputeHeader ();
>     if (CorrectInstructions ())
>         ComputeHeader ();
>     if (RequiresFatHeader ())
>         WriteFatHeader ();
>     else
>         WriteByte ((byte) (0x2 | (body.CodeSize << 2))); // tiny
>
>     WriteInstructions ();
>
>     if (body.HasExceptionHandlers)
>         WriteExceptionHandlers ();
>
>     var symbol_writer = metadata.symbol_writer;
>     if (symbol_writer != null)
>         symbol_writer.Write (body);
> }
>
>
>
> Cheers,
> Andriy
>
> --
> --
> --
> mono-cecil
> ---
> You received this message because you are subscribed to the Google Groups
> "mono-cecil" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> For more options, visit https://groups.google.com/d/optout.

-- 
-- 
--
mono-cecil
--- 
You received this message because you are subscribed to the Google Groups 
"mono-cecil" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to