From d7b3369c52cfe15d147d398f00aaf580f6535d6f Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 7 Aug 2002 20:11:00 +0200 Subject: [PATCH] stor-layout.c (place_union_field): Apply ADJUST_FIELD_ALIGN to type_align when PCC_BITFIELD_TYPE_MATTERS. * 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. Co-Authored-By: Richard Henderson From-SVN: r56104 --- gcc/ChangeLog | 20 ++++++++++ gcc/config/i386/i386.c | 15 ++++---- gcc/config/rs6000/aix.h | 7 ---- gcc/config/rs6000/darwin.h | 7 ---- gcc/config/rs6000/linux64.h | 7 ---- gcc/config/rs6000/rs6000-protos.h | 1 + gcc/config/rs6000/rs6000.c | 21 +++++++++++ gcc/config/rs6000/rs6000.h | 4 ++ gcc/config/rs6000/sysv4.h | 7 ---- gcc/doc/tm.texi | 8 ++-- gcc/stor-layout.c | 33 ++++++++++++++--- gcc/testsuite/ChangeLog | 6 +++ gcc/testsuite/g++.dg/abi/bitfield3.C | 20 +++++----- gcc/testsuite/gcc.dg/i386-bitfield1.c | 53 +++++++++++++++++++++++++++ 14 files changed, 155 insertions(+), 54 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/i386-bitfield1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2f3f632d6f17..8b6c6f6f5e57 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,23 @@ +2002-08-07 Jakub Jelinek + Richard Henderson + + * 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 * config/i386/mmintrin.h (__m64): Make the type 64-bit aligned. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 274c9a0632a9..f07ebad251f4 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -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; } - diff --git a/gcc/config/rs6000/aix.h b/gcc/config/rs6000/aix.h index d8dde5bbba81..cd069d7a8d5c 100644 --- a/gcc/config/rs6000/aix.h +++ b/gcc/config/rs6000/aix.h @@ -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) \ diff --git a/gcc/config/rs6000/darwin.h b/gcc/config/rs6000/darwin.h index 81c24e76814b..1fae4d164788 100644 --- a/gcc/config/rs6000/darwin.h +++ b/gcc/config/rs6000/darwin.h @@ -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) \ diff --git a/gcc/config/rs6000/linux64.h b/gcc/config/rs6000/linux64.h index f84e1e3a8334..cab4be91e461 100644 --- a/gcc/config/rs6000/linux64.h +++ b/gcc/config/rs6000/linux64.h @@ -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 diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 19aeb07b9e0c..83f7f21550f0 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -147,6 +147,7 @@ extern void output_mi_thunk PARAMS ((FILE *, tree, int, tree)); 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)); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 7940315fc4bb..0f6b1462eb9b 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -11534,3 +11534,24 @@ 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) + { + if (TARGET_ALTIVEC && TREE_CODE (type) == VECTOR_TYPE) + return 128; + } + else + { + if (TYPE_MODE (type) == DFmode) + return MIN (32, computed); + } + + return computed; +} diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 8c77dd558c06..ecdc1109ba9a 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -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) \ diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h index b807bb739229..f55588675423 100644 --- a/gcc/config/rs6000/sysv4.h +++ b/gcc/config/rs6000/sysv4.h @@ -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. */ diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index e98ed3fd9b3c..2e3ad05c25c2 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -1072,9 +1072,11 @@ by the @code{__attribute__ ((aligned (@var{n})))} construct. @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 diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index 2db46754838b..e20e49879906 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a5d117d973c7..1ebfed27f477 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2002-08-07 Jakub Jelinek + Richard Henderson + + * gcc.dg/i386-bitfield1.c: New test. + * g++.dg/abi/bitfield3.C: New test. + 2002-08-01 Benjamin Kosnik * g++.old-deja/g++.abi/ptrflags.C (expect): Change diff --git a/gcc/testsuite/g++.dg/abi/bitfield3.C b/gcc/testsuite/g++.dg/abi/bitfield3.C index 1e599355f697..da7b92fad7f9 100644 --- a/gcc/testsuite/g++.dg/abi/bitfield3.C +++ b/gcc/testsuite/g++.dg/abi/bitfield3.C @@ -56,25 +56,25 @@ int main (void) 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; } diff --git a/gcc/testsuite/gcc.dg/i386-bitfield1.c b/gcc/testsuite/gcc.dg/i386-bitfield1.c new file mode 100644 index 000000000000..8045a677e6c9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/i386-bitfield1.c @@ -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); +} -- 2.47.2