riscv_flatten_aggregate_argument returns 0 for an aggregate with no field,
but riscv_pass_aggregate_in_vr only rejected -1 and then read fields[0],
which was never written:
struct empty { };
__attribute__((riscv_vls_cc(1024))) void fr (struct empty x) { }
internal compiler error: tree check: expected class 'type', have
'exceptional' (error_mark) in riscv_pass_aggregate_in_vr
An aggregate with no field has nothing to put in a vector register, so
return NULL_RTX and let the generic path handle it, the same as any other
aggregate that does not fit the vector calling convention.
gcc/ChangeLog:
* config/riscv/riscv.cc (riscv_pass_aggregate_in_vr): Return
NULL_RTX for an aggregate with no field.
gcc/testsuite/ChangeLog:
* gcc.target/riscv/rvv/vls-cc/empty-aggregate.c: New test.
* g++.target/riscv/vls-cc-empty-aggregate.C: New test.
---
gcc/config/riscv/riscv.cc | 2 +-
.../g++.target/riscv/vls-cc-empty-aggregate.C | 30 +++++++++++++++++++
.../riscv/rvv/vls-cc/empty-aggregate.c | 30 +++++++++++++++++++
3 files changed, 61 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/g++.target/riscv/vls-cc-empty-aggregate.C
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vls-cc/empty-aggregate.c
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index c8139ea9073..d4dfb471fd4 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -7426,7 +7426,7 @@ riscv_pass_aggregate_in_vr (struct riscv_arg_info *info,
int n = riscv_flatten_aggregate_argument (type, fields, true, true,
/* vls_p */ true, abi_vlen);
- if (n == -1)
+ if (n <= 0)
return NULL_RTX;
/* Check all field has same size. */
diff --git a/gcc/testsuite/g++.target/riscv/vls-cc-empty-aggregate.C
b/gcc/testsuite/g++.target/riscv/vls-cc-empty-aggregate.C
new file mode 100644
index 00000000000..43e13c39598
--- /dev/null
+++ b/gcc/testsuite/g++.target/riscv/vls-cc-empty-aggregate.C
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl512b -mabi=lp64d" } */
+
+/* An aggregate with no field has nothing to pass in a vector register. It
+ used to run an empty field list into riscv_pass_aggregate_in_vr. */
+
+struct empty { };
+struct derived : empty { };
+
+__attribute__((riscv_vls_cc(1024))) void arg (empty);
+__attribute__((riscv_vls_cc(1024))) void arg_derived (derived);
+__attribute__((riscv_vls_cc(1024))) empty ret ();
+
+__attribute__((riscv_vls_cc(1024))) void
+def_arg (empty x)
+{
+ arg (x);
+}
+
+__attribute__((riscv_vls_cc(1024))) void
+def_arg_derived (derived x)
+{
+ arg_derived (x);
+}
+
+__attribute__((riscv_vls_cc(1024))) void
+call_ret ()
+{
+ ret ();
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vls-cc/empty-aggregate.c
b/gcc/testsuite/gcc.target/riscv/rvv/vls-cc/empty-aggregate.c
new file mode 100644
index 00000000000..bd51ca8b650
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/vls-cc/empty-aggregate.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl512b -mabi=lp64d -Wno-psabi" } */
+
+/* An aggregate with no field has nothing to pass in a vector register. It
+ used to run an empty field list into riscv_pass_aggregate_in_vr. */
+
+struct empty { };
+struct empty_array { struct empty a[0]; };
+
+__attribute__((riscv_vls_cc(1024))) void arg (struct empty);
+__attribute__((riscv_vls_cc(1024))) void arg_array (struct empty_array);
+__attribute__((riscv_vls_cc(1024))) struct empty ret (void);
+
+__attribute__((riscv_vls_cc(1024))) void
+def_arg (struct empty x)
+{
+ arg (x);
+}
+
+__attribute__((riscv_vls_cc(1024))) void
+def_arg_array (struct empty_array x)
+{
+ arg_array (x);
+}
+
+__attribute__((riscv_vls_cc(1024))) void
+call_ret (void)
+{
+ ret ();
+}
--
2.54.0