public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Reuse intermediate qualified DIEs even if they don't have corresponding tree type (PR debug/66668)
@ 2016-01-21 20:36 Jakub Jelinek
  2016-01-21 23:14 ` Jason Merrill
  0 siblings, 1 reply; 2+ messages in thread
From: Jakub Jelinek @ 2016-01-21 20:36 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches

Hi!

This patch attempts to fix a regression caused by early debug info, where
DIEs are created sooner and some intermediate qualified types might not
exist yet.

Rather than creating further variant tree types, this patch arranges for the
qualified DIEs (DW_TAG_{atomic,restrict,volatile,const}_type with just
DW_AT_type) to be emitted next to the unqualified type's DIE, and as there
can be only a few (for ordered at most 10, for unordered at most 15), it is
not expensive to look whether we already have the right one around.

Furthermore, for -fdebug-types-section it ignores
get_nearest_type_subqualifiers result and uses unqualified type if
using the partially qualified one would lead to non-canonical order of the
qualifiers.

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

2016-01-21  Jakub Jelinek  <jakub@redhat.com>

	PR debug/66668
	* dwarf2out.c (add_child_die_after): New function.
	(dwarf_qual_info_t): New type.
	(dwarf_qual_info): New variable.
	(qualified_die_p): New function.
	(modified_type_die): For -fdebug-types-section, ensure
	canonical order of qualifiers.  Put qualified DIEs adjacent
	to the corresponding non-qualified type DIE and search there
	for existing qualified DIEs.

--- gcc/dwarf2out.c.jj	2016-01-21 00:41:46.000000000 +0100
+++ gcc/dwarf2out.c	2016-01-21 12:35:37.229374047 +0100
@@ -4970,6 +4970,25 @@ add_child_die (dw_die_ref die, dw_die_re
   die->die_child = child_die;
 }
 
+/* Like add_child_die, but put CHILD_DIE after AFTER_DIE.  */
+
+static void
+add_child_die_after (dw_die_ref die, dw_die_ref child_die,
+		     dw_die_ref after_die)
+{
+  gcc_assert (die
+	      && child_die
+	      && after_die
+	      && die->die_child
+	      && die != child_die);
+
+  child_die->die_parent = die;
+  child_die->die_sib = after_die->die_sib;
+  after_die->die_sib = child_die;
+  if (die->die_child == after_die)
+    die->die_child = child_die;
+}
+
 /* Unassociate CHILD from its parent, and make its parent be
    NEW_PARENT.  */
 
@@ -11149,6 +11168,45 @@ get_nearest_type_subqualifiers (tree typ
   return best_qual;
 }
 
+struct dwarf_qual_info_t { int q; enum dwarf_tag t; };
+static const dwarf_qual_info_t dwarf_qual_info[] =
+{
+  { TYPE_QUAL_ATOMIC, DW_TAG_atomic_type },
+  { TYPE_QUAL_RESTRICT, DW_TAG_restrict_type },
+  { TYPE_QUAL_VOLATILE, DW_TAG_volatile_type },
+  { TYPE_QUAL_CONST, DW_TAG_const_type },
+};
+static const unsigned int dwarf_qual_info_size
+  = sizeof (dwarf_qual_info) / sizeof (dwarf_qual_info[0]);
+
+/* If DIE is a qualified DIE of some base DIE with the same parent,
+   return the base DIE, otherwise return NULL.  Set MASK to the
+   qualifiers added compared to the returned DIE.  */
+
+static dw_die_ref
+qualified_die_p (dw_die_ref die, int *mask, unsigned int depth)
+{
+  unsigned int i;
+  for (i = 0; i < dwarf_qual_info_size; i++)
+    if (die->die_tag == dwarf_qual_info[i].t)
+      break;
+  if (i == dwarf_qual_info_size)
+    return NULL;
+  if (vec_safe_length (die->die_attr) != 1)
+    return NULL;
+  dw_die_ref type = get_AT_ref (die, DW_AT_type);
+  if (type == NULL || type->die_parent != die->die_parent)
+    return NULL;
+  *mask |= dwarf_qual_info[i].q;
+  if (depth)
+    {
+      dw_die_ref ret = qualified_die_p (type, mask, depth - 1);
+      if (ret)
+	return ret;
+    }
+  return type;
+}
+
 /* Given a pointer to an arbitrary ..._TYPE tree node, return a debugging
    entry that chains the modifiers specified by CV_QUALS in front of the
    given type.  REVERSE is true if the type is to be interpreted in the
@@ -11255,31 +11313,97 @@ modified_type_die (tree type, int cv_qua
 
   if (cv_quals)
     {
-      struct qual_info { int q; enum dwarf_tag t; };
-      static const struct qual_info qual_info[] =
-	{
-	  { TYPE_QUAL_ATOMIC, DW_TAG_atomic_type },
-	  { TYPE_QUAL_RESTRICT, DW_TAG_restrict_type },
-	  { TYPE_QUAL_VOLATILE, DW_TAG_volatile_type },
-	  { TYPE_QUAL_CONST, DW_TAG_const_type },
-	};
-      int sub_quals;
+      int sub_quals = 0, first_quals = 0;
       unsigned i;
+      dw_die_ref first = NULL, last = NULL;
 
       /* Determine a lesser qualified type that most closely matches
 	 this one.  Then generate DW_TAG_* entries for the remaining
 	 qualifiers.  */
       sub_quals = get_nearest_type_subqualifiers (type, cv_quals,
 						  cv_qual_mask);
+      if (sub_quals && use_debug_types)
+	{
+	  bool needed = false;
+	  /* If emitting type units, make sure the order of qualifiers
+	     is canonical.  Thus, start from unqualified type if
+	     an earlier qualifier is missing in sub_quals, but some later
+	     one is present there.  */
+	  for (i = 0; i < dwarf_qual_info_size; i++)
+	    if (dwarf_qual_info[i].q & cv_quals & ~sub_quals)
+	      needed = true;
+	    else if (needed && (dwarf_qual_info[i].q & cv_quals))
+	      {
+		sub_quals = 0;
+		break;
+	      }
+	}
       mod_type_die = modified_type_die (type, sub_quals, reverse, context_die);
+      if (mod_scope && mod_type_die && mod_type_die->die_parent == mod_scope)
+	{
+	  /* As not all intermediate qualified DIEs have corresponding
+	     tree types, ensure that qualified DIEs in the same scope
+	     as their DW_AT_type are emitted after their DW_AT_type,
+	     only with other qualified DIEs for the same type possibly
+	     in between them.  Determine the range of such qualified
+	     DIEs now (first being the base type, last being corresponding
+	     last qualified DIE for it).  */
+	  unsigned int count = 0;
+	  first = qualified_die_p (mod_type_die, &first_quals,
+				   dwarf_qual_info_size);
+	  if (first == NULL)
+	    first = mod_type_die;
+	  gcc_assert ((first_quals & ~sub_quals) == 0);
+	  for (count = 0, last = first;
+	       count < (1U << dwarf_qual_info_size);
+	       count++, last = last->die_sib)
+	    {
+	      int quals = 0;
+	      if (last == mod_scope->die_child)
+		break;
+	      if (qualified_die_p (last->die_sib, &quals, dwarf_qual_info_size)
+		  != first)
+		break;
+	    }
+	}
 
-      for (i = 0; i < sizeof (qual_info) / sizeof (qual_info[0]); i++)
-	if (qual_info[i].q & cv_quals & ~sub_quals)
+      for (i = 0; i < dwarf_qual_info_size; i++)
+	if (dwarf_qual_info[i].q & cv_quals & ~sub_quals)
 	  {
-	    dw_die_ref d = new_die (qual_info[i].t, mod_scope, type);
+	    dw_die_ref d;
+	    if (first && first != last)
+	      {
+		for (d = first->die_sib; ; d = d->die_sib)
+		  {
+		    int quals = 0;
+		    qualified_die_p (d, &quals, dwarf_qual_info_size);
+		    if (quals == (first_quals | dwarf_qual_info[i].q))
+		      break;
+		    if (d == last)
+		      {
+			d = NULL;
+			break;
+		      }
+		  }
+		if (d)
+		  {
+		    mod_type_die = d;
+		    continue;
+		  }
+	      }
+	    if (first)
+	      {
+		d = ggc_cleared_alloc<die_node> ();
+		d->die_tag = dwarf_qual_info[i].t;
+		add_child_die_after (mod_scope, d, last);
+		last = d;
+	      }
+	    else
+	      d = new_die (dwarf_qual_info[i].t, mod_scope, type);
 	    if (mod_type_die)
 	      add_AT_die_ref (d, DW_AT_type, mod_type_die);
 	    mod_type_die = d;
+	    first_quals |= dwarf_qual_info[i].q;
 	  }
     }
   else if (code == POINTER_TYPE || code == REFERENCE_TYPE)

	Jakub

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

* Re: [PATCH] Reuse intermediate qualified DIEs even if they don't have corresponding tree type (PR debug/66668)
  2016-01-21 20:36 [PATCH] Reuse intermediate qualified DIEs even if they don't have corresponding tree type (PR debug/66668) Jakub Jelinek
@ 2016-01-21 23:14 ` Jason Merrill
  0 siblings, 0 replies; 2+ messages in thread
From: Jason Merrill @ 2016-01-21 23:14 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches

On 01/21/2016 03:35 PM, Jakub Jelinek wrote:
> +static const dwarf_qual_info_t dwarf_qual_info[] =
> +{
> +  { TYPE_QUAL_ATOMIC, DW_TAG_atomic_type },
> +  { TYPE_QUAL_RESTRICT, DW_TAG_restrict_type },
> +  { TYPE_QUAL_VOLATILE, DW_TAG_volatile_type },
> +  { TYPE_QUAL_CONST, DW_TAG_const_type },
> +};

Let's go ahead and move const to the top of this array; it should be 
much more common than the others.  OK with that change.

Jason

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

end of thread, other threads:[~2016-01-21 23:14 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-21 20:36 [PATCH] Reuse intermediate qualified DIEs even if they don't have corresponding tree type (PR debug/66668) Jakub Jelinek
2016-01-21 23:14 ` 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).