From ad9335eb67bb817cf650f4489aa0b7a9ef86c48d Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 7 Aug 2002 23:05:16 +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 DECL_USER_ALIGN here. * 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: Update. Co-Authored-By: Richard Henderson From-SVN: r56107 --- gcc/ChangeLog | 19 ++++++++++ gcc/config/i386/i386.c | 8 ++-- 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, 151 insertions(+), 50 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/i386-bitfield1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d7659d080dd..3490b504781 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,22 @@ +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 + DECL_USER_ALIGN here. + * 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-07 Neil Booth * Makefile.in (c-opts.o, c-common.o, C_AND_OBJC_OBJS): Update. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index ae2fe990db3..5ef4e7637c6 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -13818,10 +13818,12 @@ 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)); + 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) diff --git a/gcc/config/rs6000/aix.h b/gcc/config/rs6000/aix.h index 5e619e64d05..b639025c9cb 100644 --- a/gcc/config/rs6000/aix.h +++ b/gcc/config/rs6000/aix.h @@ -111,13 +111,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 417cfb9697d..6b6ca11dddb 100644 --- a/gcc/config/rs6000/darwin.h +++ b/gcc/config/rs6000/darwin.h @@ -196,13 +196,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 a1f162e0558..1d9b1a1d9f0 100644 --- a/gcc/config/rs6000/linux64.h +++ b/gcc/config/rs6000/linux64.h @@ -72,13 +72,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 42563d30378..3725c7fe9da 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -151,6 +151,7 @@ extern void setup_incoming_varargs PARAMS ((CUMULATIVE_ARGS *, int *, int)); extern struct rtx_def *rs6000_va_arg PARAMS ((tree, tree)); extern void output_mi_thunk PARAMS ((FILE *, tree, int, tree)); +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 3e6a9a93599..382f47bc224 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -13115,3 +13115,24 @@ rs6000_xcoff_encode_section_info (decl, first) && ! DECL_WEAK (decl)) SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1; } + +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 35e9f098cc6..a502d525d4c 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -631,6 +631,10 @@ extern int rs6000_default_long_calls; /* 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 ae589fd948e..24a5c9c5d7b 100644 --- a/gcc/config/rs6000/sysv4.h +++ b/gcc/config/rs6000/sysv4.h @@ -380,12 +380,6 @@ do { \ /* Real stack boundary as mandated by the appropriate ABI. */ #define ABI_STACK_BOUNDARY ((TARGET_EABI && !TARGET_ALTIVEC_ABI) ? 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 @@ -396,7 +390,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 12f6ff7399d..d13b53ee4a4 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -1068,9 +1068,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 753e41d29ad..5a4041e5af0 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -671,7 +671,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); @@ -685,10 +686,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 @@ -785,7 +790,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. @@ -829,6 +835,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)) @@ -917,6 +928,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 + @@ -946,6 +962,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 63175ca3123..2438925246b 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: Update. + 2002-08-07 Neil Booth * objc.dg/const-str-2.m: Update. diff --git a/gcc/testsuite/g++.dg/abi/bitfield3.C b/gcc/testsuite/g++.dg/abi/bitfield3.C index 1e599355f69..da7b92fad7f 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 00000000000..8045a677e6c --- /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.30.2