111 lines
3.5 KiB
Java
111 lines
3.5 KiB
Java
package ch.usi.inf.sp.cfg;
|
|
|
|
import ch.usi.inf.sp.graph.DiGraph;
|
|
|
|
|
|
public final class ControlFlowGraph extends DiGraph<BasicBlock, ControlFlowEdge> {
|
|
|
|
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();
|
|
}
|
|
|
|
}
|