Skip to content

Commit bd30790

Browse files
committed
byte_extract lowering: Use optionalt<mp_integer> instead of nil_exprt
This makes the interface much more explicit about what is or isn't supported at moment.
1 parent 445f38f commit bd30790

File tree

1 file changed

+56
-70
lines changed

1 file changed

+56
-70
lines changed

src/solvers/lowering/byte_operators.cpp

Lines changed: 56 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -21,64 +21,59 @@ Author: Daniel Kroening, [email protected]
2121
static exprt unpack_rec(
2222
const exprt &src,
2323
bool little_endian,
24-
const exprt &offset_bytes,
25-
const exprt &max_bytes,
24+
const optionalt<mp_integer> &offset_bytes,
25+
const optionalt<mp_integer> &max_bytes,
2626
const namespacet &ns,
2727
bool unpack_byte_array = false);
2828

2929
/// Rewrite an array or vector into its individual bytes.
3030
/// \param src: array/vector to unpack
31-
/// \param src_size: array/vector size; if not a constant, \p max_bytes must be
32-
/// a constant value, otherwise we fail with an exception
31+
/// \param src_size: array/vector size; if not a constant and thus not set,
32+
/// \p max_bytes must be a known constant value, otherwise we fail with an
33+
/// exception
3334
/// \param element_bits: bit width of array/vector elements
3435
/// \param little_endian: true, iff assumed endianness is little-endian
35-
/// \param offset_bytes: if not nil, bytes prior to this offset will be filled
36+
/// \param offset_bytes: if set, bytes prior to this offset will be filled
3637
/// with nil values
37-
/// \param max_bytes: if not nil, use as upper bound of the number of bytes to
38+
/// \param max_bytes: if set, use as upper bound of the number of bytes to
3839
/// unpack
3940
/// \param ns: namespace for type lookups
4041
/// \return array_exprt holding unpacked elements
4142
static array_exprt unpack_array_vector(
4243
const exprt &src,
43-
const exprt &src_size,
44+
const optionalt<mp_integer> &src_size,
4445
const mp_integer &element_bits,
4546
bool little_endian,
46-
const exprt &offset_bytes,
47-
const exprt &max_bytes,
47+
const optionalt<mp_integer> &offset_bytes,
48+
const optionalt<mp_integer> &max_bytes,
4849
const namespacet &ns)
4950
{
50-
auto max_bytes_int = numeric_cast<mp_integer>(max_bytes);
51-
auto num_elements = numeric_cast<mp_integer>(src_size);
52-
53-
if(!max_bytes_int && !num_elements)
54-
{
55-
throw non_const_array_sizet(src.type(), max_bytes);
56-
}
51+
if(!src_size.has_value() && !max_bytes.has_value())
52+
throw non_const_array_sizet(src.type(), nil_exprt());
5753

5854
exprt::operandst byte_operands;
5955
mp_integer first_element = 0;
6056

6157
// refine the number of elements to extract in case the element width is known
6258
// and a multiple of bytes; otherwise we will expand the entire array/vector
63-
optionalt<mp_integer> max_elements;
59+
optionalt<mp_integer> num_elements = src_size;
6460
if(element_bits > 0 && element_bits % 8 == 0)
6561
{
6662
mp_integer el_bytes = element_bits / 8;
6763

68-
if(!num_elements)
64+
if(!num_elements.has_value())
6965
{
7066
// turn bytes into elements, rounding up
71-
max_elements = (*max_bytes_int + el_bytes - 1) / el_bytes;
67+
num_elements = (*max_bytes + el_bytes - 1) / el_bytes;
7268
}
7369

74-
if(auto offset_bytes_int = numeric_cast<mp_integer>(offset_bytes))
70+
if(offset_bytes.has_value())
7571
{
7672
// compute offset as number of elements
77-
first_element = *offset_bytes_int / el_bytes;
73+
first_element = *offset_bytes / el_bytes;
7874
// insert offset_bytes-many nil bytes into the output array
79-
*offset_bytes_int -= *offset_bytes_int % el_bytes;
8075
byte_operands.resize(
81-
numeric_cast_v<std::size_t>(*offset_bytes_int),
76+
numeric_cast_v<std::size_t>(*offset_bytes - (*offset_bytes % el_bytes)),
8277
from_integer(0, unsignedbv_typet(8)));
8378
}
8479
}
@@ -87,7 +82,7 @@ static array_exprt unpack_array_vector(
8782
// array/vector is unknown; if element_bits was usable above this will
8883
// have been turned into a number of elements already
8984
if(!num_elements)
90-
num_elements = *max_elements;
85+
num_elements = *max_bytes;
9186

9287
const exprt src_simp = simplify_expr(src, ns);
9388

@@ -109,8 +104,7 @@ static array_exprt unpack_array_vector(
109104

110105
// recursively unpack each element until so that we eventually just have an
111106
// array of bytes left
112-
exprt sub =
113-
unpack_rec(element, little_endian, nil_exprt(), max_bytes, ns, true);
107+
exprt sub = unpack_rec(element, little_endian, {}, max_bytes, ns, true);
114108
byte_operands.insert(
115109
byte_operands.end(), sub.operands().begin(), sub.operands().end());
116110
}
@@ -124,22 +118,22 @@ static array_exprt unpack_array_vector(
124118
/// Rewrite an object into its individual bytes.
125119
/// \param src: object to unpack
126120
/// \param little_endian: true, iff assumed endianness is little-endian
127-
/// \param offset_bytes: if not nil, bytes prior to this offset will be filled
128-
/// with nil values
129-
/// \param max_bytes: if not nil, use as upper bound of the number of bytes to
121+
/// \param offset_bytes: if set, bytes prior to this offset will be filled with
122+
/// nil values
123+
/// \param max_bytes: if set, use as upper bound of the number of bytes to
130124
/// unpack
131125
/// \param ns: namespace for type lookups
132126
/// \param unpack_byte_array: if true, return unmodified \p src iff it is an
133127
// array of bytes
134128
/// \return array of bytes in the sequence found in memory
135-
/// \throws flatten_byte_extract_exceptiont Raised is unable to unpack the
129+
/// \throws flatten_byte_extract_exceptiont Raised if unable to unpack the
136130
/// object because of either non constant size, byte misalignment or
137131
/// non-constant component width.
138132
static exprt unpack_rec(
139133
const exprt &src,
140134
bool little_endian,
141-
const exprt &offset_bytes,
142-
const exprt &max_bytes,
135+
const optionalt<mp_integer> &offset_bytes,
136+
const optionalt<mp_integer> &max_bytes,
143137
const namespacet &ns,
144138
bool unpack_byte_array)
145139
{
@@ -154,9 +148,11 @@ static exprt unpack_rec(
154148
if(!unpack_byte_array && *element_bits == 8)
155149
return src;
156150

151+
const auto constant_size_or_nullopt =
152+
numeric_cast<mp_integer>(array_type.size());
157153
return unpack_array_vector(
158154
src,
159-
array_type.size(),
155+
constant_size_or_nullopt,
160156
*element_bits,
161157
little_endian,
162158
offset_bytes,
@@ -176,7 +172,7 @@ static exprt unpack_rec(
176172

177173
return unpack_array_vector(
178174
src,
179-
vector_type.size(),
175+
numeric_cast_v<mp_integer>(vector_type.size()),
180176
*element_bits,
181177
little_endian,
182178
offset_bytes,
@@ -203,29 +199,22 @@ static exprt unpack_rec(
203199
throw non_byte_alignedt(struct_type, comp, *component_bits);
204200
}
205201

206-
exprt offset_in_member = nil_exprt();
207-
auto offset_in_member_int = numeric_cast<mp_integer>(offset_bytes);
208-
exprt max_bytes_left = nil_exprt();
209-
auto max_bytes_left_int = numeric_cast<mp_integer>(max_bytes);
202+
optionalt<mp_integer> offset_in_member;
203+
optionalt<mp_integer> max_bytes_left;
210204

211-
if(offset_in_member_int.has_value())
205+
if(offset_bytes.has_value())
212206
{
213-
*offset_in_member_int -= member_offset_bits / 8;
214-
// if the offset is negative, offset_in_member remains nil, which has
207+
offset_in_member = *offset_bytes - member_offset_bits / 8;
208+
// if the offset is negative, offset_in_member remains unset, which has
215209
// the same effect as setting it to zero
216-
if(*offset_in_member_int >= 0)
217-
{
218-
offset_in_member =
219-
from_integer(*offset_in_member_int, offset_bytes.type());
220-
}
210+
if(*offset_in_member < 0)
211+
offset_in_member.reset();
221212
}
222213

223-
if(max_bytes_left_int.has_value())
214+
if(max_bytes.has_value())
224215
{
225-
*max_bytes_left_int -= member_offset_bits / 8;
226-
if(*max_bytes_left_int >= 0)
227-
max_bytes_left = from_integer(*max_bytes_left_int, max_bytes.type());
228-
else
216+
max_bytes_left = *max_bytes - member_offset_bits / 8;
217+
if(*max_bytes_left < 0)
229218
break;
230219
}
231220

@@ -256,16 +245,10 @@ static exprt unpack_rec(
256245

257246
if(bits_opt.has_value())
258247
bits = *bits_opt;
248+
else if(max_bytes.has_value())
249+
bits = *max_bytes * 8;
259250
else
260-
{
261-
bits_opt = numeric_cast<mp_integer>(max_bytes);
262-
if(!bits_opt.has_value())
263-
{
264-
throw non_constant_widtht(src, max_bytes);
265-
}
266-
else
267-
bits = *bits_opt * 8;
268-
}
251+
throw non_constant_widtht(src, nil_exprt());
269252

270253
exprt::operandst byte_operands;
271254
for(mp_integer i=0; i<bits; i+=8)
@@ -352,19 +335,22 @@ exprt lower_byte_extract(const byte_extract_exprt &src, const namespacet &ns)
352335
// determine an upper bound of the number of bytes we might need
353336
exprt upper_bound=size_of_expr(src.type(), ns);
354337
if(upper_bound.is_not_nil())
355-
upper_bound=
356-
simplify_expr(
357-
plus_exprt(
358-
upper_bound,
359-
typecast_exprt(src.offset(), upper_bound.type())),
360-
ns);
338+
upper_bound = simplify_expr(
339+
plus_exprt(
340+
upper_bound,
341+
typecast_exprt::conditional_cast(src.offset(), upper_bound.type())),
342+
ns);
361343

362-
exprt lb = src.offset();
363-
if(!lb.is_constant())
364-
lb.make_nil();
344+
const auto lower_bound_or_nullopt = numeric_cast<mp_integer>(src.offset());
345+
const auto upper_bound_or_nullopt = numeric_cast<mp_integer>(upper_bound);
365346

366347
byte_extract_exprt unpacked(src);
367-
unpacked.op() = unpack_rec(src.op(), little_endian, lb, upper_bound, ns);
348+
unpacked.op() = unpack_rec(
349+
src.op(),
350+
little_endian,
351+
lower_bound_or_nullopt,
352+
upper_bound_or_nullopt,
353+
ns);
368354

369355
if(src.type().id()==ID_array)
370356
{

0 commit comments

Comments
 (0)