use of org.checkerframework.dataflow.cfg.block.Block in project bazel by bazelbuild.
the class AnalysisResult method runAnalysisFor.
/**
* Runs the analysis again within the block of {@code node} and returns the
* store at the location of {@code node}. If {@code before} is true, then
* the store immediately before the {@link Node} {@code node} is returned.
* Otherwise, the store after {@code node} is returned.
*/
public static <A extends AbstractValue<A>, S extends Store<S>> S runAnalysisFor(Node node, boolean before, TransferInput<A, S> transferInput) {
assert node != null;
Block block = node.getBlock();
assert transferInput != null;
Analysis<A, S, ?> analysis = transferInput.analysis;
Node oldCurrentNode = analysis.currentNode;
if (analysis.isRunning) {
return analysis.currentInput.getRegularStore();
}
analysis.isRunning = true;
try {
switch(block.getType()) {
case REGULAR_BLOCK:
{
RegularBlock rb = (RegularBlock) block;
// Apply transfer function to contents until we found the node
// we
// are looking for.
TransferInput<A, S> store = transferInput;
TransferResult<A, S> transferResult = null;
for (Node n : rb.getContents()) {
analysis.currentNode = n;
if (n == node && before) {
return store.getRegularStore();
}
transferResult = analysis.callTransferFunction(n, store);
if (n == node) {
return transferResult.getRegularStore();
}
store = new TransferInput<>(n, analysis, transferResult);
}
// 'block', then 'node' must be part of the contents of 'block'.
assert false;
return null;
}
case EXCEPTION_BLOCK:
{
ExceptionBlock eb = (ExceptionBlock) block;
// apply transfer function to content
assert eb.getNode() == node;
if (before) {
return transferInput.getRegularStore();
}
analysis.currentNode = node;
TransferResult<A, S> transferResult = analysis.callTransferFunction(node, transferInput);
return transferResult.getRegularStore();
}
default:
// Only regular blocks and exceptional blocks can hold nodes.
assert false;
break;
}
return null;
} finally {
analysis.currentNode = oldCurrentNode;
analysis.isRunning = false;
}
}
use of org.checkerframework.dataflow.cfg.block.Block in project checker-framework by typetools.
the class Analysis method performAnalysis.
/**
* Perform the actual analysis. Should only be called once after the object has been created.
*/
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 once, 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;
}
use of org.checkerframework.dataflow.cfg.block.Block in project checker-framework by typetools.
the class AnalysisResult method runAnalysisFor.
/**
* Runs the analysis again within the block of {@code node} and returns the store at the
* location of {@code node}. If {@code before} is true, then the store immediately before the
* {@link Node} {@code node} is returned. Otherwise, the store after {@code node} is returned.
*
* <p>If the given {@link Node} cannot be reached (in the control flow graph), then {@code null}
* is returned.
*/
protected S runAnalysisFor(Node node, boolean before) {
Block block = node.getBlock();
TransferInput<A, S> transferInput = stores.get(block);
if (transferInput == null) {
return null;
}
return runAnalysisFor(node, before, transferInput, analysisCaches);
}
use of org.checkerframework.dataflow.cfg.block.Block in project checker-framework by typetools.
the class DOTCFGVisualizer method generateDotGraph.
/**
* Generate the dot representation as String.
*/
protected String generateDotGraph(ControlFlowGraph cfg, Block entry, @Nullable Analysis<A, S, T> analysis) {
this.sbDigraph.setLength(0);
Set<Block> visited = new HashSet<>();
// header
this.sbDigraph.append("digraph {\n");
Block cur = entry;
Queue<Block> worklist = new ArrayDeque<>();
visited.add(entry);
// 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();
addDotEdge(ccur.getId(), thenSuccessor.getId(), "then\\n" + ccur.getThenFlowRule());
if (!visited.contains(thenSuccessor)) {
visited.add(thenSuccessor);
worklist.add(thenSuccessor);
}
Block elseSuccessor = ccur.getElseSuccessor();
addDotEdge(ccur.getId(), elseSuccessor.getId(), "else\\n" + ccur.getElseFlowRule());
if (!visited.contains(elseSuccessor)) {
visited.add(elseSuccessor);
worklist.add(elseSuccessor);
}
} else {
assert cur instanceof SingleSuccessorBlock;
Block b = ((SingleSuccessorBlock) cur).getSuccessor();
if (b != null) {
addDotEdge(cur.getId(), b.getId(), ((SingleSuccessorBlock) cur).getFlowRule().name());
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) {
addDotEdge(cur.getId(), b.getId(), exception);
if (!visited.contains(b)) {
visited.add(b);
worklist.add(b);
}
}
}
}
cur = worklist.poll();
}
generateDotNodes(visited, cfg, analysis);
// footer
this.sbDigraph.append("}\n");
return this.sbDigraph.toString();
}
use of org.checkerframework.dataflow.cfg.block.Block in project checker-framework by typetools.
the class DOTCFGVisualizer method generateDotNodes.
protected void generateDotNodes(Set<Block> visited, ControlFlowGraph cfg, @Nullable Analysis<A, S, T> analysis) {
IdentityHashMap<Block, List<Integer>> processOrder = getProcessOrder(cfg);
this.sbDigraph.append(" node [shape=rectangle];\n\n");
// definition of all nodes including their labels
for (Block v : visited) {
this.sbDigraph.append(" " + v.getId() + " [");
if (v.getType() == BlockType.CONDITIONAL_BLOCK) {
this.sbDigraph.append("shape=polygon sides=8 ");
} else if (v.getType() == BlockType.SPECIAL_BLOCK) {
this.sbDigraph.append("shape=oval ");
}
this.sbDigraph.append("label=\"");
if (verbose) {
this.sbDigraph.append("Process order: " + processOrder.get(v).toString().replaceAll("[\\[\\]]", "") + "\\n");
}
visualizeBlock(v, analysis);
}
this.sbDigraph.append("\n");
}
Aggregations