On 04/13/2011 04:14 PM, Bernd Schmidt wrote:
> On 04/11/2011 07:10 PM, Richard Henderson wrote:
>> Ok.
>
> Did you receive my reply to this message from earlier today? It doesn't
> seem to have made it to gcc-patches yet.
Since gcc-patches appears to have dropped the message, I'll resend it in
three parts.
There are three patches here, but they must be applied together (things
will mostly work otherwise, but I expect -freorder-blocks-and-partition
is broken in the intermediate stages). Below is the ChangeLog for the
entire set, and the first of the patches. This is just a new version of
the previously posted 002-scanfirst patch, now changed to delete the CFI
notes afterwards in order to avoid -fcompare-debug failures.
Bernd
* target.def (dwarf_handle_frame_unspec): Remove label argument.
* doc/tm.texi: Regenerate.
* tree.h (dwarf2out_cfi_label, dwarf2out_def_cfa,
dwarf2out_window_save, dwarf2out_reg_save, dwarf2out_return_save,
dwarf2out_return_reg, dwarf2out_reg_save_reg): Don't declare.
* final.c (final_start_function): Call
dwarf2out_frame_debug_after_prologue.
(final_scan_insn): Don't call dwarf2out_frame_debug for anything.
Handle NOTE_INSN_CFI and NOTE_INSN_CFI_LABEL.
(final): Delete these notes.
* insn-notes.def (CFI, CFI_LABEL): New.
* jump.c (addr_vec_p): New function.
* dwarf2out.c (cfi_insn): New static variable.
(dwarf2out_cfi_label): Remove force argument. All callers changed.
Only generate the label, don't emit it.
(dwarf2out_maybe_emit_cfi_label): New function.
(add_fde_cfi): Remove label argument. All callers changed. Remove
most code; leave a condition to either emit a CFI insn, or add the
CFI to the FDE CFI vector.
(add_cie_cfi): New static function.
(add_cfi): Remove function.
(old_cfa): New static variable.
(cfa_remember): Remove static variable.
(dwarf2out_def_cfa): Replace label argument with a bool for_cie
argument. All callers changed. Don't use lookup_cfa; use and
update the global old_cfa variable. Call add_fde_cfi or add_cie_cfi
at the end.
(reg_save): Replace label argument with a bool. All callers changed.
Call add_fde_cfi or add_cie_cfi at the end.
(dwarf2out_reg_save, dwarf2out_return_save, dwarf2out_return_reg,
dwarf2out_args_szie, dwarf2out_stack_adjust, dwarf2out_reg_save_reg,
dwarf2out_frame_debug_def_cfa, dwarf2out_frame_debug_cfa_offset,
dwarf2out_frame_debug_cfa_register, dwarf2out_frame_debug_cfa_restore,
dwarf2out_frame_debug_cfa_expression, dwarf2out_frame_debug_expr):
Remove label argument. All callers changed.
(barrier_args_size): Remove variable.
(compute_barrier_args_size_1, compute_barrier_args_size): Remove
functions.
(dwarf2out_notice_stack_adjust): Don't handle barriers.
(last_reg_save_label): Remove variable. All sets and uses removed.
(cfi_label_required_p, add_cfis_to_fde): New static functions.
(dwarf2out_frame_debug_restore_state): Simply add the new CFI.
(dwarf2out_frame_debug): Set cfi_insn, and clear it. Don't call
dwarf2out_flush_queued_reg_saves at the top.
(dwarf2out_frame_debug_init): Initialize old_cfa.
(copy_cfi_vec_parts): New static function.
(jump_target_info): New struct type.
(dwarf2out_cfi_begin_epilogue): Remove.
(save_point_p, record_current_state, maybe_record_jump_target,
vec_is_prefix_of, append_extra_cfis, debug_cfi_vec, switch_note_p,
scan_until_barrier, find_best_starting_point): New static functions.
(dwarf2out_frame_debug_after_prologue): New function.
(dwarf2out_emit_cfi): New function.
(output_cfi_directive): New FILE argument. All callers changed.
Avoid some paths if it is not asm_out_file; otherwise print to it.
(output_all_cfis): Remove function.
(output_cfis): Remove do_cfi_asm arg. All callers changed. Never
call output_cfi_directive.
(dwarf2out_frame_init): Initialize old_cfa.
(dwarf2out_switch_text_section): Don't initialize dw_fde_current_label.
Don't call output_all_cfis.
* dwarf2out.h (dwarf2out_cfi_label, dwarf2out_def_cfa,
dwarf2out_window_save, dwarf2out_reg_save, dwarf2out_return_save,
dwarf2out_return_reg, dwarf2out_reg_save_reg, dwarf2out_emit_cfi,
dwarf2out_frame_debug_after_prologue): Declare.
(dwarf2out_cfi_begin_epilogue, dwarf2out_frame_debug_restore_state):
Don't declare.
(struct dw_cfi_struct): Add forward declaration.
* rtl.h (union rtunion_def): Add rt_cfi member.
(XCFI, XCCFI, NOTE_CFI, NOTE_LABEL_NUMBER): New macros.
(addr_vec_p): Declare.
* config/sparc/sparc.c (sparc_dwarf_handle_frame_unspec): Remove
label argument.
* config/ia64/ia64.c (ia64_dwarf_handle_frame_unspec): Likewise.
* config/arm/arm.c (thumb_pushpop): Use dwarf2out_maybe_emit_cfi_label
rather than dwarf2out_cfi_label.
(thumb1_output_function_prologue): Likewise.
(arm_dwarf_handle_frame_unspec): Remove label argument.
* cfgcleanup.c (flow_find_head_matching_sequence): Ignore
epilogue notes.
* df-problems.c (can_move_insns_across): Don't stop at epilogue
notes.
* dwarf2out.c (dwarf2out_cfi_begin_epilogue): Also allow a
simplejump to end the block.
Index: gcc/dwarf2out.c
===================================================================
--- gcc.orig/dwarf2out.c
+++ gcc/dwarf2out.c
@@ -470,6 +470,8 @@ static void output_call_frame_info (int)
static void dwarf2out_note_section_used (void);
static bool clobbers_queued_reg_save (const_rtx);
static void dwarf2out_frame_debug_expr (rtx, const char *);
+static void dwarf2out_cfi_begin_epilogue (rtx);
+static void dwarf2out_frame_debug_restore_state (void);
/* Support for complex CFA locations. */
static void output_cfa_loc (dw_cfi_ref, int);
@@ -847,6 +849,15 @@ add_cfi (cfi_vec *vec, dw_cfi_ref cfi)
VEC_safe_push (dw_cfi_ref, gc, *vec, cfi);
}
+/* 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;
+
/* Generate a new label for the CFI info to refer to. FORCE is true
if a label needs to be output even when using .cfi_* directives. */
@@ -866,18 +877,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. */
@@ -957,7 +963,8 @@ add_fde_cfi (const char *label, dw_cfi_r
}
}
- 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;
@@ -2791,6 +2798,11 @@ dwarf2out_frame_debug (rtx insn, bool af
rtx note, n;
bool handled_one = false;
+ if (after_p)
+ cfi_insn = insn;
+ else
+ cfi_insn = PREV_INSN (insn);
+
if (!NONJUMP_INSN_P (insn) || clobbers_queued_reg_save (insn))
dwarf2out_flush_queued_reg_saves ();
@@ -2914,6 +2926,7 @@ void
dwarf2out_frame_debug_init (void)
{
size_t i;
+ rtx insn;
/* Flush any queued register saves. */
dwarf2out_flush_queued_reg_saves ();
@@ -2940,12 +2953,64 @@ dwarf2out_frame_debug_init (void)
XDELETEVEC (barrier_args_size);
barrier_args_size = NULL;
}
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ {
+ rtx pat;
+ if (BARRIER_P (insn))
+ {
+ dwarf2out_frame_debug (insn, false);
+ continue;
+ }
+ else 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)
+ continue;
+ if (GET_CODE (pat) == SEQUENCE)
+ {
+ int j;
+ for (j = 1; j < XVECLEN (pat, 0); j++)
+ dwarf2out_frame_debug (XVECEXP (pat, 0, j), false);
+ insn = XVECEXP (pat, 0, 0);
+ }
+
+ if (CALL_P (insn) && dwarf2out_do_frame ())
+ dwarf2out_frame_debug (insn, false);
+ if (dwarf2out_do_frame ()
+#if !defined (HAVE_prologue)
+ && !ACCUMULATE_OUTGOING_ARGS
+#endif
+ )
+ dwarf2out_frame_debug (insn, true);
+ }
+}
+
+void
+dwarf2out_emit_cfi (dw_cfi_ref cfi)
+{
+ output_cfi_directive (cfi);
}
-/* Determine if we need to save and restore CFI information around this
- epilogue. If SIBCALL is true, then this is a sibcall epilogue. If
- 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. */
+/* Determine if we need to save and restore CFI information around
+ this epilogue. If 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
dwarf2out_cfi_begin_epilogue (rtx insn)
@@ -2960,8 +3025,10 @@ dwarf2out_cfi_begin_epilogue (rtx insn)
if (!INSN_P (i))
continue;
- /* Look for both regular and sibcalls to end the block. */
- if (returnjump_p (i))
+ /* Look for both regular and sibcalls to end the block. Various
+ optimization passes may cause us to jump to a common epilogue
+ tail, so we also accept simplejumps. */
+ if (returnjump_p (i) || simplejump_p (i))
break;
if (CALL_P (i) && SIBLING_CALL_P (i))
break;
Index: gcc/dwarf2out.h
===================================================================
--- gcc.orig/dwarf2out.h
+++ gcc/dwarf2out.h
@@ -18,11 +18,11 @@ You should have received a copy of the G
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
+struct dw_cfi_struct;
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 (struct dw_cfi_struct *);
extern void dwarf2out_flush_queued_reg_saves (void);
extern void debug_dwarf (void);
Index: gcc/insn-notes.def
===================================================================
--- gcc.orig/insn-notes.def
+++ 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
Index: gcc/rtl.h
===================================================================
--- gcc.orig/rtl.h
+++ 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
#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
#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)
@@ -882,6 +885,8 @@ extern const char * const reg_note_name[
#define NOTE_BLOCK(INSN) XCTREE (INSN, 4, NOTE)
#define NOTE_EH_HANDLER(INSN) XCINT (INSN, 4, NOTE)
#define NOTE_BASIC_BLOCK(INSN) XCBBDEF (INSN, 4, NOTE)
+#define NOTE_CFI(INSN) XCCFI (INSN, 4, NOTE)
+#define NOTE_LABEL_NUMBER(INSN) XCINT (INSN, 4, NOTE)
#define NOTE_VAR_LOCATION(INSN) XCEXP (INSN, 4, NOTE)
/* In a NOTE that is a line number, this is the line number.
Index: gcc/final.c
===================================================================
--- gcc.orig/final.c
+++ gcc/final.c
@@ -1678,7 +1678,7 @@ final_end_function (void)
void
final (rtx first, FILE *file, int optimize_p)
{
- rtx insn;
+ rtx insn, next;
int max_uid = 0;
int seen = 0;
@@ -1723,6 +1723,15 @@ final (rtx first, FILE *file, int optimi
insn = final_scan_insn (insn, file, optimize_p, 0, &seen);
}
+
+ 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 *
@@ -1899,16 +1908,19 @@ final_scan_insn (rtx insn, FILE *file, i
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:
@@ -2018,8 +2030,6 @@ final_scan_insn (rtx insn, FILE *file, i
break;
case BARRIER:
- if (dwarf2out_do_frame ())
- dwarf2out_frame_debug (insn, false);
break;
case CODE_LABEL:
@@ -2285,12 +2295,6 @@ final_scan_insn (rtx insn, FILE *file, i
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
@@ -2604,9 +2608,6 @@ final_scan_insn (rtx insn, FILE *file, i
current_output_insn = debug_insn = insn;
- if (CALL_P (insn) && dwarf2out_do_frame ())
- dwarf2out_frame_debug (insn, false);
-
/* Find the proper template for this insn. */
templ = get_insn_template (insn_code_number, insn);
@@ -2686,16 +2687,6 @@ final_scan_insn (rtx insn, FILE *file, i
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);