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 #ifdef _KEEP_RCS_ID
00065 #endif
00066
00067 #include <string.h>
00068
00069 #include "common_include.h"
00070 #include "w2cf_parentize.h"
00071 #include "mempool.h"
00072 #include "const.h"
00073 #include "wn_util.h"
00074 #include "PUinfo.h"
00075 #include "targ_sim.h"
00076 #include "unparse_target.h"
00077
00078 #define IS_RETURN_PREG(wn) \
00079 (ST_class(WN_st(wn)) == CLASS_PREG \
00080 && (Is_Return_Preg(WN_load_offset(wn)) \
00081 || WN_st(wn) == Return_Val_Preg ) )
00082
00083
00084
00085
00086 const WN *PUinfo_current_func = NULL;
00087 const RETURN_PREG *PUinfo_return_preg = NULL;
00088 TOKEN_BUFFER PUinfo_local_decls = NULL;
00089 TOKEN_BUFFER PUinfo_pragmas = NULL;
00090 UINT PUinfo_local_decls_indent = 0;
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114 typedef enum Preg_Usage_Kind
00115 {
00116 PREG_AS_UNKNOWN,
00117 PREG_AS_INT8,
00118 PREG_AS_UINT8,
00119 PREG_AS_INT16,
00120 PREG_AS_UINT16,
00121 PREG_AS_INT32,
00122 PREG_AS_UINT32,
00123 PREG_AS_INT64,
00124 PREG_AS_UINT64,
00125 PREG_AS_IEEE32,
00126 PREG_AS_IEEE64,
00127 PREG_AS_QUAD,
00128 PREG_AS_C4,
00129 PREG_AS_C8,
00130 PREG_AS_CQ
00131 } PREG_USAGE_KIND;
00132
00133 #define FIRST_PREG_USAGE_KIND PREG_AS_INT8
00134 #define SMALLEST_iPREG_USAGE_KIND FIRST_PREG_USAGE_KIND
00135 #define LARGEST_iPREG_USAGE_KIND PREG_AS_UINT64
00136 #define LAST_PREG_USAGE_KIND PREG_AS_CQ
00137
00138 static const MTYPE Ukind_to_Mtype[LAST_PREG_USAGE_KIND+1] =
00139 {
00140 MTYPE_UNKNOWN,
00141 MTYPE_I1,
00142 MTYPE_U1,
00143 MTYPE_I2,
00144 MTYPE_U2,
00145 MTYPE_I4,
00146 MTYPE_U4,
00147 MTYPE_I8,
00148 MTYPE_U8,
00149 MTYPE_F4,
00150 MTYPE_F8,
00151 MTYPE_FQ,
00152 MTYPE_C4,
00153 MTYPE_C8,
00154 MTYPE_CQ
00155 };
00156
00157 typedef struct Preg_Info PREG_INFO;
00158 struct Preg_Info
00159 {
00160 BOOL use[LAST_PREG_USAGE_KIND+1];
00161 BOOL decl[LAST_PREG_USAGE_KIND+1];
00162 INT16 preg_num;
00163 PREG_INFO *next;
00164 };
00165 #define PREG_INFO_use(info, ukind) (info)->use[ukind]
00166 #define PREG_INFO_decl(info, ukind) (info)->decl[ukind]
00167 #define PREG_INFO_preg_num(info) (info)->preg_num
00168 #define PREG_INFO_next(info) (info)->next
00169
00170 #define PREG_INFO_HASH_TABLE_SIZE 73
00171 #define PREG_INFO_HASH_IDX(offset) \
00172 (UINT32)(offset % PREG_INFO_HASH_TABLE_SIZE)
00173
00174 static PREG_INFO *Preg_Info_Hash_Tbl[PREG_INFO_HASH_TABLE_SIZE];
00175 static PREG_INFO *Free_Preg_Info = NULL;
00176
00177
00178 static BOOL
00179 WN_in_ioitem(const WN *wn)
00180 {
00181
00182
00183 BOOL found_io = FALSE, found_region = FALSE;
00184
00185 wn = W2CF_Get_Parent(wn);
00186 while (wn != NULL && !found_io && !found_region)
00187 {
00188 if (WN_opc_operator(wn) == OPR_IO_ITEM)
00189 found_io = TRUE;
00190 else if (WN_opc_operator(wn) == OPR_REGION)
00191 found_region = TRUE;
00192 wn = W2CF_Get_Parent(wn);
00193 }
00194 return (found_io);
00195 }
00196
00197
00198 static PREG_USAGE_KIND
00199 Mtype_to_Ukind(MTYPE mtype)
00200 {
00201
00202
00203
00204
00205
00206
00207 PREG_USAGE_KIND ukind;
00208
00209 switch (mtype)
00210 {
00211 case MTYPE_I1:
00212 ukind = PREG_AS_INT8;
00213 break;
00214 case MTYPE_U1:
00215 ukind = PREG_AS_UINT8;
00216 break;
00217 case MTYPE_I2:
00218 ukind = PREG_AS_INT16;
00219 break;
00220 case MTYPE_U2:
00221 ukind = PREG_AS_UINT16;
00222 break;
00223 case MTYPE_I4:
00224 ukind = PREG_AS_INT32;
00225 break;
00226 case MTYPE_U4:
00227 ukind = PREG_AS_UINT32;
00228 break;
00229 case MTYPE_I8:
00230 ukind = PREG_AS_INT64;
00231 break;
00232 case MTYPE_U8:
00233 ukind = PREG_AS_UINT64;
00234 break;
00235 case MTYPE_F4:
00236 ukind = PREG_AS_IEEE32;
00237 break;
00238 case MTYPE_F8:
00239 ukind = PREG_AS_IEEE64;
00240 break;
00241 case MTYPE_FQ:
00242 ukind = PREG_AS_QUAD;
00243 break;
00244 case MTYPE_C4:
00245 ukind = PREG_AS_C4;
00246 break;
00247 case MTYPE_C8:
00248 ukind = PREG_AS_C8;
00249 break;
00250 case MTYPE_CQ:
00251 ukind = PREG_AS_CQ;
00252 break;
00253 default:
00254 ukind = PREG_AS_UNKNOWN;
00255
00256
00257
00258
00259
00260
00261
00262 Is_True(FALSE, ("Illegal MTYPE for Mtype_to_Ukind mapping"));
00263 break;
00264 }
00265 return ukind;
00266 }
00267
00268
00269 static PREG_INFO *
00270 Get_Preg_Info(INT16 preg_num)
00271 {
00272 PREG_INFO *preg_info = NULL;
00273
00274
00275 for (preg_info = Preg_Info_Hash_Tbl[PREG_INFO_HASH_IDX(preg_num)];
00276 preg_info != NULL && PREG_INFO_preg_num(preg_info) != preg_num;
00277 preg_info = PREG_INFO_next(preg_info));
00278 return preg_info;
00279 }
00280
00281
00282 static void
00283 Accumulate_Preg_Info(TY_IDX preg_ty, INT16 preg_num)
00284 {
00285
00286
00287
00288 PREG_INFO *preg_info;
00289 INT usage_kind;
00290
00291 if (preg_num == -1)
00292 return;
00293
00294 Is_True(TY_Is_Scalar(preg_ty),
00295 ("Expected KIND_SCALAR symbol in Accumulate_Preg_Info()"));
00296
00297
00298
00299
00300 preg_info = Get_Preg_Info(preg_num);
00301 if (preg_info == NULL)
00302 {
00303
00304 if (Free_Preg_Info == NULL)
00305 preg_info = TYPE_ALLOC_N(PREG_INFO, 1);
00306 else
00307 {
00308 preg_info = Free_Preg_Info;
00309 Free_Preg_Info = PREG_INFO_next(Free_Preg_Info);
00310 }
00311
00312
00313 for (usage_kind = (INT)FIRST_PREG_USAGE_KIND;
00314 usage_kind <= (INT)LAST_PREG_USAGE_KIND;
00315 usage_kind++)
00316 {
00317 PREG_INFO_decl(preg_info, usage_kind) = FALSE;
00318 PREG_INFO_use(preg_info, usage_kind) = FALSE;
00319 }
00320 PREG_INFO_preg_num(preg_info) = preg_num;
00321 PREG_INFO_next(preg_info) =
00322 Preg_Info_Hash_Tbl[PREG_INFO_HASH_IDX(preg_num)];
00323 Preg_Info_Hash_Tbl[PREG_INFO_HASH_IDX(preg_num)] = preg_info;
00324 }
00325
00326
00327 usage_kind = (INT)Mtype_to_Ukind(TY_mtype(preg_ty));
00328 PREG_INFO_use(preg_info, usage_kind) = TRUE;
00329 }
00330
00331
00332 static void
00333 Enter_Pregs_Into_Symtab(void)
00334 {
00335
00336
00337
00338
00339
00340
00341
00342 TY_IDX preg_ty;
00343 PREG_INFO *preg_info;
00344 INT hash_idx;
00345 INT usage_kind;
00346
00347 for (hash_idx = 0; hash_idx < PREG_INFO_HASH_TABLE_SIZE; hash_idx++)
00348 for (preg_info = Preg_Info_Hash_Tbl[hash_idx];
00349 preg_info != NULL;
00350 preg_info = PREG_INFO_next(preg_info))
00351 {
00352
00353
00354
00355 for (usage_kind = (INT)LARGEST_iPREG_USAGE_KIND;
00356 (usage_kind >= (INT)SMALLEST_iPREG_USAGE_KIND &&
00357 !PREG_INFO_use(preg_info, usage_kind));
00358 usage_kind--);
00359
00360 if (usage_kind >= (INT)SMALLEST_iPREG_USAGE_KIND)
00361 {
00362 preg_ty = Stab_Mtype_To_Ty(Ukind_to_Mtype[usage_kind]);
00363 W2CF_Symtab_Nameof_Preg(preg_ty, PREG_INFO_preg_num(preg_info));
00364 }
00365
00366
00367 for (usage_kind = (INT)LARGEST_iPREG_USAGE_KIND + 1;
00368 usage_kind <= (INT)LAST_PREG_USAGE_KIND;
00369 usage_kind++)
00370 {
00371 if (PREG_INFO_use(preg_info, usage_kind))
00372 {
00373 preg_ty = Stab_Mtype_To_Ty(Ukind_to_Mtype[usage_kind]);
00374 W2CF_Symtab_Nameof_Preg(preg_ty, PREG_INFO_preg_num(preg_info));
00375 }
00376 }
00377 }
00378 }
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389 static void
00390 Enter_Local_Syms_Into_Symtab(const ST *func_st)
00391 {
00392 ST_IDX st_idx;
00393 const ST *st;
00394
00395 (void)W2CF_Symtab_Nameof_St(func_st);
00396 FOREACH_SYMBOL(CURRENT_SYMTAB, st, st_idx)
00397 {
00398 if ((ST_sym_class(st) == CLASS_VAR || ST_sym_class(st) == CLASS_FUNC) &&
00399 !Stab_Is_Based_At_Common_Or_Equivalence(st))
00400 {
00401 if (W2X_Unparse_Target->Enter_Symtab_Pointee_Names() &&
00402 TY_Is_Pointer(ST_type(st)))
00403 (void)W2CF_Symtab_Nameof_St_Pointee(st);
00404 (void)W2CF_Symtab_Nameof_St(st);
00405 }
00406 }
00407 }
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
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 #define PUINFO_WN_ITER_wn(iter) \
00492 (iter != NULL? WN_ITER_wn(iter) : NULL)
00493 #define PUINFO_WN_WALK_TreeNext(iter) \
00494 (iter != NULL? WN_WALK_TreeNext(iter) : NULL)
00495 #define PUINFO_WN_WALK_StmtNext(iter) \
00496 (iter != NULL? WN_WALK_StmtNext(iter) : NULL)
00497
00498 static CALLSITE *CallSite_First = NULL;
00499 static CALLSITE *CallSite_Last = NULL;
00500 static CALLSITE *CallSite_Free = NULL;
00501
00502 static RETURNSITE *ReturnSite_First = NULL;
00503 static RETURNSITE *ReturnSite_Last = NULL;
00504 static RETURNSITE *ReturnSite_Free = NULL;
00505
00506
00507 static void
00508 Var_Loaded_From(const WN *wn,
00509 const ST **st,
00510 STAB_OFFSET *offset)
00511 {
00512 Is_True(wn != NULL, ("wn==NULL in Var_Loaded_From()"));
00513 if (WN_opc_operator(wn) == OPR_LDID)
00514 {
00515 *st = WN_st(wn);
00516 *offset = WN_load_offset(wn);
00517 }
00518 else if (WN_opc_operator(wn) == OPR_ILOAD &&
00519 WN_opc_operator(WN_kid0(wn)) == OPR_LDA)
00520 {
00521 *st = WN_st(WN_kid0(wn));
00522 *offset = WN_load_offset(wn) + WN_lda_offset(WN_kid0(wn));
00523 }
00524 else
00525 {
00526 *st = NULL;
00527 *offset = -1;
00528 }
00529 }
00530
00531
00532 static void
00533 Var_Stored_In(const WN *wn,
00534 const ST **st,
00535 STAB_OFFSET *offset)
00536 {
00537 Is_True(wn != NULL, ("wn==NULL in Var_Stored_In()"));
00538 if (WN_opc_operator(wn) == OPR_STID)
00539 {
00540 *st = WN_st(wn);
00541 *offset = WN_store_offset(wn);
00542 }
00543 else if (WN_opc_operator(wn) == OPR_ISTORE &&
00544 WN_opc_operator(WN_kid1(wn)) == OPR_LDA)
00545 {
00546 *st = WN_st(WN_kid1(wn));
00547 *offset = WN_store_offset(wn) + WN_lda_offset(WN_kid1(wn));
00548 }
00549 else
00550 {
00551 *st = NULL;
00552 *offset = -1;
00553 }
00554 }
00555
00556
00557 static const WN *
00558 Does_Stmt_Store_From_Preg(const WN *wn, STAB_OFFSET preg_num)
00559 {
00560 if ((WN_opc_operator(wn) == OPR_STID ||
00561 WN_opc_operator(wn) == OPR_ISTORE) &&
00562 WN_opc_operator(WN_kid0(wn)) == OPR_LDID &&
00563 ST_sym_class(WN_st(WN_kid0(wn))) == CLASS_PREG &&
00564 WN_load_offset(WN_kid0(wn)) == preg_num)
00565 return wn;
00566 else
00567 return NULL;
00568 }
00569
00570
00571 static const WN *
00572 Does_Stmt_Store_Into_Preg(const WN *wn, STAB_OFFSET preg_num)
00573 {
00574 if (WN_opc_operator(wn) == OPR_STID &&
00575 ST_sym_class(WN_st(wn)) == CLASS_PREG &&
00576 WN_store_offset(wn) == preg_num)
00577 return wn;
00578 else
00579 return NULL;
00580 }
00581
00582
00583 static CALLSITE *
00584 New_CallSite(const WN *call_wn,
00585 TY_IDX return_ty,
00586 const WN *store1_wn,
00587 const WN *store2_wn,
00588 const ST *return_var,
00589 STAB_OFFSET var_offset)
00590 {
00591 CALLSITE *callsite;
00592
00593 if (CallSite_Free != NULL)
00594 {
00595 callsite = CallSite_Free;
00596 CallSite_Free = CALLSITE_next(CallSite_Free);
00597 }
00598 else
00599 {
00600 callsite = TYPE_ALLOC_N(CALLSITE, 1);
00601 }
00602 if (CallSite_Last == NULL)
00603 {
00604 CallSite_Last = callsite;
00605 CallSite_First = callsite;
00606 }
00607 else
00608 {
00609 CALLSITE_next(CallSite_Last) = callsite;
00610 CallSite_Last = callsite;
00611 }
00612 CALLSITE_call(callsite) = call_wn;
00613 CALLSITE_return_ty(callsite) = return_ty;
00614 CALLSITE_store1(callsite) = store1_wn;
00615 CALLSITE_store2(callsite) = store2_wn;
00616 CALLSITE_return_var(callsite) = return_var;
00617 CALLSITE_var_offset(callsite) = var_offset;
00618 CALLSITE_in_regs(callsite) = FALSE;
00619 CALLSITE_next(callsite) = NULL;
00620
00621 return callsite;
00622 }
00623
00624
00625 static RETURNSITE *
00626 New_ReturnSite(const WN *return_wn,
00627 const WN *store1_wn,
00628 const WN *store2_wn,
00629 const ST *return_var,
00630 STAB_OFFSET var_offset)
00631 {
00632 RETURNSITE *return_info;
00633
00634 if (ReturnSite_Free != NULL)
00635 {
00636 return_info = ReturnSite_Free;
00637 ReturnSite_Free = RETURNSITE_next(ReturnSite_Free);
00638 }
00639 else
00640 {
00641 return_info = TYPE_ALLOC_N(RETURNSITE, 1);
00642 }
00643 if (ReturnSite_Last == NULL)
00644 {
00645 ReturnSite_Last = return_info;
00646 ReturnSite_First = return_info;
00647 }
00648 else
00649 {
00650 RETURNSITE_next(ReturnSite_Last) = return_info;
00651 ReturnSite_Last = return_info;
00652 }
00653 RETURNSITE_return(return_info) = return_wn;
00654 RETURNSITE_store1(return_info) = store1_wn;
00655 RETURNSITE_store2(return_info) = store2_wn;
00656 RETURNSITE_return_var(return_info) = return_var;
00657 RETURNSITE_var_offset(return_info) = var_offset;
00658 RETURNSITE_next(return_info) = NULL;
00659
00660 return return_info;
00661 }
00662
00663
00664 static WN_ITER *
00665 Append_CallSite(WN_ITER *stmt_iter, const WN *next_stmt)
00666 {
00667
00668
00669
00670
00671 TY_IDX return_ty;
00672
00673 RETURN_PREG return_preg;
00674 const RETURN_PREG * const return_preg_ptr = &return_preg;
00675
00676 const ST *save_var1 = NULL;
00677 const ST *save_var2;
00678 STAB_OFFSET save_offset1 = 0;
00679 STAB_OFFSET save_offset2;
00680 const WN *store1 = NULL;
00681 const WN *store2 = NULL;
00682
00683 const WN * const call_wn = next_stmt;
00684
00685
00686 if (WN_opc_operator(call_wn) == OPR_CALL ||
00687 WN_opc_operator(call_wn) == OPR_PICCALL)
00688 {
00689 Is_True(WN_entry_name(call_wn) != 0,
00690 ("Missing WN_entry_name() for %s",
00691 OPCODE_name(WN_opcode(call_wn))));
00692 return_ty =
00693 W2X_Unparse_Target->Func_Return_Type(ST_pu_type(&St_Table[WN_entry_name(call_wn)]));
00694 }
00695 else if (WN_opc_operator(call_wn) == OPR_ICALL)
00696 {
00697
00698
00699
00700
00701
00702 return_ty = W2X_Unparse_Target->Func_Return_Type(WN_ty(call_wn));
00703 }
00704 else
00705 {
00706 Is_True(WN_opc_operator(call_wn) == OPR_INTRINSIC_CALL,
00707 ("Expected OPR_INTRINSIC_CALL node in Append_CallSite()"));
00708
00709 return_ty = WN_intrinsic_return_ty(WN_opcode(call_wn),
00710 (INTRINSIC)WN_intrinsic(call_wn),
00711 call_wn);
00712 }
00713
00714
00715
00716
00717 return_preg = PUinfo_Get_ReturnPreg(return_ty);
00718
00719
00720 next_stmt = PUINFO_WN_ITER_wn(stmt_iter);
00721
00722
00723 if (RETURN_PREG_num_pregs(return_preg_ptr) > 0 && next_stmt != NULL)
00724 {
00725
00726 store1 =
00727 Does_Stmt_Store_From_Preg(next_stmt,
00728 RETURN_PREG_offset(return_preg_ptr, 0));
00729
00730
00731
00732
00733 if (store1 != NULL)
00734 {
00735
00736 Var_Stored_In(next_stmt, &save_var1, &save_offset1);
00737
00738
00739
00740
00741
00742
00743 stmt_iter = PUINFO_WN_WALK_StmtNext(stmt_iter);
00744 next_stmt = PUINFO_WN_ITER_wn(stmt_iter);
00745
00746
00747
00748
00749 if (RETURN_PREG_num_pregs(return_preg_ptr) > 1 &&
00750 next_stmt != NULL &&
00751 save_var1 != NULL &&
00752 ST_sym_class(save_var1) != CLASS_PREG)
00753 {
00754 store2 =
00755 Does_Stmt_Store_From_Preg(next_stmt,
00756 RETURN_PREG_offset(return_preg_ptr,
00757 1 ));
00758
00759 if (store2 != NULL)
00760 {
00761 Var_Stored_In(next_stmt, &save_var2, &save_offset2);
00762 if (save_var1 == save_var2 && save_offset1 < save_offset2)
00763 stmt_iter = PUINFO_WN_WALK_StmtNext(stmt_iter);
00764 else
00765 {
00766 store1 = store2 = NULL;
00767 save_var1 = NULL;
00768 }
00769 }
00770 else
00771 {
00772 save_var1 = NULL;
00773 store1 = NULL;
00774 }
00775 }
00776 else if (RETURN_PREG_num_pregs(return_preg_ptr) > 1)
00777 {
00778
00779
00780
00781 save_var1 = NULL;
00782 store1 = NULL;
00783 }
00784 }
00785 }
00786
00787 (void)New_CallSite(call_wn, return_ty, store1, store2,
00788 save_var1, save_offset1);
00789
00790 return stmt_iter;
00791 }
00792
00793
00794 static WN_ITER *
00795 Append_ReturnSite(WN_ITER *stmt_iter, const WN *first_stmt)
00796 {
00797
00798
00799
00800 const WN *stmt = first_stmt;
00801 const ST *load_var1 = NULL;
00802 const ST *load_var2;
00803 STAB_OFFSET load_offset1 = 0;
00804 STAB_OFFSET load_offset2;
00805
00806 const WN *store1 = NULL;
00807 const WN *store2 = NULL;
00808
00809
00810
00811
00812 if (RETURN_PREG_num_pregs(PUinfo_return_preg) > 0 &&
00813 WN_opc_operator(stmt) == OPR_STID)
00814 {
00815
00816 store1 =
00817 Does_Stmt_Store_Into_Preg(stmt,
00818 RETURN_PREG_offset(PUinfo_return_preg, 0));
00819
00820
00821
00822
00823 if (store1 != NULL)
00824 {
00825
00826
00827
00828 Var_Loaded_From(WN_kid0(stmt), &load_var1, &load_offset1);
00829
00830
00831 stmt = PUINFO_WN_ITER_wn(stmt_iter);
00832
00833
00834
00835
00836 if (RETURN_PREG_num_pregs(PUinfo_return_preg) > 1 &&
00837 stmt != NULL &&
00838 WN_opc_operator(stmt) == OPR_STID &&
00839 load_var1 != NULL &&
00840 ST_sym_class(load_var1) != CLASS_PREG)
00841 {
00842 store2 =
00843 Does_Stmt_Store_Into_Preg(stmt,
00844 RETURN_PREG_offset(PUinfo_return_preg,
00845 1 ));
00846 if (store2 != NULL)
00847 {
00848 Var_Loaded_From(WN_kid0(stmt), &load_var2, &load_offset2);
00849 if (load_var1 == load_var2 && load_offset1 < load_offset2)
00850 {
00851 stmt_iter = PUINFO_WN_WALK_StmtNext(stmt_iter);
00852 stmt = PUINFO_WN_ITER_wn(stmt_iter);
00853 }
00854 else
00855 {
00856 store1 = store2 = NULL;
00857 load_var1 = NULL;
00858 stmt = first_stmt;
00859 }
00860 }
00861 else
00862 {
00863 store1 = NULL;
00864 load_var1 = NULL;
00865 stmt = first_stmt;
00866 }
00867 }
00868 else if (RETURN_PREG_num_pregs(PUinfo_return_preg) > 1)
00869 {
00870
00871
00872
00873 store1 = NULL;
00874 load_var1 = NULL;
00875 stmt = first_stmt;
00876 }
00877 }
00878 }
00879
00880
00881 if (stmt != NULL && WN_opc_operator(stmt) == OPR_RETURN)
00882 {
00883 (void)New_ReturnSite(stmt, store1, store2, load_var1, load_offset1);
00884
00885 if (stmt != first_stmt)
00886 stmt_iter = PUINFO_WN_WALK_StmtNext(stmt_iter);
00887 }
00888
00889 return stmt_iter;
00890 }
00891
00892
00893
00894
00895
00896 static void
00897 Accumulate_Stmt_PUinfo(WN *wn)
00898 {
00899
00900
00901
00902
00903 WN_ITER *stmt_iter = WN_WALK_StmtIter(wn);
00904 const WN *parent;
00905 const WN *gparent;
00906
00907
00908 while (stmt_iter != NULL)
00909 {
00910 const WN *stmt = PUINFO_WN_ITER_wn(stmt_iter);
00911
00912 if (stmt != NULL)
00913 {
00914 switch(WN_opc_operator(stmt))
00915 {
00916 case OPR_CALL:
00917 case OPR_ICALL:
00918 case OPR_PICCALL:
00919 case OPR_INTRINSIC_CALL:
00920
00921
00922
00923
00924
00925 parent = W2CF_Get_Parent(stmt);
00926 gparent = W2CF_Get_Parent(parent);
00927 if (!WN_in_ioitem(stmt) &&
00928 (WN_opc_operator(gparent) != OPR_REGION ||
00929 WN_region_pragmas(gparent) != parent))
00930 {
00931
00932
00933
00934
00935 stmt_iter =
00936 Append_CallSite(PUINFO_WN_WALK_StmtNext(stmt_iter), stmt);
00937 }
00938 else
00939 stmt_iter = PUINFO_WN_WALK_StmtNext(stmt_iter);
00940 break;
00941
00942 case OPR_STID:
00943
00944
00945
00946
00947 stmt_iter =
00948 Append_ReturnSite(PUINFO_WN_WALK_StmtNext(stmt_iter), stmt);
00949 break;
00950
00951 case OPR_RETURN:
00952
00953
00954
00955 stmt_iter =
00956 Append_ReturnSite(PUINFO_WN_WALK_StmtNext(stmt_iter), stmt);
00957 break;
00958
00959 default:
00960 stmt_iter = PUINFO_WN_WALK_StmtNext(stmt_iter);
00961 break;
00962 }
00963 }
00964 }
00965 }
00966
00967
00968 static void
00969 Accumulate_Expr_PUinfo(WN *root)
00970 {
00971
00972
00973
00974
00975
00976 WN_ITER *wn_iter;
00977 const WN *wn;
00978 const WN *parent;
00979 const WN *gparent;
00980 const WN *next_return_ldid = NULL;
00981 CALLSITE *last_callsite = NULL;
00982
00983
00984 for (wn_iter = WN_WALK_TreeIter(root);
00985 wn_iter != NULL;
00986 wn_iter = PUINFO_WN_WALK_TreeNext(wn_iter))
00987 {
00988
00989
00990
00991
00992
00993 wn = PUINFO_WN_ITER_wn(wn_iter);
00994 if (wn != NULL)
00995 switch(WN_opc_operator(wn))
00996 {
00997 case OPR_STID:
00998 if (ST_sym_class(WN_st(wn)) == CLASS_PREG)
00999 Accumulate_Preg_Info(ST_type(WN_st(wn)), WN_store_offset(wn));
01000
01001
01002
01003
01004
01005
01006
01007 case OPR_ISTORE:
01008 if (last_callsite != NULL &&
01009 (CALLSITE_store1(last_callsite) == wn ||
01010 CALLSITE_store2(last_callsite) == wn))
01011 {
01012
01013 Is_True(WN_operator(WN_kid0(wn)) == OPR_LDID &&
01014 IS_RETURN_PREG(WN_kid0(wn)),
01015 ("Unexpected CALLSITE in Accumulate_Expr_PUinfo()"));
01016
01017 next_return_ldid = WN_kid0(wn);
01018 }
01019 break;
01020
01021 case OPR_LDID:
01022 if (ST_sym_class(WN_st(wn)) == CLASS_PREG)
01023 {
01024 Accumulate_Preg_Info(ST_type(WN_st(wn)), WN_load_offset(wn));
01025
01026
01027
01028
01029
01030
01031 if (next_return_ldid == wn)
01032 next_return_ldid = NULL;
01033 else if (last_callsite != NULL && IS_RETURN_PREG(wn))
01034 CALLSITE_in_regs(last_callsite) = TRUE;
01035 }
01036 break;
01037
01038 case OPR_LDA:
01039
01040 Is_True(ST_sym_class(WN_st(wn)) != CLASS_PREG,
01041 ("Attempt to LDA a PREG in Accumulate_Expr_PUinfo()"));
01042 break;
01043
01044 case OPR_CALL:
01045 case OPR_ICALL:
01046 case OPR_PICCALL:
01047 case OPR_INTRINSIC_CALL:
01048
01049
01050 parent = W2CF_Get_Parent(wn);
01051 gparent = W2CF_Get_Parent(parent);
01052 if (!WN_in_ioitem(wn) &&
01053 (WN_opc_operator(gparent) != OPR_REGION ||
01054 WN_region_pragmas(gparent) != parent))
01055 {
01056
01057
01058
01059
01060
01061 if (last_callsite == NULL)
01062 last_callsite = PUinfo_Get_CallSites();
01063 else
01064 last_callsite = CALLSITE_next(last_callsite);
01065
01066 Is_True(CALLSITE_call(last_callsite) == wn,
01067 ("Unexpected callsite order in Accumulate_Expr_PUinfo()"));
01068 }
01069 break;
01070
01071 case OPR_RETURN:
01072
01073
01074
01075
01076
01077 if (RETURN_PREG_num_pregs(PUinfo_return_preg) > 0)
01078 {
01079 TY_IDX preg_ty;
01080 STAB_OFFSET preg_offset;
01081
01082 preg_offset = RETURN_PREG_offset(PUinfo_return_preg, 0);
01083 preg_ty =
01084 Stab_Mtype_To_Ty(RETURN_PREG_mtype(PUinfo_return_preg, 0));
01085 Accumulate_Preg_Info(preg_ty, preg_offset);
01086 if (RETURN_PREG_num_pregs(PUinfo_return_preg) > 1)
01087 {
01088 preg_offset = RETURN_PREG_offset(PUinfo_return_preg, 1);
01089 preg_ty =
01090 Stab_Mtype_To_Ty(RETURN_PREG_mtype(PUinfo_return_preg, 1));
01091 Accumulate_Preg_Info(preg_ty, preg_offset);
01092 }
01093 }
01094 break;
01095
01096 default:
01097 break;
01098 }
01099 }
01100 }
01101
01102
01103
01104
01105
01106 void
01107 PUinfo_initialize(void)
01108 {
01109 Is_True(PUinfo_local_decls == NULL &&
01110 PUinfo_current_func == NULL &&
01111 PUinfo_return_preg == NULL,
01112 ("Unexpected state in PUinfo_init()"));
01113
01114 }
01115
01116
01117 void
01118 PUinfo_finalize(void)
01119 {
01120
01121 CALLSITE *callsite;
01122 RETURNSITE *returnsite;
01123
01124
01125 while (CallSite_Free != NULL)
01126 {
01127 callsite = CallSite_Free;
01128 CallSite_Free = CALLSITE_next(callsite);
01129 FREE(callsite);
01130 }
01131
01132
01133 while (ReturnSite_Free != NULL)
01134 {
01135 returnsite = ReturnSite_Free;
01136 ReturnSite_Free = CALLSITE_next(returnsite);
01137 FREE(returnsite);
01138 }
01139 }
01140
01141
01142 void
01143 PUinfo_init_pu(const WN *pu, WN *body_part_of_interest)
01144 {
01145
01146
01147
01148
01149
01150
01151 static RETURN_PREG preg_info;
01152
01153 Is_True(WN_operator(pu) == OPR_FUNC_ENTRY,
01154 ("Expected an OPR_FUNC_ENTRY node in PUinfo_init()"));
01155
01156
01157 Is_True(PUinfo_local_decls == NULL &&
01158 PUinfo_pragmas == NULL &&
01159 PUinfo_current_func == NULL &&
01160 PUinfo_return_preg == NULL,
01161 ("Unexpected state in PUinfo_init_pu()"));
01162
01163 PUinfo_current_func = pu;
01164 preg_info = PUinfo_Get_ReturnPreg(PUINFO_RETURN_TY);
01165 PUinfo_return_preg = &preg_info;
01166 PUinfo_local_decls = New_Token_Buffer();
01167 PUinfo_pragmas = New_Token_Buffer();
01168
01169
01170
01171
01172
01173 if (!OPCODE_is_expression(WN_opcode(body_part_of_interest)))
01174 Accumulate_Stmt_PUinfo(body_part_of_interest);
01175
01176
01177
01178
01179
01180
01181 Accumulate_Expr_PUinfo(body_part_of_interest);
01182
01183
01184
01185
01186
01187
01188
01189 W2CF_Symtab_Push();
01190 Enter_Local_Syms_Into_Symtab(&St_Table[WN_entry_name(pu)]);
01191 Enter_Pregs_Into_Symtab();
01192
01193 }
01194
01195
01196 void
01197 PUinfo_exit_pu(void)
01198 {
01199
01200
01201
01202 UINT32 hash_idx;
01203 CALLSITE *callsite;
01204 RETURNSITE *returnsite;
01205
01206
01207 W2CF_Symtab_Pop();
01208
01209
01210 for (hash_idx = 0; hash_idx < PREG_INFO_HASH_TABLE_SIZE; hash_idx++)
01211 {
01212 PREG_INFO *preg_info = Preg_Info_Hash_Tbl[hash_idx];
01213 if (preg_info != NULL)
01214 {
01215 while (PREG_INFO_next(preg_info) != NULL)
01216 preg_info = PREG_INFO_next(preg_info);
01217 PREG_INFO_next(preg_info) = Free_Preg_Info;
01218 Free_Preg_Info = Preg_Info_Hash_Tbl[hash_idx];
01219 Preg_Info_Hash_Tbl[hash_idx] = NULL;
01220 }
01221 }
01222
01223
01224 for (callsite = CallSite_First;
01225 callsite != NULL;
01226 callsite = CALLSITE_next(callsite))
01227 {
01228 CALLSITE_next(callsite) = CallSite_Free;
01229 CallSite_Free = callsite;
01230 }
01231 CallSite_First = NULL;
01232 CallSite_Last = NULL;
01233
01234
01235 for (returnsite = ReturnSite_First;
01236 returnsite != NULL;
01237 returnsite = RETURNSITE_next(returnsite))
01238 {
01239 RETURNSITE_next(returnsite) = ReturnSite_Free;
01240 ReturnSite_Free = returnsite;
01241 }
01242 ReturnSite_First = NULL;
01243 ReturnSite_Last = NULL;
01244
01245
01246 PUinfo_current_func = NULL;
01247 PUinfo_return_preg = NULL;
01248 if (PUinfo_local_decls != NULL)
01249 Reclaim_Token_Buffer(&PUinfo_local_decls);
01250 if (PUinfo_pragmas != NULL)
01251 Reclaim_Token_Buffer(&PUinfo_pragmas);
01252
01253 }
01254
01255
01256 TY_IDX
01257 PUinfo_Preg_Type(TY_IDX preg_ty, INT16 preg_num)
01258 {
01259
01260
01261
01262
01263
01264
01265 TY_IDX ty;
01266 PREG_INFO *preg_info;
01267 INT usage_kind, this_ukind;
01268
01269
01270
01271
01272 if (!TY_Is_Integral(preg_ty))
01273 ty = preg_ty;
01274 else
01275 {
01276 preg_info = Get_Preg_Info(preg_num);
01277 if (preg_info == NULL)
01278 {
01279 Accumulate_Preg_Info(preg_ty, preg_num);
01280 preg_info = Get_Preg_Info(preg_num);
01281 }
01282
01283 this_ukind = (INT)Mtype_to_Ukind(TY_mtype(preg_ty));
01284 for (usage_kind = (INT)LARGEST_iPREG_USAGE_KIND;
01285 (usage_kind >= this_ukind &&
01286 !PREG_INFO_use(preg_info, usage_kind));
01287 usage_kind--);
01288 ty = Stab_Mtype_To_Ty(Ukind_to_Mtype[usage_kind]);
01289 }
01290 return ty;
01291 }
01292
01293
01294 BOOL
01295 PUinfo_Is_Preg_Declared(TY_IDX preg_ty, INT16 preg_num)
01296 {
01297 if (preg_ty == 0 || preg_num == -1)
01298 return TRUE;
01299
01300 PREG_INFO *preg_info = Get_Preg_Info(preg_num);
01301
01302 if (preg_info == NULL)
01303 {
01304 Accumulate_Preg_Info(preg_ty, preg_num);
01305 preg_info = Get_Preg_Info(preg_num);
01306 }
01307
01308 return PREG_INFO_decl(preg_info, Mtype_to_Ukind(TY_mtype(preg_ty)));
01309 }
01310
01311
01312 void
01313 PUinfo_Set_Preg_Declared(TY_IDX preg_ty, INT16 preg_num)
01314 {
01315 PREG_INFO *preg_info = Get_Preg_Info(preg_num);
01316
01317 if (preg_info == NULL)
01318 {
01319 Accumulate_Preg_Info(preg_ty, preg_num);
01320 preg_info = Get_Preg_Info(preg_num);
01321 }
01322
01323 PREG_INFO_decl(preg_info, Mtype_to_Ukind(TY_mtype(preg_ty))) = TRUE;
01324 }
01325
01326
01327 CALLSITE *
01328 PUinfo_Get_CallSites(void)
01329 {
01330 return CallSite_First;
01331 }
01332
01333
01334 RETURNSITE *
01335 PUinfo_Get_ReturnSites(void)
01336 {
01337 return ReturnSite_First;
01338 }
01339
01340
01341 RETURN_PREG
01342 PUinfo_Get_ReturnPreg(TY_IDX return_ty)
01343 {
01344
01345
01346
01347 RETURN_PREG return_preg;
01348 RETURN_PREG * const return_preg_ptr = &return_preg;
01349 PREG_NUM preg_num1, preg_num2;
01350
01351 if (WHIRL_Return_Info_On ) {
01352
01353 RETURN_INFO return_info = Get_Return_Info (return_ty,
01354 Use_Simulated);
01355
01356 if (RETURN_INFO_count(return_info) <= 2) {
01357
01358 RETURN_PREG_mtype(return_preg_ptr, 0) = RETURN_INFO_mtype (return_info, 0);
01359 RETURN_PREG_mtype(return_preg_ptr, 1) = RETURN_INFO_mtype (return_info, 1);
01360 preg_num1 = RETURN_INFO_preg (return_info, 0);
01361 preg_num2 = RETURN_INFO_preg (return_info, 1);
01362 }
01363
01364 else {
01365 Fail_FmtAssertion ("PUinfo_Get_ReturnPreg: more than 2 return registers");
01366 }
01367 }
01368 else {
01369
01370 Get_Return_Mtypes(return_ty,
01371 Use_Simulated,
01372 &RETURN_PREG_mtype(return_preg_ptr, 0),
01373 &RETURN_PREG_mtype(return_preg_ptr, 1));
01374
01375
01376 Get_Return_Pregs(RETURN_PREG_mtype(return_preg_ptr, 0),
01377 RETURN_PREG_mtype(return_preg_ptr, 1),
01378 &preg_num1,
01379 &preg_num2);
01380 }
01381 RETURN_PREG_offset(return_preg_ptr, 0) = preg_num1;
01382 RETURN_PREG_offset(return_preg_ptr, 1) = preg_num2;
01383
01384 if (RETURN_PREG_mtype(return_preg_ptr, 0) == MTYPE_V)
01385 RETURN_PREG_num_pregs(return_preg_ptr) = 0;
01386 else if (RETURN_PREG_mtype(return_preg_ptr, 1) == MTYPE_V)
01387 RETURN_PREG_num_pregs(return_preg_ptr) = 1;
01388 else
01389 RETURN_PREG_num_pregs(return_preg_ptr) = 2;
01390
01391 return return_preg;
01392 }
01393
01394