Skip to content

Commit f1c3e8d

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 f1c3e8d

File tree

1 file changed

+45
-32
lines changed

1 file changed

+45
-32
lines changed

src/solvers/smt2/smt2_conv.cpp

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

44234434
// figure out the offset and width of the member
44244435
const boolbv_widtht::membert &m =
44254436
boolbv_width.get_member(struct_type, component_name);
44264437

4427-
out << "(let ((?withop ";
4428-
convert_expr(expr.old());
4429-
out << ")) ";
4430-
44314438
if(m.width==struct_width)
44324439
{
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))";
4440+
// the struct is the same as the member, no concat needed
4441+
convert_operand(value);
44524442
}
44534443
else
44544444
{
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-
}
4445+
out << "(let ((?withop ";
4446+
convert_operand(expr.old());
4447+
out << ")) ";
4448+
4449+
if(m.offset == 0)
4450+
{
4451+
// the member is at the beginning
4452+
out << "(concat "
4453+
<< "((_ extract " << (struct_width - 1) << " " << m.width
4454+
<< ") ?withop) ";
4455+
convert_operand(value);
4456+
out << ")"; // concat
4457+
}
4458+
else if(m.offset + m.width == struct_width)
4459+
{
4460+
// the member is at the end
4461+
out << "(concat ";
4462+
convert_operand(value);
4463+
out << " ((_ extract " << (m.offset - 1) << " 0) ?withop))";
4464+
}
4465+
else
4466+
{
4467+
// most general case, need two concat-s
4468+
out << "(concat (concat "
4469+
<< "((_ extract " << (struct_width - 1) << " "
4470+
<< (m.offset + m.width) << ") ?withop) ";
4471+
convert_operand(value);
4472+
out << ") ((_ extract " << (m.offset - 1) << " 0) ?withop)";
4473+
out << ")"; // concat
4474+
}
44634475

4464-
out << ")"; // let ?withop
4476+
out << ")"; // let ?withop
4477+
}
44654478
}
44664479
}
44674480
else if(expr_type.id() == ID_union || expr_type.id() == ID_union_tag)

0 commit comments

Comments
 (0)