aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog55
-rw-r--r--gcc/calls.c32
-rw-r--r--gcc/calls.h4
-rw-r--r--gcc/config/alpha/alpha.c6
-rw-r--r--gcc/config/arm/arm.c8
-rw-r--r--gcc/config/cr16/cr16.c4
-rw-r--r--gcc/config/cris/cris.c4
-rw-r--r--gcc/config/fr30/fr30.c36
-rw-r--r--gcc/config/frv/frv.c10
-rw-r--r--gcc/config/gcn/gcn.c26
-rw-r--r--gcc/config/i386/i386.c20
-rw-r--r--gcc/config/iq2000/iq2000.c2
-rw-r--r--gcc/config/lm32/lm32.c2
-rw-r--r--gcc/config/mcore/mcore.c7
-rw-r--r--gcc/config/mips/mips.c2
-rw-r--r--gcc/config/mmix/mmix.c6
-rw-r--r--gcc/config/nds32/nds32.c6
-rw-r--r--gcc/config/rs6000/rs6000-call.c12
-rw-r--r--gcc/config/rs6000/rs6000-internal.h2
-rw-r--r--gcc/config/sh/sh.c2
-rw-r--r--gcc/config/stormy16/stormy16.c2
-rw-r--r--gcc/config/xtensa/xtensa.c2
-rw-r--r--gcc/doc/tm.texi4
-rw-r--r--gcc/function.c3
-rw-r--r--gcc/target.def4
-rw-r--r--gcc/targhooks.c2
26 files changed, 151 insertions, 112 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e57cc99..b5a198c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,60 @@
2019-08-20 Richard Sandiford <richard.sandiford@arm.com>
+ * 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.
+
+2019-08-20 Richard Sandiford <richard.sandiford@arm.com>
+
* target.def (callee_copies): Take a function_arg_info instead
of a mode, type and named flag.
* doc/tm.texi: Regenerate.
diff --git a/gcc/calls.c b/gcc/calls.c
index 6be8acd..1f691e8 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -2139,7 +2139,7 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
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 argblock, int flags,
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_mode mode ATTRIBUTE_UNUSED,
/* ??? 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 (machine_mode mode, const_tree type)
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. */
diff --git a/gcc/calls.h b/gcc/calls.h
index 709a076..5e8c576 100644
--- a/gcc/calls.h
+++ b/gcc/calls.h
@@ -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);
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 477c24e..fd6b5a8 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -5585,7 +5585,7 @@ alpha_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
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 cum_v, const function_arg_info &arg)
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_args_t cum_v,
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
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 74e7c54..3343a7e 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -219,7 +219,7 @@ static bool arm_promote_prototypes (const_tree);
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);
}
diff --git a/gcc/config/cr16/cr16.c b/gcc/config/cr16/cr16.c
index dc4cb91..c95d5d1 100644
--- a/gcc/config/cr16/cr16.c
+++ b/gcc/config/cr16/cr16.c
@@ -606,7 +606,7 @@ cr16_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
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_args_t cum_v,
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)
diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c
index f238853..fff641e9 100644
--- a/gcc/config/cris/cris.c
+++ b/gcc/config/cris/cris.c
@@ -4046,7 +4046,7 @@ cris_setup_incoming_varargs (cumulative_args_t ca_v,
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 @@ static int
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;
diff --git a/gcc/config/fr30/fr30.c b/gcc/config/fr30/fr30.c
index 7f1eae1..675198f 100644
--- a/gcc/config/fr30/fr30.c
+++ b/gcc/config/fr30/fr30.c
@@ -116,7 +116,7 @@ static struct fr30_frame_info zero_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 (const unsigned int);
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_args_t arg_regs_used_so_far_v,
/* 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 unsigned int regno)
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_t cum_v, const function_arg_info &arg)
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_v, const function_arg_info &arg)
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_args_t cum,
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);
}
/*}}}*/
diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c
index 5d319c0..c1b3c9e 100644
--- a/gcc/config/frv/frv.c
+++ b/gcc/config/frv/frv.c
@@ -379,7 +379,7 @@ static void frv_output_const_unspec (FILE *,
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_ARGS *cum,
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
diff --git a/gcc/config/gcn/gcn.c b/gcc/config/gcn/gcn.c
index c919d31..8645ecc 100644
--- a/gcc/config/gcn/gcn.c
+++ b/gcc/config/gcn/gcn.c
@@ -2200,22 +2200,16 @@ gcn_function_value_regno_p (const unsigned int n)
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_v, const function_arg_info &arg)
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_args_t cum_v,
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 cum_v, const function_arg_info &arg)
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;
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index f036d56..49ab50e 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -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, const_tree type,
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<tree> (type), mode, /*named=*/true);
+ if (targetm.calls.must_pass_in_stack (arg))
+ return 0;
+ }
if (type && AGGREGATE_TYPE_P (type))
{
diff --git a/gcc/config/iq2000/iq2000.c b/gcc/config/iq2000/iq2000.c
index 80c6381..59c5132 100644
--- a/gcc/config/iq2000/iq2000.c
+++ b/gcc/config/iq2000/iq2000.c
@@ -2300,7 +2300,7 @@ iq2000_pass_by_reference (cumulative_args_t cum_v,
/* 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
diff --git a/gcc/config/lm32/lm32.c b/gcc/config/lm32/lm32.c
index a393dff..267ff27 100644
--- a/gcc/config/lm32/lm32.c
+++ b/gcc/config/lm32/lm32.c
@@ -629,7 +629,7 @@ lm32_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
/* 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
diff --git a/gcc/config/mcore/mcore.c b/gcc/config/mcore/mcore.c
index 9feac95..b259da5 100644
--- a/gcc/config/mcore/mcore.c
+++ b/gcc/config/mcore/mcore.c
@@ -2713,7 +2713,8 @@ mcore_num_arg_regs (machine_mode mode, const_tree type)
{
int size;
- if (targetm.calls.must_pass_in_stack (mode, type))
+ function_arg_info arg (const_cast<tree> (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 cum, const function_arg_info &arg)
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_t cum, const function_arg_info &arg)
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
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 37ebde5..c24dc71 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -6252,7 +6252,7 @@ mips_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
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);
}
}
diff --git a/gcc/config/mmix/mmix.c b/gcc/config/mmix/mmix.c
index 7c12e74..8ebb829 100644
--- a/gcc/config/mmix/mmix.c
+++ b/gcc/config/mmix/mmix.c
@@ -621,7 +621,7 @@ mmix_function_arg_advance (cumulative_args_t argsp_v,
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_args_t argsp_v,
: 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_t argsp_v,
/* 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
diff --git a/gcc/config/nds32/nds32.c b/gcc/config/nds32/nds32.c
index 3fd4cc8..3caae14 100644
--- a/gcc/config/nds32/nds32.c
+++ b/gcc/config/nds32/nds32.c
@@ -1951,16 +1951,16 @@ nds32_function_arg (cumulative_args_t ca, const function_arg_info &arg)
}
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
diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c
index 548a715..fb87bb2 100644
--- a/gcc/config/rs6000/rs6000-call.c
+++ b/gcc/config/rs6000/rs6000-call.c
@@ -816,12 +816,12 @@ rs6000_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
/* 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_t args_so_far, tree type)
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_t cum,
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);
}
diff --git a/gcc/config/rs6000/rs6000-internal.h b/gcc/config/rs6000/rs6000-internal.h
index cdd9327..baccfb3 100644
--- a/gcc/config/rs6000/rs6000-internal.h
+++ b/gcc/config/rs6000/rs6000-internal.h
@@ -156,7 +156,7 @@ extern void setup_incoming_varargs (cumulative_args_t,
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,
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index da912ca..3b22d96 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -7901,7 +7901,7 @@ sh_pass_by_reference (cumulative_args_t cum_v, const function_arg_info &arg)
{
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
diff --git a/gcc/config/stormy16/stormy16.c b/gcc/config/stormy16/stormy16.c
index 7ccfbda..23f546a 100644
--- a/gcc/config/stormy16/stormy16.c
+++ b/gcc/config/stormy16/stormy16.c
@@ -1239,7 +1239,7 @@ xstormy16_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
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;
diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c
index a277633..98f30c5 100644
--- a/gcc/config/xtensa/xtensa.c
+++ b/gcc/config/xtensa/xtensa.c
@@ -2118,7 +2118,7 @@ xtensa_function_arg_advance (cumulative_args_t cum,
/ 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;
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 99dbfb8..5506908 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -4012,8 +4012,8 @@ defined, the argument will be computed in the stack and then loaded into
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.
diff --git a/gcc/function.c b/gcc/function.c
index 1d7687a..46ed75c 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -2552,8 +2552,7 @@ assign_parm_find_entry_rtl (struct assign_parm_data_all *all,
/* 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)
diff --git a/gcc/target.def b/gcc/target.def
index 4f8acfd..b2332d8 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -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,
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index 5a0ed2f..1d12ec5 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -323,7 +323,7 @@ bool
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