Skip to content

Commit 2d5d8f9

Browse files
author
owen-jones-diffblue
authored
Merge pull request diffblue#3413 from owen-jones-diffblue/doc/abstract-interpretation
DOC-50: Add some documentation to abstract interpretation
2 parents f4e6fbf + 756279a commit 2d5d8f9

File tree

4 files changed

+107
-44
lines changed

4 files changed

+107
-44
lines changed

src/analyses/ai.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,6 @@ void ai_baset::output(
6060
}
6161
}
6262

63-
/// Output the domains for the whole program as JSON
64-
/// \par parameters: The namespace and goto_functions
65-
/// \return The JSON object
6663
jsont ai_baset::output_json(
6764
const namespacet &ns,
6865
const goto_functionst &goto_functions) const
@@ -86,7 +83,10 @@ jsont ai_baset::output_json(
8683
}
8784

8885
/// Output the domains for a single function as JSON
89-
/// \par parameters: The namespace, goto_program and it's identifier
86+
/// \param ns: The namespace
87+
/// \param goto_program: The goto program
88+
/// \param identifier: The identifier used to find a symbol to identify the
89+
/// source language
9090
/// \return The JSON object
9191
jsont ai_baset::output_json(
9292
const namespacet &ns,
@@ -116,9 +116,6 @@ jsont ai_baset::output_json(
116116
return std::move(contents);
117117
}
118118

119-
/// Output the domains for the whole program as XML
120-
/// \par parameters: The namespace and goto_functions
121-
/// \return The XML object
122119
xmlt ai_baset::output_xml(
123120
const namespacet &ns,
124121
const goto_functionst &goto_functions) const
@@ -145,7 +142,10 @@ xmlt ai_baset::output_xml(
145142
}
146143

147144
/// Output the domains for a single function as XML
148-
/// \par parameters: The namespace, goto_program and it's identifier
145+
/// \param ns: The namespace
146+
/// \param goto_program: The goto program
147+
/// \param identifier: The identifier used to find a symbol to identify the
148+
/// source language
149149
/// \return The XML object
150150
xmlt ai_baset::output_xml(
151151
const namespacet &ns,
@@ -341,7 +341,7 @@ bool ai_baset::do_function_call(
341341

342342
if(!goto_function.body_available())
343343
{
344-
// if we don't have a body, we just do an edige call -> return
344+
// If we don't have a body, we just do an edge call -> return
345345
std::unique_ptr<statet> tmp_state(make_temporary_state(get_state(l_call)));
346346
tmp_state->transform(
347347
calling_function_identifier,

src/analyses/ai.h

Lines changed: 94 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ Author: Daniel Kroening, [email protected]
2525

2626
#include "ai_domain.h"
2727

28-
/// The basic interface of an abstract interpreter. This should be enough
28+
/// The basic interface of an abstract interpreter. This should be enough
2929
/// to create, run and query an abstract interpreter.
30-
// don't use me -- I am just a base class
31-
// use ait instead
30+
///
31+
/// Note: this is just a base class. \ref ait should be used instead.
3232
class ai_baset
3333
{
3434
public:
@@ -43,7 +43,7 @@ class ai_baset
4343
{
4444
}
4545

46-
/// Running the interpreter
46+
/// Run abstract interpretation on a single function
4747
void operator()(
4848
const irep_idt &function_identifier,
4949
const goto_programt &goto_program,
@@ -56,6 +56,7 @@ class ai_baset
5656
finalize();
5757
}
5858

59+
/// Run abstract interpretation on a whole program
5960
void operator()(
6061
const goto_functionst &goto_functions,
6162
const namespacet &ns)
@@ -66,6 +67,7 @@ class ai_baset
6667
finalize();
6768
}
6869

70+
/// Run abstract interpretation on a whole program
6971
void operator()(const goto_modelt &goto_model)
7072
{
7173
const namespacet ns(goto_model.symbol_table);
@@ -75,6 +77,7 @@ class ai_baset
7577
finalize();
7678
}
7779

80+
/// Run abstract interpretation on a single function
7881
void operator()(
7982
const irep_idt &function_identifier,
8083
const goto_functionst::goto_functiont &goto_function,
@@ -87,17 +90,27 @@ class ai_baset
8790
finalize();
8891
}
8992

90-
/// Accessing individual domains at particular locations
91-
/// (without needing to know what kind of domain or history is used)
92-
/// A pointer to a copy as the method should be const and
93-
/// there are some non-trivial cases including merging domains, etc.
94-
/// Intended for users of the abstract interpreter; don't use internally.
95-
96-
/// Returns the abstract state before the given instruction
93+
/// Get a copy of the abstract state before the given instruction, without
94+
/// needing to know what kind of domain or history is used. Note: intended
95+
/// for users of the abstract interpreter; derived classes should
96+
/// use \ref get_state or \ref find_state to access the actual underlying
97+
/// state.
9798
/// PRECONDITION(l is dereferenceable)
99+
/// \param l: The location before which we want the abstract state
100+
/// \return The abstract state before `l`. We return a pointer to a copy as
101+
/// the method should be const and there are some non-trivial cases
102+
/// including merging abstract states, etc.
98103
virtual std::unique_ptr<statet> abstract_state_before(locationt l) const = 0;
99104

100-
/// Returns the abstract state after the given instruction
105+
/// Get a copy of the abstract state after the given instruction, without
106+
/// needing to know what kind of domain or history is used. Note: intended
107+
/// for users of the abstract interpreter; derived classes should
108+
/// use \ref get_state or \ref find_state to access the actual underlying
109+
/// state.
110+
/// \param l: The location before which we want the abstract state
111+
/// \return The abstract state after `l`. We return a pointer to a copy as
112+
/// the method should be const and there are some non-trivial cases
113+
/// including merging abstract states, etc.
101114
virtual std::unique_ptr<statet> abstract_state_after(locationt l) const
102115
{
103116
/// PRECONDITION(l is dereferenceable && std::next(l) is dereferenceable)
@@ -106,16 +119,18 @@ class ai_baset
106119
return abstract_state_before(std::next(l));
107120
}
108121

109-
/// Resets the domain
122+
/// Reset the abstract state
110123
virtual void clear()
111124
{
112125
}
113126

127+
/// Output the abstract states for a whole program
114128
virtual void output(
115129
const namespacet &ns,
116130
const goto_functionst &goto_functions,
117131
std::ostream &out) const;
118132

133+
/// Output the abstract states for a whole program
119134
void output(
120135
const goto_modelt &goto_model,
121136
std::ostream &out) const
@@ -124,6 +139,7 @@ class ai_baset
124139
output(ns, goto_model.goto_functions, out);
125140
}
126141

142+
/// Output the abstract states for a function
127143
void output(
128144
const namespacet &ns,
129145
const goto_programt &goto_program,
@@ -132,6 +148,7 @@ class ai_baset
132148
output(ns, goto_program, "", out);
133149
}
134150

151+
/// Output the abstract states for a function
135152
void output(
136153
const namespacet &ns,
137154
const goto_functionst::goto_functiont &goto_function,
@@ -140,51 +157,57 @@ class ai_baset
140157
output(ns, goto_function.body, "", out);
141158
}
142159

143-
160+
/// Output the abstract states for the whole program as JSON
144161
virtual jsont output_json(
145162
const namespacet &ns,
146163
const goto_functionst &goto_functions) const;
147164

165+
/// Output the abstract states for a whole program as JSON
148166
jsont output_json(
149167
const goto_modelt &goto_model) const
150168
{
151169
const namespacet ns(goto_model.symbol_table);
152170
return output_json(ns, goto_model.goto_functions);
153171
}
154172

173+
/// Output the abstract states for a single function as JSON
155174
jsont output_json(
156175
const namespacet &ns,
157176
const goto_programt &goto_program) const
158177
{
159178
return output_json(ns, goto_program, "");
160179
}
161180

181+
/// Output the abstract states for a single function as JSON
162182
jsont output_json(
163183
const namespacet &ns,
164184
const goto_functionst::goto_functiont &goto_function) const
165185
{
166186
return output_json(ns, goto_function.body, "");
167187
}
168188

169-
189+
/// Output the abstract states for the whole program as XML
170190
virtual xmlt output_xml(
171191
const namespacet &ns,
172192
const goto_functionst &goto_functions) const;
173193

194+
/// Output the abstract states for the whole program as XML
174195
xmlt output_xml(
175196
const goto_modelt &goto_model) const
176197
{
177198
const namespacet ns(goto_model.symbol_table);
178199
return output_xml(ns, goto_model.goto_functions);
179200
}
180201

202+
/// Output the abstract states for a single function as XML
181203
xmlt output_xml(
182204
const namespacet &ns,
183205
const goto_programt &goto_program) const
184206
{
185207
return output_xml(ns, goto_program, "");
186208
}
187209

210+
/// Output the abstract states for a single function as XML
188211
xmlt output_xml(
189212
const namespacet &ns,
190213
const goto_functionst::goto_functiont &goto_function) const
@@ -193,37 +216,67 @@ class ai_baset
193216
}
194217

195218
protected:
196-
// overload to add a factory
197-
virtual void initialize(const goto_programt &);
198-
virtual void initialize(const goto_functionst::goto_functiont &);
199-
virtual void initialize(const goto_functionst &);
219+
/// Initialize all the abstract states for a single function. Override this to
220+
/// do custom per-domain initialization.
221+
virtual void initialize(const goto_programt &goto_program);
222+
223+
/// Initialize all the abstract states for a single function.
224+
virtual void initialize(const goto_functionst::goto_functiont &goto_function);
225+
226+
/// Initialize all the abstract states for a whole program. Override this to
227+
/// do custom per-analysis initialization.
228+
virtual void initialize(const goto_functionst &goto_functions);
200229

201-
// override to add a cleanup step after fixedpoint has run
230+
/// Override this to add a cleanup or post-processing step after fixedpoint
231+
/// has run
202232
virtual void finalize();
203233

204-
void entry_state(const goto_programt &);
205-
void entry_state(const goto_functionst &);
234+
/// Set the abstract state of the entry location of a single function to the
235+
/// entry state required by the analysis
236+
void entry_state(const goto_programt &goto_program);
206237

238+
/// Set the abstract state of the entry location of a whole program to the
239+
/// entry state required by the analysis
240+
void entry_state(const goto_functionst &goto_functions);
241+
242+
/// Output the abstract states for a single function
243+
/// \param ns: The namespace
244+
/// \param goto_program: The goto program
245+
/// \param identifier: The identifier used to find a symbol to identify the
246+
/// source language
247+
/// \param out: The ostream to direct output to
207248
virtual void output(
208249
const namespacet &ns,
209250
const goto_programt &goto_program,
210251
const irep_idt &identifier,
211252
std::ostream &out) const;
212253

254+
/// Output the abstract states for a single function as JSON
255+
/// \param ns: The namespace
256+
/// \param goto_program: The goto program
257+
/// \param identifier: The identifier used to find a symbol to identify the
258+
/// source language
259+
/// \return The JSON object
213260
virtual jsont output_json(
214261
const namespacet &ns,
215262
const goto_programt &goto_program,
216263
const irep_idt &identifier) const;
217264

265+
/// Output the abstract states for a single function as XML
266+
/// \param ns: The namespace
267+
/// \param goto_program: The goto program
268+
/// \param identifier: The identifier used to find a symbol to identify the
269+
/// source language
270+
/// \return The XML object
218271
virtual xmlt output_xml(
219272
const namespacet &ns,
220273
const goto_programt &goto_program,
221274
const irep_idt &identifier) const;
222275

223-
224-
// the work-queue is sorted by location number
276+
/// The work queue, sorted by location number
225277
typedef std::map<unsigned, locationt> working_sett;
226278

279+
/// Get the next location from the work queue
227280
locationt get_next(working_sett &working_set);
228281

229282
void put_in_working_set(
@@ -234,7 +287,8 @@ class ai_baset
234287
std::pair<unsigned, locationt>(l->location_number, l));
235288
}
236289

237-
// true = found something new
290+
/// Run the fixedpoint algorithm until it reaches a fixed point
291+
/// \return True if we found something new
238292
bool fixedpoint(
239293
const irep_idt &function_identifier,
240294
const goto_programt &goto_program,
@@ -253,10 +307,10 @@ class ai_baset
253307
const goto_functionst &goto_functions,
254308
const namespacet &ns);
255309

256-
// Visit performs one step of abstract interpretation from location l
257-
// Depending on the instruction type it may compute a number of "edges"
258-
// or applications of the abstract transformer
259-
// true = found something new
310+
/// Perform one step of abstract interpretation from location l
311+
/// Depending on the instruction type it may compute a number of "edges"
312+
/// or applications of the abstract transformer
313+
/// \return True if the state was changed
260314
bool visit(
261315
const irep_idt &function_identifier,
262316
locationt l,
@@ -293,8 +347,16 @@ class ai_baset
293347
locationt from,
294348
locationt to,
295349
const namespacet &ns)=0;
350+
351+
/// Get the state for the given location, creating it in a default way if it
352+
/// doesn't exist
296353
virtual statet &get_state(locationt l)=0;
354+
355+
/// Get the state for the given location if it already exists; throw an
356+
/// exception if it doesn't
297357
virtual const statet &find_state(locationt l) const=0;
358+
359+
/// Make a copy of a state
298360
virtual std::unique_ptr<statet> make_temporary_state(const statet &s)=0;
299361
};
300362

@@ -389,10 +451,11 @@ class ait:public ai_baset
389451
}
390452

391453
private:
392-
// to enforce that domainT is derived from ai_domain_baset
454+
/// This function exists to enforce that `domainT` is derived from
455+
/// \ref ai_domain_baset
393456
void dummy(const domainT &s) { const statet &x=s; (void)x; }
394457

395-
// not implemented in sequential analyses
458+
/// This function should not be implemented in sequential analyses
396459
bool merge_shared(const statet &, locationt, locationt, const namespacet &)
397460
override
398461
{

src/analyses/ai_domain.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ xmlt ai_domain_baset::output_xml(const ai_baset &ai, const namespacet &ns) const
3535
/// an assignment. This for example won't simplify symbols to their values, but
3636
/// does simplify indices in arrays, members of structs and dereferencing of
3737
/// pointers
38-
/// \param condition: the expression to simplify
39-
/// \param ns: the namespace
38+
/// \param condition: The expression to simplify
39+
/// \param ns: The namespace
4040
/// \return True if condition did not change. False otherwise. condition will be
4141
/// updated with the simplified condition if it has worked
4242
bool ai_domain_baset::ai_simplify_lhs(exprt &condition, const namespacet &ns)

src/analyses/ai_domain.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class ai_domain_baset
4646
/// (this also needs to set the LHS, if applicable)
4747
///
4848
/// "this" is the domain before the instruction "from"
49-
/// "from" is the instruction to be interpretted
49+
/// "from" is the instruction to be interpreted
5050
/// "to" is the next instruction (for GOTO, FUNCTION_CALL, END_FUNCTION)
5151
///
5252
/// PRECONDITION(from.is_dereferenceable(), "Must not be _::end()")
@@ -78,7 +78,7 @@ class ai_domain_baset
7878
/// and domains may refuse to implement it.
7979
virtual void make_top() = 0;
8080

81-
/// a reasonable entry-point state
81+
/// Make this domain a reasonable entry-point state
8282
virtual void make_entry() = 0;
8383

8484
virtual bool is_bottom() const = 0;

0 commit comments

Comments
 (0)