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,59 @@ 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 loop ID,
78
+ // and L2 relates to generation ID.
79
+ //
80
+ // If looking at the VCC they are shown as !{threadID}@{loopID}#{generationID}
81
+ // on the end of a variables name.
64
82
symex_level0t level0;
65
83
symex_level1t level1;
66
84
symex_level2t level2;
67
85
68
- // Map L1 names to (L2) constants
86
+ // Map L1 names to (L2) constants. Values will be evicted from this map
87
+ // when they become non-constant. This is used to propagate values that have
88
+ // been worked out to only have one viable value.
89
+ //
90
+ // "constants" can include symbols, but only in the context of an address-of
91
+ // op (i.e. &x can be propagated), and an address-taken thing should only be
92
+ // L1. Actual integer literals (for example) aren't symbols, and so aren't
93
+ // L-anything.
69
94
std::map<irep_idt, exprt> propagation;
70
95
void output_propagation_map (std::ostream &);
71
96
97
+ // Symex renaming levels.
72
98
enum levelt { L0=0 , L1=1 , L2=2 };
73
99
74
- // 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 latest 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).
75
117
void rename (exprt &expr, const namespacet &ns, levelt level=L2);
76
118
void rename (
77
119
typet &type,
@@ -93,8 +135,13 @@ class goto_symex_statet final
93
135
protected:
94
136
void rename_address (exprt &expr, const namespacet &ns, levelt level);
95
137
138
+ // / Update level 0 values.
96
139
void set_l0_indices (ssa_exprt &expr, const namespacet &ns);
140
+
141
+ // / Update level 0 and 1 values.
97
142
void set_l1_indices (ssa_exprt &expr, const namespacet &ns);
143
+
144
+ // / Update level 0, 1 and 2 values.
98
145
void set_l2_indices (ssa_exprt &expr, const namespacet &ns);
99
146
100
147
// this maps L1 names to (L2) types
@@ -108,6 +155,10 @@ class goto_symex_statet final
108
155
// do dereferencing
109
156
value_sett value_set;
110
157
158
+ // / Container for data that varies per program point, e.g. the constant
159
+ // / propagator state, when state needs to branch. This is copied out of
160
+ // / goto_symex_statet at a control-flow fork and then back into it (at some
161
+ // / point) and not the other way around.
111
162
class goto_statet
112
163
{
113
164
public:
@@ -266,6 +317,9 @@ class goto_symex_statet final
266
317
bool l2_thread_write_encoding (const ssa_exprt &expr, const namespacet &ns);
267
318
268
319
bool record_events;
320
+
321
+ // Local variables are considered 'dirty' if they've had an address taken and
322
+ // therefore may be referred to by a pointer.
269
323
incremental_dirtyt dirty;
270
324
271
325
goto_programt::const_targett saved_target;
0 commit comments