Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
wn_verifier.cxx
Go to the documentation of this file.
00001 /*
00002 
00003   Copyright (C) 2000, 2001 Silicon Graphics, Inc.  All Rights Reserved.
00004 
00005   This program is free software; you can redistribute it and/or modify it
00006   under the terms of version 2 of the GNU General Public License as
00007   published by the Free Software Foundation.
00008 
00009   This program is distributed in the hope that it would be useful, but
00010   WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00012 
00013   Further, this software is distributed without any warranty that it is
00014   free of the rightful claim of any third person regarding infringement 
00015   or the like.  Any license provided herein, whether implied or 
00016   otherwise, applies only to this software file.  Patent licenses, if 
00017   any, provided herein do not apply to combinations of this program with 
00018   other software, or any other product whatsoever.  
00019 
00020   You should have received a copy of the GNU General Public License along
00021   with this program; if not, write the Free Software Foundation, Inc., 59
00022   Temple Place - Suite 330, Boston MA 02111-1307, USA.
00023 
00024   Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pky,
00025   Mountain View, CA 94043, or:
00026 
00027   http://www.sgi.com
00028 
00029   For further information regarding this notice, see:
00030 
00031   http://oss.sgi.com/projects/GenInfo/NoticeExplan
00032 
00033 */
00034 
00035 
00036 //-*-c++-*-
00037 // ====================================================================
00038 // ====================================================================
00039 //
00040 //
00041 // Revision history:
00042 //  8-20-97 naftulin - Original Version
00043 //
00044 // Description:
00045 // Verifies a WHIRL tree is consistent.
00046 //
00047 // ====================================================================
00048 // ====================================================================
00049 
00050 /**********************************************************************
00051  * FILE:             wn_verifier.cxx
00052  * PROJECT:          WHIRL Verifier
00053  * PROGRAMMER:       Henry Naftulin ([email protected])
00054  * FUNCTION TO CALL: BOOL WN_verifier(WN *root);
00055  * DESCRIPTION:
00056  * This module verifies several basic assumptions about the WHIRL:
00057  *  1) That whirl is a tree (Is_WHIRL_tree)
00058  *  2) That blocks first and last nodes have appropriate
00059  *          pointers set to NULL (Proper_Block_Structure)
00060  *  3) That each LDID with return registers (2,3,32.34) has 
00061  *          a coresponding CALL statement (Call_parent_LDID)
00062  *  4) That PARM nodes parents are CALL nodes 
00063  *         (Param_parent_is_Call)
00064  *  5) That CALLs children are all PARM nodes
00065  *         (Call_children_are_PARM)
00066  *  6) That WHIRL nodes' opcode is legal (Is_legal_wn_opcode)
00067  *  7) Checks that nodes that suppose not to have a NULL ty
00068  *         indeed have valid ty (TY_is_not_NULL)
00069  *  8) Checks that nodes that suppose not to have a NULL st
00070  *         indeed have valid st (ST_is_not_NULL)
00071  *  9) Checks certain properties of the st of STID
00072  *         (STID_check_st_class)
00073  * 10) Checks it ty of LDA is not NULL and its type is a pointer
00074  *         (LDA_ty_not_NULL)
00075  * 11) Checks whether pragma that it supports are enclosed
00076  *         (* like parenthezation problem, or html tags 
00077  *            enclosing *) (Are_enclosed_pragmas)
00078  * 12) Checks that the TY and the field ids are consistent
00079  **********************************************************************/
00080 
00081 #ifdef USE_PCH
00082 #include "be_com_pch.h"
00083 #endif /* USE_PCH */
00084 #pragma hdrstop
00085 #define USE_STANDARD_TYPES
00086 
00087 #include <algorithm>
00088 #include <vector>
00089 #include <stack>
00090 
00091 using namespace std;
00092 
00093 #include <stdlib.h>
00094 #include "defs.h"
00095 #include "stab.h"
00096 #include "wn.h"
00097 #include "wn_map.h"
00098 #include "wn_util.h"
00099 #include "mempool.h"
00100 #include "tracing.h"
00101 #include "targ_sim.h"
00102 #include "wn_pragmas.h"
00103 #include "ir_reader.h"          // fdump_tree
00104 #include "cxx_template.h"
00105 #include "cxx_hash.h"
00106 #include "config_asm.h"         // for User_Label_Number_Format
00107 #include "glob.h"
00108 #include "pu_info.h"
00109 
00110 // Turning this switch to turn the debuging messages of the Verifier
00111 
00112 #define Verifier_DEBUG 0
00113 
00114 // This structure contains pragmas name and wn_parent
00115 // pointer. It is used for cheking pragma scoping.
00116 
00117 struct pragma_stack_type
00118 {
00119   WN           *parent_wn;
00120   WN_PRAGMA_ID pragma_id;
00121 };
00122 
00123 
00124 // The following structure maps each of the supported
00125 // PRAGMA_ID's to either pushing on the stack operation
00126 // or matching the top of the stack with the pragma_starting_id
00127 // Just like in parentization: '(' needs to be pushed,
00128 // ')' - requres that the top of the stack should be '(' 
00129 
00130 #define NUM_PRAGMAS_SUPPORTED 26
00131 
00132 struct pragma_mapped_ids
00133 {
00134   WN_PRAGMA_ID pragma_id;  
00135   BOOL         push;               // Do I need to push this ID on stack
00136   WN_PRAGMA_ID pragma_starting_id; // If not what ID should I expect on top
00137 };                                 // of the stack
00138 
00139 
00140 /*---------------------------------------------------------------------
00141  * The structure of the pragma_supported array is:
00142  * { pragma_name, push_it?, associated pragma on the top ot the stack }
00143  *---------------------------------------------------------------------*/
00144  
00145 pragma_mapped_ids pragmas_supported[NUM_PRAGMAS_SUPPORTED] =
00146 {
00147   { WN_PRAGMA_INLINE_BODY_START,      TRUE,  WN_PRAGMA_UNDEFINED },
00148   { WN_PRAGMA_INLINE_BODY_END,        FALSE, WN_PRAGMA_INLINE_BODY_START },
00149   { WN_PRAGMA_ENTER_GATE,             TRUE,  WN_PRAGMA_UNDEFINED },
00150   { WN_PRAGMA_EXIT_GATE,              FALSE, WN_PRAGMA_ENTER_GATE },
00151   { WN_PRAGMA_CRITICAL_SECTION_BEGIN, TRUE,  WN_PRAGMA_UNDEFINED },
00152   { WN_PRAGMA_CRITICAL_SECTION_END,   FALSE, WN_PRAGMA_CRITICAL_SECTION_BEGIN },
00153   { WN_PRAGMA_PARALLEL_BEGIN,         TRUE,  WN_PRAGMA_UNDEFINED },
00154   { WN_PRAGMA_PARALLEL_END,           FALSE, WN_PRAGMA_PARALLEL_BEGIN },
00155   { WN_PRAGMA_PDO_BEGIN,              TRUE,  WN_PRAGMA_UNDEFINED },
00156   { WN_PRAGMA_PDO_END,                FALSE, WN_PRAGMA_PDO_BEGIN },
00157   { WN_PRAGMA_PSECTION_BEGIN,         TRUE,  WN_PRAGMA_UNDEFINED },
00158   { WN_PRAGMA_PSECTION_END,           FALSE, WN_PRAGMA_PSECTION_BEGIN },
00159   { WN_PRAGMA_SINGLE_PROCESS_BEGIN,   TRUE,  WN_PRAGMA_UNDEFINED },
00160   { WN_PRAGMA_SINGLE_PROCESS_END,     FALSE, WN_PRAGMA_SINGLE_PROCESS_BEGIN },
00161   { WN_PRAGMA_FLIST_SKIP_BEGIN,       TRUE,  WN_PRAGMA_UNDEFINED },
00162   { WN_PRAGMA_FLIST_SKIP_END,         FALSE, WN_PRAGMA_FLIST_SKIP_BEGIN },
00163   { WN_PRAGMA_CLIST_SKIP_BEGIN,       TRUE,  WN_PRAGMA_UNDEFINED },
00164   { WN_PRAGMA_CLIST_SKIP_END,         FALSE, WN_PRAGMA_CLIST_SKIP_BEGIN },
00165   { WN_PRAGMA_INDEPENDENT_BEGIN,      TRUE,  WN_PRAGMA_UNDEFINED },
00166   { WN_PRAGMA_INDEPENDENT_END,        FALSE, WN_PRAGMA_INDEPENDENT_BEGIN },
00167   { WN_PRAGMA_CRI_CASE,               TRUE,  WN_PRAGMA_UNDEFINED },
00168   { WN_PRAGMA_CRI_ENDCASE,            FALSE, WN_PRAGMA_CRI_CASE },
00169   { WN_PRAGMA_CRI_GUARD,              TRUE,  WN_PRAGMA_UNDEFINED },
00170   { WN_PRAGMA_CRI_ENDGUARD,           FALSE, WN_PRAGMA_CRI_GUARD },
00171   { WN_PRAGMA_CRI_PARALLEL,           TRUE,  WN_PRAGMA_UNDEFINED },
00172   { WN_PRAGMA_CRI_ENDPARALLEL,        FALSE, WN_PRAGMA_CRI_PARALLEL}
00173 };
00174 
00175 class WN_Verifier{
00176   private:
00177 
00178     /*------------------------------------------------------
00179      * Private variable section
00180      *-----------------------------------------------------*/
00181 
00182     MEM_POOL _mem_pool;
00183     WN_MAP   _map;
00184     BOOL     _is_tree_OK;
00185     WN      *_func;
00186     stack< pragma_stack_type > _pragma_stack; 
00187    
00188     /*--------------------------------------------------------
00189      * Private function section
00190      * All those 4 functions support CALL_parent_LDID
00191      *--------------------------------------------------------*/
00192  
00193     BOOL     Is_return_register_of_call(WN *call_wn, PREG_NUM preg);
00194     WN      *One_level_removed_node(WN *parent_wn,OPERATOR opr);
00195     BOOL     Is_dedicated_return_register(WN_OFFSET preg);
00196  
00197  protected:
00198 
00199     /*--------------------------------------------------------
00200      * Protected function section
00201      *--------------------------------------------------------*/
00202 
00203     BOOL     Is_WHIRL_tree(WN *wn, WN *parent); 
00204     BOOL     CALL_parent_LDID(WN *wn, WN *parent_wn);
00205     BOOL     Proper_Block_Structure(WN *wn,OPCODE op);
00206     BOOL     Param_parent_is_Call(WN *wn,WN *parent_wn);
00207     BOOL     Call_children_are_PARM(WN *wn);
00208     BOOL     Is_legal_wn_opcode(OPCODE opc);
00209     BOOL     LDA_ty_not_NULL(WN *wn);
00210     BOOL     STID_check_st_class(WN *wn);
00211     BOOL     TY_is_not_NULL(WN *wn, OPCODE op);
00212     BOOL     ST_is_not_NULL(WN *wn, OPCODE op); 
00213     BOOL     Load_addr_TY_is_not_NULL(WN *wn, OPCODE op); 
00214     BOOL     Are_enclosed_pragmas(WN *wn, WN *parent_wn);
00215     BOOL     Field_id_valid (WN* wn);
00216 
00217 
00218   public:
00219              WN_Verifier(WN *wn);
00220             ~WN_Verifier();
00221     BOOL     WN_traverse_tree(WN *wn, WN *parent_wn);
00222 };
00223 
00224 /*-----------------------------------------------------------
00225  * This function initializes the memory map for later use in
00226  * Is_WHIRL_tree routine.
00227  *-----------------------------------------------------------*/
00228 
00229 
00230 WN_Verifier::WN_Verifier(WN *wn)
00231 {
00232   // Create and initialize memory pool
00233 
00234   MEM_POOL_Initialize(&_mem_pool, "Verifier_Pool", FALSE);
00235   MEM_POOL_Push(&_mem_pool);
00236   _map = WN_MAP_Create(&_mem_pool);
00237   
00238   // Empty WHIRL tree is OK
00239 
00240   _is_tree_OK=TRUE;
00241 
00242   if (WN_operator(wn) == OPR_FUNC_ENTRY)
00243     _func = wn;
00244   else
00245     _func = NULL;
00246 }
00247 
00248 // The destructor clears and gets rid of the map
00249 WN_Verifier::~WN_Verifier(void)
00250 {
00251   // Clear and dispose of the memory map
00252 
00253   WN_MAP_Delete(_map);
00254   MEM_POOL_Pop(&_mem_pool);
00255   MEM_POOL_Delete(&_mem_pool);
00256 }
00257 
00258 /*----------------------------------------------------------
00259  * This is the main driver of the verifier. It traverses the
00260  * tree calling appropriate verification procedures when the
00261  * needed.
00262  *----------------------------------------------------------*/
00263 
00264 
00265 BOOL
00266 WN_Verifier::WN_traverse_tree(WN *wn, WN *parent_wn)
00267 {
00268   OPCODE op;
00269         
00270   if (wn)
00271   {
00272     op = WN_opcode(wn);
00273  
00274     // Check if WHIRL is a tree.
00275     _is_tree_OK &= Is_WHIRL_tree(wn, parent_wn);
00276 
00277     // Call appropriate verification procedures when you
00278     // see the opcodes listed below
00279     switch(OPCODE_operator(op))
00280     {
00281       case OPR_FUNC_ENTRY:
00282       case OPR_XGOTO:
00283       case OPR_ALTENTRY:
00284             // check that TY should not be null 
00285             _is_tree_OK &= ST_is_not_NULL(wn,op);
00286             break;
00287       case OPR_LDID:
00288             // check if the instruction before
00289             // the parent of LDID is indeed CALL
00290             // Also check if ST and TY aren't NULLs
00291             _is_tree_OK &= CALL_parent_LDID(wn, parent_wn);
00292             _is_tree_OK &= TY_is_not_NULL(wn,op);
00293             _is_tree_OK &= ST_is_not_NULL(wn,op);
00294             _is_tree_OK &= Field_id_valid(wn);
00295             break;
00296       case OPR_LDA:
00297             // TY of LDA has to be not null - check that
00298             // and it also has to be a pointer type.
00299             // Also check that ST is not NULL
00300             _is_tree_OK &= LDA_ty_not_NULL(wn);
00301             _is_tree_OK &= ST_is_not_NULL(wn,op);
00302             break;
00303       case OPR_IDNAME:
00304       case OPR_CONST:
00305            // Check that ST is not NULL
00306            _is_tree_OK &= ST_is_not_NULL(wn,op);
00307            break;
00308       case OPR_STID:
00309             // Here check the class of the ST
00310             // Also check if TY and ST aren't NULLs
00311             _is_tree_OK &= STID_check_st_class(wn);
00312             _is_tree_OK &= TY_is_not_NULL(wn,op);
00313             _is_tree_OK &= ST_is_not_NULL(wn,op);
00314             _is_tree_OK &= Field_id_valid(wn);
00315             break;
00316       case OPR_MLOAD:
00317       case OPR_ISTORE:
00318       case OPR_MSTORE:
00319            // Check that TY is not NULL
00320            _is_tree_OK &= TY_is_not_NULL(wn,op);
00321            _is_tree_OK &= Field_id_valid(wn);
00322            break;
00323       case OPR_ISTOREX:
00324       case OPR_TAS:
00325            // Check that TY is not NULL
00326            _is_tree_OK &= TY_is_not_NULL(wn,op);
00327            break;
00328       case OPR_ILOAD:
00329            // Check if both TY's are not NULL's
00330            _is_tree_OK &= TY_is_not_NULL(wn,op);
00331            _is_tree_OK &= Load_addr_TY_is_not_NULL(wn,op);
00332            _is_tree_OK &= Field_id_valid(wn);
00333            break;
00334       case OPR_PARM:
00335             // Check if the parent is a CALL node
00336             _is_tree_OK &= Param_parent_is_Call(wn,parent_wn);
00337             break;
00338       case OPR_CALL:
00339       case OPR_PICCALL:
00340             // Check if children of CALL node are PARM
00341             // Also check the ST pointer
00342             _is_tree_OK &= Call_children_are_PARM(wn);
00343             _is_tree_OK &= ST_is_not_NULL(wn,op);
00344             break;
00345       case OPR_ICALL:
00346            // Check if children of the CALL node are PARM
00347            // Check that TY is not NULL
00348            _is_tree_OK &= Call_children_are_PARM(wn);
00349            _is_tree_OK &= TY_is_not_NULL(wn,op);
00350            break;
00351       case OPR_INTRINSIC_CALL:
00352       case OPR_IO:
00353       case OPR_INTRINSIC_OP:
00354            // Check if children of the CALL node are
00355            // are PARMS
00356            _is_tree_OK &= Call_children_are_PARM(wn);
00357            break;
00358       case OPR_PRAGMA:
00359            // Check pragma scoping
00360            _is_tree_OK &= Are_enclosed_pragmas(wn,parent_wn);
00361            break;
00362       default:
00363           //check if the opcode is legal
00364           _is_tree_OK &= Is_legal_wn_opcode(op);
00365     }
00366     // traverse the tree starting with this node.
00367     if ( op == OPC_BLOCK)
00368     {
00369       // Special traversal case for BLOCK structure
00370       Proper_Block_Structure(wn,op);
00371       for(WN *node = WN_first(wn); node; node = WN_next(node))
00372         _is_tree_OK &= WN_traverse_tree(node,wn);
00373     } else {
00374       for(INT32 i = 0; i < WN_kid_count(wn); i++)
00375        _is_tree_OK &= WN_traverse_tree(WN_kid(wn,i),wn);
00376     }
00377   }
00378   if (!parent_wn) {
00379     if (WN_Tree_Has_Duplicate_Labels(wn, &_mem_pool))
00380       Fail_FmtAssertion("WN_Verifier() found duplicate labels in "
00381                         "WHIRL tree");
00382   }
00383   return _is_tree_OK;
00384 }
00385 
00386 // This procedure checks whether TY of a node is not NULL
00387 BOOL WN_Verifier::TY_is_not_NULL(WN *wn, OPCODE op)
00388 {
00389   FmtAssert(WN_ty(wn) != (TY_IDX)NULL,
00390     ("WN_verifier Error (TY_is_not_NULL): whirl node %s has "
00391      "a TY == NULL", OPCODE_name(op)));
00392   return TRUE;
00393 }
00394 
00395 // This procedure checks whether address of the TY is not NULL
00396 BOOL WN_Verifier::Load_addr_TY_is_not_NULL(WN *wn, OPCODE op)
00397 {
00398   FmtAssert(WN_load_addr_ty(wn) != (TY_IDX)NULL,
00399             ("WN_verifier Error (Load_addr_TY_is_not_NULL): whirl "
00400              "node %s has a TY == NULL", OPCODE_name(op)));
00401   return TRUE;
00402 }
00403 
00404 // This procedure checks whether the ST of the
00405 // node is null;
00406 
00407 BOOL WN_Verifier::ST_is_not_NULL(WN *wn, OPCODE op)
00408 {
00409   FmtAssert(WN_st_idx(wn)!=(ST_IDX)NULL,
00410             ("WN_verifier Error (ST_is_not_NULL): whirl node %s "
00411              "has a ST == NULL", OPCODE_name(op)));
00412   // IPA might leave behind stores to dead variables
00413   if (ST_is_not_used (WN_st(wn)) && !OPERATOR_is_store (WN_operator (wn)))
00414       DevWarn ("WN_verifier Error: whirl node %s references symbol"
00415                " %s that is marked NOT_USED", OPCODE_name(op),
00416                ST_name (WN_st(wn))); 
00417   return TRUE;
00418 }
00419 
00420 /*-----------------------------------------------------------
00421  * Check if the WHIRL tree is actually a tree
00422  * by checking if the current node was visited
00423  * before. It uses maps to accomplish this, maping a visited
00424  * node to its parent. If the node was not visited previously
00425  * the map should return NULL, and not the parent of the node
00426  *-----------------------------------------------------------*/
00427 BOOL
00428 WN_Verifier::Is_WHIRL_tree(WN *wn, WN *parent_wn)
00429 {
00430   if (Is_legal_wn_opcode(WN_opcode(wn)) == FALSE)
00431     return FALSE;
00432   if ( WN_MAP_Get(_map, wn) != NULL ) {
00433     FmtAssert(FALSE, ("WN_verifier ERROR: This is not a WHIRL tree\n\t"
00434                       "(0x%x --> 0x%x, 0x%x --> 0x%x).\n",
00435                       WN_MAP_Get(_map, wn), wn, parent_wn, wn));
00436     return FALSE;
00437   } else
00438     WN_MAP_Set(_map, wn, (void *)parent_wn);
00439   return TRUE;
00440 }
00441 
00442 // This function returns TRUE iff the preg is indeed a dedicated
00443 // preg: which are now pregs # 2, 3, 32, 34
00444 BOOL WN_Verifier::Is_dedicated_return_register(WN_OFFSET preg)
00445 {
00446   return ((preg == 2) || (preg == 3) || (preg == 32) || (preg==34));
00447 }
00448 
00449 /*--------------------------------------------------------------
00450  * This function returns the node one level removed from
00451  * the LDID node.
00452  * [Call node]<->[STID node]
00453  *                  |
00454  *                  V
00455  *      [LDID dedicated return register]
00456  * Node call will be returned as the One_level_removed from LDID
00457  *--------------------------------------------------------------*/
00458 WN *
00459 WN_Verifier::One_level_removed_node(WN *parent_wn,OPERATOR opr)
00460 {
00461   WN *temp_wn = NULL;
00462   
00463   if (opr == OPR_LDID && parent_wn != NULL && 
00464       WN_operator(parent_wn) == OPR_STID)
00465     temp_wn = WN_prev(parent_wn);
00466   return temp_wn;
00467 }
00468 
00469 /*---------------------------------------------------------------
00470  * This function returns TRUE iff the return register passed is
00471  * the valid return register of the call node call_wn.
00472  * This function gets the registers that the call_wn could
00473  * return and checks whether one of those is preg that is passed
00474  *  as a parameter.
00475  *---------------------------------------------------------------*/
00476 BOOL
00477 WN_Verifier::Is_return_register_of_call(WN *call_wn, PREG_NUM preg)
00478 {      
00479   PREG_NUM retreg1, retreg2;
00480   TYPE_ID  ty1,ty2;
00481 
00482   if (Verifier_DEBUG)
00483     DevWarn("Verifier TODO: how do I know to use "
00484             "Use_Similated/Complex_Not...");
00485   
00486   // I will need to worry about the Use_Similated later on
00487   const PU& pu = Pu_Table[ST_pu (WN_st (call_wn))];
00488 
00489   if (WHIRL_Return_Info_On) {
00490 
00491     RETURN_INFO return_info = Get_Return_Info (TY_ret_type (Ty_Table[PU_prototype (pu)]),
00492                                                Complex_Not_Simulated);
00493 
00494     if (RETURN_INFO_count(return_info) <= 2) {
00495 
00496       ty1 = RETURN_INFO_mtype (return_info, 0);
00497       ty2 = RETURN_INFO_mtype (return_info, 1);
00498       retreg1 = RETURN_INFO_preg (return_info, 0);
00499       retreg2 = RETURN_INFO_preg (return_info, 1);
00500     }
00501 
00502     else
00503       Fail_FmtAssertion (
00504         "WN_Verifier::Is_return_register_of_call: more than 2 return registers");
00505   }
00506 
00507   else
00508     Get_Return_Mtypes (TY_ret_type (Ty_Table[PU_prototype (pu)]),
00509                        Complex_Not_Simulated, &ty1,&ty2);
00510   //Get_(MTYPE_To_TY(WN_rtype(call_wn)),
00511   //                 Use_Simulated,
00512   //                 &ty1,&ty2);
00513   if (!WHIRL_Return_Info_On)
00514     Get_Return_Pregs(ty1,ty2,&retreg1,&retreg2);  
00515   return ((preg == retreg1) || (preg == retreg2)); 
00516 }
00517 
00518 
00519 /*---------------------------------------------------
00520  * Check if the instuction previous to parent 
00521  * of LDID is indeed a CALL node
00522  * and wheather the type of the registers
00523  * of the call node match the ones used in LDID.
00524  * So for example this would be OK:
00525  *    I4CALL
00526  *      LDID 2
00527  *    STID 45
00528  *---------------------------------------------------*/
00529 BOOL WN_Verifier::CALL_parent_LDID(WN *wn, WN *parent_wn)
00530 {
00531   OPCODE   opc=WN_opcode(wn);
00532   OPERATOR opr = OPCODE_operator(opc);
00533   WN       *temp_wn;  
00534   BOOL     slink_used;
00535 
00536 #ifndef TARG_IA64
00537 
00538   // At the LDID node with special registers that are dedicated only
00539   // to return values:
00540   //   check if the call is at most twice removed
00541   //   and that the registers that call can return are indeed
00542   //   the once that were returned.
00543   if (opr == OPR_LDID && ST_class(WN_st(wn)) == CLASS_PREG &&
00544       Is_dedicated_return_register(WN_offset(wn)))
00545     { 
00546       temp_wn = One_level_removed_node(parent_wn,opr);
00547       if (_func != NULL) {
00548         const PU& pu = Pu_Table[ST_pu (WN_st (_func))];
00549         slink_used = PU_is_nested_func(pu);
00550       } else
00551         slink_used = TRUE; // since we don't know, cannot assert
00552       // If the load was twise removed from call
00553       if ((temp_wn !=NULL) && (WN_operator(temp_wn) == OPR_STID))
00554         temp_wn = WN_prev(temp_wn);
00555       
00556       // here we need to consider another situation before filing a bug.
00557       // preg 2 can be used in the nested procedure, before STID to simlink
00558       // under function entry. 
00559       if (temp_wn==NULL) {
00560         if (!slink_used) {
00561           DevWarn("WN_verifier Error (Call_parent_LDID): no CALL "
00562                   "instruction one/two level(s) removed from LDID %d",
00563                   WN_offset(wn));    
00564           return FALSE;
00565         } else {
00566           return TRUE;
00567         }
00568       }
00569       
00570       OPCODE   t_opc = WN_opcode(temp_wn);
00571       OPERATOR t_opr = OPCODE_operator(t_opc);
00572     
00573       // Check if parent indeed was the one of the CALL operators
00574 
00575       if ( t_opr == OPR_CALL || t_opr == OPR_ICALL ||
00576            t_opr == OPR_INTRINSIC_CALL ||
00577            t_opr == OPR_PICCALL || t_opr == OPR_IO ||
00578            t_opr == OPR_INTRINSIC_OP) 
00579         {
00580           // Unfortunately now I can only check OPR_CALL
00581           if ( t_opr == OPR_CALL && 
00582                !Is_return_register_of_call(temp_wn,WN_offset(wn)))
00583             {
00584               DevWarn("WN_verifier Error (Call_parent_LDID): different register "
00585                       "follows CALL than needed, LDID %d", WN_offset(wn));
00586               return FALSE;
00587             }
00588           else if (Verifier_DEBUG)
00589             DevWarn("Verifier (Call_parent_LDID): Call is Ok");
00590         }
00591 
00592       // here we need to consider another situation before filing a bug.
00593       // preg 2 can be used in the nested procedure, before STID to simlink
00594       // under function entry.
00595       else if (!slink_used)
00596         {
00597           DevWarn("WN_verifier Error (Call_parent_LDID): LDID %d was not "
00598                   "following any CALL node", WN_offset(wn));
00599           return FALSE;
00600         }
00601    
00602     }
00603 #endif
00604   return TRUE;
00605 }
00606 
00607 // This procedure verifies that blocks' last statement
00608 // and blocks first statement have appropriate NULL pointers
00609 BOOL WN_Verifier::Proper_Block_Structure(WN *wn,OPCODE op)
00610 {
00611   BOOL block_ok = TRUE;
00612 
00613   if (op == OPC_BLOCK)
00614   {
00615     // Check if first statement of block has prev == NULL;
00616     WN *first = WN_first(wn);
00617     WN *last = WN_last(wn);
00618     if ( first == NULL ) {
00619       FmtAssert( last == NULL,
00620                  ("WN_verifier Error (Proper_Block_Structure): first is NULL but last is not."));
00621       block_ok = FALSE;
00622     }
00623     if ( first != NULL && WN_prev(first) != NULL){ 
00624       FmtAssert(FALSE, ("WN_verifier Error (Proper_Block_Structure): This block does "
00625                         "not have a null pointer in the first wn node"));
00626       block_ok = FALSE;
00627     }
00628     
00629     // Check if the last statement of block has next == NULL;
00630     if ( last != NULL && WN_next(last)  != NULL ) { 
00631       FmtAssert(FALSE, ("WN_verifier Error (Proper_Block_Structure): This block does "
00632                         "not have a null pointer in the last wn node"));
00633       block_ok = FALSE;
00634     } 
00635 
00636     // Check WN_first can reach WN_last through WN_next
00637     WN *tmp = first;
00638     while (tmp && WN_next(tmp) != NULL) 
00639       tmp = WN_next(tmp);
00640     if (tmp != last) {
00641       FmtAssert (FALSE, ("WN_verifier Error (Proper_Block_Structure): last is not really last\n"));
00642       block_ok = FALSE;
00643     }
00644 
00645     // Check WN_last can reach WN_first through WN_prev
00646     tmp = last;
00647     while (tmp && WN_prev(tmp) != NULL) 
00648       tmp = WN_prev(tmp);
00649     if (tmp != first) {
00650       FmtAssert (FALSE, ("WN_verifier Error (Proper_Block_Structure): first is not really firstt\n"));
00651       block_ok = FALSE;
00652     }
00653   }
00654   return block_ok;
00655 }
00656 
00657 // This procedure checks that if the node is a PARM node, its parent have
00658 // to be a CALL node. 
00659 
00660 BOOL WN_Verifier::Param_parent_is_Call(WN *wn,WN *parent_wn)
00661 {
00662   OPCODE   opc=WN_opcode(wn);
00663   OPERATOR opr = OPCODE_operator(opc);
00664 
00665   if (opr == OPR_PARM)
00666   {
00667     opc = WN_opcode(parent_wn);
00668     opr = OPCODE_operator(opc);
00669     if (opr == OPR_CALL || opr == OPR_ICALL ||
00670         opr == OPR_INTRINSIC_CALL ||
00671         opr == OPR_PICCALL || opr == OPR_IO ||
00672         opr == OPR_INTRINSIC_OP)
00673     {
00674       // It is ok, the parents of the PARM is a Call node.
00675       return TRUE;
00676     } else {
00677       // The parent of the PARM is not a Call node;
00678       DevWarn("WN_verifier Error (Param_parent_is_Call): The parent of the "
00679               "PARM node is not a CALL node but a %s node",OPCODE_name(opc));
00680       return FALSE;
00681     }
00682   }
00683   return TRUE;
00684 }
00685 
00686 
00687 /*----------------------------------------------------------------
00688  * This procedure checks that the childern of the CALL statement
00689  * should only be PARMs. Several exeptions apply: the last
00690  * kid of the ICALL or PICCALL should not be a PARAM. Also
00691  * OPR_IO_ITEM could be a kid of OPR_IO.
00692  *----------------------------------------------------------------*/
00693 
00694 BOOL WN_Verifier::Call_children_are_PARM(WN *wn)
00695 {
00696   OPCODE   opc=WN_opcode(wn);
00697   OPCODE   parent_opc=opc;
00698   OPERATOR opr = OPCODE_operator(opc);
00699   OPERATOR parent_opr=opr;
00700 
00701   if (opr == OPR_CALL || 
00702       opr == OPR_INTRINSIC_CALL || 
00703       opr == OPR_INTRINSIC_OP   ||
00704       opr == OPR_IO) 
00705   {
00706     for(INT32 i=0; i < WN_kid_count(wn); i++)
00707     {
00708       opc = WN_opcode(WN_kid(wn,i));
00709       opr = OPCODE_operator(opc);
00710 
00711       // If the cild of the call is not PARM
00712       // or is not IO_ITEM (* in a special case of OPR_IO *)
00713       // then error out.
00714       // NOTE: I belive that OPR_IO can have cildren called PARM
00715       // so thats why I structured my if checking for PARM first
00716       // and only than special condition for IO
00717 
00718       if ((opr != OPR_PARM ) &&
00719           ((parent_opr == OPR_IO) && (opr != OPR_IO_ITEM)) ) 
00720       {
00721         // The parent of the PARM is not a Call node;
00722         DevWarn("WN_verifier Error (Call_children_are_PARM): The child of %s "
00723                 "node is not a PARM node but a %s node",
00724                 OPCODE_name(parent_opc), OPCODE_name(opc));
00725         return FALSE;
00726       }
00727     }
00728   }
00729   else if ( opr == OPR_PICCALL || opr == OPR_ICALL)
00730   {
00731       for(INT32 i=0; i < WN_kid_count(wn); i++)
00732       { opc = WN_opcode(WN_kid(wn,i));
00733         opr = OPCODE_operator(opc);
00734 
00735         // Regular case: clidren of CALL except for the last 
00736         // one should be PARM
00737         if ((opr != OPR_PARM) && (i < (WN_kid_count(wn)-1) ))  
00738         {
00739           // The parent of the PARM is not a Call node;
00740           DevWarn("WN_verifier Error (Call_children_are_PARM): The child of "
00741                   "CALL node is not a  PARM node but a %s node",
00742                   OPCODE_name(opc));
00743           return FALSE;
00744         }
00745         // Here we need to check the exception
00746         else if ((opr == OPR_PARM) && (i == (WN_kid_count(wn)-1)))
00747         {
00748           DevWarn("WN_verifier Error (Call_children_are_PARM): The last "
00749                   "child of (P)ICALL node is a  PARM node");
00750           return FALSE;
00751         }
00752       }
00753   }
00754   
00755   return TRUE;
00756 }
00757 
00758 
00759 /*------------------------------------------------------------------
00760  * This procedure checks if the opcode is legal
00761  * Since all possible combinations of the opcodes are defined in
00762  * the opcode_gen_core.h file I only need to check the range of the
00763  * opcode
00764  *------------------------------------------------------------------*/
00765 BOOL WN_Verifier::Is_legal_wn_opcode(OPCODE opc)
00766 {
00767   
00768   if (opc < OPCODE_FIRST || opc > OPCODE_LAST)
00769   {
00770     DevWarn("WN_verifier Error (Is_legal_wn_opcode): The opcode %s "
00771             "is illegal",OPCODE_name(opc));
00772   }
00773   return ((opc >= OPCODE_FIRST) && (opc <= OPCODE_LAST));
00774 }
00775 
00776 // This subroutine checks that LDA's TY is not NULL,
00777 // and it has to be a pointer type
00778 BOOL WN_Verifier::LDA_ty_not_NULL(WN *wn)
00779 {
00780     OPCODE   opc = WN_opcode(wn);
00781     OPERATOR opr = OPCODE_operator(opc);
00782     
00783     if (opr == OPR_LDA) {
00784         const TY& ty = Ty_Table[WN_ty (wn)];
00785         if (WN_ty (wn) == 0 ||
00786             !(TY_kind(ty) == KIND_POINTER || TY_kind(ty) == KIND_SCALAR)) {
00787             DevWarn("WN_verifier Error (LDA_ty_not_NULL): TY of the %s is "
00788                     "either NULL or is not a pointer or scalar",
00789                     OPCODE_name(opc));
00790             ty.Print (stderr);
00791             return FALSE;
00792         }
00793     }
00794     return TRUE;
00795 }
00796 
00797 // This procedure checks restrictions on st of STID
00798 // It also checks that if dedicated return
00799 // register is used than the next statement
00800 // after should be RETURN
00801 BOOL WN_Verifier::STID_check_st_class(WN *wn)
00802 {
00803   OPCODE   opc = WN_opcode(wn);
00804   OPERATOR opr = OPCODE_operator(opc);
00805  
00806   if (opr == OPR_STID) {
00807     ST * st = WN_st(wn);
00808     // Restricting the ST_class
00809     if ( ( ST_class(st)!=CLASS_VAR ) &&
00810          ( ST_class(st)!=CLASS_PREG ) &&
00811          ( ST_class(st)!=CLASS_BLOCK)    )
00812     {
00813       DevWarn("WN_verifier Error (STID_check_st_class): ST of the STID is "
00814               "not CLASS: VAR, PREG or Block but %d", ST_class(st));
00815       return FALSE;
00816     } 
00817     if ( (ST_class(st) == CLASS_PREG) && 
00818          (Is_dedicated_return_register(WN_offset(wn))) )
00819     {
00820        WN *temp_wn = WN_next(wn);
00821        
00822        // There could be two STIDs following one another
00823        // before actual return statement. So
00824        if ((temp_wn != NULL) && 
00825            (WN_operator(temp_wn) == OPR_STID) &&
00826            (ST_class(WN_st(temp_wn)) == CLASS_PREG ) &&
00827            (Is_dedicated_return_register(WN_offset(temp_wn)))  )
00828        {
00829          // Than scip this STID and look at the next statement
00830          // Since function can only have up to two 
00831          // dedicatd return STIDs before OPC_RETURN
00832     
00833          temp_wn=WN_next(temp_wn);
00834        }
00835 
00836        //
00837        // Check if return follows the STID of the dedicated register
00838        // also check for call immediatly following use of register 2 (static link register)
00839        //
00840        if ((WN_offset(wn) != Static_Link_Preg_Offset) && 
00841            ((temp_wn == NULL) || (WN_operator(temp_wn) != OPR_RETURN)) )
00842          {
00843            DevWarn("WN_verifier Error (STID_check_st_class): STID %d was "
00844                    "followed by %s and not by OPC_RETURN",
00845                    WN_offset(wn),
00846                    temp_wn ? OPCODE_name(WN_opcode(temp_wn)) : "NULL");
00847          }
00848        else if ((WN_offset(wn) == Static_Link_Preg_Offset) && 
00849                 ((temp_wn == NULL) || (WN_operator(temp_wn) != OPR_RETURN)
00850                  && (WN_operator(temp_wn) != OPR_PICCALL)
00851                  && (WN_operator(temp_wn) != OPR_CALL)) )
00852          {
00853            DevWarn("WN_verifier Error (STID_check_st_class): STID %d was "
00854                    "followed by %s and not by OPC_RETURN or OPR_CALL or OPR_PICCALL",
00855                    WN_offset(wn),OPCODE_name(WN_opcode(temp_wn)));
00856          }
00857     }
00858 
00859     // Restricting the ST_sclass
00860     switch(ST_sclass(st))
00861     {
00862       case SCLASS_UNKNOWN:
00863       case SCLASS_AUTO:
00864       case SCLASS_FORMAL:
00865       case SCLASS_PSTATIC:
00866       case SCLASS_FSTATIC:
00867       case SCLASS_COMMON:
00868       case SCLASS_EXTERN:
00869       case SCLASS_UGLOBAL:
00870       case SCLASS_DGLOBAL:
00871       case SCLASS_REG:
00872       case SCLASS_FORMAL_REF:
00873            //if (Verifier_DEBUG)
00874            //    DevWarn("The SCLASS of ty is fine");
00875            break;
00876 
00877       case SCLASS_TEXT:
00878            DevWarn("WN_verifier Error (STID_check_st_class): ST SCLASS "
00879                    "is SCALSS_TEXT");
00880            Print_ST(stderr, st, FALSE);
00881            return FALSE;
00882            
00883      
00884     default:
00885            DevWarn("WN_verifier Error (STID_check_st_class): ST SCLASS "
00886                    "is unknown");
00887            Print_ST(stderr, st, FALSE);
00888            return FALSE;
00889     }
00890   }
00891   return TRUE;
00892 }
00893 
00894 
00895 /*-----------------------------------------------------
00896  * This routine will check the scoping of several
00897  * pragmas. Pragmas should be self enclosed. What 
00898  * is ment by that is that if I have a pragma 
00899  * that starts the scope I should be able to
00900  * find a pragma that ends the scope on the same
00901  * block level as pragma that started the scope.
00902  * So checking pragmas would be like checking
00903  * parentisation rules, where pragma itself and
00904  * parent wn node would be saved on stack.
00905  * Algo: 
00906  * whenever I see a pragmacall this routine.
00907  * If this is the pragma that I support -
00908  * if it starts section put it on stack,
00909  * if it ends section check the top of
00910  * the stack and if it is Ok than pop off
00911  * else give warning.
00912  *------------------------------------------------------*/
00913 BOOL WN_Verifier::Are_enclosed_pragmas(WN *wn,WN *parent_wn)
00914 {
00915   pragma_stack_type temp;
00916   WN_PRAGMA_ID temp_id= (WN_PRAGMA_ID) WN_pragma(wn);
00917   int  i = 0;
00918 
00919   // Check if the pragma passed is supported
00920   while(i<NUM_PRAGMAS_SUPPORTED)
00921   {
00922     // If the pragma passed is supported then
00923     if (pragmas_supported[i].pragma_id=temp_id)
00924     {
00925        // If the flag of the supported pragma says push
00926        // push the pragma and parent id on the stack.
00927        if (pragmas_supported[i].push)
00928        {
00929          temp.pragma_id = temp_id;
00930          temp.parent_wn = parent_wn;
00931          _pragma_stack.push(temp);
00932           return TRUE;
00933        }
00934        // Otherwise we need to pop pragma - so check that stack
00935        // is not empty
00936        else if (_pragma_stack.size()>0)
00937        {
00938           temp= _pragma_stack.top();
00939 
00940           // If the top of the stack contains the pragma we expected
00941           // and the pragma closing it is at the same level (checked by
00942           // parent_wn pointers) than we can pop pragma from the stack
00943 
00944           if (temp.pragma_id == pragmas_supported[i].pragma_starting_id &&
00945               temp.parent_wn == parent_wn)
00946           {
00947              if (Verifier_DEBUG)
00948                DevWarn("Stack worked!!");
00949              _pragma_stack.pop();
00950              return TRUE;
00951           }
00952           else if (temp.pragma_id != pragmas_supported[i].pragma_starting_id)
00953           {
00954             DevWarn("WN_verifier Error (Are_enclosed_pragmas): on stack "
00955                     "expecting %d but got %d",
00956                     pragmas_supported[i].pragma_starting_id, temp.pragma_id);
00957             return FALSE;
00958           } 
00959           else
00960           {
00961             DevWarn("WN_verifier Error (Are_enclosed_pragmas): the pragma "
00962                     "is closed by different level of the parent");
00963             return FALSE;
00964           }
00965       
00966        }
00967        else // size of the stack is 0 but we need to pop
00968        {
00969          return FALSE;
00970        }
00971     } // if the pragma was supported
00972     i++;
00973   } // while you are going through supported pragmas
00974   return TRUE;
00975 }
00976 
00977 
00978 BOOL
00979 WN_Verifier::Field_id_valid (WN* wn)
00980 {
00981     const TY* ty = &Ty_Table[WN_ty (wn)];
00982     
00983     switch (WN_operator(wn)) {
00984     case OPR_MLOAD:
00985     case OPR_MSTORE:
00986         Is_True (TY_kind (*ty) == KIND_POINTER,
00987                  ("MLOAD/MSTORE expects a pointer type"));
00988         if (TY_kind(TY_pointed(*ty)) == KIND_STRUCT &&
00989             WN_field_id(wn) == 0) {
00990             WN* kid = WN_operator(wn) == OPR_MLOAD ? WN_kid1(wn) : WN_kid2(wn);
00991             if (WN_operator(kid) == OPR_INTCONST) {
00992                 INT64 ty_size = TY_size(TY_pointed(*ty));
00993                 // must be multiple of the size of the high-level type
00994                 Is_True (ty_size == 0 || WN_const_val (kid) % ty_size == 0,
00995                          ("MLOAD/MSTORE size is inconsistent with TY"));
00996             }
00997         }
00998         break;
00999 
01000     case OPR_ISTORE:
01001         ty = &Ty_Table[TY_pointed (*ty)];
01002         // fall through
01003     default:
01004         if (TY_kind(*ty) != KIND_STRUCT) {
01005             Is_True (WN_field_id(wn) == 0,
01006                      ("non-zero field id for memory op on scalar"));
01007         } else if (WN_field_id(wn) == 0) {
01008             Is_True (WN_desc(wn) == MTYPE_M ||
01009                      MTYPE_byte_size(WN_desc(wn)) == TY_size(*ty),
01010                      ("field_id and descriptor type are inconsistent"));
01011         }
01012         break;
01013     }
01014 
01015     return TRUE;
01016 } // Field_id_valid
01017 
01018   
01019 /* Return TRUE if tree rooted at pu_wn has any OPR_LABEL nodes that share
01020  * label numbers, return FALSE otherwise. tmp_pool must be initialized and
01021  * not frozen.
01022  */
01023 
01024 BOOL WN_Tree_Has_Duplicate_Labels(WN *pu_wn, MEM_POOL *tmp_pool)
01025 {
01026   MEM_POOL_Popper popper(tmp_pool);
01027   WN_ITER *it = WN_WALK_TreeIter(pu_wn);
01028   HASH_TABLE<LABEL_IDX, WN *> labels_found(257, tmp_pool);
01029 
01030   while (it) {
01031     WN *wn = it->wn;
01032 
01033     if (WN_operator(wn) == OPR_LABEL) {
01034       LABEL_IDX lab = WN_label_number(wn);
01035       Is_True(lab > 0, ("WN_verifier: found label with number 0"));
01036       Is_True(lab <= LABEL_Table_Size(CURRENT_SYMTAB),
01037               ("WN_verifier: label %d greater than last label %d",
01038                (INT) lab, LABEL_Table_Size(CURRENT_SYMTAB)));
01039       WN *dup_lab_wn = labels_found.Find(lab);
01040 
01041       if (dup_lab_wn)
01042         return TRUE;
01043 
01044       labels_found.Enter(lab, wn);
01045     }
01046 
01047     it = WN_WALK_TreeNext(it);
01048   }
01049 
01050   return FALSE;
01051 }
01052 
01053 
01054 // classification of which label fields are present in a Whirl node
01055 enum WN_Label_Fields {
01056   WN_HAS_NO_LABELS,
01057   WN_HAS_LABEL,     // WN_label_number(wn) is valid
01058   WN_HAS_LAST_LABEL // WN_last_label(wn) is valid
01059 };
01060 
01061 // return which type of label field is valid for wn
01062 static WN_Label_Fields WN_Has_Label(WN *wn)
01063 {
01064   Is_True(wn, ("NULL wn"));
01065 
01066   switch (WN_operator(wn)) {
01067   case OPR_CASEGOTO:
01068   case OPR_FALSEBR:
01069   case OPR_GOTO:
01070   case OPR_LABEL:
01071   case OPR_REGION_EXIT:
01072   case OPR_TRUEBR:
01073     return WN_HAS_LABEL;
01074   case OPR_COMPGOTO:
01075   case OPR_SWITCH:
01076     return WN_HAS_LAST_LABEL;
01077   default:
01078     break;
01079   }
01080 
01081   return WN_HAS_NO_LABELS;
01082 }
01083 
01084 typedef HASH_TABLE<LABEL_IDX, LABEL_IDX> LABEL_RENAMING_MAP;
01085 
01086 static BOOL
01087 References_Some_Label(WN *pu_wn, LABEL_RENAMING_MAP *lab_map, WN *orig_wn);
01088 
01089 static void
01090 Rename_INITV_Labels(INITO_IDX inito_idx, LABEL_RENAMING_MAP *lab_map,
01091                     MEM_POOL *tmp_pool);
01092 
01093 BOOL
01094 WN_Rename_Duplicate_Labels(WN *orig_wn, WN *copied_wn, WN *pu_wn,
01095                            MEM_POOL *tmp_pool)
01096 {
01097   MEM_POOL_Popper popper(tmp_pool);
01098   LABEL_RENAMING_MAP lab_map(1021, tmp_pool);
01099 
01100     // walk orig_wn, creating a mapping in lab_map for each label we find
01101   WN_ITER *orig_it = WN_WALK_TreeIter(orig_wn);
01102 
01103   while (orig_it) {
01104     WN *wn = orig_it->wn;
01105 
01106     if (WN_operator(wn) == OPR_LABEL) {
01107         // create new label
01108       LABEL_IDX lab_idx = WN_label_number(wn), new_lab_idx;
01109       Is_True(!lab_map.Find(lab_idx),
01110               ("duplicate label %d in orig_wn", (INT) lab_idx));
01111 
01112       LABEL &new_lab = New_LABEL(CURRENT_SYMTAB, new_lab_idx);
01113       char* Cur_PU_Name = ST_name(PU_Info_proc_sym(Current_PU_Info));
01114       INT strsize = strlen(User_Label_Number_Format) + 64 + strlen(Cur_PU_Name);
01115       char * labelname = (char*) calloc(strsize, 1);
01116       sprintf(labelname, User_Label_Number_Format, (INT) CURRENT_SYMTAB,
01117               (INT) new_lab_idx, Cur_PU_Name);
01118       LABEL_Init(new_lab, Save_Str(labelname),
01119                  LABEL_kind((*Scope_tab[CURRENT_SYMTAB].label_tab)[lab_idx]));
01120 
01121       lab_map.Enter(lab_idx, new_lab_idx);  // add mapping from old to new
01122     }
01123 
01124     orig_it = WN_WALK_TreeNext(orig_it);
01125   }
01126 
01127     // walk copied_wn, renaming each referenced label as per lab_map
01128   WN_ITER *copied_it = WN_WALK_TreeIter(copied_wn);
01129 
01130   while (copied_it) {
01131     WN *wn = copied_it->wn;
01132     WN_Label_Fields wn_lab = WN_Has_Label(wn);
01133 
01134     if (wn_lab == WN_HAS_LABEL || wn_lab == WN_HAS_LAST_LABEL) {
01135       LABEL_IDX lab_idx = (wn_lab == WN_HAS_LABEL) ? WN_label_number(wn) :
01136                           WN_last_label(wn);
01137 
01138       LABEL_IDX new_lab_idx = lab_map.Find(lab_idx);
01139       if (new_lab_idx) {
01140         if (wn_lab == WN_HAS_LABEL)
01141           WN_label_number(wn) = new_lab_idx;
01142         else
01143           WN_last_label(wn) = new_lab_idx;
01144       }
01145 
01146     } else if (wn_lab != WN_HAS_NO_LABELS)
01147       Fail_FmtAssertion("impossible return value from WN_Has_Label");
01148 
01149     if (WN_operator(wn) == OPR_REGION && WN_ereg_supp(wn))
01150       Rename_INITV_Labels(WN_ereg_supp(wn), &lab_map, tmp_pool);
01151 
01152     copied_it = WN_WALK_TreeNext(copied_it);
01153   }
01154 
01155   if (!pu_wn)
01156     return TRUE;
01157 
01158     // verify that each label in lab_map was "internal" to orig_wn
01159   return !References_Some_Label(pu_wn, &lab_map, orig_wn);
01160 }
01161 
01162 // Return TRUE if pu_wn references some label that's a key in lab_map, FALSE
01163 // otherwise.  Skip subtree orig_wn if it's not NULL.
01164 static BOOL
01165 References_Some_Label(WN *pu_wn, LABEL_RENAMING_MAP *lab_map, WN *orig_wn)
01166 {
01167   Is_True(pu_wn, ("NULL pu_wn"));
01168 
01169   if (pu_wn == orig_wn)
01170     return FALSE; // skip subtree orig_wn
01171 
01172   WN_Label_Fields wn_lab = WN_Has_Label(pu_wn);
01173 
01174   if (wn_lab == WN_HAS_LABEL || wn_lab == WN_HAS_LAST_LABEL) {
01175     LABEL_IDX lab_idx = (wn_lab == WN_HAS_LABEL) ? WN_label_number(pu_wn) :
01176                         WN_last_label(pu_wn);
01177     if (lab_map->Find(lab_idx))
01178       return TRUE;
01179 
01180   } else if (wn_lab != WN_HAS_NO_LABELS)
01181     Fail_FmtAssertion("impossible return value from WN_Has_Label");
01182 
01183   OPERATOR opr = WN_operator(pu_wn);
01184 
01185   if (!OPERATOR_is_leaf(opr)) {
01186     if (opr == OPR_BLOCK) {
01187       for (WN *kid = WN_first(pu_wn); kid; kid = WN_next(kid))
01188         if (References_Some_Label(kid, lab_map, orig_wn))
01189           return TRUE;
01190 
01191     } else {
01192       for (INT kidno = 0; kidno < WN_kid_count(pu_wn); kidno++)
01193         if (References_Some_Label(WN_kid(pu_wn, kidno), lab_map, orig_wn))
01194           return TRUE;
01195     }
01196   }
01197 
01198   return FALSE;
01199 }
01200 
01201 
01202 // If inito_idx's INITV tree contains any INITVs that reference labels in
01203 // lab_map, then give inito_idx a deep copy of the INITV tree and rename
01204 // all the labels as specified by lab_map
01205 static void
01206 Rename_INITV_Labels(INITO_IDX inito_idx, LABEL_RENAMING_MAP *lab_map,
01207                     MEM_POOL *tmp_pool)
01208 {
01209   { // see if INITV tree contains any labels that require renaming
01210     BOOL renamed_labels_found = FALSE;
01211     STACK<INITV_IDX> initv_stack(tmp_pool);
01212     INITV_IDX val_idx = INITO_val(inito_idx);
01213 
01214     while (val_idx) {
01215       INITVKIND k = INITV_kind(val_idx);
01216       switch (k) {
01217       case INITVKIND_SYMOFF:
01218       case INITVKIND_ZERO:
01219       case INITVKIND_ONE:
01220       case INITVKIND_VAL:
01221       case INITVKIND_PAD:
01222         val_idx = INITV_next(val_idx);
01223         break;
01224 
01225       case INITVKIND_BLOCK:
01226         initv_stack.Push(val_idx);
01227         val_idx = INITV_blk(val_idx);
01228         break;
01229 
01230       case INITVKIND_SYMDIFF: // these 3 kinds contain labels
01231       case INITVKIND_SYMDIFF16:
01232       case INITVKIND_LABEL:
01233         {
01234           LABEL_IDX lab = (k == INITVKIND_LABEL) ? INITV_lab(val_idx) :
01235                           INITV_lab1(val_idx);
01236           if (lab_map->Find(lab))
01237             renamed_labels_found = TRUE;
01238         }
01239         break;
01240 
01241       default:
01242         Fail_FmtAssertion("unknown INITV kind %d", (INT) k);
01243       }
01244       if (renamed_labels_found)
01245         break;
01246 
01247       while (!val_idx && initv_stack.Elements() > 0) {
01248         val_idx = INITV_next(initv_stack.Pop());
01249       }
01250     }
01251 
01252     if (!renamed_labels_found)
01253       return; // no copying needed
01254   }
01255 
01256     // make a deep copy of INITV tree and rename the copy's labels 
01257   STACK<INITV_IDX> old_stack(tmp_pool), new_stack(tmp_pool);
01258   INITV_IDX old_initv = INITO_val(inito_idx),
01259             new_initv,
01260             parent = INITV_IDX_ZERO,
01261             prev = INITV_IDX_ZERO;
01262   BOOL first_new_initv = TRUE;
01263 
01264   while (old_initv) {
01265     new_initv = Copy_INITV(INITV_IDX_ZERO, INITO_IDX_ZERO, old_initv);
01266 
01267     if (first_new_initv) {
01268       Set_INITO_val(inito_idx, new_initv);
01269       first_new_initv = FALSE;
01270     } else if (parent) {
01271       Set_INITV_blk(parent, new_initv);
01272       parent = INITV_IDX_ZERO;
01273     } else if (prev) {
01274       Set_INITV_next(prev, new_initv);
01275     }
01276 
01277     INITVKIND k = INITV_kind(old_initv);
01278     switch (k) {
01279       case INITVKIND_SYMOFF:
01280       case INITVKIND_ZERO:
01281       case INITVKIND_ONE:
01282       case INITVKIND_VAL:
01283       case INITVKIND_PAD:
01284         old_initv = INITV_next(old_initv);
01285         prev = new_initv;
01286         break;
01287 
01288       case INITVKIND_BLOCK:
01289         old_stack.Push(old_initv);
01290         new_stack.Push(new_initv);
01291         old_initv = INITV_blk(old_initv);
01292         parent = new_initv;
01293         prev = INITV_IDX_ZERO;
01294         break;
01295 
01296       case INITVKIND_SYMDIFF:
01297       case INITVKIND_SYMDIFF16:
01298       case INITVKIND_LABEL:
01299         {
01300           LABEL_IDX lab = (k == INITVKIND_LABEL) ? INITV_lab(new_initv) :
01301                           INITV_lab1(new_initv),
01302                     new_lab = lab_map->Find(lab);
01303 
01304           if (new_lab)
01305             if (k == INITVKIND_LABEL)
01306               Set_INITV_lab(new_initv, new_lab);
01307             else
01308               Set_INITV_lab1(new_initv, new_lab);
01309         }
01310         old_initv = INITV_next(old_initv);
01311         prev = new_initv;
01312         break;
01313 
01314       default:
01315         Fail_FmtAssertion("unknown INITV kind %d", (INT) k);
01316     }
01317 
01318     while (!old_initv && old_stack.Elements() > 0) {
01319       old_initv = INITV_next(old_stack.Pop());
01320       prev = new_stack.Pop();
01321     }
01322 
01323   }
01324   
01325 }
01326 
01327 
01328 BOOL
01329 WN_verifier(WN *wn)
01330 {
01331   Temporary_Error_Phase ("WN_verifier");
01332 #ifdef Is_True_On
01333   char *p = getenv ("WN_VERIFIER");
01334   if (p != 0 && strcasecmp (p, "off") == 0)
01335       return TRUE;
01336   if (Verifier_DEBUG)
01337       DevWarn("I am running newest verifier");
01338   WN_Verifier wnv(wn);
01339   return wnv.WN_traverse_tree(wn, NULL);
01340 #else
01341   return TRUE;
01342 #endif
01343 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines