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