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