Skip to content

Commit 4f5b402

Browse files
authored
Merge pull request #8246 from diffblue/extractbits-width
simplify `extractbits_exprt` representation
2 parents 2da2c76 + 97cb8a3 commit 4f5b402

18 files changed

+120
-189
lines changed

src/ansi-c/expr2c.cpp

+11-2
Original file line numberDiff line numberDiff line change
@@ -3497,9 +3497,18 @@ expr2ct::convert_extractbits(const extractbits_exprt &src, unsigned precedence)
34973497
{
34983498
std::string dest = convert_with_precedence(src.src(), precedence);
34993499
dest+='[';
3500-
dest += convert_with_precedence(src.upper(), precedence);
3500+
auto expr_width_opt = pointer_offset_bits(src.type(), ns);
3501+
if(expr_width_opt.has_value())
3502+
{
3503+
auto upper = plus_exprt{
3504+
src.index(),
3505+
from_integer(expr_width_opt.value() - 1, src.index().type())};
3506+
dest += convert_with_precedence(upper, precedence);
3507+
}
3508+
else
3509+
dest += "?";
35013510
dest+=", ";
3502-
dest += convert_with_precedence(src.lower(), precedence);
3511+
dest += convert_with_precedence(src.index(), precedence);
35033512
dest+=']';
35043513

35053514
return dest;

src/ansi-c/goto_check_c.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -999,7 +999,6 @@ void goto_check_ct::integer_overflow_check(
999999

10001000
const exprt top_bits = extractbits_exprt(
10011001
op_ext_shifted,
1002-
new_type.get_width() - 1,
10031002
new_type.get_width() - number_of_top_bits,
10041003
unsignedbv_typet(number_of_top_bits));
10051004

src/cpp/expr2cpp.cpp

-14
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

+8-23
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

+14-26
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

+5-13
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

+3-4
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

+8-4
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

+1-5
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

+2-3
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.

src/util/bitvector_expr.cpp

+2-7
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,11 @@ extractbit_exprt::extractbit_exprt(exprt _src, const std::size_t _index)
3030

3131
extractbits_exprt::extractbits_exprt(
3232
exprt _src,
33-
const std::size_t _upper,
34-
const std::size_t _lower,
33+
const std::size_t _index,
3534
typet _type)
3635
: expr_protectedt(ID_extractbits, std::move(_type))
3736
{
38-
PRECONDITION(_upper >= _lower);
39-
add_to_operands(
40-
std::move(_src),
41-
from_integer(_upper, integer_typet()),
42-
from_integer(_lower, integer_typet()));
37+
add_to_operands(std::move(_src), from_integer(_index, integer_typet()));
4338
}
4439

4540
exprt update_bit_exprt::lower() const

0 commit comments

Comments
 (0)