[06/13] Use function_arg_info for TARGET_FUNCTION_(INCOMING_)ARG
diff mbox series

Message ID mpt7e79chi1.fsf@arm.com
State New
Headers show
Series
  • Pass an argument descriptor to target hooks
Related show

Commit Message

Richard Sandiford Aug. 19, 2019, 3:16 p.m. UTC
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.

Comments

Jeff Law Aug. 19, 2019, 8:32 p.m. UTC | #1
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

Patch
diff mbox series

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);
 }
 
 
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