Skip to content

Commit d75e3d7

Browse files
committed
SMT2 back-end: fix inconsistent array flattening
Whether we flatten or don't (when datatype support is not available) depends on the expression, but we may need to unflatten when the context expects an array. Fixes: #8399
1 parent b335979 commit d75e3d7

File tree

1 file changed

+42
-46
lines changed

1 file changed

+42
-46
lines changed

src/solvers/smt2/smt2_conv.cpp

Lines changed: 42 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -4565,57 +4565,50 @@ void smt2_convt::unflatten(
45654565
}
45664566
else if(type.id() == ID_array)
45674567
{
4568-
if(use_datatypes)
4568+
PRECONDITION(use_as_const);
4569+
4570+
if(where == wheret::BEGIN)
4571+
out << "(let ((?ufop" << nesting << " ";
4572+
else
45694573
{
4570-
PRECONDITION(use_as_const);
4574+
out << ")) ";
45714575

4572-
if(where == wheret::BEGIN)
4573-
out << "(let ((?ufop" << nesting << " ";
4574-
else
4575-
{
4576-
out << ")) ";
4576+
const array_typet &array_type = to_array_type(type);
45774577

4578-
const array_typet &array_type = to_array_type(type);
4578+
std::size_t subtype_width = boolbv_width(array_type.element_type());
45794579

4580-
std::size_t subtype_width = boolbv_width(array_type.element_type());
4580+
DATA_INVARIANT(
4581+
array_type.size().is_constant(),
4582+
"cannot unflatten arrays of non-constant size");
4583+
mp_integer size =
4584+
numeric_cast_v<mp_integer>(to_constant_expr(array_type.size()));
45814585

4582-
DATA_INVARIANT(
4583-
array_type.size().is_constant(),
4584-
"cannot unflatten arrays of non-constant size");
4585-
mp_integer size =
4586-
numeric_cast_v<mp_integer>(to_constant_expr(array_type.size()));
4586+
for(mp_integer i = 1; i < size; ++i)
4587+
out << "(store ";
45874588

4588-
for(mp_integer i = 1; i < size; ++i)
4589-
out << "(store ";
4589+
out << "((as const ";
4590+
convert_type(array_type);
4591+
out << ") ";
4592+
// use element at index 0 as default value
4593+
unflatten(wheret::BEGIN, array_type.element_type(), nesting + 1);
4594+
out << "((_ extract " << subtype_width - 1 << " "
4595+
<< "0) ?ufop" << nesting << ")";
4596+
unflatten(wheret::END, array_type.element_type(), nesting + 1);
4597+
out << ") ";
45904598

4591-
out << "((as const ";
4592-
convert_type(array_type);
4593-
out << ") ";
4594-
// use element at index 0 as default value
4599+
std::size_t offset = subtype_width;
4600+
for(mp_integer i = 1; i < size; ++i, offset += subtype_width)
4601+
{
4602+
convert_expr(from_integer(i, array_type.index_type()));
4603+
out << ' ';
45954604
unflatten(wheret::BEGIN, array_type.element_type(), nesting + 1);
4596-
out << "((_ extract " << subtype_width - 1 << " "
4597-
<< "0) ?ufop" << nesting << ")";
4605+
out << "((_ extract " << offset + subtype_width - 1 << " " << offset
4606+
<< ") ?ufop" << nesting << ")";
45984607
unflatten(wheret::END, array_type.element_type(), nesting + 1);
4599-
out << ") ";
4600-
4601-
std::size_t offset = subtype_width;
4602-
for(mp_integer i = 1; i < size; ++i, offset += subtype_width)
4603-
{
4604-
convert_expr(from_integer(i, array_type.index_type()));
4605-
out << ' ';
4606-
unflatten(wheret::BEGIN, array_type.element_type(), nesting + 1);
4607-
out << "((_ extract " << offset + subtype_width - 1 << " " << offset
4608-
<< ") ?ufop" << nesting << ")";
4609-
unflatten(wheret::END, array_type.element_type(), nesting + 1);
4610-
out << ")"; // store
4611-
}
4612-
4613-
out << ")"; // let
4608+
out << ")"; // store
46144609
}
4615-
}
4616-
else
4617-
{
4618-
// nop, already a bv
4610+
4611+
out << ")"; // let
46194612
}
46204613
}
46214614
else if(type.id() == ID_struct || type.id() == ID_struct_tag)
@@ -4767,19 +4760,22 @@ void smt2_convt::set_to(const exprt &expr, bool value)
47674760
{
47684761
out << "(define-fun " << smt2_identifier;
47694762
out << " () ";
4763+
convert_type(equal_expr.lhs().type());
4764+
out << ' ';
47704765
if(
47714766
equal_expr.lhs().type().id() != ID_array ||
47724767
use_array_theory(prepared_rhs))
47734768
{
4774-
convert_type(equal_expr.lhs().type());
4769+
convert_expr(prepared_rhs);
47754770
}
47764771
else
47774772
{
4778-
std::size_t width = boolbv_width(equal_expr.lhs().type());
4779-
out << "(_ BitVec " << width << ")";
4773+
unflatten(wheret::BEGIN, equal_expr.lhs().type());
4774+
4775+
convert_expr(prepared_rhs);
4776+
4777+
unflatten(wheret::END, equal_expr.lhs().type());
47804778
}
4781-
out << ' ';
4782-
convert_expr(prepared_rhs);
47834779
out << ')' << '\n';
47844780
}
47854781

0 commit comments

Comments
 (0)