From 4c6b3b2af062645c2e744010d4fc2b3c6a4af035 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 18 Jul 2000 10:54:33 +0200 Subject: [PATCH] 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 --- gcc/ChangeLog | 10 ++- gcc/calls.c | 75 +++++++++++++++---- gcc/testsuite/ChangeLog | 5 ++ .../gcc.c-torture/execute/20000717-1.x | 3 - .../gcc.c-torture/execute/20000717-5.c | 23 ++++++ 5 files changed, 95 insertions(+), 21 deletions(-) delete mode 100644 gcc/testsuite/gcc.c-torture/execute/20000717-1.x create mode 100644 gcc/testsuite/gcc.c-torture/execute/20000717-5.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7260401d4d2..b183280c992 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2000-07-18 Jakub Jelinek + + * calls.c (store_arg): Return non-zero if sibcall_failure is + desired. + (expand_call): Adjust caller. + 2000-07-17 Gabriel Dos Reis * 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 +2000-07-17 Zack Weinberg * 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 +2000-07-15 Neil Booth * cpplib.c: Change all directive-handler functions to return void, not int. diff --git a/gcc/calls.c b/gcc/calls.c index 784b3b165f8..8c5b9bcd29c 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 95d657feaba..42c8a64f059 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2000-07-18 Jakub Jelinek + + * gcc.c-torture/execute/20000717-5.c: New test. + * gcc.c-torture/execute/20000717-1.x: Removed. + 2000-07-17 Richard Henderson * 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 1005ae6c850..00000000000 --- 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 00000000000..49dcbbc66f1 --- /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); +}