Skip to content

Commit 8ac5fad

Browse files
committed
Extract analysis results from Analyses module
1 parent 3f4a6bc commit 8ac5fad

File tree

4 files changed

+194
-188
lines changed

4 files changed

+194
-188
lines changed

src/framework/analyses.ml

Lines changed: 0 additions & 186 deletions
Original file line numberDiff line numberDiff line change
@@ -162,183 +162,6 @@ struct
162162
end
163163

164164

165-
module ResultNode: Printable.S with type t = MyCFG.node =
166-
struct
167-
include Printable.Std
168-
169-
include Node
170-
171-
let name () = "resultnode"
172-
173-
let show a =
174-
(* Not using Node.location here to have updated locations in incremental analysis.
175-
See: https://github.com/goblint/analyzer/issues/290#issuecomment-881258091. *)
176-
let x = UpdateCil.getLoc a in
177-
let f = Node.find_fundec a in
178-
CilType.Location.show x ^ "(" ^ f.svar.vname ^ ")"
179-
180-
include Printable.SimpleShow (
181-
struct
182-
type nonrec t = t
183-
let show = show
184-
end
185-
)
186-
end
187-
188-
module type ResultConf =
189-
sig
190-
val result_name: string
191-
end
192-
193-
module Result (Range: Printable.S) (C: ResultConf) =
194-
struct
195-
include Hashtbl.Make (ResultNode)
196-
type nonrec t = Range.t t (* specialize polymorphic type for Range values *)
197-
198-
let pretty () mapping =
199-
let f key st dok =
200-
dok ++ dprintf "%a ->@? @[%a@]\n" ResultNode.pretty key Range.pretty st
201-
in
202-
let content () = fold f mapping nil in
203-
let defline () = dprintf "OTHERS -> Not available\n" in
204-
dprintf "@[Mapping {\n @[%t%t@]}@]" content defline
205-
206-
include C
207-
208-
let printXml f xs =
209-
let print_one n v =
210-
(* Not using Node.location here to have updated locations in incremental analysis.
211-
See: https://github.com/goblint/analyzer/issues/290#issuecomment-881258091. *)
212-
let loc = UpdateCil.getLoc n in
213-
BatPrintf.fprintf f "<call id=\"%s\" file=\"%s\" line=\"%d\" order=\"%d\" column=\"%d\">\n" (Node.show_id n) loc.file loc.line loc.byte loc.column;
214-
BatPrintf.fprintf f "%a</call>\n" Range.printXml v
215-
in
216-
iter print_one xs
217-
218-
let printJson f xs =
219-
let print_one n v =
220-
(* Not using Node.location here to have updated locations in incremental analysis.
221-
See: https://github.com/goblint/analyzer/issues/290#issuecomment-881258091. *)
222-
let loc = UpdateCil.getLoc n in
223-
BatPrintf.fprintf f "{\n\"id\": \"%s\", \"file\": \"%s\", \"line\": \"%d\", \"byte\": \"%d\", \"column\": \"%d\", \"states\": %s\n},\n" (Node.show_id n) loc.file loc.line loc.byte loc.column (Yojson.Safe.to_string (Range.to_yojson v))
224-
in
225-
iter print_one xs
226-
227-
let printXmlWarning f () =
228-
let one_text f Messages.Piece.{loc; text = m; _} =
229-
match loc with
230-
| Some loc ->
231-
let l = Messages.Location.to_cil loc in
232-
BatPrintf.fprintf f "\n<text file=\"%s\" line=\"%d\" column=\"%d\">%s</text>" l.file l.line l.column (XmlUtil.escape m)
233-
| None ->
234-
() (* TODO: not outputting warning without location *)
235-
in
236-
let one_w f (m: Messages.Message.t) = match m.multipiece with
237-
| Single piece -> one_text f piece
238-
| Group {group_text = n; pieces = e; group_loc} ->
239-
let group_loc_text = match group_loc with
240-
| None -> ""
241-
| Some group_loc -> GobPretty.sprintf " (%a)" CilType.Location.pretty (Messages.Location.to_cil group_loc)
242-
in
243-
BatPrintf.fprintf f "<group name=\"%s%s\">%a</group>\n" n group_loc_text (BatList.print ~first:"" ~last:"" ~sep:"" one_text) e
244-
in
245-
let one_w f x = BatPrintf.fprintf f "\n<warning>%a</warning>" one_w x in
246-
List.iter (one_w f) !Messages.Table.messages_list
247-
248-
let output table gtable gtfxml (file: file) =
249-
let out = Messages.get_out result_name !Messages.out in
250-
match get_string "result" with
251-
| "pretty" -> ignore (fprintf out "%a\n" pretty (Lazy.force table))
252-
| "fast_xml" ->
253-
let module SH = BatHashtbl.Make (Basetype.RawStrings) in
254-
let file2funs = SH.create 100 in
255-
let funs2node = SH.create 100 in
256-
iter (fun n _ -> SH.add funs2node (Node.find_fundec n).svar.vname n) (Lazy.force table);
257-
iterGlobals file (function
258-
| GFun (fd,loc) -> SH.add file2funs loc.file fd.svar.vname
259-
| _ -> ()
260-
);
261-
let p_node f n = BatPrintf.fprintf f "%s" (Node.show_id n) in
262-
let p_nodes f xs =
263-
List.iter (BatPrintf.fprintf f "<node name=\"%a\"/>\n" p_node) xs
264-
in
265-
let p_funs f xs =
266-
let one_fun n =
267-
BatPrintf.fprintf f "<function name=\"%s\">\n%a</function>\n" n p_nodes (SH.find_all funs2node n)
268-
in
269-
List.iter one_fun xs
270-
in
271-
let write_file f fn =
272-
Messages.xml_file_name := fn;
273-
BatPrintf.printf "Writing xml to temp. file: %s\n%!" fn;
274-
BatPrintf.fprintf f "<run>";
275-
BatPrintf.fprintf f "<parameters>%s</parameters>" GobSys.command_line;
276-
BatPrintf.fprintf f "<statistics>";
277-
let timing_ppf = BatFormat.formatter_of_out_channel f in
278-
Timing.Default.print timing_ppf;
279-
Format.pp_print_flush timing_ppf ();
280-
BatPrintf.fprintf f "</statistics>";
281-
BatPrintf.fprintf f "<result>\n";
282-
BatEnum.iter (fun b -> BatPrintf.fprintf f "<file name=\"%s\" path=\"%s\">\n%a</file>\n" (Filename.basename b) b p_funs (SH.find_all file2funs b)) (BatEnum.uniq @@ SH.keys file2funs);
283-
BatPrintf.fprintf f "%a" printXml (Lazy.force table);
284-
gtfxml f gtable;
285-
printXmlWarning f ();
286-
BatPrintf.fprintf f "</result></run>\n";
287-
BatPrintf.fprintf f "%!"
288-
in
289-
if get_bool "g2html" then
290-
BatFile.with_temporary_out ~mode:[`create;`text;`delete_on_exit] write_file
291-
else
292-
let f = BatIO.output_channel out in
293-
write_file f (get_string "outfile")
294-
| "json" ->
295-
let open BatPrintf in
296-
let module SH = BatHashtbl.Make (Basetype.RawStrings) in
297-
let file2funs = SH.create 100 in
298-
let funs2node = SH.create 100 in
299-
iter (fun n _ -> SH.add funs2node (Node.find_fundec n).svar.vname n) (Lazy.force table);
300-
iterGlobals file (function
301-
| GFun (fd,loc) -> SH.add file2funs loc.file fd.svar.vname
302-
| _ -> ()
303-
);
304-
let p_enum p f xs = BatEnum.print ~first:"[\n " ~last:"\n]" ~sep:",\n " p f xs in
305-
let p_list p f xs = BatList.print ~first:"[\n " ~last:"\n]" ~sep:",\n " p f xs in
306-
(*let p_kv f (k,p,v) = fprintf f "\"%s\": %a" k p v in*)
307-
(*let p_obj f xs = BatList.print ~first:"{\n " ~last:"\n}" ~sep:",\n " p_kv xs in*)
308-
let p_node f n = BatPrintf.fprintf f "\"%s\"" (Node.show_id n) in
309-
let p_fun f x = fprintf f "{\n \"name\": \"%s\",\n \"nodes\": %a\n}" x (p_list p_node) (SH.find_all funs2node x) in
310-
(*let p_fun f x = p_obj f [ "name", BatString.print, x; "nodes", p_list p_node, SH.find_all funs2node x ] in*)
311-
let p_file f x = fprintf f "{\n \"name\": \"%s\",\n \"path\": \"%s\",\n \"functions\": %a\n}" (Filename.basename x) x (p_list p_fun) (SH.find_all file2funs x) in
312-
let write_file f fn =
313-
printf "Writing json to temp. file: %s\n%!" fn;
314-
fprintf f "{\n \"parameters\": \"%s\",\n " GobSys.command_line;
315-
fprintf f "\"files\": %a,\n " (p_enum p_file) (SH.keys file2funs);
316-
fprintf f "\"results\": [\n %a\n]\n" printJson (Lazy.force table);
317-
(*gtfxml f gtable;*)
318-
(*printXmlWarning f ();*)
319-
fprintf f "}\n";
320-
in
321-
if get_bool "g2html" then
322-
BatFile.with_temporary_out ~mode:[`create;`text;`delete_on_exit] write_file
323-
else
324-
let f = BatIO.output_channel out in
325-
write_file f (get_string "outfile")
326-
| "sarif" ->
327-
let open BatPrintf in
328-
printf "Writing Sarif to file: %s\n%!" (get_string "outfile");
329-
Yojson.Safe.to_channel ~std:true out (Sarif.to_yojson (List.rev !Messages.Table.messages_list));
330-
| "json-messages" ->
331-
let json = `Assoc [
332-
("files", Preprocessor.dependencies_to_yojson ());
333-
("messages", Messages.Table.to_yojson ());
334-
]
335-
in
336-
Yojson.Safe.to_channel ~std:true out json
337-
| "none" -> ()
338-
| s -> failwith @@ "Unsupported value for option `result`: "^s
339-
end
340-
341-
342165
(* Experiment to reduce the number of arguments on transfer functions and allow
343166
sub-analyses. The list sub contains the current local states of analyses in
344167
the same order as written in the dependencies list (in MCP).
@@ -598,15 +421,6 @@ module type GenericGlobSolver =
598421
val solve : (S.LVar.t*S.D.t) list -> (S.GVar.t*S.G.t) list -> S.LVar.t list -> marshal option -> (S.D.t LH.t * S.G.t GH.t) * marshal
599422
end
600423

601-
module ResultType2 (S:Spec) =
602-
struct
603-
open S
604-
include Printable.Prod3 (C) (D) (CilType.Fundec)
605-
let show (es,x,f:t) = D.show x
606-
let pretty () (_,x,_) = D.pretty () x
607-
let printXml f (c,d,fd) =
608-
BatPrintf.fprintf f "<context>\n%a</context>\n%a" C.printXml c D.printXml d
609-
end
610424

611425
module StdV =
612426
struct

src/framework/analysisResult.ml

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
(** Analysis result output. *)
2+
3+
open GoblintCil
4+
open Pretty
5+
open GobConfig
6+
7+
module ResultNode: Printable.S with type t = MyCFG.node =
8+
struct
9+
include Printable.Std
10+
11+
include Node
12+
13+
let name () = "resultnode"
14+
15+
let show a =
16+
(* Not using Node.location here to have updated locations in incremental analysis.
17+
See: https://github.com/goblint/analyzer/issues/290#issuecomment-881258091. *)
18+
let x = UpdateCil.getLoc a in
19+
let f = Node.find_fundec a in
20+
CilType.Location.show x ^ "(" ^ f.svar.vname ^ ")"
21+
22+
include Printable.SimpleShow (
23+
struct
24+
type nonrec t = t
25+
let show = show
26+
end
27+
)
28+
end
29+
30+
module type ResultConf =
31+
sig
32+
val result_name: string
33+
end
34+
35+
module Result (Range: Printable.S) (C: ResultConf) =
36+
struct
37+
include BatHashtbl.Make (ResultNode)
38+
type nonrec t = Range.t t (* specialize polymorphic type for Range values *)
39+
40+
let pretty () mapping =
41+
let f key st dok =
42+
dok ++ dprintf "%a ->@? @[%a@]\n" ResultNode.pretty key Range.pretty st
43+
in
44+
let content () = fold f mapping nil in
45+
let defline () = dprintf "OTHERS -> Not available\n" in
46+
dprintf "@[Mapping {\n @[%t%t@]}@]" content defline
47+
48+
include C
49+
50+
let printXml f xs =
51+
let print_one n v =
52+
(* Not using Node.location here to have updated locations in incremental analysis.
53+
See: https://github.com/goblint/analyzer/issues/290#issuecomment-881258091. *)
54+
let loc = UpdateCil.getLoc n in
55+
BatPrintf.fprintf f "<call id=\"%s\" file=\"%s\" line=\"%d\" order=\"%d\" column=\"%d\">\n" (Node.show_id n) loc.file loc.line loc.byte loc.column;
56+
BatPrintf.fprintf f "%a</call>\n" Range.printXml v
57+
in
58+
iter print_one xs
59+
60+
let printJson f xs =
61+
let print_one n v =
62+
(* Not using Node.location here to have updated locations in incremental analysis.
63+
See: https://github.com/goblint/analyzer/issues/290#issuecomment-881258091. *)
64+
let loc = UpdateCil.getLoc n in
65+
BatPrintf.fprintf f "{\n\"id\": \"%s\", \"file\": \"%s\", \"line\": \"%d\", \"byte\": \"%d\", \"column\": \"%d\", \"states\": %s\n},\n" (Node.show_id n) loc.file loc.line loc.byte loc.column (Yojson.Safe.to_string (Range.to_yojson v))
66+
in
67+
iter print_one xs
68+
69+
let printXmlWarning f () =
70+
let one_text f Messages.Piece.{loc; text = m; _} =
71+
match loc with
72+
| Some loc ->
73+
let l = Messages.Location.to_cil loc in
74+
BatPrintf.fprintf f "\n<text file=\"%s\" line=\"%d\" column=\"%d\">%s</text>" l.file l.line l.column (XmlUtil.escape m)
75+
| None ->
76+
() (* TODO: not outputting warning without location *)
77+
in
78+
let one_w f (m: Messages.Message.t) = match m.multipiece with
79+
| Single piece -> one_text f piece
80+
| Group {group_text = n; pieces = e; group_loc} ->
81+
let group_loc_text = match group_loc with
82+
| None -> ""
83+
| Some group_loc -> GobPretty.sprintf " (%a)" CilType.Location.pretty (Messages.Location.to_cil group_loc)
84+
in
85+
BatPrintf.fprintf f "<group name=\"%s%s\">%a</group>\n" n group_loc_text (BatList.print ~first:"" ~last:"" ~sep:"" one_text) e
86+
in
87+
let one_w f x = BatPrintf.fprintf f "\n<warning>%a</warning>" one_w x in
88+
List.iter (one_w f) !Messages.Table.messages_list
89+
90+
let output table gtable gtfxml (file: file) =
91+
let out = Messages.get_out result_name !Messages.out in
92+
match get_string "result" with
93+
| "pretty" -> ignore (fprintf out "%a\n" pretty (Lazy.force table))
94+
| "fast_xml" ->
95+
let module SH = BatHashtbl.Make (Basetype.RawStrings) in
96+
let file2funs = SH.create 100 in
97+
let funs2node = SH.create 100 in
98+
iter (fun n _ -> SH.add funs2node (Node.find_fundec n).svar.vname n) (Lazy.force table);
99+
iterGlobals file (function
100+
| GFun (fd,loc) -> SH.add file2funs loc.file fd.svar.vname
101+
| _ -> ()
102+
);
103+
let p_node f n = BatPrintf.fprintf f "%s" (Node.show_id n) in
104+
let p_nodes f xs =
105+
List.iter (BatPrintf.fprintf f "<node name=\"%a\"/>\n" p_node) xs
106+
in
107+
let p_funs f xs =
108+
let one_fun n =
109+
BatPrintf.fprintf f "<function name=\"%s\">\n%a</function>\n" n p_nodes (SH.find_all funs2node n)
110+
in
111+
List.iter one_fun xs
112+
in
113+
let write_file f fn =
114+
Messages.xml_file_name := fn;
115+
BatPrintf.printf "Writing xml to temp. file: %s\n%!" fn;
116+
BatPrintf.fprintf f "<run>";
117+
BatPrintf.fprintf f "<parameters>%s</parameters>" GobSys.command_line;
118+
BatPrintf.fprintf f "<statistics>";
119+
let timing_ppf = BatFormat.formatter_of_out_channel f in
120+
Timing.Default.print timing_ppf;
121+
Format.pp_print_flush timing_ppf ();
122+
BatPrintf.fprintf f "</statistics>";
123+
BatPrintf.fprintf f "<result>\n";
124+
BatEnum.iter (fun b -> BatPrintf.fprintf f "<file name=\"%s\" path=\"%s\">\n%a</file>\n" (Filename.basename b) b p_funs (SH.find_all file2funs b)) (BatEnum.uniq @@ SH.keys file2funs);
125+
BatPrintf.fprintf f "%a" printXml (Lazy.force table);
126+
gtfxml f gtable;
127+
printXmlWarning f ();
128+
BatPrintf.fprintf f "</result></run>\n";
129+
BatPrintf.fprintf f "%!"
130+
in
131+
if get_bool "g2html" then
132+
BatFile.with_temporary_out ~mode:[`create;`text;`delete_on_exit] write_file
133+
else
134+
let f = BatIO.output_channel out in
135+
write_file f (get_string "outfile")
136+
| "json" ->
137+
let open BatPrintf in
138+
let module SH = BatHashtbl.Make (Basetype.RawStrings) in
139+
let file2funs = SH.create 100 in
140+
let funs2node = SH.create 100 in
141+
iter (fun n _ -> SH.add funs2node (Node.find_fundec n).svar.vname n) (Lazy.force table);
142+
iterGlobals file (function
143+
| GFun (fd,loc) -> SH.add file2funs loc.file fd.svar.vname
144+
| _ -> ()
145+
);
146+
let p_enum p f xs = BatEnum.print ~first:"[\n " ~last:"\n]" ~sep:",\n " p f xs in
147+
let p_list p f xs = BatList.print ~first:"[\n " ~last:"\n]" ~sep:",\n " p f xs in
148+
(*let p_kv f (k,p,v) = fprintf f "\"%s\": %a" k p v in*)
149+
(*let p_obj f xs = BatList.print ~first:"{\n " ~last:"\n}" ~sep:",\n " p_kv xs in*)
150+
let p_node f n = BatPrintf.fprintf f "\"%s\"" (Node.show_id n) in
151+
let p_fun f x = fprintf f "{\n \"name\": \"%s\",\n \"nodes\": %a\n}" x (p_list p_node) (SH.find_all funs2node x) in
152+
(*let p_fun f x = p_obj f [ "name", BatString.print, x; "nodes", p_list p_node, SH.find_all funs2node x ] in*)
153+
let p_file f x = fprintf f "{\n \"name\": \"%s\",\n \"path\": \"%s\",\n \"functions\": %a\n}" (Filename.basename x) x (p_list p_fun) (SH.find_all file2funs x) in
154+
let write_file f fn =
155+
printf "Writing json to temp. file: %s\n%!" fn;
156+
fprintf f "{\n \"parameters\": \"%s\",\n " GobSys.command_line;
157+
fprintf f "\"files\": %a,\n " (p_enum p_file) (SH.keys file2funs);
158+
fprintf f "\"results\": [\n %a\n]\n" printJson (Lazy.force table);
159+
(*gtfxml f gtable;*)
160+
(*printXmlWarning f ();*)
161+
fprintf f "}\n";
162+
in
163+
if get_bool "g2html" then
164+
BatFile.with_temporary_out ~mode:[`create;`text;`delete_on_exit] write_file
165+
else
166+
let f = BatIO.output_channel out in
167+
write_file f (get_string "outfile")
168+
| "sarif" ->
169+
let open BatPrintf in
170+
printf "Writing Sarif to file: %s\n%!" (get_string "outfile");
171+
Yojson.Safe.to_channel ~std:true out (Sarif.to_yojson (List.rev !Messages.Table.messages_list));
172+
| "json-messages" ->
173+
let json = `Assoc [
174+
("files", Preprocessor.dependencies_to_yojson ());
175+
("messages", Messages.Table.to_yojson ());
176+
]
177+
in
178+
Yojson.Safe.to_channel ~std:true out json
179+
| "none" -> ()
180+
| s -> failwith @@ "Unsupported value for option `result`: "^s
181+
end
182+
183+
module ResultType2 (S: Analyses.Spec) =
184+
struct
185+
open S
186+
include Printable.Prod3 (C) (D) (CilType.Fundec)
187+
let show (es,x,f:t) = D.show x
188+
let pretty () (_,x,_) = D.pretty () x
189+
let printXml f (c,d,fd) =
190+
BatPrintf.fprintf f "<context>\n%a</context>\n%a" C.printXml c D.printXml d
191+
end

0 commit comments

Comments
 (0)