Skip to content

Commit ac52ff6

Browse files
peterschrammelEnrico Steffinlongo
authored and
Enrico Steffinlongo
committed
Extend expr_initializer to support byte-wise initialization
Each byte of the expression is initialized to the given initialization expression. This building block will be required for the shadow memory implementation.
1 parent cc3708c commit ac52ff6

File tree

2 files changed

+84
-0
lines changed

2 files changed

+84
-0
lines changed

src/util/expr_initializer.cpp

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ Author: Daniel Kroening, [email protected]
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+
}

src/util/expr_initializer.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,12 @@ optionalt<exprt> nondet_initializer(
2727
const source_locationt &source_location,
2828
const namespacet &ns);
2929

30+
optionalt<exprt> expr_initializer(
31+
const typet &type,
32+
const source_locationt &source_location,
33+
const namespacet &ns,
34+
const exprt &init_byte_expr);
35+
36+
exprt duplicate_per_byte(const exprt &init_byte_expr, const typet &output_type);
37+
3038
#endif // CPROVER_UTIL_EXPR_INITIALIZER_H

0 commit comments

Comments
 (0)