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]

[dwarf4][patch] Some bug fixes and updates for revised draft of DWARF-4 proposal


I've committed this patch to update the -gdwarf-4 type signature
algorithm to more closely align it with the current revision of the
DWARF-4 proposal.

The patch also fixes a bug where a nested type was pulled out into its
own type unit without leaving a declaration of that type behind (where
gdb could find it), and it adds a DW_AT_stmt_list reference from each
new type unit DIE to the main compunit's line table so that
DW_AT_decl_file has meaning inside a type unit.

-cary


	* dwarf2out.c (CHECKSUM_STRING): Redefine for DWARF-4 to include
	trailing NULL byte.
	(CHECKSUM_SLEB128, CHECKSUM_ULEB128): New macros.
	(checksum_sleb128, checksum_uleb128): New functions.
	(loc_checksum_ordered): New function.
	(attr_checksum_ordered): Use CHECKSUM_SLEB128 and CHECKSUM_ULEB128.
	(struct checksum_attributes): New structure.
	(collect_checksum_attributes): New function.
	(die_checksum_ordered): Call collect_checksum_attributes to get
	attributes of declaration if necessary. Add some additional
	attributes to the checksum. Update checksum algorithm to
	match draft DWARF-4 specification.
	(generate_type_signature): Include trailing NULL byte in ODR
	signature.
	(generate_skeleton): Leave a declaration when moving a nested
	type into its own type unit.
	(prune_unused_types_mark): Mark children of type entries when
	doing DWARF-4 comdat types.
	(dwarf2out_finish): Add a pointer to the line table from
	type unit entries so DW_AT_decl_file has meaning.


Index: dwarf2out.c
===================================================================
--- dwarf2out.c	(revision 144680)
+++ dwarf2out.c	(working copy)
@@ -5077,7 +5077,12 @@ static dw_die_ref pop_compile_unit (dw_d
 static void loc_checksum (dw_loc_descr_ref, struct md5_ctx *);
 static void attr_checksum (dw_attr_ref, struct md5_ctx *, int *);
 static void die_checksum (dw_die_ref, struct md5_ctx *, int *);
+static void checksum_sleb128 (HOST_WIDE_INT, struct md5_ctx *);
+static void checksum_uleb128 (unsigned HOST_WIDE_INT, struct md5_ctx *);
+static void loc_checksum_ordered (dw_loc_descr_ref, struct md5_ctx *);
 static void attr_checksum_ordered (dw_attr_ref, struct md5_ctx *, int *);
+struct checksum_attributes;
+static void collect_checksum_attributes (struct checksum_attributes
*, dw_die_ref);
 static void die_checksum_ordered (dw_die_ref, struct md5_ctx *, int *);
 static void checksum_die_context (dw_die_ref, struct md5_ctx *);
 static void generate_type_signature (dw_die_ref, comdat_type_node *);
@@ -7097,6 +7102,95 @@ die_checksum (dw_die_ref die, struct md5
   FOR_EACH_CHILD (die, c, die_checksum (c, ctx, mark));
 }

+#undef CHECKSUM
+#undef CHECKSUM_STRING
+
+/* For DWARF-4 types, include the trailing NULL when checksumming strings.  */
+#define CHECKSUM(FOO) md5_process_bytes (&(FOO), sizeof (FOO), ctx)
+#define CHECKSUM_STRING(FOO) md5_process_bytes ((FOO), strlen (FOO) + 1, ctx)
+#define CHECKSUM_SLEB128(FOO) checksum_sleb128 ((FOO), ctx)
+#define CHECKSUM_ULEB128(FOO) checksum_uleb128 ((FOO), ctx)
+#define CHECKSUM_ATTR(FOO) if (FOO) attr_checksum_ordered (FOO, ctx, mark)
+
+/* Calculate the checksum of a number in signed LEB128 format.  */
+
+static void
+checksum_sleb128 (HOST_WIDE_INT value, struct md5_ctx *ctx)
+{
+  unsigned char byte;
+  bool more;
+
+  while (1)
+    {
+      byte = (value & 0x7f);
+      value >>= 7;
+      more = !((value == 0 && (byte & 0x40) == 0)
+		|| (value == -1 && (byte & 0x40) != 0));
+      if (more)
+	byte |= 0x80;
+      CHECKSUM (byte);
+      if (!more)
+	break;
+    }
+}
+
+/* Calculate the checksum of a number in unsigned LEB128 format.  */
+
+static void
+checksum_uleb128 (unsigned HOST_WIDE_INT value, struct md5_ctx *ctx)
+{
+  while (1)
+    {
+      unsigned char byte = (value & 0x7f);
+      value >>= 7;
+      if (value != 0)
+	/* More bytes to follow.  */
+	byte |= 0x80;
+      CHECKSUM (byte);
+      if (value == 0)
+	break;
+    }
+}
+
+/* Checksum the context of the DIE.  This adds the names of any
+   surrounding namespaces or structures to the checksum.  */
+
+static void
+checksum_die_context (dw_die_ref die, struct md5_ctx *ctx)
+{
+  const char *name;
+  dw_die_ref spec;
+  int tag = die->die_tag;
+
+  if (tag != DW_TAG_namespace
+      && tag != DW_TAG_structure_type
+      && tag != DW_TAG_class_type)
+    return;
+
+  name = get_AT_string (die, DW_AT_name);
+
+  spec = get_AT_ref (die, DW_AT_specification);
+  if (spec != NULL)
+    die = spec;
+
+  if (die->die_parent != NULL)
+    checksum_die_context (die->die_parent, ctx);
+
+  CHECKSUM_ULEB128 (tag);
+  if (name != NULL)
+    CHECKSUM_STRING (name);
+}
+
+/* Calculate the checksum of a location expression.  */
+
+static inline void
+loc_checksum_ordered (dw_loc_descr_ref loc, struct md5_ctx *ctx)
+{
+  CHECKSUM (loc->dw_loc_opc);
+  CHECKSUM (loc->dw_loc_oprnd1);
+  CHECKSUM (loc->dw_loc_oprnd2);
+}
+
 /* Calculate the checksum of an attribute.  */

 static void
@@ -7105,20 +7199,15 @@ attr_checksum_ordered (dw_attr_ref at, s
   dw_loc_descr_ref loc;
   rtx r;

-  CHECKSUM (at->dw_attr);
-
-  /* We don't care that this was compiled with a different compiler
-     snapshot; if the output is the same, that's what matters.  */
-  if (at->dw_attr == DW_AT_producer)
-    return;
+  CHECKSUM_ULEB128 (at->dw_attr);

   switch (AT_class (at))
     {
     case dw_val_class_const:
-      CHECKSUM (at->dw_attr_val.v.val_int);
+      CHECKSUM_SLEB128 (at->dw_attr_val.v.val_int);
       break;
     case dw_val_class_unsigned_const:
-      CHECKSUM (at->dw_attr_val.v.val_unsigned);
+      CHECKSUM_ULEB128 (at->dw_attr_val.v.val_unsigned);
       break;
     case dw_val_class_long_long:
       CHECKSUM (at->dw_attr_val.v.val_long_long);
@@ -7140,12 +7229,12 @@ attr_checksum_ordered (dw_attr_ref at, s
       break;

     case dw_val_class_offset:
-      CHECKSUM (at->dw_attr_val.v.val_offset);
+      CHECKSUM_ULEB128 (at->dw_attr_val.v.val_offset);
       break;

     case dw_val_class_loc:
       for (loc = AT_loc (at); loc; loc = loc->dw_loc_next)
-	loc_checksum (loc, ctx);
+	loc_checksum_ordered (loc, ctx);
       break;

     case dw_val_class_die_ref:
@@ -7170,324 +7259,394 @@ attr_checksum_ordered (dw_attr_ref at, s
     }
 }

-#define CHECKSUM_ATTR(FOO) if (FOO) attr_checksum_ordered (FOO, ctx, mark)
+struct checksum_attributes
+{
+  dw_attr_ref at_name;
+  dw_attr_ref at_type;
+  dw_attr_ref at_friend;
+  dw_attr_ref at_accessibility;
+  dw_attr_ref at_address_class;
+  dw_attr_ref at_allocated;
+  dw_attr_ref at_artificial;
+  dw_attr_ref at_associated;
+  dw_attr_ref at_binary_scale;
+  dw_attr_ref at_bit_offset;
+  dw_attr_ref at_bit_size;
+  dw_attr_ref at_bit_stride;
+  dw_attr_ref at_byte_size;
+  dw_attr_ref at_byte_stride;
+  dw_attr_ref at_const_value;
+  dw_attr_ref at_containing_type;
+  dw_attr_ref at_count;
+  dw_attr_ref at_data_location;
+  dw_attr_ref at_data_member_location;
+  dw_attr_ref at_decimal_scale;
+  dw_attr_ref at_decimal_sign;
+  dw_attr_ref at_default_value;
+  dw_attr_ref at_digit_count;
+  dw_attr_ref at_discr;
+  dw_attr_ref at_discr_list;
+  dw_attr_ref at_discr_value;
+  dw_attr_ref at_encoding;
+  dw_attr_ref at_endianity;
+  dw_attr_ref at_explicit;
+  dw_attr_ref at_is_optional;
+  dw_attr_ref at_location;
+  dw_attr_ref at_lower_bound;
+  dw_attr_ref at_mutable;
+  dw_attr_ref at_ordering;
+  dw_attr_ref at_picture_string;
+  dw_attr_ref at_prototyped;
+  dw_attr_ref at_small;
+  dw_attr_ref at_segment;
+  dw_attr_ref at_string_length;
+  dw_attr_ref at_threads_scaled;
+  dw_attr_ref at_upper_bound;
+  dw_attr_ref at_use_location;
+  dw_attr_ref at_use_UTF8;
+  dw_attr_ref at_variable_parameter;
+  dw_attr_ref at_virtuality;
+  dw_attr_ref at_visibility;
+  dw_attr_ref at_vtable_elem_location;
+};

-/* Calculate the checksum of a DIE, using an ordered subset of attributes.  */
+/* Collect the attributes that we will want to use for the checksum.  */

 static void
-die_checksum_ordered (dw_die_ref die, struct md5_ctx *ctx, int *mark)
+collect_checksum_attributes (struct checksum_attributes *attrs, dw_die_ref die)
 {
-  dw_die_ref c;
   dw_attr_ref a;
-  dw_attr_ref at_name = NULL;
-  dw_attr_ref at_accessibility = NULL;
-  dw_attr_ref at_address_class = NULL;
-  dw_attr_ref at_allocated = NULL;
-  dw_attr_ref at_artificial = NULL;
-  dw_attr_ref at_associated = NULL;
-  dw_attr_ref at_binary_scale = NULL;
-  dw_attr_ref at_bit_offset = NULL;
-  dw_attr_ref at_bit_size = NULL;
-  dw_attr_ref at_bit_stride = NULL;
-  dw_attr_ref at_byte_size = NULL;
-  dw_attr_ref at_byte_stride = NULL;
-  dw_attr_ref at_const_value = NULL;
-  dw_attr_ref at_count = NULL;
-  dw_attr_ref at_data_location = NULL;
-  dw_attr_ref at_data_member_location = NULL;
-  dw_attr_ref at_decimal_scale = NULL;
-  dw_attr_ref at_decimal_sign = NULL;
-  dw_attr_ref at_default_value = NULL;
-  dw_attr_ref at_digit_count = NULL;
-  dw_attr_ref at_discr = NULL;
-  dw_attr_ref at_discr_list = NULL;
-  dw_attr_ref at_discr_value = NULL;
-  dw_attr_ref at_encoding = NULL;
-  dw_attr_ref at_endianity = NULL;
-  dw_attr_ref at_is_optional = NULL;
-  dw_attr_ref at_location = NULL;
-  dw_attr_ref at_lower_bound = NULL;
-  dw_attr_ref at_ordering = NULL;
-  dw_attr_ref at_picture_string = NULL;
-  dw_attr_ref at_prototyped = NULL;
-  dw_attr_ref at_small = NULL;
-  dw_attr_ref at_segment = NULL;
-  dw_attr_ref at_start_scope = NULL;
-  dw_attr_ref at_string_length = NULL;
-  dw_attr_ref at_threads_scaled = NULL;
-  dw_attr_ref at_upper_bound = NULL;
-  dw_attr_ref at_use_location = NULL;
-  dw_attr_ref at_variable_parameter = NULL;
-  dw_attr_ref at_visibility = NULL;
-  dw_attr_ref at_type = NULL;
-  dw_attr_ref at_friend = NULL;
   unsigned ix;

-  /* To avoid infinite recursion.  */
-  if (die->die_mark)
-    {
-      CHECKSUM (die->die_mark);
-      return;
-    }
-  die->die_mark = ++(*mark);
-
-  CHECKSUM (die->die_tag);
-
   for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
     {
       switch (a->dw_attr)
         {
         case DW_AT_name:
-          at_name = a;
+          attrs->at_name = a;
+          break;
+        case DW_AT_type:
+          attrs->at_type = a;
+          break;
+        case DW_AT_friend:
+          attrs->at_friend = a;
           break;
         case DW_AT_accessibility:
-          at_accessibility = a;
+          attrs->at_accessibility = a;
           break;
         case DW_AT_address_class:
-          at_address_class = a;
+          attrs->at_address_class = a;
           break;
         case DW_AT_allocated:
-          at_allocated = a;
+          attrs->at_allocated = a;
           break;
         case DW_AT_artificial:
-          at_artificial = a;
+          attrs->at_artificial = a;
           break;
         case DW_AT_associated:
-          at_associated = a;
+          attrs->at_associated = a;
           break;
         case DW_AT_binary_scale:
-          at_binary_scale = a;
+          attrs->at_binary_scale = a;
           break;
         case DW_AT_bit_offset:
-          at_bit_offset = a;
+          attrs->at_bit_offset = a;
           break;
         case DW_AT_bit_size:
-          at_bit_size = a;
+          attrs->at_bit_size = a;
           break;
         case DW_AT_bit_stride:
-          at_bit_stride = a;
+          attrs->at_bit_stride = a;
           break;
         case DW_AT_byte_size:
-          at_byte_size = a;
+          attrs->at_byte_size = a;
           break;
         case DW_AT_byte_stride:
-          at_byte_stride = a;
+          attrs->at_byte_stride = a;
           break;
         case DW_AT_const_value:
-          at_const_value = a;
+          attrs->at_const_value = a;
+          break;
+        case DW_AT_containing_type:
+          attrs->at_containing_type = a;
           break;
         case DW_AT_count:
-          at_count = a;
+          attrs->at_count = a;
           break;
         case DW_AT_data_location:
-          at_data_location = a;
+          attrs->at_data_location = a;
           break;
         case DW_AT_data_member_location:
-          at_data_member_location = a;
+          attrs->at_data_member_location = a;
           break;
         case DW_AT_decimal_scale:
-          at_decimal_scale = a;
+          attrs->at_decimal_scale = a;
           break;
         case DW_AT_decimal_sign:
-          at_decimal_sign = a;
+          attrs->at_decimal_sign = a;
           break;
         case DW_AT_default_value:
-          at_default_value = a;
+          attrs->at_default_value = a;
           break;
         case DW_AT_digit_count:
-          at_digit_count = a;
+          attrs->at_digit_count = a;
           break;
         case DW_AT_discr:
-          at_discr = a;
+          attrs->at_discr = a;
           break;
         case DW_AT_discr_list:
-          at_discr_list = a;
+          attrs->at_discr_list = a;
           break;
         case DW_AT_discr_value:
-          at_discr_value = a;
+          attrs->at_discr_value = a;
           break;
         case DW_AT_encoding:
-          at_encoding = a;
+          attrs->at_encoding = a;
           break;
         case DW_AT_endianity:
-          at_endianity = a;
+          attrs->at_endianity = a;
+          break;
+        case DW_AT_explicit:
+          attrs->at_explicit = a;
           break;
         case DW_AT_is_optional:
-          at_is_optional = a;
+          attrs->at_is_optional = a;
           break;
         case DW_AT_location:
-          at_location = a;
+          attrs->at_location = a;
           break;
         case DW_AT_lower_bound:
-          at_lower_bound = a;
+          attrs->at_lower_bound = a;
+          break;
+        case DW_AT_mutable:
+          attrs->at_mutable = a;
           break;
         case DW_AT_ordering:
-          at_ordering = a;
+          attrs->at_ordering = a;
           break;
         case DW_AT_picture_string:
-          at_picture_string = a;
+          attrs->at_picture_string = a;
           break;
         case DW_AT_prototyped:
-          at_prototyped = a;
+          attrs->at_prototyped = a;
           break;
         case DW_AT_small:
-          at_small = a;
+          attrs->at_small = a;
           break;
         case DW_AT_segment:
-          at_segment = a;
-          break;
-        case DW_AT_start_scope:
-          at_start_scope = a;
+          attrs->at_segment = a;
           break;
         case DW_AT_string_length:
-          at_string_length = a;
+          attrs->at_string_length = a;
           break;
         case DW_AT_threads_scaled:
-          at_threads_scaled = a;
+          attrs->at_threads_scaled = a;
           break;
         case DW_AT_upper_bound:
-          at_upper_bound = a;
+          attrs->at_upper_bound = a;
           break;
         case DW_AT_use_location:
-          at_use_location = a;
+          attrs->at_use_location = a;
+          break;
+        case DW_AT_use_UTF8:
+          attrs->at_use_UTF8 = a;
           break;
         case DW_AT_variable_parameter:
-          at_variable_parameter = a;
+          attrs->at_variable_parameter = a;
           break;
-        case DW_AT_visibility:
-          at_visibility = a;
+        case DW_AT_virtuality:
+          attrs->at_virtuality = a;
           break;
-        case DW_AT_type:
-          at_type = a;
+        case DW_AT_visibility:
+          attrs->at_visibility = a;
           break;
-        case DW_AT_friend:
-          at_friend = a;
+        case DW_AT_vtable_elem_location:
+          attrs->at_vtable_elem_location = a;
           break;
         default:
           break;
         }
     }
+}

-  CHECKSUM_ATTR (at_name);
-  CHECKSUM_ATTR (at_accessibility);
-  CHECKSUM_ATTR (at_address_class);
-  CHECKSUM_ATTR (at_allocated);
-  CHECKSUM_ATTR (at_artificial);
-  CHECKSUM_ATTR (at_associated);
-  CHECKSUM_ATTR (at_binary_scale);
-  CHECKSUM_ATTR (at_bit_offset);
-  CHECKSUM_ATTR (at_bit_size);
-  CHECKSUM_ATTR (at_bit_stride);
-  CHECKSUM_ATTR (at_byte_size);
-  CHECKSUM_ATTR (at_byte_stride);
-  CHECKSUM_ATTR (at_const_value);
-  CHECKSUM_ATTR (at_count);
-  CHECKSUM_ATTR (at_data_location);
-  CHECKSUM_ATTR (at_data_member_location);
-  CHECKSUM_ATTR (at_decimal_scale);
-  CHECKSUM_ATTR (at_decimal_sign);
-  CHECKSUM_ATTR (at_default_value);
-  CHECKSUM_ATTR (at_digit_count);
-  CHECKSUM_ATTR (at_discr);
-  CHECKSUM_ATTR (at_discr_list);
-  CHECKSUM_ATTR (at_discr_value);
-  CHECKSUM_ATTR (at_encoding);
-  CHECKSUM_ATTR (at_endianity);
-  CHECKSUM_ATTR (at_is_optional);
-  CHECKSUM_ATTR (at_location);
-  CHECKSUM_ATTR (at_lower_bound);
-  CHECKSUM_ATTR (at_ordering);
-  CHECKSUM_ATTR (at_picture_string);
-  CHECKSUM_ATTR (at_prototyped);
-  CHECKSUM_ATTR (at_small);
-  CHECKSUM_ATTR (at_segment);
-  CHECKSUM_ATTR (at_start_scope);
-  CHECKSUM_ATTR (at_string_length);
-  CHECKSUM_ATTR (at_threads_scaled);
-  CHECKSUM_ATTR (at_upper_bound);
-  CHECKSUM_ATTR (at_use_location);
-  CHECKSUM_ATTR (at_variable_parameter);
-  CHECKSUM_ATTR (at_visibility);
+/* Calculate the checksum of a DIE, using an ordered subset of attributes.  */
+
+static void
+die_checksum_ordered (dw_die_ref die, struct md5_ctx *ctx, int *mark)
+{
+  dw_die_ref c;
+  dw_die_ref decl;
+  struct checksum_attributes attrs;
+
+  /* To avoid infinite recursion.  */
+  if (die->die_mark)
+    {
+      CHECKSUM_ULEB128 (die->die_mark);
+      return;
+    }
+  die->die_mark = ++(*mark);
+
+  memset (&attrs, 0, sizeof (attrs));
+
+  decl = get_AT_ref (die, DW_AT_specification);
+  if (decl != NULL)
+    collect_checksum_attributes (&attrs, decl);
+  collect_checksum_attributes (&attrs, die);
+
+  CHECKSUM_ULEB128 (die->die_tag);
+  CHECKSUM_ATTR (attrs.at_name);
+  CHECKSUM_ATTR (attrs.at_accessibility);
+  CHECKSUM_ATTR (attrs.at_address_class);
+  CHECKSUM_ATTR (attrs.at_allocated);
+  CHECKSUM_ATTR (attrs.at_artificial);
+  CHECKSUM_ATTR (attrs.at_associated);
+  CHECKSUM_ATTR (attrs.at_binary_scale);
+  CHECKSUM_ATTR (attrs.at_bit_offset);
+  CHECKSUM_ATTR (attrs.at_bit_size);
+  CHECKSUM_ATTR (attrs.at_bit_stride);
+  CHECKSUM_ATTR (attrs.at_byte_size);
+  CHECKSUM_ATTR (attrs.at_byte_stride);
+  CHECKSUM_ATTR (attrs.at_const_value);
+  CHECKSUM_ATTR (attrs.at_containing_type);
+  CHECKSUM_ATTR (attrs.at_count);
+  CHECKSUM_ATTR (attrs.at_data_location);
+  CHECKSUM_ATTR (attrs.at_data_member_location);
+  CHECKSUM_ATTR (attrs.at_decimal_scale);
+  CHECKSUM_ATTR (attrs.at_decimal_sign);
+  CHECKSUM_ATTR (attrs.at_default_value);
+  CHECKSUM_ATTR (attrs.at_digit_count);
+  CHECKSUM_ATTR (attrs.at_discr);
+  CHECKSUM_ATTR (attrs.at_discr_list);
+  CHECKSUM_ATTR (attrs.at_discr_value);
+  CHECKSUM_ATTR (attrs.at_encoding);
+  CHECKSUM_ATTR (attrs.at_endianity);
+  CHECKSUM_ATTR (attrs.at_explicit);
+  CHECKSUM_ATTR (attrs.at_is_optional);
+  CHECKSUM_ATTR (attrs.at_location);
+  CHECKSUM_ATTR (attrs.at_lower_bound);
+  CHECKSUM_ATTR (attrs.at_mutable);
+  CHECKSUM_ATTR (attrs.at_ordering);
+  CHECKSUM_ATTR (attrs.at_picture_string);
+  CHECKSUM_ATTR (attrs.at_prototyped);
+  CHECKSUM_ATTR (attrs.at_small);
+  CHECKSUM_ATTR (attrs.at_segment);
+  CHECKSUM_ATTR (attrs.at_string_length);
+  CHECKSUM_ATTR (attrs.at_threads_scaled);
+  CHECKSUM_ATTR (attrs.at_upper_bound);
+  CHECKSUM_ATTR (attrs.at_use_location);
+  CHECKSUM_ATTR (attrs.at_use_UTF8);
+  CHECKSUM_ATTR (attrs.at_variable_parameter);
+  CHECKSUM_ATTR (attrs.at_virtuality);
+  CHECKSUM_ATTR (attrs.at_visibility);
+  CHECKSUM_ATTR (attrs.at_vtable_elem_location);

   if (die->die_tag == DW_TAG_pointer_type
-      || die->die_tag == DW_TAG_reference_type)
+      || die->die_tag == DW_TAG_reference_type
+      || die->die_tag == DW_TAG_ptr_to_member_type)
     {
       /* For pointer and reference types, we checksum only the name of
          the target type (if there is a name).  This allows the checksum
          to remain the same whether the target type is complete or not.  */
-      if (at_type != NULL && AT_class (at_type) == dw_val_class_die_ref)
+      if (attrs.at_type != NULL
+          && AT_class (attrs.at_type) == dw_val_class_die_ref)
         {
-          dw_die_ref type_die = AT_ref (at_type);
+          dw_die_ref type_die = AT_ref (attrs.at_type);
           dw_attr_ref name_attr = get_AT (type_die, DW_AT_name);
+          dw_die_ref decl = get_AT_ref (type_die, DW_AT_specification);
+          if (decl == NULL)
+            decl = type_die;
           if (name_attr != NULL)
             {
-              CHECKSUM_ATTR (name_attr);
+              CHECKSUM_ULEB128 ('N');
+              CHECKSUM_ULEB128 (DW_AT_type);
+              if (decl->die_parent != NULL)
+                checksum_die_context (decl->die_parent, ctx);
+              CHECKSUM_STRING (AT_string (name_attr));
             }
           else
             {
-              CHECKSUM_ATTR (at_type);
+              if (type_die->die_mark)
+                {
+                  CHECKSUM_ULEB128 ('R');
+                  CHECKSUM_ULEB128 (type_die->die_mark);
+                }
+              else
+                {
+                  CHECKSUM_ULEB128 ('T');
+                  if (decl->die_parent != NULL)
+                    checksum_die_context (decl->die_parent, ctx);
+                  die_checksum_ordered (type_die, ctx, mark);
+                }
             }
         }
     }
   else if (die->die_tag == DW_TAG_friend)
     {
       /* For friend entries, we checksum only the name of the target type.  */
-      if (at_friend != NULL && AT_class (at_friend) == dw_val_class_die_ref)
+      if (attrs.at_friend != NULL
+          && AT_class (attrs.at_friend) == dw_val_class_die_ref)
         {
-          dw_die_ref friend_die = AT_ref (at_friend);
+          dw_die_ref friend_die = AT_ref (attrs.at_friend);
           dw_attr_ref name_attr = get_AT (friend_die, DW_AT_name);
           if (name_attr != NULL)
             {
-              CHECKSUM_ATTR (name_attr);
+              dw_die_ref decl = get_AT_ref (friend_die, DW_AT_specification);
+              if (decl == NULL)
+                decl = friend_die;
+              CHECKSUM_ULEB128 ('N');
+              CHECKSUM_ULEB128 (DW_AT_friend);
+              if (decl->die_parent != NULL)
+                checksum_die_context (decl->die_parent, ctx);
+              CHECKSUM_STRING (AT_string (name_attr));
             }
         }
     }
-  else
+  else if (attrs.at_type != NULL)
     {
-      CHECKSUM_ATTR (at_type);
+      dw_die_ref type_die = AT_ref (attrs.at_type);
+      dw_die_ref decl = get_AT_ref (type_die, DW_AT_specification);
+      if (decl == NULL)
+        decl = type_die;
+      if (type_die->die_mark)
+        {
+          CHECKSUM_ULEB128 ('R');
+          CHECKSUM_ULEB128 (type_die->die_mark);
+        }
+      else
+        {
+          CHECKSUM_ULEB128 ('T');
+          if (decl->die_parent != NULL)
+            checksum_die_context (decl->die_parent, ctx);
+          die_checksum_ordered (type_die, ctx, mark);
+        }
     }

   /* Checksum the child DIEs, except for nested types.  */
   c = die->die_child;
   if (c) do {
+    dw_attr_ref name_attr;
+
     c = c->die_sib;
-    if (! is_type_die (c))
-      die_checksum_ordered (c, ctx, mark);
+    name_attr = get_AT (c, DW_AT_name);
+    if (is_type_die (c) && name_attr != NULL)
+      {
+        CHECKSUM_ULEB128 (c->die_tag);
+        CHECKSUM_STRING (AT_string (name_attr));
+      }
+    else
+      {
+        die_checksum_ordered (c, ctx, mark);
+      }
   } while (c != die->die_child);
-}

-/* Checksum the context of the DIE.  This adds the names of any
-   surrounding namespaces or structures to the checksum.  */
-
-static void
-checksum_die_context (dw_die_ref die, struct md5_ctx *ctx)
-{
-  const char *name;
-  dw_die_ref spec;
-  int tag = die->die_tag;
-
-  if (tag != DW_TAG_namespace
-      && tag != DW_TAG_structure_type
-      && tag != DW_TAG_class_type)
-    return;
-
-  name = get_AT_string (die, DW_AT_name);
-
-  spec = get_AT_ref (die, DW_AT_specification);
-  if (spec != NULL)
-    die = spec;
-
-  if (die->die_parent != NULL)
-    checksum_die_context (die->die_parent, ctx);
-
-  CHECKSUM (tag);
-  if (name != NULL)
-    CHECKSUM_STRING (name);
+  CHECKSUM_ULEB128 (0);
 }

 #undef CHECKSUM
 #undef CHECKSUM_STRING
 #undef CHECKSUM_ATTR
+#undef CHECKSUM_LEB128
+#undef CHECKSUM_ULEB128

 /* Generate the type signature for DIE.  This is computed by generating an
    MD5 checksum over the DIE's tag, its relevant attributes, and its
@@ -7522,8 +7681,9 @@ generate_type_signature (dw_die_ref die,
         checksum_die_context (decl->die_parent, &ctx);

       md5_process_bytes (&die->die_tag, sizeof (die->die_tag), &ctx);
-      md5_process_bytes (name, strlen (name), &ctx);
+      md5_process_bytes (name, strlen (name) + 1, &ctx);
       md5_finish_ctx (&ctx, checksum);
+
       add_AT_data8 (type_node->root_die, DW_AT_GNU_odr_signature,
&checksum[8]);
     }

@@ -8278,6 +8438,12 @@ generate_skeleton (dw_die_ref die)
   node.old_die = die;
   node.new_die = NULL;
   node.parent = NULL;
+
+  /* If this type definition is nested inside another type,
+     always leave at least a declaration in its place.  */
+  if (die->die_parent != NULL && is_type_die (die->die_parent))
+    node.new_die = clone_as_declaration (die);
+
   generate_skeleton_bottom_up (&node);
   return node.new_die;
 }
@@ -17460,8 +17626,11 @@ prune_unused_types_mark (dw_die_ref die,
       die->die_mark = 2;

       /* If this is an array type, we need to make sure our
-	 kids get marked, even if they're types.  */
-      if (die->die_tag == DW_TAG_array_type)
+	 kids get marked, even if they're types.  If we're
+	 breaking out types into comdat sections, do this
+	 for all types.  */
+      if (die->die_tag == DW_TAG_array_type
+          || (use_dwarf4_extensions && is_type_die (die)))
 	FOR_EACH_CHILD (die, c, prune_unused_types_mark (c, 1));
       else
 	FOR_EACH_CHILD (die, c, prune_unused_types_walk (c));
@@ -17954,6 +18123,13 @@ dwarf2out_finish (const char *filename)
       if (*slot != HTAB_EMPTY_ENTRY)
         continue;

+      /* Add a pointer to the line table for the main compilation unit
+         so that the debugger can make sense of DW_AT_decl_file
+         attributes.  */
+      if (debug_info_level >= DINFO_LEVEL_NORMAL)
+        add_AT_lineptr (ctnode->root_die, DW_AT_stmt_list,
+		        debug_line_section_label);
+
       output_comdat_type_unit (ctnode);
       *slot = ctnode;
     }


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