private Instruction GetLdArgInstruction()
 {
     if (CanInline)
     {
         var ldArgInstruction = OpCodeHelper.Clone(_pushInstruction);
         _inlinedInstructions.Add(ldArgInstruction);
         return(ldArgInstruction);
     }
     return(OpCodeHelper.CreateLoadLoc(GetVariableDefinition()));
 }
        public void Process()
        {
            CreateVars();
            CreateArgs();

            var innerVariables  = _method.Body.Variables;
            var parentVariables = _parentMethod.Body.Variables;

            var isLoadArgs = true;

            // inline body
            var instructions = _method.Body.Instructions;

            foreach (var instruction in instructions)
            {
                var         nextInstruction = instruction.Next;
                Instruction newInstruction  = null;

                // arg
                var parameterDefinition = OpCodeHelper.GetArgParameterDefinition(instruction, _parameters);
                if (parameterDefinition != null)
                {
                    var arg = _args[parameterDefinition.Sequence];
                    newInstruction = arg.GetInstruction(instruction);
                    if (isLoadArgs)
                    {
                        if (OpCodeHelper.IsLoadArg(instruction) && arg.IsDeferred)
                        {
                            _firstLoadArgs.Add(new LoadArgInfo(parameterDefinition.Sequence));
                        }
                        else
                        {
                            isLoadArgs = false;
                        }
                    }
                }
                else
                {
                    if (isLoadArgs && instruction.OpCode != OpCodes.Nop)
                    {
                        isLoadArgs = false;
                    }
                }

                // loc
                var innerVariableDefinition = OpCodeHelper.GetLocVariableDefinition(instruction, innerVariables);
                if (innerVariableDefinition != null)
                {
                    newInstruction = OpCodeHelper.CreateVarInstruction(instruction,
                                                                       parentVariables[innerVariableDefinition.Index + _firstInnerVariableIndex]);
                }

                // branch
                if (instruction.OpCode.OperandType == OperandType.InlineBrTarget ||
                    instruction.OpCode.OperandType == OperandType.ShortInlineBrTarget)
                {
                    var target = (Instruction)instruction.Operand;
                    // fix target ret
                    if (target?.OpCode.Code == Code.Ret)
                    {
                        newInstruction = Instruction.Create(instruction.OpCode, _callInstruction.Next);
                    }
                }

                // ret
                if (instruction.OpCode.Code == Code.Ret)
                {
                    // skip last return
                    if (nextInstruction == null)
                    {
                        break;
                    }

                    newInstruction = Instruction.Create(OpCodes.Br, _callInstruction.Next);
                }

                if (newInstruction == null)
                {
                    newInstruction = OpCodeHelper.Clone(instruction);
                }

                _instructionMap[instruction] = newInstruction;
                AppendToBody(newInstruction);
            }

            FinishArgs();
            Remove(_callInstruction);

            // replace call target
            if (_firstBodyInstruction != null || _beforeBodyInstruction != null)
            {
                _instructionMap[_callInstruction] = _beforeBodyInstruction ?? _firstBodyInstruction;
            }

            FixInstructions();
        }