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