See: basic blocks

Here is the pseudocode:

type Block = Vector<Instruction>
 
def instructions_to_blocks(instructions: Vector<Instruction>) {
  var current_block: Block = []
  for (instr <- instructions) {
    if (instr is label) {
      // End the current block
      if current_block is not empty {
        yield current_block
      }
 
      // Start a new block with this label
      current_block = [instr]
    } else { // is normal instruction
      // Add the instruction to the new block
      current_block.push(instr)
      
      // If it is a terminator, finish the current block
      if (instr is terminator) {
        yield current_block
        current_block = []
      }
    }
  }
  // yield final block
  if current_block is not empty {
    yield current_block;
  }
}

Lesley’s remark: I simplified the code a bit with a generator yield syntax

We can also compute a “label to basic block” map structure in this process.