Skip to content

Commit 52bc0a8

Browse files
authored
Merge pull request #3132 from diffblue/ai-function-ids
AI transformers now get function identifiers
2 parents 27742dd + 09b5ac1 commit 52bc0a8

26 files changed

+215
-85
lines changed

src/analyses/ai.cpp

Lines changed: 70 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ ai_baset::locationt ai_baset::get_next(
231231
}
232232

233233
bool ai_baset::fixedpoint(
234+
const irep_idt &function_identifier,
234235
const goto_programt &goto_program,
235236
const goto_functionst &goto_functions,
236237
const namespacet &ns)
@@ -250,14 +251,16 @@ bool ai_baset::fixedpoint(
250251
locationt l=get_next(working_set);
251252

252253
// goto_program is really only needed for iterator manipulation
253-
if(visit(l, working_set, goto_program, goto_functions, ns))
254+
if(visit(
255+
function_identifier, l, working_set, goto_program, goto_functions, ns))
254256
new_data=true;
255257
}
256258

257259
return new_data;
258260
}
259261

260262
bool ai_baset::visit(
263+
const irep_idt &function_identifier,
261264
locationt l,
262265
working_sett &working_set,
263266
const goto_programt &goto_program,
@@ -288,18 +291,22 @@ bool ai_baset::visit(
288291
to_code_function_call(l->code);
289292

290293
if(do_function_call_rec(
291-
l, to_l,
292-
code.function(),
293-
code.arguments(),
294-
goto_functions, ns))
294+
function_identifier,
295+
l,
296+
to_l,
297+
code.function(),
298+
code.arguments(),
299+
goto_functions,
300+
ns))
295301
have_new_values=true;
296302
}
297303
else
298304
{
299305
// initialize state, if necessary
300306
get_state(to_l);
301307

302-
new_values.transform(l, to_l, *this, ns);
308+
new_values.transform(
309+
function_identifier, l, function_identifier, to_l, *this, ns);
303310

304311
if(merge(new_values, l, to_l))
305312
have_new_values=true;
@@ -316,7 +323,9 @@ bool ai_baset::visit(
316323
}
317324

318325
bool ai_baset::do_function_call(
319-
locationt l_call, locationt l_return,
326+
const irep_idt &calling_function_identifier,
327+
locationt l_call,
328+
locationt l_return,
320329
const goto_functionst &goto_functions,
321330
const goto_functionst::function_mapt::const_iterator f_it,
322331
const exprt::operandst &,
@@ -334,7 +343,13 @@ bool ai_baset::do_function_call(
334343
{
335344
// if we don't have a body, we just do an edige call -> return
336345
std::unique_ptr<statet> tmp_state(make_temporary_state(get_state(l_call)));
337-
tmp_state->transform(l_call, l_return, *this, ns);
346+
tmp_state->transform(
347+
calling_function_identifier,
348+
l_call,
349+
calling_function_identifier,
350+
l_return,
351+
*this,
352+
ns);
338353

339354
return merge(*tmp_state, l_call, l_return);
340355
}
@@ -351,7 +366,8 @@ bool ai_baset::do_function_call(
351366

352367
// do the edge from the call site to the beginning of the function
353368
std::unique_ptr<statet> tmp_state(make_temporary_state(get_state(l_call)));
354-
tmp_state->transform(l_call, l_begin, *this, ns);
369+
tmp_state->transform(
370+
calling_function_identifier, l_call, f_it->first, l_begin, *this, ns);
355371

356372
bool new_data=false;
357373

@@ -361,7 +377,7 @@ bool ai_baset::do_function_call(
361377

362378
// do we need to do/re-do the fixedpoint of the body?
363379
if(new_data)
364-
fixedpoint(goto_function.body, goto_functions, ns);
380+
fixedpoint(f_it->first, goto_function.body, goto_functions, ns);
365381
}
366382

367383
// This is the edge from function end to return site.
@@ -378,15 +394,18 @@ bool ai_baset::do_function_call(
378394
return false; // function exit point not reachable
379395

380396
std::unique_ptr<statet> tmp_state(make_temporary_state(end_state));
381-
tmp_state->transform(l_end, l_return, *this, ns);
397+
tmp_state->transform(
398+
f_it->first, l_end, calling_function_identifier, l_return, *this, ns);
382399

383400
// Propagate those
384401
return merge(*tmp_state, l_end, l_return);
385402
}
386403
}
387404

388405
bool ai_baset::do_function_call_rec(
389-
locationt l_call, locationt l_return,
406+
const irep_idt &calling_function_identifier,
407+
locationt l_call,
408+
locationt l_return,
390409
const exprt &function,
391410
const exprt::operandst &arguments,
392411
const goto_functionst &goto_functions,
@@ -411,8 +430,14 @@ bool ai_baset::do_function_call_rec(
411430
it != goto_functions.function_map.end(),
412431
"Function " + id2string(identifier) + "not in function map");
413432

414-
new_data =
415-
do_function_call(l_call, l_return, goto_functions, it, arguments, ns);
433+
new_data = do_function_call(
434+
calling_function_identifier,
435+
l_call,
436+
l_return,
437+
goto_functions,
438+
it,
439+
arguments,
440+
ns);
416441

417442
return new_data;
418443
}
@@ -425,7 +450,7 @@ void ai_baset::sequential_fixedpoint(
425450
f_it=goto_functions.function_map.find(goto_functions.entry_point());
426451

427452
if(f_it!=goto_functions.function_map.end())
428-
fixedpoint(f_it->second.body, goto_functions, ns);
453+
fixedpoint(f_it->first, f_it->second.body, goto_functions, ns);
429454
}
430455

431456
void ai_baset::concurrent_fixedpoint(
@@ -443,16 +468,32 @@ void ai_baset::concurrent_fixedpoint(
443468
goto_programt::const_targett sh_target=tmp.instructions.begin();
444469
statet &shared_state=get_state(sh_target);
445470

446-
typedef std::list<std::pair<goto_programt const*,
447-
goto_programt::const_targett> > thread_wlt;
471+
struct wl_entryt
472+
{
473+
wl_entryt(
474+
const irep_idt &_function_identifier,
475+
const goto_programt &_goto_program,
476+
locationt _location)
477+
: function_identifier(_function_identifier),
478+
goto_program(&_goto_program),
479+
location(_location)
480+
{
481+
}
482+
483+
irep_idt function_identifier;
484+
const goto_programt *goto_program;
485+
locationt location;
486+
};
487+
488+
typedef std::list<wl_entryt> thread_wlt;
448489
thread_wlt thread_wl;
449490

450491
forall_goto_functions(it, goto_functions)
451492
forall_goto_program_instructions(t_it, it->second.body)
452493
{
453494
if(is_threaded(t_it))
454495
{
455-
thread_wl.push_back(std::make_pair(&(it->second.body), t_it));
496+
thread_wl.push_back(wl_entryt(it->first, it->second.body, t_it));
456497

457498
goto_programt::const_targett l_end=
458499
it->second.body.instructions.end();
@@ -469,19 +510,25 @@ void ai_baset::concurrent_fixedpoint(
469510
{
470511
new_shared=false;
471512

472-
for(const auto &wl_pair : thread_wl)
513+
for(const auto &wl_entry : thread_wl)
473514
{
474515
working_sett working_set;
475-
put_in_working_set(working_set, wl_pair.second);
516+
put_in_working_set(working_set, wl_entry.location);
476517

477-
statet &begin_state=get_state(wl_pair.second);
478-
merge(begin_state, sh_target, wl_pair.second);
518+
statet &begin_state = get_state(wl_entry.location);
519+
merge(begin_state, sh_target, wl_entry.location);
479520

480521
while(!working_set.empty())
481522
{
482523
goto_programt::const_targett l=get_next(working_set);
483524

484-
visit(l, working_set, *(wl_pair.first), goto_functions, ns);
525+
visit(
526+
wl_entry.function_identifier,
527+
l,
528+
working_set,
529+
*(wl_entry.goto_program),
530+
goto_functions,
531+
ns);
485532

486533
// the underlying domain must make sure that the final state
487534
// carries all possible values; otherwise we would need to

src/analyses/ai.h

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,14 @@ class ai_baset
4545

4646
/// Running the interpreter
4747
void operator()(
48+
const irep_idt &function_identifier,
4849
const goto_programt &goto_program,
4950
const namespacet &ns)
5051
{
5152
goto_functionst goto_functions;
5253
initialize(goto_program);
5354
entry_state(goto_program);
54-
fixedpoint(goto_program, goto_functions, ns);
55+
fixedpoint(function_identifier, goto_program, goto_functions, ns);
5556
finalize();
5657
}
5758

@@ -75,13 +76,14 @@ class ai_baset
7576
}
7677

7778
void operator()(
79+
const irep_idt &function_identifier,
7880
const goto_functionst::goto_functiont &goto_function,
7981
const namespacet &ns)
8082
{
8183
goto_functionst goto_functions;
8284
initialize(goto_function);
8385
entry_state(goto_function.body);
84-
fixedpoint(goto_function.body, goto_functions, ns);
86+
fixedpoint(function_identifier, goto_function.body, goto_functions, ns);
8587
finalize();
8688
}
8789

@@ -234,6 +236,7 @@ class ai_baset
234236

235237
// true = found something new
236238
bool fixedpoint(
239+
const irep_idt &function_identifier,
237240
const goto_programt &goto_program,
238241
const goto_functionst &goto_functions,
239242
const namespacet &ns);
@@ -245,6 +248,7 @@ class ai_baset
245248
void sequential_fixedpoint(
246249
const goto_functionst &goto_functions,
247250
const namespacet &ns);
251+
248252
void concurrent_fixedpoint(
249253
const goto_functionst &goto_functions,
250254
const namespacet &ns);
@@ -254,6 +258,7 @@ class ai_baset
254258
// or applications of the abstract transformer
255259
// true = found something new
256260
bool visit(
261+
const irep_idt &function_identifier,
257262
locationt l,
258263
working_sett &working_set,
259264
const goto_programt &goto_program,
@@ -262,14 +267,18 @@ class ai_baset
262267

263268
// function calls
264269
bool do_function_call_rec(
265-
locationt l_call, locationt l_return,
270+
const irep_idt &calling_function_identifier,
271+
locationt l_call,
272+
locationt l_return,
266273
const exprt &function,
267274
const exprt::operandst &arguments,
268275
const goto_functionst &goto_functions,
269276
const namespacet &ns);
270277

271278
bool do_function_call(
272-
locationt l_call, locationt l_return,
279+
const irep_idt &calling_function_identifier,
280+
locationt l_call,
281+
locationt l_return,
273282
const goto_functionst &goto_functions,
274283
const goto_functionst::function_mapt::const_iterator f_it,
275284
const exprt::operandst &arguments,
@@ -384,11 +393,8 @@ class ait:public ai_baset
384393
void dummy(const domainT &s) { const statet &x=s; (void)x; }
385394

386395
// not implemented in sequential analyses
387-
bool merge_shared(
388-
const statet &,
389-
goto_programt::const_targett,
390-
goto_programt::const_targett,
391-
const namespacet &) override
396+
bool merge_shared(const statet &, locationt, locationt, const namespacet &)
397+
override
392398
{
393399
throw "not implemented";
394400
}
@@ -398,7 +404,8 @@ template<typename domainT>
398404
class concurrency_aware_ait:public ait<domainT>
399405
{
400406
public:
401-
typedef typename ait<domainT>::statet statet;
407+
using statet = typename ait<domainT>::statet;
408+
using locationt = typename statet::locationt;
402409

403410
// constructor
404411
concurrency_aware_ait():ait<domainT>()
@@ -407,8 +414,8 @@ class concurrency_aware_ait:public ait<domainT>
407414

408415
bool merge_shared(
409416
const statet &src,
410-
goto_programt::const_targett from,
411-
goto_programt::const_targett to,
417+
locationt from,
418+
locationt to,
412419
const namespacet &ns) override
413420
{
414421
statet &dest=this->get_state(to);

src/analyses/ai_domain.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ class ai_domain_baset
5555
/// (from->is_function_call() || from->is_end_function())
5656

5757
virtual void transform(
58+
const irep_idt &function_from,
5859
locationt from,
60+
const irep_idt &function_to,
5961
locationt to,
6062
ai_baset &ai,
6163
const namespacet &ns) = 0;

src/analyses/constant_propagator.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ void constant_propagator_domaint::assign_rec(
5858
}
5959

6060
void constant_propagator_domaint::transform(
61+
const irep_idt &function_from,
6162
locationt from,
63+
const irep_idt &function_to,
6264
locationt to,
6365
ai_baset &ai,
6466
const namespacet &ns)
@@ -146,7 +148,7 @@ void constant_propagator_domaint::transform(
146148
const irep_idt id=symbol_expr.get_identifier();
147149

148150
// Functions with no body
149-
if(from->function == to->function)
151+
if(function_from == function_to)
150152
{
151153
if(id==CPROVER_PREFIX "set_must" ||
152154
id==CPROVER_PREFIX "get_must" ||
@@ -195,7 +197,7 @@ void constant_propagator_domaint::transform(
195197
{
196198
// unresolved call
197199
INVARIANT(
198-
from->function == to->function,
200+
function_from == function_to,
199201
"Unresolved call can only be approximated if a skip");
200202

201203
if(have_dirty)
@@ -208,7 +210,7 @@ void constant_propagator_domaint::transform(
208210
{
209211
// erase parameters
210212

211-
const irep_idt id=from->function;
213+
const irep_idt id = function_from;
212214
const symbolt &symbol=ns.lookup(id);
213215

214216
const code_typet &type=to_code_type(symbol.type);

src/analyses/constant_propagator.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ class constant_propagator_domaint:public ai_domain_baset
3434
{
3535
public:
3636
virtual void transform(
37+
const irep_idt &function_from,
3738
locationt from,
39+
const irep_idt &function_to,
3840
locationt to,
3941
ai_baset &ai_base,
4042
const namespacet &ns) final override;
@@ -196,13 +198,13 @@ class constant_propagator_ait:public ait<constant_propagator_domaint>
196198
}
197199

198200
constant_propagator_ait(
201+
const irep_idt &function_identifier,
199202
goto_functionst::goto_functiont &goto_function,
200203
const namespacet &ns,
201-
should_track_valuet should_track_value = track_all_values):
202-
dirty(goto_function),
203-
should_track_value(should_track_value)
204+
should_track_valuet should_track_value = track_all_values)
205+
: dirty(goto_function), should_track_value(should_track_value)
204206
{
205-
operator()(goto_function, ns);
207+
operator()(function_identifier, goto_function, ns);
206208
replace(goto_function, ns);
207209
}
208210

0 commit comments

Comments
 (0)