private static ControlFlowGraph ConnectNodes(IEnumerable <Instruction> instructions, IDictionary <string, CFGNode> leaders) { var cfg = new ControlFlowGraph(); var connectWithPreviousNode = true; var current = cfg.Entry; CFGNode previous; foreach (var instruction in instructions) { if (leaders.ContainsKey(instruction.Label)) { previous = current; current = leaders[instruction.Label]; // A node cannot fall-through itself, // unless it contains another // instruction with the same label // of the node's leader instruction if (connectWithPreviousNode && previous.Id != current.Id) { cfg.ConnectNodes(previous, current); } } current.Instructions.Add(instruction); connectWithPreviousNode = instruction.CanFallThroughNextInstruction(); IList <string> targets; var isBranch = instruction.IsBranch(out targets); var isExitingMethod = instruction.IsExitingMethod(); if (isBranch) { foreach (var label in targets) { var target = leaders[label]; cfg.ConnectNodes(current, target); } } else if (isExitingMethod) { //TODO: not always connect to exit, could exists a catch or finally block cfg.ConnectNodes(current, cfg.Exit); } } cfg.ConnectNodes(current, cfg.Exit); return(cfg); }
private void ConnectNodesWithExceptionHandlers(ControlFlowGraph cfg, IDictionary <string, CFGNode> leaders) { var activeProtectedBlocks = new HashSet <ProtectedBlock>(); var protectedBlocksStart = methodBody.ExceptionInformation.ToLookup(pb => pb.Start); var protectedBlocksEnd = methodBody.ExceptionInformation.ToLookup(pb => pb.End); var orderedLeaders = from entry in leaders where entry.Value.Instructions.Any() orderby entry.Value.StartOffset() select entry; foreach (var entry in orderedLeaders) { var label = entry.Key; var node = entry.Value; if (protectedBlocksStart.Contains(label)) { var startingProtectedBlocks = protectedBlocksStart[label]; activeProtectedBlocks.UnionWith(startingProtectedBlocks); } if (protectedBlocksEnd.Contains(label)) { var endingProtectedBlocks = protectedBlocksEnd[label]; activeProtectedBlocks.ExceptWith(endingProtectedBlocks); } // Connect each node inside a try block to the first corresponding handler block foreach (var block in activeProtectedBlocks) { var target = leaders[block.Handler.Start]; cfg.ConnectNodes(node, target); } } }