Skip to content

Commit 48d1e7e

Browse files
committed
Add implementation and tests for arithmetic right shift conversion to SMT terms.
1 parent 9ab674b commit 48d1e7e

File tree

3 files changed

+82
-5
lines changed

3 files changed

+82
-5
lines changed

src/solvers/smt2_incremental/convert_expr_to_smt.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,6 @@ static smt_termt convert_expr_to_smt(const index_exprt &index)
550550

551551
static smt_termt convert_expr_to_smt(const shift_exprt &shift)
552552
{
553-
// TODO: Dispatch into different types of shifting
554553
if(const auto left_shift = expr_try_dynamic_cast<shl_exprt>(shift))
555554
{
556555
return smt_bit_vector_theoryt::shift_left(
@@ -564,10 +563,18 @@ static smt_termt convert_expr_to_smt(const shift_exprt &shift)
564563
convert_expr_to_smt(right_logical_shift->op0()),
565564
convert_expr_to_smt(right_logical_shift->op1()));
566565
}
567-
568-
// TODO: split into functions for separate types of shift including rotate.
569-
UNIMPLEMENTED_FEATURE(
570-
"Generation of SMT formula for shift expression: " + shift.pretty());
566+
else if(
567+
const auto right_arith_shift = expr_try_dynamic_cast<ashr_exprt>(shift))
568+
{
569+
return smt_bit_vector_theoryt::arithmetic_shift_right(
570+
convert_expr_to_smt(right_arith_shift->op0()),
571+
convert_expr_to_smt(right_arith_shift->op1()));
572+
}
573+
else
574+
{
575+
UNIMPLEMENTED_FEATURE(
576+
"Generation of SMT formula for shift expression: " + shift.pretty());
577+
}
571578
}
572579

573580
static smt_termt convert_expr_to_smt(const with_exprt &with)

src/util/bitvector_expr.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,12 @@ class ashr_exprt : public shift_exprt
349349
}
350350
};
351351

352+
template <>
353+
inline bool can_cast_expr<ashr_exprt>(const exprt &base)
354+
{
355+
return base.id() == ID_ashr;
356+
}
357+
352358
/// \brief Logical right shift
353359
class lshr_exprt : public shift_exprt
354360
{

unit/solvers/smt2_incremental/convert_expr_to_smt.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,3 +755,67 @@ SCENARIO(
755755
}
756756
}
757757
}
758+
759+
SCENARIO(
760+
"Arithmetic Right-shift expressions are converted to SMT terms",
761+
"[core][smt2_incremental]")
762+
{
763+
GIVEN("An integer bitvector")
764+
{
765+
const auto one_bvint = from_integer({1}, signedbv_typet{8});
766+
767+
WHEN("We construct a ashr_exprt and convert it to an SMT term")
768+
{
769+
const auto shift_expr = ashr_exprt{one_bvint, one_bvint};
770+
const auto constructed_term = convert_expr_to_smt(shift_expr);
771+
772+
THEN("We should get an arithmetic shift-right SMT term")
773+
{
774+
const smt_termt smt_term_one = smt_bit_vector_constant_termt{1, 8};
775+
const auto expected_term =
776+
smt_bit_vector_theoryt::arithmetic_shift_right(
777+
/* Value to be shifted */
778+
smt_term_one,
779+
/* Places */
780+
smt_term_one);
781+
REQUIRE(constructed_term == expected_term);
782+
}
783+
}
784+
785+
WHEN("We construct an ashr_exprt and with a shift of 0 places")
786+
{
787+
const auto zero_bvint = from_integer({0}, signedbv_typet{8});
788+
const auto shift_expr = ashr_exprt{one_bvint, zero_bvint};
789+
const auto constructed_term = convert_expr_to_smt(shift_expr);
790+
791+
THEN(
792+
"When we convert it, we should be getting an arithmetic shift-right "
793+
"term")
794+
{
795+
const smt_termt smt_term_zero = smt_bit_vector_constant_termt{0, 8};
796+
const smt_termt smt_term_one = smt_bit_vector_constant_termt{1, 8};
797+
const auto expected_term =
798+
smt_bit_vector_theoryt::arithmetic_shift_right(
799+
/* Value to be shifted */
800+
smt_term_one,
801+
/* Places */
802+
smt_term_zero);
803+
REQUIRE(constructed_term == expected_term);
804+
}
805+
}
806+
807+
WHEN(
808+
"We construct a malformed ashr_exprt and attempt to convert it to an SMT "
809+
"term")
810+
{
811+
const cbmc_invariants_should_throwt invariants_throw;
812+
THEN(
813+
"convert_expr_to_smt should throw an exception because of validation "
814+
"failure")
815+
{
816+
REQUIRE_THROWS(
817+
convert_expr_to_smt(ashr_exprt{one_bvint, false_exprt{}}));
818+
}
819+
}
820+
}
821+
}

0 commit comments

Comments
 (0)