Skip to content

Commit 9b348e9

Browse files
Merge pull request #59 from goblint/const_fold_ov
Make constFold aware of overflows and prevent constant folding on overflows
2 parents a91dde0 + 1cea359 commit 9b348e9

File tree

3 files changed

+30
-14
lines changed

3 files changed

+30
-14
lines changed

src/cil.ml

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2181,6 +2181,18 @@ let rec getInteger (e:exp) : cilint option =
21812181
end
21822182
| _ -> None
21832183

2184+
(** Return the (wrapped) constant i if it fits into ik without any signed overflow,
2185+
otherwise return fallback *)
2186+
let const_if_not_overflow fallback ik i =
2187+
if not (isSigned ik) then
2188+
kintegerCilint ik i
2189+
else
2190+
let i', trunc = truncateCilint ik i in
2191+
if trunc = NoTruncation then
2192+
kintegerCilint ik i
2193+
else
2194+
fallback
2195+
21842196
let isZero (e: exp) : bool =
21852197
match getInteger e with
21862198
| Some n -> is_zero_cilint n
@@ -2518,16 +2530,16 @@ and constFold (machdep: bool) (e: exp) : exp =
25182530
try
25192531
let tk =
25202532
match unrollType tres with
2521-
TInt(ik, _) -> ik
2533+
| TInt(ik, _) -> ik
25222534
| TEnum (ei, _) -> ei.ekind
25232535
| _ -> raise Not_found (* probably a float *)
25242536
in
25252537
match constFold machdep e1 with
2526-
Const(CInt(i,ik,_)) -> begin
2527-
let ic = mkCilintIk ik i in
2538+
| Const(CInt(i,ik,s)) -> begin
2539+
let ic = mkCilintIk ik i in
25282540
match unop with
2529-
Neg -> kintegerCilint tk (neg_cilint ic)
2530-
| BNot -> kintegerCilint tk (lognot_cilint ic)
2541+
Neg -> const_if_not_overflow (UnOp(Neg,Const(CInt(i,ik,s)),tres)) tk (neg_cilint ic)
2542+
| BNot -> const_if_not_overflow (UnOp(BNot,Const(CInt(i,ik,s)),tres)) tk (lognot_cilint ic)
25312543
| LNot -> if is_zero_cilint ic then one else zero
25322544
end
25332545
| e1c -> UnOp(unop, e1c, tres)
@@ -2622,27 +2634,28 @@ and constFoldBinOp (machdep: bool) bop e1 e2 tres =
26222634
with SizeOfError _ -> false
26232635
else false
26242636
in
2637+
let no_ov = const_if_not_overflow (BinOp(bop, e1', e2', tres)) tk in
26252638
(* Assume that the necessary promotions have been done *)
26262639
match bop, getInteger e1', getInteger e2' with
2627-
| PlusA, Some i1, Some i2 -> kintegerCilint tk (add_cilint i1 i2)
2640+
| PlusA, Some i1, Some i2 -> no_ov (add_cilint i1 i2)
26282641
| PlusA, Some z, _ when is_zero_cilint z -> collapse e2'
26292642
| PlusA, _, Some z when is_zero_cilint z -> collapse e1'
2630-
| MinusA, Some i1, Some i2 -> kintegerCilint tk (sub_cilint i1 i2)
2643+
| MinusA, Some i1, Some i2 -> no_ov (sub_cilint i1 i2)
26312644
| MinusA, _, Some z when is_zero_cilint z -> collapse e1'
2632-
| Mult, Some i1, Some i2 -> kintegerCilint tk (mul_cilint i1 i2)
2645+
| Mult, Some i1, Some i2 -> no_ov (mul_cilint i1 i2)
26332646
| Mult, Some z, _ when is_zero_cilint z -> collapse0 ()
26342647
| Mult, _, Some z when is_zero_cilint z -> collapse0 ()
26352648
| Mult, Some o, _ when compare_cilint o one_cilint = 0 -> collapse e2'
26362649
| Mult, _, Some o when compare_cilint o one_cilint = 0 -> collapse e1'
26372650
| Div, Some i1, Some i2 -> begin
2638-
try kintegerCilint tk (div0_cilint i1 i2)
2651+
try no_ov (div0_cilint i1 i2)
26392652
with Division_by_zero -> BinOp(bop, e1', e2', tres)
2640-
end
2653+
end
26412654
| Div, _, Some o when compare_cilint o one_cilint = 0 -> collapse e1'
26422655
| Mod, Some i1, Some i2 -> begin
2643-
try kintegerCilint tk (rem_cilint i1 i2)
2656+
try no_ov (rem_cilint i1 i2)
26442657
with Division_by_zero -> BinOp(bop, e1', e2', tres)
2645-
end
2658+
end
26462659
| Mod, _, Some o when compare_cilint o one_cilint = 0 -> collapse0 ()
26472660

26482661
| BAnd, Some i1, Some i2 -> kintegerCilint tk (logand_cilint i1 i2)

src/cil.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2584,6 +2584,8 @@ val mkCilint : ikind -> int64 -> cilint
25842584

25852585
val mkCilintIk : ikind -> cilint -> cilint
25862586

2587+
val const_if_not_overflow : exp -> ikind -> cilint -> exp
2588+
25872589
(** The size of a type, in bytes. Returns a constant expression or a
25882590
* "sizeof" expression if it cannot compute the size. This function
25892591
* is architecture dependent, so you should only call this after you

src/frontc/cabs2cil.ml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3805,10 +3805,11 @@ and doExp (asconst: bool) (* This expression is used as a constant *)
38053805
let (se, e', t) = doExp asconst e (AExp None) in
38063806
if isIntegralType t then
38073807
let tres = integralPromotion t in
3808+
let fallback = UnOp(Neg, makeCastT ~e:e' ~oldt:t ~newt:tres, tres) in
38083809
let e'' =
38093810
match e', tres with
3810-
| Const(CInt(i, _, _)), TInt(ik, _) -> kintegerCilint ik (neg_cilint i)
3811-
| _ -> UnOp(Neg, makeCastT ~e:e' ~oldt:t ~newt:tres, tres)
3811+
| Const(CInt(i, _, _)), TInt(ik, _) -> const_if_not_overflow fallback ik (neg_cilint i)
3812+
| _ -> fallback
38123813
in
38133814
finishExp se e'' tres
38143815
else

0 commit comments

Comments
 (0)