From 74022996bccc6fac0c6227649fafadb57d3d07a2 Mon Sep 17 00:00:00 2001 From: jasonwucj Date: Wed, 3 Sep 2014 09:55:28 +0000 Subject: [PATCH] [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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@214865 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 9 +++++ gcc/config/nds32/nds32.c | 95 +++++++++++++++++++++++++++++++++++++++--------- gcc/config/nds32/nds32.h | 18 ++++++--- 3 files changed, 99 insertions(+), 23 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9f0828fe48e..d91d826c975 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2014-09-03 Chung-Ju Wu + + * 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 * 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 5fbdac869d2..509b4a5bfc5 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 d3336b6be13..920b992b1ca 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. -- 2.11.4.GIT