package cfg; import java.util.LinkedList; import java.util.List; import graphutils.AbstractTwoWayGraph; import cfg.nodes.CFGEntryNode; import cfg.nodes.CFGErrorNode; import cfg.nodes.CFGExitNode; import cfg.nodes.CFGNode; /** * Control Flow Graph. Consider this to be the target format * of CFGFactories. Please place language specific attributes * of the CFG into a sub-class. * */ public class CFG extends AbstractTwoWayGraph<CFGNode, CFGEdge> { private CFGEntryNode entry; private CFGExitNode exit; private CFGErrorNode error; private List<CFGNode> parameters; public CFG() { entry = new CFGEntryNode(); exit = new CFGExitNode(); addVertex(entry); addVertex(exit); parameters = new LinkedList<CFGNode>(); } @Override public boolean isEmpty() { // do not count entry and exit node, since they do not provide any // additional information. return size() == 2; } public CFGNode getExitNode() { return exit; } public CFGNode getEntryNode() { return entry; } public CFGNode getErrorNode() { if (error == null) { error = new CFGErrorNode(); addVertex(error); } return error; } public void registerParameter(CFGNode parameter) { parameters.add(parameter); } public List<CFGNode> getParameters() { return parameters; } public void addCFG(CFG otherCFG) { addVertices(otherCFG); addEdges(otherCFG); } public void appendCFG(CFG otherCFG) { addCFG(otherCFG); if (!otherCFG.isEmpty()) { for (CFGEdge edge1 : ingoingEdges(getExitNode())) { for (CFGEdge edge2 : otherCFG.outgoingEdges(otherCFG .getEntryNode())) { addEdge(edge1.getSource(), edge2.getDestination(), edge1.getLabel()); } } removeEdgesTo(getExitNode()); for (CFGEdge edge : otherCFG.ingoingEdges(otherCFG.getExitNode())) { addEdge(edge.getSource(), getExitNode(), edge.getLabel()); } } } public void mountCFG(CFGNode branchNode, CFGNode mergeNode, CFG cfg, String label) { if (!cfg.isEmpty()) { addCFG(cfg); for (CFGEdge edge : cfg.outgoingEdges(cfg.getEntryNode())) { addEdge(branchNode, edge.getDestination(), label); } for (CFGEdge edge : cfg.ingoingEdges(cfg.getExitNode())) { addEdge(edge.getSource(), mergeNode, edge.getLabel()); } } else { addEdge(branchNode, mergeNode, label); } } private void addVertices(CFG cfg) { for (CFGNode vertex : cfg.getVertices()) { // do not add entry and exit node if (!(vertex.equals(cfg.getEntryNode()) || vertex.equals(cfg .getExitNode()))) { addVertex(vertex); } } } private void addEdges(CFG cfg) { for (CFGNode vertex : cfg.getVertices()) { for (CFGEdge edge : cfg.outgoingEdges(vertex)) { if (!(edge.getSource().equals(cfg.getEntryNode()) || edge .getDestination().equals(cfg.getExitNode()))) { addEdge(edge); } } } } public void addEdge(CFGNode srcBlock, CFGNode dstBlock) { addEdge(srcBlock, dstBlock, CFGEdge.EMPTY_LABEL); } public void addEdge(CFGNode srcBlock, CFGNode dstBlock, String label) { CFGEdge edge = new CFGEdge(srcBlock, dstBlock, label); addEdge(edge); } }