Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
anl_region_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_region_construct.h"
00046 
00047 extern ANL_DIAGNOSTICS *Anl_Diag; // Defined in anl_driver.cxx
00048 
00049 
00050 // ================ Class Utility Functions ===============
00051 // ========================================================
00052 
00053 
00054 // A region construct appears in a REGION_pragmas section.
00055 // Thus the scope of the pragma is the region. There may be
00056 // a NOWAIT or END_MARKER to provide the line number of the
00057 // end construct in the source.
00058 
00059 BOOL 
00060 ANL_REGION_CONSTRUCT::Is_ProMpf_Region_Construct(WN *stmt)
00061 {
00062    BOOL predicate = (stmt != NULL && WN_operator(stmt) == OPR_REGION);
00063 
00064    if (predicate)
00065    {
00066       WN *pragma = WN_first(WN_region_pragmas(stmt));
00067       predicate = pragma != NULL ; 
00068 
00069       if (predicate) 
00070         {
00071           switch (WN_pragma(pragma)) 
00072             {
00073             case WN_PRAGMA_PARALLEL_BEGIN:
00074             case WN_PRAGMA_MASTER_BEGIN:
00075             case WN_PRAGMA_SINGLE_PROCESS_BEGIN:
00076             case WN_PRAGMA_PSECTION_BEGIN:
00077             case WN_PRAGMA_PARALLEL_SECTIONS:
00078               break;
00079 
00080             default:
00081               predicate  = FALSE;
00082               break ;
00083             }
00084         }
00085     }
00086    return predicate;
00087 } // ANL_REGION_CONSTRUCT::Is_ProMpf_Region_Construct
00088 
00089 
00090 BOOL 
00091 ANL_REGION_CONSTRUCT::Is_Valid_Dir(ANL_PRAGMA_ATTRIBUTE *dir,
00092                                    INT32                 construct_level)
00093 {
00094    return dir->Is_Region_Construct_Attribute(construct_level);
00095 }
00096 
00097 
00098 // =============== Private Member Functions ===============
00099 // ========================================================
00100 
00101 WN *
00102 ANL_REGION_CONSTRUCT::_First_Region_Stmt()
00103 {
00104    WN *base = _region;
00105    ANL_SRCPOS basepos(_region);
00106 
00107    while (WN_prev(base) != NULL && ANL_SRCPOS(WN_prev(base)) >= basepos)
00108       base = WN_prev(base);
00109    return base;
00110 } // ANL_REGION_CONSTRUCT::_First_Region_Stmt
00111 
00112 
00113 WN *
00114 ANL_REGION_CONSTRUCT::_Last_Region_Stmt()
00115 {
00116    WN *base = _region;
00117    ANL_SRCPOS basepos(_region);
00118 
00119    while (WN_next(base) != NULL && ANL_SRCPOS(WN_next(base)) <= basepos)
00120       base = WN_next(base);
00121    return base;
00122 } //ANL_REGION_CONSTRUCT::_Last_Region_Stmt
00123 
00124 
00125 void 
00126 ANL_REGION_CONSTRUCT::_Region_Srcpos_Range(ANL_SRCPOS *min, ANL_SRCPOS *max)
00127 {
00128    // Get the source-position range for the region, including associated
00129    // pragmas and loop initialization statements (which may have been moved
00130    // in front of the region by the compiler front-end).
00131    //
00132    // If this is an OMP region, there may be an NOWAIT/END_MARKER
00133    // which provides the line number of the end construct.  However,
00134    // we rely on the more general algorithm, which should also yield
00135    // correct results in the event of a WN_PRAGMA_PARALLEL_END,
00136    // WN_PRAGMA_END_MARKER or WN_PRAGMA_NOWAIT pragma.
00137    //
00138    WN        *end_stmt = NULL;
00139    WN        *first_stmt = _First_Region_Stmt();
00140    WN        *last_stmt = _Last_Region_Stmt();
00141    ANL_SRCPOS minpos(first_stmt);
00142    ANL_SRCPOS maxpos(last_stmt);
00143 
00144    // Start out with the top-level stmts (at same nesting level as the
00145    // region) as a first approximation, looking only at the stmts
00146    // within the region.
00147    //
00148    for (WN *stmt = first_stmt; 
00149         stmt != NULL && WN_prev(stmt) != last_stmt;
00150         stmt = WN_next(stmt))
00151    {
00152       Adjust_Srcpos_Range(stmt, &minpos, &maxpos);
00153    }
00154 
00155    // See if we have an end-marker.
00156    //
00157    for (end_stmt = WN_first(WN_region_pragmas(_region));
00158         (end_stmt != NULL                              && 
00159          WN_pragma(end_stmt) != WN_PRAGMA_PARALLEL_END &&
00160          WN_pragma(end_stmt) != WN_PRAGMA_END_MARKER   &&
00161          (WN_pragma(end_stmt) != WN_PRAGMA_NOWAIT ||
00162           _func_entry->Pu_Translator()->Language_is_C()));
00163         end_stmt = WN_next(end_stmt));
00164 
00165    // If the region does not have a clearly marked END, then consider
00166    // it to extend up till the next statement (if one is present).
00167    //
00168    if (end_stmt == NULL && WN_next(last_stmt) != NULL)
00169    {
00170       // Assume the end is just before the next statement.
00171       //
00172       ANL_SRCPOS next_min(WN_next(last_stmt));
00173       ANL_SRCPOS next_max(WN_next(last_stmt));
00174 
00175       Adjust_Srcpos_Range(WN_next(last_stmt), &next_min, &next_max);
00176       if (next_min > maxpos) // FALSE when the file-numbers are different!
00177       {
00178          next_min -= 1;
00179          maxpos = next_min;
00180       }
00181    }
00182    Is_True(end_stmt == NULL || maxpos == ANL_SRCPOS(end_stmt), 
00183            ("Unexpected maxpos in "
00184             "ANL_LOOP_CONSTRUCT::_Loop_Srcpos_Range"));
00185 
00186    *min = minpos;
00187    *max = maxpos;
00188  } // ANL_REGION_CONSTRUCT::_Region_Srcpos_Range
00189 
00190 
00191 WN *
00192 ANL_REGION_CONSTRUCT::_userEndParallel()
00193 {
00194    WN  *directive;
00195    WN  *end_directive = NULL;
00196 
00197    if (!_func_entry->Pu_Translator()->Language_is_C())
00198    {
00199       for (directive = WN_first(WN_region_pragmas(_region));
00200            end_directive == NULL && directive != NULL;
00201            directive = WN_next(directive))
00202       {
00203          if (WN_pragma(directive) == WN_PRAGMA_PARALLEL_END &&
00204              !WN_pragma_compiler_generated(directive)) 
00205             end_directive = directive;
00206          else if (WN_pragma(directive) == WN_PRAGMA_NOWAIT)
00207             end_directive = directive;
00208          else if (WN_pragma(directive) == WN_PRAGMA_END_MARKER)
00209             end_directive = directive;
00210       }
00211    }
00212    return end_directive;
00213 
00214 } // ANL_REGION_CONSTRUCT::_userEndParallel
00215 
00216 
00217 void
00218 ANL_REGION_CONSTRUCT::_Write_Region_Directive(ANL_CBUF *cbuf)
00219 {
00220   WN        *region_end_pragma = _userEndParallel();
00221   WN        *region_pragma = WN_first(WN_region_pragmas(_region));
00222   WN        *region_clause = WN_next(region_pragma);
00223   ANL_SRCPOS startpos, endpos;
00224   char      *p;
00225 
00226   _func_entry->Get_Pragma_Srcpos_Range(region_pragma, &startpos, &endpos);
00227 
00228   // The idir clause.
00229   //
00230   cbuf->Write_String("idir ");
00231   cbuf->Write_Int(_id);
00232   cbuf->Write_Char(' ');
00233   startpos.Write(cbuf);
00234   cbuf->Write_Char('-');
00235   endpos.Write(cbuf);
00236 
00237   cbuf->Append_Pragma_Preamble(_is_omp,FALSE);
00238 
00239   switch (_region_kind)
00240   {
00241   case ANL_PARALLEL_REGION:   
00242      cbuf->Write_String("PARALLEL ");
00243      break;
00244   case ANL_PSECTION_REGION:   
00245      if(_is_omp)
00246         p = "SECTIONS ";
00247      else
00248         p = "PSECTIONS ";
00249      cbuf->Write_String(p);
00250      break;
00251   case ANL_SINGLE_PROCESS_REGION:  
00252      if (_is_omp)
00253         p = "SINGLE "; 
00254      else
00255         p = "SINGLE PROCESS " ;
00256      cbuf->Write_String(p);
00257      break;
00258   case ANL_MASTER_PROCESS_REGION:  
00259      cbuf->Write_String("MASTER"); 
00260      break;
00261   default:
00262      cbuf->Write_String("<WHATREGION??> ");
00263      break;
00264   }
00265 
00266   // The list of clauses on an idir.
00267   //
00268   _func_entry->Pu_Translator()->ClauseList_To_String(cbuf, &region_clause);
00269   cbuf->Write_String("\n");
00270 
00271   if (region_end_pragma)
00272   {
00273      // Note: we should never get here for C language.
00274      //
00275      _func_entry->Get_Pragma_Srcpos_Range(region_end_pragma,
00276                                           &startpos, &endpos);
00277      cbuf->Write_String("edir ");
00278      cbuf->Write_Int(_id);
00279      cbuf->Write_String(" ");
00280      startpos = ANL_SRCPOS(region_end_pragma);
00281      startpos.Write(cbuf);
00282 
00283      cbuf->Append_Pragma_Preamble(_is_omp,FALSE);
00284 
00285      switch(_region_kind) 
00286      {
00287      case ANL_PSECTION_REGION:
00288         if(_is_omp)
00289            p = "END SECTIONS";
00290         else
00291            p = "END PSECTIONS";
00292         cbuf->Write_String(p);
00293         break ;
00294         
00295      case ANL_SINGLE_PROCESS_REGION:
00296         if(_is_omp)
00297            p = "END SINGLE";
00298         else
00299            p = "END SINGLE PROCESS";
00300         
00301         cbuf->Write_String(p);
00302         break;
00303          
00304      case ANL_MASTER_PROCESS_REGION:
00305         cbuf->Write_String("END MASTER");
00306         break;
00307         
00308      case ANL_PARALLEL_REGION:
00309         cbuf->Write_String("END PARALLEL");
00310         break;
00311          
00312      default:
00313         cbuf->Write_String("<WHAT END PRAGMA>");
00314         break;
00315      }
00316 
00317       
00318      if (_is_omp && 
00319          WN_pragma(region_end_pragma) == WN_PRAGMA_NOWAIT)
00320      {
00321         cbuf->Write_String(" NOWAIT ");
00322         _is_nowait = TRUE;
00323      }
00324 
00325      cbuf->Write_Char('\n');
00326   }
00327 } // ANL_REGION_CONSTRUCT::_Write_Region_Directive
00328 
00329 
00330 // =============== Public Member Functions ================
00331 // ========================================================
00332 
00333 ANL_REGION_CONSTRUCT::ANL_REGION_CONSTRUCT(WN             *region,
00334                                            INT32           construct_level,
00335                                            ANL_FUNC_ENTRY *func_entry,
00336                                            MEM_POOL       *pool):
00337                                            _region(region),
00338                                            _construct_level(construct_level),
00339                                            _func_entry(func_entry),
00340                                            _pool(pool)
00341 {
00342   WN * pragma;
00343 
00344   _region_kind = ANL_UNKNOWN_REGION;
00345   _id = -1;
00346   _is_nowait = FALSE ;
00347   _is_omp = FALSE ;
00348 
00349   // if this is a construct, give it a  Prompf_id. The Id is set
00350   // on the region, but as PSECTIONS,SINGLE_PROCESS etc, may
00351   // not be OMP directives and are considered (just) pragmas 
00352   // by w2f, the id goes on the pragma as well. PARALLEL_BEGIN 
00353   // is & was always a region, so doesn't need an id on the pragma.
00354 
00355   if (Is_ProMpf_Region_Construct(region))
00356     {
00357       pragma  = WN_first(WN_region_pragmas(region));
00358       _is_omp = WN_pragma_omp(pragma);
00359       _id     = _func_entry->Next_Construct_Id()->Post_Incr();
00360          
00361       func_entry->Set_Construct_Id(region, _id);
00362       func_entry->Set_Construct_Id(pragma, _id);
00363 
00364       switch(WN_pragma(pragma))
00365         {
00366         case WN_PRAGMA_PARALLEL_BEGIN:
00367           _region_kind = ANL_PARALLEL_REGION; 
00368           break;
00369           
00370         case WN_PRAGMA_PARALLEL_SECTIONS:
00371         case WN_PRAGMA_PSECTION_BEGIN:
00372           _region_kind = ANL_PSECTION_REGION; 
00373           break;
00374 
00375         case WN_PRAGMA_SINGLE_PROCESS_BEGIN:
00376           _region_kind = ANL_SINGLE_PROCESS_REGION; 
00377           break;
00378 
00379         case WN_PRAGMA_MASTER_BEGIN:
00380           _region_kind = ANL_MASTER_PROCESS_REGION; 
00381           break;
00382         }
00383     }
00384 } // ANL_REGION_CONSTRUCT::ANL_REGION_CONSTRUCT
00385 
00386 
00387 WN *
00388 ANL_REGION_CONSTRUCT::Next_Stmt()
00389 {
00390    WN *last_stmt = _Last_Region_Stmt();
00391    return WN_next(last_stmt);
00392 } // ANL_REGION_CONSTRUCT::Next_Stmt
00393 
00394 
00395 void
00396 ANL_REGION_CONSTRUCT::Write(ANL_CBUF *cbuf)
00397 {
00398   if (_region_kind != ANL_UNKNOWN_REGION)
00399     {
00400       ANL_CBUF    varlist_cbuf(_pool);
00401       ANL_CBUF    nested_cbuf(_pool);
00402       ANL_SRCPOS  min_srcpos;
00403       ANL_SRCPOS  max_srcpos;
00404       ANL_VARLIST varlist(_pool, _func_entry);
00405       WN         *first_stmt = _First_Region_Stmt();
00406       WN         *last_stmt = _Last_Region_Stmt();
00407       char       *p;
00408 
00409       // Write out the construct header
00410       //
00411       _Region_Srcpos_Range(&min_srcpos, &max_srcpos);
00412 
00413       cbuf->Append_Pragma_Preamble(_is_omp,TRUE);
00414       switch (_region_kind) 
00415         {
00416         case ANL_PARALLEL_REGION:
00417           cbuf->Write_String("pregion ");
00418           cbuf->Write_Int(_id);
00419           cbuf->Write_String(" \"parallel region\"");
00420           break;
00421           
00422         case ANL_PSECTION_REGION:
00423           cbuf->Write_String("psections ");
00424           cbuf->Write_Int(_id);
00425           cbuf->Write_String(" \"parallel sections\"");
00426           break;
00427 
00428         case ANL_SINGLE_PROCESS_REGION:
00429           if (_is_omp) 
00430             p = "single ";
00431           else
00432             p = "single_proc ";
00433           cbuf->Write_String(p);
00434           cbuf->Write_Int(_id);
00435           cbuf->Write_String(" \"single processor section\"");
00436           break;
00437 
00438         case ANL_MASTER_PROCESS_REGION:
00439           cbuf->Write_String("master ");
00440           cbuf->Write_Int(_id);
00441           cbuf->Write_String(" \"master processor section\"");
00442           break;
00443 
00444         default:
00445           cbuf->Write_String(" <WHATREGION??>");
00446           break;
00447         }
00448       cbuf->Write_String(" range ");
00449       min_srcpos.Write(cbuf);
00450       cbuf->Write_Char('-');
00451       max_srcpos.Write(cbuf);
00452       cbuf->Write_Char('\n');
00453 
00454       // Write out the region directives
00455       //
00456       _Write_Region_Directive(cbuf);
00457 
00458       // Determine variable references within the statements belonging to the
00459       // loop, and write them out to a temporary buffer.
00460       //
00461       for (WN *stmt = first_stmt;
00462            stmt != NULL && WN_prev(stmt) != last_stmt;
00463            stmt = WN_next(stmt))
00464       {
00465          varlist.Insert_Var_Refs(stmt);
00466       }
00467       varlist.Write(&varlist_cbuf, _id);
00468       varlist_cbuf.Write_Char('\n');
00469 
00470       // Write nested constructs to a temporary buffer.
00471       //
00472       _func_entry->
00473          Emit_Nested_Original_Constructs(&nested_cbuf,
00474                                          WN_first(WN_region_body(_region)),
00475                                          WN_last(WN_region_body(_region)));
00476 
00477       // Write out any applicable <dir> entries (i.e. those that were
00478       // not attributed to nested constructs).
00479       //
00480       _func_entry->
00481          Emit_Dir_Entries(cbuf, _id, _construct_level,
00482                           &ANL_REGION_CONSTRUCT::Is_Valid_Dir);
00483 
00484       // Write the varlist and nested constructs.
00485       //
00486       if (varlist_cbuf.Size() > 0)
00487          cbuf->Write_String(varlist_cbuf.Chars());
00488       if (nested_cbuf.Size() > 0)
00489          cbuf->Write_String(nested_cbuf.Chars());
00490 
00491       // Finish writing the construct descriptor to buffer
00492       //
00493 
00494       cbuf->Append_Pragma_Preamble(_is_omp,TRUE);
00495       switch (_region_kind) 
00496         {
00497         case ANL_PARALLEL_REGION:
00498           cbuf->Write_String("end_pregion ");
00499           break;
00500           
00501         case ANL_PSECTION_REGION:
00502           cbuf->Write_String("end_psections ");
00503           break ;
00504 
00505         case ANL_SINGLE_PROCESS_REGION:
00506           if (_is_omp)
00507             p = "end_single ";
00508           else
00509             p = "end_single_proc ";
00510           cbuf->Write_String(p);
00511           break ;
00512 
00513         case ANL_MASTER_PROCESS_REGION:
00514          cbuf->Write_String("end_master ");
00515          break;
00516 
00517         default:
00518           cbuf->Write_String("<what_end??> ");
00519         }
00520 
00521       if (_is_nowait)
00522         cbuf->Write_String("nowait ");
00523 
00524       cbuf->Write_Int(_id);
00525       cbuf->Write_String("\n"); // Start next construct on a new line
00526    }
00527 } // ANL_REGION_CONSTRUCT::Write
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines