30
30
#include " renaming_level.h"
31
31
#include " symex_target_equation.h"
32
32
33
- // central data structure: state
33
+ // / Central data structure: state.
34
+
35
+ // / The state is a persistent data structure that symex maintains as it
36
+ // / executes. As we walk over each instruction, state will be updated reflecting
37
+ // / their effects until a branch occurs (such as an if), where parts of the
38
+ // / state will be copied into a \ref goto_statet, stored in a map for later
39
+ // / reference and then merged again once it reaches a control-flow graph
40
+ // / convergence.
34
41
class goto_symex_statet final
35
42
{
36
43
public:
@@ -54,24 +61,60 @@ class goto_symex_statet final
54
61
// / distance from entry
55
62
unsigned depth;
56
63
64
+ // A guard is a particular condition that has to pass for an instruction
65
+ // to be executed. The easiest example is an if/else: each instruction along
66
+ // the if branch will be guarded by the condition of the if (and if there
67
+ // is an else branch then instructions on it will be guarded by the negation
68
+ // of the condition of the if).
57
69
guardt guard{true_exprt{}};
58
70
symex_targett::sourcet source;
59
71
symex_target_equationt *symex_target;
60
72
61
73
// we remember all L1 renamings
62
74
std::set<irep_idt> l1_history;
63
75
76
+ // Objects which hold the separate renaming logic for each level that a
77
+ // symex variable can be on. L0 relates to thread ID, L1 relates to frame ID
78
+ // (the number of times a function has been called), and L2 relates to
79
+ // generation ID.
80
+ //
81
+ // If looking at the VCC they are shown as !{threadID}@{frameID}#{generationID}
82
+ // on the end of a variables name.
64
83
symex_level0t level0;
65
84
symex_level1t level1;
66
85
symex_level2t level2;
67
86
68
- // Map L1 names to (L2) constants
87
+ // Map L1 names to (L2) constants. Values will be evicted from this map
88
+ // when they become non-constant. This is used to propagate values that have
89
+ // been worked out to only have one viable value.
90
+ //
91
+ // "constants" can include symbols, but only in the context of an address-of
92
+ // op (i.e. &x can be propagated), and an address-taken thing should only be
93
+ // L1. Actual integer literals (for example) aren't symbols, and so aren't
94
+ // L-anything.
69
95
std::map<irep_idt, exprt> propagation;
70
96
void output_propagation_map (std::ostream &);
71
97
98
+ // Symex renaming levels.
72
99
enum levelt { L0=0 , L1=1 , L2=2 };
73
100
74
- // performs renaming _up to_ the given level
101
+ // / Rewrites symbol expressions in \ref exprt, applying a suffix to each
102
+ // / symbol reflecting its most recent version, which differs depending on
103
+ // / which level you requested. Each level also updates its predecessors, so
104
+ // / a L1 rename will update L1 and L0. A L2 will update L2, L1 and L0.
105
+ // /
106
+ // / What happens at each level:
107
+ // / L0. Applies a suffix giving the current thread number. (Excludes
108
+ // / guards, dynamic objects and anything not considered thread-local)
109
+ // / L1. Applies a suffix giving the current loop iteration or recursive
110
+ // / function invocation.
111
+ // / L2. Applies a suffix giving the latest generation of this variable.
112
+ // /
113
+ // / Renaming will not increment any of these values, just update the
114
+ // / expression with them. Levels matter when reading a variable, for
115
+ // / example: reading the value of x really means reading the particular x
116
+ // / symbol for this thread (L0 renaming, if applicable), the most recent
117
+ // / instance of x (L1 renaming), and the most recent write to x (L2 renaming).
75
118
void rename (exprt &expr, const namespacet &ns, levelt level=L2);
76
119
void rename (
77
120
typet &type,
@@ -93,8 +136,13 @@ class goto_symex_statet final
93
136
protected:
94
137
void rename_address (exprt &expr, const namespacet &ns, levelt level);
95
138
139
+ // / Update level 0 values.
96
140
void set_l0_indices (ssa_exprt &expr, const namespacet &ns);
141
+
142
+ // / Update level 0 and 1 values.
97
143
void set_l1_indices (ssa_exprt &expr, const namespacet &ns);
144
+
145
+ // / Update level 0, 1 and 2 values.
98
146
void set_l2_indices (ssa_exprt &expr, const namespacet &ns);
99
147
100
148
// this maps L1 names to (L2) types
@@ -108,6 +156,10 @@ class goto_symex_statet final
108
156
// do dereferencing
109
157
value_sett value_set;
110
158
159
+ // / Container for data that varies per program point, e.g. the constant
160
+ // / propagator state, when state needs to branch. This is copied out of
161
+ // / goto_symex_statet at a control-flow fork and then back into it (at some
162
+ // / point) and not the other way around.
111
163
class goto_statet
112
164
{
113
165
public:
@@ -266,6 +318,9 @@ class goto_symex_statet final
266
318
bool l2_thread_write_encoding (const ssa_exprt &expr, const namespacet &ns);
267
319
268
320
bool record_events;
321
+
322
+ // Local variables are considered 'dirty' if they've had an address taken and
323
+ // therefore may be referred to by a pointer.
269
324
incremental_dirtyt dirty;
270
325
271
326
goto_programt::const_targett saved_target;
0 commit comments