Commit 7644b3c7 by Richard Henderson Committed by Richard Henderson

dwarf2: Extract cfi creation to a new pass.

        * 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
parent a518b996
2011-07-07 Richard Henderson <rth@redhat.com> 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, * dwarf2out.c (fde_table, fde_table_allocated, fde_table_in_use,
FDE_TABLE_INCREMENT): Replace with... FDE_TABLE_INCREMENT): Replace with...
(fde_vec): ... this, a new vector. (fde_vec): ... this, a new vector.
......
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> 2011-07-07 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/misc.c (gnat_init): Tweak previous change. * gcc-interface/misc.c (gnat_init): Tweak previous change.
......
...@@ -339,11 +339,6 @@ gnat_init (void) ...@@ -339,11 +339,6 @@ gnat_init (void)
void void
gnat_init_gcc_eh (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, /* 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 though. This could for instance lead to the emission of tables with
references to symbols (such as the Ada eh personality routine) within references to symbols (such as the Ada eh personality routine) within
...@@ -370,11 +365,6 @@ gnat_init_gcc_eh (void) ...@@ -370,11 +365,6 @@ gnat_init_gcc_eh (void)
flag_non_call_exceptions = 1; flag_non_call_exceptions = 1;
init_eh (); init_eh ();
#ifdef DWARF2_UNWIND_INFO
if (!dwarf2out_frame_initialized && dwarf2out_do_frame ())
dwarf2out_frame_init ();
#endif
} }
/* Print language-specific items in declaration NODE. */ /* Print language-specific items in declaration NODE. */
......
...@@ -178,12 +178,11 @@ extern void dwarf2out_begin_prologue (unsigned int, const char *); ...@@ -178,12 +178,11 @@ extern void dwarf2out_begin_prologue (unsigned int, const char *);
extern void dwarf2out_vms_end_prologue (unsigned int, const char *); extern void dwarf2out_vms_end_prologue (unsigned int, const char *);
extern void dwarf2out_vms_begin_epilogue (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_end_epilogue (unsigned int, const char *);
extern void dwarf2out_frame_init (void);
extern void dwarf2out_frame_finish (void); extern void dwarf2out_frame_finish (void);
/* Decide whether we want to emit frame unwind information for the current /* Decide whether we want to emit frame unwind information for the current
translation unit. */ translation unit. */
extern int dwarf2out_do_frame (void); extern bool dwarf2out_do_frame (void);
extern int dwarf2out_do_cfi_asm (void); extern bool dwarf2out_do_cfi_asm (void);
extern void dwarf2out_switch_text_section (void); extern void dwarf2out_switch_text_section (void);
const char *remap_debug_filename (const char *); const char *remap_debug_filename (const char *);
......
...@@ -2173,7 +2173,7 @@ dwarf2out_frame_debug_expr (rtx expr) ...@@ -2173,7 +2173,7 @@ dwarf2out_frame_debug_expr (rtx expr)
If AFTER_P is false, we're being called before the insn is emitted, If AFTER_P is false, we're being called before the insn is emitted,
otherwise after. Call instructions get invoked twice. */ otherwise after. Call instructions get invoked twice. */
void static void
dwarf2out_frame_debug (rtx insn, bool after_p) dwarf2out_frame_debug (rtx insn, bool after_p)
{ {
rtx note, n; rtx note, n;
...@@ -2318,33 +2318,6 @@ dwarf2out_frame_debug (rtx insn, bool after_p) ...@@ -2318,33 +2318,6 @@ dwarf2out_frame_debug (rtx insn, bool after_p)
cfi_insn = NULL; 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 /* Examine CFI and return true if a cfi label and set_loc is needed
beforehand. Even when generating CFI assembler instructions, we beforehand. Even when generating CFI assembler instructions, we
still have to add the cfi to the list so that lookup_cfa works still have to add the cfi to the list so that lookup_cfa works
...@@ -2440,11 +2413,10 @@ add_cfis_to_fde (void) ...@@ -2440,11 +2413,10 @@ add_cfis_to_fde (void)
} }
} }
/* After the (optional) text prologue has been written, emit CFI insns /* Scan the function and create the initial set of CFI notes. */
and update the FDE for frame-related instructions. */
void static void
dwarf2out_frame_debug_after_prologue (void) create_cfi_notes (void)
{ {
rtx insn; rtx insn;
...@@ -2499,8 +2471,6 @@ dwarf2out_frame_debug_after_prologue (void) ...@@ -2499,8 +2471,6 @@ dwarf2out_frame_debug_after_prologue (void)
dwarf2out_frame_debug (insn, true); dwarf2out_frame_debug (insn, true);
} }
add_cfis_to_fde ();
} }
/* Determine if we need to save and restore CFI information around this /* Determine if we need to save and restore CFI information around this
...@@ -2599,47 +2569,70 @@ dwarf2out_frame_debug_restore_state (void) ...@@ -2599,47 +2569,70 @@ dwarf2out_frame_debug_restore_state (void)
old_cfa = old_cfa_remember; old_cfa = old_cfa_remember;
cfa_remember.in_use = 0; cfa_remember.in_use = 0;
} }
/* 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 static unsigned int
dwarf2cfi_function_init (void) 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 /* On entry, the Canonical Frame Address is at SP. */
dwarf2out_frame_init (void) memset(&loc, 0, sizeof (loc));
{ loc.reg = STACK_POINTER_REGNUM;
dw_cfa_location loc; 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 if (targetm.debug_unwind_info () == UI_DWARF2
sake of lookup_cfa. */ || targetm_common.except_unwind_info (&global_options) == UI_DWARF2)
initial_return_save (INCOMING_RETURN_ADDR_RTX);
}
memset(&old_cfa, 0, sizeof (old_cfa)); /* Set up state for generating call frame debug info. */
old_cfa.reg = INVALID_REGNUM; lookup_cfa (&cfa);
gcc_assert (cfa.reg
== (unsigned long)DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM));
/* On entry, the Canonical Frame Address is at SP. */ old_cfa = cfa;
memset(&loc, 0, sizeof (loc)); cfa.reg = STACK_POINTER_REGNUM;
loc.reg = STACK_POINTER_REGNUM; cfa_store = cfa;
loc.offset = INCOMING_FRAME_SP_OFFSET; cfa_temp.reg = -1;
def_cfa_1 (true, &loc); 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 return 0;
|| targetm_common.except_unwind_info (&global_options) == UI_DWARF2)
initial_return_save (INCOMING_RETURN_ADDR_RTX);
} }
/* Save the result of dwarf2out_do_frame across PCH. */ /* Save the result of dwarf2out_do_frame across PCH.
static GTY(()) bool saved_do_cfi_asm = 0; 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 /* Decide whether we want to emit frame unwind information for the current
translation unit. */ translation unit. */
int bool
dwarf2out_do_frame (void) dwarf2out_do_frame (void)
{ {
/* We want to emit correct CFA location expressions or lists, so we /* We want to emit correct CFA location expressions or lists, so we
...@@ -2648,7 +2641,7 @@ dwarf2out_do_frame (void) ...@@ -2648,7 +2641,7 @@ dwarf2out_do_frame (void)
if (write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG) if (write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG)
return true; return true;
if (saved_do_cfi_asm) if (saved_do_cfi_asm > 0)
return true; return true;
if (targetm.debug_unwind_info () == UI_DWARF2) if (targetm.debug_unwind_info () == UI_DWARF2)
...@@ -2663,7 +2656,7 @@ dwarf2out_do_frame (void) ...@@ -2663,7 +2656,7 @@ dwarf2out_do_frame (void)
/* Decide whether to emit frame unwind via assembler directives. */ /* Decide whether to emit frame unwind via assembler directives. */
int bool
dwarf2out_do_cfi_asm (void) dwarf2out_do_cfi_asm (void)
{ {
int enc; int enc;
...@@ -2671,8 +2664,13 @@ dwarf2out_do_cfi_asm (void) ...@@ -2671,8 +2664,13 @@ dwarf2out_do_cfi_asm (void)
#ifdef MIPS_DEBUGGING_INFO #ifdef MIPS_DEBUGGING_INFO
return false; return false;
#endif #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 ()) if (!flag_dwarf2_cfi_asm || !dwarf2out_do_frame ())
return false; return false;
if (!HAVE_GAS_CFI_PERSONALITY_DIRECTIVE) if (!HAVE_GAS_CFI_PERSONALITY_DIRECTIVE)
...@@ -2694,8 +2692,43 @@ dwarf2out_do_cfi_asm (void) ...@@ -2694,8 +2692,43 @@ dwarf2out_do_cfi_asm (void)
&& targetm_common.except_unwind_info (&global_options) != UI_DWARF2) && targetm_common.except_unwind_info (&global_options) != UI_DWARF2)
return false; return false;
saved_do_cfi_asm = true; /* Success! */
saved_do_cfi_asm = 1;
return true; 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" #include "gt-dwarf2cfi.h"
...@@ -1605,15 +1605,20 @@ dwarf2out_begin_prologue (unsigned int line ATTRIBUTE_UNUSED, ...@@ -1605,15 +1605,20 @@ dwarf2out_begin_prologue (unsigned int line ATTRIBUTE_UNUSED,
if (!do_frame) if (!do_frame)
return; 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. */ /* 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_begin = dup_label;
fde->dw_fde_current_label = dup_label; fde->dw_fde_current_label = dup_label;
fde->in_std_section = (fnsec == text_section fde->in_std_section = (fnsec == text_section
|| (cold_text_section && fnsec == cold_text_section)); || (cold_text_section && fnsec == cold_text_section));
dwarf2cfi_function_init ();
/* We only want to output line number information for the genuine dwarf2 /* We only want to output line number information for the genuine dwarf2
prologue case, not the eh frame case. */ prologue case, not the eh frame case. */
#ifdef DWARF2_DEBUGGING_INFO #ifdef DWARF2_DEBUGGING_INFO
......
...@@ -229,7 +229,6 @@ extern enum machine_mode get_address_mode (rtx mem); ...@@ -229,7 +229,6 @@ extern enum machine_mode get_address_mode (rtx mem);
extern dw_fde_ref dwarf2out_alloc_current_fde (void); extern dw_fde_ref dwarf2out_alloc_current_fde (void);
/* Interface from dwarf2cfi.c to dwarf2out.c. */ /* 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, extern void lookup_cfa_1 (dw_cfi_ref cfi, dw_cfa_location *loc,
dw_cfa_location *remember); dw_cfa_location *remember);
extern bool cfa_equal_p (const dw_cfa_location *, const dw_cfa_location *); extern bool cfa_equal_p (const dw_cfa_location *, const dw_cfa_location *);
...@@ -243,9 +242,6 @@ extern enum dw_cfi_oprnd_type dw_cfi_oprnd2_desc ...@@ -243,9 +242,6 @@ extern enum dw_cfi_oprnd_type dw_cfi_oprnd2_desc
(enum dwarf_call_frame_info cfi); (enum dwarf_call_frame_info cfi);
extern void dwarf2out_decl (tree); 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 dwarf2out_emit_cfi (dw_cfi_ref cfi);
extern void debug_dwarf (void); extern void debug_dwarf (void);
......
...@@ -1560,11 +1560,6 @@ final_start_function (rtx first ATTRIBUTE_UNUSED, FILE *file, ...@@ -1560,11 +1560,6 @@ final_start_function (rtx first ATTRIBUTE_UNUSED, FILE *file,
if (targetm.profile_before_prologue () && crtl->profile) if (targetm.profile_before_prologue () && crtl->profile)
profile_function (file); 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 /* If debugging, assign block numbers to all of the blocks in this
function. */ function. */
if (write_symbols) if (write_symbols)
...@@ -1589,11 +1584,6 @@ final_start_function (rtx first ATTRIBUTE_UNUSED, FILE *file, ...@@ -1589,11 +1584,6 @@ final_start_function (rtx first ATTRIBUTE_UNUSED, FILE *file,
/* First output the function prologue: code to set up the stack frame. */ /* First output the function prologue: code to set up the stack frame. */
targetm.asm_out.function_prologue (file, get_frame_size ()); 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 /* If the machine represents the prologue as RTL, the profiling code must
be emitted when NOTE_INSN_PROLOGUE_END is scanned. */ be emitted when NOTE_INSN_PROLOGUE_END is scanned. */
#ifdef HAVE_prologue #ifdef HAVE_prologue
......
...@@ -657,14 +657,6 @@ lto_init_eh (void) ...@@ -657,14 +657,6 @@ lto_init_eh (void)
flag_exceptions = 1; flag_exceptions = 1;
init_eh (); 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; eh_initialized_p = true;
} }
......
...@@ -1506,6 +1506,7 @@ init_optimization_passes (void) ...@@ -1506,6 +1506,7 @@ init_optimization_passes (void)
NEXT_PASS (pass_convert_to_eh_region_ranges); NEXT_PASS (pass_convert_to_eh_region_ranges);
NEXT_PASS (pass_shorten_branches); NEXT_PASS (pass_shorten_branches);
NEXT_PASS (pass_set_nothrow_function_flags); NEXT_PASS (pass_set_nothrow_function_flags);
NEXT_PASS (pass_dwarf2_frame);
NEXT_PASS (pass_final); NEXT_PASS (pass_final);
} }
NEXT_PASS (pass_df_finish); NEXT_PASS (pass_df_finish);
......
...@@ -1741,11 +1741,6 @@ lang_dependent_init (const char *name) ...@@ -1741,11 +1741,6 @@ lang_dependent_init (const char *name)
predefined types. */ predefined types. */
timevar_push (TV_SYMOUT); 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 /* Now we have the correct original filename, we can initialize
debug output. */ debug output. */
(*debug_hooks->init) (name); (*debug_hooks->init) (name);
......
...@@ -567,6 +567,7 @@ extern struct rtl_opt_pass pass_split_before_regstack; ...@@ -567,6 +567,7 @@ extern struct rtl_opt_pass pass_split_before_regstack;
extern struct rtl_opt_pass pass_convert_to_eh_region_ranges; 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_shorten_branches;
extern struct rtl_opt_pass pass_set_nothrow_function_flags; 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_final;
extern struct rtl_opt_pass pass_rtl_seqabstr; extern struct rtl_opt_pass pass_rtl_seqabstr;
extern struct gimple_opt_pass pass_release_ssa_names; extern struct gimple_opt_pass pass_release_ssa_names;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment