Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
clone.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  * $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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines