use of org.checkerframework.dataflow.cfg.block.Block 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.Block in project bazel by bazelbuild.
the class ControlFlowGraph method getDepthFirstOrderedBlocks.
/**
* @return The list of all basic block in this control flow graph
* in reversed depth-first postorder sequence.
*
* Blocks may appear more than once in the sequence.
*/
public List<Block> getDepthFirstOrderedBlocks() {
List<Block> dfsOrderResult = new LinkedList<>();
Set<Block> visited = new HashSet<>();
Deque<Block> worklist = new LinkedList<>();
worklist.add(entryBlock);
while (!worklist.isEmpty()) {
Block cur = worklist.getLast();
if (visited.contains(cur)) {
dfsOrderResult.add(cur);
worklist.removeLast();
} else {
visited.add(cur);
Deque<Block> successors = getSuccessors(cur);
successors.removeAll(visited);
worklist.addAll(successors);
}
}
Collections.reverse(dfsOrderResult);
return dfsOrderResult;
}
use of org.checkerframework.dataflow.cfg.block.Block 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.Block in project bazel by bazelbuild.
the class Analysis method init.
/** Initialize the analysis with a new control flow graph. */
protected void init(ControlFlowGraph cfg) {
this.cfg = cfg;
thenStores = new IdentityHashMap<>();
elseStores = new IdentityHashMap<>();
inputs = new IdentityHashMap<>();
storesAtReturnStatements = new IdentityHashMap<>();
worklist = new Worklist(cfg);
nodeValues = new IdentityHashMap<>();
finalLocalValues = new HashMap<>();
worklist.add(cfg.getEntryBlock());
List<LocalVariableNode> parameters = null;
UnderlyingAST underlyingAST = cfg.getUnderlyingAST();
if (underlyingAST.getKind() == Kind.METHOD) {
MethodTree tree = ((CFGMethod) underlyingAST).getMethod();
parameters = new ArrayList<>();
for (VariableTree p : tree.getParameters()) {
LocalVariableNode var = new LocalVariableNode(p);
parameters.add(var);
// TODO: document that LocalVariableNode has no block that it
// belongs to
}
} else if (underlyingAST.getKind() == Kind.LAMBDA) {
LambdaExpressionTree lambda = ((CFGLambda) underlyingAST).getLambdaTree();
parameters = new ArrayList<>();
for (VariableTree p : lambda.getParameters()) {
LocalVariableNode var = new LocalVariableNode(p);
parameters.add(var);
// TODO: document that LocalVariableNode has no block that it
// belongs to
}
} else {
// nothing to do
}
S initialStore = transferFunction.initialStore(underlyingAST, parameters);
Block entry = cfg.getEntryBlock();
thenStores.put(entry, initialStore);
elseStores.put(entry, initialStore);
inputs.put(entry, new TransferInput<>(null, this, initialStore));
}
use of org.checkerframework.dataflow.cfg.block.Block 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