Skip to content

Commit 66dff5a

Browse files
Merge pull request #1700 from goblint/stats_on_texpr
Closing the gaps in Texpr generation
2 parents 50e8ab9 + 3231002 commit 66dff5a

File tree

1 file changed

+33
-17
lines changed

1 file changed

+33
-17
lines changed

src/cdomains/apron/sharedFunctions.apron.ml

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,19 @@ module type SV = RelationDomain.RV with type t = Var.t
5353
type unsupported_cilExp =
5454
| Var_not_found of CilType.Varinfo.t (** Variable not found in Apron environment. *)
5555
| Cast_not_injective of CilType.Typ.t (** Cast is not injective, i.e. may under-/overflow. *)
56-
| Exp_not_supported (** Expression constructor not supported. *)
56+
| Exp_not_supported of exp[@printer fun ppf e -> Format.pp_print_string ppf (GobPretty.show (Cil.d_plainexp () e))]
5757
| Overflow (** May overflow according to Apron bounds. *)
5858
| Exp_typeOf of exn [@printer fun ppf e -> Format.pp_print_string ppf (Printexc.to_string e)] (** Expression type could not be determined. *)
59-
| BinOp_not_supported (** BinOp constructor not supported. *)
59+
| BinOp_not_supported of binop [@printer fun ppf op -> Format.pp_print_string ppf (match op with
60+
| BAnd | BOr | BXor -> "Bitwise binop"
61+
| Shiftlt | Shiftrt -> "Shift binop"
62+
| PlusPI | MinusPI | IndexPI | MinusPP -> "Pointer binop"
63+
| LAnd | LOr -> "Logical binop"
64+
| Lt | Gt | Le | Ge | Eq | Ne -> "Comparison binop"
65+
| _ -> "other binop")](** BinOp constructor not supported. *)
66+
| Ikind_non_integer of string (** Exception during trying to get ikind of a non-integer typed expression *)
6067
[@@deriving show { with_path = false }]
6168

62-
6369
(** Interface for Bounds which calculates bounds for expressions and is used inside the - Convert module. *)
6470
module type ConvBounds =
6571
sig
@@ -92,7 +98,7 @@ struct
9298
established by other analyses.*)
9399
let overflow_handling no_ov ik env expr d exp =
94100
match Cilfacade.get_ikind_exp exp with
95-
| exception Invalid_argument e -> raise (Unsupported_CilExp Exp_not_supported) (* expression is not an integer expression, i.e. float *)
101+
| exception Invalid_argument a -> raise (Unsupported_CilExp (Ikind_non_integer a)) (* expression is not an integer expression, i.e. float *)
96102
| ik ->
97103
if IntDomain.should_wrap ik || not (Lazy.force no_ov) then (
98104
let (type_min, type_max) = IntDomain.Size.range ik in
@@ -110,7 +116,7 @@ struct
110116
let query e ik =
111117
let res =
112118
match ask.f (EvalInt e) with
113-
| `Bot -> raise (Unsupported_CilExp Exp_not_supported) (* This should never happen according to Michael Schwarz *)
119+
| `Bot (* This happens when called on a pointer type; -> we can safely return top *)
114120
| `Top -> IntDomain.IntDomTuple.top_of ik
115121
| `Lifted x -> x (* Cast should be unnecessary because it should be taken care of by EvalInt. *) in
116122
if M.tracing then M.trace "relation-query" "texpr1_expr_of_cil_exp/query: %a -> %a" d_plainexp e IntDomain.IntDomTuple.pretty res;
@@ -149,7 +155,7 @@ struct
149155
*)
150156
let simplify e =
151157
GobRef.wrap AnalysisState.executing_speculative_computations true @@ fun () ->
152-
let ikind = try (Cilfacade.get_ikind_exp e) with Invalid_argument _ -> raise (Unsupported_CilExp Exp_not_supported) in
158+
let ikind = try (Cilfacade.get_ikind_exp e) with Invalid_argument a -> raise (Unsupported_CilExp (Ikind_non_integer a)) in
153159
let simp = query e ikind in
154160
let const = IntDomain.IntDomTuple.to_int @@ IntDomain.IntDomTuple.cast_to ikind simp in
155161
if M.tracing then M.trace "relation" "texpr1_expr_of_cil_exp/simplify: %a -> %a" d_plainexp e IntDomain.IntDomTuple.pretty simp;
@@ -167,14 +173,14 @@ struct
167173
Binop (Div, texpr1 e1, texpr1 e2, Int, Zero)
168174
| CastE (t, e) when Cil.isIntegralType t ->
169175
begin match IntDomain.Size.is_cast_injective ~from_type:(Cilfacade.typeOf e) ~to_type:t with (* TODO: unnecessary cast check due to overflow check below? or maybe useful in general to also assume type bounds based on argument types? *)
170-
| exception Invalid_argument _ -> raise (Unsupported_CilExp Exp_not_supported)
176+
| exception Invalid_argument a -> raise (Unsupported_CilExp (Ikind_non_integer a))
171177
| true -> texpr1 e
172178
| false -> (* Cast is not injective - we now try to establish suitable ranges manually *)
173179
let t_ik = Cilfacade.get_ikind t in
174180
(* retrieving a valuerange for a non-injective cast works by a query to the value-domain with subsequent value extraction from domtuple - which should be speculative, since it is not program code *)
175181
let const,res = GobRef.wrap AnalysisState.executing_speculative_computations true @@ fun () ->
176182
(* try to evaluate e by EvalInt Query *)
177-
let res = try (query e @@ Cilfacade.get_ikind_exp e) with Invalid_argument _ -> raise (Unsupported_CilExp Exp_not_supported) in
183+
let res = try (query e @@ Cilfacade.get_ikind_exp e) with Invalid_argument a -> raise (Unsupported_CilExp (Ikind_non_integer a)) in
178184
(* convert response to a constant *)
179185
IntDomain.IntDomTuple.to_int @@ IntDomain.IntDomTuple.cast_to t_ik res, res in
180186
match const with
@@ -190,21 +196,31 @@ struct
190196
| exception Invalid_argument _ ->
191197
raise (Unsupported_CilExp (Cast_not_injective t))
192198
end
193-
| _ ->
194-
raise (Unsupported_CilExp Exp_not_supported)
199+
| BinOp (op, _,_,_) ->
200+
raise (Unsupported_CilExp (BinOp_not_supported op))
201+
| e ->
202+
raise (Unsupported_CilExp (Exp_not_supported e))
195203
in
196204
overflow_handling no_ov ik env expr d exp;
197205
expr
198-
| exception (Cilfacade.TypeOfError _ as e)
199-
| exception (Invalid_argument _ as e) ->
206+
| exception (Cilfacade.TypeOfError _ as e) ->
200207
raise (Unsupported_CilExp (Exp_typeOf e))
208+
| exception (Invalid_argument a) ->
209+
raise (Unsupported_CilExp (Ikind_non_integer a))
201210
in
202211
texpr1_expr_of_cil_exp exp
203212
in
204213
let exp = Cil.constFold false exp in
205-
let res = conv exp in
206-
if M.tracing then M.trace "relation" "texpr1_expr_of_cil_exp: %a -> %a (%b)" d_plainexp exp Texpr1.Expr.pretty res (Lazy.force no_ov);
207-
res
214+
if M.tracing then
215+
match conv exp with
216+
| exception Unsupported_CilExp ex ->
217+
M.tracel "rel-texpr-cil-conv" "unsuccessfull: %s" (show_unsupported_cilExp ex);
218+
raise (Unsupported_CilExp ex)
219+
| res ->
220+
M.trace "relation" "texpr1_expr_of_cil_exp: %a -> %a (%b)" d_plainexp exp Texpr1.Expr.pretty res (Lazy.force no_ov);
221+
M.tracel "rel-texpr-cil-conv" "successfull: Good";
222+
res
223+
else conv exp
208224

209225
let texpr1_of_cil_exp ask d env e no_ov =
210226
let res = texpr1_expr_of_cil_exp ask d env e no_ov in
@@ -225,9 +241,9 @@ struct
225241
| Ge -> (texpr1_1, texpr1_2, SUPEQ) (* e1 >= e2 ==> e1 - e2 >= 0 *)
226242
| Eq -> (texpr1_1, texpr1_2, EQ) (* e1 == e2 ==> e1 - e2 == 0 *)
227243
| Ne -> (texpr1_1, texpr1_2, DISEQ) (* e1 != e2 ==> e1 - e2 != 0 *)
228-
| _ -> raise (Unsupported_CilExp BinOp_not_supported)
244+
| _ -> raise (Unsupported_CilExp (BinOp_not_supported r))
229245
end
230-
| _ -> raise (Unsupported_CilExp Exp_not_supported)
246+
| _ -> raise (Unsupported_CilExp (Exp_not_supported e))
231247
in
232248
let inverse_typ = function
233249
| EQ -> DISEQ

0 commit comments

Comments
 (0)