aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog22
-rw-r--r--gcc/dwarf2cfi.c97
-rw-r--r--gcc/dwarf2out.c8
-rw-r--r--gcc/dwarf2out.h4
-rw-r--r--gcc/final.c54
-rw-r--r--gcc/insn-notes.def8
-rw-r--r--gcc/rtl.h5
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
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 5e009c0..e3ceecd 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -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. */