Skip to content

Commit 115b437

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

File tree

5 files changed

+86
-3
lines changed

5 files changed

+86
-3
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
@@ -401,9 +401,22 @@ 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+
const 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+
UNIMPLEMENTED_FEATURE(
417+
"Generation of SMT formula for remainder (modulus) expression: " +
418+
truncation_modulo.pretty());
419+
}
407420
}
408421

409422
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
@@ -319,3 +319,26 @@ void smt_bit_vector_theoryt::signed_dividet::validate(
319319
const smt_function_application_termt::factoryt<
320320
smt_bit_vector_theoryt::signed_dividet>
321321
smt_bit_vector_theoryt::signed_divide{};
322+
323+
const char *smt_bit_vector_theoryt::unsigned_remaindert::identifier()
324+
{
325+
return "bvurem";
326+
}
327+
328+
smt_sortt smt_bit_vector_theoryt::unsigned_remaindert::return_sort(
329+
const smt_termt &lhs,
330+
const smt_termt &rhs)
331+
{
332+
return lhs.get_sort();
333+
}
334+
335+
void smt_bit_vector_theoryt::unsigned_remaindert::validate(
336+
const smt_termt &lhs,
337+
const smt_termt &rhs)
338+
{
339+
validate_bit_vector_predicate_arguments(lhs, rhs);
340+
}
341+
342+
const smt_function_application_termt::factoryt<
343+
smt_bit_vector_theoryt::unsigned_remaindert>
344+
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
@@ -126,6 +126,15 @@ class smt_bit_vector_theoryt
126126
};
127127
static const smt_function_application_termt::factoryt<signed_dividet>
128128
signed_divide;
129+
130+
struct unsigned_remaindert final
131+
{
132+
static const char *identifier();
133+
static smt_sortt return_sort(const smt_termt &lhs, const smt_termt &rhs);
134+
static void validate(const smt_termt &lhs, const smt_termt &rhs);
135+
};
136+
static const smt_function_application_termt::factoryt<unsigned_remaindert>
137+
unsigned_remainder;
129138
};
130139

131140
#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)