/** @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;
  }
  /**
   * Get a list of all successor Blocks for 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;
  }