Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
00001 /* 00002 00003 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00004 00005 This program is free software; you can redistribute it and/or modify it 00006 under the terms of version 2 of the GNU General Public License as 00007 published by the Free Software Foundation. 00008 00009 This program is distributed in the hope that it would be useful, but 00010 WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00012 00013 Further, this software is distributed without any warranty that it is 00014 free of the rightful claim of any third person regarding infringement 00015 or the like. Any license provided herein, whether implied or 00016 otherwise, applies only to this software file. Patent licenses, if 00017 any, provided herein do not apply to combinations of this program with 00018 other software, or any other product whatsoever. 00019 00020 You should have received a copy of the GNU General Public License along 00021 with this program; if not, write the Free Software Foundation, Inc., 59 00022 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00023 00024 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00025 Mountain View, CA 94043, or: 00026 00027 http://www.sgi.com 00028 00029 For further information regarding this notice, see: 00030 00031 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00032 00033 */ 00034 00035 00036 /* ==================================================================== 00037 * ==================================================================== 00038 * 00039 * 00040 * Revision history: 00041 * dd-mmm-94 - Original Version 00042 * 00043 * Description: Base Routines for tree nodes in WHIRL 00044 * 00045 * ==================================================================== 00046 * ==================================================================== 00047 */ 00048 #ifdef USE_PCH 00049 #include "common_com_pch.h" 00050 #endif /* USE_PCH */ 00051 #pragma hdrstop 00052 #include <math.h> 00053 #include <string.h> /* for memset() */ 00054 00055 #include "defs.h" 00056 #include "stab.h" 00057 #include "irbdata.h" 00058 #include "wn.h" 00059 #include "config_targ.h" 00060 #include "wn_simp.h" 00061 #include "wio.h" 00062 #include "targ_const.h" 00063 #include "const.h" 00064 #include "strtab.h" 00065 #include "config.h" 00066 #ifdef BACK_END 00067 #include "fb_whirl.h" 00068 #include "tracing.h" 00069 #endif /* BACK_END */ 00070 00071 #if (defined(FRONT_END_C) || defined(FRONT_END_CPLUSPLUS)) && !defined(FRONT_END_MFEF77) 00072 #include "wn_util.h" 00073 #endif /* (defined(FRONT_END_C) || defined(FRONT_END_CPLUSPLUS)) && !defined(FRONT_END_MFEF77) */ 00074 00075 #ifdef KEEP_WHIRLSTATS 00076 INT32 whirl_num_allocated=0; 00077 INT32 whirl_bytes_allocated=0; 00078 INT32 whirl_num_deallocated=0; 00079 INT32 whirl_bytes_deallocated=0; 00080 00081 void whirlstats() 00082 { 00083 fprintf(stderr,"Num allocated = %d\nbytes allocated = %d\n",whirl_num_allocated,whirl_bytes_allocated); 00084 fprintf(stderr,"Num deallocated = %d\nbytes deallocated = %d\n",whirl_num_deallocated,whirl_bytes_deallocated); 00085 } 00086 #endif 00087 00088 MEM_POOL WN_mem_pool; 00089 MEM_POOL *WN_mem_pool_ptr = &WN_mem_pool; 00090 BOOL WN_mem_pool_initialized = FALSE; 00091 00092 typedef enum { 00093 UNKNOWN_TYPE, INT_TYPE, UINT_TYPE, FLOAT_TYPE, COMPLEX_TYPE 00094 } BTYPE; 00095 00096 static struct winfo { 00097 BTYPE base_type:8; 00098 BTYPE comp_type:8; 00099 INT size:16; 00100 } WINFO [MTYPE_LAST + 1] = { 00101 UNKNOWN_TYPE, UNKNOWN_TYPE, 0, /* UNKNOWN */ 00102 UNKNOWN_TYPE, UNKNOWN_TYPE, 0, /* MTYPE_B */ 00103 INT_TYPE, UINT_TYPE, 1, /* MTYPE_I1 */ 00104 INT_TYPE, UINT_TYPE, 2, /* MTYPE_I2 */ 00105 INT_TYPE, UINT_TYPE, 4, /* MTYPE_I4 */ 00106 INT_TYPE, UINT_TYPE, 8, /* MTYPE_I8 */ 00107 UINT_TYPE, INT_TYPE, 1, /* MTYPE_U1 */ 00108 UINT_TYPE, INT_TYPE, 2, /* MTYPE_U2 */ 00109 UINT_TYPE, INT_TYPE, 4, /* MTYPE_U4 */ 00110 UINT_TYPE, INT_TYPE, 8, /* MTYPE_U8 */ 00111 FLOAT_TYPE, FLOAT_TYPE, 4, /* MTYPE_F4 */ 00112 FLOAT_TYPE, FLOAT_TYPE, 8, /* MTYPE_F8 */ 00113 UNKNOWN_TYPE, UNKNOWN_TYPE, 0, /* MTYPE_F10*/ 00114 UNKNOWN_TYPE, UNKNOWN_TYPE, 0, /* MTYPE_F16*/ 00115 UNKNOWN_TYPE, UNKNOWN_TYPE, 0, /* MTYPE_STR*/ 00116 FLOAT_TYPE, FLOAT_TYPE, 16, /* MTYPE_FQ */ 00117 UNKNOWN_TYPE, UNKNOWN_TYPE, 0, /* MTYPE_M */ 00118 COMPLEX_TYPE, COMPLEX_TYPE, 8, /* MTYPE_C4 */ 00119 COMPLEX_TYPE, COMPLEX_TYPE, 16, /* MTYPE_C8 */ 00120 COMPLEX_TYPE, COMPLEX_TYPE, 32, /* MTYPE_CQ */ 00121 UNKNOWN_TYPE, UNKNOWN_TYPE, 0, /* MTYPE_V */ 00122 INT_TYPE, UINT_TYPE, 0, /* MTYPE_BS */ 00123 UINT_TYPE, INT_TYPE, 4, /* MTYPE_A4 */ 00124 UINT_TYPE, INT_TYPE, 8 /* MTYPE_A8 */ 00125 }; 00126 00127 #define WTYPE_base_type(w) WINFO[w].base_type 00128 #define WTYPE_comp_type(w) WINFO[w].comp_type 00129 #define WTYPE_size(w) WINFO[w].size 00130 00131 #if (defined(FRONT_END_C) || defined(FRONT_END_CPLUSPLUS)) && !defined(FRONT_END_MFEF77) 00132 00133 BOOL FE_Address_Opt = TRUE; 00134 BOOL FE_Store_Opt = TRUE; 00135 BOOL FE_Cvtl_Opt = TRUE; 00136 00137 extern "C" { WN * WN_COPY_Tree ( WN * ); } 00138 00139 static UINT64 masks [] = { 0, 0xff, 0xffff, 0, 0xffffffffULL, 00140 0, 0, 0, 0xffffffffffffffffULL }; 00141 00142 00143 static WN * 00144 fe_combine_address_offset ( WN_OFFSET * offset, WN * addr ) 00145 { 00146 WN * new_addr; 00147 INT64 const_val; 00148 INT32 i; 00149 00150 if ( FE_Address_Opt == FALSE ) 00151 return addr; 00152 00153 i = -1; 00154 new_addr = addr; 00155 00156 if ( WN_operator(addr) == OPR_ADD 00157 || WN_operator(addr) == OPR_SUB ) { 00158 00159 if ( WN_operator(WN_kid0(addr)) == OPR_INTCONST ) 00160 i = 0; 00161 00162 else 00163 if ( WN_operator(WN_kid1(addr)) == OPR_INTCONST ) 00164 i = 1; 00165 } 00166 00167 if ( i >= 0 ) { 00168 00169 if ( WN_operator(addr) == OPR_ADD ) 00170 const_val = *offset + WN_const_val(WN_kid(addr,i)); 00171 00172 else 00173 const_val = *offset - WN_const_val(WN_kid(addr,i)); 00174 00175 if ( const_val >= INT32_MIN && const_val <= INT32_MAX ) { 00176 00177 *offset = const_val; 00178 new_addr = WN_COPY_Tree ( WN_kid(addr,1-i) ); 00179 } 00180 } 00181 00182 return new_addr; 00183 } /* fe_combine_address_offset */ 00184 #endif /* (defined(FRONT_END_C) || defined(FRONT_END_CPLUSPLUS)) && !defined(FRONT_END_MFEF77) */ 00185 00186 BOOL 00187 Types_Are_Compatible ( TYPE_ID ltype, WN * wn ) 00188 { 00189 TYPE_ID rtype = WN_rtype(wn); 00190 return ( ( WTYPE_base_type(ltype) == WTYPE_base_type(rtype) ) 00191 || ( WTYPE_base_type(ltype) == WTYPE_comp_type(rtype) ) ); 00192 } /* Types_Are_Compatible */ 00193 00194 00195 /*-----------------------------------------------------------------------*/ 00196 BOOL 00197 IPO_Types_Are_Compatible ( TYPE_ID ltype, TYPE_ID rtype ) 00198 { 00199 BOOL compatible; 00200 00201 #if 0 00202 /* Apparently the following is an overkill. Possibly there was a 00203 frontend bug that has been fixed. Until we can come up with a test 00204 case, we allow unsigned/signed to be compatible. 00205 */ 00206 00207 /* if the formal is of UINT and actual is INT, stid could introduce */ 00208 /* problems hence return not compatible */ 00209 if ((WTYPE_base_type(ltype) == UINT_TYPE) && 00210 (WTYPE_base_type(rtype) == INT_TYPE)) 00211 return FALSE; 00212 #endif 00213 00214 /* if the base types are the same or the base type of the stid */ 00215 /* is of comparable type and size of lhs is */ 00216 /* greater than size of rhs then return true */ 00217 compatible = (((WTYPE_base_type(ltype) == WTYPE_base_type(rtype)) 00218 || (WTYPE_base_type(ltype) == WTYPE_comp_type(rtype))) 00219 && (WTYPE_size(ltype) >= WTYPE_size(rtype))); 00220 00221 return (compatible); 00222 } /* IPO_Types_Are_Compatible */ 00223 00224 /* ---------------------------------------------------------------------- */ 00225 /* Is_Const_Parm: returns true iff for call_wn and a childIndex i, 00226 the i-th formal to the function is a const parameter 00227 eg f(const int &x), or f(const int *x) 00228 */ 00229 /* ---------------------------------------------------------------------- */ 00230 /* doesn't seem like this is used anymore */ 00231 00232 00233 00234 /* --------------------------------------------------------------------- 00235 * WN Free Lists 00236 * 00237 * Each WN_FREE_LIST is a list of WHIRL nodes of a certain size that have 00238 * been freed by WN_Delete. Note that the node address stored is the 00239 * WN_StartAddress (i.e., the address of the allocated object, which may 00240 * not be the same as the WN * returned by the creator). 00241 * 00242 * TODO: Since I have very little time to implement this, the current 00243 * implementation keeps free lists only for nodes of the two most common 00244 * sizes. We should generalize this to other sizes later. 00245 * --------------------------------------------------------------------- 00246 */ 00247 00248 /* Use a field within the WN to link to next free WN. 00249 * This lets us use WN as the representation of WN_FREE_LIST. 00250 */ 00251 typedef WN * WN_FREE_LIST; 00252 00253 /* --------------------------------------------------------------------- 00254 * BOOL WN_FREE_LIST_Empty(WN_FREE_LIST *list) 00255 * 00256 * Is <list> empty? 00257 * --------------------------------------------------------------------- 00258 */ 00259 #define WN_FREE_LIST_Empty(list) (*(list) == NULL) 00260 00261 /* 00262 * provide a way to turn off free list 00263 */ 00264 static BOOL use_free_list = TRUE; 00265 00266 void 00267 Dont_Use_WN_Free_List (void) 00268 { 00269 use_free_list = FALSE; 00270 } 00271 00272 /* --------------------------------------------------------------------- 00273 * void WN_FREE_LIST_Push(WN_FREE_LIST *list, WN *wn) 00274 * 00275 * Add <wn> (actually, WN_StartAddress(wn)) to the start of <list>. 00276 * --------------------------------------------------------------------- 00277 */ 00278 inline void WN_FREE_LIST_Push(WN_FREE_LIST *list, WN *wn) 00279 { 00280 STMT_WN *stmt_wn; 00281 stmt_wn = (STMT_WN *) WN_StartAddress(wn); 00282 WN_prev_free(stmt_wn) = (WN *)(*list); 00283 *list = (WN_FREE_LIST)stmt_wn; 00284 } 00285 00286 /* --------------------------------------------------------------------- 00287 * WN *WN_FREE_LIST_Pop(WN_FREE_LIST *list) 00288 * 00289 * Requires: WN_FREE_LIST_Empty(list) == FALSE 00290 * 00291 * Remove first item from <list> and return the item. 00292 * --------------------------------------------------------------------- 00293 */ 00294 inline WN *WN_FREE_LIST_Pop(WN_FREE_LIST *list) 00295 { 00296 STMT_WN *item = (STMT_WN *)(*list); 00297 *list = (WN_FREE_LIST)WN_prev_free(item); 00298 return (WN *)item; 00299 } 00300 00301 /* --------------------------------------------------------------------- 00302 * WN_FREE_LIST *Which_WN_FREE_LIST(INT32 size) 00303 * 00304 * Return the appropriate free list for a node of the given <size>, 00305 * or NULL if there is no appropriate list. 00306 * 00307 * See TODO in Free Lists description above for note about future work. 00308 * --------------------------------------------------------------------- 00309 */ 00310 00311 /* For now, only two lists of the common sizes. Note that freed expr 00312 * nodes with two kids will end up on the free_stmt_list, which is fine. 00313 * It's the size, not type, that's important when choosing the list. 00314 */ 00315 WN_FREE_LIST free_stmt_list, free_expr_list; 00316 00317 inline WN_FREE_LIST *Which_WN_FREE_LIST(INT32 size) 00318 { 00319 if (size == sizeof(WN)+2*sizeof(WN *)) 00320 return &free_stmt_list; 00321 else if (size == sizeof(WN)) 00322 return &free_expr_list; 00323 return NULL; 00324 } 00325 00326 00327 00328 /* --------------------------------------------------------------------- 00329 * void WN_Mem_Push(void) 00330 * 00331 * Saves the WN memory state for later restoration by WN_Mem_Pop. 00332 * 00333 * --------------------------------------------------------------------- 00334 */ 00335 00336 void WN_Mem_Push(void) 00337 { 00338 if (WN_mem_pool_ptr == &WN_mem_pool && !WN_mem_pool_initialized) { 00339 MEM_POOL_Initialize(WN_mem_pool_ptr, "WHIRL Nodes", TRUE); 00340 WN_mem_pool_initialized = TRUE; 00341 } 00342 MEM_POOL_Push(WN_mem_pool_ptr); 00343 } 00344 00345 00346 00347 /* --------------------------------------------------------------------- 00348 * void WN_Mem_Pop(void) 00349 * 00350 * Deallocates all WN nodes created since the last call to WN_Mem_Push. 00351 * 00352 * --------------------------------------------------------------------- 00353 */ 00354 00355 void WN_Mem_Pop(void) 00356 { 00357 if (WN_mem_pool_ptr == &WN_mem_pool && !WN_mem_pool_initialized) { 00358 MEM_POOL_Initialize(WN_mem_pool_ptr, "WHIRL Nodes", TRUE); 00359 WN_mem_pool_initialized = TRUE; 00360 } 00361 free_stmt_list = free_expr_list = NULL; 00362 MEM_POOL_Pop(WN_mem_pool_ptr); 00363 } 00364 00365 00366 /* --------------------------------------------------------------------- 00367 * void IPA_WN_Delete(WN_MAP_TAB *maptab, WN *wn) 00368 * 00369 * Free node <wn> and its associated maps. 00370 * --------------------------------------------------------------------- 00371 */ 00372 00373 #define MAX_CLEANUP_FNS 8 00374 static void (*delete_cleanup_fns[MAX_CLEANUP_FNS])(WN *wn); 00375 static UINT16 num_delete_cleanup_fns = 0; 00376 00377 void IPA_WN_Delete(WN_MAP_TAB *maptab, WN *wn) 00378 { 00379 UINT16 i; 00380 WN_FREE_LIST *free_list; 00381 00382 Is_True((WN_opcode(wn)),("Trying to delete WHIRL node with 0 opcode")); 00383 00384 free_list = use_free_list ? Which_WN_FREE_LIST(WN_Size(wn)) : 0; 00385 00386 00387 #ifdef KEEP_WHIRLSTATS 00388 whirl_num_deallocated++; 00389 whirl_bytes_deallocated += WN_Size(wn); 00390 #endif 00391 00392 /* Invoke cleanup functions. 00393 */ 00394 for (i = 0; i < num_delete_cleanup_fns; i++) 00395 (*delete_cleanup_fns[i])(wn); 00396 00397 /* Add node to appropriate free list (if any). 00398 */ 00399 if (free_list) 00400 WN_FREE_LIST_Push(free_list, wn); 00401 00402 /* Free maps */ 00403 WN_MAP_Add_Free_List(maptab, wn); 00404 00405 /* For better error checking, set the opcode to an invalid one */ 00406 // WN_set_opcode(wn, OPCODE_UNKNOWN); 00407 WN_set_operator (wn, OPERATOR_UNKNOWN); 00408 WN_set_rtype (wn, MTYPE_UNKNOWN); 00409 WN_set_desc (wn, MTYPE_UNKNOWN); 00410 } 00411 00412 00413 /* --------------------------------------------------------------------- 00414 * void IPA_WN_DELETE_Tree(WN_MAP_TAB *maptab, WN *tree) 00415 * 00416 * Free node entire <tree> and its associated maps. 00417 * --------------------------------------------------------------------- 00418 */ 00419 00420 void IPA_WN_DELETE_Tree(WN_MAP_TAB *maptab, WN *tree) 00421 { 00422 WN *node; 00423 INT i; 00424 00425 if (tree) { 00426 if (WN_opcode(tree) == OPC_BLOCK) { 00427 node = WN_first(tree); 00428 while (node != NULL) { 00429 WN *next = WN_next(node); 00430 IPA_WN_DELETE_Tree (maptab, node); 00431 node = next; 00432 } 00433 } else 00434 for (i = 0; i < WN_kid_count(tree); i++) 00435 IPA_WN_DELETE_Tree(maptab, WN_kid(tree, i)); 00436 00437 IPA_WN_Delete(maptab, tree); 00438 } 00439 } 00440 00441 00442 /* --------------------------------------------------------------------- 00443 * void WN_Register_Delete_Cleanup_Function(void (*cleanup_fn)(WN *wn)) 00444 * 00445 * See "wn.h" for interface description. 00446 * --------------------------------------------------------------------- 00447 */ 00448 00449 void WN_Register_Delete_Cleanup_Function(void (*cleanup_fn)(WN *wn)) 00450 { 00451 UINT16 i; 00452 for (i=0; i < num_delete_cleanup_fns; i++) 00453 if (delete_cleanup_fns[i] == cleanup_fn) 00454 return; 00455 FmtAssert(num_delete_cleanup_fns < MAX_CLEANUP_FNS, 00456 ("attempting to register too many WN_Delete cleanup functions")); 00457 delete_cleanup_fns[num_delete_cleanup_fns++] = cleanup_fn; 00458 } 00459 00460 00461 /* --------------------------------------------------------------------- 00462 * void WN_Remove_Delete_Cleanup_Function(void (*cleanup_fn)(WN *wn)) 00463 * 00464 * See "wn.h" for interface description. 00465 * --------------------------------------------------------------------- 00466 */ 00467 00468 void WN_Remove_Delete_Cleanup_Function(void (*cleanup_fn)(WN *wn)) 00469 { 00470 UINT16 i; 00471 00472 for (i = 0; i < num_delete_cleanup_fns; i++) 00473 if (delete_cleanup_fns[i] == cleanup_fn) 00474 break; 00475 if (i >= num_delete_cleanup_fns) 00476 return; 00477 --num_delete_cleanup_fns; 00478 for (; i < num_delete_cleanup_fns; i++) 00479 delete_cleanup_fns[i] = delete_cleanup_fns[i+1]; 00480 } 00481 00482 00483 /* --------------------------------------------------------------------- 00484 * WN_MAP_ID New_Map_Id( void ) 00485 * 00486 * Return the map_id for a new WN. 00487 * --------------------------------------------------------------------- 00488 */ 00489 #define New_Map_Id() ((WN_MAP_ID) (-1)) 00490 00491 /* --------------------------------------------------------------------- 00492 * WN *WN_Create(OPERATOR opr, TYPE_ID rtype, TYPE_ID desc, mINT16 kid_count) 00493 * 00494 * Core create routine. Return a new <opr, rtype, desc> node with <kid_count> 00495 * kids. <kid_count> must be consistent with <opcode>. 00496 * --------------------------------------------------------------------- 00497 */ 00498 00499 WN * 00500 WN_Create (OPERATOR opr, TYPE_ID rtype, TYPE_ID desc, mINT16 kid_count) 00501 { 00502 OPCODE opcode = OPCODE_make_op (opr, rtype, desc); 00503 INT16 next_prev_ptrs = (OPCODE_has_next_prev(opcode) ? 1 : 0); 00504 INT16 size = (sizeof(WN) + 00505 (sizeof(WN *) * (max(0,kid_count-2))) + 00506 next_prev_ptrs * (sizeof(mUINT64) + (2 * sizeof(WN *)))); 00507 WN_FREE_LIST *free_list; 00508 WN *wn; 00509 00510 free_list = use_free_list ? Which_WN_FREE_LIST(size) : 0; 00511 00512 #ifdef KEEP_WHIRLSTATS 00513 whirl_num_allocated++; 00514 whirl_bytes_allocated += size; 00515 #endif 00516 00517 Is_True(((OPCODE_nkids(opcode) == kid_count) || 00518 (OPCODE_nkids(opcode) == -1)), 00519 ("Illegal number of kids for WN_Create")); 00520 00521 /* Find the memory. First try a free list, then go to the MEM_POOL. 00522 * Note: For safety, we use a memset'd MEM_POOL and memset new nodes 00523 * popped from a free list, but clients should not be relying 00524 * on uninitialized fields being zeroed. 00525 */ 00526 if (free_list && !WN_FREE_LIST_Empty(free_list)) { 00527 wn = WN_FREE_LIST_Pop(free_list); 00528 memset(wn, '\0', size); 00529 } else { 00530 if (WN_mem_pool_ptr == &WN_mem_pool && !WN_mem_pool_initialized) { 00531 MEM_POOL_Initialize(WN_mem_pool_ptr, "WHIRL Nodes", TRUE); 00532 MEM_POOL_Push(WN_mem_pool_ptr); 00533 WN_mem_pool_initialized = TRUE; 00534 } 00535 wn = (WN *)MEM_POOL_Alloc(WN_mem_pool_ptr, size); 00536 memset(wn, '\0', size); 00537 } 00538 00539 /* Some nodes have next and previous pointers grow off the bottom. 00540 */ 00541 if (next_prev_ptrs) { 00542 STMT_WN *stmt_wn; 00543 stmt_wn = (STMT_WN *)wn; 00544 wn = (WN *)&(WN_real_fields(stmt_wn)); 00545 } 00546 00547 /* Finish initialization. 00548 */ 00549 WN_set_operator(wn, opr); 00550 WN_set_rtype(wn, rtype); 00551 WN_set_desc(wn, desc); 00552 WN_set_kid_count(wn, kid_count); 00553 WN_map_id(wn) = New_Map_Id(); 00554 00555 return wn; 00556 } 00557 00558 WN * 00559 WN_Create_Generic (OPERATOR opr, TYPE_ID rtype, TYPE_ID desc, 00560 mINT16 kid_count, WN *next, WN *prev, 00561 ST_IDX st,INT32 label_number, INT32 num_entries, 00562 TY_IDX ty, TY_IDX load_addr_ty, WN_OFFSET offset, 00563 INT16 cvtl_bits, INT32 /* num_dim */, 00564 WN_ESIZE element_size, INT64 const_value, UINT32 flag, 00565 INTRINSIC intrinsic) 00566 { 00567 OPCODE opcode = OPCODE_make_op (opr, rtype, desc); 00568 WN *wn; 00569 00570 00571 wn = WN_Create(opcode,kid_count); 00572 if (OPCODE_has_next_prev(opcode)) { 00573 WN_next(wn) = next; 00574 WN_prev(wn) = prev; 00575 } 00576 if (OPCODE_has_sym(opcode)) { 00577 WN_st_idx(wn) = st; 00578 } 00579 if (OPCODE_has_label(opcode)) { 00580 WN_label_number(wn) = label_number; 00581 } 00582 if (OPCODE_has_num_entries(opcode)) { 00583 WN_num_entries(wn) = num_entries; 00584 } 00585 if (OPCODE_has_1ty(opcode)) { 00586 WN_set_ty(wn,ty); 00587 } 00588 if (OPCODE_has_2ty(opcode)) { 00589 WN_set_ty(wn,ty); 00590 WN_set_load_addr_ty(wn,load_addr_ty); 00591 } 00592 if (OPCODE_has_offset(opcode)) { 00593 WN_offset(wn) = offset; 00594 } 00595 if (OPCODE_has_bits(opcode)) { 00596 WN_cvtl_bits(wn) = cvtl_bits; 00597 } 00598 /* Num_dim is now just a read-only quantity */ 00599 #if 0 00600 if (OPCODE_has_ndim(opcode)) { 00601 WN_num_dim(wn) = num_dim; 00602 } 00603 #endif 00604 if (OPCODE_has_esize(opcode)) { 00605 WN_element_size(wn) = element_size; 00606 } 00607 if (OPCODE_has_value(opcode)) { 00608 WN_const_val(wn) = const_value; 00609 } 00610 if (OPCODE_has_flags(opcode)) { 00611 WN_set_flag(wn,flag); 00612 } 00613 if (OPCODE_has_inumber(opcode)) { 00614 WN_intrinsic(wn) = intrinsic; 00615 } 00616 return wn; 00617 } 00618 00619 /* ignore children and next-previous pointers, are the two nodes 00620 * equivalent 00621 */ 00622 BOOL WN_Equiv(WN *wn1, WN *wn2) 00623 { 00624 OPCODE opcode; 00625 00626 opcode = WN_opcode(wn1); 00627 if (opcode != WN_opcode(wn2)) return(FALSE); 00628 if (opcode == OPC_BLOCK) return(TRUE); 00629 if (WN_kid_count(wn1) != WN_kid_count(wn2)) return(FALSE); 00630 00631 if (OPCODE_has_sym(opcode)) { 00632 if (WN_st_idx(wn1) != WN_st_idx(wn2)) return(FALSE); 00633 } 00634 if (OPCODE_has_label(opcode)) { 00635 if (WN_label_number(wn1) != WN_label_number(wn2)) return(FALSE); 00636 } 00637 if (OPCODE_has_num_entries(opcode)) { 00638 if (WN_num_entries(wn1) != WN_num_entries(wn2)) return(FALSE); 00639 } 00640 if (OPCODE_has_1ty(opcode)) { 00641 if (WN_ty(wn1) != WN_ty(wn2)) return(FALSE); 00642 } 00643 if (OPCODE_has_2ty(opcode)) { 00644 if (WN_ty(wn1) != WN_ty(wn2)) return(FALSE); 00645 if (WN_load_addr_ty(wn1) != WN_load_addr_ty(wn2)) return(FALSE); 00646 } 00647 if (OPCODE_has_offset(opcode)) { 00648 if (WN_offset(wn1) != WN_offset(wn2)) return(FALSE); 00649 } 00650 if (OPCODE_has_bits(opcode)) { 00651 if (WN_cvtl_bits(wn1) != WN_cvtl_bits(wn2)) return(FALSE); 00652 } 00653 if (OPCODE_has_ndim(opcode)) { 00654 if (WN_num_dim(wn1) != WN_num_dim(wn2)) return(FALSE); 00655 } 00656 if (OPCODE_has_esize(opcode)) { 00657 if (WN_element_size(wn1) != WN_element_size(wn2)) return(FALSE); 00658 } 00659 if (OPCODE_has_value(opcode)) { 00660 if (WN_const_val(wn1) != WN_const_val(wn2)) return(FALSE); 00661 } 00662 if (OPCODE_has_flags(opcode)) { 00663 if (WN_flag(wn1) != WN_flag(wn2)) return(FALSE); 00664 } 00665 if (OPCODE_has_inumber(opcode)) { 00666 if (WN_intrinsic(wn1) != WN_intrinsic(wn2)) return(FALSE); 00667 } 00668 00669 return(TRUE); 00670 } 00671 00672 00673 /* 00674 * Create hierarchical control flow nodes 00675 * 00676 */ 00677 00678 WN *WN_CreateBlock(void) 00679 { 00680 WN *wn; 00681 00682 wn = WN_Create(OPC_BLOCK,0); 00683 WN_first(wn) = WN_last(wn) = NULL; 00684 return(wn); 00685 } 00686 00687 WN *WN_CreateDO(WN *index, WN *start, WN *end, WN *step, WN *body, WN *loop_info) 00688 { 00689 WN *wn; 00690 INT nkids = 5; 00691 if (loop_info != NULL) nkids++; 00692 00693 Is_True(OPCODE_is_stmt(WN_opcode(start)),("Bad start in WN_CreateDO")); 00694 Is_True(OPCODE_is_stmt(WN_opcode(step)),("Bad step in WN_CreateDO")); 00695 Is_True(loop_info == NULL || WN_opcode(loop_info) == OPC_LOOP_INFO, 00696 ("Bad loop_info in WN_CreateDO")); 00697 /* TODO: can't find Boolean type 00698 Is_True(WN_rtype(end)==Boolean_type, 00699 ("Bad end in WN_CreateDO")); 00700 */ 00701 Is_True(WN_opcode(body) == OPC_BLOCK,("Bad body in WN_CreateDO")); 00702 00703 wn = WN_Create(OPC_DO_LOOP,nkids); 00704 WN_index(wn) = index; 00705 WN_start(wn) = start; 00706 WN_end(wn) = end; 00707 WN_step(wn) = step; 00708 WN_do_body(wn) = body; 00709 if (loop_info) WN_set_do_loop_info(wn, loop_info); 00710 00711 return(wn); 00712 } 00713 00714 WN *WN_CreateDoWhile(WN *test, WN *body) 00715 { 00716 WN *wn; 00717 00718 Is_True(WN_opcode(body) == OPC_BLOCK, ("Bad body in WN_CreateDoWhile")); 00719 /* TODO: can't find Boolean type 00720 Is_True(WN_rtype(test)==Boolean_type, 00721 ("Bad test in WN_CreateDoWhile")); 00722 */ 00723 wn = WN_Create(OPC_DO_WHILE,2); 00724 WN_while_test(wn) = test; 00725 WN_while_body(wn) = body; 00726 00727 return(wn); 00728 } 00729 00730 WN *WN_CreateWhileDo(WN *test, WN *body) 00731 { 00732 WN *wn; 00733 00734 Is_True(WN_opcode(body) == OPC_BLOCK, ("Bad body in WN_CreateWhileDo")); 00735 /* TODO: can't find Boolean type 00736 Is_True(WN_rtype(test)==Boolean_type, 00737 ("Bad test in WN_CreateWhileDo")); 00738 */ 00739 wn = WN_Create(OPC_WHILE_DO,2); 00740 WN_while_test(wn) = test; 00741 WN_while_body(wn) = body; 00742 00743 return(wn); 00744 } 00745 00746 WN *WN_CreateIf(WN *test, WN *if_then, WN *if_else) 00747 { 00748 WN *wn; 00749 00750 Is_True(WN_opcode(if_then) == OPC_BLOCK, ("Bad then in WN_CreateIf")); 00751 Is_True(WN_opcode(if_else) == OPC_BLOCK, ("Bad else in WN_CreateIf")); 00752 /* TODO: can't find Boolean type 00753 Is_True(WN_rtype(test)==Boolean_type, 00754 ("Bad test in WN_CreateIf")); 00755 */ 00756 wn = WN_Create(OPC_IF,3); 00757 WN_if_test(wn) = test; 00758 WN_then(wn) = if_then; 00759 WN_else(wn) = if_else; 00760 00761 WN_Reset_If_Guard(wn); 00762 return(wn); 00763 } 00764 00765 /*============================================================================ 00766 REGION handling routines 00767 ============================================================================*/ 00768 00769 /* check if a region element (statement list, pragma list, or exit list) has 00770 a block surrounding it, if not create one. Some lists may be NULL, in that 00771 case return an empty block */ 00772 static WN *WN_block_element(WN *element) 00773 { 00774 if (element == NULL || WN_opcode(element) != OPC_BLOCK) { 00775 WN *block = WN_CreateBlock(); 00776 if (element != NULL) { 00777 WN_first(block) = element; 00778 WN_last (block) = element; 00779 WN_prev(element) = NULL; 00780 WN_next(element) = NULL; 00781 } 00782 return block; 00783 } else 00784 return element; 00785 } 00786 00787 static INT32 last_region_id = 0; 00788 00789 extern "C" INT32 00790 New_Region_Id(void) 00791 { 00792 return ++last_region_id; 00793 } 00794 extern "C" INT32 00795 Last_Region_Id(void) 00796 { 00797 return last_region_id; 00798 } 00799 00800 /* set maximum region id seen so far; 00801 * special case 0 to mean reset region ids to 0 */ 00802 extern void 00803 Set_Max_Region_Id (INT id) 00804 { 00805 if (id == 0) 00806 last_region_id = 0; 00807 else 00808 last_region_id = MAX(last_region_id,id); 00809 } 00810 00811 /* ======================================================================= 00812 * 00813 * WN_CreateRegion 00814 * 00815 * body must be an SCF node. 00816 * If body is not a block, 00817 * Create a REGION whose kid is a BLOCK which contains body. 00818 * If body is a BLOCK 00819 * Create a REGION whose kid is body. 00820 * Copy the linenum from body to the result. 00821 * 00822 * OPC_REGION 00823 * / | \ 00824 * OPC_BLOCK OPC_BLOCK OPC_BLOCK 00825 * exit list pragma list statement list 00826 * 00827 * region_id: pass in -1 for WN_CreateRegion to assign an unique region id, 00828 * otherwise specify a valid region_id (0-N) for the region. 00829 * 00830 * ======================================================================= 00831 */ 00832 WN * 00833 WN_CreateRegion (REGION_KIND kind, WN *body, WN *pragmas, WN *exits, 00834 INT region_id, INITO_IDX ereg_supp) 00835 { 00836 WN *wn; 00837 00838 Is_True( OPCODE_is_scf(WN_opcode(body)) , ("Bad body in WN_CreateRegion")); 00839 wn = WN_Create(OPC_REGION,3); // 3 kids: exits, pragmas, statements 00840 WN_Set_Linenum(wn,WN_Get_Linenum(body)); 00841 00842 WN_set_region_kind(wn, kind); 00843 WN_set_region_id(wn, (region_id == -1) ? New_Region_Id() : region_id); 00844 WN_region_body(wn) = WN_block_element(body); 00845 WN_region_pragmas(wn) = WN_block_element(pragmas); 00846 WN_region_exits(wn) = WN_block_element(exits); 00847 WN_ereg_supp(wn) = ereg_supp; 00848 00849 Set_PU_has_region (Get_Current_PU ()); 00850 00851 return(wn); 00852 } 00853 00854 WN *WN_CreateRegionExit (INT32 label_number) 00855 { 00856 WN *wn; 00857 00858 wn = WN_Create(OPC_REGION_EXIT,0); 00859 WN_label_number(wn) = label_number; 00860 00861 return(wn); 00862 } 00863 00864 // nkids is the number of function arguments 00865 WN * 00866 WN_CreateEntry (INT16 nkids, ST_IDX name, WN *body, WN *pragmas, WN *varrefs) 00867 { 00868 WN *wn; 00869 wn = WN_Create (OPC_FUNC_ENTRY, nkids + 3); 00870 WN_entry_name(wn) = name; 00871 WN_func_body(wn) = body; 00872 WN_func_pragmas(wn) = WN_block_element(pragmas); 00873 WN_func_varrefs(wn) = WN_block_element(varrefs); 00874 return wn; 00875 } 00876 00877 /* 00878 * Create statement nodes 00879 * 00880 */ 00881 00882 // no st anymore in goto 00883 WN *WN_CreateGoto(INT32 label_number) 00884 { 00885 WN *wn; 00886 00887 wn = WN_Create(OPC_GOTO,0); 00888 WN_label_number(wn) = label_number; 00889 00890 return(wn); 00891 } 00892 00893 WN *WN_CreateGotoOuterBlock (INT32 label_number, SYMTAB_IDX label_level) 00894 { 00895 WN * wn; 00896 wn = WN_Create(OPC_GOTO_OUTER_BLOCK, 0); 00897 WN_label_number(wn) = label_number; 00898 WN_label_level(wn) = label_level; 00899 00900 return wn; 00901 } /* WN_CreateGotoOuterBlock */ 00902 00903 WN *WN_CreateAgoto(WN *addr) 00904 { 00905 WN *wn; 00906 00907 Is_True(WN_rtype(addr)==Pointer_type, 00908 ("Bad addr in WN_CreateAgoto")); 00909 wn = WN_Create(OPC_AGOTO,1); 00910 WN_kid0(wn) = addr; 00911 00912 return(wn); 00913 } 00914 00915 WN *WN_CreateAltentry(ST_IDX entry) 00916 { 00917 WN *wn; 00918 00919 wn = WN_Create(OPC_ALTENTRY,0); 00920 WN_st_idx(wn) = entry; 00921 00922 return(wn); 00923 } 00924 00925 WN *WN_CreateTruebr(INT32 label_number, WN *exp) 00926 { 00927 WN *wn; 00928 00929 Is_True(OPCODE_is_expression(WN_opcode(exp)), 00930 ("Bad exp in WN_CreateTruebr")); 00931 wn = WN_Create(OPC_TRUEBR,1); 00932 WN_kid0(wn) = exp; 00933 WN_label_number(wn) = label_number; 00934 00935 return(wn); 00936 } 00937 00938 WN *WN_CreateFalsebr(INT32 label_number, WN *exp) 00939 { 00940 WN *wn; 00941 00942 Is_True(OPCODE_is_expression(WN_opcode(exp)), 00943 ("Bad exp in WN_CreateFalsebr")); 00944 wn = WN_Create(OPC_FALSEBR,1); 00945 WN_kid0(wn) = exp; 00946 WN_label_number(wn) = label_number; 00947 00948 return(wn); 00949 } 00950 00951 /* a return */ 00952 WN *WN_CreateReturn(void) 00953 { 00954 WN *wn; 00955 00956 wn = WN_Create(OPC_RETURN,0); 00957 00958 return(wn); 00959 } 00960 00961 WN *WN_CreateReturn_Val (OPERATOR opr, TYPE_ID rtype, TYPE_ID desc, WN *val) 00962 { 00963 WN *wn; 00964 00965 wn = WN_Create (opr, rtype, desc, 1); 00966 WN_kid0(wn) = val; 00967 00968 return(wn); 00969 } 00970 00971 WN * 00972 WN_CreateLabel ( 00973 INT32 label_number, UINT32 label_flag, WN *loop_info) 00974 { 00975 WN *wn; 00976 INT nkids = 0; 00977 if (loop_info != NULL) nkids++; 00978 Is_True(loop_info == NULL || WN_opcode(loop_info) == OPC_LOOP_INFO, 00979 ("Bad loop_info in WN_CreateDO")); 00980 00981 wn = WN_Create(OPC_LABEL, nkids); 00982 WN_label_number(wn) = label_number; 00983 WN_label_flag(wn) = label_flag; 00984 if ( loop_info ) 00985 WN_set_label_loop_info(wn, loop_info); 00986 00987 return(wn); 00988 } 00989 00990 WN *WN_CreateCompgoto(INT32 num_entries, WN *value, 00991 WN *block, WN *deflt, INT32 last_label) 00992 { 00993 WN *wn; 00994 00995 Is_True(OPCODE_is_expression(WN_opcode(value)), 00996 ("Bad value in WN_CreateCompgoto")); 00997 Is_True(WN_opcode(block) == OPC_BLOCK, 00998 ("Bad block in WN_CreateCompgoto")); 00999 if (deflt) Is_True(WN_opcode(deflt) == OPC_GOTO, 01000 ("Bad deflt in WN_CreateCompgoto")); 01001 if (deflt) { 01002 wn = WN_Create(OPC_COMPGOTO,3); 01003 } else { 01004 wn = WN_Create(OPC_COMPGOTO,2); 01005 } 01006 WN_kid0(wn) = value; 01007 WN_kid(wn,1) = block; 01008 if (deflt) WN_kid(wn,2) = deflt; 01009 WN_num_entries(wn) = num_entries; 01010 WN_last_label(wn) = last_label; 01011 01012 return(wn); 01013 } 01014 01015 WN *WN_CreateSwitch(INT32 num_entries, WN *value, 01016 WN *block, WN *deflt, INT32 last_label) 01017 { 01018 WN *wn; 01019 01020 Is_True(OPCODE_is_expression(WN_opcode(value)), 01021 ("Bad value in WN_CreateSwitch")); 01022 Is_True(WN_opcode(block) == OPC_BLOCK, 01023 ("Bad block in WN_CreateSwitch")); 01024 if (deflt) Is_True(WN_opcode(deflt) == OPC_GOTO, 01025 ("Bad deflt in WN_CreateSwitch")); 01026 if (deflt) { 01027 wn = WN_Create(OPC_SWITCH,3); 01028 } else { 01029 wn = WN_Create(OPC_SWITCH,2); 01030 } 01031 WN_switch_test(wn) = value; 01032 WN_switch_table(wn) = block; 01033 if (deflt) WN_switch_default(wn) = deflt; 01034 WN_num_entries(wn) = num_entries; 01035 WN_last_label(wn) = last_label; 01036 01037 #ifdef FRONT_END 01038 Set_PU_has_very_high_whirl (Get_Current_PU ()); 01039 #endif /* FRONT_END */ 01040 01041 return(wn); 01042 } 01043 01044 WN *WN_CreateCasegoto (INT64 case_value, INT32 case_label) 01045 { 01046 WN *wn; 01047 wn = WN_Create(OPC_CASEGOTO,0); 01048 WN_const_val(wn) = case_value; 01049 WN_label_number(wn) = case_label; 01050 return wn; 01051 } 01052 01053 WN *WN_CreateXgoto(INT32 num_entries, WN *value, WN *block, ST_IDX st) 01054 { 01055 WN *wn; 01056 01057 Is_True(OPCODE_is_expression(WN_opcode(value)), 01058 ("Bad value in WN_CreateXgoto")); 01059 Is_True(WN_opcode(block) == OPC_BLOCK, 01060 ("Bad block in WN_CreateXgoto")); 01061 wn = WN_Create(OPC_XGOTO,2); 01062 WN_kid0(wn) = value; 01063 WN_kid(wn,1) = block; 01064 WN_st_idx(wn) = st; 01065 WN_num_entries(wn) = num_entries; 01066 01067 return(wn); 01068 } 01069 01070 WN * 01071 WN_CreateIstore (OPERATOR opr, TYPE_ID rtype, TYPE_ID desc, 01072 WN_OFFSET offset, TY_IDX ty, WN *value, WN *addr, 01073 UINT field_id) 01074 { 01075 OPCODE opc = OPCODE_make_op (opr, rtype, desc); 01076 WN *wn; 01077 Is_True(MTYPE_is_pointer(WN_rtype(addr)) || 01078 WN_rtype(addr)==MTYPE_U8 || 01079 WN_rtype(addr)==MTYPE_U4 || 01080 WN_rtype(addr)==MTYPE_I8 || 01081 WN_rtype(addr)==MTYPE_I4, 01082 ("Bad addr in WN_CreateIstore")); 01083 Is_True(OPCODE_is_expression(WN_opcode(value)), 01084 ("Bad value in WN_CreateIstore")); 01085 Is_True(Types_Are_Compatible(OPCODE_desc(opc),value), 01086 ("Bad return type in WN_CreateIstore")); 01087 Is_True(opr == OPR_ISTORE || opr == OPR_ISTBITS, 01088 ("Bad opcode in WN_CreateIstore")); 01089 01090 #if (defined(FRONT_END_C) || defined(FRONT_END_CPLUSPLUS)) && !defined(FRONT_END_MFEF77) 01091 01092 addr = fe_combine_address_offset ( &offset, addr ); 01093 01094 UINT64 ty_size; 01095 if (field_id == 0) { 01096 ty_size = TY_size(TY_pointed(ty)); 01097 } 01098 else { 01099 UINT tmp = 0; 01100 ty_size = TY_size(FLD_type(FLD_get_to_field(TY_pointed(ty),field_id,tmp))); 01101 } 01102 01103 if ( FE_Cvtl_Opt ) { 01104 01105 OPCODE value_opc; 01106 01107 value_opc = WN_opcode(value); 01108 01109 if ( ( ( WN_operator(value) == OPR_CVTL 01110 || WN_operator(value) == OPR_CVT ) 01111 && WN_cvtl_bits(value) == ty_size * 8 ) 01112 || ( ( value_opc == OPC_I4I8CVT 01113 || value_opc == OPC_I4U8CVT 01114 || value_opc == OPC_U4I8CVT 01115 || value_opc == OPC_U4U8CVT ) 01116 && ty_size < 8 ) ) 01117 value = WN_kid0(value); 01118 } 01119 01120 if ( FE_Store_Opt 01121 && WN_operator(value) == OPR_BAND ) { 01122 01123 UINT64 mask; 01124 WN * kid0; 01125 WN * kid1; 01126 01127 mask = masks [ty_size]; 01128 kid0 = WN_kid0(value); 01129 kid1 = WN_kid1(value); 01130 01131 if ( WN_operator(kid0) == OPR_INTCONST 01132 && ( ( WN_const_val(kid0) & mask ) == mask ) ) 01133 value = kid1; 01134 01135 else 01136 if ( WN_operator(kid1) == OPR_INTCONST 01137 && ( ( WN_const_val(kid1) & mask ) == mask ) ) 01138 value = kid0; 01139 } 01140 #endif /* (defined(FRONT_END_C) || defined(FRONT_END_CPLUSPLUS)) && !defined(FRONT_END_MFEF77) */ 01141 01142 wn = WN_SimplifyIstore(opc,offset,ty,field_id,value,addr); 01143 01144 if (!wn) { 01145 wn = WN_Create(opc,2); 01146 WN_kid0(wn) = value; 01147 WN_kid1(wn) = addr; 01148 WN_store_offset(wn) = offset; 01149 WN_set_ty(wn,ty); 01150 WN_set_field_id(wn, field_id); 01151 } 01152 else { 01153 /* Parent pointer (if it exists) for returned node must be NULL */ 01154 if (WN_SimpParentMap != WN_MAP_UNDEFINED) { 01155 WN_MAP_Set(WN_SimpParentMap, wn, NULL); 01156 } 01157 } 01158 01159 return(wn); 01160 } 01161 01162 01163 WN * 01164 WN_CreatePstore (OPERATOR opr, TYPE_ID rtype, TYPE_ID desc, 01165 WN_OFFSET offset, TY_IDX ty, WN *value, WN *addr, 01166 UINT field_id) 01167 { 01168 OPCODE opc = OPCODE_make_op (opr, rtype, desc); 01169 WN *wn; 01170 Is_True(MTYPE_is_pointer(WN_rtype(addr)) || 01171 WN_rtype(addr)==MTYPE_U8 || 01172 WN_rtype(addr)==MTYPE_U4 || 01173 WN_rtype(addr)==MTYPE_I8 || 01174 WN_rtype(addr)==MTYPE_I4, 01175 ("Bad addr in WN_CreatePstore")); 01176 Is_True(OPCODE_is_expression(WN_opcode(value)), 01177 ("Bad value in WN_CreatePstore")); 01178 Is_True(Types_Are_Compatible(OPCODE_desc(opc),value), 01179 ("Bad return type in WN_CreatePstore")); 01180 Is_True(opr == OPR_ISTORE ||opr == OPR_PSTORE|| opr == OPR_ISTBITS, 01181 ("Bad opcode in WN_CreatePstore")); 01182 01183 #if (defined(FRONT_END_C) || defined(FRONT_END_CPLUSPLUS)) && !defined(FRONT_END_MFEF77) 01184 01185 addr = fe_combine_address_offset ( &offset, addr ); 01186 01187 UINT64 ty_size; 01188 if (field_id == 0) { 01189 ty_size = TY_size(TY_pointed(ty)); 01190 } 01191 else { 01192 UINT tmp = 0; 01193 ty_size = TY_size(FLD_type(FLD_get_to_field(TY_pointed(ty),field_id,tmp))); 01194 } 01195 01196 if ( FE_Cvtl_Opt ) { 01197 01198 OPCODE value_opc; 01199 01200 value_opc = WN_opcode(value); 01201 01202 if ( ( ( WN_operator(value) == OPR_CVTL 01203 || WN_operator(value) == OPR_CVT ) 01204 && WN_cvtl_bits(value) == ty_size * 8 ) 01205 || ( ( value_opc == OPC_I4I8CVT 01206 || value_opc == OPC_I4U8CVT 01207 || value_opc == OPC_U4I8CVT 01208 || value_opc == OPC_U4U8CVT ) 01209 && ty_size < 8 ) ) 01210 value = WN_kid0(value); 01211 } 01212 if ( FE_Store_Opt 01213 && WN_operator(value) == OPR_BAND ) { 01214 01215 UINT64 mask; 01216 WN * kid0; 01217 WN * kid1; 01218 01219 mask = masks [ty_size]; 01220 kid0 = WN_kid0(value); 01221 kid1 = WN_kid1(value); 01222 01223 if ( WN_operator(kid0) == OPR_INTCONST 01224 && ( ( WN_const_val(kid0) & mask ) == mask ) ) 01225 value = kid1; 01226 01227 else 01228 if ( WN_operator(kid1) == OPR_INTCONST 01229 && ( ( WN_const_val(kid1) & mask ) == mask ) ) 01230 value = kid0; 01231 } 01232 #endif /* (defined(FRONT_END_C) || defined(FRONT_END_CPLUSPLUS)) && !defined(FRONT_EN 01233 D_MFEF77) */ 01234 01235 wn = WN_SimplifyPstore(opc,offset,ty,field_id,value,addr); 01236 01237 if (!wn) { 01238 wn = WN_Create(opc,2); 01239 WN_kid0(wn) = value; 01240 WN_kid1(wn) = addr; 01241 WN_store_offset(wn) = offset; 01242 WN_set_ty(wn,ty); 01243 WN_set_field_id(wn, field_id); 01244 } 01245 else { 01246 /* Parent pointer (if it exists) for returned node must be NULL */ 01247 if (WN_SimpParentMap) WN_MAP_Set(WN_SimpParentMap, wn, NULL); 01248 } 01249 01250 return(wn); 01251 } 01252 01253 01254 WN * 01255 WN_CreateIstorex (OPERATOR opr, TYPE_ID rtype, TYPE_ID desc, 01256 TY_IDX ty, WN *value, WN *addr1, WN *addr2) 01257 { 01258 OPCODE opc = OPCODE_make_op (opr, rtype, desc); 01259 WN *wn; 01260 01261 Is_True(OPCODE_operator(opc) == OPR_ISTOREX, 01262 ("Bad opcode in WN_CreateIstorex")); 01263 Is_True(OPCODE_is_expression(WN_opcode(value)), 01264 ("Bad value in WN_CreateIstorex")); 01265 Is_True(WN_operator_is(addr1, OPR_LDID), 01266 ("Bad address 1 in WN_CreateIstorex")); 01267 Is_True(WN_operator_is(addr2, OPR_LDID), 01268 ("Bad address 2 in WN_CreateIstorex")); 01269 wn = WN_Create (opr, rtype, desc, 3); 01270 WN_store_offset(wn) = 0; 01271 WN_kid0(wn) = value; 01272 WN_kid1(wn) = addr1; 01273 WN_kid(wn,2) = addr2; 01274 WN_set_ty(wn,ty); 01275 return(wn); 01276 } 01277 01278 WN *WN_CreatePrefetchx(UINT32 flag, WN *addr1, WN *addr2) 01279 { 01280 WN *wn; 01281 01282 Is_True(WN_operator_is(addr1, OPR_LDID), 01283 ("Bad address 1 in WN_CreatePrefetchx")); 01284 Is_True(WN_operator_is(addr2, OPR_LDID), 01285 ("Bad address 2 in WN_CreatePrefetchx")); 01286 wn = WN_Create(OPC_PREFETCHX,2); 01287 WN_kid0(wn) = addr1; 01288 WN_kid1(wn) = addr2; 01289 WN_set_flag(wn,flag); 01290 return(wn); 01291 } 01292 01293 WN *WN_CreateMstore(WN_OFFSET offset, TY_IDX ty, 01294 WN *value, WN *addr, WN *num_bytes) 01295 { 01296 WN *wn; 01297 01298 Is_True(MTYPE_is_pointer(WN_rtype(addr)) || 01299 WN_rtype(addr)==MTYPE_U8 || 01300 WN_rtype(addr)==MTYPE_U4 || 01301 WN_rtype(addr)==MTYPE_I8 || 01302 WN_rtype(addr)==MTYPE_I4, 01303 ("Bad addr in WN_CreateMstore")); 01304 Is_True(OPCODE_is_expression(WN_opcode(value)), 01305 ("Bad value in WN_CreateMstore")); 01306 Is_True(OPCODE_is_expression(WN_opcode(num_bytes)), 01307 ("Bad num_bytes in WN_CreateMstore")); 01308 01309 #if (defined(FRONT_END_C) || defined(FRONT_END_CPLUSPLUS)) && !defined(FRONT_END_MFEF77) 01310 01311 addr = fe_combine_address_offset ( &offset, addr ); 01312 01313 #endif /* (defined(FRONT_END_C) || defined(FRONT_END_CPLUSPLUS)) && !defined(FRONT_END_MFEF77) */ 01314 01315 wn = WN_Create(OPC_MSTORE,3); 01316 WN_kid0(wn) = value; 01317 WN_kid1(wn) = addr; 01318 WN_kid(wn,2) = num_bytes; 01319 WN_store_offset(wn) = offset; 01320 WN_set_ty(wn,ty); 01321 01322 #ifdef FRONT_END 01323 Set_PU_has_very_high_whirl (Get_Current_PU ()); 01324 #endif /* FRONT_END */ 01325 return(wn); 01326 } 01327 01328 /* Create a STID, note this needs the opcode since there are many */ 01329 /* opcodes with the OPR_STID operator */ 01330 WN * 01331 WN_CreateStid (OPERATOR opr, TYPE_ID rtype, TYPE_ID desc, 01332 WN_OFFSET offset, ST* st, TY_IDX ty, WN *value, UINT field_id) 01333 { 01334 OPCODE opc = OPCODE_make_op (opr, rtype, desc); 01335 WN *wn; 01336 ST_IDX st_idx = ST_st_idx (st); 01337 01338 Is_True(OPCODE_is_expression(WN_opcode(value)), 01339 ("Bad value in WN_CreateStid")); 01340 Is_True(Types_Are_Compatible(OPCODE_desc(opc),value), 01341 ("Bad return type in WN_CreateStid")); 01342 Is_True(opr == OPR_STID || opr == OPR_STBITS, 01343 ("Bad opcode in WN_CreateStid")); 01344 #ifdef FRONT_END 01345 Is_True(!((offset == 0) && (st == Int32_Preg || 01346 st == Int64_Preg || 01347 st == Float32_Preg || 01348 st == Float64_Preg)), 01349 ("Preg offset 0 in WN_CreateStid")); 01350 #endif /* FRONT_END */ 01351 01352 #if (defined(FRONT_END_C) || defined(FRONT_END_CPLUSPLUS)) && !defined(FRONT_END_MFEF77) 01353 01354 UINT64 ty_size; 01355 if (field_id == 0) { 01356 ty_size = TY_size(ty); 01357 } 01358 else { 01359 UINT tmp = 0; 01360 ty_size = TY_size(FLD_type(FLD_get_to_field(ty, field_id, tmp))); 01361 } 01362 01363 if (FE_Cvtl_Opt && ST_class(st) != CLASS_PREG ) { 01364 01365 OPCODE value_opc; 01366 01367 value_opc = WN_opcode(value); 01368 01369 if ( ( ( WN_operator(value) == OPR_CVTL 01370 || WN_operator(value) == OPR_CVT ) 01371 && WN_cvtl_bits(value) == ty_size * 8 ) 01372 || ( ( value_opc == OPC_I4I8CVT 01373 || value_opc == OPC_I4U8CVT 01374 || value_opc == OPC_U4I8CVT 01375 || value_opc == OPC_U4U8CVT ) 01376 && ty_size < 8 ) ) 01377 value = WN_kid0(value); 01378 } 01379 01380 if (FE_Store_Opt && ST_class(st) != CLASS_PREG && 01381 WN_operator(value) == OPR_BAND ) { 01382 01383 UINT64 mask; 01384 WN * kid0; 01385 WN * kid1; 01386 01387 mask = masks [ty_size]; 01388 kid0 = WN_kid0(value); 01389 kid1 = WN_kid1(value); 01390 01391 if ( WN_operator(kid0) == OPR_INTCONST 01392 && ( ( WN_const_val(kid0) & mask ) == mask ) ) 01393 value = kid1; 01394 01395 else 01396 if ( WN_operator(kid1) == OPR_INTCONST 01397 && ( ( WN_const_val(kid1) & mask ) == mask ) ) 01398 value = kid0; 01399 } 01400 01401 #endif /* (defined(FRONT_END_C) || defined(FRONT_END_CPLUSPLUS)) && !defined(FRONT_END_MFEF77) */ 01402 01403 wn = WN_Create(opc,1); 01404 WN_kid0(wn) = value; 01405 WN_store_offset(wn) = offset; 01406 WN_st_idx(wn) = st_idx; 01407 WN_set_ty(wn,ty); 01408 WN_set_field_id(wn, field_id); 01409 01410 return(wn); 01411 } 01412 01413 WN * 01414 WN_CreatePStid (OPERATOR opr, TYPE_ID rtype, TYPE_ID desc, 01415 WN_OFFSET offset, ST* st, TY_IDX ty, WN *value, UINT field_id) 01416 { 01417 OPCODE opc = OPCODE_make_op (opr, rtype, desc); 01418 WN *wn; 01419 ST_IDX st_idx = ST_st_idx (st); 01420 01421 Is_True(OPCODE_is_expression(WN_opcode(value)), 01422 ("Bad value in WN_CreatePStid")); 01423 Is_True(Types_Are_Compatible(OPCODE_desc(opc),value), 01424 ("Bad return type in WN_CreatePStid")); 01425 Is_True(opr == OPR_STID || opr == OPR_STBITS, 01426 ("Bad opcode in WN_CreatePStid")); 01427 #ifdef FRONT_END 01428 Is_True(!((offset == 0) && (st == Int32_Preg || 01429 st == Int64_Preg || 01430 st == Float32_Preg || 01431 st == Float64_Preg)), 01432 ("Preg offset 0 in WN_CreatePStid")); 01433 #endif /* FRONT_END */ 01434 01435 #if (defined(FRONT_END_C) || defined(FRONT_END_CPLUSPLUS)) && !defined(FRONT_END_MFEF77) 01436 01437 UINT64 ty_size; 01438 if (field_id == 0) { 01439 ty_size = TY_size(ty); 01440 } 01441 else { 01442 UINT tmp = 0; 01443 ty_size = TY_size(FLD_type(FLD_get_to_field(ty, field_id, tmp))); 01444 } 01445 01446 if (FE_Cvtl_Opt && ST_class(st) != CLASS_PREG ) { 01447 01448 OPCODE value_opc; 01449 01450 value_opc = WN_opcode(value); 01451 01452 if ( ( ( WN_operator(value) == OPR_CVTL 01453 || WN_operator(value) == OPR_CVT ) 01454 && WN_cvtl_bits(value) == ty_size * 8 ) 01455 || ( ( value_opc == OPC_I4I8CVT 01456 || value_opc == OPC_I4U8CVT 01457 || value_opc == OPC_U4I8CVT 01458 || value_opc == OPC_U4U8CVT ) 01459 && ty_size < 8 ) ) 01460 value = WN_kid0(value); 01461 } 01462 01463 if (FE_Store_Opt && ST_class(st) != CLASS_PREG && 01464 WN_operator(value) == OPR_BAND ) { 01465 01466 UINT64 mask; 01467 WN * kid0; 01468 WN * kid1; 01469 01470 mask = masks [ty_size]; 01471 kid0 = WN_kid0(value); 01472 kid1 = WN_kid1(value); 01473 01474 if ( WN_operator(kid0) == OPR_INTCONST 01475 && ( ( WN_const_val(kid0) & mask ) == mask ) ) 01476 value = kid1; 01477 01478 else 01479 if ( WN_operator(kid1) == OPR_INTCONST 01480 && ( ( WN_const_val(kid1) & mask ) == mask ) ) 01481 value = kid0; 01482 } 01483 01484 #endif /* (defined(FRONT_END_C) || defined(FRONT_END_CPLUSPLUS)) && !defined(FRONT_E 01485 ND_MFEF77) */ 01486 01487 wn = WN_Create(opc,1); 01488 WN_kid0(wn) = value; 01489 WN_store_offset(wn) = offset; 01490 WN_st_idx(wn) = st_idx; 01491 WN_set_ty(wn,ty); 01492 WN_set_field_id(wn, field_id); 01493 01494 return(wn); 01495 } 01496 01497 01498 WN *WN_CreatePrefetch(WN_OFFSET offset, UINT32 flag, WN *addr) 01499 { 01500 WN *wn; 01501 Is_True(MTYPE_is_pointer(WN_rtype(addr)), 01502 ("Bad addr in WN_CreatePrefetch")); 01503 wn = WN_Create(OPC_PREFETCH,1); 01504 WN_kid0(wn) = addr; 01505 WN_offset(wn) = offset; 01506 WN_set_flag(wn,flag); 01507 return(wn); 01508 } 01509 01510 WN *WN_CreateIo(IOSTATEMENT iostatement, mINT16 kid_count) 01511 { 01512 WN *wn; 01513 01514 Is_True(kid_count >= 1,("Bad kid_count in WN_CreateIo")); 01515 wn = WN_Create(OPC_IO,kid_count); 01516 WN_io_statement(wn) = iostatement; 01517 WN_Set_IO_Library(wn,target_io_library); 01518 01519 return(wn); 01520 } 01521 01522 WN *WN_CreateIoItem0(IOITEM ioitem, TY_IDX ty) 01523 { 01524 WN *wn; 01525 01526 wn = WN_Create(OPC_IO_ITEM,0); 01527 WN_io_item(wn) = ioitem; 01528 WN_set_ty(wn, ty); 01529 01530 return(wn); 01531 } 01532 01533 WN *WN_CreateIoItem1(IOITEM ioitem, WN *kid0, TY_IDX ty) 01534 { 01535 WN *wn; 01536 01537 wn = WN_Create(OPC_IO_ITEM,1); 01538 WN_io_item(wn) = ioitem; 01539 WN_kid0(wn) = kid0; 01540 WN_set_ty(wn, ty); 01541 01542 return(wn); 01543 } 01544 01545 WN *WN_CreateIoItem2(IOITEM ioitem, WN *kid0, WN *kid1, TY_IDX ty) 01546 { 01547 WN *wn; 01548 01549 wn = WN_Create(OPC_IO_ITEM,2); 01550 WN_io_item(wn) = ioitem; 01551 WN_kid0(wn) = kid0; 01552 WN_kid1(wn) = kid1; 01553 WN_set_ty(wn, ty); 01554 01555 return(wn); 01556 } 01557 01558 WN *WN_CreateIoItem3(IOITEM ioitem, WN *kid0, WN *kid1, WN *kid2, TY_IDX ty) 01559 { 01560 WN *wn; 01561 01562 wn = WN_Create(OPC_IO_ITEM,3); 01563 WN_io_item(wn) = ioitem; 01564 WN_kid0(wn) = kid0; 01565 WN_kid1(wn) = kid1; 01566 WN_kid(wn,2) = kid2; 01567 WN_set_ty(wn, ty); 01568 01569 return(wn); 01570 } 01571 01572 WN *WN_CreateIoItemN(IOITEM ioitem, mINT16 kid_count, TY_IDX ty) 01573 { 01574 WN *wn; 01575 01576 wn = WN_Create(OPC_IO_ITEM,kid_count); 01577 WN_io_item(wn) = ioitem; 01578 WN_set_ty(wn, ty); 01579 01580 return(wn); 01581 } 01582 01583 WN *WN_CreateEval(WN *exp) 01584 { 01585 WN *wn; 01586 01587 Is_True(OPCODE_is_expression(WN_opcode(exp)), 01588 ("Bad exp in WN_CreateEval")); 01589 wn = WN_Create(OPC_EVAL,1); 01590 WN_kid0(wn) = exp; 01591 01592 return(wn); 01593 } 01594 01595 WN * 01596 WN_CreatePragma (WN_PRAGMA_ID pragma_name, ST_IDX st, INT32 arg1, INT32 arg2) 01597 { 01598 WN *wn; 01599 01600 wn = WN_Create(OPC_PRAGMA,0); 01601 WN_pragma(wn) = pragma_name; 01602 WN_st_idx(wn) = st; 01603 WN_pragma_flags(wn) = 0; 01604 WN_pragma_arg1(wn) = arg1; 01605 WN_pragma_arg2(wn) = arg2; 01606 01607 return(wn); 01608 } 01609 01610 WN * 01611 WN_CreatePragma (WN_PRAGMA_ID pragma_name, 01612 ST_IDX st, 01613 INT32 arg1, 01614 PREG_NUM asm_copyout_preg, 01615 UINT32 asm_opnd_num) 01616 { 01617 WN *wn; 01618 01619 Is_True(pragma_name == WN_PRAGMA_ASM_CONSTRAINT, 01620 ("ASM_CONSTRAINT-specific CreatePragma can't be used for " 01621 "other pragmas")); 01622 wn = WN_Create(OPC_PRAGMA,0); 01623 WN_pragma(wn) = pragma_name; 01624 WN_st_idx(wn) = st; 01625 WN_pragma_flags(wn) = 0; 01626 WN_pragma_arg1(wn) = arg1; 01627 WN_set_pragma_asm_copyout_preg(wn, asm_copyout_preg); 01628 WN_set_pragma_asm_opnd_num(wn, asm_opnd_num); 01629 01630 return(wn); 01631 } 01632 01633 WN *WN_CreateXpragma(WN_PRAGMA_ID pragma_name, ST_IDX st, INT16 kid_count) 01634 { 01635 WN *wn; 01636 01637 wn = WN_Create(OPC_XPRAGMA, kid_count); 01638 WN_pragma(wn) = pragma_name; 01639 WN_st_idx(wn) = st; 01640 WN_pragma_flags(wn) = 0; 01641 WN_pragma_arg64(wn) = 0; 01642 01643 return(wn); 01644 } 01645 01646 /* 01647 * Create expression nodes 01648 * 01649 */ 01650 01651 /* first the generic ones */ 01652 01653 WN *WN_CreateExp0(OPERATOR opr, TYPE_ID rtype, TYPE_ID desc) 01654 { 01655 WN *wn; 01656 01657 wn = WN_Create(opr, rtype, desc, 0); 01658 01659 return(wn); 01660 } 01661 01662 WN *WN_CreateExp1(OPERATOR opr, TYPE_ID rtype, TYPE_ID desc,WN *kid0) 01663 { 01664 OPCODE opc = OPCODE_make_op (opr, rtype, desc); 01665 WN *wn; 01666 01667 Is_True(OPCODE_is_expression(WN_opcode(kid0)), 01668 ("Bad kid0 in WN_CreateExp1")); 01669 01670 wn = WN_SimplifyExp1(opc, kid0); 01671 if (!wn) { 01672 wn = WN_Create(opr, rtype, desc, 1); 01673 WN_kid0(wn) = kid0; 01674 } 01675 else { 01676 /* Parent pointer (if it exists) for returned node must be NULL */ 01677 if (WN_SimpParentMap != WN_MAP_UNDEFINED) { 01678 WN_MAP_Set(WN_SimpParentMap, wn, NULL); 01679 } 01680 } 01681 01682 return(wn); 01683 } 01684 01685 WN *WN_CreateExp2(OPERATOR opr, TYPE_ID rtype, TYPE_ID desc, WN *kid0, WN *kid1) 01686 { 01687 OPCODE opc = OPCODE_make_op (opr, rtype, desc); 01688 WN *wn; 01689 01690 Is_True(OPCODE_is_expression(WN_opcode(kid0)), 01691 ("Bad kid0 in WN_CreateExp2")); 01692 Is_True(OPCODE_is_expression(WN_opcode(kid1)), 01693 ("Bad kid1 in WN_CreateExp2")); 01694 wn = WN_SimplifyExp2(opc, kid0, kid1); 01695 if (!wn) { 01696 wn = WN_Create(opr,rtype,desc,2); 01697 WN_kid0(wn) = kid0; 01698 WN_kid1(wn) = kid1; 01699 } 01700 else { 01701 /* Parent pointer (if it exists) for returned node must be NULL */ 01702 if (WN_SimpParentMap != WN_MAP_UNDEFINED) { 01703 WN_MAP_Set(WN_SimpParentMap, wn, NULL); 01704 } 01705 } 01706 01707 return(wn); 01708 } 01709 01710 WN *WN_CreateExp3(OPERATOR opr, TYPE_ID rtype, TYPE_ID desc, 01711 WN *kid0, WN *kid1, WN *kid2) 01712 { 01713 OPCODE opc = OPCODE_make_op (opr, rtype, desc); 01714 WN *wn; 01715 01716 Is_True(OPCODE_is_expression(WN_opcode(kid0)), 01717 ("Bad kid0 in WN_CreateExp3")); 01718 Is_True(OPCODE_is_expression(WN_opcode(kid1)), 01719 ("Bad kid1 in WN_CreateExp3")); 01720 Is_True(OPCODE_is_expression(WN_opcode(kid2)), 01721 ("Bad kid2 in WN_CreateExp3")); 01722 01723 wn = WN_SimplifyExp3(opc, kid0, kid1, kid2); 01724 if (!wn) { 01725 wn = WN_Create(opr,rtype,desc,3); 01726 WN_kid0(wn) = kid0; 01727 WN_kid1(wn) = kid1; 01728 WN_kid(wn,2) = kid2; 01729 } 01730 else { 01731 /* Parent pointer (if it exists) for returned node must be NULL */ 01732 if (WN_SimpParentMap != WN_MAP_UNDEFINED) { 01733 WN_MAP_Set(WN_SimpParentMap, wn, NULL); 01734 } 01735 } 01736 01737 return(wn); 01738 } 01739 01740 WN *WN_CreateCvtl(OPERATOR opr, TYPE_ID rtype, TYPE_ID desc, 01741 INT16 cvtl_bits, WN* kid0) 01742 { 01743 OPCODE opc = OPCODE_make_op (opr, rtype, desc); 01744 WN *wn; 01745 01746 Is_True(OPCODE_operator(opc) == OPR_CVTL, ("Bad opcode in WN_CreateCvtl")); 01747 01748 wn = WN_SimplifyCvtl(opc, cvtl_bits, kid0); 01749 if (!wn) { 01750 wn = WN_CreateExp1(opr, rtype, desc, kid0); 01751 WN_cvtl_bits(wn) = cvtl_bits; 01752 } 01753 else { 01754 /* Parent pointer (if it exists) for returned node must be NULL */ 01755 if (WN_SimpParentMap != WN_MAP_UNDEFINED) { 01756 WN_MAP_Set(WN_SimpParentMap, wn, NULL); 01757 } 01758 } 01759 01760 return(wn); 01761 } 01762 01763 WN * 01764 WN_CreateIload (OPERATOR opr, TYPE_ID rtype, TYPE_ID desc, 01765 WN_OFFSET offset, TY_IDX ty, 01766 TY_IDX load_addr_ty, WN *addr, UINT field_id) 01767 { 01768 OPCODE opc = OPCODE_make_op (opr, rtype, desc); 01769 WN *wn; 01770 01771 Is_True(MTYPE_is_pointer(WN_rtype(addr)) || 01772 WN_rtype(addr) == MTYPE_U8 || 01773 WN_rtype(addr) == MTYPE_U4 || 01774 WN_rtype(addr) == MTYPE_I8 || 01775 WN_rtype(addr) == MTYPE_I4, 01776 ("Bad addr in WN_CreateIload")); 01777 01778 Is_True(opr == OPR_ILOAD || opr == OPR_ILDBITS, 01779 ("Bad opcode in WN_CreateIload")); 01780 01781 #if (defined(FRONT_END_C) || defined(FRONT_END_CPLUSPLUS)) && !defined(FRONT_END_MFEF77) 01782 01783 addr = fe_combine_address_offset ( &offset, addr ); 01784 01785 #endif /* (defined(FRONT_END_C) || defined(FRONT_END_CPLUSPLUS)) && !defined(FRONT_END_MFEF77) */ 01786 01787 wn = WN_SimplifyIload(opc,offset,ty,field_id,load_addr_ty,addr); 01788 if (!wn) { 01789 wn = WN_CreateExp1(opr,rtype,desc,addr); 01790 WN_load_offset(wn) = offset; 01791 WN_set_ty(wn,ty); 01792 WN_set_load_addr_ty(wn,load_addr_ty); 01793 WN_set_field_id(wn, field_id); 01794 } 01795 else { 01796 /* Parent pointer (if it exists) for returned node must be NULL */ 01797 if (WN_SimpParentMap != WN_MAP_UNDEFINED) { 01798 WN_MAP_Set(WN_SimpParentMap, wn, NULL); 01799 } 01800 } 01801 01802 return(wn); 01803 } 01804 01805 WN * 01806 WN_CreateIloadx (OPERATOR opr, TYPE_ID rtype, TYPE_ID desc, 01807 TY_IDX ty, TY_IDX load_addr_ty, WN *addr1, 01808 WN *addr2) 01809 { 01810 OPCODE opc = OPCODE_make_op (opr, rtype, desc); 01811 WN *wn; 01812 01813 Is_True(OPCODE_operator(opc) == OPR_ILOADX, 01814 ("Bad opcode in WN_CreateIloadx")); 01815 Is_True(WN_operator(addr1) == OPR_LDID, 01816 ("Bad address1 in WN_CreateIloadx")); 01817 Is_True(WN_operator(addr2) == OPR_LDID, 01818 ("Bad address2 in WN_CreateIloadx")); 01819 wn = WN_CreateExp2(opr,rtype,desc,addr1,addr2); 01820 WN_load_offset(wn) = 0; 01821 WN_set_ty(wn,ty); 01822 WN_set_load_addr_ty(wn,load_addr_ty); 01823 return(wn); 01824 } 01825 01826 01827 WN *WN_CreateMload (WN_OFFSET offset, TY_IDX ty,WN *addr, WN *num_bytes) 01828 { 01829 WN *wn; 01830 01831 Is_True(MTYPE_is_pointer(WN_rtype(addr)) || 01832 WN_rtype(addr)==MTYPE_U8 || 01833 WN_rtype(addr)==MTYPE_U4 || 01834 WN_rtype(addr)==MTYPE_I8 || 01835 WN_rtype(addr)==MTYPE_I4, 01836 ("Bad addr in WN_CreateMload")); 01837 01838 #if (defined(FRONT_END_C) || defined(FRONT_END_CPLUSPLUS)) && !defined(FRONT_END_MFEF77) 01839 01840 addr = fe_combine_address_offset ( &offset, addr ); 01841 01842 #endif /* (defined(FRONT_END_C) || defined(FRONT_END_CPLUSPLUS)) && !defined(FRONT_END_MFEF77) */ 01843 01844 wn = WN_CreateExp2(OPC_MLOAD,addr,num_bytes); 01845 WN_load_offset(wn) = offset; 01846 WN_set_ty(wn,ty); 01847 01848 return(wn); 01849 } 01850 01851 01852 01853 01854 WN * 01855 WN_CreateLdid (OPERATOR opr, TYPE_ID rtype, TYPE_ID desc, 01856 WN_OFFSET offset, ST_IDX st, TY_IDX ty, UINT field_id) 01857 { 01858 OPCODE opc = OPCODE_make_op (opr, rtype, desc); 01859 WN *wn; 01860 01861 Is_True (opr == OPR_LDID || opr == OPR_LDBITS, 01862 ("Bad opcode in WN_CreateLdid")); 01863 01864 #ifdef FRONT_END 01865 Is_True (!((offset == 0) && (&St_Table [st] == Int32_Preg || 01866 &St_Table [st] == Int64_Preg || 01867 &St_Table [st] == Float32_Preg || 01868 &St_Table [st] == Float64_Preg)), 01869 ("Preg offset 0 in WN_CreateLdid")); 01870 #endif /* FRONT_END */ 01871 01872 01873 wn = WN_Create(opr,rtype,desc,0); 01874 WN_load_offset(wn) = offset; 01875 WN_st_idx(wn) = st; 01876 WN_set_ty(wn,ty); 01877 WN_set_field_id(wn, field_id); 01878 01879 return(wn); 01880 } 01881 01882 01883 WN *WN_CreateLda (OPERATOR opr, TYPE_ID rtype, TYPE_ID desc, 01884 WN_OFFSET offset, TY_IDX ty, ST_IDX st, UINT field_id) 01885 { 01886 OPCODE opc = OPCODE_make_op (opr, rtype, desc); 01887 WN *wn; 01888 01889 Is_True(MTYPE_is_pointer(OPCODE_rtype(opc)), 01890 ("Bad addr in WN_CreateLda")); 01891 Is_True(OPCODE_operator(opc) == OPR_LDA, 01892 ("Bad opcode in WN_CreateLda")); 01893 wn = WN_Create(opr,rtype,desc,0); 01894 WN_load_offset(wn) = offset; 01895 WN_st_idx(wn) = st; 01896 WN_set_ty(wn,ty); 01897 WN_set_field_id(wn, field_id); 01898 01899 return(wn); 01900 } 01901 01902 WN * 01903 WN_CreateIlda (OPERATOR opr, TYPE_ID rtype, TYPE_ID desc, 01904 WN_OFFSET offset, TY_IDX ty) 01905 { 01906 OPCODE opc = OPCODE_make_op (opr, rtype, desc); 01907 WN *wn; 01908 01909 Is_True(MTYPE_is_pointer(OPCODE_rtype(opc)), 01910 ("Bad addr in WN_CreateIlda")); 01911 Is_True(OPCODE_operator(opc) == OPR_ILDA, 01912 ("Bad opcode in WN_CreateIlda")); 01913 wn = WN_Create(opr,rtype,desc,0); 01914 WN_load_offset(wn) = offset; 01915 WN_set_ty(wn,ty); 01916 01917 return(wn); 01918 } 01919 01920 01921 WN *WN_CreateIdname(WN_OFFSET offset, ST_IDX st) 01922 { 01923 WN *wn; 01924 01925 wn = WN_Create(OPC_IDNAME, 0); 01926 WN_idname_offset(wn) = offset; 01927 WN_st_idx(wn) = st; 01928 01929 return(wn); 01930 } 01931 01932 01933 WN *WN_CreateConst(OPERATOR opr, TYPE_ID rtype, TYPE_ID desc, ST_IDX st) 01934 { 01935 OPCODE opc = OPCODE_make_op (opr, rtype, desc); 01936 WN *wn; 01937 01938 Is_True(OPCODE_operator(opc) == OPR_CONST, 01939 ("Bad opcode in WN_CreateConst")); 01940 wn = WN_Create(opr,rtype,desc,0); 01941 WN_st_idx(wn) = st; 01942 01943 return(wn); 01944 } 01945 01946 WN *WN_CreateIntconst(OPERATOR opr, TYPE_ID rtype, TYPE_ID desc, INT64 const_val) 01947 { 01948 OPCODE opc = OPCODE_make_op (opr, rtype, desc); 01949 WN *wn; 01950 01951 Is_True(OPCODE_operator(opc) == OPR_INTCONST, 01952 ("Bad opcode in WN_CreateIntconst")); 01953 wn = WN_Create(opr,rtype,desc,0); 01954 if (opc == OPC_U4INTCONST) { 01955 /* make sure that 32-bit value is sign-extended */ 01956 UINT32 uval = const_val; 01957 INT32 sval = uval; 01958 WN_const_val(wn) = (INT64) sval; 01959 } else { 01960 WN_const_val(wn) = const_val; 01961 } 01962 01963 return(wn); 01964 } 01965 01966 WN *WN_CreateComma(OPERATOR opr, TYPE_ID rtype, TYPE_ID desc, 01967 WN *block, WN *value) 01968 { 01969 OPCODE opc = OPCODE_make_op (opr, rtype, desc); 01970 WN *wn; 01971 01972 Is_True(OPCODE_is_expression(WN_opcode(value)), 01973 ("Bad value in WN_CreateComma")); 01974 Is_True(WN_opcode(block) == OPC_BLOCK, 01975 ("Bad block in WN_CreateComma")); 01976 wn = WN_Create(opr,rtype,desc,2); 01977 WN_kid0(wn) = block; 01978 WN_kid1(wn) = value; 01979 01980 #ifdef FRONT_END 01981 Set_PU_has_very_high_whirl (Get_Current_PU ()); 01982 #endif /* FRONT_END */ 01983 01984 return(wn); 01985 } 01986 01987 WN *WN_CreateRcomma(OPERATOR opr, TYPE_ID rtype, TYPE_ID desc, 01988 WN *value, WN *block) 01989 { 01990 OPCODE opc = OPCODE_make_op (opr, rtype, desc); 01991 WN *wn; 01992 01993 Is_True(OPCODE_is_expression(WN_opcode(value)), 01994 ("Bad value in WN_CreateComma")); 01995 Is_True(WN_opcode(block) == OPC_BLOCK, 01996 ("Bad block in WN_CreateComma")); 01997 wn = WN_Create(opr,rtype,desc,2); 01998 WN_kid0(wn) = value; 01999 WN_kid1(wn) = block; 02000 02001 #ifdef FRONT_END 02002 Set_PU_has_very_high_whirl (Get_Current_PU ()); 02003 #endif /* FRONT_END */ 02004 02005 return(wn); 02006 } 02007 02008 WN *WN_CreateAsm_Stmt (INT16 kid_count, char *asm_string) 02009 { 02010 WN *wn = WN_Create(OPC_ASM_STMT, kid_count); 02011 02012 ST *asm_st = New_ST(CURRENT_SYMTAB); 02013 WN_st_idx(wn) = ST_st_idx(asm_st); 02014 ST_Init(asm_st, 02015 Str_To_Index (Save_Str(asm_string), Current_Strtab), 02016 CLASS_NAME, 02017 SCLASS_UNKNOWN, 02018 EXPORT_LOCAL, 02019 (TY_IDX) 0); 02020 02021 return wn; 02022 } 02023 02024 WN *WN_CreateAsm_Input (char *constraint_string, 02025 UINT32 opnd_num, 02026 WN *value) 02027 { 02028 WN *wn = WN_Create(OPC_ASM_INPUT, 1); 02029 02030 ST *constraint_st = New_ST(CURRENT_SYMTAB); 02031 WN_st_idx(wn) = ST_st_idx(constraint_st); 02032 ST_Init(constraint_st, 02033 Str_To_Index (Save_Str(constraint_string), Current_Strtab), 02034 CLASS_NAME, 02035 SCLASS_UNKNOWN, 02036 EXPORT_LOCAL, 02037 (TY_IDX) 0); 02038 02039 WN_kid0(wn) = value; 02040 WN_asm_opnd_num(wn) = opnd_num; 02041 return wn; 02042 } 02043 02044 WN *WN_CreateComment (char *s) 02045 { 02046 WN *wn; 02047 wn = WN_Create(OPC_COMMENT,0); 02048 02049 ST *comment_st = New_ST(CURRENT_SYMTAB); 02050 WN_st_idx(wn) = ST_st_idx(comment_st); 02051 ST_Init(comment_st, 02052 Str_To_Index (Save_Str(s), Current_Strtab), 02053 CLASS_NAME, 02054 SCLASS_UNKNOWN, 02055 EXPORT_LOCAL, 02056 (TY_IDX) 0); 02057 02058 return wn; 02059 } 02060 02061 STR_IDX WN_GetComment (const WN *wn) 02062 { 02063 Is_True(WN_opcode(wn) == OPC_COMMENT, ("Bad opcode in WN_GetComment")); 02064 return ST_name_idx(WN_st(wn)); 02065 } 02066 02067 WN *WN_CopyNode (const WN* src_wn) 02068 { 02069 WN* wn; 02070 OPCODE opcode = WN_opcode(src_wn); 02071 02072 if (src_wn == NULL) return NULL; 02073 wn = WN_Create (opcode, WN_kid_count(src_wn)); 02074 02075 WN_Copy_u1u2 (wn, src_wn); 02076 WN_Copy_u3 (wn, src_wn); 02077 WN_set_field_id(wn, WN_field_id(src_wn)); 02078 02079 if (opcode == OPC_REGION && WN_ereg_supp(src_wn) != (INITO_IDX) 0) { 02080 const INITO& src_ino = Inito_Table[WN_ereg_supp (src_wn)]; 02081 const ST *st = Copy_ST (INITO_st (src_ino)); 02082 WN_ereg_supp(wn) = New_INITO (st, src_ino.val); 02083 } 02084 02085 if (OPCODE_has_next_prev(opcode)) { 02086 WN_linenum(wn) = WN_linenum(src_wn); 02087 } 02088 02089 return(wn); 02090 } 02091 02092 #if 0 02093 /* no one uses this currently */ 02094 void IPA_WN_Move_Maps (WN_MAP_TAB *maptab, WN *dst, WN *src) 02095 { 02096 INT32 i; 02097 02098 /* if the opcodes are in the same category, just move the map_id */ 02099 if (OPCODE_mapcat(WN_opcode(dst)) == OPCODE_mapcat(WN_opcode(src))) { 02100 if (WN_map_id(dst) != WN_MAP_UNDEFINED) WN_MAP_Add_Free_List(maptab, dst); 02101 WN_map_id(dst) = WN_map_id(src); 02102 WN_map_id(src) = WN_MAP_UNDEFINED; 02103 return; 02104 } 02105 02106 /* otherwise iterate through the mappings */ 02107 for (i = 0; i < WN_MAP_MAX; i++) { 02108 if (maptab->_is_used[i]) { 02109 switch (maptab->_kind[i]) { 02110 case WN_MAP_KIND_VOIDP: { 02111 IPA_WN_MAP_Set(maptab, i, dst, IPA_WN_MAP_Get(maptab, i, src)); 02112 break; 02113 } 02114 case WN_MAP_KIND_INT32: { 02115 IPA_WN_MAP32_Set(maptab, i, dst, IPA_WN_MAP32_Get(maptab, i, src)); 02116 break; 02117 } 02118 case WN_MAP_KIND_INT64: { 02119 IPA_WN_MAP64_Set(maptab, i, dst, IPA_WN_MAP64_Get(maptab, i, src)); 02120 break; 02121 } 02122 default: 02123 Is_True(FALSE, ("WN_Move_Maps: unknown map kind")); 02124 } 02125 } 02126 } 02127 02128 WN_MAP_Add_Free_List(maptab, src); 02129 WN_map_id(src) = WN_MAP_UNDEFINED; 02130 } 02131 #endif 02132 02133 void IPA_WN_Move_Maps_PU (WN_MAP_TAB *src, WN_MAP_TAB *dst, WN *wn) 02134 { 02135 INT32 i; 02136 OPERATOR_MAPCAT category = OPCODE_mapcat(WN_opcode(wn)); 02137 INT32 old_map_id = WN_map_id(wn); 02138 UINT c; 02139 02140 if (old_map_id == WN_MAP_UNDEFINED) 02141 return; 02142 02143 WN_MAP_Add_Free_List(src, wn); 02144 WN_map_id(wn) = WN_MAP_UNDEFINED; 02145 WN_MAP_Set_ID(dst,wn); 02146 02147 /* iterate through the mappings */ 02148 /* Note that we transfer all the maps that are live, not just the 02149 reserved ones. This is because we want to have all the maps when 02150 we start processing the child PU (Preopt and LNO are not run 02151 on the child again to recreate the maps so we save them here.) */ 02152 for (i = 0; i < WN_MAP_MAX; i++) { 02153 if (src->_is_used[i]) { 02154 02155 if (!dst->_is_used[i]) { /* Create the destination */ 02156 dst->_is_used[i] = TRUE; 02157 for (c = 0; c < WN_MAP_CATEGORIES; c++) { 02158 dst->_map_size[c][i] = 0; 02159 dst->_mapping[c][i] = NULL; 02160 } 02161 dst->_pool[i] = src->_pool[i]; 02162 dst->_kind[i] = src->_kind[i]; 02163 } 02164 02165 switch (src->_kind[i]) { 02166 case WN_MAP_KIND_VOIDP: { 02167 if (old_map_id < src->_map_size[category][i]) { 02168 IPA_WN_MAP_Set(dst, i, wn, src->_mapping[category][i][old_map_id]); 02169 } 02170 break; 02171 } 02172 case WN_MAP_KIND_INT32: { 02173 if (old_map_id < src->_map_size[category][i]) { 02174 IPA_WN_MAP32_Set(dst, i, wn, 02175 ((INT32*) src->_mapping[category][i])[old_map_id]); 02176 } 02177 break; 02178 } 02179 case WN_MAP_KIND_INT64: { 02180 if (old_map_id < src->_map_size[category][i]) { 02181 IPA_WN_MAP64_Set(dst, i, wn, 02182 ((INT64*) src->_mapping[category][i])[old_map_id]); 02183 } 02184 break; 02185 } 02186 default: 02187 Is_True(FALSE, ("IPA_WN_Move_Maps_PU: unknown map kind")); 02188 } 02189 } 02190 } 02191 02192 } 02193 02194 02195 INT32 02196 WN_Size_and_StartAddress (WN *wn, void **StartAddress) 02197 { 02198 if (OPCODE_has_next_prev(WN_opcode(wn))) { 02199 *StartAddress = (void *)&(WN_prev(wn)); 02200 return sizeof(WN) + sizeof(mUINT64) + 02201 (max (2, WN_kid_count(wn)) * sizeof(WN*)); 02202 } else { 02203 *StartAddress = (void *) wn; 02204 return sizeof(WN) + max(0, WN_kid_count(wn) - 2) * sizeof(WN*); 02205 } 02206 02207 } 02208 02209 02210 WN *WN_CreateLoopInfo (WN *induction, WN *trip, UINT16 trip_est, UINT16 depth, INT32 flags) 02211 { 02212 WN *wn; 02213 INT16 nkids = 0; 02214 if (induction != NULL) nkids++; 02215 if (trip != NULL) nkids++; 02216 Is_True(!(induction==NULL && trip != NULL), 02217 ("trip must be null if induction is null in WN_CreateLoopInfo")); 02218 02219 wn = WN_Create (OPC_LOOP_INFO, nkids); 02220 WN_loop_trip_est(wn) = trip_est; 02221 WN_loop_depth(wn) = depth; 02222 WN_loop_flag(wn) = flags; 02223 if (induction) WN_set_loop_induction(wn, induction); 02224 if (trip) WN_set_loop_trip(wn, trip); 02225 return wn; 02226 } 02227 02228 WN *WN_CreateExcScopeBegin (INT32 id, INT16 nkids, INITO_IDX ereg_supp) 02229 { 02230 WN *wn; 02231 wn = WN_Create (OPC_EXC_SCOPE_BEGIN, nkids); 02232 WN_ereg_supp(wn) = ereg_supp; 02233 WN_offset(wn) = id; 02234 return wn; 02235 } 02236 02237 WN *WN_CreateExcScopeEnd (INT32 id) 02238 { 02239 WN *wn; 02240 wn = WN_Create (OPC_EXC_SCOPE_END, 0); 02241 WN_offset(wn) = id; 02242 return wn; 02243 } 02244 02245 WN *WN_CreateBarrier (BOOL forward, INT16 nkids) 02246 { 02247 WN *wn; 02248 if (forward) 02249 wn = WN_Create (OPC_FORWARD_BARRIER, nkids); 02250 else 02251 wn = WN_Create (OPC_BACKWARD_BARRIER, nkids); 02252 return wn; 02253 } 02254 02255 WN *WN_CreateTrap (INT32 value) 02256 { 02257 WN *wn; 02258 wn = WN_Create (OPC_TRAP, 0); 02259 WN_offset(wn) = value; 02260 return wn; 02261 } 02262 02263 WN *WN_CreateAssert (INT32 value, WN *condition) 02264 { 02265 WN *wn; 02266 wn = WN_Create (OPC_ASSERT, 1); 02267 WN_kid(wn,0) = condition; 02268 WN_offset(wn) = value; 02269 return wn; 02270 } 02271 02272 WN * WN_Zerocon (TYPE_ID ty) 02273 { 02274 02275 if (MTYPE_type_class(ty)&MTYPE_CLASS_INTEGER) 02276 return WN_Intconst(ty, (INT64) 0); 02277 else 02278 return Make_Const(Targ_Conv(ty, Host_To_Targ (MTYPE_I4, 0))); 02279 } 02280 02281 WN *WN_Tas(TYPE_ID rtype, TY_IDX ty, WN *l) 02282 { 02283 WN *tas; 02284 02285 tas = WN_CreateExp1(OPR_TAS, rtype, MTYPE_V, l); 02286 /* The simplifier may have set this to something other than a TAS, 02287 so check before setting the TY */ 02288 if (WN_operator_is(tas, OPR_TAS)) { 02289 WN_set_ty(tas, ty); 02290 } 02291 02292 return tas; 02293 } 02294 02295 /* --------------------------------------------------------------------- 02296 * 02297 * WN *WN_Create_Intrinsic(OPCODE opc, INTRINSIC intrinsic, INT32 n, WN *kids[]) 02298 * 02299 * Create an intrinsic node, calling the simplifier if necessary 02300 * --------------------------------------------------------------------- 02301 */ 02302 WN *WN_Create_Intrinsic(OPERATOR opr, TYPE_ID rtype, TYPE_ID desc, 02303 INTRINSIC intrinsic, INT32 n, WN *kids[]) 02304 { 02305 OPCODE opc = OPCODE_make_op (opr, rtype, desc); 02306 WN *call; 02307 INT32 i; 02308 02309 call = WN_SimplifyIntrinsic(opc, intrinsic, n, kids); 02310 if (!call) { 02311 call = WN_Create(opr, rtype, desc, n); 02312 WN_intrinsic(call) = intrinsic; 02313 for (i=0; i<n; i++) { 02314 WN_kid(call,i) = kids[i]; 02315 } 02316 } 02317 else { 02318 /* Parent pointer (if it exists) for returned node must be NULL */ 02319 if (WN_SimpParentMap != WN_MAP_UNDEFINED) { 02320 WN_MAP_Set(WN_SimpParentMap, call, NULL); 02321 } 02322 } 02323 02324 return call; 02325 } 02326 02327 WN *WN_CreateParm(TYPE_ID rtype, WN *parm_node, TY_IDX ty, UINT32 flag) 02328 { 02329 OPCODE op = OPCODE_make_op(OPR_PARM, rtype, MTYPE_V); 02330 WN *wn; 02331 02332 if ( parm_node != NULL ) { 02333 if (op != OPC_VPARM) { 02334 Is_True( OPCODE_is_expression(WN_opcode(parm_node)), 02335 ("Bad parm_node in WN_CreateParm")); 02336 Is_True( Types_Are_Compatible (rtype, parm_node ), 02337 ("rtype and parm_node's rtype are different in WN_CreateParm")); 02338 } 02339 wn = WN_CreateExp1(op, parm_node); 02340 } 02341 else { 02342 Is_True( rtype == MTYPE_V, 02343 ("non-VOID type in WN_CreateParm with null parm_node") ); 02344 wn = WN_CreateExp0(op); 02345 } 02346 WN_set_ty(wn, ty); 02347 WN_set_flag(wn, flag); 02348 return wn; 02349 } 02350 02351 WN *WN_Intconst(TYPE_ID rtype, INT64 value) 02352 { 02353 return WN_CreateIntconst(OPR_INTCONST, rtype, MTYPE_V, value); 02354 } 02355 02356 WN *WN_Ldid(TYPE_ID desc, WN_OFFSET offset, ST_IDX sym, TY_IDX align, 02357 UINT field_id) 02358 { 02359 TYPE_ID rtype= Mtype_comparison(desc); 02360 02361 return WN_CreateLdid (OPR_LDID, rtype, desc, offset, sym, align, field_id); 02362 } 02363 02364 WN * 02365 WN_RLdid (TYPE_ID rtype, TYPE_ID desc, WN_OFFSET offset, ST_IDX sym, 02366 TY_IDX align) 02367 { 02368 return WN_CreateLdid (OPR_LDID, rtype, desc, offset, sym, align); 02369 } 02370 02371 WN *WN_LdidPreg(TYPE_ID desc, WN_OFFSET pregno) 02372 { 02373 ST *preg = MTYPE_To_PREG(desc); 02374 02375 return WN_Ldid(desc, pregno, preg, ST_type(preg)); 02376 } 02377 02378 WN * 02379 WN_Stid (TYPE_ID desc, WN_OFFSET offset, ST* sym, TY_IDX align, WN *value, 02380 UINT field_id) 02381 { 02382 return WN_CreateStid(OPR_STID, MTYPE_V, desc, offset, sym, align, value, 02383 field_id); 02384 } 02385 WN * 02386 WN_PStid (TYPE_ID desc, WN_OFFSET offset, ST* sym, TY_IDX align, WN *value, 02387 UINT field_id) 02388 { 02389 return WN_CreatePStid(OPR_STID, MTYPE_V, desc, offset, sym, align, value, 02390 field_id); 02391 } 02392 02393 02394 WN *WN_StidIntoPreg(TYPE_ID desc, WN_OFFSET offset, ST* preg, WN *value) 02395 { 02396 return WN_CreateStid(OPR_STID, MTYPE_V, desc, offset, preg, ST_type(preg), value); 02397 } 02398 02399 02400 /* 02401 * These are much needed higher level routines built on the WN_Create 02402 * to build WN. Most of them determine the opcode based on type information 02403 * supplied. 02404 * 02405 * For a more detailed description, see wn.h 02406 */ 02407 02408 02409 WN *WN_Iload(TYPE_ID desc, WN_OFFSET offset, TY_IDX align, WN *addr, 02410 UINT field_id) 02411 { 02412 TY_IDX palign; 02413 TYPE_ID rtype= Mtype_comparison(desc); 02414 palign = Make_Pointer_Type (align); 02415 02416 return WN_CreateIload (OPR_ILOAD, rtype, desc, offset, align, palign, addr, 02417 field_id); 02418 } 02419 02420 WN * 02421 WN_RIload (TYPE_ID rtype, TYPE_ID desc, WN_OFFSET offset, TY_IDX align, 02422 WN *addr) 02423 { 02424 TY_IDX palign; 02425 palign = Make_Pointer_Type(align); 02426 02427 return WN_CreateIload (OPR_ILOAD, rtype, desc, offset, align, palign, addr); 02428 } 02429 02430 WN * 02431 WN_Pstore (TYPE_ID desc, WN_OFFSET offset, TY_IDX align, WN *addr, WN *value, 02432 UINT field_id) 02433 { 02434 return WN_CreatePstore (OPR_ISTORE, MTYPE_V, desc, offset, align, value, addr, 02435 field_id); 02436 } 02437 02438 02439 WN * 02440 WN_Istore (TYPE_ID desc, WN_OFFSET offset, TY_IDX align, WN *addr, WN *value, 02441 UINT field_id) 02442 { 02443 return WN_CreateIstore (OPR_ISTORE, MTYPE_V, desc, offset, align, value, addr, 02444 field_id); 02445 } 02446 02447 WN *WN_Unary(OPERATOR opr, TYPE_ID rtype, WN *l) 02448 { 02449 return WN_CreateExp1(opr, rtype, MTYPE_V, l); 02450 } 02451 02452 WN *WN_Binary(OPERATOR opr, TYPE_ID rtype, WN *l, WN *r) 02453 { 02454 return WN_CreateExp2(opr, rtype, MTYPE_V, l, r); 02455 } 02456 02457 WN *WN_Ternary(OPERATOR opr, TYPE_ID rtype, WN *kid0, WN *kid1, WN *kid2) 02458 { 02459 return WN_CreateExp3(opr, rtype, MTYPE_V, kid0, kid1, kid2); 02460 } 02461 02462 WN * 02463 WN_IloadLdid (TYPE_ID desc, WN_OFFSET offset, TY_IDX align, ST* sym, 02464 WN_OFFSET symOffset) 02465 { 02466 WN *ldid = WN_Ldid(Pointer_type, symOffset, sym, ST_type(sym)); 02467 02468 return WN_Iload(desc, offset, align, ldid); 02469 } 02470 02471 WN *WN_Cvt(TYPE_ID desc, TYPE_ID rtype, WN *l) 02472 { 02473 return WN_CreateExp1(OPR_CVT, rtype, desc, l); 02474 } 02475 02476 WN *WN_Trunc(TYPE_ID desc, TYPE_ID rtype, WN *l) 02477 { 02478 return WN_CreateExp1(OPR_TRUNC, rtype, desc, l); 02479 } 02480 02481 WN *WN_Rnd(TYPE_ID desc, TYPE_ID rtype, WN *l) 02482 { 02483 return WN_CreateExp1(OPR_RND, rtype, desc, l); 02484 } 02485 02486 WN *WN_Ceil(TYPE_ID desc, TYPE_ID rtype, WN *l) 02487 { 02488 return WN_CreateExp1(OPR_CEIL, rtype, desc, l); 02489 } 02490 02491 WN *WN_Floor(TYPE_ID desc, TYPE_ID rtype, WN *l) 02492 { 02493 return WN_CreateExp1(OPR_FLOOR, rtype, desc, l); 02494 } 02495 02496 WN *WN_Relational(OPERATOR opr, TYPE_ID rtype, WN *l, WN *r) 02497 { 02498 return WN_CreateExp2(opr, Boolean_type, rtype, l, r); 02499 } 02500 02501 WN *WN_ConstPowerOf2( TYPE_ID type, INT32 n) 02502 { 02503 02504 switch(type) 02505 { 02506 case MTYPE_F4: 02507 case MTYPE_F8: 02508 case MTYPE_F16: 02509 case MTYPE_FQ: 02510 case MTYPE_C4: 02511 case MTYPE_C8: 02512 case MTYPE_CQ: 02513 { 02514 double val = pow( 2.0, n); 02515 02516 return Make_Const (Host_To_Targ_Float (type, val)); 02517 } 02518 default: /* integral constant */ 02519 { 02520 INT64 one= 1; 02521 UINT64 val= one << n; 02522 Is_True(((0<=n) && (n <= 63)), ("invalid power of 2")); 02523 return WN_Intconst(type, val); 02524 } 02525 } 02526 02527 } 02528 02529 WN *WN_Floatconst( TYPE_ID type, double value) 02530 { 02531 02532 switch(type) 02533 { 02534 case MTYPE_F4: 02535 case MTYPE_F8: 02536 case MTYPE_FQ: 02537 case MTYPE_F16: 02538 case MTYPE_C4: 02539 case MTYPE_C8: 02540 case MTYPE_CQ: 02541 return Make_Const (Host_To_Targ_Float (type, value)); 02542 } 02543 Is_True(FALSE, ("expected floating const type")); 02544 return NULL; 02545 } 02546 02547 WN *WN_UVConst( TYPE_ID type) 02548 { 02549 switch(type) 02550 { 02551 case MTYPE_I1: 02552 case MTYPE_U1: 02553 return WN_Intconst( Mtype_TransferSign(type, MTYPE_I4), 0x5a); 02554 case MTYPE_I2: 02555 case MTYPE_U2: 02556 return WN_Intconst( Mtype_TransferSign(type, MTYPE_I4), 0x5a5a); 02557 case MTYPE_I4: 02558 case MTYPE_U4: 02559 return WN_Intconst(type, 0xfffa5a5a); 02560 case MTYPE_I8: 02561 case MTYPE_U8: 02562 return WN_Intconst(type, 0xfffa5a5afffa5a5all); 02563 case MTYPE_F4: 02564 case MTYPE_F8: 02565 case MTYPE_FQ: 02566 case MTYPE_F16: 02567 case MTYPE_C4: 02568 case MTYPE_C8: 02569 case MTYPE_CQ: 02570 return Make_Const (Host_To_Targ_UV(type)); 02571 case MTYPE_STR: 02572 case MTYPE_M: 02573 case MTYPE_V: 02574 case MTYPE_B: 02575 break; 02576 } 02577 02578 Is_True(FALSE, ("expected Uninitialized Variable const type")); 02579 return NULL; 02580 } 02581 02582 #define NBITMASK(x) ((1ll<<(x))-1) 02583 WN *WN_RotateIntconst(WN *tree, INT32 rotate) 02584 { 02585 TYPE_ID type= WN_rtype(tree); 02586 INT32 size= MTYPE_size_reg(type); 02587 UINT64 n= WN_const_val(tree); 02588 UINT64 t; 02589 02590 Is_True(WN_operator_is(tree, OPR_INTCONST), ("expected INTCONST")); 02591 02592 rotate= rotate % size; 02593 02594 if (rotate>0) 02595 { 02596 UINT64 t= n & NBITMASK(rotate); 02597 02598 n >>= rotate; 02599 n &= NBITMASK(size-rotate); 02600 n = n | (t << (size - rotate)); 02601 WN_const_val(tree)= n; 02602 } 02603 else if (rotate < 0) 02604 { 02605 rotate= -rotate; 02606 02607 t = n & ~NBITMASK(size - rotate); 02608 n <<= rotate; 02609 n &= NBITMASK(rotate); 02610 n = n | (t >> (size - rotate)); 02611 WN_const_val(tree)= n; 02612 } 02613 02614 return tree; 02615 } 02616 02617 WN *WN_Inverse(TYPE_ID type, WN *tree) 02618 { 02619 /* 02620 * there are no integer recips. 02621 * there are no quad emulations for recip either 02622 */ 02623 if (MTYPE_float(type)) 02624 { 02625 if (MTYPE_is_quad(type)==FALSE && Recip_Allowed == TRUE) 02626 { 02627 return WN_Recip(type, tree); 02628 } 02629 return WN_Div(type, WN_Floatconst(type, 1.0), tree); 02630 } 02631 return WN_Div(type, WN_Intconst(type, 1), tree); 02632 } 02633 02634 WN * 02635 WN_Lda (TYPE_ID rtype, WN_OFFSET ldaOffset, ST* sym, UINT field_id) 02636 { 02637 TY_IDX pty; 02638 02639 02640 TY_IDX ty; 02641 02642 if (ST_class (sym) == CLASS_BLOCK) 02643 ty = Make_Align_Type (MTYPE_To_TY(rtype), STB_align(sym)); 02644 else 02645 ty = ST_class (sym) == CLASS_FUNC ? ST_pu_type (sym) : ST_type(sym); 02646 Is_True (ty != 0, ("WN_lda(): NULL ty")); 02647 pty = Make_Pointer_Type (ty); 02648 02649 02650 return WN_CreateLda(OPR_LDA, rtype, MTYPE_V, ldaOffset, pty, sym, field_id); 02651 } 02652 02653 WN * 02654 WN_LdaLabel (TYPE_ID rtype, INT32 label_number) 02655 { 02656 WN *wn; 02657 TY_IDX ty; 02658 ty = Make_Pointer_Type (Be_Type_Tbl (MTYPE_V)); 02659 wn = WN_Create(OPR_LDA_LABEL, rtype, MTYPE_V, 0); 02660 WN_label_number (wn) = label_number; 02661 WN_set_ty (wn, ty); 02662 return wn; 02663 } /* WN_LdaLabel */ 02664 02665 WN *WN_Icall(TYPE_ID rtype, TYPE_ID desc, INT32 n, TY_IDX ty) 02666 { 02667 WN *call; 02668 02669 call = WN_Create(OPR_ICALL, rtype, desc, n); 02670 WN_set_ty(call,ty); 02671 02672 return call; 02673 } 02674 02675 /* --------------------------------------------------------------------- 02676 * 02677 * WN *WN_generic_call(OPERATOR opr, TYPE_ID rtype, TYPE_ID desc, INT32 n, ST *sym) 02678 * 02679 * generic for macros 02680 * WN_Call 02681 * WN_Piccall 02682 * 02683 * --------------------------------------------------------------------- 02684 */ 02685 WN * 02686 WN_generic_call (OPERATOR opr, TYPE_ID rtype, TYPE_ID desc, INT32 n, 02687 ST_IDX sym) 02688 { 02689 WN *call; 02690 02691 if (MTYPE_is_complex(rtype)) 02692 rtype = Mtype_complex_to_real(rtype); 02693 02694 if (MTYPE_is_complex(desc)) 02695 desc = Mtype_complex_to_real(desc); 02696 02697 call = WN_Create(opr, rtype, desc, n); 02698 WN_st_idx(call) = sym; 02699 02700 return call; 02701 } 02702 02703 void WN_CopyMap(WN *dst, WN_MAP map, const WN *src) 02704 { 02705 if ( map == WN_MAP_UNDEFINED ) 02706 return; 02707 02708 switch ( Current_Map_Tab->_kind[map] ) { 02709 case WN_MAP_KIND_VOIDP: 02710 WN_MAP_Set( map, dst, WN_MAP_Get( map, src ) ); 02711 break; 02712 case WN_MAP_KIND_INT32: 02713 WN_MAP32_Set( map, dst, WN_MAP32_Get( map, src ) ); 02714 break; 02715 case WN_MAP_KIND_INT64: 02716 WN_MAP64_Set( map, dst, WN_MAP64_Get( map, src ) ); 02717 break; 02718 default: 02719 Is_True( FALSE, ("WN_CopyMap: unknown map kind") ); 02720 } 02721 } 02722 02723 02724 /*---------------------------------------------------------------------- 02725 * WN_Int_Type_Conversion( WN *wn, TYPE_ID to_type ) 02726 * 02727 * returns original wn if no conversion is necessary 02728 * otherwise returns a CVT or CVTL WN as appropriate. 02729 *---------------------------------------------------------------------- 02730 */ 02731 02732 extern WN * 02733 WN_Int_Type_Conversion( WN *wn, TYPE_ID to_type ) 02734 { 02735 /* infer the "from" type from the given whirl */ 02736 TYPE_ID from_type = WN_rtype(wn); 02737 02738 Is_True( from_type == MTYPE_I1 || 02739 from_type == MTYPE_I2 || 02740 from_type == MTYPE_I4 || 02741 from_type == MTYPE_I8 || 02742 from_type == MTYPE_U1 || 02743 from_type == MTYPE_U2 || 02744 from_type == MTYPE_U4 || 02745 from_type == MTYPE_U8, 02746 ("WN_Int_Type_Conversion: bad from_type: %d\n", from_type) ); 02747 02748 /* quickie check */ 02749 if ( from_type == to_type ) 02750 return wn; 02751 02752 /* pretty long-winded way to do it, but it's cleaner and faster than 02753 * any other way I could figure out. 02754 */ 02755 switch ( to_type ) { 02756 case MTYPE_I1: 02757 switch ( from_type ) { 02758 case MTYPE_I1: 02759 return wn; 02760 case MTYPE_I2: 02761 case MTYPE_I4: 02762 case MTYPE_U1: 02763 case MTYPE_U2: 02764 case MTYPE_U4: 02765 return WN_CreateCvtl( OPC_I4CVTL, 8, wn ); 02766 case MTYPE_I8: 02767 case MTYPE_U8: 02768 return WN_CreateCvtl( OPC_I8CVTL, 8, wn ); 02769 } /* end to_type = I1 */ 02770 case MTYPE_I2: 02771 switch ( from_type ) { 02772 case MTYPE_I1: 02773 case MTYPE_I2: 02774 return wn; 02775 case MTYPE_I4: 02776 case MTYPE_U1: 02777 case MTYPE_U2: 02778 case MTYPE_U4: 02779 return WN_CreateCvtl( OPC_I4CVTL, 16, wn ); 02780 case MTYPE_I8: 02781 case MTYPE_U8: 02782 return WN_CreateCvtl( OPC_I8CVTL, 16, wn ); 02783 } /* end to_type = I2 */ 02784 case MTYPE_I4: 02785 switch ( from_type ) { 02786 case MTYPE_I1: 02787 case MTYPE_I2: 02788 case MTYPE_I4: 02789 case MTYPE_U1: 02790 case MTYPE_U2: 02791 case MTYPE_U4: 02792 return wn; 02793 case MTYPE_I8: 02794 case MTYPE_U8: 02795 return WN_Cvt( from_type, to_type, wn ); 02796 } /* end to_type = I4 */ 02797 case MTYPE_I8: 02798 switch ( from_type ) { 02799 case MTYPE_I1: 02800 case MTYPE_I2: 02801 case MTYPE_I4: 02802 case MTYPE_U1: 02803 case MTYPE_U2: 02804 case MTYPE_U4: 02805 return WN_Cvt( from_type, to_type, wn ); 02806 case MTYPE_I8: 02807 case MTYPE_U8: 02808 return wn; 02809 } /* end to_type = I8 */ 02810 case MTYPE_U1: 02811 switch ( from_type ) { 02812 case MTYPE_I1: 02813 return wn; 02814 case MTYPE_I2: 02815 case MTYPE_I4: 02816 case MTYPE_U1: 02817 case MTYPE_U2: 02818 case MTYPE_U4: 02819 return WN_CreateCvtl( OPC_U4CVTL, 8, wn ); 02820 case MTYPE_I8: 02821 case MTYPE_U8: 02822 return WN_CreateCvtl( OPC_U8CVTL, 8, wn ); 02823 } /* end to_type = U1 */ 02824 case MTYPE_U2: 02825 switch ( from_type ) { 02826 case MTYPE_I1: 02827 case MTYPE_I2: 02828 case MTYPE_I4: 02829 case MTYPE_U4: 02830 return WN_CreateCvtl( OPC_U4CVTL, 16, wn ); 02831 case MTYPE_U1: 02832 case MTYPE_U2: 02833 return wn; 02834 case MTYPE_I8: 02835 case MTYPE_U8: 02836 return WN_CreateCvtl( OPC_U8CVTL, 16, wn ); 02837 } /* end to_type = U2 */ 02838 case MTYPE_U4: 02839 switch ( from_type ) { 02840 case MTYPE_I1: 02841 case MTYPE_I2: 02842 case MTYPE_I4: 02843 case MTYPE_U1: 02844 case MTYPE_U2: 02845 case MTYPE_U4: 02846 return wn; 02847 case MTYPE_I8: 02848 case MTYPE_U8: 02849 return WN_Cvt( from_type, to_type, wn ); 02850 } /* end to_type = U4 */ 02851 case MTYPE_U8: 02852 switch ( from_type ) { 02853 case MTYPE_I1: 02854 case MTYPE_I2: 02855 case MTYPE_I4: 02856 case MTYPE_U1: 02857 case MTYPE_U2: 02858 case MTYPE_U4: 02859 return WN_Cvt( from_type, to_type, wn ); 02860 case MTYPE_I8: 02861 case MTYPE_U8: 02862 return wn; 02863 } /* end to_type = U8 */ 02864 default: 02865 FmtAssert( FALSE, 02866 ("WN_Int_Type_Conversion: bad to_type: %d\n", to_type) ); 02867 return wn; 02868 } 02869 } 02870 02871 /*---------------------------------------------------------------------- 02872 * WN_Float_Type_Conversion( WN *wn, TYPE_ID to_type ) 02873 * 02874 * returns original wn if no conversion is necessary 02875 * otherwise returns a CVT as appropriate. 02876 *---------------------------------------------------------------------- 02877 */ 02878 02879 extern WN * 02880 WN_Float_Type_Conversion( WN *wn, TYPE_ID to_type ) 02881 { 02882 /* infer the "from" type from the given whirl */ 02883 TYPE_ID from_type = WN_rtype(wn); 02884 02885 Is_True( from_type == MTYPE_F4 || 02886 from_type == MTYPE_F8 || 02887 from_type == MTYPE_FQ, 02888 ("WN_Float_Type_Conversion: unexpected from_type: %d\n",from_type)); 02889 Is_True( to_type == MTYPE_F4 || 02890 to_type == MTYPE_F8 || 02891 to_type == MTYPE_FQ, 02892 ("WN_Float_Type_Conversion: unexpected to_type: %d\n", to_type) ); 02893 02894 /* quickie check */ 02895 if ( from_type == to_type ) 02896 return wn; 02897 else 02898 return WN_Cvt( from_type, to_type, wn ); 02899 } 02900 02901 /*---------------------------------------------------------------------- 02902 * WN_Type_Conversion( WN *wn, TYPE_ID to_type ) 02903 * 02904 * returns original wn if no conversion is necessary 02905 * otherwise returns a CVT or CVTL WN as appropriate. 02906 * 02907 * NOTE that it may be necessary to add multiple conversions to get 02908 * from/to the given types, but this function handles that for you. 02909 *---------------------------------------------------------------------- 02910 */ 02911 02912 extern WN * 02913 WN_Type_Conversion( WN *wn, TYPE_ID to_type ) 02914 { 02915 /* infer the "from" type from the given whirl */ 02916 TYPE_ID from_type = WN_rtype(wn); 02917 BOOL from_flt,to_flt; /* is type a floating type? */ 02918 02919 /* quickie check of no-op */ 02920 if ( from_type == to_type ) 02921 return wn; 02922 02923 Is_True( from_type == MTYPE_I1 || 02924 from_type == MTYPE_I2 || 02925 from_type == MTYPE_I4 || 02926 from_type == MTYPE_I8 || 02927 from_type == MTYPE_U1 || 02928 from_type == MTYPE_U2 || 02929 from_type == MTYPE_U4 || 02930 from_type == MTYPE_U8 || 02931 from_type == MTYPE_F4 || 02932 from_type == MTYPE_F8 || 02933 from_type == MTYPE_FQ, 02934 ("WN_Type_Conversion: unexpected from_type: %d\n", from_type) ); 02935 Is_True( to_type == MTYPE_I1 || 02936 to_type == MTYPE_I2 || 02937 to_type == MTYPE_I4 || 02938 to_type == MTYPE_I8 || 02939 to_type == MTYPE_U1 || 02940 to_type == MTYPE_U2 || 02941 to_type == MTYPE_U4 || 02942 to_type == MTYPE_U8 || 02943 to_type == MTYPE_F4 || 02944 to_type == MTYPE_F8 || 02945 to_type == MTYPE_FQ, 02946 ("WN_Type_Conversion: unexpected to_type: %d\n", to_type) ); 02947 02948 from_flt = MTYPE_is_float(from_type); 02949 to_flt = MTYPE_is_float(to_type); 02950 02951 /* to or from floating point type? */ 02952 if ( from_flt ) { 02953 if ( to_flt ) { 02954 /* both are floating point types, so bypass heavy-duty call */ 02955 return WN_Cvt( from_type, to_type, wn ); 02956 } 02957 02958 /* from float to int */ 02959 if ( MTYPE_size_min(to_type) >= 32/* bits */ ) { 02960 /* appropriately sized target, so just do the conversion */ 02961 return WN_Cvt( from_type, to_type, wn ); 02962 } 02963 else { 02964 /* need to first convert to 4-byte integer with correct sign */ 02965 TYPE_ID tmp_to_type = Mtype_TransferSign( to_type, MTYPE_I4 ); 02966 WN *tmp_wn = WN_Cvt( from_type, tmp_to_type, wn ); 02967 /* ok, we have a 4-byte integer, so let the all-integer 02968 * code handle the conversion from this 4-byte thing to the 02969 * ultimate type 02970 */ 02971 return WN_Int_Type_Conversion( tmp_wn, to_type ); 02972 } 02973 } 02974 else if ( to_flt ) { 02975 /* from int to float */ 02976 if ( MTYPE_size_min(from_type) >= 32/* bits */ ) { 02977 /* appropriately sized source, so just do the conversion */ 02978 return WN_Cvt( from_type, to_type, wn ); 02979 } 02980 else { 02981 /* need to first convert to appropriately sized integer */ 02982 TYPE_ID tmp_to_type = Mtype_TransferSign( to_type, MTYPE_I4 ); 02983 WN *tmp_wn = WN_Int_Type_Conversion( wn, tmp_to_type ); 02984 02985 /* and then convert that to float */ 02986 return WN_Cvt( tmp_to_type, to_type, tmp_wn ); 02987 } 02988 } 02989 else { 02990 /* all integers */ 02991 return WN_Int_Type_Conversion( wn, to_type ); 02992 } 02993 } 02994 02995 02996 WN *WN_Iloadx(TYPE_ID rtype, TY_IDX ty, TY_IDX addr_ty, WN *base, WN *index) 02997 { 02998 return WN_CreateIloadx(OPR_ILOADX, rtype, MTYPE_V, ty, addr_ty, base, index); 02999 } 03000 03001 03002 WN *WN_Istorex(TYPE_ID desc, TY_IDX ty, WN *value, WN *base, WN *index) 03003 { 03004 return WN_CreateIstorex(OPR_ISTOREX, MTYPE_V, desc, ty, value, base, index); 03005 } 03006 03007 WN *WN_LdaString(char *str, WN_OFFSET ldaOffset, INT32 len) 03008 { 03009 TCON tc; 03010 ST *st; 03011 03012 tc = Host_To_Targ_String(MTYPE_STRING, str, len); 03013 st = Gen_String_Sym(&tc, MTYPE_To_TY(MTYPE_STRING), FALSE); 03014 return WN_Lda (Pointer_type, ldaOffset, st); 03015 } 03016 03017 03018 WN* 03019 WN_CreateAffirm (WN* condition) 03020 { 03021 WN* wn; 03022 wn = WN_Create (OPR_AFFIRM, MTYPE_V, MTYPE_V, 1); 03023 WN_kid0(wn) = condition; 03024 return wn; 03025 } /* WN_CreateAffirm */ 03026 03027 WN* 03028 WN_CreateAlloca (WN* size) 03029 { 03030 WN* wn; 03031 wn = WN_Create (OPR_ALLOCA, Pointer_Mtype, MTYPE_V, 1); 03032 WN_kid0(wn) = size; 03033 return wn; 03034 } /* WN_CreateAlloca */ 03035 03036 WN* 03037 WN_CreateDealloca (INT32 nkids) 03038 { 03039 WN* wn; 03040 wn = WN_Create (OPR_DEALLOCA, MTYPE_V, MTYPE_V, nkids); 03041 return wn; 03042 } /* WN_CreateDealloca */ 03043 03044 WN* 03045 WN_CreateLdma (TYPE_ID rtype, WN_OFFSET offset, TY_IDX ty, ST_IDX st, 03046 UINT field_id) 03047 { 03048 WN *wn; 03049 03050 wn = WN_Create (OPR_LDMA, rtype, MTYPE_V, 0); 03051 WN_load_offset(wn) = offset; 03052 WN_st_idx(wn) = st; 03053 WN_set_ty(wn,ty); 03054 WN_set_field_id(wn, field_id); 03055 03056 return(wn); 03057 } /* WN_CreateLdma */ 03058 03059 03060 // Traverse the tree and set the address saved bits appropriately. 03061 03062 void 03063 WN_set_st_addr_saved (WN* wn) 03064 { 03065 ST* st; 03066 03067 switch (WN_operator (wn)) { 03068 03069 case OPR_LDA: 03070 case OPR_LDMA: 03071 03072 st = WN_st(wn); 03073 03074 if ( ST_class(st) == CLASS_VAR || ST_class(st) == CLASS_FUNC ) 03075 Set_ST_addr_saved(st); 03076 break; 03077 03078 case OPR_ARRAY: 03079 03080 WN_set_st_addr_saved (WN_kid0(wn)); 03081 break; 03082 03083 case OPR_LDID: 03084 case OPR_CONST: 03085 case OPR_ILOAD: 03086 case OPR_MLOAD: 03087 case OPR_INTCONST: 03088 case OPR_INTRINSIC_OP: 03089 case OPR_CALL: 03090 case OPR_EQ: 03091 case OPR_NE: 03092 case OPR_GT: 03093 case OPR_GE: 03094 case OPR_LT: 03095 case OPR_LE: 03096 case OPR_ALLOCA: 03097 03098 break; 03099 03100 case OPR_EVAL: 03101 case OPR_TAS: 03102 case OPR_CVT: 03103 case OPR_CVTL: 03104 case OPR_NEG: 03105 case OPR_ABS: 03106 case OPR_SQRT: 03107 case OPR_REALPART: 03108 case OPR_IMAGPART: 03109 case OPR_PAREN: 03110 case OPR_RND: 03111 case OPR_TRUNC: 03112 case OPR_CEIL: 03113 case OPR_FLOOR: 03114 case OPR_BNOT: 03115 case OPR_LNOT: 03116 case OPR_LOWPART: 03117 case OPR_HIGHPART: 03118 case OPR_MINPART: 03119 case OPR_MAXPART: 03120 case OPR_RECIP: 03121 case OPR_RSQRT: 03122 case OPR_PARM: 03123 case OPR_OPTPARM: 03124 03125 WN_set_st_addr_saved (WN_kid0(wn)); 03126 break; 03127 03128 case OPR_CSELECT: 03129 03130 WN_set_st_addr_saved (WN_kid1(wn)); 03131 WN_set_st_addr_saved (WN_kid2(wn)); 03132 break; 03133 03134 case OPR_SELECT: 03135 case OPR_ADD: 03136 case OPR_SUB: 03137 case OPR_MPY: 03138 case OPR_DIV: 03139 case OPR_MOD: 03140 case OPR_REM: 03141 case OPR_DIVREM: 03142 case OPR_MAX: 03143 case OPR_MIN: 03144 case OPR_MINMAX: 03145 case OPR_BAND: 03146 case OPR_BIOR: 03147 case OPR_BXOR: 03148 case OPR_BNOR: 03149 case OPR_LAND: 03150 case OPR_LIOR: 03151 case OPR_SHL: 03152 case OPR_ASHR: 03153 case OPR_LSHR: 03154 case OPR_COMPLEX: 03155 case OPR_HIGHMPY: 03156 03157 WN_set_st_addr_saved (WN_kid0(wn)); 03158 WN_set_st_addr_saved (WN_kid1(wn)); 03159 break; 03160 03161 case OPR_CAND: 03162 case OPR_CIOR: 03163 03164 break; 03165 03166 case OPR_COMMA: 03167 03168 WN_set_st_addr_saved (WN_kid1(wn)); 03169 break; 03170 03171 case OPR_RCOMMA: 03172 03173 WN_set_st_addr_saved (WN_kid0(wn)); 03174 break; 03175 03176 default: 03177 03178 Fail_FmtAssertion ("WN_set_st_addr_saved not implemented for %s", 03179 OPERATOR_name (WN_operator (wn))); 03180 break; 03181 } 03182 } /* WN_set_st_addr_saved */ 03183 03184 // Traverse the tree and check whether it has side effects. 03185 03186 BOOL 03187 WN_has_side_effects (const WN* wn) 03188 { 03189 switch (WN_operator (wn)) { 03190 03191 case OPR_ABS: 03192 case OPR_BNOT: 03193 case OPR_CEIL: 03194 case OPR_CVT: 03195 case OPR_CVTL: 03196 case OPR_FIRSTPART: 03197 case OPR_FLOOR: 03198 case OPR_HIGHPART: 03199 case OPR_LOWPART: 03200 case OPR_LNOT: 03201 case OPR_MAXPART: 03202 case OPR_MINPART: 03203 case OPR_NEG: 03204 case OPR_PAREN: 03205 case OPR_PARM: 03206 case OPR_OPTPARM: 03207 case OPR_RND: 03208 case OPR_RSQRT: 03209 case OPR_RECIP: 03210 case OPR_SECONDPART: 03211 case OPR_SQRT: 03212 case OPR_TAS: 03213 case OPR_TRUNC: 03214 case OPR_EXTRACT_BITS: 03215 03216 return WN_has_side_effects (WN_kid0(wn)); 03217 03218 case OPR_ADD: 03219 case OPR_ASHR: 03220 case OPR_BAND: 03221 case OPR_BIOR: 03222 case OPR_BXOR: 03223 case OPR_BNOR: 03224 case OPR_DIV: 03225 case OPR_DIVREM: 03226 case OPR_EQ: 03227 case OPR_GT: 03228 case OPR_GE: 03229 case OPR_HIGHMPY: 03230 case OPR_LAND: 03231 case OPR_LE: 03232 case OPR_LIOR: 03233 case OPR_LSHR: 03234 case OPR_LT: 03235 case OPR_MAX: 03236 case OPR_MIN: 03237 case OPR_MINMAX: 03238 case OPR_MOD: 03239 case OPR_MPY: 03240 case OPR_NE: 03241 case OPR_PAIR: 03242 case OPR_REM: 03243 case OPR_SHL: 03244 case OPR_SUB: 03245 case OPR_XMPY: 03246 case OPR_COMPOSE_BITS: 03247 03248 if (WN_has_side_effects (WN_kid0(wn))) 03249 return TRUE; 03250 03251 return WN_has_side_effects (WN_kid1(wn)); 03252 03253 case OPR_SELECT: 03254 case OPR_MADD: 03255 case OPR_MSUB: 03256 case OPR_NMADD: 03257 case OPR_NMSUB: 03258 03259 if (WN_has_side_effects (WN_kid0(wn))) 03260 return TRUE; 03261 03262 if (WN_has_side_effects (WN_kid1(wn))) 03263 return TRUE; 03264 03265 return WN_has_side_effects (WN_kid2(wn)); 03266 03267 case OPR_ARRAY: 03268 03269 if (WN_has_side_effects (WN_kid0(wn))) 03270 return TRUE; 03271 03272 else { 03273 03274 INT32 n = (WN_kid_count (wn)) >> 1; 03275 03276 for (INT32 i = n + 1; i <= 2 * n; i++) { 03277 03278 if (WN_has_side_effects (WN_kid (wn, i))) 03279 return TRUE; 03280 } 03281 03282 return FALSE; 03283 } 03284 03285 case OPR_INTRINSIC_OP: { 03286 03287 INT32 n = WN_kid_count (wn); 03288 03289 for (INT32 i = 0; i < n; i++) { 03290 03291 if (WN_has_side_effects (WN_kid (wn, i))) 03292 return TRUE; 03293 } 03294 03295 return FALSE; 03296 } 03297 03298 case OPR_LDID: 03299 03300 if (TY_is_volatile (WN_ty(wn))) 03301 return (TRUE); 03302 03303 return FALSE; 03304 03305 case OPR_ILOAD: 03306 case OPR_ILOADX: 03307 case OPR_ILDBITS: 03308 03309 if (TY_is_volatile (WN_ty(wn)) || TY_is_volatile(WN_load_addr_ty(wn))) 03310 return (TRUE); 03311 03312 return WN_has_side_effects (WN_kid0(wn)); 03313 03314 case OPR_MLOAD: 03315 03316 if (TY_is_volatile (WN_ty(wn))) 03317 return (TRUE); 03318 03319 if (WN_has_side_effects (WN_kid0(wn))) 03320 return TRUE; 03321 03322 return WN_has_side_effects (WN_kid1(wn)); 03323 03324 case OPR_CONST: 03325 case OPR_IDNAME: 03326 case OPR_INTCONST: 03327 case OPR_LDA: 03328 case OPR_LDMA: 03329 03330 return FALSE; 03331 03332 case OPR_ALLOCA: 03333 03334 return TRUE; 03335 03336 case OPR_CAND: 03337 case OPR_CIOR: 03338 03339 return TRUE; 03340 03341 case OPR_COMMA: 03342 case OPR_RCOMMA: 03343 03344 return TRUE; 03345 03346 case OPR_CSELECT: 03347 03348 return TRUE; 03349 03350 default: 03351 03352 Fail_FmtAssertion ("WN_has_side_effects not implemented for %s", 03353 OPERATOR_name (WN_operator (wn))); 03354 return FALSE; 03355 } 03356 } /* WN_has_side_effects */ 03357 03358 03359 WN * 03360 WN_Rrotate (TYPE_ID desc, WN *src, WN *cnt) 03361 { 03362 Set_PU_has_very_high_whirl (Get_Current_PU ()); 03363 return WN_CreateExp2 (OPR_RROTATE, Mtype_comparison (desc), desc, src, cnt); 03364 } /* WN_Rotate */