+2019-08-20 Richard Sandiford <richard.sandiford@arm.com>
+
+ * calls.h (apply_pass_by_reference_rules): Declare.
+ * calls.c (apply_pass_by_reference_rules): New function.
+ * config/c6x/c6x.c (c6x_call_saved_register_used): Use it.
+ * config/rs6000/rs6000-call.c (rs6000_parm_needs_stack): Likewise.
+ * config/s390/s390.c (s390_call_saved_register_used): Likewise.
+ * function.c (assign_parm_find_data_types): Likewise.
+ * var-tracking.c (prepare_call_arguments): Likewise.
+
2019-08-20 Richard Sandiford <richard.sandiford@arm.com>
* target.def (must_pass_in_stack): Take a function_arg_info instead
return pass_by_reference (NULL, function_arg_info (type, /*named=*/false));
}
+/* Decide whether ARG, which occurs in the state described by CA,
+ should be passed by reference. Return true if so and update
+ ARG accordingly. */
+
+bool
+apply_pass_by_reference_rules (CUMULATIVE_ARGS *ca, function_arg_info &arg)
+{
+ if (pass_by_reference (ca, arg))
+ {
+ arg.type = build_pointer_type (arg.type);
+ arg.mode = TYPE_MODE (arg.type);
+ return true;
+ }
+ return false;
+}
+
/* Return true if ARG, which is passed by reference, should be callee
copied instead of caller copied. */
extern bool pass_by_reference (CUMULATIVE_ARGS *, function_arg_info);
extern bool pass_va_arg_by_reference (tree);
+extern bool apply_pass_by_reference_rules (CUMULATIVE_ARGS *,
+ function_arg_info &);
extern bool reference_callee_copied (CUMULATIVE_ARGS *,
const function_arg_info &);
extern void maybe_warn_alloc_args_overflow (tree, tree, tree[2], int[2]);
cumulative_args_t cum;
HARD_REG_SET call_saved_regset;
tree parameter;
- machine_mode mode;
- tree type;
rtx parm_rtx;
int i;
if (TREE_CODE (parameter) == ERROR_MARK)
return true;
- type = TREE_TYPE (parameter);
- gcc_assert (type);
-
- mode = TYPE_MODE (type);
- gcc_assert (mode);
-
- if (pass_by_reference (&cum_v, function_arg_info (type, /*named=*/true)))
- {
- mode = Pmode;
- type = build_pointer_type (type);
- }
+ function_arg_info arg (TREE_TYPE (parameter), /*named=*/true);
+ apply_pass_by_reference_rules (&cum_v, arg);
- function_arg_info arg (type, mode, /*named=*/false);
parm_rtx = c6x_function_arg (cum, arg);
c6x_function_arg_advance (cum, arg);
static bool
rs6000_parm_needs_stack (cumulative_args_t args_so_far, tree type)
{
- machine_mode mode;
int unsignedp;
rtx entry_parm;
type = TREE_TYPE (first_field (type));
/* See if this arg was passed by invisible reference. */
- if (pass_by_reference (get_cumulative_args (args_so_far),
- function_arg_info (type, /*named=*/true)))
- type = build_pointer_type (type);
+ function_arg_info arg (type, /*named=*/true);
+ apply_pass_by_reference_rules (get_cumulative_args (args_so_far), arg);
/* Find mode as it is passed by the ABI. */
unsignedp = TYPE_UNSIGNED (type);
- mode = promote_mode (type, TYPE_MODE (type), &unsignedp);
+ arg.mode = promote_mode (arg.type, arg.mode, &unsignedp);
/* If we must pass in stack, we need a stack. */
- function_arg_info arg (type, mode, /*named=*/true);
if (rs6000_must_pass_in_stack (arg))
return true;
CUMULATIVE_ARGS cum_v;
cumulative_args_t cum;
tree parameter;
- machine_mode mode;
- tree type;
rtx parm_rtx;
int reg, i;
if (TREE_CODE (parameter) == ERROR_MARK)
return true;
- type = TREE_TYPE (parameter);
- gcc_assert (type);
-
- mode = TYPE_MODE (type);
- gcc_assert (mode);
-
/* We assume that in the target function all parameters are
named. This only has an impact on vector argument register
usage none of which is call-saved. */
- if (pass_by_reference (&cum_v, function_arg_info (type, /*named=*/true)))
- {
- mode = Pmode;
- type = build_pointer_type (type);
- }
+ function_arg_info arg (TREE_TYPE (parameter), /*named=*/true);
+ apply_pass_by_reference_rules (&cum_v, arg);
- function_arg_info arg (type, mode, /*named=*/true);
parm_rtx = s390_function_arg (cum, arg);
s390_function_arg_advance (cum, arg);
/* See if this arg was passed by invisible reference. */
{
function_arg_info arg (passed_type, passed_mode, data->named_arg);
- if (pass_by_reference (&all->args_so_far_v, arg))
+ if (apply_pass_by_reference_rules (&all->args_so_far_v, arg))
{
- passed_type = nominal_type = build_pointer_type (passed_type);
+ passed_type = nominal_type = arg.type;
data->passed_pointer = true;
- passed_mode = nominal_mode = TYPE_MODE (nominal_type);
+ passed_mode = nominal_mode = arg.mode;
}
}
}
if (t && t != void_list_node)
{
- tree argtype = TREE_VALUE (t);
rtx reg;
- function_arg_info orig_arg (argtype, /*named=*/true);
- if (pass_by_reference (&args_so_far_v, orig_arg))
- argtype = build_pointer_type (argtype);
- machine_mode mode = TYPE_MODE (argtype);
- function_arg_info arg (argtype, /*named=*/true);
+ function_arg_info arg (TREE_VALUE (t), /*named=*/true);
+ apply_pass_by_reference_rules (&args_so_far_v, arg);
reg = targetm.calls.function_arg (args_so_far, arg);
- if (TREE_CODE (argtype) == REFERENCE_TYPE
- && INTEGRAL_TYPE_P (TREE_TYPE (argtype))
+ if (TREE_CODE (arg.type) == REFERENCE_TYPE
+ && INTEGRAL_TYPE_P (TREE_TYPE (arg.type))
&& reg
&& REG_P (reg)
- && GET_MODE (reg) == mode
- && (GET_MODE_CLASS (mode) == MODE_INT
- || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
+ && GET_MODE (reg) == arg.mode
+ && (GET_MODE_CLASS (arg.mode) == MODE_INT
+ || GET_MODE_CLASS (arg.mode) == MODE_PARTIAL_INT)
&& REG_P (x)
&& REGNO (x) == REGNO (reg)
- && GET_MODE (x) == mode
+ && GET_MODE (x) == arg.mode
&& item)
{
machine_mode indmode
- = TYPE_MODE (TREE_TYPE (argtype));
+ = TYPE_MODE (TREE_TYPE (arg.type));
rtx mem = gen_rtx_MEM (indmode, x);
cselib_val *val = cselib_lookup (mem, indmode, 0, VOIDmode);
if (val && cselib_preserved_value_p (val))