Skip to content

Commit 21ee2ad

Browse files
authored
Merge pull request #1869 from goblint/apron-invariant-constFold
Avoid `Cil.constFold` in Apron invariant generation
2 parents 9f5560e + aeb2829 commit 21ee2ad

File tree

2 files changed

+51
-26
lines changed

2 files changed

+51
-26
lines changed

src/cdomains/apron/gobApron.apron.ml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ module Coeff =
1919
struct
2020
include Coeff
2121

22+
let pp = print
23+
include Printable.SimpleFormat (
24+
struct
25+
type nonrec t = t
26+
let pp = pp
27+
end
28+
)
29+
2230
let s_of_z z = Coeff.s_of_mpqf (Mpqf.of_mpz (Z_mlgmpidl.mpz_of_z z))
2331
end
2432

src/cdomains/apron/sharedFunctions.apron.ml

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ let int_of_scalar ?(scalewith=Z.one) ?round (scalar: Scalar.t) =
4141
| _ ->
4242
failwith ("int_of_scalar: unsupported: " ^ Scalar.show scalar)
4343

44+
let int_of_coeff ?scalewith ?round (coeff: Coeff.union_5) =
45+
match coeff with
46+
| Scalar scalar -> int_of_scalar ?scalewith ?round scalar
47+
| Interval _ -> None
4448

4549
module type ConvertArg =
4650
sig
@@ -269,37 +273,44 @@ struct
269273

270274
let longlong = TInt(ILongLong,[])
271275

276+
let int_of_coeff_warn ~scalewith coeff =
277+
match int_of_coeff ~scalewith coeff with
278+
| Some i -> i
279+
| None ->
280+
M.warn ~category:Analyzer "Invariant Apron: coefficient is not int: %a" Coeff.pretty coeff;
281+
raise Unsupported_Linexpr1
272282

273283
(** Returned boolean indicates whether returned expression should be negated. *)
274-
let coeff_to_const ~scalewith (c:Coeff.union_5) =
275-
match c with
276-
| Scalar c ->
277-
(match int_of_scalar ?scalewith c with
278-
| Some i ->
279-
let ci,truncation = truncateCilint ILongLong i in
280-
if truncation = NoTruncation then
281-
if Z.compare i Z.zero >= 0 then
282-
false, Const (CInt(i,ILongLong,None))
283-
else
284-
(* attempt to negate if that does not cause an overflow *)
285-
let cneg, truncation = truncateCilint ILongLong (Z.neg i) in
286-
if truncation = NoTruncation then
287-
true, Const (CInt((Z.neg i),ILongLong,None))
288-
else
289-
false, Const (CInt(i,ILongLong,None))
290-
else
291-
(M.warn ~category:Analyzer "Invariant Apron: coefficient is not int: %a" Scalar.pretty c; raise Unsupported_Linexpr1)
292-
| None -> raise Unsupported_Linexpr1)
293-
| _ -> raise Unsupported_Linexpr1
284+
let cil_exp_of_int i =
285+
let ci,truncation = truncateCilint ILongLong i in
286+
if truncation = NoTruncation then
287+
if Z.compare i Z.zero >= 0 then
288+
false, Const (CInt(i,ILongLong,None))
289+
else
290+
(* attempt to negate if that does not cause an overflow *)
291+
let cneg, truncation = truncateCilint ILongLong (Z.neg i) in
292+
if truncation = NoTruncation then
293+
true, Const (CInt((Z.neg i),ILongLong,None))
294+
else
295+
false, Const (CInt(i,ILongLong,None))
296+
else
297+
raise Unsupported_Linexpr1
294298

295299
(** Returned boolean indicates whether returned expression should be negated. *)
296300
let cil_exp_of_linexpr1_term ~scalewith (c: Coeff.t) v =
297301
match V.to_cil_varinfo v with
298302
| Some vinfo when IntDomain.Size.is_cast_injective ~from_type:vinfo.vtype ~to_type:(TInt(ILongLong,[])) ->
299303
let var = Cilfacade.mkCast ~e:(Lval(Var vinfo,NoOffset)) ~newt:longlong in
300-
let flip, coeff = coeff_to_const ~scalewith c in
301-
let prod = BinOp(Mult, coeff, var, longlong) in
302-
flip, prod
304+
let i = int_of_coeff_warn ~scalewith c in
305+
if Z.equal i Z.one then
306+
false, var
307+
else if Z.equal i Z.minus_one then
308+
true, var
309+
else (
310+
let flip, coeff = cil_exp_of_int i in
311+
let prod = BinOp(Mult, coeff, var, longlong) in
312+
flip, prod
313+
)
303314
| None ->
304315
M.warn ~category:Analyzer "Invariant Apron: cannot convert to cil var: %a" Var.pretty v;
305316
raise Unsupported_Linexpr1
@@ -308,8 +319,14 @@ struct
308319
raise Unsupported_Linexpr1
309320

310321
(** Returned booleans indicates whether returned expressions should be negated. *)
311-
let cil_exp_of_linexpr1 ?scalewith (linexpr1:Linexpr1.t) =
312-
let terms = ref [coeff_to_const ~scalewith (Linexpr1.get_cst linexpr1)] in
322+
let cil_exp_of_linexpr1 ~scalewith (linexpr1:Linexpr1.t) =
323+
let terms =
324+
let c = Linexpr1.get_cst linexpr1 in
325+
if Coeff.is_zero c then
326+
ref []
327+
else
328+
ref [cil_exp_of_int (int_of_coeff_warn ~scalewith c)]
329+
in
313330
let append_summand (c:Coeff.union_5) v =
314331
if not (Coeff.is_zero c) then
315332
terms := cil_exp_of_linexpr1_term ~scalewith c v :: !terms
@@ -369,7 +386,7 @@ struct
369386
| DISEQ -> Ne
370387
| EQMOD _ -> raise Unsupported_Linexpr1
371388
in
372-
Some (Cil.constFold false @@ BinOp(binop, lhs, rhs, TInt(IInt,[]))) (* constFold removes multiplication by factor 1 *)
389+
Some (BinOp(binop, lhs, rhs, TInt(IInt,[])))
373390
with
374391
Unsupported_Linexpr1 -> None
375392
end

0 commit comments

Comments
 (0)