From e804cb0578c677799ca8f50c1950ae23492c39ff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?David=20B=C3=BChler?= <david.buhler@cea.fr>
Date: Thu, 25 Jan 2024 11:15:35 +0100
Subject: [PATCH] [Inout] Changes and documents external API.

---
 src/plugins/impact/pdg_aux.ml        |  4 +-
 src/plugins/inout/Inout.ml           | 36 ++++++++++++++++++
 src/plugins/inout/Inout.mli          | 56 ++++++++++++++++++++++++++++
 src/plugins/inout/outputs.mli        |  1 +
 src/plugins/reduc/collect.ml         |  2 +-
 src/plugins/scope/datascope.ml       |  2 +-
 src/plugins/slicing/fct_slice.ml     |  4 +-
 src/plugins/slicing/slicingCmds.ml   |  6 +--
 src/plugins/slicing/slicingState.ml  |  2 +-
 src/plugins/sparecode/globs.ml       |  2 +-
 src/plugins/sparecode/register.ml    |  2 +-
 src/plugins/sparecode/spare_marks.ml |  2 +-
 src/plugins/studia/reads.ml          | 12 +++---
 src/plugins/studia/writes.ml         |  8 ++--
 tests/slicing/simple_intra_slice.ml  |  2 +-
 15 files changed, 116 insertions(+), 25 deletions(-)
 create mode 100644 src/plugins/inout/Inout.ml
 create mode 100644 src/plugins/inout/Inout.mli

diff --git a/src/plugins/impact/pdg_aux.ml b/src/plugins/impact/pdg_aux.ml
index a486d6adbac..29097913041 100644
--- a/src/plugins/impact/pdg_aux.ml
+++ b/src/plugins/impact/pdg_aux.ml
@@ -166,9 +166,7 @@ let find_call_input_nodes pdg_caller call_stmt ?(z=Locations.Zone.top) in_key =
 
 let all_call_input_nodes ~caller:pdg_caller ~callee:(kf_callee, pdg_callee) call_stmt =
   let real_inputs =
-    let inout =
-      Inout.Operational_inputs.get_internal_precise ~stmt:call_stmt kf_callee
-    in
+    let inout = Inout.get_precise_inout ~stmt:call_stmt kf_callee in
     inout.Inout_type.over_inputs_if_termination
   in
   let test_in acc (in_key, in_node) =
diff --git a/src/plugins/inout/Inout.ml b/src/plugins/inout/Inout.ml
new file mode 100644
index 00000000000..9eb53af878a
--- /dev/null
+++ b/src/plugins/inout/Inout.ml
@@ -0,0 +1,36 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of Frama-C.                                         *)
+(*                                                                        *)
+(*  Copyright (C) 2007-2023                                               *)
+(*    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 expr_inputs = Inputs.expr
+let stmt_inputs = Inputs.statement
+let kf_inputs = Inputs.get_internal
+let kf_external_inputs = Inputs.get_external
+
+let stmt_outputs = Outputs.statement
+let kf_outputs = Outputs.get_internal
+let kf_external_outputs = Outputs.get_external
+
+let get_precise_inout = Operational_inputs.get_internal_precise
+
+let states = [ Inputs.self; Outputs.self ]
+let proxy = State_builder.Proxy.(create "inout" Both states)
+let self = State_builder.Proxy.get proxy
diff --git a/src/plugins/inout/Inout.mli b/src/plugins/inout/Inout.mli
new file mode 100644
index 00000000000..90a3cb7230e
--- /dev/null
+++ b/src/plugins/inout/Inout.mli
@@ -0,0 +1,56 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of Frama-C.                                         *)
+(*                                                                        *)
+(*  Copyright (C) 2007-2023                                               *)
+(*    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
+
+(** Returns the memory zone needed to evaluate the given expression at the
+    given statement. *)
+val expr_inputs: stmt -> exp -> Locations.Zone.t
+
+(** Returns the memory zone read by the given statement. *)
+val stmt_inputs: stmt -> Locations.Zone.t
+
+(** Returns the memory zone modified by the given statement. *)
+val stmt_outputs: stmt -> Locations.Zone.t
+
+(** Returns the memory zone read by the given function, including its
+    local and formal variables. *)
+val kf_inputs: kernel_function -> Locations.Zone.t
+
+(** Returns the memory zone read by the given function, without its
+    local and formal variables. *)
+val kf_external_inputs: kernel_function -> Locations.Zone.t
+
+(** Returns the memory zone modified by the given function, including its
+    local and formal variables. *)
+val kf_outputs: kernel_function -> Locations.Zone.t
+
+(** Returns the memory zone modified by the given function, without its
+    local and formal variables. *)
+val kf_external_outputs: kernel_function -> Locations.Zone.t
+
+(** Returns the inputs/outputs computed for the given function.
+    If [stmt] is specified and is a possible call to the given function,
+    returns the inputs/outputs for this call specifically. *)
+val get_precise_inout: ?stmt:stmt -> kernel_function -> Inout_type.t
+
+val self: State.t
diff --git a/src/plugins/inout/outputs.mli b/src/plugins/inout/outputs.mli
index 006d55cae5c..192edda7fa5 100644
--- a/src/plugins/inout/outputs.mli
+++ b/src/plugins/inout/outputs.mli
@@ -23,6 +23,7 @@
 val self: State.t
 
 val compute: Cil_types.kernel_function -> unit
+val get_internal: Cil_types.kernel_function -> Locations.Zone.t
 val get_external: Cil_types.kernel_function -> Locations.Zone.t
 val statement: Cil_types.stmt -> Locations.Zone.t
 
diff --git a/src/plugins/reduc/collect.ml b/src/plugins/reduc/collect.ml
index d19635aa3cd..d2192b5df7a 100644
--- a/src/plugins/reduc/collect.ml
+++ b/src/plugins/reduc/collect.ml
@@ -122,7 +122,7 @@ class inout_vis
     with Kernel_function.No_Statement -> assert false
 
   method !vstmt stmt =
-    let out = Inout.Outputs.statement stmt in
+    let out = Inout.stmt_outputs stmt in
     let filter_out vi =
       let open Locations in
       let zone = enumerate_bits (loc_of_varinfo vi) in
diff --git a/src/plugins/scope/datascope.ml b/src/plugins/scope/datascope.ml
index 23c2421b339..29708325fc0 100644
--- a/src/plugins/scope/datascope.ml
+++ b/src/plugins/scope/datascope.ml
@@ -87,7 +87,7 @@ let get_writes stmt lval =
 let register_modified_zones lmap stmt =
   let register lmap zone = InitSid.add_zone lmap zone stmt in
   let aux_out out kf =
-    let inout= Inout.Operational_inputs.get_internal_precise ~stmt kf in
+    let inout= Inout.get_precise_inout ~stmt kf in
     Locations.Zone.join out inout.Inout_type.over_outputs
   in
   match stmt.skind with
diff --git a/src/plugins/slicing/fct_slice.ml b/src/plugins/slicing/fct_slice.ml
index 6d09aef97e7..3818ca7685f 100644
--- a/src/plugins/slicing/fct_slice.ml
+++ b/src/plugins/slicing/fct_slice.ml
@@ -424,7 +424,7 @@ end = struct
       let add_mark =
         let kf = fi_to_call.SlicingInternals.fi_kf in
         let op_inputs =
-          Inout.Operational_inputs.get_internal_precise ~stmt:call kf in
+          Inout.get_precise_inout ~stmt:call kf in
         let z = op_inputs.Inout_type.over_inputs in
         match s with
         | PdgMarks.SelNode (_, None) -> true
@@ -1308,7 +1308,7 @@ let apply_change_call ff call f_to_call =
           try
             let kf = ff_to_call.SlicingInternals.ff_fct.SlicingInternals.fi_kf in
             let op_inputs =
-              Inout.Operational_inputs.get_internal_precise ~stmt:call kf in
+              Inout.get_precise_inout ~stmt:call kf in
             let z = op_inputs.Inout_type.over_inputs in
             (*Format.printf "##Call at %a,@ kf %a,@ @[Z %a@]@."
                Cil.d_loc (Cil_datatype.Stmt.loc call)
diff --git a/src/plugins/slicing/slicingCmds.ml b/src/plugins/slicing/slicingCmds.ml
index 637319e1b3d..b5b773dad33 100644
--- a/src/plugins/slicing/slicingCmds.ml
+++ b/src/plugins/slicing/slicingCmds.ml
@@ -247,7 +247,7 @@ let select_func_calls_to set ~spare kf =
         SlicingMarks.mk_user_mark ~data:nspare ~addr:nspare ~ctrl:nspare
       in
       assert (Eva.Analysis.is_computed ());
-      let outputs = Inout.Outputs.get_external kf in
+      let outputs = Inout.kf_external_outputs kf in
       select_entry_point_and_some_inputs_outputs set ~mark kf
         ~return:true
         ~outputs
@@ -407,8 +407,8 @@ let select_lval_rw set mark ~rd ~wr ~eval kf ki_opt=
 
                    in
                    assert (Eva.Results.is_called kf) ; (* otherwise [!Db.Outputs.get_external kf] gives weird results *)
-                   select_inter_zone select_wr zone_wr_opt (Inout.Outputs.get_external kf) ;
-                   select_inter_zone select_rd zone_rd_opt (Inout.Inputs.get_external kf)
+                   select_inter_zone select_wr zone_wr_opt (Inout.kf_external_outputs kf) ;
+                   select_inter_zone select_rd zone_rd_opt (Inout.kf_external_inputs kf)
                  end
             ));
     !ac
diff --git a/src/plugins/slicing/slicingState.ml b/src/plugins/slicing/slicingState.ml
index bd8abdff686..a95aa8e3435 100644
--- a/src/plugins/slicing/slicingState.ml
+++ b/src/plugins/slicing/slicingState.ml
@@ -34,7 +34,7 @@ let () =
     (fun () ->
        State_dependency_graph.add_codependencies
          ~onto:self
-         [ Pdg.Api.self; Inout.Inputs.self ; Inout.Outputs.self ])
+         [ Pdg.Api.self; Inout.self ])
 
 let get () =
   try P.get ()
diff --git a/src/plugins/sparecode/globs.ml b/src/plugins/sparecode/globs.ml
index dafe82987f4..a55dbb45410 100644
--- a/src/plugins/sparecode/globs.ml
+++ b/src/plugins/sparecode/globs.ml
@@ -160,7 +160,7 @@ let () =
     (fun () ->
        State_dependency_graph.add_codependencies
          ~onto:Result.self
-         [ Pdg.Api.self; Inout.Outputs.self ])
+         [ Pdg.Api.self; Inout.self ])
 
 let rm_unused_decl =
   Result.memo
diff --git a/src/plugins/sparecode/register.ml b/src/plugins/sparecode/register.ml
index 8e2d7af9f7e..b413b26e451 100644
--- a/src/plugins/sparecode/register.ml
+++ b/src/plugins/sparecode/register.ml
@@ -43,7 +43,7 @@ let () =
     (fun () ->
        State_dependency_graph.add_codependencies
          ~onto:Result.self
-         [ Pdg.Api.self; Inout.Outputs.self ])
+         [ Pdg.Api.self; Inout.self ])
 
 module P = Sparecode_params
 
diff --git a/src/plugins/sparecode/spare_marks.ml b/src/plugins/sparecode/spare_marks.ml
index 48d1f2884d9..271a330669b 100644
--- a/src/plugins/sparecode/spare_marks.ml
+++ b/src/plugins/sparecode/spare_marks.ml
@@ -280,7 +280,7 @@ let select_entry_point proj _kf pdg =
   select_pdg_elements proj pdg to_select
 
 let select_all_outputs proj kf pdg =
-  let outputs = Inout.Outputs.get_external kf in
+  let outputs = Inout.kf_external_outputs kf in
   debug 1 "@[selecting output zones %a@]" Locations.Zone.pretty outputs;
   try
     let nodes, undef = Pdg.Api.find_location_nodes_at_end pdg outputs in
diff --git a/src/plugins/studia/reads.ml b/src/plugins/studia/reads.ml
index 457a6a17da9..058691cd35c 100644
--- a/src/plugins/studia/reads.ml
+++ b/src/plugins/studia/reads.ml
@@ -37,11 +37,11 @@ class find_read zlval = object
 
   method! vstmt_aux stmt =
     let aux_call lvopt _kf args _loc =
-      let z = Inout.Inputs.statement stmt in
+      let z = Inout.stmt_inputs stmt in
       if Zone.intersects z zlval then begin
         (* Computes what is read to evaluate [args] and [lvopt] *)
         let deps =
-          List.map (Inout.Inputs.expr stmt) args
+          List.map (Inout.expr_inputs stmt) args
         in
         let deps = List.fold_left Zone.join Zone.bottom deps in
         let deps = match lvopt with
@@ -54,7 +54,7 @@ class find_read zlval = object
         (* now determine if the functions called at [stmt] read directly or
              indirectly [zlval] *)
         let aux_kf (direct, indirect) kf =
-          let inputs = Inout.Inputs.get_internal kf in
+          let inputs = Inout.kf_inputs kf in
           (* TODO: change to this once we can get "full" inputs through Inout.
              Currently, non operational inputs disappear, and this function
              is not suitable.
@@ -85,13 +85,13 @@ class find_read zlval = object
       Cil.treat_constructor_as_func aux_call v f args k l;
       Cil.SkipChildren
     | Instr _ ->
-      let z = Inout.Inputs.statement stmt in
+      let z = Inout.stmt_inputs stmt in
       if Zone.intersects z zlval then begin
         res <- Direct stmt :: res
       end;
       Cil.SkipChildren
     | If (e, _, _, _) | Switch (e, _, _, _) | Return (Some e, _) ->
-      let z = Inout.Inputs.expr stmt e in
+      let z = Inout.expr_inputs stmt e in
       if Zone.intersects z zlval then begin
         res <- Direct stmt :: res
       end;
@@ -104,7 +104,7 @@ end
 let compute z =
   let vis = new find_read z in
   let aux_kf_fundec kf =
-    let all_in = Inout.Inputs.get_internal kf in
+    let all_in = Inout.kf_inputs kf in
     if Zone.intersects all_in z then begin
       let fundec = Kernel_function.get_definition kf in
       ignore
diff --git a/src/plugins/studia/writes.ml b/src/plugins/studia/writes.ml
index 65a670198c4..4d566dfcc64 100644
--- a/src/plugins/studia/writes.ml
+++ b/src/plugins/studia/writes.ml
@@ -65,7 +65,7 @@ let compare w1 w2 =
 (** Does the functions called at [stmt] modify directly or indirectly [zlval] *)
 let effects_of_call stmt zlval effects  =
   let aux_kf (direct, indirect) kf =
-    let inout = Inout.Operational_inputs.get_internal_precise ~stmt kf in
+    let inout = Inout.get_precise_inout ~stmt kf in
     let out = inout.Inout_type.over_outputs in
     if Zone.intersects out zlval then
       if Eva.Analysis.use_spec_instead_of_definition kf then
@@ -89,7 +89,7 @@ class find_write_insts zlval = object (self)
       let aux_call lvopt _kf _args _loc =
         (* Direct effect through the writing of [lvopt], or indirect inside
            the call. *)
-        let z = Inout.Outputs.statement stmt in
+        let z = Inout.stmt_outputs stmt in
         if Zone.intersects z zlval then
           let direct = match lvopt with
             | None -> false
@@ -106,7 +106,7 @@ class find_write_insts zlval = object (self)
       match i with
       | Set _ | Local_init(_, AssignInit _, _) ->
         (* Effect only throuh the written l-value *)
-        let z = Inout.Outputs.statement stmt in
+        let z = Inout.stmt_outputs stmt in
         if Zone.intersects z zlval then begin
           res <- Assign stmt :: res
         end
@@ -123,7 +123,7 @@ end
 let inst_writes z =
   let vis = new find_write_insts z in
   let aux_kf_fundec kf =
-    let all_out = Inout.Operational_inputs.get_internal_precise kf in
+    let all_out = Inout.get_precise_inout kf in
     let zout = all_out.Inout_type.over_outputs in
     if Zone.intersects zout z then begin
       let fundec = Kernel_function.get_definition kf in
diff --git a/tests/slicing/simple_intra_slice.ml b/tests/slicing/simple_intra_slice.ml
index a5df5c95d1f..e60a1638a7c 100644
--- a/tests/slicing/simple_intra_slice.ml
+++ b/tests/slicing/simple_intra_slice.ml
@@ -47,7 +47,7 @@ let main _ =
   in
   let print_outputs fct_name =
     let fct = Globals.Functions.find_by_name fct_name in
-    let outs = Inout.Outputs.get_external fct in
+    let outs = Inout.kf_external_outputs fct in
     Format.printf "Sorties de la fonction %s = %a\n"
       fct_name Locations.Zone.pretty outs
   in
-- 
GitLab