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 /* ==================================================================== 00037 * ==================================================================== 00038 * 00039 * 00040 * Revision history: 00041 * 22-Apr-97 - Original Version 00042 * 00043 * Description: 00044 * 00045 * This program, as it stands, doesn't do anything. It is skeleton 00046 * code which opens an existing WHIRL file and walks through all PU's, 00047 * symbols, constants, WHIRL trees, etc. There are two uses for this 00048 * code: a program which analyzes the *.B file and reports things about 00049 * it; and a program which modifies part of the information and re-writes 00050 * the WHIRL file. 00051 * 00052 * ir_walker [-v] [-o <Whirl_File_Name_out>] <Whirl_File_Name> 00053 * 00054 * Note that the <Whirl_File_Name> is a mandatory argument, and in 00055 * its absence a message about usage will be emitted. If the program 00056 * is written to output a modified WHIRL file then it will either be 00057 * written to the optional -o argument or to the original WHIRL file. 00058 * The -v option turns on pu, symbol and WHIRL node tracing. 00059 * 00060 * ==================================================================== 00061 * ==================================================================== 00062 */ 00063 00064 #include <elf.h> 00065 #include <stdio.h> 00066 #include <sys/types.h> 00067 #include <sys/stat.h> 00068 #include <search.h> 00069 #include <string.h> 00070 #include <stdlib.h> 00071 #include <unistd.h> 00072 00073 #include "wn.h" 00074 #include "stab.h" 00075 #include "aux_stab.h" 00076 #include "irbdata.h" 00077 #include "wintrinsic.h" 00078 #include "glob.h" 00079 #include "pu_info.h" 00080 #include "ir_bread.h" 00081 #include "ir_bwrite.h" 00082 #include "file_util.h" 00083 00084 00085 /* ==================================================================== 00086 * 00087 * Local data. 00088 * 00089 * ==================================================================== 00090 */ 00091 00092 #define MAX_FNAME_LENGTH 256 00093 00094 char filename_in[MAX_FNAME_LENGTH]; 00095 char filename_out[MAX_FNAME_LENGTH]; 00096 char temp_filename[MAX_FNAME_LENGTH+16]; 00097 00098 char *Irb_File_Name_out = NULL; 00099 00100 struct stat statbuf; 00101 00102 BOOL oflag = FALSE; 00103 BOOL vflag = FALSE; 00104 00105 INT32 indent = 0; 00106 INT32 indent_inc = 2; 00107 00108 00109 /* ==================================================================== 00110 * 00111 * Adaptation section. 00112 * 00113 * These routines are meant to be adapted by the user to do whatever 00114 * you'd like. Each routine is called by the walkers for each PU, 00115 * SYMTAB, symbol and WHIRL node as appropriate. 00116 * 00117 * The *_WALK defines control whether or not the corresponding walks 00118 * take place (to improve performance). 00119 * 00120 * The action of the walker is also controlled by the WRITE_IRB symbol. 00121 * If it is undefined then it is assumed that the IRB file is only 00122 * read and processed. If it is defined then it is assumed that 00123 * changes are being made by the walker and that the IRB file must 00124 * be re-written. 00125 * 00126 * ==================================================================== 00127 */ 00128 00129 00130 #undef ST_WALK 00131 #undef TY_WALK 00132 #undef WN_WALK 00133 00134 #undef WRITE_IRB 00135 00136 00137 /* Called at the beginning of processing. */ 00138 void 00139 Initialization (void) 00140 { 00141 } 00142 00143 00144 /* Called for each PU found. */ 00145 void 00146 Process_PU (PU_Info *pu) 00147 { 00148 } 00149 00150 00151 /* Called for each STAB found. */ 00152 void 00153 Process_STAB (SYMTAB *stab) 00154 { 00155 } 00156 00157 00158 /* Called for each ST found. */ 00159 void 00160 Process_ST (ST *st) 00161 { 00162 } 00163 00164 00165 /* Called for each TY found. */ 00166 void 00167 Process_TY (TY *st) 00168 { 00169 } 00170 00171 00172 /* Called for each WHIRL NODE found. */ 00173 void 00174 Process_WN (WN *wn) 00175 { 00176 } 00177 00178 00179 /* Called at the end of processing. */ 00180 void 00181 Termination (void) 00182 { 00183 } 00184 00185 00186 /* ==================================================================== 00187 * 00188 * Usage 00189 * 00190 * Give a warning about the usage of this tool, in terms of the 00191 * command line options it accepts. 00192 * 00193 * ==================================================================== 00194 */ 00195 00196 static void 00197 Usage (void) 00198 { 00199 fprintf (stderr, 00200 "USAGE:\n" 00201 "\n" 00202 "\t [-v] [-o <Whirl_File_Name_out>] <Whirl_File_Name>\n" 00203 "\n" 00204 "The <Whirl_File_Name> is a mandatory command line argument.\n" 00205 "The optional -v flag controls verbose trace messages.\n" 00206 "The optional -o flag is used to specify an alternate out file.\n" 00207 "\n" 00208 ); 00209 00210 } /* Usage */ 00211 00212 00213 /* ==================================================================== 00214 * 00215 * Get_Irb_File_Name 00216 * 00217 * Process the command line arguments to get the input file name, 00218 * the optional output file name and any other options. Return the 00219 * number of input filename arguments found on this command line 00220 * (where Irb_File_Name will be set to the first one encountered). 00221 * 00222 * ==================================================================== 00223 */ 00224 00225 static INT32 00226 Get_Irb_File_Name (INT argc, char *argv[]) 00227 { 00228 /* Find the WHIRL input filename. There should only be one. */ 00229 char *fname; 00230 INT32 argidx; 00231 INT32 src_count = 0; 00232 00233 for (argidx = 1; argidx < argc; argidx++) 00234 { 00235 /* Null argument => end of list: */ 00236 if (argv[argidx][0] == '-' ) 00237 { 00238 /* Process regular options */ 00239 if (strcmp (argv[argidx], "-o") == 0) { 00240 #ifdef WRITE_IRB 00241 oflag = TRUE; 00242 fname = argv[++argidx]; 00243 if (strlen(fname) > MAX_FNAME_LENGTH) 00244 { 00245 Irb_File_Name_out = strncpy (filename_out, fname, MAX_FNAME_LENGTH); 00246 filename_out[MAX_FNAME_LENGTH] = '\0'; 00247 fprintf (stderr, 00248 "WARNING: output filename truncated to " 00249 "(max=%d chars): \"%s\"\n", 00250 MAX_FNAME_LENGTH, fname); 00251 } 00252 else 00253 Irb_File_Name_out = strcpy (filename_out, fname); 00254 #else 00255 fprintf (stderr, 00256 "WARNING: cannot specify output file"); 00257 ++argidx; 00258 #endif 00259 } else if (strcmp (argv[argidx], "-v") == 0) { 00260 vflag = TRUE; 00261 } else { 00262 fprintf (stderr, 00263 "WARNING: unrecognized command option " 00264 "%s\n", 00265 argv[argidx]); 00266 } 00267 } 00268 else if (src_count > 0) 00269 src_count += 1; 00270 else if (src_count == 0) /* Presumably a WHIRL input file name */ 00271 { 00272 /* Copy the original filename to a static buffer */ 00273 fname = argv[argidx]; 00274 if (strlen(fname) > MAX_FNAME_LENGTH) 00275 { 00276 Irb_File_Name = strncpy (filename_in, fname, MAX_FNAME_LENGTH); 00277 filename_in[MAX_FNAME_LENGTH] = '\0'; 00278 fprintf (stderr, 00279 "WARNING: input filename truncated to " 00280 "(max=%d chars): \"%s\"\n", 00281 MAX_FNAME_LENGTH, fname); 00282 } 00283 else 00284 Irb_File_Name = strcpy (filename_in, fname); 00285 00286 src_count = 1; 00287 } /* If source file argument */ 00288 } /* While not found */ 00289 return src_count; 00290 } /* Get_Irb_File_Name */ 00291 00292 00293 /* ==================================================================== 00294 * 00295 * process_stab 00296 * 00297 * Process each STAB. 00298 * 00299 * ==================================================================== 00300 */ 00301 00302 static void 00303 process_stab (SYMTAB *stab) 00304 { 00305 00306 ST *st; 00307 TY *ty; 00308 00309 if (vflag) 00310 printf ("%*sProcessing STAB: %d\n", indent, "", SYMTAB_id(stab)); 00311 Process_STAB (stab); 00312 00313 #ifdef ST_WALK 00314 00315 indent += indent_inc; 00316 00317 for (st = SYMTAB_symbols(stab); st != NULL; st = ST_next(st)) { 00318 if (vflag) 00319 printf ("%*sProcessing ST: %s\n", indent, "", ST_name(st)); 00320 Process_ST (st); 00321 } 00322 00323 indent -= indent_inc; 00324 00325 #endif 00326 00327 #ifdef TY_WALK 00328 00329 indent += indent_inc; 00330 00331 for (ty = SYMTAB_types(stab); ty != NULL; ty = TY_next(ty)) { 00332 if (vflag) 00333 printf ("%*sProcessing TY: %s\n", indent, "", TY_name(ty)); 00334 Process_TY (ty); 00335 } 00336 00337 indent -= indent_inc; 00338 00339 #endif 00340 00341 } 00342 00343 00344 /* ==================================================================== 00345 * 00346 * process_wn 00347 * 00348 * Process each WN. 00349 * 00350 * ==================================================================== 00351 */ 00352 00353 static void 00354 process_wn (WN *wn) 00355 { 00356 00357 INT32 i; 00358 WN *node; 00359 OPCODE op; 00360 00361 if (wn) { 00362 00363 op = WN_opcode(wn); 00364 00365 if (vflag) 00366 printf ("%*sProcessing WN: %s\n", indent, "", OPCODE_name(op)); 00367 Process_WN (wn); 00368 00369 indent += indent_inc; 00370 00371 if (op == OPC_BLOCK) 00372 for (node = WN_first(wn); node; node = WN_next(node)) 00373 process_wn (node); 00374 else 00375 for (i = 0; i < WN_kid_count(wn); i++) 00376 process_wn (WN_kid(wn,i)); 00377 00378 indent -= indent_inc; 00379 00380 } 00381 00382 } 00383 00384 00385 /* ==================================================================== 00386 * 00387 * process_func 00388 * 00389 * Process each function. 00390 * 00391 * ==================================================================== 00392 */ 00393 00394 static void 00395 process_func (WN *wn) 00396 { 00397 00398 if (vflag) 00399 printf ("%*sProcessing FUNC: %s\n", indent, "", ST_name(WN_st(wn))); 00400 00401 #ifdef WN_WALK 00402 00403 indent += indent_inc; 00404 00405 process_wn (wn); 00406 00407 indent -= indent_inc; 00408 00409 #endif 00410 00411 } 00412 00413 00414 /* ==================================================================== 00415 * 00416 * process_pu 00417 * 00418 * Process each PU. 00419 * 00420 * ==================================================================== 00421 */ 00422 00423 static void 00424 process_pu (PU_Info *pu_tree) 00425 { 00426 PU_Info *pu; 00427 00428 for (pu = pu_tree; pu != NULL; pu = PU_Info_next(pu)) { 00429 Current_PU_Info = pu; 00430 MEM_POOL_Push (MEM_pu_nz_pool_ptr); 00431 Read_Local_Info (MEM_pu_nz_pool_ptr, pu); 00432 00433 if (vflag) 00434 printf ("%*sProcessing PU: %s\n", indent, "", 00435 ST_name(PU_Info_proc_sym(pu))); 00436 indent += indent_inc; 00437 Process_PU (pu); 00438 00439 process_stab (PU_Info_symtab_ptr(pu)); 00440 00441 process_func (PU_Info_tree_ptr(pu)); 00442 00443 if (PU_Info_child(pu)) { 00444 process_pu (PU_Info_child(pu)); 00445 } 00446 00447 #ifdef WRITE_IRB 00448 Write_PU_Info (pu); 00449 #endif 00450 00451 indent -= indent_inc; 00452 Free_Local_Info (pu); 00453 MEM_POOL_Pop (MEM_pu_nz_pool_ptr); 00454 00455 } 00456 } 00457 00458 00459 /* ==================================================================== 00460 * 00461 * main 00462 * 00463 * Main entry point and driver for the ir_walker program. 00464 * 00465 * ==================================================================== 00466 */ 00467 00468 void 00469 main (INT argc, /* Number of command line arguments */ 00470 char *argv[], /* Array of command line arguments */ 00471 char *envp[]) /* Array of environment pointers */ 00472 { 00473 WN *pu; 00474 INT32 inp_file_count; 00475 PU_Info *pu_tree, *current_pu; 00476 00477 /* Here are things that every process driver should do as soon as 00478 * possible upon start-up. 00479 */ 00480 MEM_Initialize (); 00481 Init_Error_Handler (10); 00482 Set_Error_Line (ERROR_LINE_UNKNOWN); 00483 Set_Error_Phase ("IR Walker"); 00484 Set_Error_File (NULL); 00485 00486 Init_Operator_To_Opcode_Table (); 00487 00488 /* Process the input file */ 00489 inp_file_count = Get_Irb_File_Name (argc, argv); 00490 if (inp_file_count == 0) 00491 { 00492 Usage (); 00493 fprintf (stderr, "ERROR: missing input file on command line\n"); 00494 } 00495 else if (inp_file_count > 1) 00496 { 00497 Usage (); 00498 fprintf (stderr, "ERROR: too many input files on command line\n"); 00499 } 00500 else if (stat (Irb_File_Name, &statbuf) != 0) 00501 { 00502 fprintf (stderr, "ERROR: input file (%s) does not exist\n", 00503 Irb_File_Name); 00504 } 00505 else 00506 { 00507 00508 #ifdef WRITE_IRB 00509 /* Setup output file */ 00510 if (!oflag) 00511 (void) strcpy (filename_out, filename_in); 00512 (void) sprintf (temp_filename, "%s$%d", filename_out, (INT32) getpid ()); 00513 (void) remove (temp_filename); 00514 #endif 00515 00516 /* User defined initialization code */ 00517 Initialization (); 00518 00519 /* Get the global symbol table, the string table, the constant table, 00520 * and the initialization table. 00521 */ 00522 (void) Open_Input_Info (Irb_File_Name); 00523 pu_tree = Read_Global_Info (NULL); 00524 00525 #ifdef WRITE_IRB 00526 (void) Open_Output_Info (temp_filename); 00527 #endif 00528 00529 /* Process global symbol table. */ 00530 process_stab (Global_Symtab); 00531 00532 /* Loop thru all the PUs */ 00533 process_pu (pu_tree); 00534 00535 /* User defined termination code */ 00536 Termination (); 00537 00538 #ifdef WRITE_IRB 00539 /* Finish up output file */ 00540 Write_Global_Info (pu_tree); 00541 Close_Output_Info (); 00542 (void) remove (filename_out); 00543 (void) rename (temp_filename, filename_out); 00544 #endif 00545 00546 } 00547 00548 exit (0); 00549 } /* main */ 00550 00551 00552 /* Dummy definitions to satisify references from routines that got pulled 00553 * in by the header files but are never called 00554 */ 00555 void Signal_Cleanup (INT sig) { } 00556 00557 char * Host_Format_Parm (INT kind, MEM_PTR parm) { return NULL; } 00558 00559 INT8 Debug_Level = 0;