use of org.checkerframework.dataflow.cfg.block.RegularBlock in project bazel by bazelbuild.
the class CFGDOTVisualizer method visualizeContent.
/**
* Produce a string representation of the contests of a basic block.
*
* @param bb
* Basic block to visualize.
* @return String representation.
*/
protected static <A extends AbstractValue<A>, S extends Store<S>, T extends TransferFunction<A, S>> String visualizeContent(Block bb, /*@Nullable*/
Analysis<A, S, T> analysis, boolean verbose) {
StringBuilder sb = new StringBuilder();
// loop over contents
List<Node> contents = new LinkedList<>();
switch(bb.getType()) {
case REGULAR_BLOCK:
contents.addAll(((RegularBlock) bb).getContents());
break;
case EXCEPTION_BLOCK:
contents.add(((ExceptionBlock) bb).getNode());
break;
case CONDITIONAL_BLOCK:
break;
case SPECIAL_BLOCK:
break;
default:
assert false : "All types of basic blocks covered";
}
boolean notFirst = false;
for (Node t : contents) {
if (notFirst) {
sb.append("\\n");
}
notFirst = true;
sb.append(prepareString(visualizeNode(t, analysis)));
}
// handle case where no contents are present
boolean centered = false;
if (sb.length() == 0) {
centered = true;
if (bb.getType() == BlockType.SPECIAL_BLOCK) {
SpecialBlock sbb = (SpecialBlock) bb;
switch(sbb.getSpecialType()) {
case ENTRY:
sb.append("<entry>");
break;
case EXIT:
sb.append("<exit>");
break;
case EXCEPTIONAL_EXIT:
sb.append("<exceptional-exit>");
break;
}
} else if (bb.getType() == BlockType.CONDITIONAL_BLOCK) {
return "";
} else {
return "?? empty ??";
}
}
// visualize transfer input if necessary
if (analysis != null) {
TransferInput<A, S> input = analysis.getInput(bb);
StringBuilder sb2 = new StringBuilder();
// split input representation to two lines
String s = input.toDOToutput().replace("}, else={", "}\\nelse={");
sb2.append("Before:");
sb2.append(s.subSequence(1, s.length() - 1));
// separator
sb2.append("\\n~~~~~~~~~\\n");
sb2.append(sb);
sb = sb2;
if (verbose) {
Node lastNode = null;
switch(bb.getType()) {
case REGULAR_BLOCK:
List<Node> blockContents = ((RegularBlock) bb).getContents();
lastNode = contents.get(blockContents.size() - 1);
break;
case EXCEPTION_BLOCK:
lastNode = ((ExceptionBlock) bb).getNode();
break;
}
if (lastNode != null) {
sb2.append("\\n~~~~~~~~~\\n");
s = analysis.getResult().getStoreAfter(lastNode.getTree()).toDOToutput().replace("}, else={", "}\\nelse={");
sb2.append("After:");
sb2.append(s);
}
}
}
return sb.toString() + (centered ? "" : "\\n");
}
use of org.checkerframework.dataflow.cfg.block.RegularBlock 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;
}
use of org.checkerframework.dataflow.cfg.block.RegularBlock 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;
}
}
Aggregations