Commit 4c6b3b2a by Jakub Jelinek

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
parent e81b4d63
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> 2000-07-17 Gabriel Dos Reis <gdr@codesourcery.com>
* diagnostic.h (report_diagnostic): Change prototype. * diagnostic.h (report_diagnostic): Change prototype.
...@@ -14,7 +20,7 @@ ...@@ -14,7 +20,7 @@
* c-errors.c (pedwarn_c99): Adjust call to report_diagnostic. End * c-errors.c (pedwarn_c99): Adjust call to report_diagnostic. End
varaible argument list. 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 * cpphash.c: Don't include hashtab.h. Most macro-handling code
moved to cppmacro.c. moved to cppmacro.c.
...@@ -41,7 +47,7 @@ ...@@ -41,7 +47,7 @@
* cppmain.c: Do not set pfile->printer if no_output is on. * 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 * cpplib.c: Change all directive-handler functions to return
void, not int. void, not int.
......
...@@ -191,7 +191,7 @@ static void emit_call_1 PARAMS ((rtx, tree, tree, HOST_WIDE_INT, ...@@ -191,7 +191,7 @@ static void emit_call_1 PARAMS ((rtx, tree, tree, HOST_WIDE_INT,
static void precompute_register_parameters PARAMS ((int, static void precompute_register_parameters PARAMS ((int,
struct arg_data *, struct arg_data *,
int *)); 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)); int));
static void store_unaligned_arguments_into_pseudos PARAMS ((struct arg_data *, static void store_unaligned_arguments_into_pseudos PARAMS ((struct arg_data *,
int)); int));
...@@ -1952,10 +1952,10 @@ check_sibcall_argument_overlap_1 (x) ...@@ -1952,10 +1952,10 @@ check_sibcall_argument_overlap_1 (x)
{ {
if (XEXP (x, 0) == current_function_internal_arg_pointer) if (XEXP (x, 0) == current_function_internal_arg_pointer)
i = 0; i = 0;
else if (GET_CODE (XEXP (x, 0)) == PLUS && else if (GET_CODE (XEXP (x, 0)) == PLUS
XEXP (XEXP (x, 0), 0) == && XEXP (XEXP (x, 0), 0) ==
current_function_internal_arg_pointer && current_function_internal_arg_pointer
GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT) && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
i = INTVAL (XEXP (XEXP (x, 0), 1)); i = INTVAL (XEXP (XEXP (x, 0), 1));
else else
return 0; return 0;
...@@ -2947,10 +2947,12 @@ expand_call (exp, target, ignore) ...@@ -2947,10 +2947,12 @@ expand_call (exp, target, ignore)
{ {
rtx before_arg = get_last_insn (); rtx before_arg = get_last_insn ();
store_one_arg (&args[i], argblock, flags, if (store_one_arg (&args[i], argblock, flags,
adjusted_args_size.var != 0, reg_parm_stack_space); adjusted_args_size.var != 0,
if (pass == 0 && reg_parm_stack_space)
check_sibcall_argument_overlap (before_arg, &args[i])) || (pass == 0
&& check_sibcall_argument_overlap (before_arg,
&args[i])))
sibcall_failure = 1; sibcall_failure = 1;
} }
...@@ -2969,10 +2971,12 @@ expand_call (exp, target, ignore) ...@@ -2969,10 +2971,12 @@ expand_call (exp, target, ignore)
{ {
rtx before_arg = get_last_insn (); rtx before_arg = get_last_insn ();
store_one_arg (&args[i], argblock, flags, if (store_one_arg (&args[i], argblock, flags,
adjusted_args_size.var != 0, reg_parm_stack_space); adjusted_args_size.var != 0,
if (pass == 0 && reg_parm_stack_space)
check_sibcall_argument_overlap (before_arg, &args[i])) || (pass == 0
&& check_sibcall_argument_overlap (before_arg,
&args[i])))
sibcall_failure = 1; sibcall_failure = 1;
} }
...@@ -4218,9 +4222,12 @@ target_for_arg (type, size, args_addr, offset) ...@@ -4218,9 +4222,12 @@ target_for_arg (type, size, args_addr, offset)
argument stack. This is used if ACCUMULATE_OUTGOING_ARGS to indicate argument stack. This is used if ACCUMULATE_OUTGOING_ARGS to indicate
that we need not worry about saving and restoring the stack. 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, store_one_arg (arg, argblock, flags, variable_size,
reg_parm_stack_space) reg_parm_stack_space)
struct arg_data *arg; struct arg_data *arg;
...@@ -4234,9 +4241,10 @@ store_one_arg (arg, argblock, flags, variable_size, ...@@ -4234,9 +4241,10 @@ store_one_arg (arg, argblock, flags, variable_size,
int partial = 0; int partial = 0;
int used = 0; int used = 0;
int i, lower_bound = 0, upper_bound = 0; int i, lower_bound = 0, upper_bound = 0;
int sibcall_failure = 0;
if (TREE_CODE (pval) == ERROR_MARK) if (TREE_CODE (pval) == ERROR_MARK)
return; return 1;
/* Push a new temporary level for any temporaries we make for /* Push a new temporary level for any temporaries we make for
this argument. */ this argument. */
...@@ -4451,6 +4459,39 @@ store_one_arg (arg, argblock, flags, variable_size, ...@@ -4451,6 +4459,39 @@ store_one_arg (arg, argblock, flags, variable_size,
size_rtx = expr_size (pval); 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, emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx,
TYPE_ALIGN (TREE_TYPE (pval)), partial, reg, excess, TYPE_ALIGN (TREE_TYPE (pval)), partial, reg, excess,
argblock, ARGS_SIZE_RTX (arg->offset), argblock, ARGS_SIZE_RTX (arg->offset),
...@@ -4482,4 +4523,6 @@ store_one_arg (arg, argblock, flags, variable_size, ...@@ -4482,4 +4523,6 @@ store_one_arg (arg, argblock, flags, variable_size,
preserve_temp_slots (NULL_RTX); preserve_temp_slots (NULL_RTX);
free_temp_slots (); free_temp_slots ();
pop_temp_slots (); pop_temp_slots ();
return sibcall_failure;
} }
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> 2000-07-17 Richard Henderson <rth@cygnus.com>
* gcc.c-torture/execute/20000717-4.c: New test. * gcc.c-torture/execute/20000717-4.c: New test.
......
set torture_execute_xfail "*-*-*"
return 0
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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment