Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
symtab.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 
00037 #ifdef USE_PCH
00038 #include "common_com_pch.h"
00039 #endif /* USE_PCH */
00040 #pragma hdrstop
00041 #include <stdio.h>
00042 #include <alloca.h>
00043 
00044 #include <algorithm>
00045 #include <string>
00046 #include <map>
00047 #include "HashTable.h"
00048 using namespace stlCompatibility;
00049 
00050 #include "defs.h"
00051 #include "config.h"
00052 #include "tracing.h"                    // for DBar
00053 #include "cxx_memory.h"                 // for CXX_NEW
00054 
00055 #include "symtab.h"
00056 #include "irbdata.h"                    // for INITO_st_idx
00057 #include "ir_a2b_util.h"                // for b2a and a2b utilities
00058 #include "const.h"                      // for MAX_SYMBOLIC_CONST_NAME_LEN
00059 #include "ttype.h"
00060 #include "targ_sim.h"
00061 #include "upc_symtab_utils.h"
00062 
00063 // global tables
00064 FILE_INFO       File_info;
00065 SCOPE           *Scope_tab;
00066 PU_TAB          Pu_Table;
00067 SYMBOL_TABLE    St_Table;
00068 TY_TAB          Ty_tab;
00069 TYPE_TABLE      Ty_Table;
00070 FLD_TAB         Fld_Table;
00071 TYLIST_TAB      Tylist_Table;
00072 ARB_TAB         Arb_Table;
00073 TCON_TAB        Tcon_Table;
00074 INITV_TAB       Initv_Table;
00075 INITO_TABLE     Inito_Table;
00076 PREG_TABLE      Preg_Table;
00077 LABEL_TABLE     Label_Table;
00078 BLK_TAB         Blk_Table;
00079 ST_ATTR_TABLE   St_Attr_Table;
00080 
00081 SYMTAB_IDX Current_scope;               // index to current scope
00082 PU *Current_pu;                         // ptr to current PU
00083 
00084 //----------------------------------------------------------------------
00085 // ST-related utilities
00086 //----------------------------------------------------------------------
00087 
00088 INT64
00089 ST_size (const ST *st)
00090 {
00091   switch (ST_class(st)) {
00092   case CLASS_BLOCK:
00093     return STB_size(st);
00094   case CLASS_VAR:
00095   case CLASS_PREG:
00096   case CLASS_PARAMETER:
00097     return TY_size(ST_type(st));
00098   case CLASS_CONST:
00099     if (TCON_ty(STC_val(st)) == MTYPE_STR)
00100         return Targ_String_Length (STC_val(st))
00101                 + (TCON_add_null(STC_val(st)) ? 1 : 0);
00102     else
00103         return TY_size(ST_type(st));
00104   case CLASS_FUNC:
00105     return 0;
00106   }
00107   FmtAssert(FALSE, ("ST_size: unexpected CLASS"));
00108   /* NOTREACHED */
00109   return 0;
00110 }
00111 
00112 // make a copy of a ST in the SAME ST table
00113 ST *
00114 Copy_ST (ST *st)
00115 {
00116     if (ST_sym_class (st) == CLASS_PREG)
00117         return st;
00118 
00119     SYMTAB_IDX level = ST_IDX_level (ST_st_idx (st));
00120 
00121     ST_TAB *st_tab = Scope_tab[level].st_tab;
00122     ST_IDX st_idx = make_ST_IDX (st_tab->Insert (*st), level);
00123     ST& copy = St_Table[st_idx];
00124     Set_ST_st_idx (copy, st_idx);
00125     if (ST_base_idx (st) == ST_st_idx (st))
00126         Set_ST_base_idx (copy, st_idx);
00127     return &copy;
00128 } // Copy_ST
00129 
00130 
00131 ST *
00132 Copy_ST (ST *st, SYMTAB_IDX scope)
00133 {
00134     if (scope == ST_level (st))
00135         return Copy_ST (st);
00136 
00137     ST_TAB *st_tab = Scope_tab[scope].st_tab;
00138     ST_IDX st_idx = make_ST_IDX (st_tab->Insert (*st), scope);
00139     ST& copy = St_Table[st_idx];
00140     Set_ST_st_idx (copy, st_idx);
00141     if (ST_base_idx (st) == ST_st_idx (st))
00142         Set_ST_base_idx (copy, st_idx);
00143     else if (scope != ST_IDX_level (ST_base_idx (st))) {
00144         ST *base_st = Copy_ST (&St_Table[ST_base_idx (st)], scope);
00145         Set_ST_base_idx (copy, ST_st_idx (base_st));
00146     }
00147     return &copy;
00148 } // Copy_ST
00149 
00150 ST *
00151 Copy_ST_No_Base (ST *st, SYMTAB_IDX scope)
00152 {
00153     static INT Temp_Index = 0;
00154     STR_IDX new_name;
00155     if (scope == GLOBAL_SYMTAB) 
00156         new_name = Save_Str2i(ST_name(st),"..", Temp_Index++);
00157     else
00158         new_name = ST_name_idx(st);
00159 
00160     if (scope == ST_level (st)) {
00161         ST* new_st = Copy_ST (st);
00162         Set_ST_name_idx (*new_st, new_name);
00163         return new_st;
00164     }
00165 
00166     ST_TAB *st_tab = Scope_tab[scope].st_tab;
00167     ST_IDX st_idx = make_ST_IDX (st_tab->Insert (*st), scope);
00168     ST& copy = St_Table[st_idx];
00169     Set_ST_st_idx (copy, st_idx);
00170     Set_ST_name_idx (copy, new_name);
00171     if (ST_base_idx (st) == ST_st_idx (st)) {
00172         Set_ST_base_idx (copy, st_idx);
00173     }
00174     return &copy;
00175 } // Copy_ST
00176 
00177 
00178 // Return TRUE if the ST is a constant literal or a const variable.
00179 BOOL
00180 ST_is_constant (const ST *st)
00181 {
00182     switch (ST_sym_class(st)) {
00183     case CLASS_CONST:
00184         return TRUE;
00185     case CLASS_VAR:
00186         return ST_is_const_var(st);
00187     default:
00188         return FALSE;
00189     }
00190 }
00191 
00192 // ====================================================================
00193 // Returns FALSE if the current PU is recursive or the ST is not in
00194 // the local symtab. May return TRUE otherwise; the more we return
00195 // TRUE, the better we optimize.
00196 // ====================================================================
00197 
00198 extern BOOL
00199 ST_is_private_local(const ST *st)
00200 {
00201   Is_True((PU_src_lang(Get_Current_PU()) &
00202            (PU_src_lang(Get_Current_PU()) - 1)) == 0,
00203           ("ST_is_private_local: Mixed-language inlining not "
00204            "allowed; need to know original PU language"));
00205  
00206   if (ST_IDX_level(ST_st_idx(st)) != CURRENT_SYMTAB)
00207     return FALSE;
00208 
00209   // Fix 643997:  for F90, -LANG:recursive=on force the compiler
00210   // to assume every procedure is recursive.
00211   //
00212   // If -LANG:recursive=[on|off] is set by user
00213   // it overrides the language default.
00214   if (LANG_Recursive_Set)
00215     return !LANG_Recursive;
00216   
00217   // TODO:  should examine PU_recursive flag for all languages.
00218   //
00219   switch (PU_src_lang(Get_Current_PU())) {
00220   case PU_F77_LANG:
00221     // F77 default is to assume procedure are not recursive.
00222     return TRUE;
00223 
00224   case PU_F90_LANG:
00225     // The default is to rely on the PU_recursive flag set by frontend.
00226     return (!PU_recursive(Get_Current_PU()));
00227   }
00228   return FALSE;
00229 }
00230 
00231 //----------------------------------------------------------------------
00232 // TY-related utilities
00233 //----------------------------------------------------------------------
00234 
00235 
00236 TY_IDX
00237 Copy_TY (TY_IDX ty)
00238 {
00239 
00240     TY_IDX copy = ty;
00241     Set_TY_IDX_index (copy, Ty_tab.Insert (Ty_Table[ty]));
00242     return copy;
00243 }
00244 
00245 
00246 // assume align is a power of 2.
00247 UINT
00248 TY_log_base2 (UINT align)
00249 {
00250     UINT result = 0;
00251 
00252     Is_True (align, ("Invalid alignment for TY"));
00253 
00254     while ((align & 0x7) == 0 && align!=0) {//fzhao May
00255         result += 3;
00256         align >>= 3;
00257     }
00258 
00259     return result + (align >> 1);
00260 } // TY_log_base2
00261 
00262 
00263 /* ====================================================================
00264  *
00265  * FLD_get_to_field
00266  *
00267  * Given the TY of a struct, get to the field corresponding to field_id.
00268  * cur_field_id gives the field_id of the struct itself.  If the field is
00269  * found, cur_field_id is set equal to field_id.  Otherwise, Is_Null() is
00270  * true for the field handle returned, and cur_field_id is set to 
00271  * correspond to the last field of this struct.
00272  *
00273  * ==================================================================== */
00274 FLD_HANDLE 
00275 FLD_get_to_field (TY_IDX struct_ty_idx, UINT field_id, UINT &cur_field_id)
00276 {
00277     FLD_ITER fld_iter = Make_fld_iter(TY_fld(struct_ty_idx));
00278     do {
00279         FLD_HANDLE fld(fld_iter);
00280         cur_field_id++;
00281         if (cur_field_id == field_id)
00282             return fld;
00283         //WEI: if the field is a {p}shared_ptr_t, make sure we don't try to traverse its fields
00284         if (TY_kind(FLD_type(fld)) == KIND_STRUCT && !is_upcr_ptr(FLD_type(fld)) &&
00285             TY_fld(FLD_type(fld)) != FLD_HANDLE()) {
00286             fld = FLD_get_to_field(FLD_type(fld), field_id, cur_field_id);
00287             if (cur_field_id == field_id)
00288                 return fld;
00289         } 
00290     } while (!FLD_last_field(fld_iter++));
00291     return FLD_HANDLE();
00292 } // FLD_get_to_field
00293 
00294 
00295 // reverse map for getting the pointer TY given the pointee
00296 
00297 
00298 // Utility functions for mapping a TY to the one that points to it.
00299 // A hash_map is used because the number of pointer types should be small
00300 // compared to all TYs.
00301 
00302 // we uniquely identify a pointee by it's TY_IDX and the TY_flags of the
00303 // pointer 
00304 typedef std::pair<TY_IDX, UINT32> TY_POINTEE_KEY;
00305 
00306 
00307 // Solaris CC workaround
00308 // hash_pointee_key contains the hash function for hash_map, we should 
00309 // no longer use it after replacing hash_map with map
00310 //
00311 struct hash_pointee_key
00312 {
00313     UINT32 operator() (TY_POINTEE_KEY key) const {
00314         return (key.first | key.second);
00315     }
00316 };
00317 
00318 typedef HashTable<TY_POINTEE_KEY, TY_IDX, hash_pointee_key> TY_IDX_POINTER_MAP;
00319 // pointer_map maps a pointee to its corresponding pointer
00320 static TY_IDX_POINTER_MAP pointer_map;
00321 static std::pair<TY_POINTEE_KEY, TY_IDX> last_valid_map_entry;
00322 
00323 
00324 static BOOL
00325 Invalid_Pointer_Map_Entry (const TY_IDX_POINTER_MAP::value_type& entry)
00326 {
00327     TY_IDX pointer = entry.second;
00328     TY_IDX pointee = entry.first.first;
00329 
00330     if (TY_IDX_index (pointer) >= TY_Table_Size () ||
00331         TY_IDX_index (pointee) >= TY_Table_Size ())
00332         return TRUE;
00333 
00334     const TY& ty = Ty_Table[pointer];
00335 
00336     if (TY_kind (ty) != KIND_POINTER ||
00337         TY_pointed (ty) != pointee ||
00338         TY_flags (ty) != entry.first.second)
00339         return TRUE;
00340 
00341     return FALSE;
00342 } // Invalid_Pointer_Map_Entry
00343 
00344 
00345 // in case the pointer_map is corrupted, we need to delete all invalid
00346 // entries.  This should rarely happen, but still possible if some pointer
00347 // types which have been inserted into the pointer_map are deleted.
00348 static void
00349 Validate_Pointer_Map ()
00350 {
00351   typedef std::vector<TY_IDX_POINTER_MAP::KeyType> InvalidEntries;
00352   class FindInvalidEntries : public TY_IDX_POINTER_MAP::ForAllAction {
00353     TY_IDX_POINTER_MAP * map;
00354     InvalidEntries invalid_entries;
00355 
00356   public:
00357     FindInvalidEntries(TY_IDX_POINTER_MAP& _map) : map(&_map) {}
00358     
00359     void handle(const TY_IDX_POINTER_MAP::KeyType k, 
00360                 TY_IDX_POINTER_MAP::ValueType &v) {
00361       UINT last_valid = 0;
00362       TY_IDX_POINTER_MAP::value_type kv(k, v);
00363       if (Invalid_Pointer_Map_Entry (kv))
00364         invalid_entries.push_back(k);
00365       else {
00366         if (last_valid < TY_IDX_index (v)) {
00367           last_valid = TY_IDX_index (v);
00368           last_valid_map_entry.first  =  k;
00369           last_valid_map_entry.second =  v;
00370         }
00371       }
00372     }
00373 
00374     void eraseInvalidEntries() {
00375       InvalidEntries::const_iterator ieIterator;
00376       for ( ieIterator = invalid_entries.begin();
00377             ieIterator != invalid_entries.end(); 
00378             ++ieIterator )
00379         map->erase(*ieIterator);
00380     }
00381   }; // class FindInvalidEntries
00382 
00383   FindInvalidEntries fie(pointer_map);
00384   pointer_map.forAll(fie);
00385   fie.eraseInvalidEntries();
00386 }
00387 
00388 struct update_pointer_map
00389 {
00390     void operator() (UINT32 idx, const TY* ty) const {
00391         if (TY_kind (*ty) != KIND_POINTER || TY_mtype (*ty) != Pointer_Mtype)
00392             return;
00393         TY_POINTEE_KEY key (TY_pointed (*ty), TY_flags (*ty));
00394         last_valid_map_entry = std::make_pair (key, make_TY_IDX (idx));
00395         pointer_map.insert (last_valid_map_entry);
00396     }
00397 };
00398 
00399 static void
00400 Update_Pointer_Map ()
00401 {
00402   const TY_IDX_POINTER_MAP::value_type ss_entry( last_valid_map_entry.first,
00403                                                  last_valid_map_entry.second);
00404   
00405   if ( TY_IDX_index (last_valid_map_entry.second) != 0 &&
00406        Invalid_Pointer_Map_Entry (ss_entry)) {
00407 
00408     DevWarn ("Rehashing TY pointer map -- this should NOT happen often");
00409     Validate_Pointer_Map ();
00410   }
00411   For_all_entries (Ty_tab, update_pointer_map (),
00412                    TY_IDX_index (last_valid_map_entry.second) + 1);
00413 }
00414 
00415 
00416 static inline TY_IDX
00417 Find_Ty_Pointer (TY_POINTEE_KEY key)
00418 {
00419   TY_IDX_POINTER_MAP::ValueBoolPair result = pointer_map.find(key);
00420 
00421   if (result.second == false) return 0;
00422 
00423   TY_IDX_POINTER_MAP::value_type vt(key, result.first);
00424   if (Invalid_Pointer_Map_Entry (vt)) {
00425     DevWarn ("Rehashing TY pointer map -- this should NOT happen often");
00426     Validate_Pointer_Map ();
00427     return 0;
00428   }
00429   
00430   TY_IDX pointer = result.first;
00431   Set_TY_align (pointer, Pointer_Size);
00432   return pointer;
00433 } // Find_Ty_Pointer    
00434 
00435 
00436 TY_IDX
00437 TY_pointer (TY_IDX pointee, BOOL f90_pointer)
00438 {
00439     TY_POINTEE_KEY key (pointee, f90_pointer ? TY_IS_F90_POINTER : 0);
00440 
00441     TY_IDX result = Find_Ty_Pointer (key);
00442 
00443     if (result == 0) {
00444         Update_Pointer_Map ();
00445         return Find_Ty_Pointer (key);
00446     }
00447 
00448     return result;
00449 } // TY_pointer
00450 
00451 static string utoa(UINT64 i) {
00452   
00453   string val = "";
00454   
00455   while (i >= 10) {
00456     val = (char) ((i % 10) + '0') + val;  
00457     i = i / 10;
00458   }
00459   return ((char) (i + '0')) + val;
00460 }
00461 
00462 string get_TY_string(TY_IDX idx) {
00463 
00464   switch (TY_kind(idx)) {
00465   case KIND_SCALAR:
00466     return utoa(TY_mtype(idx));
00467   case KIND_POINTER:
00468     return "*" + utoa(TY_pointed(idx));
00469   case KIND_ARRAY: {
00470     TY_IDX base;
00471     int dim;
00472     for (base = TY_etype(idx), dim = 1; TY_kind(base) == KIND_ARRAY; base = TY_etype(base), dim++);
00473     string res = utoa(base);
00474     for (int i = 0; i < dim; i++, res += "[]");
00475     res += utoa(TY_size(idx));
00476     return res;
00477   }
00478   case KIND_STRUCT: 
00479     return utoa(TY_name_idx(idx));
00480   case KIND_VOID:
00481     return "void";
00482   }
00483   
00484   FmtAssert(FALSE, ("TY_kind: unexpected KIND"));
00485   /* NOTREACHED */
00486   return "";
00487 }
00488 
00489 class Idx_Pair {
00490 public:
00491   TY_IDX idx;
00492   int bsize;
00493   Idx_Pair(TY_IDX i, int b) {idx = i; bsize = b;}
00494 }; 
00495 
00496 struct Pair_Cmp {
00497   bool operator() (const Idx_Pair* t1, const Idx_Pair* t2) const {
00498     return t1->idx < t2->idx || (t1->idx == t2->idx && t1->bsize < t2->bsize);
00499   }
00500 };
00501 
00502 //map<Idx_Pair*, TY_IDX, Pair_Cmp> ty_map;
00503 map<string, TY_IDX> ty_map;
00504 
00505 
00510 TY_IDX Make_Shared_Type (TY_IDX ty_idx, int bsize, CONSISTENCY_class consistency) {
00511 
00512   string key = get_TY_string(ty_idx) + "_" + utoa(bsize) + (consistency == STRICT_CONSISTENCY ? "s" : "");
00513   
00514   if (TY_is_shared(ty_idx)) {
00515     //if the type passed in is already shared, check if it has the same block size as the one given
00516     //if yes, we can safely use the same TY entry
00517     int ty_bsize;
00518     switch (TY_kind(ty_idx)) {
00519     case KIND_SCALAR:
00520     case KIND_POINTER:
00521     case KIND_STRUCT:
00522       ty_bsize = TY_block_size(ty_idx);
00523       break;
00524     case KIND_ARRAY: {
00525       TY_IDX base;
00526       for (base = TY_etype(ty_idx); TY_kind(base) == KIND_ARRAY; base = TY_etype(base));
00527       ty_bsize = TY_block_size(base);
00528       break;
00529     }
00530     }
00531     if (ty_bsize == bsize && TY_is_strict(ty_idx) &&  consistency == STRICT_CONSISTENCY) {
00532       ty_map[key] = ty_idx;
00533       return ty_idx;
00534     }
00535   }
00536 
00537   //create a new shared type
00538   TY_IDX res = ty_map[key];  
00539   if (res == 0) {
00540     TY& ty = New_TY(res);
00541     TY_Init (ty, TY_size(ty_idx), TY_kind(ty_idx), TY_mtype(ty_idx),
00542              Save_Str (TY_name(ty_idx)));
00543     Set_TY_flags(res, TY_flags(ty_idx));
00544     Set_TY_align(res, TY_align(ty_idx));
00545    
00546     if(consistency == STRICT_CONSISTENCY)
00547       Set_TY_is_strict(ty_idx);
00548     
00549     switch (TY_kind(ty_idx)) {
00550     case KIND_SCALAR:
00551       Set_TY_block_size(res, bsize);
00552       Set_TY_is_shared(res);
00553       break;
00554     case KIND_POINTER:
00555       Set_TY_block_size(res, bsize);
00556       Set_TY_is_shared(res);
00557       Set_TY_pointed(res, TY_pointed(ty_idx));      
00558       break;
00559     case KIND_STRUCT:
00560       Set_TY_block_size(res, bsize);
00561       Set_TY_is_shared(res);
00562       Set_TY_fld(res, TY_fld(ty_idx));
00563       break;
00564     case KIND_ARRAY:
00565       Set_TY_arb(res, TY_arb(ty_idx));
00566       Set_TY_etype(res, Make_Shared_Type(TY_etype(ty_idx), bsize, consistency));
00567       break;
00568     }
00569     ty_map[key] = res;
00570   }
00571   //cout << "MAKING SHARED: " << TY_name(res) << " " << key << " bsize: " << bsize << endl;
00572   return res;
00573 }
00574 
00575 TY_IDX
00576 make_ptr_type (TY_IDX ty_idx, BOOL f90_pointer)
00577 {
00578     TY_IDX ty_ptr = TY_pointer (ty_idx, f90_pointer);
00579 
00580     if (ty_ptr != 0)
00581         return ty_ptr;
00582    
00583     TY &ty = New_TY (ty_ptr);
00584     TY_Init (ty, Pointer_Size, KIND_POINTER, Pointer_Mtype,
00585              Save_Str ("anon_ptr."));
00586     Set_TY_pointed (ty, ty_idx);
00587     if (f90_pointer)
00588         Set_TY_is_f90_pointer (ty);
00589     Set_TY_align (ty_ptr, Pointer_Size);
00590     
00591     return ty_ptr;
00592 }
00593 
00594 TY_IDX
00595 Make_Pointer_Type (TY_IDX ty_idx, BOOL)
00596 {
00597   // This now only returns non-f90 pointers. It ignores the second argument
00598   return make_ptr_type (ty_idx, FALSE);
00599 } // Make_Pointer_Type
00600 
00601 TY_IDX
00602 Make_F90_Pointer_Type (TY_IDX ty_idx)
00603 {
00604   // This now only returns f90 pointers
00605   return make_ptr_type (ty_idx, TRUE);
00606 } // Make_F90_Pointer_Type
00607 
00608 
00609 TY_IDX
00610 Make_Function_Type(TY_IDX return_ty_idx)
00611 {
00612   // Return the type of a function with unspecified parameters and the
00613   // specified return type. First, iterate through the known types and
00614   // see if we can return an existing type. Then as a last resort,
00615   // create the new type if we didn't find it.
00616 #ifdef ROBERT
00617   //
00618   // Note: Check for duplicates only against functions of no
00619   // parameters. I believe functions that return values through their
00620   // first parameter have TY_arg_area_size != 0, and so are excluded
00621   // from being seen as duplicates. Wilson says we currently call
00622   // Make_Function_Type only for functions of no parameters.
00623   //      -- RK 971013
00624   TY_ITER ty;
00625   // TODO: There should be some way to get at Ty_tab.begin() and
00626   // Ty_tab.end() through Ty_Table. In other words, Ty_Table should be
00627   // the only visible way of getting at the table of types. Having two
00628   // names for the same thing is nasty. -- RK
00629   ty = Ty_tab.begin();
00630   for (++ty;
00631        ty != Ty_tab.end();
00632        ty++) {
00633     TYLIST_IDX known_return_tylist;
00634     if (TY_kind(*ty) == KIND_FUNCTION &&
00635         (known_return_tylist = TY_tylist(*ty)) != (TYLIST_IDX) 0 &&
00636         TYLIST_type(known_return_tylist) == return_ty_idx &&
00637         (return_ty_idx == 0 ||
00638          TYLIST_type(known_return_tylist + 1) == (TY_IDX) 0)) {
00639       return ty.Index();
00640     }
00641   }
00642   TYLIST_IDX  new_return_tylist_idx;
00643   TYLIST     &new_return_tylist = New_TYLIST(new_return_tylist_idx);
00644   Set_TYLIST_type(new_return_tylist, return_ty_idx);
00645 
00646   if (return_ty_idx != (TY_IDX) 0) {
00647     TYLIST_IDX tail_return_tylist_idx;
00648     new_return_tylist = New_TYLIST(tail_return_tylist_idx);
00649     Is_True(tail_return_tylist_idx == new_return_tylist_idx + 1,
00650             ("Make_Function_Type: TYLIST allocation messed up"));
00651     Set_TYLIST_type(new_return_tylist, (TY_IDX) 0);
00652   }
00653 
00654   TY_IDX  function_ty_idx;
00655   TY     &function_ty = New_TY(function_ty_idx);
00656   static char  buf[32];
00657   static INT32 tcount = 0;
00658 
00659   ++tcount;
00660   sprintf(buf, ".anon_functype.%d", tcount);
00661   TY_Init(function_ty, (UINT64) 0, KIND_FUNCTION, MTYPE_UNKNOWN,
00662           Save_Str(buf));
00663   return function_ty_idx;
00664 #else
00665   TY_IDX ty_idx;
00666   TY&    ty = New_TY (ty_idx);
00667 
00668   TY_Init (ty, 0, KIND_FUNCTION, MTYPE_UNKNOWN, 0);
00669   Set_TY_align (ty_idx, 1);
00670 
00671   TYLIST_IDX tylist_idx;
00672 
00673   (void) New_TYLIST (tylist_idx);
00674   Tylist_Table [tylist_idx] = return_ty_idx;
00675   Set_TY_tylist (ty, tylist_idx);
00676 
00677   (void) New_TYLIST (tylist_idx);
00678   Tylist_Table [tylist_idx] = 0;
00679 
00680   // check that TY is unique
00681   TY_IDX new_ty_idx = TY_is_unique (ty_idx);
00682   if (new_ty_idx != ty_idx && TY_IDX_index (ty_idx) == Ty_tab.Size () - 1) {
00683         // found duplicate
00684         // delete last two tylist entries
00685         Tylist_Table.Delete_last (2);
00686         Ty_tab.Delete_last ();
00687         ty_idx = new_ty_idx;
00688   }
00689   return ty_idx;
00690 #endif
00691 }
00692 
00693 static std::vector<ST *> intrinsic_list;
00694 
00695 struct matches_pu_ty_and_name {
00696   const TY_IDX        ty;
00697   const char   *const name;
00698 
00699   matches_pu_ty_and_name(const TY_IDX type, const char *const func_name) :
00700     ty(type), name(func_name)
00701       { }
00702 
00703   BOOL operator()(const ST *const st) {
00704     return (ST_pu_type(st) == ty &&
00705             strcmp(ST_name(st), name) == 0);
00706   }
00707 };
00708 
00709 static void INTRINSIC_LIST_add(ST *st)
00710 {
00711         intrinsic_list.push_back(st);
00712 }
00713 
00714 static ST *
00715 INTRINSIC_LIST_lookup(TY_IDX  ty,
00716                       const char *function_name)
00717 {
00718   /*
00719    * GNU g++-3.0 STL workaround
00720    * g++-3.0 has a new implementation of STL - a container's 
00721    * iterator is no longer a simple pointer, but a smart pointer
00722    * defined as __normal_iterator<Pointer, Container> in stl_algo.h.
00723    * And begin() end() return the smart pointers. To ensure 
00724    * compatibility, we use type "iterator" instead of an explicit
00725    * pointer.
00726    */
00727   
00728   std::vector<ST *>::iterator result =
00729     std::find_if(intrinsic_list.begin(),
00730                  intrinsic_list.end(),
00731                  matches_pu_ty_and_name(ty, function_name));
00732   
00733   if (result == intrinsic_list.end()) {
00734     return NULL;
00735   }
00736   else {
00737     return *result;  // okay because stl_algo.h defined operator* 
00738   }
00739 }
00740 
00741 ST *
00742 Gen_Intrinsic_Function(TY_IDX  ty,
00743                        const char *function_name)
00744 {
00745   ST *st = INTRINSIC_LIST_lookup(ty, function_name);
00746 
00747   if (st == NULL) {
00748     st = New_ST(GLOBAL_SYMTAB);
00749 
00750     PU_IDX pu_idx;
00751     PU&    pu = New_PU (pu_idx);
00752 
00753     PU_Init (pu, ty, CURRENT_SYMTAB);
00754 
00755     ST_Init (st, Save_Str(function_name), CLASS_FUNC, SCLASS_EXTERN,
00756              EXPORT_PREEMPTIBLE, (TY_IDX) pu_idx);
00757 
00758     INTRINSIC_LIST_add(st);
00759   }
00760   return st;
00761 }
00762 
00763 
00764 // Make an array type of equal len in each dimension
00765 TY_IDX
00766 Make_Array_Type (TYPE_ID element, INT32 ndim, INT64 len)
00767 {
00768     FmtAssert(MTYPE_RegisterSize(element) > 0 && MTYPE_align_best(element) > 0,
00769               ("Cannot make an array of %s", MTYPE_name(element))); 
00770     ARB_HANDLE arb,arb_first;
00771     for (UINT i = 0; i < ndim; ++i) {
00772        arb = New_ARB ();
00773        if (i==0) {
00774          arb_first = arb;
00775        }
00776        ARB_Init (arb, 0, len - 1, MTYPE_RegisterSize (element));
00777        Set_ARB_dimension (arb, ndim-i);
00778     }
00779     
00780     Set_ARB_last_dimen (arb);
00781     Set_ARB_first_dimen (arb_first);
00782 
00783     TY_IDX ty_idx;
00784     TY& ty = New_TY (ty_idx);
00785     TY_Init (ty, MTYPE_RegisterSize(element) * ndim * len, KIND_ARRAY,
00786              MTYPE_UNKNOWN, 0);
00787     Set_TY_align (ty_idx, MTYPE_align_best(element));
00788     Set_TY_etype (ty, MTYPE_To_TY (element));
00789     Set_TY_arb (ty, arb_first);
00790 
00791     return ty_idx;
00792 
00793 } // Make_Array_Type
00794 
00795 //-------------------------------------------------------------------------
00796 // The next few TY related functions allow us to check for TYPE_EQUIVALENCE
00797 //-------------------------------------------------------------------------
00798 
00799 // Hash Map
00800 // -------------
00801 // We keep a STL hash_map (see below) on the side to narrow down our search
00802 // for duplicate types.
00803 //
00804 // The hash_map maps all TY_IDXs that represent identical types, all present
00805 // in our global type tables, to ONE representative TY_IDX (first encountered).
00806 // In other words, we have a map from multiple TY_IDXs to one unique
00807 // representative.
00808 //
00809 // The hash_map stores the TY_IDX of every unique TY encountered so far.
00810 // To enter types into the hash-table, call TY_is_unique(); if an equivalent
00811 // type does not already exist the given TY_IDX will be entered into the
00812 // hash-table as a unique type; otherwise the equivalent TY_IDX is returned.
00813 // Note that both our hashing function and our "equal" function operate
00814 // on the TY, not just on the TY_IDX.
00815 
00816 // Why multiple hash_maps?
00817 // ----------------------------
00818 // Since the TY_are_equivalent function is fairly expensive we need good hash
00819 // functions to reduce the number of likely matches. To that end we define 
00820 // five different hash multimaps (rather than one) depending on the TY_kind; 
00821 // one map each for 
00822 // (a) scalars (and void), (b) pointers, (c) functions, (d) arrays, (e) structs
00823 
00824 // the type of the hash table key (i.e., what the hash function takes as input)
00825 typedef TY_IDX HashKeyType;
00826 
00827 // Hash functions based on TY_Kind
00828 // -------------------------------
00829 // We use TY_kind to determine an appropriate hash-function:
00830 // a For scalars (and void) we just use the "mtype", 
00831 // b For pointers we use the mtype of what the pointer points to
00832 // c For functions we use a hash based on the function signature (TY_fun_hash)
00833 // d For arrays we use a hash function based on dim/base/bound (TY_array_hash)
00834 // e For structs we use a hash function based on the struct name/size
00835 // These hash functions are now defined
00836 
00837 //----------------------------------------------------------------------
00838 // TY_fun_hash   : maps a function prototype into a size_t value
00839 // If the function has a signature: t1 * .. * tn -> t
00840 // then it is represented in the TYLIST_TABLE as <t,t1,...,tn>
00841 // We hash it in base MTYPE_LAST as the number <t_m,t1_m,...,tn_m>
00842 // We create an MTYPE_LAST-ary number by extracting the mtypes of 
00843 // each ti denoted by ti_m i.e., (let ML denote MTYPE_LAST)
00844 //  (((t_m *ML) + t1_m) * ML) + ... + tn_m
00845 //----------------------------------------------------------------------
00846 size_t 
00847 TY_fun_hash (const TY& ty) {
00848   size_t value = 0;
00849 
00850   TYLIST_ITER fn_iter = Make_tylist_iter(TY_tylist(ty));
00851 
00852   while (*fn_iter) {
00853     value = MTYPE_LAST * value + TY_mtype(Ty_Table[*fn_iter++]);
00854   }
00855 
00856   return value;
00857 } // TY_fun_hash
00858 
00859 //----------------------------------------------------------------------
00860 // TY_array_hash : hashes an array into a size_t value determined by
00861 //  upper_bound_value (for first dim) + (#dimensions * mtype(array_elmt))
00862 //  if two arrays have the same base type, the same number of dimensions
00863 //  and the same value for the upper bound of the first dimension then
00864 //  they are likely the same and are hashed to the same bucket
00865 //  eg int a[10][2]   and int a[10][3] would be hashed to the same bucket
00866 //  whereas  int a[10] and double b[10] would be hashed to diff buckets 
00867 //  likewise int a[10] and int b[11] would be hashed to different buckets
00868 //  just as  int a[10] and int a[10][2] would be hashed to different buckets
00869 //----------------------------------------------------------------------
00870 size_t 
00871 TY_array_hash (const TY& ty) {
00872   return ARB_ubnd_val(TY_arb(ty)) + 
00873     ARB_dimension(TY_arb(ty))  * TY_mtype(Ty_Table[TY_etype(ty)]) ;
00874 
00875 } // TY_array_hash
00876 
00877 //----------------------------------------------------------------------
00878 // TY_struct_hash: maps a struct into a size_t value
00879 // Return the name_idx (if set) or the size
00880 // If the struct has a name use the unique Str_Table index as a hash
00881 // If the struct is anonymous, use its size as a distinguishing feature
00882 //----------------------------------------------------------------------
00883 inline size_t 
00884 TY_struct_hash (const TY& ty) {
00885   return TY_name_idx(ty) ? TY_name_idx(ty) : TY_size(ty);
00886 } // TY_struct_hash
00887  
00888 
00889 size_t TY_hash_func(const TY_IDX ty_id) {
00890   TY &ty = Ty_Table[ty_id];
00891   switch (TY_kind(ty)) {
00892   case KIND_SCALAR:
00893   case KIND_VOID:
00894     return TY_mtype(ty);
00895   case KIND_ARRAY:
00896     return TY_array_hash(ty);
00897   case KIND_POINTER:
00898     return TY_mtype(Ty_Table [TY_pointed(ty)]);
00899   case KIND_FUNCTION:
00900     return TY_fun_hash(ty);
00901   case KIND_STRUCT:
00902     return TY_struct_hash(ty);
00903   case KIND_INVALID:
00904   default:
00905   case KIND_LAST:     
00906     Fail_FmtAssertion ("invalid TY_KIND in hash fn");
00907     return 0;
00908   } // switch
00909 } // TY_hash_func
00910 
00911 struct TY_hash {
00912   size_t operator()(const TY_IDX ty_id) const { 
00913     return TY_hash_func(ty_id);
00914   } // operator()
00915 }; // struct TY_hash
00916 
00917 
00918 struct TY_EQUIV
00919 {
00920   bool operator () ( const TY_IDX k1, const TY_IDX k2) const 
00921     {
00922       return TY_are_equivalent(k1, k2);
00923     }
00924 };
00925 
00926 typedef HashTable<TY_IDX, TY_IDX, TY_hash, TY_EQUIV> HASH_TY_TABLE;
00927 
00928 // The global Hash Table data structures
00929 // Depending on the TY_KIND we pick one of the five tables below.
00930 
00931 HASH_TY_TABLE Hash_ty_scalar_table; 
00932 HASH_TY_TABLE Hash_ty_array_table; 
00933 HASH_TY_TABLE Hash_ty_struct_table; 
00934 HASH_TY_TABLE Hash_ty_pointer_table; 
00935 HASH_TY_TABLE Hash_ty_function_table; 
00936 
00937 // The following is necessary to handle recursively defined types,
00938 // such as struct with a pointer to itself as a member field.
00939 // We maintain a record of the order in which types are visited
00940 // in the global type table for each of the two types being compared.
00941 // The following datastructure should be initialized to zero between
00942 // top-level calls to TY_are_equivalent(), and Ty_Equiv_Visit_Number
00943 // should also be zero between such top-level calls.
00944 //
00945 typedef SEGMENTED_ARRAY<UINT32> TY_EQUIV_VISIT_ORDER;
00946 static TY_EQUIV_VISIT_ORDER Ty_Equiv_Visit1;
00947 static TY_EQUIV_VISIT_ORDER Ty_Equiv_Visit2;
00948 static UINT32               Ty_Equiv_Visit_Number = 0;
00949 
00950 static BOOL
00951 Push_Equiv_Visit_Order(UINT32 ty_index1, UINT32 ty_index2, BOOL &are_equiv)
00952 {
00953   const UINT32 ty_tbl_size = TY_Table_Size();
00954   BOOL         pushed = FALSE;
00955 
00956   // Make sure the number of entries match the number of types,
00957   // and that entries are initialized to zero.
00958   //
00959   for (UINT32 i = Ty_Equiv_Visit1.Size(); i < ty_tbl_size; i++)
00960   {
00961      UINT dummy;
00962      Ty_Equiv_Visit1.New_entry(dummy) = 0;
00963      Ty_Equiv_Visit2.New_entry(dummy) = 0;
00964   }
00965   
00966   if (Ty_Equiv_Visit1[ty_index1] != Ty_Equiv_Visit2[ty_index2])
00967      are_equiv = FALSE;
00968   else if (Ty_Equiv_Visit1[ty_index1] > 0)
00969      are_equiv = TRUE;
00970   else
00971   {
00972      Ty_Equiv_Visit_Number++;
00973      Ty_Equiv_Visit1[ty_index1] = Ty_Equiv_Visit_Number;
00974      Ty_Equiv_Visit2[ty_index2] = Ty_Equiv_Visit_Number;
00975      are_equiv = FALSE;
00976      pushed = TRUE;
00977   }
00978   return pushed;
00979 } // Push_Equiv_Visit_Order
00980 
00981 static void
00982 Pop_Equiv_Visit_Order(UINT32 ty_index1, UINT32 ty_index2)
00983 {
00984   Ty_Equiv_Visit_Number--;
00985   Ty_Equiv_Visit1[ty_index1] = 0;
00986   Ty_Equiv_Visit2[ty_index2] = 0;
00987 } // Push_Equiv_Visit_Order
00988 
00989 
00990 // ARB_are_equivalent determines when two array types are equivalent?
00991 // ARB_are_equivalent is presumably  called with indices for which
00992 // first_dim is set.
00993 // For each entry in the Arb_Table  in the range
00994 // arb_id1 .. arb_id1'(for which last_dim is set)
00995 // ensure that Arb_Table[arb_id1++] == Arb_Table[arb_id2++]
00996 
00997 BOOL
00998 ARB_are_equivalent(ARB_HANDLE arb_id1, ARB_HANDLE arb_id2, UINT32 flags) 
00999 {
01000   if (arb_id1 == arb_id2)
01001     return TRUE;
01002 
01003   ARB_HANDLE arb1=arb_id1;
01004   ARB_HANDLE arb2=arb_id2;
01005   BOOL keep_going;
01006 
01007   do {
01008      
01009     keep_going = ! ARB_last_dimen(arb1) && ! ARB_last_dimen(arb2);
01010      
01011     if (ARB_dimension(arb1) != ARB_dimension(arb2))
01012       return FALSE;
01013 
01014     if (ARB_co_dimension(arb1) != ARB_co_dimension(arb2))
01015       return FALSE;
01016 
01017     if (ARB_flags(arb1) != ARB_flags( arb2))
01018       return FALSE;
01019 
01020     if (ARB_const_lbnd(arb1)) {
01021       if (ARB_lbnd_val( arb1) != ARB_lbnd_val( arb2))
01022         return FALSE;
01023     } else {
01024       if (ARB_lbnd_var( arb1) != ARB_lbnd_var( arb2))
01025         return FALSE;
01026     }
01027 
01028     if (ARB_const_ubnd(arb1)) {
01029       if (ARB_ubnd_val( arb1) != ARB_ubnd_val( arb2))
01030         return FALSE;
01031     } else {
01032       if (ARB_ubnd_var( arb1) != ARB_ubnd_var( arb2))
01033         return FALSE;
01034     }
01035 
01036     if (ARB_const_stride(arb1)) {
01037       if (ARB_stride_val( arb1) != ARB_stride_val( arb2))
01038         return FALSE;
01039     } else {
01040       if (ARB_stride_var(arb1) != ARB_stride_var( arb2))
01041         return FALSE;
01042     }
01043       
01044     // All tests pass; continue until you reach "last Dimension"
01045     if (keep_going) {
01046        arb1 = arb1[1];
01047        arb2 = arb2[1];
01048     }
01049     
01050   } while (keep_going);
01051   
01052   if ( ARB_last_dimen(arb2) && ARB_last_dimen(arb1))
01053      return TRUE;
01054   else
01055      return FALSE;
01056            
01057 } // ARB_are_equivalent 
01058 
01059 // ARB_swap swaps the positions of two ARB's in the table
01060 void
01061 ARB_swap(ARB_HANDLE arb1, ARB_HANDLE arb2)
01062 {
01063    ARB temp;
01064    temp = *(arb1.Entry());
01065    *(arb1.Entry()) = *(arb2.Entry());
01066    *(arb2.Entry()) = temp;
01067 }
01068    
01069 
01070 
01071 // FLD_are_equivalent determines when two struct fields are type equivalent
01072 // T1 fld_id1     ==   T2 fld_id2 (where fld_idi are struct fields) iff
01073 //    a. T1 == T2 AND
01074 //    b. FLD_name_idx  for fld_id1 == FLD_name_idx  for fld_id2
01075 //    c. FLD_attribute for fld_id1 == FLD_attribute for fld_id2
01076 BOOL
01077 FLD_are_equivalent (FLD_HANDLE fld1, FLD_HANDLE fld2, UINT32 flags)
01078 {
01079     if (!(flags & TY_EQUIV_IGNORE_NAMES) &&
01080         FLD_name_idx(fld1) != FLD_name_idx(fld2))
01081         return FALSE;
01082 
01083     if (FLD_ofst(fld1) != FLD_ofst(fld2) ||
01084         FLD_bsize(fld1) != FLD_bsize(fld2) ||
01085         FLD_bofst(fld1) != FLD_bofst(fld2) ||
01086         FLD_flags(fld1) != FLD_flags(fld2) ||
01087         FLD_st(fld1) != FLD_st(fld2))
01088       return FALSE;
01089 
01090     // For recursive type definitions, the front end may not YET have
01091     // set the TY_IDX (ie set it to 0) when it tries to do TY_are_equivalent
01092     // We have to special case this case and return FALSE (ie not duplicates)
01093     // Presumably this case should NOT arise in the backend and hence
01094     // the #if defined (FRONT_END)
01095     // TODO: should we restrict to NONF77 front ends?
01096     // If  either ty_idx is 0  return FALSE
01097 
01098     TY_IDX ty_id1 = FLD_type(fld1);
01099     TY_IDX ty_id2 = FLD_type(fld2);
01100 
01101 #ifdef FRONT_END
01102     if ( (ty_id1 == 0) || (ty_id2 == 0))
01103         return FALSE;
01104 #endif //FRONT_END  
01105 
01106     // All fields except type are equivalent; now do structural recursion
01107 
01108     return TY_are_equivalent(ty_id1, ty_id2, flags);
01109 
01110 } // FLD_are_equivalent
01111 
01112 
01113 // go through all members of a struct and return true if all of them are
01114 // equivalent 
01115 static BOOL
01116 Struct_are_equivalent (FLD_HANDLE fld_id1, FLD_HANDLE fld_id2, UINT32 flags)
01117 {
01118     if (fld_id1 == fld_id2)
01119         return TRUE;
01120 
01121     FLD_ITER fld1_iter = Make_fld_iter (fld_id1);
01122     FLD_ITER fld2_iter = Make_fld_iter (fld_id2);
01123 
01124     while (!FLD_last_field (fld1_iter) && !FLD_last_field (fld2_iter)) {
01125         if (! FLD_are_equivalent (fld1_iter, fld2_iter, flags))
01126             return FALSE;
01127         ++fld1_iter;
01128         ++fld2_iter;
01129     }
01130 
01131     return FLD_are_equivalent (fld1_iter, fld2_iter, flags);
01132 } // Struct_are_equivalent
01133 
01134 
01135 // TYLIST_are_equivalent determines when two function prototypes are equivalent
01136 // does a  pointwise comparison of component TYs (including return types)
01137 
01138 BOOL
01139 TYLIST_are_equivalent (TYLIST_IDX tylist_id1, 
01140                        TYLIST_IDX tylist_id2, 
01141                        UINT32     flags)
01142 {
01143     if (tylist_id1 == tylist_id2)
01144         return TRUE;
01145   
01146     // Function prototypes are lists of tys terminated with a "0" TY_IDX entry
01147     //
01148     TY_IDX ty_id1;
01149     TY_IDX ty_id2;  
01150 
01151     while (Tylist_Table[tylist_id1] != 0) {
01152     
01153         ty_id1 = Tylist_Table[tylist_id1];
01154         ty_id2 = Tylist_Table[tylist_id2];
01155     
01156         if ( !TY_are_equivalent(ty_id1, ty_id2, flags))
01157             return FALSE;
01158     
01159         tylist_id1++;
01160         tylist_id2++;
01161     } // end while 
01162 
01163     if (Tylist_Table[tylist_id2] == 0)
01164         return TRUE;
01165     else
01166         return FALSE;
01167 } // TYLIST_are_equivalent
01168 
01169 
01170 // TY_are_equivalent
01171 // Returns TRUE iff ty1 and ty2 are structurally equivalent
01172 // also checks that names of fields are identical 
01173 // TODO: whether one  COMMON block is a complete subset of the other
01174 
01175 BOOL
01176 TY_are_equivalent (TY_IDX ty_id1, TY_IDX ty_id2, UINT32 flags)
01177 {
01178 
01179   // The two types are equivalent when they have identical TY_IDX.
01180   // They are not necessarily equivalent if their alignments or
01181   // qualifiers are different.
01182   //
01183   const UINT32 ty_index1 = TY_IDX_index(ty_id1);
01184   const UINT32 ty_index2 = TY_IDX_index(ty_id2);
01185    
01186   if (ty_id1 == ty_id2)
01187     return TRUE;
01188   else if ((flags & TY_EQUIV_ALIGN) && 
01189            TY_align_exp(ty_id1) != TY_align_exp(ty_id2))
01190     return FALSE;
01191   else if ((flags & TY_EQUIV_QUALIFIER) &&
01192            (TY_is_const(ty_id1) != TY_is_const(ty_id2)       ||
01193             TY_is_volatile(ty_id1) != TY_is_volatile(ty_id2) ||
01194             TY_is_restrict(ty_id1) != TY_is_restrict(ty_id2)))
01195     return FALSE;
01196   else if (ty_index1 == ty_index2)
01197     return TRUE;
01198 
01199   // Handle nested structural equivalence.  If either of these types were
01200   // encountered before, then consider the types equivalent only if they
01201   // were encountered in the same order in recursive applications of this
01202   // subroutine.
01203   //
01204   BOOL are_equiv = FALSE;
01205 
01206   if (Push_Equiv_Visit_Order(ty_index1, ty_index2, are_equiv))
01207   {
01208     // Not visited before.
01209     //
01210     const TY &ty1 = Ty_Table[ty_id1];
01211     const TY &ty2 = Ty_Table[ty_id2];
01212   
01213     // Check attributes and names, and if they match, check for structural
01214     // equivalence.
01215     //
01216     if ( TY_size(ty1) != TY_size(ty2) ||
01217          TY_kind(ty1) != TY_kind(ty2) ||
01218          TY_mtype(ty1)!= TY_mtype(ty2)||
01219          TY_flags(ty1)!= TY_flags(ty2) )
01220     { 
01221       // TODO: do we want to refine this to allow ignoring certain flags?
01222       are_equiv = FALSE;
01223     }
01224     else if (!(flags & TY_EQUIV_IGNORE_NAMES) &&
01225              TY_name_idx (ty1) != TY_name_idx (ty2))
01226     { 
01227       are_equiv = FALSE;
01228     }
01229     else
01230     {
01231       // Set flags for recursive calls to this routine.  We always check 
01232       // that alignment and qualifiers are identical for nested type 
01233       // references.
01234       //
01235       flags |= (TY_EQUIV_ALIGN | TY_EQUIV_QUALIFIER);
01236        
01237       // At this point all the above attributes are equal, 
01238       // so we are ready to do "structural equivalence" checks
01239 
01240       switch (TY_kind (ty1)) {
01241 
01242       case KIND_SCALAR:
01243       case KIND_VOID:
01244         are_equiv = TRUE;
01245         break;
01246 
01247       case KIND_ARRAY:
01248         // array bounds check and structural recursion on base type
01249         are_equiv = (ARB_are_equivalent(TY_arb(ty1), TY_arb(ty2), flags) &&
01250                      TY_are_equivalent( TY_etype(ty1), TY_etype(ty2), flags));
01251         break;
01252           
01253       case KIND_STRUCT:
01254         // At this point both the ty have NON_ZERO FLD_IDX
01255 
01256         // FLD equivalence check 
01257         are_equiv = Struct_are_equivalent(TY_fld(ty1), TY_fld(ty2), flags);
01258         break;
01259 
01260       case KIND_POINTER:
01261         // structural recursion
01262         are_equiv = TY_are_equivalent (TY_pointed(ty1),TY_pointed(ty2), flags);
01263         break;
01264 
01265       case KIND_FUNCTION:
01266         // PU flags check and structural recursion on function prototype
01267         are_equiv = ( (ty1.Pu_flags() == ty2.Pu_flags()) &&
01268                       (TYLIST_are_equivalent (TY_tylist(ty1), 
01269                                               TY_tylist(ty2),
01270                                               flags)));
01271         break;
01272 
01273       case KIND_INVALID:
01274       default:
01275         // TODO: do we want to assert here instead of returning FALSE?
01276         are_equiv = FALSE;
01277         break;
01278       }
01279     }
01280     Pop_Equiv_Visit_Order(ty_index1, ty_index2);
01281   }
01282   return are_equiv;
01283 } // TY_are_equivalent
01284 
01285 
01286 // TY_is_unique: returns
01287 // a. the input TY_IDX if the input defines a unique ("new") TY. 
01288 // b. TY_IDX with index of an existing type if the input defines a TY that
01289 // is equivalent to the existing TY (uses TY_are_equivalent for this purpose)
01290 
01291 static inline TY_IDX
01292 TY_is_unique_op (const TY_IDX ty_idx, HASH_TY_TABLE& hash_ty_table)
01293 {
01294   TY_IDX return_idx = ty_idx;
01295 
01296   HASH_TY_TABLE::ValueBoolPair isInserted = 
01297     hash_ty_table.insert(HASH_TY_TABLE::KeyValuePair(ty_idx, return_idx));
01298 
01299   if (isInserted.second == false) {
01300     // match was found
01301     Set_TY_IDX_index(return_idx, TY_IDX_index(isInserted.first));
01302   }
01303   return return_idx;
01304 
01305 /*
01306   //  HASH_TY_TABLE::const_iterator hash_entry = hash_ty_table.find (ty_idx);
01307   HASH_TY_TABLE::const_iterator hash_entry;
01308   for ( hash_entry = hash_ty_table.begin(); 
01309         hash_entry != hash_ty_table.end();
01310         hash_entry++ ) {
01311     if (TY_are_equivalent(ty_idx, hash_entry->first)) break;
01312   }
01313 
01314   if (hash_entry != hash_ty_table.end ())
01315     // step b: If found, return the TY_IDX of the duplicate
01316      Set_TY_IDX_index(return_idx, TY_IDX_index((*hash_entry).second));
01317   else
01318     hash_ty_table.insert (HASH_TY_TABLE::value_type(ty_idx, ty_idx));
01319   return return_idx;
01320 */
01321 }
01322 
01323 
01324 extern TY_IDX
01325 TY_is_unique (const TY_IDX ty_idx) 
01326 {
01327   TY    &ty = Ty_Table[ty_idx];
01328 
01329   // search for the ty in the hash table determined by its TY_kind 
01330 
01331   // step a. Find "potential" matches (using hash tables).  Note that
01332   // the hashing and equivalence functions ignore any alignment and 
01333   // qualifiers in the ty_idx.
01334   //
01335   switch (TY_kind(ty)) {
01336     
01337   case KIND_SCALAR:
01338   case KIND_VOID:
01339     return TY_is_unique_op (ty_idx, Hash_ty_scalar_table);
01340 
01341   case KIND_ARRAY:
01342     return TY_is_unique_op (ty_idx, Hash_ty_array_table);
01343 
01344   case KIND_POINTER:
01345     return TY_is_unique_op (ty_idx, Hash_ty_pointer_table);
01346 
01347   case KIND_FUNCTION:
01348     return TY_is_unique_op (ty_idx, Hash_ty_function_table);
01349 
01350   case KIND_STRUCT:
01351     return TY_is_unique_op (ty_idx, Hash_ty_struct_table);
01352 
01353   case KIND_INVALID:
01354   default:
01355   case KIND_LAST:
01356     Fail_FmtAssertion ("invalid TY_KIND in TY_is_unique");
01357     return ty_idx;                      // should never reach this
01358   };
01359 } // TY_is_unique
01360 
01361 //----------------------------------------------------------------------
01362 // PREG-related utilities
01363 //----------------------------------------------------------------------
01364 
01365 const char *
01366 Preg_Name (PREG_NUM i)
01367 {
01368     Is_True((i > Last_Dedicated_Preg_Offset),
01369             ("Preg_Name:  not valid for dedicated preg"));
01370 
01371     const PREG& preg = Preg_Table[i - Last_Dedicated_Preg_Offset];
01372 
01373     if (PREG_name_idx (preg) == 0)
01374         return "<preg>";
01375     else
01376         return PREG_name (preg);
01377 } // Preg_Name 
01378 
01379 
01380 // PREG_IDX == PREG_NUM - Last_Dedicated_Preg_Offset
01381 
01382 PREG_NUM
01383 Create_Preg_explicit(TYPE_ID mtype, const char *name, 
01384                      SCOPE *scope_tab, SYMTAB_IDX level)
01385 {
01386         PREG_IDX preg_idx;
01387         PREG_IDX preg_idx2;
01388         PREG &p = New_PREG_explicit (scope_tab, level, preg_idx);
01389         Set_PREG_name_idx (p, Save_Str(name));
01390         // pregs of simulated types have to allocate space for
01391         // all the parts of the lowered types.
01392         switch (mtype) {
01393         case MTYPE_C4:
01394         case MTYPE_C8:
01395         case MTYPE_FQ:
01396                 // reserve space for another preg
01397                 (void) New_PREG_explicit (scope_tab, level, preg_idx2);
01398                 Set_PREG_name_idx ((*scope_tab[level].preg_tab)[preg_idx2], 0);
01399                 break;
01400         case MTYPE_CQ:
01401                 // reserve space for 3 more pregs
01402                 (void) New_PREG_explicit (scope_tab, level, preg_idx2);
01403                 Set_PREG_name_idx ((*scope_tab[level].preg_tab)[preg_idx2], 0);
01404                 (void) New_PREG_explicit (scope_tab, level, preg_idx2);
01405                 Set_PREG_name_idx ((*scope_tab[level].preg_tab)[preg_idx2], 0);
01406                 (void) New_PREG_explicit (scope_tab, level, preg_idx2);
01407                 Set_PREG_name_idx ((*scope_tab[level].preg_tab)[preg_idx2], 0);
01408                 break;
01409         case MTYPE_B:
01410                 // bool needs 2 pregs cause can have complement predicate tn
01411                 (void) New_PREG_explicit (scope_tab, level, preg_idx2);
01412                 Set_PREG_name_idx ((*scope_tab[level].preg_tab)[preg_idx2], 0);
01413                 break;
01414         }
01415         // return preg-num of first preg
01416         return (PREG_NUM) preg_idx + Last_Dedicated_Preg_Offset;
01417 }
01418 
01419 PREG_NUM
01420 Create_Preg (TYPE_ID mtype, const char *name)
01421 {
01422   return Create_Preg_explicit(mtype, name, Scope_tab, CURRENT_SYMTAB);
01423 }
01424 
01425 // uses the real preg size because simulated pregs might take more than one
01426 // preg number.
01427 INT32
01428 Preg_Increment (TYPE_ID mtype)
01429 {
01430     switch (mtype) {
01431 
01432     case MTYPE_C4:
01433     case MTYPE_C8:
01434     case MTYPE_FQ:
01435         return 2;
01436 
01437     case MTYPE_CQ:
01438         return 4;
01439 
01440     case MTYPE_I8:
01441     case MTYPE_U8:
01442         if (MTYPE_size_reg(MTYPE_I8) > MTYPE_size_reg(Spill_Int_Mtype))
01443             return 2;
01444     case MTYPE_B:
01445         // bool mtype not usually used, but if used, saves space for
01446         // complement preg.
01447         return 2;
01448     }
01449     return 1;
01450 }
01451 
01452 
01453 //----------------------------------------------------------------------
01454 // BLK utilities
01455 //----------------------------------------------------------------------
01456 
01457 BLK_IDX
01458 Copy_BLK (BLK_IDX b)
01459 {
01460     BLK_IDX copy = b;
01461     copy = Blk_Table.Insert (Blk_Table[b]);
01462     return copy;
01463 }
01464 
01465 /* ====================================================================
01466  *
01467  * Base_Symbol_And_Offset
01468  *      Input:  ST *st                   Symbol to analyze
01469  *      Result: ST **base_symbol         primary base of st
01470  *      Result: INT64 *offset_from_base  offset from primary base
01471  *
01472  *
01473  * ====================================================================
01474  */
01475 void
01476 Base_Symbol_And_Offset (ST     *st,
01477                         ST    **base_symbol,
01478                         INT64  *offset_from_base)
01479 {
01480   INT64 ofst = 0;
01481   ST *base = st;
01482 
01483   while ( ST_base(base) != base  ) {
01484       ofst += ST_ofst(base);
01485       base = ST_base(base);
01486   }
01487 
01488   *base_symbol      = base;
01489   *offset_from_base = ofst;
01490 }
01491 
01492 
01493 //----------------------------------------------------------------------
01494 // Printing routines
01495 //----------------------------------------------------------------------
01496 
01497 /* ====================================================================
01498  *
01499  * Class_Name / Sclass_Name / Export_Name / Kind_Name
01500  *   Given ST field values, convert to ASCII names.
01501  *
01502  * Name_To_Class / Name_To_Sclass / Name_To_Export / Name_To_Kind
01503  *   Given ASCII names, convert to ST field values.
01504  *
01505  * ====================================================================
01506  */
01507 
01508 // eraxxon (2005.01): Re-implement these routines to support
01509 // conversion in both directions.
01510 
01511 // The type for enumeration value -> string tables
01512 struct EnumToStr_t : public ir_a2b::enum2str_tbl_entry_t {
01513   EnumToStr_t(INT val_ = 0, const char* str_ = 0) 
01514     : val(val_), str(str_) { }
01515 
01516   virtual ~EnumToStr_t() { }
01517 
01518   virtual INT getEnumVal() const     { return val; }
01519   virtual const char* getStr() const { return str; }
01520 
01521   INT         val;
01522   const char* str;
01523 };
01524 
01525 
01526 // The data tables
01527 EnumToStr_t STClassToNameTbl[CLASS_COUNT] = {
01528   EnumToStr_t(CLASS_UNK,       "C_UNK"),
01529   EnumToStr_t(CLASS_VAR,       "C_VAR"),
01530   EnumToStr_t(CLASS_FUNC,      "C_FUNC"),
01531   EnumToStr_t(CLASS_CONST,     "C_CONST"),
01532   EnumToStr_t(CLASS_PREG,      "C_PREG"),
01533   EnumToStr_t(CLASS_BLOCK,     "C_BLOCK"),
01534   EnumToStr_t(CLASS_NAME,      "C_NAME"),
01535   EnumToStr_t(CLASS_MODULE,    "C_MODULE"),
01536   EnumToStr_t(CLASS_TYPE,      "C_TYPE"),
01537   EnumToStr_t(CLASS_PARAMETER, "C_PARAMETER")
01538 };
01539 
01540 EnumToStr_t STSclassToNameTbl[SCLASS_COUNT] = {
01541   EnumToStr_t(SCLASS_UNKNOWN,   "S_UNKNOWN"),
01542   EnumToStr_t(SCLASS_AUTO,      "S_AUTO"),
01543   EnumToStr_t(SCLASS_FORMAL,    "S_FORMAL"),
01544   EnumToStr_t(SCLASS_FORMAL_REF,"S_FORMAL_REF"),
01545   EnumToStr_t(SCLASS_PSTATIC,   "S_PSTATIC"),
01546   EnumToStr_t(SCLASS_FSTATIC,   "S_FSTATIC"),
01547   EnumToStr_t(SCLASS_COMMON,    "S_COMMON"),
01548   EnumToStr_t(SCLASS_EXTERN,    "S_EXTERN"),
01549   EnumToStr_t(SCLASS_UGLOBAL,   "S_UGLOBAL"),
01550   EnumToStr_t(SCLASS_DGLOBAL,   "S_DGLOBAL"),
01551   EnumToStr_t(SCLASS_TEXT,      "S_TEXT"),
01552   EnumToStr_t(SCLASS_REG,       "S_REG"),
01553   EnumToStr_t(SCLASS_CPLINIT,   "S_CPLINIT"),
01554   EnumToStr_t(SCLASS_EH_REGION, "S_EH_REGION"),
01555   EnumToStr_t(SCLASS_EH_REGION_SUPP, "S_EH_REGION_SUPP"),
01556   EnumToStr_t(SCLASS_DISTR_ARRAY, "S_DISTR_ARRAY"),
01557   EnumToStr_t(SCLASS_COMMENT,   "S_COMMENT"),
01558   EnumToStr_t(SCLASS_THREAD_PRIVATE_FUNCS, "S_THREAD_PRIVATE_FUNCS"),
01559   EnumToStr_t(SCLASS_MODULE,    "S_MODULE"),
01560   EnumToStr_t(SCLASS_COMMON1,   "S_COMMON1"),
01561 };
01562 
01563 EnumToStr_t STExportToNameTbl[EXPORT_COUNT] = {
01564   EnumToStr_t(EXPORT_LOCAL,          "X_LOCAL"),
01565   EnumToStr_t(EXPORT_LOCAL_INTERNAL, "X_LOCAL_INTERNAL"),
01566   EnumToStr_t(EXPORT_INTERNAL,       "X_INTERNAL"),
01567   EnumToStr_t(EXPORT_HIDDEN,         "X_HIDDEN"),
01568   EnumToStr_t(EXPORT_PROTECTED,      "X_PROTECTED"),
01569   EnumToStr_t(EXPORT_PREEMPTIBLE,    "X_PREEMPTIBLE"),
01570   EnumToStr_t(EXPORT_OPTIONAL,       "X_OPTIONAL"),
01571   EnumToStr_t(EXPORT_INTRINSIC,       "X_INTRINSIC"),
01572 };
01573 
01574 EnumToStr_t TYKindToNameTbl[KIND_LAST] = {
01575   EnumToStr_t(KIND_INVALID,  "INVALID"),
01576   EnumToStr_t(KIND_SCALAR,   "SCALAR"),
01577   EnumToStr_t(KIND_ARRAY,    "ARRAY"),
01578   EnumToStr_t(KIND_STRUCT,   "STRUCT"),
01579   EnumToStr_t(KIND_POINTER,  "POINTER"),
01580   EnumToStr_t(KIND_FUNCTION, "FUNCTION"),
01581   EnumToStr_t(KIND_VOID,     "VOID"),
01582 };
01583 
01584 
01585 #define STATTR_ToStrTblENTRY(flg) \
01586   EnumToStr_t(flg, #flg)
01587 
01588 EnumToStr_t STATTR_ToStrTbl[] = {
01589   STATTR_ToStrTblENTRY(ST_ATTR_UNKNOWN),
01590   STATTR_ToStrTblENTRY(ST_ATTR_DEDICATED_REGISTER),
01591   STATTR_ToStrTblENTRY(ST_ATTR_SECTION_NAME)
01592 };
01593 
01594 
01595 #define LKIND_ToStrTblENTRY(flg) \
01596   EnumToStr_t(flg, #flg)
01597 
01598 EnumToStr_t LKIND_ToStrTbl[] = {
01599   LKIND_ToStrTblENTRY(LKIND_DEFAULT),
01600   LKIND_ToStrTblENTRY(LKIND_ASSIGNED),
01601   LKIND_ToStrTblENTRY(LKIND_BEGIN_EH_RANGE),
01602   LKIND_ToStrTblENTRY(LKIND_END_EH_RANGE),
01603   LKIND_ToStrTblENTRY(LKIND_BEGIN_HANDLER),
01604   LKIND_ToStrTblENTRY(LKIND_END_HANDLER),
01605   LKIND_ToStrTblENTRY(LKIND_TAG),
01606   LKIND_ToStrTblENTRY(LKIND_INTERNAL),
01607   LKIND_ToStrTblENTRY(LKIND_LOOP_GEN),
01608   LKIND_ToStrTblENTRY(LKIND_SELECT_GEN)
01609 };
01610 
01611 
01612 const char *
01613 Class_Name (ST_CLASS cl)
01614 {
01615   using namespace ir_a2b;
01616   return MapEnumToStr<EnumToStr_t, STClassToNameTbl,
01617                       CLASS_COUNT>("STClassToNameTbl", (INT)cl);
01618 }
01619 
01620 ST_CLASS
01621 Name_To_Class (const char* nm) 
01622 {
01623   using namespace ir_a2b;
01624   return (ST_CLASS)MapStrToEnum<EnumToStr_t, STClassToNameTbl, 
01625                                 CLASS_COUNT>("STClassToNameTbl", nm);
01626 }
01627 
01628 
01629 const char *
01630 Sclass_Name (ST_SCLASS sc)
01631 {
01632   using namespace ir_a2b;
01633   return MapEnumToStr<EnumToStr_t, STSclassToNameTbl, 
01634                       SCLASS_COUNT>("STSclassToNameTbl", (INT)sc);
01635 }
01636 
01637 ST_SCLASS
01638 Name_To_Sclass (const char* nm)
01639 {
01640   using namespace ir_a2b;
01641   return (ST_SCLASS)MapStrToEnum<EnumToStr_t, STSclassToNameTbl, 
01642                                  SCLASS_COUNT>("STSclassToNameTbl", nm);
01643 }
01644 
01645 
01646 const char *
01647 Export_Name (ST_EXPORT ex)
01648 {
01649   using namespace ir_a2b;
01650   return MapEnumToStr<EnumToStr_t, STExportToNameTbl, 
01651                       EXPORT_COUNT>("STExportToNameTbl", (INT)ex);
01652 }
01653 
01654 ST_EXPORT
01655 Name_To_Export (const char* nm)
01656 {
01657   using namespace ir_a2b;
01658   return (ST_EXPORT)MapStrToEnum<EnumToStr_t, STExportToNameTbl, 
01659                                  EXPORT_COUNT>("STExportToNameTbl", nm);
01660 }
01661 
01662 
01663 const char *
01664 Kind_Name (TY_KIND k)
01665 {
01666   using namespace ir_a2b;
01667   return MapEnumToStr<EnumToStr_t, TYKindToNameTbl, 
01668                       KIND_LAST>("TYKindToNameTbl", (INT)k);
01669 }
01670 
01671 TY_KIND
01672 Name_To_Kind (const char* nm)
01673 {
01674   using namespace ir_a2b;
01675   return (TY_KIND)MapStrToEnum<EnumToStr_t, TYKindToNameTbl, 
01676                                KIND_LAST>("TYKindToNameTbl", nm);
01677 }
01678 
01679 
01680 const char *
01681 LABEL_Kind_Name (LABEL_KIND k)
01682 {
01683   using namespace ir_a2b;
01684   return MapEnumToStr<EnumToStr_t, LKIND_ToStrTbl, 
01685                       LKIND_COUNT>("LKIND_ToStrTbl", (INT)k);
01686 }
01687 
01688 LABEL_KIND
01689 Name_To_LABEL_Kind (const char* nm)
01690 {
01691   using namespace ir_a2b;
01692   return (LABEL_KIND)MapStrToEnum<EnumToStr_t, LKIND_ToStrTbl, 
01693                                   LKIND_COUNT>("LKIND_ToStrTbl", nm);
01694 }
01695 
01696 
01697 const char *
01698 ST_ATTR_Kind_Name (ST_ATTR_KIND k)
01699 {
01700   using namespace ir_a2b;
01701   return MapEnumToStr<EnumToStr_t, STATTR_ToStrTbl, 
01702                       ST_ATTR_KIND_COUNT>("STATTR_ToStrTbl", (INT)k);
01703 }
01704 
01705 ST_ATTR_KIND
01706 Name_To_ST_ATTR_Kind (const char* nm)
01707 {
01708   using namespace ir_a2b;
01709   return (ST_ATTR_KIND)MapStrToEnum<EnumToStr_t, STATTR_ToStrTbl, 
01710                                     ST_ATTR_KIND_COUNT>("STATTR_ToStrTbl", nm);
01711 }
01712 
01713 
01714 /* ====================================================================
01715  *
01716  * xxxFlag_Name 
01717  *   Given flag set, convert to a comma-separated flag string
01718  *
01719  * Name_To_xxxFlag
01720  *   Given a comma-separated flag string, convert to a flags set
01721  *
01722  * ====================================================================
01723  */
01724 
01725 // eraxxon (2005.01): Create these routines to support conversion in
01726 // both directions.
01727 
01728 // The type for flag value -> string tables
01729 struct FlagToStr_t : public ir_a2b::flag2str_tbl_entry_t {
01730   FlagToStr_t(UINT64 val_ = 0, const char* str_ = 0) 
01731     : val(val_), str(str_) { }
01732 
01733   virtual ~FlagToStr_t() { }
01734 
01735   virtual UINT64 getFlagVal() const  { return val; }
01736   virtual const char* getStr() const { return str; }
01737 
01738   UINT64      val;
01739   const char* str;
01740 };
01741 
01742 
01743 // FILE_INFO_FLAGS
01744 #define FIFLAGS_ToStrTblENTRY(flg) \
01745   FlagToStr_t(flg, #flg)
01746 
01747 FlagToStr_t FIFLAGS_ToStrTbl[] = {
01748   FIFLAGS_ToStrTblENTRY(FI_IPA),
01749   FIFLAGS_ToStrTblENTRY(FI_NEEDS_LNO),
01750   FIFLAGS_ToStrTblENTRY(FI_HAS_INLINES),
01751   FIFLAGS_ToStrTblENTRY(FI_HAS_MP)
01752 };
01753 
01754 const UINT FIFLAGS_ToStrTblSZ = 
01755   (sizeof(FIFLAGS_ToStrTbl) / sizeof(FlagToStr_t));
01756 
01757 
01758 // ST_FLAGS
01759 #define STFLAGS_ToStrTblENTRY(flg) \
01760   FlagToStr_t(flg, #flg)
01761 
01762 FlagToStr_t STFLAGS_ToStrTbl[] = {
01763   STFLAGS_ToStrTblENTRY(ST_IS_WEAK_SYMBOL),
01764   STFLAGS_ToStrTblENTRY(ST_IS_SPLIT_COMMON),
01765   STFLAGS_ToStrTblENTRY(ST_IS_NOT_USED),
01766   STFLAGS_ToStrTblENTRY(ST_IS_INITIALIZED),
01767   STFLAGS_ToStrTblENTRY(ST_IS_RETURN_VAR),
01768   STFLAGS_ToStrTblENTRY(ST_IS_VALUE_PARM),
01769   STFLAGS_ToStrTblENTRY(ST_PROMOTE_PARM),
01770   STFLAGS_ToStrTblENTRY(ST_KEEP_NAME_W2F),
01771   STFLAGS_ToStrTblENTRY(ST_IS_DATAPOOL),
01772   STFLAGS_ToStrTblENTRY(ST_IS_RESHAPED),
01773   STFLAGS_ToStrTblENTRY(ST_EMIT_SYMBOL),
01774   STFLAGS_ToStrTblENTRY(ST_HAS_NESTED_REF),
01775   STFLAGS_ToStrTblENTRY(ST_INIT_VALUE_ZERO),
01776   STFLAGS_ToStrTblENTRY(ST_GPREL),
01777   STFLAGS_ToStrTblENTRY(ST_NOT_GPREL),
01778   STFLAGS_ToStrTblENTRY(ST_IS_NAMELIST),
01779   STFLAGS_ToStrTblENTRY(ST_IS_F90_TARGET),
01780   STFLAGS_ToStrTblENTRY(ST_DECLARED_STATIC),
01781   STFLAGS_ToStrTblENTRY(ST_IS_EQUIVALENCED),
01782   STFLAGS_ToStrTblENTRY(ST_IS_FILL_ALIGN),
01783   STFLAGS_ToStrTblENTRY(ST_IS_OPTIONAL_ARGUMENT),
01784   STFLAGS_ToStrTblENTRY(ST_PT_TO_UNIQUE_MEM),
01785   STFLAGS_ToStrTblENTRY(ST_IS_TEMP_VAR),
01786   STFLAGS_ToStrTblENTRY(ST_IS_CONST_VAR),
01787   STFLAGS_ToStrTblENTRY(ST_ADDR_SAVED),
01788   STFLAGS_ToStrTblENTRY(ST_ADDR_PASSED),
01789   STFLAGS_ToStrTblENTRY(ST_IS_THREAD_PRIVATE),
01790   STFLAGS_ToStrTblENTRY(ST_PT_TO_COMPILER_GENERATED_MEM),
01791   STFLAGS_ToStrTblENTRY(ST_IS_SHARED_AUTO),
01792   STFLAGS_ToStrTblENTRY(ST_ASSIGNED_TO_DEDICATED_PREG),
01793   STFLAGS_ToStrTblENTRY(ST_ASM_FUNCTION_ST),
01794   STFLAGS_ToStrTblENTRY(ST_HAS_NAMED_SECTION)
01795 };
01796 
01797 const UINT STFLAGS_ToStrTblSZ = 
01798   (sizeof(STFLAGS_ToStrTbl) / sizeof(FlagToStr_t));
01799 
01800 
01801 // ST_EXT_FLAGS
01802 #define STEXTFLAGS_ToStrTblENTRY(flg) \
01803   FlagToStr_t(flg, #flg)
01804 
01805 FlagToStr_t STEXTFLAGS_ToStrTbl[] = {
01806   STEXTFLAGS_ToStrTblENTRY(ST_IS_POINTER),  
01807   STEXTFLAGS_ToStrTblENTRY(ST_IS_ALLOCATABLE),
01808   STEXTFLAGS_ToStrTblENTRY(ST_IS_IN_MODULE),
01809   STEXTFLAGS_ToStrTblENTRY(ST_IS_EXTERNAL),
01810   STEXTFLAGS_ToStrTblENTRY(ST_IS_BLOCK_DATA), 
01811   STEXTFLAGS_ToStrTblENTRY(ST_IS_INTENT_IN_ARGUMENT),
01812   STEXTFLAGS_ToStrTblENTRY(ST_IS_INTENT_OUT_ARGUMENT),
01813   STEXTFLAGS_ToStrTblENTRY(ST_IS_ASSIGN_INTERFACE),
01814   STEXTFLAGS_ToStrTblENTRY(ST_IS_OPERATOR_INTERFACE),
01815   STEXTFLAGS_ToStrTblENTRY(ST_IS_U_OPERATOR_INTERFACE),
01816   STEXTFLAGS_ToStrTblENTRY(ST_IS_PRIVATE),
01817   STEXTFLAGS_ToStrTblENTRY(ST_IS_M_IMPORTED),
01818   STEXTFLAGS_ToStrTblENTRY(ST_IS_IMPLEM_LEVEL_TEMP),
01819   STEXTFLAGS_ToStrTblENTRY(ST_IS_PARAMETER),
01820   STEXTFLAGS_ToStrTblENTRY(ST_ONE_PER_PU),
01821   STEXTFLAGS_ToStrTblENTRY(ST_COPY_CONSTRUCTOR_ST),
01822   STEXTFLAGS_ToStrTblENTRY(ST_INITV_IN_OTHER_ST),
01823   STEXTFLAGS_ToStrTblENTRY(ST_IS_INITIALIZED_IN_F90),
01824   STEXTFLAGS_ToStrTblENTRY(ST_IS_DELETED), 
01825   STEXTFLAGS_ToStrTblENTRY(ST_IS_COARRAY_CONCURRENT), 
01826   STEXTFLAGS_ToStrTblENTRY(ST_KEEP_IN_OPENAD), 
01827 };
01828 
01829 const UINT STEXTFLAGS_ToStrTblSZ = 
01830   (sizeof(STEXTFLAGS_ToStrTbl) / sizeof(FlagToStr_t));
01831 
01832 
01833 // FLD_FLAGS
01834 #define FLDFLAGS_ToStrTblENTRY(flg) \
01835   FlagToStr_t(flg, #flg)
01836 
01837 FlagToStr_t FLDFLAGS_ToStrTbl[] = {
01838   FLDFLAGS_ToStrTblENTRY(FLD_LAST_FIELD),
01839   FLDFLAGS_ToStrTblENTRY(FLD_EQUIVALENCE),
01840   FLDFLAGS_ToStrTblENTRY(FLD_BEGIN_UNION),
01841   FLDFLAGS_ToStrTblENTRY(FLD_END_UNION),
01842   FLDFLAGS_ToStrTblENTRY(FLD_BEGIN_MAP),
01843   FLDFLAGS_ToStrTblENTRY(FLD_END_MAP),
01844   FLDFLAGS_ToStrTblENTRY(FLD_IS_BIT_FIELD),
01845   FLDFLAGS_ToStrTblENTRY(FLD_IS_POINTER)
01846 };
01847 
01848 const UINT FLDFLAGS_ToStrTblSZ = 
01849   (sizeof(FLDFLAGS_ToStrTbl) / sizeof(FlagToStr_t));
01850 
01851 
01852 // ARB_FLAGS
01853 #define ARBFLAGS_ToStrTblENTRY(flg) \
01854   FlagToStr_t(flg, #flg)
01855 
01856 FlagToStr_t ARBFLAGS_ToStrTbl[] = {
01857   ARBFLAGS_ToStrTblENTRY(ARB_CONST_LBND),
01858   ARBFLAGS_ToStrTblENTRY(ARB_CONST_UBND),
01859   ARBFLAGS_ToStrTblENTRY(ARB_CONST_STRIDE),
01860   ARBFLAGS_ToStrTblENTRY(ARB_FIRST_DIMEN),
01861   ARBFLAGS_ToStrTblENTRY(ARB_LAST_DIMEN),
01862   ARBFLAGS_ToStrTblENTRY(ARB_EMPTY_LBND),
01863   ARBFLAGS_ToStrTblENTRY(ARB_EMPTY_UBND),
01864   ARBFLAGS_ToStrTblENTRY(ARB_STAR_UBND),
01865   ARBFLAGS_ToStrTblENTRY(ARB_EMPTY_STRIDE)
01866 };
01867 
01868 const UINT ARBFLAGS_ToStrTblSZ = 
01869   (sizeof(ARBFLAGS_ToStrTbl) / sizeof(FlagToStr_t));
01870 
01871 
01872 // LABEL_FLAGS
01873 #define LBLFLAGS_ToStrTblENTRY(flg) \
01874   FlagToStr_t(flg, #flg)
01875 
01876 FlagToStr_t LBLFLAGS_ToStrTbl[] = {
01877   LBLFLAGS_ToStrTblENTRY(LABEL_TARGET_OF_GOTO_OUTER_BLOCK),
01878   LBLFLAGS_ToStrTblENTRY(LABEL_ADDR_SAVED),
01879   LBLFLAGS_ToStrTblENTRY(LABEL_ADDR_PASSED)
01880 };
01881 
01882 const UINT LBLFLAGS_ToStrTblSZ = 
01883   (sizeof(LBLFLAGS_ToStrTbl) / sizeof(FlagToStr_t));
01884 
01885 
01886 // TY_FLAGS
01887 #define TYFLAGS_ToStrTblENTRY(flg) \
01888   FlagToStr_t(flg, #flg)
01889 
01890 FlagToStr_t TYFLAGS_ToStrTbl[] = {
01891   TYFLAGS_ToStrTblENTRY(TY_IS_CHARACTER),
01892   TYFLAGS_ToStrTblENTRY(TY_IS_LOGICAL),
01893   TYFLAGS_ToStrTblENTRY(TY_IS_UNION),
01894   TYFLAGS_ToStrTblENTRY(TY_IS_PACKED),
01895   TYFLAGS_ToStrTblENTRY(TY_PTR_AS_ARRAY),
01896   TYFLAGS_ToStrTblENTRY(TY_ANONYMOUS),
01897   TYFLAGS_ToStrTblENTRY(TY_SPLIT),
01898   TYFLAGS_ToStrTblENTRY(TY_IS_F90_POINTER),
01899   TYFLAGS_ToStrTblENTRY(TY_NOT_IN_UNION),
01900   TYFLAGS_ToStrTblENTRY(TY_NO_ANSI_ALIAS),
01901   TYFLAGS_ToStrTblENTRY(TY_IS_NON_POD),
01902   TYFLAGS_ToStrTblENTRY(TY_IS_F90_ASSUMED_SHAPE),
01903   TYFLAGS_ToStrTblENTRY(TY_IS_F90_ASSUMED_SIZE),
01904   TYFLAGS_ToStrTblENTRY(TY_IS_F90_DEFERRED_SHAPE),
01905   TYFLAGS_ToStrTblENTRY(TY_IS_EXTERNAL),
01906   TYFLAGS_ToStrTblENTRY(TY_IS_SEQUENCE),
01907   TYFLAGS_ToStrTblENTRY(TY_IS_SHARED),
01908   TYFLAGS_ToStrTblENTRY(TY_IS_STRICT),
01909   TYFLAGS_ToStrTblENTRY(TY_IS_RELAXED),
01910   TYFLAGS_ToStrTblENTRY(TY_IS_CO_ARRAY),
01911   TYFLAGS_ToStrTblENTRY(TY_IS_WRITTEN),
01912   TYFLAGS_ToStrTblENTRY(TY_RETURN_IN_MEM)
01913 };
01914 
01915 const UINT TYFLAGS_ToStrTblSZ = 
01916   (sizeof(TYFLAGS_ToStrTbl) / sizeof(FlagToStr_t));
01917 
01918 
01919 // TY_PU_FLAGS
01920 #define TYPUFLAGS_ToStrTblENTRY(flg) \
01921   FlagToStr_t(flg, #flg)
01922 
01923 FlagToStr_t TYPUFLAGS_ToStrTbl[] = {
01924   TYPUFLAGS_ToStrTblENTRY(TY_RETURN_TO_PARAM),
01925   TYPUFLAGS_ToStrTblENTRY(TY_IS_VARARGS),
01926   TYPUFLAGS_ToStrTblENTRY(TY_HAS_PROTOTYPE)
01927 };
01928 
01929 const UINT TYPUFLAGS_ToStrTblSZ = 
01930   (sizeof(TYPUFLAGS_ToStrTbl) / sizeof(FlagToStr_t));
01931 
01932 
01933 // PU_FLAGS
01934 #define PUFLAGS_ToStrTblENTRY(flg) \
01935   FlagToStr_t(flg, #flg)
01936 
01937 FlagToStr_t PUFLAGS_ToStrTbl[] = {
01938   PUFLAGS_ToStrTblENTRY(PU_IS_PURE),
01939   PUFLAGS_ToStrTblENTRY(PU_NO_SIDE_EFFECTS),
01940   PUFLAGS_ToStrTblENTRY(PU_IS_INLINE_FUNCTION),
01941   PUFLAGS_ToStrTblENTRY(PU_NO_INLINE),
01942   PUFLAGS_ToStrTblENTRY(PU_MUST_INLINE),
01943   PUFLAGS_ToStrTblENTRY(PU_NO_DELETE),
01944   PUFLAGS_ToStrTblENTRY(PU_HAS_EXC_SCOPES),
01945   PUFLAGS_ToStrTblENTRY(PU_IS_NESTED_FUNC),
01946   PUFLAGS_ToStrTblENTRY(PU_HAS_NON_MANGLED_CALL),
01947   PUFLAGS_ToStrTblENTRY(PU_ARGS_ALIASED),
01948   PUFLAGS_ToStrTblENTRY(PU_NEEDS_FILL_ALIGN_LOWERING),
01949   PUFLAGS_ToStrTblENTRY(PU_NEEDS_T9),
01950   PUFLAGS_ToStrTblENTRY(PU_HAS_VERY_HIGH_WHIRL),
01951   PUFLAGS_ToStrTblENTRY(PU_HAS_ALTENTRY),
01952   PUFLAGS_ToStrTblENTRY(PU_RECURSIVE),
01953   PUFLAGS_ToStrTblENTRY(PU_IS_MAINPU),
01954   PUFLAGS_ToStrTblENTRY(PU_UPLEVEL),
01955   PUFLAGS_ToStrTblENTRY(PU_MP_NEEDS_LNO),
01956   PUFLAGS_ToStrTblENTRY(PU_HAS_ALLOCA),
01957   PUFLAGS_ToStrTblENTRY(PU_IN_ELF_SECTION),
01958   PUFLAGS_ToStrTblENTRY(PU_HAS_MP),
01959   PUFLAGS_ToStrTblENTRY(PU_MP),
01960   PUFLAGS_ToStrTblENTRY(PU_HAS_NAMELIST),
01961   PUFLAGS_ToStrTblENTRY(PU_HAS_RETURN_ADDRESS),
01962   PUFLAGS_ToStrTblENTRY(PU_HAS_REGION),
01963   PUFLAGS_ToStrTblENTRY(PU_HAS_INLINES),
01964   PUFLAGS_ToStrTblENTRY(PU_CALLS_SETJMP),
01965   PUFLAGS_ToStrTblENTRY(PU_CALLS_LONGJMP),
01966   PUFLAGS_ToStrTblENTRY(PU_IPA_ADDR_ANALYSIS),
01967   PUFLAGS_ToStrTblENTRY(PU_SMART_ADDR_ANALYSIS),
01968   PUFLAGS_ToStrTblENTRY(PU_HAS_SYSCALL_LINKAGE),
01969   PUFLAGS_ToStrTblENTRY(PU_HAS_GLOBAL_PRAGMAS),
01970   PUFLAGS_ToStrTblENTRY(PU_HAS_USER_ALLOCA),
01971   PUFLAGS_ToStrTblENTRY(PU_HAS_UNKNOWN_CONTROL_FLOW),
01972   PUFLAGS_ToStrTblENTRY(PU_IS_THUNK),
01973   PUFLAGS_ToStrTblENTRY(PU_DECL_VIEW),
01974   PUFLAGS_ToStrTblENTRY(PU_NEED_UNPARSED),
01975   PUFLAGS_ToStrTblENTRY(PU_NEEDS_MANUAL_UNWINDING),
01976 #ifdef TARG_X8664
01977   PUFLAGS_ToStrTblENTRY(PU_FF2C_ABI)
01978 #endif
01979 };
01980 
01981 const UINT PUFLAGS_ToStrTblSZ = 
01982   (sizeof(PUFLAGS_ToStrTbl) / sizeof(FlagToStr_t));
01983 
01984 
01985 // PU_SRC_LANG_FLAGS
01986 #define PUSRCLANGFLAGS_ToStrTblENTRY(flg) \
01987   FlagToStr_t(flg, #flg)
01988 
01989 FlagToStr_t PUSRCLANGFLAGS_ToStrTbl[] = {
01990   PUSRCLANGFLAGS_ToStrTblENTRY(PU_UNKNOWN_LANG),
01991   PUSRCLANGFLAGS_ToStrTblENTRY(PU_MIXED_LANG),
01992   PUSRCLANGFLAGS_ToStrTblENTRY(PU_C_LANG),
01993   PUSRCLANGFLAGS_ToStrTblENTRY(PU_CXX_LANG),
01994   PUSRCLANGFLAGS_ToStrTblENTRY(PU_F77_LANG),
01995   PUSRCLANGFLAGS_ToStrTblENTRY(PU_F90_LANG),
01996   PUSRCLANGFLAGS_ToStrTblENTRY(PU_JAVA_LANG)
01997 };
01998 
01999 const UINT PUSRCLANGFLAGS_ToStrTblSZ = 
02000   (sizeof(PUSRCLANGFLAGS_ToStrTbl) / sizeof(FlagToStr_t));
02001 
02002 
02003 // BLK
02004 #define BLKFLAGS_ToStrTblENTRY(flg) \
02005   FlagToStr_t(flg, #flg)
02006 
02007 FlagToStr_t BLKFLAGS_ToStrTbl[] = {
02008   BLKFLAGS_ToStrTblENTRY(BLK_SECTION),
02009   BLKFLAGS_ToStrTblENTRY(BLK_ROOT_BASE),
02010   BLKFLAGS_ToStrTblENTRY(BLK_IS_BASEREG),
02011   BLKFLAGS_ToStrTblENTRY(BLK_DECREMENT),
02012   BLKFLAGS_ToStrTblENTRY(BLK_EXEC),
02013   BLKFLAGS_ToStrTblENTRY(BLK_NOBITS),
02014   BLKFLAGS_ToStrTblENTRY(BLK_MERGE),
02015   BLKFLAGS_ToStrTblENTRY(BLK_COMPILER_LAYOUT)
02016 };
02017 
02018 const UINT BLKFLAGS_ToStrTblSZ = 
02019   (sizeof(BLKFLAGS_ToStrTbl) / sizeof(FlagToStr_t));
02020 
02021 
02022 const char *
02023 FILE_INFO_FLAGS_To_Str (UINT64 flags)
02024 {
02025   using namespace ir_a2b;
02026   return MapFlagsToStr<FlagToStr_t, FIFLAGS_ToStrTbl, 
02027                        FIFLAGS_ToStrTblSZ>("FIFLAGS_ToStrTbl", flags);
02028 }
02029 
02030 UINT64
02031 Str_To_FILE_INFO_FLAGS (const char* str)
02032 {
02033   using namespace ir_a2b;
02034   return MapStrToFlags<FlagToStr_t, FIFLAGS_ToStrTbl, 
02035                        FIFLAGS_ToStrTblSZ>("FIFLAGS_ToStrTbl", str);
02036 }
02037 
02038 
02039 const char *
02040 ST_FLAGS_To_Str (UINT64 flags)
02041 {
02042   using namespace ir_a2b;
02043   return MapFlagsToStr<FlagToStr_t, STFLAGS_ToStrTbl, 
02044                        STFLAGS_ToStrTblSZ>("STFLAGS_ToStrTbl", flags);
02045 }
02046 
02047 UINT64
02048 Str_To_ST_FLAGS (const char* str)
02049 {
02050   using namespace ir_a2b;
02051   return MapStrToFlags<FlagToStr_t, STFLAGS_ToStrTbl, 
02052                        STFLAGS_ToStrTblSZ>("STFLAGS_ToStrTbl", str);
02053 }
02054 
02055 
02056 const char *
02057 ST_EXT_FLAGS_To_Str (UINT64 flags)
02058 {
02059   using namespace ir_a2b;
02060   return MapFlagsToStr<FlagToStr_t, STEXTFLAGS_ToStrTbl,
02061                        STEXTFLAGS_ToStrTblSZ>("STEXTFLAGS_ToStrTbl", flags);
02062 }
02063 
02064 UINT64
02065 Str_To_ST_EXT_FLAGS (const char* str)
02066 {
02067   using namespace ir_a2b;
02068   return MapStrToFlags<FlagToStr_t, STEXTFLAGS_ToStrTbl, 
02069                        STEXTFLAGS_ToStrTblSZ>("STEXTFLAGS_ToStrTbl", str);
02070 }
02071 
02072 
02073 const char *
02074 FLD_FLAGS_To_Str (UINT64 flags)
02075 {
02076   using namespace ir_a2b;
02077   return MapFlagsToStr<FlagToStr_t, FLDFLAGS_ToStrTbl,
02078                        FLDFLAGS_ToStrTblSZ>("FLDFLAGS_ToStrTbl", flags);
02079 }
02080 
02081 UINT64
02082 Str_To_FLD_FLAGS (const char* str)
02083 {
02084   using namespace ir_a2b;
02085   return MapStrToFlags<FlagToStr_t, FLDFLAGS_ToStrTbl, 
02086                        FLDFLAGS_ToStrTblSZ>("FLDFLAGS_ToStrTbl", str);
02087 }
02088 
02089 
02090 const char *
02091 ARB_FLAGS_To_Str (UINT64 flags)
02092 {
02093   using namespace ir_a2b;
02094   return MapFlagsToStr<FlagToStr_t, ARBFLAGS_ToStrTbl, 
02095                        ARBFLAGS_ToStrTblSZ>("ARBFLAGS_ToStrTbl", flags);
02096 }
02097 
02098 UINT64
02099 Str_To_ARB_FLAGS (const char* str)
02100 {
02101   using namespace ir_a2b;
02102   return MapStrToFlags<FlagToStr_t, ARBFLAGS_ToStrTbl, 
02103                        ARBFLAGS_ToStrTblSZ>("ARBFLAGS_ToStrTbl", str);
02104 }
02105 
02106 
02107 const char *
02108 LABEL_FLAGS_To_Str (UINT64 flags)
02109 {
02110   using namespace ir_a2b;
02111   return MapFlagsToStr<FlagToStr_t, LBLFLAGS_ToStrTbl, 
02112                        LBLFLAGS_ToStrTblSZ>("LBLFLAGS_ToStrTbl", flags);
02113 }
02114 
02115 UINT64
02116 Str_To_LABEL_FLAGS (const char* str)
02117 {
02118   using namespace ir_a2b;
02119   return MapStrToFlags<FlagToStr_t, LBLFLAGS_ToStrTbl, 
02120                        LBLFLAGS_ToStrTblSZ>("LBLFLAGS_ToStrTbl", str);
02121 }
02122 
02123 
02124 const char *
02125 TY_FLAGS_To_Str (UINT64 flags)
02126 {
02127   using namespace ir_a2b;
02128   return MapFlagsToStr<FlagToStr_t, TYFLAGS_ToStrTbl, 
02129                        TYFLAGS_ToStrTblSZ>("TYFLAGS_ToStrTbl", flags);
02130 }
02131 
02132 UINT64
02133 Str_To_TY_FLAGS (const char* str)
02134 {
02135   using namespace ir_a2b;
02136   return MapStrToFlags<FlagToStr_t, TYFLAGS_ToStrTbl, 
02137                        TYFLAGS_ToStrTblSZ>("TYFLAGS_ToStrTbl", str);
02138 }
02139 
02140 
02141 const char *
02142 TY_PU_FLAGS_To_Str (UINT64 flags)
02143 {
02144   using namespace ir_a2b;
02145   return MapFlagsToStr<FlagToStr_t, TYPUFLAGS_ToStrTbl, 
02146                        TYPUFLAGS_ToStrTblSZ>("TYPUFLAGS_ToStrTbl", flags);
02147 }
02148 
02149 UINT64
02150 Str_To_TY_PU_FLAGS (const char* str)
02151 {
02152   using namespace ir_a2b;
02153   return MapStrToFlags<FlagToStr_t, TYPUFLAGS_ToStrTbl, 
02154                        TYPUFLAGS_ToStrTblSZ>("TYPUFLAGS_ToStrTbl", str);
02155 }
02156 
02157 
02158 const char *
02159 PU_FLAGS_To_Str (UINT64 flags)
02160 {
02161   using namespace ir_a2b;
02162   return MapFlagsToStr<FlagToStr_t, PUFLAGS_ToStrTbl, 
02163                        PUFLAGS_ToStrTblSZ>("PUFLAGS_ToStrTbl", flags);
02164 }
02165 
02166 UINT64
02167 Str_To_PU_FLAGS (const char* str)
02168 {
02169   using namespace ir_a2b;
02170   return MapStrToFlags<FlagToStr_t, PUFLAGS_ToStrTbl, 
02171                        PUFLAGS_ToStrTblSZ>("PUFLAGS_ToStrTbl", str);
02172 }
02173 
02174 
02175 const char *
02176 PU_SRC_LANG_FLAGS_To_Str (UINT64 flags)
02177 {
02178   using namespace ir_a2b;
02179   return MapFlagsToStr<FlagToStr_t, PUSRCLANGFLAGS_ToStrTbl, 
02180                        PUSRCLANGFLAGS_ToStrTblSZ>("PUSRCLANGFLAGS_ToStrTbl", 
02181                                                   flags);
02182 }
02183 
02184 UINT64
02185 Str_To_PU_SRC_LANG_FLAGS (const char* str)
02186 {
02187   using namespace ir_a2b;
02188   return MapStrToFlags<FlagToStr_t, PUSRCLANGFLAGS_ToStrTbl, 
02189                        PUSRCLANGFLAGS_ToStrTblSZ>("PUSRCLANGFLAGS_ToStrTbl", 
02190                                                   str);
02191 }
02192 
02193 
02194 const char *
02195 BLK_FLAGS_To_Str (UINT64 flags)
02196 {
02197   using namespace ir_a2b;
02198   return MapFlagsToStr<FlagToStr_t, BLKFLAGS_ToStrTbl, 
02199                        BLKFLAGS_ToStrTblSZ>("BLKFLAGS_ToStrTbl", flags);
02200 }
02201 
02202 UINT64
02203 Str_To_BLK_FLAGS (const char* str)
02204 {
02205   using namespace ir_a2b;
02206   return MapStrToFlags<FlagToStr_t, BLKFLAGS_ToStrTbl, 
02207                        BLKFLAGS_ToStrTblSZ>("BLKFLAGS_ToStrTbl", str);
02208 }
02209 
02210 
02211 /* ====================================================================
02212  *
02213  * Print routines
02214  *
02215  * ====================================================================
02216  */
02217 
02218 static void
02219 Print_type_attributes (FILE *f, TY_IDX ty)
02220 {
02221     if (TY_is_const (ty))
02222         fputs ("const ", f);
02223     if (TY_is_volatile (ty))
02224         fputs ("volatile ", f);
02225     if (TY_is_restrict (ty))
02226         fputs ("restrict ", f);
02227 } // Print_type_attributes
02228 
02229 
02230 static void
02231 Print_TY_IDX_verbose (FILE *f, TY_IDX idx)
02232 {
02233     Print_type_attributes (f, idx);
02234     if (TY_IDX_index (idx) == 0) {
02235         fputs ("<NULL>", f);
02236         return;
02237     }
02238         
02239     const TY& ty = Ty_Table[idx];
02240     const char *name = TY_name_idx (ty) == 0 ? "(anon)" : TY_name (ty);
02241     fprintf (f, "%s (#%d) align %d", name, TY_IDX_index (idx), TY_align (idx));
02242 } // Print_TY_IDX_verbose
02243 
02244 
02245 static const char *
02246 TY_kind_name (const TY& ty)
02247 {
02248     if (TY_kind (ty) == KIND_SCALAR && TY_mtype (ty) != MTYPE_UNKNOWN)
02249         return MTYPE_name (TY_mtype (ty));
02250     else
02251         return Kind_Name (TY_kind (ty));
02252 }
02253 
02254 
02255 void
02256 ST::Print (FILE *f, BOOL verbose) const
02257 {
02258     const char *name_str = (sym_class == CLASS_CONST) ?
02259         "<constant>" : &Str_Table[u1.name_idx];
02260 
02261     fprintf (f, "%-14s\t<%d,%d> ", name_str, ST_IDX_level (st_idx),
02262              ST_IDX_index (st_idx));
02263     if (strlen (name_str) > 20)
02264         fputs ("\n\t\t", f);
02265 
02266     fprintf (f, "%s", Class_Name(sym_class));
02267 
02268     TY_IDX ty_idx = 0;
02269 
02270     switch (sym_class) {
02271     case CLASS_VAR:
02272     case CLASS_TYPE: 
02273         ty_idx = u2.type;
02274         break;
02275 
02276     case CLASS_FUNC:
02277         ty_idx = PU_prototype (Pu_Table[u2.pu]);
02278         break;
02279 
02280     case CLASS_CONST:
02281         ty_idx = u2.type;
02282         break;
02283 
02284     case CLASS_PREG:
02285         ty_idx = u2.type;
02286         break;
02287 
02288     case CLASS_BLOCK:
02289         fprintf (f, " (#%d)", u2.blk);
02290         break;
02291     }
02292 
02293     const TY& ty = Ty_Table [ty_idx];
02294 
02295     if (ty_idx != 0) {
02296 
02297         name_str = TY_name_idx (ty) == 0 ? NULL : TY_name (ty);
02298 
02299         if (!(sym_class == CLASS_FUNC) || name_str != NULL) {
02300             fputs (" of type ", f);
02301 
02302             Print_type_attributes (f, ty_idx);
02303 
02304             fputs (name_str ? name_str : "(anon)", f);
02305             
02306             const TY *pty = &ty;
02307             INT pcount = 0;
02308             while (TY_kind (*pty) == KIND_POINTER) {
02309                 pty = &Ty_Table[TY_pointed (*pty)];
02310                 ++pcount;
02311             }
02312             
02313             if (verbose) {
02314                 name_str = TY_kind_name (*pty);
02315                 fprintf (f, " (#%d, %s", TY_IDX_index (ty_idx), name_str);
02316                 while (pcount-- > 0)
02317                     fputc ('*', f);
02318                 fputc (')', f);
02319             } else
02320                 fprintf (f, " (#%d)", TY_IDX_index (ty_idx));
02321         }
02322     }
02323 
02324     if (!verbose) {
02325         /* quick address */
02326         fprintf (f, " @ 0x%llx", offset);
02327         if (base_idx != 0)
02328             fprintf (f, "(%s)", ST_name (base_idx));
02329     }
02330     fputc ('\n', f);
02331 
02332     if (sym_class == CLASS_FUNC && verbose) {
02333         /* Give info about the type being returned, which is different
02334          * than the type of the function.
02335          */
02336         if (ty_idx != 0 && TY_tylist (ty) != 0) {
02337             TY_IDX rettype_idx = Tylist_Table[TY_tylist (ty)];
02338             const TY& rettype = Ty_Table[rettype_idx];
02339             fputs ("\t\tReturning ", f);
02340             Print_type_attributes (f, rettype_idx);
02341             fputs (TY_name (rettype), f);
02342             name_str = TY_kind_name (rettype);
02343             fprintf (f, " (#%d, %s)  ", TY_IDX_index (rettype_idx), name_str);
02344 
02345             fprintf (f, "PU[%d] ", u2.pu);
02346             const char* srclang = 
02347               PU_SRC_LANG_FLAGS_To_Str(Pu_Table[u2.pu].src_lang);
02348             fprintf (f, "%s  ", srclang);
02349             
02350             mUINT64 flags = Pu_Table[u2.pu].flags;
02351             fprintf (f, "flags: %s", PU_FLAGS_To_Str(flags));
02352             if (TY_return_to_param(ty_idx)) fprintf (f, " return_to_param");
02353             if (TY_is_varargs(ty_idx))      fprintf (f, " varargs");
02354             if (TY_has_prototype(ty_idx))   fprintf (f, " prototype");
02355             fprintf (f, "\n");
02356         }
02357     }
02358         
02359     if (sym_class == CLASS_CONST)
02360         fprintf (f, "\t\tvalue: %s\n", Targ_Print (NULL, Tcon_Table[u1.tcon]));
02361 
02362     if (verbose) {
02363         // Print address
02364         if (base_idx != 0) {
02365             const ST& base_st = St_Table[base_idx];
02366             fprintf (f, "\t\tAddress: %lld(%s<%d,%d>)  ", offset,
02367                      ST_class (base_st) == CLASS_CONST ? "" :
02368                      ST_name (base_idx), ST_IDX_level (base_idx),
02369                      ST_IDX_index (base_idx));
02370         }
02371 
02372         if (ty_idx != 0) {
02373             if (base_idx == 0 && offset == 0)
02374                 fputs ("\t\t", f);
02375             fprintf (f, "Alignment: %d bytes", TY_align (ty_idx));
02376         }
02377         fprintf (f, "\n");
02378 
02379         fprintf (f, "\t\tFlags:\t0x%08x", flags);
02380         fprintf (f, " %s", ST_FLAGS_To_Str(flags));
02381 
02382         fprintf (f, ", %s", Export_Name(export_class));
02383         
02384         mUINT64 flags_ext = St_Table[st_idx].flags_ext;
02385         if (flags_ext) {
02386            const char* flgstr = ST_EXT_FLAGS_To_Str(flags_ext);
02387            fprintf (f, "\n\t\tFlags_ext:\t0x%016llx", flags_ext);
02388            fprintf (f, " %s", flgstr);
02389         }
02390         
02391         fprintf (f, "\n\t\tSclass: %s\n", Sclass_Name (storage_class));
02392     }
02393 } // ST::Print
02394 
02395 
02396 void
02397 FLD::Print (FILE *f) const
02398 {
02399     fprintf (f, "\t%6lld  %-8s\t", ofst, &Str_Table[name_idx]);
02400     Print_TY_IDX_verbose (f, type);
02401     fprintf (f, "\n\t\tfl:0x%04x", flags);
02402     if (flags) {
02403         const char* flgstr = FLD_FLAGS_To_Str(flags);
02404         fprintf (f, " %s", flgstr);
02405     }
02406     if (st != 0)
02407         fprintf (f, " st (%d,%d)", ST_IDX_level (st), ST_IDX_index (st));
02408     if (flags & FLD_IS_BIT_FIELD)
02409         fprintf (f, " bit field size:%d ofst:%d", bsize, bofst);
02410     fputc ('\n', f);
02411 } // FLD::Print
02412 
02413 
02414 void
02415 ARB::Print (FILE *f) const
02416 {
02417     if (flags & ARB_CONST_LBND)
02418         fprintf (f, "%lld:", Lbnd_val ());
02419     else
02420         fprintf (f, "st(%d):", ST_IDX_index (Lbnd_var ()));
02421 
02422     if (flags & ARB_CONST_UBND)
02423         fprintf (f, "%lld:", Ubnd_val ());
02424     else
02425         fprintf (f, "st(%d):", ST_IDX_index (Ubnd_var ()));
02426 
02427     if (flags & ARB_CONST_STRIDE)
02428         fprintf (f, "%lld:", Stride_val ());
02429     else
02430         fprintf (f, "st(%d):", ST_IDX_index (Stride_var ()));
02431 
02432 } // ARB::Print
02433 
02434 
02435 void
02436 TY::Print (FILE *f) const
02437 {
02438     fprintf (f, "%-14s:",
02439              name_idx ? &Str_Table[name_idx] : "(anon)");
02440 
02441     fprintf (f, " (f: 0x%08x", flags);
02442     if (flags) {
02443         const char* flgstr = TY_FLAGS_To_Str(flags);
02444         fprintf (f, " %s", flgstr);
02445     }
02446     fprintf (f, ")");
02447 
02448     fprintf (f, " size %lld %s: ",
02449              size, (mtype != 0) ? Mtype_Name (mtype) : ""); 
02450 
02451     switch (kind) {
02452     case KIND_SCALAR:
02453         fprintf (f, "SCALAR (%s)", Mtype_Name (mtype));
02454         fputc ('\n', f);
02455         break;
02456 
02457     case KIND_ARRAY:
02458         fputs ("ARRAY of ", f);
02459         Print_TY_IDX_verbose (f, Etype ());
02460         if (Arb () != 0) {
02461            ARB_HANDLE arb(Arb());
02462            INT i,ndim,co_dim,array_dim;
02463            
02464            ndim = ARB_dimension(arb);
02465            co_dim = ARB_co_dimension(arb);
02466            array_dim = ndim-co_dim;
02467 
02468            fprintf(f,"\n\t\t dimension (%d) ,co_dimension(%d) ",array_dim,co_dim);
02469 
02470            for (i = 0; i < ndim; i++) {
02471               fputs (" (", f);
02472               (*arb[i].Entry()).Print (f);
02473               fputc (')', f);
02474               // possible early exit for broken tables
02475               if (ARB_last_dimen(arb[i])) break;
02476            }
02477         }
02478         fputc ('\n', f);
02479         break;
02480             
02481     case KIND_STRUCT:
02482         if (TY_is_packed (*this))
02483             fputs ("packed ", f);
02484         fputs (kind == KIND_STRUCT ? "STRUCT\n": "CLASS\n", f);
02485         if (Fld () != 0) {
02486             FLD_ITER iter = Make_fld_iter (FLD_HANDLE (Fld ()));
02487             do {
02488                 (*iter).Print (f);
02489             } while (! FLD_last_field (iter++));
02490         } else
02491             fputc ('\n', f);
02492         break;
02493 
02494     case KIND_POINTER:
02495         fputs ("-> ", f);
02496         Print_TY_IDX_verbose (f, Pointed ());
02497         fputc ('\n', f);
02498         break;
02499 
02500     case KIND_FUNCTION:
02501         fprintf (f, "FUNCTION (f: 0x%04x)\n", Pu_flags());
02502         {
02503             TYLIST_IDX idx = Tylist ();
02504             fprintf (f, "\treturns ");
02505             Print_TY_IDX_verbose (f, Tylist_Table[idx]);
02506             if (Tylist_Table[idx] == 0) {
02507                 fputc ('\n', f);
02508                 break;
02509             }
02510             ++idx;
02511             while (Tylist_Table[idx] != 0) {
02512                 fputs ("\n\tparameter ", f);
02513                 Print_TY_IDX_verbose (f, Tylist_Table[idx]);
02514                 ++idx;
02515             }
02516             fputc ('\n', f);
02517         }
02518         break;
02519 
02520     case KIND_VOID:
02521         fputs ("VOID", f);
02522         fputc ('\n', f);
02523         break;
02524 
02525     default:
02526         fprintf (f, "Unknown type (%d)", kind);
02527         fputc ('\n', f);
02528         break;
02529     }
02530 
02531     if (flags & TY_IS_SHARED)
02532         fprintf (f, "%s %d\n", "Block:", block_size);
02533 } // TY::Print
02534 
02535 
02536 void
02537 PU::Print (FILE *f) const
02538 {
02539     Print_TY_IDX_verbose (f, prototype);
02540     fprintf (f, ", flags 0x%016llx,\n"
02541              "\tlexical level %d, LANG 0x%02x, TARGET_INFO %d\n",
02542              flags, lexical_level, src_lang, target_idx); 
02543     if (flags & PU_DECL_VIEW) {
02544         fprintf(f,"Attention!!!: Declaration only (PU_DECL_VIEW)!");
02545         fprintf(f,"\n");
02546     }
02547 
02548 } // PU::Print
02549 
02550 void
02551 BLK::Print (FILE *f) const
02552 {
02553     fprintf (f, "size %lld, align %d, flags 0x%04x, section %d, scninfo %d\n",
02554                 size, align, flags, section_idx, scninfo_idx);
02555 } // BLK::Print
02556 
02557 
02558 void
02559 LABEL::Print (FILE *f) const
02560 {
02561     const char *name_str = name_idx ? &Str_Table[name_idx] : "(anon)";
02562     fprintf (f, "%s: kind = 0x%08x fl = 0x%08x", name_str, kind, flags);
02563 
02564     const char* flgstr = LABEL_FLAGS_To_Str(flags);
02565     fprintf (f, " %s\n", flgstr);
02566 } // LABEL::Print
02567 
02568 
02569 void
02570 PREG::Print (FILE *f) const
02571 {
02572     const char *name_str = name_idx ? &Str_Table[name_idx] : "(anon)";
02573 
02574     fprintf (f, "%s\n", name_str);
02575 } // PREG::Print
02576 
02577 
02578 void
02579 ST_ATTR::Print (FILE* f) const
02580 {
02581     fprintf (f, "0x%x (%s) --> ", st_idx, ST_name (st_idx));
02582     switch (kind) {
02583     case ST_ATTR_UNKNOWN:
02584         fprintf (f, "(NOT USED)\n");
02585         break;
02586     case ST_ATTR_DEDICATED_REGISTER:
02587         fprintf (f, "(DREG) %d\n", u.reg_id);
02588         break;
02589     case ST_ATTR_SECTION_NAME:
02590         fprintf (f, "(SECTION) %s\n", Index_To_Str (u.section_name));
02591         break;
02592     default:
02593         fprintf (f, "(UNKNOWN) 0x%x\n", u.value);
02594         break;
02595     }
02596 }
02597 
02598 void
02599 FILE_INFO::Print (FILE *f) const
02600 {
02601     fprintf (f, "gp_group: %d, flags: 0x%08x", gp_group, flags);
02602     if (flags) {
02603       const char* flgstr = FILE_INFO_FLAGS_To_Str(flags);
02604       fprintf (f, " %s", flgstr);
02605     }
02606 
02607     fputs ("\n", f);
02608 
02609 } // FILE_INFO::Print
02610     
02611 
02612 
02613 // function object used in "For_all"
02614 template <class T>
02615 struct print_op
02616 {
02617     FILE *fid;
02618 
02619     print_op (FILE *f) : fid (f) {}
02620 
02621     void operator () (UINT idx, T *entry) const;
02622 }; // print_op
02623 
02624 
02625 template <class T>
02626 inline void
02627 print_op<T>::operator () (UINT idx, T *entry) const {
02628         fprintf (fid, "[%d]: ", idx);
02629         entry->Print (fid);
02630 }
02631 
02632 
02633 // specialization for printing TCONs
02634 template <>
02635 inline void
02636 print_op<TCON>::operator () (UINT idx, TCON *c) const {
02637     fprintf (fid, "[%d] %s: %s\n", idx, MTYPE_name(TCON_ty(*c)),Targ_Print (NULL, *c));
02638 } // print_op<TCON>::operator ()
02639 
02640 
02641 // Print all local symbol tables corresponding to a PU
02642 void
02643 Print_local_symtab (FILE *f, const SCOPE& scope)
02644 {
02645     // Print the function name
02646 
02647     fprintf (f, "\n%sSYMTAB for %s: level %d, st %d, label %d, preg %d,"
02648              " inito %d, st_attr %d\n%s\n", DBar, ST_name (scope.st),
02649              PU_lexical_level (scope.st), scope.st_tab->Size () - 1,
02650              scope.label_tab->Size () - 1, scope.preg_tab->Size () - 1,
02651              scope.inito_tab->Size () - 1, scope.st_attr_tab->Size () - 1, DBar);
02652 
02653     fputs ("Symbols:\n", f);
02654     For_all_entries (*scope.st_tab, print_op<ST> (f), 1);
02655 
02656     fprintf (f, "%sLabels:\n", DBar);
02657     For_all_entries (*scope.label_tab, print_op<LABEL> (f), 1);
02658     
02659     fprintf (f, "%sPseudo-registers:\n", DBar);
02660     For_all_entries (*scope.preg_tab, print_op<PREG> (f), 1);
02661     
02662     fprintf (f, "%sINITOs:\n", DBar);
02663     For_all_entries (*scope.inito_tab, print_op<INITO> (f), 1);
02664 
02665     fprintf (f, "%sST_ATTRs:\n", DBar);
02666     For_all_entries (*scope.st_attr_tab, print_op<ST_ATTR> (f), 1);
02667 
02668     fprintf (f, "%s\n", DBar);
02669     
02670 } // Print_local_symtab
02671 
02672 
02673 void
02674 Print_global_symtab (FILE *f)
02675 {
02676     fprintf(f,"%sGLOBAL SYMTAB:\n", DBar);
02677 
02678     fprintf (f, "%sFile Info:\n", DBar);
02679     File_info.Print (f);
02680 
02681     fprintf (f, "%sSymbols:\n", DBar);
02682     For_all (St_Table, GLOBAL_SYMTAB, print_op<ST> (f));
02683 
02684     fprintf (f, "%sPUs:\n", DBar);
02685     For_all (Pu_Table, print_op<PU> (f));
02686 
02687     fprintf (f, "%sTypes:\n", DBar);
02688     For_all (Ty_Table, print_op<TY> (f));
02689 
02690     fprintf (f, "%sBlocks:\n", DBar);
02691     For_all (Blk_Table, print_op<BLK> (f));
02692 
02693     fprintf (f, "%sTcons:\n", DBar);
02694     For_all (Tcon_Table, print_op<TCON> (f));
02695 
02696     fprintf (f, "%sINITOs:\n", DBar);
02697     For_all (Inito_Table, GLOBAL_SYMTAB, print_op<INITO> (f));
02698 
02699     fprintf (f, "%sST_ATTRs:\n", DBar);
02700     For_all (St_Attr_Table, GLOBAL_SYMTAB, print_op<ST_ATTR> (f));
02701 
02702     fprintf (f, "%sString table size = %d\n", DBar, STR_Table_Size());
02703     fprintf (f, "%s\n", DBar);
02704 } // Print_global_symtab
02705 
02706 // for ease of debugging, because I don't know how to call Print
02707 // routines from dbx, add simple dump routines.
02708 void
02709 dump_st (ST *st)
02710 {
02711         st->Print(stdout);
02712         switch (st->sym_class) {
02713         case CLASS_BLOCK:
02714                 Blk_Table[st->u2.blk].Print (stdout);
02715                 break;
02716         case CLASS_FUNC:
02717                 Pu_Table[st->u2.pu].Print (stdout);
02718                 break;
02719         }
02720 }
02721 
02722 void
02723 dump_st(ST_IDX st_idx)
02724 {
02725    ST *st = &St_Table[st_idx];
02726    dump_st(st);
02727 }
02728 
02729 // Since dbx cannot handle overloaded functions...
02730 void 
02731 dump_st_idx (ST_IDX st) 
02732 {
02733   dump_st(st);
02734 }
02735 
02736 
02737 void
02738 dump_ty (TY_IDX ty_idx)
02739 {
02740         TY& ty = Ty_Table[ty_idx];
02741         ty.Print(stdout);
02742 }
02743 
02744 // Since dbx cannot handle overloaded function...
02745 void
02746 dump_ty_idx (TY_IDX ty_idx)
02747 {
02748   dump_ty (ty_idx);
02749 }
02750 
02751 void
02752 dump_ty(const TY &ty)
02753 {
02754   ty.Print(stdout);
02755 }
02756 
02757 void 
02758 dump_label (LABEL_IDX idx)
02759 {
02760    Label_Table[idx].Print(stdout);
02761 }
02762 
02763 void 
02764 dump_inito(INITO_IDX idx)
02765 {
02766    Inito_Table[idx].Print(stdout);
02767 }
02768 
02769 void
02770 dump_st_attr (ST_ATTR_IDX idx)
02771 {
02772     St_Attr_Table[idx].Print(stdout);
02773 }
02774 
02775 static ST *
02776 Gen_Temp_Named_Symbol (TY_IDX ty, const char *rootname,
02777                        ST_CLASS sym_class, ST_SCLASS storage_class)
02778 {
02779   static INT Temp_Index = 0;
02780   ST *st = New_ST(CURRENT_SYMTAB);
02781   STR_IDX str_idx = Save_Str2i(rootname, "_temp_", Temp_Index++);
02782   ST_Init(st, str_idx, sym_class, storage_class, EXPORT_LOCAL, ty);
02783   return st;
02784 }
02785 
02786 // Create stack symbol for temp var.
02787 ST *
02788 Gen_Temp_Symbol (TY_IDX      ty,        // type of the desired symbol
02789                  const char *rootname)  // root of the name to use
02790 {
02791   ST *st = Gen_Temp_Named_Symbol(ty, rootname, CLASS_VAR, SCLASS_AUTO);
02792   Set_ST_is_temp_var(st);
02793   return st;
02794 }
02795 
02796 // Create a read-only file-level static symbol of the given type in
02797 // the current symbol table.
02798 ST *
02799 Gen_Read_Only_Symbol(TY_IDX ty, const char *rootname)
02800 {
02801   ST *st = Gen_Temp_Named_Symbol(ty, rootname, CLASS_VAR, SCLASS_FSTATIC);
02802   Set_ST_is_const_var(st);
02803   return st;
02804 }
02805 
02806 //----------------------------------------------------------------------
02807 //----------------------------------------------------------------------
02808 
02809 TY_IDX
02810 Promoted_Parm_Type(const ST *formal_parm)
02811 {
02812   TY_IDX ptype = ST_type(formal_parm);
02813   TY_IDX newtype;
02814   BOOL parm_float;
02815 
02816   if ( ! ST_promote_parm(formal_parm) ) return ptype;
02817 
02818   /* Otherwise, figure out the conversion: */
02819   ptype = ST_type(formal_parm);
02820   parm_float = ST_is_value_parm(formal_parm) &&
02821                 (TY_kind(ptype) == KIND_SCALAR) &&
02822                 (MTYPE_float(TY_mtype(ptype)));
02823   if ( parm_float ) {
02824     /* Must be a promotion from float to double: */
02825     newtype = MTYPE_To_TY(MTYPE_F8);
02826   } else {
02827     /* Must be a promotion to int: */
02828     newtype = MTYPE_To_TY(Integer_type);
02829   }
02830 
02831   /* For sanity, assert that we don't demote: */
02832   Is_True(TY_size(newtype) >= TY_size(ptype),
02833           ("Nonsensical demotion of parameter type"));
02834   return newtype;
02835 }
02836 
02837 //----------------------------------------------------------------------
02838 // Initialization routines
02839 //----------------------------------------------------------------------
02840 
02841 // for fast conversion of predefined types and preg.
02842 ST *MTYPE_TO_PREG_array[MTYPE_LAST+1];
02843 
02844 ST *Int_Preg, *Float_Preg, *Return_Val_Preg;
02845 
02846 TY_IDX MTYPE_TO_TY_array[MTYPE_LAST+1];
02847 
02848 TY_IDX Quad_Type, Void_Type, FE_int_Type, FE_double_Type;
02849 TY_IDX Spill_Int_Type, Spill_Float_Type;
02850 
02851 #if defined(FRONT_END) && !defined(FRONT_END_MFEF77)
02852 extern "C" TYPE_ID FE_int_To_Mtype (void);
02853 #endif
02854 
02855 static INT Max_scope = 8;
02856 
02857 // Set reserve_index_zero to FALSE when reading the symtab from a file
02858 void
02859 New_Scope (SYMTAB_IDX level, MEM_POOL *pool, BOOL reserve_index_zero)
02860 {
02861     if (level >= Max_scope) {
02862         UINT size = Max_scope * sizeof(SCOPE);
02863         Max_scope *= 2;
02864         Scope_tab = (SCOPE *) MEM_POOL_Realloc (Malloc_Mem_Pool, Scope_tab,
02865                                                 size, size * 2);
02866     }
02867 
02868     Current_scope = level;
02869 
02870     ST_TAB *st_tab = CXX_NEW (ST_TAB (pool), pool);
02871     INITO_TAB *inito_tab = CXX_NEW (INITO_TAB (pool), pool);
02872     ST_ATTR_TAB *st_attr_tab = CXX_NEW (ST_ATTR_TAB (pool), pool);
02873     LABEL_TAB *label_tab = NULL;
02874     PREG_TAB *preg_tab = NULL;
02875 
02876     UINT32 dummy_idx;
02877     if (reserve_index_zero) {
02878         st_tab->New_entry ((ST_IDX&) dummy_idx);
02879         inito_tab->New_entry ((INITO_IDX&) dummy_idx);
02880         st_attr_tab->New_entry ((ST_ATTR_IDX&) dummy_idx);
02881     }
02882     
02883     if (level > GLOBAL_SYMTAB) {
02884         label_tab = CXX_NEW (LABEL_TAB (pool), pool);
02885         preg_tab = CXX_NEW (PREG_TAB (pool), pool);
02886 
02887         if (reserve_index_zero) {
02888             label_tab->New_entry ((LABEL_IDX&) dummy_idx);
02889             preg_tab->New_entry ((PREG_IDX&) dummy_idx);
02890         }
02891     
02892     }
02893         
02894 
02895     // Allocate tables for STs, LABELS, PREGs and INITOs
02896     Scope_tab[level].Init (st_tab, label_tab, preg_tab, inito_tab,
02897                            st_attr_tab, pool);
02898 
02899 } // New_Scope
02900 
02901 
02902 void
02903 Delete_Scope (SYMTAB_IDX level)
02904 {
02905     SCOPE& scope = Scope_tab[level];
02906 
02907     CXX_DELETE (scope.st_tab, scope.pool);
02908     CXX_DELETE (scope.label_tab, scope.pool);
02909     CXX_DELETE (scope.preg_tab, scope.pool);
02910     CXX_DELETE (scope.inito_tab, scope.pool);
02911     CXX_DELETE (scope.st_attr_tab, scope.pool);
02912     
02913 } // Delete_Scope
02914 
02915 
02916 static void
02917 Setup_Preg_Pointers ()
02918 {
02919     for (TYPE_ID i = MTYPE_FIRST; i <= MTYPE_LAST; ++i) {
02920         if (MTYPE_To_PREG (i) != NULL || MTYPE_To_TY (i) == 0)
02921             continue;
02922         Is_True (MTYPE_byte_size (i) < 4, ("Invalid mtype"));
02923         MTYPE_To_PREG (i) = MTYPE_signed (i) ? MTYPE_To_PREG (MTYPE_I4) :
02924             MTYPE_To_PREG (MTYPE_U4);
02925     }
02926     
02927     if (ST_type(Int64_Preg) == Spill_Int_Type)
02928         Int_Preg = Int64_Preg;
02929     else
02930         Int_Preg = Int32_Preg;
02931     if (ST_type(Float32_Preg) == Spill_Float_Type)
02932         Float_Preg = Float32_Preg;
02933     else
02934         Float_Preg = Float64_Preg;
02935 } // Setup_Preg_Pointers
02936 
02937 
02938 static void
02939 Create_All_Preg_Symbols ()
02940 {
02941     for (TYPE_ID i = MTYPE_FIRST; i <= MTYPE_LAST; ++i) {
02942         if (MTYPE_To_TY (i) == 0)
02943             continue;
02944         if (MTYPE_To_PREG (i) != NULL)
02945             continue;
02946         if (MTYPE_byte_size(i) < 4) {
02947             // special case:  allow mtype_B
02948             if (i != MTYPE_B) continue;
02949         }
02950 
02951         ST *st = New_ST (GLOBAL_SYMTAB);
02952         ST_Init (st, Save_Str2 (".preg_", MTYPE_name(i)),
02953                  CLASS_PREG, SCLASS_REG, EXPORT_LOCAL, MTYPE_To_TY (i));
02954         MTYPE_To_PREG(i) = st;
02955     }
02956 
02957     if (Return_Val_Preg == NULL) {
02958 
02959         ST *st = New_ST (GLOBAL_SYMTAB);
02960         ST_Init (st, Save_Str (".preg_return_val"),
02961                  CLASS_PREG, SCLASS_REG, EXPORT_LOCAL, 0);
02962         Return_Val_Preg = st;
02963     }
02964 
02965     Setup_Preg_Pointers ();
02966 } // Create_All_Preg_Symbols
02967 
02968 
02969 // for phases other then the front end, we read in the global symtab from
02970 // file, so we don't create the preg sybmols.  But we still need to intialize
02971 // the MTYPE_TO_PREG_array.
02972 static void
02973 Set_up_all_preg_symbols ()
02974 {
02975     UINT32 idx = 1;
02976     
02977     UINT32 last = MIN (MTYPE_LAST + 1, ST_Table_Size (GLOBAL_SYMTAB));
02978 
02979     for (INT i = MTYPE_FIRST; i < last; ++i) {
02980         ST_IDX st_idx = make_ST_IDX (idx++, GLOBAL_SYMTAB);
02981         ST& st = St_Table[st_idx];
02982         if (ST_sym_class (st) != CLASS_PREG)
02983             break;                      // ASSUME all predefined pregs are
02984                                         // placed before all other symbols
02985 
02986         if (Return_Val_Preg == NULL) {
02987             if (strcmp (ST_name (&st), ".preg_return_val") == 0) {
02988                 Return_Val_Preg = &st;
02989                 continue;
02990             }
02991         }
02992 
02993         TY_IDX ty_idx = ST_type (st);
02994         const TY& ty = Ty_Table[ty_idx];
02995         TYPE_ID mtype = TY_mtype (ty);
02996         if (ty_idx != MTYPE_To_TY (mtype))
02997             continue;
02998         MTYPE_To_PREG (mtype) = &st;
02999     }
03000 
03001     // create any missing preg
03002     Create_All_Preg_Symbols ();
03003 
03004 } // Set_up_all_preg_symbols
03005     
03006 /* ====================================================================
03007  *
03008  * Gen_Predef_Type_Name
03009  *
03010  * Just allocate and create a predefined type name
03011  *
03012  * ====================================================================
03013  */
03014 static inline STR_IDX
03015 Gen_predef_type_name (const char *basename)
03016 {
03017     return Save_Str2 (".predef_", basename);
03018 }
03019 
03020 
03021 /* ====================================================================
03022  *
03023  * Create_Special_Global_Symbols
03024  *
03025  * Create special global symbols and types.  These are created before
03026  * the per-file initialization, because they are used for various
03027  * global purposes like initializing the segment descriptors.
03028  *
03029  * This should only be called once per execution.
03030  *
03031  * ====================================================================
03032  */
03033 
03034 static void
03035 Create_Special_Global_Symbols ()
03036 {
03037     TY_IDX ty_idx;
03038     TY_KIND ty_kind = KIND_SCALAR;
03039     
03040     /* Make predefined types for the machine types: */
03041     for (TYPE_ID i = MTYPE_FIRST; i <= MTYPE_LAST; ++i) {
03042 
03043         if (MTYPE_To_TY (i) != 0)
03044             continue;
03045 
03046         TY &ty = New_TY (ty_idx);
03047 
03048         ty_kind = KIND_SCALAR;
03049         if (MTYPE_align_req (i))
03050             Set_TY_align (ty_idx, MTYPE_align_req(i));
03051 
03052         /* If this is one of the basic spill types, remember it: */
03053         if ( i == Spill_Int_Mtype )     {
03054             Spill_Int_Type = ty_idx;
03055         } else if ( i == Spill_Float_Mtype ) {
03056             Spill_Float_Type = ty_idx;
03057         }
03058         if ( i == MTYPE_FQ )
03059             Quad_Type = ty_idx;
03060 
03061 #if defined(FRONT_END_C) || defined(FRONT_END_CPLUSPLUS)
03062 #ifndef FRONT_END_MFEF77
03063         if ( i == FE_int_To_Mtype() )
03064             FE_int_Type = ty_idx;
03065 #endif /* FRONT_END_MFEF77 */
03066         if ( i == MTYPE_F8 )
03067             FE_double_Type = ty_idx;
03068 #endif /* FRONT_END_C || FRONT_END_CPLUSPLUS */
03069         if ( i == MTYPE_V ) {
03070             Void_Type = ty_idx;
03071             ty_kind = KIND_VOID;
03072         }
03073 
03074         if (i == MTYPE_A4 || i == MTYPE_A8) {
03075             if (MTYPE_byte_size (i) != Pointer_Size) {
03076                 Ty_tab.Delete_last ();
03077                 MTYPE_To_TY (i) = 0;
03078                 continue;
03079             }
03080 
03081             ty_kind = KIND_POINTER;
03082             TY_Init (ty, MTYPE_byte_size (i), ty_kind, i,
03083                      Gen_predef_type_name (MTYPE_name (i)));
03084             Is_True (i > MTYPE_V,
03085                      ("Create_Special_Global_Symbols() assumes MTYPE_V < "
03086                       "MTYPE_A4 and MTYPE_A8"));
03087             Set_TY_pointed (ty, MTYPE_To_TY (MTYPE_V));
03088             MTYPE_To_TY (i) = ty_idx;
03089             continue;
03090         }
03091 
03092         TY_Init (ty, MTYPE_byte_size (i), ty_kind, i,
03093                  Gen_predef_type_name (MTYPE_name (i)));
03094         MTYPE_To_TY (i) = ty_idx;
03095     }
03096 
03097 } // Create_Special_Global_Symbols
03098 
03099 
03100 static inline BOOL
03101 Predefined_Void_Type (TY_IDX ty_idx)
03102 {
03103     const TY& ty = Ty_Table[ty_idx];
03104     return (ty_idx == make_TY_IDX (TY_IDX_index (ty_idx)) &&
03105             TY_mtype (ty) == MTYPE_V && TY_kind (ty) == KIND_VOID);
03106     
03107 } // Predefined_Void_Type
03108 
03109 
03110 // In phases other then the frontends, we read in the global symtab from the
03111 // file, and that includes all the predefined global symbols and types.  We
03112 // don't need to create them again, but we still need to initialize the
03113 // MTYPE_TO_TY array.
03114 void
03115 Initialize_Special_Global_Symbols ()
03116 {
03117     // ASSUME all mtype TYs, if defined, are placed before any other TY's
03118 
03119     UINT32 last = MIN (MTYPE_LAST + 1, TY_Table_Size());
03120     // for trivial program, the type table may have less entry than MTYPE_LAST
03121 
03122     for (UINT32 i = MTYPE_FIRST; i < last; ++i) {
03123         TY_IDX ty_idx = make_TY_IDX (i);
03124         const TY& ty = Ty_Table[ty_idx];
03125 
03126         TYPE_ID mtype = TY_mtype (ty);
03127         if (MTYPE_byte_size (mtype) != TY_size (ty) ||
03128             TY_flags (ty) != 0)
03129             continue;
03130         switch (mtype) {
03131         case MTYPE_V:
03132             if (TY_kind (ty) != KIND_VOID)
03133                 continue;
03134             break;
03135 
03136         case MTYPE_A4:
03137         case MTYPE_A8:
03138             if (TY_kind (ty) != KIND_POINTER || 
03139                 ! Predefined_Void_Type (TY_pointed (ty)))
03140                 continue;
03141             break;
03142 
03143         default:
03144             if (TY_kind (ty) != KIND_SCALAR)
03145                 continue;
03146             break;
03147         }
03148         if (MTYPE_align_req (mtype))
03149             Set_TY_align (ty_idx, MTYPE_align_req (mtype));
03150         MTYPE_To_TY (mtype) = ty_idx;
03151     }
03152         
03153     // create any missing predefined types
03154     Create_Special_Global_Symbols ();
03155             
03156     Spill_Int_Type = MTYPE_To_TY (Spill_Int_Mtype);
03157     Spill_Float_Type = MTYPE_To_TY (Spill_Float_Mtype);
03158     Quad_Type = MTYPE_To_TY (MTYPE_FQ);
03159     Void_Type = MTYPE_To_TY (MTYPE_V);
03160 
03161     Set_up_all_preg_symbols ();
03162 
03163 } // Initialize_Special_Global_Symbols
03164 
03165 
03166 // Initialize all symbol tables.  This function must be called before any
03167 // symbol table operation is performed.
03168 // If reading the symtab from a file, then reserve_index_zero should be FALSE
03169 void
03170 Initialize_Symbol_Tables (BOOL reserve_index_zero)
03171 {
03172     if (Scope_tab != NULL)
03173         return;
03174     
03175     Scope_tab = (SCOPE *) MEM_POOL_Alloc (Malloc_Mem_Pool,
03176                                           Max_scope * sizeof(SCOPE));
03177     memset(Scope_tab, '\0', Max_scope * sizeof(SCOPE));
03178 
03179     memset (MTYPE_TO_PREG_array, '\0', sizeof(ST*) * (MTYPE_LAST + 1));
03180     memset (MTYPE_TO_TY_array, '\0', sizeof(TY_IDX) * (MTYPE_LAST + 1));
03181 
03182     if (reserve_index_zero) {
03183         // For producer, we reserve first entry for all global tables
03184 
03185         Initialize_Strtab (0x1000);     // start with 4Kbytes for strtab.
03186 
03187         UINT dummy_idx;
03188         memset (&New_PU ((PU_IDX&) dummy_idx), '\0', sizeof(PU));
03189         memset (&New_TY ((TY_IDX&) dummy_idx), '\0', sizeof(TY));
03190         memset (New_FLD ().Entry(), '\0', sizeof(FLD));
03191         memset (&New_TYLIST ((TYLIST_IDX&) dummy_idx), '\0', sizeof(TYLIST));
03192         memset (New_ARB ().Entry(), '\0', sizeof(ARB));
03193         memset (&New_BLK ((BLK_IDX&) dummy_idx), '\0', sizeof(BLK));
03194         memset (&Initv_Table.New_entry ((INITV_IDX&) dummy_idx), '\0', 
03195                 sizeof(INITV));
03196         Init_Constab ();
03197         New_Scope (GLOBAL_SYMTAB, Malloc_Mem_Pool, TRUE);
03198         
03199         Create_Special_Global_Symbols ();
03200         Create_All_Preg_Symbols();
03201     }
03202 #ifdef BACK_END
03203     if (!Read_Global_Data) {
03204        // reserve zero index in BLK table
03205        UINT blk_idx;
03206        memset (&New_BLK ((BLK_IDX&) blk_idx), '\0', sizeof(BLK));
03207     }
03208 #endif
03209 }
03210 
03211 //----------------------------------------------------------------------
03212 // TCON
03213 //----------------------------------------------------------------------
03214 TCON_IDX
03215 Enter_tcon (const TCON& tcon)
03216 {
03217     switch (TCON_ty (tcon)) {
03218     case MTYPE_F4:
03219         if (TCON_ival (tcon) == 0)
03220             return 1;
03221     case MTYPE_F8:
03222         if (TCON_k0 (tcon) == 0)
03223             return 2;
03224     default:
03225         return Tcon_Table.Insert (tcon);
03226     }
03227 } // Enter_tcon
03228 
03229 
03230 void
03231 Init_Constab ()
03232 {
03233     if (Tcon_Table.Size () == 0) {
03234         TCON Zero;
03235         UINT32 idx;
03236         memset (&Zero, '\0', sizeof(TCON));
03237         idx = Tcon_Table.Insert (Zero); // index 0: dummy
03238         Set_TCON_ty (Zero, MTYPE_F4); 
03239         idx = Tcon_Table.Insert (Zero); // index 1: float (0.0)
03240         Set_TCON_ty (Zero, MTYPE_F8); 
03241         idx = Tcon_Table.Insert (Zero); // index 2: double (0.0)
03242 
03243         Is_True (idx == MAX_PREDEFINED_TCON_IDX,
03244                  ("Number of predefined tcons incorrect"));
03245 
03246         Initialize_TCON_strtab (1024);  // string table for TCONs
03247     }
03248 }
03249 
03250 
03251 #ifdef Is_True_On
03252 
03253 //
03254 // Additional debugging functions because Workshop can't deal with 
03255 // the [] operator correctly.
03256 //
03257 
03258 ST ST_from_IDX(ST_IDX x) {return St_Table[x];}
03259 TY TY_from_IDX(TY_IDX x) {return Ty_Table[x];}
03260 INITO INITO_from_IDX(INITO_IDX x) {return Inito_Table[x];}
03261 INITV INITV_from_IDX(INITV_IDX x) {return Initv_Table[x];}
03262 PU PU_from_IDX(PU_IDX x) {return Pu_Table[x];}
03263 ARB ARB_from_IDX(ARB_IDX x) {return Arb_Table[x];}
03264 TCON TCON_from_IDX(TCON_IDX x) {return Tcon_Table[x];}
03265 FLD FLD_from_IDX(FLD_IDX x) {return Fld_Table[x];}
03266 LABEL LABEL_from_IDX(LABEL_IDX x) {return Label_Table[x];}
03267 TYLIST TYLIST_from_IDX(TYLIST_IDX x) {return Tylist_Table[x];}
03268 
03269 #endif // Is_True_On
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines