From 7644b3c7f08daeec085f4dc2ba180dab5bc29d28 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 7 Jul 2011 17:05:57 -0700 Subject: [PATCH] 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 --- gcc/ChangeLog | 21 +++++ gcc/ada/ChangeLog | 5 ++ gcc/ada/gcc-interface/misc.c | 10 --- gcc/debug.h | 5 +- gcc/dwarf2cfi.c | 161 +++++++++++++++++++++-------------- gcc/dwarf2out.c | 11 ++- gcc/dwarf2out.h | 4 - gcc/final.c | 10 --- gcc/lto-streamer-in.c | 8 -- gcc/passes.c | 1 + gcc/toplev.c | 5 -- gcc/tree-pass.h | 1 + 12 files changed, 135 insertions(+), 107 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3322697f7ff..bfa3eb7069b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,24 @@ +2011-07-07 Richard Henderson + + * 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 * dwarf2out.c (fde_table, fde_table_allocated, fde_table_in_use, diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index a0490596d93..833c44a2a59 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2011-07-07 Richard Henderson + + * gcc-interface/misc.c (gnat_init_gcc_eh): Don't call + dwarf2out_frame_init. + 2011-07-07 Eric Botcazou * gcc-interface/misc.c (gnat_init): Tweak previous change. diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c index 70218578046..92426fd48b9 100644 --- a/gcc/ada/gcc-interface/misc.c +++ b/gcc/ada/gcc-interface/misc.c @@ -339,11 +339,6 @@ gnat_init (void) 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 @@ -370,11 +365,6 @@ gnat_init_gcc_eh (void) 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. */ diff --git a/gcc/debug.h b/gcc/debug.h index efdffe1889a..828ede2304e 100644 --- a/gcc/debug.h +++ b/gcc/debug.h @@ -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_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 *); diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c index 3e63299676c..44655bb51bc 100644 --- a/gcc/dwarf2cfi.c +++ b/gcc/dwarf2cfi.c @@ -2173,7 +2173,7 @@ dwarf2out_frame_debug_expr (rtx expr) 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; @@ -2318,33 +2318,6 @@ dwarf2out_frame_debug (rtx insn, bool after_p) 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 @@ -2440,11 +2413,10 @@ add_cfis_to_fde (void) } } -/* 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; @@ -2499,8 +2471,6 @@ dwarf2out_frame_debug_after_prologue (void) dwarf2out_frame_debug (insn, true); } - - add_cfis_to_fde (); } /* Determine if we need to save and restore CFI information around this @@ -2599,47 +2569,70 @@ dwarf2out_frame_debug_restore_state (void) old_cfa = old_cfa_remember; 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 -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; } -/* 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 @@ -2648,7 +2641,7 @@ dwarf2out_do_frame (void) 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) @@ -2663,7 +2656,7 @@ dwarf2out_do_frame (void) /* Decide whether to emit frame unwind via assembler directives. */ -int +bool dwarf2out_do_cfi_asm (void) { int enc; @@ -2671,8 +2664,13 @@ dwarf2out_do_cfi_asm (void) #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) @@ -2694,8 +2692,43 @@ dwarf2out_do_cfi_asm (void) && 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" diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 51ec613e4e4..337650d863d 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -1605,15 +1605,20 @@ dwarf2out_begin_prologue (unsigned int line ATTRIBUTE_UNUSED, 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 diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h index abc220868e0..7122dee3296 100644 --- a/gcc/dwarf2out.h +++ b/gcc/dwarf2out.h @@ -229,7 +229,6 @@ extern enum machine_mode get_address_mode (rtx mem); 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 *); @@ -243,9 +242,6 @@ extern enum dw_cfi_oprnd_type dw_cfi_oprnd2_desc (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); diff --git a/gcc/final.c b/gcc/final.c index 319d2389272..483a6452d27 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -1560,11 +1560,6 @@ final_start_function (rtx first ATTRIBUTE_UNUSED, FILE *file, 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) @@ -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. */ 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 diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c index 7a4f7225bdc..d24903309c8 100644 --- a/gcc/lto-streamer-in.c +++ b/gcc/lto-streamer-in.c @@ -657,14 +657,6 @@ lto_init_eh (void) 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; } diff --git a/gcc/passes.c b/gcc/passes.c index fc9767e39ca..c7e77cbbbc1 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -1506,6 +1506,7 @@ init_optimization_passes (void) 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); diff --git a/gcc/toplev.c b/gcc/toplev.c index 884994cb0e4..4591c30264d 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -1741,11 +1741,6 @@ lang_dependent_init (const char *name) 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); diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h index 2d277edb12b..f5de1f6c9b2 100644 --- a/gcc/tree-pass.h +++ b/gcc/tree-pass.h @@ -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_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; -- 2.30.2