Skip to content

Commit 0c4a39b

Browse files
committed
Add implementation of (signed) division operator (bvsdiv).
In addition, modify the tests and the implementation of the conversion function to account for signed/unsigned input.
1 parent 149f7e4 commit 0c4a39b

File tree

5 files changed

+73
-2
lines changed

5 files changed

+73
-2
lines changed

src/solvers/smt2_incremental/convert_expr_to_smt.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -365,10 +365,22 @@ static smt_termt convert_expr_to_smt(const div_exprt &divide)
365365
can_cast_type<integer_bitvector_typet>(divide.lhs().type()) &&
366366
can_cast_type<integer_bitvector_typet>(divide.rhs().type());
367367

368+
const bool both_operands_unsigned =
369+
can_cast_type<unsignedbv_typet>(divide.lhs().type()) &&
370+
can_cast_type<unsignedbv_typet>(divide.rhs().type());
371+
368372
if(both_operands_bitvector)
369373
{
370-
return smt_bit_vector_theoryt::unsigned_divide(
371-
convert_expr_to_smt(divide.lhs()), convert_expr_to_smt(divide.rhs()));
374+
if(both_operands_unsigned)
375+
{
376+
return smt_bit_vector_theoryt::unsigned_divide(
377+
convert_expr_to_smt(divide.lhs()), convert_expr_to_smt(divide.rhs()));
378+
}
379+
else
380+
{
381+
return smt_bit_vector_theoryt::signed_divide(
382+
convert_expr_to_smt(divide.lhs()), convert_expr_to_smt(divide.rhs()));
383+
}
372384
}
373385
else
374386
{

src/solvers/smt2_incremental/smt_bit_vector_theory.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,3 +296,26 @@ void smt_bit_vector_theoryt::unsigned_dividet::validate(
296296
const smt_function_application_termt::factoryt<
297297
smt_bit_vector_theoryt::unsigned_dividet>
298298
smt_bit_vector_theoryt::unsigned_divide{};
299+
300+
const char *smt_bit_vector_theoryt::signed_dividet::identifier()
301+
{
302+
return "bvsdiv";
303+
}
304+
305+
smt_sortt smt_bit_vector_theoryt::signed_dividet::return_sort(
306+
const smt_termt &lhs,
307+
const smt_termt &rhs)
308+
{
309+
return lhs.get_sort();
310+
}
311+
312+
void smt_bit_vector_theoryt::signed_dividet::validate(
313+
const smt_termt &lhs,
314+
const smt_termt &rhs)
315+
{
316+
validate_bit_vector_predicate_arguments(lhs, rhs);
317+
}
318+
319+
const smt_function_application_termt::factoryt<
320+
smt_bit_vector_theoryt::signed_dividet>
321+
smt_bit_vector_theoryt::signed_divide{};

src/solvers/smt2_incremental/smt_bit_vector_theory.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,15 @@ class smt_bit_vector_theoryt
117117
};
118118
static const smt_function_application_termt::factoryt<unsigned_dividet>
119119
unsigned_divide;
120+
121+
struct signed_dividet final
122+
{
123+
static const char *identifier();
124+
static smt_sortt return_sort(const smt_termt &lhs, const smt_termt &rhs);
125+
static void validate(const smt_termt &lhs, const smt_termt &rhs);
126+
};
127+
static const smt_function_application_termt::factoryt<signed_dividet>
128+
signed_divide;
120129
};
121130

122131
#endif // CPROVER_SOLVERS_SMT2_INCREMENTAL_SMT_BIT_VECTOR_THEORY_H

unit/solvers/smt2_incremental/convert_expr_to_smt.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,11 +350,19 @@ TEST_CASE(
350350
// truncates over zero)
351351
SECTION("Division of two constant size bit-vectors")
352352
{
353+
// Check of division expression with unsigned operands
353354
const auto constructed_term =
354355
convert_expr_to_smt(div_exprt{one_bvint_unsigned, two_bvint_unsigned});
355356
const auto expected_term =
356357
smt_bit_vector_theoryt::unsigned_divide(smt_term_one, smt_term_two);
357358
CHECK(constructed_term == expected_term);
359+
360+
// Check of division expression with signed operands
361+
const auto constructed_term_signed =
362+
convert_expr_to_smt(div_exprt{one_bvint, two_bvint});
363+
const auto expected_term_signed =
364+
smt_bit_vector_theoryt::signed_divide(smt_term_one, smt_term_two);
365+
CHECK(constructed_term_signed == expected_term_signed);
358366
}
359367

360368
SECTION(

unit/solvers/smt2_incremental/smt_bit_vector_theory.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,4 +252,23 @@ TEST_CASE(
252252
// A division of a bool and a bitvector should hit an invariant violation.
253253
REQUIRE_THROWS(smt_bit_vector_theoryt::unsigned_divide(true_val, three));
254254
}
255+
256+
SECTION("Signed Division")
257+
{
258+
const auto function_application =
259+
smt_bit_vector_theoryt::signed_divide(two, three);
260+
REQUIRE(
261+
function_application.function_identifier() ==
262+
smt_identifier_termt("bvsdiv", smt_bit_vector_sortt{8}));
263+
REQUIRE(function_application.get_sort() == smt_bit_vector_sortt{8});
264+
REQUIRE(function_application.arguments().size() == 2);
265+
REQUIRE(function_application.arguments()[0].get() == two);
266+
REQUIRE(function_application.arguments()[1].get() == three);
267+
268+
cbmc_invariants_should_throwt invariants_throw;
269+
// Bit-vectors of mismatched sorts are going to hit an invariant violation.
270+
REQUIRE_THROWS(smt_bit_vector_theoryt::signed_divide(three, four));
271+
// A division of a bool and a bitvector should hit an invariant violation.
272+
REQUIRE_THROWS(smt_bit_vector_theoryt::signed_divide(true_val, three));
273+
}
255274
}

0 commit comments

Comments
 (0)