From patchwork Mon Aug 19 15:20:29 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 1149342 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-507267-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=arm.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="LfsVFXj6"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46ByLT2bbGz9s3Z for ; Tue, 20 Aug 2019 01:21:04 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:references:date:in-reply-to:message-id:mime-version :content-type; q=dns; s=default; b=vS/wSE9QFnL56cssjf1BAOwBYgsMt mcgvHs8nTHVXnQLWkz4L7i8C0Vpmb2zrgzYuJ4nvJIKi2SMuhGw/Yb4ddk7fkIUQ aF3Pqyv4eyxJJAoCpRBxfRS12l2auUU2OI+YFWp0HwpYoOoN/fMceD4uocFmpr5h 7K+vOQfoLu2bC4= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:references:date:in-reply-to:message-id:mime-version :content-type; s=default; bh=mhvccZqeUFJ6yX6tcf74dHXhT/E=; b=Lfs VFXj6YwbGS8r69JaM1L5/P9p0bjtYHKVmcxWplYoaTd7MGTuivTszTKHQsSlz+7d e1v/IW4R6fvlf3LaBkJXcHuqyE6ElXlkqOrGa/0YIHdgsTxtH9ezOkcD8NptjPa4 clznj/ngBxIdP7BhSTVMVnotxVw4OJWKxHzCf7sY= Received: (qmail 20991 invoked by alias); 19 Aug 2019 15:20:37 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 20940 invoked by uid 89); 19 Aug 2019 15:20:37 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-8.5 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, SPF_PASS autolearn=ham version=3.3.1 spammy= X-HELO: foss.arm.com Received: from foss.arm.com (HELO foss.arm.com) (217.140.110.172) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 19 Aug 2019 15:20:32 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id F2873344 for ; Mon, 19 Aug 2019 08:20:30 -0700 (PDT) Received: from localhost (e121540-lin.manchester.arm.com [10.32.99.62]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 7DF253F718 for ; Mon, 19 Aug 2019 08:20:30 -0700 (PDT) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, richard.sandiford@arm.com Subject: [09/13] Use function_arg_info for TARGET_MUST_PASS_IN_STACK References: Date: Mon, 19 Aug 2019 16:20:29 +0100 In-Reply-To: (Richard Sandiford's message of "Mon, 19 Aug 2019 16:11:12 +0100") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.1 (gnu/linux) MIME-Version: 1.0 X-IsSubscribed: yes Use function_arg_info for TARGET_MUST_PASS_IN_STACK. The hook is passed the promoted mode instead of the original type mode. The expr.h reference in the documentation is no longer correct, but pointing to calls.h or calls.c doesn't help much either. I just left this as-is since it's not related to the point of the series. After previous changes, most places already pass arg.mode and arg.type. Only i386 and mcore needed to construct a new one out of nothing. rs6000 needs to construct one slightly earlier than before. 2019-08-19 Richard Sandiford gcc/ * target.def (must_pass_in_stack): Take a function_arg_info instead of a mode and a type. * doc/tm.texi: Regenerate. * calls.h (must_pass_in_stack_var_size): Take a function_arg_info instead of a mode and a type. (must_pass_in_stack_var_size_or_pad): Likewise. * calls.c (must_pass_in_stack_var_size): Likewise. (must_pass_in_stack_var_size_or_pad): Likewise. (initialize_argument_information): Update call to targetm.calls.must_pass_in_stack. (must_pass_va_arg_on_stack): Likewise. * function.c (assign_parm_find_entry_rtl): Likewise. * targhooks.c (hook_pass_by_reference_must_pass_in_stack): Likewise. * config/alpha/alpha.c (alpha_function_arg): Likewise. (alpha_function_arg_advance): Likewise. * config/cr16/cr16.c (cr16_function_arg): Likewise. (cr16_function_arg_advance): Likewise. * config/cris/cris.c (cris_pass_by_reference): Likewise. (cris_arg_partial_bytes): Likewise. * config/iq2000/iq2000.c (iq2000_pass_by_reference): Likewise. * config/lm32/lm32.c (lm32_function_arg): Likewise. * config/mcore/mcore.c (mcore_num_arg_regs): Likewise. (mcore_function_arg, mcore_arg_partial_bytes): Likewise. * config/mips/mips.c (mips_pass_by_reference): Likewise. * config/mmix/mmix.c (mmix_function_arg_advance): Likewise. (mmix_function_arg_1, mmix_pass_by_reference): Likewise. * config/sh/sh.c (sh_pass_by_reference): Likewise. * config/stormy16/stormy16.c (xstormy16_function_arg): Likewise. * config/xtensa/xtensa.c (xtensa_function_arg_advance): Likewise. * config/arm/arm.c (arm_must_pass_in_stack): Take a function_arg_info instead of a mode and a type. * config/fr30/fr30.c (fr30_must_pass_in_stack): Likewise. (fr30_num_arg_regs): Likewise. (fr30_setup_incoming_varargs): Update calls accordingly. (fr30_arg_partial_bytes, fr30_function_arg): Likewise. (fr30_function_arg_advance): Likewise. * config/frv/frv.c (frv_must_pass_in_stack): Take a function_arg_info instead of a mode and a type. * config/gcn/gcn.c (num_arg_regs): Likewise. (gcn_function_arg, gcn_function_arg_advance): Update calls to num_arg_regs and targetm.calls.must_pass_in_stack. (gcn_arg_partial_bytes): Likewise. * config/i386/i386.c (ix86_must_pass_in_stack): Take a function_arg_info instead of a mode and a type. (classify_argument): Update call accordingly. * config/nds32/nds32.c (nds32_must_pass_in_stack): Take a function_arg_info instead of a mode and a type. * config/rs6000/rs6000-internal.h (rs6000_must_pass_in_stack): Likewise. * config/rs6000/rs6000-call.c (rs6000_must_pass_in_stack): Likewise. (rs6000_parm_needs_stack): Update call accordingly. (setup_incoming_varargs): Likewise. Index: gcc/target.def =================================================================== --- gcc/target.def 2019-08-19 15:58:58.017863486 +0100 +++ gcc/target.def 2019-08-19 15:59:04.289818104 +0100 @@ -4630,11 +4630,11 @@ false.", Need audit to verify that this is the case. */ DEFHOOK (must_pass_in_stack, - "This target hook should return @code{true} if we should not pass @var{type}\n\ + "This target hook should return @code{true} if we should not pass @var{arg}\n\ solely in registers. The file @file{expr.h} defines a\n\ definition that is usually appropriate, refer to @file{expr.h} for additional\n\ documentation.", - bool, (machine_mode mode, const_tree type), + bool, (const function_arg_info &arg), must_pass_in_stack_var_size_or_pad) /* Return true if type TYPE, mode MODE, which is passed by reference, Index: gcc/doc/tm.texi =================================================================== --- gcc/doc/tm.texi 2019-08-19 15:58:58.013863514 +0100 +++ gcc/doc/tm.texi 2019-08-19 15:59:04.289818104 +0100 @@ -4012,8 +4012,8 @@ defined, the argument will be computed i a register. @end deftypefn -@deftypefn {Target Hook} bool TARGET_MUST_PASS_IN_STACK (machine_mode @var{mode}, const_tree @var{type}) -This target hook should return @code{true} if we should not pass @var{type} +@deftypefn {Target Hook} bool TARGET_MUST_PASS_IN_STACK (const function_arg_info @var{&arg}) +This target hook should return @code{true} if we should not pass @var{arg} solely in registers. The file @file{expr.h} defines a definition that is usually appropriate, refer to @file{expr.h} for additional documentation. Index: gcc/calls.h =================================================================== --- gcc/calls.h 2019-08-19 15:58:57.997863631 +0100 +++ gcc/calls.h 2019-08-19 15:59:04.261818304 +0100 @@ -108,8 +108,8 @@ extern int setjmp_call_p (const_tree); extern bool gimple_maybe_alloca_call_p (const gimple *); extern bool gimple_alloca_call_p (const gimple *); extern bool alloca_call_p (const_tree); -extern bool must_pass_in_stack_var_size (machine_mode, const_tree); -extern bool must_pass_in_stack_var_size_or_pad (machine_mode, const_tree); +extern bool must_pass_in_stack_var_size (const function_arg_info &); +extern bool must_pass_in_stack_var_size_or_pad (const function_arg_info &); extern bool must_pass_va_arg_in_stack (tree); extern rtx prepare_call_address (tree, rtx, rtx, rtx *, int, int); extern bool shift_return_value (machine_mode, bool, rtx); Index: gcc/calls.c =================================================================== --- gcc/calls.c 2019-08-19 15:58:57.993863659 +0100 +++ gcc/calls.c 2019-08-19 15:59:04.261818304 +0100 @@ -2139,7 +2139,7 @@ initialize_argument_information (int num if (args[i].reg) args[i].partial = targetm.calls.arg_partial_bytes (args_so_far, arg); - args[i].pass_on_stack = targetm.calls.must_pass_in_stack (mode, type); + args[i].pass_on_stack = targetm.calls.must_pass_in_stack (arg); /* If FUNCTION_ARG returned a (parallel [(expr_list (nil) ...) ...]), it means that we are to pass this arg in the register(s) designated @@ -5839,22 +5839,21 @@ store_one_arg (struct arg_data *arg, rtx return sibcall_failure; } -/* Nonzero if we do not know how to pass TYPE solely in registers. */ +/* Nonzero if we do not know how to pass ARG solely in registers. */ bool -must_pass_in_stack_var_size (machine_mode mode ATTRIBUTE_UNUSED, - const_tree type) +must_pass_in_stack_var_size (const function_arg_info &arg) { - if (!type) + if (!arg.type) return false; /* If the type has variable size... */ - if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) + if (TREE_CODE (TYPE_SIZE (arg.type)) != INTEGER_CST) return true; /* If the type is marked as addressable (it is required to be constructed into the stack)... */ - if (TREE_ADDRESSABLE (type)) + if (TREE_ADDRESSABLE (arg.type)) return true; return false; @@ -5865,28 +5864,28 @@ must_pass_in_stack_var_size (machine_mod /* ??? Should be able to merge these two by examining BLOCK_REG_PADDING. */ bool -must_pass_in_stack_var_size_or_pad (machine_mode mode, const_tree type) +must_pass_in_stack_var_size_or_pad (const function_arg_info &arg) { - if (!type) + if (!arg.type) return false; /* If the type has variable size... */ - if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) + if (TREE_CODE (TYPE_SIZE (arg.type)) != INTEGER_CST) return true; /* If the type is marked as addressable (it is required to be constructed into the stack)... */ - if (TREE_ADDRESSABLE (type)) + if (TREE_ADDRESSABLE (arg.type)) return true; - if (TYPE_EMPTY_P (type)) + if (TYPE_EMPTY_P (arg.type)) return false; /* If the padding and mode of the type is such that a copy into a register would put it into the wrong part of the register. */ - if (mode == BLKmode - && int_size_in_bytes (type) % (PARM_BOUNDARY / BITS_PER_UNIT) - && (targetm.calls.function_arg_padding (mode, type) + if (arg.mode == BLKmode + && int_size_in_bytes (arg.type) % (PARM_BOUNDARY / BITS_PER_UNIT) + && (targetm.calls.function_arg_padding (arg.mode, arg.type) == (BYTES_BIG_ENDIAN ? PAD_UPWARD : PAD_DOWNWARD))) return true; @@ -5899,7 +5898,8 @@ must_pass_in_stack_var_size_or_pad (mach bool must_pass_va_arg_in_stack (tree type) { - return targetm.calls.must_pass_in_stack (TYPE_MODE (type), type); + function_arg_info arg (type, /*named=*/false); + return targetm.calls.must_pass_in_stack (arg); } /* Tell the garbage collector about GTY markers in this source file. */ Index: gcc/function.c =================================================================== --- gcc/function.c 2019-08-19 15:58:58.013863514 +0100 +++ gcc/function.c 2019-08-19 15:59:04.289818104 +0100 @@ -2552,8 +2552,7 @@ assign_parm_find_entry_rtl (struct assig /* If this parameter was passed both in registers and in the stack, use the copy on the stack. */ - if (targetm.calls.must_pass_in_stack (data->promoted_mode, - data->passed_type)) + if (targetm.calls.must_pass_in_stack (arg)) entry_parm = 0; if (entry_parm) Index: gcc/targhooks.c =================================================================== --- gcc/targhooks.c 2019-08-19 15:58:58.017863486 +0100 +++ gcc/targhooks.c 2019-08-19 15:59:04.289818104 +0100 @@ -323,7 +323,7 @@ default_cxx_get_cookie_size (tree type) hook_pass_by_reference_must_pass_in_stack (cumulative_args_t, const function_arg_info &arg) { - return targetm.calls.must_pass_in_stack (arg.mode, arg.type); + return targetm.calls.must_pass_in_stack (arg); } /* Return true if a parameter follows callee copies conventions. This Index: gcc/config/alpha/alpha.c =================================================================== --- gcc/config/alpha/alpha.c 2019-08-19 15:58:50.309919261 +0100 +++ gcc/config/alpha/alpha.c 2019-08-19 15:59:04.265818276 +0100 @@ -5585,7 +5585,7 @@ alpha_function_arg (cumulative_args_t cu num_args = cum->num_args; if (num_args >= 6 - || targetm.calls.must_pass_in_stack (arg.mode, arg.type)) + || targetm.calls.must_pass_in_stack (arg)) return NULL_RTX; } #elif TARGET_ABI_OSF @@ -5596,7 +5596,7 @@ alpha_function_arg (cumulative_args_t cu if (arg.end_marker_p ()) basereg = 16; - else if (targetm.calls.must_pass_in_stack (arg.mode, arg.type)) + else if (targetm.calls.must_pass_in_stack (arg)) return NULL_RTX; } #else @@ -5613,7 +5613,7 @@ alpha_function_arg_advance (cumulative_a const function_arg_info &arg) { CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); - bool onstack = targetm.calls.must_pass_in_stack (arg.mode, arg.type); + bool onstack = targetm.calls.must_pass_in_stack (arg); int increment = onstack ? 6 : ALPHA_ARG_SIZE (arg.mode, arg.type); #if TARGET_ABI_OSF Index: gcc/config/cr16/cr16.c =================================================================== --- gcc/config/cr16/cr16.c 2019-08-19 15:58:50.317919202 +0100 +++ gcc/config/cr16/cr16.c 2019-08-19 15:59:04.273818218 +0100 @@ -606,7 +606,7 @@ cr16_function_arg (cumulative_args_t cum if (arg.end_marker_p ()) return NULL_RTX; - if (targetm.calls.must_pass_in_stack (arg.mode, arg.type) || (cum->ints < 0)) + if (targetm.calls.must_pass_in_stack (arg) || (cum->ints < 0)) return NULL_RTX; if (arg.mode == BLKmode) @@ -672,7 +672,7 @@ cr16_function_arg_advance (cumulative_ar if (!cum->last_parm_in_reg) return; - if (targetm.calls.must_pass_in_stack (arg.mode, arg.type) || (cum->ints < 0)) + if (targetm.calls.must_pass_in_stack (arg) || (cum->ints < 0)) return; if ((arg.mode == SImode) || (arg.mode == HImode) Index: gcc/config/cris/cris.c =================================================================== --- gcc/config/cris/cris.c 2019-08-19 15:58:50.321919175 +0100 +++ gcc/config/cris/cris.c 2019-08-19 15:59:04.273818218 +0100 @@ -4046,7 +4046,7 @@ cris_setup_incoming_varargs (cumulative_ static bool cris_pass_by_reference (cumulative_args_t, const function_arg_info &arg) { - return (targetm.calls.must_pass_in_stack (arg.mode, arg.type) + return (targetm.calls.must_pass_in_stack (arg) || CRIS_FUNCTION_ARG_SIZE (arg.mode, arg.type) > 8); } @@ -4111,7 +4111,7 @@ cris_function_value_regno_p (const unsig cris_arg_partial_bytes (cumulative_args_t ca, const function_arg_info &arg) { if (get_cumulative_args (ca)->regs == CRIS_MAX_ARGS_IN_REGS - 1 - && !targetm.calls.must_pass_in_stack (arg.mode, arg.type) + && !targetm.calls.must_pass_in_stack (arg) && CRIS_FUNCTION_ARG_SIZE (arg.mode, arg.type) > 4 && CRIS_FUNCTION_ARG_SIZE (arg.mode, arg.type) <= 8) return UNITS_PER_WORD; Index: gcc/config/iq2000/iq2000.c =================================================================== --- gcc/config/iq2000/iq2000.c 2019-08-19 15:58:50.329919117 +0100 +++ gcc/config/iq2000/iq2000.c 2019-08-19 15:59:04.277818191 +0100 @@ -2300,7 +2300,7 @@ iq2000_pass_by_reference (cumulative_arg /* We must pass by reference if we would be both passing in registers and the stack. This is because any subsequent partial arg would be handled incorrectly in this case. */ - if (cum && targetm.calls.must_pass_in_stack (arg.mode, arg.type)) + if (cum && targetm.calls.must_pass_in_stack (arg)) { /* Don't pass the actual CUM to FUNCTION_ARG, because we would get double copies of any offsets generated for small structs Index: gcc/config/lm32/lm32.c =================================================================== --- gcc/config/lm32/lm32.c 2019-08-19 15:58:50.329919117 +0100 +++ gcc/config/lm32/lm32.c 2019-08-19 15:59:04.277818191 +0100 @@ -629,7 +629,7 @@ lm32_function_arg (cumulative_args_t cum /* Compute operand 2 of the call insn. */ return GEN_INT (0); - if (targetm.calls.must_pass_in_stack (arg.mode, arg.type)) + if (targetm.calls.must_pass_in_stack (arg)) return NULL_RTX; if (!arg.named Index: gcc/config/mcore/mcore.c =================================================================== --- gcc/config/mcore/mcore.c 2019-08-19 15:58:50.329919117 +0100 +++ gcc/config/mcore/mcore.c 2019-08-19 15:59:04.281818160 +0100 @@ -2713,7 +2713,8 @@ mcore_num_arg_regs (machine_mode mode, c { int size; - if (targetm.calls.must_pass_in_stack (mode, type)) + function_arg_info arg (const_cast (type), mode, /*named=*/true); + if (targetm.calls.must_pass_in_stack (arg)) return 0; if (type && mode == BLKmode) @@ -2803,7 +2804,7 @@ mcore_function_arg (cumulative_args_t cu if (!arg.named || arg.end_marker_p ()) return 0; - if (targetm.calls.must_pass_in_stack (arg.mode, arg.type)) + if (targetm.calls.must_pass_in_stack (arg)) return 0; arg_reg = ROUND_REG (*get_cumulative_args (cum), arg.mode); @@ -2848,7 +2849,7 @@ mcore_arg_partial_bytes (cumulative_args if (!arg.named) return 0; - if (targetm.calls.must_pass_in_stack (arg.mode, arg.type)) + if (targetm.calls.must_pass_in_stack (arg)) return 0; /* REG is not the *hardware* register number of the register that holds Index: gcc/config/mips/mips.c =================================================================== --- gcc/config/mips/mips.c 2019-08-19 15:58:58.005863572 +0100 +++ gcc/config/mips/mips.c 2019-08-19 15:59:04.281818160 +0100 @@ -6252,7 +6252,7 @@ mips_pass_by_reference (cumulative_args_ else { /* If we have a variable-sized parameter, we have no choice. */ - return targetm.calls.must_pass_in_stack (arg.mode, arg.type); + return targetm.calls.must_pass_in_stack (arg); } } Index: gcc/config/mmix/mmix.c =================================================================== --- gcc/config/mmix/mmix.c 2019-08-19 15:58:58.005863572 +0100 +++ gcc/config/mmix/mmix.c 2019-08-19 15:59:04.281818160 +0100 @@ -621,7 +621,7 @@ mmix_function_arg_advance (cumulative_ar CUMULATIVE_ARGS *argsp = get_cumulative_args (argsp_v); int arg_size = MMIX_FUNCTION_ARG_SIZE (arg.mode, arg.type); - argsp->regs = ((targetm.calls.must_pass_in_stack (arg.mode, arg.type) + argsp->regs = ((targetm.calls.must_pass_in_stack (arg) || (arg_size > 8 && !TARGET_LIBFUNC && !argsp->lib)) @@ -647,7 +647,7 @@ mmix_function_arg_1 (const cumulative_ar : NULL_RTX; return (argsp->regs < MMIX_MAX_ARGS_IN_REGS - && !targetm.calls.must_pass_in_stack (arg.mode, arg.type) + && !targetm.calls.must_pass_in_stack (arg) && (GET_MODE_BITSIZE (arg.mode) <= 64 || argsp->lib || TARGET_LIBFUNC)) @@ -686,7 +686,7 @@ mmix_pass_by_reference (cumulative_args_ /* FIXME: Check: I'm not sure the must_pass_in_stack check is necessary. */ - if (targetm.calls.must_pass_in_stack (arg.mode, arg.type)) + if (targetm.calls.must_pass_in_stack (arg)) return true; if (MMIX_FUNCTION_ARG_SIZE (arg.mode, arg.type) > 8 Index: gcc/config/sh/sh.c =================================================================== --- gcc/config/sh/sh.c 2019-08-19 15:58:58.013863514 +0100 +++ gcc/config/sh/sh.c 2019-08-19 15:59:04.285818131 +0100 @@ -7901,7 +7901,7 @@ sh_pass_by_reference (cumulative_args_t { CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); - if (targetm.calls.must_pass_in_stack (arg.mode, arg.type)) + if (targetm.calls.must_pass_in_stack (arg)) return true; /* ??? std_gimplify_va_arg_expr passes NULL for cum. That function Index: gcc/config/stormy16/stormy16.c =================================================================== --- gcc/config/stormy16/stormy16.c 2019-08-19 15:58:50.341919030 +0100 +++ gcc/config/stormy16/stormy16.c 2019-08-19 15:59:04.285818131 +0100 @@ -1239,7 +1239,7 @@ xstormy16_function_arg (cumulative_args_ if (arg.end_marker_p ()) return const0_rtx; - if (targetm.calls.must_pass_in_stack (arg.mode, arg.type) + if (targetm.calls.must_pass_in_stack (arg) || (*cum + XSTORMY16_WORD_SIZE (arg.type, arg.mode) > NUM_ARGUMENT_REGISTERS)) return NULL_RTX; Index: gcc/config/xtensa/xtensa.c =================================================================== --- gcc/config/xtensa/xtensa.c 2019-08-19 15:58:50.341919030 +0100 +++ gcc/config/xtensa/xtensa.c 2019-08-19 15:59:04.285818131 +0100 @@ -2118,7 +2118,7 @@ xtensa_function_arg_advance (cumulative_ / UNITS_PER_WORD); if (*arg_words < max - && (targetm.calls.must_pass_in_stack (arg.mode, arg.type) + && (targetm.calls.must_pass_in_stack (arg) || *arg_words + words > max)) *arg_words = max; Index: gcc/config/arm/arm.c =================================================================== --- gcc/config/arm/arm.c 2019-08-19 15:58:50.317919202 +0100 +++ gcc/config/arm/arm.c 2019-08-19 15:59:04.269818249 +0100 @@ -219,7 +219,7 @@ static bool arm_promote_prototypes (cons static bool arm_default_short_enums (void); static bool arm_align_anon_bitfield (void); static bool arm_return_in_msb (const_tree); -static bool arm_must_pass_in_stack (machine_mode, const_tree); +static bool arm_must_pass_in_stack (const function_arg_info &); static bool arm_return_in_memory (const_tree, const_tree); #if ARM_UNWIND_INFO static void arm_unwind_emit (FILE *, rtx_insn *); @@ -15382,12 +15382,12 @@ arm_reload_out_hi (rtx *operands) (padded to the size of a word) should be passed in a register. */ static bool -arm_must_pass_in_stack (machine_mode mode, const_tree type) +arm_must_pass_in_stack (const function_arg_info &arg) { if (TARGET_AAPCS_BASED) - return must_pass_in_stack_var_size (mode, type); + return must_pass_in_stack_var_size (arg); else - return must_pass_in_stack_var_size_or_pad (mode, type); + return must_pass_in_stack_var_size_or_pad (arg); } Index: gcc/config/fr30/fr30.c =================================================================== --- gcc/config/fr30/fr30.c 2019-08-19 15:58:50.321919175 +0100 +++ gcc/config/fr30/fr30.c 2019-08-19 15:59:04.273818218 +0100 @@ -116,7 +116,7 @@ struct fr30_frame_info static void fr30_setup_incoming_varargs (cumulative_args_t, const function_arg_info &, int *, int); -static bool fr30_must_pass_in_stack (machine_mode, const_tree); +static bool fr30_must_pass_in_stack (const function_arg_info &); static int fr30_arg_partial_bytes (cumulative_args_t, const function_arg_info &); static rtx fr30_function_arg (cumulative_args_t, const function_arg_info &); @@ -129,7 +129,7 @@ static bool fr30_function_value_regno_p static bool fr30_can_eliminate (const int, const int); static void fr30_asm_trampoline_template (FILE *); static void fr30_trampoline_init (rtx, tree, rtx); -static int fr30_num_arg_regs (machine_mode, const_tree); +static int fr30_num_arg_regs (const function_arg_info &); #define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM)) #define RETURN_POINTER_MASK (1 << (RETURN_POINTER_REGNUM)) @@ -480,7 +480,7 @@ fr30_setup_incoming_varargs (cumulative_ /* If TARGET_STRICT_ARGUMENT_NAMING returns true, then the last named arg must not be treated as an anonymous arg. */ /* ??? This is a pointer increment, which makes no sense. */ - arg_regs_used_so_far += fr30_num_arg_regs (arg.mode, arg.type); + arg_regs_used_so_far += fr30_num_arg_regs (arg); size = FR30_NUM_ARG_REGS - (* arg_regs_used_so_far); @@ -743,30 +743,20 @@ fr30_function_value_regno_p (const unsig in registers. */ static bool -fr30_must_pass_in_stack (machine_mode mode, const_tree type) +fr30_must_pass_in_stack (const function_arg_info &arg) { - if (mode == BLKmode) - return true; - if (type == NULL) - return false; - return AGGREGATE_TYPE_P (type); + return arg.mode == BLKmode || arg.aggregate_type_p (); } -/* Compute the number of word sized registers needed to hold a - function argument of mode INT_MODE and tree type TYPE. */ +/* Compute the number of word sized registers needed to hold function + argument ARG. */ static int -fr30_num_arg_regs (machine_mode mode, const_tree type) +fr30_num_arg_regs (const function_arg_info &arg) { - int size; - - if (targetm.calls.must_pass_in_stack (mode, type)) + if (targetm.calls.must_pass_in_stack (arg)) return 0; - if (type && mode == BLKmode) - size = int_size_in_bytes (type); - else - size = GET_MODE_SIZE (mode); - + int size = arg.promoted_size_in_bytes (); return (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD; } @@ -792,7 +782,7 @@ fr30_arg_partial_bytes (cumulative_args_ are needed because the parameter must be passed on the stack) then return zero, as this parameter does not require partial register, partial stack stack space. */ - if (*cum + fr30_num_arg_regs (arg.mode, arg.type) <= FR30_NUM_ARG_REGS) + if (*cum + fr30_num_arg_regs (arg) <= FR30_NUM_ARG_REGS) return 0; return (FR30_NUM_ARG_REGS - *cum) * UNITS_PER_WORD; @@ -804,7 +794,7 @@ fr30_function_arg (cumulative_args_t cum CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); if (!arg.named - || fr30_must_pass_in_stack (arg.mode, arg.type) + || fr30_must_pass_in_stack (arg) || *cum >= FR30_NUM_ARG_REGS) return NULL_RTX; else @@ -817,7 +807,7 @@ fr30_function_arg_advance (cumulative_ar const function_arg_info &arg) { if (arg.named) - *get_cumulative_args (cum) += fr30_num_arg_regs (arg.mode, arg.type); + *get_cumulative_args (cum) += fr30_num_arg_regs (arg); } /*}}}*/ Index: gcc/config/frv/frv.c =================================================================== --- gcc/config/frv/frv.c 2019-08-19 15:58:50.321919175 +0100 +++ gcc/config/frv/frv.c 2019-08-19 15:59:04.273818218 +0100 @@ -379,7 +379,7 @@ static void frv_output_const_unspec (FI const struct frv_unspec *); static bool frv_function_ok_for_sibcall (tree, tree); static rtx frv_struct_value_rtx (tree, int); -static bool frv_must_pass_in_stack (machine_mode mode, const_tree type); +static bool frv_must_pass_in_stack (const function_arg_info &); static int frv_arg_partial_bytes (cumulative_args_t, const function_arg_info &); static rtx frv_function_arg (cumulative_args_t, const function_arg_info &); @@ -3077,13 +3077,9 @@ frv_init_cumulative_args (CUMULATIVE_ARG in registers. */ static bool -frv_must_pass_in_stack (machine_mode mode, const_tree type) +frv_must_pass_in_stack (const function_arg_info &arg) { - if (mode == BLKmode) - return true; - if (type == NULL) - return false; - return AGGREGATE_TYPE_P (type); + return arg.mode == BLKmode || arg.aggregate_type_p (); } /* If defined, a C expression that gives the alignment boundary, in bits, of an Index: gcc/config/gcn/gcn.c =================================================================== --- gcc/config/gcn/gcn.c 2019-08-19 15:58:50.321919175 +0100 +++ gcc/config/gcn/gcn.c 2019-08-19 15:59:04.273818218 +0100 @@ -2200,22 +2200,16 @@ gcn_function_value_regno_p (const unsign return n == RETURN_VALUE_REG; } -/* Calculate the number of registers required to hold a function argument - of MODE and TYPE. */ +/* Calculate the number of registers required to hold function argument + ARG. */ static int -num_arg_regs (machine_mode mode, const_tree type) +num_arg_regs (const function_arg_info &arg) { - int size; - - if (targetm.calls.must_pass_in_stack (mode, type)) + if (targetm.calls.must_pass_in_stack (arg)) return 0; - if (type && mode == BLKmode) - size = int_size_in_bytes (type); - else - size = GET_MODE_SIZE (mode); - + int size = arg.promoted_size_in_bytes (); return (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD; } @@ -2263,11 +2257,11 @@ gcn_function_arg (cumulative_args_t cum_ if (!arg.named || arg.end_marker_p ()) return 0; - if (targetm.calls.must_pass_in_stack (arg.mode, arg.type)) + if (targetm.calls.must_pass_in_stack (arg)) return 0; int reg_num = FIRST_PARM_REG + cum->num; - int num_regs = num_arg_regs (arg.mode, arg.type); + int num_regs = num_arg_regs (arg); if (num_regs > 0) while (reg_num % num_regs != 0) reg_num++; @@ -2323,7 +2317,7 @@ gcn_function_arg_advance (cumulative_arg if (!arg.named) return; - int num_regs = num_arg_regs (arg.mode, arg.type); + int num_regs = num_arg_regs (arg); if (num_regs > 0) while ((FIRST_PARM_REG + cum->num) % num_regs != 0) cum->num++; @@ -2355,14 +2349,14 @@ gcn_arg_partial_bytes (cumulative_args_t if (!arg.named) return 0; - if (targetm.calls.must_pass_in_stack (arg.mode, arg.type)) + if (targetm.calls.must_pass_in_stack (arg)) return 0; if (cum->num >= NUM_PARM_REGS) return 0; /* If the argument fits entirely in registers, return 0. */ - if (cum->num + num_arg_regs (arg.mode, arg.type) <= NUM_PARM_REGS) + if (cum->num + num_arg_regs (arg) <= NUM_PARM_REGS) return 0; return (NUM_PARM_REGS - cum->num) * UNITS_PER_WORD; Index: gcc/config/i386/i386.c =================================================================== --- gcc/config/i386/i386.c 2019-08-19 15:58:50.325919144 +0100 +++ gcc/config/i386/i386.c 2019-08-19 15:59:04.277818191 +0100 @@ -1455,19 +1455,19 @@ ix86_function_arg_regno_p (int regno) return false; } -/* Return if we do not know how to pass TYPE solely in registers. */ +/* Return if we do not know how to pass ARG solely in registers. */ static bool -ix86_must_pass_in_stack (machine_mode mode, const_tree type) +ix86_must_pass_in_stack (const function_arg_info &arg) { - if (must_pass_in_stack_var_size_or_pad (mode, type)) + if (must_pass_in_stack_var_size_or_pad (arg)) return true; /* For 32-bit, we want TImode aggregates to go on the stack. But watch out! The layout_type routine is crafty and tries to trick us into passing currently unsupported vector types on the stack by using TImode. */ - return (!TARGET_64BIT && mode == TImode - && type && TREE_CODE (type) != VECTOR_TYPE); + return (!TARGET_64BIT && arg.mode == TImode + && arg.type && TREE_CODE (arg.type) != VECTOR_TYPE); } /* It returns the size, in bytes, of the area reserved for arguments passed @@ -2062,9 +2062,13 @@ classify_argument (machine_mode mode, co if (bytes < 0) return 0; - if (mode != VOIDmode - && targetm.calls.must_pass_in_stack (mode, type)) - return 0; + if (mode != VOIDmode) + { + /* The value of "named" doesn't matter. */ + function_arg_info arg (const_cast (type), mode, /*named=*/true); + if (targetm.calls.must_pass_in_stack (arg)) + return 0; + } if (type && AGGREGATE_TYPE_P (type)) { Index: gcc/config/nds32/nds32.c =================================================================== --- gcc/config/nds32/nds32.c 2019-08-19 15:58:50.333919085 +0100 +++ gcc/config/nds32/nds32.c 2019-08-19 15:59:04.285818131 +0100 @@ -1951,16 +1951,16 @@ nds32_function_arg (cumulative_args_t ca } static bool -nds32_must_pass_in_stack (machine_mode mode, const_tree type) +nds32_must_pass_in_stack (const function_arg_info &arg) { /* Return true if a type must be passed in memory. If it is NOT using hard float abi, small aggregates can be passed in a register even we are calling a variadic function. So there is no need to take padding into consideration. */ if (TARGET_HARD_FLOAT) - return must_pass_in_stack_var_size_or_pad (mode, type); + return must_pass_in_stack_var_size_or_pad (arg); else - return must_pass_in_stack_var_size (mode, type); + return must_pass_in_stack_var_size (arg); } static int Index: gcc/config/rs6000/rs6000-internal.h =================================================================== --- gcc/config/rs6000/rs6000-internal.h 2019-08-19 15:58:50.337919057 +0100 +++ gcc/config/rs6000/rs6000-internal.h 2019-08-19 15:59:04.285818131 +0100 @@ -156,7 +156,7 @@ extern void setup_incoming_varargs (cumu const function_arg_info &, int *, int); extern unsigned int rs6000_function_arg_boundary (machine_mode mode, const_tree type); -extern bool rs6000_must_pass_in_stack (machine_mode mode, const_tree type); +extern bool rs6000_must_pass_in_stack (const function_arg_info &); extern int rs6000_arg_partial_bytes (cumulative_args_t, const function_arg_info &); extern void rs6000_function_arg_advance (cumulative_args_t, Index: gcc/config/rs6000/rs6000-call.c =================================================================== --- gcc/config/rs6000/rs6000-call.c 2019-08-19 15:58:50.337919057 +0100 +++ gcc/config/rs6000/rs6000-call.c 2019-08-19 15:59:04.285818131 +0100 @@ -816,12 +816,12 @@ rs6000_promote_function_mode (const_tree /* Return true if TYPE must be passed on the stack and not in registers. */ bool -rs6000_must_pass_in_stack (machine_mode mode, const_tree type) +rs6000_must_pass_in_stack (const function_arg_info &arg) { if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2 || TARGET_64BIT) - return must_pass_in_stack_var_size (mode, type); + return must_pass_in_stack_var_size (arg); else - return must_pass_in_stack_var_size_or_pad (mode, type); + return must_pass_in_stack_var_size_or_pad (arg); } static inline bool @@ -2202,11 +2202,11 @@ rs6000_parm_needs_stack (cumulative_args mode = promote_mode (type, TYPE_MODE (type), &unsignedp); /* If we must pass in stack, we need a stack. */ - if (rs6000_must_pass_in_stack (mode, type)) + function_arg_info arg (type, mode, /*named=*/true); + if (rs6000_must_pass_in_stack (arg)) return true; /* If there is no incoming register, we need a stack. */ - function_arg_info arg (type, mode, /*named=*/true); entry_parm = rs6000_function_arg (args_so_far, arg); if (entry_parm == NULL) return true; @@ -2457,7 +2457,7 @@ setup_incoming_varargs (cumulative_args_ first_reg_offset = next_cum.words; save_area = crtl->args.internal_arg_pointer; - if (targetm.calls.must_pass_in_stack (arg.mode, arg.type)) + if (targetm.calls.must_pass_in_stack (arg)) first_reg_offset += rs6000_arg_size (TYPE_MODE (arg.type), arg.type); }