aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2016-01-15 14:41:10 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2016-01-15 14:41:10 +0000
commita00fe3b787de1916bed415c57024d49bbe81cb1c (patch)
treefa57a9eddd888c9241714cfcc44471d4d36211f8
parentaea40b08771af69bb9b5e582e6147c3154e56abe (diff)
downloadgcc-a00fe3b787de1916bed415c57024d49bbe81cb1c.zip
gcc-a00fe3b787de1916bed415c57024d49bbe81cb1c.tar.gz
gcc-a00fe3b787de1916bed415c57024d49bbe81cb1c.tar.bz2
PR 69246: Invalid REG_ARGS_SIZE for sibcalls
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
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/calls.c13
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/i386/pr69246.c18
4 files changed, 38 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index de4cede..59dc4ab 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
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/ChangeLog b/gcc/testsuite/ChangeLog
index fb098b5..2c08f8d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
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);
+}