From 44014604fd949ff354345b3974761f33df19a7fa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?David=20B=C3=BChler?= <david.buhler@cea.fr>
Date: Tue, 11 Jul 2023 22:37:57 +0200
Subject: [PATCH] [Eva] Removes Conditions_table from the deprecated module
 Db.Value.

Records the truth value of conditions in a hashtbl in iterator.ml.
---
 src/kernel_services/plugin_entry_points/db.ml | 29 --------
 .../plugin_entry_points/db.mli                |  7 --
 src/plugins/eva/engine/iterator.ml            | 71 +++++++++----------
 src/plugins/eva/engine/iterator.mli           |  5 ++
 src/plugins/eva/utils/results.ml              |  2 +-
 5 files changed, 41 insertions(+), 73 deletions(-)

diff --git a/src/kernel_services/plugin_entry_points/db.ml b/src/kernel_services/plugin_entry_points/db.ml
index 4266f7dd127..960480c8c22 100644
--- a/src/kernel_services/plugin_entry_points/db.ml
+++ b/src/kernel_services/plugin_entry_points/db.ml
@@ -231,35 +231,6 @@ module Value = struct
   let dependencies = [ FunArgs.self; VGlobals.self ]
   let proxy = State_builder.Proxy.(create "eva_db" Forward dependencies)
   let self = State_builder.Proxy.get proxy
-  let only_self = [ self ]
-
-  module Conditions_table =
-    Cil_state_builder.Stmt_hashtbl
-      (Datatype.Int)
-      (struct
-        let name = "Db.Value.Conditions_table"
-        let size = 101
-        let dependencies = only_self
-      end)
-
-  let merge_conditions h =
-    Cil_datatype.Stmt.Hashtbl.iter
-      (fun stmt v ->
-         try
-           let old = Conditions_table.find stmt in
-           Conditions_table.replace stmt (old lor v)
-         with Not_found ->
-           Conditions_table.add stmt v)
-      h
-
-  let mask_then = 1
-  let mask_else = 2
-
-  let condition_truth_value s =
-    try
-      let i = Conditions_table.find s in
-      ((i land mask_then) <> 0, (i land mask_else) <> 0)
-    with Not_found -> false, false
 
   let compute = mk_fun "Value.compute"
 
diff --git a/src/kernel_services/plugin_entry_points/db.mli b/src/kernel_services/plugin_entry_points/db.mli
index 7867a74f246..d664470b29d 100644
--- a/src/kernel_services/plugin_entry_points/db.mli
+++ b/src/kernel_services/plugin_entry_points/db.mli
@@ -124,10 +124,6 @@ module Value : sig
       an incorrect number of them is given.
       @see <https://frama-c.com/download/frama-c-plugin-development-guide.pdf> Plug-in Development Guide *)
 
-  val condition_truth_value: stmt -> bool * bool
-  (** Provided [stmt] is an 'if' construct, [fst (condition_truth_value stmt)]
-      (resp. snd) is true if and only if the condition of the 'if' has been
-      evaluated to true (resp. false) at least once during the analysis. *)
 
   (** {4 Arguments of the main function} *)
 
@@ -178,9 +174,6 @@ module Value : sig
   (**/**)
   (** {3 Internal use only} *)
 
-  val merge_conditions: int Cil_datatype.Stmt.Hashtbl.t -> unit
-  val mask_then: int
-  val mask_else: int
 
   val initial_state_only_globals : (unit -> state) ref
 
diff --git a/src/plugins/eva/engine/iterator.ml b/src/plugins/eva/engine/iterator.ml
index 28a09aefb91..899fb601299 100644
--- a/src/plugins/eva/engine/iterator.ml
+++ b/src/plugins/eva/engine/iterator.ml
@@ -43,6 +43,33 @@ let blocks_share_locals b1 b2 =
   | v1 :: _, v2 :: _ -> v1.vid = v2.vid
   | _, _ -> false
 
+
+module Conditions_table =
+  Cil_state_builder.Stmt_hashtbl
+    (Datatype.Pair (Datatype.Bool) (Datatype.Bool))
+    (struct
+      let name = "Eva.Iterator.Conditions_table"
+      let size = 101
+      let dependencies = [ Self.state ]
+    end)
+
+let condition_truth_value s =
+  try Conditions_table.find s
+  with Not_found -> false, false
+
+let record_fireable edge =
+  match edge.edge_transition with
+  | Guard (_exp, kind, stmt) ->
+    let b_then, b_else = condition_truth_value stmt in
+    let new_status =
+      match kind with
+      | Then -> true, b_else
+      | Else -> b_then, true
+    in
+    Conditions_table.replace stmt new_status
+  | _ -> ()
+
+
 module Make_Dataflow
     (Abstract : Abstractions.S_with_evaluation)
     (States : Powerset.S with type state = Abstract.Dom.t)
@@ -104,10 +131,6 @@ module Make_Dataflow
   type tank = Partitioning.tank
   type widening = Partitioning.widening
 
-  type edge_info = {
-    mutable fireable : bool (* Does any states survive the transition ? *)
-  }
-
 
   (* --- Interpreted automata --- *)
 
@@ -171,7 +194,7 @@ module Make_Dataflow
     VertexTable.create control_point_count
   let w_table : widening VertexTable.t =
     VertexTable.create 7
-  let e_table : (tank * edge_info) EdgeTable.t =
+  let e_table : tank EdgeTable.t =
     EdgeTable.create transition_count
 
   (* Default (Initial) stores on vertex and edges *)
@@ -179,18 +202,18 @@ module Make_Dataflow
     Partitioning.empty_store ~stmt:v.vertex_start_of
   let default_vertex_widening (v : vertex) () : widening =
     Partitioning.empty_widening ~stmt:v.vertex_start_of
-  let default_edge_tank () : tank * edge_info =
-    Partitioning.empty_tank (), { fireable = false }
+  let default_edge_tank () : tank =
+    Partitioning.empty_tank ()
 
   (* Get the stores associated to a control point or edge *)
   let get_vertex_store (v : vertex) : store =
     VertexTable.find_or_add v_table v ~default:(default_vertex_store v)
   let get_vertex_widening (v : vertex) : widening =
     VertexTable.find_or_add w_table v ~default:(default_vertex_widening v)
-  let get_edge_data (e : vertex edge) : tank * edge_info =
+  let get_edge_data (e : vertex edge) : tank =
     EdgeTable.find_or_add e_table e ~default:default_edge_tank
   let get_succ_tanks (v : vertex) : tank list =
-    List.map (fun (_,e,_) -> fst (get_edge_data e)) (G.succ_e graph v)
+    List.map (fun (_,e,_) -> get_edge_data e) (G.succ_e graph v)
 
   module StmtTable = struct
     include Cil_datatype.Stmt.Hashtbl
@@ -422,7 +445,7 @@ module Make_Dataflow
 
   let process_edge (v1,e,v2 : G.edge) : flow =
     let {edge_transition=transition; edge_kinstr=kinstr} = e in
-    let tank,edge_info = get_edge_data e in
+    let tank = get_edge_data e in
     let flow = Partitioning.drain tank in
     Db.yield ();
     check_signals ();
@@ -431,7 +454,7 @@ module Make_Dataflow
     let flow = Partitioning.transfer (transfer_transition transition) flow in
     let flow = process_partitioning_transitions v1 v2 transition flow in
     if not (Partitioning.is_empty_flow flow) then
-      edge_info.fireable <- true;
+      record_fireable e;
     flow
 
   let gather_cvalues states = match get_cvalue with
@@ -526,7 +549,7 @@ module Make_Dataflow
 
   let reset_component (vertex_list : vertex list) : unit =
     let reset_edge (_,e,_) =
-      let t,_ = get_edge_data e in
+      let t = get_edge_data e in
       Partitioning.reset_tank t
     in
     let reset_vertex v =
@@ -611,29 +634,6 @@ module Make_Dataflow
 
   (* --- Results conversion --- *)
 
-  let merge_conditions () =
-    let table = StmtTable.create 5 in
-    let fill (_,e,_) =
-      match e.edge_transition with
-      | Guard (_exp,kind,stmt) ->
-        let mask = match kind with
-          | Then -> Db.Value.mask_then
-          | Else -> Db.Value.mask_else
-        in
-        let edge_info = snd (get_edge_data e) in
-        let old_status =
-          try StmtTable.find table stmt
-          with Not_found -> 0
-        and status =
-          if edge_info.fireable then mask else 0
-        in
-        let new_status = old_status lor status in
-        StmtTable.replace table stmt new_status;
-      | _ -> ()
-    in
-    G.iter_edges_e fill graph;
-    Db.Value.merge_conditions table
-
   let is_instr s = match s.skind with Instr _ -> true | _ -> false
 
   let states_after_stmt states_before states_after =
@@ -693,7 +693,6 @@ module Make_Dataflow
       and register_post = Domain.Store.register_state_after_stmt callstack in
       StmtTable.iter register_pre (Lazy.force merged_pre_states);
       StmtTable.iter register_post (Lazy.force merged_post_states);
-      merge_conditions ();
     end;
     let states =
       Cvalue_callbacks.{ before_stmts = merged_pre_cvalues;
diff --git a/src/plugins/eva/engine/iterator.mli b/src/plugins/eva/engine/iterator.mli
index 0d1f9944063..4c8d02c16bb 100644
--- a/src/plugins/eva/engine/iterator.mli
+++ b/src/plugins/eva/engine/iterator.mli
@@ -25,6 +25,11 @@ open Cil_types
 (** Mark the analysis as aborted. It will be stopped at the next safe point *)
 val signal_abort: unit -> unit
 
+(** Provided [stmt] is an 'if' construct, [fst (condition_truth_value stmt)]
+    (resp. snd) is true if and only if the condition of the 'if' has been
+    evaluated to true (resp. false) at least once during the analysis. *)
+val condition_truth_value: stmt -> bool * bool
+
 module Computer
     (* Abstractions with the evaluator. *)
     (Abstract: Abstractions.S_with_evaluation)
diff --git a/src/plugins/eva/utils/results.ml b/src/plugins/eva/utils/results.ml
index bc78a896d00..297a2b22d2e 100644
--- a/src/plugins/eva/utils/results.ml
+++ b/src/plugins/eva/utils/results.ml
@@ -774,7 +774,7 @@ let is_reachable_kinstr kinstr =
   let module M = Make () in
   M.is_reachable (before_kinstr kinstr)
 
-let condition_truth_value = Db.Value.condition_truth_value
+let condition_truth_value = Iterator.condition_truth_value
 
 (* Callers / callsites *)
 
-- 
GitLab