From 9e90172e13ff96b84f11c6b023e7493b5d846274 Mon Sep 17 00:00:00 2001
From: Youssef <youssef.sellami@student-cs.fr>
Date: Sun, 16 Mar 2025 15:30:37 +0100
Subject: [PATCH] functions : LTL

---
 src/linear_liveness.ml |  7 +++++--
 src/linear_run.ml      | 19 +++++++++++++++++++
 src/ltl_gen.ml         | 35 ++++++++++++++++++++++++++++++-----
 3 files changed, 54 insertions(+), 7 deletions(-)

diff --git a/src/linear_liveness.ml b/src/linear_liveness.ml
index 0a5891e..5082e7f 100644
--- a/src/linear_liveness.ml
+++ b/src/linear_liveness.ml
@@ -16,18 +16,21 @@ let gen_live (i: rtl_instr) =
   | Rmov (_, rs) -> Set.singleton rs
   | Rret r -> Set.singleton r
   | Rlabel _ -> Set.empty
+  | Rcall (_, _, args) -> Set.of_list args
 
 let kill_live (i: rtl_instr) =
   match i with
   | Rbinop (_, rd, _, _)
   | Runop (_, rd,_)
   | Rconst (rd, _)
-  | Rmov (rd,_) -> Set.singleton rd
+  | Rmov (rd,_)
+  | Rcall (Some rd, _, _) -> Set.singleton rd
   | Rbranch (_, _, _, _)
   | Rprint _
   | Rret _
   | Rjmp _
-  | Rlabel _ -> Set.empty
+  | Rlabel _ 
+  | Rcall (None, _, _) -> Set.empty
 
 let linear_succs (ins: rtl_instr) i labels =
   match ins with
diff --git a/src/linear_run.ml b/src/linear_run.ml
index 63b622a..8051790 100644
--- a/src/linear_run.ml
+++ b/src/linear_run.ml
@@ -60,6 +60,25 @@ let rec exec_linear_instr oc lp fname f st (i: rtl_instr) =
       | _ -> Error (Printf.sprintf "Ret on undefined register (%s)" (print_reg r))
     end
   | Rlabel n -> OK (None, st)
+  | Rcall (rd_opt, g, args) -> 
+    begin 
+    let vs_opt = List.fold_left (fun acc arg -> 
+        match acc with
+        | None -> None
+        | Some vs -> 
+          (match Hashtbl.find_option st.regs arg with
+          | None -> None
+          | Some v -> Some (vs@[v]))) 
+          (Some []) args 
+      in match vs_opt with
+      | Some params -> find_function lp g >>= fun found_g ->
+        (match rd_opt, exec_linear_fun oc lp st g found_g params with
+        | _, Error msg -> Error msg
+        | Some rd, OK (Some ret, st') -> exec_linear_instr oc lp fname f st' (Rconst (rd, ret))
+        | Some rd, OK (None, st') -> Error (Printf.sprintf "Function %s doesn't have a return value" g)
+        | None, OK (_, st') -> OK(None, st'))
+      | _ -> Error (Printf.sprintf "Function %s applied on undefined register" g)
+    end
 
 and exec_linear_instr_at oc lp fname ({  linearfunbody;  } as f) st i =
   let l = List.drop_while (fun x -> x <> Rlabel i) linearfunbody in
diff --git a/src/ltl_gen.ml b/src/ltl_gen.ml
index aa6a9fa..581f0c9 100644
--- a/src/ltl_gen.ml
+++ b/src/ltl_gen.ml
@@ -51,7 +51,7 @@ let make_loc_mov src dst =
     [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. *)
+   in a LTL register r'. tmp is used if necessary. *)
 let load_loc tmp allocation r =
   match Hashtbl.find_option allocation r with
   | None ->
@@ -215,26 +215,27 @@ let written_rtl_regs_instr (i: rtl_instr) =
   | Rbinop (_, rd, _, _)
   | Runop (_, rd, _)
   | Rconst (rd, _)
-  | Rmov (rd, _) -> Set.singleton rd
+  | Rmov (rd, _) 
+  | Rcall (Some rd, _, _)-> Set.singleton rd
   | Rprint _
   | Rret _
   | Rlabel _
   | Rbranch (_, _, _, _)
-  | Rjmp _ -> Set.empty
+  | Rjmp _ 
+  | Rcall (None, _, _) -> Set.empty
 
 let read_rtl_regs_instr (i: rtl_instr) =
   match i with
   | Rbinop (_, _, rs1, rs2)
   | Rbranch (_, rs1, rs2, _) -> Set.of_list [rs1; rs2]
-
   | Rprint rs
   | Runop (_, _, rs)
   | Rmov (_, rs)
   | Rret rs -> Set.singleton rs
-
   | Rlabel _
   | Rconst (_, _)
   | Rjmp _ -> Set.empty
+  | Rcall (_, _, args) -> Set.of_list args
 
 let read_rtl_regs (l: rtl_instr list) =
   List.fold_left (fun acc i -> Set.union acc (read_rtl_regs_instr i))
@@ -323,6 +324,30 @@ let ltl_instrs_of_linear_instr fname live_out allocation
     load_loc reg_tmp1 allocation r >>= fun (l,r) ->
     OK (l @ [LMov (reg_ret, r) ; LJmp epilogue_label])
   | Rlabel l -> OK [LLabel (Format.sprintf "%s_%d" fname l)]
+
+  | Rcall (rd_opt, f, rargs) -> 
+    caller_save live_out allocation rargs >>= fun to_save ->
+    let save_regs_instrs, arg_saved, ofs = save_caller_save (Set.to_list to_save) (-(numspilled + 1))
+    in let move_sp_instr1 = LSubi(reg_sp, reg_s0, (Archi.wordsize ()) * -(ofs + 1))
+    in pass_parameters rargs allocation arg_saved >>= fun (parameter_passing_instrs, npush) ->
+    let call_instr = LCall f
+    in let move_sp_instr2 = LAddi(reg_sp, reg_sp, (Archi.wordsize ()) * npush)
+    in let return_instrs_and_reg = match rd_opt with
+    | None -> OK ([], None)
+    | Some rd -> 
+      match Hashtbl.find_option allocation rd with
+      | None -> Error (Format.sprintf "Could not find allocation for register %d\n" rd)
+      | Some (Stk o) -> OK (make_loc_mov (Reg reg_ret) (Stk o) , None)
+      | Some (Reg r_phy) -> OK (make_loc_mov (Reg reg_ret) (Reg r_phy), Some r_phy)
+    in return_instrs_and_reg >>= fun (return_instrs, r_ret_opt) ->
+    let arg_saved_wout_rd = List.filter (fun (reg, stk_loc) -> match r_ret_opt with | None -> true | Some r_ret -> reg != r_ret) arg_saved
+    in let restore_caller_save_instrs = restore_caller_save arg_saved_wout_rd
+    in let move_sp_instr3 = LAddi(reg_sp, reg_sp, (Archi.wordsize ()) * -(ofs + 1))
+    in OK (save_regs_instrs 
+    @ move_sp_instr1 :: parameter_passing_instrs 
+    @ call_instr :: move_sp_instr2 :: return_instrs
+    @ restore_caller_save_instrs
+    @ [move_sp_instr3])
   in
   res >>= fun l ->
   OK (LComment (Format.asprintf "#<span style=\"background: pink;\"><b>Linear instr</b>: %a #</span>" (Rtl_print.dump_rtl_instr fname (None, None) ~endl:"") ins)::l)
-- 
GitLab