Search in sources :

Example 1 with SpecialBlock

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");
}
Also used : Node(org.checkerframework.dataflow.cfg.node.Node) SpecialBlock(org.checkerframework.dataflow.cfg.block.SpecialBlock) RegularBlock(org.checkerframework.dataflow.cfg.block.RegularBlock) LinkedList(java.util.LinkedList)

Example 2 with SpecialBlock

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;
}
Also used : ExceptionBlock(org.checkerframework.dataflow.cfg.block.ExceptionBlock) Entry(java.util.Map.Entry) TypeMirror(javax.lang.model.type.TypeMirror) ConditionalBlock(org.checkerframework.dataflow.cfg.block.ConditionalBlock) AssignmentNode(org.checkerframework.dataflow.cfg.node.AssignmentNode) ReturnNode(org.checkerframework.dataflow.cfg.node.ReturnNode) LocalVariableNode(org.checkerframework.dataflow.cfg.node.LocalVariableNode) Node(org.checkerframework.dataflow.cfg.node.Node) ExceptionBlock(org.checkerframework.dataflow.cfg.block.ExceptionBlock) SpecialBlock(org.checkerframework.dataflow.cfg.block.SpecialBlock) Block(org.checkerframework.dataflow.cfg.block.Block) RegularBlock(org.checkerframework.dataflow.cfg.block.RegularBlock) ConditionalBlock(org.checkerframework.dataflow.cfg.block.ConditionalBlock) SpecialBlock(org.checkerframework.dataflow.cfg.block.SpecialBlock) RegularBlock(org.checkerframework.dataflow.cfg.block.RegularBlock)

Example 3 with SpecialBlock

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;
}
Also used : ExceptionBlock(org.checkerframework.dataflow.cfg.block.ExceptionBlock) Entry(java.util.Map.Entry) TypeMirror(javax.lang.model.type.TypeMirror) ConditionalBlock(org.checkerframework.dataflow.cfg.block.ConditionalBlock) AssignmentNode(org.checkerframework.dataflow.cfg.node.AssignmentNode) ReturnNode(org.checkerframework.dataflow.cfg.node.ReturnNode) LocalVariableNode(org.checkerframework.dataflow.cfg.node.LocalVariableNode) Node(org.checkerframework.dataflow.cfg.node.Node) ExceptionBlock(org.checkerframework.dataflow.cfg.block.ExceptionBlock) SpecialBlock(org.checkerframework.dataflow.cfg.block.SpecialBlock) Block(org.checkerframework.dataflow.cfg.block.Block) RegularBlock(org.checkerframework.dataflow.cfg.block.RegularBlock) ConditionalBlock(org.checkerframework.dataflow.cfg.block.ConditionalBlock) SpecialBlock(org.checkerframework.dataflow.cfg.block.SpecialBlock) RegularBlock(org.checkerframework.dataflow.cfg.block.RegularBlock)

Example 4 with SpecialBlock

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();
}
Also used : Node(org.checkerframework.dataflow.cfg.node.Node) SpecialBlock(org.checkerframework.dataflow.cfg.block.SpecialBlock)

Example 5 with SpecialBlock

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.");
    }
}
Also used : ReturnNode(org.checkerframework.dataflow.cfg.node.ReturnNode) SpecialBlock(org.checkerframework.dataflow.cfg.block.SpecialBlock) BugInCF(org.checkerframework.javacutil.BugInCF) UnderlyingAST(org.checkerframework.dataflow.cfg.UnderlyingAST) RequiresNonNull(org.checkerframework.checker.nullness.qual.RequiresNonNull)

Aggregations

SpecialBlock (org.checkerframework.dataflow.cfg.block.SpecialBlock)5 Node (org.checkerframework.dataflow.cfg.node.Node)4 RegularBlock (org.checkerframework.dataflow.cfg.block.RegularBlock)3 ReturnNode (org.checkerframework.dataflow.cfg.node.ReturnNode)3 Entry (java.util.Map.Entry)2 TypeMirror (javax.lang.model.type.TypeMirror)2 Block (org.checkerframework.dataflow.cfg.block.Block)2 ConditionalBlock (org.checkerframework.dataflow.cfg.block.ConditionalBlock)2 ExceptionBlock (org.checkerframework.dataflow.cfg.block.ExceptionBlock)2 AssignmentNode (org.checkerframework.dataflow.cfg.node.AssignmentNode)2 LocalVariableNode (org.checkerframework.dataflow.cfg.node.LocalVariableNode)2 LinkedList (java.util.LinkedList)1 RequiresNonNull (org.checkerframework.checker.nullness.qual.RequiresNonNull)1 UnderlyingAST (org.checkerframework.dataflow.cfg.UnderlyingAST)1 BugInCF (org.checkerframework.javacutil.BugInCF)1