Skip to content
Snippets Groups Projects
Commit b521f5d7 authored by David Bühler's avatar David Bühler Committed by Virgile Prevosto
Browse files

[kernel] Visitor: adds a function to visit all function definitions of a file.

For visitors that only need function C bodies, replaces uses of
[visitFramacFileSameGlobals], which visits all globals of a file, by
[visitFramacFileFunctions], which visits only function definitions.

Also optimizes these visitors by skipping the visit of some nodes,
especially the visit of functions specifications and code annotations.
parent 043a8d08
No related branches found
No related tags found
No related merge requests found
...@@ -57,11 +57,15 @@ class vis_add_loop_allocates = ...@@ -57,11 +57,15 @@ class vis_add_loop_allocates =
); );
Cil.DoChildren Cil.DoChildren
method! vinst _ = Cil.SkipChildren method! vinst _ = SkipChildren
method! vexpr _ = SkipChildren
method! vlval _ = SkipChildren
method! vtype _ = SkipChildren
method! vspec _ = SkipChildren
method! vcode_annot _ = SkipChildren
end end
let add_allocates_nothing () = let add_allocates_nothing () =
Globals.Functions.iter add_allocates_nothing_funspec; Globals.Functions.iter add_allocates_nothing_funspec;
let vis = new vis_add_loop_allocates in let vis = new vis_add_loop_allocates in
Visitor.visitFramacFileSameGlobals vis (Ast.get ()) Visitor.visitFramacFileFunctions vis (Ast.get ())
...@@ -221,11 +221,17 @@ class visit_assembly = ...@@ -221,11 +221,17 @@ class visit_assembly =
~dkey:Kernel.dkey_asm_contracts "Ignoring basic assembly instruction"; ~dkey:Kernel.dkey_asm_contracts "Ignoring basic assembly instruction";
Cil.SkipChildren Cil.SkipChildren
| _ -> Cil.SkipChildren | _ -> Cil.SkipChildren
method! vexpr _ = SkipChildren
method! vlval _ = SkipChildren
method! vtype _ = SkipChildren
method! vspec _ = SkipChildren
method! vcode_annot _ = SkipChildren
end end
let transform file = let transform file =
if Kernel.AsmContractsGenerate.get() then if Kernel.AsmContractsGenerate.get() then
Visitor.visitFramacFileSameGlobals (new visit_assembly) file Visitor.visitFramacFileFunctions (new visit_assembly) file
let () = let () =
File.add_code_transformation_after_cleanup File.add_code_transformation_after_cleanup
......
...@@ -709,6 +709,13 @@ class do_it global_find_init ((force:bool),(times:int)) = object(self) ...@@ -709,6 +709,13 @@ class do_it global_find_init ((force:bool),(times:int)) = object(self)
ChangeDoChildrenPost (s, fgh) ChangeDoChildrenPost (s, fgh)
| _ -> DoChildren | _ -> DoChildren
method! vinst _ = SkipChildren
method! vexpr _ = SkipChildren
method! vlval _ = SkipChildren
method! vtype _ = SkipChildren
method! vspec _ = SkipChildren
method! vcode_annot _ = SkipChildren
end end
(* Performs unrolling transformation without using -ulevel option. (* Performs unrolling transformation without using -ulevel option.
...@@ -723,7 +730,7 @@ let apply_transformation ?(force=true) nb file = ...@@ -723,7 +730,7 @@ let apply_transformation ?(force=true) nb file =
in in
let visitor = new do_it global_find_init (force, nb) in let visitor = new do_it global_find_init (force, nb) in
Kernel.debug ~dkey "Using -ulevel %d option and UNROLL loop pragmas@." nb; Kernel.debug ~dkey "Using -ulevel %d option and UNROLL loop pragmas@." nb;
visitFramacFileSameGlobals (visitor:>Visitor.frama_c_visitor) file; visitFramacFileFunctions (visitor:>Visitor.frama_c_visitor) file;
if !ast_has_changed then Ast.mark_as_changed () if !ast_has_changed then Ast.mark_as_changed ()
else begin else begin
Kernel.debug ~dkey Kernel.debug ~dkey
......
...@@ -65,11 +65,17 @@ class all_exn = ...@@ -65,11 +65,17 @@ class all_exn =
all_exn <- Cil_datatype.Typ.Set.add (purify t) all_exn; all_exn <- Cil_datatype.Typ.Set.add (purify t) all_exn;
SkipChildren SkipChildren
| _ -> DoChildren | _ -> DoChildren
method! vinst _ = SkipChildren
method! vexpr _ = SkipChildren
method! vlval _ = SkipChildren
method! vtype _ = SkipChildren
method! vspec _ = SkipChildren
method! vcode_annot _ = SkipChildren
end end
let compute_all_exn () = let compute_all_exn () =
let vis = new all_exn in let vis = new all_exn in
Visitor.visitFramacFileSameGlobals (vis:>Visitor.frama_c_visitor) (Ast.get()); Visitor.visitFramacFileFunctions (vis:>Visitor.frama_c_visitor) (Ast.get());
vis#get_exn vis#get_exn
let all_exn () = All_exn.memo compute_all_exn let all_exn () = All_exn.memo compute_all_exn
...@@ -259,6 +265,11 @@ class exn_visit = ...@@ -259,6 +265,11 @@ class exn_visit =
in in
DoChildrenPost after_visit DoChildrenPost after_visit
method! vexpr _ = SkipChildren
method! vlval _ = SkipChildren
method! vtype _ = SkipChildren
method! vspec _ = SkipChildren
method! vcode_annot _ = SkipChildren
end end
let compute_kf kf = let compute_kf kf =
...@@ -857,7 +868,7 @@ let prepare_file f = ...@@ -857,7 +868,7 @@ let prepare_file f =
let remove_exn f = let remove_exn f =
if Kernel.RemoveExn.get() then begin if Kernel.RemoveExn.get() then begin
Visitor.visitFramacFileSameGlobals (new exn_visit) f; Visitor.visitFramacFileFunctions (new exn_visit) f;
let vis = new erase_exn in let vis = new erase_exn in
Visitor.visitFramacFile (vis :> Visitor.frama_c_visitor) f; Visitor.visitFramacFile (vis :> Visitor.frama_c_visitor) f;
let funs = vis#modified_funcs in let funs = vis#modified_funcs in
......
...@@ -342,6 +342,11 @@ let inliner functions_to_inline = object (self) ...@@ -342,6 +342,11 @@ let inliner functions_to_inline = object (self)
let kf = Globals.Functions.get f.svar in let kf = Globals.Functions.get f.svar in
already_visited <- Cil_datatype.Kf.Set.add kf functions_to_inline; f) already_visited <- Cil_datatype.Kf.Set.add kf functions_to_inline; f)
method! vexpr _ = SkipChildren
method! vlval _ = SkipChildren
method! vtype _ = SkipChildren
method! vspec _ = SkipChildren
method! vcode_annot _ = SkipChildren
end end
let remove_local_statics = object let remove_local_statics = object
...@@ -379,7 +384,7 @@ end ...@@ -379,7 +384,7 @@ end
let inline_calls ast = let inline_calls ast =
if not (InlineCalls.is_empty ()) then begin if not (InlineCalls.is_empty ()) then begin
let functions = InlineCalls.get() in let functions = InlineCalls.get() in
Visitor.visitFramacFileSameGlobals (inliner functions) ast; Visitor.visitFramacFileFunctions (inliner functions) ast;
Cil_datatype.Kf.Set.iter Cil_datatype.Kf.Set.iter
(fun kf -> ignore (Visitor.visitFramacKf remove_local_statics kf)) (fun kf -> ignore (Visitor.visitFramacKf remove_local_statics kf))
functions; functions;
......
...@@ -871,6 +871,13 @@ let visitFramacFunction vis f = ...@@ -871,6 +871,13 @@ let visitFramacFunction vis f =
Option.iter vis#set_current_kf old_current_kf; Option.iter vis#set_current_kf old_current_kf;
vis#fill_global_tables; f' vis#fill_global_tables; f'
let visitFramacFileFunctions vis file =
let process_one_global = function
| GFun (fundec, _) -> ignore (visitFramacFunction vis fundec)
| _ -> ()
in
Cil.iterGlobals file process_one_global
let visitFramacKf vis kf = let visitFramacKf vis kf =
let glob = Ast.def_or_last_decl (Kernel_function.get_vi kf) in let glob = Ast.def_or_last_decl (Kernel_function.get_vi kf) in
ignore (visitFramacGlobal vis glob); ignore (visitFramacGlobal vis glob);
......
...@@ -115,6 +115,13 @@ val visitFramacFile: frama_c_visitor -> file -> unit ...@@ -115,6 +115,13 @@ val visitFramacFile: frama_c_visitor -> file -> unit
@plugin development guide *) @plugin development guide *)
val visitFramacFileSameGlobals: frama_c_visitor -> file -> unit val visitFramacFileSameGlobals: frama_c_visitor -> file -> unit
(** Visit all function definitions of a file. Use this function instead of
{!Visitor.visitFramacFile} or {!Visitor.visitFramacFileSameGlobals} if your
visitor only needs function bodies to avoid visiting other globals,
including libc functions and their specifications.
@since Frama-c+dev *)
val visitFramacFileFunctions: frama_c_visitor -> file -> unit
(** Visit a global. (** Visit a global.
{b Warning} Do not call this function during another visit using the {b Warning} Do not call this function during another visit using the
......
...@@ -96,11 +96,16 @@ let mark_unreachable () = ...@@ -96,11 +96,16 @@ let mark_unreachable () =
end; end;
Cil.DoChildren Cil.DoChildren
method! vinst _ = Cil.SkipChildren method! vinst _ = SkipChildren
method! vexpr _ = SkipChildren
method! vlval _ = SkipChildren
method! vtype _ = SkipChildren
method! vspec _ = SkipChildren
method! vcode_annot _ = SkipChildren
end end
in in
Annotations.iter_all_code_annot do_code_annot; Annotations.iter_all_code_annot do_code_annot;
Visitor.visitFramacFile unreach (Ast.get ()) Visitor.visitFramacFileFunctions unreach (Ast.get ())
let c_labels kf cs = let c_labels kf cs =
if !Db.Value.use_spec_instead_of_definition kf then if !Db.Value.use_spec_instead_of_definition kf then
......
...@@ -208,6 +208,10 @@ module ReturnUsage = struct ...@@ -208,6 +208,10 @@ module ReturnUsage = struct
method result () = method result () =
summarize_by_lv usage summarize_by_lv usage
method! vtype _ = SkipChildren
method! vspec _ = SkipChildren
method! vcode_annot _ = SkipChildren
end end
(* For functions returning pointers, add a split on NULL/non-NULL *) (* For functions returning pointers, add a split on NULL/non-NULL *)
...@@ -223,7 +227,7 @@ module ReturnUsage = struct ...@@ -223,7 +227,7 @@ module ReturnUsage = struct
let compute file = let compute file =
let vis = new visitorVarUsage in let vis = new visitorVarUsage in
Visitor.visitFramacFileSameGlobals (vis:> Visitor.frama_c_visitor) file; Visitor.visitFramacFileFunctions (vis:> Visitor.frama_c_visitor) file;
let split_compared = vis#result () in let split_compared = vis#result () in
let split_null_pointers = add_null_pointers_split split_compared in let split_null_pointers = add_null_pointers_split split_compared in
split_null_pointers split_null_pointers
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment