Polaris: Symtab.cc Source File

Symtab.cc

Go to the documentation of this file.
00001 ///
00002 /// TO DO:  On the operator= classes, in setting, for instance, the
00003 /// _equivalence field to be equal, should also add that variable
00004 /// to the Equivalence\'s member list.  Same applies to
00005 /// the methods that set equivalence, and all similar items.
00006 /// others to do:
00007 /// common
00008 ///
00009 /// Don\'t forget to delete pointers before reassigning them in all
00010 /// reassigning methods
00011 ///
00012 /// In the operator = functions, make sure that you\'re using clone()
00013 /// for all pointers that need to be copied, such as Expression *\'s
00014 ///
00015 /// destructors for all objects
00016 ///
00017 #ifdef POLARIS_GNU_PRAGMAS
00018 #pragma implementation
00019 #endif
00020 ///
00021 #include <ctype.h>
00022 #include <stdlib.h>
00023 #include <strstream.h>
00024 
00025 #include "BinRep.h"
00026 #include "Boolean.h"
00027 #include "Collection/KeyIterator.h"
00028 #include "Collection/Map.h"
00029 #include "Declaration.h"
00030 #include "Expression/Expression.h"
00031 #include "Expression/IntrinsicTable.h"
00032 #include "IntElem.h"
00033 #include "String.h"
00034 #include "Symtab.h"
00035 #include "Symbol/FunctionSymbol.h"
00036 #include "Symbol/VariableSymbol.h"
00037 #include "VDL.h"
00038 #include "debug.h"
00039 #include "utilities/intrinsic_util.h"
00040 #include "utilities/string_util.h"
00041 #include "utilities/switches_util.h"
00042 #include "utilities/symbol_util.h"
00043 #include "Directive/Directive.h"
00044 
00045 #include "macros.h"
00046 #include "p-assert.h"
00047 
00048 template void relink_all_dptrs(Dictionary<Symbol> &,
00049                                ProgramUnit &);
00050 
00051 ostream & 
00052 operator << (ostream & o, const Symtab & symtab) 
00053 {
00054     o << "{\n";
00055 
00056     DictionaryIter<Symbol> iter = (Dictionary<Symbol>&) symtab._dict;
00057 
00058     while (iter.valid()) {
00059         cout << iter.current() << "\n";
00060         ++iter;
00061     }
00062 
00063     o << "}\n";
00064 
00065     return o;
00066 }
00067 
00068 Symtab::Symtab(const BinRep & binstr)
00069 {
00070     #ifdef CLASS_INSTANCE_REGISTRY
00071     register_instance(SYMTAB, sizeof(Symtab), this);
00072     #endif
00073 
00074     for (Iterator<BinRep> iter = binstr.to_set(); iter.valid(); ++iter) {
00075         String          symbol_name;
00076 
00077         iter.current()[0].to_string(symbol_name);
00078 
00079         if (dbx_symtab_debug_level >= 1) 
00080             cout << "Symtab: Initializing " << symbol_name << "\n";
00081 
00082         const BinRep &bs  = iter.current()[1];
00083         Symbol       *sym = make_symbol(symbol_name, bs );
00084 
00085         _dict.ins(sym);
00086     }
00087 }
00088 
00089 Symtab::Symtab(const Symtab &s) 
00090 {
00091     #ifdef CLASS_INSTANCE_REGISTRY
00092     register_instance(SYMTAB, sizeof(Symtab), this);
00093     #endif
00094 
00095         Symtab::operator = (s);
00096 }
00097 
00098 Symtab::~Symtab()
00099 {
00100     #ifdef CLASS_INSTANCE_REGISTRY
00101     unregister_instance(SYMTAB, this);
00102     #endif
00103 }
00104 
00105 Symtab &
00106 Symtab::operator = (const Symtab &s) 
00107 {
00108     _dict.clear();
00109 
00110         for (DictionaryIter<Symbol> iter = s._dict; iter.valid(); ++iter)
00111                 _dict.ins( iter.current().clone_all() );
00112 
00113     return (*this);
00114 }
00115 
00116 Symtab *
00117 Symtab::clone() const
00118 {
00119     return new Symtab( *this );
00120 }
00121 
00122 void 
00123 Symtab::fill_in(const BinRep & binstr, ExprTable & exprs,
00124                 const Dictionary<VoidPtrDef> & stmts,
00125                 const Dictionary<VoidPtrDef> & commons,
00126                 const Dictionary<VoidPtrDef> & equivalences)
00127 {
00128     for (Iterator<BinRep> iter = binstr.to_set(); iter.valid(); ++iter) {
00129         /// ...  The name of the symbol is (String)iter.current()[0] and the binstr 
00130         /// ...  data for the symbol's info is iter.current()[1]
00131 
00132         String          symbol_name;
00133 
00134         iter.current()[0].to_string(symbol_name);
00135 
00136         if (dbx_symtab_debug_level >= 2) 
00137             cout << "Symtab: Filling in " << symbol_name << "\n";
00138 
00139         /// ...  Fill in the data for that symbol
00140 
00141         _dict[symbol_name].fill_in( iter.current()[1],
00142                                     exprs, stmts, commons, equivalences);
00143 
00144         if (dbx_symtab_debug_level >= 3) 
00145             cout << "..." << _dict[symbol_name] << "\n";
00146     }
00147 }
00148 
00149 
00150 
00151 typedef Map<Symbol,IntElem> TopSortMap;
00152 
00153 static int
00154 top_sort_expressions( TopSortMap &map, Expression &e )
00155 {
00156     if (e.op() == ID_OP) 
00157         return (map.find_ref(e.symbol()) != 0 ? 1 : 0);
00158 
00159     int count = 0;
00160 
00161     for (Iterator<Expression> iter = e.arg_list(); iter.valid(); ++iter)
00162         count += top_sort_expressions( map, iter.current() );
00163 
00164     return count;
00165 }
00166 
00167 static void 
00168 top_sort_parameters( TopSortMap &map )
00169 {
00170     for (KeyIterator<Symbol,IntElem> iter = map; iter.valid(); ++iter) {
00171         iter.current_data().value( 
00172             top_sort_expressions( map, *iter.current_key().expr_ref() ));
00173     }
00174 }
00175 
00176 //_ compare strings ignoring their cases
00177 static int
00178 str_case_compare( const char* str1, const char* str2 )
00179 {
00180     int len = strlen(str2);
00181     if (strlen(str1) != len) return 1;
00182     else {
00183         char cbuf1[len+1];
00184         for (int i = 0; i <= len; str1++)
00185             cbuf1[i++] = (islower(*str1) ? toupper(*str1) : *str1);
00186         return strcmp(cbuf1, str2);
00187     }
00188 }
00189 
00190 
00191 
00192 void 
00193 Symtab::write(ostream & o, 
00194               int space_for_label GIV(0),
00195               int max_line_len    GIV(FORTRAN_MAX_LINE_LEN)) const
00196 {
00197     /// ...  We need a dictionary of declarations.  Each element of this dictionary
00198     /// ...  is tagged by a type name, such as INTEGER*4, and represents a
00199     /// ...  declaration line of FORTRAN declaring all variables of that type.
00200     /// ...  Thus, we move through the symtab one symbol at a time, and as we
00201     /// ...  find symbols with different type names, we add a new declaration line,
00202     /// ...  otherwise we just add their name to the one currently in the dictionary.
00203     /// ...  Thus, by the time we have traversed the entire symbol table, we have all
00204     /// ...  the Declarations that we need in the dictionary.
00205 
00206     TopSortMap              param_map;
00207     Dictionary<Declaration> decl_dict; 
00208 
00209     DirectiveType output_language = (DirectiveType) switch_value("output_lang");
00210     
00211     /// ...  In addition, we also need a few other declarations types:
00212 
00213     Declaration saved_decl("SAVE", " ", "",space_for_label, max_line_len);
00214     Declaration intr_decl("INTRINSIC", " ", "",space_for_label, max_line_len);
00215     Declaration extern_decl("EXTERNAL", " ", "",space_for_label, max_line_len);
00216     Declaration dim_decl("DIMENSION", " ", "",space_for_label, max_line_len);
00217     Declaration param_decl("PARAMETER", " (",")",space_for_label, max_line_len);
00218     Declaration global_decl("GLOBAL", " ", "",space_for_label, max_line_len);
00219     Declaration pointer_decl("POINTER", " ","",space_for_label, max_line_len);
00220     Declaration allocatable_decl("ALLOCATABLE", " ","",space_for_label, max_line_len);
00221 
00222     for (const String *id = _dict.first_ref();
00223          id; id = _dict.successor_ref(*id)) {
00224         const Symbol &sym = *_dict.find_ref( *id );
00225         SYMBOL_CLASS    sym_class = sym.sym_class();
00226 
00227         if (output_language == DT_CEDAR_FORTRAN) {
00228             
00229             /// ...  Check for global variables
00230 
00231             if (sym_class == VARIABLE_CLASS && sym.global())
00232                 global_decl << convert_case(sym.name_ref());
00233         }
00234 
00235         if ((output_language == DT_CRAY_T3D) ||   /// ... _
00236             (output_language == DT_SGI) ||
00237             (output_language == DT_CONVEX_SPP) || /// ... >
00238             (output_language == DT_SGI_POWER) ||
00239             (output_language == DT_KAP_SGI)) {
00240 
00241             /// ...  Check for POINTER variables
00242 
00243             if (sym_class == VARIABLE_CLASS && sym.is_pointer()) {
00244                 ostrstream      str;
00245 
00246                 str << "(" << convert_case(sym.name_ref()) << ",";
00247                 str << convert_case(sym.assoc_variable().name_ref()) << ")";
00248                 str << '\000';
00249 
00250                 char *data = str.str();
00251                 pointer_decl << data;
00252                 delete [] data;
00253             }
00254         }
00255                 
00256         if ((output_language == DT_CONVEX) ||
00257             (output_language == DT_CONVEX_SPP)) {  /// ... >
00258 
00259             /// ...  Get all allocatable variables
00260 
00261             if (sym_class == VARIABLE_CLASS && sym.allocatable()) {
00262                 allocatable_decl << convert_case(sym.name_ref());
00263             }
00264         }
00265                 
00266         /// ...  Check for saved variables
00267 
00268         if (sym_class == VARIABLE_CLASS && sym.saved())
00269             saved_decl << convert_case(sym.name_ref());
00270 
00271         // Check for intrinsic/external subroutines/functions
00272 
00273         if (sym_class == SUBROUTINE_CLASS || sym_class == FUNCTION_CLASS) {
00274             if (sym.intrinsic())
00275                 /// ...  For intrinsics, make sure we use the proper name for the machine
00276                 intr_decl << convert_case(translate_special_name(sym.name_ref()));
00277 
00278             if (sym.external()) {
00279                 if ((output_language == DT_SGI) ||
00280                     (output_language == DT_SGI_POWER) ||
00281                     (output_language == DT_KAP_SGI)) {
00282                     if ((strcmp(upcase_ch(sym.name_ref()),"MALLOC") != 0) &&
00283                         (strcmp(upcase_ch(sym.name_ref()),"FREE") != 0)) {
00284                         extern_decl << convert_case(sym.name_ref());
00285                     }
00286                 } else if (output_language == DT_CONVEX_SPP ){                     /// ... >
00287           if ((strcmp(upcase_ch(sym.name_ref()),"SPPALLOC") != 0) && /// ... >
00288               (strcmp(upcase_ch(sym.name_ref()),"SPPFREE") != 0)) {  /// ... >
00289                extern_decl << convert_case(sym.name_ref());          /// ... >
00290           }                                                          /// ... >
00291                 } else {
00292                     extern_decl << convert_case(sym.name_ref());
00293         }
00294             }
00295         }
00296         
00297         // Check for variables/functions/symbolic constants to be included
00298         /// ...  in a type statement
00299 
00300         if (sym_class == VARIABLE_CLASS || sym_class == SYMBOLIC_CONSTANT_CLASS
00301             || (sym_class == FUNCTION_CLASS && sym.intrinsic() == False)) {
00302 
00303             if (output_language != DT_CRAY_T3D ||                        /// ... _
00304                 (str_case_compare(sym.name_ref(), _T3D_NUM_PES) &&       /// ... _
00305                  (sym_class != VARIABLE_CLASS || !sym.is_pointer()))) {  /// ... _
00306 
00307                 String          type_name_str;
00308 
00309                 sym.type().format(type_name_str);
00310 
00311                 Declaration    *decl = decl_dict.find_ref(type_name_str);
00312 
00313                 if (!decl) {
00314                     /// ...  This type was not already in the dictionary -- insert a
00315                     /// ...  new Declaration for it.
00316 
00317                     decl = new Declaration(type_name_str, " ", "",
00318                                            space_for_label, max_line_len);
00319                     decl_dict.ins(decl);
00320                 }
00321 
00322                 *decl << convert_case(sym.name_ref());
00323             }                                                    /// ... _
00324         }
00325 
00326         /// ...  Look for variable arrays for a DIMENSION statement
00327 
00328         if (sym_class == VARIABLE_CLASS && sym.is_array()) {
00329             ostrstream      str;
00330 
00331             str << convert_case(sym.name_ref());
00332 
00333             if (sym.allocatable()) {
00334                 switch (output_language) {
00335                 case DT_CEDAR_FORTRAN:
00336                 case DT_CONVEX:
00337                 case DT_CONVEX_SPP:   /// ... >
00338                     sym.dim().print_all_colons(str);
00339                     break;
00340                 default:
00341                     sym.dim().print(str);
00342                     break;
00343                 }
00344             }
00345             else {
00346                 sym.dim().print(str);
00347             }
00348             str << '\000';
00349             
00350             char *data = str.str();
00351             dim_decl << data;
00352             delete [] data;
00353         }
00354 
00355         /// ...  Look for symbolic constants and create PARAMETER stmts
00356 
00357         if (sym_class == SYMBOLIC_CONSTANT_CLASS)
00358             if (output_language != DT_CRAY_T3D ||                /// ... _
00359                 str_case_compare(sym.name_ref(), _T3D_NUM_PES))  /// ... _
00360                 param_map.ins(sym, new IntElem(0));
00361     }
00362 
00363     /// ...  Now output all of the declarations that we have created
00364 
00365     o << saved_decl.str_ref();
00366     o << intr_decl.str_ref();
00367     o << extern_decl.str_ref();
00368 
00369     if (output_language == DT_CEDAR_FORTRAN) {
00370         /// ...  Print the GLOBAL declarations
00371         o << global_decl.str_ref();
00372     }
00373     
00374     if ((output_language == DT_CONVEX) ||
00375         (output_language == DT_CONVEX_SPP)) {  /// ... >
00376     /// ...  Print the ALLOCATABLE declarations
00377     o << allocatable_decl.str_ref();
00378     }
00379 
00380     for (const String *id1 = decl_dict.first_ref(); id1;
00381      id1 = decl_dict.successor_ref(*id1)) {
00382         Declaration *dec = decl_dict.find_ref( *id1 );
00383         o << dec->str_ref();
00384     }
00385 
00386     if ((output_language == DT_CRAY_T3D) ||   /// ... _
00387     (output_language == DT_SGI) ||
00388     (output_language == DT_SGI_POWER) ||
00389         (output_language == DT_CONVEX_SPP) ||  /// ... >
00390     (output_language == DT_KAP_SGI)) {
00391     /// ...  Print the POINTER declarations
00392     o << pointer_decl.str_ref();
00393     }
00394 
00395     while (param_map.entries() > 0) {
00396         Boolean     infinite_loop = True;
00397 
00398         top_sort_parameters( param_map );
00399 
00400         for (KeyIterator<Symbol,IntElem> p_iter = param_map;
00401                                          p_iter.valid(); ++p_iter) {
00402             if (p_iter.current_data().value() == 0 ) {
00403                 Symbol     &sym = p_iter.current_key();
00404                 ostrstream  str;
00405 
00406                 str << convert_case(sym.name_ref()) << "=";
00407                 str << *sym.expr_ref();
00408                 str << '\000';
00409 
00410                 char *data = str.str();
00411                 param_decl << data;
00412                 delete [] data;
00413 
00414                 param_map.del( p_iter.current_key() );
00415                 infinite_loop = False;
00416             }
00417         }
00418 
00419         if (infinite_loop) {
00420             p_assert( False, "Symtab::write: parameters in a cycle" );
00421             break;
00422         }
00423     }
00424 
00425     o << param_decl.str_ref();
00426     o << dim_decl.str_ref();
00427 }
00428 
00429 Symtab::Symtab()
00430 {
00431     #ifdef CLASS_INSTANCE_REGISTRY
00432     register_instance(SYMTAB, sizeof(Symtab), this);
00433     #endif
00434 }
00435 
00436 Symbol &
00437 Symtab::ins(Symbol * new_symbol)
00438 {
00439     p_assert(new_symbol != 0, "Symtab::ins(): symbol parameter is NULL");
00440 
00441     _dict.ins(new_symbol, 0 /* error if already exists */ );
00442     return *new_symbol;
00443 }
00444 
00445 const Symbol   *
00446 Symtab::find_ref(const char *symbol_name) const
00447 {
00448     /// ...  creating a symbol with a lower case string will result in an upper case
00449     /// ...  symbol name.  searching for that symbol with the same string will
00450     /// ...  not find it.  Petersen said that all symbols should be upper case,
00451     /// ...  so this check makes sure upper case strings are being used
00452     /// ...  30 September 1994, Thomas R. Lawrence
00453     int i = 0;
00454     while (symbol_name[i] != 0) {
00455         p_assert(!islower(symbol_name[i]),
00456                  "Symtab::find_ref:  symbols must be upper case");
00457         i += 1;
00458     }
00459 
00460     return _dict.find_ref(symbol_name);
00461 }
00462 
00463 Symbol         *
00464 Symtab::find_ref(const char *symbol_name)
00465 {
00466     /// ...  creating a symbol with a lower case string will result in an upper case
00467     /// ...  symbol name.  searching for that symbol with the same string will
00468     /// ...  not find it.  Petersen said that all symbols should be upper case,
00469     /// ...  so this check makes sure upper case strings are being used
00470     /// ...  30 September 1994, Thomas R. Lawrence
00471     int i = 0;
00472     while (symbol_name[i] != 0) {
00473         /// ...  p_assert(!islower(symbol_name[i]),
00474         /// ...           "Symtab::find_ref:  symbols must be upper case");
00475     if (islower(symbol_name[i]))
00476             p_abort( "Symtab::find_ref:  symbols must be upper case" );
00477         i += 1;
00478     }
00479 
00480     return _dict.find_ref(symbol_name);
00481 }
00482 
00483 const Symbol & 
00484 Symtab::operator[] (const char *symbol_name) const
00485 {
00486     const Symbol   *sym = _dict.find_ref(symbol_name);
00487 
00488     if (!sym) {
00489         cerr << "Error: Symtab: operator [ ]: Could not find symbol \""
00490              << symbol_name << "\" in symbol table.\n";
00491         p_assert(False, "ABORT");
00492     }
00493 
00494     return *sym;
00495 }
00496 
00497 Symbol & 
00498 Symtab::operator[] (const char *symbol_name)
00499 {
00500     Symbol         *sym = _dict.find_ref(symbol_name);
00501 
00502     if (!sym) {
00503         cerr << "Error: Symtab: operator [ ]: Could not find symbol \""
00504              << symbol_name << "\" in symbol table.\n";
00505         p_assert(False, "ABORT");
00506     }
00507 
00508     return *sym;
00509 }
00510 
00511 void 
00512 Symtab::del(const char *tag)
00513 {
00514     _dict.del(tag);
00515 }
00516 
00517 int 
00518 Symtab::entries() const
00519 {
00520     return _dict.entries();
00521 }
00522 
00523 Symbol         *
00524 Symtab::grab(const char *symbol_name)
00525 {
00526     return _dict.grab(symbol_name);
00527 }
00528 
00529 
00530 void 
00531 Symtab::absorb(Symtab & other)
00532 {
00533     while (other._dict.entries()>0) 
00534         rename_and_ins(other._dict.grab_arb());
00535 }
00536 
00537 
00538 Symbol &
00539 Symtab::rename_and_ins(Symbol * sym)
00540 {
00541     p_assert(sym != 0, "Symtab::rename_and_ins(): symbol parameter was NULL");
00542 
00543     Symbol *already_exists = find_ref(sym->_tag);
00544 
00545     if (((sym->sym_class() == FUNCTION_CLASS) ||
00546          (sym->sym_class() == SUBROUTINE_CLASS)) && 
00547         (sym->intrinsic() == IS_INTRINSIC)) {
00548         if (! already_exists)
00549             return ins(sym);
00550         return *already_exists;
00551     }
00552 
00553     if (!already_exists && (lookup_intrinsic(sym->_tag) == False)) {
00554         /// ...  No naming conflicts -- just insert
00555         return ins(sym);
00556     }
00557     else {
00558         /// ...  Successively try new renamings until no conflict is found
00559 
00560         if (!already_exists)
00561             already_exists = sym;
00562 
00563     String tag(sym->_tag);
00564         do {
00565             already_exists->renaming_suggestion(tag);
00566         } while (find_ref(tag) || (lookup_intrinsic(tag) == True));
00567     sym->_tag = tag;
00568 
00569         /// ...  Now sym has been safely renamed.  Insert.
00570 
00571         return ins(sym);
00572     }
00573 }
00574 
00575 int 
00576 Symtab::structures_OK() const
00577 {
00578     if (!_dict.structures_OK()) {
00579         cerr << "In context of Symtab:\n" << flush;
00580         write(cout);
00581         return 0;
00582     }
00583 
00584     return 1;
00585 }
00586 
00587 DictionaryIter<Symbol>
00588 Symtab::iterator() const
00589 {
00590     return DictionaryIter<Symbol> (CASTAWAY(Dictionary<Symbol> &) _dict);
00591 }
00592  
00593 Symbol &        
00594 Symtab::ins_intrinsic(const char *name)
00595 {
00596     Symbol *s = find_ref( name );
00597 
00598     if (s == 0) {
00599         String          intrin = name;
00600         IntrinsicTable  tab;
00601 
00602         int index = tab.lookup_intrinsic( intrin );
00603         p_assert( index >= 0, "not an intrinsic function" );
00604 
00605         s = new FunctionSymbol( intrin, tab.return_type(index), 
00606                                 NOT_EXTERNAL, IS_INTRINSIC, NOT_FORMAL );
00607         this->ins( s );
00608     }
00609 
00610     p_assert( s && s->intrinsic() == IS_INTRINSIC, "not an intrinsic" );
00611 
00612     return *s;
00613 }
00614 
00615 /// Change the pointers within a Symtab element to
00616 /// point within the given ProgramUnit.
00617 
00618 void 
00619 Symtab::relink_ptrs( ProgramUnit &p)
00620 {
00621     relink_all_dptrs( _dict, p );
00622 
00623 }
00624 
00625 void
00626 Symtab::exchange_convert( VDL &vdl )
00627 {
00628     BinRep  *b = CASTAWAY(BinRep *) vdl.data_ref();
00629 
00630     if (b != 0) {
00631         List<BinRep> *L  = new List<BinRep>;
00632         BinRep       *bs;
00633 
00634         bs = new BinRep( "symtab" );
00635         L->ins_last( bs );
00636 
00637         bs = new BinRep( new Set<BinRep> );
00638         L->ins_last( bs );
00639 
00640         BinRep *br = new BinRep( L );
00641         b->to_set().ins( br );
00642 
00643         for (DictionaryIter<Symbol> iter = iterator(); iter.valid(); ++iter)
00644             iter.current().exchange_convert( vdl );
00645     }
00646 }
 © 1995-2005 University of Illinois, Urbana-Champaign. All rights reserved.  Fri Mar 25 23:06:15 2005