This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[lto] fix debug information generation


The patch below fixes a problem with LTO choking on valid dwarf
information.  We are now able to run gcc/*.c through 'gcc -flto -O2'
successfully.  lto1 cannot yet read all of the output files, however.

The problematic code that triggered the problem looked like:

void
somefunc (void)
{
  ...
  if (...)
    {
      ...struct or union declaration...		(1)
      ...
    }
  ...
}

[NB: when I use "LTO" as a noun below, I mean 'gcc -flto -O2']

When LTO attempted to generate debug information for the type of the
declaration at (1), problems would ensue, as the TYPE_CONTEXT of the
type was a BLOCK and the code path LTO was taking was never written to
deal with such a case.  (The usual way this is handled is through a
top-down walk of the scope tree, generating debug info as we went.
LTO's approach was more like grabbing nodes from the scope tree more or
less at random and hoping things didn't break.)

The solution chosen was to generate complete debug information as early
as possible, rather than on-demand as was being done before.  Therefore,
when LTO information is being output and information for types is
requested, the exact information is already there.  The only wrinkle
with this is that the generation of debug information for types is
combined with the generation of debug information for frames.  The
latter expects that there will be RTL to poke at and we do not have RTL
when generating LTO information.  To handle this, a special flag was
introduced for LTO's usage that controls the generation of debug frame
info; this flag is unset when LTO is forcing early generation of DWARF
and set at all other times.

Approved by Mark offline and committed.

-Nathan

2007-09-26  Nathan Froyd  <froydnj@codesourcery.com>

	* dwarf2out.h (dwarf2_generate_frame_info_p): Declare.
	* dwarf2out.c (dwarf2_generate_frame_info_p): Define it.
	(gen_subprogram_die): Consult it to determine whether to generate
	frame information.
	(lto_type_ref): Remove sorry call.
	* lto-function-out.c (generate_early_dwarf_information): New function.
	(output_function): Call it.  Set current_function_decl and cfun to
	facilitate DWARF generation.

Index: gcc/dwarf2out.c
===================================================================
--- gcc/dwarf2out.c	(revision 128823)
+++ gcc/dwarf2out.c	(working copy)
@@ -110,6 +110,16 @@ static void dwarf2out_source_line (unsig
 #define DWARF2_FRAME_REG_OUT(REGNO, FOR_EH) (REGNO)
 #endif
 
+/* LTO needs to call into the dwarf machinery to generate dwarf as early
+   as possible, but said machinery was not implemented with this
+   possibility in mind.  The bits that cause us real problems are those
+   that deal with frame/unwind information.  We provide this flag to
+   suppress the normal generation of frame/unwind information when
+   necessary.  It should only ever be used by LTO and it may not catch
+   every case in existence--just those of interest to LTO call
+   paths.  */
+bool dwarf2_generate_frame_info_p = true;
+
 /* Decide whether we want to emit frame unwind information for the current
    translation unit.  */
 
@@ -12180,39 +12190,42 @@ gen_subprogram_die (tree decl, dw_die_re
 	   */
 	}
 
+      if (dwarf2_generate_frame_info_p)
+        {
 #ifdef MIPS_DEBUGGING_INFO
-      /* Add a reference to the FDE for this routine.  */
-      add_AT_fde_ref (subr_die, DW_AT_MIPS_fde, current_funcdef_fde);
+          /* Add a reference to the FDE for this routine.  */
+          add_AT_fde_ref (subr_die, DW_AT_MIPS_fde, current_funcdef_fde);
 #endif
 
-      cfa_fb_offset = CFA_FRAME_BASE_OFFSET (decl);
-
-      /* We define the "frame base" as the function's CFA.  This is more
-	 convenient for several reasons: (1) It's stable across the prologue
-	 and epilogue, which makes it better than just a frame pointer,
-	 (2) With dwarf3, there exists a one-byte encoding that allows us
-	 to reference the .debug_frame data by proxy, but failing that,
-	 (3) We can at least reuse the code inspection and interpretation
-	 code that determines the CFA position at various points in the
-	 function.  */
-      /* ??? Use some command-line or configury switch to enable the use
-	 of dwarf3 DW_OP_call_frame_cfa.  At present there are no dwarf
-	 consumers that understand it; fall back to "pure" dwarf2 and
-	 convert the CFA data into a location list.  */
-      {
-	dw_loc_list_ref list = convert_cfa_to_fb_loc_list (cfa_fb_offset);
-	if (list->dw_loc_next)
-	  add_AT_loc_list (subr_die, DW_AT_frame_base, list);
-	else
-	  add_AT_loc (subr_die, DW_AT_frame_base, list->expr);
-      }
+          cfa_fb_offset = CFA_FRAME_BASE_OFFSET (decl);
 
-      /* Compute a displacement from the "steady-state frame pointer" to
-	 the CFA.  The former is what all stack slots and argument slots
-	 will reference in the rtl; the later is what we've told the
-	 debugger about.  We'll need to adjust all frame_base references
-	 by this displacement.  */
-      compute_frame_pointer_to_fb_displacement (cfa_fb_offset);
+          /* We define the "frame base" as the function's CFA.  This is more
+             convenient for several reasons: (1) It's stable across the prologue
+             and epilogue, which makes it better than just a frame pointer,
+             (2) With dwarf3, there exists a one-byte encoding that allows us
+             to reference the .debug_frame data by proxy, but failing that,
+             (3) We can at least reuse the code inspection and interpretation
+             code that determines the CFA position at various points in the
+             function.  */
+          /* ??? Use some command-line or configury switch to enable the use
+             of dwarf3 DW_OP_call_frame_cfa.  At present there are no dwarf
+             consumers that understand it; fall back to "pure" dwarf2 and
+             convert the CFA data into a location list.  */
+          {
+            dw_loc_list_ref list = convert_cfa_to_fb_loc_list (cfa_fb_offset);
+            if (list->dw_loc_next)
+              add_AT_loc_list (subr_die, DW_AT_frame_base, list);
+            else
+              add_AT_loc (subr_die, DW_AT_frame_base, list->expr);
+          }
+
+          /* Compute a displacement from the "steady-state frame pointer" to
+             the CFA.  The former is what all stack slots and argument slots
+             will reference in the rtl; the later is what we've told the
+             debugger about.  We'll need to adjust all frame_base references
+             by this displacement.  */
+          compute_frame_pointer_to_fb_displacement (cfa_fb_offset);
+        }
 
       if (cfun->static_chain_decl)
 	add_AT_location_description (subr_die, DW_AT_static_link,
@@ -14953,8 +14966,8 @@ lto_type_ref (tree type, lto_out_ref *re
   scope = TYPE_CONTEXT (type);
   if (!FILE_SCOPE_P (scope))
     {
-      /* We do not yet support lexically scoped types.  */
-      sorry ("nested types are not supported by LTO");
+      /* We generate DWARF information very early in LTO, so assume that
+         modified_type_die will find already-generated type DIEs.  */
       scope_die = NULL;
     }
   else
Index: gcc/dwarf2out.h
===================================================================
--- gcc/dwarf2out.h	(revision 128823)
+++ gcc/dwarf2out.h	(working copy)
@@ -21,6 +21,8 @@ along with GCC; see the file COPYING3.  
 extern void dwarf2out_decl (tree);
 extern void dwarf2out_frame_debug (rtx, bool);
 
+extern bool dwarf2_generate_frame_info_p;
+
 extern void debug_dwarf (void);
 struct die_struct;
 extern void debug_dwarf_die (struct die_struct *);
Index: gcc/lto-function-out.c
===================================================================
--- gcc/lto-function-out.c	(revision 128823)
+++ gcc/lto-function-out.c	(working copy)
@@ -2059,6 +2059,21 @@ lto_static_init_local (void)
 static int function_num;
 #endif
 
+/* Generate complete DWARF information for the function now so that we
+   don't run into missing or incomplete information later.  */
+
+static void
+generate_early_dwarf_information (tree function)
+{
+  /* Don't bother with frame information, since we have no RTL.  */
+  dwarf2_generate_frame_info_p = false;
+
+  dwarf2out_decl (function);
+
+  /* Later passes, however, will need frame information.  */
+  dwarf2_generate_frame_info_p = true;
+}
+
 /* Output FN.  */
 
 static void
@@ -2070,6 +2085,15 @@ output_function (tree function)
 
   LTO_SET_DEBUGGING_STREAM (debug_main_stream, main_data);
 
+  gcc_assert (!current_function_decl && !cfun);
+
+  /* Set current_function_decl to what the dwarf2 machinery expects.  */
+  current_function_decl = function;
+  cfun = fn;
+
+  /* Generate debugging info as early as we can.  */
+  generate_early_dwarf_information (function);
+
   /* Make string 0 be a NULL string.  */
   output_1_stream (ob->string_stream, 0);
 
@@ -2115,6 +2139,9 @@ output_function (tree function)
   produce_asm (ob, function, true);
 
   destroy_output_block (ob, true);
+
+  current_function_decl = NULL;
+  cfun = NULL;
 }
 
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]