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 (take 4)


On Wed, Aug 07, 2002 at 08:58:08AM -0700, Mark Mitchell wrote:
> > is checked after BIGGEST_FIELD_ALIGNMENT not "instead of".  Also
> > be nice to mention that it is required that the user alignment
> > be tested.
> 
> If every ADJUST_FIELD_ALIGN implementation is going to have to honor
> DECL_USER_ALIGN, we should move that logic into stor-layout.c.  Build
> an adjust_field_align function like so:
> 
>   adjust_field_align (field, computed)
>   {
>     if (DECL_USER_ALIGN (field))
>       return computed;
>     return ADJUST_FIELD_ALIGN (field, computed):
>   }
> 
> Also, does a FIELD_DECL still ever get passed in, or is it always a
> type?  In the patch, it looks like the latter.  In which case, we
> don't need TYPE_P checks in the macros.

The patch was passing both, but if {DECL,TYPE}_USER_ALIGN is to be checked
in stor-layout.c (which makes sense, so that ports don't forgot to do it
themselves), then I don't see why to pass fields to some and types
to others, we can pass FIELD_DECL all the time.

Please let me know if this is how you'd like it to be implemented, so that
I can fire off another bootstrap (though I'd appreciate if Aldy could
check the ppc part).

2002-08-07  Jakub Jelinek  <jakub@redhat.com>
	    Richard Henderson  <rth@redhat.com>

	* stor-layout.c (place_union_field): Apply ADJUST_FIELD_ALIGN
	to type_align when PCC_BITFIELD_TYPE_MATTERS.  Only apply
	ADJUST_FIELD_ALIGN if not DECL_USER_ALIGN resp. TYPE_USER_ALIGN.
	(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.
	* config/rs6000/rs6000.c (rs6000_field_alignment): New.
	* config/rs6000/rs6000-protos.h (rs6000_field_alignment): New
	prototype.
	* config/rs6000/rs6000.h (ADJUST_FIELD_ALIGN): Define.
	* config/rs6000/aix.h (ADJUST_FIELD_ALIGN): Remove.
	* config/rs6000/darwin.h (ADJUST_FIELD_ALIGN): Remove.
	* config/rs6000/linux64.h (ADJUST_FIELD_ALIGN): Remove.
	* config/rs6000/sysv4.h (ADJUST_FIELD_ALIGN): Remove.
	* doc/tm.texi (ADJUST_FIELD_ALIGN): Update description.

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

--- gcc/doc/tm.texi.jj	2002-07-10 11:37:44.000000000 +0200
+++ gcc/doc/tm.texi	2002-08-07 18:32:57.000000000 +0200
@@ -1072,9 +1072,11 @@ by the @code{__attribute__ ((aligned (@v
 @findex ADJUST_FIELD_ALIGN
 @item ADJUST_FIELD_ALIGN (@var{field}, @var{computed})
 An expression for the alignment of a structure field @var{field} if the
-alignment computed in the usual way is @var{computed}.  GCC uses
-this value instead of the value in @code{BIGGEST_ALIGNMENT} or
-@code{BIGGEST_FIELD_ALIGNMENT}, if defined.
+alignment computed in the usual way (including applying of
+@code{BIGGEST_ALIGNMENT} and @code{BIGGEST_FIELD_ALIGNMENT} to the
+alignment) is @var{computed}.  It overrides alignment only if the
+field alignment has not been set by the
+@code{__attribute__ ((aligned (@var{n})))} construct.
 
 @findex MAX_OFILE_ALIGNMENT
 @item MAX_OFILE_ALIGNMENT
--- gcc/config/i386/i386.c.jj	2002-07-27 01:31:05.000000000 +0200
+++ gcc/config/i386/i386.c	2002-08-07 18:23:19.000000000 +0200
@@ -12640,14 +12640,15 @@ x86_field_alignment (field, computed)
      int computed;
 {
   enum machine_mode mode;
-  if (TARGET_64BIT || DECL_USER_ALIGN (field) || TARGET_ALIGN_DOUBLE)
+  tree type = TREE_TYPE (field);
+
+  if (TARGET_64BIT || TARGET_ALIGN_DOUBLE)
     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)
+  mode = TYPE_MODE (TREE_CODE (type) == ARRAY_TYPE
+		    ? get_inner_array_type (type) : type);
+  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/config/rs6000/rs6000.c.jj	2002-05-25 00:01:52.000000000 +0200
+++ gcc/config/rs6000/rs6000.c	2002-08-07 18:30:25.000000000 +0200
@@ -11534,3 +11534,19 @@ xcoff_asm_named_section (name, flags)
   fprintf (asm_out_file, "\t.csect %s\n", name);
 }
 #endif
+
+int
+rs6000_field_alignment (field, computed)
+     tree field;
+     int computed;
+{
+  tree type = get_inner_array_type (field);
+
+  if (DEFAULT_ABI == ABI_V4 && TARGET_ALTIVEC
+      && TREE_CODE (type) == VECTOR_TYPE)
+    return 128;
+
+  if (TYPE_MODE (type) == DFmode)
+    return MIN (32, computed);
+  return computed;
+}
--- gcc/config/rs6000/rs6000-protos.h.jj	2002-02-19 11:13:34.000000000 +0100
+++ gcc/config/rs6000/rs6000-protos.h	2002-08-07 10:22:40.000000000 +0200
@@ -147,6 +147,7 @@ extern void output_mi_thunk PARAMS ((FIL
 extern void rs6000_encode_section_info PARAMS ((tree));
 extern void rs6000_select_section PARAMS ((tree, int));
 extern void rs6000_unique_section PARAMS ((tree, int));
+extern int rs6000_field_alignment PARAMS ((tree, int));
 #ifdef ARGS_SIZE_RTX
 /* expr.h defines ARGS_SIZE_RTX and `enum direction' */
 extern enum direction function_arg_padding PARAMS ((enum machine_mode, tree));
--- gcc/config/rs6000/aix.h.jj	2002-03-18 23:23:52.000000000 +0100
+++ gcc/config/rs6000/aix.h	2002-08-07 18:16:51.000000000 +0200
@@ -103,13 +103,6 @@ Boston, MA 02111-1307, USA.  */
 #define LIB_SPEC "%{pg:-L/lib/profiled -L/usr/lib/profiled}\
 %{p:-L/lib/profiled -L/usr/lib/profiled} %{!shared:%{g*:-lg}} -lc"
 
-/* AIX word-aligns FP doubles but doubleword-aligns 64-bit ints.  */
-#define ADJUST_FIELD_ALIGN(FIELD, COMPUTED) \
-  (TYPE_MODE (TREE_CODE (TREE_TYPE (FIELD)) == ARRAY_TYPE \
-	      ? get_inner_array_type (FIELD) \
-	      : TREE_TYPE (FIELD)) == DFmode \
-   ? MIN ((COMPUTED), 32) : (COMPUTED))
-
 /* AIX increases natural record alignment to doubleword if the first
    field is an FP double while the FP fields remain word aligned.  */
 #define ROUND_TYPE_ALIGN(STRUCT, COMPUTED, SPECIFIED)	\
--- gcc/config/rs6000/darwin.h.jj	2002-05-03 19:25:51.000000000 +0200
+++ gcc/config/rs6000/darwin.h	2002-08-07 18:17:05.000000000 +0200
@@ -205,13 +205,6 @@ Boston, MA 02111-1307, USA.  */
 /* Fix for emit_group_load (): force large constants to be pushed via regs.  */
 #define ALWAYS_PUSH_CONSTS_USING_REGS_P		1
 
-/* Darwin word-aligns FP doubles but doubleword-aligns 64-bit ints.  */
-#define ADJUST_FIELD_ALIGN(FIELD, COMPUTED) \
-  (TYPE_MODE (TREE_CODE (TREE_TYPE (FIELD)) == ARRAY_TYPE \
-	      ? get_inner_array_type (FIELD) \
-	      : TREE_TYPE (FIELD)) == DFmode \
-   ? MIN ((COMPUTED), 32) : (COMPUTED))
-
 /* Darwin increases natural record alignment to doubleword if the first
    field is an FP double while the FP fields remain word aligned.  */
 #define ROUND_TYPE_ALIGN(STRUCT, COMPUTED, SPECIFIED)	\
--- gcc/config/rs6000/linux64.h.jj	2002-06-08 00:40:12.000000000 +0200
+++ gcc/config/rs6000/linux64.h	2002-08-07 18:17:15.000000000 +0200
@@ -64,13 +64,6 @@ Boston, MA 02111-1307, USA.  */
 
 #define USER_LABEL_PREFIX  ""
 
-/* AIX word-aligns FP doubles but doubleword-aligns 64-bit ints.  */
-#define ADJUST_FIELD_ALIGN(FIELD, COMPUTED) \
-  (TYPE_MODE (TREE_CODE (TREE_TYPE (FIELD)) == ARRAY_TYPE \
-	      ? get_inner_array_type (FIELD) \
-	      : TREE_TYPE (FIELD)) == DFmode \
-   ? MIN ((COMPUTED), 32) : (COMPUTED))
-
 /* AIX increases natural record alignment to doubleword if the first
    field is an FP double while the FP fields remain word aligned.  */
 #undef ROUND_TYPE_ALIGN
--- gcc/config/rs6000/sysv4.h.jj	2002-04-16 13:07:13.000000000 +0200
+++ gcc/config/rs6000/sysv4.h	2002-08-07 18:19:08.000000000 +0200
@@ -387,12 +387,6 @@ do {									\
 #undef	BIGGEST_ALIGNMENT
 #define BIGGEST_ALIGNMENT ((TARGET_EABI && !TARGET_ALTIVEC) ? 64 : 128)
 
-/* An expression for the alignment of a structure field FIELD if the
-   alignment computed in the usual way is COMPUTED.  */
-#define ADJUST_FIELD_ALIGN(FIELD, COMPUTED)				      \
-	((TARGET_ALTIVEC && TREE_CODE (TREE_TYPE (FIELD)) == VECTOR_TYPE)     \
-	 ? 128 : COMPUTED)
-
 /* Define this macro as an expression for the alignment of a type
    (given by TYPE as a tree node) if the alignment computed in the
    usual way is COMPUTED and the alignment explicitly specified was
@@ -403,7 +397,6 @@ do {									\
          : MAX (COMPUTED, SPECIFIED))
 
 #undef  BIGGEST_FIELD_ALIGNMENT
-#undef  ADJUST_FIELD_ALIGN
 
 /* Use ELF style section commands.  */
 
--- gcc/config/rs6000/rs6000.h.jj	2002-05-30 11:15:41.000000000 +0200
+++ gcc/config/rs6000/rs6000.h	2002-08-07 18:18:38.000000000 +0200
@@ -638,6 +638,10 @@ extern int rs6000_altivec_abi;
 /* A bitfield declared as `int' forces `int' alignment for the struct.  */
 #define PCC_BITFIELD_TYPE_MATTERS 1
 
+/* Most ABIs word-align FP doubles but doubleword-align 64-bit ints.  */
+#define ADJUST_FIELD_ALIGN(FIELD, COMPUTED) \
+  rs6000_field_alignment ((FIELD), (COMPUTED))
+
 /* Make strings word-aligned so strcpy from constants will be faster.
    Make vector constants quadword aligned.  */
 #define CONSTANT_ALIGNMENT(EXP, ALIGN)                           \
--- 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);
+}
--- gcc/stor-layout.c.jj	2002-04-15 14:42:51.000000000 +0200
+++ gcc/stor-layout.c	2002-08-07 18:26:46.000000000 +0200
@@ -669,7 +669,8 @@ place_union_field (rli, field)
 #endif
 
 #ifdef ADJUST_FIELD_ALIGN
-  desired_align = ADJUST_FIELD_ALIGN (field, desired_align);
+  if (! DECL_USER_ALIGN (field))
+    desired_align = ADJUST_FIELD_ALIGN (field, desired_align);
 #endif
 
   TYPE_USER_ALIGN (rli->t) |= DECL_USER_ALIGN (field);
@@ -683,10 +684,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 (TREE_TYPE (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
 
@@ -783,7 +788,8 @@ place_field (rli, field)
 #endif
 
 #ifdef ADJUST_FIELD_ALIGN
-  desired_align = ADJUST_FIELD_ALIGN (field, desired_align);
+  if (! user_align)
+    desired_align = ADJUST_FIELD_ALIGN (field, desired_align);
 #endif
 
   /* Record must have at least as much alignment as any field.
@@ -827,6 +833,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 +926,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 (type))
+	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 +960,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 (type))
+	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


	Jakub


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