diff mbox

PR 69246: Invalid REG_ARGS_SIZE for sibcalls

Message ID 87io2ukj6o.fsf@e105548-lin.cambridge.arm.com
State New
Headers show

Commit Message

Richard Sandiford Jan. 15, 2016, 2:31 p.m. UTC
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 (including an -m32 run and Ada).  OK to install?

Thanks,
Richard


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.

Comments

Bernd Schmidt Jan. 15, 2016, 2:35 p.m. UTC | #1
On 01/15/2016 03:31 PM, Richard Sandiford wrote:
> 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 (including an -m32 run and Ada).  OK to install?

Ok.


Bernd
diff mbox

Patch

diff --git a/gcc/calls.c b/gcc/calls.c
index a154934..8f573b8 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -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,
diff --git a/gcc/testsuite/gcc.target/i386/pr69246.c b/gcc/testsuite/gcc.target/i386/pr69246.c
new file mode 100644
index 0000000..e56e691
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr69246.c
@@ -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);
+}