Skip to content

Commit da2c2b3

Browse files
author
Enrico Steffinlongo
committed
Fix duplicate_per_byte when output is float
When the output of `duplicate_per_byte` is `float`, the init_value gets converted to `float` and not reinterpreted. This in combination with shift operation causes the return value to be different than the replication of init_value. This commit solves this issue by applying a reinterpret cast to float using byte_extract. Also this commit re-enables the shadow memory regression test that was failing due to duplicate_per_byte to a float value.
1 parent decd283 commit da2c2b3

File tree

2 files changed

+33
-6
lines changed

2 files changed

+33
-6
lines changed

regression/cbmc-shadow-memory/float1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
KNOWNBUG
1+
CORE
22
main.c
33

44
^EXIT=0$

src/util/expr_initializer.cpp

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Author: Daniel Kroening, [email protected]
1313

1414
#include "arith_tools.h"
1515
#include "bitvector_expr.h"
16+
#include "byte_operators.h"
1617
#include "c_types.h"
1718
#include "config.h"
1819
#include "magic.h"
@@ -344,6 +345,27 @@ optionalt<exprt> expr_initializer(
344345
return expr_initializert(ns)(type, source_location, init_byte_expr);
345346
}
346347

348+
/// Typecast the input to the output if this is a signed/unsigned bv.
349+
/// Perform a reinterpret cast using byte_extract otherwise.
350+
/// @param expr the expression to be casted if necessary.
351+
/// @param out_type the type to cast the expression to.
352+
/// @return the casted or reinterpreted expression.
353+
static exprt cast_or_reinterpret(const exprt &expr, const typet &out_type)
354+
{
355+
// Same type --> no cast
356+
if(expr.type() == out_type)
357+
{
358+
return expr;
359+
}
360+
if(
361+
can_cast_type<signedbv_typet>(out_type) ||
362+
can_cast_type<unsignedbv_typet>(out_type))
363+
{
364+
return typecast_exprt::conditional_cast(expr, out_type);
365+
}
366+
return make_byte_extract(expr, from_integer(0, char_type()), out_type);
367+
}
368+
347369
/// Builds an expression of the given output type with each of its bytes
348370
/// initialized to the given initialization expression.
349371
/// Integer bitvector types are currently supported.
@@ -375,7 +397,7 @@ exprt duplicate_per_byte(const exprt &init_byte_expr, const typet &output_type)
375397
const auto init_size = init_type_as_bitvector->get_width();
376398
const irep_idt init_value = to_constant_expr(init_byte_expr).get_value();
377399

378-
// Create a new BV od `output_type` size with its representation being the
400+
// Create a new BV of `output_type` size with its representation being the
379401
// replication of the init_byte_expr (padded with 0) enough times to fill.
380402
const auto output_value =
381403
make_bvrep(out_width, [&init_size, &init_value](std::size_t index) {
@@ -400,6 +422,11 @@ exprt duplicate_per_byte(const exprt &init_byte_expr, const typet &output_type)
400422
{
401423
operation_type = unsignedbv_typet{ptr_type->get_width()};
402424
}
425+
if(
426+
const auto float_type = type_try_dynamic_cast<floatbv_typet>(output_type))
427+
{
428+
operation_type = unsignedbv_typet{float_type->get_width()};
429+
}
403430
// Let's cast init_byte_expr to output_type.
404431
const exprt casted_init_byte_expr =
405432
typecast_exprt::conditional_cast(init_byte_expr, operation_type);
@@ -410,10 +437,10 @@ exprt duplicate_per_byte(const exprt &init_byte_expr, const typet &output_type)
410437
casted_init_byte_expr,
411438
from_integer(config.ansi_c.char_width * i, size_type())));
412439
}
413-
if(values.size() == 1)
414-
return typecast_exprt::conditional_cast(values[0], output_type);
415-
return typecast_exprt::conditional_cast(
416-
multi_ary_exprt(ID_bitor, values, operation_type), output_type);
440+
return cast_or_reinterpret(
441+
values.size() == 1 ? values[0]
442+
: multi_ary_exprt(ID_bitor, values, operation_type),
443+
output_type);
417444
}
418445

419446
// Anything else. We don't know what to do with it. So, just cast.

0 commit comments

Comments
 (0)