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 //-*-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 }