-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathannotators.ml
More file actions
186 lines (160 loc) · 6.55 KB
/
Copy pathannotators.ml
File metadata and controls
186 lines (160 loc) · 6.55 KB
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
(**************************************************************************)
(* *)
(* This file is part of the Frama-C's Lannotate plug-in. *)
(* *)
(* Copyright (C) 2012-2022 *)
(* CEA (Commissariat à l'énergie atomique et aux énergies *)
(* alternatives) *)
(* *)
(* you can redistribute it and/or modify it under the terms of the GNU *)
(* Lesser General Public License as published by the Free Software *)
(* Foundation, version 2.1. *)
(* *)
(* It is distributed in the hope that it will be useful, *)
(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)
(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)
(* GNU Lesser General Public License for more details. *)
(* *)
(* See the GNU Lesser General Public License version 2.1 *)
(* for more details (enclosed in the file LICENSE) *)
(* *)
(**************************************************************************)
open Cil_types
let filen = ref ""
let get_file_name () = !filen
type annotation =
int * string * exp * location
type annotator = {
name:string;
help: string;
apply: (unit -> int) -> (annotation -> unit) -> Cil_types.file -> unit;
}
module type ANNOTATOR = sig
val name : string
val help : string
val apply : (Cil_types.exp -> Cil_types.exp list -> Cil_types.location -> Cil_types.stmt) -> Cil_types.file -> unit
end
module type ANNOTATOR_WITH_EXTRA_TAGS = sig
val name : string
val help : string
val apply : (extra:string list -> Cil_types.exp -> Cil_types.exp list -> Cil_types.location -> Cil_types.stmt) -> Cil_types.file -> unit
end
module type S = sig
val self : annotator
val apply : ?id:(unit -> int) -> ?collect:(annotation -> unit) -> Cil_types.file -> unit
end
let annotators = Hashtbl.create 10
let nextId = ref 1
let nextBindingId = ref 1
let nextIdHl = ref 1
let getCurrentLabelId () = !nextId - 1
let getCurrentBindingId () = !nextBindingId - 1
let getCurrentHLId () = !nextIdHl - 1
let next () =
let id = !nextId in
incr nextId;
id
let next_binding () =
let id = !nextBindingId in
incr nextBindingId;
id
let next_hl () =
let id = !nextIdHl in
incr nextIdHl;
string_of_int id
let nocollect _ = ()
let () =
Cil_builtins.add_special_builtin "pc_label";
Cil_builtins.add_special_builtin "pc_label_bindings";
Cil_builtins.add_special_builtin "mutated"
let pc_label = ref None
let pc_label_bindings = ref None
let mutated = ref None
let label_function_vinfo = ref None
let init_builtins () =
pc_label := Some (Cil.makeGlobalVar "pc_label" (TFun(Cil.voidType, None, false, [])));
pc_label_bindings := Some (Cil.makeGlobalVar "pc_label_bindings" (TFun(Cil.voidType, None, false, [])));
mutated := Some (Cil.makeGlobalVar "mutated" (TFun(Cil.intType, None, false, [])));
label_function_vinfo := !pc_label
let annotate_with annotator ?(id=next) ?(collect=nocollect) ast =
Options.feedback "apply annotations for %s@." annotator.name;
annotator.apply id collect ast
let annotate filename names ?(id=next) ?(collect=nocollect) ast =
filen := filename;
let f name =
try
let ann = Hashtbl.find annotators name in
annotate_with ~id ~collect ann ast
with Not_found -> Options.warning "unknown annotators `%s`" name
in
List.iter f names;
if Options.Visibility.get () then Visibility.to_visibility ast !pc_label
let print_help fmt =
let annotators = Hashtbl.fold (fun _k v acc -> v :: acc) annotators [] in
let annotators = List.sort (fun a b -> compare a.name b.name) annotators in
let width = List.fold_left (fun acc ann -> max (String.length ann.name) acc) 0 annotators in
let f ann = Format.fprintf fmt "%-*s @[%s@]@." width ann.name ann.help in
List.iter f annotators
let mk_label id collect tag cond mvars loc =
let id = id () in
let cond =
if Options.Simplify.get () then
Simplify.simplify_exp cond
else
cond
in
let tag =
if (Option.get !label_function_vinfo).vname = "pc_label" &&
Options.Visibility.get ()
then "V_"^tag
else tag
in
collect (id,tag,cond,loc);
let tagExp = Ast_const.Exp_builder.mk (Const (CStr tag)) in
let idExp = Ast_const.Exp_builder.integer id in
Utils.mk_call !label_function_vinfo (List.concat [ [ cond; idExp; tagExp ] ; mvars])
let mk_apply apply name id collect ast =
apply (mk_label id collect name) ast;
Ast.mark_as_changed ()
let mk_compute_extras apply name id collect ast =
let mk_label' ~extra cond loc=
let tag = String.concat " " (name :: extra) in
mk_label id collect tag cond loc
in
apply mk_label' ast
let register_annotator ann =
Options.debug "register %s annotator" ann.name;
Hashtbl.replace annotators ann.name ann
module Register (A : ANNOTATOR) = struct
let self = { name = A.name; help = A.help; apply = mk_apply A.apply A.name }
let apply = annotate_with self
let () = register_annotator self
end
module RegisterWithExtraTags (A : ANNOTATOR_WITH_EXTRA_TAGS) = struct
let self = { name = A.name; help = A.help; apply = mk_compute_extras A.apply A.name }
let apply = annotate_with self
let () = register_annotator self
end
let shouldInstrumentFun fun_varinfo =
let do_names = Options.DoFunctionNames.get () in
let skip_names = Options.SkipFunctionNames.get () in
let f (kf : Cil_datatype.Kf.Set.elt ) =
(Cil_datatype.Kf.vi kf).vname = fun_varinfo.vname
in
not (Cil_datatype.Kf.Set.exists f skip_names) &&
(* TODO filter builtin functions *)
if Cil_datatype.Kf.Set.is_empty do_names then
not (fun_varinfo.vinline) || Options.Inline.get ()
else
Cil_datatype.Kf.Set.exists f do_names
let shouldInstrumentVar varinfo =
let do_names = Options.DoVariableNames.get () in
let skip_names = Options.SkipVariableNames.get () in
let f (vname : Datatype.String.Set.elt ) =
vname = varinfo.vname
in
not (Datatype.String.Set.exists f skip_names) &&
(* TODO filter builtin functions *)
if not (Datatype.String.Set.is_empty do_names) then
Datatype.String.Set.exists f do_names
else true