1/*******************************************************************\
5Author: Daniel Kroening, kroening@kroening.com
7\*******************************************************************/
41 std::vector<mp_integer> bytes;
47 // put back together, but backwards
53 "bytes is not empty because we just pushed just as many elements on "
54 "top of it as we are popping now");
55 new_value+=bytes.back()<<
bit;
167 // check to see if it is a number type
171 // vector of operands
174 // result of the simplification
177 // position of the constant
178 exprt::operandst::iterator constant;
180 // true if we have found a constant
185 // scan all the operands
186 for(exprt::operandst::iterator it =
new_operands.begin();
189 // if one of the operands is not a number return
193 // if one of the operands is zero the result is zero
194 // note: not true on IEEE floating point arithmetic
200 // true if the given operand has to be erased
203 // if this is a constant of the same time as the result
204 if(it->is_constant() && it->type()==expr.
type())
206 // preserve the sizeof type annotation
217 // update the constant factor
223 // set it as the constant factor if this is the first
229 // erase the factor if necessary
236 it++;
// move to the next operand
243 "c_sizeof_type is only set to a non-nil value "
244 "if a constant has been found");
254 // if the constant is a one and there are other factors
272 return std::move(
tmp);
342 return std::move(
tmp);
386 return unchanged(expr);
// division by zero
415 // floating-point addition is _NOT_ associative; thus,
416 // there is special case for float
420 // we only merge neighboring constants!
423 const exprt::operandst::iterator next = std::next(it);
427 if(it->type()==next->type() &&
440 // ((T*)p+a)+b -> (T*)p+(a+b)
468 // count the constants
470 for(
const auto &op : expr.
operands())
472 if(
is_number(op.type()) && op.is_constant())
484 if(
is_number(it->type()) && it->is_constant())
504 // search for a and -a
505 // first gather all the a's with -a
506 typedef std::unordered_map<exprt, exprt::operandst::iterator, irep_hash>
524 expr_mapt::iterator
itm=expr_map.find(*it);
526 if(
itm!=expr_map.end())
536 // (can't do for floats, as the result of 0.0 + (-0.0)
537 // need not be -0.0 in std rounding)
538 for(exprt::operandst::iterator it =
new_operands.begin();
567 return std::move(
tmp);
584 // rewrite "a-b" to "a+(-b)"
593 // pointer arithmetic: rewrite "p-i" to "p+(-i)"
669 // check if these are really boolean
674 for(
const auto &op : expr.
operands())
679 else if(op == 0 || op == 1)
688 // re-write to boolean+typecast
722 // try to merge constants
726 while(
new_expr.operands().size() >= 2)
743 std::function<
bool(
bool,
bool)> f;
746 f = [](
bool a,
bool b) {
return a &&
b; };
748 f = [](
bool a,
bool b) {
return a ||
b; };
750 f = [](
bool a,
bool b) {
return a !=
b; };
752 f = [](
bool a,
bool b) {
return a ==
b; };
764 // erase first operand
771 // 'all zeros' in bitand yields zero
776 for(
const auto &op :
new_expr.operands())
783 // 'all ones' in bitor yields all-ones
790 for(
const auto &op :
new_expr.operands())
797 // now erase 'all zeros' out of bitor, bitxor
801 for(exprt::operandst::iterator it =
new_expr.operands().begin();
802 it !=
new_expr.operands().end();)
// no it++
804 if(*it == 0 &&
new_expr.operands().size() > 1)
810 it->is_constant() && it->type().id() ==
ID_bv &&
811 *it ==
to_bv_type(it->type()).all_zeros_expr() &&
822 // now erase 'all ones' out of bitand
827 for(exprt::operandst::iterator it =
new_expr.operands().begin();
828 it !=
new_expr.operands().end();)
// no it++
844 // two operands that are syntactically the same
905 // first, turn bool into bvec[1]
909 if(op ==
true || op ==
false)
911 const bool value = op ==
true;
917 // search for neighboring constants to merge
920 while(i <
new_expr.operands().size() - 1)
926 opi.is_constant() &&
opn.is_constant() &&
957 eb_i.src() ==
eb_n.src() &&
eb_i.index().is_constant() &&
958 eb_n.index().is_constant() &&
990 // search for neighboring constants to merge
993 while(i <
new_expr.operands().size() - 1)
999 opi.is_constant() &&
opn.is_constant() &&
1004 const std::string new_value=
1019 if(
new_expr.operands().size() == 1)
1056 if(!distance.has_value())
1073 if(!value.has_value())
1084 // this is to guard against large values of distance
1085 if(*distance >= width)
1089 else if(*distance >= 0)
1092 *value +=
power(2, width);
1093 *value /=
power(2, *distance);
1101 // this is to simulate an arithmetic right shift
1108 // this is to guard against large values of distance
1109 if(*distance >= width)
1113 else if(*distance >= 0)
1115 *value *=
power(2, *distance);
1127 *value /=
power(2, *distance);
1133 // this is to simulate an arithmetic right shift
1137 if(*value < 0 && new_value == 0)
1147 *value *=
power(2, *distance);
1165 if(!exponent.has_value())
1168 if(exponent.value() == 0)
1171 if(exponent.value() == 1)
1174 if(!base.has_value())
1197 if(!end.has_value())
1202 if(!width.has_value())
1210 const auto start = std::optional(*end + *
result_width - 1);
1215 DATA_INVARIANT(*start >= *end,
"extractbits must have start >= end");
1229 if(!result.has_value())
1232 return std::move(*result);
1236 // the most-significant bit comes first in an concatenation_exprt, hence we
1247 if(*start < offset && offset <= *end + *
op_width)
1261 if(
eb_src->index().is_constant())
1271 else if(*end == 0 && *start + 1 == *width)
1283 // simply remove, this is always 'nop'
1300 // cancel out "-(-x)" to "x"
1306 else if(
operand.is_constant())
1352 const auto &type = expr.
type();
1360 if(op.
type() == type)
1365 const auto new_value =
1366 make_bvrep(width, [&value, &width](std::size_t i) {
1391 // if rhs is ID_if (and lhs is not), swap operands for == and !=
1411 // see if we are comparing pointers that are address_of
1436 // are _both_ constant?
1443 // we want the constant on the RHS
1458 // RHS is constant, LHS is not
1463 // RHS is constant, LHS is not
1468 // both are not constant
1492 // two constants compare equal when there values (as strings) are the same
1493 // or both of them are pointers and both represent NULL in some way
1503 // if NULL is not zero on this platform, we really don't know what it
1504 // is and therefore cannot simplify
1592 // we can't eliminate zeros
1594 op0 == 0 || op1 == 0 ||
1638 // pretty much all of the simplifications below are unsound
1639 // for IEEE float because of NaN!
1657 // simplifications below require same-object, which we don't check for
1666 // comparing pointers: if both are address-of-plus-some-constant such that
1667 // the resulting pointer remains within object bounds then they can never
1696 // eliminate strict inequalities
1729 // now we only have >=, =
1733 "we previously converted all other cases to >= or ==");
1735 // syntactically equal?
1737 if(expr.
op0() == expr.
op1())
1740 // See if we can eliminate common addends on both sides.
1741 // On bit-vectors, this is only sound on '='.
1762 // the constant is always on the RHS
1775 // do we deal with pointers?
1786 // very special case for pointers
1794 // the address of an object is never NULL
1813 const auto &
object =
1836 // (type)ptr == NULL -> ptr == NULL
1837 // note that 'ptr' may be an integer
1854 // NULL + N == NULL is N == 0
1857 // &x + N == NULL is false when the offset is in bounds
1872 // all we are doing with pointers
1876 // is it a separation predicate?
1880 // see if there is a constant in the sum
1890 if(it->is_constant())
1904 // adjust the constant on the RHS
1917 // (double)value REL const ---> value rel const
1918 // if 'const' can be represented exactly.
1937 return std::move(result);
1942 // is the constant zero?
1949 // zero is always smaller or equal something unsigned
1958 // rules below do not hold for >=
1968 // simplify a+-b=0 to a=b
1971 // if we have -b+a=0, make that a+(-b)=0
1992 // make sure none of the type casts lose information
2025 // are we comparing with a typecast from bool?
2032 // we re-write (TYPE)boolean == 0 -> !boolean
2038 // we re-write (TYPE)boolean != 0 -> boolean
2045 #define NORMALISE_CONSTANT_TESTS
2046 #ifdef NORMALISE_CONSTANT_TESTS
2047 // Normalise to >= and = to improve caching and term sharing
2121 if(!result.has_value())
2124 return std::move(*result);
std::unordered_map< exprt, exprt, irep_hash > expr_mapt
const T & as_const(T &value)
Return a reference to the same object but ensures the type is const.
API to expression classes for bitvectors.
const extractbits_exprt & to_extractbits_expr(const exprt &expr)
Cast an exprt to an extractbits_exprt.
const bv_typet & to_bv_type(const typet &type)
Cast a typet to a bv_typet.
const bitvector_typet & to_bitvector_type(const typet &type)
Cast a typet to a bitvector_typet.
const integer_bitvector_typet & to_integer_bitvector_type(const typet &type)
Cast a typet to an integer_bitvector_typet.
const floatbv_typet & to_floatbv_type(const typet &type)
Cast a typet to a floatbv_typet.
const c_enum_tag_typet & to_c_enum_tag_type(const typet &type)
Cast a typet to a c_enum_tag_typet.
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
A base class for binary expressions.
A base class for relations, i.e., binary predicates whose two operands have the same type.
Bit-wise negation of bit-vectors.
Reverse the order of bits in a bit-vector.
Base class of fixed-width bit-vector types.
The byte swap expression.
std::size_t get_bits_per_byte() const
Concatenation of bit-vector operands.
struct configt::ansi_ct ansi_c
A constant literal expression.
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Base class for all expressions.
std::vector< exprt > operandst
bool is_boolean() const
Return whether the expression represents a Boolean.
bool is_constant() const
Return whether the expression is a constant.
typet & type()
Return the type of the expression.
The Boolean constant false.
constant_exprt to_expr() const
An IEEE 754 floating-point value, including specificiation.
constant_exprt to_expr() const
An IEEE 754 value plus a rounding mode, enabling operations with rounding on values.
The trinary if-then-else operator.
const irep_idt & id() const
Modulo defined as lhs-(rhs * truncate(lhs/rhs)).
Binary multiplication Associativity is not specified.
A base class for multi-ary expressions Associativity is not specified.
The null pointer constant.
The plus expression Associativity is not specified.
The offset (in bytes) of a pointer relative to the object.
The pointer type These are both 'bitvector_typet' (they have a width) and 'type_with_subtypet' (they ...
const exprt & base() const
const exprt & exponent() const
A base class for shift and rotate operators.
resultt simplify_bitwise(const multi_ary_exprt &)
resultt simplify_inequality_address_of(const binary_relation_exprt &)
resultt simplify_div(const div_exprt &)
resultt simplify_bitreverse(const bitreverse_exprt &)
Try to simplify bit-reversing to a constant expression.
resultt simplify_bitnot(const bitnot_exprt &)
resultt simplify_zero_extend(const zero_extend_exprt &)
static resultt changed(resultt<> result)
resultt simplify_if(const if_exprt &)
resultt simplify_node(const exprt &)
resultt simplify_minus(const minus_exprt &)
resultt simplify_extractbit(const extractbit_exprt &)
resultt simplify_rec(const exprt &)
resultt simplify_shifts(const shift_exprt &)
resultt simplify_typecast(const typecast_exprt &)
resultt simplify_object(const exprt &)
resultt simplify_mult(const mult_exprt &)
resultt simplify_inequality_rhs_is_constant(const binary_relation_exprt &)
virtual resultt simplify_inequality(const binary_relation_exprt &)
simplifies inequalities !=, <=, <, >=, >, and also ==
resultt simplify_not(const not_exprt &)
resultt simplify_bswap(const bswap_exprt &)
virtual resultt simplify_inequality_pointer_object(const binary_relation_exprt &)
static resultt unchanged(exprt expr)
resultt simplify_extractbits(const extractbits_exprt &)
Simplifies extracting of bits from a constant.
resultt simplify_mod(const mod_exprt &)
virtual resultt simplify_pointer_offset(const pointer_offset_exprt &)
resultt simplify_plus(const plus_exprt &)
resultt simplify_inequality_no_constant(const binary_relation_exprt &)
resultt simplify_unary_plus(const unary_plus_exprt &)
resultt simplify_power(const power_exprt &)
resultt simplify_concatenation(const concatenation_exprt &)
resultt simplify_inequality_both_constant(const binary_relation_exprt &)
simplifies inequalities for the case in which both sides of the inequality are constants
resultt simplify_unary_minus(const unary_minus_exprt &)
The Boolean constant true.
Semantic type conversion.
static exprt conditional_cast(const exprt &expr, const typet &type)
The type of an expression, extends irept.
The unary minus expression.
The unary plus expression.
Fixed-width bit-vector with unsigned binary interpretation.
zero extension The operand is converted to the given type by either a) truncating if the new type is ...
#define Forall_operands(it, expr)
#define Forall_expr(it, expr)
constant_exprt make_boolean_expr(bool value)
returns true_exprt if given true and false_exprt otherwise
const exprt & skip_typecast(const exprt &expr)
find the expression nested inside typecasts, if any
if_exprt lift_if(const exprt &src, std::size_t operand_number)
lift up an if_exprt one level
Deprecated expression utility functions.
API to expression classes for 'mathematical' expressions.
bool is_number(const typet &type)
Returns true if the type is a rational, real, integer, natural, complex, unsignedbv,...
API to expression classes for Pointers.
const address_of_exprt & to_address_of_expr(const exprt &expr)
Cast an exprt to an address_of_exprt.
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
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.
std::optional< mp_integer > pointer_offset_bits(const typet &type, const namespacet &ns)
std::optional< exprt > size_of_expr(const typet &type, const namespacet &ns)
exprt object_size(const exprt &pointer)
static bool mul_expr(constant_exprt &dest, const constant_exprt &expr)
produce a product of two expressions of the same type
static bool sum_expr(constant_exprt &dest, const constant_exprt &expr)
produce a sum of two constant expressions of the same type
static bool eliminate_common_addends(exprt &op0, exprt &op1)
std::optional< exprt > bits2expr(const std::string &bits, const typet &type, bool little_endian, const namespacet &ns)
std::optional< std::string > expr2bits(const exprt &expr, bool little_endian, const namespacet &ns)
#define UNREACHABLE
This should be used to mark dead code.
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
#define PRECONDITION(CONDITION)
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
API to expression classes.
const binary_relation_exprt & to_binary_relation_expr(const exprt &expr)
Cast an exprt to a binary_relation_exprt.
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
const plus_exprt & to_plus_expr(const exprt &expr)
Cast an exprt to a plus_exprt.
const minus_exprt & to_minus_expr(const exprt &expr)
Cast an exprt to a minus_exprt.
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
const unary_minus_exprt & to_unary_minus_expr(const exprt &expr)
Cast an exprt to a unary_minus_exprt.
const equal_exprt & to_equal_expr(const exprt &expr)
Cast an exprt to an equal_exprt.