Skip to content

Commit d3a3eb5

Browse files
committed
Add implementation of arithmetic operator bvadd.
Also add tests for the data structure itself and the conversion of `plus_exprt` to `smt_bit_vector_theoryt::addition`.
1 parent 7bfa0a0 commit d3a3eb5

File tree

5 files changed

+139
-2
lines changed

5 files changed

+139
-2
lines changed

src/solvers/smt2_incremental/convert_expr_to_smt.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,21 @@ static optionalt<smt_termt> try_relational_conversion(const exprt &expr)
326326

327327
static smt_termt convert_expr_to_smt(const plus_exprt &plus)
328328
{
329-
UNIMPLEMENTED_FEATURE(
330-
"Generation of SMT formula for plus expression: " + plus.pretty());
329+
if(std::all_of(
330+
plus.operands().cbegin(),
331+
plus.operands().cend(),
332+
[](exprt operand)
333+
{ return can_cast_type<bitvector_typet>(operand.type()); }))
334+
{
335+
// if all the operands are bitvectors, call the bitvector addition constructor
336+
return convert_multiary_operator_to_terms(
337+
plus, smt_bit_vector_theoryt::add);
338+
}
339+
else
340+
{
341+
UNIMPLEMENTED_FEATURE(
342+
"Generation of SMT formula for plus expression: " + plus.pretty());
343+
}
331344
}
332345

333346
static smt_termt convert_expr_to_smt(const minus_exprt &minus)

src/solvers/smt2_incremental/smt_bit_vector_theory.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,26 @@ static void validate_bit_vector_predicate_arguments(
4242
smt_bit_vector_theoryt::the_name{};
4343
#include "smt_bit_vector_theory.def"
4444
#undef SMT_BITVECTOR_THEORY_PREDICATE
45+
46+
const char *smt_bit_vector_theoryt::additiont::identifier()
47+
{
48+
return "bvadd";
49+
}
50+
51+
smt_sortt smt_bit_vector_theoryt::additiont::return_sort(
52+
const smt_termt &lhs,
53+
const smt_termt &rhs)
54+
{
55+
return lhs.get_sort();
56+
}
57+
58+
void smt_bit_vector_theoryt::additiont::validate(
59+
const smt_termt &lhs,
60+
const smt_termt &rhs)
61+
{
62+
validate_bit_vector_predicate_arguments(lhs, rhs);
63+
}
64+
65+
const smt_function_application_termt::factoryt<
66+
smt_bit_vector_theoryt::additiont>
67+
smt_bit_vector_theoryt::add{};

src/solvers/smt2_incremental/smt_bit_vector_theory.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ class smt_bit_vector_theoryt
2020
static const smt_function_application_termt::factoryt<the_name##t> the_name;
2121
#include "smt_bit_vector_theory.def"
2222
#undef SMT_BITVECTOR_THEORY_PREDICATE
23+
24+
struct additiont final
25+
{
26+
static const char *identifier();
27+
static smt_sortt return_sort(const smt_termt &lhs, const smt_termt &rhs);
28+
static void validate(const smt_termt &lhs, const smt_termt &rhs);
29+
};
30+
static const smt_function_application_termt::factoryt<additiont> add;
2331
};
2432

2533
#endif // CPROVER_SOLVERS_SMT2_INCREMENTAL_SMT_BIT_VECTOR_THEORY_H

unit/solvers/smt2_incremental/convert_expr_to_smt.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,3 +239,68 @@ TEST_CASE(
239239
smt_bit_vector_theoryt::unsigned_less_than_or_equal(one_term, two_term));
240240
}
241241
}
242+
243+
TEST_CASE(
244+
"expr to smt conversion for arithmetic operators",
245+
"[core][smt2_incremental]")
246+
{
247+
const smt_termt smt_term_one = smt_bit_vector_constant_termt{1, 8};
248+
const smt_termt smt_term_two = smt_bit_vector_constant_termt{2, 8};
249+
250+
// Just regular (bit-vector) integers, to be used for the comparison
251+
const auto one_bvint = from_integer({1}, signedbv_typet{8});
252+
const auto two_bvint = from_integer({2}, signedbv_typet{8});
253+
const auto one_bvint_unsigned = from_integer({1}, unsignedbv_typet{8});
254+
const auto two_bvint_unsigned = from_integer({2}, unsignedbv_typet{8});
255+
256+
SECTION("Addition of two constant size bit-vectors")
257+
{
258+
const auto constructed_term =
259+
convert_expr_to_smt(plus_exprt{one_bvint, two_bvint});
260+
const auto expected_term =
261+
smt_bit_vector_theoryt::add(smt_term_one, smt_term_two);
262+
CHECK(constructed_term == expected_term);
263+
}
264+
265+
SECTION(
266+
"Addition of four constant size bit-vectors - testing multi-ary handling "
267+
"of plus_exprt")
268+
{
269+
const auto three_bv_int = from_integer({3}, signedbv_typet{8});
270+
const auto four_bv_int = from_integer({4}, signedbv_typet{8});
271+
272+
const auto three_smt_term = smt_bit_vector_constant_termt{3, 8};
273+
const auto four_smt_term = smt_bit_vector_constant_termt{4, 8};
274+
275+
const exprt::operandst plus_operands{
276+
one_bvint, two_bvint, three_bv_int, four_bv_int};
277+
const auto constructed_term =
278+
convert_expr_to_smt(plus_exprt{plus_operands, signedbv_typet{8}});
279+
const auto expected_term = smt_bit_vector_theoryt::add(
280+
smt_bit_vector_theoryt::add(
281+
smt_bit_vector_theoryt::add(smt_term_one, smt_term_two),
282+
three_smt_term),
283+
four_smt_term);
284+
285+
CHECK(constructed_term == expected_term);
286+
}
287+
288+
SECTION(
289+
"Ensure that addition node conversion fails if the operands are not "
290+
"bit-vector based")
291+
{
292+
const cbmc_invariants_should_throwt invariants_throw;
293+
REQUIRE_THROWS(
294+
convert_expr_to_smt(plus_exprt{true_exprt{}, false_exprt{}}));
295+
}
296+
297+
SECTION(
298+
"Ensure that addition node conversion fails if it has a malformed "
299+
"expression")
300+
{
301+
const cbmc_invariants_should_throwt invariants_throw;
302+
exprt::operandst operands;
303+
REQUIRE_THROWS(
304+
convert_expr_to_smt(plus_exprt{operands, signedbv_typet{8}}));
305+
}
306+
}

unit/solvers/smt2_incremental/smt_bit_vector_theory.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,3 +166,31 @@ TEST_CASE("SMT bit vector predicates", "[core][smt2_incremental]")
166166
smt_bit_vector_theoryt::signed_greater_than_or_equal(two, wider));
167167
}
168168
}
169+
170+
TEST_CASE(
171+
"SMT bit vector arithmetic operator implementation tests",
172+
"[core][smt2_incremental]")
173+
{
174+
const smt_bit_vector_constant_termt two{2, 8};
175+
const smt_bit_vector_constant_termt three{3, 8};
176+
const smt_bit_vector_constant_termt four{4, 16};
177+
const smt_bool_literal_termt true_val{true};
178+
179+
SECTION("Addition")
180+
{
181+
const auto function_application = smt_bit_vector_theoryt::add(two, three);
182+
REQUIRE(
183+
function_application.function_identifier() ==
184+
smt_identifier_termt("bvadd", smt_bit_vector_sortt{8}));
185+
REQUIRE(function_application.get_sort() == smt_bit_vector_sortt{8});
186+
REQUIRE(function_application.arguments().size() == 2);
187+
REQUIRE(function_application.arguments()[0].get() == two);
188+
REQUIRE(function_application.arguments()[1].get() == three);
189+
190+
cbmc_invariants_should_throwt invariants_throw;
191+
// Bit-vectors of mismatched sorts are going to hit an invariant violation.
192+
REQUIRE_THROWS(smt_bit_vector_theoryt::add(three, four));
193+
// An addition of a bool and a bitvector should hit an invariant violation.
194+
REQUIRE_THROWS(smt_bit_vector_theoryt::add(three, true_val));
195+
}
196+
}

0 commit comments

Comments
 (0)