-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathir.ml
122 lines (105 loc) · 3.71 KB
/
ir.ml
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
type local_id = int [@@deriving show]
type global_id = string [@@deriving show]
type label = string [@@deriving show]
type instruction =
| Alloc
| GetGlobal of string * bool
| Load of local_id
| Store of local_id * local_id
| StoreEmptyTable of local_id
| StoreClosure of local_id * global_id * local_id list
| GetField of local_id * string * bool
| GetIndex of local_id * local_id * bool
| NumberConstant of Pico_number.t
| BoolConstant of bool
| StringConstant of string
| NilConstant
| Call of local_id * local_id list
| UnaryOp of string * local_id
| BinaryOp of local_id * string * local_id
| Phi of (label * local_id) list
[@@deriving show]
type terminator =
| Ret of local_id option
| Br of label
| Cbr of local_id * label * label
[@@deriving show]
type block = {
instructions : (local_id * instruction) list;
terminator : local_id * terminator;
hint_normalize : bool;
}
[@@deriving show]
type cfg = { entry : block; named : (label * block) list } [@@deriving show]
type fun_def = {
name : global_id;
capture_ids : local_id list;
arg_ids : local_id option list;
cfg : cfg;
}
[@@deriving show]
module LocalIdMap = Map.Make (struct
type t = local_id
let compare = Stdlib.compare
end)
let show_local_id_map show_v s =
s |> LocalIdMap.bindings
|> List.map (fun (k, v) -> Printf.sprintf "%d -> %s" k (show_v v))
|> String.concat "; "
module LocalIdSet = Set.Make (struct
type t = local_id
let compare = Stdlib.compare
end)
let show_local_id_set s =
s |> LocalIdSet.elements |> List.map string_of_int |> String.concat "; "
module LabelMap = Map.Make (struct
type t = label
let compare = Stdlib.compare
end)
let instruction_map_local_ids (f : local_id -> local_id)
(instruction : instruction) : instruction =
match (instruction : instruction) with
| Alloc -> instruction
| GetGlobal _ -> instruction
| Load var_id -> Load (f var_id)
| Store (var_id, val_id) -> Store (f var_id, f val_id)
| StoreEmptyTable var_id -> StoreEmptyTable (f var_id)
| StoreClosure (var_id, closure_id, capture_ids) ->
StoreClosure (f var_id, closure_id, List.map f capture_ids)
| GetField (var_id, field_name, create_if_missing) ->
GetField (f var_id, field_name, create_if_missing)
| GetIndex (var_id, index_id, create_if_missing) ->
GetIndex (f var_id, f index_id, create_if_missing)
| NumberConstant _ -> instruction
| BoolConstant _ -> instruction
| StringConstant _ -> instruction
| NilConstant -> instruction
| Call (closure_id, arg_ids) -> Call (f closure_id, List.map f arg_ids)
| UnaryOp (op, arg_id) -> UnaryOp (op, f arg_id)
| BinaryOp (left_id, op, right_id) -> BinaryOp (f left_id, op, f right_id)
| Phi branches -> Phi (List.map (fun (label, id) -> (label, f id)) branches)
let terminator_map_local_ids (f : local_id -> local_id)
(terminator : terminator) : terminator =
match (terminator : terminator) with
| Ret (Some id) -> Ret (Some (f id))
| Ret None -> terminator
| Br _ -> terminator
| Cbr (val_id, l_true, l_false) -> Cbr (f val_id, l_true, l_false)
let cfg_map_blocks (f : block -> block) (cfg : cfg) : cfg =
{
entry = f cfg.entry;
named = List.map (fun (id, block) -> (id, f block)) cfg.named;
}
let split_block_phi_instructions (block : block) =
let is_phi = function _, Phi _ -> true | _ -> false in
let unwrap_phi = function
| id, Phi v -> (id, v)
| _ -> failwith "Not a phi instruction"
in
let phi_instructions, non_phi_instructions =
BatList.span is_phi block.instructions
in
let phi_instructions = List.map unwrap_phi phi_instructions in
if List.exists is_phi non_phi_instructions then
failwith "Phi instructions are not at the beginning of the block";
(phi_instructions, non_phi_instructions)