Source file zero_alloc_utils.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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
module type WS = sig
type t
val empty : t
val join : t -> t -> t
val meet : t -> t -> t
val lessequal : t -> t -> bool
val print : Format.formatter -> t -> unit
val compare : t -> t -> int
end
module type Component = sig
type t
type witnesses
val top : witnesses -> t
val safe : t
val bot : t
val lessequal : t -> t -> bool
val join : t -> t -> t
val meet : t -> t -> t
val compare : t -> t -> int
val print : witnesses:bool -> Format.formatter -> t -> unit
end
module Make_component (Witnesses : WS) = struct
type t =
| Top of Witnesses.t
| Safe
| Bot
let bot = Bot
let top w = Top w
let safe = Safe
let join c1 c2 =
match c1, c2 with
| Bot, Bot -> Bot
| Safe, Safe -> Safe
| Top w1, Top w2 -> Top (Witnesses.join w1 w2)
| Safe, Bot | Bot, Safe -> Safe
| Top w1, Bot | Top w1, Safe | Bot, Top w1 | Safe, Top w1 -> Top w1
let meet c1 c2 =
match c1, c2 with
| Bot, Bot -> Bot
| Safe, Safe -> Safe
| Top w1, Top w2 -> Top (Witnesses.meet w1 w2)
| Safe, Bot | Bot, Safe -> Bot
| Top _, Bot | Bot, Top _ -> Bot
| Top _, Safe | Safe, Top _ -> Safe
let lessequal v1 v2 =
match v1, v2 with
| Bot, Bot -> true
| Safe, Safe -> true
| Top w1, Top w2 -> Witnesses.lessequal w1 w2
| Bot, Safe -> true
| Bot, Top _ -> true
| Safe, Top _ -> true
| Top _, (Bot | Safe) -> false
| Safe, Bot -> false
let compare t1 t2 =
match t1, t2 with
| Bot, Bot -> 0
| Safe, Safe -> 0
| Top w1, Top w2 -> Witnesses.compare w1 w2
| Bot, (Safe | Top _) -> -1
| (Safe | Top _), Bot -> 1
| Safe, Top _ -> -1
| Top _, Safe -> 1
let print ~witnesses ppf = function
| Bot -> Format.fprintf ppf "bot"
| Top w ->
Format.fprintf ppf "top";
if witnesses then Format.fprintf ppf " (%a)" Witnesses.print w
| Safe -> Format.fprintf ppf "safe"
end
module Make_value
(Witnesses : WS)
(V : Component with type witnesses := Witnesses.t) =
struct
(** Lifts V to triples *)
type t =
{ nor : V.t;
exn : V.t;
div : V.t
}
let bot = { nor = V.bot; exn = V.bot; div = V.bot }
let lessequal v1 v2 =
V.lessequal v1.nor v2.nor && V.lessequal v1.exn v2.exn
&& V.lessequal v1.div v2.div
let join v1 v2 =
{ nor = V.join v1.nor v2.nor;
exn = V.join v1.exn v2.exn;
div = V.join v1.div v2.div
}
let meet v1 v2 =
{ nor = V.meet v1.nor v2.nor;
exn = V.meet v1.exn v2.exn;
div = V.meet v1.div v2.div
}
let normal_return = { bot with nor = V.safe }
let exn_escape = { bot with exn = V.safe }
let diverges = { bot with div = V.safe }
let safe = { nor = V.safe; exn = V.safe; div = V.safe }
let top w = { nor = V.top w; exn = V.top w; div = V.top w }
let relaxed w = { nor = V.safe; exn = V.top w; div = V.top w }
let of_annotation ~strict ~never_returns_normally ~never_raises =
let res = if strict then safe else relaxed Witnesses.empty in
let res = if never_raises then { res with exn = V.bot } else res in
if never_returns_normally then { res with nor = V.bot } else res
let print ~witnesses ppf { nor; exn; div } =
let pp = V.print ~witnesses in
Format.fprintf ppf "{ nor=%a;@ exn=%a;@ div=%a }@," pp nor pp exn pp div
let compare { nor = n1; exn = e1; div = d1 } { nor = n2; exn = e2; div = d2 }
=
let c = V.compare n1 n2 in
if c <> 0
then c
else
let c = V.compare e1 e2 in
if c <> 0 then c else V.compare d1 d2
end
module Assume_info = struct
module Witnesses = struct
type t = unit
let join _ _ = ()
let lessequal _ _ = true
let meet _ _ = ()
let print _ _ = ()
let empty = ()
let compare _ _ = 0
end
module V = Make_component (Witnesses)
module Value = Make_value (Witnesses) (V)
type t =
| No_assume
| Assume of Value.t
| Assume_inferred of Value.t
let compare t1 t2 =
match t1, t2 with
| No_assume, No_assume -> 0
| Assume v1, Assume v2 -> Value.compare v1 v2
| Assume_inferred v1, Assume_inferred v2 -> Value.compare v1 v2
| No_assume, (Assume _ | Assume_inferred _) -> -1
| Assume_inferred _, Assume _ -> -1
| Assume _, Assume_inferred _ -> 1
| (Assume _ | Assume_inferred _), No_assume -> 1
let equal t1 t2 = compare t1 t2 = 0
let print ppf = function
| No_assume -> ()
| Assume v -> Format.fprintf ppf "%a" (Value.print ~witnesses:false) v
| Assume_inferred v ->
Format.fprintf ppf "(inferred)%a" (Value.print ~witnesses:false) v
let to_string v = Format.asprintf "%a" print v
let join t1 t2 =
match t1, t2 with
| No_assume, No_assume -> No_assume
| No_assume, (Assume _ | Assume_inferred _)
| (Assume _ | Assume_inferred _), No_assume ->
No_assume
| Assume t1, Assume t2 -> Assume (Value.join t1 t2)
| Assume_inferred t1, Assume_inferred t2 ->
Assume_inferred (Value.join t1 t2)
| Assume t1, Assume_inferred t2 | Assume_inferred t1, Assume t2 ->
Assume_inferred (Value.join t1 t2)
let meet t1 t2 =
match t1, t2 with
| No_assume, No_assume -> No_assume
| No_assume, (Assume _ as t) | (Assume _ as t), No_assume -> t
| No_assume, (Assume_inferred _ as t) | (Assume_inferred _ as t), No_assume
->
t
| Assume t1, Assume t2 -> Assume (Value.meet t1 t2)
| Assume_inferred t1, Assume_inferred t2 ->
Assume_inferred (Value.meet t1 t2)
| Assume t1, Assume_inferred t2 -> Assume (Value.meet t1 t2)
| Assume_inferred t1, Assume t2 -> Assume (Value.meet t1 t2)
let none = No_assume
let create ~strict ~never_returns_normally ~never_raises ~inferred =
let v = Value.of_annotation ~strict ~never_returns_normally ~never_raises in
match inferred with false -> Assume v | true -> Assume_inferred v
let get_value t =
match t with No_assume -> None | Assume v | Assume_inferred v -> Some v
let is_none t =
match t with No_assume -> true | Assume _ | Assume_inferred _ -> false
let is_inferred t =
match t with Assume_inferred _ -> true | Assume _ | No_assume -> false
end