]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
PR 69246: Invalid REG_ARGS_SIZE for sibcalls
authorRichard Sandiford <richard.sandiford@arm.com>
Fri, 15 Jan 2016 14:41:10 +0000 (14:41 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Fri, 15 Jan 2016 14:41:10 +0000 (14:41 +0000)
The problem in this PR was that we were treating a sibcall as popping
arguments, leading to a negative REG_ARGS_SIZE.

It doesn't really make sense to treat sibcalls as popping since
(a) they're deallocating the caller's stack, not ours, and
(b) there are no optabs for popping sibcalls (any more).

Tested on x86_64-linux-gnu.

gcc/
PR middle-end/69246
* calls.c (emit_call_1): Force n_popped to zero for sibcalls.

gcc/testsuite/
PR middle-end/69246
* gcc.target/i386/pr69246.c: New test.

From-SVN: r232428

gcc/ChangeLog
gcc/calls.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr69246.c [new file with mode: 0644]

index de4cedee343dbc1c48029e1273a3ea922d8aae36..59dc4abbab50e1238b10755810ce0d5ab0f8caa6 100644 (file)
@@ -1,3 +1,8 @@
+2016-01-15  Richard Sandiford  <richard.sandiford@arm.com>
+
+       PR middle-end/69246
+       * calls.c (emit_call_1): Force n_popped to zero for sibcalls.
+
 2016-01-15  Ilya Enkovich  <enkovich.gnu@gmail.com>
 
        * config/i386/i386.c (scalar_chain::compute_convert_gain): Fix typo.
index a1549348b520ab57d2d1cd97756a5295166674fe..8f573b83430c52955e215e7aabcdb55cb3a76d6a 100644 (file)
@@ -272,12 +272,19 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU
   rtx rounded_stack_size_rtx = GEN_INT (rounded_stack_size);
   rtx call, funmem, pat;
   int already_popped = 0;
-  HOST_WIDE_INT n_popped
-    = targetm.calls.return_pops_args (fndecl, funtype, stack_size);
+  HOST_WIDE_INT n_popped = 0;
+
+  /* Sibling call patterns never pop arguments (no sibcall(_value)_pop
+     patterns exist).  Any popping that the callee does on return will
+     be from our caller's frame rather than ours.  */
+  if (!(ecf_flags & ECF_SIBCALL))
+    {
+      n_popped += targetm.calls.return_pops_args (fndecl, funtype, stack_size);
 
 #ifdef CALL_POPS_ARGS
-  n_popped += CALL_POPS_ARGS (*get_cumulative_args (args_so_far));
+      n_popped += CALL_POPS_ARGS (*get_cumulative_args (args_so_far));
 #endif
+    }
 
   /* Ensure address is valid.  SYMBOL_REF is already valid, so no need,
      and we don't want to load it into a register as an optimization,
index fb098b56763a5593d3e255fe86347c52d00c1afc..2c08f8d7f0d40264397233a6603a1341c597801b 100644 (file)
@@ -1,3 +1,8 @@
+2016-01-15  Richard Sandiford  <richard.sandiford@arm.com>
+
+       PR middle-end/69246
+       * gcc.target/i386/pr69246.c: New test.
+
 2016-01-15  Dominik Vogt  <vogt@linux.vnet.ibm.com>
 
        * gfortran.dg/bind_c_array_params_2.f90: Fix test patterns for
diff --git a/gcc/testsuite/gcc.target/i386/pr69246.c b/gcc/testsuite/gcc.target/i386/pr69246.c
new file mode 100644 (file)
index 0000000..e56e691
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-O2" } */
+
+void (__attribute__ ((stdcall)) *a) (int);
+
+void __attribute__ ((stdcall))
+foo (int x)
+{
+  a (x);
+}
+
+int (__attribute__ ((stdcall)) *b) (int);
+
+int __attribute__ ((stdcall))
+bar (int x)
+{
+  return b (x);
+}