/** * Add the given CFG node to the node map. * * @param nodeMap * @param cfgNode */ private static <N> void registerCfgNode(Map<N, Set<ICFGNode<N>>> nodeMap, ICFGNode<N> cfgNode) { N astnode = cfgNode.getASTNode(); if (astnode == null) return; Set<ICFGNode<N>> cfgnodes = nodeMap.get(astnode); if (cfgnodes == null) { cfgnodes = new HashSet<ICFGNode<N>>(); nodeMap.put(astnode, cfgnodes); } cfgnodes.add(cfgNode); }
/** * Builds a post-order comparator for the nodes in the given CFG, in which a node is bigger than * all of its successors (predecessors) if <code>isForward</code> is <code>true</code> (<code> * false</code>), and populates a map from AST nodes to all their corresponding nodes in the given * CFG. * * @param cfg * @param nodeMap Node map to be populated (will not be cleared). * @param isForward If <code>true</code> the CFG is traversed in the forward direction, meaning * starting from the {@link IControlFlowGraph#getStartNode() start node} following {@link * ICFGNode#getOutputs() outgoing edges}; if <code>false</code> the traversal direction is * reversed, meaning traversal starts from the {@link IControlFlowGraph#getEndNode() end node} * and follows {@link ICFGNode#getInputs() incoming edges}. * @return Post-order comparator for the nodes in the given CFG */ public static <N> WorklistNodeOrderComparator createPostOrderAndPopulateNodeMap( final IControlFlowGraph<N> cfg, final Map<N, Set<ICFGNode<N>>> nodeMap, final boolean isForward) { Map<ICFGNode<?>, Integer> order = new HashMap<ICFGNode<?>, Integer>(); // iterative post-order visit / depth-first search (DFS) // "visits" (numbers) nodes after all their children are // visited (ie., when nodes become "black") int cur = 0; LinkedList<Object> spine = new LinkedList<Object>(); ICFGNode<N> node = isForward ? cfg.getStartNode() : cfg.getEndNode(); order.put(node, null); spine.addFirst(node); spine.addFirst((isForward ? node.getOutputs() : node.getInputs()).iterator()); newNode: while (spine.isEmpty() == false) { Iterator<ICFGEdge<N>> it = (Iterator<ICFGEdge<N>>) spine.peek(); while (it.hasNext()) { node = isForward ? it.next().getSink() : it.next().getSource(); if (order.containsKey(node) == false) { order.put(node, null); spine.addFirst(node); spine.addFirst((isForward ? node.getOutputs() : node.getInputs()).iterator()); continue newNode; } } spine.removeFirst(); node = (ICFGNode<N>) spine.removeFirst(); // number nodes in increasing order if (order.put(node, cur++) != null) throw new IllegalStateException("Node already visited: " + node); // also register node so that we can find it given its AST node registerCfgNode(nodeMap, node); } // visitPostOrder(cfg.getStartNode(), order, Integer.MAX_VALUE); return new WorklistNodeOrderComparator(order); }