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 (via merge_goto) once it reaches a
40
+ // / control-flow graph convergence.
34
41
class goto_symex_statet final
35
42
{
36
43
public:
@@ -54,6 +61,11 @@ 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;
@@ -72,13 +84,40 @@ class goto_symex_statet final
72
84
symex_level1t level1;
73
85
symex_level2t level2;
74
86
75
- // 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 possible 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.
76
94
std::map<irep_idt, exprt> propagation;
77
95
void output_propagation_map (std::ostream &);
78
96
97
+ // Symex renaming levels.
79
98
enum levelt { L0=0 , L1=1 , L2=2 };
80
99
81
- // performs renaming _up to_ the given level
100
+ // / Rewrites symbol expressions in \ref exprt, applying a suffix to each
101
+ // / symbol reflecting its most recent version, which differs depending on
102
+ // / which level you requested. Each level also updates its predecessors, so
103
+ // / a L1 rename will update L1 and L0. A L2 will update L2, L1 and L0.
104
+ // /
105
+ // / What happens at each level:
106
+ // / L0. Applies a suffix giving the current thread number. (Excludes
107
+ // / guards, dynamic objects and anything not considered thread-local)
108
+ // / L1. Applies a suffix giving the current loop iteration or recursive
109
+ // / function invocation.
110
+ // / L2. Applies a suffix giving the generation of this variable.
111
+ // /
112
+ // / Renaming will not increment any of these values, just update the
113
+ // / expression with them. Levels matter when reading a variable, for
114
+ // / example: reading the value of x really means reading the particular x
115
+ // / symbol for this thread (L0 renaming, if applicable), the most recent
116
+ // / instance of x (L1 renaming), and the most recent write to x (L2 renaming).
117
+ // /
118
+ // / The above example after being renamed could look like this: 'x!0@0#42'.
119
+ // / That states it's the 42nd generation of this variable, on the first
120
+ // / thread, in the first frame.
82
121
void rename (exprt &expr, const namespacet &ns, levelt level=L2);
83
122
void rename (
84
123
typet &type,
@@ -100,8 +139,13 @@ class goto_symex_statet final
100
139
protected:
101
140
void rename_address (exprt &expr, const namespacet &ns, levelt level);
102
141
142
+ // / Update level 0 values.
103
143
void set_l0_indices (ssa_exprt &expr, const namespacet &ns);
144
+
145
+ // / Update level 0 and 1 values.
104
146
void set_l1_indices (ssa_exprt &expr, const namespacet &ns);
147
+
148
+ // / Update level 0, 1 and 2 values.
105
149
void set_l2_indices (ssa_exprt &expr, const namespacet &ns);
106
150
107
151
// this maps L1 names to (L2) types
@@ -115,6 +159,10 @@ class goto_symex_statet final
115
159
// do dereferencing
116
160
value_sett value_set;
117
161
162
+ // / Container for data that varies per program point, e.g. the constant
163
+ // / propagator state, when state needs to branch. This is copied out of
164
+ // / goto_symex_statet at a control-flow fork and then back into it at a
165
+ // / control-flow merge.
118
166
class goto_statet
119
167
{
120
168
public:
@@ -273,6 +321,9 @@ class goto_symex_statet final
273
321
bool l2_thread_write_encoding (const ssa_exprt &expr, const namespacet &ns);
274
322
275
323
bool record_events;
324
+
325
+ // Local variables are considered 'dirty' if they've had an address taken and
326
+ // therefore may be referred to by a pointer.
276
327
incremental_dirtyt dirty;
277
328
278
329
goto_programt::const_targett saved_target;
0 commit comments