11open Prelude
22open Cil
33open Formatcil
4- module ES = SetDomain. Make (Exp. Exp )
54
65(* * Instruments a program by inserting asserts either:
7- - After an assignment to a variable (unless trans.assert .full is activated) and
6+ - After an assignment to a variable (unless witness.invariant .full is activated) and
87 - At join points about all local variables
98
109 OR
1110
12- - Only after pthread_mutex_lock (trans.assert.only-at-locks ), about all locals and globals
11+ - Only after pthread_mutex_lock (witness.invariant.after-lock ), about all locals and globals
1312
14- Limitations without trans.assert.only-at locks :
13+ Limitations without witness.invariant.after-lock :
1514 - Currently only works for top-level variables (not inside an array, a struct, ...)
1615 - Does not work for accesses through pointers
1716 - At join points asserts all locals, but ideally should only assert ones that are
@@ -23,9 +22,6 @@ module ES = SetDomain.Make(Exp.Exp)
2322*)
2423
2524module EvalAssert = struct
26- (* should asserts of conjuncts be one-by-one instead of one big assert? *)
27- let distinctAsserts = true
28-
2925 (* should asserts be surrounded by __VERIFIER_atomic_{begin,end}? *)
3026 let surroundByAtomic = true
3127
@@ -35,30 +31,12 @@ module EvalAssert = struct
3531 let atomicEnd = makeVarinfo true " __VERIFIER_atomic_end" (TVoid [] )
3632
3733
38- (* Turns an expression into alist of conjuncts, pulling out common conjuncts from top-level disjunctions *)
39- let rec pullOutCommonConjuncts e =
40- let rec to_conjunct_set = function
41- | BinOp (LAnd,e1 ,e2 ,_ ) -> ES. join (to_conjunct_set e1) (to_conjunct_set e2)
42- | e -> ES. singleton e
43- in
44- let combine_conjuncts es = ES. fold (fun e acc -> match acc with | None -> Some e | Some acce -> Some (BinOp (LAnd ,acce,e,Cil. intType))) es None in
45- match e with
46- | BinOp (LOr, e1 , e2 ,t ) ->
47- let e1s = pullOutCommonConjuncts e1 in
48- let e2s = pullOutCommonConjuncts e2 in
49- let common = ES. inter e1s e2s in
50- let e1s' = ES. diff e1s e2s in
51- let e2s' = ES. diff e2s e1s in
52- (match combine_conjuncts e1s', combine_conjuncts e2s' with
53- | Some e1e , Some e2e -> ES. add (BinOp (LOr ,e1e,e2e,Cil. intType)) common
54- | _ -> common (* if one of the disjuncts is empty, it is equivalent to true here *)
55- )
56- | e -> to_conjunct_set e
57-
5834 class visitor (ask :Cil.location -> Queries.ask ) = object (self )
5935 inherit nopCilVisitor
60- val full = GobConfig. get_bool " trans.assert.full"
61- val only_at_locks = GobConfig. get_bool " trans.assert.only-at-locks"
36+ val full = GobConfig. get_bool " witness.invariant.full"
37+ (* TODO: handle witness.invariant.loop-head *)
38+ val emit_after_lock = GobConfig. get_bool " witness.invariant.after-lock"
39+ val emit_other = GobConfig. get_bool " witness.invariant.other"
6240
6341 method! vstmt s =
6442 let is_lock exp args =
@@ -78,7 +56,7 @@ module EvalAssert = struct
7856 } in
7957 match (ask loc).f (Queries. Invariant context) with
8058 | `Lifted e ->
81- let es = if distinctAsserts then ES. elements (pullOutCommonConjuncts e) else [e] in
59+ let es = WitnessUtil.InvariantExp. process_exp e in
8260 let asserts = List. map (fun e -> cInstr (" %v:assert (%e:exp);" ) loc [(" assert" , Fv ass); (" exp" , Fe e)]) es in
8361 if surroundByAtomic then
8462 let abegin = (cInstr (" %v:__VERIFIER_atomic_begin();" ) loc [(" __VERIFIER_atomic_begin" , Fv atomicBegin)]) in
@@ -94,13 +72,13 @@ module EvalAssert = struct
9472 let unique_succ = s.succs <> [] && (List. hd s.succs).preds |> List. length < 2 in
9573 let instrument i loc =
9674 let instrument' lval =
97- let lval_arg = if full || only_at_locks then None else lval in
75+ let lval_arg = if full then None else lval in
9876 make_assert loc lval_arg
9977 in
10078 match i with
101- | Set ( lval , _ , _ , _ ) when not only_at_locks -> instrument' ( Some lval)
102- | Call (lval , _ , _ , _ , _ ) when not only_at_locks -> instrument' lval
103- | Call (_ , exp , args , _ , _ ) when is_lock exp args -> instrument' None
79+ | Call ( _ , exp , args , _ , _ ) when emit_after_lock && is_lock exp args -> instrument' None
80+ | Set (lval , _ , _ , _ ) when emit_other -> instrument' ( Some lval)
81+ | Call (lval , _ , _ , _ , _ ) when emit_other -> instrument' lval
10482 | _ -> []
10583 in
10684 let rec instrument_instructions = function
@@ -132,10 +110,10 @@ module EvalAssert = struct
132110
133111 let instrument_join s =
134112 match s.preds with
135- | [p1; p2] when not only_at_locks ->
113+ | [p1; p2] when emit_other ->
136114 (* exactly two predecessors -> join point, assert locals if they changed *)
137115 let join_loc = get_stmtLoc s.skind in
138- (* Possible enhancement: It would be nice to only assert locals here that were modified in either branch if trans.assert .full is false *)
116+ (* Possible enhancement: It would be nice to only assert locals here that were modified in either branch if witness.invariant .full is false *)
139117 let asserts = make_assert join_loc None in
140118 self#queueInstr asserts; ()
141119 | _ -> ()
@@ -161,7 +139,7 @@ module EvalAssert = struct
161139 else
162140 ()
163141 in
164- if not only_at_locks then (add_asserts b1; add_asserts b2);
142+ if emit_other then (add_asserts b1; add_asserts b2);
165143 s
166144 | _ -> s
167145 in
0 commit comments