Skip to content

Commit 2ecd762

Browse files
Merge pull request #1623 from ManuelLerchner/master
Bitfield Domain
2 parents 39dc63e + 98a779e commit 2ecd762

33 files changed

+2249
-92
lines changed

scripts/goblint-lib-modules.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
"DefExcDomain", # included in IntDomain
5454
"EnumsDomain", # included in IntDomain
5555
"CongruenceDomain", # included in IntDomain
56+
"BitfieldDomain", #included in IntDomain
5657
"IntDomTuple", # included in IntDomain
5758
"WitnessGhostVar", # included in WitnessGhost
5859

src/analyses/base.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,8 @@ struct
624624

625625
let drop_intervalSet = CPA.map (function Int x -> Int (ID.no_intervalSet x) | x -> x )
626626

627+
let drop_bitfield = CPA.map (function Int x -> Int (ID.no_bitfield x) | x -> x )
628+
627629
let context man (fd: fundec) (st: store): store =
628630
let f keep drop_fn (st: store) = if keep then st else { st with cpa = drop_fn st.cpa} in
629631
st |>
@@ -634,6 +636,7 @@ struct
634636
%> f (ContextUtil.should_keep ~isAttr:GobContext ~keepOption:"ana.base.context.int" ~removeAttr:"base.no-int" ~keepAttr:"base.int" fd) drop_ints
635637
%> f (ContextUtil.should_keep ~isAttr:GobContext ~keepOption:"ana.base.context.interval" ~removeAttr:"base.no-interval" ~keepAttr:"base.interval" fd) drop_interval
636638
%> f (ContextUtil.should_keep ~isAttr:GobContext ~keepOption:"ana.base.context.interval_set" ~removeAttr:"base.no-interval_set" ~keepAttr:"base.interval_set" fd) drop_intervalSet
639+
%> f (ContextUtil.should_keep ~isAttr:GobContext ~keepOption:"ana.base.context.bitfield" ~removeAttr:"base.no-bitfield" ~keepAttr:"base.bitfield" fd) drop_bitfield
637640

638641

639642
let reachable_top_pointers_types man (ps: AD.t) : Queries.TS.t =

src/analyses/baseInvariant.ml

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -395,27 +395,46 @@ struct
395395
| Le, Some false -> meet_bin (ID.starting ikind (Z.succ l2)) (ID.ending ikind (Z.pred u1))
396396
| _, _ -> a, b)
397397
| _ -> a, b)
398-
| BOr | BXor as op->
399-
if M.tracing then M.tracel "inv" "Unhandled operator %a" d_binop op;
398+
| BOr ->
399+
(* Be careful: inv_exp performs a meet on both arguments of the BOr / BXor. *)
400+
if PrecisionUtil.get_bitfield () then
401+
(* refinement based on the following idea: bit set to one in c and set to zero in b must be one in a and bit set to zero in c must be zero in a too (analogously for b) *)
402+
let ((az, ao), (bz, bo)) = BitfieldDomain.Bitfield.refine_bor (ID.to_bitfield ikind a) (ID.to_bitfield ikind b) (ID.to_bitfield ikind c) in
403+
ID.meet a (ID.of_bitfield ikind (az, ao)), ID.meet b (ID.of_bitfield ikind (bz, bo))
404+
else
405+
(if M.tracing then M.tracel "inv" "Unhandled operator %a" d_binop op;
406+
(* Be careful: inv_exp performs a meet on both arguments of the BOr / BXor. *)
407+
(a, b)
408+
)
409+
| BXor ->
400410
(* Be careful: inv_exp performs a meet on both arguments of the BOr / BXor. *)
401-
a, b
411+
meet_com ID.logxor
402412
| LAnd ->
403413
if ID.to_bool c = Some true then
404414
meet_bin c c
405415
else
406416
a, b
407-
| BAnd as op ->
417+
| BAnd ->
408418
(* we only attempt to refine a here *)
419+
let b_int = ID.to_int b in
409420
let a =
410-
match ID.to_int b with
421+
match b_int with
411422
| Some x when Z.equal x Z.one ->
412423
(match ID.to_bool c with
413424
| Some true -> ID.meet a (ID.of_congruence ikind (Z.one, Z.of_int 2))
414425
| Some false -> ID.meet a (ID.of_congruence ikind (Z.zero, Z.of_int 2))
415-
| None -> if M.tracing then M.tracel "inv" "Unhandled case for operator x %a 1 = %a" d_binop op ID.pretty c; a)
416-
| _ -> if M.tracing then M.tracel "inv" "Unhandled case for operator x %a %a = %a" d_binop op ID.pretty b ID.pretty c; a
426+
| None -> a)
427+
| _ -> a
417428
in
418-
a, b
429+
if PrecisionUtil.get_bitfield () then
430+
(* refinement based on the following idea: bit set to zero in c and set to one in b must be zero in a and bit set to one in c must be one in a too (analogously for b) *)
431+
let ((az, ao), (bz, bo)) = BitfieldDomain.Bitfield.refine_band (ID.to_bitfield ikind a) (ID.to_bitfield ikind b) (ID.to_bitfield ikind c) in
432+
ID.meet a (ID.of_bitfield ikind (az, ao)), ID.meet b (ID.of_bitfield ikind (bz, bo))
433+
else if b_int = None then
434+
(if M.tracing then M.tracel "inv" "Unhandled operator %a" d_binop op;
435+
(a, b)
436+
)
437+
else a, b
419438
| op ->
420439
if M.tracing then M.tracel "inv" "Unhandled operator %a" d_binop op;
421440
a, b

0 commit comments

Comments
 (0)