use of org.checkerframework.dataflow.cfg.block.ConditionalBlock in project bazel by bazelbuild.
the class CFGDOTVisualizer method visualize.
/**
* Output a graph description in the DOT language, representing the control
* flow graph starting at <code>entry</code>.
*
* @param entry
* The entry node of the control flow graph to be represented.
* @param analysis
* An analysis containing information about the program
* represented by the CFG. The information includes {@link Store}
* s that are valid at the beginning of basic blocks reachable
* from <code>entry</code> and per-node information for value
* producing {@link Node}s. Can also be <code>null</code> to
* indicate that this information should not be output.
* @param verbose
* Add more output to the CFG description.
* @return String representation of the graph in the DOT language.
*/
public static <A extends AbstractValue<A>, S extends Store<S>, T extends TransferFunction<A, S>> String visualize(ControlFlowGraph cfg, Block entry, /*@Nullable*/
Analysis<A, S, T> analysis, boolean verbose) {
StringBuilder sb1 = new StringBuilder();
StringBuilder sb2 = new StringBuilder();
Set<Block> visited = new HashSet<>();
Queue<Block> worklist = new LinkedList<>();
Block cur = entry;
visited.add(entry);
// header
sb1.append("digraph {\n");
sb1.append(" node [shape=rectangle];\n\n");
// traverse control flow graph and define all arrows
while (true) {
if (cur == null)
break;
if (cur.getType() == BlockType.CONDITIONAL_BLOCK) {
ConditionalBlock ccur = ((ConditionalBlock) cur);
Block thenSuccessor = ccur.getThenSuccessor();
sb2.append(" " + ccur.getId() + " -> " + thenSuccessor.getId());
sb2.append(" [label=\"then\\n" + ccur.getThenFlowRule() + "\"];\n");
if (!visited.contains(thenSuccessor)) {
visited.add(thenSuccessor);
worklist.add(thenSuccessor);
}
Block elseSuccessor = ccur.getElseSuccessor();
sb2.append(" " + ccur.getId() + " -> " + elseSuccessor.getId());
sb2.append(" [label=\"else\\n" + ccur.getElseFlowRule() + "\"];\n");
if (!visited.contains(elseSuccessor)) {
visited.add(elseSuccessor);
worklist.add(elseSuccessor);
}
} else {
assert cur instanceof SingleSuccessorBlock;
Block b = ((SingleSuccessorBlock) cur).getSuccessor();
if (b != null) {
sb2.append(" " + cur.getId() + " -> " + b.getId());
sb2.append(" [label=\"" + ((SingleSuccessorBlock) cur).getFlowRule() + "\"];\n");
if (!visited.contains(b)) {
visited.add(b);
worklist.add(b);
}
}
}
// exceptional edges
if (cur.getType() == BlockType.EXCEPTION_BLOCK) {
ExceptionBlock ecur = (ExceptionBlock) cur;
for (Entry<TypeMirror, Set<Block>> e : ecur.getExceptionalSuccessors().entrySet()) {
Set<Block> blocks = e.getValue();
TypeMirror cause = e.getKey();
String exception = cause.toString();
if (exception.startsWith("java.lang.")) {
exception = exception.replace("java.lang.", "");
}
for (Block b : blocks) {
sb2.append(" " + cur.getId() + " -> " + b.getId());
sb2.append(" [label=\"" + exception + "\"];\n");
if (!visited.contains(b)) {
visited.add(b);
worklist.add(b);
}
}
}
}
cur = worklist.poll();
}
IdentityHashMap<Block, List<Integer>> processOrder = getProcessOrder(cfg);
// definition of all nodes including their labels
for (Block v : visited) {
sb1.append(" " + v.getId() + " [");
if (v.getType() == BlockType.CONDITIONAL_BLOCK) {
sb1.append("shape=polygon sides=8 ");
} else if (v.getType() == BlockType.SPECIAL_BLOCK) {
sb1.append("shape=oval ");
}
sb1.append("label=\"");
if (verbose) {
sb1.append("Process order: " + processOrder.get(v).toString().replaceAll("[\\[\\]]", "") + "\\n");
}
sb1.append(visualizeContent(v, analysis, verbose).replace("\\n", "\\l") + " \",];\n");
}
sb1.append("\n");
sb1.append(sb2);
// footer
sb1.append("}\n");
return sb1.toString();
}
use of org.checkerframework.dataflow.cfg.block.ConditionalBlock in project bazel by bazelbuild.
the class ControlFlowGraph method getSuccessors.
/**
* Get a list of all successor Blocks for cur
* @param cur
* @return A Deque of successor Blocks
*/
private Deque<Block> getSuccessors(Block cur) {
Deque<Block> succs = new LinkedList<>();
if (cur.getType() == BlockType.CONDITIONAL_BLOCK) {
ConditionalBlock ccur = ((ConditionalBlock) cur);
succs.add(ccur.getThenSuccessor());
succs.add(ccur.getElseSuccessor());
} else {
assert cur instanceof SingleSuccessorBlock;
Block b = ((SingleSuccessorBlock) cur).getSuccessor();
if (b != null) {
succs.add(b);
}
}
if (cur.getType() == BlockType.EXCEPTION_BLOCK) {
ExceptionBlock ecur = (ExceptionBlock) cur;
for (Set<Block> exceptionSuccSet : ecur.getExceptionalSuccessors().values()) {
succs.addAll(exceptionSuccSet);
}
}
return succs;
}
use of org.checkerframework.dataflow.cfg.block.ConditionalBlock in project bazel by bazelbuild.
the class ControlFlowGraph method getAllBlocks.
/**
* @return The set of all basic block in this control flow graph.
*/
public Set<Block> getAllBlocks() {
Set<Block> visited = new HashSet<>();
Queue<Block> worklist = new LinkedList<>();
Block cur = entryBlock;
visited.add(entryBlock);
// traverse the whole control flow graph
while (true) {
if (cur == null)
break;
Queue<Block> succs = new LinkedList<>();
if (cur.getType() == BlockType.CONDITIONAL_BLOCK) {
ConditionalBlock ccur = ((ConditionalBlock) cur);
succs.add(ccur.getThenSuccessor());
succs.add(ccur.getElseSuccessor());
} else {
assert cur instanceof SingleSuccessorBlock;
Block b = ((SingleSuccessorBlock) cur).getSuccessor();
if (b != null) {
succs.add(b);
}
}
if (cur.getType() == BlockType.EXCEPTION_BLOCK) {
ExceptionBlock ecur = (ExceptionBlock) cur;
for (Set<Block> exceptionSuccSet : ecur.getExceptionalSuccessors().values()) {
succs.addAll(exceptionSuccSet);
}
}
for (Block b : succs) {
if (!visited.contains(b)) {
visited.add(b);
worklist.add(b);
}
}
cur = worklist.poll();
}
return visited;
}
use of org.checkerframework.dataflow.cfg.block.ConditionalBlock in project bazel by bazelbuild.
the class Analysis method performAnalysis.
/**
* Perform the actual analysis. Should only be called once after the object
* has been created.
*
* @param cfg
*/
public void performAnalysis(ControlFlowGraph cfg) {
assert isRunning == false;
isRunning = true;
init(cfg);
while (!worklist.isEmpty()) {
Block b = worklist.poll();
switch(b.getType()) {
case REGULAR_BLOCK:
{
RegularBlock rb = (RegularBlock) b;
// apply transfer function to contents
TransferInput<A, S> inputBefore = getInputBefore(rb);
currentInput = inputBefore.copy();
TransferResult<A, S> transferResult = null;
Node lastNode = null;
boolean addToWorklistAgain = false;
for (Node n : rb.getContents()) {
transferResult = callTransferFunction(n, currentInput);
addToWorklistAgain |= updateNodeValues(n, transferResult);
currentInput = new TransferInput<>(n, this, transferResult);
lastNode = n;
}
// loop will run at least one, making transferResult non-null
// propagate store to successors
Block succ = rb.getSuccessor();
assert succ != null : "regular basic block without non-exceptional successor unexpected";
propagateStoresTo(succ, lastNode, currentInput, rb.getFlowRule(), addToWorklistAgain);
break;
}
case EXCEPTION_BLOCK:
{
ExceptionBlock eb = (ExceptionBlock) b;
// apply transfer function to content
TransferInput<A, S> inputBefore = getInputBefore(eb);
currentInput = inputBefore.copy();
Node node = eb.getNode();
TransferResult<A, S> transferResult = callTransferFunction(node, currentInput);
boolean addToWorklistAgain = updateNodeValues(node, transferResult);
// propagate store to successor
Block succ = eb.getSuccessor();
if (succ != null) {
currentInput = new TransferInput<>(node, this, transferResult);
// TODO? Variable wasn't used.
// Store.FlowRule storeFlow = eb.getFlowRule();
propagateStoresTo(succ, node, currentInput, eb.getFlowRule(), addToWorklistAgain);
}
// propagate store to exceptional successors
for (Entry<TypeMirror, Set<Block>> e : eb.getExceptionalSuccessors().entrySet()) {
TypeMirror cause = e.getKey();
S exceptionalStore = transferResult.getExceptionalStore(cause);
if (exceptionalStore != null) {
for (Block exceptionSucc : e.getValue()) {
addStoreBefore(exceptionSucc, node, exceptionalStore, Store.Kind.BOTH, addToWorklistAgain);
}
} else {
for (Block exceptionSucc : e.getValue()) {
addStoreBefore(exceptionSucc, node, inputBefore.copy().getRegularStore(), Store.Kind.BOTH, addToWorklistAgain);
}
}
}
break;
}
case CONDITIONAL_BLOCK:
{
ConditionalBlock cb = (ConditionalBlock) b;
// get store before
TransferInput<A, S> inputBefore = getInputBefore(cb);
TransferInput<A, S> input = inputBefore.copy();
// propagate store to successor
Block thenSucc = cb.getThenSuccessor();
Block elseSucc = cb.getElseSuccessor();
propagateStoresTo(thenSucc, null, input, cb.getThenFlowRule(), false);
propagateStoresTo(elseSucc, null, input, cb.getElseFlowRule(), false);
break;
}
case SPECIAL_BLOCK:
{
// special basic blocks are empty and cannot throw exceptions,
// thus there is no need to perform any analysis.
SpecialBlock sb = (SpecialBlock) b;
Block succ = sb.getSuccessor();
if (succ != null) {
propagateStoresTo(succ, null, getInputBefore(b), sb.getFlowRule(), false);
}
break;
}
default:
assert false;
break;
}
}
assert isRunning == true;
isRunning = false;
}
Aggregations