@@ -35,9 +35,9 @@ call_grapht::call_grapht(
35
35
}
36
36
}
37
37
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 )
41
41
{
42
42
forall_goto_program_instructions (i_it, body)
43
43
{
@@ -47,14 +47,73 @@ void call_grapht::add(
47
47
if (function_expr.id ()==ID_symbol)
48
48
{
49
49
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);
53
51
}
54
52
}
55
53
}
56
54
}
57
55
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
58
117
void call_grapht::add (
59
118
const irep_idt &caller,
60
119
const irep_idt &callee)
0 commit comments