Skip to content
Snippets Groups Projects
Commit 3d09eb4a authored by Allan Blanchard's avatar Allan Blanchard
Browse files

[wp] Support nullable annotation

parent c5f46df1
No related branches found
No related tags found
No related merge requests found
...@@ -516,8 +516,8 @@ struct ...@@ -516,8 +516,8 @@ struct
type mem = type mem =
| CVAL (* By-Value variable *) | CVAL (* By-Value variable *)
| CREF (* By-Ref variable *) | CREF (* By-Ref variable *)
| CTXT (* In-context pointer *) | CTXT of MemoryContext.validity (* In-context pointer *)
| CARR (* In-context array *) | CARR of MemoryContext.validity (* In-context array *)
| HEAP (* In-heap variable *) | HEAP (* In-heap variable *)
type loc = type loc =
...@@ -562,8 +562,8 @@ struct ...@@ -562,8 +562,8 @@ struct
let vtype m x = let vtype m x =
match m with match m with
| CVAL | HEAP -> x.vtype | CVAL | HEAP -> x.vtype
| CTXT | CREF -> Cil.typeOf_pointed x.vtype | CTXT _ | CREF -> Cil.typeOf_pointed x.vtype
| CARR -> Ast_info.array_type (Cil.typeOf_pointed x.vtype) | CARR _ -> Ast_info.array_type (Cil.typeOf_pointed x.vtype)
let vobject m x = Ctypes.object_of (vtype m x) let vobject m x = Ctypes.object_of (vtype m x)
...@@ -592,8 +592,8 @@ struct ...@@ -592,8 +592,8 @@ struct
let pp_mem fmt = function let pp_mem fmt = function
| CVAL -> Format.pp_print_string fmt "var" | CVAL -> Format.pp_print_string fmt "var"
| CREF -> Format.pp_print_string fmt "ref" | CREF -> Format.pp_print_string fmt "ref"
| CTXT -> Format.pp_print_string fmt "ptr" | CTXT _ -> Format.pp_print_string fmt "ptr"
| CARR -> Format.pp_print_string fmt "arr" | CARR _ -> Format.pp_print_string fmt "arr"
| HEAP -> Format.pp_print_string fmt "mem" | HEAP -> Format.pp_print_string fmt "mem"
(* re-uses strings that are used into the description of -wp-xxx-vars *) (* re-uses strings that are used into the description of -wp-xxx-vars *)
...@@ -633,6 +633,35 @@ struct ...@@ -633,6 +633,35 @@ struct
| ByAddr -> Val(HEAP,x,[]) | ByAddr -> Val(HEAP,x,[])
| InContext _ | InArray _ | ByRef -> Ref x | InContext _ | InArray _ | ByRef -> Ref x
(* -------------------------------------------------------------------------- *)
(* --- Nullable locations --- *)
(* -------------------------------------------------------------------------- *)
module Nullable = WpContext.Generator(Varinfo)
(struct
let name = "MemVar.Nullable"
type key = varinfo
type data = lfun
let compile v =
let result = t_addr () in
let lfun = Lang.generated_f ~result "pointer_%s" v.vname in
let cluster =
Definitions.cluster ~id:"Globals" ~title:"Context pointers" ()
in
Definitions.define_symbol {
d_lfun = lfun ;
d_types = 0 ;
d_params = [] ;
d_definition = Definitions.Logic result ;
d_cluster = cluster
} ;
lfun
end)
let nullable_address v =
Lang.F.e_fun (Nullable.get v) []
(* -------------------------------------------------------------------------- *) (* -------------------------------------------------------------------------- *)
(* --- Lifting --- *) (* --- Lifting --- *)
(* -------------------------------------------------------------------------- *) (* -------------------------------------------------------------------------- *)
...@@ -644,7 +673,11 @@ struct ...@@ -644,7 +673,11 @@ struct
let mseq_of_seq seq = { pre = seq.pre.mem ; post = seq.post.mem } let mseq_of_seq seq = { pre = seq.pre.mem ; post = seq.post.mem }
let mloc_of_path m x ofs = let mloc_of_path m x ofs =
List.fold_left moffset (M.cvar (vbase m x)) ofs let l = match m with
| CTXT Nullable | CARR Nullable -> M.pointer_loc @@ nullable_address x
| _ -> M.cvar (vbase m x)
in
List.fold_left moffset l ofs
let mloc_of_loc = function let mloc_of_loc = function
| Loc l -> l | Loc l -> l
...@@ -731,8 +764,8 @@ struct ...@@ -731,8 +764,8 @@ struct
| Ref x -> | Ref x ->
begin match V.param x with begin match V.param x with
| ByRef -> Sigs.Loc(Val(CREF,x,[])) | ByRef -> Sigs.Loc(Val(CREF,x,[]))
| InContext _ -> Sigs.Loc(Val(CTXT,x,[])) | InContext n -> Sigs.Loc(Val(CTXT n,x,[]))
| InArray _ -> Sigs.Loc(Val(CARR,x,[])) | InArray n -> Sigs.Loc(Val(CARR n,x,[]))
| NotUsed | ByAddr | ByValue | ByShift -> assert false | NotUsed | ByAddr | ByValue | ByShift -> assert false
end end
| Val((CREF|CVAL),x,ofs) -> | Val((CREF|CVAL),x,ofs) ->
...@@ -741,7 +774,7 @@ struct ...@@ -741,7 +774,7 @@ struct
Cvalues.map_value Cvalues.map_value
(fun l -> Loc l) (fun l -> Loc l)
(M.load sigma.mem obj l) (M.load sigma.mem obj l)
| Val((CTXT|CARR|HEAP) as m,x,ofs) -> | Val((CTXT _|CARR _|HEAP) as m,x,ofs) ->
Cvalues.map_value Cvalues.map_value
(fun l -> Loc l) (fun l -> Loc l)
(M.load sigma.mem obj (mloc_of_path m x ofs)) (M.load sigma.mem obj (mloc_of_path m x ofs))
...@@ -772,7 +805,7 @@ struct ...@@ -772,7 +805,7 @@ struct
| Val((CREF|CVAL),x,ofs) -> | Val((CREF|CVAL),x,ofs) ->
let init = Cvalues.initialized_obj obj in let init = Cvalues.initialized_obj obj in
(memvar_stored seq obj l v) :: (memvar_set_init seq x ofs init) (memvar_stored seq obj l v) :: (memvar_set_init seq x ofs init)
| Val((CTXT|CARR|HEAP) as m,x,ofs) -> | Val((CTXT _|CARR _|HEAP) as m,x,ofs) ->
M.stored (mseq_of_seq seq) obj (mloc_of_path m x ofs) v M.stored (mseq_of_seq seq) obj (mloc_of_path m x ofs) v
| Loc l -> | Loc l ->
M.stored (mseq_of_seq seq) obj l v M.stored (mseq_of_seq seq) obj l v
...@@ -789,6 +822,8 @@ struct ...@@ -789,6 +822,8 @@ struct
let is_null = function let is_null = function
| Loc l -> M.is_null l | Loc l -> M.is_null l
| Val ((CTXT Nullable|CARR Nullable)as m,x,ofs) ->
M.is_null (mloc_of_path m x ofs)
| Ref _ | Val _ -> F.p_false | Ref _ | Val _ -> F.p_false
let rec offset = function let rec offset = function
...@@ -830,7 +865,7 @@ struct ...@@ -830,7 +865,7 @@ struct
exception ShiftMismatch exception ShiftMismatch
let is_heap_allocated = function let is_heap_allocated = function
| CREF | CVAL -> false | HEAP | CTXT | CARR -> true | CREF | CVAL -> false | HEAP | CTXT _ | CARR _ -> true
let shift_mismatch l = let shift_mismatch l =
Wp_parameters.fatal "Invalid shift : %a" pretty l Wp_parameters.fatal "Invalid shift : %a" pretty l
...@@ -938,7 +973,9 @@ struct ...@@ -938,7 +973,9 @@ struct
else else
match mem with match mem with
| CVAL | HEAP -> p_bool (ALLOC.value sigma.alloc x) | CVAL | HEAP -> p_bool (ALLOC.value sigma.alloc x)
| CREF | CTXT | CARR -> p_true | CREF | CTXT Valid | CARR Valid -> p_true
| CTXT Nullable | CARR Nullable ->
p_not @@ M.is_null (mloc_of_path mem x [])
(* segment *) (* segment *)
...@@ -1220,6 +1257,20 @@ struct ...@@ -1220,6 +1257,20 @@ struct
in in
List.map uninitialized xs List.map uninitialized xs
let scope_nullable xs =
let predicate_is_nullable v =
Option.map
(fun m ->
let addr = nullable_address v in
p_or
(M.is_null @@ M.pointer_loc addr)
(p_equal (M.pointer_val @@ M.cvar (vbase m v)) addr))
(match V.param v with
| InContext Nullable -> Some (CTXT Nullable)
| InArray Nullable -> Some (CARR Nullable)
| _ -> None)
in
List.filter_map predicate_is_nullable xs
let scope seq scope xs = let scope seq scope xs =
let xm = List.filter is_mem xs in let xm = List.filter is_mem xs in
...@@ -1227,7 +1278,8 @@ struct ...@@ -1227,7 +1278,8 @@ struct
let hmem = M.scope smem scope xm in let hmem = M.scope smem scope xm in
let hvars = scope_vars seq scope xs in let hvars = scope_vars seq scope xs in
let hinit = scope_init seq scope xs in let hinit = scope_init seq scope xs in
hvars @ hinit @ hmem let hcontext = scope_nullable xs in
hvars @ hinit @ hmem @ hcontext
let global sigma p = M.global sigma.mem p let global sigma p = M.global sigma.mem p
...@@ -1362,7 +1414,7 @@ struct ...@@ -1362,7 +1414,7 @@ struct
| Val((CVAL|CREF),_,_) as vloc -> | Val((CVAL|CREF),_,_) as vloc ->
let v = Lang.freshvar ~basename:"v" (Lang.tau_of_object obj) in let v = Lang.freshvar ~basename:"v" (Lang.tau_of_object obj) in
memvar_assigned seq obj vloc (e_var v) memvar_assigned seq obj vloc (e_var v)
| Val((HEAP|CTXT|CARR) as m,x,ofs) -> | Val((HEAP|CTXT _|CARR _) as m,x,ofs) ->
M.assigned (mseq_of_seq seq) obj (Sloc (mloc_of_path m x ofs)) M.assigned (mseq_of_seq seq) obj (Sloc (mloc_of_path m x ofs))
| Loc l -> | Loc l ->
M.assigned (mseq_of_seq seq) obj (Sloc l) M.assigned (mseq_of_seq seq) obj (Sloc l)
...@@ -1384,7 +1436,7 @@ struct ...@@ -1384,7 +1436,7 @@ struct
in in
let obj = get_obj (Ctypes.object_of x.vtype) ofs in let obj = get_obj (Ctypes.object_of x.vtype) ofs in
memvar_assigned seq obj vloc (e_var v) memvar_assigned seq obj vloc (e_var v)
| Val((HEAP|CTXT|CARR) as m,x,ofs) -> | Val((HEAP|CTXT _|CARR _) as m,x,ofs) ->
let l = mloc_of_path m x ofs in let l = mloc_of_path m x ofs in
M.assigned (mseq_of_seq seq) obj (Sarray(l,elt,n)) M.assigned (mseq_of_seq seq) obj (Sarray(l,elt,n))
| Loc l -> | Loc l ->
...@@ -1395,7 +1447,7 @@ struct ...@@ -1395,7 +1447,7 @@ struct
| Ref x -> noref ~op:"assigns to" x | Ref x -> noref ~op:"assigns to" x
| Loc l -> | Loc l ->
M.assigned (mseq_of_seq seq) obj (Srange(l,elt,a,b)) M.assigned (mseq_of_seq seq) obj (Srange(l,elt,a,b))
| Val((HEAP|CTXT|CARR) as m,x,ofs) -> | Val((HEAP|CTXT _|CARR _) as m,x,ofs) ->
M.assigned (mseq_of_seq seq) obj (Srange(mloc_of_path m x ofs,elt,a,b)) M.assigned (mseq_of_seq seq) obj (Srange(mloc_of_path m x ofs,elt,a,b))
| Val((CVAL|CREF) as m,x,ofs) -> | Val((CVAL|CREF) as m,x,ofs) ->
let k = Lang.freshvar ~basename:"k" Qed.Logic.Int in let k = Lang.freshvar ~basename:"k" Qed.Logic.Int in
...@@ -1409,7 +1461,7 @@ struct ...@@ -1409,7 +1461,7 @@ struct
| Ref x -> noref ~op:"assigns to" x | Ref x -> noref ~op:"assigns to" x
| Loc l -> | Loc l ->
M.assigned (mseq_of_seq seq) obj (Sdescr(xs,l,p)) M.assigned (mseq_of_seq seq) obj (Sdescr(xs,l,p))
| Val((HEAP|CTXT|CARR) as m,x,ofs) -> | Val((HEAP|CTXT _|CARR _) as m,x,ofs) ->
M.assigned (mseq_of_seq seq) obj (Sdescr(xs,mloc_of_path m x ofs,p)) M.assigned (mseq_of_seq seq) obj (Sdescr(xs,mloc_of_path m x ofs,p))
| Val((CVAL|CREF) as m,x,ofs) -> | Val((CVAL|CREF) as m,x,ofs) ->
(monotonic_initialized_genset seq xs m x ofs p) @ (monotonic_initialized_genset seq xs m x ofs p) @
...@@ -1479,9 +1531,15 @@ struct ...@@ -1479,9 +1531,15 @@ struct
Fseg(x,range ofs obj a b) Fseg(x,range ofs obj a b)
(* in M: *) (* in M: *)
| Rloc(obj,Val((CTXT|CARR|HEAP) as m,x,ofs)) -> (* First intercept nullable context *)
| Rloc(obj,Val((CTXT Nullable|CARR Nullable) as m,x,ofs)) ->
Lseg(Rloc(obj, mloc_of_path m x ofs))
| Rrange(Val((CTXT Nullable|CARR Nullable) as m,x,ofs),obj,a,b) ->
Lseg(Rrange(mloc_of_path m x ofs, obj, a, b))
| Rloc(obj,Val((CTXT _|CARR _|HEAP) as m,x,ofs)) ->
Mseg(Rloc(obj,mloc_of_path m x ofs),x,delta obj x ofs) Mseg(Rloc(obj,mloc_of_path m x ofs),x,delta obj x ofs)
| Rrange(Val((CTXT|CARR|HEAP) as m,x,ofs),obj,a,b) -> | Rrange(Val((CTXT _|CARR _|HEAP) as m,x,ofs),obj,a,b) ->
Mseg(Rrange(mloc_of_path m x ofs,obj,a,b),x,range ofs obj a b) Mseg(Rrange(mloc_of_path m x ofs,obj,a,b),x,range ofs obj a b)
(* -------------------------------------------------------------------------- *) (* -------------------------------------------------------------------------- *)
...@@ -1556,7 +1614,7 @@ struct ...@@ -1556,7 +1614,7 @@ struct
else [] else []
in in
Heap.Set.of_list ((Var x) :: init) Heap.Set.of_list ((Var x) :: init)
| Loc _ | Val((CTXT|CARR|HEAP),_,_) -> | Loc _ | Val((CTXT _|CARR _|HEAP),_,_) ->
M.Heap.Set.fold M.Heap.Set.fold
(fun m s -> Heap.Set.add (Mem m) s) (fun m s -> Heap.Set.add (Mem m) s)
(M.domain obj (mloc_of_loc l)) Heap.Set.empty (M.domain obj (mloc_of_loc l)) Heap.Set.empty
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
------------------------------------------------------------ ------------------------------------------------------------
Goal Check 'must_fail' (file tests/wp_plugin/nullable.i, line 14): Goal Check 'must_fail' (file tests/wp_plugin/nullable.i, line 14):
Assume { (* Then *) Have: G_p_24 = 0. } Assume { (* Then *) Have: null = pointer_p. }
Prove: false. Prove: false.
------------------------------------------------------------ ------------------------------------------------------------
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment