* Makefile.in (Makefile): Added config.status to dependency list.
[deliverable/binutils-gdb.git] / gprof / cg_print.c
CommitLineData
5489fcc3
KR
1#include "libiberty.h"
2#include "cg_arcs.h"
3#include "cg_print.h"
4#include "hist.h"
5#include "utils.h"
6
7/*
8 * Return value of comparison functions used to sort tables:
9 */
10#define LESSTHAN -1
11#define EQUALTO 0
12#define GREATERTHAN 1
13
14/* declarations of automatically generated functions to output blurbs: */
12516a37
KR
15extern void bsd_callg_blurb PARAMS ((FILE * fp));
16extern void fsf_callg_blurb PARAMS ((FILE * fp));
5489fcc3
KR
17
18double print_time = 0.0;
19
20
21static void
12516a37 22DEFUN_VOID (print_header)
5489fcc3 23{
12516a37
KR
24 if (first_output)
25 {
26 first_output = FALSE;
27 }
28 else
29 {
30 printf ("\f\n");
03c35bcb 31 }
12516a37
KR
32 if (!bsd_style_output)
33 {
34 if (print_descriptions)
35 {
36 printf ("\t\t Call graph (explanation follows)\n\n");
37 }
38 else
39 {
40 printf ("\t\t\tCall graph\n\n");
03c35bcb
KR
41 }
42 }
12516a37
KR
43 printf ("\ngranularity: each sample hit covers %ld byte(s)",
44 (long) hist_scale * sizeof (UNIT));
45 if (print_time > 0.0)
46 {
47 printf (" for %.2f%% of %.2f seconds\n\n",
48 100.0 / print_time, print_time / hz);
49 }
50 else
51 {
52 printf (" no time propagated\n\n");
53 /*
54 * This doesn't hurt, since all the numerators will be 0.0:
55 */
56 print_time = 1.0;
03c35bcb 57 }
12516a37
KR
58 if (bsd_style_output)
59 {
60 printf ("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n",
61 "", "", "", "", "called", "total", "parents");
62 printf ("%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n",
63 "index", "%time", "self", "descendents",
64 "called", "self", "name", "index");
65 printf ("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n",
66 "", "", "", "", "called", "total", "children");
67 printf ("\n");
68 }
69 else
70 {
71 printf ("index %% time self children called name\n");
03c35bcb
KR
72 }
73}
5489fcc3
KR
74
75
76/*
77 * Print a cycle header.
78 */
79static void
12516a37 80DEFUN (print_cycle, (cyc), Sym * cyc)
5489fcc3 81{
12516a37 82 char buf[BUFSIZ];
5489fcc3 83
12516a37
KR
84 sprintf (buf, "[%d]", cyc->cg.index);
85 printf ("%-6.6s %5.1f %7.2f %11.2f %7d", buf,
86 100 * (cyc->cg.prop.self + cyc->cg.prop.child) / print_time,
87 cyc->cg.prop.self / hz, cyc->cg.prop.child / hz, cyc->ncalls);
88 if (cyc->cg.self_calls != 0)
89 {
90 printf ("+%-7d", cyc->cg.self_calls);
91 }
92 else
93 {
94 printf (" %7.7s", "");
03c35bcb 95 }
12516a37 96 printf (" <cycle %d as a whole>\t[%d]\n", cyc->cg.cyc.num, cyc->cg.index);
03c35bcb 97}
5489fcc3
KR
98
99
100/*
101 * Compare LEFT and RIGHT membmer. Major comparison key is
102 * CG.PROP.SELF+CG.PROP.CHILD, secondary key is NCALLS+CG.SELF_CALLS.
103 */
104static int
12516a37 105DEFUN (cmp_member, (left, right), Sym * left AND Sym * right)
5489fcc3 106{
12516a37
KR
107 double left_time = left->cg.prop.self + left->cg.prop.child;
108 double right_time = right->cg.prop.self + right->cg.prop.child;
109 long left_calls = left->ncalls + left->cg.self_calls;
110 long right_calls = right->ncalls + right->cg.self_calls;
111
112 if (left_time > right_time)
113 {
114 return GREATERTHAN;
03c35bcb 115 }
12516a37
KR
116 if (left_time < right_time)
117 {
118 return LESSTHAN;
03c35bcb 119 }
12516a37
KR
120
121 if (left_calls > right_calls)
122 {
123 return GREATERTHAN;
03c35bcb 124 }
12516a37
KR
125 if (left_calls < right_calls)
126 {
127 return LESSTHAN;
03c35bcb 128 }
12516a37 129 return EQUALTO;
03c35bcb 130}
5489fcc3
KR
131
132
133/*
134 * Sort members of a cycle.
135 */
136static void
12516a37 137DEFUN (sort_members, (cyc), Sym * cyc)
5489fcc3 138{
12516a37
KR
139 Sym *todo, *doing, *prev;
140 /*
141 * Detach cycle members from cyclehead, and insertion sort them
142 * back on.
143 */
144 todo = cyc->cg.cyc.next;
145 cyc->cg.cyc.next = 0;
146 for (doing = todo; doing && doing->cg.cyc.next; doing = todo)
147 {
148 todo = doing->cg.cyc.next;
149 for (prev = cyc; prev->cg.cyc.next; prev = prev->cg.cyc.next)
150 {
151 if (cmp_member (doing, prev->cg.cyc.next) == GREATERTHAN)
152 {
153 break;
03c35bcb
KR
154 }
155 }
12516a37
KR
156 doing->cg.cyc.next = prev->cg.cyc.next;
157 prev->cg.cyc.next = doing;
03c35bcb
KR
158 }
159}
5489fcc3
KR
160
161
162/*
163 * Print the members of a cycle.
164 */
165static void
12516a37 166DEFUN (print_members, (cyc), Sym * cyc)
5489fcc3 167{
12516a37
KR
168 Sym *member;
169
170 sort_members (cyc);
171 for (member = cyc->cg.cyc.next; member; member = member->cg.cyc.next)
172 {
173 printf ("%6.6s %5.5s %7.2f %11.2f %7d",
174 "", "", member->cg.prop.self / hz, member->cg.prop.child / hz,
175 member->ncalls);
176 if (member->cg.self_calls != 0)
177 {
178 printf ("+%-7d", member->cg.self_calls);
179 }
180 else
181 {
182 printf (" %7.7s", "");
03c35bcb 183 }
12516a37
KR
184 printf (" ");
185 print_name (member);
186 printf ("\n");
03c35bcb
KR
187 }
188}
5489fcc3
KR
189
190
191/*
192 * Compare two arcs to/from the same child/parent.
12516a37
KR
193 * - if one arc is a self arc, it's least.
194 * - if one arc is within a cycle, it's less than.
195 * - if both arcs are within a cycle, compare arc counts.
196 * - if neither arc is within a cycle, compare with
197 * time + child_time as major key
198 * arc count as minor key
5489fcc3
KR
199 */
200static int
12516a37 201DEFUN (cmp_arc, (left, right), Arc * left AND Arc * right)
5489fcc3 202{
12516a37
KR
203 Sym *left_parent = left->parent;
204 Sym *left_child = left->child;
205 Sym *right_parent = right->parent;
206 Sym *right_child = right->child;
207 double left_time, right_time;
208
209 DBG (TIMEDEBUG,
210 printf ("[cmp_arc] ");
211 print_name (left_parent);
212 printf (" calls ");
213 print_name (left_child);
214 printf (" %f + %f %d/%d\n", left->time, left->child_time,
5489fcc3 215 left->count, left_child->ncalls);
12516a37
KR
216 printf ("[cmp_arc] ");
217 print_name (right_parent);
218 printf (" calls ");
219 print_name (right_child);
220 printf (" %f + %f %d/%d\n", right->time, right->child_time,
5489fcc3 221 right->count, right_child->ncalls);
12516a37
KR
222 printf ("\n");
223 );
224 if (left_parent == left_child)
225 {
226 return LESSTHAN; /* left is a self call */
03c35bcb 227 }
12516a37
KR
228 if (right_parent == right_child)
229 {
230 return GREATERTHAN; /* right is a self call */
03c35bcb 231 }
12516a37
KR
232
233 if (left_parent->cg.cyc.num != 0 && left_child->cg.cyc.num != 0
234 && left_parent->cg.cyc.num == left_child->cg.cyc.num)
235 {
236 /* left is a call within a cycle */
237 if (right_parent->cg.cyc.num != 0 && right_child->cg.cyc.num != 0
238 && right_parent->cg.cyc.num == right_child->cg.cyc.num)
239 {
240 /* right is a call within the cycle, too */
241 if (left->count < right->count)
242 {
243 return LESSTHAN;
03c35bcb 244 }
12516a37
KR
245 if (left->count > right->count)
246 {
247 return GREATERTHAN;
03c35bcb 248 }
12516a37
KR
249 return EQUALTO;
250 }
251 else
5489fcc3 252 {
12516a37
KR
253 /* right isn't a call within the cycle */
254 return LESSTHAN;
03c35bcb 255 }
12516a37
KR
256 }
257 else
258 {
259 /* left isn't a call within a cycle */
260 if (right_parent->cg.cyc.num != 0 && right_child->cg.cyc.num != 0
261 && right_parent->cg.cyc.num == right_child->cg.cyc.num)
5489fcc3 262 {
12516a37
KR
263 /* right is a call within a cycle */
264 return GREATERTHAN;
265 }
266 else
267 {
268 /* neither is a call within a cycle */
269 left_time = left->time + left->child_time;
270 right_time = right->time + right->child_time;
271 if (left_time < right_time)
272 {
273 return LESSTHAN;
03c35bcb 274 }
12516a37
KR
275 if (left_time > right_time)
276 {
277 return GREATERTHAN;
03c35bcb 278 }
12516a37
KR
279 if (left->count < right->count)
280 {
281 return LESSTHAN;
03c35bcb 282 }
12516a37
KR
283 if (left->count > right->count)
284 {
285 return GREATERTHAN;
03c35bcb 286 }
12516a37 287 return EQUALTO;
03c35bcb
KR
288 }
289 }
290}
5489fcc3
KR
291
292
293static void
12516a37 294DEFUN (sort_parents, (child), Sym * child)
5489fcc3 295{
12516a37
KR
296 Arc *arc, *detached, sorted, *prev;
297
298 /*
299 * Unlink parents from child, then insertion sort back on to
300 * sorted's parents.
301 * *arc the arc you have detached and are inserting.
302 * *detached the rest of the arcs to be sorted.
303 * sorted arc list onto which you insertion sort.
304 * *prev arc before the arc you are comparing.
305 */
306 sorted.next_parent = 0;
307 for (arc = child->cg.parents; arc; arc = detached)
308 {
309 detached = arc->next_parent;
310
311 /* consider *arc as disconnected; insert it into sorted: */
312 for (prev = &sorted; prev->next_parent; prev = prev->next_parent)
313 {
314 if (cmp_arc (arc, prev->next_parent) != GREATERTHAN)
315 {
316 break;
03c35bcb
KR
317 }
318 }
12516a37
KR
319 arc->next_parent = prev->next_parent;
320 prev->next_parent = arc;
03c35bcb 321 }
12516a37
KR
322
323 /* reattach sorted arcs to child: */
324 child->cg.parents = sorted.next_parent;
03c35bcb 325}
5489fcc3
KR
326
327
328static void
12516a37 329DEFUN (print_parents, (child), Sym * child)
5489fcc3 330{
12516a37
KR
331 Sym *parent;
332 Arc *arc;
333 Sym *cycle_head;
334
335 if (child->cg.cyc.head != 0)
336 {
337 cycle_head = child->cg.cyc.head;
338 }
339 else
340 {
341 cycle_head = child;
03c35bcb 342 }
12516a37
KR
343 if (!child->cg.parents)
344 {
345 printf (bsd_style_output
346 ? "%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s <spontaneous>\n"
347 : "%6.6s %5.5s %7.7s %7.7s %7.7s %7.7s <spontaneous>\n",
348 "", "", "", "", "", "");
349 return;
03c35bcb 350 }
12516a37
KR
351 sort_parents (child);
352 for (arc = child->cg.parents; arc; arc = arc->next_parent)
353 {
354 parent = arc->parent;
355 if (child == parent || (child->cg.cyc.num != 0
356 && parent->cg.cyc.num == child->cg.cyc.num))
5489fcc3 357 {
12516a37
KR
358 /* selfcall or call among siblings: */
359 printf (bsd_style_output
360 ? "%6.6s %5.5s %7.7s %11.11s %7d %7.7s "
361 : "%6.6s %5.5s %7.7s %7.7s %7d %7.7s ",
362 "", "", "", "",
363 arc->count, "");
364 print_name (parent);
365 printf ("\n");
366 }
367 else
368 {
369 /* regular parent of child: */
370 printf (bsd_style_output
371 ? "%6.6s %5.5s %7.2f %11.2f %7d/%-7d "
372 : "%6.6s %5.5s %7.2f %7.2f %7d/%-7d ",
373 "", "",
374 arc->time / hz, arc->child_time / hz,
375 arc->count, cycle_head->ncalls);
376 print_name (parent);
377 printf ("\n");
03c35bcb
KR
378 }
379 }
380}
5489fcc3
KR
381
382
383static void
12516a37 384DEFUN (sort_children, (parent), Sym * parent)
5489fcc3 385{
12516a37
KR
386 Arc *arc, *detached, sorted, *prev;
387 /*
388 * Unlink children from parent, then insertion sort back on to
389 * sorted's children.
390 * *arc the arc you have detached and are inserting.
391 * *detached the rest of the arcs to be sorted.
392 * sorted arc list onto which you insertion sort.
393 * *prev arc before the arc you are comparing.
394 */
395 sorted.next_child = 0;
396 for (arc = parent->cg.children; arc; arc = detached)
397 {
398 detached = arc->next_child;
399
400 /* consider *arc as disconnected; insert it into sorted: */
401 for (prev = &sorted; prev->next_child; prev = prev->next_child)
402 {
403 if (cmp_arc (arc, prev->next_child) != LESSTHAN)
404 {
405 break;
03c35bcb
KR
406 }
407 }
12516a37
KR
408 arc->next_child = prev->next_child;
409 prev->next_child = arc;
03c35bcb 410 }
12516a37
KR
411
412 /* reattach sorted children to parent: */
413 parent->cg.children = sorted.next_child;
03c35bcb 414}
5489fcc3
KR
415
416
417static void
12516a37 418DEFUN (print_children, (parent), Sym * parent)
5489fcc3 419{
12516a37
KR
420 Sym *child;
421 Arc *arc;
422
423 sort_children (parent);
424 arc = parent->cg.children;
425 for (arc = parent->cg.children; arc; arc = arc->next_child)
426 {
427 child = arc->child;
428 if (child == parent || (child->cg.cyc.num != 0
429 && child->cg.cyc.num == parent->cg.cyc.num))
430 {
431 /* self call or call to sibling: */
432 printf (bsd_style_output
433 ? "%6.6s %5.5s %7.7s %11.11s %7d %7.7s "
434 : "%6.6s %5.5s %7.7s %7.7s %7d %7.7s ",
435 "", "", "", "", arc->count, "");
436 print_name (child);
437 printf ("\n");
438 }
439 else
5489fcc3 440 {
12516a37
KR
441 /* regular child of parent: */
442 printf (bsd_style_output
443 ? "%6.6s %5.5s %7.2f %11.2f %7d/%-7d "
444 : "%6.6s %5.5s %7.2f %7.2f %7d/%-7d ",
445 "", "",
446 arc->time / hz, arc->child_time / hz,
447 arc->count, child->cg.cyc.head->ncalls);
448 print_name (child);
449 printf ("\n");
03c35bcb
KR
450 }
451 }
452}
5489fcc3
KR
453
454
455static void
12516a37 456DEFUN (print_line, (np), Sym * np)
5489fcc3 457{
12516a37
KR
458 char buf[BUFSIZ];
459
460 sprintf (buf, "[%d]", np->cg.index);
461 printf (bsd_style_output
462 ? "%-6.6s %5.1f %7.2f %11.2f"
463 : "%-6.6s %5.1f %7.2f %7.2f", buf,
464 100 * (np->cg.prop.self + np->cg.prop.child) / print_time,
465 np->cg.prop.self / hz, np->cg.prop.child / hz);
466 if ((np->ncalls + np->cg.self_calls) != 0)
467 {
468 printf (" %7d", np->ncalls);
469 if (np->cg.self_calls != 0)
470 {
471 printf ("+%-7d ", np->cg.self_calls);
472 }
473 else
474 {
475 printf (" %7.7s ", "");
03c35bcb 476 }
12516a37
KR
477 }
478 else
479 {
480 printf (" %7.7s %7.7s ", "", "");
03c35bcb 481 }
12516a37
KR
482 print_name (np);
483 printf ("\n");
03c35bcb 484}
5489fcc3
KR
485
486
487/*
488 * Print dynamic call graph.
489 */
490void
12516a37 491DEFUN (cg_print, (timesortsym), Sym ** timesortsym)
5489fcc3 492{
12516a37
KR
493 int index;
494 Sym *parent;
5489fcc3 495
12516a37
KR
496 if (print_descriptions && bsd_style_output)
497 {
498 bsd_callg_blurb (stdout);
03c35bcb 499 }
5489fcc3 500
12516a37 501 print_header ();
5489fcc3 502
12516a37
KR
503 for (index = 0; index < symtab.len + num_cycles; ++index)
504 {
505 parent = timesortsym[index];
506 if ((ignore_zeros && parent->ncalls == 0
507 && parent->cg.self_calls == 0 && parent->cg.prop.self == 0
508 && parent->cg.prop.child == 0)
509 || !parent->cg.print_flag)
510 {
511 continue;
03c35bcb 512 }
12516a37 513 if (!parent->name && parent->cg.cyc.num != 0)
5489fcc3 514 {
12516a37
KR
515 /* cycle header: */
516 print_cycle (parent);
517 print_members (parent);
518 }
519 else
520 {
521 print_parents (parent);
522 print_line (parent);
523 print_children (parent);
03c35bcb 524 }
12516a37
KR
525 if (bsd_style_output)
526 printf ("\n");
527 printf ("-----------------------------------------------\n");
528 if (bsd_style_output)
529 printf ("\n");
5489fcc3 530 }
12516a37
KR
531 free (timesortsym);
532 if (print_descriptions && !bsd_style_output)
533 {
534 fsf_callg_blurb (stdout);
5489fcc3 535 }
03c35bcb 536}
5489fcc3
KR
537
538
539static int
12516a37 540DEFUN (cmp_name, (left, right), const PTR left AND const PTR right)
5489fcc3 541{
12516a37
KR
542 const Sym **npp1 = (const Sym **) left;
543 const Sym **npp2 = (const Sym **) right;
5489fcc3 544
12516a37 545 return strcmp ((*npp1)->name, (*npp2)->name);
03c35bcb 546}
5489fcc3
KR
547
548
549void
12516a37 550DEFUN_VOID (cg_print_index)
5489fcc3 551{
12516a37
KR
552 int index, nnames, todo, i, j, col, starting_col;
553 Sym **name_sorted_syms, *sym;
554 const char *filename;
555 char buf[20];
556 int column_width = (output_width - 1) / 3; /* don't write in last col! */
557 /*
558 * Now, sort regular function name alphabetically to create an
559 * index:
560 */
561 name_sorted_syms = (Sym **) xmalloc ((symtab.len + num_cycles) * sizeof (Sym *));
562 for (index = 0, nnames = 0; index < symtab.len; index++)
563 {
564 if (ignore_zeros && symtab.base[index].ncalls == 0
565 && symtab.base[index].hist.time == 0)
566 {
567 continue;
03c35bcb 568 }
12516a37 569 name_sorted_syms[nnames++] = &symtab.base[index];
03c35bcb 570 }
12516a37
KR
571 qsort (name_sorted_syms, nnames, sizeof (Sym *), cmp_name);
572 for (index = 1, todo = nnames; index <= num_cycles; index++)
573 {
574 name_sorted_syms[todo++] = &cycle_header[index];
03c35bcb 575 }
12516a37
KR
576 printf ("\f\nIndex by function name\n\n");
577 index = (todo + 2) / 3;
578 for (i = 0; i < index; i++)
579 {
580 col = 0;
581 starting_col = 0;
582 for (j = i; j < todo; j += index)
5489fcc3 583 {
12516a37
KR
584 sym = name_sorted_syms[j];
585 if (sym->cg.print_flag)
586 {
587 sprintf (buf, "[%d]", sym->cg.index);
588 }
589 else
590 {
591 sprintf (buf, "(%d)", sym->cg.index);
03c35bcb 592 }
12516a37
KR
593 if (j < nnames)
594 {
595 if (bsd_style_output)
596 {
597 printf ("%6.6s %-19.19s", buf, sym->name);
598 }
599 else
600 {
601 col += strlen (buf);
602 for (; col < starting_col + 5; ++col)
603 {
604 putchar (' ');
03c35bcb 605 }
12516a37
KR
606 printf (" %s ", buf);
607 col += print_name_only (sym);
608 if (!line_granularity && sym->is_static && sym->file)
609 {
610 filename = sym->file->name;
611 if (!print_path)
612 {
613 filename = strrchr (filename, '/');
614 if (filename)
615 {
616 ++filename;
617 }
618 else
619 {
620 filename = sym->file->name;
03c35bcb
KR
621 }
622 }
12516a37
KR
623 printf (" (%s)", filename);
624 col += strlen (filename) + 3;
03c35bcb
KR
625 }
626 }
12516a37
KR
627 }
628 else
629 {
630 printf ("%6.6s ", buf);
631 sprintf (buf, "<cycle %d>", sym->cg.cyc.num);
632 printf ("%-19.19s", buf);
03c35bcb 633 }
12516a37 634 starting_col += column_width;
03c35bcb 635 }
12516a37 636 printf ("\n");
03c35bcb 637 }
12516a37 638 free (name_sorted_syms);
03c35bcb 639}
This page took 0.069638 seconds and 4 git commands to generate.