12
12
#include " expr_initializer.h"
13
13
14
14
#include " arith_tools.h"
15
+ #include " bitvector_expr.h"
15
16
#include " c_types.h"
17
+ #include " config.h"
16
18
#include " magic.h"
17
19
#include " namespace.h" // IWYU pragma: keep
18
20
#include " std_code.h"
@@ -63,6 +65,8 @@ optionalt<exprt> expr_initializert::expr_initializer_rec(
63
65
result = side_effect_expr_nondett (type, source_location);
64
66
else if (init_expr.is_zero ())
65
67
result = from_integer (0 , type);
68
+ else
69
+ result = duplicate_per_byte (init_expr, type);
66
70
67
71
result.add_source_location ()=source_location;
68
72
return result;
@@ -75,6 +79,8 @@ optionalt<exprt> expr_initializert::expr_initializer_rec(
75
79
result = side_effect_expr_nondett (type, source_location);
76
80
else if (init_expr.is_zero ())
77
81
result = constant_exprt (ID_0, type);
82
+ else
83
+ result = duplicate_per_byte (init_expr, type);
78
84
79
85
result.add_source_location ()=source_location;
80
86
return result;
@@ -92,6 +98,8 @@ optionalt<exprt> expr_initializert::expr_initializer_rec(
92
98
93
99
result = constant_exprt (value, type);
94
100
}
101
+ else
102
+ result = duplicate_per_byte (init_expr, type);
95
103
96
104
result.add_source_location ()=source_location;
97
105
return result;
@@ -110,6 +118,8 @@ optionalt<exprt> expr_initializert::expr_initializer_rec(
110
118
111
119
result = complex_exprt (*sub_zero, *sub_zero, to_complex_type (type));
112
120
}
121
+ else
122
+ result = duplicate_per_byte (init_expr, type);
113
123
114
124
result.add_source_location ()=source_location;
115
125
return result;
@@ -276,6 +286,8 @@ optionalt<exprt> expr_initializert::expr_initializer_rec(
276
286
result = side_effect_expr_nondett (type, source_location);
277
287
else if (init_expr.is_zero ())
278
288
result = constant_exprt (irep_idt (), type);
289
+ else
290
+ result = duplicate_per_byte (init_expr, type);
279
291
280
292
result.add_source_location ()=source_location;
281
293
return result;
@@ -313,3 +325,67 @@ optionalt<exprt> nondet_initializer(
313
325
{
314
326
return expr_initializert (ns)(type, source_location, exprt (ID_nondet));
315
327
}
328
+
329
+ // / Create a value for type `type`, with all subtype bytes
330
+ // / initialized to the given value.
331
+ // / \param type: Type of the target expression.
332
+ // / \param source_location: Location to record in all created sub-expressions.
333
+ // / \param ns: Namespace to perform type symbol/tag lookups.
334
+ // / \param init_byte_expr: Value to be used for initialization.
335
+ // / \return An expression if a byte-initialized expression of the input type
336
+ // / can be built.
337
+ optionalt<exprt> expr_initializer (
338
+ const typet &type,
339
+ const source_locationt &source_location,
340
+ const namespacet &ns,
341
+ const exprt &init_byte_expr)
342
+ {
343
+ return expr_initializert (ns)(type, source_location, init_byte_expr);
344
+ }
345
+
346
+ // / Builds an expression of the given output type with each of its bytes
347
+ // / initialized to the given initialization expression.
348
+ // / Integer bitvector types are currently supported.
349
+ // / For unsupported types the initialization expression is casted to the
350
+ // / output type.
351
+ // / \param init_byte_expr The initialization expression
352
+ // / \param output_type The output type
353
+ // / \return The built expression
354
+ exprt duplicate_per_byte (const exprt &init_byte_expr, const typet &output_type)
355
+ {
356
+ if (output_type.id () == ID_unsignedbv || output_type.id () == ID_signedbv)
357
+ {
358
+ const size_t size =
359
+ to_bitvector_type (output_type).get_width () / config.ansi_c .char_width ;
360
+
361
+ // We've got a constant. So, precompute the value of the constant.
362
+ if (init_byte_expr.is_constant ())
363
+ {
364
+ const mp_integer value =
365
+ numeric_cast_v<mp_integer>(to_constant_expr (init_byte_expr));
366
+ mp_integer duplicated_value = value;
367
+ for (size_t i = 1 ; i < size; ++i)
368
+ {
369
+ duplicated_value =
370
+ bitwise_or (duplicated_value << config.ansi_c .char_width , value);
371
+ }
372
+ return from_integer (duplicated_value, output_type);
373
+ }
374
+
375
+ // We haven't got a constant. So, build the expression using shift-and-or.
376
+ exprt::operandst values;
377
+ values.push_back (init_byte_expr);
378
+ for (size_t i = 1 ; i < size; ++i)
379
+ {
380
+ values.push_back (shl_exprt (
381
+ init_byte_expr,
382
+ from_integer (config.ansi_c .char_width * i, size_type ())));
383
+ }
384
+ if (values.size () == 1 )
385
+ return values[0 ];
386
+ return multi_ary_exprt (ID_bitor, values, output_type);
387
+ }
388
+
389
+ // Anything else. We don't know what to do with it. So, just cast.
390
+ return typecast_exprt::conditional_cast (init_byte_expr, output_type);
391
+ }
0 commit comments