public void Rewriter(ILProcessor processor)
        {
            var branches = processor.Instructions
                           .OfType <OperandInstruction <ILProcessorInstruction> >()
                           .Where(i => OpCodesMap.ContainsKey(i.OpCode))
                           .ToList();

            if (!branches.Any())
            {
                return;
            }

            var offsets   = new Dictionary <ILProcessorInstruction, int>();
            var curOffset = 0;

            foreach (var instruction in processor.Instructions)
            {
                offsets.Add(instruction, curOffset);
                curOffset += GetInstructionSize(instruction);
            }

            while (branches.Any())
            {
                var branch = branches.FirstOrDefault(i =>
                {
                    var deltaOffset = offsets[i.Operand] - offsets[i.Next];
                    return(deltaOffset >= sbyte.MinValue && deltaOffset <= sbyte.MaxValue);
                });
                if (branch == null)
                {
                    break;
                }

                var shortFormOpCode = OpCodesMap[branch.OpCode];
                var shortBranch     = OperandInstruction.Create(shortFormOpCode, branch.Operand);
                processor.Replace(branch, shortBranch);

                //Update offsets
                ILProcessorInstruction loop = shortBranch;
                curOffset = offsets[branch];
                while (loop != null)
                {
                    offsets[loop] = curOffset;
                    curOffset    += GetInstructionSize(loop);

                    loop = loop.Next;
                }

                offsets.Remove(branch);
                branches.Remove(branch);
            }
        }
        private static int GetInstructionSize(ILProcessorInstruction instruction)
        {
            var size = instruction.OpCode.Size;

            switch (instruction.OpCode.OperandType)
            {
            case OperandType.InlineNone:
                break;

            case OperandType.ShortInlineBrTarget:
            case OperandType.ShortInlineI:
            case OperandType.ShortInlineVar:
                size += 1;
                break;

            case OperandType.InlineVar:
                size += 2;
                break;

            case OperandType.InlineBrTarget:
            case OperandType.InlineI:
            case OperandType.ShortInlineR:
            case OperandType.InlineString:
            case OperandType.InlineSig:
            case OperandType.InlineMethod:
            case OperandType.InlineField:
            case OperandType.InlineType:
            case OperandType.InlineTok:
                size += 4;
                break;

            case OperandType.InlineI8:
            case OperandType.InlineR:
                size += 8;
                break;

            case OperandType.InlineSwitch:
                size += 4 + 4 * ((OperandInstruction <IReadOnlyList <ILProcessorInstruction> >)instruction).Operand.Count;
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
            return(size);
        }
        /// <summary>
        /// Returns the overall effect of the given instruction on the stack.
        /// Negative numbers means the stack shrinks, positive the stack grows
        /// </summary>
        /// <param name="instruction"></param>
        /// <returns></returns>
        private static int GetStackDelta(ILProcessorInstruction instruction)
        {
            var method     = (instruction as OperandInstruction <MethodBase>)?.Operand;
            var stackDelta = 0;

            switch (instruction.OpCode.StackBehaviourPop)
            {
            case StackBehaviour.Pop0:
                break;

            case StackBehaviour.Pop1:
            case StackBehaviour.Popi:
            case StackBehaviour.Popref:
                stackDelta -= 1;
                break;

            case StackBehaviour.Pop1_pop1:
            case StackBehaviour.Popi_pop1:
            case StackBehaviour.Popi_popi:
            case StackBehaviour.Popi_popi8:
            case StackBehaviour.Popi_popr4:
            case StackBehaviour.Popi_popr8:
            case StackBehaviour.Popref_pop1:
            case StackBehaviour.Popref_popi:
                stackDelta -= 2;
                break;

            case StackBehaviour.Popi_popi_popi:
            case StackBehaviour.Popref_popi_pop1:
            case StackBehaviour.Popref_popi_popi:
            case StackBehaviour.Popref_popi_popi8:
            case StackBehaviour.Popref_popi_popr4:
            case StackBehaviour.Popref_popi_popr8:
            case StackBehaviour.Popref_popi_popref:
                stackDelta -= 3;
                break;

            case StackBehaviour.Varpop:
                if (method?.IsStatic == false)
                {
                    stackDelta -= 1;
                }
                stackDelta -= method?.GetParameters().Length ?? 0;
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            switch (instruction.OpCode.StackBehaviourPush)
            {
            case StackBehaviour.Push0:
                break;

            case StackBehaviour.Push1:
            case StackBehaviour.Pushi:
            case StackBehaviour.Pushi8:
            case StackBehaviour.Pushr4:
            case StackBehaviour.Pushr8:
            case StackBehaviour.Pushref:
                stackDelta += 1;
                break;

            case StackBehaviour.Push1_push1:
                stackDelta += 2;
                break;

            case StackBehaviour.Varpush:
                if ((method as MethodInfo)?.ReturnType != typeof(void))
                {
                    stackDelta += 1;
                }
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            return(stackDelta);
        }