Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
clone.h
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 /* -*-Mode: c++;-*- (Tell emacs to use c++ mode) */
00037 #ifndef clone_INCLUDED
00038 #define clone_INCLUDED
00039 // ====================================================================
00040 // ====================================================================
00041 //
00042 //
00043 // Revision history:
00044 //  22-Sep-97 - Original Version 
00045 //
00046 // Description:
00047 //
00048 // ======================= PU and Symtab clone routines =======================
00049 
00050 // CLONE LEGALITY:
00051 // (a) Cannot clone recursive PUs (TODO: investigate how to do this)
00052 // (b) Cannot clone alternate entry pts PUS
00053 
00054 // CLONE USAGE:
00055 // * During inlining (clone callee)
00056 // * During constant propogation (function cloning): 
00057 //   - need to generate unique names, need to create new "scope" struct
00058 
00059 
00060 
00061 #ifndef __SGI_STL_ALGO_H
00062 
00063 # include <algorithm>
00064 
00065 #endif // __SGI_STL_ALGO_H
00066 
00067 #ifndef __SGI_STL_HASH_MAP_H
00068 
00069 # ifndef _USE_STL_EXT
00070 # include <map>
00071 # else
00072 # include <hash_map>
00073 # endif
00074 
00075 #endif /* __SGI_STL_HASHTABLE_H */
00076 
00077 using namespace std;
00078 
00079 
00080 #ifndef CXX_MEMORY_INCLUDED
00081 #include "cxx_memory.h"                 // For CXX_NEW
00082 #endif /* CXX_MEMORY_INCLUDED */
00083 
00084 #include "defs.h"
00085 
00086 #include "symtab.h"                     // for Scope_tab
00087 #include "wn.h"                         // includes wn_map.h
00088 
00089 
00090 // ======================================================================
00091 // IPO_SYMTAB class: encapsulates LOCAL symbol table info
00092 // Under the new symtab design, the local symbol table contains info on
00093 // a. LABEL_TAB, PREG_TAB (local ONLY)
00094 // b. ST_TAB, INITO_TAB, INITV_TAB, and ST_ATTR_TAB (local/global)
00095 // Maps SYMTAB_IDX (original symtab) ---> SYMTAB_IDX (cloned symtab)
00096 // ======================================================================
00097 // (1) Function Inlining
00098 //     - create copy of callee whirl tree
00099 //     - Promote PU Statics to File Statics (These go into IPA Global symtab)
00100 //     - Append callee local tables to caller local tables
00101 //       (label, preg, st, inito): compute offsets for each of these tables
00102 //     - Assume: Global Tables already fixed when PUs are read in 
00103 //       ie IPA Global symtab is all set and has necessary maps
00104 //     - Fix/Patch ST and TY in callee using offsets and Global Maps
00105 //     - Clone INITVs, INITOs
00106 // (2) Function Cloning
00107 //    - create copy of callee whirl tree
00108 //    - Note: pu, cloned_pu are in same_file
00109 //    - Create copy of scope[orig_symtab_idx] : the "new" symtab for cloned pu
00110 //      (copy all 4 local tables: label, preg, st, inito
00111 //    - Note: during function cloning "global" tables don't change EXCEPT
00112 //    - Create new ST in global st table for "cloned" pu
00113 //    - Fix/Patch local table info in cloned pu (using the copy of scope[..]
00114 //    - Promote PU Statics to File Statics (These go into IPA Global symtab)
00115 //      Needed because both pu and cloned_pu need to access same static
00116 // 
00117 
00118 // Generic hash table for mapping a pair of addresses.  Used for
00119 // mapping the address of a TY/ST to that of its copy. 
00120 //
00121 class IPO_ADDR_HASH {
00122 
00123 private:
00124 
00125   static const INT hash_size = 256;
00126 
00127   struct hash_node {
00128     void *orig;
00129     void *copy;
00130     struct hash_node *next;
00131   } *table[hash_size];
00132 
00133   MEM_POOL *mem;
00134 
00135   BOOL table_empty;
00136 
00137   INT hash (INT key) {
00138     return (key & 0xff) ^ ((key >> 8) & 0xff);
00139   };
00140 
00141 public:
00142 
00143   IPO_ADDR_HASH (MEM_POOL *m) {
00144     mem = m;
00145     table_empty = TRUE;
00146     memset (table, '\0', sizeof(table));
00147   };
00148 
00149   void Insert (void *orig, void *copy);
00150 
00151   void *Lookup (void *);
00152 
00153   void Clear (void) {
00154     if (!table_empty) {
00155       memset (table, '\0', sizeof(table));
00156       table_empty = TRUE;
00157     }
00158   };
00159 
00160   void Reset_Lookup (void *key);
00161 }; // IPO_ADDR_HASH
00162 
00163 
00164 class IPO_SYMTAB {
00165 
00166 private:
00167   
00168   SCOPE *_orig_scope_tab;             // Original (input) scope table
00169   SCOPE *_cloned_scope_tab;           // Cloned   (output) scope table
00170   SYMTAB_IDX _orig_level;             // The level of current PU in orig scope_table
00171   SYMTAB_IDX _cloned_level;           // The level of cloned PU in cloned scope_table
00172                                       // Same as _orig_level for PU cloning
00173   MEM_POOL *_mem;                     // for temp. data structures
00174   IPO_ADDR_HASH *_hash_maps;          // maps for lookup
00175                                       // used for initos and STs
00176 
00177   BOOL _same_file;                    // both symtabs come from the same file
00178   UINT _cloned_st_last_idx;           // If the table is newly cloned,
00179                                       // then this has value = 0
00180                                       // otherwise it contains the
00181                                       // last st_idx of the ST_TAB
00182                                       // of the passed-in _cloned_level
00183                                       // usually for inlining purpose
00184   UINT _cloned_inito_last_idx;        // If the table is newly cloned,
00185                                       // then this has value = 0
00186                                       // otherwise it contains the
00187                                       // last inito_idx of the INITO_TAB
00188                                       // of the passed-in _cloned_level
00189                                       // usually for inlining purpose
00190   UINT _cloned_label_last_idx;        // If the table is newly cloned,
00191                                       // then this has value = 0
00192                                       // otherwise it contains the
00193                                       // last st_idx of the LABEL_TAB
00194                                       // of the passed-in _cloned_level
00195                                       // usually for inlining purpose
00196   UINT _cloned_preg_last_idx;         // If the table is newly cloned,
00197                                       // then this has value = 0
00198                                       // otherwise it contains the
00199                                       // last preg_idx of the PREG_TAB
00200                                       // of the passed-in _cloned_level
00201   UINT _cloned_st_attr_last_idx;      // If the table is newly cloned,
00202                                       // then this has value = 0
00203                                       // otherwise it contains the
00204                                       // last st_attr_idx of the ST_ATTR_TAB
00205                                       // of the passed-in _cloned_level
00206   BOOL _is_new_clone;                 // True if really creates a brand new
00207                                       // PU, false as in the case of inlining
00208         
00209 
00210   void Copy_Local_Tables(BOOL);       // LABEL, PREG, ST, INITO, ST_ATTR
00211 
00212   template <class T>
00213   struct fix_table_entry
00214   {
00215     IPO_SYMTAB *_sym;
00216 
00217     fix_table_entry(IPO_SYMTAB *sym): _sym(sym) {}
00218     
00219     void operator () (UINT idx, T *entry) const;
00220   };
00221 
00222   template <class T>
00223   struct promote_entry 
00224   {
00225     IPO_SYMTAB *_sym;
00226 
00227     promote_entry(IPO_SYMTAB *sym): _sym(sym) {}
00228 
00229     void operator () (UINT idx, T* entry) const;
00230   };
00231 
00232   template <class T>
00233   struct fix_base 
00234   {
00235     IPO_SYMTAB *_sym;
00236 
00237     fix_base(IPO_SYMTAB *sym): _sym(sym) {}
00238 
00239     void operator () (UINT idx, T* entry) const;
00240   };
00241 
00242 public:
00243 
00244 
00245   // Constructor
00246   // Calls to do cloning for constant propagation
00247   IPO_SYMTAB (SCOPE *orig_scope_tab, 
00248                         SYMTAB_IDX symtab_idx, MEM_POOL *m) :
00249   _orig_scope_tab(orig_scope_tab), _cloned_scope_tab(NULL), _mem(m), 
00250   _same_file(TRUE), _orig_level(symtab_idx), _cloned_level(symtab_idx) {
00251     _cloned_st_last_idx = 0;
00252     _cloned_inito_last_idx = 0;
00253     _cloned_label_last_idx = 0;
00254     _cloned_preg_last_idx = 0;
00255     _cloned_st_attr_last_idx = 0;
00256     _is_new_clone = TRUE;
00257     _hash_maps = CXX_NEW (IPO_ADDR_HASH (m), m);
00258   };
00259 
00260   // Calls to do cloning for inlining
00261   IPO_SYMTAB (SCOPE *orig_scope_tab, SCOPE *cloned_scope_tab, 
00262                         SYMTAB_IDX orig_symtab_idx, 
00263                         SYMTAB_IDX cloned_symtab_idx, MEM_POOL *m, 
00264                         BOOL Same_file = TRUE) :
00265   _orig_scope_tab(orig_scope_tab), _cloned_scope_tab(cloned_scope_tab),
00266    _mem(m), _same_file(Same_file), _orig_level(orig_symtab_idx), _cloned_level(cloned_symtab_idx) {
00267     _cloned_st_last_idx = cloned_scope_tab[cloned_symtab_idx].st_tab->Size()-1;
00268     _cloned_inito_last_idx = cloned_scope_tab[cloned_symtab_idx].inito_tab->Size()-1;
00269     _cloned_label_last_idx = cloned_scope_tab[cloned_symtab_idx].label_tab->Size()-1;
00270     _cloned_preg_last_idx = cloned_scope_tab[cloned_symtab_idx].preg_tab->Size()-1;
00271     _cloned_st_attr_last_idx = cloned_scope_tab[cloned_symtab_idx].st_attr_tab->Size()-1;
00272     _is_new_clone = FALSE;
00273     _hash_maps = CXX_NEW (IPO_ADDR_HASH (m), m);
00274   };
00275 
00276   // Member functions: initializer
00277   void New_Symtab ();                // Creates "new" cloned_scope_tab
00278                                      // Used for cloning
00279 
00280   void Update_Symtab (BOOL);         // Appends to cloned_scope_tab
00281                                      // Used for inlining
00282 
00283   void Promote_Statics ();           // move local statics to IPA global symtab
00284 
00285   INITO_IDX Copy_INITO(INITO_IDX orig_init=0);
00286                                      // Initialized data objects
00287                                      // special case for C++ EH
00288 
00289   INITV_IDX Clone_INITVs_For_EH (INITV_IDX , INITO_IDX );
00290 
00291   // member access functions
00292 
00293   SCOPE* Get_orig_scope_tab    () const { return _orig_scope_tab; }
00294   SCOPE* Get_cloned_scope_tab   () const { return _cloned_scope_tab; }
00295   SYMTAB_IDX Get_orig_level     () const { return _orig_level;}
00296   SYMTAB_IDX Get_cloned_level   () const { return _cloned_level;}
00297   UINT Get_cloned_st_last_idx   () const { return _cloned_st_last_idx;}
00298   UINT Get_cloned_inito_last_idx() const { return _cloned_inito_last_idx;}
00299   void Set_cloned_inito_last_idx   (UINT idx) { _cloned_inito_last_idx = idx;}
00300   UINT Get_cloned_label_last_idx   () const { return _cloned_label_last_idx;}
00301   void Set_cloned_label_last_idx   (UINT idx) { _cloned_label_last_idx = idx;}
00302   UINT Get_cloned_preg_last_idx() const { return _cloned_preg_last_idx;}
00303   UINT Get_cloned_st_attr_last_idx() const { return _cloned_st_attr_last_idx;}
00304   BOOL Is_new_clone             () const { return _is_new_clone; }
00305   BOOL Same_file                () const { return _same_file; }
00306 
00307   void Set_Cloned_Symtab (SCOPE *scope_tab) { 
00308         _cloned_scope_tab = scope_tab;
00309   }
00310 
00311   void Set_Cloned_ST(ST* old_st, ST* new_st);
00312 
00313   ST* Get_Cloned_ST(ST* old_st) {return (ST *) _hash_maps->Lookup (old_st); };
00314 
00315   void Hide_Cloned_ST (ST *st) { _hash_maps->Reset_Lookup (st); };
00316 
00317   void Set_Cloned_INITO(INITO* old_inito, INITO_IDX new_inito);
00318 
00319   INITO_IDX Get_Cloned_INITO_IDX(INITO* old_inito) {
00320         return (INITO_IDX)(INTPTR)_hash_maps->Lookup (old_inito);
00321   }
00322 
00323   ST* Get_ST(ST* old_st) {      // Get the copy of the orig st
00324         return ((ST_level(old_st) != _orig_level)? old_st : &_cloned_scope_tab[_cloned_level].st_tab->Entry(ST_index(old_st)+_cloned_st_last_idx));
00325   }
00326 
00327   INITO_IDX Get_INITO_IDX(INITO_IDX old_inito) {
00328         return make_INITO_IDX(INITO_IDX_index(old_inito)+_cloned_inito_last_idx, _cloned_level);
00329   }
00330 
00331   INITO* Get_INITO(INITO_IDX idx) {
00332         SYMTAB_IDX level = INITO_IDX_level (idx);
00333         UINT32 index = INITO_IDX_index (idx);
00334         return (&_orig_scope_tab[_orig_level].inito_tab->Entry(index));
00335   }
00336 
00337   ST* Get_Orig_ST(ST_IDX idx) {
00338         return (&_orig_scope_tab[ST_IDX_level(idx)].st_tab->Entry(ST_IDX_index(idx)));
00339   }
00340 
00341   ST* IPO_Copy_ST (ST* st, SYMTAB_IDX scope);
00342 
00343   BOOL Is_Cloned_ST(ST* st) { return ((ST_level(st) != _cloned_level) || 
00344         (ST_index(st) > _cloned_st_last_idx)); }
00345 
00346 }; // IPO_SYMTAB
00347 
00348 // ======================================================================
00349 // class IPO_CLONE 
00350 // ======================================================================
00351 // used during fn INLINING and fn CLONING
00352 
00353 // maps a PU into a cloned PU
00354 // Main functions:  used by others (such as IPO, IPA)
00355 //  a. Constructor
00356 //  b. Clone_Tree
00357 //  c. New_Clone
00358 
00359 class IPO_CLONE {
00360 
00361 private:
00362 
00363   WN *_orig_pu;                  // original tree
00364   WN *_cloned_pu;                // cloned tree
00365 
00366   IPO_SYMTAB *_sym;              // handle cloning of symtab
00367 
00368   static INT _label;             // unique labels for cloned function name
00369   static const INT _default_buf_size = 2048; 
00370 
00371   WN_MAP_TAB *_orig_map_tab;     // map tables
00372   WN_MAP_TAB *_cloned_map_tab;   
00373 
00374   WN_MAP _parent_map;            // parent pointers
00375 
00376   MEM_POOL *_mem;                // mem pool for cloned map tables
00377 
00378   BOOL _same_file;               // if src and dest are from the same file
00379 
00380   mUINT16 _cloned_node_file_id;  // file id of a cloned node in the
00381                                  // current file, for cross-file inlining (DST)
00382 
00383   WN *_raw_buffer;               // pre-allocated buffer for copied nodes
00384   UINT _raw_buf_size;
00385 
00386   // For each of the next three functions use the offsets determined by
00387   // (1)  copying callee tables into caller tables (inlining) OR by
00388   // (2)  maps from orig_symtab to cloned_symtab
00389 
00390   void Fix_ST (WN *, WN *);     // fix the ST pointer in a tree node: 
00391   void Fix_TY (WN *, WN *);     // fix the TY pointer in a tree node
00392   void Fix_INITO(WN* cloned_wn, WN* wn);// fix the INITO in a tree node
00393 
00394   WN *Copy_Node (const WN *src_wn); // copy one tree node
00395 
00396 public:
00397   
00398   // Constructor(s) used by MAIN IPA to clone a WN *pu
00399   // 1. Used only in function cloning (_same_file is true: also for IPO_SYMTAB)
00400   // Caller needs to specify scope_tab and symtab_idx of this PU
00401 
00402   IPO_CLONE (WN *pu, 
00403              SCOPE *scope_tab,
00404              SYMTAB_IDX symtab_idx, 
00405              WN_MAP_TAB* map_tab,
00406              MEM_POOL *map_pool,
00407              MEM_POOL *m) : 
00408     _orig_map_tab(map_tab), _cloned_map_tab(NULL), _parent_map(0),
00409     _sym(CXX_NEW (IPO_SYMTAB (scope_tab, symtab_idx, m), m)), 
00410     _orig_pu(pu), _cloned_pu(NULL), 
00411     _mem(map_pool),             // mem pool for map tables
00412     _cloned_node_file_id(0), 
00413     _same_file(TRUE), _raw_buf_size(0)
00414   {
00415   };
00416 
00417 
00418   // 2. used only by inlining 
00419   //    a. to make copy of callee, and patch symtabs
00420   //    b. to make copy of whirl tree
00421   // Called from IPO_Copy_Tree defined in ipo_clone.cxx, used in ipo_inline.cxx
00422   IPO_CLONE (WN_MAP_TAB *caller, 
00423              WN_MAP_TAB *callee, 
00424              WN_MAP parent,
00425              SCOPE *callee_scope_tab=NULL,
00426              SCOPE *caller_scope_tab=NULL,
00427              SYMTAB_IDX callee_symtab_idx=0, 
00428              SYMTAB_IDX caller_symtab_idx=0, 
00429              IPO_SYMTAB *cloned_symtab=NULL,
00430              MEM_POOL *map_pool=NULL, 
00431              BOOL same_file=TRUE,
00432              mUINT16 filenum=0) :
00433     _orig_pu(NULL), _cloned_pu(NULL),
00434 #if (!(defined(linux) && defined(_LP64)))
00435     _sym(cloned_symtab? cloned_symtab : 
00436         (callee_scope_tab == NULL? NULL : 
00437                                   CXX_NEW(IPO_SYMTAB(callee_scope_tab,
00438                                                     caller_scope_tab, 
00439                                                     callee_symtab_idx, 
00440                                                     caller_symtab_idx, 
00441                                                     Malloc_Mem_Pool, same_file),
00442                                                     Malloc_Mem_Pool))),
00443 #endif /* (!(defined(linux) && defined(_LP64))) */
00444     _orig_map_tab (callee), _cloned_map_tab(caller), _parent_map(parent),
00445     _mem(map_pool),             // mem pool for map tables
00446     _cloned_node_file_id(filenum), 
00447     _same_file(same_file), _raw_buf_size (0)
00448   {
00449 #if defined(linux) && defined(_LP64)
00450     if ((cloned_symtab == NULL) && (callee_scope_tab != NULL))
00451       _sym = CXX_NEW (IPO_SYMTAB (callee_scope_tab,
00452                                   caller_scope_tab, 
00453                                   callee_symtab_idx, 
00454                                   caller_symtab_idx, 
00455                                   Malloc_Mem_Pool, same_file),
00456                       Malloc_Mem_Pool);
00457     else
00458       _sym = cloned_symtab;
00459 #endif /* defined(linux) && defined(_LP64) */
00460   };
00461 
00462   // 3. used only for cloning dynamic array bound expressions
00463   IPO_CLONE (IPO_SYMTAB *ipo_symtab) : 
00464     _orig_map_tab(NULL), _cloned_map_tab(NULL), _parent_map(0),
00465     _sym(ipo_symtab), 
00466     _orig_pu(NULL), _cloned_pu(NULL),
00467     _mem(NULL), 
00468     _cloned_node_file_id(0), 
00469     _same_file(ipo_symtab->Same_file()), _raw_buf_size(0)
00470   {
00471   };
00472 
00473   // Extern interface 
00474   void Set_Entry_Point (WN *, WN *, ST *); // Set node as entry point
00475 #if 0
00476   void Set_Entry_Point (WN *, WN *);       // Set node as entry point
00477 #endif
00478 
00479   // Actual copying of the tree
00480   WN *Clone_Tree (WN *, ST *clone_st = NULL); 
00481 
00482   // Create a new copy of _sym
00483   void New_Clone (ST *clone_st = NULL);   
00484 
00485   // Promote Statics 
00486   void Promote_Statics() { _sym ->Promote_Statics();}
00487 
00488   //data Access functions
00489   WN *Get_Cloned_PU () const { return _cloned_pu; };
00490 
00491   SCOPE* Get_Cloned_Symtab () const { return _sym->Get_cloned_scope_tab (); };
00492 
00493   char *Get_Func_Name () { return ST_name(WN_st(_cloned_pu)); };
00494 
00495   WN_MAP_TAB *Get_Cloned_maptab () { return _cloned_map_tab; };
00496 
00497   WN_MAP Get_parent_map () { return _parent_map; };
00498 
00499   ST *Get_Func_ST () { return WN_st(_cloned_pu); };
00500 
00501   IPO_SYMTAB *Get_sym() { return _sym; };
00502 
00503   
00504 }; // IPO_CLONE
00505 
00506 
00507 #endif // clone_INCLUDED
00508 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines