This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
TARGET_MS_BITFIELD_LAYOUT_P ABI fix
- From: Joern Rennecke <joern dot rennecke at superh dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 04 Sep 2002 19:00:41 +0100
- Subject: TARGET_MS_BITFIELD_LAYOUT_P ABI fix
- Organization: SuperH UK Ltd.
--
--------------------------
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);