Skip to content

Commit a1c923c

Browse files
committed
Add implementation of signed remainder operator (bvsrem).
Along with this, change the tests and implementation of the conversion function to account for signed/unsigned inputs.
1 parent f259dc0 commit a1c923c

File tree

5 files changed

+76
-4
lines changed

5 files changed

+76
-4
lines changed

src/solvers/smt2_incremental/convert_expr_to_smt.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -404,11 +404,24 @@ static smt_termt convert_expr_to_smt(const mod_exprt &truncation_modulo)
404404
can_cast_type<integer_bitvector_typet>(truncation_modulo.lhs().type()) &&
405405
can_cast_type<integer_bitvector_typet>(truncation_modulo.rhs().type());
406406

407+
const bool both_operands_unsigned =
408+
can_cast_type<unsignedbv_typet>(truncation_modulo.lhs().type()) &&
409+
can_cast_type<unsignedbv_typet>(truncation_modulo.rhs().type());
410+
407411
if(both_operands_bitvector)
408412
{
409-
return smt_bit_vector_theoryt::unsigned_remainder(
410-
convert_expr_to_smt(truncation_modulo.lhs()),
411-
convert_expr_to_smt(truncation_modulo.rhs()));
413+
if(both_operands_unsigned)
414+
{
415+
return smt_bit_vector_theoryt::unsigned_remainder(
416+
convert_expr_to_smt(truncation_modulo.lhs()),
417+
convert_expr_to_smt(truncation_modulo.rhs()));
418+
}
419+
else
420+
{
421+
return smt_bit_vector_theoryt::signed_remainder(
422+
convert_expr_to_smt(truncation_modulo.lhs()),
423+
convert_expr_to_smt(truncation_modulo.rhs()));
424+
}
412425
}
413426
else
414427
{

src/solvers/smt2_incremental/smt_bit_vector_theory.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,3 +342,26 @@ void smt_bit_vector_theoryt::unsigned_remaindert::validate(
342342
const smt_function_application_termt::factoryt<
343343
smt_bit_vector_theoryt::unsigned_remaindert>
344344
smt_bit_vector_theoryt::unsigned_remainder{};
345+
346+
const char *smt_bit_vector_theoryt::signed_remaindert::identifier()
347+
{
348+
return "bvsrem";
349+
}
350+
351+
smt_sortt smt_bit_vector_theoryt::signed_remaindert::return_sort(
352+
const smt_termt &lhs,
353+
const smt_termt &rhs)
354+
{
355+
return lhs.get_sort();
356+
}
357+
358+
void smt_bit_vector_theoryt::signed_remaindert::validate(
359+
const smt_termt &lhs,
360+
const smt_termt &rhs)
361+
{
362+
validate_bit_vector_predicate_arguments(lhs, rhs);
363+
}
364+
365+
const smt_function_application_termt::factoryt<
366+
smt_bit_vector_theoryt::signed_remaindert>
367+
smt_bit_vector_theoryt::signed_remainder{};

src/solvers/smt2_incremental/smt_bit_vector_theory.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,15 @@ class smt_bit_vector_theoryt
135135
};
136136
static const smt_function_application_termt::factoryt<unsigned_remaindert>
137137
unsigned_remainder;
138+
139+
struct signed_remaindert final
140+
{
141+
static const char *identifier();
142+
static smt_sortt return_sort(const smt_termt &lhs, const smt_termt &rhs);
143+
static void validate(const smt_termt &lhs, const smt_termt &rhs);
144+
};
145+
static const smt_function_application_termt::factoryt<signed_remaindert>
146+
signed_remainder;
138147
};
139148

140149
#endif // CPROVER_SOLVERS_SMT2_INCREMENTAL_SMT_BIT_VECTOR_THEORY_H

unit/solvers/smt2_incremental/convert_expr_to_smt.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,14 +374,22 @@ TEST_CASE(
374374
}
375375

376376
SECTION(
377-
"Unsigned remainder (modulus) from truncating division of two constant "
377+
"Remainder (modulus) from truncating division of two constant "
378378
"size bit-vectors")
379379
{
380+
// Remainder expression with unsigned operands.
380381
const auto constructed_term =
381382
convert_expr_to_smt(mod_exprt{one_bvint_unsigned, two_bvint_unsigned});
382383
const auto expected_term =
383384
smt_bit_vector_theoryt::unsigned_remainder(smt_term_one, smt_term_two);
384385
CHECK(constructed_term == expected_term);
386+
387+
// Remainder expression with signed operands
388+
const auto constructed_term_signed =
389+
convert_expr_to_smt(mod_exprt{one_bvint, two_bvint});
390+
const auto expected_term_signed =
391+
smt_bit_vector_theoryt::signed_remainder(smt_term_one, smt_term_two);
392+
CHECK(constructed_term_signed == expected_term_signed);
385393
}
386394

387395
SECTION(

unit/solvers/smt2_incremental/smt_bit_vector_theory.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,4 +290,23 @@ TEST_CASE(
290290
// A remainder of a bool and a bitvector should hit an invariant violation.
291291
REQUIRE_THROWS(smt_bit_vector_theoryt::unsigned_remainder(true_val, three));
292292
}
293+
294+
SECTION("Signed Remainder")
295+
{
296+
const auto function_application =
297+
smt_bit_vector_theoryt::signed_remainder(two, three);
298+
REQUIRE(
299+
function_application.function_identifier() ==
300+
smt_identifier_termt("bvsrem", smt_bit_vector_sortt{8}));
301+
REQUIRE(function_application.get_sort() == smt_bit_vector_sortt{8});
302+
REQUIRE(function_application.arguments().size() == 2);
303+
REQUIRE(function_application.arguments()[0].get() == two);
304+
REQUIRE(function_application.arguments()[1].get() == three);
305+
306+
cbmc_invariants_should_throwt invariants_throw;
307+
// Bit-vectors of mismatched sorts are going to hit an invariant violation.
308+
REQUIRE_THROWS(smt_bit_vector_theoryt::signed_remainder(three, four));
309+
// A remainder of a bool and a bitvector should hit an invariant violation.
310+
REQUIRE_THROWS(smt_bit_vector_theoryt::signed_remainder(true_val, three));
311+
}
293312
}

0 commit comments

Comments
 (0)