Skip to content

Commit e487991

Browse files
author
martin
committed
Create a new kind of abstract interpreter that does function-local analysis
1 parent 34b55b5 commit e487991

File tree

2 files changed

+61
-5
lines changed

2 files changed

+61
-5
lines changed

src/analyses/ai.cpp

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ bool ai_baset::visit_edge(
411411
return return_value;
412412
}
413413

414-
bool ai_baset::visit_edge_function_call(
414+
bool ai_localt::visit_edge_function_call(
415415
const irep_idt &calling_function_id,
416416
trace_ptrt p_call,
417417
locationt l_return,
@@ -422,11 +422,11 @@ bool ai_baset::visit_edge_function_call(
422422
const namespacet &ns)
423423
{
424424
messaget log(message_handler);
425-
log.progress() << "ai_baset::visit_edge_function_call from "
425+
log.progress() << "ai_localt::visit_edge_function_call from "
426426
<< p_call->current_location()->location_number << " to "
427427
<< l_return->location_number << messaget::eom;
428428

429-
// The default implementation is not interprocedural
429+
// This implementation is not interprocedural
430430
// so the effects of the call are approximated but nothing else
431431
return visit_edge(
432432
calling_function_id,
@@ -537,6 +537,27 @@ bool ai_baset::visit_end_function(
537537
return false;
538538
}
539539

540+
void ai_localt::
541+
operator()(const goto_functionst &goto_functions, const namespacet &ns)
542+
{
543+
initialize(goto_functions);
544+
for(const auto &gf_entry : goto_functions.function_map)
545+
{
546+
if(gf_entry.second.body_available())
547+
{
548+
trace_ptrt p = entry_state(gf_entry.second.body);
549+
fixedpoint(p, gf_entry.first, gf_entry.second.body, goto_functions, ns);
550+
}
551+
}
552+
finalize();
553+
}
554+
555+
void ai_localt::operator()(const abstract_goto_modelt &goto_model)
556+
{
557+
const namespacet ns(goto_model.get_symbol_table());
558+
operator()(goto_model.get_goto_functions(), ns);
559+
}
560+
540561
void ai_recursive_interproceduralt::
541562
operator()(const goto_functionst &goto_functions, const namespacet &ns)
542563
{

src/analyses/ai.h

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ class ai_baset
469469
working_sett &working_set,
470470
const goto_programt &callee,
471471
const goto_functionst &goto_functions,
472-
const namespacet &ns);
472+
const namespacet &ns) = 0;
473473

474474
/// For creating history objects
475475
std::unique_ptr<ai_history_factory_baset> history_factory;
@@ -505,6 +505,40 @@ class ai_baset
505505
message_handlert &message_handler;
506506
};
507507

508+
// Perform function local analysis on all functions in a program.
509+
// No interprocedural analysis other than what a domain does when
510+
// visit()'ing an edge that skips a function call.
511+
class ai_localt : public ai_baset
512+
{
513+
public:
514+
ai_localt(
515+
std::unique_ptr<ai_history_factory_baset> &&hf,
516+
std::unique_ptr<ai_domain_factory_baset> &&df,
517+
std::unique_ptr<ai_storage_baset> &&st,
518+
message_handlert &mh)
519+
: ai_baset(std::move(hf), std::move(df), std::move(st), mh)
520+
{
521+
}
522+
523+
// Handle every function independently
524+
void operator()(const goto_functionst &goto_functions, const namespacet &ns)
525+
override;
526+
void operator()(const abstract_goto_modelt &goto_model) override;
527+
528+
protected:
529+
// Implement the function that handles a single function call edge
530+
// by a single edge that gets the domain to approximate the whole function call
531+
bool visit_edge_function_call(
532+
const irep_idt &calling_function_id,
533+
trace_ptrt p_call,
534+
locationt l_return,
535+
const irep_idt &callee_function_id,
536+
working_sett &working_set,
537+
const goto_programt &callee,
538+
const goto_functionst &goto_functions,
539+
const namespacet &ns) override;
540+
};
541+
508542
// Perform interprocedural analysis by simply recursing in the interpreter
509543
// This can lead to a call stack overflow if the domain has a large height
510544
class ai_recursive_interproceduralt : public ai_baset
@@ -525,7 +559,8 @@ class ai_recursive_interproceduralt : public ai_baset
525559
void operator()(const abstract_goto_modelt &goto_model) override;
526560

527561
protected:
528-
// Override the function that handles a single function call edge
562+
// Implement the function that handles a single function call edge
563+
// by a recursive call to fixpoint
529564
bool visit_edge_function_call(
530565
const irep_idt &calling_function_id,
531566
trace_ptrt p_call,

0 commit comments

Comments
 (0)