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
open Utils
open Prog
type keep = { vars : Sv.t; funs : Sf.t }
let with_var k x = { k with vars = Sv.add x k.vars }
let with_fun k f = { k with funs = Sf.add f k.funs }
let inspect_gvar k { gs; gv } =
match gs with Slocal -> k | Sglob -> with_var k (L.unloc gv)
let rec inspect_e k = function
| Pconst _ | Pbool _ | Parr_init _ -> k
| Pvar x -> inspect_gvar k x
| Pget (_, _, _, x, e) | Psub (_, _, _, x, e) -> inspect_gvar (inspect_e k e) x
| Pload (_, _, e) | Papp1 (_, e) -> inspect_e k e
| Papp2 (_, e1, e2) -> inspect_e (inspect_e k e1) e2
| PappN (_, es) -> inspect_es k es
| Pif (_, e1, e2, e3) -> inspect_e (inspect_e (inspect_e k e1) e2) e3
and inspect_es k es = List.fold_left inspect_e k es
let inspect_lv k = function
| Lnone _ | Lvar _ -> k
| Lmem (_, _, _, e) | Laset (_, _, _, _, e) | Lasub (_, _, _, _, e) -> inspect_e k e
let inspect_lvs k xs = List.fold_left inspect_lv k xs
let rec inspect_stmt k stmt = List.fold_left inspect_instr k stmt
and inspect_instr k i = inspect_instr_r k i.i_desc
and inspect_instr_r k = function
| Cassgn (x, _, _, e) -> inspect_lv (inspect_e k e) x
| Copn (xs, _, _, es) | Csyscall (xs, _, es) ->
inspect_lvs (inspect_es k es) xs
| Cif (g, a, b) | Cwhile (_, a, g, _, b) ->
inspect_stmt (inspect_stmt (inspect_e k g) a) b
| Cfor (_, (_, e1, e2), s) -> inspect_stmt (inspect_es k [ e1; e2 ]) s
| Ccall (xs, fn, es) -> with_fun (inspect_lvs (inspect_es k es) xs) fn
let slice fs (gd, fds) =
let funs =
List.fold_left
(fun s n ->
match List.find (fun fd -> String.equal n fd.f_name.fn_name) fds with
| exception Not_found ->
warning Always L.i_dummy "slicing: function ā%sā not found" n;
s
| fd -> Sf.add fd.f_name s)
Sf.empty fs
in
let k =
List.fold_left
(fun k fd ->
if Sf.mem fd.f_name k.funs then inspect_stmt k fd.f_body else k)
{ vars = Sv.empty; funs } fds
in
let gd = List.filter (fun (x, _) -> Sv.mem x k.vars) gd in
let fds = List.filter (fun fd -> Sf.mem fd.f_name k.funs) fds in
let fds =
List.map
(fun fd ->
if List.mem fd.f_name.fn_name fs || not (FInfo.is_export fd.f_cc) then
fd
else { fd with f_cc = Internal })
fds
in
(gd, fds)