private void transitionBlocks(LBlock next) {
   assert (pending_.size() == 0 || block_ != null);
   if (block_ != null) {
     assert (pending_.get(pending_.size() - 1).isControl());
     assert (block_.pc() >= lir_.entry_pc && block_.pc() < lir_.exit_pc);
     block_.setInstructions(pending_.toArray(new LInstruction[0]));
     pending_.clear();
   }
   block_ = next;
 }
  private LGraph buildBlocks() throws Exception {
    lir_.entry = new LBlock(lir_.entry_pc);
    BlockBuilder builder = new BlockBuilder(lir_);
    LBlock entry = builder.parse();

    // Get an RPO ordering of the blocks, since we don't have predecessors yet.
    LBlock[] blocks = BlockAnalysis.Order(entry);

    // Remove dead references.
    // Ignore blocks that are unreachable and are always jumped over
    // e.g.
    // if(1 != 1)
    //   loop()..
    for (LBlock block : blocks) {
      int numPredecessors = block.numPredecessors();
      for (int i = 0; i < numPredecessors; i++) {
        if (!ContainsBlock(blocks, block.getPredecessor(i))) {
          block.removePredecessor(block.getPredecessor(i));
          numPredecessors--;
        }
      }
    }

    if (!BlockAnalysis.IsReducible(blocks))
      throw new Exception("control flow graph is not reducible");

    // Split critical edges in the graph (is this even needed?)
    BlockAnalysis.SplitCriticalEdges(blocks);

    // Reorder the blocks since we could have introduced new nodes.
    blocks = BlockAnalysis.Order(entry);
    assert (BlockAnalysis.IsReducible(blocks));

    BlockAnalysis.ComputeDominators(blocks);
    BlockAnalysis.ComputeImmediateDominators(blocks);
    BlockAnalysis.ComputeDominatorTree(blocks);
    BlockAnalysis.FindLoops(blocks);

    LGraph graph = new LGraph();
    graph.blocks = blocks;
    graph.entry = blocks[0];
    if (lir_.argDepth > 0) graph.nargs = ((lir_.argDepth - 12) / 4) + 1;
    else graph.nargs = 0;

    return graph;
  }
    public LBlock parse() {
      for (int i = 0; i < lir_.instructions.size(); i++) {
        LInstruction ins = lir_.instructions.get(i);

        if (lir_.isTarget(ins.pc())) {
          // This instruction is the target of a basic block, so
          // finish the old one.
          LBlock next = lir_.blockOfTarget(ins.pc());

          // Multiple instructions could be at the same pc,
          // because of decomposition, so make sure we're not
          // transitioning to the same block.
          if (block_ != next) {
            // Add implicit control flow to make further algorithms easier.
            if (block_ != null) {
              assert (!pending_.get(pending_.size() - 1).isControl());
              pending_.add(new LGoto(next));
              next.addPredecessor(block_);
            }

            // Fallthrough to the next block.
            transitionBlocks(next);
          }
        }

        // If there is no block present, we assume this is dead code.
        if (block_ == null) continue;

        pending_.add(ins);

        switch (ins.op()) {
          case Return:
            {
              // A return terminates the current block.
              transitionBlocks(null);
              break;
            }

          case Jump:
            {
              LJump jump = (LJump) ins;
              jump.target().addPredecessor(block_);
              transitionBlocks(null);
              break;
            }

          case JumpCondition:
            {
              LJumpCondition jcc = (LJumpCondition) ins;
              jcc.trueTarget().addPredecessor(block_);
              jcc.falseTarget().addPredecessor(block_);

              // The next iteration will pick the false target up.
              assert (lir_.instructions.get(i + 1).pc() == jcc.falseTarget().pc());
              transitionBlocks(null);
              break;
            }

          case Switch:
            {
              LSwitch switch_ = (LSwitch) ins;
              for (int j = 0; j < switch_.numSuccessors(); j++) {
                switch_.getSuccessor(j).addPredecessor(block_);
              }
              transitionBlocks(null);
              break;
            }

          default:
            break;
        }
      }
      return lir_.entry;
    }