From 793b7f20e05d92347468268d92d994ce63e44ec4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?David=20B=C3=BChler?= <david.buhler@cea.fr>
Date: Fri, 14 Jan 2022 22:23:51 +0100
Subject: [PATCH] [Eva] Uses the plugins callgraph, rtegen and scope via the
 dynamic API.

The new file eva_dynamic contains all accesses via the dynamic API.
---
 Makefile                                      |  2 +-
 headers/header_spec.txt                       |  2 +
 .../value/domains/cvalue/cvalue_domain.ml     |  2 +-
 src/plugins/value/engine/compute_functions.ml |  4 +-
 src/plugins/value/gui_files/register_gui.ml   |  4 +-
 src/plugins/value/legacy/eval_annots.ml       |  5 --
 src/plugins/value/legacy/eval_annots.mli      |  1 -
 src/plugins/value/utils/eva_dynamic.ml        | 67 +++++++++++++++++++
 src/plugins/value/utils/eva_dynamic.mli       | 43 ++++++++++++
 9 files changed, 117 insertions(+), 13 deletions(-)
 create mode 100644 src/plugins/value/utils/eva_dynamic.ml
 create mode 100644 src/plugins/value/utils/eva_dynamic.mli

diff --git a/Makefile b/Makefile
index 9fa91830176..75ce964f267 100644
--- a/Makefile
+++ b/Makefile
@@ -856,7 +856,7 @@ endif
 # - try to keep the legacy Value before Eva
 PLUGIN_CMO:= partitioning/split_strategy domains/domain_mode value_parameters \
 	utils/eva_audit utils/value_perf utils/eva_annotations \
-	utils/value_util utils/red_statuses \
+	utils/eva_dynamic utils/value_util utils/red_statuses \
 	utils/mark_noresults \
 	utils/widen_hints_ext utils/widen \
 	partitioning/split_return \
diff --git a/headers/header_spec.txt b/headers/header_spec.txt
index 081be10cddc..40c2cc32fa2 100644
--- a/headers/header_spec.txt
+++ b/headers/header_spec.txt
@@ -1483,6 +1483,8 @@ src/plugins/value/utils/eva_annotations.ml: CEA_LGPL_OR_PROPRIETARY
 src/plugins/value/utils/eva_annotations.mli: CEA_LGPL_OR_PROPRIETARY
 src/plugins/value/utils/eva_audit.ml: CEA_LGPL_OR_PROPRIETARY
 src/plugins/value/utils/eva_audit.mli: CEA_LGPL_OR_PROPRIETARY
+src/plugins/value/utils/eva_dynamic.ml: CEA_LGPL_OR_PROPRIETARY
+src/plugins/value/utils/eva_dynamic.mli: CEA_LGPL_OR_PROPRIETARY
 src/plugins/value/utils/structure.ml: CEA_LGPL_OR_PROPRIETARY
 src/plugins/value/utils/structure.mli: CEA_LGPL_OR_PROPRIETARY
 src/plugins/value/utils/summary.ml: CEA_LGPL_OR_PROPRIETARY
diff --git a/src/plugins/value/domains/cvalue/cvalue_domain.ml b/src/plugins/value/domains/cvalue/cvalue_domain.ml
index 80abee069dd..57dd8ab350c 100644
--- a/src/plugins/value/domains/cvalue/cvalue_domain.ml
+++ b/src/plugins/value/domains/cvalue/cvalue_domain.ml
@@ -559,7 +559,7 @@ module State = struct
 
   let display_results () =
     Value_parameters.result "====== VALUES COMPUTED ======";
-    Callgraph.Uses.iter_in_rev_order display;
+    Eva_dynamic.Callgraph.iter_in_rev_order display;
     Value_parameters.result "%t" Value_perf.display
 
   let post_analysis _state =
diff --git a/src/plugins/value/engine/compute_functions.ml b/src/plugins/value/engine/compute_functions.ml
index 718da24a529..e294447de66 100644
--- a/src/plugins/value/engine/compute_functions.ml
+++ b/src/plugins/value/engine/compute_functions.ml
@@ -108,10 +108,10 @@ let post_analysis () =
   (* Try to refine the 'Unknown' statuses that have been emitted during
      this analysis. *)
   Eval_annots.mark_green_and_red ();
-  Eval_annots.mark_rte ();
+  Eva_dynamic.RteGen.mark_generated_rte ();
   post_analysis_cleanup ~aborted:false;
   (* Remove redundant alarms *)
-  if Value_parameters.RmAssert.get () then !Db.Value.rm_asserts ()
+  if Value_parameters.RmAssert.get () then Eva_dynamic.Scope.rm_asserts ()
 
 (* Registers signal handlers for SIGUSR1 and SIGINT to cleanly abort the Eva
    analysis. Returns a function that restores previous signal behaviors after
diff --git a/src/plugins/value/gui_files/register_gui.ml b/src/plugins/value/gui_files/register_gui.ml
index 5adf217e9f9..3587497948d 100644
--- a/src/plugins/value/gui_files/register_gui.ml
+++ b/src/plugins/value/gui_files/register_gui.ml
@@ -227,9 +227,7 @@ let gui_compute_values (main_ui:main_ui) =
 
 let cleaned_outputs kf s =
   let outs = Db.Outputs.kinstr (Kstmt s) in
-  let accept =
-    Callgraph.Uses.accept_base ~with_formals:true ~with_locals:true kf
-  in
+  let accept = Eva_dynamic.Callgraph.accept_base kf in
   let filter = Locations.Zone.filter_base accept in
   Option.map filter outs
 
diff --git a/src/plugins/value/legacy/eval_annots.ml b/src/plugins/value/legacy/eval_annots.ml
index 7e3434b351b..68aed0aadab 100644
--- a/src/plugins/value/legacy/eval_annots.ml
+++ b/src/plugins/value/legacy/eval_annots.ml
@@ -102,11 +102,6 @@ let mark_unreachable () =
   Annotations.iter_all_code_annot do_code_annot;
   Visitor.visitFramacFile unreach (Ast.get ())
 
-let mark_rte () =
-  let list = !Db.RteGen.get_all_status () in
-  let mark kf = List.iter (fun (_kind, set, _get) -> set kf true) list in
-  Globals.Functions.iter (fun kf -> if !Db.Value.is_called kf then mark kf)
-
 let c_labels kf cs =
   if !Db.Value.use_spec_instead_of_definition kf then
     Cil_datatype.Logic_label.Map.empty
diff --git a/src/plugins/value/legacy/eval_annots.mli b/src/plugins/value/legacy/eval_annots.mli
index 03fbb8c5154..ba43b7aa2f9 100644
--- a/src/plugins/value/legacy/eval_annots.mli
+++ b/src/plugins/value/legacy/eval_annots.mli
@@ -26,5 +26,4 @@ val has_requires: spec -> bool
 val mark_invalid_initializers: unit -> unit
 val mark_unreachable: unit -> unit
 val mark_green_and_red: unit -> unit
-val mark_rte: unit -> unit
 val c_labels: kernel_function -> Value_types.callstack -> Eval_terms.labels_states
diff --git a/src/plugins/value/utils/eva_dynamic.ml b/src/plugins/value/utils/eva_dynamic.ml
new file mode 100644
index 00000000000..b62a8ec73cb
--- /dev/null
+++ b/src/plugins/value/utils/eva_dynamic.ml
@@ -0,0 +1,67 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of Frama-C.                                         *)
+(*                                                                        *)
+(*  Copyright (C) 2007-2021                                               *)
+(*    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).            *)
+(*                                                                        *)
+(**************************************************************************)
+
+let get ~plugin name typ ~fallback =
+  try Dynamic.get ~plugin name typ
+  with Failure _ | Dynamic.(Unbound_value _ | Incompatible_type _) -> fallback
+
+module Callgraph = struct
+  let plugin = "callgraph"
+
+  let iter_in_rev_order f =
+    let fallback = Globals.Functions.iter in
+    let typ = Datatype.(func (func Kernel_function.ty unit) unit) in
+    get ~plugin "iter_in_rev_order" typ ~fallback f
+
+  let accept_base kf v =
+    let fallback _ _ = true in
+    let typ = Datatype.(func2 Kernel_function.ty Base.ty bool) in
+    get ~plugin "accept_base" typ ~fallback kf v
+end
+
+module Scope = struct
+  let plugin = "scope"
+
+  let rm_asserts () =
+    let fallback () =
+      Value_parameters.warning
+        "The scope plugin is missing: cannot remove redundant alarms."
+    in
+    let typ = Datatype.(func unit unit) in
+    get ~plugin "rm_asserts" typ ~fallback ()
+end
+
+module RteGen = struct
+  let plugin = "RteGen"
+
+  let all_statuses () =
+    let kf = Kernel_function.ty in
+    let typ =
+      Datatype.(list (triple string (func2 kf bool unit) (func kf bool)))
+    in
+    get ~plugin "all_statuses" typ ~fallback:[]
+
+  let mark_generated_rte () =
+    let list = all_statuses () in
+    let mark kf = List.iter (fun (_kind, set, _get) -> set kf true) list in
+    Globals.Functions.iter (fun kf -> if !Db.Value.is_called kf then mark kf)
+end
diff --git a/src/plugins/value/utils/eva_dynamic.mli b/src/plugins/value/utils/eva_dynamic.mli
new file mode 100644
index 00000000000..85648b91530
--- /dev/null
+++ b/src/plugins/value/utils/eva_dynamic.mli
@@ -0,0 +1,43 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of Frama-C.                                         *)
+(*                                                                        *)
+(*  Copyright (C) 2007-2021                                               *)
+(*    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).            *)
+(*                                                                        *)
+(**************************************************************************)
+
+(** Access to other plugins API via {Dynamic.get}. *)
+
+module Callgraph: sig
+  (** Iterates over all functions in the callgraph in reverse order, i.e. from
+      callees to callers. If callgraph is missing, the order is unspecified. *)
+  val iter_in_rev_order: (Kernel_function.t -> unit) -> unit
+
+  (** Returns [true] if [base] is a global, or a formal or local of either [kf]
+      or one of its callers. If callgraph is missing, always returns true. *)
+  val accept_base: Kernel_function.t -> Base.t -> bool
+end
+
+module Scope: sig
+  (** Removes redundant assertions. Warns if the scope plugin is missing. *)
+  val rm_asserts: unit -> unit
+end
+
+module RteGen: sig
+  (** Marks all RTE as generated. Does nothing if the rte plugin is missing. *)
+  val mark_generated_rte: unit -> unit
+end
-- 
GitLab