@@ -12,7 +12,9 @@ Author: Daniel Kroening, kroening@kroening.com
1212#include " expr_initializer.h"
1313
1414#include " arith_tools.h"
15+ #include " bitvector_expr.h"
1516#include " c_types.h"
17+ #include " config.h"
1618#include " magic.h"
1719#include " namespace.h" // IWYU pragma: keep
1820#include " std_code.h"
@@ -63,6 +65,8 @@ optionalt<exprt> expr_initializert::expr_initializer_rec(
6365 result = side_effect_expr_nondett (type, source_location);
6466 else if (init_expr.is_zero ())
6567 result = from_integer (0 , type);
68+ else
69+ result = duplicate_per_byte (init_expr, type);
6670
6771 result.add_source_location ()=source_location;
6872 return result;
@@ -75,6 +79,8 @@ optionalt<exprt> expr_initializert::expr_initializer_rec(
7579 result = side_effect_expr_nondett (type, source_location);
7680 else if (init_expr.is_zero ())
7781 result = constant_exprt (ID_0, type);
82+ else
83+ result = duplicate_per_byte (init_expr, type);
7884
7985 result.add_source_location ()=source_location;
8086 return result;
@@ -92,6 +98,8 @@ optionalt<exprt> expr_initializert::expr_initializer_rec(
9298
9399 result = constant_exprt (value, type);
94100 }
101+ else
102+ result = duplicate_per_byte (init_expr, type);
95103
96104 result.add_source_location ()=source_location;
97105 return result;
@@ -110,6 +118,8 @@ optionalt<exprt> expr_initializert::expr_initializer_rec(
110118
111119 result = complex_exprt (*sub_zero, *sub_zero, to_complex_type (type));
112120 }
121+ else
122+ result = duplicate_per_byte (init_expr, type);
113123
114124 result.add_source_location ()=source_location;
115125 return result;
@@ -276,6 +286,8 @@ optionalt<exprt> expr_initializert::expr_initializer_rec(
276286 result = side_effect_expr_nondett (type, source_location);
277287 else if (init_expr.is_zero ())
278288 result = constant_exprt (irep_idt (), type);
289+ else
290+ result = duplicate_per_byte (init_expr, type);
279291
280292 result.add_source_location ()=source_location;
281293 return result;
@@ -313,3 +325,67 @@ optionalt<exprt> nondet_initializer(
313325{
314326 return expr_initializert (ns)(type, source_location, exprt (ID_nondet));
315327}
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