private void ProcessImpl() { _method.Body.SimplifyMacros(); PushPreProcessor.ValidatePushMethods(_method); ProcessMethodCalls(ProcessMethodCallFirstPass); ProcessMethodCalls(ProcessMethodCallSecondPass); _labels.PostProcess(); PostProcessTailCalls(); _sequencePoints.PostProcess(); ValidateAfterProcessing(); _method.Body.SimplifyMacros(); _method.Body.OptimizeMacros(); }
private static bool CheckMethod(MethodDefinition method) { var branchStates = new Dictionary <Instruction, StackState>(ReferenceEqualityComparer <Instruction> .Instance); if (method.Body.HasExceptionHandlers) { foreach (var handler in method.Body.ExceptionHandlers) { branchStates[handler.TryStart] = StackState.StartOfProtectedBlockStackState; branchStates[handler.HandlerStart] = handler.HandlerType switch { ExceptionHandlerType.Catch => StackState.ExceptionHandlerStackState, ExceptionHandlerType.Filter => StackState.ExceptionHandlerStackState, ExceptionHandlerType.Finally => StackState.FinallyOrFaultHandlerStackState, ExceptionHandlerType.Fault => StackState.FinallyOrFaultHandlerStackState, _ => throw new ArgumentOutOfRangeException() }; if (handler.HandlerType == ExceptionHandlerType.Filter) { branchStates[handler.FilterStart] = StackState.ExceptionHandlerStackState; } } } var state = StackState.InitialStackState; foreach (var instruction in method.Body.Instructions) { if (branchStates.TryGetValue(instruction, out var forwardBranchState)) { if (forwardBranchState.Priority == StackStatePriority.Forced || state.Priority == StackStatePriority.IgnoreWhenFollowedByTargetOfForwardBranch) { state = forwardBranchState; } else { if (state.StackSize != forwardBranchState.StackSize) { return(false); } } } var stackSize = state.StackSize; PushPreProcessor.PopStack(instruction, ref stackSize); if (stackSize < 0) { return(false); } PushPreProcessor.PushStack(instruction, ref stackSize); state = new StackState(stackSize, StackStatePriority.Normal); switch (instruction.OpCode.OperandType) { case OperandType.InlineBrTarget: case OperandType.ShortInlineBrTarget: { if (instruction.Operand is not Instruction operand) { return(false); } if (!UpdateBranchState(operand, state)) { return(false); } break; } case OperandType.InlineSwitch: { if (instruction.Operand is not Instruction[] operands) { return(false); } foreach (var operand in operands) { if (!UpdateBranchState(operand, state)) { return(false); } } break; } } switch (instruction.OpCode.FlowControl) { case FlowControl.Branch: case FlowControl.Throw: case FlowControl.Return: state = StackState.PostUnconditionalBranchStackState; break; } } return(true); bool UpdateBranchState(Instruction targetInstruction, StackState branchState) { if (branchStates.TryGetValue(targetInstruction, out var existingState)) { if (existingState.StackSize != branchState.StackSize) { return(false); } } else { branchStates[targetInstruction] = branchState; } return(true); } }