Skip to content

Commit 8f6f429

Browse files
committed
Add call graph helpers
These translate from function name to node ID and back, thus giving more concise ways of running very simple graph algorithms over the call graph.
1 parent 3b06a16 commit 8f6f429

File tree

3 files changed

+125
-0
lines changed

3 files changed

+125
-0
lines changed

src/analyses/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
SRC = ai.cpp \
22
call_graph.cpp \
3+
call_graph_helpers.cpp \
34
constant_propagator.cpp \
45
custom_bitvector_analysis.cpp \
56
dependence_graph.cpp \

src/analyses/call_graph_helpers.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*******************************************************************\
2+
3+
Module: Function Call Graph Helpers
4+
5+
Author: Chris Smowton, [email protected]
6+
7+
\*******************************************************************/
8+
9+
/// \file
10+
/// Function Call Graph Helpers
11+
12+
#include "call_graph_helpers.h"
13+
14+
/// Get either callers or callees of a given function
15+
/// \param graph: call graph
16+
/// \param function: function to query
17+
/// \param forwards: if true, get callees; otherwise get callers.
18+
static std::set<irep_idt> get_neighbours(
19+
const call_grapht::directed_grapht &graph,
20+
const irep_idt &function,
21+
bool forwards)
22+
{
23+
std::set<irep_idt> result;
24+
const auto &fnode = graph[*(graph.get_node_index(function))];
25+
const auto &neighbours = forwards ? fnode.out : fnode.in;
26+
for(const auto &succ_edge : neighbours)
27+
result.insert(graph[succ_edge.first].function);
28+
return result;
29+
}
30+
31+
std::set<irep_idt> get_callees(
32+
const call_grapht::directed_grapht &graph, const irep_idt &function)
33+
{
34+
return get_neighbours(graph, function, true);
35+
}
36+
37+
std::set<irep_idt> get_callers(
38+
const call_grapht::directed_grapht &graph, const irep_idt &function)
39+
{
40+
return get_neighbours(graph, function, false);
41+
}
42+
43+
/// Get either reachable functions or functions that can reach a given function.
44+
/// In both cases the query function itself is included.
45+
/// \param graph: call graph
46+
/// \param function: function to query
47+
/// \param forwards: if true, get reachable functions; otherwise get functions
48+
/// that can reach the given function.
49+
static std::set<irep_idt> get_connected_functions(
50+
const call_grapht::directed_grapht &graph,
51+
const irep_idt &function,
52+
bool forwards)
53+
{
54+
std::vector<call_grapht::directed_grapht::node_indext> connected_nodes =
55+
graph.get_reachable(*(graph.get_node_index(function)), forwards);
56+
std::set<irep_idt> result;
57+
for(const auto i : connected_nodes)
58+
result.insert(graph[i].function);
59+
return result;
60+
}
61+
62+
std::set<irep_idt> get_reachable_functions(
63+
const call_grapht::directed_grapht &graph, const irep_idt &function)
64+
{
65+
return get_connected_functions(graph, function, true);
66+
}
67+
68+
std::set<irep_idt> get_reaching_functions(
69+
const call_grapht::directed_grapht &graph, const irep_idt &function)
70+
{
71+
return get_connected_functions(graph, function, false);
72+
}

src/analyses/call_graph_helpers.h

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*******************************************************************\
2+
3+
Module: Function Call Graph Helpers
4+
5+
Author: Chris Smowton, [email protected]
6+
7+
\*******************************************************************/
8+
9+
/// \file
10+
/// Function Call Graph Helpers
11+
12+
#ifndef CPROVER_ANALYSES_CALL_GRAPH_HELPERS_H
13+
#define CPROVER_ANALYSES_CALL_GRAPH_HELPERS_H
14+
15+
#include "call_graph.h"
16+
17+
// These are convenience functions for working with the directed graph
18+
// representation of a call graph, obtained via
19+
// `call_grapht::get_directed_graph`. Usually function names must be mapped
20+
// to and from node indices, as in `graph.get_node_index("f")`, or
21+
// `graph[node_index].function`; these helpers include the translation for
22+
// convenience.
23+
24+
/// Get functions directly callable from a given function
25+
/// \param graph: call graph
26+
/// \param function: function to query
27+
/// \return set of called functions
28+
std::set<irep_idt> get_callees(
29+
const call_grapht::directed_grapht &graph, const irep_idt &function);
30+
31+
/// Get functions that call a given function
32+
/// \param graph: call graph
33+
/// \param function: function to query
34+
/// \return set of caller functions
35+
std::set<irep_idt> get_callers(
36+
const call_grapht::directed_grapht &graph, const irep_idt &function);
37+
38+
/// Get functions reachable from a given function
39+
/// \param graph: call graph
40+
/// \param function: function to query
41+
/// \return set of reachable functions, including `function`
42+
std::set<irep_idt> get_reachable_functions(
43+
const call_grapht::directed_grapht &graph, const irep_idt &function);
44+
45+
/// Get functions that can reach a given function
46+
/// \param graph: call graph
47+
/// \param function: function to query
48+
/// \return set of functions that can reach the target, including `function`
49+
std::set<irep_idt> get_reaching_functions(
50+
const call_grapht::directed_grapht &graph, const irep_idt &function);
51+
52+
#endif

0 commit comments

Comments
 (0)