aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorChung-Ju Wu <jasonwucj@gmail.com>2014-09-03 09:55:28 +0000
committerChung-Ju Wu <jasonwucj@gcc.gnu.org>2014-09-03 09:55:28 +0000
commit7f6cd86bef0d942ca6e4d7a38f942cd38daaff95 (patch)
tree84c7d09e05d0df11d11b81726f282263ee893fbf /gcc
parent52e4630c51f511137b0018fe9f5661182fd5e668 (diff)
downloadgcc-7f6cd86bef0d942ca6e4d7a38f942cd38daaff95.zip
gcc-7f6cd86bef0d942ca6e4d7a38f942cd38daaff95.tar.gz
gcc-7f6cd86bef0d942ca6e4d7a38f942cd38daaff95.tar.bz2
[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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/config/nds32/nds32.c95
-rw-r--r--gcc/config/nds32/nds32.h18
3 files changed, 99 insertions, 23 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9f0828f..d91d826 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/config/nds32/nds32.c b/gcc/config/nds32/nds32.c
index 5fbdac8..509b4a5 100644
--- a/gcc/config/nds32/nds32.c
+++ b/gcc/config/nds32/nds32.c
@@ -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);
+ }
}
}
diff --git a/gcc/config/nds32/nds32.h b/gcc/config/nds32/nds32.h
index d3336b6..920b992 100644
--- a/gcc/config/nds32/nds32.h
+++ b/gcc/config/nds32/nds32.h
@@ -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.