Skip to content

Commit 149f7e4

Browse files
committed
Add implementation of (unsigned) division operator bvudiv.
Along with tests of its conversion and the function application factory integrity.
1 parent 5538759 commit 149f7e4

File tree

5 files changed

+84
-2
lines changed

5 files changed

+84
-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
@@ -361,8 +361,20 @@ static smt_termt convert_expr_to_smt(const minus_exprt &minus)
361361

362362
static smt_termt convert_expr_to_smt(const div_exprt &divide)
363363
{
364-
UNIMPLEMENTED_FEATURE(
365-
"Generation of SMT formula for divide expression: " + divide.pretty());
364+
const bool both_operands_bitvector =
365+
can_cast_type<integer_bitvector_typet>(divide.lhs().type()) &&
366+
can_cast_type<integer_bitvector_typet>(divide.rhs().type());
367+
368+
if(both_operands_bitvector)
369+
{
370+
return smt_bit_vector_theoryt::unsigned_divide(
371+
convert_expr_to_smt(divide.lhs()), convert_expr_to_smt(divide.rhs()));
372+
}
373+
else
374+
{
375+
UNIMPLEMENTED_FEATURE(
376+
"Generation of SMT formula for divide expression: " + divide.pretty());
377+
}
366378
}
367379

368380
static smt_termt convert_expr_to_smt(const ieee_float_op_exprt &float_operation)

src/solvers/smt2_incremental/smt_bit_vector_theory.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,3 +273,26 @@ void smt_bit_vector_theoryt::multiplyt::validate(
273273
const smt_function_application_termt::factoryt<
274274
smt_bit_vector_theoryt::multiplyt>
275275
smt_bit_vector_theoryt::multiply{};
276+
277+
const char *smt_bit_vector_theoryt::unsigned_dividet::identifier()
278+
{
279+
return "bvudiv";
280+
}
281+
282+
smt_sortt smt_bit_vector_theoryt::unsigned_dividet::return_sort(
283+
const smt_termt &lhs,
284+
const smt_termt &rhs)
285+
{
286+
return lhs.get_sort();
287+
}
288+
289+
void smt_bit_vector_theoryt::unsigned_dividet::validate(
290+
const smt_termt &lhs,
291+
const smt_termt &rhs)
292+
{
293+
validate_bit_vector_predicate_arguments(lhs, rhs);
294+
}
295+
296+
const smt_function_application_termt::factoryt<
297+
smt_bit_vector_theoryt::unsigned_dividet>
298+
smt_bit_vector_theoryt::unsigned_divide{};

src/solvers/smt2_incremental/smt_bit_vector_theory.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,15 @@ class smt_bit_vector_theoryt
108108
static void validate(const smt_termt &lhs, const smt_termt &rhs);
109109
};
110110
static const smt_function_application_termt::factoryt<multiplyt> multiply;
111+
112+
struct unsigned_dividet final
113+
{
114+
static const char *identifier();
115+
static smt_sortt return_sort(const smt_termt &lhs, const smt_termt &rhs);
116+
static void validate(const smt_termt &lhs, const smt_termt &rhs);
117+
};
118+
static const smt_function_application_termt::factoryt<unsigned_dividet>
119+
unsigned_divide;
111120
};
112121

113122
#endif // CPROVER_SOLVERS_SMT2_INCREMENTAL_SMT_BIT_VECTOR_THEORY_H

unit/solvers/smt2_incremental/convert_expr_to_smt.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,4 +345,23 @@ TEST_CASE(
345345
const cbmc_invariants_should_throwt invariants_throw;
346346
REQUIRE_THROWS(convert_expr_to_smt(mult_exprt{one_bvint, false_exprt{}}));
347347
}
348+
349+
// Division is defined over unsigned numbers only (theory notes say it
350+
// truncates over zero)
351+
SECTION("Division of two constant size bit-vectors")
352+
{
353+
const auto constructed_term =
354+
convert_expr_to_smt(div_exprt{one_bvint_unsigned, two_bvint_unsigned});
355+
const auto expected_term =
356+
smt_bit_vector_theoryt::unsigned_divide(smt_term_one, smt_term_two);
357+
CHECK(constructed_term == expected_term);
358+
}
359+
360+
SECTION(
361+
"Ensure that division node conversion fails if the operands are not "
362+
"bit-vector based")
363+
{
364+
const cbmc_invariants_should_throwt invariants_throw;
365+
REQUIRE_THROWS(convert_expr_to_smt(div_exprt{one_bvint, false_exprt{}}));
366+
}
348367
}

unit/solvers/smt2_incremental/smt_bit_vector_theory.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,4 +233,23 @@ TEST_CASE(
233233
// invariant violation.
234234
REQUIRE_THROWS(smt_bit_vector_theoryt::multiply(true_val, three));
235235
}
236+
237+
SECTION("Unsigned Division")
238+
{
239+
const auto function_application =
240+
smt_bit_vector_theoryt::unsigned_divide(two, three);
241+
REQUIRE(
242+
function_application.function_identifier() ==
243+
smt_identifier_termt("bvudiv", smt_bit_vector_sortt{8}));
244+
REQUIRE(function_application.get_sort() == smt_bit_vector_sortt{8});
245+
REQUIRE(function_application.arguments().size() == 2);
246+
REQUIRE(function_application.arguments()[0].get() == two);
247+
REQUIRE(function_application.arguments()[1].get() == three);
248+
249+
cbmc_invariants_should_throwt invariants_throw;
250+
// Bit-vectors of mismatched sorts are going to hit an invariant violation.
251+
REQUIRE_THROWS(smt_bit_vector_theoryt::unsigned_divide(three, four));
252+
// A division of a bool and a bitvector should hit an invariant violation.
253+
REQUIRE_THROWS(smt_bit_vector_theoryt::unsigned_divide(true_val, three));
254+
}
236255
}

0 commit comments

Comments
 (0)