00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include "libelf/libelf.h"
00004 #include <sys/unwindP.h>
00005 #include <list>
00006 #include "elf_stuff.h"
00007 #include <elfaccess.h>
00008 #include "dwarf.h"
00009
00010 #include "defs.h"
00011 #include "erglob.h"
00012 #include "glob.h"
00013 #include "flags.h"
00014 #include "tracing.h"
00015 #include "em_elf.h"
00016 #include "em_dwarf.h"
00017 #include "config.h"
00018 #include "config_asm.h"
00019 #include "cgir.h"
00020 #include "register.h"
00021 #include "cgtarget.h"
00022 #include "calls.h"
00023 #include "stblock.h"
00024 #include "data_layout.h"
00025 #include "cg_spill.h"
00026 #include "cgdwarf.h"
00027 #include "cgdwarf_targ.h"
00028 #include "dwarf_incl.h"
00029 #include "pro_opaque.h"
00030 #include "pro_frame.h"
00031 #include "be_util.h"
00032
00033 static Dwarf_Error dw_error;
00034 static BOOL Trace_Unwind = TRUE;
00035 static UINT last_when;
00036 static BOOL simple_unwind = FALSE;
00037 static BOOL has_asm = FALSE;
00038 static UINT last_label = 0;
00039 static BOOL has_create = FALSE;
00040
00041
00042
00043
00044
00045
00046
00047 #define FD_R0 0
00048 #define FD_RA FD_R0 // we don't anticipate R0 save/spill
00049 #define FD_R1 1
00050 #define FD_R2 2
00051 #define FD_SL FD_R2
00052 #define FD_R3 3
00053 #define FD_R4 4
00054 #define FD_R5 5
00055 #define FD_R6 6
00056 #define FD_R7 7
00057 #define FD_R8 8
00058 #define FD_R9 9
00059 #define FD_R10 10
00060 #define FD_R11 11
00061 #define FD_R12 12
00062 #define FD_R13 13
00063 #define FD_R14 14
00064 #define FD_R15 15
00065 #define FD_R16 16
00066 #define FD_R17 17
00067 #define FD_R18 18
00068 #define FD_R19 19
00069 #define FD_R20 20
00070 #define FD_R21 21
00071 #define FD_R22 22
00072 #define FD_R23 23
00073 #define FD_R24 24
00074 #define FD_R25 25
00075 #define FD_R26 26
00076 #define FD_R27 27
00077 #define FD_CFA 28 // I don't anticipate gp used for spill/save
00078 #define FD_R29 29
00079 #define FD_R30 30
00080 #define FD_S8 FD_R30 // fp
00081 #define FD_R31 31
00082 #define FD_FIRST FD_R0
00083 #define FD_LAST 32
00084
00085 typedef UINT32 FD_REG;
00086
00087 static const UINT32 fd_to_track[FD_LAST] = {
00088
00089
00090
00091 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00092 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0,
00093 };
00094
00095
00096 static const UINT32 fd_to_dwarf[FD_LAST] = {
00097 DW_FRAME_REG35, DW_FRAME_REG1, DW_FRAME_REG2, DW_FRAME_REG3,
00098 DW_FRAME_REG4, DW_FRAME_REG5, DW_FRAME_REG6, DW_FRAME_REG7,
00099 DW_FRAME_REG8, DW_FRAME_REG9, DW_FRAME_REG10, DW_FRAME_REG11,
00100 DW_FRAME_REG12, DW_FRAME_REG13, DW_FRAME_REG14, DW_FRAME_REG15,
00101 DW_FRAME_REG16, DW_FRAME_REG17, DW_FRAME_REG18, DW_FRAME_REG19,
00102 DW_FRAME_REG20, DW_FRAME_REG21, DW_FRAME_REG22, DW_FRAME_REG23,
00103 DW_FRAME_REG24, DW_FRAME_REG25, DW_FRAME_REG26, DW_FRAME_REG27,
00104 0, DW_FRAME_REG29, DW_FRAME_REG30, DW_FRAME_REG31,
00105
00106 };
00107
00108
00109 static ST *fd_to_spill_loc[FD_LAST];
00110
00111 static ST *prev_fd_to_spill_loc[FD_LAST];
00112
00113
00114
00115 typedef enum {
00116 DS_In_Register,
00117 DS_In_Memory,
00118 DS_CFA_Is_SP,
00119 DS_CFA_Is_Adj_SP,
00120 DS_CFA_Is_FP,
00121 DS_CFA_Last
00122 } CGD_STATES;
00123
00124 static const char *CGD_Name[DS_CFA_Last] = {
00125 "DS_In_Register",
00126 "DS_In_Memory",
00127 "DS_CFA_Is_SP",
00128 "DS_CFA_Is_Adj_SP",
00129 "DS_CFA_Is_FP"
00130 };
00131
00132 static char *fmt_string = "\t%s\t0x%x\n";
00133 #define AS_4BYTE ".4byte"
00134 #define AS_1BYTE ".byte"
00135 #define AS_ASCII ".ascii"
00136 #define AS_ULEBW ".uleb128"
00137 #define AS_SLEBW ".sleb128"
00138
00139 static INT unw_info_pu_start_count;
00140
00141 static void
00142 CIE_dump2asm(Dwarf_P_Cie cie)
00143 {
00144 unw_info_pu_start_count = Current_PU_Count();
00145
00146 fprintf(Asm_File, "\t%s\t%s\n", AS_SECTION, ".debug_frame,\"\",@progbits");
00147 fprintf(Asm_File, "$Lunwind_info_%d:\n", unw_info_pu_start_count);
00148 fprintf(Asm_File, "\t%s\t$CIE_E%d-$CIE_B%d\n", AS_4BYTE, Current_PU_Count(), Current_PU_Count());
00149 fprintf(Asm_File, "$CIE_B%d:\n", Current_PU_Count());
00150 fprintf(Asm_File, fmt_string, AS_4BYTE, -1);
00151 fprintf(Asm_File, fmt_string, AS_BYTE, cie->cie_version);
00152
00153 if (*(cie->cie_aug))
00154 fprintf(Asm_File, "\t%s\t\"%s\"\n", AS_ASCII, cie->cie_aug);
00155 else
00156 fprintf(Asm_File, "\t%s \"\\000\"\n", ".ascii");
00157 #if 0 // we must set 1 here, don't know why
00158 fprintf(Asm_File, fmt_string, AS_ULEBW, cie->cie_code_align);
00159 #else
00160 fprintf(Asm_File, fmt_string, AS_ULEBW, 1);
00161 #endif
00162 fprintf(Asm_File, fmt_string, AS_SLEBW, cie->cie_data_align);
00163 fprintf(Asm_File, fmt_string, AS_1BYTE, cie->cie_ret_reg);
00164
00165 Is_True(cie->cie_personality == 0, ("size does not account for personality != 0"));
00166 Is_True(cie->cie_next == 0, ("not the last cie"));
00167 Is_True(*(cie->cie_inst) == 0, ("not extra instruction expected"));
00168 }
00169
00170
00171
00172
00173
00174 static void
00175 FDE_dump2asm(INT low_pc, INT high_pc)
00176 {
00177 Is_True((high_pc-low_pc) >= 0, ("invalid pc pair"));
00178 if ( Trace_Dwarf ) {
00179 fprintf ( TFile, "dump2asm pc %x -> %x\n", low_pc, high_pc );
00180 }
00181
00182 fprintf(Asm_File, "\t%s\t%s\n", AS_SECTION, ".debug_frame");
00183 fprintf(Asm_File, "\t%s\t$LFE%d-$LFB%d\n", AS_4BYTE, Current_PU_Count(), Current_PU_Count());
00184 fprintf(Asm_File, "$LFB%d:\n", Current_PU_Count());
00185 fprintf(Asm_File, "\t%s\t$Lunwind_info_%d\n", AS_4BYTE,unw_info_pu_start_count);
00186 fprintf(Asm_File, "\t%s\t%s\n", AS_4BYTE, Cur_PU_Name);
00187 fprintf(Asm_File, fmt_string, AS_4BYTE, high_pc-low_pc);
00188 }
00189
00190 static void
00191 CIE_end_dump2asm(void)
00192 {
00193
00194 fprintf(Asm_File, "\t.ALIGN\t2\n");
00195 fprintf(Asm_File, "$CIE_E%d:\n", Current_PU_Count());
00196 }
00197
00198 static void
00199 FDE_end_dump2asm(void)
00200 {
00201
00202 fprintf(Asm_File, "\t.ALIGN\t2\n");
00203 fprintf(Asm_File, "$LFE%d:\n", Current_PU_Count());
00204 }
00205
00206 static INT
00207 CFA_dump2asm(Dwarf_Small dw_op, Dwarf_Unsigned op1, Dwarf_Unsigned op2)
00208 {
00209 if (dw_op == DW_CFA_offset) {
00210 if (op1 != 35) {
00211 dw_op = (dw_op & 0xc0) | ((Dwarf_Small)op1 & 0x1F);
00212 } else {
00213 dw_op = (dw_op & 0xc0) | ((Dwarf_Small)op1 & 0x3F);
00214 }
00215 fprintf(Asm_File, fmt_string, AS_1BYTE, dw_op);
00216 fprintf(Asm_File, fmt_string, AS_ULEBW, op2);
00217 return 9;
00218 }
00219 fprintf(Asm_File, fmt_string, AS_1BYTE, dw_op);
00220 switch(dw_op) {
00221 case DW_CFA_def_cfa:
00222 case DW_CFA_register:
00223 fprintf(Asm_File, fmt_string, AS_ULEBW, op1);
00224 fprintf(Asm_File, fmt_string, AS_ULEBW, op2);
00225 return 9;
00226 case DW_CFA_advance_loc:
00227 case DW_CFA_advance_loc4:
00228 fprintf(Asm_File, fmt_string, AS_4BYTE, op1);
00229 return 5;
00230 case DW_CFA_def_cfa_offset:
00231 case DW_CFA_def_cfa_register:
00232 case DW_CFA_same_value:
00233 fprintf(Asm_File, fmt_string, AS_ULEBW, op1);
00234 return 5;
00235 #ifdef TARG_SL
00236
00237
00238 case DW_CFA_SL_gpr_reginfo:
00239 case DW_CFA_SL_cr_reginfo:
00240 case DW_CFA_SL_sr_reginfo:
00241 fprintf(Asm_File, fmt_string, AS_4BYTE, op1);
00242 return 9;
00243 case DW_CFA_low_user:
00244 case DW_CFA_high_user:
00245 return 9;
00246 #endif
00247 default:
00248 Is_True(0, ("unsupported DW_op %x\n",dw_op));
00249 break;
00250 }
00251 return 0;
00252 }
00253
00254
00255
00256
00257
00258 static INT32 curloc, lastloc;
00259
00260
00261
00262
00263 static Dwarf_P_Fde
00264 Add_Fde_Inst (
00265 Dwarf_P_Fde fde,
00266 Dwarf_Small dw_op,
00267 Dwarf_Unsigned op1,
00268 Dwarf_Unsigned op2)
00269 {
00270
00271 #ifdef TARG_SL
00272
00273
00274
00275 if ((lastloc < curloc)
00276 && (dw_op < DW_CFA_low_user || dw_op > DW_CFA_high_user)) {
00277 #else
00278 if (lastloc < curloc) {
00279 #endif
00280 fde = dwarf_add_fde_inst (fde, DW_CFA_advance_loc, curloc - lastloc,
00281 0, &dw_error);
00282 if (Assembly)
00283 CFA_dump2asm(DW_CFA_advance_loc4, curloc-lastloc, 0);
00284 if (Trace_Dwarf)
00285 fprintf(TFile, "add_fde_inst DW_CFA_advance_loc of %d\n", curloc-lastloc);
00286 lastloc = curloc;
00287 }
00288 fde = dwarf_add_fde_inst (fde, dw_op, op1, op2, &dw_error);
00289 if (Assembly)
00290 CFA_dump2asm(dw_op, op1, op2);
00291 if (Trace_Dwarf)
00292 fprintf(TFile, "add_fde_inst %x of %lld,%lld\n", dw_op, op1, op2);
00293 return fde;
00294 }
00295
00296
00297
00298
00299
00300 static Dwarf_P_Fde
00301 update_state (
00302 Dwarf_P_Fde fde,
00303 FD_REG fd_reg,
00304 CGD_STATES *current_state,
00305 CGD_STATES new_state )
00306 {
00307 if ( Trace_Dwarf ) {
00308 fprintf ( TFile, "<update_state> curloc:%x:%x: %d(r%d) curr:%s new:%s\n",
00309 curloc, lastloc, fd_reg, fd_to_dwarf[fd_reg],
00310 CGD_Name[current_state[fd_reg]], CGD_Name[new_state] );
00311 }
00312
00313
00314 if (fd_reg == FD_RA) {
00315 return fde;
00316 }
00317
00318 if (fd_reg == FD_CFA) {
00319 if ( new_state == DS_CFA_Is_SP ) {
00320
00321 if ( current_state[FD_CFA] == DS_CFA_Is_FP ) {
00322 fde = Add_Fde_Inst (fde, DW_CFA_def_cfa_register, DW_FRAME_REG29, 0);
00323 }
00324 else if (Frame_Len != 0) {
00325
00326 fde = Add_Fde_Inst (fde, DW_CFA_def_cfa_offset, 0, 0);
00327 }
00328 }
00329 else if ( new_state == DS_CFA_Is_Adj_SP ) {
00330 if ( current_state[FD_CFA] != DS_CFA_Is_SP)
00331 DevWarn ("Jumping from state %s to DS_CFA_Is_Adj_SP",
00332 CGD_Name[current_state[FD_CFA]] );
00333
00334 if (Frame_Len != 0) {
00335 fde = Add_Fde_Inst (fde, DW_CFA_def_cfa_offset,
00336 Frame_Len, 0);
00337 }
00338 }
00339 else if ( new_state == DS_CFA_Is_FP ) {
00340 if ( current_state[FD_CFA] == DS_CFA_Is_Adj_SP ) {
00341 fde = Add_Fde_Inst (fde, DW_CFA_def_cfa_offset, 0, 0);
00342 }
00343
00344 fde = Add_Fde_Inst (fde, DW_CFA_def_cfa_register, DW_FRAME_REG30, 0);
00345 }
00346 else {
00347 ErrMsg( EC_Misc_Int, "Bad new state for CFA",
00348 (INT) current_state[FD_CFA] );
00349 }
00350 }
00351 else {
00352
00353 Is_True( new_state == DS_In_Memory || new_state == DS_In_Register,
00354 ("Invalid new state for fd:%d = %d", fd_reg, (INT) new_state) );
00355
00356 if ( current_state[fd_reg] == DS_In_Memory ) {
00357
00358 if (current_state[fd_reg] == new_state) {
00359 if (Trace_Dwarf) fprintf (TFile, "<update_state> ignore redundancy (Mem->Mem)\n");
00360 return fde;
00361 }
00362
00363
00364
00365 if (fd_reg == FD_RA) {
00366 fde = Add_Fde_Inst (fde, DW_CFA_register, DW_FRAME_RA_COL,
00367 fd_to_dwarf[fd_reg]);
00368 }
00369 else if (fd_reg == FD_SL) {
00370 fde = Add_Fde_Inst (fde, DW_CFA_register, DW_FRAME_STATIC_LINK,
00371 fd_to_dwarf[fd_reg]);
00372 }
00373 }
00374 else if ( current_state[fd_reg] == DS_In_Register ) {
00375 if (fd_to_track[fd_reg] == 0) {
00376
00377 }
00378
00379
00380 if (current_state[fd_reg] == new_state) {
00381 if (Trace_Dwarf) fprintf (TFile, "<update_state> ignore redundancy (Reg->Reg)\n");
00382 return fde;
00383 }
00384 #if defined(TARG_SL)
00385 if (fd_reg == FD_RA) {
00386 fde = Add_Fde_Inst (fde, DW_CFA_offset, 32,
00387 Offset_from_FP (fd_to_spill_loc[fd_reg]) /
00388 data_alignment_factor);
00389 }
00390 else {
00391 fde = Add_Fde_Inst (fde, DW_CFA_offset,
00392 fd_to_dwarf[fd_reg],
00393 Offset_from_FP (fd_to_spill_loc[fd_reg]) /
00394 data_alignment_factor);
00395 }
00396 #else
00397 if (fd_reg == FD_RA) {
00398 fde = Add_Fde_Inst (fde, DW_CFA_offset,
00399 DW_FRAME_RA_COL,
00400 Offset_from_FP (fd_to_spill_loc[fd_reg]) /
00401 data_alignment_factor);
00402 }
00403 else if (fd_reg == FD_SL) {
00404 fde = Add_Fde_Inst (fde, DW_CFA_offset,
00405 DW_FRAME_STATIC_LINK,
00406 Offset_from_FP (fd_to_spill_loc[fd_reg]) /
00407 data_alignment_factor);
00408 }
00409 else {
00410 fde = Add_Fde_Inst (fde, DW_CFA_offset,
00411 fd_to_dwarf[fd_reg],
00412 Offset_from_FP (fd_to_spill_loc[fd_reg]) /
00413 data_alignment_factor);
00414 }
00415 #endif
00416 }
00417 else {
00418 ErrMsg( EC_Misc_Int, "Invalid current state",
00419 (INT) current_state[fd_reg] );
00420 }
00421 }
00422
00423 current_state[fd_reg] = new_state;
00424 return fde;
00425 }
00426
00427
00428 static FD_REG Machine_Reg_To_FD (TN *tn, UINT32 mc_id, ISA_REGISTER_CLASS c)
00429 {
00430 #if defined(TARG_SL)
00431 FD_REG fd_num;
00432 if (TN_is_float(tn)) {
00433 Is_True(0, ("float reg not supported"));
00434 }
00435 else if (mc_id == 28) {
00436 Is_True(0,("Do not expect gp as save/spill"));
00437 }
00438 else if ((c == ISA_REGISTER_CLASS_control) &&
00439 (mc_id == 1)) {
00440 fd_num = FD_RA;
00441 }
00442 else if (mc_id <= 31) {
00443 fd_num = mc_id;
00444 }
00445 else {
00446 Is_True(0, ("mc_id too large %d\n",mc_id));
00447 }
00448 return fd_num;
00449
00450 #else
00451 FD_REG fd_num;
00452 if (TN_is_float(tn)) {
00453 fd_num = mc_id + FD_F20 -20;
00454 }
00455 else if (mc_id >= 16 && mc_id <= 23) {
00456 fd_num = mc_id + FD_S0 - 16;
00457 }
00458 else if (mc_id == 30) {
00459 fd_num = FD_S8;
00460 }
00461 else if (mc_id == 28) {
00462 fd_num = FD_GP;
00463 }
00464 else if (mc_id == 2) {
00465 fd_num = FD_JA;
00466 }
00467 else if ((TN_save_rclass(tn) == ISA_REGISTER_CLASS_control) &&
00468 (TN_save_reg(tn) == 4)) {
00469 fd_num = FD_RA;
00470 }
00471 else {
00472
00473 }
00474 return fd_num;
00475 #endif
00476 }
00477
00478 extern void dump_tn(TN*);
00479
00480 static FD_REG Save_TN_to_fd (TN *tn)
00481 {
00482 UINT32 mc_id;
00483 FD_REG fd_num;
00484
00485 Is_True (TN_is_save_reg(tn) || TN_is_ra_reg(tn),
00486 ("illegal TN input to Save_TN_to_fd"));
00487
00488 mc_id = REGISTER_machine_id (TN_save_rclass(tn), TN_save_reg(tn));
00489 fd_num = Machine_Reg_To_FD (tn, mc_id, TN_save_rclass(tn));
00490 if (TN_spill(tn) != NULL) {
00491 if (fd_to_spill_loc[fd_num] == NULL)
00492 fd_to_spill_loc[fd_num] = TN_spill(tn);
00493 }
00494 return fd_num;
00495 }
00496
00497
00498
00499 static FD_REG TN_to_fd (TN *tn)
00500 {
00501 UINT32 mc_id;
00502 FD_REG fd_num;
00503
00504 mc_id = TN_register(tn)-1;
00505 fd_num = Machine_Reg_To_FD (tn, mc_id, TN_register_class(tn));
00506 if (TN_spill(tn) != NULL) {
00507 fd_to_spill_loc[fd_num] = TN_spill(tn);
00508 }
00509 return fd_num;
00510 }
00511
00512
00513 static INT *local_state, *entry_state, *exit_state;
00514
00515 #define LOCAL_STATE(bb) (local_state[BB_id(bb)])
00516 #define ENTRY_STATE(bb) (entry_state[BB_id(bb)])
00517 #define EXIT_STATE(bb) (exit_state[BB_id(bb)])
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528 static void Compute_Reg_State (BB *firstbb)
00529 {
00530 BB *bb;
00531 OP *op;
00532 BBLIST *blst;
00533 BOOL changes;
00534 INT i;
00535 ST *slink_sym = NULL;
00536
00537 if (PU_is_nested_func(Get_Current_PU())) {
00538 slink_sym = Find_Slink_Symbol(CURRENT_SYMTAB);
00539 }
00540 local_state = TYPE_PU_ALLOC_N (INT, PU_BB_Count+2);
00541 entry_state = TYPE_PU_ALLOC_N (INT, PU_BB_Count+2);
00542 exit_state = TYPE_PU_ALLOC_N (INT, PU_BB_Count+2);
00543 memset (exit_state, -1, (PU_BB_Count+2) * sizeof(INT));
00544
00545 BB_Mark_Unreachable_Blocks ();
00546 for ( bb = firstbb; bb; bb = BB_next(bb) ) {
00547 if (BB_unreachable(bb)) continue;
00548 for (op = BB_first_op(bb); op; op = OP_next(op)) {
00549
00550 if (OP_store(op) && TN_is_save_reg(OP_opnd(op,0))) {
00551 LOCAL_STATE(bb) |= 1 << Save_TN_to_fd(OP_opnd(op,0));
00552 }
00553 #if !defined(TARG_SL)
00554
00555 if (PU_is_nested_func(Get_Current_PU()) && BB_entry(bb) && OP_store(op)) {
00556 if (TN_is_register(OP_opnd(op,0))
00557 && TN_is_static_link_reg(OP_opnd(op,0))
00558 && TN_is_symbol(OP_opnd(op,2))
00559 && TN_var(OP_opnd(op,2)) == slink_sym)
00560 {
00561 LOCAL_STATE(bb) |= 1 << FD_SL;
00562 }
00563 }
00564 #endif
00565 }
00566 }
00567
00568 changes = TRUE;
00569 while (changes) {
00570 changes = FALSE;
00571 for ( bb = firstbb; bb; bb = BB_next(bb) ) {
00572 INT old_exit_state;
00573 if (BB_unreachable(bb)) continue;
00574 if (Trace_Dwarf) fprintf (TFile, "curbb: %d, preds: ", BB_id(bb));
00575 if (BB_preds(bb) != NULL) {
00576 INT new_entry_state = -1;
00577 FOR_ALL_BB_PREDS (bb, blst) {
00578 new_entry_state &= EXIT_STATE(BBLIST_item(blst));
00579 if (Trace_Dwarf) fprintf (TFile, "[%d %x], ",
00580 BB_id(BBLIST_item(blst)), EXIT_STATE(BBLIST_item(blst)));
00581 }
00582 ENTRY_STATE(bb) = new_entry_state;
00583 }
00584
00585
00586
00587
00588 if (BB_handler(bb) && (Current_PU_Stack_Model != SMODEL_SMALL))
00589 {
00590 ENTRY_STATE(bb) |= 1 << FD_S8;
00591 }
00592 if (Trace_Dwarf) fprintf (TFile, "\n entry_state: %x\n", ENTRY_STATE(bb));
00593 old_exit_state = EXIT_STATE(bb);
00594 EXIT_STATE(bb) = ENTRY_STATE(bb) | LOCAL_STATE(bb);
00595 if (old_exit_state != EXIT_STATE(bb))
00596 changes = TRUE;
00597 }
00598 }
00599 if (Trace_Dwarf) {
00600 fprintf (TFile, "\n**** REG_STATE ****\n");
00601 for (i = 1; i <= PU_BB_Count; i++) {
00602 fprintf (TFile, "%4d %8x %8x %8x\n", i, entry_state[i], local_state[i],
00603 exit_state[i]);
00604 }
00605 }
00606 }
00607
00608
00609 static BOOL
00610 Has_Matching_Load_In_BB ( BB *bb, TN *dest, TN *spill)
00611 {
00612 OP *op;
00613 for (op = BB_first_op(bb); op; op = OP_next(op)) {
00614 if (OP_load(op) && OP_has_result(op)
00615 && CLASS_REG_PAIR_EqualP (TN_class_reg(OP_result(op,0)),
00616 TN_class_reg(dest) )
00617 && OP_opnd(op,1) == spill)
00618 {
00619 return TRUE;
00620 }
00621 }
00622 return FALSE;
00623 }
00624
00625 static BOOL
00626 Has_Matching_Store_In_BB ( BB *bb, TN *dest, TN *spill)
00627 {
00628 OP *op;
00629 for (op = BB_first_op(bb); op; op = OP_next(op)) {
00630 if (OP_store(op)
00631 && CLASS_REG_PAIR_EqualP (TN_class_reg(OP_opnd(op,0)),
00632 TN_class_reg(dest) )
00633 && OP_opnd(op,2) == spill)
00634 {
00635 return TRUE;
00636 }
00637 }
00638 return FALSE;
00639 }
00640
00641 #ifdef TARG_SL
00642
00643
00644 static void
00645 Gen_Register_Mask(BB *firstbb, REGISTER_SET *interrupt_saved,
00646 REGISTER_SET *ctrl_saved, REGISTER_SET *spe_saved)
00647 {
00648 BB *bb;
00649 OP *op;
00650
00651 REGISTER_SET caller_saved = REGISTER_CLASS_caller_saves(ISA_REGISTER_CLASS_integer);
00652 REGISTER_SET used_gpr = REGISTER_SET_EMPTY_SET;
00653 REGISTER_SET used_spe_reg = REGISTER_SET_EMPTY_SET;
00654 REGISTER_SET used_ctr_reg = REGISTER_SET_EMPTY_SET;
00655
00656 for(bb = firstbb; bb; bb = BB_next(bb))
00657 {
00658 FOR_ALL_BB_OPs(bb, op)
00659 {
00660 for(INT i = 0; i < OP_results(op); i++) {
00661 TN* tn = OP_result(op, i);
00662 if (TN_is_register(tn) && (TN_register_class(tn) == ISA_REGISTER_CLASS_integer)) {
00663 used_gpr = REGISTER_SET_Union(used_gpr, (1 << (TN_register(tn)-1)));
00664 } else if (tn == JA_TN) {
00665 used_ctr_reg = REGISTER_SET_Union (used_ctr_reg, 1);
00666 } else if (tn == RA_TN) {
00667 used_ctr_reg = REGISTER_SET_Union (used_ctr_reg, 2);
00668 } else if (TN_is_LoopRegister(tn)) {
00669
00670 used_ctr_reg = REGISTER_SET_Union(used_ctr_reg, (1 << (TN_number(tn)-TN_number(LC0_TN)+2)));
00671 } else if (tn == HI_TN) {
00672
00673 used_spe_reg = REGISTER_SET_Union(used_spe_reg, 21);
00674 } else if (TN_is_AddrRegister(tn)) {
00675 used_spe_reg = REGISTER_SET_Union(used_spe_reg, (1 << (TN_number(tn)-TN_number(Addr0_TN))));
00676 } else if (TN_is_AccRegister(tn)) {
00677 used_spe_reg = REGISTER_SET_Union(used_spe_reg, (1 << (TN_number(tn)-TN_number(Acc0_TN)+16)));
00678 } else if (TN_is_AddrSizeRegister(tn)) {
00679 used_spe_reg = REGISTER_SET_Union(used_spe_reg, (1 << (TN_number(tn)-TN_number(Addrsize0_TN)+8)));
00680 }
00681 }
00682 if (CG_ISR == 2) {
00683 for(INT i = 0; i < OP_opnds(op); i++) {
00684 TN* tn = OP_opnd(op, i);
00685 if (TN_is_register(tn) && (TN_register_class(tn) == ISA_REGISTER_CLASS_integer)) {
00686 used_gpr = REGISTER_SET_Union(used_gpr, (1 << (TN_register(tn)-1)));
00687 } else if (tn == JA_TN) {
00688 used_ctr_reg = REGISTER_SET_Union (used_ctr_reg, 1);
00689 } else if (tn == RA_TN) {
00690 used_ctr_reg = REGISTER_SET_Union (used_ctr_reg, 2);
00691 } else if (TN_is_LoopRegister(tn)) {
00692
00693 used_ctr_reg = REGISTER_SET_Union(used_ctr_reg, (1 << (TN_number(tn)-TN_number(LC0_TN)+2)));
00694 } else if (tn == HI_TN) {
00695
00696 used_spe_reg = REGISTER_SET_Union(used_spe_reg, 21);
00697 } else if (TN_is_AddrRegister(tn)) {
00698 used_spe_reg = REGISTER_SET_Union(used_spe_reg, (1 << (TN_number(tn)-TN_number(Addr0_TN))));
00699 } else if (TN_is_AccRegister(tn)) {
00700 used_spe_reg = REGISTER_SET_Union(used_spe_reg, (1 << (TN_number(tn)-TN_number(Acc0_TN)+16)));
00701 } else if (TN_is_AddrSizeRegister(tn)) {
00702 used_spe_reg = REGISTER_SET_Union(used_spe_reg, (1 << (TN_number(tn)-TN_number(Addrsize0_TN)+8)));
00703 }
00704 }
00705 }
00706 }
00707 }
00708 *interrupt_saved = REGISTER_SET_Intersection(caller_saved, used_gpr);
00709 *ctrl_saved = used_ctr_reg;
00710 *spe_saved = used_spe_reg;
00711 }
00712 #endif
00713
00714 static INT32
00715 OP_Inst_Size(const OP * op)
00716 {
00717 INT32 size = 0;
00718 extern INT Simulated_Op_Real_Inst_Words(const OP *op);
00719
00720 if (TOP_asm == op->opr) {
00721 size = Simulated_Op_Real_Inst_Words(op) * 2;
00722 } else {
00723 size = OP_Real_Ops(op) ? ((ISA_PACK_Inst_Words(OP_code(op))) * 2) : 0;
00724 }
00725
00726 return size;
00727 }
00728
00729
00730 extern Dwarf_P_Fde
00731 Build_Fde_For_Proc (Dwarf_P_Debug dw_dbg, BB *firstbb, LABEL_IDX begin_label, LABEL_IDX end_label, INT end_offset, INT low_pc, INT high_pc)
00732 {
00733 Dwarf_P_Fde fde;
00734 FD_REG fd_reg;
00735 BOOL has_fp = (Current_PU_Stack_Model != SMODEL_SMALL);
00736 BOOL seen_entry_sp_adj;
00737 BB *bb;
00738 OP *op;
00739 TN *ra_sv = NULL;
00740 CGD_STATES current_state[FD_LAST];
00741 CGD_STATES init_state;
00742 INT i;
00743 ST *slink_sym = NULL;
00744 #ifdef TARG_SL
00745 REGISTER_SET gpr_saved = REGISTER_SET_EMPTY_SET;
00746 REGISTER_SET ctrl_saved = REGISTER_SET_EMPTY_SET;
00747 REGISTER_SET spe_saved = REGISTER_SET_EMPTY_SET;
00748 Gen_Register_Mask(firstbb, &gpr_saved, &ctrl_saved, &spe_saved);
00749 #endif
00750
00751 for (fd_reg = FD_FIRST; fd_reg < FD_LAST; fd_reg++) {
00752 current_state[fd_reg] = DS_In_Register;
00753 fd_to_spill_loc[fd_reg] = NULL;
00754 prev_fd_to_spill_loc[fd_reg] = NULL;
00755 }
00756
00757 curloc = 0;
00758 lastloc = 0;
00759
00760
00761 fde = dwarf_new_fde (dw_dbg, &dw_error);
00762
00763 if (Assembly)
00764 fprintf(Asm_File, "\t%s\t%s\n", AS_SECTION, ".debug_frame");
00765
00766
00767
00768 Is_True(dw_dbg->de_last_cie, ("CIE pointer is NULL"));
00769 static BOOL emit_cie_head = FALSE;
00770 if (Assembly && (emit_cie_head == FALSE)) {
00771 emit_cie_head = TRUE;
00772 CIE_dump2asm(dw_dbg->de_last_cie);
00773
00774 fde = Add_Fde_Inst (fde,DW_CFA_def_cfa, DW_FRAME_REG29, 0);
00775 }
00776
00777
00778 current_state[FD_CFA] = DS_CFA_Is_SP;
00779
00780
00781 if (PU_is_nested_func(Get_Current_PU())) {
00782 fde = Add_Fde_Inst (fde, DW_CFA_register, DW_FRAME_STATIC_LINK,
00783 fd_to_dwarf[FD_SL]);
00784 slink_sym = Find_Slink_Symbol(CURRENT_SYMTAB);
00785 }
00786
00787
00788 if (Assembly) {
00789 CIE_end_dump2asm();
00790 FDE_dump2asm(low_pc, high_pc);
00791 }
00792
00793 Compute_Reg_State (firstbb);
00794
00795 for ( bb = firstbb; bb; bb = BB_next(bb) )
00796 {
00797 if (BB_unreachable(bb)) {
00798 for (op = BB_first_op(bb); op; op = OP_next(op)) {
00799 curloc += OP_Inst_Size(op);
00800 }
00801 continue;
00802 }
00803
00804 if ( Trace_Dwarf ) {
00805 fprintf ( TFile, "<update_state> BB:%d\n", BB_id(bb) );
00806 }
00807
00808 seen_entry_sp_adj = FALSE;
00809
00810
00811
00812
00813
00814
00815 if (!(ENTRY_STATE(bb) & (1 << FD_LAST))) {
00816
00817
00818
00819
00820 init_state = (BB_entry(bb) && !BB_handler(bb)) ? DS_CFA_Is_SP :
00821 ((has_fp) ? DS_CFA_Is_FP : DS_CFA_Is_Adj_SP);
00822 if (current_state[FD_CFA] != init_state) {
00823 fde = update_state (fde, FD_CFA, current_state, init_state);
00824 }
00825
00826 for ( fd_reg = FD_FIRST; fd_reg < FD_CFA; fd_reg++ ) {
00827 if (fd_to_track[fd_reg] == 0)
00828 continue;
00829 init_state = (CGD_STATES) ((ENTRY_STATE(bb) >> fd_reg) & 1);
00830 if (current_state[fd_reg] != init_state) {
00831 fde = update_state (fde, fd_reg, current_state, init_state);
00832 }
00833 }
00834 }
00835
00836 for (op = BB_first_op(bb); op; op = OP_next(op))
00837 {
00838 curloc += OP_Inst_Size(op);
00839
00840
00841
00842
00843
00844 if (curloc == high_pc) break;
00845
00846 if (OP_dummy(op) || OP_noop(op)) continue;
00847
00848
00849
00850
00851
00852 for (i = 0; i < OP_results(op); ++i) {
00853 TN *result_tn = OP_result(op,i);
00854 if (TN_is_save_reg(result_tn) || TN_is_ra_reg(result_tn)) {
00855 if (OP_load(op)) {
00856
00857 fde = update_state (fde, TN_to_fd(result_tn), current_state, DS_In_Register);
00858 }
00859 else {
00860 if (TN_is_save_reg(result_tn)) {
00861 if ((OP_code(op) == TOP_mvfc16) && (OP_opnd(op, 0) == RA_TN)) {
00862 ra_sv = result_tn;
00863 } else {
00864 fd_reg = Save_TN_to_fd (result_tn);
00865 fde = Add_Fde_Inst (
00866 fde,
00867 DW_CFA_register,
00868 fd_to_dwarf[fd_reg],
00869
00870 REGISTER_machine_id(TN_register_class(result_tn),
00871 TN_register(result_tn)));
00872 current_state[fd_reg] = DS_In_Register;
00873 }
00874 }
00875 else if (OP_code(op) == TOP_mvtc16) {
00876
00877 TN *src_tn = OP_opnd(op, 0);
00878 fde = Add_Fde_Inst (fde,
00879 DW_CFA_register,
00880 REGISTER_machine_id(TN_register_class(src_tn),
00881 TN_register(src_tn)),
00882 fd_to_dwarf[FD_RA]);
00883
00884 current_state[FD_RA] = DS_In_Register;
00885 }
00886 }
00887 }
00888 }
00889 if (OP_opnds(op) > 0) {
00890 TN *src_tn = OP_opnd(op,0);
00891 if (TN_is_register(src_tn) && TN_is_save_reg(src_tn)) {
00892 fd_reg = TN_to_fd (src_tn);
00893 if (OP_store(op)) {
00894 prev_fd_to_spill_loc[fd_reg] = fd_to_spill_loc[fd_reg];
00895 fd_to_spill_loc[fd_reg] = TN_spill(OP_opnd(op,2));
00896 if ((ra_sv != NULL) && (OP_opnd(op, 0) == ra_sv)) {
00897 fde = Add_Fde_Inst(fde, DW_CFA_offset, fd_to_dwarf[FD_RA],
00898 Offset_from_FP(TN_var(ra_sv))/data_alignment_factor);
00899 current_state[FD_RA] = DS_In_Memory;
00900 }
00901 else
00902 fde = update_state (fde, fd_reg, current_state, DS_In_Memory);
00903 }
00904 else if (OP_copy(op)) {
00905
00906 current_state[fd_reg] = DS_In_Register;
00907 }
00908 }
00909 }
00910
00911
00912
00913
00914
00915
00916
00917 if (OP_store(op)
00918 && ! TN_is_save_reg(OP_opnd(op,0))
00919 && REGISTER_SET_MemberP(
00920 REGISTER_CLASS_callee_saves(TN_register_class(OP_opnd(op,0))),
00921 TN_register(OP_opnd(op,0)) ) )
00922 {
00923 TN *tn = OP_opnd(op,0);
00924 fd_reg = Machine_Reg_To_FD (tn, REGISTER_machine_id (
00925 TN_register_class(tn), TN_register(tn) ),ISA_REGISTER_CLASS_integer);
00926 if (current_state[fd_reg] == DS_In_Register
00927 && CGSPILL_Is_Spill_Op(op)
00928 && Has_Matching_Load_In_BB (bb, tn, OP_opnd(op,2)) )
00929 {
00930 DevWarn("found local store of callee_save reg that was not save_reg: bb %d, reg %d",
00931 BB_id(bb), REGISTER_machine_id( TN_register_class(tn), TN_register(tn)) );
00932 prev_fd_to_spill_loc[fd_reg] = fd_to_spill_loc[fd_reg];
00933 fd_to_spill_loc[fd_reg] = TN_spill(OP_opnd(op,2));
00934
00935
00936
00937
00938
00939 fde = update_state (fde, fd_reg, current_state, DS_In_Memory);
00940 }
00941 }
00942 else if (OP_load(op)
00943 && OP_has_result(op)
00944 && ! TN_is_save_reg(OP_result(op,0))
00945 && REGISTER_SET_MemberP(
00946 REGISTER_CLASS_callee_saves(TN_register_class(OP_result(op,0))),
00947 TN_register(OP_result(op,0)) ) )
00948 {
00949 TN *tn = OP_result(op,0);
00950 fd_reg = Machine_Reg_To_FD (tn, REGISTER_machine_id (
00951 TN_register_class(tn), TN_register(tn) ), ISA_REGISTER_CLASS_integer);
00952 if (current_state[fd_reg] == DS_In_Memory
00953 && TN_is_symbol(OP_opnd(op,1)) && TN_spill(OP_opnd(op,1))
00954 && fd_to_spill_loc[fd_reg] == TN_spill(OP_opnd(op,1))
00955 && Has_Matching_Store_In_BB (bb, tn, OP_opnd(op,1)) )
00956 {
00957 DevWarn("found local load of callee_save reg: bb %d, reg %d",
00958 BB_id(bb),
00959 REGISTER_machine_id(TN_register_class(tn),TN_register(tn)));
00960 fde = update_state (fde, fd_reg, current_state, DS_In_Register);
00961 fd_to_spill_loc[fd_reg] = prev_fd_to_spill_loc[fd_reg];
00962 }
00963 }
00964
00965
00966 if (PU_is_nested_func(Get_Current_PU()) && BB_entry(bb) && OP_store(op)) {
00967 if (TN_is_register(OP_opnd(op,0))
00968 && TN_is_static_link_reg(OP_opnd(op,0))
00969 && TN_is_symbol(OP_opnd(op,2))
00970 && TN_var(OP_opnd(op,2)) == slink_sym)
00971 {
00972 fd_to_spill_loc[FD_SL] = slink_sym;
00973 fde = update_state (fde, FD_SL, current_state, DS_In_Memory);
00974 }
00975 }
00976
00977
00978
00979
00980 if (BB_entry(bb) && !seen_entry_sp_adj) {
00981 if ( op == BB_entry_sp_adj_op(bb) ) {
00982 seen_entry_sp_adj = TRUE;
00983 }
00984 if (OP_Defs_Reg (op, REGISTER_CLASS_sp, REGISTER_sp)) {
00985 fde = update_state(fde, FD_CFA, current_state,DS_CFA_Is_Adj_SP);
00986 continue;
00987 }
00988 if (has_fp && OP_Defs_TN (op, FP_TN)) {
00989
00990 fde = update_state( fde, FD_CFA, current_state, DS_CFA_Is_FP );
00991 continue;
00992 }
00993 }
00994
00995 if (BB_exit(bb) && op == BB_exit_sp_adj_op(bb)) {
00996 fde = update_state(fde, FD_CFA, current_state,DS_CFA_Is_Adj_SP);
00997 Is_True( OP_Defs_Reg(op, REGISTER_CLASS_sp, REGISTER_sp),
00998 ("(BB:%d) BB_exit_sp_adj_op does not define SP",BB_id(bb)));
00999
01000
01001
01002
01003
01004 if (op != BB_last_op(bb)) {
01005 fde = update_state (fde, FD_CFA, current_state,DS_CFA_Is_SP);
01006 for ( fd_reg = FD_FIRST; fd_reg < FD_CFA; fd_reg++ ) {
01007 if (current_state[fd_reg] == DS_In_Memory) {
01008 update_state (fde, fd_reg, current_state, DS_In_Register);
01009 }
01010 }
01011 }
01012 }
01013
01014 }
01015 }
01016 #ifdef TARG_SL
01017
01018 fde = Add_Fde_Inst (fde,DW_CFA_SL_gpr_reginfo, gpr_saved, 0);
01019 fde = Add_Fde_Inst (fde,DW_CFA_SL_cr_reginfo, ctrl_saved, 0);
01020 fde = Add_Fde_Inst (fde,DW_CFA_SL_sr_reginfo, spe_saved, 0);
01021 #endif
01022 if (Assembly)
01023 FDE_end_dump2asm();
01024
01025 return fde;
01026 }
01027
01028
01029 static BOOL
01030 Is_Unwind_Simple (void)
01031 {
01032 if (has_asm) return FALSE;
01033 #if 0
01034 for (ue_iter = ue_list.begin(); ue_iter != ue_list.end(); ++ue_iter) {
01035
01036 if (BB_prev(ue_iter->bb) != NULL && BB_next(ue_iter->bb) != NULL) {
01037 return FALSE;
01038 }
01039
01040 if ( ! BB_entry(ue_iter->bb) && ! BB_exit(ue_iter->bb)) {
01041 return FALSE;
01042 }
01043 }
01044 #endif
01045
01046 return TRUE;
01047 }
01048
01049
01050 void
01051 Init_Unwind_Info (BOOL trace)
01052 {
01053 Trace_Unwind = trace;
01054 has_asm = FALSE;
01055 has_create = FALSE;
01056
01057
01058 simple_unwind = Is_Unwind_Simple();
01059 #if 0
01060
01061 last_label = 0;
01062 next_when = 0;
01063 proc_region = UNDEFINED_UREGION;
01064 if ( ! simple_unwind) {
01065 if (Trace_Unwind) fprintf (TFile, "need to propagate unwind info\n");
01066
01067
01068 Do_Control_Flow_Analysis_Of_Unwind_Info ();
01069 if ( ! has_asm) simple_unwind = TRUE;
01070 }
01071 Compute_Region_Sizes();
01072 #endif
01073 if (Trace_Unwind) {
01074 fprintf (TFile, "%s unwind\n", (simple_unwind ? "simple" : "complicated"));
01075
01076 }
01077
01078
01079
01080 }
01081
01082 void
01083 Finalize_Unwind_Info(void)
01084 {
01085
01086 }
01087
01088 void
01089 Emit_Unwind_Directives_For_OP(OP *op, FILE *f)
01090 {
01091 }
01092
01093 void
01094 Check_Dwarf_Rel(Elf32_Rel const ¤t_reloc)
01095 {
01096 FmtAssert(REL32_type(current_reloc) == R_IA_64_DIR32MSB,
01097 ("Unimplemented 32-bit relocation type %d",
01098 REL32_type(current_reloc)));
01099 }
01100
01101 void
01102 Check_Dwarf_Rel(Elf64_AltRel const ¤t_reloc)
01103 {
01104 FmtAssert(REL64_type(current_reloc) == R_IA_64_DIR64MSB,
01105 ("Unimplemented 64-bit relocation type %d",
01106 REL64_type(current_reloc)));
01107 }
01108
01109 void
01110 Check_Dwarf_Rela(const Elf64_AltRela ¤t_reloc)
01111 {
01112 FmtAssert(FALSE,
01113 ("Unimplemented 64-bit relocation type %d",
01114 REL64_type(current_reloc)));
01115 }
01116
01117 void
01118 Check_Dwarf_Rela(const Elf32_Rela ¤t_reloc)
01119 {
01120 FmtAssert(FALSE,
01121 ("Unimplemented 32-bit relocation type %d",
01122 REL32_type(current_reloc)));
01123 }
01124
01125 static char *drop_these[] = {
01126
01127
01128 ".debug_line",
01129
01130
01131 ".debug_weaknames",
01132 ".debug_varnames",
01133 ".debug_typenames",
01134 ".debug_funcnames",
01135
01136 ".debug_frame",
01137 0
01138 };
01139
01140 extern BOOL Is_Dwarf_Section_To_Emit(const char *name)
01141 {
01142
01143 for(int i = 0; drop_these[i]; ++i) {
01144 if(strcmp(name,drop_these[i]) == 0) {
01145 return FALSE;
01146 }
01147 }
01148 return TRUE;
01149 }
01150