90 lines
3.4 KiB
Diff
90 lines
3.4 KiB
Diff
2020-09-14 H.J. Lu <hjl.tools@gmail.com>
|
|
|
|
PR target/97032
|
|
* cfgexpand.c (asm_clobber_reg_kind): Set sp_is_clobbered_by_asm
|
|
to true if the stack pointer is clobbered by asm statement.
|
|
* emit-rtl.h (rtl_data): Add sp_is_clobbered_by_asm.
|
|
* config/i386/i386.c (ix86_get_drap_rtx): Set need_drap to true
|
|
if the stack pointer is clobbered by asm statement.
|
|
|
|
* gcc.target/i386/pr97032.c: New test.
|
|
|
|
--- gcc/cfgexpand.c
|
|
+++ gcc/cfgexpand.c
|
|
@@ -2879,11 +2879,15 @@ asm_clobber_reg_is_valid (int regno, int nregs, const char *regname)
|
|
as it was before, so no asm can validly clobber the stack pointer in
|
|
the usual sense. Adding the stack pointer to the clobber list has
|
|
traditionally had some undocumented and somewhat obscure side-effects. */
|
|
- if (overlaps_hard_reg_set_p (regset, Pmode, STACK_POINTER_REGNUM)
|
|
- && warning (OPT_Wdeprecated, "listing the stack pointer register"
|
|
- " %qs in a clobber list is deprecated", regname))
|
|
- inform (input_location, "the value of the stack pointer after an %<asm%>"
|
|
- " statement must be the same as it was before the statement");
|
|
+ if (overlaps_hard_reg_set_p (regset, Pmode, STACK_POINTER_REGNUM))
|
|
+ {
|
|
+ crtl->sp_is_clobbered_by_asm = true;
|
|
+ if (warning (OPT_Wdeprecated, "listing the stack pointer register"
|
|
+ " %qs in a clobber list is deprecated", regname))
|
|
+ inform (input_location, "the value of the stack pointer after"
|
|
+ " an %<asm%> statement must be the same as it was before"
|
|
+ " the statement");
|
|
+ }
|
|
|
|
return is_valid;
|
|
}
|
|
--- gcc/config/i386/i386.c
|
|
+++ gcc/config/i386/i386.c
|
|
@@ -12283,10 +12283,12 @@ ix86_update_stack_boundary (void)
|
|
static rtx
|
|
ix86_get_drap_rtx (void)
|
|
{
|
|
- /* We must use DRAP if there are outgoing arguments on stack and
|
|
+ /* We must use DRAP if there are outgoing arguments on stack or
|
|
+ the stack pointer register is clobbered by asm statment and
|
|
ACCUMULATE_OUTGOING_ARGS is false. */
|
|
if (ix86_force_drap
|
|
- || (cfun->machine->outgoing_args_on_stack
|
|
+ || ((cfun->machine->outgoing_args_on_stack
|
|
+ || crtl->sp_is_clobbered_by_asm)
|
|
&& !ACCUMULATE_OUTGOING_ARGS))
|
|
crtl->need_drap = true;
|
|
|
|
--- gcc/emit-rtl.h
|
|
+++ gcc/emit-rtl.h
|
|
@@ -266,6 +266,9 @@ struct GTY(()) rtl_data {
|
|
pass_stack_ptr_mod has run. */
|
|
bool sp_is_unchanging;
|
|
|
|
+ /* True if the stack pointer is clobbered by asm statement. */
|
|
+ bool sp_is_clobbered_by_asm;
|
|
+
|
|
/* Nonzero if function being compiled doesn't contain any calls
|
|
(ignoring the prologue and epilogue). This is set prior to
|
|
register allocation in IRA and is valid for the remaining
|
|
--- gcc/testsuite/gcc.target/i386/pr97032.c
|
|
+++ gcc/testsuite/gcc.target/i386/pr97032.c
|
|
@@ -0,0 +1,23 @@
|
|
+/* { dg-do compile { target { ia32 && fstack_protector } } } */
|
|
+/* { dg-options "-O2 -mincoming-stack-boundary=2 -fstack-protector-all" } */
|
|
+
|
|
+#include <stdarg.h>
|
|
+
|
|
+extern int *__errno_location (void);
|
|
+
|
|
+long
|
|
+sys_socketcall (int op, ...)
|
|
+{
|
|
+ long int res;
|
|
+ va_list ap;
|
|
+ va_start (ap, op);
|
|
+ asm volatile ("push %%ebx; movl %2, %%ebx; int $0x80; pop %%ebx"
|
|
+ /* { dg-warning "listing the stack pointer register" "" { target *-*-* } .-1 } */
|
|
+ : "=a" (res) : "0" (102), "ri" (16), "c" (ap) : "memory", "esp");
|
|
+ if (__builtin_expect (res > 4294963200UL, 0))
|
|
+ *__errno_location () = -res;
|
|
+ va_end (ap);
|
|
+ return res;
|
|
+}
|
|
+
|
|
+/* { dg-final { scan-assembler "call\[ \t\]*_?__errno_location" } } */
|