Beispiel #1
0
        private void AnalyzeBlockFrom(MethodDefinition method, Instruction instruction, IntervalCollection methodBlocks)
        {
            int nextIntervalStart;
            var startingOffset = instruction.Offset;

            // if our entry point can be found in some existing block
            // we have to divide that block
            if (methodBlocks.DivideIfNecessary(startingOffset, out nextIntervalStart))
            {
                return;
            }
            if (nextIntervalStart == -1)
            {
                nextIntervalStart = int.MaxValue;
            }

            while (NextInstructionShouldBeReached(instruction) &&
                   (instruction.Offset + instruction.GetSize()) < nextIntervalStart)
            {
                instruction = instruction.Next;
                if (instruction == null)
                {
                    throw new InvalidOperationException("Invalid IL code.");
                }
            }

            var instructionSize = instruction.GetSize();

            methodBlocks.Insert(startingOffset, instruction.Offset - startingOffset + instructionSize);

            switch (instruction.OpCode.FlowControl)
            {
            case FlowControl.Return:
            case FlowControl.Throw:
                return;

            case FlowControl.Branch:
                AnalyzeBlockFrom(method, ((Instruction)instruction.Operand), methodBlocks);
                break;

            case FlowControl.Cond_Branch:
                var operandAsInstruction      = instruction.Operand as Instruction;
                var operandAsInstructionArray = instruction.Operand as Instruction[];

                if (operandAsInstruction != null)
                {
                    AnalyzeBlockFrom(method, operandAsInstruction, methodBlocks);
                }
                else if (operandAsInstructionArray != null)
                {
                    foreach (var operandInstruction in operandAsInstructionArray)
                    {
                        AnalyzeBlockFrom(method, operandInstruction, methodBlocks);
                    }
                }
                AnalyzeBlockFrom(method, instruction.Next, methodBlocks);
                break;

            case FlowControl.Break:
            case FlowControl.Meta:
            case FlowControl.Phi:
                throw new NotImplementedException();

            case FlowControl.Call:
            case FlowControl.Next:
                // we've reached here due to the nextIntervalStart that finished our scan prematurely
                return;
            }
        }