public static Dictionary<CFGBlock, List<CFGBlock>> ComputeContainingLoopMap(ICFG cfg) { Contract.Requires(cfg != null); Contract.Ensures(Contract.Result<Dictionary<CFGBlock, List<CFGBlock>>>() != null); var result = new Dictionary<CFGBlock, List<CFGBlock>>(); var visitedSubroutines = new Set<int>(); var pendingSubroutines = new Stack<Subroutine>(); var pendingAPCs = new Stack<APC>(); var graph = cfg.AsBackwardGraph(includeExceptionEdges:false, skipContracts:true); foreach (var loophead in cfg.LoopHeads) { // push back-edge sources var loopPC = new APC(loophead, 0, null); foreach (var pred in cfg.Predecessors(loopPC)) { if (cfg.IsForwardBackEdge(pred, loopPC)) { var normalizedPred = new APC(pred.Block, 0, null); pendingAPCs.Push(normalizedPred); } } var visit = new DepthFirst.Visitor<APC, Unit>(graph, (APC pc) => { if (pc.SubroutineContext != null) { // push continuation PC pendingAPCs.Push(new APC(pc.SubroutineContext.Head.One, 0, null)); if (visitedSubroutines.AddQ(pc.Block.Subroutine.Id)) { pendingSubroutines.Push(pc.Block.Subroutine); } return false; // stop exploration } return !pc.Equals(loopPC); }); while (pendingAPCs.Count > 0) { var root = pendingAPCs.Pop(); visit.VisitSubGraphNonRecursive(root); while (pendingSubroutines.Count > 0) { var sub = pendingSubroutines.Pop(); pendingAPCs.Push(new APC(sub.Exit, 0, null)); } } foreach (var visited in visit.Visited) { if (visited.SubroutineContext != null) continue; // ignore non-primary pcs MaterializeContainingLoop(result, visited.Block).AssumeNotNull().Add(loophead); } } return result; }
protected void PostProcessBlocks() { var blockStack = new Stack <CFGBlock> (); this.successor_edges = new EdgeMap <EdgeTag> (this.successors); this.edge_info = new DepthFirst.Visitor <CFGBlock, Dummy> (this, null, (block) => blockStack.Push(block), null); this.edge_info.VisitSubGraphNonRecursive(this.exception_exit); this.edge_info.VisitSubGraphNonRecursive(this.exit); this.edge_info.VisitSubGraphNonRecursive(this.entry); foreach (var successorEdge in this.successor_edges) { int idGen = UnusedBlockIndex; successorEdge.From.Renumber(ref idGen); } int idGen1 = 0; foreach (CFGBlock cfgBlock in blockStack) { cfgBlock.Renumber(ref idGen1); } SuccessorEdges.Filter((e) => e.From.Index != UnusedBlockIndex); this.predecessor_edges = this.successor_edges.Reverse(); int finishTime = 0; var visitor = new DepthFirst.Visitor <CFGBlock, EdgeTag> (this.predecessor_edges, null, block => block.ReversePostOrderIndex = finishTime++, null); visitor.VisitSubGraphNonRecursive(this.exit); foreach (CFGBlock node in blockStack) { visitor.VisitSubGraphNonRecursive(node); } SuccessorEdges.Resort(); this.blocks = blockStack.ToArray(); this.LabelsThatStartBlocks = null; Builder = null; }
public static Dictionary <CFGBlock, List <CFGBlock> > ComputeContainingLoopMap(ICFG cfg) { Contract.Requires(cfg != null); Contract.Ensures(Contract.Result <Dictionary <CFGBlock, List <CFGBlock> > >() != null); var result = new Dictionary <CFGBlock, List <CFGBlock> >(); var visitedSubroutines = new Set <int>(); var pendingSubroutines = new Stack <Subroutine>(); var pendingAPCs = new Stack <APC>(); var graph = cfg.AsBackwardGraph(includeExceptionEdges: false, skipContracts: true); foreach (var loophead in cfg.LoopHeads) { // push back-edge sources var loopPC = new APC(loophead, 0, null); foreach (var pred in cfg.Predecessors(loopPC)) { if (cfg.IsForwardBackEdge(pred, loopPC)) { var normalizedPred = new APC(pred.Block, 0, null); pendingAPCs.Push(normalizedPred); } } var visit = new DepthFirst.Visitor <APC, Unit>(graph, (APC pc) => { if (pc.SubroutineContext != null) { // push continuation PC pendingAPCs.Push(new APC(pc.SubroutineContext.Head.One, 0, null)); if (visitedSubroutines.AddQ(pc.Block.Subroutine.Id)) { pendingSubroutines.Push(pc.Block.Subroutine); } return(false); // stop exploration } return(!pc.Equals(loopPC)); }); while (pendingAPCs.Count > 0) { var root = pendingAPCs.Pop(); visit.VisitSubGraphNonRecursive(root); while (pendingSubroutines.Count > 0) { var sub = pendingSubroutines.Pop(); pendingAPCs.Push(new APC(sub.Exit, 0, null)); } } foreach (var visited in visit.Visited) { if (visited.SubroutineContext != null) { continue; // ignore non-primary pcs } MaterializeContainingLoop(result, visited.Block).AssumeNotNull().Add(loophead); } } return(result); }
// Callgraph-ordered public override IEnumerable <Method> OrderedMethods() { var components = StronglyConnectedComponents.Compute(this.callGraph); // components are in caller to callee order, so reverse it components.Reverse(); var classGraph = new SingleEdgeGraph <Type, Unit>(null); var mAlreadyThere = new Set <Type>(); Predicate <Node> nodeStartVisitor = n => { if (n.Kind != Node.Tag.method) { return(true); } var m = n.Method; var dt = this.md.DeclaringType(m); if (mAlreadyThere.Add(dt)) { classGraph.AddNode(dt); } // add edge dt -> type(each successor) foreach (var suc in this.callGraph.Successors(n)) { if (suc.Two.Kind != Node.Tag.method) { continue; } var succmethod = suc.Two.Method; var tsuc = this.md.DeclaringType(succmethod); if (mAlreadyThere.Add(tsuc)) { classGraph.AddNode(tsuc); } classGraph.AddEdge(dt, Unit.Value, tsuc); } return(true); }; var dfs_construct_class_graph = new DepthFirst.Visitor <Node, Unit>(this.callGraph, nodeStartVisitor); dfs_construct_class_graph.VisitAll(); // Now get the ordering of the class graph var class_components = StronglyConnectedComponents.Compute(classGraph); class_components.Reverse(); // Stores the class order var class_order = new Dictionary <Type, int>(); int index = 0; foreach (var compo in class_components) { foreach (var cl in compo) { class_order.Add(cl, index++); } } var indexes = new Dictionary <Method, int>(); Comparison <Method> compareMethods = (m1, m2) => { var t1 = class_order[this.md.DeclaringType(m1)]; var t2 = class_order[this.md.DeclaringType(m2)]; if (t1 != t2) { return(t2 - t1); } // regarding to class order, m1 == m2, i.e. keep global methods order return(indexes[m2] - indexes[m1]); }; // Stores the global method order to decide inside class graph strong components // And populate the method list var ordered_methods = new PriorityQueue <Method>(compareMethods); index = 0; foreach (var component in components) { foreach (var node in component) { if (node.Kind == Node.Tag.method) { indexes[node.Method] = index++; ordered_methods.Add(node.Method); } } } while (ordered_methods.Count > 0) { yield return(ordered_methods.Pull()); } }