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 #include <stdio.h>
00037 #include <stdlib.h>
00038 #include <elf_stuff.h>
00039 #include <elfaccess.h>
00040 #include <libelf/libelf.h>
00041 #include <sys/unwindP.h>
00042 #include <list>
00043
00044 #include "defs.h"
00045 #include "erglob.h"
00046 #include "glob.h"
00047 #include "flags.h"
00048 #include "tracing.h"
00049 #include "config.h"
00050 #include "config_asm.h"
00051 #include "be_util.h"
00052 #include "cgir.h"
00053 #include "register.h"
00054 #include "tn_map.h"
00055 #include "em_elf.h"
00056 #include "em_dwarf.h"
00057 #include "cgtarget.h"
00058 #include "calls.h"
00059 #include "cgemit.h"
00060 #include "data_layout.h"
00061 #include "cgdwarf_targ.h"
00062
00063 static BOOL Trace_Unwind = FALSE;
00064
00065
00066
00067
00068
00069 typedef enum {
00070 UNDEFINED_UREGION,
00071 PROLOGUE_UREGION,
00072 EPILOGUE_BODY_UREGION,
00073 LABEL_BODY_UREGION,
00074 COPY_BODY_UREGION
00075 } UREGION_TYPE;
00076
00077
00078 enum {
00079 UE_UNDEFINED,
00080 UE_CREATE_FRAME,
00081 UE_DESTROY_FRAME,
00082 UE_SAVE_GR,
00083 UE_SAVE_SP,
00084 UE_SAVE_PSP,
00085 UE_RESTORE_GR,
00086 UE_RESTORE_MEM,
00087 UE_EPILOG,
00088 UE_LABEL,
00089 UE_COPY
00090 };
00091
00092 typedef struct unwind_elem {
00093 mUINT32 when;
00094 BB *bb;
00095 mUINT8 kind;
00096 mUINT8 qp;
00097 mUINT16 label;
00098 CLASS_REG_PAIR rc_reg;
00099 CLASS_REG_PAIR save_rc_reg;
00100 union {
00101 mINT64 offset;
00102 struct {
00103 mUINT32 size;
00104 mUINT32 start;
00105 } region;
00106 } u;
00107 } UNWIND_ELEM;
00108
00109
00110 static std::list < UNWIND_ELEM > ue_list;
00111 static std::list < UNWIND_ELEM >::iterator ue_iter;
00112 static UINT last_when;
00113 static BOOL simple_unwind = FALSE;
00114 static BOOL has_asm = FALSE;
00115 static UINT last_label = 0;
00116 static BOOL has_create = FALSE;
00117 static TN_MAP tn_def_op;
00118
00119 static const char *
00120 UE_Register_Name (ISA_REGISTER_CLASS rc, REGISTER r)
00121 {
00122 if (rc == ISA_REGISTER_CLASS_branch && r == REGISTER_MIN+0)
00123 return "rp";
00124 else
00125 return REGISTER_name(rc,r);
00126 }
00127
00128 static void
00129 Print_Unwind_Elem (UNWIND_ELEM ue, char *msg)
00130 {
00131 fprintf(TFile, "<%s> at bb %d when %d: ", msg, ue.bb->id, ue.when);
00132 switch (ue.kind) {
00133 case UE_CREATE_FRAME:
00134 fprintf(TFile, " create_frame, size %d, start %d",
00135 ue.u.region.size, ue.u.region.start);
00136 break;
00137 case UE_DESTROY_FRAME:
00138 fprintf(TFile, " destroy_frame");
00139 break;
00140 case UE_EPILOG:
00141 fprintf(TFile, " body epilog, size %d, start %d",
00142 ue.u.region.size, ue.u.region.start);
00143 break;
00144 case UE_LABEL:
00145 fprintf(TFile, " label state %d, size %d, start %d",
00146 ue.label, ue.u.region.size, ue.u.region.start);
00147 break;
00148 case UE_COPY:
00149 fprintf(TFile, " copy label state %d, size %d, start %d",
00150 ue.label, ue.u.region.size, ue.u.region.start);
00151 break;
00152 case UE_SAVE_GR:
00153 fprintf(TFile, " save %s in gr %s",
00154 UE_Register_Name(
00155 CLASS_REG_PAIR_rclass(ue.rc_reg),
00156 CLASS_REG_PAIR_reg(ue.rc_reg) ),
00157 UE_Register_Name(
00158 CLASS_REG_PAIR_rclass(ue.save_rc_reg),
00159 CLASS_REG_PAIR_reg(ue.save_rc_reg) ));
00160 break;
00161 case UE_SAVE_SP:
00162 case UE_SAVE_PSP:
00163 fprintf(TFile, "save %s", UE_Register_Name(
00164 CLASS_REG_PAIR_rclass(ue.rc_reg),
00165 CLASS_REG_PAIR_reg(ue.rc_reg) ));
00166 fprintf(TFile, " to mem %lld(%s)",
00167 ue.u.offset,
00168 (ue.kind == UE_SAVE_SP ? "sp" : "psp") );
00169 break;
00170 case UE_RESTORE_GR:
00171 fprintf(TFile, " restore %s", UE_Register_Name(
00172 CLASS_REG_PAIR_rclass(ue.rc_reg),
00173 CLASS_REG_PAIR_reg(ue.rc_reg) ));
00174 break;
00175 case UE_RESTORE_MEM:
00176 fprintf(TFile, " restore %s from mem", UE_Register_Name(
00177 CLASS_REG_PAIR_rclass(ue.rc_reg),
00178 CLASS_REG_PAIR_reg(ue.rc_reg) ));
00179 break;
00180 }
00181 fprintf(TFile, "\n");
00182 }
00183
00184 static void
00185 Print_All_Unwind_Elem (char *msg)
00186 {
00187 for (ue_iter = ue_list.begin(); ue_iter != ue_list.end(); ++ue_iter) {
00188 Print_Unwind_Elem (*ue_iter, msg);
00189 }
00190 }
00191
00192 static BOOL
00193 TN_Is_Unwind_Reg (TN *tn)
00194 {
00195 if (REGISTER_SET_MemberP(
00196 REGISTER_CLASS_callee_saves(TN_register_class(tn)),
00197 TN_register(tn)))
00198 {
00199 return TRUE;
00200 }
00201 else if (CLASS_REG_PAIR_EqualP(TN_class_reg(tn), CLASS_REG_PAIR_ra)) {
00202 return TRUE;
00203 }
00204 else if (CLASS_REG_PAIR_EqualP(TN_class_reg(tn), CLASS_REG_PAIR_pfs)) {
00205 return TRUE;
00206 }
00207 return FALSE;
00208 }
00209
00210 static OP*
00211 Find_Def_Of_TN (TN *tn, OP *last_op)
00212 {
00213
00214
00215
00216
00217
00218
00219
00220 OP *op = (OP*) TN_MAP_Get (tn_def_op, tn);
00221 if ( op == NULL && REGISTER_SET_MemberP(
00222 REGISTER_CLASS_function_value(TN_register_class(tn)),
00223 TN_register(tn) ) )
00224 {
00225
00226 return NULL;
00227 }
00228 if (op == NULL && Trace_Unwind)
00229 fprintf(TFile, "couldn't find def of tn %d\n", TN_number(tn));
00230 return op;
00231 #if 0
00232
00233 DEF_KIND kind;
00234 OP *op = TN_Reaching_Value_At_Op(tn, last_op, &kind, TRUE);
00235 if (op && OP_has_result(op) && OP_result(op,0) == tn) {
00236 return op;
00237 }
00238
00239
00240 BB *bb;
00241 bb = OP_bb(last_op);
00242 bb = BB_Unique_Predecessor(bb);
00243 if (bb != NULL && BB_call(bb)
00244 && ! REGISTER_SET_MemberP(
00245 REGISTER_CLASS_callee_saves(TN_register_class(tn)),
00246 TN_register(tn) ) )
00247 {
00248 return NULL;
00249 }
00250
00251 DevWarn("unwind: couldn't initially find def of tn %d, so search all bbs", TN_number(tn));
00252 for (BB *bb = REGION_First_BB; bb; bb = BB_next(bb)) {
00253 if (BB_unreachable(bb)) continue;
00254 FOR_ALL_BB_OPs_FWD(bb, op) {
00255 if (op && OP_has_result(op) && OP_result(op,0) == tn) {
00256 return op;
00257 }
00258 }
00259 }
00260 DevWarn("unwind: still couldn't find def of tn %d", TN_number(tn));
00261 return NULL;
00262 #endif
00263 }
00264
00265 static TN*
00266 Find_Spill_TN (OP *last_op, TN *reg_tn)
00267 {
00268
00269 OP *op = Find_Def_Of_TN (reg_tn, last_op);
00270 if (op == NULL) return NULL;
00271 if (OP_code(op) == TOP_adds) {
00272 if (TN_is_symbol(OP_opnd(op,1)))
00273 return OP_opnd(op,1);
00274 }
00275 else if (OP_code(op) == TOP_add
00276 && (OP_opnd(op,2) == FP_TN || OP_opnd(op,2) == SP_TN))
00277 {
00278 op = Find_Def_Of_TN (OP_opnd(op,1), op);
00279 if (op && OP_code(op) == TOP_movl) {
00280 if (TN_is_symbol(OP_opnd(op,1)))
00281 return OP_opnd(op,1);
00282 }
00283 else if (op && OP_code(op) == TOP_mov_i) {
00284 if (TN_is_symbol(OP_opnd(op,1)))
00285 return OP_opnd(op,1);
00286 }
00287 }
00288 return NULL;
00289 }
00290
00291
00292 static TN*
00293 Get_Copied_Save_TN (TN *tn, OP *cur_op)
00294 {
00295
00296 if (TN_is_save_reg(tn))
00297 return tn;
00298 if (TN_is_dedicated(tn))
00299 return NULL;
00300
00301 OP *op = Find_Def_Of_TN (tn, cur_op);
00302 if (!op) return NULL;
00303 TN *otn = CGTARG_Copy_Operand_TN(op);
00304 if (!otn) {
00305 if (OP_code(op) == TOP_alloc)
00306 otn = OP_result(op,0);
00307 if (OP_code(op) == TOP_mov_f_br)
00308 otn = OP_opnd(op,1);
00309 }
00310 if (otn && TN_is_save_reg(otn))
00311 return otn;
00312 else
00313 return NULL;
00314 }
00315
00316
00317
00318 static TN*
00319 Get_Source_Of_Restore (TN *tn, OP *cur_op)
00320 {
00321
00322 if (REGISTER_SET_MemberP(
00323 REGISTER_CLASS_callee_saves(TN_register_class(tn)),
00324 TN_register(tn)))
00325 {
00326 return tn;
00327 }
00328 if (REGISTER_Is_Stacked(TN_register_class(tn), TN_register(tn))) {
00329 return tn;
00330 }
00331
00332 OP *op = Find_Def_Of_TN (tn, cur_op);
00333 if (!op) return tn;
00334 if (OP_load(op)) {
00335
00336 TN *spill_tn = Find_Spill_TN (op,
00337 OP_opnd(op, TOP_Find_Operand_Use(OP_code(op), OU_base) ));
00338 if ( spill_tn) {
00339 return spill_tn;
00340 }
00341 }
00342 return tn;
00343 }
00344
00345 static void
00346 Analyze_OP_For_Unwind_Info (OP *op, UINT when, BB *bb)
00347 {
00348 UNWIND_ELEM ue;
00349 ue.kind = UE_UNDEFINED;
00350 TN *tn;
00351 TOP opc = OP_code(op);
00352
00353 FmtAssert(!OP_simulated(op) || opc== TOP_asm,
00354 ("Found a simulated OP: %s",TOP_Name(opc)));
00355 if (opc == TOP_asm) {
00356 has_asm = TRUE;
00357 }
00358
00359 if (OP_has_result(op) && OP_result(op,0) == SP_TN) {
00360 ue.rc_reg = CLASS_REG_PAIR_sp;
00361 if (BB_entry(bb) && op == BB_entry_sp_adj_op (bb)) {
00362 ue.kind = UE_CREATE_FRAME;
00363 }
00364 else if (BB_exit(bb) && op == BB_exit_sp_adj_op (bb)) {
00365 ue.kind = UE_DESTROY_FRAME;
00366 }
00367 }
00368 else if (OP_has_result(op) && OP_result(op,0) == FP_TN) {
00369
00370 ue.rc_reg = CLASS_REG_PAIR_sp;
00371 if (BB_entry(bb) && op == BB_entry_sp_adj_op (bb)) {
00372 ue.kind = UE_CREATE_FRAME;
00373 }
00374 else if (BB_exit(bb) && op == BB_exit_sp_adj_op (bb)) {
00375 ue.kind = UE_DESTROY_FRAME;
00376 }
00377 }
00378 if (ue.kind == UE_CREATE_FRAME) {
00379 if (has_create) {
00380
00381
00382
00383
00384 ue.kind = UE_UNDEFINED;
00385 }
00386 else has_create = TRUE;
00387 }
00388
00389 if (ue.kind != UE_UNDEFINED)
00390 ;
00391
00392 else if (opc == TOP_alloc) {
00393 ue.kind = UE_SAVE_GR;
00394 ue.rc_reg = CLASS_REG_PAIR_pfs;
00395 ue.save_rc_reg = TN_class_reg(OP_result(op, 0));
00396 }
00397 else if ((opc == TOP_mov_t_ar_r_i
00398 || opc == TOP_mov_t_ar_r_m)
00399 && TN_register(OP_result(op,0)) == REGISTER_pfs)
00400 {
00401 ue.rc_reg = CLASS_REG_PAIR_pfs;
00402 ue.kind = UE_RESTORE_GR;
00403 }
00404
00405
00406 else if (opc == TOP_mov_f_br
00407 && TN_is_save_reg(OP_opnd(op,1))
00408 && TN_save_reg(OP_opnd(op,1)) == REGISTER_ra)
00409 {
00410 ue.kind = UE_SAVE_GR;
00411 ue.rc_reg = CLASS_REG_PAIR_ra;
00412 ue.save_rc_reg = TN_class_reg(OP_result(op, 0));
00413 }
00414 else if (opc == TOP_mov_f_br
00415 && TN_is_save_reg(OP_result(op,0))
00416 && TN_save_reg(OP_result(op,0)) == REGISTER_ra)
00417 {
00418 ue.kind = UE_SAVE_GR;
00419 ue.rc_reg = CLASS_REG_PAIR_ra;
00420 ue.save_rc_reg = TN_class_reg(OP_result(op, 0));
00421 }
00422 else if (opc == TOP_mov_t_br
00423 && TN_is_save_reg(OP_result(op,0))
00424 && TN_save_reg(OP_result(op,0)) == REGISTER_ra)
00425 {
00426 ue.rc_reg = CLASS_REG_PAIR_ra;
00427 ue.kind = UE_RESTORE_GR;
00428 }
00429 else if (opc == TOP_mov_t_br
00430 && TN_is_save_reg(OP_opnd(op,1))
00431 && TN_save_reg(OP_opnd(op,1)) == REGISTER_ra)
00432 {
00433 ue.rc_reg = CLASS_REG_PAIR_ra;
00434 ue.kind = UE_RESTORE_GR;
00435 }
00436 else if ((opc == TOP_mov_f_ar_i || opc == TOP_mov_f_ar_m)
00437 && TN_is_save_reg(OP_result(op,0)))
00438 {
00439 ue.kind = UE_SAVE_GR;
00440 ue.rc_reg = TN_save_creg(OP_result(op,0));
00441 ue.save_rc_reg = TN_class_reg(OP_result(op, 0));
00442 }
00443 else if ((opc == TOP_mov_t_ar_r_i || opc == TOP_mov_t_ar_r_m)
00444 && TN_is_save_reg(OP_opnd(op,1)))
00445 {
00446 ue.kind = UE_RESTORE_GR;
00447 ue.rc_reg = TN_save_creg(OP_opnd(op,1));
00448 }
00449 else if (opc == TOP_mov
00450 && TN_is_save_reg(OP_result(op,0)) )
00451 {
00452 ue.kind = UE_SAVE_GR;
00453 ue.rc_reg = TN_save_creg(OP_result(op,0));
00454 ue.save_rc_reg = TN_class_reg(OP_result(op, 0));
00455 }
00456 else if (opc == TOP_mov
00457 && TN_is_save_reg(OP_opnd(op,1)) )
00458 {
00459 ue.kind = UE_RESTORE_GR;
00460 ue.rc_reg = TN_save_creg(OP_opnd(op,1));
00461 }
00462 else if (OP_store(op)) {
00463
00464
00465 TN *save_tn;
00466 INT opndnum = TOP_Find_Operand_Use(opc, OU_storeval);
00467 FmtAssert(opndnum >= 0, ("no OU_storeval for %s", TOP_Name(opc)));
00468 save_tn = Get_Copied_Save_TN(OP_opnd(op,opndnum), op);
00469 if (save_tn) {
00470 opndnum = TOP_Find_Operand_Use(opc, OU_base);
00471 FmtAssert(opndnum >= 0, ("no OU_base for %s", TOP_Name(opc)));
00472 ue.rc_reg = TN_save_creg(save_tn);
00473 TN *store_tn = OP_opnd(op,opndnum);
00474 if (store_tn == SP_TN) {
00475 ue.kind = UE_SAVE_SP;
00476 ue.u.offset = 0;
00477 }
00478 else if (store_tn == FP_TN) {
00479 ue.kind = UE_SAVE_PSP;
00480 ue.u.offset = 0;
00481 }
00482 else {
00483 TN *spill_tn = Find_Spill_TN (op, store_tn);
00484 if ( ! spill_tn) {
00485 DevWarn("unwind: save but no spill-tn for TN %d",
00486 TN_number(store_tn));
00487 return;
00488 }
00489 ST *base; INT64 offset;
00490 Base_Symbol_And_Offset (TN_var(spill_tn), &base, &offset);
00491 ue.u.offset = offset;
00492 ue.kind = (base == SP_Sym ? UE_SAVE_SP : UE_SAVE_PSP);
00493 }
00494 }
00495 }
00496 else if (OP_load(op)) {
00497 if (TN_is_save_reg(OP_result(op,0)) && TN_Is_Unwind_Reg(OP_result(op,0))) {
00498 ue.kind = UE_RESTORE_MEM;
00499 ue.rc_reg = TN_class_reg(OP_result(op,0));
00500 }
00501 }
00502
00503 if (ue.kind != UE_UNDEFINED) {
00504 ue.qp = 0;
00505 if (OP_has_predicate(op)) {
00506 ue.qp = REGISTER_machine_id (ISA_REGISTER_CLASS_predicate,
00507 TN_register(OP_opnd(op, OP_PREDICATE_OPND)) );
00508 }
00509 if (ue.kind == UE_SAVE_GR) {
00510 ISA_REGISTER_CLASS rc = CLASS_REG_PAIR_rclass(ue.save_rc_reg);
00511 REGISTER reg = CLASS_REG_PAIR_reg(ue.save_rc_reg);
00512 if (ABI_PROPERTY_Is_stacked(rc, REGISTER_machine_id(rc, reg))
00513 && ! BB_rotating_kernel(bb)
00514 && REGISTER_Is_Stacked_Output(rc, reg) )
00515 {
00516 reg = REGISTER_Translate_Stacked_Output(reg);
00517 Set_CLASS_REG_PAIR_reg(ue.save_rc_reg, reg);
00518 }
00519 }
00520 ue.when = when;
00521 ue.bb = bb;
00522 ue_list.push_back (ue);
00523 if (Trace_Unwind) Print_Unwind_Elem (ue, "unwind1");
00524 }
00525 }
00526
00527 static UINT
00528 Get_BB_When_Length (BB *bb)
00529 {
00530 UINT w = 0;
00531 OP *op;
00532 FOR_ALL_BB_OPs_FWD(bb, op) {
00533 if (OP_dummy(op)) continue;
00534 w += OP_Real_Inst_Words(op);
00535 }
00536 return w;
00537 }
00538
00539 static void
00540 Find_Unwind_Info (void)
00541 {
00542 OP *op;
00543 UINT when = 0;
00544 BB_Mark_Unreachable_Blocks ();
00545
00546
00547
00548
00549
00550
00551
00552 tn_def_op = TN_MAP_Create();
00553 for (BB *bb = REGION_First_BB; bb; bb = BB_next(bb)) {
00554 if (BB_unreachable(bb)) continue;
00555 FOR_ALL_BB_OPs_FWD(bb, op) {
00556
00557 if (OP_has_result(op))
00558 TN_MAP_Set (tn_def_op, OP_result(op,0), op);
00559 }
00560 }
00561
00562 for (BB *bb = REGION_First_BB; bb; bb = BB_next(bb)) {
00563 if (BB_unreachable(bb)) {
00564 when += Get_BB_When_Length(bb);
00565 continue;
00566 }
00567 if (Trace_Unwind) Print_BB(bb);
00568 FOR_ALL_BB_OPs_FWD(bb, op) {
00569 if (OP_dummy(op)) continue;
00570 Analyze_OP_For_Unwind_Info(op, when, bb);
00571 when += OP_Real_Inst_Words(op);
00572 }
00573 }
00574 last_when = when - 1;
00575 TN_MAP_Delete (tn_def_op);
00576 }
00577
00578
00579
00580
00581 typedef enum {
00582 PR_SP,
00583 PR_R4,
00584 PR_R5,
00585 PR_R6,
00586 PR_R7,
00587 PR_F2,
00588 PR_F3,
00589 PR_F4,
00590 PR_F5,
00591 PR_F16,
00592 PR_F17,
00593 PR_F18,
00594 PR_F19,
00595 PR_F20,
00596 PR_F21,
00597 PR_F22,
00598 PR_F23,
00599 PR_F24,
00600 PR_F25,
00601 PR_F26,
00602 PR_F27,
00603 PR_F28,
00604 PR_F29,
00605 PR_F30,
00606 PR_F31,
00607 PR_PRED,
00608 PR_RP,
00609 PR_B1,
00610 PR_B2,
00611 PR_B3,
00612 PR_B4,
00613 PR_B5,
00614 PR_PFS,
00615 PR_LC,
00616 PR_FPSR,
00617 PR_UNAT,
00618 PR_RNAT,
00619 PR_PRIUNAT,
00620 PR_BSP,
00621 PR_BSPSTORE,
00622
00623
00624 PR_LAST
00625 } PR_TYPE;
00626 #define PR_FIRST PR_SP
00627 #define INCR(p) (p = static_cast<PR_TYPE>(static_cast<INT>(p) +1))
00628
00629 static PR_TYPE
00630 CR_To_PR (CLASS_REG_PAIR crp)
00631 {
00632 ISA_REGISTER_CLASS rc = CLASS_REG_PAIR_rclass(crp);
00633 INT reg = CLASS_REG_PAIR_reg(crp) - REGISTER_MIN;
00634 switch (rc) {
00635 case ISA_REGISTER_CLASS_integer:
00636 if (reg == 12) return PR_SP;
00637 if (reg >= 4 && reg <= 7) return (PR_TYPE) (PR_R4 + (reg-4));
00638 break;
00639 case ISA_REGISTER_CLASS_float:
00640 if (reg >= 2 && reg <= 5) return (PR_TYPE) (PR_F2 + (reg-2));
00641 if (reg >= 16 && reg <= 31) return (PR_TYPE) (PR_F16 + (reg-16));
00642 break;
00643 case ISA_REGISTER_CLASS_branch:
00644 if (reg == 0) return PR_RP;
00645 if (reg >= 1 && reg <= 5) return (PR_TYPE) (PR_B1 + (reg-1));
00646 break;
00647 case ISA_REGISTER_CLASS_predicate:
00648 return PR_PRED;
00649 break;
00650 case ISA_REGISTER_CLASS_application:
00651 if (reg == 64) return PR_PFS;
00652 if (reg == 65) return PR_LC;
00653 if (reg == 40) return PR_FPSR;
00654 if (reg == 36) return PR_UNAT;
00655 if (reg == 19) return PR_RNAT;
00656 if (reg == 17) return PR_BSP;
00657 if (reg == 18) return PR_BSPSTORE;
00658
00659 break;
00660 default:
00661 FmtAssert(FALSE, ("unexpected rclass in CR_To_PR"));
00662 }
00663 FmtAssert(FALSE, ("unexpected reg (%d,%d) in CR_To_PR", rc, reg));
00664 }
00665
00666 static CLASS_REG_PAIR
00667 PR_To_CR (PR_TYPE p)
00668 {
00669 CLASS_REG_PAIR crp;
00670 switch (p) {
00671 case PR_SP:
00672 crp = CLASS_REG_PAIR_sp; break;
00673 case PR_R4:
00674 case PR_R5:
00675 case PR_R6:
00676 case PR_R7:
00677 Set_CLASS_REG_PAIR_rclass(crp, ISA_REGISTER_CLASS_integer);
00678 Set_CLASS_REG_PAIR_reg(crp, REGISTER_MIN+4 + p-PR_R4);
00679 break;
00680 case PR_F2:
00681 case PR_F3:
00682 case PR_F4:
00683 case PR_F5:
00684 Set_CLASS_REG_PAIR_rclass(crp, ISA_REGISTER_CLASS_float);
00685 Set_CLASS_REG_PAIR_reg(crp, REGISTER_MIN+2 + p-PR_F2);
00686 break;
00687 case PR_F16:
00688 case PR_F17:
00689 case PR_F18:
00690 case PR_F19:
00691 case PR_F20:
00692 case PR_F21:
00693 case PR_F22:
00694 case PR_F23:
00695 case PR_F24:
00696 case PR_F25:
00697 case PR_F26:
00698 case PR_F27:
00699 case PR_F28:
00700 case PR_F29:
00701 case PR_F30:
00702 case PR_F31:
00703 Set_CLASS_REG_PAIR_rclass(crp, ISA_REGISTER_CLASS_float);
00704 Set_CLASS_REG_PAIR_reg(crp, REGISTER_MIN+16 + p-PR_F16);
00705 break;
00706 case PR_RP:
00707 crp = CLASS_REG_PAIR_ra; break;
00708 case PR_B1:
00709 case PR_B2:
00710 case PR_B3:
00711 case PR_B4:
00712 case PR_B5:
00713 Set_CLASS_REG_PAIR_rclass(crp, ISA_REGISTER_CLASS_branch);
00714 Set_CLASS_REG_PAIR_reg(crp, REGISTER_MIN+1 + p-PR_B1);
00715 break;
00716 case PR_PFS:
00717 crp = CLASS_REG_PAIR_pfs; break;
00718 case PR_LC:
00719 crp = CLASS_REG_PAIR_lc; break;
00720 case PR_FPSR:
00721 Set_CLASS_REG_PAIR_rclass(crp, ISA_REGISTER_CLASS_application);
00722 Set_CLASS_REG_PAIR_reg(crp, REGISTER_MIN+40);
00723 break;
00724 case PR_UNAT:
00725 Set_CLASS_REG_PAIR_rclass(crp, ISA_REGISTER_CLASS_application);
00726 Set_CLASS_REG_PAIR_reg(crp, REGISTER_MIN+36);
00727 break;
00728 case PR_RNAT:
00729 Set_CLASS_REG_PAIR_rclass(crp, ISA_REGISTER_CLASS_application);
00730 Set_CLASS_REG_PAIR_reg(crp, REGISTER_MIN+19);
00731 break;
00732 case PR_BSP:
00733 Set_CLASS_REG_PAIR_rclass(crp, ISA_REGISTER_CLASS_application);
00734 Set_CLASS_REG_PAIR_reg(crp, REGISTER_MIN+17);
00735 break;
00736 case PR_BSPSTORE:
00737 Set_CLASS_REG_PAIR_rclass(crp, ISA_REGISTER_CLASS_application);
00738 Set_CLASS_REG_PAIR_reg(crp, REGISTER_MIN+18);
00739 break;
00740 case PR_PRED:
00741 case PR_PRIUNAT:
00742 default:
00743 FmtAssert(FALSE, ("unexpected pr (%d) in PR_To_CR", p));
00744 }
00745 return crp;
00746 }
00747
00748 typedef UINT64 PR_BITSET;
00749 static inline BOOL Get_PR (PR_BITSET state, PR_TYPE p)
00750 {
00751 return (BOOL) ((state >> p) & 1);
00752 }
00753 static inline BOOL Get_PR (PR_BITSET *state, BB *bb, PR_TYPE p)
00754 {
00755 return (BOOL) ((state[bb->id] >> p) & 1);
00756 }
00757 static inline PR_BITSET Set_PR (PR_BITSET state, PR_TYPE p)
00758 {
00759 return (state | (1LL << p));
00760 }
00761 static inline void Set_PR (PR_BITSET *state, BB *bb, PR_TYPE p)
00762 {
00763 state[bb->id] |= (1LL << p);
00764 }
00765 static inline PR_BITSET Clear_PR (PR_BITSET state, PR_TYPE p)
00766 {
00767 return (state & (~(1LL << p)));
00768 }
00769
00770
00771 static void
00772 Mark_Local_Saves_Restores (PR_BITSET *local_save_state,
00773 PR_BITSET *local_restore_state)
00774 {
00775 PR_TYPE p;
00776 memset (local_save_state, 0, ((PU_BB_Count+1) * sizeof(PR_BITSET)));
00777 memset (local_restore_state, 0, ((PU_BB_Count+1) * sizeof(PR_BITSET)));
00778
00779 for (ue_iter = ue_list.begin(); ue_iter != ue_list.end(); ++ue_iter) {
00780 switch (ue_iter->kind) {
00781 case UE_CREATE_FRAME:
00782 case UE_SAVE_GR:
00783 case UE_SAVE_SP:
00784 case UE_SAVE_PSP:
00785 p = CR_To_PR (ue_iter->rc_reg);
00786 Set_PR(local_save_state, ue_iter->bb, p);
00787 break;
00788 case UE_DESTROY_FRAME:
00789 case UE_RESTORE_GR:
00790 case UE_RESTORE_MEM:
00791 p = CR_To_PR (ue_iter->rc_reg);
00792 Set_PR(local_restore_state, ue_iter->bb, p);
00793 break;
00794 }
00795 }
00796 }
00797
00798 static void
00799 Propagate_Save_Restore_State (PR_BITSET *entry_state,
00800 PR_BITSET *local_save_state,
00801 PR_BITSET *local_restore_state,
00802 PR_BITSET *exit_state)
00803 {
00804 BB *bb;
00805 BBLIST *blst;
00806 INT bbid;
00807 BOOL changed = TRUE;
00808 INT count = 0;
00809 memset (entry_state, 0, ((PU_BB_Count+1) * sizeof(PR_BITSET)));
00810 memset (exit_state, -1, ((PU_BB_Count+1) * sizeof(PR_BITSET)));
00811
00812 while (changed) {
00813 ++count;
00814 if (count > 150) {
00815 DevWarn("infinite loop in propagating unwind info");
00816 break;
00817 }
00818 changed = FALSE;
00819 for (bb = REGION_First_BB; bb; bb = BB_next(bb)) {
00820 if (BB_unreachable(bb)) continue;
00821 if (Trace_Unwind)
00822 fprintf (TFile, "curbb: %d, preds: ", BB_id(bb));
00823 if (BB_preds(bb) != NULL) {
00824 PR_BITSET new_entry_state = (PR_BITSET) -1;
00825 FOR_ALL_BB_PREDS (bb, blst) {
00826 bbid = BB_id(BBLIST_item(blst));
00827 new_entry_state &= exit_state[bbid];
00828 if (Trace_Unwind) fprintf (TFile, "[%d %llx], ",
00829 bbid, exit_state[bbid]);
00830 }
00831 entry_state[BB_id(bb)] = new_entry_state;
00832 }
00833 bbid = BB_id(bb);
00834 if (Trace_Unwind)
00835 fprintf (TFile, "\n entry_state: %llx\n", entry_state[bbid]);
00836
00837
00838 PR_BITSET new_exit_state =
00839 entry_state[bbid] | local_save_state[bbid];
00840 new_exit_state &= ~local_restore_state[bbid];
00841 if (new_exit_state != exit_state[bbid]) {
00842 changed = TRUE;
00843 exit_state[bbid] = new_exit_state;
00844 }
00845 }
00846 }
00847 if (Trace_Unwind) {
00848 fprintf(TFile, "bb\tentry\t\tlocal_save\tlocal_restore\texit:\n");
00849 for (INT i = 1; i <= PU_BB_Count; ++i) {
00850 fprintf(TFile, "%4d:\t%12llx\t%12llx\t%12llx\t%12llx\n",
00851 i, entry_state[i], local_save_state[i], local_restore_state[i], exit_state[i]);
00852 }
00853 }
00854 }
00855
00856 static UNWIND_ELEM
00857 Find_Prev_Save_UE_For_BB (std::list < UNWIND_ELEM > prev_ue, BB *bb, UINT level)
00858 {
00859 BBLIST *blst;
00860 std::list < UNWIND_ELEM >::iterator prev_iter;
00861 FOR_ALL_BB_PREDS (bb, blst) {
00862
00863 for (prev_iter = prev_ue.begin(); prev_iter != prev_ue.end(); ++prev_iter) {
00864 if (prev_iter->bb != BBLIST_item(blst)) continue;
00865 if (prev_iter->kind == UE_SAVE_GR || prev_iter->kind == UE_SAVE_SP || prev_iter->kind == UE_SAVE_PSP) {
00866 return *prev_iter;
00867 }
00868 }
00869 }
00870 UNWIND_ELEM ue;
00871 ue.kind = UE_UNDEFINED;
00872 ++level;
00873 if (level > 10) return ue;
00874
00875 FOR_ALL_BB_PREDS (bb, blst) {
00876 ue = Find_Prev_Save_UE_For_BB (prev_ue, BBLIST_item(blst), level);
00877 if (ue.kind != UE_UNDEFINED) return ue;
00878 }
00879 return ue;
00880 }
00881
00882
00883 static void
00884 Add_UE (std::list < UNWIND_ELEM > prev_ue, PR_TYPE p, UINT when, BB *bb)
00885 {
00886 std::list < UNWIND_ELEM >::iterator prev_iter;
00887 UNWIND_ELEM ue;
00888 ue.kind = UE_UNDEFINED;
00889 UINT num_found = 0;
00890 for (prev_iter = prev_ue.begin(); prev_iter != prev_ue.end(); ++prev_iter) {
00891
00892 if (prev_iter->kind == UE_SAVE_GR || prev_iter->kind == UE_SAVE_SP || prev_iter->kind == UE_SAVE_PSP) {
00893 ue = *prev_iter;
00894 ++num_found;
00895 }
00896 }
00897 if (num_found == 0) {
00898 DevWarn("unwind: no pr_info found for %d", p);
00899 return;
00900 }
00901 if (num_found > 1) {
00902
00903 for (prev_iter = prev_ue.begin(); prev_iter != prev_ue.end(); ++prev_iter) {
00904 if (prev_iter->kind == ue.kind
00905 && CLASS_REG_PAIR_EqualP(prev_iter->rc_reg, ue.rc_reg))
00906 --num_found;
00907 }
00908 ++num_found;
00909 }
00910 if (num_found > 1) {
00911 UNWIND_ELEM nue;
00912 nue = Find_Prev_Save_UE_For_BB (prev_ue, bb, 0);
00913 if (nue.kind == UE_UNDEFINED) {
00914
00915 for (prev_iter = prev_ue.begin(); prev_iter != prev_ue.end(); ++prev_iter) {
00916 if (prev_iter->kind == UE_SAVE_SP || prev_iter->kind == UE_SAVE_PSP) {
00917 nue = *prev_iter;
00918 break;
00919 }
00920 }
00921 if (nue.kind == UE_UNDEFINED) {
00922 DevWarn("couldn't find unwind save for %d", p);
00923 }
00924 else
00925 ue = nue;
00926 }
00927 else
00928 ue = nue;
00929 }
00930 ue.when = when;
00931 ue.bb = bb;
00932 ue_list.insert(ue_iter, ue);
00933 if (Trace_Unwind)
00934 fprintf(TFile, "state change for %d at entry to bb %d\n", p, BB_id(bb));
00935 }
00936
00937 static void
00938 Add_UE (INT8 kind, PR_TYPE p, UINT when, BB *bb)
00939 {
00940 UNWIND_ELEM ue;
00941 ue.kind = kind;
00942 ue.qp = 0;
00943 ue.rc_reg = PR_To_CR(p);
00944 ue.when = when;
00945 ue.bb = bb;
00946 ue_list.insert(ue_iter, ue);
00947 if (Trace_Unwind)
00948 fprintf(TFile, "state change for %d at entry to bb %d\n", p, BB_id(bb));
00949 }
00950
00951 static void
00952 Add_UE (INT8 kind, UINT label, UINT when, BB *bb)
00953 {
00954 UNWIND_ELEM ue;
00955 ue.kind = kind;
00956 ue.label = label;
00957 ue.when = when;
00958 ue.bb = bb;
00959 ue_list.insert(ue_iter, ue);
00960 if (Trace_Unwind)
00961 fprintf(TFile, "add ue kind %d label %d at bb %d\n", kind, label, BB_id(bb));
00962 }
00963
00964 static void
00965 Do_Control_Flow_Analysis_Of_Unwind_Info (void)
00966 {
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981 #ifdef linux
00982 PR_BITSET *entry_state =
00983 (PR_BITSET *) alloca((PU_BB_Count+1) * sizeof(PR_BITSET));
00984 PR_BITSET *local_save_state =
00985 (PR_BITSET *) alloca((PU_BB_Count+1) * sizeof(PR_BITSET));
00986 PR_BITSET *local_restore_state =
00987 (PR_BITSET *) alloca((PU_BB_Count+1) * sizeof(PR_BITSET));
00988 PR_BITSET *exit_state =
00989 (PR_BITSET *) alloca((PU_BB_Count+1) * sizeof(PR_BITSET));
00990 #else
00991 PR_BITSET entry_state[PU_BB_Count+1];
00992 PR_BITSET local_save_state[PU_BB_Count+1];
00993 PR_BITSET local_restore_state[PU_BB_Count+1];
00994 PR_BITSET exit_state[PU_BB_Count+1];
00995 #endif
00996
00997
00998 Mark_Local_Saves_Restores (local_save_state, local_restore_state);
00999
01000
01001
01002 Propagate_Save_Restore_State (entry_state, local_save_state,
01003 local_restore_state, exit_state);
01004
01005 PR_TYPE p;
01006
01007 std::list < UNWIND_ELEM > pr_last_info[PR_LAST];
01008 for (ue_iter = ue_list.begin(); ue_iter != ue_list.end(); ++ue_iter) {
01009 p = CR_To_PR (ue_iter->rc_reg);
01010
01011 if ( ! pr_last_info[p].empty()
01012 && pr_last_info[p].front().bb == ue_iter->bb)
01013 {
01014 pr_last_info[p].pop_front();
01015 }
01016 pr_last_info[p].push_front (*ue_iter);
01017 }
01018
01019
01020
01021 PR_BITSET current_state = 0;
01022 INT bbid;
01023 UINT lwhen = 0;
01024 ue_iter = ue_list.begin();
01025
01026
01027 bool label_state = FALSE;
01028 bool copy_state = FALSE;
01029 for (BB *bb = REGION_First_BB; bb; bb = BB_next(bb)) {
01030 if (label_state && BB_prev(bb) != NULL && BB_exit(BB_prev(bb))) {
01031 copy_state = TRUE;
01032 }
01033 if (BB_unreachable(bb)) {
01034 lwhen += Get_BB_When_Length(bb);
01035 continue;
01036 }
01037 if (BB_length(bb) == 0) {
01038
01039 continue;
01040 }
01041 bbid = BB_id(bb);
01042
01043
01044
01045 if (BB_entry(bb)) {
01046 current_state = entry_state[bbid];
01047 }
01048
01049
01050
01051 if (copy_state) {
01052
01053 Add_UE (UE_COPY, last_label, lwhen, bb);
01054 current_state = entry_state[BB_id(BB_prev(bb))];
01055 label_state = FALSE;
01056 }
01057 if (BB_exit(bb) && BB_next(bb) != NULL) {
01058
01059
01060
01061 if (BB_entry(bb) && BB_prev(bb) == NULL) {
01062
01063
01064 while (ue_iter != ue_list.end() && ue_iter->bb == bb) {
01065 if (ue_iter->kind == UE_CREATE_FRAME) {
01066
01067
01068 label_state = TRUE;
01069 ++ue_iter;
01070 Add_UE (UE_LABEL, ++last_label,
01071 ue_iter->when, bb);
01072 break;
01073 }
01074 ++ue_iter;
01075 }
01076 }
01077 else {
01078
01079
01080 label_state = TRUE;
01081 Add_UE (UE_LABEL, ++last_label, lwhen, bb);
01082 }
01083 }
01084
01085
01086
01087
01088 if (0) {
01089 for (p = PR_FIRST; p < PR_LAST; INCR(p)) {
01090
01091
01092 if (p == PR_SP) continue;
01093 if (Get_PR(current_state,p) != Get_PR(entry_state[bbid],p))
01094 {
01095
01096 if (Get_PR(entry_state[bbid],p) == FALSE) {
01097
01098 Add_UE (UE_RESTORE_GR, p, lwhen, bb);
01099 }
01100 else {
01101
01102 Add_UE (pr_last_info[p], p, lwhen, bb);
01103 }
01104 }
01105 }
01106 current_state = entry_state[bbid];
01107 }
01108
01109
01110 while (ue_iter != ue_list.end() && ue_iter->bb == bb) {
01111 p = CR_To_PR (ue_iter->rc_reg);
01112 if (Trace_Unwind) fprintf(TFile,
01113 "state change for %d in bb %d\n", p, bbid);
01114 if (ue_iter->kind == UE_RESTORE_GR
01115 || ue_iter->kind == UE_RESTORE_MEM)
01116 {
01117 current_state = Clear_PR(current_state, p);
01118 }
01119 else {
01120 current_state = Set_PR(current_state, p);
01121 }
01122 ++ue_iter;
01123 }
01124 lwhen += Get_BB_When_Length(bb);
01125 }
01126 }
01127
01128
01129 static BOOL
01130 Is_Unwind_Simple (void)
01131 {
01132 if (has_asm) return FALSE;
01133
01134 for (ue_iter = ue_list.begin(); ue_iter != ue_list.end(); ++ue_iter) {
01135
01136 if (BB_prev(ue_iter->bb) != NULL && BB_next(ue_iter->bb) != NULL) {
01137 return FALSE;
01138 }
01139
01140 if ( ! BB_entry(ue_iter->bb) && ! BB_exit(ue_iter->bb)) {
01141 return FALSE;
01142 }
01143 }
01144 return TRUE;
01145 }
01146
01147 static void
01148 Insert_Epilogs (void)
01149 {
01150 std::list < UNWIND_ELEM >::iterator prev_ue;
01151 UNWIND_ELEM ue;
01152 for (ue_iter = ue_list.begin(); ue_iter != ue_list.end(); ++ue_iter) {
01153 switch (ue_iter->kind) {
01154 case UE_DESTROY_FRAME:
01155
01156 prev_ue = ue_iter;
01157 --prev_ue;
01158 while (prev_ue != ue_list.begin()) {
01159 if (prev_ue->bb != ue_iter->bb) break;
01160 if (prev_ue->kind != UE_RESTORE_GR && prev_ue->kind != UE_RESTORE_MEM)
01161 break;
01162 --prev_ue;
01163 }
01164 ++prev_ue;
01165 ue.kind = UE_EPILOG;
01166 ue.when = prev_ue->when;
01167 ue.bb = prev_ue->bb;
01168 ue_list.insert(prev_ue, ue);
01169 if (Trace_Unwind)
01170 fprintf(TFile, "add epilog at bb %d, when %d\n", BB_id(ue.bb), ue.when);
01171 }
01172 }
01173 }
01174
01175
01176 static void
01177 Compute_Region_Sizes (void)
01178 {
01179 std::list < UNWIND_ELEM >::iterator current_ue = ue_list.end();
01180 for (ue_iter = ue_list.begin(); ue_iter != ue_list.end(); ++ue_iter) {
01181 switch (ue_iter->kind) {
01182 case UE_CREATE_FRAME:
01183
01184 Is_True (current_ue == ue_list.end(), ("multiple unwind create frames?"));
01185 current_ue = ue_iter;
01186 current_ue->u.region.start = 0;
01187 break;
01188 case UE_EPILOG:
01189 case UE_LABEL:
01190 case UE_COPY:
01191
01192 current_ue->u.region.size = ue_iter->when - current_ue->u.region.start;
01193 current_ue = ue_iter;
01194 current_ue->u.region.start = ue_iter->when;
01195 break;
01196 }
01197 }
01198 if (current_ue != ue_list.end())
01199 current_ue->u.region.size = last_when - current_ue->u.region.start + 1;
01200 }
01201
01202 static UINT next_when;
01203 static UREGION_TYPE proc_region;
01204
01205
01206 void
01207 Init_Unwind_Info (BOOL trace)
01208 {
01209 Trace_Unwind = trace;
01210 has_asm = FALSE;
01211 has_create = FALSE;
01212
01213 Find_Unwind_Info ();
01214 simple_unwind = Is_Unwind_Simple();
01215
01216 last_label = 0;
01217 next_when = 0;
01218 proc_region = UNDEFINED_UREGION;
01219
01220 if ( ! simple_unwind) {
01221 if (Trace_Unwind) fprintf (TFile, "need to propagate unwind info\n");
01222
01223
01224 Do_Control_Flow_Analysis_Of_Unwind_Info ();
01225 if ( ! has_asm) simple_unwind = TRUE;
01226 }
01227 Insert_Epilogs();
01228 Compute_Region_Sizes();
01229
01230 if (Trace_Unwind) {
01231 fprintf (TFile, "%s unwind\n", (simple_unwind ? "simple" : "complicated"));
01232 Print_All_Unwind_Elem ("unwind2");
01233 }
01234
01235
01236 ue_iter = ue_list.begin();
01237 }
01238
01239 void
01240 Finalize_Unwind_Info(void)
01241 {
01242 ue_list.clear();
01243 }
01244
01245
01246
01247
01248 static BOOL
01249 Use_Spill_Record (CLASS_REG_PAIR crp)
01250 {
01251 if (CLASS_REG_PAIR_EqualP(crp, CLASS_REG_PAIR_ra))
01252 return FALSE;
01253 if (CLASS_REG_PAIR_EqualP(crp, CLASS_REG_PAIR_pfs))
01254 return FALSE;
01255 if (CLASS_REG_PAIR_EqualP(crp, CLASS_REG_PAIR_lc))
01256 return FALSE;
01257 return TRUE;
01258 }
01259
01260 void
01261 Emit_Unwind_Directives_For_OP(OP *op, FILE *f)
01262 {
01263 char prefix[3];
01264 if ( CG_emit_unwind_directives)
01265 strcpy(prefix, "");
01266 else
01267 strcpy(prefix, "//");
01268
01269 if (ue_iter == ue_list.end()) {
01270 if (proc_region == UNDEFINED_UREGION) {
01271
01272
01273 fprintf(f, "%s\t.unwentry\n", prefix);
01274 proc_region = PROLOGUE_UREGION;
01275 }
01276 return;
01277 }
01278 if (OP_dummy(op)) return;
01279
01280 if (proc_region == UNDEFINED_UREGION) {
01281 fprintf(f, "%s\t.prologue\n", prefix);
01282 proc_region = PROLOGUE_UREGION;
01283 }
01284
01285 while (ue_iter != ue_list.end() && ue_iter->when == next_when) {
01286 ISA_REGISTER_CLASS rc = CLASS_REG_PAIR_rclass(ue_iter->rc_reg);
01287 REGISTER reg = CLASS_REG_PAIR_reg(ue_iter->rc_reg);
01288
01289 switch (ue_iter->kind) {
01290 case UE_CREATE_FRAME:
01291 if (Current_PU_Stack_Model == SMODEL_SMALL) {
01292 fprintf(f, "%s\t.fframe %lld\n", prefix, Frame_Len);
01293 } else {
01294 fprintf(f, "%s\t.vframe %s\n",
01295 prefix,
01296 UE_Register_Name(TN_register_class(FP_TN), TN_register(FP_TN)));
01297 }
01298 break;
01299 case UE_EPILOG:
01300 fprintf(f, "%s\t.body\n", prefix);
01301 proc_region = EPILOGUE_BODY_UREGION;
01302 break;
01303 case UE_DESTROY_FRAME:
01304
01305
01306
01307
01308 if (Omit_UE_DESTROY_FRAME)
01309 break;
01310 else
01311 fprintf(f, "%s\t.restore %s\n",
01312 prefix,
01313 UE_Register_Name(TN_register_class(SP_TN), TN_register(SP_TN)));
01314 break;
01315 case UE_LABEL:
01316 fprintf(f, "%s\t.body\n", prefix);
01317 proc_region = LABEL_BODY_UREGION;
01318 fprintf(f, "%s\t.label_state %d\n", prefix, ue_iter->label);
01319 break;
01320 case UE_COPY:
01321 fprintf(f, "%s\t.body\n", prefix);
01322 proc_region = COPY_BODY_UREGION;
01323 fprintf(f, "%s\t.copy_state %d\n", prefix, ue_iter->label);
01324 break;
01325 case UE_RESTORE_MEM:
01326
01327 break;
01328 case UE_RESTORE_GR:
01329
01330 if (proc_region == EPILOGUE_BODY_UREGION)
01331 break;
01332 if (ue_iter->qp != 0) {
01333 fprintf(f, "%s\t.restorereg.p p%d, %s\n", prefix,
01334 ue_iter->qp,
01335 UE_Register_Name(rc, reg) );
01336 }
01337 else {
01338 fprintf(f, "%s\t.restorereg %s\n", prefix,
01339 UE_Register_Name(rc, reg) );
01340 }
01341 break;
01342 case UE_SAVE_GR:
01343 if (ue_iter->qp != 0) {
01344 fprintf(f, "%s\t%s p%d, %s, %s\n", prefix, ".spillreg.p",
01345 ue_iter->qp,
01346 UE_Register_Name(rc, reg),
01347 UE_Register_Name( CLASS_REG_PAIR_rclass(ue_iter->save_rc_reg),
01348 CLASS_REG_PAIR_reg(ue_iter->save_rc_reg) ) );
01349 }
01350 else {
01351 fprintf(f, "%s\t%s %s, %s\n", prefix,
01352 (Use_Spill_Record (ue_iter->rc_reg) ? ".spillreg" : ".save"),
01353 UE_Register_Name(rc, reg),
01354 UE_Register_Name( CLASS_REG_PAIR_rclass(ue_iter->save_rc_reg),
01355 CLASS_REG_PAIR_reg(ue_iter->save_rc_reg) ) );
01356 }
01357 break;
01358 case UE_SAVE_SP:
01359 if (ue_iter->qp != 0) {
01360 fprintf(f, "%s\t%s p%d, %s, %lld\n", prefix, ".spillsp.p",
01361 ue_iter->qp,
01362 UE_Register_Name(rc, reg),
01363 ue_iter->u.offset);
01364 }
01365 else {
01366 fprintf(f, "%s\t%s %s, %lld\n", prefix,
01367 Use_Spill_Record (ue_iter->rc_reg) ? ".spillsp" : ".savesp",
01368 UE_Register_Name(rc, reg),
01369 ue_iter->u.offset);
01370 }
01371 break;
01372 case UE_SAVE_PSP:
01373 if (ue_iter->qp != 0) {
01374 fprintf(f, "%s\t%s p%d, %s, %lld\n", prefix, ".spillpsp.p",
01375 ue_iter->qp,
01376 UE_Register_Name(rc, reg),
01377 ue_iter->u.offset);
01378 }
01379 else {
01380 fprintf(f, "%s\t%s %s, %lld\n", prefix,
01381 Use_Spill_Record (ue_iter->rc_reg) ? ".spillpsp" : ".savepsp",
01382 UE_Register_Name(rc, reg),
01383 ue_iter->u.offset);
01384 }
01385 break;
01386 default:
01387 FmtAssert(FALSE, ("Unhandled UNWIND_ELEM kind (%d)\n", ue_iter->kind));
01388
01389 }
01390
01391 ++ue_iter;
01392 }
01393
01394 next_when += OP_Real_Inst_Words(op);
01395 }
01396
01397
01398
01399 static void
01400 Add_Prologue_Header (__unw_info_t *uinfo, UINT64 size)
01401 {
01402 __unw_error_t st = 0;
01403 if (Trace_Unwind) fprintf(TFile, "prolog header size %llu\n", size);
01404 st |= unwind_info_add_prologue_header(uinfo, size);
01405 Is_True(st == __UNW_OK, ("unwind_info prolog error (%d)", st));
01406 }
01407 static void
01408 Add_Body_Header (__unw_info_t *uinfo, UINT64 size)
01409 {
01410 __unw_error_t st = 0;
01411 if (Trace_Unwind) fprintf(TFile, "body header size %llu\n", size);
01412 st = unwind_info_add_body_header(uinfo, size);
01413 Is_True(st == __UNW_OK, ("unwind_info body error (%d)", st));
01414 }
01415
01416
01417 static void
01418 Create_Unwind_Descriptors (__unw_info_t *uinfo)
01419 {
01420 __unw_error_t st = 0;
01421 ISA_REGISTER_CLASS rc;
01422 REGISTER reg;
01423 UREGION_TYPE uregion = UNDEFINED_UREGION;
01424 UINT start_when = 0;
01425 UINT end_when = 0;
01426
01427 if (!simple_unwind) return;
01428
01429 for (ue_iter = ue_list.begin(); ue_iter != ue_list.end(); ++ue_iter) {
01430 if (ue_iter->kind == UE_CREATE_FRAME)
01431 break;
01432 }
01433 if (ue_iter == ue_list.end()) {
01434
01435 Add_Prologue_Header (uinfo, last_when);
01436 }
01437 else {
01438 Add_Prologue_Header (uinfo, ue_iter->u.region.size);
01439
01440 if (Current_PU_Stack_Model == SMODEL_SMALL) {
01441 if (Trace_Unwind) fprintf(TFile, "fixed stack frame of size %lld, set at when %d\n",
01442 Frame_Len, ue_iter->when);
01443 st |= unwind_info_add_prologue_mem_stack_f_info(uinfo,
01444 ue_iter->when, Frame_Len / INST_BYTES);
01445 }
01446 else {
01447 if (Trace_Unwind) fprintf(TFile, "large or variable-size stack frame, when = %d\n", ue_iter->when);
01448 st |= unwind_info_add_prologue_mem_stack_v_info (uinfo, ue_iter->when);
01449 st |= unwind_info_add_prologue_psp_gr_info (uinfo,
01450 REGISTER_machine_id (
01451 TN_register_class(FP_TN), TN_register(FP_TN) ) );
01452 }
01453 Is_True(st == __UNW_OK, ("unwind_info mem_stack error (%d)", st));
01454 }
01455 uregion = PROLOGUE_UREGION;
01456
01457 for (ue_iter = ue_list.begin(); ue_iter != ue_list.end(); ++ue_iter) {
01458 switch (ue_iter->kind) {
01459 case UE_EPILOG:
01460 Add_Body_Header (uinfo, ue_iter->u.region.size);
01461 uregion = EPILOGUE_BODY_UREGION;
01462 start_when = ue_iter->u.region.start;
01463 end_when = start_when + ue_iter->u.region.size;
01464 break;
01465 case UE_DESTROY_FRAME:
01466 {
01467 INT when_from_end = end_when - ue_iter->when - 1;
01468 Is_True(end_when != 0, ("unwind: no epilog before destroy_frame?"));
01469 if (Trace_Unwind) fprintf(TFile, "body epilogue at when %d\n", when_from_end);
01470 st |= unwind_info_add_body_epilogue_info(uinfo, when_from_end, 0);
01471 Is_True(st == __UNW_OK, ("unwind_info frame restore error (%d)",st));
01472 }
01473 break;
01474 case UE_LABEL:
01475 Add_Body_Header (uinfo, ue_iter->u.region.size);
01476 uregion = LABEL_BODY_UREGION;
01477
01478 if (Trace_Unwind) fprintf(TFile, "body label at when %d\n", ue_iter->when);
01479 st |= unwind_info_add_body_label_state_info(uinfo, ue_iter->label);
01480 Is_True(st == __UNW_OK, ("unwind_info label error (%d)",st));
01481 start_when = ue_iter->u.region.start;
01482 break;
01483 case UE_COPY:
01484 Add_Body_Header (uinfo, ue_iter->u.region.size);
01485 uregion = COPY_BODY_UREGION;
01486
01487 if (Trace_Unwind) fprintf(TFile, "body copy at when %d\n", ue_iter->when);
01488 st |= unwind_info_add_body_copy_state_info(uinfo, ue_iter->label);
01489 Is_True(st == __UNW_OK, ("unwind_info copy error (%d)",st));
01490 start_when = ue_iter->u.region.start;
01491 break;
01492
01493 case UE_SAVE_GR:
01494 {
01495 rc = CLASS_REG_PAIR_rclass(ue_iter->rc_reg);
01496 reg = CLASS_REG_PAIR_reg(ue_iter->rc_reg);
01497 ISA_REGISTER_CLASS save_rc = CLASS_REG_PAIR_rclass(ue_iter->save_rc_reg);
01498 REGISTER save_reg = CLASS_REG_PAIR_reg(ue_iter->save_rc_reg);
01499 if (Trace_Unwind) fprintf(TFile, "save reg to reg at when %d\n", ue_iter->when);
01500
01501 if (uregion == PROLOGUE_UREGION) {
01502 st |= unwind_info_add_prologue_info_reg (
01503 uinfo,
01504 rc,
01505 REGISTER_machine_id(rc, reg),
01506 ue_iter->when - start_when,
01507 save_rc,
01508 REGISTER_machine_id(save_rc, save_reg));
01509 }
01510 else {
01511
01512 st |= unwind_info_add_body_info_reg (
01513 uinfo,
01514 rc,
01515 REGISTER_machine_id(rc, reg),
01516 ue_iter->when - start_when,
01517 save_rc,
01518 REGISTER_machine_id(save_rc, save_reg));
01519 }
01520 }
01521 Is_True(st == __UNW_OK, ("unwind_info save error (%d) on reg %s",
01522 st, UE_Register_Name(rc, reg) ));
01523 break;
01524
01525 case UE_SAVE_SP:
01526 rc = CLASS_REG_PAIR_rclass(ue_iter->rc_reg);
01527 reg = CLASS_REG_PAIR_reg(ue_iter->rc_reg);
01528 if (Trace_Unwind) fprintf(TFile, "save reg to sp mem at when %d\n", ue_iter->when);
01529 if (uregion == PROLOGUE_UREGION) {
01530 st |= unwind_info_add_prologue_info_sp_offset(
01531 uinfo,
01532 rc,
01533 REGISTER_machine_id(rc, reg),
01534 ue_iter->when - start_when,
01535 ue_iter->u.offset);
01536 }
01537 else {
01538 st |= unwind_info_add_body_info_sp_offset(
01539 uinfo,
01540 rc,
01541 REGISTER_machine_id(rc, reg),
01542 ue_iter->when - start_when,
01543 ue_iter->u.offset);
01544 }
01545 Is_True(st == __UNW_OK, ("unwind_info prolog error (%d) on reg %s",
01546 st, UE_Register_Name(rc, reg) ));
01547 break;
01548
01549 case UE_SAVE_PSP:
01550 rc = CLASS_REG_PAIR_rclass(ue_iter->rc_reg);
01551 reg = CLASS_REG_PAIR_reg(ue_iter->rc_reg);
01552
01553 if (Trace_Unwind) fprintf(TFile, "save reg to psp mem at when %d\n", ue_iter->when);
01554 if (uregion == PROLOGUE_UREGION) {
01555 st |= unwind_info_add_prologue_info_psp_offset(
01556 uinfo,
01557 rc,
01558 REGISTER_machine_id(rc, reg),
01559 ue_iter->when - start_when,
01560 ue_iter->u.offset);
01561 }
01562 else {
01563 st |= unwind_info_add_body_info_psp_offset(
01564 uinfo,
01565 rc,
01566 REGISTER_machine_id(rc, reg),
01567 ue_iter->when - start_when,
01568 ue_iter->u.offset);
01569 }
01570 Is_True(st == __UNW_OK, ("unwind_info prolog error (%d) on reg %s",
01571 st, UE_Register_Name(rc, reg) ));
01572 break;
01573
01574 case UE_RESTORE_MEM:
01575
01576 break;
01577 case UE_RESTORE_GR:
01578
01579 if (uregion == EPILOGUE_BODY_UREGION)
01580 break;
01581 rc = CLASS_REG_PAIR_rclass(ue_iter->rc_reg);
01582 reg = CLASS_REG_PAIR_reg(ue_iter->rc_reg);
01583 if (Trace_Unwind) fprintf(TFile, "restore reg at when %d\n", ue_iter->when);
01584 st |= unwind_info_add_body_info_restore (uinfo,
01585 rc,
01586 REGISTER_machine_id(rc, reg),
01587 ue_iter->when - start_when);
01588 Is_True(st == __UNW_OK, ("unwind_info restore error (%d) on reg %s",
01589 st, UE_Register_Name(rc, reg) ));
01590 break;
01591 }
01592 }
01593 }
01594
01595
01596 __unw_error_t
01597 unwind_dump2asm (char *unwind_table_ptr,
01598 __uint64_t unwind_table_size,
01599 char *unwind_info_ptr,
01600 __uint64_t unwind_info_size,
01601 void *arg)
01602 {
01603 static __uint64_t last_info_size = 0;
01604 static __uint64_t last_table_size = 0;
01605 __uint64_t i;
01606 __uint64_t unwind_table_size_in_entries =
01607 unwind_table_size/sizeof(__unw_table_entry_t);
01608 fprintf(Asm_File, "// emit unwind info\n");
01609
01610 fprintf(Asm_File, "\t%s %s\n", AS_SECTION, IA64_UNWIND_INFO);
01611
01612 fprintf(Asm_File, ".Lunwind_info_%d:\n", Current_PU_Count());
01613 for (i = last_info_size; i < unwind_info_size; i+=8) {
01614 fprintf(Asm_File, "\t%s %#llx\n", AS_DWORD, (UINT64)*(__uint64_t *)(unwind_info_ptr+i));
01615 }
01616 fprintf(Asm_File, "\t%s %s\n", AS_SECTION, IA64_UNWIND);
01617
01618 i = last_table_size;
01619 fprintf(Asm_File, "\t%s @segrel(%s#)\n", AS_DWORD, Cur_PU_Name);
01620 i+=8;
01621 fprintf(Asm_File, "\t%s @segrel(%s#+%p)\n", AS_DWORD, Cur_PU_Name, arg);
01622 fprintf(Asm_File, "\t%s @segrel(.Lunwind_info_%d)\n", AS_DWORD, Current_PU_Count());
01623 last_info_size = unwind_info_size;
01624 last_table_size = unwind_table_size;
01625 }
01626
01627
01628 extern Dwarf_P_Fde
01629 Build_Fde_For_Proc (Dwarf_P_Debug dw_dbg, BB *firstbb,
01630 LABEL_IDX begin_label,
01631 LABEL_IDX end_label,
01632 INT32 end_offset,
01633
01634
01635
01636 INT low_pc,
01637 INT high_pc)
01638 {
01639 __unw_info_t *uinfo = NULL;
01640 __unw_error_t st;
01641
01642 if ( ! CG_emit_unwind_info) return NULL;
01643 if ( CG_emit_unwind_directives) return NULL;
01644
01645
01646 st = unwind_info_initialize(&uinfo, low_pc, high_pc);
01647 Is_True(st == __UNW_OK, ("unwind_info initialize error (%d)", st));
01648
01649
01650 Create_Unwind_Descriptors (uinfo);
01651
01652 st = unwind_info_finalize(uinfo);
01653 FmtAssert(st == __UNW_OK, ("unwind_info finalize error (%d)", st));
01654
01655 if (has_asm)
01656 DevWarn("no unwind info cause PU has asm");
01657 else if ( ! simple_unwind)
01658 DevWarn("no unwind info cause PU is too complicated");
01659 if (simple_unwind) {
01660 unwind_process (unwind_dump2asm, (void*)(INTPTR)(high_pc-low_pc));
01661 }
01662 return NULL;
01663 }
01664
01665 #include <elf_stuff.h>
01666 #include <elfaccess.h>
01667
01668 void
01669 Check_Dwarf_Rel(const Elf32_Rel ¤t_reloc)
01670 {
01671 FmtAssert(REL32_type(current_reloc) == R_IA_64_DIR32MSB,
01672 ("Unimplemented 32-bit relocation type %d",
01673 REL32_type(current_reloc)));
01674 }
01675
01676 void
01677 Check_Dwarf_Rel(const Elf64_AltRel ¤t_reloc)
01678 {
01679 FmtAssert(REL64_type(current_reloc) == R_IA_64_DIR64MSB,
01680 ("Unimplemented 64-bit relocation type %d",
01681 REL64_type(current_reloc)));
01682 }
01683
01684 void
01685 Check_Dwarf_Rela(const Elf64_AltRela ¤t_reloc)
01686 {
01687 FmtAssert(FALSE,
01688 ("Unimplemented 64-bit relocation type %d",
01689 REL64_type(current_reloc)));
01690 }
01691
01692 void
01693 Check_Dwarf_Rela(const Elf32_Rela ¤t_reloc)
01694 {
01695 FmtAssert(FALSE,
01696 ("Unimplemented 32-bit relocation type %d",
01697 REL32_type(current_reloc)));
01698 }
01699 static char *drop_these[] = {
01700
01701
01702 ".debug_line",
01703
01704
01705 ".debug_weaknames",
01706 ".debug_varnames",
01707 ".debug_typenames",
01708 ".debug_funcnames",
01709
01710 ".debug_frame",
01711 ".eh_frame",
01712 0
01713 };
01714
01715
01716 extern BOOL Is_Dwarf_Section_To_Emit(const char *name)
01717 {
01718
01719 for(int i = 0; drop_these[i]; ++i) {
01720 if(strcmp(name,drop_these[i]) == 0) {
01721 return FALSE;
01722 }
01723 }
01724 return TRUE;
01725 }
01726