dwarf2: Extract cfi creation to a new pass.
authorRichard Henderson <rth@redhat.com>
Fri, 8 Jul 2011 00:05:57 +0000 (17:05 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Fri, 8 Jul 2011 00:05:57 +0000 (17:05 -0700)
        * 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

12 files changed:
gcc/ChangeLog
gcc/ada/ChangeLog
gcc/ada/gcc-interface/misc.c
gcc/debug.h
gcc/dwarf2cfi.c
gcc/dwarf2out.c
gcc/dwarf2out.h
gcc/final.c
gcc/lto-streamer-in.c
gcc/passes.c
gcc/toplev.c
gcc/tree-pass.h

index 3322697f7ff821514feac5ab2f5b75c011b77d6e..bfa3eb7069b9866feebd270bc7d63be90ce6bb4e 100644 (file)
@@ -1,3 +1,24 @@
+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,
index a0490596d93615b24d421cb41443c432c86a984f..833c44a2a596ba51555b686692a3a0f934f1c2a6 100644 (file)
@@ -1,3 +1,8 @@
+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.
index 7021857804615548fac9c1cbad43c9ca89c48b9e..92426fd48b9943c4b5dab981a10a9f3385737a4c 100644 (file)
@@ -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.  */
index efdffe1889ab8a91fc720bc73248e5178bfdebe0..828ede2304e2b93f76eeba17af7d573b4091ac7a 100644 (file)
@@ -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 *);
index 3e63299676c503bc3f500e9fd81dd971ac54e24b..44655bb51bcb45ea4aff32cc657a90facc8c5840 100644 (file)
@@ -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;
 }
+\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
@@ -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"
index 51ec613e4e499febb70995244d3fd4a8466a3f72..337650d863d7eeb1d0193aa0069f9650bf09a42c 100644 (file)
@@ -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
index abc220868e0160b8c84715e3b169880cc9960549..7122dee3296af9dc2360331b19e94c11ead2618c 100644 (file)
@@ -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);
index 319d2389272d662fe6e0ec415984238995d1fb9d..483a6452d27a018bbca355e0bcab716ed2659448 100644 (file)
@@ -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
index 7a4f7225bdc14ec58d8388a0a8b3de093b5abd14..d24903309c8488d3a131fcd7c5fa0d692e5c6945 100644 (file)
@@ -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;
 }
 
index fc9767e39ca453a9d9b7ab360cf46e735f8f80b1..c7e77cbbbc1e179cf474c627a3d25c44f07293a7 100644 (file)
@@ -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);
index 884994cb0e4766cad1b82d6c6dac3e3d36965f68..4591c30264dbf8c8a916e25ae905750a554a9616 100644 (file)
@@ -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);
index 2d277edb12b4c0228756df4ef27592ca6d3843ae..f5de1f6c9b2dc8959339d11d91d12455a6d82bba 100644 (file)
@@ -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;