diff options
-rw-r--r-- | gcc/ChangeLog | 22 | ||||
-rw-r--r-- | gcc/dwarf2cfi.c | 97 | ||||
-rw-r--r-- | gcc/dwarf2out.c | 8 | ||||
-rw-r--r-- | gcc/dwarf2out.h | 4 | ||||
-rw-r--r-- | gcc/final.c | 54 | ||||
-rw-r--r-- | gcc/insn-notes.def | 8 | ||||
-rw-r--r-- | gcc/rtl.h | 5 |
7 files changed, 143 insertions, 55 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 45836c2..104c4ac 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,25 @@ +2011-07-07 Bernd Schmidt <bernds@codesourcery.com> + Richard Henderson <rth@redhat.com> + + * dwarf2cfi.c (cfi_insn): New. + (dwarf2out_cfi_label): Don't emit cfi label here. + (add_fde_cfi): Create a NOTE_INSN_CFI. + (dwarf2out_frame_debug): Setup cfi_insn. + (dwarf2out_frame_debug_init): Loop over insns creating CFI notes. + (dwarf2out_cfi_begin_epilogue): Make static. + (dwarf2out_frame_debug_restore_state): Make static. + * dwarf2out.c (output_cfi_directive): Make static. + (dwarf2out_emit_cfi): New. + * dwarf2out.h: Update. + * final.c (final): Remove CFI notes. + (final_scan_insn): Don't call dwarf2out_cfi_begin_epilogue, + dwarf2out_frame_debug_restore_state, dwarf2out_frame_debug. + Handle NOTE_INSN_CFI and NOTE_INSN_CFI_LABEL. + * insn-notes.def (NOTE_INSN_CFI): New. + (NOTE_INSN_CFI_LABEL): New. + * rtl.h (union rtunion_def): Add rt_cfi member. + (XCFI, XCCFI, NOTE_CFI, NOTE_LABEL_NUMBER): New. + 2011-07-07 Richard Henderson <rth@redhat.com> * dwarf2cfi.c: New file. diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c index 8de13e5..3e8958f 100644 --- a/gcc/dwarf2cfi.c +++ b/gcc/dwarf2cfi.c @@ -143,6 +143,19 @@ cfi_vec cie_cfi_vec; static GTY(()) unsigned long dwarf2out_cfi_label_num; +/* The insn after which a new CFI note should be emitted. */ +static rtx cfi_insn; + +/* True if remember_state should be emitted before following CFI directive. */ +static bool emit_cfa_remember; + +/* True if any CFI directives were emitted at the current insn. */ +static bool any_cfis_emitted; + + +static void dwarf2out_cfi_begin_epilogue (rtx insn); +static void dwarf2out_frame_debug_restore_state (void); + /* Hook used by __throw. */ @@ -292,18 +305,13 @@ dwarf2out_cfi_label (bool force) { int num = dwarf2out_cfi_label_num++; ASM_GENERATE_INTERNAL_LABEL (label, "LCFI", num); - ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LCFI", num); + cfi_insn = emit_note_after (NOTE_INSN_CFI_LABEL, cfi_insn); + NOTE_LABEL_NUMBER (cfi_insn) = num; } return label; } -/* True if remember_state should be emitted before following CFI directive. */ -static bool emit_cfa_remember; - -/* True if any CFI directives were emitted at the current insn. */ -static bool any_cfis_emitted; - /* Add CFI to the current fde at the PC value indicated by LABEL if specified, or to the CIE if LABEL is NULL. */ @@ -383,7 +391,8 @@ add_fde_cfi (const char *label, dw_cfi_ref cfi) } } - output_cfi_directive (cfi); + cfi_insn = emit_note_after (NOTE_INSN_CFI, cfi_insn); + NOTE_CFI (cfi_insn) = cfi; vec = &fde->dw_fde_cfi; any_cfis_emitted = true; @@ -2301,6 +2310,9 @@ dwarf2out_frame_debug (rtx insn, bool after_p) bool handled_one = false; bool need_flush = false; + /* Remember where we are to insert notes. */ + cfi_insn = (after_p ? insn : PREV_INSN (insn)); + if (!NONJUMP_INSN_P (insn) || clobbers_queued_reg_save (insn)) dwarf2out_flush_queued_reg_saves (); @@ -2440,8 +2452,16 @@ dwarf2out_frame_debug (rtx insn, bool after_p) void dwarf2out_frame_debug_init (void) { - /* Flush any queued register saves. */ - dwarf2out_flush_queued_reg_saves (); + rtx insn; + + regs_saved_in_regs = NULL; + queued_reg_saves = NULL; + + if (barrier_args_size) + { + XDELETEVEC (barrier_args_size); + barrier_args_size = NULL; + } /* Set up state for generating call frame debug info. */ lookup_cfa (&cfa); @@ -2453,12 +2473,55 @@ dwarf2out_frame_debug_init (void) cfa_temp.reg = -1; cfa_temp.offset = 0; - regs_saved_in_regs = NULL; - - if (barrier_args_size) + for (insn = get_insns (); insn ; insn = NEXT_INSN (insn)) { - XDELETEVEC (barrier_args_size); - barrier_args_size = NULL; + rtx pat; + + if (BARRIER_P (insn)) + { + dwarf2out_frame_debug (insn, false); + continue; + } + + if (NOTE_P (insn)) + { + switch (NOTE_KIND (insn)) + { + case NOTE_INSN_EPILOGUE_BEG: +#if defined(HAVE_epilogue) + dwarf2out_cfi_begin_epilogue (insn); +#endif + break; + case NOTE_INSN_CFA_RESTORE_STATE: + cfi_insn = insn; + dwarf2out_frame_debug_restore_state (); + break; + } + continue; + } + + if (!NONDEBUG_INSN_P (insn)) + continue; + + pat = PATTERN (insn); + if (asm_noperands (pat) >= 0) + { + dwarf2out_frame_debug (insn, false); + continue; + } + + if (GET_CODE (pat) == SEQUENCE) + { + int i, n = XVECLEN (pat, 0); + for (i = 1; i < n; ++i) + dwarf2out_frame_debug (XVECEXP (pat, 0, i), false); + } + + if (CALL_P (insn) + || find_reg_note (insn, REG_CFA_FLUSH_QUEUE, NULL)) + dwarf2out_frame_debug (insn, false); + + dwarf2out_frame_debug (insn, true); } } @@ -2467,7 +2530,7 @@ dwarf2out_frame_debug_init (void) we do need to save/restore, then emit the save now, and insert a NOTE_INSN_CFA_RESTORE_STATE at the appropriate place in the stream. */ -void +static void dwarf2out_cfi_begin_epilogue (rtx insn) { bool saw_frp = false; @@ -2544,7 +2607,7 @@ dwarf2out_cfi_begin_epilogue (rtx insn) /* A "subroutine" of dwarf2out_cfi_begin_epilogue. Emit the restore required. */ -void +static void dwarf2out_frame_debug_restore_state (void) { dw_cfi_ref cfi = new_cfi (); diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 0f6918d..78e1b1a 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -843,7 +843,7 @@ output_cfi (dw_cfi_ref cfi, dw_fde_ref fde, int for_eh) /* Similar, but do it via assembler directives instead. */ -void +static void output_cfi_directive (dw_cfi_ref cfi) { unsigned long r, r2; @@ -942,6 +942,12 @@ output_cfi_directive (dw_cfi_ref cfi) } } +void +dwarf2out_emit_cfi (dw_cfi_ref cfi) +{ + output_cfi_directive (cfi); +} + /* Output CFIs from VEC, up to index UPTO, to bring current FDE to the same state as after executing CFIs in CFI chain. DO_CFI_ASM is true if .cfi_* directives shall be emitted, false otherwise. If it diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h index 40cd848..9342d50 100644 --- a/gcc/dwarf2out.h +++ b/gcc/dwarf2out.h @@ -216,7 +216,6 @@ dw_loc_descr_node; /* Interface from dwarf2out.c to dwarf2cfi.c. */ extern dw_fde_ref current_fde (void); -extern void output_cfi_directive (dw_cfi_ref); extern struct dw_loc_descr_struct *build_cfa_loc (dw_cfa_location *, HOST_WIDE_INT); extern struct dw_loc_descr_struct *build_cfa_aligned_loc @@ -244,8 +243,7 @@ extern enum dw_cfi_oprnd_type dw_cfi_oprnd2_desc extern void dwarf2out_decl (tree); extern void dwarf2out_frame_debug (rtx, bool); extern void dwarf2out_frame_debug_init (void); -extern void dwarf2out_cfi_begin_epilogue (rtx); -extern void dwarf2out_frame_debug_restore_state (void); +extern void dwarf2out_emit_cfi (dw_cfi_ref cfi); extern void debug_dwarf (void); struct die_struct; diff --git a/gcc/final.c b/gcc/final.c index c0c1fc85..835bbd5 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -1727,7 +1727,7 @@ dump_basic_block_info (FILE *file, rtx insn, basic_block *start_to_bb, void final (rtx first, FILE *file, int optimize_p) { - rtx insn; + rtx insn, next; int max_uid = 0; int seen = 0; @@ -1801,6 +1801,16 @@ final (rtx first, FILE *file, int optimize_p) free (start_to_bb); free (end_to_bb); } + + /* Remove CFI notes, to avoid compare-debug failures. */ + for (insn = first; insn; insn = next) + { + next = NEXT_INSN (insn); + if (NOTE_P (insn) + && (NOTE_KIND (insn) == NOTE_INSN_CFI + || NOTE_KIND (insn) == NOTE_INSN_CFI_LABEL)) + delete_insn (insn); + } } const char * @@ -1973,16 +1983,20 @@ final_scan_insn (rtx insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, break; case NOTE_INSN_EPILOGUE_BEG: -#if defined (HAVE_epilogue) - if (dwarf2out_do_frame ()) - dwarf2out_cfi_begin_epilogue (insn); -#endif (*debug_hooks->begin_epilogue) (last_linenum, last_filename); targetm.asm_out.function_begin_epilogue (file); break; case NOTE_INSN_CFA_RESTORE_STATE: - dwarf2out_frame_debug_restore_state (); + break; + + case NOTE_INSN_CFI: + dwarf2out_emit_cfi (NOTE_CFI (insn)); + break; + + case NOTE_INSN_CFI_LABEL: + ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LCFI", + NOTE_LABEL_NUMBER (insn)); break; case NOTE_INSN_FUNCTION_BEG: @@ -2092,8 +2106,6 @@ final_scan_insn (rtx insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, break; case BARRIER: - if (dwarf2out_do_frame ()) - dwarf2out_frame_debug (insn, false); break; case CODE_LABEL: @@ -2314,11 +2326,6 @@ final_scan_insn (rtx insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, location_t loc; expanded_location expanded; - /* Make sure we flush any queued register saves in case this - clobbers affected registers. */ - if (dwarf2out_do_frame ()) - dwarf2out_frame_debug (insn, false); - /* There's no telling what that did to the condition codes. */ CC_STATUS_INIT; @@ -2364,12 +2371,6 @@ final_scan_insn (rtx insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, final_sequence = body; - /* Record the delay slots' frame information before the branch. - This is needed for delayed calls: see execute_cfa_program(). */ - if (dwarf2out_do_frame ()) - for (i = 1; i < XVECLEN (body, 0); i++) - dwarf2out_frame_debug (XVECEXP (body, 0, i), false); - /* The first insn in this SEQUENCE might be a JUMP_INSN that will force the restoration of a comparison that was previously thought unnecessary. If that happens, cancel this sequence @@ -2683,11 +2684,6 @@ final_scan_insn (rtx insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, current_output_insn = debug_insn = insn; - if (dwarf2out_do_frame () - && (CALL_P (insn) - || find_reg_note (insn, REG_CFA_FLUSH_QUEUE, NULL))) - dwarf2out_frame_debug (insn, false); - /* Find the proper template for this insn. */ templ = get_insn_template (insn_code_number, insn); @@ -2767,16 +2763,6 @@ final_scan_insn (rtx insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, targetm.asm_out.final_postscan_insn (file, insn, recog_data.operand, recog_data.n_operands); - /* If necessary, report the effect that the instruction has on - the unwind info. We've already done this for delay slots - and call instructions. */ - if (final_sequence == 0 -#if !defined (HAVE_prologue) - && !ACCUMULATE_OUTGOING_ARGS -#endif - && dwarf2out_do_frame ()) - dwarf2out_frame_debug (insn, true); - if (!targetm.asm_out.unwind_emit_before_insn && targetm.asm_out.unwind_emit) targetm.asm_out.unwind_emit (asm_out_file, insn); diff --git a/gcc/insn-notes.def b/gcc/insn-notes.def index 6cdbabd..859cdac 100644 --- a/gcc/insn-notes.def +++ b/gcc/insn-notes.def @@ -77,4 +77,12 @@ INSN_NOTE (SWITCH_TEXT_SECTIONS) when an epilogue appears in the middle of a function. */ INSN_NOTE (CFA_RESTORE_STATE) +/* When emitting dwarf2 frame information, contains a directive that + should be emitted. */ +INSN_NOTE (CFI) + +/* When emitting dwarf2 frame information, contains the number of a debug + label that should be emitted. */ +INSN_NOTE (CFI_LABEL) + #undef INSN_NOTE @@ -180,6 +180,7 @@ union rtunion_def mem_attrs *rt_mem; reg_attrs *rt_reg; struct constant_descriptor_rtx *rt_constant; + struct dw_cfi_struct *rt_cfi; }; typedef union rtunion_def rtunion; @@ -708,6 +709,7 @@ extern void rtl_check_failed_flag (const char *, const_rtx, const char *, #define XTREE(RTX, N) (RTL_CHECK1 (RTX, N, 't').rt_tree) #define XBBDEF(RTX, N) (RTL_CHECK1 (RTX, N, 'B').rt_bb) #define XTMPL(RTX, N) (RTL_CHECK1 (RTX, N, 'T').rt_str) +#define XCFI(RTX, N) (RTL_CHECK1 (RTX, N, 'C').rt_cfi) #define XVECEXP(RTX, N, M) RTVEC_ELT (XVEC (RTX, N), M) #define XVECLEN(RTX, N) GET_NUM_ELEM (XVEC (RTX, N)) @@ -740,6 +742,7 @@ extern void rtl_check_failed_flag (const char *, const_rtx, const char *, #define XCMODE(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rt_type) #define XCTREE(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rt_tree) #define XCBBDEF(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rt_bb) +#define XCCFI(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rt_cfi) #define XCCSELIB(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rt_cselib) #define XCVECEXP(RTX, N, M, C) RTVEC_ELT (XCVEC (RTX, N, C), M) @@ -883,6 +886,8 @@ extern const char * const reg_note_name[]; #define NOTE_EH_HANDLER(INSN) XCINT (INSN, 4, NOTE) #define NOTE_BASIC_BLOCK(INSN) XCBBDEF (INSN, 4, NOTE) #define NOTE_VAR_LOCATION(INSN) XCEXP (INSN, 4, NOTE) +#define NOTE_CFI(INSN) XCCFI (INSN, 4, NOTE) +#define NOTE_LABEL_NUMBER(INSN) XCINT (INSN, 4, NOTE) /* In a NOTE that is a line number, this is the line number. Other kinds of NOTEs are identified by negative numbers here. */ |