Skip to content

Commit 78fbf08

Browse files
authored
Merge pull request diffblue#1844 from smowton/smowton/feature/prepare-symex-for-lazy-loading
Prepare symex for lazy loading
2 parents 4098ed5 + e918a91 commit 78fbf08

File tree

9 files changed

+169
-48
lines changed

9 files changed

+169
-48
lines changed

src/analyses/dirty.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,14 @@ void dirtyt::output(std::ostream &out) const
7272
for(const auto &d : dirty)
7373
out << d << '\n';
7474
}
75+
76+
/// Analyse the given function with dirtyt if it hasn't been seen before
77+
/// \param id: function id to analyse
78+
/// \param function: function to analyse
79+
void incremental_dirtyt::populate_dirty_for_function(
80+
const irep_idt &id, const goto_functionst::goto_functiont &function)
81+
{
82+
auto insert_result = dirty_processed_functions.insert(id);
83+
if(insert_result.second)
84+
dirty.add_function(function);
85+
}

src/analyses/dirty.h

+32
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ class dirtyt
2525
typedef std::unordered_set<irep_idt, irep_id_hash> id_sett;
2626
typedef goto_functionst::goto_functiont goto_functiont;
2727

28+
dirtyt()
29+
{
30+
}
31+
2832
explicit dirtyt(const goto_functiont &goto_function)
2933
{
3034
build(goto_function);
@@ -53,6 +57,11 @@ class dirtyt
5357
return dirty;
5458
}
5559

60+
void add_function(const goto_functiont &goto_function)
61+
{
62+
build(goto_function);
63+
}
64+
5665
protected:
5766
void build(const goto_functiont &goto_function);
5867

@@ -71,4 +80,27 @@ inline std::ostream &operator<<(
7180
return out;
7281
}
7382

83+
/// Wrapper for dirtyt that permits incremental population, ensuring each
84+
/// function is analysed exactly once.
85+
class incremental_dirtyt
86+
{
87+
public:
88+
void populate_dirty_for_function(
89+
const irep_idt &id, const goto_functionst::goto_functiont &function);
90+
91+
bool operator()(const irep_idt &id) const
92+
{
93+
return dirty(id);
94+
}
95+
96+
bool operator()(const symbol_exprt &expr) const
97+
{
98+
return dirty(expr);
99+
}
100+
101+
private:
102+
dirtyt dirty;
103+
std::unordered_set<irep_idt, irep_id_hash> dirty_processed_functions;
104+
};
105+
74106
#endif // CPROVER_ANALYSES_DIRTY_H

src/cbmc/symex_bmc.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ symex_bmct::symex_bmct(
3131

3232
/// show progress
3333
void symex_bmct::symex_step(
34-
const goto_functionst &goto_functions,
34+
const get_goto_functiont &get_goto_function,
3535
statet &state)
3636
{
3737
const source_locationt &source_location=state.source.pc->source_location;
@@ -63,12 +63,12 @@ void symex_bmct::symex_step(
6363
log.statistics() << log.eom;
6464
}
6565

66-
goto_symext::symex_step(goto_functions, state);
66+
goto_symext::symex_step(get_goto_function, state);
6767

6868
if(record_coverage &&
6969
// avoid an invalid iterator in state.source.pc
7070
(!cur_pc->is_end_function() ||
71-
cur_pc->function!=goto_functions.entry_point()))
71+
cur_pc->function!=goto_functionst::entry_point()))
7272
{
7373
// forward goto will effectively be covered via phi function,
7474
// which does not invoke symex_step; as symex_step is called

src/cbmc/symex_bmc.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ class symex_bmct: public goto_symext
128128
// overloaded from goto_symext
129129
//
130130
virtual void symex_step(
131-
const goto_functionst &goto_functions,
131+
const get_goto_functiont &get_goto_function,
132132
statet &state);
133133

134134
virtual void merge_goto(

src/goto-symex/goto_symex.h

+48-9
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ class goto_symext
6767

6868
typedef goto_symex_statet statet;
6969

70+
typedef
71+
std::function<const goto_functionst::goto_functiont &(const irep_idt &)>
72+
get_goto_functiont;
73+
7074
/// \brief symex entire program starting from entry point
7175
///
7276
/// The state that goto_symext maintains has a large memory footprint.
@@ -76,6 +80,15 @@ class goto_symext
7680
virtual void symex_from_entry_point_of(
7781
const goto_functionst &goto_functions);
7882

83+
/// \brief symex entire program starting from entry point
84+
///
85+
/// The state that goto_symext maintains has a large memory footprint.
86+
/// This method deallocates the state as soon as symbolic execution
87+
/// has completed, so use it if you don't care about having the state
88+
/// around afterwards.
89+
virtual void symex_from_entry_point_of(
90+
const get_goto_functiont &get_goto_function);
91+
7992
//// \brief symex entire program starting from entry point
8093
///
8194
/// This method uses the `state` argument as the symbolic execution
@@ -88,6 +101,18 @@ class goto_symext
88101
const goto_functionst &,
89102
const goto_programt &);
90103

104+
//// \brief symex entire program starting from entry point
105+
///
106+
/// This method uses the `state` argument as the symbolic execution
107+
/// state, which is useful for examining the state after this method
108+
/// returns. The state that goto_symext maintains has a large memory
109+
/// footprint, so if keeping the state around is not necessary,
110+
/// clients should instead call goto_symext::symex_from_entry_point_of().
111+
virtual void symex_with_state(
112+
statet &,
113+
const get_goto_functiont &,
114+
const goto_programt &);
115+
91116
/// Symexes from the first instruction and the given state, terminating as
92117
/// soon as the last instruction is reached. This is useful to explicitly
93118
/// symex certain ranges of a program, e.g. in an incremental decision
@@ -102,6 +127,20 @@ class goto_symext
102127
goto_programt::const_targett first,
103128
goto_programt::const_targett limit);
104129

130+
/// Symexes from the first instruction and the given state, terminating as
131+
/// soon as the last instruction is reached. This is useful to explicitly
132+
/// symex certain ranges of a program, e.g. in an incremental decision
133+
/// procedure.
134+
/// \param state Symex state to start with.
135+
/// \param get_goto_function retrieves a function body
136+
/// \param first Entry point in form of a first instruction.
137+
/// \param limit Final instruction, which itself will not be symexed.
138+
virtual void symex_instruction_range(
139+
statet &state,
140+
const get_goto_functiont &get_goto_function,
141+
goto_programt::const_targett first,
142+
goto_programt::const_targett limit);
143+
105144
protected:
106145
/// Initialise the symbolic execution and the given state with <code>pc</code>
107146
/// as entry point.
@@ -111,21 +150,21 @@ class goto_symext
111150
/// \param limit final instruction, which itself will not
112151
/// be symexed.
113152
void initialize_entry_point(
114-
statet &,
115-
const goto_functionst &,
153+
statet &state,
154+
const get_goto_functiont &get_goto_function,
116155
goto_programt::const_targett pc,
117156
goto_programt::const_targett limit);
118157

119158
/// Invokes symex_step and verifies whether additional threads can be
120159
/// executed.
121160
/// \param state Current GOTO symex step.
122-
/// \param goto_functions GOTO model to symex.
161+
/// \param get_goto_function function that retrieves function bodies
123162
void symex_threaded_step(
124-
statet &, const goto_functionst &);
163+
statet &, const get_goto_functiont &);
125164

126165
/** execute just one step */
127166
virtual void symex_step(
128-
const goto_functionst &,
167+
const get_goto_functiont &,
129168
statet &);
130169

131170
public:
@@ -213,7 +252,7 @@ class goto_symext
213252
virtual void symex_decl(statet &);
214253
virtual void symex_decl(statet &, const symbol_exprt &expr);
215254
virtual void symex_dead(statet &);
216-
virtual void symex_other(const goto_functionst &, statet &);
255+
virtual void symex_other(statet &);
217256

218257
virtual void vcc(
219258
const exprt &,
@@ -255,19 +294,19 @@ class goto_symext
255294
}
256295

257296
virtual void symex_function_call(
258-
const goto_functionst &,
297+
const get_goto_functiont &,
259298
statet &,
260299
const code_function_callt &);
261300

262301
virtual void symex_end_of_function(statet &);
263302

264303
virtual void symex_function_call_symbol(
265-
const goto_functionst &,
304+
const get_goto_functiont &,
266305
statet &,
267306
const code_function_callt &);
268307

269308
virtual void symex_function_call_code(
270-
const goto_functionst &,
309+
const get_goto_functiont &,
271310
statet &,
272311
const code_function_callt &);
273312

src/goto-symex/goto_symex_state.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Author: Daniel Kroening, [email protected]
2626

2727
#include "symex_target.h"
2828

29-
class dirtyt;
29+
class incremental_dirtyt;
3030

3131
// central data structure: state
3232
class goto_symex_statet final
@@ -340,9 +340,12 @@ class goto_symex_statet final
340340
bool l2_thread_read_encoding(ssa_exprt &expr, const namespacet &ns);
341341
bool l2_thread_write_encoding(const ssa_exprt &expr, const namespacet &ns);
342342

343+
void populate_dirty_for_function(
344+
const irep_idt &id, const goto_functionst::goto_functiont &);
345+
343346
void switch_to_thread(unsigned t);
344347
bool record_events;
345-
std::unique_ptr<const dirtyt> dirty;
348+
std::unique_ptr<incremental_dirtyt> dirty;
346349
};
347350

348351
#endif // CPROVER_GOTO_SYMEX_GOTO_SYMEX_STATE_H

src/goto-symex/symex_function_call.cpp

+9-13
Original file line numberDiff line numberDiff line change
@@ -172,14 +172,14 @@ void goto_symext::parameter_assignments(
172172
}
173173

174174
void goto_symext::symex_function_call(
175-
const goto_functionst &goto_functions,
175+
const get_goto_functiont &get_goto_function,
176176
statet &state,
177177
const code_function_callt &code)
178178
{
179179
const exprt &function=code.function();
180180

181181
if(function.id()==ID_symbol)
182-
symex_function_call_symbol(goto_functions, state, code);
182+
symex_function_call_symbol(get_goto_function, state, code);
183183
else if(function.id()==ID_if)
184184
throw "symex_function_call can't do if";
185185
else if(function.id()==ID_dereference)
@@ -189,7 +189,7 @@ void goto_symext::symex_function_call(
189189
}
190190

191191
void goto_symext::symex_function_call_symbol(
192-
const goto_functionst &goto_functions,
192+
const get_goto_functiont &get_goto_function,
193193
statet &state,
194194
const code_function_callt &code)
195195
{
@@ -213,27 +213,23 @@ void goto_symext::symex_function_call_symbol(
213213
symex_macro(state, code);
214214
}
215215
else
216-
symex_function_call_code(goto_functions, state, code);
216+
symex_function_call_code(get_goto_function, state, code);
217217
}
218218

219219
/// do function call by inlining
220220
void goto_symext::symex_function_call_code(
221-
const goto_functionst &goto_functions,
221+
const get_goto_functiont &get_goto_function,
222222
statet &state,
223223
const code_function_callt &call)
224224
{
225225
const irep_idt &identifier=
226226
to_symbol_expr(call.function()).get_identifier();
227227

228-
// find code in function map
228+
const goto_functionst::goto_functiont &goto_function =
229+
get_goto_function(identifier);
229230

230-
goto_functionst::function_mapt::const_iterator it=
231-
goto_functions.function_map.find(identifier);
232-
233-
if(it==goto_functions.function_map.end())
234-
throw "failed to find `"+id2string(identifier)+"' in function_map";
235-
236-
const goto_functionst::goto_functiont &goto_function=it->second;
231+
if(state.dirty)
232+
state.dirty->populate_dirty_for_function(identifier, goto_function);
237233

238234
const bool stop_recursing=get_unwind_recursion(
239235
identifier,

0 commit comments

Comments
 (0)