sparc-protos.h (sparc_skip_caller_unimp): New declaration.
authorEric Botcazou <ebotcazou@act-europe.fr>
Fri, 7 May 2004 11:40:42 +0000 (13:40 +0200)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Fri, 7 May 2004 11:40:42 +0000 (11:40 +0000)
* config/sparc/sparc-protos.h (sparc_skip_caller_unimp): New
declaration.
* config/sparc/sparc.c (SKIP_CALLERS_UNIMP_P): Delete.
(sparc_skip_caller_unimp): New global variable.
(sparc_function_epilogue): Set 'sparc_skip_caller_unimp'.
Use it instead of SKIP_CALLERS_UNIMP_P.
* config/sparc/sparc.md (call expander): Add sanity check.
(call_address_struct_value_sp32): Re-sync with expander.
(call_symbolic_struct_value_sp32): Likewise.
(return peepholes): Use 'sparc_skip_caller_unimp' instead
of custom predicate.

From-SVN: r81617

gcc/ChangeLog
gcc/config/sparc/sparc-protos.h
gcc/config/sparc/sparc.c
gcc/config/sparc/sparc.md

index edad48cad9db0da84296a53e0f5b578a796e5508..a4e9863953889631e913fd9fca37bdbc3dbfc539 100644 (file)
@@ -1,3 +1,17 @@
+2004-05-07  Eric Botcazou  <ebotcazou@act-europe.fr>
+
+       * config/sparc/sparc-protos.h (sparc_skip_caller_unimp): New
+       declaration.
+       * config/sparc/sparc.c (SKIP_CALLERS_UNIMP_P): Delete.
+       (sparc_skip_caller_unimp): New global variable.
+       (sparc_function_epilogue): Set 'sparc_skip_caller_unimp'.
+       Use it instead of SKIP_CALLERS_UNIMP_P.
+       * config/sparc/sparc.md (call expander): Add sanity check.
+       (call_address_struct_value_sp32): Re-sync with expander.
+       (call_symbolic_struct_value_sp32): Likewise.
+       (return peepholes): Use 'sparc_skip_caller_unimp' instead
+       of custom predicate.
+
 2004-05-07  Eric Botcazou  <ebotcazou@libertysurf.fr>
 
        PR c++/14962
index 0908aaa5ea58f53ffbbfa0c8ad01c31ec539b4e2..4b1f9f0d3bebfeb7f1b0757735b9fd743b796550 100644 (file)
@@ -25,6 +25,7 @@ Boston, MA 02111-1307, USA.  */
 #define __SPARC_PROTOS_H__
 
 extern bool sparc_emitting_epilogue;
+extern bool sparc_skip_caller_unimp;
 
 #ifdef TREE_CODE
 extern struct rtx_def *function_value (tree, enum machine_mode, int);
index 76ccb34eade3ee4c5571e6c2990d4c3a5b73d68d..2192d96722447a35d05cae720a9d19880f0fbca7 100644 (file)
@@ -48,17 +48,6 @@ Boston, MA 02111-1307, USA.  */
 #include "target-def.h"
 #include "cfglayout.h"
 
-/* 1 if the caller has placed an "unimp" insn immediately after the call.
-   This is used in v8 code when calling a function that returns a structure.
-   v9 doesn't have this.  Be careful to have this test be the same as that
-   used on the call.  */
-
-#define SKIP_CALLERS_UNIMP_P  \
-(!TARGET_ARCH64 && current_function_returns_struct                     \
- && ! integer_zerop (DECL_SIZE (DECL_RESULT (current_function_decl)))  \
- && (TREE_CODE (DECL_SIZE (DECL_RESULT (current_function_decl)))       \
-     == INTEGER_CST))
-
 /* Global variables for machine-dependent things.  */
 
 /* Size of frame.  Need to know this to emit return insns from leaf procedures.
@@ -81,6 +70,7 @@ rtx sparc_compare_op0, sparc_compare_op1;
 /* Coordinate with the md file wrt special insns created by
    sparc_function_epilogue.  */
 bool sparc_emitting_epilogue;
+bool sparc_skip_caller_unimp;
 
 /* Vector to say how input registers are mapped to output registers.
    HARD_FRAME_POINTER_REGNUM cannot be remapped by this function to
@@ -4498,6 +4488,17 @@ sparc_function_epilogue (FILE *file,
 {
   const char *ret;
 
+  /* True if the caller has placed an "unimp" insn immediately after the call.
+     This insn is used in the 32-bit ABI when calling a function that returns
+     a non zero-sized structure. The 64-bit ABI doesn't have it.  Be careful
+     to have this test be the same as that used on the call.  */
+  sparc_skip_caller_unimp =
+    ! TARGET_ARCH64
+    && current_function_returns_struct
+    && (TREE_CODE (DECL_SIZE (DECL_RESULT (current_function_decl)))
+       == INTEGER_CST)
+    && ! integer_zerop (DECL_SIZE (DECL_RESULT (current_function_decl)));
+
   if (current_function_epilogue_delay_list == 0)
     {
       /* If code does not drop into the epilogue, we need
@@ -4532,9 +4533,9 @@ sparc_function_epilogue (FILE *file,
 
   /* Work out how to skip the caller's unimp instruction if required.  */
   if (leaf_function)
-    ret = (SKIP_CALLERS_UNIMP_P ? "jmp\t%o7+12" : "retl");
+    ret = (sparc_skip_caller_unimp ? "jmp\t%o7+12" : "retl");
   else
-    ret = (SKIP_CALLERS_UNIMP_P ? "jmp\t%i7+12" : "ret");
+    ret = (sparc_skip_caller_unimp ? "jmp\t%i7+12" : "ret");
 
   if (! leaf_function)
     {
@@ -4542,7 +4543,7 @@ sparc_function_epilogue (FILE *file,
        {
          if (current_function_epilogue_delay_list)
            abort ();
-         if (SKIP_CALLERS_UNIMP_P)
+         if (sparc_skip_caller_unimp)
            abort ();
 
          fputs ("\trestore\n\tretl\n\tadd\t%sp, %g1, %sp\n", file);
@@ -4555,7 +4556,7 @@ sparc_function_epilogue (FILE *file,
          if (TARGET_V9 && ! epilogue_renumber (&delay, 1))
            {
              epilogue_renumber (&delay, 0);
-             fputs (SKIP_CALLERS_UNIMP_P
+             fputs (sparc_skip_caller_unimp
                     ? "\treturn\t%i7+12\n"
                     : "\treturn\t%i7+8\n", file);
              final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),
@@ -4588,7 +4589,7 @@ sparc_function_epilogue (FILE *file,
              sparc_emitting_epilogue = false;
            }
        }
-      else if (TARGET_V9 && ! SKIP_CALLERS_UNIMP_P)
+      else if (TARGET_V9 && ! sparc_skip_caller_unimp)
        fputs ("\treturn\t%i7+8\n\tnop\n", file);
       else
        fprintf (file, "\t%s\n\trestore\n", ret);
index 2c388f99c8a7207fd85ede4f7827f511015172b7..130d58c84f8e87c66e51110e6f9507b4101675ea 100644 (file)
 {
   rtx fn_rtx;
 
-   if (GET_MODE (operands[0]) != FUNCTION_MODE)
+  if (GET_MODE (operands[0]) != FUNCTION_MODE)
     abort ();
 
+  if (GET_CODE (operands[3]) != CONST_INT)
+    abort();
+
   if (GET_CODE (XEXP (operands[0], 0)) == LABEL_REF)
     {
       /* This is really a PIC sequence.  We want to represent
         call-clobbered registers?  We lose this if it is a JUMP_INSN.
         Why cannot we have delay slots filled if it were a CALL?  */
 
+      /* We accept negative sizes for untyped calls.  */
       if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0)
        emit_jump_insn
          (gen_rtx_PARALLEL
 
   fn_rtx = operands[0];
 
+  /* We accept negative sizes for untyped calls.  */
   if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0)
     emit_call_insn
       (gen_rtx_PARALLEL
    (match_operand 2 "immediate_operand" "")
    (clobber (reg:SI 15))]
   ;;- Do not use operand 1 for most machines.
-  "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
+  "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 0"
   "call\t%a0, %1\n\tnop\n\tunimp\t%2"
   [(set_attr "type" "call_no_delay_slot")
    (set_attr "length" "3")])
    (match_operand 2 "immediate_operand" "")
    (clobber (reg:SI 15))]
   ;;- Do not use operand 1 for most machines.
-  "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
+  "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 0"
   "call\t%a0, %1\n\tnop\n\tunimp\t%2"
   [(set_attr "type" "call_no_delay_slot")
    (set_attr "length" "3")])
   [(set_attr "type" "call_no_delay_slot")
    (set_attr "length" "3")])
 
-;; This is a call that wants a structure value.
+;; This is a call that may want a structure value.  This is used for
+;; untyped_calls.
 (define_insn "*call_symbolic_untyped_struct_value_sp32"
   [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
         (match_operand 1 "" ""))
    (return)]
   "sparc_emitting_epilogue"
 {
-  if (! TARGET_ARCH64 && current_function_returns_struct)
+  if (sparc_skip_caller_unimp)
     return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
   else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
                         || IN_OR_GLOBAL_P (operands[1])))
    (return)]
   "sparc_emitting_epilogue"
 {
-  if (! TARGET_ARCH64 && current_function_returns_struct)
+  if (sparc_skip_caller_unimp)
     return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
   else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
                         || IN_OR_GLOBAL_P (operands[1])))
    (return)]
   "sparc_emitting_epilogue"
 {
-  if (! TARGET_ARCH64 && current_function_returns_struct)
+  if (sparc_skip_caller_unimp)
     return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
   else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
                         || IN_OR_GLOBAL_P (operands[1])))
    (return)]
   "sparc_emitting_epilogue"
 {
-  if (! TARGET_ARCH64 && current_function_returns_struct)
+  if (sparc_skip_caller_unimp)
     return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
   else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1]))
     return "return\t%%i7+8\n\tmov\t%Y1, %Y0";
    (return)]
   "sparc_emitting_epilogue"
 {
-  if (! TARGET_ARCH64 && current_function_returns_struct)
+  if (sparc_skip_caller_unimp)
     return "jmp\t%%i7+12\n\trestore %r1, %2, %Y0";
   /* If operands are global or in registers, can use return */
   else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1])
    (return)]
   "sparc_emitting_epilogue && ! TARGET_CM_MEDMID"
 {
-  if (! TARGET_ARCH64 && current_function_returns_struct)
+  if (sparc_skip_caller_unimp)
     return "jmp\t%%i7+12\n\trestore %r1, %%lo(%a2), %Y0";
   /* If operands are global or in registers, can use return */
   else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1]))