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 #define __STDC_LIMIT_MACROS
00040 #include <stdint.h>
00041 #include <ext/hash_set>
00042 #include <ext/functional>
00043 using __gnu_cxx::identity;
00044 using __gnu_cxx::hashtable;
00045 using __gnu_cxx::hash_multiset;
00046 using std::equal_to;
00047
00048 #include "defs.h"
00049 #include "symtab.h"
00050
00051 #include "ipc_symtab_merge.h"
00052 #include "ipc_ty_hash.h"
00053 #include "config_ipa.h"
00054
00055
00056
00057 static TY_IDX_MAP* ty_map;
00058 static SYMSTR_IDX_MAP* str_map;
00059
00060
00061 static const TY* ty_table;
00062 static const FLD* fld_table;
00063 static const ARB* arb_table;
00064 static const TYLIST* tylist_table;
00065
00066 static const TY* ty_to_be_inserted;
00067
00068 #include <ext/hash_map>
00069 using __gnu_cxx::hash_map;
00070 extern hash_map <STR_IDX, TY_INDEX, __new_hash::hash<STR_IDX>, std::equal_to<STR_IDX> > struct_by_name_idx;
00071
00072 static inline TY_IDX
00073 Get_Kid_TY_IDX (TY_IDX ty_idx)
00074 {
00075 TY_IDX kid_idx = ty_map->map_[TY_IDX_index (ty_idx)];
00076 if (TY_Inserted (kid_idx))
00077 Clean_TY_IDX (kid_idx);
00078 Is_True (Valid_TY_IDX (kid_idx), ("Invalid entry in ty_map"));
00079 return Replace_TY_IDX_index (ty_idx, kid_idx);
00080 }
00081
00082
00083
00084
00085
00086
00087
00088
00089 static inline BOOL
00090 operator== (const TY& ty1, const TY& ty2)
00091 {
00092 const UINT64* p1 = reinterpret_cast<const UINT64*> (&ty1);
00093 const UINT64* p2 = reinterpret_cast<const UINT64*> (&ty2);
00094
00095 return (p1 == p2 || (p1[0] == p2[0] &&
00096 p1[1] == p2[1] &&
00097 p1[2] == p2[2] &&
00098 ty1.Pu_flags() == ty2.Pu_flags()));
00099 }
00100
00101
00102 namespace
00103 {
00104
00105
00106 struct TY_EXTRACT_KEY {
00107 const TY& operator() (TY_IDX ty_idx) const {
00108 if (ty_idx == (TY_IDX) -1)
00109 return *ty_to_be_inserted;
00110 else
00111 return Ty_Table[ty_idx];
00112 }
00113 };
00114
00115 struct TY_HASH {
00116 size_t operator() (const TY& key) const {
00117 const UINT64 *p = reinterpret_cast<const UINT64*> (&key);
00118 UINT64 tmp;
00119 if (IPA_Enable_Old_Type_Merge) {
00120 tmp = (p[0] ^ p[1]) + p[2] + key.Pu_flags();
00121 }
00122 else {
00123
00124
00125
00126 tmp = (p[0] ^ p[1]) + p[2] + TY_IDX_without_attribute(key.Pu_flags());
00127
00128 if (TY_anonymous(key))
00129 tmp -= p[2];
00130 }
00131 return (size_t) (tmp ^ (tmp >> 32));
00132 }
00133 };
00134
00135
00136 struct TY_IS_EQUIVALENT {
00137 BOOL operator() (const TY &k1, const TY &k2) const {
00138
00139
00140 if (k1.size != k2.size ||
00141 k1.kind != k2.kind ||
00142 k1.mtype != k2.mtype ||
00143 k1.flags != k2.flags ||
00144 k1.u1.fld != k2.u1.fld)
00145 return FALSE;
00146
00147
00148 if (TY_kind(k1) == KIND_STRUCT || TY_kind(k1) == KIND_ARRAY) {
00149 if (TY_anonymous(k1) || TY_anonymous(k2)) {
00150 if (TY_anonymous(k1) != TY_anonymous(k2))
00151 return FALSE;
00152 }
00153 else {
00154 if (k1.name_idx != k2.name_idx)
00155 return FALSE;
00156 }
00157 }
00158 if (k1.u2.etype == k2.u2.etype)
00159 return TRUE;
00160
00161
00162
00163 return TY_kind(k1) == KIND_POINTER &&
00164 TY_IDX_without_attribute(k1.u2.pointed)
00165 == TY_IDX_without_attribute(k2.u2.pointed);
00166 }
00167 };
00168 }
00169
00170
00171 typedef hashtable<TY_IDX, TY, TY_HASH, TY_EXTRACT_KEY, equal_to<TY>,
00172 mempool_allocator<TY_IDX> > TY_HASH_TABLE;
00173
00174
00175 typedef hashtable<TY_IDX, TY, TY_HASH, TY_EXTRACT_KEY, TY_IS_EQUIVALENT,
00176 mempool_allocator<TY_IDX> > NEW_TY_HASH_TABLE;
00177
00178
00179
00180
00181 namespace
00182 {
00183
00184 template <class IDX>
00185 inline BOOL Is_File_Idx (IDX idx) {
00186 return (idx & 0x80000000);
00187 }
00188
00189 template <class IDX>
00190 inline IDX Get_Idx (IDX idx) {
00191 return (idx & ~0x80000000);
00192 }
00193
00194 template <class IDX>
00195 inline IDX File_Idx (IDX idx) {
00196 return (idx | 0x80000000);
00197 }
00198 }
00199
00200 inline BOOL
00201 FLD_is_anonymous (const FLD *fld) { return fld->flags & FLD_IS_ANONYMOUS; }
00202
00203 inline BOOL
00204 FLD_last_field (const FLD *fld) { return fld->flags & FLD_LAST_FIELD; }
00205
00206
00207
00208
00209 namespace
00210 {
00211
00212
00213
00214 struct FLD_HASH {
00215 size_t operator() (FLD_IDX key) const {
00216 size_t value = 0;
00217 if (Is_File_Idx (key)) {
00218 const FLD* fld = fld_table + Get_Idx (key);
00219 if (IPA_Enable_Old_Type_Merge) {
00220 do {
00221 value +=
00222 Get_Kid_TY_IDX (fld->type) + (*str_map)[fld->name_idx];
00223 } while ((fld++->flags & FLD_LAST_FIELD) == 0);
00224 }
00225 else {
00226 do {
00227 TY_IDX mapped_ty_idx = Get_Kid_TY_IDX(fld->type);
00228
00229
00230 value += TY_IDX_without_attribute(mapped_ty_idx);
00231 if (!FLD_is_anonymous(fld))
00232 value += (*str_map)[fld->name_idx];
00233 } while ((fld++->flags & FLD_LAST_FIELD) == 0);
00234 }
00235 return value;
00236 } else {
00237 FLD_HANDLE fld (key);
00238 FLD_ITER fld_iter = Make_fld_iter (fld);
00239 do {
00240 fld = fld_iter;
00241 if (IPA_Enable_Old_Type_Merge) {
00242 value += FLD_type (fld) + FLD_name_idx (fld);
00243 }
00244 else {
00245
00246
00247 value += TY_IDX_without_attribute(FLD_type (fld));
00248 if (!FLD_is_anonymous(fld))
00249 value += FLD_name_idx(fld);
00250 }
00251 ++fld_iter;
00252 } while (! FLD_last_field (fld));
00253 return value;
00254 }
00255 }
00256
00257 };
00258
00259
00260
00261 struct FLD_IS_EQUIVALENT {
00262 BOOL operator() (FLD_IDX k1, FLD_IDX k2) const {
00263
00264 if (k1 == k2)
00265 return TRUE;
00266
00267 if (!Is_File_Idx (k1) && !Is_File_Idx (k2))
00268 return k1 == k2;
00269
00270
00271 Is_True (!Is_File_Idx (k1) || !Is_File_Idx (k2),
00272 ("Invalid FLD_IDX in fld hash table"));
00273
00274 FLD_HANDLE merged_fld;
00275 const FLD* new_fld;
00276
00277 if (Is_File_Idx (k1)) {
00278 new_fld = fld_table + Get_Idx (k1);
00279 merged_fld = FLD_HANDLE (k2);
00280 } else {
00281 new_fld = fld_table + Get_Idx (k2);
00282 merged_fld = FLD_HANDLE (k1);
00283 }
00284
00285 FLD_ITER fld_iter = Make_fld_iter (merged_fld);
00286 do {
00287 merged_fld = fld_iter;
00288
00289 if (IPA_Enable_Old_Type_Merge) {
00290 if (FLD_type (merged_fld) != (*ty_map)[new_fld->type] ||
00291 FLD_name_idx (merged_fld) != (*str_map)[new_fld->name_idx])
00292 return FALSE;
00293 }
00294 else {
00295 if (TY_IDX_without_attribute(FLD_type (merged_fld)) !=
00296 TY_IDX_without_attribute((*ty_map)[new_fld->type]))
00297 return FALSE;
00298 if (FLD_is_anonymous(merged_fld) || FLD_is_anonymous((FLD *)new_fld)) {
00299 if (FLD_is_anonymous(merged_fld) != FLD_is_anonymous((FLD *)new_fld))
00300 return FALSE;
00301 }
00302 else {
00303 if (FLD_name_idx (merged_fld) != (*str_map)[new_fld->name_idx])
00304 return FALSE;
00305 }
00306 }
00307
00308 const UINT64* p1 = reinterpret_cast<const UINT64*> (new_fld);
00309 const UINT64* p2 =
00310 reinterpret_cast<const UINT64*> (merged_fld.Entry ());
00311
00312 if (p1[1] != p2[1] || p1[2] != p2[2])
00313 return FALSE;
00314
00315 ++fld_iter;
00316 ++new_fld;
00317 } while (! FLD_last_field (merged_fld));
00318
00319 return TRUE;
00320 }
00321 };
00322 }
00323
00324 typedef hashtable<FLD_IDX, FLD_IDX, FLD_HASH, identity<FLD_IDX>,
00325 FLD_IS_EQUIVALENT, mempool_allocator<FLD_IDX> > FLD_HASH_TABLE;
00326
00327
00328
00329
00330
00331 namespace
00332 {
00333
00334
00335
00336 struct ARB_HASH {
00337 size_t operator() (ARB_IDX key) const {
00338 size_t value = 0;
00339 if (Is_File_Idx (key)) {
00340 const ARB* arb = arb_table + Get_Idx (key);
00341 UINT dim = arb->dimension;
00342 value = arb->flags + dim;
00343 for (UINT i = 0; i < dim; ++i) {
00344 value += (arb->Lbnd_val () + arb->Ubnd_val () +
00345 arb->Stride_val ()) << i;
00346 #ifdef KEY // bug 9181
00347 ++arb;
00348 #endif
00349 }
00350 } else {
00351 ARB_ITER arb_iter = Make_arb_iter (ARB_HANDLE (key));
00352 UINT dim = ARB_dimension (arb_iter);
00353 value = ARB_flags (arb_iter) + dim;
00354 for (UINT i = 0; i < dim; ++i) {
00355 ARB_HANDLE arb (arb_iter);
00356 ++arb_iter;
00357 value += (ARB_lbnd_val (arb) + ARB_ubnd_val (arb) +
00358 ARB_stride_val (arb)) << i;
00359 }
00360 }
00361 return ~value;
00362 }
00363 };
00364
00365
00366
00367 struct ARB_IS_EQUIVALENT {
00368 BOOL operator() (ARB_IDX k1, ARB_IDX k2) const {
00369
00370 if (k1 == k2)
00371 return TRUE;
00372
00373 if (!Is_File_Idx (k1) && !Is_File_Idx (k2))
00374 return k1 == k2;
00375
00376
00377 Is_True (!Is_File_Idx (k1) || !Is_File_Idx (k2),
00378 ("Invalid ARB_IDX in arb hash table"));
00379
00380 ARB_HANDLE merged_arb;
00381 const ARB* new_arb;
00382
00383 if (Is_File_Idx (k1)) {
00384 new_arb = arb_table + Get_Idx (k1);
00385 merged_arb = ARB_HANDLE (k2);
00386 } else {
00387 new_arb = arb_table + Get_Idx (k2);
00388 merged_arb = ARB_HANDLE (k1);
00389 }
00390
00391 ARB_ITER arb_iter = Make_arb_iter (merged_arb);
00392 UINT dim = new_arb->dimension;
00393 for (UINT i = 0; i < dim; ++i, ++arb_iter) {
00394 merged_arb = arb_iter;
00395
00396 const UINT64* p1 =
00397 reinterpret_cast<const UINT64*> (new_arb + i);
00398 const UINT64* p2 =
00399 reinterpret_cast<const UINT64*> (merged_arb.Entry ());
00400
00401 if (p1[0] != p2[0] ||
00402 p1[1] != p2[1] ||
00403 p1[2] != p2[2] ||
00404 p1[3] != p2[3])
00405 return FALSE;
00406
00407 }
00408
00409 return TRUE;
00410 }
00411 };
00412 }
00413
00414
00415 typedef hashtable<ARB_IDX, ARB_IDX, ARB_HASH, identity<ARB_IDX>,
00416 ARB_IS_EQUIVALENT, mempool_allocator<ARB_IDX> > ARB_HASH_TABLE;
00417
00418
00419
00420
00421
00422 namespace
00423 {
00424
00425
00426
00427 struct TYLIST_HASH {
00428 size_t operator() (TYLIST_IDX key) const {
00429 size_t value = 0;
00430 if (Is_File_Idx (key)) {
00431 const TYLIST* tylist = tylist_table + Get_Idx (key);
00432 if (IPA_Enable_Old_Type_Merge) {
00433 while (*tylist != 0) {
00434 value += Get_Kid_TY_IDX (*tylist);
00435 ++tylist;
00436 }
00437 }
00438 else {
00439 while (*tylist != 0) {
00440 value += TY_IDX_without_attribute(Get_Kid_TY_IDX(*tylist));
00441 ++tylist;
00442 }
00443 }
00444 } else {
00445 TYLIST_ITER tylist_iter = Make_tylist_iter (key);
00446 if (IPA_Enable_Old_Type_Merge) {
00447 while (*tylist_iter != 0) {
00448 value += *tylist_iter;
00449 ++tylist_iter;
00450 }
00451 }
00452 else {
00453 while (*tylist_iter != 0) {
00454 value += TY_IDX_without_attribute(*tylist_iter);;
00455 ++tylist_iter;
00456 }
00457 }
00458 }
00459 return (~value);
00460 }
00461 };
00462
00463
00464
00465 struct TYLIST_IS_EQUIVALENT {
00466 BOOL operator() (TYLIST_IDX k1, TYLIST_IDX k2) const {
00467
00468 if (k1 == k2)
00469 return TRUE;
00470
00471 if (!Is_File_Idx (k1) && !Is_File_Idx (k2))
00472 return k1 == k2;
00473
00474
00475 Is_True (!Is_File_Idx (k1) || !Is_File_Idx (k2),
00476 ("Invalid TYLIST_IDX in tylist hash table"));
00477
00478 TYLIST_ITER merged_tylist;
00479 const TYLIST* new_tylist;
00480
00481 if (Is_File_Idx (k1)) {
00482 new_tylist = tylist_table + Get_Idx (k1);
00483 merged_tylist = Make_tylist_iter (k2);
00484 } else {
00485 new_tylist = tylist_table + Get_Idx (k2);
00486 merged_tylist = Make_tylist_iter (k1);
00487 }
00488
00489 while (*new_tylist != 0) {
00490 if (IPA_Enable_Old_Type_Merge) {
00491 if ((*ty_map)[*new_tylist] != *merged_tylist)
00492 return FALSE;
00493 }
00494 else {
00495
00496 if (TY_IDX_without_attribute((*ty_map)[*new_tylist])
00497 != TY_IDX_without_attribute(*merged_tylist))
00498 return FALSE;
00499
00500
00501 if (TY_align((*ty_map)[*new_tylist]) != TY_align(*merged_tylist)
00502 && TY_align((*ty_map)[*new_tylist]) > 1
00503 && TY_align(*merged_tylist) > 1)
00504 return FALSE;
00505 }
00506 ++new_tylist;
00507 ++merged_tylist;
00508 }
00509 return (*merged_tylist ? FALSE : TRUE);
00510 }
00511 };
00512 }
00513
00514
00515 typedef hashtable<TYLIST_IDX, TYLIST_IDX, TYLIST_HASH, identity<TYLIST_IDX>,
00516 TYLIST_IS_EQUIVALENT, mempool_allocator<TYLIST_IDX> > TYLIST_HASH_TABLE;
00517
00518
00519
00520
00521
00522
00523
00524
00525 BOOL
00526 Partial_Compare_Fld (const TY &ty1, BOOL is_file1, const TY &ty2, BOOL is_file2)
00527 {
00528 UINT i = 0;
00529
00530 while (1) {
00531 const FLD *fld1 = is_file1 ? (fld_table+ty1.Fld()+i) : &Fld_Table[ty1.Fld()+i];
00532 const FLD *fld2 = is_file2 ? (fld_table+ty2.Fld()+i) : &Fld_Table[ty2.Fld()+i];
00533
00534 if (FLD_is_anonymous(fld1) || FLD_is_anonymous(fld2)) {
00535 if (FLD_is_anonymous(fld1) != FLD_is_anonymous(fld2))
00536 return FALSE;
00537 }
00538 else {
00539 STR_IDX name_str1 = is_file1 ? (*str_map)[fld1->name_idx] : fld1->name_idx;
00540 STR_IDX name_str2 = is_file2 ? (*str_map)[fld2->name_idx] : fld2->name_idx;
00541 if (name_str1 != name_str2)
00542 return FALSE;
00543 }
00544
00545 const UINT64* p1 = reinterpret_cast<const UINT64*> (fld1);
00546 const UINT64* p2 = reinterpret_cast<const UINT64*> (fld2);
00547
00548 if (p1[1] != p2[1] || p1[2] != p2[2])
00549 return FALSE;
00550
00551 if (FLD_last_field(fld1))
00552 break;
00553
00554 ++i;
00555 }
00556
00557 return TRUE;
00558 }
00559
00560 BOOL
00561 Partial_Compare_Fld (FLD_HANDLE merged_fld, const FLD* new_fld)
00562 {
00563 FLD_ITER fld_iter = Make_fld_iter (merged_fld);
00564
00565 do {
00566 if (IPA_Enable_Old_Type_Merge) {
00567 if (FLD_name_idx (fld_iter) != (*str_map)[new_fld->name_idx])
00568 return FALSE;
00569 }
00570 else {
00571 if (FLD_is_anonymous(fld_iter) || FLD_is_anonymous(new_fld)) {
00572 if (FLD_is_anonymous(fld_iter) != FLD_is_anonymous(new_fld))
00573 return FALSE;
00574 }
00575 else {
00576 if (FLD_name_idx(fld_iter) != (*str_map)[new_fld->name_idx])
00577 return FALSE;
00578 }
00579 }
00580
00581 const UINT64* p1 = reinterpret_cast<const UINT64*> (&(*fld_iter));
00582 const UINT64* p2 = reinterpret_cast<const UINT64*> (new_fld);
00583
00584 if (p1[1] != p2[1] || p1[2] != p2[2])
00585 return FALSE;
00586 ++fld_iter;
00587 } while ((new_fld++->flags & FLD_LAST_FIELD) == 0);
00588
00589 return TRUE;
00590 }
00591
00592
00593
00594 static inline BOOL
00595 ARB_equal (const ARB* arb1, const ARB* arb2)
00596 {
00597 const UINT64* p1 = reinterpret_cast<const UINT64*> (arb1);
00598 const UINT64* p2 = reinterpret_cast<const UINT64*> (arb2);
00599
00600 return (p1[0] == p2[0] &&
00601 p1[1] == p2[1] &&
00602 p1[2] == p2[2] &&
00603 p1[3] == p2[3]);
00604 }
00605
00606 static inline BOOL
00607 ARB_equal (const ARB_HANDLE merged_arb, const ARB& new_arb)
00608 {
00609 const UINT64* p1 = reinterpret_cast<const UINT64*> (merged_arb.Entry ());
00610 const UINT64* p2 = reinterpret_cast<const UINT64*> (&new_arb);
00611
00612 return (p1[0] == p2[0] &&
00613 p1[1] == p2[1] &&
00614 p1[2] == p2[2] &&
00615 p1[3] == p2[3]);
00616 }
00617
00618
00619
00620 BOOL
00621 Partial_Compare_Arb (const TY &ty1, BOOL is_file1, const TY &ty2, BOOL is_file2)
00622 {
00623 const ARB *arb1 = is_file1 ? (arb_table+ty1.Arb()) : &Arb_Table[ty1.Arb()];
00624 const ARB *arb2 = is_file2 ? (arb_table+ty2.Arb()) : &Arb_Table[ty2.Arb()];
00625
00626 UINT dim = arb1->dimension;
00627
00628 if (arb2->dimension != dim)
00629 return FALSE;
00630
00631 for (UINT i = 0; i < dim; ++i) {
00632 arb1 = is_file1 ? (arb_table+ty1.Arb()+i) : &Arb_Table[ty1.Arb()+i];
00633 arb2 = is_file2 ? (arb_table+ty2.Arb()+i) : &Arb_Table[ty2.Arb()+i];
00634 if (!ARB_equal (arb1, arb2))
00635 return FALSE;
00636 }
00637 return TRUE;
00638 }
00639
00640 BOOL
00641 Partial_Compare_Arb (ARB_HANDLE merged_arb, const ARB* new_arb)
00642 {
00643 UINT dim = new_arb->dimension;
00644
00645 if (ARB_dimension (merged_arb) != dim)
00646 return FALSE;
00647
00648 for (UINT i = 0; i < dim; ++i) {
00649 if (!ARB_equal (merged_arb[i], new_arb[i]))
00650 return FALSE;
00651 }
00652 return TRUE;
00653 }
00654
00655
00656 namespace
00657 {
00658
00659
00660 size_t recursive_ty_hash (TY_INDEX idx) {
00661 const TY& ty = Is_File_Idx (idx) ?
00662 ty_table[Get_Idx (idx)] : Ty_Table[make_TY_IDX (idx)];
00663 const UINT32* p = reinterpret_cast<const UINT32*> (&ty);
00664 size_t value = p[0] + p[1] + p[2];
00665 switch (TY_kind (ty)) {
00666 case KIND_SCALAR:
00667 case KIND_VOID:
00668 default:
00669 Fail_FmtAssertion ("Unexpected TY_kind in recursive type %d\n",
00670 TY_kind (ty));
00671
00672 case KIND_POINTER:
00673 {
00674 const TY& pointed = Is_File_Idx (idx) ?
00675 ty_table[TY_IDX_index (TY_pointed (ty))] :
00676 Ty_Table[TY_pointed (ty)];
00677 return ~(value + pointed.kind + pointed.mtype);
00678 }
00679 case KIND_ARRAY:
00680 if (Is_File_Idx (idx)) {
00681 const ARB* arb = arb_table + ty.Arb ();
00682 UINT dim = arb->dimension;
00683 value = arb->flags + dim;
00684 for (UINT i = 0; i < dim; ++i) {
00685 value += (arb->Lbnd_val () + arb->Ubnd_val () +
00686 arb->Stride_val ()) << i;
00687 }
00688 } else {
00689 ARB_ITER arb_iter = Make_arb_iter (TY_arb (ty));
00690 UINT dim = ARB_dimension (arb_iter);
00691 value = ARB_flags (arb_iter) + dim;
00692 for (UINT i = 0; i < dim; ++i) {
00693 ARB_HANDLE arb (arb_iter);
00694 ++arb_iter;
00695 value += (ARB_lbnd_val (arb) + ARB_ubnd_val (arb) +
00696 ARB_stride_val (arb)) << i;
00697 }
00698 }
00699 return ~value;
00700
00701 case KIND_STRUCT:
00702 if (ty.Fld () == 0)
00703 return ~value;
00704 if (Is_File_Idx (idx)) {
00705 if (!TY_anonymous(ty))
00706 value += (*str_map)[TY_name_idx (ty)];
00707 const FLD* fld = fld_table + ty.Fld ();
00708 do {
00709 if (!FLD_is_anonymous((FLD *)fld))
00710 value += (*str_map)[fld->name_idx];
00711 } while ((fld++->flags & FLD_LAST_FIELD) == 0);
00712 } else {
00713 if (!TY_anonymous(ty))
00714 value += TY_name_idx (ty);
00715 FLD_ITER fld_iter = Make_fld_iter (TY_fld (ty));
00716 BOOL done = FALSE;
00717 do {
00718 if (!FLD_is_anonymous(fld_iter))
00719 value += FLD_name_idx (fld_iter);
00720 done = FLD_last_field (fld_iter);
00721 ++fld_iter;
00722 } while (!done);
00723 }
00724 return ~value;
00725
00726 case KIND_FUNCTION:
00727 if (Is_File_Idx (idx)) {
00728 value += (*str_map)[TY_name_idx (ty)];
00729 const TYLIST* tylist = tylist_table + TY_tylist (ty);
00730 while (*tylist != 0) {
00731 const TY* parm_ty = ty_table + TY_IDX_index (*tylist);
00732 if (TY_kind(*parm_ty) != KIND_STRUCT) {
00733 p = reinterpret_cast<const UINT32*> (parm_ty);
00734 value += (p[0] + p[1] + p[2]);
00735 }
00736 ++tylist;
00737 }
00738 } else {
00739 value += TY_name_idx (ty);
00740 TYLIST_ITER tylist = Make_tylist_iter (TY_tylist (ty));
00741 while (*tylist != 0) {
00742 const TY& parm_ty = Ty_Table[*tylist];
00743 if (TY_kind(parm_ty) != KIND_STRUCT) {
00744 p = reinterpret_cast<const UINT32*> (&parm_ty);
00745 value += (p[0] + p[1] + p[2]);
00746 }
00747 ++tylist;
00748 }
00749 }
00750 return ~value;
00751 }
00752 }
00753
00754 struct partial_ty_hash {
00755 size_t operator() (TY_INDEX idx) const {
00756
00757 if (!IPA_Enable_Old_Type_Merge) {
00758
00759
00760
00761 return recursive_ty_hash(idx);
00762 }
00763
00764 const TY& ty = Is_File_Idx (idx) ?
00765 ty_table[Get_Idx (idx)] : Ty_Table[make_TY_IDX (idx)];
00766
00767 const UINT32* p = reinterpret_cast<const UINT32*> (&ty);
00768 size_t value = p[0] + p[1] + p[2];
00769
00770 switch (TY_kind (ty)) {
00771 case KIND_SCALAR:
00772 case KIND_VOID:
00773 default:
00774 Fail_FmtAssertion ("Unexpected TY_kind in recursive type %d\n",
00775 TY_kind (ty));
00776
00777 case KIND_POINTER:
00778 {
00779 const TY& pointed = Is_File_Idx (idx) ?
00780 ty_table[TY_IDX_index (TY_pointed (ty))] :
00781 Ty_Table[TY_pointed (ty)];
00782 p = reinterpret_cast<const UINT32*> (&pointed);
00783 return ~(value + (p[0] + p[1] + p[2]));
00784 }
00785
00786 case KIND_ARRAY:
00787 if (Is_File_Idx (idx)) {
00788 const ARB* arb = arb_table + ty.Arb ();
00789 UINT dim = arb->dimension;
00790 value = arb->flags + dim;
00791 for (UINT i = 0; i < dim; ++i) {
00792 value += (arb->Lbnd_val () + arb->Ubnd_val () +
00793 arb->Stride_val ()) << i;
00794 }
00795 } else {
00796 ARB_ITER arb_iter = Make_arb_iter (TY_arb (ty));
00797 UINT dim = ARB_dimension (arb_iter);
00798 value = ARB_flags (arb_iter) + dim;
00799 for (UINT i = 0; i < dim; ++i) {
00800 ARB_HANDLE arb (arb_iter);
00801 ++arb_iter;
00802 value += (ARB_lbnd_val (arb) + ARB_ubnd_val (arb) +
00803 ARB_stride_val (arb)) << i;
00804 }
00805 }
00806 return ~value;
00807
00808
00809 case KIND_STRUCT:
00810 if (ty.Fld () == 0)
00811 return ~value;
00812
00813 if (Is_File_Idx (idx)) {
00814 value += (*str_map)[TY_name_idx (ty)];
00815 const FLD* fld = fld_table + ty.Fld ();
00816 do {
00817 value += (*str_map)[fld->name_idx];
00818 } while ((fld++->flags & FLD_LAST_FIELD) == 0);
00819 } else {
00820 value += TY_name_idx (ty);
00821 FLD_ITER fld_iter = Make_fld_iter (TY_fld (ty));
00822 BOOL done = FALSE;
00823 do {
00824 value += FLD_name_idx (fld_iter);
00825 done = FLD_last_field (fld_iter);
00826 ++fld_iter;
00827 } while (!done);
00828 }
00829 return ~value;
00830
00831 case KIND_FUNCTION:
00832 if (Is_File_Idx (idx)) {
00833 value += (*str_map)[TY_name_idx (ty)];
00834 const TYLIST* tylist = tylist_table + TY_tylist (ty);
00835 while (*tylist != 0) {
00836 const TY* parm_ty = ty_table + TY_IDX_index (*tylist);
00837 p = reinterpret_cast<const UINT32*> (parm_ty);
00838 value += (p[0] + p[1] + p[2]);
00839 ++tylist;
00840 }
00841 } else {
00842 value += TY_name_idx (ty);
00843 TYLIST_ITER tylist = Make_tylist_iter (TY_tylist (ty));
00844 while (*tylist != 0) {
00845 const TY& parm_ty = Ty_Table[*tylist];
00846 p = reinterpret_cast<const UINT32*> (&parm_ty);
00847 value += (p[0] + p[1] + p[2]);
00848 ++tylist;
00849 }
00850 }
00851 return ~value;
00852 }
00853 }
00854 };
00855
00856
00857 struct ty_index_compare {
00858 BOOL operator() (TY_INDEX idx1, TY_INDEX idx2) const {
00859
00860 if (IPA_Enable_Old_Type_Merge) {
00861 if (idx1 == idx2)
00862 return TRUE;
00863
00864 if (!Is_File_Idx (idx1) && !Is_File_Idx (idx2))
00865 return idx1 == idx2;
00866
00867 Is_True (!Is_File_Idx (idx1) || !Is_File_Idx (idx2),
00868 ("Invalid TY_INDEX in recursive_ty_hash_table"));
00869
00870 const TY& new_ty = Is_File_Idx (idx1) ? ty_table[Get_Idx (idx1)] :
00871 ty_table[Get_Idx (idx2)];
00872 const TY& merged_ty = Is_File_Idx (idx1) ?
00873 Ty_Table[make_TY_IDX (idx2)] : Ty_Table[make_TY_IDX (idx1)];
00874
00875 if (TY_size (new_ty) != TY_size (merged_ty) ||
00876 (*str_map)[TY_name_idx (new_ty)] != TY_name_idx (merged_ty))
00877 return FALSE;
00878
00879 const UINT32* p1 = reinterpret_cast<const UINT32*> (&new_ty);
00880 const UINT32* p2 = reinterpret_cast<const UINT32*> (&merged_ty);
00881
00882 if (p1[2] != p2[2])
00883 return FALSE;
00884
00885 switch (TY_kind (new_ty)) {
00886 case KIND_SCALAR:
00887 case KIND_VOID:
00888 default:
00889 Fail_FmtAssertion ("Unexpected TY_kind in recursive type %d\n",
00890 TY_kind (new_ty));
00891
00892 case KIND_POINTER:
00893 return (TY_IDX_Attributes (TY_pointed (new_ty)) ==
00894 TY_IDX_Attributes (TY_pointed (merged_ty)));
00895
00896 case KIND_ARRAY:
00897 if (TY_IDX_Attributes (TY_etype (new_ty)) !=
00898 TY_IDX_Attributes (TY_etype (merged_ty)))
00899 return FALSE;
00900 return Partial_Compare_Arb (TY_arb (merged_ty),
00901 arb_table + new_ty.Arb ());
00902
00903 case KIND_STRUCT:
00904 if (new_ty.Fld () == 0 || merged_ty.Fld () == 0)
00905 return new_ty.Fld () == merged_ty.Fld ();
00906 return Partial_Compare_Fld (TY_fld (merged_ty),
00907 fld_table + new_ty.Fld ());
00908
00909 case KIND_FUNCTION:
00910 return (new_ty.Pu_flags () == merged_ty.Pu_flags ());
00911 }
00912 }
00913 else {
00914 if (idx1 == idx2)
00915 return TRUE;
00916
00917 if (recursive_ty_hash(idx1) != recursive_ty_hash(idx2))
00918 return FALSE;
00919
00920 const TY& ty1 = Is_File_Idx (idx1) ? ty_table[Get_Idx (idx1)] : Ty_tab[idx1];
00921 const TY& ty2 = Is_File_Idx (idx2) ? ty_table[Get_Idx (idx2)] : Ty_tab[idx2];
00922
00923 if (TY_size (ty1) != TY_size (ty2) || TY_kind (ty1) != TY_kind (ty2))
00924 return FALSE;
00925
00926 if (TY_kind(ty1) == KIND_STRUCT || TY_kind(ty1) == KIND_ARRAY) {
00927 if (TY_anonymous(ty1) || TY_anonymous(ty2)) {
00928 if (TY_anonymous(ty1) != TY_anonymous(ty2))
00929 return FALSE;
00930 }
00931 else {
00932 STR_IDX name_str1 = Is_File_Idx (idx1) ?
00933 (*str_map)[TY_name_idx (ty1)] : TY_name_idx (ty1);
00934 STR_IDX name_str2 = Is_File_Idx (idx2) ?
00935 (*str_map)[TY_name_idx (ty2)] : TY_name_idx (ty2);
00936 if (name_str1 != name_str2)
00937 return FALSE;
00938 }
00939 }
00940 else {
00941 STR_IDX name_str1 = Is_File_Idx (idx1) ?
00942 (*str_map)[TY_name_idx (ty1)] : TY_name_idx (ty1);
00943 STR_IDX name_str2 = Is_File_Idx (idx2) ?
00944 (*str_map)[TY_name_idx (ty2)] : TY_name_idx (ty2);
00945 if (name_str1 != name_str2)
00946 return FALSE;
00947 }
00948
00949 const UINT32* p1 = reinterpret_cast<const UINT32*> (&ty1);
00950 const UINT32* p2 = reinterpret_cast<const UINT32*> (&ty2);
00951 if (p1[2] != p2[2])
00952 return FALSE;
00953
00954 switch (TY_kind (ty1)) {
00955 case KIND_SCALAR:
00956 case KIND_VOID:
00957 default:
00958 Fail_FmtAssertion ("Unexpected TY_kind in recursive type %d\n",
00959 TY_kind (ty1));
00960 case KIND_POINTER:
00961 return TRUE;
00962 case KIND_ARRAY:
00963 if (TY_IDX_Attributes (TY_etype (ty1)) != TY_IDX_Attributes (TY_etype (ty2)))
00964 return FALSE;
00965 return Partial_Compare_Arb (ty1, Is_File_Idx(idx1), ty2, Is_File_Idx(idx2));
00966 case KIND_STRUCT:
00967 if (ty1.Fld () == 0 || ty2.Fld () == 0)
00968 return ty1.Fld () == ty2.Fld ();
00969 return Partial_Compare_Fld (ty1, Is_File_Idx(idx1), ty2, Is_File_Idx(idx2));
00970 case KIND_FUNCTION:
00971 return (ty1.Pu_flags () == ty2.Pu_flags ());
00972 }
00973 }
00974 }
00975 };
00976 }
00977
00978
00979 typedef hash_multiset<TY_INDEX, partial_ty_hash, ty_index_compare,
00980 mempool_allocator<TY_INDEX> > RECURSIVE_TY_HASH_TABLE;
00981
00982
00983
00984
00985 static NEW_TY_HASH_TABLE* ty_hash_table;
00986 static FLD_HASH_TABLE* fld_hash_table;
00987 static ARB_HASH_TABLE* arb_hash_table;
00988 static TYLIST_HASH_TABLE* tylist_hash_table;
00989
00990 static RECURSIVE_TY_HASH_TABLE* recursive_table;
00991
00992 typedef vector<TY_IDX, mempool_allocator<TY_IDX> > RECURSIVE_TYPE;
00993
00994
00995 static RECURSIVE_TYPE *recursive_type;
00996
00997 static UINT collecting_recursive_ty = 0;
00998
00999 void
01000 Initialize_Type_Merging_Hash_Tables (MEM_POOL* pool)
01001 {
01002 #if 0
01003
01004
01005
01006
01007 #ifdef __GNUC__
01008 #ifndef TARG_SL
01009 Is_True (sizeof(TY) == 28 && __alignof__(TY) == 4 &&
01010 sizeof(FLD) == 28 && __alignof__(FLD) == 4 &&
01011 sizeof(ARB) == 32 && __alignof__(ARB) == 4,
01012 ("Invalid size/alignment assumption:"
01013 " TY sz %d al %d, FLD sz%d al %d, ARB sz %d al %d",
01014 sizeof(TY), __alignof__(TY), sizeof(FLD),
01015 __alignof__(FLD), sizeof(ARB), __alignof__(ARB)));
01016 #else
01017
01018
01019 Is_True (sizeof(TY) == 32 && __alignof__(TY) == 8 &&
01020 sizeof(FLD) == 32 && __alignof__(FLD) == 8 &&
01021 sizeof(ARB) == 32 && __alignof__(ARB) == 8,
01022 ("Invalid size/alignment assumption:"
01023 " TY sz %d al %d, FLD sz%d al %d, ARB sz %d al %d",
01024 sizeof(TY), __alignof__(TY), sizeof(FLD),
01025 __alignof__(FLD), sizeof(ARB), __alignof__(ARB)));
01026 #endif // ! TARG_SL
01027 #else // for SL as well as IRIX, this is guaranteed by compiler, except for packed data
01028 Is_True (sizeof(TY) == 32 && __builtin_alignof(TY) == 8 &&
01029 sizeof(FLD) == 32 && __builtin_alignof(FLD) == 8 &&
01030 sizeof(ARB) == 32 && __builtin_alignof(ARB) == 8,
01031 ("Invalid size/alignment assumption:"
01032 " TY sz %d al %d, FLD sz%d al %d, ARB sz %d al %d",
01033 sizeof(TY), __builtin_alignof(TY), sizeof(FLD),
01034 __builtin_alignof(FLD), sizeof(ARB), __builtin_alignof(ARB)));
01035 #endif // __GNUC__
01036 #endif // 0
01037 ty_hash_table = CXX_NEW (NEW_TY_HASH_TABLE (1000, TY_HASH (), TY_IS_EQUIVALENT(),
01038 TY_EXTRACT_KEY (), pool),
01039 pool);
01040 fld_hash_table = CXX_NEW (FLD_HASH_TABLE (100, FLD_HASH (),
01041 FLD_IS_EQUIVALENT(),
01042 identity<FLD_IDX>(), pool),
01043 pool);
01044 arb_hash_table = CXX_NEW (ARB_HASH_TABLE (100, ARB_HASH (),
01045 ARB_IS_EQUIVALENT(),
01046 identity<ARB_IDX>(), pool),
01047 pool);
01048 tylist_hash_table = CXX_NEW (TYLIST_HASH_TABLE (100, TYLIST_HASH (),
01049 TYLIST_IS_EQUIVALENT(),
01050 identity<TYLIST_IDX>(),
01051 pool),
01052 pool);
01053
01054 recursive_table =
01055 CXX_NEW (RECURSIVE_TY_HASH_TABLE (500, partial_ty_hash (),
01056 ty_index_compare (), pool),
01057 pool);
01058
01059 for (UINT i = 1; i < TY_Table_Size (); ++i)
01060 ty_hash_table->find_or_insert (make_TY_IDX (i));
01061
01062 if (IPA_Enable_Old_Type_Merge)
01063 recursive_type = CXX_NEW (RECURSIVE_TYPE (pool), pool);
01064
01065 }
01066
01067
01068
01069 void
01070 Setup_Type_Merging_Hash_Tables (const IPC_GLOBAL_TABS& original_tabs,
01071 IPC_GLOBAL_IDX_MAP& idx_map)
01072 {
01073 ty_map = &idx_map.ty;
01074 str_map = &idx_map.sym_str;
01075
01076 ty_table = original_tabs.ty_tab;
01077 fld_table = original_tabs.fld_tab;
01078 arb_table = original_tabs.arb_tab;
01079 tylist_table = original_tabs.tylist_tab;
01080 }
01081
01082
01083 static void
01084 Setup_Ty (TY& ty)
01085 {
01086 Set_TY_name_idx (ty, (*str_map)[TY_name_idx (ty)]);
01087
01088 switch (TY_kind (ty)) {
01089 ARB_IDX* arb_idx;
01090 FLD_IDX* fld_idx;
01091 TYLIST_IDX* tylist_idx;
01092
01093 case KIND_SCALAR:
01094 case KIND_VOID:
01095 break;
01096
01097 case KIND_ARRAY:
01098 arb_idx = &(arb_hash_table->find_or_insert (File_Idx (ty.Arb ())));
01099 if (Is_File_Idx (*arb_idx)) {
01100 const ARB* arb = arb_table + ty.Arb ();
01101 *arb_idx = Arb_Table.Insert (*arb);
01102 while ((arb->flags & ARB_LAST_DIMEN) == 0) {
01103 Arb_Table.Insert (*++arb);
01104 }
01105 }
01106 Set_TY_arb (ty, ARB_HANDLE (*arb_idx));
01107 Set_TY_etype (ty, Get_Kid_TY_IDX (TY_etype (ty)));
01108 break;
01109
01110 case KIND_STRUCT:
01111 if (ty.Fld () == 0)
01112 break;
01113 fld_idx = &(fld_hash_table->find_or_insert (File_Idx (ty.Fld ())));
01114 if (Is_File_Idx (*fld_idx)) {
01115 const FLD* fld = fld_table + ty.Fld();
01116 *fld_idx = Fld_Table.Insert (*fld);
01117 for (FLD_HANDLE merged_fld (*fld_idx);;) {
01118 Set_FLD_name_idx (merged_fld, (*str_map)[fld->name_idx]);
01119 Set_FLD_type (merged_fld, Get_Kid_TY_IDX (fld->type));
01120 Set_FLD_st (merged_fld, 0);
01121 if (FLD_last_field (merged_fld))
01122 break;
01123 ++fld;
01124 merged_fld = FLD_HANDLE (Fld_Table.Insert (*fld));
01125 }
01126 }
01127 Set_TY_fld (ty, FLD_HANDLE (*fld_idx));
01128 break;
01129
01130 case KIND_POINTER:
01131 Set_TY_pointed (ty, Get_Kid_TY_IDX (TY_pointed (ty)));
01132 break;
01133
01134 case KIND_FUNCTION:
01135 tylist_idx =
01136 &(tylist_hash_table->find_or_insert (File_Idx (TY_tylist (ty))));
01137 if (Is_File_Idx (*tylist_idx)) {
01138 const TYLIST* tylist = tylist_table + TY_tylist (ty);
01139 *tylist_idx = Tylist_Table.Insert (Get_Kid_TY_IDX (*tylist));
01140 ++tylist;
01141 while (*tylist != 0) {
01142 Tylist_Table.Insert (Get_Kid_TY_IDX (*tylist));
01143 ++tylist;
01144 }
01145 Tylist_Table.Insert (0);
01146 }
01147 Set_TY_tylist (ty, *tylist_idx);
01148 break;
01149
01150 default:
01151 Fail_FmtAssertion ("Invalid TY_kind");
01152 }
01153 }
01154
01155
01156 TY_IDX
01157 Insert_Unique_Ty (const TY& ty)
01158 {
01159 TY new_ty = ty;
01160
01161 Setup_Ty (new_ty);
01162
01163 ty_to_be_inserted = &new_ty;
01164 TY_IDX& result = ty_hash_table->find_or_insert ((TY_IDX) -1);
01165 if (result == (TY_IDX) -1) {
01166 result = make_TY_IDX (Ty_tab.Insert (new_ty));
01167 if (IPA_Enable_Old_Type_Merge) {
01168 if (collecting_recursive_ty)
01169 recursive_type->push_back (result);
01170 }
01171 }
01172 return result;
01173 }
01174
01175
01176 void
01177 Insert_Allocated_Ty (TY& ty, TY_IDX ty_idx)
01178 {
01179 Setup_Ty (ty);
01180 ty_to_be_inserted = &ty;
01181 TY_IDX& result = ty_hash_table->find_or_insert ((TY_IDX) -1);
01182
01183 if (IPA_Enable_Old_Type_Merge)
01184 Is_True (result == (TY_IDX) -1, ("Trying to insert duplicated TY"));
01185 result = ty_idx;
01186 if (!IPA_Enable_Old_Type_Merge) {
01187 if (TY_kind(ty) == KIND_STRUCT)
01188 struct_by_name_idx[ty.name_idx] = TY_IDX_index(ty_idx);
01189 }
01190 }
01191
01192
01193
01194 void
01195 Insert_Recursive_Type (TY_IDX ty_idx)
01196 {
01197 const TY& ty = Ty_Table[ty_idx];
01198
01199 if (!IPA_Enable_Old_Type_Merge) {
01200 if (TY_is_incomplete_struct(ty))
01201 return;
01202 }
01203 switch (TY_kind (ty)) {
01204 case KIND_POINTER:
01205 case KIND_STRUCT:
01206 case KIND_FUNCTION:
01207 recursive_table->insert (TY_IDX_index (ty_idx));
01208 }
01209 }
01210
01211
01212 void
01213 Initialize_New_Recursive_Type (TY_IDX ty_idx)
01214 {
01215 Is_True (collecting_recursive_ty || recursive_type->empty (),
01216 ("Found uninserted recursive types"));
01217
01218 ++collecting_recursive_ty;
01219 recursive_type->push_back (ty_idx);
01220 }
01221
01222
01223 void
01224 Finalize_New_Recursive_Type ()
01225 {
01226 Is_True (collecting_recursive_ty, ("inconsistent recursive type"));
01227
01228 --collecting_recursive_ty;
01229
01230 if (collecting_recursive_ty != 0)
01231 return;
01232
01233 for (RECURSIVE_TYPE::const_iterator i (recursive_type->begin ());
01234 i != recursive_type->end (); ++i) {
01235
01236 Insert_Recursive_Type (*i);
01237 }
01238
01239 recursive_type->erase (recursive_type->begin (), recursive_type->end ());
01240
01241 }
01242
01243
01244
01245 void
01246 Find_Matching_Ty (const TY& ty, TY_IDX_VEC& matched_list)
01247 {
01248 TY_INDEX idx = &ty - ty_table;
01249
01250 typedef RECURSIVE_TY_HASH_TABLE::iterator ITER;
01251
01252 pair<ITER, ITER> found = recursive_table->equal_range (File_Idx (idx));
01253 for (ITER first = found.first; first != found.second; ++first)
01254 matched_list.push_back (make_TY_IDX (*first));
01255 }
01256
01257