aboutsummaryrefslogtreecommitdiffstats
path: root/scheduling/BTLtoRTLaux.ml
blob: dd7ba4c7603aad86660108d58e7000c500e998c4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
open Maps
open BTL
open RTL
open Camlcoq
open AuxTools
open DebugPrint
open PrintBTL

let is_atom = function
  | Bseq (_, _) | Bcond (_, _, _, _, _, _) -> false
  | _ -> true

let rec get_nn = function
  | Bnop ni
  | Bop (_, _, _, ni)
  | Bload (_, _, _, _, _, ni)
  | Bstore (_, _, _, _, ni)
  | Bcond (_, _, _, _, _, ni)
  | BF (Breturn (_, ni))
  | BF (Bcall (_, _, _, _, _, ni))
  | BF (Btailcall (_, _, _, ni))
  | BF (Bbuiltin (_, _, _, _, ni))
  | BF (Bjumptable (_, _, ni)) ->
      ni
  | BF (Bgoto s) -> s
  | Bseq (ib1, _) -> get_nn ib1

let translate_function code entry =
  let reached = ref (PTree.map (fun n i -> false) code) in
  let rtl_code = ref PTree.empty in
  let rec build_rtl_tree e =
    if get_some @@ PTree.get e !reached then ()
    else (
      reached := PTree.set e true !reached;
      let next_nodes = ref [] in
      let ib = (get_some @@ PTree.get e code).entry in
      let rec translate_btl_block ib k =
        print_btl_inst stderr ib;
        let rtli =
          match ib with
          | Bcond (cond, lr, BF (Bgoto s1), BF (Bgoto s2), info, ni) ->
              next_nodes := s1 :: s2 :: !next_nodes;
              Some (Icond (cond, lr, s1, s2, info), ni)
          | Bcond (cond, lr, BF (Bgoto s1), ib2, info, ni) ->
              assert (info = Some false);
              next_nodes := s1 :: !next_nodes;
              translate_btl_block ib2 None;
              Some (Icond (cond, lr, s1, get_nn ib2, info), ni)
          (* TODO gourdinl remove dynamic check *)
          | Bcond (_, _, _, _, _, _) ->
              failwith "translate_function: invalid Bcond"
          | Bseq (ib1, ib2) ->
              (* TODO gourdinl remove dynamic check *)
              assert (is_atom ib1);
              translate_btl_block ib1 (Some ib2);
              translate_btl_block ib2 None;
              None
          | Bnop ni -> Some (Inop (get_nn (get_some k)), ni)
          | Bop (op, lr, rd, ni) ->
              Some (Iop (op, lr, rd, get_nn (get_some k)), ni)
          | Bload (trap, chk, addr, lr, rd, ni) ->
              Some (Iload (trap, chk, addr, lr, rd, get_nn (get_some k)), ni)
          | Bstore (chk, addr, lr, rd, ni) ->
              Some (Istore (chk, addr, lr, rd, get_nn (get_some k)), ni)
          | BF (Bcall (sign, fn, lr, rd, s, ni)) ->
              next_nodes := s :: !next_nodes;
              Some (Icall (sign, fn, lr, rd, s), ni)
          | BF (Btailcall (sign, fn, lr, ni)) ->
              Some (Itailcall (sign, fn, lr), ni)
          | BF (Bbuiltin (ef, lr, rd, s, ni)) ->
              next_nodes := s :: !next_nodes;
              Some (Ibuiltin (ef, lr, rd, s), ni)
          | BF (Bjumptable (arg, tbl, ni)) -> Some (Ijumptable (arg, tbl), ni)
          | BF (Breturn (oreg, ni)) -> Some (Ireturn oreg, ni)
          | BF (Bgoto s) ->
              next_nodes := s :: !next_nodes;
              None
        in
        match rtli with
        | Some (inst, ni) -> rtl_code := PTree.set ni inst !rtl_code
        | None -> ()
      in
      translate_btl_block ib None;
      let succs = !next_nodes in
      List.iter build_rtl_tree succs)
  in
  build_rtl_tree entry;
  !rtl_code

let btl2rtl (f : BTL.coq_function) =
  debug_flag := true;
  let code = f.fn_code in
  let entry = f.fn_entrypoint in
  let rtl = translate_function code entry in
  let dm = PTree.map (fun n i -> n) code in
  debug "Entry %d\n" (P.to_int entry);
  debug "RTL Code: ";
  print_code rtl;
  debug "Dupmap:\n";
  print_ptree print_pint dm;
  debug "\n";
  debug_flag := false;
  ((rtl, entry), dm)