package ch.usi.inf.sp.cfg; import ch.usi.inf.sp.graph.DiGraph; public final class ControlFlowGraph extends DiGraph { private BasicBlock entry; private BasicBlock exit; public ControlFlowGraph() { entry = new BasicBlock(-1); addNode(entry); exit = new BasicBlock(-2); addNode(exit); } private final void checkContains(BasicBlock block, String name) { if (!getNodes().contains(block)) { throw new IllegalStateException("Control flow graph does not contain the given " + name + " block."); } } public ControlFlowEdge addEntryEdge(BasicBlock firstBlock) { if (entry.getOutEdges().size() > 0) { throw new IllegalStateException("Control flow graph already has an entry edge. It can only have one."); } checkContains(firstBlock, "firstBlock"); ControlFlowEdge edge = new ControlFlowEdge(""); addEdge(edge); connect(entry, edge, firstBlock); return edge; } public ControlFlowEdge addExitEdge(BasicBlock returnBlock) { checkContains(returnBlock, "returnBlock"); ControlFlowEdge edge = new ControlFlowEdge(""); addEdge(edge); connect(returnBlock, edge, exit); return edge; } public ControlFlowEdge addFallthroughEdge(BasicBlock fromBlock, BasicBlock toBlock) { checkContains(fromBlock, "fromBlock"); checkContains(toBlock, "toBlock"); ControlFlowEdge edge = new ControlFlowEdge(""); addEdge(edge); connect(fromBlock, edge, toBlock); return edge; } public ControlFlowEdge addBranchTakenEdge(BasicBlock fromBlock, BasicBlock toBlock) { checkContains(fromBlock, "fromBlock"); checkContains(toBlock, "toBlock"); ControlFlowEdge edge = new ControlFlowEdge("T"); addEdge(edge); connect(fromBlock, edge, toBlock); return edge; } public ControlFlowEdge addCaseEdge(BasicBlock fromBlock, BasicBlock toBlock, int key) { checkContains(fromBlock, "fromBlock"); checkContains(toBlock, "toBlock"); ControlFlowEdge edge = new ControlFlowEdge("" + key); addEdge(edge); connect(fromBlock, edge, toBlock); return edge; } public ControlFlowEdge addDefaultEdge(BasicBlock fromBlock, BasicBlock toBlock) { checkContains(fromBlock, "fromBlock"); checkContains(toBlock, "toBlock"); ControlFlowEdge edge = new ControlFlowEdge("default"); addEdge(edge); connect(fromBlock, edge, toBlock); return edge; } public BasicBlock getEntry() { return entry; } public BasicBlock getExit() { return exit; } public String toString() { final StringBuffer sb = new StringBuffer("digraph CFG {\n"); for (final BasicBlock node : getNodes()) { if (node==entry) { sb.append(" " + node + " [shape=circle,style=filled,label=e]\n"); } else if (node==exit) { sb.append(" " + node + " [shape=circle,style=filled,label=x]\n"); } else { sb.append(" " + node + " [shape=rectangle]\n"); } } for (final ControlFlowEdge edge : getEdges()) { if (edge.getLabel().length()>0) { sb.append(" " + edge + " [label=" + edge.getLabel() + "]\n"); } else { sb.append(" " + edge + "\n"); } } sb.append("}\n"); return sb.toString(); } }