aboutsummaryrefslogtreecommitdiff
path: root/gcc/calls.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2007-06-20 08:35:55 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2007-06-20 08:35:55 +0200
commit6a4e56a90e3c299e0eb634611cab3d076acbe818 (patch)
tree166cd1ce7322fc29d8e7721de1c5dcbb7dfe0b43 /gcc/calls.c
parent6cb62483b6958cd89877df5b8c479fc6b9c1faa2 (diff)
downloadgcc-6a4e56a90e3c299e0eb634611cab3d076acbe818.zip
gcc-6a4e56a90e3c299e0eb634611cab3d076acbe818.tar.gz
gcc-6a4e56a90e3c299e0eb634611cab3d076acbe818.tar.bz2
re PR middle-end/32285 (Miscompilation with pure _Complex returning call inside another fn's argument list)
PR middle-end/32285 * calls.c (precompute_arguments): Also precompute CALL_EXPR arguments if ACCUMULATE_OUTGOING_ARGS. * gcc.c-torture/execute/20070614-1.c: New test. From-SVN: r125873
Diffstat (limited to 'gcc/calls.c')
-rw-r--r--gcc/calls.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/gcc/calls.c b/gcc/calls.c
index b339c04..868edfc 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -1269,13 +1269,25 @@ precompute_arguments (int flags, int num_actuals, struct arg_data *args)
/* If this is a libcall, then precompute all arguments so that we do not
get extraneous instructions emitted as part of the libcall sequence. */
- if ((flags & ECF_LIBCALL_BLOCK) == 0)
+
+ /* If we preallocated the stack space, and some arguments must be passed
+ on the stack, then we must precompute any parameter which contains a
+ function call which will store arguments on the stack.
+ Otherwise, evaluating the parameter may clobber previous parameters
+ which have already been stored into the stack. (we have code to avoid
+ such case by saving the outgoing stack arguments, but it results in
+ worse code) */
+ if ((flags & ECF_LIBCALL_BLOCK) == 0 && !ACCUMULATE_OUTGOING_ARGS)
return;
for (i = 0; i < num_actuals; i++)
{
enum machine_mode mode;
+ if ((flags & ECF_LIBCALL_BLOCK) == 0
+ && TREE_CODE (args[i].tree_value) != CALL_EXPR)
+ continue;
+
/* If this is an addressable type, we cannot pre-evaluate it. */
gcc_assert (!TREE_ADDRESSABLE (TREE_TYPE (args[i].tree_value)));