* op50n-rom.c: Add the control registers.
[platform/upstream/binutils.git] / gprof / cg_print.c
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: */
15 extern void bsd_callg_blurb PARAMS ((FILE * fp));
16 extern void fsf_callg_blurb PARAMS ((FILE * fp));
17
18 double print_time = 0.0;
19
20
21 static void
22 DEFUN_VOID (print_header)
23 {
24   if (first_output)
25     {
26       first_output = FALSE;
27     }
28   else
29     {
30       printf ("\f\n");
31     }                           /* if */
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");
41         }                       /* if */
42     }                           /* if */
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;
57     }                           /* if */
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");
72     }                           /* if */
73 }                               /* print_header */
74
75
76 /*
77  * Print a cycle header.
78  */
79 static void
80 DEFUN (print_cycle, (cyc), Sym * cyc)
81 {
82   char buf[BUFSIZ];
83
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", "");
95     }                           /* if */
96   printf (" <cycle %d as a whole>\t[%d]\n", cyc->cg.cyc.num, cyc->cg.index);
97 }                               /* print_cycle */
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  */
104 static int
105 DEFUN (cmp_member, (left, right), Sym * left AND Sym * right)
106 {
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;
115     }                           /* if */
116   if (left_time < right_time)
117     {
118       return LESSTHAN;
119     }                           /* if */
120
121   if (left_calls > right_calls)
122     {
123       return GREATERTHAN;
124     }                           /* if */
125   if (left_calls < right_calls)
126     {
127       return LESSTHAN;
128     }                           /* if */
129   return EQUALTO;
130 }                               /* cmp_member */
131
132
133 /*
134  * Sort members of a cycle.
135  */
136 static void
137 DEFUN (sort_members, (cyc), Sym * cyc)
138 {
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;
154             }                   /* if */
155         }                       /* for */
156       doing->cg.cyc.next = prev->cg.cyc.next;
157       prev->cg.cyc.next = doing;
158     }                           /* for */
159 }                               /* sort_members */
160
161
162 /*
163  * Print the members of a cycle.
164  */
165 static void
166 DEFUN (print_members, (cyc), Sym * cyc)
167 {
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", "");
183         }                       /* if */
184       printf ("     ");
185       print_name (member);
186       printf ("\n");
187     }                           /* for */
188 }                               /* print_members */
189
190
191 /*
192  * Compare two arcs to/from the same child/parent.
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
199  */
200 static int
201 DEFUN (cmp_arc, (left, right), Arc * left AND Arc * right)
202 {
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,
215                left->count, left_child->ncalls);
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,
221                right->count, right_child->ncalls);
222        printf ("\n");
223     );
224   if (left_parent == left_child)
225     {
226       return LESSTHAN;          /* left is a self call */
227     }                           /* if */
228   if (right_parent == right_child)
229     {
230       return GREATERTHAN;       /* right is a self call */
231     }                           /* if */
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;
244             }                   /* if */
245           if (left->count > right->count)
246             {
247               return GREATERTHAN;
248             }                   /* if */
249           return EQUALTO;
250         }
251       else
252         {
253           /* right isn't a call within the cycle */
254           return LESSTHAN;
255         }                       /* if */
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)
262         {
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;
274             }                   /* if */
275           if (left_time > right_time)
276             {
277               return GREATERTHAN;
278             }                   /* if */
279           if (left->count < right->count)
280             {
281               return LESSTHAN;
282             }                   /* if */
283           if (left->count > right->count)
284             {
285               return GREATERTHAN;
286             }                   /* if */
287           return EQUALTO;
288         }                       /* if */
289     }                           /* if */
290 }                               /* cmp_arc */
291
292
293 static void
294 DEFUN (sort_parents, (child), Sym * child)
295 {
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;
317             }                   /* if */
318         }                       /* for */
319       arc->next_parent = prev->next_parent;
320       prev->next_parent = arc;
321     }                           /* for */
322
323   /* reattach sorted arcs to child: */
324   child->cg.parents = sorted.next_parent;
325 }                               /* sort_parents */
326
327
328 static void
329 DEFUN (print_parents, (child), Sym * child)
330 {
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;
342     }                           /* if */
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;
350     }                           /* if */
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))
357         {
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");
378         }                       /* if */
379     }                           /* for */
380 }                               /* print_parents */
381
382
383 static void
384 DEFUN (sort_children, (parent), Sym * parent)
385 {
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;
406             }                   /* if */
407         }                       /* for */
408       arc->next_child = prev->next_child;
409       prev->next_child = arc;
410     }                           /* for */
411
412   /* reattach sorted children to parent: */
413   parent->cg.children = sorted.next_child;
414 }                               /* sort_children */
415
416
417 static void
418 DEFUN (print_children, (parent), Sym * parent)
419 {
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
440         {
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");
450         }                       /* if */
451     }                           /* for */
452 }                               /* print_children */
453
454
455 static void
456 DEFUN (print_line, (np), Sym * np)
457 {
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 ", "");
476         }                       /* if */
477     }
478   else
479     {
480       printf (" %7.7s %7.7s ", "", "");
481     }                           /* if */
482   print_name (np);
483   printf ("\n");
484 }                               /* print_line */
485
486
487 /*
488  * Print dynamic call graph.
489  */
490 void
491 DEFUN (cg_print, (timesortsym), Sym ** timesortsym)
492 {
493   int index;
494   Sym *parent;
495
496   if (print_descriptions && bsd_style_output)
497     {
498       bsd_callg_blurb (stdout);
499     }                           /* if */
500
501   print_header ();
502
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;
512         }                       /* if */
513       if (!parent->name && parent->cg.cyc.num != 0)
514         {
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);
524         }                       /* if */
525       if (bsd_style_output)
526         printf ("\n");
527       printf ("-----------------------------------------------\n");
528       if (bsd_style_output)
529         printf ("\n");
530     }
531   free (timesortsym);
532   if (print_descriptions && !bsd_style_output)
533     {
534       fsf_callg_blurb (stdout);
535     }
536 }                               /* cg_print */
537
538
539 static int
540 DEFUN (cmp_name, (left, right), const PTR left AND const PTR right)
541 {
542   const Sym **npp1 = (const Sym **) left;
543   const Sym **npp2 = (const Sym **) right;
544
545   return strcmp ((*npp1)->name, (*npp2)->name);
546 }                               /* cmp_name */
547
548
549 void
550 DEFUN_VOID (cg_print_index)
551 {
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;
568         }                       /* if */
569       name_sorted_syms[nnames++] = &symtab.base[index];
570     }                           /* for */
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];
575     }                           /* for */
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)
583         {
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);
592             }                   /* if */
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 (' ');
605                     }           /* for */
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;
621                             }   /* if */
622                         }       /* if */
623                       printf (" (%s)", filename);
624                       col += strlen (filename) + 3;
625                     }           /* if */
626                 }               /* if */
627             }
628           else
629             {
630               printf ("%6.6s ", buf);
631               sprintf (buf, "<cycle %d>", sym->cg.cyc.num);
632               printf ("%-19.19s", buf);
633             }                   /* if */
634           starting_col += column_width;
635         }                       /* for */
636       printf ("\n");
637     }                           /* for */
638   free (name_sorted_syms);
639 }                               /* cg_print_index */
640
641 /*** end of cg_print.c ***/