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 * $Revision: 00041 * $Author: 00042 * $Source: 00043 * 00044 * Description: 00045 * clone a procedure and its local symbol table 00046 * 00047 * ==================================================================== 00048 * ==================================================================== 00049 */ 00050 00051 #include <elf.h> 00052 00053 // ====================================================================== 00054 #include "defs.h" // pre-defined types 00055 #include "strtab.h" // Save_Str() 00056 #include "irbdata.h" // INITO 00057 #include "cxx_memory.h" // CXX_NEW () 00058 #include "wn.h" // WN 00059 #ifndef _LEGO_CLONER 00060 #include "config_ipa.h" // IPA_Enable_Merge_ty 00061 #include "ipo_parent.h" // for WN_Parentize 00062 #endif 00063 00064 #include "clone.h" // IPO_CLONE, IPO_SYMTAB, 00065 #include "targ_sim.h" 00066 00067 // ====================================================================== 00068 // For easy switching of Scope_tab 00069 // ====================================================================== 00070 class SCOPE_CONTEXT 00071 { 00072 private: 00073 SCOPE* _scope_tab; 00074 00075 public: 00076 SCOPE_CONTEXT (SCOPE *scope) { 00077 _scope_tab = Scope_tab; 00078 Scope_tab = scope; 00079 } 00080 00081 ~SCOPE_CONTEXT () { 00082 Scope_tab = _scope_tab; 00083 } 00084 }; // SCOPE_CONTEXT 00085 00086 00087 // ====================================================================== 00088 00089 // ====================================================================== 00090 // 00091 // IPO_CLONE Member Functions 00092 // 00093 // ====================================================================== 00094 00095 INT IPO_CLONE::_label = 0; // initialize static class member 00096 00097 00098 // ====================================================================== 00099 // create a new global ST entry for this entry point. Note, this 00100 // is to be used by the distribution cloner, since it doesn't need 00101 // to set the symbol to hidden. It could reside in a DSO and be 00102 // called from a main program 00103 // ====================================================================== 00104 00105 void 00106 IPO_CLONE::Set_Entry_Point(WN *wn, WN *cloned_wn, ST *cloned_st) 00107 { 00108 Is_True(wn && cloned_wn && cloned_st && _sym, 00109 ("IPO_CLONE::Set_Entry_Point parameter is null")); 00110 Is_True(WN_opcode(wn) == OPC_FUNC_ENTRY || 00111 WN_opcode(wn) == OPC_ALTENTRY, 00112 ("Set_Entry_Point can only be invoked on FUNCTIONs\n")); 00113 00114 WN_st_idx(cloned_wn) = ST_st_idx(cloned_st); 00115 00116 #ifndef _LEGO_CLONER 00117 // reset this bit since all the unknown edges which may be 00118 // due to addr taken and saved will point to the original procedure 00119 Set_ST_addr_not_saved(cloned_st); 00120 00121 Set_ST_export (cloned_st, EXPORT_INTERNAL); 00122 #endif 00123 00124 #if _THIS_SEEMS_TO_BE_DOING_NOTHING_ 00125 ST *st = WN_st(wn); 00126 _sym->Set_Cloned_ST(st, cloned_st); 00127 _sym->Hide_Cloned_ST(st); // so that recursive calls go to the orig. 00128 #endif 00129 } // IPO_CLONE::Set_Entry_Point 00130 00131 00132 #if 0 // obsolete function 00133 // ====================================================================== 00134 // Create a new global ST for this entry point, with new symbol name 00135 // ====================================================================== 00136 00137 void 00138 IPO_CLONE::Set_Entry_Point (WN* wn, WN* cloned_wn) 00139 { 00140 Is_True(wn && cloned_wn && _sym, 00141 ("IPO_CLONE::Set_Entry_Point parameter is null")); 00142 Is_True(WN_opcode(wn) == OPC_FUNC_ENTRY || 00143 WN_opcode(wn) == OPC_ALTENTRY, 00144 ("Set_Entry_Point can only be invoked on FUNCTIONs\n")); 00145 00146 ST* st = WN_st(wn); 00147 ST* cloned_st = _sym->IPO_Copy_ST(st, GLOBAL_SYMTAB); 00148 00149 if (WN_opcode(wn) == OPC_FUNC_ENTRY) { 00150 // Create a PU (don't do it for alternate entry points) 00151 PU_IDX pu_idx; 00152 PU& pu = New_PU (pu_idx); 00153 PU_Init (pu, ST_pu_type(st), PU_lexical_level(st)); 00154 Set_ST_pu (cloned_st, pu_idx); 00155 } 00156 00157 // reset this bit since all the unknown edges which may be 00158 // due to addr taken and saved will point to the original procedure 00159 Set_ST_addr_not_saved(cloned_st); 00160 00161 Set_ST_export (cloned_st, EXPORT_INTERNAL); 00162 00163 WN_st_idx(cloned_wn) = ST_st_idx(cloned_st); 00164 00165 _sym->Hide_Cloned_ST (st); // so that recursive calls go to the orig. 00166 00167 } // IPO_CLONE::Set_Entry_Point 00168 #endif // obsolete function 00169 00170 00171 // ====================================================================== 00172 // Fix up the ST pointer of the given node. Clone if necessary. 00173 // ====================================================================== 00174 00175 void 00176 IPO_CLONE::Fix_ST (WN* cloned_wn, WN* wn) 00177 { 00178 ST *st = NULL; 00179 ST *cloned_st; 00180 00181 FmtAssert(wn && cloned_wn && _sym,("IPO_CLONE::Fix_ST parameter is null")); 00182 00183 OPCODE op = WN_opcode(wn); 00184 if (OPCODE_has_sym(op)) 00185 st = WN_st(wn); 00186 00187 if (st == NULL) { 00188 // label opcodes don't always have a valid st 00189 if (OPCODE_has_label(op)) { 00190 WN_label_number(cloned_wn) += _sym->Get_cloned_label_last_idx(); 00191 } 00192 if (OPCODE_has_last_label(op)) { 00193 WN_last_label(cloned_wn) += _sym->Get_cloned_label_last_idx(); 00194 } 00195 return; 00196 } 00197 00198 if (WN_operator(wn) == OPR_PRAGMA && 00199 WN_pragma(wn) == WN_PRAGMA_ASM_CONSTRAINT) { 00200 cloned_st = _sym->Get_Cloned_ST (&St_Table[(ST_IDX) WN_pragma_arg1(wn)]); 00201 if ((cloned_st != NULL) && (ST_level(cloned_st) == GLOBAL_SYMTAB)) { 00202 WN_pragma_arg1(wn) = (INT32) ST_st_idx(cloned_st); 00203 } 00204 else { 00205 cloned_st = _sym->Get_ST(&St_Table[(ST_IDX) WN_pragma_arg1(wn)]); 00206 } 00207 WN_pragma_arg1(cloned_wn) = (INT32) ST_st_idx(cloned_st); 00208 } 00209 00210 if (ST_class(st) == CLASS_PREG) { 00211 // the preg number is in the WHIRL node, not in the ST 00212 WN_OFFSET offst; 00213 00214 if (WN_operator(wn) == OPR_PRAGMA) { 00215 if (WN_pragma(wn) != WN_PRAGMA_ASM_CONSTRAINT) { 00216 offst = WN_pragma_arg1(cloned_wn); 00217 if (!Preg_Is_Dedicated(offst)) 00218 WN_pragma_arg1(cloned_wn) += _sym->Get_cloned_preg_last_idx(); 00219 } 00220 } 00221 else { 00222 offst = WN_offset(cloned_wn); 00223 if (!Preg_Is_Dedicated(offst)) 00224 WN_offset(cloned_wn) += _sym->Get_cloned_preg_last_idx(); 00225 } 00226 00227 return; 00228 } 00229 00230 cloned_st = _sym->Get_Cloned_ST (st); 00231 00232 if ((cloned_st != NULL) && (ST_level(cloned_st) == GLOBAL_SYMTAB)) 00233 // Promoted as global 00234 WN_st_idx(wn) = ST_st_idx(cloned_st); // So fix up the orig tree also 00235 else 00236 cloned_st = _sym->Get_ST(st); 00237 00238 WN_st_idx(cloned_wn) = ST_st_idx(cloned_st); 00239 00240 } // IPO_CLONE::Fix_ST 00241 00242 00243 // ====================================================================== 00244 // Fix up the INITO pointers 00245 // ====================================================================== 00246 00247 void 00248 IPO_CLONE::Fix_INITO(WN* cloned_wn, WN* wn) 00249 { 00250 FmtAssert(wn && cloned_wn && _sym,("IPO_CLONE::Fix_INITO parameter is null")); 00251 00252 INITO_IDX init_idx, init_cp_idx; 00253 if (init_idx = WN_ereg_supp(wn)) { 00254 if (_sym) { 00255 // if Get_Cloned_INITO_IDX is true, then it is a promoted static 00256 if (init_cp_idx = _sym->Get_Cloned_INITO_IDX(_sym->Get_INITO(init_idx))) { 00257 WN_ereg_supp(cloned_wn) = init_cp_idx; 00258 WN_ereg_supp(wn) = init_cp_idx; 00259 } 00260 else 00261 WN_ereg_supp(cloned_wn) = _sym->Get_INITO_IDX(WN_ereg_supp(wn)); 00262 } 00263 else { 00264 WN_ereg_supp(cloned_wn) = WN_ereg_supp(wn); 00265 } 00266 } 00267 } 00268 00269 00270 // ====================================================================== 00271 // Copy some of the PU flags that inlining/cloning would need. 00272 // ====================================================================== 00273 static void 00274 Copy_PU_Flags(PU_IDX old_pu, PU_IDX new_pu) 00275 { 00276 #if _DONT_COPY_ALL_THE_FLAGS_ 00277 Pu_Table[new_pu].flags |= 00278 (Pu_Table[old_pu].flags & (PU_HAS_EXC_SCOPES | 00279 PU_NEEDS_FILL_ALIGN_LOWERING | 00280 PU_HAS_VERY_HIGH_WHIRL | 00281 PU_MP_NEEDS_LNO | 00282 PU_HAS_ALLOCA | 00283 PU_HAS_MP | 00284 PU_HAS_NAMELIST | 00285 PU_UPLEVEL | 00286 PU_HAS_REGION )); 00287 #else 00288 Pu_Table[new_pu].src_lang = Pu_Table[old_pu].src_lang; 00289 Pu_Table[new_pu].flags = Pu_Table[old_pu].flags; 00290 #endif 00291 } 00292 00293 00294 // ====================================================================== 00295 // taken from WN_CopyNode () in wn.c. Optimized for IPA. 00296 // ====================================================================== 00297 00298 WN * 00299 IPO_CLONE::Copy_Node (const WN *src_wn) 00300 { 00301 INT16 next_prev_ptrs 00302 = (OPERATOR_has_next_prev(WN_operator(src_wn)) ? 1 : 0); 00303 INT16 size = (sizeof(WN) + 00304 (sizeof(WN *) * (max(0,WN_kid_count(src_wn)-2))) + 00305 next_prev_ptrs * (sizeof(mUINT64) + (2 * sizeof(WN *)))); 00306 00307 size = (size + 7) & (~7); // 8 byte aligned 00308 00309 /* avoid calling MEM_POOL_Alloc for every single node */ 00310 if (_raw_buf_size < size) { 00311 UINT new_size = _default_buf_size; 00312 while (new_size < size) 00313 new_size *= 2; 00314 _raw_buffer = (WN *)MEM_POOL_Alloc(WN_mem_pool_ptr, new_size); 00315 memset (_raw_buffer, '\0', new_size); 00316 _raw_buf_size = new_size; 00317 } 00318 00319 WN *wn = _raw_buffer; 00320 _raw_buffer = (WN *) ((char *) _raw_buffer + size); 00321 _raw_buf_size -= size; 00322 00323 if (next_prev_ptrs) { 00324 STMT_WN *stmt_wn = (STMT_WN *) wn; 00325 wn = (WN *)&(WN_real_fields(stmt_wn)); 00326 00327 WN_linenum(wn) = WN_linenum(src_wn); 00328 if (_cloned_node_file_id) 00329 USRCPOS_filenum(*(USRCPOS *)&(WN_linenum(wn))) = _cloned_node_file_id; 00330 } 00331 00332 wn->common = src_wn->common; 00333 WN_map_id(wn) = (WN_MAP_ID) (-1); 00334 00335 WN_Copy_u1u2 (wn, src_wn); 00336 WN_Copy_u3 (wn, src_wn); 00337 00338 return(wn); 00339 } // Copy_Node 00340 00341 00342 //====================================================================== 00343 // Walk the tree nodes and clone each one of them. Take care of the 00344 // STs, LABELs, INITOs and PREGs at the same time. The goal to to 00345 // minimize the work of the caller to Clone_Tree so that the caller 00346 // does not have to walk the tree and fix up the symtab-related pointers 00347 // as much. 00348 //====================================================================== 00349 WN * 00350 IPO_CLONE::Clone_Tree (WN *wn, ST *clone_st) 00351 { 00352 WN *ret_wn = NULL; 00353 WN* kid; 00354 WN* ret_kid; 00355 WN* prev_wn; 00356 OPCODE op; 00357 00358 if (wn == NULL) 00359 return NULL; 00360 00361 ret_wn = Copy_Node (wn); 00362 00363 op = WN_opcode(wn); 00364 00365 if (_sym) { 00366 00367 // when we are fixing the original tree after moving statics 00368 // and initos to the global symtab 00369 // which occur in the exception handling opcode 00370 // Exceptions now come as REGIONS (not as EXC_SCOPE_BEGINS) 00371 if ((WN_operator(wn) == OPR_REGION) && (WN_region_is_EH(wn))) { 00372 #if 0 00373 // ensure that sym is not null (which is true when promoting pstatics 00374 if (_sym && (!_sym->Get_Cloned_Scope_Tab())) { 00375 INITO_IDX init_idx = WN_ereg_supp(wn); 00376 if (init_idx) { 00377 // check if this is a result of moving initos to 00378 // the global symtab due to promoting static 00379 // variables 00380 INITO_IDX init_cp_idx; 00381 if (init_cp_idx = _sym->Get_Cloned_INITO_IDX(Get_INITO(init_idx))) { 00382 WN_ereg_supp(wn) = init_cp_idx; 00383 WN_ereg_supp(ret_wn) = init_cp_idx; 00384 } 00385 } 00386 } 00387 else 00388 #endif 00389 // else we need to fix up the inito's occuring in whirl 00390 Fix_INITO(ret_wn, wn); 00391 } 00392 00393 00394 /* handle entry points last so that Fix_ST() won't treat the entry 00395 points as a promoted statics */ 00396 if (op == OPC_ALTENTRY || op == OPC_FUNC_ENTRY) { 00397 if (_sym->Is_new_clone()) 00398 Set_Entry_Point (wn, ret_wn, clone_st); 00399 } 00400 else if (OPCODE_has_sym(op) || OPCODE_has_label(op)) 00401 Fix_ST (ret_wn, wn); 00402 00403 #if 0 00404 // fix the ST_base, this occurs in fortran for local 00405 // data statements and equivalences. see test case 00406 // mf77tests/rag_misc/test028.f, test029.f 00407 if (OPCODE_has_sym(op) && WN_st(wn)) { 00408 ST * st = _sym->Get_Cloned_ST(ST_base(WN_st(wn))); 00409 if (st) { 00410 Set_ST_sclass(ST_base(WN_st(wn)),SCLASS_AUTO); 00411 Set_ST_base_idx(WN_st(ret_wn), ST_st_idx(st)); 00412 Set_ST_base_idx(WN_st(wn), ST_st_idx(st)); 00413 } 00414 } 00415 #endif 00416 } 00417 00418 00419 if (op == OPC_BLOCK) { 00420 ret_kid = NULL; 00421 kid = WN_first (wn); 00422 if (kid) { 00423 ret_kid = Clone_Tree (kid); 00424 WN_prev (ret_kid) = NULL; 00425 WN_first(ret_wn) = ret_kid; 00426 00427 if (_parent_map) 00428 IPA_WN_MAP_Set (_cloned_map_tab, _parent_map, ret_kid, ret_wn); 00429 00430 kid = WN_next (kid); 00431 prev_wn = ret_kid; 00432 00433 while (kid) { 00434 ret_kid = Clone_Tree (kid); 00435 WN_next (prev_wn) = ret_kid; 00436 WN_prev (ret_kid) = prev_wn; 00437 00438 if (_parent_map) 00439 IPA_WN_MAP_Set (_cloned_map_tab, _parent_map, ret_kid, ret_wn); 00440 00441 prev_wn = ret_kid; 00442 kid = WN_next(kid); 00443 } 00444 00445 WN_next(ret_kid) = NULL; 00446 00447 } else 00448 WN_first(ret_wn) = NULL; 00449 00450 WN_last(ret_wn) = ret_kid; 00451 00452 } else { 00453 INT kidno; 00454 for (kidno = 0; kidno < WN_kid_count(wn); kidno++) { 00455 if (WN_kid (wn, kidno)) { 00456 ret_kid = Clone_Tree (WN_kid (wn, kidno)); 00457 00458 if (_parent_map) 00459 IPA_WN_MAP_Set (_cloned_map_tab, _parent_map, 00460 ret_kid, ret_wn); 00461 00462 WN_kid (ret_wn, kidno) = ret_kid; 00463 } else 00464 WN_kid (ret_wn, kidno) = NULL; 00465 } 00466 } 00467 00468 return ret_wn; 00469 00470 } // IPO_CLONE::Clone_Tree 00471 00472 // ====================================================================== 00473 // New_Clone should be called if the consumer needs to clone an entire 00474 // function. This will: 00475 // 1) create a local symtab for the cloned PU 00476 // 2) promote all the static variables from the original and cloned PU 00477 // to be global 00478 // 3) clone the tree of the PU and fix up all its symtab related pointers 00479 // 4) copy the symbol table flags from the orig. PU to the cloned PU 00480 // ====================================================================== 00481 00482 void 00483 IPO_CLONE::New_Clone (ST *clone_st) 00484 { 00485 _sym->New_Symtab(); 00486 00487 _sym->Promote_Statics (); 00488 00489 FmtAssert(_orig_pu,("IPO_CLONE::orig_pu is null")); 00490 ST * s = WN_st(_orig_pu); 00491 #if 0 00492 SYMTAB_IDX o_symtab = _sym->Get_Orig_Level(); 00493 // copy the initos for the local symtab 00494 if (o_symtab && PU_has_exc_scopes(Get_Current_PU())) 00495 { 00496 _sym->Copy_INITO(); 00497 } 00498 #endif 00499 00500 _cloned_map_tab = WN_MAP_TAB_Create (_mem); 00501 00502 _cloned_pu = Clone_Tree (_orig_pu, clone_st); 00503 00504 Copy_PU_Flags(ST_pu(s), ST_pu(WN_st(_cloned_pu))); 00505 00506 #ifndef _LEGO_CLONER 00507 _parent_map = IPA_WN_MAP_Create (_cloned_map_tab, _mem); 00508 WN_Parentize (_cloned_pu, _parent_map, _cloned_map_tab); 00509 #endif 00510 00511 } // IPO_CLONE::New_Clone 00512 00513 00514 00515 // ====================================================================== 00516 // IPO_SYMTAB Related Functions 00517 // ====================================================================== 00518 00519 // ====================================================================== 00520 // Fix up ST entries 00521 // ====================================================================== 00522 00523 template <> 00524 inline void 00525 IPO_SYMTAB::fix_table_entry<ST>::operator () (UINT idx, ST* st) const 00526 { 00527 Set_ST_st_idx(st, make_ST_IDX(idx, _sym->Get_cloned_level())); 00528 if (ST_IDX_level (ST_base_idx (st)) == _sym->Get_orig_level ()) 00529 Set_ST_base_idx(st, make_ST_IDX (ST_IDX_index (ST_base_idx (st)) + 00530 _sym->Get_cloned_st_last_idx (), 00531 _sym->Get_cloned_level ())); 00532 if (ST_base_idx(st) == ST_st_idx(st)) 00533 Set_ST_ofst(st, 0); 00534 switch (ST_sclass(st)) { 00535 case SCLASS_FORMAL: 00536 case SCLASS_FORMAL_REF: 00537 // We don't need these entries since they would be entered 00538 // as local symbols later during formal parameter processing 00539 Set_ST_is_not_used(st); 00540 break; 00541 default: 00542 break; 00543 } 00544 } 00545 00546 // ====================================================================== 00547 // Fix up INITO entries 00548 // ====================================================================== 00549 template <> 00550 inline void 00551 IPO_SYMTAB::fix_table_entry<INITO>::operator () (UINT idx, INITO* inito) const 00552 { 00553 Set_INITO_st_idx(*inito, make_ST_IDX(ST_IDX_index(INITO_st_idx(*inito))+_sym->Get_cloned_st_last_idx(), _sym->Get_cloned_level())); 00554 } 00555 00556 // ====================================================================== 00557 // Fix up ST_ATTR entries 00558 // ====================================================================== 00559 template <> 00560 inline void 00561 IPO_SYMTAB::fix_table_entry<ST_ATTR>::operator () (UINT idx, ST_ATTR* st_attr) const 00562 { 00563 Is_True (ST_ATTR_kind (*st_attr) == ST_ATTR_DEDICATED_REGISTER, 00564 ("expecting ST_ATTR_DEDICATED_REGISTER")); 00565 ST_IDX st_idx = ST_ATTR_st_idx (*st_attr); 00566 Set_ST_ATTR_st_idx (*st_attr, make_ST_IDX (ST_IDX_index (st_idx) + 00567 _sym->Get_cloned_st_last_idx(), 00568 ST_IDX_level (st_idx))); 00569 } 00570 00571 00572 // ====================================================================== 00573 // Main function to create/update the local symbol table for the cloned PU 00574 // Copy Local tables from orig to cloned SYMTAB using block copy 00575 // This is to take advantage of the NEW SYMTAB organizaion and minimize 00576 // individual symbol table entry insertion. Should be better for 00577 // performance. 00578 // If label_only is TRUE, only the LABEL table will be copied 00579 // ====================================================================== 00580 00581 void 00582 IPO_SYMTAB::Copy_Local_Tables(BOOL label_only) 00583 { 00584 00585 UINT32 start_idx = 0; 00586 00587 if (_is_new_clone == FALSE) 00588 start_idx = 1; // don't need to copy the 0'th entry 00589 00590 if (label_only == FALSE) { 00591 (void)Copy_array_range(*_orig_scope_tab[_orig_level].st_tab, 00592 *_cloned_scope_tab[_cloned_level].st_tab, 00593 start_idx, 00594 (_orig_scope_tab[_orig_level].st_tab)->Size()); 00595 00596 (void)Copy_array_range(*_orig_scope_tab[_orig_level].preg_tab, 00597 *_cloned_scope_tab[_cloned_level].preg_tab, 00598 start_idx, 00599 (_orig_scope_tab[_orig_level].preg_tab)->Size()); 00600 00601 (void)Copy_array_range(*_orig_scope_tab[_orig_level].st_attr_tab, 00602 *_cloned_scope_tab[_cloned_level].st_attr_tab, 00603 start_idx, 00604 (_orig_scope_tab[_orig_level].st_attr_tab)->Size()); 00605 00606 } 00607 else { 00608 // Need to reset _cloned_label_last_idx to reflect the current cloned SYMTAB 00609 Set_cloned_label_last_idx((_cloned_scope_tab[_cloned_level].label_tab)->Size()-1); 00610 Set_cloned_inito_last_idx((_cloned_scope_tab[_cloned_level].inito_tab)->Size()-1); 00611 } 00612 00613 (void)Copy_array_range(*_orig_scope_tab[_orig_level].inito_tab, 00614 *_cloned_scope_tab[_cloned_level].inito_tab, 00615 start_idx, 00616 (_orig_scope_tab[_orig_level].inito_tab)->Size()); 00617 00618 (void)Copy_array_range(*_orig_scope_tab[_orig_level].label_tab, 00619 *_cloned_scope_tab[_cloned_level].label_tab, 00620 start_idx, 00621 (_orig_scope_tab[_orig_level].label_tab)->Size()); 00622 00623 00624 if ((_is_new_clone == FALSE) && (label_only == FALSE)) { 00625 // The tables are appended to the end of the cloned table, so 00626 // we have to fix up the values in those tables 00627 00628 For_all_entries(*_cloned_scope_tab[_cloned_level].st_tab, 00629 fix_table_entry<ST> (this), _cloned_st_last_idx+1); 00630 00631 For_all_entries(*_cloned_scope_tab[_cloned_level].st_attr_tab, 00632 fix_table_entry<ST_ATTR> (this), _cloned_st_attr_last_idx+1); 00633 } 00634 00635 For_all_entries(*_cloned_scope_tab[_cloned_level].inito_tab, 00636 fix_table_entry<INITO> (this), _cloned_inito_last_idx+1); 00637 00638 } 00639 00640 00641 // ====================================================================== 00642 // This function should be called if a PU needs to be cloned into a 00643 // seperate PU, as needed in constant propagation. 00644 // Create a new scope_tab array for cloned_scope_tab and initialize it 00645 // then create a local symbol table for the cloned_scope_tab 00646 // ====================================================================== 00647 void 00648 IPO_SYMTAB::New_Symtab (void) 00649 { 00650 00651 FmtAssert(!PU_has_altentry(Pu_Table[ST_pu(_orig_scope_tab[_orig_level].st)]), 00652 ("Can't clone procedures with multiple entry point")); 00653 00654 SCOPE *_cloned_scope_tab = (SCOPE *) MEM_POOL_Alloc (_mem, 00655 (_orig_level+1) * sizeof(SCOPE)); 00656 00657 00658 // Copy all except the current _level for this cloned symtab 00659 // memcpy(_cloned_scope_tab, _orig_scope_tab, _orig_level*sizeof(SCOPE)); 00660 SYMTAB_IDX i; 00661 for (i = 1; i < _orig_level; ++i) { 00662 _cloned_scope_tab[i] = _orig_scope_tab[i]; 00663 } 00664 00665 Set_Cloned_Symtab(_cloned_scope_tab); 00666 00667 // Set the current Scope_tab to the cloned one 00668 // Scope_tab = _cloned_scope_tab; 00669 SCOPE_CONTEXT switch_scope(_cloned_scope_tab); 00670 00671 // The following would creat instances of ST_TAB, LABEL_TABLE, PREG_TAB and 00672 // INITO_TAB 00673 New_Scope(_orig_level, _mem, FALSE); 00674 00675 Copy_Local_Tables(FALSE); 00676 00677 } // IPO_SYMTAB::New_Symtab 00678 00679 00680 // ====================================================================== 00681 // This function should be called for inlining purposes -- the PU 00682 // is NOT cloned as a seperate PU but is actually integrated into 00683 // another PU. 00684 // Append symtab from orig_scope_tab to cloned_scope_tab 00685 // If label_only is TRUE, only the LABEL table will be copied 00686 // ====================================================================== 00687 void 00688 IPO_SYMTAB::Update_Symtab (BOOL label_only) 00689 { 00690 00691 FmtAssert(!PU_has_altentry(Pu_Table[ST_pu(_orig_scope_tab[_orig_level].st)]), 00692 ("Can't inline procedures with multiple entry point")); 00693 00694 FmtAssert(_cloned_scope_tab, ("Cloned scope tab is not set up in Update_Symtab")); 00695 00696 Copy_Local_Tables(label_only); 00697 } 00698 00699 // ====================================================================== 00700 // Walk the ST list and for those that are PU-level static, move them and 00701 // their correcponding INITO to the Global Symtab 00702 // ====================================================================== 00703 00704 template <> 00705 inline void 00706 IPO_SYMTAB::promote_entry<ST>::operator () (UINT idx, ST* old_st) const 00707 { 00708 ST *copy_st; 00709 00710 switch (ST_sclass(old_st)) { 00711 case SCLASS_PSTATIC: 00712 case SCLASS_FSTATIC: 00713 copy_st = _sym->IPO_Copy_ST(old_st, GLOBAL_SYMTAB); 00714 Set_ST_sclass(copy_st, SCLASS_FSTATIC); 00715 Set_ST_is_not_used(old_st); 00716 break; 00717 default: 00718 break; 00719 } 00720 } 00721 00722 // ====================================================================== 00723 // Walk the ST list and for those that are PU-level static that have 00724 // a different base, need to fix it 00725 // ====================================================================== 00726 00727 template <> 00728 inline void 00729 IPO_SYMTAB::fix_base<ST>::operator () (UINT idx, ST* old_st) const 00730 { 00731 ST *copy_st = NULL; 00732 00733 switch (ST_sclass(old_st)) { 00734 case SCLASS_PSTATIC: 00735 case SCLASS_FSTATIC: 00736 copy_st = _sym->Get_Cloned_ST(old_st); 00737 Is_True(copy_st, ("PSTATIC symbol must have been promoted at this point")); 00738 if (ST_base_idx (old_st) != ST_st_idx (old_st)) { 00739 // Need to fix up its base idx 00740 ST *st = _sym->Get_Cloned_ST(ST_base(old_st)); 00741 Is_True(st, ("Base of PSTATIC symbol must have been promoted at this point")); 00742 Set_ST_base_idx(copy_st, ST_st_idx(st)); 00743 } 00744 break; 00745 default: 00746 break; 00747 } 00748 } 00749 00750 template <> 00751 inline void 00752 IPO_SYMTAB::promote_entry<INITO>::operator () (UINT idx, INITO* old_inito) const 00753 { 00754 // If the ST entry of the INITO has been promoted, then need to 00755 // promote this INITO also 00756 ST *cloned_ST = _sym->Get_Cloned_ST(INITO_st(old_inito)); 00757 if (cloned_ST) { 00758 INITO_IDX new_inito_idx = New_INITO(ST_st_idx(cloned_ST), old_inito->val); 00759 _sym->Set_Cloned_INITO(old_inito, new_inito_idx); 00760 } 00761 } 00762 00763 void 00764 IPO_SYMTAB::Promote_Statics (void) 00765 { 00766 00767 For_all (St_Table, _orig_level, promote_entry<ST>(this)); 00768 For_all (St_Table, _orig_level, fix_base<ST>(this)); 00769 For_all (Inito_Table, _orig_level, promote_entry<INITO>(this)); 00770 00771 } // IPO_SYMTAB::Promote_Statics 00772 00773 // ====================================================================== 00774 // Copy the ST, INITO (from orig_scope_tab, to cloned_scope_tab) 00775 // ====================================================================== 00776 ST* 00777 IPO_SYMTAB::IPO_Copy_ST (ST* st, SYMTAB_IDX scope) 00778 { 00779 ST* new_st; 00780 00781 new_st = Get_Cloned_ST(st); 00782 00783 // comma nodes ==> there can be calls within calls : nested calls 00784 // hence we use cached name ONLY if its the same as the new_name 00785 // 00786 if (new_st && (scope == GLOBAL_SYMTAB)) 00787 return new_st; 00788 00789 // Set the current Scope_tab to the cloned one 00790 // Scope_tab = _cloned_scope_tab; 00791 SCOPE_CONTEXT switch_scope(_cloned_scope_tab); 00792 00793 new_st = Copy_ST_No_Base(st, scope); 00794 00795 Set_Cloned_ST(st, new_st); 00796 00797 return new_st; 00798 } // IPO_SYMTAB::IPO_Copy_ST 00799 00800 00801 INITO_IDX 00802 IPO_SYMTAB::Copy_INITO(INITO_IDX orig_init_idx) 00803 { 00804 FmtAssert(FALSE,("IPO_SYMTAB::Copy_INITO NOT IMPLEMENTED FOR NEW SYMTAB\n")); 00805 return orig_init_idx; 00806 } 00807 00808 void 00809 IPO_SYMTAB::Set_Cloned_ST (ST *old_st, ST* new_st) 00810 { 00811 00812 _hash_maps->Insert(old_st, new_st); 00813 } 00814 00815 void 00816 IPO_SYMTAB::Set_Cloned_INITO (INITO *old_inito, INITO_IDX new_inito) 00817 { 00818 00819 _hash_maps->Insert(old_inito, (void *)new_inito); 00820 } 00821 00822 INITV_IDX 00823 IPO_SYMTAB::Clone_INITVs_For_EH (INITV_IDX inov, INITO_IDX ino) 00824 { 00825 INITV_IDX head=0, tail=0; 00826 00827 while (inov) { 00828 INITV_IDX cloned_iv = Copy_INITV(tail, ino, inov); 00829 INITV &iv = Initv_Table[inov]; 00830 INITV &c_iv = Initv_Table[cloned_iv]; 00831 00832 if (head == 0) 00833 head = tail = cloned_iv; 00834 00835 tail = cloned_iv; 00836 00837 switch (INITV_kind(iv)) { 00838 case INITVKIND_SYMOFF: 00839 { 00840 ST* initv_st = Get_Orig_ST(INITV_st(iv)); 00841 ST* cloned_st; 00842 00843 if (ST_level(initv_st) == GLOBAL_SYMTAB) 00844 cloned_st = initv_st; 00845 else 00846 cloned_st = Get_Cloned_ST(initv_st); 00847 00848 if (cloned_st == NULL) { 00849 cloned_st = Get_ST(initv_st); 00850 00851 switch (ST_sclass(cloned_st)) { 00852 case SCLASS_FORMAL: 00853 case SCLASS_FORMAL_REF: 00854 if (ST_is_not_used(cloned_st)) { 00855 // This ST should have been copied and turned into 00856 // an AUTO var 00857 cloned_st = Get_Cloned_ST(cloned_st); 00858 Is_True(cloned_st, ("FORMAL ST should have been cloned")); 00859 } 00860 break; 00861 default: 00862 break; 00863 } 00864 } 00865 00866 Set_INITV_st (cloned_iv, ST_st_idx(cloned_st)); 00867 } 00868 break; 00869 case INITVKIND_SYMDIFF: 00870 case INITVKIND_SYMDIFF16: 00871 { 00872 ST* initv_st = Get_Orig_ST(INITV_st2(iv)); 00873 ST* cloned_st; 00874 00875 if (ST_level(initv_st) == GLOBAL_SYMTAB) 00876 cloned_st = initv_st; 00877 else 00878 cloned_st = Get_Cloned_ST(initv_st); 00879 00880 if (cloned_st == NULL) { 00881 cloned_st = Get_ST(initv_st); 00882 00883 switch (ST_sclass(cloned_st)) { 00884 case SCLASS_FORMAL: 00885 case SCLASS_FORMAL_REF: 00886 if (ST_is_not_used(cloned_st)) { 00887 // This ST should have been copied and turned into 00888 // an AUTO var 00889 cloned_st = Get_Cloned_ST(cloned_st); 00890 Is_True(cloned_st, ("FORMAL ST should have been cloned")); 00891 } 00892 break; 00893 default: 00894 break; 00895 } 00896 } 00897 Set_INITV_lab1 (cloned_iv, 00898 INITV_lab1(iv)+Get_cloned_label_last_idx()); 00899 Set_INITV_st2 (cloned_iv, ST_st_idx(cloned_st)); 00900 } 00901 break; 00902 00903 case INITVKIND_LABEL: 00904 Set_INITV_lab (cloned_iv, INITV_lab(iv)+Get_cloned_label_last_idx()); 00905 break; 00906 00907 case INITVKIND_BLOCK: 00908 Set_INITV_blk(cloned_iv, Clone_INITVs_For_EH (INITV_blk(iv), ino)); 00909 break; 00910 00911 default: 00912 break; 00913 } 00914 00915 00916 inov = INITV_next(iv); 00917 } 00918 00919 return head; 00920 00921 } // IPO_SYMTAB::Clone_INITVs_For_EH 00922 00923 // --------------------------------------------------------------------- 00924 // 00925 // IPO_ADDR_HASH Member Functions 00926 // 00927 // --------------------------------------------------------------------- 00928 00929 const INT IPO_ADDR_HASH::hash_size; 00930 00931 void 00932 IPO_ADDR_HASH::Insert (void *orig, void *copy) 00933 { 00934 struct hash_node *p = CXX_NEW (struct hash_node, mem); 00935 INT hash_value = hash ((INT)(INTPS) orig); 00936 00937 p->orig = orig; 00938 p->copy = copy; 00939 p->next = table[hash_value]; 00940 table[hash_value] = p; 00941 table_empty = FALSE; 00942 00943 } // IPO_ADDR_HASH::Insert 00944 00945 void * 00946 IPO_ADDR_HASH::Lookup (void *key) 00947 { 00948 if (key == 0 || table_empty) 00949 return 0; 00950 00951 INT hash_value = hash ((INT)(INTPS) key); 00952 struct hash_node *p = table[hash_value]; 00953 00954 while (p) { 00955 if (p->orig == key) 00956 return p->copy; 00957 p = p->next; 00958 } 00959 00960 return 0; 00961 } // IPO_ADDR_HASH::Lookup 00962 00963 00964 //-------------------------------------------------------------------- 00965 // this routine is used to reset the copied entry. This is needed 00966 // for fortran based pu static variables 00967 //-------------------------------------------------------------------- 00968 void 00969 IPO_ADDR_HASH::Reset_Lookup (void *key) 00970 { 00971 if (key == 0 || table_empty) 00972 return; 00973 00974 INT hash_value = hash ((INT)(INTPS) key); 00975 struct hash_node *p = table[hash_value]; 00976 struct hash_node *prev = table[hash_value]; 00977 00978 while (p) { 00979 if (p->orig == key) 00980 { 00981 if (table[hash_value] == p) 00982 table[hash_value] = p->next; 00983 else 00984 prev->next = p->next; 00985 CXX_DELETE(p, mem); 00986 return; 00987 } 00988 prev = p; 00989 p = p->next; 00990 } 00991 } // IPO_ADDR_HASH::Reset_Lookup 00992