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]

[lto] PATCH: DIE readers for struct/union/class types, + other bug fixes


Here's a patch to implement support for reading DWARF information for struct/union types. I put in a few hooks for dealing with C++ class stuff as well, but that part is still very incomplete (since we are explicitly targeting only C for now). This patch also includes fixes for a couple of unrelated bugs I found while testing.

OK to commit?

I'm going to prepare a separate patch to correct the documentation of the FIELD_DECL offset stuff in tree.h and the manual, BTW. Presumably that can go on mainline since it is not specific to LTO.

-Sandra

2006-09-29  Sandra Loosemore  <sandra@codesourcery.com>

	* gcc/lto/lto.c (lto_check_HOST_WIDE_INT_val): New.
	(lto_read_form): Make it know about DW_AT_bit_offset, DW_AT_bit_size,
	DW_AT_data_member_location, DW_AT_specification.
	(struct lto_die_cache_entry): Add sibling field.
	(lto_cache_store_DIE): Set sibling field.
	(lto_cache_lookup_DIE): Add SKIP argument; if true, skip to stored
	sibling pointer when a cache hit is found.
	(lto_read_referenced_type_DIE): Save/restore context->parentdata
	while reading the DIE.  Add FIXME note about potential bugs.
	(lto_read_structure_union_class_type_DIE): New.
	(lto_read_member_DIE): New.
	(lto_read_pointer_reference_type_DIE): Treat missing type attribute
	as void instead of error, for compatibility with dwarf2out.c behavior.
	(lto_read_const_volatile_restrict_type_DIE): Likewise.
	(lto_read_DIE): Add entries for new DIE readers to lookup table.
	Don't read children of an already-processed DIE a second time.
Index: gcc/lto/lto.c
===================================================================
*** gcc/lto/lto.c	(revision 117309)
--- gcc/lto/lto.c	(working copy)
*************** lto_abi_mismatch_error (void)
*** 321,326 ****
--- 321,327 ----
     C datatypes.  */
  LTO_CHECK_INT_VAL(size_t);
  LTO_CHECK_INT_VAL(int);
+ LTO_CHECK_INT_VAL(HOST_WIDE_INT);
  
  #undef LTO_CHECK_INT_VAL
  
*************** lto_read_form (lto_info_fd *info_fd, 
*** 701,708 ****
      DW_cl_constant, /* ordering */
      DW_cl_error, /* subscr_data */
      DW_cl_block | DW_cl_constant | DW_cl_reference, /* byte_size */
!     DW_cl_error, /* bit_offset */
!     DW_cl_error, /* bit_size */
      DW_cl_error, /* padding */
      DW_cl_error, /* element_list */
      DW_cl_lineptr, /* stmt_list */
--- 702,709 ----
      DW_cl_constant, /* ordering */
      DW_cl_error, /* subscr_data */
      DW_cl_block | DW_cl_constant | DW_cl_reference, /* byte_size */
!     DW_cl_constant, /* bit_offset */
!     DW_cl_constant, /* bit_size */
      DW_cl_error, /* padding */
      DW_cl_error, /* element_list */
      DW_cl_lineptr, /* stmt_list */
*************** lto_read_form (lto_info_fd *info_fd, 
*** 745,751 ****
      DW_cl_error, /* base_types */
      DW_cl_error, /* calling_convention */
      DW_cl_block | DW_cl_constant | DW_cl_reference, /* count */
!     DW_cl_error, /* data_member_location */
      DW_cl_error, /* decl_column */
      DW_cl_constant, /* decl_file */
      DW_cl_constant, /* decl_line */
--- 746,752 ----
      DW_cl_error, /* base_types */
      DW_cl_error, /* calling_convention */
      DW_cl_block | DW_cl_constant | DW_cl_reference, /* count */
!     DW_cl_block | DW_cl_constant, /* data_member_location */
      DW_cl_error, /* decl_column */
      DW_cl_constant, /* decl_file */
      DW_cl_constant, /* decl_line */
*************** lto_read_form (lto_info_fd *info_fd, 
*** 760,766 ****
      DW_cl_error, /* namelist_items */
      DW_cl_error, /* priority */
      DW_cl_error, /* segment */
!     DW_cl_error, /* specification */
      DW_cl_error, /* static_link */
      DW_cl_reference, /* type */
      DW_cl_error, /* use_location */
--- 761,767 ----
      DW_cl_error, /* namelist_items */
      DW_cl_error, /* priority */
      DW_cl_error, /* segment */
!     DW_cl_reference, /* specification */
      DW_cl_error, /* static_link */
      DW_cl_reference, /* type */
      DW_cl_error, /* use_location */
*************** typedef struct lto_die_cache_entry {
*** 1129,1134 ****
--- 1130,1137 ----
    const char *die;
    /* The tree corresponding to this DIE.  */
    tree val;
+   /* The address of the next sibling after the DIE.  */
+   const char *sibling;
  } lto_die_cache_entry;
  
  static hashval_t
*************** lto_cache_store_DIE (lto_info_fd *fd,
*** 1167,1185 ****
    entry = XNEW (lto_die_cache_entry);
    entry->die = die;
    entry->val = val;
    *slot = entry;
  }
  
! /* If FD points to a DIE that has already been processed, returned the
!    cached value.  */
  static tree
! lto_cache_lookup_DIE (lto_info_fd *fd, const char *die)
  {
    lto_die_cache_entry *entry;
  
    entry = htab_find_with_hash (fd->die_cache, die, 
  			       htab_hash_pointer (die));
!   return entry ? entry->val : NULL_TREE;
  }  
  
  
--- 1170,1198 ----
    entry = XNEW (lto_die_cache_entry);
    entry->die = die;
    entry->val = val;
+   entry->sibling = fd->base.cur;
    *slot = entry;
  }
  
! /* If FD points to a DIE that has already been processed, return the
!    cached value.  If SKIP is true and the DIE has already been processed,
!    adjust FD to skip over the DIE and its children and point to its next
!    sibling.  */
  static tree
! lto_cache_lookup_DIE (lto_info_fd *fd, const char *die, bool skip)
  {
    lto_die_cache_entry *entry;
  
    entry = htab_find_with_hash (fd->die_cache, die, 
  			       htab_hash_pointer (die));
!   if (entry)
!     {
!       if (skip)
! 	fd->base.cur = entry->sibling;
!       return entry->val;
!     }
!   else
!     return NULL_TREE;
  }  
  
  
*************** lto_get_identifier (const DWARF2_form_da
*** 1362,1374 ****
  
  /* Read a type DIE (located at REFERENCE) from FD.  CONTEXT is the
     current context within the compilation unit.  Returns the _TYPE
!    node corresponding to the DIE.  */
  static tree
  lto_read_referenced_type_DIE (lto_info_fd *fd,
  			      lto_context *context,
  			      const char *reference)
  {
-   const char *saved_cur;
    tree type;
  
    /* Check that the reference is in range.  We use an assert, rather
--- 1375,1392 ----
  
  /* Read a type DIE (located at REFERENCE) from FD.  CONTEXT is the
     current context within the compilation unit.  Returns the _TYPE
!    node corresponding to the DIE.
!    FIXME: Skipping around in the DWARF tree is potentially buggy if
!    there are references to types thare arbitrarily nested children of
!    other DIEs, because this will attempt to read those children without
!    the context parentdata that would otherwise be set up by their parents.
!    Current uses of parentdata for parsing DW_TAG_ENUMERATOR and
!    DW_TAG_MEMBER ought to be OK since those are not types.  */
  static tree
  lto_read_referenced_type_DIE (lto_info_fd *fd,
  			      lto_context *context,
  			      const char *reference)
  {
    tree type;
  
    /* Check that the reference is in range.  We use an assert, rather
*************** lto_read_referenced_type_DIE (lto_info_f
*** 1376,1391 ****
       checked for validity when it is read from the file.  */
    gcc_assert (reference >= context->cu_start
  	      && reference < context->cu_end);
!   type = lto_cache_lookup_DIE (fd, reference);
    if (!type)
      {
        /* Move the file pointer to the referenced location.  */
-       saved_cur = fd->base.cur;
        fd->base.cur = reference;
        /* Read the DIE, which we insist must be a type.  */
        type = lto_read_DIE (fd, context, NULL);
!       /* Restore the file pointer.  */
        fd->base.cur = saved_cur;
      }
    /* The DIE read should have been a type.  */
    if (!type || !TYPE_P (type))
--- 1394,1414 ----
       checked for validity when it is read from the file.  */
    gcc_assert (reference >= context->cu_start
  	      && reference < context->cu_end);
!   type = lto_cache_lookup_DIE (fd, reference, false);
    if (!type)
      {
+       const char *saved_cur = fd->base.cur;
+       tree parentdata = context->parentdata; 
+ 
        /* Move the file pointer to the referenced location.  */
        fd->base.cur = reference;
+       /* Reset parent data in context.  */
+       context->parentdata = NULL_TREE;
        /* Read the DIE, which we insist must be a type.  */
        type = lto_read_DIE (fd, context, NULL);
!       /* Restore the file pointer and parentdata.  */
        fd->base.cur = saved_cur;
+       context->parentdata = parentdata;
      }
    /* The DIE read should have been a type.  */
    if (!type || !TYPE_P (type))
*************** lto_read_array_type_DIE (lto_info_fd *fd
*** 1529,1534 ****
--- 1552,1753 ----
    return type;
  }
  
+ 
+ static tree
+ lto_read_structure_union_class_type_DIE (lto_info_fd *fd,
+ 					 const DWARF2_abbrev *abbrev,
+ 					 lto_context *context)
+ {
+   tree type = NULL_TREE;
+   bool declaration = false;
+   tree name = NULL_TREE;
+   int size = 0;
+   unsigned int align = 0;
+   tree parentdata;
+   VEC(tree,heap) *children;
+   int i, n;
+   tree *fields_tail;
+   tree *methods_tail;
+ 
+   LTO_BEGIN_READ_ATTRS ()
+     {
+     case DW_AT_decl_column:
+     case DW_AT_decl_file:
+     case DW_AT_decl_line:
+       /* Ignore.  */
+       break;
+ 
+     case DW_AT_name:
+       name = lto_get_identifier (&attr_data);
+       break;
+ 
+     case DW_AT_byte_size:
+       if (attr_data.cl == DW_cl_uconstant || attr_data.cl == DW_cl_sconstant)
+ 	size = attribute_value_as_int (&attr_data);
+       else
+ 	sorry ("can't handle dynamically-sized struct/union/class types");
+       break;
+ 
+     case DW_AT_declaration:
+       declaration = attr_data.u.flag;
+       break;
+ 
+     case DW_AT_specification:
+       type = lto_read_referenced_type_DIE (fd, context, attr_data.u.reference);
+       if (TREE_CODE (type) != RECORD_TYPE
+ 	  && TREE_CODE (type) != UNION_TYPE
+ 	  && TREE_CODE (type) != QUAL_UNION_TYPE)
+ 	lto_file_corrupt_error ((lto_fd *) fd);
+       break;
+ 
+     }
+   LTO_END_READ_ATTRS ();
+ 
+   /* Create the type, if this isn't a definition of a previously
+      forward-declared type.  */
+   if (!type)
+     {
+       switch (abbrev->tag)
+ 	{
+ 	case DW_TAG_structure_type:
+ 	case DW_TAG_class_type:
+ 	  type = make_node (RECORD_TYPE);
+ 	  break;
+ 
+ 	case DW_TAG_union_type:
+ 	  type = make_node (UNION_TYPE);
+ 	  break;
+ 
+ 	default:
+ 	  gcc_unreachable ();
+ 	}
+       switch (context->language)
+ 	{
+ 	case DW_LANG_C_plus_plus:
+ 	  /* In C++, the name slot gets a TYPE_DECL.  */
+ 	  if (name)
+ 	    {
+ 	      tree decl = build_decl (TYPE_DECL, name, type);
+ 	      TYPE_NAME (type) = decl;
+ 	      TYPE_STUB_DECL (type) = decl;
+ 	    }
+ 	  else
+ 	    TYPE_STUB_DECL (type) = build_decl (TYPE_DECL, NULL_TREE, type);
+ 	  break;
+ 
+ 	case DW_LANG_C:
+ 	case DW_LANG_C89:
+ 	case DW_LANG_C99:
+ 	default:
+ 	  /* In C, the name slot gets the identifier which represents the
+ 	     only the struct/union tag name, not a type name.  TYPE_STUB_DECL
+ 	     contains an anonymous decl to be used when emitting debug info. */
+ 	  if (name)
+ 	    TYPE_NAME (type) = name;
+ 	  TYPE_STUB_DECL (type) = build_decl (TYPE_DECL, NULL_TREE, type);
+ 	  break;
+ 	}
+     }
+   if (size)
+     {
+       TYPE_SIZE (type) = bitsize_int (size * BITS_PER_UNIT);
+       TYPE_SIZE_UNIT (type) = size_int (size);
+     }
+ 
+   /* Process the members.  */
+   parentdata = context->parentdata;
+   context->parentdata = type;
+   children = lto_collect_child_DIEs (fd, abbrev, context);
+   context->parentdata = parentdata;
+ 
+   n = VEC_length (tree, children);
+   fields_tail = &TYPE_FIELDS (type);
+   methods_tail = &TYPE_METHODS (type);
+   for (i = 0; i < n; i++)
+     {
+       tree child = VEC_index (tree, children, i);
+ 
+       if (!child)
+ 	continue;
+ 
+       switch (TREE_CODE (child))
+ 	{
+ 	case FIELD_DECL:
+ 	  /* Field declarations.  */
+ 	  DECL_CONTEXT (child) = type;
+ 	  *fields_tail = child;
+ 	  fields_tail = &TREE_CHAIN (child);
+ 	  /* This is kind of nasty.  DWARF doesn't encode the overall
+ 	     alignment of the struct/union type, so we'll take a stab at
+ 	     recomputing it and hope it comes out the same as for the
+ 	     original type.  */
+ 	  if (DECL_ALIGN (child) > align)
+ 	    align = DECL_ALIGN (child);
+ 	  /* FIXME: mess with propagating mutable/volatile/etc attributes
+ 	     back to parent struct type.  */
+ 	  break;
+ 	  
+ 	case VAR_DECL:
+ 	  /* Static variables in a class.  */
+ 	  DECL_CONTEXT (child) = type;
+ 	  *fields_tail = child;
+ 	  fields_tail = &TREE_CHAIN (child);
+ 	  break;
+ 
+ 	case FUNCTION_DECL:
+ 	  /* Member functions of a class.
+ 	     FIXME: Extend the DW_TAG_subprogram reader to recognize
+ 	     additional attributes for member functions.  */
+ 	  DECL_CONTEXT (child) = type;
+ 	  *methods_tail = child;
+ 	  methods_tail = &TREE_CHAIN (child);
+ 	  break;
+ 
+ 	  /* FIXME: Add support for DW_TAG_access_declaration,
+ 	     DW_TAG_inheritance,  DW_TAG_friend, and DW_TAG_variant_part
+ 	     which can appear as children of a class/struct type.  */
+ 
+ 	default:
+ 	  if (TYPE_P (child))
+ 	    /* Types declared locally within the scope of a class.  */
+ 	    {
+ 	      tree name = TYPE_NAME (child);
+ 	      if (name && (TREE_CODE (name) == TYPE_DECL))
+ 		{
+ 		  *fields_tail = name;
+ 		  fields_tail = &TREE_CHAIN (name);
+ 		}
+ 	      if (TREE_CODE (child) == ENUMERAL_TYPE)
+ 		{
+ 		/* Add enumerators to TYPE_FIELDS, too.  */
+ 		  tree pair;
+ 		  for (pair = TYPE_VALUES (child); pair;
+ 		       pair = TREE_CHAIN (pair))
+ 		    {
+ 		      tree decl = build_decl (CONST_DECL, TREE_PURPOSE (pair),
+ 					      TREE_VALUE (pair));
+ 		      *fields_tail = decl;
+ 		      fields_tail = &TREE_CHAIN (decl);
+ 		    }
+ 		}
+ 	    }
+ 	}
+     }
+   VEC_free (tree, heap, children);
+ 
+   /* The type mode isn't encoded in the DWARF spec, either, so just recompute
+      it from scratch.  */
+   compute_record_mode (type);
+   if (GET_MODE_ALIGNMENT (TYPE_MODE (type)) > align)
+     align = GET_MODE_ALIGNMENT (TYPE_MODE (type));
+   TYPE_ALIGN (type) = align;
+ 
+   /* Finish debugging output for this type.  */
+   if (!declaration)
+     rest_of_type_compilation (type, /*top_level=*/1);
+   return type;
+ }
+ 
  static tree
  lto_read_enumeration_type_DIE (lto_info_fd *fd,
  			       const DWARF2_abbrev *abbrev,
*************** lto_read_variable_formal_parameter_const
*** 1768,1773 ****
--- 1987,2193 ----
    return decl;
  }
  
+ 
+ static tree
+ lto_read_member_DIE (lto_info_fd *fd,
+ 		     const DWARF2_abbrev *abbrev,
+ 		     lto_context *context)
+ {
+   tree name = NULL_TREE;
+   tree type = NULL_TREE;
+   tree byte_offset = NULL_TREE;
+   tree bit_offset = NULL_TREE;
+   tree bit_size = NULL_TREE;
+   tree byte_size = NULL_TREE;
+   bool bit_field_p = false;
+   tree decl;
+   int code;
+   tree bitpos;
+   unsigned int bitpos_align;
+ 
+   /* The DWARF spec implies that data member entries can appear outside of a
+      structure, union, or class, but doesn't say what that might mean.  */
+   code = context->parentdata ? TREE_CODE (context->parentdata) : ERROR_MARK;
+   if (code != RECORD_TYPE
+       && code != UNION_TYPE
+       && code != QUAL_UNION_TYPE)
+     sorry ("member declaration not inside structure, class, or union");
+ 
+   LTO_BEGIN_READ_ATTRS ()
+     {
+     case DW_AT_decl_column:
+     case DW_AT_decl_file:
+     case DW_AT_decl_line:
+       /* Ignore.  */
+       break;
+ 
+     case DW_AT_name:
+       name = lto_get_identifier (&attr_data);
+       break;
+ 
+     case DW_AT_type:
+       type = lto_read_referenced_type_DIE (fd, 
+ 					   context, 
+ 					   attr_data.u.reference);
+       break;
+ 
+     case DW_AT_data_member_location:
+       /* This is a constant or location description giving the offset in
+ 	 bytes from the beginning of the data member.  If it's a location
+ 	 description, it's an expression that would be evaluated as if the
+ 	 offset of the beginning of the structure has already been pushed
+ 	 on the stack.  */
+       if (attr_data.cl == DW_cl_uconstant || attr_data.cl == DW_cl_sconstant)
+ 	byte_offset = attribute_value_as_constant (&attr_data, bitsizetype);
+       else if (attr_data.cl != DW_cl_block)
+ 	lto_file_corrupt_error ((lto_fd *) fd);
+       else
+ 	/* Instead of doing a general location evaluation, just look
+ 	   for the patterns generated by dwarf2out.c.  */
+ 	{
+ 	  struct lto_fd datafd;
+ 	  uint64_t operator;
+ 
+ 	  lto_fd_init (&datafd, "DW_AT_data_member_location data",
+ 		       ((lto_fd *)fd)->file);
+ 	  datafd.start = (const char *)attr_data.u.block.data;
+ 	  datafd.end = datafd.start + attr_data.u.block.length;
+ 	  datafd.cur = datafd.start;
+ 	  datafd.dwarf64 = ((lto_fd *)fd)->dwarf64;
+ 
+ 	  operator = lto_read_uleb128 (&datafd);
+ 	  if (operator == DW_OP_constu || operator == DW_OP_plus_uconst)
+ 	    {
+ 	      uint64_t operand = lto_read_uleb128 (&datafd);
+ 	      HOST_WIDE_INT opval =
+ 		lto_check_HOST_WIDE_INT_val (operand, "offset too large");
+ 	      byte_offset = build_int_cst (bitsizetype, opval);
+ 	      if (datafd.cur != datafd.end)
+ 		lto_unsupported_attr_error (abbrev, attr);
+ 	    }
+ 	  else
+ 	    lto_unsupported_attr_error (abbrev, attr);
+ 	}
+       break;
+ 
+     case DW_AT_byte_size:
+       byte_size = attribute_value_as_constant (&attr_data, bitsizetype);
+       break;
+ 
+     case DW_AT_bit_offset:
+       bit_offset = attribute_value_as_constant (&attr_data, bitsizetype);
+       bit_field_p = true;
+       break;
+ 
+     case DW_AT_bit_size:
+       bit_size = attribute_value_as_constant (&attr_data, bitsizetype);
+       bit_field_p = true;
+       break;
+ 
+     case DW_AT_accessibility:
+     case DW_AT_mutable:
+       lto_unsupported_attr_error (abbrev, attr);
+       break;
+ 
+     }
+   LTO_END_READ_ATTRS ();
+ 
+   /* Complain if we didn't get a type.  */
+   if (! type)
+     lto_file_corrupt_error ((lto_fd *) fd);
+ 
+   /* Complain if we got a non-zero offset or bit field attribute for a union,
+      or a missing offset when we're not processing a union, or incomplete
+      bit field information.  */
+   if (code == UNION_TYPE)
+     {
+       if (bit_field_p)
+ 	lto_file_corrupt_error ((lto_fd *) fd);
+       if (!byte_offset)
+ 	byte_offset = bitsize_zero_node;
+       else if (! integer_zerop (byte_offset))
+ 	lto_file_corrupt_error ((lto_fd *) fd);
+     }
+   else
+     {
+       if (! byte_offset)
+ 	lto_file_corrupt_error ((lto_fd *) fd);
+       if (bit_field_p && ! (bit_size && bit_offset))
+ 	lto_file_corrupt_error ((lto_fd *) fd);
+     }
+ 
+   /* Make sure we got a byte size if we need one, or that it's not
+      incompatible with the specified type.  */
+   if (bit_field_p && ! byte_size)
+     byte_size = fold_convert (bitsizetype, TYPE_SIZE_UNIT (type));
+   else if (!bit_field_p && byte_size &&
+ 	   !tree_int_cst_equal (byte_size, TYPE_SIZE_UNIT (type)))
+     sorry ("don't know what to do with DW_AT_byte_size for non-bitfields");
+ 
+   /* Compute the bit position of the field relative to the beginning of
+      its containing structure.  */
+   bitpos = size_binop (MULT_EXPR, byte_offset, bitsize_unit_node);
+   if (bit_field_p)
+     {
+       /* DWARF's bit offset is the number of bits from the most significant
+ 	 bit of the anonymous containing object to the most significant
+ 	 bit of the bit field.  So we need to reverse to count from the
+ 	 opposite end of the container in the little-endian case.  */
+       if (! BYTES_BIG_ENDIAN)
+ 	{
+ 	  tree container_bit_size =
+ 	    size_binop (MULT_EXPR, byte_size, bitsize_unit_node);
+ 	  bit_offset = size_binop (MINUS_EXPR,
+ 				   size_binop (MINUS_EXPR,
+ 					       container_bit_size, bit_offset),
+ 				   bit_size);
+ 	}
+       bitpos = size_binop (PLUS_EXPR, bitpos, bit_offset);
+     }
+ 
+   /* Next we need to find the alignment of the bit position.  This bit of
+      code copied from the Ada front end.  */
+   if (host_integerp (bitpos, 1))
+     bitpos_align = (tree_low_cst (bitpos, 1) & -
+ 		   tree_low_cst (bitpos, 1));
+   else
+     bitpos_align = BITS_PER_UNIT;
+ 
+   /* Build the decl and fill in its attributes.  For bit fields, create
+      and layout the field with its declared type, then overwrite it with
+      a type of the specified precision; this is the way the C front end
+      does it, and doing it the same way ensures that all of the various
+      types, sizes, and alignments are compatible with those generated by
+      C.  */
+   decl = build_decl (FIELD_DECL, name, type);
+   if (bit_field_p)
+     {
+       DECL_SIZE (decl) = bit_size;
+       DECL_BIT_FIELD (decl) = true;
+       DECL_NONADDRESSABLE_P (decl) = true;
+       layout_decl (decl, bitpos_align);
+       TREE_TYPE (decl) =
+ 	build_nonstandard_integer_type (tree_low_cst (bit_size, 1),
+ 					TYPE_UNSIGNED (type));
+       DECL_MODE (decl) = TYPE_MODE (type);
+     }
+   else
+     layout_decl (decl, bitpos_align);
+ 
+   /* Now set the offset explicitly.  This bit of code was stolen from the
+      Ada front end.  */
+   SET_DECL_OFFSET_ALIGN (decl,
+ 			 (host_integerp (bitpos, 1)
+ 			  ? BIGGEST_ALIGNMENT : BITS_PER_UNIT));
+   pos_from_bit (&DECL_FIELD_OFFSET (decl),
+ 		&DECL_FIELD_BIT_OFFSET (decl),
+ 		DECL_OFFSET_ALIGN (decl),
+ 		bitpos);
+ 
+   lto_read_child_DIEs (fd, abbrev, context);
+   return decl;
+ }
+ 
  static tree
  lto_read_subroutine_type_subprogram_DIE (lto_info_fd *fd,
  					 const DWARF2_abbrev *abbrev,
*************** lto_read_pointer_reference_type_DIE (lto
*** 2034,2042 ****
      }
    LTO_END_READ_ATTRS ();
  
!   /* The DW_AT_type attribute is required.  */
    if (!pointed_to)
!     lto_file_corrupt_error ((lto_fd *)fd);
    /* Build the pointer or reference type.  */
    switch (abbrev->tag)
      {
--- 2454,2466 ----
      }
    LTO_END_READ_ATTRS ();
  
!   /* The DW_AT_type attribute is supposed to be required, but since DWARF
!      has no representation for the void type, dwarf2out.c omits the type
!      attribute in that case.  So, in order to allow GCC's output to be
!      read in again, we have to interpret a missing base type attribute as
!      the void type, too.  */
    if (!pointed_to)
!     pointed_to = void_type_node;
    /* Build the pointer or reference type.  */
    switch (abbrev->tag)
      {
*************** lto_read_const_volatile_restrict_type_DI
*** 2281,2289 ****
      }
    LTO_END_READ_ATTRS ();
  
!   /* The DW_AT_type attribute is required.  */
    if (!base_type)
!     lto_file_corrupt_error ((lto_fd *)fd);
    /* Build the modified type.  */
    switch (abbrev->tag)
      {
--- 2705,2717 ----
      }
    LTO_END_READ_ATTRS ();
  
!   /* The DW_AT_type attribute is supposed to be required, but since DWARF
!      has no representation for the void type, dwarf2out.c omits the type
!      attribute in that case.  So, in order to allow GCC's output to be
!      read in again, we have to interpret a missing base type attribute as
!      the void type, too.  */
    if (!base_type)
!     base_type = void_type_node;
    /* Build the modified type.  */
    switch (abbrev->tag)
      {
*************** lto_read_DIE (lto_info_fd *fd, lto_conte
*** 2321,2327 ****
      {
        NULL, /* padding */
        lto_read_array_type_DIE,
!       NULL, /* class_type */
        NULL, /* entry_point */
        lto_read_enumeration_type_DIE,
        lto_read_variable_formal_parameter_constant_DIE,
--- 2749,2755 ----
      {
        NULL, /* padding */
        lto_read_array_type_DIE,
!       lto_read_structure_union_class_type_DIE,
        NULL, /* entry_point */
        lto_read_enumeration_type_DIE,
        lto_read_variable_formal_parameter_constant_DIE,
*************** lto_read_DIE (lto_info_fd *fd, lto_conte
*** 2332,2348 ****
        NULL, /* label */
        NULL, /* lexical_block */
        NULL, /* padding */
!       NULL, /* member */
        NULL, /* padding */
        lto_read_pointer_reference_type_DIE,
        lto_read_pointer_reference_type_DIE,
        lto_read_compile_unit_DIE,
        NULL, /* string_type */
!       NULL, /* structure_type */
        NULL, /* padding */
        lto_read_subroutine_type_subprogram_DIE,
        lto_read_typedef_DIE,
!       NULL, /* union_type */
        lto_read_unspecified_parameters_DIE,
        NULL, /* variant */
        NULL, /* common_block */
--- 2760,2776 ----
        NULL, /* label */
        NULL, /* lexical_block */
        NULL, /* padding */
!       lto_read_member_DIE,
        NULL, /* padding */
        lto_read_pointer_reference_type_DIE,
        lto_read_pointer_reference_type_DIE,
        lto_read_compile_unit_DIE,
        NULL, /* string_type */
!       lto_read_structure_union_class_type_DIE,
        NULL, /* padding */
        lto_read_subroutine_type_subprogram_DIE,
        lto_read_typedef_DIE,
!       lto_read_structure_union_class_type_DIE,
        lto_read_unspecified_parameters_DIE,
        NULL, /* variant */
        NULL, /* common_block */
*************** lto_read_DIE (lto_info_fd *fd, lto_conte
*** 2391,2397 ****
    DIE_reader_fnptr reader;
    const char *die;
    tree val;
-   bool skip;
  
    /* Record the location of the current DIE -- before we change the
       file pointer.  */
--- 2819,2824 ----
*************** lto_read_DIE (lto_info_fd *fd, lto_conte
*** 2407,2416 ****
      }
    /* Get the actual abbreviation entry.  */
    abbrev = lto_abbrev_lookup (&fd->base.file->debug_abbrev, index);
!   /* Assume that we will need to skip over this DIE.  */
!   skip = true;
!   /* Check to see if this DIE has already been processed.  */
!   val = lto_cache_lookup_DIE (fd, die);
    if (!val)
      {
        /* Determine the DIE reader function.  */
--- 2834,2842 ----
      }
    /* Get the actual abbreviation entry.  */
    abbrev = lto_abbrev_lookup (&fd->base.file->debug_abbrev, index);
!   /* Check to see if this DIE has already been processed.  If so, skip
!      over it and its children.  */
!   val = lto_cache_lookup_DIE (fd, die, true);
    if (!val)
      {
        /* Determine the DIE reader function.  */
*************** lto_read_DIE (lto_info_fd *fd, lto_conte
*** 2425,2449 ****
  	     references to the type can be processed quickly.  */
  	  if (val && TYPE_P (val))
  	    lto_cache_store_DIE (fd, die, val);
- 	  skip = false;
  	}
        else
- 	/* Assume that all other tags matter, as we are otherwise at
- 	   risk of silently generating wrong code.  If a tag can be
- 	   safely ignored, it should be explicitly ignored above.  */
- 	error ("DWARF tag " HOST_WIDEST_INT_PRINT_UNSIGNED " not "
- 	       "supported by link-time optimization", abbrev->tag);
-     }
-   /* Skip over this DIE if it has not already been processed.  */
-   if (skip)
-     {
-       /* Read and ignore all attributes.  */
-       LTO_BEGIN_READ_ATTRS_UNCHECKED ()
  	{
  	}
-       LTO_END_READ_ATTRS ();
-       /* Read children.  */ 
-       lto_read_child_DIEs (fd, abbrev, context);
      }
  
    if (more)
--- 2851,2873 ----
  	     references to the type can be processed quickly.  */
  	  if (val && TYPE_P (val))
  	    lto_cache_store_DIE (fd, die, val);
  	}
        else
  	{
+ 	  /* Assume that all other tags matter, as we are otherwise at
+ 	     risk of silently generating wrong code.  If a tag can be
+ 	     safely ignored, it should be explicitly ignored above.  */
+ 	  error ("DWARF tag " HOST_WIDEST_INT_PRINT_UNSIGNED " not "
+ 		 "supported by link-time optimization", abbrev->tag);
+ 
+ 	  /* Skip over this DIE, but attempt to read its children.  */
+ 	  LTO_BEGIN_READ_ATTRS_UNCHECKED ()
+ 	    {
+ 	    }
+ 	  LTO_END_READ_ATTRS ();
+ 	  /* Read children.  */ 
+ 	  lto_read_child_DIEs (fd, abbrev, context);
  	}
      }
  
    if (more)

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