Skip to content

Commit db49fe9

Browse files
authored
Merge pull request #1274 from goblint/base-invariant-abs-cleanup
Generalize and clean up `abs` invariant in base analysis
2 parents 7fa7bfd + cdf0dee commit db49fe9

File tree

2 files changed

+33
-53
lines changed

2 files changed

+33
-53
lines changed

src/analyses/baseInvariant.ml

Lines changed: 26 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -709,18 +709,22 @@ struct
709709
| _ -> Int c
710710
in
711711
(* handle special calls *)
712-
begin match t with
713-
| TInt (ik, _) ->
714-
begin match x with
715-
| ((Var v), offs) ->
716-
if M.tracing then M.trace "invSpecial" "qry Result: %a\n" Queries.ML.pretty (ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil offs)));
717-
let tv_opt = ID.to_bool c in
718-
begin match tv_opt with
712+
begin match x, t with
713+
| (Var v, offs), TInt (ik, _) ->
714+
let tmpSpecial = ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil offs)) in
715+
if M.tracing then M.trace "invSpecial" "qry Result: %a\n" Queries.ML.pretty tmpSpecial;
716+
begin match tmpSpecial with
717+
| `Lifted (Abs (ik, xInt)) ->
718+
let c' = ID.cast_to ik c in (* different ik! *)
719+
inv_exp (Int (ID.join c' (ID.neg c'))) xInt st
720+
| tmpSpecial ->
721+
begin match ID.to_bool c with
719722
| Some tv ->
720-
begin match ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil offs)) with
723+
begin match tmpSpecial with
721724
| `Lifted (Isfinite xFloat) when tv -> inv_exp (Float (FD.finite (unroll_fk_of_exp xFloat))) xFloat st
722725
| `Lifted (Isnan xFloat) when tv -> inv_exp (Float (FD.nan_of (unroll_fk_of_exp xFloat))) xFloat st
723726
(* should be correct according to C99 standard*)
727+
(* The following do to_bool and of_bool to convert Not{0} into 1 for downstream float inversions *)
724728
| `Lifted (Isgreater (xFloat, yFloat)) -> inv_exp (Int (ID.of_bool ik tv)) (BinOp (Gt, xFloat, yFloat, (typeOf xFloat))) st
725729
| `Lifted (Isgreaterequal (xFloat, yFloat)) -> inv_exp (Int (ID.of_bool ik tv)) (BinOp (Ge, xFloat, yFloat, (typeOf xFloat))) st
726730
| `Lifted (Isless (xFloat, yFloat)) -> inv_exp (Int (ID.of_bool ik tv)) (BinOp (Lt, xFloat, yFloat, (typeOf xFloat))) st
@@ -730,9 +734,8 @@ struct
730734
end
731735
| None -> update_lval c x c' ID.pretty
732736
end
733-
| _ -> update_lval c x c' ID.pretty
734737
end
735-
| _ -> update_lval c x c' ID.pretty
738+
| _, _ -> update_lval c x c' ID.pretty
736739
end
737740
| Float c ->
738741
let c' = match t with
@@ -744,22 +747,19 @@ struct
744747
| _ -> Float c
745748
in
746749
(* handle special calls *)
747-
begin match t with
748-
| TFloat (fk, _) ->
749-
begin match x with
750-
| ((Var v), offs) ->
751-
if M.tracing then M.trace "invSpecial" "qry Result: %a\n" Queries.ML.pretty (ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil offs)));
752-
begin match ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil offs)) with
753-
| `Lifted (Ceil (ret_fk, xFloat)) -> inv_exp (Float (FD.inv_ceil (FD.cast_to ret_fk c))) xFloat st
754-
| `Lifted (Floor (ret_fk, xFloat)) -> inv_exp (Float (FD.inv_floor (FD.cast_to ret_fk c))) xFloat st
755-
| `Lifted (Fabs (ret_fk, xFloat)) ->
756-
let inv = FD.inv_fabs (FD.cast_to ret_fk c) in
757-
if FD.is_bot inv then
758-
raise Analyses.Deadcode
759-
else
760-
inv_exp (Float inv) xFloat st
761-
| _ -> update_lval c x c' FD.pretty
762-
end
750+
begin match x, t with
751+
| (Var v, offs), TFloat (fk, _) ->
752+
let tmpSpecial = ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil offs)) in
753+
if M.tracing then M.trace "invSpecial" "qry Result: %a\n" Queries.ML.pretty tmpSpecial;
754+
begin match tmpSpecial with
755+
| `Lifted (Ceil (ret_fk, xFloat)) -> inv_exp (Float (FD.inv_ceil (FD.cast_to ret_fk c))) xFloat st
756+
| `Lifted (Floor (ret_fk, xFloat)) -> inv_exp (Float (FD.inv_floor (FD.cast_to ret_fk c))) xFloat st
757+
| `Lifted (Fabs (ret_fk, xFloat)) ->
758+
let inv = FD.inv_fabs (FD.cast_to ret_fk c) in
759+
if FD.is_bot inv then
760+
raise Analyses.Deadcode
761+
else
762+
inv_exp (Float inv) xFloat st
763763
| _ -> update_lval c x c' FD.pretty
764764
end
765765
| _ -> update_lval c x c' FD.pretty
@@ -821,31 +821,4 @@ struct
821821
FD.top_of fk
822822
in
823823
inv_exp (Float ftv) exp st
824-
825-
let invariant ctx a gs st exp tv: D.t =
826-
let refine0 = invariant ctx a gs st exp tv in
827-
(* bodge for abs(...); To be removed once we have a clean solution *)
828-
let refineAbs op absargexp valexp =
829-
let flip op = match op with | Le -> Ge | Lt -> Gt | _ -> failwith "impossible" in
830-
(* e.g. |arg| <= 40 *)
831-
(* arg <= e (arg <= 40) *)
832-
let le = BinOp (op, absargexp, valexp, intType) in
833-
(* arg >= -e (arg >= -40) *)
834-
let gt = BinOp(flip op, absargexp, UnOp (Neg, valexp, Cilfacade.typeOf valexp), intType) in
835-
let one = invariant ctx (Analyses.ask_of_ctx ctx) ctx.global refine0 le tv in
836-
invariant ctx (Analyses.ask_of_ctx ctx) ctx.global one gt tv
837-
in
838-
match exp with
839-
| BinOp ((Lt|Le) as op, CastE(t, Lval (Var v, NoOffset)), e,_) when tv ->
840-
begin match ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil NoOffset)) with
841-
| `Lifted (Abs (ik, arg)) -> refineAbs op (CastE (t, arg)) e
842-
| _ -> refine0
843-
end
844-
| BinOp ((Lt|Le) as op, Lval (Var v, NoOffset), e, _) when tv ->
845-
begin match ctx.ask (Queries.TmpSpecial (v, Offset.Exp.of_cil NoOffset)) with
846-
| `Lifted (Abs (ik, arg)) -> refineAbs op arg e
847-
| _ -> refine0
848-
end
849-
| _ -> refine0
850-
851824
end

tests/regression/39-signed-overflows/06-abs.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ int main() {
1717
__goblint_check(-100 <= data);
1818
int result = data * data; //NOWARN
1919
}
20+
21+
if(abs(data) - 1 <= 99)
22+
{
23+
__goblint_check(data <= 100);
24+
__goblint_check(-100 <= data);
25+
int result = data * data; //NOWARN
26+
}
2027
}
2128
return 8;
2229
}

0 commit comments

Comments
 (0)