-
Notifications
You must be signed in to change notification settings - Fork 273
/
Copy pathsimplify_expr_class.h
299 lines (261 loc) · 10.4 KB
/
simplify_expr_class.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
/*******************************************************************\
Module:
Author: Daniel Kroening, [email protected]
\*******************************************************************/
#ifndef CPROVER_UTIL_SIMPLIFY_EXPR_CLASS_H
#define CPROVER_UTIL_SIMPLIFY_EXPR_CLASS_H
// #define DEBUG_ON_DEMAND
#ifdef DEBUG_ON_DEMAND
#include <sys/stat.h>
#endif
#include <set>
#include "expr.h"
#include "mp_arith.h"
#include "type.h"
// #define USE_LOCAL_REPLACE_MAP
#ifdef USE_LOCAL_REPLACE_MAP
#include "replace_expr.h"
#endif
class abs_exprt;
class address_of_exprt;
class array_exprt;
class binary_exprt;
class binary_overflow_exprt;
class binary_relation_exprt;
class bitnot_exprt;
class bitreverse_exprt;
class bswap_exprt;
class byte_extract_exprt;
class byte_update_exprt;
class concatenation_exprt;
class count_leading_zeros_exprt;
class count_trailing_zeros_exprt;
class dereference_exprt;
class div_exprt;
class exprt;
class extractbit_exprt;
class extractbits_exprt;
class find_first_set_exprt;
class floatbv_round_to_integral_exprt;
class floatbv_typecast_exprt;
class function_application_exprt;
class ieee_float_op_exprt;
class if_exprt;
class index_exprt;
class lambda_exprt;
class member_exprt;
class minus_exprt;
class mod_exprt;
class multi_ary_exprt;
class mult_exprt;
class namespacet;
class not_exprt;
class object_size_exprt;
class overflow_result_exprt;
class plus_exprt;
class pointer_object_exprt;
class pointer_offset_exprt;
class popcount_exprt;
class power_exprt;
class prophecy_pointer_in_range_exprt;
class prophecy_r_or_w_ok_exprt;
class quantifier_exprt;
class refined_string_exprt;
class shift_exprt;
class sign_exprt;
class typecast_exprt;
class unary_exprt;
class unary_minus_exprt;
class unary_overflow_exprt;
class unary_plus_exprt;
class update_exprt;
class with_exprt;
class zero_extend_exprt;
class simplify_exprt
{
public:
explicit simplify_exprt(const namespacet &_ns):
do_simplify_if(true),
ns(_ns)
#ifdef DEBUG_ON_DEMAND
, debug_on(false)
#endif
{
#ifdef DEBUG_ON_DEMAND
struct stat f;
debug_on=stat("SIMP_DEBUG", &f)==0;
#endif
}
virtual ~simplify_exprt()
{
}
bool do_simplify_if;
template <typename T = exprt>
struct resultt
{
bool has_changed() const
{
return expr_changed == CHANGED;
}
enum expr_changedt
{
CHANGED,
UNCHANGED
} expr_changed;
T expr;
/// conversion to expression, to enable chaining
operator T() const
{
return expr;
}
/// conversion from expression, thus not 'explicit'
/// marks the expression as "CHANGED"
// NOLINTNEXTLINE(runtime/explicit)
resultt(T _expr) : expr_changed(CHANGED), expr(std::move(_expr))
{
}
resultt(expr_changedt _expr_changed, T _expr)
: expr_changed(_expr_changed), expr(std::move(_expr))
{
}
};
[[nodiscard]] static resultt<> unchanged(exprt expr)
{
return resultt<>(resultt<>::UNCHANGED, std::move(expr));
}
[[nodiscard]] static resultt<> changed(resultt<> result)
{
result.expr_changed = resultt<>::CHANGED;
return result;
}
// These below all return 'true' if the simplification wasn't applicable.
// If false is returned, the expression has changed.
[[nodiscard]] resultt<> simplify_typecast(const typecast_exprt &);
[[nodiscard]] resultt<> simplify_typecast_preorder(const typecast_exprt &);
[[nodiscard]] resultt<> simplify_extractbit(const extractbit_exprt &);
[[nodiscard]] resultt<> simplify_extractbits(const extractbits_exprt &);
[[nodiscard]] resultt<> simplify_concatenation(const concatenation_exprt &);
[[nodiscard]] resultt<> simplify_zero_extend(const zero_extend_exprt &);
[[nodiscard]] resultt<> simplify_mult(const mult_exprt &);
[[nodiscard]] resultt<> simplify_div(const div_exprt &);
[[nodiscard]] resultt<> simplify_mod(const mod_exprt &);
[[nodiscard]] resultt<> simplify_plus(const plus_exprt &);
[[nodiscard]] resultt<> simplify_minus(const minus_exprt &);
[[nodiscard]] resultt<> simplify_floatbv_op(const ieee_float_op_exprt &);
[[nodiscard]] resultt<>
simplify_floatbv_round_to_integral(const floatbv_round_to_integral_exprt &);
[[nodiscard]] resultt<>
simplify_floatbv_typecast(const floatbv_typecast_exprt &);
[[nodiscard]] resultt<> simplify_shifts(const shift_exprt &);
[[nodiscard]] resultt<> simplify_power(const power_exprt &);
[[nodiscard]] resultt<> simplify_bitwise(const multi_ary_exprt &);
[[nodiscard]] resultt<> simplify_if_preorder(const if_exprt &expr);
[[nodiscard]] resultt<> simplify_if(const if_exprt &);
[[nodiscard]] resultt<> simplify_bitnot(const bitnot_exprt &);
[[nodiscard]] resultt<> simplify_not(const not_exprt &);
[[nodiscard]] resultt<> simplify_boolean(const exprt &);
[[nodiscard]] resultt<> simplify_inequality(const binary_relation_exprt &);
[[nodiscard]] resultt<>
simplify_ieee_float_relation(const binary_relation_exprt &);
[[nodiscard]] resultt<> simplify_lambda(const lambda_exprt &);
[[nodiscard]] resultt<> simplify_with(const with_exprt &);
[[nodiscard]] resultt<> simplify_update(const update_exprt &);
[[nodiscard]] resultt<> simplify_index(const index_exprt &);
[[nodiscard]] resultt<> simplify_index_preorder(const index_exprt &);
[[nodiscard]] resultt<> simplify_member(const member_exprt &);
[[nodiscard]] resultt<> simplify_member_preorder(const member_exprt &);
[[nodiscard]] resultt<> simplify_byte_update(const byte_update_exprt &);
[[nodiscard]] resultt<> simplify_byte_extract(const byte_extract_exprt &);
[[nodiscard]] resultt<>
simplify_byte_extract_preorder(const byte_extract_exprt &);
[[nodiscard]] resultt<> simplify_pointer_object(const pointer_object_exprt &);
[[nodiscard]] resultt<>
simplify_unary_pointer_predicate_preorder(const unary_exprt &);
[[nodiscard]] resultt<> simplify_object_size(const object_size_exprt &);
[[nodiscard]] resultt<> simplify_is_dynamic_object(const unary_exprt &);
[[nodiscard]] resultt<> simplify_is_invalid_pointer(const unary_exprt &);
[[nodiscard]] resultt<> simplify_object(const exprt &);
[[nodiscard]] resultt<> simplify_unary_minus(const unary_minus_exprt &);
[[nodiscard]] resultt<> simplify_unary_plus(const unary_plus_exprt &);
[[nodiscard]] resultt<> simplify_dereference(const dereference_exprt &);
[[nodiscard]] resultt<>
simplify_dereference_preorder(const dereference_exprt &);
[[nodiscard]] resultt<> simplify_address_of(const address_of_exprt &);
[[nodiscard]] resultt<> simplify_pointer_offset(const pointer_offset_exprt &);
[[nodiscard]] resultt<> simplify_bswap(const bswap_exprt &);
[[nodiscard]] resultt<> simplify_isinf(const unary_exprt &);
[[nodiscard]] resultt<> simplify_isnan(const unary_exprt &);
[[nodiscard]] resultt<> simplify_isnormal(const unary_exprt &);
[[nodiscard]] resultt<> simplify_abs(const abs_exprt &);
[[nodiscard]] resultt<> simplify_sign(const sign_exprt &);
[[nodiscard]] resultt<> simplify_popcount(const popcount_exprt &);
[[nodiscard]] resultt<> simplify_complex(const unary_exprt &);
/// Try to simplify overflow-+, overflow-*, overflow--, overflow-shl.
/// Simplification will be possible when the operands are constants or the
/// types of the operands have infinite domains.
[[nodiscard]] resultt<>
simplify_overflow_binary(const binary_overflow_exprt &);
/// Try to simplify overflow-unary-.
/// Simplification will be possible when the operand is constants or the
/// type of the operand has an infinite domain.
[[nodiscard]] resultt<> simplify_overflow_unary(const unary_overflow_exprt &);
/// Try to simplify overflow_result-+, overflow_result-*, overflow_result--,
/// overflow_result-shl, overflow_result-unary--.
/// Simplification will be possible when the operands are constants or the
/// types of the operands have infinite domains.
[[nodiscard]] resultt<>
simplify_overflow_result(const overflow_result_exprt &);
/// Attempt to simplify mathematical function applications if we have
/// enough information to do so. Currently focused on constant comparisons.
[[nodiscard]] resultt<>
simplify_function_application(const function_application_exprt &);
/// Try to simplify count-leading-zeros to a constant expression.
[[nodiscard]] resultt<> simplify_clz(const count_leading_zeros_exprt &);
/// Try to simplify count-trailing-zeros to a constant expression.
[[nodiscard]] resultt<> simplify_ctz(const count_trailing_zeros_exprt &);
/// Try to simplify bit-reversing to a constant expression.
[[nodiscard]] resultt<> simplify_bitreverse(const bitreverse_exprt &);
/// Try to simplify find-first-set to a constant expression.
[[nodiscard]] resultt<> simplify_ffs(const find_first_set_exprt &);
/// Try to simplify prophecy_{r,w,rw}_ok to a constant expression.
[[nodiscard]] resultt<>
simplify_prophecy_r_or_w_ok(const prophecy_r_or_w_ok_exprt &);
/// Try to simplify prophecy_pointer_in_range to a constant expression.
[[nodiscard]] resultt<>
simplify_prophecy_pointer_in_range(const prophecy_pointer_in_range_exprt &);
/// Try to simplify exists/forall to a constant expression.
[[nodiscard]] resultt<> simplify_quantifier_expr(const quantifier_exprt &);
// auxiliary
bool simplify_if_implies(
exprt &expr, const exprt &cond, bool truth, bool &new_truth);
bool simplify_if_recursive(exprt &expr, const exprt &cond, bool truth);
bool simplify_if_conj(exprt &expr, const exprt &cond);
bool simplify_if_disj(exprt &expr, const exprt &cond);
bool simplify_if_branch(exprt &trueexpr, exprt &falseexpr, const exprt &cond);
bool simplify_if_cond(exprt &expr);
[[nodiscard]] resultt<> simplify_address_of_arg(const exprt &);
[[nodiscard]] resultt<>
simplify_inequality_both_constant(const binary_relation_exprt &);
[[nodiscard]] resultt<>
simplify_inequality_no_constant(const binary_relation_exprt &);
[[nodiscard]] resultt<>
simplify_inequality_rhs_is_constant(const binary_relation_exprt &);
[[nodiscard]] resultt<>
simplify_inequality_address_of(const binary_relation_exprt &);
[[nodiscard]] resultt<>
simplify_inequality_pointer_object(const binary_relation_exprt &);
// main recursion
[[nodiscard]] resultt<> simplify_node(const exprt &);
[[nodiscard]] resultt<> simplify_node_preorder(const exprt &);
[[nodiscard]] resultt<> simplify_rec(const exprt &);
virtual bool simplify(exprt &expr);
protected:
const namespacet &ns;
#ifdef DEBUG_ON_DEMAND
bool debug_on;
#endif
#ifdef USE_LOCAL_REPLACE_MAP
replace_mapt local_replace_map;
#endif
};
#endif // CPROVER_UTIL_SIMPLIFY_EXPR_CLASS_H