let allocate_registers base_block =
  
  (** Number of the last used register. *)

  let max_reg = ref 0 in
  let alloc_reg l v =
    let r =
      try
        assocp v.var_def l
      with
        | Not_found ->
            let r = !max_reg in incr max_reg; r
    in
      v.var_reg <- Some r;
      (v.var_def, r) :: l
  in
    
    (** @param l list of definition and associated register *)

    (* TODO: add destoys an operand! *)
  let alloc_instr l instr =
    match instr with
      | Nop -> l
      | Movi(v1, v2) -> alloc_reg (alloc_reg l v1) v2
      | Addi(v1, v2, v3) -> alloc_reg (alloc_reg (alloc_reg l v1) v2) v3
      | Call(_, a)
      | ExtCall(_, a) -> List.fold_left (fun l v -> alloc_reg l v) l a
  in
  let rec alloc_instrs l = function
    | h :: t -> alloc_instrs (alloc_instr l h) t
    | [] -> l
  in
    (* TODO: also allocate linked base blocks *)
    ignore (alloc_instrs [] base_block.bb_block)