[NDS32] Deal with nameless arguments in nds32_function_arg and nds32_function_arg_advance.

1. We have caller prepare nameless arguments in the way of calling a normal function.

     e.g. Assume a function: void va_test (int n, ...);
          When calling "va_test (6, 11, 22, 33, 44, 55, 66);",
               r0    <- 6
               r1    <- 11
               r2    <- 22
               r3    <- 33
               r4    <- 44
               r5    <- 55
            [sp + 0] <- 66

  2. Note that we DO NOT handle it for TARGET_HARD_FLOAT case.
     The TARGET_HARD_FLOAT should push all the nameless arguments into
     stack and GCC is able to take care of them itself.
     In addition, we have not implemented hard float on trunk yet.

	* config/nds32/nds32.c (nds32_function_arg): Deal with nameless
	arguments.
	(nds32_function_arg_advance): Deal with nameless arguments.
	* config/nds32/nds32.h (NDS32_ARG_PASS_IN_REG_P): Split it into ...
	(NDS32_ARG_ENTIRE_IN_GPR_REG_P): ... this one and ...
	(NDS32_ARG_PARTIAL_IN_GPR_REG_P): ... this one.

From-SVN: r214865
This commit is contained in:
Chung-Ju Wu 2014-09-03 09:55:28 +00:00 committed by Chung-Ju Wu
parent 52e4630c51
commit 7f6cd86bef
3 changed files with 99 additions and 23 deletions

View File

@ -1,3 +1,12 @@
2014-09-03 Chung-Ju Wu <jasonwucj@gmail.com>
* config/nds32/nds32.c (nds32_function_arg): Deal with nameless
arguments.
(nds32_function_arg_advance): Deal with nameless arguments.
* config/nds32/nds32.h (NDS32_ARG_PASS_IN_REG_P): Split it into ...
(NDS32_ARG_ENTIRE_IN_GPR_REG_P): ... this one and ...
(NDS32_ARG_PARTIAL_IN_GPR_REG_P): ... this one.
2014-09-03 Richard Biener <rguenther@suse.de>
* tree-ssa-pre.c (alloc_expression_id): Use quick_grow_cleared.

View File

@ -1294,6 +1294,7 @@ static rtx
nds32_function_arg (cumulative_args_t ca, enum machine_mode mode,
const_tree type, bool named)
{
unsigned int regno;
CUMULATIVE_ARGS *cum = get_cumulative_args (ca);
/* The last time this hook is called,
@ -1301,41 +1302,99 @@ nds32_function_arg (cumulative_args_t ca, enum machine_mode mode,
if (mode == VOIDmode)
return NULL_RTX;
/* For nameless arguments, they are passed on the stack. */
/* For nameless arguments, we need to take care it individually. */
if (!named)
return NULL_RTX;
/* If there are still registers available, return it. */
if (NDS32_ARG_PASS_IN_REG_P (cum->gpr_offset, mode, type))
{
/* Pick up the next available register number. */
unsigned int regno;
/* If we are under hard float abi, we have arguments passed on the
stack and all situation can be handled by GCC itself. */
if (TARGET_HARD_FLOAT)
return NULL_RTX;
if (NDS32_ARG_PARTIAL_IN_GPR_REG_P (cum->gpr_offset, mode, type))
{
/* If we still have enough registers to pass argument, pick up
next available register number. */
regno
= NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, mode, type);
return gen_rtx_REG (mode, regno);
}
regno = NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, mode, type);
return gen_rtx_REG (mode, regno);
}
else
{
/* No register available, return NULL_RTX.
The compiler will use stack to pass argument instead. */
return NULL_RTX;
}
/* The following is to handle named argument.
Note that the strategies of TARGET_HARD_FLOAT and !TARGET_HARD_FLOAT
are different. */
if (TARGET_HARD_FLOAT)
{
/* Currently we have not implemented hard float yet. */
gcc_unreachable ();
}
else
{
/* For !TARGET_HARD_FLOAT calling convention, we always use GPR to pass
argument. Since we allow to pass argument partially in registers,
we can just return it if there are still registers available. */
if (NDS32_ARG_PARTIAL_IN_GPR_REG_P (cum->gpr_offset, mode, type))
{
/* Pick up the next available register number. */
regno
= NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, mode, type);
return gen_rtx_REG (mode, regno);
}
}
/* No register available, return NULL_RTX.
The compiler will use stack to pass argument instead. */
return NULL_RTX;
}
static void
nds32_function_arg_advance (cumulative_args_t ca, enum machine_mode mode,
const_tree type, bool named)
{
enum machine_mode sub_mode;
CUMULATIVE_ARGS *cum = get_cumulative_args (ca);
/* Advance next register for use.
Only named argument could be advanced. */
if (named)
{
cum->gpr_offset
= NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, mode, type)
- NDS32_GPR_ARG_FIRST_REGNUM
+ NDS32_NEED_N_REGS_FOR_ARG (mode, type);
/* We need to further check TYPE and MODE so that we can determine
which kind of register we shall advance. */
if (type && TREE_CODE (type) == COMPLEX_TYPE)
sub_mode = TYPE_MODE (TREE_TYPE (type));
else
sub_mode = mode;
/* Under hard float abi, we may advance FPR registers. */
if (TARGET_HARD_FLOAT && GET_MODE_CLASS (sub_mode) == MODE_FLOAT)
{
/* Currently we have not implemented hard float yet. */
gcc_unreachable ();
}
else
{
cum->gpr_offset
= NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, mode, type)
- NDS32_GPR_ARG_FIRST_REGNUM
+ NDS32_NEED_N_REGS_FOR_ARG (mode, type);
}
}
else
{
/* If this nameless argument is NOT under TARGET_HARD_FLOAT,
we can advance next register as well so that caller is
able to pass arguments in registers and callee must be
in charge of pushing all of them into stack. */
if (!TARGET_HARD_FLOAT)
{
cum->gpr_offset
= NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, mode, type)
- NDS32_GPR_ARG_FIRST_REGNUM
+ NDS32_NEED_N_REGS_FOR_ARG (mode, type);
}
}
}

View File

@ -166,11 +166,19 @@ enum nds32_16bit_address_type
: ((reg_offset) + NDS32_GPR_ARG_FIRST_REGNUM))
/* This macro is to check if there are still available registers
for passing argument. */
#define NDS32_ARG_PASS_IN_REG_P(reg_offset, mode, type) \
(((reg_offset) < NDS32_MAX_GPR_REGS_FOR_ARGS) \
&& ((reg_offset) + NDS32_NEED_N_REGS_FOR_ARG (mode, type) \
<= NDS32_MAX_GPR_REGS_FOR_ARGS))
for passing argument, which must be entirely in registers. */
#define NDS32_ARG_ENTIRE_IN_GPR_REG_P(reg_offset, mode, type) \
((NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (reg_offset, mode, type) \
+ NDS32_NEED_N_REGS_FOR_ARG (mode, type)) \
<= (NDS32_GPR_ARG_FIRST_REGNUM \
+ NDS32_MAX_GPR_REGS_FOR_ARGS))
/* This macro is to check if there are still available registers
for passing argument, either entirely in registers or partially
in registers. */
#define NDS32_ARG_PARTIAL_IN_GPR_REG_P(reg_offset, mode, type) \
(NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (reg_offset, mode, type) \
< NDS32_GPR_ARG_FIRST_REGNUM + NDS32_MAX_GPR_REGS_FOR_ARGS)
/* This macro is to check if the register is required to be saved on stack.
If call_used_regs[regno] == 0, regno is the callee-saved register.