Skip to content
Snippets Groups Projects
ltl_gen.ml 15.90 KiB
open Batteries
open Rtl
open Linear
open Ltl
open Ltl_print
open Prog
open Utils
open Regalloc
open Linear_liveness

(* list of registers used to store arguments. [a0-a7] *)
let arg_registers =
  range ~start:starting_arg_register 8

(* Helpers to build pseudo-instructions.
 ** [push x] is compiled into [sub sp, sp, 8; sd r, 0(sp)]
 ** [pop x] is compiled into [ld r, 0(sp); add sp, sp, 8]
*)

let make_push r =
  [LSubi(reg_sp, reg_sp, !Archi.wordsize);
   LStore(reg_sp, 0, r, !Archi.wordsize)]

let make_pop r =
  [LLoad(r, reg_sp, 0, !Archi.wordsize);
   LAddi(reg_sp, reg_sp, !Archi.wordsize)]

let make_sp_sub v =
  [LSubi(reg_sp, reg_sp, v)]

let make_sp_add v =
  [LAddi(reg_sp, reg_sp, v)]

(* Moving between locations. [src] and [dst] are locations. [make_loc_mov src
   dst] generates instructions so that the value in [src] ends up in [dst],
   where [src] and [dst] can be registers [Reg r] or stack offsets [Stk o].
*)
let make_loc_mov src dst =
  match src, dst with
  | Stk osrc , Stk odst ->
    let rtmp = reg_tmp1 in
    [LLoad(rtmp, reg_fp, !Archi.wordsize * osrc, !Archi.wordsize);
     LStore(reg_fp, !Archi.wordsize * odst, rtmp, !Archi.wordsize)]
  | Stk osrc, Reg rdst ->
    [LLoad(rdst, reg_fp, !Archi.wordsize * osrc, !Archi.wordsize)]
  | Reg rsrc, Stk ofst ->
    [LStore(reg_fp, !Archi.wordsize * ofst, rsrc, !Archi.wordsize)]
  | Reg rsrc, Reg rdst ->
    [LMov(rdst,rsrc)]

(* load_loc tmp allocation r = (l, r'). Loads the equivalent of RTL register r
   in a LTL register r'. tmpis used if necessary. *)
let load_loc tmp allocation r =
  match Hashtbl.find_option allocation r with
  | None ->
    Error (Format.sprintf "Unable to allocate RTL register r%d." r)
  | Some (Stk o) -> OK ([LLoad(tmp, reg_fp, !Archi.wordsize * o, !Archi.wordsize)], tmp)
  | Some (Reg r) -> OK ([], r)

(* store_loc tmp allocation r = (l, r'). I want to write in RTL register r.
   Tells me that I just have to write to LTL register r' and execute l. *)
let store_loc tmp allocation r =
  match Hashtbl.find_option allocation r with
  | None ->
    Error (Format.sprintf "Unable to allocate RTL register r%d." r)
  | Some (Stk o) -> OK ([LStore(reg_fp, !Archi.wordsize * o, tmp, !Archi.wordsize)], tmp)
  | Some (Reg r) -> OK ([], r)

(* saves registers in [to_save] on the stack at offsets [fp + 8 * o, fp + 8 * (o
   - 1), fp + 8 * (o - 2)...]. Returns: