Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
wn.cxx
Go to the documentation of this file.
00001 /*
00002 
00003   Copyright (C) 2000, 2001 Silicon Graphics, Inc.  All Rights Reserved.
00004 
00005   This program is free software; you can redistribute it and/or modify it
00006   under the terms of version 2 of the GNU General Public License as
00007   published by the Free Software Foundation.
00008 
00009   This program is distributed in the hope that it would be useful, but
00010   WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00012 
00013   Further, this software is distributed without any warranty that it is
00014   free of the rightful claim of any third person regarding infringement 
00015   or the like.  Any license provided herein, whether implied or 
00016   otherwise, applies only to this software file.  Patent licenses, if 
00017   any, provided herein do not apply to combinations of this program with 
00018   other software, or any other product whatsoever.  
00019 
00020   You should have received a copy of the GNU General Public License along
00021   with this program; if not, write the Free Software Foundation, Inc., 59
00022   Temple Place - Suite 330, Boston MA 02111-1307, USA.
00023 
00024   Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pky,
00025   Mountain View, CA 94043, or:
00026 
00027   http://www.sgi.com
00028 
00029   For further information regarding this notice, see:
00030 
00031   http://oss.sgi.com/projects/GenInfo/NoticeExplan
00032 
00033 */
00034 
00035 
00036 /* ====================================================================
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 */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines