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(); }