[PATCH] Fix dwarf2out related bootstrap failure on Solaris (PR debug/78191)

Jakub Jelinek jakub@redhat.com
Thu Nov 3 16:42:00 GMT 2016


Hi!

My recent optimize_abbrev_table optimization apparently broke Solaris
bootstrap.
The bug is specific I think just to -gdwarf-{2,3} -gno-strict-dwarf, where
DW_FORM_exprloc can't be used for location expressions and some location
expression contains DW_OP_GNU_{{const,regval,deref}_type,convert,reinterpret}
and there are at least 128 die abbreviations used by more than one DIE.
Because of the lack of DW_FORM_exprloc we need to decide on
DW_FORM_block{1,2,4} and size the location expression, for that we need to know
the DIE offsets of base offset DIEs that are referenced (earlier code
ensures such types appear very early in the CU, right after the
DW_TAG_compile_unit DIE) and for that their size and their abbreviation values
need to be constant, so the optimize_abbrev_table opts that reorder abbreviation
numbers by decreasing usage count or for -gdwarf-5 attempt to optimize implicit
constants can't be done for the CU and base types.
For -gdwarf-4 and above, we can emit DW_FORM_exprloc, so value_format doesn't
need to compute any sizes and thus calc_base_type_die_sizes shouldn't be
called.

Bootstrapped/regtested on x86_64-linux and i686-linux and Rainer has kindly
tested it on Solaris, ok for trunk?

2016-11-03  Jakub Jelinek  <jakub@redhat.com>

	* dwarf2out.c (size_of_discr_list): Fix typo in function comment.

	PR debug/78191
	* dwarf2out.c (abbrev_opt_base_type_end): New variable.
	(die_abbrev_cmp): Sort dies with die_abbrev smaller than
	abbrev_opt_base_type_end only by increasing die_abbrev, before
	any other dies.
	(optimize_abbrev_table): Don't change abbrev numbers of
	base types and CU or optimize implicit consts in them if
	calc_base_type_die_sizes has been called during build_abbrev_table.
	(calc_base_type_die_sizes): If abbrev_opt_start, set
	abbrev_opt_base_type_end to one plus largest base type's
	die_abbrev.

--- gcc/dwarf2out.c.jj	2016-11-03 08:47:59.000000000 +0100
+++ gcc/dwarf2out.c	2016-11-03 12:26:03.192459170 +0100
@@ -1909,7 +1909,7 @@ size_of_discr_value (dw_discr_value *dis
     return size_of_sleb128 (discr_value->v.sval);
 }
 
-/* Return the size of the value in a DW_discr_list attribute.  */
+/* Return the size of the value in a DW_AT_discr_list attribute.  */
 
 static int
 size_of_discr_list (dw_discr_list_ref discr_list)
@@ -8548,6 +8548,11 @@ optimize_external_refs (dw_die_ref die)
 /* First abbrev_id that can be optimized based on usage.  */
 static unsigned int abbrev_opt_start;
 
+/* Maximum abbrev_id of a base type plus one (we can't optimize DIEs with
+   abbrev_id smaller than this, because they must be already sized
+   during build_abbrev_table).  */
+static unsigned int abbrev_opt_base_type_end;
+
 /* Vector of usage counts during build_abbrev_table.  Indexed by
    abbrev_id - abbrev_opt_start.  */
 static vec<unsigned int> abbrev_usage_count;
@@ -8646,12 +8651,16 @@ die_abbrev_cmp (const void *p1, const vo
   gcc_checking_assert (die1->die_abbrev >= abbrev_opt_start);
   gcc_checking_assert (die2->die_abbrev >= abbrev_opt_start);
 
-  if (abbrev_usage_count[die1->die_abbrev - abbrev_opt_start]
-      > abbrev_usage_count[die2->die_abbrev - abbrev_opt_start])
-    return -1;
-  if (abbrev_usage_count[die1->die_abbrev - abbrev_opt_start]
-      < abbrev_usage_count[die2->die_abbrev - abbrev_opt_start])
-    return 1;
+  if (die1->die_abbrev >= abbrev_opt_base_type_end
+      && die2->die_abbrev >= abbrev_opt_base_type_end)
+    {
+      if (abbrev_usage_count[die1->die_abbrev - abbrev_opt_start]
+	  > abbrev_usage_count[die2->die_abbrev - abbrev_opt_start])
+	return -1;
+      if (abbrev_usage_count[die1->die_abbrev - abbrev_opt_start]
+	  < abbrev_usage_count[die2->die_abbrev - abbrev_opt_start])
+	return 1;
+    }
 
   /* Stabilize the sort.  */
   if (die1->die_abbrev < die2->die_abbrev)
@@ -8729,10 +8738,12 @@ optimize_abbrev_table (void)
       sorted_abbrev_dies.qsort (die_abbrev_cmp);
 
       unsigned int abbrev_id = abbrev_opt_start - 1;
-      unsigned int first_id = 0;
+      unsigned int first_id = ~0U;
       unsigned int last_abbrev_id = 0;
       unsigned int i;
       dw_die_ref die;
+      if (abbrev_opt_base_type_end > abbrev_opt_start)
+	abbrev_id = abbrev_opt_base_type_end - 1;
       /* Reassign abbreviation ids from abbrev_opt_start above, so that
 	 most commonly used abbreviations come first.  */
       FOR_EACH_VEC_ELT (sorted_abbrev_dies, i, die)
@@ -8740,10 +8751,15 @@ optimize_abbrev_table (void)
 	  dw_attr_node *a;
 	  unsigned ix;
 
+	  /* If calc_base_type_die_sizes has been called, the CU and
+	     base types after it can't be optimized, because we've already
+	     calculated their DIE offsets.  We've sorted them first.  */
+	  if (die->die_abbrev < abbrev_opt_base_type_end)
+	    continue;
 	  if (die->die_abbrev != last_abbrev_id)
 	    {
 	      last_abbrev_id = die->die_abbrev;
-	      if (dwarf_version >= 5 && i)
+	      if (dwarf_version >= 5 && first_id != ~0U)
 		optimize_implicit_const (first_id, i, implicit_consts);
 	      abbrev_id++;
 	      (*abbrev_die_table)[abbrev_id] = die;
@@ -8783,11 +8799,12 @@ optimize_abbrev_table (void)
 	  die->die_abbrev = abbrev_id;
 	}
       gcc_assert (abbrev_id == vec_safe_length (abbrev_die_table) - 1);
-      if (dwarf_version >= 5)
+      if (dwarf_version >= 5 && first_id != ~0U)
 	optimize_implicit_const (first_id, i, implicit_consts);
     }
 
   abbrev_opt_start = 0;
+  abbrev_opt_base_type_end = 0;
   abbrev_usage_count.release ();
   sorted_abbrev_dies.release ();
 }
@@ -9041,6 +9058,9 @@ calc_base_type_die_sizes (void)
 		  && base_type->die_abbrev);
       prev = base_type;
 #endif
+      if (abbrev_opt_start
+	  && base_type->die_abbrev >= abbrev_opt_base_type_end)
+	abbrev_opt_base_type_end = base_type->die_abbrev + 1;
       base_type->die_offset = die_offset;
       die_offset += size_of_die (base_type);
     }


	Jakub



More information about the Gcc-patches mailing list