Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
anl_pragma_construct.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_func_entry.h"
00045 #include "anl_pragma_construct.h"
00046 
00047 extern ANL_DIAGNOSTICS *Anl_Diag; // Defined in anl_driver.cxx
00048 
00049 
00050 // ================ Class Utility Functions ===============
00051 // ========================================================
00052 
00053 BOOL 
00054 ANL_PRAGMA_CONSTRUCT::Is_ProMpf_Pragma_Construct(WN *stmt)
00055 {
00056    BOOL predicate = (stmt != NULL && 
00057                      (WN_operator(stmt) == OPR_PRAGMA ||
00058                       WN_operator(stmt) == OPR_XPRAGMA));
00059 
00060    if (predicate)
00061       switch (WN_pragma(stmt))
00062       {
00063 
00064       case WN_PRAGMA_SECTION:
00065       case WN_PRAGMA_BARRIER:
00066       case WN_PRAGMA_CRITICAL_SECTION_BEGIN:
00067       case WN_PRAGMA_ORDERED_BEGIN:
00068       case WN_PRAGMA_ATOMIC:
00069          break;
00070          
00071       default:
00072          predicate = FALSE;
00073          break;
00074       }
00075    return predicate;
00076 } // ANL_PRAGMA_CONSTRUCT::Is_ProMpf_Pragma_Construct
00077 
00078 
00079 BOOL 
00080 ANL_PRAGMA_CONSTRUCT::Is_Valid_Dir(ANL_PRAGMA_ATTRIBUTE *dir,
00081                                    INT32                 construct_level)
00082 {
00083    return dir->Is_Pragma_Construct_Attribute(construct_level);
00084 }
00085 
00086 
00087 // =============== Private Member Functions ===============
00088 // ========================================================
00089 
00090 
00091 // Is there an end of construct marker ie: a pragma, available?
00092 // if called with a context of 'for_id', it implies _pragma_end
00093 // may be given an ID & must be an end of construct marker to get
00094 // a T result. If it's just for evaluating a line number, then 
00095 // for_id is FALSE and T may be returned on the grounds _pragma_end 
00096 // is just a line marker. for_id matters only for ATOMIC, just now.
00097 
00098 BOOL
00099 ANL_PRAGMA_CONSTRUCT::_End_Is_Part_Of_Construct(BOOL for_id)
00100 {
00101    // PRECONDITION: Must have done _Find_Pragma_End_Stmt()
00102    //
00103    BOOL predicate;
00104    
00105    if (_pragma_end != NULL)
00106    {
00107       switch (_pragma_kind)
00108       {
00109       case ANL_SECTION_PRAGMA:
00110          predicate = FALSE;
00111          break;
00112 
00113       case ANL_BARRIER_PRAGMA:
00114          predicate = TRUE;  // _pragma_end == _pragma_begin
00115          break;
00116 
00117       case ANL_ATOMIC_PRAGMA:
00118          predicate = !for_id;
00119          break;
00120 
00121       case ANL_CRITICAL_SECTION_PRAGMA:
00122          predicate = 
00123             (WN_pragma(_pragma_end) == WN_PRAGMA_CRITICAL_SECTION_END);
00124          break;
00125 
00126       case ANL_ORDERED_PRAGMA:
00127          predicate = 
00128             (WN_pragma(_pragma_end) == WN_PRAGMA_ORDERED_END);
00129          break;
00130 
00131       default:
00132          predicate = FALSE;
00133          break;
00134       }
00135    }
00136    else // (_pragma_end == NULL)
00137    {
00138       predicate = FALSE;
00139    }
00140    return predicate;
00141 } // ANL_PRAGMA_CONSTRUCT::_End_Is_Part_Of_Construct
00142 
00143 
00144 void
00145 ANL_PRAGMA_CONSTRUCT::_Find_Pragma_End_Stmt()
00146 {
00147    // We allow two ways of ending a pragma delimited region
00148    // of statements.  This function finds any such statement, returns
00149    // "pragma_begin" if not applicable (e.g. for BARRIER), and NULL if
00150    // none is found.  The exact values returned here have consequences
00151    // for the algorithms used elsewhere (w.g. for _Get_Max_Construct_Srcpos).
00152    //
00153    WN_PRAGMA_ID end_id[2] = {WN_PRAGMA_UNDEFINED, 
00154                              WN_PRAGMA_UNDEFINED};
00155 
00156    BOOL search_loop =  (_pragma_end != _pragma_begin) ;
00157 
00158    switch (_pragma_kind)
00159    {
00160 
00161    case ANL_SECTION_PRAGMA:
00162       end_id[0] = WN_PRAGMA_SECTION;
00163       end_id[1] = WN_PRAGMA_PSECTION_END;
00164       break;
00165 
00166    case ANL_BARRIER_PRAGMA:
00167       _pragma_end = _pragma_begin; // Does not bracket any statements.
00168       search_loop = FALSE;
00169       break;
00170 
00171    case ANL_ATOMIC_PRAGMA:
00172       _pragma_end = WN_next(_pragma_begin);
00173       _pr_end_part_of_body = TRUE;
00174       search_loop = FALSE;
00175       break ;
00176 
00177    case ANL_CRITICAL_SECTION_PRAGMA:
00178       end_id[0] = WN_PRAGMA_CRITICAL_SECTION_END;
00179       break;
00180 
00181    case ANL_ORDERED_PRAGMA:
00182       end_id[0] = WN_PRAGMA_ORDERED_END;
00183       break;
00184 
00185    default:
00186       Anl_Diag->Error("Unexpected pragma in _Find_Pragma_End_Stmt()!!");
00187       break;
00188    }
00189 
00190    if (search_loop)
00191      {
00192        // Search for a pragma that matches the expected END pragma,
00193        // or end up with (pragma_end == NULL) when none is found.
00194        //
00195        WN *stmt;
00196 
00197        for (stmt = WN_next(_pragma_begin);
00198             (stmt != NULL &&
00199              !((WN_operator(stmt) == OPR_PRAGMA ||
00200                 WN_operator(stmt) == OPR_XPRAGMA) &&
00201                (WN_pragma(stmt) == end_id[0] ||
00202                 WN_pragma(stmt) == end_id[1])));
00203             stmt = WN_next(stmt));
00204        _pragma_end = stmt;
00205      } 
00206 } // ANL_PRAGMA_CONSTRUCT::_Find_Pragma_End_Stmt
00207 
00208    
00209 void 
00210 ANL_PRAGMA_CONSTRUCT::_Get_Max_Construct_Srcpos(ANL_SRCPOS *max)
00211 {
00212    ANL_SRCPOS min(_pragma_begin);
00213 
00214    *max = ANL_SRCPOS(_pragma_begin);
00215    for (WN *stmt = _pragma_begin; 
00216         stmt != _pragma_end;
00217         stmt = WN_next(stmt))
00218    {
00219       Adjust_Srcpos_Range(stmt, &min, max);
00220    }
00221 
00222    if (_End_Is_Part_Of_Construct(FALSE))
00223       Adjust_Srcpos_Range(_pragma_end, &min, max);
00224 } // ANL_PRAGMA_CONSTRUCT::_Get_Max_Construct_Srcpos
00225 
00226 
00227 void 
00228 ANL_PRAGMA_CONSTRUCT::_Write_Pragma_Directives(ANL_CBUF *cbuf)
00229 {
00230    WN         *next_stmt = WN_next(_pragma_begin);
00231    ANL_CBUF    clause_list(_pool);
00232    ANL_SRCPOS  begin_pos;
00233    ANL_SRCPOS  begin_extent;
00234    ANL_SRCPOS  end_pos;
00235 
00236    // Some preliminiaries.
00237    //
00238    _Get_Max_Construct_Srcpos(&end_pos);
00239    _func_entry->Get_Pragma_Srcpos_Range(_pragma_begin,
00240                                         &begin_pos, &begin_extent);
00241 
00242    clause_list.Write_Char(' ');
00243    _func_entry->Pu_Translator()->
00244       ClauseList_To_String(&clause_list, &next_stmt);
00245 
00246    // The idir clause.
00247    //
00248    cbuf->Write_String("idir ");
00249    cbuf->Write_Int(_id);
00250    cbuf->Write_Char(' ');
00251    begin_pos.Write(cbuf);
00252    cbuf->Write_Char('-');
00253    begin_extent.Write(cbuf);
00254    
00255    cbuf->Append_Pragma_Preamble((BOOL) WN_pragma_omp(_pragma_begin),FALSE);
00256 
00257    switch (_pragma_kind)
00258    {
00259    case ANL_SECTION_PRAGMA:
00260       cbuf->Write_String("SECTION ");
00261       break;
00262    case ANL_BARRIER_PRAGMA:
00263       cbuf->Write_String("BARRIER ");
00264       break;
00265    case ANL_CRITICAL_SECTION_PRAGMA:
00266       cbuf->Write_String("CRITICAL SECTION ");
00267       if (WN_operator(_pragma_begin) == OPR_XPRAGMA)
00268         {
00269          cbuf->Write_Char('(');
00270          _func_entry->Pu_Translator()->
00271             A_Pragma_Expr_To_String(cbuf, _pragma_begin);
00272          cbuf->Write_Char(')');
00273         } 
00274       else if (WN_st(_pragma_begin) != NULL)
00275         {
00276           /* 
00277            * In OMP code the pragma has a string const ST
00278            * whose value is the name of the locking varbl.
00279            */
00280 
00281           ST * st = WN_st( _pragma_begin);
00282           if (ST_class(st) == CLASS_CONST)
00283             {
00284              cbuf->Write_Char('(');
00285              cbuf->Write_String(Targ_String_Address(STC_val(st)));
00286              cbuf->Write_Char(')');
00287             }
00288         }
00289       cbuf->Write_Char(' ');
00290       break;
00291     case ANL_ORDERED_PRAGMA:
00292       cbuf->Write_String("ORDERED ");
00293       break;
00294     case ANL_ATOMIC_PRAGMA:
00295       cbuf->Write_String("ATOMIC ");
00296       break;
00297    default:
00298       cbuf->Write_String("<WHATPRAGMA??> ");
00299       break;
00300    }
00301    cbuf->Write_String(clause_list.Chars());
00302    cbuf->Write_String("\n");
00303 
00304    if (_pragma_end != _pragma_begin && 
00305        _End_Is_Part_Of_Construct(TRUE) &&
00306        !_func_entry->Pu_Translator()->Language_is_C())
00307    {
00308       cbuf->Write_String("edir ");
00309       cbuf->Write_Int(_id);
00310       cbuf->Write_String(" ");
00311       end_pos.Write(cbuf);
00312 
00313       cbuf->Append_Pragma_Preamble((BOOL) WN_pragma_omp(_pragma_begin),FALSE);
00314 
00315       switch (_pragma_kind)
00316       {
00317       case ANL_CRITICAL_SECTION_PRAGMA:
00318          cbuf->Write_String("END CRITICAL SECTION\n");
00319          break;
00320       case ANL_ORDERED_PRAGMA:
00321          cbuf->Write_String("END_ORDERED\n");
00322          break;
00323       case ANL_ATOMIC_PRAGMA:
00324          cbuf->Write_String("END ATOMIC\n");
00325          break;
00326 
00327       default:
00328          cbuf->Write_String("<WHAT_PRAGMA_END??>\n");
00329          break;
00330       }
00331    }
00332 } // ANL_PRAGMA_CONSTRUCT::_Write_Pragma_Directives
00333 
00334 
00335 // =============== Public Member Functions ================
00336 // ========================================================
00337 
00338 
00339 ANL_PRAGMA_CONSTRUCT::ANL_PRAGMA_CONSTRUCT(WN             *pragma_begin,
00340                                            INT32           construct_level,
00341                                            ANL_FUNC_ENTRY *func_entry,
00342                                            MEM_POOL       *pool):
00343    _pragma_begin(pragma_begin),
00344    _construct_level(construct_level),
00345    _pragma_end((WN *)-1),  // To catch errors
00346    _pr_end_part_of_body(FALSE),
00347    _func_entry(func_entry),
00348    _pool(pool)
00349 {
00350   _is_omp = FALSE ;
00351 
00352    if (WN_operator(pragma_begin) == OPR_PRAGMA ||
00353        WN_operator(pragma_begin) == OPR_XPRAGMA)
00354    {
00355       _is_omp = WN_pragma_omp(pragma_begin);
00356 
00357       switch (WN_pragma(pragma_begin))
00358       {
00359       case WN_PRAGMA_SECTION:
00360          _pragma_kind = ANL_SECTION_PRAGMA;
00361          break;
00362       case WN_PRAGMA_BARRIER:
00363          _pragma_kind = ANL_BARRIER_PRAGMA;
00364          break;
00365       case WN_PRAGMA_CRITICAL_SECTION_BEGIN:
00366          _pragma_kind = ANL_CRITICAL_SECTION_PRAGMA;
00367          break;
00368       case WN_PRAGMA_ORDERED_BEGIN:
00369          _pragma_kind = ANL_ORDERED_PRAGMA;
00370          break;
00371       case WN_PRAGMA_ATOMIC:
00372          _pragma_kind = ANL_ATOMIC_PRAGMA;
00373          break;
00374       default:
00375          _pragma_kind = ANL_UNKNOWN_PRAGMA;
00376          break;
00377       }
00378       _id = _func_entry->Next_Construct_Id()->Post_Incr();
00379       func_entry->Set_Construct_Id(pragma_begin, _id);
00380 
00381       _Find_Pragma_End_Stmt();
00382       if (_End_Is_Part_Of_Construct(TRUE))
00383          func_entry->Set_Construct_Id(_pragma_end, _id);
00384    }
00385    else
00386    {
00387       _pragma_kind = ANL_UNKNOWN_PRAGMA;
00388       _id = -1;
00389    }
00390 } // ANL_PRAGMA_CONSTRUCT::ANL_PRAGMA_CONSTRUCT
00391 
00392 
00393 WN *
00394 ANL_PRAGMA_CONSTRUCT::Next_Stmt()
00395 {
00396    WN *next;
00397 
00398    if (_End_Is_Part_Of_Construct(TRUE))
00399       next = WN_next(_pragma_end);
00400    else
00401       next = _pragma_end;
00402    return next;
00403 } // ANL_PRAGMA_CONSTRUCT::Next_Stmt
00404 
00405 
00406 void
00407 ANL_PRAGMA_CONSTRUCT::Write(ANL_CBUF *cbuf)
00408 {
00409    if (_pragma_kind != ANL_UNKNOWN_PRAGMA)
00410    {
00411       ANL_CBUF    varlist_cbuf(_pool);
00412       ANL_CBUF    nested_cbuf(_pool);
00413       ANL_SRCPOS  min_srcpos(_pragma_begin);
00414       ANL_SRCPOS  max_srcpos;
00415       ANL_VARLIST varlist(_pool, _func_entry);
00416       WN         *stmt;
00417 
00418       // Write out the pragma construct header
00419       //
00420       _Get_Max_Construct_Srcpos(&max_srcpos);
00421       cbuf->Append_Pragma_Preamble(_is_omp,TRUE);
00422 
00423       switch (_pragma_kind)
00424       {
00425       case ANL_SECTION_PRAGMA:
00426          cbuf->Write_String("section ");
00427          cbuf->Write_Int(_id);
00428          cbuf->Write_String(" \"parallel subsection\"");
00429          break;
00430       case ANL_BARRIER_PRAGMA:
00431          cbuf->Write_String("barrier ");
00432          cbuf->Write_Int(_id);
00433          cbuf->Write_String(" \"barrier\"");
00434          break;
00435       case ANL_CRITICAL_SECTION_PRAGMA:
00436          cbuf->Write_String("critsect ");
00437          cbuf->Write_Int(_id);
00438          cbuf->Write_String(" \"");
00439          if (WN_operator(_pragma_begin) == OPR_XPRAGMA)
00440          {
00441             _func_entry->Pu_Translator()->
00442                A_Pragma_Expr_To_String(cbuf, _pragma_begin);
00443          }
00444          cbuf->Write_Char('\"');
00445          break;
00446       case ANL_ORDERED_PRAGMA:
00447          cbuf->Write_String("ordered ");
00448          cbuf->Write_Int(_id);
00449          cbuf->Write_String(" \"sequential section\"");
00450          break;
00451       case ANL_ATOMIC_PRAGMA:
00452          cbuf->Write_String("atomic ");
00453          cbuf->Write_Int(_id);
00454          cbuf->Write_String(" \"atomic store\"");
00455          break;
00456       default:
00457          cbuf->Write_String("<WHATPRAGMA??> ");
00458          cbuf->Write_Int(_id);
00459          cbuf->Write_String(" \"???\"");
00460          break;
00461       }
00462       cbuf->Write_String(" range ");
00463       min_srcpos.Write(cbuf);
00464       cbuf->Write_Char('-');
00465       max_srcpos.Write(cbuf);
00466       cbuf->Write_Char('\n');
00467 
00468       // Write out the region directives
00469       //
00470       _Write_Pragma_Directives(cbuf);
00471 
00472       // Determine variable references within the statements belonging to the
00473       // loop, and write them out to a temporary buffer. Sometimes (atomic)
00474       // need to look at _pragma_end too.
00475 
00476       for (stmt = _pragma_begin; stmt != _pragma_end; stmt = WN_next(stmt))
00477       {
00478          varlist.Insert_Var_Refs(stmt);
00479       }
00480       if (_pr_end_part_of_body)
00481          varlist.Insert_Var_Refs(stmt);
00482 
00483       varlist.Write(&varlist_cbuf, _id);
00484       varlist_cbuf.Write_Char('\n');
00485 
00486       // Write nested constructs to temporary buffer
00487       //
00488       if (_End_Is_Part_Of_Construct(FALSE))
00489          stmt = _pragma_end;
00490       else
00491          for (stmt = _pragma_begin; 
00492               WN_next(stmt) != _pragma_end; 
00493               stmt = WN_next(stmt));
00494       _func_entry->Emit_Nested_Original_Constructs(&nested_cbuf,
00495                                                    WN_next(_pragma_begin),
00496                                                    stmt);
00497 
00498       // Write out any applicable <dir> entries (i.e. those that were
00499       // not attributed to nested constructs).
00500       //
00501       _func_entry->
00502          Emit_Dir_Entries(cbuf, _id, _construct_level,
00503                           &ANL_PRAGMA_CONSTRUCT::Is_Valid_Dir);
00504 
00505       // Write the varlist and nested constructs.
00506       //
00507       if (varlist_cbuf.Size() > 0)
00508          cbuf->Write_String(varlist_cbuf.Chars());
00509       if (nested_cbuf.Size() > 0)
00510          cbuf->Write_String(nested_cbuf.Chars());
00511 
00512       // Finish writing the construct descriptor
00513       //
00514       cbuf->Append_Pragma_Preamble(_is_omp,TRUE);
00515       switch (_pragma_kind)
00516       {
00517       case ANL_SECTION_PRAGMA:
00518          cbuf->Write_String("end_section ");
00519          break;
00520       case ANL_BARRIER_PRAGMA:
00521          cbuf->Write_String("end_barrier ");
00522          break;
00523       case ANL_CRITICAL_SECTION_PRAGMA:
00524          cbuf->Write_String("end_critsect ");
00525          break;
00526       case ANL_ORDERED_PRAGMA:
00527          cbuf->Write_String("end_ordered ");
00528          break;
00529       case ANL_ATOMIC_PRAGMA:
00530          cbuf->Write_String("end_atomic ");
00531          break;
00532       default:
00533          cbuf->Write_String("<ENDWHATPRAGMA??> \"???\" ");
00534          break;
00535       }
00536       cbuf->Write_Int(_id);
00537       cbuf->Write_String("\n"); // Start next construct on a new line
00538    }
00539 } // ANL_PRAGMA_CONSTRUCT::Write
00540 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines