Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
ir_walker.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 /* ====================================================================
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;
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines