From ce212670d3b0bcb3a189ff882d261b21431b529f Mon Sep 17 00:00:00 2001
From: Julien Signoles <julien.signoles@cea.fr>
Date: Fri, 27 Sep 2019 17:54:23 +0200
Subject: [PATCH] [archi] kill vstmt_aux

---
 .../e-acsl/src/code_generator/injector.ml     | 201 +++++++++++++++-
 .../e-acsl/src/code_generator/loops.ml        |  29 +--
 .../e-acsl/src/code_generator/loops.mli       |   2 +-
 .../e-acsl/src/code_generator/visit.ml        | 222 ------------------
 src/plugins/e-acsl/src/libraries/misc.ml      |  17 +-
 src/plugins/e-acsl/src/libraries/misc.mli     |   2 +-
 6 files changed, 219 insertions(+), 254 deletions(-)

diff --git a/src/plugins/e-acsl/src/code_generator/injector.ml b/src/plugins/e-acsl/src/code_generator/injector.ml
index df801c571ad..41f1983a915 100644
--- a/src/plugins/e-acsl/src/code_generator/injector.ml
+++ b/src/plugins/e-acsl/src/code_generator/injector.ml
@@ -20,25 +20,217 @@
 (*                                                                        *)
 (**************************************************************************)
 
+module E_acsl_label = Label (* [Label] is hidden by opening [Cil_datatype *)
 open Cil_types
 open Cil_datatype
 
 let dkey = Options.dkey_translation
 
+(* ************************************************************************** *)
+(* Utilities *)
+(* ************************************************************************** *)
+
 (* [TODO ARCHI] move it in another module *)
 let is_main kf =
   Datatype.String.equal (Kernel_function.get_name kf) "main"
 
+(* [TODO ARCHI] move it *)
+let is_first_stmt kf stmt =
+  try Stmt.equal stmt (Kernel_function.find_first_stmt kf)
+  with Kernel_function.No_Statement -> assert false
+
+let is_return_stmt kf stmt =
+  try Stmt.equal stmt (Kernel_function.find_return kf)
+  with Kernel_function.No_Statement -> assert false
+
 (* ************************************************************************** *)
 (* Code *)
 (* ************************************************************************** *)
 
-let inject_in_block _env _main kf blk =
+let add_new_block_in_stmt env kf stmt =
+  (* be careful: since this function is called in a post action, [env] has been
+     modified from the time where pre actions have been executed.  Use
+     [function_env] to get it back. *)
+  (* [TODO ARCHI] what about the above comment? *)
+  (* Add temporal analysis instrumentations *)
+  let env = Temporal.handle_stmt stmt env kf in
+  let new_stmt, env, must_mv =
+    if Functions.check kf then
+      let env =
+        (* handle ghost statement *)
+        if stmt.ghost then begin
+          stmt.ghost <- false;
+          (* translate potential RTEs of ghost code *)
+          let rtes = Rte.stmt ~warn:false kf stmt in
+          Translate.translate_rte_annots Printer.pp_stmt stmt kf env rtes
+        end else
+          env
+      in
+      (* handle loop invariants *)
+      let new_stmt, env, must_mv = Loops.preserve_invariant env kf stmt in
+      new_stmt, env, must_mv
+    else
+      stmt, env, false
+  in
+  let mk_post_env env stmt =
+    Annotations.fold_code_annot
+      (fun _ a env -> Translate.translate_post_code_annotation kf env a)
+      stmt
+      env
+  in
+  let new_stmt, env =
+    (* Remove local variables which scopes ended via goto/break/continue. *)
+    let del_vars = Exit_points.delete_vars stmt in
+    let env = Memory_observer.delete_from_set ~before:stmt env kf del_vars in
+    if is_return_stmt kf stmt then
+      let env =
+        if Functions.check kf then
+          (* must generate the post_block before including [stmt] (the
+             'return') since no code is executed after it. However, since
+             this statement is pure (Cil invariant), that is semantically
+             correct. *)
+          (* [JS 2019/2/19] TODO: what about the other ways of early exiting
+             a block? *)
+          let env = mk_post_env env stmt in
+          (* also handle the postcondition of the function and clear the
+             env *)
+          Translate.translate_post_spec kf env (Annotations.funspec kf)
+        else
+          env
+      in
+      (* de-allocating memory previously allocating by the kf *)
+      (* remove recorded function arguments *)
+      let fargs = Kernel_function.get_formals kf in
+      let env = Memory_observer.delete_from_list env kf fargs in
+      let b, env =
+        Env.pop_and_get env new_stmt ~global_clear:true Env.After
+      in
+      if is_main kf && Mmodel_analysis.use_model () then begin
+        let stmts = b.bstmts in
+        let l = List.rev stmts in
+        let mclean = (Functions.RTL.mk_api_name "memory_clean") in
+        match l with
+        | [] -> assert false (* at least the 'return' stmt *)
+        | ret :: l ->
+          let loc = Stmt.loc stmt in
+          let delete_stmts =
+            Global_observer.mk_delete_stmts [ Misc.mk_call ~loc mclean []; ret ]
+          in
+          b.bstmts <- List.rev l @ delete_stmts
+      end;
+      let new_stmt = Misc.mk_block stmt b in
+      if not (Cil_datatype.Stmt.equal stmt new_stmt) then begin
+        (* move the labels of the return to the new block in order to
+           evaluate the postcondition when jumping to them. *)
+        E_acsl_label.move kf stmt new_stmt
+      end;
+      new_stmt, env
+    else (* i.e. not (is_return stmt) *)
+      (* must generate [pre_block] which includes [stmt] before generating
+         [post_block] *)
+      let pre_block, env =
+        Env.pop_and_get
+          ~split:true
+          env
+          new_stmt
+          ~global_clear:false
+          Env.After
+      in
+      let env =
+        (* if [kf] is not monitored, do not translate any postcondition,
+           but still push an empty environment consumed by
+           [Env.pop_and_get] below. This [Env.pop_and_get] call is always
+           required in order to generate the code not directly related to
+           the annotations of the current stmt in anycase. *)
+        if Functions.check kf then mk_post_env (Env.push env) stmt
+        else Env.push env
+      in
+      let post_block, env =
+        Env.pop_and_get
+          env
+          (Misc.mk_block new_stmt pre_block)
+          ~global_clear:false
+          Env.Before
+      in
+      let post_block =
+        if post_block.blocals = [] && new_stmt.labels = []
+        then Cil.transient_block post_block
+        else post_block
+      in
+      let res = Misc.mk_block new_stmt post_block in
+      if not (Cil_datatype.Stmt.equal new_stmt res) then
+        E_acsl_label.move kf new_stmt res;
+      res, env
+  in
+  if must_mv then Loops.mv_invariants kf ~old:new_stmt stmt;
+  Options.debug ~level:4
+    "@[new stmt (from sid %d):@ %a@]" stmt.sid Printer.pp_stmt new_stmt;
+  new_stmt, env
+
+let inject_in_stmt env kf stmt =
+  Options.debug ~level:4
+    "proceeding stmt (sid %d) %a@."
+    stmt.sid Stmt.pretty stmt;
+  (* pushing a new context *)
+  let env = Env.push env in
+  let env = match stmt.skind with
+    | Loop _ -> Env.push_loop env
+    | _ -> env
+  in
+  (* initial environment *)
+  let env =
+    if is_first_stmt kf stmt then
+      let env =
+        if is_main kf then
+          env
+        else
+          let env =
+            Memory_observer.store env kf (Kernel_function.get_formals kf)
+          in
+          Temporal.handle_function_parameters kf env
+      in
+      (* translate the precondition of the function *)
+      if Functions.check kf then
+        let funspec = Annotations.funspec kf in
+        Translate.translate_pre_spec kf env funspec
+      else env
+    else
+      env
+  in
+  (* translate code annotations *)
+  let env =
+    if Functions.check kf then
+      Annotations.fold_code_annot
+        (fun _ a env -> Translate.translate_pre_code_annotation kf env a)
+        stmt
+        env
+    else
+      env
+  in
+  (* add [__e_acsl_store_duplicate] calls for local variables which declarations
+     are bypassed by gotos. Note: should be done before visiting instructions
+     (which adds initializers), otherwise init calls appear before store
+     calls. *)
+  let duplicates = Exit_points.store_vars stmt in
+  let env = Memory_observer.duplicate_store ~before:stmt env kf duplicates in
   (* [TODO ARCHI] HERE recursive call *)
+  (* building the new block of code *)
+  add_new_block_in_stmt env kf stmt
+
+let inject_in_block (env: Env.t) kf blk =
+  let stmts, env =
+    List.fold_right
+      (fun stmt (stmts, env) ->
+         let stmt, env = inject_in_stmt env kf stmt in
+         stmt :: stmts, env)
+      blk.bstmts
+      ([], env)
+  in
+  blk.bstmts <- stmts;
   let free_stmts = At_with_lscope.Free.find_all kf in
   match blk.blocals, free_stmts with
   | [], [] ->
-    ()
+    env
   | [], _ :: _ | _ :: _, [] | _ :: _, _ :: _ ->
     let add_locals stmts =
       if Functions.instrument kf then
@@ -83,7 +275,8 @@ let inject_in_block _env _main kf blk =
              then Misc.mk_store_stmt vi :: acc
              else acc)
           blk.bstmts
-          blk.blocals
+          blk.blocals;
+    env
 
 (* ************************************************************************** *)
 (* Function definition *)
@@ -129,7 +322,7 @@ let inject_in_fundec env main fundec =
   Options.feedback ~dkey ~level:2 "entering in function %a."
     Kernel_function.pretty kf;
   (* recursive visit *)
-  inject_in_block env main kf fundec.sbody;
+  let env = inject_in_block env kf fundec.sbody in
   Exit_points.clear ();
   add_generated_variables_in_function env fundec;
   add_malloc_and_free_stmts kf fundec;
diff --git a/src/plugins/e-acsl/src/code_generator/loops.ml b/src/plugins/e-acsl/src/code_generator/loops.ml
index e9849e324dc..7adcd834c2c 100644
--- a/src/plugins/e-acsl/src/code_generator/loops.ml
+++ b/src/plugins/e-acsl/src/code_generator/loops.ml
@@ -65,26 +65,23 @@ let mv_invariants kf ~old stmt =
               Annotations.add_code_annot e ~kf stmt ca)
            l)
 
-let preserve_invariant prj env kf stmt = match stmt.skind with
+let preserve_invariant env kf stmt = match stmt.skind with
   | Loop(_, ({ bstmts = stmts } as blk), loc, cont, break) ->
     let rec handle_invariants (stmts, env, _ as acc) = function
       | [] ->
-	(* empty loop body: no need to verify the invariant twice *)
-	acc
+        (* empty loop body: no need to verify the invariant twice *)
+        acc
       | [ last ] ->
-	let invariants, env = Env.pop_loop env in
-	let env = Env.push env in
-	let env =
-    let translate_named_predicate = !translate_named_predicate_ref in
-	  Project.on
-	    prj
-	    (List.fold_left (translate_named_predicate kf) env)
-	    invariants
-	in
-	let blk, env =
-	  Env.pop_and_get env last ~global_clear:false Env.Before
-	in
-	Misc.mk_block prj last blk :: stmts, env, invariants != []
+        let invariants, env = Env.pop_loop env in
+        let env = Env.push env in
+        let env =
+          let translate_named_predicate = !translate_named_predicate_ref in
+          List.fold_left (translate_named_predicate kf) env invariants
+        in
+        let blk, env =
+          Env.pop_and_get env last ~global_clear:false Env.Before
+        in
+        Misc.mk_block last blk :: stmts, env, invariants != []
       | s :: tl -> handle_invariants (s :: stmts, env, false) tl
     in
     let env = Env.set_annotation_kind env Misc.Invariant in
diff --git a/src/plugins/e-acsl/src/code_generator/loops.mli b/src/plugins/e-acsl/src/code_generator/loops.mli
index a55e09d7a65..a37b5beaee7 100644
--- a/src/plugins/e-acsl/src/code_generator/loops.mli
+++ b/src/plugins/e-acsl/src/code_generator/loops.mli
@@ -35,7 +35,7 @@ val mv_invariants: kernel_function -> old:stmt -> stmt -> unit
     Both statements must be loops. *)
 
 val preserve_invariant:
-  Project.t -> Env.t -> Kernel_function.t -> stmt -> stmt * Env.t * bool
+  Env.t -> Kernel_function.t -> stmt -> stmt * Env.t * bool
 (** modify the given stmt loop to insert the code which preserves its loop
     invariants. Also return the modify environment and a boolean which
     indicates whether the annotations corresponding to the loop invariant must
diff --git a/src/plugins/e-acsl/src/code_generator/visit.ml b/src/plugins/e-acsl/src/code_generator/visit.ml
index 0083db8f3a0..e7da48a8438 100644
--- a/src/plugins/e-acsl/src/code_generator/visit.ml
+++ b/src/plugins/e-acsl/src/code_generator/visit.ml
@@ -107,228 +107,6 @@ class e_acsl_visitor prj generate = object (self)
               s;*)
       false
 
-  method !vstmt_aux stmt =
-    Options.debug ~level:4 "proceeding stmt (sid %d) %a@."
-      stmt.sid Stmt.pretty stmt;
-    let kf = Extlib.the self#current_kf in
-    let is_main = self#is_main kf in
-    let env = Env.push !function_env in
-    let env = match stmt.skind with
-      | Loop _ -> Env.push_loop env
-      | _ -> env
-    in
-    let env =
-      if self#is_first_stmt kf stmt then
-        (* JS: should be done in the new project? *)
-        let env =
-          if generate && not is_main then
-            let env =
-              Memory_observer.store env kf (Kernel_function.get_formals kf)
-            in
-            Temporal.handle_function_parameters kf env
-          else
-            env
-        in
-        (* translate the precondition of the function *)
-        if Functions.check kf then
-          Project.on prj (Translate.translate_pre_spec kf env) !funspec
-        else
-          env
-      else
-        env
-    in
-
-    let env, new_annots =
-      if Functions.check kf then
-        Annotations.fold_code_annot
-          (fun _ old_a (env, new_annots) ->
-            let a =
-              (* [VP] Don't use Visitor here, as it will fill the queue in the
-                 middle of the computation... *)
-              Cil.visitCilCodeAnnotation (self :> Cil.cilVisitor) old_a
-            in
-            let env =
-              Project.on prj (Translate.translate_pre_code_annotation kf env) a
-            in
-            env, a :: new_annots)
-          (Visitor_behavior.Get_orig.stmt self#behavior stmt)
-          (env, [])
-      else
-        env, []
-    in
-
-    (* Add [__e_acsl_store_duplicate] calls for local variables which
-     * declarations are bypassed by gotos. Note: should be done before
-     * [vinst] method (which adds initializers) is executed, otherwise
-     * init calls appear before store calls. *)
-    let duplicates = Exit_points.store_vars stmt in
-    let env =
-      if generate
-      then Memory_observer.duplicate_store ~before:stmt env kf duplicates
-      else env
-    in
-    function_env := env;
-
-    let mk_block stmt =
-      (* be careful: since this function is called in a post action, [env] has
-         been modified from the time where pre actions have been executed.
-         Use [function_env] to get it back. *)
-      let env = !function_env in
-      let env =
-        if generate then
-          (* Add temporal analysis instrumentations *)
-          let env = Temporal.handle_stmt stmt env in
-          (* Add initialization statements and store_block statements stemming
-             from Local_init *)
-          self#handle_instructions stmt env kf
-        else
-          env
-      in
-      let new_stmt, env, must_mv =
-        if Functions.check kf then
-          let env =
-            (* handle ghost statement *)
-            if stmt.ghost then begin
-              stmt.ghost <- false;
-              (* translate potential RTEs of ghost code *)
-              let rtes = Rte.stmt ~warn:false kf stmt in
-              Translate.translate_rte_annots Printer.pp_stmt stmt kf env rtes
-            end else
-              env
-          in
-          (* handle loop invariants *)
-          let new_stmt, env, must_mv =
-            Loops.preserve_invariant prj env kf stmt
-          in
-          let orig = Visitor_behavior.Get_orig.stmt self#behavior stmt in
-          Visitor_behavior.Set_orig.stmt self#behavior new_stmt orig;
-          Visitor_behavior.Set.stmt self#behavior orig new_stmt;
-          new_stmt, env, must_mv
-        else
-          stmt, env, false
-      in
-      let mk_post_env env =
-        (* [fold_right] to preserve order of generation of pre_conditions *)
-        Project.on
-          prj
-          (List.fold_right
-             (fun a env -> Translate.translate_post_code_annotation kf env a)
-             new_annots)
-          env
-      in
-      let new_stmt, env =
-        (* 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_observer.delete_from_set ~before:stmt env kf del_vars
-          else env
-        in
-        if self#is_return kf stmt then
-          let env =
-            if Functions.check kf then
-              (* must generate the post_block before including [stmt] (the
-                 'return') since no code is executed after it. However, since
-                 this statement is pure (Cil invariant), that is semantically
-                 correct. *)
-              (* [JS 2019/2/19] TODO: what about the other ways of early exiting
-                 a block? *)
-              let env = mk_post_env env in
-              (* also handle the postcondition of the function and clear the
-                 env *)
-              Project.on prj (Translate.translate_post_spec kf env) !funspec
-            else
-              env
-          in
-          (* de-allocating memory previously allocating by the kf *)
-          (* JS: should be done in the new project? *)
-          if generate then
-            (* Remove recorded function arguments *)
-            let fargs = Kernel_function.get_formals kf in
-            let env =
-              if generate then Memory_observer.delete_from_list env kf fargs
-              else env
-            in
-            let b, env =
-              Env.pop_and_get env new_stmt ~global_clear:true Env.After
-            in
-            if is_main && Mmodel_analysis.use_model () then begin
-              let stmts = b.bstmts in
-              let l = List.rev stmts in
-              let mclean = (Functions.RTL.mk_api_name "memory_clean") in
-              match l with
-              | [] -> assert false (* at least the 'return' stmt *)
-              | ret :: l ->
-                let loc = Stmt.loc stmt in
-                let delete_stmts =
-                  Global_observer.mk_delete
-                    self#behavior
-                    [ Misc.mk_call ~loc mclean []; ret ]
-                in
-                b.bstmts <- List.rev l @ delete_stmts
-            end;
-            let new_stmt = Misc.mk_block prj stmt b in
-            if not (Cil_datatype.Stmt.equal stmt new_stmt) then begin
-              (* move the labels of the return to the new block in order to
-                 evaluate the postcondition when jumping to them. *)
-              E_acsl_label.move
-                (self :> Visitor.generic_frama_c_visitor) stmt new_stmt
-            end;
-            new_stmt, env
-          else
-            stmt, env
-        else (* i.e. not (is_return stmt) *)
-          if generate then begin
-            (* must generate [pre_block] which includes [stmt] before generating
-               [post_block] *)
-            let pre_block, env =
-              Env.pop_and_get
-                ~split:true
-                env
-                new_stmt
-                ~global_clear:false
-                Env.After
-            in
-            let env =
-              (* if [kf] is not monitored, do not translate any postcondition,
-                 but still push an empty environment consumed by
-                 [Env.pop_and_get] below. This [Env.pop_and_get] call is always
-                 required in order to generate the code not directly related to
-                 the annotations of the current stmt in anycase. *)
-              if Functions.check kf then mk_post_env (Env.push env)
-              else Env.push env
-            in
-            let post_block, env =
-              Env.pop_and_get
-                env
-                (Misc.mk_block prj new_stmt pre_block)
-                ~global_clear:false
-                Env.Before
-            in
-            let post_block =
-              if post_block.blocals = [] && new_stmt.labels = []
-              then Cil.transient_block post_block
-              else post_block
-            in
-            let res = Misc.mk_block prj new_stmt post_block in
-            if not (Cil_datatype.Stmt.equal new_stmt res) then
-              E_acsl_label.move (self :> Visitor.generic_frama_c_visitor)
-                new_stmt res;
-            let orig = Visitor_behavior.Get_orig.stmt self#behavior stmt in
-            Visitor_behavior.Set.stmt self#behavior orig res;
-            Visitor_behavior.Set_orig.stmt self#behavior res orig;
-            res, env
-          end else
-            stmt, env
-      in
-      if must_mv then Loops.mv_invariants env ~old:new_stmt stmt;
-      function_env := env;
-      Options.debug ~level:4
-      "@[new stmt (from sid %d):@ %a@]" stmt.sid Printer.pp_stmt new_stmt;
-      if generate then new_stmt else stmt
-    in
-    Cil.ChangeDoChildrenPost(stmt, mk_block)
-
   method private handle_instructions stmt env kf =
     let add_initializer loc ?vi lv ?(post=false) stmt env kf =
       assert generate;
diff --git a/src/plugins/e-acsl/src/libraries/misc.ml b/src/plugins/e-acsl/src/libraries/misc.ml
index 1b0ff8112c5..876b77dd686 100644
--- a/src/plugins/e-acsl/src/libraries/misc.ml
+++ b/src/plugins/e-acsl/src/libraries/misc.ml
@@ -124,16 +124,13 @@ let mk_e_acsl_guard ?(reverse=false) kind kf e p =
       Cil.mkString ~loc msg;
       Cil.integer loc line ]
 
-let mk_block prj stmt b =
-  let mk b = match b.bstmts with
-    | [] ->
-      (match stmt.skind with
-      | Instr(Skip _) -> stmt
-      | _ -> assert false)
-    | [ s ] -> s
-    |  _ :: _ -> Cil.mkStmt ~valid_sid:true (Block b)
-  in
-  Project.on prj mk b
+let mk_block stmt b = match b.bstmts with
+  | [] ->
+    (match stmt.skind with
+     | Instr(Skip _) -> stmt
+     | _ -> assert false)
+  | [ s ] -> s
+  |  _ :: _ -> Cil.mkStmt ~valid_sid:true (Block b)
 
 (* ************************************************************************** *)
 (** {2 Handling \result} *)
diff --git a/src/plugins/e-acsl/src/libraries/misc.mli b/src/plugins/e-acsl/src/libraries/misc.mli
index f54bf923fe5..fb335a7e892 100644
--- a/src/plugins/e-acsl/src/libraries/misc.mli
+++ b/src/plugins/e-acsl/src/libraries/misc.mli
@@ -53,7 +53,7 @@ val mk_e_acsl_guard:
   ?reverse:bool -> annotation_kind -> kernel_function -> exp -> predicate
   -> stmt
 
-val mk_block: Project.t -> stmt -> block -> stmt
+val mk_block: stmt -> block -> stmt
 
 (* ************************************************************************** *)
 (** {2 Handling \result} *)
-- 
GitLab