Skip to content

Commit a2a55ac

Browse files
committed
SMT-LIB2 parser now models bit-vector division by zero correctly
SMT-LIB2 defines the result of bvsdiv and bvudiv to be 1...1.
1 parent 9a04436 commit a2a55ac

File tree

3 files changed

+44
-15
lines changed

3 files changed

+44
-15
lines changed

regression/smt2_solver/basic-bv1/basic-bv1.smt2

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,21 @@
88
(define-fun b03 () Bool (= (bvneg #x07) #xf9)) ; unary minus
99
(define-fun b04 () Bool (= (bvmul #x07 #x03) #x15)) ; multiplication
1010
(define-fun b05 () Bool (= (bvurem #x07 #x03) #x01)) ; unsigned remainder
11-
(define-fun b06 () Bool (= (bvsrem #x07 #x03) #x01)) ; signed remainder
12-
(define-fun b07 () Bool (= (bvsmod #x07 #x03) #x01)) ; signed modulo
13-
(define-fun b08 () Bool (= (bvshl #x07 #x03) #x38)) ; shift left
14-
(define-fun b09 () Bool (= (bvlshr #xf0 #x03) #x1e)) ; unsigned (logical) shift right
15-
(define-fun b10 () Bool (= (bvashr #xf0 #x03) #xfe)) ; signed (arithmetical) shift right#x0a
11+
(define-fun b06 () Bool (= (bvudiv #x01 #x00) #xff)) ; unsigned division
12+
(define-fun b07 () Bool (= (bvsrem #x07 #x03) #x01)) ; signed remainder
13+
(define-fun b08 () Bool (= (bvsmod #x07 #x03) #x01)) ; signed modulo
14+
(define-fun b09 () Bool (= (bvsdiv #x01 #x00) #xff)) ; signed division
15+
(define-fun b10 () Bool (= (bvshl #x07 #x03) #x38)) ; shift left
16+
(define-fun b11 () Bool (= (bvlshr #xf0 #x03) #x1e)) ; unsigned (logical) shift right
17+
(define-fun b12 () Bool (= (bvashr #xf0 #x03) #xfe)) ; signed (arithmetical) shift right#x0a
1618

1719
; Multi-ary variants, where applicable
18-
(define-fun b11 () Bool (= (bvadd #x07 #x03 #x01) #x0b)) ; addition
19-
(define-fun b12 () Bool (= (bvmul #x07 #x03 #x01) #x15)) ; multiplication
20+
(define-fun b13 () Bool (= (bvadd #x07 #x03 #x01) #x0b)) ; addition
21+
(define-fun b14 () Bool (= (bvmul #x07 #x03 #x01) #x15)) ; multiplication
2022

2123
; rotation
22-
(define-fun b13 () Bool (= ((_ rotate_left 2) #xf7) #xdf)) ; rotation left
23-
(define-fun b14 () Bool (= ((_ rotate_right 2) #x07) #xc1)) ; rotation right
24+
(define-fun b15 () Bool (= ((_ rotate_left 2) #xf7) #xdf)) ; rotation left
25+
(define-fun b16 () Bool (= ((_ rotate_right 2) #x07) #xc1)) ; rotation right
2426

2527
; Bitwise Operations
2628

@@ -67,7 +69,7 @@
6769
; all must be true
6870

6971
(assert (not (and
70-
b01 b02 b03 b04 b05 b06 b07 b08 b09 b10 b11 b12 b13 b14
72+
b01 b02 b03 b04 b05 b06 b07 b08 b09 b10 b11 b12 b13 b14 b15 b16
7173
d01
7274
power-test
7375
p1 p2 p3 p4 p5 p6 p7 p8)))

src/solvers/smt2/smt2_parser.cpp

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,35 @@ exprt smt2_parsert::function_application()
872872
UNREACHABLE;
873873
}
874874

875+
exprt smt2_parsert::bv_division(
876+
const exprt::operandst &operands,
877+
bool is_signed)
878+
{
879+
if(operands.size() != 2)
880+
throw error() << "bitvector division expects two operands";
881+
882+
// SMT-LIB2 defines the result of division by 0 to be 1....1
883+
auto divisor = symbol_exprt("divisor", operands[1].type());
884+
auto divisor_is_zero = equal_exprt(divisor, from_integer(0, divisor.type()));
885+
auto all_ones = to_unsignedbv_type(operands[0].type()).largest_expr();
886+
887+
exprt division_result;
888+
889+
if(is_signed)
890+
{
891+
auto signed_operands = cast_bv_to_signed({operands[0], divisor});
892+
division_result =
893+
cast_bv_to_unsigned(div_exprt(signed_operands[0], signed_operands[1]));
894+
}
895+
else
896+
division_result = div_exprt(operands[0], divisor);
897+
898+
return let_exprt(
899+
{divisor},
900+
{operands[1]},
901+
if_exprt(divisor_is_zero, all_ones, division_result));
902+
}
903+
875904
exprt smt2_parsert::expression()
876905
{
877906
switch(next_token())
@@ -1045,11 +1074,8 @@ void smt2_parsert::setup_expressions()
10451074
return binary(ID_minus, op);
10461075
};
10471076

1048-
expressions["bvsdiv"] = [this] {
1049-
return cast_bv_to_unsigned(binary(ID_div, cast_bv_to_signed(operands())));
1050-
};
1051-
1052-
expressions["bvudiv"] = [this] { return binary(ID_div, operands()); };
1077+
expressions["bvsdiv"] = [this] { return bv_division(operands(), true); };
1078+
expressions["bvudiv"] = [this] { return bv_division(operands(), false); };
10531079
expressions["/"] = [this] { return binary(ID_div, operands()); };
10541080
expressions["div"] = [this] { return binary(ID_div, operands()); };
10551081

src/solvers/smt2/smt2_parser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ class smt2_parsert
162162
exprt binary_predicate(irep_idt, const exprt::operandst &);
163163
exprt binary(irep_idt, const exprt::operandst &);
164164
exprt unary(irep_idt, const exprt::operandst &);
165+
exprt bv_division(const exprt::operandst &, bool is_signed);
165166

166167
exprt let_expression();
167168
exprt quantifier_expression(irep_idt);

0 commit comments

Comments
 (0)