+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.
+
2002-08-06 Jakub Jelinek <jakub@redhat.com>
* config/i386/mmintrin.h (__m64): Make the type 64-bit aligned.
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;
}
-
#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) \
/* 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) \
#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
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));
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)
+ {
+ if (TARGET_ALTIVEC && TREE_CODE (type) == VECTOR_TYPE)
+ return 128;
+ }
+ else
+ {
+ if (TYPE_MODE (type) == DFmode)
+ return MIN (32, computed);
+ }
+
+ return computed;
+}
/* 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) \
#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
: MAX (COMPUTED, SPECIFIED))
#undef BIGGEST_FIELD_ALIGNMENT
-#undef ADJUST_FIELD_ALIGN
/* Use ELF style section commands. */
@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
#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);
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
#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.
{
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))
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 +
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
+2002-08-07 Jakub Jelinek <jakub@redhat.com>
+ Richard Henderson <rth@redhat.com>
+
+ * gcc.dg/i386-bitfield1.c: New test.
+ * g++.dg/abi/bitfield3.C: New test.
+
2002-08-01 Benjamin Kosnik <bkoz@redhat.com>
* g++.old-deja/g++.abi/ptrflags.C (expect): Change
return 4;
if (__alignof__ (b.e) != 4)
return 5;
- if (&c.i - &c.g != 16)
+ if (&c.i - &c.g != 12)
return 6;
- if (sizeof (c) != 24)
+ if (sizeof (c) != 16)
return 7;
- if (sizeof (c4) != 4 * 24)
+ if (sizeof (c4) != 4 * 16)
return 8;
- if (sizeof (d) != 2 * 8 + 24)
+ if (sizeof (d) != 2 * 4 + 16)
return 9;
- if (__alignof__ (d.k) != 8)
+ if (__alignof__ (d.k) != 4)
return 10;
- if (&e.o - &e.m != 28)
+ if (&e.o - &e.m != 24)
return 11;
- if (sizeof (e) != 32)
+ if (sizeof (e) != 28)
return 12;
- if (sizeof (e4) != 4 * 32)
+ if (sizeof (e4) != 4 * 28)
return 13;
- if (sizeof (f) != 2 * 8 + 32)
+ if (sizeof (f) != 2 * 4 + 28)
return 14;
- if (__alignof__ (f.q) != 8)
+ if (__alignof__ (f.q) != 4)
return 15;
return 0;
}
--- /dev/null
+// 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);
+}