Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
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, ®ion_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