-
David Bühler authored
For the functions [use_spec_instead_of_definition] and [no_results].
David Bühler authoredFor the functions [use_spec_instead_of_definition] and [no_results].
from_register.ml 6.42 KiB
(**************************************************************************)
(* *)
(* This file is part of Frama-C. *)
(* *)
(* Copyright (C) 2007-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 licenses/LGPLv2.1). *)
(* *)
(**************************************************************************)
open Cil_types
let pretty_with_indirect fmt v =
let deps = !Db.From.get v in
Function_Froms.pretty_with_type_indirect (Kernel_function.get_type v) fmt deps
let display fmtopt =
Option.iter (fun fmt -> Format.fprintf fmt "@[<v>") fmtopt;
Callgraph.Uses.iter_in_rev_order
(fun kf ->
if Eva.Results.is_called kf then
let header fmt =
Format.fprintf fmt "Function %a:" Kernel_function.pretty kf
in
let pretty =
if From_parameters.ShowIndirectDeps.get ()
then pretty_with_indirect
else !Db.From.pretty
in
match fmtopt with
| None ->
From_parameters.printf ~header "@[ %a@]" pretty kf
| Some fmt ->
Format.fprintf fmt "@[%t@]@ @[ %a]" header pretty kf
);
Option.iter (fun fmt -> Format.fprintf fmt "@]") fmtopt
module SortCalls = struct
type t = stmt
(* Sort first by original source code location, then by sid *)
let compare s1 s2 =
let r = Cil_datatype.Location.compare
(Cil_datatype.Stmt.loc s1) (Cil_datatype.Stmt.loc s2) in
if r = 0
then Cil_datatype.Stmt.compare s1 s2 (* This is not really stable, but no
good criterion is left *)
else r
end
module MapStmtCalls = Map.Make(SortCalls)
let iter_callwise_calls_sorted f =
let hkf = Kernel_function.Hashtbl.create 17 in
let kglobal = ref None in
!Db.From.Callwise.iter
(fun ki d ->
match ki with
| Kglobal -> kglobal := Some d
| Kstmt s ->
let kf = Kernel_function.find_englobing_kf s in
let m =
try Kernel_function.Hashtbl.find hkf kf
with Not_found -> MapStmtCalls.empty
in
let m = MapStmtCalls.add s d m in
Kernel_function.Hashtbl.replace hkf kf m
);
Callgraph.Uses.iter_in_rev_order
(fun kf ->
try
let m = Kernel_function.Hashtbl.find hkf kf in
MapStmtCalls.iter (fun s d -> f (Kstmt s) d) m
with Not_found -> ()
);
match !kglobal with
| None -> ()
| Some d -> f Kglobal d
let print_deps () =
From_parameters.feedback
"====== DEPENDENCIES COMPUTED ======@\n\
These dependencies hold at termination for the executions that terminate:";
display None;
From_parameters.feedback "====== END OF DEPENDENCIES ======"
let print_calldeps () =
let treat_call s funtype =
let caller = Kernel_function.find_englobing_kf s in
let f, typ_f =
if not (Eva.Analysis.save_results caller)
then "<unknown>", funtype
else
match Eva.Results.callee s with
| kf :: _ ->
Pretty_utils.to_string Kernel_function.pretty kf,
Kernel_function.get_type kf
| [] ->
From_parameters.fatal
~source:(fst (Cil_datatype.Stmt.loc s))
"Invalid call %a@." Printer.pp_stmt s
in
(fun fmt ->
Format.fprintf fmt "@[call to %s at %a (by %a)%t:@]"
f
Cil_datatype.Location.pretty (Cil_datatype.Stmt.loc s)
Kernel_function.pretty caller
(fun fmt ->
if From_parameters.debug_atleast 1 then
Format.fprintf fmt " <sid %d>" s.Cil_types.sid)
),
typ_f
in
From_parameters.feedback "====== DISPLAYING CALLWISE DEPENDENCIES ======";
iter_callwise_calls_sorted
(fun ki d ->
let header, typ =
match ki with
| Kglobal ->
(fun fmt -> Format.fprintf fmt "@[entry point:@]"),
Kernel_function.get_type (fst (Globals.entry_point ()))
| Kstmt ({skind = Instr (Call (_, ekf, _, _))} as s) ->
treat_call s (Cil.typeOf ekf)
| Kstmt ({skind = Instr (Local_init(_,ConsInit(f,_,_),_))} as s)->
treat_call s f.vtype
| _ -> assert false (* Not a call *)
in
From_parameters.printf ~header
"@[ %a@]"
((if From_parameters.ShowIndirectDeps.get ()
then Function_Froms.pretty_with_type_indirect
else Function_Froms.pretty_with_type) typ)
d);
From_parameters.feedback "====== END OF CALLWISE DEPENDENCIES ======"
let main () =
let not_quiet = From_parameters.verbose_atleast 1 in
if From_parameters.ForceDeps.get () then
From_parameters.ForceDeps.output
(fun () ->
!Db.From.compute_all ();
print_deps ();
);
if From_parameters.ForceCallDeps.get () then
From_parameters.ForceCallDeps.output
(fun () ->
!Db.From.compute_all_calldeps ();
if not_quiet then print_calldeps ();
)
let () = Db.Main.extend main
let access_from zone mem = Function_Froms.Memory.find mem zone
(* Registration for most Db.From functions is done at the end of the
Functionwise and Callwise modules *)
let () =
Db.From.display := (fun fmt -> display (Some fmt));
Db.From.access := access_from;
(*
Local Variables:
compile-command: "make -C ../../.."
End:
*)