File tree Expand file tree Collapse file tree 5 files changed +86
-3
lines changed
src/solvers/smt2_incremental
unit/solvers/smt2_incremental Expand file tree Collapse file tree 5 files changed +86
-3
lines changed Original file line number Diff line number Diff line change @@ -400,9 +400,22 @@ static smt_termt convert_expr_to_smt(const ieee_float_op_exprt &float_operation)
400400
401401static smt_termt convert_expr_to_smt (const mod_exprt &truncation_modulo)
402402{
403- UNIMPLEMENTED_FEATURE (
404- " Generation of SMT formula for truncation modulo expression: " +
405- truncation_modulo.pretty ());
403+ const bool both_operands_bitvector =
404+ can_cast_type<integer_bitvector_typet>(truncation_modulo.lhs ().type ()) &&
405+ can_cast_type<integer_bitvector_typet>(truncation_modulo.rhs ().type ());
406+
407+ if (both_operands_bitvector)
408+ {
409+ return smt_bit_vector_theoryt::unsigned_remainder (
410+ convert_expr_to_smt (truncation_modulo.lhs ()),
411+ convert_expr_to_smt (truncation_modulo.rhs ()));
412+ }
413+ else
414+ {
415+ UNIMPLEMENTED_FEATURE (
416+ " Generation of SMT formula for remainder (modulus) expression: " +
417+ truncation_modulo.pretty ());
418+ }
406419}
407420
408421static smt_termt
Original file line number Diff line number Diff line change @@ -319,3 +319,26 @@ void smt_bit_vector_theoryt::signed_dividet::validate(
319319const 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{};
Original file line number Diff line number Diff 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
Original file line number Diff line number Diff 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}
Original file line number Diff line number Diff line change @@ -271,4 +271,23 @@ TEST_CASE(
271271 // A division of a bool and a bitvector should hit an invariant violation.
272272 REQUIRE_THROWS (smt_bit_vector_theoryt::signed_divide (true_val, three));
273273 }
274+
275+ SECTION (" Unsigned Remainder" )
276+ {
277+ const auto function_application =
278+ smt_bit_vector_theoryt::unsigned_remainder (two, three);
279+ REQUIRE (
280+ function_application.function_identifier () ==
281+ smt_identifier_termt (" bvurem" , smt_bit_vector_sortt{8 }));
282+ REQUIRE (function_application.get_sort () == smt_bit_vector_sortt{8 });
283+ REQUIRE (function_application.arguments ().size () == 2 );
284+ REQUIRE (function_application.arguments ()[0 ].get () == two);
285+ REQUIRE (function_application.arguments ()[1 ].get () == three);
286+
287+ cbmc_invariants_should_throwt invariants_throw;
288+ // Bit-vectors of mismatched sorts are going to hit an invariant violation.
289+ REQUIRE_THROWS (smt_bit_vector_theoryt::unsigned_remainder (three, four));
290+ // A remainder of a bool and a bitvector should hit an invariant violation.
291+ REQUIRE_THROWS (smt_bit_vector_theoryt::unsigned_remainder (true_val, three));
292+ }
274293}
You can’t perform that action at this time.
0 commit comments