Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
anl_varlist.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 writing to output file
00041 #include "w2cf_translator.h"  // For translating WHIRL into high-level-language
00042 #include "anl_func_entry.h"   // For func entry related utilities
00043 #include "anl_varlist.h"
00044 
00045 extern ANL_DIAGNOSTICS *Anl_Diag; // Defined in anl_driver.cxx
00046 
00047 // ================== Internal utilities ==================
00048 // ========================================================
00049 
00050 // This is necessary until we consistently use SCLASS_FORMAL_REF ro
00051 // represent reference parameters.
00052 //
00053 #define ANL_IS_REF_PARM_ADDR(st) \
00054 (ST_sclass(st) == SCLASS_FORMAL && \
00055  TY_IS_POINTER(ST_type(st)) && \
00056  !ST_is_value_parm(st))
00057 
00058 static BOOL 
00059 St_Belongs_In_Varlist(ST *st)
00060 {
00061    return ((ST_sym_class(st) == CLASS_VAR) &&
00062            (!ST_is_temp_var(st)) &&
00063            (!Has_Base_Block(st) || St_Belongs_In_Varlist(ST_base(st))));
00064 } // St_Belongs_In_Varlist
00065 
00066 
00067 static void
00068 Write_Sclass(ANL_CBUF *cbuf, ST *st)
00069 {
00070 
00071   if (Has_Base_Block(st))
00072     st = ST_base(st);
00073 
00074    switch (ST_sclass(st))
00075    {
00076    case SCLASS_AUTO:
00077       cbuf->Write_Char('A');
00078       break;
00079 
00080    case SCLASS_FORMAL:
00081       if (ANL_IS_REF_PARM_ADDR(st))
00082          cbuf->Write_Char('R'); // Reference parameter
00083       else
00084          cbuf->Write_Char('V'); // Value parameter
00085       break;
00086 
00087    case SCLASS_PSTATIC:
00088    case SCLASS_FSTATIC:
00089       cbuf->Write_Char('S');
00090       break;
00091 
00092    case SCLASS_COMMON:
00093    case SCLASS_EXTERN:
00094    case SCLASS_UGLOBAL:
00095    case SCLASS_DGLOBAL:
00096       cbuf->Write_Char('G');
00097       break;
00098 
00099 
00100    case SCLASS_FORMAL_REF:
00101       cbuf->Write_Char('R'); // Reference parameter
00102       break;
00103 
00104    default:
00105       cbuf->Write_Char('U'); // We do not expect this in a varlist!
00106       break;
00107    }
00108 } // Write_Sclass
00109 
00110 
00111 // =============== Private Member Functions ===============
00112 // ========================================================
00113 
00114 mUINT32 
00115 ANL_VARLIST::_Binary_Search(INT32 id, mUINT32 from, mUINT32 till)
00116 {
00117    // Return the approximate insertion point, if the desired item
00118    // is not found.  Note that the actual insertion point will be
00119    // either immediately before or after the returned index.
00120    //
00121    mUINT32 found_idx;
00122 
00123    if (from >= till)
00124       found_idx = from;
00125    else
00126    {
00127       const mUINT32 halfway = (till + from) / 2;
00128       const INT32   id2 = _vlist.Indexed_Get(halfway)->Id();
00129 
00130       if (id == id2)
00131          found_idx = halfway;
00132       else if (id < id2)
00133       {
00134          if (halfway == 0)
00135             found_idx = 0;
00136          else
00137             found_idx = _Binary_Search(id, from, halfway-1);
00138       }
00139       else
00140          found_idx = _Binary_Search(id, halfway+1, till);
00141    }
00142    return found_idx;
00143 } // ANL_VARLIST::_Binary_Search
00144 
00145 
00146 UINT32 
00147 ANL_VARLIST::_Get_Io_Item_Lda_Access_Status(WN *io_item)
00148 {
00149    UINT32 status;
00150 
00151    // Assume all LDAs under io items that are not in an IO list are
00152    // read but not written.
00153    //
00154    switch (WN_io_item(io_item))
00155    {
00156    case IOL_ARRAY:
00157    case IOL_CHAR:
00158    case IOL_CHAR_ARRAY:
00159    case IOL_EXPR:
00160    case IOL_IMPLIED_DO:
00161    case IOL_IMPLIED_DO_1TRIP:
00162    case IOL_LOGICAL:
00163    case IOL_RECORD:
00164    case IOL_VAR:
00165    case IOL_DOPE:
00166       status = 0;
00167       break;
00168    default:
00169       status = ANL_VAR_READ;
00170       break;
00171    }
00172 
00173    if (status == 0)
00174    {
00175       // First determine whether this is an input or output IO statement
00176       // for the given IO list item.
00177       //
00178       WN *io_stmt = io_item;
00179       while (WN_operator(io_stmt) != OPR_IO)
00180          io_stmt = LWN_Get_Parent(io_stmt);
00181 
00182       switch (WN_io_statement(io_stmt))
00183       {
00184       case IOS_PRINT:
00185       case IOS_TYPE:
00186       case IOS_REWRITE:
00187       case IOS_WRITE:
00188          status = ANL_VAR_READ;
00189          break;
00190 
00191       case IOS_READ:
00192       case IOS_ACCEPT:
00193          status = ANL_VAR_WRITTEN;
00194          break;
00195 
00196       case IOS_ENCODE:
00197          status = ANL_VAR_READ;     // Reads from the IOL item
00198          break;
00199 
00200       case IOS_DECODE:
00201          status = ANL_VAR_WRITTEN;  // Writes to the IOL item
00202          break;
00203 
00204       default:
00205          status = ANL_VAR_READ | ANL_VAR_WRITTEN;
00206          break;
00207       }
00208    }
00209    return status;
00210 } // ANL_VARLIST::_Get_Io_Item_Lda_Access_Status
00211 
00212 
00213 UINT32 
00214 ANL_VARLIST::_Get_Lda_Access_Status(WN *lda)
00215 {
00216    UINT32 status;
00217    WN    *parent = LWN_Get_Parent(lda);
00218 
00219    switch (WN_operator(parent))
00220    {
00221    case OPR_ARRAY:
00222       if (lda == WN_kid0(parent))
00223          status = _Get_Lda_Access_Status(parent);
00224       else
00225          status = ANL_VAR_READ | ANL_VAR_WRITTEN; // Whatever this means!
00226       break;
00227 
00228    case OPR_ILOAD:
00229       status = ANL_VAR_READ;
00230       break;
00231 
00232    case OPR_MLOAD:
00233       if (lda == WN_kid0(parent))
00234          status = ANL_VAR_READ;
00235       else
00236          status = ANL_VAR_READ | ANL_VAR_WRITTEN; // Whatever this means!
00237       break;
00238 
00239    case OPR_ISTORE:
00240       if (lda == WN_kid1(parent))
00241          status = ANL_VAR_WRITTEN;
00242       else
00243          status = ANL_VAR_READ | ANL_VAR_WRITTEN; // Whatever this means!
00244       break;
00245 
00246    case OPR_MSTORE:
00247       if (lda == WN_kid1(parent))
00248          status = ANL_VAR_READ;
00249       else
00250          status = ANL_VAR_READ | ANL_VAR_WRITTEN; // Whatever this means!
00251       break;
00252 
00253    case OPR_SUB:
00254    case OPR_ADD:
00255       status = _Get_Lda_Access_Status(parent); // Pointer arithmetics??
00256       break;
00257 
00258    case OPR_PARM:
00259       // Base this on flag values associated with the PARM node, instead
00260       // of specially recognizing intrinsics while feeling hopeless about
00261       // non-instrinsic calls.
00262       //
00263       if (WN_Parm_In(parent) || WN_Parm_Out(parent))
00264       {
00265          if (WN_Parm_In(parent))
00266             status = ANL_VAR_READ;
00267          if (WN_Parm_Out(parent))
00268             status = ANL_VAR_WRITTEN;
00269       }
00270       else
00271       {
00272          status = ANL_VAR_READ | ANL_VAR_WRITTEN; // We have no idea
00273       }
00274       break;
00275 
00276    case OPR_IO_ITEM:
00277       // Base this on the kind of IO item.
00278       //
00279       status = _Get_Io_Item_Lda_Access_Status(parent);
00280       break;
00281 
00282    case OPR_XPRAGMA:
00283       if (WN_pragma(parent) == WN_PRAGMA_CRITICAL_SECTION_BEGIN)
00284          status = ANL_VAR_READ;
00285       else
00286          status = ANL_VAR_READ | ANL_VAR_WRITTEN;
00287       break;
00288 
00289    default:
00290       // We have no idea, so just assume it is both read and written.
00291       //
00292       status = ANL_VAR_READ | ANL_VAR_WRITTEN;
00293       break;
00294    }
00295    return status;
00296 } // ANL_VARLIST::_Get_Lda_Access_Status
00297 
00298 
00299 // =============== Public Member Functions ================
00300 // ========================================================
00301 
00302 
00303 void
00304 ANL_VAR::Set_Name_Alias(ANL_VAR *var)
00305 {
00306    if (this != var)
00307    {
00308       ANL_VAR *alias;
00309 
00310       // See if var is already in the alias list for this
00311       //
00312       for (alias = _alias; 
00313            alias != var && alias != this; 
00314            alias = alias->_alias);
00315 
00316       if (alias == this)
00317       {
00318          // Combine the two disjoint alias cycles into one cycle.
00319          //
00320          ANL_VAR *next = _alias;
00321 
00322          _alias = var;  // Open and connect this cycle to var cycle
00323          for (alias = var->_alias; 
00324               alias->_alias != var; 
00325               alias = alias->_alias); // Gets to the end of the var cycle
00326          alias->_alias = next; // Connect the var cycle with this cycle.
00327       }
00328    }
00329 } // ANL_VAR::Set_Name_Alias
00330 
00331 
00332 void 
00333 ANL_VAR::Reset_References()
00334 {
00335    _status = 0;
00336    for (ANL_VAR *var = _alias; var != this; var = var->_alias)
00337       var->_status = 0;
00338 } // ANL_VAR::Reset_References
00339 
00340 
00341 void 
00342 ANL_VAR::Write(ANL_CBUF *cbuf, ANL_FUNC_ENTRY *func_entry)
00343 {
00344    BOOL     read = Is_Read();
00345    BOOL     written = Is_Written();
00346    ANL_VAR *var;
00347 
00348    for (var = _alias; var != this; var = var->_alias)
00349    {
00350       read = read || var->Is_Read();
00351       written = written || var->Is_Written();
00352    }
00353    
00354    cbuf->Write_String(" \"");
00355    func_entry->Pu_Translator()->Original_Symname_To_String(cbuf, _st);
00356    cbuf->Write_String("\"(");
00357    Write_Sclass(cbuf, _st);
00358    cbuf->Write_String("):");
00359    if (read)
00360       cbuf->Write_Char('r');
00361    if (written)
00362       cbuf->Write_Char('w');
00363 } // ANL_VAR::Write
00364 
00365 
00366 ANL_VAR *
00367 ANL_VARLIST::Find(ST *st)
00368 {
00369    // Return NULL if not found.
00370    //
00371    ANL_VAR    *found;
00372    const INT32 id = ST_st_idx(st);
00373    mUINT32     idx = _Binary_Search(id, 0, _vlist.Size());
00374    if (idx < _vlist.Size() && id == _vlist.Indexed_Get(idx)->Id())
00375       found = _vlist.Indexed_Get(idx);
00376    else
00377       found = NULL;
00378 
00379    return found;
00380 } // ANL_VARLIST::Find
00381 
00382 
00383 ANL_VAR *
00384 ANL_VARLIST::Find_or_Insert(ST *st)
00385 {
00386    // Insert new ANL_VAR if not found.
00387    //
00388    ANL_VAR    *found;
00389    const INT32 id = ST_st_idx(st);
00390 
00391    mUINT32     idx = _Binary_Search(id, 0, _vlist.Size());
00392    if (idx < _vlist.Size() && id == _vlist.Indexed_Get(idx)->Id())
00393       found = _vlist.Indexed_Get(idx);
00394    else
00395    {
00396       ANL_VAR *var = CXX_NEW(ANL_VAR(st), _pool);
00397       BOOL     added;
00398 
00399       // Insert the new item
00400       //
00401       if (idx >= _vlist.Size())
00402       {
00403          _vlist.Insert_Last(var, &added);
00404          found = _vlist.Indexed_Get(_vlist.Size()-1);
00405       }
00406       else if (id < _vlist.Indexed_Get(idx)->Id())
00407       {
00408          _vlist.Insert_Before(var, idx, &added);
00409          found = _vlist.Indexed_Get(idx);
00410       }
00411       else
00412       {
00413          _vlist.Insert_After(var, idx, &added);
00414          found = _vlist.Indexed_Get(idx+1);
00415       }
00416       if (!added)
00417          Anl_Diag->Error("Cannot insert element in variable list!!");
00418    }
00419    return found;
00420 } // ANL_VARLIST::Find_or_Insert
00421 
00422 
00423 void 
00424 ANL_VARLIST::Insert_Var_Refs(WN *subtree)
00425 { 
00426    // Traverse every expression subtree in the PU to determine what
00427    // variables are referenced and how they are referenced.
00428    //
00429    for (WN_ITER *tree_iter = WN_WALK_TreeIter(subtree);
00430         tree_iter != NULL;
00431         tree_iter = WN_WALK_TreeNext(tree_iter))
00432    {
00433       UINT32   status;
00434       ANL_VAR *var;
00435       WN      *wn = WN_ITER_wn(tree_iter);
00436 
00437       switch (WN_operator(wn))
00438       {
00439       case OPR_LDID:
00440          if (St_Belongs_In_Varlist(WN_st(wn)))
00441          {
00442             var = Find_or_Insert(WN_st(wn));
00443 
00444             if (ANL_IS_REF_PARM_ADDR(WN_st(wn)) ||
00445                 ST_pt_to_unique_mem(WN_st(wn)))
00446             {
00447                // Either a reference parameter or an adjustable array,
00448                // where references are indirect.
00449                //
00450                status = _Get_Lda_Access_Status(wn);
00451                if ((status & ANL_VAR_READ) != 0)
00452                   var->Set_Read();
00453                if ((status & ANL_VAR_WRITTEN) != 0)
00454                   var->Set_Written();
00455             }
00456             else
00457             {
00458                var->Set_Read();
00459             }
00460          }
00461          break;
00462 
00463       case OPR_STID:
00464          if (St_Belongs_In_Varlist(WN_st(wn)) &&
00465              !ST_pt_to_unique_mem(WN_st(wn)))
00466          {
00467             // Typically a unique memory pointer is due to an adjustable
00468             // automatic variable.  We do not record the initial assignment
00469             // to such a variable.
00470             //
00471             BOOL record_write = TRUE;
00472 
00473             var = Find_or_Insert(WN_st(wn));
00474 
00475             if (WN_operator(WN_kid0(wn)) == OPR_LDID)
00476             {
00477                // Detect compiler temporaries used as aliases for user-declared
00478                // scalar variables (e.g. for parameters used in adjustable
00479                // array bounds).
00480                //
00481                ANL_CBUF lhs(_pool);
00482                ANL_CBUF rhs(_pool);
00483                _func_entry->Pu_Translator()->
00484                   Original_Symname_To_String(&lhs, WN_st(wn));
00485                _func_entry->Pu_Translator()->
00486                   Original_Symname_To_String(&rhs, WN_st(WN_kid0(wn)));
00487 
00488                if (strcmp(lhs.Chars(), rhs.Chars()) == 0)
00489                {
00490                   record_write = FALSE; // Copy-in of params into temporary
00491                   var->Set_Name_Alias(Find_or_Insert(WN_st(WN_kid0(wn))));
00492                }
00493             }
00494             if (record_write)
00495                var->Set_Written();
00496          }
00497          break;
00498 
00499       case OPR_LDA:
00500          if (St_Belongs_In_Varlist(WN_st(wn)))
00501          {
00502             status = _Get_Lda_Access_Status(wn);
00503             var = Find_or_Insert(WN_st(wn));
00504             if ((status & ANL_VAR_READ) != 0)
00505                var->Set_Read();
00506             if ((status & ANL_VAR_WRITTEN) != 0)
00507                var->Set_Written();
00508          }
00509          break;
00510 
00511       case OPR_PRAGMA:
00512          if (WN_operator(wn) == OPR_PRAGMA)
00513          {
00514             switch (WN_pragma(wn))
00515             {
00516             case WN_PRAGMA_LOCAL:
00517             case WN_PRAGMA_LASTLOCAL:
00518             case WN_PRAGMA_SHARED:
00519             case WN_PRAGMA_FIRSTPRIVATE:
00520                break;  // No need to register a reference for these?
00521 
00522             case WN_PRAGMA_COPYIN:
00523                if (St_Belongs_In_Varlist(WN_st(wn)))
00524                {
00525                   var = Find_or_Insert(WN_st(wn));
00526                   var->Set_Read();
00527                }
00528                break;
00529             default:
00530                break;
00531             }
00532          }
00533          break;
00534 
00535       default:
00536          break; // Nothing to do
00537       }
00538    }
00539 } // ANL_VARLIST::Insert_Var_Refs
00540 
00541 
00542 void 
00543 ANL_VARLIST::Write(ANL_CBUF *cbuf, INT64 construct_id)
00544 {
00545    const INT32 NUM_CHARS_PER_LINE = 72;
00546    BOOL     first_var_list_item = TRUE;
00547    INT      max_idx;
00548    ANL_CBUF tmpbuf(_pool);
00549 
00550    tmpbuf.Write_String("varlist ");
00551    tmpbuf.Write_Int(construct_id);
00552    for (INT var_idx = 0; var_idx < _vlist.Size(); var_idx++)
00553    {
00554       ANL_VAR *var = _vlist.Indexed_Get(var_idx);
00555       
00556       if (tmpbuf.Size() >= NUM_CHARS_PER_LINE)
00557       {
00558          // Start a new "varlist"
00559          //
00560          tmpbuf.Write_Char('\n');
00561          cbuf->Write_String(tmpbuf.Chars());
00562          tmpbuf.Reset();
00563          tmpbuf.Write_String("varlist ");
00564          tmpbuf.Write_Int(construct_id);
00565          first_var_list_item = TRUE;
00566       }
00567 
00568       // Write the next varlist item
00569       //
00570       if (var->Is_Read() || var->Is_Written())
00571       {
00572          if (first_var_list_item)
00573          {
00574             first_var_list_item = FALSE;
00575          }
00576          else
00577          {
00578             tmpbuf.Write_String(",");
00579          }
00580          var->Write(&tmpbuf, _func_entry);
00581          var->Reset_References();
00582       }
00583    }
00584    if (tmpbuf.Size() > 0)
00585       cbuf->Write_String(tmpbuf.Chars());
00586 } // ANL_VARLIST::Write
00587 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines