This repository has been archived by the owner on Oct 30, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathinfer.ml
110 lines (104 loc) · 4.02 KB
/
infer.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
open Cil_types
let append_end l elt = List.rev_append (List.rev l) [elt]
let is_one = function
| {term_node= TConst (Integer (i, _))} when Integer.equal i Integer.one ->
true
| _ -> false
(* Extracts the varinfo of the variable and its inferred size as a term
from a term t as \valid(t). *)
let rec extract_from_valid t =
let loc = t.term_loc in
match t.term_node with
| TBinOp
( ((PlusPI | IndexPI | MinusPI) as op)
, {term_node= TCastE ((TPtr _ as ty), t)}
, ({term_node= Trange (_, Some _)} as operand2) ) ->
extract_from_valid
{t with term_node= TBinOp (op, {t with term_type= Ctype ty}, operand2)}
| TBinOp
( (PlusPI | IndexPI)
, {term_node= TLval (TVar {lv_origin= Some varinfo}, _)}
, {term_node= Trange (_, Some {term_node= TBinOp (MinusA, x, k)})} )
when is_one k ->
(varinfo, x)
| TBinOp
( (PlusPI | IndexPI)
, {term_node= TLval (TVar {lv_origin= Some varinfo}, _)}
, {term_node= Trange (_, Some bound)} ) ->
let tnode = TBinOp (PlusA, bound, Cil.lone ~loc ()) in
let einfo = {exp_type= bound.term_type; exp_name= []} in
(varinfo, Cil.term_of_exp_info t.term_loc tnode einfo)
| TBinOp
( (PlusPI | IndexPI)
, {term_node= TLval (TVar {lv_origin= Some vi}, _)}
, t2 ) ->
let tnode = TBinOp (PlusA, t2, Cil.lone ~loc ()) in
let einfo = {exp_type= t2.term_type; exp_name= []} in
(vi, Cil.term_of_exp_info t.term_loc tnode einfo)
| TBinOp
( (PlusPI | IndexPI)
, {term_node= TLval tlval}
, {term_node= Trange (_, Some {term_node= TBinOp (MinusA, x, k)})} )
when is_one k ->
let varinfo, _ = extract_from_valid {t with term_node= TLval tlval} in
(varinfo, x)
| TBinOp
( (PlusPI | IndexPI)
, {term_node= TLval tlval}
, {term_node= Trange (_, Some bound)} ) ->
let tnode = TBinOp (PlusA, bound, Cil.lone ~loc ()) in
let einfo = {exp_type= bound.term_type; exp_name= []} in
let term = Cil.term_of_exp_info t.term_loc tnode einfo in
let varinfo, _ = extract_from_valid {t with term_node= TLval tlval} in
(varinfo, term)
| TLval (TVar {lv_origin= Some vi}, TNoOffset) -> (vi, Cil.lone ~loc ())
| TLval (TMem m, TNoOffset) ->
let varinfo, _ = extract_from_valid m in
(varinfo, Cil.lone ~loc ())
| TAddrOf (TMem x, TIndex (y, TNoOffset)) ->
let x' = Cil.mkTermMem ~addr:x ~off:TNoOffset in
let rec type_of_pointed = function
| Ctype (TPtr (ty, _)) -> Ctype ty
| Ctype (TArray (ty, _, _, _)) -> Ctype ty
| Ctype (TNamed (x, _)) -> type_of_pointed (Ctype x.ttype)
| ty ->
Options.abort ~current:true "unsupported type %a"
Printer.pp_logic_type ty
in
let ty = type_of_pointed (Cil.typeOfTermLval x') in
let x' = Logic_const.term (TLval x') ty in
extract_from_valid {t with term_node= TBinOp (PlusPI, x', y)}
| _ ->
Options.debug "\\valid(%a)" Debug.pp_term t ;
assert false
let lengths_from_requires kf =
let vi = Kernel_function.get_vi kf in
let kf_tbl = Cil_datatype.Varinfo.Hashtbl.create 32 in
let o =
object
inherit Visitor.frama_c_inplace
method! vpredicate p =
if List.mem "rte" p.pred_name then Cil.SkipChildren else Cil.DoChildren
method! vpredicate_node =
function
| Pvalid (_, t) | Pvalid_read (_, t) -> (
try
let v, term = extract_from_valid t in
let terms =
try Cil_datatype.Varinfo.Hashtbl.find kf_tbl v
with Not_found -> []
in
let terms = append_end terms term in
Cil_datatype.Varinfo.Hashtbl.replace kf_tbl v terms ;
Cil.DoChildren
with _ -> Cil.DoChildren )
| _ -> Cil.DoChildren
end
in
let on_requires p =
let p' = Inline.id_pred p in
ignore (Visitor.visitFramacIdPredicate o p')
in
let on_bhv _ bhv = List.iter on_requires bhv.b_requires in
if not (Cil.is_unused_builtin vi) then Annotations.iter_behaviors on_bhv kf ;
kf_tbl