예제 #1
0
    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();
    }
예제 #2
0
    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);
        }
    }