00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "anl_common.h"
00039 #include "anl_diagnostics.h"
00040 #include "anl_file_mngr.h"
00041 #include "w2cf_translator.h"
00042 #include "anl_func_entry.h"
00043 #include "anl_varlist.h"
00044
00045 extern ANL_DIAGNOSTICS *Anl_Diag;
00046
00047
00048
00049
00050
00051
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 }
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');
00083 else
00084 cbuf->Write_Char('V');
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');
00102 break;
00103
00104 default:
00105 cbuf->Write_Char('U');
00106 break;
00107 }
00108 }
00109
00110
00111
00112
00113
00114 mUINT32
00115 ANL_VARLIST::_Binary_Search(INT32 id, mUINT32 from, mUINT32 till)
00116 {
00117
00118
00119
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 }
00144
00145
00146 UINT32
00147 ANL_VARLIST::_Get_Io_Item_Lda_Access_Status(WN *io_item)
00148 {
00149 UINT32 status;
00150
00151
00152
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
00176
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;
00198 break;
00199
00200 case IOS_DECODE:
00201 status = ANL_VAR_WRITTEN;
00202 break;
00203
00204 default:
00205 status = ANL_VAR_READ | ANL_VAR_WRITTEN;
00206 break;
00207 }
00208 }
00209 return status;
00210 }
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;
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;
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;
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;
00251 break;
00252
00253 case OPR_SUB:
00254 case OPR_ADD:
00255 status = _Get_Lda_Access_Status(parent);
00256 break;
00257
00258 case OPR_PARM:
00259
00260
00261
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;
00273 }
00274 break;
00275
00276 case OPR_IO_ITEM:
00277
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
00291
00292 status = ANL_VAR_READ | ANL_VAR_WRITTEN;
00293 break;
00294 }
00295 return status;
00296 }
00297
00298
00299
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
00311
00312 for (alias = _alias;
00313 alias != var && alias != this;
00314 alias = alias->_alias);
00315
00316 if (alias == this)
00317 {
00318
00319
00320 ANL_VAR *next = _alias;
00321
00322 _alias = var;
00323 for (alias = var->_alias;
00324 alias->_alias != var;
00325 alias = alias->_alias);
00326 alias->_alias = next;
00327 }
00328 }
00329 }
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 }
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 }
00364
00365
00366 ANL_VAR *
00367 ANL_VARLIST::Find(ST *st)
00368 {
00369
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 }
00381
00382
00383 ANL_VAR *
00384 ANL_VARLIST::Find_or_Insert(ST *st)
00385 {
00386
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
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 }
00421
00422
00423 void
00424 ANL_VARLIST::Insert_Var_Refs(WN *subtree)
00425 {
00426
00427
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
00448
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
00468
00469
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
00478
00479
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;
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;
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;
00537 }
00538 }
00539 }
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
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
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 }
00587