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]

TARGET_MS_BITFIELD_LAYOUT_P ABI fix


-- 
--------------------------
SuperH (UK) Ltd.
2430 Aztec West / Almondsbury / BRISTOL / BS32 4AQ
T:+44 1454 462330
The recent changes with argument passing alignemnt have uncovered a latent
bug in the way we lay out structures for TARGET_MS_BITFIELD_LAYOUT_P.
execute/931031-1.c fails because

struct foo
{
  unsigned y:1;
  unsigned x:32;
};

gets laid out as 5 bytes, with x straddling an alignment boundary.

Wed Sep  4 16:28:45 2002  J"orn Rennecke <joern.rennecke@superh.com>

	* stor-layout.c (excess_unit_span): New function.
	(place_union_field): Use it.  Take result in account for ms
	bitfields too.

Index: stor-layout.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/stor-layout.c,v
retrieving revision 1.128
diff -p -r1.128 stor-layout.c
*** stor-layout.c	7 Aug 2002 23:20:34 -0000	1.128
--- stor-layout.c	4 Sep 2002 15:28:34 -0000
*************** static int reference_types_internal = 0;
*** 60,65 ****
--- 60,68 ----
  static void finalize_record_size	PARAMS ((record_layout_info));
  static void finalize_type_size		PARAMS ((tree));
  static void place_union_field		PARAMS ((record_layout_info, tree));
+ static int excess_unit_span		PARAMS ((HOST_WIDE_INT, HOST_WIDE_INT,
+ 						 HOST_WIDE_INT, HOST_WIDE_INT,
+ 						 tree));
  extern void debug_rli			PARAMS ((record_layout_info));
  
  /* SAVE_EXPRs for sizes of types and decls, waiting to be expanded.  */
*************** place_union_field (rli, field)
*** 708,713 ****
--- 711,734 ----
  			       DECL_SIZE_UNIT (field), rli->offset));
  }
  
+ /* A bitfield of SIZE with a required access alignment of ALIGN is allocated
+    at BYTE_OFFSET / BIT_OFFSET.  Return non-zero if the field would span more
+    units of alignment than the underlying TYPE.  */
+ static int
+ excess_unit_span (byte_offset, bit_offset, size, align, type)
+      HOST_WIDE_INT byte_offset, bit_offset, size, align;
+      tree type;
+ {
+   /* Note that the calculation of OFFSET might overflow; we calculate it so
+      that we still get the right result as long as ALIGN is a power of two.  */
+   unsigned HOST_WIDE_INT offset = byte_offset * BITS_PER_UNIT + bit_offset;
+ 
+   offset = offset % align;
+   return ((offset + size + align - 1) / align
+ 	  > ((unsigned HOST_WIDE_INT) tree_low_cst (TYPE_SIZE (type), 1)
+ 	     / align));
+ }
+ 
  /* 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;
*************** place_field (rli, field)
*** 937,947 ****
  
        /* A bit field may not span more units of alignment of its type
  	 than its type itself.  Advance to next boundary if necessary.  */
!       if ((((offset * BITS_PER_UNIT + bit_offset + field_size +
! 	     type_align - 1)
! 	    / type_align)
! 	   - (offset * BITS_PER_UNIT + bit_offset) / type_align)
! 	  > tree_low_cst (TYPE_SIZE (type), 1) / type_align)
  	rli->bitpos = round_up (rli->bitpos, type_align);
  
        user_align |= TYPE_USER_ALIGN (type);
--- 958,964 ----
  
        /* A bit field may not span more units of alignment of its type
  	 than its type itself.  Advance to next boundary if necessary.  */
!       if (excess_unit_span (offset, bit_offset, field_size, type_align, type))
  	rli->bitpos = round_up (rli->bitpos, type_align);
  
        user_align |= TYPE_USER_ALIGN (type);
*************** place_field (rli, field)
*** 980,990 ****
  
        /* 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 ((offset * BITS_PER_UNIT + bit_offset) / type_align
! 	  != ((offset * BITS_PER_UNIT + bit_offset + field_size - 1)
! 	      / type_align))
  	rli->bitpos = round_up (rli->bitpos, type_align);
  
        user_align |= TYPE_USER_ALIGN (type);
--- 997,1003 ----
  
        /* A bit field may not span the unit of alignment of its type.
  	 Advance to next boundary if necessary.  */
!       if (excess_unit_span (offset, bit_offset, field_size, type_align, type))
  	rli->bitpos = round_up (rli->bitpos, type_align);
  
        user_align |= TYPE_USER_ALIGN (type);
*************** place_field (rli, field)
*** 1016,1022 ****
  	     alignment of this field, in which case forcing the
  	     alignment again is harmless.  So, do it in both cases.  */
  	  || (DECL_BIT_FIELD_TYPE (rli->prev_field)
! 	      && integer_zerop (DECL_SIZE (rli->prev_field)))))
      {
        unsigned int type_align = TYPE_ALIGN (type);
  
--- 1029,1039 ----
  	     alignment of this field, in which case forcing the
  	     alignment again is harmless.  So, do it in both cases.  */
  	  || (DECL_BIT_FIELD_TYPE (rli->prev_field)
! 	      && integer_zerop (DECL_SIZE (rli->prev_field)))
! 	  || excess_unit_span (tree_low_cst (rli->offset, 0),
! 			       tree_low_cst (rli->bitpos, 0),
! 			       tree_low_cst (DECL_SIZE (field), 1),
! 			       TYPE_ALIGN (type), type)))
      {
        unsigned int type_align = TYPE_ALIGN (type);
  

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