From ee55fd924ed161850e31f415b13be4bd445d5740 Mon Sep 17 00:00:00 2001
From: Valentin Perrelle <valentin.perrelle@cea.fr>
Date: Fri, 19 Nov 2021 16:06:52 +0100
Subject: [PATCH] [Eva] multidim: specialize the join between Raw and Array

---
 .../abstract_interp/abstract_memory.ml        | 32 +++++++++++++++----
 1 file changed, 26 insertions(+), 6 deletions(-)

diff --git a/src/kernel_services/abstract_interp/abstract_memory.ml b/src/kernel_services/abstract_interp/abstract_memory.ml
index 3e2538f1a59..eda35089182 100644
--- a/src/kernel_services/abstract_interp/abstract_memory.ml
+++ b/src/kernel_services/abstract_interp/abstract_memory.ml
@@ -504,14 +504,14 @@ sig
   val hash : t -> int
   val equal : t -> t -> bool
   val compare : t -> t -> int
+  val hull : oracle:oracle -> t -> bound * bound
   val raw : t -> Bit.t
   val weak_erase : Bit.t -> t -> t
   val is_included : t -> t -> bool
   val unify : oracle:bioracle -> (submemory -> submemory -> submemory) ->
     t -> t -> t
   val single : bit -> bound -> bound -> submemory -> t
-  val read :
-    oracle:(Cil_types.exp -> Ival.t) ->
+  val read : oracle:oracle ->
     (submemory -> 'a) -> ('a -> 'a -> 'a) -> t -> bound -> 'a
   val write : oracle:oracle -> (submemory -> submemory) ->
     t -> bound -> bound -> t
@@ -605,6 +605,15 @@ struct
       List.for_all2 included_segments m1.segments m2.segments
     with Invalid_argument _ -> false (* Segmentations have different sizes *)
 
+  let hull ~oracle (m : t) : Bound.t * Bound.t =
+    let rec last = function
+      | [] -> assert false
+      | [(_v,u)] -> u
+      | _ :: t -> last t
+    in
+    Bound.lower_const ~oracle m.start,
+    Bound.upper_const ~oracle (last m.segments)
+
   let is_empty_segment ~oracle l u =
     match Bound.cmp ~oracle l u with
     | Equal | Greater -> true
@@ -627,6 +636,7 @@ struct
       | `Bottom -> tail
       | `Value v -> (v,u) :: tail
 
+  (* Unify two arrays m1 and m2 *)
   let unify ~oracle f (m1 (*Left*): t) (m2 (*Right*) : t) : t =
     (* Shortcuts *)
     let compare side = Bound.cmp ~oracle:(oracle side) in
@@ -637,7 +647,6 @@ struct
       let oracle = fun _ -> oracle side in
       Bottom.join (M.join ~oracle)
     in
-
     let {start=l1 ; segments=s1 ; padding=p1 } = m1
     and {start=l2 ; segments=s2 ; padding=p2 } = m2 in
     (* Unify the segmentation start *)
@@ -1047,10 +1056,13 @@ struct
       | Union _, (Scalar _ | Array _ | Struct _) -> false
 
     let unify ~oracle f =
+      let raw_to_array ~oracle side prototype b =
+        let l,u = A.hull ~oracle:(oracle side) prototype in
+        A.single b l u (Raw b)
+      in
       let rec aux m1 m2 =
         match m1, m2 with
         | Raw b1, Raw b2 -> Raw (Bit.join b1 b2)
-        | m, Raw b | Raw b, m -> weak_erase b m
         | Scalar s1, Scalar s2
           when are_typ_compatible s1.scalar_type s2.scalar_type ->
           let size = typ_size s1.scalar_type in
@@ -1059,6 +1071,14 @@ struct
         | Array a1, Array a2 when are_aray_compatible a1 a2 ->
           let array_value = A.unify ~oracle aux a1.array_value a2.array_value in
           Array { a1 with array_value }
+        | Array a, Raw b ->
+          let array_value' = raw_to_array ~oracle Left a.array_value b in
+          let array_value = A.unify ~oracle aux a.array_value array_value' in
+          Array { a with array_value }
+        | Raw b, Array a ->
+          let array_value' = raw_to_array ~oracle Right a.array_value b in
+          let array_value = A.unify ~oracle aux array_value' a.array_value in
+          Array { a with array_value }
         | Struct s1, Struct s2 when are_structs_compatible s1 s2 ->
           let struct_value = S.unify aux s1.struct_value s2.struct_value in
           Struct { s1 with struct_value }
@@ -1068,8 +1088,8 @@ struct
             union_value = aux u1.union_value u2.union_value;
             union_padding = Bit.join u1.union_padding u2.union_padding;
           }
-        | _,_ ->
-          Raw (Bit.join (raw m1) (raw m2))
+        | m, Raw b | Raw b, m -> weak_erase b m
+        | _,_ -> Raw (Bit.join (raw m1) (raw m2))
       in
       aux
 
-- 
GitLab