Skip to content

Commit 73df636

Browse files
author
Enrico Steffinlongo
committed
Improved checks and fixed duplicate_per_byte
1 parent 32799c2 commit 73df636

File tree

1 file changed

+19
-5
lines changed

1 file changed

+19
-5
lines changed

src/util/expr_initializer.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -346,17 +346,28 @@ optionalt<exprt> expr_initializer(
346346
/// Builds an expression of the given output type with each of its bytes
347347
/// initialized to the given initialization expression.
348348
/// 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
350350
/// output type.
351351
/// \param init_byte_expr The initialization expression
352352
/// \param output_type The output type
353353
/// \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`
354356
exprt duplicate_per_byte(const exprt &init_byte_expr, const typet &output_type)
355357
{
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))
357365
{
366+
const auto out_width = output_bv->get_width();
367+
// Replicate `init_byte_expr` enough times until it completely fills
368+
// `output_type`.
358369
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;
360371

361372
// We've got a constant. So, precompute the value of the constant.
362373
if(init_byte_expr.is_constant())
@@ -374,11 +385,14 @@ exprt duplicate_per_byte(const exprt &init_byte_expr, const typet &output_type)
374385

375386
// We haven't got a constant. So, build the expression using shift-and-or.
376387
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);
378392
for(size_t i = 1; i < size; ++i)
379393
{
380394
values.push_back(shl_exprt(
381-
init_byte_expr,
395+
casted_init_byte_expr,
382396
from_integer(config.ansi_c.char_width * i, size_type())));
383397
}
384398
if(values.size() == 1)

0 commit comments

Comments
 (0)