Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
anl_func_entry.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 /* -*-Mode: c++;-*- (Tell emacs to use c++ mode) */
00037 
00038 #include "anl_common.h"
00039 #include "anl_diagnostics.h"  // For warnings and errors
00040 #include "anl_file_mngr.h"    // For managing files
00041 #include "w2cf_translator.h"  // For translating WHIRL into high-level-language
00042 #include "anl_varlist.h"      // For emitting attributes of symbol references
00043 #include "anl_pragma_attribute.h" // For <dir> entries
00044 #include "anl_loop_construct.h"
00045 #include "anl_pragma_construct.h"
00046 #include "anl_region_construct.h"
00047 #include "anl_func_entry.h"
00048 
00049 extern ANL_DIAGNOSTICS *Anl_Diag; // Defined in anl_driver.cxx
00050 extern BOOL             Anl_Owhile; // Defined in anl_driver.cxx
00051 
00052 
00053 // ================== External Functions ==================
00054 // ========================================================
00055 
00056 void 
00057 Adjust_Srcpos_Range(WN         *stmt,
00058                     ANL_SRCPOS *min,
00059                     ANL_SRCPOS *max)
00060 {
00061    WN_ITER *stmt_iter;
00062 
00063    // Traverse all statements and pragmas in the stmt, and increase the given
00064    // srcpos range to encompass the srcpos of the stmts encountered in the
00065    // walk.
00066    //
00067    for (stmt_iter = WN_WALK_StmtIter(stmt);
00068         stmt_iter != NULL;
00069         stmt_iter = WN_WALK_StmtNext(stmt_iter))
00070    {
00071       ANL_SRCPOS srcpos(WN_ITER_wn(stmt_iter));
00072 
00073       if (srcpos > *max)
00074          *max = srcpos;
00075       else if (srcpos < *min)
00076          *min = srcpos;
00077    }
00078 } // Adjust_Srcpos_Range
00079 
00080 
00081 // =============== Private Member Functions ===============
00082 // ========================================================
00083 
00084 void
00085 ANL_FUNC_ENTRY::_Push_Construct_Level(ANL_CBUF *cbuf)
00086 {
00087    _construct_level++;
00088    if (_construct_level == 1)
00089       cbuf->Write_Char('\n');
00090 } // ANL_FUNC_ENTRY::_Push_Construct_Level
00091 
00092 
00093 void
00094 ANL_FUNC_ENTRY::_Pop_Construct_Level()
00095 {
00096    _construct_level--;
00097 } // ANL_FUNC_ENTRY::_Pop_Construct_Level
00098 
00099 
00100 // =============== Public Member Functions ================
00101 // ========================================================
00102 
00103 ANL_FUNC_ENTRY::~ANL_FUNC_ENTRY()
00104 {
00105    for (INT i = _dir_entries.Size()-1; i >= 0; i--)
00106       CXX_DELETE(_dir_entries.Indexed_Get(i), _pool);
00107 } // ANL_FUNC_ENTRY::~ANL_FUNC_ENTRY
00108 
00109 
00110 void 
00111 ANL_FUNC_ENTRY::Get_Pragma_Srcpos_Range(WN         *apragma,
00112                                         ANL_SRCPOS *min,
00113                                         ANL_SRCPOS *max)
00114 {
00115    ANL_SRCPOS   pos(apragma);
00116    WN_PRAGMA_ID id = (WN_PRAGMA_ID)WN_pragma(apragma);
00117    WN          *next = WN_next(apragma);
00118    INT32        num_dims;
00119 
00120    *min = pos;
00121    *max = pos;
00122 
00123    switch (id)
00124    {
00125    case WN_PRAGMA_PREFETCH_REF:
00126    case WN_PRAGMA_DYNAMIC:
00127    case WN_PRAGMA_COPYIN:
00128    case WN_PRAGMA_NUMTHREADS:
00129    case WN_PRAGMA_PAGE_PLACE:
00130    case WN_PRAGMA_KAP_CONCURRENTIZE:
00131    case WN_PRAGMA_KAP_NOCONCURRENTIZE:
00132    case WN_PRAGMA_KAP_ASSERT_PERMUTATION:
00133    case WN_PRAGMA_CRI_CNCALL:
00134    case WN_PRAGMA_KAP_ASSERT_CONCURRENT_CALL:
00135    case WN_PRAGMA_KAP_ASSERT_DO:
00136    case WN_PRAGMA_KAP_ASSERT_DOPREFER:
00137    case WN_PRAGMA_IVDEP:
00138       while (next != NULL                          &&
00139              (WN_operator(next) == OPR_XPRAGMA || 
00140               WN_operator(next) == OPR_PRAGMA)     &&
00141              WN_pragma(next) == id                 &&
00142              ANL_SRCPOS(next).Linenum() == pos.Linenum())
00143       {
00144          ANL_SRCPOS srcpos(next);
00145          if (srcpos > *max)
00146             *max = srcpos;
00147          next = WN_next(next);
00148       }
00149       break;
00150    case WN_PRAGMA_DISTRIBUTE:
00151    case WN_PRAGMA_REDISTRIBUTE:
00152    case WN_PRAGMA_DISTRIBUTE_RESHAPE:
00153       for (num_dims = 1; 
00154            (next != NULL                        &&
00155             WN_operator(next) == OPR_PRAGMA     &&
00156             WN_pragma(next) == id               &&
00157             num_dims == WN_pragma_index(next));
00158            num_dims++, next = WN_next(next))
00159       {
00160          ANL_SRCPOS srcpos(next);
00161          if (srcpos > *max)
00162             *max = srcpos;
00163       }
00164 
00165       /* Skip two stores, which are generated purely for dependency analysis
00166        * purposes.
00167        */
00168       if (WN_operator(next)==OPR_STID && 
00169           ST_class(WN_st(next))==CLASS_PREG)
00170       {
00171          next = WN_next(next);
00172          if (WN_operator(next)==OPR_STID && 
00173              ST_class(WN_st(next))==CLASS_PREG)
00174             next = WN_next(next);
00175       }
00176       break;
00177    default:
00178       break;
00179    }
00180    while (_w2cf->Is_A_Pragma_Clause(next))
00181    {
00182       if (!WN_pragma_compiler_generated(next))
00183       {
00184          ANL_SRCPOS srcpos(next);
00185          if (srcpos > *max)
00186             *max = srcpos;
00187       }
00188       next = WN_next(next);
00189    }
00190 } // ANL_FUNC_ENTRY::Get_Pragma_Srcpos_Range
00191 
00192 
00193 void 
00194 ANL_FUNC_ENTRY::Set_Construct_Id(WN *construct, INT64 id)
00195 {
00196    if (id > INT32_MAX)
00197       Anl_Diag->Error("Too many constructs for PROMPF!!");
00198    else
00199       WN_MAP32_Set(_id_map, construct, id);
00200 } // ANL_FUNC_ENTRY::Set_Construct_Id
00201 
00202 
00203 void
00204 ANL_FUNC_ENTRY::Emit_Nested_Original_Constructs(ANL_CBUF *cbuf,
00205                                                 WN            *from_stmt, 
00206                                                 WN            *to_stmt)
00207 {
00208    // Look for nested original constructs in the range of statements
00209    // on the list from "from_stmt" to "to_stmt" inclusively.  We assume
00210    // "from_stmt!=NULL" implies "to_stmt!=NULL".
00211    //
00212    BOOL                  flag;
00213    ANL_PRAGMA_ATTRIBUTE *dir_attribute = NULL;
00214    ANL_PRAGMA_CONSTRUCT *pragma_construct = NULL;
00215    ANL_REGION_CONSTRUCT *region_construct = NULL;
00216    ANL_LOOP_CONSTRUCT   *loop_construct = NULL;
00217    WN                   *stmt = from_stmt;
00218 
00219    while (stmt != NULL && stmt != WN_next(to_stmt))
00220    {
00221       switch (WN_operator(stmt))
00222       {
00223       case OPR_IF:
00224          Emit_Nested_Original_Constructs(cbuf,
00225                                          WN_kid1(stmt),
00226                                          WN_kid1(stmt));
00227          Emit_Nested_Original_Constructs(cbuf,
00228                                          WN_kid2(stmt),
00229                                          WN_kid2(stmt));
00230          stmt = WN_next(stmt);
00231          break;
00232 
00233       case OPR_BLOCK:
00234          Emit_Nested_Original_Constructs(cbuf,
00235                                          WN_first(stmt),
00236                                          WN_last(stmt));
00237          stmt = WN_next(stmt);
00238          break;
00239 
00240       case OPR_XPRAGMA:
00241       case OPR_PRAGMA:
00242          if (ANL_PRAGMA_CONSTRUCT::Is_ProMpf_Pragma_Construct(stmt))
00243          {
00244             _Push_Construct_Level(cbuf); 
00245             pragma_construct =
00246                CXX_NEW(ANL_PRAGMA_CONSTRUCT(stmt, 
00247                                             _construct_level,
00248                                             this, 
00249                                             _pool), _pool);
00250             pragma_construct->Write(cbuf);
00251             stmt = pragma_construct->Next_Stmt();
00252             CXX_DELETE(pragma_construct, _pool);
00253             _Pop_Construct_Level(); 
00254          }
00255          else if (ANL_PRAGMA_ATTRIBUTE::Is_ProMpf_Pragma_Attribute(stmt))
00256          {
00257             dir_attribute = 
00258                CXX_NEW(ANL_PRAGMA_ATTRIBUTE(stmt,
00259                                             _construct_level,
00260                                             this, 
00261                                             _pool), _pool);
00262             _dir_entries.Insert_Last(dir_attribute, &flag);
00263             stmt = dir_attribute->Next_Stmt();
00264          }
00265          else
00266             stmt = WN_next(stmt);
00267          break;
00268 
00269       case OPR_REGION:
00270          if (ANL_REGION_CONSTRUCT::Is_ProMpf_Region_Construct(stmt))
00271          {
00272             _Push_Construct_Level(cbuf);
00273             region_construct = 
00274                CXX_NEW(ANL_REGION_CONSTRUCT(stmt, 
00275                                             _construct_level,
00276                                             this, 
00277                                             _pool), _pool);
00278             region_construct->Write(cbuf);
00279             stmt = region_construct->Next_Stmt();
00280             CXX_DELETE(region_construct, _pool);
00281             _Pop_Construct_Level();
00282          }
00283          else
00284          {
00285             Emit_Nested_Original_Constructs(cbuf,
00286                                             WN_first(WN_region_body(stmt)),
00287                                             WN_last(WN_region_body(stmt)));
00288             stmt = WN_next(stmt);
00289          }
00290          break;
00291 
00292       case OPR_DO_WHILE:
00293       case OPR_WHILE_DO:
00294          if (Anl_Owhile)
00295          {
00296             // Emit original construct for a while-loop.
00297             //
00298             _Push_Construct_Level(cbuf);
00299             loop_construct = 
00300                CXX_NEW(ANL_LOOP_CONSTRUCT(stmt, 
00301                                           _construct_level,
00302                                           this,
00303                                           _pool), _pool);
00304             loop_construct->Write(cbuf);
00305             stmt = loop_construct->Next_Stmt();
00306             CXX_DELETE(loop_construct, _pool);
00307             _Pop_Construct_Level();
00308          }
00309          else
00310          {
00311             // Do not treat while-loops as original constructs.
00312             //
00313             Emit_Nested_Original_Constructs(cbuf,
00314                                             WN_kid1(stmt),
00315                                             WN_kid1(stmt));
00316             stmt = WN_next(stmt);
00317          } 
00318          break;
00319 
00320       case OPR_DO_LOOP:
00321          _Push_Construct_Level(cbuf);
00322          loop_construct = 
00323             CXX_NEW(ANL_LOOP_CONSTRUCT(stmt, 
00324                                        _construct_level,
00325                                        this,
00326                                        _pool), _pool);
00327          loop_construct->Write(cbuf);
00328          stmt = loop_construct->Next_Stmt();
00329          CXX_DELETE(loop_construct, _pool);
00330          _Pop_Construct_Level();
00331          break;
00332 
00333       default:
00334          stmt = WN_next(stmt);
00335          break;
00336       }
00337    }
00338 } // ANL_FUNC_ENTRY::Emit_Nested_Original_Constructs
00339 
00340 
00341 void 
00342 ANL_FUNC_ENTRY::Emit_Dir_Entries(ANL_CBUF *cbuf,
00343                                  INT64     for_construct_id,
00344                                  INT32     for_construct_level,
00345                                  BOOL (*do_emit)(ANL_PRAGMA_ATTRIBUTE *dir,
00346                                                  INT32      construct_level))
00347 {
00348    for (INT i = _dir_entries.Size() - 1; i >= 0; i--)
00349    {
00350       ANL_PRAGMA_ATTRIBUTE *dir = _dir_entries.Indexed_Get(i);
00351 
00352       if (do_emit(dir, for_construct_level))
00353       {
00354          dir->Write(cbuf, for_construct_id);
00355          _dir_entries.Indexed_Remove(i); // Changes _dir_entries.Size()!
00356          CXX_DELETE(dir, _pool);
00357       }
00358    }
00359 } // ANL_FUNC_ENTRY::Emit_Dir_Entries
00360 
00361 
00362 void 
00363 ANL_FUNC_ENTRY::Emit_Original_Construct(ANL_FILE_MNGR *outp_file)
00364 {
00365    const INT64 id = _next_id->Post_Incr();
00366    ANL_CBUF    cbuf(_pool);
00367    ANL_CBUF    varlist_cbuf(_pool);
00368    ANL_CBUF    nested_cbuf(_pool);
00369    ANL_SRCPOS  min_srcpos(_pu);
00370    ANL_SRCPOS  max_srcpos(_pu);
00371    ANL_VARLIST varlist(_pool, this);
00372 
00373    Set_Construct_Id(_pu, id);
00374 
00375    // Start writing the function descriptor to file
00376    //
00377    Adjust_Srcpos_Range(_pu, &min_srcpos, &max_srcpos);
00378    cbuf.Write_String("function ");
00379    cbuf.Write_Int(id);
00380    cbuf.Write_String(" \"");
00381    _w2cf->Original_Symname_To_String(&cbuf, &St_Table[WN_entry_name(_pu)]);
00382    cbuf.Write_String("\" range ");
00383    min_srcpos.Write(&cbuf);
00384    cbuf.Write_Char('-');
00385    max_srcpos.Write(&cbuf);
00386    cbuf.Write_Char('\n');
00387    outp_file->Write_String(cbuf.Chars());
00388 
00389    // Determine variable references within the function body, and
00390    // write them out to a temporary buffer.
00391    //
00392    varlist.Insert_Var_Refs(WN_func_body(_pu));
00393    varlist.Write(&varlist_cbuf, id);
00394    varlist_cbuf.Write_Char('\n');
00395 
00396    // Write nested constructs to a temporary buffer
00397    //
00398    Emit_Nested_Original_Constructs(&nested_cbuf, 
00399                                    WN_first(WN_func_body(_pu)), 
00400                                    WN_last(WN_func_body(_pu)));
00401 
00402    // Write out any remaining <dir> entries to file (i.e. those that were
00403    // not attributed to nested constructs.
00404    //
00405    cbuf.Reset();
00406    for (INT i = _dir_entries.Size()-1; i >= 0; i--)
00407    {
00408       ANL_PRAGMA_ATTRIBUTE *dir = _dir_entries.Indexed_Get(i);
00409       dir->Write(&cbuf, id);
00410       _dir_entries.Indexed_Remove(i); // Changes _dir_entries.Size()
00411       CXX_DELETE(dir, _pool);
00412    }
00413 
00414    // Write the varlist and nested constructs to file.
00415    //
00416    if (cbuf.Size() > 0)
00417       outp_file->Write_String(cbuf.Chars());
00418    if (varlist_cbuf.Size() > 0)
00419       outp_file->Write_String(varlist_cbuf.Chars());
00420    if (nested_cbuf.Size() > 0)
00421       outp_file->Write_String(nested_cbuf.Chars());
00422 
00423    // Finish writing the function descriptor to file
00424    //
00425    cbuf.Reset();
00426    cbuf.Write_String("end_function ");
00427    cbuf.Write_Int(id);
00428    cbuf.Write_String("\n\n\n"); // Seperate function entries by two empty lines
00429    outp_file->Write_String(cbuf.Chars());
00430 
00431 } // ANL_FUNC_ENTRY::Emit_Original_Construct
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines