-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathsolvingPolicy.ml
487 lines (458 loc) · 14.5 KB
/
solvingPolicy.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
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
(** Solving the equations *)
(* This file is part of the Interproc analyzer, released under GPL license.
Please read the COPYING file packaged in the distribution.
Copyright (C) Mathias Argoud, Gaël Lalire, Bertrand Jeannet 2007.
*)
open Format
type 'a policy = 'a Apron.Policy.t Boolexpr.t
let policy_equal pmanager p1 p2 =
Boolexpr.fold2
(fun res p1 p2 -> res && (Apron.Policy.equal pmanager p1 p2))
true p1 p2
let policy_print pman fmt p =
Boolexpr.print (fun fmt p -> Apron.Policy.fdump pman p) fmt p
let hash_policy_print pman fmt p =
Hashhe.iter
(begin fun hedge policy ->
fprintf fmt "hedge %i:@.%a" hedge
(policy_print pman) policy
end)
p;
fprintf fmt "policy end@."
(* ********************************************************************* *)
(** {2 Instanciated module and options} *)
(* ********************************************************************* *)
(* ===================================================================== *)
(** {3 Functions} *)
(* ===================================================================== *)
(** Build a fixpoint manager (for module [Fixpoint]) given:
- an equation graph (forward or backward)
- optionally, the result of a previous, dual analysis
- a function [apply graph output manager hyperedge tabstract]
- a function [abstract_init]
- an APRON manager;
- a debug level
*)
let make_fpmanager
~(fmt : Format.formatter)
~(output : (Spl_syn.point, int, 'a Apron.Abstract1.t, unit) Fixpoint.output option ref)
~(debug:int)
~(graph: Equation.graph)
~(policy:(Equation.hedge, 'a policy) Hashhe.t ref)
~(pman:'abstract Apron.Policy.man)
~(abstract_init : Spl_syn.point -> 'a Apron.Abstract1.t)
~(apply :
Equation.graph ->
output:(Spl_syn.point, int, 'a Apron.Abstract1.t, unit) Fixpoint.output option ref ->
policy:(Equation.hedge, 'a policy) Hashhe.t ref ->
'a Apron.Policy.man ->
Equation.hedge ->
'a Apron.Abstract1.t array -> unit * 'a Apron.Abstract1.t)
:
(Spl_syn.point, int, 'a Apron.Abstract1.t, unit) Fixpoint.manager
=
let man = Apron.Policy.manager_get_manager pman in
{
begin
Solving.make_fpmanager ~fmt ~output:None ~debug ~graph
~man
~abstract_init ~apply:(fun _ -> failwith "")
end
with
(* Interpreting hyperedges *)
Fixpoint.apply = begin fun hedge tx ->
apply graph ~output ~policy pman hedge tx
end;
}
(** Make an output graph filled with bottom abstract values *)
let make_emptyoutput = Solving.make_emptyoutput
let environment_of_tvar = Solving.environment_of_tvar
let make_policy pmanager graph rooutput =
let manager = Apron.Policy.manager_get_manager pmanager in
let info = PSHGraph.info graph in
let policy = Hashhe.create 31 in
PSHGraph.iter_hedge graph
(begin fun hedge transfer ~pred ~succ ->
begin match transfer with
| Equation.Condition cond ->
let env = Hashhe.find info.Equation.pointenv pred.(0) in
let abs = match !rooutput with
| None ->
Apron.Abstract1.top manager env
| Some(output) ->
PSHGraph.attrvertex output pred.(0)
in
let p =
Boolexpr.map
(fun conj ->
Apron.Policy.Abstract1.meet_tcons_array_improve
pmanager None abs conj)
cond
in
Hashhe.add policy hedge p;
| _ -> ()
end
end)
;
ref policy
let apply_condition
(pmanager:'a Apron.Policy.man)
(bpolicy:'a Apron.Policy.t Boolexpr.t)
(abstract:'a Apron.Abstract1.t)
(expr:Apron.Tcons1.earray Boolexpr.t)
(dest:'a Apron.Abstract1.t option)
:
'a Apron.Abstract1.t
=
let dabstract =
Boolexpr.map2
(fun policy conj ->
Apron.Policy.Abstract1.meet_tcons_array_apply
pmanager policy abstract conj)
bpolicy expr
in
let labstract = match dabstract with
| Boolexpr.TRUE -> [abstract]
| Boolexpr.DISJ l -> l
in
let manager = Apron.Policy.manager_get_manager pmanager in
let labstract =
match dest with
| None -> labstract
| Some dest ->
List.map
(fun abstract -> Apron.Abstract1.meet manager abstract dest)
labstract
in
match labstract with
| [] ->
Apron.Abstract1.bottom manager (Apron.Abstract1.env abstract)
| [x] -> x
| _ -> Apron.Abstract1.join_array manager (Array.of_list labstract)
let improve_condition
(pmanager:'a Apron.Policy.man)
(obpolicy:'a Apron.Policy.t Boolexpr.t option)
(abstract:'a Apron.Abstract1.t)
(expr:Apron.Tcons1.earray Boolexpr.t)
(dest:'a Apron.Abstract1.t option)
:
'a Apron.Policy.t Boolexpr.t
=
match obpolicy with
| None ->
Boolexpr.map
(fun conj ->
Apron.Policy.Abstract1.meet_tcons_array_improve
pmanager None abstract conj)
expr
| Some bpolicy ->
Boolexpr.map2
(fun policy conj ->
Apron.Policy.Abstract1.meet_tcons_array_improve
pmanager (Some policy) abstract conj)
bpolicy expr
(* ********************************************************************** *)
(** {2 Forward semantics} *)
(* ********************************************************************** *)
module Forward = struct
(* ===================================================================== *)
(** {3 Transfer function} *)
(* ===================================================================== *)
(** Main transfer function *)
let apply
(graph:Equation.graph)
~(output : (Spl_syn.point, int, 'a Apron.Abstract1.t, unit) Fixpoint.output option ref)
~(policy:(Equation.hedge, 'a policy) Hashhe.t ref)
(pmanager:'a Apron.Policy.man)
(hedge:int)
(tabs:'a Apron.Abstract1.t array)
:
unit * 'a Apron.Abstract1.t
=
let transfer = PSHGraph.attrhedge graph hedge in
let abs = tabs.(0) in
let dest = match !output with
| None -> None
| Some(output) ->
let tdest = PSHGraph.succvertex graph hedge in
assert(Array.length tdest = 1);
let dest = PSHGraph.attrvertex output tdest.(0) in
Some dest
in
let manager = Apron.Policy.manager_get_manager pmanager in
let res =
match transfer with
| Equation.Tassign(var,expr) ->
Solving.Forward.apply_tassign manager abs var expr dest
| Equation.Lassign _ ->
failwith ""
| Equation.Condition cond ->
let policy = Hashhe.find !policy hedge in
apply_condition pmanager policy abs cond dest
| Equation.Call(callerinfo,calleeinfo,tin,tout) ->
Solving.Forward.apply_call manager abs calleeinfo tin dest
| Equation.Return(callerinfo,calleeinfo,tin,tout) ->
Solving.Forward.apply_return manager abs tabs.(1) calleeinfo tin tout dest
in
((),res)
(* ===================================================================== *)
(** {3 Compute (post)fixpoint} *)
(* ===================================================================== *)
let compute
~(fmt : Format.formatter)
(prog:Spl_syn.program)
(graph:Equation.graph)
~(output : (Spl_syn.point, int, 'a Apron.Abstract1.t, unit) Fixpoint.output option)
(pmanager:'a Apron.Policy.man)
~(debug:int)
:
(Spl_syn.point, int, 'a Apron.Abstract1.t, unit) Fixpoint.output
=
let manager = Apron.Policy.manager_get_manager pmanager in
let info = PSHGraph.info graph in
let output = ref output in
let sstart =
let maininfo = Hashhe.find info.Equation.procinfo "" in
let start = maininfo.Equation.pstart in
begin match !output with
| None ->
PSette.singleton Equation.compare_point start
| Some output ->
let abstract = PSHGraph.attrvertex output start in
if Apron.Abstract1.is_bottom manager abstract then
PSette.empty Equation.compare_point
else
(PSette.singleton Equation.compare_point start)
end
in
if PSette.is_empty sstart then begin
make_emptyoutput graph manager
end
else begin
let abstract_init = begin fun vertex ->
begin match !output with
| None ->
Apron.Abstract1.top manager (Hashhe.find info.Equation.pointenv vertex)
| Some(output) ->
PSHGraph.attrvertex output vertex
end
end
in
let policy = make_policy pmanager graph output in
let fpmanager =
make_fpmanager ~fmt ~output ~debug ~graph
~policy
~pman:pmanager
~abstract_init ~apply
in
let result = ref None in
let loop = ref true in
while !loop do
let fp =
if !Option.iteration_guided then
Fixpoint.analysis_guided
fpmanager graph sstart
(fun filter ->
Fixpoint.make_strategy_default
~vertex_dummy:Equation.vertex_dummy
~hedge_dummy:Equation.hedge_dummy
~priority:(PSHGraph.Filter filter)
graph sstart)
else
Fixpoint.analysis_std
fpmanager graph sstart
(Fixpoint.make_strategy_default
~vertex_dummy:Equation.vertex_dummy
~hedge_dummy:Equation.hedge_dummy
graph sstart)
in
result := Some fp;
(* Display *)
if !Option.debug>0 then begin
printf "policy=%a" (hash_policy_print pmanager) !policy;
Solving.print_output prog fmt fp;
end;
(* Now try to modify the policy *)
loop := false;
policy :=
Hashhe.map
(begin fun hedge oldpolicy ->
let predvertex = (PSHGraph.predvertex graph hedge).(0) in
let abs = PSHGraph.attrvertex fp predvertex in
let transfer = PSHGraph.attrhedge graph hedge in
let policy =
begin match transfer with
| Equation.Condition cond ->
improve_condition pmanager (Some oldpolicy) abs cond None
| _ -> failwith ""
end
in
loop := !loop || (not (policy_equal pmanager oldpolicy policy));
policy
end)
!policy
;
(* In the next iteration, intersect with the previous one *)
output := !result;
done;
begin match !result with
| Some x -> x
| None -> failwith ""
end
end
end
(* ********************************************************************** *)
(** {2 Bacward semantics} *)
(* ********************************************************************** *)
module Backward = struct
(* ===================================================================== *)
(** {3 Transfer function} *)
(* ===================================================================== *)
(** Main transfer function *)
let apply
(graph:Equation.graph)
~(output : (Spl_syn.point, int, 'a Apron.Abstract1.t, unit) Fixpoint.output option ref)
~(policy:(Equation.hedge, 'a policy) Hashhe.t ref)
(pmanager:'a Apron.Policy.man)
(hedge:int)
(tabs:'a Apron.Abstract1.t array)
:
unit * 'a Apron.Abstract1.t
=
let manager = Apron.Policy.manager_get_manager pmanager in
let transfer = PSHGraph.attrhedge graph hedge in
let abs = tabs.(0) in
let dest = match !output with
| None -> None
| Some(output) ->
let tdest = PSHGraph.succvertex graph hedge in
assert(Array.length tdest = 1);
let dest = PSHGraph.attrvertex output tdest.(0) in
Some dest
in
let res =
match transfer with
| Equation.Tassign(var,expr) ->
Solving.Backward.apply_tassign manager abs var expr dest
| Equation.Lassign _ ->
failwith ""
| Equation.Condition cond ->
let policy = Hashhe.find !policy hedge in
apply_condition pmanager policy abs cond dest
| Equation.Call(callerinfo,calleeinfo,tin,tout) ->
Solving.Backward.apply_call manager abs callerinfo calleeinfo tin dest
| Equation.Return(callerinfo,calleeinfo,tin,tout) ->
Solving.Backward.apply_return manager abs callerinfo calleeinfo tin tout dest
in
((),res)
(* ===================================================================== *)
(** {3 Compute (post)fixpoint} *)
(* ===================================================================== *)
let compute
~(fmt : Format.formatter)
(prog:Spl_syn.program)
(graph:Equation.graph)
~(output : (Spl_syn.point, int, 'a Apron.Abstract1.t, unit) Fixpoint.output option)
(pmanager:'a Apron.Policy.man)
~(debug:int)
:
(Spl_syn.point, int, 'a Apron.Abstract1.t, unit) Fixpoint.output
=
let manager = Apron.Policy.manager_get_manager pmanager in
let info = PSHGraph.info graph in
let output = ref output in
let sstart = ref (PSette.empty Equation.compare_point) in
List.iter
(begin fun procedure ->
Spl_syn.iter_eltinstr
(begin fun (bpoint,instr) ->
if instr.Spl_syn.instruction = Spl_syn.FAIL then begin
let ok = match !output with
| None -> true
| Some output ->
let abstract = PSHGraph.attrvertex output bpoint in
not (Apron.Abstract1.is_bottom manager abstract)
in
if ok then
sstart := PSette.add bpoint !sstart;
end
end)
procedure.Spl_syn.pcode;
end)
prog.Spl_syn.procedures;
if PSette.is_empty !sstart then begin
make_emptyoutput graph manager
end
else begin
let abstract_init = begin fun vertex ->
begin match !output with
| None ->
Apron.Abstract1.top manager (Hashhe.find info.Equation.pointenv vertex)
| Some(output) ->
PSHGraph.attrvertex output vertex
end
end
in
let policy = make_policy pmanager graph output in
let fpmanager =
make_fpmanager ~fmt ~output ~debug ~graph
~policy
~pman:pmanager
~abstract_init ~apply
in
let result = ref None in
let loop = ref true in
while !loop do
let fp =
if !Option.iteration_guided then
Fixpoint.analysis_guided
fpmanager graph !sstart
(fun filter ->
Fixpoint.make_strategy_default
~vertex_dummy:Equation.vertex_dummy
~hedge_dummy:Equation.hedge_dummy
~priority:(PSHGraph.Filter filter)
graph !sstart)
else
Fixpoint.analysis_std
fpmanager graph !sstart
(Fixpoint.make_strategy_default
~vertex_dummy:Equation.vertex_dummy
~hedge_dummy:Equation.hedge_dummy
graph !sstart)
in
result := Some fp;
(* Display *)
if !Option.debug >0 then begin
printf "policy=%a" (hash_policy_print pmanager) !policy;
Solving.print_output prog fmt fp;
end;
(* Now try to modify the policy *)
loop := false;
policy :=
Hashhe.map
(begin fun hedge oldpolicy ->
let predvertex = (PSHGraph.predvertex graph hedge).(0) in
let abs = PSHGraph.attrvertex fp predvertex in
let transfer = PSHGraph.attrhedge graph hedge in
let policy =
begin match transfer with
| Equation.Condition cond ->
improve_condition pmanager (Some oldpolicy) abs cond None
| _ -> failwith ""
end
in
loop := !loop || (not (policy_equal pmanager oldpolicy policy));
policy
end)
!policy
;
(* In the next iteration, intersect with the previous one *)
output := !result;
done;
begin match !result with
| Some x -> x
| None -> failwith ""
end
end
end