diff --git a/src/plugins/wp/MemLoader.ml b/src/plugins/wp/MemLoader.ml index ac6e5cbcda1d19012b80a37f5a0ea87ae09c44ca..4b8f5ba39f7d4b123a16d776839ab9515c977d7c 100644 --- a/src/plugins/wp/MemLoader.ml +++ b/src/plugins/wp/MemLoader.ml @@ -79,7 +79,7 @@ sig val store_float : Sigma.t -> c_float -> loc -> term -> Chunk.t * term val store_pointer : Sigma.t -> typ -> loc -> term -> Chunk.t * term - val init_atom : Sigma.t -> loc -> Chunk.t * term + val set_init_atom : Sigma.t -> loc -> term -> Chunk.t * term val is_init_atom : Sigma.t -> loc -> term end @@ -382,43 +382,26 @@ struct let () = initrec := initvalue - (* -------------------------------------------------------------------------- *) - (* --- Havocs --- *) - (* -------------------------------------------------------------------------- *) - - let havoc_length s obj loc length = - let ps = ref [] in - Domain.iter - (fun chunk -> - let pre = Sigma.value s.pre chunk in - let post = Sigma.value s.post chunk in - let tau = Chunk.tau_of_chunk chunk in - let basename = Chunk.basename_of_chunk chunk ^ "_undef" in - let fresh = F.e_var (Lang.freshvar ~basename tau) in - let havoc = M.havoc obj loc ~length chunk ~fresh ~current:pre in - ps := Set(post,havoc) :: !ps - ) (domain obj loc) ; !ps - - let havoc seq obj loc = havoc_length seq obj loc F.e_one - (* -------------------------------------------------------------------------- *) (* --- Initialized --- *) (* -------------------------------------------------------------------------- *) - let rec initialized_term obj term = + let rec on_initialized_terms map on_leave obj terms = match obj with - | C_int _ | C_float _ | C_pointer _ -> p_bool term + | C_int _ | C_float _ | C_pointer _ -> on_leave terms | C_comp ci -> let initialized_field f = - initialized_term + on_initialized_terms map on_leave (object_of f.ftype) - (e_getfield term (Cfield (f, KInit))) + (map (fun t -> e_getfield t (Cfield (f, KInit))) terms) in p_conj (List.map initialized_field ci.cfields) | C_array ai -> let obj_e, ds = Matrix.of_array ai in let denv = Matrix.denv ds in - let values = List.fold_left e_get term denv.index_val in + let values = + map (fun t -> List.fold_left e_get t denv.index_val) terms + in let make_subst var value p = match value with | None -> p @@ -428,7 +411,16 @@ struct let conj = List.fold_left (fun p f -> f p) (p_conj denv.index_range) substs in - p_imply conj (initialized_term obj_e values) + p_forall denv.index_var + (p_imply conj (on_initialized_terms map on_leave obj_e values)) + + let initialized_term = + on_initialized_terms Extlib.id p_bool + + let initialized_monotonic = + on_initialized_terms + (fun f (a, b) -> f a, f b) + (fun (a, b) -> p_imply (p_bool a) (p_bool b)) let initialized_loc sigma obj loc = initialized_term obj (initvalue sigma obj loc) @@ -446,21 +438,61 @@ struct "Invalid infinite range @[<hov 2>+@,(%a@,..%a)@]" Vset.pp_bound low Vset.pp_bound up + let initialized_loc_monotonic seq obj loc = + initialized_monotonic + obj ((initvalue seq.pre obj loc), (initvalue seq.post obj loc)) + + let initialized_range_monotonic s obj loc a b = + let i = Lang.freshvar ~basename:"i" Lang.t_int in + let init = + p_forall [i] + (p_imply + (p_and (p_leq a (e_var i)) (p_leq (e_var i) b)) + (initialized_loc_monotonic s obj (M.shift loc obj (e_var i)))) + in + Assert init + + (* -------------------------------------------------------------------------- *) + (* --- Havocs --- *) + (* -------------------------------------------------------------------------- *) + + let havoc_length s obj loc length = + let ps = ref [] in + Domain.iter + (fun chunk -> + let pre = Sigma.value s.pre chunk in + let post = Sigma.value s.post chunk in + let tau = Chunk.tau_of_chunk chunk in + let basename = Chunk.basename_of_chunk chunk ^ "_undef" in + let fresh = F.e_var (Lang.freshvar ~basename tau) in + let havoc = M.havoc obj loc ~length chunk ~fresh ~current:pre in + ps := Set(post,havoc) :: !ps + ) (domain obj loc) ; !ps + + let havoc seq obj loc = havoc_length seq obj loc F.e_one + (* -------------------------------------------------------------------------- *) (* --- Stored & Copied --- *) (* -------------------------------------------------------------------------- *) - let updated seq phi_store alpha loc value = - let chunk_store,mem_store = phi_store seq.pre alpha loc value in - let chunk_init,mem_init = M.init_atom seq.pre loc in - [Set(Sigma.value seq.post chunk_store,mem_store) ; - Set(Sigma.value seq.post chunk_init,mem_init)] + let updated_init seq loc value = + let chunk_init,mem_init = M.set_init_atom seq.pre loc value in + Set(Sigma.value seq.post chunk_init,mem_init) + + let updated_atom seq obj loc value = + let phi_store sigma = match obj with + | C_int i -> M.store_int sigma i + | C_float f -> M.store_float sigma f + | C_pointer ty -> M.store_pointer sigma ty + | _ -> failwith "MemLoader updated_atom called on a non atomic type" + in + let chunk_store,mem_store = phi_store seq.pre loc value in + Set(Sigma.value seq.post chunk_store,mem_store) let stored seq obj loc value = match obj with - | C_int i -> updated seq M.store_int i loc value - | C_float f -> updated seq M.store_float f loc value - | C_pointer ty -> updated seq M.store_pointer ty loc value + | C_int _ | C_float _ | C_pointer _ -> + updated_init seq loc e_true :: [ updated_atom seq obj loc value ] | C_comp _ | C_array _ -> let init = Cvalues.initialized_obj obj in Set(initvalue seq.post obj loc, init) :: @@ -475,12 +507,17 @@ struct let assigned_loc seq obj loc = match obj with | C_int _ | C_float _ | C_pointer _ -> - let x = Lang.freshvar ~basename:"v" (Lang.tau_of_object obj) in - stored seq obj loc (e_var x) + let value = Lang.freshvar ~basename:"v" (Lang.tau_of_object obj) in + let init = Lang.freshvar ~basename:"i" (Lang.init_of_object obj) in + [ Assert (initialized_loc_monotonic seq obj loc) ; + updated_init seq loc (e_var init) ; + updated_atom seq obj loc (e_var value) ] | C_comp _ | C_array _ -> + Assert (initialized_loc_monotonic seq obj loc) :: havoc seq obj loc let assigned_range s obj l a b = + initialized_range_monotonic s obj l a b :: havoc_length s obj (M.shift l obj a) (e_range a b) let assigned seq obj = function @@ -495,7 +532,12 @@ struct let sep_from_all = F.p_forall xs (F.p_imply condition separated) in let phi = F.p_forall p (F.p_imply sep_from_all equal) in ps := Assert phi :: !ps - ) (M.value_footprint obj loc) ; !ps + ) (domain obj loc) ; + let mono = + F.p_forall xs + (F.p_imply condition (initialized_loc_monotonic seq obj loc)) + in + Assert mono :: !ps | Sarray(loc,obj,n) -> assigned_range seq obj loc e_zero (e_int (n-1)) | Srange(loc,obj,u,v) -> diff --git a/src/plugins/wp/MemLoader.mli b/src/plugins/wp/MemLoader.mli index 7240bbcc920442864f2268a454177550a482b6e4..16cf3b31168362479905890be976b309df5044b1 100644 --- a/src/plugins/wp/MemLoader.mli +++ b/src/plugins/wp/MemLoader.mli @@ -75,7 +75,7 @@ sig val store_float : Sigma.t -> c_float -> loc -> term -> Chunk.t * term val store_pointer : Sigma.t -> typ -> loc -> term -> Chunk.t * term - val init_atom : Sigma.t -> loc -> Chunk.t * term + val set_init_atom : Sigma.t -> loc -> term -> Chunk.t * term val is_init_atom : Sigma.t -> loc -> term end diff --git a/src/plugins/wp/MemRegion.ml b/src/plugins/wp/MemRegion.ml index ec013da03bcc008997900d389705f7c2c4e29494..85f5d00e3503555d0383fdba13bc13234c81a455 100644 --- a/src/plugins/wp/MemRegion.ml +++ b/src/plugins/wp/MemRegion.ml @@ -813,7 +813,7 @@ struct | Lmem(r,l,rt,(Pointer _ as v)) -> store_mem sigma r rt v l value | _ -> error "Can not store pointer values into %a" pretty loc - let init_atom _ _ = assert false + let set_init_atom _ _ _ = assert false let is_init_atom _ _ = assert false end diff --git a/src/plugins/wp/MemTyped.ml b/src/plugins/wp/MemTyped.ml index 51d49141a7ed7131f5eb22ae3fc461a33ffac94c..3de96aa6c9d95f3f71a41fc0cd252fd3ee2deefa 100644 --- a/src/plugins/wp/MemTyped.ml +++ b/src/plugins/wp/MemTyped.ml @@ -984,7 +984,7 @@ struct 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 init_atom sigma l = updated sigma T_init l e_true + let set_init_atom sigma l v = updated sigma T_init l v let is_init_atom sigma l = F.e_get (Sigma.value sigma T_init) l end