Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
ir_reader.cxx
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 //-*-c++-*-
00037 /* ====================================================================
00038  * ====================================================================
00039  *
00040  *
00041  * Revision history:
00042  *  1-SEP-94 - Original Version
00043  *
00044  * Description:
00045  *
00046  * ====================================================================
00047  * ====================================================================
00048  */
00049 
00050 /*************************************************************************
00051    IR Ascii/Binary Reader/Write
00052 
00053    Interface routines:
00054       IR_init
00055       IR_open
00056       IR_close
00057       IR_finish
00058       IR_get_func
00059       IR_output
00060 
00061  *************************************************************************/
00062 #ifdef USE_PCH
00063 #include "common_com_pch.h"
00064 #endif /* USE_PCH */
00065 #pragma hdrstop
00066 #include <stdio.h>
00067 #include <string.h>
00068 #include <sys/types.h>
00069 #include <sys/mman.h>
00070 #include <sys/stat.h>
00071 #include <fcntl.h>
00072 #include <stdarg.h>
00073 #include <ctype.h>
00074 #include <unistd.h>
00075 #include <cmplrs/rcodes.h>
00076 
00077 // Solaric CC workaround
00078 #ifndef USE_STANDARD_TYPES
00079 #define USE_STANDARD_TYPES // to allow wn_tree_op.h to include ... vector.h
00080 #endif                     // which uses standard types.
00081 
00082 #include "wn_tree_util.h"
00083 #include "defs.h"
00084 #include "errors.h"
00085 #include "srcpos.h"
00086 #include "opcode.h"
00087 #include "stab.h"
00088 #include "const.h"
00089 #include "targ_const.h"
00090 extern char * Targ_Print ( const char *fmt, TCON c );
00091 #include "targ_sim.h"
00092 #include "strtab.h"
00093 #include "irbdata.h"
00094 #include "wn.h"         /* Whirl Node descriptor */
00095 #include "wn_simp.h"    /* Whirl simplifier (can be stubs) */
00096 #include "dwarf_DST.h"
00097 #include "dwarf_DST_mem.h"
00098 #include "ir_reader.h"
00099 #include "tracing.h"
00100 
00101 #ifdef BACK_END
00102 #include "opt_alias_mgr.h"
00103 #endif /* BACK_END */
00104 
00105 #include "wio.h"
00106 #include "wintrinsic.h"
00107 #include "wn_pragmas.h"
00108 #include "wutil.h"
00109 #ifdef BACK_END
00110 #include "region_util.h"
00111 #include "dvector.h"
00112 #endif /* BACK_END */
00113 
00114 /* Extended Ascii-WHIRL */
00115 
00116 enum OPR_EXTENDED {
00117     OPR_END_BLOCK       = OPERATOR_LAST+1,
00118     OPR_BODY            = OPERATOR_LAST+2,
00119     OPR_NOOP            = OPERATOR_LAST+3,
00120     OPR_THEN            = OPERATOR_LAST+4,
00121     OPR_ELSE            = OPERATOR_LAST+5,
00122     OPR_END_IF          = OPERATOR_LAST+6,
00123     OPR_INIT            = OPERATOR_LAST+7,
00124     OPR_COMP            = OPERATOR_LAST+8,
00125     OPR_INCR            = OPERATOR_LAST+9,
00126     OPR_END_COMPGOTO    = OPERATOR_LAST+10,
00127     OPR_END_XGOTO       = OPERATOR_LAST+11,
00128     OPR_LOC             = OPERATOR_LAST+12,
00129     OPR_END_LINFO       = OPERATOR_LAST+13,
00130     OPR_END_SWITCH      = OPERATOR_LAST+14
00131 };
00132 
00133 enum OPC_EXTENDED {
00134     OPC_END_BLOCK       = OPCODE_LAST+1,
00135     OPC_BODY            = OPCODE_LAST+2,
00136     OPC_NOOP            = OPCODE_LAST+3,
00137     OPC_THEN            = OPCODE_LAST+4,
00138     OPC_ELSE            = OPCODE_LAST+5,
00139     OPC_END_IF          = OPCODE_LAST+6,
00140     OPC_INIT            = OPCODE_LAST+7,
00141     OPC_COMP            = OPCODE_LAST+8,
00142     OPC_INCR            = OPCODE_LAST+9,
00143     OPC_END_COMPGOTO    = OPCODE_LAST+10,
00144     OPC_END_XGOTO       = OPCODE_LAST+11,
00145     OPC_LOC             = OPCODE_LAST+12,
00146     OPC_END_LINFO       = OPCODE_LAST+13,
00147     OPC_END_SWITCH      = OPCODE_LAST+14,
00148     MAX_OPCODE          = OPCODE_LAST+15
00149 };
00150 
00151 typedef struct {
00152   char *pr_name;
00153   INT  n_kids;
00154   INT  flags;
00155 } IR_OPCODE_TABLE;
00156 
00157 
00158 IR_OPCODE_TABLE ir_opcode_table[1];         /* index by opcode */
00159 
00160 
00161 #define HASH_LEN        2413           /* prime number */
00162 #define IR_MAX_ARGS     3              /* IR opcode has at most 3 arguments */
00163 
00164 IR_OPCODE_TABLE *opcode_hash[HASH_LEN]; 
00165 
00166 #define LINE_LEN  1024  /* maximum length of line */
00167 
00168 typedef struct {
00169   OPCODE opcode;
00170   INT _operator;
00171   INT n_kids;
00172   INT flags;
00173   ST *st;
00174   TY_IDX ty;
00175   TY_IDX load_addr_ty;
00176   INT id;
00177   INT num_dim;
00178   INT num_entries;
00179   INT last_label;
00180   WN_OFFSET offset;
00181   INT16 offset1_of_2;
00182   INT16 offset2_of_2;
00183   WN_ESIZE  esize;
00184   INT16 cvtl_bits;
00185   INT64 const_val;
00186   INT32 label_number;
00187   UINT32 flags_val;
00188   INT cgoto;
00189   INT intrinsic;
00190   char *intrinsic_name;
00191   char *args[IR_MAX_ARGS+1];
00192 } TOKEN;
00193 
00194 static void ir_error(char *s);
00195 static INT ir_get_expr_list(void);
00196 static WN * ir_get_expr(void);
00197 static WN * ir_get_stmt(void);
00198 static void ir_skip_token(void);
00199 static char *ir_read_line(char *buf, INT size, FILE *ir_file);
00200 static void ir_match_token(OPERATOR opr);
00201 static void ir_expect_token(OPERATOR opc);
00202 static TOKEN *ir_next_token(void);
00203 static void ir_get_token(TOKEN *token);
00204 static BOOL ir_insert_hash(char *s, IR_OPCODE_TABLE *irt);
00205 static INT ir_lookup(char *s);
00206 static void ir_build_hashtable(void);
00207 static void ir_put_wn(WN * wn, INT indent);
00208 static void ir_put_expr(WN * wn, INT indent);
00209 static void ir_put_marker(char *str, INT indent);
00210 static void ir_put_stmt(WN * wn, INT indent);
00211 static void WN_TREE_put_stmt(WN *, INT); // fwd declaration
00212 
00213 /* Should we dump the tree in prefix order or postfix order? */
00214 /* The default is postfix */
00215 
00216 static BOOL dump_parent_before_children = FALSE;
00217 
00218 BOOL IR_dump_map_info = FALSE;
00219 BOOL IR_dump_region = FALSE;
00220 BOOL IR_DUMPDEP_info = FALSE;
00221 BOOL IR_dump_line_numbers = FALSE;
00222 BOOL IR_dump_wn_addr = FALSE;
00223 
00224 WN_MAP IR_alias_map = WN_MAP_UNDEFINED;
00225 const struct ALIAS_MANAGER *IR_alias_mgr = NULL;
00226 WN_MAP IR_freq_map = WN_MAP_UNDEFINED;
00227 
00228 #define OPCODE_has_alias_info(opc)      (OPCODE_is_load(opc) ||\
00229                                          OPCODE_is_store(opc) ||\
00230                                          OPCODE_operator(opc) == OPR_PARM)
00231 
00232 #define IR_dump_alias_info(opc)         (IR_alias_map != WN_MAP_UNDEFINED && OPCODE_has_alias_info(opc))
00233 
00234 typedef struct DUMPDEP
00235 {
00236   WN                    *node;
00237   INT32                 id;
00238   struct DUMPDEP        *next;
00239 } DUMPDEP, *DUMPDEPp;
00240 
00241 #define DUMPDEP_node(x)         (x)->node
00242 #define DUMPDEP_id(x)           (x)->id
00243 #define DUMPDEP_next(x)         ((x)->next)
00244 
00245 
00246 DUMPDEPp IR_DUMPDEP_head= NULL;
00247 static INT32 AddToDUMPDEP(WN *node);
00248 
00249 
00250 /*
00251 **  Add node to list to be processed for a dep graph dump
00252 **  List is processed in order
00253 **  reset id if null. start at 1 (no good reason)
00254 */
00255 static INT32 AddToDUMPDEP(WN *node)
00256 {
00257   static DUMPDEPp       last;
00258   static INT32          id= 0;
00259 
00260   if (IR_DUMPDEP_head==NULL)
00261   {
00262     id=         1;
00263     last=       NULL;
00264   }
00265 
00266   {
00267     DUMPDEPp p;
00268 
00269     p = TYPE_L_ALLOC(DUMPDEP);
00270 
00271     DUMPDEP_node(p)=    node;
00272     DUMPDEP_id(p)=      id++;
00273     DUMPDEP_next(p)=    NULL;
00274 
00275     if (last)
00276     {
00277       DUMPDEP_next(last) = p;
00278       last=             p;
00279     }
00280     else
00281     {
00282       IR_DUMPDEP_head=  p;
00283       last=             p;
00284     }
00285     return DUMPDEP_id(p);
00286   }
00287 }
00288 
00289 
00290 /*========================================================================
00291    
00292     Initialization
00293 
00294  ========================================================================*/
00295 
00296 #ifndef MONGOOSE_BE
00297 static FILE *ir_file;
00298 #endif
00299 static FILE *ir_ofile;
00300 static INT  ir_line;
00301 #ifdef IR_TOOLS 
00302 static char *line;
00303 static char *errmsg;
00304 #endif
00305 static BOOL follow_st;
00306 static USRCPOS last_srcpos;
00307 static BOOL is_initialized = FALSE;
00308 static WN_MAP ir_put_map = WN_MAP_UNDEFINED;
00309 
00310 extern void IR_reader_init(void)
00311 {
00312   is_initialized = TRUE;
00313   MEM_POOL_Push(&MEM_local_pool);
00314 #ifdef IR_TOOLS
00315   errmsg = (char *) MEM_POOL_Alloc(&MEM_local_pool, LINE_LEN);
00316   line   = (char *) MEM_POOL_Alloc(&MEM_local_pool, LINE_LEN);
00317 //ir_build_hashtable();
00318 #endif
00319   ir_ofile = stdout;
00320   follow_st = TRUE;
00321   USRCPOS_clear(last_srcpos);
00322 }
00323 
00324 /* If prefix is true, set the dump order to prefix order instead of postfix order */
00325 /* return the old order. */
00326 /* This function will soon be removed. R. Shapiro */
00327 extern BOOL IR_set_dump_order(BOOL prefix)
00328 {
00329    BOOL old_order;
00330    old_order = dump_parent_before_children;
00331    dump_parent_before_children = prefix;
00332    return (old_order);
00333 }
00334 
00335 
00336 #ifndef MONGOOSE_BE
00337 extern void IR_reader_finish(void)
00338 {
00339   MEM_POOL_Pop(&MEM_local_pool);
00340 }
00341 
00342 
00343 extern FILE *IR_open(const char *filename)
00344 {
00345    char prefix_check[6];
00346    ir_file = fopen(filename, "r");
00347    ir_line = 0;
00348    
00349    /* Check for prefix ordered file */
00350    (void) fread(prefix_check,6,1,ir_file);
00351    if (strncmp(prefix_check,"PREFIX",6)==0) {
00352       fclose(ir_file);
00353       fprintf(stderr,"File %s is prefix ordered and cannot be read.\n",filename);
00354    } else {
00355       /* seek back to the start of the file */
00356       rewind(ir_file);
00357    }
00358    return ir_file;
00359 }
00360 
00361 extern void IR_close(void)
00362 {
00363   fclose(ir_file);
00364 }
00365 
00366 
00367 /*
00368  *  Write the IR into a file in ascii form.
00369  */
00370 extern BOOL IR_open_output(const char *filename)
00371 {
00372   if (filename == NULL)
00373     ir_ofile = stdout;
00374   else
00375     if ((ir_ofile = fopen(filename, "w+")) == NULL) {
00376       ir_error("cannot open file for write");
00377       return FALSE;
00378     }
00379   return TRUE;
00380 }
00381 
00382 
00383 extern void IR_close_output(void)
00384 {
00385   if (ir_ofile != NULL && ir_ofile != stdout)
00386     fclose(ir_ofile);
00387 }
00388 #endif /* MONGOOSE_BE */
00389 
00390 
00391 /*========================================================================
00392 
00393    IR Error Handling
00394  
00395  ========================================================================*/
00396 
00397 #define ir_chk_kids(m,n)   {if (m != n) ir_error("wrong number of kids"); }
00398 
00399 static void ir_error(char *s)
00400 {
00401   fprintf(stderr, "Error parsing ascii IR at line %d: %s.\n", ir_line, s);
00402   exit(RC_INTERNAL_ERROR);
00403 }
00404 
00405 
00406 /*========================================================================
00407 
00408    Get source file path name from DST (taken from cgdwarf.c)
00409  
00410  ========================================================================*/
00411 
00412 typedef struct {
00413   char *filename;
00414   INT incl_index;
00415   FILE *fileptr;
00416   INT max_line_printed;
00417 } file_info;
00418 
00419 static file_info *file_table = NULL;
00420 static char **incl_table;
00421 static INT cur_file_index = 0;
00422 static BOOL file_table_generated = FALSE;
00423 
00424 // separated the following functionality from IR_Dwarf_Gen_File_Table
00425 // ir_print_filename allows us to print path names from DST onto the
00426 // ir_ofile in the form of LOC entries.  This function can
00427 // be called (with dump_filenames == TRUE) from multiple places.
00428 
00429 static void ir_print_filename(BOOL dump_filenames)
00430 {
00431 /*
00432     * Optionally, (if dump_filenames == TRUE)
00433     * all path names present in the DST information may
00434     * be dumped to the ir_ofile in the form of LOC entries.
00435 */
00436   INT count;
00437   DST_IDX idx;
00438   DST_FILE_NAME *file;
00439   char *name;
00440   INT file_table_size;
00441   INT new_size;
00442 
00443 
00444   file_table_size = 0;
00445   file_table = NULL;
00446   count = 1;
00447   for (idx = DST_get_file_names (); 
00448        !DST_IS_NULL(idx); 
00449        idx = DST_FILE_NAME_next(file))
00450     {
00451       file = DST_FILE_IDX_TO_PTR (idx);
00452       if (DST_IS_NULL(DST_FILE_NAME_name(file))) {
00453         name = "NULLNAME";
00454       }
00455       else {
00456         name = DST_STR_IDX_TO_PTR (DST_FILE_NAME_name(file));
00457       }
00458       if (count >= file_table_size) {
00459         new_size = count + 10;
00460         if (file_table == NULL)
00461           file_table = (file_info *) malloc (new_size * sizeof (file_info));
00462         else 
00463           file_table = (file_info *) realloc (file_table, 
00464                                               new_size * sizeof (file_info));
00465         if (file_table == NULL) 
00466           fprintf(stderr, "IR_Dwarf_Gen_File_Table: Run out of memory\n");
00467         file_table_size = new_size;
00468       }
00469       file_table[count].filename = name;
00470       file_table[count].incl_index = DST_FILE_NAME_dir(file);
00471       file_table[count].fileptr = NULL;
00472       file_table[count].max_line_printed = 0;
00473       if (dump_filenames)
00474         fprintf (ir_ofile, " LOC 0 0 source files:\t%d\t\"%s/%s\"\n",
00475                  count,
00476                  incl_table[DST_FILE_NAME_dir(file)],
00477                  name);
00478       count++;
00479     }
00480   /* make sure all fileptr values are NULL */
00481   while (count < file_table_size) {
00482     file_table[count].fileptr = NULL;
00483     count++;
00484   }
00485 
00486 } /* ir_print_filename */
00487 
00488 extern void IR_Dwarf_Gen_File_Table (BOOL dump_filenames)
00489 {
00490    /* Generate a table of the include directory names and a table
00491     * of the file names, based on the DST (Debugging Symbol Table).
00492     * The USRCPOS_filenum() is a positional index into the list of
00493     * file names as given by DST_get_file_names(), starting at 
00494     * index==1.  Similarly, the DST_FILE_NAME_dir(file_info) is a
00495     * positional index into the list of directory names as given by
00496     * DST_get_dir_names().
00497     * call ir_print_filename to optionally print all pathnames in the DST info
00498     */
00499   INT count;
00500   DST_IDX idx;
00501   DST_INCLUDE_DIR *incl;
00502   char *name;
00503   INT incl_table_size;
00504   INT new_size;
00505 
00506   if (file_table_generated && file_table != NULL) {
00507         /* only need to reset the fileptr and line_printed info */
00508         for (count = 1; file_table[count].fileptr != NULL; count++) {
00509                 fclose (file_table[count].fileptr);
00510                 file_table[count].fileptr = NULL;
00511                 file_table[count].max_line_printed = 0;
00512               }
00513         cur_file_index = 0;
00514         return;
00515         }
00516 
00517   incl_table_size = 0;
00518   incl_table = NULL;
00519   file_table = NULL;
00520   count = 1;
00521   for (idx = DST_get_include_dirs (); 
00522        !DST_IS_NULL(idx); 
00523        idx = DST_INCLUDE_DIR_next(incl))
00524     {
00525       incl = DST_DIR_IDX_TO_PTR (idx);
00526       name = DST_STR_IDX_TO_PTR (DST_INCLUDE_DIR_path(incl));
00527       if (count >= incl_table_size) {
00528         new_size = count + 10;
00529         if (incl_table == NULL)
00530           incl_table = (char **) malloc (new_size * sizeof (char *));
00531         else 
00532           incl_table = (char **) realloc (incl_table, new_size * sizeof (char *));
00533         if (incl_table == NULL) 
00534           fprintf(stderr, "IR_Dwarf_Gen_File_Table: Run out of memory\n");
00535         incl_table_size = new_size;
00536       }
00537       incl_table[count] = name;
00538       count++;
00539     }
00540   
00541   ir_print_filename(dump_filenames); /* print the loc 0 0 heading */
00542 
00543   file_table_generated = TRUE;
00544 } /* IR_Dwarf_Gen_File_Table */
00545 
00546 
00547 extern void IR_Srcpos_Filename(SRCPOS srcpos,        /* in */
00548                                const char **fname,   /* out */
00549                                const char **dirname) /* out */
00550 {
00551    /* Get two character strings denoting the file-name and directory
00552     * path-name for the file-number denoted by the srcpos.  fname
00553     * and dirname must both be non-NULL references to objects that
00554     * can denote the character strings returned by this subroutine.
00555     * For unknown file/directory components, *fname and/or *dirname 
00556     * will be set to NULL.
00557     */
00558    USRCPOS usrcpos;
00559 
00560    USRCPOS_srcpos(usrcpos) = srcpos;
00561    if (USRCPOS_filenum(usrcpos) == 0)
00562    {
00563       *fname = NULL;
00564       *dirname = NULL;
00565    }
00566    else
00567    {
00568       file_info *cur_file;
00569 
00570       if (!file_table_generated)
00571          IR_Dwarf_Gen_File_Table(FALSE/*dump_filenames*/);
00572 
00573       cur_file = &file_table[USRCPOS_filenum(usrcpos)];
00574       *fname = cur_file->filename;
00575       *dirname = incl_table[cur_file->incl_index];
00576    }
00577 } /* IR_Srcpos_Filename */
00578 
00579 
00580 /*========================================================================
00581 
00582    Print source lines (taken from cgdwarf.c)
00583  
00584  ========================================================================*/
00585 static void
00586 print_source (SRCPOS srcpos)
00587 {
00588   USRCPOS usrcpos;
00589   char srcfile[1024];
00590   char text[1024];
00591   file_info *cur_file;
00592   INT i;
00593   INT newmax;
00594 
00595   USRCPOS_srcpos(usrcpos) = srcpos;
00596 
00597   if (USRCPOS_filenum(usrcpos) == 0) { 
00598         /* ??? Shouldn't see this, but print it so know when it does occur */
00599         fprintf(ir_ofile, "LOC 0 %d\n", USRCPOS_linenum(usrcpos));
00600         return;
00601   }
00602 
00603   cur_file = &file_table[USRCPOS_filenum(usrcpos)];
00604   if (USRCPOS_filenum(usrcpos) != cur_file_index) {
00605     if (cur_file_index != 0) {
00606       /* close the previous file. */
00607       file_info *prev_file = &file_table[cur_file_index];
00608       fclose (prev_file->fileptr);
00609       prev_file->fileptr = NULL;
00610     }
00611     cur_file_index = USRCPOS_filenum(usrcpos);
00612     cur_file = &file_table[cur_file_index];
00613     /* open the new file. */
00614     sprintf (srcfile, "%s/%s", incl_table[cur_file->incl_index], 
00615                                 cur_file->filename);
00616     cur_file->fileptr = fopen (srcfile, "r");
00617     if (cur_file->fileptr == NULL) {
00618       cur_file_index = 0;       /* indicate invalid cur_file */
00619       fprintf (ir_ofile, " LOC %d %d\n", cur_file_index, 
00620                USRCPOS_linenum(usrcpos));
00621       return;
00622     }
00623     cur_file->max_line_printed = 0;     /* reset so lines will be reprinted */
00624     newmax = USRCPOS_linenum(usrcpos) - 2;
00625   }
00626   else {
00627     newmax = USRCPOS_linenum(usrcpos) - 5;
00628   }
00629   if (cur_file->max_line_printed < newmax) {
00630     for (i = cur_file->max_line_printed; i < newmax; i++) {
00631       fgets (text, sizeof(text), cur_file->fileptr);
00632     }
00633     cur_file->max_line_printed = newmax;
00634   }
00635   if (cur_file->max_line_printed < USRCPOS_linenum(usrcpos)) {
00636     for (i = cur_file->max_line_printed; i < USRCPOS_linenum(usrcpos); i++) {
00637       if (fgets (text, sizeof(text), cur_file->fileptr) != NULL)
00638         fprintf (ir_ofile, " LOC %d %d %s", cur_file_index, i+1, text);
00639     }
00640     cur_file->max_line_printed = USRCPOS_linenum(usrcpos);
00641   }
00642   else if (cur_file->max_line_printed != USRCPOS_linenum(usrcpos)
00643         && USRCPOS_linenum(usrcpos) != 0) 
00644   {
00645     /* 
00646      * could be a line before the last LOC;
00647      * too hard to print text, but at least print LOC
00648      */
00649     fprintf (ir_ofile, " LOC %d %d\n", cur_file_index, 
00650         USRCPOS_linenum(usrcpos));
00651   }
00652 }
00653 
00654 /*========================================================================
00655 
00656   Misc utilities
00657 
00658  ========================================================================*/
00659  
00660 
00661 #ifdef IR_TOOLS /* only included for tools which translate ascii->binary */
00662 
00663 /*========================================================================
00664 
00665   Hash table routines for the lookup keywords.
00666 
00667     ir_insert_hash
00668     ir_lookup
00669     ir_build_hashtable
00670 
00671 ========================================================================*/
00672 
00673 
00674 /*
00675  *  Find a new entry from the string in the operator table.
00676  */
00677 static BOOL ir_insert_hash(char *s, IR_OPCODE_TABLE *opcode_entry)
00678 {
00679   char *p;
00680   UINT sum = 0;
00681   INT i;
00682 
00683   for (p = s; *p != '\0'; p++)
00684     sum = (sum+sum+3377)^*p;    /* better than sum+= *p for our keyword set */
00685 //if (sum < 0) sum = -sum;
00686   sum %= HASH_LEN;
00687   for (i = 0; i < HASH_LEN; i++) {
00688     if (opcode_hash[sum] == NULL) {
00689       opcode_hash[sum] = opcode_entry;
00690       return TRUE;
00691     }
00692     if (strcmp(opcode_hash[sum]->pr_name, s) == 0)
00693       return FALSE;
00694     sum = (sum + 1) % HASH_LEN;
00695   }
00696   return FALSE;
00697 }
00698 
00699 
00700 /*
00701  *  Lookup the string from the operator table.
00702  */
00703 static INT ir_lookup(char *s)
00704 {
00705   char *p;
00706   INT sum = 0;
00707   INT i;
00708 
00709   for (p = s; *p != '\0'; p++)
00710     sum = (sum+sum+3377)^*p;
00711   sum %= HASH_LEN;
00712   for (i = 0; i < HASH_LEN; i++) {
00713     if (opcode_hash[sum] == NULL)
00714       return -1;
00715     if (strcmp(opcode_hash[sum]->pr_name, s) == 0)
00716       return (opcode_hash[sum] - ir_opcode_table);
00717     sum = (sum + 1) % HASH_LEN;
00718   }
00719   return -1;
00720 }
00721 
00722 
00723 /*
00724  *  Enter opcode into the IR table.
00725  */
00726 static void enter_opcode_table(char *name, OPCODE opc, INT opr)
00727 {
00728     ir_opcode_table[opc].pr_name = name;
00729     if (!ir_insert_hash(ir_opcode_table[opc].pr_name, &ir_opcode_table[opc])) {
00730       sprintf(errmsg, "cannot insert %s into hash table", OPCODE_name(opc));
00731       ir_error(errmsg);
00732     }
00733 }
00734 
00735 
00736 static inline
00737 void enter_opcode_table (char *name, OPC_EXTENDED opc, INT opr)
00738 {
00739     enter_opcode_table (name, (OPCODE) opc, opr);
00740 }
00741 
00742 /*
00743  *  Build IR table 
00744  */
00745 static void ir_build_hashtable(void)
00746 {
00747   INT i;
00748   INT opr;
00749   
00750   /* Clear the tables */
00751   memset(ir_opcode_table, 0, sizeof(ir_opcode_table));
00752   memset(opcode_hash,     0, sizeof(opcode_hash));
00753 
00754   /* Enter the WHIRL opcodes. */
00755   for (i = OPCODE_FIRST; i <= OPCODE_LAST; i++) {
00756       OPCODE opc = (OPCODE) i;
00757     opr = OPCODE_operator(opc);
00758     enter_opcode_table(((char *)OPCODE_name(opc))+strlen("OPC_"), opc, opr);
00759   }
00760 
00761   /* Enter the extended opcodes. */
00762   enter_opcode_table("BODY", OPC_BODY, OPR_BODY);
00763   enter_opcode_table("NOOP", OPC_NOOP, OPR_NOOP);
00764   enter_opcode_table("END_BLOCK", OPC_END_BLOCK, OPR_END_BLOCK);
00765   enter_opcode_table("THEN", OPC_THEN, OPR_THEN);
00766   enter_opcode_table("ELSE", OPC_ELSE, OPR_ELSE);
00767   enter_opcode_table("END_IF", OPC_END_IF, OPR_END_IF);
00768   enter_opcode_table("INIT", OPC_INIT, OPR_INIT);
00769   enter_opcode_table("COMP", OPC_COMP, OPR_COMP);
00770   enter_opcode_table("INCR", OPC_INCR, OPR_INCR);
00771   enter_opcode_table("END_COMPGOTO", OPC_END_COMPGOTO, OPR_END_COMPGOTO);
00772   enter_opcode_table("END_XGOTO", OPC_END_XGOTO, OPR_END_XGOTO);
00773   enter_opcode_table("LOC", OPC_LOC, OPR_LOC);
00774   enter_opcode_table("END_LOOP_INFO", OPC_END_LINFO, OPR_END_LINFO);
00775   enter_opcode_table("END_SWITCH", OPC_END_SWITCH, OPR_END_SWITCH);
00776 }
00777 
00778 #endif /* IR_TOOLS */
00779 
00780 
00781 /*========================================================================
00782 
00783   IR Ascii Writer
00784     ir_put_wn
00785     ir_put_expr
00786     ir_put_stmt
00787     IR_put_func
00788 
00789  ========================================================================*/
00790 
00791 static void
00792 ir_put_st (ST_IDX st_idx)
00793 {
00794   char *name;
00795   char *p;
00796   
00797   if (st_idx == (ST_IDX) 0) {
00798     /* labels may have empty st */
00799     fprintf(ir_ofile, " <null-st>");
00800 
00801   } else if (!follow_st) {
00802     /* Do not follow ST *, so that it can dump useful information
00803        even when ST * is not valid */
00804     fprintf(ir_ofile, " <st %d>", (INT32) st_idx);
00805 
00806   } else {
00807     const ST* st = &St_Table[st_idx];
00808     if (ST_class(st) == CLASS_CONST) {
00809       name = Targ_Print(NULL, STC_val(st));
00810       /* new lines and spaces in constant strings 
00811        * will mess up the ascii reader,
00812        * so replace with underlines */
00813       for (p = name; *p != '\0'; p++)
00814         switch (*p) {
00815         case ' ':
00816         case '\t':
00817         case '\n':
00818           *p = '_';
00819         }
00820     } else
00821       name = ST_name(st);
00822     fprintf (ir_ofile, " <%d,%d,%s>", ST_level (st), ST_index (st), name);
00823   }
00824 }
00825 
00826 
00827 /* 
00828  * little routine to print TY's and their attributes, since otherwise they aren't visible
00829  */
00830 static void
00831 ir_put_ty(TY_IDX ty)
00832 {
00833    fprintf(ir_ofile, " T<%d,%s,%d", TY_id(ty),
00834            TY_name(ty),TY_align(ty));
00835    
00836    if (TY_is_restrict(ty)) 
00837       fprintf(ir_ofile, ",R");
00838    
00839    if (TY_is_volatile(ty)) 
00840       fprintf(ir_ofile, ",V");
00841    
00842    if (TY_is_const(ty)) 
00843       fprintf(ir_ofile, ",C");
00844    
00845    fprintf(ir_ofile, ">");
00846 }
00847 
00848 
00849 static void
00850 ir_put_parm_keyword(ST * st)
00851 {
00852     TCON          strcon = STC_val(st);
00853   INT32         strlen ;
00854   INT32         stridx ;
00855   const char    *strbase;
00856   char          *keyword;
00857                                                                                        
00858   strlen  = Targ_String_Length(strcon);
00859   strbase = Targ_String_Address(strcon);
00860 
00861   keyword = (char *) malloc((strlen+1)* sizeof(char));
00862   FmtAssert (keyword,("No more memory for holding keyword."));
00863 
00864   for (stridx = 0; stridx<strlen;stridx++)
00865        keyword[stridx] = strbase[stridx];
00866   keyword[stridx] = '\0';
00867   fprintf(ir_ofile, keyword);
00868   free(keyword);
00869  }
00870 
00871 /*
00872  *  Write an WN * in ascii form on an individual line.
00873  */ 
00874 static void ir_put_wn(WN * wn, INT indent)
00875 {
00876     OPCODE opcode;
00877 
00878     if (wn == NULL) {
00879         /* null statement */
00880 //      fprintf(ir_ofile, "### error: null WN pointer\n");
00881         fprintf(ir_ofile, "### attention: null WN pointer, place holder\n");
00882         return;
00883     } else {
00884         if (IR_dump_wn_addr) {
00885             fprintf(ir_ofile, "0x%8p: ", wn);
00886         }
00887         opcode = WN_opcode(wn);
00888     }
00889     if (opcode == 0) {
00890         fprintf(ir_ofile,"### error: WN opcode 0\n");
00891         return;
00892     }
00893     /*
00894      *  for dependency dumping, dump a handle to refer to later
00895      */
00896     if (IR_DUMPDEP_info) {
00897         INT32 handle=  0;
00898         if (OPCODE_has_alias_info(WN_opcode(wn)) && WN_map_id(wn) != -1) {
00899             handle= AddToDUMPDEP(wn);
00900         }
00901         fprintf(ir_ofile, "[%5d]", handle);
00902     }
00903 
00904     if (indent > 0 && opcode == OPC_LABEL)
00905         fprintf(ir_ofile, "%*s", indent-1, "");
00906     else
00907         fprintf(ir_ofile, "%*s", indent, "");
00908 
00909     fprintf(ir_ofile, "%s", OPCODE_name(opcode) + strlen("OPC_"));
00910     if (OPCODE_has_offset(opcode)) {
00911         if (OPCODE_operator(opcode) == OPR_PRAGMA || 
00912             OPCODE_operator(opcode) == OPR_XPRAGMA)
00913             fprintf(ir_ofile, " %d %d", WN_pragma_flags(wn), WN_pragma(wn));
00914         else
00915             fprintf(ir_ofile, " %d", WN_offset(wn));
00916     } else if (OPCODE_has_2offsets(opcode)) {
00917         fprintf(ir_ofile, " %d %d",
00918                 WN_loop_trip_est(wn), WN_loop_depth(wn));
00919     }
00920 
00921     switch (OPCODE_operator(opcode)) {
00922 
00923     case OPR_INTRINSIC_OP:
00924     case OPR_ARRAYEXP:
00925       fprintf(ir_ofile, " %d", WN_kid_count(wn));
00926       break;
00927 
00928     case OPR_REGION:
00929       fprintf(ir_ofile, " %d", WN_region_id(wn));
00930       fprintf(ir_ofile, " (kind=%d)",WN_region_kind(wn));
00931       break;
00932 
00933     case OPR_LDBITS:
00934     case OPR_ILDBITS:
00935     case OPR_STBITS:
00936     case OPR_ISTBITS:
00937     case OPR_EXTRACT_BITS:
00938     case OPR_COMPOSE_BITS:
00939       fprintf(ir_ofile, " <bofst:%d bsize:%d>", WN_bit_offset(wn),
00940               WN_bit_size(wn));
00941       break;
00942 
00943     case OPR_ASM_INPUT:
00944       fprintf(ir_ofile, " opnd:%d", WN_asm_opnd_num(wn));
00945       break;
00946 
00947     default:
00948       break;
00949     }
00950 
00951     if (OPCODE_has_inumber(opcode)) {
00952         switch (opcode) {
00953         case OPC_IO:
00954             fprintf(ir_ofile, " <%d,%s,%s>", WN_intrinsic(wn),
00955                     IOSTATEMENT_name((IOSTATEMENT) WN_intrinsic(wn)),
00956                     get_iolibrary_name(WN_IO_Library(wn)));
00957             break;
00958         case OPC_IO_ITEM:
00959             fprintf(ir_ofile, " <%d,%s>", WN_intrinsic(wn),
00960                     IOITEM_name((IOITEM) WN_intrinsic(wn)));
00961             break;
00962         default:                /* intrinsic */
00963             Is_True(OPCODE_operator(opcode) == OPR_INTRINSIC_OP ||
00964                     OPCODE_operator(opcode) == OPR_INTRINSIC_CALL,
00965                     ("ir_put_wn, expected an intrinsic"));
00966             fprintf(ir_ofile, " <%d,%s>", WN_intrinsic(wn),
00967                     INTRINSIC_name((INTRINSIC) WN_intrinsic(wn)));
00968             break;
00969         }
00970     }
00971 
00972     if (OPCODE_has_bits(opcode))
00973         fprintf(ir_ofile, " %d", WN_cvtl_bits(wn));
00974     if (OPCODE_has_label(opcode))
00975         fprintf(ir_ofile, " L%d", WN_label_number(wn));
00976     if (OPCODE_has_flags(opcode)) 
00977         fprintf(ir_ofile, " %d", WN_flag(wn));
00978     if (OPCODE_has_sym(opcode)) {
00979         ir_put_st (WN_st_idx(wn));
00980     }
00981 
00982     if (OPCODE_has_1ty(opcode)) {
00983         if (WN_ty(wn) != (TY_IDX) 0) 
00984            ir_put_ty(WN_ty(wn));
00985         else
00986             if (opcode != OPC_IO_ITEM)
00987                 fprintf(ir_ofile, " T<### ERROR: null ptr>");
00988     } else if (OPCODE_has_2ty(opcode)) {
00989         if (WN_ty(wn) != (TY_IDX) 0) 
00990            ir_put_ty(WN_ty(wn));
00991         else
00992             fprintf(ir_ofile, " T<### ERROR: null ptr>");
00993         if (WN_load_addr_ty(wn) != (TY_IDX) 0) 
00994            ir_put_ty(WN_load_addr_ty(wn));
00995         else
00996             fprintf(ir_ofile, " T<### ERROR: null ptr>");
00997     }
00998 
00999     if (OPCODE_has_ndim(opcode))
01000         fprintf(ir_ofile, " %d", WN_num_dim(wn));
01001     if (OPCODE_has_esize(opcode))
01002         fprintf(ir_ofile, " %lld", WN_element_size(wn));
01003 
01004     if (OPCODE_has_num_entries(opcode))
01005         fprintf(ir_ofile, " %d", WN_num_entries(wn));
01006     if (OPCODE_has_last_label(opcode))
01007         fprintf(ir_ofile, " %d", WN_last_label(wn));
01008 
01009     if (OPCODE_has_value(opcode)) {
01010         fprintf(ir_ofile, " %lld", WN_const_val(wn));
01011         /* Also print the hex value for INTCONSTs */
01012         if (OPCODE_operator(opcode) == OPR_INTCONST || opcode == OPC_PRAGMA) {
01013             fprintf(ir_ofile, " (0x%llx)", WN_const_val(wn));
01014         }
01015     }
01016 
01017     if (OPCODE_has_field_id(opcode) && WN_field_id(wn)) {
01018         fprintf(ir_ofile, " <field_id:%d>", WN_field_id(wn));
01019     }
01020     
01021 
01022     if (OPCODE_has_ereg_supp(opcode)) {
01023         INITO_IDX ino = WN_ereg_supp(wn);
01024         if (ino != 0)
01025             fprintf (ir_ofile, " INITO<%d,%s>", INITO_IDX_index (ino), 
01026                      ST_name (INITO_st_idx (Inito_Table[ino])));
01027     }
01028     if (opcode == OPC_COMMENT) {
01029         fprintf(ir_ofile, " # %s", Index_To_Str(WN_offset(wn)));
01030     }
01031 
01032     if (follow_st && OPCODE_has_sym(opcode) && OPCODE_has_offset(opcode)
01033         && WN_st_idx(wn) != (ST_IDX) 0 && (ST_class(WN_st(wn)) == CLASS_PREG)
01034         && opcode != OPC_PRAGMA)
01035         {
01036             if (Preg_Is_Dedicated(WN_offset(wn))) {
01037                 if (Preg_Offset_Is_Int(WN_offset(wn))) {
01038                         fprintf(ir_ofile, " # $r%d", WN_offset(wn));
01039                 }
01040                 else if (Preg_Offset_Is_Float(WN_offset(wn))) {
01041                         fprintf(ir_ofile, " # $f%d", 
01042                                 WN_offset(wn) - Float_Preg_Min_Offset);
01043                 }
01044             }
01045             else { 
01046                 /* reference to a non-dedicated preg */
01047                 if ((WN_offset(wn) - Last_Dedicated_Preg_Offset) 
01048                         < PREG_Table_Size (CURRENT_SYMTAB) )
01049                     fprintf(ir_ofile, " # %s", Preg_Name(WN_offset(wn)));
01050                 else
01051                     fprintf(ir_ofile, " # <Invalid PREG Table index (%d)>",
01052                             WN_offset(wn));
01053             }
01054         }
01055 
01056     if (opcode == OPC_XPRAGMA) {
01057         fprintf(ir_ofile, " # %s", WN_pragmas[WN_pragma(wn)].name);
01058     }
01059 
01060     if (OPCODE_operator(opcode) == OPR_ASM_INPUT) {
01061       fprintf(ir_ofile, " # \"%s\"", WN_asm_input_constraint(wn));
01062     }
01063 
01064     if (opcode == OPC_PRAGMA) {
01065         fprintf(ir_ofile, " # %s", WN_pragmas[WN_pragma(wn)].name);
01066         switch(WN_pragma(wn)) {
01067         case WN_PRAGMA_DISTRIBUTE:
01068         case WN_PRAGMA_REDISTRIBUTE:
01069         case WN_PRAGMA_DISTRIBUTE_RESHAPE:
01070             fprintf(ir_ofile, ", %d",WN_pragma_index(wn));
01071             switch(WN_pragma_distr_type(wn)) {
01072             case DISTRIBUTE_STAR:
01073                 fprintf(ir_ofile, ", *");
01074                 break;
01075             case DISTRIBUTE_BLOCK:
01076                 fprintf(ir_ofile, ", BLOCK");
01077                 break;
01078             case DISTRIBUTE_CYCLIC_CONST:
01079                 fprintf(ir_ofile, ", CYCLIC(%d)", WN_pragma_preg(wn));
01080                 break;
01081             case DISTRIBUTE_CYCLIC_EXPR:
01082                 fprintf(ir_ofile, ", CYCLIC(expr)");
01083                 break;
01084             }
01085             break;
01086         case WN_PRAGMA_ASM_CONSTRAINT:
01087           fprintf(ir_ofile, ", \"%s\", opnd:%d preg:%d",
01088                   WN_pragma_asm_constraint(wn),
01089                   WN_pragma_asm_opnd_num(wn),
01090                   WN_pragma_asm_copyout_preg(wn));
01091           break;
01092         default:
01093             if (WN_pragma_arg2(wn) != 0 )
01094                 fprintf(ir_ofile, ", %d, %d", WN_pragma_arg1(wn), WN_pragma_arg2(wn));
01095             else
01096                 if (WN_pragma_arg1(wn) != 0 )
01097                     fprintf(ir_ofile, ", %d", WN_pragma_arg1(wn));
01098             break;
01099         } /* switch */
01100     }
01101 
01102     if (OPCODE_operator(opcode) == OPR_ASM_STMT) {
01103       fprintf(ir_ofile, " # \"%s\"", WN_asm_string(wn));
01104       if (WN_Asm_Volatile(wn))
01105         fprintf(ir_ofile, " (volatile)");
01106       if (WN_Asm_Clobbers_Mem(wn))
01107         fprintf(ir_ofile, " (memory)");
01108       if (WN_Asm_Clobbers_Cc(wn))
01109         fprintf(ir_ofile, " (cc)");
01110     }
01111 
01112     if (OPCODE_is_call(opcode))
01113         fprintf(ir_ofile, " # flags 0x%x", WN_call_flag(wn));
01114 
01115     if (OPCODE_operator(opcode) == OPR_PARM) {
01116         INT flag =  WN_flag(wn);
01117         fprintf(ir_ofile, " # ");
01118         if (flag & WN_PARM_BY_REFERENCE) fprintf(ir_ofile, " by_reference ");
01119         if (flag & WN_PARM_BY_VALUE)     fprintf(ir_ofile, " by_value ");
01120         if (flag & WN_PARM_OUT)          fprintf(ir_ofile, " out ");
01121         if (flag & WN_PARM_DUMMY)        fprintf(ir_ofile, " dummy ");
01122         if (flag & WN_PARM_READ_ONLY)    fprintf(ir_ofile, " read_only ");
01123         if (flag & WN_PARM_PASSED_NOT_SAVED) fprintf(ir_ofile, "passed_not_saved ");
01124         if (flag & WN_PARM_NOT_EXPOSED_USE) fprintf(ir_ofile, " not_euse ");
01125         if (flag & WN_PARM_IS_KILLED) fprintf(ir_ofile, " killed ");
01126 
01127 /* following add for detail association information*/     
01128         if (flag & WN_PARM_PASS_ADDRESS) fprintf(ir_ofile, "PASS_ADDRESS ");
01129         if (flag & WN_PARM_PASS_ADDRESS_FROM_DV) fprintf(ir_ofile, "PASS_ADDRESS_FROM_DV ");
01130         if (flag & WN_PARM_PASS_DV) fprintf(ir_ofile, "PASS_DV ");
01131         if (flag & WN_PARM_PASS_DV_COPY) fprintf(ir_ofile, "PASS_DV_COPY ");
01132         if (flag & WN_PARM_COPY_IN) fprintf(ir_ofile, "COPY_IN ");
01133         if (flag & WN_PARM_COPY_IN_COPY_OUT ) fprintf(ir_ofile, "COPY_IN_COPY_OUT ");
01134         if (flag & WN_PARM_MAKE_DV) fprintf(ir_ofile, "MAKE_DV ");
01135         if (flag & WN_PARM_COPY_IN_MAKE_DV) fprintf(ir_ofile, "COPY_IN_MAKE_DV ");
01136         if (flag & WN_PARM_MAKE_NEW_DV) fprintf(ir_ofile, "MAKE_NEW_DV ");
01137         if (flag & WN_PARM_PASS_SECTION_ADDRESS) fprintf(ir_ofile, "PASS_SECTION_ADDRESS ");
01138         if (flag & WN_PARM_CHECK_CONTIG_FLAG) fprintf(ir_ofile, "CHECK_CONTIG_FLAG ");
01139         /* ST_IDX point to the keyword of the parameter */
01140         if ( wn->u3.ty_fields.ty) { 
01141            ST * kwrd = &St_Table[wn->u3.ty_fields.ty];
01142            fprintf(ir_ofile, "Keyword: ");
01143            ir_put_parm_keyword(kwrd);
01144           }
01145     
01146      }
01147 
01148     if (IR_dump_map_info) {
01149         fprintf(ir_ofile, " # <id %d:%d>", OPCODE_mapcat(opcode),
01150                 WN_map_id(wn));
01151         if (ir_put_map && ( WN_map_id(wn) != -1 )) {
01152             switch ( WN_MAP_Get_Kind( ir_put_map ) ) {
01153             case WN_MAP_KIND_VOIDP:
01154                 fprintf(ir_ofile, " <map %8p>", WN_MAP_Get( ir_put_map, wn ));
01155                 break;
01156             case WN_MAP_KIND_INT32:
01157                 fprintf(ir_ofile, " <map %08x>", WN_MAP32_Get( ir_put_map, wn ));
01158                 break;
01159             case WN_MAP_KIND_INT64:
01160                 fprintf(ir_ofile, " <map %08llx>", WN_MAP64_Get( ir_put_map, wn ));
01161                 break;
01162             }
01163         }
01164     }
01165 
01166     if (IR_dump_line_numbers &&
01167         (OPCODE_is_scf(WN_opcode(wn)) || OPCODE_is_stmt(WN_opcode(wn)))) {
01168 
01169         USRCPOS srcpos;
01170         USRCPOS_srcpos(srcpos) = WN_Get_Linenum(wn);
01171 
01172         fprintf(ir_ofile, " {line: %d}", USRCPOS_linenum(srcpos));
01173     }
01174 
01175 
01176     if (IR_freq_map != WN_MAP_UNDEFINED && (OPCODE_is_scf(WN_opcode(wn)) ||
01177                                             OPCODE_is_stmt(WN_opcode(wn)))) {
01178         USRCPOS srcpos;
01179         USRCPOS_srcpos(srcpos) = WN_Get_Linenum(wn);
01180 
01181         fprintf(ir_ofile, " {freq: %d, ln: %d, col: %d}",
01182                 WN_MAP32_Get(IR_freq_map, wn),
01183                 USRCPOS_linenum(srcpos),
01184                 USRCPOS_column(srcpos));
01185     }
01186     if (Current_Map_Tab != NULL 
01187         && WN_MAP32_Get(WN_MAP_ALIAS_CLASS, wn) != 0) 
01188     {
01189       fprintf(ir_ofile, " {class %d}",
01190               WN_MAP32_Get(WN_MAP_ALIAS_CLASS, wn));
01191     }
01192     fprintf(ir_ofile, "\n");
01193 }
01194 
01195 
01196 /*
01197  *  Write an expression and its children in postfix order.
01198  *  If dump_parent_before_children, write it in prefix order instead.
01199  */
01200 static void ir_put_expr(WN * wn, INT indent)
01201 {
01202   INT i;
01203   WN * wn2;
01204 
01205   /* See if the parent op should be dumped before or after the children */
01206   if (dump_parent_before_children) {
01207      ir_put_wn(wn,indent);
01208   }
01209   for (i = 0; i < WN_kid_count(wn); i++) {
01210     wn2 = WN_kid(wn,i);
01211     if (wn2) {
01212       OPCODE op = WN_opcode(wn2);
01213       if ((OPCODE_FIRST <= op && op <= OPCODE_LAST) &&
01214           (OPCODE_is_expression(op) || OPCODE_is_call(op)))
01215               ir_put_expr(WN_kid(wn,i), indent+1);
01216       else
01217       if (    op == OPC_BLOCK
01218            && (    (WN_operator(wn) == OPR_RCOMMA && i == 1)
01219                 || (WN_operator(wn) == OPR_COMMA && i == 0)))
01220         ir_put_stmt(wn2, indent+1);
01221       else
01222 //March  fprintf(ir_ofile, "%*sopcode %d not an expression\n", indent+1, "", op);
01223          if (op == OPC_IMPLICIT_BND)
01224                 fprintf(ir_ofile,"%*sIMPLICIT_BND\n",indent+1,""); 
01225          else
01226          fprintf(ir_ofile, "%*sopcode %d not an expression\n", indent+1, "", op);
01227 
01228     } else  
01229       fprintf(ir_ofile, "%*snull-expression\n", indent+1, "");
01230   }
01231   if (!dump_parent_before_children) {
01232      ir_put_wn(wn, indent);
01233   }
01234 }
01235 
01236 
01237 /*
01238  *  Write out a marker at the indentation level.
01239  */
01240 static void ir_put_marker(char *str, INT indent)
01241 {
01242   fprintf(ir_ofile, "%*s%s\n", indent, "", str);
01243 }
01244 
01245 
01246 /*
01247  *  Write a statement WN * and its children in prefix order.
01248  */
01249 static void ir_put_stmt(WN * wn, INT indent)
01250 {
01251   INT i;
01252   WN * wn2;
01253   USRCPOS srcpos;
01254   
01255   if (wn) {
01256     OPCODE opc = WN_opcode(wn);
01257     BOOL already_dumped_wn = FALSE;
01258     USRCPOS_srcpos(srcpos) = WN_Get_Linenum(wn);
01259     if (USRCPOS_srcpos(srcpos) != 0 && 
01260         USRCPOS_srcpos(srcpos) != USRCPOS_srcpos(last_srcpos)) {
01261       last_srcpos = srcpos;
01262 #ifdef FRONT_END
01263       fprintf(ir_ofile, "%*sLOC %d %d\n", indent, "",
01264                 USRCPOS_filenum(srcpos), USRCPOS_linenum(srcpos));
01265 #else
01266       print_source(USRCPOS_srcpos(srcpos));
01267 #endif
01268     }
01269 
01270     if (OPCODE_is_scf(opc) || dump_parent_before_children) {
01271       ir_put_wn(wn, indent);
01272       already_dumped_wn = TRUE;
01273     }
01274 
01275     switch (opc) {
01276 
01277     case OPC_BLOCK:
01278       wn2 = WN_first(wn);
01279       while (wn2) {
01280         ir_put_stmt(wn2, indent);
01281         wn2 = WN_next(wn2);
01282       }
01283       ir_put_marker("END_BLOCK", indent);
01284       break;
01285 
01286     case OPC_LABEL:
01287       ir_put_wn(wn, indent);
01288       if ( WN_label_loop_info(wn) != NULL ) {
01289         ir_put_stmt(WN_label_loop_info(wn), indent+1);
01290       }
01291       already_dumped_wn = TRUE;
01292       break;
01293 
01294     case OPC_IF:
01295       ir_put_expr(WN_if_test(wn), indent+1);
01296       if (WN_then(wn)) {
01297         ir_put_marker("THEN", indent);
01298         ir_put_stmt(WN_then(wn), indent+1);
01299       }
01300       if (WN_else(wn)) {
01301         ir_put_marker("ELSE", indent);
01302         ir_put_stmt(WN_else(wn), indent+1);
01303       }
01304       ir_put_marker("END_IF", indent);
01305       break;
01306 
01307     case OPC_DO_LOOP:
01308       ir_put_expr(WN_index(wn), indent+1);
01309       ir_put_marker("INIT",indent);
01310       ir_put_stmt(WN_start(wn), indent+1);
01311       ir_put_marker("COMP", indent);
01312       ir_put_expr(WN_end(wn), indent+1);
01313       ir_put_marker("INCR", indent);
01314       ir_put_stmt(WN_step(wn), indent+1);
01315       /* optional loop_info */
01316       if ( WN_do_loop_info(wn) != NULL ) {
01317         ir_put_stmt(WN_do_loop_info(wn), indent);
01318       }
01319       ir_put_marker("BODY", indent);
01320       ir_put_stmt(WN_do_body(wn), indent+1);
01321       break;
01322 
01323     case OPC_LOOP_INFO:
01324       ir_put_wn(wn, indent);
01325       if ( WN_loop_induction(wn) != NULL ) {
01326         ir_put_expr(WN_loop_induction(wn), indent+1);
01327       }
01328       if ( WN_loop_trip(wn) != NULL ) {
01329         ir_put_expr(WN_loop_trip(wn), indent+1);
01330       }
01331       ir_put_marker("END_LOOP_INFO", indent);
01332       already_dumped_wn = TRUE;
01333       break;
01334 
01335     case OPC_COMPGOTO:
01336       ir_put_wn(wn, indent);
01337       ir_put_expr(WN_kid(wn,0), indent+1);
01338       ir_put_stmt(WN_kid(wn,1), indent+1);
01339       if (WN_kid_count(wn) > 2)
01340         ir_put_stmt(WN_kid(wn,2), indent+1);
01341       ir_put_marker("END_COMPGOTO", indent);
01342       already_dumped_wn = TRUE;
01343       break;
01344 
01345     case OPC_SWITCH:
01346       ir_put_wn(wn, indent);
01347       ir_put_expr(WN_kid(wn,0), indent+1);
01348       ir_put_stmt(WN_kid(wn,1), indent+1);
01349       if (WN_kid_count(wn) > 2)
01350         ir_put_stmt(WN_kid(wn,2), indent+1);
01351       ir_put_marker("END_SWITCH", indent);
01352       already_dumped_wn = TRUE;
01353       break;
01354 
01355     case OPC_XGOTO:
01356       ir_put_wn(wn, indent);
01357       ir_put_expr(WN_kid(wn,0), indent+1);
01358       ir_put_stmt(WN_kid(wn,1), indent+1);
01359       ir_put_marker("END_XGOTO", indent);
01360       already_dumped_wn = TRUE;
01361       break;
01362 
01363     case OPC_WHERE:
01364       ir_put_expr(WN_kid(wn,0), indent+1);
01365       ir_put_marker("BODY", indent);
01366       ir_put_stmt(WN_kid(wn,1), indent+1);
01367       ir_put_stmt(WN_kid(wn,2), indent+1);
01368       break;
01369 
01370     case OPC_EXC_SCOPE_BEGIN:
01371       {
01372         INT i;
01373         for (i = 0; i < WN_kid_count(wn); i++)
01374           ir_put_stmt(WN_kid(wn, i), indent+1);
01375         break;
01376       }
01377     case OPC_EXC_SCOPE_END:
01378      break;
01379 
01380     case OPC_ASM_STMT:
01381       ir_put_wn(wn, indent);
01382       already_dumped_wn = TRUE;
01383       ir_put_stmt(WN_kid(wn,0), indent+1);
01384       ir_put_stmt(WN_kid(wn,1), indent+1);
01385       ir_put_marker("ASM_INPUTS", indent);
01386       {
01387         INT i;
01388         for (i = 2; i < WN_kid_count(wn); i++) {
01389           ir_put_expr(WN_kid(wn,i), indent+1);
01390         }
01391       }
01392       ir_put_marker("END_ASM_INPUTS", indent);
01393       break;
01394 
01395     case OPC_VUSE:
01396     case OPC_BUSE:
01397       ir_put_marker("USE!!!!!", indent); // VUSE is plain USE. BUSE is USE::ONLY
01398       break; 
01399 
01400     default: 
01401       {
01402         INT last_is_expr = TRUE;
01403         OPCODE opc2;
01404         for (i = 0; i < WN_kid_count(wn); i++) {
01405           wn2 = WN_kid(wn,i);
01406           if (wn2) {
01407             opc2 = WN_opcode(wn2);
01408             if (opc2 == 0) {
01409                fprintf(ir_ofile, "### error: WN opcode 0\n");
01410             } else if (OPCODE_is_expression(opc2)) {
01411               ir_put_expr(wn2, indent+1);
01412               last_is_expr = 1;
01413             }
01414             else if (OPCODE_is_stmt(opc2) || OPCODE_is_scf(opc2)) {
01415               if (last_is_expr) {
01416                 ir_put_marker("BODY", indent);
01417                 ir_put_stmt(wn2, indent+1);
01418               } else
01419                 ir_put_stmt(WN_kid(wn,i), indent+1);
01420               last_is_expr = 0;
01421             } else {
01422                fprintf(ir_ofile, "### error: unknown opcode type %d\n",opc2);
01423             }
01424           } else
01425             ir_put_stmt(wn2, indent+1);
01426         }
01427       }
01428     }
01429     if (!already_dumped_wn)
01430       ir_put_wn(wn, indent);
01431   } else
01432     ir_put_wn(wn, indent);
01433 }
01434 
01435 /*
01436  *  Write an WN * with OPC_FUNC_ENTRY.
01437  */
01438 extern void IR_put_func(WN * wn, FILE *f)
01439 {
01440   FILE *save;
01441   if (f) {
01442       save = ir_ofile;
01443       ir_ofile = f;
01444   }
01445   ir_put_stmt(wn, 0);
01446   if (f) {
01447       ir_ofile = save;
01448   }
01449 }
01450 
01451 
01452 /*========================================================================
01453  
01454       Dumping the WN structure.
01455   
01456  ========================================================================*/
01457 
01458 /*
01459  *  Debugging:  dump an wn to stdout.
01460  */
01461 extern void dump_wn(WN *wn)
01462 {
01463   FILE *save;
01464   /* building hashtable is expensive, so may not initialize until dumping */
01465   if (!is_initialized) IR_reader_init();
01466   save = ir_ofile;
01467   ir_ofile = stdout; 
01468   IR_Dwarf_Gen_File_Table(TRUE/*dump_filenames*/); /* read source pathnames */
01469   ir_put_wn(wn, 0);
01470   ir_ofile = save;
01471 }
01472 
01473 extern void fdump_wn(FILE *fp, WN *wn)
01474 {
01475   FILE *save;
01476   /* building hashtable is expensive, so may not initialize until dumping */
01477   if (!is_initialized) IR_reader_init();
01478   save = ir_ofile;
01479   ir_ofile = fp;
01480   IR_Dwarf_Gen_File_Table(TRUE/*dump_filenames*/); /* read source pathnames */
01481   ir_put_wn(wn, 0);
01482   ir_ofile = save;
01483 }
01484 
01485 extern void dump_tree(WN *wn)
01486 {
01487    fdump_tree(stdout,wn);
01488 }
01489 
01490 
01491 extern void dump_region_tree(WN *wn)
01492 {
01493    BOOL save = IR_dump_region;
01494    IR_dump_region = TRUE;
01495    fdump_tree(stdout, wn);
01496    IR_dump_region = save;
01497 }
01498 
01499 extern void dump_wn_no_st(WN *wn)
01500 {
01501   BOOL save_follow_st;
01502   if (!is_initialized) IR_reader_init();
01503   save_follow_st = follow_st;
01504   follow_st = FALSE;
01505   dump_wn(wn);
01506   follow_st = save_follow_st;
01507 }
01508 
01509 extern void fdump_wn_no_st(FILE *fp, WN *wn)
01510 {
01511   BOOL save_follow_st;
01512   FILE *save = ir_ofile;
01513   if (!is_initialized) IR_reader_init();
01514   save_follow_st = follow_st;
01515   ir_ofile = fp;
01516   follow_st = FALSE;
01517   IR_Dwarf_Gen_File_Table(TRUE/*dump_filenames*/); /* read source pathnames */
01518   ir_put_wn(wn, 0);
01519   follow_st = save_follow_st;
01520   ir_ofile = save;
01521 }
01522 
01523 extern void dump_tree_no_st(WN *wn)
01524 {
01525   BOOL save_follow_st;
01526   if (!is_initialized) IR_reader_init();
01527   save_follow_st = follow_st;
01528   follow_st = FALSE;
01529   dump_tree(wn);
01530   follow_st = save_follow_st;
01531 }
01532 
01533 extern void fdump_tree(FILE *f, WN *wn)
01534 {
01535   FILE *save;
01536 
01537   /* building hashtable is expensive, so may not initialize until dumping */
01538   if (!is_initialized) IR_reader_init();
01539   save = ir_ofile;
01540   ir_ofile = f;
01541   IR_Dwarf_Gen_File_Table(TRUE/*dump_filenames*/); /* read source pathnames */
01542   if (!wn) {
01543      fprintf(ir_ofile, "<null whirl tree>\n");
01544   } else if (OPCODE_is_stmt(WN_opcode(wn)) || OPCODE_is_scf(WN_opcode(wn)))
01545     ir_put_stmt(wn, 0);
01546   else if (OPCODE_is_expression(WN_opcode(wn)))
01547     ir_put_expr(wn, 0);
01548   else if (WN_opcode(wn) == OPC_FUNC_ENTRY)
01549     IR_put_func(wn, NULL);
01550   else
01551     fprintf(ir_ofile, "unknown opcode in (WN *) 0x%p\n", wn);
01552   ir_ofile = save;
01553 }
01554 
01555 
01556 extern void fdump_tree_no_st( FILE *f, WN *wn )
01557 {
01558   BOOL save_follow_st;
01559   if (!is_initialized) IR_reader_init();
01560   save_follow_st = follow_st;
01561   follow_st = FALSE;
01562   fdump_tree( f, wn );
01563   follow_st = save_follow_st;
01564 }
01565 
01566 extern void fdump_tree_with_alias( FILE *f, const WN *wn, WN_MAP map, const struct ALIAS_MANAGER *am)
01567 {
01568   WN_MAP save = IR_alias_map;
01569   const struct ALIAS_MANAGER *save_am = am;
01570   IR_alias_map = map;
01571   IR_alias_mgr = am;
01572   fdump_tree( f, (WN *)wn );
01573   IR_alias_map = save;
01574   IR_alias_mgr = save_am;
01575 }
01576 
01577 extern void enable_tree_freq_display(void)
01578 {
01579   IR_freq_map = WN_MAP_FEEDBACK;
01580 }
01581 
01582 extern void disable_tree_freq_display(void)
01583 {
01584   IR_freq_map = WN_MAP_UNDEFINED;
01585 }
01586 
01587 extern void fdump_tree_with_freq( FILE *f, const WN *wn, WN_MAP map)
01588 {
01589   WN_MAP save = IR_freq_map;
01590   IR_freq_map = map;
01591   fdump_tree( f, (WN *)wn );
01592   IR_freq_map = save;
01593 }
01594 
01595 extern void fdump_region_tree(FILE *f, WN *wn)
01596 {
01597    BOOL save = IR_dump_region;
01598    IR_dump_region = TRUE;
01599    fdump_tree(f, wn);
01600    IR_dump_region = save;
01601 }
01602 // ======================================================================
01603 //   WN_TREE_put_stmt, WN_TREE_put_expr, WN_TREE_put_func
01604 //   (akin to ir_put_stmt, ir_put_expr, IR_put_func in ir_reader.c)
01605 // ======================================================================
01606 
01607 // Expressions are printed in POSTFIX order unless dump_parent_before_children
01608 // is set in which case they are printed in prefix order.
01609 // WN_TREE_put_expr is akin to ir_put_expr
01610 
01611 static void WN_TREE_put_expr(WN * wn, INT indent) {
01612   WN * wn2;
01613   WN * parent_wn;
01614 
01615   Is_True(OPCODE_is_expression(WN_opcode(wn)) || OPCODE_is_call(WN_opcode(wn)),
01616           ("WN_TREE_put_expr invoked with non-expression, opcode = %s",
01617            OPCODE_name(WN_opcode(wn))));
01618 
01619   // See if the parent op should be dumped before the children  (PRE_ORDER)
01620   if (dump_parent_before_children) {
01621     // create PRE_ORDER tree iterator; use stack of default size
01622 
01623     WN_TREE_ITER<PRE_ORDER> tree_iter(wn);
01624 
01625 #ifndef __GNU_BUG_WORKAROUND
01626     while (tree_iter != LAST_PRE_ORDER_ITER) {
01627 #else
01628     while (tree_iter != WN_TREE_ITER<PRE_ORDER, WN*>()) {
01629 #endif
01630       wn2 = tree_iter.Wn();
01631 
01632       if (OPCODE_is_expression(WN_opcode(wn2)) ||
01633           OPCODE_is_call(WN_opcode(wn2)))
01634         ir_put_wn(wn2,indent+tree_iter.Depth());
01635 
01636       else if (WN_operator(wn2) == OPR_BLOCK) {
01637         // block under an expression had better be due to comma/rcomma
01638         parent_wn = tree_iter.Get_parent_wn();
01639         Is_True(parent_wn && 
01640                 ((WN_operator(parent_wn) == OPR_COMMA) ||
01641                  (WN_operator(parent_wn) == OPR_RCOMMA)),
01642                 ("block under expression not a part of comma/rcomma"));
01643 
01644         WN_TREE_put_stmt(wn2, indent + tree_iter.Depth()); 
01645         tree_iter.Unwind();// have already traversed down the tree 
01646                            //  skip going down this tree again
01647       }
01648 
01649       else
01650         fprintf(ir_ofile, "%*sopcode %d not an expression\n", 
01651                 indent+1,"", WN_opcode(wn2));
01652       ++tree_iter;
01653     } // while
01654   } // if dump_parent_before_children
01655   else {
01656     // post order traversal of expressions falls back on ir_put_expr
01657     // this is so because expressions can contain statements (through comma)
01658     // and in post order, we need to stop going down at statement boundaries 
01659     // which is not currently possible with the generic post_order tree
01660     // iterator
01661     ir_put_expr(wn,indent);
01662   } 
01663 }
01664 
01665 // ======================================================================
01666 // Statements are printed in PREFIX order or if dump_parent_before_children
01667 // is set 
01668 // WN_TREE_put_stmt is akin to ir_put_stmt (it is also recursive)
01669 // ======================================================================
01670 
01671 static void WN_TREE_put_stmt(WN * wn, INT indent)
01672 {
01673   INT i;
01674   WN * wn2;
01675   USRCPOS srcpos;
01676 
01677   Is_True(wn != 0, ("WN_TREE_put_stmt called with null whirl tree"));
01678 
01679   OPCODE opc = WN_opcode(wn);
01680   Is_True(OPCODE_is_scf(opc) || OPCODE_is_stmt(opc),
01681           ("WN_TREE_put_stmt invoked on non statement: opcode = %s",
01682            OPCODE_name(opc)));
01683 
01684   if (wn) {
01685     BOOL already_dumped_wn = FALSE;
01686     USRCPOS_srcpos(srcpos) = WN_Get_Linenum(wn);
01687     if (USRCPOS_srcpos(srcpos) != 0 && 
01688         USRCPOS_srcpos(srcpos) != USRCPOS_srcpos(last_srcpos)) {
01689       last_srcpos = srcpos;
01690 #ifdef FRONT_END
01691       fprintf(ir_ofile, "%*sLOC %d %d\n", indent, "",
01692                 USRCPOS_filenum(srcpos), USRCPOS_linenum(srcpos));
01693 #else
01694       print_source(USRCPOS_srcpos(srcpos));
01695 #endif
01696     }
01697 
01698     if (OPCODE_is_scf(opc) || dump_parent_before_children) {
01699       ir_put_wn(wn, indent);
01700       already_dumped_wn = TRUE;
01701     }
01702 
01703     // create an iterator to go through the statements in a block;
01704     WN_TREE_ITER<PRE_ORDER> tree_iter(wn);
01705 
01706     switch (opc) {
01707 
01708     case OPC_BLOCK:
01709       if (WN_first(wn)) {
01710           ++tree_iter; // get to the first kid of the block
01711 #ifndef __GNU_BUG_WORKAROUND
01712         while (tree_iter != LAST_PRE_ORDER_ITER) {
01713 #else
01714         while (tree_iter != WN_TREE_ITER<PRE_ORDER, WN*>()) {
01715 #endif
01716           wn2 = tree_iter.Wn();
01717           WN_TREE_put_stmt(wn2, indent);// traverse the tree under wn2
01718           tree_iter.Unwind(); // have already traversed the tree under wn2
01719                               // skip going down the tree again
01720         }
01721       }
01722       ir_put_marker("END_BLOCK", indent);
01723       break;
01724 
01725     case OPC_LABEL:
01726       ir_put_wn(wn, indent);
01727       if ( WN_label_loop_info(wn) != NULL ) {
01728         WN_TREE_put_stmt(WN_label_loop_info(wn), indent+1);
01729       }
01730       already_dumped_wn = TRUE;
01731       break;
01732 
01733     case OPC_IF:
01734       WN_TREE_put_expr(WN_if_test(wn), indent+1);
01735       if (WN_then(wn)) {
01736         ir_put_marker("THEN", indent);
01737         WN_TREE_put_stmt(WN_then(wn), indent+1);
01738       }
01739       if (WN_else(wn)) {
01740         ir_put_marker("ELSE", indent);
01741         WN_TREE_put_stmt(WN_else(wn), indent+1);
01742       }
01743       ir_put_marker("END_IF", indent);
01744       break;
01745 
01746     case OPC_DO_LOOP:
01747       WN_TREE_put_expr(WN_index(wn), indent+1);
01748       ir_put_marker("INIT",indent);
01749       WN_TREE_put_stmt(WN_start(wn), indent+1);
01750       ir_put_marker("COMP", indent);
01751       WN_TREE_put_expr(WN_end(wn), indent+1);
01752       ir_put_marker("INCR", indent);
01753       WN_TREE_put_stmt(WN_step(wn), indent+1);
01754       /* optional loop_info */
01755       if ( WN_do_loop_info(wn) != NULL ) {
01756         WN_TREE_put_stmt(WN_do_loop_info(wn), indent);
01757       }
01758       ir_put_marker("BODY", indent);
01759       WN_TREE_put_stmt(WN_do_body(wn), indent+1);
01760       break;
01761 
01762     case OPC_LOOP_INFO:
01763       ir_put_wn(wn, indent);
01764       if ( WN_loop_induction(wn) != NULL ) {
01765         WN_TREE_put_expr(WN_loop_induction(wn), indent+1);
01766       }
01767       if ( WN_loop_trip(wn) != NULL ) {
01768         WN_TREE_put_expr(WN_loop_trip(wn), indent+1);
01769       }
01770       ir_put_marker("END_LOOP_INFO", indent);
01771       already_dumped_wn = TRUE;
01772       break;
01773 
01774     case OPC_COMPGOTO:
01775       ir_put_wn(wn, indent);
01776       WN_TREE_put_expr(WN_kid(wn,0), indent+1);
01777       WN_TREE_put_stmt(WN_kid(wn,1), indent+1);
01778       if (WN_kid_count(wn) > 2)
01779         WN_TREE_put_stmt(WN_kid(wn,2), indent+1);
01780       ir_put_marker("END_COMPGOTO", indent);
01781       already_dumped_wn = TRUE;
01782       break;
01783 
01784     case OPC_SWITCH:
01785       ir_put_wn(wn, indent);
01786       WN_TREE_put_expr(WN_kid(wn,0), indent+1);
01787       WN_TREE_put_stmt(WN_kid(wn,1), indent+1);
01788       if (WN_kid_count(wn) > 2)
01789         WN_TREE_put_stmt(WN_kid(wn,2), indent+1);
01790       ir_put_marker("END_SWITCH", indent);
01791       already_dumped_wn = TRUE;
01792       break;
01793 
01794     case OPC_XGOTO:
01795       ir_put_wn(wn, indent);
01796       WN_TREE_put_expr(WN_kid(wn,0), indent+1);
01797       WN_TREE_put_stmt(WN_kid(wn,1), indent+1);
01798       ir_put_marker("END_XGOTO", indent);
01799       already_dumped_wn = TRUE;
01800       break;
01801 
01802     case OPC_WHERE:
01803       WN_TREE_put_expr(WN_kid(wn,0), indent+1);
01804       ir_put_marker("BODY", indent);
01805       WN_TREE_put_stmt(WN_kid(wn,1), indent+1);
01806       WN_TREE_put_stmt(WN_kid(wn,2), indent+1);
01807       break;
01808 
01809     case OPC_EXC_SCOPE_BEGIN:
01810       {
01811         INT i;
01812         for (i = 0; i < WN_kid_count(wn); i++)
01813           WN_TREE_put_stmt(WN_kid(wn, i), indent+1);
01814         break;
01815       }
01816     case OPC_EXC_SCOPE_END:
01817      break;
01818     default: 
01819       {
01820         INT last_is_expr = TRUE;
01821         OPCODE opc2;
01822         for (i = 0; i < WN_kid_count(wn); i++) {
01823           wn2 = WN_kid(wn,i);
01824           if (wn2) {
01825             opc2 = WN_opcode(wn2);
01826             if (opc2 == 0) {
01827                fprintf(ir_ofile, "### error: WN opcode 0\n");
01828             } else if (OPCODE_is_expression(opc2)) {
01829               WN_TREE_put_expr(wn2, indent+1);
01830               last_is_expr = 1;
01831             }
01832             else if (OPCODE_is_stmt(opc2) || OPCODE_is_scf(opc2)) {
01833               if (last_is_expr) {
01834                 ir_put_marker("BODY", indent);
01835                 WN_TREE_put_stmt(wn2, indent+1);
01836               } else
01837                 WN_TREE_put_stmt(WN_kid(wn,i), indent+1);
01838               last_is_expr = 0;
01839             } else {
01840                fprintf(ir_ofile, "### error: unknown opcode type %d\n",opc2);
01841             }
01842           } else
01843             WN_TREE_put_stmt(wn2, indent+1);
01844         }
01845       }
01846     }
01847     if (!already_dumped_wn)
01848       ir_put_wn(wn, indent);
01849   } else
01850     ir_put_wn(wn, indent);
01851 }
01852 
01853 extern void WN_TREE_put_func(WN * wn, FILE *f)
01854 {
01855   FILE *save;
01856   if (f) {
01857       save = ir_ofile;
01858       ir_ofile = f;
01859   }
01860   WN_TREE_put_stmt(wn, 0);
01861   if (f) {
01862       ir_ofile = save;
01863   }
01864 }
01865 
01866 extern void WN_TREE_fdump_tree(FILE *f, WN *wn)
01867 {
01868   FILE *save;
01869 
01870   /* building hashtable is expensive, so may not initialize until dumping */
01871   if (!is_initialized) IR_reader_init();
01872   save = ir_ofile;
01873   ir_ofile = f;
01874   IR_Dwarf_Gen_File_Table(TRUE/*dump_filenames*/); /* read source pathnames */
01875   ir_print_filename(TRUE/*dump_filenames*/); /* print LOC 0 0 header */
01876   if (!wn) {
01877      fprintf(ir_ofile, "<null whirl tree>\n");
01878   } else if (OPCODE_is_stmt(WN_opcode(wn)) || OPCODE_is_scf(WN_opcode(wn)))
01879     WN_TREE_put_stmt(wn, 0);
01880   else if (OPCODE_is_expression(WN_opcode(wn)))
01881     WN_TREE_put_expr(wn, 0);
01882   else if (WN_opcode(wn) == OPC_FUNC_ENTRY)
01883   WN_TREE_put_func(wn, NULL);
01884   else
01885     fprintf(ir_ofile, "unknown opcode in (WN *) 0x%p\n", wn);
01886   ir_ofile = save;
01887 } 
01888 
01889 extern void WN_TREE_dump_tree(WN *wn)
01890 {
01891    WN_TREE_fdump_tree(stdout,wn);
01892 }
01893 
01894 
01895 #ifdef BACK_END
01896 #endif /* BACK_END */
01897 
01898 extern void Check_for_IR_Dump(INT phase, WN *pu, const char *phase_name)
01899 {
01900     BOOL dump_ir;
01901     BOOL dump_symtab;
01902     dump_ir = Get_Trace ( TKIND_IR, phase );
01903     dump_symtab =  Get_Trace ( TKIND_SYMTAB, phase );
01904     if (dump_ir || dump_symtab) {
01905         fprintf(TFile,"\n\n========== Driver dump after %s ==========\n",
01906                 phase_name);
01907         if (dump_ir) fdump_tree (TFile,pu);
01908         if (dump_symtab) {
01909             Print_symtab (TFile, GLOBAL_SYMTAB);
01910             Print_symtab (TFile, CURRENT_SYMTAB);
01911         }
01912     }
01913 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines