Search in sources :

Example 36 with Block

use of org.checkerframework.dataflow.cfg.block.Block in project checker-framework by typetools.

the class CFGTranslationPhaseThree method process.

/**
 * Perform phase three on the control flow graph {@code cfg}.
 *
 * @param cfg the control flow graph. Ownership is transfered to this method and the caller is not
 *     allowed to read or modify {@code cfg} after the call to {@code process} any more.
 * @return the resulting control flow graph
 */
// TODO: successors
@SuppressWarnings("nullness")
public static ControlFlowGraph process(ControlFlowGraph cfg) {
    Set<Block> worklist = cfg.getAllBlocks();
    Set<Block> dontVisit = new HashSet<>();
    // fix predecessor lists by removing any unreachable predecessors
    for (Block c : worklist) {
        BlockImpl cur = (BlockImpl) c;
        for (Block pred : new HashSet<>(cur.getPredecessors())) {
            if (!worklist.contains(pred)) {
                cur.removePredecessor((BlockImpl) pred);
            }
        }
    }
    // remove empty blocks
    for (Block cur : worklist) {
        if (dontVisit.contains(cur)) {
            continue;
        }
        if (cur.getType() == BlockType.REGULAR_BLOCK) {
            RegularBlockImpl b = (RegularBlockImpl) cur;
            if (b.isEmpty()) {
                Set<RegularBlockImpl> emptyBlocks = new HashSet<>();
                Set<PredecessorHolder> predecessors = new LinkedHashSet<>();
                BlockImpl succ = computeNeighborhoodOfEmptyBlock(b, emptyBlocks, predecessors);
                for (RegularBlockImpl e : emptyBlocks) {
                    succ.removePredecessor(e);
                    dontVisit.add(e);
                }
                for (PredecessorHolder p : predecessors) {
                    BlockImpl block = p.getBlock();
                    dontVisit.add(block);
                    succ.removePredecessor(block);
                    p.setSuccessor(succ);
                }
            }
        }
    }
    // remove useless conditional blocks
    /* Issue 3267 revealed that this is a dangerous optimization:
       it merges a block that evaluates one condition onto an unrelated following block,
       which can also be a condition. The then/else stores from the first block are still
       set, leading to incorrect results for the then/else stores in the following block.
       The correct result would be to merge the then/else stores from the previous block.
       However, as this is late in the CFG construction, I didn't see how to add e.g. a
       dummy variable declaration node in a dummy regular block, which would cause a merge.
       So for now, let's not perform this optimization.
       It would be interesting to know how large the impact of this optimization is.

    worklist = cfg.getAllBlocks();
    for (Block c : worklist) {
        BlockImpl cur = (BlockImpl) c;

        if (cur.getType() == BlockType.CONDITIONAL_BLOCK) {
            ConditionalBlockImpl cb = (ConditionalBlockImpl) cur;
            assert cb.getPredecessors().size() == 1;
            if (cb.getThenSuccessor() == cb.getElseSuccessor()) {
                BlockImpl pred = cb.getPredecessors().iterator().next();
                PredecessorHolder predecessorHolder = getPredecessorHolder(pred, cb);
                BlockImpl succ = (BlockImpl) cb.getThenSuccessor();
                succ.removePredecessor(cb);
                predecessorHolder.setSuccessor(succ);
            }
        }
    }
    */
    // merge consecutive basic blocks if possible
    worklist = cfg.getAllBlocks();
    for (Block cur : worklist) {
        if (cur.getType() == BlockType.REGULAR_BLOCK) {
            RegularBlockImpl b = (RegularBlockImpl) cur;
            Block succ = b.getRegularSuccessor();
            if (succ.getType() == BlockType.REGULAR_BLOCK) {
                RegularBlockImpl rs = (RegularBlockImpl) succ;
                if (rs.getPredecessors().size() == 1) {
                    b.setSuccessor(rs.getRegularSuccessor());
                    b.addNodes(rs.getNodes());
                    rs.getRegularSuccessor().removePredecessor(rs);
                }
            }
        }
    }
    return cfg;
}
Also used : ExceptionBlockImpl(org.checkerframework.dataflow.cfg.block.ExceptionBlockImpl) BlockImpl(org.checkerframework.dataflow.cfg.block.BlockImpl) RegularBlockImpl(org.checkerframework.dataflow.cfg.block.RegularBlockImpl) ConditionalBlockImpl(org.checkerframework.dataflow.cfg.block.ConditionalBlockImpl) SingleSuccessorBlockImpl(org.checkerframework.dataflow.cfg.block.SingleSuccessorBlockImpl) LinkedHashSet(java.util.LinkedHashSet) RegularBlockImpl(org.checkerframework.dataflow.cfg.block.RegularBlockImpl) Block(org.checkerframework.dataflow.cfg.block.Block) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet)

Example 37 with Block

use of org.checkerframework.dataflow.cfg.block.Block in project checker-framework by typetools.

the class ControlFlowGraph method getDepthFirstOrderedBlocks.

/**
 * Returns all basic blocks in this control flow graph, in reversed depth-first postorder. Blocks
 * may appear more than once in the sequence.
 *
 * @return the list of all basic block in this control flow graph in reversed depth-first
 *     postorder sequence
 */
public List<Block> getDepthFirstOrderedBlocks() {
    List<Block> dfsOrderResult = new ArrayList<>();
    Set<Block> visited = new HashSet<>();
    // worklist can contain values that are not yet in visited.
    Deque<Block> worklist = new ArrayDeque<>();
    worklist.add(entryBlock);
    while (!worklist.isEmpty()) {
        Block cur = worklist.getLast();
        if (visited.contains(cur)) {
            dfsOrderResult.add(cur);
            worklist.removeLast();
        } else {
            visited.add(cur);
            for (Block b : cur.getSuccessors()) {
                if (!visited.contains(b)) {
                    worklist.add(b);
                }
            }
        }
    }
    Collections.reverse(dfsOrderResult);
    return dfsOrderResult;
}
Also used : ArrayList(java.util.ArrayList) 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) SingleSuccessorBlock(org.checkerframework.dataflow.cfg.block.SingleSuccessorBlock) ConditionalBlock(org.checkerframework.dataflow.cfg.block.ConditionalBlock) ArrayDeque(java.util.ArrayDeque) HashSet(java.util.HashSet)

Aggregations

Block (org.checkerframework.dataflow.cfg.block.Block)37 ExceptionBlock (org.checkerframework.dataflow.cfg.block.ExceptionBlock)30 ConditionalBlock (org.checkerframework.dataflow.cfg.block.ConditionalBlock)27 SpecialBlock (org.checkerframework.dataflow.cfg.block.SpecialBlock)25 RegularBlock (org.checkerframework.dataflow.cfg.block.RegularBlock)20 SingleSuccessorBlock (org.checkerframework.dataflow.cfg.block.SingleSuccessorBlock)18 HashSet (java.util.HashSet)10 ArrayList (java.util.ArrayList)9 List (java.util.List)9 TypeMirror (javax.lang.model.type.TypeMirror)9 Node (org.checkerframework.dataflow.cfg.node.Node)8 LocalVariableNode (org.checkerframework.dataflow.cfg.node.LocalVariableNode)7 ArrayDeque (java.util.ArrayDeque)6 IdentityHashMap (java.util.IdentityHashMap)6 LinkedHashSet (java.util.LinkedHashSet)6 Set (java.util.Set)6 BugInCF (org.checkerframework.javacutil.BugInCF)6 LinkedList (java.util.LinkedList)5 ReturnNode (org.checkerframework.dataflow.cfg.node.ReturnNode)5 Map (java.util.Map)4