ESBMC
Efficient SMT-based Context-Bounded Model Checker
Loading...
Searching...
No Matches
symex_target_equation.h
Go to the documentation of this file.
1#ifndef CPROVER_BASIC_SYMEX_EQUATION_H
2#define CPROVER_BASIC_SYMEX_EQUATION_H
3
4#include <cstdint>
5#include <cstdio>
6#include <cstring>
9#include <list>
10#include <map>
11#include <memory>
12#include <util/config/config.h>
13#include <irep2/irep2.h>
15#include <util/base/threeval.h>
16#include <vector>
17
18class smt_convt;
19
21{
22public:
23 class SSA_stept;
24
26 {
27 debug_print = config.options.get_bool_option("symex-ssa-trace");
28 ssa_trace = config.options.get_bool_option("ssa-trace");
29 ssa_smt_trace = config.options.get_bool_option("ssa-smt-trace");
30 }
31
32 // assignment to a variable - lhs must be a symbol
33 void assignment(
34 const expr2tc &guard,
35 const expr2tc &lhs,
36 const expr2tc &original_lhs,
37 const expr2tc &rhs,
38 const expr2tc &original_rhs,
39 const sourcet &source,
40 std::vector<stack_framet> stack_trace,
41 const bool hidden,
42 unsigned loop_number) override;
43
44 // output
45 void output(
46 const expr2tc &guard,
47 const sourcet &source,
48 const std::string &fmt,
49 const std::list<expr2tc> &args) override;
50
51 void branching(
52 const expr2tc &guard,
53 const expr2tc &cond,
54 const sourcet &source,
55 const bool hidden,
56 unsigned loop_number) override;
57
58 // record an assumption
59 void assumption(
60 const expr2tc &guard,
61 const expr2tc &cond,
62 const sourcet &source,
63 unsigned loop_number) override;
64
65 // record an assertion
66 void assertion(
67 const expr2tc &guard,
68 const expr2tc &cond,
69 const expr2tc &cond_neg,
70 const std::string &msg,
71 std::vector<stack_framet> stack_trace,
72 const sourcet &source,
73 unsigned loop_number) override;
74
75 void renumber(
76 const expr2tc &guard,
77 const expr2tc &symbol,
78 const expr2tc &size,
79 const sourcet &source) override;
80
81 // `runtime_encoded_equationt` overrides `convert` and supports only the
82 // default mode; incremental BMC callers must run probes through the
83 // non-incremental path.
97
98 virtual void convert(
99 smt_convt &smt_conv,
101
102 void reconstruct_symbolic_expression(expr2tc &expr, bool keep_local_variables)
103 const override;
104 void replace_rec(const SSA_stept &step, expr2tc &e, bool keep_local) const;
105
107 {
108 public:
111
112 bool is_assert() const
113 {
114 return type == symex_targett::ASSERT;
115 }
116 bool is_assume() const
117 {
118 return type == symex_targett::ASSUME;
119 }
120 bool is_assignment() const
121 {
123 }
124 bool is_output() const
125 {
126 return type == symex_targett::OUTPUT;
127 }
128 bool is_renumber() const
129 {
131 }
132 bool is_skip() const
133 {
134 return type == symex_targett::SKIP;
135 }
136 bool is_branching() const
137 {
139 }
140
142
143 // for ASSIGNMENT; RENUMBER reuses lhs = symbol, rhs = new size
146
147 // cond: assume/assert condition, assignment equality, or branch guard.
148 // comment interned: assertion messages are a small, highly repetitive
149 // set ("dereference failure", "array bounds violated", ...), so
150 // irep_idt both shrinks the inline footprint (4 bytes vs a 32-byte
151 // std::string) and dedups the payload across the many steps that share
152 // a message.
157
158 // OUTPUT-step payload. OUTPUT steps are rare (only printf-family
159 // side effects produce them), so the format string and argument
160 // lists live in a lazily-allocated side struct rather than inline
161 // on every SSA step. This keeps sizeof(SSA_stept) ~80 bytes smaller
162 // on the assignment/assume/assert steps that dominate large
163 // equations. Access through the output_* helpers below.
165 {
166 std::string format_string;
167 std::list<expr2tc> output_args;
168 std::list<expr2tc> converted_output_args; // filled during conversion
169 };
170 std::unique_ptr<output_datat> output_data;
171
172 // One stack trace recorded per function activation record, in reverse
173 // order (most recent in idx 0). Only assignment and assert steps ever
174 // populate it, so — like output_data — it lives in a lazily-allocated
175 // side vector rather than costing 24 bytes inline on the assume/branch/
176 // renumber/output steps that never use it. Read through stack_trace(),
177 // write through stack_trace_payload().
178 std::unique_ptr<std::vector<stack_framet>> stack_trace_box;
179
180 // Discharged assertion expression used for counterexample trace queries.
181 // Conversion sets it to the discharged claim for asserts and to true
182 // for ignored steps and other non-assume steps; it stays nil for
183 // non-ignored assumes and before conversion.
185
186 // for slicing
187 bool ignore;
188
189 // for visibility
190 bool hidden;
191
192 // for bidirectional search
193 unsigned loop_number;
194
196 {
197 }
198
199 // SSA_stept is copied wholesale (e.g. the per-claim local_eq in
200 // bmc.cpp), so the unique_ptr payload needs deep-copy semantics.
201 // Moves stay default (cheap pointer steal).
203 : source(o.source),
204 type(o.type),
205 guard(o.guard),
206 lhs(o.lhs),
207 rhs(o.rhs),
210 cond(o.cond),
212 comment(o.comment),
214 o.output_data ? std::make_unique<output_datat>(*o.output_data)
215 : nullptr),
218 ? std::make_unique<std::vector<stack_framet>>(*o.stack_trace_box)
219 : nullptr),
221 ignore(o.ignore),
222 hidden(o.hidden),
224 {
225 }
227 {
228 if (this != &o)
229 *this = SSA_stept(o); // copy-and-move
230 return *this;
231 }
232 SSA_stept(SSA_stept &&) = default;
234
236 {
237 if (!output_data)
238 output_data = std::make_unique<output_datat>();
239 return *output_data;
240 }
241
242 // Read-only view of the stack trace; empty when none was recorded.
243 const std::vector<stack_framet> &stack_trace() const
244 {
245 static const std::vector<stack_framet> empty;
246 return stack_trace_box ? *stack_trace_box : empty;
247 }
248
249 std::vector<stack_framet> &stack_trace_payload()
250 {
251 if (!stack_trace_box)
252 stack_trace_box = std::make_unique<std::vector<stack_framet>>();
253 return *stack_trace_box;
254 }
255
256 void output(const namespacet &ns, std::ostream &out) const;
257 void short_output(
258 const namespacet &ns,
259 std::ostream &out,
260 bool show_ignored = false) const;
261 void dump() const;
262 };
263
264 unsigned count_ignored_SSA_steps() const
265 {
266 unsigned i = 0;
267 for (const auto &SSA_step : SSA_steps)
268 if (SSA_step.ignore)
269 i++;
270 return i;
271 }
272
273 typedef std::list<SSA_stept> SSA_stepst;
275
276 SSA_stepst::iterator get_SSA_step(unsigned s)
277 {
278 SSA_stepst::iterator it = SSA_steps.begin();
279 for (; s != 0; s--)
280 {
281 assert(it != SSA_steps.end());
282 it++;
283 }
284 return it;
285 }
286
287 void output(std::ostream &out) const;
288 void short_output(std::ostream &out, bool show_ignored = false) const;
289
294 bool check_for_duplicate_assigns() const;
295
296 void clear()
297 {
298 SSA_steps.clear();
299 output_count = 0;
300 }
301
302 unsigned int clear_assertions();
303
304 std::shared_ptr<symex_targett> clone() const override
305 {
306 // SSA_stept's copy constructor deep-copies its unique_ptr payloads, so
307 // plain member-wise duplication is safe.
308 return std::shared_ptr<symex_targett>(new symex_target_equationt(*this));
309 }
310
311 void push_ctx() override;
312 void pop_ctx() override;
313
314protected:
316
320 unsigned output_count;
321
322private:
323 void debug_print_step(const SSA_stept &step) const;
324};
325
327{
328public:
330 {
331 };
332
335
336 void push_ctx() override;
337 void pop_ctx() override;
338
339 std::shared_ptr<symex_targett> clone() const override;
340
341 void convert(
342 smt_convt &smt_conv,
345
346 tvt ask_solver_question(const expr2tc &question);
347
349 struct solver_statet;
350 std::unique_ptr<solver_statet> solver_state;
351 std::list<SSA_stepst::iterator> scoped_end_points;
352 SSA_stepst::iterator cvt_progress;
353};
354
355extern inline bool operator<(
356 const symex_target_equationt::SSA_stepst::const_iterator a,
357 const symex_target_equationt::SSA_stepst::const_iterator b)
358{
359 return &(*a) < &(*b);
360}
361
362std::ostream &
363operator<<(std::ostream &out, const symex_target_equationt::SSA_stept &step);
364std::ostream &
365operator<<(std::ostream &out, const symex_target_equationt &equation);
366
367#endif
Definition irep_idt.h:12
Definition namespace.h:10
Definition symex_target_equation.h:330
~runtime_encoded_equationt() override
SSA_stepst::iterator cvt_progress
Definition symex_target_equation.h:352
runtime_encoded_equationt(const namespacet &_ns, smt_convt &conv)
Definition symex_target_equation.cpp:573
void pop_ctx() override
Definition symex_target_equation.cpp:642
void push_ctx() override
Definition symex_target_equation.cpp:632
smt_convt & conv
Definition symex_target_equation.h:348
void convert(smt_convt &smt_conv, assertion_modet mode=assertion_modet::Violated) override
Definition symex_target_equation.cpp:657
std::shared_ptr< symex_targett > clone() const override
Definition symex_target_equation.cpp:681
std::list< SSA_stepst::iterator > scoped_end_points
Definition symex_target_equation.h:351
void flush_latest_instructions()
Definition symex_target_equation.cpp:587
std::unique_ptr< solver_statet > solver_state
Definition symex_target_equation.h:350
tvt ask_solver_question(const expr2tc &question)
Definition symex_target_equation.cpp:695
Slim, frontend-facing SMT interface.
Definition smt_conv.h:30
Definition symex_target.h:125
Definition symex_target_equation.h:107
SSA_stept(const SSA_stept &o)
Definition symex_target_equation.h:202
irep_idt comment
Definition symex_target_equation.h:156
expr2tc cond_expr
Definition symex_target_equation.h:184
expr2tc cond_neg
cond with the claim negated under the same guards (issue #7585).
Definition symex_target_equation.h:155
std::vector< stack_framet > & stack_trace_payload()
Definition symex_target_equation.h:249
std::unique_ptr< output_datat > output_data
Definition symex_target_equation.h:170
SSA_stept()
Definition symex_target_equation.h:195
expr2tc guard
Definition symex_target_equation.h:141
SSA_stept & operator=(const SSA_stept &o)
Definition symex_target_equation.h:226
SSA_stept(SSA_stept &&)=default
symex_targett::step_typet type
Definition symex_target_equation.h:110
const std::vector< stack_framet > & stack_trace() const
Definition symex_target_equation.h:243
sourcet source
Definition symex_target_equation.h:109
expr2tc lhs
Definition symex_target_equation.h:144
bool is_assert() const
Definition symex_target_equation.h:112
bool is_branching() const
Definition symex_target_equation.h:136
std::unique_ptr< std::vector< stack_framet > > stack_trace_box
Definition symex_target_equation.h:178
void short_output(const namespacet &ns, std::ostream &out, bool show_ignored=false) const
Definition symex_target_equation.cpp:459
expr2tc rhs
Definition symex_target_equation.h:144
bool is_assignment() const
Definition symex_target_equation.h:120
SSA_stept & operator=(SSA_stept &&)=default
expr2tc original_lhs
Definition symex_target_equation.h:145
unsigned loop_number
Definition symex_target_equation.h:193
output_datat & output_payload()
Definition symex_target_equation.h:235
bool ignore
Definition symex_target_equation.h:187
bool is_assume() const
Definition symex_target_equation.h:116
bool is_skip() const
Definition symex_target_equation.h:132
bool is_output() const
Definition symex_target_equation.h:124
bool hidden
Definition symex_target_equation.h:190
expr2tc original_rhs
Definition symex_target_equation.h:145
bool is_renumber() const
Definition symex_target_equation.h:128
void dump() const
Definition symex_target_equation.cpp:400
void output(const namespacet &ns, std::ostream &out) const
Definition symex_target_equation.cpp:407
expr2tc cond
Definition symex_target_equation.h:153
Definition symex_target_equation.h:21
const namespacet & ns
Definition symex_target_equation.h:315
void branching(const expr2tc &guard, const expr2tc &cond, const sourcet &source, const bool hidden, unsigned loop_number) override
Definition symex_target_equation.cpp:252
void clear()
Definition symex_target_equation.h:296
SSA_stepst SSA_steps
Definition symex_target_equation.h:274
void assumption(const expr2tc &guard, const expr2tc &cond, const sourcet &source, unsigned loop_number) override
Definition symex_target_equation.cpp:273
unsigned count_ignored_SSA_steps() const
Definition symex_target_equation.h:264
void assignment(const expr2tc &guard, const expr2tc &lhs, const expr2tc &original_lhs, const expr2tc &rhs, const expr2tc &original_rhs, const sourcet &source, std::vector< stack_framet > stack_trace, const bool hidden, unsigned loop_number) override
Definition symex_target_equation.cpp:199
symex_target_equationt(const namespacet &_ns)
Definition symex_target_equation.h:25
void replace_rec(const SSA_stept &step, expr2tc &e, bool keep_local) const
Definition symex_target_equation.cpp:534
void output(const expr2tc &guard, const sourcet &source, const std::string &fmt, const std::list< expr2tc > &args) override
Definition symex_target_equation.cpp:232
bool debug_print
Definition symex_target_equation.h:317
bool ssa_smt_trace
Definition symex_target_equation.h:319
std::shared_ptr< symex_targett > clone() const override
Definition symex_target_equation.h:304
bool check_for_duplicate_assigns() const
I10: no SSA name is defined twice.
Definition symex_target_equation.cpp:489
std::list< SSA_stept > SSA_stepst
Definition symex_target_equation.h:273
void short_output(std::ostream &out, bool show_ignored=false) const
Definition symex_target_equation.cpp:391
assertion_modet
How an assertion is encoded.
Definition symex_target_equation.h:92
@ PathReachable
Definition symex_target_equation.h:94
@ Violated
Definition symex_target_equation.h:93
@ Satisfiable
Definition symex_target_equation.h:95
SSA_stepst::iterator get_SSA_step(unsigned s)
Definition symex_target_equation.h:276
void push_ctx() override
Definition symex_target_equation.cpp:474
void pop_ctx() override
Definition symex_target_equation.cpp:478
void assertion(const expr2tc &guard, const expr2tc &cond, const expr2tc &cond_neg, const std::string &msg, std::vector< stack_framet > stack_trace, const sourcet &source, unsigned loop_number) override
cond_neg is cond with the claim negated under the same guards, so a probe can ask whether the claim h...
Definition symex_target_equation.cpp:292
unsigned int clear_assertions()
Definition symex_target_equation.cpp:515
void reconstruct_symbolic_expression(expr2tc &expr, bool keep_local_variables) const override
Replaces trace symbols from expression with their values.
Definition symex_target_equation.cpp:555
virtual void convert(smt_convt &smt_conv, assertion_modet mode=assertion_modet::Violated)
Definition symex_target_equation.cpp:339
void renumber(const expr2tc &guard, const expr2tc &symbol, const expr2tc &size, const sourcet &source) override
Definition symex_target_equation.cpp:318
unsigned output_count
Definition symex_target_equation.h:320
bool ssa_trace
Definition symex_target_equation.h:318
Definition symex_target.h:14
step_typet
Definition symex_target.h:20
@ OUTPUT
Definition symex_target.h:24
@ RENUMBER
Definition symex_target.h:26
@ ASSERT
Definition symex_target.h:23
@ SKIP
Definition symex_target.h:25
@ BREANCHING
Definition symex_target.h:27
@ ASSIGNMENT
Definition symex_target.h:21
@ ASSUME
Definition symex_target.h:22
Definition threeval.h:10
configt config
Definition config.cpp:8
pthread_cond_t cond
Definition cuda.h:50
Classes and definitions for non-stringy internal representation.
irep_container< expr2t > expr2tc
Definition irep2.h:431
Definition format.h:30
Definition exception.cpp:51
#define false
Definition stdbool.h:10
Definition symex_target_equation.cpp:569
Definition symex_target_equation.h:165
std::list< expr2tc > converted_output_args
Definition symex_target_equation.h:168
std::list< expr2tc > output_args
Definition symex_target_equation.h:167
std::string format_string
Definition symex_target_equation.h:166
Definition symex_target.h:31
bool operator<(const symex_target_equationt::SSA_stepst::const_iterator a, const symex_target_equationt::SSA_stepst::const_iterator b)
Definition symex_target_equation.h:355
std::ostream & operator<<(std::ostream &out, const symex_target_equationt::SSA_stept &step)