@@ -346,39 +346,63 @@ optionalt<exprt> expr_initializer(
346
346
// / Builds an expression of the given output type with each of its bytes
347
347
// / initialized to the given initialization expression.
348
348
// / Integer bitvector types are currently supported.
349
- // / For unsupported types the initialization expression is casted to the
349
+ // / For unsupported `output_type` the initialization expression is casted to the
350
350
// / output type.
351
351
// / \param init_byte_expr The initialization expression
352
352
// / \param output_type The output type
353
353
// / \return The built expression
354
+ // / \note `init_byte_expr` must be a boolean or a bitvector and must be of at
355
+ // / most `size <= config.ansi_c.char_width`
354
356
exprt duplicate_per_byte (const exprt &init_byte_expr, const typet &output_type)
355
357
{
356
- if (output_type.id () == ID_unsignedbv || output_type.id () == ID_signedbv)
358
+ const auto init_type_as_bitvector =
359
+ type_try_dynamic_cast<bitvector_typet>(init_byte_expr.type ());
360
+ // Fail if `init_byte_expr` is not a bitvector of maximum 8 bits or a boolean.
361
+ PRECONDITION (
362
+ (init_type_as_bitvector &&
363
+ init_type_as_bitvector->get_width () <= config.ansi_c .char_width ) ||
364
+ init_byte_expr.type ().id () == ID_bool);
365
+ if (const auto output_bv = type_try_dynamic_cast<bitvector_typet>(output_type))
357
366
{
358
- const size_t size =
359
- to_bitvector_type (output_type).get_width () / config.ansi_c .char_width ;
367
+ const auto out_width = output_bv->get_width ();
368
+ // Replicate `init_byte_expr` enough times until it completely fills
369
+ // `output_type`.
360
370
361
371
// We've got a constant. So, precompute the value of the constant.
362
372
if (init_byte_expr.is_constant ())
363
373
{
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);
374
+ const auto init_size = init_type_as_bitvector->get_width ();
375
+ const irep_idt init_value = to_constant_expr (init_byte_expr).get_value ();
376
+
377
+ // Create a new BV od `output_type` size with its representation being the
378
+ // replication of the init_byte_expr (padded with 0) enough times to fill.
379
+ const auto output_value = make_bvrep (
380
+ out_width,
381
+ [&init_size, &init_value](std::size_t index )
382
+ {
383
+ // Index modded by 8 to access the i-th bit of init_value
384
+ const auto source_index = index % config.ansi_c .char_width ;
385
+ // If the modded i-th bit exists get it, otherwise add 0 padding.
386
+ return source_index < init_size &&
387
+ get_bvrep_bit (init_value, init_size, source_index);
388
+ });
389
+
390
+ return constant_exprt{output_value, output_type};
373
391
}
374
392
393
+ const size_t size =
394
+ (out_width + config.ansi_c .char_width - 1 ) / config.ansi_c .char_width ;
395
+
375
396
// We haven't got a constant. So, build the expression using shift-and-or.
376
397
exprt::operandst values;
377
- values.push_back (init_byte_expr);
398
+ // Let's cast init_byte_expr to output_type.
399
+ const exprt casted_init_byte_expr =
400
+ typecast_exprt::conditional_cast (init_byte_expr, output_type);
401
+ values.push_back (casted_init_byte_expr);
378
402
for (size_t i = 1 ; i < size; ++i)
379
403
{
380
404
values.push_back (shl_exprt (
381
- init_byte_expr ,
405
+ casted_init_byte_expr ,
382
406
from_integer (config.ansi_c .char_width * i, size_type ())));
383
407
}
384
408
if (values.size () == 1 )
0 commit comments