An old itch being scratched: the documentation lies; it's not "the number of registers used as operands", unless the target makes a special arrangement to that effect, and there's nothing in the guts of gcc setting up or assuming those semantics.
Instead, see calls.c:expand_call, variable next_arg_reg. Or just consider the variable name. The text is somewhat transcribed from the head comment of emit_call_1 for parameter next_arg_reg. Most important is to document the relation to function_arg_info::end_marker() and the TARGET_FUNCTION_ARG hook. The "normally" in the head comment, in "normally it is the first arg-register beyond those used for args in this call, or 0 if all the arg-registers are used in this call" means "by default", unless the target tests end_marker_p and does something special, but the port is free to return whatever it likes when it sees the end-marker. And, I do mean "whatever it likes" because if the port doesn't actually mention that operand in the RTX emitted for its "call" or "call_value" patterns ("usually" define_expands), it can be any mumbo-jumbo, such as a VOIDmode register, which seems like it happens for some targets, or NULL, that happens for others. Returning a VOIDmode register until recently included MMIX, where it made it into the emitted RTL, confusing later passes, recently exposed as an ICE. Tested by inspecting the info and generated pdf for sanity. Ok for the doc part? gcc: * doc/md.texi (call): Correct information about operand 2. * config/mmix/mmix.md ("call", "call_value"): Remove fixed FIXMEs. --- gcc/config/mmix/mmix.md | 12 +++--------- gcc/doc/md.texi | 8 ++++++-- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 07681e2ad292..f6d1bc1ad0f7 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -7048,8 +7048,12 @@ machines. @item @samp{call} Subroutine call instruction returning no value. Operand 0 is the function to call; operand 1 is the number of bytes of arguments pushed -as a @code{const_int}; operand 2 is the number of registers used as -operands. +as a @code{const_int}. Operand 2 is the result of calling the target +hook @code{TARGET_FUNCTION_ARG} with the second argument @code{arg} +yielding true for @code{arg.end_marker_p ()}, in a call after all +parameters have been passed to that hook. By default this is the first +register beyond those used for arguments in the call, or @code{NULL} if +all the argument-registers are used in the call. On most machines, operand 2 is not actually stored into the RTL pattern. It is supplied for the sake of some RISC machines which need diff --git a/gcc/config/mmix/mmix.md b/gcc/config/mmix/mmix.md index a6d7608ef50c..33e9c60982d6 100644 --- a/gcc/config/mmix/mmix.md +++ b/gcc/config/mmix/mmix.md @@ -999,10 +999,8 @@ (define_expand "call" = mmix_get_hard_reg_initial_val (Pmode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM); - /* FIXME: There's a bug in gcc which causes NULL to be passed as - operand[2] when we get out of registers, which later confuses gcc. - Work around it by replacing it with const_int 0. Possibly documentation - error too. */ + /* NULL gets passed as operand[2] when we get out of registers, + which later confuses gcc. Replace it with const_int 0. */ if (operands[2] == NULL_RTX) operands[2] = const0_rtx; @@ -1036,14 +1034,10 @@ (define_expand "call_value" = mmix_get_hard_reg_initial_val (Pmode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM); - /* FIXME: See 'call'. */ + /* See 'call'. */ if (operands[3] == NULL_RTX) operands[3] = const0_rtx; - /* FIXME: Documentation bug: operands[3] (operands[2] for 'call') is the - *next* argument register, not the number of arguments in registers. - (There used to be code here where that mattered.) */ - operands[5] = gen_rtx_REG (DImode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM); }") -- 2.20.1