00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "c_breeze.h"
00040 #include "callgraph.h"
00041
00042 callGraph::callGraph(procNode * root, Linker & linker)
00043 : Walker(Preorder, Subtree),
00044 _callgraph(),
00045 _root(root),
00046 _linker(linker),
00047 _current(0)
00048 {
00049
00050
00051 const proc_decl_map & procs = linker.procedures();
00052 for (proc_decl_map_cp p = procs.begin();
00053 p != procs.end();
00054 ++p)
00055 {
00056 procNode * pr = (*p).second;
00057 _current = lookup(pr);
00058 pr->walk(*this);
00059 }
00060 }
00061
00062 callGraph::~callGraph()
00063 {
00064 for (callgraph_map_p p = _callgraph.begin();
00065 p != _callgraph.end();
00066 ++p)
00067 delete (*p).second;
00068 }
00069
00070 void callGraph::at_id(idNode * the_id, Order ord)
00071 {
00072 if (! the_id->decl())
00073 cout << "ID with no decl: " << the_id->name() << endl;
00074 else
00075 if (the_id->decl()->type()->typ() == Func) {
00076 procNode * proc = _linker.lookup_procedure(the_id->decl());
00077 if (proc) {
00078 callGraphNode * cgn = lookup(proc);
00079
00080 _current->add_edge(cgn);
00081 }
00082 }
00083 }
00084
00085 callGraphNode * callGraph::lookup(procNode * proc)
00086 {
00087 callGraphNode * cgnode;
00088 callgraph_map_p p = _callgraph.find(proc);
00089 if (p == _callgraph.end()) {
00090 cgnode = new callGraphNode(proc);
00091 _callgraph[proc] = cgnode;
00092 }
00093 else
00094 cgnode = (*p).second;
00095
00096 return cgnode;
00097 }
00098
00099 void callGraph::show_all_contexts()
00100 {
00101 callgraph_edge_list stack;
00102 int count = 0;
00103 callGraphNode * start = lookup(_root);
00104 show_all_contexts(start, stack, count);
00105
00106 cout << "Total procedures: " << _callgraph.size() << endl;
00107 cout << "Total contexts: " << count << endl;
00108 }
00109
00110 void callGraph::show_all_contexts(callGraphNode * cur,
00111 callgraph_edge_list & stack,
00112 int & count)
00113 {
00114 callgraph_edge_list_p rec = find(stack.begin(), stack.end(), cur);
00115 if (rec != stack.end()) {
00116
00117 return;
00118 }
00119
00120 stack.push_back(cur);
00121 count++;
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136 for (callgraph_edge_list_cp p = cur->calls().begin();
00137 p != cur->calls().end();
00138 ++p)
00139 {
00140 callGraphNode * cgn = *p;
00141 show_all_contexts(cgn, stack, count);
00142 }
00143
00144 stack.pop_back();
00145 }
00146
00147 void callGraphNode::add_edge(callGraphNode * to)
00148 {
00149 _calls.push_back(to);
00150 to->_called_by.push_back(this);
00151 }
00152
00153 int callGraphNode::times_called()
00154 {
00155 callgraph_node_set visited;
00156
00157 return times_called(visited);
00158 }
00159
00160 int callGraphNode::times_called(callgraph_node_set & visited)
00161 {
00162 int total = 0;
00163
00164 if (visited.find(this) != visited.end())
00165 return _times_called;
00166
00167 visited.insert(this);
00168
00169
00170
00171 if (_times_called != -1)
00172 return _times_called;
00173
00174
00175
00176 if (_called_by.empty())
00177 total = 1;
00178 else {
00179
00180
00181
00182
00183
00184 for (callgraph_edge_list_p p = _called_by.begin();
00185 p != _called_by.end();
00186 ++p)
00187 {
00188 callGraphNode * caller = *p;
00189 total += caller->times_called(visited);
00190 }
00191 }
00192
00193 _times_called = total;
00194
00195 return total;
00196 }
00197
00198 void callGraphNode::ancestors(callgraph_node_set & ancestors_set)
00199 {
00200
00201
00202 for (callgraph_edge_list_p p = _called_by.begin();
00203 p != _called_by.end();
00204 ++p)
00205 {
00206 callGraphNode * caller = *p;
00207
00208
00209
00210 if (ancestors_set.find(caller) == ancestors_set.end()) {
00211 ancestors_set.insert(caller);
00212 caller->ancestors(ancestors_set);
00213 }
00214 }
00215 }
00216