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]

[PATCH] Fix ICEs with -fdebug-types-section (PR debug/78835)


Hi!

The following patch fixes ICE with -fdebug-types-section on the following
testcase.  We prune DIEs in the main CU for methods in a class that is
moved into .debug_types section, because we don't see any uses of those
in the debug info.  But those uses are only added later when adding
DW_TAG_call_site DIEs.  The patch just goes through all direct call edges
at the time of the early debug finish and marks the callees as used, so that
we do not prune them.  Of course, some edges might be still indirect and
turned into direct edges only later on, so as fallback the patch for now
just drops DW_AT_call_origin attributes on the floor if they would need to
point into a DIE that would need to be (re-)created inside of .debug_types
section (which is not valid and one can't refer to such DIEs anyway).
The right thing to do is create skeleton DIEs in the main CU as mentioned
in the PR, but that is lots of work.

The patch grows .debug_info on bootstrapped x86_64-linux cc1plus by 0.009%
and on libstdc++.so.6 by 0.29%, so I think that is still acceptable.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

I've also tried bootstrap with -fdebug-types-section on by default, but that
failed miserably during building of libstdc++, seems there are other bugs
unrelated to what this patch addresses (the ICE I've looked at has been
that std::string class had _Rep class inside of it and that contained some
method and during break_out_comdat_type GCC actually didn't keep that
method's DIE inside of the main CU, which is what it ought to be doing
(i.e. have std::string in one .debug_types unit (that DIE moved, all
children duplicated into the .debug_types unit), then std::string::_Rep
in another .debug_types unit (again, that DIE moved, all children
duplicated) and in the main CU std::string and std::string::_Rep be copies
(skeleton), and the rest kept and optionally pruned as unused later on.

I'll try to reduce a testcase for that and file another PR.

2017-01-18  Jakub Jelinek  <jakub@redhat.com>

	PR debug/78835
	* dwarf2out.c (prune_unused_types): Mark all functions with DIEs
	which have direct callers with -fvar-tracking-assignments enabled
	in the current TU.
	(resolve_addr): Avoid adding skeleton DIEs for DW_AT_call_origin
	inside of type units.

	* g++.dg/debug/dwarf2/pr78835.C: New test.

--- gcc/dwarf2out.c.jj	2017-01-16 22:31:10.779526222 +0100
+++ gcc/dwarf2out.c	2017-01-17 10:12:11.853440897 +0100
@@ -27768,6 +27768,25 @@ prune_unused_types (void)
   for (i = 0; base_types.iterate (i, &base_type); i++)
     prune_unused_types_mark (base_type, 1);
 
+  /* For -fvar-tracking-assignments, also set the mark on nodes that could be
+     referenced by DW_TAG_call_site DW_AT_call_origin (i.e. direct call
+     callees).  */
+  cgraph_node *cnode;
+  FOR_EACH_FUNCTION (cnode)
+    if (cnode->referred_to_p (false))
+      {
+	dw_die_ref die = lookup_decl_die (cnode->decl);
+	if (die == NULL || die->die_mark)
+	  continue;
+	for (cgraph_edge *e = cnode->callers; e; e = e->next_caller)
+	  if (e->caller != cnode
+	      && opt_for_fn (e->caller->decl, flag_var_tracking_assignments))
+	    {
+	      prune_unused_types_mark (die, 1);
+	      break;
+	    }
+      }
+
   if (debug_str_hash)
     debug_str_hash->empty ();
   if (skeleton_debug_str_hash)
@@ -28669,16 +28688,27 @@ resolve_addr (dw_die_ref die)
 		&& DECL_ABSTRACT_ORIGIN (tdecl) == NULL_TREE
 		&& (cdie = lookup_context_die (DECL_CONTEXT (tdecl))))
 	      {
-		/* Creating a full DIE for tdecl is overly expensive and
-		   at this point even wrong when in the LTO phase
-		   as it can end up generating new type DIEs we didn't
-		   output and thus optimize_external_refs will crash.  */
-		tdie = new_die (DW_TAG_subprogram, cdie, NULL_TREE);
-		add_AT_flag (tdie, DW_AT_external, 1);
-		add_AT_flag (tdie, DW_AT_declaration, 1);
-		add_linkage_attr (tdie, tdecl);
-		add_name_and_src_coords_attributes (tdie, tdecl);
-		equate_decl_number_to_die (tdecl, tdie);
+		dw_die_ref pdie = cdie;
+		/* Make sure we don't add these DIEs into type units.
+		   We could emit skeleton DIEs for context (namespaces,
+		   outer structs/classes) and a skeleton DIE for the
+		   innermost context with DW_AT_signature pointing to the
+		   type unit.  See PR78835.  */
+		while (pdie && pdie->die_tag != DW_TAG_type_unit)
+		  pdie = pdie->die_parent;
+		if (pdie == NULL)
+		  {
+		    /* Creating a full DIE for tdecl is overly expensive and
+		       at this point even wrong when in the LTO phase
+		       as it can end up generating new type DIEs we didn't
+		       output and thus optimize_external_refs will crash.  */
+		    tdie = new_die (DW_TAG_subprogram, cdie, NULL_TREE);
+		    add_AT_flag (tdie, DW_AT_external, 1);
+		    add_AT_flag (tdie, DW_AT_declaration, 1);
+		    add_linkage_attr (tdie, tdecl);
+		    add_name_and_src_coords_attributes (tdie, tdecl);
+		    equate_decl_number_to_die (tdecl, tdie);
+		  }
 	      }
 	    if (tdie)
 	      {
--- gcc/testsuite/g++.dg/debug/dwarf2/pr78835.C.jj	2017-01-17 10:16:34.301004406 +0100
+++ gcc/testsuite/g++.dg/debug/dwarf2/pr78835.C	2017-01-17 10:17:45.034078227 +0100
@@ -0,0 +1,11 @@
+/* PR debug/78835 */
+/* { dg-do compile } */
+/* { dg-options "-gdwarf-4 -O2 -fdebug-types-section" } */
+
+struct A { void foo (); };
+
+void
+bar (A &x)
+{
+  x.foo ();
+}

	Jakub


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