Skip to content

Commit d723971

Browse files
committed
Add SMT bit vector extension operations
1 parent 64e4d4d commit d723971

File tree

3 files changed

+118
-0
lines changed

3 files changed

+118
-0
lines changed

src/solvers/smt2_incremental/smt_bit_vector_theory.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -731,3 +731,61 @@ smt_bit_vector_theoryt::repeat(std::size_t i)
731731
PRECONDITION(i >= 1);
732732
return smt_function_application_termt::factoryt<repeatt>(i);
733733
}
734+
735+
const char *smt_bit_vector_theoryt::zero_extendt::identifier()
736+
{
737+
return "zero_extend";
738+
}
739+
740+
smt_sortt smt_bit_vector_theoryt::zero_extendt::return_sort(
741+
const smt_termt &operand) const
742+
{
743+
const std::size_t operand_width =
744+
operand.get_sort().cast<smt_bit_vector_sortt>()->bit_width();
745+
return smt_bit_vector_sortt{i + operand_width};
746+
}
747+
748+
std::vector<smt_indext> smt_bit_vector_theoryt::zero_extendt::indices() const
749+
{
750+
return {smt_numeral_indext{i}};
751+
}
752+
753+
void smt_bit_vector_theoryt::zero_extendt::validate(const smt_termt &operand)
754+
{
755+
PRECONDITION(operand.get_sort().cast<smt_bit_vector_sortt>());
756+
}
757+
758+
smt_function_application_termt::factoryt<smt_bit_vector_theoryt::zero_extendt>
759+
smt_bit_vector_theoryt::zero_extend(std::size_t i)
760+
{
761+
return smt_function_application_termt::factoryt<zero_extendt>(i);
762+
}
763+
764+
const char *smt_bit_vector_theoryt::sign_extendt::identifier()
765+
{
766+
return "sign_extend";
767+
}
768+
769+
smt_sortt smt_bit_vector_theoryt::sign_extendt::return_sort(
770+
const smt_termt &operand) const
771+
{
772+
const std::size_t operand_width =
773+
operand.get_sort().cast<smt_bit_vector_sortt>()->bit_width();
774+
return smt_bit_vector_sortt{i + operand_width};
775+
}
776+
777+
std::vector<smt_indext> smt_bit_vector_theoryt::sign_extendt::indices() const
778+
{
779+
return {smt_numeral_indext{i}};
780+
}
781+
782+
void smt_bit_vector_theoryt::sign_extendt::validate(const smt_termt &operand)
783+
{
784+
PRECONDITION(operand.get_sort().cast<smt_bit_vector_sortt>());
785+
}
786+
787+
smt_function_application_termt::factoryt<smt_bit_vector_theoryt::sign_extendt>
788+
smt_bit_vector_theoryt::sign_extend(std::size_t i)
789+
{
790+
return smt_function_application_termt::factoryt<sign_extendt>(i);
791+
}

src/solvers/smt2_incremental/smt_bit_vector_theory.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,28 @@ class smt_bit_vector_theoryt
275275
};
276276
static smt_function_application_termt::factoryt<repeatt>
277277
repeat(std::size_t i);
278+
279+
struct zero_extendt final
280+
{
281+
std::size_t i;
282+
static const char *identifier();
283+
smt_sortt return_sort(const smt_termt &operand) const;
284+
std::vector<smt_indext> indices() const;
285+
static void validate(const smt_termt &operand);
286+
};
287+
static smt_function_application_termt::factoryt<zero_extendt>
288+
zero_extend(std::size_t i);
289+
290+
struct sign_extendt final
291+
{
292+
std::size_t i;
293+
static const char *identifier();
294+
smt_sortt return_sort(const smt_termt &operand) const;
295+
std::vector<smt_indext> indices() const;
296+
static void validate(const smt_termt &operand);
297+
};
298+
static smt_function_application_termt::factoryt<sign_extendt>
299+
sign_extend(std::size_t i);
278300
};
279301

280302
#endif // CPROVER_SOLVERS_SMT2_INCREMENTAL_SMT_BIT_VECTOR_THEORY_H

unit/solvers/smt2_incremental/smt_bit_vector_theory.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,3 +595,41 @@ TEST_CASE("SMT bit vector repeat", "[core][smt2_incremental]")
595595
REQUIRE_THROWS(smt_bit_vector_theoryt::repeat(0));
596596
REQUIRE_THROWS(smt_bit_vector_theoryt::repeat(1)(true_val));
597597
}
598+
599+
TEST_CASE("SMT bit vector extend", "[core][smt2_incremental]")
600+
{
601+
const smt_bit_vector_constant_termt two{2, 8};
602+
const smt_bool_literal_termt true_val{true};
603+
SECTION("Zero extension")
604+
{
605+
const auto function_application =
606+
smt_bit_vector_theoryt::zero_extend(4)(two);
607+
const auto expected_return_sort = smt_bit_vector_sortt{12};
608+
REQUIRE(
609+
function_application.function_identifier() ==
610+
smt_identifier_termt(
611+
"zero_extend", expected_return_sort, {smt_numeral_indext{4}}));
612+
REQUIRE(function_application.get_sort() == expected_return_sort);
613+
REQUIRE(function_application.arguments().size() == 1);
614+
REQUIRE(function_application.arguments()[0].get() == two);
615+
cbmc_invariants_should_throwt invariants_throw;
616+
REQUIRE_NOTHROW(smt_bit_vector_theoryt::zero_extend(0));
617+
REQUIRE_THROWS(smt_bit_vector_theoryt::zero_extend(1)(true_val));
618+
}
619+
SECTION("Sign extension")
620+
{
621+
const auto function_application =
622+
smt_bit_vector_theoryt::sign_extend(4)(two);
623+
const auto expected_return_sort = smt_bit_vector_sortt{12};
624+
REQUIRE(
625+
function_application.function_identifier() ==
626+
smt_identifier_termt(
627+
"sign_extend", expected_return_sort, {smt_numeral_indext{4}}));
628+
REQUIRE(function_application.get_sort() == expected_return_sort);
629+
REQUIRE(function_application.arguments().size() == 1);
630+
REQUIRE(function_application.arguments()[0].get() == two);
631+
cbmc_invariants_should_throwt invariants_throw;
632+
REQUIRE_NOTHROW(smt_bit_vector_theoryt::sign_extend(0));
633+
REQUIRE_THROWS(smt_bit_vector_theoryt::sign_extend(1)(true_val));
634+
}
635+
}

0 commit comments

Comments
 (0)