[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:
parent
52e4630c51
commit
7f6cd86bef
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user