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 <sys/stat.h> 00039 #include <elf.h> 00040 00041 #include "defs.h" 00042 #include "x_libgen.h" /* for basename() */ 00043 #include "mempool.h" 00044 #include "wn.h" /* for ir_reader.h */ 00045 #include "wn_simp.h" 00046 #include "stab.h" 00047 #include "const.h" 00048 #include "pu_info.h" 00049 #include "irbdata.h" 00050 #include "ir_reader.h" /* for IR_reader_init(), etc. */ 00051 #include "ir_bwrite.h" /* for WN_open_output(), etc. */ 00052 #include "ir_bread.h" /* for WN_open_input(), etc. */ 00053 #include "dwarf_DST_dump.h" 00054 #include "erglob.h" 00055 #include "errors.h" 00056 #include "err_host.tab" 00057 #include "config.h" 00058 #include "config_opt.h" 00059 #include "tracing.h" 00060 #include "profile_com.h" 00061 #include "fb_info.h" 00062 00063 static BOOL simplify_tree = FALSE; /* Should we run the simplifier (for testing purposes) */ 00064 00065 extern BOOL 00066 file_exists (char *path) 00067 { 00068 INT st; 00069 struct stat sbuf; 00070 st = stat(path, &sbuf); 00071 if (st == -1 && (errno == ENOENT || errno == ENOTDIR)) 00072 return FALSE; 00073 else 00074 return TRUE; 00075 } 00076 00077 00078 template <class T> 00079 void 00080 FB_Print (const T* info, INT size, const char* name) 00081 { 00082 if (size != 0) 00083 printf ("%s Profile:\n", name); 00084 for (INT i = 0; i < size; ++i) { 00085 printf("\t%s id = %ld\t", name, i); 00086 info[i].Print (stdout); 00087 fputc ('\n', stdout); 00088 } 00089 } 00090 00091 static void 00092 Print_Feedback_Info (const Pu_Hdr* pu_hdr) 00093 { 00094 const char* base = (const char*) pu_hdr; 00095 00096 const FB_Info_Invoke* fb_invoke = 00097 (const FB_Info_Invoke*) (base + pu_hdr->pu_inv_offset); 00098 FB_Print (fb_invoke, pu_hdr->pu_num_inv_entries, "Invoke"); 00099 00100 const FB_Info_Branch* fb_branch = 00101 (const FB_Info_Branch*) (base + pu_hdr->pu_br_offset); 00102 FB_Print (fb_branch, pu_hdr->pu_num_br_entries, "Branch"); 00103 00104 const FB_FREQ* fb_switch = 00105 (const FB_FREQ*) (base + pu_hdr->pu_switch_offset); 00106 const INT32* fb_switch_target = 00107 (const INT32*) (base + pu_hdr->pu_switch_target_offset); 00108 if (pu_hdr->pu_num_switch_entries != 0) 00109 printf ("Switch Profile:\n"); 00110 for (INT32 i = 0; i < pu_hdr->pu_num_switch_entries; ++i) { 00111 FB_Info_Switch info; 00112 info.freq_targets.insert (info.freq_targets.begin (), 00113 fb_switch, fb_switch + *fb_switch_target); 00114 info.Print (stdout); 00115 fb_switch += *fb_switch_target; 00116 ++fb_switch_target; 00117 } 00118 00119 const FB_Info_Loop* fb_loop = 00120 (const FB_Info_Loop*) (base + pu_hdr->pu_loop_offset); 00121 FB_Print (fb_loop, pu_hdr->pu_num_loop_entries, "Loop"); 00122 00123 const FB_Info_Circuit* fb_circuit = 00124 (const FB_Info_Circuit*) (base + pu_hdr->pu_scircuit_offset); 00125 FB_Print (fb_circuit, pu_hdr->pu_num_scircuit_entries, "Short Circuit"); 00126 00127 const FB_Info_Call* fb_call = 00128 (const FB_Info_Call*) (base + pu_hdr->pu_call_offset); 00129 FB_Print (fb_call, pu_hdr->pu_num_call_entries, "Call"); 00130 } 00131 00132 00133 /* Binary to ASCII conversion */ 00134 static void 00135 ir_b2a_process_PUs (PU_Info *pu_tree, BOOL stflag, BOOL fbflag) 00136 { 00137 PU_Info *pu; 00138 WN *wn; 00139 00140 for (pu = pu_tree; pu != NULL; pu = PU_Info_next (pu)) { 00141 if (!stflag) { 00142 MEM_POOL_Push(MEM_pu_nz_pool_ptr); 00143 MEM_POOL_Push(MEM_pu_pool_ptr); 00144 } 00145 Read_Local_Info (MEM_pu_nz_pool_ptr, pu); 00146 00147 wn = PU_Info_tree_ptr(pu); 00148 if (simplify_tree) wn = WN_Simplify_Tree(wn); 00149 00150 IR_put_func (wn, NULL); 00151 00152 if (PU_Info_child(pu)) { 00153 ir_b2a_process_PUs(PU_Info_child(pu), stflag, fbflag); 00154 } 00155 00156 if (stflag) { 00157 SYMTAB_IDX level = 00158 PU_lexical_level (&St_Table[PU_Info_proc_sym (pu)]); 00159 Print_local_symtab (stdout, Scope_tab[level]); 00160 } 00161 00162 if (fbflag) { 00163 if (PU_Info_feedback_ptr (pu)) { 00164 const Pu_Hdr* pu_hdr = (const Pu_Hdr*) 00165 PU_Info_feedback_ptr (pu); 00166 printf ("\n********* Feedback Info *********\n"); 00167 Print_Feedback_Info (pu_hdr); 00168 printf ("=======================================================================\n"); 00169 } 00170 } 00171 00172 if (!stflag) { 00173 Free_Local_Info (pu); 00174 MEM_POOL_Pop(MEM_pu_nz_pool_ptr); 00175 MEM_POOL_Pop(MEM_pu_pool_ptr); 00176 } 00177 } 00178 } 00179 00180 00181 static void 00182 ir_b2a (char *global_file, char *input_file, char *output_file, BOOL stflag, 00183 BOOL fbflag) 00184 { 00185 PU_Info *pu_tree; 00186 00187 if (global_file == NULL) { 00188 (void)Open_Input_Info (input_file); 00189 } else { 00190 (void)Open_Global_Input (global_file); 00191 (void)Open_Local_Input (input_file); 00192 } 00193 00194 Initialize_Symbol_Tables (FALSE); 00195 New_Scope (GLOBAL_SYMTAB, Malloc_Mem_Pool, FALSE); 00196 pu_tree = Read_Global_Info (NULL); 00197 00198 if (output_file != NULL) { 00199 if (freopen (output_file, "w+", stdout) == NULL) { 00200 fprintf (stderr, "Can't open output file %s\n", output_file); 00201 exit (1); 00202 } 00203 } 00204 00205 IR_reader_init(); 00206 IR_Dwarf_Gen_File_Table(TRUE); 00207 00208 ir_b2a_process_PUs(pu_tree, stflag, fbflag); 00209 00210 if (stflag) { 00211 /* print the symbol tables */ 00212 Print_global_symtab (stdout); 00213 Dump_DST (stdout); 00214 } 00215 00216 Free_Input_Info (); 00217 00218 } // ir_b2a 00219 00220 00221 /* Binary to ASCII conversion */ 00222 static void 00223 ir_sel (char *input_file, char *output_file, char *func_name) 00224 { 00225 WN *wn; 00226 PU_Info *pu_tree, *pu = NULL; 00227 BOOL found = FALSE; 00228 00229 (void)Open_Input_Info (input_file); 00230 pu_tree = Read_Global_Info (NULL); 00231 00232 Open_Output_Info (output_file); 00233 00234 /* don't bother searching through nested procedures since they can't 00235 be written out by themselves anyway */ 00236 00237 for (pu = pu_tree; pu != NULL; pu = PU_Info_next (pu)) { 00238 MEM_POOL_Push(MEM_pu_nz_pool_ptr); 00239 MEM_POOL_Push(MEM_pu_pool_ptr); 00240 Read_Local_Info (MEM_pu_nz_pool_ptr, pu); 00241 00242 wn = PU_Info_tree_ptr(pu); 00243 if ((WN_opcode(wn) == OPC_FUNC_ENTRY) && 00244 (strcmp(func_name, ST_name(WN_st(wn))) == 0)) { 00245 00246 Write_PU_Info (pu); 00247 found = TRUE; 00248 00249 Free_Local_Info (pu); 00250 MEM_POOL_Pop(MEM_pu_nz_pool_ptr); 00251 MEM_POOL_Pop(MEM_pu_pool_ptr); 00252 00253 /* remove all the other PUs from the list */ 00254 PU_Info_next(pu) = NULL; 00255 PU_Info_child(pu) = NULL; 00256 pu_tree = pu; 00257 00258 break; 00259 } 00260 00261 Free_Local_Info (pu); 00262 MEM_POOL_Pop(MEM_pu_nz_pool_ptr); 00263 MEM_POOL_Pop(MEM_pu_pool_ptr); 00264 } 00265 00266 if (!found) { 00267 fprintf (stderr, "Can't find function %s\n", func_name); 00268 exit (1); 00269 } 00270 00271 Write_Global_Info(pu_tree); 00272 Close_Output_Info (); 00273 Free_Input_Info (); 00274 00275 } /* ir_sel */ 00276 00277 00278 static void 00279 usage (char *progname) 00280 { 00281 INT a2b, b2a, sel; 00282 00283 a2b = (strcmp (progname, "ir_a2b") == 0); 00284 b2a = (strcmp (progname, "ir_b2a") == 0); 00285 sel = (strcmp (progname, "ir_sel") == 0); 00286 00287 if (a2b) { 00288 fprintf (stderr, "New symbol table format not supported by ir_a2b (yet)\n"); 00289 } else if (b2a) { 00290 fprintf (stderr, "Usage: %s [-st] [-v] <Binary IR> [<ASCII IR>]\n", 00291 progname); 00292 fprintf (stderr, "\t(will write to stdout if ascii file not given)\n"); 00293 fprintf (stderr, "\t-st option will also print out the symbol table\n"); 00294 fprintf (stderr, "\t-opcodes option will print out opcodes as seen\n"); 00295 fprintf (stderr, "\t-lines option will print out line numbers\n"); 00296 fprintf (stderr, "\t-global_local <.G file> option will use separate global table\n"); 00297 fprintf (stderr, "\t-sym <.G file> is the same as -global_local\n"); 00298 } else if (sel) { 00299 fprintf (stderr, "Usage: %s <function> <Binary IR input> [<Binary IR output>]\n", progname); 00300 00301 } 00302 exit (1); 00303 } 00304 00305 main (INT argc, char *argv[]) 00306 { 00307 register char *progname; 00308 register INT a2b, b2a, sel; 00309 char *infile; 00310 char *outfile; 00311 INT binarg = 1; 00312 BOOL stflag = FALSE; 00313 BOOL fbflag = FALSE; 00314 00315 00316 MEM_Initialize(); 00317 Set_Error_Tables (Phases, host_errlist); 00318 Init_Error_Handler (10); 00319 Set_Error_File(NULL); 00320 Set_Error_Line(ERROR_LINE_UNKNOWN); 00321 WHIRL_Mldid_Mstid_On = TRUE; 00322 00323 progname = ux_basename (argv[0]); 00324 // weird linux bug with basename where it doesn't strip the leading / 00325 if (*progname == '/') ++progname; 00326 a2b = (strcmp (progname, "ir_a2b") == 0); 00327 b2a = (strcmp (progname, "ir_b2a") == 0); 00328 sel = (strcmp (progname, "ir_sel") == 0); 00329 00330 if (a2b) { 00331 usage (progname); 00332 } 00333 else if (b2a) { 00334 Read_Global_Data = NULL; 00335 if (argc < 2) 00336 usage(progname); 00337 00338 while (*argv[binarg] == '-') { 00339 if (strncmp(argv[binarg], "-st", 3) == 0) { 00340 stflag = TRUE; 00341 } else if (strcmp(argv[binarg], "-fb") == 0) { 00342 fbflag = TRUE; 00343 } else if (strcmp(argv[binarg], "-v") == 0) { 00344 IR_dump_map_info = TRUE; 00345 } else if (strcmp(argv[binarg], "-opcodes") == 0) { 00346 /* this option is for tracing errors when reading the whirl. 00347 * should probably rename Set_Verbose_Info to something 00348 * more descriptive. */ 00349 Set_Verbose_Info(TRUE); /* print opcodes as seen */ 00350 IR_dump_map_info = TRUE; 00351 } else if (strcmp(argv[binarg], "-ws") == 0) { 00352 simplify_tree = TRUE; 00353 (void) WN_Simplifier_Enable(TRUE); 00354 } else if (strcmp(argv[binarg], "-wsa") == 0) { 00355 simplify_tree = TRUE; 00356 (void) WN_Simplifier_Enable(TRUE); 00357 00358 Roundoff_Level=ROUNDOFF_ANY; 00359 Enable_Cfold_Reassociate=TRUE; /* Re-association allowed? */ 00360 Rsqrt_Allowed=TRUE; /* Generate RSQRT instruction? */ 00361 Recip_Allowed=TRUE; /* Generate RECIP instruction? */ 00362 Div_Split_Allowed=TRUE; /* Change a/b --> a*1/b ? */ 00363 Enable_Cfold_Aggressive=TRUE; /* Complex constant folding? */ 00364 IEEE_Arithmetic = IEEE_ANY; 00365 Simp_Multiply_To_Shift = TRUE; 00366 } else if (strcmp(argv[binarg], "-wst") == 0) { 00367 Set_Trace(TP_WHIRLSIMP,1); 00368 Set_Trace(TP_WHIRLSIMP,2); 00369 } else if (strcmp(argv[binarg], "-pre") == 0) { 00370 (void) IR_set_dump_order(TRUE); 00371 } else if (strcmp(argv[binarg], "-lines") == 0) { 00372 IR_dump_line_numbers = TRUE; 00373 } else if (strcmp(argv[binarg], "-global_local") == 0 || 00374 strcmp(argv[binarg], "-sym") == 0) { 00375 ++binarg; 00376 Read_Global_Data = argv[binarg]; 00377 } else { 00378 usage(progname); 00379 } 00380 ++binarg; 00381 } 00382 00383 if (argc < binarg+1) 00384 usage(progname); 00385 if (!file_exists(argv[binarg])) 00386 usage(progname); 00387 00388 infile = argv[binarg]; 00389 outfile = argv[binarg+1]; 00390 ir_b2a (Read_Global_Data, infile, outfile, stflag, fbflag); 00391 } 00392 else if (sel) { 00393 if (argc < 3) 00394 usage(progname); 00395 if (!file_exists(argv[2])) 00396 usage(progname); 00397 00398 if (argc == 3) { 00399 outfile = (char *) malloc(strlen(argv[1])+3); 00400 strcpy(outfile, argv[1]); 00401 strcat(outfile, ".B"); 00402 } else { 00403 outfile = argv[3]; 00404 } 00405 ir_sel (argv[2], outfile, argv[1]); 00406 } 00407 else { 00408 fprintf(stderr, "unrecognized command %s\n", progname); 00409 } 00410 00411 exit (0); 00412 } /* main */ 00413 00414 00415 /* Dummy definitions to satisify references from routines that got pulled 00416 * in by the header files but are never called 00417 */ 00418 void 00419 Signal_Cleanup (INT sig) { } 00420 00421 char * 00422 Host_Format_Parm (INT kind, MEM_PTR parm) 00423 { 00424 fprintf (stderr, "Internal: Host_Format_Parm () not implemented\n"); 00425 return ""; 00426 } 00427 00428 INT8 Debug_Level = 0;