aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@gcc.gnu.org>2000-07-18 10:54:33 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2000-07-18 10:54:33 +0200
commit4c6b3b2af062645c2e744010d4fc2b3c6a4af035 (patch)
treece199b5558bf3556d55470271b06cd8224c00987 /gcc
parente81b4d6305ef9885149e87d374a909e8ff442edb (diff)
downloadgcc-4c6b3b2af062645c2e744010d4fc2b3c6a4af035.zip
gcc-4c6b3b2af062645c2e744010d4fc2b3c6a4af035.tar.gz
gcc-4c6b3b2af062645c2e744010d4fc2b3c6a4af035.tar.bz2
calls.c (store_arg): Return non-zero if sibcall_failure is desired.
* calls.c (store_arg): Return non-zero if sibcall_failure is desired. (expand_call): Adjust caller. * gcc.c-torture/execute/20000717-5.c: New test. * gcc.c-torture/execute/20000717-1.x: Removed. From-SVN: r35117
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/calls.c75
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20000717-1.x3
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20000717-5.c23
5 files changed, 95 insertions, 21 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7260401..b183280 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2000-07-18 Jakub Jelinek <jakub@redhat.com>
+
+ * calls.c (store_arg): Return non-zero if sibcall_failure is
+ desired.
+ (expand_call): Adjust caller.
+
2000-07-17 Gabriel Dos Reis <gdr@codesourcery.com>
* diagnostic.h (report_diagnostic): Change prototype.
@@ -14,7 +20,7 @@
* c-errors.c (pedwarn_c99): Adjust call to report_diagnostic. End
varaible argument list.
-2000-02-17 Zack Weinberg <zack@wolery.cumb.org>
+2000-07-17 Zack Weinberg <zack@wolery.cumb.org>
* cpphash.c: Don't include hashtab.h. Most macro-handling code
moved to cppmacro.c.
@@ -41,7 +47,7 @@
* cppmain.c: Do not set pfile->printer if no_output is on.
-2000-02-15 Neil Booth <neilb@earthling.net>
+2000-07-15 Neil Booth <neilb@earthling.net>
* cpplib.c: Change all directive-handler functions to return
void, not int.
diff --git a/gcc/calls.c b/gcc/calls.c
index 784b3b1..8c5b9bc 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -191,7 +191,7 @@ static void emit_call_1 PARAMS ((rtx, tree, tree, HOST_WIDE_INT,
static void precompute_register_parameters PARAMS ((int,
struct arg_data *,
int *));
-static void store_one_arg PARAMS ((struct arg_data *, rtx, int, int,
+static int store_one_arg PARAMS ((struct arg_data *, rtx, int, int,
int));
static void store_unaligned_arguments_into_pseudos PARAMS ((struct arg_data *,
int));
@@ -1952,10 +1952,10 @@ check_sibcall_argument_overlap_1 (x)
{
if (XEXP (x, 0) == current_function_internal_arg_pointer)
i = 0;
- else if (GET_CODE (XEXP (x, 0)) == PLUS &&
- XEXP (XEXP (x, 0), 0) ==
- current_function_internal_arg_pointer &&
- GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
+ else if (GET_CODE (XEXP (x, 0)) == PLUS
+ && XEXP (XEXP (x, 0), 0) ==
+ current_function_internal_arg_pointer
+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
i = INTVAL (XEXP (XEXP (x, 0), 1));
else
return 0;
@@ -2947,10 +2947,12 @@ expand_call (exp, target, ignore)
{
rtx before_arg = get_last_insn ();
- store_one_arg (&args[i], argblock, flags,
- adjusted_args_size.var != 0, reg_parm_stack_space);
- if (pass == 0 &&
- check_sibcall_argument_overlap (before_arg, &args[i]))
+ if (store_one_arg (&args[i], argblock, flags,
+ adjusted_args_size.var != 0,
+ reg_parm_stack_space)
+ || (pass == 0
+ && check_sibcall_argument_overlap (before_arg,
+ &args[i])))
sibcall_failure = 1;
}
@@ -2969,10 +2971,12 @@ expand_call (exp, target, ignore)
{
rtx before_arg = get_last_insn ();
- store_one_arg (&args[i], argblock, flags,
- adjusted_args_size.var != 0, reg_parm_stack_space);
- if (pass == 0 &&
- check_sibcall_argument_overlap (before_arg, &args[i]))
+ if (store_one_arg (&args[i], argblock, flags,
+ adjusted_args_size.var != 0,
+ reg_parm_stack_space)
+ || (pass == 0
+ && check_sibcall_argument_overlap (before_arg,
+ &args[i])))
sibcall_failure = 1;
}
@@ -4218,9 +4222,12 @@ target_for_arg (type, size, args_addr, offset)
argument stack. This is used if ACCUMULATE_OUTGOING_ARGS to indicate
that we need not worry about saving and restoring the stack.
- FNDECL is the declaration of the function we are calling. */
+ FNDECL is the declaration of the function we are calling.
+
+ Return non-zero if this arg should cause sibcall failure,
+ zero otherwise. */
-static void
+static int
store_one_arg (arg, argblock, flags, variable_size,
reg_parm_stack_space)
struct arg_data *arg;
@@ -4234,9 +4241,10 @@ store_one_arg (arg, argblock, flags, variable_size,
int partial = 0;
int used = 0;
int i, lower_bound = 0, upper_bound = 0;
+ int sibcall_failure = 0;
if (TREE_CODE (pval) == ERROR_MARK)
- return;
+ return 1;
/* Push a new temporary level for any temporaries we make for
this argument. */
@@ -4451,6 +4459,39 @@ store_one_arg (arg, argblock, flags, variable_size,
size_rtx = expr_size (pval);
}
+ if ((flags & ECF_SIBCALL) && GET_CODE (arg->value) == MEM)
+ {
+ /* emit_push_insn might not work properly if arg->value and
+ argblock + arg->offset areas overlap. */
+ rtx x = arg->value;
+ int i = 0;
+
+ if (XEXP (x, 0) == current_function_internal_arg_pointer
+ || (GET_CODE (XEXP (x, 0)) == PLUS
+ && XEXP (XEXP (x, 0), 0) ==
+ current_function_internal_arg_pointer
+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))
+ {
+ if (XEXP (x, 0) != current_function_internal_arg_pointer)
+ i = INTVAL (XEXP (XEXP (x, 0), 1));
+
+ /* expand_call should ensure this */
+ if (arg->offset.var || GET_CODE (size_rtx) != CONST_INT)
+ abort ();
+
+ if (arg->offset.constant > i)
+ {
+ if (arg->offset.constant < i + INTVAL (size_rtx))
+ sibcall_failure = 1;
+ }
+ else if (arg->offset.constant < i)
+ {
+ if (i < arg->offset.constant + INTVAL (size_rtx))
+ sibcall_failure = 1;
+ }
+ }
+ }
+
emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx,
TYPE_ALIGN (TREE_TYPE (pval)), partial, reg, excess,
argblock, ARGS_SIZE_RTX (arg->offset),
@@ -4482,4 +4523,6 @@ store_one_arg (arg, argblock, flags, variable_size,
preserve_temp_slots (NULL_RTX);
free_temp_slots ();
pop_temp_slots ();
+
+ return sibcall_failure;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 95d657f..42c8a64 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2000-07-18 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.c-torture/execute/20000717-5.c: New test.
+ * gcc.c-torture/execute/20000717-1.x: Removed.
+
2000-07-17 Richard Henderson <rth@cygnus.com>
* gcc.c-torture/execute/20000717-4.c: New test.
diff --git a/gcc/testsuite/gcc.c-torture/execute/20000717-1.x b/gcc/testsuite/gcc.c-torture/execute/20000717-1.x
deleted file mode 100644
index 1005ae6..0000000
--- a/gcc/testsuite/gcc.c-torture/execute/20000717-1.x
+++ /dev/null
@@ -1,3 +0,0 @@
-set torture_execute_xfail "*-*-*"
-
-return 0
diff --git a/gcc/testsuite/gcc.c-torture/execute/20000717-5.c b/gcc/testsuite/gcc.c-torture/execute/20000717-5.c
new file mode 100644
index 0000000..49dcbbc
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/20000717-5.c
@@ -0,0 +1,23 @@
+typedef struct trio { int a, b, c; } trio;
+
+int
+bar (int i, int j, int k, trio t)
+{
+ if (t.a != 1 || t.b != 2 || t.c != 3 ||
+ i != 4 || j != 5 || k != 6)
+ abort ();
+}
+
+int
+foo (trio t, int i, int j, int k)
+{
+ return bar (i, j, k, t);
+}
+
+main ()
+{
+ trio t = { 1, 2, 3 };
+
+ foo (t, 4, 5, 6);
+ exit (0);
+}