Skip to content

Commit 3b06a16

Browse files
committed
Call graph: add constructors that only include reachable functions
These start from a nominated node and walk outwards, rather than build the entire call-graph as usual.
1 parent 9b65862 commit 3b06a16

File tree

2 files changed

+76
-6
lines changed

2 files changed

+76
-6
lines changed

src/analyses/call_graph.cpp

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ call_grapht::call_grapht(
3535
}
3636
}
3737

38-
void call_grapht::add(
39-
const irep_idt &function,
40-
const goto_programt &body)
38+
static void forall_callsites(
39+
const goto_programt &body,
40+
std::function<void(goto_programt::const_targett, const irep_idt &)> call_task)
4141
{
4242
forall_goto_program_instructions(i_it, body)
4343
{
@@ -47,14 +47,73 @@ void call_grapht::add(
4747
if(function_expr.id()==ID_symbol)
4848
{
4949
const irep_idt &callee=to_symbol_expr(function_expr).get_identifier();
50-
add(function, callee);
51-
if(collect_callsites)
52-
callsites[{function, callee}].insert(i_it);
50+
call_task(i_it, callee);
5351
}
5452
}
5553
}
5654
}
5755

56+
/// Create call graph restricted to functions reachable from `root`
57+
/// \param functions: functions to search for callsites
58+
/// \param root: function to start exploring the graph
59+
/// \param collect_callsites: if true, then each added graph edge will have
60+
/// the calling instruction recorded in `callsites` map.
61+
call_grapht::call_grapht(
62+
const goto_functionst &goto_functions,
63+
const irep_idt &root,
64+
bool collect_callsites)
65+
{
66+
std::stack<irep_idt, std::vector<irep_idt>> pending_stack;
67+
pending_stack.push(root);
68+
69+
while(!pending_stack.empty())
70+
{
71+
irep_idt function=pending_stack.top();
72+
pending_stack.pop();
73+
const goto_programt &goto_program=
74+
goto_functions.function_map.at(function).body;
75+
76+
forall_callsites(
77+
goto_program,
78+
[&](goto_programt::const_targett i_it, const irep_idt &callee)
79+
{
80+
add(function, callee, i_it);
81+
if(graph.find(callee)==graph.end())
82+
pending_stack.push(callee);
83+
}
84+
); // NOLINT
85+
}
86+
}
87+
88+
/// Create call graph restricted to functions reachable from `root`
89+
/// \param goto_model: model to search for callsites
90+
/// \param root: function to start exploring the graph
91+
/// \param collect_callsites: if true, then each added graph edge will have
92+
/// the calling instruction recorded in `callsites` map.
93+
call_grapht::call_grapht(
94+
const goto_modelt &goto_model,
95+
const irep_idt &root,
96+
bool collect_callsites):
97+
call_grapht(goto_model.goto_functions, root, collect_callsites)
98+
{
99+
}
100+
101+
void call_grapht::add(
102+
const irep_idt &function,
103+
const goto_programt &body)
104+
{
105+
forall_callsites(
106+
body,
107+
[&](goto_programt::const_targett i_it, const irep_idt &callee)
108+
{
109+
add(function, callee, i_it);
110+
}
111+
); // NOLINT
112+
}
113+
114+
/// Add edge
115+
/// \param caller: caller function
116+
/// \param callee: callee function
58117
void call_grapht::add(
59118
const irep_idt &caller,
60119
const irep_idt &callee)

src/analyses/call_graph.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,17 @@ class call_grapht
2525
explicit call_grapht(const goto_modelt &, bool collect_callsites=false);
2626
explicit call_grapht(const goto_functionst &, bool collect_callsites=false);
2727

28+
// These two constructors build a call graph restricted to functions
29+
// reachable from the given root.
30+
call_grapht(
31+
const goto_modelt &model,
32+
const irep_idt &root,
33+
bool collect_callsites);
34+
call_grapht(
35+
const goto_functionst &functions,
36+
const irep_idt &root,
37+
bool collect_callsites);
38+
2839
void output_dot(std::ostream &out) const;
2940
void output(std::ostream &out) const;
3041
void output_xml(std::ostream &out) const;

0 commit comments

Comments
 (0)