@@ -346,17 +346,28 @@ 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 of bitvector type and must be of
355
+ // / `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.
361
+ PRECONDITION (
362
+ init_type_as_bitvector &&
363
+ init_type_as_bitvector->get_width () <= config.ansi_c .char_width );
364
+ if (const auto output_bv = type_try_dynamic_cast<bitvector_typet>(output_type))
357
365
{
366
+ const auto out_width = output_bv->get_width ();
367
+ // Replicate `init_byte_expr` enough times until it completely fills
368
+ // `output_type`.
358
369
const size_t size =
359
- to_bitvector_type (output_type). get_width ( ) / config.ansi_c .char_width ;
370
+ (out_width + config. ansi_c . char_width - 1 ) / config.ansi_c .char_width ;
360
371
361
372
// We've got a constant. So, precompute the value of the constant.
362
373
if (init_byte_expr.is_constant ())
@@ -374,11 +385,14 @@ exprt duplicate_per_byte(const exprt &init_byte_expr, const typet &output_type)
374
385
375
386
// We haven't got a constant. So, build the expression using shift-and-or.
376
387
exprt::operandst values;
377
- values.push_back (init_byte_expr);
388
+ // Let's cast init_byte_expr to output_type.
389
+ const exprt casted_init_byte_expr =
390
+ typecast_exprt::conditional_cast (init_byte_expr, output_type);
391
+ values.push_back (casted_init_byte_expr);
378
392
for (size_t i = 1 ; i < size; ++i)
379
393
{
380
394
values.push_back (shl_exprt (
381
- init_byte_expr ,
395
+ casted_init_byte_expr ,
382
396
from_integer (config.ansi_c .char_width * i, size_type ())));
383
397
}
384
398
if (values.size () == 1 )
0 commit comments