re PR target/63668 (-mstd-struct-return fails for non-leaf functions)
authorEric Botcazou <ebotcazou@gcc.gnu.org>
Mon, 7 Dec 2015 23:18:29 +0000 (23:18 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Mon, 7 Dec 2015 23:18:29 +0000 (23:18 +0000)
PR target/63668
* doc/invoke.texi (SPARC options): Document -mstd-struct-return.
* config/sparc/sparc.c (sparc_struct_value_rtx): Minor tweaks.
* config/sparc/sparc.h (CALL_REALLY_USED_REGISTERS): Define.
* config/sparc/sparc.opt (mstd-struct-return): Accept negative form.

From-SVN: r231387

gcc/ChangeLog
gcc/config/sparc/sparc.c
gcc/config/sparc/sparc.h
gcc/config/sparc/sparc.opt
gcc/doc/invoke.texi
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/sparc/struct-ret-check-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/sparc/struct-ret-check-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/sparc/struct-ret-check.c [deleted file]

index ade56278e4bcd0ae8bfc42d14896c16f058f1ff9..f6f3ff5723192b60e0c75f2f3eb171e1f1c47f5b 100644 (file)
@@ -1,3 +1,11 @@
+2015-12-07  Eric Botcazou  <ebotcazou@adacore.com>
+
+       PR target/63668
+       * doc/invoke.texi (SPARC options): Document -mstd-struct-return.
+       * config/sparc/sparc.c (sparc_struct_value_rtx): Minor tweaks.
+       * config/sparc/sparc.h (CALL_REALLY_USED_REGISTERS): Define.
+       * config/sparc/sparc.opt (mstd-struct-return): Accept negative.
+
 2015-12-07  Steve Ellcey  <sellcey@imgtec.com>
 
        * reorg.c (optimize_skip): Do not put frame related instructions
@@ -14,7 +22,7 @@
 
 2015-12-07  Jan Hubicka  <hubicka@ucw.cz>
 
-       * fold-const.c (operand_equal_p): Drp flag_strict_aliasing check.
+       * fold-const.c (operand_equal_p): Drop flag_strict_aliasing check.
 
 2015-12-07  Nathan Sidwell  <nathan@acm.org>
 
index ae96a9bf8db98f61fcb887d4dfb73bcc69121156..55ddacf511eefe48d53fb7f724bfdc08bb09c8d4 100644 (file)
@@ -7199,17 +7199,16 @@ sparc_struct_value_rtx (tree fndecl, int incoming)
          && TYPE_SIZE_UNIT (TREE_TYPE (fndecl))
          && TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (fndecl))) == INTEGER_CST)
        {
-         /* We must check and adjust the return address, as it is
-            optional as to whether the return object is really
-            provided.  */
-         rtx ret_reg = gen_rtx_REG (Pmode, 31);
+         /* We must check and adjust the return address, as it is optional
+            as to whether the return object is really provided.  */
+         rtx ret_reg = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
          rtx scratch = gen_reg_rtx (SImode);
          rtx_code_label *endlab = gen_label_rtx ();
 
-         /* Calculate the return object size */
+         /* Calculate the return object size */
          tree size = TYPE_SIZE_UNIT (TREE_TYPE (fndecl));
          rtx size_rtx = GEN_INT (TREE_INT_CST_LOW (size) & 0xfff);
-         /* Construct a temporary return value */
+         /* Construct a temporary return value */
          rtx temp_val
            = assign_stack_local (Pmode, TREE_INT_CST_LOW (size), 0);
 
@@ -7221,13 +7220,13 @@ sparc_struct_value_rtx (tree fndecl, int incoming)
          emit_move_insn (scratch, gen_rtx_MEM (SImode,
                                                plus_constant (Pmode,
                                                               ret_reg, 8)));
-         /* Assume the size is valid and pre-adjust */
+         /* Assume the size is valid and pre-adjust */
          emit_insn (gen_add3_insn (ret_reg, ret_reg, GEN_INT (4)));
          emit_cmp_and_jump_insns (scratch, size_rtx, EQ, const0_rtx, SImode,
                                   0, endlab);
          emit_insn (gen_sub3_insn (ret_reg, ret_reg, GEN_INT (4)));
          /* Write the address of the memory pointed to by temp_val into
-            the memory pointed to by mem */
+            the memory pointed to by mem */
          emit_move_insn (mem, XEXP (temp_val, 0));
          emit_label (endlab);
        }
index d2782a47bb1630d54828aae16aa73832b1b1b979..d599418c0885ca1a0812fbc044e52932fbe9cdf3 100644 (file)
@@ -696,6 +696,31 @@ extern enum cmodel sparc_cmodel;
                                \
   1, 1, 1, 1, 1, 1, 1}
 
+/* 1 for registers not available across function calls.
+   Unlike the above, this need not include the FIXED_REGISTERS, but any
+   registers that can be used without being saved.
+   The latter must include the registers where values are returned
+   and the register where structure-value addresses are passed.
+   Aside from that, you can include as many other registers as you like.  */
+
+#define CALL_REALLY_USED_REGISTERS  \
+ {1, 1, 1, 1, 1, 1, 1, 1,      \
+  1, 1, 1, 1, 1, 1, 1, 1,      \
+  0, 0, 0, 0, 0, 0, 0, 0,      \
+  0, 0, 0, 0, 0, 0, 0, 0,      \
+                               \
+  1, 1, 1, 1, 1, 1, 1, 1,      \
+  1, 1, 1, 1, 1, 1, 1, 1,      \
+  1, 1, 1, 1, 1, 1, 1, 1,      \
+  1, 1, 1, 1, 1, 1, 1, 1,      \
+                               \
+  1, 1, 1, 1, 1, 1, 1, 1,      \
+  1, 1, 1, 1, 1, 1, 1, 1,      \
+  1, 1, 1, 1, 1, 1, 1, 1,      \
+  1, 1, 1, 1, 1, 1, 1, 1,      \
+                               \
+  1, 1, 1, 1, 1, 1, 1}
+
 /* Return number of consecutive hard regs needed starting at reg REGNO
    to hold something of mode MODE.
    This is ordinarily the length in words of a value of mode MODE
index 16583c38545592806b483af6b615a5a4dda57d55..a50ba05ace4c9fc53f65d1fc3c936fb96e55d4e8 100644 (file)
@@ -203,7 +203,7 @@ Target RejectNegative Joined Var(sparc_debug_string)
 Enable debug output.
 
 mstd-struct-return
-Target Report RejectNegative Var(sparc_std_struct_return)
+Target Report Var(sparc_std_struct_return)
 Enable strict 32-bit psABI struct return checking.
 
 mfix-at697f
index 33f579f88cd82a9cfeb2df1e9ff9b106f5529f2b..9a30a2f769e6b675630f6f8779d3e004edbd3e64 100644 (file)
@@ -1022,6 +1022,7 @@ See RS/6000 and PowerPC Options.
 -mfpu  -mno-fpu  -mhard-float  -msoft-float @gol
 -mhard-quad-float  -msoft-quad-float @gol
 -mstack-bias  -mno-stack-bias @gol
+-mstd-struct-return  -mno-std-struct-return @gol
 -munaligned-doubles  -mno-unaligned-doubles @gol
 -muser-mode  -mno-user-mode @gol
 -mv8plus  -mno-v8plus  -mvis  -mno-vis @gol
@@ -21586,10 +21587,10 @@ Do not generate code that can only run in supervisor mode.  This is relevant
 only for the @code{casa} instruction emitted for the LEON3 processor.  This
 is the default.
 
-@item -mno-faster-structs
-@itemx -mfaster-structs
-@opindex mno-faster-structs
+@item -mfaster-structs
+@itemx -mno-faster-structs
 @opindex mfaster-structs
+@opindex mno-faster-structs
 With @option{-mfaster-structs}, the compiler assumes that structures
 should have 8-byte alignment.  This enables the use of pairs of
 @code{ldd} and @code{std} instructions for copies in structure
@@ -21599,6 +21600,17 @@ ABI@.  Thus, it's intended only for use on targets where the developer
 acknowledges that their resulting code is not directly in line with
 the rules of the ABI@.
 
+@item -mstd-struct-return
+@itemx -mno-std-struct-return
+@opindex mstd-struct-return
+@opindex mno-std-struct-return
+With @option{-mstd-struct-return}, the compiler generates checking code
+in functions returning structures or unions that detect size mismatches
+between the two sides of function calls, as per the 32-bit ABI@.
+
+The default is @option{-mno-std-struct-return}.  This option has no effect
+in 64-bit mode.
+
 @item -mcpu=@var{cpu_type}
 @opindex mcpu
 Set the instruction set, register set, and instruction scheduling parameters
index 000165ce0f982faaeedd27c6c9f4777178944908..fec47e137fb80f3dd690fa4cfde080a68f7d4123 100644 (file)
@@ -1,3 +1,9 @@
+2015-12-07  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gcc.target/sparc/struct-ret-check.c: Rename to...
+       * gcc.target/sparc/struct-ret-check-1.c: ...this.
+       * gcc.target/sparc/struct-ret-check-2.c: New test.
+
 2015-12-07  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/68760
diff --git a/gcc/testsuite/gcc.target/sparc/struct-ret-check-1.c b/gcc/testsuite/gcc.target/sparc/struct-ret-check-1.c
new file mode 100644 (file)
index 0000000..00307fe
--- /dev/null
@@ -0,0 +1,126 @@
+/* Copyright (C) 2006 Free Software Foundation, Inc. */
+/* Contributed by Carlos O'Donell on 2006-03-14 */
+
+/* Test that GCC follows the SPARC 32-bit psABI with regards to
+   structure return checking in a callee. When -mstd-struct-return 
+   is specificed then gcc will emit code to skip the unimp insn. */ 
+
+/* Origin: Carlos O'Donell <carlos@codesourcery.com> */
+/* { dg-do run { target sparc*-*-solaris* sparc*-*-linux* sparc*-*-*bsd* } } */
+/* { dg-options "-mstd-struct-return" } */
+/* { dg-require-effective-target ilp32 } */
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+
+/* Local declaration of div_t structure */
+struct mydiv_t {
+  int rem;
+  int quot;
+};
+
+/* Global check variable used by signal handler */
+int check = 1;
+struct mydiv_t dcheck;
+
+struct mydiv_t foo (void)
+{
+  struct mydiv_t bar;
+  bar.rem = 3;
+  bar.quot = 4;
+  return bar;
+}
+
+void handle_sigill (int signum)
+{
+  if (signum == SIGILL && check == 2)
+    {
+      /* We expected a SIGILL due to a mismatch in unimp size
+        and struct mydiv_t size */
+      exit (0);
+    }
+  else
+    abort ();
+}
+
+/* Implement 3 checks to validate SPARC 32-bit psABI callee 
+   returns struct
+   
+   Test1: Save area is valid. unimp size is valid.
+   Success: Save area modified correctly.
+   Failure: Save area unmodified.
+
+   Test2: Save area is valid. unimp size is invalid (invalid insn).
+   Success: Save area unmodified. check == 2.
+   Failure: Save area modified or check == 1.
+
+   Test3: Save area is invalid. unimp size is invalid (invalid size).
+   Success: Will raise a SIGILL. 
+   Failure: SIGSEGV caused by write to invalid save area. */
+
+int main (void)
+{
+  dcheck.rem = 1;
+  dcheck.quot = 2;
+
+  /*** Test1 ***/
+  /* Insert a call, insert unimp by hand */
+  __asm__ ("st %1, [ %%sp + 0x40 ]\n\t"
+          "call foo\n\t"
+          " nop\n\t"
+          "unimp %2\n\t" 
+          : "=m" (dcheck)
+          : "r" (&dcheck), "i" (sizeof(struct mydiv_t)) 
+          : "memory");
+
+  /* If the caller doesn't adjust the return, then it crashes.
+     Check the result too. */
+
+  if ((dcheck.rem != 3) || (dcheck.quot !=4))
+    abort ();
+  
+
+  /*** Test 2 ***/
+  dcheck.rem = 1;
+  dcheck.quot = 2;
+
+  /* Ignore the return of the function */
+  __asm__ ("st %3, [ %%sp + 0x40 ]\n\t"
+          "call foo\n\t"
+          " nop\n\t"
+          "mov %2, %0\n\t"
+          : "+r" (check), "=m" (dcheck) 
+          : "i" (0x2), "r" (&dcheck)
+          : "memory");
+
+  /* If the caller does an unconditional adjustment it will skip
+     the mov, and then we can fail the test based on check's value 
+     We pass a valid pointer to a save area in order to check if 
+     caller incorrectly wrote to the save area as well. There may
+     be a case where the unimp check and skip is correct, but the
+     write to the save area still occurs. */
+
+  if (check != 2)
+    abort ();
+
+  if ((dcheck.rem != 1) || (dcheck.quot != 2))
+    abort ();
+
+  /*** Test 3 ***/
+  /* Prepare a test that must SIGILL. According to the spec
+     if the sizes of the save area and return don't match then
+     the copy is ignored and we return to the unimp. */
+
+  signal (SIGILL, handle_sigill);
+
+  __asm__ ("st %%g0, [ %%sp + 0x40 ]\n\t"
+          "call foo\n\t"
+          " nop\n\t"
+          "unimp %0\n\t"
+          : /* No outputs */ 
+          : "i" (sizeof(struct mydiv_t)-1) 
+          : "memory");
+
+  /* NEVER REACHED */
+  exit (0);
+}
diff --git a/gcc/testsuite/gcc.target/sparc/struct-ret-check-2.c b/gcc/testsuite/gcc.target/sparc/struct-ret-check-2.c
new file mode 100644 (file)
index 0000000..2b81534
--- /dev/null
@@ -0,0 +1,29 @@
+/* { dg-do run } */
+/* { dg-options "-O -mstd-struct-return" } */
+/* { dg-require-effective-target ilp32 } */
+
+extern void abort (void);
+
+struct S { int x, y, z; };
+
+extern void bar (struct S *s) __attribute__ ((noinline, noclone));
+
+void bar (struct S *s)
+{
+  s->x++;
+}
+
+struct S foo (void)
+{
+  struct S s = { 0, 2, 3 };
+  bar (&s);
+  return s;
+}
+
+int main (void)
+{
+  struct S s = foo ();
+  if (s.x != 1)
+    abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/sparc/struct-ret-check.c b/gcc/testsuite/gcc.target/sparc/struct-ret-check.c
deleted file mode 100644 (file)
index 00307fe..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/* Copyright (C) 2006 Free Software Foundation, Inc. */
-/* Contributed by Carlos O'Donell on 2006-03-14 */
-
-/* Test that GCC follows the SPARC 32-bit psABI with regards to
-   structure return checking in a callee. When -mstd-struct-return 
-   is specificed then gcc will emit code to skip the unimp insn. */ 
-
-/* Origin: Carlos O'Donell <carlos@codesourcery.com> */
-/* { dg-do run { target sparc*-*-solaris* sparc*-*-linux* sparc*-*-*bsd* } } */
-/* { dg-options "-mstd-struct-return" } */
-/* { dg-require-effective-target ilp32 } */
-#include <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
-
-/* Local declaration of div_t structure */
-struct mydiv_t {
-  int rem;
-  int quot;
-};
-
-/* Global check variable used by signal handler */
-int check = 1;
-struct mydiv_t dcheck;
-
-struct mydiv_t foo (void)
-{
-  struct mydiv_t bar;
-  bar.rem = 3;
-  bar.quot = 4;
-  return bar;
-}
-
-void handle_sigill (int signum)
-{
-  if (signum == SIGILL && check == 2)
-    {
-      /* We expected a SIGILL due to a mismatch in unimp size
-        and struct mydiv_t size */
-      exit (0);
-    }
-  else
-    abort ();
-}
-
-/* Implement 3 checks to validate SPARC 32-bit psABI callee 
-   returns struct
-   
-   Test1: Save area is valid. unimp size is valid.
-   Success: Save area modified correctly.
-   Failure: Save area unmodified.
-
-   Test2: Save area is valid. unimp size is invalid (invalid insn).
-   Success: Save area unmodified. check == 2.
-   Failure: Save area modified or check == 1.
-
-   Test3: Save area is invalid. unimp size is invalid (invalid size).
-   Success: Will raise a SIGILL. 
-   Failure: SIGSEGV caused by write to invalid save area. */
-
-int main (void)
-{
-  dcheck.rem = 1;
-  dcheck.quot = 2;
-
-  /*** Test1 ***/
-  /* Insert a call, insert unimp by hand */
-  __asm__ ("st %1, [ %%sp + 0x40 ]\n\t"
-          "call foo\n\t"
-          " nop\n\t"
-          "unimp %2\n\t" 
-          : "=m" (dcheck)
-          : "r" (&dcheck), "i" (sizeof(struct mydiv_t)) 
-          : "memory");
-
-  /* If the caller doesn't adjust the return, then it crashes.
-     Check the result too. */
-
-  if ((dcheck.rem != 3) || (dcheck.quot !=4))
-    abort ();
-  
-
-  /*** Test 2 ***/
-  dcheck.rem = 1;
-  dcheck.quot = 2;
-
-  /* Ignore the return of the function */
-  __asm__ ("st %3, [ %%sp + 0x40 ]\n\t"
-          "call foo\n\t"
-          " nop\n\t"
-          "mov %2, %0\n\t"
-          : "+r" (check), "=m" (dcheck) 
-          : "i" (0x2), "r" (&dcheck)
-          : "memory");
-
-  /* If the caller does an unconditional adjustment it will skip
-     the mov, and then we can fail the test based on check's value 
-     We pass a valid pointer to a save area in order to check if 
-     caller incorrectly wrote to the save area as well. There may
-     be a case where the unimp check and skip is correct, but the
-     write to the save area still occurs. */
-
-  if (check != 2)
-    abort ();
-
-  if ((dcheck.rem != 1) || (dcheck.quot != 2))
-    abort ();
-
-  /*** Test 3 ***/
-  /* Prepare a test that must SIGILL. According to the spec
-     if the sizes of the save area and return don't match then
-     the copy is ignored and we return to the unimp. */
-
-  signal (SIGILL, handle_sigill);
-
-  __asm__ ("st %%g0, [ %%sp + 0x40 ]\n\t"
-          "call foo\n\t"
-          " nop\n\t"
-          "unimp %0\n\t"
-          : /* No outputs */ 
-          : "i" (sizeof(struct mydiv_t)-1) 
-          : "memory");
-
-  /* NEVER REACHED */
-  exit (0);
-}