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: Add DIE readers for array and enum types


This code has been very minimally tested, since the LTO front end is still a work in progress. Any comments before I check this in?

-Sandra

2006-08-31  Sandra Loosemore  <sandra@codesourcery.com>

	* gcc/lto/lto.c (struct lto_context): Remove type field, add language.
	(lto_read_uleb128): Fix to assemble bytes in the correct order.
	(lto_read_sleb128): New.
	(lto_read_form): Make it know about some more attributes.  Make it
	understand DW_FORM_sdata and DW_FORM_udata.
	(lto_find_integral_type): New.
	(lto_read_compile_unit_DIE): Return tree instead of void.  Set the
	language in the context.
	(lto_read_array_type_DIE): New.
	(lto_read_enumeration_type_DIE): New.
	(lto_read_enumerator_DIE): New.
	(lto_read_variable_formal_parameter_constant_DIE): Return the decl
	instead of void.
	(lto_read_pointer_type_DIE): Return the type instead of void.
	(lto_read_subrange_type_DIE): New.
	(lto_read_base_type_DIE): Return the type instead of void.  Also,
	GCC generates unnamed base_type DIEs, so do something sensible if
	we get one.
	(lto_read_DIE): Change type to return the tree value constructed from
	reading the DIE.  Make the boolean "more" flag a parameter instead.
	Updated all callers.  Make it know about the readers for array_type,
	enumeration_type, and subrange_type, and enumerator DIEs.
	(lto_collect_child_DIEs): New.
Index: gcc/lto/lto.c
===================================================================
*** gcc/lto/lto.c	(revision 116299)
--- gcc/lto/lto.c	(working copy)
*************** typedef struct DWARF2_form_data
*** 89,95 ****
    union {
      /* If CL is DW_address, DW_lineptr, DW_loclistptr, DW_macptr, 
         or DW_rangelistptr, there is no additional data.  These forms
!        are not of interest to us for linke-time optimization.  */
      /* Used when CL is DW_cl_constant.  */
      uint64_t constant;
      /* Used when CL is DW_cl_block.  */
--- 89,95 ----
    union {
      /* If CL is DW_address, DW_lineptr, DW_loclistptr, DW_macptr, 
         or DW_rangelistptr, there is no additional data.  These forms
!        are not of interest to us for link-time optimization.  */
      /* Used when CL is DW_cl_constant.  */
      uint64_t constant;
      /* Used when CL is DW_cl_block.  */
*************** typedef struct lto_context
*** 127,139 ****
       containing the DIE about to be read.  NULL_TREE if at the
       outermost level.  */
    tree scope;
!   /* If the last DIE read (with lto_read_DIE) was a type, then this
!      field is the type.  NULL otherwise.  */
!   tree type;
  } lto_context;
  
  /* We can't use DWARF_Internal_CompUnit because it does not track the
!    offset from the beginning of debug_info, which necessary for
     lookups of DW_FORM_ref_addr data.  */
     
  struct DWARF2_CompUnit
--- 127,139 ----
       containing the DIE about to be read.  NULL_TREE if at the
       outermost level.  */
    tree scope;
!   /* Some things (like lower array bounds) have language-specific defaults,
!      so keep track of the language here.  */
!   int language;
  } lto_context;
  
  /* We can't use DWARF_Internal_CompUnit because it does not track the
!    offset from the beginning of debug_info, which is necessary for
     lookups of DW_FORM_ref_addr data.  */
     
  struct DWARF2_CompUnit
*************** lto_cache_hash (const void *data);
*** 160,174 ****
  static int
  lto_cache_eq (const void *data, const void *key);
  
! static bool
  lto_read_DIE (lto_info_fd *fd,
! 	      lto_context *context);
  
  static void
  lto_read_child_DIEs (lto_info_fd *fd, 
  		     const DWARF2_abbrev *abbrev, 
  		     lto_context *context);
  
  static void
  lto_set_cu_context (lto_context *context, lto_info_fd *fd,
  		    DWARF2_CompUnit *unit);
--- 160,180 ----
  static int
  lto_cache_eq (const void *data, const void *key);
  
! static tree
  lto_read_DIE (lto_info_fd *fd,
! 	      lto_context *context,
! 	      bool *more);
  
  static void
  lto_read_child_DIEs (lto_info_fd *fd, 
  		     const DWARF2_abbrev *abbrev, 
  		     lto_context *context);
  
+ static VEC(tree,heap) *
+ lto_collect_child_DIEs (lto_info_fd *fd, 
+ 			const DWARF2_abbrev *abbrev, 
+ 			lto_context *context);
+ 
  static void
  lto_set_cu_context (lto_context *context, lto_info_fd *fd,
  		    DWARF2_CompUnit *unit);
*************** lto_read_uleb128 (lto_fd *fd)
*** 342,360 ****
    uint8_t byte;
    uint64_t result;
    bool more;
  
    result = 0;
    do
      {
        byte = lto_read_ubyte (fd);
        more = byte & 0x80;
!       result = (result << 7) | (byte & ~0x80);
      }
    while (more);
  
    return result;
  }
  
  /* Read an initial length field from FD.  The length may be a 32-bit
     or 64-bit quantity, depending on whether 32-bit or 64-bit DWARF is
     in use, so the value returned is always a 64-bit value.  Set
--- 348,396 ----
    uint8_t byte;
    uint64_t result;
    bool more;
+   unsigned shift;
  
    result = 0;
+   shift = 0;
    do
      {
        byte = lto_read_ubyte (fd);
        more = byte & 0x80;
!       result |= (byte & ~0x80) << shift;
!       shift += 7;
      }
    while (more);
  
    return result;
  }
  
+ /* Read an signed LEB128 value from FD.  */
+ static int64_t
+ lto_read_sleb128 (lto_fd *fd)
+ {
+   uint8_t byte;
+   uint64_t result;
+   bool more;
+   uint8_t sign;
+   unsigned shift;
+ 
+   result = 0;
+   shift = 0;
+   do
+     {
+       byte = lto_read_ubyte (fd);
+       more = byte & 0x80;
+       result |= (byte & ~0x80) << shift;
+       shift += 7;
+       sign = (byte & 0x40);
+     }
+   while (more);
+ 
+   if (sign && shift < 64)
+     result |= (int64_t)(-1) << shift;
+   return (int64_t) result;
+ }
+ 
  /* Read an initial length field from FD.  The length may be a 32-bit
     or 64-bit quantity, depending on whether 32-bit or 64-bit DWARF is
     in use, so the value returned is always a 64-bit value.  Set
*************** lto_read_form (lto_info_fd *info_fd, 
*** 628,640 ****
      DW_cl_error, /* string_length */
      DW_cl_error, /* common_reference */
      DW_cl_string, /* comp_dir */
!     DW_cl_error, /* const_value */
      DW_cl_error, /* containing_type */
      DW_cl_error, /* default_value */
      DW_cl_error, /* padding */
      DW_cl_error, /* inline */
      DW_cl_error, /* is_optional */
!     DW_cl_error, /* lower_bound */
      DW_cl_error, /* padding */
      DW_cl_error, /* padding */
      DW_cl_string, /* producer */
--- 664,676 ----
      DW_cl_error, /* string_length */
      DW_cl_error, /* common_reference */
      DW_cl_string, /* comp_dir */
!     DW_cl_block | DW_cl_constant | DW_cl_string, /* const_value */
      DW_cl_error, /* containing_type */
      DW_cl_error, /* default_value */
      DW_cl_error, /* padding */
      DW_cl_error, /* inline */
      DW_cl_error, /* is_optional */
!     DW_cl_block | DW_cl_constant | DW_cl_reference, /* lower_bound */
      DW_cl_error, /* padding */
      DW_cl_error, /* padding */
      DW_cl_string, /* producer */
*************** lto_read_form (lto_info_fd *info_fd, 
*** 647,653 ****
      DW_cl_error, /* start_scope */
      DW_cl_error, /* padding */
      DW_cl_error, /* stride_size */
!     DW_cl_error, /* upper_bound */
      DW_cl_error, /* padding */
      DW_cl_error, /* abstract_origin */
      DW_cl_error, /* accessibility */
--- 683,689 ----
      DW_cl_error, /* start_scope */
      DW_cl_error, /* padding */
      DW_cl_error, /* stride_size */
!     DW_cl_block | DW_cl_constant | DW_cl_reference, /* upper_bound */
      DW_cl_error, /* padding */
      DW_cl_error, /* abstract_origin */
      DW_cl_error, /* accessibility */
*************** lto_read_form (lto_info_fd *info_fd, 
*** 655,661 ****
      DW_cl_error, /* artificial */
      DW_cl_error, /* base_types */
      DW_cl_error, /* calling_convention */
!     DW_cl_error, /* count */
      DW_cl_error, /* data_member_location */
      DW_cl_error, /* decl_column */
      DW_cl_constant, /* decl_file */
--- 691,697 ----
      DW_cl_error, /* artificial */
      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 */
*************** lto_read_form (lto_info_fd *info_fd, 
*** 749,754 ****
--- 785,792 ----
      case DW_FORM_data2:
      case DW_FORM_data4:
      case DW_FORM_data8:
+     case DW_FORM_sdata:
+     case DW_FORM_udata:
        {
  	uint64_t data;
  	/* Read the actual data.  */
*************** lto_read_form (lto_info_fd *info_fd, 
*** 766,771 ****
--- 804,815 ----
  	  case DW_FORM_data8:
  	    data = lto_read_udword (fd);
  	    break;
+ 	  case DW_FORM_sdata:
+ 	    data = (uint64_t)lto_read_sleb128 (fd);
+ 	    break;
+ 	  case DW_FORM_udata:
+ 	    data = lto_read_sleb128 (fd);
+ 	    break;
  	  default:
  	    gcc_unreachable ();
  	    break;
*************** lto_cache_lookup_DIE (lto_info_fd *fd, c
*** 1004,1009 ****
--- 1048,1095 ----
  			       htab_hash_pointer (die));
    return entry ? entry->val : NULL_TREE;
  }  
+ 
+ 
+ /* Some DIEs (notably those for DW_TAG_subrange_type and
+    DW_TAG_enumeration_type) may include either or both of base type and 
+    byte size attributes; the byte size is supposed modify the base
+    type.  Put them together and return the resulting type.
+    Additionally enforce the restriction that the base type must be
+    a complete integral type.
+    If neither attribute is specified, then return int_type as the default.
+    FIXME: This currently just barfs if both are specified and are not
+    the same size.  */
+ 
+ static tree
+ lto_find_integral_type (tree base_type, int byte_size, bool got_byte_size)
+ {
+   int nbits = byte_size * BITS_PER_UNIT;
+ 
+   if (! base_type)
+     {
+       if (! got_byte_size)
+ 	base_type = integer_type_node;
+       else if (nbits == INT_TYPE_SIZE)
+ 	base_type = integer_type_node;
+       else if (nbits == CHAR_TYPE_SIZE)
+ 	base_type = char_type_node;
+       else if (nbits == SHORT_TYPE_SIZE)
+ 	base_type = short_integer_type_node;
+       else if (nbits == LONG_TYPE_SIZE)
+ 	base_type = long_integer_type_node;
+       else if (nbits == LONG_LONG_TYPE_SIZE)
+ 	base_type = long_long_integer_type_node;
+       else
+ 	lto_abi_mismatch_error ();
+     }
+   else if (! INTEGRAL_TYPE_P (base_type)
+ 	   || !TYPE_SIZE (base_type)
+ 	   || !host_integerp (TYPE_SIZE (base_type), 1)
+ 	   || (got_byte_size
+ 	       && nbits != tree_low_cst (TYPE_SIZE (base_type), 1)))
+     lto_abi_mismatch_error ();
+   return base_type;
+ }
     
  /* DIE Readers
   
*************** lto_cache_lookup_DIE (lto_info_fd *fd, c
*** 1017,1023 ****
     Each DIE reader is responsible for reading a DIE and its children.
     In general, the form of each DIE reader is:
  
!       static void
        lto_read_tag_DIE (lto_info_fd *fd, 
                          const DWARF2_abbrev *abbrev,
  		        lto_context *context)
--- 1103,1109 ----
     Each DIE reader is responsible for reading a DIE and its children.
     In general, the form of each DIE reader is:
  
!       static tree
        lto_read_tag_DIE (lto_info_fd *fd, 
                          const DWARF2_abbrev *abbrev,
  		        lto_context *context)
*************** lto_cache_lookup_DIE (lto_info_fd *fd, c
*** 1037,1058 ****
  	 LTO_END_READ_ATTRS ();  
  	 
  	 lto_read_child_DIES (fd, abbrev, context);
        }  
  
!    The set of attributes handle should include (at least) all the
!    attributes actually emitted by GCC.  Uinteresting attributes may
     simply be ignored, but they should be named.  Attributes that you
     know are important, but for which support has not yet been
     implemented, should be handled by calling
     lto_unsupported_attr_error.  As a special case, you do not need to
     handle DW_AT_sibling; this attribute is just a hint, and is ignored
!    everywhere.  LTO_{BEGIN,END}_READ_ATTRS will add a default case
     that issues about errors for unhandled attributes to help to
     enforce these rules.  
     
     These rules may seem in contrast to the normal rules for a DWARF
!    consumer which suggest that consumers should just ignore entries do
!    not understand.  However, in this situation, we can assume that the
     input files came from GCC itself (so we do not need to worry about
     extensions from other tools).  Furthermore, we must be concerned
     that ignoring entries might result in silent wrong-code generation.
--- 1123,1146 ----
  	 LTO_END_READ_ATTRS ();  
  	 
  	 lto_read_child_DIES (fd, abbrev, context);
+ 
+          return ...tree representing decoded DIE;        
        }  
  
!    The set of attributes handled should include (at least) all the
!    attributes actually emitted by GCC.  Uninteresting attributes may
     simply be ignored, but they should be named.  Attributes that you
     know are important, but for which support has not yet been
     implemented, should be handled by calling
     lto_unsupported_attr_error.  As a special case, you do not need to
     handle DW_AT_sibling; this attribute is just a hint, and is ignored
!    everywhere.  LTO_{BEGIN,END}_READ_ATTRS add a default case
     that issues about errors for unhandled attributes to help to
     enforce these rules.  
     
     These rules may seem in contrast to the normal rules for a DWARF
!    consumer which suggest that consumers should just ignore entries they 
!    do not understand.  However, in this situation, we can assume that the
     input files came from GCC itself (so we do not need to worry about
     extensions from other tools).  Furthermore, we must be concerned
     that ignoring entries might result in silent wrong-code generation.
*************** lto_read_referenced_type_DIE (lto_info_f
*** 1160,1172 ****
        saved_cur = fd->base.cur;
        fd->base.cur = reference;
        /* Read the DIE, which we insist must be a type.  */
!       lto_read_DIE (fd, context);
        /* Restore the file pointer.  */
        fd->base.cur = saved_cur;
-       type = context->type;
-       /* Clear CONTEXT->TYPE since we are just reading a reference to
- 	 a type, not the DWARF subtree for a type.  */
-       context->type = NULL_TREE;
      }
    /* The DIE read should have been a type.  */
    if (!type || !TYPE_P (type))
--- 1248,1256 ----
        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))
*************** lto_read_referenced_type_DIE (lto_info_f
*** 1175,1181 ****
    return type;
  }
  
! static void
  lto_read_compile_unit_DIE (lto_info_fd *fd, 
  			   const DWARF2_abbrev *abbrev,
  			   lto_context *context)
--- 1259,1265 ----
    return type;
  }
  
! static tree
  lto_read_compile_unit_DIE (lto_info_fd *fd, 
  			   const DWARF2_abbrev *abbrev,
  			   lto_context *context)
*************** lto_read_compile_unit_DIE (lto_info_fd *
*** 1197,1202 ****
--- 1281,1287 ----
  		 attr_data.u.constant);
  	  break;
  	}
+       context->language = attr_data.u.constant;
        break;
  
      case DW_AT_low_pc:
*************** lto_read_compile_unit_DIE (lto_info_fd *
*** 1220,1228 ****
    LTO_END_READ_ATTRS ();
  
    lto_read_child_DIEs (fd, abbrev, context);
  }
  
! static void
  lto_read_variable_formal_parameter_constant_DIE (lto_info_fd *fd,
  						 const DWARF2_abbrev *abbrev,
  						 lto_context *context)
--- 1305,1522 ----
    LTO_END_READ_ATTRS ();
  
    lto_read_child_DIEs (fd, abbrev, context);
+   return NULL_TREE;
  }
  
! static tree
! lto_read_array_type_DIE (lto_info_fd *fd,
! 			 const DWARF2_abbrev *abbrev,
! 			 lto_context *context)
! {
!   tree type = NULL_TREE;
!   VEC(tree,heap) *dims;
!   int ndims;
!   int order = -1;
!   int i, istart, iend;
! 
!   LTO_BEGIN_READ_ATTRS ()
!     {
!     case DW_AT_decl_column:
!     case DW_AT_decl_file:
!     case DW_AT_decl_line:
!       /* Ignore.  */
!       break;
! 
!     case DW_AT_type:
!       type = lto_read_referenced_type_DIE (fd, 
! 					   context, 
! 					   attr_data.u.reference);
!       break;
! 
!     case DW_AT_ordering:
!       switch (attr_data.u.constant)
! 	{
! 	case DW_ORD_col_major:
! 	  /* Process dimensions left-to-right */
! 	  order = 1;
! 	  break;
! 	case DW_ORD_row_major:
! 	  /* Process dimensions right-to-left */
! 	  order = -1;
! 	  break;
! 	default:
! 	  lto_file_corrupt_error ((lto_fd *)fd);
! 	}
!       break;
!       
!     case DW_AT_byte_size:
!     case DW_AT_stride:
!       lto_unsupported_attr_error (abbrev, attr);
!       break;
! 
!     }
!   LTO_END_READ_ATTRS ();
! 
!   /* The DW_AT_type attribute is required.  */
!   if (!type)
!     lto_file_corrupt_error ((lto_fd *)fd);
! 
!   /* Array dimensions are given as children of the DW_TAG_array_type DIE,
!      and are tagged with either DW_TAG_subrange_type or
!      DW_TAG_enumeration_type.  */
! 
!   dims = lto_collect_child_DIEs (fd, abbrev, context);
!   ndims = VEC_length (tree, dims);
! 
!   /* Construct and cache the array type object for our caller.  */
!   if (ndims == 0)
!     lto_file_corrupt_error ((lto_fd *)fd);
!   if (order == -1)
!     {
!       istart = ndims - 1;
!       iend = -1;
!     }
!   else
!     {
!       gcc_assert (order == 1);
!       istart = 0;
!       iend = ndims;
!     }
!   for (i = istart; i != iend; i += order)
!     {
!       tree dim = VEC_index (tree, dims, i);
!       if (!dim || ! INTEGRAL_TYPE_P (dim))
! 	lto_file_corrupt_error ((lto_fd *)fd);	
!       type = build_array_type (type, dim);
!     }
!   VEC_free (tree, heap, dims);
!   return type;
! }
! 
! static tree
! lto_read_enumeration_type_DIE (lto_info_fd *fd,
! 			       const DWARF2_abbrev *abbrev,
! 			       lto_context *context)
! {
!   VEC(tree,heap) *enumerators;
!   int i, n;
!   tree type;
!   tree base = NULL_TREE;
!   tree name = NULL_TREE;
!   int byte_size = 0;
!   bool got_byte_size = false;
!   tree enumlist = NULL_TREE;
! 
!   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:
!       base = lto_read_referenced_type_DIE (fd, 
! 					   context, 
! 					   attr_data.u.reference);
!       break;
! 
!     case DW_AT_byte_size:
!       if (attr_data.cl != DW_cl_constant)
! 	lto_abi_mismatch_error ();
!       byte_size = attr_data.u.constant;
!       got_byte_size = true;
!       break;
! 
!     case DW_AT_stride:
!       lto_unsupported_attr_error (abbrev, attr);
!     }
!   LTO_END_READ_ATTRS ();
! 
!   /* Reconcile base type and byte size attributes.  */
!   base = lto_find_integral_type (base, byte_size, got_byte_size);
! 
!   /* Build the (empty) enumeration type and fill in some attributes
!      copied from the base type.  */
!   type = make_node (ENUMERAL_TYPE);
!   if (name)
!     TYPE_NAME (type) = name;
!   TYPE_MIN_VALUE (type) = TYPE_MIN_VALUE (base);
!   TYPE_MAX_VALUE (type) = TYPE_MAX_VALUE (base);
!   TYPE_UNSIGNED (type) = TYPE_UNSIGNED (base);
!   TYPE_SIZE (type) = 0;
!   TYPE_PRECISION (type) = TYPE_PRECISION (base);
!   layout_type (type);
! 
!   /* Process the enumerators.  */
!   enumerators = lto_collect_child_DIEs (fd, abbrev, context);
!   n = VEC_length (tree, enumerators);
!   for (i = n-1; i >= 0; i--)
!     {
!       tree pair = VEC_index (tree, enumerators, i);
!       /* Make sure the child was actually an enumerator, which parse as
! 	 (name, value) pairs.  */
!       if (! pair || TREE_CODE (pair) != TREE_LIST)
! 	lto_abi_mismatch_error ();
!       /* The enumerator values stored in the ENUMERAL_TYPE are supposed
! 	 to have the enum type rather than integer type.  Adjust it here.  */
!       TREE_VALUE (pair) =
! 	build_int_cst (type, TREE_INT_CST_LOW (TREE_VALUE (pair)));
!       /* FIXME:  Do we need to build and record a DECL for the enumerators? */
!       TREE_CHAIN (pair) = enumlist;
!       enumlist = pair;
!     }
!   TYPE_VALUES (type) = enumlist;
!   TYPE_STUB_DECL (type) = build_decl (TYPE_DECL, NULL_TREE, type);
! 
!   /* Finish debugging output for this type.  */
!   rest_of_type_compilation (type, /*top_level=*/1);
!   return type;
! }
! 
! static tree
! lto_read_enumerator_DIE (lto_info_fd *fd,
! 			 const DWARF2_abbrev *abbrev,
! 			 lto_context *context)
! {
!   tree name = NULL_TREE;
!   tree value = NULL_TREE;
! 
!   /* FIXME:  enumerators have integer type in C, but in C++ they may have
!      bigger values.  What about other languages?  Probably should pass in
!      base type from the parent enumeration type.  */
!   tree type = integer_type_node;
! 
!   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_const_value:
!       value = build_int_cst (type, (int64_t)attr_data.u.constant);
!       break;
!     }
!   LTO_END_READ_ATTRS ();
! 
!   lto_read_child_DIEs (fd, abbrev, context);
! 
!   /* Return a TREE_LIST with the name as TREE_PURPOSE and the value as
!      TREE_VALUE.  */
!   return tree_cons (name, value, NULL_TREE);
! }
! 
! static tree
  lto_read_variable_formal_parameter_constant_DIE (lto_info_fd *fd,
  						 const DWARF2_abbrev *abbrev,
  						 lto_context *context)
*************** lto_read_variable_formal_parameter_const
*** 1321,1334 ****
  			      /*at_end=*/0);
  
    lto_read_child_DIEs (fd, abbrev, context);
  }
  
! static void
  lto_read_pointer_type_DIE (lto_info_fd *fd,
  			   const DWARF2_abbrev *abbrev,
  			   lto_context *context)
  {
!   tree pointed_to;
    tree type;
  
    LTO_BEGIN_READ_ATTRS ()
--- 1615,1629 ----
  			      /*at_end=*/0);
  
    lto_read_child_DIEs (fd, abbrev, context);
+   return decl;
  }
  
! static tree
  lto_read_pointer_type_DIE (lto_info_fd *fd,
  			   const DWARF2_abbrev *abbrev,
  			   lto_context *context)
  {
!   tree pointed_to = NULL_TREE;
    tree type;
  
    LTO_BEGIN_READ_ATTRS ()
*************** lto_read_pointer_type_DIE (lto_info_fd *
*** 1352,1364 ****
      lto_file_corrupt_error ((lto_fd *)fd);
    /* Build the pointer type.  */
    type = build_pointer_type (pointed_to);
-   /* Record the type for our caller.  */
-   context->type = type;
  
    lto_read_child_DIEs (fd, abbrev, context);
  }
  
! static void
  lto_read_base_type_DIE (lto_info_fd *fd, 
  			const DWARF2_abbrev *abbrev,
  			lto_context *context)
--- 1647,1781 ----
      lto_file_corrupt_error ((lto_fd *)fd);
    /* Build the pointer type.  */
    type = build_pointer_type (pointed_to);
  
    lto_read_child_DIEs (fd, abbrev, context);
+   return type;
  }
  
! static tree
! lto_read_subrange_type_DIE (lto_info_fd *fd,
! 			    const DWARF2_abbrev *abbrev,
! 			    lto_context *context)
! {
!   tree type;
!   tree base = NULL;
!   int byte_size = 0;
!   bool got_byte_size = false;
!   uint64_t lower = 0;
!   uint64_t upper = 0;
!   uint64_t count = 0;
!   bool got_lower = false;
!   bool got_upper = false;
!   bool got_count = false;
!   tree lower_bound, upper_bound;
! 
!   LTO_BEGIN_READ_ATTRS ()
!     {
!     case DW_AT_decl_column:
!     case DW_AT_decl_file:
!     case DW_AT_decl_line:
!       /* Ignore.  */
!       break;
! 
!     case DW_AT_type:
!       base = lto_read_referenced_type_DIE (fd, 
! 					   context, 
! 					   attr_data.u.reference);
!       break;
! 
!     case DW_AT_byte_size:
!       if (attr_data.cl != DW_cl_constant)
! 	lto_abi_mismatch_error ();
!       byte_size = attr_data.u.constant;
!       got_byte_size = true;
!       break;
! 
!     case DW_AT_lower_bound:
!       if (attr_data.cl != DW_cl_constant)
! 	lto_unsupported_attr_error (abbrev, attr);
!       got_lower = true;
!       lower = attr_data.u.constant;
!       break;
! 
!     case DW_AT_upper_bound:
!       if (attr_data.cl != DW_cl_constant)
! 	lto_unsupported_attr_error (abbrev, attr);
!       got_upper = true;
!       upper = attr_data.u.constant;
!       break;
! 
!     case DW_AT_count:
!       if (attr_data.cl != DW_cl_constant)
! 	lto_unsupported_attr_error (abbrev, attr);
!       got_count = true;
!       count = attr_data.u.constant;
!       break;
! 
!     case DW_AT_threads_scaled:
!     case DW_AT_stride:
!       lto_unsupported_attr_error (abbrev, attr);
!     }
!   LTO_END_READ_ATTRS ();
! 
!   /* Reconcile base type and byte size attributes.  */
!   base = lto_find_integral_type (base, byte_size, got_byte_size);
! 
!   /* Lower bound can be omitted if there is a language-specific default.  */
!   if (!got_lower)
!     {
!       switch (context->language)
! 	{
! 	case DW_LANG_C89:
! 	case DW_LANG_C:
! 	case DW_LANG_C_plus_plus:
! 	case DW_LANG_C99:
! 	  lower = 0;
! 	  break;
! 
! 	case DW_LANG_Fortran77:
! 	case DW_LANG_Fortran90:
! 	case DW_LANG_Fortran95:
! 	  lower = 1;
! 	  break;
! 
! 	default:
! 	  /* No other default lower bound values are currently defined.  */
! 	  lto_file_corrupt_error ((lto_fd *)fd);
! 	}
!     }
! 
!   /* At most one of count and upper bound can be specified.  If we got count,
!      use it to compute the upper bound.  */
!   if (got_count)
!     {
!       if (got_upper)
! 	lto_file_corrupt_error ((lto_fd *)fd);
!       upper = lower + count - 1;
!       got_upper = true;
!     }
! 
!   /* Convert the bound constants to tree values, being careful to maintain
!      the signed-ness appropriate for the base type.  */
!   if (TYPE_UNSIGNED (base))
!     lower_bound = build_int_cstu (base, lower);
!   else
!     lower_bound = build_int_cst (base, (int64_t)lower);
! 
!   if (!got_upper)
!     upper_bound = NULL;
!   else if (TYPE_UNSIGNED (base))
!     upper_bound = build_int_cstu (base, upper);
!   else
!     upper_bound = build_int_cst (base, (int64_t)upper);
! 
!   /* Build the range type, and record it for our caller.  */
!   type = build_range_type (base, lower_bound, upper_bound);
! 
!   lto_read_child_DIEs (fd, abbrev, context);
!   return type;
! }
! 
! static tree
  lto_read_base_type_DIE (lto_info_fd *fd, 
  			const DWARF2_abbrev *abbrev,
  			lto_context *context)
*************** lto_read_base_type_DIE (lto_info_fd *fd,
*** 1408,1414 ****
      }
    LTO_END_READ_ATTRS ();
  
!   if (!name || !have_encoding || !have_size)
      lto_file_corrupt_error ((lto_fd *)fd);
  
    lto_read_child_DIEs (fd, abbrev, context);
--- 1825,1831 ----
      }
    LTO_END_READ_ATTRS ();
  
!   if (!have_encoding || !have_size)
      lto_file_corrupt_error ((lto_fd *)fd);
  
    lto_read_child_DIEs (fd, abbrev, context);
*************** lto_read_base_type_DIE (lto_info_fd *fd,
*** 1431,1438 ****
        sorry ("unsupported base type encoding");
        break;
      }
!   /* If this is a new type, declare it.  */
!   if (!TYPE_NAME (type))
      {
        tree decl;
        decl = build_decl (TYPE_DECL, name, type);
--- 1848,1860 ----
        sorry ("unsupported base type encoding");
        break;
      }
!   /* If this is a new type, declare it.
!      The DWARF spec seems to imply that the name attribute is required,
!      but GCC generates base_type DIEs without names in some cases (e.g.,
!      for the referenced type of the subrange type used as an array
!      subscript).  Accept that without complaining by just skipping making
!      the declaration.  */
!   if (name && !TYPE_NAME (type))
      {
        tree decl;
        decl = build_decl (TYPE_DECL, name, type);
*************** lto_read_base_type_DIE (lto_info_fd *fd,
*** 1443,1470 ****
  				/*at_end=*/0);
      }
   
!   /* Record the type for our caller.  */
!   context->type = type;
  }
  
  /* Read the next DIE from FD.  CONTEXT provides information about the
!    current state of the compilation unit.  Returns true iff there was
!    a real DIE present; false if the DIE was a null entry indicating
!    the end of a list of sibling DIEs.  */
! static bool
! lto_read_DIE (lto_info_fd *fd, lto_context *context)
  {
!   typedef void (*DIE_reader_fnptr)(lto_info_fd * fd,
  				   const DWARF2_abbrev *abbrev,
  				   lto_context *context);
    /* Reader functions for the tags defined by DWARF 3.  */
    static const DIE_reader_fnptr readers[DW_TAG_shared_type + 1] = 
      {
        NULL, /* padding */
!       NULL, /* array_type */
        NULL, /* class_type */
        NULL, /* entry_point */
!       NULL, /* enumeration_type */
        lto_read_variable_formal_parameter_constant_DIE,
        NULL, /* padding */
        NULL, /* padding */
--- 1865,1892 ----
  				/*at_end=*/0);
      }
   
!   return type;
  }
  
  /* Read the next DIE from FD.  CONTEXT provides information about the
!    current state of the compilation unit.  Returns a (possibly null) TREE
!    representing the DIE read.  If more is non-NULL, *more is set to true
!    iff there was a real DIE present; false if the DIE was a null entry
!    indicating the end of a list of sibling DIEs.  */
! static tree
! lto_read_DIE (lto_info_fd *fd, lto_context *context, bool *more)
  {
!   typedef tree (*DIE_reader_fnptr)(lto_info_fd * fd,
  				   const DWARF2_abbrev *abbrev,
  				   lto_context *context);
    /* Reader functions for the tags defined by DWARF 3.  */
    static const DIE_reader_fnptr readers[DW_TAG_shared_type + 1] = 
      {
        NULL, /* padding */
!       lto_read_array_type_DIE, /* array_type */
        NULL, /* class_type */
        NULL, /* entry_point */
!       lto_read_enumeration_type_DIE, /* enumeration_type */
        lto_read_variable_formal_parameter_constant_DIE,
        NULL, /* padding */
        NULL, /* padding */
*************** lto_read_DIE (lto_info_fd *fd, lto_conte
*** 1493,1506 ****
        NULL, /* module */
        NULL, /* ptr_to_member_type */
        NULL, /* set_type */
!       NULL, /* subrange_type */
        NULL, /* with_stmt */
        NULL, /* access_declaration */
        lto_read_base_type_DIE,
        NULL, /* catch_block */
        NULL, /* const_type */
        lto_read_variable_formal_parameter_constant_DIE,
!       NULL, /* enumerator */
        NULL, /* file_type */
        NULL, /* friend */
        NULL, /* namelist */
--- 1915,1928 ----
        NULL, /* module */
        NULL, /* ptr_to_member_type */
        NULL, /* set_type */
!       lto_read_subrange_type_DIE, /* subrange_type */
        NULL, /* with_stmt */
        NULL, /* access_declaration */
        lto_read_base_type_DIE,
        NULL, /* catch_block */
        NULL, /* const_type */
        lto_read_variable_formal_parameter_constant_DIE,
!       lto_read_enumerator_DIE,
        NULL, /* file_type */
        NULL, /* friend */
        NULL, /* namelist */
*************** lto_read_DIE (lto_info_fd *fd, lto_conte
*** 1537,1561 ****
    /* Record the location of the current DIE -- before we change the
       file pointer.  */
    die = ((lto_fd *)fd)->cur;
-   /* This DIE is not yet known to be a type.  */
-   context->type = NULL_TREE;
    /* Read the abbreviation index.  */
    index = lto_read_uleb128 ((lto_fd *)fd);
    /* Zero indicates a null entry.  */
    if (!index)
!     return false; 
    /* 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)
!     {
!       if (TYPE_P (val))
! 	context->type = val;
!     }
!   else
      {
        /* Determine the DIE reader function.  */
        reader = NULL;
--- 1959,1980 ----
    /* Record the location of the current DIE -- before we change the
       file pointer.  */
    die = ((lto_fd *)fd)->cur;
    /* Read the abbreviation index.  */
    index = lto_read_uleb128 ((lto_fd *)fd);
    /* Zero indicates a null entry.  */
    if (!index)
!     {
!       if (more)
! 	*more = false;
!       return NULL_TREE;
!     }
    /* 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.  */
        reader = NULL;
*************** lto_read_DIE (lto_info_fd *fd, lto_conte
*** 1564,1578 ****
        if (reader)
  	{
  	  /* If there is a reader, use it.  */
! 	  reader (fd, abbrev, context);
  	  /* If this DIE refers to a type, cache the value so that future
  	     references to the type can be processed quickly.  */
! 	  if (context->type)
! 	    lto_cache_store_DIE (fd, die, context->type);
  	  skip = false;
  	}
        else
! 	/* Aassume 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 "
--- 1983,1997 ----
        if (reader)
  	{
  	  /* If there is a reader, use it.  */
! 	  val = reader (fd, abbrev, context);
  	  /* If this DIE refers to a type, cache the value so that future
  	     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 "
*************** lto_read_DIE (lto_info_fd *fd, lto_conte
*** 1590,1596 ****
        lto_read_child_DIEs (fd, abbrev, context);
      }
  
!   return true;
  }
  
  /* Read the children of a DIE from FD, passing CONTEXT to the DIE readers
--- 2009,2017 ----
        lto_read_child_DIEs (fd, abbrev, context);
      }
  
!   if (more)
!     *more = true;
!   return val;
  }
  
  /* Read the children of a DIE from FD, passing CONTEXT to the DIE readers
*************** lto_read_DIE (lto_info_fd *fd, lto_conte
*** 1598,1604 ****
     read.  ABBREV indicates whether or not the DIE actually has
     children; if it does not, then this function returns without
     reading anything.  Therefore, it is always safe to call this
!    function from a DIE reader, after reading the DIE's attributes.  */
  static void
  lto_read_child_DIEs (lto_info_fd *fd, 
  		     const DWARF2_abbrev *abbrev,
--- 2019,2028 ----
     read.  ABBREV indicates whether or not the DIE actually has
     children; if it does not, then this function returns without
     reading anything.  Therefore, it is always safe to call this
!    function from a DIE reader, after reading the DIE's attributes.
!    This function simply discards the tree valued returned by lto_read_DIE
!    for each child.
! */
  static void
  lto_read_child_DIEs (lto_info_fd *fd, 
  		     const DWARF2_abbrev *abbrev,
*************** lto_read_child_DIEs (lto_info_fd *fd, 
*** 1608,1618 ****
      {
        bool more;
        do 
! 	more = lto_read_DIE (fd, context);
        while (more);
      }
  }
  
  /* Read all the DWARF2 compile units from INFO_FD, placing them in
     INFO_FD->UNITS.  */
  static void
--- 2032,2067 ----
      {
        bool more;
        do 
! 	lto_read_DIE (fd, context, &more);
        while (more);
      }
  }
  
+ /* This function is similar to lto_read_child_DIEs but collects the tree
+    values from reading each child into a heap-allocated VEC, which is
+    returned.
+ */
+ static VEC(tree,heap) *
+ lto_collect_child_DIEs (lto_info_fd *fd, 
+ 			const DWARF2_abbrev *abbrev,
+ 			lto_context *context)
+ {
+   VEC(tree,heap) *result = VEC_alloc (tree, heap, 32);
+   if (abbrev->has_children)
+     {
+       bool more;
+       do
+ 	{
+ 	  tree val = lto_read_DIE (fd, context, &more);
+ 	  if (more)
+ 	    VEC_safe_push (tree, heap, result, val);
+ 	}
+       while (more);
+     }
+   return result;
+ }
+ 
+ 
  /* Read all the DWARF2 compile units from INFO_FD, placing them in
     INFO_FD->UNITS.  */
  static void
*************** lto_file_read (lto_file *file)
*** 1713,1723 ****
        lto_set_cu_context (&context, &file->debug_info, unit);
        fd->cur = context.cu_start + unit->cu_header_length;
        context.scope = NULL_TREE;
-       context.type = NULL_TREE;
  
        /* Read DIEs.  */
        while (fd->cur < context.cu_end)
! 	lto_read_DIE (&file->debug_info, &context);
      }
  
    return true;
--- 2162,2171 ----
        lto_set_cu_context (&context, &file->debug_info, unit);
        fd->cur = context.cu_start + unit->cu_header_length;
        context.scope = NULL_TREE;
  
        /* Read DIEs.  */
        while (fd->cur < context.cu_end)
! 	lto_read_DIE (&file->debug_info, &context, NULL);
      }
  
    return true;

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