From c9947f0e07091d7ed5d2bfc2ac8b7277e3acc829 Mon Sep 17 00:00:00 2001
From: Valentin Perrelle <valentin.perrelle@cea.fr>
Date: Thu, 24 Mar 2022 18:07:53 +0100
Subject: [PATCH] [Eva] slight improvements

---
 .../abstract_interp/abstract_memory.ml        | 68 +++++++++++--------
 src/plugins/value/domains/multidim_domain.ml  |  4 +-
 2 files changed, 43 insertions(+), 29 deletions(-)

diff --git a/src/kernel_services/abstract_interp/abstract_memory.ml b/src/kernel_services/abstract_interp/abstract_memory.ml
index cac821fd871..d43c2dd4684 100644
--- a/src/kernel_services/abstract_interp/abstract_memory.ml
+++ b/src/kernel_services/abstract_interp/abstract_memory.ml
@@ -29,6 +29,20 @@ exception Not_implemented
 open Abstract_offset
 open Bottom.Type
 
+let zip_bottom x y =
+  match x, y with
+  | `Bottom, _ | _, `Bottom -> `Bottom
+  | `Value x, `Value y -> `Value (x,y)
+
+(* Applicative syntax *)
+let ( let+ ) : 'a or_bottom -> ('a -> 'b) -> 'b or_bottom = (>>-:)
+let ( and+ ): 'a or_bottom -> 'b or_bottom -> ('a * 'b) or_bottom = zip_bottom
+
+(* Monad syntax *)
+let ( let* ) : 'a or_bottom -> ('a -> 'b or_bottom) -> 'b or_bottom = (>>-)
+let ( and* ): 'a or_bottom -> 'b or_bottom -> ('a * 'b) or_bottom = zip_bottom
+
+
 type size = Integer.t
 
 
@@ -46,8 +60,8 @@ let debug b format =
 
 (* Composition operator for compare function *)
 
-let (<?>) c (cmp,x,y) =
-  if c = 0 then cmp x y else c
+let (<?>) c lcmp =
+  if c = 0 then 0 else Lazy.force lcmp
 
 (* Pretty printing for iterators - inspired by Pretty_utils.pp_iter *)
 
@@ -171,7 +185,7 @@ struct
     | Uninitialized, Uninitialized -> 0
     | Zero i1, Zero i2 -> Initialization.compare i1 i2
     | Any (set1,i1), Any (set2,i2) ->
-      Bases.compare set1 set2 <?> (Initialization.compare, i1, i2)
+      Bases.compare set1 set2 <?> lazy (Initialization.compare i1 i2)
     | Uninitialized, _ -> 1
     | _, Uninitialized -> -1
     | Zero _, _ -> 1
@@ -347,7 +361,7 @@ struct
 
   let compare m1 m2 =
     FieldMap.compare m1.fields m2.fields <?>
-    (Bit.compare, m1.padding, m2.padding)
+    lazy (Bit.compare m1.padding m2.padding)
 
   let raw m =
     FieldMap.fold (fun _ x acc -> Bit.join acc (M.raw x)) m.fields m.padding
@@ -687,7 +701,7 @@ struct
     match b1, b2 with
     | Const i1, Const i2 -> Integer.compare i1 i2
     | Exp (e1, i1), Exp (e2, i2) ->
-      Exp.compare e1 e2 <?> (Integer.compare, i1, i2)
+      Exp.compare e1 e2 <?> lazy (Integer.compare i1 i2)
     | Ptroffset _, Ptroffset _ -> raise Not_implemented
     | Const _, _ -> 1
     | _, Const _-> -1
@@ -1008,11 +1022,11 @@ struct
 
   let compare (m1 : t) (m2 : t) : int =
     let compare_segments (v1,u1) (v2,u2) =
-      M.compare v1 v2 <?> (B.compare, u1, u2)
+      M.compare v1 v2 <?> lazy (B.compare u1 u2)
     in
     B.compare m1.start m2.start <?>
-    (Transitioning.List.compare compare_segments, m1.segments, m2.segments) <?>
-    (Bit.compare, m1.padding, m2.padding)
+    lazy (Transitioning.List.compare compare_segments m1.segments m2.segments) <?>
+    lazy (Bit.compare m1.padding m2.padding)
 
   let equal (m1 : t) (m2 : t) : bool =
     let equal_segments (v1,u1) (v2,u2) =
@@ -1054,7 +1068,7 @@ struct
     let l = m.start and u = last m.segments in
     match B.lower_const ~oracle l, B.upper_const ~oracle u with
     | None, _ | _, None -> None
-    | Some l, Some u -> Some (B.raw_bound l, B.raw_bound (B.pred u))
+    | Some l, Some u -> Some (B.raw_bound l, B.raw_bound u)
 
   let is_empty_segment ~oracle l u =
     let open (val (B.operators oracle)) in
@@ -1181,11 +1195,11 @@ struct
     (* Iterate through segmentations *)
     check { start = l ; segments ; padding = Bit.join p1 p2 }
 
-  let single padding lindex (* included *) uindex (* included *) value =
+  let single padding lindex (* included *) uindex (* excluded *) value =
     check {
       padding ;
       start = B.birth lindex ;
-      segments = [(value,B.birth (Bound.succ uindex))] ;
+      segments = [(value,B.birth uindex)] ;
     }
 
   let read ~oracle map reduce m lindex uindex =
@@ -1213,7 +1227,7 @@ struct
     in
     { m with segments = List.rev (aux [] m.segments) }
 
-  let oldest_inner_bound m =
+  let age m = (* Age of the segmentation / age of the oldest bound *)
     match m.segments with (* ignore m.start bound *)
     | [] -> None
     | (_,b) :: t ->
@@ -1224,11 +1238,11 @@ struct
       in
       aux (B.age b) t
 
-  let remove_oldest_bounds ~oracle m =
-    match oldest_inner_bound m with
+  let remove_elderlies ~oracle m =
+    match age m with
     | None -> m (* no inner bounds, should not happen if segments_limit > 2 *)
     | Some oldest_age ->
-      (* Remvoe all bounds of this age *)
+      (* Remove all bounds of this age *)
       let rec aux acc l = function
         | ([] | [_]) as t -> List.rev (t @ acc)
         | ((v,u) :: t) as s ->
@@ -1240,11 +1254,11 @@ struct
       { m with segments = aux [] m.start m.segments }
 
   let limit_size ~oracle m =
-    let limit = Config.slice_limit () in
+    let limit = max 1 (Config.slice_limit ()) in
     let rec aux m =
       if List.length m.segments <= limit
       then m
-      else aux (remove_oldest_bounds ~oracle m)
+      else aux (remove_elderlies ~oracle m)
     in
     aux m
 
@@ -1290,11 +1304,11 @@ struct
           and v = M.smash ~oracle v (M.of_raw m.padding) in
           aux_end start head l v u []
         | (v',u') :: t ->
-          (* TODO: do not smash if the slices are covered by the write *)
+          (* TODO: do not smash for overwrites if the slices are covered by the write *)
           aux_over start head l (M.smash ~oracle v v') u' t
     and aux_end start head l v u tail = (* l <= lindex < uindex <= u*)
       debug dwrite  "aux_end: %a <{%a} %a {%a}> %a@." pretty_segments (start,head) B.pretty l M.pretty v B.pretty u pretty_segments (u,tail);
-      f v >>-: fun new_v ->
+      let+ new_v = f v in
       let previous_is_empty = is_empty_segment ~oracle l lindex
       and next_is_empty = is_empty_segment ~oracle uindex u in
       let tail' =
@@ -1753,11 +1767,11 @@ struct
           if fi.fcomp.cstruct then (* Structures *)
             if Config.disjunctive_invariants () then
               let old = to_disj fi.fcomp m in
-              D.write ~oracle (aux ~weak offset') old fi >>-: fun disj_value ->
+              let+ disj_value = D.write ~oracle (aux ~weak offset') old fi in
               Disjunct { disj_type = fi.fcomp ; disj_value }
             else
               let old = to_struct ~oracle fi.fcomp m in
-              S.write (aux ~weak offset') old fi >>-: fun struct_value ->
+              let+ struct_value = S.write (aux ~weak offset') old fi in
               Struct { struct_type = fi.fcomp; struct_value }
           else (* Unions *)
             let old = match m with
@@ -1766,26 +1780,26 @@ struct
                 let b = raw m in
                 { union_value = Raw b ; union_field = fi ; union_padding = b }
             in
-            aux ~weak offset' old.union_value >>-: fun union_value ->
+            let+ union_value = aux ~weak offset' old.union_value in
             Union { old with union_value }
         | Index (exp, index, elem_type, offset') ->
           let lindex, uindex, weak = match Option.map Bound.of_exp exp with
-            | Some b -> b, b, weak
+            | Some b -> b, Bound.succ b, weak
             | None | exception Bound.UnsupportedBoundExpression ->
               let l, u = Int_val.min_and_max index in
               let l = Option.get l and u = Option.get u in (* TODO: handle exceptions *)
-              Bound.of_integer l, Bound.of_integer u,
+              Bound.of_integer l, Bound.(succ (of_integer u)),
               weak || Integer.equal l u
           in
           match m with
           | Array a when are_typ_compatible a.array_cell_type elem_type ->
-            A.write ~oracle (aux ~weak offset') a.array_value
-              lindex (Bound.succ uindex) >>-: fun array_value ->
+            let+ array_value =
+              A.write ~oracle (aux ~weak offset') a.array_value lindex uindex in
             debug dwrite "wrote from previous@.%a@.->%a" A.pretty a.array_value A.pretty array_value;
             Array { a with array_value }
           | _ ->
             let b = raw m in
-            aux ~weak offset' (Raw b) >>-: fun new_value ->
+            let+ new_value = aux ~weak offset' (Raw b) in
             let array_value = A.single b lindex uindex new_value in
             debug dwrite "wrote from raw@.%a" A.pretty array_value;
             Array { array_cell_type = elem_type ; array_value }
diff --git a/src/plugins/value/domains/multidim_domain.ml b/src/plugins/value/domains/multidim_domain.ml
index 4152193ac2b..de0eaa3bef9 100644
--- a/src/plugins/value/domains/multidim_domain.ml
+++ b/src/plugins/value/domains/multidim_domain.ml
@@ -848,9 +848,9 @@ struct
 
   let relate _kf _bases _state = Base.SetLattice.empty
 
-  let filter _kf _kind bases (base_map,tracked) =
+  let filter _kf _kind bases (base_map,tracked : t) =
     BaseMap.filter (fun elt -> Base.Hptset.mem elt bases) base_map,
-    tracked (* TODO: intersection with bases *)
+    Option.map (TrackedBases.inter bases) tracked
 
   let reuse _kf bases =
     let open BaseMap in
-- 
GitLab