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
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 #ifndef opt_alias_class_INCLUDED
00111 #define opt_alias_class_INCLUDED "opt_alias_class.h"
00112
00113 #include "cxx_memory.h"
00114 #include "cxx_template.h"
00115 #include "errors.h"
00116 #include "tracing.h"
00117 #include "opt_defs.h"
00118 #include "opt_union_find.h"
00119 #include "opt_wn.h"
00120 #include "id_map.h"
00121 #ifndef opt_points_to_INCLUDED
00122 #include "opt_points_to.h"
00123 #endif
00124
00125 extern "C" {
00126 #include "bitset.h"
00127 }
00128
00129 using idmap::ID_MAP;
00130
00131
00132
00133
00134
00135
00136
00137 template <class T>
00138 class SLIST_RECYCLE {
00139 private:
00140 SLIST_RECYCLE<T> *_next;
00141 T _node;
00142 public:
00143 SLIST_RECYCLE(const T node, SLIST_RECYCLE<T> *next) :
00144 _node(node), _next(next) { }
00145
00146 void Set_next(SLIST_RECYCLE<T> *next) { _next = next; }
00147 void Set_node(const T node) { _node = node; }
00148 SLIST_RECYCLE<T> *Next(void) const { return _next; }
00149 T Node(void) const { return _node; }
00150
00151 SLIST_RECYCLE<T> *Merge(SLIST_RECYCLE<T> *that) {
00152 if (that == NULL)
00153 return this;
00154 SLIST_RECYCLE<T> *curr, *next = that;
00155 do {
00156 curr = next;
00157 next = curr->Next();
00158 } while (next != NULL);
00159 curr->Set_next(this);
00160 return that;
00161 }
00162 };
00163
00164
00165 template <class T>
00166 class SLIST_RECYCLE_HOME {
00167 private:
00168 MEM_POOL *_pool;
00169 SLIST_RECYCLE<T> *_available;
00170 public:
00171 SLIST_RECYCLE_HOME(MEM_POOL *pool) :
00172 _pool(pool), _available(NULL) { }
00173
00174 ~SLIST_RECYCLE_HOME() {
00175
00176
00177
00178
00179
00180
00181
00182 }
00183
00184 SLIST_RECYCLE<T> *Produce(T node, SLIST_RECYCLE<T> *next) {
00185 SLIST_RECYCLE<T> *result;
00186 if (_available == NULL) {
00187 result = CXX_NEW(SLIST_RECYCLE<T>(node, next), _pool);
00188 } else {
00189 result = _available;
00190 _available = _available->Next();
00191 result->Set_node(node);
00192 result->Set_next(next);
00193 }
00194 return result;
00195 }
00196
00197 SLIST_RECYCLE<T> *Receive(SLIST_RECYCLE<T> *head) {
00198 SLIST_RECYCLE<T> *next = head->Next();
00199 head->Set_next(_available);
00200 _available = head;
00201 return next;
00202 }
00203 };
00204
00205
00206
00207
00208
00209 class ALIAS_CLASS_REP;
00210
00211 class ALIAS_CLASS_MEMBER : public U_F_ELEMENT<ALIAS_CLASS_MEMBER> {
00212 private:
00213 typedef enum {
00214 ACM_NONE,
00215 ACM_BASE,
00216 ACM_WN,
00217 ACM_LDA
00218 } ACM_KIND;
00219
00220 ACM_KIND _kind;
00221 union {
00222 IDTYPE _base_id;
00223 WN *_wn;
00224 };
00225
00226 void Set_kind(ACM_KIND kind) { _kind = kind; }
00227
00228 public:
00229 ALIAS_CLASS_MEMBER(IDTYPE base_id) :
00230 _kind(ACM_BASE), _base_id(base_id)
00231 { }
00232
00233 ALIAS_CLASS_MEMBER(WN *wn) :
00234 _kind(ACM_WN), _wn(wn)
00235 { }
00236
00237 ALIAS_CLASS_MEMBER(IDTYPE base_id, ALIAS_CLASS_REP *acr) :
00238 _kind(ACM_BASE), _base_id(base_id)
00239 { Put_in_set((U_F_REP<ALIAS_CLASS_MEMBER> *) acr); }
00240
00241 ALIAS_CLASS_MEMBER(void) :
00242 _kind(ACM_NONE), _base_id(0)
00243 { }
00244
00245 IDTYPE Base_id(void) const
00246 {
00247 Is_True(_kind == ACM_BASE,
00248 ("ALIAS_CLASS_MEMBER::Base_id: ACM must be BASE kind"));
00249 return _base_id;
00250 }
00251
00252 void Set_base_id(IDTYPE base_id)
00253 {
00254 Is_True(_kind == ACM_NONE,
00255 ("ALIAS_CLASS_MEMBER::Set_base_id: ACM kind must not be set"));
00256 Set_kind(ACM_BASE);
00257 _base_id = base_id;
00258 }
00259
00260 WN *Wn(void) const
00261 {
00262 Is_True(_kind == ACM_WN,
00263 ("ALIAS_CLASS_MEMBER::Wn: ACM must be WN kind"));
00264 return _wn;
00265 }
00266
00267 void Set_wn(WN *wn)
00268 {
00269 Is_True(_kind == ACM_NONE,
00270 ("ALIAS_CLASS_MEMBER::Set_wn: ACM kind must not be set"));
00271 Set_kind(ACM_WN);
00272 _wn = wn;
00273 }
00274
00275 void Set_lda_kind(void)
00276 { Set_kind(ACM_LDA); }
00277
00278 BOOL Is_LDA_kind(void) const
00279 { return _kind == ACM_LDA; }
00280
00281 void Print(FILE *) const;
00282
00283
00284
00285
00286
00287
00288
00289 ALIAS_CLASS_REP *Alias_class(void)
00290 { return (ALIAS_CLASS_REP *) Find(); }
00291 };
00292
00293
00294 typedef slist<ALIAS_CLASS_MEMBER *,
00295 mempool_allocator<ALIAS_CLASS_MEMBER *> >
00296 ALIAS_CLASS_MEMBER_LIST;
00297
00298
00299
00300
00301 typedef SLIST_RECYCLE<ALIAS_CLASS_MEMBER *> *PENDING_LIST;
00302 typedef SLIST_RECYCLE_HOME<ALIAS_CLASS_MEMBER *> PENDING_LIST_HOME;
00303
00304 class ALIAS_CLASSIFICATION;
00305
00306
00307 class ALIAS_CLASS_REP : public U_F_REP<ALIAS_CLASS_MEMBER> {
00308 friend class ALIAS_CLASSIFICATION;
00309 #if Is_True_On
00310 friend void print_table(void);
00311 #endif
00312
00313 enum ACR_FLAGS {
00314 ACR_FLAG_NONE = 0x0,
00315 ACR_FLAG_WRITABLE_BY_CALL = 0x1,
00316 ACR_FLAG_ALLOCA_CLASS = 0x2,
00317 };
00318
00319 private:
00320 static IDTYPE _last_id_used;
00321 static BOOL _structure_not_frozen;
00322
00323 IDTYPE _id;
00324
00325
00326
00327
00328
00329
00330
00331
00332 ALIAS_CLASS_MEMBER *_member_of_class_pointed_to;
00333
00334 PENDING_LIST _pending;
00335 mUINT32 _flags;
00336
00337 #if Is_True_On
00338 BOOL _lda_class;
00339 #endif
00340
00341 public:
00342 ALIAS_CLASS_REP(void) :
00343 #if Is_True_On
00344 _lda_class(FALSE),
00345 #endif
00346 _member_of_class_pointed_to(NULL), _pending(NULL),
00347 _flags(ACR_FLAG_NONE), _id(++_last_id_used)
00348 {
00349 Is_True(_structure_not_frozen,
00350 ("ALIAS_CLASS_REP: Cannot construct with frozen structure"));
00351 }
00352
00353 IDTYPE Id(void) const { return _id; }
00354
00355 void Add_pending(ALIAS_CLASS_REP *, ALIAS_CLASSIFICATION &);
00356 void Merge_pending(ALIAS_CLASS_REP &);
00357 void Process_pending(ALIAS_CLASSIFICATION &);
00358 PENDING_LIST &Pending(void) { return _pending; }
00359 #ifdef KEY
00360 BOOL Pending_rep_match(ALIAS_CLASS_REP *);
00361 #endif
00362 void Join_object_class(ALIAS_CLASS_REP &,
00363 ALIAS_CLASSIFICATION &);
00364
00365 BOOL Is_pointer_class(void) const
00366 { return _member_of_class_pointed_to != NULL; }
00367
00368 ALIAS_CLASS_REP *Class_pointed_to(void) const
00369 {
00370 Is_True(_member_of_class_pointed_to == NULL ||
00371 _member_of_class_pointed_to->Alias_class() != NULL,
00372 ("ALIAS_CLASS_REP::Class_pointed_to: inconsistent "
00373 "data structure"));
00374 return (_member_of_class_pointed_to != NULL ?
00375 _member_of_class_pointed_to->Alias_class() :
00376 NULL);
00377 }
00378
00379 void Set_class_pointed_to(ALIAS_CLASS_REP *const cpt)
00380 {
00381 Is_True(cpt->Representative() != NULL,
00382 ("object class has no representative"));
00383 #if 0
00384 if (Pending() != NULL) {
00385 fprintf(TFile, "\n");
00386 Print(TFile);
00387 fprintf(TFile, " is becoming a pointer. Should see pending:\n");
00388 }
00389 #endif
00390 _member_of_class_pointed_to = cpt->Representative();
00391 }
00392
00393 void Set_writable_by_call(void)
00394 { _flags |= ACR_FLAG_WRITABLE_BY_CALL; }
00395
00396 BOOL Writable_by_call(void) const
00397 { return _flags & ACR_FLAG_WRITABLE_BY_CALL; }
00398
00399 void Set_alloca_class(void)
00400 { _flags |= ACR_FLAG_ALLOCA_CLASS; }
00401
00402 BOOL Alloca_class(void) const
00403 { return _flags & ACR_FLAG_ALLOCA_CLASS; }
00404
00405 void Print(FILE *,
00406 ALIAS_CLASS_REP *global_class = NULL) const;
00407 };
00408
00409
00410
00411
00412
00413
00414
00415
00416 class AC_PTR_OBJ_PAIR {
00417 private:
00418 ALIAS_CLASS_REP *_ref_class;
00419 ALIAS_CLASS_REP *_obj_class;
00420
00421 public:
00422 AC_PTR_OBJ_PAIR(void) : _ref_class(NULL), _obj_class(NULL)
00423 { }
00424
00425 AC_PTR_OBJ_PAIR(ALIAS_CLASS_REP *ref_class,
00426 ALIAS_CLASS_REP *obj_class) :
00427 _ref_class(ref_class), _obj_class(obj_class)
00428 {
00429 Is_True(ref_class == NULL ||
00430 ref_class->Class_pointed_to() == obj_class,
00431 ("AC_PTR_OBJ_PAIR: reference must point to object"));
00432 }
00433
00434 void Set_ref_class(ALIAS_CLASS_REP *ref_class)
00435 { _ref_class = ref_class; }
00436
00437 ALIAS_CLASS_REP *Ref_class(void) const
00438 { return _ref_class; }
00439
00440 void Set_obj_class(ALIAS_CLASS_REP *obj_class)
00441 { _obj_class = obj_class; }
00442
00443 ALIAS_CLASS_REP *Obj_class(void) const
00444 {
00445 Is_True(_ref_class == NULL ||
00446 _ref_class->Class_pointed_to() == _obj_class,
00447 ("AC_PTR_OBJ_PAIR::Obj_class: Reference must refer to object"));
00448 return _obj_class;
00449 }
00450 };
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498 typedef enum {
00499 AC_DESTINATION_OPT_STAB,
00500 AC_DESTINATION_ALIAS_MANAGER
00501 } AC_DESTINATION;
00502
00503
00504 class BASE_ID_MAP_ENTRY;
00505
00506
00507 class ALIAS_CLASSIFICATION {
00508 friend class ALIAS_CLASS_REP;
00509 friend class MERGE_NEST_REF_CLASSES;
00510
00511 private:
00512 AC_DESTINATION _destination;
00513 OPT_STAB *_opt_stab;
00514 ID_MAP<IDTYPE, ST_IDX> _st_idx_to_base_id_map;
00515 ID_MAP<const ALIAS_CLASS_REP *, IDTYPE> _ac_id_to_acr_map;
00516 DYN_ARRAY<BASE_ID_MAP_ENTRY *> _base_id_map;
00517 ID_MAP<IDTYPE, INT64> _preg_num_base_id_map;
00518 WN_MAP _memop_classification_map;
00519 WN_MAP _indir_classification_map;
00520 BOOL _memops_classified;
00521 MEM_POOL *_pool;
00522 BOOL _mem_pool_valid;
00523 BOOL _collapsed_nested_references;
00524 ALIAS_CLASS_MEMBER *_member_of_global_class;
00525
00526 ALIAS_CLASS_MEMBER_LIST _altered_non_points_to_parms;
00527 ALIAS_CLASS_MEMBER_LIST _alloca_memory_members;
00528
00529
00530 BS *_inaccessible_to_callees;
00531
00532
00533
00534 ALIAS_CLASS_REP *_const_addr_class;
00535
00536 PENDING_LIST_HOME _pending_list_home;
00537
00538 BOOL _tracing;
00539
00540
00541 BOOL Is_LDA_of_variable(const WN *) const;
00542
00543 ALIAS_CLASS_REP *Class_of_base_id_LDID(IDTYPE) const;
00544
00545 ALIAS_CLASS_REP *Class_of_base_id_LDA(IDTYPE) const;
00546
00547 WN *Classify_wn_and_kids(WN *);
00548
00549 AC_PTR_OBJ_PAIR Classify_lhs_of_store(WN *);
00550 BOOL Expr_may_contain_pointer (WN* const expr);
00551 AC_PTR_OBJ_PAIR Classify_deref_of_expr(WN *, BOOL);
00552
00553 void Set_collapsed_nested_references(void)
00554 { _collapsed_nested_references = TRUE; }
00555 BOOL Collapsed_nested_references(void)
00556 { return _collapsed_nested_references; }
00557
00558 BOOL Assignment_may_xfer_pointer (WN* const);
00559 WN *Handle_assignment(WN *);
00560 WN *Handle_call(WN *);
00561 void Handle_call_of_nested_PU(ST *);
00562 BOOL May_icall_nested_PU(const WN *, ST **);
00563
00564 BOOL WN_is_alloca_intrinsic(const WN *);
00565
00566 BOOL Callee_changes_no_points_to(const WN *, const WN *);
00567 BOOL Callee_returns_new_memory(const WN *);
00568 BOOL Stmt_stores_return_value(const WN *);
00569 BOOL Uses_no_return_value(const WN *);
00570
00571 WN_MAP Indir_classification_map(void) const
00572 { return _indir_classification_map; }
00573
00574 void Finalize_ac_map(WN *);
00575 void Finalize_ac_map_wn(WN *);
00576
00577 ALIAS_CLASS_REP *New_alias_class(ALIAS_CLASS_MEMBER *);
00578
00579 ALIAS_CLASS_MEMBER *New_alias_class_member(void);
00580 ALIAS_CLASS_MEMBER *New_alias_class_member(IDTYPE);
00581 ALIAS_CLASS_MEMBER *New_alias_class_member(WN *);
00582
00583 void Find_declared_base_and_offset(ST_IDX,
00584 ST_IDX &,
00585 INT64 &);
00586 IDTYPE New_base_id(const ST *, TY_IDX);
00587 IDTYPE ST_base_id(ST *, TY_IDX);
00588 IDTYPE Base_id(AUX_ID, TY_IDX);
00589 IDTYPE Base_id(ST *, INT64, TY_IDX);
00590 IDTYPE WN_base_id(const WN *);
00591 ID_MAP<IDTYPE, INT64> &Preg_num_base_id_map(void)
00592 { return _preg_num_base_id_map; }
00593
00594 ST *ST_of_wn(const WN *) const;
00595
00596 MEM_POOL *Pool(void) const { return _pool; }
00597
00598
00599
00600
00601
00602 PENDING_LIST Alloc_pending(ALIAS_CLASS_MEMBER *mbr, PENDING_LIST pdg)
00603 { return _pending_list_home.Produce(mbr, pdg); }
00604 PENDING_LIST Release_pending(PENDING_LIST pdg)
00605 { return _pending_list_home.Receive(pdg); }
00606
00607 void Merge_conditional(AC_PTR_OBJ_PAIR,
00608 AC_PTR_OBJ_PAIR);
00609
00610 ALIAS_CLASS_REP *Global_class(void) const
00611 { return _member_of_global_class->Alias_class(); }
00612
00613 ALIAS_CLASS_REP *Const_addr_class(void) const
00614 { return _const_addr_class; }
00615
00616 void Set_inaccessible_to_callees(BS *bs)
00617 { _inaccessible_to_callees = bs; }
00618
00619 OPT_STAB *Opt_stab(void) const { return _opt_stab; }
00620
00621 BOOL Tracing(void) const { return _tracing; }
00622
00623 WN_MAP Memop_classification_map(void) const
00624 { return _memop_classification_map; }
00625
00626 void Dump_wn_tree(FILE *fp, WN *wn) const
00627 {
00628 if (_destination == AC_DESTINATION_OPT_STAB) {
00629 fdump_tree_no_st(fp, wn);
00630 }
00631 else {
00632 fdump_tree(fp, wn);
00633 }
00634 }
00635
00636 void Dump_wn(FILE *fp, WN *wn) const
00637 {
00638 if (_destination == AC_DESTINATION_OPT_STAB) {
00639 fdump_wn_no_st(fp, wn);
00640 }
00641 else {
00642 fdump_wn(fp, wn);
00643 }
00644 }
00645
00646 public:
00647 ALIAS_CLASSIFICATION(OPT_STAB *, AC_DESTINATION, MEM_POOL *);
00648
00649 void Release_resources(void);
00650
00651 void Add_to_altered_non_points_to_parms(const ALIAS_CLASS_REP *const acr)
00652 {
00653 Is_True(acr->Representative() != NULL,
00654 ("ALIAS_CLASSIFICATION::Add_to_altered_non_points_to_parms: "
00655 "Representative must not be NULL"));
00656 _altered_non_points_to_parms.push_front(acr->Representative());
00657 }
00658
00659 ALIAS_CLASS_MEMBER_LIST &Altered_non_points_to_parms(void)
00660 { return _altered_non_points_to_parms; }
00661
00662 BS *Inaccessible_to_callees(void) const
00663 { return _inaccessible_to_callees; }
00664
00665 void Classify_memops(WN *);
00666
00667 IDTYPE Alias_class(const WN *) const;
00668
00669 void Copy_alias_class(const WN *, WN *);
00670
00671 BOOL Non_alloca_memop(IDTYPE) const;
00672
00673 BOOL Writable_by_call(IDTYPE) const;
00674
00675 void Print(FILE *) const;
00676 };
00677 #endif