Skip to content

Commit 2611c6d

Browse files
committed
Support extractbits with out-of-bounds limits
Byte extract already supports access beyond the bounds of the object being extracted from. Any bits outside bounds are free variables. extractbits now equally supports this case (via free variables).
1 parent b577ad2 commit 2611c6d

File tree

1 file changed

+33
-14
lines changed

1 file changed

+33
-14
lines changed

src/solvers/flattening/boolbv_extractbits.cpp

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,6 @@ bvt boolbvt::convert_extractbits(const extractbits_exprt &expr)
3131
auto upper_as_int = maybe_upper_as_int.value();
3232
auto lower_as_int = maybe_lower_as_int.value();
3333

34-
DATA_INVARIANT_WITH_DIAGNOSTICS(
35-
upper_as_int >= 0 && upper_as_int < src_bv.size(),
36-
"upper end of extracted bits must be within the bitvector",
37-
expr.find_source_location(),
38-
irep_pretty_diagnosticst{expr});
39-
40-
DATA_INVARIANT_WITH_DIAGNOSTICS(
41-
lower_as_int >= 0 && lower_as_int < src_bv.size(),
42-
"lower end of extracted bits must be within the bitvector",
43-
expr.find_source_location(),
44-
irep_pretty_diagnosticst{expr});
45-
4634
DATA_INVARIANT(
4735
lower_as_int <= upper_as_int,
4836
"upper bound must be greater or equal to lower bound");
@@ -56,9 +44,40 @@ bvt boolbvt::convert_extractbits(const extractbits_exprt &expr)
5644
expr.find_source_location(),
5745
irep_pretty_diagnosticst{expr});
5846

59-
const std::size_t offset = numeric_cast_v<std::size_t>(lower_as_int);
47+
bvt result_bv;
6048

61-
bvt result_bv(src_bv.begin() + offset, src_bv.begin() + offset + bv_width);
49+
// add out-of-bounds bits (if any) at the lower end
50+
if(lower_as_int < 0)
51+
{
52+
if(upper_as_int < 0)
53+
{
54+
lower_as_int -= upper_as_int + 1;
55+
upper_as_int = 0;
56+
}
57+
58+
const std::size_t lower_out_of_bounds =
59+
numeric_cast_v<std::size_t>(-lower_as_int);
60+
result_bv = prop.new_variables(lower_out_of_bounds);
61+
lower_as_int = 0;
62+
}
63+
64+
const std::size_t offset = numeric_cast_v<std::size_t>(lower_as_int);
65+
const std::size_t upper_size_t = numeric_cast_v<std::size_t>(upper_as_int);
66+
67+
result_bv.reserve(bv_width);
68+
result_bv.insert(
69+
result_bv.end(),
70+
src_bv.begin() + std::min(offset, src_bv.size()),
71+
src_bv.begin() + std::min(src_bv.size(), upper_size_t + 1));
72+
73+
// add out-of-bounds bits (if any) at the upper end
74+
if(upper_size_t >= src_bv.size())
75+
{
76+
bvt upper_oob_bits =
77+
prop.new_variables(upper_size_t - std::max(offset, src_bv.size()) + 1);
78+
result_bv.insert(
79+
result_bv.end(), upper_oob_bits.begin(), upper_oob_bits.end());
80+
}
6281

6382
return result_bv;
6483
}

0 commit comments

Comments
 (0)