Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
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