Polaris: ProgramUnit.cc Source File

ProgramUnit.cc

Go to the documentation of this file.
00001 ///
00002 /// \file ProgramUnit.cc
00003 ///
00004 #include "define.h"
00005 
00006 #ifdef POLARIS_GNU_PRAGMAS
00007 #pragma implementation
00008 #endif
00009 
00010 #include <stdio.h>
00011 #include <time.h>
00012 #include <sys/time.h>
00013 
00014 #include "ProgramUnit.h"
00015 #include "Relinkable.h"
00016 #include "TranslateObject.h"
00017 
00018 #include "BinRep.h"
00019 #include "Collection/Iterator.h"
00020 #include "Collection/KeyIterator.h"
00021 #include "Collection/RefMap.h"
00022 #include "DDgraph.h"
00023 #include "ExprTable.h"
00024 #include "Statement/EntryStmt.h"
00025 #include "Symbol/ProgramSymbol.h"
00026 #include "version.h"
00027 #include "utilities/switches_util.h"
00028 #include "utilities/symbol_util.h"
00029 #include "wide_output.h"
00030 
00031 #include <set>
00032 
00033 template class RefList<ProgramUnit>;
00034 template class RefSet<ProgramUnit>;
00035 template class List<RefList<ProgramUnit> >;
00036 template class Iterator<ProgramUnit>;
00037 template class Iterator<RefList<ProgramUnit> >;
00038 template class Map<ProgramUnit,List<Expression> >; 
00039 template class Map<ProgramUnit,RefList<Symbol> >; 
00040 template class RefMap<ProgramUnit,ProgramUnit>; 
00041 template class RefMap<ProgramUnit,Symbol>; 
00042 template class Assign<RefList<ProgramUnit> >; 
00043 template class TypedCollection<RefList<ProgramUnit> >; 
00044 template class TypedBaseMap<ProgramUnit,List<Expression> >; 
00045 template class TypedBaseMap<ProgramUnit,List<Symbol> >; 
00046 template class TypedBaseMap<ProgramUnit,RefList<Symbol> >; 
00047 template class TypedBaseRefMap<ProgramUnit,ProgramUnit>; 
00048 template class TypedBaseRefMap<ProgramUnit,Symbol>; 
00049 template class ProtoMap<ProgramUnit,List<Expression> >; 
00050 template class ProtoMap<ProgramUnit,RefList<Symbol> >; 
00051 template class ProtoRefMap<ProgramUnit,ProgramUnit>; 
00052 template class ProtoRefMap<ProgramUnit,Symbol>; 
00053 template class KeyIterator<ProgramUnit,List<Expression> >; 
00054 template class KeyIterator<ProgramUnit,ProgramUnit>; 
00055 template class KeyIterator<ProgramUnit,RefList<Symbol> >; 
00056 template class KeyIterator<ProgramUnit,Symbol>; 
00057 template ostream &operator << (ostream &, const List<RefList<ProgramUnit> > &); 
00058 
00059 
00060 
00061 static const char *routine_type_names[NUM_PU_TYPES] = {
00062      "UNDEFINED ROUTINE TYPE",  /// ...  UNDEFINED_PU_TYPE
00063      "BLOCK DATA",              /// ...  BLOCK_DATA_PU_TYPE
00064      "PROGRAM",                 /// ...  PROGRAM_PU_TYPE
00065      "SUBROUTINE",              /// ...  SUBROUTINE_PU_TYPE
00066      "FUNCTION"                 /// ...  FUNCTION_PU_TYPE
00067 };
00068 
00069 ProgramUnit::ProgramUnit(const ProgramUnit &p) 
00070     : Definition(p._tag) 
00071 {
00072     #ifdef CLASS_INSTANCE_REGISTRY
00073     register_instance(PROGRAM_UNIT, sizeof(ProgramUnit), this);
00074     #endif
00075 
00076     _symtab          = NULL;
00077     _data_list       = NULL;
00078     _common_blocks   = NULL;
00079     _namelists       = NULL;
00080     _equivalences    = NULL;
00081     _formats         = NULL;
00082     _overflow        = NULL;
00083     _ddgraph         = NULL;
00084     _gsa_deflocs     = NULL;
00085     _gsa_names       = NULL;
00086     _ranges          = NULL;
00087     _inline_map      = NULL;
00088 #ifdef PERFORMANCE_EVAL
00089     _perf_estimator  = NULL;
00090 #endif
00091     *this = p;
00092 }
00093 
00094 ProgramUnit & 
00095 ProgramUnit::operator = (const ProgramUnit &p) 
00096 {
00097     _routine_type    = p._routine_type;
00098     _original_file   = p._original_file;
00099     _work_stack      = p._work_stack;
00100 
00101     delete _symtab;
00102     _symtab          = p._symtab->clone();
00103 
00104     delete _common_blocks;
00105     _common_blocks   = p._common_blocks->clone();
00106 
00107     delete _namelists;
00108     _namelists   = p._namelists->clone();
00109 
00110     delete _equivalences;
00111     _equivalences    = p._equivalences->clone();
00112 
00113     delete _formats;
00114     _formats         = p._formats->clone();
00115 
00116     delete _gsa_deflocs;
00117     delete _gsa_names;
00118 
00119     if (_ranges) {
00120     delete _ranges;
00121         _ranges = 0;      /// ...  For now, the RangeDict must be recomputed
00122     }
00123 
00124     if (_inline_map) {
00125     delete _inline_map;
00126     _inline_map = 0;
00127     }
00128 
00129     _formats->_pgm   = this;
00130 
00131     if (_overflow != NULL)
00132         delete _overflow;
00133     _overflow        = p._overflow->clone();
00134 
00135     if (_data_list != NULL)
00136         delete _data_list;
00137     _data_list       = p._data_list->clone();
00138     _data_list->relink_ptrs(*this);
00139 
00140     _statements = p._statements;
00141 
00142     _statements._pgm = this;
00143 
00144     /// ...  ORDER DEPENDENCY: Symtab relink requires StmtList to have been copied
00145     _symtab->relink_ptrs(*this);
00146 
00147     relink_all_lptrs((List<Statement> &) _statements, *this);
00148     _common_blocks->relink_ptrs(*this);
00149     _namelists->relink_ptrs(*this);
00150     _equivalences->relink_ptrs(*this);
00151     if (p.gsa_valid()) {
00152       _gsa_deflocs = new DefLocMap(*p._gsa_deflocs, *this);
00153       _gsa_names = new TranslateObject(*p._gsa_names, *this);
00154     }
00155 
00156     _multithread = p._multithread;   /// ... _
00157 
00158 #ifdef PERFORMANCE_EVAL
00159     _perf_estimator = p._perf_estimator;
00160 #endif
00161     return (*this);
00162 }
00163 
00164 ProgramUnit *
00165 ProgramUnit::clone() const
00166 {
00167     return new ProgramUnit( *this );
00168 }
00169 
00170 Definition *
00171 ProgramUnit::definition_clone() const
00172 {
00173     return (Definition *) clone();
00174 }
00175 
00176 ProgramUnit::ProgramUnit(const char *tag, PU_TYPE routine_type)
00177     : Definition(tag) 
00178 {
00179     #ifdef CLASS_INSTANCE_REGISTRY
00180     register_instance(PROGRAM_UNIT, sizeof(ProgramUnit), this);
00181     #endif
00182 
00183     _routine_type = routine_type;
00184     _symtab = new Symtab;
00185     _common_blocks = new CommonBlockDict;
00186     _namelists = new NamelistDict;
00187     _equivalences = new EquivalenceDict;
00188     _gsa_deflocs = NULL;
00189     _gsa_names = NULL;
00190 
00191     _overflow = new BinRep;
00192     Set<BinRep> *S = new Set<BinRep>;
00193     _overflow->put_set( S );
00194 
00195     _data_list = new DataList;
00196 
00197     _formats = new FormatDB( *this );
00198 
00199     _statements._pgm = this;
00200     _formats->_pgm   = this;
00201 
00202     _inline_map = NULL;
00203 
00204     _ddgraph      = NULL;
00205     _ranges       = NULL;
00206 
00207 #ifdef PERFORMANCE_EVAL
00208     _perf_estimator = NULL;
00209 #endif
00210 
00211 }
00212 
00213 ProgramUnit::ProgramUnit(const char *tag, const VDL & vdl_bs)
00214     : Definition(tag) 
00215 {
00216     #ifdef CLASS_INSTANCE_REGISTRY
00217     register_instance(PROGRAM_UNIT, sizeof(ProgramUnit), this);
00218     #endif
00219 
00220     _ddgraph = NULL;
00221     _ranges  = NULL;
00222     _gsa_deflocs = NULL;
00223     _gsa_names = NULL;
00224 
00225     _inline_map = NULL;
00226 
00227 #ifdef PERFORMANCE_EVAL
00228     _perf_estimator = NULL;
00229 #endif
00230 
00231     if (vdl_bs.data_ref() != 0) {
00232         create_program_unit( *vdl_bs.data_ref() );
00233 
00234         _statements._pgm = this;
00235         _formats->_pgm   = this;
00236     }
00237 }
00238 
00239 ProgramUnit::ProgramUnit(const char *tag, const BinRep & bs)
00240     : Definition(tag) 
00241 {
00242     #ifdef CLASS_INSTANCE_REGISTRY
00243     register_instance(PROGRAM_UNIT, sizeof(ProgramUnit), this);
00244     #endif
00245 
00246     _ddgraph = NULL;
00247     _ranges  = NULL;
00248     _gsa_deflocs = NULL;
00249     _gsa_names = NULL;
00250 
00251     create_program_unit( bs );
00252 
00253     _statements._pgm = this;
00254     _formats->_pgm   = this;
00255 
00256     _inline_map = NULL;
00257 
00258 #ifdef PERFORMANCE_EVAL
00259     _perf_estimator = NULL;
00260 #endif
00261 }
00262 
00263 void
00264 ProgramUnit::create_program_unit( const BinRep & bs )
00265 {
00266     BinRep    & dict = CASTAWAY(BinRep &) bs;
00267 
00268     Boolean errors = False;
00269 
00270     /// ...  First, check if the BinRep contains a "messages" field which
00271     /// ...  indicates that there were syntax errors or warnings in the the 
00272     /// ...  Fortran code.  If that is the case, print out the errors.
00273 
00274     {
00275         if (dict.find_ref("messages")) {
00276             BinRep & messages = dict["messages"];
00277 
00278             for (Iterator<BinRep> file_iter = messages.to_set(); 
00279                                   file_iter.valid(); ++file_iter) {
00280                 String curr_file;
00281                 file_iter.current()[0].to_string(curr_file);
00282 
00283                 cerr << endl;
00284                 cerr << "In " << curr_file << endl;
00285                 
00286                 Iterator<BinRep> line_iter = file_iter.current()[1].to_tuple();
00287 
00288                 for (; line_iter.valid(); ++line_iter) {
00289                     String event, msg;
00290 
00291                     line_iter.current()[1].to_string(event);
00292                     line_iter.current()[2].to_string(msg);
00293 
00294                     cerr << "  >>> " << event << " on line ";
00295                     cerr << (line_iter.current()[0]).to_integer();
00296                     cerr << "   " << msg << endl;
00297                 }
00298                 cerr << endl;
00299             }
00300 
00301             dict.del("messages");
00302             errors = True;
00303         }
00304     }
00305 
00306     
00307     /// ...  Now for the conversions.  Most must take place in a fairly determined
00308     /// ...  order.  After each field is converted, it should be deleted from the
00309     /// ...  dictionary so that what remains afterwards should all go into overflow.
00310 
00311     /// ...  Get the file name.
00312 
00313     {
00314         if (dict.find_ref("file")) {
00315             if (dbx_program_debug_level >= 1)
00316                 cout << "*ProgramUnit: Converting original_file ....";
00317 
00318             dict["file"].to_string(_original_file);
00319 
00320             if (dbx_program_debug_level >= 1)
00321                 cout << _original_file << endl;
00322 
00323             dict.del("file");
00324         }
00325     }
00326 
00327     /// ...  Get the routine type
00328 
00329     {
00330         if (dbx_program_debug_level >= 1)
00331             cout << "*ProgramUnit: Converting routine_type....";
00332 
00333         String          routine_type;
00334 
00335         if (! dict.find_ref("routine_type")) {
00336             if (errors)
00337                 cerr << "\nPolaris aborted due to errors.\n\n";
00338             else
00339                 cerr << "\nPolaris aborted due to missing routine type.\n\n";
00340 
00341             p_abort( "Abort.");
00342         }
00343 
00344         dict["routine_type"].to_string(routine_type);
00345 
00346         if (dbx_program_debug_level >= 1)
00347             cout << routine_type << endl;
00348 
00349         if (routine_type == "BLOCKDATA")
00350             _routine_type = BLOCK_DATA_PU_TYPE;
00351         else if (routine_type == "PROGRAM")
00352             _routine_type = PROGRAM_PU_TYPE;
00353         else if (routine_type == "SUBROUTINE")
00354             _routine_type = SUBROUTINE_PU_TYPE;
00355         else if (routine_type == "FUNCTION")
00356             _routine_type = FUNCTION_PU_TYPE;
00357         else {
00358             cerr << "Error: ProgramUnit: Unrecognized routine type '"
00359                  << routine_type << "'\n";
00360         }
00361         dict.del("routine_type");
00362     }
00363 
00364     /// ...  Do the initial conversion of the symbol table
00365 
00366     if (dbx_program_debug_level >= 1) {
00367         cout << "*ProgramUnit: First pass over symbol table.\n";
00368     }
00369     _symtab = new Symtab( dict["symtab"] );
00370 
00371     /// ...  Don't delete the "symtab" field from dict yet--we need another
00372     /// ...  pass on it first
00373 
00374     /// ...  Create a temporary expression table
00375 
00376     if (dbx_program_debug_level >= 1) {
00377         cout << "*ProgramUnit: Gathering expression table....\n";
00378     }
00379 
00380     ExprTable exprs( dict["expression"], *_symtab);
00381 
00382     dict.del("expression");
00383 
00384     if (dbx_program_debug_level >= 1) {
00385         cout << "*ProgramUnit: "
00386              << "Translating/creating Dictionary<VoidPtrDef> for stmts....\n";
00387     }
00388 
00389     if (dict.find_ref("final_statement")) {
00390         /// ...  (No reason to directly translate this)
00391         dict.del("final_statement");
00392     }
00393 
00394     /// ...  Read in the formats, if any
00395 
00396     if (dict.find_ref("formats")) {
00397         if (dbx_program_debug_level >= 1) {
00398             cout << "*ProgramUnit: Converting Formats....\n";
00399         }
00400         _formats = new FormatDB( *this, dict["formats"] );
00401         dict.del("formats");
00402     }
00403     else {
00404         _formats = new FormatDB( *this );
00405     }
00406 
00407     /// ...  Read in the namelists, if any
00408 
00409     if (dict.find_ref("namelist_blocks")) {
00410         if (dbx_program_debug_level >= 1) 
00411             cout << "*ProgramUnit: Converting Namelists....\n";
00412 
00413         _namelists = new NamelistDict( dict["namelist_blocks"], *_symtab);
00414         dict.del("namelist_blocks");
00415     }
00416     else {
00417         _namelists = new NamelistDict;
00418     }
00419 
00420     if (dict.find_ref("initial_statement")) {
00421         String          init_stmt;
00422 
00423         dict["initial_statement"].to_string(init_stmt);
00424         dict.del("initial_statement");
00425 
00426         /// ...  Convert the statement list
00427 
00428         if (dbx_program_debug_level >= 1) 
00429             cout << "*ProgramUnit: Converting statements....\n";
00430 
00431         _statements.convert( dict["statements"], exprs, *_symtab, *_namelists,
00432                              *_formats, init_stmt);
00433 
00434         if (dict.find_ref("statements"))
00435             dict.del("statements");
00436     }
00437     else {
00438         /// ...  No "initial_statement" field was found.  It could only then be
00439         /// ...  a block data program unit
00440 
00441         p_assert( _routine_type == BLOCK_DATA_PU_TYPE ||
00442                   _routine_type == PROGRAM_PU_TYPE, 
00443                   "the statement list is empty, not a BLOCKDATA or PROGRAM");
00444 
00445         dict.del("statements");
00446     }
00447 
00448     /// ...  Read in the equivalences, if any
00449 
00450     if (dict.find_ref("equivalences")) {
00451         if (dbx_program_debug_level >= 1) {
00452             cout << "*ProgramUnit: Converting equivalences....\n";
00453         }
00454         _equivalences =
00455             new EquivalenceDict( dict["equivalences"], *_symtab);
00456         dict.del("equivalences");
00457     }
00458     else {
00459         _equivalences = new EquivalenceDict;
00460     }
00461 
00462     /// ...  Read in the common blocks, if any
00463 
00464     if (dict.find_ref("common_blocks")) {
00465         if (dbx_program_debug_level >= 1) 
00466             cout << "*ProgramUnit: Converting Common Blocks....\n";
00467 
00468         _common_blocks = new CommonBlockDict( dict["common_blocks"], *_symtab);
00469         dict.del("common_blocks");
00470     }
00471     else {
00472         _common_blocks = new CommonBlockDict;
00473     }
00474 
00475     /// ...  Read in the data statements, if any
00476 
00477     if (dict.find_ref("data_expr")) {
00478         if (dbx_program_debug_level >= 1) {
00479             cout << "*ProgramUnit: Converting DATA statement info....\n";
00480         }
00481         _data_list = new DataList( dict["data_expr"], exprs);
00482         dict.del("data_expr");
00483     }
00484     else {
00485         _data_list = new DataList;
00486     }
00487 
00488     /// ...  Prepare VoidPtrDef dictionaries for fillining in the symbol table.
00489 
00490     Dictionary<VoidPtrDef> equiv_dict, common_dict, namelist_dict;
00491 
00492     {
00493         if (dbx_program_debug_level >= 1) {
00494             cout << "*ProgramUnit: "
00495                  << "Preparing Dictionary<VoidPtrDef> of Common Blocks....\n";
00496         }
00497 
00498         KeyIterator<String,CommonBlock> iter = *_common_blocks;
00499 
00500         for (; iter.valid(); ++iter) {
00501             common_dict.ins(new VoidPtrDef(iter.current_data().name_ref(), 
00502                             &iter.current_data()));
00503         }
00504     }
00505 
00506     {
00507         if (dbx_program_debug_level >= 1) {
00508             cout << "*ProgramUnit: "
00509                  << "Preparing Dictionary<VoidPtrDef> of Namelists....\n";
00510         }
00511 
00512         KeyIterator<String,Namelist>iter = *_namelists;
00513 
00514         for (; iter.valid(); ++iter) {
00515             namelist_dict.ins(new VoidPtrDef(iter.current_data().name_ref(), 
00516                             &iter.current_data()));
00517         }
00518     }
00519 
00520     {
00521         if (dbx_program_debug_level >= 1) {
00522             cout << "*ProgramUnit: "
00523                  << "Preparing Dictionary<VoidPtrDef> of Equivalences....\n";
00524         }
00525 
00526         KeyIterator<String,Equivalence> iter = *_equivalences;
00527 
00528         for ( ; iter.valid(); ++iter) {
00529             equiv_dict.ins(new VoidPtrDef(iter.current_data().name_ref(), 
00530                             &iter.current_data()));
00531         }
00532     }
00533 
00534     /// ...  Fill in the symbol table now that everything else has been
00535     /// ...  converted.  Then delete that field from dict.
00536 
00537     if (dbx_program_debug_level >= 1) 
00538         cout << "*ProgramUnit: Filling in the Symbol Table....\n";
00539 
00540     _symtab->fill_in( dict["symtab"], exprs, *(stmts()._stmt_tag_dict),
00541                       common_dict, equiv_dict);
00542     dict.del("symtab");
00543 
00544     /// ...  Stick everything else into overflow
00545 
00546     _overflow = new BinRep;
00547     Set<BinRep> *S = new Set<BinRep>;
00548     _overflow->put_set( S );
00549 
00550     if (dbx_program_debug_level >= 1) {
00551         cout << "*ProgramUnit: "
00552              << "Putting anything else into overflow fields....\n";
00553     }
00554 
00555     {
00556         for (Iterator<BinRep> iter = dict.to_set(); iter.valid(); ++iter) {
00557             warn_overflow_map("ProgramUnit", iter.current() );
00558             _overflow->ins( iter.current() );
00559         }
00560     }
00561 
00562     /// ...   Check whether there is a PROGRAM statement or not
00563     /// ...   If not, add one!
00564     
00565     Iterator<Statement> entries = _statements.stmts_of_type(ENTRY_STMT);
00566     
00567     if ((!entries.valid()) &&
00568     (pu_class() == PROGRAM_PU_TYPE)) {
00569         String new_entry_name = "MAIN";
00570 
00571         Symbol *pgm_name = symtab().find_ref(new_entry_name);
00572 
00573         if (pgm_name) {
00574         while (symtab().find_ref(new_entry_name)) {
00575             pgm_name->renaming_suggestion(new_entry_name);
00576         }
00577         }
00578         pgm_name = new ProgramSymbol(new_entry_name, 0);
00579         Statement *entry_stmt = new EntryStmt(_statements.new_tag(),
00580                           id(*pgm_name),
00581                           comma());
00582         pgm_name->entry(entry_stmt);
00583         symtab().ins(pgm_name);
00584         entry_stmt->routine(id(*pgm_name));
00585         
00586         /// ...  The following will only find the FLOW_ENTRY_STMT because
00587         /// ...  we proved above that there are no ENTRY_STMTs in the program unit!
00588         Iterator<Statement> flowiter = _statements.iterate_entry_points();
00589 
00590         p_assert(flowiter.valid(), "ProgramUnit missing FLOW_ENTRY_STMT");
00591 
00592         _statements.ins_after(entry_stmt, &flowiter.current());
00593     }
00594     
00595     stmts().create_flow_graph();
00596 
00597     /// ...  Fill in the dimension entry in the 'Type' field of a Symbol
00598 
00599     _propagate_symbol_dimensions();
00600 
00601     /// ...  Propagate size and dimension information from Types found in
00602     /// ...  VariableSymbols to all expressions.
00603 
00604     _propagate_types();
00605 }
00606 
00607 /// Propagate dimension information from the symbol table to every
00608 /// expression in the ProgramUnit.
00609 
00610 void 
00611 ProgramUnit::_propagate_types()
00612 {
00613     for (Iterator<Statement> stmt_iter = stmts().iterator();
00614                              stmt_iter.valid(); ++stmt_iter) {
00615         Statement & s = stmt_iter.current();
00616         for (Iterator<Expression> expr_iter = s.iterate_expressions();
00617                                   expr_iter.valid(); ++expr_iter) {
00618             propagate_expr_types(expr_iter.current());
00619         }
00620 
00621         if (stmt_iter.current().stmt_class() == RETURN_STMT) {
00622             /// ...  Set Function symbol type to type of return expr?
00623         }
00624     }
00625 }
00626 
00627 /// Update the Type field of each symbol with specific dimension data
00628 
00629 void 
00630 ProgramUnit::_propagate_symbol_dimensions()
00631 {
00632     for (DictionaryIter<Symbol> sym = symtab().iterator(); sym.valid(); ++sym) {
00633         Symbol & s = sym.current_data();
00634 
00635         switch (s.sym_class()) {
00636         case VARIABLE_CLASS:
00637             {
00638                 Type & sym_type  = CASTAWAY(Type &) s.type();
00639             
00640                 sym_type.rank_known( True );
00641                 sym_type.redimension( s.dim().entries() );
00642             }
00643             break;
00644     default: break;
00645         }
00646     }
00647 }
00648 
00649 ProgramUnit::~ProgramUnit()
00650 {
00651     #ifdef CLASS_INSTANCE_REGISTRY
00652     unregister_instance(PROGRAM_UNIT, this);
00653     #endif
00654 
00655   if (_ddgraph)
00656       delete _ddgraph;
00657   if (_data_list)
00658       delete _data_list;
00659   if (_ranges)
00660       delete _ranges;
00661   if (_inline_map)
00662       delete _inline_map;
00663   delete _common_blocks;
00664   delete _namelists;
00665   delete _equivalences;
00666   delete _formats;
00667   delete _overflow;
00668   delete _gsa_deflocs;
00669   delete _gsa_names;
00670   delete _symtab;
00671 }
00672 
00673 const char     *
00674 ProgramUnit::pu_tag_ref() const
00675 {
00676     return _tag;
00677 }
00678 
00679 void
00680 ProgramUnit::burst_header( ostream &o ) const
00681 {
00682     static time_t   t = 0;
00683 
00684     if (switch_value( "burst_header" ) > 0) {
00685         o << "*\f";
00686 
00687         o << " * V" << polaris_major_version << "." << polaris_minor_version;
00688 
00689         if (t == 0)
00690             time( &t );
00691 
00692         char    *c = ctime( &t );
00693 
00694         c[ strlen(c)-1 ] = ' ';
00695 
00696         o << "  * DATE: " << c;
00697 
00698         if (_original_file.defined())
00699             o << "  * FILE: " << _original_file;
00700 
00701         o << endl;
00702     }
00703 }
00704 
00705 void 
00706 ProgramUnit::display(ostream & o) const
00707 {
00708     const int       space_for_label = 6;
00709 
00710     if (_original_file.defined())
00711         o << "FILE: " << _original_file << endl;
00712 
00713     _symtab->write(o, space_for_label, FORTRAN_MAX_LINE_LEN);
00714     _common_blocks->write(o, space_for_label, FORTRAN_MAX_LINE_LEN);
00715     _equivalences->write(o, space_for_label, FORTRAN_MAX_LINE_LEN, *_symtab);
00716     _data_list->write(o, space_for_label, FORTRAN_MAX_LINE_LEN);
00717     _namelists->write(o, space_for_label, FORTRAN_MAX_LINE_LEN);
00718     
00719     /// ...  Statement list
00720     _statements.display(o);
00721     
00722     _formats->write(o, space_for_label, FORTRAN_MAX_LINE_LEN);
00723 }
00724 
00725 void 
00726 ProgramUnit::write(ostream & o) const
00727 {
00728     const int       space_for_label = 0;
00729 
00730     burst_header( o );
00731 
00732     Iterator<Statement> entries = _statements.stmts_of_type(ENTRY_STMT);
00733 
00734     if (entries.valid()) {
00735         int ind = 0;
00736         /// ...  entries.current() is the first entry statement
00737         blank_wide_output( o );
00738         entries.current().write(o, ind, (char *)routine_type_names[pu_class()]);
00739     }
00740     else if (pu_class() == BLOCK_DATA_PU_TYPE) {
00741         blank_wide_output( o );
00742         o << "      BLOCK DATA\n";
00743     }
00744 
00745     _symtab->write(o, space_for_label, FORTRAN_MAX_LINE_LEN);
00746     _common_blocks->write(o, space_for_label, FORTRAN_MAX_LINE_LEN);
00747     _equivalences->write(o, space_for_label, FORTRAN_MAX_LINE_LEN, *_symtab);
00748     _data_list->write(o, space_for_label, FORTRAN_MAX_LINE_LEN);
00749     _namelists->write(o, space_for_label, FORTRAN_MAX_LINE_LEN);
00750     _statements.write(o);
00751     _formats->write(o, space_for_label, FORTRAN_MAX_LINE_LEN);
00752 
00753     blank_wide_output( o );
00754     o << "      END\n";
00755 }
00756 
00757 
00758 void 
00759 ProgramUnit::display_debug(ostream & o) const
00760 {
00761     /// ...   const int       space_for_label = 6;
00762 
00763     if (_routine_type < 0 || _routine_type >= NUM_PU_TYPES) {
00764         cerr << "Error: ProgramUnit: display(): Unknown routine type: "
00765              << _routine_type << endl;
00766         p_abort( "(see above message)" );
00767     }
00768 
00769     display(o);
00770 
00771     /// ...  Symbol table
00772     o << "\nSymtab:\n" << *_symtab << endl;
00773 
00774     /// ...  Equivalences
00775     o << "\nEquivalences:\n" << *_equivalences << endl;
00776 
00777     /// ...  Common Blocks
00778     o << "\nCommon Blocks:\n" << *_common_blocks << endl;
00779 
00780     /// ...  Data
00781     o << "\nData:\n" << *_data_list << endl;
00782 
00783     /// ...  Namelists
00784     o << "\nNamelists:\n" << *_namelists << endl;
00785 
00786     /// ...  Formats
00787     o << "\nFormats:\n" << *_formats << endl;
00788 
00789     /// ...  overflow
00790     o << "\nOverflow:\n" << *_overflow << endl;
00791 }
00792 
00793 ostream & 
00794 operator << (ostream & o, const ProgramUnit & pr)
00795 {
00796   pr.display(o);
00797   return o;
00798 }
00799 
00800 void 
00801 ProgramUnit::print(ostream & o) const
00802 {
00803     display(o);
00804 }
00805 
00806 int 
00807 ProgramUnit::structures_OK() const
00808 {
00809     cout << "Testing ProgramUnit structures....\n";
00810 
00811     if ( !_statements.structures_OK()
00812     /// ...  xxx      || ! _symtab->structures_OK()
00813     /// ...  xxx      || ! _data->structures_OK()
00814         || !_common_blocks->structures_OK()
00815         || !_namelists->structures_OK()
00816         || !_equivalences->structures_OK()
00817     /// ...  xxx      || ! _formats->_structures_OK()
00818     /// ...  xxx      || ! (_overflow == 0 || _overflow->_structures_OK())
00819         ) {
00820         cerr << "\n\n**** Error found in structure of pgm:" << flush << endl;
00821         cerr << *this << endl << endl;
00822         return 0;
00823     }
00824 
00825     return 1;
00826 }
00827 
00828 const char     *
00829 ProgramUnit::routine_name_ref() const
00830 {
00831     Iterator<Statement> entries = stmts().stmts_of_type(ENTRY_STMT);
00832 
00833     if (entries.valid()) {
00834         /// ...  entries.current() is the first entry statement
00835         if (entries.current().routine_valid())
00836             return entries.current().routine_guarded().symbol().name_ref();
00837     }
00838 
00839     /// ...  No entry statements found
00840     return "";
00841 }
00842 
00843 const char     *
00844 ProgramUnit::original_file_ref() const
00845 {
00846     return ((_original_file.defined()) ? (const char *) _original_file : 0);
00847 }
00848 
00849 void
00850 ProgramUnit::clean_workspace(unsigned int pass_tag)
00851 {
00852     work_stack().pop(pass_tag);
00853 
00854     Iterator<Statement> iter = stmts().iterator();
00855 
00856     for ( ; iter.valid(); ++iter)
00857         iter.current().work_stack().pop(pass_tag);
00858 }
00859 
00860 //------------------------------------------------------------------------ 
00861 
00862 typedef set<const Symbol*> SymbolSet;
00863 
00864 static void
00865 collect_all_symbols(const Expression &e, SymbolSet &used )
00866 {
00867     if (e.op() != ID_OP) {
00868         for (Iterator<Expression> iter = e.arg_list(); iter.valid(); ++iter)
00869             collect_all_symbols( iter.current(), used );
00870     }
00871     else {
00872         const Symbol    & sym  = e.symbol();
00873 
00874         if (used.find( &sym ) == used.end()) {
00875             used.insert( &sym);
00876 
00877             switch (sym.sym_class()) {
00878             case VARIABLE_CLASS:
00879                 if (sym.is_array()) {
00880                     for (Iterator<ArrayBounds> iter = sym.dim(); 
00881                                               iter.valid(); ++iter) {
00882                         ArrayBounds & ad = iter.current();
00883 
00884                         if (ad.lower_exists()) 
00885                             collect_all_symbols( ad.lower_guarded(), used );
00886 
00887                         if (ad.upper_exists()) 
00888                             collect_all_symbols( ad.upper_guarded(), used );
00889                     }
00890                 }
00891                 break;
00892 
00893             case SYMBOLIC_CONSTANT_CLASS:
00894                 if (sym.expr_ref())
00895                     collect_all_symbols( *sym.expr_ref(), used );
00896                 break;
00897         default: break;
00898             }
00899         }
00900     }
00901 }
00902 
00903 void
00904 ProgramUnit::clean()
00905 {
00906     SymbolSet       used;
00907     SymbolSet       assertion_symbols;
00908 
00909     /// ...  Look at all of the statements and the expressions in them and 
00910     /// ...  collect the variables which are used.
00911 
00912     for (Iterator<Statement> st_iter = this->stmts().iterator(); 
00913                              st_iter.valid(); ++st_iter) {
00914         Statement & st = st_iter.current();
00915 
00916         for (Iterator<Expression> e_iter = st.iterate_expressions();
00917                                   e_iter.valid(); ++e_iter) {
00918             Expression &e = e_iter.current();
00919 
00920             /// ...  Find all symbol references in e and add to used.
00921             collect_all_symbols( e, used );
00922         }
00923 
00924         if (st.s_control_valid()) {
00925             for (Iterator<s_control_type> sc_iter = st.s_control_guarded();
00926                                           sc_iter.valid(); ++sc_iter) {
00927                 for (Iterator<Expression> e_iter = sc_iter.current().expr;
00928                                           e_iter.valid(); ++e_iter) {
00929                     Expression &e = e_iter.current();
00930                     collect_all_symbols( e, used );
00931                 }
00932             }
00933         }
00934 
00935         for (Iterator<Assertion> a_iter = st.assertions();
00936                                  a_iter.valid(); ++a_iter) {
00937             Assertion & a = a_iter.current();
00938             if (a.arg_list_valid()) {
00939                 for (Iterator<Expression> e_iter = a.arg_list_guarded();
00940                                           e_iter.valid(); ++e_iter) {
00941                     Expression &e = e_iter.current();
00942 
00943             collect_all_symbols( e, used );
00944                 }
00945 
00946             }
00947         }
00948     }
00949 
00950     /// ...  Examine the DATA statements.
00951     /// ...      assume for now that all DATA is used.
00952     {
00953         for (Iterator<Data> iter = this->data(); iter.valid(); ++iter) {
00954             collect_all_symbols( iter.current().variable_list(), used );
00955             collect_all_symbols( iter.current().value_list(), used );
00956         }
00957     }
00958 
00959     /// ...  Examine the COMMON blocks.
00960     /// ...      assume for now that all COMMON variables are used.
00961     {
00962         for (DictionaryIter<CommonBlock> iter = this->common_blocks(); 
00963                                          iter.valid(); ++iter) {
00964             for (Iterator<Symbol> sym_iter = iter.current().iterator();
00965                                   sym_iter.valid(); ++sym_iter) {
00966                 Symbol & sym = sym_iter.current();
00967 
00968                 if (used.find( &sym ) == used.end()) 
00969                     used.insert( &sym );
00970             }
00971         }
00972     }
00973 
00974     /// ...  Examine the NAMELIST blocks.
00975     /// ...      assume for now that all NAMELIST variables are used.
00976     {
00977         for (DictionaryIter<Namelist> iter = this->namelists(); 
00978                                          iter.valid(); ++iter) {
00979             for (Iterator<Symbol> sym_iter = iter.current().iterator();
00980                                   sym_iter.valid(); ++sym_iter) {
00981                 Symbol & sym = sym_iter.current();
00982 
00983                 if (used.find( &sym ) == used.end() ) 
00984                     used.insert( &sym );
00985             }
00986         }
00987     }
00988 
00989     /// ...  Examine symbols in the symbol table, gathering symbolic constants
00990     /// ...  used to declare the dimensions of arrays.
00991     {
00992         for (DictionaryIter<Symbol> symscn = this->_symtab->iterator();
00993          symscn.valid(); ++symscn) {
00994 
00995             Symbol     &sym = symscn.current();
00996 
00997             if (sym.is_array()) {
00998 
00999         RefSet<Symbol> symb_const;
01000         collect_symb_const(symb_const, sym.dim());
01001 
01002         for (Iterator<Symbol> siter = symb_const;
01003              siter.valid();
01004              ++siter) {
01005             Symbol & constant = siter.current();
01006                     used.insert(&constant);
01007                 }       
01008         }  else if (sym.expr_ref()) {
01009           
01010           /// ...  Added this section to make sure symbols of type
01011           /// ...  SYMBOLIC_CONSTANT_CLASS have been inserted into
01012           /// ...  the SymTab. Without this section, those variables
01013           /// ...  that are declared in 'parameter' without being used
01014           /// ...  in the code body cause "undefined string" in the
01015           // generated code. 12/16/99. Vinh
01016 
01017           collect_all_symbols (*sym.expr_ref (), used);
01018         }
01019         
01020         }
01021     }
01022     
01023     /// ...  Now, check to see if there are any symbols whose only
01024     /// ...  references are in assertions.
01025 
01026 /// We cannot just remove things from the symbol table which are only
01027 /// referenced in assertions - if we did, then the references would
01028 /// not print properly.  We also must delete the stuff from the assertions.
01029 /// The problem is that deleting the symbols from the assertions is
01030 /// very difficult, if not impossible.  For now, we will just hope it
01031 /// does not occur.
01032 ///
01033 ///    for (KeyIterator<Symbol,Assertion> a_iter = sym_to_assert;
01034 //   a_iter.valid();
01035 //   ++a_iter) {
01036 ///
01037 //  Symbol & sym = a_iter.current_key();
01038 //  
01039 //  if (used.find_ref( sym ) == 0) {
01040 ///            /// ...  it is not used outside the assertions,
01041 //      /// ...  so lets remove it from the Symtab.
01042 ///
01043 //      if (sym.common_ref()) 
01044 //      sym.clear_common();
01045 ///
01046 ///            if (sym.equivalence_ref()) {
01047 ///                Equivalence *eq = sym.equivalence_ref();
01048 ///                sym.clear_equivalence();
01049 ///
01050 ///                /// ...  Rebuild the EQUIVALENCE classes if necessary.
01051 ///                this->equivalences().clean( *eq );
01052 ///            }
01053 ///
01054 ///            this->symtab().del( a_iter.current_key().name_ref() );
01055 //  }
01056 ///    }
01057 
01058     /// ...  Now go through the symbol table and remove anything we have not
01059     /// ...  already found.
01060 
01061     for (DictionaryIter<Symbol> iter = this->symtab().iterator();
01062                                 iter.valid(); ++iter) {
01063         Symbol & sym = iter.current_data();
01064 
01065         if (used.find( &sym ) == used.end() ) {
01066 
01067             /// ...  it is not used so lets remove it from the Symtab.
01068 
01069             if (sym.common_ref()) 
01070                 sym.clear_common();
01071 
01072             if (sym.equivalence_ref()) {
01073                 Equivalence *eq = sym.equivalence_ref();
01074                 sym.clear_equivalence();
01075 
01076                 /// ...  Rebuild the EQUIVALENCE classes if necessary.
01077                 this->equivalences().clean( *eq );
01078             }
01079 
01080             this->symtab().del( iter.current_key() );
01081         }
01082     }
01083 }
01084 
01085 BinRep *
01086 ProgramUnit::exchange()
01087 {
01088     VDL             vdl;
01089 
01090     vdl.start_object();
01091     vdl.start_set();
01092     vdl.end_set();
01093     vdl.end_object();
01094 
01095     BinRep  *b = CASTAWAY(BinRep *) vdl.data_ref();
01096 
01097     if (b != 0) {
01098         List<BinRep> *L  = new List<BinRep>;
01099         L->ins_last( new BinRep( "routine_type" ) );
01100         L->ins_last( new BinRep( (char *) routine_type_names[pu_class()] ));
01101         b->to_set().ins( new BinRep( L ) );
01102     }
01103 
01104     if (_original_file.defined()) {
01105         List<BinRep> *L  = new List<BinRep>;
01106         L->ins_last( new BinRep( "file" ) );
01107         L->ins_last( new BinRep( _original_file ) );
01108         b->to_set().ins( new BinRep( L ) );
01109     }
01110 
01111     {
01112         List<BinRep> *L  = new List<BinRep>;
01113         L->ins_last( new BinRep( "expression" ) );
01114         L->ins_last( new BinRep( new List<BinRep> ));
01115         b->to_set().ins( new BinRep( L ) );
01116     }
01117 
01118     symtab().exchange_convert( vdl );
01119     common_blocks().exchange_convert( vdl );
01120     equivalences().exchange_convert( vdl );
01121     data().exchange_convert( vdl );
01122     formats().exchange_convert( vdl );
01123     namelists().exchange_convert( vdl );
01124     stmts().exchange_convert( vdl );
01125 
01126     if (_overflow != 0) {
01127         for (Iterator<BinRep> iter = _overflow->to_set(); iter.valid(); ++iter)
01128             vdl.data_ref()->to_set().ins( iter.current().clone() );
01129     }
01130 
01131     return vdl.give_up_data();
01132 }
01133 
01134 void
01135 ProgramUnit::ddgraph(DDgraph *ddg)
01136 {
01137     if (_ddgraph)
01138     delete _ddgraph;
01139 
01140     _ddgraph = ddg;
01141 }
01142 
01143 void
01144 ProgramUnit::gsa_deflocs(DefLocMap * new_map)
01145 {
01146   delete _gsa_deflocs;
01147   _gsa_deflocs = new_map;
01148 }
01149 
01150 void
01151 ProgramUnit::gsa_names(TranslateObject * new_names)
01152 {
01153   delete _gsa_names;
01154   _gsa_names = new_names;
01155 }
01156 
01157 void
01158 ProgramUnit::function_to_subroutine() {
01159 
01160     p_assert(_routine_type == FUNCTION_PU_TYPE,
01161          "ProgramUnit::function_to_subroutine:  isn't a function");
01162 
01163     _routine_type = SUBROUTINE_PU_TYPE;
01164 }
01165 
01166 void
01167 ProgramUnit::subroutine_to_function() {
01168 
01169     p_assert(_routine_type == SUBROUTINE_PU_TYPE,
01170          "ProgramUnit::subroutine_to_function:  isn't a subroutine");
01171 
01172     _routine_type = FUNCTION_PU_TYPE;
01173 }
01174 
01175 void
01176 ProgramUnit::program_to_subroutine() {
01177 
01178     p_assert(_routine_type == PROGRAM_PU_TYPE,
01179          "ProgramUnit::program_to_subroutine:  isn't a program");
01180 
01181     _routine_type = SUBROUTINE_PU_TYPE;
01182 }
01183 
01184 //_
01185 Expression *
01186 ProgramUnit::distribution_of(Symbol *sym)
01187 {
01188     if (sym->sym_class() != VARIABLE_CLASS)
01189     return 0;
01190     
01191     Iterator<Assertion> iter = _statements.first().assertions();
01192 
01193     for (; iter.valid(); ++iter)
01194     if (iter.current().type() == AS_SHARED)
01195         break;
01196 
01197     if (!iter.valid())    /// ...  No shared vairables in this PU.
01198     return 0;
01199     
01200     /// ...  Search the shared assertion for the matching symbol
01201     for (Iterator<Expression> eiter = iter.current().arg_list_guarded();
01202     eiter.valid(); ++eiter)
01203     if (eiter.current().op() == DISTRIBUTE_OP &&
01204         sym == &eiter.current().symbol())
01205         return &eiter.current();          /// ...  Found
01206 
01207     return 0;
01208 }
01209 
 © 1995-2005 University of Illinois, Urbana-Champaign. All rights reserved.  Fri Mar 25 23:06:02 2005