public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [00/13] Pass an argument descriptor to target hooks
@ 2019-08-19 15:15 Richard Sandiford
  2019-08-19 15:16 ` [01/13] Add pass_va_arg_by_reference Richard Sandiford
                   ` (12 more replies)
  0 siblings, 13 replies; 27+ messages in thread
From: Richard Sandiford @ 2019-08-19 15:15 UTC (permalink / raw)
  To: gcc-patches

For the SVE calling conventions, function_arg and function_arg_advance
need to know whether an argument is being passed by reference or not.
The simplest way of providing that information would have been to add a
new parameter, or convert the "named" parameter into a bitmask.  But it
seemed cleaner to wrap the argument information in a struct/class instead.

The bulk of this series therefore adds a function_arg_info that
initially records the type, mode and named flag.  The final patch then
adds the pass-by-reference information as well, which becomes a small
change on its own.

The new struct/class inherits a couple of non-obvious points of the
current interface:

(a) For some hooks the mode is the mode of the type.  For others it's
    the mode after promotion.  On targets that use argument promotion,
    this affects the choice between the mode and the type when both
    pieces of information are specified.

(a) Traditionally the type is null when calling libgcc support functions.
    But I think the argument conceptually still has a type (most of the
    functions are written in C after all).  It's just that the type is
    inferred from the unpromoted mode rather than being specified directly.
    So when we have access to the unpromoted mode, we can still query some
    properties of the type even if we don't have access to the type itself.

    (I remember it was said years ago that we should clean this up and
    call libgcc functions like any other function.  But TBH I can't see
    that ever happening.)

Of course, the ABI support is one of the most sensitive areas of the
compiler and it would be very easy to introduce a silent ABI break.
I've therefore tried to be conservative and stick to the following
changes:

(1) Replace uses of the old parameters with the corresponding fields
    of the function_arg_info (which hold the same values as before).

(2) In cases where the mode is the unpromoted mode, replace the calculation:

      type ? int_size_in_bytes (type) : GET_MODE_SIZE (mode)

    with a new type_size_in_bytes (), which computes the same thing
    in the same way.

    [The name is based on (b) above -- every argument has a type,
    even if we aren't given it explicitly.]

(3) In cases where the mode is the promoted mode, replace the calculation:

      mode == BLKmode ? int_size_in_bytes (type) : GET_MODE_SIZE (mode)

    with a new promoted_size_in_bytes (), which computes the same thing
    in the same way.

    Not all the affected targets use argument promotion, but that's
    what the calculation is logically providing in the affected contexts.

    [The only case I found in which the calculation was used for an
    unpromoted mode was aarch64_pass_by_reference.  Other targets use
    the expression in (2) here, and the later:

      /* Aggregates are passed by reference based on their size.  */
      if (type && AGGREGATE_TYPE_P (type))
	{
	  size = int_size_in_bytes (type);
	}

    suggests that that might have been the intention for aarch64 too.
    The series just leaves the aarch64 calculation as-is.]

(4) In cases where the mode is the promoted mode, replace the calculation:

      mode == BLKmode && type ? int_size_in_bytes (type) : GET_MODE_SIZE (mode)

    with promoted_size_in_bytes (), as for (3).  This means that the
    compiler will now ICE (via a segfault) on the invalid combination:

      mode == BLKmode && !type

    which I think is preferable to letting the error slip past.

(5) Replace the common test:

      type && AGGREGRATE_TYPE_P (type)

    with a new aggregate_type_p (), which computes the same thing
    in the same way.  This is again based on point (b) above.

(6) In function_arg only, replace:

      mode == VOIDmode

    and

      type == void_type_node

    (or both) with end_marker_p ().

Bootstrapped & regression-tested on aarch64-linux-gnu and x86_64-linux-gnu
(all languages for the latter).  I also tested each individual patch in
the series by compiling at least one target per CPU directory, checking
for no new warnings, and checking that there were no changes in assembly
output for gcc.c-torture, gcc.dg and g++.dg at -O0.

diffstat for series:

 66 files changed, 1676 insertions(+), 2246 deletions(-)

although admittedly a lot of that comes from culling out-of-date comments.

Richard

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [01/13] Add pass_va_arg_by_reference
  2019-08-19 15:15 [00/13] Pass an argument descriptor to target hooks Richard Sandiford
@ 2019-08-19 15:16 ` Richard Sandiford
  2019-08-19 20:04   ` Jeff Law
  2019-08-19 15:17 ` [02/13] Add must_pass_va_arg_in_stack Richard Sandiford
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 27+ messages in thread
From: Richard Sandiford @ 2019-08-19 15:16 UTC (permalink / raw)
  To: gcc-patches

This patch splits out a common idiom from the va_arg gimplification
routines, so that there's only one place to update later.


2019-08-19  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	* calls.h (pass_va_arg_by_reference): Declare.
	* calls.c (pass_va_arg_by_reference): New function.
	* config/aarch64/aarch64.c (aarch64_gimplify_va_arg_expr): Use it.
	* config/alpha/alpha.c (alpha_gimplify_va_arg): Likewise.
	* config/gcn/gcn.c (gcn_gimplify_va_arg_expr): Likewise.
	* config/i386/i386.c (ix86_gimplify_va_arg): Likewise.
	* config/ia64/ia64.c (ia64_gimplify_va_arg): Likewise.
	* config/mips/mips.c (mips_std_gimplify_va_arg_expr): Likewise.
	(mips_gimplify_va_arg_expr): Likewise.
	* config/msp430/msp430.c (msp430_gimplify_va_arg_expr): Likewise.
	* config/pa/pa.c (hppa_gimplify_va_arg_expr): Likewise.
	* config/rs6000/rs6000-call.c (rs6000_gimplify_va_arg): Likewise.
	* config/s390/s390.c (s390_gimplify_va_arg): Likewise.
	* config/sparc/sparc.c (sparc_gimplify_va_arg): Likewise.
	* config/spu/spu.c (spu_gimplify_va_arg_expr): Likewise.
	* config/tilegx/tilegx.c (tilegx_gimplify_va_arg_expr): Likewise.
	* config/tilepro/tilepro.c (tilepro_gimplify_va_arg_expr): Likewise.
	* config/visium/visium.c (visium_gimplify_va_arg): Likewise.
	* config/xtensa/xtensa.c (xtensa_gimplify_va_arg_expr): Likewise.
	* targhooks.c (std_gimplify_va_arg_expr): Likewise.

Index: gcc/calls.h
===================================================================
--- gcc/calls.h	2019-03-08 18:15:33.696751769 +0000
+++ gcc/calls.h	2019-08-19 15:58:10.742205564 +0100
@@ -35,6 +35,7 @@ extern void fixup_tail_calls (void);
 
 extern bool pass_by_reference (CUMULATIVE_ARGS *, machine_mode,
 			       tree, bool);
+extern bool pass_va_arg_by_reference (tree);
 extern bool reference_callee_copied (CUMULATIVE_ARGS *, machine_mode,
 				     tree, bool);
 extern void maybe_warn_alloc_args_overflow (tree, tree, tree[2], int[2]);
Index: gcc/calls.c
===================================================================
--- gcc/calls.c	2019-08-13 22:35:04.921302360 +0100
+++ gcc/calls.c	2019-08-19 15:58:10.742205564 +0100
@@ -927,6 +927,15 @@ pass_by_reference (CUMULATIVE_ARGS *ca,
 					  type, named_arg);
 }
 
+/* Return true if TYPE should be passed by reference when passed to
+   the "..." arguments of a function.  */
+
+bool
+pass_va_arg_by_reference (tree type)
+{
+  return pass_by_reference (NULL, TYPE_MODE (type), type, false);
+}
+
 /* Return true if TYPE, which is passed by reference, should be callee
    copied instead of caller copied.  */
 
Index: gcc/config/aarch64/aarch64.c
===================================================================
--- gcc/config/aarch64/aarch64.c	2019-08-15 10:00:02.366735649 +0100
+++ gcc/config/aarch64/aarch64.c	2019-08-19 15:58:10.746205533 +0100
@@ -14271,7 +14271,7 @@ aarch64_gimplify_va_arg_expr (tree valis
   HOST_WIDE_INT size, rsize, adjust, align;
   tree t, u, cond1, cond2;
 
-  indirect_p = pass_by_reference (NULL, TYPE_MODE (type), type, false);
+  indirect_p = pass_va_arg_by_reference (type);
   if (indirect_p)
     type = build_pointer_type (type);
 
Index: gcc/config/alpha/alpha.c
===================================================================
--- gcc/config/alpha/alpha.c	2019-08-13 22:35:11.721252311 +0100
+++ gcc/config/alpha/alpha.c	2019-08-19 15:58:10.750205506 +0100
@@ -6330,7 +6330,7 @@ alpha_gimplify_va_arg (tree valist, tree
   t = fold_convert (build_nonstandard_integer_type (64, 0), offset_field);
   offset = get_initialized_tmp_var (t, pre_p, NULL);
 
-  indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
+  indirect = pass_va_arg_by_reference (type);
 
   if (indirect)
     {
Index: gcc/config/gcn/gcn.c
===================================================================
--- gcc/config/gcn/gcn.c	2019-08-13 22:35:11.733252223 +0100
+++ gcc/config/gcn/gcn.c	2019-08-19 15:58:10.750205506 +0100
@@ -2493,7 +2493,7 @@ gcn_gimplify_va_arg_expr (tree valist, t
   tree t, u;
   bool indirect;
 
-  indirect = pass_by_reference (NULL, TYPE_MODE (type), type, 0);
+  indirect = pass_va_arg_by_reference (type);
   if (indirect)
     {
       type = ptr;
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	2019-08-19 15:57:56.338309784 +0100
+++ gcc/config/i386/i386.c	2019-08-19 15:58:10.754205475 +0100
@@ -4307,7 +4307,7 @@ ix86_gimplify_va_arg (tree valist, tree
   ovf = build3 (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE);
   sav = build3 (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);
 
-  indirect_p = pass_by_reference (NULL, TYPE_MODE (type), type, false);
+  indirect_p = pass_va_arg_by_reference (type);
   if (indirect_p)
     type = build_pointer_type (type);
   size = arg_int_size_in_bytes (type);
Index: gcc/config/ia64/ia64.c
===================================================================
--- gcc/config/ia64/ia64.c	2019-08-13 22:35:11.741252166 +0100
+++ gcc/config/ia64/ia64.c	2019-08-19 15:58:10.754205475 +0100
@@ -5147,7 +5147,7 @@ ia64_gimplify_va_arg (tree valist, tree
 		      gimple_seq *post_p)
 {
   /* Variable sized types are passed by reference.  */
-  if (pass_by_reference (NULL, TYPE_MODE (type), type, false))
+  if (pass_va_arg_by_reference (type))
     {
       tree ptrtype = build_pointer_type (type);
       tree addr = std_gimplify_va_arg_expr (valist, ptrtype, pre_p, post_p);
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	2019-08-13 22:35:11.741252166 +0100
+++ gcc/config/mips/mips.c	2019-08-19 15:58:10.758205447 +0100
@@ -6780,7 +6780,7 @@ mips_std_gimplify_va_arg_expr (tree vali
   unsigned HOST_WIDE_INT align, boundary;
   bool indirect;
 
-  indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
+  indirect = pass_va_arg_by_reference (type);
   if (indirect)
     type = build_pointer_type (type);
 
@@ -6867,7 +6867,7 @@ mips_gimplify_va_arg_expr (tree valist,
   tree addr;
   bool indirect_p;
 
-  indirect_p = pass_by_reference (NULL, TYPE_MODE (type), type, 0);
+  indirect_p = pass_va_arg_by_reference (type);
   if (indirect_p)
     type = build_pointer_type (type);
 
Index: gcc/config/msp430/msp430.c
===================================================================
--- gcc/config/msp430/msp430.c	2019-08-15 15:26:04.800237365 +0100
+++ gcc/config/msp430/msp430.c	2019-08-19 15:58:10.758205447 +0100
@@ -856,7 +856,7 @@ msp430_gimplify_va_arg_expr (tree valist
   unsigned HOST_WIDE_INT align, boundary;
   bool indirect;
 
-  indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
+  indirect = pass_va_arg_by_reference (type);
   if (indirect)
     type = build_pointer_type (type);
 
Index: gcc/config/pa/pa.c
===================================================================
--- gcc/config/pa/pa.c	2019-08-13 22:35:11.749252108 +0100
+++ gcc/config/pa/pa.c	2019-08-19 15:58:10.762205420 +0100
@@ -6377,7 +6377,7 @@ hppa_gimplify_va_arg_expr (tree valist,
       unsigned int size, ofs;
       bool indirect;
 
-      indirect = pass_by_reference (NULL, TYPE_MODE (type), type, 0);
+      indirect = pass_va_arg_by_reference (type);
       if (indirect)
 	{
 	  type = ptr;
Index: gcc/config/rs6000/rs6000-call.c
===================================================================
--- gcc/config/rs6000/rs6000-call.c	2019-08-13 22:35:11.765251990 +0100
+++ gcc/config/rs6000/rs6000-call.c	2019-08-19 15:58:10.762205420 +0100
@@ -2690,7 +2690,7 @@ rs6000_gimplify_va_arg (tree valist, tre
   int regalign = 0;
   gimple *stmt;
 
-  if (pass_by_reference (NULL, TYPE_MODE (type), type, false))
+  if (pass_va_arg_by_reference (type))
     {
       t = rs6000_gimplify_va_arg (valist, ptrtype, pre_p, post_p);
       return build_va_arg_indirect_ref (t);
Index: gcc/config/s390/s390.c
===================================================================
--- gcc/config/s390/s390.c	2019-08-13 22:35:11.789251813 +0100
+++ gcc/config/s390/s390.c	2019-08-19 15:58:10.762205420 +0100
@@ -12476,7 +12476,7 @@ s390_gimplify_va_arg (tree valist, tree
 
   s390_check_type_for_vector_abi (type, true, false);
 
-  if (pass_by_reference (NULL, TYPE_MODE (type), type, false))
+  if (pass_va_arg_by_reference (type))
     {
       if (TARGET_DEBUG_ARG)
 	{
Index: gcc/config/sparc/sparc.c
===================================================================
--- gcc/config/sparc/sparc.c	2019-08-13 22:35:11.797251752 +0100
+++ gcc/config/sparc/sparc.c	2019-08-19 15:58:10.766205389 +0100
@@ -7935,7 +7935,7 @@ sparc_gimplify_va_arg (tree valist, tree
   bool indirect;
   tree ptrtype = build_pointer_type (type);
 
-  if (pass_by_reference (NULL, TYPE_MODE (type), type, false))
+  if (pass_va_arg_by_reference (type))
     {
       indirect = true;
       size = rsize = UNITS_PER_WORD;
Index: gcc/config/spu/spu.c
===================================================================
--- gcc/config/spu/spu.c	2019-08-13 22:35:11.801251725 +0100
+++ gcc/config/spu/spu.c	2019-08-19 15:58:10.766205389 +0100
@@ -4053,8 +4053,7 @@ spu_gimplify_va_arg_expr (tree valist, t
 
   /* if an object is dynamically sized, a pointer to it is passed
      instead of the object itself. */
-  pass_by_reference_p = pass_by_reference (NULL, TYPE_MODE (type), type,
-					   false);
+  pass_by_reference_p = pass_va_arg_by_reference (type);
   if (pass_by_reference_p)
     type = build_pointer_type (type);
   size = int_size_in_bytes (type);
Index: gcc/config/tilegx/tilegx.c
===================================================================
--- gcc/config/tilegx/tilegx.c	2019-08-13 22:35:11.805251695 +0100
+++ gcc/config/tilegx/tilegx.c	2019-08-19 15:58:10.766205389 +0100
@@ -471,8 +471,7 @@ tilegx_gimplify_va_arg_expr (tree valist
 
   /* If an object is dynamically sized, a pointer to it is passed
      instead of the object itself.  */
-  pass_by_reference_p = pass_by_reference (NULL, TYPE_MODE (type), type,
-					   false);
+  pass_by_reference_p = pass_va_arg_by_reference (type);
 
   if (pass_by_reference_p)
     type = build_pointer_type (type);
Index: gcc/config/tilepro/tilepro.c
===================================================================
--- gcc/config/tilepro/tilepro.c	2019-08-13 22:35:11.805251695 +0100
+++ gcc/config/tilepro/tilepro.c	2019-08-19 15:58:10.766205389 +0100
@@ -419,8 +419,7 @@ tilepro_gimplify_va_arg_expr (tree valis
 
   /* if an object is dynamically sized, a pointer to it is passed
      instead of the object itself.  */
-  pass_by_reference_p = pass_by_reference (NULL, TYPE_MODE (type), type,
-					   false);
+  pass_by_reference_p = pass_va_arg_by_reference (type);
 
   if (pass_by_reference_p)
     type = build_pointer_type (type);
Index: gcc/config/visium/visium.c
===================================================================
--- gcc/config/visium/visium.c	2019-03-18 12:24:58.875434349 +0000
+++ gcc/config/visium/visium.c	2019-08-19 15:58:10.766205389 +0100
@@ -1637,8 +1637,7 @@ visium_gimplify_va_arg (tree valist, tre
   tree f_ovfl, f_gbase, f_fbase, f_gbytes, f_fbytes;
   tree ovfl, base, bytes;
   HOST_WIDE_INT size, rsize;
-  const bool by_reference_p
-    = pass_by_reference (NULL, TYPE_MODE (type), type, false);
+  const bool by_reference_p = pass_va_arg_by_reference (type);
   const bool float_reg_arg_p
     = (TARGET_FPU && !by_reference_p
        && ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT
Index: gcc/config/xtensa/xtensa.c
===================================================================
--- gcc/config/xtensa/xtensa.c	2019-08-13 22:35:11.805251695 +0100
+++ gcc/config/xtensa/xtensa.c	2019-08-19 15:58:10.766205389 +0100
@@ -3252,7 +3252,7 @@ xtensa_gimplify_va_arg_expr (tree valist
   tree lab_false, lab_over, lab_false2;
   bool indirect;
 
-  indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
+  indirect = pass_va_arg_by_reference (type);
   if (indirect)
     type = build_pointer_type (type);
 
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c	2019-08-15 15:26:09.232205170 +0100
+++ gcc/targhooks.c	2019-08-19 15:58:10.766205389 +0100
@@ -2177,7 +2177,7 @@ std_gimplify_va_arg_expr (tree valist, t
   if (ARGS_GROW_DOWNWARD)
     gcc_unreachable ();
 
-  indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
+  indirect = pass_va_arg_by_reference (type);
   if (indirect)
     type = build_pointer_type (type);
 

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [02/13] Add must_pass_va_arg_in_stack
  2019-08-19 15:15 [00/13] Pass an argument descriptor to target hooks Richard Sandiford
  2019-08-19 15:16 ` [01/13] Add pass_va_arg_by_reference Richard Sandiford
@ 2019-08-19 15:17 ` Richard Sandiford
  2019-08-19 20:05   ` Jeff Law
  2019-08-19 15:18 ` [03/13] Use function_arg_info for TARGET_ARG_PARTIAL_BYTES Richard Sandiford
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 27+ messages in thread
From: Richard Sandiford @ 2019-08-19 15:17 UTC (permalink / raw)
  To: gcc-patches

This patch splits out another idiom from the va_arg gimplification
routines, so that there's only one place to update later.


2019-08-19  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	* 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.
	* config/sh/sh.c (sh_gimplify_va_arg_expr): Likewise.
	* config/stormy16/stormy16.c (xstormy16_gimplify_va_arg_expr):
	Likewise.
	* config/xtensa/xtensa.c (xtensa_gimplify_va_arg_expr): Likewise.

Index: gcc/calls.h
===================================================================
--- gcc/calls.h	2019-08-19 15:58:10.742205564 +0100
+++ gcc/calls.h	2019-08-19 15:58:16.094166837 +0100
@@ -28,6 +28,7 @@ extern bool gimple_alloca_call_p (const
 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_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);
 extern rtx expand_call (tree, rtx, int);
Index: gcc/calls.c
===================================================================
--- gcc/calls.c	2019-08-19 15:58:10.742205564 +0100
+++ gcc/calls.c	2019-08-19 15:58:16.094166837 +0100
@@ -5900,5 +5900,14 @@ must_pass_in_stack_var_size_or_pad (mach
   return false;
 }
 
+/* Return true if TYPE must be passed on the stack when passed to
+   the "..." arguments of a function.  */
+
+bool
+must_pass_va_arg_in_stack (tree type)
+{
+  return targetm.calls.must_pass_in_stack (TYPE_MODE (type), type);
+}
+
 /* Tell the garbage collector about GTY markers in this source file.  */
 #include "gt-calls.h"
Index: gcc/config/alpha/alpha.c
===================================================================
--- gcc/config/alpha/alpha.c	2019-08-19 15:58:10.750205506 +0100
+++ gcc/config/alpha/alpha.c	2019-08-19 15:58:16.094166837 +0100
@@ -6243,7 +6243,7 @@ alpha_gimplify_va_arg_1 (tree type, tree
 
   /* If the type could not be passed in registers, skip the block
      reserved for the registers.  */
-  if (targetm.calls.must_pass_in_stack (TYPE_MODE (type), type))
+  if (must_pass_va_arg_in_stack (type))
     {
       t = build_int_cst (TREE_TYPE (offset), 6*8);
       gimplify_assign (offset,
Index: gcc/config/sh/sh.c
===================================================================
--- gcc/config/sh/sh.c	2019-08-13 22:35:11.793251783 +0100
+++ gcc/config/sh/sh.c	2019-08-19 15:58:16.098166809 +0100
@@ -7656,9 +7656,8 @@ sh_gimplify_va_arg_expr (tree valist, tr
   tree addr, lab_over = NULL, result = NULL;
   tree eff_type;
 
-  const bool pass_by_ref =
-    !VOID_TYPE_P (type)
-    && targetm.calls.must_pass_in_stack (TYPE_MODE (type), type);
+  const bool pass_by_ref
+    = !VOID_TYPE_P (type) && must_pass_va_arg_in_stack (type);
 
   if (pass_by_ref)
     type = build_pointer_type (type);
Index: gcc/config/stormy16/stormy16.c
===================================================================
--- gcc/config/stormy16/stormy16.c	2019-08-13 22:35:11.805251695 +0100
+++ gcc/config/stormy16/stormy16.c	2019-08-19 15:58:16.098166809 +0100
@@ -1342,7 +1342,7 @@ xstormy16_gimplify_va_arg_expr (tree val
   count = build3 (COMPONENT_REF, TREE_TYPE (f_count), valist, f_count,
 		  NULL_TREE);
 
-  must_stack = targetm.calls.must_pass_in_stack (TYPE_MODE (type), type);
+  must_stack = must_pass_va_arg_in_stack (type);
   size_tree = round_up (size_in_bytes (type), UNITS_PER_WORD);
   gimplify_expr (&size_tree, pre_p, NULL, is_gimple_val, fb_rvalue);
 
Index: gcc/config/xtensa/xtensa.c
===================================================================
--- gcc/config/xtensa/xtensa.c	2019-08-19 15:58:10.766205389 +0100
+++ gcc/config/xtensa/xtensa.c	2019-08-19 15:58:16.098166809 +0100
@@ -3328,7 +3328,7 @@ xtensa_gimplify_va_arg_expr (tree valist
   array = create_tmp_var (ptr_type_node);
 
   lab_over = NULL;
-  if (!targetm.calls.must_pass_in_stack (TYPE_MODE (type), type))
+  if (!must_pass_va_arg_in_stack (type))
     {
       lab_false = create_artificial_label (UNKNOWN_LOCATION);
       lab_over = create_artificial_label (UNKNOWN_LOCATION);

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [03/13] Use function_arg_info for TARGET_ARG_PARTIAL_BYTES
  2019-08-19 15:15 [00/13] Pass an argument descriptor to target hooks Richard Sandiford
  2019-08-19 15:16 ` [01/13] Add pass_va_arg_by_reference Richard Sandiford
  2019-08-19 15:17 ` [02/13] Add must_pass_va_arg_in_stack Richard Sandiford
@ 2019-08-19 15:18 ` Richard Sandiford
  2019-08-19 20:42   ` Jeff Law
  2019-08-19 15:19 ` [04/13] Use function_arg_info for TARGET_PASS_BY_REFERENCE Richard Sandiford
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 27+ messages in thread
From: Richard Sandiford @ 2019-08-19 15:18 UTC (permalink / raw)
  To: gcc-patches

This patch adds the function_arg_info class and uses it for
TARGET_ARG_PARTIAL_BYTES.

The hook is passed the promoted mode instead of the original type mode.

The arguments aren't mentioned in the documentation, which is why the
target.def change is so small.

The patch changes "true" to "arg.named" in:

  gcc_assert (!epiphany_pass_by_reference (cum, mode, type, /* named */ true));

but epiphany_pass_by_reference doesn't care about the named flag.


2019-08-19  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	* 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.

Index: gcc/target.def
===================================================================
--- gcc/target.def	2019-08-15 15:26:09.232205170 +0100
+++ gcc/target.def	2019-08-19 15:58:21.746125942 +0100
@@ -4677,8 +4677,8 @@ compiler when this occurs, and how many
 @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
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	2019-08-15 15:26:09.228205200 +0100
+++ gcc/doc/tm.texi	2019-08-19 15:58:21.746125942 +0100
@@ -4057,7 +4057,7 @@ Perform a target dependent initializatio
 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
Index: gcc/target.h
===================================================================
--- gcc/target.h	2019-07-10 19:41:21.619936277 +0100
+++ gcc/target.h	2019-08-19 15:58:21.746125942 +0100
@@ -149,6 +149,9 @@ struct noce_if_info;
 /* 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 *);
Index: gcc/calls.h
===================================================================
--- gcc/calls.h	2019-08-19 15:58:16.094166837 +0100
+++ gcc/calls.h	2019-08-19 15:58:21.714126173 +0100
@@ -20,6 +20,77 @@ Software Foundation; either version 3, o
 #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);
Index: gcc/targhooks.h
===================================================================
--- gcc/targhooks.h	2019-08-15 15:26:09.232205170 +0100
+++ gcc/targhooks.h	2019-08-19 15:58:21.746125942 +0100
@@ -137,8 +137,8 @@ extern bool hook_bool_CUMULATIVE_ARGS_tr
   (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
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c	2019-08-19 15:58:10.766205389 +0100
+++ gcc/targhooks.c	2019-08-19 15:58:21.746125942 +0100
@@ -768,10 +768,8 @@ hook_bool_CUMULATIVE_ARGS_mode_tree_bool
 }
 
 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;
 }
Index: gcc/calls.c
===================================================================
--- gcc/calls.c	2019-08-19 15:58:16.094166837 +0100
+++ gcc/calls.c	2019-08-19 15:58:21.714126173 +0100
@@ -2142,10 +2142,9 @@ initialize_argument_information (int num
       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, r
       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, r
 	}
 
       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
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	2019-07-16 09:11:06.105419196 +0100
+++ gcc/expr.c	2019-08-19 15:58:21.746125942 +0100
@@ -1709,11 +1709,12 @@ block_move_libcall_safe_for_call_parm (v
     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);
Index: gcc/function.c
===================================================================
--- gcc/function.c	2019-08-15 15:26:04.772237567 +0100
+++ gcc/function.c	2019-08-19 15:58:21.746125942 +0100
@@ -2559,10 +2559,9 @@ assign_parm_find_entry_rtl (struct assig
     {
       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
Index: gcc/config/alpha/alpha.c
===================================================================
--- gcc/config/alpha/alpha.c	2019-08-19 15:58:16.094166837 +0100
+++ gcc/config/alpha/alpha.c	2019-08-19 15:58:21.718126146 +0100
@@ -5635,20 +5635,17 @@ alpha_function_arg_advance (cumulative_a
 }
 
 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
Index: gcc/config/arc/arc.c
===================================================================
--- gcc/config/arc/arc.c	2019-08-13 22:35:11.721252311 +0100
+++ gcc/config/arc/arc.c	2019-08-19 15:58:21.718126146 +0100
@@ -6432,17 +6432,15 @@ #define ARC_NEXT_ARG_REG(REGNO) ( (REGNO
 /* 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 */
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c	2019-07-10 19:41:36.755815057 +0100
+++ gcc/config/arm/arm.c	2019-08-19 15:58:21.726126086 +0100
@@ -187,8 +187,8 @@ static int arm_memory_move_cost (machine
 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
 }
 
 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
       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);
Index: gcc/config/bfin/bfin.c
===================================================================
--- gcc/config/bfin/bfin.c	2019-08-13 22:35:11.729252254 +0100
+++ gcc/config/bfin/bfin.c	2019-08-19 15:58:21.726126086 +0100
@@ -1723,12 +1723,9 @@ bfin_function_arg (cumulative_args_t cum
    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)
Index: gcc/config/cris/cris.c
===================================================================
--- gcc/config/cris/cris.c	2019-05-29 10:49:36.676710232 +0100
+++ gcc/config/cris/cris.c	2019-08-19 15:58:21.726126086 +0100
@@ -141,8 +141,8 @@ static bool cris_rtx_costs (rtx, machine
 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 unsig
 }
 
 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;
Index: gcc/config/csky/csky.c
===================================================================
--- gcc/config/csky/csky.c	2019-05-29 10:49:36.968709386 +0100
+++ gcc/config/csky/csky.c	2019-08-19 15:58:21.726126086 +0100
@@ -1917,11 +1917,10 @@ csky_return_addr (int count, rtx frame A
    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)
Index: gcc/config/epiphany/epiphany.c
===================================================================
--- gcc/config/epiphany/epiphany.c	2019-05-29 10:49:36.648710313 +0100
+++ gcc/config/epiphany/epiphany.c	2019-08-19 15:58:21.730126059 +0100
@@ -744,18 +744,20 @@ epiphany_setup_incoming_varargs (cumulat
 }
 
 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;
Index: gcc/config/fr30/fr30.c
===================================================================
--- gcc/config/fr30/fr30.c	2019-03-08 18:15:37.772736275 +0000
+++ gcc/config/fr30/fr30.c	2019-08-19 15:58:21.730126059 +0100
@@ -39,6 +39,7 @@ #define IN_TARGET_CODE 1
 #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 @@ struct fr30_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, co
   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_
      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;
Index: gcc/config/frv/frv.c
===================================================================
--- gcc/config/frv/frv.c	2019-08-13 22:35:11.729252254 +0100
+++ gcc/config/frv/frv.c	2019-08-19 15:58:21.730126059 +0100
@@ -49,6 +49,7 @@ #define IN_TARGET_CODE 1
 #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		(FI
 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_arg
 }
 
 \f
-/* 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);
Index: gcc/config/ft32/ft32.c
===================================================================
--- gcc/config/ft32/ft32.c	2019-04-08 21:55:28.370369171 +0100
+++ gcc/config/ft32/ft32.c	2019-08-19 15:58:21.730126059 +0100
@@ -711,8 +711,7 @@ ft32_pass_by_reference (cumulative_args_
    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_
   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);
 
Index: gcc/config/gcn/gcn.c
===================================================================
--- gcc/config/gcn/gcn.c	2019-08-19 15:58:10.750205506 +0100
+++ gcc/config/gcn/gcn.c	2019-08-19 15:58:21.730126059 +0100
@@ -2349,22 +2349,21 @@ gcn_function_arg_advance (cumulative_arg
    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;
Index: gcc/config/ia64/ia64.c
===================================================================
--- gcc/config/ia64/ia64.c	2019-08-19 15:58:10.754205475 +0100
+++ gcc/config/ia64/ia64.c	2019-08-19 15:58:21.734126028 +0100
@@ -201,8 +201,8 @@ static bool ia64_can_eliminate (const in
 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_a
    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)
Index: gcc/config/iq2000/iq2000.c
===================================================================
--- gcc/config/iq2000/iq2000.c	2019-08-13 22:35:11.741252166 +0100
+++ gcc/config/iq2000/iq2000.c	2019-08-19 15:58:21.734126028 +0100
@@ -161,8 +161,8 @@ static section *iq2000_select_section (t
 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_mo
 }
 
 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);
Index: gcc/config/m32r/m32r.c
===================================================================
--- gcc/config/m32r/m32r.c	2019-07-01 09:37:06.080534032 +0100
+++ gcc/config/m32r/m32r.c	2019-08-19 15:58:21.734126028 +0100
@@ -93,8 +93,8 @@ static bool m32r_rtx_costs (rtx, machine
 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[])
 
 \f
 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;
Index: gcc/config/mcore/mcore.c
===================================================================
--- gcc/config/mcore/mcore.c	2019-03-08 18:15:38.512733464 +0000
+++ gcc/config/mcore/mcore.c	2019-08-19 15:58:21.734126028 +0100
@@ -129,8 +129,7 @@ static bool       mcore_rtx_costs		(rtx,
 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_mod
 }
 
 /* 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
     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.
Index: gcc/config/microblaze/microblaze.c
===================================================================
--- gcc/config/microblaze/microblaze.c	2019-07-01 09:37:06.516530382 +0100
+++ gcc/config/microblaze/microblaze.c	2019-08-19 15:58:21.734126028 +0100
@@ -1653,30 +1653,25 @@ microblaze_function_arg (cumulative_args
 
 /* 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;
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	2019-08-19 15:58:10.758205447 +0100
+++ gcc/config/mips/mips.c	2019-08-19 15:58:21.738126000 +0100
@@ -6140,12 +6140,12 @@ mips_function_arg_advance (cumulative_ar
 /* 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;
 }
 
Index: gcc/config/mn10300/mn10300.c
===================================================================
--- gcc/config/mn10300/mn10300.c	2019-05-29 10:49:36.680710222 +0100
+++ gcc/config/mn10300/mn10300.c	2019-08-19 15:58:21.738126000 +0100
@@ -1607,8 +1607,8 @@ mn10300_function_arg_advance (cumulative
    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_ar
   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_ar
 
   /* 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;
 
Index: gcc/config/moxie/moxie.c
===================================================================
--- gcc/config/moxie/moxie.c	2019-03-08 18:15:37.800736169 +0000
+++ gcc/config/moxie/moxie.c	2019-08-19 15:58:21.738126000 +0100
@@ -478,9 +478,7 @@ moxie_pass_by_reference (cumulative_args
    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
   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);
 
Index: gcc/config/msp430/msp430.c
===================================================================
--- gcc/config/msp430/msp430.c	2019-08-19 15:58:10.758205447 +0100
+++ gcc/config/msp430/msp430.c	2019-08-19 15:58:21.738126000 +0100
@@ -728,14 +728,11 @@ msp430_function_arg (cumulative_args_t c
 #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;
Index: gcc/config/nds32/nds32.c
===================================================================
--- gcc/config/nds32/nds32.c	2019-05-29 10:49:36.604710441 +0100
+++ gcc/config/nds32/nds32.c	2019-08-19 15:58:21.738126000 +0100
@@ -1963,8 +1963,7 @@ nds32_must_pass_in_stack (machine_mode m
 }
 
 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
 
   /* 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.  */
Index: gcc/config/nios2/nios2.c
===================================================================
--- gcc/config/nios2/nios2.c	2019-08-13 22:35:11.749252108 +0100
+++ gcc/config/nios2/nios2.c	2019-08-19 15:58:21.738126000 +0100
@@ -3390,20 +3390,11 @@ nios2_function_arg (cumulative_args_t cu
    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;
Index: gcc/config/pa/pa.c
===================================================================
--- gcc/config/pa/pa.c	2019-08-19 15:58:10.762205420 +0100
+++ gcc/config/pa/pa.c	2019-08-19 15:58:21.738126000 +0100
@@ -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 m
    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
   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)
Index: gcc/config/pru/pru.c
===================================================================
--- gcc/config/pru/pru.c	2019-08-13 22:35:11.749252108 +0100
+++ gcc/config/pru/pru.c	2019-08-19 15:58:21.738126000 +0100
@@ -2179,10 +2179,7 @@ pru_function_arg (cumulative_args_t cum_
    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;
 }
Index: gcc/config/riscv/riscv.c
===================================================================
--- gcc/config/riscv/riscv.c	2019-08-09 09:31:25.661331004 +0100
+++ gcc/config/riscv/riscv.c	2019-08-19 15:58:21.738126000 +0100
@@ -2778,11 +2778,12 @@ riscv_function_arg_advance (cumulative_a
 
 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;
 }
 
Index: gcc/config/rs6000/rs6000-internal.h
===================================================================
--- gcc/config/rs6000/rs6000-internal.h	2019-07-29 09:39:47.206185758 +0100
+++ gcc/config/rs6000/rs6000-internal.h	2019-08-19 15:58:21.742125973 +0100
@@ -159,9 +159,8 @@ extern void setup_incoming_varargs (cumu
 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);
Index: gcc/config/rs6000/rs6000-call.c
===================================================================
--- gcc/config/rs6000/rs6000-call.c	2019-08-19 15:58:10.762205420 +0100
+++ gcc/config/rs6000/rs6000-call.c	2019-08-19 15:58:21.742125973 +0100
@@ -2007,8 +2007,8 @@ rs6000_function_arg (cumulative_args_t c
    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_arg
   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_arg
     }
 
   /* 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_arg
          (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_arg
 
   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
     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.  */
Index: gcc/config/sh/sh.c
===================================================================
--- gcc/config/sh/sh.c	2019-08-19 15:58:16.098166809 +0100
+++ gcc/config/sh/sh.c	2019-08-19 15:58:21.742125973 +0100
@@ -298,8 +298,7 @@ static bool sh_pass_by_reference (cumula
 				  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&
 }
 
 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;
 }
Index: gcc/config/sparc/sparc.c
===================================================================
--- gcc/config/sparc/sparc.c	2019-08-19 15:58:10.766205389 +0100
+++ gcc/config/sparc/sparc.c	2019-08-19 15:58:21.742125973 +0100
@@ -668,7 +668,7 @@ static pad_direction sparc_function_arg_
 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_mod
    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
       /* 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
       /* 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)))
-	{
-	  const int size = (type && VECTOR_FLOAT_TYPE_P (type))
-			   ? int_size_in_bytes (type)
-			   : GET_MODE_SIZE (mode);
+      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 = (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;
Index: gcc/config/v850/v850.c
===================================================================
--- gcc/config/v850/v850.c	2019-03-08 18:15:39.112731182 +0000
+++ gcc/config/v850/v850.c	2019-08-19 15:58:21.742125973 +0100
@@ -196,27 +196,22 @@ v850_function_arg (cumulative_args_t cum
 /* 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_
   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;
 

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [04/13] Use function_arg_info for TARGET_PASS_BY_REFERENCE
  2019-08-19 15:15 [00/13] Pass an argument descriptor to target hooks Richard Sandiford
                   ` (2 preceding siblings ...)
  2019-08-19 15:18 ` [03/13] Use function_arg_info for TARGET_ARG_PARTIAL_BYTES Richard Sandiford
@ 2019-08-19 15:19 ` Richard Sandiford
  2019-08-19 20:43   ` Jeff Law
  2019-08-19 15:20 ` [05/13] Use function_arg_info for TARGET_SETUP_INCOMING_ARGS Richard Sandiford
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 27+ messages in thread
From: Richard Sandiford @ 2019-08-19 15:19 UTC (permalink / raw)
  To: gcc-patches

Use function_arg_info for TARGET_PASS_BY_REFERENCE.

The hook is passed the unpromoted type mode instead of the promoted mode.


2019-08-19  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	* target.def (pass_by_reference): Take a function_arg_info instead
	of a mode, type and named flag.
	* doc/tm.texi: Regenerate.
	* targhooks.h (hook_pass_by_reference_must_pass_in_stack): Update
	accordingly.
	(hook_bool_CUMULATIVE_ARGS_arg_info_false): Declare.
	* targhooks.c (hook_pass_by_reference_must_pass_in_stack): Take a
	function_arg_info instead of a mode, type and named flag.
	(hook_bool_CUMULATIVE_ARGS_arg_info_false): New function.
	* calls.h (pass_by_reference): Take a function_arg_info instead of a
	mode, type and named flag.
	* calls.c (pass_by_reference): Likewise.
	(pass_va_arg_by_reference): Update call accordingly.
	(initialize_argument_information): Likewise.
	(emit_library_call_value_1): Likewise.
	* function.c (assign_parm_find_data_types): Likewise.
	* var-tracking.c (prepare_call_arguments): Likewise.
	* stor-layout.c: Include calls.h.
	(compute_record_mode): Update call to targetm.calls.pass_by_reference.
	* config/aarch64/aarch64.c (aarch64_pass_by_reference): Take a
	function_arg_info instead of a mode, type and named flag.
	* config/alpha/alpha.c (alpha_pass_by_reference): Likewise.
	* config/arc/arc.c (arc_pass_by_reference): Likewise.
	* config/arm/arm.c (arm_pass_by_reference): Likewise.
	* config/bfin/bfin.c (bfin_pass_by_reference): Likewise.
	* config/c6x/c6x.c (c6x_pass_by_reference): Likewise.
	(c6x_call_saved_register_used): Update call to pass_by_reference.
	* config/cris/cris.c (cris_pass_by_reference): Take a
	function_arg_info instead of a mode, type and named flag.
	* config/epiphany/epiphany.c (epiphany_pass_by_reference): Take a
	function_arg_info instead of a mode, type and named flag.
	(epiphany_arg_partial_bytes): Update call accordingly.
	* config/ft32/ft32.c (ft32_pass_by_reference): Take a
	function_arg_info instead of a mode, type and named flag.
	(ft32_arg_partial_bytes): Update call accordingly.
	* config/i386/i386.c (ix86_pass_by_reference): Take a
	function_arg_info instead of a mode, type and named flag.
	* config/iq2000/iq2000.c (iq2000_pass_by_reference): Likewise.
	* config/m32c/m32c.c (m32c_pass_by_reference): Likewise.
	* config/m32r/m32r.c (m32r_pass_by_reference): Likewise.
	(m32r_return_in_memory): Update call accordingly.
	* config/mips/mips.c (mips_pass_by_reference): Take a
	function_arg_info instead of a mode, type and named flag.
	* config/mmix/mmix.c (mmix_pass_by_reference): Likewise.
	* config/mn10300/mn10300.c (mn10300_pass_by_reference): Likewise.
	* config/moxie/moxie.c (moxie_pass_by_reference): Likewise.
	(moxie_arg_partial_bytes): Update call accordingly.
	* config/msp430/msp430.c (msp430_pass_by_reference): Take a
	function_arg_info instead of a mode, type and named flag.
	* config/nvptx/nvptx.c (nvptx_pass_by_reference): Likewise.
	* config/or1k/or1k.c (or1k_pass_by_reference): Likewise.
	* config/pa/pa.c (pa_pass_by_reference): Likewise.
	* config/riscv/riscv.c (riscv_pass_by_reference): Likewise.
	(riscv_return_in_memory): Update call accordingly.
	* config/rs6000/rs6000-internal.h (rs6000_pass_by_reference): Take a
	function_arg_info instead of a mode, type and named flag.
	* config/rs6000/rs6000-call.c (rs6000_pass_by_reference): Likewise.
	(rs6000_parm_needs_stack): Update call to pass_by_reference.
	* config/s390/s390.c (s390_pass_by_reference): Take a
	function_arg_info instead of a mode, type and named flag.
	(s390_call_saved_register_used): Update call accordingly.
	* config/sh/sh.c (sh_pass_by_reference): Take a function_arg_info
	instead of a mode, type and named flag.
	* config/sparc/sparc.c (sparc_pass_by_reference): Likewise.
	* config/spu/spu.c (spu_pass_by_reference): Likewise.
	* config/tilegx/tilegx.c (tilegx_pass_by_reference): Likewise.
	* config/tilepro/tilepro.c (tilepro_pass_by_reference): Likewise.
	* config/v850/v850.c (v850_pass_by_reference): Likewise.
	* config/visium/visium.c (visium_pass_by_reference): Likewise.

gcc/ada/
	* gcc-interface/misc.c (default_pass_by_ref): Update call to
	pass_by_reference.

Index: gcc/target.def
===================================================================
--- gcc/target.def	2019-08-19 15:58:21.746125942 +0100
+++ gcc/target.def	2019-08-19 15:58:28.450077433 +0100
@@ -4450,18 +4450,18 @@ or 3-byte structure is returned at the m
    from __builtin_va_arg.  */
 DEFHOOK
 (pass_by_reference,
- "This target hook should return @code{true} if an argument at the\n\
+ "This target hook should return @code{true} if argument @var{arg} at the\n\
 position indicated by @var{cum} should be passed by reference.  This\n\
 predicate is queried after target independent reasons for being\n\
-passed by reference, such as @code{TREE_ADDRESSABLE (type)}.\n\
+passed by reference, such as @code{TREE_ADDRESSABLE (@var{arg}.type)}.\n\
 \n\
 If the hook returns true, a copy of that argument is made in memory and a\n\
 pointer to the argument is passed instead of the argument itself.\n\
 The pointer is passed in whatever way is appropriate for passing a pointer\n\
 to that type.",
  bool,
- (cumulative_args_t cum, machine_mode mode, const_tree type, bool named),
- hook_bool_CUMULATIVE_ARGS_mode_tree_bool_false)
+ (cumulative_args_t cum, const function_arg_info &arg),
+ hook_bool_CUMULATIVE_ARGS_arg_info_false)
 
 DEFHOOK
 (expand_builtin_saveregs,
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	2019-08-19 15:58:21.746125942 +0100
+++ gcc/doc/tm.texi	2019-08-19 15:58:28.450077433 +0100
@@ -4076,11 +4076,11 @@ register to be used by the caller for th
 @code{TARGET_FUNCTION_INCOMING_ARG}, for the called function.
 @end deftypefn
 
-@deftypefn {Target Hook} bool TARGET_PASS_BY_REFERENCE (cumulative_args_t @var{cum}, machine_mode @var{mode}, const_tree @var{type}, bool @var{named})
-This target hook should return @code{true} if an argument at the
+@deftypefn {Target Hook} bool TARGET_PASS_BY_REFERENCE (cumulative_args_t @var{cum}, const function_arg_info @var{&arg})
+This target hook should return @code{true} if argument @var{arg} at the
 position indicated by @var{cum} should be passed by reference.  This
 predicate is queried after target independent reasons for being
-passed by reference, such as @code{TREE_ADDRESSABLE (type)}.
+passed by reference, such as @code{TREE_ADDRESSABLE (@var{arg}.type)}.
 
 If the hook returns true, a copy of that argument is made in memory and a
 pointer to the argument is passed instead of the argument itself.
Index: gcc/targhooks.h
===================================================================
--- gcc/targhooks.h	2019-08-19 15:58:21.746125942 +0100
+++ gcc/targhooks.h	2019-08-19 15:58:28.450077433 +0100
@@ -63,7 +63,7 @@ extern tree default_cxx_guard_type (void
 extern tree default_cxx_get_cookie_size (tree);
 
 extern bool hook_pass_by_reference_must_pass_in_stack
-  (cumulative_args_t, machine_mode mode, const_tree, bool);
+  (cumulative_args_t, const function_arg_info &);
 extern bool hook_callee_copies_named
   (cumulative_args_t ca, machine_mode, const_tree, bool);
 
@@ -137,6 +137,8 @@ extern bool hook_bool_CUMULATIVE_ARGS_tr
   (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 bool hook_bool_CUMULATIVE_ARGS_arg_info_false
+  (cumulative_args_t, const function_arg_info &);
 extern int hook_int_CUMULATIVE_ARGS_arg_info_0
   (cumulative_args_t, const function_arg_info &);
 extern void hook_void_CUMULATIVE_ARGS_tree
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c	2019-08-19 15:58:21.746125942 +0100
+++ gcc/targhooks.c	2019-08-19 15:58:28.450077433 +0100
@@ -323,11 +323,10 @@ default_cxx_get_cookie_size (tree type)
    of the TARGET_PASS_BY_REFERENCE hook uses just MUST_PASS_IN_STACK.  */
 
 bool
-hook_pass_by_reference_must_pass_in_stack (cumulative_args_t c ATTRIBUTE_UNUSED,
-	machine_mode mode ATTRIBUTE_UNUSED, const_tree type ATTRIBUTE_UNUSED,
-	bool named_arg ATTRIBUTE_UNUSED)
+hook_pass_by_reference_must_pass_in_stack (cumulative_args_t,
+					   const function_arg_info &arg)
 {
-  return targetm.calls.must_pass_in_stack (mode, type);
+  return targetm.calls.must_pass_in_stack (arg.mode, arg.type);
 }
 
 /* Return true if a parameter follows callee copies conventions.  This
@@ -767,6 +766,13 @@ hook_bool_CUMULATIVE_ARGS_mode_tree_bool
   return true;
 }
 
+bool
+hook_bool_CUMULATIVE_ARGS_arg_info_false (cumulative_args_t,
+					  const function_arg_info &)
+{
+  return false;
+}
+
 int
 hook_int_CUMULATIVE_ARGS_arg_info_0 (cumulative_args_t,
 				     const function_arg_info &)
Index: gcc/calls.h
===================================================================
--- gcc/calls.h	2019-08-19 15:58:21.714126173 +0100
+++ gcc/calls.h	2019-08-19 15:58:28.418077667 +0100
@@ -105,8 +105,7 @@ extern bool shift_return_value (machine_
 extern rtx expand_call (tree, rtx, int);
 extern void fixup_tail_calls (void);
 
-extern bool pass_by_reference (CUMULATIVE_ARGS *, machine_mode,
-			       tree, bool);
+extern bool pass_by_reference (CUMULATIVE_ARGS *, function_arg_info);
 extern bool pass_va_arg_by_reference (tree);
 extern bool reference_callee_copied (CUMULATIVE_ARGS *, machine_mode,
 				     tree, bool);
Index: gcc/calls.c
===================================================================
--- gcc/calls.c	2019-08-19 15:58:21.714126173 +0100
+++ gcc/calls.c	2019-08-19 15:58:28.418077667 +0100
@@ -897,13 +897,12 @@ call_expr_flags (const_tree t)
   return flags;
 }
 
-/* Return true if TYPE should be passed by invisible reference.  */
+/* Return true if ARG should be passed by invisible reference.  */
 
 bool
-pass_by_reference (CUMULATIVE_ARGS *ca, machine_mode mode,
-		   tree type, bool named_arg)
+pass_by_reference (CUMULATIVE_ARGS *ca, function_arg_info arg)
 {
-  if (type)
+  if (tree type = arg.type)
     {
       /* If this type contains non-trivial constructors, then it is
 	 forbidden for the middle-end to create any new copies.  */
@@ -918,13 +917,12 @@ pass_by_reference (CUMULATIVE_ARGS *ca,
 	 member, use the type and mode of that member.  */
       if (TREE_CODE (type) == RECORD_TYPE && TYPE_TRANSPARENT_AGGR (type))
 	{
-	  type = TREE_TYPE (first_field (type));
-	  mode = TYPE_MODE (type);
+	  arg.type = TREE_TYPE (first_field (type));
+	  arg.mode = TYPE_MODE (arg.type);
 	}
     }
 
-  return targetm.calls.pass_by_reference (pack_cumulative_args (ca), mode,
-					  type, named_arg);
+  return targetm.calls.pass_by_reference (pack_cumulative_args (ca), arg);
 }
 
 /* Return true if TYPE should be passed by reference when passed to
@@ -933,7 +931,7 @@ pass_by_reference (CUMULATIVE_ARGS *ca,
 bool
 pass_va_arg_by_reference (tree type)
 {
-  return pass_by_reference (NULL, TYPE_MODE (type), type, false);
+  return pass_by_reference (NULL, function_arg_info (type, /*named=*/false));
 }
 
 /* Return true if TYPE, which is passed by reference, should be callee
@@ -1997,8 +1995,8 @@ initialize_argument_information (int num
 	 with those made by function.c.  */
 
       /* See if this argument should be passed by invisible reference.  */
-      if (pass_by_reference (args_so_far_pnt, TYPE_MODE (type),
-			     type, argpos < n_named_args))
+      function_arg_info orig_arg (type, argpos < n_named_args);
+      if (pass_by_reference (args_so_far_pnt, orig_arg))
 	{
 	  bool callee_copies;
 	  tree base = NULL_TREE;
@@ -4909,7 +4907,8 @@ emit_library_call_value_1 (int retval, r
 	  && !(CONSTANT_P (val) && targetm.legitimate_constant_p (mode, val)))
 	val = force_operand (val, NULL_RTX);
 
-      if (pass_by_reference (&args_so_far_v, mode, NULL_TREE, 1))
+      function_arg_info orig_arg (mode, /*named=*/true);
+      if (pass_by_reference (&args_so_far_v, orig_arg))
 	{
 	  rtx slot;
 	  int must_copy
Index: gcc/function.c
===================================================================
--- gcc/function.c	2019-08-19 15:58:21.746125942 +0100
+++ gcc/function.c	2019-08-19 15:58:28.450077433 +0100
@@ -2454,13 +2454,15 @@ assign_parm_find_data_types (struct assi
     passed_type = TREE_TYPE (first_field (passed_type));
 
   /* See if this arg was passed by invisible reference.  */
-  if (pass_by_reference (&all->args_so_far_v, passed_mode,
-			 passed_type, data->named_arg))
-    {
-      passed_type = nominal_type = build_pointer_type (passed_type);
-      data->passed_pointer = true;
-      passed_mode = nominal_mode = TYPE_MODE (nominal_type);
-    }
+  {
+    function_arg_info arg (passed_type, passed_mode, data->named_arg);
+    if (pass_by_reference (&all->args_so_far_v, arg))
+      {
+	passed_type = nominal_type = build_pointer_type (passed_type);
+	data->passed_pointer = true;
+	passed_mode = nominal_mode = TYPE_MODE (nominal_type);
+      }
+  }
 
   /* Find mode as it is passed by the ABI.  */
   unsignedp = TYPE_UNSIGNED (passed_type);
Index: gcc/var-tracking.c
===================================================================
--- gcc/var-tracking.c	2019-07-10 19:41:27.167891845 +0100
+++ gcc/var-tracking.c	2019-08-19 15:58:28.450077433 +0100
@@ -6431,13 +6431,11 @@ prepare_call_arguments (basic_block bb,
 	if (t && t != void_list_node)
 	  {
 	    tree argtype = TREE_VALUE (t);
-	    machine_mode mode = TYPE_MODE (argtype);
 	    rtx reg;
-	    if (pass_by_reference (&args_so_far_v, mode, argtype, true))
-	      {
-		argtype = build_pointer_type (argtype);
-		mode = TYPE_MODE (argtype);
-	      }
+	    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);
 	    reg = targetm.calls.function_arg (args_so_far, mode,
 					      argtype, true);
 	    if (TREE_CODE (argtype) == REFERENCE_TYPE
Index: gcc/stor-layout.c
===================================================================
--- gcc/stor-layout.c	2019-07-01 09:37:05.772536611 +0100
+++ gcc/stor-layout.c	2019-08-19 15:58:28.450077433 +0100
@@ -42,6 +42,7 @@ Software Foundation; either version 3, o
 #include "gimplify.h"
 #include "attribs.h"
 #include "debug.h"
+#include "calls.h"
 
 /* Data type for the expressions representing sizes of data types.
    It is the first integer type laid out.  */
@@ -1859,8 +1860,9 @@ compute_record_mode (tree type)
        || (TREE_CODE (type) == UNION_TYPE
 	   && (GET_MODE_CLASS (mode) == MODE_INT
 	       || (GET_MODE_CLASS (mode) == MODE_PARTIAL_INT
-		   && targetm.calls.pass_by_reference (pack_cumulative_args (0),
-						       mode, type, 0)))))
+		   && (targetm.calls.pass_by_reference
+		       (pack_cumulative_args (0),
+			function_arg_info (type, mode, /*named=*/false)))))))
       && mode != VOIDmode
       && poly_int_tree_p (TYPE_SIZE (type), &type_size)
       && known_eq (GET_MODE_BITSIZE (mode), type_size))
Index: gcc/config/aarch64/aarch64.c
===================================================================
--- gcc/config/aarch64/aarch64.c	2019-08-19 15:58:10.746205533 +0100
+++ gcc/config/aarch64/aarch64.c	2019-08-19 15:58:28.422077636 +0100
@@ -4409,35 +4409,30 @@ aarch64_function_ok_for_sibcall (tree de
 /* Implement TARGET_PASS_BY_REFERENCE.  */
 
 static bool
-aarch64_pass_by_reference (cumulative_args_t pcum ATTRIBUTE_UNUSED,
-			   machine_mode mode,
-			   const_tree type,
-			   bool named ATTRIBUTE_UNUSED)
+aarch64_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
 {
   HOST_WIDE_INT size;
   machine_mode dummymode;
   int nregs;
 
   /* GET_MODE_SIZE (BLKmode) is useless since it is 0.  */
-  if (mode == BLKmode && type)
-    size = int_size_in_bytes (type);
+  if (arg.mode == BLKmode && arg.type)
+    size = int_size_in_bytes (arg.type);
   else
     /* No frontends can create types with variable-sized modes, so we
        shouldn't be asked to pass or return them.  */
-    size = GET_MODE_SIZE (mode).to_constant ();
+    size = GET_MODE_SIZE (arg.mode).to_constant ();
 
   /* Aggregates are passed by reference based on their size.  */
-  if (type && AGGREGATE_TYPE_P (type))
-    {
-      size = int_size_in_bytes (type);
-    }
+  if (arg.aggregate_type_p ())
+    size = int_size_in_bytes (arg.type);
 
   /* Variable sized arguments are always returned by reference.  */
   if (size < 0)
     return true;
 
   /* Can this be a candidate to be passed in fp/simd register(s)?  */
-  if (aarch64_vfp_is_call_or_return_candidate (mode, type,
+  if (aarch64_vfp_is_call_or_return_candidate (arg.mode, arg.type,
 					       &dummymode, &nregs,
 					       NULL))
     return false;
Index: gcc/config/alpha/alpha.c
===================================================================
--- gcc/config/alpha/alpha.c	2019-08-19 15:58:21.718126146 +0100
+++ gcc/config/alpha/alpha.c	2019-08-19 15:58:28.422077636 +0100
@@ -5710,13 +5710,10 @@ alpha_return_in_memory (const_tree type,
   return size > UNITS_PER_WORD;
 }
 
-/* Return true if TYPE should be passed by invisible reference.  */
+/* Return true if ARG should be passed by invisible reference.  */
 
 static bool
-alpha_pass_by_reference (cumulative_args_t ca ATTRIBUTE_UNUSED,
-			 machine_mode mode,
-			 const_tree type ATTRIBUTE_UNUSED,
-			 bool named)
+alpha_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
 {
   /* Pass float and _Complex float variable arguments by reference.
      This avoids 64-bit store from a FP register to a pretend args save area
@@ -5736,10 +5733,10 @@ alpha_pass_by_reference (cumulative_args
      to worry about, and passing unpromoted _Float32 and _Complex float
      as a variable argument will actually work in the future.  */
 
-  if (mode == SFmode || mode == SCmode)
-    return !named;
+  if (arg.mode == SFmode || arg.mode == SCmode)
+    return !arg.named;
 
-  return mode == TFmode || mode == TCmode;
+  return arg.mode == TFmode || arg.mode == TCmode;
 }
 
 /* Define how to find the value returned by a function.  VALTYPE is the
Index: gcc/config/arc/arc.c
===================================================================
--- gcc/config/arc/arc.c	2019-08-19 15:58:21.718126146 +0100
+++ gcc/config/arc/arc.c	2019-08-19 15:58:28.426077609 +0100
@@ -7566,14 +7566,11 @@ arc_return_in_memory (const_tree type, c
 }
 
 static bool
-arc_pass_by_reference (cumulative_args_t ca_v ATTRIBUTE_UNUSED,
-		       machine_mode mode ATTRIBUTE_UNUSED,
-		       const_tree type,
-		       bool named ATTRIBUTE_UNUSED)
+arc_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
 {
-  return (type != 0
-	  && (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
-	      || TREE_ADDRESSABLE (type)));
+  return (arg.type != 0
+	  && (TREE_CODE (TYPE_SIZE (arg.type)) != INTEGER_CST
+	      || TREE_ADDRESSABLE (arg.type)));
 }
 
 /* Implement TARGET_CAN_USE_DOLOOP_P.  */
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c	2019-08-19 15:58:21.726126086 +0100
+++ gcc/config/arm/arm.c	2019-08-19 15:58:28.430077578 +0100
@@ -215,7 +215,7 @@ static void arm_insert_attributes (tree,
 static void arm_setup_incoming_varargs (cumulative_args_t, machine_mode,
 					tree, int *, int);
 static bool arm_pass_by_reference (cumulative_args_t,
-				   machine_mode, const_tree, bool);
+				   const function_arg_info &);
 static bool arm_promote_prototypes (const_tree);
 static bool arm_default_short_enums (void);
 static bool arm_align_anon_bitfield (void);
@@ -6819,11 +6819,9 @@ arm_function_arg_advance (cumulative_arg
    extension to the ARM ABI.  */
 
 static bool
-arm_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
-		       machine_mode mode ATTRIBUTE_UNUSED,
-		       const_tree type, bool named ATTRIBUTE_UNUSED)
+arm_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
 {
-  return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
+  return arg.type && TREE_CODE (TYPE_SIZE (arg.type)) != INTEGER_CST;
 }
 \f
 /* Encode the current state of the #pragma [no_]long_calls.  */
Index: gcc/config/bfin/bfin.c
===================================================================
--- gcc/config/bfin/bfin.c	2019-08-19 15:58:21.726126086 +0100
+++ gcc/config/bfin/bfin.c	2019-08-19 15:58:28.430077578 +0100
@@ -1741,11 +1741,9 @@ bfin_arg_partial_bytes (cumulative_args_
 /* Variable sized types are passed by reference.  */
 
 static bool
-bfin_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
-			machine_mode mode ATTRIBUTE_UNUSED,
-			const_tree type, bool named ATTRIBUTE_UNUSED)
+bfin_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
 {
-  return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
+  return arg.type && TREE_CODE (TYPE_SIZE (arg.type)) != INTEGER_CST;
 }
 
 /* Decide whether a type should be returned in memory (true)
Index: gcc/config/c6x/c6x.c
===================================================================
--- gcc/config/c6x/c6x.c	2019-08-13 22:35:11.729252254 +0100
+++ gcc/config/c6x/c6x.c	2019-08-19 15:58:28.430077578 +0100
@@ -642,15 +642,13 @@ c6x_function_value_regno_p (const unsign
    reference.  The callee must copy them; see c6x_callee_copies.  */
 
 static bool
-c6x_pass_by_reference (cumulative_args_t cum_v ATTRIBUTE_UNUSED,
-		       machine_mode mode, const_tree type,
-		       bool named ATTRIBUTE_UNUSED)
+c6x_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
 {
   int size = -1;
-  if (type)
-    size = int_size_in_bytes (type);
-  else if (mode != VOIDmode)
-    size = GET_MODE_SIZE (mode);
+  if (arg.type)
+    size = int_size_in_bytes (arg.type);
+  else if (arg.mode != VOIDmode)
+    size = GET_MODE_SIZE (arg.mode);
   return size > 2 * UNITS_PER_WORD || size == -1;
 }
 
@@ -1130,7 +1128,7 @@ c6x_call_saved_register_used (tree call_
       mode = TYPE_MODE (type);
       gcc_assert (mode);
 
-      if (pass_by_reference (&cum_v, mode, type, true))
+      if (pass_by_reference (&cum_v, function_arg_info (type, /*named=*/true)))
  	{
  	  mode = Pmode;
  	  type = build_pointer_type (type);
Index: gcc/config/cris/cris.c
===================================================================
--- gcc/config/cris/cris.c	2019-08-19 15:58:21.726126086 +0100
+++ gcc/config/cris/cris.c	2019-08-19 15:58:28.430077578 +0100
@@ -139,8 +139,8 @@ static int cris_register_move_cost (mach
 static int cris_memory_move_cost (machine_mode, reg_class_t, bool);
 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 bool cris_pass_by_reference (cumulative_args_t,
+				    const function_arg_info &);
 static int cris_arg_partial_bytes (cumulative_args_t,
 				   const function_arg_info &);
 static rtx cris_function_arg (cumulative_args_t, machine_mode,
@@ -4041,16 +4041,14 @@ cris_setup_incoming_varargs (cumulative_
 	     ca->regs, *pretend_arg_size, second_time);
 }
 
-/* Return true if TYPE must be passed by invisible reference.
+/* Return true if ARG must be passed by invisible reference.
    For cris, we pass <= 8 bytes by value, others by reference.  */
 
 static bool
-cris_pass_by_reference (cumulative_args_t ca ATTRIBUTE_UNUSED,
-			machine_mode mode, const_tree type,
-			bool named ATTRIBUTE_UNUSED)
+cris_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
 {
-  return (targetm.calls.must_pass_in_stack (mode, type)
-	  || CRIS_FUNCTION_ARG_SIZE (mode, type) > 8);
+  return (targetm.calls.must_pass_in_stack (arg.mode, arg.type)
+	  || CRIS_FUNCTION_ARG_SIZE (arg.mode, arg.type) > 8);
 }
 
 /* A combination of defining TARGET_PROMOTE_FUNCTION_MODE, promoting arguments
Index: gcc/config/epiphany/epiphany.c
===================================================================
--- gcc/config/epiphany/epiphany.c	2019-08-19 15:58:21.730126059 +0100
+++ gcc/config/epiphany/epiphany.c	2019-08-19 15:58:28.434077550 +0100
@@ -71,8 +71,8 @@ static int get_epiphany_condition_code (
 static tree epiphany_handle_interrupt_attribute (tree *, tree, tree, int, bool *);
 static tree epiphany_handle_forwarder_attribute (tree *, tree, tree, int,
 						 bool *);
-static bool epiphany_pass_by_reference (cumulative_args_t, machine_mode,
-					const_tree, bool);
+static bool epiphany_pass_by_reference (cumulative_args_t,
+					const function_arg_info &);
 static rtx_insn *frame_insn (rtx);
 \f
 /* defines for the initialization of the GCC target structure.  */
@@ -749,8 +749,7 @@ epiphany_arg_partial_bytes (cumulative_a
 {
   int words = 0, rounded_cum;
 
-  gcc_assert (!epiphany_pass_by_reference (cum, arg.mode, arg.type,
-					   arg.named));
+  gcc_assert (!epiphany_pass_by_reference (cum, arg));
 
   rounded_cum = ROUND_ADVANCE_CUM (*get_cumulative_args (cum),
 				   arg.mode, arg.type);
@@ -1487,14 +1486,12 @@ epiphany_return_in_memory (const_tree ty
    passed by reference.  */
 
 static bool
-epiphany_pass_by_reference (cumulative_args_t ca ATTRIBUTE_UNUSED,
-		       machine_mode mode, const_tree type,
-		       bool named ATTRIBUTE_UNUSED)
+epiphany_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
 {
-  if (type)
+  if (tree type = arg.type)
     {
       if (AGGREGATE_TYPE_P (type)
-	  && (mode == BLKmode || TYPE_NEEDS_CONSTRUCTING (type)))
+	  && (arg.mode == BLKmode || TYPE_NEEDS_CONSTRUCTING (type)))
 	return true;
     }
   return false;
Index: gcc/config/ft32/ft32.c
===================================================================
--- gcc/config/ft32/ft32.c	2019-08-19 15:58:21.730126059 +0100
+++ gcc/config/ft32/ft32.c	2019-08-19 15:58:28.434077550 +0100
@@ -684,25 +684,15 @@ ft32_function_arg_advance (cumulative_ar
           ? *cum + ((3 + FT32_FUNCTION_ARG_SIZE (mode, type)) / 4) : *cum);
 }
 
-/* Return non-zero if the function argument described by TYPE is to be
+/* Return non-zero if the function argument described by ARG is to be
    passed by reference.  */
 
 static bool
-ft32_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
-                        machine_mode mode, const_tree type,
-                        bool named ATTRIBUTE_UNUSED)
+ft32_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
 {
-  unsigned HOST_WIDE_INT size;
-
-  if (type)
-    {
-      if (AGGREGATE_TYPE_P (type))
-        return true;
-      size = int_size_in_bytes (type);
-    }
-  else
-    size = GET_MODE_SIZE (mode);
-
+  if (arg.aggregate_type_p ())
+    return true;
+  unsigned HOST_WIDE_INT size = arg.type_size_in_bytes ();
   return size > 4 * 6;
 }
 
@@ -719,7 +709,7 @@ ft32_arg_partial_bytes (cumulative_args_
   if (*cum >= 8)
     return 0;
 
-  if (ft32_pass_by_reference (cum_v, arg.mode, arg.type, arg.named))
+  if (ft32_pass_by_reference (cum_v, arg))
     size = 4;
   else if (arg.type)
     {
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	2019-08-19 15:58:10.754205475 +0100
+++ gcc/config/i386/i386.c	2019-08-19 15:58:28.434077550 +0100
@@ -3286,8 +3286,7 @@ ix86_function_arg (cumulative_args_t cum
    appropriate for passing a pointer to that type.  */
 
 static bool
-ix86_pass_by_reference (cumulative_args_t cum_v, machine_mode mode,
-			const_tree type, bool)
+ix86_pass_by_reference (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
@@ -3298,9 +3297,9 @@ ix86_pass_by_reference (cumulative_args_
       /* See Windows x64 Software Convention.  */
       if (call_abi == MS_ABI)
 	{
-	  HOST_WIDE_INT msize = GET_MODE_SIZE (mode);
+	  HOST_WIDE_INT msize = GET_MODE_SIZE (arg.mode);
 
-	  if (type)
+	  if (tree type = arg.type)
 	    {
 	      /* Arrays are passed by reference.  */
 	      if (TREE_CODE (type) == ARRAY_TYPE)
@@ -3317,7 +3316,7 @@ ix86_pass_by_reference (cumulative_args_
 	  /* __m128 is passed by reference.  */
 	  return msize != 1 && msize != 2 && msize != 4 && msize != 8;
 	}
-      else if (type && int_size_in_bytes (type) == -1)
+      else if (arg.type && int_size_in_bytes (arg.type) == -1)
 	return true;
     }
 
Index: gcc/config/iq2000/iq2000.c
===================================================================
--- gcc/config/iq2000/iq2000.c	2019-08-19 15:58:21.734126028 +0100
+++ gcc/config/iq2000/iq2000.c	2019-08-19 15:58:28.434077550 +0100
@@ -159,8 +159,8 @@ static int  iq2000_address_cost       (r
 				       bool);
 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 bool iq2000_pass_by_reference  (cumulative_args_t,
+				       const function_arg_info &);
 static int  iq2000_arg_partial_bytes  (cumulative_args_t,
 				       const function_arg_info &arg);
 static rtx iq2000_function_arg	      (cumulative_args_t,
@@ -2292,8 +2292,8 @@ iq2000_function_value_regno_p (const uns
 /* Return true when an argument must be passed by reference.  */
 
 static bool
-iq2000_pass_by_reference (cumulative_args_t cum_v, machine_mode mode,
-			  const_tree type, bool named ATTRIBUTE_UNUSED)
+iq2000_pass_by_reference (cumulative_args_t cum_v,
+			  const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   int size;
@@ -2301,7 +2301,7 @@ iq2000_pass_by_reference (cumulative_arg
   /* We must pass by reference if we would be both passing in registers
      and the stack.  This is because any subsequent partial arg would be
      handled incorrectly in this case.  */
-  if (cum && targetm.calls.must_pass_in_stack (mode, type))
+  if (cum && targetm.calls.must_pass_in_stack (arg.mode, arg.type))
      {
        /* Don't pass the actual CUM to FUNCTION_ARG, because we would
 	  get double copies of any offsets generated for small structs
@@ -2309,15 +2309,15 @@ iq2000_pass_by_reference (cumulative_arg
        CUMULATIVE_ARGS temp;
 
        temp = *cum;
-       if (iq2000_function_arg (pack_cumulative_args (&temp), mode, type, named)
-	   != 0)
+       if (iq2000_function_arg (pack_cumulative_args (&temp), arg.mode,
+				arg.type, arg.named) != 0)
 	 return 1;
      }
 
-  if (type == NULL_TREE || mode == DImode || mode == DFmode)
+  if (arg.type == NULL_TREE || arg.mode == DImode || arg.mode == DFmode)
     return 0;
 
-  size = int_size_in_bytes (type);
+  size = int_size_in_bytes (arg.type);
   return size == -1 || size > UNITS_PER_WORD;
 }
 
Index: gcc/config/m32c/m32c.c
===================================================================
--- gcc/config/m32c/m32c.c	2019-07-01 09:37:06.044534332 +0100
+++ gcc/config/m32c/m32c.c	2019-08-19 15:58:28.434077550 +0100
@@ -78,8 +78,8 @@ static bool m32c_legitimate_address_p (m
 static bool m32c_addr_space_legitimate_address_p (machine_mode, rtx, bool, addr_space_t);
 static rtx m32c_function_arg (cumulative_args_t, machine_mode,
 			      const_tree, bool);
-static bool m32c_pass_by_reference (cumulative_args_t, machine_mode,
-				    const_tree, bool);
+static bool m32c_pass_by_reference (cumulative_args_t,
+				    const function_arg_info &);
 static void m32c_function_arg_advance (cumulative_args_t, machine_mode,
 				       const_tree, bool);
 static unsigned int m32c_function_arg_boundary (machine_mode, const_tree);
@@ -1373,10 +1373,7 @@ m32c_function_arg (cumulative_args_t ca_
 #undef TARGET_PASS_BY_REFERENCE
 #define TARGET_PASS_BY_REFERENCE m32c_pass_by_reference
 static bool
-m32c_pass_by_reference (cumulative_args_t ca ATTRIBUTE_UNUSED,
-			machine_mode mode ATTRIBUTE_UNUSED,
-			const_tree type ATTRIBUTE_UNUSED,
-			bool named ATTRIBUTE_UNUSED)
+m32c_pass_by_reference (cumulative_args_t, const function_arg_info &)
 {
   return 0;
 }
Index: gcc/config/m32r/m32r.c
===================================================================
--- gcc/config/m32r/m32r.c	2019-08-19 15:58:21.734126028 +0100
+++ gcc/config/m32r/m32r.c	2019-08-19 15:58:28.434077550 +0100
@@ -91,8 +91,8 @@ static void m32r_setup_incoming_varargs
 static void init_idents (void);
 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 bool m32r_pass_by_reference (cumulative_args_t,
+				    const function_arg_info &arg);
 static int m32r_arg_partial_bytes (cumulative_args_t,
 				   const function_arg_info &);
 static rtx m32r_function_arg (cumulative_args_t, machine_mode,
@@ -680,20 +680,12 @@ memreg_operand (rtx op, machine_mode mod
   return MEM_P (op) && REG_P (XEXP (op, 0));
 }
 
-/* Return nonzero if TYPE must be passed by indirect reference.  */
+/* Return nonzero if ARG must be passed by indirect reference.  */
 
 static bool
-m32r_pass_by_reference (cumulative_args_t ca ATTRIBUTE_UNUSED,
-			machine_mode mode, const_tree type,
-			bool named ATTRIBUTE_UNUSED)
+m32r_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
 {
-  int size;
-
-  if (type)
-    size = int_size_in_bytes (type);
-  else
-    size = GET_MODE_SIZE (mode);
-
+  int size = arg.type_size_in_bytes ();
   return (size < 0 || size > 8);
 }
 \f
@@ -1251,8 +1243,8 @@ m32r_function_arg_advance (cumulative_ar
 m32r_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
 {
   cumulative_args_t dummy = pack_cumulative_args (NULL);
-
-  return m32r_pass_by_reference (dummy, TYPE_MODE (type), type, false);
+  function_arg_info arg (const_cast<tree> (type), /*named=*/false);
+  return m32r_pass_by_reference (dummy, arg);
 }
 
 /* Worker function for TARGET_FUNCTION_VALUE.  */
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	2019-08-19 15:58:21.738126000 +0100
+++ gcc/config/mips/mips.c	2019-08-19 15:58:28.438077523 +0100
@@ -6235,27 +6235,25 @@ mips_pad_reg_upward (machine_mode mode,
 /* Return nonzero when an argument must be passed by reference.  */
 
 static bool
-mips_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
-			machine_mode mode, const_tree type,
-			bool named ATTRIBUTE_UNUSED)
+mips_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
 {
   if (mips_abi == ABI_EABI)
     {
       int size;
 
       /* ??? How should SCmode be handled?  */
-      if (mode == DImode || mode == DFmode
-	  || mode == DQmode || mode == UDQmode
-	  || mode == DAmode || mode == UDAmode)
+      if (arg.mode == DImode || arg.mode == DFmode
+	  || arg.mode == DQmode || arg.mode == UDQmode
+	  || arg.mode == DAmode || arg.mode == UDAmode)
 	return 0;
 
-      size = type ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
+      size = arg.type_size_in_bytes ();
       return size == -1 || size > UNITS_PER_WORD;
     }
   else
     {
       /* If we have a variable-sized parameter, we have no choice.  */
-      return targetm.calls.must_pass_in_stack (mode, type);
+      return targetm.calls.must_pass_in_stack (arg.mode, arg.type);
     }
 }
 
Index: gcc/config/mmix/mmix.c
===================================================================
--- gcc/config/mmix/mmix.c	2019-05-29 10:49:36.972709373 +0100
+++ gcc/config/mmix/mmix.c	2019-08-19 15:58:28.438077523 +0100
@@ -161,7 +161,7 @@ static rtx mmix_function_value (const_tr
 static rtx mmix_libcall_value (machine_mode, const_rtx);
 static bool mmix_function_value_regno_p (const unsigned int);
 static bool mmix_pass_by_reference (cumulative_args_t,
-				    machine_mode, const_tree, bool);
+				    const function_arg_info &);
 static bool mmix_frame_pointer_required (void);
 static void mmix_asm_trampoline_template (FILE *);
 static void mmix_trampoline_init (rtx, tree, rtx);
@@ -690,17 +690,17 @@ mmix_function_incoming_arg (cumulative_a
    everything that goes by value.  */
 
 static bool
-mmix_pass_by_reference (cumulative_args_t argsp_v, machine_mode mode,
-			const_tree type, bool named ATTRIBUTE_UNUSED)
+mmix_pass_by_reference (cumulative_args_t argsp_v,
+			const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *argsp = get_cumulative_args (argsp_v);
 
   /* FIXME: Check: I'm not sure the must_pass_in_stack check is
      necessary.  */
-  if (targetm.calls.must_pass_in_stack (mode, type))
+  if (targetm.calls.must_pass_in_stack (arg.mode, arg.type))
     return true;
 
-  if (MMIX_FUNCTION_ARG_SIZE (mode, type) > 8
+  if (MMIX_FUNCTION_ARG_SIZE (arg.mode, arg.type) > 8
       && !TARGET_LIBFUNC
       && (!argsp || !argsp->lib))
     return true;
Index: gcc/config/mn10300/mn10300.c
===================================================================
--- gcc/config/mn10300/mn10300.c	2019-08-19 15:58:21.738126000 +0100
+++ gcc/config/mn10300/mn10300.c	2019-08-19 15:58:28.438077523 +0100
@@ -1526,17 +1526,9 @@ mn10300_va_start (tree valist, rtx nexta
 /* Return true when a parameter should be passed by reference.  */
 
 static bool
-mn10300_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
-			   machine_mode mode, const_tree type,
-			   bool named ATTRIBUTE_UNUSED)
+mn10300_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
 {
-  unsigned HOST_WIDE_INT size;
-
-  if (type)
-    size = int_size_in_bytes (type);
-  else
-    size = GET_MODE_SIZE (mode);
-
+  unsigned HOST_WIDE_INT size = arg.type_size_in_bytes ();
   return (size > 8 || size == 0);
 }
 
Index: gcc/config/moxie/moxie.c
===================================================================
--- gcc/config/moxie/moxie.c	2019-08-19 15:58:21.738126000 +0100
+++ gcc/config/moxie/moxie.c	2019-08-19 15:58:28.438077523 +0100
@@ -451,25 +451,15 @@ moxie_function_arg_advance (cumulative_a
 	  : *cum);
 }
 
-/* Return non-zero if the function argument described by TYPE is to be
+/* Return non-zero if the function argument described by ARG is to be
    passed by reference.  */
 
 static bool
-moxie_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
-			 machine_mode mode, const_tree type,
-			 bool named ATTRIBUTE_UNUSED)
+moxie_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
 {
-  unsigned HOST_WIDE_INT size;
-
-  if (type)
-    {
-      if (AGGREGATE_TYPE_P (type))
-	return true;
-      size = int_size_in_bytes (type);
-    }
-  else
-    size = GET_MODE_SIZE (mode);
-
+  if (arg.aggregate_type_p ())
+    return true;
+  unsigned HOST_WIDE_INT size = arg.type_size_in_bytes ();
   return size > 4*6;
 }
 
@@ -486,7 +476,7 @@ moxie_arg_partial_bytes (cumulative_args
   if (*cum >= 8)
     return 0;
 
-  if (moxie_pass_by_reference (cum_v, arg.mode, arg.type, arg.named))
+  if (moxie_pass_by_reference (cum_v, arg))
     size = 4;
   else if (arg.type)
     {
Index: gcc/config/msp430/msp430.c
===================================================================
--- gcc/config/msp430/msp430.c	2019-08-19 15:58:21.738126000 +0100
+++ gcc/config/msp430/msp430.c	2019-08-19 15:58:28.438077523 +0100
@@ -744,14 +744,11 @@ msp430_arg_partial_bytes (cumulative_arg
 #define TARGET_PASS_BY_REFERENCE msp430_pass_by_reference
 
 static bool
-msp430_pass_by_reference (cumulative_args_t cap ATTRIBUTE_UNUSED,
-			  machine_mode mode,
-			  const_tree type,
-			  bool named ATTRIBUTE_UNUSED)
+msp430_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
 {
-  return (mode == BLKmode
-	  || (type && TREE_CODE (type) == RECORD_TYPE)
-	  || (type && TREE_CODE (type) == UNION_TYPE));
+  return (arg.mode == BLKmode
+	  || (arg.type && TREE_CODE (arg.type) == RECORD_TYPE)
+	  || (arg.type && TREE_CODE (arg.type) == UNION_TYPE));
 }
 
 #undef  TARGET_CALLEE_COPIES
Index: gcc/config/nvptx/nvptx.c
===================================================================
--- gcc/config/nvptx/nvptx.c	2019-08-13 22:35:11.749252108 +0100
+++ gcc/config/nvptx/nvptx.c	2019-08-19 15:58:28.438077523 +0100
@@ -633,11 +633,9 @@ nvptx_function_value_regno_p (const unsi
    reference in memory.  */
 
 static bool
-nvptx_pass_by_reference (cumulative_args_t ARG_UNUSED (cum),
-			 machine_mode mode, const_tree type,
-			 bool ARG_UNUSED (named))
+nvptx_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
 {
-  return pass_in_memory (mode, type, false);
+  return pass_in_memory (arg.mode, arg.type, false);
 }
 
 /* Implement TARGET_RETURN_IN_MEMORY.  */
Index: gcc/config/or1k/or1k.c
===================================================================
--- gcc/config/or1k/or1k.c	2019-07-29 09:39:47.294185050 +0100
+++ gcc/config/or1k/or1k.c	2019-08-19 15:58:28.442077491 +0100
@@ -928,23 +928,16 @@ or1k_legitimate_constant_p (machine_mode
 #define TARGET_LEGITIMATE_CONSTANT_P or1k_legitimate_constant_p
 
 /* Worker for TARGET_PASS_BY_REFERENCE.
-   Returns true if an argument of TYPE in MODE should be passed by reference
-   as required by the OpenRISC ABI.  On OpenRISC structures, unions and
+   Returns true if an argument ARG should be passed by reference as
+   required by the OpenRISC ABI.  On OpenRISC structures, unions and
    arguments larger than 64-bits are passed by reference.  */
 
 static bool
-or1k_pass_by_reference (cumulative_args_t, machine_mode mode,
-			const_tree type, bool)
+or1k_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
 {
-  HOST_WIDE_INT size;
-  if (type)
-    {
-      if (AGGREGATE_TYPE_P (type))
-	return true;
-      size = int_size_in_bytes (type);
-    }
-  else
-    size = GET_MODE_SIZE (mode);
+  if (arg.aggregate_type_p ())
+    return true;
+  HOST_WIDE_INT size = arg.type_size_in_bytes ();
   return size < 0 || size > 8;
 }
 
Index: gcc/config/pa/pa.c
===================================================================
--- gcc/config/pa/pa.c	2019-08-19 15:58:21.738126000 +0100
+++ gcc/config/pa/pa.c	2019-08-19 15:58:28.442077491 +0100
@@ -164,8 +164,8 @@ static void output_deferred_profile_coun
 static void pa_file_end (void);
 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 bool pa_pass_by_reference (cumulative_args_t,
+				  const function_arg_info &);
 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);
@@ -6222,17 +6222,9 @@ pa_eh_return_handler_rtx (void)
    or updates the ABI.  */
 
 static bool
-pa_pass_by_reference (cumulative_args_t ca ATTRIBUTE_UNUSED,
-		      machine_mode mode, const_tree type,
-		      bool named ATTRIBUTE_UNUSED)
+pa_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
 {
-  HOST_WIDE_INT size;
-
-  if (type)
-    size = int_size_in_bytes (type);
-  else
-    size = GET_MODE_SIZE (mode);
-
+  HOST_WIDE_INT size = arg.type_size_in_bytes ();
   if (TARGET_64BIT)
     return size <= 0;
   else
Index: gcc/config/riscv/riscv.c
===================================================================
--- gcc/config/riscv/riscv.c	2019-08-19 15:58:21.738126000 +0100
+++ gcc/config/riscv/riscv.c	2019-08-19 15:58:28.442077491 +0100
@@ -2815,10 +2815,9 @@ riscv_function_value (const_tree type, c
 /* Implement TARGET_PASS_BY_REFERENCE. */
 
 static bool
-riscv_pass_by_reference (cumulative_args_t cum_v, machine_mode mode,
-			 const_tree type, bool named)
+riscv_pass_by_reference (cumulative_args_t cum_v, const function_arg_info &arg)
 {
-  HOST_WIDE_INT size = type ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
+  HOST_WIDE_INT size = arg.type_size_in_bytes ();
   struct riscv_arg_info info;
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
@@ -2828,7 +2827,7 @@ riscv_pass_by_reference (cumulative_args
   if (cum != NULL)
     {
       /* Don't pass by reference if we can use a floating-point register.  */
-      riscv_get_arg_info (&info, cum, mode, type, named, false);
+      riscv_get_arg_info (&info, cum, arg.mode, arg.type, arg.named, false);
       if (info.num_fprs)
 	return false;
     }
@@ -2848,7 +2847,8 @@ riscv_return_in_memory (const_tree type,
   /* The rules for returning in memory are the same as for passing the
      first named argument by reference.  */
   memset (&args, 0, sizeof args);
-  return riscv_pass_by_reference (cum, TYPE_MODE (type), type, true);
+  function_arg_info arg (const_cast<tree> (type), /*named=*/true);
+  return riscv_pass_by_reference (cum, arg);
 }
 
 /* Implement TARGET_SETUP_INCOMING_VARARGS.  */
Index: gcc/config/rs6000/rs6000-internal.h
===================================================================
--- gcc/config/rs6000/rs6000-internal.h	2019-08-19 15:58:21.742125973 +0100
+++ gcc/config/rs6000/rs6000-internal.h	2019-08-19 15:58:28.442077491 +0100
@@ -150,9 +150,8 @@ extern machine_mode rs6000_promote_funct
 extern bool rs6000_return_in_memory (const_tree type, 
 				     const_tree fntype ATTRIBUTE_UNUSED);
 extern bool rs6000_return_in_msb (const_tree valtype);
-extern bool rs6000_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
-				      machine_mode mode, const_tree type,
-				      bool named ATTRIBUTE_UNUSED);
+extern bool rs6000_pass_by_reference (cumulative_args_t,
+				      const function_arg_info &);
 extern void setup_incoming_varargs (cumulative_args_t cum, machine_mode mode,
 				    tree type, int *pretend_size ATTRIBUTE_UNUSED,
 				    int no_rtl);
Index: gcc/config/rs6000/rs6000-call.c
===================================================================
--- gcc/config/rs6000/rs6000-call.c	2019-08-19 15:58:21.742125973 +0100
+++ gcc/config/rs6000/rs6000-call.c	2019-08-19 15:58:28.442077491 +0100
@@ -2111,29 +2111,27 @@ rs6000_arg_partial_bytes (cumulative_arg
    reference.  */
 
 bool
-rs6000_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
-			  machine_mode mode, const_tree type,
-			  bool named ATTRIBUTE_UNUSED)
+rs6000_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
 {
-  if (!type)
+  if (!arg.type)
     return 0;
 
   if (DEFAULT_ABI == ABI_V4 && TARGET_IEEEQUAD
-      && FLOAT128_IEEE_P (TYPE_MODE (type)))
+      && FLOAT128_IEEE_P (TYPE_MODE (arg.type)))
     {
       if (TARGET_DEBUG_ARG)
 	fprintf (stderr, "function_arg_pass_by_reference: V4 IEEE 128-bit\n");
       return 1;
     }
 
-  if (DEFAULT_ABI == ABI_V4 && AGGREGATE_TYPE_P (type))
+  if (DEFAULT_ABI == ABI_V4 && AGGREGATE_TYPE_P (arg.type))
     {
       if (TARGET_DEBUG_ARG)
 	fprintf (stderr, "function_arg_pass_by_reference: V4 aggregate\n");
       return 1;
     }
 
-  if (int_size_in_bytes (type) < 0)
+  if (int_size_in_bytes (arg.type) < 0)
     {
       if (TARGET_DEBUG_ARG)
 	fprintf (stderr, "function_arg_pass_by_reference: variable size\n");
@@ -2142,7 +2140,7 @@ rs6000_pass_by_reference (cumulative_arg
 
   /* Allow -maltivec -mabi=no-altivec without warning.  Altivec vector
      modes only exist for GCC vector types if -maltivec.  */
-  if (TARGET_32BIT && !TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
+  if (TARGET_32BIT && !TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (arg.mode))
     {
       if (TARGET_DEBUG_ARG)
 	fprintf (stderr, "function_arg_pass_by_reference: AltiVec\n");
@@ -2150,8 +2148,8 @@ rs6000_pass_by_reference (cumulative_arg
     }
 
   /* Pass synthetic vectors in memory.  */
-  if (TREE_CODE (type) == VECTOR_TYPE
-      && int_size_in_bytes (type) > (TARGET_ALTIVEC_ABI ? 16 : 8))
+  if (TREE_CODE (arg.type) == VECTOR_TYPE
+      && int_size_in_bytes (arg.type) > (TARGET_ALTIVEC_ABI ? 16 : 8))
     {
       static bool warned_for_pass_big_vectors = false;
       if (TARGET_DEBUG_ARG)
@@ -2200,7 +2198,7 @@ rs6000_parm_needs_stack (cumulative_args
 
   /* See if this arg was passed by invisible reference.  */
   if (pass_by_reference (get_cumulative_args (args_so_far),
-			 TYPE_MODE (type), type, true))
+			 function_arg_info (type, /*named=*/true)))
     type = build_pointer_type (type);
 
   /* Find mode as it is passed by the ABI.  */
Index: gcc/config/s390/s390.c
===================================================================
--- gcc/config/s390/s390.c	2019-08-19 15:58:10.762205420 +0100
+++ gcc/config/s390/s390.c	2019-08-19 15:58:28.442077491 +0100
@@ -11953,26 +11953,23 @@ s390_function_arg_integer (machine_mode
   return false;
 }
 
-/* Return 1 if a function argument of type TYPE and mode MODE
-   is to be passed by reference.  The ABI specifies that only
-   structures of size 1, 2, 4, or 8 bytes are passed by value,
-   all other structures (and complex numbers) are passed by
-   reference.  */
+/* Return 1 if a function argument ARG is to be passed by reference.
+   The ABI specifies that only structures of size 1, 2, 4, or 8 bytes
+   are passed by value, all other structures (and complex numbers) are
+   passed by reference.  */
 
 static bool
-s390_pass_by_reference (cumulative_args_t ca ATTRIBUTE_UNUSED,
-			machine_mode mode, const_tree type,
-			bool named ATTRIBUTE_UNUSED)
+s390_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
 {
-  int size = s390_function_arg_size (mode, type);
+  int size = s390_function_arg_size (arg.mode, arg.type);
 
-  if (s390_function_arg_vector (mode, type))
+  if (s390_function_arg_vector (arg.mode, arg.type))
     return false;
 
   if (size > 8)
     return true;
 
-  if (type)
+  if (tree type = arg.type)
     {
       if (AGGREGATE_TYPE_P (type) && exact_log2 (size) < 0)
 	return true;
@@ -13349,7 +13346,7 @@ s390_call_saved_register_used (tree call
       /* 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, mode, type, true))
+      if (pass_by_reference (&cum_v, function_arg_info (type, /*named=*/true)))
 	{
 	  mode = Pmode;
 	  type = build_pointer_type (type);
Index: gcc/config/sh/sh.c
===================================================================
--- gcc/config/sh/sh.c	2019-08-19 15:58:21.742125973 +0100
+++ gcc/config/sh/sh.c	2019-08-19 15:58:28.446077464 +0100
@@ -294,8 +294,8 @@ static machine_mode sh_promote_function_
 						   int *punsignedp,
 						   const_tree funtype,
 						   int for_return);
-static bool sh_pass_by_reference (cumulative_args_t, machine_mode,
-				  const_tree, bool);
+static bool sh_pass_by_reference (cumulative_args_t,
+				  const function_arg_info &);
 static bool sh_callee_copies (cumulative_args_t, machine_mode,
 			      const_tree, bool);
 static int sh_arg_partial_bytes (cumulative_args_t, const function_arg_info &);
@@ -7899,12 +7899,11 @@ sh_promote_prototypes (const_tree type)
 }
 
 static bool
-sh_pass_by_reference (cumulative_args_t cum_v, machine_mode mode,
-		      const_tree type, bool named ATTRIBUTE_UNUSED)
+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 (mode, type))
+  if (targetm.calls.must_pass_in_stack (arg.mode, arg.type))
     return true;
 
   /* ??? std_gimplify_va_arg_expr passes NULL for cum.  That function
Index: gcc/config/sparc/sparc.c
===================================================================
--- gcc/config/sparc/sparc.c	2019-08-19 15:58:21.742125973 +0100
+++ gcc/config/sparc/sparc.c	2019-08-19 15:58:28.446077464 +0100
@@ -655,7 +655,7 @@ static rtx sparc_legitimize_address (rtx
 static rtx sparc_delegitimize_address (rtx);
 static bool sparc_mode_dependent_address_p (const_rtx, addr_space_t);
 static bool sparc_pass_by_reference (cumulative_args_t,
-				     machine_mode, const_tree, bool);
+				     const function_arg_info &);
 static void sparc_function_arg_advance (cumulative_args_t,
 					machine_mode, const_tree, bool);
 static rtx sparc_function_arg_1 (cumulative_args_t,
@@ -6743,10 +6743,10 @@ sparc_strict_argument_naming (cumulative
    Specify whether to pass the argument by reference.  */
 
 static bool
-sparc_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
-			 machine_mode mode, const_tree type,
-			 bool named ATTRIBUTE_UNUSED)
+sparc_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
 {
+  tree type = arg.type;
+  machine_mode mode = arg.mode;
   if (TARGET_ARCH32)
     /* Original SPARC 32-bit ABI says that structures and unions,
        and quad-precision floats are passed by reference.
Index: gcc/config/spu/spu.c
===================================================================
--- gcc/config/spu/spu.c	2019-08-19 15:58:10.766205389 +0100
+++ gcc/config/spu/spu.c	2019-08-19 15:58:28.446077464 +0100
@@ -3902,11 +3902,9 @@ spu_function_arg_padding (machine_mode,
 
 /* Variable sized types are passed by reference.  */
 static bool
-spu_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
-		       machine_mode mode ATTRIBUTE_UNUSED,
-		       const_tree type, bool named ATTRIBUTE_UNUSED)
+spu_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
 {
-  return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
+  return arg.type && TREE_CODE (TYPE_SIZE (arg.type)) != INTEGER_CST;
 }
 \f
 
Index: gcc/config/tilegx/tilegx.c
===================================================================
--- gcc/config/tilegx/tilegx.c	2019-08-19 15:58:10.766205389 +0100
+++ gcc/config/tilegx/tilegx.c	2019-08-19 15:58:28.446077464 +0100
@@ -159,12 +159,11 @@ tilegx_function_ok_for_sibcall (tree dec
 /* Implement TARGET_PASS_BY_REFERENCE.  Variable sized types are
    passed by reference.  */
 static bool
-tilegx_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
-			  machine_mode mode ATTRIBUTE_UNUSED,
-			  const_tree type, bool named ATTRIBUTE_UNUSED)
+tilegx_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
 {
-  return (type && TYPE_SIZE (type)
-	  && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST);
+  return (arg.type
+	  && TYPE_SIZE (arg.type)
+	  && TREE_CODE (TYPE_SIZE (arg.type)) != INTEGER_CST);
 }
 
 
Index: gcc/config/tilepro/tilepro.c
===================================================================
--- gcc/config/tilepro/tilepro.c	2019-08-19 15:58:10.766205389 +0100
+++ gcc/config/tilepro/tilepro.c	2019-08-19 15:58:28.446077464 +0100
@@ -134,12 +134,11 @@ tilepro_function_ok_for_sibcall (tree de
 /* Implement TARGET_PASS_BY_REFERENCE.  Variable sized types are
    passed by reference.  */
 static bool
-tilepro_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
-			   machine_mode mode ATTRIBUTE_UNUSED,
-			   const_tree type, bool named ATTRIBUTE_UNUSED)
+tilepro_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
 {
-  return (type && TYPE_SIZE (type)
-	  && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST);
+  return (arg.type
+	  && TYPE_SIZE (arg.type)
+	  && TREE_CODE (TYPE_SIZE (arg.type)) != INTEGER_CST);
 }
 
 
Index: gcc/config/v850/v850.c
===================================================================
--- gcc/config/v850/v850.c	2019-08-19 15:58:21.742125973 +0100
+++ gcc/config/v850/v850.c	2019-08-19 15:58:28.446077464 +0100
@@ -110,20 +110,12 @@ v850_all_frame_related (rtx par)
    Specify whether to pass the argument by reference.  */
 
 static bool
-v850_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
-			machine_mode mode, const_tree type,
-			bool named ATTRIBUTE_UNUSED)
+v850_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
 {
-  unsigned HOST_WIDE_INT size;
-
   if (!TARGET_GCC_ABI)
     return 0;
 
-  if (type)
-    size = int_size_in_bytes (type);
-  else
-    size = GET_MODE_SIZE (mode);
-
+  unsigned HOST_WIDE_INT size = arg.type_size_in_bytes ();
   return size > 8;
 }
 
Index: gcc/config/visium/visium.c
===================================================================
--- gcc/config/visium/visium.c	2019-08-19 15:58:10.766205389 +0100
+++ gcc/config/visium/visium.c	2019-08-19 15:58:28.446077464 +0100
@@ -158,8 +158,8 @@ static struct machine_function *visium_i
 
 /* Target hooks and TARGET_INITIALIZER  */
 
-static bool visium_pass_by_reference (cumulative_args_t, machine_mode,
-				      const_tree, bool);
+static bool visium_pass_by_reference (cumulative_args_t,
+				      const function_arg_info &);
 
 static rtx visium_function_arg (cumulative_args_t, machine_mode,
 				const_tree, bool);
@@ -1310,11 +1310,9 @@ visium_reorg (void)
 /* Return true if an argument must be passed by indirect reference.  */
 
 static bool
-visium_pass_by_reference (cumulative_args_t ca ATTRIBUTE_UNUSED,
-			  machine_mode mode ATTRIBUTE_UNUSED,
-			  const_tree type,
-			  bool named ATTRIBUTE_UNUSED)
+visium_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
 {
+  tree type = arg.type;
   return type && (AGGREGATE_TYPE_P (type) || TREE_CODE (type) == VECTOR_TYPE);
 }
 
Index: gcc/ada/gcc-interface/misc.c
===================================================================
--- gcc/ada/gcc-interface/misc.c	2019-08-19 15:57:58.586293518 +0100
+++ gcc/ada/gcc-interface/misc.c	2019-08-19 15:58:28.414077694 +0100
@@ -1136,7 +1136,7 @@ default_pass_by_ref (tree gnu_type)
 			       TYPE_ALIGN (gnu_type)) > 0))
     return true;
 
-  if (pass_by_reference (NULL, TYPE_MODE (gnu_type), gnu_type, true))
+  if (pass_by_reference (NULL, function_arg_info (gnu_type, /*named=*/true)))
     return true;
 
   if (targetm.calls.return_in_memory (gnu_type, NULL_TREE))

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [05/13] Use function_arg_info for TARGET_SETUP_INCOMING_ARGS
  2019-08-19 15:15 [00/13] Pass an argument descriptor to target hooks Richard Sandiford
                   ` (3 preceding siblings ...)
  2019-08-19 15:19 ` [04/13] Use function_arg_info for TARGET_PASS_BY_REFERENCE Richard Sandiford
@ 2019-08-19 15:20 ` Richard Sandiford
  2019-08-19 20:50   ` Jeff Law
  2019-08-19 15:21 ` [06/13] Use function_arg_info for TARGET_FUNCTION_(INCOMING_)ARG Richard Sandiford
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 27+ messages in thread
From: Richard Sandiford @ 2019-08-19 15:20 UTC (permalink / raw)
  To: gcc-patches

Use function_arg_info for TARGET_SETUP_INCOMING_ARGS.

The hook is passed the promoted mode instead of the original type mode.


2019-08-19  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	* target.def (setup_incoming_varargs): Take a function_arg_info
	instead of a mode and tree.
	* doc/tm.texi: Regenerate.
	* targhooks.h (default_setup_incoming_varargs): Take a
	function_arg_info instead of a mode and tree.
	* targhooks.c (default_setup_incoming_varargs): Likewise.
	* config/aarch64/aarch64.c (aarch64_setup_incoming_varargs): Likewise.
	* config/alpha/alpha.c (alpha_setup_incoming_varargs): Likewise.
	* config/arc/arc.c (arc_setup_incoming_varargs): Likewise.
	* config/arm/arm.c (arm_setup_incoming_varargs): Likewise.
	* config/bfin/bfin.c (setup_incoming_varargs): Likewise.
	* config/cris/cris.c (cris_setup_incoming_varargs): Likewise.
	* config/csky/csky.c (csky_setup_incoming_varargs): Likewise.
	* config/epiphany/epiphany.c (epiphany_setup_incoming_varargs):
	Likewise.
	* config/fr30/fr30.c (fr30_setup_incoming_varargs): Likewise.
	* config/frv/frv.c (frv_setup_incoming_varargs): Likewise.
	* config/ft32/ft32.c (ft32_setup_incoming_varargs): Likewise.
	* config/i386/i386.c (ix86_setup_incoming_varargs): Likewise.
	* config/ia64/ia64.c (ia64_setup_incoming_varargs): Likewise.
	* config/iq2000/iq2000.c (iq2000_setup_incoming_varargs): Likewise.
	* config/lm32/lm32.c (lm32_setup_incoming_varargs): Likewise.
	* config/m32r/m32r.c (m32r_setup_incoming_varargs): Likewise.
	* config/mcore/mcore.c (mcore_setup_incoming_varargs): Likewise.
	* config/mips/mips.c (mips_setup_incoming_varargs): Likewise.
	* config/mmix/mmix.c (mmix_setup_incoming_varargs): Likewise.
	* config/moxie/moxie.c (moxie_setup_incoming_varargs): Likewise.
	* config/nds32/nds32.c (nds32_setup_incoming_varargs): Likewise.
	* config/nios2/nios2.c (nios2_setup_incoming_varargs): Likewise.
	* config/riscv/riscv.c (riscv_setup_incoming_varargs): Likewise.
	* config/rs6000/rs6000-internal.h (setup_incoming_varargs): Likewise.
	* config/rs6000/rs6000-call.c (setup_incoming_varargs): Likewise.
	* config/sh/sh.c (sh_setup_incoming_varargs): Likewise.
	* config/spu/spu.c (spu_setup_incoming_varargs): Likewise.
	* config/tilegx/tilegx.c (tilegx_setup_incoming_varargs): Likewise.
	* config/tilepro/tilepro.c (tilepro_setup_incoming_varargs): Likewise.
	* config/visium/visium.c (visium_setup_incoming_varargs): Likewise.
	* function.c (assign_parms_setup_varargs): Update call to
	targetm.calls.setup_incoming_varargs.

Index: gcc/target.def
===================================================================
--- gcc/target.def	2019-08-19 15:58:28.450077433 +0100
+++ gcc/target.def	2019-08-19 15:58:34.850031127 +0100
@@ -4486,8 +4486,8 @@ pass all their arguments on the stack.\n
 \n\
 The argument @var{args_so_far} points to the @code{CUMULATIVE_ARGS} data\n\
 structure, containing the values that are obtained after processing the\n\
-named arguments.  The arguments @var{mode} and @var{type} describe the\n\
-last named argument---its machine mode and its data type as a tree node.\n\
+named arguments.  The argument @var{arg} describes the last of these named\n\
+arguments.\n\
 \n\
 The target hook should do two things: first, push onto the stack all the\n\
 argument registers @emph{not} used for the named arguments, and second,\n\
@@ -4507,7 +4507,7 @@ arguments of the function are being anal
 happens for an inline function, which is not actually compiled until the\n\
 end of the source file.  The hook @code{TARGET_SETUP_INCOMING_VARARGS} should\n\
 not generate any instructions in this case.",
- void, (cumulative_args_t args_so_far, machine_mode mode, tree type,
+ void, (cumulative_args_t args_so_far, const function_arg_info &arg,
 	int *pretend_args_size, int second_time),
  default_setup_incoming_varargs)
 
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	2019-08-19 15:58:28.450077433 +0100
+++ gcc/doc/tm.texi	2019-08-19 15:58:34.850031127 +0100
@@ -5202,7 +5202,7 @@ return value of this function should be
 to use as the return of @code{__builtin_saveregs}.
 @end deftypefn
 
-@deftypefn {Target Hook} void TARGET_SETUP_INCOMING_VARARGS (cumulative_args_t @var{args_so_far}, machine_mode @var{mode}, tree @var{type}, int *@var{pretend_args_size}, int @var{second_time})
+@deftypefn {Target Hook} void TARGET_SETUP_INCOMING_VARARGS (cumulative_args_t @var{args_so_far}, const function_arg_info @var{&arg}, int *@var{pretend_args_size}, int @var{second_time})
 This target hook offers an alternative to using
 @code{__builtin_saveregs} and defining the hook
 @code{TARGET_EXPAND_BUILTIN_SAVEREGS}.  Use it to store the anonymous
@@ -5213,8 +5213,8 @@ pass all their arguments on the stack.
 
 The argument @var{args_so_far} points to the @code{CUMULATIVE_ARGS} data
 structure, containing the values that are obtained after processing the
-named arguments.  The arguments @var{mode} and @var{type} describe the
-last named argument---its machine mode and its data type as a tree node.
+named arguments.  The argument @var{arg} describes the last of these named
+arguments.
 
 The target hook should do two things: first, push onto the stack all the
 argument registers @emph{not} used for the named arguments, and second,
Index: gcc/targhooks.h
===================================================================
--- gcc/targhooks.h	2019-08-19 15:58:28.450077433 +0100
+++ gcc/targhooks.h	2019-08-19 15:58:34.850031127 +0100
@@ -40,7 +40,9 @@ extern machine_mode default_cc_modes_com
 extern bool default_return_in_memory (const_tree, const_tree);
 
 extern rtx default_expand_builtin_saveregs (void);
-extern void default_setup_incoming_varargs (cumulative_args_t, machine_mode, tree, int *, int);
+extern void default_setup_incoming_varargs (cumulative_args_t,
+					    const function_arg_info &,
+					    int *, int);
 extern rtx default_builtin_setjmp_frame_value (void);
 extern bool default_pretend_outgoing_varargs_named (cumulative_args_t);
 
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c	2019-08-19 15:58:28.450077433 +0100
+++ gcc/targhooks.c	2019-08-19 15:58:34.850031127 +0100
@@ -193,11 +193,8 @@ default_expand_builtin_saveregs (void)
 }
 
 void
-default_setup_incoming_varargs (cumulative_args_t ca ATTRIBUTE_UNUSED,
-				machine_mode mode ATTRIBUTE_UNUSED,
-				tree type ATTRIBUTE_UNUSED,
-				int *pretend_arg_size ATTRIBUTE_UNUSED,
-				int second_time ATTRIBUTE_UNUSED)
+default_setup_incoming_varargs (cumulative_args_t,
+				const function_arg_info &, int *, int)
 {
 }
 
Index: gcc/config/aarch64/aarch64.c
===================================================================
--- gcc/config/aarch64/aarch64.c	2019-08-19 15:58:28.422077636 +0100
+++ gcc/config/aarch64/aarch64.c	2019-08-19 15:58:34.822031327 +0100
@@ -14511,9 +14511,9 @@ aarch64_gimplify_va_arg_expr (tree valis
 /* Implement TARGET_SETUP_INCOMING_VARARGS.  */
 
 static void
-aarch64_setup_incoming_varargs (cumulative_args_t cum_v, machine_mode mode,
-				tree type, int *pretend_size ATTRIBUTE_UNUSED,
-				int no_rtl)
+aarch64_setup_incoming_varargs (cumulative_args_t cum_v,
+				const function_arg_info &arg,
+				int *pretend_size ATTRIBUTE_UNUSED, int no_rtl)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   CUMULATIVE_ARGS local_cum;
@@ -14524,7 +14524,8 @@ aarch64_setup_incoming_varargs (cumulati
      argument.  Advance a local copy of CUM past the last "real" named
      argument, to find out how many registers are left over.  */
   local_cum = *cum;
-  aarch64_function_arg_advance (pack_cumulative_args(&local_cum), mode, type, true);
+  aarch64_function_arg_advance (pack_cumulative_args(&local_cum),
+				arg.mode, arg.type, arg.named);
 
   /* Found out how many registers we need to save.
      Honor tree-stdvar analysis results.  */
Index: gcc/config/alpha/alpha.c
===================================================================
--- gcc/config/alpha/alpha.c	2019-08-19 15:58:28.422077636 +0100
+++ gcc/config/alpha/alpha.c	2019-08-19 15:58:34.822031327 +0100
@@ -6090,14 +6090,15 @@ alpha_stdarg_optimize_hook (struct stdar
    variable number of arguments.  */
 
 static void
-alpha_setup_incoming_varargs (cumulative_args_t pcum, machine_mode mode,
-			      tree type, int *pretend_size, int no_rtl)
+alpha_setup_incoming_varargs (cumulative_args_t pcum,
+			      const function_arg_info &arg,
+			      int *pretend_size, int no_rtl)
 {
   CUMULATIVE_ARGS cum = *get_cumulative_args (pcum);
 
   /* Skip the current argument.  */
-  targetm.calls.function_arg_advance (pack_cumulative_args (&cum), mode, type,
-				      true);
+  targetm.calls.function_arg_advance (pack_cumulative_args (&cum),
+				      arg.mode, arg.type, arg.named);
 
 #if TARGET_ABI_OPEN_VMS
   /* For VMS, we allocate space for all 6 arg registers plus a count.
Index: gcc/config/arc/arc.c
===================================================================
--- gcc/config/arc/arc.c	2019-08-19 15:58:28.426077609 +0100
+++ gcc/config/arc/arc.c	2019-08-19 15:58:34.826031299 +0100
@@ -2415,12 +2415,12 @@ arc_double_limm_p (rtx value)
    create a register parameter block, and then copy any anonymous arguments
    in registers to memory.
 
-   CUM has not been updated for the last named argument which has type TYPE
-   and mode MODE, and we rely on this fact.  */
+   CUM has not been updated for the last named argument (which is given
+   by ARG), and we rely on this fact.  */
 
 static void
 arc_setup_incoming_varargs (cumulative_args_t args_so_far,
-			    machine_mode mode, tree type,
+			    const function_arg_info &arg,
 			    int *pretend_size, int no_rtl)
 {
   int first_anon_arg;
@@ -2430,7 +2430,7 @@ arc_setup_incoming_varargs (cumulative_a
 
   next_cum = *get_cumulative_args (args_so_far);
   arc_function_arg_advance (pack_cumulative_args (&next_cum),
-			    mode, type, true);
+			    arg.mode, arg.type, arg.named);
   first_anon_arg = next_cum;
 
   if (FUNCTION_ARG_REGNO_P (first_anon_arg))
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c	2019-08-19 15:58:28.430077578 +0100
+++ gcc/config/arm/arm.c	2019-08-19 15:58:34.830031272 +0100
@@ -212,8 +212,8 @@ static void arm_file_end (void);
 static void arm_file_start (void);
 static void arm_insert_attributes (tree, tree *);
 
-static void arm_setup_incoming_varargs (cumulative_args_t, machine_mode,
-					tree, int *, int);
+static void arm_setup_incoming_varargs (cumulative_args_t,
+					const function_arg_info &, int *, int);
 static bool arm_pass_by_reference (cumulative_args_t,
 				   const function_arg_info &);
 static bool arm_promote_prototypes (const_tree);
@@ -27054,8 +27054,7 @@ arm_output_load_gr (rtx *operands)
 
 static void
 arm_setup_incoming_varargs (cumulative_args_t pcum_v,
-			    machine_mode mode,
-			    tree type,
+			    const function_arg_info &arg,
 			    int *pretend_size,
 			    int second_time ATTRIBUTE_UNUSED)
 {
@@ -27068,17 +27067,17 @@ arm_setup_incoming_varargs (cumulative_a
       nregs = pcum->aapcs_ncrn;
       if (nregs & 1)
 	{
-	  int res = arm_needs_doubleword_align (mode, type);
+	  int res = arm_needs_doubleword_align (arg.mode, arg.type);
 	  if (res < 0 && warn_psabi)
 	    inform (input_location, "parameter passing for argument of "
-		    "type %qT changed in GCC 7.1", type);
+		    "type %qT changed in GCC 7.1", arg.type);
 	  else if (res > 0)
 	    {
 	      nregs++;
 	      if (res > 1 && warn_psabi)
 		inform (input_location,
 			"parameter passing for argument of type "
-			"%qT changed in GCC 9.1", type);
+			"%qT changed in GCC 9.1", arg.type);
 	    }
 	}
     }
Index: gcc/config/bfin/bfin.c
===================================================================
--- gcc/config/bfin/bfin.c	2019-08-19 15:58:28.430077578 +0100
+++ gcc/config/bfin/bfin.c	2019-08-19 15:58:34.830031272 +0100
@@ -540,7 +540,7 @@ expand_epilogue_reg_restore (rtx spreg,
 
    CUM is as above.
 
-   MODE and TYPE are the mode and type of the current parameter.
+   ARG is the last named argument.
 
    PRETEND_SIZE is a variable that should be set to the amount of stack
    that must be pushed by the prolog to pretend that our caller pushed
@@ -559,8 +559,7 @@ expand_epilogue_reg_restore (rtx spreg,
 
 static void
 setup_incoming_varargs (cumulative_args_t cum,
-			machine_mode mode ATTRIBUTE_UNUSED,
-			tree type ATTRIBUTE_UNUSED, int *pretend_size,
+			const function_arg_info &, int *pretend_size,
 			int no_rtl)
 {
   rtx mem;
Index: gcc/config/cris/cris.c
===================================================================
--- gcc/config/cris/cris.c	2019-08-19 15:58:28.430077578 +0100
+++ gcc/config/cris/cris.c	2019-08-19 15:58:34.834031241 +0100
@@ -108,8 +108,9 @@ static struct machine_function * cris_in
 
 static rtx cris_struct_value_rtx (tree, int);
 
-static void cris_setup_incoming_varargs (cumulative_args_t, machine_mode,
-					 tree type, int *, int);
+static void cris_setup_incoming_varargs (cumulative_args_t,
+					 const function_arg_info &,
+					 int *, int);
 
 static int cris_initial_frame_pointer_offset (void);
 
@@ -4021,8 +4022,7 @@ cris_struct_value_rtx (tree fntype ATTRI
 
 static void
 cris_setup_incoming_varargs (cumulative_args_t ca_v,
-			     machine_mode mode ATTRIBUTE_UNUSED,
-			     tree type ATTRIBUTE_UNUSED,
+			     const function_arg_info &,
 			     int *pretend_arg_size,
 			     int second_time)
 {
Index: gcc/config/csky/csky.c
===================================================================
--- gcc/config/csky/csky.c	2019-08-19 15:58:21.726126086 +0100
+++ gcc/config/csky/csky.c	2019-08-19 15:58:34.834031241 +0100
@@ -1937,8 +1937,7 @@ csky_arg_partial_bytes (cumulative_args_
 
 static void
 csky_setup_incoming_varargs (cumulative_args_t pcum_v,
-			     machine_mode mode,
-			     tree type,
+			     const function_arg_info &arg,
 			     int *pretend_size,
 			     int second_time ATTRIBUTE_UNUSED)
 {
@@ -1949,7 +1948,7 @@ csky_setup_incoming_varargs (cumulative_
 
   cfun->machine->uses_anonymous_args = 1;
   local_cum = *pcum;
-  csky_function_arg_advance (local_cum_v, mode, type, true);
+  csky_function_arg_advance (local_cum_v, arg.mode, arg.type, arg.named);
   regs_to_push = CSKY_NPARM_REGS - local_cum;
   if (regs_to_push)
     *pretend_size  = regs_to_push * UNITS_PER_WORD;
Index: gcc/config/epiphany/epiphany.c
===================================================================
--- gcc/config/epiphany/epiphany.c	2019-08-19 15:58:28.434077550 +0100
+++ gcc/config/epiphany/epiphany.c	2019-08-19 15:58:34.834031241 +0100
@@ -711,24 +711,25 @@ epiphany_function_arg_boundary (machine_
 /* Do any needed setup for a variadic function.  For the EPIPHANY, we
    actually emit the code in epiphany_expand_prologue.
 
-   CUM has not been updated for the last named argument which has type TYPE
-   and mode MODE, and we rely on this fact.  */
+   CUM has not been updated for the last named argument (which is given
+   by ARG), and we rely on this fact.  */
 
 
 static void
-epiphany_setup_incoming_varargs (cumulative_args_t cum, machine_mode mode,
-				 tree type, int *pretend_size, int no_rtl)
+epiphany_setup_incoming_varargs (cumulative_args_t cum,
+				 const function_arg_info &arg,
+				 int *pretend_size, int no_rtl)
 {
   int first_anon_arg;
   CUMULATIVE_ARGS next_cum;
   machine_function_t *mf = MACHINE_FUNCTION (cfun);
 
   /* All BLKmode values are passed by reference.  */
-  gcc_assert (mode != BLKmode);
+  gcc_assert (arg.mode != BLKmode);
 
   next_cum = *get_cumulative_args (cum);
-  next_cum
-    = ROUND_ADVANCE_CUM (next_cum, mode, type) + ROUND_ADVANCE_ARG (mode, type);
+  next_cum = (ROUND_ADVANCE_CUM (next_cum, arg.mode, arg.type)
+	      + ROUND_ADVANCE_ARG (arg.mode, arg.type));
   first_anon_arg = next_cum;
 
   if (first_anon_arg < MAX_EPIPHANY_PARM_REGS && !no_rtl)
Index: gcc/config/fr30/fr30.c
===================================================================
--- gcc/config/fr30/fr30.c	2019-08-19 15:58:21.730126059 +0100
+++ gcc/config/fr30/fr30.c	2019-08-19 15:58:34.834031241 +0100
@@ -113,8 +113,9 @@ struct fr30_frame_info
 /* Zero structure to initialize current_frame_info.  */
 static struct fr30_frame_info 	zero_frame_info;
 
-static void fr30_setup_incoming_varargs (cumulative_args_t, machine_mode,
-					 tree, int *, int);
+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 int fr30_arg_partial_bytes (cumulative_args_t,
 				   const function_arg_info &);
@@ -459,12 +460,11 @@ fr30_expand_epilogue (void)
    named argument, from registers into memory.  * copying actually done in
    fr30_expand_prologue().
 
-   ARG_REGS_USED_SO_FAR has *not* been updated for the last named argument
-   which has type TYPE and mode MODE, and we rely on this fact.  */
+   CUM has not been updated for the last named argument which has type TYPE
+   and mode MODE, and we rely on this fact.  */
 void
 fr30_setup_incoming_varargs (cumulative_args_t arg_regs_used_so_far_v,
-			     machine_mode mode,
-			     tree type ATTRIBUTE_UNUSED,
+			     const function_arg_info &arg,
 			     int *pretend_size,
 			     int second_time ATTRIBUTE_UNUSED)
 {
@@ -473,7 +473,7 @@ fr30_setup_incoming_varargs (cumulative_
   int size;
 
   /* All BLKmode values are passed by reference.  */
-  gcc_assert (mode != BLKmode);
+  gcc_assert (arg.mode != BLKmode);
 
   /* ??? This run-time test as well as the code inside the if
      statement is probably unnecessary.  */
@@ -481,7 +481,7 @@ fr30_setup_incoming_varargs (cumulative_
     /* If TARGET_STRICT_ARGUMENT_NAMING returns true, then the last named
        arg must not be treated as an anonymous arg.  */
     /* ??? This is a pointer increment, which makes no sense.  */
-    arg_regs_used_so_far += fr30_num_arg_regs (mode, type);
+    arg_regs_used_so_far += fr30_num_arg_regs (arg.mode, arg.type);
 
   size = FR30_NUM_ARG_REGS - (* arg_regs_used_so_far);
 
Index: gcc/config/frv/frv.c
===================================================================
--- gcc/config/frv/frv.c	2019-08-19 15:58:21.730126059 +0100
+++ gcc/config/frv/frv.c	2019-08-19 15:58:34.834031241 +0100
@@ -359,8 +359,8 @@ static bool frv_in_small_data_p			(const
 static void frv_asm_output_mi_thunk
   (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree);
 static void frv_setup_incoming_varargs		(cumulative_args_t,
-						 machine_mode,
-						 tree, int *, int);
+						 const function_arg_info &,
+						 int *, int);
 static rtx frv_expand_builtin_saveregs		(void);
 static void frv_expand_builtin_va_start		(tree, rtx);
 static bool frv_rtx_costs			(rtx, machine_mode, int, int,
@@ -2109,17 +2109,16 @@ frv_initial_elimination_offset (int from
 
 static void
 frv_setup_incoming_varargs (cumulative_args_t cum_v,
-                            machine_mode mode,
-                            tree type ATTRIBUTE_UNUSED,
-                            int *pretend_size,
-                            int second_time)
+			    const function_arg_info &arg,
+			    int *pretend_size,
+			    int second_time)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
   if (TARGET_DEBUG_ARG)
     fprintf (stderr,
 	     "setup_vararg: words = %2d, mode = %4s, pretend_size = %d, second_time = %d\n",
-	     *cum, GET_MODE_NAME (mode), *pretend_size, second_time);
+	     *cum, GET_MODE_NAME (arg.mode), *pretend_size, second_time);
 }
 
 \f
Index: gcc/config/ft32/ft32.c
===================================================================
--- gcc/config/ft32/ft32.c	2019-08-19 15:58:28.434077550 +0100
+++ gcc/config/ft32/ft32.c	2019-08-19 15:58:34.834031241 +0100
@@ -630,13 +630,12 @@ ft32_initial_elimination_offset (int fro
 
 static void
 ft32_setup_incoming_varargs (cumulative_args_t cum_v,
-			     machine_mode mode,
-			     tree type ATTRIBUTE_UNUSED,
+			     const function_arg_info &arg,
 			     int *pretend_size, int no_rtl ATTRIBUTE_UNUSED)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   int named_size =
-    GET_MODE_SIZE (SImode) * (*cum - FT32_R0) + GET_MODE_SIZE (mode);
+    GET_MODE_SIZE (SImode) * (*cum - FT32_R0) + GET_MODE_SIZE (arg.mode);
 
   if (named_size < 24)
     *pretend_size = 24 - named_size;
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	2019-08-19 15:58:28.434077550 +0100
+++ gcc/config/i386/i386.c	2019-08-19 15:58:34.838031214 +0100
@@ -4096,8 +4096,9 @@ setup_incoming_varargs_ms_64 (CUMULATIVE
 }
 
 static void
-ix86_setup_incoming_varargs (cumulative_args_t cum_v, machine_mode mode,
-			     tree type, int *, int no_rtl)
+ix86_setup_incoming_varargs (cumulative_args_t cum_v,
+			     const function_arg_info &arg,
+			     int *, int no_rtl)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   CUMULATIVE_ARGS next_cum;
@@ -4116,8 +4117,8 @@ ix86_setup_incoming_varargs (cumulative_
      For stdargs, we do want to skip the last named argument.  */
   next_cum = *cum;
   if (stdarg_p (fntype))
-    ix86_function_arg_advance (pack_cumulative_args (&next_cum), mode, type,
-			       true);
+    ix86_function_arg_advance (pack_cumulative_args (&next_cum),
+			       arg.mode, arg.type, arg.named);
 
   if (cum->call_abi == MS_ABI)
     setup_incoming_varargs_ms_64 (&next_cum);
Index: gcc/config/ia64/ia64.c
===================================================================
--- gcc/config/ia64/ia64.c	2019-08-19 15:58:21.734126028 +0100
+++ gcc/config/ia64/ia64.c	2019-08-19 15:58:34.838031214 +0100
@@ -199,8 +199,9 @@ static rtx gen_fr_restore_x (rtx, rtx, r
 static void ia64_option_override (void);
 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 void ia64_setup_incoming_varargs (cumulative_args_t,
+					 const function_arg_info &,
+					 int *, int);
 static int ia64_arg_partial_bytes (cumulative_args_t,
 				   const function_arg_info &);
 static rtx ia64_function_arg_1 (cumulative_args_t, machine_mode,
@@ -4585,19 +4586,21 @@ ia64_trampoline_init (rtx m_tramp, tree
 }
 \f
 /* Do any needed setup for a variadic function.  CUM has not been updated
-   for the last named argument which has type TYPE and mode MODE.
+   for the last named argument, which is given by ARG.
 
    We generate the actual spill instructions during prologue generation.  */
 
 static void
-ia64_setup_incoming_varargs (cumulative_args_t cum, machine_mode mode,
-			     tree type, int * pretend_size,
+ia64_setup_incoming_varargs (cumulative_args_t cum,
+			     const function_arg_info &arg,
+			     int *pretend_size,
 			     int second_time ATTRIBUTE_UNUSED)
 {
   CUMULATIVE_ARGS next_cum = *get_cumulative_args (cum);
 
   /* Skip the current argument.  */
-  ia64_function_arg_advance (pack_cumulative_args (&next_cum), mode, type, 1);
+  ia64_function_arg_advance (pack_cumulative_args (&next_cum),
+			     arg.mode, arg.type, arg.named);
 
   if (next_cum.words < MAX_ARGUMENT_SLOTS)
     {
Index: gcc/config/iq2000/iq2000.c
===================================================================
--- gcc/config/iq2000/iq2000.c	2019-08-19 15:58:28.434077550 +0100
+++ gcc/config/iq2000/iq2000.c	2019-08-19 15:58:34.842031183 +0100
@@ -152,8 +152,8 @@ static void iq2000_init_builtins      (v
 static rtx  iq2000_expand_builtin     (tree, rtx, rtx, machine_mode, int);
 static bool iq2000_return_in_memory   (const_tree, const_tree);
 static void iq2000_setup_incoming_varargs (cumulative_args_t,
-					   machine_mode, tree, int *,
-					   int);
+					   const function_arg_info &,
+					   int *, int);
 static bool iq2000_rtx_costs          (rtx, machine_mode, int, int, int *, bool);
 static int  iq2000_address_cost       (rtx, machine_mode, addr_space_t,
 				       bool);
@@ -2894,9 +2894,8 @@ iq2000_return_in_memory (const_tree type
 
 static void
 iq2000_setup_incoming_varargs (cumulative_args_t cum_v,
-			       machine_mode mode ATTRIBUTE_UNUSED,
-			       tree type ATTRIBUTE_UNUSED, int * pretend_size,
-			       int no_rtl)
+			       const function_arg_info &,
+			       int *pretend_size, int no_rtl)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   unsigned int iq2000_off = ! cum->last_arg_fp; 
Index: gcc/config/lm32/lm32.c
===================================================================
--- gcc/config/lm32/lm32.c	2019-03-08 18:15:37.796736185 +0000
+++ gcc/config/lm32/lm32.c	2019-08-19 15:58:34.842031183 +0100
@@ -64,7 +64,7 @@ static void expand_save_restore (struct
 static void stack_adjust (HOST_WIDE_INT amount);
 static bool lm32_in_small_data_p (const_tree);
 static void lm32_setup_incoming_varargs (cumulative_args_t cum,
-					 machine_mode mode, tree type,
+					 const function_arg_info &,
 					 int *pretend_size, int no_rtl);
 static bool lm32_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno,
 			    int *total, bool speed);
@@ -684,8 +684,9 @@ lm32_compute_initial_elimination_offset
 }
 
 static void
-lm32_setup_incoming_varargs (cumulative_args_t cum_v, machine_mode mode,
-			     tree type, int *pretend_size, int no_rtl)
+lm32_setup_incoming_varargs (cumulative_args_t cum_v,
+			     const function_arg_info &arg,
+			     int *pretend_size, int no_rtl)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   int first_anon_arg;
@@ -702,12 +703,7 @@ lm32_setup_incoming_varargs (cumulative_
          registers, if any used in passing this named paramter in
          order to determine which is the first registers used to pass
          anonymous arguments.  */
-      int size;
-
-      if (mode == BLKmode)
-	size = int_size_in_bytes (type);
-      else
-	size = GET_MODE_SIZE (mode);
+      int size = arg.promoted_size_in_bytes ();
 
       first_anon_arg =
 	*cum + LM32_FIRST_ARG_REG +
Index: gcc/config/m32r/m32r.c
===================================================================
--- gcc/config/m32r/m32r.c	2019-08-19 15:58:28.434077550 +0100
+++ gcc/config/m32r/m32r.c	2019-08-19 15:58:34.842031183 +0100
@@ -86,8 +86,9 @@ static bool m32r_return_in_memory (const
 static rtx m32r_function_value (const_tree, const_tree, bool);
 static rtx m32r_libcall_value (machine_mode, const_rtx);
 static bool m32r_function_value_regno_p (const unsigned int);
-static void m32r_setup_incoming_varargs (cumulative_args_t, machine_mode,
-					 tree, int *, int);
+static void m32r_setup_incoming_varargs (cumulative_args_t,
+					 const function_arg_info &,
+					 int *, int);
 static void init_idents (void);
 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);
@@ -1280,12 +1281,13 @@ m32r_function_value_regno_p (const unsig
    create a register parameter block, and then copy any anonymous arguments
    in registers to memory.
 
-   CUM has not been updated for the last named argument which has type TYPE
-   and mode MODE, and we rely on this fact.  */
+   CUM has not been updated for the last named argument (which is given
+   by ARG), and we rely on this fact.  */
 
 static void
-m32r_setup_incoming_varargs (cumulative_args_t cum, machine_mode mode,
-			     tree type, int *pretend_size, int no_rtl)
+m32r_setup_incoming_varargs (cumulative_args_t cum,
+			     const function_arg_info &arg,
+			     int *pretend_size, int no_rtl)
 {
   int first_anon_arg;
 
@@ -1293,10 +1295,11 @@ m32r_setup_incoming_varargs (cumulative_
     return;
 
   /* All BLKmode values are passed by reference.  */
-  gcc_assert (mode != BLKmode);
+  gcc_assert (arg.mode != BLKmode);
 
-  first_anon_arg = (ROUND_ADVANCE_CUM (*get_cumulative_args (cum), mode, type)
-		    + ROUND_ADVANCE_ARG (mode, type));
+  first_anon_arg = (ROUND_ADVANCE_CUM (*get_cumulative_args (cum),
+				       arg.mode, arg.type)
+		    + ROUND_ADVANCE_ARG (arg.mode, arg.type));
 
   if (first_anon_arg < M32R_MAX_PARM_REGS)
     {
Index: gcc/config/mcore/mcore.c
===================================================================
--- gcc/config/mcore/mcore.c	2019-08-19 15:58:21.734126028 +0100
+++ gcc/config/mcore/mcore.c	2019-08-19 15:58:34.842031183 +0100
@@ -99,7 +99,9 @@ static int        calc_live_regs
 static int        try_constant_tricks           (HOST_WIDE_INT, HOST_WIDE_INT *, HOST_WIDE_INT *);
 static const char *     output_inline_const     (machine_mode, rtx *);
 static void       layout_mcore_frame            (struct mcore_frame *);
-static void       mcore_setup_incoming_varargs	(cumulative_args_t, machine_mode, tree, int *, int);
+static void       mcore_setup_incoming_varargs	(cumulative_args_t,
+						 const function_arg_info &,
+						 int *, int);
 static cond_type  is_cond_candidate             (rtx);
 static rtx_insn  *emit_new_cond_insn            (rtx_insn *, int);
 static rtx_insn  *conditionalize_block          (rtx_insn *);
@@ -1942,7 +1944,7 @@ mcore_initial_elimination_offset (int fr
 
 static void
 mcore_setup_incoming_varargs (cumulative_args_t args_so_far_v,
-			      machine_mode mode, tree type,
+			      const function_arg_info &arg,
 			      int * ptr_pretend_size ATTRIBUTE_UNUSED,
 			      int second_time ATTRIBUTE_UNUSED)
 {
@@ -1953,7 +1955,8 @@ mcore_setup_incoming_varargs (cumulative
   /* We need to know how many argument registers are used before
      the varargs start, so that we can push the remaining argument
      registers during the prologue.  */
-  number_of_regs_before_varargs = *args_so_far + mcore_num_arg_regs (mode, type);
+  number_of_regs_before_varargs
+    = *args_so_far + mcore_num_arg_regs (arg.mode, arg.type);
   
   /* There is a bug somewhere in the arg handling code.
      Until I can find it this workaround always pushes the
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	2019-08-19 15:58:28.438077523 +0100
+++ gcc/config/mips/mips.c	2019-08-19 15:58:34.842031183 +0100
@@ -6544,9 +6544,9 @@ mips_return_in_memory (const_tree type,
 /* Implement TARGET_SETUP_INCOMING_VARARGS.  */
 
 static void
-mips_setup_incoming_varargs (cumulative_args_t cum, machine_mode mode,
-			     tree type, int *pretend_size ATTRIBUTE_UNUSED,
-			     int no_rtl)
+mips_setup_incoming_varargs (cumulative_args_t cum,
+			     const function_arg_info &arg,
+			     int *pretend_size ATTRIBUTE_UNUSED, int no_rtl)
 {
   CUMULATIVE_ARGS local_cum;
   int gp_saved, fp_saved;
@@ -6555,8 +6555,8 @@ mips_setup_incoming_varargs (cumulative_
      argument.  Advance a local copy of CUM past the last "real" named
      argument, to find out how many registers are left over.  */
   local_cum = *get_cumulative_args (cum);
-  mips_function_arg_advance (pack_cumulative_args (&local_cum), mode, type,
-			     true);
+  mips_function_arg_advance (pack_cumulative_args (&local_cum),
+			     arg.mode, arg.type, arg.named);
 
   /* Found out how many registers we need to save.  */
   gp_saved = MAX_ARGS_IN_REGISTERS - local_cum.num_gprs;
Index: gcc/config/mmix/mmix.c
===================================================================
--- gcc/config/mmix/mmix.c	2019-08-19 15:58:28.438077523 +0100
+++ gcc/config/mmix/mmix.c	2019-08-19 15:58:34.842031183 +0100
@@ -138,7 +138,7 @@ static void mmix_reorg (void);
 static void mmix_asm_output_mi_thunk
   (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree);
 static void mmix_setup_incoming_varargs
-  (cumulative_args_t, machine_mode, tree, int *, int);
+  (cumulative_args_t, const function_arg_info &, int *, int);
 static void mmix_file_start (void);
 static void mmix_file_end (void);
 static void mmix_init_libfuncs (void);
@@ -960,8 +960,7 @@ mmix_function_profiler (FILE *stream ATT
 
 static void
 mmix_setup_incoming_varargs (cumulative_args_t args_so_farp_v,
-			     machine_mode mode,
-			     tree vartype,
+			     const function_arg_info &arg,
 			     int *pretend_sizep,
 			     int second_time ATTRIBUTE_UNUSED)
 {
@@ -974,7 +973,7 @@ mmix_setup_incoming_varargs (cumulative_
 
   /* We assume that one argument takes up one register here.  That should
      be true until we start messing with multi-reg parameters.  */
-  if ((7 + (MMIX_FUNCTION_ARG_SIZE (mode, vartype))) / 8 != 1)
+  if ((7 + (MMIX_FUNCTION_ARG_SIZE (arg.mode, arg.type))) / 8 != 1)
     internal_error ("MMIX Internal: Last named vararg would not fit in a register");
 }
 
Index: gcc/config/moxie/moxie.c
===================================================================
--- gcc/config/moxie/moxie.c	2019-08-19 15:58:28.438077523 +0100
+++ gcc/config/moxie/moxie.c	2019-08-19 15:58:34.842031183 +0100
@@ -385,8 +385,7 @@ moxie_initial_elimination_offset (int fr
 
 static void
 moxie_setup_incoming_varargs (cumulative_args_t cum_v,
-			      machine_mode mode ATTRIBUTE_UNUSED,
-			      tree type ATTRIBUTE_UNUSED,
+			      const function_arg_info &,
 			      int *pretend_size, int no_rtl)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
Index: gcc/config/nds32/nds32.c
===================================================================
--- gcc/config/nds32/nds32.c	2019-08-19 15:58:21.738126000 +0100
+++ gcc/config/nds32/nds32.c	2019-08-19 15:58:34.846031154 +0100
@@ -2345,8 +2345,7 @@ nds32_warn_func_return (tree decl)
 
 static void
 nds32_setup_incoming_varargs (cumulative_args_t ca,
-			      machine_mode mode,
-			      tree type,
+			      const function_arg_info &arg,
 			      int *pretend_args_size,
 			      int second_time ATTRIBUTE_UNUSED)
 {
@@ -2370,14 +2369,14 @@ nds32_setup_incoming_varargs (cumulative
 
   cum = get_cumulative_args (ca);
 
-  /* The MODE and TYPE describe the last argument.
+  /* ARG describes the last argument.
      We need those information to determine the remaining registers
      for varargs.  */
   total_args_regs
     = NDS32_MAX_GPR_REGS_FOR_ARGS + NDS32_GPR_ARG_FIRST_REGNUM;
   num_of_used_regs
-    = NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, mode, type)
-      + NDS32_NEED_N_REGS_FOR_ARG (mode, type);
+    = NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, arg.mode, arg.type)
+      + NDS32_NEED_N_REGS_FOR_ARG (arg.mode, arg.type);
 
   remaining_reg_count = total_args_regs - num_of_used_regs;
   *pretend_args_size = remaining_reg_count * UNITS_PER_WORD;
Index: gcc/config/nios2/nios2.c
===================================================================
--- gcc/config/nios2/nios2.c	2019-08-19 15:58:21.738126000 +0100
+++ gcc/config/nios2/nios2.c	2019-08-19 15:58:34.846031154 +0100
@@ -3516,8 +3516,8 @@ nios2_return_in_memory (const_tree type,
    own va_arg type.  */
 static void
 nios2_setup_incoming_varargs (cumulative_args_t cum_v,
-                              machine_mode mode, tree type,
-                              int *pretend_size, int second_time)
+			      const function_arg_info &arg,
+			      int *pretend_size, int second_time)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); 
   CUMULATIVE_ARGS local_cum;
@@ -3527,7 +3527,7 @@ nios2_setup_incoming_varargs (cumulative
 
   cfun->machine->uses_anonymous_args = 1;
   local_cum = *cum;
-  nios2_function_arg_advance (local_cum_v, mode, type, true);
+  nios2_function_arg_advance (local_cum_v, arg.mode, arg.type, arg.named);
 
   regs_to_push = NUM_ARG_REGS - local_cum.regs_used;
 
Index: gcc/config/riscv/riscv.c
===================================================================
--- gcc/config/riscv/riscv.c	2019-08-19 15:58:28.442077491 +0100
+++ gcc/config/riscv/riscv.c	2019-08-19 15:58:34.846031154 +0100
@@ -2854,9 +2854,9 @@ riscv_return_in_memory (const_tree type,
 /* Implement TARGET_SETUP_INCOMING_VARARGS.  */
 
 static void
-riscv_setup_incoming_varargs (cumulative_args_t cum, machine_mode mode,
-			     tree type, int *pretend_size ATTRIBUTE_UNUSED,
-			     int no_rtl)
+riscv_setup_incoming_varargs (cumulative_args_t cum,
+			      const function_arg_info &arg,
+			      int *pretend_size ATTRIBUTE_UNUSED, int no_rtl)
 {
   CUMULATIVE_ARGS local_cum;
   int gp_saved;
@@ -2865,7 +2865,8 @@ riscv_setup_incoming_varargs (cumulative
      argument.  Advance a local copy of CUM past the last "real" named
      argument, to find out how many registers are left over.  */
   local_cum = *get_cumulative_args (cum);
-  riscv_function_arg_advance (pack_cumulative_args (&local_cum), mode, type, 1);
+  riscv_function_arg_advance (pack_cumulative_args (&local_cum),
+			      arg.mode, arg.type, arg.named);
 
   /* Found out how many registers we need to save.  */
   gp_saved = MAX_ARGS_IN_REGISTERS - local_cum.num_gprs;
Index: gcc/config/rs6000/rs6000-internal.h
===================================================================
--- gcc/config/rs6000/rs6000-internal.h	2019-08-19 15:58:28.442077491 +0100
+++ gcc/config/rs6000/rs6000-internal.h	2019-08-19 15:58:34.846031154 +0100
@@ -152,9 +152,8 @@ extern bool rs6000_return_in_memory (con
 extern bool rs6000_return_in_msb (const_tree valtype);
 extern bool rs6000_pass_by_reference (cumulative_args_t,
 				      const function_arg_info &);
-extern void setup_incoming_varargs (cumulative_args_t cum, machine_mode mode,
-				    tree type, int *pretend_size ATTRIBUTE_UNUSED,
-				    int no_rtl);
+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);
Index: gcc/config/rs6000/rs6000-call.c
===================================================================
--- gcc/config/rs6000/rs6000-call.c	2019-08-19 15:58:28.442077491 +0100
+++ gcc/config/rs6000/rs6000-call.c	2019-08-19 15:58:34.846031154 +0100
@@ -2365,7 +2365,7 @@ rs6000_move_block_from_reg (int regno, r
 
    CUM is as above.
 
-   MODE and TYPE are the mode and type of the current parameter.
+   ARG is the last named argument.
 
    PRETEND_SIZE is a variable that should be set to the amount of stack
    that must be pushed by the prolog to pretend that our caller pushed
@@ -2375,9 +2375,9 @@ rs6000_move_block_from_reg (int regno, r
    stack and set PRETEND_SIZE to the length of the registers pushed.  */
 
 void
-setup_incoming_varargs (cumulative_args_t cum, machine_mode mode,
-			tree type, int *pretend_size ATTRIBUTE_UNUSED,
-			int no_rtl)
+setup_incoming_varargs (cumulative_args_t cum,
+			const function_arg_info &arg,
+			int *pretend_size ATTRIBUTE_UNUSED, int no_rtl)
 {
   CUMULATIVE_ARGS next_cum;
   int reg_size = TARGET_32BIT ? 4 : 8;
@@ -2387,7 +2387,7 @@ setup_incoming_varargs (cumulative_args_
 
   /* Skip the last named argument.  */
   next_cum = *get_cumulative_args (cum);
-  rs6000_function_arg_advance_1 (&next_cum, mode, type, true, 0);
+  rs6000_function_arg_advance_1 (&next_cum, arg.mode, arg.type, arg.named, 0);
 
   if (DEFAULT_ABI == ABI_V4)
     {
@@ -2461,8 +2461,8 @@ setup_incoming_varargs (cumulative_args_
       first_reg_offset = next_cum.words;
       save_area = crtl->args.internal_arg_pointer;
 
-      if (targetm.calls.must_pass_in_stack (mode, type))
-	first_reg_offset += rs6000_arg_size (TYPE_MODE (type), type);
+      if (targetm.calls.must_pass_in_stack (arg.mode, arg.type))
+	first_reg_offset += rs6000_arg_size (TYPE_MODE (arg.type), arg.type);
     }
 
   set = get_varargs_alias_set ();
Index: gcc/config/sh/sh.c
===================================================================
--- gcc/config/sh/sh.c	2019-08-19 15:58:28.446077464 +0100
+++ gcc/config/sh/sh.c	2019-08-19 15:58:34.846031154 +0100
@@ -280,8 +280,8 @@ static bool sh_function_value_regno_p (c
 static rtx sh_libcall_value (machine_mode, const_rtx);
 static bool sh_return_in_memory (const_tree, const_tree);
 static rtx sh_builtin_saveregs (void);
-static void sh_setup_incoming_varargs (cumulative_args_t, machine_mode,
-				       tree, int *, int);
+static void sh_setup_incoming_varargs (cumulative_args_t,
+				       const function_arg_info &, int *, int);
 static bool sh_strict_argument_naming (cumulative_args_t);
 static bool sh_pretend_outgoing_varargs_named (cumulative_args_t);
 static void sh_atomic_assign_expand_fenv (tree *, tree *, tree *);
@@ -8184,8 +8184,7 @@ sh_return_in_memory (const_tree type, co
    function that tell if a function uses varargs or stdarg.  */
 static void
 sh_setup_incoming_varargs (cumulative_args_t ca,
-			   machine_mode mode,
-			   tree type,
+			   const function_arg_info &arg,
 			   int *pretend_arg_size,
 			   int second_time ATTRIBUTE_UNUSED)
 {
@@ -8194,10 +8193,9 @@ sh_setup_incoming_varargs (cumulative_ar
     {
       int named_parm_regs, anon_parm_regs;
 
-      named_parm_regs = (sh_round_reg (*get_cumulative_args (ca), mode)
-			 + (mode == BLKmode
-			    ? CEIL (int_size_in_bytes (type), UNITS_PER_WORD)
-			    : CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD)));
+      named_parm_regs = (sh_round_reg (*get_cumulative_args (ca), arg.mode)
+			 + CEIL (arg.promoted_size_in_bytes (),
+				 UNITS_PER_WORD));
       anon_parm_regs = NPARM_REGS (SImode) - named_parm_regs;
       if (anon_parm_regs > 0)
 	*pretend_arg_size = anon_parm_regs * 4;
Index: gcc/config/spu/spu.c
===================================================================
--- gcc/config/spu/spu.c	2019-08-19 15:58:28.446077464 +0100
+++ gcc/config/spu/spu.c	2019-08-19 15:58:34.846031154 +0100
@@ -4089,8 +4089,9 @@ spu_gimplify_va_arg_expr (tree valist, t
    in the stack then save no registers.  Set pretend_args_size to the
    amount of space needed to save the registers. */
 static void
-spu_setup_incoming_varargs (cumulative_args_t cum, machine_mode mode,
-			    tree type, int *pretend_size, int no_rtl)
+spu_setup_incoming_varargs (cumulative_args_t cum,
+			    const function_arg_info &arg,
+			    int *pretend_size, int no_rtl)
 {
   if (!no_rtl)
     {
@@ -4101,7 +4102,8 @@ spu_setup_incoming_varargs (cumulative_a
 
       /* cum currently points to the last named argument, we want to
          start at the next argument. */
-      spu_function_arg_advance (pack_cumulative_args (&ncum), mode, type, true);
+      spu_function_arg_advance (pack_cumulative_args (&ncum),
+				arg.mode, arg.type, arg.named);
 
       offset = -STACK_POINTER_OFFSET;
       for (regno = ncum; regno < MAX_REGISTER_ARGS; regno++)
Index: gcc/config/tilegx/tilegx.c
===================================================================
--- gcc/config/tilegx/tilegx.c	2019-08-19 15:58:28.446077464 +0100
+++ gcc/config/tilegx/tilegx.c	2019-08-19 15:58:34.850031127 +0100
@@ -390,8 +390,8 @@ tilegx_va_start (tree valist, rtx nextar
 /* Implement TARGET_SETUP_INCOMING_VARARGS.  */
 static void
 tilegx_setup_incoming_varargs (cumulative_args_t cum,
-			       machine_mode mode,
-			       tree type, int *pretend_args, int no_rtl)
+			       const function_arg_info &arg,
+			       int *pretend_args, int no_rtl)
 {
   CUMULATIVE_ARGS local_cum = *get_cumulative_args (cum);
   int first_reg;
@@ -400,7 +400,7 @@ tilegx_setup_incoming_varargs (cumulativ
      argument.  Advance a local copy of CUM past the last "real" named
      argument, to find out how many registers are left over.  */
   targetm.calls.function_arg_advance (pack_cumulative_args (&local_cum),
-				      mode, type, true);
+				      arg.mode, arg.type, arg.named);
   first_reg = local_cum;
 
   if (local_cum < TILEGX_NUM_ARG_REGS)
Index: gcc/config/tilepro/tilepro.c
===================================================================
--- gcc/config/tilepro/tilepro.c	2019-08-19 15:58:28.446077464 +0100
+++ gcc/config/tilepro/tilepro.c	2019-08-19 15:58:34.850031127 +0100
@@ -342,8 +342,8 @@ tilepro_va_start (tree valist, rtx nexta
 /* Implement TARGET_SETUP_INCOMING_VARARGS.  */
 static void
 tilepro_setup_incoming_varargs (cumulative_args_t cum,
-				machine_mode mode,
-				tree type, int *pretend_args, int no_rtl)
+				const function_arg_info &arg,
+				int *pretend_args, int no_rtl)
 {
   CUMULATIVE_ARGS local_cum = *get_cumulative_args (cum);
   int first_reg;
@@ -352,7 +352,7 @@ tilepro_setup_incoming_varargs (cumulati
      argument.  Advance a local copy of CUM past the last "real" named
      argument, to find out how many registers are left over.  */
   targetm.calls.function_arg_advance (pack_cumulative_args (&local_cum),
-				      mode, type, true);
+				      arg.mode, arg.type, arg.named);
   first_reg = local_cum;
 
   if (local_cum < TILEPRO_NUM_ARG_REGS)
Index: gcc/config/visium/visium.c
===================================================================
--- gcc/config/visium/visium.c	2019-08-19 15:58:28.446077464 +0100
+++ gcc/config/visium/visium.c	2019-08-19 15:58:34.850031127 +0100
@@ -175,8 +175,8 @@ static rtx visium_function_value (const_
 static rtx visium_libcall_value (machine_mode, const_rtx);
 
 static void visium_setup_incoming_varargs (cumulative_args_t,
-					   machine_mode,
-					   tree, int *, int);
+					   const function_arg_info &,
+					   int *, int);
 
 static void visium_va_start (tree valist, rtx nextarg);
 
@@ -1460,8 +1460,7 @@ visium_libcall_value (machine_mode mode,
 
 static void
 visium_setup_incoming_varargs (cumulative_args_t pcum_v,
-			       machine_mode mode,
-			       tree type,
+			       const function_arg_info &arg,
 			       int *pretend_size ATTRIBUTE_UNUSED,
 			       int no_rtl)
 {
@@ -1487,7 +1486,8 @@ visium_setup_incoming_varargs (cumulativ
   /* The caller has advanced ARGS_SO_FAR up to, but not beyond, the last named
      argument.  Advance a local copy of ARGS_SO_FAR past the last "real" named
      argument, to find out how many registers are left over.  */
-  TARGET_FUNCTION_ARG_ADVANCE (local_args_so_far, mode, type, 1);
+  TARGET_FUNCTION_ARG_ADVANCE (local_args_so_far, arg.mode,
+			       arg.type, arg.named);
 
   /* Find how many registers we need to save.  */
   locargs = get_cumulative_args (local_args_so_far);
Index: gcc/function.c
===================================================================
--- gcc/function.c	2019-08-19 15:58:28.450077433 +0100
+++ gcc/function.c	2019-08-19 15:58:34.850031127 +0100
@@ -2485,9 +2485,9 @@ assign_parms_setup_varargs (struct assig
 {
   int varargs_pretend_bytes = 0;
 
-  targetm.calls.setup_incoming_varargs (all->args_so_far,
-					data->promoted_mode,
-					data->passed_type,
+  function_arg_info last_named_arg (data->passed_type, data->promoted_mode,
+				    /*named=*/true);
+  targetm.calls.setup_incoming_varargs (all->args_so_far, last_named_arg,
 					&varargs_pretend_bytes, no_rtl);
 
   /* If the back-end has requested extra stack space, record how much is

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [06/13] Use function_arg_info for TARGET_FUNCTION_(INCOMING_)ARG
  2019-08-19 15:15 [00/13] Pass an argument descriptor to target hooks Richard Sandiford
                   ` (4 preceding siblings ...)
  2019-08-19 15:20 ` [05/13] Use function_arg_info for TARGET_SETUP_INCOMING_ARGS Richard Sandiford
@ 2019-08-19 15:21 ` Richard Sandiford
  2019-08-19 21:07   ` Jeff Law
  2019-08-19 15:22 ` [07/13] Use function_arg_info for TARGET_FUNCTION_ARG_ADVANCE Richard Sandiford
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 27+ messages in thread
From: Richard Sandiford @ 2019-08-19 15:21 UTC (permalink / raw)
  To: gcc-patches

This patch makes both TARGET_FUNCTION_ARG and
TARGET_FUNCTION_INCOMING_ARG take a function_arg_info.
They have to be done together since many targets use the
same function for both.

The hooks are passed the promoted mode instead of the original type mode.


2019-08-19  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	* target.def (function_arg, function_incoming_arg): Take a
	function_arg_info instead of a mode, tree and named flag.
	* doc/tm.texi: Regenerate.
	* targhooks.h (default_function_arg): Take a function_arg_info
	instead of a mode, tree and named flag.
	(default_function_incoming_arg): Likewise.
	* targhooks.c (default_function_arg): Likewise.
	(default_function_incoming_arg): Likewise.
	* calls.h (function_arg_info::end_marker_p): New function.
	(function_arg_info::end_marker): Likewise.
	* calls.c (prepare_call_address, initialize_argument_information)
	(expand_call, emit_library_call_value_1): Update calls to
	targetm.calls.function_arg and targetm.calls.function_incoming_arg.
	* dse.c: Include calls.h.
	(get_call_args): Update call to targetm.calls.function_arg.
	* expr.c (block_move_libcall_safe_for_call_parm): Likewise.
	* var-tracking.c (prepare_call_arguments): Likewise.
	* function.c (assign_parm_find_entry_rtl): Update call to
	targetm.calls.function_incoming_arg.
	* config/aarch64/aarch64.c (aarch64_function_arg): Take a
	function_arg_info instead of a mode, tree and named flag.
	* config/alpha/alpha.c (alpha_function_arg): Likewise.
	* config/arc/arc.c (arc_function_arg): Likewise.
	* config/arm/arm.c (arm_function_arg): Likewise.
	(cmse_func_args_or_return_in_stack): Update call accordingly.
	(arm_function_ok_for_sibcall): Likewise.
	(cmse_nonsecure_call_clear_caller_saved): Likewise.
	* config/avr/avr.c (avr_function_arg): Take a function_arg_info
	instead of a mode, tree and named flag.
	* config/bfin/bfin.c (bfin_function_arg): Likewise.
	* config/c6x/c6x.c (c6x_function_arg): Likewise.
	(c6x_call_saved_register_used): Update call accordingly.
	* config/cr16/cr16.c (cr16_function_arg): Take a function_arg_info
	instead of a mode, tree and named flag.
	* config/cris/cris.c (cris_function_arg, cris_function_incoming_arg)
	(cris_function_arg_1): Likewise.
	* config/csky/csky.c (csky_function_arg): Likewise.
	* config/epiphany/epiphany.c (epiphany_function_arg): Likewise.
	* config/fr30/fr30.c (fr30_function_arg): Likewise.
	* config/frv/frv.c (frv_function_arg, frv_function_incoming_arg)
	(frv_function_arg_1): Likewise.
	* config/ft32/ft32.c (ft32_function_arg): Likewise.
	* config/gcn/gcn.c (gcn_function_arg): Likewise.
	* config/h8300/h8300.c (h8300_function_arg): Likewise.
	* config/i386/i386.c (ix86_function_arg): Likewise.
	* config/ia64/ia64.c (ia64_function_arg, ia64_function_incoming_arg)
	(ia64_function_arg_1): Likewise.
	* config/iq2000/iq2000.c (iq2000_function_arg): Likewise.
	(iq2000_expand_prologue, iq2000_pass_by_reference): Update call
	accordingly.
	* config/lm32/lm32.c (lm32_function_arg): Take a function_arg_info
	instead of a mode, tree and named flag.
	* config/m32c/m32c.c (m32c_function_arg): Likewise.
	* config/m32r/m32r.c (m32r_function_arg): Likewise.
	* config/m68k/m68k.c (m68k_function_arg): Likewise.
	* config/mcore/mcore.c (mcore_function_arg): Likewise.
	* config/microblaze/microblaze.c (microblaze_function_arg): Likewise.
	(microblaze_expand_prologue): Update call accordingly.
	* config/mips/mips.c (mips_function_arg): Take a function_arg_info
	instead of a mode, tree and named flag.
	* config/mmix/mmix.c (mmix_function_incoming_arg, mmix_function_arg)
	(mmix_function_arg_1): Likewise.
	* config/mn10300/mn10300.c (mn10300_function_arg): Likewise.
	* config/moxie/moxie.c (moxie_function_arg): Likewise.
	* config/msp430/msp430.c (msp430_function_arg): Likewise.
	* config/nds32/nds32.c (nds32_function_arg): Likewise.
	* config/nios2/nios2.c (nios2_function_arg): Likewise.
	* config/nvptx/nvptx.c (nvptx_function_arg): Likewise.
	(nvptx_function_incoming_arg): Likewise.
	* config/or1k/or1k.c (or1k_function_arg): Likewise.
	* config/pa/pa.c (pa_function_arg): Likewise.
	* config/pdp11/pdp11.c (pdp11_function_arg): Likewise.
	* config/pru/pru.c (pru_function_arg): Likewise.
	* config/riscv/riscv.c (riscv_function_arg): Likewise.
	* config/rl78/rl78.c (rl78_function_arg): Likewise.
	* config/rs6000/rs6000-internal.h (rs6000_function_arg): Likewise.
	* config/rs6000/rs6000-call.c (rs6000_function_arg): Likewise.
	(rs6000_parm_needs_stack): Update call accordingly.
	* config/rx/rx.c (rx_function_arg): Take a function_arg_info
	instead of a mode, tree and named flag.
	* config/s390/s390.c (s390_function_arg): Likewise.
	(s390_call_saved_register_used): Update call accordingly.
	* config/sh/sh.c (sh_function_arg): Take a function_arg_info
	instead of a mode, tree and named flag.
	(sh_output_mi_thunk): Update call accordingly.
	* config/sparc/sparc.c (sparc_function_arg_1, sparc_function_arg)
	(sparc_function_incoming_arg): Take a function_arg_info instead of
	a mode, tree and named flag.
	* config/spu/spu.c (spu_function_arg): Likewise.
	* config/stormy16/stormy16.c (xstormy16_function_arg): Likewise.
	* config/tilegx/tilegx.c (tilegx_function_arg): Likewise.
	* config/tilepro/tilepro.c (tilepro_function_arg): Likewise.
	* config/v850/v850.c (v850_function_arg): Likewise.
	* config/vax/vax.c (vax_function_arg): Likewise.
	* config/visium/visium.c (visium_function_arg): Likewise.
	* config/xtensa/xtensa.c (xtensa_function_arg_1, xtensa_function_arg)
	(xtensa_function_incoming_arg): Likewise.

Index: gcc/target.def
===================================================================
--- gcc/target.def	2019-08-19 15:58:34.850031127 +0100
+++ gcc/target.def	2019-08-19 15:58:42.425976307 +0100
@@ -4732,17 +4732,9 @@ constant size shorter than an @code{int}
    argument.  */
 DEFHOOK
 (function_arg,
- "Return an RTX indicating whether a function argument is passed in a\n\
-register and if so, which register.\n\
-\n\
-The arguments are @var{ca}, which summarizes all the previous\n\
-arguments; @var{mode}, the machine mode of the argument; @var{type},\n\
-the data type of the argument as a tree node or 0 if that is not known\n\
-(which happens for C support library functions); and @var{named},\n\
-which is @code{true} for an ordinary argument and @code{false} for\n\
-nameless arguments that correspond to @samp{@dots{}} in the called\n\
-function's prototype.  @var{type} can be an incomplete type if a\n\
-syntax error has previously occurred.\n\
+ "Return an RTX indicating whether function argument @var{arg} is passed\n\
+in a register and if so, which register.  Argument @var{ca} summarizes all\n\
+the previous arguments.\n\
 \n\
 The return value is usually either a @code{reg} RTX for the hard\n\
 register in which to pass the argument, or zero to pass the argument\n\
@@ -4788,8 +4780,7 @@ is not defined and @code{TARGET_FUNCTION
 argument, the compiler will abort.  If @code{REG_PARM_STACK_SPACE} is\n\
 defined, the argument will be computed in the stack and then loaded into\n\
 a register.",
- rtx, (cumulative_args_t ca, machine_mode mode, const_tree type,
-       bool named),
+ rtx, (cumulative_args_t ca, const function_arg_info &arg),
  default_function_arg)
 
 DEFHOOK
@@ -4811,8 +4802,7 @@ so that it can be used to pass special a
 \n\
 If @code{TARGET_FUNCTION_INCOMING_ARG} is not defined,\n\
 @code{TARGET_FUNCTION_ARG} serves both purposes.",
- rtx, (cumulative_args_t ca, machine_mode mode, const_tree type,
-       bool named),
+ rtx, (cumulative_args_t ca, const function_arg_info &arg),
  default_function_incoming_arg)
 
 DEFHOOK
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	2019-08-19 15:58:34.850031127 +0100
+++ gcc/doc/tm.texi	2019-08-19 15:58:42.421976335 +0100
@@ -3961,18 +3961,10 @@ This section describes the macros which
 types of arguments are passed in registers or how they are arranged in
 the stack.
 
-@deftypefn {Target Hook} rtx TARGET_FUNCTION_ARG (cumulative_args_t @var{ca}, machine_mode @var{mode}, const_tree @var{type}, bool @var{named})
-Return an RTX indicating whether a function argument is passed in a
-register and if so, which register.
-
-The arguments are @var{ca}, which summarizes all the previous
-arguments; @var{mode}, the machine mode of the argument; @var{type},
-the data type of the argument as a tree node or 0 if that is not known
-(which happens for C support library functions); and @var{named},
-which is @code{true} for an ordinary argument and @code{false} for
-nameless arguments that correspond to @samp{@dots{}} in the called
-function's prototype.  @var{type} can be an incomplete type if a
-syntax error has previously occurred.
+@deftypefn {Target Hook} rtx TARGET_FUNCTION_ARG (cumulative_args_t @var{ca}, const function_arg_info @var{&arg})
+Return an RTX indicating whether function argument @var{arg} is passed
+in a register and if so, which register.  Argument @var{ca} summarizes all
+the previous arguments.
 
 The return value is usually either a @code{reg} RTX for the hard
 register in which to pass the argument, or zero to pass the argument
@@ -4027,7 +4019,7 @@ definition that is usually appropriate,
 documentation.
 @end deftypefn
 
-@deftypefn {Target Hook} rtx TARGET_FUNCTION_INCOMING_ARG (cumulative_args_t @var{ca}, machine_mode @var{mode}, const_tree @var{type}, bool @var{named})
+@deftypefn {Target Hook} rtx TARGET_FUNCTION_INCOMING_ARG (cumulative_args_t @var{ca}, const function_arg_info @var{&arg})
 Define this hook if the caller and callee on the target have different
 views of where arguments are passed.  Also define this hook if there are
 functions that are never directly called, but are invoked by the hardware
Index: gcc/targhooks.h
===================================================================
--- gcc/targhooks.h	2019-08-19 15:58:34.850031127 +0100
+++ gcc/targhooks.h	2019-08-19 15:58:42.425976307 +0100
@@ -151,10 +151,9 @@ extern bool hook_bool_CUMULATIVE_ARGS_tr
   (cumulative_args_t, machine_mode, const_tree, bool);
 extern HOST_WIDE_INT default_function_arg_offset (machine_mode, const_tree);
 extern pad_direction default_function_arg_padding (machine_mode, const_tree);
-extern rtx default_function_arg
-  (cumulative_args_t, machine_mode, const_tree, bool);
-extern rtx default_function_incoming_arg
-  (cumulative_args_t, machine_mode, const_tree, bool);
+extern rtx default_function_arg (cumulative_args_t, const function_arg_info &);
+extern rtx default_function_incoming_arg (cumulative_args_t,
+					  const function_arg_info &);
 extern unsigned int default_function_arg_boundary (machine_mode,
 						   const_tree);
 extern unsigned int default_function_arg_round_boundary (machine_mode,
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c	2019-08-19 15:58:34.850031127 +0100
+++ gcc/targhooks.c	2019-08-19 15:58:42.425976307 +0100
@@ -828,19 +828,13 @@ default_function_arg_padding (machine_mo
 }
 
 rtx
-default_function_arg (cumulative_args_t ca ATTRIBUTE_UNUSED,
-		      machine_mode mode ATTRIBUTE_UNUSED,
-		      const_tree type ATTRIBUTE_UNUSED,
-		      bool named ATTRIBUTE_UNUSED)
+default_function_arg (cumulative_args_t, const function_arg_info &)
 {
   gcc_unreachable ();
 }
 
 rtx
-default_function_incoming_arg (cumulative_args_t ca ATTRIBUTE_UNUSED,
-			       machine_mode mode ATTRIBUTE_UNUSED,
-			       const_tree type ATTRIBUTE_UNUSED,
-			       bool named ATTRIBUTE_UNUSED)
+default_function_incoming_arg (cumulative_args_t, const function_arg_info &)
 {
   gcc_unreachable ();
 }
Index: gcc/calls.h
===================================================================
--- gcc/calls.h	2019-08-19 15:58:28.418077667 +0100
+++ gcc/calls.h	2019-08-19 15:58:42.381976625 +0100
@@ -77,6 +77,17 @@ #define GCC_CALLS_H
     return GET_MODE_SIZE (mode);
   }
 
+  /* True if the argument represents the end of the argument list,
+     as returned by end_marker ().  */
+  bool end_marker_p () const { return mode == VOIDmode; }
+
+  /* Return a function_arg_info that represents the end of the
+     argument list.  */
+  static function_arg_info end_marker ()
+  {
+    return function_arg_info (void_type_node, /*named=*/true);
+  }
+
   /* The type of the argument, or null if not known (which is true for
      libgcc support functions).  */
   tree type;
Index: gcc/calls.c
===================================================================
--- gcc/calls.c	2019-08-19 15:58:28.418077667 +0100
+++ gcc/calls.c	2019-08-19 15:58:42.381976625 +0100
@@ -346,7 +346,8 @@ prepare_call_address (tree fndecl_or_typ
    It is zero if this call doesn't want a structure value.
 
    NEXT_ARG_REG is the rtx that results from executing
-     targetm.calls.function_arg (&args_so_far, VOIDmode, void_type_node, true)
+     targetm.calls.function_arg (&args_so_far,
+				 function_arg_info::end_marker ());
    just after all the args have had their registers assigned.
    This could be whatever you like, but normally it is the first
    arg-register beyond those used for args in this call,
@@ -2124,8 +2125,8 @@ initialize_argument_information (int num
 
       targetm.calls.warn_parameter_passing_abi (args_so_far, type);
 
-      args[i].reg = targetm.calls.function_arg (args_so_far, mode, type,
-						argpos < n_named_args);
+      function_arg_info arg (type, mode, argpos < n_named_args);
+      args[i].reg = targetm.calls.function_arg (args_so_far, arg);
 
       if (args[i].reg && CONST_INT_P (args[i].reg))
 	args[i].reg = NULL;
@@ -2135,12 +2136,10 @@ initialize_argument_information (int num
 	 arguments have to go into the incoming registers.  */
       if (targetm.calls.function_incoming_arg != targetm.calls.function_arg)
 	args[i].tail_call_reg
-	  = targetm.calls.function_incoming_arg (args_so_far, mode, type,
-						 argpos < n_named_args);
+	  = targetm.calls.function_incoming_arg (args_so_far, arg);
       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, arg);
 
@@ -4244,14 +4243,11 @@ expand_call (tree exp, rtx target, int i
       /* Set up next argument register.  For sibling calls on machines
 	 with register windows this should be the incoming register.  */
       if (pass == 0)
-	next_arg_reg = targetm.calls.function_incoming_arg (args_so_far,
-							    VOIDmode,
-							    void_type_node,
-							    true);
+	next_arg_reg = targetm.calls.function_incoming_arg
+	  (args_so_far, function_arg_info::end_marker ());
       else
-	next_arg_reg = targetm.calls.function_arg (args_so_far,
-						   VOIDmode, void_type_node,
-						   true);
+	next_arg_reg = targetm.calls.function_arg
+	  (args_so_far, function_arg_info::end_marker ());
 
       if (pass == 1 && (return_flags & ERF_RETURNS_ARG))
 	{
@@ -4869,8 +4865,7 @@ emit_library_call_value_1 (int retval, r
       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);
+      argvec[count].reg = targetm.calls.function_arg (args_so_far, ptr_arg);
       gcc_assert (targetm.calls.arg_partial_bytes (args_so_far, ptr_arg) == 0);
 
       locate_and_pad_parm (Pmode, NULL_TREE,
@@ -4953,8 +4948,7 @@ emit_library_call_value_1 (int retval, r
       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].reg = targetm.calls.function_arg (args_so_far, arg);
 
       argvec[count].partial
 	= targetm.calls.arg_partial_bytes (args_so_far, arg);
@@ -5332,7 +5326,7 @@ emit_library_call_value_1 (int retval, r
 	       original_args_size.constant, args_size.constant,
 	       struct_value_size,
 	       targetm.calls.function_arg (args_so_far,
-					   VOIDmode, void_type_node, true),
+					   function_arg_info::end_marker ()),
 	       valreg,
 	       old_inhibit_defer_pop + 1, call_fusage, flags, args_so_far);
 
Index: gcc/dse.c
===================================================================
--- gcc/dse.c	2019-07-18 09:22:13.805768620 +0100
+++ gcc/dse.c	2019-08-19 15:58:42.421976335 +0100
@@ -50,6 +50,7 @@ Software Foundation; either version 3, o
 #include "params.h"
 #include "rtl-iter.h"
 #include "cfgcleanup.h"
+#include "calls.h"
 
 /* This file contains three techniques for performing Dead Store
    Elimination (dse).
@@ -2343,7 +2344,8 @@ get_call_args (rtx call_insn, tree fn, r
       if (!is_int_mode (TYPE_MODE (TREE_VALUE (arg)), &mode))
 	return false;
 
-      reg = targetm.calls.function_arg (args_so_far, mode, NULL_TREE, true);
+      function_arg_info arg (mode, /*named=*/true);
+      reg = targetm.calls.function_arg (args_so_far, arg);
       if (!reg || !REG_P (reg) || GET_MODE (reg) != mode)
 	return false;
 
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	2019-08-19 15:58:21.746125942 +0100
+++ gcc/expr.c	2019-08-19 15:58:42.425976307 +0100
@@ -1710,8 +1710,7 @@ block_move_libcall_safe_for_call_parm (v
       {
 	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);
+	rtx tmp = targetm.calls.function_arg (args_so_far, arg_info);
 	if (!tmp || !REG_P (tmp))
 	  return false;
 	if (targetm.calls.arg_partial_bytes (args_so_far, arg_info))
Index: gcc/var-tracking.c
===================================================================
--- gcc/var-tracking.c	2019-08-19 15:58:28.450077433 +0100
+++ gcc/var-tracking.c	2019-08-19 15:58:42.425976307 +0100
@@ -6294,11 +6294,11 @@ prepare_call_arguments (basic_block bb,
 		{
 		  tree struct_addr = build_pointer_type (TREE_TYPE (type));
 		  machine_mode mode = TYPE_MODE (struct_addr);
+		  function_arg_info arg (struct_addr, /*named=*/true);
 		  rtx reg;
 		  INIT_CUMULATIVE_ARGS (args_so_far_v, type, NULL_RTX, fndecl,
 					nargs + 1);
-		  reg = targetm.calls.function_arg (args_so_far, mode,
-						    struct_addr, true);
+		  reg = targetm.calls.function_arg (args_so_far, arg);
 		  targetm.calls.function_arg_advance (args_so_far, mode,
 						      struct_addr, true);
 		  if (reg == NULL_RTX)
@@ -6318,11 +6318,9 @@ prepare_call_arguments (basic_block bb,
 				      nargs);
 	      if (obj_type_ref && TYPE_ARG_TYPES (type) != void_list_node)
 		{
-		  machine_mode mode;
 		  t = TYPE_ARG_TYPES (type);
-		  mode = TYPE_MODE (TREE_VALUE (t));
-		  this_arg = targetm.calls.function_arg (args_so_far, mode,
-							 TREE_VALUE (t), true);
+		  function_arg_info arg (TREE_VALUE (t), /*named=*/true);
+		  this_arg = targetm.calls.function_arg (args_so_far, arg);
 		  if (this_arg && !REG_P (this_arg))
 		    this_arg = NULL_RTX;
 		  else if (this_arg == NULL_RTX)
@@ -6436,8 +6434,8 @@ prepare_call_arguments (basic_block bb,
 	    if (pass_by_reference (&args_so_far_v, orig_arg))
 	      argtype = build_pointer_type (argtype);
 	    machine_mode mode = TYPE_MODE (argtype);
-	    reg = targetm.calls.function_arg (args_so_far, mode,
-					      argtype, true);
+	    function_arg_info arg (argtype, /*named=*/true);
+	    reg = targetm.calls.function_arg (args_so_far, arg);
 	    if (TREE_CODE (argtype) == REFERENCE_TYPE
 		&& INTEGRAL_TYPE_P (TREE_TYPE (argtype))
 		&& reg
Index: gcc/function.c
===================================================================
--- gcc/function.c	2019-08-19 15:58:34.850031127 +0100
+++ gcc/function.c	2019-08-19 15:58:42.425976307 +0100
@@ -2517,11 +2517,9 @@ assign_parm_find_entry_rtl (struct assig
   targetm.calls.warn_parameter_passing_abi (all->args_so_far,
 					    data->passed_type);
 
-  entry_parm = targetm.calls.function_incoming_arg (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);
+  entry_parm = targetm.calls.function_incoming_arg (all->args_so_far, arg);
   if (entry_parm == 0)
     data->promoted_mode = data->passed_mode;
 
@@ -2544,9 +2542,10 @@ assign_parm_find_entry_rtl (struct assig
       if (targetm.calls.pretend_outgoing_varargs_named (all->args_so_far))
 	{
 	  rtx tem;
+	  function_arg_info named_arg (data->passed_type, data->promoted_mode,
+				       /*named=*/true);
 	  tem = targetm.calls.function_incoming_arg (all->args_so_far,
-						     data->promoted_mode,
-						     data->passed_type, true);
+						     named_arg);
 	  in_regs = tem != NULL;
 	}
     }
Index: gcc/config/aarch64/aarch64.c
===================================================================
--- gcc/config/aarch64/aarch64.c	2019-08-19 15:58:34.822031327 +0100
+++ gcc/config/aarch64/aarch64.c	2019-08-19 15:58:42.385976597 +0100
@@ -4801,16 +4801,15 @@ aarch64_layout_arg (cumulative_args_t pc
 /* Implement TARGET_FUNCTION_ARG.  */
 
 static rtx
-aarch64_function_arg (cumulative_args_t pcum_v, machine_mode mode,
-		      const_tree type, bool named)
+aarch64_function_arg (cumulative_args_t pcum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v);
   gcc_assert (pcum->pcs_variant == ARM_PCS_AAPCS64);
 
-  if (mode == VOIDmode)
+  if (arg.end_marker_p ())
     return NULL_RTX;
 
-  aarch64_layout_arg (pcum_v, mode, type, named);
+  aarch64_layout_arg (pcum_v, arg.mode, arg.type, arg.named);
   return pcum->aapcs_reg;
 }
 
Index: gcc/config/alpha/alpha.c
===================================================================
--- gcc/config/alpha/alpha.c	2019-08-19 15:58:34.822031327 +0100
+++ gcc/config/alpha/alpha.c	2019-08-19 15:58:42.385976597 +0100
@@ -5545,38 +5545,32 @@ alpha_trampoline_init (rtx m_tramp, tree
    Value is zero to push the argument on the stack,
    or a hard register in which to store the argument.
 
-   MODE is the argument's machine mode.
-   TYPE is the data type of the argument (as a tree).
-    This is null for libcalls where that information may
-    not be available.
    CUM is a variable of type CUMULATIVE_ARGS which gives info about
     the preceding args and about the function being called.
-   NAMED is nonzero if this argument is a named parameter
-    (otherwise it is an extra parameter matching an ellipsis).
+   ARG is a description of the argument.
 
    On Alpha the first 6 words of args are normally in registers
    and the rest are pushed.  */
 
 static rtx
-alpha_function_arg (cumulative_args_t cum_v, machine_mode mode,
-		    const_tree type, bool named ATTRIBUTE_UNUSED)
+alpha_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   int basereg;
   int num_args;
 
   /* Don't get confused and pass small structures in FP registers.  */
-  if (type && AGGREGATE_TYPE_P (type))
+  if (arg.aggregate_type_p ())
     basereg = 16;
   else
     {
       /* With alpha_split_complex_arg, we shouldn't see any raw complex
 	 values here.  */
-      gcc_checking_assert (!COMPLEX_MODE_P (mode));
+      gcc_checking_assert (!COMPLEX_MODE_P (arg.mode));
 
       /* Set up defaults for FP operands passed in FP registers, and
 	 integral operands passed in integer registers.  */
-      if (TARGET_FPREGS && GET_MODE_CLASS (mode) == MODE_FLOAT)
+      if (TARGET_FPREGS && GET_MODE_CLASS (arg.mode) == MODE_FLOAT)
 	basereg = 32 + 16;
       else
 	basereg = 16;
@@ -5586,12 +5580,12 @@ alpha_function_arg (cumulative_args_t cu
      the two platforms, so we can't avoid conditional compilation.  */
 #if TARGET_ABI_OPEN_VMS
     {
-      if (mode == VOIDmode)
+      if (arg.end_marker_p ())
 	return alpha_arg_info_reg_val (*cum);
 
       num_args = cum->num_args;
       if (num_args >= 6
-	  || targetm.calls.must_pass_in_stack (mode, type))
+	  || targetm.calls.must_pass_in_stack (arg.mode, arg.type))
 	return NULL_RTX;
     }
 #elif TARGET_ABI_OSF
@@ -5600,17 +5594,16 @@ alpha_function_arg (cumulative_args_t cu
 	return NULL_RTX;
       num_args = *cum;
 
-      /* VOID is passed as a special flag for "last argument".  */
-      if (type == void_type_node)
+      if (arg.end_marker_p ())
 	basereg = 16;
-      else if (targetm.calls.must_pass_in_stack (mode, type))
+      else if (targetm.calls.must_pass_in_stack (arg.mode, arg.type))
 	return NULL_RTX;
     }
 #else
 #error Unhandled ABI
 #endif
 
-  return gen_rtx_REG (mode, num_args + basereg);
+  return gen_rtx_REG (arg.mode, num_args + basereg);
 }
 
 /* Update the data in CUM to advance over an argument
Index: gcc/config/arc/arc.c
===================================================================
--- gcc/config/arc/arc.c	2019-08-19 15:58:34.826031299 +0100
+++ gcc/config/arc/arc.c	2019-08-19 15:58:42.389976569 +0100
@@ -6449,63 +6449,27 @@ arc_arg_partial_bytes (cumulative_args_t
   return ret;
 }
 
-/* This function is used to control a function argument is passed in a
-   register, and which register.
-
-   The arguments are CUM, of type CUMULATIVE_ARGS, which summarizes
-   (in a way defined by INIT_CUMULATIVE_ARGS and FUNCTION_ARG_ADVANCE)
-   all of the previous arguments so far passed in registers; MODE, the
-   machine mode of the argument; TYPE, the data type of the argument
-   as a tree node or 0 if that is not known (which happens for C
-   support library functions); and NAMED, which is 1 for an ordinary
-   argument and 0 for nameless arguments that correspond to `...' in
-   the called function's prototype.
-
-   The returned value should either be a `reg' RTX for the hard
-   register in which to pass the argument, or zero to pass the
-   argument on the stack.
-
-   For machines like the Vax and 68000, where normally all arguments
-   are pushed, zero suffices as a definition.
-
-   The usual way to make the ANSI library `stdarg.h' work on a machine
-   where some arguments are usually passed in registers, is to cause
-   nameless arguments to be passed on the stack instead.  This is done
-   by making the function return 0 whenever NAMED is 0.
-
-   You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the
-   definition of this function to determine if this argument is of a
-   type that must be passed in the stack.  If `REG_PARM_STACK_SPACE'
-   is not defined and the function returns non-zero for such an
-   argument, the compiler will abort.  If `REG_PARM_STACK_SPACE' is
-   defined, the argument will be computed in the stack and then loaded
-   into a register.
-
-   The function is used to implement macro FUNCTION_ARG.  */
-/* On the ARC the first MAX_ARC_PARM_REGS args are normally in registers
-   and the rest are pushed.  */
+/* Implement TARGET_FUNCTION_ARG.  On the ARC the first MAX_ARC_PARM_REGS
+   args are normally in registers and the rest are pushed.  */
 
 static rtx
-arc_function_arg (cumulative_args_t cum_v,
-		  machine_mode mode,
-		  const_tree type ATTRIBUTE_UNUSED,
-		  bool named ATTRIBUTE_UNUSED)
+arc_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   int arg_num = *cum;
   rtx ret;
   const char *debstr ATTRIBUTE_UNUSED;
 
-  arg_num = ROUND_ADVANCE_CUM (arg_num, mode, type);
+  arg_num = ROUND_ADVANCE_CUM (arg_num, arg.mode, arg.type);
   /* Return a marker for use in the call instruction.  */
-  if (mode == VOIDmode)
+  if (arg.end_marker_p ())
     {
       ret = const0_rtx;
       debstr = "<0>";
     }
   else if (GPR_REST_ARG_REGS (arg_num) > 0)
     {
-      ret = gen_rtx_REG (mode, arg_num);
+      ret = gen_rtx_REG (arg.mode, arg_num);
       debstr = reg_names [arg_num];
     }
   else
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c	2019-08-19 15:58:34.830031272 +0100
+++ gcc/config/arm/arm.c	2019-08-19 15:58:42.393976538 +0100
@@ -189,8 +189,7 @@ 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,
 				  const function_arg_info &);
-static rtx arm_function_arg (cumulative_args_t, machine_mode,
-			     const_tree, bool);
+static rtx arm_function_arg (cumulative_args_t, const function_arg_info &);
 static void arm_function_arg_advance (cumulative_args_t, machine_mode,
 				      const_tree, bool);
 static pad_direction arm_function_arg_padding (machine_mode, const_tree);
@@ -6658,14 +6657,9 @@ arm_needs_doubleword_align (machine_mode
    Value is zero to push the argument on the stack,
    or a hard register in which to store the argument.
 
-   MODE is the argument's machine mode.
-   TYPE is the data type of the argument (as a tree).
-    This is null for libcalls where that information may
-    not be available.
    CUM is a variable of type CUMULATIVE_ARGS which gives info about
     the preceding args and about the function being called.
-   NAMED is nonzero if this argument is a named parameter
-    (otherwise it is an extra parameter matching an ellipsis).
+   ARG is a description of the argument.
 
    On the ARM, normally the first 16 bytes are passed in registers r0-r3; all
    other arguments are passed on the stack.  If (NAMED == 0) (which happens
@@ -6674,31 +6668,31 @@ arm_needs_doubleword_align (machine_mode
    indeed make it pass in the stack if necessary).  */
 
 static rtx
-arm_function_arg (cumulative_args_t pcum_v, machine_mode mode,
-		  const_tree type, bool named)
+arm_function_arg (cumulative_args_t pcum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v);
   int nregs;
 
   /* Handle the special case quickly.  Pick an arbitrary value for op2 of
      a call insn (op3 of a call_value insn).  */
-  if (mode == VOIDmode)
+  if (arg.end_marker_p ())
     return const0_rtx;
 
   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_reg;
     }
 
   /* Varargs vectors are treated the same as long long.
      named_count avoids having to change the way arm handles 'named' */
   if (TARGET_IWMMXT_ABI
-      && arm_vector_mode_supported_p (mode)
+      && arm_vector_mode_supported_p (arg.mode)
       && pcum->named_count > pcum->nargs + 1)
     {
       if (pcum->iwmmxt_nregs <= 9)
-	return gen_rtx_REG (mode, pcum->iwmmxt_nregs + FIRST_IWMMXT_REGNUM);
+	return gen_rtx_REG (arg.mode,
+			    pcum->iwmmxt_nregs + FIRST_IWMMXT_REGNUM);
       else
 	{
 	  pcum->can_split = false;
@@ -6709,16 +6703,16 @@ arm_function_arg (cumulative_args_t pcum
   /* Put doubleword aligned quantities in even register pairs.  */
   if ((pcum->nregs & 1) && ARM_DOUBLEWORD_ALIGN)
     {
-      int res = arm_needs_doubleword_align (mode, type);
+      int res = arm_needs_doubleword_align (arg.mode, arg.type);
       if (res < 0 && warn_psabi)
 	inform (input_location, "parameter passing for argument of type "
-		"%qT changed in GCC 7.1", type);
+		"%qT changed in GCC 7.1", arg.type);
       else if (res > 0)
 	{
 	  pcum->nregs++;
 	  if (res > 1 && warn_psabi)
 	    inform (input_location, "parameter passing for argument of type "
-		    "%qT changed in GCC 9.1", type);
+		    "%qT changed in GCC 9.1", arg.type);
 	}
     }
 
@@ -6728,12 +6722,12 @@ arm_function_arg (cumulative_args_t pcum
   if (pcum->can_split)
     nregs = 1;
   else
-    nregs = ARM_NUM_REGS2 (mode, type);
+    nregs = ARM_NUM_REGS2 (arg.mode, arg.type);
 
-  if (!named || pcum->nregs + nregs > NUM_ARG_REGS)
+  if (!arg.named || pcum->nregs + nregs > NUM_ARG_REGS)
     return NULL_RTX;
 
-  return gen_rtx_REG (mode, pcum->nregs);
+  return gen_rtx_REG (arg.mode, pcum->nregs);
 }
 
 static unsigned int
@@ -6999,7 +6993,7 @@ cmse_func_args_or_return_in_stack (tree
       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);
+      arg_rtx = arm_function_arg (args_so_far, arg);
       if (!arg_rtx || arm_arg_partial_bytes (args_so_far, arg))
 	{
 	  error ("%qE attribute not available to functions with arguments "
@@ -7387,7 +7381,8 @@ arm_function_ok_for_sibcall (tree decl,
 	    arm_function_arg_advance (cum_v, TYPE_MODE (type), type, true);
 	}
 
-      if (!arm_function_arg (cum_v, SImode, integer_type_node, true))
+      function_arg_info arg (integer_type_node, /*named=*/true);
+      if (!arm_function_arg (cum_v, arg))
 	return false;
     }
 
@@ -17451,12 +17446,12 @@ cmse_nonsecure_call_clear_caller_saved (
 	      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);
+	      arg_rtx = arm_function_arg (args_so_far, arg);
 	      gcc_assert (REG_P (arg_rtx));
 	      to_clear_args_mask
 		= compute_not_to_clear_mask (arg_type, arg_rtx,
Index: gcc/config/avr/avr.c
===================================================================
--- gcc/config/avr/avr.c	2019-08-13 22:35:11.725252284 +0100
+++ gcc/config/avr/avr.c	2019-08-19 15:58:42.397976511 +0100
@@ -3388,14 +3388,13 @@ avr_num_arg_regs (machine_mode mode, con
    in a register, and which register.  */
 
 static rtx
-avr_function_arg (cumulative_args_t cum_v, machine_mode mode,
-                  const_tree type, bool named ATTRIBUTE_UNUSED)
+avr_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
-  int bytes = avr_num_arg_regs (mode, type);
+  int bytes = avr_num_arg_regs (arg.mode, arg.type);
 
   if (cum->nregs && bytes <= cum->nregs)
-    return gen_rtx_REG (mode, cum->regno - bytes);
+    return gen_rtx_REG (arg.mode, cum->regno - bytes);
 
   return NULL_RTX;
 }
Index: gcc/config/bfin/bfin.c
===================================================================
--- gcc/config/bfin/bfin.c	2019-08-19 15:58:34.830031272 +0100
+++ gcc/config/bfin/bfin.c	2019-08-19 15:58:42.397976511 +0100
@@ -1682,24 +1682,17 @@ bfin_function_arg_advance (cumulative_ar
    Value is zero to push the argument on the stack,
    or a hard register in which to store the argument.
 
-   MODE is the argument's machine mode.
-   TYPE is the data type of the argument (as a tree).
-    This is null for libcalls where that information may
-    not be available.
    CUM is a variable of type CUMULATIVE_ARGS which gives info about
     the preceding args and about the function being called.
-   NAMED is nonzero if this argument is a named parameter
-    (otherwise it is an extra parameter matching an ellipsis).  */
+   ARG is a description of the argument.  */
 
 static rtx
-bfin_function_arg (cumulative_args_t cum_v, machine_mode mode,
-		   const_tree type, bool named ATTRIBUTE_UNUSED)
+bfin_function_arg (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) : GET_MODE_SIZE (mode);
+  int bytes = arg.promoted_size_in_bytes ();
 
-  if (mode == VOIDmode)
+  if (arg.end_marker_p ())
     /* Compute operand 2 of the call insn.  */
     return GEN_INT (cum->call_cookie);
 
@@ -1707,7 +1700,7 @@ bfin_function_arg (cumulative_args_t cum
     return NULL_RTX;
 
   if (cum->nregs)
-    return gen_rtx_REG (mode, *(cum->arg_regs));
+    return gen_rtx_REG (arg.mode, *(cum->arg_regs));
 
   return NULL_RTX;
 }
Index: gcc/config/c6x/c6x.c
===================================================================
--- gcc/config/c6x/c6x.c	2019-08-19 15:58:28.430077578 +0100
+++ gcc/config/c6x/c6x.c	2019-08-19 15:58:42.397976511 +0100
@@ -499,16 +499,15 @@ c6x_init_cumulative_args (CUMULATIVE_ARG
     }
 }
 
-/* Implements the macro FUNCTION_ARG defined in c6x.h.  */
+/* Implement TARGET_FUNCTION_ARG.  */
 
 static rtx
-c6x_function_arg (cumulative_args_t cum_v, machine_mode mode,
-		  const_tree type, bool named ATTRIBUTE_UNUSED)
+c6x_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   if (cum->count >= cum->nregs)
     return NULL_RTX;
-  if (type)
+  if (tree type = arg.type)
     {
       HOST_WIDE_INT size = int_size_in_bytes (type);
       if (TARGET_BIG_ENDIAN && AGGREGATE_TYPE_P (type))
@@ -519,11 +518,11 @@ c6x_function_arg (cumulative_args_t cum_
 	      rtx reg2 = gen_rtx_REG (SImode, argument_registers[cum->count]);
 	      rtvec vec = gen_rtvec (2, gen_rtx_EXPR_LIST (VOIDmode, reg1, const0_rtx),
 				     gen_rtx_EXPR_LIST (VOIDmode, reg2, GEN_INT (4)));
-	      return gen_rtx_PARALLEL (mode, vec);
+	      return gen_rtx_PARALLEL (arg.mode, vec);
 	    }
 	}
     }
-  return gen_rtx_REG (mode, argument_registers[cum->count]);
+  return gen_rtx_REG (arg.mode, argument_registers[cum->count]);
 }
 
 static void
@@ -1134,7 +1133,8 @@ c6x_call_saved_register_used (tree call_
  	  type = build_pointer_type (type);
  	}
 
-       parm_rtx = c6x_function_arg (cum, mode, type, 0);
+       function_arg_info arg (type, mode, /*named=*/false);
+       parm_rtx = c6x_function_arg (cum, arg);
 
        c6x_function_arg_advance (cum, mode, type, 0);
 
Index: gcc/config/cr16/cr16.c
===================================================================
--- gcc/config/cr16/cr16.c	2019-03-18 12:24:58.927434152 +0000
+++ gcc/config/cr16/cr16.c	2019-08-19 15:58:42.397976511 +0100
@@ -592,10 +592,9 @@ enough_regs_for_param (CUMULATIVE_ARGS *
   return 0;
 }
 
-/* Implements the macro FUNCTION_ARG defined in cr16.h.  */
+/* Implement TARGET_FUNCTION_ARG.  */
 static rtx
-cr16_function_arg (cumulative_args_t cum_v, machine_mode mode,
-		   const_tree type, bool named ATTRIBUTE_UNUSED)
+cr16_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   cum->last_parm_in_reg = 0;
@@ -604,20 +603,20 @@ cr16_function_arg (cumulative_args_t cum
      had their registers assigned. The rtx that function_arg returns from 
      this type is supposed to pass to 'gen_call' but currently it is not 
      implemented.  */
-  if (type == void_type_node)
+  if (arg.end_marker_p ())
     return NULL_RTX;
 
-  if (targetm.calls.must_pass_in_stack (mode, type) || (cum->ints < 0))
+  if (targetm.calls.must_pass_in_stack (arg.mode, arg.type) || (cum->ints < 0))
     return NULL_RTX;
 
-  if (mode == BLKmode)
+  if (arg.mode == BLKmode)
     {
       /* Enable structures that need padding bytes at the end to pass to a
          function in registers.  */
-      if (enough_regs_for_param (cum, type, mode) != 0)
+      if (enough_regs_for_param (cum, arg.type, arg.mode) != 0)
 	{
 	  cum->last_parm_in_reg = 1;
-	  return gen_rtx_REG (mode, MIN_REG_FOR_PASSING_ARGS + cum->ints);
+	  return gen_rtx_REG (arg.mode, MIN_REG_FOR_PASSING_ARGS + cum->ints);
 	}
     }
 
@@ -625,10 +624,10 @@ cr16_function_arg (cumulative_args_t cum
     return NULL_RTX;
   else
     {
-      if (enough_regs_for_param (cum, type, mode) != 0)
+      if (enough_regs_for_param (cum, arg.type, arg.mode) != 0)
 	{
 	  cum->last_parm_in_reg = 1;
-	  return gen_rtx_REG (mode, MIN_REG_FOR_PASSING_ARGS + cum->ints);
+	  return gen_rtx_REG (arg.mode, MIN_REG_FOR_PASSING_ARGS + cum->ints);
 	}
     }
 
Index: gcc/config/cris/cris.c
===================================================================
--- gcc/config/cris/cris.c	2019-08-19 15:58:34.834031241 +0100
+++ gcc/config/cris/cris.c	2019-08-19 15:58:42.397976511 +0100
@@ -144,10 +144,9 @@ static bool cris_pass_by_reference (cumu
 				    const function_arg_info &);
 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_arg (cumulative_args_t, const function_arg_info &);
 static rtx cris_function_incoming_arg (cumulative_args_t,
-				       machine_mode, const_tree, bool);
+				       const function_arg_info &);
 static void cris_function_arg_advance (cumulative_args_t, machine_mode,
 				       const_tree, bool);
 static rtx_insn *cris_md_asm_adjust (vec<rtx> &, vec<rtx> &,
@@ -4121,15 +4120,13 @@ cris_arg_partial_bytes (cumulative_args_
 }
 
 static rtx
-cris_function_arg_1 (cumulative_args_t ca_v,
-		     machine_mode mode ATTRIBUTE_UNUSED,
-		     const_tree type ATTRIBUTE_UNUSED,
-		     bool named, bool incoming)
+cris_function_arg_1 (cumulative_args_t ca_v, const function_arg_info &arg,
+		     bool incoming)
 {
   const CUMULATIVE_ARGS *ca = get_cumulative_args (ca_v);
 
-  if ((!incoming || named) && ca->regs < CRIS_MAX_ARGS_IN_REGS)
-    return gen_rtx_REG (mode, CRIS_FIRST_ARG_REG + ca->regs);
+  if ((!incoming || arg.named) && ca->regs < CRIS_MAX_ARGS_IN_REGS)
+    return gen_rtx_REG (arg.mode, CRIS_FIRST_ARG_REG + ca->regs);
   else
     return NULL_RTX;
 }
@@ -4138,10 +4135,9 @@ cris_function_arg_1 (cumulative_args_t c
    The void_type_node is sent as a "closing" call.  */
 
 static rtx
-cris_function_arg (cumulative_args_t ca, machine_mode mode,
-		   const_tree type, bool named)
+cris_function_arg (cumulative_args_t ca, const function_arg_info &arg)
 {
-  return cris_function_arg_1 (ca, mode, type, named, false);
+  return cris_function_arg_1 (ca, arg, false);
 }
 
 /* Worker function for TARGET_FUNCTION_INCOMING_ARG.
@@ -4149,13 +4145,12 @@ cris_function_arg (cumulative_args_t ca,
    The differences between this and the previous, is that this one checks
    that an argument is named, since incoming stdarg/varargs arguments are
    pushed onto the stack, and we don't have to check against the "closing"
-   void_type_node TYPE parameter.  */
+   function_arg_info::end_marker parameter.  */
 
 static rtx
-cris_function_incoming_arg (cumulative_args_t ca, machine_mode mode,
-			    const_tree type, bool named)
+cris_function_incoming_arg (cumulative_args_t ca, const function_arg_info &arg)
 {
-  return cris_function_arg_1 (ca, mode, type, named, true);
+  return cris_function_arg_1 (ca, arg, true);
 }
 
 /* Worker function for TARGET_FUNCTION_ARG_ADVANCE.  */
Index: gcc/config/csky/csky.c
===================================================================
--- gcc/config/csky/csky.c	2019-08-19 15:58:34.834031241 +0100
+++ gcc/config/csky/csky.c	2019-08-19 15:58:42.401976480 +0100
@@ -1784,23 +1784,16 @@ csky_initial_elimination_offset (int fro
    Value is zero to push the argument on the stack,
    or a hard register in which to store the argument.
 
-   MODE is the argument's machine mode.
-   TYPE is the data type of the argument (as a tree).
-    This is null for libcalls where that information may
-    not be available.
    CUM is a variable of type CUMULATIVE_ARGS which gives info about
     the preceding args and about the function being called.
-   NAMED is nonzero if this argument is a named parameter
-    (otherwise it is an extra parameter matching an ellipsis).  */
+   ARG is a description of the argument.  */
 static rtx
-csky_function_arg (cumulative_args_t pcum_v, machine_mode mode,
-		   const_tree type ATTRIBUTE_UNUSED,
-		   bool named ATTRIBUTE_UNUSED)
+csky_function_arg (cumulative_args_t pcum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v);
 
   if (*pcum < CSKY_NPARM_REGS)
-    return gen_rtx_REG (mode, CSKY_FIRST_PARM_REGNUM + *pcum);
+    return gen_rtx_REG (arg.mode, CSKY_FIRST_PARM_REGNUM + *pcum);
 
   return NULL_RTX;
 }
Index: gcc/config/epiphany/epiphany.c
===================================================================
--- gcc/config/epiphany/epiphany.c	2019-08-19 15:58:34.834031241 +0100
+++ gcc/config/epiphany/epiphany.c	2019-08-19 15:58:42.401976480 +0100
@@ -2254,24 +2254,18 @@ epiphany_conditional_register_usage (voi
    Value is zero to push the argument on the stack,
    or a hard register in which to store the argument.
 
-   MODE is the argument's machine mode.
-   TYPE is the data type of the argument (as a tree).
-    This is null for libcalls where that information may
-    not be available.
    CUM is a variable of type CUMULATIVE_ARGS which gives info about
     the preceding args and about the function being called.
-   NAMED is nonzero if this argument is a named parameter
-    (otherwise it is an extra parameter matching an ellipsis).  */
+   ARG is a description of the argument.  */
 /* On the EPIPHANY the first MAX_EPIPHANY_PARM_REGS args are normally in
    registers and the rest are pushed.  */
 static rtx
-epiphany_function_arg (cumulative_args_t cum_v, machine_mode mode,
-		       const_tree type, bool named ATTRIBUTE_UNUSED)
+epiphany_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS cum = *get_cumulative_args (cum_v);
 
-  if (PASS_IN_REG_P (cum, mode, type))
-    return gen_rtx_REG (mode, ROUND_ADVANCE_CUM (cum, mode, type));
+  if (PASS_IN_REG_P (cum, arg.mode, arg.type))
+    return gen_rtx_REG (arg.mode, ROUND_ADVANCE_CUM (cum, arg.mode, arg.type));
   return 0;
 }
 
Index: gcc/config/fr30/fr30.c
===================================================================
--- gcc/config/fr30/fr30.c	2019-08-19 15:58:34.834031241 +0100
+++ gcc/config/fr30/fr30.c	2019-08-19 15:58:42.401976480 +0100
@@ -119,8 +119,7 @@ static void fr30_setup_incoming_varargs
 static bool fr30_must_pass_in_stack (machine_mode, const_tree);
 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 rtx fr30_function_arg (cumulative_args_t, const function_arg_info &);
 static void fr30_function_arg_advance (cumulative_args_t, machine_mode,
 				       const_tree, bool);
 static bool fr30_frame_pointer_required (void);
@@ -800,17 +799,16 @@ fr30_arg_partial_bytes (cumulative_args_
 }
 
 static rtx
-fr30_function_arg (cumulative_args_t cum_v, machine_mode mode,
-		   const_tree type, bool named)
+fr30_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
-  if (!named
-      || fr30_must_pass_in_stack (mode, type)
+  if (!arg.named
+      || fr30_must_pass_in_stack (arg.mode, arg.type)
       || *cum >= FR30_NUM_ARG_REGS)
     return NULL_RTX;
   else
-    return gen_rtx_REG (mode, *cum + FIRST_ARG_REGNUM);
+    return gen_rtx_REG (arg.mode, *cum + FIRST_ARG_REGNUM);
 }
 
 /* A C statement (sans semicolon) to update the summarizer variable CUM to
Index: gcc/config/frv/frv.c
===================================================================
--- gcc/config/frv/frv.c	2019-08-19 15:58:34.834031241 +0100
+++ gcc/config/frv/frv.c	2019-08-19 15:58:42.401976480 +0100
@@ -382,10 +382,9 @@ static rtx frv_struct_value_rtx			(tree,
 static bool frv_must_pass_in_stack (machine_mode mode, const_tree type);
 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,
-				      const_tree, bool);
+static rtx frv_function_arg (cumulative_args_t, const function_arg_info &);
+static rtx frv_function_incoming_arg (cumulative_args_t,
+				      const function_arg_info &);
 static void frv_function_arg_advance (cumulative_args_t, machine_mode,
 				       const_tree, bool);
 static unsigned int frv_function_arg_boundary	(machine_mode,
@@ -3099,13 +3098,12 @@ frv_function_arg_boundary (machine_mode
 }
 
 static rtx
-frv_function_arg_1 (cumulative_args_t cum_v, machine_mode mode,
-		    const_tree type ATTRIBUTE_UNUSED, bool named,
+frv_function_arg_1 (cumulative_args_t cum_v, const function_arg_info &arg,
 		    bool incoming ATTRIBUTE_UNUSED)
 {
   const CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
-  machine_mode xmode = (mode == BLKmode) ? SImode : mode;
+  machine_mode xmode = (arg.mode == BLKmode) ? SImode : arg.mode;
   int arg_num = *cum;
   rtx ret;
   const char *debstr;
@@ -3132,23 +3130,22 @@ frv_function_arg_1 (cumulative_args_t cu
   if (TARGET_DEBUG_ARG)
     fprintf (stderr,
 	     "function_arg: words = %2d, mode = %4s, named = %d, size = %3d, arg = %s\n",
-	     arg_num, GET_MODE_NAME (mode), named, GET_MODE_SIZE (mode), debstr);
+	     arg_num, GET_MODE_NAME (arg.mode), arg.named,
+	     GET_MODE_SIZE (arg.mode), debstr);
 
   return ret;
 }
 
 static rtx
-frv_function_arg (cumulative_args_t cum, machine_mode mode,
-		  const_tree type, bool named)
+frv_function_arg (cumulative_args_t cum, const function_arg_info &arg)
 {
-  return frv_function_arg_1 (cum, mode, type, named, false);
+  return frv_function_arg_1 (cum, arg, false);
 }
 
 static rtx
-frv_function_incoming_arg (cumulative_args_t cum, machine_mode mode,
-			   const_tree type, bool named)
+frv_function_incoming_arg (cumulative_args_t cum, const function_arg_info &arg)
 {
-  return frv_function_arg_1 (cum, mode, type, named, true);
+  return frv_function_arg_1 (cum, arg, true);
 }
 
 \f
Index: gcc/config/ft32/ft32.c
===================================================================
--- gcc/config/ft32/ft32.c	2019-08-19 15:58:34.834031241 +0100
+++ gcc/config/ft32/ft32.c	2019-08-19 15:58:42.401976480 +0100
@@ -657,14 +657,12 @@ ft32_fixed_condition_code_regs (unsigned
    NULL_RTX if there's no more space.  */
 
 static rtx
-ft32_function_arg (cumulative_args_t cum_v, machine_mode mode,
-                   const_tree type ATTRIBUTE_UNUSED,
-                   bool named ATTRIBUTE_UNUSED)
+ft32_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
   if (*cum < 8)
-    return gen_rtx_REG (mode, *cum);
+    return gen_rtx_REG (arg.mode, *cum);
   else
     return NULL_RTX;
 }
Index: gcc/config/gcn/gcn.c
===================================================================
--- gcc/config/gcn/gcn.c	2019-08-19 15:58:21.730126059 +0100
+++ gcc/config/gcn/gcn.c	2019-08-19 15:58:42.401976480 +0100
@@ -2255,49 +2255,48 @@ gcn_pretend_outgoing_varargs_named (cumu
    and if so, which register.  */
 
 static rtx
-gcn_function_arg (cumulative_args_t cum_v, machine_mode mode, const_tree type,
-		  bool named)
+gcn_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   if (cum->normal_function)
     {
-      if (!named || mode == VOIDmode)
+      if (!arg.named || arg.end_marker_p ())
 	return 0;
 
-      if (targetm.calls.must_pass_in_stack (mode, type))
+      if (targetm.calls.must_pass_in_stack (arg.mode, arg.type))
 	return 0;
 
       int reg_num = FIRST_PARM_REG + cum->num;
-      int num_regs = num_arg_regs (mode, type);
+      int num_regs = num_arg_regs (arg.mode, arg.type);
       if (num_regs > 0)
 	while (reg_num % num_regs != 0)
 	  reg_num++;
       if (reg_num + num_regs <= FIRST_PARM_REG + NUM_PARM_REGS)
-	return gen_rtx_REG (mode, reg_num);
+	return gen_rtx_REG (arg.mode, reg_num);
     }
   else
     {
       if (cum->num >= cum->args.nargs)
 	{
-	  cum->offset = (cum->offset + TYPE_ALIGN (type) / 8 - 1)
-	    & -(TYPE_ALIGN (type) / 8);
+	  cum->offset = (cum->offset + TYPE_ALIGN (arg.type) / 8 - 1)
+	    & -(TYPE_ALIGN (arg.type) / 8);
 	  cfun->machine->kernarg_segment_alignment
 	    = MAX ((unsigned) cfun->machine->kernarg_segment_alignment,
-		   TYPE_ALIGN (type) / 8);
+		   TYPE_ALIGN (arg.type) / 8);
 	  rtx addr = gen_rtx_REG (DImode,
 				  cum->args.reg[KERNARG_SEGMENT_PTR_ARG]);
 	  if (cum->offset)
 	    addr = gen_rtx_PLUS (DImode, addr,
 				 gen_int_mode (cum->offset, DImode));
-	  rtx mem = gen_rtx_MEM (mode, addr);
-	  set_mem_attributes (mem, const_cast<tree>(type), 1);
+	  rtx mem = gen_rtx_MEM (arg.mode, addr);
+	  set_mem_attributes (mem, arg.type, 1);
 	  set_mem_addr_space (mem, ADDR_SPACE_SCALAR_FLAT);
 	  MEM_READONLY_P (mem) = 1;
 	  return mem;
 	}
 
       int a = cum->args.order[cum->num];
-      if (mode != gcn_kernel_arg_types[a].mode)
+      if (arg.mode != gcn_kernel_arg_types[a].mode)
 	{
 	  error ("wrong type of argument %s", gcn_kernel_arg_types[a].name);
 	  return 0;
Index: gcc/config/h8300/h8300.c
===================================================================
--- gcc/config/h8300/h8300.c	2019-03-18 12:24:58.907434228 +0000
+++ gcc/config/h8300/h8300.c	2019-08-19 15:58:42.405976452 +0100
@@ -1081,17 +1081,16 @@ h8300_pr_saveall (struct cpp_reader *pfi
   pragma_saveall = 1;
 }
 
-/* If the next function argument with MODE and TYPE is to be passed in
-   a register, return a reg RTX for the hard register in which to pass
-   the argument.  CUM represents the state after the last argument.
-   If the argument is to be pushed, NULL_RTX is returned.
+/* If the next function argument ARG is to be passed in a register, return
+   a reg RTX for the hard register in which to pass the argument.  CUM
+   represents the state after the last argument.  If the argument is to
+   be pushed, NULL_RTX is returned.
 
    On the H8/300 all normal args are pushed, unless -mquickcall in which
    case the first 3 arguments are passed in registers.  */
 
 static rtx
-h8300_function_arg (cumulative_args_t cum_v, machine_mode mode,
-		    const_tree type, bool named)
+h8300_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
@@ -1119,7 +1118,7 @@ h8300_function_arg (cumulative_args_t cu
   int regpass = 0;
 
   /* Never pass unnamed arguments in registers.  */
-  if (!named)
+  if (!arg.named)
     return NULL_RTX;
 
   /* Pass 3 regs worth of data in regs when user asked on the command line.  */
@@ -1143,16 +1142,10 @@ h8300_function_arg (cumulative_args_t cu
 
   if (regpass)
     {
-      int size;
-
-      if (mode == BLKmode)
-	size = int_size_in_bytes (type);
-      else
-	size = GET_MODE_SIZE (mode);
-
+      int size = arg.promoted_size_in_bytes ();
       if (size + cum->nbytes <= regpass * UNITS_PER_WORD
 	  && cum->nbytes / UNITS_PER_WORD <= 3)
-	result = gen_rtx_REG (mode, cum->nbytes / UNITS_PER_WORD);
+	result = gen_rtx_REG (arg.mode, cum->nbytes / UNITS_PER_WORD);
     }
 
   return result;
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	2019-08-19 15:58:34.838031214 +0100
+++ gcc/config/i386/i386.c	2019-08-19 15:58:42.405976452 +0100
@@ -3206,77 +3206,69 @@ function_arg_ms_64 (const CUMULATIVE_ARG
 /* Return where to put the arguments to a function.
    Return zero to push the argument on the stack, or a hard register in which to store the argument.
 
-   MODE is the argument's machine mode.  TYPE is the data type of the
-   argument.  It is null for libcalls where that information may not be
-   available.  CUM gives information about the preceding args and about
-   the function being called.  NAMED is nonzero if this argument is a
-   named parameter (otherwise it is an extra parameter matching an
-   ellipsis).  */
+   ARG describes the argument while CUM gives information about the
+   preceding args and about the function being called.  */
 
 static rtx
-ix86_function_arg (cumulative_args_t cum_v, machine_mode omode,
-		   const_tree type, bool named)
+ix86_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
-  machine_mode mode = omode;
+  machine_mode mode = arg.mode;
   HOST_WIDE_INT bytes, words;
-  rtx arg;
+  rtx reg;
 
   if (!cum->caller && cfun->machine->func_type != TYPE_NORMAL)
     {
-      gcc_assert (type != NULL_TREE);
-      if (POINTER_TYPE_P (type))
+      gcc_assert (arg.type != NULL_TREE);
+      if (POINTER_TYPE_P (arg.type))
 	{
 	  /* This is the pointer argument.  */
-	  gcc_assert (TYPE_MODE (type) == Pmode);
+	  gcc_assert (TYPE_MODE (arg.type) == Pmode);
 	  /* It is at -WORD(AP) in the current frame in interrupt and
 	     exception handlers.  */
-	  arg = plus_constant (Pmode, arg_pointer_rtx, -UNITS_PER_WORD);
+	  reg = plus_constant (Pmode, arg_pointer_rtx, -UNITS_PER_WORD);
 	}
       else
 	{
 	  gcc_assert (cfun->machine->func_type == TYPE_EXCEPTION
-		      && TREE_CODE (type) == INTEGER_TYPE
-		      && TYPE_MODE (type) == word_mode);
+		      && TREE_CODE (arg.type) == INTEGER_TYPE
+		      && TYPE_MODE (arg.type) == word_mode);
 	  /* The error code is the word-mode integer argument at
 	     -2 * WORD(AP) in the current frame of the exception
 	     handler.  */
-	  arg = gen_rtx_MEM (word_mode,
+	  reg = gen_rtx_MEM (word_mode,
 			     plus_constant (Pmode,
 					    arg_pointer_rtx,
 					    -2 * UNITS_PER_WORD));
 	}
-      return arg;
+      return reg;
     }
 
-  if (mode == BLKmode)
-    bytes = int_size_in_bytes (type);
-  else
-    bytes = GET_MODE_SIZE (mode);
+  bytes = arg.promoted_size_in_bytes ();
   words = CEIL (bytes, UNITS_PER_WORD);
 
   /* To simplify the code below, represent vector types with a vector mode
      even if MMX/SSE are not active.  */
-  if (type && TREE_CODE (type) == VECTOR_TYPE)
-    mode = type_natural_mode (type, cum, false);
+  if (arg.type && TREE_CODE (arg.type) == VECTOR_TYPE)
+    mode = type_natural_mode (arg.type, cum, false);
 
   if (TARGET_64BIT)
     {
       enum calling_abi call_abi = cum ? cum->call_abi : ix86_abi;
 
       if (call_abi == MS_ABI)
-	arg = function_arg_ms_64 (cum, mode, omode, named, bytes);
+	reg = function_arg_ms_64 (cum, mode, arg.mode, arg.named, bytes);
       else
-	arg = function_arg_64 (cum, mode, omode, type, named);
+	reg = function_arg_64 (cum, mode, arg.mode, arg.type, arg.named);
     }
   else
-    arg = function_arg_32 (cum, mode, omode, type, bytes, words);
+    reg = function_arg_32 (cum, mode, arg.mode, arg.type, bytes, words);
 
   /* Track if there are outgoing arguments on stack.  */
-  if (arg == NULL_RTX && cum->caller)
+  if (reg == NULL_RTX && cum->caller)
     cfun->machine->outgoing_args_on_stack = true;
 
-  return arg;
+  return reg;
 }
 
 /* A C expression that indicates when an argument must be passed by
Index: gcc/config/ia64/ia64.c
===================================================================
--- gcc/config/ia64/ia64.c	2019-08-19 15:58:34.838031214 +0100
+++ gcc/config/ia64/ia64.c	2019-08-19 15:58:42.405976452 +0100
@@ -204,12 +204,9 @@ static void ia64_setup_incoming_varargs
 					 int *, int);
 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,
-			      const_tree, bool);
+static rtx ia64_function_arg (cumulative_args_t, const function_arg_info &);
 static rtx ia64_function_incoming_arg (cumulative_args_t,
-				       machine_mode, const_tree, bool);
+				       const function_arg_info &);
 static void ia64_function_arg_advance (cumulative_args_t, machine_mode,
 				       const_tree, bool);
 static pad_direction ia64_function_arg_padding (machine_mode, const_tree);
@@ -4748,14 +4745,14 @@ ia64_function_arg_offset (const CUMULATI
    registers.  */
 
 static rtx
-ia64_function_arg_1 (cumulative_args_t cum_v, machine_mode mode,
-		     const_tree type, bool named, bool incoming)
+ia64_function_arg_1 (cumulative_args_t cum_v, const function_arg_info &arg,
+		     bool incoming)
 {
   const CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
   int basereg = (incoming ? GR_ARG_FIRST : AR_ARG_FIRST);
-  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);
   machine_mode hfa_mode = VOIDmode;
 
   /* For OPEN VMS, emit the instruction setting up the argument register here,
@@ -4763,8 +4760,7 @@ ia64_function_arg_1 (cumulative_args_t c
      insns.  This is not the conceptually best place to do this, but this is
      the easiest as we have convenient access to cumulative args info.  */
 
-  if (TARGET_ABI_OPEN_VMS && mode == VOIDmode && type == void_type_node
-      && named == 1)
+  if (TARGET_ABI_OPEN_VMS && arg.end_marker_p ())
     {
       unsigned HOST_WIDE_INT regval = cum->words;
       int i;
@@ -4783,19 +4779,19 @@ ia64_function_arg_1 (cumulative_args_t c
   /* On OpenVMS argument is either in Rn or Fn.  */
   if (TARGET_ABI_OPEN_VMS)
     {
-      if (FLOAT_MODE_P (mode))
-	return gen_rtx_REG (mode, FR_ARG_FIRST + cum->words);
+      if (FLOAT_MODE_P (arg.mode))
+	return gen_rtx_REG (arg.mode, FR_ARG_FIRST + cum->words);
       else
-	return gen_rtx_REG (mode, basereg + cum->words);
+	return gen_rtx_REG (arg.mode, basereg + cum->words);
     }
 
   /* Check for and handle homogeneous FP aggregates.  */
-  if (type)
-    hfa_mode = hfa_element_mode (type, 0);
+  if (arg.type)
+    hfa_mode = hfa_element_mode (arg.type, 0);
 
   /* Unnamed prototyped hfas are passed as usual.  Named prototyped hfas
      and unprototyped hfas are passed specially.  */
-  if (hfa_mode != VOIDmode && (! cum->prototype || named))
+  if (hfa_mode != VOIDmode && (! cum->prototype || arg.named))
     {
       rtx loc[16];
       int i = 0;
@@ -4815,8 +4811,7 @@ ia64_function_arg_1 (cumulative_args_t c
       /* Fill the FP regs.  We do this always.  We stop if we reach the end
 	 of the argument, the last FP register, or the last argument slot.  */
 
-      byte_size = ((mode == BLKmode)
-		   ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
+      byte_size = arg.promoted_size_in_bytes ();
       args_byte_size = int_regs * UNITS_PER_WORD;
       offset = 0;
       for (; (offset < byte_size && fp_regs < MAX_ARGUMENT_SLOTS
@@ -4872,31 +4867,31 @@ ia64_function_arg_1 (cumulative_args_t c
 	  else if (gr_size > UNITS_PER_WORD)
 	    int_regs += gr_size / UNITS_PER_WORD;
 	}
-      return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
+      return gen_rtx_PARALLEL (arg.mode, gen_rtvec_v (i, loc));
     }
   
   /* Integral and aggregates go in general registers.  If we have run out of
      FR registers, then FP values must also go in general registers.  This can
      happen when we have a SFmode HFA.  */
-  else if (mode == TFmode || mode == TCmode
-	   || (! FLOAT_MODE_P (mode) || cum->fp_regs == MAX_ARGUMENT_SLOTS))
+  else if (arg.mode == TFmode || arg.mode == TCmode
+	   || !FLOAT_MODE_P (arg.mode)
+	   || cum->fp_regs == MAX_ARGUMENT_SLOTS)
     {
-      int byte_size = ((mode == BLKmode)
-                       ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
+      int byte_size = arg.promoted_size_in_bytes ();
       if (BYTES_BIG_ENDIAN
-	&& (mode == BLKmode || (type && AGGREGATE_TYPE_P (type)))
-	&& byte_size < UNITS_PER_WORD
-	&& byte_size > 0)
+	  && (arg.mode == BLKmode || arg.aggregate_type_p ())
+	  && byte_size < UNITS_PER_WORD
+	  && byte_size > 0)
 	{
 	  rtx gr_reg = gen_rtx_EXPR_LIST (VOIDmode,
 					  gen_rtx_REG (DImode,
 						       (basereg + cum->words
 							+ offset)),
 					  const0_rtx);
-	  return gen_rtx_PARALLEL (mode, gen_rtvec (1, gr_reg));
+	  return gen_rtx_PARALLEL (arg.mode, gen_rtvec (1, gr_reg));
 	}
       else
-	return gen_rtx_REG (mode, basereg + cum->words + offset);
+	return gen_rtx_REG (arg.mode, basereg + cum->words + offset);
 
     }
 
@@ -4904,19 +4899,19 @@ ia64_function_arg_1 (cumulative_args_t c
      named, and in a GR register when unnamed.  */
   else if (cum->prototype)
     {
-      if (named)
-	return gen_rtx_REG (mode, FR_ARG_FIRST + cum->fp_regs);
+      if (arg.named)
+	return gen_rtx_REG (arg.mode, FR_ARG_FIRST + cum->fp_regs);
       /* In big-endian mode, an anonymous SFmode value must be represented
          as (parallel:SF [(expr_list (reg:DI n) (const_int 0))]) to force
 	 the value into the high half of the general register.  */
-      else if (BYTES_BIG_ENDIAN && mode == SFmode)
-	return gen_rtx_PARALLEL (mode,
+      else if (BYTES_BIG_ENDIAN && arg.mode == SFmode)
+	return gen_rtx_PARALLEL (arg.mode,
 		 gen_rtvec (1,
                    gen_rtx_EXPR_LIST (VOIDmode,
 		     gen_rtx_REG (DImode, basereg + cum->words + offset),
 				      const0_rtx)));
       else
-	return gen_rtx_REG (mode, basereg + cum->words + offset);
+	return gen_rtx_REG (arg.mode, basereg + cum->words + offset);
     }
   /* If there is no prototype, then FP values go in both FR and GR
      registers.  */
@@ -4924,10 +4919,10 @@ ia64_function_arg_1 (cumulative_args_t c
     {
       /* See comment above.  */
       machine_mode inner_mode =
-	(BYTES_BIG_ENDIAN && mode == SFmode) ? DImode : mode;
+	(BYTES_BIG_ENDIAN && arg.mode == SFmode) ? DImode : arg.mode;
 
       rtx fp_reg = gen_rtx_EXPR_LIST (VOIDmode,
-				      gen_rtx_REG (mode, (FR_ARG_FIRST
+				      gen_rtx_REG (arg.mode, (FR_ARG_FIRST
 							  + cum->fp_regs)),
 				      const0_rtx);
       rtx gr_reg = gen_rtx_EXPR_LIST (VOIDmode,
@@ -4936,27 +4931,25 @@ ia64_function_arg_1 (cumulative_args_t c
 						    + offset)),
 				      const0_rtx);
 
-      return gen_rtx_PARALLEL (mode, gen_rtvec (2, fp_reg, gr_reg));
+      return gen_rtx_PARALLEL (arg.mode, gen_rtvec (2, fp_reg, gr_reg));
     }
 }
 
 /* Implement TARGET_FUNCION_ARG target hook.  */
 
 static rtx
-ia64_function_arg (cumulative_args_t cum, machine_mode mode,
-		   const_tree type, bool named)
+ia64_function_arg (cumulative_args_t cum, const function_arg_info &arg)
 {
-  return ia64_function_arg_1 (cum, mode, type, named, false);
+  return ia64_function_arg_1 (cum, arg, false);
 }
 
 /* Implement TARGET_FUNCION_INCOMING_ARG target hook.  */
 
 static rtx
 ia64_function_incoming_arg (cumulative_args_t cum,
-			    machine_mode mode,
-			    const_tree type, bool named)
+			    const function_arg_info &arg)
 {
-  return ia64_function_arg_1 (cum, mode, type, named, true);
+  return ia64_function_arg_1 (cum, arg, true);
 }
 
 /* Return number of bytes, at the beginning of the argument, that must be
Index: gcc/config/iq2000/iq2000.c
===================================================================
--- gcc/config/iq2000/iq2000.c	2019-08-19 15:58:34.842031183 +0100
+++ gcc/config/iq2000/iq2000.c	2019-08-19 15:58:42.405976452 +0100
@@ -164,7 +164,7 @@ static bool iq2000_pass_by_reference  (c
 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);
+				       const function_arg_info &);
 static void iq2000_function_arg_advance (cumulative_args_t,
 					 machine_mode, const_tree, bool);
 static pad_direction iq2000_function_arg_padding (machine_mode, const_tree);
@@ -1224,14 +1224,15 @@ iq2000_function_arg_advance (cumulative_
     }
 }
 
-/* Return an RTL expression containing the register for the given mode MODE
-   and type TYPE in CUM, or 0 if the argument is to be passed on the stack.  */
+/* Return an RTL expression containing the register for argument ARG in CUM,
+   or 0 if the argument is to be passed on the stack.  */
 
 static rtx
-iq2000_function_arg (cumulative_args_t cum_v, machine_mode mode,
-		     const_tree type, bool named)
+iq2000_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
+  tree type = arg.type;
+  machine_mode mode = arg.mode;
   rtx ret;
   int regbase = -1;
   int bias = 0;
@@ -1248,7 +1249,7 @@ iq2000_function_arg (cumulative_args_t c
 	       cum->gp_reg_found, cum->arg_number, cum->arg_words,
 	       GET_MODE_NAME (mode));
       fprintf (stderr, "%p", (const void *) type);
-      fprintf (stderr, ", %d ) = ", named);
+      fprintf (stderr, ", %d ) = ", arg.named);
     }
 
 
@@ -1306,7 +1307,7 @@ iq2000_function_arg (cumulative_args_t c
       gcc_assert (regbase != -1);
 
       if (! type || TREE_CODE (type) != RECORD_TYPE
-	  || ! named  || ! TYPE_SIZE_UNIT (type)
+	  || ! arg.named || ! TYPE_SIZE_UNIT (type)
 	  || ! tree_fits_uhwi_p (TYPE_SIZE_UNIT (type)))
 	ret = gen_rtx_REG (mode, regbase + *arg_words + bias);
       else
@@ -1378,11 +1379,11 @@ iq2000_function_arg (cumulative_args_t c
 		 struct_p ? ", [struct]" : "");
     }
 
-  /* We will be called with a mode of VOIDmode after the last argument
+  /* We will be called with an end marker after the last argument
      has been seen.  Whatever we return will be passed to the call
      insn.  If we need any shifts for small structures, return them in
      a PARALLEL.  */
-  if (mode == VOIDmode)
+  if (arg.end_marker_p ())
     {
       if (cum->num_adjusts > 0)
 	ret = gen_rtx_PARALLEL ((machine_mode) cum->fp_code,
@@ -1967,8 +1968,8 @@ iq2000_expand_prologue (void)
 	  passed_mode = Pmode;
 	}
 
-      entry_parm = iq2000_function_arg (args_so_far, passed_mode,
-					passed_type, true);
+      function_arg_info arg (passed_type, passed_mode, /*named=*/true);
+      entry_parm = iq2000_function_arg (args_so_far, arg);
 
       iq2000_function_arg_advance (args_so_far, passed_mode,
 				   passed_type, true);
@@ -2013,8 +2014,8 @@ iq2000_expand_prologue (void)
      iq2000_unction_arg has encoded a PARALLEL rtx, holding a vector of
      adjustments to be made as the next_arg_reg variable, so we split up
      the insns, and emit them separately.  */
-  next_arg_reg = iq2000_function_arg (args_so_far, VOIDmode,
-				      void_type_node, true);
+  next_arg_reg = iq2000_function_arg (args_so_far,
+				      function_arg_info::end_marker ());
   if (next_arg_reg != 0 && GET_CODE (next_arg_reg) == PARALLEL)
     {
       rtvec adjust = XVEC (next_arg_reg, 0);
@@ -2309,8 +2310,7 @@ iq2000_pass_by_reference (cumulative_arg
        CUMULATIVE_ARGS temp;
 
        temp = *cum;
-       if (iq2000_function_arg (pack_cumulative_args (&temp), arg.mode,
-				arg.type, arg.named) != 0)
+       if (iq2000_function_arg (pack_cumulative_args (&temp), arg) != 0)
 	 return 1;
      }
 
Index: gcc/config/lm32/lm32.c
===================================================================
--- gcc/config/lm32/lm32.c	2019-08-19 15:58:34.842031183 +0100
+++ gcc/config/lm32/lm32.c	2019-08-19 15:58:42.405976452 +0100
@@ -73,9 +73,7 @@ static bool lm32_can_eliminate (const in
 lm32_legitimate_address_p (machine_mode mode, rtx x, bool strict);
 static HOST_WIDE_INT lm32_compute_frame_size (int size);
 static void lm32_option_override (void);
-static rtx lm32_function_arg (cumulative_args_t cum,
-			      machine_mode mode, const_tree type,
-			      bool named);
+static rtx lm32_function_arg (cumulative_args_t, const function_arg_info &);
 static void lm32_function_arg_advance (cumulative_args_t cum,
 				       machine_mode mode,
 				       const_tree type, bool named);
@@ -619,32 +617,27 @@ lm32_print_operand_address (FILE * file,
    Value is zero to push the argument on the stack,
    or a hard register in which to store the argument.
 
-   MODE is the argument's machine mode.
-   TYPE is the data type of the argument (as a tree).
-    This is null for libcalls where that information may
-    not be available.
    CUM is a variable of type CUMULATIVE_ARGS which gives info about
     the preceding args and about the function being called.
-   NAMED is nonzero if this argument is a named parameter
-    (otherwise it is an extra parameter matching an ellipsis).  */
+   ARG is a description of the argument.  */
 
 static rtx
-lm32_function_arg (cumulative_args_t cum_v, machine_mode mode,
-		   const_tree type, bool named)
+lm32_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
-  if (mode == VOIDmode)
+  if (arg.end_marker_p ())
     /* Compute operand 2 of the call insn.  */
     return GEN_INT (0);
 
-  if (targetm.calls.must_pass_in_stack (mode, type))
+  if (targetm.calls.must_pass_in_stack (arg.mode, arg.type))
     return NULL_RTX;
 
-  if (!named || (*cum + LM32_NUM_REGS2 (mode, type) > LM32_NUM_ARG_REGS))
+  if (!arg.named
+      || *cum + LM32_NUM_REGS2 (arg.mode, arg.type) > LM32_NUM_ARG_REGS)
     return NULL_RTX;
 
-  return gen_rtx_REG (mode, *cum + LM32_FIRST_ARG_REG);
+  return gen_rtx_REG (arg.mode, *cum + LM32_FIRST_ARG_REG);
 }
 
 static void
Index: gcc/config/m32c/m32c.c
===================================================================
--- gcc/config/m32c/m32c.c	2019-08-19 15:58:28.434077550 +0100
+++ gcc/config/m32c/m32c.c	2019-08-19 15:58:42.409976425 +0100
@@ -76,8 +76,7 @@ static struct machine_function *m32c_ini
 static void m32c_insert_attributes (tree, tree *);
 static bool m32c_legitimate_address_p (machine_mode, rtx, bool);
 static bool m32c_addr_space_legitimate_address_p (machine_mode, rtx, bool, addr_space_t);
-static rtx m32c_function_arg (cumulative_args_t, machine_mode,
-			      const_tree, bool);
+static rtx m32c_function_arg (cumulative_args_t, const function_arg_info &);
 static bool m32c_pass_by_reference (cumulative_args_t,
 				    const function_arg_info &);
 static void m32c_function_arg_advance (cumulative_args_t, machine_mode,
@@ -1320,8 +1319,7 @@ m32c_push_rounding (poly_int64 n)
 #undef TARGET_FUNCTION_ARG
 #define TARGET_FUNCTION_ARG m32c_function_arg
 static rtx
-m32c_function_arg (cumulative_args_t ca_v,
-		   machine_mode mode, const_tree type, bool named)
+m32c_function_arg (cumulative_args_t ca_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *ca = get_cumulative_args (ca_v);
 
@@ -1329,38 +1327,38 @@ m32c_function_arg (cumulative_args_t ca_
   rtx rv = NULL_RTX;
 #if DEBUG0
   fprintf (stderr, "func_arg %d (%s, %d)\n",
-	   ca->parm_num, mode_name[mode], named);
-  debug_tree ((tree)type);
+	   ca->parm_num, mode_name[arg.mode], arg.named);
+  debug_tree (arg.type);
 #endif
 
-  if (mode == VOIDmode)
+  if (arg.end_marker_p ())
     return GEN_INT (0);
 
-  if (ca->force_mem || !named)
+  if (ca->force_mem || !arg.named)
     {
 #if DEBUG0
       fprintf (stderr, "func arg: force %d named %d, mem\n", ca->force_mem,
-	       named);
+	       arg.named);
 #endif
       return NULL_RTX;
     }
 
-  if (type && INTEGRAL_TYPE_P (type) && POINTER_TYPE_P (type))
+  if (arg.type && INTEGRAL_TYPE_P (arg.type) && POINTER_TYPE_P (arg.type))
     return NULL_RTX;
 
-  if (type && AGGREGATE_TYPE_P (type))
+  if (arg.aggregate_type_p ())
     return NULL_RTX;
 
   switch (ca->parm_num)
     {
     case 1:
-      if (GET_MODE_SIZE (mode) == 1 || GET_MODE_SIZE (mode) == 2)
-	rv = gen_rtx_REG (mode, TARGET_A16 ? R1_REGNO : R0_REGNO);
+      if (GET_MODE_SIZE (arg.mode) == 1 || GET_MODE_SIZE (arg.mode) == 2)
+	rv = gen_rtx_REG (arg.mode, TARGET_A16 ? R1_REGNO : R0_REGNO);
       break;
 
     case 2:
-      if (TARGET_A16 && GET_MODE_SIZE (mode) == 2)
-	rv = gen_rtx_REG (mode, R2_REGNO);
+      if (TARGET_A16 && GET_MODE_SIZE (arg.mode) == 2)
+	rv = gen_rtx_REG (arg.mode, R2_REGNO);
       break;
     }
 
Index: gcc/config/m32r/m32r.c
===================================================================
--- gcc/config/m32r/m32r.c	2019-08-19 15:58:34.842031183 +0100
+++ gcc/config/m32r/m32r.c	2019-08-19 15:58:42.409976425 +0100
@@ -96,8 +96,7 @@ static bool m32r_pass_by_reference (cumu
 				    const function_arg_info &arg);
 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 rtx m32r_function_arg (cumulative_args_t, const function_arg_info &);
 static void m32r_function_arg_advance (cumulative_args_t, machine_mode,
 				       const_tree, bool);
 static bool m32r_can_eliminate (const int, const int);
@@ -1201,26 +1200,20 @@ #define PASS_IN_REG_P(CUM, MODE, TYPE) \
    Value is zero to push the argument on the stack,
    or a hard register in which to store the argument.
 
-   MODE is the argument's machine mode.
-   TYPE is the data type of the argument (as a tree).
-    This is null for libcalls where that information may
-    not be available.
    CUM is a variable of type CUMULATIVE_ARGS which gives info about
     the preceding args and about the function being called.
-   NAMED is nonzero if this argument is a named parameter
-    (otherwise it is an extra parameter matching an ellipsis).  */
+   ARG is a description of the argument.  */
 /* On the M32R the first M32R_MAX_PARM_REGS args are normally in registers
    and the rest are pushed.  */
 
 static rtx
-m32r_function_arg (cumulative_args_t cum_v, machine_mode mode,
-		   const_tree type ATTRIBUTE_UNUSED,
-		   bool named ATTRIBUTE_UNUSED)
+m32r_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
-  return (PASS_IN_REG_P (*cum, mode, type)
-	  ? gen_rtx_REG (mode, ROUND_ADVANCE_CUM (*cum, mode, type))
+  return (PASS_IN_REG_P (*cum, arg.mode, arg.type)
+	  ? gen_rtx_REG (arg.mode,
+			 ROUND_ADVANCE_CUM (*cum, arg.mode, arg.type))
 	  : NULL_RTX);
 }
 
Index: gcc/config/m68k/m68k.c
===================================================================
--- gcc/config/m68k/m68k.c	2019-05-29 10:49:36.720710106 +0100
+++ gcc/config/m68k/m68k.c	2019-08-19 15:58:42.409976425 +0100
@@ -183,8 +183,7 @@ static poly_int64 m68k_return_pops_args
 static rtx m68k_delegitimize_address (rtx);
 static void m68k_function_arg_advance (cumulative_args_t, machine_mode,
 				       const_tree, bool);
-static rtx m68k_function_arg (cumulative_args_t, machine_mode,
-			      const_tree, bool);
+static rtx m68k_function_arg (cumulative_args_t, const function_arg_info &);
 static bool m68k_cannot_force_const_mem (machine_mode mode, rtx x);
 static bool m68k_output_addr_const_extra (FILE *, rtx);
 static void m68k_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
@@ -1464,10 +1463,7 @@ m68k_ok_for_sibcall_p (tree decl, tree e
 /* On the m68k all args are always pushed.  */
 
 static rtx
-m68k_function_arg (cumulative_args_t cum ATTRIBUTE_UNUSED,
-		   machine_mode mode ATTRIBUTE_UNUSED,
-		   const_tree type ATTRIBUTE_UNUSED,
-		   bool named ATTRIBUTE_UNUSED)
+m68k_function_arg (cumulative_args_t, const function_arg_info &)
 {
   return NULL_RTX;
 }
Index: gcc/config/mcore/mcore.c
===================================================================
--- gcc/config/mcore/mcore.c	2019-08-19 15:58:34.842031183 +0100
+++ gcc/config/mcore/mcore.c	2019-08-19 15:58:42.409976425 +0100
@@ -133,8 +133,7 @@ static bool       mcore_return_in_memory
 static int        mcore_arg_partial_bytes       (cumulative_args_t,
 						 const function_arg_info &);
 static rtx        mcore_function_arg            (cumulative_args_t,
-						 machine_mode,
-						 const_tree, bool);
+						 const function_arg_info &);
 static void       mcore_function_arg_advance    (cumulative_args_t,
 						 machine_mode,
 						 const_tree, bool);
@@ -2788,14 +2787,9 @@ mcore_function_value (const_tree valtype
    Value is zero to push the argument on the stack,
    or a hard register in which to store the argument.
 
-   MODE is the argument's machine mode.
-   TYPE is the data type of the argument (as a tree).
-    This is null for libcalls where that information may
-    not be available.
    CUM is a variable of type CUMULATIVE_ARGS which gives info about
     the preceding args and about the function being called.
-   NAMED is nonzero if this argument is a named parameter
-    (otherwise it is an extra parameter matching an ellipsis).
+   ARG is a description of the argument.
 
    On MCore the first args are normally in registers
    and the rest are pushed.  Any arg that starts within the first
@@ -2803,21 +2797,21 @@ mcore_function_value (const_tree valtype
    its data type forbids.  */
 
 static rtx
-mcore_function_arg (cumulative_args_t cum, machine_mode mode,
-		    const_tree type, bool named)
+mcore_function_arg (cumulative_args_t cum, const function_arg_info &arg)
 {
   int arg_reg;
   
-  if (! named || mode == VOIDmode)
+  if (!arg.named || arg.end_marker_p ())
     return 0;
 
-  if (targetm.calls.must_pass_in_stack (mode, type))
+  if (targetm.calls.must_pass_in_stack (arg.mode, arg.type))
     return 0;
 
-  arg_reg = ROUND_REG (*get_cumulative_args (cum), mode);
+  arg_reg = ROUND_REG (*get_cumulative_args (cum), arg.mode);
   
   if (arg_reg < NPARM_REGS)
-    return handle_structs_in_regs (mode, type, FIRST_PARM_REG + arg_reg);
+    return handle_structs_in_regs (arg.mode, arg.type,
+				   FIRST_PARM_REG + arg_reg);
 
   return 0;
 }
Index: gcc/config/microblaze/microblaze.c
===================================================================
--- gcc/config/microblaze/microblaze.c	2019-08-19 15:58:21.734126028 +0100
+++ gcc/config/microblaze/microblaze.c	2019-08-19 15:58:42.409976425 +0100
@@ -1596,13 +1596,11 @@ microblaze_function_arg_advance (cumulat
     }
 }
 
-/* Return an RTL expression containing the register for the given mode,
+/* Return an RTL expression containing the register for the given argument
    or 0 if the argument is to be passed on the stack.  */
 
 static rtx
-microblaze_function_arg (cumulative_args_t cum_v, machine_mode mode, 
-			 const_tree type ATTRIBUTE_UNUSED,
-			 bool named ATTRIBUTE_UNUSED)
+microblaze_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
@@ -1611,7 +1609,7 @@ microblaze_function_arg (cumulative_args
   int *arg_words = &cum->arg_words;
 
   cum->last_arg_fp = 0;
-  switch (mode)
+  switch (arg.mode)
     {
     case E_SFmode:
     case E_DFmode:
@@ -1624,8 +1622,8 @@ microblaze_function_arg (cumulative_args
       regbase = GP_ARG_FIRST;
       break;
     default:
-      gcc_assert (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT
-	  || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT);
+      gcc_assert (GET_MODE_CLASS (arg.mode) == MODE_COMPLEX_INT
+		  || GET_MODE_CLASS (arg.mode) == MODE_COMPLEX_FLOAT);
       /* FALLTHRU */
     case E_BLKmode:
       regbase = GP_ARG_FIRST;
@@ -1638,10 +1636,10 @@ microblaze_function_arg (cumulative_args
     {
       gcc_assert (regbase != -1);
 
-      ret = gen_rtx_REG (mode, regbase + *arg_words);
+      ret = gen_rtx_REG (arg.mode, regbase + *arg_words);
     }
 
-  if (mode == VOIDmode)
+  if (arg.end_marker_p ())
     {
       if (cum->num_adjusts > 0)
 	ret = gen_rtx_PARALLEL ((machine_mode) cum->fp_code,
@@ -2916,8 +2914,8 @@ microblaze_expand_prologue (void)
 	  passed_mode = Pmode;
 	}
 
-      entry_parm = targetm.calls.function_arg (args_so_far, passed_mode,
-					       passed_type, true);
+      function_arg_info arg (passed_type, passed_mode, /*named=*/true);
+      entry_parm = targetm.calls.function_arg (args_so_far, arg);
 
       if (entry_parm)
 	{
@@ -2952,8 +2950,8 @@ microblaze_expand_prologue (void)
 
   /* Split parallel insn into a sequence of insns.  */
 
-  next_arg_reg = targetm.calls.function_arg (args_so_far, VOIDmode,
-					     void_type_node, true);
+  next_arg_reg = targetm.calls.function_arg (args_so_far,
+					     function_arg_info::end_marker ());
   if (next_arg_reg != 0 && GET_CODE (next_arg_reg) == PARALLEL)
     {
       rtvec adjust = XVEC (next_arg_reg, 0);
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	2019-08-19 15:58:34.842031183 +0100
+++ gcc/config/mips/mips.c	2019-08-19 15:58:42.409976425 +0100
@@ -5976,17 +5976,16 @@ mips_strict_argument_naming (cumulative_
 /* Implement TARGET_FUNCTION_ARG.  */
 
 static rtx
-mips_function_arg (cumulative_args_t cum_v, machine_mode mode,
-		   const_tree type, bool named)
+mips_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   struct mips_arg_info info;
 
-  /* We will be called with a mode of VOIDmode after the last argument
+  /* We will be called with an end marker after the last argument
      has been seen.  Whatever we return will be passed to the call expander.
      If we need a MIPS16 fp_code, return a REG with the code stored as
      the mode.  */
-  if (mode == VOIDmode)
+  if (arg.end_marker_p ())
     {
       if (TARGET_MIPS16 && cum->fp_code != 0)
 	return gen_rtx_REG ((machine_mode) cum->fp_code, 0);
@@ -5994,7 +5993,7 @@ mips_function_arg (cumulative_args_t cum
 	return NULL;
     }
 
-  mips_get_arg_info (&info, cum, mode, type, named);
+  mips_get_arg_info (&info, cum, arg.mode, arg.type, arg.named);
 
   /* Return straight away if the whole argument is passed on the stack.  */
   if (info.reg_offset == MAX_ARGS_IN_REGISTERS)
@@ -6005,16 +6004,16 @@ mips_function_arg (cumulative_args_t cum
      in a floating-point register.  */
   if (TARGET_NEWABI
       && TARGET_HARD_FLOAT
-      && named
-      && type != 0
-      && TREE_CODE (type) == RECORD_TYPE
-      && TYPE_SIZE_UNIT (type)
-      && tree_fits_uhwi_p (TYPE_SIZE_UNIT (type)))
+      && arg.named
+      && arg.type != 0
+      && TREE_CODE (arg.type) == RECORD_TYPE
+      && TYPE_SIZE_UNIT (arg.type)
+      && tree_fits_uhwi_p (TYPE_SIZE_UNIT (arg.type)))
     {
       tree field;
 
       /* First check to see if there is any such field.  */
-      for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+      for (field = TYPE_FIELDS (arg.type); field; field = DECL_CHAIN (field))
 	if (TREE_CODE (field) == FIELD_DECL
 	    && SCALAR_FLOAT_TYPE_P (TREE_TYPE (field))
 	    && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD
@@ -6033,10 +6032,10 @@ mips_function_arg (cumulative_args_t cum
 
 	  /* assign_parms checks the mode of ENTRY_PARM, so we must
 	     use the actual mode here.  */
-	  ret = gen_rtx_PARALLEL (mode, rtvec_alloc (info.reg_words));
+	  ret = gen_rtx_PARALLEL (arg.mode, rtvec_alloc (info.reg_words));
 
 	  bitpos = 0;
-	  field = TYPE_FIELDS (type);
+	  field = TYPE_FIELDS (arg.type);
 	  for (i = 0; i < info.reg_words; i++)
 	    {
 	      rtx reg;
@@ -6069,13 +6068,13 @@ mips_function_arg (cumulative_args_t cum
      and the imaginary part goes in the upper register.  */
   if (TARGET_NEWABI
       && info.fpr_p
-      && GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
+      && GET_MODE_CLASS (arg.mode) == MODE_COMPLEX_FLOAT)
     {
       rtx real, imag;
       machine_mode inner;
       unsigned int regno;
 
-      inner = GET_MODE_INNER (mode);
+      inner = GET_MODE_INNER (arg.mode);
       regno = FP_ARG_FIRST + info.reg_offset;
       if (info.reg_words * UNITS_PER_WORD == GET_MODE_SIZE (inner))
 	{
@@ -6093,11 +6092,11 @@ mips_function_arg (cumulative_args_t cum
 				    gen_rtx_REG (inner,
 						 regno + info.reg_words / 2),
 				    GEN_INT (GET_MODE_SIZE (inner)));
-	  return gen_rtx_PARALLEL (mode, gen_rtvec (2, real, imag));
+	  return gen_rtx_PARALLEL (arg.mode, gen_rtvec (2, real, imag));
 	}
     }
 
-  return gen_rtx_REG (mode, mips_arg_regno (&info, TARGET_HARD_FLOAT));
+  return gen_rtx_REG (arg.mode, mips_arg_regno (&info, TARGET_HARD_FLOAT));
 }
 
 /* Implement TARGET_FUNCTION_ARG_ADVANCE.  */
Index: gcc/config/mmix/mmix.c
===================================================================
--- gcc/config/mmix/mmix.c	2019-08-19 15:58:34.842031183 +0100
+++ gcc/config/mmix/mmix.c	2019-08-19 15:58:42.413976394 +0100
@@ -151,12 +151,9 @@ static machine_mode mmix_promote_functio
 	                                             int *, const_tree, int);
 static void mmix_function_arg_advance (cumulative_args_t, machine_mode,
 				       const_tree, bool);
-static rtx mmix_function_arg_1 (const cumulative_args_t, machine_mode,
-				const_tree, bool, bool);
-static rtx mmix_function_incoming_arg (cumulative_args_t, machine_mode,
-				       const_tree, bool);
-static rtx mmix_function_arg (cumulative_args_t, machine_mode,
-			      const_tree, bool);
+static rtx mmix_function_incoming_arg (cumulative_args_t,
+				       const function_arg_info &);
+static rtx mmix_function_arg (cumulative_args_t, const function_arg_info &);
 static rtx mmix_function_value (const_tree, const_tree, bool);
 static rtx mmix_libcall_value (machine_mode, const_rtx);
 static bool mmix_function_value_regno_p (const unsigned int);
@@ -636,28 +633,25 @@ mmix_function_arg_advance (cumulative_ar
 
 static rtx
 mmix_function_arg_1 (const cumulative_args_t argsp_v,
-		     machine_mode mode,
-		     const_tree type,
-		     bool named ATTRIBUTE_UNUSED,
-		     bool incoming)
+		     const function_arg_info &arg, bool incoming)
 {
   CUMULATIVE_ARGS *argsp = get_cumulative_args (argsp_v);
 
   /* Last-argument marker.  */
-  if (type == void_type_node)
+  if (arg.end_marker_p ())
     return (argsp->regs < MMIX_MAX_ARGS_IN_REGS)
-      ? gen_rtx_REG (mode,
+      ? gen_rtx_REG (arg.mode,
 		     (incoming
 		      ? MMIX_FIRST_INCOMING_ARG_REGNUM
 		      : MMIX_FIRST_ARG_REGNUM) + argsp->regs)
       : NULL_RTX;
 
   return (argsp->regs < MMIX_MAX_ARGS_IN_REGS
-	  && !targetm.calls.must_pass_in_stack (mode, type)
-	  && (GET_MODE_BITSIZE (mode) <= 64
+	  && !targetm.calls.must_pass_in_stack (arg.mode, arg.type)
+	  && (GET_MODE_BITSIZE (arg.mode) <= 64
 	      || argsp->lib
 	      || TARGET_LIBFUNC))
-    ? gen_rtx_REG (mode,
+    ? gen_rtx_REG (arg.mode,
 		   (incoming
 		    ? MMIX_FIRST_INCOMING_ARG_REGNUM
 		    : MMIX_FIRST_ARG_REGNUM)
@@ -669,21 +663,16 @@ mmix_function_arg_1 (const cumulative_ar
    one that must go on stack.  */
 
 static rtx
-mmix_function_arg (cumulative_args_t argsp,
-		   machine_mode mode,
-		   const_tree type,
-		   bool named)
+mmix_function_arg (cumulative_args_t argsp, const function_arg_info &arg)
 {
-  return mmix_function_arg_1 (argsp, mode, type, named, false);
+  return mmix_function_arg_1 (argsp, arg, false);
 }
 
 static rtx
 mmix_function_incoming_arg (cumulative_args_t argsp,
-			    machine_mode mode,
-			    const_tree type,
-			    bool named)
+			    const function_arg_info &arg)
 {
-  return mmix_function_arg_1 (argsp, mode, type, named, true);
+  return mmix_function_arg_1 (argsp, arg, true);
 }
 
 /* Returns nonzero for everything that goes by reference, 0 for
Index: gcc/config/mn10300/mn10300.c
===================================================================
--- gcc/config/mn10300/mn10300.c	2019-08-19 15:58:28.438077523 +0100
+++ gcc/config/mn10300/mn10300.c	2019-08-19 15:58:42.413976394 +0100
@@ -1532,12 +1532,11 @@ mn10300_pass_by_reference (cumulative_ar
   return (size > 8 || size == 0);
 }
 
-/* Return an RTX to represent where a value with mode MODE will be returned
-   from a function.  If the result is NULL_RTX, the argument is pushed.  */
+/* Return an RTX to represent where argument ARG will be passed to a function.
+   If the result is NULL_RTX, the argument is pushed.  */
 
 static rtx
-mn10300_function_arg (cumulative_args_t cum_v, machine_mode mode,
-		      const_tree type, bool named ATTRIBUTE_UNUSED)
+mn10300_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   rtx result = NULL_RTX;
@@ -1547,11 +1546,7 @@ mn10300_function_arg (cumulative_args_t
   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
@@ -1561,17 +1556,17 @@ mn10300_function_arg (cumulative_args_t
 
   /* 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 result;
 
   switch (cum->nbytes / UNITS_PER_WORD)
     {
     case 0:
-      result = gen_rtx_REG (mode, FIRST_ARGUMENT_REGNUM);
+      result = gen_rtx_REG (arg.mode, FIRST_ARGUMENT_REGNUM);
       break;
     case 1:
-      result = gen_rtx_REG (mode, FIRST_ARGUMENT_REGNUM + 1);
+      result = gen_rtx_REG (arg.mode, FIRST_ARGUMENT_REGNUM + 1);
       break;
     default:
       break;
Index: gcc/config/moxie/moxie.c
===================================================================
--- gcc/config/moxie/moxie.c	2019-08-19 15:58:34.842031183 +0100
+++ gcc/config/moxie/moxie.c	2019-08-19 15:58:42.413976394 +0100
@@ -423,14 +423,12 @@ moxie_fixed_condition_code_regs (unsigne
    NULL_RTX if there's no more space.  */
 
 static rtx
-moxie_function_arg (cumulative_args_t cum_v, machine_mode mode,
-		    const_tree type ATTRIBUTE_UNUSED,
-		    bool named ATTRIBUTE_UNUSED)
+moxie_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
   if (*cum < 8)
-    return gen_rtx_REG (mode, *cum);
+    return gen_rtx_REG (arg.mode, *cum);
   else 
     return NULL_RTX;
 }
Index: gcc/config/msp430/msp430.c
===================================================================
--- gcc/config/msp430/msp430.c	2019-08-19 15:58:28.438077523 +0100
+++ gcc/config/msp430/msp430.c	2019-08-19 15:58:42.413976394 +0100
@@ -710,16 +710,14 @@ #define TARGET_FUNCTION_ARG msp430_funct
 
 rtx
 msp430_function_arg (cumulative_args_t cap,
-		     machine_mode mode,
-		     const_tree type,
-		     bool named)
+		     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)
-    return gen_rtx_REG (mode, ca->start_reg);
+    return gen_rtx_REG (arg.mode, ca->start_reg);
 
   return 0;
 }
Index: gcc/config/nds32/nds32.c
===================================================================
--- gcc/config/nds32/nds32.c	2019-08-19 15:58:34.846031154 +0100
+++ gcc/config/nds32/nds32.c	2019-08-19 15:58:42.413976394 +0100
@@ -1868,19 +1868,20 @@ nds32_can_eliminate (const int from_reg,
 /* -- Passing Arguments in Registers.  */
 
 static rtx
-nds32_function_arg (cumulative_args_t ca, machine_mode mode,
-		    const_tree type, bool named)
+nds32_function_arg (cumulative_args_t ca, const function_arg_info &arg)
 {
   unsigned int regno;
   CUMULATIVE_ARGS *cum = get_cumulative_args (ca);
+  tree type = arg.type;
+  machine_mode mode = arg.mode;
 
   /* The last time this hook is called,
-     it is called with MODE == VOIDmode.  */
-  if (mode == VOIDmode)
+     it is called with an end marker.  */
+  if (arg.end_marker_p ())
     return NULL_RTX;
 
   /* For nameless arguments, we need to take care it individually.  */
-  if (!named)
+  if (!arg.named)
     {
       /* If we are under hard float abi, we have arguments passed on the
 	 stack and all situation can be handled by GCC itself.  */
Index: gcc/config/nios2/nios2.c
===================================================================
--- gcc/config/nios2/nios2.c	2019-08-19 15:58:34.846031154 +0100
+++ gcc/config/nios2/nios2.c	2019-08-19 15:58:42.413976394 +0100
@@ -3362,25 +3362,18 @@ nios2_fpu_insn_asm (enum n2fpu_code code
    push the argument on the stack, or a hard register in which to
    store the argument.
 
-   MODE is the argument's machine mode.
-   TYPE is the data type of the argument (as a tree).
-   This is null for libcalls where that information may
-   not be available.
    CUM is a variable of type CUMULATIVE_ARGS which gives info about
    the preceding args and about the function being called.
-   NAMED is nonzero if this argument is a named parameter
-   (otherwise it is an extra parameter matching an ellipsis).  */
+   ARG is a description of the argument.  */
 
 static rtx
-nios2_function_arg (cumulative_args_t cum_v, machine_mode mode,
-		    const_tree type ATTRIBUTE_UNUSED,
-		    bool named ATTRIBUTE_UNUSED)
+nios2_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); 
   rtx return_rtx = NULL_RTX;
 
   if (cum->regs_used < NUM_ARG_REGS)
-    return_rtx = gen_rtx_REG (mode, FIRST_ARG_REGNO + cum->regs_used);
+    return_rtx = gen_rtx_REG (arg.mode, FIRST_ARG_REGNO + cum->regs_used);
 
   return return_rtx;
 }
Index: gcc/config/nvptx/nvptx.c
===================================================================
--- gcc/config/nvptx/nvptx.c	2019-08-19 15:58:28.438077523 +0100
+++ gcc/config/nvptx/nvptx.c	2019-08-19 15:58:42.413976394 +0100
@@ -520,30 +520,29 @@ promote_return (machine_mode mode)
 /* Implement TARGET_FUNCTION_ARG.  */
 
 static rtx
-nvptx_function_arg (cumulative_args_t ARG_UNUSED (cum_v), machine_mode mode,
-		    const_tree, bool named)
+nvptx_function_arg (cumulative_args_t, const function_arg_info &arg)
 {
-  if (mode == VOIDmode || !named)
+  if (arg.end_marker_p () || !arg.named)
     return NULL_RTX;
 
-  return gen_reg_rtx (mode);
+  return gen_reg_rtx (arg.mode);
 }
 
 /* Implement TARGET_FUNCTION_INCOMING_ARG.  */
 
 static rtx
-nvptx_function_incoming_arg (cumulative_args_t cum_v, machine_mode mode,
-			     const_tree, bool named)
+nvptx_function_incoming_arg (cumulative_args_t cum_v,
+			     const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
-  if (mode == VOIDmode || !named)
+  if (arg.end_marker_p () || !arg.named)
     return NULL_RTX;
 
   /* No need to deal with split modes here, the only case that can
      happen is complex modes and those are dealt with by
      TARGET_SPLIT_COMPLEX_ARG.  */
-  return gen_rtx_UNSPEC (mode,
+  return gen_rtx_UNSPEC (arg.mode,
 			 gen_rtvec (1, GEN_INT (cum->count)),
 			 UNSPEC_ARG_REG);
 }
Index: gcc/config/or1k/or1k.c
===================================================================
--- gcc/config/or1k/or1k.c	2019-08-19 15:58:28.442077491 +0100
+++ gcc/config/or1k/or1k.c	2019-08-19 15:58:42.413976394 +0100
@@ -997,20 +997,19 @@ #define TARGET_STRICT_ARGUMENT_NAMING or
    maybe be passed in registers r3 to r8.  */
 
 static rtx
-or1k_function_arg (cumulative_args_t cum_v, machine_mode mode,
-		   const_tree /* type */, bool named)
+or1k_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
-  /* VOIDmode is passed as a special flag for "last argument".  */
-  if (mode == VOIDmode)
+  /* Handle the special marker for the end of the arguments.  */
+  if (arg.end_marker_p ())
     return NULL_RTX;
 
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
-  int nreg = CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD);
+  int nreg = CEIL (GET_MODE_SIZE (arg.mode), UNITS_PER_WORD);
 
   /* Note that all large arguments are passed by reference.  */
   gcc_assert (nreg <= 2);
-  if (named && *cum + nreg <= 6)
-    return gen_rtx_REG (mode, *cum + 3);
+  if (arg.named && *cum + nreg <= 6)
+    return gen_rtx_REG (arg.mode, *cum + 3);
   else
     return NULL_RTX;
 }
Index: gcc/config/pa/pa.c
===================================================================
--- gcc/config/pa/pa.c	2019-08-19 15:58:28.442077491 +0100
+++ gcc/config/pa/pa.c	2019-08-19 15:58:42.413976394 +0100
@@ -169,8 +169,7 @@ static bool pa_pass_by_reference (cumula
 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,
-			    const_tree, bool);
+static rtx pa_function_arg (cumulative_args_t, const function_arg_info &);
 static pad_direction pa_function_arg_padding (machine_mode, const_tree);
 static unsigned int pa_function_arg_boundary (machine_mode, const_tree);
 static struct machine_function * pa_init_machine_status (void);
@@ -9465,10 +9464,11 @@ pa_function_arg_advance (cumulative_args
    ??? We might want to restructure this so that it looks more like other
    ports.  */
 static rtx
-pa_function_arg (cumulative_args_t cum_v, machine_mode mode,
-		 const_tree type, bool named ATTRIBUTE_UNUSED)
+pa_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
+  tree type = arg.type;
+  machine_mode mode = arg.mode;
   int max_arg_words = (TARGET_64BIT ? 8 : 4);
   int alignment = 0;
   int arg_size;
@@ -9476,7 +9476,7 @@ pa_function_arg (cumulative_args_t cum_v
   int gpr_reg_base;
   rtx retval;
 
-  if (mode == VOIDmode)
+  if (arg.end_marker_p ())
     return NULL_RTX;
 
   arg_size = pa_function_arg_size (mode, type);
Index: gcc/config/pdp11/pdp11.c
===================================================================
--- gcc/config/pdp11/pdp11.c	2019-03-08 18:15:37.572737035 +0000
+++ gcc/config/pdp11/pdp11.c	2019-08-19 15:58:42.413976394 +0100
@@ -162,8 +162,7 @@ static rtx pdp11_function_value (const_t
 static rtx pdp11_libcall_value (machine_mode, const_rtx);
 static bool pdp11_function_value_regno_p (const unsigned int);
 static void pdp11_trampoline_init (rtx, tree, rtx);
-static rtx pdp11_function_arg (cumulative_args_t, machine_mode,
-			       const_tree, bool);
+static rtx pdp11_function_arg (cumulative_args_t, const function_arg_info &);
 static void pdp11_function_arg_advance (cumulative_args_t,
 					machine_mode, const_tree, bool);
 static void pdp11_conditional_register_usage (void);
@@ -2180,26 +2179,10 @@ pdp11_trampoline_init (rtx m_tramp, tree
   emit_move_insn (mem, fnaddr);
 }
 
-/* Worker function for TARGET_FUNCTION_ARG.
-
-   Determine where to put an argument to a function.
-   Value is zero to push the argument on the stack,
-   or a hard register in which to store the argument.
-
-   MODE is the argument's machine mode.
-   TYPE is the data type of the argument (as a tree).
-    This is null for libcalls where that information may
-    not be available.
-   CUM is a variable of type CUMULATIVE_ARGS which gives info about
-    the preceding args and about the function being called.
-   NAMED is nonzero if this argument is a named parameter
-    (otherwise it is an extra parameter matching an ellipsis).  */
+/* Worker function for TARGET_FUNCTION_ARG.  */
 
 static rtx
-pdp11_function_arg (cumulative_args_t cum ATTRIBUTE_UNUSED,
-		    machine_mode mode ATTRIBUTE_UNUSED,
-		    const_tree type ATTRIBUTE_UNUSED,
-		    bool named ATTRIBUTE_UNUSED)
+pdp11_function_arg (cumulative_args_t, const function_arg_info &)
 {
   return NULL_RTX;
 }
Index: gcc/config/pru/pru.c
===================================================================
--- gcc/config/pru/pru.c	2019-08-19 15:58:21.738126000 +0100
+++ gcc/config/pru/pru.c	2019-08-19 15:58:42.413976394 +0100
@@ -2152,25 +2152,18 @@ pru_function_arg_regi_mark_slot (int reg
    push the argument on the stack, or a hard register in which to
    store the argument.
 
-   MODE is the argument's machine mode.
-   TYPE is the data type of the argument (as a tree).
-   This is null for libcalls where that information may
-   not be available.
    CUM is a variable of type CUMULATIVE_ARGS which gives info about
    the preceding args and about the function being called.
-   NAMED is nonzero if this argument is a named parameter
-   (otherwise it is an extra parameter matching an ellipsis).  */
+   ARG is a description of the argument.  */
 
 static rtx
-pru_function_arg (cumulative_args_t cum_v, machine_mode mode,
-		  const_tree type,
-		  bool named)
+pru_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   rtx return_rtx = NULL_RTX;
-  int regi = pru_function_arg_regi (cum_v, mode, type, named);
+  int regi = pru_function_arg_regi (cum_v, arg.mode, arg.type, arg.named);
 
   if (regi >= 0)
-    return_rtx = gen_rtx_REG (mode, regi);
+    return_rtx = gen_rtx_REG (arg.mode, regi);
 
   return return_rtx;
 }
Index: gcc/config/riscv/riscv.c
===================================================================
--- gcc/config/riscv/riscv.c	2019-08-19 15:58:34.846031154 +0100
+++ gcc/config/riscv/riscv.c	2019-08-19 15:58:42.417976367 +0100
@@ -2743,16 +2743,15 @@ riscv_get_arg_info (struct riscv_arg_inf
 /* Implement TARGET_FUNCTION_ARG.  */
 
 static rtx
-riscv_function_arg (cumulative_args_t cum_v, machine_mode mode,
-		    const_tree type, bool named)
+riscv_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   struct riscv_arg_info info;
 
-  if (mode == VOIDmode)
+  if (arg.end_marker_p ())
     return NULL;
 
-  return riscv_get_arg_info (&info, cum, mode, type, named, false);
+  return riscv_get_arg_info (&info, cum, arg.mode, arg.type, arg.named, false);
 }
 
 /* Implement TARGET_FUNCTION_ARG_ADVANCE.  */
Index: gcc/config/rl78/rl78.c
===================================================================
--- gcc/config/rl78/rl78.c	2019-03-18 12:24:58.903434241 +0000
+++ gcc/config/rl78/rl78.c	2019-08-19 15:58:42.417976367 +0100
@@ -1737,21 +1737,11 @@ rl78_promote_function_mode (const_tree t
   return mode;
 }
 
-/* Return an RTL expression describing the register holding a function
-   parameter of mode MODE and type TYPE or NULL_RTX if the parameter should
-   be passed on the stack.  CUM describes the previous parameters to the
-   function and NAMED is false if the parameter is part of a variable
-   parameter list, or the last named parameter before the start of a
-   variable parameter list.  */
-
 #undef  TARGET_FUNCTION_ARG
 #define TARGET_FUNCTION_ARG     	rl78_function_arg
 
 static rtx
-rl78_function_arg (cumulative_args_t cum_v ATTRIBUTE_UNUSED,
-		   machine_mode mode ATTRIBUTE_UNUSED,
-		   const_tree type ATTRIBUTE_UNUSED,
-		   bool named ATTRIBUTE_UNUSED)
+rl78_function_arg (cumulative_args_t, const function_arg_info &)
 {
   return NULL_RTX;
 }
Index: gcc/config/rs6000/rs6000-internal.h
===================================================================
--- gcc/config/rs6000/rs6000-internal.h	2019-08-19 15:58:34.846031154 +0100
+++ gcc/config/rs6000/rs6000-internal.h	2019-08-19 15:58:42.417976367 +0100
@@ -164,8 +164,7 @@ extern void rs6000_function_arg_advance
 					 const_tree type, bool named);
 extern pad_direction rs6000_function_arg_padding (machine_mode mode,
 						  const_tree type);
-extern rtx rs6000_function_arg (cumulative_args_t cum_v, machine_mode mode,
-				const_tree type, bool named);
+extern rtx rs6000_function_arg (cumulative_args_t, const function_arg_info &);
 extern rtx rs6000_darwin64_record_arg (CUMULATIVE_ARGS *, const_tree,
 				       bool, bool);
 extern rtx rs6000_internal_arg_pointer (void);
Index: gcc/config/rs6000/rs6000-call.c
===================================================================
--- gcc/config/rs6000/rs6000-call.c	2019-08-19 15:58:34.846031154 +0100
+++ gcc/config/rs6000/rs6000-call.c	2019-08-19 15:58:42.417976367 +0100
@@ -1729,15 +1729,10 @@ rs6000_finish_function_arg (machine_mode
    Value is zero to push the argument on the stack,
    or a hard register in which to store the argument.
 
-   MODE is the argument's machine mode.
-   TYPE is the data type of the argument (as a tree).
-    This is null for libcalls where that information may
-    not be available.
    CUM is a variable of type CUMULATIVE_ARGS which gives info about
     the preceding args and about the function being called.  It is
     not modified in this routine.
-   NAMED is nonzero if this argument is a named parameter
-    (otherwise it is an extra parameter matching an ellipsis).
+   ARG is a description of the argument.
 
    On RS/6000 the first eight words of non-FP are normally in registers
    and the rest are pushed.  Under AIX, the first 13 FP args are in registers.
@@ -1750,14 +1745,15 @@ rs6000_finish_function_arg (machine_mode
    doesn't support PARALLEL anyway.
 
    Note that for args passed by reference, function_arg will be called
-   with MODE and TYPE set to that of the pointer to the arg, not the arg
-   itself.  */
+   with ARG describing the pointer to the arg, not the arg itself.  */
 
 rtx
-rs6000_function_arg (cumulative_args_t cum_v, machine_mode mode,
-		     const_tree type, bool named)
+rs6000_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
+  tree type = arg.type;
+  machine_mode mode = arg.mode;
+  bool named = arg.named;
   enum rs6000_abi abi = DEFAULT_ABI;
   machine_mode elt_mode;
   int n_elts;
@@ -1766,7 +1762,7 @@ rs6000_function_arg (cumulative_args_t c
      bit that V.4 uses to say fp args were passed in registers.
      Assume that we don't need the marker for software floating point,
      or compiler generated library calls.  */
-  if (mode == VOIDmode)
+  if (arg.end_marker_p ())
     {
       if (abi == ABI_V4
 	  && (cum->call_cookie & CALL_LIBCALL) == 0
@@ -2210,7 +2206,8 @@ rs6000_parm_needs_stack (cumulative_args
     return true;
 
   /* If there is no incoming register, we need a stack.  */
-  entry_parm = rs6000_function_arg (args_so_far, mode, type, true);
+  function_arg_info arg (type, mode, /*named=*/true);
+  entry_parm = rs6000_function_arg (args_so_far, arg);
   if (entry_parm == NULL)
     return true;
 
@@ -2220,7 +2217,6 @@ rs6000_parm_needs_stack (cumulative_args
     return true;
 
   /* Also true if we're partially in registers and partially not.  */
-  function_arg_info arg (type, mode, /*named=*/true);
   if (rs6000_arg_partial_bytes (args_so_far, arg) != 0)
     return true;
 
Index: gcc/config/rx/rx.c
===================================================================
--- gcc/config/rx/rx.c	2019-08-13 22:35:11.773251928 +0100
+++ gcc/config/rx/rx.c	2019-08-19 15:58:42.417976367 +0100
@@ -1064,24 +1064,19 @@ rx_function_arg_size (machine_mode mode,
 #define NUM_ARG_REGS		4
 #define MAX_NUM_ARG_BYTES	(NUM_ARG_REGS * UNITS_PER_WORD)
 
-/* Return an RTL expression describing the register holding a function
-   parameter of mode MODE and type TYPE or NULL_RTX if the parameter should
-   be passed on the stack.  CUM describes the previous parameters to the
-   function and NAMED is false if the parameter is part of a variable
-   parameter list, or the last named parameter before the start of a
-   variable parameter list.  */
+/* Return an RTL expression describing the register holding function
+   argument ARG or NULL_RTX if the parameter should be passed on the
+   stack.  CUM describes the previous parameters to the function.  */
 
 static rtx
-rx_function_arg (cumulative_args_t cum, machine_mode mode,
-		 const_tree type, bool named)
+rx_function_arg (cumulative_args_t cum, const function_arg_info &arg)
 {
   unsigned int next_reg;
   unsigned int bytes_so_far = *get_cumulative_args (cum);
   unsigned int size;
   unsigned int rounded_size;
 
-  /* An exploded version of rx_function_arg_size.  */
-  size = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
+  size = arg.promoted_size_in_bytes ();
   /* If the size is not known it cannot be passed in registers.  */
   if (size < 1)
     return NULL_RTX;
@@ -1095,18 +1090,18 @@ rx_function_arg (cumulative_args_t cum,
 
   /* Unnamed arguments and the last named argument in a
      variadic function are always passed on the stack.  */
-  if (!named)
+  if (!arg.named)
     return NULL_RTX;
 
   /* Structures must occupy an exact number of registers,
      otherwise they are passed on the stack.  */
-  if ((type == NULL || AGGREGATE_TYPE_P (type))
+  if ((arg.type == NULL || AGGREGATE_TYPE_P (arg.type))
       && (size % UNITS_PER_WORD) != 0)
     return NULL_RTX;
 
   next_reg = (bytes_so_far / UNITS_PER_WORD) + 1;
 
-  return gen_rtx_REG (mode, next_reg);
+  return gen_rtx_REG (arg.mode, next_reg);
 }
 
 static void
Index: gcc/config/s390/s390.c
===================================================================
--- gcc/config/s390/s390.c	2019-08-19 15:58:28.442077491 +0100
+++ gcc/config/s390/s390.c	2019-08-19 15:58:42.417976367 +0100
@@ -12021,14 +12021,9 @@ s390_function_arg_advance (cumulative_ar
    Value is zero to push the argument on the stack,
    or a hard register in which to store the argument.
 
-   MODE is the argument's machine mode.
-   TYPE is the data type of the argument (as a tree).
-    This is null for libcalls where that information may
-    not be available.
    CUM is a variable of type CUMULATIVE_ARGS which gives info about
     the preceding args and about the function being called.
-   NAMED is nonzero if this argument is a named parameter
-    (otherwise it is an extra parameter matching an ellipsis).
+   ARG is a description of the argument.
 
    On S/390, we use general purpose registers 2 through 6 to
    pass integer, pointer, and certain structure arguments, and
@@ -12037,39 +12032,38 @@ s390_function_arg_advance (cumulative_ar
    are pushed to the stack.  */
 
 static rtx
-s390_function_arg (cumulative_args_t cum_v, machine_mode mode,
-		   const_tree type, bool named)
+s390_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
-  if (!named)
-    s390_check_type_for_vector_abi (type, true, false);
+  if (!arg.named)
+    s390_check_type_for_vector_abi (arg.type, true, false);
 
-  if (s390_function_arg_vector (mode, type))
+  if (s390_function_arg_vector (arg.mode, arg.type))
     {
       /* Vector arguments being part of the ellipsis are passed on the
 	 stack.  */
-      if (!named || (cum->vrs + 1 > VEC_ARG_NUM_REG))
+      if (!arg.named || (cum->vrs + 1 > VEC_ARG_NUM_REG))
 	return NULL_RTX;
 
-      return gen_rtx_REG (mode, cum->vrs + FIRST_VEC_ARG_REGNO);
+      return gen_rtx_REG (arg.mode, cum->vrs + FIRST_VEC_ARG_REGNO);
     }
-  else if (s390_function_arg_float (mode, type))
+  else if (s390_function_arg_float (arg.mode, arg.type))
     {
       if (cum->fprs + 1 > FP_ARG_NUM_REG)
 	return NULL_RTX;
       else
-	return gen_rtx_REG (mode, cum->fprs + 16);
+	return gen_rtx_REG (arg.mode, cum->fprs + 16);
     }
-  else if (s390_function_arg_integer (mode, type))
+  else if (s390_function_arg_integer (arg.mode, arg.type))
     {
-      int size = s390_function_arg_size (mode, type);
+      int size = s390_function_arg_size (arg.mode, arg.type);
       int n_gprs = (size + UNITS_PER_LONG - 1) / UNITS_PER_LONG;
 
       if (cum->gprs + n_gprs > GP_ARG_NUM_REG)
 	return NULL_RTX;
       else if (n_gprs == 1 || UNITS_PER_WORD == UNITS_PER_LONG)
-	return gen_rtx_REG (mode, cum->gprs + 2);
+	return gen_rtx_REG (arg.mode, cum->gprs + 2);
       else if (n_gprs == 2)
 	{
 	  rtvec p = rtvec_alloc (2);
@@ -12081,16 +12075,16 @@ s390_function_arg (cumulative_args_t cum
 	    = gen_rtx_EXPR_LIST (SImode, gen_rtx_REG (SImode, cum->gprs + 3),
 					 GEN_INT (4));
 
-	  return gen_rtx_PARALLEL (mode, p);
+	  return gen_rtx_PARALLEL (arg.mode, p);
 	}
     }
 
-  /* After the real arguments, expand_call calls us once again
-     with a void_type_node type.  Whatever we return here is
-     passed as operand 2 to the call expanders.
+  /* After the real arguments, expand_call calls us once again with an
+     end marker.  Whatever we return here is passed as operand 2 to the
+     call expanders.
 
      We don't need this feature ...  */
-  else if (type == void_type_node)
+  else if (arg.end_marker_p ())
     return const0_rtx;
 
   gcc_unreachable ();
@@ -13352,7 +13346,8 @@ s390_call_saved_register_used (tree call
 	  type = build_pointer_type (type);
 	}
 
-       parm_rtx = s390_function_arg (cum, mode, type, true);
+       function_arg_info arg (type, mode, /*named=*/true);
+       parm_rtx = s390_function_arg (cum, arg);
 
        s390_function_arg_advance (cum, mode, type, true);
 
Index: gcc/config/sh/sh.c
===================================================================
--- gcc/config/sh/sh.c	2019-08-19 15:58:34.846031154 +0100
+++ gcc/config/sh/sh.c	2019-08-19 15:58:42.417976367 +0100
@@ -301,8 +301,7 @@ static bool sh_callee_copies (cumulative
 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,
-			    const_tree, bool);
+static rtx sh_function_arg (cumulative_args_t, const function_arg_info &);
 static int sh_dwarf_calling_convention (const_tree);
 static void sh_encode_section_info (tree, rtx, int);
 static bool sh2a_function_vector_p (tree);
@@ -8010,30 +8009,25 @@ sh_arg_partial_bytes (cumulative_args_t
    Value is zero to push the argument on the stack,
    or a hard register in which to store the argument.
 
-   MODE is the argument's machine mode.
-   TYPE is the data type of the argument (as a tree).
-    This is null for libcalls where that information may
-    not be available.
    CUM is a variable of type CUMULATIVE_ARGS which gives info about
     the preceding args and about the function being called.
-   NAMED is nonzero if this argument is a named parameter
-    (otherwise it is an extra parameter matching an ellipsis).
+   ARG is a description of the argument.
 
    On SH the first args are normally in registers
    and the rest are pushed.  Any arg that starts within the first
    NPARM_REGS words is at least partially passed in a register unless
    its data type forbids.  */
 static rtx
-sh_function_arg (cumulative_args_t ca_v, machine_mode mode,
-		 const_tree type, bool named)
+sh_function_arg (cumulative_args_t ca_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *ca = get_cumulative_args (ca_v);
+  machine_mode mode = arg.mode;
 
-  if (mode == VOIDmode)
+  if (arg.end_marker_p ())
     return ca->renesas_abi ? const1_rtx : const0_rtx;
 
-  if (sh_pass_in_reg_p (*ca, mode, type)
-      && (named || ! (TARGET_HITACHI || ca->renesas_abi)))
+  if (sh_pass_in_reg_p (*ca, mode, arg.type)
+      && (arg.named || ! (TARGET_HITACHI || ca->renesas_abi)))
     {
       int regno;
 
@@ -10819,8 +10813,8 @@ sh_output_mi_thunk (FILE *file, tree thu
 
       sh_function_arg_advance (pack_cumulative_args (&cum), Pmode, ptype, true);
     }
-  this_rtx
-    = sh_function_arg (pack_cumulative_args (&cum), Pmode, ptr_type_node, true);
+  function_arg_info ptr_arg (ptr_type_node, Pmode, /*named=*/true);
+  this_rtx = sh_function_arg (pack_cumulative_args (&cum), ptr_arg);
 
   /* For SHcompact, we only have r0 for a scratch register: r1 is the
      static chain pointer (even if you can't have nested virtual functions
Index: gcc/config/sparc/sparc.c
===================================================================
--- gcc/config/sparc/sparc.c	2019-08-19 15:58:28.446077464 +0100
+++ gcc/config/sparc/sparc.c	2019-08-19 15:58:42.417976367 +0100
@@ -658,12 +658,9 @@ static bool sparc_pass_by_reference (cum
 				     const function_arg_info &);
 static void sparc_function_arg_advance (cumulative_args_t,
 					machine_mode, const_tree, bool);
-static rtx sparc_function_arg_1 (cumulative_args_t,
-				 machine_mode, const_tree, bool, bool);
-static rtx sparc_function_arg (cumulative_args_t,
-			       machine_mode, const_tree, bool);
+static rtx sparc_function_arg (cumulative_args_t, const function_arg_info &);
 static rtx sparc_function_incoming_arg (cumulative_args_t,
-					machine_mode, const_tree, bool);
+					const function_arg_info &);
 static pad_direction sparc_function_arg_padding (machine_mode, const_tree);
 static unsigned int sparc_function_arg_boundary (machine_mode,
 						 const_tree);
@@ -7379,24 +7376,22 @@ function_arg_vector_value (int size, int
 
    CUM is a variable of type CUMULATIVE_ARGS which gives info about
     the preceding args and about the function being called.
-   MODE is the argument's machine mode.
-   TYPE is the data type of the argument (as a tree).
-    This is null for libcalls where that information may
-    not be available.
-   NAMED is true if this argument is a named parameter
-    (otherwise it is an extra parameter matching an ellipsis).
+   ARG is a description of the argument.
    INCOMING_P is false for TARGET_FUNCTION_ARG, true for
     TARGET_FUNCTION_INCOMING_ARG.  */
 
 static rtx
-sparc_function_arg_1 (cumulative_args_t cum_v, machine_mode mode,
-		      const_tree type, bool named, bool incoming)
+sparc_function_arg_1 (cumulative_args_t cum_v, const function_arg_info &arg,
+		      bool incoming)
 {
   const CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   const int regbase
     = incoming ? SPARC_INCOMING_INT_ARG_FIRST : SPARC_OUTGOING_INT_ARG_FIRST;
   int slotno, regno, padding;
+  tree type = arg.type;
+  machine_mode mode = arg.mode;
   enum mode_class mclass = GET_MODE_CLASS (mode);
+  bool named = arg.named;
 
   slotno
     = function_arg_slotno (cum, mode, type, named, incoming, &regno, &padding);
@@ -7495,19 +7490,18 @@ sparc_function_arg_1 (cumulative_args_t
 /* Handle the TARGET_FUNCTION_ARG target hook.  */
 
 static rtx
-sparc_function_arg (cumulative_args_t cum, machine_mode mode,
-		    const_tree type, bool named)
+sparc_function_arg (cumulative_args_t cum, const function_arg_info &arg)
 {
-  return sparc_function_arg_1 (cum, mode, type, named, false);
+  return sparc_function_arg_1 (cum, arg, false);
 }
 
 /* Handle the TARGET_FUNCTION_INCOMING_ARG target hook.  */
 
 static rtx
-sparc_function_incoming_arg (cumulative_args_t cum, machine_mode mode,
-			     const_tree type, bool named)
+sparc_function_incoming_arg (cumulative_args_t cum,
+			     const function_arg_info &arg)
 {
-  return sparc_function_arg_1 (cum, mode, type, named, true);
+  return sparc_function_arg_1 (cum, arg, true);
 }
 
 /* For sparc64, objects requiring 16 byte alignment are passed that way.  */
Index: gcc/config/spu/spu.c
===================================================================
--- gcc/config/spu/spu.c	2019-08-19 15:58:34.846031154 +0100
+++ gcc/config/spu/spu.c	2019-08-19 15:58:42.421976335 +0100
@@ -3829,9 +3829,7 @@ spu_function_value (const_tree type, con
 }
 
 static rtx
-spu_function_arg (cumulative_args_t cum_v,
-		  machine_mode mode,
-		  const_tree type, bool named ATTRIBUTE_UNUSED)
+spu_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   int byte_size;
@@ -3839,8 +3837,7 @@ spu_function_arg (cumulative_args_t cum_
   if (*cum >= MAX_REGISTER_ARGS)
     return 0;
 
-  byte_size = ((mode == BLKmode)
-	       ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
+  byte_size = arg.promoted_size_in_bytes ();
 
   /* The ABI does not allow parameters to be passed partially in
      reg and partially in stack. */
@@ -3848,7 +3845,7 @@ spu_function_arg (cumulative_args_t cum_
     return 0;
 
   /* Make sure small structs are left justified in a register. */
-  if ((mode == BLKmode || (type && AGGREGATE_TYPE_P (type)))
+  if ((arg.mode == BLKmode || arg.aggregate_type_p ())
       && byte_size < UNITS_PER_WORD && byte_size > 0)
     {
       machine_mode smode;
@@ -3859,10 +3856,10 @@ spu_function_arg (cumulative_args_t cum_
       gr_reg = gen_rtx_EXPR_LIST (VOIDmode,
 				  gen_rtx_REG (smode, FIRST_ARG_REGNUM + *cum),
 				  const0_rtx);
-      return gen_rtx_PARALLEL (mode, gen_rtvec (1, gr_reg));
+      return gen_rtx_PARALLEL (arg.mode, gen_rtvec (1, gr_reg));
     }
   else
-    return gen_rtx_REG (mode, FIRST_ARG_REGNUM + *cum);
+    return gen_rtx_REG (arg.mode, FIRST_ARG_REGNUM + *cum);
 }
 
 static void
Index: gcc/config/stormy16/stormy16.c
===================================================================
--- gcc/config/stormy16/stormy16.c	2019-08-19 15:58:16.098166809 +0100
+++ gcc/config/stormy16/stormy16.c	2019-08-19 15:58:42.421976335 +0100
@@ -1233,17 +1233,17 @@ xstormy16_function_arg_advance (cumulati
 }
 
 static rtx
-xstormy16_function_arg (cumulative_args_t cum_v, machine_mode mode,
-			const_tree type, bool named ATTRIBUTE_UNUSED)
+xstormy16_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
-  if (mode == VOIDmode)
+  if (arg.end_marker_p ())
     return const0_rtx;
-  if (targetm.calls.must_pass_in_stack (mode, type)
-      || *cum + XSTORMY16_WORD_SIZE (type, mode) > NUM_ARGUMENT_REGISTERS)
+  if (targetm.calls.must_pass_in_stack (arg.mode, arg.type)
+      || (*cum + XSTORMY16_WORD_SIZE (arg.type, arg.mode)
+	  > NUM_ARGUMENT_REGISTERS))
     return NULL_RTX;
-  return gen_rtx_REG (mode, *cum + FIRST_ARGUMENT_REGISTER);
+  return gen_rtx_REG (arg.mode, *cum + FIRST_ARGUMENT_REGISTER);
 }
 
 /* Build the va_list type.
Index: gcc/config/tilegx/tilegx.c
===================================================================
--- gcc/config/tilegx/tilegx.c	2019-08-19 15:58:34.850031127 +0100
+++ gcc/config/tilegx/tilegx.c	2019-08-19 15:58:42.421976335 +0100
@@ -216,13 +216,10 @@ tilegx_function_arg_boundary (machine_mo
 
 /* Implement TARGET_FUNCTION_ARG.  */
 static rtx
-tilegx_function_arg (cumulative_args_t cum_v,
-		     machine_mode mode,
-		     const_tree type, bool named ATTRIBUTE_UNUSED)
+tilegx_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS cum = *get_cumulative_args (cum_v);
-  int byte_size = ((mode == BLKmode)
-		   ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
+  int byte_size = arg.promoted_size_in_bytes ();
   bool doubleword_aligned_p;
 
   if (cum >= TILEGX_NUM_ARG_REGS)
@@ -230,7 +227,7 @@ tilegx_function_arg (cumulative_args_t c
 
   /* See whether the argument has doubleword alignment.  */
   doubleword_aligned_p =
-    tilegx_function_arg_boundary (mode, type) > BITS_PER_WORD;
+    tilegx_function_arg_boundary (arg.mode, arg.type) > BITS_PER_WORD;
 
   if (doubleword_aligned_p)
     cum += cum & 1;
@@ -241,7 +238,7 @@ tilegx_function_arg (cumulative_args_t c
       > TILEGX_NUM_ARG_REGS)
     return NULL_RTX;
 
-  return gen_rtx_REG (mode, cum);
+  return gen_rtx_REG (arg.mode, cum);
 }
 
 
Index: gcc/config/tilepro/tilepro.c
===================================================================
--- gcc/config/tilepro/tilepro.c	2019-08-19 15:58:34.850031127 +0100
+++ gcc/config/tilepro/tilepro.c	2019-08-19 15:58:42.421976335 +0100
@@ -168,13 +168,10 @@ tilepro_function_arg_boundary (machine_m
 
 /* Implement TARGET_FUNCTION_ARG.  */
 static rtx
-tilepro_function_arg (cumulative_args_t cum_v,
-		      machine_mode mode,
-		      const_tree type, bool named ATTRIBUTE_UNUSED)
+tilepro_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS cum = *get_cumulative_args (cum_v);
-  int byte_size = ((mode == BLKmode)
-		   ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
+  int byte_size = arg.promoted_size_in_bytes ();
   bool doubleword_aligned_p;
 
   if (cum >= TILEPRO_NUM_ARG_REGS)
@@ -182,7 +179,7 @@ tilepro_function_arg (cumulative_args_t
 
   /* See whether the argument has doubleword alignment.  */
   doubleword_aligned_p =
-    tilepro_function_arg_boundary (mode, type) > BITS_PER_WORD;
+    tilepro_function_arg_boundary (arg.mode, arg.type) > BITS_PER_WORD;
 
   if (doubleword_aligned_p)
     cum += cum & 1;
@@ -193,7 +190,7 @@ tilepro_function_arg (cumulative_args_t
       > TILEPRO_NUM_ARG_REGS)
     return NULL_RTX;
 
-  return gen_rtx_REG (mode, cum);
+  return gen_rtx_REG (arg.mode, cum);
 }
 
 
Index: gcc/config/v850/v850.c
===================================================================
--- gcc/config/v850/v850.c	2019-08-19 15:58:28.446077464 +0100
+++ gcc/config/v850/v850.c	2019-08-19 15:58:42.421976335 +0100
@@ -119,26 +119,20 @@ v850_pass_by_reference (cumulative_args_
   return size > 8;
 }
 
-/* Return an RTX to represent where an argument with mode MODE
-   and type TYPE will be passed to a function.  If the result
-   is NULL_RTX, the argument will be pushed.  */
+/* Return an RTX to represent where argument ARG will be passed to a function.
+   If the result is NULL_RTX, the argument will be pushed.  */
 
 static rtx
-v850_function_arg (cumulative_args_t cum_v, machine_mode mode,
-		   const_tree type, bool named)
+v850_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   rtx result = NULL_RTX;
   int size, align;
 
-  if (!named)
+  if (!arg.named)
     return NULL_RTX;
 
-  if (mode == BLKmode)
-    size = int_size_in_bytes (type);
-  else
-    size = GET_MODE_SIZE (mode);
-
+  size = arg.promoted_size_in_bytes ();
   size = (size + UNITS_PER_WORD -1) & ~(UNITS_PER_WORD -1);
 
   if (size < 1)
@@ -150,8 +144,8 @@ v850_function_arg (cumulative_args_t cum
 
   if (!TARGET_GCC_ABI)
     align = UNITS_PER_WORD;
-  else if (size <= UNITS_PER_WORD && type)
-    align = TYPE_ALIGN (type) / BITS_PER_UNIT;
+  else if (size <= UNITS_PER_WORD && arg.type)
+    align = TYPE_ALIGN (arg.type) / BITS_PER_UNIT;
   else
     align = size;
 
@@ -160,23 +154,23 @@ v850_function_arg (cumulative_args_t cum
   if (cum->nbytes > 4 * UNITS_PER_WORD)
     return NULL_RTX;
 
-  if (type == NULL_TREE
+  if (arg.type == NULL_TREE
       && cum->nbytes + size > 4 * UNITS_PER_WORD)
     return NULL_RTX;
 
   switch (cum->nbytes / UNITS_PER_WORD)
     {
     case 0:
-      result = gen_rtx_REG (mode, 6);
+      result = gen_rtx_REG (arg.mode, 6);
       break;
     case 1:
-      result = gen_rtx_REG (mode, 7);
+      result = gen_rtx_REG (arg.mode, 7);
       break;
     case 2:
-      result = gen_rtx_REG (mode, 8);
+      result = gen_rtx_REG (arg.mode, 8);
       break;
     case 3:
-      result = gen_rtx_REG (mode, 9);
+      result = gen_rtx_REG (arg.mode, 9);
       break;
     default:
       result = NULL_RTX;
Index: gcc/config/vax/vax.c
===================================================================
--- gcc/config/vax/vax.c	2019-06-21 15:37:50.187874344 +0100
+++ gcc/config/vax/vax.c	2019-08-19 15:58:42.421976335 +0100
@@ -54,8 +54,7 @@ static void vax_output_mi_thunk (FILE *,
 static int vax_address_cost_1 (rtx);
 static int vax_address_cost (rtx, machine_mode, addr_space_t, bool);
 static bool vax_rtx_costs (rtx, machine_mode, int, int, int *, bool);
-static rtx vax_function_arg (cumulative_args_t, machine_mode,
-			     const_tree, bool);
+static rtx vax_function_arg (cumulative_args_t, const function_arg_info &);
 static void vax_function_arg_advance (cumulative_args_t, machine_mode,
 				      const_tree, bool);
 static rtx vax_struct_value_rtx (tree, int);
@@ -2141,26 +2140,10 @@ vax_return_pops_args (tree fundecl ATTRI
   return size > 255 * 4 ? 0 : (HOST_WIDE_INT) size;
 }
 
-/* Define where to put the arguments to a function.
-   Value is zero to push the argument on the stack,
-   or a hard register in which to store the argument.
-
-   MODE is the argument's machine mode.
-   TYPE is the data type of the argument (as a tree).
-    This is null for libcalls where that information may
-    not be available.
-   CUM is a variable of type CUMULATIVE_ARGS which gives info about
-    the preceding args and about the function being called.
-   NAMED is nonzero if this argument is a named parameter
-    (otherwise it is an extra parameter matching an ellipsis).  */
-
-/* On the VAX all args are pushed.  */
+/* Implement TARGET_FUNCTION_ARG.  On the VAX all args are pushed.  */
 
 static rtx
-vax_function_arg (cumulative_args_t cum ATTRIBUTE_UNUSED,
-		  machine_mode mode ATTRIBUTE_UNUSED,
-		  const_tree type ATTRIBUTE_UNUSED,
-		  bool named ATTRIBUTE_UNUSED)
+vax_function_arg (cumulative_args_t, const function_arg_info &)
 {
   return NULL_RTX;
 }
Index: gcc/config/visium/visium.c
===================================================================
--- gcc/config/visium/visium.c	2019-08-19 15:58:34.850031127 +0100
+++ gcc/config/visium/visium.c	2019-08-19 15:58:42.421976335 +0100
@@ -161,8 +161,7 @@ static struct machine_function *visium_i
 static bool visium_pass_by_reference (cumulative_args_t,
 				      const function_arg_info &);
 
-static rtx visium_function_arg (cumulative_args_t, machine_mode,
-				const_tree, bool);
+static rtx visium_function_arg (cumulative_args_t, const function_arg_info &);
 
 static void visium_function_arg_advance (cumulative_args_t, machine_mode,
 					 const_tree, bool);
@@ -1330,33 +1329,31 @@ visium_pass_by_reference (cumulative_arg
    in general registers.  */
 
 static rtx
-visium_function_arg (cumulative_args_t pcum_v, machine_mode mode,
-		     const_tree type ATTRIBUTE_UNUSED,
-		     bool named ATTRIBUTE_UNUSED)
+visium_function_arg (cumulative_args_t pcum_v, const function_arg_info &arg)
 {
   int size;
   CUMULATIVE_ARGS *ca = get_cumulative_args (pcum_v);
 
-  size = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
-  if (mode == VOIDmode)
+  size = (GET_MODE_SIZE (arg.mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+  if (arg.end_marker_p ())
     return GEN_INT (0);
 
   /* Scalar or complex single precision floating point arguments are returned
      in floating registers.  */
   if (TARGET_FPU
-      && ((GET_MODE_CLASS (mode) == MODE_FLOAT
-	   && GET_MODE_SIZE (mode) <= UNITS_PER_HWFPVALUE)
-	  || (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
-	      && GET_MODE_SIZE (mode) <= UNITS_PER_HWFPVALUE * 2)))
+      && ((GET_MODE_CLASS (arg.mode) == MODE_FLOAT
+	   && GET_MODE_SIZE (arg.mode) <= UNITS_PER_HWFPVALUE)
+	  || (GET_MODE_CLASS (arg.mode) == MODE_COMPLEX_FLOAT
+	      && GET_MODE_SIZE (arg.mode) <= UNITS_PER_HWFPVALUE * 2)))
     {
       if (ca->frcount + size <= MAX_ARGS_IN_FP_REGISTERS)
-	return gen_rtx_REG (mode, FP_ARG_FIRST + ca->frcount);
+	return gen_rtx_REG (arg.mode, FP_ARG_FIRST + ca->frcount);
       else
 	return NULL_RTX;
     }
 
   if (ca->grcount + size <= MAX_ARGS_IN_GP_REGISTERS)
-    return gen_rtx_REG (mode, ca->grcount + GP_ARG_FIRST);
+    return gen_rtx_REG (arg.mode, ca->grcount + GP_ARG_FIRST);
 
   return NULL_RTX;
 }
Index: gcc/config/xtensa/xtensa.c
===================================================================
--- gcc/config/xtensa/xtensa.c	2019-08-19 15:58:16.098166809 +0100
+++ gcc/config/xtensa/xtensa.c	2019-08-19 15:58:42.421976335 +0100
@@ -143,10 +143,9 @@ static tree xtensa_gimplify_va_arg_expr
 					 gimple_seq *);
 static void xtensa_function_arg_advance (cumulative_args_t, machine_mode,
 					 const_tree, bool);
-static rtx xtensa_function_arg (cumulative_args_t, machine_mode,
-				const_tree, bool);
+static rtx xtensa_function_arg (cumulative_args_t, const function_arg_info &);
 static rtx xtensa_function_incoming_arg (cumulative_args_t,
-					 machine_mode, const_tree, bool);
+					 const function_arg_info &);
 static rtx xtensa_function_value (const_tree, const_tree, bool);
 static rtx xtensa_libcall_value (machine_mode, const_rtx);
 static bool xtensa_function_value_regno_p (const unsigned int);
@@ -2128,13 +2127,13 @@ xtensa_function_arg_advance (cumulative_
 }
 
 
-/* Return an RTL expression containing the register for the given mode,
+/* Return an RTL expression containing the register for the given argument,
    or 0 if the argument is to be passed on the stack.  INCOMING_P is nonzero
    if this is an incoming argument to the current function.  */
 
 static rtx
-xtensa_function_arg_1 (cumulative_args_t cum_v, machine_mode mode,
-		       const_tree type, bool incoming_p)
+xtensa_function_arg_1 (cumulative_args_t cum_v, const function_arg_info &arg,
+		       bool incoming_p)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   int regbase, words, max;
@@ -2145,13 +2144,12 @@ xtensa_function_arg_1 (cumulative_args_t
   regbase = (incoming_p ? GP_ARG_FIRST : GP_OUTGOING_ARG_FIRST);
   max = MAX_ARGS_IN_REGISTERS;
 
-  words = (((mode != BLKmode)
-	    ? (int) GET_MODE_SIZE (mode)
-	    : int_size_in_bytes (type)) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+  words = ((arg.promoted_size_in_bytes () + UNITS_PER_WORD - 1)
+	   / UNITS_PER_WORD);
 
-  if (type && (TYPE_ALIGN (type) > BITS_PER_WORD))
+  if (arg.type && (TYPE_ALIGN (arg.type) > BITS_PER_WORD))
     {
-      int align = MIN (TYPE_ALIGN (type), STACK_BOUNDARY) / BITS_PER_WORD;
+      int align = MIN (TYPE_ALIGN (arg.type), STACK_BOUNDARY) / BITS_PER_WORD;
       *arg_words = (*arg_words + align - 1) & -align;
     }
 
@@ -2163,25 +2161,24 @@ xtensa_function_arg_1 (cumulative_args_t
   if (cum->incoming && regno <= A7_REG && regno + words > A7_REG)
     cfun->machine->need_a7_copy = TARGET_WINDOWED_ABI;
 
-  return gen_rtx_REG (mode, regno);
+  return gen_rtx_REG (arg.mode, regno);
 }
 
 /* Implement TARGET_FUNCTION_ARG.  */
 
 static rtx
-xtensa_function_arg (cumulative_args_t cum, machine_mode mode,
-		     const_tree type, bool named ATTRIBUTE_UNUSED)
+xtensa_function_arg (cumulative_args_t cum, const function_arg_info &arg)
 {
-  return xtensa_function_arg_1 (cum, mode, type, false);
+  return xtensa_function_arg_1 (cum, arg, false);
 }
 
 /* Implement TARGET_FUNCTION_INCOMING_ARG.  */
 
 static rtx
-xtensa_function_incoming_arg (cumulative_args_t cum, machine_mode mode,
-			      const_tree type, bool named ATTRIBUTE_UNUSED)
+xtensa_function_incoming_arg (cumulative_args_t cum,
+			      const function_arg_info &arg)
 {
-  return xtensa_function_arg_1 (cum, mode, type, true);
+  return xtensa_function_arg_1 (cum, arg, true);
 }
 
 static unsigned int

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [07/13] Use function_arg_info for TARGET_FUNCTION_ARG_ADVANCE
  2019-08-19 15:15 [00/13] Pass an argument descriptor to target hooks Richard Sandiford
                   ` (5 preceding siblings ...)
  2019-08-19 15:21 ` [06/13] Use function_arg_info for TARGET_FUNCTION_(INCOMING_)ARG Richard Sandiford
@ 2019-08-19 15:22 ` Richard Sandiford
  2019-08-19 21:11   ` Jeff Law
  2019-08-19 15:23 ` [08/13] Use function_arg_info for TARGET_CALLEE_COPIES Richard Sandiford
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 27+ messages in thread
From: Richard Sandiford @ 2019-08-19 15:22 UTC (permalink / raw)
  To: gcc-patches

Use function_arg_info for TARGET_FUNCTION_ARG_ADVANCE.

There seems to be a bit of confusion around this one.  Almost all
callers pass the same arguments as TARGET_FUNCTION_ARG, meaning
that the mode is the promoted mode rather than the type mode.
But the calls.c handling for normal typed arguments instead passes
the unpromoted TYPE_MODE (despite passing the promoted mode to
TARGET_FUNCTION_ARG).  I've kept this behaviour with a ??? comment.

(The calls.c handling of libgcc functions does pass the promoted
mode though, as does the function.c handling of incoming arguments.)

Also, a couple of the arm callers don't seem to be using the hook
correctly.  Again I kept the current choices and added a ??? comment.


2019-08-19  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	* target.def (function_arg_advance): Take a function_arg_info instead
	of a mode, type and named flag.
	* doc/tm.texi: Regenerate.
	* targhooks.h (default_function_arg_advance): Take a function_arg_info
	instead of a mode, type and named flag.
	* targhooks.c (default_function_arg_advance): Likewise.
	* calls.c (initialize_argument_information): Update call to
	targetm.calls.function_arg_advance.
	(emit_library_call_value_1): Likewise.
	* dse.c (get_call_args): Likewise.
	* expr.c (block_move_libcall_safe_for_call_parm): Likewise.
	* function.c (assign_parms, gimplify_parameters): Likewise.
	* var-tracking.c (prepare_call_arguments): Likewise.
	* config/aarch64/aarch64.c (aarch64_function_arg_advance): Take a
	function_arg_info instead of a mode, type and named flag.
	(aarch64_setup_incoming_varargs): Update call accordingly.
	* config/alpha/alpha.c (alpha_function_arg_advance): Take a
	function_arg_info instead of a mode, type and named flag.
	(alpha_setup_incoming_varargs): Update call accordingly.
	* config/arc/arc.c (arc_function_arg_advance): Take a
	function_arg_info instead of a mode, type and named flag.
	(arc_setup_incoming_varargs): Update call accordingly.
	* config/arm/arm.c (arm_function_arg_advance): Take a
	function_arg_info instead of a mode, type and named flag.
	(cmse_func_args_or_return_in_stack): Update call accordingly.
	(arm_function_ok_for_sibcall): Likewise.
	(cmse_nonsecure_call_clear_caller_saved): Likewise.
	* config/avr/avr.c (avr_function_arg_advance): Take a
	function_arg_info instead of a mode, type and named flag.
	* config/bfin/bfin.c (bfin_function_arg_advance): Likewise.
	* config/c6x/c6x.c (c6x_function_arg_advance): Likewise.
	(c6x_call_saved_register_used): Update call accordingly.
	* config/cr16/cr16.c (cr16_function_arg_advance): Take a
	function_arg_info instead of a mode, type and named flag.
	* config/cris/cris.c (cris_function_arg_advance): Likewise.
	* config/csky/csky.c (csky_function_arg_advance): Likewise.
	(csky_setup_incoming_varargs): Update call accordingly.
	* config/epiphany/epiphany.c (epiphany_function_arg_advance): Take a
	function_arg_info instead of a mode, type and named flag.
	* config/fr30/fr30.c (fr30_function_arg_advance): Likewise.
	* config/frv/frv.c (frv_function_arg_advance): Likewise.
	* config/ft32/ft32.c (ft32_function_arg_advance): Likewise.
	* config/gcn/gcn.c (gcn_function_arg_advance): Likewise.
	* config/h8300/h8300.c (h8300_function_arg_advance): Likewise.
	* config/i386/i386.c (ix86_function_arg_advance): Likewise.
	(ix86_setup_incoming_varargs): Update call accordingly.
	* config/ia64/ia64.c (ia64_function_arg_advance): Take a
	function_arg_info instead of a mode, type and named flag.
	(ia64_setup_incoming_varargs): Update call accordingly.
	* config/iq2000/iq2000.c (iq2000_function_arg_advance): Take a
	function_arg_info instead of a mode, type and named flag.
	(iq2000_expand_prologue): Update call accordingly.
	* config/lm32/lm32.c (lm32_function_arg_advance): Take a
	function_arg_info instead of a mode, type and named flag.
	* config/m32c/m32c.c (m32c_function_arg_advance): Likewise.
	* config/m32r/m32r.c (m32r_function_arg_advance): Likewise.
	* config/m68k/m68k.c (m68k_function_arg_advance): Likewise.
	* config/mcore/mcore.c (mcore_function_arg_advance): Likewise.
	* config/microblaze/microblaze.c (microblaze_function_arg_advance):
	Likewise.
	(microblaze_expand_prologue): Update call accordingly.
	* config/mips/mips.c (mips_function_arg_advance): Take a
	function_arg_info instead of a mode, type and named flag.
	(mips_setup_incoming_varargs): Update call accordingly.
	(mips_output_args_xfer): Likewise.
	* config/mmix/mmix.c (mmix_function_arg_advance): Take a
	function_arg_info instead of a mode, type and named flag.
	* config/mn10300/mn10300.c (mn10300_function_arg_advance): Likewise.
	* config/moxie/moxie.c (moxie_function_arg_advance): Likewise.
	* config/msp430/msp430.c (msp430_function_arg_advance): Likewise.
	* config/nds32/nds32.c (nds32_function_arg_advance): Likewise.
	* config/nios2/nios2.c (nios2_function_arg_advance): Likewise.
	(nios2_setup_incoming_varargs): Update call accordingly.
	* config/nvptx/nvptx.c (nvptx_function_arg_advance): Take a
	function_arg_info instead of a mode, type and named flag.
	* config/or1k/or1k.c (or1k_function_arg_advance): Likewise.
	* config/pa/pa.c (pa_function_arg_advance): Likewise.
	* config/pdp11/pdp11.c (pdp11_function_arg_advance): Likewise.
	* config/pru/pru.c (pru_function_arg_advance): Likewise.
	* config/riscv/riscv.c (riscv_function_arg_advance): Likewise.
	(riscv_setup_incoming_varargs): Update call accordingly.
	* config/rl78/rl78.c (rl78_function_arg_advance): Take a
	function_arg_info instead of a mode, type and named flag.
	* config/rs6000/rs6000-internal.h (rs6000_function_arg_advance):
	Likewise.
	* config/rs6000/rs6000-call.c (rs6000_function_arg_advance): Likewise.
	(rs6000_parm_needs_stack): Update call accordingly.
	* config/rx/rx.c (rx_function_arg_advance): Take a function_arg_info
	instead of a mode, type and named flag.
	* config/s390/s390.c (s390_function_arg_advance): Likewise.
	(s390_call_saved_register_used): Update call accordingly.
	* config/sh/sh.c (sh_function_arg_advance): Take a function_arg_info
	instead of a mode, type and named flag.
	(sh_output_mi_thunk): Update call accordingly.
	* config/sparc/sparc.c (sparc_function_arg_advance): Take a
	function_arg_info instead of a mode, type and named flag.
	* config/spu/spu.c (spu_function_arg_advance): Likewise.
	(spu_setup_incoming_varargs): Update call accordingly.
	* config/stormy16/stormy16.c (xstormy16_function_arg_advance): Take a
	function_arg_info instead of a mode, type and named flag.
	* config/tilegx/tilegx.c (tilegx_function_arg_advance): Likewise.
	(tilegx_setup_incoming_varargs): Update call accordingly.
	* config/tilepro/tilepro.c (tilepro_function_arg_advance): Take a
	function_arg_info instead of a mode, type and named flag.
	(tilegx_setup_incoming_varargs): Update call accordingly.
	* config/v850/v850.c (v850_function_arg_advance): Take a
	function_arg_info instead of a mode, type and named flag.
	* config/vax/vax.c (vax_function_arg_advance): Likewise.
	* config/visium/visium.c (visium_function_arg_advance): Likewise.
	(visium_setup_incoming_varargs): Update call accordingly.
	* config/xtensa/xtensa.c (xtensa_function_arg_advance): Take a
	function_arg_info instead of a mode, type and named flag.

Index: gcc/target.def
===================================================================
--- gcc/target.def	2019-08-19 15:58:42.425976307 +0100
+++ gcc/target.def	2019-08-19 15:58:50.345918999 +0100
@@ -4686,8 +4686,7 @@ register to be used by the caller for th
 DEFHOOK
 (function_arg_advance,
  "This hook updates the summarizer variable pointed to by @var{ca} to\n\
-advance past an argument in the argument list.  The values @var{mode},\n\
-@var{type} and @var{named} describe that argument.  Once this is done,\n\
+advance past argument @var{arg} in the argument list.  Once this is done,\n\
 the variable @var{cum} is suitable for analyzing the @emph{following}\n\
 argument with @code{TARGET_FUNCTION_ARG}, etc.\n\
 \n\
@@ -4695,7 +4694,7 @@ This hook need not do anything if the ar
 on the stack.  The compiler knows how to track the amount of stack space\n\
 used for arguments without any special help.",
  void,
- (cumulative_args_t ca, machine_mode mode, const_tree type, bool named),
+ (cumulative_args_t ca, const function_arg_info &arg),
  default_function_arg_advance)
 
 DEFHOOK
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	2019-08-19 15:58:42.421976335 +0100
+++ gcc/doc/tm.texi	2019-08-19 15:58:50.341919030 +0100
@@ -4159,10 +4159,9 @@ argument @var{libname} exists for symmet
 @c --mew 5feb93   i switched the order of the sentences.  --mew 10feb93
 @end defmac
 
-@deftypefn {Target Hook} void TARGET_FUNCTION_ARG_ADVANCE (cumulative_args_t @var{ca}, machine_mode @var{mode}, const_tree @var{type}, bool @var{named})
+@deftypefn {Target Hook} void TARGET_FUNCTION_ARG_ADVANCE (cumulative_args_t @var{ca}, const function_arg_info @var{&arg})
 This hook updates the summarizer variable pointed to by @var{ca} to
-advance past an argument in the argument list.  The values @var{mode},
-@var{type} and @var{named} describe that argument.  Once this is done,
+advance past argument @var{arg} in the argument list.  Once this is done,
 the variable @var{cum} is suitable for analyzing the @emph{following}
 argument with @code{TARGET_FUNCTION_ARG}, etc.
 
Index: gcc/targhooks.h
===================================================================
--- gcc/targhooks.h	2019-08-19 15:58:42.425976307 +0100
+++ gcc/targhooks.h	2019-08-19 15:58:50.345918999 +0100
@@ -148,7 +148,7 @@ extern bool hook_bool_CUMULATIVE_ARGS_tr
 extern const char *hook_invalid_arg_for_unprototyped_fn
   (const_tree, const_tree, const_tree);
 extern void default_function_arg_advance
-  (cumulative_args_t, machine_mode, const_tree, bool);
+  (cumulative_args_t, const function_arg_info &);
 extern HOST_WIDE_INT default_function_arg_offset (machine_mode, const_tree);
 extern pad_direction default_function_arg_padding (machine_mode, const_tree);
 extern rtx default_function_arg (cumulative_args_t, const function_arg_info &);
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c	2019-08-19 15:58:42.425976307 +0100
+++ gcc/targhooks.c	2019-08-19 15:58:50.345918999 +0100
@@ -784,10 +784,7 @@ hook_void_CUMULATIVE_ARGS_tree (cumulati
 }
 
 void
-default_function_arg_advance (cumulative_args_t ca ATTRIBUTE_UNUSED,
-			      machine_mode mode ATTRIBUTE_UNUSED,
-			      const_tree type ATTRIBUTE_UNUSED,
-			      bool named ATTRIBUTE_UNUSED)
+default_function_arg_advance (cumulative_args_t, const function_arg_info &)
 {
   gcc_unreachable ();
 }
Index: gcc/calls.c
===================================================================
--- gcc/calls.c	2019-08-19 15:58:42.381976625 +0100
+++ gcc/calls.c	2019-08-19 15:58:50.301919320 +0100
@@ -2192,8 +2192,13 @@ initialize_argument_information (int num
       /* Increment ARGS_SO_FAR, which has info about which arg-registers
 	 have been used, etc.  */
 
-      targetm.calls.function_arg_advance (args_so_far, TYPE_MODE (type),
-					  type, argpos < n_named_args);
+      /* ??? Traditionally we've passed TYPE_MODE here, instead of the
+	 promoted_mode used for function_arg above.  However, the
+	 corresponding handling of incoming arguments in function.c
+	 does pass the promoted mode.  */
+      function_arg_info arg_to_skip (type, TYPE_MODE (type),
+				     argpos < n_named_args);
+      targetm.calls.function_arg_advance (args_so_far, arg_to_skip);
 
       /* Store argument values for functions decorated with attribute
 	 alloc_size.  */
@@ -4881,7 +4886,7 @@ emit_library_call_value_1 (int retval, r
 	  || reg_parm_stack_space > 0)
 	args_size.constant += argvec[count].locate.size.constant;
 
-      targetm.calls.function_arg_advance (args_so_far, Pmode, (tree) 0, true);
+      targetm.calls.function_arg_advance (args_so_far, ptr_arg);
 
       count++;
     }
@@ -4977,7 +4982,7 @@ emit_library_call_value_1 (int retval, r
 			     known_le (GET_MODE_SIZE (mode), UNITS_PER_WORD));
 #endif
 
-      targetm.calls.function_arg_advance (args_so_far, mode, (tree) 0, true);
+      targetm.calls.function_arg_advance (args_so_far, arg);
     }
 
   for (int i = 0; i < nargs; i++)
Index: gcc/dse.c
===================================================================
--- gcc/dse.c	2019-08-19 15:58:42.421976335 +0100
+++ gcc/dse.c	2019-08-19 15:58:50.345918999 +0100
@@ -2377,7 +2377,7 @@ get_call_args (rtx call_insn, tree fn, r
       if (tmp)
 	args[idx] = tmp;
 
-      targetm.calls.function_arg_advance (args_so_far, mode, NULL_TREE, true);
+      targetm.calls.function_arg_advance (args_so_far, arg);
     }
   if (arg != void_list_node || idx != nargs)
     return false;
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	2019-08-19 15:58:42.425976307 +0100
+++ gcc/expr.c	2019-08-19 15:58:50.345918999 +0100
@@ -1715,8 +1715,7 @@ block_move_libcall_safe_for_call_parm (v
 	  return false;
 	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);
+	targetm.calls.function_arg_advance (args_so_far, arg_info);
       }
   }
   return true;
Index: gcc/function.c
===================================================================
--- gcc/function.c	2019-08-19 15:58:42.425976307 +0100
+++ gcc/function.c	2019-08-19 15:58:50.345918999 +0100
@@ -3657,8 +3657,9 @@ assign_parms (tree fndecl)
 	assign_parms_setup_varargs (&all, &data, false);
 
       /* Update info on where next arg arrives in registers.  */
-      targetm.calls.function_arg_advance (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);
+      targetm.calls.function_arg_advance (all.args_so_far, arg);
     }
 
   if (targetm.calls.split_complex_arg)
@@ -3845,8 +3846,9 @@ gimplify_parameters (gimple_seq *cleanup
 	continue;
 
       /* Update info on where next arg arrives in registers.  */
-      targetm.calls.function_arg_advance (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);
+      targetm.calls.function_arg_advance (all.args_so_far, arg);
 
       /* ??? Once upon a time variable_size stuffed parameter list
 	 SAVE_EXPRs (amongst others) onto a pending sizes list.  This
Index: gcc/var-tracking.c
===================================================================
--- gcc/var-tracking.c	2019-08-19 15:58:42.425976307 +0100
+++ gcc/var-tracking.c	2019-08-19 15:58:50.345918999 +0100
@@ -6293,14 +6293,12 @@ prepare_call_arguments (basic_block bb,
 		  && targetm.calls.struct_value_rtx (type, 0) == 0)
 		{
 		  tree struct_addr = build_pointer_type (TREE_TYPE (type));
-		  machine_mode mode = TYPE_MODE (struct_addr);
 		  function_arg_info arg (struct_addr, /*named=*/true);
 		  rtx reg;
 		  INIT_CUMULATIVE_ARGS (args_so_far_v, type, NULL_RTX, fndecl,
 					nargs + 1);
 		  reg = targetm.calls.function_arg (args_so_far, arg);
-		  targetm.calls.function_arg_advance (args_so_far, mode,
-						      struct_addr, true);
+		  targetm.calls.function_arg_advance (args_so_far, arg);
 		  if (reg == NULL_RTX)
 		    {
 		      for (; link; link = XEXP (link, 1))
@@ -6489,8 +6487,7 @@ prepare_call_arguments (basic_block bb,
 			}
 		  }
 	      }
-	    targetm.calls.function_arg_advance (args_so_far, mode,
-						argtype, true);
+	    targetm.calls.function_arg_advance (args_so_far, arg);
 	    t = TREE_CHAIN (t);
 	  }
       }
Index: gcc/config/aarch64/aarch64.c
===================================================================
--- gcc/config/aarch64/aarch64.c	2019-08-19 15:58:42.385976597 +0100
+++ gcc/config/aarch64/aarch64.c	2019-08-19 15:58:50.305919288 +0100
@@ -4846,14 +4846,12 @@ aarch64_init_cumulative_args (CUMULATIVE
 
 static void
 aarch64_function_arg_advance (cumulative_args_t pcum_v,
-			      machine_mode mode,
-			      const_tree type,
-			      bool named)
+			      const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v);
   if (pcum->pcs_variant == ARM_PCS_AAPCS64)
     {
-      aarch64_layout_arg (pcum_v, mode, type, named);
+      aarch64_layout_arg (pcum_v, arg.mode, arg.type, arg.named);
       gcc_assert ((pcum->aapcs_reg != NULL_RTX)
 		  != (pcum->aapcs_stack_words != 0));
       pcum->aapcs_arg_processed = false;
@@ -14523,8 +14521,7 @@ aarch64_setup_incoming_varargs (cumulati
      argument.  Advance a local copy of CUM past the last "real" named
      argument, to find out how many registers are left over.  */
   local_cum = *cum;
-  aarch64_function_arg_advance (pack_cumulative_args(&local_cum),
-				arg.mode, arg.type, arg.named);
+  aarch64_function_arg_advance (pack_cumulative_args(&local_cum), arg);
 
   /* Found out how many registers we need to save.
      Honor tree-stdvar analysis results.  */
Index: gcc/config/alpha/alpha.c
===================================================================
--- gcc/config/alpha/alpha.c	2019-08-19 15:58:42.385976597 +0100
+++ gcc/config/alpha/alpha.c	2019-08-19 15:58:50.309919261 +0100
@@ -5606,23 +5606,21 @@ alpha_function_arg (cumulative_args_t cu
   return gen_rtx_REG (arg.mode, num_args + basereg);
 }
 
-/* Update the data in CUM to advance over an argument
-   of mode MODE and data type TYPE.
-   (TYPE is null for libcalls where that information may not be available.)  */
+/* Update the data in CUM to advance over argument ARG.  */
 
 static void
-alpha_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
-			    const_tree type, bool named ATTRIBUTE_UNUSED)
+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 (mode, type);
-  int increment = onstack ? 6 : ALPHA_ARG_SIZE (mode, type);
+  bool onstack = targetm.calls.must_pass_in_stack (arg.mode, arg.type);
+  int increment = onstack ? 6 : ALPHA_ARG_SIZE (arg.mode, arg.type);
 
 #if TARGET_ABI_OSF
   *cum += increment;
 #else
   if (!onstack && cum->num_args < 6)
-    cum->atypes[cum->num_args] = alpha_arg_type (mode);
+    cum->atypes[cum->num_args] = alpha_arg_type (arg.mode);
   cum->num_args += increment;
 #endif
 }
@@ -6090,8 +6088,7 @@ alpha_setup_incoming_varargs (cumulative
   CUMULATIVE_ARGS cum = *get_cumulative_args (pcum);
 
   /* Skip the current argument.  */
-  targetm.calls.function_arg_advance (pack_cumulative_args (&cum),
-				      arg.mode, arg.type, arg.named);
+  targetm.calls.function_arg_advance (pack_cumulative_args (&cum), arg);
 
 #if TARGET_ABI_OPEN_VMS
   /* For VMS, we allocate space for all 6 arg registers plus a count.
Index: gcc/config/arc/arc.c
===================================================================
--- gcc/config/arc/arc.c	2019-08-19 15:58:42.389976569 +0100
+++ gcc/config/arc/arc.c	2019-08-19 15:58:50.309919261 +0100
@@ -642,8 +642,8 @@ static bool arc_can_follow_jump (const r
 				 const rtx_insn *followee);
 
 static rtx frame_insn (rtx);
-static void arc_function_arg_advance (cumulative_args_t, machine_mode,
-				      const_tree, bool);
+static void arc_function_arg_advance (cumulative_args_t,
+				      const function_arg_info &);
 static rtx arc_legitimize_address_0 (rtx, rtx, machine_mode mode);
 
 /* initialize the GCC target structure.  */
@@ -2429,8 +2429,7 @@ arc_setup_incoming_varargs (cumulative_a
   /* We must treat `__builtin_va_alist' as an anonymous arg.  */
 
   next_cum = *get_cumulative_args (args_so_far);
-  arc_function_arg_advance (pack_cumulative_args (&next_cum),
-			    arg.mode, arg.type, arg.named);
+  arc_function_arg_advance (pack_cumulative_args (&next_cum), arg);
   first_anon_arg = next_cum;
 
   if (FUNCTION_ARG_REGNO_P (first_anon_arg))
@@ -6480,17 +6479,7 @@ arc_function_arg (cumulative_args_t cum_
   return ret;
 }
 
-/* The function to update the summarizer variable *CUM to advance past
-   an argument in the argument list.  The values MODE, TYPE and NAMED
-   describe that argument.  Once this is done, the variable *CUM is
-   suitable for analyzing the *following* argument with
-   `FUNCTION_ARG', etc.
-
-   This function need not do anything if the argument in question was
-   passed on the stack.  The compiler knows how to track the amount of
-   stack space used for arguments without any special help.
-
-   The function is used to implement macro FUNCTION_ARG_ADVANCE.  */
+/* Implement TARGET_FUNCTION_ARG_ADVANCE.  */
 /* For the ARC: the cum set here is passed on to function_arg where we
    look at its value and say which reg to use. Strategy: advance the
    regnumber here till we run out of arg regs, then set *cum to last
@@ -6500,18 +6489,15 @@ arc_function_arg (cumulative_args_t cum_
 
 static void
 arc_function_arg_advance (cumulative_args_t cum_v,
-			  machine_mode mode,
-			  const_tree type,
-			  bool named ATTRIBUTE_UNUSED)
+			  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 i;
 
   if (words)
-    *cum = ROUND_ADVANCE_CUM (*cum, mode, type);
+    *cum = ROUND_ADVANCE_CUM (*cum, arg.mode, arg.type);
   for (i = 0; i < words; i++)
     *cum = ARC_NEXT_ARG_REG (*cum);
 
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c	2019-08-19 15:58:42.393976538 +0100
+++ gcc/config/arm/arm.c	2019-08-19 15:58:50.317919202 +0100
@@ -190,8 +190,8 @@ static rtx emit_multi_reg_push (unsigned
 static int arm_arg_partial_bytes (cumulative_args_t,
 				  const function_arg_info &);
 static rtx arm_function_arg (cumulative_args_t, const function_arg_info &);
-static void arm_function_arg_advance (cumulative_args_t, machine_mode,
-				      const_tree, bool);
+static void arm_function_arg_advance (cumulative_args_t,
+				      const function_arg_info &);
 static pad_direction arm_function_arg_padding (machine_mode, const_tree);
 static unsigned int arm_function_arg_boundary (machine_mode, const_tree);
 static rtx aapcs_allocate_return_reg (machine_mode, const_tree,
@@ -6770,24 +6770,22 @@ arm_arg_partial_bytes (cumulative_args_t
   return 0;
 }
 
-/* Update the data in PCUM to advance over an argument
-   of mode MODE and data type TYPE.
-   (TYPE is null for libcalls where that information may not be available.)  */
+/* Update the data in PCUM to advance over argument ARG.  */
 
 static void
-arm_function_arg_advance (cumulative_args_t pcum_v, machine_mode mode,
-			  const_tree type, bool named)
+arm_function_arg_advance (cumulative_args_t pcum_v,
+			  const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v);
 
   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);
 
       if (pcum->aapcs_cprc_slot >= 0)
 	{
-	  aapcs_cp_arg_layout[pcum->aapcs_cprc_slot].advance (pcum, mode,
-							      type);
+	  aapcs_cp_arg_layout[pcum->aapcs_cprc_slot].advance (pcum, arg.mode,
+							      arg.type);
 	  pcum->aapcs_cprc_slot = -1;
 	}
 
@@ -6800,12 +6798,12 @@ arm_function_arg_advance (cumulative_arg
   else
     {
       pcum->nargs += 1;
-      if (arm_vector_mode_supported_p (mode)
+      if (arm_vector_mode_supported_p (arg.mode)
 	  && pcum->named_count > pcum->nargs
 	  && TARGET_IWMMXT_ABI)
 	pcum->iwmmxt_nregs += 1;
       else
-	pcum->nregs += ARM_NUM_REGS2 (mode, type);
+	pcum->nregs += ARM_NUM_REGS2 (arg.mode, arg.type);
     }
 }
 
@@ -6984,7 +6982,6 @@ cmse_func_args_or_return_in_stack (tree
   FOREACH_FUNCTION_ARGS (fntype, arg_type, args_iter)
     {
       rtx arg_rtx;
-      machine_mode arg_mode = TYPE_MODE (arg_type);
 
       prev_arg_type = arg_type;
       if (VOID_TYPE_P (arg_type))
@@ -6992,7 +6989,9 @@ cmse_func_args_or_return_in_stack (tree
 
       function_arg_info arg (arg_type, /*named=*/true);
       if (!first_param)
-	arm_function_arg_advance (args_so_far, arg_mode, arg_type, true);
+	/* ??? We should advance after processing the argument and pass
+	   the argument we're advancing past.  */
+	arm_function_arg_advance (args_so_far, arg);
       arg_rtx = arm_function_arg (args_so_far, arg);
       if (!arg_rtx || arm_arg_partial_bytes (args_so_far, arg))
 	{
@@ -7378,7 +7377,10 @@ arm_function_ok_for_sibcall (tree decl,
 	{
 	  tree type = TREE_VALUE (t);
 	  if (!VOID_TYPE_P (type))
-	    arm_function_arg_advance (cum_v, TYPE_MODE (type), type, true);
+	    {
+	      function_arg_info arg (type, /*named=*/true);
+	      arm_function_arg_advance (cum_v, arg);
+	    }
 	}
 
       function_arg_info arg (integer_type_node, /*named=*/true);
@@ -17441,15 +17443,15 @@ cmse_nonsecure_call_clear_caller_saved (
 	    {
 	      rtx arg_rtx;
 	      uint64_t to_clear_args_mask;
-	      machine_mode arg_mode = TYPE_MODE (arg_type);
 
 	      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);
+		/* ??? We should advance after processing the argument and pass
+		   the argument we're advancing past.  */
+		arm_function_arg_advance (args_so_far, arg);
 
 	      arg_rtx = arm_function_arg (args_so_far, arg);
 	      gcc_assert (REG_P (arg_rtx));
Index: gcc/config/avr/avr.c
===================================================================
--- gcc/config/avr/avr.c	2019-08-19 15:58:42.397976511 +0100
+++ gcc/config/avr/avr.c	2019-08-19 15:58:50.317919202 +0100
@@ -3405,11 +3405,11 @@ avr_function_arg (cumulative_args_t cum_
    in the argument list.  */
 
 static void
-avr_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
-                          const_tree type, bool named ATTRIBUTE_UNUSED)
+avr_function_arg_advance (cumulative_args_t cum_v,
+			  const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
-  int bytes = avr_num_arg_regs (mode, type);
+  int bytes = avr_num_arg_regs (arg.mode, arg.type);
 
   cum->nregs -= bytes;
   cum->regno -= bytes;
Index: gcc/config/bfin/bfin.c
===================================================================
--- gcc/config/bfin/bfin.c	2019-08-19 15:58:42.397976511 +0100
+++ gcc/config/bfin/bfin.c	2019-08-19 15:58:50.317919202 +0100
@@ -1647,18 +1647,16 @@ init_cumulative_args (CUMULATIVE_ARGS *c
   return;
 }
 
-/* Update the data in CUM to advance over an argument
-   of mode MODE and data type TYPE.
-   (TYPE is null for libcalls where that information may not be available.)  */
+/* Update the data in CUM to advance over argument ARG.  */
 
 static void
-bfin_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
-			   const_tree type, bool named ATTRIBUTE_UNUSED)
+bfin_function_arg_advance (cumulative_args_t cum_v,
+			   const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   int count, bytes, words;
 
-  bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
+  bytes = arg.promoted_size_in_bytes ();
   words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
 
   cum->words += words;
Index: gcc/config/c6x/c6x.c
===================================================================
--- gcc/config/c6x/c6x.c	2019-08-19 15:58:42.397976511 +0100
+++ gcc/config/c6x/c6x.c	2019-08-19 15:58:50.317919202 +0100
@@ -526,10 +526,7 @@ c6x_function_arg (cumulative_args_t cum_
 }
 
 static void
-c6x_function_arg_advance (cumulative_args_t cum_v,
-			  machine_mode mode ATTRIBUTE_UNUSED,
-			  const_tree type ATTRIBUTE_UNUSED,
-			  bool named ATTRIBUTE_UNUSED)
+c6x_function_arg_advance (cumulative_args_t cum_v, const function_arg_info &)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   cum->count++;
@@ -1136,7 +1133,7 @@ c6x_call_saved_register_used (tree call_
        function_arg_info arg (type, mode, /*named=*/false);
        parm_rtx = c6x_function_arg (cum, arg);
 
-       c6x_function_arg_advance (cum, mode, type, 0);
+       c6x_function_arg_advance (cum, arg);
 
        if (!parm_rtx)
 	 continue;
Index: gcc/config/cr16/cr16.c
===================================================================
--- gcc/config/cr16/cr16.c	2019-08-19 15:58:42.397976511 +0100
+++ gcc/config/cr16/cr16.c	2019-08-19 15:58:50.317919202 +0100
@@ -660,34 +660,34 @@ cr16_init_cumulative_args (CUMULATIVE_AR
 
 /* Implements the macro FUNCTION_ARG_ADVANCE defined in cr16.h.  */
 static void
-cr16_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
-			   const_tree type, bool named ATTRIBUTE_UNUSED)
+cr16_function_arg_advance (cumulative_args_t cum_v,
+			   const function_arg_info &arg)
 {
   CUMULATIVE_ARGS * cum = get_cumulative_args (cum_v);
 
   /* l holds the number of registers required.  */
-  int l = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
+  int l = GET_MODE_BITSIZE (arg.mode) / BITS_PER_WORD;
 
   /* If the parameter isn't passed on a register don't advance cum.  */
   if (!cum->last_parm_in_reg)
     return;
 
-  if (targetm.calls.must_pass_in_stack (mode, type) || (cum->ints < 0))
+  if (targetm.calls.must_pass_in_stack (arg.mode, arg.type) || (cum->ints < 0))
     return;
 
-  if ((mode == SImode) || (mode == HImode)
-      || (mode == QImode) || (mode == DImode))
+  if ((arg.mode == SImode) || (arg.mode == HImode)
+      || (arg.mode == QImode) || (arg.mode == DImode))
     {
       if (l <= 1)
 	cum->ints += 1;
       else
 	cum->ints += l;
     }
-  else if ((mode == SFmode) || (mode == DFmode))
+  else if ((arg.mode == SFmode) || (arg.mode == DFmode))
     cum->ints += l;
-  else if ((mode) == BLKmode)
+  else if (arg.mode == BLKmode)
     {
-      if ((l = enough_regs_for_param (cum, type, mode)) != 0)
+      if ((l = enough_regs_for_param (cum, arg.type, arg.mode)) != 0)
 	cum->ints += l;
     }
   return;
Index: gcc/config/cris/cris.c
===================================================================
--- gcc/config/cris/cris.c	2019-08-19 15:58:42.397976511 +0100
+++ gcc/config/cris/cris.c	2019-08-19 15:58:50.321919175 +0100
@@ -147,8 +147,8 @@ static int cris_arg_partial_bytes (cumul
 static rtx cris_function_arg (cumulative_args_t, const function_arg_info &);
 static rtx cris_function_incoming_arg (cumulative_args_t,
 				       const function_arg_info &);
-static void cris_function_arg_advance (cumulative_args_t, machine_mode,
-				       const_tree, bool);
+static void cris_function_arg_advance (cumulative_args_t,
+				       const function_arg_info &);
 static rtx_insn *cris_md_asm_adjust (vec<rtx> &, vec<rtx> &,
 				     vec<const char *> &,
 				     vec<rtx> &, HARD_REG_SET &);
@@ -4156,12 +4156,12 @@ cris_function_incoming_arg (cumulative_a
 /* Worker function for TARGET_FUNCTION_ARG_ADVANCE.  */
 
 static void
-cris_function_arg_advance (cumulative_args_t ca_v, machine_mode mode,
-			   const_tree type, bool named ATTRIBUTE_UNUSED)
+cris_function_arg_advance (cumulative_args_t ca_v,
+			   const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *ca = get_cumulative_args (ca_v);
 
-  ca->regs += (3 + CRIS_FUNCTION_ARG_SIZE (mode, type)) / 4;
+  ca->regs += (3 + CRIS_FUNCTION_ARG_SIZE (arg.mode, arg.type)) / 4;
 }
 
 /* Worker function for TARGET_MD_ASM_ADJUST.  */
Index: gcc/config/csky/csky.c
===================================================================
--- gcc/config/csky/csky.c	2019-08-19 15:58:42.401976480 +0100
+++ gcc/config/csky/csky.c	2019-08-19 15:58:50.321919175 +0100
@@ -1819,11 +1819,11 @@ csky_num_arg_regs (machine_mode mode, co
 /* Implement TARGET_FUNCTION_ARG_ADVANCE.  */
 
 static void
-csky_function_arg_advance (cumulative_args_t pcum_v, machine_mode mode,
-			   const_tree type, bool named ATTRIBUTE_UNUSED)
+csky_function_arg_advance (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 + param_size > CSKY_NPARM_REGS)
     *pcum = CSKY_NPARM_REGS;
@@ -1941,7 +1941,7 @@ csky_setup_incoming_varargs (cumulative_
 
   cfun->machine->uses_anonymous_args = 1;
   local_cum = *pcum;
-  csky_function_arg_advance (local_cum_v, arg.mode, arg.type, arg.named);
+  csky_function_arg_advance (local_cum_v, arg);
   regs_to_push = CSKY_NPARM_REGS - local_cum;
   if (regs_to_push)
     *pretend_size  = regs_to_push * UNITS_PER_WORD;
Index: gcc/config/epiphany/epiphany.c
===================================================================
--- gcc/config/epiphany/epiphany.c	2019-08-19 15:58:42.401976480 +0100
+++ gcc/config/epiphany/epiphany.c	2019-08-19 15:58:50.321919175 +0100
@@ -2269,16 +2269,15 @@ epiphany_function_arg (cumulative_args_t
   return 0;
 }
 
-/* Update the data in CUM to advance over an argument
-   of mode MODE and data type TYPE.
-   (TYPE is null for libcalls where that information may not be available.)  */
+/* Update the data in CUM to advance over argument ARG.  */
 static void
-epiphany_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
-			       const_tree type, bool named ATTRIBUTE_UNUSED)
+epiphany_function_arg_advance (cumulative_args_t cum_v,
+			       const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
-  *cum = ROUND_ADVANCE_CUM (*cum, mode, type) + ROUND_ADVANCE_ARG (mode, type);
+  *cum = (ROUND_ADVANCE_CUM (*cum, arg.mode, arg.type)
+	  + ROUND_ADVANCE_ARG (arg.mode, arg.type));
 }
 \f
 /* Nested function support.
Index: gcc/config/fr30/fr30.c
===================================================================
--- gcc/config/fr30/fr30.c	2019-08-19 15:58:42.401976480 +0100
+++ gcc/config/fr30/fr30.c	2019-08-19 15:58:50.321919175 +0100
@@ -120,8 +120,8 @@ static bool fr30_must_pass_in_stack (mac
 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 &);
-static void fr30_function_arg_advance (cumulative_args_t, machine_mode,
-				       const_tree, bool);
+static void fr30_function_arg_advance (cumulative_args_t,
+				       const function_arg_info &);
 static bool fr30_frame_pointer_required (void);
 static rtx fr30_function_value (const_tree, const_tree, bool);
 static rtx fr30_libcall_value (machine_mode, const_rtx);
@@ -811,19 +811,13 @@ fr30_function_arg (cumulative_args_t cum
     return gen_rtx_REG (arg.mode, *cum + FIRST_ARG_REGNUM);
 }
 
-/* A C statement (sans semicolon) to update the summarizer variable CUM to
-   advance past an argument in the argument list.  The values MODE, TYPE and
-   NAMED describe that argument.  Once this is done, the variable CUM is
-   suitable for analyzing the *following* argument with `FUNCTION_ARG', etc.
-
-   This macro need not do anything if the argument in question was passed on
-   the stack.  The compiler knows how to track the amount of stack space used
-   for arguments without any special help.  */
+/* Implement TARGET_FUNCTION_ARG_ADVANCE.  */
 static void
-fr30_function_arg_advance (cumulative_args_t cum, machine_mode mode,
-			   const_tree type, bool named)
+fr30_function_arg_advance (cumulative_args_t cum,
+			   const function_arg_info &arg)
 {
-  *get_cumulative_args (cum) += named * fr30_num_arg_regs (mode, type);
+  if (arg.named)
+    *get_cumulative_args (cum) += fr30_num_arg_regs (arg.mode, arg.type);
 }
 
 /*}}}*/
Index: gcc/config/frv/frv.c
===================================================================
--- gcc/config/frv/frv.c	2019-08-19 15:58:42.401976480 +0100
+++ gcc/config/frv/frv.c	2019-08-19 15:58:50.321919175 +0100
@@ -385,8 +385,8 @@ static int frv_arg_partial_bytes (cumula
 static rtx frv_function_arg (cumulative_args_t, const function_arg_info &);
 static rtx frv_function_incoming_arg (cumulative_args_t,
 				      const function_arg_info &);
-static void frv_function_arg_advance (cumulative_args_t, machine_mode,
-				       const_tree, bool);
+static void frv_function_arg_advance (cumulative_args_t,
+				      const function_arg_info &);
 static unsigned int frv_function_arg_boundary	(machine_mode,
 						 const_tree);
 static void frv_output_dwarf_dtprel		(FILE *, int, rtx)
@@ -3149,24 +3149,15 @@ frv_function_incoming_arg (cumulative_ar
 }
 
 \f
-/* A C statement (sans semicolon) to update the summarizer variable CUM to
-   advance past an argument in the argument list.  The values MODE, TYPE and
-   NAMED describe that argument.  Once this is done, the variable CUM is
-   suitable for analyzing the *following* argument with `FUNCTION_ARG', etc.
-
-   This macro need not do anything if the argument in question was passed on
-   the stack.  The compiler knows how to track the amount of stack space used
-   for arguments without any special help.  */
+/* Implement TARGET_FUNCTION_ARG_ADVANCE.  */
 
 static void
 frv_function_arg_advance (cumulative_args_t cum_v,
-                          machine_mode mode,
-                          const_tree type ATTRIBUTE_UNUSED,
-                          bool named)
+			  const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
-  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 = *cum;
@@ -3176,7 +3167,8 @@ frv_function_arg_advance (cumulative_arg
   if (TARGET_DEBUG_ARG)
     fprintf (stderr,
 	     "function_adv: words = %2d, mode = %4s, named = %d, size = %3d\n",
-	     arg_num, GET_MODE_NAME (mode), named, words * UNITS_PER_WORD);
+	     arg_num, GET_MODE_NAME (arg.mode), arg.named,
+	     words * UNITS_PER_WORD);
 }
 
 \f
Index: gcc/config/ft32/ft32.c
===================================================================
--- gcc/config/ft32/ft32.c	2019-08-19 15:58:42.401976480 +0100
+++ gcc/config/ft32/ft32.c	2019-08-19 15:58:50.321919175 +0100
@@ -672,13 +672,14 @@ #define FT32_FUNCTION_ARG_SIZE(MODE, TYP
    : (unsigned) int_size_in_bytes (TYPE))
 
 static void
-ft32_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
-                           const_tree type, bool named ATTRIBUTE_UNUSED)
+ft32_function_arg_advance (cumulative_args_t cum_v,
+			   const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
   *cum = (*cum < FT32_R6
-          ? *cum + ((3 + FT32_FUNCTION_ARG_SIZE (mode, type)) / 4) : *cum);
+	  ? *cum + ((3 + FT32_FUNCTION_ARG_SIZE (arg.mode, arg.type)) / 4)
+	  : *cum);
 }
 
 /* Return non-zero if the function argument described by ARG is to be
Index: gcc/config/gcn/gcn.c
===================================================================
--- gcc/config/gcn/gcn.c	2019-08-19 15:58:42.401976480 +0100
+++ gcc/config/gcn/gcn.c	2019-08-19 15:58:50.321919175 +0100
@@ -2313,17 +2313,17 @@ gcn_function_arg (cumulative_args_t cum_
    argument in the argument list.  */
 
 static void
-gcn_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
-			  const_tree type, bool named)
+gcn_function_arg_advance (cumulative_args_t cum_v,
+			  const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
   if (cum->normal_function)
     {
-      if (!named)
+      if (!arg.named)
 	return;
 
-      int num_regs = num_arg_regs (mode, type);
+      int num_regs = num_arg_regs (arg.mode, arg.type);
       if (num_regs > 0)
 	while ((FIRST_PARM_REG + cum->num) % num_regs != 0)
 	  cum->num++;
@@ -2335,7 +2335,7 @@ gcn_function_arg_advance (cumulative_arg
 	cum->num++;
       else
 	{
-	  cum->offset += tree_to_uhwi (TYPE_SIZE_UNIT (type));
+	  cum->offset += tree_to_uhwi (TYPE_SIZE_UNIT (arg.type));
 	  cfun->machine->kernarg_segment_byte_size = cum->offset;
 	}
     }
Index: gcc/config/h8300/h8300.c
===================================================================
--- gcc/config/h8300/h8300.c	2019-08-19 15:58:42.405976452 +0100
+++ gcc/config/h8300/h8300.c	2019-08-19 15:58:50.325919144 +0100
@@ -1151,19 +1151,16 @@ h8300_function_arg (cumulative_args_t cu
   return result;
 }
 
-/* Update the data in CUM to advance over an argument
-   of mode MODE and data type TYPE.
-   (TYPE is null for libcalls where that information may not be available.)  */
+/* Update the data in CUM to advance over argument ARG.  */
 
 static void
-h8300_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
-			    const_tree type, bool named ATTRIBUTE_UNUSED)
+h8300_function_arg_advance (cumulative_args_t cum_v,
+			    const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
-  cum->nbytes += (mode != BLKmode
-		  ? (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) & -UNITS_PER_WORD
-		  : (int_size_in_bytes (type) + UNITS_PER_WORD - 1) & -UNITS_PER_WORD);
+  cum->nbytes += ((arg.promoted_size_in_bytes () + UNITS_PER_WORD - 1)
+		  & -UNITS_PER_WORD);
 }
 
 \f
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	2019-08-19 15:58:42.405976452 +0100
+++ gcc/config/i386/i386.c	2019-08-19 15:58:50.325919144 +0100
@@ -2919,15 +2919,14 @@ function_arg_advance_ms_64 (CUMULATIVE_A
   return 0;
 }
 
-/* Update the data in CUM to advance over an argument of mode MODE and
-   data type TYPE.  (TYPE is null for libcalls where that information
-   may not be available.)  */
+/* Update the data in CUM to advance over argument ARG.  */
 
 static void
-ix86_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
-			   const_tree type, bool named)
+ix86_function_arg_advance (cumulative_args_t cum_v,
+			   const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
+  machine_mode mode = arg.mode;
   HOST_WIDE_INT bytes, words;
   int nregs;
 
@@ -2936,14 +2935,11 @@ ix86_function_arg_advance (cumulative_ar
   if (!cum->caller && cfun->machine->func_type != TYPE_NORMAL)
     return;
 
-  if (mode == BLKmode)
-    bytes = int_size_in_bytes (type);
-  else
-    bytes = GET_MODE_SIZE (mode);
+  bytes = arg.promoted_size_in_bytes ();
   words = CEIL (bytes, UNITS_PER_WORD);
 
-  if (type)
-    mode = type_natural_mode (type, NULL, false);
+  if (arg.type)
+    mode = type_natural_mode (arg.type, NULL, false);
 
   if (TARGET_64BIT)
     {
@@ -2952,10 +2948,11 @@ ix86_function_arg_advance (cumulative_ar
       if (call_abi == MS_ABI)
 	nregs = function_arg_advance_ms_64 (cum, bytes, words);
       else
-	nregs = function_arg_advance_64 (cum, mode, type, words, named);
+	nregs = function_arg_advance_64 (cum, mode, arg.type, words,
+					 arg.named);
     }
   else
-    nregs = function_arg_advance_32 (cum, mode, type, bytes, words);
+    nregs = function_arg_advance_32 (cum, mode, arg.type, bytes, words);
 
   if (!nregs)
     {
@@ -4109,8 +4106,7 @@ ix86_setup_incoming_varargs (cumulative_
      For stdargs, we do want to skip the last named argument.  */
   next_cum = *cum;
   if (stdarg_p (fntype))
-    ix86_function_arg_advance (pack_cumulative_args (&next_cum),
-			       arg.mode, arg.type, arg.named);
+    ix86_function_arg_advance (pack_cumulative_args (&next_cum), arg);
 
   if (cum->call_abi == MS_ABI)
     setup_incoming_varargs_ms_64 (&next_cum);
Index: gcc/config/ia64/ia64.c
===================================================================
--- gcc/config/ia64/ia64.c	2019-08-19 15:58:42.405976452 +0100
+++ gcc/config/ia64/ia64.c	2019-08-19 15:58:50.329919117 +0100
@@ -207,8 +207,8 @@ static int ia64_arg_partial_bytes (cumul
 static rtx ia64_function_arg (cumulative_args_t, const function_arg_info &);
 static rtx ia64_function_incoming_arg (cumulative_args_t,
 				       const function_arg_info &);
-static void ia64_function_arg_advance (cumulative_args_t, machine_mode,
-				       const_tree, bool);
+static void ia64_function_arg_advance (cumulative_args_t,
+				       const function_arg_info &);
 static pad_direction ia64_function_arg_padding (machine_mode, const_tree);
 static unsigned int ia64_function_arg_boundary (machine_mode,
 						const_tree);
@@ -4596,8 +4596,7 @@ ia64_setup_incoming_varargs (cumulative_
   CUMULATIVE_ARGS next_cum = *get_cumulative_args (cum);
 
   /* Skip the current argument.  */
-  ia64_function_arg_advance (pack_cumulative_args (&next_cum),
-			     arg.mode, arg.type, arg.named);
+  ia64_function_arg_advance (pack_cumulative_args (&next_cum), arg);
 
   if (next_cum.words < MAX_ARGUMENT_SLOTS)
     {
@@ -4999,12 +4998,12 @@ ia64_arg_type (machine_mode mode)
    ia64_function_arg.  */
 
 static void
-ia64_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
-			   const_tree type, bool named)
+ia64_function_arg_advance (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);
   machine_mode hfa_mode = VOIDmode;
 
   /* If all arg slots are already full, then there is nothing to do.  */
@@ -5014,7 +5013,7 @@ ia64_function_arg_advance (cumulative_ar
       return;
     }
 
-  cum->atypes[cum->words] = ia64_arg_type (mode);
+  cum->atypes[cum->words] = ia64_arg_type (arg.mode);
   cum->words += words + offset;
 
   /* On OpenVMS argument is either in Rn or Fn.  */
@@ -5026,12 +5025,12 @@ ia64_function_arg_advance (cumulative_ar
     }
 
   /* Check for and handle homogeneous FP aggregates.  */
-  if (type)
-    hfa_mode = hfa_element_mode (type, 0);
+  if (arg.type)
+    hfa_mode = hfa_element_mode (arg.type, 0);
 
   /* Unnamed prototyped hfas are passed as usual.  Named prototyped hfas
      and unprototyped hfas are passed specially.  */
-  if (hfa_mode != VOIDmode && (! cum->prototype || named))
+  if (hfa_mode != VOIDmode && (! cum->prototype || arg.named))
     {
       int fp_regs = cum->fp_regs;
       /* This is the original value of cum->words + offset.  */
@@ -5050,8 +5049,7 @@ ia64_function_arg_advance (cumulative_ar
       /* Fill the FP regs.  We do this always.  We stop if we reach the end
 	 of the argument, the last FP register, or the last argument slot.  */
 
-      byte_size = ((mode == BLKmode)
-		   ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
+      byte_size = arg.promoted_size_in_bytes ();
       args_byte_size = int_regs * UNITS_PER_WORD;
       offset = 0;
       for (; (offset < byte_size && fp_regs < MAX_ARGUMENT_SLOTS
@@ -5068,26 +5066,29 @@ ia64_function_arg_advance (cumulative_ar
   /* Integral and aggregates go in general registers.  So do TFmode FP values.
      If we have run out of FR registers, then other FP values must also go in
      general registers.  This can happen when we have a SFmode HFA.  */
-  else if (mode == TFmode || mode == TCmode
-           || (! FLOAT_MODE_P (mode) || cum->fp_regs == MAX_ARGUMENT_SLOTS))
+  else if (arg.mode == TFmode || arg.mode == TCmode
+           || !FLOAT_MODE_P (arg.mode)
+	   || cum->fp_regs == MAX_ARGUMENT_SLOTS)
     cum->int_regs = cum->words;
 
   /* If there is a prototype, then FP values go in a FR register when
      named, and in a GR register when unnamed.  */
   else if (cum->prototype)
     {
-      if (! named)
+      if (! arg.named)
 	cum->int_regs = cum->words;
       else
 	/* ??? Complex types should not reach here.  */
-	cum->fp_regs += (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT ? 2 : 1);
+	cum->fp_regs
+	  += (GET_MODE_CLASS (arg.mode) == MODE_COMPLEX_FLOAT ? 2 : 1);
     }
   /* If there is no prototype, then FP values go in both FR and GR
      registers.  */
   else
     {
       /* ??? Complex types should not reach here.  */
-      cum->fp_regs += (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT ? 2 : 1);
+      cum->fp_regs
+	+= (GET_MODE_CLASS (arg.mode) == MODE_COMPLEX_FLOAT ? 2 : 1);
       cum->int_regs = cum->words;
     }
 }
Index: gcc/config/iq2000/iq2000.c
===================================================================
--- gcc/config/iq2000/iq2000.c	2019-08-19 15:58:42.405976452 +0100
+++ gcc/config/iq2000/iq2000.c	2019-08-19 15:58:50.329919117 +0100
@@ -166,7 +166,7 @@ static int  iq2000_arg_partial_bytes  (c
 static rtx iq2000_function_arg	      (cumulative_args_t,
 				       const function_arg_info &);
 static void iq2000_function_arg_advance (cumulative_args_t,
-					 machine_mode, const_tree, bool);
+					 const function_arg_info &);
 static pad_direction iq2000_function_arg_padding (machine_mode, const_tree);
 static unsigned int iq2000_function_arg_boundary (machine_mode,
 						  const_tree);
@@ -1153,12 +1153,11 @@ init_cumulative_args (CUMULATIVE_ARGS *c
     }
 }
 
-/* Advance the argument of type TYPE and mode MODE to the next argument
-   position in CUM.  */
+/* Implement TARGET_FUNCTION_ARG_ADVANCE.  */
 
 static void
-iq2000_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
-			     const_tree type, bool named)
+iq2000_function_arg_advance (cumulative_args_t cum_v,
+			     const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
@@ -1167,29 +1166,29 @@ iq2000_function_arg_advance (cumulative_
       fprintf (stderr,
 	       "function_adv({gp reg found = %d, arg # = %2d, words = %2d}, %4s, ",
 	       cum->gp_reg_found, cum->arg_number, cum->arg_words,
-	       GET_MODE_NAME (mode));
-      fprintf (stderr, "%p", (const void *) type);
-      fprintf (stderr, ", %d )\n\n", named);
+	       GET_MODE_NAME (arg.mode));
+      fprintf (stderr, "%p", (const void *) arg.type);
+      fprintf (stderr, ", %d )\n\n", arg.named);
     }
 
   cum->arg_number++;
-  switch (mode)
+  switch (arg.mode)
     {
     case E_VOIDmode:
       break;
 
     default:
-      gcc_assert (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT
-		  || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT);
+      gcc_assert (GET_MODE_CLASS (arg.mode) == MODE_COMPLEX_INT
+		  || GET_MODE_CLASS (arg.mode) == MODE_COMPLEX_FLOAT);
 
       cum->gp_reg_found = 1;
-      cum->arg_words += ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
+      cum->arg_words += ((GET_MODE_SIZE (arg.mode) + UNITS_PER_WORD - 1)
 			 / UNITS_PER_WORD);
       break;
 
     case E_BLKmode:
       cum->gp_reg_found = 1;
-      cum->arg_words += ((int_size_in_bytes (type) + UNITS_PER_WORD - 1)
+      cum->arg_words += ((int_size_in_bytes (arg.type) + UNITS_PER_WORD - 1)
 			 / UNITS_PER_WORD);
       break;
 
@@ -1971,8 +1970,7 @@ iq2000_expand_prologue (void)
       function_arg_info arg (passed_type, passed_mode, /*named=*/true);
       entry_parm = iq2000_function_arg (args_so_far, arg);
 
-      iq2000_function_arg_advance (args_so_far, passed_mode,
-				   passed_type, true);
+      iq2000_function_arg_advance (args_so_far, arg);
       next_arg = DECL_CHAIN (cur_arg);
 
       if (entry_parm && store_args_on_stack)
Index: gcc/config/lm32/lm32.c
===================================================================
--- gcc/config/lm32/lm32.c	2019-08-19 15:58:42.405976452 +0100
+++ gcc/config/lm32/lm32.c	2019-08-19 15:58:50.329919117 +0100
@@ -75,8 +75,7 @@ static HOST_WIDE_INT lm32_compute_frame_
 static void lm32_option_override (void);
 static rtx lm32_function_arg (cumulative_args_t, const function_arg_info &);
 static void lm32_function_arg_advance (cumulative_args_t cum,
-				       machine_mode mode,
-				       const_tree type, bool named);
+				       const function_arg_info &);
 static bool lm32_hard_regno_mode_ok (unsigned int, machine_mode);
 static bool lm32_modes_tieable_p (machine_mode, machine_mode);
 static HOST_WIDE_INT lm32_starting_frame_offset (void);
@@ -641,10 +640,10 @@ lm32_function_arg (cumulative_args_t cum
 }
 
 static void
-lm32_function_arg_advance (cumulative_args_t cum, machine_mode mode,
-			   const_tree type, bool named ATTRIBUTE_UNUSED)
+lm32_function_arg_advance (cumulative_args_t cum,
+			   const function_arg_info &arg)
 {
-  *get_cumulative_args (cum) += LM32_NUM_REGS2 (mode, type);
+  *get_cumulative_args (cum) += LM32_NUM_REGS2 (arg.mode, arg.type);
 }
 
 HOST_WIDE_INT
Index: gcc/config/m32c/m32c.c
===================================================================
--- gcc/config/m32c/m32c.c	2019-08-19 15:58:42.409976425 +0100
+++ gcc/config/m32c/m32c.c	2019-08-19 15:58:50.329919117 +0100
@@ -79,8 +79,8 @@ static bool m32c_addr_space_legitimate_a
 static rtx m32c_function_arg (cumulative_args_t, const function_arg_info &);
 static bool m32c_pass_by_reference (cumulative_args_t,
 				    const function_arg_info &);
-static void m32c_function_arg_advance (cumulative_args_t, machine_mode,
-				       const_tree, bool);
+static void m32c_function_arg_advance (cumulative_args_t,
+				       const function_arg_info &);
 static unsigned int m32c_function_arg_boundary (machine_mode, const_tree);
 static int m32c_pushm_popm (Push_Pop_Type);
 static bool m32c_strict_argument_naming (cumulative_args_t);
@@ -1399,9 +1399,7 @@ m32c_init_cumulative_args (CUMULATIVE_AR
 #define TARGET_FUNCTION_ARG_ADVANCE m32c_function_arg_advance
 static void
 m32c_function_arg_advance (cumulative_args_t ca_v,
-			   machine_mode mode ATTRIBUTE_UNUSED,
-			   const_tree type ATTRIBUTE_UNUSED,
-			   bool named ATTRIBUTE_UNUSED)
+			   const function_arg_info &)
 {
   CUMULATIVE_ARGS *ca = get_cumulative_args (ca_v);
 
Index: gcc/config/m32r/m32r.c
===================================================================
--- gcc/config/m32r/m32r.c	2019-08-19 15:58:42.409976425 +0100
+++ gcc/config/m32r/m32r.c	2019-08-19 15:58:50.329919117 +0100
@@ -97,8 +97,8 @@ static bool m32r_pass_by_reference (cumu
 static int m32r_arg_partial_bytes (cumulative_args_t,
 				   const function_arg_info &);
 static rtx m32r_function_arg (cumulative_args_t, const function_arg_info &);
-static void m32r_function_arg_advance (cumulative_args_t, machine_mode,
-				       const_tree, bool);
+static void m32r_function_arg_advance (cumulative_args_t,
+				       const function_arg_info &);
 static bool m32r_can_eliminate (const int, const int);
 static void m32r_conditional_register_usage (void);
 static void m32r_trampoline_init (rtx, tree, rtx);
@@ -1217,18 +1217,16 @@ m32r_function_arg (cumulative_args_t cum
 	  : NULL_RTX);
 }
 
-/* Update the data in CUM to advance over an argument
-   of mode MODE and data type TYPE.
-   (TYPE is null for libcalls where that information may not be available.)  */
+/* Update the data in CUM to advance over argument ARG.  */
 
 static void
-m32r_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
-			   const_tree type, bool named ATTRIBUTE_UNUSED)
+m32r_function_arg_advance (cumulative_args_t cum_v,
+			   const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
-  *cum = (ROUND_ADVANCE_CUM (*cum, mode, type)
-	  + ROUND_ADVANCE_ARG (mode, type));
+  *cum = (ROUND_ADVANCE_CUM (*cum, arg.mode, arg.type)
+	  + ROUND_ADVANCE_ARG (arg.mode, arg.type));
 }
 
 /* Worker function for TARGET_RETURN_IN_MEMORY.  */
Index: gcc/config/m68k/m68k.c
===================================================================
--- gcc/config/m68k/m68k.c	2019-08-19 15:58:42.409976425 +0100
+++ gcc/config/m68k/m68k.c	2019-08-19 15:58:50.329919117 +0100
@@ -181,8 +181,8 @@ static void m68k_output_dwarf_dtprel (FI
 static void m68k_trampoline_init (rtx, tree, rtx);
 static poly_int64 m68k_return_pops_args (tree, tree, poly_int64);
 static rtx m68k_delegitimize_address (rtx);
-static void m68k_function_arg_advance (cumulative_args_t, machine_mode,
-				       const_tree, bool);
+static void m68k_function_arg_advance (cumulative_args_t,
+				       const function_arg_info &);
 static rtx m68k_function_arg (cumulative_args_t, const function_arg_info &);
 static bool m68k_cannot_force_const_mem (machine_mode mode, rtx x);
 static bool m68k_output_addr_const_extra (FILE *, rtx);
@@ -1469,14 +1469,12 @@ m68k_function_arg (cumulative_args_t, co
 }
 
 static void
-m68k_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
-			   const_tree type, bool named ATTRIBUTE_UNUSED)
+m68k_function_arg_advance (cumulative_args_t cum_v,
+			   const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
-  *cum += (mode != BLKmode
-	   ? (GET_MODE_SIZE (mode) + 3) & ~3
-	   : (int_size_in_bytes (type) + 3) & ~3);
+  *cum += (arg.promoted_size_in_bytes () + 3) & ~3;
 }
 
 /* Convert X to a legitimate function call memory reference and return the
Index: gcc/config/mcore/mcore.c
===================================================================
--- gcc/config/mcore/mcore.c	2019-08-19 15:58:42.409976425 +0100
+++ gcc/config/mcore/mcore.c	2019-08-19 15:58:50.329919117 +0100
@@ -135,8 +135,7 @@ static int        mcore_arg_partial_byte
 static rtx        mcore_function_arg            (cumulative_args_t,
 						 const function_arg_info &);
 static void       mcore_function_arg_advance    (cumulative_args_t,
-						 machine_mode,
-						 const_tree, bool);
+						 const function_arg_info &);
 static unsigned int mcore_function_arg_boundary (machine_mode,
 						 const_tree);
 static void       mcore_asm_trampoline_template (FILE *);
@@ -2817,13 +2816,13 @@ mcore_function_arg (cumulative_args_t cu
 }
 
 static void
-mcore_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
-			    const_tree type, bool named ATTRIBUTE_UNUSED)
+mcore_function_arg_advance (cumulative_args_t cum_v,
+			    const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
-  *cum = (ROUND_REG (*cum, mode)
-	  + (int)named * mcore_num_arg_regs (mode, type));
+  *cum = (ROUND_REG (*cum, arg.mode)
+	  + (int) arg.named * mcore_num_arg_regs (arg.mode, arg.type));
 }
 
 static unsigned int
Index: gcc/config/microblaze/microblaze.c
===================================================================
--- gcc/config/microblaze/microblaze.c	2019-08-19 15:58:42.409976425 +0100
+++ gcc/config/microblaze/microblaze.c	2019-08-19 15:58:50.329919117 +0100
@@ -1543,29 +1543,28 @@ init_cumulative_args (CUMULATIVE_ARGS *
 
 static void
 microblaze_function_arg_advance (cumulative_args_t cum_v,
-				 machine_mode mode,
-				 const_tree type, bool named ATTRIBUTE_UNUSED)
+				 const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
   cum->arg_number++;
-  switch (mode)
+  switch (arg.mode)
     {
     case E_VOIDmode:
       break;
 
     default:
-      gcc_assert (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT
-	  || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT);
+      gcc_assert (GET_MODE_CLASS (arg.mode) == MODE_COMPLEX_INT
+		  || GET_MODE_CLASS (arg.mode) == MODE_COMPLEX_FLOAT);
 
       cum->gp_reg_found = 1;
-      cum->arg_words += ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
+      cum->arg_words += ((GET_MODE_SIZE (arg.mode) + UNITS_PER_WORD - 1)
 			 / UNITS_PER_WORD);
       break;
 
     case E_BLKmode:
       cum->gp_reg_found = 1;
-      cum->arg_words += ((int_size_in_bytes (type) + UNITS_PER_WORD - 1)
+      cum->arg_words += ((int_size_in_bytes (arg.type) + UNITS_PER_WORD - 1)
 			 / UNITS_PER_WORD);
       break;
 
@@ -2935,8 +2934,7 @@ microblaze_expand_prologue (void)
 	  break;
 	}
 
-      targetm.calls.function_arg_advance (args_so_far, passed_mode,
-					  passed_type, true);
+      targetm.calls.function_arg_advance (args_so_far, arg);
 
       next_arg = TREE_CHAIN (cur_arg);
       if (next_arg == 0)
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	2019-08-19 15:58:42.409976425 +0100
+++ gcc/config/mips/mips.c	2019-08-19 15:58:50.333919085 +0100
@@ -6102,13 +6102,13 @@ mips_function_arg (cumulative_args_t cum
 /* Implement TARGET_FUNCTION_ARG_ADVANCE.  */
 
 static void
-mips_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
-			   const_tree type, bool named)
+mips_function_arg_advance (cumulative_args_t cum_v,
+			   const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   struct mips_arg_info info;
 
-  mips_get_arg_info (&info, cum, mode, type, named);
+  mips_get_arg_info (&info, cum, arg.mode, arg.type, arg.named);
 
   if (!info.fpr_p)
     cum->gp_reg_found = true;
@@ -6118,7 +6118,7 @@ mips_function_arg_advance (cumulative_ar
      either the o32 or the o64 ABI, both of which pass at most 2 arguments
      in FPRs.  */
   if (cum->arg_number < 2 && info.fpr_p)
-    cum->fp_code += (mode == SFmode ? 1 : 2) << (cum->arg_number * 2);
+    cum->fp_code += (arg.mode == SFmode ? 1 : 2) << (cum->arg_number * 2);
 
   /* Advance the register count.  This has the effect of setting
      num_gprs to MAX_ARGS_IN_REGISTERS if a doubleword-aligned
@@ -6554,8 +6554,7 @@ mips_setup_incoming_varargs (cumulative_
      argument.  Advance a local copy of CUM past the last "real" named
      argument, to find out how many registers are left over.  */
   local_cum = *get_cumulative_args (cum);
-  mips_function_arg_advance (pack_cumulative_args (&local_cum),
-			     arg.mode, arg.type, arg.named);
+  mips_function_arg_advance (pack_cumulative_args (&local_cum), arg);
 
   /* Found out how many registers we need to save.  */
   gp_saved = MAX_ARGS_IN_REGISTERS - local_cum.num_gprs;
@@ -7305,7 +7304,8 @@ mips_output_args_xfer (int fp_code, char
       else
 	mips_output_64bit_xfer (direction, gparg, fparg);
 
-      mips_function_arg_advance (pack_cumulative_args (&cum), mode, NULL, true);
+      function_arg_info arg (mode, /*named=*/true);
+      mips_function_arg_advance (pack_cumulative_args (&cum), arg);
     }
 }
 
Index: gcc/config/mmix/mmix.c
===================================================================
--- gcc/config/mmix/mmix.c	2019-08-19 15:58:42.413976394 +0100
+++ gcc/config/mmix/mmix.c	2019-08-19 15:58:50.333919085 +0100
@@ -149,8 +149,8 @@ static rtx mmix_struct_value_rtx (tree,
 static machine_mode mmix_promote_function_mode (const_tree,
 						     machine_mode,
 	                                             int *, const_tree, int);
-static void mmix_function_arg_advance (cumulative_args_t, machine_mode,
-				       const_tree, bool);
+static void mmix_function_arg_advance (cumulative_args_t,
+				       const function_arg_info &);
 static rtx mmix_function_incoming_arg (cumulative_args_t,
 				       const function_arg_info &);
 static rtx mmix_function_arg (cumulative_args_t, const function_arg_info &);
@@ -615,13 +615,13 @@ mmix_initial_elimination_offset (int fro
 }
 
 static void
-mmix_function_arg_advance (cumulative_args_t argsp_v, machine_mode mode,
-			   const_tree type, bool named ATTRIBUTE_UNUSED)
+mmix_function_arg_advance (cumulative_args_t argsp_v,
+			   const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *argsp = get_cumulative_args (argsp_v);
-  int arg_size = MMIX_FUNCTION_ARG_SIZE (mode, type);
+  int arg_size = MMIX_FUNCTION_ARG_SIZE (arg.mode, arg.type);
 
-  argsp->regs = ((targetm.calls.must_pass_in_stack (mode, type)
+  argsp->regs = ((targetm.calls.must_pass_in_stack (arg.mode, arg.type)
 		  || (arg_size > 8
 		      && !TARGET_LIBFUNC
 		      && !argsp->lib))
Index: gcc/config/mn10300/mn10300.c
===================================================================
--- gcc/config/mn10300/mn10300.c	2019-08-19 15:58:42.413976394 +0100
+++ gcc/config/mn10300/mn10300.c	2019-08-19 15:58:50.333919085 +0100
@@ -1575,19 +1575,15 @@ mn10300_function_arg (cumulative_args_t
   return result;
 }
 
-/* Update the data in CUM to advance over an argument
-   of mode MODE and data type TYPE.
-   (TYPE is null for libcalls where that information may not be available.)  */
+/* Update the data in CUM to advance over argument ARG.  */
 
 static void
-mn10300_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
-			      const_tree type, bool named ATTRIBUTE_UNUSED)
+mn10300_function_arg_advance (cumulative_args_t cum_v,
+			      const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
-  cum->nbytes += (mode != BLKmode
-		  ? (GET_MODE_SIZE (mode) + 3) & ~3
-		  : (int_size_in_bytes (type) + 3) & ~3);
+  cum->nbytes += (arg.promoted_size_in_bytes () + 3) & ~3;
 }
 
 /* Return the number of bytes of registers to use for an argument passed
Index: gcc/config/moxie/moxie.c
===================================================================
--- gcc/config/moxie/moxie.c	2019-08-19 15:58:42.413976394 +0100
+++ gcc/config/moxie/moxie.c	2019-08-19 15:58:50.333919085 +0100
@@ -438,13 +438,13 @@ #define MOXIE_FUNCTION_ARG_SIZE(MODE, TY
    : (unsigned) int_size_in_bytes (TYPE))
 
 static void
-moxie_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
-			    const_tree type, bool named ATTRIBUTE_UNUSED)
+moxie_function_arg_advance (cumulative_args_t cum_v,
+			    const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
   *cum = (*cum < MOXIE_R6
-	  ? *cum + ((3 + MOXIE_FUNCTION_ARG_SIZE (mode, type)) / 4)
+	  ? *cum + ((3 + MOXIE_FUNCTION_ARG_SIZE (arg.mode, arg.type)) / 4)
 	  : *cum);
 }
 
Index: gcc/config/msp430/msp430.c
===================================================================
--- gcc/config/msp430/msp430.c	2019-08-19 15:58:42.413976394 +0100
+++ gcc/config/msp430/msp430.c	2019-08-19 15:58:50.333919085 +0100
@@ -766,14 +766,12 @@ #define TARGET_FUNCTION_ARG_ADVANCE msp4
 
 void
 msp430_function_arg_advance (cumulative_args_t cap,
-			     machine_mode mode,
-			     const_tree type,
-			     bool named)
+			     const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
   int i;
 
-  msp430_evaluate_arg (cap, mode, type, named);
+  msp430_evaluate_arg (cap, arg.mode, arg.type, arg.named);
 
   if (ca->start_reg >= CA_FIRST_REG)
     for (i = 0; i < ca->reg_count; i ++)
Index: gcc/config/nds32/nds32.c
===================================================================
--- gcc/config/nds32/nds32.c	2019-08-19 15:58:42.413976394 +0100
+++ gcc/config/nds32/nds32.c	2019-08-19 15:58:50.333919085 +0100
@@ -2008,12 +2008,14 @@ nds32_arg_partial_bytes (cumulative_args
 }
 
 static void
-nds32_function_arg_advance (cumulative_args_t ca, machine_mode mode,
-			    const_tree type, bool named)
+nds32_function_arg_advance (cumulative_args_t ca,
+			    const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (ca);
+  tree type = arg.type;
+  machine_mode mode = arg.mode;
 
-  if (named)
+  if (arg.named)
     {
       /* We need to further check TYPE and MODE so that we can determine
 	 which kind of register we shall advance.  */
Index: gcc/config/nios2/nios2.c
===================================================================
--- gcc/config/nios2/nios2.c	2019-08-19 15:58:42.413976394 +0100
+++ gcc/config/nios2/nios2.c	2019-08-19 15:58:50.333919085 +0100
@@ -3399,25 +3399,15 @@ nios2_arg_partial_bytes (cumulative_args
   return 0;
 }
 
-/* Update the data in CUM to advance over an argument of mode MODE
-   and data type TYPE; TYPE is null for libcalls where that information
-   may not be available.  */
+/* Update the data in CUM to advance over argument ARG.  */
 
 static void
-nios2_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
-			    const_tree type ATTRIBUTE_UNUSED,
-			    bool named ATTRIBUTE_UNUSED)
+nios2_function_arg_advance (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;
@@ -3520,7 +3510,7 @@ nios2_setup_incoming_varargs (cumulative
 
   cfun->machine->uses_anonymous_args = 1;
   local_cum = *cum;
-  nios2_function_arg_advance (local_cum_v, arg.mode, arg.type, arg.named);
+  nios2_function_arg_advance (local_cum_v, arg);
 
   regs_to_push = NUM_ARG_REGS - local_cum.regs_used;
 
Index: gcc/config/nvptx/nvptx.c
===================================================================
--- gcc/config/nvptx/nvptx.c	2019-08-19 15:58:42.413976394 +0100
+++ gcc/config/nvptx/nvptx.c	2019-08-19 15:58:50.333919085 +0100
@@ -550,10 +550,7 @@ nvptx_function_incoming_arg (cumulative_
 /* Implement TARGET_FUNCTION_ARG_ADVANCE.  */
 
 static void
-nvptx_function_arg_advance (cumulative_args_t cum_v,
-			    machine_mode ARG_UNUSED (mode),
-			    const_tree ARG_UNUSED (type),
-			    bool ARG_UNUSED (named))
+nvptx_function_arg_advance (cumulative_args_t cum_v, const function_arg_info &)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
Index: gcc/config/or1k/or1k.c
===================================================================
--- gcc/config/or1k/or1k.c	2019-08-19 15:58:42.413976394 +0100
+++ gcc/config/or1k/or1k.c	2019-08-19 15:58:50.333919085 +0100
@@ -1019,15 +1019,15 @@ or1k_function_arg (cumulative_args_t cum
    argument.  Note, this is not called for arguments passed on the stack.  */
 
 static void
-or1k_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
-			   const_tree /* type */, bool named)
+or1k_function_arg_advance (cumulative_args_t cum_v,
+			   const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
-  int nreg = CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD);
+  int nreg = CEIL (GET_MODE_SIZE (arg.mode), UNITS_PER_WORD);
 
   /* Note that all large arguments are passed by reference.  */
   gcc_assert (nreg <= 2);
-  if (named)
+  if (arg.named)
     *cum += nreg;
 }
 
Index: gcc/config/pa/pa.c
===================================================================
--- gcc/config/pa/pa.c	2019-08-19 15:58:42.413976394 +0100
+++ gcc/config/pa/pa.c	2019-08-19 15:58:50.337919057 +0100
@@ -167,8 +167,8 @@ static rtx pa_struct_value_rtx (tree, in
 static bool pa_pass_by_reference (cumulative_args_t,
 				  const function_arg_info &);
 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 void pa_function_arg_advance (cumulative_args_t,
+				     const function_arg_info &);
 static rtx pa_function_arg (cumulative_args_t, const function_arg_info &);
 static pad_direction pa_function_arg_padding (machine_mode, const_tree);
 static unsigned int pa_function_arg_boundary (machine_mode, const_tree);
@@ -9437,21 +9437,19 @@ pa_function_value_regno_p (const unsigne
   return false;
 }
 
-/* Update the data in CUM to advance over an argument
-   of mode MODE and data type TYPE.
-   (TYPE is null for libcalls where that information may not be available.)  */
+/* Update the data in CUM to advance over argument ARG.  */
 
 static void
-pa_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
-			 const_tree type, bool named ATTRIBUTE_UNUSED)
+pa_function_arg_advance (cumulative_args_t cum_v,
+			 const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
-  int arg_size = pa_function_arg_size (mode, type);
+  int arg_size = pa_function_arg_size (arg.mode, arg.type);
 
   cum->nargs_prototype--;
   cum->words += (arg_size
 		 + ((cum->words & 01)
-		    && type != NULL_TREE
+		    && arg.type != NULL_TREE
 		    && arg_size > 1));
 }
 
Index: gcc/config/pdp11/pdp11.c
===================================================================
--- gcc/config/pdp11/pdp11.c	2019-08-19 15:58:42.413976394 +0100
+++ gcc/config/pdp11/pdp11.c	2019-08-19 15:58:50.337919057 +0100
@@ -164,7 +164,7 @@ static bool pdp11_function_value_regno_p
 static void pdp11_trampoline_init (rtx, tree, rtx);
 static rtx pdp11_function_arg (cumulative_args_t, const function_arg_info &);
 static void pdp11_function_arg_advance (cumulative_args_t,
-					machine_mode, const_tree, bool);
+					const function_arg_info &);
 static void pdp11_conditional_register_usage (void);
 static bool pdp11_legitimate_constant_p (machine_mode, rtx);
 
@@ -2189,19 +2189,15 @@ pdp11_function_arg (cumulative_args_t, c
 
 /* Worker function for TARGET_FUNCTION_ARG_ADVANCE.
 
-   Update the data in CUM to advance over an argument of mode MODE and
-   data type TYPE.  (TYPE is null for libcalls where that information
-   may not be available.)  */
+   Update the data in CUM to advance over argument ARG.  */
 
 static void
-pdp11_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
-			    const_tree type, bool named ATTRIBUTE_UNUSED)
+pdp11_function_arg_advance (cumulative_args_t cum_v,
+			    const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
-  *cum += (mode != BLKmode
-	   ? GET_MODE_SIZE (mode)
-	   : int_size_in_bytes (type));
+  *cum += arg.promoted_size_in_bytes ();
 }
 
 /* Make sure everything's fine if we *don't* have an FPU.
Index: gcc/config/pru/pru.c
===================================================================
--- gcc/config/pru/pru.c	2019-08-19 15:58:42.413976394 +0100
+++ gcc/config/pru/pru.c	2019-08-19 15:58:50.337919057 +0100
@@ -2177,19 +2177,17 @@ pru_arg_partial_bytes (cumulative_args_t
   return 0;
 }
 
-/* Update the data in CUM to advance over an argument of mode MODE
-   and data type TYPE; TYPE is null for libcalls where that information
-   may not be available.  */
+/* Update the data in CUM to advance over argument ARG.  */
 
 static void
-pru_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
-			    const_tree type,
-			    bool named)
+pru_function_arg_advance (cumulative_args_t cum_v,
+			  const function_arg_info &arg)
 {
-  int regi = pru_function_arg_regi (cum_v, mode, type, named);
+  int regi = pru_function_arg_regi (cum_v, arg.mode, arg.type, arg.named);
 
   if (regi >= 0)
-    pru_function_arg_regi_mark_slot (regi, cum_v, mode, type, named);
+    pru_function_arg_regi_mark_slot (regi, cum_v, arg.mode,
+				     arg.type, arg.named);
 }
 
 /* Implement TARGET_FUNCTION_VALUE.  */
Index: gcc/config/riscv/riscv.c
===================================================================
--- gcc/config/riscv/riscv.c	2019-08-19 15:58:42.417976367 +0100
+++ gcc/config/riscv/riscv.c	2019-08-19 15:58:50.337919057 +0100
@@ -2757,13 +2757,13 @@ riscv_function_arg (cumulative_args_t cu
 /* Implement TARGET_FUNCTION_ARG_ADVANCE.  */
 
 static void
-riscv_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
-			    const_tree type, bool named)
+riscv_function_arg_advance (cumulative_args_t cum_v,
+			    const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   struct riscv_arg_info info;
 
-  riscv_get_arg_info (&info, cum, mode, type, named, false);
+  riscv_get_arg_info (&info, cum, arg.mode, arg.type, arg.named, false);
 
   /* Advance the register count.  This has the effect of setting
      num_gprs to MAX_ARGS_IN_REGISTERS if a doubleword-aligned
@@ -2864,8 +2864,7 @@ riscv_setup_incoming_varargs (cumulative
      argument.  Advance a local copy of CUM past the last "real" named
      argument, to find out how many registers are left over.  */
   local_cum = *get_cumulative_args (cum);
-  riscv_function_arg_advance (pack_cumulative_args (&local_cum),
-			      arg.mode, arg.type, arg.named);
+  riscv_function_arg_advance (pack_cumulative_args (&local_cum), arg);
 
   /* Found out how many registers we need to save.  */
   gp_saved = MAX_ARGS_IN_REGISTERS - local_cum.num_gprs;
Index: gcc/config/rl78/rl78.c
===================================================================
--- gcc/config/rl78/rl78.c	2019-08-19 15:58:42.417976367 +0100
+++ gcc/config/rl78/rl78.c	2019-08-19 15:58:50.337919057 +0100
@@ -1750,14 +1750,13 @@ rl78_function_arg (cumulative_args_t, co
 #define TARGET_FUNCTION_ARG_ADVANCE     rl78_function_arg_advance
 
 static void
-rl78_function_arg_advance (cumulative_args_t cum_v, machine_mode mode, const_tree type,
-			   bool named ATTRIBUTE_UNUSED)
+rl78_function_arg_advance (cumulative_args_t cum_v,
+			   const function_arg_info &arg)
 {
   int rounded_size;
   CUMULATIVE_ARGS * cum = get_cumulative_args (cum_v);
 
-  rounded_size = ((mode == BLKmode)
-		  ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
+  rounded_size = arg.promoted_size_in_bytes ();
   if (rounded_size & 1)
     rounded_size ++;
   (*cum) += rounded_size;
Index: gcc/config/rs6000/rs6000-internal.h
===================================================================
--- gcc/config/rs6000/rs6000-internal.h	2019-08-19 15:58:42.417976367 +0100
+++ gcc/config/rs6000/rs6000-internal.h	2019-08-19 15:58:50.337919057 +0100
@@ -159,9 +159,8 @@ extern unsigned int rs6000_function_arg_
 extern bool rs6000_must_pass_in_stack (machine_mode mode, const_tree type);
 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);
+extern void rs6000_function_arg_advance (cumulative_args_t,
+					 const function_arg_info &);
 extern pad_direction rs6000_function_arg_padding (machine_mode mode,
 						  const_tree type);
 extern rtx rs6000_function_arg (cumulative_args_t, const function_arg_info &);
Index: gcc/config/rs6000/rs6000-call.c
===================================================================
--- gcc/config/rs6000/rs6000-call.c	2019-08-19 15:58:42.417976367 +0100
+++ gcc/config/rs6000/rs6000-call.c	2019-08-19 15:58:50.337919057 +0100
@@ -1400,11 +1400,11 @@ rs6000_function_arg_advance_1 (CUMULATIV
 }
 
 void
-rs6000_function_arg_advance (cumulative_args_t cum, machine_mode mode,
-			     const_tree type, bool named)
+rs6000_function_arg_advance (cumulative_args_t cum,
+			     const function_arg_info &arg)
 {
-  rs6000_function_arg_advance_1 (get_cumulative_args (cum), mode, type, named,
-				 0);
+  rs6000_function_arg_advance_1 (get_cumulative_args (cum),
+				 arg.mode, arg.type, arg.named, 0);
 }
 
 /* A subroutine of rs6000_darwin64_record_arg.  Assign the bits of the
@@ -2221,7 +2221,7 @@ rs6000_parm_needs_stack (cumulative_args
     return true;
 
   /* Update info on where next arg arrives in registers.  */
-  rs6000_function_arg_advance (args_so_far, mode, type, true);
+  rs6000_function_arg_advance (args_so_far, arg);
   return false;
 }
 
Index: gcc/config/rx/rx.c
===================================================================
--- gcc/config/rx/rx.c	2019-08-19 15:58:42.417976367 +0100
+++ gcc/config/rx/rx.c	2019-08-19 15:58:50.337919057 +0100
@@ -1105,10 +1105,10 @@ rx_function_arg (cumulative_args_t cum,
 }
 
 static void
-rx_function_arg_advance (cumulative_args_t cum, machine_mode mode,
-			 const_tree type, bool named ATTRIBUTE_UNUSED)
+rx_function_arg_advance (cumulative_args_t cum,
+			 const function_arg_info &arg)
 {
-  *get_cumulative_args (cum) += rx_function_arg_size (mode, type);
+  *get_cumulative_args (cum) += rx_function_arg_size (arg.mode, arg.type);
 }
 
 static unsigned int
Index: gcc/config/s390/s390.c
===================================================================
--- gcc/config/s390/s390.c	2019-08-19 15:58:42.417976367 +0100
+++ gcc/config/s390/s390.c	2019-08-19 15:58:50.337919057 +0100
@@ -11982,35 +11982,31 @@ s390_pass_by_reference (cumulative_args_
   return false;
 }
 
-/* Update the data in CUM to advance over an argument of mode MODE and
-   data type TYPE.  (TYPE is null for libcalls where that information
-   may not be available.).  The boolean NAMED specifies whether the
-   argument is a named argument (as opposed to an unnamed argument
-   matching an ellipsis).  */
+/* Update the data in CUM to advance over argument ARG.  */
 
 static void
-s390_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
-			   const_tree type, bool named)
+s390_function_arg_advance (cumulative_args_t cum_v,
+			   const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
-  if (s390_function_arg_vector (mode, type))
+  if (s390_function_arg_vector (arg.mode, arg.type))
     {
       /* We are called for unnamed vector stdarg arguments which are
 	 passed on the stack.  In this case this hook does not have to
 	 do anything since stack arguments are tracked by common
 	 code.  */
-      if (!named)
+      if (!arg.named)
 	return;
       cum->vrs += 1;
     }
-  else if (s390_function_arg_float (mode, type))
+  else if (s390_function_arg_float (arg.mode, arg.type))
     {
       cum->fprs += 1;
     }
-  else if (s390_function_arg_integer (mode, type))
+  else if (s390_function_arg_integer (arg.mode, arg.type))
     {
-      int size = s390_function_arg_size (mode, type);
+      int size = s390_function_arg_size (arg.mode, arg.type);
       cum->gprs += ((size + UNITS_PER_LONG - 1) / UNITS_PER_LONG);
     }
   else
@@ -13349,7 +13345,7 @@ s390_call_saved_register_used (tree call
        function_arg_info arg (type, mode, /*named=*/true);
        parm_rtx = s390_function_arg (cum, arg);
 
-       s390_function_arg_advance (cum, mode, type, true);
+       s390_function_arg_advance (cum, arg);
 
        if (!parm_rtx)
 	 continue;
Index: gcc/config/sh/sh.c
===================================================================
--- gcc/config/sh/sh.c	2019-08-19 15:58:42.417976367 +0100
+++ gcc/config/sh/sh.c	2019-08-19 15:58:50.337919057 +0100
@@ -299,8 +299,8 @@ static bool sh_pass_by_reference (cumula
 static bool sh_callee_copies (cumulative_args_t, machine_mode,
 			      const_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 void sh_function_arg_advance (cumulative_args_t,
+				     const function_arg_info &);
 static rtx sh_function_arg (cumulative_args_t, const function_arg_info &);
 static int sh_dwarf_calling_convention (const_tree);
 static void sh_encode_section_info (tree, rtx, int);
@@ -8066,13 +8066,10 @@ sh_function_arg (cumulative_args_t ca_v,
   return NULL_RTX;
 }
 
-/* Update the data in CUM to advance over an argument
-   of mode MODE and data type TYPE.
-   (TYPE is null for libcalls where that information may not be
-   available.)  */
+/* Update the data in CUM to advance over argument ARG.  */
 static void
-sh_function_arg_advance (cumulative_args_t ca_v, machine_mode mode,
-			 const_tree type, bool named ATTRIBUTE_UNUSED)
+sh_function_arg_advance (cumulative_args_t ca_v,
+			 const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *ca = get_cumulative_args (ca_v);
 
@@ -8082,7 +8079,7 @@ sh_function_arg_advance (cumulative_args
   if ((TARGET_HITACHI || ca->renesas_abi) && TARGET_FPU_DOUBLE)
     {
       /* Note that we've used the skipped register.  */
-      if (mode == SFmode && ca->free_single_fp_reg)
+      if (arg.mode == SFmode && ca->free_single_fp_reg)
 	{
 	  ca->free_single_fp_reg = 0;
 	  return;
@@ -8091,21 +8088,19 @@ sh_function_arg_advance (cumulative_args
 	 skipped in order to align the DF value.  We note this skipped
 	 register, because the next SF value will use it, and not the
 	 SF that follows the DF.  */
-      if (mode == DFmode
+      if (arg.mode == DFmode
 	  && sh_round_reg (*ca, DFmode) != sh_round_reg (*ca, SFmode))
 	{
 	  ca->free_single_fp_reg = (sh_round_reg (*ca, SFmode)
-				    + BASE_ARG_REG (mode));
+				    + BASE_ARG_REG (arg.mode));
 	}
     }
 
   if (! ((TARGET_SH4 || TARGET_SH2A) || ca->renesas_abi)
-      || sh_pass_in_reg_p (*ca, mode, type))
-    (ca->arg_count[(int) get_sh_arg_class (mode)]
-     = (sh_round_reg (*ca, mode)
-	+ (mode == BLKmode
-	   ? CEIL (int_size_in_bytes (type), UNITS_PER_WORD)
-	   : CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD))));
+      || sh_pass_in_reg_p (*ca, arg.mode, arg.type))
+    (ca->arg_count[(int) get_sh_arg_class (arg.mode)]
+     = (sh_round_reg (*ca, arg.mode)
+	+ CEIL (arg.promoted_size_in_bytes (), UNITS_PER_WORD)));
 }
 
 /* The Renesas calling convention doesn't quite fit into this scheme since
@@ -10811,7 +10806,8 @@ sh_output_mi_thunk (FILE *file, tree thu
     {
       tree ptype = build_pointer_type (TREE_TYPE (funtype));
 
-      sh_function_arg_advance (pack_cumulative_args (&cum), Pmode, ptype, true);
+      function_arg_info ptr_arg (ptype, Pmode, /*named=*/true);
+      sh_function_arg_advance (pack_cumulative_args (&cum), ptr_arg);
     }
   function_arg_info ptr_arg (ptr_type_node, Pmode, /*named=*/true);
   this_rtx = sh_function_arg (pack_cumulative_args (&cum), ptr_arg);
Index: gcc/config/sparc/sparc.c
===================================================================
--- gcc/config/sparc/sparc.c	2019-08-19 15:58:42.417976367 +0100
+++ gcc/config/sparc/sparc.c	2019-08-19 15:58:50.341919030 +0100
@@ -657,7 +657,7 @@ static bool sparc_mode_dependent_address
 static bool sparc_pass_by_reference (cumulative_args_t,
 				     const function_arg_info &);
 static void sparc_function_arg_advance (cumulative_args_t,
-					machine_mode, const_tree, bool);
+					const function_arg_info &);
 static rtx sparc_function_arg (cumulative_args_t, const function_arg_info &);
 static rtx sparc_function_incoming_arg (cumulative_args_t,
 					const function_arg_info &);
@@ -7590,19 +7590,19 @@ sparc_arg_partial_bytes (cumulative_args
 }
 
 /* Handle the TARGET_FUNCTION_ARG_ADVANCE hook.
-   Update the data in CUM to advance over an argument
-   of mode MODE and data type TYPE.
-   TYPE is null for libcalls where that information may not be available.  */
+   Update the data in CUM to advance over argument ARG.  */
 
 static void
-sparc_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
-			    const_tree type, bool named)
+sparc_function_arg_advance (cumulative_args_t cum_v,
+			    const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
+  tree type = arg.type;
+  machine_mode mode = arg.mode;
   int regno, padding;
 
   /* We pass false for incoming here, it doesn't matter.  */
-  function_arg_slotno (cum, mode, type, named, false, &regno, &padding);
+  function_arg_slotno (cum, mode, type, arg.named, false, &regno, &padding);
 
   /* If argument requires leading padding, add it.  */
   cum->words += padding;
Index: gcc/config/spu/spu.c
===================================================================
--- gcc/config/spu/spu.c	2019-08-19 15:58:42.421976335 +0100
+++ gcc/config/spu/spu.c	2019-08-19 15:58:50.341919030 +0100
@@ -3863,18 +3863,18 @@ spu_function_arg (cumulative_args_t cum_
 }
 
 static void
-spu_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
-			  const_tree type, bool named ATTRIBUTE_UNUSED)
+spu_function_arg_advance (cumulative_args_t cum_v,
+			  const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
-  *cum += (type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
+  *cum += (arg.type && TREE_CODE (TYPE_SIZE (arg.type)) != INTEGER_CST
 	   ? 1
-	   : mode == BLKmode
-	   ? ((int_size_in_bytes (type) + 15) / 16)
-	   : mode == VOIDmode
+	   : arg.mode == BLKmode
+	   ? ((int_size_in_bytes (arg.type) + 15) / 16)
+	   : arg.mode == VOIDmode
 	   ? 1
-	   : spu_hard_regno_nregs (FIRST_ARG_REGNUM, mode));
+	   : spu_hard_regno_nregs (FIRST_ARG_REGNUM, arg.mode));
 }
 
 /* Implement TARGET_FUNCTION_ARG_OFFSET.  The SPU ABI wants 32/64-bit
@@ -4099,8 +4099,7 @@ spu_setup_incoming_varargs (cumulative_a
 
       /* cum currently points to the last named argument, we want to
          start at the next argument. */
-      spu_function_arg_advance (pack_cumulative_args (&ncum),
-				arg.mode, arg.type, arg.named);
+      spu_function_arg_advance (pack_cumulative_args (&ncum), arg);
 
       offset = -STACK_POINTER_OFFSET;
       for (regno = ncum; regno < MAX_REGISTER_ARGS; regno++)
Index: gcc/config/stormy16/stormy16.c
===================================================================
--- gcc/config/stormy16/stormy16.c	2019-08-19 15:58:42.421976335 +0100
+++ gcc/config/stormy16/stormy16.c	2019-08-19 15:58:50.341919030 +0100
@@ -1205,9 +1205,8 @@ xstormy16_function_profiler (void)
   sorry ("function_profiler support");
 }
 \f
-/* Update CUM to advance past an argument in the argument list.  The
-   values MODE, TYPE and NAMED describe that argument.  Once this is
-   done, the variable CUM is suitable for analyzing the *following*
+/* Update CUM to advance past argument ARG.  Once this is done,
+   the variable CUM is suitable for analyzing the *following*
    argument with `TARGET_FUNCTION_ARG', etc.
 
    This function need not do anything if the argument in question was
@@ -1217,8 +1216,8 @@ xstormy16_function_profiler (void)
    the word count.  */
 
 static void
-xstormy16_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
-				const_tree type, bool named ATTRIBUTE_UNUSED)
+xstormy16_function_arg_advance (cumulative_args_t cum_v,
+				const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
@@ -1226,10 +1225,11 @@ xstormy16_function_arg_advance (cumulati
      and partially on the stack, the whole of it is passed on the
      stack.  */
   if (*cum < NUM_ARGUMENT_REGISTERS
-      && *cum + XSTORMY16_WORD_SIZE (type, mode) > NUM_ARGUMENT_REGISTERS)
+      && (*cum + XSTORMY16_WORD_SIZE (arg.type, arg.mode)
+	  > NUM_ARGUMENT_REGISTERS))
     *cum = NUM_ARGUMENT_REGISTERS;
 
-  *cum += XSTORMY16_WORD_SIZE (type, mode);
+  *cum += XSTORMY16_WORD_SIZE (arg.type, arg.mode);
 }
 
 static rtx
Index: gcc/config/tilegx/tilegx.c
===================================================================
--- gcc/config/tilegx/tilegx.c	2019-08-19 15:58:42.421976335 +0100
+++ gcc/config/tilegx/tilegx.c	2019-08-19 15:58:50.341919030 +0100
@@ -245,19 +245,17 @@ tilegx_function_arg (cumulative_args_t c
 /* Implement TARGET_FUNCTION_ARG_ADVANCE.  */
 static void
 tilegx_function_arg_advance (cumulative_args_t cum_v,
-			     machine_mode mode,
-			     const_tree type, bool named ATTRIBUTE_UNUSED)
+			     const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
-  int byte_size = ((mode == BLKmode)
-		   ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
+  int byte_size = arg.promoted_size_in_bytes ();
   int word_size = (byte_size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
   bool doubleword_aligned_p;
 
   /* See whether the argument has doubleword alignment.  */
   doubleword_aligned_p =
-    tilegx_function_arg_boundary (mode, type) > BITS_PER_WORD;
+    tilegx_function_arg_boundary (arg.mode, arg.type) > BITS_PER_WORD;
 
   if (doubleword_aligned_p)
     *cum += *cum & 1;
@@ -396,8 +394,7 @@ tilegx_setup_incoming_varargs (cumulativ
   /* The caller has advanced CUM up to, but not beyond, the last named
      argument.  Advance a local copy of CUM past the last "real" named
      argument, to find out how many registers are left over.  */
-  targetm.calls.function_arg_advance (pack_cumulative_args (&local_cum),
-				      arg.mode, arg.type, arg.named);
+  targetm.calls.function_arg_advance (pack_cumulative_args (&local_cum), arg);
   first_reg = local_cum;
 
   if (local_cum < TILEGX_NUM_ARG_REGS)
Index: gcc/config/tilepro/tilepro.c
===================================================================
--- gcc/config/tilepro/tilepro.c	2019-08-19 15:58:42.421976335 +0100
+++ gcc/config/tilepro/tilepro.c	2019-08-19 15:58:50.341919030 +0100
@@ -197,19 +197,17 @@ tilepro_function_arg (cumulative_args_t
 /* Implement TARGET_FUNCTION_ARG_ADVANCE.  */
 static void
 tilepro_function_arg_advance (cumulative_args_t cum_v,
-			      machine_mode mode,
-			      const_tree type, bool named ATTRIBUTE_UNUSED)
+			      const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
-  int byte_size = ((mode == BLKmode)
-		   ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
+  int byte_size = arg.promoted_size_in_bytes ();
   int word_size = (byte_size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
   bool doubleword_aligned_p;
 
   /* See whether the argument has doubleword alignment.  */
   doubleword_aligned_p =
-    tilepro_function_arg_boundary (mode, type) > BITS_PER_WORD;
+    tilepro_function_arg_boundary (arg.mode, arg.type) > BITS_PER_WORD;
 
   if (doubleword_aligned_p)
     *cum += *cum & 1;
@@ -348,8 +346,7 @@ tilepro_setup_incoming_varargs (cumulati
   /* The caller has advanced CUM up to, but not beyond, the last named
      argument.  Advance a local copy of CUM past the last "real" named
      argument, to find out how many registers are left over.  */
-  targetm.calls.function_arg_advance (pack_cumulative_args (&local_cum),
-				      arg.mode, arg.type, arg.named);
+  targetm.calls.function_arg_advance (pack_cumulative_args (&local_cum), arg);
   first_reg = local_cum;
 
   if (local_cum < TILEPRO_NUM_ARG_REGS)
Index: gcc/config/v850/v850.c
===================================================================
--- gcc/config/v850/v850.c	2019-08-19 15:58:42.421976335 +0100
+++ gcc/config/v850/v850.c	2019-08-19 15:58:50.341919030 +0100
@@ -216,27 +216,22 @@ v850_arg_partial_bytes (cumulative_args_
   return 4 * UNITS_PER_WORD - cum->nbytes;
 }
 
-/* Update the data in CUM to advance over an argument
-   of mode MODE and data type TYPE.
-   (TYPE is null for libcalls where that information may not be available.)  */
+/* Update the data in CUM to advance over argument ARG.  */
 
 static void
-v850_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
-			   const_tree type, bool named ATTRIBUTE_UNUSED)
+v850_function_arg_advance (cumulative_args_t cum_v,
+			   const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
   if (!TARGET_GCC_ABI)
-    cum->nbytes += (((mode != BLKmode
-		      ? GET_MODE_SIZE (mode)
-		      : int_size_in_bytes (type)) + UNITS_PER_WORD - 1)
+    cum->nbytes += ((arg.promoted_size_in_bytes () + UNITS_PER_WORD - 1)
 		    & -UNITS_PER_WORD);
   else
-    cum->nbytes += (((type && int_size_in_bytes (type) > 8
+    cum->nbytes += (((arg.type && int_size_in_bytes (arg.type) > 8
 		      ? GET_MODE_SIZE (Pmode)
-		      : (mode != BLKmode
-			 ? GET_MODE_SIZE (mode)
-			 : int_size_in_bytes (type))) + UNITS_PER_WORD - 1)
+		      : (HOST_WIDE_INT) arg.promoted_size_in_bytes ())
+		     + UNITS_PER_WORD - 1)
 		    & -UNITS_PER_WORD);
 }
 
Index: gcc/config/vax/vax.c
===================================================================
--- gcc/config/vax/vax.c	2019-08-19 15:58:42.421976335 +0100
+++ gcc/config/vax/vax.c	2019-08-19 15:58:50.341919030 +0100
@@ -55,8 +55,8 @@ static int vax_address_cost_1 (rtx);
 static int vax_address_cost (rtx, machine_mode, addr_space_t, bool);
 static bool vax_rtx_costs (rtx, machine_mode, int, int, int *, bool);
 static rtx vax_function_arg (cumulative_args_t, const function_arg_info &);
-static void vax_function_arg_advance (cumulative_args_t, machine_mode,
-				      const_tree, bool);
+static void vax_function_arg_advance (cumulative_args_t,
+				      const function_arg_info &);
 static rtx vax_struct_value_rtx (tree, int);
 static void vax_asm_trampoline_template (FILE *);
 static void vax_trampoline_init (rtx, tree, rtx);
@@ -2148,19 +2148,15 @@ vax_function_arg (cumulative_args_t, con
   return NULL_RTX;
 }
 
-/* Update the data in CUM to advance over an argument of mode MODE and
-   data type TYPE.  (TYPE is null for libcalls where that information
-   may not be available.)  */
+/* Update the data in CUM to advance over argument ARG.  */
 
 static void
-vax_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
-			  const_tree type, bool named ATTRIBUTE_UNUSED)
+vax_function_arg_advance (cumulative_args_t cum_v,
+			  const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
-  *cum += (mode != BLKmode
-	   ? (GET_MODE_SIZE (mode) + 3) & ~3
-	   : (int_size_in_bytes (type) + 3) & ~3);
+  *cum += (arg.promoted_size_in_bytes () + 3) & ~3;
 }
 
 static HOST_WIDE_INT
Index: gcc/config/visium/visium.c
===================================================================
--- gcc/config/visium/visium.c	2019-08-19 15:58:42.421976335 +0100
+++ gcc/config/visium/visium.c	2019-08-19 15:58:50.341919030 +0100
@@ -163,8 +163,8 @@ static bool visium_pass_by_reference (cu
 
 static rtx visium_function_arg (cumulative_args_t, const function_arg_info &);
 
-static void visium_function_arg_advance (cumulative_args_t, machine_mode,
-					 const_tree, bool);
+static void visium_function_arg_advance (cumulative_args_t,
+					 const function_arg_info &);
 
 static bool visium_return_in_memory (const_tree, const_tree fntype);
 
@@ -1358,28 +1358,25 @@ visium_function_arg (cumulative_args_t p
   return NULL_RTX;
 }
 
-/* Update the summarizer variable pointed to by PCUM_V to advance past an
-   argument in the argument list.  The values MODE, TYPE and NAMED describe
-   that argument.  Once this is done, the variable CUM is suitable for
+/* Update the summarizer variable pointed to by PCUM_V to advance past
+   argument ARG.  Once this is done, the variable CUM is suitable for
    analyzing the _following_ argument with visium_function_arg.  */
 
 static void
 visium_function_arg_advance (cumulative_args_t pcum_v,
-			     machine_mode mode,
-			     const_tree type ATTRIBUTE_UNUSED,
-			     bool named)
+			     const function_arg_info &arg)
 {
-  int size = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+  int size = (GET_MODE_SIZE (arg.mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
   int stack_size = 0;
   CUMULATIVE_ARGS *ca = get_cumulative_args (pcum_v);
 
   /* Scalar or complex single precision floating point arguments are returned
      in floating registers.  */
   if (TARGET_FPU
-      && ((GET_MODE_CLASS (mode) == MODE_FLOAT
-	   && GET_MODE_SIZE (mode) <= UNITS_PER_HWFPVALUE)
-	  || (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
-	      && GET_MODE_SIZE (mode) <= UNITS_PER_HWFPVALUE * 2)))
+      && ((GET_MODE_CLASS (arg.mode) == MODE_FLOAT
+	   && GET_MODE_SIZE (arg.mode) <= UNITS_PER_HWFPVALUE)
+	  || (GET_MODE_CLASS (arg.mode) == MODE_COMPLEX_FLOAT
+	      && GET_MODE_SIZE (arg.mode) <= UNITS_PER_HWFPVALUE * 2)))
     {
       if (ca->frcount + size <= MAX_ARGS_IN_FP_REGISTERS)
 	ca->frcount += size;
@@ -1402,7 +1399,7 @@ visium_function_arg_advance (cumulative_
 	}
     }
 
-  if (named)
+  if (arg.named)
     ca->stack_words += stack_size;
 }
 
@@ -1483,8 +1480,7 @@ visium_setup_incoming_varargs (cumulativ
   /* The caller has advanced ARGS_SO_FAR up to, but not beyond, the last named
      argument.  Advance a local copy of ARGS_SO_FAR past the last "real" named
      argument, to find out how many registers are left over.  */
-  TARGET_FUNCTION_ARG_ADVANCE (local_args_so_far, arg.mode,
-			       arg.type, arg.named);
+  TARGET_FUNCTION_ARG_ADVANCE (local_args_so_far, arg);
 
   /* Find how many registers we need to save.  */
   locargs = get_cumulative_args (local_args_so_far);
Index: gcc/config/xtensa/xtensa.c
===================================================================
--- gcc/config/xtensa/xtensa.c	2019-08-19 15:58:42.421976335 +0100
+++ gcc/config/xtensa/xtensa.c	2019-08-19 15:58:50.341919030 +0100
@@ -141,8 +141,8 @@ static tree xtensa_build_builtin_va_list
 static bool xtensa_return_in_memory (const_tree, const_tree);
 static tree xtensa_gimplify_va_arg_expr (tree, tree, gimple_seq *,
 					 gimple_seq *);
-static void xtensa_function_arg_advance (cumulative_args_t, machine_mode,
-					 const_tree, bool);
+static void xtensa_function_arg_advance (cumulative_args_t,
+					 const function_arg_info &);
 static rtx xtensa_function_arg (cumulative_args_t, const function_arg_info &);
 static rtx xtensa_function_incoming_arg (cumulative_args_t,
 					 const function_arg_info &);
@@ -2105,8 +2105,8 @@ init_cumulative_args (CUMULATIVE_ARGS *c
 /* Advance the argument to the next argument position.  */
 
 static void
-xtensa_function_arg_advance (cumulative_args_t cum, machine_mode mode,
-			     const_tree type, bool named ATTRIBUTE_UNUSED)
+xtensa_function_arg_advance (cumulative_args_t cum,
+			     const function_arg_info &arg)
 {
   int words, max;
   int *arg_words;
@@ -2114,12 +2114,11 @@ xtensa_function_arg_advance (cumulative_
   arg_words = &get_cumulative_args (cum)->arg_words;
   max = MAX_ARGS_IN_REGISTERS;
 
-  words = (((mode != BLKmode)
-	    ? (int) GET_MODE_SIZE (mode)
-	    : int_size_in_bytes (type)) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+  words = ((arg.promoted_size_in_bytes () + UNITS_PER_WORD - 1)
+	   / UNITS_PER_WORD);
 
   if (*arg_words < max
-      && (targetm.calls.must_pass_in_stack (mode, type)
+      && (targetm.calls.must_pass_in_stack (arg.mode, arg.type)
 	  || *arg_words + words > max))
     *arg_words = max;
 

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [08/13] Use function_arg_info for TARGET_CALLEE_COPIES
  2019-08-19 15:15 [00/13] Pass an argument descriptor to target hooks Richard Sandiford
                   ` (6 preceding siblings ...)
  2019-08-19 15:22 ` [07/13] Use function_arg_info for TARGET_FUNCTION_ARG_ADVANCE Richard Sandiford
@ 2019-08-19 15:23 ` Richard Sandiford
  2019-08-19 21:16   ` Jeff Law
  2019-08-19 15:24 ` [09/13] Use function_arg_info for TARGET_MUST_PASS_IN_STACK Richard Sandiford
                   ` (4 subsequent siblings)
  12 siblings, 1 reply; 27+ messages in thread
From: Richard Sandiford @ 2019-08-19 15:23 UTC (permalink / raw)
  To: gcc-patches

Use function_arg_info for TARGET_CALLEE_COPIES.

The hook is passed the unpromoted type mode instead of the promoted mode.

The aarch64 definition is redundant, but worth keeping for emphasis.


2019-08-19  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	* target.def (callee_copies): Take a function_arg_info instead
	of a mode, type and named flag.
	* doc/tm.texi: Regenerate.
	* targhooks.h (hook_callee_copies_named): Take a function_arg_info
	instead of a mode, type and named flag.
	(hook_bool_CUMULATIVE_ARGS_mode_tree_bool_false): Delete.
	(hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true): Likewise.
	(hook_bool_CUMULATIVE_ARGS_arg_info_true): New function.
	* targhooks.c (hook_callee_copies_named): Take a function_arg_info
	instead of a mode, type and named flag.
	(hook_bool_CUMULATIVE_ARGS_mode_tree_bool_false): Delete.
	(hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true): Likewise.
	(hook_bool_CUMULATIVE_ARGS_arg_info_true): New function.
	* calls.h (reference_callee_copied): Take a function_arg_info
	instead of a mode, type and named flag.
	* calls.c (reference_callee_copied): Likewise.
	(initialize_argument_information): Update call accordingly.
	(emit_library_call_value_1): Likewise.
	* function.c (gimplify_parameters): Likewise.
	* config/aarch64/aarch64.c (TARGET_CALLEE_COPIES): Define to
	hook_bool_CUMULATIVE_ARGS_arg_info_false instead of
	hook_bool_CUMULATIVE_ARGS_mode_tree_bool_false.
	* config/c6x/c6x.c (c6x_callee_copies): Delete.
	(TARGET_CALLEE_COPIES): Define to
	hook_bool_CUMULATIVE_ARGS_arg_info_true instead.
	* config/epiphany/epiphany.c (TARGET_CALLEE_COPIES): Define to
	hook_bool_CUMULATIVE_ARGS_arg_info_true instead of
	hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true.
	* config/mips/mips.c (mips_callee_copies): Take a function_arg_info
	instead of a mode, type and named flag.
	* config/mmix/mmix.c (TARGET_CALLEE_COPIES): Define to
	hook_bool_CUMULATIVE_ARGS_arg_info_true instead of
	hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true.
	* config/mn10300/mn10300.c (TARGET_CALLEE_COPIES): Likewise.
	* config/msp430/msp430.c (msp430_callee_copies): Delete.
	(TARGET_CALLEE_COPIES): Define to
	hook_bool_CUMULATIVE_ARGS_arg_info_true instead.
	* config/pa/pa.c (pa_callee_copies): Take a function_arg_info
	instead of a mode, type and named flag.
	* config/sh/sh.c (sh_callee_copies): Likewise.
	* config/v850/v850.c (TARGET_CALLEE_COPIES): Define to
	hook_bool_CUMULATIVE_ARGS_arg_info_true instead of
	hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true.

Index: gcc/target.def
===================================================================
--- gcc/target.def	2019-08-19 15:58:50.345918999 +0100
+++ gcc/target.def	2019-08-19 15:58:58.017863486 +0100
@@ -4653,8 +4653,8 @@ not be generated.\n\
 \n\
 The default version of this hook always returns false.",
  bool,
- (cumulative_args_t cum, machine_mode mode, const_tree type, bool named),
- hook_bool_CUMULATIVE_ARGS_mode_tree_bool_false)
+ (cumulative_args_t cum, const function_arg_info &arg),
+ hook_bool_CUMULATIVE_ARGS_arg_info_false)
 
 /* Return zero for arguments passed entirely on the stack or entirely
    in registers.  If passed in both, return the number of bytes passed
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	2019-08-19 15:58:50.341919030 +0100
+++ gcc/doc/tm.texi	2019-08-19 15:58:58.013863514 +0100
@@ -4080,7 +4080,7 @@ The pointer is passed in whatever way is
 to that type.
 @end deftypefn
 
-@deftypefn {Target Hook} bool TARGET_CALLEE_COPIES (cumulative_args_t @var{cum}, machine_mode @var{mode}, const_tree @var{type}, bool @var{named})
+@deftypefn {Target Hook} bool TARGET_CALLEE_COPIES (cumulative_args_t @var{cum}, const function_arg_info @var{&arg})
 The function argument described by the parameters to this hook is
 known to be passed by reference.  The hook should return true if the
 function argument should be copied by the callee instead of copied
Index: gcc/targhooks.h
===================================================================
--- gcc/targhooks.h	2019-08-19 15:58:50.345918999 +0100
+++ gcc/targhooks.h	2019-08-19 15:58:58.017863486 +0100
@@ -67,7 +67,7 @@ extern tree default_cxx_get_cookie_size
 extern bool hook_pass_by_reference_must_pass_in_stack
   (cumulative_args_t, const function_arg_info &);
 extern bool hook_callee_copies_named
-  (cumulative_args_t ca, machine_mode, const_tree, bool);
+  (cumulative_args_t ca, const function_arg_info &);
 
 extern void default_print_operand (FILE *, rtx, int);
 extern void default_print_operand_address (FILE *, machine_mode, rtx);
@@ -135,12 +135,10 @@ extern void default_goacc_reduction (gca
 extern bool hook_bool_CUMULATIVE_ARGS_false (cumulative_args_t);
 extern bool hook_bool_CUMULATIVE_ARGS_true (cumulative_args_t);
 
-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 bool hook_bool_CUMULATIVE_ARGS_arg_info_false
   (cumulative_args_t, const function_arg_info &);
+extern bool hook_bool_CUMULATIVE_ARGS_arg_info_true
+  (cumulative_args_t, const function_arg_info &);
 extern int hook_int_CUMULATIVE_ARGS_arg_info_0
   (cumulative_args_t, const function_arg_info &);
 extern void hook_void_CUMULATIVE_ARGS_tree
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c	2019-08-19 15:58:50.345918999 +0100
+++ gcc/targhooks.c	2019-08-19 15:58:58.017863486 +0100
@@ -330,11 +330,9 @@ hook_pass_by_reference_must_pass_in_stac
    version of the hook is true for all named arguments.  */
 
 bool
-hook_callee_copies_named (cumulative_args_t ca ATTRIBUTE_UNUSED,
-			  machine_mode mode ATTRIBUTE_UNUSED,
-			  const_tree type ATTRIBUTE_UNUSED, bool named)
+hook_callee_copies_named (cumulative_args_t, const function_arg_info &arg)
 {
-  return named;
+  return arg.named;
 }
 
 /* Emit to STREAM the assembler syntax for insn operand X.  */
@@ -746,30 +744,19 @@ default_builtin_reciprocal (tree)
 }
 
 bool
-hook_bool_CUMULATIVE_ARGS_mode_tree_bool_false (
-	cumulative_args_t ca ATTRIBUTE_UNUSED,
-	machine_mode mode ATTRIBUTE_UNUSED,
-	const_tree type ATTRIBUTE_UNUSED, bool named ATTRIBUTE_UNUSED)
+hook_bool_CUMULATIVE_ARGS_arg_info_false (cumulative_args_t,
+					  const function_arg_info &)
 {
   return false;
 }
 
 bool
-hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true (
-	cumulative_args_t ca ATTRIBUTE_UNUSED,
-	machine_mode mode ATTRIBUTE_UNUSED,
-	const_tree type ATTRIBUTE_UNUSED, bool named ATTRIBUTE_UNUSED)
+hook_bool_CUMULATIVE_ARGS_arg_info_true (cumulative_args_t,
+					 const function_arg_info &)
 {
   return true;
 }
 
-bool
-hook_bool_CUMULATIVE_ARGS_arg_info_false (cumulative_args_t,
-					  const function_arg_info &)
-{
-  return false;
-}
-
 int
 hook_int_CUMULATIVE_ARGS_arg_info_0 (cumulative_args_t,
 				     const function_arg_info &)
Index: gcc/calls.h
===================================================================
--- gcc/calls.h	2019-08-19 15:58:42.381976625 +0100
+++ gcc/calls.h	2019-08-19 15:58:57.997863631 +0100
@@ -118,8 +118,8 @@ extern void fixup_tail_calls (void);
 
 extern bool pass_by_reference (CUMULATIVE_ARGS *, function_arg_info);
 extern bool pass_va_arg_by_reference (tree);
-extern bool reference_callee_copied (CUMULATIVE_ARGS *, machine_mode,
-				     tree, bool);
+extern bool reference_callee_copied (CUMULATIVE_ARGS *,
+				     const function_arg_info &);
 extern void maybe_warn_alloc_args_overflow (tree, tree, tree[2], int[2]);
 extern tree get_attr_nonstring_decl (tree, tree * = NULL);
 extern void maybe_warn_nonstring_arg (tree, tree);
Index: gcc/calls.c
===================================================================
--- gcc/calls.c	2019-08-19 15:58:50.301919320 +0100
+++ gcc/calls.c	2019-08-19 15:58:57.993863659 +0100
@@ -935,17 +935,15 @@ pass_va_arg_by_reference (tree type)
   return pass_by_reference (NULL, function_arg_info (type, /*named=*/false));
 }
 
-/* Return true if TYPE, which is passed by reference, should be callee
+/* Return true if ARG, which is passed by reference, should be callee
    copied instead of caller copied.  */
 
 bool
-reference_callee_copied (CUMULATIVE_ARGS *ca, machine_mode mode,
-			 tree type, bool named_arg)
+reference_callee_copied (CUMULATIVE_ARGS *ca, const function_arg_info &arg)
 {
-  if (type && TREE_ADDRESSABLE (type))
+  if (arg.type && TREE_ADDRESSABLE (arg.type))
     return false;
-  return targetm.calls.callee_copies (pack_cumulative_args (ca), mode, type,
-				      named_arg);
+  return targetm.calls.callee_copies (pack_cumulative_args (ca), arg);
 }
 
 
@@ -2002,9 +2000,7 @@ initialize_argument_information (int num
 	  bool callee_copies;
 	  tree base = NULL_TREE;
 
-	  callee_copies
-	    = reference_callee_copied (args_so_far_pnt, TYPE_MODE (type),
-				       type, argpos < n_named_args);
+	  callee_copies = reference_callee_copied (args_so_far_pnt, orig_arg);
 
 	  /* If we're compiling a thunk, pass through invisible references
 	     instead of making a copy.  */
@@ -4911,8 +4907,7 @@ emit_library_call_value_1 (int retval, r
       if (pass_by_reference (&args_so_far_v, orig_arg))
 	{
 	  rtx slot;
-	  int must_copy
-	    = !reference_callee_copied (&args_so_far_v, mode, NULL_TREE, 1);
+	  int must_copy = !reference_callee_copied (&args_so_far_v, orig_arg);
 
 	  /* If this was a CONST function, it is now PURE since it now
 	     reads memory.  */
Index: gcc/function.c
===================================================================
--- gcc/function.c	2019-08-19 15:58:50.345918999 +0100
+++ gcc/function.c	2019-08-19 15:58:58.013863514 +0100
@@ -3866,8 +3866,8 @@ gimplify_parameters (gimple_seq *cleanup
       if (data.passed_pointer)
 	{
           tree type = TREE_TYPE (data.passed_type);
-	  if (reference_callee_copied (&all.args_so_far_v, TYPE_MODE (type),
-				       type, data.named_arg))
+	  function_arg_info orig_arg (type, data.named_arg);
+	  if (reference_callee_copied (&all.args_so_far_v, orig_arg))
 	    {
 	      tree local, t;
 
Index: gcc/config/aarch64/aarch64.c
===================================================================
--- gcc/config/aarch64/aarch64.c	2019-08-19 15:58:50.305919288 +0100
+++ gcc/config/aarch64/aarch64.c	2019-08-19 15:58:58.001863604 +0100
@@ -20323,7 +20323,7 @@ #define TARGET_ASM_TRAMPOLINE_TEMPLATE a
 #define TARGET_BUILD_BUILTIN_VA_LIST aarch64_build_builtin_va_list
 
 #undef TARGET_CALLEE_COPIES
-#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_false
+#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_arg_info_false
 
 #undef TARGET_CAN_ELIMINATE
 #define TARGET_CAN_ELIMINATE aarch64_can_eliminate
Index: gcc/config/c6x/c6x.c
===================================================================
--- gcc/config/c6x/c6x.c	2019-08-19 15:58:50.317919202 +0100
+++ gcc/config/c6x/c6x.c	2019-08-19 15:58:58.001863604 +0100
@@ -635,7 +635,7 @@ c6x_function_value_regno_p (const unsign
 }
 
 /* Types larger than 64 bit, and variable sized types, are passed by
-   reference.  The callee must copy them; see c6x_callee_copies.  */
+   reference.  The callee must copy them; see TARGET_CALLEE_COPIES.  */
 
 static bool
 c6x_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
@@ -669,17 +669,6 @@ c6x_return_in_msb (const_tree valtype)
   return TARGET_BIG_ENDIAN && AGGREGATE_TYPE_P (valtype) && size == 3;
 }
 
-/* Implement TARGET_CALLEE_COPIES.  */
-
-static bool
-c6x_callee_copies (cumulative_args_t cum_v ATTRIBUTE_UNUSED,
-		   machine_mode mode ATTRIBUTE_UNUSED,
-		   const_tree type ATTRIBUTE_UNUSED,
-		   bool named ATTRIBUTE_UNUSED)
-{
-  return true;
-}
-
 /* Return the type to use as __builtin_va_list.  */
 static tree
 c6x_build_builtin_va_list (void)
@@ -6726,7 +6715,7 @@ #define TARGET_RETURN_IN_MSB c6x_return_
 #undef TARGET_PASS_BY_REFERENCE
 #define TARGET_PASS_BY_REFERENCE c6x_pass_by_reference
 #undef TARGET_CALLEE_COPIES
-#define TARGET_CALLEE_COPIES c6x_callee_copies
+#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_arg_info_true
 #undef TARGET_STRUCT_VALUE_RTX
 #define TARGET_STRUCT_VALUE_RTX c6x_struct_value_rtx
 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
Index: gcc/config/epiphany/epiphany.c
===================================================================
--- gcc/config/epiphany/epiphany.c	2019-08-19 15:58:50.321919175 +0100
+++ gcc/config/epiphany/epiphany.c	2019-08-19 15:58:58.001863604 +0100
@@ -90,7 +90,7 @@ #define TARGET_PROMOTE_PROTOTYPES hook_b
 
 #define TARGET_RETURN_IN_MEMORY epiphany_return_in_memory
 #define TARGET_PASS_BY_REFERENCE epiphany_pass_by_reference
-#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true
+#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_arg_info_true
 #define TARGET_FUNCTION_VALUE epiphany_function_value
 #define TARGET_LIBCALL_VALUE epiphany_libcall_value
 #define TARGET_FUNCTION_VALUE_REGNO_P epiphany_function_value_regno_p
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	2019-08-19 15:58:50.333919085 +0100
+++ gcc/config/mips/mips.c	2019-08-19 15:58:58.005863572 +0100
@@ -6259,11 +6259,9 @@ mips_pass_by_reference (cumulative_args_
 /* Implement TARGET_CALLEE_COPIES.  */
 
 static bool
-mips_callee_copies (cumulative_args_t cum ATTRIBUTE_UNUSED,
-		    machine_mode mode ATTRIBUTE_UNUSED,
-		    const_tree type ATTRIBUTE_UNUSED, bool named)
+mips_callee_copies (cumulative_args_t, const function_arg_info &arg)
 {
-  return mips_abi == ABI_EABI && named;
+  return mips_abi == ABI_EABI && arg.named;
 }
 \f
 /* See whether VALTYPE is a record whose fields should be returned in
Index: gcc/config/mmix/mmix.c
===================================================================
--- gcc/config/mmix/mmix.c	2019-08-19 15:58:50.333919085 +0100
+++ gcc/config/mmix/mmix.c	2019-08-19 15:58:58.005863572 +0100
@@ -263,7 +263,7 @@ #define TARGET_SETUP_INCOMING_VARARGS mm
 #undef TARGET_PASS_BY_REFERENCE
 #define TARGET_PASS_BY_REFERENCE mmix_pass_by_reference
 #undef TARGET_CALLEE_COPIES
-#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true
+#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_arg_info_true
 
 #undef TARGET_PREFERRED_RELOAD_CLASS
 #define TARGET_PREFERRED_RELOAD_CLASS mmix_preferred_reload_class
Index: gcc/config/mn10300/mn10300.c
===================================================================
--- gcc/config/mn10300/mn10300.c	2019-08-19 15:58:50.333919085 +0100
+++ gcc/config/mn10300/mn10300.c	2019-08-19 15:58:58.009863545 +0100
@@ -3354,7 +3354,7 @@ #define TARGET_RETURN_IN_MEMORY mn10300_
 #undef  TARGET_PASS_BY_REFERENCE
 #define TARGET_PASS_BY_REFERENCE mn10300_pass_by_reference
 #undef  TARGET_CALLEE_COPIES
-#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true
+#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_arg_info_true
 #undef  TARGET_ARG_PARTIAL_BYTES
 #define TARGET_ARG_PARTIAL_BYTES mn10300_arg_partial_bytes
 #undef  TARGET_FUNCTION_ARG
Index: gcc/config/msp430/msp430.c
===================================================================
--- gcc/config/msp430/msp430.c	2019-08-19 15:58:50.333919085 +0100
+++ gcc/config/msp430/msp430.c	2019-08-19 15:58:58.009863545 +0100
@@ -750,16 +750,7 @@ msp430_pass_by_reference (cumulative_arg
 }
 
 #undef  TARGET_CALLEE_COPIES
-#define TARGET_CALLEE_COPIES msp430_callee_copies
-
-static bool
-msp430_callee_copies (cumulative_args_t cap ATTRIBUTE_UNUSED,
-		      machine_mode mode ATTRIBUTE_UNUSED,
-		      const_tree type ATTRIBUTE_UNUSED,
-		      bool named ATTRIBUTE_UNUSED)
-{
-  return true;
-}
+#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_arg_info_true
 
 #undef  TARGET_FUNCTION_ARG_ADVANCE
 #define TARGET_FUNCTION_ARG_ADVANCE msp430_function_arg_advance
Index: gcc/config/pa/pa.c
===================================================================
--- gcc/config/pa/pa.c	2019-08-19 15:58:50.337919057 +0100
+++ gcc/config/pa/pa.c	2019-08-19 15:58:58.009863545 +0100
@@ -197,8 +197,7 @@ static bool pa_cannot_force_const_mem (m
 static bool pa_legitimate_constant_p (machine_mode, rtx);
 static unsigned int pa_section_type_flags (tree, const char *, int);
 static bool pa_legitimate_address_p (machine_mode, rtx, bool);
-static bool pa_callee_copies (cumulative_args_t, machine_mode,
-			      const_tree, bool);
+static bool pa_callee_copies (cumulative_args_t, const function_arg_info &);
 static unsigned int pa_hard_regno_nregs (unsigned int, machine_mode);
 static bool pa_hard_regno_mode_ok (unsigned int, machine_mode);
 static bool pa_modes_tieable_p (machine_mode, machine_mode);
@@ -10764,10 +10763,7 @@ pa_maybe_emit_compare_and_swap_exchange_
    in the 64-bit HP runtime.  */
 
 static bool
-pa_callee_copies (cumulative_args_t cum ATTRIBUTE_UNUSED,
-		  machine_mode mode ATTRIBUTE_UNUSED,
-		  const_tree type ATTRIBUTE_UNUSED,
-		  bool named ATTRIBUTE_UNUSED)
+pa_callee_copies (cumulative_args_t, const function_arg_info &)
 {
   return !TARGET_CALLER_COPIES;
 }
Index: gcc/config/sh/sh.c
===================================================================
--- gcc/config/sh/sh.c	2019-08-19 15:58:50.337919057 +0100
+++ gcc/config/sh/sh.c	2019-08-19 15:58:58.013863514 +0100
@@ -296,8 +296,7 @@ static machine_mode sh_promote_function_
 						   int for_return);
 static bool sh_pass_by_reference (cumulative_args_t,
 				  const function_arg_info &);
-static bool sh_callee_copies (cumulative_args_t, machine_mode,
-			      const_tree, bool);
+static bool sh_callee_copies (cumulative_args_t, const function_arg_info &);
 static int sh_arg_partial_bytes (cumulative_args_t, const function_arg_info &);
 static void sh_function_arg_advance (cumulative_args_t,
 				     const function_arg_info &);
@@ -7915,14 +7914,15 @@ sh_pass_by_reference (cumulative_args_t
 }
 
 static bool
-sh_callee_copies (cumulative_args_t cum, machine_mode mode,
-		  const_tree type, bool named ATTRIBUTE_UNUSED)
+sh_callee_copies (cumulative_args_t cum, const function_arg_info &arg)
 {
   /* ??? How can it possibly be correct to return true only on the
      caller side of the equation?  Is there someplace else in the
      sh backend that's magically producing the copies?  */
   return (get_cumulative_args (cum)->outgoing
-	  && ((mode == BLKmode ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode))
+	  && ((arg.mode == BLKmode
+	       ? TYPE_ALIGN (arg.type)
+	       : GET_MODE_ALIGNMENT (arg.mode))
 	      % SH_MIN_ALIGN_FOR_CALLEE_COPY == 0));
 }
 
Index: gcc/config/v850/v850.c
===================================================================
--- gcc/config/v850/v850.c	2019-08-19 15:58:50.341919030 +0100
+++ gcc/config/v850/v850.c	2019-08-19 15:58:58.013863514 +0100
@@ -3263,7 +3263,7 @@ #define TARGET_RETURN_IN_MEMORY v850_ret
 #define TARGET_PASS_BY_REFERENCE v850_pass_by_reference
 
 #undef  TARGET_CALLEE_COPIES
-#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true
+#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_arg_info_true
 
 #undef  TARGET_ARG_PARTIAL_BYTES
 #define TARGET_ARG_PARTIAL_BYTES v850_arg_partial_bytes

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [09/13] Use function_arg_info for TARGET_MUST_PASS_IN_STACK
  2019-08-19 15:15 [00/13] Pass an argument descriptor to target hooks Richard Sandiford
                   ` (7 preceding siblings ...)
  2019-08-19 15:23 ` [08/13] Use function_arg_info for TARGET_CALLEE_COPIES Richard Sandiford
@ 2019-08-19 15:24 ` Richard Sandiford
  2019-08-19 22:04   ` Jeff Law
  2019-08-19 15:47 ` [10/13] Add a apply_pass_by_reference_rules helper Richard Sandiford
                   ` (3 subsequent siblings)
  12 siblings, 1 reply; 27+ messages in thread
From: Richard Sandiford @ 2019-08-19 15:24 UTC (permalink / raw)
  To: gcc-patches

Use function_arg_info for TARGET_MUST_PASS_IN_STACK.

The hook is passed the promoted mode instead of the original type mode.

The expr.h reference in the documentation is no longer correct, but
pointing to calls.h or calls.c doesn't help much either.  I just left
this as-is since it's not related to the point of the series.

After previous changes, most places already pass arg.mode and arg.type.
Only i386 and mcore needed to construct a new one out of nothing.
rs6000 needs to construct one slightly earlier than before.


2019-08-19  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	* target.def (must_pass_in_stack): Take a function_arg_info instead
	of a mode and a type.
	* doc/tm.texi: Regenerate.
	* calls.h (must_pass_in_stack_var_size): Take a function_arg_info
	instead of a mode and a type.
	(must_pass_in_stack_var_size_or_pad): Likewise.
	* calls.c (must_pass_in_stack_var_size): Likewise.
	(must_pass_in_stack_var_size_or_pad): Likewise.
	(initialize_argument_information): Update call to
	targetm.calls.must_pass_in_stack.
	(must_pass_va_arg_on_stack): Likewise.
	* function.c (assign_parm_find_entry_rtl): Likewise.
	* targhooks.c (hook_pass_by_reference_must_pass_in_stack): Likewise.
	* config/alpha/alpha.c (alpha_function_arg): Likewise.
	(alpha_function_arg_advance): Likewise.
	* config/cr16/cr16.c (cr16_function_arg): Likewise.
	(cr16_function_arg_advance): Likewise.
	* config/cris/cris.c (cris_pass_by_reference): Likewise.
	(cris_arg_partial_bytes): Likewise.
	* config/iq2000/iq2000.c (iq2000_pass_by_reference): Likewise.
	* config/lm32/lm32.c (lm32_function_arg): Likewise.
	* config/mcore/mcore.c (mcore_num_arg_regs): Likewise.
	(mcore_function_arg, mcore_arg_partial_bytes): Likewise.
	* config/mips/mips.c (mips_pass_by_reference): Likewise.
	* config/mmix/mmix.c (mmix_function_arg_advance): Likewise.
	(mmix_function_arg_1, mmix_pass_by_reference): Likewise.
	* config/sh/sh.c (sh_pass_by_reference): Likewise.
	* config/stormy16/stormy16.c (xstormy16_function_arg): Likewise.
	* config/xtensa/xtensa.c (xtensa_function_arg_advance): Likewise.
	* config/arm/arm.c (arm_must_pass_in_stack): Take a function_arg_info
	instead of a mode and a type.
	* config/fr30/fr30.c (fr30_must_pass_in_stack): Likewise.
	(fr30_num_arg_regs): Likewise.
	(fr30_setup_incoming_varargs): Update calls accordingly.
	(fr30_arg_partial_bytes, fr30_function_arg): Likewise.
	(fr30_function_arg_advance): Likewise.
	* config/frv/frv.c (frv_must_pass_in_stack): Take a function_arg_info
	instead of a mode and a type.
	* config/gcn/gcn.c (num_arg_regs): Likewise.
	(gcn_function_arg, gcn_function_arg_advance): Update calls to
	num_arg_regs and targetm.calls.must_pass_in_stack.
	(gcn_arg_partial_bytes): Likewise.
	* config/i386/i386.c (ix86_must_pass_in_stack): Take a
	function_arg_info instead of a mode and a type.
	(classify_argument): Update call accordingly.
	* config/nds32/nds32.c (nds32_must_pass_in_stack): Take a
	function_arg_info instead of a mode and a type.
	* config/rs6000/rs6000-internal.h (rs6000_must_pass_in_stack):
	Likewise.
	* config/rs6000/rs6000-call.c (rs6000_must_pass_in_stack): Likewise.
	(rs6000_parm_needs_stack): Update call accordingly.
	(setup_incoming_varargs): Likewise.

Index: gcc/target.def
===================================================================
--- gcc/target.def	2019-08-19 15:58:58.017863486 +0100
+++ gcc/target.def	2019-08-19 15:59:04.289818104 +0100
@@ -4630,11 +4630,11 @@ false.",
    Need audit to verify that this is the case.  */
 DEFHOOK
 (must_pass_in_stack,
- "This target hook should return @code{true} if we should not pass @var{type}\n\
+ "This target hook should return @code{true} if we should not pass @var{arg}\n\
 solely in registers.  The file @file{expr.h} defines a\n\
 definition that is usually appropriate, refer to @file{expr.h} for additional\n\
 documentation.",
- bool, (machine_mode mode, const_tree type),
+ bool, (const function_arg_info &arg),
  must_pass_in_stack_var_size_or_pad)
 
 /* Return true if type TYPE, mode MODE, which is passed by reference,
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	2019-08-19 15:58:58.013863514 +0100
+++ gcc/doc/tm.texi	2019-08-19 15:59:04.289818104 +0100
@@ -4012,8 +4012,8 @@ defined, the argument will be computed i
 a register.
 @end deftypefn
 
-@deftypefn {Target Hook} bool TARGET_MUST_PASS_IN_STACK (machine_mode @var{mode}, const_tree @var{type})
-This target hook should return @code{true} if we should not pass @var{type}
+@deftypefn {Target Hook} bool TARGET_MUST_PASS_IN_STACK (const function_arg_info @var{&arg})
+This target hook should return @code{true} if we should not pass @var{arg}
 solely in registers.  The file @file{expr.h} defines a
 definition that is usually appropriate, refer to @file{expr.h} for additional
 documentation.
Index: gcc/calls.h
===================================================================
--- gcc/calls.h	2019-08-19 15:58:57.997863631 +0100
+++ gcc/calls.h	2019-08-19 15:59:04.261818304 +0100
@@ -108,8 +108,8 @@ extern int setjmp_call_p (const_tree);
 extern bool gimple_maybe_alloca_call_p (const gimple *);
 extern bool gimple_alloca_call_p (const gimple *);
 extern bool alloca_call_p (const_tree);
-extern bool must_pass_in_stack_var_size (machine_mode, const_tree);
-extern bool must_pass_in_stack_var_size_or_pad (machine_mode, const_tree);
+extern bool must_pass_in_stack_var_size (const function_arg_info &);
+extern bool must_pass_in_stack_var_size_or_pad (const function_arg_info &);
 extern bool must_pass_va_arg_in_stack (tree);
 extern rtx prepare_call_address (tree, rtx, rtx, rtx *, int, int);
 extern bool shift_return_value (machine_mode, bool, rtx);
Index: gcc/calls.c
===================================================================
--- gcc/calls.c	2019-08-19 15:58:57.993863659 +0100
+++ gcc/calls.c	2019-08-19 15:59:04.261818304 +0100
@@ -2139,7 +2139,7 @@ initialize_argument_information (int num
       if (args[i].reg)
 	args[i].partial = targetm.calls.arg_partial_bytes (args_so_far, arg);
 
-      args[i].pass_on_stack = targetm.calls.must_pass_in_stack (mode, type);
+      args[i].pass_on_stack = targetm.calls.must_pass_in_stack (arg);
 
       /* If FUNCTION_ARG returned a (parallel [(expr_list (nil) ...) ...]),
 	 it means that we are to pass this arg in the register(s) designated
@@ -5839,22 +5839,21 @@ store_one_arg (struct arg_data *arg, rtx
   return sibcall_failure;
 }
 
-/* Nonzero if we do not know how to pass TYPE solely in registers.  */
+/* Nonzero if we do not know how to pass ARG solely in registers.  */
 
 bool
-must_pass_in_stack_var_size (machine_mode mode ATTRIBUTE_UNUSED,
-			     const_tree type)
+must_pass_in_stack_var_size (const function_arg_info &arg)
 {
-  if (!type)
+  if (!arg.type)
     return false;
 
   /* If the type has variable size...  */
-  if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+  if (TREE_CODE (TYPE_SIZE (arg.type)) != INTEGER_CST)
     return true;
 
   /* If the type is marked as addressable (it is required
      to be constructed into the stack)...  */
-  if (TREE_ADDRESSABLE (type))
+  if (TREE_ADDRESSABLE (arg.type))
     return true;
 
   return false;
@@ -5865,28 +5864,28 @@ must_pass_in_stack_var_size (machine_mod
 /* ??? Should be able to merge these two by examining BLOCK_REG_PADDING.  */
 
 bool
-must_pass_in_stack_var_size_or_pad (machine_mode mode, const_tree type)
+must_pass_in_stack_var_size_or_pad (const function_arg_info &arg)
 {
-  if (!type)
+  if (!arg.type)
     return false;
 
   /* If the type has variable size...  */
-  if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+  if (TREE_CODE (TYPE_SIZE (arg.type)) != INTEGER_CST)
     return true;
 
   /* If the type is marked as addressable (it is required
      to be constructed into the stack)...  */
-  if (TREE_ADDRESSABLE (type))
+  if (TREE_ADDRESSABLE (arg.type))
     return true;
 
-  if (TYPE_EMPTY_P (type))
+  if (TYPE_EMPTY_P (arg.type))
     return false;
 
   /* If the padding and mode of the type is such that a copy into
      a register would put it into the wrong part of the register.  */
-  if (mode == BLKmode
-      && int_size_in_bytes (type) % (PARM_BOUNDARY / BITS_PER_UNIT)
-      && (targetm.calls.function_arg_padding (mode, type)
+  if (arg.mode == BLKmode
+      && int_size_in_bytes (arg.type) % (PARM_BOUNDARY / BITS_PER_UNIT)
+      && (targetm.calls.function_arg_padding (arg.mode, arg.type)
 	  == (BYTES_BIG_ENDIAN ? PAD_UPWARD : PAD_DOWNWARD)))
     return true;
 
@@ -5899,7 +5898,8 @@ must_pass_in_stack_var_size_or_pad (mach
 bool
 must_pass_va_arg_in_stack (tree type)
 {
-  return targetm.calls.must_pass_in_stack (TYPE_MODE (type), type);
+  function_arg_info arg (type, /*named=*/false);
+  return targetm.calls.must_pass_in_stack (arg);
 }
 
 /* Tell the garbage collector about GTY markers in this source file.  */
Index: gcc/function.c
===================================================================
--- gcc/function.c	2019-08-19 15:58:58.013863514 +0100
+++ gcc/function.c	2019-08-19 15:59:04.289818104 +0100
@@ -2552,8 +2552,7 @@ assign_parm_find_entry_rtl (struct assig
 
   /* If this parameter was passed both in registers and in the stack, use
      the copy on the stack.  */
-  if (targetm.calls.must_pass_in_stack (data->promoted_mode,
-					data->passed_type))
+  if (targetm.calls.must_pass_in_stack (arg))
     entry_parm = 0;
 
   if (entry_parm)
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c	2019-08-19 15:58:58.017863486 +0100
+++ gcc/targhooks.c	2019-08-19 15:59:04.289818104 +0100
@@ -323,7 +323,7 @@ default_cxx_get_cookie_size (tree type)
 hook_pass_by_reference_must_pass_in_stack (cumulative_args_t,
 					   const function_arg_info &arg)
 {
-  return targetm.calls.must_pass_in_stack (arg.mode, arg.type);
+  return targetm.calls.must_pass_in_stack (arg);
 }
 
 /* Return true if a parameter follows callee copies conventions.  This
Index: gcc/config/alpha/alpha.c
===================================================================
--- gcc/config/alpha/alpha.c	2019-08-19 15:58:50.309919261 +0100
+++ gcc/config/alpha/alpha.c	2019-08-19 15:59:04.265818276 +0100
@@ -5585,7 +5585,7 @@ alpha_function_arg (cumulative_args_t cu
 
       num_args = cum->num_args;
       if (num_args >= 6
-	  || targetm.calls.must_pass_in_stack (arg.mode, arg.type))
+	  || targetm.calls.must_pass_in_stack (arg))
 	return NULL_RTX;
     }
 #elif TARGET_ABI_OSF
@@ -5596,7 +5596,7 @@ alpha_function_arg (cumulative_args_t cu
 
       if (arg.end_marker_p ())
 	basereg = 16;
-      else if (targetm.calls.must_pass_in_stack (arg.mode, arg.type))
+      else if (targetm.calls.must_pass_in_stack (arg))
 	return NULL_RTX;
     }
 #else
@@ -5613,7 +5613,7 @@ alpha_function_arg_advance (cumulative_a
 			    const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
-  bool onstack = targetm.calls.must_pass_in_stack (arg.mode, arg.type);
+  bool onstack = targetm.calls.must_pass_in_stack (arg);
   int increment = onstack ? 6 : ALPHA_ARG_SIZE (arg.mode, arg.type);
 
 #if TARGET_ABI_OSF
Index: gcc/config/cr16/cr16.c
===================================================================
--- gcc/config/cr16/cr16.c	2019-08-19 15:58:50.317919202 +0100
+++ gcc/config/cr16/cr16.c	2019-08-19 15:59:04.273818218 +0100
@@ -606,7 +606,7 @@ cr16_function_arg (cumulative_args_t cum
   if (arg.end_marker_p ())
     return NULL_RTX;
 
-  if (targetm.calls.must_pass_in_stack (arg.mode, arg.type) || (cum->ints < 0))
+  if (targetm.calls.must_pass_in_stack (arg) || (cum->ints < 0))
     return NULL_RTX;
 
   if (arg.mode == BLKmode)
@@ -672,7 +672,7 @@ cr16_function_arg_advance (cumulative_ar
   if (!cum->last_parm_in_reg)
     return;
 
-  if (targetm.calls.must_pass_in_stack (arg.mode, arg.type) || (cum->ints < 0))
+  if (targetm.calls.must_pass_in_stack (arg) || (cum->ints < 0))
     return;
 
   if ((arg.mode == SImode) || (arg.mode == HImode)
Index: gcc/config/cris/cris.c
===================================================================
--- gcc/config/cris/cris.c	2019-08-19 15:58:50.321919175 +0100
+++ gcc/config/cris/cris.c	2019-08-19 15:59:04.273818218 +0100
@@ -4046,7 +4046,7 @@ cris_setup_incoming_varargs (cumulative_
 static bool
 cris_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
 {
-  return (targetm.calls.must_pass_in_stack (arg.mode, arg.type)
+  return (targetm.calls.must_pass_in_stack (arg)
 	  || CRIS_FUNCTION_ARG_SIZE (arg.mode, arg.type) > 8);
 }
 
@@ -4111,7 +4111,7 @@ cris_function_value_regno_p (const unsig
 cris_arg_partial_bytes (cumulative_args_t ca, const function_arg_info &arg)
 {
   if (get_cumulative_args (ca)->regs == CRIS_MAX_ARGS_IN_REGS - 1
-      && !targetm.calls.must_pass_in_stack (arg.mode, arg.type)
+      && !targetm.calls.must_pass_in_stack (arg)
       && CRIS_FUNCTION_ARG_SIZE (arg.mode, arg.type) > 4
       && CRIS_FUNCTION_ARG_SIZE (arg.mode, arg.type) <= 8)
     return UNITS_PER_WORD;
Index: gcc/config/iq2000/iq2000.c
===================================================================
--- gcc/config/iq2000/iq2000.c	2019-08-19 15:58:50.329919117 +0100
+++ gcc/config/iq2000/iq2000.c	2019-08-19 15:59:04.277818191 +0100
@@ -2300,7 +2300,7 @@ iq2000_pass_by_reference (cumulative_arg
   /* We must pass by reference if we would be both passing in registers
      and the stack.  This is because any subsequent partial arg would be
      handled incorrectly in this case.  */
-  if (cum && targetm.calls.must_pass_in_stack (arg.mode, arg.type))
+  if (cum && targetm.calls.must_pass_in_stack (arg))
      {
        /* Don't pass the actual CUM to FUNCTION_ARG, because we would
 	  get double copies of any offsets generated for small structs
Index: gcc/config/lm32/lm32.c
===================================================================
--- gcc/config/lm32/lm32.c	2019-08-19 15:58:50.329919117 +0100
+++ gcc/config/lm32/lm32.c	2019-08-19 15:59:04.277818191 +0100
@@ -629,7 +629,7 @@ lm32_function_arg (cumulative_args_t cum
     /* Compute operand 2 of the call insn.  */
     return GEN_INT (0);
 
-  if (targetm.calls.must_pass_in_stack (arg.mode, arg.type))
+  if (targetm.calls.must_pass_in_stack (arg))
     return NULL_RTX;
 
   if (!arg.named
Index: gcc/config/mcore/mcore.c
===================================================================
--- gcc/config/mcore/mcore.c	2019-08-19 15:58:50.329919117 +0100
+++ gcc/config/mcore/mcore.c	2019-08-19 15:59:04.281818160 +0100
@@ -2713,7 +2713,8 @@ mcore_num_arg_regs (machine_mode mode, c
 {
   int size;
 
-  if (targetm.calls.must_pass_in_stack (mode, type))
+  function_arg_info arg (const_cast<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 cu
   if (!arg.named || arg.end_marker_p ())
     return 0;
 
-  if (targetm.calls.must_pass_in_stack (arg.mode, arg.type))
+  if (targetm.calls.must_pass_in_stack (arg))
     return 0;
 
   arg_reg = ROUND_REG (*get_cumulative_args (cum), arg.mode);
@@ -2848,7 +2849,7 @@ mcore_arg_partial_bytes (cumulative_args
   if (!arg.named)
     return 0;
 
-  if (targetm.calls.must_pass_in_stack (arg.mode, arg.type))
+  if (targetm.calls.must_pass_in_stack (arg))
     return 0;
       
   /* REG is not the *hardware* register number of the register that holds
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	2019-08-19 15:58:58.005863572 +0100
+++ gcc/config/mips/mips.c	2019-08-19 15:59:04.281818160 +0100
@@ -6252,7 +6252,7 @@ mips_pass_by_reference (cumulative_args_
   else
     {
       /* If we have a variable-sized parameter, we have no choice.  */
-      return targetm.calls.must_pass_in_stack (arg.mode, arg.type);
+      return targetm.calls.must_pass_in_stack (arg);
     }
 }
 
Index: gcc/config/mmix/mmix.c
===================================================================
--- gcc/config/mmix/mmix.c	2019-08-19 15:58:58.005863572 +0100
+++ gcc/config/mmix/mmix.c	2019-08-19 15:59:04.281818160 +0100
@@ -621,7 +621,7 @@ mmix_function_arg_advance (cumulative_ar
   CUMULATIVE_ARGS *argsp = get_cumulative_args (argsp_v);
   int arg_size = MMIX_FUNCTION_ARG_SIZE (arg.mode, arg.type);
 
-  argsp->regs = ((targetm.calls.must_pass_in_stack (arg.mode, arg.type)
+  argsp->regs = ((targetm.calls.must_pass_in_stack (arg)
 		  || (arg_size > 8
 		      && !TARGET_LIBFUNC
 		      && !argsp->lib))
@@ -647,7 +647,7 @@ mmix_function_arg_1 (const cumulative_ar
       : NULL_RTX;
 
   return (argsp->regs < MMIX_MAX_ARGS_IN_REGS
-	  && !targetm.calls.must_pass_in_stack (arg.mode, arg.type)
+	  && !targetm.calls.must_pass_in_stack (arg)
 	  && (GET_MODE_BITSIZE (arg.mode) <= 64
 	      || argsp->lib
 	      || TARGET_LIBFUNC))
@@ -686,7 +686,7 @@ mmix_pass_by_reference (cumulative_args_
 
   /* FIXME: Check: I'm not sure the must_pass_in_stack check is
      necessary.  */
-  if (targetm.calls.must_pass_in_stack (arg.mode, arg.type))
+  if (targetm.calls.must_pass_in_stack (arg))
     return true;
 
   if (MMIX_FUNCTION_ARG_SIZE (arg.mode, arg.type) > 8
Index: gcc/config/sh/sh.c
===================================================================
--- gcc/config/sh/sh.c	2019-08-19 15:58:58.013863514 +0100
+++ gcc/config/sh/sh.c	2019-08-19 15:59:04.285818131 +0100
@@ -7901,7 +7901,7 @@ sh_pass_by_reference (cumulative_args_t
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
-  if (targetm.calls.must_pass_in_stack (arg.mode, arg.type))
+  if (targetm.calls.must_pass_in_stack (arg))
     return true;
 
   /* ??? std_gimplify_va_arg_expr passes NULL for cum.  That function
Index: gcc/config/stormy16/stormy16.c
===================================================================
--- gcc/config/stormy16/stormy16.c	2019-08-19 15:58:50.341919030 +0100
+++ gcc/config/stormy16/stormy16.c	2019-08-19 15:59:04.285818131 +0100
@@ -1239,7 +1239,7 @@ xstormy16_function_arg (cumulative_args_
 
   if (arg.end_marker_p ())
     return const0_rtx;
-  if (targetm.calls.must_pass_in_stack (arg.mode, arg.type)
+  if (targetm.calls.must_pass_in_stack (arg)
       || (*cum + XSTORMY16_WORD_SIZE (arg.type, arg.mode)
 	  > NUM_ARGUMENT_REGISTERS))
     return NULL_RTX;
Index: gcc/config/xtensa/xtensa.c
===================================================================
--- gcc/config/xtensa/xtensa.c	2019-08-19 15:58:50.341919030 +0100
+++ gcc/config/xtensa/xtensa.c	2019-08-19 15:59:04.285818131 +0100
@@ -2118,7 +2118,7 @@ xtensa_function_arg_advance (cumulative_
 	   / UNITS_PER_WORD);
 
   if (*arg_words < max
-      && (targetm.calls.must_pass_in_stack (arg.mode, arg.type)
+      && (targetm.calls.must_pass_in_stack (arg)
 	  || *arg_words + words > max))
     *arg_words = max;
 
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c	2019-08-19 15:58:50.317919202 +0100
+++ gcc/config/arm/arm.c	2019-08-19 15:59:04.269818249 +0100
@@ -219,7 +219,7 @@ static bool arm_promote_prototypes (cons
 static bool arm_default_short_enums (void);
 static bool arm_align_anon_bitfield (void);
 static bool arm_return_in_msb (const_tree);
-static bool arm_must_pass_in_stack (machine_mode, const_tree);
+static bool arm_must_pass_in_stack (const function_arg_info &);
 static bool arm_return_in_memory (const_tree, const_tree);
 #if ARM_UNWIND_INFO
 static void arm_unwind_emit (FILE *, rtx_insn *);
@@ -15382,12 +15382,12 @@ arm_reload_out_hi (rtx *operands)
    (padded to the size of a word) should be passed in a register.  */
 
 static bool
-arm_must_pass_in_stack (machine_mode mode, const_tree type)
+arm_must_pass_in_stack (const function_arg_info &arg)
 {
   if (TARGET_AAPCS_BASED)
-    return must_pass_in_stack_var_size (mode, type);
+    return must_pass_in_stack_var_size (arg);
   else
-    return must_pass_in_stack_var_size_or_pad (mode, type);
+    return must_pass_in_stack_var_size_or_pad (arg);
 }
 
 
Index: gcc/config/fr30/fr30.c
===================================================================
--- gcc/config/fr30/fr30.c	2019-08-19 15:58:50.321919175 +0100
+++ gcc/config/fr30/fr30.c	2019-08-19 15:59:04.273818218 +0100
@@ -116,7 +116,7 @@ struct fr30_frame_info
 static void fr30_setup_incoming_varargs (cumulative_args_t,
 					 const function_arg_info &,
 					 int *, int);
-static bool fr30_must_pass_in_stack (machine_mode, const_tree);
+static bool fr30_must_pass_in_stack (const function_arg_info &);
 static int fr30_arg_partial_bytes (cumulative_args_t,
 				   const function_arg_info &);
 static rtx fr30_function_arg (cumulative_args_t, const function_arg_info &);
@@ -129,7 +129,7 @@ static bool fr30_function_value_regno_p
 static bool fr30_can_eliminate (const int, const int);
 static void fr30_asm_trampoline_template (FILE *);
 static void fr30_trampoline_init (rtx, tree, rtx);
-static int fr30_num_arg_regs (machine_mode, const_tree);
+static int fr30_num_arg_regs (const function_arg_info &);
 
 #define FRAME_POINTER_MASK 	(1 << (FRAME_POINTER_REGNUM))
 #define RETURN_POINTER_MASK 	(1 << (RETURN_POINTER_REGNUM))
@@ -480,7 +480,7 @@ fr30_setup_incoming_varargs (cumulative_
     /* If TARGET_STRICT_ARGUMENT_NAMING returns true, then the last named
        arg must not be treated as an anonymous arg.  */
     /* ??? This is a pointer increment, which makes no sense.  */
-    arg_regs_used_so_far += fr30_num_arg_regs (arg.mode, arg.type);
+    arg_regs_used_so_far += fr30_num_arg_regs (arg);
 
   size = FR30_NUM_ARG_REGS - (* arg_regs_used_so_far);
 
@@ -743,30 +743,20 @@ fr30_function_value_regno_p (const unsig
    in registers.  */
 
 static bool
-fr30_must_pass_in_stack (machine_mode mode, const_tree type)
+fr30_must_pass_in_stack (const function_arg_info &arg)
 {
-  if (mode == BLKmode)
-    return true;
-  if (type == NULL)
-    return false;
-  return AGGREGATE_TYPE_P (type);
+  return arg.mode == BLKmode || arg.aggregate_type_p ();
 }
 
-/* Compute the number of word sized registers needed to hold a
-   function argument of mode INT_MODE and tree type TYPE.  */
+/* Compute the number of word sized registers needed to hold function
+   argument ARG.  */
 static int
-fr30_num_arg_regs (machine_mode mode, const_tree type)
+fr30_num_arg_regs (const function_arg_info &arg)
 {
-  int size;
-
-  if (targetm.calls.must_pass_in_stack (mode, type))
+  if (targetm.calls.must_pass_in_stack (arg))
     return 0;
 
-  if (type && mode == BLKmode)
-    size = int_size_in_bytes (type);
-  else
-    size = GET_MODE_SIZE (mode);
-
+  int size = arg.promoted_size_in_bytes ();
   return (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
 }
 
@@ -792,7 +782,7 @@ fr30_arg_partial_bytes (cumulative_args_
      are needed because the parameter must be passed on the stack)
      then return zero, as this parameter does not require partial
      register, partial stack stack space.  */
-  if (*cum + fr30_num_arg_regs (arg.mode, arg.type) <= FR30_NUM_ARG_REGS)
+  if (*cum + fr30_num_arg_regs (arg) <= FR30_NUM_ARG_REGS)
     return 0;
   
   return (FR30_NUM_ARG_REGS - *cum) * UNITS_PER_WORD;
@@ -804,7 +794,7 @@ fr30_function_arg (cumulative_args_t cum
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
   if (!arg.named
-      || fr30_must_pass_in_stack (arg.mode, arg.type)
+      || fr30_must_pass_in_stack (arg)
       || *cum >= FR30_NUM_ARG_REGS)
     return NULL_RTX;
   else
@@ -817,7 +807,7 @@ fr30_function_arg_advance (cumulative_ar
 			   const function_arg_info &arg)
 {
   if (arg.named)
-    *get_cumulative_args (cum) += fr30_num_arg_regs (arg.mode, arg.type);
+    *get_cumulative_args (cum) += fr30_num_arg_regs (arg);
 }
 
 /*}}}*/
Index: gcc/config/frv/frv.c
===================================================================
--- gcc/config/frv/frv.c	2019-08-19 15:58:50.321919175 +0100
+++ gcc/config/frv/frv.c	2019-08-19 15:59:04.273818218 +0100
@@ -379,7 +379,7 @@ static void frv_output_const_unspec		(FI
 						 const struct frv_unspec *);
 static bool frv_function_ok_for_sibcall		(tree, tree);
 static rtx frv_struct_value_rtx			(tree, int);
-static bool frv_must_pass_in_stack (machine_mode mode, const_tree type);
+static bool frv_must_pass_in_stack (const function_arg_info &);
 static int frv_arg_partial_bytes (cumulative_args_t,
 				  const function_arg_info &);
 static rtx frv_function_arg (cumulative_args_t, const function_arg_info &);
@@ -3077,13 +3077,9 @@ frv_init_cumulative_args (CUMULATIVE_ARG
    in registers.  */
 
 static bool
-frv_must_pass_in_stack (machine_mode mode, const_tree type)
+frv_must_pass_in_stack (const function_arg_info &arg)
 {
-  if (mode == BLKmode)
-    return true;
-  if (type == NULL)
-    return false;
-  return AGGREGATE_TYPE_P (type);
+  return arg.mode == BLKmode || arg.aggregate_type_p ();
 }
 
 /* If defined, a C expression that gives the alignment boundary, in bits, of an
Index: gcc/config/gcn/gcn.c
===================================================================
--- gcc/config/gcn/gcn.c	2019-08-19 15:58:50.321919175 +0100
+++ gcc/config/gcn/gcn.c	2019-08-19 15:59:04.273818218 +0100
@@ -2200,22 +2200,16 @@ gcn_function_value_regno_p (const unsign
   return n == RETURN_VALUE_REG;
 }
 
-/* Calculate the number of registers required to hold a function argument
-   of MODE and TYPE.  */
+/* Calculate the number of registers required to hold function argument
+   ARG.  */
 
 static int
-num_arg_regs (machine_mode mode, const_tree type)
+num_arg_regs (const function_arg_info &arg)
 {
-  int size;
-
-  if (targetm.calls.must_pass_in_stack (mode, type))
+  if (targetm.calls.must_pass_in_stack (arg))
     return 0;
 
-  if (type && mode == BLKmode)
-    size = int_size_in_bytes (type);
-  else
-    size = GET_MODE_SIZE (mode);
-
+  int size = arg.promoted_size_in_bytes ();
   return (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
 }
 
@@ -2263,11 +2257,11 @@ gcn_function_arg (cumulative_args_t cum_
       if (!arg.named || arg.end_marker_p ())
 	return 0;
 
-      if (targetm.calls.must_pass_in_stack (arg.mode, arg.type))
+      if (targetm.calls.must_pass_in_stack (arg))
 	return 0;
 
       int reg_num = FIRST_PARM_REG + cum->num;
-      int num_regs = num_arg_regs (arg.mode, arg.type);
+      int num_regs = num_arg_regs (arg);
       if (num_regs > 0)
 	while (reg_num % num_regs != 0)
 	  reg_num++;
@@ -2323,7 +2317,7 @@ gcn_function_arg_advance (cumulative_arg
       if (!arg.named)
 	return;
 
-      int num_regs = num_arg_regs (arg.mode, arg.type);
+      int num_regs = num_arg_regs (arg);
       if (num_regs > 0)
 	while ((FIRST_PARM_REG + cum->num) % num_regs != 0)
 	  cum->num++;
@@ -2355,14 +2349,14 @@ gcn_arg_partial_bytes (cumulative_args_t
   if (!arg.named)
     return 0;
 
-  if (targetm.calls.must_pass_in_stack (arg.mode, arg.type))
+  if (targetm.calls.must_pass_in_stack (arg))
     return 0;
 
   if (cum->num >= NUM_PARM_REGS)
     return 0;
 
   /* If the argument fits entirely in registers, return 0.  */
-  if (cum->num + num_arg_regs (arg.mode, arg.type) <= NUM_PARM_REGS)
+  if (cum->num + num_arg_regs (arg) <= NUM_PARM_REGS)
     return 0;
 
   return (NUM_PARM_REGS - cum->num) * UNITS_PER_WORD;
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	2019-08-19 15:58:50.325919144 +0100
+++ gcc/config/i386/i386.c	2019-08-19 15:59:04.277818191 +0100
@@ -1455,19 +1455,19 @@ ix86_function_arg_regno_p (int regno)
   return false;
 }
 
-/* Return if we do not know how to pass TYPE solely in registers.  */
+/* Return if we do not know how to pass ARG solely in registers.  */
 
 static bool
-ix86_must_pass_in_stack (machine_mode mode, const_tree type)
+ix86_must_pass_in_stack (const function_arg_info &arg)
 {
-  if (must_pass_in_stack_var_size_or_pad (mode, type))
+  if (must_pass_in_stack_var_size_or_pad (arg))
     return true;
 
   /* For 32-bit, we want TImode aggregates to go on the stack.  But watch out!
      The layout_type routine is crafty and tries to trick us into passing
      currently unsupported vector types on the stack by using TImode.  */
-  return (!TARGET_64BIT && mode == TImode
-	  && type && TREE_CODE (type) != VECTOR_TYPE);
+  return (!TARGET_64BIT && arg.mode == TImode
+	  && arg.type && TREE_CODE (arg.type) != VECTOR_TYPE);
 }
 
 /* It returns the size, in bytes, of the area reserved for arguments passed
@@ -2062,9 +2062,13 @@ classify_argument (machine_mode mode, co
   if (bytes < 0)
     return 0;
 
-  if (mode != VOIDmode
-      && targetm.calls.must_pass_in_stack (mode, type))
-    return 0;
+  if (mode != VOIDmode)
+    {
+      /* The value of "named" doesn't matter.  */
+      function_arg_info arg (const_cast<tree> (type), mode, /*named=*/true);
+      if (targetm.calls.must_pass_in_stack (arg))
+	return 0;
+    }
 
   if (type && AGGREGATE_TYPE_P (type))
     {
Index: gcc/config/nds32/nds32.c
===================================================================
--- gcc/config/nds32/nds32.c	2019-08-19 15:58:50.333919085 +0100
+++ gcc/config/nds32/nds32.c	2019-08-19 15:59:04.285818131 +0100
@@ -1951,16 +1951,16 @@ nds32_function_arg (cumulative_args_t ca
 }
 
 static bool
-nds32_must_pass_in_stack (machine_mode mode, const_tree type)
+nds32_must_pass_in_stack (const function_arg_info &arg)
 {
   /* Return true if a type must be passed in memory.
      If it is NOT using hard float abi, small aggregates can be
      passed in a register even we are calling a variadic function.
      So there is no need to take padding into consideration.  */
   if (TARGET_HARD_FLOAT)
-    return must_pass_in_stack_var_size_or_pad (mode, type);
+    return must_pass_in_stack_var_size_or_pad (arg);
   else
-    return must_pass_in_stack_var_size (mode, type);
+    return must_pass_in_stack_var_size (arg);
 }
 
 static int
Index: gcc/config/rs6000/rs6000-internal.h
===================================================================
--- gcc/config/rs6000/rs6000-internal.h	2019-08-19 15:58:50.337919057 +0100
+++ gcc/config/rs6000/rs6000-internal.h	2019-08-19 15:59:04.285818131 +0100
@@ -156,7 +156,7 @@ extern void setup_incoming_varargs (cumu
 				    const function_arg_info &, int *, int);
 extern unsigned int rs6000_function_arg_boundary (machine_mode mode,
 						  const_tree type);
-extern bool rs6000_must_pass_in_stack (machine_mode mode, const_tree type);
+extern bool rs6000_must_pass_in_stack (const function_arg_info &);
 extern int rs6000_arg_partial_bytes (cumulative_args_t,
 				     const function_arg_info &);
 extern void rs6000_function_arg_advance (cumulative_args_t,
Index: gcc/config/rs6000/rs6000-call.c
===================================================================
--- gcc/config/rs6000/rs6000-call.c	2019-08-19 15:58:50.337919057 +0100
+++ gcc/config/rs6000/rs6000-call.c	2019-08-19 15:59:04.285818131 +0100
@@ -816,12 +816,12 @@ rs6000_promote_function_mode (const_tree
 /* Return true if TYPE must be passed on the stack and not in registers.  */
 
 bool
-rs6000_must_pass_in_stack (machine_mode mode, const_tree type)
+rs6000_must_pass_in_stack (const function_arg_info &arg)
 {
   if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2 || TARGET_64BIT)
-    return must_pass_in_stack_var_size (mode, type);
+    return must_pass_in_stack_var_size (arg);
   else
-    return must_pass_in_stack_var_size_or_pad (mode, type);
+    return must_pass_in_stack_var_size_or_pad (arg);
 }
 
 static inline bool
@@ -2202,11 +2202,11 @@ rs6000_parm_needs_stack (cumulative_args
   mode = promote_mode (type, TYPE_MODE (type), &unsignedp);
 
   /* If we must pass in stack, we need a stack.  */
-  if (rs6000_must_pass_in_stack (mode, type))
+  function_arg_info arg (type, mode, /*named=*/true);
+  if (rs6000_must_pass_in_stack (arg))
     return true;
 
   /* If there is no incoming register, we need a stack.  */
-  function_arg_info arg (type, mode, /*named=*/true);
   entry_parm = rs6000_function_arg (args_so_far, arg);
   if (entry_parm == NULL)
     return true;
@@ -2457,7 +2457,7 @@ setup_incoming_varargs (cumulative_args_
       first_reg_offset = next_cum.words;
       save_area = crtl->args.internal_arg_pointer;
 
-      if (targetm.calls.must_pass_in_stack (arg.mode, arg.type))
+      if (targetm.calls.must_pass_in_stack (arg))
 	first_reg_offset += rs6000_arg_size (TYPE_MODE (arg.type), arg.type);
     }
 

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [10/13] Add a apply_pass_by_reference_rules helper
  2019-08-19 15:15 [00/13] Pass an argument descriptor to target hooks Richard Sandiford
                   ` (8 preceding siblings ...)
  2019-08-19 15:24 ` [09/13] Use function_arg_info for TARGET_MUST_PASS_IN_STACK Richard Sandiford
@ 2019-08-19 15:47 ` Richard Sandiford
  2019-08-19 22:19   ` Jeff Law
  2019-08-19 15:51 ` [11/13] Make function.c use function_arg_info internally Richard Sandiford
                   ` (2 subsequent siblings)
  12 siblings, 1 reply; 27+ messages in thread
From: Richard Sandiford @ 2019-08-19 15:47 UTC (permalink / raw)
  To: gcc-patches

This patch adds a helper routine that applies pass-by-reference
semantics to an existing function_arg_info.

The c6x part means that c6x_function_arg and c6x_function_arg_advance
see the same "named" value as pass_by_reference did, rather than
pass_by_reference seeing "true" and the others seeing "false".
This doesn't matter because the c6x port doesn't care about namedness.

The rs6000.c patch removes an assignment to "type", but the only
later code to use it was the patched promote_mode line.

(The reason for patching these places despite the above is that
often target code gets used as a basis for new targets or changes
to existing ones.)


2019-08-19  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	* 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.

Index: gcc/calls.h
===================================================================
--- gcc/calls.h	2019-08-19 15:59:04.261818304 +0100
+++ gcc/calls.h	2019-08-19 15:59:09.801778220 +0100
@@ -118,6 +118,8 @@ extern void fixup_tail_calls (void);
 
 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]);
Index: gcc/calls.c
===================================================================
--- gcc/calls.c	2019-08-19 15:59:04.261818304 +0100
+++ gcc/calls.c	2019-08-19 15:59:09.801778220 +0100
@@ -935,6 +935,22 @@ pass_va_arg_by_reference (tree type)
   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.  */
 
Index: gcc/config/c6x/c6x.c
===================================================================
--- gcc/config/c6x/c6x.c	2019-08-19 15:58:58.001863604 +0100
+++ gcc/config/c6x/c6x.c	2019-08-19 15:59:09.805778189 +0100
@@ -1088,8 +1088,6 @@ c6x_call_saved_register_used (tree call_
   cumulative_args_t cum;
   HARD_REG_SET call_saved_regset;
   tree parameter;
-  machine_mode mode;
-  tree type;
   rtx parm_rtx;
   int i;
 
@@ -1107,19 +1105,9 @@ c6x_call_saved_register_used (tree call_
       if (TREE_CODE (parameter) == ERROR_MARK)
 	return true;
 
-      type = TREE_TYPE (parameter);
-      gcc_assert (type);
+      function_arg_info arg (TREE_TYPE (parameter), /*named=*/true);
+      apply_pass_by_reference_rules (&cum_v, arg);
 
-      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 (type, mode, /*named=*/false);
        parm_rtx = c6x_function_arg (cum, arg);
 
        c6x_function_arg_advance (cum, arg);
Index: gcc/config/rs6000/rs6000-call.c
===================================================================
--- gcc/config/rs6000/rs6000-call.c	2019-08-19 15:59:04.285818131 +0100
+++ gcc/config/rs6000/rs6000-call.c	2019-08-19 15:59:09.805778189 +0100
@@ -2170,7 +2170,6 @@ rs6000_pass_by_reference (cumulative_arg
 static bool
 rs6000_parm_needs_stack (cumulative_args_t args_so_far, tree type)
 {
-  machine_mode mode;
   int unsignedp;
   rtx entry_parm;
 
@@ -2193,16 +2192,14 @@ rs6000_parm_needs_stack (cumulative_args
     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;
 
Index: gcc/config/s390/s390.c
===================================================================
--- gcc/config/s390/s390.c	2019-08-19 15:58:50.337919057 +0100
+++ gcc/config/s390/s390.c	2019-08-19 15:59:09.809778162 +0100
@@ -13309,8 +13309,6 @@ s390_call_saved_register_used (tree call
   CUMULATIVE_ARGS cum_v;
   cumulative_args_t cum;
   tree parameter;
-  machine_mode mode;
-  tree type;
   rtx parm_rtx;
   int reg, i;
 
@@ -13327,22 +13325,12 @@ s390_call_saved_register_used (tree call
       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);
Index: gcc/function.c
===================================================================
--- gcc/function.c	2019-08-19 15:59:04.289818104 +0100
+++ gcc/function.c	2019-08-19 15:59:09.809778162 +0100
@@ -2456,11 +2456,11 @@ assign_parm_find_data_types (struct assi
   /* 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;
       }
   }
 
Index: gcc/var-tracking.c
===================================================================
--- gcc/var-tracking.c	2019-08-19 15:58:50.345918999 +0100
+++ gcc/var-tracking.c	2019-08-19 15:59:09.813778131 +0100
@@ -6426,28 +6426,24 @@ prepare_call_arguments (basic_block bb,
 	  }
 	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))

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [11/13] Make function.c use function_arg_info internally
  2019-08-19 15:15 [00/13] Pass an argument descriptor to target hooks Richard Sandiford
                   ` (9 preceding siblings ...)
  2019-08-19 15:47 ` [10/13] Add a apply_pass_by_reference_rules helper Richard Sandiford
@ 2019-08-19 15:51 ` Richard Sandiford
  2019-08-19 22:47   ` Jeff Law
  2019-08-19 15:52 ` [12/13] Make calls.c " Richard Sandiford
  2019-08-19 15:52 ` [13/13] Add a pass_by_reference flag to function_arg_info Richard Sandiford
  12 siblings, 1 reply; 27+ messages in thread
From: Richard Sandiford @ 2019-08-19 15:51 UTC (permalink / raw)
  To: gcc-patches

This patch adds a function_arg_info field to assign_parm_data_one,
so that:

  - passed_type -> arg.type
  - promoted_mode -> arg.mode
  - named_arg -> arg.named

We can then pass this function_arg_info directly to the converted
hooks.

Between the initialisation of the assign_parm_data_one and the
application of promotion rules (which is a state internal to
assign_parm_find_data_types), arg.mode is equivalent to passed_mode
(i.e. to TYPE_MODE).


2019-08-19  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	* function.c (assign_parm_data_one): Replace passed_type,
	promoted_mode and named_arg with a function_arg_info field.
	(assign_parm_find_data_types): Remove local variables and
	assign directly to "data".  Make data->passed_mode shadow
	data->arg.mode until promotion, then assign the promoted
	mode to data->arg.mode.
	(assign_parms_setup_varargs, assign_parm_find_entry_rtl)
	(assign_parm_find_stack_rtl, assign_parm_adjust_entry_rtl)
	(assign_parm_remove_parallels, assign_parm_setup_block_p)
	(assign_parm_setup_block, assign_parm_setup_reg)
	(assign_parm_setup_stack, assign_parms, gimplify_parameters): Use
	arg.mode instead of promoted_mode, arg.type instead of passed_type
	and arg.named instead of named_arg.  Use data->arg for
	function_arg_info structures that had the field values passed_type,
	promoted_mode and named_arg.  Base other function_arg_infos on
	data->arg, changing the necessary properties.

Index: gcc/function.c
===================================================================
--- gcc/function.c	2019-08-19 15:59:09.809778162 +0100
+++ gcc/function.c	2019-08-19 15:59:14.297745685 +0100
@@ -2264,15 +2264,13 @@ struct assign_parm_data_all
 struct assign_parm_data_one
 {
   tree nominal_type;
-  tree passed_type;
+  function_arg_info arg;
   rtx entry_parm;
   rtx stack_parm;
   machine_mode nominal_mode;
   machine_mode passed_mode;
-  machine_mode promoted_mode;
   struct locate_and_pad_arg_data locate;
   int partial;
-  BOOL_BITFIELD named_arg : 1;
   BOOL_BITFIELD passed_pointer : 1;
 };
 
@@ -2407,24 +2405,22 @@ assign_parms_augmented_arg_list (struct
 assign_parm_find_data_types (struct assign_parm_data_all *all, tree parm,
 			     struct assign_parm_data_one *data)
 {
-  tree nominal_type, passed_type;
-  machine_mode nominal_mode, passed_mode, promoted_mode;
   int unsignedp;
 
-  memset (data, 0, sizeof (*data));
+  *data = assign_parm_data_one ();
 
   /* NAMED_ARG is a misnomer.  We really mean 'non-variadic'. */
   if (!cfun->stdarg)
-    data->named_arg = 1;  /* No variadic parms.  */
+    data->arg.named = 1;  /* No variadic parms.  */
   else if (DECL_CHAIN (parm))
-    data->named_arg = 1;  /* Not the last non-variadic parm. */
+    data->arg.named = 1;  /* Not the last non-variadic parm. */
   else if (targetm.calls.strict_argument_naming (all->args_so_far))
-    data->named_arg = 1;  /* Only variadic ones are unnamed.  */
+    data->arg.named = 1;  /* Only variadic ones are unnamed.  */
   else
-    data->named_arg = 0;  /* Treat as variadic.  */
+    data->arg.named = 0;  /* Treat as variadic.  */
 
-  nominal_type = TREE_TYPE (parm);
-  passed_type = DECL_ARG_TYPE (parm);
+  data->nominal_type = TREE_TYPE (parm);
+  data->arg.type = DECL_ARG_TYPE (parm);
 
   /* Look out for errors propagating this far.  Also, if the parameter's
      type is void then its value doesn't matter.  */
@@ -2432,49 +2428,40 @@ assign_parm_find_data_types (struct assi
       /* This can happen after weird syntax errors
 	 or if an enum type is defined among the parms.  */
       || TREE_CODE (parm) != PARM_DECL
-      || passed_type == NULL
-      || VOID_TYPE_P (nominal_type))
+      || data->arg.type == NULL
+      || VOID_TYPE_P (data->nominal_type))
     {
-      nominal_type = passed_type = void_type_node;
-      nominal_mode = passed_mode = promoted_mode = VOIDmode;
-      goto egress;
+      data->nominal_type = data->arg.type = void_type_node;
+      data->nominal_mode = data->passed_mode = data->arg.mode = VOIDmode;
+      return;
     }
 
   /* Find mode of arg as it is passed, and mode of arg as it should be
      during execution of this function.  */
-  passed_mode = TYPE_MODE (passed_type);
-  nominal_mode = TYPE_MODE (nominal_type);
+  data->passed_mode = data->arg.mode = TYPE_MODE (data->arg.type);
+  data->nominal_mode = TYPE_MODE (data->nominal_type);
 
   /* If the parm is to be passed as a transparent union or record, use the
      type of the first field for the tests below.  We have already verified
      that the modes are the same.  */
-  if ((TREE_CODE (passed_type) == UNION_TYPE
-       || TREE_CODE (passed_type) == RECORD_TYPE)
-      && TYPE_TRANSPARENT_AGGR (passed_type))
-    passed_type = TREE_TYPE (first_field (passed_type));
+  if ((TREE_CODE (data->arg.type) == UNION_TYPE
+       || TREE_CODE (data->arg.type) == RECORD_TYPE)
+      && TYPE_TRANSPARENT_AGGR (data->arg.type))
+    data->arg.type = TREE_TYPE (first_field (data->arg.type));
 
   /* See if this arg was passed by invisible reference.  */
-  {
-    function_arg_info arg (passed_type, passed_mode, data->named_arg);
-    if (apply_pass_by_reference_rules (&all->args_so_far_v, arg))
-      {
-	passed_type = nominal_type = arg.type;
-	data->passed_pointer = true;
-	passed_mode = nominal_mode = arg.mode;
-      }
-  }
+  if (apply_pass_by_reference_rules (&all->args_so_far_v, data->arg))
+    {
+      data->nominal_type = data->arg.type;
+      data->passed_pointer = true;
+      data->passed_mode = data->nominal_mode = data->arg.mode;
+    }
 
   /* Find mode as it is passed by the ABI.  */
-  unsignedp = TYPE_UNSIGNED (passed_type);
-  promoted_mode = promote_function_mode (passed_type, passed_mode, &unsignedp,
-				         TREE_TYPE (current_function_decl), 0);
-
- egress:
-  data->nominal_type = nominal_type;
-  data->passed_type = passed_type;
-  data->nominal_mode = nominal_mode;
-  data->passed_mode = passed_mode;
-  data->promoted_mode = promoted_mode;
+  unsignedp = TYPE_UNSIGNED (data->arg.type);
+  data->arg.mode
+    = promote_function_mode (data->arg.type, data->arg.mode, &unsignedp,
+			     TREE_TYPE (current_function_decl), 0);
 }
 
 /* A subroutine of assign_parms.  Invoke setup_incoming_varargs.  */
@@ -2485,8 +2472,8 @@ assign_parms_setup_varargs (struct assig
 {
   int varargs_pretend_bytes = 0;
 
-  function_arg_info last_named_arg (data->passed_type, data->promoted_mode,
-				    /*named=*/true);
+  function_arg_info last_named_arg = data->arg;
+  last_named_arg.named = true;
   targetm.calls.setup_incoming_varargs (all->args_so_far, last_named_arg,
 					&varargs_pretend_bytes, no_rtl);
 
@@ -2508,20 +2495,19 @@ assign_parm_find_entry_rtl (struct assig
   rtx entry_parm;
   bool in_regs;
 
-  if (data->promoted_mode == VOIDmode)
+  if (data->arg.mode == VOIDmode)
     {
       data->entry_parm = data->stack_parm = const0_rtx;
       return;
     }
 
   targetm.calls.warn_parameter_passing_abi (all->args_so_far,
-					    data->passed_type);
+					    data->arg.type);
 
-  function_arg_info arg (data->passed_type, data->promoted_mode,
-			 data->named_arg);
-  entry_parm = targetm.calls.function_incoming_arg (all->args_so_far, arg);
+  entry_parm = targetm.calls.function_incoming_arg (all->args_so_far,
+						    data->arg);
   if (entry_parm == 0)
-    data->promoted_mode = data->passed_mode;
+    data->arg.mode = data->passed_mode;
 
   /* Determine parm's home in the stack, in case it arrives in the stack
      or we should pretend it did.  Compute the stack position and rtx where
@@ -2537,13 +2523,13 @@ assign_parm_find_entry_rtl (struct assig
 #ifdef STACK_PARMS_IN_REG_PARM_AREA
   in_regs = true;
 #endif
-  if (!in_regs && !data->named_arg)
+  if (!in_regs && !data->arg.named)
     {
       if (targetm.calls.pretend_outgoing_varargs_named (all->args_so_far))
 	{
 	  rtx tem;
-	  function_arg_info named_arg (data->passed_type, data->promoted_mode,
-				       /*named=*/true);
+	  function_arg_info named_arg = data->arg;
+	  named_arg.named = true;
 	  tem = targetm.calls.function_incoming_arg (all->args_so_far,
 						     named_arg);
 	  in_regs = tem != NULL;
@@ -2552,16 +2538,14 @@ assign_parm_find_entry_rtl (struct assig
 
   /* If this parameter was passed both in registers and in the stack, use
      the copy on the stack.  */
-  if (targetm.calls.must_pass_in_stack (arg))
+  if (targetm.calls.must_pass_in_stack (data->arg))
     entry_parm = 0;
 
   if (entry_parm)
     {
       int partial;
 
-      function_arg_info arg (data->passed_type, data->promoted_mode,
-			     data->named_arg);
-      partial = targetm.calls.arg_partial_bytes (all->args_so_far, arg);
+      partial = targetm.calls.arg_partial_bytes (all->args_so_far, data->arg);
       data->partial = partial;
 
       /* The caller might already have allocated stack space for the
@@ -2596,7 +2580,7 @@ assign_parm_find_entry_rtl (struct assig
 	}
     }
 
-  locate_and_pad_parm (data->promoted_mode, data->passed_type, in_regs,
+  locate_and_pad_parm (data->arg.mode, data->arg.type, in_regs,
 		       all->reg_parm_stack_space,
 		       entry_parm ? data->partial : 0, current_function_decl,
 		       &all->stack_args_size, &data->locate);
@@ -2667,21 +2651,21 @@ assign_parm_find_stack_rtl (tree parm, s
   stack_parm = crtl->args.internal_arg_pointer;
   if (offset_rtx != const0_rtx)
     stack_parm = gen_rtx_PLUS (Pmode, stack_parm, offset_rtx);
-  stack_parm = gen_rtx_MEM (data->promoted_mode, stack_parm);
+  stack_parm = gen_rtx_MEM (data->arg.mode, stack_parm);
 
   if (!data->passed_pointer)
     {
       set_mem_attributes (stack_parm, parm, 1);
       /* set_mem_attributes could set MEM_SIZE to the passed mode's size,
 	 while promoted mode's size is needed.  */
-      if (data->promoted_mode != BLKmode
-	  && data->promoted_mode != DECL_MODE (parm))
+      if (data->arg.mode != BLKmode
+	  && data->arg.mode != DECL_MODE (parm))
 	{
-	  set_mem_size (stack_parm, GET_MODE_SIZE (data->promoted_mode));
+	  set_mem_size (stack_parm, GET_MODE_SIZE (data->arg.mode));
 	  if (MEM_EXPR (stack_parm) && MEM_OFFSET_KNOWN_P (stack_parm))
 	    {
 	      poly_int64 offset = subreg_lowpart_offset (DECL_MODE (parm),
-							 data->promoted_mode);
+							 data->arg.mode);
 	      if (maybe_ne (offset, 0))
 		set_mem_offset (stack_parm, MEM_OFFSET (stack_parm) - offset);
 	    }
@@ -2733,8 +2717,7 @@ assign_parm_adjust_entry_rtl (struct ass
 	 locations.  The Irix 6 ABI has examples of this.  */
       if (GET_CODE (entry_parm) == PARALLEL)
 	emit_group_store (validize_mem (copy_rtx (stack_parm)), entry_parm,
-			  data->passed_type,
-			  int_size_in_bytes (data->passed_type));
+			  data->arg.type, int_size_in_bytes (data->arg.type));
       else
 	{
 	  gcc_assert (data->partial % UNITS_PER_WORD == 0);
@@ -2790,7 +2773,7 @@ assign_parm_remove_parallels (struct ass
   if (GET_CODE (entry_parm) == PARALLEL && GET_MODE (entry_parm) != BLKmode)
     {
       rtx parmreg = gen_reg_rtx (GET_MODE (entry_parm));
-      emit_group_store (parmreg, entry_parm, data->passed_type,
+      emit_group_store (parmreg, entry_parm, data->arg.type,
 			GET_MODE_SIZE (GET_MODE (entry_parm)));
       entry_parm = parmreg;
     }
@@ -2851,8 +2834,8 @@ assign_parm_setup_block_p (struct assign
   /* Only assign_parm_setup_block knows how to deal with register arguments
      that are padded at the least significant end.  */
   if (REG_P (data->entry_parm)
-      && known_lt (GET_MODE_SIZE (data->promoted_mode), UNITS_PER_WORD)
-      && (BLOCK_REG_PADDING (data->passed_mode, data->passed_type, 1)
+      && known_lt (GET_MODE_SIZE (data->arg.mode), UNITS_PER_WORD)
+      && (BLOCK_REG_PADDING (data->passed_mode, data->arg.type, 1)
 	  == (BYTES_BIG_ENDIAN ? PAD_UPWARD : PAD_DOWNWARD)))
     return true;
 #endif
@@ -2907,7 +2890,7 @@ assign_parm_setup_block (struct assign_p
       data->stack_parm = NULL;
     }
 
-  size = int_size_in_bytes (data->passed_type);
+  size = int_size_in_bytes (data->arg.type);
   size_stored = CEIL_ROUND (size, UNITS_PER_WORD);
   if (stack_parm == 0)
     {
@@ -2962,12 +2945,12 @@ assign_parm_setup_block (struct assign_p
 
       /* Handle values in multiple non-contiguous locations.  */
       if (GET_CODE (entry_parm) == PARALLEL && !MEM_P (mem))
-	emit_group_store (mem, entry_parm, data->passed_type, size);
+	emit_group_store (mem, entry_parm, data->arg.type, size);
       else if (GET_CODE (entry_parm) == PARALLEL)
 	{
 	  push_to_sequence2 (all->first_conversion_insn,
 			     all->last_conversion_insn);
-	  emit_group_store (mem, entry_parm, data->passed_type, size);
+	  emit_group_store (mem, entry_parm, data->arg.type, size);
 	  all->first_conversion_insn = get_insns ();
 	  all->last_conversion_insn = get_last_insn ();
 	  end_sequence ();
@@ -2987,7 +2970,7 @@ assign_parm_setup_block (struct assign_p
 	  if (mode != BLKmode
 #ifdef BLOCK_REG_PADDING
 	      && (size == UNITS_PER_WORD
-		  || (BLOCK_REG_PADDING (mode, data->passed_type, 1)
+		  || (BLOCK_REG_PADDING (mode, data->arg.type, 1)
 		      != (BYTES_BIG_ENDIAN ? PAD_UPWARD : PAD_DOWNWARD)))
 #endif
 	      )
@@ -3028,7 +3011,7 @@ assign_parm_setup_block (struct assign_p
 		 additional changes to work correctly.  */
 	      gcc_checking_assert (BYTES_BIG_ENDIAN
 				   && (BLOCK_REG_PADDING (mode,
-							  data->passed_type, 1)
+							  data->arg.type, 1)
 				       == PAD_UPWARD));
 
 	      int by = (UNITS_PER_WORD - size) * BITS_PER_UNIT;
@@ -3049,7 +3032,7 @@ assign_parm_setup_block (struct assign_p
 	     handle all cases (e.g. SIZE == 3).  */
 	  else if (size != UNITS_PER_WORD
 #ifdef BLOCK_REG_PADDING
-		   && (BLOCK_REG_PADDING (mode, data->passed_type, 1)
+		   && (BLOCK_REG_PADDING (mode, data->arg.type, 1)
 		       == PAD_DOWNWARD)
 #else
 		   && BYTES_BIG_ENDIAN
@@ -3073,7 +3056,7 @@ assign_parm_setup_block (struct assign_p
 	  gcc_checking_assert (size > UNITS_PER_WORD);
 #ifdef BLOCK_REG_PADDING
 	  gcc_checking_assert (BLOCK_REG_PADDING (GET_MODE (mem),
-						  data->passed_type, 0)
+						  data->arg.type, 0)
 			       == PAD_UPWARD);
 #endif
 	  emit_move_insn (mem, entry_parm);
@@ -3144,7 +3127,7 @@ assign_parm_setup_reg (struct assign_par
      set rtl appropriately.  */
   if (data->passed_pointer)
     {
-      rtl = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (data->passed_type)), parmreg);
+      rtl = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (data->arg.type)), parmreg);
       set_mem_attributes (rtl, parm, 1);
     }
   else
@@ -3159,7 +3142,7 @@ assign_parm_setup_reg (struct assign_par
   validated_mem = validize_mem (copy_rtx (data->entry_parm));
 
   need_conversion = (data->nominal_mode != data->passed_mode
-		     || promoted_nominal_mode != data->promoted_mode);
+		     || promoted_nominal_mode != data->arg.mode);
   moved = false;
 
   if (need_conversion
@@ -3429,7 +3412,7 @@ assign_parm_setup_stack (struct assign_p
 
   assign_parm_remove_parallels (data);
 
-  if (data->promoted_mode != data->nominal_mode)
+  if (data->arg.mode != data->nominal_mode)
     {
       /* Conversion is required.  */
       rtx tempreg = gen_reg_rtx (GET_MODE (data->entry_parm));
@@ -3462,9 +3445,9 @@ assign_parm_setup_stack (struct assign_p
 
       if (data->stack_parm == 0)
 	{
-	  int align = STACK_SLOT_ALIGNMENT (data->passed_type,
+	  int align = STACK_SLOT_ALIGNMENT (data->arg.type,
 					    GET_MODE (data->entry_parm),
-					    TYPE_ALIGN (data->passed_type));
+					    TYPE_ALIGN (data->arg.type));
 	  data->stack_parm
 	    = assign_stack_local (GET_MODE (data->entry_parm),
 				  GET_MODE_SIZE (GET_MODE (data->entry_parm)),
@@ -3484,7 +3467,7 @@ assign_parm_setup_stack (struct assign_p
 	  to_conversion = true;
 
 	  emit_block_move (dest, src,
-			   GEN_INT (int_size_in_bytes (data->passed_type)),
+			   GEN_INT (int_size_in_bytes (data->arg.type)),
 			   BLOCK_OP_NORMAL);
 	}
       else
@@ -3608,10 +3591,9 @@ assign_parms (tree fndecl)
       if (SUPPORTS_STACK_ALIGNMENT)
         {
           unsigned int align
-	    = targetm.calls.function_arg_boundary (data.promoted_mode,
-						   data.passed_type);
-	  align = MINIMUM_ALIGNMENT (data.passed_type, data.promoted_mode,
-				     align);
+	    = targetm.calls.function_arg_boundary (data.arg.mode,
+						   data.arg.type);
+	  align = MINIMUM_ALIGNMENT (data.arg.type, data.arg.mode, align);
 	  if (TYPE_ALIGN (data.nominal_type) > align)
 	    align = MINIMUM_ALIGNMENT (data.nominal_type,
 				       TYPE_MODE (data.nominal_type),
@@ -3636,7 +3618,7 @@ assign_parms (tree fndecl)
       if (data.passed_pointer)
 	{
 	  rtx incoming_rtl
-	    = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (data.passed_type)),
+	    = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (data.arg.type)),
 			   data.entry_parm);
 	  set_decl_incoming_rtl (parm, incoming_rtl, true);
 	}
@@ -3656,9 +3638,7 @@ assign_parms (tree fndecl)
 	assign_parms_setup_varargs (&all, &data, false);
 
       /* Update info on where next arg arrives in registers.  */
-      function_arg_info arg (data.passed_type, data.promoted_mode,
-			     data.named_arg);
-      targetm.calls.function_arg_advance (all.args_so_far, arg);
+      targetm.calls.function_arg_advance (all.args_so_far, data.arg);
     }
 
   if (targetm.calls.split_complex_arg)
@@ -3845,15 +3825,13 @@ gimplify_parameters (gimple_seq *cleanup
 	continue;
 
       /* Update info on where next arg arrives in registers.  */
-      function_arg_info arg (data.passed_type, data.promoted_mode,
-			     data.named_arg);
-      targetm.calls.function_arg_advance (all.args_so_far, arg);
+      targetm.calls.function_arg_advance (all.args_so_far, data.arg);
 
       /* ??? Once upon a time variable_size stuffed parameter list
 	 SAVE_EXPRs (amongst others) onto a pending sizes list.  This
 	 turned out to be less than manageable in the gimple world.
 	 Now we have to hunt them down ourselves.  */
-      walk_tree_without_duplicates (&data.passed_type,
+      walk_tree_without_duplicates (&data.arg.type,
 				    gimplify_parm_type, &stmts);
 
       if (TREE_CODE (DECL_SIZE_UNIT (parm)) != INTEGER_CST)
@@ -3864,8 +3842,8 @@ gimplify_parameters (gimple_seq *cleanup
 
       if (data.passed_pointer)
 	{
-          tree type = TREE_TYPE (data.passed_type);
-	  function_arg_info orig_arg (type, data.named_arg);
+	  tree type = TREE_TYPE (data.arg.type);
+	  function_arg_info orig_arg (type, data.arg.named);
 	  if (reference_callee_copied (&all.args_so_far_v, orig_arg))
 	    {
 	      tree local, t;

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [12/13] Make calls.c use function_arg_info internally
  2019-08-19 15:15 [00/13] Pass an argument descriptor to target hooks Richard Sandiford
                   ` (10 preceding siblings ...)
  2019-08-19 15:51 ` [11/13] Make function.c use function_arg_info internally Richard Sandiford
@ 2019-08-19 15:52 ` Richard Sandiford
  2019-08-19 22:49   ` Jeff Law
  2019-08-19 15:52 ` [13/13] Add a pass_by_reference flag to function_arg_info Richard Sandiford
  12 siblings, 1 reply; 27+ messages in thread
From: Richard Sandiford @ 2019-08-19 15:52 UTC (permalink / raw)
  To: gcc-patches

This patch makes the two main calls.c argument-processing
routines track the state of the argument in a function_arg_info
instead of using separate mode variables.


2019-08-19  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	* calls.c (emit_library_call_value_1): Merge arg and orig_arg
	into a single function_arg_info, updating its fields when we
	apply pass-by-reference and promotion semantics.  Use the
	function_arg_info to track the mode rather than keeping it in
	a separate local variable.
	(initialize_argument_information): Likewise.  Base the final
	arg_to_skip on this new function_arg_info rather than creating
	a new one from scratch.

Index: gcc/calls.c
===================================================================
--- gcc/calls.c	2019-08-19 15:59:09.801778220 +0100
+++ gcc/calls.c	2019-08-19 15:59:18.145717843 +0100
@@ -1982,7 +1982,6 @@ initialize_argument_information (int num
     {
       tree type = TREE_TYPE (args[i].tree_value);
       int unsignedp;
-      machine_mode mode;
 
       /* Replace erroneous argument with constant zero.  */
       if (type == error_mark_node || !COMPLETE_TYPE_P (type))
@@ -2010,13 +2009,13 @@ initialize_argument_information (int num
 	 with those made by function.c.  */
 
       /* See if this argument should be passed by invisible reference.  */
-      function_arg_info orig_arg (type, argpos < n_named_args);
-      if (pass_by_reference (args_so_far_pnt, orig_arg))
+      function_arg_info arg (type, argpos < n_named_args);
+      if (pass_by_reference (args_so_far_pnt, arg))
 	{
 	  bool callee_copies;
 	  tree base = NULL_TREE;
 
-	  callee_copies = reference_callee_copied (args_so_far_pnt, orig_arg);
+	  callee_copies = reference_callee_copied (args_so_far_pnt, arg);
 
 	  /* If we're compiling a thunk, pass through invisible references
 	     instead of making a copy.  */
@@ -2129,15 +2128,16 @@ initialize_argument_information (int num
 	}
 
       unsignedp = TYPE_UNSIGNED (type);
-      mode = promote_function_mode (type, TYPE_MODE (type), &unsignedp,
-				    fndecl ? TREE_TYPE (fndecl) : fntype, 0);
+      arg.type = type;
+      arg.mode
+	= promote_function_mode (type, TYPE_MODE (type), &unsignedp,
+				 fndecl ? TREE_TYPE (fndecl) : fntype, 0);
 
       args[i].unsignedp = unsignedp;
-      args[i].mode = mode;
+      args[i].mode = arg.mode;
 
       targetm.calls.warn_parameter_passing_abi (args_so_far, type);
 
-      function_arg_info arg (type, mode, argpos < n_named_args);
       args[i].reg = targetm.calls.function_arg (args_so_far, arg);
 
       if (args[i].reg && CONST_INT_P (args[i].reg))
@@ -2177,7 +2177,7 @@ initialize_argument_information (int num
       if (args[i].reg == 0 || args[i].partial != 0
 	       || reg_parm_stack_space > 0
 	       || args[i].pass_on_stack)
-	locate_and_pad_parm (mode, type,
+	locate_and_pad_parm (arg.mode, type,
 #ifdef STACK_PARMS_IN_REG_PARM_AREA
 			     1,
 #else
@@ -2191,7 +2191,7 @@ initialize_argument_information (int num
 	/* The argument is passed entirely in registers.  See at which
 	   end it should be padded.  */
 	args[i].locate.where_pad =
-	  BLOCK_REG_PADDING (mode, type,
+	  BLOCK_REG_PADDING (arg.mode, type,
 			     int_size_in_bytes (type) <= UNITS_PER_WORD);
 #endif
 
@@ -2208,9 +2208,8 @@ initialize_argument_information (int num
 	 promoted_mode used for function_arg above.  However, the
 	 corresponding handling of incoming arguments in function.c
 	 does pass the promoted mode.  */
-      function_arg_info arg_to_skip (type, TYPE_MODE (type),
-				     argpos < n_named_args);
-      targetm.calls.function_arg_advance (args_so_far, arg_to_skip);
+      arg.mode = TYPE_MODE (type);
+      targetm.calls.function_arg_advance (args_so_far, arg);
 
       /* Store argument values for functions decorated with attribute
 	 alloc_size.  */
@@ -4906,24 +4905,25 @@ emit_library_call_value_1 (int retval, r
   for (unsigned int i = 0; count < nargs; i++, count++)
     {
       rtx val = args[i].first;
-      machine_mode mode = args[i].second;
+      function_arg_info arg (args[i].second, /*named=*/true);
       int unsigned_p = 0;
 
       /* We cannot convert the arg value to the mode the library wants here;
 	 must do it earlier where we know the signedness of the arg.  */
-      gcc_assert (mode != BLKmode
-		  && (GET_MODE (val) == mode || GET_MODE (val) == VOIDmode));
+      gcc_assert (arg.mode != BLKmode
+		  && (GET_MODE (val) == arg.mode
+		      || GET_MODE (val) == VOIDmode));
 
       /* Make sure it is a reasonable operand for a move or push insn.  */
       if (!REG_P (val) && !MEM_P (val)
-	  && !(CONSTANT_P (val) && targetm.legitimate_constant_p (mode, val)))
+	  && !(CONSTANT_P (val)
+	       && targetm.legitimate_constant_p (arg.mode, val)))
 	val = force_operand (val, NULL_RTX);
 
-      function_arg_info orig_arg (mode, /*named=*/true);
-      if (pass_by_reference (&args_so_far_v, orig_arg))
+      if (pass_by_reference (&args_so_far_v, arg))
 	{
 	  rtx slot;
-	  int must_copy = !reference_callee_copied (&args_so_far_v, orig_arg);
+	  int must_copy = !reference_callee_copied (&args_so_far_v, arg);
 
 	  /* If this was a CONST function, it is now PURE since it now
 	     reads memory.  */
@@ -4942,7 +4942,7 @@ emit_library_call_value_1 (int retval, r
 	    }
 	  else
 	    {
-	      slot = assign_temp (lang_hooks.types.type_for_mode (mode, 0),
+	      slot = assign_temp (lang_hooks.types.type_for_mode (arg.mode, 0),
 				  1, 1);
 	      emit_move_insn (slot, val);
 	    }
@@ -4956,14 +4956,15 @@ emit_library_call_value_1 (int retval, r
 							      slot),
 					     call_fusage);
 
-	  mode = Pmode;
+	  arg.mode = Pmode;
 	  val = force_operand (XEXP (slot, 0), NULL_RTX);
 	}
 
-      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);
+      arg.mode = promote_function_mode (NULL_TREE, arg.mode, &unsigned_p,
+					NULL_TREE, 0);
+      argvec[count].mode = arg.mode;
+      argvec[count].value = convert_modes (arg.mode, GET_MODE (val), val,
+					   unsigned_p);
       argvec[count].reg = targetm.calls.function_arg (args_so_far, arg);
 
       argvec[count].partial
@@ -4973,7 +4974,7 @@ emit_library_call_value_1 (int retval, r
 	  || argvec[count].partial != 0
 	  || reg_parm_stack_space > 0)
 	{
-	  locate_and_pad_parm (mode, NULL_TREE,
+	  locate_and_pad_parm (arg.mode, NULL_TREE,
 #ifdef STACK_PARMS_IN_REG_PARM_AREA
 			       1,
 #else
@@ -4989,8 +4990,9 @@ emit_library_call_value_1 (int retval, r
 	/* The argument is passed entirely in registers.  See at which
 	   end it should be padded.  */
 	argvec[count].locate.where_pad =
-	  BLOCK_REG_PADDING (mode, NULL_TREE,
-			     known_le (GET_MODE_SIZE (mode), UNITS_PER_WORD));
+	  BLOCK_REG_PADDING (arg.mode, NULL_TREE,
+			     known_le (GET_MODE_SIZE (arg.mode),
+				       UNITS_PER_WORD));
 #endif
 
       targetm.calls.function_arg_advance (args_so_far, arg);

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [13/13] Add a pass_by_reference flag to function_arg_info
  2019-08-19 15:15 [00/13] Pass an argument descriptor to target hooks Richard Sandiford
                   ` (11 preceding siblings ...)
  2019-08-19 15:52 ` [12/13] Make calls.c " Richard Sandiford
@ 2019-08-19 15:52 ` Richard Sandiford
  2019-08-19 22:54   ` Jeff Law
  12 siblings, 1 reply; 27+ messages in thread
From: Richard Sandiford @ 2019-08-19 15:52 UTC (permalink / raw)
  To: gcc-patches

This patch adds a flag that tells targets whether an argument
has been converted to pass-by-reference form.  This replaces
assign_parm_data_one::passed_pointer in function.c.

The flag is set automatically for places that call
apply_pass_by_reference_rules.  Places that apply
pass-by-reference manually need to set it themselves.

(After previous changes, no targets apply pass-by-reference
manually.  They all go through apply_pass_by_reference_rules.)


2019-08-19  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	* calls.h (function_arg_info): Add a pass_by_reference field,
	defaulting to false.
	* calls.c (apply_pass_by_reference_rules): Set pass_by_reference
	when applying pass-by-reference semantics.
	(initialize_argument_information): Likewise.
	(emit_library_call_value_1): Likewise.
	* function.c (assign_parm_data_one): Remove passed_pointer field.
	(assign_parm_find_data_types): Don't set it.
	(assign_parm_find_stack_rtl, assign_parm_adjust_stack_rtl)
	(assign_parm_setup_reg, assign_parms, gimplify_parameters): Use
	arg.pass_by_reference instead of passed_pointer.

Index: gcc/calls.h
===================================================================
--- gcc/calls.h	2019-08-19 15:59:09.801778220 +0100
+++ gcc/calls.h	2019-08-19 15:59:21.817691272 +0100
@@ -34,21 +34,25 @@ #define GCC_CALLS_H
 class function_arg_info
 {
 public:
-  function_arg_info () : type (NULL_TREE), mode (VOIDmode), named (false) {}
+  function_arg_info ()
+    : type (NULL_TREE), mode (VOIDmode), named (false),
+      pass_by_reference (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)
+    : type (NULL_TREE), mode (mode), named (named), pass_by_reference (false)
   {}
 
   /* Initialize an unpromoted argument of type TYPE.  */
   function_arg_info (tree type, bool named)
-    : type (type), mode (TYPE_MODE (type)), named (named)
+    : type (type), mode (TYPE_MODE (type)), named (named),
+      pass_by_reference (false)
   {}
 
   /* Initialize an argument with explicit properties.  */
   function_arg_info (tree type, machine_mode mode, bool named)
-    : type (type), mode (mode), named (named)
+    : type (type), mode (mode), named (named), pass_by_reference (false)
   {}
 
   /* Return true if the gimple-level type is an aggregate.  */
@@ -100,6 +104,10 @@ #define GCC_CALLS_H
      treated as an unnamed variadic argument (i.e. one passed through
      "...").  See also TARGET_STRICT_ARGUMENT_NAMING.  */
   unsigned int named : 1;
+
+  /* True if we have decided to pass the argument by reference, in which case
+     the function_arg_info describes a pointer to the original argument.  */
+  unsigned int pass_by_reference : 1;
 };
 
 extern int flags_from_decl_or_type (const_tree);
Index: gcc/calls.c
===================================================================
--- gcc/calls.c	2019-08-19 15:59:18.145717843 +0100
+++ gcc/calls.c	2019-08-19 15:59:21.817691272 +0100
@@ -946,6 +946,7 @@ apply_pass_by_reference_rules (CUMULATIV
     {
       arg.type = build_pointer_type (arg.type);
       arg.mode = TYPE_MODE (arg.type);
+      arg.pass_by_reference = true;
       return true;
     }
   return false;
@@ -2125,6 +2126,7 @@ initialize_argument_information (int num
 					      "argument must be passed"
 					      " by copying");
 	    }
+	  arg.pass_by_reference = true;
 	}
 
       unsignedp = TYPE_UNSIGNED (type);
@@ -4957,6 +4959,7 @@ emit_library_call_value_1 (int retval, r
 					     call_fusage);
 
 	  arg.mode = Pmode;
+	  arg.pass_by_reference = true;
 	  val = force_operand (XEXP (slot, 0), NULL_RTX);
 	}
 
Index: gcc/function.c
===================================================================
--- gcc/function.c	2019-08-19 15:59:14.297745685 +0100
+++ gcc/function.c	2019-08-19 15:59:21.821691241 +0100
@@ -2271,7 +2271,6 @@ struct assign_parm_data_one
   machine_mode passed_mode;
   struct locate_and_pad_arg_data locate;
   int partial;
-  BOOL_BITFIELD passed_pointer : 1;
 };
 
 /* A subroutine of assign_parms.  Initialize ALL.  */
@@ -2453,7 +2452,6 @@ assign_parm_find_data_types (struct assi
   if (apply_pass_by_reference_rules (&all->args_so_far_v, data->arg))
     {
       data->nominal_type = data->arg.type;
-      data->passed_pointer = true;
       data->passed_mode = data->nominal_mode = data->arg.mode;
     }
 
@@ -2653,7 +2651,7 @@ assign_parm_find_stack_rtl (tree parm, s
     stack_parm = gen_rtx_PLUS (Pmode, stack_parm, offset_rtx);
   stack_parm = gen_rtx_MEM (data->arg.mode, stack_parm);
 
-  if (!data->passed_pointer)
+  if (!data->arg.pass_by_reference)
     {
       set_mem_attributes (stack_parm, parm, 1);
       /* set_mem_attributes could set MEM_SIZE to the passed mode's size,
@@ -2812,7 +2810,7 @@ assign_parm_adjust_stack_rtl (struct ass
      pointers in their passed stack slots.  */
   else if (crtl->stack_protect_guard
 	   && (flag_stack_protect == 2
-	       || data->passed_pointer
+	       || data->arg.pass_by_reference
 	       || POINTER_TYPE_P (data->nominal_type)))
     stack_parm = NULL;
 
@@ -3125,7 +3123,7 @@ assign_parm_setup_reg (struct assign_par
 
   /* If this was an item that we received a pointer to,
      set rtl appropriately.  */
-  if (data->passed_pointer)
+  if (data->arg.pass_by_reference)
     {
       rtl = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (data->arg.type)), parmreg);
       set_mem_attributes (rtl, parm, 1);
@@ -3295,7 +3293,7 @@ assign_parm_setup_reg (struct assign_par
 
   /* If we were passed a pointer but the actual value can safely live
      in a register, retrieve it and use it directly.  */
-  if (data->passed_pointer && TYPE_MODE (TREE_TYPE (parm)) != BLKmode)
+  if (data->arg.pass_by_reference && TYPE_MODE (TREE_TYPE (parm)) != BLKmode)
     {
       /* We can't use nominal_mode, because it will have been set to
 	 Pmode above.  We must use the actual mode of the parm.  */
@@ -3615,7 +3613,7 @@ assign_parms (tree fndecl)
 	  assign_parm_adjust_entry_rtl (&data);
 	}
       /* Record permanently how this parm was passed.  */
-      if (data.passed_pointer)
+      if (data.arg.pass_by_reference)
 	{
 	  rtx incoming_rtl
 	    = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (data.arg.type)),
@@ -3629,7 +3627,7 @@ assign_parms (tree fndecl)
 
       if (assign_parm_setup_block_p (&data))
 	assign_parm_setup_block (&all, parm, &data);
-      else if (data.passed_pointer || use_register_for_decl (parm))
+      else if (data.arg.pass_by_reference || use_register_for_decl (parm))
 	assign_parm_setup_reg (&all, parm, &data);
       else
 	assign_parm_setup_stack (&all, parm, &data);
@@ -3840,7 +3838,7 @@ gimplify_parameters (gimple_seq *cleanup
 	  gimplify_one_sizepos (&DECL_SIZE_UNIT (parm), &stmts);
 	}
 
-      if (data.passed_pointer)
+      if (data.arg.pass_by_reference)
 	{
 	  tree type = TREE_TYPE (data.arg.type);
 	  function_arg_info orig_arg (type, data.arg.named);

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [01/13] Add pass_va_arg_by_reference
  2019-08-19 15:16 ` [01/13] Add pass_va_arg_by_reference Richard Sandiford
@ 2019-08-19 20:04   ` Jeff Law
  0 siblings, 0 replies; 27+ messages in thread
From: Jeff Law @ 2019-08-19 20:04 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

On 8/19/19 9:11 AM, Richard Sandiford wrote:
> This patch splits out a common idiom from the va_arg gimplification
> routines, so that there's only one place to update later.
> 
> 
> 2019-08-19  Richard Sandiford  <richard.sandiford@arm.com>
> 
> gcc/
> 	* calls.h (pass_va_arg_by_reference): Declare.
> 	* calls.c (pass_va_arg_by_reference): New function.
> 	* config/aarch64/aarch64.c (aarch64_gimplify_va_arg_expr): Use it.
> 	* config/alpha/alpha.c (alpha_gimplify_va_arg): Likewise.
> 	* config/gcn/gcn.c (gcn_gimplify_va_arg_expr): Likewise.
> 	* config/i386/i386.c (ix86_gimplify_va_arg): Likewise.
> 	* config/ia64/ia64.c (ia64_gimplify_va_arg): Likewise.
> 	* config/mips/mips.c (mips_std_gimplify_va_arg_expr): Likewise.
> 	(mips_gimplify_va_arg_expr): Likewise.
> 	* config/msp430/msp430.c (msp430_gimplify_va_arg_expr): Likewise.
> 	* config/pa/pa.c (hppa_gimplify_va_arg_expr): Likewise.
> 	* config/rs6000/rs6000-call.c (rs6000_gimplify_va_arg): Likewise.
> 	* config/s390/s390.c (s390_gimplify_va_arg): Likewise.
> 	* config/sparc/sparc.c (sparc_gimplify_va_arg): Likewise.
> 	* config/spu/spu.c (spu_gimplify_va_arg_expr): Likewise.
> 	* config/tilegx/tilegx.c (tilegx_gimplify_va_arg_expr): Likewise.
> 	* config/tilepro/tilepro.c (tilepro_gimplify_va_arg_expr): Likewise.
> 	* config/visium/visium.c (visium_gimplify_va_arg): Likewise.
> 	* config/xtensa/xtensa.c (xtensa_gimplify_va_arg_expr): Likewise.
> 	* targhooks.c (std_gimplify_va_arg_expr): Likewise.
OK
jeff

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [02/13] Add must_pass_va_arg_in_stack
  2019-08-19 15:17 ` [02/13] Add must_pass_va_arg_in_stack Richard Sandiford
@ 2019-08-19 20:05   ` Jeff Law
  0 siblings, 0 replies; 27+ messages in thread
From: Jeff Law @ 2019-08-19 20:05 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

On 8/19/19 9:12 AM, Richard Sandiford wrote:
> This patch splits out another idiom from the va_arg gimplification
> routines, so that there's only one place to update later.
> 
> 
> 2019-08-19  Richard Sandiford  <richard.sandiford@arm.com>
> 
> gcc/
> 	* 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.
> 	* config/sh/sh.c (sh_gimplify_va_arg_expr): Likewise.
> 	* config/stormy16/stormy16.c (xstormy16_gimplify_va_arg_expr):
> 	Likewise.
> 	* config/xtensa/xtensa.c (xtensa_gimplify_va_arg_expr): Likewise.
OK.  Hopefully they're all this easy to review :-)

jeff

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [03/13] Use function_arg_info for TARGET_ARG_PARTIAL_BYTES
  2019-08-19 15:18 ` [03/13] Use function_arg_info for TARGET_ARG_PARTIAL_BYTES Richard Sandiford
@ 2019-08-19 20:42   ` Jeff Law
  0 siblings, 0 replies; 27+ messages in thread
From: Jeff Law @ 2019-08-19 20:42 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

On 8/19/19 9:14 AM, Richard Sandiford wrote:
> This patch adds the function_arg_info class and uses it for
> TARGET_ARG_PARTIAL_BYTES.
> 
> The hook is passed the promoted mode instead of the original type mode.
> 
> The arguments aren't mentioned in the documentation, which is why the
> target.def change is so small.
> 
> The patch changes "true" to "arg.named" in:
> 
>   gcc_assert (!epiphany_pass_by_reference (cum, mode, type, /* named */ true));
> 
> but epiphany_pass_by_reference doesn't care about the named flag.
> 
> 
> 2019-08-19  Richard Sandiford  <richard.sandiford@arm.com>
> 
> gcc/
> 	* 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.
OK
jeff

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [04/13] Use function_arg_info for TARGET_PASS_BY_REFERENCE
  2019-08-19 15:19 ` [04/13] Use function_arg_info for TARGET_PASS_BY_REFERENCE Richard Sandiford
@ 2019-08-19 20:43   ` Jeff Law
  0 siblings, 0 replies; 27+ messages in thread
From: Jeff Law @ 2019-08-19 20:43 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

On 8/19/19 9:15 AM, Richard Sandiford wrote:
> Use function_arg_info for TARGET_PASS_BY_REFERENCE.
> 
> The hook is passed the unpromoted type mode instead of the promoted mode.
> 
> 
> 2019-08-19  Richard Sandiford  <richard.sandiford@arm.com>
> 
> gcc/
> 	* target.def (pass_by_reference): Take a function_arg_info instead
> 	of a mode, type and named flag.
> 	* doc/tm.texi: Regenerate.
> 	* targhooks.h (hook_pass_by_reference_must_pass_in_stack): Update
> 	accordingly.
> 	(hook_bool_CUMULATIVE_ARGS_arg_info_false): Declare.
> 	* targhooks.c (hook_pass_by_reference_must_pass_in_stack): Take a
> 	function_arg_info instead of a mode, type and named flag.
> 	(hook_bool_CUMULATIVE_ARGS_arg_info_false): New function.
> 	* calls.h (pass_by_reference): Take a function_arg_info instead of a
> 	mode, type and named flag.
> 	* calls.c (pass_by_reference): Likewise.
> 	(pass_va_arg_by_reference): Update call accordingly.
> 	(initialize_argument_information): Likewise.
> 	(emit_library_call_value_1): Likewise.
> 	* function.c (assign_parm_find_data_types): Likewise.
> 	* var-tracking.c (prepare_call_arguments): Likewise.
> 	* stor-layout.c: Include calls.h.
> 	(compute_record_mode): Update call to targetm.calls.pass_by_reference.
> 	* config/aarch64/aarch64.c (aarch64_pass_by_reference): Take a
> 	function_arg_info instead of a mode, type and named flag.
> 	* config/alpha/alpha.c (alpha_pass_by_reference): Likewise.
> 	* config/arc/arc.c (arc_pass_by_reference): Likewise.
> 	* config/arm/arm.c (arm_pass_by_reference): Likewise.
> 	* config/bfin/bfin.c (bfin_pass_by_reference): Likewise.
> 	* config/c6x/c6x.c (c6x_pass_by_reference): Likewise.
> 	(c6x_call_saved_register_used): Update call to pass_by_reference.
> 	* config/cris/cris.c (cris_pass_by_reference): Take a
> 	function_arg_info instead of a mode, type and named flag.
> 	* config/epiphany/epiphany.c (epiphany_pass_by_reference): Take a
> 	function_arg_info instead of a mode, type and named flag.
> 	(epiphany_arg_partial_bytes): Update call accordingly.
> 	* config/ft32/ft32.c (ft32_pass_by_reference): Take a
> 	function_arg_info instead of a mode, type and named flag.
> 	(ft32_arg_partial_bytes): Update call accordingly.
> 	* config/i386/i386.c (ix86_pass_by_reference): Take a
> 	function_arg_info instead of a mode, type and named flag.
> 	* config/iq2000/iq2000.c (iq2000_pass_by_reference): Likewise.
> 	* config/m32c/m32c.c (m32c_pass_by_reference): Likewise.
> 	* config/m32r/m32r.c (m32r_pass_by_reference): Likewise.
> 	(m32r_return_in_memory): Update call accordingly.
> 	* config/mips/mips.c (mips_pass_by_reference): Take a
> 	function_arg_info instead of a mode, type and named flag.
> 	* config/mmix/mmix.c (mmix_pass_by_reference): Likewise.
> 	* config/mn10300/mn10300.c (mn10300_pass_by_reference): Likewise.
> 	* config/moxie/moxie.c (moxie_pass_by_reference): Likewise.
> 	(moxie_arg_partial_bytes): Update call accordingly.
> 	* config/msp430/msp430.c (msp430_pass_by_reference): Take a
> 	function_arg_info instead of a mode, type and named flag.
> 	* config/nvptx/nvptx.c (nvptx_pass_by_reference): Likewise.
> 	* config/or1k/or1k.c (or1k_pass_by_reference): Likewise.
> 	* config/pa/pa.c (pa_pass_by_reference): Likewise.
> 	* config/riscv/riscv.c (riscv_pass_by_reference): Likewise.
> 	(riscv_return_in_memory): Update call accordingly.
> 	* config/rs6000/rs6000-internal.h (rs6000_pass_by_reference): Take a
> 	function_arg_info instead of a mode, type and named flag.
> 	* config/rs6000/rs6000-call.c (rs6000_pass_by_reference): Likewise.
> 	(rs6000_parm_needs_stack): Update call to pass_by_reference.
> 	* config/s390/s390.c (s390_pass_by_reference): Take a
> 	function_arg_info instead of a mode, type and named flag.
> 	(s390_call_saved_register_used): Update call accordingly.
> 	* config/sh/sh.c (sh_pass_by_reference): Take a function_arg_info
> 	instead of a mode, type and named flag.
> 	* config/sparc/sparc.c (sparc_pass_by_reference): Likewise.
> 	* config/spu/spu.c (spu_pass_by_reference): Likewise.
> 	* config/tilegx/tilegx.c (tilegx_pass_by_reference): Likewise.
> 	* config/tilepro/tilepro.c (tilepro_pass_by_reference): Likewise.
> 	* config/v850/v850.c (v850_pass_by_reference): Likewise.
> 	* config/visium/visium.c (visium_pass_by_reference): Likewise.
> 
> gcc/ada/
> 	* gcc-interface/misc.c (default_pass_by_ref): Update call to
> 	pass_by_reference.
OK
jeff

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [05/13] Use function_arg_info for TARGET_SETUP_INCOMING_ARGS
  2019-08-19 15:20 ` [05/13] Use function_arg_info for TARGET_SETUP_INCOMING_ARGS Richard Sandiford
@ 2019-08-19 20:50   ` Jeff Law
  0 siblings, 0 replies; 27+ messages in thread
From: Jeff Law @ 2019-08-19 20:50 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

On 8/19/19 9:16 AM, Richard Sandiford wrote:
> Use function_arg_info for TARGET_SETUP_INCOMING_ARGS.
> 
> The hook is passed the promoted mode instead of the original type mode.
> 
> 
> 2019-08-19  Richard Sandiford  <richard.sandiford@arm.com>
> 
> gcc/
> 	* target.def (setup_incoming_varargs): Take a function_arg_info
> 	instead of a mode and tree.
> 	* doc/tm.texi: Regenerate.
> 	* targhooks.h (default_setup_incoming_varargs): Take a
> 	function_arg_info instead of a mode and tree.
> 	* targhooks.c (default_setup_incoming_varargs): Likewise.
> 	* config/aarch64/aarch64.c (aarch64_setup_incoming_varargs): Likewise.
> 	* config/alpha/alpha.c (alpha_setup_incoming_varargs): Likewise.
> 	* config/arc/arc.c (arc_setup_incoming_varargs): Likewise.
> 	* config/arm/arm.c (arm_setup_incoming_varargs): Likewise.
> 	* config/bfin/bfin.c (setup_incoming_varargs): Likewise.
> 	* config/cris/cris.c (cris_setup_incoming_varargs): Likewise.
> 	* config/csky/csky.c (csky_setup_incoming_varargs): Likewise.
> 	* config/epiphany/epiphany.c (epiphany_setup_incoming_varargs):
> 	Likewise.
> 	* config/fr30/fr30.c (fr30_setup_incoming_varargs): Likewise.
> 	* config/frv/frv.c (frv_setup_incoming_varargs): Likewise.
> 	* config/ft32/ft32.c (ft32_setup_incoming_varargs): Likewise.
> 	* config/i386/i386.c (ix86_setup_incoming_varargs): Likewise.
> 	* config/ia64/ia64.c (ia64_setup_incoming_varargs): Likewise.
> 	* config/iq2000/iq2000.c (iq2000_setup_incoming_varargs): Likewise.
> 	* config/lm32/lm32.c (lm32_setup_incoming_varargs): Likewise.
> 	* config/m32r/m32r.c (m32r_setup_incoming_varargs): Likewise.
> 	* config/mcore/mcore.c (mcore_setup_incoming_varargs): Likewise.
> 	* config/mips/mips.c (mips_setup_incoming_varargs): Likewise.
> 	* config/mmix/mmix.c (mmix_setup_incoming_varargs): Likewise.
> 	* config/moxie/moxie.c (moxie_setup_incoming_varargs): Likewise.
> 	* config/nds32/nds32.c (nds32_setup_incoming_varargs): Likewise.
> 	* config/nios2/nios2.c (nios2_setup_incoming_varargs): Likewise.
> 	* config/riscv/riscv.c (riscv_setup_incoming_varargs): Likewise.
> 	* config/rs6000/rs6000-internal.h (setup_incoming_varargs): Likewise.
> 	* config/rs6000/rs6000-call.c (setup_incoming_varargs): Likewise.
> 	* config/sh/sh.c (sh_setup_incoming_varargs): Likewise.
> 	* config/spu/spu.c (spu_setup_incoming_varargs): Likewise.
> 	* config/tilegx/tilegx.c (tilegx_setup_incoming_varargs): Likewise.
> 	* config/tilepro/tilepro.c (tilepro_setup_incoming_varargs): Likewise.
> 	* config/visium/visium.c (visium_setup_incoming_varargs): Likewise.
> 	* function.c (assign_parms_setup_varargs): Update call to
> 	targetm.calls.setup_incoming_varargs.
OK
jeff

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [06/13] Use function_arg_info for TARGET_FUNCTION_(INCOMING_)ARG
  2019-08-19 15:21 ` [06/13] Use function_arg_info for TARGET_FUNCTION_(INCOMING_)ARG Richard Sandiford
@ 2019-08-19 21:07   ` Jeff Law
  0 siblings, 0 replies; 27+ messages in thread
From: Jeff Law @ 2019-08-19 21:07 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

On 8/19/19 9:16 AM, Richard Sandiford wrote:
> This patch makes both TARGET_FUNCTION_ARG and
> TARGET_FUNCTION_INCOMING_ARG take a function_arg_info.
> They have to be done together since many targets use the
> same function for both.
> 
> The hooks are passed the promoted mode instead of the original type mode.
> 
> 
> 2019-08-19  Richard Sandiford  <richard.sandiford@arm.com>
> 
> gcc/
> 	* target.def (function_arg, function_incoming_arg): Take a
> 	function_arg_info instead of a mode, tree and named flag.
> 	* doc/tm.texi: Regenerate.
> 	* targhooks.h (default_function_arg): Take a function_arg_info
> 	instead of a mode, tree and named flag.
> 	(default_function_incoming_arg): Likewise.
> 	* targhooks.c (default_function_arg): Likewise.
> 	(default_function_incoming_arg): Likewise.
> 	* calls.h (function_arg_info::end_marker_p): New function.
> 	(function_arg_info::end_marker): Likewise.
> 	* calls.c (prepare_call_address, initialize_argument_information)
> 	(expand_call, emit_library_call_value_1): Update calls to
> 	targetm.calls.function_arg and targetm.calls.function_incoming_arg.
> 	* dse.c: Include calls.h.
> 	(get_call_args): Update call to targetm.calls.function_arg.
> 	* expr.c (block_move_libcall_safe_for_call_parm): Likewise.
> 	* var-tracking.c (prepare_call_arguments): Likewise.
> 	* function.c (assign_parm_find_entry_rtl): Update call to
> 	targetm.calls.function_incoming_arg.
> 	* config/aarch64/aarch64.c (aarch64_function_arg): Take a
> 	function_arg_info instead of a mode, tree and named flag.
> 	* config/alpha/alpha.c (alpha_function_arg): Likewise.
> 	* config/arc/arc.c (arc_function_arg): Likewise.
> 	* config/arm/arm.c (arm_function_arg): Likewise.
> 	(cmse_func_args_or_return_in_stack): Update call accordingly.
> 	(arm_function_ok_for_sibcall): Likewise.
> 	(cmse_nonsecure_call_clear_caller_saved): Likewise.
> 	* config/avr/avr.c (avr_function_arg): Take a function_arg_info
> 	instead of a mode, tree and named flag.
> 	* config/bfin/bfin.c (bfin_function_arg): Likewise.
> 	* config/c6x/c6x.c (c6x_function_arg): Likewise.
> 	(c6x_call_saved_register_used): Update call accordingly.
> 	* config/cr16/cr16.c (cr16_function_arg): Take a function_arg_info
> 	instead of a mode, tree and named flag.
> 	* config/cris/cris.c (cris_function_arg, cris_function_incoming_arg)
> 	(cris_function_arg_1): Likewise.
> 	* config/csky/csky.c (csky_function_arg): Likewise.
> 	* config/epiphany/epiphany.c (epiphany_function_arg): Likewise.
> 	* config/fr30/fr30.c (fr30_function_arg): Likewise.
> 	* config/frv/frv.c (frv_function_arg, frv_function_incoming_arg)
> 	(frv_function_arg_1): Likewise.
> 	* config/ft32/ft32.c (ft32_function_arg): Likewise.
> 	* config/gcn/gcn.c (gcn_function_arg): Likewise.
> 	* config/h8300/h8300.c (h8300_function_arg): Likewise.
> 	* config/i386/i386.c (ix86_function_arg): Likewise.
> 	* config/ia64/ia64.c (ia64_function_arg, ia64_function_incoming_arg)
> 	(ia64_function_arg_1): Likewise.
> 	* config/iq2000/iq2000.c (iq2000_function_arg): Likewise.
> 	(iq2000_expand_prologue, iq2000_pass_by_reference): Update call
> 	accordingly.
> 	* config/lm32/lm32.c (lm32_function_arg): Take a function_arg_info
> 	instead of a mode, tree and named flag.
> 	* config/m32c/m32c.c (m32c_function_arg): Likewise.
> 	* config/m32r/m32r.c (m32r_function_arg): Likewise.
> 	* config/m68k/m68k.c (m68k_function_arg): Likewise.
> 	* config/mcore/mcore.c (mcore_function_arg): Likewise.
> 	* config/microblaze/microblaze.c (microblaze_function_arg): Likewise.
> 	(microblaze_expand_prologue): Update call accordingly.
> 	* config/mips/mips.c (mips_function_arg): Take a function_arg_info
> 	instead of a mode, tree and named flag.
> 	* config/mmix/mmix.c (mmix_function_incoming_arg, mmix_function_arg)
> 	(mmix_function_arg_1): Likewise.
> 	* config/mn10300/mn10300.c (mn10300_function_arg): Likewise.
> 	* config/moxie/moxie.c (moxie_function_arg): Likewise.
> 	* config/msp430/msp430.c (msp430_function_arg): Likewise.
> 	* config/nds32/nds32.c (nds32_function_arg): Likewise.
> 	* config/nios2/nios2.c (nios2_function_arg): Likewise.
> 	* config/nvptx/nvptx.c (nvptx_function_arg): Likewise.
> 	(nvptx_function_incoming_arg): Likewise.
> 	* config/or1k/or1k.c (or1k_function_arg): Likewise.
> 	* config/pa/pa.c (pa_function_arg): Likewise.
> 	* config/pdp11/pdp11.c (pdp11_function_arg): Likewise.
> 	* config/pru/pru.c (pru_function_arg): Likewise.
> 	* config/riscv/riscv.c (riscv_function_arg): Likewise.
> 	* config/rl78/rl78.c (rl78_function_arg): Likewise.
> 	* config/rs6000/rs6000-internal.h (rs6000_function_arg): Likewise.
> 	* config/rs6000/rs6000-call.c (rs6000_function_arg): Likewise.
> 	(rs6000_parm_needs_stack): Update call accordingly.
> 	* config/rx/rx.c (rx_function_arg): Take a function_arg_info
> 	instead of a mode, tree and named flag.
> 	* config/s390/s390.c (s390_function_arg): Likewise.
> 	(s390_call_saved_register_used): Update call accordingly.
> 	* config/sh/sh.c (sh_function_arg): Take a function_arg_info
> 	instead of a mode, tree and named flag.
> 	(sh_output_mi_thunk): Update call accordingly.
> 	* config/sparc/sparc.c (sparc_function_arg_1, sparc_function_arg)
> 	(sparc_function_incoming_arg): Take a function_arg_info instead of
> 	a mode, tree and named flag.
> 	* config/spu/spu.c (spu_function_arg): Likewise.
> 	* config/stormy16/stormy16.c (xstormy16_function_arg): Likewise.
> 	* config/tilegx/tilegx.c (tilegx_function_arg): Likewise.
> 	* config/tilepro/tilepro.c (tilepro_function_arg): Likewise.
> 	* config/v850/v850.c (v850_function_arg): Likewise.
> 	* config/vax/vax.c (vax_function_arg): Likewise.
> 	* config/visium/visium.c (visium_function_arg): Likewise.
> 	* config/xtensa/xtensa.c (xtensa_function_arg_1, xtensa_function_arg)
> 	(xtensa_function_incoming_arg): Likewise.
> 
OK
jeff

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [07/13] Use function_arg_info for TARGET_FUNCTION_ARG_ADVANCE
  2019-08-19 15:22 ` [07/13] Use function_arg_info for TARGET_FUNCTION_ARG_ADVANCE Richard Sandiford
@ 2019-08-19 21:11   ` Jeff Law
  0 siblings, 0 replies; 27+ messages in thread
From: Jeff Law @ 2019-08-19 21:11 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

On 8/19/19 9:18 AM, Richard Sandiford wrote:
> Use function_arg_info for TARGET_FUNCTION_ARG_ADVANCE.
> 
> There seems to be a bit of confusion around this one.  Almost all
> callers pass the same arguments as TARGET_FUNCTION_ARG, meaning
> that the mode is the promoted mode rather than the type mode.
> But the calls.c handling for normal typed arguments instead passes
> the unpromoted TYPE_MODE (despite passing the promoted mode to
> TARGET_FUNCTION_ARG).  I've kept this behaviour with a ??? comment.
> 
> (The calls.c handling of libgcc functions does pass the promoted
> mode though, as does the function.c handling of incoming arguments.)
> 
> Also, a couple of the arm callers don't seem to be using the hook
> correctly.  Again I kept the current choices and added a ??? comment.
Keeping current behavior seems reasonable as does marking the
inconsistent bits.


> 
> 
> 2019-08-19  Richard Sandiford  <richard.sandiford@arm.com>
> 
> gcc/
> 	* target.def (function_arg_advance): Take a function_arg_info instead
> 	of a mode, type and named flag.
> 	* doc/tm.texi: Regenerate.
> 	* targhooks.h (default_function_arg_advance): Take a function_arg_info
> 	instead of a mode, type and named flag.
> 	* targhooks.c (default_function_arg_advance): Likewise.
> 	* calls.c (initialize_argument_information): Update call to
> 	targetm.calls.function_arg_advance.
> 	(emit_library_call_value_1): Likewise.
> 	* dse.c (get_call_args): Likewise.
> 	* expr.c (block_move_libcall_safe_for_call_parm): Likewise.
> 	* function.c (assign_parms, gimplify_parameters): Likewise.
> 	* var-tracking.c (prepare_call_arguments): Likewise.
> 	* config/aarch64/aarch64.c (aarch64_function_arg_advance): Take a
> 	function_arg_info instead of a mode, type and named flag.
> 	(aarch64_setup_incoming_varargs): Update call accordingly.
> 	* config/alpha/alpha.c (alpha_function_arg_advance): Take a
> 	function_arg_info instead of a mode, type and named flag.
> 	(alpha_setup_incoming_varargs): Update call accordingly.
> 	* config/arc/arc.c (arc_function_arg_advance): Take a
> 	function_arg_info instead of a mode, type and named flag.
> 	(arc_setup_incoming_varargs): Update call accordingly.
> 	* config/arm/arm.c (arm_function_arg_advance): Take a
> 	function_arg_info instead of a mode, type and named flag.
> 	(cmse_func_args_or_return_in_stack): Update call accordingly.
> 	(arm_function_ok_for_sibcall): Likewise.
> 	(cmse_nonsecure_call_clear_caller_saved): Likewise.
> 	* config/avr/avr.c (avr_function_arg_advance): Take a
> 	function_arg_info instead of a mode, type and named flag.
> 	* config/bfin/bfin.c (bfin_function_arg_advance): Likewise.
> 	* config/c6x/c6x.c (c6x_function_arg_advance): Likewise.
> 	(c6x_call_saved_register_used): Update call accordingly.
> 	* config/cr16/cr16.c (cr16_function_arg_advance): Take a
> 	function_arg_info instead of a mode, type and named flag.
> 	* config/cris/cris.c (cris_function_arg_advance): Likewise.
> 	* config/csky/csky.c (csky_function_arg_advance): Likewise.
> 	(csky_setup_incoming_varargs): Update call accordingly.
> 	* config/epiphany/epiphany.c (epiphany_function_arg_advance): Take a
> 	function_arg_info instead of a mode, type and named flag.
> 	* config/fr30/fr30.c (fr30_function_arg_advance): Likewise.
> 	* config/frv/frv.c (frv_function_arg_advance): Likewise.
> 	* config/ft32/ft32.c (ft32_function_arg_advance): Likewise.
> 	* config/gcn/gcn.c (gcn_function_arg_advance): Likewise.
> 	* config/h8300/h8300.c (h8300_function_arg_advance): Likewise.
> 	* config/i386/i386.c (ix86_function_arg_advance): Likewise.
> 	(ix86_setup_incoming_varargs): Update call accordingly.
> 	* config/ia64/ia64.c (ia64_function_arg_advance): Take a
> 	function_arg_info instead of a mode, type and named flag.
> 	(ia64_setup_incoming_varargs): Update call accordingly.
> 	* config/iq2000/iq2000.c (iq2000_function_arg_advance): Take a
> 	function_arg_info instead of a mode, type and named flag.
> 	(iq2000_expand_prologue): Update call accordingly.
> 	* config/lm32/lm32.c (lm32_function_arg_advance): Take a
> 	function_arg_info instead of a mode, type and named flag.
> 	* config/m32c/m32c.c (m32c_function_arg_advance): Likewise.
> 	* config/m32r/m32r.c (m32r_function_arg_advance): Likewise.
> 	* config/m68k/m68k.c (m68k_function_arg_advance): Likewise.
> 	* config/mcore/mcore.c (mcore_function_arg_advance): Likewise.
> 	* config/microblaze/microblaze.c (microblaze_function_arg_advance):
> 	Likewise.
> 	(microblaze_expand_prologue): Update call accordingly.
> 	* config/mips/mips.c (mips_function_arg_advance): Take a
> 	function_arg_info instead of a mode, type and named flag.
> 	(mips_setup_incoming_varargs): Update call accordingly.
> 	(mips_output_args_xfer): Likewise.
> 	* config/mmix/mmix.c (mmix_function_arg_advance): Take a
> 	function_arg_info instead of a mode, type and named flag.
> 	* config/mn10300/mn10300.c (mn10300_function_arg_advance): Likewise.
> 	* config/moxie/moxie.c (moxie_function_arg_advance): Likewise.
> 	* config/msp430/msp430.c (msp430_function_arg_advance): Likewise.
> 	* config/nds32/nds32.c (nds32_function_arg_advance): Likewise.
> 	* config/nios2/nios2.c (nios2_function_arg_advance): Likewise.
> 	(nios2_setup_incoming_varargs): Update call accordingly.
> 	* config/nvptx/nvptx.c (nvptx_function_arg_advance): Take a
> 	function_arg_info instead of a mode, type and named flag.
> 	* config/or1k/or1k.c (or1k_function_arg_advance): Likewise.
> 	* config/pa/pa.c (pa_function_arg_advance): Likewise.
> 	* config/pdp11/pdp11.c (pdp11_function_arg_advance): Likewise.
> 	* config/pru/pru.c (pru_function_arg_advance): Likewise.
> 	* config/riscv/riscv.c (riscv_function_arg_advance): Likewise.
> 	(riscv_setup_incoming_varargs): Update call accordingly.
> 	* config/rl78/rl78.c (rl78_function_arg_advance): Take a
> 	function_arg_info instead of a mode, type and named flag.
> 	* config/rs6000/rs6000-internal.h (rs6000_function_arg_advance):
> 	Likewise.
> 	* config/rs6000/rs6000-call.c (rs6000_function_arg_advance): Likewise.
> 	(rs6000_parm_needs_stack): Update call accordingly.
> 	* config/rx/rx.c (rx_function_arg_advance): Take a function_arg_info
> 	instead of a mode, type and named flag.
> 	* config/s390/s390.c (s390_function_arg_advance): Likewise.
> 	(s390_call_saved_register_used): Update call accordingly.
> 	* config/sh/sh.c (sh_function_arg_advance): Take a function_arg_info
> 	instead of a mode, type and named flag.
> 	(sh_output_mi_thunk): Update call accordingly.
> 	* config/sparc/sparc.c (sparc_function_arg_advance): Take a
> 	function_arg_info instead of a mode, type and named flag.
> 	* config/spu/spu.c (spu_function_arg_advance): Likewise.
> 	(spu_setup_incoming_varargs): Update call accordingly.
> 	* config/stormy16/stormy16.c (xstormy16_function_arg_advance): Take a
> 	function_arg_info instead of a mode, type and named flag.
> 	* config/tilegx/tilegx.c (tilegx_function_arg_advance): Likewise.
> 	(tilegx_setup_incoming_varargs): Update call accordingly.
> 	* config/tilepro/tilepro.c (tilepro_function_arg_advance): Take a
> 	function_arg_info instead of a mode, type and named flag.
> 	(tilegx_setup_incoming_varargs): Update call accordingly.
> 	* config/v850/v850.c (v850_function_arg_advance): Take a
> 	function_arg_info instead of a mode, type and named flag.
> 	* config/vax/vax.c (vax_function_arg_advance): Likewise.
> 	* config/visium/visium.c (visium_function_arg_advance): Likewise.
> 	(visium_setup_incoming_varargs): Update call accordingly.
> 	* config/xtensa/xtensa.c (xtensa_function_arg_advance): Take a
> 	function_arg_info instead of a mode, type and named flag.
> 

OK
jeff

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [08/13] Use function_arg_info for TARGET_CALLEE_COPIES
  2019-08-19 15:23 ` [08/13] Use function_arg_info for TARGET_CALLEE_COPIES Richard Sandiford
@ 2019-08-19 21:16   ` Jeff Law
  0 siblings, 0 replies; 27+ messages in thread
From: Jeff Law @ 2019-08-19 21:16 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

On 8/19/19 9:19 AM, Richard Sandiford wrote:
> Use function_arg_info for TARGET_CALLEE_COPIES.
> 
> The hook is passed the unpromoted type mode instead of the promoted mode.
> 
> The aarch64 definition is redundant, but worth keeping for emphasis.
> 
> 
> 2019-08-19  Richard Sandiford  <richard.sandiford@arm.com>
> 
> gcc/
> 	* target.def (callee_copies): Take a function_arg_info instead
> 	of a mode, type and named flag.
> 	* doc/tm.texi: Regenerate.
> 	* targhooks.h (hook_callee_copies_named): Take a function_arg_info
> 	instead of a mode, type and named flag.
> 	(hook_bool_CUMULATIVE_ARGS_mode_tree_bool_false): Delete.
> 	(hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true): Likewise.
> 	(hook_bool_CUMULATIVE_ARGS_arg_info_true): New function.
> 	* targhooks.c (hook_callee_copies_named): Take a function_arg_info
> 	instead of a mode, type and named flag.
> 	(hook_bool_CUMULATIVE_ARGS_mode_tree_bool_false): Delete.
> 	(hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true): Likewise.
> 	(hook_bool_CUMULATIVE_ARGS_arg_info_true): New function.
> 	* calls.h (reference_callee_copied): Take a function_arg_info
> 	instead of a mode, type and named flag.
> 	* calls.c (reference_callee_copied): Likewise.
> 	(initialize_argument_information): Update call accordingly.
> 	(emit_library_call_value_1): Likewise.
> 	* function.c (gimplify_parameters): Likewise.
> 	* config/aarch64/aarch64.c (TARGET_CALLEE_COPIES): Define to
> 	hook_bool_CUMULATIVE_ARGS_arg_info_false instead of
> 	hook_bool_CUMULATIVE_ARGS_mode_tree_bool_false.
> 	* config/c6x/c6x.c (c6x_callee_copies): Delete.
> 	(TARGET_CALLEE_COPIES): Define to
> 	hook_bool_CUMULATIVE_ARGS_arg_info_true instead.
> 	* config/epiphany/epiphany.c (TARGET_CALLEE_COPIES): Define to
> 	hook_bool_CUMULATIVE_ARGS_arg_info_true instead of
> 	hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true.
> 	* config/mips/mips.c (mips_callee_copies): Take a function_arg_info
> 	instead of a mode, type and named flag.
> 	* config/mmix/mmix.c (TARGET_CALLEE_COPIES): Define to
> 	hook_bool_CUMULATIVE_ARGS_arg_info_true instead of
> 	hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true.
> 	* config/mn10300/mn10300.c (TARGET_CALLEE_COPIES): Likewise.
> 	* config/msp430/msp430.c (msp430_callee_copies): Delete.
> 	(TARGET_CALLEE_COPIES): Define to
> 	hook_bool_CUMULATIVE_ARGS_arg_info_true instead.
> 	* config/pa/pa.c (pa_callee_copies): Take a function_arg_info
> 	instead of a mode, type and named flag.
> 	* config/sh/sh.c (sh_callee_copies): Likewise.
> 	* config/v850/v850.c (TARGET_CALLEE_COPIES): Define to
> 	hook_bool_CUMULATIVE_ARGS_arg_info_true instead of
> 	hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true.
> 
OK
jeff

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [09/13] Use function_arg_info for TARGET_MUST_PASS_IN_STACK
  2019-08-19 15:24 ` [09/13] Use function_arg_info for TARGET_MUST_PASS_IN_STACK Richard Sandiford
@ 2019-08-19 22:04   ` Jeff Law
  0 siblings, 0 replies; 27+ messages in thread
From: Jeff Law @ 2019-08-19 22:04 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

On 8/19/19 9:20 AM, Richard Sandiford wrote:
> Use function_arg_info for TARGET_MUST_PASS_IN_STACK.
> 
> The hook is passed the promoted mode instead of the original type mode.
> 
> The expr.h reference in the documentation is no longer correct, but
> pointing to calls.h or calls.c doesn't help much either.  I just left
> this as-is since it's not related to the point of the series.
> 
> After previous changes, most places already pass arg.mode and arg.type.
> Only i386 and mcore needed to construct a new one out of nothing.
> rs6000 needs to construct one slightly earlier than before.
> 
> 
> 2019-08-19  Richard Sandiford  <richard.sandiford@arm.com>
> 
> gcc/
> 	* target.def (must_pass_in_stack): Take a function_arg_info instead
> 	of a mode and a type.
> 	* doc/tm.texi: Regenerate.
> 	* calls.h (must_pass_in_stack_var_size): Take a function_arg_info
> 	instead of a mode and a type.
> 	(must_pass_in_stack_var_size_or_pad): Likewise.
> 	* calls.c (must_pass_in_stack_var_size): Likewise.
> 	(must_pass_in_stack_var_size_or_pad): Likewise.
> 	(initialize_argument_information): Update call to
> 	targetm.calls.must_pass_in_stack.
> 	(must_pass_va_arg_on_stack): Likewise.
> 	* function.c (assign_parm_find_entry_rtl): Likewise.
> 	* targhooks.c (hook_pass_by_reference_must_pass_in_stack): Likewise.
> 	* config/alpha/alpha.c (alpha_function_arg): Likewise.
> 	(alpha_function_arg_advance): Likewise.
> 	* config/cr16/cr16.c (cr16_function_arg): Likewise.
> 	(cr16_function_arg_advance): Likewise.
> 	* config/cris/cris.c (cris_pass_by_reference): Likewise.
> 	(cris_arg_partial_bytes): Likewise.
> 	* config/iq2000/iq2000.c (iq2000_pass_by_reference): Likewise.
> 	* config/lm32/lm32.c (lm32_function_arg): Likewise.
> 	* config/mcore/mcore.c (mcore_num_arg_regs): Likewise.
> 	(mcore_function_arg, mcore_arg_partial_bytes): Likewise.
> 	* config/mips/mips.c (mips_pass_by_reference): Likewise.
> 	* config/mmix/mmix.c (mmix_function_arg_advance): Likewise.
> 	(mmix_function_arg_1, mmix_pass_by_reference): Likewise.
> 	* config/sh/sh.c (sh_pass_by_reference): Likewise.
> 	* config/stormy16/stormy16.c (xstormy16_function_arg): Likewise.
> 	* config/xtensa/xtensa.c (xtensa_function_arg_advance): Likewise.
> 	* config/arm/arm.c (arm_must_pass_in_stack): Take a function_arg_info
> 	instead of a mode and a type.
> 	* config/fr30/fr30.c (fr30_must_pass_in_stack): Likewise.
> 	(fr30_num_arg_regs): Likewise.
> 	(fr30_setup_incoming_varargs): Update calls accordingly.
> 	(fr30_arg_partial_bytes, fr30_function_arg): Likewise.
> 	(fr30_function_arg_advance): Likewise.
> 	* config/frv/frv.c (frv_must_pass_in_stack): Take a function_arg_info
> 	instead of a mode and a type.
> 	* config/gcn/gcn.c (num_arg_regs): Likewise.
> 	(gcn_function_arg, gcn_function_arg_advance): Update calls to
> 	num_arg_regs and targetm.calls.must_pass_in_stack.
> 	(gcn_arg_partial_bytes): Likewise.
> 	* config/i386/i386.c (ix86_must_pass_in_stack): Take a
> 	function_arg_info instead of a mode and a type.
> 	(classify_argument): Update call accordingly.
> 	* config/nds32/nds32.c (nds32_must_pass_in_stack): Take a
> 	function_arg_info instead of a mode and a type.
> 	* config/rs6000/rs6000-internal.h (rs6000_must_pass_in_stack):
> 	Likewise.
> 	* config/rs6000/rs6000-call.c (rs6000_must_pass_in_stack): Likewise.
> 	(rs6000_parm_needs_stack): Update call accordingly.
> 	(setup_incoming_varargs): Likewise.
> 
OK
jeff

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [10/13] Add a apply_pass_by_reference_rules helper
  2019-08-19 15:47 ` [10/13] Add a apply_pass_by_reference_rules helper Richard Sandiford
@ 2019-08-19 22:19   ` Jeff Law
  0 siblings, 0 replies; 27+ messages in thread
From: Jeff Law @ 2019-08-19 22:19 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

On 8/19/19 9:21 AM, Richard Sandiford wrote:
> This patch adds a helper routine that applies pass-by-reference
> semantics to an existing function_arg_info.
> 
> The c6x part means that c6x_function_arg and c6x_function_arg_advance
> see the same "named" value as pass_by_reference did, rather than
> pass_by_reference seeing "true" and the others seeing "false".
> This doesn't matter because the c6x port doesn't care about namedness.
> 
> The rs6000.c patch removes an assignment to "type", but the only
> later code to use it was the patched promote_mode line.
> 
> (The reason for patching these places despite the above is that
> often target code gets used as a basis for new targets or changes
> to existing ones.)
> 
> 
> 2019-08-19  Richard Sandiford  <richard.sandiford@arm.com>
> 
> gcc/
> 	* 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.
> 
OK
jeff

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [11/13] Make function.c use function_arg_info internally
  2019-08-19 15:51 ` [11/13] Make function.c use function_arg_info internally Richard Sandiford
@ 2019-08-19 22:47   ` Jeff Law
  0 siblings, 0 replies; 27+ messages in thread
From: Jeff Law @ 2019-08-19 22:47 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

On 8/19/19 9:22 AM, Richard Sandiford wrote:
> This patch adds a function_arg_info field to assign_parm_data_one,
> so that:
> 
>   - passed_type -> arg.type
>   - promoted_mode -> arg.mode
>   - named_arg -> arg.named
> 
> We can then pass this function_arg_info directly to the converted
> hooks.
> 
> Between the initialisation of the assign_parm_data_one and the
> application of promotion rules (which is a state internal to
> assign_parm_find_data_types), arg.mode is equivalent to passed_mode
> (i.e. to TYPE_MODE).
> 
> 
> 2019-08-19  Richard Sandiford  <richard.sandiford@arm.com>
> 
> gcc/
> 	* function.c (assign_parm_data_one): Replace passed_type,
> 	promoted_mode and named_arg with a function_arg_info field.
> 	(assign_parm_find_data_types): Remove local variables and
> 	assign directly to "data".  Make data->passed_mode shadow
> 	data->arg.mode until promotion, then assign the promoted
> 	mode to data->arg.mode.
> 	(assign_parms_setup_varargs, assign_parm_find_entry_rtl)
> 	(assign_parm_find_stack_rtl, assign_parm_adjust_entry_rtl)
> 	(assign_parm_remove_parallels, assign_parm_setup_block_p)
> 	(assign_parm_setup_block, assign_parm_setup_reg)
> 	(assign_parm_setup_stack, assign_parms, gimplify_parameters): Use
> 	arg.mode instead of promoted_mode, arg.type instead of passed_type
> 	and arg.named instead of named_arg.  Use data->arg for
> 	function_arg_info structures that had the field values passed_type,
> 	promoted_mode and named_arg.  Base other function_arg_infos on
> 	data->arg, changing the necessary properties.
OK
jeff

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [12/13] Make calls.c use function_arg_info internally
  2019-08-19 15:52 ` [12/13] Make calls.c " Richard Sandiford
@ 2019-08-19 22:49   ` Jeff Law
  0 siblings, 0 replies; 27+ messages in thread
From: Jeff Law @ 2019-08-19 22:49 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

On 8/19/19 9:23 AM, Richard Sandiford wrote:
> This patch makes the two main calls.c argument-processing
> routines track the state of the argument in a function_arg_info
> instead of using separate mode variables.
> 
> 
> 2019-08-19  Richard Sandiford  <richard.sandiford@arm.com>
> 
> gcc/
> 	* calls.c (emit_library_call_value_1): Merge arg and orig_arg
> 	into a single function_arg_info, updating its fields when we
> 	apply pass-by-reference and promotion semantics.  Use the
> 	function_arg_info to track the mode rather than keeping it in
> 	a separate local variable.
> 	(initialize_argument_information): Likewise.  Base the final
> 	arg_to_skip on this new function_arg_info rather than creating
> 	a new one from scratch.
> 
OK
jeff

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [13/13] Add a pass_by_reference flag to function_arg_info
  2019-08-19 15:52 ` [13/13] Add a pass_by_reference flag to function_arg_info Richard Sandiford
@ 2019-08-19 22:54   ` Jeff Law
  0 siblings, 0 replies; 27+ messages in thread
From: Jeff Law @ 2019-08-19 22:54 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

On 8/19/19 9:24 AM, Richard Sandiford wrote:
> This patch adds a flag that tells targets whether an argument
> has been converted to pass-by-reference form.  This replaces
> assign_parm_data_one::passed_pointer in function.c.
> 
> The flag is set automatically for places that call
> apply_pass_by_reference_rules.  Places that apply
> pass-by-reference manually need to set it themselves.
> 
> (After previous changes, no targets apply pass-by-reference
> manually.  They all go through apply_pass_by_reference_rules.)
> 
> 
> 2019-08-19  Richard Sandiford  <richard.sandiford@arm.com>
> 
> gcc/
> 	* calls.h (function_arg_info): Add a pass_by_reference field,
> 	defaulting to false.
> 	* calls.c (apply_pass_by_reference_rules): Set pass_by_reference
> 	when applying pass-by-reference semantics.
> 	(initialize_argument_information): Likewise.
> 	(emit_library_call_value_1): Likewise.
> 	* function.c (assign_parm_data_one): Remove passed_pointer field.
> 	(assign_parm_find_data_types): Don't set it.
> 	(assign_parm_find_stack_rtl, assign_parm_adjust_stack_rtl)
> 	(assign_parm_setup_reg, assign_parms, gimplify_parameters): Use
> 	arg.pass_by_reference instead of passed_pointer.
> 
OK.  I think that's the whole series.  I don't expect any problems, but
my tester will pick testing across the various targets ~24hrs after
you've committed the changes.

jeff

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2019-08-19 22:22 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-19 15:15 [00/13] Pass an argument descriptor to target hooks Richard Sandiford
2019-08-19 15:16 ` [01/13] Add pass_va_arg_by_reference Richard Sandiford
2019-08-19 20:04   ` Jeff Law
2019-08-19 15:17 ` [02/13] Add must_pass_va_arg_in_stack Richard Sandiford
2019-08-19 20:05   ` Jeff Law
2019-08-19 15:18 ` [03/13] Use function_arg_info for TARGET_ARG_PARTIAL_BYTES Richard Sandiford
2019-08-19 20:42   ` Jeff Law
2019-08-19 15:19 ` [04/13] Use function_arg_info for TARGET_PASS_BY_REFERENCE Richard Sandiford
2019-08-19 20:43   ` Jeff Law
2019-08-19 15:20 ` [05/13] Use function_arg_info for TARGET_SETUP_INCOMING_ARGS Richard Sandiford
2019-08-19 20:50   ` Jeff Law
2019-08-19 15:21 ` [06/13] Use function_arg_info for TARGET_FUNCTION_(INCOMING_)ARG Richard Sandiford
2019-08-19 21:07   ` Jeff Law
2019-08-19 15:22 ` [07/13] Use function_arg_info for TARGET_FUNCTION_ARG_ADVANCE Richard Sandiford
2019-08-19 21:11   ` Jeff Law
2019-08-19 15:23 ` [08/13] Use function_arg_info for TARGET_CALLEE_COPIES Richard Sandiford
2019-08-19 21:16   ` Jeff Law
2019-08-19 15:24 ` [09/13] Use function_arg_info for TARGET_MUST_PASS_IN_STACK Richard Sandiford
2019-08-19 22:04   ` Jeff Law
2019-08-19 15:47 ` [10/13] Add a apply_pass_by_reference_rules helper Richard Sandiford
2019-08-19 22:19   ` Jeff Law
2019-08-19 15:51 ` [11/13] Make function.c use function_arg_info internally Richard Sandiford
2019-08-19 22:47   ` Jeff Law
2019-08-19 15:52 ` [12/13] Make calls.c " Richard Sandiford
2019-08-19 22:49   ` Jeff Law
2019-08-19 15:52 ` [13/13] Add a pass_by_reference flag to function_arg_info Richard Sandiford
2019-08-19 22:54   ` Jeff Law

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).