Skip to content

Commit 8836523

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

File tree

1 file changed

+63
-62
lines changed

1 file changed

+63
-62
lines changed

src/solvers/lowering/byte_operators.cpp

Lines changed: 63 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -21,46 +21,44 @@ 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<constant_exprt> &offset_bytes,
25+
const optionalt<constant_exprt> &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<constant_exprt> &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<constant_exprt> &offset_bytes,
48+
const optionalt<constant_exprt> &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;
60+
if(src_size.has_value())
61+
num_elements = numeric_cast<mp_integer>(*src_size);
6462
if(element_bits > 0 && element_bits % 8 == 0)
6563
{
6664
mp_integer el_bytes = element_bits / 8;
@@ -69,17 +67,19 @@ static array_exprt unpack_array_vector(
6967
if(!num_elements)
7068
{
7169
// round up to nearest multiple of el_bytes
72-
max_elements = (*max_bytes_int + el_bytes - 1) / el_bytes;
70+
auto max_bytes_int = numeric_cast_v<mp_integer>(*max_bytes);
71+
num_elements = (max_bytes_int + el_bytes - 1) / el_bytes;
7372
}
7473

75-
if(auto offset_bytes_int = numeric_cast<mp_integer>(offset_bytes))
74+
if(offset_bytes.has_value())
7675
{
76+
auto offset_bytes_int = numeric_cast_v<mp_integer>(*offset_bytes);
7777
// compute offset as number of elements
78-
first_element = *offset_bytes_int / el_bytes;
78+
first_element = offset_bytes_int / el_bytes;
7979
// insert offset_bytes-many nil bytes into the output array
80-
*offset_bytes_int -= *offset_bytes_int % el_bytes;
80+
offset_bytes_int -= offset_bytes_int % el_bytes;
8181
byte_operands.resize(
82-
numeric_cast_v<std::size_t>(*offset_bytes_int),
82+
numeric_cast_v<std::size_t>(offset_bytes_int),
8383
from_integer(0, unsignedbv_typet(8)));
8484
}
8585
}
@@ -88,7 +88,7 @@ static array_exprt unpack_array_vector(
8888
// array/vector is unknown; if element_bits was usable above this will
8989
// have been turned into a number of elements already
9090
if(!num_elements)
91-
num_elements = *max_elements;
91+
num_elements = numeric_cast_v<mp_integer>(*max_bytes);
9292

9393
const exprt src_simp = simplify_expr(src, ns);
9494

@@ -111,7 +111,7 @@ static array_exprt unpack_array_vector(
111111
// recursively unpack each element until so that we eventually just have an
112112
// array of bytes left
113113
exprt sub =
114-
unpack_rec(element, little_endian, nil_exprt(), max_bytes, ns, true);
114+
unpack_rec(element, little_endian, nullopt, max_bytes, ns, true);
115115
byte_operands.insert(
116116
byte_operands.end(), sub.operands().begin(), sub.operands().end());
117117
}
@@ -125,22 +125,22 @@ static array_exprt unpack_array_vector(
125125
/// Rewrite an object into its individual bytes.
126126
/// \param src: object to unpack
127127
/// \param little_endian: true, iff assumed endianness is little-endian
128-
/// \param offset_bytes: if not nil, bytes prior to this offset will be filled
129-
/// with nil values
130-
/// \param max_bytes: if not nil, use as upper bound of the number of bytes to
128+
/// \param offset_bytes: if set, bytes prior to this offset will be filled with
129+
/// nil values
130+
/// \param max_bytes: if set, use as upper bound of the number of bytes to
131131
/// unpack
132132
/// \param ns: namespace for type lookups
133133
/// \param unpack_byte_array: if true, return unmodified \p src iff it is an
134134
// array of bytes
135135
/// \return array of bytes in the sequence found in memory
136-
/// \throws flatten_byte_extract_exceptiont Raised is unable to unpack the
136+
/// \throws flatten_byte_extract_exceptiont Raised if unable to unpack the
137137
/// object because of either non constant size, byte misalignment or
138138
/// non-constant component width.
139139
static exprt unpack_rec(
140140
const exprt &src,
141141
bool little_endian,
142-
const exprt &offset_bytes,
143-
const exprt &max_bytes,
142+
const optionalt<constant_exprt> &offset_bytes,
143+
const optionalt<constant_exprt> &max_bytes,
144144
const namespacet &ns,
145145
bool unpack_byte_array)
146146
{
@@ -155,9 +155,11 @@ static exprt unpack_rec(
155155
if(!unpack_byte_array && *element_bits == 8)
156156
return src;
157157

158+
const auto constant_size_or_nullopt =
159+
expr_try_dynamic_cast<constant_exprt>(exprt(array_type.size()));
158160
return unpack_array_vector(
159161
src,
160-
array_type.size(),
162+
constant_size_or_nullopt,
161163
*element_bits,
162164
little_endian,
163165
offset_bytes,
@@ -204,28 +206,28 @@ static exprt unpack_rec(
204206
throw non_byte_alignedt(struct_type, comp, *component_bits);
205207
}
206208

207-
exprt offset_in_member = nil_exprt();
208-
auto offset_in_member_int = numeric_cast<mp_integer>(offset_bytes);
209-
exprt max_bytes_left = nil_exprt();
210-
auto max_bytes_left_int = numeric_cast<mp_integer>(max_bytes);
209+
optionalt<constant_exprt> offset_in_member;
210+
optionalt<constant_exprt> max_bytes_left;
211211

212-
if(offset_in_member_int.has_value())
212+
if(offset_bytes.has_value())
213213
{
214-
*offset_in_member_int -= member_offset_bits / 8;
214+
auto offset_in_member_int = numeric_cast_v<mp_integer>(*offset_bytes);
215+
offset_in_member_int -= member_offset_bits / 8;
215216
// if the offset is negative, offset_in_member remains nil, which has
216217
// the same effect as setting it to zero
217-
if(*offset_in_member_int >= 0)
218+
if(offset_in_member_int >= 0)
218219
{
219220
offset_in_member =
220-
from_integer(*offset_in_member_int, offset_bytes.type());
221+
from_integer(offset_in_member_int, offset_bytes->type());
221222
}
222223
}
223224

224-
if(max_bytes_left_int.has_value())
225+
if(max_bytes.has_value())
225226
{
226-
*max_bytes_left_int -= member_offset_bits / 8;
227-
if(*max_bytes_left_int >= 0)
228-
max_bytes_left = from_integer(*max_bytes_left_int, max_bytes.type());
227+
auto max_bytes_left_int = numeric_cast_v<mp_integer>(*max_bytes);
228+
max_bytes_left_int -= member_offset_bits / 8;
229+
if(max_bytes_left_int >= 0)
230+
max_bytes_left = from_integer(max_bytes_left_int, max_bytes->type());
229231
else
230232
break;
231233
}
@@ -257,16 +259,10 @@ static exprt unpack_rec(
257259

258260
if(bits_opt.has_value())
259261
bits = *bits_opt;
262+
else if(max_bytes.has_value())
263+
bits = numeric_cast_v<mp_integer>(*max_bytes) * 8;
260264
else
261-
{
262-
bits_opt = numeric_cast<mp_integer>(max_bytes);
263-
if(!bits_opt.has_value())
264-
{
265-
throw non_constant_widtht(src, max_bytes);
266-
}
267-
else
268-
bits = *bits_opt * 8;
269-
}
265+
throw non_constant_widtht(src, nil_exprt());
270266

271267
exprt::operandst byte_operands;
272268
for(mp_integer i=0; i<bits; i+=8)
@@ -353,19 +349,24 @@ exprt lower_byte_extract(const byte_extract_exprt &src, const namespacet &ns)
353349
// determine an upper bound of the number of bytes we might need
354350
exprt upper_bound=size_of_expr(src.type(), ns);
355351
if(upper_bound.is_not_nil())
356-
upper_bound=
357-
simplify_expr(
358-
plus_exprt(
359-
upper_bound,
360-
typecast_exprt(src.offset(), upper_bound.type())),
361-
ns);
352+
upper_bound = simplify_expr(
353+
plus_exprt(
354+
upper_bound,
355+
typecast_exprt::conditional_cast(src.offset(), upper_bound.type())),
356+
ns);
362357

363-
exprt lb = src.offset();
364-
if(!lb.is_constant())
365-
lb.make_nil();
358+
const auto lower_bound_or_nullopt =
359+
expr_try_dynamic_cast<constant_exprt>(exprt(src.offset()));
360+
const auto upper_bound_or_nullopt =
361+
expr_try_dynamic_cast<constant_exprt>(std::move(upper_bound));
366362

367363
byte_extract_exprt unpacked(src);
368-
unpacked.op() = unpack_rec(src.op(), little_endian, lb, upper_bound, ns);
364+
unpacked.op() = unpack_rec(
365+
src.op(),
366+
little_endian,
367+
lower_bound_or_nullopt,
368+
upper_bound_or_nullopt,
369+
ns);
369370

370371
if(src.type().id()==ID_array)
371372
{

0 commit comments

Comments
 (0)