]> Git Repo - binutils.git/blob - gprof/printgprof.c
Support for the Z8000
[binutils.git] / gprof / printgprof.c
1 /*
2  * Copyright (c) 1983 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that: (1) source distributions retain this entire copyright
7  * notice and comment, and (2) distributions including binaries display
8  * the following acknowledgement:  ``This product includes software
9  * developed by the University of California, Berkeley and its contributors''
10  * in the documentation or other materials provided with the distribution
11  * and in all advertising materials mentioning features or use of this
12  * software. Neither the name of the University nor the names of its
13  * contributors may be used to endorse or promote products derived
14  * from this software without specific prior written permission.
15  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18  */
19
20 #ifndef lint
21 static char sccsid[] = "@(#)printgprof.c        5.7 (Berkeley) 6/1/90";
22 #endif /* not lint */
23
24 #include "gprof.h"
25
26 printprof()
27 {
28     register nltype     *np;
29     nltype              **sortednlp;
30     int                 index, timecmp();
31
32     actime = 0.0;
33     printf( "\f\n" );
34     flatprofheader();
35         /*
36          *      Sort the symbol table in by time
37          */
38     sortednlp = (nltype **) calloc( nname , sizeof(nltype *) );
39     if ( sortednlp == (nltype **) 0 ) {
40         fprintf( stderr , "[printprof] ran out of memory for time sorting\n" );
41     }
42     for ( index = 0 ; index < nname ; index += 1 ) {
43         sortednlp[ index ] = &nl[ index ];
44     }
45     qsort( sortednlp , nname , sizeof(nltype *) , timecmp );
46     for ( index = 0 ; index < nname ; index += 1 ) {
47         np = sortednlp[ index ];
48         flatprofline( np );
49     }
50     actime = 0.0;
51     cfree( sortednlp );
52 }
53
54 timecmp( npp1 , npp2 )
55     nltype **npp1, **npp2;
56 {
57     double      timediff;
58     long        calldiff;
59
60     timediff = (*npp2) -> time - (*npp1) -> time;
61     if ( timediff > 0.0 )
62         return 1 ;
63     if ( timediff < 0.0 )
64         return -1;
65     calldiff = (*npp2) -> ncall - (*npp1) -> ncall;
66     if ( calldiff > 0 )
67         return 1;
68     if ( calldiff < 0 )
69         return -1;
70     return( strcmp( (*npp1) -> name , (*npp2) -> name ) );
71 }
72
73     /*
74      *  header for flatprofline
75      */
76 flatprofheader()
77 {
78     
79     if ( bflag ) {
80         flat_blurb(stdout);
81     }
82     printf( "\ngranularity: each sample hit covers %d byte(s)" ,
83             (long) scale * sizeof(UNIT) );
84     if ( totime > 0.0 ) {
85         printf( " for %.2f%% of %.2f seconds\n\n" ,
86                 100.0/totime , totime / hz );
87     } else {
88         printf( " no time accumulated\n\n" );
89             /*
90              *  this doesn't hurt since all the numerators will be zero.
91              */
92         totime = 1.0;
93     }
94     printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s  %-8.8s\n" ,
95             "%  " , "cumulative" , "self  " , "" , "self  " , "total " , "" );
96     printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s  %-8.8s\n" ,
97             "time" , "seconds " , "seconds" , "calls" ,
98             "ms/call" , "ms/call" , "name" );
99 }
100
101 flatprofline( np )
102     register nltype     *np;
103 {
104
105     if ( zflag == 0 && np -> ncall == 0 && np -> time == 0 ) {
106         return;
107     }
108     actime += np -> time;
109     printf( "%5.1f %10.2f %8.2f" ,
110         100 * np -> time / totime , actime / hz , np -> time / hz );
111     if ( np -> ncall != 0 ) {
112         printf( " %8d %8.2f %8.2f  " , np -> ncall ,
113             1000 * np -> time / hz / np -> ncall ,
114             1000 * ( np -> time + np -> childtime ) / hz / np -> ncall );
115     } else {
116         printf( " %8.8s %8.8s %8.8s  " , "" , "" , "" );
117     }
118     printname( np );
119     printf( "\n" );
120 }
121
122 gprofheader()
123 {
124
125     if ( bflag ) {
126         callg_blurb(stdout);
127     }
128     printf( "\ngranularity: each sample hit covers %d byte(s)" ,
129             (long) scale * sizeof(UNIT) );
130     if ( printtime > 0.0 ) {
131         printf( " for %.2f%% of %.2f seconds\n\n" ,
132                 100.0/printtime , printtime / hz );
133     } else {
134         printf( " no time propagated\n\n" );
135             /*
136              *  this doesn't hurt, since all the numerators will be 0.0
137              */
138         printtime = 1.0;
139     }
140     printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s     %-8.8s\n" ,
141         "" , "" , "" , "" , "called" , "total" , "parents");
142     printf( "%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n" ,
143         "index" , "%time" , "self" , "descendents" ,
144         "called" , "self" , "name" , "index" );
145     printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s     %-8.8s\n" ,
146         "" , "" , "" , "" , "called" , "total" , "children");
147     printf( "\n" );
148 }
149
150 gprofline( np )
151     register nltype     *np;
152 {
153     char        kirkbuffer[ BUFSIZ ];
154
155     sprintf( kirkbuffer , "[%d]" , np -> index );
156     printf( "%-6.6s %5.1f %7.2f %11.2f" ,
157             kirkbuffer ,
158             100 * ( np -> propself + np -> propchild ) / printtime ,
159             np -> propself / hz ,
160             np -> propchild / hz );
161     if ( ( np -> ncall + np -> selfcalls ) != 0 ) {
162         printf( " %7d" , np -> ncall );
163         if ( np -> selfcalls != 0 ) {
164             printf( "+%-7d " , np -> selfcalls );
165         } else {
166             printf( " %7.7s " , "" );
167         }
168     } else {
169         printf( " %7.7s %7.7s " , "" , "" );
170     }
171     printname( np );
172     printf( "\n" );
173 }
174
175 printgprof(timesortnlp)
176     nltype      **timesortnlp;
177 {
178     int         index;
179     nltype      *parentp;
180
181         /*
182          *      Print out the structured profiling list
183          */
184     gprofheader();
185     for ( index = 0 ; index < nname + ncycle ; index ++ ) {
186         parentp = timesortnlp[ index ];
187         if ( zflag == 0 &&
188              parentp -> ncall == 0 &&
189              parentp -> selfcalls == 0 &&
190              parentp -> propself == 0 &&
191              parentp -> propchild == 0 ) {
192             continue;
193         }
194         if ( ! parentp -> printflag ) {
195             continue;
196         }
197         if ( parentp -> name == 0 && parentp -> cycleno != 0 ) {
198                 /*
199                  *      cycle header
200                  */
201             printcycle( parentp );
202             printmembers( parentp );
203         } else {
204             printparents( parentp );
205             gprofline( parentp );
206             printchildren( parentp );
207         }
208         printf( "\n" );
209         printf( "-----------------------------------------------\n" );
210         printf( "\n" );
211     }
212     cfree( timesortnlp );
213 }
214
215     /*
216      *  sort by decreasing propagated time
217      *  if times are equal, but one is a cycle header,
218      *          say that's first (e.g. less, i.e. -1).
219      *  if one's name doesn't have an underscore and the other does,
220      *          say the one is first.
221      *  all else being equal, sort by names.
222      */
223 int
224 totalcmp( npp1 , npp2 )
225     nltype      **npp1;
226     nltype      **npp2;
227 {
228     register nltype     *np1 = *npp1;
229     register nltype     *np2 = *npp2;
230     double              diff;
231
232     diff =    ( np1 -> propself + np1 -> propchild )
233             - ( np2 -> propself + np2 -> propchild );
234     if ( diff < 0.0 )
235             return 1;
236     if ( diff > 0.0 )
237             return -1;
238     if ( np1 -> name == 0 && np1 -> cycleno != 0 ) 
239         return -1;
240     if ( np2 -> name == 0 && np2 -> cycleno != 0 )
241         return 1;
242     if ( np1 -> name == 0 )
243         return -1;
244     if ( np2 -> name == 0 )
245         return 1;
246     if ( *(np1 -> name) != '_' && *(np2 -> name) == '_' )
247         return -1;
248     if ( *(np1 -> name) == '_' && *(np2 -> name) != '_' )
249         return 1;
250     if ( np1 -> ncall > np2 -> ncall )
251         return -1;
252     if ( np1 -> ncall < np2 -> ncall ) 
253         return 1;
254     return strcmp( np1 -> name , np2 -> name );
255 }
256
257 printparents( childp )
258     nltype      *childp;
259 {
260     nltype      *parentp;
261     arctype     *arcp;
262     nltype      *cycleheadp;
263
264     if ( childp -> cyclehead != 0 ) {
265         cycleheadp = childp -> cyclehead;
266     } else {
267         cycleheadp = childp;
268     }
269     if ( childp -> parents == 0 ) {
270         printf( "%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s     <spontaneous>\n" ,
271                 "" , "" , "" , "" , "" , "" );
272         return;
273     }
274     sortparents( childp );
275     for ( arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist ) {
276         parentp = arcp -> arc_parentp;
277         if ( childp == parentp ||
278              ( childp->cycleno != 0 && parentp->cycleno == childp->cycleno ) ) {
279                 /*
280                  *      selfcall or call among siblings
281                  */
282             printf( "%6.6s %5.5s %7.7s %11.11s %7d %7.7s     " ,
283                     "" , "" , "" , "" ,
284                     arcp -> arc_count , "" );
285             printname( parentp );
286             printf( "\n" );
287         } else {
288                 /*
289                  *      regular parent of child
290                  */
291             printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d     " ,
292                     "" , "" ,
293                     arcp -> arc_time / hz , arcp -> arc_childtime / hz ,
294                     arcp -> arc_count , cycleheadp -> ncall );
295             printname( parentp );
296             printf( "\n" );
297         }
298     }
299 }
300
301 printchildren( parentp )
302     nltype      *parentp;
303 {
304     nltype      *childp;
305     arctype     *arcp;
306
307     sortchildren( parentp );
308     arcp = parentp -> children;
309     for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
310         childp = arcp -> arc_childp;
311         if ( childp == parentp ||
312             ( childp->cycleno != 0 && childp->cycleno == parentp->cycleno ) ) {
313                 /*
314                  *      self call or call to sibling
315                  */
316             printf( "%6.6s %5.5s %7.7s %11.11s %7d %7.7s     " ,
317                     "" , "" , "" , "" , arcp -> arc_count , "" );
318             printname( childp );
319             printf( "\n" );
320         } else {
321                 /*
322                  *      regular child of parent
323                  */
324             printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d     " ,
325                     "" , "" ,
326                     arcp -> arc_time / hz , arcp -> arc_childtime / hz ,
327                     arcp -> arc_count , childp -> cyclehead -> ncall );
328             printname( childp );
329             printf( "\n" );
330         }
331     }
332 }
333
334 printname( selfp )
335     nltype      *selfp;
336 {
337
338     if ( selfp -> name != 0 ) {
339         printf( "%s" , selfp -> name );
340 #       ifdef DEBUG
341             if ( debug & DFNDEBUG ) {
342                 printf( "{%d} " , selfp -> toporder );
343             }
344             if ( debug & PROPDEBUG ) {
345                 printf( "%5.2f%% " , selfp -> propfraction );
346             }
347 #       endif DEBUG
348     }
349     if ( selfp -> cycleno != 0 ) {
350         printf( " <cycle %d>" , selfp -> cycleno );
351     }
352     if ( selfp -> index != 0 ) {
353         if ( selfp -> printflag ) {
354             printf( " [%d]" , selfp -> index );
355         } else {
356             printf( " (%d)" , selfp -> index );
357         }
358     }
359 }
360
361 sortchildren( parentp )
362     nltype      *parentp;
363 {
364     arctype     *arcp;
365     arctype     *detachedp;
366     arctype     sorted;
367     arctype     *prevp;
368
369         /*
370          *      unlink children from parent,
371          *      then insertion sort back on to sorted's children.
372          *          *arcp       the arc you have detached and are inserting.
373          *          *detachedp  the rest of the arcs to be sorted.
374          *          sorted      arc list onto which you insertion sort.
375          *          *prevp      arc before the arc you are comparing.
376          */
377     sorted.arc_childlist = 0;
378     for (  (arcp = parentp -> children)&&(detachedp = arcp -> arc_childlist);
379             arcp ;
380            (arcp = detachedp)&&(detachedp = detachedp -> arc_childlist)) {
381             /*
382              *  consider *arcp as disconnected
383              *  insert it into sorted
384              */
385         for (   prevp = &sorted ;
386                 prevp -> arc_childlist ;
387                 prevp = prevp -> arc_childlist ) {
388             if ( arccmp( arcp , prevp -> arc_childlist ) != LESSTHAN ) {
389                 break;
390             }
391         }
392         arcp -> arc_childlist = prevp -> arc_childlist;
393         prevp -> arc_childlist = arcp;
394     }
395         /*
396          *      reattach sorted children to parent
397          */
398     parentp -> children = sorted.arc_childlist;
399 }
400
401 sortparents( childp )
402     nltype      *childp;
403 {
404     arctype     *arcp;
405     arctype     *detachedp;
406     arctype     sorted;
407     arctype     *prevp;
408
409         /*
410          *      unlink parents from child,
411          *      then insertion sort back on to sorted's parents.
412          *          *arcp       the arc you have detached and are inserting.
413          *          *detachedp  the rest of the arcs to be sorted.
414          *          sorted      arc list onto which you insertion sort.
415          *          *prevp      arc before the arc you are comparing.
416          */
417     sorted.arc_parentlist = 0;
418     for (  (arcp = childp -> parents)&&(detachedp = arcp -> arc_parentlist);
419             arcp ;
420            (arcp = detachedp)&&(detachedp = detachedp -> arc_parentlist)) {
421             /*
422              *  consider *arcp as disconnected
423              *  insert it into sorted
424              */
425         for (   prevp = &sorted ;
426                 prevp -> arc_parentlist ;
427                 prevp = prevp -> arc_parentlist ) {
428             if ( arccmp( arcp , prevp -> arc_parentlist ) != GREATERTHAN ) {
429                 break;
430             }
431         }
432         arcp -> arc_parentlist = prevp -> arc_parentlist;
433         prevp -> arc_parentlist = arcp;
434     }
435         /*
436          *      reattach sorted arcs to child
437          */
438     childp -> parents = sorted.arc_parentlist;
439 }
440
441     /*
442      *  print a cycle header
443      */
444 printcycle( cyclep )
445     nltype      *cyclep;
446 {
447     char        kirkbuffer[ BUFSIZ ];
448
449     sprintf( kirkbuffer , "[%d]" , cyclep -> index );
450     printf( "%-6.6s %5.1f %7.2f %11.2f %7d" ,
451             kirkbuffer ,
452             100 * ( cyclep -> propself + cyclep -> propchild ) / printtime ,
453             cyclep -> propself / hz ,
454             cyclep -> propchild / hz ,
455             cyclep -> ncall );
456     if ( cyclep -> selfcalls != 0 ) {
457         printf( "+%-7d" , cyclep -> selfcalls );
458     } else {
459         printf( " %7.7s" , "" );
460     }
461     printf( " <cycle %d as a whole>\t[%d]\n" ,
462             cyclep -> cycleno , cyclep -> index );
463 }
464
465     /*
466      *  print the members of a cycle
467      */
468 printmembers( cyclep )
469     nltype      *cyclep;
470 {
471     nltype      *memberp;
472
473     sortmembers( cyclep );
474     for ( memberp = cyclep -> cnext ; memberp ; memberp = memberp -> cnext ) {
475         printf( "%6.6s %5.5s %7.2f %11.2f %7d" , 
476                 "" , "" , memberp -> propself / hz , memberp -> propchild / hz ,
477                 memberp -> ncall );
478         if ( memberp -> selfcalls != 0 ) {
479             printf( "+%-7d" , memberp -> selfcalls );
480         } else {
481             printf( " %7.7s" , "" );
482         }
483         printf( "     " );
484         printname( memberp );
485         printf( "\n" );
486     }
487 }
488
489     /*
490      *  sort members of a cycle
491      */
492 sortmembers( cyclep )
493     nltype      *cyclep;
494 {
495     nltype      *todo;
496     nltype      *doing;
497     nltype      *prev;
498
499         /*
500          *      detach cycle members from cyclehead,
501          *      and insertion sort them back on.
502          */
503     todo = cyclep -> cnext;
504     cyclep -> cnext = 0;
505     for (  (doing = todo)&&(todo = doing -> cnext);
506             doing ;
507            (doing = todo )&&(todo = doing -> cnext )){
508         for ( prev = cyclep ; prev -> cnext ; prev = prev -> cnext ) {
509             if ( membercmp( doing , prev -> cnext ) == GREATERTHAN ) {
510                 break;
511             }
512         }
513         doing -> cnext = prev -> cnext;
514         prev -> cnext = doing;
515     }
516 }
517
518     /*
519      *  major sort is on propself + propchild,
520      *  next is sort on ncalls + selfcalls.
521      */
522 int
523 membercmp( this , that )
524     nltype      *this;
525     nltype      *that;
526 {
527     double      thistime = this -> propself + this -> propchild;
528     double      thattime = that -> propself + that -> propchild;
529     long        thiscalls = this -> ncall + this -> selfcalls;
530     long        thatcalls = that -> ncall + that -> selfcalls;
531
532     if ( thistime > thattime ) {
533         return GREATERTHAN;
534     }
535     if ( thistime < thattime ) {
536         return LESSTHAN;
537     }
538     if ( thiscalls > thatcalls ) {
539         return GREATERTHAN;
540     }
541     if ( thiscalls < thatcalls ) {
542         return LESSTHAN;
543     }
544     return EQUALTO;
545 }
546     /*
547      *  compare two arcs to/from the same child/parent.
548      *  - if one arc is a self arc, it's least.
549      *  - if one arc is within a cycle, it's less than.
550      *  - if both arcs are within a cycle, compare arc counts.
551      *  - if neither arc is within a cycle, compare with
552      *          arc_time + arc_childtime as major key
553      *          arc count as minor key
554      */
555 int
556 arccmp( thisp , thatp )
557     arctype     *thisp;
558     arctype     *thatp;
559 {
560     nltype      *thisparentp = thisp -> arc_parentp;
561     nltype      *thischildp = thisp -> arc_childp;
562     nltype      *thatparentp = thatp -> arc_parentp;
563     nltype      *thatchildp = thatp -> arc_childp;
564     double      thistime;
565     double      thattime;
566
567 #   ifdef DEBUG
568         if ( debug & TIMEDEBUG ) {
569             printf( "[arccmp] " );
570             printname( thisparentp );
571             printf( " calls " );
572             printname ( thischildp );
573             printf( " %f + %f %d/%d\n" ,
574                     thisp -> arc_time , thisp -> arc_childtime ,
575                     thisp -> arc_count , thischildp -> ncall );
576             printf( "[arccmp] " );
577             printname( thatparentp );
578             printf( " calls " );
579             printname( thatchildp );
580             printf( " %f + %f %d/%d\n" ,
581                     thatp -> arc_time , thatp -> arc_childtime ,
582                     thatp -> arc_count , thatchildp -> ncall );
583             printf( "\n" );
584         }
585 #   endif DEBUG
586     if ( thisparentp == thischildp ) {
587             /* this is a self call */
588         return LESSTHAN;
589     }
590     if ( thatparentp == thatchildp ) {
591             /* that is a self call */
592         return GREATERTHAN;
593     }
594     if ( thisparentp -> cycleno != 0 && thischildp -> cycleno != 0 &&
595         thisparentp -> cycleno == thischildp -> cycleno ) {
596             /* this is a call within a cycle */
597         if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 &&
598             thatparentp -> cycleno == thatchildp -> cycleno ) {
599                 /* that is a call within the cycle, too */
600             if ( thisp -> arc_count < thatp -> arc_count ) {
601                 return LESSTHAN;
602             }
603             if ( thisp -> arc_count > thatp -> arc_count ) {
604                 return GREATERTHAN;
605             }
606             return EQUALTO;
607         } else {
608                 /* that isn't a call within the cycle */
609             return LESSTHAN;
610         }
611     } else {
612             /* this isn't a call within a cycle */
613         if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 &&
614             thatparentp -> cycleno == thatchildp -> cycleno ) {
615                 /* that is a call within a cycle */
616             return GREATERTHAN;
617         } else {
618                 /* neither is a call within a cycle */
619             thistime = thisp -> arc_time + thisp -> arc_childtime;
620             thattime = thatp -> arc_time + thatp -> arc_childtime;
621             if ( thistime < thattime )
622                 return LESSTHAN;
623             if ( thistime > thattime )
624                 return GREATERTHAN;
625             if ( thisp -> arc_count < thatp -> arc_count )
626                 return LESSTHAN;
627             if ( thisp -> arc_count > thatp -> arc_count )
628                 return GREATERTHAN;
629             return EQUALTO;
630         }
631     }
632 }
633
634 int
635 namecmp( npp1 , npp2 )
636     nltype **npp1, **npp2;
637 {
638     return( strcmp( (*npp1) -> name , (*npp2) -> name ) );
639 }
640
641 printindex()
642 {
643     nltype              **namesortnlp;
644     register nltype     *nlp;
645     int                 index, nnames, todo, i, j;
646     char                peterbuffer[ BUFSIZ ];
647
648         /*
649          *      Now, sort regular function name alphbetically
650          *      to create an index.
651          */
652     namesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) );
653     if ( namesortnlp == (nltype **) 0 ) {
654         fprintf( stderr , "%s: ran out of memory for sorting\n" , whoami );
655     }
656     for ( index = 0 , nnames = 0 ; index < nname ; index++ ) {
657         if ( zflag == 0 && nl[index].ncall == 0 && nl[index].time == 0 )
658                 continue;
659         namesortnlp[nnames++] = &nl[index];
660     }
661     qsort( namesortnlp , nnames , sizeof(nltype *) , namecmp );
662     for ( index = 1 , todo = nnames ; index <= ncycle ; index++ ) {
663         namesortnlp[todo++] = &cyclenl[index];
664     }
665     printf( "\f\nIndex by function name\n\n" );
666     index = ( todo + 2 ) / 3;
667     for ( i = 0; i < index ; i++ ) {
668         for ( j = i; j < todo ; j += index ) {
669             nlp = namesortnlp[ j ];
670             if ( nlp -> printflag ) {
671                 sprintf( peterbuffer , "[%d]" , nlp -> index );
672             } else {
673                 sprintf( peterbuffer , "(%d)" , nlp -> index );
674             }
675             if ( j < nnames ) {
676                 printf( "%6.6s %-19.19s" , peterbuffer , nlp -> name );
677             } else {
678                 printf( "%6.6s " , peterbuffer );
679                 sprintf( peterbuffer , "<cycle %d>" , nlp -> cycleno );
680                 printf( "%-19.19s" , peterbuffer );
681             }
682         }
683         printf( "\n" );
684     }
685     cfree( namesortnlp );
686 }
This page took 0.063188 seconds and 4 git commands to generate.