Skip to content

Commit

Permalink
Extend expr_initializer to support byte-wise initialization
Browse files Browse the repository at this point in the history
Each byte of the expression is initialized to the given
initialization expression.

This building block will be required for the shadow
memory implementation.
  • Loading branch information
peterschrammel authored and esteffin committed Jul 6, 2023
1 parent cc3708c commit ac52ff6
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 0 deletions.
76 changes: 76 additions & 0 deletions src/util/expr_initializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ Author: Daniel Kroening, kroening@kroening.com
#include "expr_initializer.h"

#include "arith_tools.h"
#include "bitvector_expr.h"
#include "c_types.h"
#include "config.h"
#include "magic.h"
#include "namespace.h" // IWYU pragma: keep
#include "std_code.h"
Expand Down Expand Up @@ -63,6 +65,8 @@ optionalt<exprt> expr_initializert::expr_initializer_rec(
result = side_effect_expr_nondett(type, source_location);
else if(init_expr.is_zero())
result = from_integer(0, type);
else
result = duplicate_per_byte(init_expr, type);

Check warning on line 69 in src/util/expr_initializer.cpp

View check run for this annotation

Codecov / codecov/patch

src/util/expr_initializer.cpp#L69

Added line #L69 was not covered by tests

result.add_source_location()=source_location;
return result;
Expand All @@ -75,6 +79,8 @@ optionalt<exprt> expr_initializert::expr_initializer_rec(
result = side_effect_expr_nondett(type, source_location);
else if(init_expr.is_zero())

Check warning on line 80 in src/util/expr_initializer.cpp

View check run for this annotation

Codecov / codecov/patch

src/util/expr_initializer.cpp#L80

Added line #L80 was not covered by tests
result = constant_exprt(ID_0, type);
else
result = duplicate_per_byte(init_expr, type);

Check warning on line 83 in src/util/expr_initializer.cpp

View check run for this annotation

Codecov / codecov/patch

src/util/expr_initializer.cpp#L83

Added line #L83 was not covered by tests

result.add_source_location()=source_location;
return result;
Expand All @@ -92,6 +98,8 @@ optionalt<exprt> expr_initializert::expr_initializer_rec(

result = constant_exprt(value, type);
}
else
result = duplicate_per_byte(init_expr, type);

Check warning on line 102 in src/util/expr_initializer.cpp

View check run for this annotation

Codecov / codecov/patch

src/util/expr_initializer.cpp#L102

Added line #L102 was not covered by tests

result.add_source_location()=source_location;
return result;
Expand All @@ -110,6 +118,8 @@ optionalt<exprt> expr_initializert::expr_initializer_rec(

result = complex_exprt(*sub_zero, *sub_zero, to_complex_type(type));
}
else
result = duplicate_per_byte(init_expr, type);

Check warning on line 122 in src/util/expr_initializer.cpp

View check run for this annotation

Codecov / codecov/patch

src/util/expr_initializer.cpp#L122

Added line #L122 was not covered by tests

result.add_source_location()=source_location;
return result;
Expand Down Expand Up @@ -276,6 +286,8 @@ optionalt<exprt> expr_initializert::expr_initializer_rec(
result = side_effect_expr_nondett(type, source_location);
else if(init_expr.is_zero())
result = constant_exprt(irep_idt(), type);
else
result = duplicate_per_byte(init_expr, type);

Check warning on line 290 in src/util/expr_initializer.cpp

View check run for this annotation

Codecov / codecov/patch

src/util/expr_initializer.cpp#L290

Added line #L290 was not covered by tests

result.add_source_location()=source_location;
return result;
Expand Down Expand Up @@ -313,3 +325,67 @@ optionalt<exprt> nondet_initializer(
{
return expr_initializert(ns)(type, source_location, exprt(ID_nondet));
}

/// Create a value for type `type`, with all subtype bytes
/// initialized to the given value.
/// \param type: Type of the target expression.
/// \param source_location: Location to record in all created sub-expressions.
/// \param ns: Namespace to perform type symbol/tag lookups.
/// \param init_byte_expr: Value to be used for initialization.
/// \return An expression if a byte-initialized expression of the input type
/// can be built.
optionalt<exprt> expr_initializer(

Check warning on line 337 in src/util/expr_initializer.cpp

View check run for this annotation

Codecov / codecov/patch

src/util/expr_initializer.cpp#L337

Added line #L337 was not covered by tests
const typet &type,
const source_locationt &source_location,
const namespacet &ns,
const exprt &init_byte_expr)
{
return expr_initializert(ns)(type, source_location, init_byte_expr);

Check warning on line 343 in src/util/expr_initializer.cpp

View check run for this annotation

Codecov / codecov/patch

src/util/expr_initializer.cpp#L343

Added line #L343 was not covered by tests
}

/// Builds an expression of the given output type with each of its bytes
/// initialized to the given initialization expression.
/// Integer bitvector types are currently supported.
/// For unsupported types the initialization expression is casted to the
/// output type.
/// \param init_byte_expr The initialization expression
/// \param output_type The output type
/// \return The built expression
exprt duplicate_per_byte(const exprt &init_byte_expr, const typet &output_type)

Check warning on line 354 in src/util/expr_initializer.cpp

View check run for this annotation

Codecov / codecov/patch

src/util/expr_initializer.cpp#L354

Added line #L354 was not covered by tests
{
if(output_type.id() == ID_unsignedbv || output_type.id() == ID_signedbv)

Check warning on line 356 in src/util/expr_initializer.cpp

View check run for this annotation

Codecov / codecov/patch

src/util/expr_initializer.cpp#L356

Added line #L356 was not covered by tests
{
const size_t size =
to_bitvector_type(output_type).get_width() / config.ansi_c.char_width;

Check warning on line 359 in src/util/expr_initializer.cpp

View check run for this annotation

Codecov / codecov/patch

src/util/expr_initializer.cpp#L358-L359

Added lines #L358 - L359 were not covered by tests

// We've got a constant. So, precompute the value of the constant.
if(init_byte_expr.is_constant())

Check warning on line 362 in src/util/expr_initializer.cpp

View check run for this annotation

Codecov / codecov/patch

src/util/expr_initializer.cpp#L362

Added line #L362 was not covered by tests
{
const mp_integer value =
numeric_cast_v<mp_integer>(to_constant_expr(init_byte_expr));
mp_integer duplicated_value = value;
for(size_t i = 1; i < size; ++i)

Check warning on line 367 in src/util/expr_initializer.cpp

View check run for this annotation

Codecov / codecov/patch

src/util/expr_initializer.cpp#L364-L367

Added lines #L364 - L367 were not covered by tests
{
duplicated_value =
bitwise_or(duplicated_value << config.ansi_c.char_width, value);

Check warning on line 370 in src/util/expr_initializer.cpp

View check run for this annotation

Codecov / codecov/patch

src/util/expr_initializer.cpp#L369-L370

Added lines #L369 - L370 were not covered by tests
}
return from_integer(duplicated_value, output_type);

Check warning on line 372 in src/util/expr_initializer.cpp

View check run for this annotation

Codecov / codecov/patch

src/util/expr_initializer.cpp#L372

Added line #L372 was not covered by tests
}

// We haven't got a constant. So, build the expression using shift-and-or.
exprt::operandst values;
values.push_back(init_byte_expr);
for(size_t i = 1; i < size; ++i)

Check warning on line 378 in src/util/expr_initializer.cpp

View check run for this annotation

Codecov / codecov/patch

src/util/expr_initializer.cpp#L376-L378

Added lines #L376 - L378 were not covered by tests
{
values.push_back(shl_exprt(

Check warning on line 380 in src/util/expr_initializer.cpp

View check run for this annotation

Codecov / codecov/patch

src/util/expr_initializer.cpp#L380

Added line #L380 was not covered by tests
init_byte_expr,
from_integer(config.ansi_c.char_width * i, size_type())));

Check warning on line 382 in src/util/expr_initializer.cpp

View check run for this annotation

Codecov / codecov/patch

src/util/expr_initializer.cpp#L382

Added line #L382 was not covered by tests
}
if(values.size() == 1)
return values[0];
return multi_ary_exprt(ID_bitor, values, output_type);

Check warning on line 386 in src/util/expr_initializer.cpp

View check run for this annotation

Codecov / codecov/patch

src/util/expr_initializer.cpp#L384-L386

Added lines #L384 - L386 were not covered by tests
}

// Anything else. We don't know what to do with it. So, just cast.
return typecast_exprt::conditional_cast(init_byte_expr, output_type);

Check warning on line 390 in src/util/expr_initializer.cpp

View check run for this annotation

Codecov / codecov/patch

src/util/expr_initializer.cpp#L390

Added line #L390 was not covered by tests
}
8 changes: 8 additions & 0 deletions src/util/expr_initializer.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,12 @@ optionalt<exprt> nondet_initializer(
const source_locationt &source_location,
const namespacet &ns);

optionalt<exprt> expr_initializer(
const typet &type,
const source_locationt &source_location,
const namespacet &ns,
const exprt &init_byte_expr);

exprt duplicate_per_byte(const exprt &init_byte_expr, const typet &output_type);

#endif // CPROVER_UTIL_EXPR_INITIALIZER_H

0 comments on commit ac52ff6

Please sign in to comment.