11
11
#include < util/std_expr.h>
12
12
#include < util/arith_tools.h>
13
13
#include < util/pointer_offset_size.h>
14
+ #include < util/byte_operators.h>
15
+ #include < util/namespace.h>
14
16
15
17
#include " flatten_byte_operators.h"
16
18
@@ -28,11 +30,9 @@ Function: flatten_byte_extract
28
30
\*******************************************************************/
29
31
30
32
exprt flatten_byte_extract (
31
- const exprt &src,
33
+ const byte_extract_exprt &src,
32
34
const namespacet &ns)
33
35
{
34
- assert (src.id ()==ID_byte_extract_little_endian ||
35
- src.id ()==ID_byte_extract_big_endian);
36
36
assert (src.operands ().size ()==2 );
37
37
38
38
bool little_endian;
@@ -47,39 +47,45 @@ exprt flatten_byte_extract(
47
47
mp_integer size_bits=pointer_offset_bits (src.type (), ns);
48
48
if (size_bits<0 )
49
49
throw " byte_extract flatting with non-constant size: " +src.pretty ();
50
- std::size_t width_bits=integer2unsigned (size_bits);
51
-
52
- std::size_t width_bytes=width_bits/8 +(width_bits%8 ==0 ?0 :1 );
53
-
54
- const typet &t=src.op0 ().type ();
55
50
56
- if (t .id ()==ID_array)
51
+ if (src. op0 (). type () .id ()==ID_array)
57
52
{
58
- const array_typet &array_type=to_array_type (t);
53
+ const exprt &root=src.op0 ();
54
+ const exprt &offset=src.op1 ();
55
+
56
+ const array_typet &array_type=to_array_type (root.type ());
59
57
const typet &subtype=array_type.subtype ();
58
+
59
+ mp_integer element_width=pointer_offset_bits (subtype, ns);
60
+ if (element_width<0 ) // failed
61
+ throw " failed to flatten array with unknown element width" ;
62
+
63
+ mp_integer num_elements=
64
+ size_bits/element_width+((size_bits%element_width==0 )?0 :1 );
65
+
66
+ const typet &offset_type=ns.follow (offset.type ());
60
67
61
68
// byte-array?
62
- if ((subtype.id ()==ID_unsignedbv ||
63
- subtype.id ()==ID_signedbv) &&
64
- to_bitvector_type (subtype).get_width ()==8 )
69
+ if (element_width==8 )
65
70
{
66
71
// get 'width'-many bytes, and concatenate
72
+ std::size_t width_bytes=integer2unsigned (num_elements);
67
73
exprt::operandst op;
68
- op.resize (width_bytes);
74
+ op.reserve (width_bytes);
69
75
70
76
for (std::size_t i=0 ; i<width_bytes; i++)
71
77
{
72
78
// the most significant byte comes first in the concatenation!
73
- std::size_t offset_i =
79
+ std::size_t offset_int =
74
80
little_endian?(width_bytes-i-1 ):i;
75
81
76
- plus_exprt offset (from_integer (offset_i, src.op1 ().type ()), src.op1 ());
77
- index_exprt index_expr (subtype);
78
- index_expr.array ()=src.op0 ();
79
- index_expr.index ()=offset;
80
- op[i]=index_expr;
82
+ plus_exprt offset_i (from_integer (offset_int, offset_type), offset);
83
+ index_exprt index_expr (root, offset_i);
84
+ op.push_back (index_expr);
81
85
}
82
86
87
+ // TODO this doesn't seem correct if size_bits%8!=0 as more
88
+ // bits than the original expression will be returned.
83
89
if (width_bytes==1 )
84
90
return op[0 ];
85
91
else // width_bytes>=2
@@ -91,44 +97,36 @@ exprt flatten_byte_extract(
91
97
}
92
98
else // non-byte array
93
99
{
94
- const exprt &root=src.op0 ();
95
- const exprt &offset=src.op1 ();
96
- const typet &array_type=ns.follow (root.type ());
97
- const typet &offset_type=ns.follow (offset.type ());
98
- const typet &element_type=ns.follow (array_type.subtype ());
99
- mp_integer element_width=pointer_offset_size (element_type, ns);
100
-
101
- if (element_width==-1 ) // failed
102
- throw " failed to flatten non-byte array with unknown element width" ;
103
-
104
- mp_integer result_width=pointer_offset_size (src.type (), ns);
105
- mp_integer num_elements=(element_width+result_width-2 )/element_width+1 ;
100
+ // add an extra element as the access need not be aligned with
101
+ // element boundaries and could thus stretch over extra elements
102
+ ++num_elements;
106
103
107
104
// compute new root and offset
108
105
concatenation_exprt concat (
109
- unsignedbv_typet (integer2unsigned (element_width*8 * num_elements)));
106
+ unsignedbv_typet (integer2unsigned (element_width*num_elements)));
110
107
108
+ assert (element_width%8 ==0 );
111
109
exprt first_index=
112
- (element_width==1 )?offset
113
- : div_exprt (offset, from_integer (element_width, offset_type)); // 8*offset/el_w
110
+ div_exprt (offset, from_integer (element_width/8 , offset_type));
114
111
115
- for (mp_integer i=num_elements; i>0 ; --i)
112
+ // byte extract will do the appropriate mapping, thus MSB comes
113
+ // last here (as opposed to the above, where no further byte
114
+ // extract is involved)
115
+ for (mp_integer i=0 ; i<num_elements; ++i)
116
116
{
117
- plus_exprt index (first_index, from_integer (i-1 , offset_type));
117
+ // the most significant byte comes first in the concatenation!
118
+ plus_exprt index (first_index, from_integer (i, offset_type));
118
119
concat.copy_to_operands (index_exprt (root, index));
119
120
}
120
121
121
- // the new offset is width%offset
122
- exprt new_offset;
123
-
124
- if (element_width==1 )
125
- new_offset=from_integer (0 , offset_type);
126
- else
127
- new_offset=mod_exprt (offset, from_integer (element_width, offset_type));
122
+ // the new offset is offset%width
123
+ mod_exprt new_offset (offset,
124
+ from_integer (element_width/8 , offset_type));
128
125
129
126
// build new byte-extract expression
130
- exprt tmp (src.id (), src.type ());
131
- tmp.copy_to_operands (concat, new_offset);
127
+ byte_extract_exprt tmp (src);
128
+ tmp.op ()=concat;
129
+ tmp.offset ()=new_offset;
132
130
133
131
return tmp;
134
132
}
@@ -166,7 +164,7 @@ exprt flatten_byte_extract(
166
164
167
165
extractbits.src ()=left_shift;
168
166
extractbits.type ()=src.type ();
169
- extractbits.upper ()=from_integer (width_bits -1 , offset_type);
167
+ extractbits.upper ()=from_integer (size_bits -1 , offset_type);
170
168
extractbits.lower ()=from_integer (0 , offset_type);
171
169
172
170
return extractbits;
@@ -186,11 +184,9 @@ Function: flatten_byte_update
186
184
\*******************************************************************/
187
185
188
186
exprt flatten_byte_update (
189
- const exprt &src,
187
+ const byte_update_exprt &src,
190
188
const namespacet &ns)
191
189
{
192
- assert (src.id ()==ID_byte_update_little_endian ||
193
- src.id ()==ID_byte_update_big_endian);
194
190
assert (src.operands ().size ()==3 );
195
191
196
192
mp_integer element_size=
@@ -233,7 +229,7 @@ exprt flatten_byte_update(
233
229
}
234
230
else
235
231
{
236
- exprt byte_extract_expr (
232
+ byte_extract_exprt byte_extract_expr (
237
233
src.id ()==ID_byte_update_little_endian?ID_byte_extract_little_endian:
238
234
src.id ()==ID_byte_update_big_endian?ID_byte_extract_big_endian:
239
235
throw " unexpected src.id() in flatten_byte_update" ,
@@ -265,7 +261,7 @@ exprt flatten_byte_update(
265
261
266
262
index_exprt index_expr (src.op0 (), div_offset, array_type.subtype ());
267
263
268
- exprt byte_update_expr (src.id (), array_type.subtype ());
264
+ byte_update_exprt byte_update_expr (src.id (), array_type.subtype ());
269
265
byte_update_expr.copy_to_operands (index_expr, mod_offset, src.op2 ());
270
266
271
267
// Call recurisvely, the array is gone!
@@ -380,10 +376,10 @@ exprt flatten_byte_operators(const exprt &src, const namespacet &ns)
380
376
381
377
if (src.id ()==ID_byte_update_little_endian ||
382
378
src.id ()==ID_byte_update_big_endian)
383
- return flatten_byte_update (tmp, ns);
379
+ return flatten_byte_update (to_byte_update_expr ( tmp) , ns);
384
380
else if (src.id ()==ID_byte_extract_little_endian ||
385
381
src.id ()==ID_byte_extract_big_endian)
386
- return flatten_byte_extract (tmp, ns);
382
+ return flatten_byte_extract (to_byte_extract_expr ( tmp) , ns);
387
383
else
388
384
return tmp;
389
385
}
0 commit comments