let get_multsubadd_unsigned_assertion
~simplify_constants:simplify_constants
~warning:warning
full_expr op expr1 expr2 =
let t = Cil.typeOf full_expr in
let size = bitsSizeOf t
in if (size > 32) then (
rte_warn fmt_warn_bitsize_over_32 d_exp full_expr ;
[]
)
else
let (minType,maxType) = My_bigint.zero, max_unsigned_number size in
let full_add_term () =
let term1 = translate_C_expr_to_term ~cast:false expr1
and term2 = translate_C_expr_to_term ~cast:false expr2
in Logic_const.term (TBinOp (op, term1,term2)) (Ctype t)
in let assertion () =
if op = MinusA then
assertion_ge (full_add_term ()) minType
else
assertion_le (full_add_term ()) maxType
in
if simplify_constants then begin
match get_expr_val expr1, get_expr_val expr2 with
| Some big_a64, Some big_b64 ->
if op = MinusA then
let big_diff = Int.sub big_a64 big_b64
in
if Int.lt big_diff minType then
let assertion = assertion () in
if warning then
rte_warn
fmt_unsigned_overflow_assert
d_predicate_named assertion;
[ assertion, Some Property_status.False_if_reachable ]
else [ ]
else if op = PlusA then
let big_add = Int.add big_a64 big_b64 in
if Int.gt big_add maxType then
let assertion = assertion () in
if warning then
rte_warn
fmt_unsigned_overflow_assert
d_predicate_named assertion;
[ assertion, Some Property_status.False_if_reachable ]
else [ ]
else (
assert(op = Mult) ;
let big_mult = Int.mul big_a64 big_b64 in
let () = assert(Int.compare big_mult Int.zero >= 0) in
let b_ov = Int.gt big_mult maxType in
if b_ov then
let assertion = assertion () in
if warning then
rte_warn
fmt_unsigned_overflow_assert
d_predicate_named assertion ;
[ assertion, Some Property_status.False_if_reachable ]
else [ ])
| Some a64, None
| None, Some a64 ->
if op = Mult then begin
if My_bigint.equal a64 My_bigint.zero
|| My_bigint.equal a64 My_bigint.one
then []
else [ assertion (), None ]
end else [ assertion (), None ]
| None, None ->
[ assertion (), None ]
end else
[ assertion (), None ]