@@ -12,6 +12,15 @@ Date: February 2013
12
12
// / \file
13
13
// / Range-based reaching definitions analysis (following Field- Sensitive
14
14
// / Program Dependence Analysis, Litvak et al., FSE 2010)
15
+ // /
16
+ // / This module implements the reaching definitions data-flow analysis
17
+ // / (see https://en.wikipedia.org/wiki/Reaching_definition for basic
18
+ // / introduction) on multi-threaded GOTO programs.
19
+ // /
20
+ // / The domain element is defined in a class `rd_range_domaint` and the actual
21
+ // / analysis is implemented in a class `reaching_definitions_analysist`. Beside
22
+ // / these classes there are more data structures necessary in the computation.
23
+ // / We discuss all of them in the following sub-sections.
15
24
16
25
#ifndef CPROVER_ANALYSES_REACHING_DEFINITIONS_H
17
26
#define CPROVER_ANALYSES_REACHING_DEFINITIONS_H
@@ -27,7 +36,9 @@ class is_threadedt;
27
36
class dirtyt ;
28
37
class reaching_definitions_analysist ;
29
38
30
- // requirement: V has a member "identifier" of type irep_idt
39
+ // / An instance of this class provides an assignment of unique numeric `ID` to
40
+ // / each inserted `reaching_definitiont` instance.
41
+ // / Requirement: V has a member "identifier" of type irep_idt
31
42
template <typename V>
32
43
class sparse_bitvector_analysist
33
44
{
@@ -59,18 +70,36 @@ class sparse_bitvector_analysist
59
70
60
71
protected:
61
72
typedef typename std::map<V, std::size_t > inner_mapt;
73
+ // / It is a map from an `ID` to the corresponding `reaching_definitiont`
74
+ // / instance inside the map `value_map`. Namely, the map is implemented as an
75
+ // / `std::vector` of iterators to elements of the map `value_map`. An index to
76
+ // / this vector is the `ID` of the related `reaching_definitiont` instance.
62
77
std::vector<typename inner_mapt::const_iterator> values;
78
+ // / A map from names of program variables to a set of pairs
79
+ // / (`reaching_definitiont`, `ID`). Formally, the map is defined as
80
+ // / `value_map: var_names -> (reaching_definitiont -> ID)`.
63
81
std::unordered_map<irep_idt, inner_mapt> value_map;
64
82
};
65
83
84
+ // / Identifies a GOTO instruction where a given variable is defined (i.e. it is
85
+ // / set to a certain value). It consists of these data:
66
86
struct reaching_definitiont
67
87
{
88
+ // / The name of the variable which was defined.
68
89
irep_idt identifier;
90
+ // / The iterator to the GOTO instruction where the variable has been written to.
69
91
ai_domain_baset::locationt definition_at;
92
+ // / The two integers below define a range of bits (i.e. the begin and end bit
93
+ // / indices) which represent the value of the variable. So, the integers
94
+ // / represents the half-open interval `[bit_begin, bit_end)` of bits.
95
+ // / However, `bit_end` can also be set a special value `-1`, which means
96
+ // / infinite/unknown index.
70
97
range_spect bit_begin;
71
98
range_spect bit_end;
72
99
};
73
100
101
+ // / In order to use instances of this structure as keys in ordered containers,
102
+ // / such as std::map, an ordering is defined.
74
103
inline bool operator <(
75
104
const reaching_definitiont &a,
76
105
const reaching_definitiont &b)
@@ -97,6 +126,12 @@ inline bool operator<(
97
126
return false ;
98
127
}
99
128
129
+ // / Because the class is inherited from `ai_domain_baset`, its instance
130
+ // / represents an element of a domain of the reaching definitions abstract
131
+ // / interpretation analysis. Each instance is thus associated with exactly one
132
+ // / instruction in an analysed GOTO program. And so, the instance holds
133
+ // / information for individual program variables about their reaching
134
+ // / definitions, at that instruction.
100
135
class rd_range_domaint :public ai_domain_baset
101
136
{
102
137
public:
@@ -113,6 +148,18 @@ class rd_range_domaint:public ai_domain_baset
113
148
bv_container=&_bv_container;
114
149
}
115
150
151
+ // / Computes an instance obtained from the instance `*this` by transformation
152
+ // / over a GOTO instruction referenced by `from`. The method implements a
153
+ // / switch according to a type of the instruction and then calls a dedicated
154
+ // / transform_*` method for the recognised instruction.
155
+ // / \param function_from: Just passed to `transform_function_call` and
156
+ // / `transform_end_function` callees.
157
+ // / \param from: Reference to a GOTO instruction according to which `*this`
158
+ // / instance should be transformed.
159
+ // / \param function_to: Just passed to `transform_function_call` callee.
160
+ // / \param to: Just passed to `transform_end_function` callee.
161
+ // / \param ai: A reference to 'reaching_definitions_analysist' instance.
162
+ // / \param ns: Just passed to callees.
116
163
void transform (
117
164
const irep_idt &function_from,
118
165
locationt from,
@@ -164,7 +211,18 @@ class rd_range_domaint:public ai_domain_baset
164
211
return has_values.is_false ();
165
212
}
166
213
167
- // returns true iff there is something new
214
+ // / Implements the `join` operation of two instances `*this` and other`. It
215
+ // / operates only on `this->values` and `other.values`. The keys in the
216
+ // / resulting map is the union of variable names in both `this->values` and
217
+ // / `other.values`. And for each variable `v` appearing in both maps
218
+ // / `this->values` and `other.values` the resulting mapped set
219
+ // / of `ID`s is the set union of `this->values[v]` and `other.values[v]`.
220
+ // / NOTE: The operation actually does not produce a new `join` element. The
221
+ // / instance `*this` is modified to become the `join` element.
222
+ // / \param other: The instance to be merged into `*this` as the join operation
223
+ // / \param from: Not used at all.
224
+ // / \param to: Not used at all.
225
+ // / \return Returns true iff there is something new
168
226
bool merge (
169
227
const rd_range_domaint &other,
170
228
locationt from,
@@ -187,8 +245,18 @@ class rd_range_domaint:public ai_domain_baset
187
245
}
188
246
189
247
private:
248
+ // / This (three value logic) flag determines, whether the instance represents
249
+ // / `top`, `bottom`, or any other element of the lattice, by values `TRUE`,
250
+ // / `FALSE`, and `UNKNOWN` respectively. Initially it is set to `FALSE`.
190
251
tvt has_values;
191
252
253
+ // / It points to the actual reaching definitions data of individual program
254
+ // / variables. This pointer is initially `nullptr` and it is later set (by
255
+ // / `reaching_definitions_analysist` instance using the method
256
+ // / `set_bitvector_container`) to a valid pointer, which is actually shared by
257
+ // / all `rd_range_domaint` instances. NOTE: `reaching_definitions_analysist`
258
+ // / inherits from `sparse_bitvector_analysist<reaching_definitiont>` and so
259
+ // / `this` is passed to `set_bitvector_container` for all instances.
192
260
sparse_bitvector_analysist<reaching_definitiont> *bv_container;
193
261
194
262
typedef std::set<std::size_t > values_innert;
@@ -197,13 +265,29 @@ class rd_range_domaint:public ai_domain_baset
197
265
#else
198
266
typedef std::unordered_map<irep_idt, values_innert> valuest;
199
267
#endif
268
+ // / It is an ordered map from program variable names to `ID`s of
269
+ // / `reaching_definitiont` instances stored in map pointed to by
270
+ // / `bv_container`. The map is not empty only if `has_value` is `UNKNOWN`.
271
+ // / Variables in the map are all those which are live at the associated
272
+ // / instruction.
200
273
valuest values;
201
274
202
275
#ifdef USE_DSTRING
203
276
typedef std::map<irep_idt, ranges_at_loct> export_cachet;
204
277
#else
205
278
typedef std::unordered_map<irep_idt, ranges_at_loct> export_cachet;
206
279
#endif
280
+ // / It is a helper data structure. It consists of data already stored in
281
+ // / `values` and `bv_container`. It is basically (an ordered) map from (a
282
+ // / subset of) variables in `values` to iterators to GOTO instructions where
283
+ // / the variables are defined. Moreover, each such iterator is also
284
+ // / associated with a range of bits defining the value of that variable at
285
+ // / that GOTO instruction. Both the iterators and the corresponding bit ranges
286
+ // / are simply taken from `reaching_definitiont` instances obtained for `ID`s
287
+ // / in `values[var_name]`. This data structure is actually used only in the
288
+ // / `output` method; other methods only remove outdated data from it. Since
289
+ // / the cache does not contribute to the computation, it should be either
290
+ // / moved to the `output` method or removed entirely.
207
291
mutable export_cachet export_cache;
208
292
209
293
void populate_cache (const irep_idt &identifier) const ;
0 commit comments