diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2017-04-25 16:47:32 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2017-04-25 16:47:32 +0000 |
commit | 8f9e51281cb62566c35d40db97b4245983639ec2 (patch) | |
tree | cfce85ddd83a61a40259792f7a8e1d473de62493 /gcc/config/arm | |
parent | a4c2e86c30cad82b30fe5a611c01a91289178df1 (diff) | |
download | gcc-8f9e51281cb62566c35d40db97b4245983639ec2.tar.gz |
PR target/77728
* config/arm/arm.c: Include gimple.h.
(aapcs_layout_arg): Emit -Wpsabi note if arm_needs_doubleword_align
returns negative, increment ncrn only if it returned positive.
(arm_needs_doubleword_align): Return int instead of bool,
ignore DECL_ALIGN of non-FIELD_DECL TYPE_FIELDS chain
members, but if there is any such non-FIELD_DECL
> PARM_BOUNDARY aligned decl, return -1 instead of false.
(arm_function_arg): Emit -Wpsabi note if arm_needs_doubleword_align
returns negative, increment nregs only if it returned positive.
(arm_setup_incoming_varargs): Likewise.
(arm_function_arg_boundary): Emit -Wpsabi note if
arm_needs_doubleword_align returns negative, return
DOUBLEWORD_ALIGNMENT only if it returned positive.
testsuite/
* g++.dg/abi/pr77728-1.C: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-7-branch@247259 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/arm')
-rw-r--r-- | gcc/config/arm/arm.c | 78 |
1 files changed, 61 insertions, 17 deletions
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index f3a6b64b168..d719020dcde 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -64,6 +64,7 @@ #include "rtl-iter.h" #include "optabs-libfuncs.h" #include "gimplify.h" +#include "gimple.h" /* This file should be included last. */ #include "target-def.h" @@ -81,7 +82,7 @@ struct four_ints /* Forward function declarations. */ static bool arm_const_not_ok_for_debug_p (rtx); -static bool arm_needs_doubleword_align (machine_mode, const_tree); +static int arm_needs_doubleword_align (machine_mode, const_tree); static int arm_compute_static_chain_stack_bytes (void); static arm_stack_offsets *arm_get_frame_offsets (void); static void arm_add_gc_roots (void); @@ -6349,8 +6350,20 @@ aapcs_layout_arg (CUMULATIVE_ARGS *pcum, machine_mode mode, /* C3 - For double-word aligned arguments, round the NCRN up to the next even number. */ ncrn = pcum->aapcs_ncrn; - if ((ncrn & 1) && arm_needs_doubleword_align (mode, type)) - ncrn++; + if (ncrn & 1) + { + int res = arm_needs_doubleword_align (mode, type); + /* Only warn during RTL expansion of call stmts, otherwise we would + warn e.g. during gimplification even on functions that will be + always inlined, and we'd warn multiple times. Don't warn when + called in expand_function_start either, as we warn instead in + arm_function_arg_boundary in that case. */ + if (res < 0 && warn_psabi && currently_expanding_gimple_stmt) + inform (input_location, "parameter passing for argument of type " + "%qT changed in GCC 7.1", type); + else if (res > 0) + ncrn++; + } nregs = ARM_NUM_REGS2(mode, type); @@ -6455,12 +6468,16 @@ arm_init_cumulative_args (CUMULATIVE_ARGS *pcum, tree fntype, } } -/* Return true if mode/type need doubleword alignment. */ -static bool +/* 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 + before either. */ +static int arm_needs_doubleword_align (machine_mode mode, const_tree type) { if (!type) - return PARM_BOUNDARY < GET_MODE_ALIGNMENT (mode); + return GET_MODE_ALIGNMENT (mode) > PARM_BOUNDARY; /* Scalar and vector types: Use natural alignment, i.e. of base type. */ if (!AGGREGATE_TYPE_P (type)) @@ -6470,12 +6487,21 @@ arm_needs_doubleword_align (machine_mode mode, const_tree type) if (TREE_CODE (type) == ARRAY_TYPE) return TYPE_ALIGN (TREE_TYPE (type)) > PARM_BOUNDARY; + int ret = 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) - return true; + { + if (TREE_CODE (field) == FIELD_DECL) + return 1; + else + /* Before PR77728 fix, we were incorrectly considering also + other aggregate fields, like VAR_DECLs, TYPE_DECLs etc. + Make sure we can warn about that with -Wpsabi. */ + ret = -1; + } - return false; + return ret; } @@ -6532,10 +6558,15 @@ arm_function_arg (cumulative_args_t pcum_v, machine_mode mode, } /* Put doubleword aligned quantities in even register pairs. */ - if (pcum->nregs & 1 - && ARM_DOUBLEWORD_ALIGN - && arm_needs_doubleword_align (mode, type)) - pcum->nregs++; + if ((pcum->nregs & 1) && ARM_DOUBLEWORD_ALIGN) + { + int res = arm_needs_doubleword_align (mode, type); + if (res < 0 && warn_psabi) + inform (input_location, "parameter passing for argument of type " + "%qT changed in GCC 7.1", type); + else if (res > 0) + pcum->nregs++; + } /* Only allow splitting an arg between regs and memory if all preceding args were allocated to regs. For args passed by reference we only count @@ -6554,9 +6585,15 @@ arm_function_arg (cumulative_args_t pcum_v, machine_mode mode, static unsigned int arm_function_arg_boundary (machine_mode mode, const_tree type) { - return (ARM_DOUBLEWORD_ALIGN && arm_needs_doubleword_align (mode, type) - ? DOUBLEWORD_ALIGNMENT - : PARM_BOUNDARY); + if (!ARM_DOUBLEWORD_ALIGN) + return PARM_BOUNDARY; + + int res = arm_needs_doubleword_align (mode, type); + if (res < 0 && warn_psabi) + inform (input_location, "parameter passing for argument of type %qT " + "changed in GCC 7.1", type); + + return res > 0 ? DOUBLEWORD_ALIGNMENT : PARM_BOUNDARY; } static int @@ -26516,8 +26553,15 @@ arm_setup_incoming_varargs (cumulative_args_t pcum_v, if (pcum->pcs_variant <= ARM_PCS_AAPCS_LOCAL) { nregs = pcum->aapcs_ncrn; - if ((nregs & 1) && arm_needs_doubleword_align (mode, type)) - nregs++; + if (nregs & 1) + { + int res = arm_needs_doubleword_align (mode, type); + if (res < 0 && warn_psabi) + inform (input_location, "parameter passing for argument of " + "type %qT changed in GCC 7.1", type); + else if (res > 0) + nregs++; + } } else nregs = pcum->nregs; |