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]

[PATCH] IA-32 bitfields (was Re: libgcc_s, Linux, and PT_GNU_EH_FRAME, and binutils)


On Tue, Aug 06, 2002 at 01:33:33PM -0700, Mark Mitchell wrote:
> > So what do we do?  Personally I'm for fixing the bug.
> 
> Blech.  I don't like that we broke the C ABI, but I'm not sure I like
> breaking it again in the name of fixing it, some two years later.
> 
> I guess the fact that nobody noticed until now suggests that maybe
> the problem isn't very common, which makes either decision less
> important.
> 
> If we *do* want to fix it, we need to look everywhere.  For example,
> place_union_field gives the union the alignment of the type of the bit
> field in the PCC_BITFIELD_TYPE_MATTERS case.  So, I think a union with
> a long long bit field will get 8-byte aligned, which is weird.
> 
> And place_field gates the alignment by maximum_field_alignment -- but
> not by desired_field_alignment.  Again, in the PCC_BITFIELD_TYPE_MATTERS
> case, which is the usual case on x86.

This worked for me and IMHO shouldn't make a difference anywhere but
on IA-32 (since ADJUST_FIELD_ALIGN is defined on IA-32 and PPC only
and on PPC it only changes something if the field's type is DFmode,
but bitfields cannot have DFmode TYPE_MODE).

This only shows that we need to add extensive layout testcases at least
for all important arches, so that screwups like this don't happen ever
again. i386-bitfield1.c passes on egcs 1.1.2, gcc 2.95.x and gcc 3.2 
with this patch, fails with gcc 2.96-RH, 3.[01]* and trunk.
bitfield3.C fails everywhere but in gcc 3.2 with this patch,
since egcs 1.1.2 and gcc 2.95.x did not support bitfields larger than
the underlying type.

2002-08-05  Jakub Jelinek  <jakub@redhat.com>

	* stor-layout.c (place_union_field): Apply ADJUST_FIELD_ALIGN
	to type_align when PCC_BITFIELD_TYPE_MATTERS.
	(place_field): Likewise.
	* config/i386/i386.c (x86_field_alignment): Don't check
	TARGET_ALIGN_DOUBLE for the second time.
	Apply min for all MODE_INT and MODE_CLASS_INT modes.

	* gcc.dg/i386-bitfield1.c: New test.
	* g++.dg/abi/bitfield3.C: New test.

--- gcc/config/i386/i386.c.jj	2002-07-27 01:31:05.000000000 +0200
+++ gcc/config/i386/i386.c	2002-08-05 13:31:53.000000000 +0200
@@ -12644,10 +12644,9 @@ x86_field_alignment (field, computed)
     return computed;
   mode = TYPE_MODE (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
 		    ? get_inner_array_type (field) : TREE_TYPE (field));
-  if ((mode == DFmode || mode == DCmode
-      || mode == DImode || mode == CDImode)
-      && !TARGET_ALIGN_DOUBLE)
+  if (mode == DFmode || mode == DCmode
+      || GET_MODE_CLASS (mode) == MODE_INT
+      || GET_MODE_CLASS (mode) == MODE_COMPLEX_INT)
     return MIN (32, computed);
   return computed;
 }
-
--- gcc/stor-layout.c.jj	2002-04-15 14:42:51.000000000 +0200
+++ gcc/stor-layout.c	2002-08-07 00:11:13.000000000 +0200
@@ -683,10 +683,14 @@ place_union_field (rli, field)
      entire union to have `int' alignment.  */
   if (PCC_BITFIELD_TYPE_MATTERS && DECL_BIT_FIELD_TYPE (field))
     {
-      rli->record_align = MAX (rli->record_align, 
-			       TYPE_ALIGN (TREE_TYPE (field)));
-      rli->unpadded_align = MAX (rli->unpadded_align,
-				 TYPE_ALIGN (TREE_TYPE (field)));
+      unsigned int type_align = TYPE_ALIGN (TREE_TYPE (field));
+
+#ifdef ADJUST_FIELD_ALIGN
+      if (! TYPE_USER_ALIGN (field))
+	type_align = ADJUST_FIELD_ALIGN (field, type_align);
+#endif
+      rli->record_align = MAX (rli->record_align, type_align);
+      rli->unpadded_align = MAX (rli->unpadded_align, type_align);
     }
 #endif
 
@@ -827,6 +831,11 @@ place_field (rli, field)
 	{
 	  unsigned int type_align = TYPE_ALIGN (type);
 
+#ifdef ADJUST_FIELD_ALIGN
+	  if (! TYPE_USER_ALIGN (type))
+	    type_align = ADJUST_FIELD_ALIGN (field, type_align);
+#endif
+
 	  if (maximum_field_alignment != 0)
 	    type_align = MIN (type_align, maximum_field_alignment);
 	  else if (DECL_PACKED (field))
@@ -915,6 +924,11 @@ place_field (rli, field)
       HOST_WIDE_INT offset = tree_low_cst (rli->offset, 0);
       HOST_WIDE_INT bit_offset = tree_low_cst (rli->bitpos, 0);
 
+#ifdef ADJUST_FIELD_ALIGN
+      if (! TYPE_USER_ALIGN (field))
+	type_align = ADJUST_FIELD_ALIGN (field, type_align);
+#endif
+
       /* 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 +
@@ -944,6 +958,11 @@ place_field (rli, field)
       HOST_WIDE_INT offset = tree_low_cst (rli->offset, 0);
       HOST_WIDE_INT bit_offset = tree_low_cst (rli->bitpos, 0);
 
+#ifdef ADJUST_FIELD_ALIGN
+      if (! TYPE_USER_ALIGN (field))
+	type_align = ADJUST_FIELD_ALIGN (field, type_align);
+#endif
+
       if (maximum_field_alignment != 0)
 	type_align = MIN (type_align, maximum_field_alignment);
       /* ??? This test is opposite the test in the containing if
--- gcc/testsuite/g++.dg/abi/bitfield3.C.jj	2002-08-05 13:47:02.000000000 +0200
+++ gcc/testsuite/g++.dg/abi/bitfield3.C	2002-08-07 00:21:01.000000000 +0200
@@ -0,0 +1,80 @@
+// Test for oversized bitfield alignment in structs on IA-32
+// { dg-do run { target i?86-*-* } }
+// { dg-options "-O2" }
+
+struct A
+{
+  char a;
+  int b : 224;	// { dg-warning "exceeds its type" "" }
+  char c;
+} a, a4[4];
+
+struct B
+{
+  char d;
+  A e;
+  char f;
+} b;
+
+struct C
+{
+  char g;
+  long long h : 64;
+  char i;
+} c, c4[4];
+
+struct D
+{
+  char j;
+  C k;
+  char l;
+} d;
+
+struct E
+{
+  char m;
+  long long n : 160;	// { dg-warning "exceeds its type" "" }
+  char o;
+} e, e4[4];
+
+struct F
+{
+  char p;
+  E q;
+  char r;
+} f;
+
+int main (void)
+{
+  if (&a.c - &a.a != 32)
+    return 1;
+  if (sizeof (a) != 36)
+    return 2;
+  if (sizeof (a4) != 4 * 36)
+    return 3;
+  if (sizeof (b) != 2 * 4 + 36)
+    return 4;
+  if (__alignof__ (b.e) != 4)
+    return 5;
+  if (&c.i - &c.g != 12)
+    return 6;
+  if (sizeof (c) != 16)
+    return 7;
+  if (sizeof (c4) != 4 * 16)
+    return 8;
+  if (sizeof (d) != 2 * 4 + 16)
+    return 9;
+  if (__alignof__ (d.k) != 4)
+    return 10;
+  if (&e.o - &e.m != 24)
+    return 11;
+  if (sizeof (e) != 28)
+    return 12;
+  if (sizeof (e4) != 4 * 28)
+    return 13;
+  if (sizeof (f) != 2 * 4 + 28)
+    return 14;
+  if (__alignof__ (f.q) != 4)
+    return 15;
+  return 0;
+}
--- gcc/testsuite/gcc.dg/i386-bitfield1.c.jj	2002-08-07 00:17:59.000000000 +0200
+++ gcc/testsuite/gcc.dg/i386-bitfield1.c	2002-08-07 00:15:48.000000000 +0200
@@ -0,0 +1,53 @@
+// Test for bitfield alignment in structs on IA-32
+// { dg-do run { target i?86-*-* } }
+// { dg-options "-O2" }
+
+extern void abort (void);
+extern void exit (int);
+
+struct A
+{
+  char a;
+  long long b : 61;
+  char c;
+} a, a4[4];
+
+struct B
+{
+  char d;
+  struct A e;
+  char f;
+} b;
+
+struct C
+{
+  char g;
+  union U
+  {
+    char u1;
+    long long u2;
+    long long u3 : 64;
+  } h;
+  char i;
+} c;
+
+int main (void)
+{
+  if (&a.c - &a.a != 12)
+    abort ();
+  if (sizeof (a) != 16)
+    abort ();
+  if (sizeof (a4) != 4 * 16)
+    abort ();
+  if (sizeof (b) != 2 * 4 + 16)
+    abort ();
+  if (__alignof__ (b.e) != 4)
+    abort ();
+  if (&c.i - &c.g != 12)
+    abort ();
+  if (sizeof (c) != 16)
+    abort ();
+  if (__alignof__ (c.h) != 4)
+    abort ();
+  exit (0);
+}


	Jakub


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