From 6608ae46bd12189b229345b776cce657a625afd5 Mon Sep 17 00:00:00 2001 From: Allan Blanchard <allan.blanchard@cea.fr> Date: Thu, 28 May 2020 14:19:14 +0200 Subject: [PATCH] [wp] Deals with globals in MemTyped --- src/plugins/wp/MemLoader.ml | 31 ++++++++++-- src/plugins/wp/MemLoader.mli | 1 + src/plugins/wp/MemMemory.ml | 7 ++- src/plugins/wp/MemMemory.mli | 3 ++ src/plugins/wp/MemRegion.ml | 1 + src/plugins/wp/MemTyped.ml | 50 +++++++++++++++---- src/plugins/wp/MemVar.ml | 1 + .../wp/share/why3/frama_c_wp/memory.mlw | 11 +++- 8 files changed, 87 insertions(+), 18 deletions(-) diff --git a/src/plugins/wp/MemLoader.ml b/src/plugins/wp/MemLoader.ml index 5e4fd439273..801cb06218e 100644 --- a/src/plugins/wp/MemLoader.ml +++ b/src/plugins/wp/MemLoader.ml @@ -80,6 +80,7 @@ sig val store_pointer : Sigma.t -> typ -> loc -> term -> Chunk.t * term val is_init_atom : Sigma.t -> loc -> term + val is_init_range : Sigma.t -> c_object -> loc -> term -> pred val set_init_atom : Sigma.t -> loc -> term -> Chunk.t * term val set_init : c_object -> loc -> length:term -> Chunk.t -> current:term -> term @@ -317,6 +318,19 @@ struct let isinitrec = ref (fun _ _ _ -> assert false) + let initialization_lemma cluster name (sigma, obj, loc) (lfun, params) = + let high = p_call lfun (List.map F.e_var params) in + let low = M.is_init_range sigma obj loc e_one in + let lemma = p_equiv high low in + { + l_assumed = true ; + l_name = name ^ "_low" ; l_types = 0 ; + l_forall = F.p_vars lemma ; + l_triggers = [] ; + l_lemma = lemma ; + l_cluster = cluster ; + } + module IS_INIT_COMP = WpContext.Generator(COMP_KEY) (struct let name = M.name ^ ".IS_INIT_COMP" @@ -329,6 +343,8 @@ struct let obj = C_comp c in let loc = M.of_region_pointer r obj v in (* t_pointer -> loc *) let domain = M.init_footprint obj loc in + let cluster = cluster () in + (* Function Is_init *) let name = Format.asprintf "Is%s%a" (Lang.comp_init_id c) pp_rid r in @@ -342,8 +358,11 @@ struct d_lfun = lfun ; d_types = 0 ; d_params = x :: xms ; d_definition = Predicate(Def , def) ; - d_cluster = cluster () ; + d_cluster = cluster ; } ; + (* Lemma for low-level view of the memory *) + Definitions.define_lemma + (initialization_lemma cluster name (sigma,obj,loc) (lfun,x::xms)) ; lfun , chunks let compile = Lang.local generate @@ -371,12 +390,18 @@ struct let ofs = e_sum denv.index_offset in let vm = !isinitrec sigma obj_e (M.shift loc obj_e ofs) in let def = p_forall denv.index_var (p_hyps denv.index_range vm) in + let cluster = cluster () in Definitions.define_symbol { d_lfun = lfun ; d_types = 0 ; d_params = x :: denv.size_var @ xmem ; d_definition = Predicate (Def, def) ; - d_cluster = cluster () ; + d_cluster = cluster ; } ; + (* Lemma for low-level view of the memory *) + Definitions.define_lemma + (initialization_lemma cluster name + (sigma, obj_a, loc) + (lfun, x :: denv.size_var @ xmem)) ; lfun , chunks let compile = Lang.local generate @@ -471,7 +496,7 @@ struct let stored seq obj loc value = match obj with | C_int _ | C_float _ | C_pointer _ -> - updated_atom seq obj loc value :: [ updated_init_atom seq loc e_true ] + [ updated_atom seq obj loc value ; updated_init_atom seq loc e_true ] | C_comp _ | C_array _ -> let set_value = Set(loadvalue seq.post obj loc, value) in set_value :: havoc seq obj loc @ set_init seq obj loc diff --git a/src/plugins/wp/MemLoader.mli b/src/plugins/wp/MemLoader.mli index 2cd1ed7a5db..177e2ce96b5 100644 --- a/src/plugins/wp/MemLoader.mli +++ b/src/plugins/wp/MemLoader.mli @@ -76,6 +76,7 @@ sig val store_pointer : Sigma.t -> typ -> loc -> term -> Chunk.t * term val is_init_atom : Sigma.t -> loc -> term + val is_init_range : Sigma.t -> c_object -> loc -> term -> pred val set_init_atom : Sigma.t -> loc -> term -> Chunk.t * term val set_init : c_object -> loc -> length:term -> Chunk.t -> current:term -> term diff --git a/src/plugins/wp/MemMemory.ml b/src/plugins/wp/MemMemory.ml index 56849a666de..b7d7f2ba856 100644 --- a/src/plugins/wp/MemMemory.ml +++ b/src/plugins/wp/MemMemory.ml @@ -74,8 +74,6 @@ let p_separated = Lang.extern_fp ~library "separated" let p_included = Lang.extern_fp ~library "included" let p_eqmem = Lang.extern_fp ~library "eqmem" let f_havoc = Lang.extern_f ~library ~typecheck:ty_fst_arg ~link:l_havoc "havoc" -let f_set_init = - Lang.extern_f ~library ~typecheck:ty_fst_arg ~link:l_set_init "set_init" let p_monotonic = Lang.extern_fp ~library "monotonic_init" let f_region = Lang.extern_f ~library ~result:L.Int "region" (* base -> region *) let p_framed = Lang.extern_fp ~library "framed" (* m-pointer -> prop *) @@ -83,6 +81,10 @@ let p_linked = Lang.extern_fp ~library "linked" (* allocation-table -> prop *) let p_sconst = Lang.extern_fp ~library "sconst" (* int-memory -> prop *) let p_addr_lt = Lang.extern_p ~library ~bool:"addr_lt_bool" ~prop:"addr_lt" () let p_addr_le = Lang.extern_p ~library ~bool:"addr_le_bool" ~prop:"addr_le" () +let f_set_init = + Lang.extern_f ~library ~typecheck:ty_fst_arg ~link:l_set_init "set_init" +let p_cinits = Lang.extern_fp ~library "cinits" (* initializaton-table -> prop *) +let p_is_init_r = Lang.extern_fp ~library "is_init_range" let f_addr_of_int = Lang.extern_f ~category:L.Injection @@ -98,6 +100,7 @@ let f_int_of_addr = Lang.extern_f let t_mem t = L.Array(t_addr,t) let t_malloc = L.Array(L.Int,L.Int) +let t_init = L.Array(t_addr,L.Bool) let a_null = F.constant (e_fun f_null []) let a_base p = e_fun f_base [p] diff --git a/src/plugins/wp/MemMemory.mli b/src/plugins/wp/MemMemory.mli index bc7ccb47ffa..bd50be0f171 100644 --- a/src/plugins/wp/MemMemory.mli +++ b/src/plugins/wp/MemMemory.mli @@ -31,6 +31,7 @@ open Lang.F val t_addr : tau val t_malloc : tau (** allocation tables *) +val t_init : tau (** initialization tables *) val t_mem : tau -> tau (** t_addr indexed array *) val a_null : term (** Null address. Same as [a_addr 0 0] *) @@ -59,6 +60,8 @@ val p_addr_le : lfun val p_linked : lfun val p_framed : lfun val p_sconst : lfun +val p_cinits : lfun +val p_is_init_r : lfun val p_separated : lfun val p_included : lfun val p_valid_rd : lfun diff --git a/src/plugins/wp/MemRegion.ml b/src/plugins/wp/MemRegion.ml index 1ed00876a4d..427bd92700c 100644 --- a/src/plugins/wp/MemRegion.ml +++ b/src/plugins/wp/MemRegion.ml @@ -819,6 +819,7 @@ struct let _ = current in assert false let is_init_atom _ _ = assert false + let is_init_range _ _ _ _ = assert false let monotonic_init _ _ = assert false end diff --git a/src/plugins/wp/MemTyped.ml b/src/plugins/wp/MemTyped.ml index 441376e8f85..f09f8b9249f 100644 --- a/src/plugins/wp/MemTyped.ml +++ b/src/plugins/wp/MemTyped.ml @@ -172,8 +172,8 @@ struct | M_pointer -> L.Array(t_addr,t_addr) | M_f32 -> L.Array(t_addr,Cfloat.tau_of_float Ctypes.Float32) | M_f64 -> L.Array(t_addr,Cfloat.tau_of_float Ctypes.Float64) - | T_alloc -> L.Array(L.Int,L.Int) - | T_init -> L.Array(t_addr,L.Bool) + | T_alloc -> t_malloc + | T_init -> t_init let basename_of_chunk = name let is_framed _ = false end @@ -529,6 +529,28 @@ module BASE = WpContext.Generator(Varinfo) l_cluster = cluster_globals () ; } + let initialization prefix x base = + match sizeof x with + | Some size when x.vformal || x.vglob -> + let a = Lang.freshvar ~basename:"init" t_init in + let m = e_var a in + let init_access = + if size = 1 then + p_bool (F.e_get m (a_addr base e_zero)) + else + F.p_call p_is_init_r [ m ; a_addr base e_zero ; e_int size ] + in + let m_init = p_call p_cinits [m] in + let init_prop = p_forall [a] (p_imply m_init init_access) in + Definitions.define_lemma { + l_assumed = true ; + l_name = prefix ^ "_init" ; l_types = 0 ; + l_triggers = [] ; l_forall = [] ; + l_lemma = init_prop ; + l_cluster = cluster_globals () ; + } + | _ -> () + let generate x = let acs_rd = Cil.typeHasQualifier "const" x.vtype in let prefix = @@ -550,6 +572,7 @@ module BASE = WpContext.Generator(Varinfo) RegisterBASE.define lfun x ; region prefix x base ; linked prefix x base ; + initialization prefix x base ; base let compile = Lang.local generate @@ -967,15 +990,6 @@ struct F.e_fun f_havoc [fresh;current;loc;n] else fresh - let set_init obj loc ~length _chunk ~current = - let n = F.e_fact (length_of_object obj) length in - F.e_fun f_set_init [current;loc;n] - - let monotonic_init s1 s2 = - let m1 = Sigma.value s1 T_init in - let m2 = Sigma.value s2 T_init in - F.p_call p_monotonic [m1; m2] - let eqmem obj loc _chunk m1 m2 = F.p_call p_eqmem [m1;m2;loc;e_int (length_of_object obj)] @@ -996,6 +1010,19 @@ struct 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 + let is_init_range sigma obj loc length = + let n = F.e_fact (length_of_object obj) length in + F.p_call p_is_init_r [ Sigma.value sigma T_init ; loc ; n ] + + let set_init obj loc ~length _chunk ~current = + let n = F.e_fact (length_of_object obj) length in + F.e_fun f_set_init [current;loc;n] + + let monotonic_init s1 s2 = + let m1 = Sigma.value s1 T_init in + let m2 = Sigma.value s2 T_init in + F.p_call p_monotonic [m1; m2] + end module LOADER = MemLoader.Make(MODEL) @@ -1063,6 +1090,7 @@ let frame sigma = else [] in wellformed_frame p_linked T_alloc @ + wellformed_frame p_cinits T_init @ wellformed_frame p_sconst M_char @ wellformed_frame p_framed M_pointer diff --git a/src/plugins/wp/MemVar.ml b/src/plugins/wp/MemVar.ml index 25755526f67..32e840f7893 100644 --- a/src/plugins/wp/MemVar.ml +++ b/src/plugins/wp/MemVar.ml @@ -371,6 +371,7 @@ struct let get_init s x = INIT.get s.init x let get_init_term s x = e_var (get_init s x) + (* -------------------------------------------------------------------------- *) (* --- State Pretty Printer --- *) (* -------------------------------------------------------------------------- *) diff --git a/src/plugins/wp/share/why3/frama_c_wp/memory.mlw b/src/plugins/wp/share/why3/frama_c_wp/memory.mlw index 0c1a3429cd0..a8b720a310a 100644 --- a/src/plugins/wp/share/why3/frama_c_wp/memory.mlw +++ b/src/plugins/wp/share/why3/frama_c_wp/memory.mlw @@ -69,8 +69,6 @@ theory Memory function havoc (m0 m1 : map addr 'a) (p:addr) (a:int) : map addr 'a - function set_init (m: map addr bool) (p:addr) (a:int) : map addr bool - predicate monotonic_init(m1 m2 : map addr bool) = forall p: addr. m1[p] -> m2[p] @@ -164,6 +162,15 @@ theory Memory (Map.([]) (havoc m0 m1 p a) (q)) = (if (separated q 1 p a) then (Map.([]) (m1) (q)) else (Map.([]) (m0) (q))) + (* Initialization memory *) + + predicate cinits (map addr bool) + + predicate is_init_range(m: map addr bool) (p: addr) (l: int) = + forall i : int. 0 <= i < l -> m[shift p i] = true + + function set_init (m: map addr bool) (p:addr) (a:int) : map addr bool + lemma set_init_access : forall m : map addr bool. forall q p : addr. -- GitLab