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