@@ -19,6 +19,241 @@ Author: Daniel Kroening, kroening@kroening.com
1919
2020#include " flatten_byte_extract_exceptions.h"
2121
22+ static exprt bv_to_expr (
23+ const exprt &bitvector_expr,
24+ const typet &target_type,
25+ const namespacet &ns);
26+
27+ // / Convert a bitvector-typed expression \p bitvector_expr to a struct-typed
28+ // / expression. See \ref bv_to_expr for an overview.
29+ static struct_exprt bv_to_struct_expr (
30+ const exprt &bitvector_expr,
31+ const struct_typet &struct_type,
32+ const namespacet &ns)
33+ {
34+ const struct_typet::componentst &components = struct_type.components ();
35+
36+ exprt::operandst operands;
37+ operands.reserve (components.size ());
38+ std::size_t member_offset_bits = 0 ;
39+ for (const auto &comp : components)
40+ {
41+ const auto component_bits_opt = pointer_offset_bits (comp.type (), ns);
42+ std::size_t component_bits;
43+ if (component_bits_opt.has_value ())
44+ component_bits = numeric_cast_v<std::size_t >(*component_bits_opt);
45+ else
46+ component_bits = to_bitvector_type (bitvector_expr.type ()).get_width () -
47+ member_offset_bits;
48+
49+ if (component_bits == 0 )
50+ {
51+ operands.push_back (constant_exprt{irep_idt{}, comp.type ()});
52+ continue ;
53+ }
54+
55+ bitvector_typet type{bitvector_expr.type ().id (), component_bits};
56+ operands.push_back (bv_to_expr (
57+ extractbits_exprt{bitvector_expr,
58+ member_offset_bits + component_bits - 1 ,
59+ member_offset_bits,
60+ std::move (type)},
61+ comp.type (),
62+ ns));
63+
64+ if (component_bits_opt.has_value ())
65+ member_offset_bits += component_bits;
66+ }
67+
68+ return struct_exprt{std::move (operands), struct_type};
69+ }
70+
71+ // / Convert a bitvector-typed expression \p bitvector_expr to an array-typed
72+ // / expression. See \ref bv_to_expr for an overview.
73+ static array_exprt bv_to_array_expr (
74+ const exprt &bitvector_expr,
75+ const array_typet &array_type,
76+ const namespacet &ns)
77+ {
78+ auto num_elements = numeric_cast<std::size_t >(array_type.size ());
79+ auto subtype_bits = pointer_offset_bits (array_type.subtype (), ns);
80+
81+ const std::size_t total_bits =
82+ to_bitvector_type (bitvector_expr.type ()).get_width ();
83+ if (!num_elements.has_value ())
84+ {
85+ if (!subtype_bits.has_value () || *subtype_bits == 0 )
86+ num_elements = total_bits;
87+ else
88+ num_elements = total_bits / numeric_cast_v<std::size_t >(*subtype_bits);
89+ }
90+ DATA_INVARIANT (
91+ !num_elements.has_value () || !subtype_bits.has_value () ||
92+ *subtype_bits * *num_elements == total_bits,
93+ " subtype width times array size should be total bitvector width" );
94+
95+ exprt::operandst operands;
96+ operands.reserve (*num_elements);
97+ for (std::size_t i = 0 ; i < *num_elements; ++i)
98+ {
99+ if (subtype_bits.has_value ())
100+ {
101+ const std::size_t subtype_bits_int =
102+ numeric_cast_v<std::size_t >(*subtype_bits);
103+ bitvector_typet type{bitvector_expr.type ().id (), subtype_bits_int};
104+ operands.push_back (bv_to_expr (
105+ extractbits_exprt{bitvector_expr,
106+ ((i + 1 ) * subtype_bits_int) - 1 ,
107+ i * subtype_bits_int,
108+ std::move (type)},
109+ array_type.subtype (),
110+ ns));
111+ }
112+ else
113+ {
114+ operands.push_back (bv_to_expr (bitvector_expr, array_type.subtype (), ns));
115+ }
116+ }
117+
118+ return array_exprt{std::move (operands), array_type};
119+ }
120+
121+ // / Convert a bitvector-typed expression \p bitvector_expr to a vector-typed
122+ // / expression. See \ref bv_to_expr for an overview.
123+ static vector_exprt bv_to_vector_expr (
124+ const exprt &bitvector_expr,
125+ const vector_typet &vector_type,
126+ const namespacet &ns)
127+ {
128+ const std::size_t num_elements =
129+ numeric_cast_v<std::size_t >(vector_type.size ());
130+ auto subtype_bits = pointer_offset_bits (vector_type.subtype (), ns);
131+ DATA_INVARIANT (
132+ !subtype_bits.has_value () ||
133+ *subtype_bits * num_elements ==
134+ to_bitvector_type (bitvector_expr.type ()).get_width (),
135+ " subtype width times vector size should be total bitvector width" );
136+
137+ exprt::operandst operands;
138+ operands.reserve (num_elements);
139+ for (std::size_t i = 0 ; i < num_elements; ++i)
140+ {
141+ if (subtype_bits.has_value ())
142+ {
143+ const std::size_t subtype_bits_int =
144+ numeric_cast_v<std::size_t >(*subtype_bits);
145+ bitvector_typet type{bitvector_expr.type ().id (), subtype_bits_int};
146+ operands.push_back (bv_to_expr (
147+ extractbits_exprt{bitvector_expr,
148+ ((i + 1 ) * subtype_bits_int) - 1 ,
149+ i * subtype_bits_int,
150+ std::move (type)},
151+ vector_type.subtype (),
152+ ns));
153+ }
154+ else
155+ {
156+ operands.push_back (bv_to_expr (bitvector_expr, vector_type.subtype (), ns));
157+ }
158+ }
159+
160+ return vector_exprt{std::move (operands), vector_type};
161+ }
162+
163+ // / Convert a bitvector-typed expression \p bitvector_expr to a complex-typed
164+ // / expression. See \ref bv_to_expr for an overview.
165+ static complex_exprt bv_to_complex_expr (
166+ const exprt &bitvector_expr,
167+ const complex_typet &complex_type,
168+ const namespacet &ns)
169+ {
170+ const std::size_t total_bits =
171+ to_bitvector_type (bitvector_expr.type ()).get_width ();
172+ const auto subtype_bits_opt = pointer_offset_bits (complex_type.subtype (), ns);
173+ std::size_t subtype_bits;
174+ if (subtype_bits_opt.has_value ())
175+ {
176+ subtype_bits = numeric_cast_v<std::size_t >(*subtype_bits_opt);
177+ DATA_INVARIANT (
178+ subtype_bits * 2 == total_bits,
179+ " subtype width should be half of the total bitvector width" );
180+ }
181+ else
182+ subtype_bits = total_bits / 2 ;
183+
184+ const bitvector_typet type{bitvector_expr.type ().id (), subtype_bits};
185+
186+ return complex_exprt{
187+ bv_to_expr (
188+ extractbits_exprt{bitvector_expr, subtype_bits - 1 , 0 , type},
189+ complex_type.subtype (),
190+ ns),
191+ bv_to_expr (
192+ extractbits_exprt{
193+ bitvector_expr, subtype_bits * 2 - 1 , subtype_bits, type},
194+ complex_type.subtype (),
195+ ns),
196+ complex_type};
197+ }
198+
199+ // / Convert a bitvector-typed expression \p bitvector_expr to an expression of
200+ // / type \p target_type. If \p target_type is a bitvector type this may be a
201+ // / no-op or a typecast. For composite types such as structs, the bitvectors
202+ // / corresponding to the individual members are extracted and then a compound
203+ // / expression is built from those extracted members. When the size of a
204+ // / component isn't constant we fall back to computing its size based on the
205+ // / width of \p bitvector_expr.
206+ // / \param bitvector_expr: Bitvector-typed expression to extract from.
207+ // / \param target_type: Type of the expression to build.
208+ // / \param ns: Namespace to resolve tag types.
209+ // / \return Expression of type \p target_type constructed from sequences of bits
210+ // / from \p bitvector_expr.
211+ static exprt bv_to_expr (
212+ const exprt &bitvector_expr,
213+ const typet &target_type,
214+ const namespacet &ns)
215+ {
216+ PRECONDITION (can_cast_type<bitvector_typet>(bitvector_expr.type ()));
217+
218+ if (
219+ can_cast_type<bitvector_typet>(target_type) ||
220+ target_type.id () == ID_c_enum || target_type.id () == ID_c_enum_tag ||
221+ target_type.id () == ID_string)
222+ {
223+ return simplify_expr (
224+ typecast_exprt::conditional_cast (bitvector_expr, target_type), ns);
225+ }
226+
227+ if (target_type.id () == ID_struct)
228+ {
229+ return bv_to_struct_expr (bitvector_expr, to_struct_type (target_type), ns);
230+ }
231+ else if (target_type.id () == ID_struct_tag)
232+ {
233+ struct_exprt result = bv_to_struct_expr (
234+ bitvector_expr, ns.follow_tag (to_struct_tag_type (target_type)), ns);
235+ result.type () = target_type;
236+ return std::move (result);
237+ }
238+ else if (target_type.id () == ID_array)
239+ {
240+ return bv_to_array_expr (bitvector_expr, to_array_type (target_type), ns);
241+ }
242+ else if (target_type.id () == ID_vector)
243+ {
244+ return bv_to_vector_expr (bitvector_expr, to_vector_type (target_type), ns);
245+ }
246+ else if (target_type.id () == ID_complex)
247+ {
248+ return bv_to_complex_expr (bitvector_expr, to_complex_type (target_type), ns);
249+ }
250+ else
251+ {
252+ PRECONDITION_WITH_DIAGNOSTICS (
253+ false , " bv_to_expr does not yet support " , target_type.id_string ());
254+ }
255+ }
256+
22257static exprt unpack_rec (
23258 const exprt &src,
24259 bool little_endian,
@@ -500,7 +735,7 @@ exprt lower_byte_extract(const byte_extract_exprt &src, const namespacet &ns)
500735
501736 plus_exprt new_offset (
502737 unpacked.offset (),
503- typecast_exprt (
738+ typecast_exprt::conditional_cast (
504739 member_offset_expr (struct_type, comp.get_name (), ns),
505740 unpacked.offset ().type ()));
506741
@@ -606,13 +841,16 @@ exprt lower_byte_extract(const byte_extract_exprt &src, const namespacet &ns)
606841 }
607842
608843 if (width_bytes==1 )
609- return simplify_expr (typecast_exprt (op.front (), src.type ()), ns);
844+ {
845+ return simplify_expr (
846+ typecast_exprt::conditional_cast (op.front (), src.type ()), ns);
847+ }
610848 else // width_bytes>=2
611849 {
612850 concatenation_exprt concatenation (
613851 std::move (op), bitvector_typet (subtype->id (), width_bytes * 8 ));
614- return simplify_expr (
615- typecast_exprt ( std::move ( concatenation) , src.type () ), ns);
852+
853+ return bv_to_expr ( concatenation, src.type (), ns);
616854 }
617855}
618856
0 commit comments