From: Eric Botcazou Date: Mon, 7 Dec 2015 23:18:29 +0000 (+0000) Subject: re PR target/63668 (-mstd-struct-return fails for non-leaf functions) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=9250444b59bb08bd5939c4af410eb153153baef9;p=gcc.git re PR target/63668 (-mstd-struct-return fails for non-leaf functions) 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ade56278e4b..f6f3ff57231 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2015-12-07 Eric Botcazou + + 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 * reorg.c (optimize_skip): Do not put frame related instructions @@ -14,7 +22,7 @@ 2015-12-07 Jan Hubicka - * 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 diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index ae96a9bf8db..55ddacf511e 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -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); } diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h index d2782a47bb1..d599418c088 100644 --- a/gcc/config/sparc/sparc.h +++ b/gcc/config/sparc/sparc.h @@ -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 diff --git a/gcc/config/sparc/sparc.opt b/gcc/config/sparc/sparc.opt index 16583c38545..a50ba05ace4 100644 --- a/gcc/config/sparc/sparc.opt +++ b/gcc/config/sparc/sparc.opt @@ -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 diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 33f579f88cd..9a30a2f769e 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 000165ce0f9..fec47e137fb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2015-12-07 Eric Botcazou + + * 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 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 index 00000000000..00307fe2978 --- /dev/null +++ b/gcc/testsuite/gcc.target/sparc/struct-ret-check-1.c @@ -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 */ +/* { dg-do run { target sparc*-*-solaris* sparc*-*-linux* sparc*-*-*bsd* } } */ +/* { dg-options "-mstd-struct-return" } */ +/* { dg-require-effective-target ilp32 } */ +#include +#include +#include + +/* 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 index 00000000000..2b815345ab9 --- /dev/null +++ b/gcc/testsuite/gcc.target/sparc/struct-ret-check-2.c @@ -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 index 00307fe2978..00000000000 --- a/gcc/testsuite/gcc.target/sparc/struct-ret-check.c +++ /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 */ -/* { dg-do run { target sparc*-*-solaris* sparc*-*-linux* sparc*-*-*bsd* } } */ -/* { dg-options "-mstd-struct-return" } */ -/* { dg-require-effective-target ilp32 } */ -#include -#include -#include - -/* 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); -}