Polaris: Program.cc Source File

Program.cc

Go to the documentation of this file.
00001 ///
00002 #ifdef POLARIS_GNU_PRAGMAS
00003 #pragma implementation
00004 #endif
00005 ///
00006 #include <stdio.h>
00007 #include <stdlib.h>
00008 #include <stream.h>
00009 #include <fstream.h>
00010 #include <unistd.h>
00011 #include <sys/types.h>
00012 #include <sys/stat.h>
00013 
00014 #include "Collection/KeyIterator.h"
00015 #include "EntryPoints.h"
00016 #include "Program.h"
00017 #include "ProgramTag.h"
00018 #include "utilities/lambda_util.h"
00019 #include "utilities/loopMark.h"
00020 #include "utilities/stmt_util.h"
00021 #include "utilities/switches_util.h"
00022 #include "VDL.h"
00023 #include "version.h"
00024 #include "mem_manager.h"
00025 
00026 #include "p-assert.h"
00027 
00028 template class TypedCollection<Program>;
00029 template class List<Program>;
00030 template ostream & operator << (ostream &, const List<Program> &);
00031 template class Assign<Program>;
00032 
00033 Program::Program()
00034 {
00035     #ifdef CLASS_INSTANCE_REGISTRY
00036     register_instance(PROGRAM, sizeof(Program), this);
00037     #endif
00038 }
00039 
00040 Program::Program(ProgramUnit *pgm)
00041 {
00042     #ifdef CLASS_INSTANCE_REGISTRY
00043     register_instance(PROGRAM, sizeof(Program), this);
00044     #endif
00045 
00046     absorb( pgm );
00047 }
00048 
00049 Program::Program(const Program &p)
00050 {
00051     #ifdef CLASS_INSTANCE_REGISTRY
00052     register_instance(PROGRAM, sizeof(Program), this);
00053     #endif
00054 
00055     clear();
00056     Database<String,ProgramUnit>::operator = ( p );
00057 }
00058 
00059 Program & 
00060 Program::operator = (const Program & p)
00061 {
00062     clear();
00063     Database<String,ProgramUnit>::operator = ( p );
00064 
00065     return (*this);
00066 }
00067 
00068 
00069 Program *
00070 Program::clone() const
00071 {
00072     return new Program( *this );
00073 }
00074 
00075 Program::~Program()
00076 {
00077     #ifdef CLASS_INSTANCE_REGISTRY
00078     unregister_instance(PROGRAM, this);
00079     #endif
00080 }
00081 
00082 void    
00083 Program::absorb( ProgramUnit * pgm )
00084 {
00085     String tag = pgm->tag_ref();
00086 
00087     ins( tag, pgm );
00088 }
00089 
00090 void
00091 Program::absorb(Program * p)
00092 {
00093     for (KeyIterator<String,ProgramUnit> iter = *p; iter.valid(); ++iter) {
00094         ProgramUnit    *pgm = p->grab( iter.current_key() );
00095         absorb( pgm );
00096     }
00097 
00098     delete p;
00099 }
00100 
00101 EntryPoints    *
00102 Program::entry_points() const
00103 {
00104     EntryPoints    *ep = new EntryPoints;
00105 
00106     for (KeyIterator<String,ProgramUnit> iter = *this; iter.valid(); ++iter) {
00107         Iterator<Statement> entries = 
00108             iter.current_data().stmts().stmts_of_type(ENTRY_STMT);
00109 
00110         if (! entries.valid()) {
00111             String name = "";
00112             ep->ins( name, iter.current_data() );
00113         }
00114         else {
00115             for (; entries.valid(); ++entries) {
00116                 Statement &stmt = entries.current();
00117                 if (stmt.routine_valid()) {
00118                     String name = stmt.routine_guarded().symbol().name_ref();
00119                     ep->ins( name, iter.current_data() );
00120                 }
00121             }
00122         }
00123     }
00124 
00125     return ep;
00126 }
00127 
00128 int
00129 Program::structures_OK() const
00130 {
00131     int rc = 1;
00132 
00133     for (KeyIterator<String,ProgramUnit> iter = *this; iter.valid(); ++iter) {
00134         if (! iter.current_data().structures_OK()) {
00135             rc = 0;
00136             cout << "Error in ProgramUnit";
00137         }
00138     }
00139 
00140     return rc;
00141 }
00142 
00143 void
00144 Program::write(ostream & o) const
00145 {
00146     KeyIterator<String,ProgramUnit> iter = *this;
00147 
00148     if (switch_value( "burst_page" ) > 0) {
00149         o << "*\f" << "Polaris ";
00150         o << "v" << polaris_major_version << "." << polaris_minor_version;
00151         o << " Switches Database:" << endl;
00152         o << endl;
00153         dump_switches( o );
00154         o << endl;
00155     }
00156 
00157     if (iter.valid()) {
00158         iter.current_data().write( o );
00159         for (++iter; iter.valid(); ++iter) {
00160             o << endl;
00161             iter.current_data().write( o );
00162         }
00163     }
00164 }
00165 
00166 void
00167 Program::print(ostream & o) const
00168 {
00169     KeyIterator<String,ProgramUnit> iter = *this;
00170 
00171     if (switch_value( "burst_page" ) > 0) {
00172         o << "*\f" << "Polaris ";
00173         o << "v" << polaris_major_version << "." << polaris_minor_version;
00174         o << " Switches Database:" << endl;
00175         o << endl;
00176         dump_switches( o );
00177         o << endl;
00178     }
00179 
00180     if (iter.valid()) {
00181         iter.current_data().print( o );
00182         for (++iter; iter.valid(); ++iter) {
00183             o << endl;
00184             iter.current_data().print( o );
00185         }
00186     }
00187 }
00188 
00189 
00190 inline bool is_vdl(const char* fname){
00191   String name=fname;
00192   if (name.index(".vdl")==name.len()-4){
00193     return true;
00194   } else {
00195     return false;
00196   }
00197 }
00198 
00199 
00200 void
00201 Program::read(const char *fname) 
00202 {
00203     BinRep  vdl;
00204 
00205     String  cmd;
00206     int     x;
00207 
00208     if (switch_value("p_subst_fld") != 0) {
00209         set_subst_field_print();
00210     }
00211     
00212 
00213     
00214     char *vname=(char*)fname;
00215     if (!is_vdl(fname)){
00216     // char *vname = tempnam( "/tmp", "PVDL" );
00217     // char *wname = tempnam( "/tmp", "PVDLW" );
00218     /// ...  
00219     /// ...  previous 2 statement is replaced by following due to complainment from
00220     /// ...  gcc 2.96 as:
00221     //  /tmp/cceIAdb5.o(.text+0x17): the use of `tempnam' is dangerous, better use `mkstemp'
00222     vname = ( char * )malloc( 100 );    /// ...  new char[100];
00223     char *wname = ( char * )malloc( 100 );      /// ...  new char[100];
00224     
00225     strcpy( vname, "/tmp/PVDLXXXXXX" );
00226     strcpy( wname, "/tmp/PVDLWXXXXXX" );
00227     int vfid = mkstemp( vname ); 
00228     int wfid = mkstemp( wname ); 
00229 
00230     /// ...  Allocate vname and wname using malloc(), these are temporary files
00231     /// ...  File vname is for the VDL coming from the scanner.
00232     /// ...  File wname is for any warnings coming from the scanner
00233 
00234     /// ...  p_assert( vname, "can not allocate temporary file name" );
00235     /// ...  -->
00236     p_assert( vfid > -1, "can not allocate temporary file name" );
00237 
00238     if ((x = switch_value("kap_scanner")) != 0) 
00239         cmd  = "p-kap-scanner";
00240     else
00241         cmd  = "p-scanner3 +vdl";
00242 
00243     if ((x = switch_value("comments")) != 0) 
00244         cmd += " +comment";
00245 
00246     if ((x = switch_value("integer_len")) != 0) {
00247         change_default_type_size(INTEGER_TYPE, x);
00248         cmd += " -i";
00249         char    buffer[32];
00250         sprintf( buffer, "%d", x );
00251         cmd += buffer;
00252     }
00253 
00254     if ((x = switch_value("real_len")) != 0) {
00255         change_default_type_size(REAL_TYPE, x);
00256         cmd += " -r";
00257         char    buffer[32];
00258         sprintf( buffer, "%d", x );
00259         cmd += buffer;
00260     }
00261 
00262     if ((x = switch_value("logical_len")) != 0) {
00263         change_default_type_size(LOGICAL_TYPE, x);
00264         cmd += " -l";
00265         char    buffer[32];
00266         sprintf( buffer, "%d", x );
00267         cmd += buffer;
00268     }
00269 
00270     if ((x = switch_value("nolinelenwarn")) != 0) {
00271         cmd += " -nowarnlong ";
00272     }
00273 
00274     if ((x = switch_value("double_len")) != 0) {
00275         change_default_type_size(DOUBLE_PRECISION_TYPE, x);
00276 ///        cmd += " -d";
00277 ///        cmd += dec( x );
00278     }
00279 
00280     if ((x = switch_value("complex_len")) != 0) {
00281         change_default_type_size(COMPLEX_TYPE, x);
00282 ///        cmd += " -c";
00283 ///        cmd += dec( x );
00284     }
00285 
00286     cmd += " -o ";
00287     cmd += vname;
00288     cmd += " ";
00289     cmd += fname;
00290     cmd += " -e ";
00291     cmd += wname;
00292 
00293     system( cmd );
00294 
00295     struct stat buf;
00296     stat(wname, &buf);
00297 
00298     if (buf.st_size == 0) {
00299     /// ...  If the warnings file is empty, just delete it
00300     unlink( wname );
00301 #ifdef CLASS_INSTANCE_REGISTRY
00302     pfree( wname );
00303 #else
00304     free( wname );
00305 #endif
00306     } else {
00307     /// ...  Copy the warnings to cerr and delete the file
00308     ifstream warnings( wname );
00309     char input;
00310     while (warnings) {
00311         warnings.get(input);
00312         cerr << input;
00313     }
00314     warnings.close();
00315     unlink( wname );
00316 #ifdef CLASS_INSTANCE_REGISTRY
00317     pfree( wname );
00318 #else
00319     free( wname );
00320 #endif
00321     }
00322     }
00323 
00324     /// ...  Should be using the wait() call here to return the status of the
00325     /// ...  system call.
00326 
00327     ifstream ifs( vname );
00328 
00329     /// ...  silvius: do not unlink if it was given as input.
00330     if (vname!=fname){
00331       unlink( vname );
00332 
00333     #ifdef CLASS_INSTANCE_REGISTRY
00334     pfree( vname );
00335     #else
00336     free( vname );
00337     #endif
00338     /// ...  Deallocate vname using free().
00339     }
00340 
00341     while (! ifs.eof()) {
00342         vdl.read( ifs );
00343 
00344         if (vdl.is_set()) {
00345             ProgramTag   tag;
00346 
00347             ProgramUnit *pgm = new ProgramUnit( tag, vdl );
00348 
00349             if (pgm && pgm->stmts().entries() > 0) {
00350                 pgm->stmts()._set_block_structure( pgm->stmts().first_ref(), 
00351                                                    pgm->stmts().last_ref(), 
00352                                                    "Program::read" );
00353                 pgm->stmts().create_assertions();
00354         mark_loops_with_location(*pgm);
00355                 remove_all_statement_functions(*pgm);
00356             }
00357             absorb( pgm );
00358         }
00359     }
00360 }
00361 
00362 void
00363 Program::clean()
00364 {
00365     KeyIterator<String,ProgramUnit> iter = *this;
00366 
00367     for ( ; iter.valid(); ++iter) 
00368         iter.current_data().clean();
00369 }
00370 
00371 void 
00372 Program::compute_call_lists()
00373 {
00374 
00375     RefDatabase<StringElem, ProgramUnit> entrydb;
00376 
00377     for (KeyIterator<String, ProgramUnit> piter = *this;
00378      piter.valid();
00379      ++piter) {
00380 
00381     ProgramUnit & p = piter.current_data();
00382     /// ... silvius: clear up old calls and called_by lists.
00383     p.calls().clear();
00384     p.called_by().clear();
00385 
00386     const char * namech = p.routine_name_ref();
00387     StringElem * name = new StringElem(namech);
00388     entrydb.ins(*name, p);
00389     }
00390 
00391     for (KeyIterator<String, ProgramUnit> piter = *this;
00392      piter.valid();
00393      ++piter) {
00394 
00395     ProgramUnit & p = piter.current_data();
00396 
00397     /// ...  silvius: find the ones that are actually called.
00398     /// ...  The old method was giving wrong results after deadcode
00399     /// ...  elimination (of routine calls).
00400     for(Iterator<Statement> stit=p.stmts().iterator(); 
00401         stit.valid(); ++stit){
00402       Statement& s=stit.current();
00403       if (s.stmt_class()==CALL_STMT){
00404         ProgramUnit* callee=
00405           entrydb.find_ref(s.routine_guarded().symbol().tag_ref());
00406         if (callee) {
00407           p.add_call(*callee);
00408           callee->add_called_by(p);
00409         }
00410       } else {
00411         if (s.stmt_class()==ASSIGNMENT_STMT){
00412           if (s.rhs().op()==FUNCTION_CALL_OP) {
00413         ProgramUnit* callee=
00414           entrydb.find_ref(s.rhs().function().symbol().tag_ref());
00415         if (callee) {
00416           p.add_call(*callee);
00417           callee->add_called_by(p);
00418         }
00419           }
00420         }
00421       }
00422     }
00423     
00424 #if 0
00425     for (DictionaryIter<Symbol> dictiter = p.symtab().iterator();
00426          dictiter.valid();
00427          ++dictiter) 
00428         {
00429 
00430         Symbol & sym = dictiter.current_data();
00431 
00432         /// ...  Find the called routines by finding all EXTERNAL symbols mentioned
00433 
00434         if (((sym.sym_class() == SUBROUTINE_CLASS) ||
00435              (sym.sym_class() == FUNCTION_CLASS)) &&
00436             sym.external()) {
00437             
00438             const StringElem & name(sym.name_ref());
00439             ProgramUnit * callee = entrydb.find_ref(name);
00440 
00441             if (callee) {
00442             p.add_call(*callee);
00443             callee->add_called_by(p);
00444             }
00445         }
00446         }
00447 #endif
00448 
00449     }
00450 }
00451 
 © 1995-2005 University of Illinois, Urbana-Champaign. All rights reserved.  Fri Mar 25 23:06:02 2005