On 22/01/2019 14:50, Jakub Jelinek wrote: > On Tue, Jan 22, 2019 at 02:10:59PM +0000, Richard Earnshaw (lists) wrote: >> @@ -6630,6 +6633,13 @@ arm_needs_doubleword_align (machine_mode mode, >> const_tree type) >> Make sure we can warn about that with -Wpsabi. */ >> ret = -1; >> } >> + else if (TREE_CODE (field) == FIELD_DECL >> + && DECL_BIT_FIELD (field) >> + && TYPE_ALIGN (DECL_BIT_FIELD_TYPE (field)) > PARM_BOUNDARY) >> + ret2 = 1; >> + >> + if (ret2) >> + return 2; > > Can you double check what behavior you want e.g. for: > typedef int alint __attribute__((aligned (8))); > struct S1 { alint a : 17; alint b : 15; }; > struct __attribute__((packed)) S2 { char a; long long b : 12; long long c : > 20; long long d : 32; }; > struct __attribute__((packed)) S3 { char a; alint b : 12; alint c : 20; }; > and passing/returning of S1/S2/S3? > TYPE_ALIGN (DECL_BIT_FIELD_TYPE (field)) is I think alint in this case, > and for packed structures, I guess DECL_ALIGN of the fields is generally > small, but TYPE_ALIGN might not be.
If TYPE_ALIGN says that we need DWORD alignment then we never look inside the bitfield, it's only when that is less than 64-bit alignment that we look deeper. But Richi pointed out that int64_t a : 16; can be internally transformed into a 'short' so we need to look at DECL_BIT_FIELD_TYPE not at DECL_BIT_FIELD. I've also added a test for bitfields that are based on overaligned types. Fixed thusly. PR target/88469 gcc: * config/arm/arm.c (arm_needs_double_word_align): Check DECL_BIT_FIELD_TYPE. gcc/testsuite: * gcc.target/arm/aapcs/bitfield2.c: New test. * gcc.target/arm/aapcs/bitfield3.c: New test. > > Jakub >
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index c6fbda25e96..16e22eed871 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -6634,7 +6634,7 @@ arm_needs_doubleword_align (machine_mode mode, const_tree type) ret = -1; } else if (TREE_CODE (field) == FIELD_DECL - && DECL_BIT_FIELD (field) + && DECL_BIT_FIELD_TYPE (field) && TYPE_ALIGN (DECL_BIT_FIELD_TYPE (field)) > PARM_BOUNDARY) ret2 = 1; diff --git a/gcc/testsuite/gcc.target/arm/aapcs/bitfield2.c b/gcc/testsuite/gcc.target/arm/aapcs/bitfield2.c new file mode 100644 index 00000000000..9cbe2b08962 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/aapcs/bitfield2.c @@ -0,0 +1,26 @@ +/* Test AAPCS layout (alignment). */ + +/* { dg-do run { target arm_eabi } } */ +/* { dg-require-effective-target arm32 } */ +/* { dg-options "-O" } */ + +#ifndef IN_FRAMEWORK +#define TESTFILE "bitfield2.c" + +typedef unsigned int alint __attribute__((aligned (8))); + +struct bf +{ + alint a: 17; + alint b: 15; +} v = {1, 1}; + +#include "abitest.h" +#else + ARG (int, 7, R0) + ARG (int, 9, R1) + ARG (int, 11, R2) + /* Alignment of the bitfield type should affect alignment of the overall + type, so R3 not used. */ + LAST_ARG (struct bf, v, STACK) +#endif diff --git a/gcc/testsuite/gcc.target/arm/aapcs/bitfield3.c b/gcc/testsuite/gcc.target/arm/aapcs/bitfield3.c new file mode 100644 index 00000000000..0386e669c2d --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/aapcs/bitfield3.c @@ -0,0 +1,26 @@ +/* Test AAPCS layout (alignment). */ + +/* { dg-do run { target arm_eabi } } */ +/* { dg-require-effective-target arm32 } */ +/* { dg-options "-O" } */ + +#ifndef IN_FRAMEWORK +#define TESTFILE "bitfield3.c" + +struct bf +{ + /* Internally this may be mapped to unsigned short. Ensure we still + check the original declaration. */ + unsigned long long a: 16; + unsigned b: 3; +} v = {1, 3}; + +#include "abitest.h" +#else + ARG (int, 7, R0) + ARG (int, 9, R1) + ARG (int, 11, R2) + /* Alignment of the bitfield type should affect alignment of the overall + type, so R3 not used. */ + LAST_ARG (struct bf, v, STACK) +#endif