Skip to content

Commit 97cb8a3

Browse files
committed
simplify extractbits_exprt representation
The current representation of extractbits_exprt stores both the upper and lower indices of the range that is to be extracted, and their difference plus one in form of the width of the type of the expression. This removes the upper index, as it can be deduced from the lower index and the width of the result. The key benefit is reducing burden on the user of the class, who a) doesn't have to remember which index comes first, and b) doesn't have to do the calculation of the upper index.
1 parent baaccb6 commit 97cb8a3

File tree

18 files changed

+120
-189
lines changed

18 files changed

+120
-189
lines changed

src/ansi-c/expr2c.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3494,9 +3494,18 @@ expr2ct::convert_extractbits(const extractbits_exprt &src, unsigned precedence)
34943494
{
34953495
std::string dest = convert_with_precedence(src.src(), precedence);
34963496
dest+='[';
3497-
dest += convert_with_precedence(src.upper(), precedence);
3497+
auto expr_width_opt = pointer_offset_bits(src.type(), ns);
3498+
if(expr_width_opt.has_value())
3499+
{
3500+
auto upper = plus_exprt{
3501+
src.index(),
3502+
from_integer(expr_width_opt.value() - 1, src.index().type())};
3503+
dest += convert_with_precedence(upper, precedence);
3504+
}
3505+
else
3506+
dest += "?";
34983507
dest+=", ";
3499-
dest += convert_with_precedence(src.lower(), precedence);
3508+
dest += convert_with_precedence(src.index(), precedence);
35003509
dest+=']';
35013510

35023511
return dest;

src/ansi-c/goto_check_c.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -973,7 +973,6 @@ void goto_check_ct::integer_overflow_check(
973973

974974
const exprt top_bits = extractbits_exprt(
975975
op_ext_shifted,
976-
new_type.get_width() - 1,
977976
new_type.get_width() - number_of_top_bits,
978977
unsignedbv_typet(number_of_top_bits));
979978

src/cpp/expr2cpp.cpp

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ class expr2cppt:public expr2ct
3333
std::string convert_cpp_this();
3434
std::string convert_cpp_new(const exprt &src);
3535
std::string convert_extractbit(const exprt &src);
36-
std::string convert_extractbits(const exprt &src);
3736
std::string convert_code_cpp_delete(const exprt &src, unsigned indent);
3837
std::string convert_code_cpp_new(const exprt &src, unsigned indent);
3938
std::string convert_struct(const exprt &src, unsigned &precedence) override;
@@ -433,11 +432,6 @@ std::string expr2cppt::convert_with_precedence(
433432
precedence = 15;
434433
return convert_extractbit(src);
435434
}
436-
else if(src.id()==ID_extractbits)
437-
{
438-
precedence = 15;
439-
return convert_extractbits(src);
440-
}
441435
else if(src.id()==ID_side_effect &&
442436
(src.get(ID_statement)==ID_cpp_new ||
443437
src.get(ID_statement)==ID_cpp_new_array))
@@ -489,14 +483,6 @@ std::string expr2cppt::convert_extractbit(const exprt &src)
489483
"]";
490484
}
491485

492-
std::string expr2cppt::convert_extractbits(const exprt &src)
493-
{
494-
const auto &extractbits_expr = to_extractbits_expr(src);
495-
return convert(extractbits_expr.src()) + ".range(" +
496-
convert(extractbits_expr.upper()) + "," +
497-
convert(extractbits_expr.lower()) + ")";
498-
}
499-
500486
std::string expr2cpp(const exprt &expr, const namespacet &ns)
501487
{
502488
expr2cppt expr2cpp(ns);

src/solvers/flattening/boolbv_extractbits.cpp

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,43 +17,28 @@ bvt boolbvt::convert_extractbits(const extractbits_exprt &expr)
1717

1818
auto const &src_bv = convert_bv(expr.src());
1919

20-
auto const maybe_upper_as_int = numeric_cast<mp_integer>(expr.upper());
21-
auto const maybe_lower_as_int = numeric_cast<mp_integer>(expr.lower());
20+
auto const maybe_index_as_int = numeric_cast<mp_integer>(expr.index());
2221

2322
// We only do constants for now.
2423
// Should implement a shift here.
25-
if(!maybe_upper_as_int.has_value() || !maybe_lower_as_int.has_value())
24+
if(!maybe_index_as_int.has_value())
2625
return conversion_failed(expr);
2726

28-
auto upper_as_int = maybe_upper_as_int.value();
29-
auto lower_as_int = maybe_lower_as_int.value();
27+
auto index_as_int = maybe_index_as_int.value();
3028

3129
DATA_INVARIANT_WITH_DIAGNOSTICS(
32-
upper_as_int >= 0 && upper_as_int < src_bv.size(),
33-
"upper end of extracted bits must be within the bitvector",
30+
index_as_int >= 0 && index_as_int < src_bv.size(),
31+
"index of extractbits must be within the bitvector",
3432
expr.find_source_location(),
3533
irep_pretty_diagnosticst{expr});
3634

3735
DATA_INVARIANT_WITH_DIAGNOSTICS(
38-
lower_as_int >= 0 && lower_as_int < src_bv.size(),
39-
"lower end of extracted bits must be within the bitvector",
36+
index_as_int + bv_width - 1 < src_bv.size(),
37+
"index+width-1 of extractbits must be within the bitvector",
4038
expr.find_source_location(),
4139
irep_pretty_diagnosticst{expr});
4240

43-
DATA_INVARIANT(
44-
lower_as_int <= upper_as_int,
45-
"upper bound must be greater or equal to lower bound");
46-
47-
// now lower_as_int <= upper_as_int
48-
49-
DATA_INVARIANT_WITH_DIAGNOSTICS(
50-
(upper_as_int - lower_as_int + 1) == bv_width,
51-
"the difference between upper and lower end of the range must have the "
52-
"same width as the resulting bitvector type",
53-
expr.find_source_location(),
54-
irep_pretty_diagnosticst{expr});
55-
56-
const std::size_t offset = numeric_cast_v<std::size_t>(lower_as_int);
41+
const std::size_t offset = numeric_cast_v<std::size_t>(index_as_int);
5742

5843
bvt result_bv(src_bv.begin() + offset, src_bv.begin() + offset + bv_width);
5944

src/solvers/floatbv/float_bv.cpp

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,7 @@ exprt float_bvt::convert(const exprt &expr) const
9292
return nil_exprt{};
9393
}
9494

95-
return extractbits_exprt{
96-
to_typecast_expr(expr).op(), dest_type.get_width() - 1, 0, dest_type};
95+
return extractbits_exprt{to_typecast_expr(expr).op(), 0, dest_type};
9796
}
9897
else if(expr.id()==ID_floatbv_plus)
9998
{
@@ -669,12 +668,11 @@ exprt float_bvt::limit_distance(
669668
return dist;
670669

671670
const extractbits_exprt upper_bits(
672-
dist, dist_width - 1, nb_bits, unsignedbv_typet(dist_width - nb_bits));
671+
dist, nb_bits, unsignedbv_typet(dist_width - nb_bits));
673672
const equal_exprt upper_bits_zero(
674673
upper_bits, from_integer(0, upper_bits.type()));
675674

676-
const extractbits_exprt lower_bits(
677-
dist, nb_bits - 1, 0, unsignedbv_typet(nb_bits));
675+
const extractbits_exprt lower_bits(dist, 0, unsignedbv_typet(nb_bits));
678676

679677
return if_exprt(
680678
upper_bits_zero,
@@ -924,19 +922,15 @@ exprt float_bvt::get_exponent(
924922
const exprt &src,
925923
const ieee_float_spect &spec)
926924
{
927-
return extractbits_exprt(
928-
src, spec.f+spec.e-1, spec.f,
929-
unsignedbv_typet(spec.e));
925+
return extractbits_exprt(src, spec.f, unsignedbv_typet(spec.e));
930926
}
931927

932928
/// Gets the fraction without hidden bit in a floating-point bit-vector src
933929
exprt float_bvt::get_fraction(
934930
const exprt &src,
935931
const ieee_float_spect &spec)
936932
{
937-
return extractbits_exprt(
938-
src, spec.f-1, 0,
939-
unsignedbv_typet(spec.f));
933+
return extractbits_exprt(src, 0, unsignedbv_typet(spec.f));
940934
}
941935

942936
exprt float_bvt::isnan(
@@ -975,10 +969,7 @@ void float_bvt::normalization_shift(
975969

976970
// check if first 'distance'-many bits are zeros
977971
const extractbits_exprt prefix(
978-
fraction,
979-
fraction_bits - 1,
980-
fraction_bits - distance,
981-
unsignedbv_typet(distance));
972+
fraction, fraction_bits - distance, unsignedbv_typet(distance));
982973
const equal_exprt prefix_is_zero(prefix, from_integer(0, prefix.type()));
983974

984975
// If so, shift the zeros out left by 'distance'.
@@ -1147,7 +1138,7 @@ exprt float_bvt::fraction_rounding_decision(
11471138
// We keep most-significant bits, and thus the tail is made
11481139
// of least-significant bits.
11491140
const extractbits_exprt tail(
1150-
fraction, extra_bits - 2, 0, unsignedbv_typet(extra_bits - 2 + 1));
1141+
fraction, 0, unsignedbv_typet(extra_bits - 2 + 1));
11511142
sticky_bit=notequal_exprt(tail, from_integer(0, tail.type()));
11521143
}
11531144

@@ -1216,9 +1207,8 @@ void float_bvt::round_fraction(
12161207
fraction_size, result.sign, result.fraction, rounding_mode_bits);
12171208

12181209
// chop off all the extra bits
1219-
result.fraction=extractbits_exprt(
1220-
result.fraction, result_fraction_size-1, extra_bits,
1221-
unsignedbv_typet(fraction_size));
1210+
result.fraction = extractbits_exprt(
1211+
result.fraction, extra_bits, unsignedbv_typet(fraction_size));
12221212

12231213
#if 0
12241214
// *** does not catch when the overflow goes subnormal -> normal ***
@@ -1306,8 +1296,8 @@ void float_bvt::round_exponent(
13061296
else // exponent gets smaller -- chop off top bits
13071297
{
13081298
exprt old_exponent=result.exponent;
1309-
result.exponent=
1310-
extractbits_exprt(result.exponent, spec.e-1, 0, signedbv_typet(spec.e));
1299+
result.exponent =
1300+
extractbits_exprt(result.exponent, 0, signedbv_typet(spec.e));
13111301

13121302
// max_exponent is the maximum representable
13131303
// i.e. 1 higher than the maximum possible for a normal number
@@ -1374,10 +1364,8 @@ float_bvt::biased_floatt float_bvt::bias(
13741364
const extractbit_exprt hidden_bit(src.fraction, spec.f);
13751365
const not_exprt denormal(hidden_bit);
13761366

1377-
result.fraction=
1378-
extractbits_exprt(
1379-
src.fraction, spec.f-1, 0,
1380-
unsignedbv_typet(spec.f));
1367+
result.fraction =
1368+
extractbits_exprt(src.fraction, 0, unsignedbv_typet(spec.f));
13811369

13821370
// make exponent zero if its denormal
13831371
// (includes zero)
@@ -1490,7 +1478,7 @@ exprt float_bvt::sticky_right_shift(
14901478
exprt lost_bits;
14911479

14921480
if(d<=width)
1493-
lost_bits=extractbits_exprt(result, d-1, 0, unsignedbv_typet(d));
1481+
lost_bits = extractbits_exprt(result, 0, unsignedbv_typet(d));
14941482
else
14951483
lost_bits=result;
14961484

src/solvers/smt2/smt2_conv.cpp

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1831,22 +1831,14 @@ void smt2_convt::convert_expr(const exprt &expr)
18311831
else if(expr.id()==ID_extractbits)
18321832
{
18331833
const extractbits_exprt &extractbits_expr = to_extractbits_expr(expr);
1834+
auto width = boolbv_width(expr.type());
18341835

1835-
if(
1836-
extractbits_expr.upper().is_constant() &&
1837-
extractbits_expr.lower().is_constant())
1836+
if(extractbits_expr.index().is_constant())
18381837
{
1839-
mp_integer op1_i =
1840-
numeric_cast_v<mp_integer>(to_constant_expr(extractbits_expr.upper()));
1841-
mp_integer op2_i =
1842-
numeric_cast_v<mp_integer>(to_constant_expr(extractbits_expr.lower()));
1843-
1844-
if(op2_i>op1_i)
1845-
std::swap(op1_i, op2_i);
1846-
1847-
// now op1_i>=op2_i
1838+
mp_integer index_i =
1839+
numeric_cast_v<mp_integer>(to_constant_expr(extractbits_expr.index()));
18481840

1849-
out << "((_ extract " << op1_i << " " << op2_i << ") ";
1841+
out << "((_ extract " << (width + index_i - 1) << " " << index_i << ") ";
18501842
flatten2bv(extractbits_expr.src());
18511843
out << ")";
18521844
}

src/solvers/smt2/smt2_parser.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -638,15 +638,14 @@ exprt smt2_parsert::function_application()
638638
if(op.size()!=1)
639639
throw error("extract takes one operand");
640640

641-
auto upper_e=from_integer(upper, integer_typet());
642-
auto lower_e=from_integer(lower, integer_typet());
643-
644641
if(upper<lower)
645642
throw error("extract got bad indices");
646643

644+
auto lower_e = from_integer(lower, integer_typet());
645+
647646
unsignedbv_typet t(upper-lower+1);
648647

649-
return extractbits_exprt(op[0], upper_e, lower_e, t);
648+
return extractbits_exprt(op[0], lower_e, t);
650649
}
651650
else if(id=="rotate_left" ||
652651
id=="rotate_right" ||

src/solvers/smt2_incremental/convert_expr_to_smt.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,10 +1111,14 @@ static smt_termt convert_expr_to_smt(
11111111
const sub_expression_mapt &converted)
11121112
{
11131113
const smt_termt &from = converted.at(extract_bits.src());
1114-
const auto upper_value = numeric_cast<std::size_t>(extract_bits.upper());
1115-
const auto lower_value = numeric_cast<std::size_t>(extract_bits.lower());
1116-
if(upper_value && lower_value)
1117-
return smt_bit_vector_theoryt::extract(*upper_value, *lower_value)(from);
1114+
const auto bit_vector_sort =
1115+
convert_type_to_smt_sort(extract_bits.type()).cast<smt_bit_vector_sortt>();
1116+
INVARIANT(
1117+
bit_vector_sort, "Extract can only be applied to bit vector terms.");
1118+
const auto index_value = numeric_cast<std::size_t>(extract_bits.index());
1119+
if(index_value)
1120+
return smt_bit_vector_theoryt::extract(
1121+
*index_value + bit_vector_sort->bit_width() - 1, *index_value)(from);
11181122
UNIMPLEMENTED_FEATURE(
11191123
"Generation of SMT formula for extract bits expression: " +
11201124
extract_bits.pretty());

src/solvers/smt2_incremental/encoding/struct_encoding.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,6 @@ static std::size_t count_trailing_bit_width(
195195
exprt struct_encodingt::encode_member(const member_exprt &member_expr) const
196196
{
197197
const auto &type = ns.get().follow(member_expr.compound().type());
198-
const auto member_bits_width = (*boolbv_width)(member_expr.type());
199198
const auto offset_bits = [&]() -> std::size_t {
200199
if(can_cast_type<union_typet>(type))
201200
return 0;
@@ -204,10 +203,7 @@ exprt struct_encodingt::encode_member(const member_exprt &member_expr) const
204203
struct_type, member_expr.get_component_name(), *boolbv_width);
205204
}();
206205
return extractbits_exprt{
207-
member_expr.compound(),
208-
offset_bits + member_bits_width - 1,
209-
offset_bits,
210-
member_expr.type()};
206+
member_expr.compound(), offset_bits, member_expr.type()};
211207
}
212208

213209
exprt struct_encodingt::encode(exprt expr) const

src/solvers/strings/string_constraint_generator_float.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@ Author: Romain Brenguier, romain.brenguier@diffblue.com
2828
/// in octuple precision.
2929
exprt get_exponent(const exprt &src, const ieee_float_spect &spec)
3030
{
31-
const extractbits_exprt exp_bits(
32-
src, spec.f + spec.e - 1, spec.f, unsignedbv_typet(spec.e));
31+
const extractbits_exprt exp_bits(src, spec.f, unsignedbv_typet(spec.e));
3332

3433
// Exponent is in biased form (numbers from -128 to 127 are encoded with
3534
// integer from 0 to 255) we have to remove the bias.
@@ -44,7 +43,7 @@ exprt get_exponent(const exprt &src, const ieee_float_spect &spec)
4443
/// \return An unsigned value representing the fractional part.
4544
exprt get_fraction(const exprt &src, const ieee_float_spect &spec)
4645
{
47-
return extractbits_exprt(src, spec.f - 1, 0, unsignedbv_typet(spec.f));
46+
return extractbits_exprt(src, 0, unsignedbv_typet(spec.f));
4847
}
4948

5049
/// Gets the significand as a java integer, looking for the hidden bit.

0 commit comments

Comments
 (0)