+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
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>
&& 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);
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);
}
\
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
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
-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
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
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
+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
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* { 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;
+}
+++ /dev/null
-/* 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);
-}