rtl_data: Add sp_is_clobbered_by_asm
authorH.J. Lu <hjl.tools@gmail.com>
Mon, 14 Sep 2020 15:52:27 +0000 (08:52 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Wed, 16 Sep 2020 12:26:19 +0000 (05:26 -0700)
Add sp_is_clobbered_by_asm to rtl_data to inform backends that the stack
pointer is clobbered by asm statement.

gcc/

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/testsuite/

PR target/97032
* gcc.target/i386/pr97032.c: New test.

gcc/cfgexpand.c
gcc/config/i386/i386.c
gcc/emit-rtl.h
gcc/testsuite/gcc.target/i386/pr97032.c [new file with mode: 0644]

index b334ea03c2568a79e778c41c68a7c71327ad46f8..1eaa1da11b9714dacfc51f3ffb774a62500bfa6c 100644 (file)
@@ -2868,11 +2868,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;
 }
index a15807d91da366eebf7a0f17f61d0f702f6f10e9..c890a73329398eb4fdb02db1184651932c893356 100644 (file)
@@ -6968,10 +6968,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;
 
index 3d6565c8a30d8da0bae32a09584ef5c7f2671074..92ad0dd6fc0e1b010d053b8e6c18492489b9b785 100644 (file)
@@ -281,6 +281,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
diff --git a/gcc/testsuite/gcc.target/i386/pr97032.c b/gcc/testsuite/gcc.target/i386/pr97032.c
new file mode 100644 (file)
index 0000000..7cbbe9b
--- /dev/null
@@ -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" } } */