Skip to content

Commit 8097fb4

Browse files
committed
Add (unsigned) remainder (modulus) arithmetic operator bvurem.
Along with tests of its conversion and the function application factory integrity.
1 parent edf32b7 commit 8097fb4

File tree

5 files changed

+88
-3
lines changed

5 files changed

+88
-3
lines changed

src/solvers/smt2_incremental/convert_expr_to_smt.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -401,9 +401,24 @@ static smt_termt convert_expr_to_smt(const ieee_float_op_exprt &float_operation)
401401

402402
static smt_termt convert_expr_to_smt(const mod_exprt &truncation_modulo)
403403
{
404-
UNIMPLEMENTED_FEATURE(
405-
"Generation of SMT formula for truncation modulo expression: " +
406-
truncation_modulo.pretty());
404+
bool both_operands_bitvector =
405+
can_cast_type<integer_bitvector_typet>(truncation_modulo.lhs().type()) &&
406+
can_cast_type<integer_bitvector_typet>(truncation_modulo.rhs().type());
407+
408+
if(both_operands_bitvector)
409+
{
410+
return smt_bit_vector_theoryt::unsigned_remainder(
411+
convert_expr_to_smt(truncation_modulo.lhs()),
412+
convert_expr_to_smt(truncation_modulo.rhs()));
413+
}
414+
else
415+
{
416+
{
417+
UNIMPLEMENTED_FEATURE(
418+
"Generation of SMT formula for remainder (modulus) expression: " +
419+
truncation_modulo.pretty());
420+
}
421+
}
407422
}
408423

409424
static smt_termt

src/solvers/smt2_incremental/smt_bit_vector_theory.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,3 +156,26 @@ void smt_bit_vector_theoryt::signed_dividet::validate(
156156
const smt_function_application_termt::factoryt<
157157
smt_bit_vector_theoryt::signed_dividet>
158158
smt_bit_vector_theoryt::signed_divide{};
159+
160+
const char *smt_bit_vector_theoryt::unsigned_remaindert::identifier()
161+
{
162+
return "bvurem";
163+
}
164+
165+
smt_sortt smt_bit_vector_theoryt::unsigned_remaindert::return_sort(
166+
const smt_termt &lhs,
167+
const smt_termt &rhs)
168+
{
169+
return lhs.get_sort();
170+
}
171+
172+
void smt_bit_vector_theoryt::unsigned_remaindert::validate(
173+
const smt_termt &lhs,
174+
const smt_termt &rhs)
175+
{
176+
validate_bit_vector_predicate_arguments(lhs, rhs);
177+
}
178+
179+
const smt_function_application_termt::factoryt<
180+
smt_bit_vector_theoryt::unsigned_remaindert>
181+
smt_bit_vector_theoryt::unsigned_remainder{};

src/solvers/smt2_incremental/smt_bit_vector_theory.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,15 @@ class smt_bit_vector_theoryt
6262
};
6363
static const smt_function_application_termt::factoryt<signed_dividet>
6464
signed_divide;
65+
66+
struct unsigned_remaindert final
67+
{
68+
static const char *identifier();
69+
static smt_sortt return_sort(const smt_termt &lhs, const smt_termt &rhs);
70+
static void validate(const smt_termt &lhs, const smt_termt &rhs);
71+
};
72+
static const smt_function_application_termt::factoryt<unsigned_remaindert>
73+
unsigned_remainder;
6574
};
6675

6776
#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
@@ -372,4 +372,23 @@ TEST_CASE(
372372
const cbmc_invariants_should_throwt invariants_throw;
373373
REQUIRE_THROWS(convert_expr_to_smt(div_exprt{one_bvint, false_exprt{}}));
374374
}
375+
376+
SECTION(
377+
"Unsigned remainder (modulus) from truncating division of two constant "
378+
"size bit-vectors")
379+
{
380+
const auto constructed_term =
381+
convert_expr_to_smt(mod_exprt{one_bvint_unsigned, two_bvint_unsigned});
382+
const auto expected_term =
383+
smt_bit_vector_theoryt::unsigned_remainder(smt_term_one, smt_term_two);
384+
CHECK(constructed_term == expected_term);
385+
}
386+
387+
SECTION(
388+
"Ensure that remainder (truncated modulo) node conversion fails if the "
389+
"operands are not bit-vector based")
390+
{
391+
const cbmc_invariants_should_throwt invariants_throw;
392+
REQUIRE_THROWS(convert_expr_to_smt(mod_exprt{one_bvint, false_exprt{}}));
393+
}
375394
}

unit/solvers/smt2_incremental/smt_bit_vector_theory.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,4 +269,23 @@ TEST_CASE(
269269
// A division of a bool and a bitvector should hit an invariant violation.
270270
REQUIRE_THROWS(smt_bit_vector_theoryt::signed_divide(true_val, three));
271271
}
272+
273+
SECTION("Unsigned Remainder")
274+
{
275+
const auto function_application =
276+
smt_bit_vector_theoryt::unsigned_remainder(two, three);
277+
REQUIRE(
278+
function_application.function_identifier() ==
279+
smt_identifier_termt("bvurem", smt_bit_vector_sortt{8}));
280+
REQUIRE(function_application.get_sort() == smt_bit_vector_sortt{8});
281+
REQUIRE(function_application.arguments().size() == 2);
282+
REQUIRE(function_application.arguments()[0].get() == two);
283+
REQUIRE(function_application.arguments()[1].get() == three);
284+
285+
cbmc_invariants_should_throwt invariants_throw;
286+
// Bit-vectors of mismatched sorts are going to hit an invariant violation.
287+
REQUIRE_THROWS(smt_bit_vector_theoryt::unsigned_remainder(three, four));
288+
// A remainder of a bool and a bitvector should hit an invariant violation.
289+
REQUIRE_THROWS(smt_bit_vector_theoryt::unsigned_remainder(true_val, three));
290+
}
272291
}

0 commit comments

Comments
 (0)