Skip to content

Commit f2489e3

Browse files
authored
Merge pull request #8537 from diffblue/smt2-range-fix
SMT2: range_type fixes
2 parents 3c4ffae + 632093c commit f2489e3

File tree

3 files changed

+80
-7
lines changed

3 files changed

+80
-7
lines changed

Diff for: src/solvers/smt2/smt2_conv.cpp

+60-7
Original file line numberDiff line numberDiff line change
@@ -517,11 +517,14 @@ constant_exprt smt2_convt::parse_literal(
517517
std::size_t width=boolbv_width(type);
518518
return constant_exprt(integer2bvrep(value, width), type);
519519
}
520-
else if(type.id()==ID_integer ||
521-
type.id()==ID_range)
520+
else if(type.id() == ID_integer)
522521
{
523522
return from_integer(value, type);
524523
}
524+
else if(type.id() == ID_range)
525+
{
526+
return from_integer(value + to_range_type(type).get_from(), type);
527+
}
525528
else
526529
UNREACHABLE_BECAUSE(
527530
"smt2_convt::parse_literal should not be of unsupported type " +
@@ -1317,17 +1320,26 @@ void smt2_convt::convert_expr(const exprt &expr)
13171320
else if(expr.id()==ID_unary_minus)
13181321
{
13191322
const unary_minus_exprt &unary_minus_expr = to_unary_minus_expr(expr);
1323+
const auto &type = expr.type();
13201324

13211325
if(
1322-
unary_minus_expr.type().id() == ID_rational ||
1323-
unary_minus_expr.type().id() == ID_integer ||
1324-
unary_minus_expr.type().id() == ID_real)
1326+
type.id() == ID_rational || type.id() == ID_integer ||
1327+
type.id() == ID_real)
13251328
{
13261329
out << "(- ";
13271330
convert_expr(unary_minus_expr.op());
13281331
out << ")";
13291332
}
1330-
else if(unary_minus_expr.type().id() == ID_floatbv)
1333+
else if(type.id() == ID_range)
1334+
{
1335+
auto &range_type = to_range_type(type);
1336+
PRECONDITION(type == unary_minus_expr.op().type());
1337+
// turn -x into 0-x
1338+
auto minus_expr =
1339+
minus_exprt{range_type.zero_expr(), unary_minus_expr.op()};
1340+
convert_expr(minus_expr);
1341+
}
1342+
else if(type.id() == ID_floatbv)
13311343
{
13321344
// this has no rounding mode
13331345
if(use_FPA_theory)
@@ -3764,7 +3776,7 @@ void smt2_convt::convert_plus(const plus_exprt &expr)
37643776
}
37653777
else if(
37663778
expr.type().id() == ID_unsignedbv || expr.type().id() == ID_signedbv ||
3767-
expr.type().id() == ID_fixedbv || expr.type().id() == ID_range)
3779+
expr.type().id() == ID_fixedbv)
37683780
{
37693781
// These could be chained, i.e., need not be binary,
37703782
// but at least MathSat doesn't like that.
@@ -3781,6 +3793,31 @@ void smt2_convt::convert_plus(const plus_exprt &expr)
37813793
convert_plus(to_plus_expr(make_binary(expr)));
37823794
}
37833795
}
3796+
else if(expr.type().id() == ID_range)
3797+
{
3798+
auto &range_type = to_range_type(expr.type());
3799+
3800+
// These could be chained, i.e., need not be binary,
3801+
// but at least MathSat doesn't like that.
3802+
if(expr.operands().size() == 2)
3803+
{
3804+
// add: lhs + from + rhs + from - from = lhs + rhs + from
3805+
mp_integer from = range_type.get_from();
3806+
const auto size = range_type.get_to() - range_type.get_from() + 1;
3807+
const auto width = address_bits(size);
3808+
3809+
out << "(bvadd ";
3810+
convert_expr(expr.op0());
3811+
out << " (bvadd ";
3812+
convert_expr(expr.op1());
3813+
out << " (_ bv" << range_type.get_from() << ' ' << width
3814+
<< ")))"; // bv, bvadd, bvadd
3815+
}
3816+
else
3817+
{
3818+
convert_plus(to_plus_expr(make_binary(expr)));
3819+
}
3820+
}
37843821
else if(expr.type().id() == ID_floatbv)
37853822
{
37863823
// Floating-point additions should have be been converted
@@ -4018,6 +4055,22 @@ void smt2_convt::convert_minus(const minus_exprt &expr)
40184055
"unsupported operand types for -: " + expr.op0().type().id_string() +
40194056
" and " + expr.op1().type().id_string());
40204057
}
4058+
else if(expr.type().id() == ID_range)
4059+
{
4060+
auto &range_type = to_range_type(expr.type());
4061+
4062+
// sub: lhs + from - (rhs + from) - from = lhs - rhs - from
4063+
mp_integer from = range_type.get_from();
4064+
const auto size = range_type.get_to() - range_type.get_from() + 1;
4065+
const auto width = address_bits(size);
4066+
4067+
out << "(bvsub (bvsub ";
4068+
convert_expr(expr.op0());
4069+
out << ' ';
4070+
convert_expr(expr.op1());
4071+
out << ") (_ bv" << range_type.get_from() << ' ' << width
4072+
<< "))"; // bv, bvsub
4073+
}
40214074
else
40224075
UNEXPECTEDCASE("unsupported type for -: "+expr.type().id_string());
40234076
}

Diff for: src/util/std_types.cpp

+17
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,23 @@ void bitvector_typet::width(const mp_integer &width)
165165
set_width(numeric_cast_v<std::size_t>(width));
166166
}
167167

168+
bool range_typet::includes(const mp_integer &singleton) const
169+
{
170+
return get_from() <= singleton && singleton <= get_to();
171+
}
172+
173+
constant_exprt range_typet::one_expr() const
174+
{
175+
PRECONDITION(includes(1));
176+
return constant_exprt{ID_1, *this};
177+
}
178+
179+
constant_exprt range_typet::zero_expr() const
180+
{
181+
PRECONDITION(includes(0));
182+
return constant_exprt{ID_0, *this};
183+
}
184+
168185
void range_typet::set_from(const mp_integer &from)
169186
{
170187
set(ID_from, integer2string(from));

Diff for: src/util/std_types.h

+3
Original file line numberDiff line numberDiff line change
@@ -1012,6 +1012,9 @@ class range_typet:public typet
10121012

10131013
mp_integer get_from() const;
10141014
mp_integer get_to() const;
1015+
bool includes(const mp_integer &) const;
1016+
constant_exprt zero_expr() const;
1017+
constant_exprt one_expr() const;
10151018

10161019
void set_from(const mp_integer &_from);
10171020
void set_to(const mp_integer &to);

0 commit comments

Comments
 (0)