Unfortunately another PCS bug has come to light with the layout of
structs whose alignment is dominated by a 64-bit bitfield element.
Such fields in the type list appear to have alignment 1, but in
reality, for the purposes of alignment of the underlying structure,
the alignment is derived from the underlying bitfield's type. We've
been getting this wrong since support for over-aligned record types
was added several releases back. Worse still, the existing code may
generate unaligned memory accesses that may fault on some versions of
the architecture.
I've taken the opportunity to add a few more tests that check the
passing arguments with overalignment in the PCS. Looking through the
existing tests it looked like they were really only checking
self-consistency and not the precise location of the arguments.
PR target/88469
gcc:
* config/arm/arm.c (arm_needs_doubleword_align): Return 2 if a record's
alignment is dominated by a bitfield with 64-bit aligned base type.
(arm_function_arg): Emit a warning if the alignment has changed since
earlier GCC releases.
(arm_function_arg_boundary): Likewise.
(arm_setup_incoming_varargs): Likewise.
gcc/testsuite:
* gcc.target/arm/aapcs/bitfield1.c: New test.
* gcc.target/arm/aapcs/overalign_rec1.c: New test.
* gcc.target/arm/aapcs/overalign_rec2.c: New test.
* gcc.target/arm/aapcs/overalign_rec3.c: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@268151
138bc75d-0d04-0410-961f-
82ee72b054a4
+2019-01-22 Richard Earnshaw <rearnsha@arm.com>
+
+ PR target/88469
+ * config/arm/arm.c (arm_needs_doubleword_align): Return 2 if a record's
+ alignment is dominated by a bitfield with 64-bit aligned base type.
+ (arm_function_arg): Emit a warning if the alignment has changed since
+ earlier GCC releases.
+ (arm_function_arg_boundary): Likewise.
+ (arm_setup_incoming_varargs): Likewise.
+
2019-01-22 Richard Biener <rguenther@suse.de>
PR tree-optimization/88862
}
}
-/* Return 1 if double word alignment is required for argument passing.
+/* Return 2 if double word alignment is required for argument passing,
+ but wasn't required before the fix for PR88469.
+ Return 1 if double word alignment is required for argument passing.
Return -1 if double word alignment used to be required for argument
passing before PR77728 ABI fix, but is not required anymore.
Return 0 if double word alignment is not required and wasn't requried
return TYPE_ALIGN (TREE_TYPE (type)) > PARM_BOUNDARY;
int ret = 0;
- /* Record/aggregate types: Use greatest member alignment of any member. */
+ int ret2 = 0;
+ /* Record/aggregate types: Use greatest member alignment of any member. */
for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
if (DECL_ALIGN (field) > PARM_BOUNDARY)
{
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;
return ret;
}
inform (input_location, "parameter passing for argument of type "
"%qT changed in GCC 7.1", type);
else if (res > 0)
- pcum->nregs++;
+ {
+ pcum->nregs++;
+ if (res > 1 && warn_psabi)
+ inform (input_location, "parameter passing for argument of type "
+ "%qT changed in GCC 9.1", type);
+ }
}
/* Only allow splitting an arg between regs and memory if all preceding
if (res < 0 && warn_psabi)
inform (input_location, "parameter passing for argument of type %qT "
"changed in GCC 7.1", type);
+ if (res > 1 && warn_psabi)
+ inform (input_location, "parameter passing for argument of type "
+ "%qT changed in GCC 9.1", type);
return res > 0 ? DOUBLEWORD_ALIGNMENT : PARM_BOUNDARY;
}
inform (input_location, "parameter passing for argument of "
"type %qT changed in GCC 7.1", type);
else if (res > 0)
- nregs++;
+ {
+ nregs++;
+ if (res > 1 && warn_psabi)
+ inform (input_location,
+ "parameter passing for argument of type "
+ "%qT changed in GCC 9.1", type);
+ }
}
}
else
+2019-01-22 Richard Earnshaw <rearnsha@arm.com>
+
+ PR target/88469
+ * gcc.target/arm/aapcs/bitfield1.c: New test.
+ * gcc.target/arm/aapcs/overalign_rec1.c: New test.
+ * gcc.target/arm/aapcs/overalign_rec2.c: New test.
+ * gcc.target/arm/aapcs/overalign_rec3.c: New test.
+
2019-01-22 Manfred Schwarb <manfred99@gmx.ch>
* gfortran.dg/array_function_5.f90: Fix a dg directive.
--- /dev/null
+/* Test AAPCS layout (alignment). */
+
+/* { dg-do run { target arm_eabi } } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-options "-O" } */
+
+#ifndef IN_FRAMEWORK
+#define TESTFILE "bitfield1.c"
+
+struct bf
+{
+ unsigned long long a: 61;
+ unsigned b: 3;
+} 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
--- /dev/null
+/* Test AAPCS layout (alignment). */
+
+/* { dg-do run { target arm_eabi } } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-options "-O" } */
+
+#ifndef IN_FRAMEWORK
+#define TESTFILE "overalign_rec1.c"
+
+typedef struct __attribute__((aligned(8)))
+{
+ int a;
+ int b;
+} overaligned;
+
+overaligned v = {1, 3};
+overaligned w = {33, 99};
+
+#include "abitest.h"
+#else
+ ARG (int, 7, R0)
+ /* Overalignment is ignored for the purposes of parameter passing. */
+ ARG (overaligned, v, R1)
+ ARG (int, 11, R3)
+ ARG (int, 9, STACK)
+ LAST_ARG (overaligned, w, STACK+4)
+#endif
--- /dev/null
+/* Test AAPCS layout (alignment). */
+
+/* { dg-do run { target arm_eabi } } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-options "-O" } */
+
+#ifndef IN_FRAMEWORK
+#define TESTFILE "overalign_rec2.c"
+
+typedef struct
+{
+ int __attribute__((aligned(8))) a;
+ int b;
+} overaligned;
+
+overaligned v = {1, 3};
+overaligned w = {33, 99};
+
+#include "abitest.h"
+#else
+ ARG (int, 7, R0)
+ ARG (overaligned, v, R2)
+ ARG (int, 9, STACK)
+ LAST_ARG (overaligned, w, STACK+8)
+#endif
--- /dev/null
+/* Test AAPCS layout (alignment). */
+
+/* { dg-do run { target arm_eabi } } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-options "-O" } */
+
+#ifndef IN_FRAMEWORK
+#define TESTFILE "overalign_rec3.c"
+
+typedef struct
+{
+ int __attribute__((aligned(16))) a;
+ int b;
+} overaligned;
+
+overaligned v = {1, 3};
+overaligned w = {33, 99};
+
+#include "abitest.h"
+#else
+ ARG (int, 7, R0)
+ /* Objects with alignment > 8 are passed with alignment 8. */
+ ARG (overaligned, v, R2)
+ ARG (int, 9, STACK+8)
+ ARG (int, 10, STACK+12)
+ ARG (int, 11, STACK+16)
+ LAST_ARG (overaligned, w, STACK+24)
+#endif