[NDS32] Deal with nameless arguments in nds32_function_arg and nds32_function_arg_adv...
authorChung-Ju Wu <jasonwucj@gmail.com>
Wed, 3 Sep 2014 09:55:28 +0000 (09:55 +0000)
committerChung-Ju Wu <jasonwucj@gcc.gnu.org>
Wed, 3 Sep 2014 09:55:28 +0000 (09:55 +0000)
  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

gcc/ChangeLog
gcc/config/nds32/nds32.c
gcc/config/nds32/nds32.h

index 9f0828fe48e8f140b239df62cc36eeef29c5ce6d..d91d826c97579eb3546547ca6f30ccea49a996e1 100644 (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.
index 5fbdac869d27d5cefafc5c232ae2cb294d389a84..509b4a5bfc519ab142cd71d2a609bf7126866963 100644 (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);
+       }
     }
 }
 
index d3336b6be13ead43efb398ec0e63d89283520ce8..920b992b1ca9e0ba19c42213193e57dc5a45ad0e 100644 (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.