ESBMC
Efficient SMT-based Context-Bounded Model Checker
Loading...
Searching...
No Matches
renaming.h
Go to the documentation of this file.
1#ifndef _GOTO_SYMEX_RENAMING_H_
2#define _GOTO_SYMEX_RENAMING_H_
3
4#include <set>
8#include <irep2/irep2_guard.h>
10#include <irep2/irep2_expr.h>
11#include <util/irep/std_expr.h>
12
13class namespacet;
14
15namespace renaming
16{
18{
19public:
20 virtual void get_original_name(expr2tc &expr) const = 0;
21 virtual void rename(expr2tc &expr) = 0;
22 virtual void remove(const expr2tc &symbol) = 0;
23
24 virtual void get_ident_name(expr2tc &symbol) const = 0;
25
26 virtual ~renaming_levelt() = default;
27 // protected:
28 // XXX: should leave protected enabled, but g++ 5.4 on ubuntu 16.04 does not
29 // appear to honor the following friend directive?
32};
33
34// level 1 -- function frames
35// this is to preserve locality in case of recursion
36
37struct level1t : public renaming_levelt
38{
39public:
40 struct name_rec_hash;
42 {
43 public:
45 {
46 }
47
48 name_record(const symbol2t &sym) : base_name(sym.thename)
49 {
50 }
51
52 name_record(const irep_idt &name) : base_name(name)
53 {
54 }
55
56 int compare(const name_record &ref) const
57 {
58 if (base_name.get_no() < ref.base_name.get_no())
59 return -1;
60 if (base_name.get_no() > ref.base_name.get_no())
61 return 1;
62
63 return 0;
64 }
65
66 bool operator<(const name_record &ref) const
67 {
68 if (compare(ref) == -1)
69 return true;
70 return false;
71 }
72
73 bool operator==(const name_record &ref) const
74 {
75 if (compare(ref) == 0)
76 return true;
77 return false;
78 }
79
81
83 };
84
86 {
87 size_t operator()(const name_record &ref) const
88 {
89 return ref.base_name.get_no();
90 }
91
92 bool operator()(const name_record &ref, const name_record &ref2) const
93 {
94 return ref < ref2;
95 }
96 };
97
100 unsigned int thread_id;
101 // Set externally (alongside thread_id) so rename() / get_ident_name()
102 // can check is_thread_local on globals and route them per-thread
103 // instead of to the shared level1_global bucket (issue #4434, #4433).
104 const namespacet *ns = nullptr;
105
106 void rename(expr2tc &expr) override;
107 void get_ident_name(expr2tc &symbol) const override;
108 void remove(const expr2tc &symbol) override
109 {
110 current_names.erase(name_record(to_symbol2t(symbol)));
111 }
112
113 void rename(const expr2tc &symbol, unsigned frame)
114 {
115 // Given that this is level1, use base symbol.
116 name_record rec(to_symbol2t(symbol));
117 const unsigned *cur = current_names.find(rec);
118 // I1 at L1: an activation index only ever grows.
120 !cur || *cur <= frame, "L1 activation counter moved backwards");
121 current_names.set(rec, frame);
122 }
123
128
129 unsigned int current_number(const irep_idt &name) const;
130
131 level1t() = default;
132 ~level1t() override = default;
133
134 virtual void print(std::ostream &out) const;
135};
136
137// level 2 -- SSA
138
140{
141protected:
142 virtual void
143 coveredinbees(expr2tc &lhs_sym, unsigned count, unsigned node_id);
144
145public:
147 {
148 public:
150 {
151 compute_hash();
152 }
153
155 : base_name(sym.thename),
156 lev(sym.rlevel),
157 l1_num(sym.level1_num),
158 t_num(sym.thread_num)
159 {
160 compute_hash();
161 }
162
163 int compare(const name_record &ref) const
164 {
165 if (hash < ref.hash)
166 return -1;
167 if (hash > ref.hash)
168 return 1;
169
170 if (base_name < ref.base_name)
171 return -1;
172 if (ref.base_name < base_name)
173 return 1;
174
175 if (lev < ref.lev)
176 return -1;
177 if (lev > ref.lev)
178 return 1;
179
180 if (l1_num < ref.l1_num)
181 return -1;
182 if (l1_num > ref.l1_num)
183 return 1;
184
185 if (t_num < ref.t_num)
186 return -1;
187 if (t_num > ref.t_num)
188 return 1;
189
190 return 0;
191 }
192
193 bool operator<(const name_record &ref) const
194 {
195 if (compare(ref) == -1)
196 return true;
197 return false;
198 }
199
200 bool operator==(const name_record &ref) const
201 {
202 if (compare(ref) == 0)
203 return true;
204 return false;
205 }
206
208 symbol2t::renaming_level lev = symbol2t::renaming_level::level0;
209 unsigned int l1_num = 0;
210 unsigned int t_num = 0;
211
212 // Derived from the fields above; used as the fast-path primary key in
213 // compare() and by name_rec_hash. compare() short-circuits on it, so it
214 // must stay a pure function of them — compute_hash() is the only writer.
215 size_t hash = 0;
216
217 private:
218 void compute_hash()
219 {
220 size_t seed = 0;
221 esbmct::hash_combine(seed, base_name.get_no());
222 esbmct::hash_combine(seed, (uint8_t)lev);
225 hash = seed;
226 }
227 };
228
230 {
231 size_t operator()(const name_record &ref) const
232 {
233 return ref.hash;
234 }
235
236 bool operator()(const name_record &ref, const name_record &ref2) const
237 {
238 return ref < ref2;
239 }
240 };
241
242public:
243 struct valuet
244 {
245 unsigned count;
247 unsigned node_id;
249 {
250 }
251 // Value equality so the persistent map can be structurally diffed
252 // (phi_function). Only invoked on the divergent leaves.
253 bool operator==(const valuet &v) const
254 {
255 return count == v.count && node_id == v.node_id && constant == v.constant;
256 }
257 bool operator!=(const valuet &v) const
258 {
259 return !(*this == v);
260 }
261 };
262
263 virtual void make_assignment(
264 expr2tc &lhs_symbol,
265 const expr2tc &constant_value,
266 const expr2tc &assigned_value);
267
268 void rename(expr2tc &expr) override;
269 virtual void rename(expr2tc &expr, unsigned count) = 0;
270
271 void get_ident_name(expr2tc &symbol) const override;
272
273 void remove(const expr2tc &symbol) override
274 {
275 current_names.erase(name_record(to_symbol2t(symbol)));
276 }
277
282 {
283 const valuet *p = current_names.find(rec);
284 return p ? *p : valuet();
285 }
286
295 void retire(const name_record &rec)
296 {
297 current_names.update(rec, [](valuet entry) {
298 ++entry.count;
299 entry.constant = expr2tc();
300 return entry;
301 });
302 }
303
309 void declare(const name_record &rec)
310 {
311 if (current_names.find(rec) == nullptr)
312 current_names.set(rec, valuet());
313 }
314
319
325 void set_constant(const name_record &rec, const expr2tc &value)
326 {
327 const valuet *entry = current_names.find(rec);
329 entry != nullptr && is_nil_expr(entry->constant),
330 "a propagated value may only complete the assignment that minted it");
331 // `entry` dangles once the map is written; do not read it below.
332 current_names.update(rec, [&value](valuet v) {
333 v.constant = value;
334 return v;
335 });
336 }
337
338 unsigned current_number(const expr2tc &sym) const;
339 unsigned current_number(const name_record &rec) const;
340
341 // static method to rename a (l0) variable to the l1 number record specified
342 // in the given name_record. The use case for this is phi_function, where
343 // we have a handle on name_record's identifying the storage variable that
344 // we want to assign to, but lack the ability to address it as a symbol.
345 // In that case (or any similar) we need a facility independent of a
346 // specific level2t object.
347 static void rename_to_record(expr2tc &sym, const name_record &rec);
348
349 level2t() = default;
350 ~level2t() override = default;
351 virtual std::shared_ptr<level2t> clone() const = 0;
352
353 virtual void print(std::ostream &out) const;
354 virtual void dump() const;
355
357 // Repeat of the above ignored friend directive.
358 //
359 // Persistent (structurally shared) like level1's map. clone() snapshots
360 // this map at every branch for the later merge; a std::unordered_map would
361 // deep-copy there, O(tracked names) per branch and so symex quadratic on
362 // branch-heavy inputs. The immer HAMT makes the snapshot O(1) and lets
363 // phi_function diff two states in O(divergence).
365
367};
368
369} // namespace renaming
370
371#endif /* _GOTO_SYMEX_RENAMING_H_ */
Definition irep_idt.h:12
unsigned get_no() const
Definition irep_idt.h:167
Definition namespace.h:10
Persistent (structurally shared) map with O(1) copy.
Definition persistent_map.h:31
Definition renaming.h:42
name_record(const symbol2t &sym)
Definition renaming.h:48
name_record()
Definition renaming.h:44
int compare(const name_record &ref) const
Definition renaming.h:56
bool operator<(const name_record &ref) const
Definition renaming.h:66
irep_idt base_name
Definition renaming.h:80
bool operator==(const name_record &ref) const
Definition renaming.h:73
name_record(const irep_idt &name)
Definition renaming.h:52
Definition renaming.h:147
bool operator<(const name_record &ref) const
Definition renaming.h:193
irep_idt base_name
Definition renaming.h:207
int compare(const name_record &ref) const
Definition renaming.h:163
name_record()
Definition renaming.h:149
symbol2t::renaming_level lev
Definition renaming.h:208
bool operator==(const name_record &ref) const
Definition renaming.h:200
size_t hash
Definition renaming.h:215
unsigned int t_num
Definition renaming.h:210
unsigned int l1_num
Definition renaming.h:209
name_record(const symbol2t &sym)
Definition renaming.h:154
Symbol type.
Definition irep2_expr.h:625
symbol_renaming_level renaming_level
Definition irep2_expr.h:627
Definition toml.hpp:1531
int count
Definition cuda.h:51
bool is_nil_expr(const expr2tc &exp)
Definition irep2.h:916
irep_container< expr2t > expr2tc
Definition irep2.h:431
@ level1
Definition irep2_expr.h:56
@ level0
Definition irep2_expr.h:55
void hash_combine(std::size_t &seed, const T &v)
Mix a value into a running hash seed.
Definition irep2.h:111
Definition renaming.h:16
static exprt assigned_value(exprt rhs, const symbol_exprt &lhs)
Definition st_fb_translator.cpp:339
Definition renaming.h:86
bool operator()(const name_record &ref, const name_record &ref2) const
Definition renaming.h:92
size_t operator()(const name_record &ref) const
Definition renaming.h:87
void rename(expr2tc &expr) override
Definition renaming.cpp:96
~level1t() override=default
virtual void print(std::ostream &out) const
Definition renaming.cpp:361
void remove(const expr2tc &symbol) override
Definition renaming.h:108
persistent_map< name_record, unsigned, name_rec_hash > current_namest
Definition renaming.h:98
unsigned int current_number(const irep_idt &name) const
Definition renaming.cpp:37
void rename(const expr2tc &symbol, unsigned frame)
Definition renaming.h:113
void get_ident_name(expr2tc &symbol) const override
Definition renaming.cpp:43
unsigned int thread_id
Definition renaming.h:100
current_namest current_names
Definition renaming.h:99
void get_original_name(expr2tc &expr) const override
Definition renaming.h:124
const namespacet * ns
Definition renaming.h:104
Definition renaming.h:230
size_t operator()(const name_record &ref) const
Definition renaming.h:231
bool operator()(const name_record &ref, const name_record &ref2) const
Definition renaming.h:236
Definition renaming.h:244
bool operator==(const valuet &v) const
Definition renaming.h:253
unsigned node_id
Definition renaming.h:247
expr2tc constant
Definition renaming.h:246
valuet()
Definition renaming.h:248
unsigned count
Definition renaming.h:245
bool operator!=(const valuet &v) const
Definition renaming.h:257
void retire(const name_record &rec)
Retire a name whose storage has gone out of scope.
Definition renaming.h:295
virtual void rename(expr2tc &expr, unsigned count)=0
void set_constant(const name_record &rec, const expr2tc &value)
Complete an assignment make_assignment has just made, whose value only its caller can build: #7597 re...
Definition renaming.h:325
virtual void print(std::ostream &out) const
Definition renaming.cpp:368
persistent_map< name_record, valuet, name_rec_hash > current_namest
Definition renaming.h:364
void get_ident_name(expr2tc &symbol) const override
Definition renaming.cpp:71
virtual void make_assignment(expr2tc &lhs_symbol, const expr2tc &constant_value, const expr2tc &assigned_value)
Definition renaming.cpp:402
friend void build_goto_symex_classes()
void remove(const expr2tc &symbol) override
Definition renaming.h:273
valuet current_value(const name_record &rec) const
Get-or-default then re-store: the persistent map hands out immutable values, so a "modify the entry i...
Definition renaming.h:281
virtual void coveredinbees(expr2tc &lhs_sym, unsigned count, unsigned node_id)
Definition renaming.cpp:229
virtual void dump() const
Definition renaming.cpp:395
unsigned current_number(const expr2tc &sym) const
Definition renaming.cpp:26
void rename(expr2tc &expr) override
Definition renaming.cpp:155
void get_original_name(expr2tc &expr) const override
Definition renaming.h:315
static void rename_to_record(expr2tc &sym, const name_record &rec)
Definition renaming.cpp:447
void declare(const name_record &rec)
Record rec at its initial version.
Definition renaming.h:309
~level2t() override=default
current_namest current_names
Definition renaming.h:366
virtual std::shared_ptr< level2t > clone() const =0
Definition renaming.h:18
virtual ~renaming_levelt()=default
virtual void remove(const expr2tc &symbol)=0
virtual void get_ident_name(expr2tc &symbol) const =0
friend void build_goto_symex_classes()
virtual void rename(expr2tc &expr)=0
virtual void get_original_name(expr2tc &expr) const =0
#define SYMEX_INVARIANT(condition, reason)
Definition symex_invariant.h:18