[gcc r13-8509] rs6000: Fix up setup_incoming_varargs [PR114175]
Jakub Jelinek
jakub@gcc.gnu.org
Sat Mar 30 03:54:22 GMT 2024
https://gcc.gnu.org/g:af189fa9c2c4a0c8230f308e1934f046df3e80f7
commit r13-8509-gaf189fa9c2c4a0c8230f308e1934f046df3e80f7
Author: Jakub Jelinek <jakub@redhat.com>
Date: Tue Mar 19 09:13:32 2024 +0100
rs6000: Fix up setup_incoming_varargs [PR114175]
The c23-stdarg-8.c test (as well as the new test below added to cover even
more cases) FAIL on powerpc64le-linux and presumably other powerpc* targets
as well.
Like in the r14-9503-g218d174961 change on x86-64 we need to advance
next_cum after the hidden return pointer argument even in case where
there are no user arguments before ... in C23.
The following patch does that.
There is another TYPE_NO_NAMED_ARGS_STDARG_P use later on:
if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl))
&& targetm.calls.must_pass_in_stack (arg))
first_reg_offset += rs6000_arg_size (TYPE_MODE (arg.type), arg.type);
but I believe it was added there in r13-3549-g4fe34cdc unnecessarily,
when there is no hidden return pointer argument, arg.type is NULL and
must_pass_in_stack_var_size as well as must_pass_in_stack_var_size_or_pad
return false in that case, and for the TYPE_NO_NAMED_ARGS_STDARG_P
case with hidden return pointer argument that argument should have pointer
type and it is the first argument, so must_pass_in_stack shouldn't be true
for it either.
2024-03-19 Jakub Jelinek <jakub@redhat.com>
PR target/114175
* config/rs6000/rs6000-call.cc (setup_incoming_varargs): Only skip
rs6000_function_arg_advance_1 for TYPE_NO_NAMED_ARGS_STDARG_P functions
if arg.type is NULL.
* gcc.dg/c23-stdarg-9.c: New test.
(cherry picked from commit 8f85b46337f90c3126b9cefd72ffd29eb9a4ebf3)
Diff:
---
gcc/config/rs6000/rs6000-call.cc | 3 +-
gcc/testsuite/gcc.dg/c23-stdarg-9.c | 284 ++++++++++++++++++++++++++++++++++++
2 files changed, 286 insertions(+), 1 deletion(-)
diff --git a/gcc/config/rs6000/rs6000-call.cc b/gcc/config/rs6000/rs6000-call.cc
index 214613e083e..74ee908a1a8 100644
--- a/gcc/config/rs6000/rs6000-call.cc
+++ b/gcc/config/rs6000/rs6000-call.cc
@@ -2253,7 +2253,8 @@ setup_incoming_varargs (cumulative_args_t cum,
/* Skip the last named argument. */
next_cum = *get_cumulative_args (cum);
- if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl)))
+ if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl))
+ || arg.type != NULL_TREE)
rs6000_function_arg_advance_1 (&next_cum, arg.mode, arg.type, arg.named,
0);
diff --git a/gcc/testsuite/gcc.dg/c23-stdarg-9.c b/gcc/testsuite/gcc.dg/c23-stdarg-9.c
new file mode 100644
index 00000000000..fe96fc7a864
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c23-stdarg-9.c
@@ -0,0 +1,284 @@
+/* Test C23 variadic functions with no named parameters, or last named
+ parameter with a declaration not allowed in C17. Execution tests. */
+/* { dg-do run } */
+/* { dg-options "-O2 -std=c2x -pedantic-errors" } */
+
+#include <stdarg.h>
+
+struct S { int a[1024]; };
+
+int
+f1 (...)
+{
+ int r = 0;
+ va_list ap;
+ va_start (ap);
+ r += va_arg (ap, int);
+ va_end (ap);
+ return r;
+}
+
+int
+f2 (...)
+{
+ int r = 0;
+ va_list ap;
+ va_start (ap);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ va_end (ap);
+ return r;
+}
+
+int
+f3 (...)
+{
+ int r = 0;
+ va_list ap;
+ va_start (ap);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ va_end (ap);
+ return r;
+}
+
+int
+f4 (...)
+{
+ int r = 0;
+ va_list ap;
+ va_start (ap);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ va_end (ap);
+ return r;
+}
+
+int
+f5 (...)
+{
+ int r = 0;
+ va_list ap;
+ va_start (ap);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ va_end (ap);
+ return r;
+}
+
+int
+f6 (...)
+{
+ int r = 0;
+ va_list ap;
+ va_start (ap);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ va_end (ap);
+ return r;
+}
+
+int
+f7 (...)
+{
+ int r = 0;
+ va_list ap;
+ va_start (ap);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ va_end (ap);
+ return r;
+}
+
+int
+f8 (...)
+{
+ int r = 0;
+ va_list ap;
+ va_start (ap);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ va_end (ap);
+ return r;
+}
+
+struct S
+s1 (...)
+{
+ int r = 0;
+ va_list ap;
+ va_start (ap);
+ r += va_arg (ap, int);
+ va_end (ap);
+ struct S s = {};
+ s.a[0] = r;
+ return s;
+}
+
+struct S
+s2 (...)
+{
+ int r = 0;
+ va_list ap;
+ va_start (ap);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ va_end (ap);
+ struct S s = {};
+ s.a[0] = r;
+ return s;
+}
+
+struct S
+s3 (...)
+{
+ int r = 0;
+ va_list ap;
+ va_start (ap);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ va_end (ap);
+ struct S s = {};
+ s.a[0] = r;
+ return s;
+}
+
+struct S
+s4 (...)
+{
+ int r = 0;
+ va_list ap;
+ va_start (ap);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ va_end (ap);
+ struct S s = {};
+ s.a[0] = r;
+ return s;
+}
+
+struct S
+s5 (...)
+{
+ int r = 0;
+ va_list ap;
+ va_start (ap);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ va_end (ap);
+ struct S s = {};
+ s.a[0] = r;
+ return s;
+}
+
+struct S
+s6 (...)
+{
+ int r = 0;
+ va_list ap;
+ va_start (ap);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ va_end (ap);
+ struct S s = {};
+ s.a[0] = r;
+ return s;
+}
+
+struct S
+s7 (...)
+{
+ int r = 0;
+ va_list ap;
+ va_start (ap);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ va_end (ap);
+ struct S s = {};
+ s.a[0] = r;
+ return s;
+}
+
+struct S
+s8 (...)
+{
+ int r = 0;
+ va_list ap;
+ va_start (ap);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ r += va_arg (ap, int);
+ va_end (ap);
+ struct S s = {};
+ s.a[0] = r;
+ return s;
+}
+
+int
+b1 (void)
+{
+ return f8 (1, 2, 3, 4, 5, 6, 7, 8);
+}
+
+int
+b2 (void)
+{
+ return s8 (1, 2, 3, 4, 5, 6, 7, 8).a[0];
+}
+
+int
+main ()
+{
+ if (f1 (1) != 1 || f2 (1, 2) != 3 || f3 (1, 2, 3) != 6
+ || f4 (1, 2, 3, 4) != 10 || f5 (1, 2, 3, 4, 5) != 15
+ || f6 (1, 2, 3, 4, 5, 6) != 21 || f7 (1, 2, 3, 4, 5, 6, 7) != 28
+ || f8 (1, 2, 3, 4, 5, 6, 7, 8) != 36)
+ __builtin_abort ();
+ if (s1 (1).a[0] != 1 || s2 (1, 2).a[0] != 3 || s3 (1, 2, 3).a[0] != 6
+ || s4 (1, 2, 3, 4).a[0] != 10 || s5 (1, 2, 3, 4, 5).a[0] != 15
+ || s6 (1, 2, 3, 4, 5, 6).a[0] != 21
+ || s7 (1, 2, 3, 4, 5, 6, 7).a[0] != 28
+ || s8 (1, 2, 3, 4, 5, 6, 7, 8).a[0] != 36)
+ __builtin_abort ();
+}
More information about the Gcc-cvs
mailing list