public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [debug-early] C++ clones and limbo DIEs
@ 2015-01-16  3:11 Aldy Hernandez
  2015-01-16  4:30 ` Jason Merrill
  0 siblings, 1 reply; 36+ messages in thread
From: Aldy Hernandez @ 2015-01-16  3:11 UTC (permalink / raw)
  To: jason merrill; +Cc: Richard Biener, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1476 bytes --]

Hi Jason.  Hi Richard.

While adjusting the limbdo_die_list for early debug I noticed we weren't 
early generating C++ constructors/destructors.  This got me on a detour 
of sorts.

I noticed dwarf2out's gen_member_die() disallows generation of clones 
earlier, by design:

      /* Don't include clones in the member list.  */
      if (DECL_ABSTRACT_ORIGIN (member))
        continue;

I played around trying to disable this "feature", but my approach ran 
into various walls, and I decided instead to attack it from the 
front-end side. The attached patch generates early DIEs for the C++ 
clones in the C++ parser. I'd be (un)happy to revisit the dwarf2out 
approach if it's deemed more appropriate.

Now back to limbdo_die_list... My approach is to flush the limbo list, 
generically, after the front-ends have finished, by adding a new 
"early_finish" debug hook.  This gets rid of any permanence into LTO 
time.  Then I flush it out again, if the middle end (or LTO, etc) has 
added any limbo DIEs.  I wish we didn't need to flush the limbo list 
past the compilation proper, but some things like Cilk+ generate 
function trees way late in the game, so we end up generating limbo DIEs 
past where I'd like to.  Please see the comment in the source code.

All in all, this patch should get rid of any middle-end dependence on 
the early debug generated limbo DIEs.

Are you happy with this?  I'd like to get your input before committing 
to this approach.

Thanks.
Aldy

[-- Attachment #2: curr --]
[-- Type: text/plain, Size: 10736 bytes --]

commit cd20df2a48ce4f0d4e64626d61f8f61a810cf742
Author: Aldy Hernandez <aldyh@redhat.com>
Date:   Wed Jan 14 13:33:40 2015 -0800

    	* cp/decl2.c (c_parse_final_cleanups): Emit early debug
    	information for clones.
    	* dbxout.c (dbx_debug_hooks): Add early_finish field.
    	(xcoff_debug_hooks): Same.
    	* sdbout.c (sdb_debug_hooks): Same.
    	* vmsdbgout.c (vmsdbg_debug_hooks): Same.
    	* debug.c (do_nothing_debug_hooks): Same.
    	* debug.h (struct gcc_debug_hooks): Same.
    	* dwarf2out.c (dwarf2_debug_hooks): Same.
    	(dwarf2out_finish): Move limbo list handling to...
    	(dwarf2out_early_finish): ...here.
    	* toplev.c (compile_file): Call debug_hooks->early_finish.

diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 691688b..b9a407a 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -4737,6 +4737,13 @@ c_parse_final_cleanups (void)
      generate initial debug information.  */
   timevar_stop (TV_PHASE_PARSING);
   timevar_start (TV_PHASE_DBGINFO);
+
+  /* Emit debug information for clones.  */
+  symtab_node *node;
+  FOR_EACH_DEFINED_SYMBOL (node)
+    if (DECL_ABSTRACT_ORIGIN (node->decl))
+      debug_hooks->early_global_decl (DECL_ABSTRACT_ORIGIN (node->decl));
+
   walk_namespaces (emit_debug_for_namespace, 0);
   if (vec_safe_length (pending_statics) != 0)
     {
diff --git a/gcc/dbxout.c b/gcc/dbxout.c
index 430a2eb..202ef8a 100644
--- a/gcc/dbxout.c
+++ b/gcc/dbxout.c
@@ -359,6 +359,7 @@ const struct gcc_debug_hooks dbx_debug_hooks =
   dbxout_init,
   dbxout_finish,
   debug_nothing_void,
+  debug_nothing_void,
   debug_nothing_int_charstar,
   debug_nothing_int_charstar,
   dbxout_start_source_file,
@@ -400,6 +401,7 @@ const struct gcc_debug_hooks xcoff_debug_hooks =
   dbxout_init,
   dbxout_finish,
   debug_nothing_void,
+  debug_nothing_void,
   debug_nothing_int_charstar,
   debug_nothing_int_charstar,
   dbxout_start_source_file,
diff --git a/gcc/debug.c b/gcc/debug.c
index 449d3a1..d0e00c0 100644
--- a/gcc/debug.c
+++ b/gcc/debug.c
@@ -27,6 +27,7 @@ const struct gcc_debug_hooks do_nothing_debug_hooks =
 {
   debug_nothing_charstar,
   debug_nothing_charstar,
+  debug_nothing_void,			/* early_finish */
   debug_nothing_void,
   debug_nothing_int_charstar,
   debug_nothing_int_charstar,
diff --git a/gcc/debug.h b/gcc/debug.h
index f9485bc..a8d3f23 100644
--- a/gcc/debug.h
+++ b/gcc/debug.h
@@ -30,6 +30,9 @@ struct gcc_debug_hooks
   /* Output debug symbols.  */
   void (* finish) (const char *main_filename);
 
+  /* Run cleanups necessary after early debug generation.  */
+  void (* early_finish) (void);
+
   /* Called from cgraph_optimize before starting to assemble
      functions/variables/toplevel asms.  */
   void (* assembly_start) (void);
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index e3ccda2..80d43af 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -2424,6 +2424,7 @@ build_cfa_aligned_loc (dw_cfa_location *cfa,
 
 static void dwarf2out_init (const char *);
 static void dwarf2out_finish (const char *);
+static void dwarf2out_early_finish (void);
 static void dwarf2out_assembly_start (void);
 static void dwarf2out_define (unsigned int, const char *);
 static void dwarf2out_undef (unsigned int, const char *);
@@ -2451,6 +2452,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
 {
   dwarf2out_init,
   dwarf2out_finish,
+  dwarf2out_early_finish,
   dwarf2out_assembly_start,
   dwarf2out_define,
   dwarf2out_undef,
@@ -24739,10 +24741,27 @@ optimize_location_lists (dw_die_ref die)
 static void
 dwarf2out_finish (const char *filename)
 {
-  limbo_die_node *node, *next_node;
   comdat_type_node *ctnode;
   dw_die_ref main_comp_unit_die;
 
+  /* Technically limbo_die_list should either be empty because
+     dwarf2out_early_finish took care of everything, or should _only_
+     have inline instances that will be created late (which is OK,
+     because they'll be pointing to the early generated abstract).
+
+     However, functions can be created after the parsers are done
+     (e.g. create_cilk_helper_decl), which will populate the
+     limbo_die_list again.  Eventually all late function creation
+     should be banned, or these new functions should be created with a
+     proper context_die, thus avoiding limbo.  For now, it doesn't
+     hurt, since late creation should have all the location
+     information needed (and if it doesn't, we don't care-- the code
+     is undebuggable).
+
+     If there was anything created late, flush it out.  */
+  if (limbo_die_list)
+    dwarf2out_early_finish ();
+
   /* PCH might result in DW_AT_producer string being restored from the
      header compilation, so always fill it with empty string initially
      and overwrite only here.  */
@@ -24767,55 +24786,6 @@ dwarf2out_finish (const char *filename)
 	add_comp_dir_attribute (comp_unit_die ());
     }
 
-  /* Traverse the limbo die list, and add parent/child links.  The only
-     dies without parents that should be here are concrete instances of
-     inline functions, and the comp_unit_die.  We can ignore the comp_unit_die.
-     For concrete instances, we can get the parent die from the abstract
-     instance.  */
-  for (node = limbo_die_list; node; node = next_node)
-    {
-      dw_die_ref die = node->die;
-      next_node = node->next;
-
-      if (die->die_parent == NULL)
-	{
-	  dw_die_ref origin = get_AT_ref (die, DW_AT_abstract_origin);
-
-	  if (origin && origin->die_parent)
-	    add_child_die (origin->die_parent, die);
-	  else if (is_cu_die (die))
-	    ;
-	  else if (seen_error ())
-	    /* It's OK to be confused by errors in the input.  */
-	    add_child_die (comp_unit_die (), die);
-	  else
-	    {
-	      /* In certain situations, the lexical block containing a
-		 nested function can be optimized away, which results
-		 in the nested function die being orphaned.  Likewise
-		 with the return type of that nested function.  Force
-		 this to be a child of the containing function.
-
-		 It may happen that even the containing function got fully
-		 inlined and optimized out.  In that case we are lost and
-		 assign the empty child.  This should not be big issue as
-		 the function is likely unreachable too.  */
-	      gcc_assert (node->created_for);
-
-	      if (DECL_P (node->created_for))
-		origin = get_context_die (DECL_CONTEXT (node->created_for));
-	      else if (TYPE_P (node->created_for))
-		origin = scope_die_for (node->created_for, comp_unit_die ());
-	      else
-		origin = comp_unit_die ();
-
-	      add_child_die (origin, die);
-	    }
-	}
-    }
-
-  limbo_die_list = NULL;
-
 #if ENABLE_ASSERT_CHECKING
   {
     dw_die_ref die = comp_unit_die (), c;
@@ -24860,9 +24830,10 @@ dwarf2out_finish (const char *filename)
   if (flag_eliminate_dwarf2_dups)
     break_out_includes (comp_unit_die ());
 
-  /* Traverse the DIE's and add add sibling attributes to those DIE's
+  /* Traverse the DIE's and add sibling attributes to those DIE's
      that have children.  */
   add_sibling_attributes (comp_unit_die ());
+  limbo_die_node *node;
   for (node = limbo_die_list; node; node = node->next)
     add_sibling_attributes (node->die);
   for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next)
@@ -25124,6 +25095,66 @@ dwarf2out_finish (const char *filename)
     output_indirect_strings ();
 }
 
+/* Perform any cleanups needed after the early debug generation pass
+   has run.  */
+
+static void
+dwarf2out_early_finish (void)
+{
+  /* Traverse the limbo die list, and add parent/child links.  The only
+     dies without parents that should be here are concrete instances of
+     inline functions, and the comp_unit_die.  We can ignore the comp_unit_die.
+     For concrete instances, we can get the parent die from the abstract
+     instance.
+
+     The point here is to flush out the limbo list so that it is empty
+     and we don't need to stream it for LTO.  */
+  limbo_die_node *node, *next_node;
+  for (node = limbo_die_list; node; node = next_node)
+    {
+      dw_die_ref die = node->die;
+      next_node = node->next;
+
+      if (die->die_parent == NULL)
+	{
+	  dw_die_ref origin = get_AT_ref (die, DW_AT_abstract_origin);
+
+	  if (origin && origin->die_parent)
+	    add_child_die (origin->die_parent, die);
+	  else if (is_cu_die (die))
+	    ;
+	  else if (seen_error ())
+	    /* It's OK to be confused by errors in the input.  */
+	    add_child_die (comp_unit_die (), die);
+	  else
+	    {
+	      /* In certain situations, the lexical block containing a
+		 nested function can be optimized away, which results
+		 in the nested function die being orphaned.  Likewise
+		 with the return type of that nested function.  Force
+		 this to be a child of the containing function.
+
+		 It may happen that even the containing function got fully
+		 inlined and optimized out.  In that case we are lost and
+		 assign the empty child.  This should not be big issue as
+		 the function is likely unreachable too.  */
+	      gcc_assert (node->created_for);
+
+	      if (DECL_P (node->created_for))
+		origin = get_context_die (DECL_CONTEXT (node->created_for));
+	      else if (TYPE_P (node->created_for))
+		origin = scope_die_for (node->created_for, comp_unit_die ());
+	      else
+		origin = comp_unit_die ();
+
+	      add_child_die (origin, die);
+	    }
+	}
+    }
+
+  limbo_die_list = NULL;
+}
+
 /* Reset all state within dwarf2out.c so that we can rerun the compiler
    within the same process.  For use by toplev::finalize.  */
 
diff --git a/gcc/sdbout.c b/gcc/sdbout.c
index d7b2d6b..43b8cf2 100644
--- a/gcc/sdbout.c
+++ b/gcc/sdbout.c
@@ -279,6 +279,7 @@ const struct gcc_debug_hooks sdb_debug_hooks =
 {
   sdbout_init,			         /* init */
   sdbout_finish,		         /* finish */
+  debug_nothing_void,			 /* early_finish */
   debug_nothing_void,			 /* assembly_start */
   debug_nothing_int_charstar,	         /* define */
   debug_nothing_int_charstar,	         /* undef */
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 42a2cdc..12fa509 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -586,6 +586,10 @@ compile_file (void)
   if (flag_syntax_only || flag_wpa)
     return;
 
+  /* Clean up anything that needs cleaning up after initial debug
+     generation.  */
+  (*debug_hooks->early_finish) ();
+
   ggc_protect_identifiers = false;
 
   /* Run the actual compilation process.  */
diff --git a/gcc/vmsdbgout.c b/gcc/vmsdbgout.c
index 5cb66bc..6da48eb 100644
--- a/gcc/vmsdbgout.c
+++ b/gcc/vmsdbgout.c
@@ -179,6 +179,7 @@ static void vmsdbgout_abstract_function (tree);
 const struct gcc_debug_hooks vmsdbg_debug_hooks
 = {vmsdbgout_init,
    vmsdbgout_finish,
+   debug_nothing_void,
    vmsdbgout_assembly_start,
    vmsdbgout_define,
    vmsdbgout_undef,

^ permalink raw reply	[flat|nested] 36+ messages in thread

end of thread, other threads:[~2015-02-16 20:46 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-16  3:11 [debug-early] C++ clones and limbo DIEs Aldy Hernandez
2015-01-16  4:30 ` Jason Merrill
2015-01-16 11:03   ` Richard Biener
2015-01-16 16:38     ` Jason Merrill
2015-01-16 18:09       ` Aldy Hernandez
2015-01-16 18:51       ` Richard Biener
2015-01-28 19:44     ` Aldy Hernandez
2015-01-16 17:54   ` Aldy Hernandez
2015-01-16 21:38     ` Jason Merrill
2015-01-23 19:53       ` Aldy Hernandez
2015-01-26  9:21         ` Richard Biener
2015-01-27 22:33         ` Jason Merrill
2015-01-28 19:24           ` Aldy Hernandez
2015-01-28 19:32             ` Aldy Hernandez
2015-01-28 19:47               ` Jason Merrill
2015-01-30 22:15                 ` Aldy Hernandez
2015-01-30 22:23                   ` Jason Merrill
2015-01-31  7:28                     ` Aldy Hernandez
2015-02-01  6:27                       ` Jason Merrill
2015-02-01  8:43                         ` Richard Biener
2015-02-02  3:15                         ` Aldy Hernandez
2015-02-02  4:16                           ` Jason Merrill
2015-02-05  0:27                             ` Aldy Hernandez
2015-02-05 20:11                               ` Jason Merrill
2015-02-06  1:15                                 ` Aldy Hernandez
2015-02-06 14:02                                   ` Jason Merrill
2015-02-06 16:42                                     ` Aldy Hernandez
2015-02-06 17:40                                       ` Jason Merrill
2015-02-06 17:47                                         ` Aldy Hernandez
2015-02-10 10:52                                       ` Richard Biener
2015-02-10 17:58                                         ` Jason Merrill
2015-02-12 18:04                                         ` Aldy Hernandez
2015-02-12 19:27                                           ` Jason Merrill
2015-02-16 20:46                                             ` Aldy Hernandez
2015-02-01  8:42                     ` Richard Biener
2015-02-02  1:48                       ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).