summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog57
-rw-r--r--gcc/calls.c12
-rw-r--r--gcc/calls.h71
-rw-r--r--gcc/config/alpha/alpha.c9
-rw-r--r--gcc/config/arc/arc.c8
-rw-r--r--gcc/config/arm/arm.c17
-rw-r--r--gcc/config/bfin/bfin.c7
-rw-r--r--gcc/config/cris/cris.c13
-rw-r--r--gcc/config/csky/csky.c5
-rw-r--r--gcc/config/epiphany/epiphany.c12
-rw-r--r--gcc/config/fr30/fr30.c22
-rw-r--r--gcc/config/frv/frv.c27
-rw-r--r--gcc/config/ft32/ft32.c13
-rw-r--r--gcc/config/gcn/gcn.c9
-rw-r--r--gcc/config/ia64/ia64.c11
-rw-r--r--gcc/config/iq2000/iq2000.c11
-rw-r--r--gcc/config/m32r/m32r.c12
-rw-r--r--gcc/config/mcore/mcore.c22
-rw-r--r--gcc/config/microblaze/microblaze.c21
-rw-r--r--gcc/config/mips/mips.c6
-rw-r--r--gcc/config/mn10300/mn10300.c12
-rw-r--r--gcc/config/moxie/moxie.c14
-rw-r--r--gcc/config/msp430/msp430.c7
-rw-r--r--gcc/config/nds32/nds32.c10
-rw-r--r--gcc/config/nios2/nios2.c15
-rw-r--r--gcc/config/pa/pa.c11
-rw-r--r--gcc/config/pru/pru.c5
-rw-r--r--gcc/config/riscv/riscv.c5
-rw-r--r--gcc/config/rs6000/rs6000-call.c23
-rw-r--r--gcc/config/rs6000/rs6000-internal.h5
-rw-r--r--gcc/config/sh/sh.c18
-rw-r--r--gcc/config/sparc/sparc.c39
-rw-r--r--gcc/config/v850/v850.c17
-rw-r--r--gcc/doc/tm.texi2
-rw-r--r--gcc/expr.c3
-rw-r--r--gcc/function.c7
-rw-r--r--gcc/target.def4
-rw-r--r--gcc/target.h3
-rw-r--r--gcc/targhooks.c6
-rw-r--r--gcc/targhooks.h4
40 files changed, 315 insertions, 260 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 86bd73af74a..55c0714e277 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,62 @@
2019-08-20 Richard Sandiford <richard.sandiford@arm.com>
+ * target.def (arg_partial_bytes): Take a function_arg_info instead
+ of a mode, type and named flag.
+ * doc/tm.texi: Regenerate.
+ * target.h (function_arg_info): Declare.
+ * calls.h (function_arg_info): New class.
+ * targhooks.h (hook_int_CUMULATIVE_ARGS_mode_tree_bool_0): Delete.
+ (hook_int_CUMULATIVE_ARGS_arg_info_0): Declare.
+ * targhooks.c (hook_int_CUMULATIVE_ARGS_mode_tree_bool_0): Delete.
+ (hook_int_CUMULATIVE_ARGS_arg_info_0): New function.
+ * calls.c (initialize_argument_information): Update call to
+ targetm.calls.partial_bytes.
+ (emit_library_call_value_1): Likewise.
+ * expr.c (block_move_libcall_safe_for_call_parm): Likewise.
+ * function.c (assign_parm_find_entry_rtl): Likewise.
+ * config/alpha/alpha.c (alpha_arg_partial_bytes): Take a
+ function_arg_info instead of a mode, type and named flag.
+ * config/arc/arc.c (arc_arg_partial_bytes): Likewise.
+ * config/arm/arm.c (arm_arg_partial_bytes): Likewise.
+ (cmse_func_args_or_return_in_stack): Update accordingly.
+ * config/bfin/bfin.c (bfin_arg_partial_bytes): Take a
+ function_arg_info instead of a mode, type and named flag.
+ * config/cris/cris.c (cris_arg_partial_bytes): Likewise.
+ * config/csky/csky.c (csky_arg_partial_bytes): Likewise.
+ * config/epiphany/epiphany.c (epiphany_arg_partial_bytes): Likewise.
+ * config/fr30/fr30.c: Include calls.h.
+ (fr30_arg_partial_bytes): Take a function_arg_info instead of a mode,
+ type and named flag.
+ * config/frv/frv.c: Include calls.h.
+ (frv_arg_partial_bytes): Take a function_arg_info instead of a mode,
+ type and named flag.
+ * config/ft32/ft32.c (ft32_arg_partial_bytes): Likewise.
+ * config/gcn/gcn.c (gcn_arg_partial_bytes): Likewise.
+ * config/ia64/ia64.c (ia64_arg_partial_bytes): Likewise.
+ * config/iq2000/iq2000.c (iq2000_arg_partial_bytes): Likewise.
+ * config/m32r/m32r.c (m32r_arg_partial_bytes): Likewise.
+ * config/mcore/mcore.c (mcore_arg_partial_bytes): Likewise.
+ * config/microblaze/microblaze.c (function_arg_partial_bytes):
+ Likewise.
+ * config/mips/mips.c (mips_arg_partial_bytes): Likewise.
+ * config/mn10300/mn10300.c (mn10300_arg_partial_bytes): Likewise.
+ * config/moxie/moxie.c (moxie_arg_partial_bytes): Likewise.
+ * config/msp430/msp430.c (msp430_arg_partial_bytes): Likewise.
+ * config/nds32/nds32.c (nds32_arg_partial_bytes): Likewise.
+ * config/nios2/nios2.c (nios2_arg_partial_bytes): Likewise.
+ * config/pa/pa.c (pa_arg_partial_bytes): Likewise.
+ * config/pru/pru.c (pru_arg_partial_bytes): Likewise.
+ * config/riscv/riscv.c (riscv_arg_partial_bytes): Likewise.
+ * config/rs6000/rs6000-internal.h (rs6000_arg_partial_bytes): Likewise.
+ * config/rs6000/rs6000-call.c (rs6000_arg_partial_bytes): Likewise.
+ (rs6000_parm_needs_stack): Update call accordingly.
+ * config/sh/sh.c (sh_arg_partial_bytes): Take a
+ function_arg_info instead of a mode, type and named flag.
+ * config/sparc/sparc.c (sparc_arg_partial_bytes): Likewise.
+ * config/v850/v850.c (v850_arg_partial_bytes): Likewise.
+
+2019-08-20 Richard Sandiford <richard.sandiford@arm.com>
+
* calls.h (must_pass_va_arg_in_stack): Declare.
* calls.c (must_pass_va_arg_in_stack): New function.
* config/alpha/alpha.c (alpha_gimplify_va_arg_1): Use it.
diff --git a/gcc/calls.c b/gcc/calls.c
index dd428b9bbb1..8f3574e4249 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -2142,10 +2142,9 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
else
args[i].tail_call_reg = args[i].reg;
+ function_arg_info arg (type, mode, argpos < n_named_args);
if (args[i].reg)
- args[i].partial
- = targetm.calls.arg_partial_bytes (args_so_far, mode, type,
- argpos < n_named_args);
+ 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);
@@ -4871,10 +4870,10 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
argvec[count].mode = Pmode;
argvec[count].partial = 0;
+ function_arg_info ptr_arg (Pmode, /*named=*/true);
argvec[count].reg = targetm.calls.function_arg (args_so_far,
Pmode, NULL_TREE, true);
- gcc_assert (targetm.calls.arg_partial_bytes (args_so_far, Pmode,
- NULL_TREE, 1) == 0);
+ gcc_assert (targetm.calls.arg_partial_bytes (args_so_far, ptr_arg) == 0);
locate_and_pad_parm (Pmode, NULL_TREE,
#ifdef STACK_PARMS_IN_REG_PARM_AREA
@@ -4952,13 +4951,14 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
}
mode = promote_function_mode (NULL_TREE, mode, &unsigned_p, NULL_TREE, 0);
+ function_arg_info arg (mode, /*named=*/true);
argvec[count].mode = mode;
argvec[count].value = convert_modes (mode, GET_MODE (val), val, unsigned_p);
argvec[count].reg = targetm.calls.function_arg (args_so_far, mode,
NULL_TREE, true);
argvec[count].partial
- = targetm.calls.arg_partial_bytes (args_so_far, mode, NULL_TREE, 1);
+ = targetm.calls.arg_partial_bytes (args_so_far, arg);
if (argvec[count].reg == 0
|| argvec[count].partial != 0
diff --git a/gcc/calls.h b/gcc/calls.h
index b08427044b1..38ab6ef7fa1 100644
--- a/gcc/calls.h
+++ b/gcc/calls.h
@@ -20,6 +20,77 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_CALLS_H
#define GCC_CALLS_H
+/* Describes a function argument.
+
+ Each argument conceptually has a gimple-level type. Usually this type
+ is available directly as a tree via the TYPE field, but when calling
+ libgcc support functions it might instead be inferred from a mode,
+ in which case the type isn't available directly.
+
+ This gimple-level type might go through promotion before being passed to
+ the target function. Depending on the context, the MODE field is either
+ the mode of the gimple-level type (whether explicitly given or not)
+ or the mode after promotion has been performed. */
+class function_arg_info
+{
+public:
+ function_arg_info () : type (NULL_TREE), mode (VOIDmode), named (false) {}
+
+ /* Initialize an argument of mode MODE, either before or after promotion. */
+ function_arg_info (machine_mode mode, bool named)
+ : type (NULL_TREE), mode (mode), named (named)
+ {}
+
+ /* Initialize an unpromoted argument of type TYPE. */
+ function_arg_info (tree type, bool named)
+ : type (type), mode (TYPE_MODE (type)), named (named)
+ {}
+
+ /* Initialize an argument with explicit properties. */
+ function_arg_info (tree type, machine_mode mode, bool named)
+ : type (type), mode (mode), named (named)
+ {}
+
+ /* Return true if the gimple-level type is an aggregate. */
+ bool aggregate_type_p () const { return type && AGGREGATE_TYPE_P (type); }
+
+ /* Return the size of the gimple-level type, or -1 if the size is
+ variable or otherwise not representable as a poly_int64.
+
+ Use this function when MODE is the mode of the type before promotion,
+ or in any context if the target never promotes function arguments. */
+ poly_int64 type_size_in_bytes () const
+ {
+ if (type)
+ return int_size_in_bytes (type);
+ return GET_MODE_SIZE (mode);
+ }
+
+ /* Return the size of the argument after promotion, or -1 if the size
+ is variable or otherwise not representable as a poly_int64.
+
+ Use this function when MODE is the mode of the type after promotion. */
+ poly_int64 promoted_size_in_bytes () const
+ {
+ if (mode == BLKmode)
+ return int_size_in_bytes (type);
+ return GET_MODE_SIZE (mode);
+ }
+
+ /* The type of the argument, or null if not known (which is true for
+ libgcc support functions). */
+ tree type;
+
+ /* The mode of the argument. Depending on context, this might be
+ the mode of the argument type or the mode after promotion. */
+ machine_mode mode;
+
+ /* True if the argument is treated as a named argument, false if it is
+ treated as an unnamed variadic argument (i.e. one passed through
+ "..."). See also TARGET_STRICT_ARGUMENT_NAMING. */
+ unsigned int named : 1;
+};
+
extern int flags_from_decl_or_type (const_tree);
extern int call_expr_flags (const_tree);
extern int setjmp_call_p (const_tree);
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 479d1ad2722..f7e35c2b1ad 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -5635,20 +5635,17 @@ alpha_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
}
static int
-alpha_arg_partial_bytes (cumulative_args_t cum_v,
- machine_mode mode ATTRIBUTE_UNUSED,
- tree type ATTRIBUTE_UNUSED,
- bool named ATTRIBUTE_UNUSED)
+alpha_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg)
{
int words = 0;
CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED = get_cumulative_args (cum_v);
#if TARGET_ABI_OPEN_VMS
if (cum->num_args < 6
- && 6 < cum->num_args + ALPHA_ARG_SIZE (mode, type))
+ && 6 < cum->num_args + ALPHA_ARG_SIZE (arg.mode, arg.type))
words = 6 - cum->num_args;
#elif TARGET_ABI_OSF
- if (*cum < 6 && 6 < *cum + ALPHA_ARG_SIZE (mode, type))
+ if (*cum < 6 && 6 < *cum + ALPHA_ARG_SIZE (arg.mode, arg.type))
words = 6 - *cum;
#else
#error Unhandled ABI
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index 98fbfea7efb..ace7d52f66b 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -6432,17 +6432,15 @@ arc_output_pic_addr_const (FILE * file, rtx x, int code)
/* Implement TARGET_ARG_PARTIAL_BYTES. */
static int
-arc_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
- tree type, bool named ATTRIBUTE_UNUSED)
+arc_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg)
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
- int bytes = (mode == BLKmode
- ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode));
+ int bytes = arg.promoted_size_in_bytes ();
int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
int arg_num = *cum;
int ret;
- arg_num = ROUND_ADVANCE_CUM (arg_num, mode, type);
+ arg_num = ROUND_ADVANCE_CUM (arg_num, arg.mode, arg.type);
ret = GPR_REST_ARG_REGS (arg_num);
/* ICEd at function.c:2361, and ret is copied to data->partial */
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 81286cadf32..92bfe16f48e 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -187,8 +187,8 @@ static int arm_memory_move_cost (machine_mode, reg_class_t, bool);
static void emit_constant_insn (rtx cond, rtx pattern);
static rtx_insn *emit_set_insn (rtx, rtx);
static rtx emit_multi_reg_push (unsigned long, unsigned long);
-static int arm_arg_partial_bytes (cumulative_args_t, machine_mode,
- tree, bool);
+static int arm_arg_partial_bytes (cumulative_args_t,
+ const function_arg_info &);
static rtx arm_function_arg (cumulative_args_t, machine_mode,
const_tree, bool);
static void arm_function_arg_advance (cumulative_args_t, machine_mode,
@@ -6754,23 +6754,22 @@ arm_function_arg_boundary (machine_mode mode, const_tree type)
}
static int
-arm_arg_partial_bytes (cumulative_args_t pcum_v, machine_mode mode,
- tree type, bool named)
+arm_arg_partial_bytes (cumulative_args_t pcum_v, const function_arg_info &arg)
{
CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v);
int nregs = pcum->nregs;
if (pcum->pcs_variant <= ARM_PCS_AAPCS_LOCAL)
{
- aapcs_layout_arg (pcum, mode, type, named);
+ aapcs_layout_arg (pcum, arg.mode, arg.type, arg.named);
return pcum->aapcs_partial;
}
- if (TARGET_IWMMXT_ABI && arm_vector_mode_supported_p (mode))
+ if (TARGET_IWMMXT_ABI && arm_vector_mode_supported_p (arg.mode))
return 0;
if (NUM_ARG_REGS > nregs
- && (NUM_ARG_REGS < nregs + ARM_NUM_REGS2 (mode, type))
+ && (NUM_ARG_REGS < nregs + ARM_NUM_REGS2 (arg.mode, arg.type))
&& pcum->can_split)
return (NUM_ARG_REGS - nregs) * UNITS_PER_WORD;
@@ -6999,11 +6998,11 @@ cmse_func_args_or_return_in_stack (tree fndecl, tree name, tree fntype)
if (VOID_TYPE_P (arg_type))
continue;
+ function_arg_info arg (arg_type, /*named=*/true);
if (!first_param)
arm_function_arg_advance (args_so_far, arg_mode, arg_type, true);
arg_rtx = arm_function_arg (args_so_far, arg_mode, arg_type, true);
- if (!arg_rtx
- || arm_arg_partial_bytes (args_so_far, arg_mode, arg_type, true))
+ if (!arg_rtx || arm_arg_partial_bytes (args_so_far, arg))
{
error ("%qE attribute not available to functions with arguments "
"passed on the stack", name);
diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c
index d1a68321c11..c4281a12486 100644
--- a/gcc/config/bfin/bfin.c
+++ b/gcc/config/bfin/bfin.c
@@ -1723,12 +1723,9 @@ bfin_function_arg (cumulative_args_t cum_v, machine_mode mode,
stack. */
static int
-bfin_arg_partial_bytes (cumulative_args_t cum, machine_mode mode,
- tree type ATTRIBUTE_UNUSED,
- bool named ATTRIBUTE_UNUSED)
+bfin_arg_partial_bytes (cumulative_args_t cum, const function_arg_info &arg)
{
- int bytes
- = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
+ int bytes = arg.promoted_size_in_bytes ();
int bytes_left = get_cumulative_args (cum)->nregs * UNITS_PER_WORD;
if (bytes == -1)
diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c
index 88de088fc9f..aac8552eb62 100644
--- a/gcc/config/cris/cris.c
+++ b/gcc/config/cris/cris.c
@@ -141,8 +141,8 @@ static bool cris_rtx_costs (rtx, machine_mode, int, int, int *, bool);
static int cris_address_cost (rtx, machine_mode, addr_space_t, bool);
static bool cris_pass_by_reference (cumulative_args_t, machine_mode,
const_tree, bool);
-static int cris_arg_partial_bytes (cumulative_args_t, machine_mode,
- tree, bool);
+static int cris_arg_partial_bytes (cumulative_args_t,
+ const function_arg_info &);
static rtx cris_function_arg (cumulative_args_t, machine_mode,
const_tree, bool);
static rtx cris_function_incoming_arg (cumulative_args_t,
@@ -4111,13 +4111,12 @@ cris_function_value_regno_p (const unsigned int regno)
}
static int
-cris_arg_partial_bytes (cumulative_args_t ca, machine_mode mode,
- tree type, bool named ATTRIBUTE_UNUSED)
+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 (mode, type)
- && CRIS_FUNCTION_ARG_SIZE (mode, type) > 4
- && CRIS_FUNCTION_ARG_SIZE (mode, type) <= 8)
+ && !targetm.calls.must_pass_in_stack (arg.mode, arg.type)
+ && CRIS_FUNCTION_ARG_SIZE (arg.mode, arg.type) > 4
+ && CRIS_FUNCTION_ARG_SIZE (arg.mode, arg.type) <= 8)
return UNITS_PER_WORD;
else
return 0;
diff --git a/gcc/config/csky/csky.c b/gcc/config/csky/csky.c
index 3cfa13e22cd..98789bcfcff 100644
--- a/gcc/config/csky/csky.c
+++ b/gcc/config/csky/csky.c
@@ -1917,11 +1917,10 @@ csky_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
that are passed entirely in registers or
that are entirely pushed on the stack. */
static int
-csky_arg_partial_bytes (cumulative_args_t pcum_v, machine_mode mode,
- tree type, bool named ATTRIBUTE_UNUSED)
+csky_arg_partial_bytes (cumulative_args_t pcum_v, const function_arg_info &arg)
{
CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v);
- int param_size = csky_num_arg_regs (mode, type);
+ int param_size = csky_num_arg_regs (arg.mode, arg.type);
if (*pcum < CSKY_NPARM_REGS
&& *pcum + param_size > CSKY_NPARM_REGS)
diff --git a/gcc/config/epiphany/epiphany.c b/gcc/config/epiphany/epiphany.c
index 657a8886ac7..67b1bd9bc0a 100644
--- a/gcc/config/epiphany/epiphany.c
+++ b/gcc/config/epiphany/epiphany.c
@@ -744,18 +744,20 @@ epiphany_setup_incoming_varargs (cumulative_args_t cum, machine_mode mode,
}
static int
-epiphany_arg_partial_bytes (cumulative_args_t cum, machine_mode mode,
- tree type, bool named ATTRIBUTE_UNUSED)
+epiphany_arg_partial_bytes (cumulative_args_t cum,
+ const function_arg_info &arg)
{
int words = 0, rounded_cum;
- gcc_assert (!epiphany_pass_by_reference (cum, mode, type, /* named */ true));
+ gcc_assert (!epiphany_pass_by_reference (cum, arg.mode, arg.type,
+ arg.named));
- rounded_cum = ROUND_ADVANCE_CUM (*get_cumulative_args (cum), mode, type);
+ rounded_cum = ROUND_ADVANCE_CUM (*get_cumulative_args (cum),
+ arg.mode, arg.type);
if (rounded_cum < MAX_EPIPHANY_PARM_REGS)
{
words = MAX_EPIPHANY_PARM_REGS - rounded_cum;
- if (words >= ROUND_ADVANCE_ARG (mode, type))
+ if (words >= ROUND_ADVANCE_ARG (arg.mode, arg.type))
words = 0;
}
return words * UNITS_PER_WORD;
diff --git a/gcc/config/fr30/fr30.c b/gcc/config/fr30/fr30.c
index d21fc45e3f1..59728015f14 100644
--- a/gcc/config/fr30/fr30.c
+++ b/gcc/config/fr30/fr30.c
@@ -39,6 +39,7 @@
#include "output.h"
#include "expr.h"
#include "builtins.h"
+#include "calls.h"
/* This file should be included last. */
#include "target-def.h"
@@ -115,8 +116,8 @@ static struct fr30_frame_info zero_frame_info;
static void fr30_setup_incoming_varargs (cumulative_args_t, machine_mode,
tree, int *, int);
static bool fr30_must_pass_in_stack (machine_mode, const_tree);
-static int fr30_arg_partial_bytes (cumulative_args_t, machine_mode,
- tree, bool);
+static int fr30_arg_partial_bytes (cumulative_args_t,
+ const function_arg_info &);
static rtx fr30_function_arg (cumulative_args_t, machine_mode,
const_tree, bool);
static void fr30_function_arg_advance (cumulative_args_t, machine_mode,
@@ -770,23 +771,20 @@ fr30_num_arg_regs (machine_mode mode, const_tree type)
return (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
}
-/* Returns the number of bytes in which *part* of a parameter of machine
- mode MODE and tree type TYPE (which may be NULL if the type is not known).
- If the argument fits entirely in the argument registers, or entirely on
- the stack, then 0 is returned.
- CUM is the number of argument registers already used by earlier
- parameters to the function. */
+/* Returns the number of bytes of argument registers required to hold *part*
+ of argument ARG. If the argument fits entirely in the argument registers,
+ or entirely on the stack, then 0 is returned. CUM is the number of
+ argument registers already used by earlier parameters to the function. */
static int
-fr30_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
- tree type, bool named)
+fr30_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg)
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
/* Unnamed arguments, i.e. those that are prototyped as ...
are always passed on the stack.
Also check here to see if all the argument registers are full. */
- if (named == 0 || *cum >= FR30_NUM_ARG_REGS)
+ if (!arg.named || *cum >= FR30_NUM_ARG_REGS)
return 0;
/* Work out how many argument registers would be needed if this
@@ -795,7 +793,7 @@ fr30_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
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 (mode, type) <= FR30_NUM_ARG_REGS)
+ if (*cum + fr30_num_arg_regs (arg.mode, arg.type) <= FR30_NUM_ARG_REGS)
return 0;
return (FR30_NUM_ARG_REGS - *cum) * UNITS_PER_WORD;
diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c
index f8a3a075319..4560fc6f9ca 100644
--- a/gcc/config/frv/frv.c
+++ b/gcc/config/frv/frv.c
@@ -49,6 +49,7 @@ along with GCC; see the file COPYING3. If not see
#include "builtins.h"
#include "ifcvt.h"
#include "rtl-iter.h"
+#include "calls.h"
/* This file should be included last. */
#include "target-def.h"
@@ -379,8 +380,8 @@ static void frv_output_const_unspec (FILE *,
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 int frv_arg_partial_bytes (cumulative_args_t, machine_mode,
- tree, bool);
+static int frv_arg_partial_bytes (cumulative_args_t,
+ const function_arg_info &);
static rtx frv_function_arg (cumulative_args_t, machine_mode,
const_tree, bool);
static rtx frv_function_incoming_arg (cumulative_args_t, machine_mode,
@@ -3183,28 +3184,12 @@ frv_function_arg_advance (cumulative_args_t cum_v,
}
-/* A C expression for the number of words, at the beginning of an argument,
- must be put in registers. The value must be zero for arguments that are
- passed entirely in registers or that are entirely pushed on the stack.
-
- On some machines, certain arguments must be passed partially in registers
- and partially in memory. On these machines, typically the first N words of
- arguments are passed in registers, and the rest on the stack. If a
- multi-word argument (a `double' or a structure) crosses that boundary, its
- first few words must be passed in registers and the rest must be pushed.
- This macro tells the compiler when this occurs, and how many of the words
- should go in registers.
-
- `FUNCTION_ARG' for these arguments should return the first register to be
- used by the caller for this argument; likewise `FUNCTION_INCOMING_ARG', for
- the called function. */
+/* Implement TARGET_ARG_PARTIAL_BYTES. */
static int
-frv_arg_partial_bytes (cumulative_args_t cum, machine_mode mode,
- tree type ATTRIBUTE_UNUSED, bool named ATTRIBUTE_UNUSED)
+frv_arg_partial_bytes (cumulative_args_t cum, const function_arg_info &arg)
{
-
- machine_mode xmode = (mode == BLKmode) ? SImode : mode;
+ machine_mode xmode = (arg.mode == BLKmode) ? SImode : arg.mode;
int bytes = GET_MODE_SIZE (xmode);
int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
int arg_num = *get_cumulative_args (cum);
diff --git a/gcc/config/ft32/ft32.c b/gcc/config/ft32/ft32.c
index 64b3172834f..58448c3dad2 100644
--- a/gcc/config/ft32/ft32.c
+++ b/gcc/config/ft32/ft32.c
@@ -711,8 +711,7 @@ ft32_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
that fit in argument passing registers. */
static int
-ft32_arg_partial_bytes (cumulative_args_t cum_v,
- machine_mode mode, tree type, bool named)
+ft32_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg)
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
int bytes_left, size;
@@ -720,16 +719,16 @@ ft32_arg_partial_bytes (cumulative_args_t cum_v,
if (*cum >= 8)
return 0;
- if (ft32_pass_by_reference (cum_v, mode, type, named))
+ if (ft32_pass_by_reference (cum_v, arg.mode, arg.type, arg.named))
size = 4;
- else if (type)
+ else if (arg.type)
{
- if (AGGREGATE_TYPE_P (type))
+ if (AGGREGATE_TYPE_P (arg.type))
return 0;
- size = int_size_in_bytes (type);
+ size = int_size_in_bytes (arg.type);
}
else
- size = GET_MODE_SIZE (mode);
+ size = GET_MODE_SIZE (arg.mode);
bytes_left = (4 * 6) - ((*cum - 2) * 4);
diff --git a/gcc/config/gcn/gcn.c b/gcc/config/gcn/gcn.c
index 0826c819dd6..d9eb82f876d 100644
--- a/gcc/config/gcn/gcn.c
+++ b/gcc/config/gcn/gcn.c
@@ -2349,22 +2349,21 @@ gcn_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
in registers or that are entirely pushed on the stack. */
static int
-gcn_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode, tree type,
- bool named)
+gcn_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg)
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
- if (!named)
+ if (!arg.named)
return 0;
- if (targetm.calls.must_pass_in_stack (mode, type))
+ if (targetm.calls.must_pass_in_stack (arg.mode, arg.type))
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 (mode, type) <= NUM_PARM_REGS)
+ if (cum->num + num_arg_regs (arg.mode, arg.type) <= NUM_PARM_REGS)
return 0;
return (NUM_PARM_REGS - cum->num) * UNITS_PER_WORD;
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index 4449151b6e1..13dd71575e4 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -201,8 +201,8 @@ static bool ia64_can_eliminate (const int, const int);
static machine_mode hfa_element_mode (const_tree, bool);
static void ia64_setup_incoming_varargs (cumulative_args_t, machine_mode,
tree, int *, int);
-static int ia64_arg_partial_bytes (cumulative_args_t, machine_mode,
- tree, bool);
+static int ia64_arg_partial_bytes (cumulative_args_t,
+ const function_arg_info &);
static rtx ia64_function_arg_1 (cumulative_args_t, machine_mode,
const_tree, bool, bool);
static rtx ia64_function_arg (cumulative_args_t, machine_mode,
@@ -4961,13 +4961,12 @@ ia64_function_incoming_arg (cumulative_args_t cum,
in memory. */
static int
-ia64_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
- tree type, bool named ATTRIBUTE_UNUSED)
+ia64_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg)
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
- int words = ia64_function_arg_words (type, mode);
- int offset = ia64_function_arg_offset (cum, type, words);
+ int words = ia64_function_arg_words (arg.type, arg.mode);
+ int offset = ia64_function_arg_offset (cum, arg.type, words);
/* If all argument slots are used, then it must go on the stack. */
if (cum->words + offset >= MAX_ARGUMENT_SLOTS)
diff --git a/gcc/config/iq2000/iq2000.c b/gcc/config/iq2000/iq2000.c
index ad21f1c8776..9652fa5e1fe 100644
--- a/gcc/config/iq2000/iq2000.c
+++ b/gcc/config/iq2000/iq2000.c
@@ -161,8 +161,8 @@ static section *iq2000_select_section (tree, int, unsigned HOST_WIDE_INT);
static rtx iq2000_legitimize_address (rtx, rtx, machine_mode);
static bool iq2000_pass_by_reference (cumulative_args_t, machine_mode,
const_tree, bool);
-static int iq2000_arg_partial_bytes (cumulative_args_t, machine_mode,
- tree, bool);
+static int iq2000_arg_partial_bytes (cumulative_args_t,
+ const function_arg_info &arg);
static rtx iq2000_function_arg (cumulative_args_t,
machine_mode, const_tree, bool);
static void iq2000_function_arg_advance (cumulative_args_t,
@@ -1421,13 +1421,12 @@ iq2000_function_arg_boundary (machine_mode mode, const_tree type)
}
static int
-iq2000_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
- tree type ATTRIBUTE_UNUSED,
- bool named ATTRIBUTE_UNUSED)
+iq2000_arg_partial_bytes (cumulative_args_t cum_v,
+ const function_arg_info &arg)
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
- if (mode == DImode && cum->arg_words == MAX_ARGS_IN_REGISTERS - 1)
+ if (arg.mode == DImode && cum->arg_words == MAX_ARGS_IN_REGISTERS - 1)
{
if (TARGET_DEBUG_D_MODE)
fprintf (stderr, "iq2000_arg_partial_bytes=%d\n", UNITS_PER_WORD);
diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c
index ac18aa286c8..ba6ba762301 100644
--- a/gcc/config/m32r/m32r.c
+++ b/gcc/config/m32r/m32r.c
@@ -93,8 +93,8 @@ static bool m32r_rtx_costs (rtx, machine_mode, int, int, int *, bool speed);
static int m32r_memory_move_cost (machine_mode, reg_class_t, bool);
static bool m32r_pass_by_reference (cumulative_args_t, machine_mode,
const_tree, bool);
-static int m32r_arg_partial_bytes (cumulative_args_t, machine_mode,
- tree, bool);
+static int m32r_arg_partial_bytes (cumulative_args_t,
+ const function_arg_info &);
static rtx m32r_function_arg (cumulative_args_t, machine_mode,
const_tree, bool);
static void m32r_function_arg_advance (cumulative_args_t, machine_mode,
@@ -1164,17 +1164,13 @@ gen_split_move_double (rtx operands[])
static int
-m32r_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
- tree type, bool named ATTRIBUTE_UNUSED)
+m32r_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg)
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
int words;
unsigned int size =
- (((mode == BLKmode && type)
- ? (unsigned int) int_size_in_bytes (type)
- : GET_MODE_SIZE (mode)) + UNITS_PER_WORD - 1)
- / UNITS_PER_WORD;
+ (arg.promoted_size_in_bytes () + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
if (*cum >= M32R_MAX_PARM_REGS)
words = 0;
diff --git a/gcc/config/mcore/mcore.c b/gcc/config/mcore/mcore.c
index 06f093eee12..d93c818f381 100644
--- a/gcc/config/mcore/mcore.c
+++ b/gcc/config/mcore/mcore.c
@@ -129,8 +129,7 @@ static bool mcore_rtx_costs (rtx, machine_mode, int, int,
static void mcore_external_libcall (rtx);
static bool mcore_return_in_memory (const_tree, const_tree);
static int mcore_arg_partial_bytes (cumulative_args_t,
- machine_mode,
- tree, bool);
+ const function_arg_info &);
static rtx mcore_function_arg (cumulative_args_t,
machine_mode,
const_tree, bool);
@@ -2841,22 +2840,19 @@ mcore_function_arg_boundary (machine_mode mode,
}
/* Returns the number of bytes of argument registers required to hold *part*
- of a parameter of machine mode MODE and type TYPE (which may be NULL if
- the type is not known). If the argument fits entirely in the argument
- registers, or entirely on the stack, then 0 is returned. CUM is the
- number of argument registers already used by earlier parameters to
- the function. */
+ of argument ARG. If the argument fits entirely in the argument registers,
+ or entirely on the stack, then 0 is returned. CUM is the number of
+ argument registers already used by earlier parameters to the function. */
static int
-mcore_arg_partial_bytes (cumulative_args_t cum, machine_mode mode,
- tree type, bool named)
+mcore_arg_partial_bytes (cumulative_args_t cum, const function_arg_info &arg)
{
- int reg = ROUND_REG (*get_cumulative_args (cum), mode);
+ int reg = ROUND_REG (*get_cumulative_args (cum), arg.mode);
- if (named == 0)
+ if (!arg.named)
return 0;
- if (targetm.calls.must_pass_in_stack (mode, type))
+ if (targetm.calls.must_pass_in_stack (arg.mode, arg.type))
return 0;
/* REG is not the *hardware* register number of the register that holds
@@ -2871,7 +2867,7 @@ mcore_arg_partial_bytes (cumulative_args_t cum, machine_mode mode,
return 0;
/* If the argument fits entirely in registers, return 0. */
- if (reg + mcore_num_arg_regs (mode, type) <= NPARM_REGS)
+ if (reg + mcore_num_arg_regs (arg.mode, arg.type) <= NPARM_REGS)
return 0;
/* The argument overflows the number of available argument registers.
diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c
index c2cbe3b016c..d80acdea876 100644
--- a/gcc/config/microblaze/microblaze.c
+++ b/gcc/config/microblaze/microblaze.c
@@ -1653,30 +1653,25 @@ microblaze_function_arg (cumulative_args_t cum_v, machine_mode mode,
/* Return number of bytes of argument to put in registers. */
static int
-function_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
- tree type, bool named ATTRIBUTE_UNUSED)
+function_arg_partial_bytes (cumulative_args_t cum_v,
+ const function_arg_info &arg)
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
- if ((mode == BLKmode
- || GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
- || GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT)
+ if ((arg.mode == BLKmode
+ || GET_MODE_CLASS (arg.mode) != MODE_COMPLEX_INT
+ || GET_MODE_CLASS (arg.mode) != MODE_COMPLEX_FLOAT)
&& cum->arg_words < MAX_ARGS_IN_REGISTERS)
{
- int words;
- if (mode == BLKmode)
- words = ((int_size_in_bytes (type) + UNITS_PER_WORD - 1)
- / UNITS_PER_WORD);
- else
- words = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
-
+ int words = ((arg.promoted_size_in_bytes () + UNITS_PER_WORD - 1)
+ / UNITS_PER_WORD);
if (words + cum->arg_words <= MAX_ARGS_IN_REGISTERS)
return 0; /* structure fits in registers */
return (MAX_ARGS_IN_REGISTERS - cum->arg_words) * UNITS_PER_WORD;
}
- else if (mode == DImode && cum->arg_words == MAX_ARGS_IN_REGISTERS - 1)
+ else if (arg.mode == DImode && cum->arg_words == MAX_ARGS_IN_REGISTERS - 1)
return UNITS_PER_WORD;
return 0;
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index fd5d78d1d13..10455011617 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -6140,12 +6140,12 @@ mips_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
/* Implement TARGET_ARG_PARTIAL_BYTES. */
static int
-mips_arg_partial_bytes (cumulative_args_t cum,
- machine_mode mode, tree type, bool named)
+mips_arg_partial_bytes (cumulative_args_t cum, const function_arg_info &arg)
{
struct mips_arg_info info;
- mips_get_arg_info (&info, get_cumulative_args (cum), mode, type, named);
+ mips_get_arg_info (&info, get_cumulative_args (cum),
+ arg.mode, arg.type, arg.named);
return info.stack_words > 0 ? info.reg_words * UNITS_PER_WORD : 0;
}
diff --git a/gcc/config/mn10300/mn10300.c b/gcc/config/mn10300/mn10300.c
index 8fdd1c5adf6..6f7437a42fd 100644
--- a/gcc/config/mn10300/mn10300.c
+++ b/gcc/config/mn10300/mn10300.c
@@ -1607,8 +1607,8 @@ mn10300_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
partially in registers and partially in memory. */
static int
-mn10300_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
- tree type, bool named ATTRIBUTE_UNUSED)
+mn10300_arg_partial_bytes (cumulative_args_t cum_v,
+ const function_arg_info &arg)
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
int size;
@@ -1617,11 +1617,7 @@ mn10300_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
int nregs = 2;
/* Figure out the size of the object to be passed. */
- if (mode == BLKmode)
- size = int_size_in_bytes (type);
- else
- size = GET_MODE_SIZE (mode);
-
+ size = arg.promoted_size_in_bytes ();
cum->nbytes = (cum->nbytes + 3) & ~3;
/* Don't pass this arg via a register if all the argument registers
@@ -1634,7 +1630,7 @@ mn10300_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
/* Don't pass this arg via a register if it would be split between
registers and memory. */
- if (type == NULL_TREE
+ if (arg.type == NULL_TREE
&& cum->nbytes + size > nregs * UNITS_PER_WORD)
return 0;
diff --git a/gcc/config/moxie/moxie.c b/gcc/config/moxie/moxie.c
index 0284f3c40a4..bd382f1e689 100644
--- a/gcc/config/moxie/moxie.c
+++ b/gcc/config/moxie/moxie.c
@@ -478,9 +478,7 @@ moxie_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
that fit in argument passing registers. */
static int
-moxie_arg_partial_bytes (cumulative_args_t cum_v,
- machine_mode mode,
- tree type, bool named)
+moxie_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg)
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
int bytes_left, size;
@@ -488,16 +486,16 @@ moxie_arg_partial_bytes (cumulative_args_t cum_v,
if (*cum >= 8)
return 0;
- if (moxie_pass_by_reference (cum_v, mode, type, named))
+ if (moxie_pass_by_reference (cum_v, arg.mode, arg.type, arg.named))
size = 4;
- else if (type)
+ else if (arg.type)
{
- if (AGGREGATE_TYPE_P (type))
+ if (AGGREGATE_TYPE_P (arg.type))
return 0;
- size = int_size_in_bytes (type);
+ size = int_size_in_bytes (arg.type);
}
else
- size = GET_MODE_SIZE (mode);
+ size = GET_MODE_SIZE (arg.mode);
bytes_left = (4 * 6) - ((*cum - 2) * 4);
diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c
index 84762f9edb4..fb6c5fb8bec 100644
--- a/gcc/config/msp430/msp430.c
+++ b/gcc/config/msp430/msp430.c
@@ -728,14 +728,11 @@ msp430_function_arg (cumulative_args_t cap,
#define TARGET_ARG_PARTIAL_BYTES msp430_arg_partial_bytes
int
-msp430_arg_partial_bytes (cumulative_args_t cap,
- machine_mode mode,
- tree type,
- bool named)
+msp430_arg_partial_bytes (cumulative_args_t cap, const function_arg_info &arg)
{
CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
- msp430_evaluate_arg (cap, mode, type, named);
+ msp430_evaluate_arg (cap, arg.mode, arg.type, arg.named);
if (ca->reg_count && ca->mem_count)
return ca->reg_count * UNITS_PER_WORD;
diff --git a/gcc/config/nds32/nds32.c b/gcc/config/nds32/nds32.c
index eba98126705..c92a598dc5e 100644
--- a/gcc/config/nds32/nds32.c
+++ b/gcc/config/nds32/nds32.c
@@ -1963,8 +1963,7 @@ nds32_must_pass_in_stack (machine_mode mode, const_tree type)
}
static int
-nds32_arg_partial_bytes (cumulative_args_t ca, machine_mode mode,
- tree type, bool named ATTRIBUTE_UNUSED)
+nds32_arg_partial_bytes (cumulative_args_t ca, const function_arg_info &arg)
{
/* Returns the number of bytes at the beginning of an argument that
must be put in registers. The value must be zero for arguments that are
@@ -1985,18 +1984,19 @@ nds32_arg_partial_bytes (cumulative_args_t ca, machine_mode mode,
/* If we have already runned out of argument registers, return zero
so that the argument will be entirely pushed on the stack. */
- if (NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, mode, type)
+ if (NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, arg.mode, arg.type)
>= NDS32_GPR_ARG_FIRST_REGNUM + NDS32_MAX_GPR_REGS_FOR_ARGS)
return 0;
/* Calculate how many registers do we need for this argument. */
- needed_reg_count = NDS32_NEED_N_REGS_FOR_ARG (mode, type);
+ needed_reg_count = NDS32_NEED_N_REGS_FOR_ARG (arg.mode, arg.type);
/* Calculate how many argument registers have left for passing argument.
Note that we should count it from next available register number. */
remaining_reg_count
= NDS32_MAX_GPR_REGS_FOR_ARGS
- - (NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, mode, type)
+ - (NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset,
+ arg.mode, arg.type)
- NDS32_GPR_ARG_FIRST_REGNUM);
/* Note that we have to return the nubmer of bytes, not registers count. */
diff --git a/gcc/config/nios2/nios2.c b/gcc/config/nios2/nios2.c
index e54bdba8403..1e04cf96f27 100644
--- a/gcc/config/nios2/nios2.c
+++ b/gcc/config/nios2/nios2.c
@@ -3390,20 +3390,11 @@ nios2_function_arg (cumulative_args_t cum_v, machine_mode mode,
in memory. */
static int
-nios2_arg_partial_bytes (cumulative_args_t cum_v,
- machine_mode mode, tree type ATTRIBUTE_UNUSED,
- bool named ATTRIBUTE_UNUSED)
+nios2_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg)
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
- HOST_WIDE_INT param_size;
-
- if (mode == BLKmode)
- {
- param_size = int_size_in_bytes (type);
- gcc_assert (param_size >= 0);
- }
- else
- param_size = GET_MODE_SIZE (mode);
+ HOST_WIDE_INT param_size = arg.promoted_size_in_bytes ();
+ gcc_assert (param_size >= 0);
/* Convert to words (round up). */
param_size = (UNITS_PER_WORD - 1 + param_size) / UNITS_PER_WORD;
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 778e1364540..231286e3aae 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -166,8 +166,7 @@ static void pa_init_libfuncs (void);
static rtx pa_struct_value_rtx (tree, int);
static bool pa_pass_by_reference (cumulative_args_t, machine_mode,
const_tree, bool);
-static int pa_arg_partial_bytes (cumulative_args_t, machine_mode,
- tree, bool);
+static int pa_arg_partial_bytes (cumulative_args_t, const function_arg_info &);
static void pa_function_arg_advance (cumulative_args_t, machine_mode,
const_tree, bool);
static rtx pa_function_arg (cumulative_args_t, machine_mode,
@@ -9685,8 +9684,7 @@ pa_function_arg_boundary (machine_mode mode, const_tree type)
then this routine should return zero. */
static int
-pa_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
- tree type, bool named ATTRIBUTE_UNUSED)
+pa_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg)
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
unsigned int max_arg_words = 8;
@@ -9695,10 +9693,11 @@ pa_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
if (!TARGET_64BIT)
return 0;
- if (pa_function_arg_size (mode, type) > 1 && (cum->words & 1))
+ if (pa_function_arg_size (arg.mode, arg.type) > 1 && (cum->words & 1))
offset = 1;
- if (cum->words + offset + pa_function_arg_size (mode, type) <= max_arg_words)
+ if (cum->words + offset + pa_function_arg_size (arg.mode, arg.type)
+ <= max_arg_words)
/* Arg fits fully into registers. */
return 0;
else if (cum->words + offset >= max_arg_words)
diff --git a/gcc/config/pru/pru.c b/gcc/config/pru/pru.c
index 4e1c0815385..c8ec89c6908 100644
--- a/gcc/config/pru/pru.c
+++ b/gcc/config/pru/pru.c
@@ -2179,10 +2179,7 @@ pru_function_arg (cumulative_args_t cum_v, machine_mode mode,
between registers and memory, so we can return 0. */
static int
-pru_arg_partial_bytes (cumulative_args_t cum_v ATTRIBUTE_UNUSED,
- machine_mode mode ATTRIBUTE_UNUSED,
- tree type ATTRIBUTE_UNUSED,
- bool named ATTRIBUTE_UNUSED)
+pru_arg_partial_bytes (cumulative_args_t, const function_arg_info &)
{
return 0;
}
diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
index c12b26f0dc4..f1991029bb5 100644
--- a/gcc/config/riscv/riscv.c
+++ b/gcc/config/riscv/riscv.c
@@ -2778,11 +2778,12 @@ riscv_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
static int
riscv_arg_partial_bytes (cumulative_args_t cum,
- machine_mode mode, tree type, bool named)
+ const function_arg_info &generic_arg)
{
struct riscv_arg_info arg;
- riscv_get_arg_info (&arg, get_cumulative_args (cum), mode, type, named, false);
+ riscv_get_arg_info (&arg, get_cumulative_args (cum), generic_arg.mode,
+ generic_arg.type, generic_arg.named, false);
return arg.stack_p ? arg.num_gprs * UNITS_PER_WORD : 0;
}
diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c
index f7c5384e92e..c3fc5eeb1d0 100644
--- a/gcc/config/rs6000/rs6000-call.c
+++ b/gcc/config/rs6000/rs6000-call.c
@@ -2007,8 +2007,8 @@ rs6000_function_arg (cumulative_args_t cum_v, machine_mode mode,
returns the number of bytes used by the first element of the PARALLEL. */
int
-rs6000_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
- tree type, bool named)
+rs6000_arg_partial_bytes (cumulative_args_t cum_v,
+ const function_arg_info &arg)
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
bool passed_in_gprs = true;
@@ -2017,12 +2017,13 @@ rs6000_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
machine_mode elt_mode;
int n_elts;
- rs6000_discover_homogeneous_aggregate (mode, type, &elt_mode, &n_elts);
+ rs6000_discover_homogeneous_aggregate (arg.mode, arg.type,
+ &elt_mode, &n_elts);
if (DEFAULT_ABI == ABI_V4)
return 0;
- if (USE_ALTIVEC_FOR_ARG_P (cum, elt_mode, named))
+ if (USE_ALTIVEC_FOR_ARG_P (cum, elt_mode, arg.named))
{
/* If we are passing this arg in the fixed parameter save area (gprs or
memory) as well as VRs, we do not use the partial bytes mechanism;
@@ -2041,14 +2042,13 @@ rs6000_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
}
/* In this complicated case we just disable the partial_nregs code. */
- if (TARGET_MACHO && rs6000_darwin64_struct_check_p (mode, type))
+ if (TARGET_MACHO && rs6000_darwin64_struct_check_p (arg.mode, arg.type))
return 0;
- align_words = rs6000_parm_start (mode, type, cum->words);
+ align_words = rs6000_parm_start (arg.mode, arg.type, cum->words);
if (USE_FP_FOR_ARG_P (cum, elt_mode)
- && !(TARGET_AIX && !TARGET_ELF
- && type != NULL && AGGREGATE_TYPE_P (type)))
+ && !(TARGET_AIX && !TARGET_ELF && arg.aggregate_type_p ()))
{
unsigned long n_fpreg = (GET_MODE_SIZE (elt_mode) + 7) >> 3;
@@ -2056,7 +2056,7 @@ rs6000_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
(gprs or memory) as well as FPRs, we do not use the partial
bytes mechanism; instead, rs6000_function_arg will return a
PARALLEL including a memory element as necessary. */
- if (type
+ if (arg.type
&& (cum->nargs_prototype <= 0
|| ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
&& TARGET_XL_COMPAT
@@ -2087,7 +2087,7 @@ rs6000_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
if (passed_in_gprs
&& align_words < GP_ARG_NUM_REG
- && GP_ARG_NUM_REG < align_words + rs6000_arg_size (mode, type))
+ && GP_ARG_NUM_REG < align_words + rs6000_arg_size (arg.mode, arg.type))
ret = (GP_ARG_NUM_REG - align_words) * (TARGET_32BIT ? 4 : 8);
if (ret != 0 && TARGET_DEBUG_ARG)
@@ -2222,7 +2222,8 @@ rs6000_parm_needs_stack (cumulative_args_t args_so_far, tree type)
return true;
/* Also true if we're partially in registers and partially not. */
- if (rs6000_arg_partial_bytes (args_so_far, mode, type, true) != 0)
+ function_arg_info arg (type, mode, /*named=*/true);
+ if (rs6000_arg_partial_bytes (args_so_far, arg) != 0)
return true;
/* Update info on where next arg arrives in registers. */
diff --git a/gcc/config/rs6000/rs6000-internal.h b/gcc/config/rs6000/rs6000-internal.h
index 0da040c9632..b330a5663cf 100644
--- a/gcc/config/rs6000/rs6000-internal.h
+++ b/gcc/config/rs6000/rs6000-internal.h
@@ -159,9 +159,8 @@ extern void setup_incoming_varargs (cumulative_args_t cum, machine_mode mode,
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 int rs6000_arg_partial_bytes (cumulative_args_t cum_v,
- machine_mode mode, tree type,
- bool named);
+extern int rs6000_arg_partial_bytes (cumulative_args_t,
+ const function_arg_info &);
extern void rs6000_function_arg_advance (cumulative_args_t cum,
machine_mode mode,
const_tree type, bool named);
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index ab01809ecc4..1276d3aec0f 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -298,8 +298,7 @@ static bool sh_pass_by_reference (cumulative_args_t, machine_mode,
const_tree, bool);
static bool sh_callee_copies (cumulative_args_t, machine_mode,
const_tree, bool);
-static int sh_arg_partial_bytes (cumulative_args_t, machine_mode,
- tree, bool);
+static int sh_arg_partial_bytes (cumulative_args_t, const function_arg_info &);
static void sh_function_arg_advance (cumulative_args_t, machine_mode,
const_tree, bool);
static rtx sh_function_arg (cumulative_args_t, machine_mode,
@@ -7992,20 +7991,17 @@ sh_pass_in_reg_p (const CUMULATIVE_ARGS& cum, machine_mode mode,
}
static int
-sh_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
- tree type, bool named ATTRIBUTE_UNUSED)
+sh_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg)
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
int words = 0;
- if (sh_pass_in_reg_p (*cum, mode, type)
+ if (sh_pass_in_reg_p (*cum, arg.mode, arg.type)
&& !TARGET_FPU_DOUBLE
- && (sh_round_reg (*cum, mode)
- + (mode != BLKmode
- ? CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD)
- : CEIL (int_size_in_bytes (type), UNITS_PER_WORD))
- > NPARM_REGS (mode)))
- words = NPARM_REGS (mode) - sh_round_reg (*cum, mode);
+ && (sh_round_reg (*cum, arg.mode)
+ + CEIL (arg.promoted_size_in_bytes (), UNITS_PER_WORD)
+ > NPARM_REGS (arg.mode)))
+ words = NPARM_REGS (arg.mode) - sh_round_reg (*cum, arg.mode);
return words * UNITS_PER_WORD;
}
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index e5cf9a8dfb1..6fb61749c3f 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -668,7 +668,7 @@ static pad_direction sparc_function_arg_padding (machine_mode, const_tree);
static unsigned int sparc_function_arg_boundary (machine_mode,
const_tree);
static int sparc_arg_partial_bytes (cumulative_args_t,
- machine_mode, tree, bool);
+ const function_arg_info &);
static bool sparc_return_in_memory (const_tree, const_tree);
static rtx sparc_struct_value_rtx (tree, int);
static rtx sparc_function_value (const_tree, const_tree, bool);
@@ -7533,14 +7533,13 @@ sparc_function_arg_boundary (machine_mode mode, const_tree type)
mode] will be split between that reg and memory. */
static int
-sparc_arg_partial_bytes (cumulative_args_t cum, machine_mode mode,
- tree type, bool named)
+sparc_arg_partial_bytes (cumulative_args_t cum, const function_arg_info &arg)
{
int slotno, regno, padding;
/* We pass false for incoming here, it doesn't matter. */
- slotno = function_arg_slotno (get_cumulative_args (cum), mode, type, named,
- false, &regno, &padding);
+ slotno = function_arg_slotno (get_cumulative_args (cum), arg.mode, arg.type,
+ arg.named, false, &regno, &padding);
if (slotno == -1)
return 0;
@@ -7550,7 +7549,7 @@ sparc_arg_partial_bytes (cumulative_args_t cum, machine_mode mode,
/* We are guaranteed by pass_by_reference that the size of the
argument is not greater than 8 bytes, so we only need to return
one word if the argument is partially passed in registers. */
- const int size = GET_MODE_SIZE (mode);
+ const int size = GET_MODE_SIZE (arg.mode);
if (size > UNITS_PER_WORD && slotno == SPARC_INT_ARG_MAX - 1)
return UNITS_PER_WORD;
@@ -7560,33 +7559,33 @@ sparc_arg_partial_bytes (cumulative_args_t cum, machine_mode mode,
/* We are guaranteed by pass_by_reference that the size of the
argument is not greater than 16 bytes, so we only need to return
one word if the argument is partially passed in registers. */
- if (type && AGGREGATE_TYPE_P (type))
+ if (arg.aggregate_type_p ())
{
- const int size = int_size_in_bytes (type);
+ const int size = int_size_in_bytes (arg.type);
if (size > UNITS_PER_WORD
&& (slotno == SPARC_INT_ARG_MAX - 1
|| slotno == SPARC_FP_ARG_MAX - 1))
return UNITS_PER_WORD;
}
- else if (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT
- || ((GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
- || (type && VECTOR_TYPE_P (type)))
- && !(TARGET_FPU && named)))
+ else if (GET_MODE_CLASS (arg.mode) == MODE_COMPLEX_INT
+ || ((GET_MODE_CLASS (arg.mode) == MODE_COMPLEX_FLOAT
+ || (arg.type && VECTOR_TYPE_P (arg.type)))
+ && !(TARGET_FPU && arg.named)))
{
- const int size = (type && VECTOR_FLOAT_TYPE_P (type))
- ? int_size_in_bytes (type)
- : GET_MODE_SIZE (mode);
+ const int size = (arg.type && VECTOR_FLOAT_TYPE_P (arg.type))
+ ? int_size_in_bytes (arg.type)
+ : GET_MODE_SIZE (arg.mode);
if (size > UNITS_PER_WORD && slotno == SPARC_INT_ARG_MAX - 1)
return UNITS_PER_WORD;
}
- else if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
- || (type && VECTOR_TYPE_P (type)))
+ else if (GET_MODE_CLASS (arg.mode) == MODE_COMPLEX_FLOAT
+ || (arg.type && VECTOR_TYPE_P (arg.type)))
{
- const int size = (type && VECTOR_FLOAT_TYPE_P (type))
- ? int_size_in_bytes (type)
- : GET_MODE_SIZE (mode);
+ const int size = (arg.type && VECTOR_FLOAT_TYPE_P (arg.type))
+ ? int_size_in_bytes (arg.type)
+ : GET_MODE_SIZE (arg.mode);
if (size > UNITS_PER_WORD && slotno == SPARC_FP_ARG_MAX - 1)
return UNITS_PER_WORD;
diff --git a/gcc/config/v850/v850.c b/gcc/config/v850/v850.c
index cca24edb3ae..9e221126bb0 100644
--- a/gcc/config/v850/v850.c
+++ b/gcc/config/v850/v850.c
@@ -196,27 +196,22 @@ v850_function_arg (cumulative_args_t cum_v, machine_mode mode,
/* Return the number of bytes which must be put into registers
for values which are part in registers and part in memory. */
static int
-v850_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
- tree type, bool named)
+v850_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg)
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
int size, align;
- if (!named)
+ if (!arg.named)
return 0;
- if (mode == BLKmode)
- size = int_size_in_bytes (type);
- else
- size = GET_MODE_SIZE (mode);
-
+ size = arg.promoted_size_in_bytes ();
if (size < 1)
size = 1;
if (!TARGET_GCC_ABI)
align = UNITS_PER_WORD;
- else if (type)
- align = TYPE_ALIGN (type) / BITS_PER_UNIT;
+ else if (arg.type)
+ align = TYPE_ALIGN (arg.type) / BITS_PER_UNIT;
else
align = size;
@@ -228,7 +223,7 @@ v850_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
if (cum->nbytes + size <= 4 * UNITS_PER_WORD)
return 0;
- if (type == NULL_TREE
+ if (arg.type == NULL_TREE
&& cum->nbytes + size > 4 * UNITS_PER_WORD)
return 0;
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index f05b31173e2..a7838ff3dc0 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -4057,7 +4057,7 @@ Perform a target dependent initialization of pic_offset_table_rtx.
This hook is called at the start of register allocation.
@end deftypefn
-@deftypefn {Target Hook} int TARGET_ARG_PARTIAL_BYTES (cumulative_args_t @var{cum}, machine_mode @var{mode}, tree @var{type}, bool @var{named})
+@deftypefn {Target Hook} int TARGET_ARG_PARTIAL_BYTES (cumulative_args_t @var{cum}, const function_arg_info @var{&arg})
This target hook returns the number of bytes at the beginning of an
argument that must be put in registers. The value must be zero for
arguments that are passed entirely in registers or that are entirely
diff --git a/gcc/expr.c b/gcc/expr.c
index 20e3f9ce337..b008a64d142 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -1709,11 +1709,12 @@ block_move_libcall_safe_for_call_parm (void)
for ( ; arg != void_list_node ; arg = TREE_CHAIN (arg))
{
machine_mode mode = TYPE_MODE (TREE_VALUE (arg));
+ function_arg_info arg_info (mode, /*named=*/true);
rtx tmp = targetm.calls.function_arg (args_so_far, mode,
NULL_TREE, true);
if (!tmp || !REG_P (tmp))
return false;
- if (targetm.calls.arg_partial_bytes (args_so_far, mode, NULL, 1))
+ if (targetm.calls.arg_partial_bytes (args_so_far, arg_info))
return false;
targetm.calls.function_arg_advance (args_so_far, mode,
NULL_TREE, true);
diff --git a/gcc/function.c b/gcc/function.c
index f8019513928..eabe6986d5e 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -2559,10 +2559,9 @@ assign_parm_find_entry_rtl (struct assign_parm_data_all *all,
{
int partial;
- partial = targetm.calls.arg_partial_bytes (all->args_so_far,
- data->promoted_mode,
- data->passed_type,
- data->named_arg);
+ function_arg_info arg (data->passed_type, data->promoted_mode,
+ data->named_arg);
+ partial = targetm.calls.arg_partial_bytes (all->args_so_far, arg);
data->partial = partial;
/* The caller might already have allocated stack space for the
diff --git a/gcc/target.def b/gcc/target.def
index 4266b8c7184..22f623022d3 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -4677,8 +4677,8 @@ compiler when this occurs, and how many bytes should go in registers.\n\
@code{TARGET_FUNCTION_ARG} for these arguments should return the first\n\
register to be used by the caller for this argument; likewise\n\
@code{TARGET_FUNCTION_INCOMING_ARG}, for the called function.",
- int, (cumulative_args_t cum, machine_mode mode, tree type, bool named),
- hook_int_CUMULATIVE_ARGS_mode_tree_bool_0)
+ int, (cumulative_args_t cum, const function_arg_info &arg),
+ hook_int_CUMULATIVE_ARGS_arg_info_0)
/* Update the state in CA to advance past an argument in the
argument list. The values MODE, TYPE, and NAMED describe that
diff --git a/gcc/target.h b/gcc/target.h
index 633e38469a9..a65693049b2 100644
--- a/gcc/target.h
+++ b/gcc/target.h
@@ -149,6 +149,9 @@ class ao_ref;
/* This is defined in tree-vectorizer.h. */
class _stmt_vec_info;
+/* This is defined in calls.h. */
+class function_arg_info;
+
/* These are defined in tree-vect-stmts.c. */
extern tree stmt_vectype (class _stmt_vec_info *);
extern bool stmt_in_inner_loop_p (class _stmt_vec_info *);
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index 8a83ce8332c..855a5b385d3 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -768,10 +768,8 @@ hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true (
}
int
-hook_int_CUMULATIVE_ARGS_mode_tree_bool_0 (
- cumulative_args_t ca ATTRIBUTE_UNUSED,
- machine_mode mode ATTRIBUTE_UNUSED,
- tree type ATTRIBUTE_UNUSED, bool named ATTRIBUTE_UNUSED)
+hook_int_CUMULATIVE_ARGS_arg_info_0 (cumulative_args_t,
+ const function_arg_info &)
{
return 0;
}
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 017a9d21908..9dc249bd140 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -137,8 +137,8 @@ extern bool hook_bool_CUMULATIVE_ARGS_mode_tree_bool_false
(cumulative_args_t, machine_mode, const_tree, bool);
extern bool hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true
(cumulative_args_t, machine_mode, const_tree, bool);
-extern int hook_int_CUMULATIVE_ARGS_mode_tree_bool_0
- (cumulative_args_t, machine_mode, tree, bool);
+extern int hook_int_CUMULATIVE_ARGS_arg_info_0
+ (cumulative_args_t, const function_arg_info &);
extern void hook_void_CUMULATIVE_ARGS_tree
(cumulative_args_t, tree);
extern const char *hook_invalid_arg_for_unprototyped_fn