From e8abbf7699d67ff742e836a555f416d6e175d8ee Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Loi=CC=88c=20Correnson?= <loic.correnson@cea.fr>
Date: Wed, 21 Aug 2019 15:27:27 +0200
Subject: [PATCH] [wp/region] use mem-loader and mem-memory into mem-typed

---
 src/plugins/wp/Definitions.ml                 |   2 +
 src/plugins/wp/Definitions.mli                |   1 +
 src/plugins/wp/Lang.mli                       |   3 +
 src/plugins/wp/LogicAssigns.ml                |   6 +-
 src/plugins/wp/MemMemory.ml                   |   4 +-
 src/plugins/wp/MemTyped.ml                    | 879 ++++--------------
 src/plugins/wp/MemTyped.mli                   |   8 -
 src/plugins/wp/MemVar.ml                      |  15 +-
 src/plugins/wp/Sigs.ml                        |   2 +-
 src/plugins/wp/TacHavoc.ml                    |  42 +-
 .../tests/wp_bts/oracle/bts_2110.res.oracle   |  18 +-
 .../frama_c_hashtbl_solved.res.oracle         |   4 +-
 .../wp_plugin/oracle/inductive.res.oracle     |   2 +-
 src/plugins/wp/why3_api.ml                    |   3 +-
 14 files changed, 218 insertions(+), 771 deletions(-)

diff --git a/src/plugins/wp/Definitions.ml b/src/plugins/wp/Definitions.ml
index 4d152b904f7..bc8debdd639 100644
--- a/src/plugins/wp/Definitions.ml
+++ b/src/plugins/wp/Definitions.ml
@@ -212,6 +212,8 @@ let newcluster ~id ?title ?position () =
 let cluster ~id ?title ?position () =
   Cluster.memoize (fun id -> newcluster ~id ?title ?position ()) id
 
+let dummy () = cluster ~id:"dummy" ()
+
 let axiomatic ax =
   Cluster.memoize
     (fun id ->
diff --git a/src/plugins/wp/Definitions.mli b/src/plugins/wp/Definitions.mli
index 5814a70c952..cd93d34343d 100644
--- a/src/plugins/wp/Definitions.mli
+++ b/src/plugins/wp/Definitions.mli
@@ -28,6 +28,7 @@ open Lang.F
 
 type cluster
 
+val dummy : unit -> cluster
 val cluster : id:string -> ?title:string -> ?position:Filepath.position -> unit -> cluster
 val axiomatic : axiomatic -> cluster
 val section : logic_section -> cluster
diff --git a/src/plugins/wp/Lang.mli b/src/plugins/wp/Lang.mli
index 7ef00de80b2..1dd7541f7db 100644
--- a/src/plugins/wp/Lang.mli
+++ b/src/plugins/wp/Lang.mli
@@ -31,7 +31,10 @@ open Qed.Logic
 
 type library = string
 
+(** Name for external prover.
 
+    In case a Qed.Engine.link is used, [F_subst] patterns
+    are not supported for Why-3. *)
 type 'a infoprover = {
   altergo: 'a;
   why3   : 'a;
diff --git a/src/plugins/wp/LogicAssigns.ml b/src/plugins/wp/LogicAssigns.ml
index 024797e3177..8da52bbfe32 100644
--- a/src/plugins/wp/LogicAssigns.ml
+++ b/src/plugins/wp/LogicAssigns.ml
@@ -53,7 +53,8 @@ struct
     | [] -> Bag.concat (M.Sigma.assigned ~pre:s.pre ~post:s.post D.empty) hs
 
     | [obj,sloc] ->
-        let hs_sloc = Bag.list (M.assigned s obj sloc) in
+        let eq_sloc = M.assigned s obj sloc in
+        let hs_sloc = Bag.list (List.map Cvalues.equation eq_sloc) in
         let hs_sdom = M.Sigma.assigned ~pre:s.pre ~post:s.post (dsloc obj sloc) in
         Bag.concat (Bag.concat hs_sloc hs_sdom) hs
 
@@ -61,7 +62,8 @@ struct
         let sigma = M.Sigma.havoc s.post (dsloc obj sloc) in
         let s_local = { pre = sigma ; post = s.post } in
         let s_other = { pre = s.pre ; post = sigma } in
-        let hs_sloc = Bag.list (M.assigned s_local obj sloc) in
+        let eq_sloc = M.assigned s_local obj sloc in
+        let hs_sloc = Bag.list (List.map Cvalues.equation eq_sloc) in
         assigned_seq (Bag.concat hs_sloc hs) s_other tail
 
   let apply_assigns (s:sigma sequence) (r: M.loc Sigs.region) =
diff --git a/src/plugins/wp/MemMemory.ml b/src/plugins/wp/MemMemory.ml
index 8568209bc57..1ea1e473997 100644
--- a/src/plugins/wp/MemMemory.ml
+++ b/src/plugins/wp/MemMemory.ml
@@ -35,12 +35,12 @@ let a_addr = Lang.datatype ~library "addr"
 let t_addr = L.Data(a_addr,[])
 let f_base   = Lang.extern_f ~library ~result:L.Int
     ~link:{altergo = Qed.Engine.F_subst("%1.base");
-           why3    = Qed.Engine.F_subst("%1.base");
+           why3    = Qed.Engine.F_call "base";
            coq     = Qed.Engine.F_subst("(base %1)");
           } "base"
 let f_offset = Lang.extern_f ~library ~result:L.Int
     ~link:{altergo = Qed.Engine.F_subst("%1.offset");
-           why3    = Qed.Engine.F_subst("%1.offset");
+           why3    = Qed.Engine.F_call "offset";
            coq     = Qed.Engine.F_subst("(offset %1)");
           } "offset"
 let f_shift  = Lang.extern_f ~library ~result:t_addr "shift"
diff --git a/src/plugins/wp/MemTyped.ml b/src/plugins/wp/MemTyped.ml
index 414d5f49fcf..c93c76e5288 100644
--- a/src/plugins/wp/MemTyped.ml
+++ b/src/plugins/wp/MemTyped.ml
@@ -31,63 +31,38 @@ open Lang
 open Lang.F
 open Sigs
 open Definitions
+open MemMemory
 
 let dkey_layout = Wp_parameters.register_category "layout"
 
 module L = Qed.Logic
 
+(* -------------------------------------------------------------------------- *)
+(* --- Model Configuration                                                --- *)
+(* -------------------------------------------------------------------------- *)
+
 let datatype = "MemTyped"
 let hypotheses () = []
-let library = "memory"
-
-let a_addr = Lang.datatype ~library "addr"
-let t_addr = L.Data(a_addr,[])
-let f_base   = Lang.extern_f ~library ~result:L.Int
-    ~link:{altergo = Qed.Engine.F_subst("%1.base");
-           why3    = Qed.Engine.F_call("base");
-           coq     = Qed.Engine.F_subst("(base %1)");
-          } "base"
-let f_offset = Lang.extern_f ~library ~result:L.Int
-    ~link:{altergo = Qed.Engine.F_subst("%1.offset");
-           why3    = Qed.Engine.F_call("offset");
-           coq     = Qed.Engine.F_subst("(offset %1)");
-          } "offset"
-let f_shift  = Lang.extern_f ~library ~result:t_addr "shift"
-let f_global = Lang.extern_f ~library ~result:t_addr ~category:L.Injection "global"
-let f_null   = Lang.extern_f ~library ~result:t_addr "null"
-let f_base_offset = Lang.extern_f ~library ~category:Qed.Logic.Injection ~result:L.Int "base_offset"
-
-let ty_havoc = function
-  | Some l :: _ -> l
-  | _ -> raise Not_found
+let configure () =
+  begin
+    Context.set Lang.pointer (fun _ -> t_addr) ;
+    Context.set Cvalues.null (p_equal a_null) ;
+  end
 
-let l_havoc = Qed.Engine.{
-    coq = F_call "fhavoc" ;
-    altergo = F_call "havoc" ;
-    why3 = F_call "havoc" ;
-  }
-
-let p_valid_rd = Lang.extern_fp ~library "valid_rd"
-let p_valid_rw = Lang.extern_fp ~library "valid_rw"
-let p_invalid = Lang.extern_fp ~library "invalid"
-let p_separated = Lang.extern_fp ~library "separated"
-let p_included = Lang.extern_fp ~library "included"
-let p_eqmem = Lang.extern_fp ~library "eqmem"
-let f_havoc = Lang.extern_f ~library ~typecheck:ty_havoc ~link:l_havoc "havoc"
-let f_region = Lang.extern_f ~library ~result:L.Int "region" (* base -> region *)
-let p_framed = Lang.extern_fp ~library "framed" (* m-pointer -> prop *)
-let p_linked = Lang.extern_fp ~library "linked" (* allocation-table -> prop *)
-let p_sconst = Lang.extern_fp ~library "sconst" (* int-memory -> prop *)
-let a_lt = Lang.extern_p ~library ~bool:"addr_lt_bool" ~prop:"addr_lt" ()
-let a_leq = Lang.extern_p ~library ~bool:"addr_le_bool" ~prop:"addr_le" ()
-
-let a_addr_of_int = Lang.extern_f
-    ~category:L.Injection
-    ~library ~result:t_addr "addr_of_int"
-
-let a_int_of_addr = Lang.extern_f
-    ~category:L.Injection
-    ~library ~result:L.Int "int_of_addr"
+let configure_ia =
+  let no_binder = { bind = fun _ f v -> f v } in
+  fun _vertex -> no_binder
+
+(* -------------------------------------------------------------------------- *)
+(* --- Model Parameters                                                   --- *)
+(* -------------------------------------------------------------------------- *)
+
+type pointer = NoCast | Fits | Unsafe
+let pointer = Context.create "MemTyped.pointer"
+
+(* -------------------------------------------------------------------------- *)
+(* --- Model Semantics                                                    --- *)
+(* -------------------------------------------------------------------------- *)
 
 (*
 
@@ -132,270 +107,6 @@ let a_int_of_addr = Lang.extern_f
 
 *)
 
-(* -------------------------------------------------------------------------- *)
-(* --- Utilities                                                          --- *)
-(* -------------------------------------------------------------------------- *)
-
-let a_null = F.constant (e_fun f_null [])
-let a_base p = e_fun f_base [p]
-let a_offset p = e_fun f_offset [p]
-let a_global b = e_fun f_global [b]
-let a_base_offset k = e_fun f_base_offset [k]
-let a_shift l k = e_fun f_shift [l;k]
-let a_addr b k = a_shift (a_global b) k
-
-(* -------------------------------------------------------------------------- *)
-(* --- Qed Simplifiers                                                    --- *)
-(* -------------------------------------------------------------------------- *)
-
-(*
-    Pointer arithmetic for structure access and array access could be
-    defined directly using the record [{ base = p.base; offset = p.offset
-    + c*i + c' }]. However that gives very bad triggers for the memory
-    model axiomatization, so `shift p (c*i+c')` was used instead. It is
-    not sufficient for user axiomatisation because memory access in
-    axioms require trigger with arithmetic operators which is badly
-    handled by provers. So for each c and c', ie for each kind of
-    structure access and array access a specific function is used
-    `shift_xxx`.
-
-    Moreover no simplification of `shift_xxx` is done for keeping the
-    same terms in axioms and the goal. `base` and `offset` function
-    simplify all the `shift_xxx` because it seems they don't appear
-    often in axioms and they are useful for simplifying `separated`,
-    `assigns` and pointer comparisons in goals.
-
-    To sum up memory access should match, but not `\base`, `\offset`,
-    `\separated`, ...
-*)
-
-type registered_shift =
-  | RS_Field of fieldinfo * term (* offset of the field *)
-  | RS_Shift of Z.t  (* size of the element *)
-
-module RegisterShift = Model.Static
-    (struct
-      type key = lfun
-      type data = registered_shift
-      let name = "MemTyped.RegisterShift"
-      include Lang.Fun
-    end)
-
-let phi_base l =
-  match F.repr l with
-  | L.Fun(f,p::_) when RegisterShift.mem f -> a_base p
-  | L.Fun(f,[p;_]) when f==f_shift -> a_base p
-  | L.Fun(f,[b]) when f==f_global -> b
-  | L.Fun(f,[]) when f==f_null -> e_zero
-  | _ -> raise Not_found
-
-let phi_offset l = match F.repr l with
-  | L.Fun(f,[p;k]) when f==f_shift -> e_add (a_offset p) k
-  | L.Fun(f,_) when f==f_global || f==f_null -> F.e_zero
-  | L.Fun(f,p::args) ->
-      begin match RegisterShift.get f, args with
-        | Some (RS_Field(_,offset)), [] -> e_add offset (a_offset p)
-        | Some (RS_Shift size), [k] -> e_add (a_offset p) ((F.e_times size) k)
-        | Some _, _ -> assert false (* constructed at one place only *)
-        | None, _ -> raise Not_found
-      end
-  | _ -> raise Not_found
-
-let eq_shift a b =
-  let p = a_base a in
-  let q = a_base b in
-  let i = a_offset a in
-  let j = a_offset b in
-  if i==j then F.p_equal p q else
-    match F.is_equal p q with
-    | L.No -> F.p_false
-    | L.Yes -> F.p_equal i j
-    | L.Maybe -> raise Not_found
-
-let phi_shift f p i =
-  match F.repr p with
-  | L.Fun(g,[q;j]) when f == g -> F.e_fun f [q;F.e_add i j]
-  | _ -> raise Not_found
-
-(* -------------------------------------------------------------------------- *)
-(* --- Simplifier for 'separated'                                         --- *)
-(* -------------------------------------------------------------------------- *)
-
-(*
-logic a : int
-logic b : int
-logic S : prop
-
-predicate separated = a <= 0 or b <= 0 or S
-*)
-
-let r_separated = function
-  | [p;a;q;b] ->
-      if a == F.e_one && b == F.e_one then F.e_neq p q
-      else
-        begin
-          let a_negative = F.e_leq a F.e_zero in
-          let b_negative = F.e_leq b F.e_zero in
-          if a_negative == e_true || b_negative == e_true then e_true else
-            let bp = a_base p in
-            let bq = a_base q in
-            let open Qed.Logic in
-            match F.is_true (F.e_eq bp bq) with
-            | No -> e_true (* Have S *)
-            | Yes when (a_negative == e_false && b_negative == e_false) ->
-                (* Reduced to S *)
-                let p_ofs = a_offset p in
-                let q_ofs = a_offset q in
-                let p_ofs' = F.e_add p_ofs a in
-                let q_ofs' = F.e_add q_ofs b in
-                F.e_or [ F.e_leq q_ofs' p_ofs ;
-                         F.e_leq p_ofs' q_ofs ]
-            | _ -> raise Not_found
-        end
-  | _ -> raise Not_found
-
-let is_separated args = F.is_true (r_separated args)
-
-(* -------------------------------------------------------------------------- *)
-(* --- Simplifier for 'included'                                          --- *)
-(* -------------------------------------------------------------------------- *)
-
-(*
-logic a : int
-logic b : int
-
-predicate R =     p.base = q.base
-              /\ (q.offset <= p.offset)
-              /\ (p.offset + a <= q.offset + b)
-
-predicate included = 0 < a -> ( 0 <= b and R )
-predicate a_empty = a <= 0
-predicate b_negative = b < 0
-
-lemma SAME_P: p=q -> (R <-> a<=b)
-lemma SAME_A: a=b -> (R <-> p=q)
-
-goal INC_P:  p=q -> (included <-> ( 0 < a -> a <= b )) (by SAME_P)
-goal INC_A:  a=b -> 0 < a -> (included <-> R) (by SAME_A)
-goal INC_1:  a_empty -> (included <-> true)
-goal INC_2:  b_negative -> (included <-> a_empty)
-goal INC_3:  not R -> (included <-> a_empty)
-goal INC_4:  not a_empty -> not b_negative -> (included <-> R)
-*)
-
-let r_included = function
-  | [p;a;q;b] ->
-      if F.e_eq p q == F.e_true
-      then F.e_imply [F.e_lt F.e_zero a] (F.e_leq a b) (* INC_P *)
-      else
-      if (F.e_eq a b == F.e_true) && (F.e_lt F.e_zero a == F.e_true)
-      then F.e_eq p q (* INC_A *)
-      else
-        begin
-          let a_empty = F.e_leq a F.e_zero in
-          let b_negative = F.e_lt b F.e_zero in
-          if a_empty == F.e_true then F.e_true (* INC_1 *) else
-          if b_negative == F.e_true then a_empty (* INC_2 *) else
-            let bp = a_base p in
-            let bq = a_base q in
-            let open Qed.Logic in
-            match F.is_true (F.e_eq bp bq) with
-            | No -> a_empty (* INC_3 *)
-            | Yes when (a_empty == e_false && b_negative == e_false) ->
-                (* INC_4 *)
-                let p_ofs = a_offset p in
-                let q_ofs = a_offset q in
-                if a == b then F.e_eq p_ofs q_ofs
-                else
-                  let p_ofs' = e_add p_ofs a in
-                  let q_ofs' = e_add q_ofs b in
-                  e_and [ F.e_leq q_ofs p_ofs ; F.e_leq p_ofs' q_ofs' ]
-            | _ -> raise Not_found
-        end
-  | _ -> raise Not_found
-
-(* -------------------------------------------------------------------------- *)
-(* --- Simplifier for 'havoc'                                             --- *)
-(* -------------------------------------------------------------------------- *)
-
-(* havoc(m_undef, havoc(_undef,m0,p0,a0), p1,a1) =
-   - havoc(m_undef, m0, p1,a1) WHEN included (p1,a1,p0,a0) *)
-let r_havoc = function
-  | [undef1;m1;p1;a1] -> begin
-      match F.repr m1 with
-      | L.Fun( f , [_undef0;m0;p0;a0] ) when f == f_havoc -> begin
-          let open Qed.Logic in
-          match F.is_true (r_included [p0;a0;p1;a1]) with
-          | Yes -> F.e_fun f_havoc [undef1;m0;p1;a1]
-          | _ -> raise Not_found
-        end
-      | _ -> raise Not_found
-    end
-  | _ -> raise Not_found
-
-(* havoc(undef,m,p,a)[k] =
-   - undef[k]      WHEN separated (p,a,k,1)
-   - m[k]  WHEN NOT separated (p,a,k,1)
-*)
-let r_get_havoc = function
-  | [undef;m;p;a] ->
-      (fun _ k ->
-         match is_separated [p;a;k;e_one] with
-         | L.Yes -> F.e_get m k
-         | L.No  -> F.e_get undef k
-         | _ -> raise Not_found)
-  | _ -> raise Not_found
-
-(* -------------------------------------------------------------------------- *)
-(* --- Simplifier for int/addr conversion                                 --- *)
-(* -------------------------------------------------------------------------- *)
-
-let phi_int_of_addr p =
-  if p == a_null then F.e_zero else
-    match F.repr p with
-    | L.Fun(f,[a]) when f == a_addr_of_int -> a
-    | _ -> raise Not_found
-
-let phi_addr_of_int p =
-  if p == F.e_zero then a_null else
-    match F.repr p with
-    | L.Fun(f,[a]) when f == a_int_of_addr -> a
-    | _ -> raise Not_found
-
-(* -------------------------------------------------------------------------- *)
-(* --- Simplifier Registration                                            --- *)
-(* -------------------------------------------------------------------------- *)
-
-let () = Context.register
-    begin fun () ->
-      F.set_builtin_1   f_base   phi_base ;
-      F.set_builtin_1   f_offset phi_offset ;
-      F.set_builtin_2   f_shift  (phi_shift f_shift) ;
-      F.set_builtin_eqp f_shift  eq_shift ;
-      F.set_builtin_eqp f_global eq_shift ;
-      F.set_builtin p_separated r_separated ;
-      F.set_builtin p_included  r_included ;
-      F.set_builtin f_havoc r_havoc ;
-      F.set_builtin_get f_havoc r_get_havoc ;
-      F.set_builtin_1 a_addr_of_int phi_addr_of_int ;
-      F.set_builtin_1 a_int_of_addr phi_int_of_addr ;
-    end
-
-(* -------------------------------------------------------------------------- *)
-(* --- Model Parameters                                                   --- *)
-(* -------------------------------------------------------------------------- *)
-
-let configure () =
-  begin
-    Context.set Lang.pointer (fun _ -> t_addr) ;
-    Context.set Cvalues.null (p_equal a_null) ;
-  end
-let no_binder = { bind = fun _ f v -> f v }
-let configure_ia _ = no_binder
-
-type pointer = NoCast | Fits | Unsafe
-let pointer = Context.create "MemTyped.pointer"
-
 (* -------------------------------------------------------------------------- *)
 (* --- Chunks                                                             --- *)
 (* -------------------------------------------------------------------------- *)
@@ -430,9 +141,6 @@ struct
   let compare a b = rank a - rank b
   let equal = (=)
   let pretty fmt c = Format.pp_print_string fmt (name c)
-  let key_of_chunk = function
-    | M_int | M_char | M_f32 | M_f64 | M_pointer -> t_addr
-    | T_alloc -> L.Int
   let val_of_chunk = function
     | M_int | M_char -> L.Int
     | M_f32 -> Cfloat.tau_of_float Ctypes.Float32
@@ -474,24 +182,13 @@ and footprint_comp c =
        Heap.Set.union ft (footprint (object_of f.ftype))
     ) Heap.Set.empty c.cfields
 
-let signature ft =
-  let s = Sigma.create () in
-  let xs = ref [] in
-  let cs = ref [] in
-  Heap.Set.iter
-    (fun c ->
-       cs := c :: !cs ;
-       xs := (Sigma.get s c) :: !xs ;
-    ) ft ;
-  List.rev !xs , List.rev !cs , s
-
-let memories sigma ft = List.map (Sigma.value sigma) ft
+let domain obj _l = footprint obj
 
-let rec size_of_object = function
+let rec length_of_object = function
   | C_int _ | C_float _ | C_pointer _ -> 1
-  | C_comp c -> size_of_comp c
+  | C_comp c -> length_of_comp c
   | C_array { arr_flat = Some { arr_size = n } ; arr_element = elt } ->
-      n * (size_of_typ elt)
+      n * (length_of_typ elt)
   | C_array _ as a ->
       if Wp_parameters.ExternArrays.get () then
         max_int
@@ -499,20 +196,20 @@ let rec size_of_object = function
         Warning.error ~source:"Typed Model"
           "Undefined array-size (%a)" Ctypes.pretty a
 
-and size_of_typ t = size_of_object (object_of t)
-and size_of_field f = size_of_typ f.ftype
-and size_of_comp c =
+and length_of_typ t = length_of_object (object_of t)
+and length_of_field f = length_of_typ f.ftype
+and length_of_comp c =
   (* union field are considered as struct field *)
   List.fold_left
-    (fun s f -> s + size_of_field f)
+    (fun s f -> s + length_of_field f)
     0 c.cfields
 
-let offset_of_field f =
+let position_of_field f =
   let rec fnext k f = function
     | [] -> assert false
     | g::gs ->
         if Fieldinfo.equal f g then k
-        else fnext (k + size_of_field g) f gs
+        else fnext (k + length_of_field g) f gs
   in fnext 0 f f.fcomp.cfields
 
 (* -------------------------------------------------------------------------- *)
@@ -531,15 +228,32 @@ let occurs x l = F.occurs x l
 (* --- Generated Axiomatization                                           --- *)
 (* -------------------------------------------------------------------------- *)
 
-let loadrec = ref (fun _ _ _ -> assert false)
-
 let cluster_globals () =
   Definitions.cluster ~id:"Globals" ~title:"Global Variables" ()
 
-let cluster_memory () =
-  Definitions.cluster ~id:"Compound" ~title:"Memory Compound Updates" ()
+type shift =
+  | RS_Field of fieldinfo * int (* offset of the field *)
+  | RS_Index of int  (* size of the shift *)
 
-let cluster_dummy () = Definitions.cluster ~id:"dummy" ()
+let phi_base = function
+  | p::_ -> a_base p
+  | _ -> raise Not_found
+
+let phi_field offset = function
+  | [p] -> e_add (a_offset p) (F.e_int offset)
+  | _ -> raise Not_found
+
+let phi_index size = function
+  | [p;k] -> e_add (a_offset p) (F.e_fact size k)
+  | _ -> raise Not_found
+
+module RegisterShift = Model.Static
+    (struct
+      type key = lfun
+      type data = shift
+      let name = "MemTyped.RegisterShift"
+      include Lang.Fun
+    end)
 
 module ShiftFieldDef = Model.StaticGenerator(Cil_datatype.Fieldinfo)
     (struct
@@ -550,19 +264,19 @@ module ShiftFieldDef = Model.StaticGenerator(Cil_datatype.Fieldinfo)
       let generate f =
         let result = t_addr in
         let lfun = Lang.generated_f ~result "shiftfield_%s" (Lang.field_id f) in
-        let offset = (F.e_int (offset_of_field f)) in
+        let position = position_of_field f in
         (* Since its a generated it is the unique name given *)
         let xloc = Lang.freshvar ~basename:"p" t_addr in
         let loc = e_var xloc in
-        let def = a_shift loc offset in
+        let def = a_shift loc (F.e_int position) in
         let dfun = Definitions.Function( result , Def , def) in
-        RegisterShift.define lfun (RS_Field(f,offset)) ;
-        F.set_builtin_eqp lfun eq_shift ;
+        RegisterShift.define lfun (RS_Field(f,position)) ;
+        MemMemory.register ~base:phi_base ~offset:(phi_field position) lfun ;
         {
           d_lfun = lfun ; d_types = 0 ;
           d_params = [xloc] ;
           d_definition = dfun ;
-          d_cluster = cluster_dummy () ;
+          d_cluster = Definitions.dummy () ;
         }
 
       let compile = Lang.local generate
@@ -575,7 +289,7 @@ module ShiftField = Model.Generator(Cil_datatype.Fieldinfo)
       type data = lfun
       let compile fd =
         let dfun = ShiftFieldDef.get fd in
-        let d_cluster = cluster_memory () in
+        let d_cluster = MemLoader.cluster () in
         Definitions.define_symbol { dfun with d_cluster } ;
         dfun.d_lfun
     end)
@@ -611,22 +325,22 @@ module ShiftGen = Model.StaticGenerator(Cobj)
       let generate obj =
         let result = t_addr in
         let shift = Lang.generated_f ~result "shift_%s" (c_object_id obj) in
-        let size = Integer.of_int (size_of_object obj) in
+        let size = length_of_object obj in
         (* Since its a generated it is the unique name given *)
         let xloc = Lang.freshvar ~basename:"p" t_addr in
         let loc = e_var xloc in
         let xk = Lang.freshvar ~basename:"k" Qed.Logic.Int in
         let k = e_var xk in
-        let def = a_shift loc (F.e_times size k) in
+        let def = a_shift loc (F.e_fact size k) in
         let dfun = Definitions.Function( result , Def , def) in
-        RegisterShift.define shift (RS_Shift size) ;
-        F.set_builtin_eqp shift eq_shift ;
-        F.set_builtin_2 shift (phi_shift shift) ;
+        RegisterShift.define shift (RS_Index size) ;
+        MemMemory.register ~base:phi_base ~offset:(phi_index size)
+          ~linear:true shift ;
         {
           d_lfun = shift ; d_types = 0 ;
           d_params = [xloc;xk] ;
           d_definition = dfun ;
-          d_cluster = cluster_dummy () ;
+          d_cluster = Definitions.dummy () ;
         }
 
       let compile = Lang.local generate
@@ -640,7 +354,7 @@ module Shift = Model.Generator(Cobj)
       type data = lfun
       let compile obj =
         let dfun = ShiftGen.get obj in
-        let d_cluster = cluster_memory () in
+        let d_cluster = MemLoader.cluster () in
         Definitions.define_symbol { dfun with d_cluster } ;
         dfun.d_lfun
     end)
@@ -740,6 +454,10 @@ module STRING = Model.Generator(LITERAL)
 
     end)
 
+(* -------------------------------------------------------------------------- *)
+(* --- Base Registration                                                  --- *)
+(* -------------------------------------------------------------------------- *)
+
 module RegisterBASE = Model.Static
     (struct
       type key = lfun
@@ -764,22 +482,20 @@ module BASE = Model.Generator(Varinfo)
           l_cluster = cluster_globals () ;
         }
 
+      let sizeof x =
+        Warning.handle
+          ~handler:(fun _ -> None)
+          ~effect:(Printf.sprintf "No allocation size for variable '%s'" x.vname)
+          (fun obj -> Some (length_of_object obj))
+          (Ctypes.object_of x.vtype)
+
       let linked prefix x base =
         let name = prefix ^ "_linked" in
-        let obj = Ctypes.object_of x.vtype in
-        let size =
-          if x.vglob then
-            Warning.handle
-              ~handler:(fun _ -> None)
-              ~effect:(Printf.sprintf "No allocation size for variable '%s'" x.vname)
-              (fun obj -> Some (size_of_object obj))
-              obj
-          else Some 0
-        in
+        let size = if x.vglob then sizeof x else Some 0 in
         match size with
         | None -> ()
         | Some size ->
-            let a = Lang.freshvar ~basename:"alloc" (Chunk.tau_of_chunk T_alloc) in
+            let a = Lang.freshvar ~basename:"alloc" t_malloc in
             let m = e_var a in
             let m_linked = p_call p_linked [m] in
             let base_size = p_equal (F.e_get m base) (e_int size) in
@@ -817,215 +533,6 @@ module BASE = Model.Generator(Varinfo)
       let compile = Lang.local generate
     end)
 
-
-(* Add frame lemmas for generated logical function *)
-module MONOTONIC :
-sig
-  val generate :
-    string -> lfun -> var list -> chunk list -> (term list -> term) -> unit
-end =
-struct
-
-  type env = {
-    lfun : lfun ;
-    sigma : sigma ;
-    vars : var list ;
-    params : term list ;
-    range : term ;
-    chunks : chunk list ;
-    memories : term list ;
-  }
-
-  let _cluster () = Definitions.cluster ~id:"TypedMemory" ()
-  (* projectified *)
-
-  let update env c m  =
-    List.map
-      (fun c' ->
-         if Chunk.equal c c' then m else Sigma.value env.sigma c'
-      ) env.chunks
-
-  let separated env q k = F.p_call p_separated [List.hd env.params;env.range;q;k]
-  let included env q k = F.p_call p_included [List.hd env.params;env.range;q;k]
-
-  let generate_update prefix env c =
-    let name = prefix ^ "_update_" ^ Chunk.name c in
-    let q = e_var (Lang.freshvar ~basename:"q" (Chunk.key_of_chunk c)) in
-    let v = e_var (Lang.freshvar ~basename:"v" (Chunk.val_of_chunk c)) in
-    let phi = e_fun env.lfun (env.params @ env.memories) in
-    let mem' = e_set (Sigma.value env.sigma c) q v in
-    let phi' = e_fun env.lfun (env.params @ update env c mem') in
-    let lemma = p_imply (separated env q e_one) (p_equal phi' phi) in
-    Definitions.define_lemma {
-      l_assumed = true ;
-      l_name = name ; l_types = 0 ;
-      l_triggers = [[Trigger.of_term phi']] ;
-      l_forall = F.p_vars lemma ;
-      l_lemma = lemma ;
-      l_cluster = cluster_memory () ;
-    }
-
-  let generate_eqmem prefix env c =
-    let name = prefix  ^ "_eqmem_" ^ Chunk.name c in
-    let q = e_var (Lang.freshvar ~basename:"q" (Chunk.key_of_chunk c)) in
-    let k = e_var (Lang.freshvar ~basename:"k" L.Int) in
-    let phi = e_fun env.lfun (env.params @ env.memories) in
-    let mem = Sigma.value env.sigma c in
-    let mem' = e_var (Lang.freshen (Sigma.get env.sigma c)) in
-    let phi' = e_fun env.lfun (env.params @ update env c mem') in
-    let eqmem = F.p_call p_eqmem [mem;mem';q;k] in
-    let lemma = p_hyps [included env q k;eqmem] (p_equal phi' phi) in
-    Definitions.define_lemma {
-      l_assumed = true ;
-      l_name = name ; l_types = 0 ;
-      l_triggers = [
-        [Trigger.of_pred eqmem ; Trigger.of_term phi ] ;
-        [Trigger.of_pred eqmem ; Trigger.of_term phi'] ;
-      ] ;
-      l_forall = F.p_vars lemma ;
-      l_lemma = lemma ;
-      l_cluster = cluster_memory () ;
-    }
-
-  let generate_havoc prefix env c =
-    let name = prefix ^ "_havoc_" ^ Chunk.name c in
-    let q = e_var (Lang.freshvar ~basename:"q" (Chunk.key_of_chunk c)) in
-    let k = e_var (Lang.freshvar ~basename:"k" L.Int) in
-    let phi = e_fun env.lfun (env.params @ env.memories) in
-    let mem = Sigma.value env.sigma c in
-    let mem' = e_var (Lang.freshen (Sigma.get env.sigma c)) in
-    let m_undef = e_var (Lang.freshen (Sigma.get env.sigma c)) in
-    let phi' = e_fun env.lfun (env.params @ update env c mem') in
-    let havoc = p_equal mem' (F.e_fun f_havoc [m_undef;mem;q;k]) in
-    let lemma = p_hyps [separated env q k;havoc] (p_equal phi' phi) in
-    Definitions.define_lemma {
-      l_assumed = true ;
-      l_name = name ; l_types = 0 ;
-      l_triggers = [
-        [ Trigger.of_pred havoc ; Trigger.of_term phi ] ;
-        [ Trigger.of_pred havoc ; Trigger.of_term phi'] ;
-      ] ;
-      l_forall = F.p_vars lemma ;
-      l_lemma = lemma ;
-      l_cluster = cluster_memory () ;
-    }
-
-  let generate prefix lfun xs cs range =
-    let sigma = Sigma.create () in
-    let xp = Lang.freshvar ~basename:"p" t_addr in
-    let xs = List.map Lang.freshen xs in
-    let ps = List.map e_var xs in
-    let ms = memories sigma cs in
-    let env = {
-      sigma = sigma ; lfun = lfun ;
-      vars = xp::xs ; params = e_var xp::ps ;
-      chunks = cs ; memories = ms ;
-      range = range ps ;
-    } in
-    List.iter
-      (fun chunk ->
-         generate_update prefix env chunk ;
-         generate_eqmem prefix env chunk ;
-         generate_havoc prefix env chunk ;
-      ) cs
-
-end
-
-module COMP = Model.Generator(Compinfo)
-    (struct
-      let name = "MemTyped.COMP"
-      type key = compinfo
-      type data = lfun * chunk list
-
-      let generate c =
-        let result = Lang.tau_of_comp c in
-        let lfun = Lang.generated_f ~result "Load_%s" (Lang.comp_id c) in
-        (* Since its a generated it is the unique name given *)
-        let prefix = Lang.Fun.debug lfun in
-        let xmem,ft,sigma = signature (footprint_comp c) in
-        let xloc = Lang.freshvar ~basename:"p" t_addr in
-        let loc = e_var xloc in
-        let def = List.map
-            (fun f ->
-               Cfield f , !loadrec sigma (object_of f.ftype) (field loc f)
-            ) c.cfields in
-        let dfun = Definitions.Function( result , Def , e_record def ) in
-        Definitions.define_symbol {
-          d_lfun = lfun ; d_types = 0 ;
-          d_params = xloc :: xmem ;
-          d_definition = dfun ;
-          d_cluster = cluster_memory () ;
-        } ;
-        let range = e_int (size_of_comp c) in
-        MONOTONIC.generate prefix lfun [] ft (fun _ -> range) ;
-        lfun , ft
-
-      let compile = Lang.local generate
-    end)
-
-module ARRAY = Model.Generator(Matrix.NATURAL)
-    (struct
-      open Matrix
-      let name = "MemTyped.ARRAY"
-      type key = matrix
-      type data = lfun * chunk list
-
-      let generate (obj,ds) =
-        let result = Matrix.tau obj ds in
-        let lfun = Lang.generated_f ~result "Array%s_%s"
-            (Matrix.id ds) (Matrix.natural_id obj) in
-        let prefix = Lang.Fun.debug lfun in
-        let axiom = prefix ^ "_access" in
-        let xmem,ft,sigma = signature (footprint obj) in
-        let xloc = Lang.freshvar ~basename:"p" t_addr in
-        let loc = e_var xloc in
-        let denv = Matrix.denv ds in
-        let phi = e_fun lfun (loc :: denv.size_val @ List.map e_var xmem) in
-        let arr = List.fold_left e_get phi denv.index_val in
-        let elt = !loadrec sigma obj (shift loc obj (e_sum denv.index_offset)) in
-        let lemma = p_hyps denv.index_range (p_equal arr elt) in
-        let cluster = cluster_memory () in
-        Definitions.define_symbol {
-          d_lfun = lfun ; d_types = 0 ;
-          d_params = xloc :: denv.size_var @ xmem ;
-          d_definition = Logic result ;
-          d_cluster = cluster ;
-        } ;
-        Definitions.define_lemma {
-          l_assumed = true ;
-          l_name = axiom ; l_types = 0 ;
-          l_forall = F.p_vars lemma ;
-          l_triggers = [[Trigger.of_term arr]] ;
-          l_lemma = lemma ;
-          l_cluster = cluster ;
-        } ;
-        if denv.monotonic then
-          MONOTONIC.generate prefix lfun denv.size_var ft F.e_prod ;
-        lfun , ft
-
-      let compile = Lang.local generate
-    end)
-
-(* -------------------------------------------------------------------------- *)
-(* --- Loading Elementary Values                                          --- *)
-(* -------------------------------------------------------------------------- *)
-
-let loadvalue sigma obj l = match obj with
-  | C_int i -> F.e_get (Sigma.value sigma (m_int i)) l
-  | C_float f -> F.e_get (Sigma.value sigma (m_float f)) l
-  | C_pointer _ -> F.e_get (Sigma.value sigma M_pointer) l
-  | C_comp c ->
-      let phi,cs = COMP.get c in
-      e_fun phi (l :: memories sigma cs)
-  | C_array a ->
-      let m = Matrix.of_array a in
-      let phi,cs = ARRAY.get m in
-      e_fun phi ( l :: Matrix.size m @ memories sigma cs )
-
-let () = loadrec := loadvalue
-
-let load sigma obj l = Val (loadvalue sigma obj l)
-
 (* -------------------------------------------------------------------------- *)
 (* --- Locations                                                          --- *)
 (* -------------------------------------------------------------------------- *)
@@ -1045,13 +552,12 @@ let cvar x =
 let pointer_loc t = t
 let pointer_val t = t
 
-let get_alloc sigma l = F.e_get (Sigma.value sigma T_alloc) (a_base l)
-let get_last sigma l = e_add (get_alloc sigma l) e_minus_one
+let allocated sigma l = F.e_get (Sigma.value sigma T_alloc) (a_base l)
 
 let base_addr l = a_addr (a_base l) e_zero
 let base_offset l = a_base_offset (a_offset l)
 let block_length sigma obj l =
-  e_fact (Ctypes.sizeof_object obj) (get_alloc sigma l)
+  e_fact (Ctypes.sizeof_object obj) (allocated sigma l)
 
 (* -------------------------------------------------------------------------- *)
 (* --- Cast                                                               --- *)
@@ -1349,99 +855,80 @@ let cast s l =
               "%a" pp_mismatch s ; l
     end
 
-let loc_of_int _ v = F.e_fun a_addr_of_int [v]
-let int_of_loc _ l = F.e_fun a_int_of_addr [l]
+let loc_of_int _ v = F.e_fun f_addr_of_int [v]
+let int_of_loc _ l = F.e_fun f_int_of_addr [l]
 
 (* -------------------------------------------------------------------------- *)
-(* --- Updates                                                            --- *)
+(* --- Frames                                                             --- *)
 (* -------------------------------------------------------------------------- *)
 
-let domain obj _l = footprint obj
-
-let updated s c l v =
-  let m1 = Sigma.value s.pre c in
-  let m2 = Sigma.value s.post c in
-  [Set(m2,F.e_set m1 l v)]
-
-let havoc_range s obj l n =
-  let ps = ref [] in
-  Heap.Set.iter
-    (fun c ->
-       let basename = (Chunk.basename_of_chunk c)^"_undef" in
-       let tau = Chunk.tau_of_chunk c in
-       let m_undef = e_var (Lang.freshvar ~basename tau) in
-       let m1 = Sigma.value s.pre c in
-       let m2 = Sigma.value s.post c in
-       ps := (p_equal m2 (F.e_fun f_havoc [m_undef;m1;l;n])) :: !ps
-    ) (footprint obj) ; !ps
-
-let havoc s obj l = havoc_range s obj l (e_int (size_of_object obj))
-
-let eqmem s obj l =
-  let ps = ref [] in
-  let n = e_int (size_of_object obj) in
-  Heap.Set.iter
-    (fun c ->
-       let m1 = Sigma.value s.pre c in
-       let m2 = Sigma.value s.post c in
-       if m1 != m2 then
-         ps := F.p_call p_eqmem [m1;m2;l;n] :: !ps
-    ) (footprint obj) ; !ps
+let frames obj addr = function
+  | T_alloc -> []
+  | m ->
+      let offset = F.e_int (length_of_object obj) in
+      let sizeof = F.e_one in
+      let tau = Chunk.val_of_chunk m in
+      let basename = Chunk.basename_of_chunk m in
+      MemMemory.frames ~addr ~offset ~sizeof ~basename tau
 
 (* -------------------------------------------------------------------------- *)
-(* --- Copy                                                               --- *)
+(* --- Loader                                                             --- *)
 (* -------------------------------------------------------------------------- *)
 
-let stored s obj l v =
-  match obj with
-  | C_int i -> updated s (m_int i) l v
-  | C_float f -> updated s (m_float f) l v
-  | C_pointer _ -> updated s M_pointer l v
-  | C_comp _ | C_array _ ->
-      Set(loadvalue s.post obj l, v) ::
-      (List.map (fun p -> Assert p) (havoc s obj l))
+module MODEL =
+struct
+  module Chunk = Chunk
+  module Sigma = Sigma
+  let name = "MemTyped.LOADER"
+  type nonrec loc = loc
+  let field = field
+  let shift = shift
+  let sizeof = length_of_object
+  let domain = domain
+  let frames = frames
+  let to_addr l = l
+  let to_region_pointer l = 0,l
+  let of_region_pointer _ _ l = l
+
+  let load_int sigma i l = F.e_get (Sigma.value sigma (m_int i)) l
+  let load_float sigma f l = F.e_get (Sigma.value sigma (m_float f)) l
+  let load_pointer sigma _t l = F.e_get (Sigma.value sigma M_pointer) l
+
+  let last sigma obj l =
+    let n = length_of_object obj in
+    e_sub (F.e_div (allocated sigma l) (F.e_int n)) e_one
+
+  let havoc obj loc ~length chunk ~fresh ~current =
+    if chunk <> T_alloc then
+      let n = F.e_fact (length_of_object obj) length in
+      F.e_fun f_havoc [fresh;current;loc;n]
+    else fresh
+
+  let eqmem obj loc _chunk m1 m2 =
+    F.p_call p_eqmem [m1;m2;loc;e_int (length_of_object obj)]
+
+  let eqmem_forall obj loc _chunk m1 m2 =
+    let xp = Lang.freshvar ~basename:"p" t_addr in
+    let p = F.e_var xp in
+    let n = F.e_int (length_of_object obj) in
+    let separated = F.p_call p_separated [p;e_one;loc;n] in
+    let equal = p_equal (e_get m1 p) (e_get m2 p) in
+    [xp],separated,equal
 
-let copied s obj p q = stored s obj p (loadvalue s.pre obj q)
+  let updated sigma c l v = c , F.e_set (Sigma.value sigma c) l v
 
-(* -------------------------------------------------------------------------- *)
-(* --- Assignation                                                        --- *)
-(* -------------------------------------------------------------------------- *)
+  let store_int sigma i l v = updated sigma (m_int i) l v
+  let store_float sigma f l v = updated sigma (m_float f) l v
+  let store_pointer sigma _ty l v = updated sigma M_pointer l v
 
-let assigned_loc s obj l =
-  match obj with
-  | C_int _ | C_float _ | C_pointer _ ->
-      let x = Lang.freshvar ~basename:"v" (Lang.tau_of_object obj) in
-      List.map Cvalues.equation (stored s obj l (e_var x))
-  | C_comp _ | C_array _ ->
-      havoc s obj l
-
-let equal_loc s obj l =
-  match obj with
-  | C_int _ | C_float _ | C_pointer _ ->
-      [p_equal (loadvalue s.pre obj l) (loadvalue s.post obj l)]
-  | C_comp _ | C_array _ -> eqmem s obj l
-
-let assigned_range s obj l a b =
-  let l = shift l obj a in
-  let n = e_fact (size_of_object obj) (e_range a b) in
-  havoc_range s obj l n
-
-let assigned s obj = function
-  | Sloc l -> assigned_loc s obj l
-  | Sdescr(xs,l,p) ->
-      let xa = Lang.freshvar ~basename:"p" t_addr in
-      let la = F.e_var xa in
-      let n = F.e_int (size_of_object obj) in
-      let sep = F.p_call p_separated [la;n;l;n] in
-      let sep_all = F.p_forall xs (F.p_imply p sep) in
-      let eq_loc = F.p_conj (equal_loc s obj la) in
-      [F.p_forall [xa] (F.p_imply sep_all eq_loc)]
-  | Sarray(l,obj,n) ->
-      assigned_range s obj l e_zero (e_int (n-1))
-  | Srange(l,obj,u,v) ->
-      let a = match u with Some a -> a | None -> e_zero in
-      let b = match v with Some b -> b | None -> get_last s.pre l in
-      assigned_range s obj l a b
+end
+
+module LOADER = MemLoader.Make(MODEL)
+
+let load = LOADER.load
+let stored = LOADER.stored
+let copied = LOADER.copied
+let assigned = LOADER.assigned
 
 (* -------------------------------------------------------------------------- *)
 (* --- Loc Comparison                                                     --- *)
@@ -1455,11 +942,11 @@ let loc_compare f_cmp i_cmp p q =
 let is_null l = p_equal l null
 let loc_eq = p_equal
 let loc_neq = p_neq
-let loc_lt = loc_compare a_lt p_lt
-let loc_leq = loc_compare a_leq p_leq
+let loc_lt = loc_compare p_addr_lt p_lt
+let loc_leq = loc_compare p_addr_le p_leq
 let loc_diff obj p q =
   let delta = e_sub (a_offset p) (a_offset q) in
-  let size = e_int (size_of_object obj) in
+  let size = e_int (length_of_object obj) in
   e_div delta size
 
 (* -------------------------------------------------------------------------- *)
@@ -1475,10 +962,10 @@ let s_invalid sigma p n =
 
 let segment phi = function
   | Rloc(obj,l) ->
-      phi l (e_int (size_of_object obj))
+      phi l (e_int (length_of_object obj))
   | Rrange(l,obj,Some a,Some b) ->
       let l = shift l obj a in
-      let n = e_fact (size_of_object obj) (e_range a b) in
+      let n = e_fact (length_of_object obj) (e_range a b) in
       phi l n
   | Rrange(l,_,a,b) ->
       Wp_parameters.abort ~current:true
@@ -1508,7 +995,7 @@ let scope seq scope xs =
         (fun m x ->
            let size = match scope with
              | Sigs.Leave -> 0
-             | Sigs.Enter -> size_of_typ x.vtype
+             | Sigs.Enter -> length_of_typ x.vtype
            in F.e_set m (BASE.get x) (e_int size))
         (Sigma.value seq.pre T_alloc) xs in
     [ p_equal (Sigma.value seq.post T_alloc) alloc ]
@@ -1516,58 +1003,18 @@ let scope seq scope xs =
 let global _sigma p = p_leq (e_fun f_region [a_base p]) e_zero
 
 (* -------------------------------------------------------------------------- *)
-(* --- Domain                                                             --- *)
+(* --- Segments                                                           --- *)
 (* -------------------------------------------------------------------------- *)
 
-type range =
-  | LOC of term * term (* loc - size *)
-  | RANGE of term * Vset.set (* base - range offset *)
+let included =
+  let addrof l = l in
+  let sizeof = length_of_object in
+  MemMemory.included ~shift ~addrof ~sizeof
 
-let range = function
-  | Rloc(obj,l) ->
-      LOC( l , e_int (size_of_object obj) )
-  | Rrange(l,obj,Some a,Some b) ->
-      let l = shift l obj a in
-      let n = e_fact (size_of_object obj) (e_range a b) in
-      LOC( l , n )
-  | Rrange(l,_obj,None,None) ->
-      RANGE( a_base l , Vset.range None None )
-  | Rrange(l,obj,Some a,None) ->
-      let se = size_of_object obj in
-      RANGE( a_base l , Vset.range (Some (e_fact se a)) None )
-  | Rrange(l,obj,None,Some b) ->
-      let se = size_of_object obj in
-      RANGE( a_base l , Vset.range None (Some (e_fact se b)) )
-
-let range_set = function
-  | LOC(l,n) ->
-      let a = a_offset l in
-      let b = e_add a n in
-      a_base l , Vset.range (Some a) (Some b)
-  | RANGE(base,set) -> base , set
-
-let r_included r1 r2 =
-  match r1 , r2 with
-  | LOC(l1,n1) , LOC(l2,n2) ->
-      p_call p_included [l1;n1;l2;n2]
-  | _ ->
-      let base1,set1 = range_set r1 in
-      let base2,set2 = range_set r2 in
-      p_if (p_equal base1 base2)
-        (Vset.subset set1 set2)
-        (Vset.is_empty set1)
-
-let r_disjoint r1 r2 =
-  match r1 , r2 with
-  | LOC(l1,n1) , LOC(l2,n2) ->
-      p_call p_separated [l1;n1;l2;n2]
-  | _ ->
-      let base1,set1 = range_set r1 in
-      let base2,set2 = range_set r2 in
-      p_imply (p_equal base1 base2) (Vset.disjoint set1 set2)
-
-let included s1 s2  = r_included (range s1) (range s2)
-let separated s1 s2 = r_disjoint (range s1) (range s2)
+let separated =
+  let addrof l = l in
+  let sizeof = length_of_object in
+  MemMemory.separated ~shift ~addrof ~sizeof
 
 (* -------------------------------------------------------------------------- *)
 (* --- State Model                                                        --- *)
@@ -1584,7 +1031,7 @@ let rec lookup_a e =
 and lookup_f f es =
   try match RegisterShift.find f , es with
     | RS_Field(fd,_) , [e] -> Mstate.field (lookup_lv e) fd
-    | RS_Shift _ , [e;k] -> Mstate.index (lookup_lv e) k
+    | RS_Index _ , [e;k] -> Mstate.index (lookup_lv e) k
     | _ -> raise Not_found
   with Not_found when es = [] ->
     Sigs.(Mvar (RegisterBASE.find f),[])
diff --git a/src/plugins/wp/MemTyped.mli b/src/plugins/wp/MemTyped.mli
index 6c23647b4fe..5bd5298918c 100644
--- a/src/plugins/wp/MemTyped.mli
+++ b/src/plugins/wp/MemTyped.mli
@@ -28,11 +28,3 @@ include Sigs.Model
 
 type pointer = NoCast | Fits | Unsafe
 val pointer : pointer Context.value
-val f_havoc : Lang.lfun
-val p_separated : Lang.lfun
-val p_included : Lang.lfun
-val p_valid_rd : Lang.lfun
-val p_valid_rw : Lang.lfun
-val p_invalid : Lang.lfun
-val a_base : Lang.F.term -> Lang.F.term
-val a_offset : Lang.F.term -> Lang.F.term
diff --git a/src/plugins/wp/MemVar.ml b/src/plugins/wp/MemVar.ml
index b4d8a304b5e..58845184bfd 100644
--- a/src/plugins/wp/MemVar.ml
+++ b/src/plugins/wp/MemVar.ml
@@ -1016,14 +1016,15 @@ struct
             let eqk = p_forall (y::ys) (p_imply ek (p_equal ak bk)) in
             assigned_path (eqk :: hs) xs ys ae be ofs
 
-  let assigned_descr s xs mem x ofs p =
+  let assigned_genset s xs mem x ofs p =
     let valid = valid_offset_path s.post Sigs.RW mem x ofs in
     let a = get_term s.pre x in
     let b = get_term s.post x in
     let a_ofs = access a ofs in
     let b_ofs = access b ofs in
     let p_sloc = p_forall xs (p_hyps [valid;p_not p] (p_equal a_ofs b_ofs)) in
-    assigned_path [p_sloc] xs [] a b ofs
+    let conds = assigned_path [p_sloc] xs [] a b ofs in
+    List.map (fun p -> Assert p) conds
 
   (* -------------------------------------------------------------------------- *)
   (* ---  Assigned                                                          --- *)
@@ -1034,8 +1035,7 @@ struct
     | Val((CVAL|CREF),_,[]) -> [] (* full update *)
     | Val((CVAL|CREF),_,_) as vloc ->
         let v = Lang.freshvar ~basename:"v" (Lang.tau_of_object obj) in
-        let eqs = stored seq obj vloc (e_var v) in
-        List.map Cvalues.equation eqs
+        stored seq obj vloc (e_var v)
     | Val((HEAP|CTXT|CARR) as m,x,ofs) ->
         M.assigned (mseq_of_seq seq) obj (Sloc (mloc_of_path m x ofs))
     | Loc l ->
@@ -1048,8 +1048,7 @@ struct
     | Val((CVAL|CREF),_,_) as vloc ->
         let te = Lang.tau_of_object elt in
         let v = Lang.freshvar ~basename:"v" Qed.Logic.(Array(Int,te)) in
-        let eqs = stored seq obj vloc (e_var v) in
-        List.map Cvalues.equation eqs
+        stored seq obj vloc (e_var v)
     | Val((HEAP|CTXT|CARR) as m,x,ofs) ->
         let l = mloc_of_path m x ofs in
         M.assigned (mseq_of_seq seq) obj (Sarray(l,elt,n))
@@ -1067,7 +1066,7 @@ struct
         let k = Lang.freshvar ~basename:"k" Qed.Logic.Int in
         let p = Vset.in_range (e_var k) a b in
         let ofs = ofs_shift elt (e_var k) ofs in
-        assigned_descr seq [k] m x ofs p
+        assigned_genset seq [k] m x ofs p
 
   let assigned_descr seq obj xs l p =
     match l with
@@ -1077,7 +1076,7 @@ struct
     | Val((HEAP|CTXT|CARR) as m,x,ofs) ->
         M.assigned (mseq_of_seq seq) obj (Sdescr(xs,mloc_of_path m x ofs,p))
     | Val((CVAL|CREF) as m,x,ofs) ->
-        assigned_descr seq xs m x ofs p
+        assigned_genset seq xs m x ofs p
 
   let assigned seq obj = function
     | Sloc l -> assigned_loc seq obj l
diff --git a/src/plugins/wp/Sigs.ml b/src/plugins/wp/Sigs.ml
index a91e7770466..add077d6028 100644
--- a/src/plugins/wp/Sigs.ml
+++ b/src/plugins/wp/Sigs.ml
@@ -434,7 +434,7 @@ sig
      location [loc] which is represented by [t] in [sigma.post].
   *)
 
-  val assigned : sigma sequence -> c_object -> loc sloc -> pred list
+  val assigned : sigma sequence -> c_object -> loc sloc -> equation list
   (**
      Return a set of formula that express that two memory state are the same
      except at the given set of memory location.
diff --git a/src/plugins/wp/TacHavoc.ml b/src/plugins/wp/TacHavoc.ml
index 9b7034cc308..9e68996a899 100644
--- a/src/plugins/wp/TacHavoc.ml
+++ b/src/plugins/wp/TacHavoc.ml
@@ -35,7 +35,7 @@ let lookup_havoc e =
   | L.Aget( m , p ) ->
       begin
         match F.repr m with
-        | L.Fun( f , [mr;m0;a;n] ) when f == MemTyped.f_havoc ->
+        | L.Fun( f , [mr;m0;a;n] ) when f == MemMemory.f_havoc ->
             Some( mr , m0 , a , n , p )
         | _ -> None
       end
@@ -55,7 +55,7 @@ class havoc =
       | None -> Not_applicable
       | Some(mr,m0,a,n,p) ->
           let separated =
-            F.p_call MemTyped.p_separated
+            F.p_call MemMemory.p_separated
               [ p ; F.e_int 1 ; a ; n ] in
           let process = Tactical.rewrite ?at [
               "Unassigned" , separated , e , F.e_get m0 p ;
@@ -70,11 +70,11 @@ class havoc =
 
 let separated ?at property =
   match F.e_expr property with
-  | L.Fun( f , [p;n;q;m] ) when f == MemTyped.p_separated ->
-      let base_p = MemTyped.a_base p in
-      let ofs_p = MemTyped.a_offset p in
-      let base_q = MemTyped.a_base q in
-      let ofs_q = MemTyped.a_offset q in
+  | L.Fun( f , [p;n;q;m] ) when f == MemMemory.p_separated ->
+      let base_p = MemMemory.a_base p in
+      let ofs_p = MemMemory.a_offset p in
+      let base_q = MemMemory.a_base q in
+      let ofs_q = MemMemory.a_offset q in
       let eq_base = F.p_equal base_p base_q in
       let on_left = F.p_leq (F.e_add ofs_p n) ofs_q in
       let on_right = F.p_leq (F.e_add ofs_q m) ofs_p in
@@ -110,8 +110,8 @@ class separated =
 (* -------------------------------------------------------------------------- *)
 
 let invalid m p n =
-  let base = MemTyped.a_base p in
-  let offset = MemTyped.a_offset p in
+  let base = MemMemory.a_base p in
+  let offset = MemMemory.a_offset p in
   let malloc = F.e_get m base in
   "Invalid",
   F.p_imply
@@ -121,8 +121,8 @@ let invalid m p n =
        (F.p_leq (F.e_add offset n) F.e_zero))
 
 let valid_rd m p n =
-  let base = MemTyped.a_base p in
-  let offset = MemTyped.a_offset p in
+  let base = MemMemory.a_base p in
+  let offset = MemMemory.a_offset p in
   let malloc = F.e_get m base in
   "Valid (Read)",
   F.p_imply
@@ -132,8 +132,8 @@ let valid_rd m p n =
        (F.p_leq (F.e_add offset n) malloc))
 
 let valid_rw m p n =
-  let base = MemTyped.a_base p in
-  let offset = MemTyped.a_offset p in
+  let base = MemMemory.a_base p in
+  let offset = MemMemory.a_offset p in
   let malloc = F.e_get m base in
   "Valid (Read & Write)",
   F.p_imply
@@ -145,10 +145,10 @@ let valid_rw m p n =
       ])
 
 let included p a q b =
-  let p_base = MemTyped.a_base p in
-  let q_base = MemTyped.a_base q in
-  let p_offset = MemTyped.a_offset p in
-  let q_offset = MemTyped.a_offset q in
+  let p_base = MemMemory.a_base p in
+  let q_base = MemMemory.a_base q in
+  let p_offset = MemMemory.a_offset p in
+  let q_offset = MemMemory.a_offset q in
   "Included",
   F.p_imply
     (F.p_lt F.e_zero a)
@@ -161,10 +161,10 @@ let included p a q b =
          ]))
 
 let lookup f = function
-  | [p;a;q;b] when f == MemTyped.p_included -> included p a q b
-  | [m;p;n] when f == MemTyped.p_invalid -> invalid m p n
-  | [m;p;n] when f == MemTyped.p_valid_rd -> valid_rd m p n
-  | [m;p;n] when f == MemTyped.p_valid_rw -> valid_rw m p n
+  | [p;a;q;b] when f == MemMemory.p_included -> included p a q b
+  | [m;p;n] when f == MemMemory.p_invalid -> invalid m p n
+  | [m;p;n] when f == MemMemory.p_valid_rd -> valid_rd m p n
+  | [m;p;n] when f == MemMemory.p_valid_rw -> valid_rw m p n
   | _ -> raise Not_found
 
 let unfold ?at e f es =
diff --git a/src/plugins/wp/tests/wp_bts/oracle/bts_2110.res.oracle b/src/plugins/wp/tests/wp_bts/oracle/bts_2110.res.oracle
index 9cf4378ece6..feda6936719 100644
--- a/src/plugins/wp/tests/wp_bts/oracle/bts_2110.res.oracle
+++ b/src/plugins/wp/tests/wp_bts/oracle/bts_2110.res.oracle
@@ -66,17 +66,17 @@ theory Compound
      not q = p -> Load_S2_A p (set mint q v) = Load_S2_A p mint
   
   axiom Q_Load_S2_A_eqmem_Mint :
-    forall mint:addr -> int, mint1:addr -> int, k:int, p:addr, q:addr
-     [eqmem mint mint1 q k, Load_S2_A p mint| eqmem mint mint1 q k,
-     Load_S2_A p mint1].
-     included p 1 q k ->
-     eqmem mint mint1 q k -> Load_S2_A p mint1 = Load_S2_A p mint
+    forall mint:addr -> int, mint1:addr -> int, n:int, p:addr, q:addr
+     [Load_S2_A p mint, eqmem mint mint1 q n| Load_S2_A p mint1,
+     eqmem mint mint1 q n].
+     included p 1 q n ->
+     eqmem mint mint1 q n -> Load_S2_A p mint1 = Load_S2_A p mint
   
   axiom Q_Load_S2_A_havoc_Mint :
-    forall mint:addr -> int, mint1:addr -> int, mint2:addr -> int, k:int, p:
-     addr, q:addr [Load_S2_A p mint| Load_S2_A p mint1].
-     havoc mint2 mint q k = mint1 ->
-     separated p 1 q k -> Load_S2_A p mint1 = Load_S2_A p mint
+    forall mint:addr -> int, mint1:addr -> int, n:int, p:addr, q:addr
+     [Load_S2_A p (havoc mint1 mint q n)].
+     separated p 1 q n ->
+     Load_S2_A p (havoc mint1 mint q n) = Load_S2_A p mint
 end
 [wp:print-generated] 
   theory WP
diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.res.oracle b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.res.oracle
index 63ef86ba980..747410102e8 100644
--- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.res.oracle
+++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.res.oracle
@@ -118,7 +118,7 @@ eq_string           11      4 (52..64)      15       100%
 hash                 6      1 (12..24)       7       100%
 size                 2     -                 2       100%
 init                 8      5 (80..104)     13       100%
-add                 24     15 (208..256)    39       100%
+add                 24     15 (224..272)    39       100%
 mem_binding         18      8 (800..896)    26       100%
 -------------------------------------------------------------
 [wp] Running WP plugin...
@@ -283,6 +283,6 @@ eq_string           11      7 (56..80)      18       100%
 hash                 7      3 (44..56)      10       100%
 size                 2      1 (16..28)       3       100%
 init                10      8 (88..112)     18       100%
-add                 30     24 (208..256)    54       100%
+add                 30     24 (224..272)    54       100%
 mem_binding         25     15 (800..896)    40       100%
 -------------------------------------------------------------
diff --git a/src/plugins/wp/tests/wp_plugin/oracle/inductive.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle/inductive.res.oracle
index 9acab6dd84f..7095462df43 100644
--- a/src/plugins/wp/tests/wp_plugin/oracle/inductive.res.oracle
+++ b/src/plugins/wp/tests/wp_plugin/oracle/inductive.res.oracle
@@ -6,7 +6,7 @@
 [wp:print-generated] 
   "WPOUT/typed/Compound.v"
   (* ---------------------------------------------------------- *)
-  (* --- Memory Compound Updates                            --- *)
+  (* --- Memory Compound Loader                             --- *)
   (* ---------------------------------------------------------- *)
   
   Require Import ZArith.
diff --git a/src/plugins/wp/why3_api.ml b/src/plugins/wp/why3_api.ml
index 1d4c70adb63..73df3e4c6a8 100644
--- a/src/plugins/wp/why3_api.ml
+++ b/src/plugins/wp/why3_api.ml
@@ -450,7 +450,8 @@ let rec of_term ~cnv expected t : Why3.Term.term =
         in
         match lfun_name f, expected with
         | F_call s, _ -> apply_from_ns' s l sort
-        | Qed.Engine.F_subst _, _ -> Wp_parameters.not_yet_implemented "lfun with subst"
+        | Qed.Engine.F_subst _, _ ->
+            raise (Invalid_argument "Can not export 'F_subst' pattern to why-3")
         | Qed.Engine.F_left s, _ | Qed.Engine.F_assoc s, _ ->
             let rec aux = function
               | [] -> Wp_parameters.fatal "Empty application"
-- 
GitLab