* tree-pass.h (pass_dwarf2_frame): Declare.
* passes.c (init_optimization_passes): Add it.
* dwarf2cfi.c (dwarf2out_frame_debug): Make static.
(create_cfi_notes): Rename from dwarf2out_frame_debug_after_prologue;
make static, do not call add_cfis_to_fde.
(dwarf2out_frame_debug_init, dwarf2cfi_function_init,
dwarf2out_frame_init): Merge into...
(execute_dwarf2_frame): ... here. New function.
(dwarf2out_do_frame, dwarf2out_do_cfi_asm): Make boolean. Change
saved_do_cfi_asm to a tri-state variable.
(gate_dwarf2_frame, pass_dwarf2_frame): New.
* dwarf2out.c (dwarf2out_begin_prologue): Only allocate the fde
if it has yet to be done. Don't call dwarf2cfi_function_init.
* dwarf2out.h, debug.h: Update decls.
* final.c (final_start_function): Don't call
dwarf2out_frame_debug_init or dwarf2out_frame_debug_after_prologue.
* lto-streamer-in.c (lto_init_eh): Don't call dwarf2out_frame_init.
* toplev.c (lang_dependent_init): Likewise.
From-SVN: r176019
+2011-07-07 Richard Henderson <rth@redhat.com>
+
+ * tree-pass.h (pass_dwarf2_frame): Declare.
+ * passes.c (init_optimization_passes): Add it.
+ * dwarf2cfi.c (dwarf2out_frame_debug): Make static.
+ (create_cfi_notes): Rename from dwarf2out_frame_debug_after_prologue;
+ make static, do not call add_cfis_to_fde.
+ (dwarf2out_frame_debug_init, dwarf2cfi_function_init,
+ dwarf2out_frame_init): Merge into...
+ (execute_dwarf2_frame): ... here. New function.
+ (dwarf2out_do_frame, dwarf2out_do_cfi_asm): Make boolean. Change
+ saved_do_cfi_asm to a tri-state variable.
+ (gate_dwarf2_frame, pass_dwarf2_frame): New.
+ * dwarf2out.c (dwarf2out_begin_prologue): Only allocate the fde
+ if it has yet to be done. Don't call dwarf2cfi_function_init.
+ * dwarf2out.h, debug.h: Update decls.
+ * final.c (final_start_function): Don't call
+ dwarf2out_frame_debug_init or dwarf2out_frame_debug_after_prologue.
+ * lto-streamer-in.c (lto_init_eh): Don't call dwarf2out_frame_init.
+ * toplev.c (lang_dependent_init): Likewise.
+
2011-07-07 Richard Henderson <rth@redhat.com>
* dwarf2out.c (fde_table, fde_table_allocated, fde_table_in_use,
+2011-07-07 Richard Henderson <rth@redhat.com>
+
+ * gcc-interface/misc.c (gnat_init_gcc_eh): Don't call
+ dwarf2out_frame_init.
+
2011-07-07 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/misc.c (gnat_init): Tweak previous change.
void
gnat_init_gcc_eh (void)
{
-#ifdef DWARF2_UNWIND_INFO
- /* lang_dependent_init already called dwarf2out_frame_init if true. */
- int dwarf2out_frame_initialized = dwarf2out_do_frame ();
-#endif
-
/* We shouldn't do anything if the No_Exceptions_Handler pragma is set,
though. This could for instance lead to the emission of tables with
references to symbols (such as the Ada eh personality routine) within
flag_non_call_exceptions = 1;
init_eh ();
-
-#ifdef DWARF2_UNWIND_INFO
- if (!dwarf2out_frame_initialized && dwarf2out_do_frame ())
- dwarf2out_frame_init ();
-#endif
}
/* Print language-specific items in declaration NODE. */
extern void dwarf2out_vms_end_prologue (unsigned int, const char *);
extern void dwarf2out_vms_begin_epilogue (unsigned int, const char *);
extern void dwarf2out_end_epilogue (unsigned int, const char *);
-extern void dwarf2out_frame_init (void);
extern void dwarf2out_frame_finish (void);
/* Decide whether we want to emit frame unwind information for the current
translation unit. */
-extern int dwarf2out_do_frame (void);
-extern int dwarf2out_do_cfi_asm (void);
+extern bool dwarf2out_do_frame (void);
+extern bool dwarf2out_do_cfi_asm (void);
extern void dwarf2out_switch_text_section (void);
const char *remap_debug_filename (const char *);
If AFTER_P is false, we're being called before the insn is emitted,
otherwise after. Call instructions get invoked twice. */
-void
+static void
dwarf2out_frame_debug (rtx insn, bool after_p)
{
rtx note, n;
cfi_insn = NULL;
}
-/* Called once at the start of final to initialize some data for the
- current function. */
-
-void
-dwarf2out_frame_debug_init (void)
-{
- 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);
- gcc_assert (cfa.reg
- == (unsigned long)DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM));
-
- old_cfa = cfa;
- cfa.reg = STACK_POINTER_REGNUM;
- cfa_store = cfa;
- cfa_temp.reg = -1;
- cfa_temp.offset = 0;
-}
-
/* Examine CFI and return true if a cfi label and set_loc is needed
beforehand. Even when generating CFI assembler instructions, we
still have to add the cfi to the list so that lookup_cfa works
}
}
-/* After the (optional) text prologue has been written, emit CFI insns
- and update the FDE for frame-related instructions. */
+/* Scan the function and create the initial set of CFI notes. */
-void
-dwarf2out_frame_debug_after_prologue (void)
+static void
+create_cfi_notes (void)
{
rtx insn;
dwarf2out_frame_debug (insn, true);
}
-
- add_cfis_to_fde ();
}
/* Determine if we need to save and restore CFI information around this
old_cfa = old_cfa_remember;
cfa_remember.in_use = 0;
}
+\f
-/* Run once per function. */
+/* Annotate the function with NOTE_INSN_CFI notes to record the CFI
+ state at each location within the function. These notes will be
+ emitted during pass_final. */
-void
-dwarf2cfi_function_init (void)
+static unsigned int
+execute_dwarf2_frame (void)
{
- args_size = old_args_size = 0;
-}
+ /* The first time we're called, compute the incoming frame state. */
+ if (cie_cfi_vec == NULL)
+ {
+ dw_cfa_location loc;
-/* Run once. */
+ memset(&old_cfa, 0, sizeof (old_cfa));
+ old_cfa.reg = INVALID_REGNUM;
-void
-dwarf2out_frame_init (void)
-{
- dw_cfa_location loc;
+ /* On entry, the Canonical Frame Address is at SP. */
+ memset(&loc, 0, sizeof (loc));
+ loc.reg = STACK_POINTER_REGNUM;
+ loc.offset = INCOMING_FRAME_SP_OFFSET;
+ def_cfa_1 (true, &loc);
- /* Generate the CFA instructions common to all FDE's. Do it now for the
- sake of lookup_cfa. */
+ if (targetm.debug_unwind_info () == UI_DWARF2
+ || targetm_common.except_unwind_info (&global_options) == UI_DWARF2)
+ initial_return_save (INCOMING_RETURN_ADDR_RTX);
+ }
- memset(&old_cfa, 0, sizeof (old_cfa));
- old_cfa.reg = INVALID_REGNUM;
+ /* Set up state for generating call frame debug info. */
+ lookup_cfa (&cfa);
+ gcc_assert (cfa.reg
+ == (unsigned long)DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM));
- /* On entry, the Canonical Frame Address is at SP. */
- memset(&loc, 0, sizeof (loc));
- loc.reg = STACK_POINTER_REGNUM;
- loc.offset = INCOMING_FRAME_SP_OFFSET;
- def_cfa_1 (true, &loc);
+ old_cfa = cfa;
+ cfa.reg = STACK_POINTER_REGNUM;
+ cfa_store = cfa;
+ cfa_temp.reg = -1;
+ cfa_temp.offset = 0;
+
+ dwarf2out_alloc_current_fde ();
+
+ /* Do the work. */
+ create_cfi_notes ();
+ add_cfis_to_fde ();
+
+ /* Reset all function-specific information, particularly for GC. */
+ XDELETEVEC (barrier_args_size);
+ barrier_args_size = NULL;
+ regs_saved_in_regs = NULL;
+ queued_reg_saves = NULL;
+ args_size = old_args_size = 0;
- if (targetm.debug_unwind_info () == UI_DWARF2
- || targetm_common.except_unwind_info (&global_options) == UI_DWARF2)
- initial_return_save (INCOMING_RETURN_ADDR_RTX);
+ return 0;
}
\f
-/* Save the result of dwarf2out_do_frame across PCH. */
-static GTY(()) bool saved_do_cfi_asm = 0;
+/* Save the result of dwarf2out_do_frame across PCH.
+ This variable is tri-state, with 0 unset, >0 true, <0 false. */
+static GTY(()) signed char saved_do_cfi_asm = 0;
/* Decide whether we want to emit frame unwind information for the current
translation unit. */
-int
+bool
dwarf2out_do_frame (void)
{
/* We want to emit correct CFA location expressions or lists, so we
if (write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG)
return true;
- if (saved_do_cfi_asm)
+ if (saved_do_cfi_asm > 0)
return true;
if (targetm.debug_unwind_info () == UI_DWARF2)
/* Decide whether to emit frame unwind via assembler directives. */
-int
+bool
dwarf2out_do_cfi_asm (void)
{
int enc;
#ifdef MIPS_DEBUGGING_INFO
return false;
#endif
- if (saved_do_cfi_asm)
- return true;
+
+ if (saved_do_cfi_asm != 0)
+ return saved_do_cfi_asm > 0;
+
+ /* Assume failure for a moment. */
+ saved_do_cfi_asm = -1;
+
if (!flag_dwarf2_cfi_asm || !dwarf2out_do_frame ())
return false;
if (!HAVE_GAS_CFI_PERSONALITY_DIRECTIVE)
&& targetm_common.except_unwind_info (&global_options) != UI_DWARF2)
return false;
- saved_do_cfi_asm = true;
+ /* Success! */
+ saved_do_cfi_asm = 1;
return true;
}
+static bool
+gate_dwarf2_frame (void)
+{
+#ifndef HAVE_prologue
+ /* Targets which still implement the prologue in assembler text
+ cannot use the generic dwarf2 unwinding. */
+ return false;
+#endif
+
+ /* ??? What to do for UI_TARGET unwinding? They might be able to benefit
+ from the optimized shrink-wrapping annotations that we will compute.
+ For now, only produce the CFI notes for dwarf2. */
+ return dwarf2out_do_frame ();
+}
+
+struct rtl_opt_pass pass_dwarf2_frame =
+{
+ {
+ RTL_PASS,
+ "dwarf2", /* name */
+ gate_dwarf2_frame, /* gate */
+ execute_dwarf2_frame, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_FINAL, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0 /* todo_flags_finish */
+ }
+};
+
#include "gt-dwarf2cfi.h"
if (!do_frame)
return;
+ /* Cater to the various TARGET_ASM_OUTPUT_MI_THUNK implementations that
+ emit insns as rtx but bypass the bulk of rest_of_compilation, which
+ would include pass_dwarf2_frame. If we've not created the FDE yet,
+ do so now. */
+ fde = cfun->fde;
+ if (fde == NULL)
+ fde = dwarf2out_alloc_current_fde ();
+
/* Initialize the bits of CURRENT_FDE that were not available earlier. */
- fde = dwarf2out_alloc_current_fde ();
fde->dw_fde_begin = dup_label;
fde->dw_fde_current_label = dup_label;
fde->in_std_section = (fnsec == text_section
|| (cold_text_section && fnsec == cold_text_section));
- dwarf2cfi_function_init ();
-
/* We only want to output line number information for the genuine dwarf2
prologue case, not the eh frame case. */
#ifdef DWARF2_DEBUGGING_INFO
extern dw_fde_ref dwarf2out_alloc_current_fde (void);
/* Interface from dwarf2cfi.c to dwarf2out.c. */
-extern void dwarf2cfi_function_init (void);
extern void lookup_cfa_1 (dw_cfi_ref cfi, dw_cfa_location *loc,
dw_cfa_location *remember);
extern bool cfa_equal_p (const dw_cfa_location *, const dw_cfa_location *);
(enum dwarf_call_frame_info cfi);
extern void dwarf2out_decl (tree);
-extern void dwarf2out_frame_debug (rtx, bool);
-extern void dwarf2out_frame_debug_init (void);
-extern void dwarf2out_frame_debug_after_prologue (void);
extern void dwarf2out_emit_cfi (dw_cfi_ref cfi);
extern void debug_dwarf (void);
if (targetm.profile_before_prologue () && crtl->profile)
profile_function (file);
-#if defined (HAVE_prologue)
- if (dwarf2out_do_frame ())
- dwarf2out_frame_debug_init ();
-#endif
-
/* If debugging, assign block numbers to all of the blocks in this
function. */
if (write_symbols)
/* First output the function prologue: code to set up the stack frame. */
targetm.asm_out.function_prologue (file, get_frame_size ());
-#if defined (HAVE_prologue)
- if (dwarf2out_do_frame ())
- dwarf2out_frame_debug_after_prologue ();
-#endif
-
/* If the machine represents the prologue as RTL, the profiling code must
be emitted when NOTE_INSN_PROLOGUE_END is scanned. */
#ifdef HAVE_prologue
flag_exceptions = 1;
init_eh ();
- /* Initialize dwarf2 tables. Since dwarf2out_do_frame() returns
- true only when exceptions are enabled, this initialization is
- never done during lang_dependent_init. */
-#if defined DWARF2_DEBUGGING_INFO || defined DWARF2_UNWIND_INFO
- if (dwarf2out_do_frame ())
- dwarf2out_frame_init ();
-#endif
-
eh_initialized_p = true;
}
NEXT_PASS (pass_convert_to_eh_region_ranges);
NEXT_PASS (pass_shorten_branches);
NEXT_PASS (pass_set_nothrow_function_flags);
+ NEXT_PASS (pass_dwarf2_frame);
NEXT_PASS (pass_final);
}
NEXT_PASS (pass_df_finish);
predefined types. */
timevar_push (TV_SYMOUT);
-#if defined DWARF2_DEBUGGING_INFO || defined DWARF2_UNWIND_INFO
- if (dwarf2out_do_frame ())
- dwarf2out_frame_init ();
-#endif
-
/* Now we have the correct original filename, we can initialize
debug output. */
(*debug_hooks->init) (name);
extern struct rtl_opt_pass pass_convert_to_eh_region_ranges;
extern struct rtl_opt_pass pass_shorten_branches;
extern struct rtl_opt_pass pass_set_nothrow_function_flags;
+extern struct rtl_opt_pass pass_dwarf2_frame;
extern struct rtl_opt_pass pass_final;
extern struct rtl_opt_pass pass_rtl_seqabstr;
extern struct gimple_opt_pass pass_release_ssa_names;