Skip to content

Commit 0a327e2

Browse files
committed
Conversion of logical and arithmetic right shift expressions to SMT.
1 parent 0ef6deb commit 0a327e2

File tree

3 files changed

+133
-6
lines changed

3 files changed

+133
-6
lines changed

src/solvers/smt2_incremental/convert_expr_to_smt.cpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -548,16 +548,31 @@ static smt_termt convert_expr_to_smt(const index_exprt &index)
548548
static smt_termt convert_expr_to_smt(const shift_exprt &shift)
549549
{
550550
// TODO: Dispatch into different types of shifting
551+
const auto &first_operand = shift.op0();
552+
const auto &second_operand = shift.op1();
553+
551554
if(const auto left_shift = expr_try_dynamic_cast<shl_exprt>(shift))
552555
{
553556
return smt_bit_vector_theoryt::shift_left(
554-
convert_expr_to_smt(left_shift->op0()),
555-
convert_expr_to_smt(left_shift->op1()));
557+
convert_expr_to_smt(first_operand), convert_expr_to_smt(second_operand));
558+
}
559+
else if(
560+
const auto right_logical_shift = expr_try_dynamic_cast<lshr_exprt>(shift))
561+
{
562+
return smt_bit_vector_theoryt::logical_shift_right(
563+
convert_expr_to_smt(first_operand), convert_expr_to_smt(second_operand));
564+
}
565+
else if(
566+
const auto right_arith_shift = expr_try_dynamic_cast<ashr_exprt>(shift))
567+
{
568+
return smt_bit_vector_theoryt::arithmetic_shift_right(
569+
convert_expr_to_smt(first_operand), convert_expr_to_smt(second_operand));
570+
}
571+
else
572+
{
573+
UNIMPLEMENTED_FEATURE(
574+
"Generation of SMT formula for shift expression: " + shift.pretty());
556575
}
557-
558-
// TODO: split into functions for separate types of shift including rotate.
559-
UNIMPLEMENTED_FEATURE(
560-
"Generation of SMT formula for shift expression: " + shift.pretty());
561576
}
562577

563578
static smt_termt convert_expr_to_smt(const with_exprt &with)

src/util/bitvector_expr.h

Lines changed: 12 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
{
@@ -364,6 +370,12 @@ class lshr_exprt : public shift_exprt
364370
}
365371
};
366372

373+
template <>
374+
inline bool can_cast_expr<lshr_exprt>(const exprt &base)
375+
{
376+
return base.id() == ID_lshr;
377+
}
378+
367379
/// \brief Extracts a single bit of a bit-vector operand
368380
class extractbit_exprt : public binary_predicate_exprt
369381
{

unit/solvers/smt2_incremental/convert_expr_to_smt.cpp

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,3 +714,103 @@ SCENARIO(
714714
}
715715
}
716716
}
717+
718+
SCENARIO(
719+
"Logical Right-shift expressions are converted to SMT terms",
720+
"[core][smt2_incremental]")
721+
{
722+
GIVEN("Two integer bitvectors, one for the value and one for the places")
723+
{
724+
const auto to_be_shifted = from_integer(1, signedbv_typet{8});
725+
const auto places = from_integer(2, signedbv_typet{8});
726+
727+
WHEN("We construct a lshr_exprt and convert it to an SMT term")
728+
{
729+
const auto shift_expr = lshr_exprt{to_be_shifted, places};
730+
const auto constructed_term = convert_expr_to_smt(shift_expr);
731+
732+
THEN("We should get an logical shift right SMT term")
733+
{
734+
const smt_termt smt_term_value = smt_bit_vector_constant_termt{1, 8};
735+
const smt_termt smt_term_places = smt_bit_vector_constant_termt{2, 8};
736+
const auto expected_term = smt_bit_vector_theoryt::logical_shift_right(
737+
smt_term_value, smt_term_places);
738+
REQUIRE(constructed_term == expected_term);
739+
}
740+
}
741+
742+
WHEN(
743+
"We construct a malformed lshr_exprt and attempt to convert it to an SMT"
744+
" term")
745+
{
746+
const cbmc_invariants_should_throwt invariants_throw;
747+
THEN(
748+
"convert_expr_to_smt should throw an exception because of validation "
749+
"failure")
750+
{
751+
REQUIRE_THROWS(
752+
convert_expr_to_smt(lshr_exprt{to_be_shifted, false_exprt{}}));
753+
}
754+
}
755+
}
756+
}
757+
758+
SCENARIO(
759+
"Arithmetic Right-shift expressions are converted to SMT terms",
760+
"[core][smt2_incremental]")
761+
{
762+
GIVEN("Two integer bitvectors, one for the value and one for the places")
763+
{
764+
const auto to_be_shifted = from_integer(1, signedbv_typet{8});
765+
const auto places = from_integer(2, 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{to_be_shifted, places};
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_value = smt_bit_vector_constant_termt{1, 8};
775+
const smt_termt smt_term_places = smt_bit_vector_constant_termt{2, 8};
776+
const auto expected_term =
777+
smt_bit_vector_theoryt::arithmetic_shift_right(
778+
smt_term_value, smt_term_places);
779+
REQUIRE(constructed_term == expected_term);
780+
}
781+
}
782+
783+
WHEN("We construct an ashr_exprt and with a shift of 0 places")
784+
{
785+
const auto zero_places = from_integer(0, signedbv_typet{8});
786+
const auto shift_expr = ashr_exprt{to_be_shifted, zero_places};
787+
const auto constructed_term = convert_expr_to_smt(shift_expr);
788+
789+
THEN(
790+
"When we convert it, we should be getting an arithmetic shift-right "
791+
"term")
792+
{
793+
const smt_termt smt_term_value = smt_bit_vector_constant_termt{1, 8};
794+
const smt_termt smt_term_places = smt_bit_vector_constant_termt{0, 8};
795+
const auto expected_term =
796+
smt_bit_vector_theoryt::arithmetic_shift_right(
797+
smt_term_value, smt_term_places);
798+
REQUIRE(constructed_term == expected_term);
799+
}
800+
}
801+
802+
WHEN(
803+
"We construct a malformed ashr_exprt and attempt to convert it to an SMT "
804+
"term")
805+
{
806+
const cbmc_invariants_should_throwt invariants_throw;
807+
THEN(
808+
"convert_expr_to_smt should throw an exception because of validation "
809+
"failure")
810+
{
811+
REQUIRE_THROWS(
812+
convert_expr_to_smt(ashr_exprt{to_be_shifted, false_exprt{}}));
813+
}
814+
}
815+
}
816+
}

0 commit comments

Comments
 (0)