commit ed0241d122fc56ab60599ef0addac66c303e569b Author: Ramana Radhakrishnan Date: Sat Apr 22 02:29:37 2017 +0100 arm implementation for fix for PR77728 fixup missing bits fixup changes diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index f3a6b64b168..ec1f5f450c0 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -79,9 +79,18 @@ struct four_ints int i[4]; }; +struct arm_dbl_word_alignment +{ + /* Double word alignment is required for argument passing. */ + bool dwa_needed; + /* Warn if double word alignment was thought to be required because + of the issue from PR77728. */ + bool wdwa_needed; +}; + /* Forward function declarations. */ static bool arm_const_not_ok_for_debug_p (rtx); -static bool arm_needs_doubleword_align (machine_mode, const_tree); +static struct arm_dbl_word_alignment 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,7 +6358,9 @@ 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)) + struct arm_dbl_word_alignment res = arm_needs_doubleword_align (mode, + type); + if ((ncrn & 1) && res.dwa_needed) ncrn++; nregs = ARM_NUM_REGS2(mode, type); @@ -6456,26 +6467,53 @@ arm_init_cumulative_args (CUMULATIVE_ARGS *pcum, tree fntype, } /* Return true if mode/type need doubleword alignment. */ -static bool +static struct arm_dbl_word_alignment arm_needs_doubleword_align (machine_mode mode, const_tree type) { + struct arm_dbl_word_alignment a = { false, false}; + if (!type) - return PARM_BOUNDARY < GET_MODE_ALIGNMENT (mode); + { + a.dwa_needed = PARM_BOUNDARY < GET_MODE_ALIGNMENT (mode); + return a; + } /* Scalar and vector types: Use natural alignment, i.e. of base type. */ if (!AGGREGATE_TYPE_P (type)) - return TYPE_ALIGN (TYPE_MAIN_VARIANT (type)) > PARM_BOUNDARY; + { + a.dwa_needed = TYPE_ALIGN (TYPE_MAIN_VARIANT (type)) > PARM_BOUNDARY; + return a; + } /* Array types: Use member alignment of element type. */ if (TREE_CODE (type) == ARRAY_TYPE) - return TYPE_ALIGN (TREE_TYPE (type)) > PARM_BOUNDARY; + { + a.dwa_needed = TYPE_ALIGN (TREE_TYPE (type)) > PARM_BOUNDARY; + return a; + } + + unsigned int alignment = 0; + unsigned int warn_align = 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 (DECL_ALIGN (field) > PARM_BOUNDARY) + { + if (TREE_CODE (field) == FIELD_DECL) + { + alignment = MAX (alignment, DECL_ALIGN (field)); + a.dwa_needed = true; + } + else + warn_align = MAX (warn_align, DECL_ALIGN (field)); + } + } - return false; + if (warn_align > alignment && !a.dwa_needed) + a.wdwa_needed = true; + + return a; } @@ -6532,9 +6570,16 @@ arm_function_arg (cumulative_args_t pcum_v, machine_mode mode, } /* Put doubleword aligned quantities in even register pairs. */ - if (pcum->nregs & 1 + struct arm_dbl_word_alignment res = arm_needs_doubleword_align (mode, type); + + if ((pcum->nregs & 1) && ARM_DOUBLEWORD_ALIGN && res.wdwa_needed && warn_psabi) + inform (input_location, + "parameter passing for argument of type %qT changed in GCC 7.1", + type); + + if ((pcum->nregs & 1) && ARM_DOUBLEWORD_ALIGN - && arm_needs_doubleword_align (mode, type)) + && res.dwa_needed) pcum->nregs++; /* Only allow splitting an arg between regs and memory if all preceding @@ -6554,7 +6599,14 @@ 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) + struct arm_dbl_word_alignment res = arm_needs_doubleword_align (mode, type); + + if (ARM_DOUBLEWORD_ALIGN && res.wdwa_needed && warn_psabi) + inform (input_location, + "parameter passing for argument of type %qT changed in GCC 7.1", + type); + + return (ARM_DOUBLEWORD_ALIGN && res.dwa_needed ? DOUBLEWORD_ALIGNMENT : PARM_BOUNDARY); } @@ -26516,7 +26568,12 @@ 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)) + struct arm_dbl_word_alignment res = arm_needs_doubleword_align (mode, + type); + if ((nregs & 1) && res.wdwa_needed && warn_psabi) + inform (input_location, "parameter passing for argument of type %qT " + "changed in GCC 7.1", type); + if ((nregs & 1) && res.dwa_needed) nregs++; } else