use of org.checkerframework.dataflow.cfg.block.SpecialBlock 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.SpecialBlock 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.SpecialBlock 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.SpecialBlock in project checker-framework by typetools.
the class AbstractCFGVisualizer method visualizeBlockHelper.
/**
* Helper method to visualize a block.
*
* <p>NOTE: The output ends with a separator, only if an "after" store is visualized. The client
* {@link #visualizeBlock} should correct this if needed.
*
* @param bb the block
* @param analysis the current analysis
* @param separator the line separator. Examples: "\\l" for left justification in {@link
* DOTCFGVisualizer} (this is really a terminator, not a separator), "\n" to add a new line in
* {@link StringCFGVisualizer}
* @return the String representation of the block
*/
protected String visualizeBlockHelper(Block bb, @Nullable Analysis<V, S, T> analysis, String separator) {
StringBuilder sbBlock = new StringBuilder();
String contents = loopOverBlockContents(bb, analysis, separator);
if (!contents.isEmpty()) {
sbBlock.append(contents);
}
if (sbBlock.length() == 0) {
// Nothing got appended; use default text for empty block
if (bb.getType() == Block.BlockType.SPECIAL_BLOCK) {
sbBlock.append(visualizeSpecialBlock((SpecialBlock) bb));
} else if (bb.getType() == Block.BlockType.CONDITIONAL_BLOCK) {
sbBlock.append(visualizeConditionalBlock((ConditionalBlock) bb));
} else {
sbBlock.append("<empty block>");
}
}
// Visualize transfer input if necessary.
if (analysis != null) {
sbBlock.insert(0, visualizeBlockTransferInputBefore(bb, analysis) + separator);
if (verbose) {
Node lastNode = bb.getLastNode();
if (lastNode != null) {
if (!sbBlock.toString().endsWith(separator)) {
sbBlock.append(separator);
}
sbBlock.append(visualizeBlockTransferInputAfter(bb, analysis) + separator);
}
}
}
return sbBlock.toString();
}
use of org.checkerframework.dataflow.cfg.block.SpecialBlock in project checker-framework by typetools.
the class BackwardAnalysisImpl method initInitialInputs.
@Override
@RequiresNonNull("cfg")
protected void initInitialInputs() {
worklist.process(cfg);
SpecialBlock regularExitBlock = cfg.getRegularExitBlock();
SpecialBlock exceptionExitBlock = cfg.getExceptionalExitBlock();
if (worklist.depthFirstOrder.get(regularExitBlock) == null && worklist.depthFirstOrder.get(exceptionExitBlock) == null) {
throw new BugInCF("regularExitBlock and exceptionExitBlock should never both be null at the same time.");
}
UnderlyingAST underlyingAST = cfg.getUnderlyingAST();
List<ReturnNode> returnNodes = cfg.getReturnNodes();
assert transferFunction != null : "@AssumeAssertion(nullness): invariant";
S normalInitialStore = transferFunction.initialNormalExitStore(underlyingAST, returnNodes);
S exceptionalInitialStore = transferFunction.initialExceptionalExitStore(underlyingAST);
// initialize it as a start point of the analysis.
if (worklist.depthFirstOrder.get(regularExitBlock) != null) {
worklist.add(regularExitBlock);
inputs.put(regularExitBlock, new TransferInput<>(null, this, normalInitialStore));
outStores.put(regularExitBlock, normalInitialStore);
}
if (worklist.depthFirstOrder.get(exceptionExitBlock) != null) {
worklist.add(exceptionExitBlock);
inputs.put(exceptionExitBlock, new TransferInput<>(null, this, exceptionalInitialStore));
outStores.put(exceptionExitBlock, exceptionalInitialStore);
}
if (worklist.isEmpty()) {
throw new BugInCF("The worklist needs at least one exit block as starting point.");
}
if (inputs.isEmpty() || outStores.isEmpty()) {
throw new BugInCF("At least one input and one output store are required.");
}
}
Aggregations