1/*******************************************************************\
5Author: Daniel Kroening, kroening@kroening.com
7\*******************************************************************/
35 // see if the array size is constant
39 // use array decision procedure
48 // record type if array is a symbol
60 // make sure we have the index in the cache
70 // record type if array is a symbol
78 // make sure we have the index in the cache
85 // Must have a finite size
90 // see if the index address is constant
91 // many of these are compacted by simplify_expr
92 // but variable location writes will block this
100 // Special case : arrays of one thing (useful for constants)
101 // TODO : merge with ACTUAL_ARRAY_HACK so that ranges of the same
102 // value, bit-patterns with the same value, etc. are treated like
103 // this rather than as a series of individual options.
104 #define UNIFORM_ARRAY_HACK
105 #ifdef UNIFORM_ARRAY_HACK
114 [&array](
const exprt &expr) {
115 return expr == to_multi_ary_expr(array).op0();
123 const std::string identifier =
CPROVER_PREFIX "internal_uniform_array_" +
129 // return an unconstrained value in case of an empty array (the access is
130 // necessarily out-of-bounds)
145 // Simplify may remove the lower bound if the type
153 #define ACTUAL_ARRAY_HACK
154 #ifdef ACTUAL_ARRAY_HACK
155 // More useful when updates to concrete locations in
156 // actual arrays are compacted by simplify_expr
159 #ifdef CONSTANT_ARRAY_HACK
160 // TODO : Compile the whole array into a single relation
166 const std::string identifier =
CPROVER_PREFIX "internal_actual_array_" +
174#ifdef COMPACT_EQUAL_CONST
179 exprt::operandst::const_iterator it = array.
operands().begin();
185 "this loop iterates over the array, so `it` shouldn't be increased "
186 "past the array's end");
188 // Cache comparisons and equalities
200 // TODO : As with constant index, there is a trade-off
201 // of when it is best to flatten the whole array and
202 // when it is best to use the array theory and then use
203 // one or more of the above encoding strategies.
205 // get literals for the whole array
211 // TODO: maybe a shifter-like construction would be better
212 // Would be a lot more compact but propagate worse
221#ifdef COMPACT_EQUAL_CONST
232 for(std::size_t j=0; j<width; j++)
245#ifdef COMPACT_EQUAL_CONST
253 "non-positive array sizes are forbidden in goto programs");
262 for(std::size_t j=0; j<width; j++)
266 if(i==0)
// this initializes bv
289 // TODO: If the underlying array can use one of the
290 // improvements given above then it may be better to use
291 // the array theory for short chains of updates and then
292 // the improved array handling rather than full flattening.
293 // Note that the calculation is non-trivial as the cost of
294 // full flattening is amortised against all uses of
295 // the array (constant and variable indexes) and updated
307 // The assertion below is disabled as we want to be able
308 // to run CBMC without simplifier.
309 // Expression simplification should remove these cases
310 // assert(array.id()!=ID_array_of &&
311 // array.id()!=ID_array);
312 // If not there are large improvements possible as above
319 // out of bounds for the component, but not necessarily outside the bounds
320 // of the underlying object
349 // add offset to index
bool has_byte_operator(const exprt &src)
Return true iff src or one of its operands contain a byte extract or byte update expression.
byte_extract_exprt make_byte_extract(const exprt &_op, const exprt &_offset, const typet &_type)
Construct a byte_extract_exprt with endianness and byte width matching the current configuration.
Expression classes for byte-level operators.
const byte_extract_exprt & to_byte_extract_expr(const exprt &expr)
exprt lower_byte_operators(const exprt &src, const namespacet &ns)
Rewrite an expression possibly containing byte-extract or -update expressions to more fundamental ope...
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Boolean AND All operands must be boolean, and the result is always boolean.
void record_array_index(const index_exprt &expr)
A base class for relations, i.e., binary predicates whose two operands have the same type.
const bvt & get_literals(const irep_idt &identifier, const typet &type, std::size_t width)
virtual std::optional< std::size_t > get_width_opt(const typet &type) const
virtual bvt convert_index(const exprt &array, const mp_integer &index)
index operator with constant index
virtual const bvt & convert_bv(const exprt &expr, const std::optional< std::size_t > expected_width={})
Convert expression to vector of literalts, using an internal cache to speed up conversion if availabl...
bool is_unbounded_array(const typet &type) const override
bvt conversion_failed(const exprt &expr)
Print that the expression of x has failed conversion, then return a vector of x's width.
virtual std::size_t boolbv_width(const typet &type) const
Base class for all expressions.
bool has_operands() const
Return true if there is at least one operand.
bool is_constant() const
Return whether the expression is a constant.
typet & type()
Return the type of the expression.
const irep_idt & get(const irep_idt &name) const
const irep_idt & id() const
Split an expression into a base object and a (byte) offset.
void build(const exprt &expr, const namespacet &ns)
Given an expression expr, attempt to find the underlying object it represents by skipping over type c...
static const exprt & root_object(const exprt &expr)
The plus expression Associativity is not specified.
literalt convert(const exprt &expr) override
Convert a Boolean expression and return the corresponding literal.
void l_set_to_true(literalt a)
virtual literalt land(literalt a, literalt b)=0
virtual literalt limplies(literalt a, literalt b)=0
virtual literalt lselect(literalt a, literalt b, literalt c)=0
virtual bvt new_variables(std::size_t width)
generates a bitvector of given width with new variables
virtual literalt lequal(literalt a, literalt b)=0
virtual bool has_set_to() const
Expression to hold a symbol (variable)
The type of an expression, extends irept.
static exprt implication(exprt lhs, exprt rhs)
std::vector< literalt > bvt
API to expression classes for Pointers.
std::optional< mp_integer > pointer_offset_size(const typet &type, const namespacet &ns)
Compute the size of a type in bytes, rounding up to full bytes.
exprt simplify_expr(exprt src, const namespacet &ns)
#define CHECK_RETURN(CONDITION)
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
API to expression classes.
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
const multi_ary_exprt & to_multi_ary_expr(const exprt &expr)
Cast an exprt to a multi_ary_exprt.
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.