Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
ir_prof.c
Go to the documentation of this file.
00001 /*
00002 
00003   Copyright (C) 2000, 2001 Silicon Graphics, Inc.  All Rights Reserved.
00004 
00005   This program is free software; you can redistribute it and/or modify it
00006   under the terms of version 2 of the GNU General Public License as
00007   published by the Free Software Foundation.
00008 
00009   This program is distributed in the hope that it would be useful, but
00010   WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00012 
00013   Further, this software is distributed without any warranty that it is
00014   free of the rightful claim of any third person regarding infringement 
00015   or the like.  Any license provided herein, whether implied or 
00016   otherwise, applies only to this software file.  Patent licenses, if 
00017   any, provided herein do not apply to combinations of this program with 
00018   other software, or any other product whatsoever.  
00019 
00020   You should have received a copy of the GNU General Public License along
00021   with this program; if not, write the Free Software Foundation, Inc., 59
00022   Temple Place - Suite 330, Boston MA 02111-1307, USA.
00023 
00024   Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pky,
00025   Mountain View, CA 94043, or:
00026 
00027   http://www.sgi.com
00028 
00029   For further information regarding this notice, see:
00030 
00031   http://oss.sgi.com/projects/GenInfo/NoticeExplan
00032 
00033 */
00034 
00035 
00036 #include <errno.h>                  /* for sys_errlist */
00037 #include <stdio.h>                  /* for stderr */
00038 #include <fcntl.h>
00039 #include <libgen.h>                 /* for basename() */
00040 #include <sys/stat.h>
00041 #include "ir_prof.h"
00042 static char *thisfile = __FILE__;
00043 
00044 
00045 static int fd_counts;   /* counts file handle */
00046 
00047 #define FALSE 0
00048 #define TRUE  1
00049 #define NUM_COUNTS_ENTRY 4097
00050 #define SAMPLE_SIZE 15
00051 
00052 static counts_entry *counts_array;
00053 static long   num_counts;
00054 static long   sizeof_counts_array = NUM_COUNTS_ENTRY;
00055 
00056 typedef struct {
00057     unsigned *phash;   /* the hash */
00058     unsigned *chain;   /* real symbol chain */
00059     char     *strtab;
00060     unsigned  nchain;  /* # of syms in chain */
00061     unsigned  size;    /* number of buckets */
00062     unsigned  nsym;    /* max # of syms in chain */
00063     unsigned  strsize;
00064     unsigned  nchars;
00065 } HASH_STRUCT;
00066 
00067 #define DEF_STRSIZE 3
00068 #define DEF_NBUCKETS (NUM_COUNTS_ENTRY-1)
00069 #define DEF_NSYM (NUM_COUNTS_ENTRY-1)
00070 #define UNDEF -1
00071 static HASH_STRUCT h_tab;
00072 
00073 extern void hashinit(void);
00074 
00075 
00076 
00077 extern void *atexit();
00078 
00079 extern int
00080 file_exists (char *path)
00081 {
00082   int st;
00083   struct stat sbuf;
00084   st = stat(path, &sbuf);
00085   if (st == -1 && (errno == ENOENT || errno == ENOTDIR))
00086     return FALSE;
00087   else
00088     return TRUE;
00089 }
00090 
00091 
00092 static void
00093 usage (char *progname)
00094 {
00095   fprintf (stderr, "Usage: %s [-v] <Binary IR>\n", progname);
00096   fprintf (stderr, "\t-v option will print out verbose info\n");
00097   fprintf (stderr, "\tall sizes are in bytes\n");
00098   exit (1);
00099 }
00100 
00101 
00102 #define PR_ASSERT(EX, p)      if (!(EX)) ir_prof_error(ER_FATAL, p, "Ir_pr")
00103 #define MALLOC(nbytes)        malloc((size_t)(nbytes))
00104 #define REALLOC(ptr, size)    realloc((void *)(ptr), (size_t)(size))
00105 
00106 void 
00107 ir_prof_dump(void)
00108 {
00109   int i;
00110  
00111   printf("Edge Counts Dump: (%d), total = %d\n", num_counts, SAMPLE_SIZE);
00112   for (i=0; i < num_counts; i++) {
00113     printf("\t0x%x : 0x%x\t%d\t%s(%d):\t%s(%d)\n", 
00114            counts_array[i].caller, counts_array[i].callee, counts_array[i].count,
00115            (h_tab.strtab + counts_array[i].caller_name_idx),counts_array[i].caller_name_idx,
00116            (h_tab.strtab + counts_array[i].callee_name_idx),counts_array[i].callee_name_idx);
00117   }
00118 }
00119 
00120 
00121 void 
00122 ir_prof_error(int type, char *fmt, char *fname)
00123 {
00124     fprintf (stderr, "%s: ", "Ir_prof");
00125     fprintf(stderr, fmt, fname);
00126     fputc('\n', stderr);
00127     fflush(stderr);
00128     switch (type) {
00129     ER_FATAL:
00130       exit(1);
00131     ER_WARNING:
00132     ER_INFO:
00133     ER_ERROR:
00134     ER_VERBOSE:
00135     ER_MSG:
00136       return;
00137     }
00138 }
00139 
00140 
00141 void
00142 ir_prof_start(void)
00143 {
00144   char *errmsg;
00145 
00146   counts_array = (counts_entry *)(MALLOC(NUM_COUNTS_ENTRY * sizeof(counts_entry)));
00147   PR_ASSERT(counts_array, "ir_prof_start: malloc of counts_entry returns null");
00148   num_counts = 0;
00149   hashinit();
00150   return;
00151 }
00152 
00153 
00154 void 
00155 ir_prof_dump_counts(int fd_counts)
00156 {
00157   Counts_hdr hdr;
00158 
00159   PR_ASSERT(fd_counts, "ir_prof_dump_counts: fd_counts is null");
00160 
00161   hdr.c_ident[0] = COUNTSMAG0;
00162   hdr.c_ident[1] = COUNTSMAG1;
00163   hdr.c_ident[2] = COUNTSMAG2;
00164   hdr.c_ident[3] = COUNTSMAG3;
00165   hdr.c_ident[4] = COUNTSMAG4;
00166   hdr.c_ident[5] = COUNTSMAG5;
00167   hdr.c_ident[6] = COUNTSMAG6;
00168   hdr.c_ident[7] = COUNTSMAG7;
00169   hdr.c_entry = num_counts;
00170   hdr.c_version = C_VERSION;
00171   hdr.c_dummy1 = 0;
00172 #ifdef _64BIT
00173   hdr.c_dummy2 = 0;
00174   hdr.c_dummy3 = 0;
00175 #endif
00176   write(fd_counts, (char *)&hdr, sizeof(hdr));
00177   write(fd_counts, (char *)counts_array, sizeof(counts_entry)*num_counts);
00178   write(fd_counts, h_tab.strtab, h_tab.nchars);
00179 }
00180 
00181 
00182 void
00183 cgt_fini(void)
00184 {
00185   char *errmsg;
00186   char *name = "junk.prof";
00187   int file_exists = 0;
00188   struct stat statbuf;
00189   int res, fd_counts;
00190 
00191   if (num_counts == 0)
00192     return;
00193 
00194   res = stat(name,&statbuf);
00195   if (res < 0) {
00196     if(errno == ENOENT) {
00197       /* file does not exist */
00198       if ((fd_counts = open(name, O_RDWR|O_CREAT, 0555)) < 0) {
00199         errmsg = sys_errlist[errno];
00200         ir_prof_error(ER_FATAL, "Unable to open addr_counts file: %s", name);
00201       }
00202     } else {
00203       errmsg = sys_errlist[errno];
00204       ir_prof_error(ER_FATAL, "Unable to open addr_counts file: %s", name);
00205     }
00206   } 
00207   else { /* file exists */
00208     file_exists = 1;
00209     if ((fd_counts = open(name, O_RDWR|O_TRUNC, 0555)) == 0) {
00210       errmsg = sys_errlist[errno];
00211       ir_prof_error(ER_FATAL, "Existing addr_counts file open error: %s", name);
00212     }
00213   }
00214 
00215   /* sort and flush counts */
00216   (void)ir_prof_dump();
00217   ir_prof_dump_counts(fd_counts);
00218   /* close the file. */
00219   close (fd_counts);
00220 }
00221 
00222 
00223 void 
00224 ir_prof_init(void)
00225 {
00226   void (*pf)() = cgt_fini;
00227   num_counts = 0;
00228   atexit(pf);
00229 }
00230 
00231 
00232 void hashinit()
00233 {
00234     unsigned *p;
00235 
00236     h_tab.nchain = 0;
00237     h_tab.strsize = DEF_STRSIZE;
00238 
00239     if ((p = (unsigned *)malloc(h_tab.strsize)) == (unsigned *)0)
00240         ir_prof_error(ER_FATAL, "Malloc error in %s\n", "malloc strtab");
00241     h_tab.strtab = (char *)p;
00242     p[0] = '\0';     /* first entry in strtab is a null */
00243     h_tab.nchars = 1;
00244 
00245     if ((p = (unsigned *)malloc(DEF_NBUCKETS * sizeof(unsigned))) == (unsigned *)0)
00246         ir_prof_error(ER_FATAL, "Malloc error in %s\n", "malloc hash");
00247     memset((char *)p, -1, DEF_NBUCKETS * sizeof(unsigned));
00248     h_tab.phash = p;
00249     h_tab.size = DEF_NBUCKETS;
00250    
00251     if ((p = (unsigned *)malloc(DEF_NSYM *sizeof(unsigned))) == (unsigned *)0)
00252         ir_prof_error(ER_FATAL, "Malloc error in %s\n", "hashtab");
00253     bzero (p, DEF_NSYM * sizeof(unsigned));
00254     h_tab.chain = p;
00255     h_tab.nsym = DEF_NSYM;
00256     return ;
00257 }
00258 
00259 
00260 void
00261 expand_htab()
00262 {
00263     unsigned *pnew;
00264     int nsym = h_tab.nsym * 2;
00265 
00266     if ((pnew = (unsigned *)realloc(h_tab.chain, nsym*sizeof(unsigned))) == 0)
00267         ir_prof_error(ER_FATAL, "Realloc error when %s", "expanding hash");
00268     h_tab.chain = pnew;
00269     bzero (&pnew[h_tab.nsym], h_tab.nsym * sizeof(unsigned));
00270     h_tab.nsym = nsym;
00271 }
00272 
00273 
00274 void
00275 expand_strtab(int i)
00276 {
00277   char *pnew;
00278 
00279   h_tab.strsize = 2 * (h_tab.strsize + i);
00280   if ((pnew = (char *)realloc(h_tab.strtab, h_tab.strsize)) == 0)
00281     ir_prof_error(ER_FATAL, "Realloc error when %s", "expanding strtab");
00282   h_tab.strtab = pnew;
00283 }
00284 
00285 
00286 int
00287 enter_str(char *name)
00288 {
00289   int i, ret;
00290   char *p = h_tab.strtab;
00291 
00292   if (name == 0 || name[0] == '\0')
00293     return 0;
00294 
00295   i = strlen(name) + 1;
00296   if ((i + h_tab.nchars) > h_tab.strsize) 
00297     expand_strtab(i);
00298 
00299   memcpy(h_tab.strtab + h_tab.nchars, name, i);
00300   ret = h_tab.nchars;
00301   h_tab.nchars += i;
00302   return ret;
00303 }
00304 
00305 
00306 static void
00307 hash_entry(ADDR caller, ADDR callee, char *caller_name, char *callee_name) 
00308 {
00309   unsigned *pchain = h_tab.chain;
00310   int y;
00311   int i = h_tab.nchain;
00312 
00313   /* the hash uses caller and callee address only, this will cause */
00314   /* duplication in the string table when either one of them is */
00315   /* different. I am ignoring that for now */
00316   int hash = ((caller + callee) & 0x0FFFFFFFF) % h_tab.size;
00317 
00318 /* printf("caller %x callee %x hash %d\n",caller, callee, hash);   */
00319   if ((y = h_tab.phash[hash]) == UNDEF) {
00320     if (h_tab.nchain == h_tab.nsym) {
00321       expand_htab();
00322       pchain = h_tab.chain;
00323     }
00324     pchain[i] = UNDEF;
00325 
00326     counts_array[i].count = 1;
00327     counts_array[i].caller = caller;
00328     counts_array[i].callee = callee;
00329     counts_array[i].caller_name_idx = enter_str(caller_name);
00330     counts_array[i].callee_name_idx = enter_str(callee_name);
00331 
00332     h_tab.phash[hash] = h_tab.nchain++;
00333     num_counts++;
00334 /* printf("not found and new\n"); */
00335     return;
00336   }
00337 
00338   while (y != UNDEF) {
00339     if (counts_array[y].caller == caller &&
00340         counts_array[y].callee == callee) {
00341       counts_array[y].count++;
00342 /* printf("found and count %d\n", counts_array[y].count); */
00343       return;
00344     }
00345     hash = y;
00346     y = pchain[y];
00347   }
00348 
00349   /* not found */
00350   pchain[hash] = h_tab.nchain;
00351   if (i == h_tab.nsym) {
00352     expand_htab();
00353     pchain = h_tab.chain;
00354   }
00355 /* printf("not found and old hash\n"); */
00356   pchain[i] = UNDEF;
00357 
00358   counts_array[i].caller = caller;
00359   counts_array[i].callee = callee;
00360   counts_array[i].caller_name_idx = enter_str(caller_name);
00361   counts_array[i].callee_name_idx = enter_str(callee_name);
00362   counts_array[i].count = 1;
00363   
00364   h_tab.nchain++;
00365   num_counts++;
00366   return;
00367 }
00368 
00369 
00370 void 
00371 __profile_call(ADDR caller, ADDR callee, char *caller_name, char *callee_name)
00372 {
00373 #ifdef _DEBUG
00374   return;
00375 #else
00376   if (num_counts == 0)
00377     ir_prof_start();
00378 
00379   if (num_counts == sizeof_counts_array) {
00380     sizeof_counts_array *= 2;
00381     counts_array = (counts_entry *)REALLOC(
00382                     counts_array, sizeof_counts_array);
00383     PR_ASSERT(counts_array, "realloc of counts_array failed");
00384   }
00385 
00386   hash_entry(caller, callee, caller_name, callee_name);
00387 #endif
00388 }
00389 
00390 
00391 
00392 #ifdef _MAIN_DEBUG
00393 
00394 
00395 struct counts_desc_char {
00396   char caller[9];
00397   char callee[9];
00398   int caller_idx;
00399   int callee_idx;
00400 };
00401 
00402 static char *str[6] = {
00403 "", "scan", "foo", "a", "longgggggggggggg", "new"};
00404 static struct counts_desc_char debugi[SAMPLE_SIZE] = {
00405 {"1000129c","1000129c",1, 1},
00406 {"1000133c","1000129c",2, 1},
00407 {"100012bc","1000129c",3, 1},
00408 {"1000127c","1000127c",4, 4},
00409 {"100012bc","100012ac",3, 0},
00410 {"1000127c","1000129c",4, 1},
00411 {"1000133c","1000129c",2, 1},
00412 {"1000129c","1000127c",1, 4},
00413 {"100012bc","1000129c",3, 1},
00414 {"10002340","1000129c",5, 1},
00415 {"1000127c","1000127c",4, 4},
00416 {"1000127c","1000127c",4, 4},
00417 {"100012bc","1000133c",3, 2},
00418 {"1000133c","10002340",2, 5},
00419 {"1000133c","1000127c",2, 4},
00420 };
00421 static counts_entry debug[SAMPLE_SIZE];
00422 
00423 
00424 long h2d(char *p)
00425 {
00426   int i;
00427   long val = 0;
00428   long ret = 0;
00429 
00430   for (i=0; i < 8; i++) {
00431     if (p[i] < '0' || p[i] > '9') {
00432       val = p[i] - 'a' + 10;
00433     }
00434     else
00435       val = p[i] - '0';
00436 
00437     ret = ret * 16 + val;
00438   }
00439   return ret;
00440 }
00441 
00442 
00443 int 
00444 debug_init(void)
00445 {
00446   int i;
00447   for (i=0; i < SAMPLE_SIZE; i++) {
00448     debug[i].caller = h2d(debugi[i].caller);
00449     debug[i].callee = h2d(debugi[i].callee);
00450     debug[i].caller_name_idx = debugi[i].caller_idx;
00451     debug[i].callee_name_idx = debugi[i].callee_idx;
00452   }
00453   return SAMPLE_SIZE;
00454 }
00455 
00456 
00457 void
00458 main (int argc, char *argv[])
00459 {
00460     register char *progname = "ir_prof";
00461     int binarg = 1;
00462     int verbose = FALSE;
00463     int j, i;
00464 
00465     progname = (argv[0]);
00466 
00467     if (argc == 2) {
00468       if (strcmp(argv[1], "-h") == 0)
00469         usage(progname);
00470       exit(0);
00471     }
00472     j = debug_init();
00473     for (i = 0; i < j; i++) {
00474       __profile_call(debug[i].caller, debug[i].callee, str[debug[i].caller_name_idx],
00475                      str[debug[i].callee_name_idx]);
00476     }
00477     ir_prof_dump();
00478     cgt_fini();
00479 
00480     exit (0);
00481 } /* main */
00482 #endif
00483 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines