Skip to content

Commit 935663c

Browse files
committed
SMT2 back-end: flatten with_exprt operands
Solvers without datatypes support require flattening towards bitvectors. This is also true for array-typed expressions when the array is not at the top level (despite possible array-theory support). This changes makes sure we will flatten such array-typed expressions.
1 parent 48490fb commit 935663c

File tree

1 file changed

+44
-32
lines changed

1 file changed

+44
-32
lines changed

src/solvers/smt2/smt2_conv.cpp

Lines changed: 44 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4418,50 +4418,62 @@ void smt2_convt::convert_with(const with_exprt &expr)
44184418
}
44194419
else
44204420
{
4421+
auto convert_operand = [this](const exprt &op) {
4422+
// may need to flatten array-theory arrays in there
4423+
if(op.type().id() == ID_array && use_array_theory(op))
4424+
flatten_array(op);
4425+
else if(op.type().id() == ID_bool)
4426+
flatten2bv(op);
4427+
else
4428+
convert_expr(op);
4429+
};
4430+
44214431
std::size_t struct_width=boolbv_width(struct_type);
44224432

44234433
// figure out the offset and width of the member
44244434
const boolbv_widtht::membert &m =
44254435
boolbv_width.get_member(struct_type, component_name);
44264436

4427-
out << "(let ((?withop ";
4428-
convert_expr(expr.old());
4429-
out << ")) ";
4430-
44314437
if(m.width==struct_width)
44324438
{
4433-
// the struct is the same as the member, no concat needed,
4434-
// ?withop won't be used
4435-
convert_expr(value);
4436-
}
4437-
else if(m.offset==0)
4438-
{
4439-
// the member is at the beginning
4440-
out << "(concat "
4441-
<< "((_ extract " << (struct_width-1) << " "
4442-
<< m.width << ") ?withop) ";
4443-
convert_expr(value);
4444-
out << ")"; // concat
4445-
}
4446-
else if(m.offset+m.width==struct_width)
4447-
{
4448-
// the member is at the end
4449-
out << "(concat ";
4450-
convert_expr(value);
4451-
out << " ((_ extract " << (m.offset - 1) << " 0) ?withop))";
4439+
// the struct is the same as the member, no concat needed
4440+
convert_operand(value);
44524441
}
44534442
else
44544443
{
4455-
// most general case, need two concat-s
4456-
out << "(concat (concat "
4457-
<< "((_ extract " << (struct_width-1) << " "
4458-
<< (m.offset+m.width) << ") ?withop) ";
4459-
convert_expr(value);
4460-
out << ") ((_ extract " << (m.offset-1) << " 0) ?withop)";
4461-
out << ")"; // concat
4462-
}
4444+
out << "(let ((?withop ";
4445+
convert_operand(expr.old());
4446+
out << ")) ";
4447+
4448+
if(m.offset==0)
4449+
{
4450+
// the member is at the beginning
4451+
out << "(concat "
4452+
<< "((_ extract " << (struct_width-1) << " "
4453+
<< m.width << ") ?withop) ";
4454+
convert_operand(value);
4455+
out << ")"; // concat
4456+
}
4457+
else if(m.offset+m.width==struct_width)
4458+
{
4459+
// the member is at the end
4460+
out << "(concat ";
4461+
convert_operand(value);
4462+
out << " ((_ extract " << (m.offset - 1) << " 0) ?withop))";
4463+
}
4464+
else
4465+
{
4466+
// most general case, need two concat-s
4467+
out << "(concat (concat "
4468+
<< "((_ extract " << (struct_width-1) << " "
4469+
<< (m.offset+m.width) << ") ?withop) ";
4470+
convert_operand(value);
4471+
out << ") ((_ extract " << (m.offset-1) << " 0) ?withop)";
4472+
out << ")"; // concat
4473+
}
44634474

4464-
out << ")"; // let ?withop
4475+
out << ")"; // let ?withop
4476+
}
44654477
}
44664478
}
44674479
else if(expr_type.id() == ID_union || expr_type.id() == ID_union_tag)

0 commit comments

Comments
 (0)