From e69ee47461ab96a697d9437a13231785f598ad6e Mon Sep 17 00:00:00 2001
From: Julien Signoles <julien.signoles@cea.fr>
Date: Thu, 19 Sep 2019 20:26:43 +0200
Subject: [PATCH] [archi] put Visit' submodules in independent files

---
 src/plugins/e-acsl/Makefile.in                |   3 +
 .../src/code_generator/global_observer.ml     | 186 ++++++++++
 .../src/code_generator/global_observer.mli    |  50 +++
 .../src/code_generator/literal_observer.ml    |  74 ++++
 .../src/code_generator/literal_observer.mli   |  38 ++
 .../src/code_generator/memory_observer.ml     |  79 +++++
 .../src/code_generator/memory_observer.mli    |  44 +++
 .../e-acsl/src/code_generator/visit.ml        | 334 +-----------------
 8 files changed, 493 insertions(+), 315 deletions(-)
 create mode 100644 src/plugins/e-acsl/src/code_generator/global_observer.ml
 create mode 100644 src/plugins/e-acsl/src/code_generator/global_observer.mli
 create mode 100644 src/plugins/e-acsl/src/code_generator/literal_observer.ml
 create mode 100644 src/plugins/e-acsl/src/code_generator/literal_observer.mli
 create mode 100644 src/plugins/e-acsl/src/code_generator/memory_observer.ml
 create mode 100644 src/plugins/e-acsl/src/code_generator/memory_observer.mli

diff --git a/src/plugins/e-acsl/Makefile.in b/src/plugins/e-acsl/Makefile.in
index ba6c3dc0200..667f43e2f6d 100644
--- a/src/plugins/e-acsl/Makefile.in
+++ b/src/plugins/e-acsl/Makefile.in
@@ -76,6 +76,9 @@ SRC_CODE_GENERATOR:= \
 	logic_functions \
 	translate \
 	temporal \
+	memory_observer \
+	literal_observer \
+	global_observer \
 	visit \
 	injector
 SRC_CODE_GENERATOR:=$(addprefix src/code_generator/, $(SRC_CODE_GENERATOR))
diff --git a/src/plugins/e-acsl/src/code_generator/global_observer.ml b/src/plugins/e-acsl/src/code_generator/global_observer.ml
new file mode 100644
index 00000000000..4fffa4ab20a
--- /dev/null
+++ b/src/plugins/e-acsl/src/code_generator/global_observer.ml
@@ -0,0 +1,186 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of the Frama-C's E-ACSL plug-in.                    *)
+(*                                                                        *)
+(*  Copyright (C) 2012-2018                                               *)
+(*    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
+open Cil_datatype
+
+let function_name = Functions.RTL.mk_api_name "globals_init"
+
+(* Hashtable mapping global variables (as Cil_type.varinfo) to their
+   initializers (if any).
+
+   NOTE: here, varinfos as keys belong to the original project while values
+   belong to the new one *)
+let tbl
+  : (offset (* compound initializers *) * init) list ref Varinfo.Hashtbl.t
+  = Varinfo.Hashtbl.create 7
+
+let reset () = Varinfo.Hashtbl.reset tbl
+
+let is_empty () = Varinfo.Hashtbl.length tbl = 0
+
+let add vi =
+  if Mmodel_analysis.must_model_vi vi then
+    Varinfo.Hashtbl.replace tbl vi (ref [])
+
+let add_initializer vi offset init =
+  if Mmodel_analysis.must_model_vi vi then
+    try
+      let l = Varinfo.Hashtbl.find tbl vi in
+      l := (offset, init) :: !l
+    with Not_found ->
+      assert false
+
+let rec literal_in_initializer env = function
+  | SingleInit exp -> snd (Literal_observer.exp_in_depth env exp)
+  | CompoundInit (_, l) ->
+    List.fold_left (fun env (_, i) -> literal_in_initializer env i) env l
+
+let mk_init bhv env =
+  (* Create [__e_acsl_globals_init] function with definition
+     for initialization of global variables *)
+  let vi =
+    Cil.makeGlobalVar ~source:true
+      function_name
+      (TFun(Cil.voidType, Some [], false, []))
+  in
+  vi.vdefined <- true;
+  (* There is no contract associated with the function *)
+  let spec = Cil.empty_funspec () in
+  (* Create function definition which no stmt yet: they will be added
+     afterwards *)
+  let blk = Cil.mkBlock [] in
+  let fundec =
+    { svar = vi;
+      sformals = [];
+      slocals = [];
+      smaxid = 0;
+      sbody = blk;
+      smaxstmtid = None;
+      sallstmts = [];
+      sspec = spec }
+  in
+  let fct = Definition(fundec, Location.unknown) in
+  (* Create and register [__e_acsl_globals_init] as kernel
+     function *)
+  let kf =
+    { fundec = fct; spec = spec }
+  in
+  Globals.Functions.register kf;
+  Globals.Functions.replace_by_definition spec fundec Location.unknown;
+  (* Now generate the statements. The generation is done only now because it
+     depends on the local variable [already_run] whose generation required the
+     existence of [fundec] *)
+  let env = Env.push env in
+  (* 2-stage observation of initializers: temporal analysis must be performed
+     after generating observers of **all** globals *)
+  let env, stmts =
+    Varinfo.Hashtbl.fold_sorted
+      (fun old_vi l stmts ->
+         let new_vi = Visitor_behavior.Get.varinfo bhv old_vi in
+         List.fold_left
+           (fun (env, stmts) (off, init) ->
+              let env = literal_in_initializer env init in
+              let stmt = Temporal.generate_global_init new_vi off init env in
+              env, match stmt with None -> stmts | Some stmt -> stmt :: stmts)
+           stmts
+           !l)
+      tbl
+      (env, [])
+  in
+  (* allocation and initialization of globals *)
+  let stmts =
+    Varinfo.Hashtbl.fold_sorted
+      (fun old_vi _ stmts ->
+         let new_vi = Visitor_behavior.Get.varinfo bhv old_vi in
+         (* a global is both allocated and initialized *)
+         Misc.mk_store_stmt new_vi
+         :: Misc.mk_initialize ~loc:Location.unknown (Cil.var new_vi)
+         :: stmts)
+      tbl
+      stmts
+  in
+  (* literal strings allocations and initializations *)
+  let stmts =
+    Literal_strings.fold
+      (fun s vi stmts ->
+         let loc = Location.unknown in
+         let e = Cil.new_exp ~loc:loc (Const (CStr s)) in
+         let str_size = Cil.new_exp loc (SizeOfStr s) in
+         Cil.mkStmtOneInstr ~valid_sid:true (Set(Cil.var vi, e, loc))
+         :: Misc.mk_store_stmt ~str_size vi
+         :: Misc.mk_full_init_stmt ~addr:false vi
+         :: Misc.mk_mark_readonly vi
+         :: stmts)
+      stmts
+  in
+  (* Create a new code block with generated statements *)
+  let (b, env), stmts = match stmts with
+    | [] -> assert false
+    | stmt :: stmts ->
+      Env.pop_and_get env stmt ~global_clear:true Env.Before, stmts
+  in
+  let stmts = Cil.mkStmt ~valid_sid:true (Block b) :: stmts in
+  (* Prevent multiple calls to globals_init *)
+  let loc = Location.unknown in
+  let vi_already_run =
+    Cil.makeLocalVar
+      fundec
+      (Functions.RTL.mk_api_name "already_run")
+      (TInt(IChar, []))
+  in
+  vi_already_run.vdefined <- true;
+  vi_already_run.vreferenced <- true;
+  vi_already_run.vstorage <- Static;
+  let init = AssignInit (SingleInit (Cil.zero ~loc)) in
+  let init_stmt =
+    Cil.mkStmtOneInstr ~valid_sid:true
+      (Local_init (vi_already_run, init, loc))
+  in
+  let already_run =
+    Cil.mkStmtOneInstr ~valid_sid:true
+      (Set (Cil.var vi_already_run, Cil.one ~loc, loc))
+  in
+  let stmts = already_run :: stmts in
+  let guard =
+    Cil.mkStmt
+      ~valid_sid:true
+      (If (Cil.evar vi_already_run, Cil.mkBlock [], Cil.mkBlock stmts, loc))
+  in
+  let return = Cil.mkStmt ~valid_sid:true (Return (None, loc)) in
+  let stmts = [ init_stmt; guard; return ] in
+  blk.bstmts <- stmts;
+  vi, fundec, env
+
+let mk_delete bhv stmts =
+  Varinfo.Hashtbl.fold_sorted
+    (fun old_vi _l acc ->
+       let new_vi = Visitor_behavior.Get.varinfo bhv old_vi in
+       Misc.mk_delete_stmt new_vi :: acc)
+    tbl
+    stmts
+
+(*
+Local Variables:
+compile-command: "make -C ../.."
+End:
+*)
diff --git a/src/plugins/e-acsl/src/code_generator/global_observer.mli b/src/plugins/e-acsl/src/code_generator/global_observer.mli
new file mode 100644
index 00000000000..6b1ce04936a
--- /dev/null
+++ b/src/plugins/e-acsl/src/code_generator/global_observer.mli
@@ -0,0 +1,50 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of the Frama-C's E-ACSL plug-in.                    *)
+(*                                                                        *)
+(*  Copyright (C) 2012-2018                                               *)
+(*    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).            *)
+(*                                                                        *)
+(**************************************************************************)
+
+(** Observation of global variables. *)
+
+open Cil_types
+
+val function_name: string
+(** name of the function in which [mk_init] generates the code *)
+
+val reset: unit -> unit
+val is_empty: unit -> bool
+
+val add: varinfo -> unit
+(** observes the given variable if necessary *)
+
+val add_initializer: varinfo -> offset -> init -> unit
+(** add the initializer for the given observed variable *)
+
+val mk_init: Visitor_behavior.t -> Env.t -> varinfo * fundec * Env.t
+(** generates a new C function containing the observers for global variable
+     declaration and initialization *)
+
+val mk_delete: Visitor_behavior.t -> stmt list -> stmt list
+(** generates the observers for global variable de-allocation *)
+
+(*
+Local Variables:
+compile-command: "make -C ../.."
+End:
+*)
diff --git a/src/plugins/e-acsl/src/code_generator/literal_observer.ml b/src/plugins/e-acsl/src/code_generator/literal_observer.ml
new file mode 100644
index 00000000000..2be3b192a55
--- /dev/null
+++ b/src/plugins/e-acsl/src/code_generator/literal_observer.ml
@@ -0,0 +1,74 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of the Frama-C's E-ACSL plug-in.                    *)
+(*                                                                        *)
+(*  Copyright (C) 2012-2018                                               *)
+(*    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 literal loc env s =
+  try
+    let vi = Literal_strings.find s in
+    (* if the literal string was already created, just get it. *)
+    Cil.evar ~loc vi, env
+  with Not_found ->
+    (* never seen this string before: replace it by a new global var *)
+    let vi, exp, env =
+      Env.new_var
+        ~loc
+        ~scope:Varname.Global
+        ~name:"literal_string"
+        env
+        None
+        Cil.charPtrType
+        (fun _ _ -> [] (* done in the initializer, see {!vglob_aux} *))
+    in
+    Literal_strings.add s vi;
+    exp, env
+
+let exp env e = match e.enode with
+  (* the guard below could be optimized: if no annotation **depends on this
+     string**, then it is not required to monitor it.
+     (currently, the guard says: "no annotation uses the memory model" *)
+  | Const (CStr s) when Mmodel_analysis.use_model () -> literal e.eloc env s
+  | _ -> e, env
+
+let exp_in_depth env e =
+  let env_ref = ref env in
+  let o = object
+    inherit Cil.genericCilVisitor (Visitor_behavior.copy (Project.current ()))
+    method !vexpr e = match e.enode with
+      (* the guard below could be optimized: if no annotation **depends on this
+         string**, then it is not required to monitor it.
+         (currently, the guard says: "no annotation uses the memory model" *)
+      | Const (CStr s) when Mmodel_analysis.use_model () ->
+        let e, env = literal e.eloc !env_ref s in
+        env_ref := env;
+        Cil.ChangeTo e
+      | _ ->
+        Cil.DoChildren
+  end in
+  let e = Cil.visitCilExpr o e in
+  e, !env_ref
+
+(*
+Local Variables:
+compile-command: "make -C ../.."
+End:
+*)
diff --git a/src/plugins/e-acsl/src/code_generator/literal_observer.mli b/src/plugins/e-acsl/src/code_generator/literal_observer.mli
new file mode 100644
index 00000000000..f5cea67adfe
--- /dev/null
+++ b/src/plugins/e-acsl/src/code_generator/literal_observer.mli
@@ -0,0 +1,38 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of the Frama-C's E-ACSL plug-in.                    *)
+(*                                                                        *)
+(*  Copyright (C) 2012-2018                                               *)
+(*    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).            *)
+(*                                                                        *)
+(**************************************************************************)
+
+(** Observation of literal strings in C expressions. *)
+
+open Cil_types
+
+val exp: Env.t -> exp -> exp * Env.t
+(** replace the given exp by an observed variable if it is a literal string *)
+
+val exp_in_depth: Env.t -> exp -> exp * Env.t
+(** replace any sub-expression of the given exp that is a literal string by an
+     observed variable   *)
+
+(*
+Local Variables:
+compile-command: "make -C ../.."
+End:
+*)
diff --git a/src/plugins/e-acsl/src/code_generator/memory_observer.ml b/src/plugins/e-acsl/src/code_generator/memory_observer.ml
new file mode 100644
index 00000000000..2004c9a510e
--- /dev/null
+++ b/src/plugins/e-acsl/src/code_generator/memory_observer.ml
@@ -0,0 +1,79 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of the Frama-C's E-ACSL plug-in.                    *)
+(*                                                                        *)
+(*  Copyright (C) 2012-2018                                               *)
+(*    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_datatype
+
+let tracking_stmt ?before fold mk_stmt env kf vars =
+  if Functions.instrument kf then
+    fold
+      (fun vi env ->
+         if Mmodel_analysis.must_model_vi ~kf vi then
+           let vi = Visitor_behavior.Get.varinfo (Env.get_behavior env) vi in
+           Env.add_stmt ?before env (mk_stmt vi)
+         else
+           env)
+      vars
+      env
+  else
+    env
+
+let store ?before env kf vars =
+  tracking_stmt
+    ?before
+    List.fold_right (* small list *)
+    Misc.mk_store_stmt
+    env
+    kf
+    vars
+
+let duplicate_store ?before env kf vars =
+  tracking_stmt
+    ?before
+    Varinfo.Set.fold
+    Misc.mk_duplicate_store_stmt
+    env
+    kf
+    vars
+
+let delete_from_list ?before env kf vars =
+  tracking_stmt
+    ?before
+    List.fold_right (* small list *)
+    Misc.mk_delete_stmt
+    env
+    kf
+    vars
+
+let delete_from_set ?before env kf vars =
+  tracking_stmt
+    ?before
+    Varinfo.Set.fold
+    Misc.mk_delete_stmt
+    env
+    kf
+    vars
+
+(*
+Local Variables:
+compile-command: "make -C ../.."
+End:
+*)
diff --git a/src/plugins/e-acsl/src/code_generator/memory_observer.mli b/src/plugins/e-acsl/src/code_generator/memory_observer.mli
new file mode 100644
index 00000000000..e105f747932
--- /dev/null
+++ b/src/plugins/e-acsl/src/code_generator/memory_observer.mli
@@ -0,0 +1,44 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of the Frama-C's E-ACSL plug-in.                    *)
+(*                                                                        *)
+(*  Copyright (C) 2012-2018                                               *)
+(*    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).            *)
+(*                                                                        *)
+(**************************************************************************)
+
+(** Extend the environment with statements which allocate/deallocate memory
+    blocks. *)
+
+open Cil_types
+open Cil_datatype
+
+val store: ?before:stmt -> Env.t -> kernel_function -> varinfo list -> Env.t
+
+val duplicate_store:
+  ?before:stmt -> Env.t -> kernel_function -> Varinfo.Set.t -> Env.t
+
+val delete_from_list:
+  ?before:stmt -> Env.t -> kernel_function -> varinfo list -> Env.t
+
+val delete_from_set:
+  ?before:stmt -> Env.t -> kernel_function -> Varinfo.Set.t -> Env.t
+
+(*
+Local Variables:
+compile-command: "make -C ../.."
+End:
+*)
diff --git a/src/plugins/e-acsl/src/code_generator/visit.ml b/src/plugins/e-acsl/src/code_generator/visit.ml
index 93874cf54d7..4cf562bb0fb 100644
--- a/src/plugins/e-acsl/src/code_generator/visit.ml
+++ b/src/plugins/e-acsl/src/code_generator/visit.ml
@@ -21,7 +21,6 @@
 (**************************************************************************)
 
 module Libc = Functions.Libc
-module RTL = Functions.RTL
 module E_acsl_label = Label
 open Cil_types
 open Cil_datatype
@@ -37,305 +36,6 @@ let function_env = ref Env.dummy
 let dft_funspec = Cil.empty_funspec ()
 let funspec = ref dft_funspec
 
-(* extend the environment with statements which allocate/deallocate memory
-   blocks *)
-module Memory: sig
-  val store: ?before:stmt -> Env.t -> kernel_function -> varinfo list -> Env.t
-  val duplicate_store:
-    ?before:stmt -> Env.t -> kernel_function -> Varinfo.Set.t -> Env.t
-  val delete_from_list:
-    ?before:stmt -> Env.t -> kernel_function -> varinfo list -> Env.t
-  val delete_from_set:
-    ?before:stmt -> Env.t -> kernel_function -> Varinfo.Set.t -> Env.t
-end = struct
-
-  let tracking_stmt ?before fold mk_stmt env kf vars =
-    if Functions.instrument kf then
-      fold
-        (fun vi env ->
-           if Mmodel_analysis.must_model_vi ~kf vi then
-             let vi = Visitor_behavior.Get.varinfo (Env.get_behavior env) vi in
-             Env.add_stmt ?before env (mk_stmt vi)
-           else
-             env)
-        vars
-        env
-    else
-      env
-
-  let store ?before env kf vars =
-    tracking_stmt
-      ?before
-      List.fold_right (* small list *)
-      Misc.mk_store_stmt
-    env
-      kf
-      vars
-
-  let duplicate_store ?before env kf vars =
-    tracking_stmt
-      ?before
-      Varinfo.Set.fold
-      Misc.mk_duplicate_store_stmt
-      env
-      kf
-      vars
-
-  let delete_from_list ?before env kf vars =
-    tracking_stmt
-      ?before
-      List.fold_right (* small list *)
-      Misc.mk_delete_stmt
-      env
-      kf
-      vars
-
-  let delete_from_set ?before env kf vars =
-    tracking_stmt
-      ?before
-      Varinfo.Set.fold
-      Misc.mk_delete_stmt
-      env
-      kf
-      vars
-
-end
-
-(* Observation of literal strings in C expressions *)
-module Literal_observer: sig
-
-  val exp: Env.t -> exp -> exp * Env.t
-  (* replace the given exp by an observed variable if it is a literal string *)
-
-  val exp_in_depth: Env.t -> exp -> exp * Env.t
-  (* replace any sub-expression of the given exp that is a literal string by an
-     observed variable   *)
-
-end =
-struct
-
-  let literal loc env s =
-    try
-      let vi = Literal_strings.find s in
-      (* if the literal string was already created, just get it. *)
-      Cil.evar ~loc vi, env
-    with Not_found ->
-      (* never seen this string before: replace it by a new global var *)
-      let vi, exp, env =
-        Env.new_var
-          ~loc
-          ~scope:Varname.Global
-          ~name:"literal_string"
-          env
-          None
-          Cil.charPtrType
-          (fun _ _ -> [] (* done in the initializer, see {!vglob_aux} *))
-      in
-      Literal_strings.add s vi;
-      exp, env
-
-  let exp env e = match e.enode with
-    (* the guard below could be optimized: if no annotation **depends on this
-       string**, then it is not required to monitor it.
-       (currently, the guard says: "no annotation uses the memory model" *)
-    | Const (CStr s) when Mmodel_analysis.use_model () -> literal e.eloc env s
-    | _ -> e, env
-
-  let exp_in_depth env e =
-    let env_ref = ref env in
-    let o = object
-      inherit Cil.genericCilVisitor (Visitor_behavior.copy (Project.current ()))
-      method !vexpr e = match e.enode with
-      (* the guard below could be optimized: if no annotation **depends on this
-         string**, then it is not required to monitor it.
-         (currently, the guard says: "no annotation uses the memory model" *)
-      | Const (CStr s) when Mmodel_analysis.use_model () ->
-        let e, env = literal e.eloc !env_ref s in
-        env_ref := env;
-        Cil.ChangeTo e
-      | _ ->
-        Cil.DoChildren
-    end in
-    let e = Cil.visitCilExpr o e in
-    e, !env_ref
-
-end
-
-(* Observation of global variables. *)
-module Global_observer: sig
-  val function_name: string (* name of the function in which [mk_init] generates
-                               the code *)
-  val reset: unit -> unit
-  val is_empty: unit -> bool
-
-  val add: varinfo -> unit (* observes the given variable if necessary *)
-  val add_initializer: varinfo -> offset -> init -> unit
-  (* add the initializer for the given observed variable *)
-
-  val mk_init: Visitor_behavior.t -> Env.t -> varinfo * fundec * Env.t
-  (* generates a new C function containing the observers for global variable
-     declaration and initialization *)
-
-  val mk_delete: Visitor_behavior.t -> stmt list -> stmt list
-  (* generates the observers for global variable de-allocation *)
-
-end = struct
-
-  let function_name = RTL.mk_api_name "globals_init"
-
-  (* Hashtable mapping global variables (as Cil_type.varinfo) to their
-     initializers (if any).
-
-     NOTE: here, varinfos as keys belong to the original project while values
-     belong to the new one *)
-  let tbl
-      : (offset (* compound initializers *) * init) list ref Varinfo.Hashtbl.t
-      = Varinfo.Hashtbl.create 7
-
-  let reset () = Varinfo.Hashtbl.reset tbl
-
-  let is_empty () = Varinfo.Hashtbl.length tbl = 0
-
-  let add vi =
-    if Mmodel_analysis.must_model_vi vi then
-      Varinfo.Hashtbl.replace tbl vi (ref [])
-
-  let add_initializer vi offset init =
-    if Mmodel_analysis.must_model_vi vi then
-      try
-        let l = Varinfo.Hashtbl.find tbl vi in
-        l := (offset, init) :: !l
-      with Not_found ->
-        assert false
-
-  let rec literal_in_initializer env = function
-    | SingleInit exp -> snd (Literal_observer.exp_in_depth env exp)
-    | CompoundInit (_, l) ->
-      List.fold_left (fun env (_, i) -> literal_in_initializer env i) env l
-
-  let mk_init bhv env =
-    (* Create [__e_acsl_globals_init] function with definition
-       for initialization of global variables *)
-    let vi =
-      Cil.makeGlobalVar ~source:true
-        function_name
-        (TFun(Cil.voidType, Some [], false, []))
-    in
-    vi.vdefined <- true;
-    (* There is no contract associated with the function *)
-    let spec = Cil.empty_funspec () in
-    (* Create function definition which no stmt yet: they will be added
-       afterwards *)
-    let blk = Cil.mkBlock [] in
-    let fundec =
-      { svar = vi;
-        sformals = [];
-        slocals = [];
-        smaxid = 0;
-        sbody = blk;
-        smaxstmtid = None;
-        sallstmts = [];
-        sspec = spec }
-    in
-    let fct = Definition(fundec, Location.unknown) in
-    (* Create and register [__e_acsl_globals_init] as kernel
-       function *)
-    let kf =
-      { fundec = fct; spec = spec }
-    in
-    Globals.Functions.register kf;
-    Globals.Functions.replace_by_definition spec fundec Location.unknown;
-    (* Now generate the statements. The generation is done only now because it
-       depends on the local variable [already_run] whose generation required the
-       existence of [fundec] *)
-    let env = Env.push env in
-    (* 2-stage observation of initializers: temporal analysis must be performed
-       after generating observers of **all** globals *)
-    let env, stmts =
-      Varinfo.Hashtbl.fold_sorted
-        (fun old_vi l stmts ->
-          let new_vi = Visitor_behavior.Get.varinfo bhv old_vi in
-          List.fold_left
-            (fun (env, stmts) (off, init) ->
-              let env = literal_in_initializer env init in
-              let stmt = Temporal.generate_global_init new_vi off init env in
-              env, match stmt with None -> stmts | Some stmt -> stmt :: stmts)
-            stmts
-            !l)
-        tbl
-        (env, [])
-    in
-    (* allocation and initialization of globals *)
-    let stmts =
-      Varinfo.Hashtbl.fold_sorted
-        (fun old_vi _ stmts ->
-          let new_vi = Visitor_behavior.Get.varinfo bhv old_vi in
-          (* a global is both allocated and initialized *)
-          Misc.mk_store_stmt new_vi
-          :: Misc.mk_initialize ~loc:Location.unknown (Cil.var new_vi)
-          :: stmts)
-        tbl
-        stmts
-    in
-    (* literal strings allocations and initializations *)
-    let stmts =
-      Literal_strings.fold
-        (fun s vi stmts ->
-          let loc = Location.unknown in
-          let e = Cil.new_exp ~loc:loc (Const (CStr s)) in
-          let str_size = Cil.new_exp loc (SizeOfStr s) in
-          Cil.mkStmtOneInstr ~valid_sid:true (Set(Cil.var vi, e, loc))
-          :: Misc.mk_store_stmt ~str_size vi
-          :: Misc.mk_full_init_stmt ~addr:false vi
-          :: Misc.mk_mark_readonly vi
-          :: stmts)
-        stmts
-    in
-    (* Create a new code block with generated statements *)
-    let (b, env), stmts = match stmts with
-      | [] -> assert false
-      | stmt :: stmts ->
-        Env.pop_and_get env stmt ~global_clear:true Env.Before, stmts
-    in
-    let stmts = Cil.mkStmt ~valid_sid:true (Block b) :: stmts in
-    (* Prevent multiple calls to globals_init *)
-    let loc = Location.unknown in
-    let vi_already_run =
-      Cil.makeLocalVar fundec (RTL.mk_api_name "already_run") (TInt(IChar, []))
-    in
-    vi_already_run.vdefined <- true;
-    vi_already_run.vreferenced <- true;
-    vi_already_run.vstorage <- Static;
-    let init = AssignInit (SingleInit (Cil.zero ~loc)) in
-    let init_stmt =
-      Cil.mkStmtOneInstr ~valid_sid:true
-        (Local_init (vi_already_run, init, loc))
-    in
-    let already_run =
-      Cil.mkStmtOneInstr ~valid_sid:true
-        (Set (Cil.var vi_already_run, Cil.one ~loc, loc))
-    in
-    let stmts = already_run :: stmts in
-    let guard =
-      Cil.mkStmt
-        ~valid_sid:true
-        (If (Cil.evar vi_already_run, Cil.mkBlock [], Cil.mkBlock stmts, loc))
-    in
-    let return = Cil.mkStmt ~valid_sid:true (Return (None, loc)) in
-    let stmts = [ init_stmt; guard; return ] in
-    blk.bstmts <- stmts;
-    vi, fundec, env
-
-    let mk_delete bhv stmts =
-      Varinfo.Hashtbl.fold_sorted
-        (fun old_vi _l acc ->
-          let new_vi = Visitor_behavior.Get.varinfo bhv old_vi in
-          Misc.mk_delete_stmt new_vi :: acc)
-        tbl
-        stmts
-
-end
-
 (* the main visitor performing e-acsl checking and C code generator *)
 class e_acsl_visitor prj generate = object (self)
 
@@ -447,7 +147,7 @@ you must call function `%s' and `__e_acsl_memory_clean by yourself.@]"
               in
               let ptr_size = Cil.sizeOf loc Cil.voidPtrType in
               let args = args @ [ ptr_size ] in
-              let name = RTL.mk_api_name "memory_init" in
+              let name = Functions.RTL.mk_api_name "memory_init" in
               let init = Misc.mk_call loc name args in
               main.sbody.bstmts <- init :: main.sbody.bstmts
             in
@@ -663,7 +363,9 @@ you must call function `%s' and `__e_acsl_memory_clean by yourself.@]"
         (* JS: should be done in the new project? *)
         let env =
           if generate && not is_main then
-            let env = Memory.store env kf (Kernel_function.get_formals kf) in
+            let env =
+              Memory_observer.store env kf (Kernel_function.get_formals kf)
+            in
             Temporal.handle_function_parameters kf env
           else
             env
@@ -702,7 +404,8 @@ you must call function `%s' and `__e_acsl_memory_clean by yourself.@]"
      * init calls appear before store calls. *)
     let duplicates = Exit_points.store_vars stmt in
     let env =
-      if generate then Memory.duplicate_store ~before:stmt env kf duplicates
+      if generate
+      then Memory_observer.duplicate_store ~before:stmt env kf duplicates
       else env
     in
     function_env := env;
@@ -758,7 +461,8 @@ you must call function `%s' and `__e_acsl_memory_clean by yourself.@]"
         (* Remove local variables which scopes ended via goto/break/continue. *)
         let del_vars = Exit_points.delete_vars stmt in
         let env =
-          if generate then Memory.delete_from_set ~before:stmt env kf del_vars
+          if generate
+          then Memory_observer.delete_from_set ~before:stmt env kf del_vars
           else env
         in
         if self#is_return kf stmt then
@@ -783,7 +487,7 @@ you must call function `%s' and `__e_acsl_memory_clean by yourself.@]"
             (* Remove recorded function arguments *)
             let fargs = Kernel_function.get_formals kf in
             let env =
-              if generate then Memory.delete_from_list env kf fargs
+              if generate then Memory_observer.delete_from_list env kf fargs
               else env
             in
             let b, env =
@@ -792,7 +496,7 @@ you must call function `%s' and `__e_acsl_memory_clean by yourself.@]"
             if is_main && Mmodel_analysis.use_model () then begin
               let stmts = b.bstmts in
               let l = List.rev stmts in
-              let mclean = (RTL.mk_api_name "memory_clean") in
+              let mclean = (Functions.RTL.mk_api_name "memory_clean") in
               match l with
               | [] -> assert false (* at least the 'return' stmt *)
               | ret :: l ->
@@ -916,13 +620,13 @@ you must call function `%s' and `__e_acsl_memory_clean by yourself.@]"
         fvi.vname <- Libc.actual_alloca;
         (* Since we need to pass [vi] by value cannot use [Misc.mk_store_stmt]
            here. Do it manually. *)
-        let sname = RTL.mk_api_name "store_block" in
+        let sname = Functions.RTL.mk_api_name "store_block" in
         let store = Misc.mk_call ~loc sname [ Cil.evar vi ; sz ] in
         Env.add_stmt ~post:true env store
       (* Rewrite format functions (e.g., [printf]). See some comments below *)
       | ConsInit (fvi, args, knd) when check_formats
           && Libc.is_printf_name fvi.vname ->
-        let name = RTL.get_rtl_replacement_name fvi.vname in
+        let name = Functions.RTL.get_rtl_replacement_name fvi.vname in
         let new_vi = Misc.get_lib_fun_vi name in
         let fmt = Libc.get_printf_argument_str ~loc fvi.vname args in
         stmt.skind <-
@@ -931,8 +635,8 @@ you must call function `%s' and `__e_acsl_memory_clean by yourself.@]"
       (* Rewrite names of functions for which we have alternative
         definitions in the RTL. *)
       | ConsInit (fvi, _, _) when replace_libc_fn &&
-        RTL.has_rtl_replacement fvi.vname ->
-        fvi.vname <- RTL.get_rtl_replacement_name fvi.vname;
+        Functions.RTL.has_rtl_replacement fvi.vname ->
+        fvi.vname <- Functions.RTL.get_rtl_replacement_name fvi.vname;
         env
       | _ -> env)
     | Instr(Call (result, exp, args, loc)) ->
@@ -940,18 +644,18 @@ you must call function `%s' and `__e_acsl_memory_clean by yourself.@]"
          definitions in the RTL. *)
       (match exp.enode with
       | Lval(Var vi, _) when replace_libc_fn &&
-          RTL.has_rtl_replacement vi.vname ->
-        vi.vname <- RTL.get_rtl_replacement_name vi.vname
+          Functions.RTL.has_rtl_replacement vi.vname ->
+        vi.vname <- Functions.RTL.get_rtl_replacement_name vi.vname
       | Lval(Var vi , _) when Libc.is_vla_free_name vi.vname ->
         (* Handle variable-length array allocation via [__fc_vla_free].
            Rewrite its name to [delete_block]. The rest is in place. *)
-        vi.vname <- RTL.mk_api_name "delete_block"
+        vi.vname <- Functions.RTL.mk_api_name "delete_block"
       | Lval(Var vi, _) when check_formats && Libc.is_printf_name vi.vname ->
         (* Rewrite names of format functions (such as printf). This case
            differs from the above because argument list of format functions is
            extended with an argument describing actual variadic arguments *)
         (* Replacement name, e.g., [printf] -> [__e_acsl_builtin_printf] *)
-        let name = RTL.get_rtl_replacement_name vi.vname in
+        let name = Functions.RTL.get_rtl_replacement_name vi.vname in
         (* Variadic arguments descriptor *)
         let fmt = Libc.get_printf_argument_str ~loc vi.vname args in
         (* get the name of the library function we need. Cannot just rewrite
@@ -962,7 +666,7 @@ you must call function `%s' and `__e_acsl_memory_clean by yourself.@]"
       (* Add statement tracking initialization of return values of function
          calls *)
       (match result with
-        | Some lv when not (RTL.is_generated_kf kf) ->
+        | Some lv when not (Functions.RTL.is_generated_kf kf) ->
           add_initializer loc lv ~post:false stmt env kf
         | _ -> env)
     | _ -> env
-- 
GitLab