/** * Removes the nodes given by <code>list</code> from the control flow graph and rewires them to be a sequence of * separate nodes, e.g. in the body of an if-statement. The first node has <code>base</code> as predecessor. For the * last node in the list, base's successor will be set as successor, e.g. the first statement after an if-then-else * statement. * * @param list list of nodes from a block * @param base basis of block, e.g. an if-statement */ private void rewireNodes(List<SequentialNode> list, SequentialNode base) { if (list == null || list.size() == 0) { return; } Iterator<SequentialNode> it = list.iterator(); SequentialNode current = it.next(); graph.removeNode(current); current.addPredecessor(base); // first node has if-then-else node as predecessor while (it.hasNext()) { SequentialNode next = it.next(); graph.removeNode(next); current.replaceSuccessor(current.getSuccessor(), next); // could be redundant next.addPredecessor(current); current = next; } current.replaceSuccessor(current.getSuccessor(), new BlockEndNode(graph, base)); // mark the end of this block }
private void copySubtree(SequentialNode root, SequentialNode newBase) { if (root instanceof BlockEndNode) { ((BlockEndNode) root).updateBase(newBase); return; } else if (root.getSuccessor() instanceof SequentialNode) { SequentialNode successor = (SequentialNode) root.getSuccessor(); SequentialNode newSuccessor = successor.copy(); root.replaceSuccessor(successor, newSuccessor); copySubtree(newSuccessor, newBase); } }
/** * Makes a deep copy of this node using the same predecessors and successor as the original. Depending on the * subtype, more properties are copied according to the {@link #copyElements()} method. * * @return a copy of this node with same predecessors and successors */ public SequentialNode copy() { SequentialNode copy = copyElements(); copy.setSuccessor(successor); for (Node p : getPredecessors()) { copy.addPredecessor(p); } return copy; } }
Variable newVariable = createNewVariable(); AssignmentNode assignmentNode = new AssignmentNode(graph, newVariable, arg); curNode.insertBefore(assignmentNode); StoreResultNode storeNode = new StoreResultNode(graph, newVariable); curNode.insertBefore(storeNode); newArgs.add(newVariable); } else SequentialNode copySNode = sNode.copy(); copySNode.accept(r); curNode.insertBefore(copySNode);
@Override public String toString() { SequentialNode curr = startNode; StringBuilder sb = new StringBuilder(); sb.append("CFG:\n"); sb.append(startNode); do { sb.append("\n--> "); if (curr.getSuccessor() instanceof SequentialNode) { curr = (SequentialNode) curr.getSuccessor(); sb.append(curr); } else { Node end = curr.getSuccessor(); sb.append(end); break; } } while (true); return sb.toString(); }
@Override public IfThenElseNode copyElements() { IfThenElseNode copy = new IfThenElseNode(getGraph(), condition.copy()); copy.elseif = elseif; SequentialNode newPositive = positive.copy(); newPositive.removePredecessor(this); newPositive.addPredecessor(copy); copy.setPositive(newPositive); copySubtree(newPositive, copy); SequentialNode newNegative = negative.copy(); newNegative.removePredecessor(this); newNegative.addPredecessor(copy); copy.setNegative(newNegative); copySubtree(newNegative, copy); return copy; }
/** * Removes the given node from the control flow graph. The graph will be traversed in order to find the node to be * removed. Once the desired node is found, its predecessors are rewired to have the old node's successor as direct * successors. * * @param node node to be removed */ public void removeNode(SequentialNode node) { Node successor = node.getSuccessor(); successor.removePredecessor(node); Set<Node> predecessors = new HashSet<Node>(node.getPredecessors()); for (Node predecessor : predecessors) { successor.addPredecessor(predecessor); predecessor.replaceSuccessor(node, successor); } }
@Override public void replaceSuccessor(Node oldSuccessor, Node newSuccessor) { if (oldSuccessor == body) { newSuccessor.removePredecessor(oldSuccessor); newSuccessor.addPredecessor(this); body = (SequentialNode) newSuccessor; } else { super.replaceSuccessor(oldSuccessor, newSuccessor); } }
/** * Inserts a node after this sequential node and its successor. This method will rewire the nodes to keep the graph * consistent. It will do the following: * <ol> * <li>Remove the connection between this node and its successor.</li> * <li>Add a bi-directional connection between this node and the new node.</li> * <li>Add a bi-directional connection between the new node and this nodes old successor.</li> * </ol> * * @param newNode The new node that should be inserted in the control flow after this one. */ public void insertAfter(SequentialNode newNode) { Node oldSuccessor = successor; successor = newNode; newNode.addPredecessor(this); if (oldSuccessor != null) { newNode.successor = oldSuccessor; oldSuccessor.removePredecessor(this); oldSuccessor.addPredecessor(newNode); } }
/** * Adds a node to the end of the graph. * * @param node The node that should be added. */ private void addNode(SequentialNode node) { lastNode.insertAfter(node); lastNode = node; }
@Override public Macro copyElements() { List<SequentialNode> bodyCopy = new ArrayList<SequentialNode>(); for (SequentialNode node : body) { bodyCopy.add(node.copy()); } return new Macro(getGraph(), name, bodyCopy, returnValue.copy()); }
@Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("if(" + condition + ")"); sb.append(",then={"); SequentialNode current = positive; while (!(current instanceof BlockEndNode)) { sb.append(current); sb.append(';'); current = (SequentialNode) current.getSuccessor(); } sb.append("}"); current = negative; if (!(current instanceof BlockEndNode)) { sb.append(",else={"); while (!(current instanceof BlockEndNode)) { sb.append(current); sb.append(';'); current = (SequentialNode) current.getSuccessor(); } sb.append("}"); } return sb.toString(); }
@Override public LoopNode copyElements() { LoopNode copy = new LoopNode(getGraph()); copy.setIterations(iterations); copy.setCounterVariable(counter); SequentialNode newBody = body.copy(); newBody.removePredecessor(this); newBody.addPredecessor(copy); copy.setBody(newBody); copySubtree(newBody, copy); return copy; }
@Override public void replaceSuccessor(Node oldSuccessor, Node newSuccessor) { if (oldSuccessor == positive) { newSuccessor.removePredecessor(oldSuccessor); newSuccessor.addPredecessor(this); // cast is safe since branch of if-then-else cannot be the end node setPositive((SequentialNode) newSuccessor); } else if (oldSuccessor == negative) { newSuccessor.removePredecessor(oldSuccessor); newSuccessor.addPredecessor(this); // cast is safe since branch of if-then-else cannot be the end node setNegative((SequentialNode) newSuccessor); } else { super.replaceSuccessor(oldSuccessor, newSuccessor); } }
/** * Adds a node to the end of the graph. * * @param node The node that should be added. */ private void addNode(SequentialNode node) { lastNode.insertAfter(node); lastNode = node; }
/** * Removes the nodes given by <code>list</code> from the control flow graph and rewires them to be a sequence of separate * nodes, e.g. in the body of an if-statement. The first node has <code>base</code> as predecessor. For the last node in the * list, base's successor will be set as successor, e.g. the first statement after an if-then-else statement. * * @param list list of nodes from a block * @param base basis of block, e.g. an if-statement */ private void rewireNodes(List<SequentialNode> list, IfThenElseNode base) { if (list == null || list.size() == 0) { return; } Iterator<SequentialNode> it = list.iterator(); SequentialNode current = it.next(); graph.removeNode(current); current.addPredecessor(base); // first node has if-then-else node as predecessor while (it.hasNext()) { SequentialNode next = it.next(); graph.removeNode(next); current.replaceSuccessor(current.getSuccessor(), next); // could be redundant next.addPredecessor(current); current = next; } current.replaceSuccessor(current.getSuccessor(), new BlockEndNode(graph, current)); // mark the end of this block }
private void copySubtree(SequentialNode root, SequentialNode newBase) { if (root instanceof BlockEndNode) { ((BlockEndNode) root).updateBase(newBase); return; } else if (root.getSuccessor() instanceof SequentialNode) { SequentialNode successor = (SequentialNode) root.getSuccessor(); SequentialNode newSuccessor = successor.copy(); root.replaceSuccessor(successor, newSuccessor); copySubtree(newSuccessor, newBase); } }
private void replaceSubtree(Node root, Expression old, Expression newExpression) { if (root instanceof BlockEndNode || root instanceof EndNode) { return; } else if (root instanceof SequentialNode) { root.replaceExpression(old, newExpression); replaceSubtree(((SequentialNode) root).getSuccessor(), old, newExpression); } }