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_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