diff --git a/bin/rebuild.sh b/bin/rebuild.sh index e6f5900bd94fb75da5bcbffc16f78fa03d92e103..f8d3346fab80481cfd8a6eaa73f3f1d92765a6eb 100755 --- a/bin/rebuild.sh +++ b/bin/rebuild.sh @@ -5,4 +5,4 @@ autoconf -f ./configure make clean make depend -make -j +make -kj diff --git a/headers/header_spec.txt b/headers/header_spec.txt index b66be1d6251f0bfde9c04b103943158952b9c1c6..8eb63cc4d24298a365fca941401f0573cee0eeff 100644 --- a/headers/header_spec.txt +++ b/headers/header_spec.txt @@ -1422,6 +1422,8 @@ src/plugins/wp/GuiSource.ml: CEA_WP src/plugins/wp/GuiSource.mli: CEA_WP src/plugins/wp/GuiTactic.ml: CEA_WP src/plugins/wp/GuiTactic.mli: CEA_WP +src/plugins/wp/Layout.ml: CEA_WP +src/plugins/wp/Layout.mli: CEA_WP src/plugins/wp/Lang.ml: CEA_WP src/plugins/wp/Lang.mli: CEA_WP src/plugins/wp/Letify.ml: CEA_WP @@ -1444,6 +1446,12 @@ src/plugins/wp/MemoryContext.ml: CEA_WP src/plugins/wp/MemoryContext.mli: CEA_WP src/plugins/wp/MemEmpty.ml: CEA_WP src/plugins/wp/MemEmpty.mli: CEA_WP +src/plugins/wp/MemLoader.ml: CEA_WP +src/plugins/wp/MemLoader.mli: CEA_WP +src/plugins/wp/MemMemory.ml: CEA_WP +src/plugins/wp/MemMemory.mli: CEA_WP +src/plugins/wp/MemRegion.ml: CEA_WP +src/plugins/wp/MemRegion.mli: CEA_WP src/plugins/wp/MemTyped.ml: CEA_WP src/plugins/wp/MemTyped.mli: CEA_WP src/plugins/wp/MemVar.ml: CEA_WP @@ -1487,6 +1495,14 @@ src/plugins/wp/RefUsage.ml: CEA_WP src/plugins/wp/RefUsage.mli: CEA_WP src/plugins/wp/Region.ml: CEA_WP src/plugins/wp/Region.mli: CEA_WP +src/plugins/wp/RegionAccess.ml: CEA_WP +src/plugins/wp/RegionAccess.mli: CEA_WP +src/plugins/wp/RegionAnalysis.ml: CEA_WP +src/plugins/wp/RegionAnalysis.mli: CEA_WP +src/plugins/wp/RegionAnnot.ml: CEA_WP +src/plugins/wp/RegionAnnot.mli: CEA_WP +src/plugins/wp/RegionDump.ml: CEA_WP +src/plugins/wp/RegionDump.mli: CEA_WP src/plugins/wp/Repr.ml: CEA_WP src/plugins/wp/Repr.mli: CEA_WP src/plugins/wp/Sigma.ml: CEA_WP diff --git a/src/plugins/qed/listmap.ml b/src/plugins/qed/listmap.ml index d83fbecf9bc96f487b8932022a807d2bdd756a1b..b8e3d5aab747b37efe9b35121f5f359d6a608cc4 100644 --- a/src/plugins/qed/listmap.ml +++ b/src/plugins/qed/listmap.ml @@ -43,6 +43,7 @@ struct let equal eq = Hcons.equal_list (fun (i,x) (j,y) -> K.equal i j && eq x y) let empty = [] + let is_empty = function [] -> true | _ -> false (* used for better sharing between a list and a modified list *) let rev_append_until i l1 l2 = diff --git a/src/plugins/qed/listmap.mli b/src/plugins/qed/listmap.mli index 5819c1b62ae7b9918baf261a6939ec1c76c3a004..2c8d45acd8c2aca57560412886fdfd1bcb5527c1 100644 --- a/src/plugins/qed/listmap.mli +++ b/src/plugins/qed/listmap.mli @@ -42,6 +42,8 @@ sig val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool val empty : 'a t + val is_empty : 'a t -> bool + val add : key -> 'a -> 'a t -> 'a t val mem : key -> 'a t -> bool val find : key -> 'a t -> 'a diff --git a/src/plugins/qed/listset.ml b/src/plugins/qed/listset.ml index 228dfd3439e239797292da925ac9ac6f07e73920..ab081f890b2c86987e4e6cd30832ac8a7adc13a7 100644 --- a/src/plugins/qed/listset.ml +++ b/src/plugins/qed/listset.ml @@ -42,6 +42,7 @@ struct let equal = Hcons.equal_list E.equal let empty = [] + let is_empty = function [] -> true | _ -> false (* used for better sharing between a list and a modified list *) let rev_append_until i l1 l2 = diff --git a/src/plugins/qed/listset.mli b/src/plugins/qed/listset.mli index e37b3a70c4cfcc71b479a66a7cb74560bc9be49d..761b54bd054ed02aa158bf6d08307204cddca987 100644 --- a/src/plugins/qed/listset.mli +++ b/src/plugins/qed/listset.mli @@ -41,6 +41,7 @@ sig val compare : t -> t -> int val empty : t + val is_empty : t -> bool (* good sharing *) val add : elt -> t -> t diff --git a/src/plugins/wp/Cint.ml b/src/plugins/wp/Cint.ml index 7664ac4a71c16c2cbea578e7fb592303485412ae..c6d48f85cc31f16c9983b13534f09e9e6c629f93 100644 --- a/src/plugins/wp/Cint.ml +++ b/src/plugins/wp/Cint.ml @@ -257,8 +257,8 @@ let match_binop_one_extraction binop = match_list_extraction (match_binop_one_ar (* to_iota(e) where e = to_iota'(e'), only ranges for iota *) let simplify_range_comp f iota e conv e' = let iota' = to_cint conv in - let size' = Ctypes.range iota' in - let size = Ctypes.range iota in + let size' = Ctypes.i_bits iota' in + let size = Ctypes.i_bits iota in if size <= size' then e_fun f [e'] (* rule B: @@ -288,7 +288,7 @@ let configure_to_int iota = begin try match F.repr e with | Logic.Kint value -> - let size = Integer.of_int (Ctypes.range iota) in + let size = Integer.of_int (Ctypes.i_bits iota) in let signed = Ctypes.signed iota in F.e_zint (Integer.cast ~size ~signed ~value) | Logic.Fun( fland , es ) @@ -518,7 +518,7 @@ let smp_bitk_positive = function F.e_not (bitk_positive k a) | Logic.Fun( conv , [a] ) (* when is_to_c_int conv *) -> let iota = to_cint conv in - let range = Ctypes.range iota in + let range = Ctypes.i_bits iota in let signed = Ctypes.signed iota in if signed then (* beware of sign-bit *) begin match is_leq k (e_int (range-2)) with @@ -858,14 +858,15 @@ module Dom = struct let top = Tmap.empty [@@@ warning "-32"] - let print fmt dom = + let pretty fmt dom = Tmap.iter (fun k v -> Format.fprintf fmt "%a: %a,@ " Lang.F.pp_term k Ival.pretty v) dom - [@@@ warning "+32"] let find t dom = Tmap.find t dom + let get t dom = try find t dom with Not_found -> Ival.top + let narrow t v dom = if Ival.is_bottom v then raise Lang.Contradiction else if is_top_ival v then dom @@ -930,7 +931,7 @@ module Dom = struct | Fun(g,[a]) -> begin try (* just checks for a contraction *) let ubound = c_int_bounds_ival (is_cint g) (* may raise Not_found *) in - let v = find a dom (* may raise Not_found *) in + let v = Tmap.find a dom (* may raise Not_found *) in if Ival.is_included v ubound then raise Lang.Contradiction; dom with Not_found -> dom diff --git a/src/plugins/wp/Factory.ml b/src/plugins/wp/Factory.ml index 45339f9fa7496a9d2b2dca9d7cc28e3f20245792..23c889c0ac52eb3d4d44f9ce124d3663eaac4e5c 100644 --- a/src/plugins/wp/Factory.ml +++ b/src/plugins/wp/Factory.ml @@ -24,7 +24,7 @@ (* --- Model Factory --- *) (* -------------------------------------------------------------------------- *) -type mheap = Hoare | ZeroAlias | Typed of MemTyped.pointer +type mheap = Hoare | ZeroAlias | Region | Typed of MemTyped.pointer type mvar = Raw | Var | Ref | Caveat type setup = { @@ -64,6 +64,7 @@ let descr_mtyped d = function | MemTyped.Fits -> () let descr_mheap d = function + | Region -> main d "region" | ZeroAlias -> main d "zeroalias" | Hoare -> main d "hoare" | Typed p -> main d "typed" ; descr_mtyped d p @@ -157,6 +158,16 @@ struct end end +module Static : Proxy = +struct + let datatype = "Static" + let param x = + let open Cil_types in + if x.vaddrof || Cil.isArrayType x.vtype || Cil.isPointerType x.vtype + then MemoryContext.ByAddr else MemoryContext.ByValue + let iter = Raw.iter +end + (* -------------------------------------------------------------------------- *) (* --- RefUsage-based Proxies --- *) (* -------------------------------------------------------------------------- *) @@ -228,6 +239,7 @@ module MakeCompiler(M:Sigs.Model) = struct module A = LogicAssigns.Make(M)(C)(L) end +module Comp_Region = MakeCompiler(Register(Static)(MemRegion)) module Comp_MemZeroAlias = MakeCompiler(MemZeroAlias) module Comp_Hoare_Raw = MakeCompiler(Model_Hoare_Raw) module Comp_Hoare_Ref = MakeCompiler(Model_Hoare_Ref) @@ -240,6 +252,7 @@ module Comp_Caveat = MakeCompiler(Model_Caveat) let compiler mheap mvar : (module Sigs.Compiler) = match mheap , mvar with | ZeroAlias , _ -> (module Comp_MemZeroAlias) + | Region , _ -> (module Comp_Region) | _ , Caveat -> (module Comp_Caveat) | Hoare , (Raw|Var) -> (module Comp_Hoare_Raw) | Hoare , Ref -> (module Comp_Hoare_Ref) @@ -254,6 +267,7 @@ let compiler mheap mvar : (module Sigs.Compiler) = let configure_mheap = function | Hoare -> MemEmpty.configure () | ZeroAlias -> MemZeroAlias.configure () + | Region -> MemRegion.configure () | Typed p -> MemTyped.configure () ; Context.set MemTyped.pointer p let configure (s:setup) (d:driver) () = @@ -320,6 +334,7 @@ let split ~warning (m:string) : string list = let update_config ~warning m s = function | "ZEROALIAS" -> { s with mheap = ZeroAlias } + | "REGION" -> { s with mheap = Region } | "HOARE" -> { s with mheap = Hoare } | "TYPED" -> { s with mheap = Typed MemTyped.Fits } | "CAST" -> { s with mheap = Typed MemTyped.Unsafe } diff --git a/src/plugins/wp/Factory.mli b/src/plugins/wp/Factory.mli index b430af8263e69035c50e25a3808e1874baad50de..973daad343f83e449867c99592f1d3719573a678 100644 --- a/src/plugins/wp/Factory.mli +++ b/src/plugins/wp/Factory.mli @@ -24,7 +24,7 @@ (* --- Model Factory --- *) (* -------------------------------------------------------------------------- *) -type mheap = Hoare | ZeroAlias | Typed of MemTyped.pointer +type mheap = Hoare | ZeroAlias | Region | Typed of MemTyped.pointer type mvar = Raw | Var | Ref | Caveat type setup = { diff --git a/src/plugins/wp/Generator.ml b/src/plugins/wp/Generator.ml index 19d7566bd9e479187ddf4b71a8c69daaee38aeaf..1423602f463b8a50526ed8032a5698846cb3a2da 100644 --- a/src/plugins/wp/Generator.ml +++ b/src/plugins/wp/Generator.ml @@ -86,63 +86,42 @@ let compute_ip cc ip = (* --- Annotations Entry Point --- *) (* -------------------------------------------------------------------------- *) -type functions = - | F_All - | F_List of Cil_datatype.Kf.Set.t - | F_Skip of Cil_datatype.Kf.Set.t - -let iter_kf phi = function - | None -> Globals.Functions.iter phi - | Some kf -> phi kf - -let iter_fct phi = function - | F_All -> Globals.Functions.iter phi - | F_Skip fs -> - Globals.Functions.iter - (fun kf -> if not (Cil_datatype.Kf.Set.mem kf fs) then phi kf) - | F_List fs -> Cil_datatype.Kf.Set.iter phi fs - let add_kf cc ?bhv ?prop kf = let model = cc#model in let assigns = WpAnnot.WithAssigns in List.iter cc#add_strategy (WpAnnot.get_function_strategies ~model ~assigns ?bhv ?prop kf) +let add_lemmas cc = function + | None | Some[] -> + LogicUsage.iter_lemmas + (fun lem -> + let idp = WpPropId.mk_lemma_id lem in + if WpAnnot.filter_status idp then cc#add_lemma lem) + | Some ps -> + if List.mem "-@lemmas" ps then () + else LogicUsage.iter_lemmas + (fun lem -> + let idp = WpPropId.mk_lemma_id lem in + if WpAnnot.filter_status idp && WpPropId.select_by_name ps idp + then cc#add_lemma lem) + let compute_kf cc ?kf ?bhv ?prop () = begin - iter_kf (add_kf cc ?bhv ?prop) kf ; + Extlib.may (add_kf cc ?bhv ?prop) kf ; cc#compute end -let do_lemmas = function F_All | F_Skip _ -> true | F_List _ -> false - -let compute_selection cc ?(fct=F_All) ?bhv ?prop () = +let compute_selection cc ?(fct=Wp_parameters.Fct_all) ?bhv ?prop () = begin - if do_lemmas fct then - begin - match prop with - | None | Some[] -> - LogicUsage.iter_lemmas - (fun lem -> - let idp = WpPropId.mk_lemma_id lem in - if WpAnnot.filter_status idp then cc#add_lemma lem) - | Some ps -> - if List.mem "-@lemmas" ps then () - else LogicUsage.iter_lemmas - (fun lem -> - let idp = WpPropId.mk_lemma_id lem in - if WpAnnot.filter_status idp && WpPropId.select_by_name ps idp - then cc#add_lemma lem) - end ; - iter_fct (add_kf cc ?bhv ?prop) fct ; + add_lemmas cc prop ; + Wp_parameters.iter_fct (add_kf cc ?bhv ?prop) fct ; cc#compute end -(* -------------------------------------------------------------------------- *) -(* --- Calls Entry Point --- *) -(* -------------------------------------------------------------------------- *) - let compute_call cc stmt = let model = cc#model in List.iter cc#add_strategy (WpAnnot.get_call_pre_strategies ~model stmt) ; cc#compute + +(* -------------------------------------------------------------------------- *) diff --git a/src/plugins/wp/Generator.mli b/src/plugins/wp/Generator.mli index 123691fc02993f51c74b6a207e0cddffb30b48f9..72e40d4b919d7178a905b829292b572bdc4e42e1 100644 --- a/src/plugins/wp/Generator.mli +++ b/src/plugins/wp/Generator.mli @@ -33,18 +33,17 @@ class type computer = method compute : Wpo.t Bag.t end -type functions = - | F_All - | F_List of Cil_datatype.Kf.Set.t - | F_Skip of Cil_datatype.Kf.Set.t +open Wp_parameters val compute_ip : computer -> Property.t -> Wpo.t Bag.t val compute_call : computer -> Cil_types.stmt -> Wpo.t Bag.t + val compute_kf : computer -> ?kf:Kernel_function.t -> ?bhv:string list -> ?prop:string list -> unit -> Wpo.t Bag.t + val compute_selection : computer -> ?fct:functions -> ?bhv:string list -> diff --git a/src/plugins/wp/GuiPanel.ml b/src/plugins/wp/GuiPanel.ml index da074d2311efa22959f55a17467314188ed34ac0..253b9ef08efdbfa0fd33dfee36d2b4f4d1268ee6 100644 --- a/src/plugins/wp/GuiPanel.ml +++ b/src/plugins/wp/GuiPanel.ml @@ -87,7 +87,7 @@ let run_and_prove (* --- Model Panel --- *) (* ------------------------------------------------------------------------ *) -type memory = TREE | HOARE | TYPED +type memory = TREE | HOARE | TYPED | REGION class model_selector (main : Design.main_window_extension_points) = let dialog = new Wpane.dialog @@ -128,6 +128,7 @@ class model_selector (main : Design.main_window_extension_points) = begin (match s.mheap with | ZeroAlias -> memory#set TREE + | Region -> memory#set REGION | Hoare -> memory#set HOARE | Typed m -> memory#set TYPED ; c_casts#set (m = MemTyped.Unsafe)) ; c_byref#set (s.mvar = Ref) ; @@ -138,6 +139,7 @@ class model_selector (main : Design.main_window_extension_points) = method get : setup = let m = match memory#get with | TREE -> ZeroAlias + | REGION -> Region | HOARE -> Hoare | TYPED -> Typed (if c_casts#get then MemTyped.Unsafe else MemTyped.Fits) diff --git a/src/plugins/wp/Lang.ml b/src/plugins/wp/Lang.ml index 8e3198ad1a8ddd7d9b8a597fa72efbf1ef740b87..a1cd8c082965e828251e992e1f7d4ec8990ea82c 100644 --- a/src/plugins/wp/Lang.ml +++ b/src/plugins/wp/Lang.ml @@ -176,7 +176,7 @@ let t_int = Logic.Int let t_bool = Logic.Bool let t_real = Logic.Real let t_prop = Logic.Prop -let t_addr () = Context.get pointer (Cil_types.TVoid []) +let t_addr () = Context.get pointer Cil.voidType let t_array a = Logic.Array(Logic.Int,a) let t_farray a b = Logic.Array(a,b) let t_datatype adt ts = Logic.Data(adt,ts) diff --git a/src/plugins/wp/Lang.mli b/src/plugins/wp/Lang.mli index ed8866cc4a1de4ac1c7b4dc05b410a7943e88383..7f1f0f1a35815877a55c4a4cbc9d9f9a4effebeb 100644 --- a/src/plugins/wp/Lang.mli +++ b/src/plugins/wp/Lang.mli @@ -31,7 +31,10 @@ open Qed.Logic type library = string +(** Name for external prover. + In case a Qed.Engine.link is used, [F_subst] patterns + are not supported for Why-3. *) type 'a infoprover = { altergo: 'a; why3 : 'a; @@ -161,7 +164,7 @@ val t_int : tau val t_real : tau val t_bool : tau val t_prop : tau -val t_addr : unit -> tau +val t_addr : unit -> tau (** pointer on Void *) val t_array : tau -> tau val t_farray : tau -> tau -> tau val t_datatype : adt -> tau list -> tau diff --git a/src/plugins/wp/Layout.ml b/src/plugins/wp/Layout.ml new file mode 100644 index 0000000000000000000000000000000000000000..d71aa0bb8cc132e7a844d95f7d671948f6ac56e8 --- /dev/null +++ b/src/plugins/wp/Layout.ml @@ -0,0 +1,701 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2019 *) +(* CEA (Commissariat a l'energie atomique et aux energies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Pretty_utils +open Cil_datatype +open Cil_types + +module Wp = Wp_parameters + +module type Data = +sig + type t + val equal : t -> t -> bool + val compare : t -> t -> int + val pretty : t formatter +end + +(* -------------------------------------------------------------------------- *) +(* --- Offsets --- *) +(* -------------------------------------------------------------------------- *) + +type offset = + | Field of fieldinfo + | Index of typ * int + +module Offset = +struct + type t = offset + let compare a b = + if a == b then 0 else match a,b with + | Field f, Field g -> Fieldinfo.compare f g + | Field _ , _ -> (-1) + | _ , Field _ -> 1 + | Index(ta,n) , Index(tb,m) -> + let cmp = Typ.compare ta tb in + if cmp <> 0 then cmp else Pervasives.compare n m + + let equal a b = (compare a b = 0) + + let pretty fmt = function + | Field fd -> Format.fprintf fmt "{%s}.%a" fd.fcomp.cname Fieldinfo.pretty fd + | Index(ty,n) -> Format.fprintf fmt "{%a}[%d]" Typ.pretty ty n + + let typeof = function + | Field f -> f.ftype + | Index(ty,_) -> ty + + let field fd = Field fd + + let index ty = + match Cil.unrollType ty with + | TArray(te,n,_,_) -> + begin + match Extlib.opt_bind Ctypes.get_int n with + | None -> failwith "Wp.Layout: unkown array size" + | Some n -> Index(te,n) + end + | _ -> failwith "Wp.Layout: not an array-type" + + let rec typeof_chain ty = function [] -> ty | _::ds -> typeof_chain ty ds + + let rec pp_chain ty fmt = function + | [] -> () + | d::ds -> + let next = + Format.pp_print_cut fmt () ; + match d with + | Index(t,n) when Typ.equal t ty -> + Format.fprintf fmt "[%d]" n ; t + | d -> Format.fprintf fmt "%a" pretty d ; typeof d + in pp_chain next fmt ds + + module H = Compinfo.Hashtbl + + type cache = typ H.t + let cache () : cache = H.create 0 + + let typ_of_comp cache comp = + try H.find cache comp with Not_found -> + let typ = TComp(comp,Cil.empty_size_cache (),[]) in + H.add cache comp typ ; typ + + let field_offset cache fd = + let typ = typ_of_comp cache fd.fcomp in + let offset = Cil_types.(Field(fd,NoOffset)) in + Cil.bitsOffset typ offset + + let range_field cache fd = + let typ = typ_of_comp cache fd.fcomp in + let offset = Cil_types.(Field(fd,NoOffset)) in + Cil.bitsOffset typ offset , Cil.bitsSizeOf typ + + let range_index typ n = + let len = Cil.bitsSizeOf typ * n in (0 , len) , len + + let range cache = function + | Field fd -> range_field cache fd + | Index(typ,n) -> range_index typ n + + let sizeof = function + | Field fd -> Cil.bitsSizeOf fd.ftype + | Index(ty,n) -> Cil.bitsSizeOf ty * n + + let container cache = function + | Index(ty,n) -> Cil.bitsSizeOf ty * n + | Field fd -> Cil.bitsSizeOf (typ_of_comp cache fd.fcomp) + +end + +(* -------------------------------------------------------------------------- *) +(* --- Deref --- *) +(* -------------------------------------------------------------------------- *) + +type alias = NotUsed | NotAliased | Aliased +type usage = Value | Deref | Array +type deref = usage * typ + +module Alias = +struct + let use = function NotUsed | NotAliased -> NotAliased | Aliased -> Aliased + let is_aliased = function NotUsed | NotAliased -> false | Aliased -> true + let merge a b = + match a,b with + | Aliased,_ | _,Aliased -> Aliased + | NotAliased,NotAliased -> NotAliased + | NotUsed,c | c,NotUsed -> c + let alias a b = + match a,b with + | NotUsed,c | c,NotUsed -> c + | _ -> Aliased + let to_string = function + | NotUsed -> "not used" + | NotAliased -> "not aliased" + | Aliased -> "aliased" + let pretty fmt a = Format.pp_print_string fmt (to_string a) +end + +module Usage = +struct + let pretty fmt = function + | Value -> () + | Deref -> Format.pp_print_char fmt '*' + | Array -> Format.pp_print_string fmt "[]" + let order = function Value -> 0 | Deref -> 1 | Array -> 2 + let merge a b = if order a < order b then b else a + let is_aliased = function Value -> false | Deref | Array -> true + let is_shifted = function Value | Deref -> false | Array -> true +end + +module Deref = +struct + type t = deref + + let pretty fmt (usage,typ) = + Format.fprintf fmt "{%a}" Typ.pretty typ ; + Usage.pretty fmt usage + + let compare ((da,ta):t) ((db,tb):t) = + let cmp = Pervasives.compare da db in + if cmp <> 0 then cmp else Typ.compare ta tb + + let equal a b = (compare a b = 0) +end + +(* -------------------------------------------------------------------------- *) +(* --- Access --- *) +(* -------------------------------------------------------------------------- *) + +type lvalue = + | Eval of exp + | Tval of term + | Assigned of stmt + +module Lvalue = +struct + + type t = lvalue + + let order = function Eval _ -> 0 | Tval _ -> 1 | Assigned _ -> 2 + + let compare a b = if a == b then 0 else match a,b with + | Eval x , Eval y -> Exp.compare x y + | Tval x , Tval y -> Term.compare x y + | Assigned a , Assigned b -> Stmt.compare a b + | _ -> order a - order b + + let equal a b = a == b || match a,b with + | Eval x , Eval y -> Exp.equal x y + | Tval x , Tval y -> Term.equal x y + | Assigned a , Assigned b -> Stmt.equal a b + | _ -> false + + let pretty fmt = function + | Eval x -> Exp.pretty fmt x + | Tval t -> Term.pretty fmt t + | Assigned { skind = Instr(Set(lv,_,_)) } + | Assigned { skind = Instr(Call(Some lv,_,_,_)) } -> Lval.pretty fmt lv + | Assigned { skind = Instr(Local_init(x,_,_)) } -> Varinfo.pretty fmt x + | Assigned stmt -> Format.fprintf fmt "stmt:s%d" stmt.sid + +end + +module Mode(OPT : sig val get : unit -> bool end) = +struct + let default = OPT.get + let merge a b = if default () then a && b else a || b +end + +module RW = Mode(Wp.Region_rw) +module Flat = Mode(Wp.Region_flat) +module Pack = Mode(Wp.Region_pack) + +(* -------------------------------------------------------------------------- *) +(* --- Data Layout --- *) +(* -------------------------------------------------------------------------- *) + +type 'a value = + | Int of Ctypes.c_int + | Float of Ctypes.c_float + | Pointer of 'a + +module Value = +struct + + let compare phi u v = + if u == v then 0 else match u,v with + | Int a , Int b -> Ctypes.compare_c_int a b + | Int _ , _ -> (-1) + | _ , Int _ -> 1 + | Float a , Float b -> Ctypes.compare_c_float a b + | Float _ , _ -> (-1) + | _ , Float _ -> 1 + | Pointer ra , Pointer rb -> phi ra rb + + let equal phi a b = + match a,b with + | Pointer ra , Pointer rb -> phi ra rb + | Int a , Int b -> a = b + | Float a , Float b -> a = b + | _ -> false + + let pretty pp fmt = function + | Int iota -> Ctypes.pp_int fmt iota + | Float flt -> Ctypes.pp_float fmt flt + | Pointer r -> Format.fprintf fmt "ptr(%a)" pp r + + let sizeof = function + | Int iota -> Ctypes.i_bits iota + | Float flt -> Ctypes.f_bits flt + | Pointer _ -> Ctypes.p_bits () + + let pointed = function + | Int _ | Float _ -> None + | Pointer r -> Some r + + let merge mu a b = + match a,b with + | Int i , Int j when i = j -> Some a + | Float f , Float g when f = g -> Some a + | Pointer r , Pointer r' -> Some(Pointer(mu r r')) + | _ -> None + +end + +module Matrix = +struct + + let rec gcd a b = if b = 0 then a else gcd b (a mod b) + + let pretty fmt = function + | [] -> () + | d::ds -> + Format.fprintf fmt "@[<hov 1>[%d" d ; + List.iter (fun d -> Format.fprintf fmt ",@,%d" d) ds ; + Format.fprintf fmt "]@]" + + let rec sizeof n = function [] -> n | d::ds -> sizeof (n*d) ds + + let array ds n = if n = 1 then ds else ds @ [n] + + (* Assumes s divides len *) + let join_array s len = let n = len / s in if n = 1 then [] else [n] + + (* Assumes s divides len , computes (s,ds) that fits exactly in len + with ds maximal prefix of da and db *) + let rec join s da db len = + match da , db with + | d::da , d'::db when d = d' -> + let s' = s * d in + if len mod s' = 0 then d :: join s' da db len else + join_array s len + | _ -> join_array s len + + let rec merge d1 d2 = + match d1 , d2 with + | n::d1 , n'::d2 when n=n' -> n :: merge d1 d2 + | _ -> [] + +end + +(* -------------------------------------------------------------------------- *) +(* --- Range & Overlays --- *) +(* -------------------------------------------------------------------------- *) + +let garbled_key = Wp.register_category "garbled" + +type dim = Raw of int | Dim of int * int list + +type 'a range = { + ofs : int ; (* in bits, start from 0 *) + len : int ; + reg : 'a ; + dim : dim ; +} + +type 'a overlay = 'a range list + +type 'a merger = raw:bool -> 'a -> 'a -> 'a + +module Range = +struct + + let pp_dim fmt = function + | Raw _ -> Format.pp_print_string fmt "raw" + | Dim(s,ds) -> Format.fprintf fmt "{%d}%a" s Matrix.pretty ds + + let pretty pp fmt { ofs ; len ; reg ; dim } = + Format.fprintf fmt "%d..%d: %a#%a" ofs (ofs+len-1) pp reg pp_dim dim + + let overlap (type a) (_ : a formatter) (mu : a merger) ra rb = + let aligned = ref None in + let ofs = min ra.ofs rb.ofs in + let len = max (ra.ofs + ra.len) (rb.ofs + rb.len) - ofs in + begin match ra.dim , rb.dim with + | Dim(s,da) , Dim(s',db) when s = s' -> + if len mod s = 0 then + let ta = abs (ra.ofs - rb.ofs) in + let tb = abs (ra.ofs + ra.len - rb.ofs - rb.len) in + if ta mod s = 0 && tb mod s = 0 then + let reg = mu ~raw:false ra.reg rb.reg in + let ds = Matrix.join s da db len in + let dim = Dim(s,ds) in + aligned := Some { ofs ; len ; reg ; dim } + | _ -> () + end ; + match !aligned with + | Some rg -> rg + | None -> { ofs ; len ; reg = mu ~raw:true ra.reg rb.reg ; dim = Raw len } + + let shift ofs rg = { rg with ofs = rg.ofs + ofs } + + let flatten rg = match rg.dim with + | Dim(s,ds) when ds <> [] -> + let n = Matrix.sizeof 1 ds in + { rg with dim = Dim(s,Matrix.array [] n) } + | _ -> rg + + let included p n { ofs ; len } = + ofs <= p && p + n <= ofs + len + +end + +module Overlay = +struct + + let pretty ?title pp fmt rs = + begin + Format.fprintf fmt "@[<hv 0>" ; + Extlib.may (fun pp -> pp fmt) title ; + Format.fprintf fmt "@[<hov 2>{" ; + List.iter + (fun rg -> + Format.fprintf fmt "@ @[<hov 2>%a@];" (Range.pretty pp) rg + ) rs ; + Format.fprintf fmt "@]@ }@]" ; + end + + let rec merge (pp : 'a formatter) (mu : _ merger) ova ovb = + match ova , ovb with + | [],ovc | ovc,[] -> ovc + | ra::wa , rb::wb -> + let sa = ra.ofs + ra.len in + let sb = rb.ofs + rb.len in + if sa <= rb.ofs then ra :: merge pp mu wa ovb else + if sb <= ra.ofs then rb :: merge pp mu ova wb else + if sa < sb then + merge pp mu wa (Range.overlap pp mu ra rb :: wb) + else + merge pp mu (Range.overlap pp mu ra rb :: wa) wb + + let rec pack eq = function + | ({ dim = Dim(s ,da) } as ra ) :: + ({ dim = Dim(s',db) } as rb ) :: + ovl when eq ra.reg rb.reg && s = s' && ra.ofs + ra.len = rb.ofs -> + let len = ra.len + rb.len in + let ds = Matrix.join s da db len in + pack eq ({ ofs = ra.ofs ; len ; reg = ra.reg ; dim = Dim(s,ds) } :: ovl) + | rg :: ovl -> + rg :: pack eq ovl + | [] -> [] + + let flatten ovl = List.map Range.flatten ovl + + let once reg overlay = + match List.filter (fun rg -> rg.reg == reg) overlay with + | [] | [_] -> true | _ -> false + +end + +(* -------------------------------------------------------------------------- *) +(* --- Layout --- *) +(* -------------------------------------------------------------------------- *) + +type 'a layout = { + sizeof : int ; + layout : 'a overlay ; +} + +module Compound = +struct + + let garbled cache offset reg = + let (ofs,len),sizeof = Offset.range cache offset in + { sizeof ; layout = [ { ofs ; len ; reg ; dim = Raw len } ] } + + let field cache fd reg dim = + let (ofs,len),sizeof = Offset.range_field cache fd in + { sizeof ; layout = [ { ofs ; len ; reg ; dim } ] } + + let index te n reg dim = + let len = Cil.bitsSizeOf te * n in + { sizeof = len ; layout = [ { ofs = 0 ; len ; reg ; dim } ] } + + let reshape ~eq ~flat ~pack { sizeof ; layout } = + let ovl = if flat then Overlay.flatten layout else layout in + let ovl = if pack then Overlay.pack eq ovl else ovl in + { sizeof ; layout = ovl } + +end + +(* -------------------------------------------------------------------------- *) +(* --- Clustering --- *) +(* -------------------------------------------------------------------------- *) + +type 'a cluster = + | Empty + | Garbled + | Chunk of 'a value + | Layout of 'a layout + +module Cluster = +struct + + let is_empty = function Empty -> true | _ -> false + let is_garbled = function Garbled -> true | _ -> false + + let pretty pp fmt = function + | Empty -> Format.pp_print_string fmt "empty" + | Garbled -> Format.pp_print_string fmt "garbled" + | Chunk v -> Value.pretty pp fmt v + | Layout { sizeof ; layout } -> + Overlay.pretty + ~title:(fun fmt -> Format.fprintf fmt "sizeof:%d" sizeof) + pp fmt layout + + let deref ~pointed (_,typ) = + match Cil.unrollType typ with + | TInt(ti,_) | TEnum({ ekind = ti },_) -> Chunk (Int (Ctypes.c_int ti)) + | TFloat(tf,_) -> Chunk (Float (Ctypes.c_float tf)) + | TPtr _ | TFun _ -> Chunk(Pointer(Lazy.force pointed)) + | TVoid _ | TNamed _ | TComp _ | TArray _ | TBuiltin_va_list _ -> Empty + + let rec get_dim s rds typ = + if s = Cil.bitsSizeOf typ then Some (List.rev rds) else + match Cil.unrollType typ with + | TArray( te , Some e , _ , _ ) -> + begin match Ctypes.get_int e with + | None -> None + | Some n -> get_dim s (if n = 1 then rds else n::rds) te + end + | _ -> None + + let shift_may cache pp offset reg ~inline cluster = + match offset , cluster with + | _ , Garbled -> None + | _ , Empty -> + let sizeof = Offset.container cache offset in + Some { sizeof ; layout = [] } + | Field fd , Chunk v -> + begin + let s = Value.sizeof v in + match get_dim s [] fd.ftype with + | None -> None + | Some ds -> + let dim = Dim(s,ds) in + Some (Compound.field cache fd reg dim) + end + | Index(te,n) , Chunk v -> + begin + let s = Value.sizeof v in + match get_dim s (Matrix.array [] n) te with + | None -> None + | Some ds -> + let dim = Dim(s,ds) in + Some (Compound.index te n reg dim) + end + | Field fd , Layout d -> + let (ofs,len),sizeof = Offset.range_field cache fd in + if d.sizeof = len then + let layout = + if inline then + List.map (Range.shift ofs) d.layout + else + [ { ofs ; len ; reg ; dim=Dim(len,[]) } ] + in Some { sizeof ; layout } + else None + | Index(te,n) , Layout { + sizeof = s ; + layout = [ { ofs=0 ; len ; reg ; dim = Dim(se,dse) } ] + } + when inline && s = len && Cil.bitsSizeOf te = len -> + let dim = Dim(se,Matrix.array dse n) in + Some (Compound.index te n reg dim) + | Index(te,n) , Layout { sizeof } -> + let size = Cil.bitsSizeOf te in + if sizeof = size then + let dim = Dim(size,Matrix.array [] n) in + Some (Compound.index te n reg dim) + else + ( if Wp.has_dkey garbled_key then + Wp.debug ~dkey:garbled_key + "@[<hv 0>Garbled Offset:@ Index= {%a}[%d];@ Cluster= %a;@]" + Cil_datatype.Typ.pretty te n (pretty pp) cluster ; + None ) + + let shift cache pp offset reg ~inline cluster = + match shift_may cache pp offset reg ~inline cluster + with Some ovl -> ovl + | None -> Compound.garbled cache offset reg + + let do_merge pp (mu : 'a merger) (a : 'a cluster) (b : 'a cluster) = + match a,b with + | Empty , c | c , Empty -> c + | Chunk va , Chunk vb -> + begin match Value.merge (mu ~raw:false) va vb with + | None -> Garbled + | Some v -> Chunk v + end + | Layout { layout = [ { ofs=0 ; len=la ; reg=ra ; dim=Dim(s,da) } ] } , + Layout { layout = [ { ofs=0 ; len=lb ; reg=rb ; dim=Dim(s',db) } ] } + when s = s' -> + let reg = mu ~raw:false ra rb in + let len = max la lb in + let ds = Matrix.join s da db len in + let layout = [ { ofs=0 ; len ; reg ; dim=Dim(s,ds) } ] in + Layout { sizeof = len ; layout } + | Layout { sizeof ; layout = la } , + Layout { sizeof = s ; layout = lb } + when s = sizeof -> + let layout = Overlay.merge pp mu la lb in + Layout { sizeof ; layout } + | _ -> Garbled + + let merge pp mu a b = + let result = do_merge pp mu a b in + if result = Garbled && Wp.has_dkey garbled_key then + Wp.debug ~dkey:garbled_key + "@[<hv 0>Garbled Clusters:@ A=%a@ B=%a@]" + (pretty pp) a (pretty pp) b ; + result + + let reshape ~eq ~flat ~pack = function + | Layout layout when flat || pack -> + Layout (Compound.reshape ~eq ~flat ~pack layout) + | cluster -> cluster + +end + +(* -------------------------------------------------------------------------- *) +(* --- Roots --- *) +(* -------------------------------------------------------------------------- *) + +type 'a from = + | Fvar of varinfo + | Ffield of 'a * int + | Findex of 'a + | Fderef of 'a + | Farray of 'a + +type root = + | Rnone + | Rfield of varinfo * int (* static offset *) + | Rindex of varinfo (* any offset rooted at var *) + | Rtop + +module Root = +struct + + let pretty fmt = function + | Rtop -> Format.pp_print_string fmt "*" + | Rnone -> Format.pp_print_string fmt "-" + | Rfield(x,0) -> Format.fprintf fmt "&%a" Varinfo.pretty x + | Rfield(x,ofs) -> Format.fprintf fmt "&%a+%d" Varinfo.pretty x ofs + | Rindex(x) -> Format.fprintf fmt "&%a+(..)" Varinfo.pretty x + + let field ofs = function + | Rfield(x,p) -> Rfield(x,p+ofs) + | (Rindex _ | Rnone | Rtop) as r -> r + + let index = function + | Rfield(x,_) -> Rindex x + | (Rindex _ | Rnone | Rtop) as r -> r + + let from ~root = function + | Fvar x -> Rfield(x,0) + | Ffield(r,ofs) -> field ofs (root r) + | Findex r -> index (root r) + | Fderef r -> root r + | Farray _ -> Rtop + + let merge_var a b = match a,b with + | (Rfield(x,_) | Rindex x) , + (Rfield(y,_) | Rindex y) + when Varinfo.equal x y -> Some x + | _ -> None + + let merge_field x a b = match a,b with + | Rfield(_,p) , Rfield(_,q) when p = q -> a + | _ -> Rindex x + + let merge a b = + if a == b then a else + match a,b with + | Rnone,s | s,Rnone -> s + | Rtop,_ | _,Rtop -> Rtop + | _ -> + match merge_var a b with + | Some x -> merge_field x a b + | None -> Rtop + + let indexed = function + | Rnone | Rfield _ -> false + | Rindex _ | Rtop -> true + + let framed = function + | Rfield(x,_) | Rindex x -> not x.vglob && not x.vaddrof (* Cf. MemVar *) + | Rnone -> true + | Rtop -> false + +end + +(* -------------------------------------------------------------------------- *) +(* --- Chunks --- *) +(* -------------------------------------------------------------------------- *) + +module R = Qed.Intset + +type chunks = R.t + +type 'a chunk = + | Mref of 'a + | Mmem of root * 'a value + | Mraw of root * 'a option + | Mcomp of chunks * 'a overlay + +module Chunk = +struct + let mem = R.mem + let empty = R.empty + let singleton = R.singleton + let union = R.union + let union_map f es = List.fold_left (fun w e -> R.union w @@ f e) R.empty es + let disjoint a b = not (R.intersect a b) + let pretty pp fmt es = + begin + Format.fprintf fmt "@[<hov 2>{" ; + R.iter (fun e -> Format.fprintf fmt "@ %a" pp e) es ; + Format.fprintf fmt " }@]" ; + end +end + +(* -------------------------------------------------------------------------- *) diff --git a/src/plugins/wp/Layout.mli b/src/plugins/wp/Layout.mli new file mode 100644 index 0000000000000000000000000000000000000000..afb433b20663d8a8cb7970bd70a1049be1906fb2 --- /dev/null +++ b/src/plugins/wp/Layout.mli @@ -0,0 +1,284 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2019 *) +(* CEA (Commissariat a l'energie atomique et aux energies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Region Utilities *) + +open Pretty_utils +open Cil_types + +module type Data = +sig + type t + val equal : t -> t -> bool + val compare : t -> t -> int + val pretty : t formatter +end + +(* -------------------------------------------------------------------------- *) +(** {2 L-Path} *) +(* -------------------------------------------------------------------------- *) + +type offset = + | Field of fieldinfo + | Index of typ * int + +type lvalue = (** Generalized l-values *) + | Eval of exp + | Tval of term + | Assigned of stmt + +module Offset : +sig + include Data with type t = offset + val index : typ -> offset + val field : fieldinfo -> offset + val typeof : offset -> typ + val typeof_chain : typ -> offset list -> typ + val pp_chain : typ -> offset list formatter + + type cache + val cache : unit -> cache + val field_offset : cache -> fieldinfo -> int * int (* in bits *) + val range : cache -> offset -> (int * int) * int (* in bits *) + val sizeof : offset -> int (* in bits *) +end + +module Lvalue : Data with type t = lvalue + +(* -------------------------------------------------------------------------- *) +(** {2 Access} *) +(* -------------------------------------------------------------------------- *) + +type alias = NotUsed | NotAliased | Aliased +type usage = Value | Deref | Array +type deref = usage * typ + +module Alias : +sig + val use : alias -> alias + val merge : alias -> alias -> alias + val alias : alias -> alias -> alias + val is_aliased : alias -> bool + val pretty : alias formatter +end + +module Usage : +sig + val pretty : usage formatter + val merge : usage -> usage -> usage + val is_shifted : usage -> bool + val is_aliased : usage -> bool +end + +module Deref : Data with type t = deref + +(* -------------------------------------------------------------------------- *) +(** {2 R-Values} *) +(* -------------------------------------------------------------------------- *) + +type 'a value = + | Int of Ctypes.c_int + | Float of Ctypes.c_float + | Pointer of 'a + +module Value : +sig + + val compare : ('a -> 'a -> int) -> 'a value -> 'a value -> int + val equal : ('a -> 'a -> bool) -> 'a value -> 'a value -> bool + val pretty : 'a formatter -> 'a value formatter + + val sizeof : 'a value -> int + val pointed : 'a value -> 'a option + + val merge : ('a -> 'a -> 'a) -> 'a value -> 'a value -> 'a value option + +end + +module Matrix : +sig + + val gcd : int -> int -> int + val pretty : int list formatter + val sizeof : int -> int list -> int + val merge : int list -> int list -> int list + +end + +(* -------------------------------------------------------------------------- *) +(** {2 Overlays} *) +(* -------------------------------------------------------------------------- *) + +type dim = Raw of int | Dim of int * int list + +type 'a range = private { + ofs : int ; (* in bits, start from 0 *) + len : int ; + reg : 'a ; + dim : dim ; +} + +type 'a overlay = 'a range list + +type 'a merger = raw:bool -> 'a -> 'a -> 'a + +module Range : +sig + + val pretty : 'a formatter -> 'a range formatter + val overlap : 'a formatter -> 'a merger -> 'a range -> 'a range -> 'a range + val included : int -> int -> 'a range -> bool + +end + +module Overlay : +sig + + val pretty : ?title:(Format.formatter -> unit) -> + 'a formatter -> 'a overlay formatter + val merge : 'a formatter -> + 'a merger -> 'a overlay -> 'a overlay -> 'a overlay + + val once : 'a -> 'a overlay -> bool + +end + +(* -------------------------------------------------------------------------- *) +(** {2 Compound Layout} *) +(* -------------------------------------------------------------------------- *) + +type 'a layout = { + sizeof : int ; + layout : 'a overlay ; +} + +module Compound : +sig + + val garbled : Offset.cache -> offset -> 'a -> 'a layout + val reshape : eq:('a -> 'a -> bool) -> flat:bool -> pack:bool -> + 'a layout -> 'a layout + +end + +(* -------------------------------------------------------------------------- *) +(** {2 Clustering} *) +(* -------------------------------------------------------------------------- *) + +type 'a cluster = + | Empty + | Garbled + | Chunk of 'a value + | Layout of 'a layout + +module Cluster : +sig + + val pretty : 'a formatter -> 'a cluster formatter + val deref : pointed:'a Lazy.t -> deref -> 'a cluster + val shift : Offset.cache -> 'a formatter -> + offset -> 'a -> inline:bool -> 'a cluster -> 'a layout + val merge : 'a formatter -> 'a merger -> 'a cluster -> 'a cluster -> 'a cluster + val is_empty : 'a cluster -> bool + val is_garbled : 'a cluster -> bool + val reshape : eq:('a -> 'a -> bool) -> flat:bool -> pack:bool -> + 'a cluster -> 'a cluster + +end + +(* -------------------------------------------------------------------------- *) +(** {2 Roots} *) +(* -------------------------------------------------------------------------- *) + +type 'a from = + | Fvar of varinfo + | Ffield of 'a * int + | Findex of 'a + | Fderef of 'a + | Farray of 'a + +type root = + | Rnone + | Rfield of varinfo * int (* static offset *) + | Rindex of varinfo (* any offset rooted at var *) + | Rtop + +module Root : +sig + + val pretty : root formatter + val from : root:('a -> root) -> 'a from -> root + val merge : root -> root -> root + val indexed : root -> bool + val framed : root -> bool + +end + +(* -------------------------------------------------------------------------- *) +(** {2 Chunks} *) +(* -------------------------------------------------------------------------- *) + +type chunks = Qed.Intset.t + +type 'a chunk = + | Mref of 'a (** Constant pointers to region *) + | Mmem of root * 'a value (** Aliased values *) + | Mraw of root * 'a option (** Bits that may points-to *) + | Mcomp of chunks * 'a overlay (** Aliased chunks & overlay *) + +module Chunk : +sig + val empty : chunks + val singleton : int -> chunks + val union : chunks -> chunks -> chunks + val disjoint : chunks -> chunks -> bool + val union_map : ('a -> chunks) -> 'a list -> chunks + val mem : int -> chunks -> bool + val pretty : int formatter -> chunks formatter +end + +(* -------------------------------------------------------------------------- *) +(** {2 Options} *) +(* -------------------------------------------------------------------------- *) + +(** Read-Write access *) +module RW : +sig + val default : unit -> bool + val merge : bool -> bool -> bool +end + +(** Flatten arrays *) +module Flat : +sig + val default : unit -> bool + val merge : bool -> bool -> bool +end + +(** Pack fields *) +module Pack : +sig + val default : unit -> bool + val merge : bool -> bool -> bool +end + +(* -------------------------------------------------------------------------- *) diff --git a/src/plugins/wp/LogicAssigns.ml b/src/plugins/wp/LogicAssigns.ml index 024797e31770826ea1a2ef947e00793690f57e50..8da52bbfe3284f24683773458023027af7e55c15 100644 --- a/src/plugins/wp/LogicAssigns.ml +++ b/src/plugins/wp/LogicAssigns.ml @@ -53,7 +53,8 @@ struct | [] -> Bag.concat (M.Sigma.assigned ~pre:s.pre ~post:s.post D.empty) hs | [obj,sloc] -> - let hs_sloc = Bag.list (M.assigned s obj sloc) in + let eq_sloc = M.assigned s obj sloc in + let hs_sloc = Bag.list (List.map Cvalues.equation eq_sloc) in let hs_sdom = M.Sigma.assigned ~pre:s.pre ~post:s.post (dsloc obj sloc) in Bag.concat (Bag.concat hs_sloc hs_sdom) hs @@ -61,7 +62,8 @@ struct let sigma = M.Sigma.havoc s.post (dsloc obj sloc) in let s_local = { pre = sigma ; post = s.post } in let s_other = { pre = s.pre ; post = sigma } in - let hs_sloc = Bag.list (M.assigned s_local obj sloc) in + let eq_sloc = M.assigned s_local obj sloc in + let hs_sloc = Bag.list (List.map Cvalues.equation eq_sloc) in assigned_seq (Bag.concat hs_sloc hs) s_other tail let apply_assigns (s:sigma sequence) (r: M.loc Sigs.region) = diff --git a/src/plugins/wp/Makefile.in b/src/plugins/wp/Makefile.in index 700675e62b85cd73ce33bf43d4dad80af0525a23..c4d82ec1ddebe78e7601bcfaebcb2a6a3d6487a3 100644 --- a/src/plugins/wp/Makefile.in +++ b/src/plugins/wp/Makefile.in @@ -65,10 +65,12 @@ PLUGIN_CMO:= \ Why3Provers \ Context Warning MemoryContext wpContext \ LogicUsage RefUsage \ + Layout Region \ + RegionAnnot RegionAccess RegionDump RegionAnalysis \ cil2cfg normAtLabels wpPropId mcfg \ Lang Repr Matrix Passive Splitter \ LogicBuiltins Definitions \ - Cmath Cint Cfloat Vset Vlist Region Cstring Cvalues \ + Cmath Cint Cfloat Vset Vlist Cstring Cvalues \ Letify Cleaning \ Sigs Mstate Conditions \ Filtering \ @@ -76,7 +78,9 @@ PLUGIN_CMO:= \ CodeSemantics \ LogicCompiler \ LogicSemantics LogicAssigns \ - Sigma MemEmpty MemZeroAlias MemVar MemTyped \ + Sigma MemLoader \ + MemEmpty MemZeroAlias MemVar \ + MemMemory MemTyped MemRegion \ wpStrategy wpRTE wpAnnot \ CfgCompiler StmtSemantics \ VCS script proof wpo wpReport \ @@ -126,7 +130,8 @@ CEA_WP_GENEREATED= script.ml rformat.ml driver.ml PLUGIN_TESTS_DIRS:= \ wp wp_plugin wp_acsl wp_bts \ wp_store wp_hoare wp_typed wp_usage \ - wp_gallery wp_manual wp_tip + wp_gallery wp_manual wp_tip \ + wp_region ifeq ($(FRAMAC_INTERNAL),yes) Wp_DEFAULT_TESTS: create_share_link diff --git a/src/plugins/wp/MemLoader.ml b/src/plugins/wp/MemLoader.ml new file mode 100644 index 0000000000000000000000000000000000000000..b9fb6bf805e2fe03b3a70e43473957ac2fc9fbb7 --- /dev/null +++ b/src/plugins/wp/MemLoader.ml @@ -0,0 +1,370 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2019 *) +(* CEA (Commissariat a l'energie atomique et aux energies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- Memory Model --- *) +(* -------------------------------------------------------------------------- *) + +open Cil_types +open Cil_datatype +open Definitions +open Ctypes +open Lang +open Lang.F +open Sigs + +(* -------------------------------------------------------------------------- *) +(* --- Compound Loader --- *) +(* -------------------------------------------------------------------------- *) + +let cluster () = + Definitions.cluster ~id:"Compound" ~title:"Memory Compound Loader" () + +module type Model = +sig + + module Chunk : Chunk + module Sigma : Sigma with type chunk = Chunk.t + + val name : string + + type loc + val sizeof : c_object -> int + val field : loc -> fieldinfo -> loc + val shift : loc -> c_object -> term -> loc + + val to_addr : loc -> term + val to_region_pointer : loc -> int * term + val of_region_pointer : int -> c_object -> term -> loc + + val domain : c_object -> loc -> Sigma.domain + val frames : c_object -> loc -> Chunk.t -> frame list + + val last : Sigma.t -> c_object -> loc -> term + + val havoc : c_object -> loc -> length:term -> + Chunk.t -> fresh:term -> current:term -> term + + val eqmem : c_object -> loc -> Chunk.t -> term -> term -> pred + + val eqmem_forall : + c_object -> loc -> Chunk.t -> term -> term -> var list * pred * pred + + val load_int : Sigma.t -> c_int -> loc -> term + val load_float : Sigma.t -> c_float -> loc -> term + val load_pointer : Sigma.t -> typ -> loc -> loc + + val store_int : Sigma.t -> c_int -> loc -> term -> Chunk.t * term + val store_float : Sigma.t -> c_float -> loc -> term -> Chunk.t * term + val store_pointer : Sigma.t -> typ -> loc -> term -> Chunk.t * term + +end + +module Make (M : Model) = +struct + + type chunk = M.Chunk.t + + module Chunk = M.Chunk + module Sigma = M.Sigma + module Domain = M.Sigma.Chunk.Set + + let signature ft = + let s = Sigma.create () in + let xs = ref [] in + let cs = ref [] in + Domain.iter + (fun c -> + cs := c :: !cs ; + xs := (Sigma.get s c) :: !xs ; + ) ft ; + List.rev !xs , List.rev !cs , s + + let pp_rid fmt r = if r <> 0 then Format.fprintf fmt "_R%03d" r + + let loadrec = ref (fun _ _ _ -> assert false) + + (* -------------------------------------------------------------------------- *) + (* --- Frame Lemmas for Compound Access --- *) + (* -------------------------------------------------------------------------- *) + + let memories sigma chunks = List.map (Sigma.value sigma) chunks + let assigned sigma c m chunks = + List.map + (fun c0 -> if Chunk.equal c0 c then m else Sigma.value sigma c0) + chunks + + let frame_lemmas phi obj loc params chunks = + begin + let prefix = Fun.debug phi in + let sigma = Sigma.create () in + List.iter + (fun chunk -> + List.iter + (fun (name,triggers,conditions,m1,m2) -> + let mem1 = assigned sigma chunk m1 chunks in + let mem2 = assigned sigma chunk m2 chunks in + let value1 = e_fun phi (params @ mem1) in + let value2 = e_fun phi (params @ mem2) in + let vars1 = F.vars value1 in + let vars2 = F.vars value2 in + let l_triggers = + if Vars.subset vars1 vars2 then + [ (Trigger.of_term value2 :: triggers ) ] + else + if Vars.subset vars2 vars1 then + [ (Trigger.of_term value1 :: triggers ) ] + else + [ (Trigger.of_term value1 :: triggers ); + (Trigger.of_term value2 :: triggers ) ] + in + let l_name = Pretty_utils.sfprintf "%s_%s_%a" + prefix name Chunk.pretty chunk in + let l_lemma = F.p_hyps conditions (p_equal value1 value2) in + Definitions.define_lemma { + l_assumed = true ; + l_name ; l_types = 0 ; + l_triggers ; + l_forall = F.p_vars l_lemma ; + l_lemma = l_lemma ; + l_cluster = cluster () ; + } + ) (M.frames obj loc chunk) + ) chunks + end + + (* -------------------------------------------------------------------------- *) + (* --- Compound Loader --- *) + (* -------------------------------------------------------------------------- *) + + module COMP_KEY = + struct + type t = int * compinfo + let compare (r,c) (r',c') = if r=r' then Compinfo.compare c c' else r-r' + let pretty fmt (r,c) = Format.fprintf fmt "%d:%a" r Compinfo.pretty c + end + + module COMP = WpContext.Generator(COMP_KEY) + (struct + let name = M.name ^ ".COMP" + type key = int * compinfo + type data = lfun * chunk list + + let generate (r,c) = + let x = Lang.freshvar ~basename:"p" (Lang.t_addr()) in + let v = e_var x in + let obj = C_comp c in + let loc = M.of_region_pointer r obj v in (* t_pointer -> loc *) + let domain = M.domain obj loc in + let result = Lang.tau_of_comp c in + let lfun = Lang.generated_f ~result "Load%a_%s" pp_rid r (Lang.comp_id c) in + (* Since its a generated it is the unique name given *) + let xms,chunks,sigma = signature domain in + let def = List.map + (fun f -> + Cfield f , !loadrec sigma (object_of f.ftype) (M.field loc f) + ) c.cfields in + let dfun = Definitions.Function( result , Def , e_record def ) in + Definitions.define_symbol { + d_lfun = lfun ; d_types = 0 ; + d_params = x :: xms ; + d_definition = dfun ; + d_cluster = cluster () ; + } ; + frame_lemmas lfun obj loc [v] chunks ; + lfun , chunks + + let compile = Lang.local generate + end) + + (* -------------------------------------------------------------------------- *) + (* --- Array Loader --- *) + (* -------------------------------------------------------------------------- *) + + module ARRAY_KEY = + struct + type t = int * arrayinfo * Matrix.matrix + let pretty fmt (r,_,m) = + Format.fprintf fmt "%d:%a" r Matrix.NATURAL.pretty m + let compare (r1,_,m1) (r2,_,m2) = + if r1 = r2 then Matrix.NATURAL.compare m1 m2 else r1-r2 + end + + module ARRAY = WpContext.Generator(ARRAY_KEY) + (struct + open Matrix + let name = M.name ^ ".ARRAY" + type key = int * arrayinfo * Matrix.matrix + type data = lfun * chunk list + + let generate (r,ainfo,(obj_e,ds)) = + let x = Lang.freshvar ~basename:"p" (Lang.t_addr()) in + let v = e_var x in + let obj_a = C_array ainfo in + let loc = M.of_region_pointer r obj_a v in (* t_pointer -> loc *) + let domain = M.domain obj_a loc in + let result = Matrix.tau obj_e ds in + let lfun = Lang.generated_f ~result "Array%a%s_%s" pp_rid r + (Matrix.id ds) (Matrix.natural_id obj_e) in + let prefix = Lang.Fun.debug lfun in + let axiom = prefix ^ "_access" in + let xmem,chunks,sigma = signature domain in + let denv = Matrix.denv ds in + let phi = e_fun lfun (v :: denv.size_val @ List.map e_var xmem) in + let va = List.fold_left e_get phi denv.index_val in + let ofs = e_sum denv.index_offset in + let vm = !loadrec sigma obj_e (M.shift loc obj_e ofs) in + let lemma = p_hyps denv.index_range (p_equal va vm) in + let cluster = cluster () in + Definitions.define_symbol { + d_lfun = lfun ; d_types = 0 ; + d_params = x :: denv.size_var @ xmem ; + d_definition = Logic result ; + d_cluster = cluster ; + } ; + Definitions.define_lemma { + l_assumed = true ; + l_name = axiom ; l_types = 0 ; + l_forall = F.p_vars lemma ; + l_triggers = [[Trigger.of_term va]] ; + l_lemma = lemma ; + l_cluster = cluster ; + } ; + if denv.monotonic then + begin + let ns = List.map F.e_var denv.size_var in + frame_lemmas lfun obj_a loc (v::ns) chunks + end ; + lfun , chunks + + let compile = Lang.local generate + end) + + (* -------------------------------------------------------------------------- *) + (* --- Loader --- *) + (* -------------------------------------------------------------------------- *) + + let load_comp sigma comp loc = + let r , p = M.to_region_pointer loc in + let f , m = COMP.get (r,comp) in + F.e_fun f (p :: memories sigma m) + + let load_array sigma a loc = + let d = Matrix.of_array a in + let r , p = M.to_region_pointer loc in + let f , m = ARRAY.get (r,a,d) in + F.e_fun f (p :: Matrix.size d @ memories sigma m) + + let loadvalue sigma obj loc = + match obj with + | C_int i -> M.load_int sigma i loc + | C_float f -> M.load_float sigma f loc + | C_pointer t -> snd @@ M.to_region_pointer @@ M.load_pointer sigma t loc + | C_comp c -> load_comp sigma c loc + | C_array a -> load_array sigma a loc + + let load sigma obj loc = + let open Sigs in + match obj with + | C_int i -> Val (M.load_int sigma i loc) + | C_float f -> Val (M.load_float sigma f loc) + | C_pointer t -> Loc (M.load_pointer sigma t loc) + | C_comp c -> Val (load_comp sigma c loc) + | C_array a -> Val (load_array sigma a loc) + + let () = loadrec := loadvalue + + (* -------------------------------------------------------------------------- *) + (* --- 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 + ) (M.domain obj loc) ; !ps + + let havoc seq obj loc = havoc_length seq obj loc F.e_one + + (* -------------------------------------------------------------------------- *) + (* --- Stored & Copied --- *) + (* -------------------------------------------------------------------------- *) + + let updated seq phi alpha loc value = + let chunk,mem = phi seq.pre alpha loc value in + [Set(Sigma.value seq.post chunk,mem)] + + 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_comp _ | C_array _ -> + Set(loadvalue seq.post obj loc, value) :: havoc seq obj loc + + let copied s obj p q = stored s obj p (loadvalue s.pre obj q) + + (* -------------------------------------------------------------------------- *) + (* --- Assigned --- *) + (* -------------------------------------------------------------------------- *) + + 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) + | C_comp _ | C_array _ -> + havoc seq obj loc + + let assigned_range s obj l a b = + havoc_length s obj (M.shift l obj a) (e_range a b) + + let assigned seq obj = function + | Sloc loc -> assigned_loc seq obj loc + | Sdescr(xs,loc,condition) -> + let ps = ref [] in + Domain.iter + (fun c -> + let m1 = Sigma.value seq.pre c in + let m2 = Sigma.value seq.post c in + let p,separated,equal = M.eqmem_forall obj loc c m1 m2 in + 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.domain obj loc) ; !ps + | Sarray(loc,obj,n) -> + assigned_range seq obj loc e_zero (e_int (n-1)) + | Srange(loc,obj,u,v) -> + let a = match u with Some a -> a | None -> e_zero in + let b = match v with Some b -> b | None -> M.last seq.pre obj loc in + assigned_range seq obj loc a b + + (* -------------------------------------------------------------------------- *) + +end diff --git a/src/plugins/wp/MemLoader.mli b/src/plugins/wp/MemLoader.mli new file mode 100644 index 0000000000000000000000000000000000000000..ddc2677cbc01eff8c56b345c59582ab40f103109 --- /dev/null +++ b/src/plugins/wp/MemLoader.mli @@ -0,0 +1,95 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2019 *) +(* CEA (Commissariat a l'energie atomique et aux energies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) + +(** Compound Loader *) + +open Cil_types +open Definitions +open Ctypes +open Lang.F +open Sigs + +val cluster : unit -> cluster + +(** Loader Model for Atomic Values *) +module type Model = +sig + + module Chunk : Chunk + module Sigma : Sigma with type chunk = Chunk.t + + val name : string + + type loc + val sizeof : c_object -> int + val field : loc -> fieldinfo -> loc + val shift : loc -> c_object -> term -> loc + + (** Conversion among loc, t_pointer terms and t_addr terms *) + + val to_addr : loc -> term + val to_region_pointer : loc -> int * term + val of_region_pointer : int -> c_object -> term -> loc + + val domain : c_object -> loc -> Sigma.domain + val frames : c_object -> loc -> Chunk.t -> frame list + + val last : Sigma.t -> c_object -> loc -> term + + val havoc : c_object -> loc -> length:term -> + Chunk.t -> fresh:term -> current:term -> term + + val eqmem : c_object -> loc -> Chunk.t -> term -> term -> pred + + val eqmem_forall : + c_object -> loc -> Chunk.t -> term -> term -> var list * pred * pred + + val load_int : Sigma.t -> c_int -> loc -> term + val load_float : Sigma.t -> c_float -> loc -> term + val load_pointer : Sigma.t -> typ -> loc -> loc + + val store_int : Sigma.t -> c_int -> loc -> term -> Chunk.t * term + val store_float : Sigma.t -> c_float -> loc -> term -> Chunk.t * term + val store_pointer : Sigma.t -> typ -> loc -> term -> Chunk.t * term + +end + +(** Generates Loader for Compound Values *) +module Make (M : Model) : +sig + + val load : M.Sigma.t -> c_object -> M.loc -> M.loc Sigs.value + val loadvalue : M.Sigma.t -> c_object -> M.loc -> term + + val havoc : M.Sigma.t sequence -> c_object -> M.loc -> equation list + val havoc_length : M.Sigma.t sequence -> c_object -> M.loc -> term -> equation list + + val stored : M.Sigma.t sequence -> c_object -> M.loc -> term -> equation list + val copied : M.Sigma.t sequence -> c_object -> M.loc -> M.loc -> equation list + + val assigned : M.Sigma.t sequence -> c_object -> M.loc sloc -> equation list + +end + +(* -------------------------------------------------------------------------- *) diff --git a/src/plugins/wp/MemMemory.ml b/src/plugins/wp/MemMemory.ml new file mode 100644 index 0000000000000000000000000000000000000000..3297bfdd33e5d765bec98e4957292dc31982f31a --- /dev/null +++ b/src/plugins/wp/MemMemory.ml @@ -0,0 +1,427 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2019 *) +(* CEA (Commissariat a l'energie atomique et aux energies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- Memory Model --- *) +(* -------------------------------------------------------------------------- *) + +open Lang +open Lang.F + +module L = Qed.Logic + +let library = "memory" + +let a_addr = Lang.datatype ~library "addr" +let t_addr = L.Data(a_addr,[]) +let f_base = Lang.extern_f ~library ~result:L.Int + ~link:{altergo = Qed.Engine.F_subst("%1.base"); + why3 = Qed.Engine.F_call "base"; + coq = Qed.Engine.F_subst("(base %1)"); + } "base" +let f_offset = Lang.extern_f ~library ~result:L.Int + ~link:{altergo = Qed.Engine.F_subst("%1.offset"); + why3 = Qed.Engine.F_call "offset"; + coq = Qed.Engine.F_subst("(offset %1)"); + } "offset" +let f_shift = Lang.extern_f ~library ~result:t_addr "shift" +let f_global = Lang.extern_f ~library ~result:t_addr ~category:L.Injection "global" +let f_null = Lang.extern_f ~library ~result:t_addr "null" + +let f_base_offset = Lang.extern_f ~library + ~category:Qed.Logic.Injection ~result:L.Int "base_offset" + +let ty_havoc = function + | Some l :: _ -> l + | _ -> raise Not_found + +let l_havoc = Qed.Engine.{ + coq = F_call "fhavoc" ; + altergo = F_call "havoc" ; + why3 = F_call "havoc" ; + } + +let p_valid_rd = Lang.extern_fp ~library "valid_rd" +let p_valid_rw = Lang.extern_fp ~library "valid_rw" +let p_invalid = Lang.extern_fp ~library "invalid" +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_havoc ~link:l_havoc "havoc" +let f_region = Lang.extern_f ~library ~result:L.Int "region" (* base -> region *) +let p_framed = Lang.extern_fp ~library "framed" (* m-pointer -> prop *) +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_addr_of_int = Lang.extern_f + ~category:L.Injection + ~library ~result:t_addr "addr_of_int" + +let f_int_of_addr = Lang.extern_f + ~category:L.Injection + ~library ~result:L.Int "int_of_addr" + +(* -------------------------------------------------------------------------- *) +(* --- Utilities --- *) +(* -------------------------------------------------------------------------- *) + +let t_mem t = L.Array(t_addr,t) +let t_malloc = L.Array(L.Int,L.Int) + +let a_null = F.constant (e_fun f_null []) +let a_base p = e_fun f_base [p] +let a_offset p = e_fun f_offset [p] +let a_global b = e_fun f_global [b] +let a_shift l k = e_fun f_shift [l;k] +let a_addr b k = a_shift (a_global b) k +let a_base_offset k = e_fun f_base_offset [k] + +(* -------------------------------------------------------------------------- *) +(* --- Qed Simplifiers --- *) +(* -------------------------------------------------------------------------- *) + +(* + Pointer arithmetic for structure access and array access could be + defined directly using the record [{ base = p.base; offset = p.offset + + c*i + c' }]. However that gives very bad triggers for the memory + model axiomatization, so `shift p (c*i+c')` was used instead. It is + not sufficient for user axiomatisation because memory access in + axioms require trigger with arithmetic operators which is badly + handled by provers. So for each c and c', ie for each kind of + structure access and array access a specific function is used + `shift_xxx`. + + Moreover no simplification of `shift_xxx` is done for keeping the + same terms in axioms and the goal. `base` and `offset` function + simplify all the `shift_xxx` because it seems they don't appear + often in axioms and they are useful for simplifying `separated`, + `assigns` and pointer comparisons in goals. + + To sum up memory access should match, but not `\base`, `\offset`, + `\separated`, ... +*) + +type addr_builtin = { + base: term list -> term ; + offset: term list -> term ; +} + +module ADDR_BUILTIN = WpContext.Static + (struct + type key = lfun + type data = addr_builtin + let name = "MemMemory.ADDR_BUILTIN" + include Lang.Fun + end) + +let phi_base l = + match F.repr l with + | L.Fun(f,[p;_]) when f==f_shift -> a_base p + | L.Fun(f,[b]) when f==f_global -> b + | L.Fun(f,[]) when f==f_null -> e_zero + | L.Fun(f,args) -> (ADDR_BUILTIN.find f).base args + | _ -> raise Not_found + +let phi_offset l = match F.repr l with + | L.Fun(f,[p;k]) when f==f_shift -> e_add (a_offset p) k + | L.Fun(f,_) when f==f_global || f==f_null -> F.e_zero + | L.Fun(f,args) -> (ADDR_BUILTIN.find f).offset args + | _ -> raise Not_found + +let phi_shift f p i = + match F.repr p with + | L.Fun(g,[q;j]) when f == g -> F.e_fun f [q;F.e_add i j] + | _ -> raise Not_found + +let eq_shift a b = + let p = a_base a in + let q = a_base b in + let i = a_offset a in + let j = a_offset b in + if i==j then F.p_equal p q else + match F.is_equal p q with + | L.No -> F.p_false + | L.Yes -> F.p_equal i j + | L.Maybe -> raise Not_found + +let eq_shift_gen phi a b = + try phi a b with Not_found -> eq_shift a b + +let nop _ = raise Not_found + +let register ?(base=nop) ?(offset=nop) ?equal ?(linear=false) lfun = + begin + if base != nop || offset != nop then + ADDR_BUILTIN.define lfun { base ; offset } ; + if linear then + F.set_builtin_2 lfun (phi_shift lfun) ; + let phi_equal = match equal with + | None -> eq_shift + | Some phi -> eq_shift_gen phi + in + F.set_builtin_eqp lfun phi_equal ; + end + +(* -------------------------------------------------------------------------- *) +(* --- Simplifier for 'separated' --- *) +(* -------------------------------------------------------------------------- *) + +let r_separated = function + | [p;a;q;b] -> + if a == F.e_one && b == F.e_one then F.e_neq p q + else + begin + let a_negative = F.e_leq a F.e_zero in + let b_negative = F.e_leq b F.e_zero in + if a_negative == e_true || b_negative == e_true then e_true else + let bp = a_base p in + let bq = a_base q in + let open Qed.Logic in + match F.is_true (F.e_eq bp bq) with + | No -> e_true (* Have S *) + | Yes when (a_negative == e_false && b_negative == e_false) -> + (* Reduced to S *) + let p_ofs = a_offset p in + let q_ofs = a_offset q in + let p_ofs' = F.e_add p_ofs a in + let q_ofs' = F.e_add q_ofs b in + F.e_or [ F.e_leq q_ofs' p_ofs ; + F.e_leq p_ofs' q_ofs ] + | _ -> raise Not_found + end + | _ -> raise Not_found + +let is_separated args = F.is_true (r_separated args) + +(* -------------------------------------------------------------------------- *) +(* --- Simplifier for 'included' --- *) +(* -------------------------------------------------------------------------- *) + +(* +logic a : int +logic b : int + +predicate R = p.base = q.base + /\ (q.offset <= p.offset) + /\ (p.offset + a <= q.offset + b) + +predicate included = 0 < a -> ( 0 <= b and R ) +predicate a_empty = a <= 0 +predicate b_negative = b < 0 + +lemma SAME_P: p=q -> (R <-> a<=b) +lemma SAME_A: a=b -> (R <-> p=q) + +goal INC_P: p=q -> (included <-> ( 0 < a -> a <= b )) (by SAME_P) +goal INC_A: a=b -> 0 < a -> (included <-> R) (by SAME_A) +goal INC_1: a_empty -> (included <-> true) +goal INC_2: b_negative -> (included <-> a_empty) +goal INC_3: not R -> (included <-> a_empty) +goal INC_4: not a_empty -> not b_negative -> (included <-> R) +*) + +let r_included = function + | [p;a;q;b] -> + if F.e_eq p q == F.e_true + then F.e_imply [F.e_lt F.e_zero a] (F.e_leq a b) (* INC_P *) + else + if (F.e_eq a b == F.e_true) && (F.e_lt F.e_zero a == F.e_true) + then F.e_eq p q (* INC_A *) + else + begin + let a_empty = F.e_leq a F.e_zero in + let b_negative = F.e_lt b F.e_zero in + if a_empty == F.e_true then F.e_true (* INC_1 *) else + if b_negative == F.e_true then a_empty (* INC_2 *) else + let bp = a_base p in + let bq = a_base q in + let open Qed.Logic in + match F.is_true (F.e_eq bp bq) with + | No -> a_empty (* INC_3 *) + | Yes when (a_empty == e_false && b_negative == e_false) -> + (* INC_4 *) + let p_ofs = a_offset p in + let q_ofs = a_offset q in + if a == b then F.e_eq p_ofs q_ofs + else + let p_ofs' = e_add p_ofs a in + let q_ofs' = e_add q_ofs b in + e_and [ F.e_leq q_ofs p_ofs ; F.e_leq p_ofs' q_ofs' ] + | _ -> raise Not_found + end + | _ -> raise Not_found + +(* -------------------------------------------------------------------------- *) +(* --- Simplifier for 'havoc' --- *) +(* -------------------------------------------------------------------------- *) + +(* havoc(m_undef, havoc(_undef,m0,p0,a0), p1,a1) = + - havoc(m_undef, m0, p1,a1) WHEN included (p1,a1,p0,a0) *) +let r_havoc = function + | [undef1;m1;p1;a1] -> begin + match F.repr m1 with + | L.Fun( f , [_undef0;m0;p0;a0] ) when f == f_havoc -> begin + let open Qed.Logic in + match F.is_true (r_included [p0;a0;p1;a1]) with + | Yes -> F.e_fun f_havoc [undef1;m0;p1;a1] + | _ -> raise Not_found + end + | _ -> raise Not_found + end + | _ -> raise Not_found + +(* havoc(undef,m,p,a)[k] = + - undef[k] WHEN separated (p,a,k,1) + - m[k] WHEN NOT separated (p,a,k,1) +*) +let r_get_havoc = function + | [undef;m;p;a] -> + (fun _ k -> + match is_separated [p;a;k;e_one] with + | L.Yes -> F.e_get m k + | L.No -> F.e_get undef k + | _ -> raise Not_found) + | _ -> raise Not_found + +(* -------------------------------------------------------------------------- *) +(* --- Simplifier for int/addr conversion --- *) +(* -------------------------------------------------------------------------- *) + +let phi_int_of_addr p = + if p == a_null then F.e_zero else + match F.repr p with + | L.Fun(f,[a]) when f == f_addr_of_int -> a + | _ -> raise Not_found + +let phi_addr_of_int p = + if p == F.e_zero then a_null else + match F.repr p with + | L.Fun(f,[a]) when f == f_int_of_addr -> a + | _ -> raise Not_found + +(* -------------------------------------------------------------------------- *) +(* --- Simplifiers Registration --- *) +(* -------------------------------------------------------------------------- *) + +let () = Context.register + begin fun () -> + F.set_builtin_1 f_base phi_base ; + F.set_builtin_1 f_offset phi_offset ; + F.set_builtin_2 f_shift (phi_shift f_shift) ; + F.set_builtin_eqp f_shift eq_shift ; + F.set_builtin_eqp f_global eq_shift ; + F.set_builtin p_separated r_separated ; + F.set_builtin p_included r_included ; + F.set_builtin f_havoc r_havoc ; + F.set_builtin_get f_havoc r_get_havoc ; + F.set_builtin_1 f_addr_of_int phi_addr_of_int ; + F.set_builtin_1 f_int_of_addr phi_int_of_addr ; + end + +(* -------------------------------------------------------------------------- *) +(* --- Frame Conditions --- *) +(* -------------------------------------------------------------------------- *) + +module T = Definitions.Trigger + +let frames ~addr:p ~offset:n ~sizeof:s ?(basename="mem") tau = + let t_mem = L.Array(t_addr,tau) in + let m = F.e_var (Lang.freshvar ~basename t_mem) in + let m' = F.e_var (Lang.freshvar ~basename t_mem) in + let p' = F.e_var (Lang.freshvar ~basename:"q" t_addr) in + let n' = F.e_var (Lang.freshvar ~basename:"n" L.Int) in + let mh = F.e_fun f_havoc [m';m;p';n'] in + let v' = F.e_var (Lang.freshvar ~basename:"v" tau) in + let meq = F.p_call p_eqmem [m;m';p';n'] in + let diff = F.p_call p_separated [p;n;p';s] in + let sep = F.p_call p_separated [p;n;p';n'] in + let inc = F.p_call p_included [p;n;p';n'] in + let teq = T.of_pred meq in + [ + "update" , [] , [diff] , m , e_set m p' v' ; + "eqmem" , [teq] , [inc;meq] , m , m' ; + "havoc" , [] , [sep] , m , mh ; + ] + +(* -------------------------------------------------------------------------- *) +(* --- Range Comparison --- *) +(* -------------------------------------------------------------------------- *) + +type range = + | LOC of term * term (* loc - size *) + | RANGE of term * Vset.set (* base - range offset *) + +let range ~shift ~addrof ~sizeof = function + | Sigs.Rloc(obj,loc) -> + LOC( addrof loc , F.e_int (sizeof obj) ) + | Sigs.Rrange(loc,obj,Some a,Some b) -> + let s = sizeof obj in + let p = addrof (shift loc obj a) in + let n = e_fact s (e_range a b) in + LOC( p , n ) + | Sigs.Rrange(loc,_obj,None,None) -> + RANGE( a_base (addrof loc) , Vset.range None None ) + | Sigs.Rrange(loc,obj,Some a,None) -> + let s = sizeof obj in + RANGE( a_base (addrof loc) , Vset.range (Some (e_fact s a)) None ) + | Sigs.Rrange(loc,obj,None,Some b) -> + let s = sizeof obj in + RANGE( a_base (addrof loc) , Vset.range None (Some (e_fact s b)) ) + +let range_set = function + | LOC(l,n) -> + let a = a_offset l in + let b = e_add a n in + a_base l , Vset.range (Some a) (Some b) + | RANGE(base,set) -> base , set + +let r_included r1 r2 = + match r1 , r2 with + | LOC(l1,n1) , LOC(l2,n2) -> + F.p_call p_included [l1;n1;l2;n2] + | _ -> + let base1,set1 = range_set r1 in + let base2,set2 = range_set r2 in + F.p_if (F.p_equal base1 base2) + (Vset.subset set1 set2) + (Vset.is_empty set1) + +let r_disjoint r1 r2 = + match r1 , r2 with + | LOC(l1,n1) , LOC(l2,n2) -> + F.p_call p_separated [l1;n1;l2;n2] + | _ -> + let base1,set1 = range_set r1 in + let base2,set2 = range_set r2 in + F.p_imply (F.p_equal base1 base2) (Vset.disjoint set1 set2) + +let included ~shift ~addrof ~sizeof s1 s2 = + let range = range ~shift ~addrof ~sizeof in + r_included (range s1) (range s2) + +let separated ~shift ~addrof ~sizeof s1 s2 = + let range = range ~shift ~addrof ~sizeof in + r_disjoint (range s1) (range s2) + +(* -------------------------------------------------------------------------- *) diff --git a/src/plugins/wp/MemMemory.mli b/src/plugins/wp/MemMemory.mli new file mode 100644 index 0000000000000000000000000000000000000000..557ab0826a150e92ab99d14fe0b06dc0c5fe8324 --- /dev/null +++ b/src/plugins/wp/MemMemory.mli @@ -0,0 +1,118 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2019 *) +(* CEA (Commissariat a l'energie atomique et aux energies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- Memory Theory --- *) +(* -------------------------------------------------------------------------- *) + +open Lang +open Lang.F + +(** {2 Theory} *) + +val t_addr : tau +val t_malloc : tau (** allocation tables *) +val t_mem : tau -> tau (** t_addr indexed array *) + +val a_null : term (** Null address. Same as [a_addr 0 0] *) +val a_global : term -> term (** Zero-offset base. Same as [a_addr base 0] *) +val a_addr : term -> term -> term (** Constructor for [{ base ; offset }] *) +val a_shift : term -> term -> term (** Shift: [a_shift a k] adds [k] to [a.offset] *) +val a_base : term -> term (** Returns the base *) +val a_offset : term -> term (** Returns the offset *) +val a_base_offset : term -> term +(** Returns the offset in {i bytes} from the {i logic} offset + (which is a memory cell index, actually) *) + +val f_null : lfun +val f_base : lfun +val f_global : lfun +val f_shift : lfun +val f_offset : lfun +val f_havoc : lfun +val f_region : lfun +val f_addr_of_int : lfun (** Physical address *) +val f_int_of_addr : lfun (** Physical address *) + +val p_addr_lt : lfun +val p_addr_le : lfun +val p_linked : lfun +val p_framed : lfun +val p_sconst : lfun +val p_separated : lfun +val p_included : lfun +val p_valid_rd : lfun +val p_valid_rw : lfun +val p_invalid : lfun +val p_eqmem : lfun + +(* -------------------------------------------------------------------------- *) + +(** {2 Addr Producer Registration} *) + +(** Register simplifiers for functions producing [addr] terms: + - [~base es] is the simplifier for [(f es).base] + - [~offset es] is the simplifier for [(f es).offset] + - [~linear:true] register simplifier [f(f(p,i),k)=f(p,i+j)] on [f] + - [~equal a b] is the [set_eq_builtin] for [f] + + The equality builtin is wrapped inside a default builtin that + compares [f es] by computing [base] and [offset]. +*) + +val register : + ?base:(term list -> term) -> + ?offset:(term list -> term) -> + ?equal:(term -> term -> pred) -> + ?linear:bool -> + lfun -> unit + + +(** {2 Frame Conditions} + + [frames ~addr] are frame conditions for reading a value + at address [addr] from a chunk of memory. + The value read at [addr] have length [offset], + while individual element in memory chunk have type [tau] and + offset length [sizeof]. + + Memory variables use [~basename] or ["mem"] by default. +*) + +val frames : addr:term -> offset:term -> sizeof:term -> + ?basename:string -> tau -> Sigs.frame list + +(** {2 Range of Address} *) + +val separated : + shift:('a -> Ctypes.c_object -> term -> 'a) -> + addrof:('a -> term) -> + sizeof:(Ctypes.c_object -> int) -> + 'a Sigs.rloc -> 'a Sigs.rloc -> pred + +val included : + shift:('a -> Ctypes.c_object -> term -> 'a) -> + addrof:('a -> term) -> + sizeof:(Ctypes.c_object -> int) -> + 'a Sigs.rloc -> 'a Sigs.rloc -> pred + +(* -------------------------------------------------------------------------- *) diff --git a/src/plugins/wp/MemRegion.ml b/src/plugins/wp/MemRegion.ml new file mode 100644 index 0000000000000000000000000000000000000000..be5c827b90ec3f24e3731f57629334ef66557946 --- /dev/null +++ b/src/plugins/wp/MemRegion.ml @@ -0,0 +1,878 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2019 *) +(* CEA (Commissariat a l'energie atomique et aux energies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* TODO DEVEL MODE *) +[@@@ warning "-32-37-60"] + +(* -------------------------------------------------------------------------- *) +(* --- Region Memory Model --- *) +(* -------------------------------------------------------------------------- *) + +open Cil_types +open Sigs +open Definitions + +module Wp = Wp_parameters +module F = Lang.F +module L = Qed.Logic + +(* -------------------------------------------------------------------------- *) +(* --- Why-3 Region Theory --- *) +(* -------------------------------------------------------------------------- *) + +let library = "region" + +let cluster_region () = + Definitions.cluster ~id:"Region" ~title:"Region Index Constructors" () + +(* Index *) +let t_addr = MemMemory.t_addr +let t_index = L.Data( Lang.datatype ~library "index" ,[] ) +let f_addrof = Lang.extern_f ~library ~result:t_addr "addrof" +let f_consistent = Lang.extern_fp ~library "consistent" +let f_consistent_range = Lang.extern_fp ~library "consistent_range" + +let a_addrof l = F.e_fun f_addrof [l] +let p_consistent l = F.p_call f_consistent [l] +let p_consistent_range l n = F.p_call f_consistent_range [l;n] +let p_range k n ps = F.(p_leq e_zero k :: p_lt k n :: ps) + +(* Null *) +let f_inull = Lang.extern_f ~library ~result:t_index "inull" +let l_inull = F.e_fun f_inull [] +let a_null = MemMemory.a_null +let p_inull l = F.p_equal a_null (a_addrof l) + +(* Address *) + +let p_separated p n q m = F.p_call MemMemory.p_separated [p;n;q;m] + +(* Constructors *) +let region_ctor ~result = + Lang.extern_f ~library ~category:L.Constructor ~result "%s" + +let f_addr_var = region_ctor ~result:t_addr "addr_var" +let f_addr_ref = region_ctor ~result:t_addr "addr_ref" +let f_base_var = region_ctor ~result:L.Int "base_var" +let f_base_ref = region_ctor ~result:L.Int "base_ref" +let f_index_var = region_ctor ~result:t_index "index_var" +let f_index_ref = region_ctor ~result:t_index "index_ref" +let f_index_mem = region_ctor ~result:t_index "index_mem" + +let a_addr_var x = F.e_fun f_addr_var [x] +let a_addr_ref p = F.e_fun f_addr_ref [p] +let l_index_var x = F.e_fun f_index_var [F.e_int x] +let l_index_mem l k n = F.e_fun f_index_ref [l;k;n] +let l_index_ref l = F.e_fun f_index_ref [l] + +(* Shifts *) + +let a_shift = MemMemory.a_shift +let f_shift_index = Lang.extern_f ~library ~result:t_index "shift_index" +let l_shift_index l p = F.e_fun f_shift_index [l;p] + +(* Bits *) +let t_bits = L.Int + +(* -------------------------------------------------------------------------- *) +(* --- Index Simplifiers --- *) +(* -------------------------------------------------------------------------- *) + +type index_builtin = { + index: (Lang.lfun -> F.term list -> F.term -> F.term) ; + addrof : (F.term list -> F.term) ; + consistent : (F.term list -> F.pred) ; +} + +module IndexBuiltin = WpContext.Static + (struct + type key = Lang.lfun + type data = index_builtin + let name = "MemRegion.INDEXER" + include Lang.Fun + end) + +(* f enjoys shifting props: + - f(l,p,...)+k == f(l,p+k,...) + - &f(l,p,...) = &l+p +*) +let is_shiftable f = + ( f == f_shift_index ) || ( f == f_index_mem) + +let phi_addrof index = + match F.repr index with + | L.Fun(f,[]) when f == f_inull -> a_null + | L.Fun(f,[x]) when f == f_index_var -> a_addr_var x + | L.Fun(f,[l]) when f == f_index_ref -> a_addr_ref (a_addrof l) + | L.Fun(f,l::p::_) when is_shiftable f -> a_shift (a_addrof l) p + | L.Fun(f,es) -> (IndexBuiltin.find f).addrof es + | _ -> raise Not_found + +let phi_shift_index l p = + if p == F.e_zero then l else + match F.repr l with + | L.Fun(f,l::q::w) when is_shiftable f -> F.e_fun f (l::(F.e_add p q)::w) + | L.Fun(f,es) -> (IndexBuiltin.find f).index f es p + | _ -> raise Not_found + +let phi_consistent index = + match F.repr index with + | L.Fun(f,[]) when f == f_inull -> F.e_false + | L.Fun(f,[x]) when f == f_index_var -> + F.e_neq x F.e_zero + | L.Fun(f,[l]) when f == f_index_ref -> + F.e_prop @@ p_consistent l + | L.Fun(f,[l;k;n]) when f == f_index_mem -> + F.e_prop @@ F.p_conj @@ p_range k n [p_consistent l] + | L.Fun(f,es) -> + F.e_prop @@ (IndexBuiltin.find f).consistent es + | _ -> raise Not_found + +let phi_consistent_range index sizeof = + match F.repr index with + | L.Fun(f,[l;k;n]) when f == f_index_mem -> + F.e_prop @@ F.p_conj @@ F.[ + p_leq e_zero sizeof ; + p_leq e_zero k ; + p_leq (e_add k sizeof) n ; + p_consistent l ; + ] + | _ -> raise Not_found + +let () = Context.register + begin fun () -> + MemMemory.register f_addr_var + ~base:(F.e_fun f_base_var) ~offset:(fun _ -> F.e_zero) ; + MemMemory.register f_addr_ref + ~base:(F.e_fun f_base_ref) ; + F.set_builtin_1 f_addrof phi_addrof ; + F.set_builtin_1 f_consistent phi_consistent ; + F.set_builtin_2 f_shift_index phi_shift_index ; + F.set_builtin_2 f_consistent_range phi_consistent_range ; + end + +let cid = ref 0 (* TODO: projectified *) + +let constructor ~basename ~params ~index ~addrof ~consistent = + let id = incr cid ; !cid in + let lfun = Lang.generated_f ~result:t_index "%s_%d" basename id in + let ps = List.map F.e_var params in + let l = F.e_fun lfun ps in + let k = Lang.freshvar ~basename:"k" L.Int in + let ofs = F.e_var k in + (* Must compute properties before registering simplifiers *) + let p_addrof = F.p_equal (a_addrof l) (addrof ps) in + let p_consistent = F.p_equiv (p_consistent l) (consistent ps) in + let p_index = F.p_equal (l_shift_index l ofs) (index lfun ps ofs) in + IndexBuiltin.define lfun { index ; addrof ; consistent } ; + fun cluster -> + begin + Definitions.define_symbol { + d_cluster = cluster ; + d_lfun = lfun ; d_params = params ; d_types = 0 ; + d_definition = Logic t_index ; + } ; + Definitions.define_lemma { + l_cluster = cluster ; + l_assumed = true ; + l_name = Printf.sprintf "addrof_%s_%d" basename id ; + l_forall = params ; l_types = 0 ; l_triggers = [] ; + l_lemma = p_addrof ; + } ; + Definitions.define_lemma { + l_cluster = cluster ; + l_assumed = true ; + l_name = Printf.sprintf "consistent_%s_%d" basename id ; + l_forall = params ; l_types = 0 ; l_triggers = [] ; + l_lemma = p_consistent ; + } ; + if p_index != F.p_true then + Definitions.define_lemma { + l_cluster = cluster ; + l_assumed = true ; + l_name = Printf.sprintf "index_%s_%d" basename id ; + l_forall = params @ [k] ; l_types = 0 ; l_triggers = [] ; + l_lemma = p_index ; + } ; + lfun + end + +(* -------------------------------------------------------------------------- *) +(* --- Field Index Constructors --- *) +(* -------------------------------------------------------------------------- *) + +module FIELD = +struct + + type t = int list (* Overlay offsets *) + + let pretty fmt = function + | [] -> Format.fprintf fmt "{}" + | p::ps -> + begin + Format.fprintf fmt "@[<hov 2>{%d" p ; + List.iter (fun p -> Format.fprintf fmt ",@,%d" p) ps ; + Format.fprintf fmt "}@]" ; + end + + let compare = Pervasives.compare + + (* Extract constant offset *) + let offset k = + let rec walk s a = + match F.repr a with + | L.Add es -> List.fold_left walk s es + | L.Kint z -> + (try s + Integer.to_int z + with Z.Overflow -> s) + | _ -> s + in walk 0 k + + let builtin_index f es q = match es with + | [l;p] -> F.e_fun f [l;F.e_add q p] + | _ -> raise Not_found + + let builtin_addrof = function + | [l;p] -> a_shift (a_addrof l) p + | _ -> raise Not_found + + let builtin_consistent fds = function + | [l;p] -> F.p_and (p_consistent l) + (F.p_any (fun fd -> F.p_equal (F.e_int fd) p) fds) + | _ -> raise Not_found + +end + +(* Model Independant Generators *) +module FIELD_GEN = WpContext.StaticGenerator(FIELD) + (struct + type key = FIELD.t + type data = cluster -> Lang.lfun + let name = "MemRegion.FIELD_GEN" + let compile fds = + let l = Lang.freshvar ~basename:"l" t_index in + let p = Lang.freshvar ~basename:"p" L.Int in + constructor + ~basename:"field" + ~params:[l;p] + ~index:FIELD.builtin_index + ~addrof:FIELD.builtin_addrof + ~consistent:(FIELD.builtin_consistent fds) + end) + +(* Model Dependent Definitions *) +module FIELD_MODEL = WpContext.Generator(FIELD) + (struct + type key = FIELD.t + type data = Lang.lfun + let name = "MemRegion.FIELD_MODEL" + let compile fds = FIELD_GEN.get fds @@ cluster_region () + end) + +let l_field ovl l k = + let fds = List.map (fun rg -> rg.Layout.ofs) ovl in + F.e_fun (FIELD_MODEL.get fds) [l;k] + +(* -------------------------------------------------------------------------- *) +(* --- Array Index Constructors --- *) +(* -------------------------------------------------------------------------- *) + +module ARRAY = +struct + + type t = int * int list + let compare = Pervasives.compare + let pretty fmt (s,ds) = Format.fprintf fmt "%d%a" s Layout.Matrix.pretty ds + + (* Coefficient from Matrix dimensions: c_i = \Pi_{i<j} d_j *) + let coefs s ds = + let rec walk cs s = function + | d::ds -> walk (s::cs) (d*s) ds + | [] -> cs + in walk [] s ds + + (* All zeroes *) + let zeroes = List.map (fun _ -> F.e_zero) + + (* Address shift with coefficient c_i for each index k_i *) + let rec shift a cs ks = + match cs , ks with + | c::cs , k::ks -> shift (a_shift a (F.e_fact c k)) cs ks + | _ -> a + + (* Address of an array index *) + let builtin_addrof cs = function + | l::ks -> shift (a_addrof l) cs ks + | _ -> raise Not_found + + (* Add conditions (0 <= ki < ni) to [ps]. + WARNING: ns = rev ds *) + let rec add_range_dims ps ks ns = + match ks , ns with + | k::ks , n::ns -> + add_range_dims F.(p_range k (e_int n) ps) ks ns + | k::ks , [] -> + add_range_dims F.(p_equal e_zero k :: ps) ks [] + | [] , _ -> ps + + (* Consistent index. + WARNING: ns = rev ds *) + let builtin_consistent ns = function + | l::ks -> F.p_conj (add_range_dims [p_consistent l] ks ns) + | _ -> raise Not_found + + (* Extract linear forms *) + let rec get_linear poly a = + match F.repr a with + | L.Add es -> List.fold_left get_linear poly es + | L.Kint z -> + (try (Integer.to_int z,F.e_one)::poly + with Z.Overflow -> (1,a)::poly) + | L.Times(c,e) -> + (try (Integer.to_int c,e)::poly + with Z.Overflow -> (1,a)::poly) + | _ -> (1,a)::poly + + (* Some of linear form *) + let rec add_linear s = function + | (k,e)::poly -> add_linear (F.e_add s (F.e_fact k e)) poly + | [] -> s + + (* Euclidian division *) + (* euclid q r ci p = q',r' <-> p + ci.q + r = ci.q' + r' *) + let rec euclid q r ci = function + | [] -> q,r + | (c,k)::poly -> + let q0 = c / ci in + let r0 = c mod ci in + euclid (F.e_add q (F.e_fact q0 k)) ((r0,k)::r) ci poly + + (* Linear offset decomposed on each coefficient *) + let rec add_linear_index cs ks ks' p = + match cs , ks with + | c :: cs , k :: ks -> + let k' , r = euclid k [] c p in + add_linear_index cs ks (k'::ks') r + | _ -> List.rev_append ks' ks , p + + (* Linear offset and remainder delta *) + let offset cs ks p = + let ks',r = add_linear_index cs ks [] (get_linear [] p) in + ks' , add_linear F.e_zero r + + (* Builtin simplifier *) + let builtin_index cs f es p = match es with + | l::ks -> + let ks' , r = offset cs ks p in + if Qed.Hcons.equal_list F.equal ks ks' then + raise Not_found + else + let l' = F.e_fun f (l :: ks) in + l_shift_index l' r + | _ -> raise Not_found + +end + +module ARRAY_GEN = WpContext.StaticGenerator(ARRAY) + (struct + type key = ARRAY.t + type data = (cluster -> Lang.lfun) + let name = "MemRegion.ARRAY_GEN" + let compile (s,ds) = + let l = Lang.freshvar ~basename:"l" t_index in + let ks = List.map (fun _ -> Lang.freshvar ~basename:"k" L.Int) ds in + let cs = ARRAY.coefs s ds in + let ns = List.rev ds in + constructor + ~basename:"array" + ~params:(l::ks) + ~index:(ARRAY.builtin_index cs) + ~addrof:(ARRAY.builtin_addrof cs) + ~consistent:(ARRAY.builtin_consistent ns) + end) + +module ARRAY_MODEL = WpContext.Generator(ARRAY) + (struct + type key = ARRAY.t + type data = Lang.lfun + let name = "MemRegion.ARRAY_MODEL" + let compile dim = ARRAY_GEN.get dim @@ cluster_region () + end) + +let l_array s ds l ks = F.e_fun (ARRAY_MODEL.get (s,ds)) (l::ks) + +(* -------------------------------------------------------------------------- *) +(* --- Model Context --- *) +(* -------------------------------------------------------------------------- *) + +let datatype = "MemRegion" + +let configure () = + begin + Context.set Lang.pointer (fun _ -> t_index) ; + Context.set Cvalues.null p_inull ; + end + +let configure_ia = + let no_binder = { bind = fun _ f v -> f v } in + fun _vertex -> no_binder + +let hypotheses () = [] + +let error msg = Warning.error ~source:"Region Model" msg + +(* -------------------------------------------------------------------------- *) +(* --- Region Maps --- *) +(* -------------------------------------------------------------------------- *) + +let map () = + RegionAnalysis.get + begin match WpContext.get_scope () with + | WpContext.Global -> None + | WpContext.Kf kf -> Some kf + end + +(* -------------------------------------------------------------------------- *) +(* --- Locations --- *) +(* -------------------------------------------------------------------------- *) + +open Layout + +type region = Region.region +type index = F.term + +let pp_index = F.pp_term +let pp_region = Region.R.pretty +let pp_value = Value.pretty pp_region +let pp_args fmt = function + | [] -> () + | k::ks -> + F.pp_term fmt k ; + List.iter (fun k -> Format.fprintf fmt "@,,%a" F.pp_term k) ks + +let pp_field fmt k = + if F.is_atomic k then + Format.fprintf fmt "@,+%a" F.pp_term k + else + Format.fprintf fmt "@,+(%a)" F.pp_term k + +let pp_delta fmt k = + if k != F.e_zero then pp_field fmt k + +type loc = + | GarbledMix (* any possible location *) + | Index of index (* unqualified address *) + | Lref of region * index * region + | Lmem of region * index * root * region value + | Lraw of region * index * root * region option + | Lfld of region * index * F.term * region overlay + | Larr of region * index * F.term * F.term list * int * int list + (* For Lxxx locations: + - index: start index inside the chunk + - term: additional shift index + - term list: array index from start *) + +(* -------------------------------------------------------------------------- *) +(* --- Loc Basics --- *) +(* -------------------------------------------------------------------------- *) + +let null = Index l_inull + +let vars = function + | GarbledMix -> F.Vars.empty + | Index l | Lref(_,l,_) | Lmem(_,l,_,_) | Lraw(_,l,_,_) -> F.vars l + | Lfld(_,l,k,_) -> + F.Vars.union (F.vars l) (F.vars k) + | Larr(_,l,k,ks,_,_) -> + Qed.Hcons.fold_list F.Vars.union F.vars F.Vars.empty (l::k::ks) + +let occurs x = function + | GarbledMix -> false + | Index l | Lref(_,l,_) | Lmem(_,l,_,_) | Lraw(_,l,_,_) -> F.occurs x l + | Lfld(_,l,k,_) -> + F.occurs x l || F.occurs x k + | Larr(_,l,k,ks,_,_) -> + List.exists (F.occurs x) (l::k::ks) + +let pretty fmt = function + | GarbledMix -> Format.pp_print_string fmt "garbled-mix" + | Index l -> + Format.fprintf fmt "@[<hov 2>Index(%a)@]" pp_index l + | Lref(r,l,r') -> + Format.fprintf fmt "@[<hov 2>Ref@,{%a->%a}@,(%a)@]" + pp_region r pp_region r' pp_index l + | Lmem(r,l,_,v) -> + Format.fprintf fmt "@[<hov 2>Mem@,{%a:@,%a}@,(%a)@]" + pp_region r pp_value v pp_index l + | Lraw(r,l,_,None) -> + Format.fprintf fmt "@[<hov 2>Raw@,{%a}@,(%a)" + pp_region r pp_index l + | Lraw(r,l,_,Some r') -> + Format.fprintf fmt "@[<hov 2>Raw@,{%a->%a}@,(%a)" + pp_region r pp_region r' pp_index l + | Lfld(r,l,k,_) -> + Format.fprintf fmt "@[<hov 2>Field@,{%a}@,(%a%a)@]" + pp_region r pp_index l pp_field k + | Larr(r,l,k,ks,_,_) -> + Format.fprintf fmt "@[<hov 2>Index@,{%a}@,@[<hov 2>(%a[%a]%a)@]@]" + pp_region r pp_index l pp_args ks pp_delta k + +(* -------------------------------------------------------------------------- *) +(* --- Loc Constructors --- *) +(* -------------------------------------------------------------------------- *) + +let rec index map (r:region) (l:index) (ofs:F.term) (len:int) = + index_chunk map r l ofs len (Region.chunk map r) + +and index_chunk map (r:region) l ofs len = function + | Mref r' -> Lref(r,l_shift_index l ofs,r') + | Mraw(m,p) -> Lraw(r,l_shift_index l ofs,m,p) + | Mmem(m,v) -> Lmem(r,l_shift_index l ofs,m,v) + | Mcomp(_,[{ofs=0;reg;dim}]) -> index_dim map reg l ofs len dim + | Mcomp(_,overlay) -> index_field map r l ofs len overlay + +and index_field map r l ofs len overlay = + try + let k = FIELD.offset ofs in + let rg = List.find (Layout.Range.included k len) overlay in + let fd = F.e_int k in + let l' = l_field overlay l fd in + index_dim map rg.reg l' (F.e_sub ofs fd) len rg.dim + with Not_found -> + Lfld(r,l,ofs,overlay) + +and index_dim map r l ofs len = function + | Raw s | Dim(s,[]) -> + index map r (l_index_mem l F.e_zero (F.e_int s)) ofs len + | Dim(s,ds) -> + index_array map r l (ARRAY.zeroes ds) ofs len s ds + +and index_array map r l ks ofs len s ds = + let cs = ARRAY.coefs s ds in + let ks,ofs = ARRAY.offset cs ks ofs in + if len <= s then + let l' = l_array s ds l ks in + index map r l' ofs len + else + Larr(r,l,ofs,ks,s,ds) + +and shift_index_loc map loc ofs len = + match loc with + | GarbledMix -> GarbledMix + | Index l -> Index (l_shift_index l ofs) + | Lref(r,l,r') -> Lref(r,l_shift_index l ofs,r') + | Lmem(r,l,m,v) -> Lmem(r,l_shift_index l ofs,m,v) + | Lraw(r,l,m,p) -> Lraw(r,l_shift_index l ofs,m,p) + | Lfld(r,l,k,overlay) -> index_field map r l (F.e_add k ofs) len overlay + | Larr(r,l,k,ks,s,ds) -> index_array map r l ks (F.e_add k ofs) len s ds + +let cvar x = + let map = map () in + let region = Region.of_cvar map x in + let id = if Cil.isConstType x.vtype then - x.vid else x.vid in + index map region (l_index_var id) F.e_zero (Cil.bitsSizeOf x.vtype) + +let field loc fd = + let map = map () in + let ofs,len = Region.field_offset map fd in + shift_index_loc map loc (F.e_int ofs) len + +let shift loc obj n = + let map = map () in + let s = Ctypes.bits_sizeof_object obj in + shift_index_loc map loc (F.e_fact s n) s + +let pointer_loc l = Index l +let pointer_val = function + | GarbledMix -> error "Can not obtain address of Garbled-Mix location" + | Index l | Lref(_,l,_) | Lmem(_,l,_,_) | Lraw(_,l,_,_) -> l + | Lfld(_,l,k,overlay) -> l_field overlay l k + | Larr(_,l,k,ks,s,ds) -> l_shift_index (l_array s ds l ks) k + +let loc_of_index re ty l = + index (map()) re l F.e_zero (Cil.bitsSizeOf ty) + +(* -------------------------------------------------------------------------- *) +(* --- Chunks --- *) +(* -------------------------------------------------------------------------- *) + +type chunk = + | Mu_alloc + | Mu_raw of region * root + | Mu_mem of region * root * region value + +module Chunk = +struct + + type t = chunk + let self = "region" + + let id = function + | Mu_raw(r,_) | Mu_mem(r,_,_) -> Region.id r + | Mu_alloc -> Region.noid + + let hash m = id m + let compare m m' = if m==m then 0 else Pervasives.compare (id m) (id m') + let equal m m' = m==m' || (id m = id m') + + let tau_of_value = function + | Int _ -> L.Int + | Float _ -> L.Real + | Pointer _ -> t_index + + let tau_of_chunk = function + | Mu_alloc -> MemMemory.t_malloc + | Mu_raw _ -> t_bits + | Mu_mem(_,root,v) -> + let value = tau_of_value v in + if Root.indexed root then L.Array(t_addr,value) else value + + let basename_of_chunk = function + | Mu_raw _ -> "B" + | Mu_mem(_,root,Int _) -> if Root.indexed root then "M" else "V" + | Mu_mem(_,root,Float _) -> if Root.indexed root then "Mf" else "F" + | Mu_mem(_,root,Pointer _) -> if Root.indexed root then "Mp" else "M" + | Mu_alloc -> "A" + + let is_framed = function + | Mu_raw(_,root) | Mu_mem(_,root,_) -> Root.framed root + | Mu_alloc -> false + + let pretty fmt mu = Format.pp_print_string fmt (basename_of_chunk mu) + +end + +module Heap = +struct + include Qed.Collection.Make(Chunk) + let empty = Set.empty + let of_raw r rt = Set.singleton (Mu_raw(r,rt)) + let of_mem r rt v = Set.singleton (Mu_mem(r,rt,v)) + + let rec of_region map r = + match Region.chunk map r with + | Mref _ -> Set.empty + | Mraw(rt,_) -> of_raw r rt + | Mmem(rt,v) -> of_mem r rt v + | Mcomp(_,overlay) -> of_overlay map overlay + + and of_range map { reg } = of_region map reg + + and of_overlay map ovl = + Qed.Hcons.fold_list Set.union (of_range map) empty ovl + +end +module Sigma = Sigma.Make(Chunk)(Heap) + +type sigma = Sigma.t +type domain = Sigma.domain + +let domain _obj = function + | GarbledMix | Index _ -> error "Can not compute Garbled-mix domain" + | Lref _ -> Heap.empty + | Lraw(r,_,rt,_) -> Heap.of_raw r rt + | Lmem(r,_,rt,v) -> Heap.of_mem r rt v + | Lfld(_,_,_,ovl) -> Heap.of_overlay (map()) ovl + | Larr(r,_,_,_,_,_) -> Heap.of_region (map()) r + +let region_of_loc = function + | (GarbledMix | Index _) as l -> error "Can not find region of %a" pretty l + | Lref(r,_,_) | Lraw(r,_,_,_) | Lmem(r,_,_,_) + | Lfld(r,_,_,_) | Larr(r,_,_,_,_,_) -> r + +(* -------------------------------------------------------------------------- *) +(* --- Loader --- *) +(* -------------------------------------------------------------------------- *) + +module MODEL = +struct + + module Chunk = Chunk + module Sigma = Sigma + let name = "MemRegion.LOADER" + type nonrec loc = loc + let field = field + let shift = shift + let sizeof = Ctypes.bits_sizeof_object + let domain = domain + let frames _ _ _ = [] + + let to_addr l = a_addrof (pointer_val l) + let to_region_pointer l = Region.id (region_of_loc l) , pointer_val l + let of_region_pointer r obj l = + let map = map () in + index map (Region.region map r) l F.e_zero (Ctypes.bits_sizeof_object obj) + + let load_mem sigma r rt v l = + let m = Sigma.value sigma (Mu_mem(r,rt,v)) in + if Root.indexed rt then F.e_get m (a_addrof l) else m + + let load_int sigma i = function + | Lmem(r,l,rt,(Int i0 as v)) when i = i0 -> load_mem sigma r rt v l + | l -> error "Can not load %a value from %a" Ctypes.pp_int i pretty l + + let load_float sigma f = function + | Lmem(r,l,rt,(Float f0 as v)) when f = f0 -> load_mem sigma r rt v l + | l -> error "Can not load %a value from %a" Ctypes.pp_float f pretty l + + let load_pointer sigma ty = function + | Lmem(r,l,rt,(Pointer r' as v)) -> + loc_of_index r' ty (load_mem sigma r rt v l) + | Lref(_,l,r') -> + loc_of_index r' ty (l_index_ref l) + | l -> error "Can not load pointer value from %a" pretty l + + let havoc obj loc ~length (chunk:chunk) ~fresh ~current = + match chunk with + | Mu_alloc -> fresh + | Mu_raw _ -> error "Can not havoc raw memories" + | Mu_mem(_,root,_) -> + if Layout.Root.indexed root then + let addr = to_addr loc in + let offset = F.e_fact (Ctypes.bits_sizeof_object obj) length in + F.e_fun MemMemory.f_havoc [fresh;current;addr;offset] + else + fresh + + let eqmem obj loc chunk m1 m2 = + match chunk with + | Mu_alloc -> error "Can not compare allocation tables" + | Mu_raw _ -> error "Can not compare raw memories" + | Mu_mem(_,root,_) -> + if Layout.Root.indexed root then + let addr = to_addr loc in + let offset = F.e_int (Ctypes.bits_sizeof_object obj) in + F.p_call MemMemory.p_eqmem [m1;m2;addr;offset] + else F.p_equal m1 m2 + + let eqmem_forall obj loc chunk m1 m2 = + match chunk with + | Mu_alloc -> error "Can not compare allocation tables" + | Mu_raw _ -> error "Can not compare raw memories" + | Mu_mem(_,root,_) -> + if Layout.Root.indexed root then + let xp = Lang.freshvar ~basename:"p" t_addr in + let p = F.e_var xp in + let a = to_addr loc in + let n = F.e_int (Ctypes.bits_sizeof_object obj) in + let separated = p_separated p F.e_one a n in + let equal = F.p_equal (F.e_get m1 p) (F.e_get m2 p) in + [xp],separated,equal + else [],F.p_true,F.p_equal m1 m2 + + let last _ = error "Can not compute last valid index" + + let store_mem sigma r rt v l value = + let c = Mu_mem(r,rt,v) in + if Root.indexed rt then + c , F.e_set (Sigma.value sigma c) (a_addrof l) value + else c , value + + let store_int sigma i loc value = + match loc with + | Lmem(r,l,rt,(Int i0 as v)) when i = i0 -> store_mem sigma r rt v l value + | _ -> error "Can not store %a value into %a" Ctypes.pp_int i pretty loc + + let store_float sigma f loc value = + match loc with + | Lmem(r,l,rt,(Float f0 as v)) when f = f0 -> store_mem sigma r rt v l value + | _ -> error "Can not store %a value into %a" Ctypes.pp_float f pretty loc + + let store_pointer sigma _ty loc value = + match loc with + | 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 + +end + +module LOADER = MemLoader.Make(MODEL) + +let load = LOADER.load +let loadvalue = LOADER.loadvalue + +let stored = LOADER.stored +let copied = LOADER.copied +let assigned = LOADER.assigned + +(* -------------------------------------------------------------------------- *) +(* --- Loc Segments --- *) +(* -------------------------------------------------------------------------- *) + +type segment = loc rloc + +let region_of_sloc = function Rloc(_,l) | Rrange(l,_,_,_) -> region_of_loc l + +let disjoint_region s1 s2 = + let map = map () in + let c1 = Region.chunks map (region_of_sloc s1) in + let c2 = Region.chunks map (region_of_sloc s2) in + not (Qed.Intset.intersect c1 c2) + + +let addrof = MODEL.to_addr +let sizeof = Ctypes.bits_sizeof_object + +let included s1 s2 = + if disjoint_region s1 s2 then F.p_false else + MemMemory.included ~shift ~addrof ~sizeof s1 s2 + +let separated s1 s2 = + if disjoint_region s1 s2 then F.p_true else + MemMemory.separated ~shift ~addrof ~sizeof s1 s2 + +(* -------------------------------------------------------------------------- *) +(* --- TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO --- *) +(* -------------------------------------------------------------------------- *) + +type state = unit + +let state _ = () +let iter _ _ = () +let lookup _ _ = Mterm +let updates _ _ = Bag.empty +let apply _ _ = () + +let literal ~eid _ = ignore eid ; GarbledMix + +let base_addr _l = GarbledMix +let base_offset l = MemMemory.a_offset (addrof l) +let block_length _s _obj _l = F.e_zero + +let cast _ _l = GarbledMix +let loc_of_int _ _ = GarbledMix +let int_of_loc _ _ = F.e_zero + +let not_yet_pointer () = error "Pointer comparison not yet implemented" + +let is_null _ = not_yet_pointer () +let loc_eq _ _ = not_yet_pointer () +let loc_lt _ _ = not_yet_pointer () +let loc_leq _ _ = not_yet_pointer () +let loc_neq _ _ = not_yet_pointer () +let loc_diff _ _ _ = not_yet_pointer () + +let frame _sigma = [] +let alloc sigma _xs = sigma +let scope _seq _s _xs = [] +let valid _sigma _acs _l = error "Validity not yet implemented" +let invalid _sigma _l = error "Validity not yet implemented" +let global _sigma _p = F.p_true diff --git a/src/plugins/wp/MemRegion.mli b/src/plugins/wp/MemRegion.mli new file mode 100644 index 0000000000000000000000000000000000000000..6191649db155bbd608cd6adb2fc67907cc03e8a0 --- /dev/null +++ b/src/plugins/wp/MemRegion.mli @@ -0,0 +1,27 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2019 *) +(* CEA (Commissariat a l'energie atomique et aux energies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- Empty Memory Model --- *) +(* -------------------------------------------------------------------------- *) + +include Sigs.Model diff --git a/src/plugins/wp/MemTyped.ml b/src/plugins/wp/MemTyped.ml index f088afb4eb9c9cb216adb6893e14c88295dcab83..23b1b0349468c9b6e0be9ee7ff3a3cdd3eedda35 100644 --- a/src/plugins/wp/MemTyped.ml +++ b/src/plugins/wp/MemTyped.ml @@ -31,64 +31,38 @@ open Lang open Lang.F open Sigs open Definitions +open MemMemory let dkey_layout = Wp_parameters.register_category "layout" - module L = Qed.Logic +(* -------------------------------------------------------------------------- *) +(* --- Model Configuration --- *) +(* -------------------------------------------------------------------------- *) + let datatype = "MemTyped" let hypotheses () = [] -let library = "memory" - -let a_addr = Lang.datatype ~library "addr" -let t_addr = L.Data(a_addr,[]) -let f_base = Lang.extern_f ~library ~result:L.Int - ~link:{altergo = Qed.Engine.F_subst("%1.base"); - why3 = Qed.Engine.F_call("base"); - coq = Qed.Engine.F_subst("(base %1)"); - } "base" -let f_offset = Lang.extern_f ~library ~result:L.Int - ~link:{altergo = Qed.Engine.F_subst("%1.offset"); - why3 = Qed.Engine.F_call("offset"); - coq = Qed.Engine.F_subst("(offset %1)"); - } "offset" -let f_shift = Lang.extern_f ~library ~result:t_addr "shift" -let f_global = Lang.extern_f ~library ~result:t_addr ~category:L.Injection "global" -let f_null = Lang.extern_f ~library ~result:t_addr "null" -let f_base_offset = Lang.extern_f ~library ~category:Qed.Logic.Injection ~result:L.Int "base_offset" - -let ty_havoc = function - | Some l :: _ -> l - | _ -> raise Not_found +let configure () = + begin + Context.set Lang.pointer (fun _ -> t_addr) ; + Context.set Cvalues.null (p_equal a_null) ; + end -let l_havoc = Qed.Engine.{ - coq = F_call "fhavoc" ; - altergo = F_call "havoc" ; - why3 = F_call "havoc" ; - } - -let p_valid_rd = Lang.extern_fp ~library "valid_rd" -let p_valid_rw = Lang.extern_fp ~library "valid_rw" -let p_invalid = Lang.extern_fp ~library "invalid" -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_havoc ~link:l_havoc "havoc" -let f_region = Lang.extern_f ~library ~result:L.Int "region" (* base -> region *) -let p_framed = Lang.extern_fp ~library "framed" (* m-pointer -> prop *) -let p_linked = Lang.extern_fp ~library "linked" (* allocation-table -> prop *) -let p_sconst = Lang.extern_fp ~library "sconst" (* int-memory -> prop *) -let a_lt = Lang.extern_p ~library ~bool:"addr_lt_bool" ~prop:"addr_lt" () -let a_leq = Lang.extern_p ~library ~bool:"addr_le_bool" ~prop:"addr_le" () - -let a_addr_of_int = Lang.extern_f - ~category:L.Injection - ~library ~result:t_addr "addr_of_int" - -let a_int_of_addr = Lang.extern_f - ~category:L.Injection - ~library ~result:L.Int "int_of_addr" +let configure_ia = + let no_binder = { bind = fun _ f v -> f v } in + fun _vertex -> no_binder + +(* -------------------------------------------------------------------------- *) +(* --- Model Parameters --- *) +(* -------------------------------------------------------------------------- *) + +type pointer = NoCast | Fits | Unsafe +let pointer = Context.create "MemTyped.pointer" + +(* -------------------------------------------------------------------------- *) +(* --- Model Semantics --- *) +(* -------------------------------------------------------------------------- *) (* @@ -133,270 +107,6 @@ let a_int_of_addr = Lang.extern_f *) -(* -------------------------------------------------------------------------- *) -(* --- Utilities --- *) -(* -------------------------------------------------------------------------- *) - -let a_null = F.constant (e_fun f_null []) -let a_base p = e_fun f_base [p] -let a_offset p = e_fun f_offset [p] -let a_global b = e_fun f_global [b] -let a_base_offset k = e_fun f_base_offset [k] -let a_shift l k = e_fun f_shift [l;k] -let a_addr b k = a_shift (a_global b) k - -(* -------------------------------------------------------------------------- *) -(* --- Qed Simplifiers --- *) -(* -------------------------------------------------------------------------- *) - -(* - Pointer arithmetic for structure access and array access could be - defined directly using the record [{ base = p.base; offset = p.offset - + c*i + c' }]. However that gives very bad triggers for the memory - model axiomatization, so `shift p (c*i+c')` was used instead. It is - not sufficient for user axiomatisation because memory access in - axioms require trigger with arithmetic operators which is badly - handled by provers. So for each c and c', ie for each kind of - structure access and array access a specific function is used - `shift_xxx`. - - Moreover no simplification of `shift_xxx` is done for keeping the - same terms in axioms and the goal. `base` and `offset` function - simplify all the `shift_xxx` because it seems they don't appear - often in axioms and they are useful for simplifying `separated`, - `assigns` and pointer comparisons in goals. - - To sum up memory access should match, but not `\base`, `\offset`, - `\separated`, ... -*) - -type registered_shift = - | RS_Field of fieldinfo * term (* offset of the field *) - | RS_Shift of Z.t (* size of the element *) - -module RegisterShift = WpContext.Static - (struct - type key = lfun - type data = registered_shift - let name = "MemTyped.RegisterShift" - include Lang.Fun - end) - -let phi_base l = - match F.repr l with - | L.Fun(f,p::_) when RegisterShift.mem f -> a_base p - | L.Fun(f,[p;_]) when f==f_shift -> a_base p - | L.Fun(f,[b]) when f==f_global -> b - | L.Fun(f,[]) when f==f_null -> e_zero - | _ -> raise Not_found - -let phi_offset l = match F.repr l with - | L.Fun(f,[p;k]) when f==f_shift -> e_add (a_offset p) k - | L.Fun(f,_) when f==f_global || f==f_null -> F.e_zero - | L.Fun(f,p::args) -> - begin match RegisterShift.get f, args with - | Some (RS_Field(_,offset)), [] -> e_add offset (a_offset p) - | Some (RS_Shift size), [k] -> e_add (a_offset p) ((F.e_times size) k) - | Some _, _ -> assert false (* constructed at one place only *) - | None, _ -> raise Not_found - end - | _ -> raise Not_found - -let eq_shift a b = - let p = a_base a in - let q = a_base b in - let i = a_offset a in - let j = a_offset b in - if i==j then F.p_equal p q else - match F.is_equal p q with - | L.No -> F.p_false - | L.Yes -> F.p_equal i j - | L.Maybe -> raise Not_found - -let phi_shift f p i = - match F.repr p with - | L.Fun(g,[q;j]) when f == g -> F.e_fun f [q;F.e_add i j] - | _ -> raise Not_found - -(* -------------------------------------------------------------------------- *) -(* --- Simplifier for 'separated' --- *) -(* -------------------------------------------------------------------------- *) - -(* -logic a : int -logic b : int -logic S : prop - -predicate separated = a <= 0 or b <= 0 or S -*) - -let r_separated = function - | [p;a;q;b] -> - if a == F.e_one && b == F.e_one then F.e_neq p q - else - begin - let a_negative = F.e_leq a F.e_zero in - let b_negative = F.e_leq b F.e_zero in - if a_negative == e_true || b_negative == e_true then e_true else - let bp = a_base p in - let bq = a_base q in - let open Qed.Logic in - match F.is_true (F.e_eq bp bq) with - | No -> e_true (* Have S *) - | Yes when (a_negative == e_false && b_negative == e_false) -> - (* Reduced to S *) - let p_ofs = a_offset p in - let q_ofs = a_offset q in - let p_ofs' = F.e_add p_ofs a in - let q_ofs' = F.e_add q_ofs b in - F.e_or [ F.e_leq q_ofs' p_ofs ; - F.e_leq p_ofs' q_ofs ] - | _ -> raise Not_found - end - | _ -> raise Not_found - -let is_separated args = F.is_true (r_separated args) - -(* -------------------------------------------------------------------------- *) -(* --- Simplifier for 'included' --- *) -(* -------------------------------------------------------------------------- *) - -(* -logic a : int -logic b : int - -predicate R = p.base = q.base - /\ (q.offset <= p.offset) - /\ (p.offset + a <= q.offset + b) - -predicate included = 0 < a -> ( 0 <= b and R ) -predicate a_empty = a <= 0 -predicate b_negative = b < 0 - -lemma SAME_P: p=q -> (R <-> a<=b) -lemma SAME_A: a=b -> (R <-> p=q) - -goal INC_P: p=q -> (included <-> ( 0 < a -> a <= b )) (by SAME_P) -goal INC_A: a=b -> 0 < a -> (included <-> R) (by SAME_A) -goal INC_1: a_empty -> (included <-> true) -goal INC_2: b_negative -> (included <-> a_empty) -goal INC_3: not R -> (included <-> a_empty) -goal INC_4: not a_empty -> not b_negative -> (included <-> R) -*) - -let r_included = function - | [p;a;q;b] -> - if F.e_eq p q == F.e_true - then F.e_imply [F.e_lt F.e_zero a] (F.e_leq a b) (* INC_P *) - else - if (F.e_eq a b == F.e_true) && (F.e_lt F.e_zero a == F.e_true) - then F.e_eq p q (* INC_A *) - else - begin - let a_empty = F.e_leq a F.e_zero in - let b_negative = F.e_lt b F.e_zero in - if a_empty == F.e_true then F.e_true (* INC_1 *) else - if b_negative == F.e_true then a_empty (* INC_2 *) else - let bp = a_base p in - let bq = a_base q in - let open Qed.Logic in - match F.is_true (F.e_eq bp bq) with - | No -> a_empty (* INC_3 *) - | Yes when (a_empty == e_false && b_negative == e_false) -> - (* INC_4 *) - let p_ofs = a_offset p in - let q_ofs = a_offset q in - if a == b then F.e_eq p_ofs q_ofs - else - let p_ofs' = e_add p_ofs a in - let q_ofs' = e_add q_ofs b in - e_and [ F.e_leq q_ofs p_ofs ; F.e_leq p_ofs' q_ofs' ] - | _ -> raise Not_found - end - | _ -> raise Not_found - -(* -------------------------------------------------------------------------- *) -(* --- Simplifier for 'havoc' --- *) -(* -------------------------------------------------------------------------- *) - -(* havoc(m_undef, havoc(_undef,m0,p0,a0), p1,a1) = - - havoc(m_undef, m0, p1,a1) WHEN included (p1,a1,p0,a0) *) -let r_havoc = function - | [undef1;m1;p1;a1] -> begin - match F.repr m1 with - | L.Fun( f , [_undef0;m0;p0;a0] ) when f == f_havoc -> begin - let open Qed.Logic in - match F.is_true (r_included [p0;a0;p1;a1]) with - | Yes -> F.e_fun f_havoc [undef1;m0;p1;a1] - | _ -> raise Not_found - end - | _ -> raise Not_found - end - | _ -> raise Not_found - -(* havoc(undef,m,p,a)[k] = - - undef[k] WHEN separated (p,a,k,1) - - m[k] WHEN NOT separated (p,a,k,1) -*) -let r_get_havoc = function - | [undef;m;p;a] -> - (fun _ k -> - match is_separated [p;a;k;e_one] with - | L.Yes -> F.e_get m k - | L.No -> F.e_get undef k - | _ -> raise Not_found) - | _ -> raise Not_found - -(* -------------------------------------------------------------------------- *) -(* --- Simplifier for int/addr conversion --- *) -(* -------------------------------------------------------------------------- *) - -let phi_int_of_addr p = - if p == a_null then F.e_zero else - match F.repr p with - | L.Fun(f,[a]) when f == a_addr_of_int -> a - | _ -> raise Not_found - -let phi_addr_of_int p = - if p == F.e_zero then a_null else - match F.repr p with - | L.Fun(f,[a]) when f == a_int_of_addr -> a - | _ -> raise Not_found - -(* -------------------------------------------------------------------------- *) -(* --- Simplifier Registration --- *) -(* -------------------------------------------------------------------------- *) - -let () = Context.register - begin fun () -> - F.set_builtin_1 f_base phi_base ; - F.set_builtin_1 f_offset phi_offset ; - F.set_builtin_2 f_shift (phi_shift f_shift) ; - F.set_builtin_eqp f_shift eq_shift ; - F.set_builtin_eqp f_global eq_shift ; - F.set_builtin p_separated r_separated ; - F.set_builtin p_included r_included ; - F.set_builtin f_havoc r_havoc ; - F.set_builtin_get f_havoc r_get_havoc ; - F.set_builtin_1 a_addr_of_int phi_addr_of_int ; - F.set_builtin_1 a_int_of_addr phi_int_of_addr ; - end - -(* -------------------------------------------------------------------------- *) -(* --- Model Parameters --- *) -(* -------------------------------------------------------------------------- *) - -let configure () = - begin - Context.set Lang.pointer (fun _ -> t_addr) ; - Context.set Cvalues.null (p_equal a_null) ; - end -let no_binder = { bind = fun _ f v -> f v } -let configure_ia _ = no_binder - -type pointer = NoCast | Fits | Unsafe -let pointer = Context.create "MemTyped.pointer" - (* -------------------------------------------------------------------------- *) (* --- Chunks --- *) (* -------------------------------------------------------------------------- *) @@ -431,9 +141,6 @@ struct let compare a b = rank a - rank b let equal = (=) let pretty fmt c = Format.pp_print_string fmt (name c) - let key_of_chunk = function - | M_int | M_char | M_f32 | M_f64 | M_pointer -> t_addr - | T_alloc -> L.Int let val_of_chunk = function | M_int | M_char -> L.Int | M_f32 -> Cfloat.tau_of_float Ctypes.Float32 @@ -475,24 +182,13 @@ and footprint_comp c = Heap.Set.union ft (footprint (object_of f.ftype)) ) Heap.Set.empty c.cfields -let signature ft = - let s = Sigma.create () in - let xs = ref [] in - let cs = ref [] in - Heap.Set.iter - (fun c -> - cs := c :: !cs ; - xs := (Sigma.get s c) :: !xs ; - ) ft ; - List.rev !xs , List.rev !cs , s - -let memories sigma ft = List.map (Sigma.value sigma) ft +let domain obj _l = footprint obj -let rec size_of_object = function +let rec length_of_object = function | C_int _ | C_float _ | C_pointer _ -> 1 - | C_comp c -> size_of_comp c + | C_comp c -> length_of_comp c | C_array { arr_flat = Some { arr_size = n } ; arr_element = elt } -> - n * (size_of_typ elt) + n * (length_of_typ elt) | C_array _ as a -> if Wp_parameters.ExternArrays.get () then max_int @@ -500,20 +196,20 @@ let rec size_of_object = function Warning.error ~source:"Typed Model" "Undefined array-size (%a)" Ctypes.pretty a -and size_of_typ t = size_of_object (object_of t) -and size_of_field f = size_of_typ f.ftype -and size_of_comp c = +and length_of_typ t = length_of_object (object_of t) +and length_of_field f = length_of_typ f.ftype +and length_of_comp c = (* union field are considered as struct field *) List.fold_left - (fun s f -> s + size_of_field f) + (fun s f -> s + length_of_field f) 0 c.cfields -let offset_of_field f = +let position_of_field f = let rec fnext k f = function | [] -> assert false | g::gs -> if Fieldinfo.equal f g then k - else fnext (k + size_of_field g) f gs + else fnext (k + length_of_field g) f gs in fnext 0 f f.fcomp.cfields (* -------------------------------------------------------------------------- *) @@ -532,13 +228,32 @@ let occurs x l = F.occurs x l (* --- Generated Axiomatization --- *) (* -------------------------------------------------------------------------- *) -let loadrec = ref (fun _ _ _ -> assert false) - let cluster_globals () = Definitions.cluster ~id:"Globals" ~title:"Global Variables" () -let cluster_memory () = - Definitions.cluster ~id:"Compound" ~title:"Memory Compound Updates" () +type shift = + | RS_Field of fieldinfo * int (* offset of the field *) + | RS_Index of int (* size of the shift *) + +let phi_base = function + | p::_ -> a_base p + | _ -> raise Not_found + +let phi_field offset = function + | [p] -> e_add (a_offset p) (F.e_int offset) + | _ -> raise Not_found + +let phi_index size = function + | [p;k] -> e_add (a_offset p) (F.e_fact size k) + | _ -> raise Not_found + +module RegisterShift = WpContext.Static + (struct + type key = lfun + type data = shift + let name = "MemTyped.RegisterShift" + include Lang.Fun + end) module ShiftFieldDef = WpContext.StaticGenerator(Cil_datatype.Fieldinfo) (struct @@ -549,14 +264,14 @@ module ShiftFieldDef = WpContext.StaticGenerator(Cil_datatype.Fieldinfo) let generate f = let result = t_addr in let lfun = Lang.generated_f ~result "shiftfield_%s" (Lang.field_id f) in - let offset = (F.e_int (offset_of_field f)) in + let position = position_of_field f in (* Since its a generated it is the unique name given *) let xloc = Lang.freshvar ~basename:"p" t_addr in let loc = e_var xloc in - let def = a_shift loc offset in + let def = a_shift loc (F.e_int position) in let dfun = Definitions.Function( result , Def , def) in - RegisterShift.define lfun (RS_Field(f,offset)) ; - F.set_builtin_eqp lfun eq_shift ; + RegisterShift.define lfun (RS_Field(f,position)) ; + MemMemory.register ~base:phi_base ~offset:(phi_field position) lfun ; { d_lfun = lfun ; d_types = 0 ; d_params = [xloc] ; @@ -574,7 +289,7 @@ module ShiftField = WpContext.Generator(Cil_datatype.Fieldinfo) type data = lfun let compile fd = let dfun = ShiftFieldDef.get fd in - let d_cluster = cluster_memory () in + let d_cluster = MemLoader.cluster () in Definitions.define_symbol { dfun with d_cluster } ; dfun.d_lfun end) @@ -610,17 +325,17 @@ module ShiftGen = WpContext.StaticGenerator(Cobj) let generate obj = let result = t_addr in let shift = Lang.generated_f ~result "shift_%s" (c_object_id obj) in - let size = Integer.of_int (size_of_object obj) in + let size = length_of_object obj in (* Since its a generated it is the unique name given *) let xloc = Lang.freshvar ~basename:"p" t_addr in let loc = e_var xloc in let xk = Lang.freshvar ~basename:"k" Qed.Logic.Int in let k = e_var xk in - let def = a_shift loc (F.e_times size k) in + let def = a_shift loc (F.e_fact size k) in let dfun = Definitions.Function( result , Def , def) in - RegisterShift.define shift (RS_Shift size) ; - F.set_builtin_eqp shift eq_shift ; - F.set_builtin_2 shift (phi_shift shift) ; + RegisterShift.define shift (RS_Index size) ; + MemMemory.register ~base:phi_base ~offset:(phi_index size) + ~linear:true shift ; { d_lfun = shift ; d_types = 0 ; d_params = [xloc;xk] ; @@ -639,7 +354,7 @@ module Shift = WpContext.Generator(Cobj) type data = lfun let compile obj = let dfun = ShiftGen.get obj in - let d_cluster = cluster_memory () in + let d_cluster = MemLoader.cluster () in Definitions.define_symbol { dfun with d_cluster } ; dfun.d_lfun end) @@ -739,6 +454,10 @@ module STRING = WpContext.Generator(LITERAL) end) +(* -------------------------------------------------------------------------- *) +(* --- Base Registration --- *) +(* -------------------------------------------------------------------------- *) + module RegisterBASE = WpContext.Index (struct type key = lfun @@ -763,22 +482,20 @@ module BASE = WpContext.Generator(Varinfo) l_cluster = cluster_globals () ; } + let sizeof x = + Warning.handle + ~handler:(fun _ -> None) + ~effect:(Printf.sprintf "No allocation size for variable '%s'" x.vname) + (fun obj -> Some (length_of_object obj)) + (Ctypes.object_of x.vtype) + let linked prefix x base = let name = prefix ^ "_linked" in - let obj = Ctypes.object_of x.vtype in - let size = - if x.vglob then - Warning.handle - ~handler:(fun _ -> None) - ~effect:(Printf.sprintf "No allocation size for variable '%s'" x.vname) - (fun obj -> Some (size_of_object obj)) - obj - else Some 0 - in + let size = if x.vglob then sizeof x else Some 0 in match size with | None -> () | Some size -> - let a = Lang.freshvar ~basename:"alloc" (Chunk.tau_of_chunk T_alloc) in + let a = Lang.freshvar ~basename:"alloc" t_malloc in let m = e_var a in let m_linked = p_call p_linked [m] in let base_size = p_equal (F.e_get m base) (e_int size) in @@ -816,215 +533,6 @@ module BASE = WpContext.Generator(Varinfo) let compile = Lang.local generate end) - -(* Add frame lemmas for generated logical function *) -module MONOTONIC : -sig - val generate : - string -> lfun -> var list -> chunk list -> (term list -> term) -> unit -end = -struct - - type env = { - lfun : lfun ; - sigma : sigma ; - vars : var list ; - params : term list ; - range : term ; - chunks : chunk list ; - memories : term list ; - } - - let _cluster () = Definitions.cluster ~id:"TypedMemory" () - (* projectified *) - - let update env c m = - List.map - (fun c' -> - if Chunk.equal c c' then m else Sigma.value env.sigma c' - ) env.chunks - - let separated env q k = F.p_call p_separated [List.hd env.params;env.range;q;k] - let included env q k = F.p_call p_included [List.hd env.params;env.range;q;k] - - let generate_update prefix env c = - let name = prefix ^ "_update_" ^ Chunk.name c in - let q = e_var (Lang.freshvar ~basename:"q" (Chunk.key_of_chunk c)) in - let v = e_var (Lang.freshvar ~basename:"v" (Chunk.val_of_chunk c)) in - let phi = e_fun env.lfun (env.params @ env.memories) in - let mem' = e_set (Sigma.value env.sigma c) q v in - let phi' = e_fun env.lfun (env.params @ update env c mem') in - let lemma = p_imply (separated env q e_one) (p_equal phi' phi) in - Definitions.define_lemma { - l_assumed = true ; - l_name = name ; l_types = 0 ; - l_triggers = [[Trigger.of_term phi']] ; - l_forall = F.p_vars lemma ; - l_lemma = lemma ; - l_cluster = cluster_memory () ; - } - - let generate_eqmem prefix env c = - let name = prefix ^ "_eqmem_" ^ Chunk.name c in - let q = e_var (Lang.freshvar ~basename:"q" (Chunk.key_of_chunk c)) in - let k = e_var (Lang.freshvar ~basename:"k" L.Int) in - let phi = e_fun env.lfun (env.params @ env.memories) in - let mem = Sigma.value env.sigma c in - let mem' = e_var (Lang.freshen (Sigma.get env.sigma c)) in - let phi' = e_fun env.lfun (env.params @ update env c mem') in - let eqmem = F.p_call p_eqmem [mem;mem';q;k] in - let lemma = p_hyps [included env q k;eqmem] (p_equal phi' phi) in - Definitions.define_lemma { - l_assumed = true ; - l_name = name ; l_types = 0 ; - l_triggers = [ - [Trigger.of_pred eqmem ; Trigger.of_term phi ] ; - [Trigger.of_pred eqmem ; Trigger.of_term phi'] ; - ] ; - l_forall = F.p_vars lemma ; - l_lemma = lemma ; - l_cluster = cluster_memory () ; - } - - let generate_havoc prefix env c = - let name = prefix ^ "_havoc_" ^ Chunk.name c in - let q = e_var (Lang.freshvar ~basename:"q" (Chunk.key_of_chunk c)) in - let k = e_var (Lang.freshvar ~basename:"k" L.Int) in - let phi = e_fun env.lfun (env.params @ env.memories) in - let mem = Sigma.value env.sigma c in - let mem' = e_var (Lang.freshen (Sigma.get env.sigma c)) in - let m_undef = e_var (Lang.freshen (Sigma.get env.sigma c)) in - let phi' = e_fun env.lfun (env.params @ update env c mem') in - let havoc = p_equal mem' (F.e_fun f_havoc [m_undef;mem;q;k]) in - let lemma = p_hyps [separated env q k;havoc] (p_equal phi' phi) in - Definitions.define_lemma { - l_assumed = true ; - l_name = name ; l_types = 0 ; - l_triggers = [ - [ Trigger.of_pred havoc ; Trigger.of_term phi ] ; - [ Trigger.of_pred havoc ; Trigger.of_term phi'] ; - ] ; - l_forall = F.p_vars lemma ; - l_lemma = lemma ; - l_cluster = cluster_memory () ; - } - - let generate prefix lfun xs cs range = - let sigma = Sigma.create () in - let xp = Lang.freshvar ~basename:"p" t_addr in - let xs = List.map Lang.freshen xs in - let ps = List.map e_var xs in - let ms = memories sigma cs in - let env = { - sigma = sigma ; lfun = lfun ; - vars = xp::xs ; params = e_var xp::ps ; - chunks = cs ; memories = ms ; - range = range ps ; - } in - List.iter - (fun chunk -> - generate_update prefix env chunk ; - generate_eqmem prefix env chunk ; - generate_havoc prefix env chunk ; - ) cs - -end - -module COMP = WpContext.Generator(Compinfo) - (struct - let name = "MemTyped.COMP" - type key = compinfo - type data = lfun * chunk list - - let generate c = - let result = Lang.tau_of_comp c in - let lfun = Lang.generated_f ~result "Load_%s" (Lang.comp_id c) in - (* Since its a generated it is the unique name given *) - let prefix = Lang.Fun.debug lfun in - let xmem,ft,sigma = signature (footprint_comp c) in - let xloc = Lang.freshvar ~basename:"p" t_addr in - let loc = e_var xloc in - let def = List.map - (fun f -> - Cfield f , !loadrec sigma (object_of f.ftype) (field loc f) - ) c.cfields in - let dfun = Definitions.Function( result , Def , e_record def ) in - Definitions.define_symbol { - d_lfun = lfun ; d_types = 0 ; - d_params = xloc :: xmem ; - d_definition = dfun ; - d_cluster = cluster_memory () ; - } ; - let range = e_int (size_of_comp c) in - MONOTONIC.generate prefix lfun [] ft (fun _ -> range) ; - lfun , ft - - let compile = Lang.local generate - end) - -module ARRAY = WpContext.Generator(Matrix.NATURAL) - (struct - open Matrix - let name = "MemTyped.ARRAY" - type key = matrix - type data = lfun * chunk list - - let generate (obj,ds) = - let result = Matrix.tau obj ds in - let lfun = Lang.generated_f ~result "Array%s_%s" - (Matrix.id ds) (Matrix.natural_id obj) in - let prefix = Lang.Fun.debug lfun in - let axiom = prefix ^ "_access" in - let xmem,ft,sigma = signature (footprint obj) in - let xloc = Lang.freshvar ~basename:"p" t_addr in - let loc = e_var xloc in - let denv = Matrix.denv ds in - let phi = e_fun lfun (loc :: denv.size_val @ List.map e_var xmem) in - let arr = List.fold_left e_get phi denv.index_val in - let elt = !loadrec sigma obj (shift loc obj (e_sum denv.index_offset)) in - let lemma = p_hyps denv.index_range (p_equal arr elt) in - let cluster = cluster_memory () in - Definitions.define_symbol { - d_lfun = lfun ; d_types = 0 ; - d_params = xloc :: denv.size_var @ xmem ; - d_definition = Logic result ; - d_cluster = cluster ; - } ; - Definitions.define_lemma { - l_assumed = true ; - l_name = axiom ; l_types = 0 ; - l_forall = F.p_vars lemma ; - l_triggers = [[Trigger.of_term arr]] ; - l_lemma = lemma ; - l_cluster = cluster ; - } ; - if denv.monotonic then - MONOTONIC.generate prefix lfun denv.size_var ft F.e_prod ; - lfun , ft - - let compile = Lang.local generate - end) - -(* -------------------------------------------------------------------------- *) -(* --- Loading Elementary Values --- *) -(* -------------------------------------------------------------------------- *) - -let loadvalue sigma obj l = match obj with - | C_int i -> F.e_get (Sigma.value sigma (m_int i)) l - | C_float f -> F.e_get (Sigma.value sigma (m_float f)) l - | C_pointer _ -> F.e_get (Sigma.value sigma M_pointer) l - | C_comp c -> - let phi,cs = COMP.get c in - e_fun phi (l :: memories sigma cs) - | C_array a -> - let m = Matrix.of_array a in - let phi,cs = ARRAY.get m in - e_fun phi ( l :: Matrix.size m @ memories sigma cs ) - -let () = loadrec := loadvalue - -let load sigma obj l = Val (loadvalue sigma obj l) - (* -------------------------------------------------------------------------- *) (* --- Locations --- *) (* -------------------------------------------------------------------------- *) @@ -1044,13 +552,12 @@ let cvar x = let pointer_loc t = t let pointer_val t = t -let get_alloc sigma l = F.e_get (Sigma.value sigma T_alloc) (a_base l) -let get_last sigma l = e_add (get_alloc sigma l) e_minus_one +let allocated sigma l = F.e_get (Sigma.value sigma T_alloc) (a_base l) let base_addr l = a_addr (a_base l) e_zero let base_offset l = a_base_offset (a_offset l) let block_length sigma obj l = - e_fact (Ctypes.sizeof_object obj) (get_alloc sigma l) + e_fact (Ctypes.sizeof_object obj) (allocated sigma l) (* -------------------------------------------------------------------------- *) (* --- Cast --- *) @@ -1348,99 +855,80 @@ let cast s l = "%a" pp_mismatch s ; l end -let loc_of_int _ v = F.e_fun a_addr_of_int [v] -let int_of_loc _ l = F.e_fun a_int_of_addr [l] +let loc_of_int _ v = F.e_fun f_addr_of_int [v] +let int_of_loc _ l = F.e_fun f_int_of_addr [l] (* -------------------------------------------------------------------------- *) -(* --- Updates --- *) +(* --- Frames --- *) (* -------------------------------------------------------------------------- *) -let domain obj _l = footprint obj - -let updated s c l v = - let m1 = Sigma.value s.pre c in - let m2 = Sigma.value s.post c in - [Set(m2,F.e_set m1 l v)] - -let havoc_range s obj l n = - let ps = ref [] in - Heap.Set.iter - (fun c -> - let basename = (Chunk.basename_of_chunk c)^"_undef" in - let tau = Chunk.tau_of_chunk c in - let m_undef = e_var (Lang.freshvar ~basename tau) in - let m1 = Sigma.value s.pre c in - let m2 = Sigma.value s.post c in - ps := (p_equal m2 (F.e_fun f_havoc [m_undef;m1;l;n])) :: !ps - ) (footprint obj) ; !ps - -let havoc s obj l = havoc_range s obj l (e_int (size_of_object obj)) - -let eqmem s obj l = - let ps = ref [] in - let n = e_int (size_of_object obj) in - Heap.Set.iter - (fun c -> - let m1 = Sigma.value s.pre c in - let m2 = Sigma.value s.post c in - if m1 != m2 then - ps := F.p_call p_eqmem [m1;m2;l;n] :: !ps - ) (footprint obj) ; !ps +let frames obj addr = function + | T_alloc -> [] + | m -> + let offset = F.e_int (length_of_object obj) in + let sizeof = F.e_one in + let tau = Chunk.val_of_chunk m in + let basename = Chunk.basename_of_chunk m in + MemMemory.frames ~addr ~offset ~sizeof ~basename tau (* -------------------------------------------------------------------------- *) -(* --- Copy --- *) +(* --- Loader --- *) (* -------------------------------------------------------------------------- *) -let stored s obj l v = - match obj with - | C_int i -> updated s (m_int i) l v - | C_float f -> updated s (m_float f) l v - | C_pointer _ -> updated s M_pointer l v - | C_comp _ | C_array _ -> - Set(loadvalue s.post obj l, v) :: - (List.map (fun p -> Assert p) (havoc s obj l)) +module MODEL = +struct + module Chunk = Chunk + module Sigma = Sigma + let name = "MemTyped.LOADER" + type nonrec loc = loc + let field = field + let shift = shift + let sizeof = length_of_object + let domain = domain + let frames = frames + let to_addr l = l + let to_region_pointer l = 0,l + let of_region_pointer _ _ l = l + + let load_int sigma i l = F.e_get (Sigma.value sigma (m_int i)) l + let load_float sigma f l = F.e_get (Sigma.value sigma (m_float f)) l + let load_pointer sigma _t l = F.e_get (Sigma.value sigma M_pointer) l + + let last sigma obj l = + let n = length_of_object obj in + e_sub (F.e_div (allocated sigma l) (F.e_int n)) e_one + + let havoc obj loc ~length chunk ~fresh ~current = + if chunk <> T_alloc then + let n = F.e_fact (length_of_object obj) length in + F.e_fun f_havoc [fresh;current;loc;n] + else fresh + + let eqmem obj loc _chunk m1 m2 = + F.p_call p_eqmem [m1;m2;loc;e_int (length_of_object obj)] + + let eqmem_forall obj loc _chunk m1 m2 = + let xp = Lang.freshvar ~basename:"p" t_addr in + let p = F.e_var xp in + let n = F.e_int (length_of_object obj) in + let separated = F.p_call p_separated [p;e_one;loc;n] in + let equal = p_equal (e_get m1 p) (e_get m2 p) in + [xp],separated,equal -let copied s obj p q = stored s obj p (loadvalue s.pre obj q) + let updated sigma c l v = c , F.e_set (Sigma.value sigma c) l v -(* -------------------------------------------------------------------------- *) -(* --- Assignation --- *) -(* -------------------------------------------------------------------------- *) + let store_int sigma i l v = updated sigma (m_int i) l v + 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 assigned_loc s obj l = - match obj with - | C_int _ | C_float _ | C_pointer _ -> - let x = Lang.freshvar ~basename:"v" (Lang.tau_of_object obj) in - List.map Cvalues.equation (stored s obj l (e_var x)) - | C_comp _ | C_array _ -> - havoc s obj l - -let equal_loc s obj l = - match obj with - | C_int _ | C_float _ | C_pointer _ -> - [p_equal (loadvalue s.pre obj l) (loadvalue s.post obj l)] - | C_comp _ | C_array _ -> eqmem s obj l - -let assigned_range s obj l a b = - let l = shift l obj a in - let n = e_fact (size_of_object obj) (e_range a b) in - havoc_range s obj l n - -let assigned s obj = function - | Sloc l -> assigned_loc s obj l - | Sdescr(xs,l,p) -> - let xa = Lang.freshvar ~basename:"p" t_addr in - let la = F.e_var xa in - let n = F.e_int (size_of_object obj) in - let sep = F.p_call p_separated [la;n;l;n] in - let sep_all = F.p_forall xs (F.p_imply p sep) in - let eq_loc = F.p_conj (equal_loc s obj la) in - [F.p_forall [xa] (F.p_imply sep_all eq_loc)] - | Sarray(l,obj,n) -> - assigned_range s obj l e_zero (e_int (n-1)) - | Srange(l,obj,u,v) -> - let a = match u with Some a -> a | None -> e_zero in - let b = match v with Some b -> b | None -> get_last s.pre l in - assigned_range s obj l a b +end + +module LOADER = MemLoader.Make(MODEL) + +let load = LOADER.load +let stored = LOADER.stored +let copied = LOADER.copied +let assigned = LOADER.assigned (* -------------------------------------------------------------------------- *) (* --- Loc Comparison --- *) @@ -1454,11 +942,11 @@ let loc_compare f_cmp i_cmp p q = let is_null l = p_equal l null let loc_eq = p_equal let loc_neq = p_neq -let loc_lt = loc_compare a_lt p_lt -let loc_leq = loc_compare a_leq p_leq +let loc_lt = loc_compare p_addr_lt p_lt +let loc_leq = loc_compare p_addr_le p_leq let loc_diff obj p q = let delta = e_sub (a_offset p) (a_offset q) in - let size = e_int (size_of_object obj) in + let size = e_int (length_of_object obj) in e_div delta size (* -------------------------------------------------------------------------- *) @@ -1474,10 +962,10 @@ let s_invalid sigma p n = let segment phi = function | Rloc(obj,l) -> - phi l (e_int (size_of_object obj)) + phi l (e_int (length_of_object obj)) | Rrange(l,obj,Some a,Some b) -> let l = shift l obj a in - let n = e_fact (size_of_object obj) (e_range a b) in + let n = e_fact (length_of_object obj) (e_range a b) in phi l n | Rrange(l,_,a,b) -> Wp_parameters.abort ~current:true @@ -1507,7 +995,7 @@ let scope seq scope xs = (fun m x -> let size = match scope with | Sigs.Leave -> 0 - | Sigs.Enter -> size_of_typ x.vtype + | Sigs.Enter -> length_of_typ x.vtype in F.e_set m (BASE.get x) (e_int size)) (Sigma.value seq.pre T_alloc) xs in [ p_equal (Sigma.value seq.post T_alloc) alloc ] @@ -1515,58 +1003,18 @@ let scope seq scope xs = let global _sigma p = p_leq (e_fun f_region [a_base p]) e_zero (* -------------------------------------------------------------------------- *) -(* --- Domain --- *) +(* --- Segments --- *) (* -------------------------------------------------------------------------- *) -type range = - | LOC of term * term (* loc - size *) - | RANGE of term * Vset.set (* base - range offset *) +let included = + let addrof l = l in + let sizeof = length_of_object in + MemMemory.included ~shift ~addrof ~sizeof -let range = function - | Rloc(obj,l) -> - LOC( l , e_int (size_of_object obj) ) - | Rrange(l,obj,Some a,Some b) -> - let l = shift l obj a in - let n = e_fact (size_of_object obj) (e_range a b) in - LOC( l , n ) - | Rrange(l,_obj,None,None) -> - RANGE( a_base l , Vset.range None None ) - | Rrange(l,obj,Some a,None) -> - let se = size_of_object obj in - RANGE( a_base l , Vset.range (Some (e_fact se a)) None ) - | Rrange(l,obj,None,Some b) -> - let se = size_of_object obj in - RANGE( a_base l , Vset.range None (Some (e_fact se b)) ) - -let range_set = function - | LOC(l,n) -> - let a = a_offset l in - let b = e_add a n in - a_base l , Vset.range (Some a) (Some b) - | RANGE(base,set) -> base , set - -let r_included r1 r2 = - match r1 , r2 with - | LOC(l1,n1) , LOC(l2,n2) -> - p_call p_included [l1;n1;l2;n2] - | _ -> - let base1,set1 = range_set r1 in - let base2,set2 = range_set r2 in - p_if (p_equal base1 base2) - (Vset.subset set1 set2) - (Vset.is_empty set1) - -let r_disjoint r1 r2 = - match r1 , r2 with - | LOC(l1,n1) , LOC(l2,n2) -> - p_call p_separated [l1;n1;l2;n2] - | _ -> - let base1,set1 = range_set r1 in - let base2,set2 = range_set r2 in - p_imply (p_equal base1 base2) (Vset.disjoint set1 set2) - -let included s1 s2 = r_included (range s1) (range s2) -let separated s1 s2 = r_disjoint (range s1) (range s2) +let separated = + let addrof l = l in + let sizeof = length_of_object in + MemMemory.separated ~shift ~addrof ~sizeof (* -------------------------------------------------------------------------- *) (* --- State Model --- *) @@ -1583,7 +1031,7 @@ let rec lookup_a e = and lookup_f f es = try match RegisterShift.find f , es with | RS_Field(fd,_) , [e] -> Mstate.field (lookup_lv e) fd - | RS_Shift _ , [e;k] -> Mstate.index (lookup_lv e) k + | RS_Index _ , [e;k] -> Mstate.index (lookup_lv e) k | _ -> raise Not_found with Not_found when es = [] -> Sigs.(Mvar (RegisterBASE.find f),[]) diff --git a/src/plugins/wp/MemTyped.mli b/src/plugins/wp/MemTyped.mli index 6c23647b4fe25faa6e81b96584cbae0f23199dae..5bd5298918c5a58fba5741d150fb2c19e81c1aea 100644 --- a/src/plugins/wp/MemTyped.mli +++ b/src/plugins/wp/MemTyped.mli @@ -28,11 +28,3 @@ include Sigs.Model type pointer = NoCast | Fits | Unsafe val pointer : pointer Context.value -val f_havoc : Lang.lfun -val p_separated : Lang.lfun -val p_included : Lang.lfun -val p_valid_rd : Lang.lfun -val p_valid_rw : Lang.lfun -val p_invalid : Lang.lfun -val a_base : Lang.F.term -> Lang.F.term -val a_offset : Lang.F.term -> Lang.F.term diff --git a/src/plugins/wp/MemVar.ml b/src/plugins/wp/MemVar.ml index b4d8a304b5e39ebcfb26c760a27b16bc269f24c9..58845184bfd33806fb328bf9d3fdbecb4f842b8a 100644 --- a/src/plugins/wp/MemVar.ml +++ b/src/plugins/wp/MemVar.ml @@ -1016,14 +1016,15 @@ struct let eqk = p_forall (y::ys) (p_imply ek (p_equal ak bk)) in assigned_path (eqk :: hs) xs ys ae be ofs - let assigned_descr s xs mem x ofs p = + let assigned_genset s xs mem x ofs p = let valid = valid_offset_path s.post Sigs.RW mem x ofs in let a = get_term s.pre x in let b = get_term s.post x in let a_ofs = access a ofs in let b_ofs = access b ofs in let p_sloc = p_forall xs (p_hyps [valid;p_not p] (p_equal a_ofs b_ofs)) in - assigned_path [p_sloc] xs [] a b ofs + let conds = assigned_path [p_sloc] xs [] a b ofs in + List.map (fun p -> Assert p) conds (* -------------------------------------------------------------------------- *) (* --- Assigned --- *) @@ -1034,8 +1035,7 @@ struct | Val((CVAL|CREF),_,[]) -> [] (* full update *) | Val((CVAL|CREF),_,_) as vloc -> let v = Lang.freshvar ~basename:"v" (Lang.tau_of_object obj) in - let eqs = stored seq obj vloc (e_var v) in - List.map Cvalues.equation eqs + stored seq obj vloc (e_var v) | Val((HEAP|CTXT|CARR) as m,x,ofs) -> M.assigned (mseq_of_seq seq) obj (Sloc (mloc_of_path m x ofs)) | Loc l -> @@ -1048,8 +1048,7 @@ struct | Val((CVAL|CREF),_,_) as vloc -> let te = Lang.tau_of_object elt in let v = Lang.freshvar ~basename:"v" Qed.Logic.(Array(Int,te)) in - let eqs = stored seq obj vloc (e_var v) in - List.map Cvalues.equation eqs + stored seq obj vloc (e_var v) | Val((HEAP|CTXT|CARR) as m,x,ofs) -> let l = mloc_of_path m x ofs in M.assigned (mseq_of_seq seq) obj (Sarray(l,elt,n)) @@ -1067,7 +1066,7 @@ struct let k = Lang.freshvar ~basename:"k" Qed.Logic.Int in let p = Vset.in_range (e_var k) a b in let ofs = ofs_shift elt (e_var k) ofs in - assigned_descr seq [k] m x ofs p + assigned_genset seq [k] m x ofs p let assigned_descr seq obj xs l p = match l with @@ -1077,7 +1076,7 @@ struct | Val((HEAP|CTXT|CARR) as m,x,ofs) -> M.assigned (mseq_of_seq seq) obj (Sdescr(xs,mloc_of_path m x ofs,p)) | Val((CVAL|CREF) as m,x,ofs) -> - assigned_descr seq xs m x ofs p + assigned_genset seq xs m x ofs p let assigned seq obj = function | Sloc l -> assigned_loc seq obj l diff --git a/src/plugins/wp/Region.ml b/src/plugins/wp/Region.ml index 22813de5c12093676432f308fbce7fec0de96961..dc77afe871e5063a16ec80c7a15e096c539fd10b 100644 --- a/src/plugins/wp/Region.ml +++ b/src/plugins/wp/Region.ml @@ -20,254 +20,630 @@ (* *) (**************************************************************************) +open Cil_datatype +open Layout + +module Wp = Wp_parameters + (* -------------------------------------------------------------------------- *) -(* --- Logic Path and Regions --- *) +(* --- Access Maps --- *) (* -------------------------------------------------------------------------- *) -open Qed.Logic -open Lang -open Lang.F -open Vset +module Vmap = Varinfo.Map +module Smap = Datatype.String.Map +module Rmap = Qed.Intmap +module Rset = Qed.Intset +module Dmap = Qed.Listmap.Make(Offset) +module Dset = Qed.Listset.Make(Deref) +module Acs = Qed.Listset.Make(Lvalue) +module Class = Qed.Listset.Make(Datatype.String) +module Ranks = Qed.Listset.Make(Datatype.Int) + +type region = { + id : int ; + mutable garbled : bool ; + mutable rw : bool ; + mutable pack : bool ; + mutable flat : bool ; + mutable names : Class.t ; + mutable alias : alias ; + mutable delta : int Dmap.t ; + mutable deref : Dset.t ; + mutable read : Acs.t ; + mutable written : Acs.t ; + mutable shifted : Acs.t ; + mutable copiedTo : Rset.t ; (* copies to *) + mutable pointsTo : int option ; +} + +type map = { + cache : Offset.cache ; + queue : int Queue.t ; + mutable rid : int ; + mutable vars : int Vmap.t ; + mutable return : int ; (* -1 when undefined *) + mutable strings : (int * string) Rmap.t ; (* eid -> rid *) + mutable index : int Smap.t ; + mutable region : region Rmap.t ; + mutable aliasing : int Rmap.t ; + mutable cluster : region cluster Rmap.t ; + mutable roots : root Rmap.t ; + mutable froms : region from list Rmap.t ; + mutable mranks : Ranks.t Rmap.t ; (* set of sizeof(ds) accessed by shifting *) + mutable mdims : int list Rmap.t ; (* common dim prefix accessed from cluster *) + mutable domain : Rset.t ; (* reachable regions via clusters *) + mutable chunk : region chunk Rmap.t ; (* memory chunks *) +} + +let create () = { + rid = 0 ; + return = (-1) ; + cache = Offset.cache () ; + vars = Vmap.empty ; + strings = Rmap.empty ; + index = Smap.empty ; + region = Rmap.empty ; + aliasing = Rmap.empty ; + queue = Queue.create () ; + cluster = Rmap.empty ; + roots = Rmap.empty ; + froms = Rmap.empty ; + mranks = Rmap.empty ; + mdims = Rmap.empty ; + domain = Rset.empty ; + chunk = Rmap.empty ; +} + +let noid = 0 +let is_empty map = (map.rid = 0) + +let fresh map = + let id = map.rid in + map.rid <- succ id ; + let region = { + id ; + garbled = false ; + rw = RW.default () ; + flat = Flat.default () ; + pack = Pack.default () ; + names = [] ; + alias = NotUsed ; + delta = Dmap.empty ; + deref = Dset.empty ; + read = Acs.empty ; + written = Acs.empty ; + shifted = Acs.empty ; + copiedTo = Rset.empty ; + pointsTo = None ; + } in + map.region <- Rmap.add id region map.region ; + region -type path = offset list -and offset = - | Oindex of term - | Ofield of field +(* -------------------------------------------------------------------------- *) +(* --- Datatype --- *) +(* -------------------------------------------------------------------------- *) -let rec access e = function - | [] -> e - | Oindex k :: path -> access (e_get e k) path - | Ofield f :: path -> access (e_getfield e f) path +module R = +struct + type t = region + let id a = a.id + let equal a b = (a.id = b.id) + let compare a b = Pervasives.compare a.id b.id + let pp_rid fmt id = Format.fprintf fmt "R%03d" id + let pretty fmt r = pp_rid fmt r.id +end -let rec update e path v = - match path with - | [] -> v - | Oindex k :: tail -> - let e_k = update (e_get e k) tail v in - e_set e k e_k - | Ofield f :: tail -> - let e_f = update (e_getfield e f) tail v in - e_setfield e f e_f +module Map = Qed.Idxmap.Make(R) +module Set = Qed.Idxset.Make(R) (* -------------------------------------------------------------------------- *) -(* --- Region --- *) +(* --- Union Find --- *) (* -------------------------------------------------------------------------- *) -type rpath = roffset list -and roffset = - | Rindex of set - | Rfield of field +let rec aliasing map i = + try + let j = aliasing map (Rmap.find i map.aliasing) in + if j <> i then map.aliasing <- Rmap.add i j map.aliasing ; j + with Not_found -> i + +let linkto map i k = + if i <> k then + begin + map.aliasing <- Rmap.add i k map.aliasing ; + Queue.add i map.queue ; + end + +let region map r = + try Rmap.find (aliasing map r) map.region + with Not_found -> failwith "Wp.Region: Undefined Region" + +let join_classes map i j = + let k = min i j in (linkto map i k ; linkto map j k ; k) + +let join_id map i j = + let i = aliasing map i in + let j = aliasing map j in + if i = j then i else join_classes map i j + +let join_region map ra rb = + let i = aliasing map ra.id in + let j = aliasing map rb.id in + let k = join_classes map i j in + if k = i then ra else + if k = j then rb else + (* defensive *) region map k -type region = - | Empty - | Full - | Fields of (field * region) list (* SORTED, DEFAULT : empty *) - | Indices of set * ( set * region ) list - (* Indices for FULL region. - Then indices for non-FULL and non-EMPTY regions *) +(* -------------------------------------------------------------------------- *) +(* --- Aliasing --- *) +(* -------------------------------------------------------------------------- *) -let empty = Empty -let full = Full +let alias map a b = + let k = join_id map a.id b.id in + let r = region map k in + r.alias <- Aliased ; r -let rec path = function - | [] -> Full - | Oindex k :: tail -> - let r = path tail in - let s = Vset.singleton k in - begin - match r with (* never Empty *) - | Full -> Indices(s,[]) - | _ -> Indices(Vset.empty,[s,r]) - end - | Ofield f :: tail -> - Fields [f,path tail] +let do_alias map a b = ignore (alias map a b) + +let add_alias map ~into:a b = + let i = aliasing map a.id in + let j = aliasing map b.id in + let wa = (region map i).alias in + let wb = (region map j).alias in + let k = join_classes map i j in + (* Aliasing has changed *) + (region map k).alias <- Alias.alias wa (Alias.use wb) + +let get_merged map r = + let i = aliasing map r.id in + if i <> r.id then Some (region map i) else None + +let get_alias map r = + let i = aliasing map r.id in + if i <> r.id then region map i else r + +let eq_alias map a b = (aliasing map a.id = aliasing map b.id) + +(* -------------------------------------------------------------------------- *) +(* --- General Iterator --- *) +(* -------------------------------------------------------------------------- *) + +let once mark r = + if Rset.mem r.id !mark then false + else ( mark := Rset.add r.id !mark ; true ) + +let iter map f = + let do_once marks f r = if once marks r then f r else () in + Rmap.iter (do_once (ref Rset.empty) f) map.region + +(* -------------------------------------------------------------------------- *) +(* --- Region Accessor --- *) +(* -------------------------------------------------------------------------- *) + +let id reg = reg.id +let is_garbled reg = reg.garbled +let has_pointed reg = reg.pointsTo <> None +let has_deref reg = not (Dset.is_empty reg.deref) +let has_layout reg = not (Dmap.is_empty reg.delta) +let has_offset reg d = Dmap.mem d reg.delta +let iter_offset map f reg = + Dmap.iter (fun ofs r -> f ofs (region map r)) reg.delta + +let has_copies reg = not (Rset.is_empty reg.copiedTo) +let iter_copies map f reg = + Rset.iter (fun r -> f (region map r)) reg.copiedTo + +let add_offset map reg d = + try region map (Dmap.find d reg.delta) + with Not_found -> + let rd = fresh map in + reg.delta <- Dmap.add d rd.id reg.delta ; rd + +let add_pointed map reg = + match reg.pointsTo with + | Some k -> region map k + | None -> + let r = fresh map in + reg.pointsTo <- Some r.id ; r + +let get_addrof map reg = + let addr = fresh map in + addr.pointsTo <- Some reg.id ; addr + +let get_pointed map reg = + match reg.pointsTo with + | None -> None + | Some r -> Some (region map r) + +let get_offset map reg d = + try Some (region map (Dmap.find d reg.delta)) + with Not_found -> None + +let get_copies map reg = + List.map (region map) (Rset.elements reg.copiedTo) + +(* -------------------------------------------------------------------------- *) +(* --- Access --- *) +(* -------------------------------------------------------------------------- *) + +let acs_read rg lvalue = rg.read <- Acs.add lvalue rg.read +let acs_write rg lvalue = rg.written <- Acs.add lvalue rg.written +let acs_shift rg lvalue = rg.shifted <- Acs.add lvalue rg.shifted +let acs_deref rg deref = rg.deref <- Dset.add deref rg.deref +let acs_copy ~src ~tgt = + if tgt.id <> src.id then src.copiedTo <- Rset.add tgt.id src.copiedTo + +let iter_read f rg = Acs.iter f rg.read +let iter_write f rg = Acs.iter f rg.written +let iter_shift f rg = Acs.iter f rg.shifted +let iter_deref f rg = Dset.iter f rg.deref + +let is_read rg = not (Acs.is_empty rg.read) +let is_written rg = not (Acs.is_empty rg.written) +let is_shifted rg = not (Acs.is_empty rg.shifted) +let is_aliased rg = Alias.is_aliased rg.alias + +(* -------------------------------------------------------------------------- *) +(* --- Varinfo Index --- *) +(* -------------------------------------------------------------------------- *) + +let rvar map x r = + let reg = region map r in + if reg.id <> r then map.vars <- Vmap.add x reg.id map.vars ; reg + +let of_null map = fresh map (* A fresh region each time: polymorphic *) + +let of_cvar map x = + try rvar map x (Vmap.find x map.vars) + with Not_found -> + let reg = fresh map in + map.vars <- Vmap.add x reg.id map.vars ; reg + +let of_return map = + if map.return < 0 then + let reg = fresh map in + map.return <- reg.id ; reg + else + region map map.return + +let has_return map = 0 <= map.return + +let iter_vars map f = Vmap.iter (fun x r -> f x (rvar map x r)) map.vars + +(* -------------------------------------------------------------------------- *) +(* --- Field Info Index --- *) +(* -------------------------------------------------------------------------- *) + +let field_offset map fd = Offset.field_offset map.cache fd + +(* -------------------------------------------------------------------------- *) +(* --- String Literal Index --- *) +(* -------------------------------------------------------------------------- *) + +let of_cstring map ~eid ~cst = + try region map (fst @@ Rmap.find eid map.strings) + with Not_found -> + let reg = fresh map in + map.strings <- Rmap.add eid (reg.id,cst) map.strings ; reg + +let iter_strings map f = + Rmap.iter (fun (rid,cst) -> f (region map rid) cst) map.strings + +(* -------------------------------------------------------------------------- *) +(* --- Region Index --- *) +(* -------------------------------------------------------------------------- *) + +let rindex map a r = + let reg = region map r in + if reg.id <> r then map.index <- Smap.add a reg.id map.index ; reg + +let of_name map a = + try rindex map a (Smap.find a map.index) + with Not_found -> + let reg = fresh map in + reg.names <- [a] ; + map.index <- Smap.add a reg.id map.index ; reg -let rec rpath = function - | [] -> Full - | Rindex s :: tail -> - let r = rpath tail in +let of_class map = function + | None -> fresh map + | Some a -> of_name map a + +let has_names reg = not (Class.is_empty reg.names) +let iter_names map f = Smap.iter (fun a r -> f a (rindex map a r)) map.index + +(* -------------------------------------------------------------------------- *) +(* --- Fusion --- *) +(* -------------------------------------------------------------------------- *) + +let merge_pointed map u v = + match u,v with + | None , w | w , None -> w + | Some i , Some j -> Some (join_id map i j) + +let merge_delta map _d a b = join_id map a b + +let merge_region map ~id a b = + { + id ; + garbled = a.garbled || b.garbled ; + rw = RW.merge a.rw b.rw ; + flat = Flat.merge a.flat b.flat ; + pack = Pack.merge a.pack b.pack ; + alias = Alias.merge a.alias b.alias ; + names = Class.union a.names b.names ; + read = Acs.union a.read b.read ; + written = Acs.union a.written b.written ; + shifted = Acs.union a.shifted b.shifted ; + copiedTo = Rset.union a.copiedTo b.copiedTo ; + pointsTo = merge_pointed map a.pointsTo b.pointsTo ; + delta = Dmap.union (merge_delta map) a.delta b.delta ; + deref = Dset.union a.deref b.deref ; + } + +let fusion map = + while not (Queue.is_empty map.queue) do + let i = Queue.pop map.queue in + let j = aliasing map i in + if i <> j then begin - match r with (* never Empty *) - | Full -> Indices(s,[]) - | _ -> Indices(Vset.empty,[s,r]) + if not (Wp.Region_fixpoint.get ()) then + Wp.debug "Region %a -> %a" R.pp_rid i R.pp_rid j ; + let a = try Rmap.find i map.region with Not_found -> assert false in + let b = try Rmap.find j map.region with Not_found -> assert false in + assert (i = a.id) ; + assert (j = b.id ) ; + let c = merge_region map ~id:j a b in + map.region <- Rmap.add j c (Rmap.remove i map.region) ; end - | Rfield f :: tail -> - Fields [f,rpath tail] - -let rec merge a b = - match a , b with - | Full , _ | _ , Full -> Full - | Empty , c | c , Empty -> c - | Fields fxs , Fields gys -> Fields (merge_fields fxs gys) - | Indices(s1,kxs) , Indices(s2,kys) -> - Indices(Vset.union s1 s2,kxs @ kys) - | Fields _ , Indices _ - | Indices _ , Fields _ -> assert false - -and merge_fields fxs gys = - match fxs , gys with - | [] , w | w , [] -> w - | (f,x)::fxstail , (g,y)::gystail -> - let c = Field.compare f g in - if c < 0 then (f,x)::merge_fields fxstail gys else - if c > 0 then (g,y)::merge_fields fxs gystail else - (f,merge x y) :: merge_fields fxstail gystail - -(* -------------------------------------------------------------------------- *) -(* --- Disjunction --- *) -(* -------------------------------------------------------------------------- *) - -let rec disjoint a b = - match a , b with - | Empty , _ | _ , Empty -> p_true - | Full , _ | _ , Full -> p_false - - | Fields fxs , Fields gys -> - p_conj (disjoint_fields fxs gys) - - | Indices(s,xs) , Indices(t,ts) -> - p_conj (disjoint_indices [Vset.disjoint s t] xs ts) - - | Fields _ , Indices _ - | Indices _ , Fields _ -> assert false - -and disjoint_fields frs grs = - match frs , grs with - | [] , _ | _ , [] -> [] - | (f,r)::ftail , (g,s)::gtail -> - let c = Field.compare f g in - if c < 0 then disjoint_fields ftail grs else - if c > 0 then disjoint_fields frs gtail else - disjoint r s :: disjoint_fields ftail gtail - -and disjoint_indices w sr1 sr2 = - List.fold_left - (fun w (s1,r1) -> - List.fold_left - (fun w (s2,r2) -> - (p_or (Vset.disjoint s1 s2) (disjoint r1 r2)) :: w - ) w sr2 - ) w sr1 - -(* -------------------------------------------------------------------------- *) -(* --- Region Inclusion --- *) -(* -------------------------------------------------------------------------- *) - -let rec subset r1 r2 = - match r1 , r2 with - | _ , Full -> p_true - | Empty , _ -> p_true - | _ , Empty -> p_false - | Full , _ -> p_false - | Fields frs , Fields grs -> subset_fields frs grs - | Indices(s1,ks1) , Indices(s2,ks2) -> - p_and - (Vset.subset s1 s2) (* because FULL never appears in ks2 *) - (p_all (fun (s1,r1) -> subset_indices s1 r1 ks2) ks1) - | Fields _ , Indices _ - | Indices _ , Fields _ -> assert false - -and subset_fields frs grs = - match frs , grs with - | [] , _ -> p_true - | _ , [] -> p_false - | (f,r)::ftail , (g,s)::gtail -> - let c = Field.compare f g in - if c < 0 then p_false (* only f is present *) else - if c > 0 then subset_fields frs gtail (* g is not present *) - else (* f=g *) - p_and (subset r s) (subset_fields ftail gtail) - -(* All path (k,p) in (s1,r1) are in ks2 - = AND (k in s1 -> p in r1 -> (k,p) in ks2 - = AND (k in s1 -> p in r1 -> (OR (k in s2 and p in r2) for (s2,r2) in r2) - = AND (k in s1 -> OR (k in s2 and r1 in r2) for (s2,r2) in r2) - = AND (k in s1 -> subset_index k r1 ks2) -*) -and subset_indices s1 r1 ks2 = - p_all (fun w -> - let xs,e,p = Vset.descr w in - p_forall xs - (p_imply p (subset_index e r1 ks2)) - ) s1 - -(* OR (k in s2 and r1 in r2) for (s2,r2) in r2) *) -and subset_index e r1 ks2 = - p_any (fun (s2,r2) -> - p_and (Vset.member e s2) (subset r1 r2) - ) ks2 - -(* -------------------------------------------------------------------------- *) -(* --- Equality outside a Region --- *) -(* -------------------------------------------------------------------------- *) - -let rec equal_but t r a b = - match t , r with - | _ , Full -> p_true - | _ , Empty -> p_equal a b - | _ , Fields grs -> - let fs = List.sort Field.compare (fields_of_tau t) in - p_conj (equal_but_fields a b fs grs) - | Array(ta,tb) , Indices(s,krs) -> - let x = freshvar ta in - let k = e_var x in - let a_k = e_get a k in - let b_k = e_get b k in - p_forall [x] (p_conj (equal_but_index tb k a_k b_k s krs)) - | _ -> assert false - -and equal_but_fields a b fts grs = - match fts , grs with - | [] , _ -> [] - | _ , [] -> - List.map (fun f -> p_equal (e_getfield a f) (e_getfield b f)) fts - | f::ftail , (g,r)::gtail -> - let c = Field.compare f g in - if c < 0 then - let eqf = p_equal (e_getfield a f) (e_getfield b f) in - eqf :: equal_but_fields a b ftail grs - else - if c > 0 then - (* field g does not appear *) - equal_but_fields a b fts gtail - else - let tf = tau_of_field f in - let eqf = equal_but tf r (e_getfield a f) (e_getfield b f) in - eqf :: equal_but_fields a b ftail gtail - -and equal_but_index tb k a_k b_k s krs = - List.map - (fun (s,r) -> p_or (Vset.member k s) (equal_but tb r a_k b_k)) - ((s,Full)::krs) - -(* -------------------------------------------------------------------------- *) -(* --- Utils --- *) -(* -------------------------------------------------------------------------- *) - -let rec occurs x = function - | Empty | Full -> false - | Fields frs -> List.exists (fun (_,r) -> occurs x r) frs - | Indices(s,srs) -> Vset.occurs x s || List.exists (occurs_idx x) srs - -and occurs_idx x (s,r) = Vset.occurs x s || occurs x r - -let rec vars = function - | Empty | Full -> Vars.empty - | Fields frs -> - List.fold_left - (fun xs (_,r) -> Vars.union xs (vars r)) - Vars.empty frs - | Indices(s,srs) -> - List.fold_left - (fun xs (s,r) -> Vars.union xs (Vars.union (Vset.vars s) (vars r))) - (Vset.vars s) srs - -(* -------------------------------------------------------------------------- *) -(* --- Pretty --- *) -(* -------------------------------------------------------------------------- *) - -let pretty fmt = function - | Empty -> Format.fprintf fmt "empty" - | Full -> Format.fprintf fmt "full" - | Fields _ -> Format.fprintf fmt "fields" (*TODO*) - | Indices _ -> Format.fprintf fmt "indices" (*TODO*) + done + +let fusionned map = not (Queue.is_empty map.queue) +let iter_fusion map f = Queue.iter (fun i -> f i (region map i)) map.queue + +(* -------------------------------------------------------------------------- *) +(* --- Garbling --- *) +(* -------------------------------------------------------------------------- *) + +let rec garblify map reg = + if not reg.garbled then + begin + reg.garbled <- true ; + Dmap.iter + (fun _delta r -> + garblify map (region map r) ; + ignore (join_id map reg.id r) ; + ) reg.delta ; + reg.delta <- Dmap.empty ; + end + +(* -------------------------------------------------------------------------- *) +(* --- Clustering --- *) +(* -------------------------------------------------------------------------- *) + +let cluster map reg = + try Rmap.find reg.id map.cluster + with Not_found -> Layout.Empty + +module Cluster = +struct + open Layout + + let rec from_region map reg = + try Rmap.find reg.id map.cluster + with Not_found -> + if reg.garbled then Garbled else + if not (Wp.Region_cluster.get ()) then Empty else + begin + map.cluster <- Rmap.add reg.id Empty map.cluster ; + let mu ~raw ra rb = + if raw then + begin + garblify map ra ; + garblify map rb ; + end ; + join_region map ra rb + in + let cluster = + if has_layout reg then + Cluster.reshape ~eq:R.equal ~flat:reg.flat ~pack:reg.pack @@ + from_layout map mu reg + else + from_deref map mu reg + in + if cluster = Garbled then garblify map reg ; + map.cluster <- Rmap.add reg.id cluster map.cluster ; + cluster + end + + and from_deref map mu reg = + let pointed = lazy (add_pointed map reg) in + List.fold_left + (fun chunk deref -> + Cluster.merge R.pretty mu chunk (Cluster.deref ~pointed deref) + ) Empty reg.deref + + and from_layout map mu reg = + Dmap.fold + (fun offset tgt acc -> + let layout = shift map offset (region map tgt) in + Cluster.merge R.pretty mu (Layout layout) acc + ) reg.delta Empty + + and shift map offset target = + let inline = Wp.Region_inline.get () || not (is_aliased target) in + let cluster = from_region map target in + Cluster.shift map.cache R.pretty offset target ~inline cluster + + let compute map reg = + begin + if has_layout reg && has_deref reg then + begin + Dset.iter + (fun deref -> + let target = add_offset map reg (Index(snd deref,1)) in + target.read <- Acs.union reg.read target.read ; + target.written <- Acs.union reg.written target.written ; + acs_deref target deref + ) reg.deref ; + reg.deref <- Dset.empty ; + reg.read <- Acs.empty ; + reg.written <- Acs.empty ; + Queue.add reg.id map.queue ; + end ; + ignore (from_region map reg) ; + end + +end + +(* -------------------------------------------------------------------------- *) +(* --- Froms Analysis --- *) +(* -------------------------------------------------------------------------- *) + +let get_froms map reg = + try Rmap.find reg.id map.froms + with Not_found -> [] + +let add_from map ~from ~target = + let rs = get_froms map target in + map.froms <- Rmap.add target.id (from :: rs) map.froms + +module Froms = +struct + open Layout + + let rec forward map marks ~source ~from ~target = + map.domain <- Rset.add source.id map.domain ; + add_from map ~from ~target ; + if once marks target then add_region map marks target + + and add_region map marks reg = + begin + add_points_to map marks ~source:reg reg.pointsTo ; + add_cluster map marks ~source:reg (cluster map reg) ; + end + + and add_points_to map marks ~source = function + | None -> () + | Some p -> add_deref map marks ~source ~target:(region map p) + + and add_deref map marks ~source ~target = + let from = if is_shifted target then Farray source else Fderef source in + forward map marks ~source ~from ~target + + and add_cluster map marks ~source = function + | Empty | Garbled | Chunk (Int _ | Float _) -> () + | Chunk (Pointer target) -> add_deref map marks ~source ~target + | Layout { layout } -> List.iter (add_range map marks ~source) layout + + and add_range map marks ~source = function + | { ofs ; reg = target ; dim = Dim(_,[]) } -> + forward map marks ~source ~from:(Ffield(source,ofs)) ~target + | { reg = target } -> + forward map marks ~source ~from:(Findex source) ~target + +end + +(* -------------------------------------------------------------------------- *) +(* --- Roots Analysis --- *) +(* -------------------------------------------------------------------------- *) + +let get_roots map reg = + try Rmap.find reg.id map.roots + with Not_found -> Rnone + +let has_roots map reg = get_roots map reg <> Rnone + +module Roots = +struct + + let rec of_region map region = + try Rmap.find region.id map.roots + with Not_found -> + let froms = get_froms map region in + let roots = + List.fold_left + (fun roots from -> + Root.merge roots (Root.from ~root:(of_region map) from) + ) Rnone froms + in map.roots <- Rmap.add region.id roots map.roots ; roots + + let compute map reg = ignore (of_region map reg) + +end + +(* -------------------------------------------------------------------------- *) +(* --- Forward & Backward Propagation --- *) +(* -------------------------------------------------------------------------- *) + +let forward map = + begin + let marks = ref Rset.empty in + map.domain <- Rset.empty ; + Vmap.iter + (fun x r -> + let reg = region map r in + let open Cil_types in + if x.vglob || x.vformal then + add_from map ~from:(Fvar x) ~target:(region map r) ; + Froms.add_region map marks reg ; + ) map.vars ; + end + +let backward map = + begin + Rmap.iter (Roots.compute map) map.region ; + end + +(* -------------------------------------------------------------------------- *) +(* --- Chunk Analysis --- *) +(* -------------------------------------------------------------------------- *) + +let rec chunk map region = + try Rmap.find region.id map.chunk + with Not_found -> + let roots = get_roots map region in + let chunk = + match cluster map region with + | Empty | Garbled -> Mraw (roots,get_pointed map region) + | Chunk v -> + if is_read region || is_written region then + Mmem(roots,v) + else + begin match v with + | Pointer r -> Mref r + | _ -> Mraw (roots,get_pointed map region) + end + | Layout { layout } -> + let chunks = Chunk.union_map (fun { reg } -> chunks map reg) layout + in Mcomp(chunks,layout) + + in map.chunk <- Rmap.add region.id chunk map.chunk ; chunk + +and chunks map region = + match chunk map region with + | Mcomp(rs,_) -> rs + | _ -> Chunk.singleton region.id + +(* -------------------------------------------------------------------------- *) +(* --- Fixpoint --- *) +(* -------------------------------------------------------------------------- *) + +let fixpoint map = + begin + let turn = ref 0 in + let loop = ref true in + while !loop do + incr turn ; + Wp.feedback ~ontty:`Transient "Region clustering (loop #%d)" !turn ; + fusion map ; + map.cluster <- Rmap.empty ; + iter map (Cluster.compute map) ; + loop := fusionned map ; + done ; + Wp.feedback ~ontty:`Transient "Region forward analysis" ; + forward map ; + Wp.feedback ~ontty:`Transient "Region backward analysis" ; + backward map ; + Wp.feedback ~ontty:`Transient "Region fixpoint reached" ; + end + +(* -------------------------------------------------------------------------- *) diff --git a/src/plugins/wp/Region.mli b/src/plugins/wp/Region.mli index f7a5eba2289224f8072eb1b563eae5d56859b1c3..98c01f12825ac7bbf87f351dcbb17416877f7971 100644 --- a/src/plugins/wp/Region.mli +++ b/src/plugins/wp/Region.mli @@ -20,43 +20,86 @@ (* *) (**************************************************************************) -(* -------------------------------------------------------------------------- *) -(* --- Logic Path and Regions --- *) -(* -------------------------------------------------------------------------- *) +open Cil_types +open Layout -open Lang -open Lang.F -open Vset +type region +type map -(** {2 Paths} *) +module R : Layout.Data with type t = region +module Map : Qed.Idxmap.S with type key = region +module Set : Qed.Idxset.S with type elt = region -type path = offset list -and offset = - | Oindex of term - | Ofield of field +val create : unit -> map +val is_empty : map -> bool +val iter : map -> (region -> unit) -> unit -val access : term -> path -> term -val update : term -> path -> term -> term +val id: region -> int +val noid: int -(** {2 Regions} *) +val get_addrof : map -> region -> region +val add_pointed : map -> region -> region +val add_offset : map -> region -> offset -> region +val field_offset : map -> fieldinfo -> int * int -type rpath = roffset list -and roffset = - | Rindex of set - | Rfield of field +val get_froms : map -> region -> region from list +val get_roots : map -> region -> root +val has_roots : map -> region -> bool -type region +val is_garbled : region -> bool +val has_pointed : region -> bool +val has_layout : region -> bool +val has_offset : region -> offset -> bool +val has_copies : region -> bool +val has_deref : region -> bool +val has_names : region -> bool +val has_return : map -> bool + +val get_pointed : map -> region -> region option +val get_offset : map -> region -> offset -> region option +val get_copies : map -> region -> region list +val get_alias : map -> region -> region +val get_merged : map -> region -> region option +val eq_alias : map -> region -> region -> bool + +val acs_read : region -> lvalue -> unit +val acs_write : region -> lvalue -> unit +val acs_shift : region -> lvalue -> unit +val acs_deref : region -> deref -> unit +val acs_copy : src:region -> tgt:region -> unit + +val is_read : region -> bool +val is_written : region -> bool +val is_shifted : region -> bool +val is_aliased : region -> bool + +val iter_read : (lvalue -> unit) -> region -> unit +val iter_write : (lvalue -> unit) -> region -> unit +val iter_shift : (lvalue -> unit) -> region -> unit +val iter_deref : (deref -> unit) -> region -> unit +val iter_offset : map -> (offset -> region -> unit) -> region -> unit +val iter_copies : map -> (region -> unit) -> region -> unit +val iter_vars : map -> (varinfo -> region -> unit) -> unit +val iter_names : map -> (string -> region -> unit) -> unit +val iter_strings : map -> (region -> string -> unit) -> unit + +val of_null : map -> region +val of_return : map -> region +val of_cvar : map -> varinfo -> region +val of_cstring : map -> eid:int -> cst:string -> region +val of_name : map -> string -> region +val of_class : map -> string option -> region -val empty : region -val full : region -val path : path -> region (** Empty, but Full for the path *) -val rpath : rpath -> region (** Empty, but Full for the r-paths *) -val merge : region -> region -> region +val region : map -> int -> region +val cluster : map -> region -> region cluster +val chunk : map -> region -> region chunk +val chunks : map -> region -> chunks -val disjoint : region -> region -> pred -val subset : region -> region -> pred -val equal_but : tau -> region -> term -> term -> pred +val alias : map -> region -> region -> region +val do_alias : map -> region -> region -> unit +val add_alias : map -> into:region -> region -> unit -val vars : region -> Vars.t -val occurs : var -> region -> bool -val pretty : Format.formatter -> region -> unit +val fusion : map -> unit +val fusionned : map -> bool +val iter_fusion : map -> (int -> region -> unit) -> unit +val fixpoint : map -> unit diff --git a/src/plugins/wp/RegionAccess.ml b/src/plugins/wp/RegionAccess.ml new file mode 100644 index 0000000000000000000000000000000000000000..591b77b53d291436a440b5a85ba37fca895cad77 --- /dev/null +++ b/src/plugins/wp/RegionAccess.ml @@ -0,0 +1,455 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2019 *) +(* CEA (Commissariat a l'energie atomique et aux energies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types +open Layout +open Region + +(* -------------------------------------------------------------------------- *) +(* --- Location Compiler --- *) +(* -------------------------------------------------------------------------- *) + +type addr = { + addrof : Region.region ; + typeOfPointed : typ ; + shift : bool ; +} + +type value = + | Pure + | Read_at of typ * region + | Addr_of of addr + +[@@@ warning "-32"] +let pp_value fmt = function + | Pure -> Format.pp_print_string fmt "scalar" + | Read_at(_,r) -> Format.fprintf fmt "read %a" R.pretty r + | Addr_of a -> + if a.shift then + Format.fprintf fmt "addr %a+" R.pretty a.addrof + else + Format.fprintf fmt "addr %a" R.pretty a.addrof +[@@@ warning "+32"] + +(* -------------------------------------------------------------------------- *) +(* --- Strings --- *) +(* -------------------------------------------------------------------------- *) + +let cc_string map exp = + let cst = Pretty_utils.to_string Cil_datatype.Exp.pretty exp in + let addrof = Region.of_cstring map ~eid:exp.eid ~cst in + { addrof ; typeOfPointed = Cil.charType ; shift=false } + +(* -------------------------------------------------------------------------- *) +(* --- Reading Values --- *) +(* -------------------------------------------------------------------------- *) + +let read acs = function + | Pure -> () + | Addr_of _ -> () + | Read_at(tr,r) -> + acs_deref r (Value,tr) ; + acs_read r acs + +let points_to = function { shift ; addrof = pointed ; typeOfPointed = typ } -> + acs_deref pointed ((if shift then Array else Deref),typ) + +let addrof map = function + | Pure -> failwith "Wp.Region: physical address" + | Read_at(tr,r) -> + acs_deref r (Value,tr) ; + { + addrof = add_pointed map r ; + typeOfPointed = Cil.typeOf_pointed tr ; + shift = false ; + } + | Addr_of addr -> addr + +let cast ty value = + if Cil.isPointerType ty then + match value with + | Addr_of addr -> + Addr_of { addr with typeOfPointed = Cil.typeOf_pointed ty } + | Read_at (_,r) -> Read_at(ty,r) + | Pure -> Pure + else + value + +let is_pointer_value = function + | Pure -> false + | Addr_of _ -> true + | Read_at(tr,_) -> Cil.isPointerType tr + +let merge_type t t' = + if Cil.isVoidType t then t' else + if Cil.isVoidType t' then t else + if Cil_datatype.Typ.equal t t' then t + else failwith "Wp.Region: merge incompatible pointer types" + +let merge_addrof (map:map) v1 v2 = + if not (is_pointer_value v1) then v2 else + if not (is_pointer_value v2) then v1 else + let a1 = addrof map v1 in + let a2 = addrof map v2 in + let typeOfPointed = merge_type a1.typeOfPointed a2.typeOfPointed in + let addrof = Region.alias map a1.addrof a2.addrof in + let shift = a1.shift || a2.shift in + Addr_of { addrof ; typeOfPointed ; shift } + +(* -------------------------------------------------------------------------- *) +(* --- Expressions & L-values --- *) +(* -------------------------------------------------------------------------- *) + +let rec cc_exp (map:map) exp = + match exp.enode with + | BinOp( (PlusPI | IndexPI | MinusPI) , a , b , _ ) -> + cc_read map b ; + let { addrof = pointed } as addr = cc_addr map a in + acs_shift pointed (Eval exp) ; + Addr_of { addr with shift = true } + | AddrOf lv | StartOf lv -> + Addr_of { + addrof = cc_lval map lv ; + typeOfPointed = Cil.typeOfLval lv ; + shift = false ; + } + | Lval lv -> Read_at (Cil.typeOfLval lv , cc_lval map lv) + | CastE(ty,e) -> cast ty (cc_exp map e) + | Info(e,_) -> cc_exp map e + | Const (CStr _ | CWStr _) -> Addr_of (cc_string map exp) + | Const (CInt64 _ | CChr _ | CEnum _ | CReal _) + | SizeOf _ | SizeOfE _ | SizeOfStr _ + | AlignOf _ | AlignOfE _ -> Pure + | UnOp(_,e,ty) -> + assert (not (Cil.isPointerType ty)) ; + cc_read map e ; Pure + | BinOp(_,a,b,ty) -> + assert (not (Cil.isPointerType ty)) ; + cc_read map a ; cc_read map b ; Pure + +and cc_host map = function + | Var x -> of_cvar map x , x.vtype + | Mem e -> + let a = cc_addr map e in + points_to a ; (* deref, not read !*) + a.addrof , a.typeOfPointed + +and cc_lval map (host , offset) = + let r,ty = cc_host map host in cc_offset map r ty offset + +and cc_offset map r ty = function + | Cil_types.NoOffset -> r + | Cil_types.Field(fd,ofs) -> + let df = Offset.field fd in + cc_offset map (add_offset map r df) fd.ftype ofs + | Cil_types.Index(e,ofs) -> + cc_read map e ; + let de = Offset.index ty in + let te = Offset.typeof de in + cc_offset map (add_offset map r de) te ofs + +and cc_addr map a = addrof map (cc_exp map a) + +and cc_read map e = read (Eval e) (cc_exp map e) + +and cc_comp map e = + match cc_exp map e with + | Pure | Addr_of _ -> failwith "Wp.Region: comp expected" + | Read_at(_,r) -> r + +let cc_writes map stmt tgt typ e = + acs_deref tgt (Value,typ) ; + acs_write tgt (Assigned stmt) ; + match Cil.unrollType typ with + | TPtr _ -> + let a = cc_addr map e in + points_to a ; (* deref, not read! *) + do_alias map a.addrof (add_pointed map tgt) + | TComp _ -> + let src = cc_comp map e in + acs_copy ~src ~tgt + | _ -> + cc_read map e + +let cc_assign map stmt lv e = + cc_writes map stmt (cc_lval map lv) (Cil.typeOfLval lv) e + +let cc_return map stmt e = + cc_writes map stmt (Region.of_return map) (Cil.typeOf e) e + +(* -------------------------------------------------------------------------- *) +(* --- Stmt & Instructions --- *) +(* -------------------------------------------------------------------------- *) + +let rec cc_init map stmt lv = function + | SingleInit e -> cc_assign map stmt lv e + | CompoundInit(_,content) -> + List.iter + (fun (ofs,vi) -> + cc_init map stmt (Cil.addOffsetLval ofs lv) vi + ) content + +let cc_local_init map stmt x = function + | AssignInit vi -> cc_init map stmt (Var x,NoOffset) vi + | ConsInit _ -> failwith "Wp.Region: cons-init not implemented" + +let cc_instr map stmt = function + | Set(lv,e,_) -> cc_assign map stmt lv e + | Call _ -> failwith "Wp.Region: call not implemented" + | Local_init(x,vi,_) -> cc_local_init map stmt x vi + | Asm _ | Skip _ | Code_annot _ -> () + +let cc_skind map stmt = + match stmt.skind with + | Instr instr -> cc_instr map stmt instr + | Return(Some ve,_) -> cc_return map stmt ve + | If(e,_,_,_) -> cc_read map e + | Switch(e,_,_,_) -> cc_read map e + + | Return(None,_) | Goto _ | Break _ | Continue _ | Loop _ + | Block _ | UnspecifiedSequence _ + | Throw _ | TryCatch _ | TryFinally _ | TryExcept _ -> () + +(* -------------------------------------------------------------------------- *) +(* --- ACSL Terms --- *) +(* -------------------------------------------------------------------------- *) + +let rec cc_term map t = read (Tval t) (cc_term_value map t) + +and cc_term_value (map:map) (term:term) = + match term.term_node with + | TLval lv -> + begin match cc_term_lval map lv with + | None -> Pure + | Some(ty,reg) -> Read_at(ty,reg) + end + | TAddrOf lv | TStartOf lv -> + begin match cc_term_lval map lv with + | None -> failwith "Wp.Region: pure term-value" + | Some(ty,reg) -> Addr_of { + addrof = reg ; + typeOfPointed = ty ; + shift = false ; + } + end + | TBinOp( (PlusPI | IndexPI | MinusPI) , a , b ) -> + begin + cc_term map b ; + let { addrof = pointed } as addr = cc_term_addr map a in + acs_shift pointed (Tval term) ; + Addr_of { addr with shift = true } + end + + | Tnull -> + Addr_of { + addrof = Region.of_null map ; + typeOfPointed = Cil.charType ; + shift = false ; + } + + | TUnOp(_,a) -> cc_term map a ; Pure + | TBinOp(_,a,b) -> cc_term map a ; cc_term map b ; Pure + + | Tat(t,_) -> cc_term_value map t + + | TCastE(ty,t) -> cast ty @@ cc_term_value map t + | TLogic_coerce (Ctype ty,t) -> cast ty @@ cc_term_value map t + | TLogic_coerce (_,t) -> cc_term_value map t + + | TConst _ + | TSizeOf _ | TSizeOfE _ | TSizeOfStr _ + | TAlignOf _ | TAlignOfE _ | Ttype _ | Ttypeof _ + -> Pure + + | TDataCons(_,ts) -> List.iter (cc_term map) ts ; Pure + | TUpdate(w,ofs,v) -> + cc_term map w ; + cc_term map v ; + cc_term_offset_read map ofs ; + Pure + + | Tbase_addr(_at,t) -> cast Cil.voidPtrType @@ cc_term_value map t + | Tblock_length(_at,t) | Toffset(_at,t) -> cc_term map t ; Pure + + | Tif(c,a,b) -> + cc_term map c ; + merge_addrof map (cc_term_value map a) (cc_term_value map b) + + | Tempty_set -> Pure + | Tunion ts | Tinter ts -> + List.fold_left + (fun v t -> merge_addrof map v (cc_term_value map t)) Pure ts + + | Tcomprehension(t,_,None) -> cc_term_value map t + | Tcomprehension(t,_,Some p) -> cc_pred map p ; cc_term_value map t + | Trange(a,b) -> cc_term_option map a ; cc_term_option map b ; Pure + + | Tlet _ | Tlambda _ | Tapp _ -> + failwith "Wp.Region: unsupported logic functions and bindings" + +and cc_term_lval map (lhost,loffset) = + match lhost with + | TResult typ -> Some(typ,of_return map) + | TVar lvar -> + begin + match lvar.lv_origin with + | Some x -> + let ty,rv = cc_term_offset map (of_cvar map x) x.vtype loffset in + Some(ty,rv) + | None -> + cc_term_offset_read map loffset ; + None + end + | TMem p -> + begin + let a = cc_term_addr map p in + points_to a ; + let ty,ra = cc_term_offset map a.addrof a.typeOfPointed loffset in + Some(ty,ra) + end + +and cc_term_offset map r ty = function + | TNoOffset -> ty,r + | TField(fd,ofs) -> + let df = Offset.field fd in + cc_term_offset map (add_offset map r df) fd.ftype ofs + | TIndex(t,ofs) -> + cc_term map t ; + let de = Offset.index ty in + let te = Offset.typeof de in + cc_term_offset map (add_offset map r de) te ofs + | TModel _ -> failwith "Wp.Region: model field" + +and cc_term_offset_read map = function + | TNoOffset -> () + | TField(_,ofs) -> cc_term_offset_read map ofs + | TModel(_,ofs) -> cc_term_offset_read map ofs + | TIndex(t,ofs) -> cc_term map t ; cc_term_offset_read map ofs + +and cc_term_addr map t = addrof map @@ cc_term_value map t + +and cc_term_option map = function None -> () | Some t -> cc_term map t + +(* -------------------------------------------------------------------------- *) +(* --- ACSL Predicates --- *) +(* -------------------------------------------------------------------------- *) + +and cc_pred (map:map) (p:predicate) = + match p.pred_content with + | Pfalse | Ptrue -> () + + | Prel(_,a,b) -> + cc_term map a ; cc_term map b + + | Pnot a -> cc_pred map a + | Pif(t,a,b) -> + cc_term map t ; cc_pred map a ; cc_pred map b + | Pand(a,b) | Por(a,b) | Pxor(a,b) | Pimplies(a,b) | Piff(a,b) -> + cc_pred map a ; cc_pred map b + + | Pforall(_,p) | Pexists(_,p) -> cc_pred map p + + | Pseparated ts -> List.iter (cc_term map) ts + | Pvalid(_,t) | Pvalid_read(_,t) | Pvalid_function t + | Pinitialized(_,t) | Pdangling(_,t) | Pallocable(_,t) + | Pfreeable(_,t) -> cc_term map t + | Pfresh(_,_,ptr,n) -> cc_term map ptr ; cc_term map n + + | Pat(p,_at) -> cc_pred map p + + | Plet _ | Papp _ -> + failwith "Wp.Region: unsupported logic predicates and bindings" + +(* -------------------------------------------------------------------------- *) +(* --- ACSL Spec & Defs --- *) +(* -------------------------------------------------------------------------- *) + +class visitor map = + object + inherit Visitor.frama_c_inplace as super + + method! vpredicate p = cc_pred map p ; Cil.SkipChildren + method! vterm t = cc_term map t ; Cil.SkipChildren + method! vstmt s = cc_skind map s ; super#vstmt s + (* vpredicate and vterm are called from vcode_annot *) + + (* speed up: skip non interesting subtrees *) + method! vloop_pragma _ = Cil.SkipChildren (* no need *) + method! vvdec _ = Cil.SkipChildren (* done via stmt *) + method! vexpr _ = Cil.SkipChildren (* done via stmt *) + method! vlval _ = Cil.SkipChildren (* done via stmt *) + method! vattr _ = Cil.SkipChildren (* done via stmt *) + method! vinst _ = Cil.SkipChildren (* done via stmt *) + end + +let cc_fundec map def = + let visitor = new visitor map in + ignore (Cil.visitCilFunction (visitor:>Cil.cilVisitor) def) + +let cc_spec map spec = + let visitor = new visitor map in + ignore (Cil.visitCilFunspec (visitor:>Cil.cilVisitor) spec) + +(* -------------------------------------------------------------------------- *) +(* --- L-path Iterator --- *) +(* -------------------------------------------------------------------------- *) + +open RegionAnnot + +let iter_star map f t r = + let pointed = add_pointed map r in + acs_deref pointed (Deref,t) ; f pointed + +let iter_shift map f t r = + let pointed = add_pointed map r in + acs_deref pointed (Array,t) ; f r + +let iter_index map f tarr r = + f (add_offset map r (Offset.index tarr)) + +let iter_fields map f fds r = + List.iter (fun fd -> f (add_offset map r (Offset.field fd))) fds + +let rec iter_lpath map f lv = + match lv.lnode with + | L_var x -> f (of_cvar map x) + | L_region a -> f (of_name map a) + | L_cast(_,a) -> iter_lpath map f a + | L_addr a -> iter_lpath map (fun r -> f (get_addrof map r)) a + | L_star(te,a) -> iter_lpath map (iter_star map f te) a + | L_shift(a,te,_) -> iter_lpath map (iter_shift map f te) a + | L_index(a,_,_) -> iter_lpath map (iter_index map f lv.ltype) a + | L_field(a,fs) -> iter_lpath map (iter_fields map f fs) a + +(* -------------------------------------------------------------------------- *) +(* --- Region Specs --- *) +(* -------------------------------------------------------------------------- *) + +let cc_lpath map rclass _rpattern lv = + iter_lpath map (Region.add_alias map ~into:rclass) lv + +let cc_region map spec = + let rclass = Region.of_class map spec.region_name in + let rpattern = spec.region_pattern in + List.iter (cc_lpath map rclass rpattern) spec.region_lpath + +(* -------------------------------------------------------------------------- *) diff --git a/src/plugins/wp/RegionAccess.mli b/src/plugins/wp/RegionAccess.mli new file mode 100644 index 0000000000000000000000000000000000000000..58f219332a3c52c4e9ea927c5d00c8b27a21963d --- /dev/null +++ b/src/plugins/wp/RegionAccess.mli @@ -0,0 +1,42 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2019 *) +(* CEA (Commissariat a l'energie atomique et aux energies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types +open Region + +(* -------------------------------------------------------------------------- *) + +val cc_lval : map -> lval -> region +val cc_read : map -> exp -> unit +val cc_assign : map -> stmt -> lval -> exp -> unit +val cc_init : map -> stmt -> lval -> init -> unit +val cc_instr : map -> stmt -> instr -> unit +val cc_fundec : map -> fundec -> unit + +val cc_pred : map -> predicate -> unit +val cc_term : map -> term -> unit +val cc_spec : map -> spec -> unit + +open RegionAnnot +val cc_region : map -> region_spec -> unit + +(* -------------------------------------------------------------------------- *) diff --git a/src/plugins/wp/RegionAnalysis.ml b/src/plugins/wp/RegionAnalysis.ml new file mode 100644 index 0000000000000000000000000000000000000000..a0679ed23c6e1ca88da3a29849da8c3ba782ffcd --- /dev/null +++ b/src/plugins/wp/RegionAnalysis.ml @@ -0,0 +1,110 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2019 *) +(* CEA (Commissariat a l'energie atomique et aux energies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types +module Wp = Wp_parameters +module Kf = Kernel_function + +(* ---------------------------------------------------------------------- *) +(* --- Compute Analysis --- *) +(* ---------------------------------------------------------------------- *) + +let compute kf = + let map = Region.create () in + if Kf.is_definition kf then + begin + Wp.feedback ~ontty:`Transient "[region] Analyzing %a" Kf.pretty kf ; + let def = Kf.get_definition kf in + RegionAccess.cc_fundec map def ; + let spec = Annotations.funspec kf in + RegionAccess.cc_spec map spec ; + List.iter + (fun bhv -> + let region_specs = RegionAnnot.of_behavior bhv in + if region_specs <> [] then + if Cil.is_default_behavior bhv then + List.iter (RegionAccess.cc_region map) region_specs + else + Wp.warning ~once:true + "Region specifications in non-default behaviours are skipped." + ) spec.spec_behavior ; + if Wp.Region_fixpoint.get () then Region.fixpoint map ; + end ; + map + +(* ---------------------------------------------------------------------- *) +(* --- Projectified Analysis Result --- *) +(* ---------------------------------------------------------------------- *) + +module REGION = Datatype.Make + (struct + type t = Region.map + include Datatype.Undefined + let reprs = [Region.create ()] + let name = "Wp.RegionAnalysis.region" + let mem_project = Datatype.never_any_project + end) + +module GLOBAL = State_builder.Ref + (REGION) + (struct + let name = "Wp.RegionAnalysis.ref" + let dependencies = [Ast.self] + let default = Region.create + end) + +module REGISTRY = State_builder.Hashtbl + (Kernel_function.Hashtbl) + (REGION) + (struct + let name = "Wp.RegionAnalysis.registry" + let dependencies = [Ast.self] + let size = 32 + end) + +let get = function + | None -> GLOBAL.get () + | Some kf -> + try REGISTRY.find kf + with Not_found -> + let map = compute kf in + REGISTRY.add kf map ; map + +(* ---------------------------------------------------------------------- *) +(* --- Command Line Registry --- *) +(* ---------------------------------------------------------------------- *) + +let main () = + if Wp.Region.get () then + begin + Ast.compute () ; + let dir = Wp.get_output_dir "region" in + Wp.iter_kf (fun kf -> + let map = get (Some kf) in + if not (Region.is_empty map) then + RegionDump.dump ~dir kf map + ) ; + end + +let () = Db.Main.extend main + +(* ---------------------------------------------------------------------- *) diff --git a/src/plugins/wp/RegionAnalysis.mli b/src/plugins/wp/RegionAnalysis.mli new file mode 100644 index 0000000000000000000000000000000000000000..396190e6283ef2974b4094483b890b3d455f19a8 --- /dev/null +++ b/src/plugins/wp/RegionAnalysis.mli @@ -0,0 +1,29 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2019 *) +(* CEA (Commissariat a l'energie atomique et aux energies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + + +(* -------------------------------------------------------------------------- *) + +(** Memoized and Projectified Region Analyzis for the given Function. *) +val get : Kernel_function.t option -> Region.map + +(* -------------------------------------------------------------------------- *) diff --git a/src/plugins/wp/RegionAnnot.ml b/src/plugins/wp/RegionAnnot.ml new file mode 100644 index 0000000000000000000000000000000000000000..5ada4f4dc9434380e19dfa9d69147f562c6ecb12 --- /dev/null +++ b/src/plugins/wp/RegionAnnot.ml @@ -0,0 +1,494 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2019 *) +(* CEA (Commissariat a l'energie atomique et aux energies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types +open Cil_datatype +open Logic_ptree + +module Wp = Wp_parameters + +(* -------------------------------------------------------------------------- *) +(* --- L-Path --- *) +(* -------------------------------------------------------------------------- *) + +type region_pattern = + | FREE + | PVAR + | PREF + | PMEM + | PVECTOR + | PMATRIX + +type lrange = + | R_index of term + | R_range of term option * term option + +type lpath = { + loc : location ; + lnode : lnode ; + ltype : typ ; +} +and lnode = + | L_var of varinfo + | L_region of string + | L_addr of lpath + | L_star of typ * lpath + | L_shift of lpath * typ * lrange + | L_index of lpath * typ * lrange + | L_field of lpath * fieldinfo list + | L_cast of typ * lpath + +type region_spec = { + region_name: string option ; + region_pattern: region_pattern ; + region_lpath: lpath list ; +} + +(* +let get_int e = + match Logic_utils.constFoldTermToInt e with + | None -> None + | Some a -> Some (Integer.to_int a) + +let get_int_option = function + | None -> None + | Some e -> get_int e +*) + +module Lpath = +struct + + type t = lpath + + let compare_bound a b = + match a,b with + | None , None -> 0 + | Some a , Some b -> Term.compare a b + | None , Some _ -> (-1) + | Some _ , None -> 1 + + let compare_range a b = + match a,b with + | R_index a , R_index b -> Term.compare a b + | R_index _ , _ -> (-1) + | _ , R_index _ -> 1 + | R_range(a1,b1) , R_range(a2,b2) -> + let cmp = compare_bound a1 a2 in + if cmp <> 0 then cmp else compare_bound b1 b2 + + let rec compare a b = + match a.lnode , b.lnode with + | L_var x , L_var y -> Varinfo.compare x y + | L_var _ , _ -> (-1) + | _ , L_var _ -> 1 + | L_region a , L_region b -> String.compare a b + | L_region _ , _ -> (-1) + | _ , L_region _ -> 1 + | L_star(ta,a) , L_star(tb,b) -> + let cmp = Typ.compare ta tb in + if cmp <> 0 then cmp else compare a b + | L_star _ , _ -> (-1) + | _ , L_star _ -> 1 + | L_addr a , L_addr b -> compare a b + | L_addr _ , _ -> (-1) + | _ , L_addr _ -> 1 + | L_shift(a,ta,i) , L_shift(b,tb,j) -> compare_index a ta i b tb j + | L_shift _ , _ -> (-1) + | _ , L_shift _ -> 1 + | L_index(a,ta,i) , L_index(b,tb,j) -> compare_index a ta i b tb j + | L_index _ , _ -> (-1) + | _ , L_index _ -> 1 + | L_field(a,fs) , L_field(b,gs) -> + let cmp = compare a b in + if cmp <> 0 then cmp + else Qed.Hcons.compare_list Fieldinfo.compare fs gs + | L_field _ , _ -> (-1) + | _ , L_field _ -> 1 + | L_cast(ta,a) , L_cast(tb,b) -> + let cmp = Typ.compare ta tb in + if cmp <> 0 then cmp else compare a b + + and compare_index a ta i b tb j = + let cmp = compare a b in + if cmp <> 0 then cmp else + let cmp = Typ.compare ta tb in + if cmp <> 0 then cmp else + compare_range i j + + let equal a b = (compare a b = 0) + + let pp_bound pp fmt = function None -> () | Some a -> pp fmt a + let pp_range pp fmt = function + | R_index a -> pp fmt a + | R_range(a,b) -> + begin + pp_bound pp fmt a ; + Format.fprintf fmt "@,.." ; + pp_bound pp fmt b ; + end + + let first = function [] -> assert false | f::_ -> f + let rec last = function [] -> assert false | [f] -> f | _::fs -> last fs + + let is_lval = function + | L_var _ | L_region _ | L_index _ | L_field _ -> true + | _ -> false + + let rec pp_lpath pp fmt a = match a.lnode with + | L_var x -> Varinfo.pretty fmt x + | L_region a -> Format.pp_print_string fmt a + | L_field( p , [f] ) -> pfield pp p f fmt + | L_field( p , fs ) -> + Format.fprintf fmt "@[<hov 2>(%t@,..%t)@]" + (pfield pp p (first fs)) (pfield pp p (last fs)) + | L_index(a,_,i) -> + Format.fprintf fmt "@[<hov 2>%a@,[%a]@]" + (pp_lval pp) a (pp_range pp) i + | L_shift(a,_,i) -> + Format.fprintf fmt "@[<hov 2>%a@,+(%a)@]" + (pp_lpath pp) a (pp_range pp) i + | L_star(_,a) -> Format.fprintf fmt "*%a" (pp_lval pp) a + | L_addr a -> Format.fprintf fmt "&%a" (pp_lval pp) a + | L_cast(t,a) -> Format.fprintf fmt "(%a)@,%a" Typ.pretty t (pp_lval pp) a + + and pfield pp a f fmt = + Format.fprintf fmt "@[<hov 2>%a%a@]" (panchor pp) a Fieldinfo.pretty f + + and panchor pp fmt a = + match a.lnode with + | L_star(_,p) -> Format.fprintf fmt "%a@,->" (pp_lval pp) p + | _ -> Format.fprintf fmt "%a@,." (pp_lval pp) a + + and pp_lval pp fmt a = + if is_lval a.lnode then pp_lpath pp fmt a + else Format.fprintf fmt "(%a)" (pp_lpath pp) a + + let pretty = pp_lpath Term.pretty + +end + +(* -------------------------------------------------------------------------- *) +(* --- Region Spec Printer --- *) +(* -------------------------------------------------------------------------- *) + +let patterns = [ + "PVAR" , PVAR ; + "PREF" , PREF ; + "PMEM" , PMEM ; + "PVECTOR" , PVECTOR ; + "PMATRIX" , PMATRIX ; +] + +let p_name p = fst (List.find (fun (_,q) -> q = p) patterns) + +let pp_pattern_spec fmt p = + try Format.fprintf fmt "\\pattern{%s}" (p_name p) ; true + with Not_found -> false + +let pp_path_spec pp fmt coma lv = + if coma then Format.fprintf fmt ",@ " ; + Lpath.pp_lpath pp fmt lv ; true + +let pp_region_spec pp fmt coma spec = + begin + if coma then Format.fprintf fmt ",@ " ; + Format.fprintf fmt "@[<hv 2>" ; + Extlib.may (Format.fprintf fmt "%s:@ ") spec.region_name ; + let coma = pp_pattern_spec fmt spec.region_pattern in + let coma = List.fold_left (pp_path_spec pp fmt) coma spec.region_lpath in + Format.fprintf fmt "@]" ; + coma + end + +(* -------------------------------------------------------------------------- *) +(* --- Typing Env --- *) +(* -------------------------------------------------------------------------- *) + +type env = { + context : Logic_typing.typing_context ; + mutable declared : string list ; + mutable name : string option ; + mutable pattern : region_pattern ; + mutable paths : lpath list ; + mutable specs : region_spec list ; +} + +let error env ~loc msg = env.context.Logic_typing.error loc msg + +let flush env = + let region_name = env.name in env.name <- None ; + let region_pattern = env.pattern in env.pattern <- FREE ; + let region_lpath = List.rev env.paths in env.paths <- [] ; + Extlib.may (fun a -> env.declared <- a::env.declared) region_name ; + if not (region_name = None && region_lpath = []) then + let region = { region_name ; region_pattern ; region_lpath } in + env.specs <- region :: env.specs + +(* -------------------------------------------------------------------------- *) +(* --- Type Utils --- *) +(* -------------------------------------------------------------------------- *) + +let isIndexType t = + match Logic_utils.unroll_type t with + | Ctype (TInt _) | Linteger -> true + | _ -> false + +let getCompoundType env ~loc typ = + match Cil.unrollType typ with + | TComp(comp,_,_) -> comp + | _ -> error env ~loc "Expected compound type for term" + +(* -------------------------------------------------------------------------- *) +(* --- Path Typechecking --- *) +(* -------------------------------------------------------------------------- *) + +let parse_varinfo env ~loc x = + try + match env.context.Logic_typing.find_var x with + | { lv_origin = Some v } -> v + | _ -> error env ~loc "Variable '%s' is not a C-variable" x + with Not_found -> + error env ~loc "Unknown variable (or region) '%s'" x + +let parse_fieldinfo env ~loc comp f = + try List.find (fun fd -> fd.fname = f) comp.cfields + with Not_found -> + error env ~loc "No field '%s' in compound type '%s'" f comp.cname + +let parse_lindex env e = + let open Logic_typing in + let g = env.context in + let t = g.type_term g g.pre_state e in + if isIndexType t.term_type then t + else error env ~loc:t.term_loc "Index term shall have a integer type" + +let parse_ltype env ~loc t = + let open Logic_typing in + let g = env.context in + let t = g.logic_type g loc g.pre_state t in + match Logic_utils.unroll_type t with + | Ctype typ -> typ + | _ -> error env ~loc "C-type expected for casting l-values" + +let parse_lbound env = function + | None -> None + | Some e -> Some (parse_lindex env e) + +let parse_lrange env e = + match e.lexpr_node with + | PLrange(a,b) -> R_range( parse_lbound env a , parse_lbound env b ) + | _ -> R_index( parse_lindex env e ) + +let sugar ~loc node = { lexpr_loc = loc ; lexpr_node = node } + +let rec field_range ~inside fa fb = function + | [] -> [] + | f::fs -> + let bound = Fieldinfo.equal f fa || Fieldinfo.equal f fb in + if inside then f :: (if bound then [] else field_range ~inside fa fb fs) + else if bound then f :: (field_range ~inside:true fa fb fs) + else field_range ~inside fa fb fs + +let rec typeof_fields = function + | [] -> TVoid [] + | [f] -> f.ftype + | f::fs -> + let t = typeof_fields fs in + if Typ.equal f.ftype t then t else TVoid [] + +let rec parse_lpath env e = + let loc = e.lexpr_loc in + match e.lexpr_node with + | PLvar x -> + if List.mem x env.declared + then { loc ; lnode = L_region x ; ltype = TVoid [] } + else + let v = parse_varinfo env ~loc x in + { loc ; lnode = L_var v ; ltype = v.vtype } + | PLunop( Ustar , p ) -> + let lv = parse_lpath env p in + if Cil.isPointerType lv.ltype then + let te = Cil.typeOf_pointed lv.ltype in + { loc ; lnode = L_star(te,lv) ; ltype = te } + else + error env ~loc "Pointer-type expected for operator '&'" + | PLunop( Uamp , p ) -> + let lv = parse_lpath env p in + let ltype = TPtr( lv.ltype , [] ) in + { loc ; lnode = L_addr lv ; ltype } + | PLbinop( p , Badd , r ) -> + let { ltype } as lv = parse_lpath env p in + let rg = parse_lrange env r in + if Cil.isPointerType ltype then + let te = Cil.typeOf_pointed ltype in + { loc ; lnode = L_shift(lv,te,rg) ; ltype = ltype } + else + if Cil.isArrayType ltype then + let te = Cil.typeOf_array_elem ltype in + { loc ; lnode = L_shift(lv,te,rg) ; ltype = TPtr(te,[]) } + else + error env ~loc "Pointer-type expected for operator '+'" + | PLdot( p , f ) -> + let lv = parse_lpath env p in + let comp = getCompoundType env ~loc:lv.loc lv.ltype in + let fd = parse_fieldinfo env ~loc comp f in + { loc ; lnode = L_field(lv,[fd]) ; ltype = fd.ftype } + | PLarrow( p , f ) -> + let sp = sugar ~loc (PLunop(Ustar,p)) in + let pf = sugar ~loc (PLdot(sp,f)) in + parse_lpath env pf + | PLarrget( p , k ) -> + let { ltype } as lv = parse_lpath env p in + let rg = parse_lrange env k in + if Cil.isPointerType ltype then + let pointed = Cil.typeOf_pointed ltype in + let ls = { loc ; lnode = L_shift(lv,pointed,rg) ; ltype } in + { loc ; lnode = L_star(pointed,ls) ; ltype = pointed } + else + if Cil.isArrayType ltype then + let elt = Cil.typeOf_array_elem ltype in + { loc ; lnode = L_index(lv,elt,rg) ; ltype = elt } + else + error env ~loc:lv.loc "Pointer or array type expected" + | PLcast( t , a ) -> + let lv = parse_lpath env a in + let ty = parse_ltype env ~loc t in + { loc ; lnode = L_cast(ty,lv) ; ltype = ty } + | PLrange( Some a , Some b ) -> + let pa,fa = parse_fpath env a in + let pb,fb = parse_fpath env b in + let p = + if Lpath.equal pa pb then pa + else error env ~loc "Range of fields from different l-values" in + let comp = + if Compinfo.equal fa.fcomp fb.fcomp then fa.fcomp + else error env ~loc "Range of fields from incompatible types" in + let fields = field_range ~inside:false fa fb comp.cfields in + let ltype = typeof_fields fields in + { loc ; lnode = L_field(p,fields) ; ltype } + | PLrange( Some a , None ) -> + let p,fd = parse_fpath env a in + let fields = field_range ~inside:false fd fd fd.fcomp.cfields in + let ltype = typeof_fields fields in + { loc ; lnode = L_field(p,fields) ; ltype } + | PLrange( None , Some a ) -> + let p,fd = parse_fpath env a in + let fields = field_range ~inside:true fd fd fd.fcomp.cfields in + let ltype = typeof_fields fields in + { loc ; lnode = L_field(p,fields) ; ltype } + | _ -> + error env ~loc "Unexpected expression for region spec" + +and parse_fpath env p = + let lv = parse_lpath env p in + match lv.lnode with + | L_field( a , [f] ) -> a , f + | _ -> error env ~loc:lv.loc "Missing field access in range" + +(* -------------------------------------------------------------------------- *) +(* --- Spec Typechecking --- *) +(* -------------------------------------------------------------------------- *) + +let kspec = ref 0 +let registry = Hashtbl.create 0 + +let parse_pattern env ~loc names params = + match names with + | [name] -> + let pattern = + try List.assoc name patterns + with Not_found -> error env ~loc "Unknown pattern '%s'" name in + if params <> [] then + error env ~loc "Unexpected parameters for pattern '%s'" name ; + pattern + | [] -> error env ~loc "Missing pattern name" + | _ -> error env ~loc "Duplicate pattern names" + +let rec parse_region env p = + let loc = p.lexpr_loc in + match p.lexpr_node with + | PLnamed( name , p ) -> + flush env ; + env.name <- Some name ; + parse_region env p + | PLapp("\\pattern",names,params) -> + let pattern = parse_pattern env ~loc names params in + if env.pattern <> FREE && env.pattern <> pattern then + error env ~loc "Duplicate pattern definition in region" + else + env.pattern <- pattern + | _ -> + let path = parse_lpath env p in + env.paths <- path :: env.paths + +let typecheck ~typing_context ~loc:_loc ps = + let env = { + name = None ; + declared = [] ; + context = typing_context ; + pattern = FREE ; + paths = [] ; specs = [] ; + } in + List.iter (parse_region env) ps ; + let id = !kspec in incr kspec ; + let specs = flush env ; env.specs in + Hashtbl.add registry id specs ; Ext_id id + +(* -------------------------------------------------------------------------- *) +(* --- Registry --- *) +(* -------------------------------------------------------------------------- *) + +let of_extid = Hashtbl.find registry +let of_extrev = function + | { ext_name="region" ; ext_kind = Ext_id k } -> of_extid k + | _ -> raise Not_found +let of_extension e = List.rev (of_extrev e) +let of_behavior bhv = + List.fold_left + (fun acc e -> List.rev_append (try of_extrev e with Not_found -> []) acc) + [] bhv.Cil_types.b_extended + +let pp_extension printer fmt = function + | Ext_id k -> + let spec = try Hashtbl.find registry k with Not_found -> [] in + ignore (List.fold_left (pp_region_spec printer#term fmt) false spec) + | _ -> () + +let specified = + let re = Str.regexp_case_fold "region" in + fun model -> + try + ignore (Str.search_forward re model 0) ; true + with Not_found -> false + +let register () = + if Wp.Region.get () || Wp.Region_annot.get () || + List.exists specified (Wp.Model.get ()) + then + begin + Logic_typing.register_behavior_extension "region" true typecheck ; + Cil_printer.register_behavior_extension "region" pp_extension ; + end + +let () = Cmdline.run_after_configuring_stage register + +(* -------------------------------------------------------------------------- *) diff --git a/src/plugins/wp/RegionAnnot.mli b/src/plugins/wp/RegionAnnot.mli new file mode 100644 index 0000000000000000000000000000000000000000..c48c63f3e2f1aab417b5dc36b2d1a365b8bc9d74 --- /dev/null +++ b/src/plugins/wp/RegionAnnot.mli @@ -0,0 +1,70 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2019 *) +(* CEA (Commissariat a l'energie atomique et aux energies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types + +type lrange = + | R_index of term + | R_range of term option * term option + +type lpath = { + loc : location ; + lnode : lnode ; + ltype : typ ; +} +and lnode = + | L_var of varinfo + | L_region of string + | L_addr of lpath + | L_star of typ * lpath + | L_shift of lpath * typ * lrange + | L_index of lpath * typ * lrange + | L_field of lpath * fieldinfo list + | L_cast of typ * lpath + +module Lpath : +sig + type t = lpath + val equal : t -> t -> bool + val compare : t -> t -> int + val pretty : Format.formatter -> t -> unit +end + +type region_pattern = + | FREE + | PVAR + | PREF + | PMEM + | PVECTOR + | PMATRIX + +type region_spec = { + region_name: string option ; + region_pattern: region_pattern ; + region_lpath: lpath list ; +} + +val p_name : region_pattern -> string +val of_extension : acsl_extension -> region_spec list +val of_behavior : behavior -> region_spec list + +val register : unit -> unit (** Auto when `-wp-region` *) diff --git a/src/plugins/wp/RegionDump.ml b/src/plugins/wp/RegionDump.ml new file mode 100644 index 0000000000000000000000000000000000000000..cd4d31c78b4b93c0b790124aee648d1ce95dfcdc --- /dev/null +++ b/src/plugins/wp/RegionDump.ml @@ -0,0 +1,295 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2019 *) +(* CEA (Commissariat a l'energie atomique et aux energies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +module Wp = Wp_parameters +module Kf = Kernel_function +module G = Dotgraph +module R = G.Node(Region.Map) + +let node_default = [`Attr("fontname","monospace")] +let edge_default = [`Attr("fontname","monospace")] + +let attr_offset = [ `Filled ; `Color "grey" ; `Box ] +let attr_write = [ `Label "W" ; `Fillcolor "green" ; `Filled ] +let attr_read = [ `Label "R" ; `Fillcolor "green" ; `Filled ] +let attr_alias = [ `Label "&" ; `Fillcolor "orange" ; `Filled ] +let attr_merge = [ `Color "red" ; `Fillcolor "red" ; `Filled ] +let attr_shift = [ `Label "[]" ] +let attr_delta = [ `Filled ; `Color "lightblue" ; `Box ] +let attr_deref = [ `ArrowHead "tee" ] +let attr_cil = [ `Filled ; `Fillcolor "yellow" ] +let attr_region = `Shape "tab" :: attr_cil +let attr_var = `Shape "cds" :: attr_cil +let attr_garbled = [`Fillcolor "red";`Filled] +let attr_froms = [ `Color "blue" ; `Attr("dir","back") ] + +let attr_pointed = [ + `Color "red" +] + +let attr_pointed_deref = [ + `Attr("taillabel","*"); + `Attr("labelangle","+30"); + `Color "red"; +] + +let attr_pointed_shift = [ + `Attr("taillabel","[..]"); + `Attr("labeldistance","1.7"); + `Attr("labelangle","+40"); + `Color "red"; +] + +let rid_key = Wp.register_category "rid" +let dot_key = Wp.register_category "dot" +let pdf_key = Wp.register_category "pdf" +let deref_key = Wp.register_category "deref" +let roots_key = Wp.register_category "roots" +let froms_key = Wp.register_category "froms" +let cluster_key = Wp.register_category "cluster" +let chunk_key = Wp.register_category "chunk" +let offset_key = Wp.register_category "offset" + +let sfprintf = Pretty_utils.sfprintf + +let dotpointed ~label r = + let attr = + if Region.is_shifted r + then attr_pointed_shift else attr_pointed_deref in + let target = G.port (R.get r) "w" in + `Port ("",["",attr,target],label) + +let dotvalue ?(prefix="") value : Dotgraph.record = + let open Layout in + match value with + | Int i -> `Label (sfprintf "%s%a" prefix Ctypes.pp_int i) + | Float f -> `Label (sfprintf "%s%a" prefix Ctypes.pp_float f) + | Pointer r -> dotpointed ~label:(prefix ^ "ptr") r + +let dotrange ?(prefix="") rg : Dotgraph.record = + let open Layout in + let pp_dim fmt = function + | Raw _ -> Format.pp_print_string fmt "raw" + | Dim(s,ds) -> Format.fprintf fmt "%d%a" s Matrix.pretty ds + in + let label = sfprintf "%d..%d: %s%a" + rg.ofs (rg.ofs + rg.len - 1) + prefix pp_dim rg.dim in + `Port("",["",[`Dotted],R.get rg.reg],label) + +let dotcluster cluster : Dotgraph.record = + let open Layout in + match cluster with + | Empty -> `Label "-" + | Garbled -> `Label "Garbled" + | Chunk v -> dotvalue v + | Layout { sizeof ; layout } -> + let label = Printf.sprintf "sizeof:%d" sizeof in + `Hbox (`Label label :: List.map dotrange layout) + +let dotchunk mem : Dotgraph.record = + let open Layout in + match mem with + | Mraw(_,None) -> `Label "Raw" + | Mraw(_,Some r) -> dotpointed ~label:"Raw" r + | Mref r -> dotpointed ~label:"Ref" r + | Mmem(rt,v) -> + let prefix = if Layout.Root.indexed rt then "Mem " else "Var " in + dotvalue ~prefix v + | Mcomp(_,ovl) -> + let range rg = dotrange + ~prefix:(if Overlay.once rg.reg ovl then "D" else "C") rg in + `Hbox (List.map range ovl) + +let dotregion dot map region node = + begin + let is_read = Region.is_read region in + let is_written = Region.is_written region in + let is_aliased = Region.is_aliased region in + let is_accessed = is_read || is_written || is_aliased in + let has_deref = Wp.has_dkey deref_key && Region.has_deref region in + let has_roots = Wp.has_dkey roots_key && Region.has_roots map region in + let has_index_infos = has_deref || has_roots in + let has_side_cluster = + is_accessed || + has_index_infos || + Region.has_names region || + Wp.has_dkey offset_key || + Wp.has_dkey rid_key || + not (Wp.has_dkey cluster_key || Wp.has_dkey chunk_key) || + not (Wp.Region_fixpoint.get ()) + in + if has_side_cluster then + begin + let attr = G.decorate [ `Oval ] [ + is_read , attr_read ; + Region.has_pointed region , [ `Label "D" ] ; + is_written , attr_write ; + Region.is_shifted region , attr_shift ; + is_aliased , attr_alias ; + Region.get_alias map region != region , attr_merge ; + Region.is_garbled region , attr_merge ; + ] in + G.node dot node attr ; + end ; + if Wp.has_dkey offset_key then + Region.iter_offset map + (fun offset target -> + let label = Pretty_utils.to_string Layout.Offset.pretty offset in + let delta = G.inode dot (`Label label :: attr_offset) in + G.link dot [node;delta;R.get target] [`Dotted] + ) region ; + if Wp.has_dkey offset_key then + Extlib.may + (fun target -> + let label = if Region.is_shifted target then "[..]" else "*" in + let deref = G.inode dot (`Label label :: attr_offset) in + G.link dot [node;deref;R.get target] attr_pointed + ) (Region.get_pointed map region) ; + if has_index_infos then + begin + let derefs = ref [] in + let label s = derefs := s :: !derefs in + if has_roots then + label @@ sfprintf "roots:%a" + Layout.Root.pretty (Region.get_roots map region) ; + if has_deref then + Region.iter_deref + (fun deref -> + label @@ Pretty_utils.to_string Layout.Deref.pretty deref + ) region ; + if !derefs <> [] then + begin + let label = String.concat "\n" (List.rev !derefs) in + let delta = G.inode dot (`Label label :: attr_delta) in + G.rank dot [node;delta] ; + G.edge dot delta node attr_deref + end + end ; + if Wp.has_dkey cluster_key then + begin + let cluster = Region.cluster map region in + if not (has_side_cluster && Layout.Cluster.is_empty cluster) then + let record = dotcluster cluster in + let attr = if Region.is_garbled region then attr_garbled else [] in + if has_side_cluster then + let delta = G.irecord dot ~attr record in + G.edge dot node (G.port delta "w") attr_deref + else + G.record dot node ~attr record + end ; + if Wp.has_dkey chunk_key then + begin + let chunk = Region.chunk map region in + let record = dotchunk chunk in + let attr = if Region.is_garbled region then attr_garbled else [] in + if has_side_cluster then + let delta = G.irecord dot ~attr record in + G.edge dot node (G.port delta "w") attr_deref + else + G.record dot node ~attr record + end ; + if Wp.has_dkey froms_key then + begin + let open Layout in + List.iter + (function + | Fvar _ -> () + | Farray r -> + G.edge dot (R.get r) node (`Label "[]"::attr_froms) + | Fderef r -> + G.edge dot (R.get r) node (`Label "*"::attr_froms) + | Findex r -> + G.edge dot (R.get r) node (`Label "+(..)"::attr_froms) + | Ffield(r,ofs) -> + let label = Printf.sprintf "+%d" ofs in + G.edge dot (R.get r) node (`Label label::attr_froms) + ) (Region.get_froms map region) + end ; + Region.iter_copies map + (fun target -> + G.edge dot node (R.get target) [`Color "green"] + ) region ; + Extlib.may + (fun target -> + G.edge dot node (R.get target) [`Color "red"] + ) (Region.get_merged map region) ; + end + +let dotvar dot x r = + begin + let open Cil_types in + let xnode = G.inode dot ~prefix:"V" (`Label x.vname :: attr_var) in + G.edge dot (G.port xnode "e") (R.get r) [] ; + end + +let dotlabel dot a r = + begin + let anode = G.inode dot ~prefix:"R" (`Label a :: attr_region) in + let rnode = R.get r in + G.rank dot [ anode ; rnode ] ; + G.edge dot anode rnode [] + end + +let dotrid dot r = + dotlabel dot (Pretty_utils.to_string Region.R.pretty r) r + +let dotstr dot r cst = + dotlabel dot (String.escaped cst) r + +let dotgraph dot map = + begin + G.node_default dot node_default ; + G.edge_default dot edge_default ; + R.clear () ; + R.push dot (dotregion dot map) ; + Region.iter_vars map (dotvar dot) ; + Region.iter_strings map (dotstr dot) ; + G.pop_all dot ; + if Wp.has_dkey rid_key then Region.iter map (dotrid dot) ; + Region.iter_names map (dotlabel dot) ; + if Region.has_return map then + dotlabel dot "\\result" (Region.of_return map) ; + Region.iter_fusion map (fun i r -> + let rid = Region.id r in + if i <> rid then + dotlabel dot (Printf.sprintf "Fusion R%03d" i) r + else + dotlabel dot "Fusion (Self)" r + ) ; + G.pop_all dot ; + end + +let dump ~dir kf map = + if Wp.has_dkey dot_key || Wp.has_dkey pdf_key then + begin + let name = Kf.get_name kf in + let file = Printf.sprintf "%s/%s.dot" dir name in + let dot = Dotgraph.open_dot ~attr:[`LR] ~name ~file () in + dotgraph dot map ; + Dotgraph.close dot ; + let outcome = + if Wp.has_dkey pdf_key + then Dotgraph.layout dot + else file in + Wp.result "Region Graph: %s" outcome + end diff --git a/src/plugins/wp/RegionDump.mli b/src/plugins/wp/RegionDump.mli new file mode 100644 index 0000000000000000000000000000000000000000..362876448cd0c752ae7661005952d286ec9040ad --- /dev/null +++ b/src/plugins/wp/RegionDump.mli @@ -0,0 +1,26 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2019 *) +(* CEA (Commissariat a l'energie atomique et aux energies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* Dump region graphs to dir according to -wp options. + By default, does nothing. *) + +val dump : dir:string -> Kernel_function.t -> Region.map -> unit diff --git a/src/plugins/wp/Sigs.ml b/src/plugins/wp/Sigs.ml index 3c5e197bbe689567d2e3ce1bf8b7bc712f502ba8..9626908c66c8901490dc7e57c60b18153c9f0773 100644 --- a/src/plugins/wp/Sigs.ml +++ b/src/plugins/wp/Sigs.ml @@ -85,6 +85,16 @@ type 'a result = (** Polarity of predicate compilation *) type polarity = [ `Positive | `Negative | `NoPolarity ] +(** Frame Conditions. + Consider a function [phi(m)] over memory [m], + we want memories [m1,m2] and condition [p] such that + [p(m1,m2) -> phi(m1) = phi(m2)]. + - [name] used for generating lemma + - [triggers] for the lemma + - [conditions] for the frame lemma to hold + - [mem1,mem2] to two memories for which the lemma holds *) +type frame = string * Definitions.trigger list * pred list * term * term + (* -------------------------------------------------------------------------- *) (** {1 Reversing Models} @@ -135,6 +145,7 @@ sig type t val self : string (** Chunk names, for pretty-printing. *) val hash : t -> int + val equal : t -> t -> bool val compare : t -> t -> int val pretty : Format.formatter -> t -> unit @@ -423,7 +434,7 @@ sig location [loc] which is represented by [t] in [sigma.post]. *) - val assigned : sigma sequence -> c_object -> loc sloc -> pred list + val assigned : sigma sequence -> c_object -> loc sloc -> equation list (** Return a set of formula that express that two memory state are the same except at the given set of memory location. diff --git a/src/plugins/wp/TacBitwised.ml b/src/plugins/wp/TacBitwised.ml index 4c9efb759af6245f97c86a542ab8f644806eb71e..31e47696959e28e323cd8236f4e2ca2160856d4d 100644 --- a/src/plugins/wp/TacBitwised.ml +++ b/src/plugins/wp/TacBitwised.ml @@ -117,7 +117,7 @@ let rec lookup push clause ~nbits ~priority p = class autobitwise = object(self) - method private nbits = Ctypes.range (Ctypes.c_ptr ()) + method private nbits = Ctypes.i_bits (Ctypes.c_ptr ()) method id = "wp:bitwised" method title = diff --git a/src/plugins/wp/TacHavoc.ml b/src/plugins/wp/TacHavoc.ml index 9b7034cc30839c0ed07020faf82927db93ef5e96..9e68996a899b6602601fc6334b8daa46eaa4e600 100644 --- a/src/plugins/wp/TacHavoc.ml +++ b/src/plugins/wp/TacHavoc.ml @@ -35,7 +35,7 @@ let lookup_havoc e = | L.Aget( m , p ) -> begin match F.repr m with - | L.Fun( f , [mr;m0;a;n] ) when f == MemTyped.f_havoc -> + | L.Fun( f , [mr;m0;a;n] ) when f == MemMemory.f_havoc -> Some( mr , m0 , a , n , p ) | _ -> None end @@ -55,7 +55,7 @@ class havoc = | None -> Not_applicable | Some(mr,m0,a,n,p) -> let separated = - F.p_call MemTyped.p_separated + F.p_call MemMemory.p_separated [ p ; F.e_int 1 ; a ; n ] in let process = Tactical.rewrite ?at [ "Unassigned" , separated , e , F.e_get m0 p ; @@ -70,11 +70,11 @@ class havoc = let separated ?at property = match F.e_expr property with - | L.Fun( f , [p;n;q;m] ) when f == MemTyped.p_separated -> - let base_p = MemTyped.a_base p in - let ofs_p = MemTyped.a_offset p in - let base_q = MemTyped.a_base q in - let ofs_q = MemTyped.a_offset q in + | L.Fun( f , [p;n;q;m] ) when f == MemMemory.p_separated -> + let base_p = MemMemory.a_base p in + let ofs_p = MemMemory.a_offset p in + let base_q = MemMemory.a_base q in + let ofs_q = MemMemory.a_offset q in let eq_base = F.p_equal base_p base_q in let on_left = F.p_leq (F.e_add ofs_p n) ofs_q in let on_right = F.p_leq (F.e_add ofs_q m) ofs_p in @@ -110,8 +110,8 @@ class separated = (* -------------------------------------------------------------------------- *) let invalid m p n = - let base = MemTyped.a_base p in - let offset = MemTyped.a_offset p in + let base = MemMemory.a_base p in + let offset = MemMemory.a_offset p in let malloc = F.e_get m base in "Invalid", F.p_imply @@ -121,8 +121,8 @@ let invalid m p n = (F.p_leq (F.e_add offset n) F.e_zero)) let valid_rd m p n = - let base = MemTyped.a_base p in - let offset = MemTyped.a_offset p in + let base = MemMemory.a_base p in + let offset = MemMemory.a_offset p in let malloc = F.e_get m base in "Valid (Read)", F.p_imply @@ -132,8 +132,8 @@ let valid_rd m p n = (F.p_leq (F.e_add offset n) malloc)) let valid_rw m p n = - let base = MemTyped.a_base p in - let offset = MemTyped.a_offset p in + let base = MemMemory.a_base p in + let offset = MemMemory.a_offset p in let malloc = F.e_get m base in "Valid (Read & Write)", F.p_imply @@ -145,10 +145,10 @@ let valid_rw m p n = ]) let included p a q b = - let p_base = MemTyped.a_base p in - let q_base = MemTyped.a_base q in - let p_offset = MemTyped.a_offset p in - let q_offset = MemTyped.a_offset q in + let p_base = MemMemory.a_base p in + let q_base = MemMemory.a_base q in + let p_offset = MemMemory.a_offset p in + let q_offset = MemMemory.a_offset q in "Included", F.p_imply (F.p_lt F.e_zero a) @@ -161,10 +161,10 @@ let included p a q b = ])) let lookup f = function - | [p;a;q;b] when f == MemTyped.p_included -> included p a q b - | [m;p;n] when f == MemTyped.p_invalid -> invalid m p n - | [m;p;n] when f == MemTyped.p_valid_rd -> valid_rd m p n - | [m;p;n] when f == MemTyped.p_valid_rw -> valid_rw m p n + | [p;a;q;b] when f == MemMemory.p_included -> included p a q b + | [m;p;n] when f == MemMemory.p_invalid -> invalid m p n + | [m;p;n] when f == MemMemory.p_valid_rd -> valid_rd m p n + | [m;p;n] when f == MemMemory.p_valid_rw -> valid_rw m p n | _ -> raise Not_found let unfold ?at e f es = diff --git a/src/plugins/wp/cfgWP.ml b/src/plugins/wp/cfgWP.ml index ea3cd5016fe6236b9dc0d1679b10ebb05f45b238..5f50a2b765e08572d52e8dae984122823859ea63 100644 --- a/src/plugins/wp/cfgWP.ml +++ b/src/plugins/wp/cfgWP.ml @@ -789,7 +789,7 @@ struct let rec cc_case_values ks vs sigma = function | [] -> ks , vs | e::es -> - match Ctypes.get_int e with + match Ctypes.get_int64 e with | Some k -> cc_case_values (k::ks) (F.e_int64 k::vs) sigma es | None -> diff --git a/src/plugins/wp/ctypes.ml b/src/plugins/wp/ctypes.ml index f26b90250538d28231b9fbbee1bd422d4f3fe95d..d6ad36e4a1ff099a330ae22fbfcbf432199d583c 100644 --- a/src/plugins/wp/ctypes.ml +++ b/src/plugins/wp/ctypes.ml @@ -47,14 +47,14 @@ let signed = function | UInt8 | UInt16 | UInt32 | UInt64 -> false | SInt8 | SInt16 | SInt32 | SInt64 -> true -let range = function +let i_bits = function | CBool -> 1 | UInt8 | SInt8 -> 8 | UInt16 | SInt16 -> 16 | UInt32 | SInt32 -> 32 | UInt64 | SInt64 -> 64 -let sizeof_i = function +let i_bytes = function | CBool -> 1 | UInt8 | SInt8 -> 1 | UInt16 | SInt16 -> 2 @@ -73,7 +73,8 @@ let is_char = function | SInt8 -> not Cil.theMachine.Cil.theMachine.char_is_unsigned | UInt16 | SInt16 | UInt32 | SInt32 - | UInt64 | SInt64 | CBool -> false + | UInt64 | SInt64 + | CBool -> false let c_int ikind = let mach = Cil.theMachine.Cil.theMachine in @@ -93,12 +94,15 @@ let c_int ikind = let c_bool () = c_int IBool let c_char () = c_int IChar -let c_ptr () = - make_c_int false Cil.theMachine.Cil.theMachine.sizeof_ptr + +let p_bytes () = Cil.theMachine.Cil.theMachine.sizeof_ptr +let p_bits () = 8 * p_bytes () + +let c_ptr () = make_c_int false (p_bytes ()) let sub_c_int t1 t2 = - if (signed t1 = signed t2) then range t1 <= range t2 - else (not(signed t1) && (range t1 < range t2)) + if (signed t1 = signed t2) then i_bits t1 <= i_bits t2 + else (not(signed t1) && (i_bits t1 < i_bits t2)) type c_float = | Float32 @@ -106,7 +110,7 @@ type c_float = let compare_c_float : c_float -> c_float -> _ = Extlib.compare_basic -let sizeof_f = function +let f_bytes = function | Float32 -> 4 | Float64 -> 8 @@ -126,7 +130,7 @@ let c_float fkind = | FDouble -> make_c_float mach.sizeof_double | FLongDouble -> make_c_float mach.sizeof_longdouble -let equal_float f1 f2 = (f1 = f2) +let equal_float f1 f2 = f_bits f1 = f_bits f2 (* Array objects, with both the head view and the flatten view. *) @@ -195,15 +199,15 @@ let f_iter f = (* --- Bounds --- *) (* -------------------------------------------------------------------------- *) -let bounds = - let i_bounds i = - if signed i then - let m = Integer.two_power_of_int (range i - 1) in - Integer.neg m , Integer.pred m - else - let m = Integer.two_power_of_int (range i) in - Integer.zero , Integer.pred m - in i_memo i_bounds +let i_bounds i = + if signed i then + let m = Integer.two_power_of_int (i_bits i - 1) in + Integer.neg m , Integer.pred m + else + let m = Integer.two_power_of_int (i_bits i) in + Integer.zero , Integer.pred m + +let bounds i = i_memo i_bounds i (* -------------------------------------------------------------------------- *) (* --- Pretty Printers --- *) @@ -211,7 +215,7 @@ let bounds = let pp_int fmt i = if i = CBool then Format.pp_print_string fmt "bool" - else Format.fprintf fmt "%cint%d" (if signed i then 's' else 'u') (range i) + else Format.fprintf fmt "%cint%d" (if signed i then 's' else 'u') (i_bits i) let pp_float fmt f = Format.fprintf fmt "float%d" (f_bits f) @@ -234,6 +238,11 @@ let constant e = | _ -> WpLog.fatal "Non-constant expression (%a)" Printer.pp_exp e let get_int e = + match (Cil.constFold true e).enode with + | Const(CInt64(k,_,_)) -> Some (Integer.to_int k) + | _ -> None + +let get_int64 e = match (Cil.constFold true e).enode with | Const(CInt64(k,_,_)) -> Some (Integer.to_int64 k) | _ -> None @@ -254,14 +263,12 @@ let is_pointer = function | C_pointer _ -> true | C_int _ | C_float _ | C_array _ | C_comp _ -> false -let is_void = Cil.isVoidType - let rec object_of typ = match typ with | TInt(i,_) -> C_int (c_int i) | TFloat(f,_) -> C_float (c_float f) - | TPtr(typ,_) -> C_pointer (if is_void typ then TInt (IChar,[]) else typ) - | TFun _ -> C_pointer (TVoid []) + | TPtr(typ,_) -> C_pointer (if Cil.isVoidType typ then Cil.charType else typ) + | TFun _ -> C_pointer Cil.voidType | TEnum ({ekind=i},_) -> C_int (c_int i) | TComp (comp,_,_) -> C_comp comp | TArray (typ_elt,e_opt,_,_) -> @@ -272,7 +279,6 @@ let rec object_of typ = arr_element = typ_elt; arr_flat = None; } - | Some e -> let dim,ncells,ty_cell = dimension typ in C_array { @@ -444,24 +450,36 @@ let sizeof_defined = function | C_array { arr_flat = None } -> false | _ -> true +let typ_comp cinfo = TComp(cinfo,Cil.empty_size_cache(),[]) + +let bits_sizeof_comp cinfo = Cil.bitsSizeOf (typ_comp cinfo) + +let bits_sizeof_array ainfo = + match ainfo.arr_flat with + | Some a -> + let csize = Cil.integer ~loc:Cil.builtinLoc a.arr_cell_nbr in + let ctype = TArray(a.arr_cell,Some csize,Cil.empty_size_cache(),[]) in + Cil.bitsSizeOf ctype + | None -> + if WpLog.ExternArrays.get () then + max_int + else + WpLog.fatal ~current:true "Sizeof unknown-size array" + + let sizeof_object = function - | C_int i -> sizeof_i i - | C_float f -> sizeof_f f - | C_pointer _ty -> sizeof_i (c_ptr()) - | C_comp cinfo -> - let ctype = TComp(cinfo,Cil.empty_size_cache(),[]) in - (Cil.bitsSizeOf ctype / 8) - | C_array ainfo -> - match ainfo.arr_flat with - | Some a -> - let csize = Cil.integer ~loc:Cil.builtinLoc a.arr_cell_nbr in - let ctype = TArray(a.arr_cell,Some csize,Cil.empty_size_cache(),[]) in - (Cil.bitsSizeOf ctype / 8) - | None -> - if WpLog.ExternArrays.get () then - max_int - else - WpLog.fatal ~current:true "Sizeof unknown-size array" + | C_int i -> i_bytes i + | C_float f -> f_bytes f + | C_pointer _ty -> p_bytes () + | C_comp cinfo -> bits_sizeof_comp cinfo / 8 + | C_array ainfo -> bits_sizeof_array ainfo / 8 + +let bits_sizeof_object = function + | C_int i -> i_bits i + | C_float f -> f_bits f + | C_pointer _ty -> p_bits () + | C_comp cinfo -> bits_sizeof_comp cinfo + | C_array ainfo -> bits_sizeof_array ainfo let field_offset fd = if fd.fcomp.cstruct then (* C struct *) @@ -490,7 +508,7 @@ let field_offset fd = (* with greater rank, whatever *) (* their sign. *) -let i_convert t1 t2 = if range t1 < range t2 then t2 else t1 +let i_convert t1 t2 = if i_bits t1 < i_bits t2 then t2 else t1 let f_convert t1 t2 = if f_bits t1 < f_bits t2 then t2 else t1 let promote a1 a2 = diff --git a/src/plugins/wp/ctypes.mli b/src/plugins/wp/ctypes.mli index b09df11064c7352f237ebc29997f42b18528b8a3..5de9dbf2e282193a7a99d5e21cd1c090f0d95e6e 100644 --- a/src/plugins/wp/ctypes.mli +++ b/src/plugins/wp/ctypes.mli @@ -90,18 +90,23 @@ val c_int : ikind -> c_int (** Conforms to {Cil.theMachine} *) val c_float : fkind -> c_float (** Conforms to {Cil.theMachine} *) val object_of : typ -> c_object -val is_void : typ -> bool val is_pointer : c_object -> bool val char : char -> int64 val constant : exp -> int64 -val get_int : exp -> int64 option + +val get_int : exp -> int option +val get_int64 : exp -> int64 option val signed : c_int -> bool (** [true] if signed *) -val range : c_int -> int (** range in 2^n *) val bounds: c_int -> Integer.t * Integer.t (** domain, bounds included *) -(** All sizes are in bits *) +val i_bits : c_int -> int (** size in bits *) +val i_bytes : c_int -> int (** size in bytes *) +val f_bits : c_float -> int (** size in bits *) +val f_bytes : c_float -> int (** size in bytes *) +val p_bits : unit -> int (** pointer size in bits *) +val p_bytes : unit -> int (** pointer size in bits *) val sub_c_int: c_int -> c_int -> bool @@ -109,6 +114,9 @@ val equal_float : c_float -> c_float -> bool val sizeof_defined : c_object -> bool val sizeof_object : c_object -> int +val bits_sizeof_comp : compinfo -> int +val bits_sizeof_array : arrayinfo -> int +val bits_sizeof_object : c_object -> int val field_offset : fieldinfo -> int val no_infinite_array : c_object -> bool @@ -149,5 +157,8 @@ sig val hash : t -> int end +val compare_c_int : c_int -> c_int -> int +val compare_c_float : c_float -> c_float -> int + val compare_ptr_conflated : c_object -> c_object -> int (** same as {!compare} but all PTR are considered the same *) diff --git a/src/plugins/wp/register.ml b/src/plugins/wp/register.ml index a02ddbecf0ee2978202c40d5ada24ab3d1f11295..7b4d1efe744adb0261e2d04bd7b245dd09272c6a 100644 --- a/src/plugins/wp/register.ml +++ b/src/plugins/wp/register.ml @@ -759,24 +759,17 @@ let cmdline_run () = end ; Generator.compute_selection computer ~fct ~bhv ~prop () in - match Wp_parameters.job () with - | Wp_parameters.WP_None -> () - | Wp_parameters.WP_All -> + let fct = Wp_parameters.get_wp () in + match fct with + | Wp_parameters.Fct_none -> () + | Wp_parameters.Fct_all -> begin - ignore (wp_main Generator.F_All); + ignore (wp_main fct); do_wp_proofs (); do_wp_print (); do_wp_report (); end - | jb -> - let fct = - let open Wp_parameters in - match jb with - | WP_None -> Generator.F_List Cil_datatype.Kf.Set.empty - | WP_All -> Generator.F_All - | WP_Fct fs -> Generator.F_List fs - | WP_SkipFct fs -> Generator.F_Skip fs - in + | _ -> begin let goals = wp_main fct in do_wp_proofs_for goals ; diff --git a/src/plugins/wp/tests/wp_acsl/oracle_qualif/init_value_mem.0.session/cache/22897f38fca9d1f1cd1837f1350d4499.json b/src/plugins/wp/tests/wp_acsl/oracle_qualif/init_value_mem.0.session/cache/ada35ef3207f170ebebb1029d3420256.json similarity index 91% rename from src/plugins/wp/tests/wp_acsl/oracle_qualif/init_value_mem.0.session/cache/22897f38fca9d1f1cd1837f1350d4499.json rename to src/plugins/wp/tests/wp_acsl/oracle_qualif/init_value_mem.0.session/cache/ada35ef3207f170ebebb1029d3420256.json index bae3da127cbd881ecd10c973b23f6aea0154f5b8..3783f56fa7d1ce2810f838c883105ecdb344ec7f 100644 --- a/src/plugins/wp/tests/wp_acsl/oracle_qualif/init_value_mem.0.session/cache/22897f38fca9d1f1cd1837f1350d4499.json +++ b/src/plugins/wp/tests/wp_acsl/oracle_qualif/init_value_mem.0.session/cache/ada35ef3207f170ebebb1029d3420256.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0232, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0307, "steps": 36 } diff --git a/src/plugins/wp/tests/wp_acsl/oracle_qualif/logic.0.session/cache/090dcbb7243fc5374efafdaf37e519bb.json b/src/plugins/wp/tests/wp_acsl/oracle_qualif/logic.0.session/cache/47d1b9e051b4330350aa41a5c9d5a242.json similarity index 100% rename from src/plugins/wp/tests/wp_acsl/oracle_qualif/logic.0.session/cache/090dcbb7243fc5374efafdaf37e519bb.json rename to src/plugins/wp/tests/wp_acsl/oracle_qualif/logic.0.session/cache/47d1b9e051b4330350aa41a5c9d5a242.json diff --git a/src/plugins/wp/tests/wp_acsl/oracle_qualif/logic.0.session/cache/47212b097d7a57e437c6007c537e0914.json b/src/plugins/wp/tests/wp_acsl/oracle_qualif/logic.0.session/cache/680324ac6d96e356bd6c39b70e081433.json similarity index 100% rename from src/plugins/wp/tests/wp_acsl/oracle_qualif/logic.0.session/cache/47212b097d7a57e437c6007c537e0914.json rename to src/plugins/wp/tests/wp_acsl/oracle_qualif/logic.0.session/cache/680324ac6d96e356bd6c39b70e081433.json diff --git a/src/plugins/wp/tests/wp_bts/oracle/bts_2110.res.oracle b/src/plugins/wp/tests/wp_bts/oracle/bts_2110.res.oracle index 6f1d2b5ff9f58712c11ecd95a3b6bdc7a381220a..54d45f3925f1f9d511f7d0f85546683e15f2b689 100644 --- a/src/plugins/wp/tests/wp_bts/oracle/bts_2110.res.oracle +++ b/src/plugins/wp/tests/wp_bts/oracle/bts_2110.res.oracle @@ -66,17 +66,17 @@ theory Compound not q = p -> Load_S2_A p (set mint q v) = Load_S2_A p mint axiom Q_Load_S2_A_eqmem_Mint : - forall mint:addr -> int, mint1:addr -> int, k:int, p:addr, q:addr - [eqmem mint mint1 q k, Load_S2_A p mint| eqmem mint mint1 q k, - Load_S2_A p mint1]. - included p 1 q k -> - eqmem mint mint1 q k -> Load_S2_A p mint1 = Load_S2_A p mint + forall mint:addr -> int, mint1:addr -> int, n:int, p:addr, q:addr + [Load_S2_A p mint, eqmem mint mint1 q n| Load_S2_A p mint1, + eqmem mint mint1 q n]. + included p 1 q n -> + eqmem mint mint1 q n -> Load_S2_A p mint1 = Load_S2_A p mint axiom Q_Load_S2_A_havoc_Mint : - forall mint:addr -> int, mint1:addr -> int, mint2:addr -> int, k:int, p: - addr, q:addr [Load_S2_A p mint| Load_S2_A p mint1]. - havoc mint2 mint q k = mint1 -> - separated p 1 q k -> Load_S2_A p mint1 = Load_S2_A p mint + forall mint:addr -> int, mint1:addr -> int, n:int, p:addr, q:addr + [Load_S2_A p (havoc mint1 mint q n)]. + separated p 1 q n -> + Load_S2_A p (havoc mint1 mint q n) = Load_S2_A p mint end [wp:print-generated] theory WP diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/09dec9b675cb72a17a7c7f694202bc2a.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/09dec9b675cb72a17a7c7f694202bc2a.json deleted file mode 100644 index fa5c0688aa29541e24fcadc5716bb839b136f98a..0000000000000000000000000000000000000000 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/09dec9b675cb72a17a7c7f694202bc2a.json +++ /dev/null @@ -1,2 +0,0 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 3.0065, - "steps": 856 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/2932211f5ea4822c1cc4f1d7b5aca14c.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/0c3a16ff3ecb02ed6f91b69f76942a5f.json similarity index 91% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/2932211f5ea4822c1cc4f1d7b5aca14c.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/0c3a16ff3ecb02ed6f91b69f76942a5f.json index 97bcecd17ab6f7c514c39bf9cefa558e10ec21d5..5a1b1f7dd70df8229f800765237be67c19c211e9 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/2932211f5ea4822c1cc4f1d7b5aca14c.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/0c3a16ff3ecb02ed6f91b69f76942a5f.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0554, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0314, "steps": 74 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/214b0fb9511817c8882f41d7586b6bb4.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/214b0fb9511817c8882f41d7586b6bb4.json new file mode 100644 index 0000000000000000000000000000000000000000..03f152ed73ea0df3011f5f2956eaaa3b4b8774c9 --- /dev/null +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/214b0fb9511817c8882f41d7586b6bb4.json @@ -0,0 +1,2 @@ +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 2.5518, + "steps": 856 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/1a5d45fc87de676bd6e65e2299275bd8.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/27e2e343658ccf65535b56edee720c46.json similarity index 91% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/1a5d45fc87de676bd6e65e2299275bd8.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/27e2e343658ccf65535b56edee720c46.json index 0785bafe2151662d4a053c9a58f682a5afb5b79a..25159578e1f869a89a1ca200043f2f9ffeaf2bab 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/1a5d45fc87de676bd6e65e2299275bd8.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/27e2e343658ccf65535b56edee720c46.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0833, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0624, "steps": 96 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/417d31f008385f8de844ebd8a2b26109.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/32f18b2b6ec78668204d73a4ef122549.json similarity index 91% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/417d31f008385f8de844ebd8a2b26109.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/32f18b2b6ec78668204d73a4ef122549.json index 7bb9f5b96b8e6f2fbaeb7b363dafa8f8a0efe814..ad485ff38d104b60f6b3457f22a920331d34593b 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/417d31f008385f8de844ebd8a2b26109.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/32f18b2b6ec78668204d73a4ef122549.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0825, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0517, "steps": 99 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/788de7a3ed5ac15364ec4b0d1d549517.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/41abf1fe4d6a6b46b204b97a55f5ba46.json similarity index 92% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/788de7a3ed5ac15364ec4b0d1d549517.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/41abf1fe4d6a6b46b204b97a55f5ba46.json index 4a0fe0253e07d2a53533afbdb5016048727c86d3..63a12236c80c74ebd59b9f7c2940929da036bceb 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/788de7a3ed5ac15364ec4b0d1d549517.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/41abf1fe4d6a6b46b204b97a55f5ba46.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 1.6653, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 1.221, "steps": 586 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/50198fa843b3c6d73486e1c8e97986fe.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/41db8884cdb35e4120e231fbcf59b7cf.json similarity index 92% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/50198fa843b3c6d73486e1c8e97986fe.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/41db8884cdb35e4120e231fbcf59b7cf.json index 189d0bd33804fc2c666a38055ab371b1fd16b1bd..14c6cd80068e6f4c31771a12bec60d7ed9bb5d35 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/50198fa843b3c6d73486e1c8e97986fe.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/41db8884cdb35e4120e231fbcf59b7cf.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.2276, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.1436, "steps": 179 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/720f79b436175dca03ae7858fc5c1f26.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/461fe24ecd8d691d91a96770806ef5ff.json similarity index 91% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/720f79b436175dca03ae7858fc5c1f26.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/461fe24ecd8d691d91a96770806ef5ff.json index 1488f15736938024e2f8bca896ea0c7c72438e98..702ecef4ec3780ab1b83b2ed2b414618a2d74ee1 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/720f79b436175dca03ae7858fc5c1f26.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/461fe24ecd8d691d91a96770806ef5ff.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0553, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0538, "steps": 77 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/9d34f304e163ac58156095e675166f3d.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/4995e8c730ee8819901115149d1bb625.json similarity index 91% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/9d34f304e163ac58156095e675166f3d.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/4995e8c730ee8819901115149d1bb625.json index 5200215dad1ef9f15e0f244d9a4afe4cb9203320..a9cf316c04100e411ebf7d23308e447c1784ff52 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/9d34f304e163ac58156095e675166f3d.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/4995e8c730ee8819901115149d1bb625.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0833, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0734, "steps": 93 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/a2409dfdbd49a74d79f3176de0036845.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/520cfa9227ef9a8499ea5907b0f1a23d.json similarity index 92% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/a2409dfdbd49a74d79f3176de0036845.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/520cfa9227ef9a8499ea5907b0f1a23d.json index f08a403b51571b2d112da532004f2f84fd5380c1..c84a16d022afcb122bdf635c41d0350a22b8b760 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/a2409dfdbd49a74d79f3176de0036845.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/520cfa9227ef9a8499ea5907b0f1a23d.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.2383, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.1518, "steps": 222 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/f73790b589aedf4d1aa297026d17411a.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/597cff9f1dc565dac843b5ef236377f7.json similarity index 92% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/f73790b589aedf4d1aa297026d17411a.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/597cff9f1dc565dac843b5ef236377f7.json index b0178e16c84d96d90f8016a878a8fcf1c56b21b3..6903049fadd16ae56e8ab9ad02b55fb8afca6e13 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/f73790b589aedf4d1aa297026d17411a.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/597cff9f1dc565dac843b5ef236377f7.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.1924, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.1081, "steps": 167 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/078985c01b8321ee067c085a1e9cf2ce.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/5a2a0c8957f907ffd6d1208c9bc716c9.json similarity index 72% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/078985c01b8321ee067c085a1e9cf2ce.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/5a2a0c8957f907ffd6d1208c9bc716c9.json index 377ffd62394faccc376804f41f93d937b87ff610..006402faf3aa9f1094742bd84c688df125703030 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/078985c01b8321ee067c085a1e9cf2ce.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/5a2a0c8957f907ffd6d1208c9bc716c9.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.4288, - "steps": 238 } +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0687, + "steps": 108 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/b3c26bb27e0fffaaa5110deff2e14300.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/5c1973c9a7e767b15e43009917c6851e.json similarity index 91% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/b3c26bb27e0fffaaa5110deff2e14300.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/5c1973c9a7e767b15e43009917c6851e.json index 3e8c5a6c4fce755deea076d119c3fc6500003333..5f84f2d9717e9ef8adaea39adfbf9985e815cd0c 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/b3c26bb27e0fffaaa5110deff2e14300.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/5c1973c9a7e767b15e43009917c6851e.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0557, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0485, "steps": 65 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/14ef4399e9eaf6ab84982330b2695be9.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/5e8a70a24df8668e3eddea0531ad99e5.json similarity index 91% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/14ef4399e9eaf6ab84982330b2695be9.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/5e8a70a24df8668e3eddea0531ad99e5.json index ff22fb4a9a392384af661673d45542e10968d56a..888fbc5f5c36ffdec95559f72265fb2a8f8a6f3c 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/14ef4399e9eaf6ab84982330b2695be9.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/5e8a70a24df8668e3eddea0531ad99e5.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0367, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0299, "steps": 64 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/23ea7b534e6e972e901f5d280822c447.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/7df9a56da14d9dd93c12da0522e8e8b3.json similarity index 91% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/23ea7b534e6e972e901f5d280822c447.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/7df9a56da14d9dd93c12da0522e8e8b3.json index 9e949102af53ca208400d66d954ab0a7e5ec4dc9..845dbcfd989ab1871ca9d0604925c0e6e261fe1d 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/23ea7b534e6e972e901f5d280822c447.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/7df9a56da14d9dd93c12da0522e8e8b3.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0622, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0329, "steps": 80 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/3a42861a3ebc3563932adaaefa80583d.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/80d8e9979c233523c50a19ebcad3be19.json similarity index 92% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/3a42861a3ebc3563932adaaefa80583d.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/80d8e9979c233523c50a19ebcad3be19.json index d3181803ea05726224233a31cef3965208d8b346..d02b72c658e1a0df71d40e8b465e5728d1de4482 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/3a42861a3ebc3563932adaaefa80583d.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/80d8e9979c233523c50a19ebcad3be19.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.2867, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.1793, "steps": 252 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/8bcc8ca7683995ab021498efdff9c7a9.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/8167f048a31fdace22ee03da7fa539af.json similarity index 91% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/8bcc8ca7683995ab021498efdff9c7a9.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/8167f048a31fdace22ee03da7fa539af.json index a6c42bf73f3fb69c0265f03dda16dd747f9a719f..8f661693c04653f377d96045a530ffee1b8517af 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/8bcc8ca7683995ab021498efdff9c7a9.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/8167f048a31fdace22ee03da7fa539af.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0197, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0209, "steps": 33 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/82b3f47a066db73685d212791359b54d.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/82b3f47a066db73685d212791359b54d.json new file mode 100644 index 0000000000000000000000000000000000000000..b452c7d49a58bb6dd979bc209e90dff56736f4fe --- /dev/null +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/82b3f47a066db73685d212791359b54d.json @@ -0,0 +1,2 @@ +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.348, + "steps": 212 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/845af4414c6bd5a5b8bb00092dfffa78.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/845af4414c6bd5a5b8bb00092dfffa78.json deleted file mode 100644 index d245def208eeac3469f6d3492be56d5d3f4f1cdd..0000000000000000000000000000000000000000 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/845af4414c6bd5a5b8bb00092dfffa78.json +++ /dev/null @@ -1,2 +0,0 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.1146, - "steps": 106 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/8982084a56561a53c5d6455bcda003af.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/85c0b453bc87d1ad6dfe2aa142c4b0ba.json similarity index 92% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/8982084a56561a53c5d6455bcda003af.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/85c0b453bc87d1ad6dfe2aa142c4b0ba.json index b3d102960bf3457c638a7b40f62061b6d185058b..2a1c1d97bb3f448afc7f3adfae2b7afbbe2d0767 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/8982084a56561a53c5d6455bcda003af.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/85c0b453bc87d1ad6dfe2aa142c4b0ba.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.395, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.2355, "steps": 267 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/12f261955534946a80dfa69cdf0af7df.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/951faf191dfc11e8fc646c586d96289c.json similarity index 72% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/12f261955534946a80dfa69cdf0af7df.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/951faf191dfc11e8fc646c586d96289c.json index 843b66a32693d2a086c9502b727c3e6ddb5e5017..3d82fce1aa03492447957b5ef223b606c1dcdfca 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/12f261955534946a80dfa69cdf0af7df.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/951faf191dfc11e8fc646c586d96289c.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.1377, - "steps": 133 } +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0784, + "steps": 119 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/f8d98bcd8d53476d7b4bcd5ee998a283.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/9ade3e7bb7e61fe51ea8379e0903d0a3.json similarity index 91% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/f8d98bcd8d53476d7b4bcd5ee998a283.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/9ade3e7bb7e61fe51ea8379e0903d0a3.json index 1920fce8363108a8eab70533220536771920434a..88509a32dbcf88199e487d664dfd0690efe9182e 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/f8d98bcd8d53476d7b4bcd5ee998a283.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/9ade3e7bb7e61fe51ea8379e0903d0a3.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0889, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.05, "steps": 95 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/0d901f10aad13b11e2481369a063c076.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/9cf655198880bef2ca355ed1f121fc66.json similarity index 72% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/0d901f10aad13b11e2481369a063c076.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/9cf655198880bef2ca355ed1f121fc66.json index 89a531e9caae449bab92994594cebaeeeac8e517..04e8c1bfa4e4e948d58f333afdfdfcb2f04955b0 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/0d901f10aad13b11e2481369a063c076.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/9cf655198880bef2ca355ed1f121fc66.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.3412, - "steps": 249 } +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.1134, + "steps": 135 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/9d2df333d71dd7cc761d785740777970.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/9d2df333d71dd7cc761d785740777970.json new file mode 100644 index 0000000000000000000000000000000000000000..29ddbb59ebe0c79473dd4b4b8f38971b1297b44e --- /dev/null +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/9d2df333d71dd7cc761d785740777970.json @@ -0,0 +1,2 @@ +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.3665, + "steps": 243 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/d10fb006c2e7ab1ae79ed39f7a2856e6.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/a01c8acaa455eb12c637dfaa78fb6281.json similarity index 91% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/d10fb006c2e7ab1ae79ed39f7a2856e6.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/a01c8acaa455eb12c637dfaa78fb6281.json index 991bdd6f20bb35a7df582e50b0d5d0dcdf4c0a7e..f505851df0b16b78a7074398035698c78702bdb0 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/d10fb006c2e7ab1ae79ed39f7a2856e6.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/a01c8acaa455eb12c637dfaa78fb6281.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.055, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0537, "steps": 65 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/eb9e8de8de87cc201e95fc1b82db0191.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/a2fed4c123e00a399b2a71264588ae3f.json similarity index 93% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/eb9e8de8de87cc201e95fc1b82db0191.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/a2fed4c123e00a399b2a71264588ae3f.json index 09a743ded655ba077979243585d58e89861ce0c3..021c0527cdcbdbbff2c7f0b935820ee6d72ad3d9 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/eb9e8de8de87cc201e95fc1b82db0191.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/a2fed4c123e00a399b2a71264588ae3f.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.057, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.053, "steps": 62 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/a4c1cf1b26ba59b95dce2092293d58df.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/a4c1cf1b26ba59b95dce2092293d58df.json new file mode 100644 index 0000000000000000000000000000000000000000..83fac27d56de5577d8693954d28397d3fdac08cd --- /dev/null +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/a4c1cf1b26ba59b95dce2092293d58df.json @@ -0,0 +1,2 @@ +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.2842, + "steps": 323 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/7293c9e0a0720923a5210c1362dd38f3.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/a71babb73b425cb72938455297d27098.json similarity index 92% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/7293c9e0a0720923a5210c1362dd38f3.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/a71babb73b425cb72938455297d27098.json index 1584919b4858e055a67d6284dc21fd9090248cfc..984ffc993a93a5f3de07e9c04c1c2fd5578bf25d 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/7293c9e0a0720923a5210c1362dd38f3.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/a71babb73b425cb72938455297d27098.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.1527, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.095, "steps": 139 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/2d6cb92f2fd6ce2467089566831ba3fa.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/b081be9daf7d73611002878d723b3594.json similarity index 91% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/2d6cb92f2fd6ce2467089566831ba3fa.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/b081be9daf7d73611002878d723b3594.json index f1fa2095778bb0350e9486c575aa7bf6133bc6e9..687204992bc710724e470dc88ef16dfafd81f291 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/2d6cb92f2fd6ce2467089566831ba3fa.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/b081be9daf7d73611002878d723b3594.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0407, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0342, "steps": 61 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/a5be279fac32f0b7fee94dffea8f8101.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/b6c50154bbca0d093a38a64d7c2bb3fe.json similarity index 91% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/a5be279fac32f0b7fee94dffea8f8101.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/b6c50154bbca0d093a38a64d7c2bb3fe.json index 3f6cb1870ec20e97a67c10493b274b68170b4f61..0824f2ae2922155d2d58fff8f36f3201ccdc1984 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/a5be279fac32f0b7fee94dffea8f8101.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/b6c50154bbca0d093a38a64d7c2bb3fe.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0269, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.017, "steps": 29 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/824309b24946e399494ae77d99d9da7d.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/bb264654a0f79375e32e1f67e7065442.json similarity index 91% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/824309b24946e399494ae77d99d9da7d.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/bb264654a0f79375e32e1f67e7065442.json index ec67bb2ba5b0058fd7c33398fe1bafedcfc810d7..719ae1a925db3c3838ef60199d4afc7a8d6e1caa 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/824309b24946e399494ae77d99d9da7d.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/bb264654a0f79375e32e1f67e7065442.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0495, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0351, "steps": 73 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/6c6d479ce89091eebd496b240d58507a.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/bcd2f5408ea8fd10bdf1a0bde16708e0.json similarity index 91% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/6c6d479ce89091eebd496b240d58507a.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/bcd2f5408ea8fd10bdf1a0bde16708e0.json index 4e61eb313dbd2970e2a5e9c4106a809e16864757..17778ee60e38cbf1cecd3270815799e8f9389711 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/6c6d479ce89091eebd496b240d58507a.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/bcd2f5408ea8fd10bdf1a0bde16708e0.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0858, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0701, "steps": 96 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/1958628752b3b6ef861b93e29a4b0740.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/c11b57a25c76c5aefd4f4ca106023f8d.json similarity index 91% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/1958628752b3b6ef861b93e29a4b0740.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/c11b57a25c76c5aefd4f4ca106023f8d.json index 811a5cae509221cb77c948ae7b771f3ad756e5fb..da4e3144b8fa5e1ec9e3c4944e41380cc0b4b816 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/1958628752b3b6ef861b93e29a4b0740.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/c11b57a25c76c5aefd4f4ca106023f8d.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0432, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0351, "steps": 54 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/5d7433204af8e481f7a8887889f7ce55.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/c2cb928753e5eb6454e63f3c29c88ec5.json similarity index 91% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/5d7433204af8e481f7a8887889f7ce55.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/c2cb928753e5eb6454e63f3c29c88ec5.json index 64f59330da434ee7786f06da4ef7121ddc40bfcc..2028373e9345f8a930255b6c56a876a449ab7b61 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/5d7433204af8e481f7a8887889f7ce55.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/c2cb928753e5eb6454e63f3c29c88ec5.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.078, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0746, "steps": 91 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/b660ee1efdfd8a16a79a7c33e707143b.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/c5ca73eda7b61e6faf847606cdfcf53e.json similarity index 92% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/b660ee1efdfd8a16a79a7c33e707143b.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/c5ca73eda7b61e6faf847606cdfcf53e.json index 781a6129b8f74d7ef4f21ed049b6c366314c0890..71af6217dcac1bafeaf7e1fc68e7250eab85c689 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/b660ee1efdfd8a16a79a7c33e707143b.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/c5ca73eda7b61e6faf847606cdfcf53e.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.1566, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0736, "steps": 133 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/27853ddb3ca2f0f4ad61cab2d03126b2.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/d14fb37372690722d97188281edbd253.json similarity index 92% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/27853ddb3ca2f0f4ad61cab2d03126b2.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/d14fb37372690722d97188281edbd253.json index 1c63c89a9db768c3849cfd1242320374e61da0a6..3180bf13001ddada1f6b0e9a04566fa649512f9f 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/27853ddb3ca2f0f4ad61cab2d03126b2.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/d14fb37372690722d97188281edbd253.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0966, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.082, "steps": 114 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/1a14c3c38306b325267f495a3b96cb22.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/d9f6b94c2290c22af167ebadf0b9c8c6.json similarity index 91% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/1a14c3c38306b325267f495a3b96cb22.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/d9f6b94c2290c22af167ebadf0b9c8c6.json index 20ecc6f41bfa8f743c6076fd2339a5f55ff55883..a808230480d5e152a1165c19cdab59e15fe13733 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/1a14c3c38306b325267f495a3b96cb22.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/d9f6b94c2290c22af167ebadf0b9c8c6.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0267, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0245, "steps": 19 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/b0313efe215d188230cbbcc2142dd6ed.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/dccefa8264c6127cfde9ab4406f616ce.json similarity index 92% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/b0313efe215d188230cbbcc2142dd6ed.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/dccefa8264c6127cfde9ab4406f616ce.json index 763be250ed6a99c835d242f0186dbef2cbf048b3..7e9b39297affebbd4dee1c1adee35ebce2fa450b 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/b0313efe215d188230cbbcc2142dd6ed.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/dccefa8264c6127cfde9ab4406f616ce.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0969, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0743, "steps": 121 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/e1345f50f3bc2ff3a80387d8ffbda596.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/e1345f50f3bc2ff3a80387d8ffbda596.json deleted file mode 100644 index 670b9e65e4fdeff23b2fe0ecf3bf9897e00af300..0000000000000000000000000000000000000000 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/e1345f50f3bc2ff3a80387d8ffbda596.json +++ /dev/null @@ -1,2 +0,0 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.522, - "steps": 209 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/e904a93fbfc0c12d33cae6f83d3efe25.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/e904a93fbfc0c12d33cae6f83d3efe25.json deleted file mode 100644 index c13a305f3f656d4b2e40e0f1bc8831cab45faff6..0000000000000000000000000000000000000000 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/e904a93fbfc0c12d33cae6f83d3efe25.json +++ /dev/null @@ -1,2 +0,0 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.1242, - "steps": 117 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/292e5c2995144e8404ec9571f6249f8e.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/eacfb63f26eb59d486f4b27509498428.json similarity index 91% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/292e5c2995144e8404ec9571f6249f8e.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/eacfb63f26eb59d486f4b27509498428.json index 7529b30fb9e14f8b9a92318dbfb02fc85b03f3f2..580d13e0c1ae1a7864667a84742278a023d9a8e3 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/292e5c2995144e8404ec9571f6249f8e.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/eacfb63f26eb59d486f4b27509498428.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0703, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0505, "steps": 82 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/e0bebedc1cebd03d88317637efe09d8d.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/f2ed0f1b93feba9c781bb7f0f2119c8e.json similarity index 91% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/e0bebedc1cebd03d88317637efe09d8d.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/f2ed0f1b93feba9c781bb7f0f2119c8e.json index 2108f99e49d78d8caeedb0b0b7397152aebc38b6..9084cb890c92bff37e7790dd8854866de7a66d70 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/e0bebedc1cebd03d88317637efe09d8d.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/f2ed0f1b93feba9c781bb7f0f2119c8e.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0367, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0292, "steps": 74 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/86a33c92a0d8181413212c0955f840e9.json b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/f5f0d5b17ac51b44de3a90bf08e03769.json similarity index 91% rename from src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/86a33c92a0d8181413212c0955f840e9.json rename to src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/f5f0d5b17ac51b44de3a90bf08e03769.json index 16e4b03a58d77d91047ccf2b09c95b3aa8bfdb67..89fb35478f0d7cde07da4b95511b69a54ab3dd94 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/86a33c92a0d8181413212c0955f840e9.json +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.0.session/cache/f5f0d5b17ac51b44de3a90bf08e03769.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0675, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0578, "steps": 77 } diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.res.oracle b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.res.oracle index a551c80874c5dc909fbc66b4c6143d3a0e826539..3d09ff0d0a33583400382e55c994a9c741c86a50 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.res.oracle +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/frama_c_hashtbl_solved.res.oracle @@ -118,7 +118,7 @@ eq_string 11 4 (52..64) 15 100% hash 6 1 (12..24) 7 100% size 2 - 2 100% init 8 5 (80..104) 13 100% -add 24 15 (208..256) 39 100% +add 24 15 (224..272) 39 100% mem_binding 18 8 (800..896) 26 100% ------------------------------------------------------------- [wp] Running WP plugin... diff --git a/src/plugins/wp/tests/wp_hoare/oracle_qualif/logicarr.0.session/cache/d30ddbd7a04ea0b23fb737f7bf348101.json b/src/plugins/wp/tests/wp_hoare/oracle_qualif/logicarr.0.session/cache/4f9da7c614ebe0bcfe98b06701074b7d.json similarity index 91% rename from src/plugins/wp/tests/wp_hoare/oracle_qualif/logicarr.0.session/cache/d30ddbd7a04ea0b23fb737f7bf348101.json rename to src/plugins/wp/tests/wp_hoare/oracle_qualif/logicarr.0.session/cache/4f9da7c614ebe0bcfe98b06701074b7d.json index 9331760469135b61493efde123dbffb94105ab0f..58c7bc2c48c3295f6a2ae0b392313c0c4710a710 100644 --- a/src/plugins/wp/tests/wp_hoare/oracle_qualif/logicarr.0.session/cache/d30ddbd7a04ea0b23fb737f7bf348101.json +++ b/src/plugins/wp/tests/wp_hoare/oracle_qualif/logicarr.0.session/cache/4f9da7c614ebe0bcfe98b06701074b7d.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0345, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.034, "steps": 39 } diff --git a/src/plugins/wp/tests/wp_hoare/oracle_qualif/logicarr.0.session/cache/41a9a847c06c86a1a870724f991b1ea0.json b/src/plugins/wp/tests/wp_hoare/oracle_qualif/logicarr.0.session/cache/e0b658eb338f06deb3c8280c99a8d303.json similarity index 91% rename from src/plugins/wp/tests/wp_hoare/oracle_qualif/logicarr.0.session/cache/41a9a847c06c86a1a870724f991b1ea0.json rename to src/plugins/wp/tests/wp_hoare/oracle_qualif/logicarr.0.session/cache/e0b658eb338f06deb3c8280c99a8d303.json index eafe55cabc3c0729cfc68b994dc74d7954af3128..52fc00f8675c5bdd11e48c24d9944700b14a8f90 100644 --- a/src/plugins/wp/tests/wp_hoare/oracle_qualif/logicarr.0.session/cache/41a9a847c06c86a1a870724f991b1ea0.json +++ b/src/plugins/wp/tests/wp_hoare/oracle_qualif/logicarr.0.session/cache/e0b658eb338f06deb3c8280c99a8d303.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0378, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0443, "steps": 35 } diff --git a/src/plugins/wp/tests/wp_hoare/oracle_qualif/logicarr.0.session/cache/38f01fcc3946eedc95de0627fa9e9c8e.json b/src/plugins/wp/tests/wp_hoare/oracle_qualif/logicarr.0.session/cache/e9033d4c1c2df4da5f6adda51fecf8a5.json similarity index 91% rename from src/plugins/wp/tests/wp_hoare/oracle_qualif/logicarr.0.session/cache/38f01fcc3946eedc95de0627fa9e9c8e.json rename to src/plugins/wp/tests/wp_hoare/oracle_qualif/logicarr.0.session/cache/e9033d4c1c2df4da5f6adda51fecf8a5.json index bb3d1e3d493e679341d7c3935a1c7feea894c897..ea410c31a008fd16925e4a776e523cfc93d5902f 100644 --- a/src/plugins/wp/tests/wp_hoare/oracle_qualif/logicarr.0.session/cache/38f01fcc3946eedc95de0627fa9e9c8e.json +++ b/src/plugins/wp/tests/wp_hoare/oracle_qualif/logicarr.0.session/cache/e9033d4c1c2df4da5f6adda51fecf8a5.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0442, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.027, "steps": 39 } diff --git a/src/plugins/wp/tests/wp_plugin/oracle/inductive.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle/inductive.res.oracle index dd2765302d270cbe5e050c1f726d2217e2850cc0..b4e08f2f351ade114947266fc0b50e60efdaefef 100644 --- a/src/plugins/wp/tests/wp_plugin/oracle/inductive.res.oracle +++ b/src/plugins/wp/tests/wp_plugin/oracle/inductive.res.oracle @@ -6,7 +6,7 @@ [wp:print-generated] "WPOUT/typed/Compound.v" (* ---------------------------------------------------------- *) - (* --- Memory Compound Updates --- *) + (* --- Memory Compound Loader --- *) (* ---------------------------------------------------------- *) Require Import ZArith. diff --git a/src/plugins/wp/tests/wp_region/README.md b/src/plugins/wp/tests/wp_region/README.md new file mode 100644 index 0000000000000000000000000000000000000000..54aa9413764131ff977dc1b9539a6f01c5c599fa --- /dev/null +++ b/src/plugins/wp/tests/wp_region/README.md @@ -0,0 +1,13 @@ +# Testing WP/Region + +Use `./fc.sh -h|--help` to visualize the output before commiting changes. + +# Recommanded workflow + +With default configuration, put a single 'job' function in each test file. +Then: + +1. Run `./fc.sh test.i -r` to visualize the region graph and check the proofs +2. Run `./fc.sh test.i -u` to update the region-graph oracle (creates also the oracle directories) +3. Run `./fc.sh test.i -t` to check test is OK (eventually use `-t -show` or `-t -update`) +4. Run `./fc.sh test.i -q` to check qualif test is OK diff --git a/src/plugins/wp/tests/wp_region/annot.i b/src/plugins/wp/tests/wp_region/annot.i new file mode 100644 index 0000000000000000000000000000000000000000..23463af75a974c021bf5955e9689f873ac0c053e --- /dev/null +++ b/src/plugins/wp/tests/wp_region/annot.i @@ -0,0 +1,63 @@ +/* run.config + OPT: -region-annot -print + EXECNOW: @frama-c@ -region-annot -print @PTEST_DIR@/@PTEST_NAME@.i -ocode @PTEST_DIR@/@PTEST_NAME@/a.i + EXECNOW: @frama-c@ -region-annot -print @PTEST_DIR@/@PTEST_NAME@/a.i -ocode @PTEST_DIR@/@PTEST_NAME@/b.i > /dev/null + EXECNOW: diff @PTEST_DIR@/@PTEST_NAME@/a.i @PTEST_DIR@/@PTEST_NAME@/b.i > /dev/null + */ + +/* run.config_qualif + DONTRUN: +*/ + +// This test only checks that annotation are correctly parsed & printed + +typedef struct N { double v ; int s ; } *SN ; +typedef struct L { int v ; int s ; } *SL ; + +typedef struct Block { + SN prm ; + SN inp1 ; + SN inp2 ; + SN inp3 ; + SN out1 ; + SN out2 ; + SN out3 ; + SL idx1 ; + SL idx2 ; + SL idx3 ; + SN sum ; +} FB ; + +//@ region *fb ; +void fb_ADD(FB *fb) +{ + fb->out1->v = fb->out1->v + fb->out2->v ; + fb->out1->s = fb->out1->s | fb->out2->s ; +} + +/*@ + region IN: (fb->inp1 .. fb->inp3), \pattern{PMEM} ; + region OUT: (fb->out1 .. fb->out3), \pattern{PVECTOR} ; + region IDX: (fb->idx1 .. fb->idx3), \pattern{PVECTOR} ; + */ +void fb_SORT(FB *fb) +{ + SN *inp = &(fb->inp1) ; + SN *out = &(fb->out1) ; + SL *idx = &(fb->idx1) ; + + for (int i = 0; i < 3; i++) { + out[i]->v = inp[i]->v + fb->prm->v ; + out[i]->s = 0 ; + idx[i]->v = inp[i]->s ; + idx[i]->s = 0 ; + } + + fb->sum->v = + fb->out1->v + + fb->out2->v + + fb->out3->v ; + + fb->sum->s = 0 ; + +} diff --git a/src/plugins/wp/tests/wp_region/annot/a.i b/src/plugins/wp/tests/wp_region/annot/a.i new file mode 100644 index 0000000000000000000000000000000000000000..88fa61563c1be65c5d7db0846e8cb9298e45d8b1 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/annot/a.i @@ -0,0 +1,58 @@ +/* Generated by Frama-C */ +struct N { + double v ; + int s ; +}; +typedef struct N *SN; +struct L { + int v ; + int s ; +}; +typedef struct L *SL; +struct Block { + SN prm ; + SN inp1 ; + SN inp2 ; + SN inp3 ; + SN out1 ; + SN out2 ; + SN out3 ; + SL idx1 ; + SL idx2 ; + SL idx3 ; + SN sum ; +}; +typedef struct Block FB; +/*@ region *fb; */ +void fb_ADD(FB *fb) +{ + (fb->out1)->v += (fb->out2)->v; + (fb->out1)->s |= (fb->out2)->s; + return; +} + +/*@ region IN: \pattern{PMEM}, (fb->inp1..fb->inp3); + region OUT: \pattern{PVECTOR}, (fb->out1..fb->out3); + region IDX: \pattern{PVECTOR}, (fb->idx1..fb->idx3); + */ +void fb_SORT(FB *fb) +{ + SN *inp = & fb->inp1; + SN *out = & fb->out1; + SL *idx = & fb->idx1; + { + int i = 0; + while (i < 3) { + (*(out + i))->v = (*(inp + i))->v + (fb->prm)->v; + (*(out + i))->s = 0; + (*(idx + i))->v = (*(inp + i))->s; + (*(idx + i))->s = 0; + i ++; + } + } + (fb->sum)->v = ((fb->out1)->v + (fb->out2)->v) + (fb->out3)->v; + (fb->sum)->s = 0; + return; +} + + diff --git a/src/plugins/wp/tests/wp_region/annot/b.i b/src/plugins/wp/tests/wp_region/annot/b.i new file mode 100644 index 0000000000000000000000000000000000000000..88fa61563c1be65c5d7db0846e8cb9298e45d8b1 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/annot/b.i @@ -0,0 +1,58 @@ +/* Generated by Frama-C */ +struct N { + double v ; + int s ; +}; +typedef struct N *SN; +struct L { + int v ; + int s ; +}; +typedef struct L *SL; +struct Block { + SN prm ; + SN inp1 ; + SN inp2 ; + SN inp3 ; + SN out1 ; + SN out2 ; + SN out3 ; + SL idx1 ; + SL idx2 ; + SL idx3 ; + SN sum ; +}; +typedef struct Block FB; +/*@ region *fb; */ +void fb_ADD(FB *fb) +{ + (fb->out1)->v += (fb->out2)->v; + (fb->out1)->s |= (fb->out2)->s; + return; +} + +/*@ region IN: \pattern{PMEM}, (fb->inp1..fb->inp3); + region OUT: \pattern{PVECTOR}, (fb->out1..fb->out3); + region IDX: \pattern{PVECTOR}, (fb->idx1..fb->idx3); + */ +void fb_SORT(FB *fb) +{ + SN *inp = & fb->inp1; + SN *out = & fb->out1; + SL *idx = & fb->idx1; + { + int i = 0; + while (i < 3) { + (*(out + i))->v = (*(inp + i))->v + (fb->prm)->v; + (*(out + i))->s = 0; + (*(idx + i))->v = (*(inp + i))->s; + (*(idx + i))->s = 0; + i ++; + } + } + (fb->sum)->v = ((fb->out1)->v + (fb->out2)->v) + (fb->out3)->v; + (fb->sum)->s = 0; + return; +} + + diff --git a/src/plugins/wp/tests/wp_region/array1.i b/src/plugins/wp/tests/wp_region/array1.i new file mode 100644 index 0000000000000000000000000000000000000000..eac00551a13634c34e79f284c7a0bebb362b0591 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/array1.i @@ -0,0 +1,8 @@ +//@ region *p, *q ; +int job( int n, int * p , int * q ) +{ + int s = 0 ; + for (int k = 0; k < n; k++) + s += p[k] * q[k] ; + return s ; +} diff --git a/src/plugins/wp/tests/wp_region/array1.i.0.report.json b/src/plugins/wp/tests/wp_region/array1.i.0.report.json new file mode 100644 index 0000000000000000000000000000000000000000..19765bd501b636fce433540d9e6735f51d66151d --- /dev/null +++ b/src/plugins/wp/tests/wp_region/array1.i.0.report.json @@ -0,0 +1 @@ +null diff --git a/src/plugins/wp/tests/wp_region/array2.i b/src/plugins/wp/tests/wp_region/array2.i new file mode 100644 index 0000000000000000000000000000000000000000..9b8ded175cb723b3fc41dede06d21632206f6e08 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/array2.i @@ -0,0 +1,8 @@ +//@ region *p; region *q ; +int job( int n, int * p , int * q ) +{ + int s = 0 ; + for (int k = 0; k < n; k++) + s += p[k] * q[k] ; + return s ; +} diff --git a/src/plugins/wp/tests/wp_region/array2.i.0.report.json b/src/plugins/wp/tests/wp_region/array2.i.0.report.json new file mode 100644 index 0000000000000000000000000000000000000000..19765bd501b636fce433540d9e6735f51d66151d --- /dev/null +++ b/src/plugins/wp/tests/wp_region/array2.i.0.report.json @@ -0,0 +1 @@ +null diff --git a/src/plugins/wp/tests/wp_region/array3.i b/src/plugins/wp/tests/wp_region/array3.i new file mode 100644 index 0000000000000000000000000000000000000000..5035254bf8aaa6b247354033761c93d685946871 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/array3.i @@ -0,0 +1,6 @@ +int job( int * p ) +{ + int s = 0 ; + while (!*p) { s+=*p ; p++; } + return s; +} diff --git a/src/plugins/wp/tests/wp_region/array3.i.0.report.json b/src/plugins/wp/tests/wp_region/array3.i.0.report.json new file mode 100644 index 0000000000000000000000000000000000000000..19765bd501b636fce433540d9e6735f51d66151d --- /dev/null +++ b/src/plugins/wp/tests/wp_region/array3.i.0.report.json @@ -0,0 +1 @@ +null diff --git a/src/plugins/wp/tests/wp_region/array4.i b/src/plugins/wp/tests/wp_region/array4.i new file mode 100644 index 0000000000000000000000000000000000000000..bc3b3b68375becdfef9d8e8bbffcc76fe9d9dc30 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/array4.i @@ -0,0 +1,7 @@ +int job( int * p ) +{ + int s = 0 ; + int *q = p ; + while (!*q) { s+=*q ; q++; } + return s; +} diff --git a/src/plugins/wp/tests/wp_region/array4.i.0.report.json b/src/plugins/wp/tests/wp_region/array4.i.0.report.json new file mode 100644 index 0000000000000000000000000000000000000000..19765bd501b636fce433540d9e6735f51d66151d --- /dev/null +++ b/src/plugins/wp/tests/wp_region/array4.i.0.report.json @@ -0,0 +1 @@ +null diff --git a/src/plugins/wp/tests/wp_region/array5.i b/src/plugins/wp/tests/wp_region/array5.i new file mode 100644 index 0000000000000000000000000000000000000000..9fd9f2aa9f6e13083b6fb42918c613bec93e32c1 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/array5.i @@ -0,0 +1,7 @@ +int job( int * p , int * q ) +{ + int s = 0 ; + q = p ; + while (!*q) { s+=*p ; p[s]; q++; } + return s; +} diff --git a/src/plugins/wp/tests/wp_region/array5.i.0.report.json b/src/plugins/wp/tests/wp_region/array5.i.0.report.json new file mode 100644 index 0000000000000000000000000000000000000000..19765bd501b636fce433540d9e6735f51d66151d --- /dev/null +++ b/src/plugins/wp/tests/wp_region/array5.i.0.report.json @@ -0,0 +1 @@ +null diff --git a/src/plugins/wp/tests/wp_region/array6.i b/src/plugins/wp/tests/wp_region/array6.i new file mode 100644 index 0000000000000000000000000000000000000000..8136a3c37b0541a2fce551b0c69651d1214258d0 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/array6.i @@ -0,0 +1,9 @@ +int A[10] ; +int B[20] ; + +int job(int k) +{ + int s = 0 ; + while (!A[k]) { s += A[k]; k++; } + return s ; +} diff --git a/src/plugins/wp/tests/wp_region/array6.i.0.report.json b/src/plugins/wp/tests/wp_region/array6.i.0.report.json new file mode 100644 index 0000000000000000000000000000000000000000..19765bd501b636fce433540d9e6735f51d66151d --- /dev/null +++ b/src/plugins/wp/tests/wp_region/array6.i.0.report.json @@ -0,0 +1 @@ +null diff --git a/src/plugins/wp/tests/wp_region/array7.i b/src/plugins/wp/tests/wp_region/array7.i new file mode 100644 index 0000000000000000000000000000000000000000..8178ba26808b9319194fdf1966fd1a6b1ce531cd --- /dev/null +++ b/src/plugins/wp/tests/wp_region/array7.i @@ -0,0 +1,10 @@ +int A[10] ; +int B[20] ; + +int job(int k) +{ + int s = 0 ; + int * p = A+k ; + while (!*p) { s += *p; p++; } + return s ; +} diff --git a/src/plugins/wp/tests/wp_region/array7.i.0.report.json b/src/plugins/wp/tests/wp_region/array7.i.0.report.json new file mode 100644 index 0000000000000000000000000000000000000000..19765bd501b636fce433540d9e6735f51d66151d --- /dev/null +++ b/src/plugins/wp/tests/wp_region/array7.i.0.report.json @@ -0,0 +1 @@ +null diff --git a/src/plugins/wp/tests/wp_region/array8.i b/src/plugins/wp/tests/wp_region/array8.i new file mode 100644 index 0000000000000000000000000000000000000000..2ded4d8661dcd95ee85c15161272ee6de7fc3831 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/array8.i @@ -0,0 +1,10 @@ +int A[10] ; +int B[20] ; + +int job(int c,int k) +{ + int s = 0 ; + int * p = (c?A:B)+k ; + while (!*p) { s += *p; p++; } + return s ; +} diff --git a/src/plugins/wp/tests/wp_region/array8.i.0.report.json b/src/plugins/wp/tests/wp_region/array8.i.0.report.json new file mode 100644 index 0000000000000000000000000000000000000000..19765bd501b636fce433540d9e6735f51d66151d --- /dev/null +++ b/src/plugins/wp/tests/wp_region/array8.i.0.report.json @@ -0,0 +1 @@ +null diff --git a/src/plugins/wp/tests/wp_region/fb_ADD.i b/src/plugins/wp/tests/wp_region/fb_ADD.i new file mode 100644 index 0000000000000000000000000000000000000000..3bab8bad0655f3fcce7b968520c2a3558895f45b --- /dev/null +++ b/src/plugins/wp/tests/wp_region/fb_ADD.i @@ -0,0 +1,25 @@ +typedef struct N { double v ; int s ; } *SN ; +typedef struct L { int v ; int s ; } *SL ; + +typedef struct Block { + SN prm ; + SN inp1 ; + SN inp2 ; + SN inp3 ; + SN out1 ; + SN out2 ; + SN out3 ; + SL idx1 ; + SL idx2 ; + SL idx3 ; + SN sum ; +} FB ; + +/*@ + region A: fb ; +*/ +void job(FB *fb) +{ + fb->out1->v = fb->out1->v + fb->out2->v ; + fb->out1->s = fb->out1->s | fb->out2->s ; +} diff --git a/src/plugins/wp/tests/wp_region/fb_ADD.i.0.report.json b/src/plugins/wp/tests/wp_region/fb_ADD.i.0.report.json new file mode 100644 index 0000000000000000000000000000000000000000..19765bd501b636fce433540d9e6735f51d66151d --- /dev/null +++ b/src/plugins/wp/tests/wp_region/fb_ADD.i.0.report.json @@ -0,0 +1 @@ +null diff --git a/src/plugins/wp/tests/wp_region/fb_SORT.i b/src/plugins/wp/tests/wp_region/fb_SORT.i new file mode 100644 index 0000000000000000000000000000000000000000..b6289be1c9e2df06aad82783823a748864535063 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/fb_SORT.i @@ -0,0 +1,44 @@ +typedef struct N { double v ; int s ; } *SN ; +typedef struct L { int v ; int s ; } *SL ; + +typedef struct Block { + SN prm ; + SN inp1 ; + SN inp2 ; + SN inp3 ; + SN out1 ; + SN out2 ; + SN out3 ; + SL idx1 ; + SL idx2 ; + SL idx3 ; + SN sum ; +} FB ; + +/*@ + region Shared: *(fb->inp1 .. fb->inp3); + region IN: (fb->inp1 .. fb->inp3); + region OUT: (fb->out1 .. fb->out3); + region IDX: (fb->idx1 .. fb->idx3); + */ +void job(FB *fb) +{ + SN *inp = &(fb->inp1) ; + SN *out = &(fb->out1) ; + SL *idx = &(fb->idx1) ; + + for (int i = 0; i < 3; i++) { + out[i]->v = inp[i]->v + fb->prm->v ; + out[i]->s = 0 ; + idx[i]->v = inp[i]->s ; + idx[i]->s = 0 ; + } + + fb->sum->v = + fb->out1->v + + fb->out2->v + + fb->out3->v ; + + fb->sum->s = 0 ; + +} diff --git a/src/plugins/wp/tests/wp_region/fb_SORT.i.0.report.json b/src/plugins/wp/tests/wp_region/fb_SORT.i.0.report.json new file mode 100644 index 0000000000000000000000000000000000000000..19765bd501b636fce433540d9e6735f51d66151d --- /dev/null +++ b/src/plugins/wp/tests/wp_region/fb_SORT.i.0.report.json @@ -0,0 +1 @@ +null diff --git a/src/plugins/wp/tests/wp_region/fc.sh b/src/plugins/wp/tests/wp_region/fc.sh new file mode 100755 index 0000000000000000000000000000000000000000..f070fd5bb55354fb5e143e54c8b4bdc752c274a1 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/fc.sh @@ -0,0 +1,109 @@ +# Visualize output of WP/Region tests + +OPT= +CMD=fc +TEST="<none>" +NAME="none" +OPEN="none" +DEFAULT="-wp-msg-key dot,chunk,roots,garbled" + +if type open &> /dev/null ; then + OPEN=open +elif type xpdf &> /dev/null ; then + OPEN=xpdf +elif type evince &> /dev/null ; then + OPEN=evince +fi + +while [ "$1" != "" ]; +do + case $1 in + "-h"|"--help") + echo "fc.sh [options...] <test.[ic]>" ; + echo " -h,--help help and exit" ; + echo " -D,--delete clean output directory and exit" ; + echo " -g,--gui run in Frama-C Gui" ; + echo " -r,--region visualize region graph" ; + echo " -u,--update commit region graph in oracle" ; + echo " -t,--test run ptests.opt on test file (or all files)" ; + echo " -q,--qualif run ptests.opt with test-config qualif" ; + echo " --open <cmd> opens pdf with '<cmd>'" ; + echo " -k <keys> set message keys" ; + echo " * any other Frama-C options" ; + exit 0 ; + ;; + *.i) TEST=${1}; NAME=${TEST/.i/} ;; + *.c) TEST=${1}; NAME=${TEST/.c/} ;; + "-D"|"--delete") CMD=delete ;; + "-u"|"--update") CMD=update ;; + "-t"|"--test") CMD=test ;; + "-q"|"--qualif") CMD=qualif ;; + "-g"|"--gui") CMD=gui ;; + "-r"|"--region") CMD=region ; OPT="${OPT} -wp-msg-key pdf" ;; + "--open") shift ; CMD=region ; OPEN=${1} ;; + "-k") shift ; CMD=region ; DEFAULT="" ; OPT="${OPT} -wp-msg-key $1" ;; + *) + OPT="${OPT} $1" + ;; + esac + shift +done + +BIN=../../../../../bin +WP="-wp-region -wp-model Region -wp-fct job -wp-out result/${NAME}" + +case $CMD in + "fc"|"region") + echo "Running frama-c $TEST" + $BIN/frama-c $WP $TEST $DEFAULT $OPT + PDF="./result/${NAME}/region/job.pdf" + if [ $CMD = region ] && [ -f $PDF ] + then + if [ $OPEN != none ] ; then + echo "Source File:" + cat $TEST + $OPEN $PDF + else + echo "No command found for opening $PDF" + echo "Use --open <cmd> option" + fi + fi + ;; + "gui") + echo "Running frama-c $TEST (Gui)" + $BIN/frama-c-gui $WP $TEST $OPT + ;; + "test") + if [ $TEST == "<none>" ] + then + echo "Testing directory..." + ( cd ../.. ; ../../../bin/ptests.opt tests/wp_region > /dev/null ) + for test in *.i + do + name=${test/.i/} + oracle=oracle/$name/region/job.dot + result=result/$name/region/job.dot + if [ -f $oracle ] && !( diff -q $oracle $result > /dev/null ) + then + echo "Diff: ./fc.sh $test -r" + fi + done + else + echo "Testing $TEST$OPT" + ( cd ../.. ; ../../../bin/ptests.opt tests/wp_region/$TEST $OPT ) + fi + ;; + "qualif") + echo "Testing $TEST -config qualif$OPT" + ( cd ../.. ; ../../../bin/ptests.opt tests/wp_region/$TEST -config qualif $OPT ) + ;; + "update") + echo "Update './oracle/$NAME/region/job.dot" + mkdir -p ./oracle/$NAME/region + cp -f ./result/$NAME/region/job.dot ./oracle/$NAME/region/ + ;; + "delete") + echo "Cleaning './result/$NAME'" + rm -fr result/$NAME/* + ;; +esac diff --git a/src/plugins/wp/tests/wp_region/garbled.i b/src/plugins/wp/tests/wp_region/garbled.i new file mode 100644 index 0000000000000000000000000000000000000000..6b703ba4245ba130e45827ac182b69f5dd03dfdd --- /dev/null +++ b/src/plugins/wp/tests/wp_region/garbled.i @@ -0,0 +1,6 @@ + + +float job(int *p,int *q) +{ + return *q + *(float*)p + *p ; +} diff --git a/src/plugins/wp/tests/wp_region/garbled.i.0.report.json b/src/plugins/wp/tests/wp_region/garbled.i.0.report.json new file mode 100644 index 0000000000000000000000000000000000000000..19765bd501b636fce433540d9e6735f51d66151d --- /dev/null +++ b/src/plugins/wp/tests/wp_region/garbled.i.0.report.json @@ -0,0 +1 @@ +null diff --git a/src/plugins/wp/tests/wp_region/index.i b/src/plugins/wp/tests/wp_region/index.i new file mode 100644 index 0000000000000000000000000000000000000000..6151de509bc5b4fc3eb172d09db656921aae72fb --- /dev/null +++ b/src/plugins/wp/tests/wp_region/index.i @@ -0,0 +1,6 @@ +int A[3][4][5] ; + +int job(int i,int j,int k) +{ + return A[i][j][k]; +} diff --git a/src/plugins/wp/tests/wp_region/index.i.0.report.json b/src/plugins/wp/tests/wp_region/index.i.0.report.json new file mode 100644 index 0000000000000000000000000000000000000000..19765bd501b636fce433540d9e6735f51d66151d --- /dev/null +++ b/src/plugins/wp/tests/wp_region/index.i.0.report.json @@ -0,0 +1 @@ +null diff --git a/src/plugins/wp/tests/wp_region/matrix.i b/src/plugins/wp/tests/wp_region/matrix.i new file mode 100644 index 0000000000000000000000000000000000000000..f5133222090c0c4e7e9bfc09ca31aa381523eb44 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/matrix.i @@ -0,0 +1,8 @@ +void job( int cols , int rows , int ** m , int * v , int * r ) +{ + for (int i = 0; i < rows; i++) { + r[i] = 0 ; + for (int j = 0; j < cols; j++) + r[i] += m[i][j] * v[j] ; + } +} diff --git a/src/plugins/wp/tests/wp_region/matrix.i.0.report.json b/src/plugins/wp/tests/wp_region/matrix.i.0.report.json new file mode 100644 index 0000000000000000000000000000000000000000..19765bd501b636fce433540d9e6735f51d66151d --- /dev/null +++ b/src/plugins/wp/tests/wp_region/matrix.i.0.report.json @@ -0,0 +1 @@ +null diff --git a/src/plugins/wp/tests/wp_region/oracle/annot.res.oracle b/src/plugins/wp/tests/wp_region/oracle/annot.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..d552bd47df89c1ee23ac54de7ea541b3e6e9d95b --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/annot.res.oracle @@ -0,0 +1,59 @@ +[kernel] Parsing tests/wp_region/annot.i (no preprocessing) +/* Generated by Frama-C */ +struct N { + double v ; + int s ; +}; +typedef struct N *SN; +struct L { + int v ; + int s ; +}; +typedef struct L *SL; +struct Block { + SN prm ; + SN inp1 ; + SN inp2 ; + SN inp3 ; + SN out1 ; + SN out2 ; + SN out3 ; + SL idx1 ; + SL idx2 ; + SL idx3 ; + SN sum ; +}; +typedef struct Block FB; +/*@ region *fb; */ +void fb_ADD(FB *fb) +{ + (fb->out1)->v += (fb->out2)->v; + (fb->out1)->s |= (fb->out2)->s; + return; +} + +/*@ region IN: \pattern{PMEM}, (fb->inp1..fb->inp3); + region OUT: \pattern{PVECTOR}, (fb->out1..fb->out3); + region IDX: \pattern{PVECTOR}, (fb->idx1..fb->idx3); + */ +void fb_SORT(FB *fb) +{ + SN *inp = & fb->inp1; + SN *out = & fb->out1; + SL *idx = & fb->idx1; + { + int i = 0; + while (i < 3) { + (*(out + i))->v = (*(inp + i))->v + (fb->prm)->v; + (*(out + i))->s = 0; + (*(idx + i))->v = (*(inp + i))->s; + (*(idx + i))->s = 0; + i ++; + } + } + (fb->sum)->v = ((fb->out1)->v + (fb->out2)->v) + (fb->out3)->v; + (fb->sum)->s = 0; + return; +} + + diff --git a/src/plugins/wp/tests/wp_region/oracle/array1.res.oracle b/src/plugins/wp/tests/wp_region/oracle/array1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..4987dd9ae45263a17a6338e3a4cb844be4876e93 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/array1.res.oracle @@ -0,0 +1,4 @@ +[kernel] Parsing tests/wp_region/array1.i (no preprocessing) +[wp] Region Graph: tests/wp_region/result/array1/region/job.dot +[wp] Running WP plugin... +[wp] Warning: Missing RTE guards diff --git a/src/plugins/wp/tests/wp_region/oracle/array1/region/job.dot b/src/plugins/wp/tests/wp_region/oracle/array1/region/job.dot new file mode 100644 index 0000000000000000000000000000000000000000..8061a50b2de13b2a37de192630ce8e3dc7ca4ba7 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/array1/region/job.dot @@ -0,0 +1,57 @@ +digraph "job" { + rankdir="LR" ; + node [ fontname="monospace" ]; + edge [ fontname="monospace" ]; + V000 [ label="n", shape="cds", style="filled", fillcolor="yellow" ]; + V000:e -> A000 ; + V001 [ label="p", shape="cds", style="filled", fillcolor="yellow" ]; + V001:e -> A001 ; + V002 [ label="q", shape="cds", style="filled", fillcolor="yellow" ]; + V002:e -> A002 ; + V003 [ label="s", shape="cds", style="filled", fillcolor="yellow" ]; + V003:e -> A003 ; + V004 [ label="k", shape="cds", style="filled", fillcolor="yellow" ]; + V004:e -> A004 ; + A000 [ label="R", shape="oval", fillcolor="green", style="filled" ]; + _005 [ label="roots:&n", style="filled", color="lightblue", shape="box" ]; + { rank=same; A000; _005; } + _005 -> A000 [ arrowhead="tee" ]; + _006 [ shape="record", label="Var sint32" ]; + A000 -> _006:w [ arrowhead="tee" ]; + A001 [ label="D", shape="oval" ]; + _007 [ label="roots:&p", style="filled", color="lightblue", shape="box" ]; + { rank=same; A001; _007; } + _007 -> A001 [ arrowhead="tee" ]; + _008 [ shape="record", label="<_p1> Ref" ]; + _008:_p1 -> A005:w [ taillabel="[..]", labeldistance="1.7", + labelangle="+40", color="red" + ]; + A001 -> _008:w [ arrowhead="tee" ]; + A002 [ label="D", shape="oval" ]; + _009 [ label="roots:&q", style="filled", color="lightblue", shape="box" ]; + { rank=same; A002; _009; } + _009 -> A002 [ arrowhead="tee" ]; + _010 [ shape="record", label="<_p1> Ref" ]; + _010:_p1 -> A005:w [ taillabel="[..]", labeldistance="1.7", + labelangle="+40", color="red" + ]; + A002 -> _010:w [ arrowhead="tee" ]; + A003 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _011 [ shape="record", label="Var sint32" ]; + A003 -> _011:w [ arrowhead="tee" ]; + A004 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _012 [ shape="record", label="Var sint32" ]; + A004 -> _012:w [ arrowhead="tee" ]; + A005 [ label="R[]&", shape="oval", fillcolor="orange", style="filled" ]; + _013 [ label="roots:*", style="filled", color="lightblue", shape="box" ]; + { rank=same; A005; _013; } + _013 -> A005 [ arrowhead="tee" ]; + _014 [ shape="record", label="Mem sint32" ]; + A005 -> _014:w [ arrowhead="tee" ]; + R015 [ label="\\result", shape="tab", style="filled", fillcolor="yellow" ]; + { rank=same; R015; A006; } + R015 -> A006 ; + A006 [ label="W", shape="oval", fillcolor="green", style="filled" ]; + _016 [ shape="record", label="Var sint32" ]; + A006 -> _016:w [ arrowhead="tee" ]; +} diff --git a/src/plugins/wp/tests/wp_region/oracle/array2.res.oracle b/src/plugins/wp/tests/wp_region/oracle/array2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..b724073ea5e6c6a7fac7738b6d831e6fc1e177ca --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/array2.res.oracle @@ -0,0 +1,4 @@ +[kernel] Parsing tests/wp_region/array2.i (no preprocessing) +[wp] Region Graph: tests/wp_region/result/array2/region/job.dot +[wp] Running WP plugin... +[wp] Warning: Missing RTE guards diff --git a/src/plugins/wp/tests/wp_region/oracle/array2/region/job.dot b/src/plugins/wp/tests/wp_region/oracle/array2/region/job.dot new file mode 100644 index 0000000000000000000000000000000000000000..4e9b35936cb28e85a2e52c1329c3263720bd15f5 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/array2/region/job.dot @@ -0,0 +1,63 @@ +digraph "job" { + rankdir="LR" ; + node [ fontname="monospace" ]; + edge [ fontname="monospace" ]; + V000 [ label="n", shape="cds", style="filled", fillcolor="yellow" ]; + V000:e -> A000 ; + V001 [ label="p", shape="cds", style="filled", fillcolor="yellow" ]; + V001:e -> A001 ; + V002 [ label="q", shape="cds", style="filled", fillcolor="yellow" ]; + V002:e -> A002 ; + V003 [ label="s", shape="cds", style="filled", fillcolor="yellow" ]; + V003:e -> A003 ; + V004 [ label="k", shape="cds", style="filled", fillcolor="yellow" ]; + V004:e -> A004 ; + A000 [ label="R", shape="oval", fillcolor="green", style="filled" ]; + _005 [ label="roots:&n", style="filled", color="lightblue", shape="box" ]; + { rank=same; A000; _005; } + _005 -> A000 [ arrowhead="tee" ]; + _006 [ shape="record", label="Var sint32" ]; + A000 -> _006:w [ arrowhead="tee" ]; + A001 [ label="D", shape="oval" ]; + _007 [ label="roots:&p", style="filled", color="lightblue", shape="box" ]; + { rank=same; A001; _007; } + _007 -> A001 [ arrowhead="tee" ]; + _008 [ shape="record", label="<_p1> Ref" ]; + _008:_p1 -> A005:w [ taillabel="[..]", labeldistance="1.7", + labelangle="+40", color="red" + ]; + A001 -> _008:w [ arrowhead="tee" ]; + A002 [ label="D", shape="oval" ]; + _009 [ label="roots:&q", style="filled", color="lightblue", shape="box" ]; + { rank=same; A002; _009; } + _009 -> A002 [ arrowhead="tee" ]; + _010 [ shape="record", label="<_p1> Ref" ]; + _010:_p1 -> A006:w [ taillabel="[..]", labeldistance="1.7", + labelangle="+40", color="red" + ]; + A002 -> _010:w [ arrowhead="tee" ]; + A003 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _011 [ shape="record", label="Var sint32" ]; + A003 -> _011:w [ arrowhead="tee" ]; + A004 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _012 [ shape="record", label="Var sint32" ]; + A004 -> _012:w [ arrowhead="tee" ]; + A005 [ label="R[]", shape="oval", fillcolor="green", style="filled" ]; + _013 [ label="roots:*", style="filled", color="lightblue", shape="box" ]; + { rank=same; A005; _013; } + _013 -> A005 [ arrowhead="tee" ]; + _014 [ shape="record", label="Mem sint32" ]; + A005 -> _014:w [ arrowhead="tee" ]; + A006 [ label="R[]", shape="oval", fillcolor="green", style="filled" ]; + _015 [ label="roots:*", style="filled", color="lightblue", shape="box" ]; + { rank=same; A006; _015; } + _015 -> A006 [ arrowhead="tee" ]; + _016 [ shape="record", label="Mem sint32" ]; + A006 -> _016:w [ arrowhead="tee" ]; + R017 [ label="\\result", shape="tab", style="filled", fillcolor="yellow" ]; + { rank=same; R017; A007; } + R017 -> A007 ; + A007 [ label="W", shape="oval", fillcolor="green", style="filled" ]; + _018 [ shape="record", label="Var sint32" ]; + A007 -> _018:w [ arrowhead="tee" ]; +} diff --git a/src/plugins/wp/tests/wp_region/oracle/array3.res.oracle b/src/plugins/wp/tests/wp_region/oracle/array3.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..fa7682e21183bf98f749787a3ecde94f7c1b3ce3 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/array3.res.oracle @@ -0,0 +1,4 @@ +[kernel] Parsing tests/wp_region/array3.i (no preprocessing) +[wp] Region Graph: tests/wp_region/result/array3/region/job.dot +[wp] Running WP plugin... +[wp] Warning: Missing RTE guards diff --git a/src/plugins/wp/tests/wp_region/oracle/array3/region/job.dot b/src/plugins/wp/tests/wp_region/oracle/array3/region/job.dot new file mode 100644 index 0000000000000000000000000000000000000000..02d81fff4e3f858e95add60a92a064b67aad324f --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/array3/region/job.dot @@ -0,0 +1,33 @@ +digraph "job" { + rankdir="LR" ; + node [ fontname="monospace" ]; + edge [ fontname="monospace" ]; + V000 [ label="p", shape="cds", style="filled", fillcolor="yellow" ]; + V000:e -> A000 ; + V001 [ label="s", shape="cds", style="filled", fillcolor="yellow" ]; + V001:e -> A001 ; + A000 [ label="DW", shape="oval", fillcolor="green", style="filled" ]; + _002 [ label="roots:&p", style="filled", color="lightblue", shape="box" ]; + { rank=same; A000; _002; } + _002 -> A000 [ arrowhead="tee" ]; + _003 [ shape="record", label="<_p1> Var ptr" ]; + _003:_p1 -> A002:w [ taillabel="[..]", labeldistance="1.7", + labelangle="+40", color="red" + ]; + A000 -> _003:w [ arrowhead="tee" ]; + A001 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _004 [ shape="record", label="Var sint32" ]; + A001 -> _004:w [ arrowhead="tee" ]; + A002 [ label="R[]&", shape="oval", fillcolor="orange", style="filled" ]; + _005 [ label="roots:*", style="filled", color="lightblue", shape="box" ]; + { rank=same; A002; _005; } + _005 -> A002 [ arrowhead="tee" ]; + _006 [ shape="record", label="Mem sint32" ]; + A002 -> _006:w [ arrowhead="tee" ]; + R007 [ label="\\result", shape="tab", style="filled", fillcolor="yellow" ]; + { rank=same; R007; A003; } + R007 -> A003 ; + A003 [ label="W", shape="oval", fillcolor="green", style="filled" ]; + _008 [ shape="record", label="Var sint32" ]; + A003 -> _008:w [ arrowhead="tee" ]; +} diff --git a/src/plugins/wp/tests/wp_region/oracle/array4.res.oracle b/src/plugins/wp/tests/wp_region/oracle/array4.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..f39da987941e0ffab9390a9e6e5329dcc2a9dde6 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/array4.res.oracle @@ -0,0 +1,4 @@ +[kernel] Parsing tests/wp_region/array4.i (no preprocessing) +[wp] Region Graph: tests/wp_region/result/array4/region/job.dot +[wp] Running WP plugin... +[wp] Warning: Missing RTE guards diff --git a/src/plugins/wp/tests/wp_region/oracle/array4/region/job.dot b/src/plugins/wp/tests/wp_region/oracle/array4/region/job.dot new file mode 100644 index 0000000000000000000000000000000000000000..e885c887b4e821e26250b46ada6140d9bf34d4bb --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/array4/region/job.dot @@ -0,0 +1,41 @@ +digraph "job" { + rankdir="LR" ; + node [ fontname="monospace" ]; + edge [ fontname="monospace" ]; + V000 [ label="p", shape="cds", style="filled", fillcolor="yellow" ]; + V000:e -> A000 ; + V001 [ label="s", shape="cds", style="filled", fillcolor="yellow" ]; + V001:e -> A001 ; + V002 [ label="q", shape="cds", style="filled", fillcolor="yellow" ]; + V002:e -> A002 ; + A000 [ label="D", shape="oval" ]; + _003 [ label="roots:&p", style="filled", color="lightblue", shape="box" ]; + { rank=same; A000; _003; } + _003 -> A000 [ arrowhead="tee" ]; + _004 [ shape="record", label="<_p1> Ref" ]; + _004:_p1 -> A003:w [ taillabel="[..]", labeldistance="1.7", + labelangle="+40", color="red" + ]; + A000 -> _004:w [ arrowhead="tee" ]; + A001 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _005 [ shape="record", label="Var sint32" ]; + A001 -> _005:w [ arrowhead="tee" ]; + A002 [ label="DW", shape="oval", fillcolor="green", style="filled" ]; + _006 [ shape="record", label="<_p1> Var ptr" ]; + _006:_p1 -> A003:w [ taillabel="[..]", labeldistance="1.7", + labelangle="+40", color="red" + ]; + A002 -> _006:w [ arrowhead="tee" ]; + A003 [ label="R[]&", shape="oval", fillcolor="orange", style="filled" ]; + _007 [ label="roots:*", style="filled", color="lightblue", shape="box" ]; + { rank=same; A003; _007; } + _007 -> A003 [ arrowhead="tee" ]; + _008 [ shape="record", label="Mem sint32" ]; + A003 -> _008:w [ arrowhead="tee" ]; + R009 [ label="\\result", shape="tab", style="filled", fillcolor="yellow" ]; + { rank=same; R009; A004; } + R009 -> A004 ; + A004 [ label="W", shape="oval", fillcolor="green", style="filled" ]; + _010 [ shape="record", label="Var sint32" ]; + A004 -> _010:w [ arrowhead="tee" ]; +} diff --git a/src/plugins/wp/tests/wp_region/oracle/array5.res.oracle b/src/plugins/wp/tests/wp_region/oracle/array5.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..5a0a75703bf70121d5cebd897d7699c9d6a6ac96 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/array5.res.oracle @@ -0,0 +1,4 @@ +[kernel] Parsing tests/wp_region/array5.i (no preprocessing) +[wp] Region Graph: tests/wp_region/result/array5/region/job.dot +[wp] Running WP plugin... +[wp] Warning: Missing RTE guards diff --git a/src/plugins/wp/tests/wp_region/oracle/array5/region/job.dot b/src/plugins/wp/tests/wp_region/oracle/array5/region/job.dot new file mode 100644 index 0000000000000000000000000000000000000000..f017daa76b51774c4d4fa9f340f6e92c6b42d810 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/array5/region/job.dot @@ -0,0 +1,49 @@ +digraph "job" { + rankdir="LR" ; + node [ fontname="monospace" ]; + edge [ fontname="monospace" ]; + V000 [ label="p", shape="cds", style="filled", fillcolor="yellow" ]; + V000:e -> A000 ; + V001 [ label="q", shape="cds", style="filled", fillcolor="yellow" ]; + V001:e -> A001 ; + V002 [ label="s", shape="cds", style="filled", fillcolor="yellow" ]; + V002:e -> A002 ; + V003 [ label="tmp", shape="cds", style="filled", fillcolor="yellow" ]; + V003:e -> A003 ; + A000 [ label="D", shape="oval" ]; + _004 [ label="roots:&p", style="filled", color="lightblue", shape="box" ]; + { rank=same; A000; _004; } + _004 -> A000 [ arrowhead="tee" ]; + _005 [ shape="record", label="<_p1> Ref" ]; + _005:_p1 -> A004:w [ taillabel="[..]", labeldistance="1.7", + labelangle="+40", color="red" + ]; + A000 -> _005:w [ arrowhead="tee" ]; + A001 [ label="DW", shape="oval", fillcolor="green", style="filled" ]; + _006 [ label="roots:&q", style="filled", color="lightblue", shape="box" ]; + { rank=same; A001; _006; } + _006 -> A001 [ arrowhead="tee" ]; + _007 [ shape="record", label="<_p1> Var ptr" ]; + _007:_p1 -> A004:w [ taillabel="[..]", labeldistance="1.7", + labelangle="+40", color="red" + ]; + A001 -> _007:w [ arrowhead="tee" ]; + A002 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _008 [ shape="record", label="Var sint32" ]; + A002 -> _008:w [ arrowhead="tee" ]; + A003 [ label="W", shape="oval", fillcolor="green", style="filled" ]; + _009 [ shape="record", label="Var sint32" ]; + A003 -> _009:w [ arrowhead="tee" ]; + A004 [ label="R[]&", shape="oval", fillcolor="orange", style="filled" ]; + _010 [ label="roots:*", style="filled", color="lightblue", shape="box" ]; + { rank=same; A004; _010; } + _010 -> A004 [ arrowhead="tee" ]; + _011 [ shape="record", label="Mem sint32" ]; + A004 -> _011:w [ arrowhead="tee" ]; + R012 [ label="\\result", shape="tab", style="filled", fillcolor="yellow" ]; + { rank=same; R012; A005; } + R012 -> A005 ; + A005 [ label="W", shape="oval", fillcolor="green", style="filled" ]; + _013 [ shape="record", label="Var sint32" ]; + A005 -> _013:w [ arrowhead="tee" ]; +} diff --git a/src/plugins/wp/tests/wp_region/oracle/array6.res.oracle b/src/plugins/wp/tests/wp_region/oracle/array6.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..da6ccf4e0f1e820a4d240e64df242b33930b7278 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/array6.res.oracle @@ -0,0 +1,4 @@ +[kernel] Parsing tests/wp_region/array6.i (no preprocessing) +[wp] Region Graph: tests/wp_region/result/array6/region/job.dot +[wp] Running WP plugin... +[wp] Warning: Missing RTE guards diff --git a/src/plugins/wp/tests/wp_region/oracle/array6/region/job.dot b/src/plugins/wp/tests/wp_region/oracle/array6/region/job.dot new file mode 100644 index 0000000000000000000000000000000000000000..a55f8bb5e6ea2b6edd1878b2c9e765168e6aa0e7 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/array6/region/job.dot @@ -0,0 +1,41 @@ +digraph "job" { + rankdir="LR" ; + node [ fontname="monospace" ]; + edge [ fontname="monospace" ]; + V000 [ label="A", shape="cds", style="filled", fillcolor="yellow" ]; + V000:e -> A000 ; + V001 [ label="k", shape="cds", style="filled", fillcolor="yellow" ]; + V001:e -> A001 ; + V002 [ label="s", shape="cds", style="filled", fillcolor="yellow" ]; + V002:e -> A002 ; + A000 [ label="", shape="oval" ]; + _003 [ label="roots:&A", style="filled", color="lightblue", shape="box" ]; + { rank=same; A000; _003; } + _003 -> A000 [ arrowhead="tee" ]; + _004 [ shape="record", label="<_p1> 0..319: D32[10]" ]; + _004:_p1 -> A003 [ style="dotted" ]; + A000 -> _004:w [ arrowhead="tee" ]; + A001 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _005 [ label="roots:&k", style="filled", color="lightblue", shape="box" ]; + { rank=same; A001; _005; } + _005 -> A001 [ arrowhead="tee" ]; + _006 [ shape="record", label="Var sint32" ]; + A001 -> _006:w [ arrowhead="tee" ]; + A002 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _007 [ shape="record", label="Var sint32" ]; + A002 -> _007:w [ arrowhead="tee" ]; + A003 [ label="R", shape="oval", fillcolor="green", style="filled" ]; + _008 [ label="roots:&A+(..)", style="filled", color="lightblue", + shape="box" + ]; + { rank=same; A003; _008; } + _008 -> A003 [ arrowhead="tee" ]; + _009 [ shape="record", label="Mem sint32" ]; + A003 -> _009:w [ arrowhead="tee" ]; + R010 [ label="\\result", shape="tab", style="filled", fillcolor="yellow" ]; + { rank=same; R010; A004; } + R010 -> A004 ; + A004 [ label="W", shape="oval", fillcolor="green", style="filled" ]; + _011 [ shape="record", label="Var sint32" ]; + A004 -> _011:w [ arrowhead="tee" ]; +} diff --git a/src/plugins/wp/tests/wp_region/oracle/array7.res.oracle b/src/plugins/wp/tests/wp_region/oracle/array7.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..cb757d81d87267e4a38812b6cb8762f8489e6848 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/array7.res.oracle @@ -0,0 +1,4 @@ +[kernel] Parsing tests/wp_region/array7.i (no preprocessing) +[wp] Region Graph: tests/wp_region/result/array7/region/job.dot +[wp] Running WP plugin... +[wp] Warning: Missing RTE guards diff --git a/src/plugins/wp/tests/wp_region/oracle/array7/region/job.dot b/src/plugins/wp/tests/wp_region/oracle/array7/region/job.dot new file mode 100644 index 0000000000000000000000000000000000000000..e4b91ca2a02e735f39c91a531d400469093f4cd9 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/array7/region/job.dot @@ -0,0 +1,47 @@ +digraph "job" { + rankdir="LR" ; + node [ fontname="monospace" ]; + edge [ fontname="monospace" ]; + V000 [ label="A", shape="cds", style="filled", fillcolor="yellow" ]; + V000:e -> A000 ; + V001 [ label="k", shape="cds", style="filled", fillcolor="yellow" ]; + V001:e -> A001 ; + V002 [ label="s", shape="cds", style="filled", fillcolor="yellow" ]; + V002:e -> A002 ; + V003 [ label="p", shape="cds", style="filled", fillcolor="yellow" ]; + V003:e -> A003 ; + A000 [ label="", shape="oval" ]; + _004 [ label="roots:&A", style="filled", color="lightblue", shape="box" ]; + { rank=same; A000; _004; } + _004 -> A000 [ arrowhead="tee" ]; + _005 [ shape="record", label="<_p1> 0..319: D32[10]" ]; + _005:_p1 -> A004 [ style="dotted" ]; + A000 -> _005:w [ arrowhead="tee" ]; + A001 [ label="R", shape="oval", fillcolor="green", style="filled" ]; + _006 [ label="roots:&k", style="filled", color="lightblue", shape="box" ]; + { rank=same; A001; _006; } + _006 -> A001 [ arrowhead="tee" ]; + _007 [ shape="record", label="Var sint32" ]; + A001 -> _007:w [ arrowhead="tee" ]; + A002 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _008 [ shape="record", label="Var sint32" ]; + A002 -> _008:w [ arrowhead="tee" ]; + A003 [ label="DW", shape="oval", fillcolor="green", style="filled" ]; + _009 [ shape="record", label="<_p1> Var ptr" ]; + _009:_p1 -> A004:w [ taillabel="[..]", labeldistance="1.7", + labelangle="+40", color="red" + ]; + A003 -> _009:w [ arrowhead="tee" ]; + A004 [ label="R[]&", shape="oval", fillcolor="orange", style="filled" ]; + _010 [ label="roots:*", style="filled", color="lightblue", shape="box" ]; + { rank=same; A004; _010; } + _010 -> A004 [ arrowhead="tee" ]; + _011 [ shape="record", label="Mem sint32" ]; + A004 -> _011:w [ arrowhead="tee" ]; + R012 [ label="\\result", shape="tab", style="filled", fillcolor="yellow" ]; + { rank=same; R012; A005; } + R012 -> A005 ; + A005 [ label="W", shape="oval", fillcolor="green", style="filled" ]; + _013 [ shape="record", label="Var sint32" ]; + A005 -> _013:w [ arrowhead="tee" ]; +} diff --git a/src/plugins/wp/tests/wp_region/oracle/array8.res.oracle b/src/plugins/wp/tests/wp_region/oracle/array8.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..83dd9d4238255784aba7772b3e57fb754865ad16 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/array8.res.oracle @@ -0,0 +1,4 @@ +[kernel] Parsing tests/wp_region/array8.i (no preprocessing) +[wp] Region Graph: tests/wp_region/result/array8/region/job.dot +[wp] Running WP plugin... +[wp] Warning: Missing RTE guards diff --git a/src/plugins/wp/tests/wp_region/oracle/array8/region/job.dot b/src/plugins/wp/tests/wp_region/oracle/array8/region/job.dot new file mode 100644 index 0000000000000000000000000000000000000000..f062fa1492fad2f399e0458c6bb0dd25153c5714 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/array8/region/job.dot @@ -0,0 +1,58 @@ +digraph "job" { + rankdir="LR" ; + node [ fontname="monospace" ]; + edge [ fontname="monospace" ]; + V000 [ label="A", shape="cds", style="filled", fillcolor="yellow" ]; + V000:e -> A000 ; + V001 [ label="B", shape="cds", style="filled", fillcolor="yellow" ]; + V001:e -> A000 ; + V002 [ label="c", shape="cds", style="filled", fillcolor="yellow" ]; + V002:e -> A001 ; + V003 [ label="k", shape="cds", style="filled", fillcolor="yellow" ]; + V003:e -> A002 ; + V004 [ label="s", shape="cds", style="filled", fillcolor="yellow" ]; + V004:e -> A003 ; + V005 [ label="p", shape="cds", style="filled", fillcolor="yellow" ]; + V005:e -> A004 ; + V006 [ label="tmp", shape="cds", style="filled", fillcolor="yellow" ]; + V006:e -> A005 ; + A000 [ label="R[]&", shape="oval", fillcolor="orange", style="filled" ]; + _007 [ label="roots:*", style="filled", color="lightblue", shape="box" ]; + { rank=same; A000; _007; } + _007 -> A000 [ arrowhead="tee" ]; + _008 [ shape="record", label="Mem sint32" ]; + A000 -> _008:w [ arrowhead="tee" ]; + A001 [ label="R", shape="oval", fillcolor="green", style="filled" ]; + _009 [ label="roots:&c", style="filled", color="lightblue", shape="box" ]; + { rank=same; A001; _009; } + _009 -> A001 [ arrowhead="tee" ]; + _010 [ shape="record", label="Var sint32" ]; + A001 -> _010:w [ arrowhead="tee" ]; + A002 [ label="R", shape="oval", fillcolor="green", style="filled" ]; + _011 [ label="roots:&k", style="filled", color="lightblue", shape="box" ]; + { rank=same; A002; _011; } + _011 -> A002 [ arrowhead="tee" ]; + _012 [ shape="record", label="Var sint32" ]; + A002 -> _012:w [ arrowhead="tee" ]; + A003 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _013 [ shape="record", label="Var sint32" ]; + A003 -> _013:w [ arrowhead="tee" ]; + A004 [ label="DW", shape="oval", fillcolor="green", style="filled" ]; + _014 [ shape="record", label="<_p1> Var ptr" ]; + _014:_p1 -> A000:w [ taillabel="[..]", labeldistance="1.7", + labelangle="+40", color="red" + ]; + A004 -> _014:w [ arrowhead="tee" ]; + A005 [ label="DW", shape="oval", fillcolor="green", style="filled" ]; + _015 [ shape="record", label="<_p1> Var ptr" ]; + _015:_p1 -> A000:w [ taillabel="[..]", labeldistance="1.7", + labelangle="+40", color="red" + ]; + A005 -> _015:w [ arrowhead="tee" ]; + R016 [ label="\\result", shape="tab", style="filled", fillcolor="yellow" ]; + { rank=same; R016; A006; } + R016 -> A006 ; + A006 [ label="W", shape="oval", fillcolor="green", style="filled" ]; + _017 [ shape="record", label="Var sint32" ]; + A006 -> _017:w [ arrowhead="tee" ]; +} diff --git a/src/plugins/wp/tests/wp_region/oracle/fb_ADD.res.oracle b/src/plugins/wp/tests/wp_region/oracle/fb_ADD.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..2331b4aae9657c583924d185d3f0c3fb0a9b0bc8 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/fb_ADD.res.oracle @@ -0,0 +1,4 @@ +[kernel] Parsing tests/wp_region/fb_ADD.i (no preprocessing) +[wp] Region Graph: tests/wp_region/result/fb_ADD/region/job.dot +[wp] Running WP plugin... +[wp] Warning: Missing RTE guards diff --git a/src/plugins/wp/tests/wp_region/oracle/fb_ADD/region/job.dot b/src/plugins/wp/tests/wp_region/oracle/fb_ADD/region/job.dot new file mode 100644 index 0000000000000000000000000000000000000000..eb1fa949b61292f0492473059be5e7da8c88292c --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/fb_ADD/region/job.dot @@ -0,0 +1,95 @@ +digraph "job" { + rankdir="LR" ; + node [ fontname="monospace" ]; + edge [ fontname="monospace" ]; + V000 [ label="fb", shape="cds", style="filled", fillcolor="yellow" ]; + V000:e -> A000 ; + A000 [ label="D", shape="oval" ]; + _001 [ label="roots:&fb", style="filled", color="lightblue", shape="box" ]; + { rank=same; A000; _001; } + _001 -> A000 [ arrowhead="tee" ]; + _002 [ shape="record", label="<_p1> Ref" ]; + _002:_p1 -> A001:w [ taillabel="*", labelangle="+30", color="red" ]; + A000 -> _002:w [ arrowhead="tee" ]; + A001 [ label="", shape="oval" ]; + _003 [ label="roots:&fb", style="filled", color="lightblue", shape="box" ]; + { rank=same; A001; _003; } + _003 -> A001 [ arrowhead="tee" ]; + _004 [ shape="record", label="<_p1> 128..159: D32|<_p2> 160..191: D32" ]; + _004:_p2 -> A003 [ style="dotted" ]; + _004:_p1 -> A002 [ style="dotted" ]; + A001 -> _004:w [ arrowhead="tee" ]; + A002 [ label="D", shape="oval" ]; + _005 [ label="roots:&fb+128", style="filled", color="lightblue", + shape="box" + ]; + { rank=same; A002; _005; } + _005 -> A002 [ arrowhead="tee" ]; + _006 [ shape="record", label="<_p1> Ref" ]; + _006:_p1 -> A004:w [ taillabel="*", labelangle="+30", color="red" ]; + A002 -> _006:w [ arrowhead="tee" ]; + A003 [ label="D", shape="oval" ]; + _007 [ label="roots:&fb+160", style="filled", color="lightblue", + shape="box" + ]; + { rank=same; A003; _007; } + _007 -> A003 [ arrowhead="tee" ]; + _008 [ shape="record", label="<_p1> Ref" ]; + _008:_p1 -> A005:w [ taillabel="*", labelangle="+30", color="red" ]; + A003 -> _008:w [ arrowhead="tee" ]; + A004 [ label="", shape="oval" ]; + _009 [ label="roots:&fb+128", style="filled", color="lightblue", + shape="box" + ]; + { rank=same; A004; _009; } + _009 -> A004 [ arrowhead="tee" ]; + _010 [ shape="record", label="<_p1> 0..63: D64|<_p2> 64..95: D32" ]; + _010:_p2 -> A007 [ style="dotted" ]; + _010:_p1 -> A006 [ style="dotted" ]; + A004 -> _010:w [ arrowhead="tee" ]; + A005 [ label="", shape="oval" ]; + _011 [ label="roots:&fb+160", style="filled", color="lightblue", + shape="box" + ]; + { rank=same; A005; _011; } + _011 -> A005 [ arrowhead="tee" ]; + _012 [ shape="record", label="<_p1> 0..63: D64|<_p2> 64..95: D32" ]; + _012:_p2 -> A009 [ style="dotted" ]; + _012:_p1 -> A008 [ style="dotted" ]; + A005 -> _012:w [ arrowhead="tee" ]; + A006 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _013 [ label="roots:&fb+128", style="filled", color="lightblue", + shape="box" + ]; + { rank=same; A006; _013; } + _013 -> A006 [ arrowhead="tee" ]; + _014 [ shape="record", label="Var float64" ]; + A006 -> _014:w [ arrowhead="tee" ]; + A007 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _015 [ label="roots:&fb+192", style="filled", color="lightblue", + shape="box" + ]; + { rank=same; A007; _015; } + _015 -> A007 [ arrowhead="tee" ]; + _016 [ shape="record", label="Var sint32" ]; + A007 -> _016:w [ arrowhead="tee" ]; + A008 [ label="R", shape="oval", fillcolor="green", style="filled" ]; + _017 [ label="roots:&fb+160", style="filled", color="lightblue", + shape="box" + ]; + { rank=same; A008; _017; } + _017 -> A008 [ arrowhead="tee" ]; + _018 [ shape="record", label="Var float64" ]; + A008 -> _018:w [ arrowhead="tee" ]; + A009 [ label="R", shape="oval", fillcolor="green", style="filled" ]; + _019 [ label="roots:&fb+224", style="filled", color="lightblue", + shape="box" + ]; + { rank=same; A009; _019; } + _019 -> A009 [ arrowhead="tee" ]; + _020 [ shape="record", label="Var sint32" ]; + A009 -> _020:w [ arrowhead="tee" ]; + R021 [ label="A", shape="tab", style="filled", fillcolor="yellow" ]; + { rank=same; R021; A000; } + R021 -> A000 ; +} diff --git a/src/plugins/wp/tests/wp_region/oracle/fb_SORT.res.oracle b/src/plugins/wp/tests/wp_region/oracle/fb_SORT.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..ec1a0b83feb62c26278e26829c9a50d83687ef97 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/fb_SORT.res.oracle @@ -0,0 +1,4 @@ +[kernel] Parsing tests/wp_region/fb_SORT.i (no preprocessing) +[wp] Region Graph: tests/wp_region/result/fb_SORT/region/job.dot +[wp] Running WP plugin... +[wp] Warning: Missing RTE guards diff --git a/src/plugins/wp/tests/wp_region/oracle/fb_SORT/region/job.dot b/src/plugins/wp/tests/wp_region/oracle/fb_SORT/region/job.dot new file mode 100644 index 0000000000000000000000000000000000000000..4cbd5b27d23593f242fbdb78151766885a29f883 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/fb_SORT/region/job.dot @@ -0,0 +1,204 @@ +digraph "job" { + rankdir="LR" ; + node [ fontname="monospace" ]; + edge [ fontname="monospace" ]; + V000 [ label="fb", shape="cds", style="filled", fillcolor="yellow" ]; + V000:e -> A000 ; + V001 [ label="inp", shape="cds", style="filled", fillcolor="yellow" ]; + V001:e -> A001 ; + V002 [ label="out", shape="cds", style="filled", fillcolor="yellow" ]; + V002:e -> A002 ; + V003 [ label="idx", shape="cds", style="filled", fillcolor="yellow" ]; + V003:e -> A003 ; + V004 [ label="i", shape="cds", style="filled", fillcolor="yellow" ]; + V004:e -> A004 ; + A000 [ label="D", shape="oval" ]; + _005 [ label="roots:&fb", style="filled", color="lightblue", shape="box" ]; + { rank=same; A000; _005; } + _005 -> A000 [ arrowhead="tee" ]; + _006 [ shape="record", label="<_p1> Ref" ]; + _006:_p1 -> A005:w [ taillabel="*", labelangle="+30", color="red" ]; + A000 -> _006:w [ arrowhead="tee" ]; + A001 [ label="DW", shape="oval", fillcolor="green", style="filled" ]; + _007 [ shape="record", label="<_p1> Var ptr" ]; + _007:_p1 -> A006:w [ taillabel="[..]", labeldistance="1.7", + labelangle="+40", color="red" + ]; + A001 -> _007:w [ arrowhead="tee" ]; + A002 [ label="DW", shape="oval", fillcolor="green", style="filled" ]; + _008 [ shape="record", label="<_p1> Var ptr" ]; + _008:_p1 -> A007:w [ taillabel="[..]", labeldistance="1.7", + labelangle="+40", color="red" + ]; + A002 -> _008:w [ arrowhead="tee" ]; + A003 [ label="DW", shape="oval", fillcolor="green", style="filled" ]; + _009 [ shape="record", label="<_p1> Var ptr" ]; + _009:_p1 -> A008:w [ taillabel="[..]", labeldistance="1.7", + labelangle="+40", color="red" + ]; + A003 -> _009:w [ arrowhead="tee" ]; + A004 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _010 [ shape="record", label="Var sint32" ]; + A004 -> _010:w [ arrowhead="tee" ]; + A005 [ label="", shape="oval" ]; + _011 [ label="roots:&fb", style="filled", color="lightblue", shape="box" ]; + { rank=same; A005; _011; } + _011 -> A005 [ arrowhead="tee" ]; + _012 [ shape="record", + label="<_p1> 0..31: D32|<_p2> 32..127: D32[3]|<_p3> 128..223: D32[3]|<_p4> 224..319: D32[3]|<_p5> 320..351: D32" + ]; + _012:_p5 -> A010 [ style="dotted" ]; + _012:_p4 -> A008 [ style="dotted" ]; + _012:_p3 -> A007 [ style="dotted" ]; + _012:_p2 -> A006 [ style="dotted" ]; + _012:_p1 -> A009 [ style="dotted" ]; + A005 -> _012:w [ arrowhead="tee" ]; + A006 [ label="D[]&", shape="oval", fillcolor="orange", style="filled" ]; + _013 [ label="roots:*", style="filled", color="lightblue", shape="box" ]; + { rank=same; A006; _013; } + _013 -> A006 [ arrowhead="tee" ]; + _014 [ shape="record", label="<_p1> Ref" ]; + _014:_p1 -> A011:w [ taillabel="*", labelangle="+30", color="red" ]; + A006 -> _014:w [ arrowhead="tee" ]; + A007 [ label="D[]&", shape="oval", fillcolor="orange", style="filled" ]; + _015 [ label="roots:*", style="filled", color="lightblue", shape="box" ]; + { rank=same; A007; _015; } + _015 -> A007 [ arrowhead="tee" ]; + _016 [ shape="record", label="<_p1> Ref" ]; + _016:_p1 -> A012:w [ taillabel="*", labelangle="+30", color="red" ]; + A007 -> _016:w [ arrowhead="tee" ]; + A008 [ label="D[]&", shape="oval", fillcolor="orange", style="filled" ]; + _017 [ label="roots:*", style="filled", color="lightblue", shape="box" ]; + { rank=same; A008; _017; } + _017 -> A008 [ arrowhead="tee" ]; + _018 [ shape="record", label="<_p1> Ref" ]; + _018:_p1 -> A013:w [ taillabel="*", labelangle="+30", color="red" ]; + A008 -> _018:w [ arrowhead="tee" ]; + A009 [ label="D", shape="oval" ]; + _019 [ label="roots:&fb", style="filled", color="lightblue", shape="box" ]; + { rank=same; A009; _019; } + _019 -> A009 [ arrowhead="tee" ]; + _020 [ shape="record", label="<_p1> Ref" ]; + _020:_p1 -> A014:w [ taillabel="*", labelangle="+30", color="red" ]; + A009 -> _020:w [ arrowhead="tee" ]; + A010 [ label="D", shape="oval" ]; + _021 [ label="roots:&fb+320", style="filled", color="lightblue", + shape="box" + ]; + { rank=same; A010; _021; } + _021 -> A010 [ arrowhead="tee" ]; + _022 [ shape="record", label="<_p1> Ref" ]; + _022:_p1 -> A015:w [ taillabel="*", labelangle="+30", color="red" ]; + A010 -> _022:w [ arrowhead="tee" ]; + A011 [ label="&", shape="oval", fillcolor="orange", style="filled" ]; + _023 [ label="roots:*", style="filled", color="lightblue", shape="box" ]; + { rank=same; A011; _023; } + _023 -> A011 [ arrowhead="tee" ]; + _024 [ shape="record", label="<_p1> 0..63: D64|<_p2> 64..95: D32" ]; + _024:_p2 -> A017 [ style="dotted" ]; + _024:_p1 -> A016 [ style="dotted" ]; + A011 -> _024:w [ arrowhead="tee" ]; + A012 [ label="", shape="oval" ]; + _025 [ label="roots:*", style="filled", color="lightblue", shape="box" ]; + { rank=same; A012; _025; } + _025 -> A012 [ arrowhead="tee" ]; + _026 [ shape="record", label="<_p1> 0..63: D64|<_p2> 64..95: D32" ]; + _026:_p2 -> A019 [ style="dotted" ]; + _026:_p1 -> A018 [ style="dotted" ]; + A012 -> _026:w [ arrowhead="tee" ]; + A013 [ label="", shape="oval" ]; + _027 [ label="roots:*", style="filled", color="lightblue", shape="box" ]; + { rank=same; A013; _027; } + _027 -> A013 [ arrowhead="tee" ]; + _028 [ shape="record", label="<_p1> 0..31: D32|<_p2> 32..63: D32" ]; + _028:_p2 -> A021 [ style="dotted" ]; + _028:_p1 -> A020 [ style="dotted" ]; + A013 -> _028:w [ arrowhead="tee" ]; + A014 [ label="", shape="oval" ]; + _029 [ label="roots:&fb", style="filled", color="lightblue", shape="box" ]; + { rank=same; A014; _029; } + _029 -> A014 [ arrowhead="tee" ]; + _030 [ shape="record", label="<_p1> 0..63: D64" ]; + _030:_p1 -> A022 [ style="dotted" ]; + A014 -> _030:w [ arrowhead="tee" ]; + A015 [ label="", shape="oval" ]; + _031 [ label="roots:&fb+320", style="filled", color="lightblue", + shape="box" + ]; + { rank=same; A015; _031; } + _031 -> A015 [ arrowhead="tee" ]; + _032 [ shape="record", label="<_p1> 0..63: D64|<_p2> 64..95: D32" ]; + _032:_p2 -> A024 [ style="dotted" ]; + _032:_p1 -> A023 [ style="dotted" ]; + A015 -> _032:w [ arrowhead="tee" ]; + A016 [ label="R", shape="oval", fillcolor="green", style="filled" ]; + _033 [ label="roots:*", style="filled", color="lightblue", shape="box" ]; + { rank=same; A016; _033; } + _033 -> A016 [ arrowhead="tee" ]; + _034 [ shape="record", label="Mem float64" ]; + A016 -> _034:w [ arrowhead="tee" ]; + A017 [ label="R", shape="oval", fillcolor="green", style="filled" ]; + _035 [ label="roots:*", style="filled", color="lightblue", shape="box" ]; + { rank=same; A017; _035; } + _035 -> A017 [ arrowhead="tee" ]; + _036 [ shape="record", label="Mem sint32" ]; + A017 -> _036:w [ arrowhead="tee" ]; + A018 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _037 [ label="roots:*", style="filled", color="lightblue", shape="box" ]; + { rank=same; A018; _037; } + _037 -> A018 [ arrowhead="tee" ]; + _038 [ shape="record", label="Mem float64" ]; + A018 -> _038:w [ arrowhead="tee" ]; + A019 [ label="W", shape="oval", fillcolor="green", style="filled" ]; + _039 [ label="roots:*", style="filled", color="lightblue", shape="box" ]; + { rank=same; A019; _039; } + _039 -> A019 [ arrowhead="tee" ]; + _040 [ shape="record", label="Mem sint32" ]; + A019 -> _040:w [ arrowhead="tee" ]; + A020 [ label="W", shape="oval", fillcolor="green", style="filled" ]; + _041 [ label="roots:*", style="filled", color="lightblue", shape="box" ]; + { rank=same; A020; _041; } + _041 -> A020 [ arrowhead="tee" ]; + _042 [ shape="record", label="Mem sint32" ]; + A020 -> _042:w [ arrowhead="tee" ]; + A021 [ label="W", shape="oval", fillcolor="green", style="filled" ]; + _043 [ label="roots:*", style="filled", color="lightblue", shape="box" ]; + { rank=same; A021; _043; } + _043 -> A021 [ arrowhead="tee" ]; + _044 [ shape="record", label="Mem sint32" ]; + A021 -> _044:w [ arrowhead="tee" ]; + A022 [ label="R", shape="oval", fillcolor="green", style="filled" ]; + _045 [ label="roots:&fb", style="filled", color="lightblue", shape="box" ]; + { rank=same; A022; _045; } + _045 -> A022 [ arrowhead="tee" ]; + _046 [ shape="record", label="Var float64" ]; + A022 -> _046:w [ arrowhead="tee" ]; + A023 [ label="W", shape="oval", fillcolor="green", style="filled" ]; + _047 [ label="roots:&fb+320", style="filled", color="lightblue", + shape="box" + ]; + { rank=same; A023; _047; } + _047 -> A023 [ arrowhead="tee" ]; + _048 [ shape="record", label="Var float64" ]; + A023 -> _048:w [ arrowhead="tee" ]; + A024 [ label="W", shape="oval", fillcolor="green", style="filled" ]; + _049 [ label="roots:&fb+384", style="filled", color="lightblue", + shape="box" + ]; + { rank=same; A024; _049; } + _049 -> A024 [ arrowhead="tee" ]; + _050 [ shape="record", label="Var sint32" ]; + A024 -> _050:w [ arrowhead="tee" ]; + R051 [ label="IDX", shape="tab", style="filled", fillcolor="yellow" ]; + { rank=same; R051; A008; } + R051 -> A008 ; + R052 [ label="IN", shape="tab", style="filled", fillcolor="yellow" ]; + { rank=same; R052; A006; } + R052 -> A006 ; + R053 [ label="OUT", shape="tab", style="filled", fillcolor="yellow" ]; + { rank=same; R053; A007; } + R053 -> A007 ; + R054 [ label="Shared", shape="tab", style="filled", fillcolor="yellow" ]; + { rank=same; R054; A011; } + R054 -> A011 ; +} diff --git a/src/plugins/wp/tests/wp_region/oracle/garbled.res.oracle b/src/plugins/wp/tests/wp_region/oracle/garbled.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..13973473a6739603448758d6940000363173431e --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/garbled.res.oracle @@ -0,0 +1,7 @@ +[kernel] Parsing tests/wp_region/garbled.i (no preprocessing) +[wp:garbled] Garbled Clusters: A=sint32 B=float32 +[wp:garbled] Garbled Clusters: A=garbled B=sint32 +[wp:garbled] Garbled Clusters: A=garbled B=float32 +[wp] Region Graph: tests/wp_region/result/garbled/region/job.dot +[wp] Running WP plugin... +[wp] Warning: Missing RTE guards diff --git a/src/plugins/wp/tests/wp_region/oracle/garbled/region/job.dot b/src/plugins/wp/tests/wp_region/oracle/garbled/region/job.dot new file mode 100644 index 0000000000000000000000000000000000000000..1f13727a1f33006dd8dc3a85b608b3e74a1b5dc3 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/garbled/region/job.dot @@ -0,0 +1,48 @@ +digraph "job" { + rankdir="LR" ; + node [ fontname="monospace" ]; + edge [ fontname="monospace" ]; + V000 [ label="p", shape="cds", style="filled", fillcolor="yellow" ]; + V000:e -> A000 ; + V001 [ label="q", shape="cds", style="filled", fillcolor="yellow" ]; + V001:e -> A001 ; + V002 [ label="__retres", shape="cds", style="filled", fillcolor="yellow" ]; + V002:e -> A002 ; + A000 [ label="D", shape="oval" ]; + _003 [ label="roots:&p", style="filled", color="lightblue", shape="box" ]; + { rank=same; A000; _003; } + _003 -> A000 [ arrowhead="tee" ]; + _004 [ shape="record", label="<_p1> Ref" ]; + _004:_p1 -> A003:w [ taillabel="*", labelangle="+30", color="red" ]; + A000 -> _004:w [ arrowhead="tee" ]; + A001 [ label="D", shape="oval" ]; + _005 [ label="roots:&q", style="filled", color="lightblue", shape="box" ]; + { rank=same; A001; _005; } + _005 -> A001 [ arrowhead="tee" ]; + _006 [ shape="record", label="<_p1> Ref" ]; + _006:_p1 -> A004:w [ taillabel="*", labelangle="+30", color="red" ]; + A001 -> _006:w [ arrowhead="tee" ]; + A002 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _007 [ shape="record", label="Var float32" ]; + A002 -> _007:w [ arrowhead="tee" ]; + A003 [ label="R", shape="oval", color="red", fillcolor="red", + style="filled" + ]; + _008 [ label="roots:&p", style="filled", color="lightblue", shape="box" ]; + { rank=same; A003; _008; } + _008 -> A003 [ arrowhead="tee" ]; + _009 [ shape="record", label="Raw", fillcolor="red", style="filled" ]; + A003 -> _009:w [ arrowhead="tee" ]; + A004 [ label="R", shape="oval", fillcolor="green", style="filled" ]; + _010 [ label="roots:&q", style="filled", color="lightblue", shape="box" ]; + { rank=same; A004; _010; } + _010 -> A004 [ arrowhead="tee" ]; + _011 [ shape="record", label="Var sint32" ]; + A004 -> _011:w [ arrowhead="tee" ]; + R012 [ label="\\result", shape="tab", style="filled", fillcolor="yellow" ]; + { rank=same; R012; A005; } + R012 -> A005 ; + A005 [ label="W", shape="oval", fillcolor="green", style="filled" ]; + _013 [ shape="record", label="Var float32" ]; + A005 -> _013:w [ arrowhead="tee" ]; +} diff --git a/src/plugins/wp/tests/wp_region/oracle/index.res.oracle b/src/plugins/wp/tests/wp_region/oracle/index.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..834049467cbde15d83aba42c883878baaa71ed0f --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/index.res.oracle @@ -0,0 +1,4 @@ +[kernel] Parsing tests/wp_region/index.i (no preprocessing) +[wp] Region Graph: tests/wp_region/result/index/region/job.dot +[wp] Running WP plugin... +[wp] Warning: Missing RTE guards diff --git a/src/plugins/wp/tests/wp_region/oracle/index/region/job.dot b/src/plugins/wp/tests/wp_region/oracle/index/region/job.dot new file mode 100644 index 0000000000000000000000000000000000000000..5aea05755a41cc4c8ae8eaf06c3a06ed763927e8 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/index/region/job.dot @@ -0,0 +1,57 @@ +digraph "job" { + rankdir="LR" ; + node [ fontname="monospace" ]; + edge [ fontname="monospace" ]; + V000 [ label="A", shape="cds", style="filled", fillcolor="yellow" ]; + V000:e -> A000 ; + V001 [ label="i", shape="cds", style="filled", fillcolor="yellow" ]; + V001:e -> A001 ; + V002 [ label="j", shape="cds", style="filled", fillcolor="yellow" ]; + V002:e -> A002 ; + V003 [ label="k", shape="cds", style="filled", fillcolor="yellow" ]; + V003:e -> A003 ; + V004 [ label="__retres", shape="cds", style="filled", fillcolor="yellow" ]; + V004:e -> A004 ; + A000 [ label="", shape="oval" ]; + _005 [ label="roots:&A", style="filled", color="lightblue", shape="box" ]; + { rank=same; A000; _005; } + _005 -> A000 [ arrowhead="tee" ]; + _006 [ shape="record", label="<_p1> 0..1919: D32[5,4,3]" ]; + _006:_p1 -> A005 [ style="dotted" ]; + A000 -> _006:w [ arrowhead="tee" ]; + A001 [ label="R", shape="oval", fillcolor="green", style="filled" ]; + _007 [ label="roots:&i", style="filled", color="lightblue", shape="box" ]; + { rank=same; A001; _007; } + _007 -> A001 [ arrowhead="tee" ]; + _008 [ shape="record", label="Var sint32" ]; + A001 -> _008:w [ arrowhead="tee" ]; + A002 [ label="R", shape="oval", fillcolor="green", style="filled" ]; + _009 [ label="roots:&j", style="filled", color="lightblue", shape="box" ]; + { rank=same; A002; _009; } + _009 -> A002 [ arrowhead="tee" ]; + _010 [ shape="record", label="Var sint32" ]; + A002 -> _010:w [ arrowhead="tee" ]; + A003 [ label="R", shape="oval", fillcolor="green", style="filled" ]; + _011 [ label="roots:&k", style="filled", color="lightblue", shape="box" ]; + { rank=same; A003; _011; } + _011 -> A003 [ arrowhead="tee" ]; + _012 [ shape="record", label="Var sint32" ]; + A003 -> _012:w [ arrowhead="tee" ]; + A004 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _013 [ shape="record", label="Var sint32" ]; + A004 -> _013:w [ arrowhead="tee" ]; + A005 [ label="R", shape="oval", fillcolor="green", style="filled" ]; + _014 [ label="roots:&A+(..)", style="filled", color="lightblue", + shape="box" + ]; + { rank=same; A005; _014; } + _014 -> A005 [ arrowhead="tee" ]; + _015 [ shape="record", label="Mem sint32" ]; + A005 -> _015:w [ arrowhead="tee" ]; + R016 [ label="\\result", shape="tab", style="filled", fillcolor="yellow" ]; + { rank=same; R016; A006; } + R016 -> A006 ; + A006 [ label="W", shape="oval", fillcolor="green", style="filled" ]; + _017 [ shape="record", label="Var sint32" ]; + A006 -> _017:w [ arrowhead="tee" ]; +} diff --git a/src/plugins/wp/tests/wp_region/oracle/matrix.res.oracle b/src/plugins/wp/tests/wp_region/oracle/matrix.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..fe737f1db75548cc56518bebf54a18bc070f442f --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/matrix.res.oracle @@ -0,0 +1,4 @@ +[kernel] Parsing tests/wp_region/matrix.i (no preprocessing) +[wp] Region Graph: tests/wp_region/result/matrix/region/job.dot +[wp] Running WP plugin... +[wp] Warning: Missing RTE guards diff --git a/src/plugins/wp/tests/wp_region/oracle/matrix/region/job.dot b/src/plugins/wp/tests/wp_region/oracle/matrix/region/job.dot new file mode 100644 index 0000000000000000000000000000000000000000..fcce73f07e94697143a17a714e1605709e77c9f6 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/matrix/region/job.dot @@ -0,0 +1,93 @@ +digraph "job" { + rankdir="LR" ; + node [ fontname="monospace" ]; + edge [ fontname="monospace" ]; + V000 [ label="cols", shape="cds", style="filled", fillcolor="yellow" ]; + V000:e -> A000 ; + V001 [ label="rows", shape="cds", style="filled", fillcolor="yellow" ]; + V001:e -> A001 ; + V002 [ label="m", shape="cds", style="filled", fillcolor="yellow" ]; + V002:e -> A002 ; + V003 [ label="v", shape="cds", style="filled", fillcolor="yellow" ]; + V003:e -> A003 ; + V004 [ label="r", shape="cds", style="filled", fillcolor="yellow" ]; + V004:e -> A004 ; + V005 [ label="i", shape="cds", style="filled", fillcolor="yellow" ]; + V005:e -> A005 ; + V006 [ label="j", shape="cds", style="filled", fillcolor="yellow" ]; + V006:e -> A006 ; + A000 [ label="R", shape="oval", fillcolor="green", style="filled" ]; + _007 [ label="roots:&cols", style="filled", color="lightblue", shape="box" + ]; + { rank=same; A000; _007; } + _007 -> A000 [ arrowhead="tee" ]; + _008 [ shape="record", label="Var sint32" ]; + A000 -> _008:w [ arrowhead="tee" ]; + A001 [ label="R", shape="oval", fillcolor="green", style="filled" ]; + _009 [ label="roots:&rows", style="filled", color="lightblue", shape="box" + ]; + { rank=same; A001; _009; } + _009 -> A001 [ arrowhead="tee" ]; + _010 [ shape="record", label="Var sint32" ]; + A001 -> _010:w [ arrowhead="tee" ]; + A002 [ label="D", shape="oval" ]; + _011 [ label="roots:&m", style="filled", color="lightblue", shape="box" ]; + { rank=same; A002; _011; } + _011 -> A002 [ arrowhead="tee" ]; + _012 [ shape="record", label="<_p1> Ref" ]; + _012:_p1 -> A007:w [ taillabel="[..]", labeldistance="1.7", + labelangle="+40", color="red" + ]; + A002 -> _012:w [ arrowhead="tee" ]; + A003 [ label="D", shape="oval" ]; + _013 [ label="roots:&v", style="filled", color="lightblue", shape="box" ]; + { rank=same; A003; _013; } + _013 -> A003 [ arrowhead="tee" ]; + _014 [ shape="record", label="<_p1> Ref" ]; + _014:_p1 -> A008:w [ taillabel="[..]", labeldistance="1.7", + labelangle="+40", color="red" + ]; + A003 -> _014:w [ arrowhead="tee" ]; + A004 [ label="D", shape="oval" ]; + _015 [ label="roots:&r", style="filled", color="lightblue", shape="box" ]; + { rank=same; A004; _015; } + _015 -> A004 [ arrowhead="tee" ]; + _016 [ shape="record", label="<_p1> Ref" ]; + _016:_p1 -> A009:w [ taillabel="[..]", labeldistance="1.7", + labelangle="+40", color="red" + ]; + A004 -> _016:w [ arrowhead="tee" ]; + A005 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _017 [ shape="record", label="Var sint32" ]; + A005 -> _017:w [ arrowhead="tee" ]; + A006 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _018 [ shape="record", label="Var sint32" ]; + A006 -> _018:w [ arrowhead="tee" ]; + A007 [ label="D[]", shape="oval" ]; + _019 [ label="roots:*", style="filled", color="lightblue", shape="box" ]; + { rank=same; A007; _019; } + _019 -> A007 [ arrowhead="tee" ]; + _020 [ shape="record", label="<_p1> Ref" ]; + _020:_p1 -> A010:w [ taillabel="[..]", labeldistance="1.7", + labelangle="+40", color="red" + ]; + A007 -> _020:w [ arrowhead="tee" ]; + A008 [ label="R[]", shape="oval", fillcolor="green", style="filled" ]; + _021 [ label="roots:*", style="filled", color="lightblue", shape="box" ]; + { rank=same; A008; _021; } + _021 -> A008 [ arrowhead="tee" ]; + _022 [ shape="record", label="Mem sint32" ]; + A008 -> _022:w [ arrowhead="tee" ]; + A009 [ label="RW[]", shape="oval", fillcolor="green", style="filled" ]; + _023 [ label="roots:*", style="filled", color="lightblue", shape="box" ]; + { rank=same; A009; _023; } + _023 -> A009 [ arrowhead="tee" ]; + _024 [ shape="record", label="Mem sint32" ]; + A009 -> _024:w [ arrowhead="tee" ]; + A010 [ label="R[]", shape="oval", fillcolor="green", style="filled" ]; + _025 [ label="roots:*", style="filled", color="lightblue", shape="box" ]; + { rank=same; A010; _025; } + _025 -> A010 [ arrowhead="tee" ]; + _026 [ shape="record", label="Mem sint32" ]; + A010 -> _026:w [ arrowhead="tee" ]; +} diff --git a/src/plugins/wp/tests/wp_region/oracle/structarray1.res.oracle b/src/plugins/wp/tests/wp_region/oracle/structarray1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..eac3247d2ca75c18f6bdb8de8851ca83750f7ac4 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/structarray1.res.oracle @@ -0,0 +1,4 @@ +[kernel] Parsing tests/wp_region/structarray1.i (no preprocessing) +[wp] Region Graph: tests/wp_region/result/structarray1/region/job.dot +[wp] Running WP plugin... +[wp] Warning: Missing RTE guards diff --git a/src/plugins/wp/tests/wp_region/oracle/structarray1/region/job.dot b/src/plugins/wp/tests/wp_region/oracle/structarray1/region/job.dot new file mode 100644 index 0000000000000000000000000000000000000000..c9b16ac8ffe732d0e3f0782dc984f4254a571ad3 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/structarray1/region/job.dot @@ -0,0 +1,70 @@ +digraph "job" { + rankdir="LR" ; + node [ fontname="monospace" ]; + edge [ fontname="monospace" ]; + V000 [ label="M", shape="cds", style="filled", fillcolor="yellow" ]; + V000:e -> A000 ; + V001 [ label="X", shape="cds", style="filled", fillcolor="yellow" ]; + V001:e -> A001 ; + V002 [ label="R", shape="cds", style="filled", fillcolor="yellow" ]; + V002:e -> A002 ; + V003 [ label="i", shape="cds", style="filled", fillcolor="yellow" ]; + V003:e -> A003 ; + V004 [ label="j", shape="cds", style="filled", fillcolor="yellow" ]; + V004:e -> A004 ; + A000 [ label="D", shape="oval" ]; + _005 [ label="roots:&M", style="filled", color="lightblue", shape="box" ]; + { rank=same; A000; _005; } + _005 -> A000 [ arrowhead="tee" ]; + _006 [ shape="record", label="<_p1> Ref" ]; + _006:_p1 -> A005:w [ taillabel="*", labelangle="+30", color="red" ]; + A000 -> _006:w [ arrowhead="tee" ]; + A001 [ label="D", shape="oval" ]; + _007 [ label="roots:&X", style="filled", color="lightblue", shape="box" ]; + { rank=same; A001; _007; } + _007 -> A001 [ arrowhead="tee" ]; + _008 [ shape="record", label="<_p1> Ref" ]; + _008:_p1 -> A006:w [ taillabel="*", labelangle="+30", color="red" ]; + A001 -> _008:w [ arrowhead="tee" ]; + A002 [ label="D", shape="oval" ]; + _009 [ label="roots:&R", style="filled", color="lightblue", shape="box" ]; + { rank=same; A002; _009; } + _009 -> A002 [ arrowhead="tee" ]; + _010 [ shape="record", label="<_p1> Ref" ]; + _010:_p1 -> A006:w [ taillabel="*", labelangle="+30", color="red" ]; + A002 -> _010:w [ arrowhead="tee" ]; + A003 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _011 [ shape="record", label="Var sint32" ]; + A003 -> _011:w [ arrowhead="tee" ]; + A004 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _012 [ shape="record", label="Var sint32" ]; + A004 -> _012:w [ arrowhead="tee" ]; + A005 [ label="", shape="oval" ]; + _013 [ label="roots:&M", style="filled", color="lightblue", shape="box" ]; + { rank=same; A005; _013; } + _013 -> A005 [ arrowhead="tee" ]; + _014 [ shape="record", label="<_p1> 0..511: D32[4,4]" ]; + _014:_p1 -> A007 [ style="dotted" ]; + A005 -> _014:w [ arrowhead="tee" ]; + A006 [ label="&", shape="oval", fillcolor="orange", style="filled" ]; + _015 [ label="roots:*", style="filled", color="lightblue", shape="box" ]; + { rank=same; A006; _015; } + _015 -> A006 [ arrowhead="tee" ]; + _016 [ shape="record", label="<_p1> 0..127: D32[4]" ]; + _016:_p1 -> A008 [ style="dotted" ]; + A006 -> _016:w [ arrowhead="tee" ]; + A007 [ label="R", shape="oval", fillcolor="green", style="filled" ]; + _017 [ label="roots:&M+(..)", style="filled", color="lightblue", + shape="box" + ]; + { rank=same; A007; _017; } + _017 -> A007 [ arrowhead="tee" ]; + _018 [ shape="record", label="Mem sint32" ]; + A007 -> _018:w [ arrowhead="tee" ]; + A008 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _019 [ label="roots:*", style="filled", color="lightblue", shape="box" ]; + { rank=same; A008; _019; } + _019 -> A008 [ arrowhead="tee" ]; + _020 [ shape="record", label="Mem sint32" ]; + A008 -> _020:w [ arrowhead="tee" ]; +} diff --git a/src/plugins/wp/tests/wp_region/oracle/structarray2.res.oracle b/src/plugins/wp/tests/wp_region/oracle/structarray2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..178fe6a89808245f88bbd916e648129d57347505 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/structarray2.res.oracle @@ -0,0 +1,4 @@ +[kernel] Parsing tests/wp_region/structarray2.i (no preprocessing) +[wp] Region Graph: tests/wp_region/result/structarray2/region/job.dot +[wp] Running WP plugin... +[wp] Warning: Missing RTE guards diff --git a/src/plugins/wp/tests/wp_region/oracle/structarray2/region/job.dot b/src/plugins/wp/tests/wp_region/oracle/structarray2/region/job.dot new file mode 100644 index 0000000000000000000000000000000000000000..c230c91fe3fba56ccab5ad31aeb5b20e6952036a --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/structarray2/region/job.dot @@ -0,0 +1,97 @@ +digraph "job" { + rankdir="LR" ; + node [ fontname="monospace" ]; + edge [ fontname="monospace" ]; + V000 [ label="M", shape="cds", style="filled", fillcolor="yellow" ]; + V000:e -> A000 ; + V001 [ label="X", shape="cds", style="filled", fillcolor="yellow" ]; + V001:e -> A001 ; + V002 [ label="R", shape="cds", style="filled", fillcolor="yellow" ]; + V002:e -> A002 ; + V003 [ label="i", shape="cds", style="filled", fillcolor="yellow" ]; + V003:e -> A003 ; + V004 [ label="j", shape="cds", style="filled", fillcolor="yellow" ]; + V004:e -> A004 ; + V005 [ label="C", shape="cds", style="filled", fillcolor="yellow" ]; + V005:e -> A005 ; + A000 [ label="D", shape="oval" ]; + _006 [ label="roots:&M", style="filled", color="lightblue", shape="box" ]; + { rank=same; A000; _006; } + _006 -> A000 [ arrowhead="tee" ]; + _007 [ shape="record", label="<_p1> Ref" ]; + _007:_p1 -> A006:w [ taillabel="*", labelangle="+30", color="red" ]; + A000 -> _007:w [ arrowhead="tee" ]; + A001 [ label="D", shape="oval" ]; + _008 [ label="roots:&X", style="filled", color="lightblue", shape="box" ]; + { rank=same; A001; _008; } + _008 -> A001 [ arrowhead="tee" ]; + _009 [ shape="record", label="<_p1> Ref" ]; + _009:_p1 -> A007:w [ taillabel="*", labelangle="+30", color="red" ]; + A001 -> _009:w [ arrowhead="tee" ]; + A002 [ label="D", shape="oval" ]; + _010 [ label="roots:&R", style="filled", color="lightblue", shape="box" ]; + { rank=same; A002; _010; } + _010 -> A002 [ arrowhead="tee" ]; + _011 [ shape="record", label="<_p1> Ref" ]; + _011:_p1 -> A008:w [ taillabel="*", labelangle="+30", color="red" ]; + A002 -> _011:w [ arrowhead="tee" ]; + A003 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _012 [ shape="record", label="Var sint32" ]; + A003 -> _012:w [ arrowhead="tee" ]; + A004 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _013 [ shape="record", label="Var sint32" ]; + A004 -> _013:w [ arrowhead="tee" ]; + A005 [ label="DW", shape="oval", fillcolor="green", style="filled" ]; + _014 [ shape="record", label="<_p1> Var ptr" ]; + _014:_p1 -> A009:w [ taillabel="*", labelangle="+30", color="red" ]; + A005 -> _014:w [ arrowhead="tee" ]; + A006 [ label="", shape="oval" ]; + _015 [ label="roots:&M", style="filled", color="lightblue", shape="box" ]; + { rank=same; A006; _015; } + _015 -> A006 [ arrowhead="tee" ]; + _016 [ shape="record", label="<_p1> 0..511: D32[4,4]" ]; + _016:_p1 -> A010 [ style="dotted" ]; + A006 -> _016:w [ arrowhead="tee" ]; + A007 [ label="", shape="oval" ]; + _017 [ label="roots:&X", style="filled", color="lightblue", shape="box" ]; + { rank=same; A007; _017; } + _017 -> A007 [ arrowhead="tee" ]; + _018 [ shape="record", label="<_p1> 0..127: D32[4]" ]; + _018:_p1 -> A011 [ style="dotted" ]; + A007 -> _018:w [ arrowhead="tee" ]; + A008 [ label="", shape="oval" ]; + _019 [ label="roots:&R", style="filled", color="lightblue", shape="box" ]; + { rank=same; A008; _019; } + _019 -> A008 [ arrowhead="tee" ]; + _020 [ shape="record", label="<_p1> 0..127: D32[4]" ]; + _020:_p1 -> A012 [ style="dotted" ]; + A008 -> _020:w [ arrowhead="tee" ]; + A009 [ label="&", shape="oval", fillcolor="orange", style="filled" ]; + _021 [ shape="record", label="<_p1> 0..127: D32[4]" ]; + _021:_p1 -> A010 [ style="dotted" ]; + A009 -> _021:w [ arrowhead="tee" ]; + A010 [ label="R", shape="oval", fillcolor="green", style="filled" ]; + _022 [ label="roots:&M+(..)", style="filled", color="lightblue", + shape="box" + ]; + { rank=same; A010; _022; } + _022 -> A010 [ arrowhead="tee" ]; + _023 [ shape="record", label="Mem sint32" ]; + A010 -> _023:w [ arrowhead="tee" ]; + A011 [ label="R", shape="oval", fillcolor="green", style="filled" ]; + _024 [ label="roots:&X+(..)", style="filled", color="lightblue", + shape="box" + ]; + { rank=same; A011; _024; } + _024 -> A011 [ arrowhead="tee" ]; + _025 [ shape="record", label="Mem sint32" ]; + A011 -> _025:w [ arrowhead="tee" ]; + A012 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _026 [ label="roots:&R+(..)", style="filled", color="lightblue", + shape="box" + ]; + { rank=same; A012; _026; } + _026 -> A012 [ arrowhead="tee" ]; + _027 [ shape="record", label="Mem sint32" ]; + A012 -> _027:w [ arrowhead="tee" ]; +} diff --git a/src/plugins/wp/tests/wp_region/oracle/structarray3.res.oracle b/src/plugins/wp/tests/wp_region/oracle/structarray3.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..1d4865e408e6511794022d8846142fd16724b46e --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/structarray3.res.oracle @@ -0,0 +1,4 @@ +[kernel] Parsing tests/wp_region/structarray3.i (no preprocessing) +[wp] Region Graph: tests/wp_region/result/structarray3/region/job.dot +[wp] Running WP plugin... +[wp] Warning: Missing RTE guards diff --git a/src/plugins/wp/tests/wp_region/oracle/structarray3/region/job.dot b/src/plugins/wp/tests/wp_region/oracle/structarray3/region/job.dot new file mode 100644 index 0000000000000000000000000000000000000000..8f7746c098f792497d8e861672c41824c426e180 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/structarray3/region/job.dot @@ -0,0 +1,114 @@ +digraph "job" { + rankdir="LR" ; + node [ fontname="monospace" ]; + edge [ fontname="monospace" ]; + V000 [ label="c", shape="cds", style="filled", fillcolor="yellow" ]; + V000:e -> A000 ; + V001 [ label="P", shape="cds", style="filled", fillcolor="yellow" ]; + V001:e -> A001 ; + V002 [ label="Q", shape="cds", style="filled", fillcolor="yellow" ]; + V002:e -> A002 ; + V003 [ label="X", shape="cds", style="filled", fillcolor="yellow" ]; + V003:e -> A003 ; + V004 [ label="R", shape="cds", style="filled", fillcolor="yellow" ]; + V004:e -> A004 ; + V005 [ label="M", shape="cds", style="filled", fillcolor="yellow" ]; + V005:e -> A005 ; + V006 [ label="tmp", shape="cds", style="filled", fillcolor="yellow" ]; + V006:e -> A006 ; + V007 [ label="i", shape="cds", style="filled", fillcolor="yellow" ]; + V007:e -> A007 ; + V008 [ label="j", shape="cds", style="filled", fillcolor="yellow" ]; + V008:e -> A008 ; + A000 [ label="R", shape="oval", fillcolor="green", style="filled" ]; + _009 [ label="roots:&c", style="filled", color="lightblue", shape="box" ]; + { rank=same; A000; _009; } + _009 -> A000 [ arrowhead="tee" ]; + _010 [ shape="record", label="Var sint32" ]; + A000 -> _010:w [ arrowhead="tee" ]; + A001 [ label="D", shape="oval" ]; + _011 [ label="roots:&P", style="filled", color="lightblue", shape="box" ]; + { rank=same; A001; _011; } + _011 -> A001 [ arrowhead="tee" ]; + _012 [ shape="record", label="<_p1> Ref" ]; + _012:_p1 -> A009:w [ taillabel="*", labelangle="+30", color="red" ]; + A001 -> _012:w [ arrowhead="tee" ]; + A002 [ label="D", shape="oval" ]; + _013 [ label="roots:&Q", style="filled", color="lightblue", shape="box" ]; + { rank=same; A002; _013; } + _013 -> A002 [ arrowhead="tee" ]; + _014 [ shape="record", label="<_p1> Ref" ]; + _014:_p1 -> A009:w [ taillabel="*", labelangle="+30", color="red" ]; + A002 -> _014:w [ arrowhead="tee" ]; + A003 [ label="D", shape="oval" ]; + _015 [ label="roots:&X", style="filled", color="lightblue", shape="box" ]; + { rank=same; A003; _015; } + _015 -> A003 [ arrowhead="tee" ]; + _016 [ shape="record", label="<_p1> Ref" ]; + _016:_p1 -> A010:w [ taillabel="*", labelangle="+30", color="red" ]; + A003 -> _016:w [ arrowhead="tee" ]; + A004 [ label="D", shape="oval" ]; + _017 [ label="roots:&R", style="filled", color="lightblue", shape="box" ]; + { rank=same; A004; _017; } + _017 -> A004 [ arrowhead="tee" ]; + _018 [ shape="record", label="<_p1> Ref" ]; + _018:_p1 -> A011:w [ taillabel="*", labelangle="+30", color="red" ]; + A004 -> _018:w [ arrowhead="tee" ]; + A005 [ label="DW", shape="oval", fillcolor="green", style="filled" ]; + _019 [ shape="record", label="<_p1> Var ptr" ]; + _019:_p1 -> A009:w [ taillabel="*", labelangle="+30", color="red" ]; + A005 -> _019:w [ arrowhead="tee" ]; + A006 [ label="DW", shape="oval", fillcolor="green", style="filled" ]; + _020 [ shape="record", label="<_p1> Var ptr" ]; + _020:_p1 -> A009:w [ taillabel="*", labelangle="+30", color="red" ]; + A006 -> _020:w [ arrowhead="tee" ]; + A007 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _021 [ shape="record", label="Var sint32" ]; + A007 -> _021:w [ arrowhead="tee" ]; + A008 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _022 [ shape="record", label="Var sint32" ]; + A008 -> _022:w [ arrowhead="tee" ]; + A009 [ label="&", shape="oval", fillcolor="orange", style="filled" ]; + _023 [ label="roots:*", style="filled", color="lightblue", shape="box" ]; + { rank=same; A009; _023; } + _023 -> A009 [ arrowhead="tee" ]; + _024 [ shape="record", label="<_p1> 0..511: D32[4,4]" ]; + _024:_p1 -> A012 [ style="dotted" ]; + A009 -> _024:w [ arrowhead="tee" ]; + A010 [ label="", shape="oval" ]; + _025 [ label="roots:&X", style="filled", color="lightblue", shape="box" ]; + { rank=same; A010; _025; } + _025 -> A010 [ arrowhead="tee" ]; + _026 [ shape="record", label="<_p1> 0..127: D32[4]" ]; + _026:_p1 -> A013 [ style="dotted" ]; + A010 -> _026:w [ arrowhead="tee" ]; + A011 [ label="", shape="oval" ]; + _027 [ label="roots:&R", style="filled", color="lightblue", shape="box" ]; + { rank=same; A011; _027; } + _027 -> A011 [ arrowhead="tee" ]; + _028 [ shape="record", label="<_p1> 0..127: D32[4]" ]; + _028:_p1 -> A014 [ style="dotted" ]; + A011 -> _028:w [ arrowhead="tee" ]; + A012 [ label="R", shape="oval", fillcolor="green", style="filled" ]; + _029 [ label="roots:*", style="filled", color="lightblue", shape="box" ]; + { rank=same; A012; _029; } + _029 -> A012 [ arrowhead="tee" ]; + _030 [ shape="record", label="Mem sint32" ]; + A012 -> _030:w [ arrowhead="tee" ]; + A013 [ label="R", shape="oval", fillcolor="green", style="filled" ]; + _031 [ label="roots:&X+(..)", style="filled", color="lightblue", + shape="box" + ]; + { rank=same; A013; _031; } + _031 -> A013 [ arrowhead="tee" ]; + _032 [ shape="record", label="Mem sint32" ]; + A013 -> _032:w [ arrowhead="tee" ]; + A014 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _033 [ label="roots:&R+(..)", style="filled", color="lightblue", + shape="box" + ]; + { rank=same; A014; _033; } + _033 -> A014 [ arrowhead="tee" ]; + _034 [ shape="record", label="Mem sint32" ]; + A014 -> _034:w [ arrowhead="tee" ]; +} diff --git a/src/plugins/wp/tests/wp_region/oracle/structarray4.res.oracle b/src/plugins/wp/tests/wp_region/oracle/structarray4.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..2bc45be7e59d5d04cc65b58b30e9b86dea76af19 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/structarray4.res.oracle @@ -0,0 +1,4 @@ +[kernel] Parsing tests/wp_region/structarray4.i (no preprocessing) +[wp] Region Graph: tests/wp_region/result/structarray4/region/job.dot +[wp] Running WP plugin... +[wp] Warning: Missing RTE guards diff --git a/src/plugins/wp/tests/wp_region/oracle/structarray4/region/job.dot b/src/plugins/wp/tests/wp_region/oracle/structarray4/region/job.dot new file mode 100644 index 0000000000000000000000000000000000000000..7e75e99526513c32b32f184aa7c173118bac28b1 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/structarray4/region/job.dot @@ -0,0 +1,110 @@ +digraph "job" { + rankdir="LR" ; + node [ fontname="monospace" ]; + edge [ fontname="monospace" ]; + V000 [ label="M", shape="cds", style="filled", fillcolor="yellow" ]; + V000:e -> A000 ; + V001 [ label="X", shape="cds", style="filled", fillcolor="yellow" ]; + V001:e -> A001 ; + V002 [ label="R", shape="cds", style="filled", fillcolor="yellow" ]; + V002:e -> A002 ; + V003 [ label="p", shape="cds", style="filled", fillcolor="yellow" ]; + V003:e -> A003 ; + V004 [ label="i", shape="cds", style="filled", fillcolor="yellow" ]; + V004:e -> A004 ; + V005 [ label="j", shape="cds", style="filled", fillcolor="yellow" ]; + V005:e -> A005 ; + V006 [ label="C", shape="cds", style="filled", fillcolor="yellow" ]; + V006:e -> A006 ; + A000 [ label="D", shape="oval" ]; + _007 [ label="roots:&M", style="filled", color="lightblue", shape="box" ]; + { rank=same; A000; _007; } + _007 -> A000 [ arrowhead="tee" ]; + _008 [ shape="record", label="<_p1> Ref" ]; + _008:_p1 -> A007:w [ taillabel="*", labelangle="+30", color="red" ]; + A000 -> _008:w [ arrowhead="tee" ]; + A001 [ label="D", shape="oval" ]; + _009 [ label="roots:&X", style="filled", color="lightblue", shape="box" ]; + { rank=same; A001; _009; } + _009 -> A001 [ arrowhead="tee" ]; + _010 [ shape="record", label="<_p1> Ref" ]; + _010:_p1 -> A008:w [ taillabel="*", labelangle="+30", color="red" ]; + A001 -> _010:w [ arrowhead="tee" ]; + A002 [ label="D", shape="oval" ]; + _011 [ label="roots:&R", style="filled", color="lightblue", shape="box" ]; + { rank=same; A002; _011; } + _011 -> A002 [ arrowhead="tee" ]; + _012 [ shape="record", label="<_p1> Ref" ]; + _012:_p1 -> A009:w [ taillabel="*", labelangle="+30", color="red" ]; + A002 -> _012:w [ arrowhead="tee" ]; + A003 [ label="DW", shape="oval", fillcolor="green", style="filled" ]; + _013 [ shape="record", label="<_p1> Var ptr" ]; + _013:_p1 -> A010:w [ taillabel="[..]", labeldistance="1.7", + labelangle="+40", color="red" + ]; + A003 -> _013:w [ arrowhead="tee" ]; + A004 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _014 [ shape="record", label="Var sint32" ]; + A004 -> _014:w [ arrowhead="tee" ]; + A005 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _015 [ shape="record", label="Var sint32" ]; + A005 -> _015:w [ arrowhead="tee" ]; + A006 [ label="DW", shape="oval", fillcolor="green", style="filled" ]; + _016 [ shape="record", label="<_p1> Var ptr" ]; + _016:_p1 -> A011:w [ taillabel="*", labelangle="+30", color="red" ]; + A006 -> _016:w [ arrowhead="tee" ]; + A007 [ label="", shape="oval" ]; + _017 [ label="roots:&M", style="filled", color="lightblue", shape="box" ]; + { rank=same; A007; _017; } + _017 -> A007 [ arrowhead="tee" ]; + _018 [ shape="record", label="<_p1> 0..511: D32[16]" ]; + _018:_p1 -> A012 [ style="dotted" ]; + A007 -> _018:w [ arrowhead="tee" ]; + A008 [ label="", shape="oval" ]; + _019 [ label="roots:&X", style="filled", color="lightblue", shape="box" ]; + { rank=same; A008; _019; } + _019 -> A008 [ arrowhead="tee" ]; + _020 [ shape="record", label="<_p1> 0..127: D32[4]" ]; + _020:_p1 -> A013 [ style="dotted" ]; + A008 -> _020:w [ arrowhead="tee" ]; + A009 [ label="", shape="oval" ]; + _021 [ label="roots:&R", style="filled", color="lightblue", shape="box" ]; + { rank=same; A009; _021; } + _021 -> A009 [ arrowhead="tee" ]; + _022 [ shape="record", label="<_p1> 0..127: D32[4]" ]; + _022:_p1 -> A014 [ style="dotted" ]; + A009 -> _022:w [ arrowhead="tee" ]; + A010 [ label="[]&", shape="oval", fillcolor="orange", style="filled" ]; + _023 [ label="roots:*", style="filled", color="lightblue", shape="box" ]; + { rank=same; A010; _023; } + _023 -> A010 [ arrowhead="tee" ]; + _024 [ shape="record", label="<_p1> 0..511: D32[16]" ]; + _024:_p1 -> A012 [ style="dotted" ]; + A010 -> _024:w [ arrowhead="tee" ]; + A011 [ label="&", shape="oval", fillcolor="orange", style="filled" ]; + _025 [ shape="record", label="<_p1> 0..127: D32[4]" ]; + _025:_p1 -> A012 [ style="dotted" ]; + A011 -> _025:w [ arrowhead="tee" ]; + A012 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _026 [ label="roots:*", style="filled", color="lightblue", shape="box" ]; + { rank=same; A012; _026; } + _026 -> A012 [ arrowhead="tee" ]; + _027 [ shape="record", label="Mem sint32" ]; + A012 -> _027:w [ arrowhead="tee" ]; + A013 [ label="R", shape="oval", fillcolor="green", style="filled" ]; + _028 [ label="roots:&X+(..)", style="filled", color="lightblue", + shape="box" + ]; + { rank=same; A013; _028; } + _028 -> A013 [ arrowhead="tee" ]; + _029 [ shape="record", label="Mem sint32" ]; + A013 -> _029:w [ arrowhead="tee" ]; + A014 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _030 [ label="roots:&R+(..)", style="filled", color="lightblue", + shape="box" + ]; + { rank=same; A014; _030; } + _030 -> A014 [ arrowhead="tee" ]; + _031 [ shape="record", label="Mem sint32" ]; + A014 -> _031:w [ arrowhead="tee" ]; +} diff --git a/src/plugins/wp/tests/wp_region/oracle/swap.res.oracle b/src/plugins/wp/tests/wp_region/oracle/swap.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..d7076d6dbc8cb0e241490c9707bd7bc5470ba1e7 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/swap.res.oracle @@ -0,0 +1,4 @@ +[kernel] Parsing tests/wp_region/swap.i (no preprocessing) +[wp] Region Graph: tests/wp_region/result/swap/region/job.dot +[wp] Running WP plugin... +[wp] Warning: Missing RTE guards diff --git a/src/plugins/wp/tests/wp_region/oracle/swap/region/job.dot b/src/plugins/wp/tests/wp_region/oracle/swap/region/job.dot new file mode 100644 index 0000000000000000000000000000000000000000..f4e8e067375c647f46f431296f159c8600f387aa --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle/swap/region/job.dot @@ -0,0 +1,40 @@ +digraph "job" { + rankdir="LR" ; + node [ fontname="monospace" ]; + edge [ fontname="monospace" ]; + V000 [ label="x", shape="cds", style="filled", fillcolor="yellow" ]; + V000:e -> A000 ; + V001 [ label="y", shape="cds", style="filled", fillcolor="yellow" ]; + V001:e -> A001 ; + V002 [ label="t", shape="cds", style="filled", fillcolor="yellow" ]; + V002:e -> A002 ; + A000 [ label="D", shape="oval" ]; + _003 [ label="roots:&x", style="filled", color="lightblue", shape="box" ]; + { rank=same; A000; _003; } + _003 -> A000 [ arrowhead="tee" ]; + _004 [ shape="record", label="<_p1> Ref" ]; + _004:_p1 -> A003:w [ taillabel="*", labelangle="+30", color="red" ]; + A000 -> _004:w [ arrowhead="tee" ]; + A001 [ label="D", shape="oval" ]; + _005 [ label="roots:&y", style="filled", color="lightblue", shape="box" ]; + { rank=same; A001; _005; } + _005 -> A001 [ arrowhead="tee" ]; + _006 [ shape="record", label="<_p1> Ref" ]; + _006:_p1 -> A004:w [ taillabel="*", labelangle="+30", color="red" ]; + A001 -> _006:w [ arrowhead="tee" ]; + A002 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _007 [ shape="record", label="Var sint32" ]; + A002 -> _007:w [ arrowhead="tee" ]; + A003 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _008 [ label="roots:&x", style="filled", color="lightblue", shape="box" ]; + { rank=same; A003; _008; } + _008 -> A003 [ arrowhead="tee" ]; + _009 [ shape="record", label="Var sint32" ]; + A003 -> _009:w [ arrowhead="tee" ]; + A004 [ label="RW", shape="oval", fillcolor="green", style="filled" ]; + _010 [ label="roots:&y", style="filled", color="lightblue", shape="box" ]; + { rank=same; A004; _010; } + _010 -> A004 [ arrowhead="tee" ]; + _011 [ shape="record", label="Var sint32" ]; + A004 -> _011:w [ arrowhead="tee" ]; +} diff --git a/src/plugins/wp/tests/wp_region/oracle_qualif/array1.res.oracle b/src/plugins/wp/tests/wp_region/oracle_qualif/array1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..1104fba8da15783a9af200a808ac6497ae76452b --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle_qualif/array1.res.oracle @@ -0,0 +1,10 @@ +# frama-c -wp [...] +[kernel] Parsing tests/wp_region/array1.i (no preprocessing) +[wp] Running WP plugin... +[wp] Loading driver 'share/wp.driver' +[wp] Warning: Missing RTE guards +[wp] 0 goal scheduled +[wp] Proved goals: 0 / 0 +[wp] Report in: 'tests/wp_region/oracle_qualif/array1.0.report.json' +[wp] Report out: 'tests/wp_region/result_qualif/array1.0.report.json' +------------------------------------------------------------- diff --git a/src/plugins/wp/tests/wp_region/oracle_qualif/array2.res.oracle b/src/plugins/wp/tests/wp_region/oracle_qualif/array2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..abd77f2e04f52c9431005eba9996abb777f85bee --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle_qualif/array2.res.oracle @@ -0,0 +1,10 @@ +# frama-c -wp [...] +[kernel] Parsing tests/wp_region/array2.i (no preprocessing) +[wp] Running WP plugin... +[wp] Loading driver 'share/wp.driver' +[wp] Warning: Missing RTE guards +[wp] 0 goal scheduled +[wp] Proved goals: 0 / 0 +[wp] Report in: 'tests/wp_region/oracle_qualif/array2.0.report.json' +[wp] Report out: 'tests/wp_region/result_qualif/array2.0.report.json' +------------------------------------------------------------- diff --git a/src/plugins/wp/tests/wp_region/oracle_qualif/array3.res.oracle b/src/plugins/wp/tests/wp_region/oracle_qualif/array3.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..ae12b744a10ff18184e3687712a0364d896970b2 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle_qualif/array3.res.oracle @@ -0,0 +1,10 @@ +# frama-c -wp [...] +[kernel] Parsing tests/wp_region/array3.i (no preprocessing) +[wp] Running WP plugin... +[wp] Loading driver 'share/wp.driver' +[wp] Warning: Missing RTE guards +[wp] 0 goal scheduled +[wp] Proved goals: 0 / 0 +[wp] Report in: 'tests/wp_region/oracle_qualif/array3.0.report.json' +[wp] Report out: 'tests/wp_region/result_qualif/array3.0.report.json' +------------------------------------------------------------- diff --git a/src/plugins/wp/tests/wp_region/oracle_qualif/array4.res.oracle b/src/plugins/wp/tests/wp_region/oracle_qualif/array4.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..27b0fb5624bac6cc7269f18a84f1a3348a7383b6 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle_qualif/array4.res.oracle @@ -0,0 +1,10 @@ +# frama-c -wp [...] +[kernel] Parsing tests/wp_region/array4.i (no preprocessing) +[wp] Running WP plugin... +[wp] Loading driver 'share/wp.driver' +[wp] Warning: Missing RTE guards +[wp] 0 goal scheduled +[wp] Proved goals: 0 / 0 +[wp] Report in: 'tests/wp_region/oracle_qualif/array4.0.report.json' +[wp] Report out: 'tests/wp_region/result_qualif/array4.0.report.json' +------------------------------------------------------------- diff --git a/src/plugins/wp/tests/wp_region/oracle_qualif/array5.res.oracle b/src/plugins/wp/tests/wp_region/oracle_qualif/array5.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..74acbbde6f5560d61df4c43cc7baba4d0e116147 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle_qualif/array5.res.oracle @@ -0,0 +1,10 @@ +# frama-c -wp [...] +[kernel] Parsing tests/wp_region/array5.i (no preprocessing) +[wp] Running WP plugin... +[wp] Loading driver 'share/wp.driver' +[wp] Warning: Missing RTE guards +[wp] 0 goal scheduled +[wp] Proved goals: 0 / 0 +[wp] Report in: 'tests/wp_region/oracle_qualif/array5.0.report.json' +[wp] Report out: 'tests/wp_region/result_qualif/array5.0.report.json' +------------------------------------------------------------- diff --git a/src/plugins/wp/tests/wp_region/oracle_qualif/array6.res.oracle b/src/plugins/wp/tests/wp_region/oracle_qualif/array6.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..5732e647753b6122c337e4a827b660523bc86dac --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle_qualif/array6.res.oracle @@ -0,0 +1,10 @@ +# frama-c -wp [...] +[kernel] Parsing tests/wp_region/array6.i (no preprocessing) +[wp] Running WP plugin... +[wp] Loading driver 'share/wp.driver' +[wp] Warning: Missing RTE guards +[wp] 0 goal scheduled +[wp] Proved goals: 0 / 0 +[wp] Report in: 'tests/wp_region/oracle_qualif/array6.0.report.json' +[wp] Report out: 'tests/wp_region/result_qualif/array6.0.report.json' +------------------------------------------------------------- diff --git a/src/plugins/wp/tests/wp_region/oracle_qualif/array7.res.oracle b/src/plugins/wp/tests/wp_region/oracle_qualif/array7.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..ad26b6b026cda98aa9b737e6ef3cd7611e03425f --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle_qualif/array7.res.oracle @@ -0,0 +1,10 @@ +# frama-c -wp [...] +[kernel] Parsing tests/wp_region/array7.i (no preprocessing) +[wp] Running WP plugin... +[wp] Loading driver 'share/wp.driver' +[wp] Warning: Missing RTE guards +[wp] 0 goal scheduled +[wp] Proved goals: 0 / 0 +[wp] Report in: 'tests/wp_region/oracle_qualif/array7.0.report.json' +[wp] Report out: 'tests/wp_region/result_qualif/array7.0.report.json' +------------------------------------------------------------- diff --git a/src/plugins/wp/tests/wp_region/oracle_qualif/array8.res.oracle b/src/plugins/wp/tests/wp_region/oracle_qualif/array8.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..5c2c5ca7afbd0de1ce75a2dfd14c3c58439f80ad --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle_qualif/array8.res.oracle @@ -0,0 +1,10 @@ +# frama-c -wp [...] +[kernel] Parsing tests/wp_region/array8.i (no preprocessing) +[wp] Running WP plugin... +[wp] Loading driver 'share/wp.driver' +[wp] Warning: Missing RTE guards +[wp] 0 goal scheduled +[wp] Proved goals: 0 / 0 +[wp] Report in: 'tests/wp_region/oracle_qualif/array8.0.report.json' +[wp] Report out: 'tests/wp_region/result_qualif/array8.0.report.json' +------------------------------------------------------------- diff --git a/src/plugins/wp/tests/wp_region/oracle_qualif/fb_ADD.res.oracle b/src/plugins/wp/tests/wp_region/oracle_qualif/fb_ADD.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..33eaf9d7ddab649bf56632e7581860c0c56b8199 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle_qualif/fb_ADD.res.oracle @@ -0,0 +1,10 @@ +# frama-c -wp [...] +[kernel] Parsing tests/wp_region/fb_ADD.i (no preprocessing) +[wp] Running WP plugin... +[wp] Loading driver 'share/wp.driver' +[wp] Warning: Missing RTE guards +[wp] 0 goal scheduled +[wp] Proved goals: 0 / 0 +[wp] Report in: 'tests/wp_region/oracle_qualif/fb_ADD.0.report.json' +[wp] Report out: 'tests/wp_region/result_qualif/fb_ADD.0.report.json' +------------------------------------------------------------- diff --git a/src/plugins/wp/tests/wp_region/oracle_qualif/fb_SORT.res.oracle b/src/plugins/wp/tests/wp_region/oracle_qualif/fb_SORT.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..e0be524f223e42cf1d1eb2c30e56c4b1a4a4d8f7 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle_qualif/fb_SORT.res.oracle @@ -0,0 +1,10 @@ +# frama-c -wp [...] +[kernel] Parsing tests/wp_region/fb_SORT.i (no preprocessing) +[wp] Running WP plugin... +[wp] Loading driver 'share/wp.driver' +[wp] Warning: Missing RTE guards +[wp] 0 goal scheduled +[wp] Proved goals: 0 / 0 +[wp] Report in: 'tests/wp_region/oracle_qualif/fb_SORT.0.report.json' +[wp] Report out: 'tests/wp_region/result_qualif/fb_SORT.0.report.json' +------------------------------------------------------------- diff --git a/src/plugins/wp/tests/wp_region/oracle_qualif/garbled.res.oracle b/src/plugins/wp/tests/wp_region/oracle_qualif/garbled.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..8dd7d80af3d6ea1ea51b43be8c649d5ec4eb59e1 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle_qualif/garbled.res.oracle @@ -0,0 +1,10 @@ +# frama-c -wp [...] +[kernel] Parsing tests/wp_region/garbled.i (no preprocessing) +[wp] Running WP plugin... +[wp] Loading driver 'share/wp.driver' +[wp] Warning: Missing RTE guards +[wp] 0 goal scheduled +[wp] Proved goals: 0 / 0 +[wp] Report in: 'tests/wp_region/oracle_qualif/garbled.0.report.json' +[wp] Report out: 'tests/wp_region/result_qualif/garbled.0.report.json' +------------------------------------------------------------- diff --git a/src/plugins/wp/tests/wp_region/oracle_qualif/index.res.oracle b/src/plugins/wp/tests/wp_region/oracle_qualif/index.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..af97d99c26e36511609936a5f386c9c3db1d3bfd --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle_qualif/index.res.oracle @@ -0,0 +1,10 @@ +# frama-c -wp [...] +[kernel] Parsing tests/wp_region/index.i (no preprocessing) +[wp] Running WP plugin... +[wp] Loading driver 'share/wp.driver' +[wp] Warning: Missing RTE guards +[wp] 0 goal scheduled +[wp] Proved goals: 0 / 0 +[wp] Report in: 'tests/wp_region/oracle_qualif/index.0.report.json' +[wp] Report out: 'tests/wp_region/result_qualif/index.0.report.json' +------------------------------------------------------------- diff --git a/src/plugins/wp/tests/wp_region/oracle_qualif/matrix.res.oracle b/src/plugins/wp/tests/wp_region/oracle_qualif/matrix.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..ad21316f06b9e791d9f2f671e735f3e75d393aeb --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle_qualif/matrix.res.oracle @@ -0,0 +1,10 @@ +# frama-c -wp [...] +[kernel] Parsing tests/wp_region/matrix.i (no preprocessing) +[wp] Running WP plugin... +[wp] Loading driver 'share/wp.driver' +[wp] Warning: Missing RTE guards +[wp] 0 goal scheduled +[wp] Proved goals: 0 / 0 +[wp] Report in: 'tests/wp_region/oracle_qualif/matrix.0.report.json' +[wp] Report out: 'tests/wp_region/result_qualif/matrix.0.report.json' +------------------------------------------------------------- diff --git a/src/plugins/wp/tests/wp_region/oracle_qualif/structarray1.res.oracle b/src/plugins/wp/tests/wp_region/oracle_qualif/structarray1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..8819e244467624ca0fb1b763841345d163a19e20 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle_qualif/structarray1.res.oracle @@ -0,0 +1,10 @@ +# frama-c -wp [...] +[kernel] Parsing tests/wp_region/structarray1.i (no preprocessing) +[wp] Running WP plugin... +[wp] Loading driver 'share/wp.driver' +[wp] Warning: Missing RTE guards +[wp] 0 goal scheduled +[wp] Proved goals: 0 / 0 +[wp] Report in: 'tests/wp_region/oracle_qualif/structarray1.0.report.json' +[wp] Report out: 'tests/wp_region/result_qualif/structarray1.0.report.json' +------------------------------------------------------------- diff --git a/src/plugins/wp/tests/wp_region/oracle_qualif/structarray2.res.oracle b/src/plugins/wp/tests/wp_region/oracle_qualif/structarray2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..c416a3c4c89a8995e8cb82833a82132378d8bdcc --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle_qualif/structarray2.res.oracle @@ -0,0 +1,10 @@ +# frama-c -wp [...] +[kernel] Parsing tests/wp_region/structarray2.i (no preprocessing) +[wp] Running WP plugin... +[wp] Loading driver 'share/wp.driver' +[wp] Warning: Missing RTE guards +[wp] 0 goal scheduled +[wp] Proved goals: 0 / 0 +[wp] Report in: 'tests/wp_region/oracle_qualif/structarray2.0.report.json' +[wp] Report out: 'tests/wp_region/result_qualif/structarray2.0.report.json' +------------------------------------------------------------- diff --git a/src/plugins/wp/tests/wp_region/oracle_qualif/structarray3.res.oracle b/src/plugins/wp/tests/wp_region/oracle_qualif/structarray3.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..12107fb88f51cc2db43a3ce9a9deab0d5674a3da --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle_qualif/structarray3.res.oracle @@ -0,0 +1,10 @@ +# frama-c -wp [...] +[kernel] Parsing tests/wp_region/structarray3.i (no preprocessing) +[wp] Running WP plugin... +[wp] Loading driver 'share/wp.driver' +[wp] Warning: Missing RTE guards +[wp] 0 goal scheduled +[wp] Proved goals: 0 / 0 +[wp] Report in: 'tests/wp_region/oracle_qualif/structarray3.0.report.json' +[wp] Report out: 'tests/wp_region/result_qualif/structarray3.0.report.json' +------------------------------------------------------------- diff --git a/src/plugins/wp/tests/wp_region/oracle_qualif/structarray4.res.oracle b/src/plugins/wp/tests/wp_region/oracle_qualif/structarray4.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..4297af9bc0454c0ce34a3fce366f8ba47df91a34 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle_qualif/structarray4.res.oracle @@ -0,0 +1,10 @@ +# frama-c -wp [...] +[kernel] Parsing tests/wp_region/structarray4.i (no preprocessing) +[wp] Running WP plugin... +[wp] Loading driver 'share/wp.driver' +[wp] Warning: Missing RTE guards +[wp] 0 goal scheduled +[wp] Proved goals: 0 / 0 +[wp] Report in: 'tests/wp_region/oracle_qualif/structarray4.0.report.json' +[wp] Report out: 'tests/wp_region/result_qualif/structarray4.0.report.json' +------------------------------------------------------------- diff --git a/src/plugins/wp/tests/wp_region/oracle_qualif/swap.res.oracle b/src/plugins/wp/tests/wp_region/oracle_qualif/swap.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..3d6f5d28f72214571ee58af943d1a7d6f2fbe3c6 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/oracle_qualif/swap.res.oracle @@ -0,0 +1,10 @@ +# frama-c -wp [...] +[kernel] Parsing tests/wp_region/swap.i (no preprocessing) +[wp] Running WP plugin... +[wp] Loading driver 'share/wp.driver' +[wp] Warning: Missing RTE guards +[wp] 0 goal scheduled +[wp] Proved goals: 0 / 0 +[wp] Report in: 'tests/wp_region/oracle_qualif/swap.0.report.json' +[wp] Report out: 'tests/wp_region/result_qualif/swap.0.report.json' +------------------------------------------------------------- diff --git a/src/plugins/wp/tests/wp_region/structarray1.i b/src/plugins/wp/tests/wp_region/structarray1.i new file mode 100644 index 0000000000000000000000000000000000000000..d657867ad894507712c52647e6d164a7391f2683 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/structarray1.i @@ -0,0 +1,18 @@ +typedef struct Vector { + int coord[4]; +} * vector ; + +typedef struct Matrix { + int coef[4][4]; +} * matrix ; + +//@ region *X , *R ; +void job( matrix M , vector X , vector R ) +{ + for (int i = 0; i < 4; i++) { + R->coord[i] = 0 ; + for (int j = 0; j < 4; i++) { + R->coord[i] += M->coef[i][j] * X->coord[j]; + } + } +} diff --git a/src/plugins/wp/tests/wp_region/structarray1.i.0.report.json b/src/plugins/wp/tests/wp_region/structarray1.i.0.report.json new file mode 100644 index 0000000000000000000000000000000000000000..19765bd501b636fce433540d9e6735f51d66151d --- /dev/null +++ b/src/plugins/wp/tests/wp_region/structarray1.i.0.report.json @@ -0,0 +1 @@ +null diff --git a/src/plugins/wp/tests/wp_region/structarray2.i b/src/plugins/wp/tests/wp_region/structarray2.i new file mode 100644 index 0000000000000000000000000000000000000000..472077d231c95dd046d466e3f7871abe3e46ad43 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/structarray2.i @@ -0,0 +1,18 @@ +typedef struct Vector { + int coord[4]; +} * vector ; + +typedef struct Matrix { + int coef[4][4]; +} * matrix ; + +void job( matrix M , vector X , vector R ) +{ + for (int i = 0; i < 4; i++) { + R->coord[i] = 0 ; + for (int j = 0; j < 4; i++) { + vector C = (vector) (M->coef[i]) ; + R->coord[i] += C->coord[j] * X->coord[j]; + } + } +} diff --git a/src/plugins/wp/tests/wp_region/structarray2.i.0.report.json b/src/plugins/wp/tests/wp_region/structarray2.i.0.report.json new file mode 100644 index 0000000000000000000000000000000000000000..19765bd501b636fce433540d9e6735f51d66151d --- /dev/null +++ b/src/plugins/wp/tests/wp_region/structarray2.i.0.report.json @@ -0,0 +1 @@ +null diff --git a/src/plugins/wp/tests/wp_region/structarray3.i b/src/plugins/wp/tests/wp_region/structarray3.i new file mode 100644 index 0000000000000000000000000000000000000000..fc05e0a87a77b692fcd6a4106ffcf7532a7dd039 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/structarray3.i @@ -0,0 +1,18 @@ +typedef struct Vector { + int coord[4]; +} * vector ; + +typedef struct Matrix { + int coef[4][4]; +} * matrix ; + +void job( int c , matrix P , matrix Q , vector X , vector R ) +{ + matrix M = c ? P : Q ; + for (int i = 0; i < 4; i++) { + R->coord[i] = 0 ; + for (int j = 0; j < 4; i++) { + R->coord[i] += M->coef[i][j] * X->coord[j]; + } + } +} diff --git a/src/plugins/wp/tests/wp_region/structarray3.i.0.report.json b/src/plugins/wp/tests/wp_region/structarray3.i.0.report.json new file mode 100644 index 0000000000000000000000000000000000000000..19765bd501b636fce433540d9e6735f51d66151d --- /dev/null +++ b/src/plugins/wp/tests/wp_region/structarray3.i.0.report.json @@ -0,0 +1 @@ +null diff --git a/src/plugins/wp/tests/wp_region/structarray4.i b/src/plugins/wp/tests/wp_region/structarray4.i new file mode 100644 index 0000000000000000000000000000000000000000..c27ac7ed8f7fa1ea3ea5a52a0c1e87b0a23a1bd9 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/structarray4.i @@ -0,0 +1,20 @@ +typedef struct Vector { + int coord[4]; +} * vector ; + +typedef struct Matrix { + int coef[4][4]; +} * matrix ; + +void job( matrix M , vector X , vector R ) +{ + int * p = (int *) M->coef ; + p[14] = 2 ; + for (int i = 0; i < 4; i++) { + R->coord[i] = 0 ; + for (int j = 0; j < 4; i++) { + vector C = (vector) (M->coef[i]) ; + R->coord[i] += C->coord[j] * X->coord[j]; + } + } +} diff --git a/src/plugins/wp/tests/wp_region/structarray4.i.0.report.json b/src/plugins/wp/tests/wp_region/structarray4.i.0.report.json new file mode 100644 index 0000000000000000000000000000000000000000..19765bd501b636fce433540d9e6735f51d66151d --- /dev/null +++ b/src/plugins/wp/tests/wp_region/structarray4.i.0.report.json @@ -0,0 +1 @@ +null diff --git a/src/plugins/wp/tests/wp_region/swap.i b/src/plugins/wp/tests/wp_region/swap.i new file mode 100644 index 0000000000000000000000000000000000000000..f299d9687047b1df56a724cb770bc950972274f0 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/swap.i @@ -0,0 +1,8 @@ +// Test Config + +void job(int *x,int *y) +{ + int t = *x ; + *x = *y ; + *y = t ; +} diff --git a/src/plugins/wp/tests/wp_region/swap.i.0.report.json b/src/plugins/wp/tests/wp_region/swap.i.0.report.json new file mode 100644 index 0000000000000000000000000000000000000000..19765bd501b636fce433540d9e6735f51d66151d --- /dev/null +++ b/src/plugins/wp/tests/wp_region/swap.i.0.report.json @@ -0,0 +1 @@ +null diff --git a/src/plugins/wp/tests/wp_region/test_config b/src/plugins/wp/tests/wp_region/test_config new file mode 100644 index 0000000000000000000000000000000000000000..36003c91eeff9b752b08515c756f5e0268465e56 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/test_config @@ -0,0 +1,3 @@ +CMD: @frama-c@ -no-autoload-plugins -load-module wp +LOG: @PTEST_NAME@/region/job.dot +OPT: -wp-prover none -wp-region -wp-msg-key dot,chunk,roots,garbled -wp-out @PTEST_DIR@/result/@PTEST_NAME@ -wp-fct job diff --git a/src/plugins/wp/tests/wp_region/test_config_qualif b/src/plugins/wp/tests/wp_region/test_config_qualif new file mode 100644 index 0000000000000000000000000000000000000000..a6cc52bc1de6ecd3ad796948a36e74a1c67f1fd9 --- /dev/null +++ b/src/plugins/wp/tests/wp_region/test_config_qualif @@ -0,0 +1 @@ +OPT: -wp-region diff --git a/src/plugins/wp/tests/wp_store/oracle_qualif/struct.0.session/cache/4f3f819897e17d244836052e8e391eeb.json b/src/plugins/wp/tests/wp_store/oracle_qualif/struct.0.session/cache/0397215be1cc2dddcdf43bf1afd9ffe4.json similarity index 91% rename from src/plugins/wp/tests/wp_store/oracle_qualif/struct.0.session/cache/4f3f819897e17d244836052e8e391eeb.json rename to src/plugins/wp/tests/wp_store/oracle_qualif/struct.0.session/cache/0397215be1cc2dddcdf43bf1afd9ffe4.json index bd18f2d694e48d3b4a4118ffec9d15fadad58200..37a7317f01bf64583e8f6b99bd73f938e4face03 100644 --- a/src/plugins/wp/tests/wp_store/oracle_qualif/struct.0.session/cache/4f3f819897e17d244836052e8e391eeb.json +++ b/src/plugins/wp/tests/wp_store/oracle_qualif/struct.0.session/cache/0397215be1cc2dddcdf43bf1afd9ffe4.json @@ -1,2 +1,2 @@ -{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0297, +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0284, "steps": 36 } diff --git a/src/plugins/wp/wpPropId.ml b/src/plugins/wp/wpPropId.ml index ee456686522018f540bd0c8641fa71e1720e1d63..4a154c087a2c207237585752f955d3d57dd00842 100644 --- a/src/plugins/wp/wpPropId.ml +++ b/src/plugins/wp/wpPropId.ml @@ -567,7 +567,7 @@ let stmt_hints hs s = match label with | Label(a,_,src) -> if src then add_hint hs a | Default _ -> add_hint hs "default" - | Case(e,_) -> match Ctypes.get_int e with + | Case(e,_) -> match Ctypes.get_int64 e with | Some k -> add_hint hs ("case-" ^ Int64.to_string k) | None -> () ) s.labels diff --git a/src/plugins/wp/wp_parameters.ml b/src/plugins/wp/wp_parameters.ml index 008dde9e07fd880217e16b011afd64fa3581ce3c..521d61ef385abcbf80ea69639788b4a6ec8a030a 100644 --- a/src/plugins/wp/wp_parameters.ml +++ b/src/plugins/wp/wp_parameters.ml @@ -105,23 +105,6 @@ module Properties = end) let () = on_reset Properties.clear -type job = - | WP_None - | WP_All - | WP_SkipFct of Cil_datatype.Kf.Set.t - | WP_Fct of Cil_datatype.Kf.Set.t - -let job () = - if WP.get () || not (Functions.is_empty()) || - not (Behaviors.is_empty()) || not (Properties.is_empty()) - then - if Functions.is_empty() then - if SkipFunctions.is_empty () then WP_All - else WP_SkipFct (SkipFunctions.get()) - else - WP_Fct (Cil_datatype.Kf.Set.diff (Functions.get()) (SkipFunctions.get())) - else WP_None - let () = Parameter_customize.set_group wp_generation module StatusAll = False(struct @@ -150,6 +133,42 @@ module StatusMaybe = let help = "Select properties with status 'Maybe'." end) +(* ------------------------------------------------------------------------ *) +(* --- Selected Functions --- *) +(* ------------------------------------------------------------------------ *) + +module Fct = Cil_datatype.Kf.Set + +type functions = + | Fct_none + | Fct_all + | Fct_skip of Fct.t + | Fct_list of Fct.t + +let iter_fct phi = function + | Fct_none -> () + | Fct_all -> Globals.Functions.iter phi + | Fct_skip fs -> + Globals.Functions.iter + (fun kf -> if not (Fct.mem kf fs) then phi kf) + | Fct_list fs -> Fct.iter phi fs + +let get_kf () = + if Functions.is_empty() then + if SkipFunctions.is_empty () then Fct_all + else Fct_skip (SkipFunctions.get()) + else + Fct_list (Fct.diff (Functions.get()) (SkipFunctions.get())) + +let get_wp () = + if WP.get () || not (Functions.is_empty()) || + not (Behaviors.is_empty()) || not (Properties.is_empty()) + then get_kf () + else Fct_none + +let iter_wp f = iter_fct f (get_wp ()) +let iter_kf f = iter_fct f (get_kf ()) + (* ------------------------------------------------------------------------ *) (* --- Memory Models --- *) (* ------------------------------------------------------------------------ *) @@ -246,6 +265,83 @@ module Volatile = Use -wp-no-volatile to ignore volatile attributes." end) +(* -------------------------------------------------------------------------- *) +(* --- Region Model --- *) +(* -------------------------------------------------------------------------- *) + +let wp_region = add_group "Region Analysis" + +let () = Parameter_customize.set_group wp_region +let () = Parameter_customize.do_not_save () +module Region = + False + (struct + let option_name = "-wp-region" + let help = "Perform Region Analysis (experimental)" + end) + +let () = Parameter_customize.set_group wp_region +let () = Parameter_customize.do_not_save () +module Region_fixpoint = + True + (struct + let option_name = "-wp-region-fixpoint" + let help = "Compute region aliasing fixpoint" + end) + +let () = Parameter_customize.set_group wp_region +let () = Parameter_customize.do_not_save () +module Region_cluster = + True + (struct + let option_name = "-wp-region-cluster" + let help = "Compute region clustering fixpoint" + end) + +let () = Parameter_customize.set_group wp_region +let () = Parameter_customize.do_not_save () +module Region_inline = + True + (struct + let option_name = "-wp-region-inline" + let help = "Inline aliased sub-clusters" + end) + +let () = Parameter_customize.set_group wp_region +let () = Parameter_customize.do_not_save () +module Region_rw = + True + (struct + let option_name = "-wp-region-rw" + let help = "Written region are considered read-write by default" + end) + +let () = Parameter_customize.set_group wp_region +let () = Parameter_customize.do_not_save () +module Region_pack = + True + (struct + let option_name = "-wp-region-pack" + let help = "Pack clusters by default" + end) + +let () = Parameter_customize.set_group wp_region +let () = Parameter_customize.do_not_save () +module Region_flat = + False + (struct + let option_name = "-wp-region-flat" + let help = "Flatten arrays by default" + end) + +let () = Parameter_customize.set_group wp_region +module Region_annot = + False + (struct + let option_name = "-region-annot" + let help = "Register '@region' ACSL Annotations (auto with -wp-region)" + end) + (* ------------------------------------------------------------------------ *) (* --- WP Strategy --- *) (* ------------------------------------------------------------------------ *) diff --git a/src/plugins/wp/wp_parameters.mli b/src/plugins/wp/wp_parameters.mli index 43db4176f892546d7a789889da12388e74c96846..a25d76270d259a539cbb604339121f161ce20bae 100644 --- a/src/plugins/wp/wp_parameters.mli +++ b/src/plugins/wp/wp_parameters.mli @@ -24,6 +24,20 @@ include Plugin.S val reset : unit -> unit +(** {2 Function Selection} *) + +type functions = + | Fct_none + | Fct_all + | Fct_skip of Cil_datatype.Kf.Set.t + | Fct_list of Cil_datatype.Kf.Set.t + +val get_kf : unit -> functions +val get_wp : unit -> functions +val iter_fct : (Kernel_function.t -> unit) -> functions -> unit +val iter_kf : (Kernel_function.t -> unit) -> unit +val iter_wp : (Kernel_function.t -> unit) -> unit + (** {2 Goal Selection} *) module WP : Parameter_sig.Bool @@ -34,14 +48,6 @@ module StatusTrue : Parameter_sig.Bool module StatusFalse : Parameter_sig.Bool module StatusMaybe : Parameter_sig.Bool -type job = - | WP_None - | WP_All - | WP_SkipFct of Cil_datatype.Kf.Set.t - | WP_Fct of Cil_datatype.Kf.Set.t - -val job : unit -> job - (** {2 Model Selection} *) val has_dkey : category -> bool @@ -60,6 +66,15 @@ module Volatile : Parameter_sig.Bool (* module BoolRange : Parameter_sig.Bool *) (* use get_bool_range() below *) +module Region: Parameter_sig.Bool +module Region_rw: Parameter_sig.Bool +module Region_pack: Parameter_sig.Bool +module Region_flat: Parameter_sig.Bool +module Region_annot: Parameter_sig.Bool +module Region_inline: Parameter_sig.Bool +module Region_fixpoint: Parameter_sig.Bool +module Region_cluster: Parameter_sig.Bool + (** {2 Computation Strategies} *) module Init: Parameter_sig.Bool