Skip to content
Snippets Groups Projects
Commit c9947f0e authored by Valentin Perrelle's avatar Valentin Perrelle Committed by David Bühler
Browse files

[Eva] slight improvements

parent cef56ae8
No related branches found
No related tags found
No related merge requests found
...@@ -29,6 +29,20 @@ exception Not_implemented ...@@ -29,6 +29,20 @@ exception Not_implemented
open Abstract_offset open Abstract_offset
open Bottom.Type 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 type size = Integer.t
...@@ -46,8 +60,8 @@ let debug b format = ...@@ -46,8 +60,8 @@ let debug b format =
(* Composition operator for compare function *) (* Composition operator for compare function *)
let (<?>) c (cmp,x,y) = let (<?>) c lcmp =
if c = 0 then cmp x y else c if c = 0 then 0 else Lazy.force lcmp
(* Pretty printing for iterators - inspired by Pretty_utils.pp_iter *) (* Pretty printing for iterators - inspired by Pretty_utils.pp_iter *)
...@@ -171,7 +185,7 @@ struct ...@@ -171,7 +185,7 @@ struct
| Uninitialized, Uninitialized -> 0 | Uninitialized, Uninitialized -> 0
| Zero i1, Zero i2 -> Initialization.compare i1 i2 | Zero i1, Zero i2 -> Initialization.compare i1 i2
| Any (set1,i1), Any (set2,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
| _, Uninitialized -> -1 | _, Uninitialized -> -1
| Zero _, _ -> 1 | Zero _, _ -> 1
...@@ -347,7 +361,7 @@ struct ...@@ -347,7 +361,7 @@ struct
let compare m1 m2 = let compare m1 m2 =
FieldMap.compare m1.fields m2.fields <?> FieldMap.compare m1.fields m2.fields <?>
(Bit.compare, m1.padding, m2.padding) lazy (Bit.compare m1.padding m2.padding)
let raw m = let raw m =
FieldMap.fold (fun _ x acc -> Bit.join acc (M.raw x)) m.fields m.padding FieldMap.fold (fun _ x acc -> Bit.join acc (M.raw x)) m.fields m.padding
...@@ -687,7 +701,7 @@ struct ...@@ -687,7 +701,7 @@ struct
match b1, b2 with match b1, b2 with
| Const i1, Const i2 -> Integer.compare i1 i2 | Const i1, Const i2 -> Integer.compare i1 i2
| Exp (e1, i1), Exp (e2, 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 | Ptroffset _, Ptroffset _ -> raise Not_implemented
| Const _, _ -> 1 | Const _, _ -> 1
| _, Const _-> -1 | _, Const _-> -1
...@@ -1008,11 +1022,11 @@ struct ...@@ -1008,11 +1022,11 @@ struct
let compare (m1 : t) (m2 : t) : int = let compare (m1 : t) (m2 : t) : int =
let compare_segments (v1,u1) (v2,u2) = 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 in
B.compare m1.start m2.start <?> B.compare m1.start m2.start <?>
(Transitioning.List.compare compare_segments, m1.segments, m2.segments) <?> lazy (Transitioning.List.compare compare_segments m1.segments m2.segments) <?>
(Bit.compare, m1.padding, m2.padding) lazy (Bit.compare m1.padding m2.padding)
let equal (m1 : t) (m2 : t) : bool = let equal (m1 : t) (m2 : t) : bool =
let equal_segments (v1,u1) (v2,u2) = let equal_segments (v1,u1) (v2,u2) =
...@@ -1054,7 +1068,7 @@ struct ...@@ -1054,7 +1068,7 @@ struct
let l = m.start and u = last m.segments in let l = m.start and u = last m.segments in
match B.lower_const ~oracle l, B.upper_const ~oracle u with match B.lower_const ~oracle l, B.upper_const ~oracle u with
| None, _ | _, None -> None | 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 is_empty_segment ~oracle l u =
let open (val (B.operators oracle)) in let open (val (B.operators oracle)) in
...@@ -1181,11 +1195,11 @@ struct ...@@ -1181,11 +1195,11 @@ struct
(* Iterate through segmentations *) (* Iterate through segmentations *)
check { start = l ; segments ; padding = Bit.join p1 p2 } 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 { check {
padding ; padding ;
start = B.birth lindex ; start = B.birth lindex ;
segments = [(value,B.birth (Bound.succ uindex))] ; segments = [(value,B.birth uindex)] ;
} }
let read ~oracle map reduce m lindex uindex = let read ~oracle map reduce m lindex uindex =
...@@ -1213,7 +1227,7 @@ struct ...@@ -1213,7 +1227,7 @@ struct
in in
{ m with segments = List.rev (aux [] m.segments) } { 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 *) match m.segments with (* ignore m.start bound *)
| [] -> None | [] -> None
| (_,b) :: t -> | (_,b) :: t ->
...@@ -1224,11 +1238,11 @@ struct ...@@ -1224,11 +1238,11 @@ struct
in in
aux (B.age b) t aux (B.age b) t
let remove_oldest_bounds ~oracle m = let remove_elderlies ~oracle m =
match oldest_inner_bound m with match age m with
| None -> m (* no inner bounds, should not happen if segments_limit > 2 *) | None -> m (* no inner bounds, should not happen if segments_limit > 2 *)
| Some oldest_age -> | Some oldest_age ->
(* Remvoe all bounds of this age *) (* Remove all bounds of this age *)
let rec aux acc l = function let rec aux acc l = function
| ([] | [_]) as t -> List.rev (t @ acc) | ([] | [_]) as t -> List.rev (t @ acc)
| ((v,u) :: t) as s -> | ((v,u) :: t) as s ->
...@@ -1240,11 +1254,11 @@ struct ...@@ -1240,11 +1254,11 @@ struct
{ m with segments = aux [] m.start m.segments } { m with segments = aux [] m.start m.segments }
let limit_size ~oracle m = let limit_size ~oracle m =
let limit = Config.slice_limit () in let limit = max 1 (Config.slice_limit ()) in
let rec aux m = let rec aux m =
if List.length m.segments <= limit if List.length m.segments <= limit
then m then m
else aux (remove_oldest_bounds ~oracle m) else aux (remove_elderlies ~oracle m)
in in
aux m aux m
...@@ -1290,11 +1304,11 @@ struct ...@@ -1290,11 +1304,11 @@ struct
and v = M.smash ~oracle v (M.of_raw m.padding) in and v = M.smash ~oracle v (M.of_raw m.padding) in
aux_end start head l v u [] aux_end start head l v u []
| (v',u') :: t -> | (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 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*) 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); 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 let previous_is_empty = is_empty_segment ~oracle l lindex
and next_is_empty = is_empty_segment ~oracle uindex u in and next_is_empty = is_empty_segment ~oracle uindex u in
let tail' = let tail' =
...@@ -1753,11 +1767,11 @@ struct ...@@ -1753,11 +1767,11 @@ struct
if fi.fcomp.cstruct then (* Structures *) if fi.fcomp.cstruct then (* Structures *)
if Config.disjunctive_invariants () then if Config.disjunctive_invariants () then
let old = to_disj fi.fcomp m in 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 } Disjunct { disj_type = fi.fcomp ; disj_value }
else else
let old = to_struct ~oracle fi.fcomp m in 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 } Struct { struct_type = fi.fcomp; struct_value }
else (* Unions *) else (* Unions *)
let old = match m with let old = match m with
...@@ -1766,26 +1780,26 @@ struct ...@@ -1766,26 +1780,26 @@ struct
let b = raw m in let b = raw m in
{ union_value = Raw b ; union_field = fi ; union_padding = b } { union_value = Raw b ; union_field = fi ; union_padding = b }
in 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 } Union { old with union_value }
| Index (exp, index, elem_type, offset') -> | Index (exp, index, elem_type, offset') ->
let lindex, uindex, weak = match Option.map Bound.of_exp exp with 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 -> | None | exception Bound.UnsupportedBoundExpression ->
let l, u = Int_val.min_and_max index in let l, u = Int_val.min_and_max index in
let l = Option.get l and u = Option.get u in (* TODO: handle exceptions *) 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 weak || Integer.equal l u
in in
match m with match m with
| Array a when are_typ_compatible a.array_cell_type elem_type -> | Array a when are_typ_compatible a.array_cell_type elem_type ->
A.write ~oracle (aux ~weak offset') a.array_value let+ array_value =
lindex (Bound.succ uindex) >>-: fun 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; debug dwrite "wrote from previous@.%a@.->%a" A.pretty a.array_value A.pretty array_value;
Array { a with array_value } Array { a with array_value }
| _ -> | _ ->
let b = raw m in 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 let array_value = A.single b lindex uindex new_value in
debug dwrite "wrote from raw@.%a" A.pretty array_value; debug dwrite "wrote from raw@.%a" A.pretty array_value;
Array { array_cell_type = elem_type ; array_value } Array { array_cell_type = elem_type ; array_value }
......
...@@ -848,9 +848,9 @@ struct ...@@ -848,9 +848,9 @@ struct
let relate _kf _bases _state = Base.SetLattice.empty 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, 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 reuse _kf bases =
let open BaseMap in let open BaseMap in
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment