@@ -21,46 +21,44 @@ Author: Daniel Kroening, kroening@kroening.com
2121static 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
4142static 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.
139139static 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