From 47b24b366cb91a6bb7ec7f1b6435ff1471e5d2f5 Mon Sep 17 00:00:00 2001 From: Valentin Perrelle <valentin.perrelle@cea.fr> Date: Wed, 15 Dec 2021 14:29:16 +0100 Subject: [PATCH] [Eva] multidim: ensure join correction and allow partition hints on raw memory --- .../abstract_interp/abstract_memory.ml | 86 ++++++++++++------- 1 file changed, 54 insertions(+), 32 deletions(-) diff --git a/src/kernel_services/abstract_interp/abstract_memory.ml b/src/kernel_services/abstract_interp/abstract_memory.ml index cb1d202d3d5..d2e361038cc 100644 --- a/src/kernel_services/abstract_interp/abstract_memory.ml +++ b/src/kernel_services/abstract_interp/abstract_memory.ml @@ -217,7 +217,8 @@ sig weak:bool -> Abstract_offset.typed_offset -> t -> t or_bottom val incr_bound : oracle:oracle -> Cil_types.varinfo -> Integer.t option -> t -> t - val add_segmentation_bounds : oracle:oracle -> Cil_types.exp list -> t -> t + val add_segmentation_bounds : oracle:oracle -> typ:Cil_types.typ -> + Cil_types.exp list -> t -> t end @@ -311,13 +312,12 @@ struct ~decide_fast ~decide_fst ~decide_snd ~decide_both m1.fields m2.fields - let unify f m1 m2 = - let decide b = - FieldMap.Traversing (fun _fi m -> Some (f (M.of_raw b) m)) - in + let unify f m1 m2 = (* f is not symmetric *) let decide_both _fi = fun m1 m2 -> Some (f m1 m2) - and decide_left = decide m2.padding - and decide_right = decide m1.padding + and decide_left = FieldMap.Traversing (fun _fi m1 -> + Some (f m1 (M.of_raw m2.padding))) + and decide_right = FieldMap.Traversing (fun _fi m2 -> + Some (f (M.of_raw m1.padding) m2)) in let fields = FieldMap.merge ~cache:Hptmap_sig.NoCache ~symmetric:false ~idempotent:true @@ -1004,7 +1004,14 @@ struct (* Shortcuts *) let compare side = B.cmp ~oracle:(oracle side) in let equals side b1 b2 = - compare side b1 b2 = Equal + let r = compare side b1 b2 = Equal in + (* Format.printf "%a (%a) = %a (%a) ? %B@." + B.pretty b1 + Ival.pretty (B._to_ival ~oracle:(oracle side) b1) + B.pretty b2 + Ival.pretty (B._to_ival ~oracle:(oracle side) b2) + r; *) + r in let smash side = Bottom.join (M.smash ~oracle:(oracle side)) in let {start=l1 ; segments=s1 ; padding=p1 } = m1 @@ -1527,6 +1534,7 @@ struct A.single b l u (Raw b) in let rec aux m1 m2 = + debug dunify "unification between@.%a and@.%a" pretty m1 pretty m2; match m1, m2 with | Raw b1, Raw b2 -> Raw (Bit.join b1 b2) | Scalar s1, Scalar s2 @@ -1537,23 +1545,29 @@ 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 -> + | Array a1, Raw b2 -> begin try - 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 - debug demerging "emerging unification between@.%a and@.%a result:@.%a" A.pretty a.array_value A.pretty array_value' A.pretty array_value; - Array { a with array_value } + let array_value2 = raw_to_array ~oracle Left a1.array_value b2 in + let array_value = A.unify ~oracle aux a1.array_value array_value2 in + debug demerging "emerging unification between@.%a and@.%a result:@.%a" + A.pretty a1.array_value + A.pretty array_value2 + A.pretty array_value; + Array { a1 with array_value } with Bound.NoBound -> - weak_erase b m1 (* TODO: find a better way to handle this case *) + weak_erase b2 m1 (* TODO: find a better way to handle this case *) end - | Raw b, Array a -> + | Raw b1, Array a2 -> begin try - 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 - debug demerging "emerging unification between@.%a and@.%a result:@.%a" A.pretty array_value' A.pretty a.array_value A.pretty array_value; - Array { a with array_value } + let array_value1 = raw_to_array ~oracle Right a2.array_value b1 in + let array_value = A.unify ~oracle aux array_value1 a2.array_value in + debug demerging "emerging unification between@.%a and@.%a result:@.%a" + A.pretty array_value1 + A.pretty a2.array_value + A.pretty array_value; + Array { a2 with array_value } with Bound.NoBound -> - weak_erase b m2 (* TODO: find a better way to handle this case *) + weak_erase b1 m2 (* TODO: find a better way to handle this case *) end | Struct s1, Struct s2 when are_structs_compatible s1 s2 -> let struct_value = S.unify aux s1.struct_value s2.struct_value in @@ -1685,18 +1699,26 @@ struct Array { a with array_value=A.map aux array_value } in aux - let add_segmentation_bounds ~oracle bounds = function + let add_segmentation_bounds ~oracle ~typ bounds = + let convert_bound exp = + try + Some (Bound.of_exp exp) + with Bound.UnsupportedBoundExpression -> None + in + let bounds = List.filter_map convert_bound bounds in + function + | (Raw b as m) -> + begin match bounds with + | l :: u :: t -> + let array_value = A.single b l u m in + let array_value = A.add_segmentation_bounds ~oracle t array_value in + Array { array_cell_type = typ ; array_value } + | _ -> m (* Can't build a segmentation with only one bound *) + end | Array a -> - let convert_bound exp = - try - Some (Bound.of_exp exp) - with Bound.UnsupportedBoundExpression -> None + let array_value = A.add_segmentation_bounds ~oracle bounds a.array_value in - let bounds = List.filter_map convert_bound bounds in - Array { - a with - array_value = A.add_segmentation_bounds ~oracle bounds a.array_value - } + Array { a with array_value } | m -> m (* Ignore segmentation hints on non-array *) end and S : Structures with type submemory = ProtoMemory.t = @@ -1780,8 +1802,8 @@ struct write' ~oracle ~weak f offset dst let segmentation_hint ~oracle m offset bounds = - let f ~weak:_ _typ m = - add_segmentation_bounds ~oracle bounds m + let f ~weak:_ typ m = + add_segmentation_bounds ~oracle ~typ bounds m in write' ~oracle ~weak:false f offset m end -- GitLab