aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/aarch64
diff options
context:
space:
mode:
authorRamana Radhakrishnan <ramana.radhakrishnan@arm.com>2017-04-25 13:56:10 +0000
committerJakub Jelinek <jakub@redhat.com>2017-04-25 13:56:10 +0000
commit12de10439a90acc523ca809740e515b14f057d17 (patch)
tree2b6686e8eb79dae9575da1f88b15243d8381fa1d /gcc/config/aarch64
parentccccf360aec010f2144cca45e431099c611c0c20 (diff)
PR target/77728
* config/aarch64/aarch64.c (struct aarch64_fn_arg_alignment): New type. (aarch64_function_arg_alignment): Return aarch64_fn_arg_alignment struct. Ignore DECL_ALIGN of decls other than FIELD_DECL for the alignment computation, but return their maximum in warn_alignment. (aarch64_layout_arg): Adjust aarch64_function_arg_alignment caller. Emit a -Wpsabi note if warn_alignment is 16 bytes, but alignment is smaller. (aarch64_function_arg_boundary): Likewise. Simplify using MIN/MAX. (aarch64_gimplify_va_arg_expr): Adjust aarch64_function_arg_alignment caller. testsuite/ * g++.dg/abi/pr77728-2.C: New test. git-svn-id: https://gcc.gnu.org/svn/gcc/branches/gcc-7-branch@247241 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/aarch64')
-rw-r--r--gcc/config/aarch64/aarch64.c101
1 files changed, 75 insertions, 26 deletions
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 2e385c43e96..1e58e9d7819 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -2256,33 +2256,58 @@ aarch64_vfp_is_call_candidate (cumulative_args_t pcum_v, machine_mode mode,
NULL);
}
-/* Given MODE and TYPE of a function argument, return the alignment in
+struct aarch64_fn_arg_alignment
+{
+ /* Alignment for FIELD_DECLs in function arguments. */
+ unsigned int alignment;
+ /* Alignment for decls other than FIELD_DECLs in function arguments. */
+ unsigned int warn_alignment;
+};
+
+/* Given MODE and TYPE of a function argument, return a pair of alignments in
bits. The idea is to suppress any stronger alignment requested by
the user and opt for the natural alignment (specified in AAPCS64 \S 4.1).
This is a helper function for local use only. */
-static unsigned int
+static struct aarch64_fn_arg_alignment
aarch64_function_arg_alignment (machine_mode mode, const_tree type)
{
+ struct aarch64_fn_arg_alignment aa;
+ aa.alignment = 0;
+ aa.warn_alignment = 0;
+
if (!type)
- return GET_MODE_ALIGNMENT (mode);
+ {
+ aa.alignment = GET_MODE_ALIGNMENT (mode);
+ return aa;
+ }
+
if (integer_zerop (TYPE_SIZE (type)))
- return 0;
+ return aa;
gcc_assert (TYPE_MODE (type) == mode);
if (!AGGREGATE_TYPE_P (type))
- return TYPE_ALIGN (TYPE_MAIN_VARIANT (type));
+ {
+ aa.alignment = TYPE_ALIGN (TYPE_MAIN_VARIANT (type));
+ return aa;
+ }
if (TREE_CODE (type) == ARRAY_TYPE)
- return TYPE_ALIGN (TREE_TYPE (type));
-
- unsigned int alignment = 0;
+ {
+ aa.alignment = TYPE_ALIGN (TREE_TYPE (type));
+ return aa;
+ }
for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
- alignment = std::max (alignment, DECL_ALIGN (field));
+ {
+ if (TREE_CODE (field) == FIELD_DECL)
+ aa.alignment = std::max (aa.alignment, DECL_ALIGN (field));
+ else
+ aa.warn_alignment = std::max (aa.warn_alignment, DECL_ALIGN (field));
+ }
- return alignment;
+ return aa;
}
/* Layout a function argument according to the AAPCS64 rules. The rule
@@ -2369,24 +2394,39 @@ aarch64_layout_arg (cumulative_args_t pcum_v, machine_mode mode,
entirely general registers. */
if (allocate_ncrn && (ncrn + nregs <= NUM_ARG_REGS))
{
- unsigned int alignment = aarch64_function_arg_alignment (mode, type);
gcc_assert (nregs == 0 || nregs == 1 || nregs == 2);
/* C.8 if the argument has an alignment of 16 then the NGRN is
rounded up to the next even number. */
- if (nregs == 2 && alignment == 16 * BITS_PER_UNIT && ncrn % 2)
- {
- ++ncrn;
- gcc_assert (ncrn + nregs <= NUM_ARG_REGS);
+ if (nregs == 2 && ncrn % 2)
+ {
+ struct aarch64_fn_arg_alignment aa
+ = aarch64_function_arg_alignment (mode, type);
+
+ /* The == 16 * BITS_PER_UNIT instead of >= 16 * BITS_PER_UNIT
+ comparisons are there because for > 16 * BITS_PER_UNIT
+ alignment nregs should be > 2 and therefore it should be
+ passed by reference rather than value. */
+ if (aa.warn_alignment == 16 * BITS_PER_UNIT
+ && aa.alignment < aa.warn_alignment
+ && warn_psabi
+ && currently_expanding_gimple_stmt)
+ inform (input_location,
+ "parameter passing for argument of type %qT "
+ "changed in GCC 7.1", type);
+ else if (aa.alignment == 16 * BITS_PER_UNIT)
+ {
+ ++ncrn;
+ gcc_assert (ncrn + nregs <= NUM_ARG_REGS);
+ }
}
+
/* NREGS can be 0 when e.g. an empty structure is to be passed.
A reg is still generated for it, but the caller should be smart
enough not to use it. */
if (nregs == 0 || nregs == 1 || GET_MODE_CLASS (mode) == MODE_INT)
- {
- pcum->aapcs_reg = gen_rtx_REG (mode, R0_REGNUM + ncrn);
- }
+ pcum->aapcs_reg = gen_rtx_REG (mode, R0_REGNUM + ncrn);
else
{
rtx par;
@@ -2414,7 +2454,10 @@ aarch64_layout_arg (cumulative_args_t pcum_v, machine_mode mode,
this argument and align the total size if necessary. */
on_stack:
pcum->aapcs_stack_words = size / UNITS_PER_WORD;
- if (aarch64_function_arg_alignment (mode, type) == 16 * BITS_PER_UNIT)
+ struct aarch64_fn_arg_alignment aa
+ = aarch64_function_arg_alignment (mode, type);
+
+ if (aa.alignment == 16 * BITS_PER_UNIT)
pcum->aapcs_stack_size = ROUND_UP (pcum->aapcs_stack_size,
16 / UNITS_PER_WORD);
return;
@@ -2505,13 +2548,17 @@ aarch64_function_arg_regno_p (unsigned regno)
static unsigned int
aarch64_function_arg_boundary (machine_mode mode, const_tree type)
{
- unsigned int alignment = aarch64_function_arg_alignment (mode, type);
+ struct aarch64_fn_arg_alignment aa
+ = aarch64_function_arg_alignment (mode, type);
+ aa.alignment = MIN (MAX (aa.alignment, PARM_BOUNDARY), STACK_BOUNDARY);
+ aa.warn_alignment
+ = MIN (MAX (aa.warn_alignment, PARM_BOUNDARY), STACK_BOUNDARY);
+
+ if (warn_psabi && aa.warn_alignment > aa.alignment)
+ inform (input_location, "parameter passing for argument of type %qT "
+ "changed in GCC 7.1", type);
- if (alignment < PARM_BOUNDARY)
- alignment = PARM_BOUNDARY;
- if (alignment > STACK_BOUNDARY)
- alignment = STACK_BOUNDARY;
- return alignment;
+ return aa.alignment;
}
/* For use by FUNCTION_ARG_PADDING (MODE, TYPE).
@@ -10211,7 +10258,9 @@ aarch64_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
stack = build3 (COMPONENT_REF, TREE_TYPE (f_stack), unshare_expr (valist),
f_stack, NULL_TREE);
size = int_size_in_bytes (type);
- align = aarch64_function_arg_alignment (mode, type) / BITS_PER_UNIT;
+ struct aarch64_fn_arg_alignment aa
+ = aarch64_function_arg_alignment (mode, type);
+ align = aa.alignment / BITS_PER_UNIT;
dw_align = false;
adjust = 0;