private static uint BuildPointsForBranch(List <BranchPoint> list, Instruction then, int branchingInstructionLine, string document, int branchOffset, uint ordinal, int pathCounter, BranchPoint path0, List <Instruction> instructions, MethodDefinition methodDefinition) { var pathOffsetList1 = GetBranchPath(@then); // Add path 1 var path1 = new BranchPoint { StartLine = branchingInstructionLine, Document = document, Offset = branchOffset, Ordinal = ordinal++, Path = pathCounter, OffsetPoints = pathOffsetList1.Count > 1 ? pathOffsetList1.GetRange(0, pathOffsetList1.Count - 1) : new List <int>(), EndOffset = pathOffsetList1.Last() }; // only add branch if branch does not match a known sequence // e.g. auto generated field assignment // or encapsulates at least one sequence point var offsets = new[] { path0.Offset, path0.EndOffset, path1.Offset, path1.EndOffset }; var ignoreSequences = new[] { // we may need other samples new[] { Code.Brtrue_S, Code.Pop, Code.Ldsfld, Code.Ldftn, Code.Newobj, Code.Dup, Code.Stsfld, Code.Newobj }, // CachedAnonymousMethodDelegate field allocation }; var bs = offsets.Min(); var be = offsets.Max(); var range = instructions.Where(i => (i.Offset >= bs) && (i.Offset <= be)).ToList(); var match = ignoreSequences .Where(ignoreSequence => range.Count >= ignoreSequence.Length) .Any(ignoreSequence => range.Zip(ignoreSequence, (instruction, code) => instruction.OpCode.Code == code).All(x => x)); var count = range .Count(i => methodDefinition.DebugInformation.GetSequencePoint(i) != null); if (!match || count > 0) { list.Add(path0); list.Add(path1); } return(ordinal); }
private static bool BuildPointsForConditionalBranch(List <BranchPoint> list, Instruction instruction, int branchingInstructionLine, string document, int branchOffset, int pathCounter, List <Instruction> instructions, ref uint ordinal, MethodDefinition methodDefinition) { // Add Default branch (Path=0) // Follow else/default instruction var @else = instruction.Next; var pathOffsetList = GetBranchPath(@else); // add Path 0 var path0 = new BranchPoint { StartLine = branchingInstructionLine, Document = document, Offset = branchOffset, Ordinal = ordinal++, Path = pathCounter++, OffsetPoints = pathOffsetList.Count > 1 ? pathOffsetList.GetRange(0, pathOffsetList.Count - 1) : new List <int>(), EndOffset = pathOffsetList.Last() }; // Add Conditional Branch (Path=1) if (instruction.OpCode.Code != Code.Switch) { // Follow instruction at operand var @then = instruction.Operand as Instruction; if (@then == null) { return(false); } ordinal = BuildPointsForBranch(list, then, branchingInstructionLine, document, branchOffset, ordinal, pathCounter, path0, instructions, methodDefinition); } else // instruction.OpCode.Code == Code.Switch { var branchInstructions = instruction.Operand as Instruction[]; if (branchInstructions == null || branchInstructions.Length == 0) { return(false); } ordinal = BuildPointsForSwitchCases(list, path0, branchInstructions, branchingInstructionLine, document, branchOffset, ordinal, ref pathCounter); } return(true); }
private static uint BuildPointsForSwitchCases(List <BranchPoint> list, BranchPoint path0, Instruction[] branchInstructions, int branchingInstructionLine, string document, int branchOffset, uint ordinal, ref int pathCounter) { var counter = pathCounter; list.Add(path0); // Add Conditional Branches (Path>0) list.AddRange(branchInstructions.Select(GetBranchPath) .Select(pathOffsetList1 => new BranchPoint { StartLine = branchingInstructionLine, Document = document, Offset = branchOffset, Ordinal = ordinal++, Path = counter++, OffsetPoints = pathOffsetList1.Count > 1 ? pathOffsetList1.GetRange(0, pathOffsetList1.Count - 1) : new List <int>(), EndOffset = pathOffsetList1.Last() })); pathCounter = counter; return(ordinal); }