PATCH: reorganize layout of RECORD_TYPEs

Mark Mitchell mark@codesourcery.com
Mon Mar 13 01:14:00 GMT 2000


This patch breaks up some functions in stor-layout.c, in order to
provide entry-points callable from a front-end to handle class layout.
In particular, the C++ front-end needs to be able to layout fields
depending on the placement of previous fields in the structure.  By
allowing the front-end to access the class-layout machinery before all
the FIELD_DECLs are in place, we can accomplish this cleanly.

There's really no new code here, nor any substantive changes -- just
breaking apart of functions.  As a side-effect, the layout code became
a good deal more readable.

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

2000-03-13  Mark Mitchell  <mark@codesourcery.com>

	* tree.h (record_layout_info_s): New structure.
	(record_layout_info): New type.
	(new_record_layout_info): New function.
	(layout_field): Likewise.
	(finish_record_layout): Likewise.
	* stor-layout.c (layout_record): Remove.
	(new_record_layout_info): New function.
	(layout_field): New function, broken out from layout_record.
	(finalize_record_size): Likewise.
	(compute_record_mode): Likewise.
	(finalize_type_size): New function, broken out from layout_type.
	(finish_record_layout): Likewise.
	(layout_type): Use them.
	
Index: stor-layout.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/stor-layout.c,v
retrieving revision 1.53
diff -c -p -r1.53 stor-layout.c
*** stor-layout.c	2000/03/07 11:41:19	1.53
--- stor-layout.c	2000/03/13 09:08:14
*************** unsigned int maximum_field_alignment;
*** 50,56 ****
     May be overridden by front-ends.  */
  unsigned int set_alignment = 0;
  
- static tree layout_record	PARAMS ((tree));
  static void layout_union	PARAMS ((tree));
  
  /* SAVE_EXPRs for sizes of types and decls, waiting to be expanded.  */
--- 50,55 ----
*************** layout_decl (decl, known_align)
*** 400,742 ****
      }
  }
  
! /* Lay out a RECORD_TYPE type (a C struct).
!    This means laying out the fields, determining their positions,
!    and computing the overall size and required alignment of the record.
!    Note that if you set the TYPE_ALIGN before calling this
!    then the struct is aligned to at least that boundary.
! 
!    If the type has basetypes, you must call layout_basetypes
!    before calling this function.
! 
!    The return value is a list of static members of the record.
!    They still need to be laid out.  */
! 
! static tree
! layout_record (rec)
!      tree rec;
  {
!   register tree field;
!   unsigned int record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (rec));
!   unsigned int unpacked_align = record_align;
!   /* These must be laid out *after* the record is.  */
!   tree pending_statics = NULL_TREE;
!   /* Record size so far is CONST_SIZE + VAR_SIZE bits,
!      where CONST_SIZE is an integer
!      and VAR_SIZE is a tree expression.
!      If VAR_SIZE is null, the size is just CONST_SIZE.
!      Naturally we try to avoid using VAR_SIZE.  */
!   unsigned HOST_WIDE_INT const_size = 0;
!   tree var_size = 0;
!   /* Once we start using VAR_SIZE, this is the maximum alignment
!      that we know VAR_SIZE has.  */
!   unsigned int var_align = BITS_PER_UNIT;
!   int packed_maybe_necessary = 0;
  
  #ifdef STRUCTURE_SIZE_BOUNDARY
    /* Packed structures don't need to have minimum size.  */
    if (! TYPE_PACKED (rec))
!     record_align = MAX (record_align, STRUCTURE_SIZE_BOUNDARY);
  #endif
  
!   for (field = TYPE_FIELDS (rec); field; field = TREE_CHAIN (field))
!     {
!       unsigned int known_align = var_size ? var_align : const_size;
!       unsigned int desired_align = 0;
!       tree type = TREE_TYPE (field);
! 
!       /* If FIELD is static, then treat it like a separate variable,
! 	 not really like a structure field.
! 	 If it is a FUNCTION_DECL, it's a method.
! 	 In both cases, all we do is lay out the decl,
! 	 and we do it *after* the record is laid out.  */
  
!       if (TREE_CODE (field) == VAR_DECL)
! 	{
! 	  pending_statics = tree_cons (NULL_TREE, field, pending_statics);
! 	  continue;
! 	}
  
!       /* Enumerators and enum types which are local to this class need not
! 	 be laid out.  Likewise for initialized constant fields.  */
!       if (TREE_CODE (field) != FIELD_DECL)
! 	continue;
  
!       /* Lay out the field so we know what alignment it needs.
! 	 For a packed field, use the alignment as specified,
! 	 disregarding what the type would want.  */
!       if (DECL_PACKED (field))
! 	desired_align = DECL_ALIGN (field);
!       layout_decl (field, known_align);
!       if (! DECL_PACKED (field))
! 	desired_align = DECL_ALIGN (field);
!       /* Some targets (i.e. VMS) limit struct field alignment
! 	 to a lower boundary than alignment of variables.  */
  #ifdef BIGGEST_FIELD_ALIGNMENT
!       desired_align = MIN (desired_align, BIGGEST_FIELD_ALIGNMENT);
  #endif
  #ifdef ADJUST_FIELD_ALIGN
!       desired_align = ADJUST_FIELD_ALIGN (field, desired_align);
  #endif
- 
-       /* Record must have at least as much alignment as any field.
- 	 Otherwise, the alignment of the field within the record
- 	 is meaningless.  */
  
  #ifdef PCC_BITFIELD_TYPE_MATTERS
!       if (PCC_BITFIELD_TYPE_MATTERS && type != error_mark_node
! 	  && DECL_BIT_FIELD_TYPE (field)
! 	  && ! integer_zerop (TYPE_SIZE (type)))
  	{
! 	  /* For these machines, a zero-length field does not
! 	     affect the alignment of the structure as a whole.
! 	     It does, however, affect the alignment of the next field
! 	     within the structure.  */
! 	  if (! integer_zerop (DECL_SIZE (field)))
! 	    record_align = MAX (record_align, desired_align);
! 	  else if (! DECL_PACKED (field))
! 	    desired_align = TYPE_ALIGN (type);
! 	  /* A named bit field of declared type `int'
! 	     forces the entire structure to have `int' alignment.  */
! 	  if (DECL_NAME (field) != 0)
! 	    {
! 	      unsigned int type_align = TYPE_ALIGN (type);
  
! 	      if (maximum_field_alignment != 0)
! 		type_align = MIN (type_align, maximum_field_alignment);
! 	      else if (DECL_PACKED (field))
! 		type_align = MIN (type_align, BITS_PER_UNIT);
! 
! 	      record_align = MAX (record_align, type_align);
! 	      if (warn_packed)
! 		unpacked_align = MAX (unpacked_align, TYPE_ALIGN (type));
! 	    }
! 	}
!       else
! #endif
! 	{
! 	  record_align = MAX (record_align, desired_align);
  	  if (warn_packed)
! 	    unpacked_align = MAX (unpacked_align, TYPE_ALIGN (type));
  	}
  
!       if (warn_packed && DECL_PACKED (field))
  	{
! 	  if (const_size % TYPE_ALIGN (type) == 0
! 	      || (var_align % TYPE_ALIGN (type) == 0 && var_size != NULL_TREE))
  	    {
! 	      if (TYPE_ALIGN (type) > desired_align)
! 		{
! 		  if (STRICT_ALIGNMENT)
! 		    warning_with_decl (field, "packed attribute causes inefficient alignment for `%s'");
! 		  else
! 		    warning_with_decl (field, "packed attribute is unnecessary for `%s'");
! 		}
  	    }
- 	  else
- 	    packed_maybe_necessary = 1;
  	}
! 
!       /* Does this field automatically have alignment it needs
! 	 by virtue of the fields that precede it and the record's
! 	 own alignment?  */
  
!       if (const_size % desired_align != 0
! 	  || (var_align % desired_align != 0 && var_size != NULL_TREE))
! 	{
! 	  /* No, we need to skip space before this field.
! 	     Bump the cumulative size to multiple of field alignment.  */
  
! 	  if (warn_padded)
! 	    warning_with_decl (field, "padding struct to align `%s'");
  
! 	  if (var_size == NULL_TREE || var_align % desired_align == 0)
! 	    const_size
! 	      = CEIL (const_size, desired_align) * desired_align;
! 	  else
! 	    {
! 	      if (const_size > 0)
! 		var_size = size_binop (PLUS_EXPR, var_size,
! 				       bitsize_int (const_size));
! 	      const_size = 0;
! 	      var_size = round_up (var_size, desired_align);
! 	      var_align = MIN (var_align, desired_align);
! 	    }
  	}
  
  #ifdef PCC_BITFIELD_TYPE_MATTERS
!       if (PCC_BITFIELD_TYPE_MATTERS
! 	  && TREE_CODE (field) == FIELD_DECL
! 	  && type != error_mark_node
! 	  && DECL_BIT_FIELD_TYPE (field)
! 	  && !DECL_PACKED (field)
! 	  && maximum_field_alignment == 0
! 	  && !integer_zerop (DECL_SIZE (field)))
! 	{
! 	  unsigned int type_align = TYPE_ALIGN (type);
! 	  register tree dsize = DECL_SIZE (field);
! 	  unsigned int field_size = TREE_INT_CST_LOW (dsize);
! 
! 	  /* A bit field may not span more units of alignment of its type
! 	     than its type itself.  Advance to next boundary if necessary.  */
! 	  if (((const_size + field_size + type_align - 1) / type_align
! 	       - const_size / type_align)
! 	      > TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (field))) / type_align)
! 	    const_size = CEIL (const_size, type_align) * type_align;
! 	}
  #endif
  
! /* No existing machine description uses this parameter.
!    So I have made it in this aspect identical to PCC_BITFIELD_TYPE_MATTERS.  */
  #ifdef BITFIELD_NBYTES_LIMITED
!       if (BITFIELD_NBYTES_LIMITED
! 	  && TREE_CODE (field) == FIELD_DECL
! 	  && type != error_mark_node
! 	  && DECL_BIT_FIELD_TYPE (field)
! 	  && !DECL_PACKED (field)
! 	  && !integer_zerop (DECL_SIZE (field)))
! 	{
! 	  unsigned int type_align = TYPE_ALIGN (type);
! 	  register tree dsize = DECL_SIZE (field);
! 	  int field_size = TREE_INT_CST_LOW (dsize);
! 
! 	  if (maximum_field_alignment != 0)
! 	    type_align = MIN (type_align, maximum_field_alignment);
! 	  /* ??? This test is opposite the test in the containing if
! 	     statement, so this code is unreachable currently.  */
! 	  else if (DECL_PACKED (field))
! 	    type_align = MIN (type_align, BITS_PER_UNIT);
  
! 	  /* A bit field may not span the unit of alignment of its type.
! 	     Advance to next boundary if necessary.  */
! 	  /* ??? This code should match the code above for the
! 	     PCC_BITFIELD_TYPE_MATTERS case.  */
! 	  if (const_size / type_align
! 	      != (const_size + field_size - 1) / type_align)
! 	    const_size = CEIL (const_size, type_align) * type_align;
! 	}
  #endif
  
!       /* Size so far becomes the position of this field.  */
  
!       if (var_size && const_size)
! 	DECL_FIELD_BITPOS (field)
! 	  = size_binop (PLUS_EXPR, var_size, bitsize_int (const_size));
!       else if (var_size)
! 	DECL_FIELD_BITPOS (field) = var_size;
!       else
! 	{
! 	  DECL_FIELD_BITPOS (field) = bitsize_int (const_size);
! 
! 	  /* If this field ended up more aligned than we thought it
! 	     would be (we approximate this by seeing if its position
! 	     changed), lay out the field again; perhaps we can use an
! 	     integral mode for it now.  */
! 	  if (known_align != const_size)
! 	    layout_decl (field, const_size);
! 	}
  
!       /* Now add size of this field to the size of the record.  */
  
!       {
!         register tree dsize = DECL_SIZE (field);
  
! 	/* This can happen when we have an invalid nested struct definition,
! 	   such as struct j { struct j { int i; } }.  The error message is
! 	   printed in finish_struct.  */
! 	if (dsize == 0)
! 	  /* Do nothing.  */;
! 	else if (TREE_CODE (dsize) == INTEGER_CST
! 		 && ! TREE_CONSTANT_OVERFLOW (dsize)
! 		 && TREE_INT_CST_HIGH (dsize) == 0
! 		 && TREE_INT_CST_LOW (dsize) + const_size >= const_size)
! 	  /* Use const_size if there's no overflow.  */
! 	  const_size += TREE_INT_CST_LOW (dsize);
! 	else
! 	  {
! 	    if (var_size == NULL_TREE)
! 	      var_size = dsize;
! 	    else
! 	      var_size = size_binop (PLUS_EXPR, var_size, dsize);
! 	  }
!       }
      }
  
!   /* Work out the total size and alignment of the record
!      as one expression and store in the record type.
!      Round it up to a multiple of the record's alignment.  */
  
!   if (var_size == NULL_TREE)
!     TYPE_SIZE (rec) = bitsize_int (const_size);
    else
      {
!       if (const_size)
! 	var_size = size_binop (PLUS_EXPR, var_size, bitsize_int (const_size));
! 
!       TYPE_SIZE (rec) = var_size;
      }
  
    /* Determine the desired alignment.  */
  #ifdef ROUND_TYPE_ALIGN
!   TYPE_ALIGN (rec) = ROUND_TYPE_ALIGN (rec, TYPE_ALIGN (rec), record_align);
  #else
!   TYPE_ALIGN (rec) = MAX (TYPE_ALIGN (rec), record_align);
  #endif
  
    /* Record the un-rounded size in the binfo node.  But first we check
       the size of TYPE_BINFO to make sure that BINFO_SIZE is available.  */
!   if (TYPE_BINFO (rec) && TREE_VEC_LENGTH (TYPE_BINFO (rec)) > 6)
      {
!       TYPE_BINFO_SIZE (rec) = TYPE_SIZE (rec);
!       TYPE_BINFO_SIZE_UNIT (rec)
  	= convert (sizetype,
! 		   size_binop (FLOOR_DIV_EXPR, TYPE_SIZE (rec),
  			       bitsize_int (BITS_PER_UNIT)));
      }
    
    {
!     tree unpadded_size = TYPE_SIZE (rec);
  
  #ifdef ROUND_TYPE_SIZE
!     TYPE_SIZE (rec) = ROUND_TYPE_SIZE (rec, TYPE_SIZE (rec), TYPE_ALIGN (rec));
  #else
      /* Round the size up to be a multiple of the required alignment */
!     TYPE_SIZE (rec) = round_up (TYPE_SIZE (rec), TYPE_ALIGN (rec));
  #endif
  
!     if (warn_padded && var_size == NULL_TREE
! 	&& simple_cst_equal (unpadded_size, TYPE_SIZE (rec)) == 0)
        warning ("padding struct size to alignment boundary");
    }
    
!   if (warn_packed && TYPE_PACKED (rec) && !packed_maybe_necessary
!       && var_size == NULL_TREE)
      {
        tree unpacked_size;
  
!       TYPE_PACKED (rec) = 0;
  #ifdef ROUND_TYPE_ALIGN
!       unpacked_align
! 	= ROUND_TYPE_ALIGN (rec, TYPE_ALIGN (rec), unpacked_align);
  #else
!       unpacked_align = MAX (TYPE_ALIGN (rec), unpacked_align);
  #endif
  #ifdef ROUND_TYPE_SIZE
!       unpacked_size = ROUND_TYPE_SIZE (rec, TYPE_SIZE (rec), unpacked_align);
  #else
!       unpacked_size = round_up (TYPE_SIZE (rec), unpacked_align);
  #endif
  
!       if (simple_cst_equal (unpacked_size, TYPE_SIZE (rec)))
  	{
! 	  if (TYPE_NAME (rec))
  	    {
  	      char *name;
  
! 	      if (TREE_CODE (TYPE_NAME (rec)) == IDENTIFIER_NODE)
! 		name = IDENTIFIER_POINTER (TYPE_NAME (rec));
  	      else
! 		name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (rec)));
  	      if (STRICT_ALIGNMENT)
  		warning ("packed attribute causes inefficient alignment for `%s'", name);
  	      else
--- 399,751 ----
      }
  }
  
! /* Create a new record_layout_info for the RECORD_TYPE T.  It is the
!    responsibility of the caller to call `free' for the storage the
!    returned.  */
! 
! record_layout_info
! new_record_layout_info (t)
!      tree t;
  {
!   record_layout_info rli 
!     = (record_layout_info) xcalloc (1, sizeof (struct record_layout_info_s));
! 
!   rli->t = t;
!   /* If the type has a minimum specified alignment (via an attribute
!      declaration, for example) use it -- otherwise, start with a
!      one-byte alignment.  */
!   rli->record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (t));
!   rli->unpacked_align = rli->record_align;
  
  #ifdef STRUCTURE_SIZE_BOUNDARY
    /* Packed structures don't need to have minimum size.  */
    if (! TYPE_PACKED (rec))
!     rli->record_align = MAX (rli->record_align, STRUCTURE_SIZE_BOUNDARY);
  #endif
  
!   return rli;
! }
  
! /* RLI contains information about the layout of a RECORD_TYPE.  FIELD
!    is a FIELD_DECL to be added after those fields already present in
!    T.  (FIELD is not actually added to the TYPE_FIELDS list here;
!    callers that desire that behavior must manually perform that step.)  */
  
! void
! layout_field (rli, field)
!      record_layout_info rli;
!      tree field;
! {
!   /* The alignment required for FIELD.  */
!   unsigned int desired_align;
!   /* The alignment FIELD would have if we just dropped it into the
!      record as it presently stands.  */
!   unsigned int known_align;
!   /* The type of this field.  */
!   tree type = TREE_TYPE (field);
!   /* The size of this field, in bits.  */
!   tree dsize;
! 
!   /* If FIELD is static, then treat it like a separate variable, not
!      really like a structure field.  If it is a FUNCTION_DECL, it's a
!      method.  In both cases, all we do is lay out the decl, and we do
!      it *after* the record is laid out.  */
!   if (TREE_CODE (field) == VAR_DECL)
!     {
!       rli->pending_statics = tree_cons (NULL_TREE, field,
! 					rli->pending_statics);
!       return;
!     }
!   /* Enumerators and enum types which are local to this class need not
!      be laid out.  Likewise for initialized constant fields.  */
!   else if (TREE_CODE (field) != FIELD_DECL)
!     return;
  
!   /* Work out the known alignment so far.  */
!   known_align = rli->var_size ? rli->var_align : rli->const_size;
! 
!   /* Lay out the field so we know what alignment it needs.  For a
!      packed field, use the alignment as specified, disregarding what
!      the type would want.  */
!   if (DECL_PACKED (field))
!     desired_align = DECL_ALIGN (field);
!   layout_decl (field, known_align);
!   if (! DECL_PACKED (field))
!     desired_align = DECL_ALIGN (field);
!   /* Some targets (i.e. VMS) limit struct field alignment
!      to a lower boundary than alignment of variables.  */
  #ifdef BIGGEST_FIELD_ALIGNMENT
!   desired_align = MIN (desired_align, BIGGEST_FIELD_ALIGNMENT);
  #endif
  #ifdef ADJUST_FIELD_ALIGN
!   desired_align = ADJUST_FIELD_ALIGN (field, desired_align);
  #endif
  
+   /* Record must have at least as much alignment as any field.
+      Otherwise, the alignment of the field within the record is
+      meaningless.  */
  #ifdef PCC_BITFIELD_TYPE_MATTERS
!   if (PCC_BITFIELD_TYPE_MATTERS && type != error_mark_node
!       && DECL_BIT_FIELD_TYPE (field)
!       && ! integer_zerop (TYPE_SIZE (type)))
!     {
!       /* For these machines, a zero-length field does not
! 	 affect the alignment of the structure as a whole.
! 	 It does, however, affect the alignment of the next field
! 	 within the structure.  */
!       if (! integer_zerop (DECL_SIZE (field)))
! 	rli->record_align = MAX (rli->record_align, desired_align);
!       else if (! DECL_PACKED (field))
! 	desired_align = TYPE_ALIGN (type);
!       /* A named bit field of declared type `int'
! 	 forces the entire structure to have `int' alignment.  */
!       if (DECL_NAME (field) != 0)
  	{
! 	  unsigned int type_align = TYPE_ALIGN (type);
  
! 	  if (maximum_field_alignment != 0)
! 	    type_align = MIN (type_align, maximum_field_alignment);
! 	  else if (DECL_PACKED (field))
! 	    type_align = MIN (type_align, BITS_PER_UNIT);
! 
! 	  rli->record_align = MAX (rli->record_align, type_align);
  	  if (warn_packed)
! 	    rli->unpacked_align = MAX (rli->unpacked_align, 
! 				       TYPE_ALIGN (type));
  	}
+     }
+   else
+ #endif
+     {
+       rli->record_align = MAX (rli->record_align, desired_align);
+       if (warn_packed)
+ 	rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type));
+     }
  
!   if (warn_packed && DECL_PACKED (field))
!     {
!       if (rli->const_size % TYPE_ALIGN (type) == 0
! 	  || (rli->var_align % TYPE_ALIGN (type) == 0 
! 	      && rli->var_size != NULL_TREE))
  	{
! 	  if (TYPE_ALIGN (type) > desired_align)
  	    {
! 	      if (STRICT_ALIGNMENT)
! 		warning_with_decl (field, "packed attribute causes inefficient alignment for `%s'");
! 	      else
! 		warning_with_decl (field, "packed attribute is unnecessary for `%s'");
  	    }
  	}
!       else
! 	rli->packed_maybe_necessary = 1;
!     }
  
!   /* Does this field automatically have alignment it needs by virtue
!      of the fields that precede it and the record's own alignment?  */
!   if (rli->const_size % desired_align != 0
!       || (rli->var_align % desired_align != 0 
! 	  && rli->var_size != NULL_TREE))
!     {
!       /* No, we need to skip space before this field.
! 	 Bump the cumulative size to multiple of field alignment.  */
  
!       if (warn_padded)
! 	warning_with_decl (field, "padding struct to align `%s'");
  
!       if (rli->var_size == NULL_TREE || rli->var_align % desired_align == 0)
! 	rli->const_size
! 	  = CEIL (rli->const_size, desired_align) * desired_align;
!       else
! 	{
! 	  if (rli->const_size > 0)
! 	    rli->var_size = size_binop (PLUS_EXPR, rli->var_size,
! 					bitsize_int (rli->const_size));
! 	  rli->const_size = 0;
! 	  rli->var_size = round_up (rli->var_size, desired_align);
! 	  rli->var_align = MIN (rli->var_align, desired_align);
  	}
+     }
  
  #ifdef PCC_BITFIELD_TYPE_MATTERS
!   if (PCC_BITFIELD_TYPE_MATTERS
!       && TREE_CODE (field) == FIELD_DECL
!       && type != error_mark_node
!       && DECL_BIT_FIELD_TYPE (field)
!       && !DECL_PACKED (field)
!       && maximum_field_alignment == 0
!       && !integer_zerop (DECL_SIZE (field)))
!     {
!       unsigned int type_align = TYPE_ALIGN (type);
!       register tree dsize = DECL_SIZE (field);
!       unsigned int field_size = TREE_INT_CST_LOW (dsize);
! 
!       /* A bit field may not span more units of alignment of its type
! 	 than its type itself.  Advance to next boundary if necessary.  */
!       if (((rli->const_size + field_size + type_align - 1) / type_align
! 	   - rli->const_size / type_align)
! 	  > TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (field))) / type_align)
! 	rli->const_size = CEIL (rli->const_size, type_align) * type_align;
!     }
  #endif
  
!   /* No existing machine description uses this parameter.  So I have
!      made it in this aspect identical to PCC_BITFIELD_TYPE_MATTERS.  */
  #ifdef BITFIELD_NBYTES_LIMITED
!   if (BITFIELD_NBYTES_LIMITED
!       && TREE_CODE (field) == FIELD_DECL
!       && type != error_mark_node
!       && DECL_BIT_FIELD_TYPE (field)
!       && !DECL_PACKED (field)
!       && !integer_zerop (DECL_SIZE (field)))
!     {
!       unsigned int type_align = TYPE_ALIGN (type);
!       register tree dsize = DECL_SIZE (field);
!       int field_size = TREE_INT_CST_LOW (dsize);
  
!       if (maximum_field_alignment != 0)
! 	type_align = MIN (type_align, maximum_field_alignment);
!       /* ??? This test is opposite the test in the containing if
! 	 statement, so this code is unreachable currently.  */
!       else if (DECL_PACKED (field))
! 	type_align = MIN (type_align, BITS_PER_UNIT);
! 
!       /* A bit field may not span the unit of alignment of its type.
! 	 Advance to next boundary if necessary.  */
!       /* ??? This code should match the code above for the
! 	 PCC_BITFIELD_TYPE_MATTERS case.  */
!       if (rli->const_size / type_align
! 	  != (rli->const_size + field_size - 1) / type_align)
! 	rli->const_size = CEIL (rli->const_size, type_align) * type_align;
!     }
  #endif
  
!   /* Size so far becomes the position of this field.  */
  
!   if (rli->var_size && rli->const_size)
!     DECL_FIELD_BITPOS (field)
!       = size_binop (PLUS_EXPR, rli->var_size, bitsize_int (rli->const_size));
!   else if (rli->var_size)
!     DECL_FIELD_BITPOS (field) = rli->var_size;
!   else
!     {
!       DECL_FIELD_BITPOS (field) = bitsize_int (rli->const_size);
  
!       /* If this field ended up more aligned than we thought it
! 	 would be (we approximate this by seeing if its position
! 	 changed), lay out the field again; perhaps we can use an
! 	 integral mode for it now.  */
!       if (known_align != rli->const_size)
! 	layout_decl (field, rli->const_size);
!     }
  
!   /* Now add size of this field to the size of the record.  */
!   dsize = DECL_SIZE (field);
  
!   /* This can happen when we have an invalid nested struct definition,
!      such as struct j { struct j { int i; } }.  The error message is
!      printed in finish_struct.  */
!   if (dsize == 0)
!     /* Do nothing.  */;
!   else if (TREE_CODE (dsize) == INTEGER_CST
! 	   && ! TREE_CONSTANT_OVERFLOW (dsize)
! 	   && TREE_INT_CST_HIGH (dsize) == 0
! 	   && TREE_INT_CST_LOW (dsize) + rli->const_size >= rli->const_size)
!     /* Use const_size if there's no overflow.  */
!     rli->const_size += TREE_INT_CST_LOW (dsize);
!   else
!     {
!       if (rli->var_size == NULL_TREE)
! 	rli->var_size = dsize;
!       else
! 	rli->var_size = size_binop (PLUS_EXPR, rli->var_size, dsize);
      }
+ }
  
! /* Assuming that all the fields have been laid out, this function uses
!    RLI to compute the final TYPE_SIZE, TYPE_ALIGN, etc. for the type
!    inidicated by RLI.  */
  
! static void
! finalize_record_size (rli)
!      record_layout_info rli;
! {
!   /* Work out the total size and alignment of the record as one
!      expression and store in the record type.  Round it up to a
!      multiple of the record's alignment.  */
!   if (rli->var_size == NULL_TREE)
!     TYPE_SIZE (rli->t) = bitsize_int (rli->const_size);
    else
      {
!       if (rli->const_size)
! 	rli->var_size = size_binop (PLUS_EXPR, rli->var_size,
! 				    bitsize_int (rli->const_size));
!       TYPE_SIZE (rli->t) = rli->var_size;
      }
  
    /* Determine the desired alignment.  */
  #ifdef ROUND_TYPE_ALIGN
!   TYPE_ALIGN (rli->t) = ROUND_TYPE_ALIGN (rli->t, TYPE_ALIGN (rli->t),
! 					  record_align);
  #else
!   TYPE_ALIGN (rli->t) = MAX (TYPE_ALIGN (rli->t), rli->record_align);
  #endif
  
    /* Record the un-rounded size in the binfo node.  But first we check
       the size of TYPE_BINFO to make sure that BINFO_SIZE is available.  */
!   if (TYPE_BINFO (rli->t) && TREE_VEC_LENGTH (TYPE_BINFO (rli->t)) > 6)
      {
!       TYPE_BINFO_SIZE (rli->t) = TYPE_SIZE (rli->t);
!       TYPE_BINFO_SIZE_UNIT (rli->t)
  	= convert (sizetype,
! 		   size_binop (FLOOR_DIV_EXPR, TYPE_SIZE (rli->t),
  			       bitsize_int (BITS_PER_UNIT)));
      }
    
    {
!     tree unpadded_size = TYPE_SIZE (rli->t);
  
  #ifdef ROUND_TYPE_SIZE
!     TYPE_SIZE (rli->t) = ROUND_TYPE_SIZE (rli->t, TYPE_SIZE (rli->t),
! 					  TYPE_ALIGN (rli->t));
  #else
      /* Round the size up to be a multiple of the required alignment */
!     TYPE_SIZE (rli->t) = round_up (TYPE_SIZE (rli->t), TYPE_ALIGN (rli->t));
  #endif
  
!     if (warn_padded && rli->var_size == NULL_TREE
! 	&& simple_cst_equal (unpadded_size, TYPE_SIZE (rli->t)) == 0)
        warning ("padding struct size to alignment boundary");
    }
    
!   if (warn_packed && TYPE_PACKED (rli->t) && !rli->packed_maybe_necessary
!       && rli->var_size == NULL_TREE)
      {
        tree unpacked_size;
  
!       TYPE_PACKED (rli->t) = 0;
  #ifdef ROUND_TYPE_ALIGN
!       rli->unpacked_align
! 	= ROUND_TYPE_ALIGN (rli->t, TYPE_ALIGN (rli->t), rli->unpacked_align);
  #else
!       rli->unpacked_align = MAX (TYPE_ALIGN (rli->t), rli->unpacked_align);
  #endif
  #ifdef ROUND_TYPE_SIZE
!       unpacked_size = ROUND_TYPE_SIZE (rli->t, TYPE_SIZE (rli->t),
! 				       rli->unpacked_align);
  #else
!       unpacked_size = round_up (TYPE_SIZE (rli->t), rli->unpacked_align);
  #endif
  
!       if (simple_cst_equal (unpacked_size, TYPE_SIZE (rli->t)))
  	{
! 	  if (TYPE_NAME (rli->t))
  	    {
  	      char *name;
  
! 	      if (TREE_CODE (TYPE_NAME (rli->t)) == IDENTIFIER_NODE)
! 		name = IDENTIFIER_POINTER (TYPE_NAME (rli->t));
  	      else
! 		name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (rli->t)));
  	      if (STRICT_ALIGNMENT)
  		warning ("packed attribute causes inefficient alignment for `%s'", name);
  	      else
*************** layout_record (rec)
*** 749,760 ****
  	      else
  		warning ("packed attribute is unnecessary");
  	    }
  	}
-       TYPE_PACKED (rec) = 1;
      }
  
!   return pending_statics;
  }
  
  /* Lay out a UNION_TYPE or QUAL_UNION_TYPE type.
     Lay out all the fields, set their positions to zero,
--- 758,950 ----
  	      else
  		warning ("packed attribute is unnecessary");
  	    }
+ 	}
+       TYPE_PACKED (rli->t) = 1;
+     }
+ }
+ 
+ /* Compute the TYPE_MODE for the TYPE (which is a RECORD_TYPE).  */
+ 
+ static void
+ compute_record_mode (type)
+      tree type;
+ {
+   /* Most RECORD_TYPEs have BLKmode, so we start off assuming that.
+      However, if possible, we use a mode that fits in a register
+      instead, in order to allow for better optimization down the
+      line.  */
+   TYPE_MODE (type) = BLKmode;
+   if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
+     {
+       tree field;
+       enum machine_mode mode = VOIDmode;
+ 
+       /* A record which has any BLKmode members must itself be
+ 	 BLKmode; it can't go in a register.  Unless the member is
+ 	 BLKmode only because it isn't aligned.  */
+       for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ 	{
+ 	  unsigned HOST_WIDE_INT bitpos;
+ 
+ 	  if (TREE_CODE (field) != FIELD_DECL
+ 	      || TREE_CODE (TREE_TYPE (field)) == ERROR_MARK)
+ 	    continue;
+ 
+ 	  if (TYPE_MODE (TREE_TYPE (field)) == BLKmode
+ 	      && ! TYPE_NO_FORCE_BLK (TREE_TYPE (field)))
+ 	    return;
+ 
+ 	  if (TREE_CODE (DECL_FIELD_BITPOS (field)) != INTEGER_CST)
+ 	    return;
+ 
+ 	  bitpos = TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field));
+ 
+ 	  /* Must be BLKmode if any field crosses a word boundary,
+ 	     since extract_bit_field can't handle that in registers.  */
+ 	  if (bitpos / BITS_PER_WORD
+ 	      != ((TREE_INT_CST_LOW (DECL_SIZE (field)) + bitpos - 1)
+ 		  / BITS_PER_WORD)
+ 	      /* But there is no problem if the field is entire words.  */
+ 	      && TREE_INT_CST_LOW (DECL_SIZE (field)) % BITS_PER_WORD != 0)
+ 	    return;
+ 
+ 	  /* If this field is the whole struct, remember its mode so
+ 	     that, say, we can put a double in a class into a DF
+ 	     register instead of forcing it to live in the stack.  */
+ 	  if (simple_cst_equal (TYPE_SIZE (type), DECL_SIZE (field)))
+ 	    mode = DECL_MODE (field);
+ 
+ #ifdef STRUCT_FORCE_BLK
+ 	  /* With some targets, eg. c4x, it is sub-optimal
+ 	     to access an aligned BLKmode structure as a scalar.  */
+ 	  if (mode == VOIDmode && STRUCT_FORCE_BLK (field))
+ 	    return;
+ #endif /* STRUCT_FORCE_BLK  */
+ 	}
+ 
+       if (mode != VOIDmode)
+ 	/* We only have one real field; use its mode.  */
+ 	TYPE_MODE (type) = mode;
+       else
+ 	TYPE_MODE (type)
+ 	  = mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1);
+ 
+       /* If structure's known alignment is less than what the scalar
+ 	 mode would need, and it matters, then stick with BLKmode.  */
+       if (TYPE_MODE (type) != BLKmode
+ 	  && STRICT_ALIGNMENT
+ 	  && ! (TYPE_ALIGN (type) >= BIGGEST_ALIGNMENT
+ 		|| (TYPE_ALIGN (type) >=
+ 		    GET_MODE_ALIGNMENT (TYPE_MODE (type)))))
+ 	{
+ 	  /* If this is the only reason this type is BLKmode, then
+ 	     don't force containing types to be BLKmode.  */
+ 	  TYPE_NO_FORCE_BLK (type) = 1;
+ 	  TYPE_MODE (type) = BLKmode;
+ 	}
+     }
+ }
+ 
+ /* Compute TYPE_SIZE and TYPE_ALIGN for TYPE, once it has been laid
+    out.  */
+ 
+ static void
+ finalize_type_size (type)
+      tree type;
+ {
+   /* Normally, use the alignment corresponding to the mode chosen.
+      However, where strict alignment is not required, avoid
+      over-aligning structures, since most compilers do not do this
+      alignment.  */
+ 
+   if (TYPE_MODE (type) != BLKmode && TYPE_MODE (type) != VOIDmode
+       && (STRICT_ALIGNMENT
+ 	  || (TREE_CODE (type) != RECORD_TYPE && TREE_CODE (type) != UNION_TYPE
+ 	      && TREE_CODE (type) != QUAL_UNION_TYPE
+ 	      && TREE_CODE (type) != ARRAY_TYPE)))
+     TYPE_ALIGN (type) = GET_MODE_ALIGNMENT (TYPE_MODE (type));
+ 
+   /* Do machine-dependent extra alignment.  */
+ #ifdef ROUND_TYPE_ALIGN
+   TYPE_ALIGN (type)
+     = ROUND_TYPE_ALIGN (type, TYPE_ALIGN (type), BITS_PER_UNIT);
+ #endif
+ 
+ #ifdef ROUND_TYPE_SIZE
+   if (TYPE_SIZE (type) != 0)
+     TYPE_SIZE (type)
+       = ROUND_TYPE_SIZE (type, TYPE_SIZE (type), TYPE_ALIGN (type));
+ #endif
+ 
+   /* Evaluate nonconstant size only once, either now or as soon as safe.  */
+   if (TYPE_SIZE (type) != 0 && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+     TYPE_SIZE (type) = variable_size (TYPE_SIZE (type));
+ 
+   /* If we failed to find a simple way to calculate the unit size
+      of the type above, find it by division.  */
+   if (TYPE_SIZE_UNIT (type) == 0 && TYPE_SIZE (type) != 0)
+     /* TYPE_SIZE (type) is computed in bitsizetype.  After the division, the
+        result will fit in sizetype.  We will get more efficient code using
+        sizetype, so we force a conversion.  */
+     TYPE_SIZE_UNIT (type)
+       = convert (sizetype,
+ 		 size_binop (FLOOR_DIV_EXPR, TYPE_SIZE (type),
+ 			     bitsize_int (BITS_PER_UNIT)));
+ 
+   /* Once again evaluate only once, either now or as soon as safe.  */
+   if (TYPE_SIZE_UNIT (type) != 0
+       && TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST)
+     TYPE_SIZE_UNIT (type) = variable_size (TYPE_SIZE_UNIT (type));
+ 
+   /* Also layout any other variants of the type.  */
+   if (TYPE_NEXT_VARIANT (type)
+       || type != TYPE_MAIN_VARIANT (type))
+     {
+       tree variant;
+       /* Record layout info of this variant.  */
+       tree size = TYPE_SIZE (type);
+       tree size_unit = TYPE_SIZE_UNIT (type);
+       unsigned int align = TYPE_ALIGN (type);
+       enum machine_mode mode = TYPE_MODE (type);
+ 
+       /* Copy it into all variants.  */
+       for (variant = TYPE_MAIN_VARIANT (type);
+ 	   variant != 0;
+ 	   variant = TYPE_NEXT_VARIANT (variant))
+ 	{
+ 	  TYPE_SIZE (variant) = size;
+ 	  TYPE_SIZE_UNIT (variant) = size_unit;
+ 	  TYPE_ALIGN (variant) = align;
+ 	  TYPE_MODE (variant) = mode;
  	}
      }
+ }
+ 
+ /* Do all of the work required to layout the type indicated by RLI,
+    once the fields have been laid out.  This function will call `free'
+    for RLI.  */
  
! void
! finish_record_layout (rli)
!      record_layout_info rli;
! {
!   /* Compute the final size.  */
!   finalize_record_size (rli);
!   /* Compute the TYPE_MODE for the record.  */
!   compute_record_mode (rli->t);
!   /* Lay out any static members.  This is done now because their type
!      may use the record's type.  */
!   while (rli->pending_statics)
!     {
!       layout_decl (TREE_VALUE (rli->pending_statics), 0);
!       rli->pending_statics = TREE_CHAIN (rli->pending_statics);
!     }
!   /* Perform any last tweaks to the TYPE_SIZE, etc.  */
!   finalize_type_size (rli->t);
!   /* Clean up.  */
!   free (rli);
  }
+ 
  
  /* Lay out a UNION_TYPE or QUAL_UNION_TYPE type.
     Lay out all the fields, set their positions to zero,
*************** layout_type (type)
*** 877,883 ****
       tree type;
  {
    int old;
-   tree pending_statics;
  
    if (type == 0)
      abort ();
--- 1067,1072 ----
*************** layout_type (type)
*** 886,893 ****
    if (TYPE_SIZE (type))
      return;
  
!   /* Make sure all nodes we allocate are not momentary;
!      they must last past the current statement.  */
    old = suspend_momentary ();
  
    /* Put all our nodes into the same obstack as the type.  Also,
--- 1075,1082 ----
    if (TYPE_SIZE (type))
      return;
  
!   /* Make sure all nodes we allocate are not momentary; they must last
!      past the current statement.  */
    old = suspend_momentary ();
  
    /* Put all our nodes into the same obstack as the type.  Also,
*************** layout_type (type)
*** 1095,1182 ****
        }
  
      case RECORD_TYPE:
!       pending_statics = layout_record (type);
!       TYPE_MODE (type) = BLKmode;
!       if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
! 	{
! 	  tree field;
! 	  enum machine_mode mode = VOIDmode;
! 
! 	  /* A record which has any BLKmode members must itself be BLKmode;
! 	     it can't go in a register.
! 	     Unless the member is BLKmode only because it isn't aligned.  */
! 	  for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
! 	    {
! 	      unsigned HOST_WIDE_INT bitpos;
! 
! 	      if (TREE_CODE (field) != FIELD_DECL
! 		  || TREE_CODE (TREE_TYPE (field)) == ERROR_MARK)
! 		continue;
! 
! 	      if (TYPE_MODE (TREE_TYPE (field)) == BLKmode
! 		  && ! TYPE_NO_FORCE_BLK (TREE_TYPE (field)))
! 		goto record_lose;
! 
! 	      if (TREE_CODE (DECL_FIELD_BITPOS (field)) != INTEGER_CST)
! 		goto record_lose;
! 
! 	      bitpos = TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field));
! 
! 	      /* Must be BLKmode if any field crosses a word boundary,
! 		 since extract_bit_field can't handle that in registers.  */
! 	      if (bitpos / BITS_PER_WORD
! 		  != ((TREE_INT_CST_LOW (DECL_SIZE (field)) + bitpos - 1)
! 		      / BITS_PER_WORD)
! 		  /* But there is no problem if the field is entire words.  */
! 		  && TREE_INT_CST_LOW (DECL_SIZE (field)) % BITS_PER_WORD != 0)
! 		goto record_lose;
! 
! 	      /* If this field is the whole struct, remember its mode so
! 		 that, say, we can put a double in a class into a DF
! 		 register instead of forcing it to live in the stack.  */
! 	      if (simple_cst_equal (TYPE_SIZE (type), DECL_SIZE (field)))
! 		mode = DECL_MODE (field);
! 
! #ifdef STRUCT_FORCE_BLK
! 	      /* With some targets, eg. c4x, it is sub-optimal
! 		 to access an aligned BLKmode structure as a scalar.  */
! 	      if (mode == VOIDmode && STRUCT_FORCE_BLK (field))
! 		  goto record_lose;
! #endif /* STRUCT_FORCE_BLK  */
! 	    }
! 
! 	  if (mode != VOIDmode)
! 	    /* We only have one real field; use its mode.  */
! 	    TYPE_MODE (type) = mode;
! 	  else
! 	    TYPE_MODE (type)
! 	      = mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1);
! 
! 	  /* If structure's known alignment is less than
! 	     what the scalar mode would need, and it matters,
! 	     then stick with BLKmode.  */
! 	  if (TYPE_MODE (type) != BLKmode
! 	      && STRICT_ALIGNMENT
! 	      && ! (TYPE_ALIGN (type) >= BIGGEST_ALIGNMENT
! 		    || (TYPE_ALIGN (type) >=
! 			GET_MODE_ALIGNMENT (TYPE_MODE (type)))))
! 	    {
! 	      /* If this is the only reason this type is BLKmode,
! 		 then don't force containing types to be BLKmode.  */
! 	      TYPE_NO_FORCE_BLK (type) = 1;
! 	      TYPE_MODE (type) = BLKmode;
! 	    }
! 
! 	record_lose: ;
! 	}
  
!       /* Lay out any static members.  This is done now
! 	 because their type may use the record's type.  */
!       while (pending_statics)
! 	{
! 	  layout_decl (TREE_VALUE (pending_statics), 0);
! 	  pending_statics = TREE_CHAIN (pending_statics);
! 	}
        break;
  
      case UNION_TYPE:
--- 1284,1301 ----
        }
  
      case RECORD_TYPE:
!       {
! 	tree field;
! 	record_layout_info rli;
  
! 	/* Initialize the layout information.  */
! 	rli = new_record_layout_info (type);
! 	/* Layout all the fields.  */
! 	for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
! 	  layout_field (rli, field);
! 	/* Finish laying out the record.  */
! 	finish_record_layout (rli);
!       }
        break;
  
      case UNION_TYPE:
*************** layout_type (type)
*** 1252,1325 ****
      default:
        abort ();
      }
- 
-   /* Normally, use the alignment corresponding to the mode chosen.
-      However, where strict alignment is not required, avoid
-      over-aligning structures, since most compilers do not do this
-      alignment.  */
- 
-   if (TYPE_MODE (type) != BLKmode && TYPE_MODE (type) != VOIDmode
-       && (STRICT_ALIGNMENT
- 	  || (TREE_CODE (type) != RECORD_TYPE && TREE_CODE (type) != UNION_TYPE
- 	      && TREE_CODE (type) != QUAL_UNION_TYPE
- 	      && TREE_CODE (type) != ARRAY_TYPE)))
-     TYPE_ALIGN (type) = GET_MODE_ALIGNMENT (TYPE_MODE (type));
- 
-   /* Do machine-dependent extra alignment.  */
- #ifdef ROUND_TYPE_ALIGN
-   TYPE_ALIGN (type)
-     = ROUND_TYPE_ALIGN (type, TYPE_ALIGN (type), BITS_PER_UNIT);
- #endif
- 
- #ifdef ROUND_TYPE_SIZE
-   if (TYPE_SIZE (type) != 0)
-     TYPE_SIZE (type)
-       = ROUND_TYPE_SIZE (type, TYPE_SIZE (type), TYPE_ALIGN (type));
- #endif
- 
-   /* Evaluate nonconstant size only once, either now or as soon as safe.  */
-   if (TYPE_SIZE (type) != 0 && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
-     TYPE_SIZE (type) = variable_size (TYPE_SIZE (type));
- 
-   /* If we failed to find a simple way to calculate the unit size
-      of the type above, find it by division.  */
-   if (TYPE_SIZE_UNIT (type) == 0 && TYPE_SIZE (type) != 0)
-     /* TYPE_SIZE (type) is computed in bitsizetype.  After the division, the
-        result will fit in sizetype.  We will get more efficient code using
-        sizetype, so we force a conversion.  */
-     TYPE_SIZE_UNIT (type)
-       = convert (sizetype,
- 		 size_binop (FLOOR_DIV_EXPR, TYPE_SIZE (type),
- 			     bitsize_int (BITS_PER_UNIT)));
  
!   /* Once again evaluate only once, either now or as soon as safe.  */
!   if (TYPE_SIZE_UNIT (type) != 0
!       && TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST)
!     TYPE_SIZE_UNIT (type) = variable_size (TYPE_SIZE_UNIT (type));
! 
!   /* Also layout any other variants of the type.  */
!   if (TYPE_NEXT_VARIANT (type)
!       || type != TYPE_MAIN_VARIANT (type))
!     {
!       tree variant;
!       /* Record layout info of this variant.  */
!       tree size = TYPE_SIZE (type);
!       tree size_unit = TYPE_SIZE_UNIT (type);
!       unsigned int align = TYPE_ALIGN (type);
!       enum machine_mode mode = TYPE_MODE (type);
  
-       /* Copy it into all variants.  */
-       for (variant = TYPE_MAIN_VARIANT (type);
- 	   variant != 0;
- 	   variant = TYPE_NEXT_VARIANT (variant))
- 	{
- 	  TYPE_SIZE (variant) = size;
- 	  TYPE_SIZE_UNIT (variant) = size_unit;
- 	  TYPE_ALIGN (variant) = align;
- 	  TYPE_MODE (variant) = mode;
- 	}
-     }
- 	
    pop_obstacks ();
    resume_momentary (old);
  
--- 1371,1382 ----
      default:
        abort ();
      }
  
!   /* Compute the final TYPE_SIZE, TYPE_ALIGN, etc. for TYPE.  For
!      RECORD_TYPEs, finish_record_layout already called this function.  */
!   if (TREE_CODE (type) != RECORD_TYPE)
!     finalize_type_size (type);
  
    pop_obstacks ();
    resume_momentary (old);
  
Index: tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/tree.h,v
retrieving revision 1.140
diff -c -p -r1.140 tree.h
*** tree.h	2000/03/09 20:34:50	1.140
--- tree.h	2000/03/13 09:08:15
*************** extern tree build_qualified_type        
*** 1776,1786 ****
  extern tree build_type_copy		PARAMS ((tree));
  
  /* Given a ..._TYPE node, calculate the TYPE_SIZE, TYPE_SIZE_UNIT,
!    TYPE_ALIGN and TYPE_MODE fields.
!    If called more than once on one node, does nothing except
!    for the first time.  */
  
  extern void layout_type			PARAMS ((tree));
  
  /* Given a hashcode and a ..._TYPE node (for which the hashcode was made),
     return a canonicalized ..._TYPE node, so that duplicates are not made.
--- 1776,1820 ----
  extern tree build_type_copy		PARAMS ((tree));
  
  /* Given a ..._TYPE node, calculate the TYPE_SIZE, TYPE_SIZE_UNIT,
!    TYPE_ALIGN and TYPE_MODE fields.  If called more than once on one
!    node, does nothing except for the first time.  */
  
  extern void layout_type			PARAMS ((tree));
+ 
+ /* These functions allow a front-end to perform a manual layout of a
+    RECORD_TYPE.  (For instance, if the placement of subsequent fields
+    depends on the placement of fields so far.)  Begin by calling
+    new_record_layout_info.  Then, call layout_field for each of the
+    fields.  Then, call finish_record_layout.  See layout_type for the
+    default way in which these functions are used.  */
+ 
+ struct record_layout_info_s
+ {
+   /* The RECORD_TYPE that we are laying out.  */
+   tree t;
+   /* The size of the record so far, in bits.  */
+   unsigned HOST_WIDE_INT const_size;
+   /* The alignment of the record so far, in bits.  */
+   unsigned int record_align;
+   /* If the record can have a variable size, then this will be
+      non-NULL, and the total size will be CONST_SIZE + VAR_SIZE.  */
+   tree var_size;
+   /* If the record can have a variable size, then this will be the
+      maximum alignment that we know VAR_SIZE has.  */
+   unsigned int var_align;
+   /* The static variables (i.e., class variables, as opposed to
+      instance variables) encountered in T.  */
+   tree pending_statics;
+   unsigned int unpacked_align;
+   int packed_maybe_necessary;
+ };
+ 
+ typedef struct record_layout_info_s *record_layout_info;
+ 
+ extern record_layout_info new_record_layout_info 
+                                         PARAMS ((tree));
+ extern void layout_field                PARAMS ((record_layout_info, tree));
+ extern void finish_record_layout        PARAMS ((record_layout_info));
  
  /* Given a hashcode and a ..._TYPE node (for which the hashcode was made),
     return a canonicalized ..._TYPE node, so that duplicates are not made.



More information about the Gcc-patches mailing list