source: branches/libc-0.6/src/binutils/gprof/cg_dfn.c

Last change on this file was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 7.5 KB
Line 
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29#include "libiberty.h"
30#include "gprof.h"
31#include "search_list.h"
32#include "source.h"
33#include "symtab.h"
34#include "cg_arcs.h"
35#include "cg_dfn.h"
36#include "utils.h"
37
38#define DFN_INCR_DEPTH (128)
39
40typedef struct
41 {
42 Sym *sym;
43 int cycle_top;
44 }
45DFN_Stack;
46
47static bfd_boolean is_numbered PARAMS ((Sym *));
48static bfd_boolean is_busy PARAMS ((Sym *));
49static void find_cycle PARAMS ((Sym *));
50static void pre_visit PARAMS ((Sym *));
51static void post_visit PARAMS ((Sym *));
52
53DFN_Stack *dfn_stack = NULL;
54int dfn_maxdepth = 0;
55int dfn_depth = 0;
56int dfn_counter = DFN_NAN;
57
58
59/*
60 * Is CHILD already numbered?
61 */
62static bfd_boolean
63is_numbered (child)
64 Sym *child;
65{
66 return child->cg.top_order != DFN_NAN && child->cg.top_order != DFN_BUSY;
67}
68
69
70/*
71 * Is CHILD already busy?
72 */
73static bfd_boolean
74is_busy (child)
75 Sym *child;
76{
77 if (child->cg.top_order == DFN_NAN)
78 {
79 return FALSE;
80 }
81 return TRUE;
82}
83
84
85/*
86 * CHILD is part of a cycle. Find the top caller into this cycle
87 * that is not part of the cycle and make all functions in cycle
88 * members of that cycle (top caller == caller with smallest
89 * depth-first number).
90 */
91static void
92find_cycle (child)
93 Sym *child;
94{
95 Sym *head = 0;
96 Sym *tail;
97 int cycle_top;
98 int index;
99
100 for (cycle_top = dfn_depth; cycle_top > 0; --cycle_top)
101 {
102 head = dfn_stack[cycle_top].sym;
103 if (child == head)
104 {
105 break;
106 }
107 if (child->cg.cyc.head != child && child->cg.cyc.head == head)
108 {
109 break;
110 }
111 }
112 if (cycle_top <= 0)
113 {
114 fprintf (stderr, "[find_cycle] couldn't find head of cycle\n");
115 done (1);
116 }
117#ifdef DEBUG
118 if (debug_level & DFNDEBUG)
119 {
120 printf ("[find_cycle] dfn_depth %d cycle_top %d ",
121 dfn_depth, cycle_top);
122 if (head)
123 {
124 print_name (head);
125 }
126 else
127 {
128 printf ("<unknown>");
129 }
130 printf ("\n");
131 }
132#endif
133 if (cycle_top == dfn_depth)
134 {
135 /*
136 * This is previous function, e.g. this calls itself. Sort of
137 * boring.
138 *
139 * Since we are taking out self-cycles elsewhere no need for
140 * the special case, here.
141 */
142 DBG (DFNDEBUG,
143 printf ("[find_cycle] ");
144 print_name (child);
145 printf ("\n"));
146 }
147 else
148 {
149 /*
150 * Glom intervening functions that aren't already glommed into
151 * this cycle. Things have been glommed when their cyclehead
152 * field points to the head of the cycle they are glommed
153 * into.
154 */
155 for (tail = head; tail->cg.cyc.next; tail = tail->cg.cyc.next)
156 {
157 /* void: chase down to tail of things already glommed */
158 DBG (DFNDEBUG,
159 printf ("[find_cycle] tail ");
160 print_name (tail);
161 printf ("\n"));
162 }
163 /*
164 * If what we think is the top of the cycle has a cyclehead
165 * field, then it's not really the head of the cycle, which is
166 * really what we want.
167 */
168 if (head->cg.cyc.head != head)
169 {
170 head = head->cg.cyc.head;
171 DBG (DFNDEBUG, printf ("[find_cycle] new cyclehead ");
172 print_name (head);
173 printf ("\n"));
174 }
175 for (index = cycle_top + 1; index <= dfn_depth; ++index)
176 {
177 child = dfn_stack[index].sym;
178 if (child->cg.cyc.head == child)
179 {
180 /*
181 * Not yet glommed anywhere, glom it and fix any
182 * children it has glommed.
183 */
184 tail->cg.cyc.next = child;
185 child->cg.cyc.head = head;
186 DBG (DFNDEBUG, printf ("[find_cycle] glomming ");
187 print_name (child);
188 printf (" onto ");
189 print_name (head);
190 printf ("\n"));
191 for (tail = child; tail->cg.cyc.next; tail = tail->cg.cyc.next)
192 {
193 tail->cg.cyc.next->cg.cyc.head = head;
194 DBG (DFNDEBUG, printf ("[find_cycle] and its tail ");
195 print_name (tail->cg.cyc.next);
196 printf (" onto ");
197 print_name (head);
198 printf ("\n"));
199 }
200 }
201 else if (child->cg.cyc.head != head /* firewall */ )
202 {
203 fprintf (stderr, "[find_cycle] glommed, but not to head\n");
204 done (1);
205 }
206 }
207 }
208}
209
210
211/*
212 * Prepare for visiting the children of PARENT. Push a parent onto
213 * the stack and mark it busy.
214 */
215static void
216pre_visit (parent)
217 Sym *parent;
218{
219 ++dfn_depth;
220
221 if (dfn_depth >= dfn_maxdepth)
222 {
223 dfn_maxdepth += DFN_INCR_DEPTH;
224 dfn_stack = xrealloc (dfn_stack, dfn_maxdepth * sizeof *dfn_stack);
225 }
226
227 dfn_stack[dfn_depth].sym = parent;
228 dfn_stack[dfn_depth].cycle_top = dfn_depth;
229 parent->cg.top_order = DFN_BUSY;
230 DBG (DFNDEBUG, printf ("[pre_visit]\t\t%d:", dfn_depth);
231 print_name (parent);
232 printf ("\n"));
233}
234
235
236/*
237 * Done with visiting node PARENT. Pop PARENT off dfn_stack
238 * and number functions if PARENT is head of a cycle.
239 */
240static void
241post_visit (parent)
242 Sym *parent;
243{
244 Sym *member;
245
246 DBG (DFNDEBUG, printf ("[post_visit]\t%d: ", dfn_depth);
247 print_name (parent);
248 printf ("\n"));
249 /*
250 * Number functions and things in their cycles unless the function
251 * is itself part of a cycle:
252 */
253 if (parent->cg.cyc.head == parent)
254 {
255 ++dfn_counter;
256 for (member = parent; member; member = member->cg.cyc.next)
257 {
258 member->cg.top_order = dfn_counter;
259 DBG (DFNDEBUG, printf ("[post_visit]\t\tmember ");
260 print_name (member);
261 printf ("-> cg.top_order = %d\n", dfn_counter));
262 }
263 }
264 else
265 {
266 DBG (DFNDEBUG, printf ("[post_visit]\t\tis part of a cycle\n"));
267 }
268 --dfn_depth;
269}
270
271
272/*
273 * Given this PARENT, depth first number its children.
274 */
275void
276cg_dfn (parent)
277 Sym *parent;
278{
279 Arc *arc;
280
281 DBG (DFNDEBUG, printf ("[dfn] dfn( ");
282 print_name (parent);
283 printf (")\n"));
284 /*
285 * If we're already numbered, no need to look any further:
286 */
287 if (is_numbered (parent))
288 {
289 return;
290 }
291 /*
292 * If we're already busy, must be a cycle:
293 */
294 if (is_busy (parent))
295 {
296 find_cycle (parent);
297 return;
298 }
299 pre_visit (parent);
300 /*
301 * Recursively visit children:
302 */
303 for (arc = parent->cg.children; arc; arc = arc->next_child)
304 {
305 cg_dfn (arc->child);
306 }
307 post_visit (parent);
308}
Note: See TracBrowser for help on using the repository browser.