use of org.checkerframework.dataflow.cfg.block.Block in project checker-framework by typetools.
the class ForwardAnalysisImpl method initInitialInputs.
@Override
@RequiresNonNull("cfg")
protected void initInitialInputs() {
worklist.process(cfg);
Block entry = cfg.getEntryBlock();
worklist.add(entry);
UnderlyingAST underlyingAST = cfg.getUnderlyingAST();
List<LocalVariableNode> parameters = getParameters(underlyingAST);
assert transferFunction != null : "@AssumeAssertion(nullness): invariant";
S initialStore = transferFunction.initialStore(underlyingAST, parameters);
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 checker-framework by typetools.
the class ForwardAnalysisImpl method runAnalysisFor.
@Override
public S runAnalysisFor(@FindDistinct Node node, Analysis.BeforeOrAfter preOrPost, TransferInput<V, S> blockTransferInput, IdentityHashMap<Node, V> nodeValues, Map<TransferInput<V, S>, IdentityHashMap<Node, TransferResult<V, S>>> analysisCaches) {
Block block = node.getBlock();
assert block != null : "@AssumeAssertion(nullness): invariant";
Node oldCurrentNode = currentNode;
// Prepare cache
IdentityHashMap<Node, TransferResult<V, S>> cache;
if (analysisCaches != null) {
cache = analysisCaches.computeIfAbsent(blockTransferInput, __ -> new IdentityHashMap<>());
} else {
cache = null;
}
if (isRunning) {
assert currentInput != null : "@AssumeAssertion(nullness): invariant";
return currentInput.getRegularStore();
}
setNodeValues(nodeValues);
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<V, S> store = blockTransferInput;
TransferResult<V, S> transferResult;
for (Node n : rb.getNodes()) {
setCurrentNode(n);
if (n == node && preOrPost == Analysis.BeforeOrAfter.BEFORE) {
return store.getRegularStore();
}
if (cache != null && cache.containsKey(n)) {
transferResult = cache.get(n);
} else {
// Copy the store to avoid changing other blocks' transfer inputs in {@link #inputs}
transferResult = callTransferFunction(n, store.copy());
if (cache != null) {
cache.put(n, transferResult);
}
}
if (n == node) {
return transferResult.getRegularStore();
}
store = new TransferInput<>(n, this, transferResult);
}
throw new BugInCF("node %s is not in node.getBlock()=%s", node, block);
}
case EXCEPTION_BLOCK:
{
ExceptionBlock eb = (ExceptionBlock) block;
// Apply the transfer function to content
if (eb.getNode() != node) {
throw new BugInCF("Node should be equal to eb.getNode(). But get: node: " + node + "\teb.getNode(): " + eb.getNode());
}
if (preOrPost == Analysis.BeforeOrAfter.BEFORE) {
return blockTransferInput.getRegularStore();
}
setCurrentNode(node);
// Copy the store to avoid changing other blocks' transfer inputs in {@link #inputs}
TransferResult<V, S> transferResult;
if (cache != null && cache.containsKey(node)) {
transferResult = cache.get(node);
} else {
// Copy the store to avoid changing other blocks' transfer inputs in {@link #inputs}
transferResult = callTransferFunction(node, blockTransferInput.copy());
if (cache != null) {
cache.put(node, transferResult);
}
}
return transferResult.getRegularStore();
}
default:
// Only regular blocks and exceptional blocks can hold nodes.
throw new BugInCF("Unexpected block type: " + block.getType());
}
} finally {
setCurrentNode(oldCurrentNode);
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.
*
* @param node the node to analyze
* @param preOrPost which store to return: the store immediately before {@code node} or the store
* after {@code node}
* @return the store before or after {@code node} (depends on the value of {@code before}) after
* running the analysis
*/
@Nullable
protected S runAnalysisFor(Node node, Analysis.BeforeOrAfter preOrPost) {
Block block = node.getBlock();
assert block != null : "@AssumeAssertion(nullness): invariant";
TransferInput<V, S> transferInput = stores.get(block);
if (transferInput == null) {
return null;
}
return runAnalysisFor(node, preOrPost, transferInput, nodeValues, analysisCaches);
}
use of org.checkerframework.dataflow.cfg.block.Block in project checker-framework by typetools.
the class BackwardAnalysisImpl method performAnalysis.
@Override
public void performAnalysis(ControlFlowGraph cfg) {
if (isRunning) {
throw new BugInCF("performAnalysis() shouldn't be called when the analysis is running.");
}
isRunning = true;
try {
init(cfg);
while (!worklist.isEmpty()) {
Block b = worklist.poll();
performAnalysisBlock(b);
}
} finally {
assert isRunning;
// In case performAnalysisBlock crashed, reset isRunning to false.
isRunning = false;
}
}
use of org.checkerframework.dataflow.cfg.block.Block in project checker-framework by typetools.
the class CFGTranslationPhaseThree method getPredecessorHolder.
/**
* Return a predecessor holder that can be used to set the successor of {@code pred} in the place
* where previously the edge pointed to {@code cur}. Additionally, the predecessor holder also
* takes care of unlinking (i.e., removing the {@code pred} from {@code cur's} predecessors).
*
* @param pred a block whose successor should be set
* @param cur the previous successor of {@code pred}
* @return a predecessor holder to set the successor of {@code pred}
*/
// AST node comparisons
@SuppressWarnings("interning:not.interned")
protected static PredecessorHolder getPredecessorHolder(final BlockImpl pred, final BlockImpl cur) {
switch(pred.getType()) {
case SPECIAL_BLOCK:
SingleSuccessorBlockImpl s = (SingleSuccessorBlockImpl) pred;
return singleSuccessorHolder(s, cur);
case CONDITIONAL_BLOCK:
// add pred correctly to predecessor list
final ConditionalBlockImpl c = (ConditionalBlockImpl) pred;
if (c.getThenSuccessor() == cur) {
return new PredecessorHolder() {
@Override
public void setSuccessor(BlockImpl b) {
c.setThenSuccessor(b);
cur.removePredecessor(pred);
}
@Override
public BlockImpl getBlock() {
return c;
}
};
} else {
assert c.getElseSuccessor() == cur;
return new PredecessorHolder() {
@Override
public void setSuccessor(BlockImpl b) {
c.setElseSuccessor(b);
cur.removePredecessor(pred);
}
@Override
public BlockImpl getBlock() {
return c;
}
};
}
case EXCEPTION_BLOCK:
// add pred correctly to predecessor list
final ExceptionBlockImpl e = (ExceptionBlockImpl) pred;
if (e.getSuccessor() == cur) {
return singleSuccessorHolder(e, cur);
} else {
// ignore keyfor type
@SuppressWarnings("keyfor:assignment") Set<Map.Entry<TypeMirror, Set<Block>>> entrySet = e.getExceptionalSuccessors().entrySet();
for (final Map.Entry<TypeMirror, Set<Block>> entry : entrySet) {
if (entry.getValue().contains(cur)) {
return new PredecessorHolder() {
@Override
public void setSuccessor(BlockImpl b) {
e.addExceptionalSuccessor(b, entry.getKey());
cur.removePredecessor(pred);
}
@Override
public BlockImpl getBlock() {
return e;
}
};
}
}
}
throw new BugInCF("Unreachable");
case REGULAR_BLOCK:
RegularBlockImpl r = (RegularBlockImpl) pred;
return singleSuccessorHolder(r, cur);
default:
throw new BugInCF("Unexpected block type " + pred.getType());
}
}
Aggregations