On Tue, 2021-09-21 at 17:35 -0500, Bill Schmidt wrote:
Hi!
Previously zero-width bit fields were removed from structs, so that otherwise
homogeneous aggregates were treated as such and passed in FPRs and VSRs.
This was incorrect behavior per the ELFv2 ABI. Now that these fields are no
longer being removed, we generate the correct parameter passing code. Alert
the unwary user in the rare cases where this behavior changes.
As noted in the PR, once the GCC 12 Changes page has text describing this issue,
we can update the diagnostic message to reference that URL. I'll handle that
in a follow-up patch.
Bootstrapped and tested on powerpc64le-unknown-linux-gnu with no regressions.
Is this okay for trunk?
How previously? is this one that will need all the backports?
Thanks!
Bill
2021-09-21 Bill Schmidt <wschm...@linux.ibm.com>
gcc/
PR target/102024
* config/rs6000/rs6000-call.c (rs6000_aggregate_candidate): Detect
zero-width bit fields and return indicator.
(rs6000_discover_homogeneous_aggregate): Diagnose when the
presence of a zero-width bit field changes parameter passing in
GCC 12.
gcc/testsuite/
PR target/102024
* g++.target/powerpc/pr102024.C: New.
ok
---
gcc/config/rs6000/rs6000-call.c | 39 ++++++++++++++++++---
gcc/testsuite/g++.target/powerpc/pr102024.C | 23 ++++++++++++
2 files changed, 57 insertions(+), 5 deletions(-)
create mode 100644 gcc/testsuite/g++.target/powerpc/pr102024.C
diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c
index 7d485480225..c02b202b0cd 100644
--- a/gcc/config/rs6000/rs6000-call.c
+++ b/gcc/config/rs6000/rs6000-call.c
@@ -6227,7 +6227,7 @@ const struct altivec_builtin_types
altivec_overloaded_builtins[] = {
static int
rs6000_aggregate_candidate (const_tree type, machine_mode *modep,
- int *empty_base_seen)
+ int *empty_base_seen, int *zero_width_bf_seen)
{
machine_mode mode;
HOST_WIDE_INT size;
@@ -6298,7 +6298,8 @@ rs6000_aggregate_candidate (const_tree type, machine_mode
*modep,
return -1;
count = rs6000_aggregate_candidate (TREE_TYPE (type), modep,
- empty_base_seen);
+ empty_base_seen,
+ zero_width_bf_seen);
if (count == -1
|| !index
|| !TYPE_MAX_VALUE (index)
@@ -6336,6 +6337,12 @@ rs6000_aggregate_candidate (const_tree type,
machine_mode *modep,
if (TREE_CODE (field) != FIELD_DECL)
continue;
+ if (DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD (field))
+ {
+ *zero_width_bf_seen = 1;
+ continue;
+ }
+
Noting that the definition comes from tree.h and is
#define SET_DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD(NODE, VAL) \
do { \
gcc_checking_assert (DECL_BIT_FIELD (NODE)); \
FIELD_DECL_CHECK (NODE)->decl_common.decl_flag_0 = (VAL); \
} while (0)
ok.
if (DECL_FIELD_ABI_IGNORED (field))
{
if (lookup_attribute ("no_unique_address",
@@ -6347,7 +6354,8 @@ rs6000_aggregate_candidate (const_tree type, machine_mode
*modep,
}
sub_count = rs6000_aggregate_candidate (TREE_TYPE (field), modep,
- empty_base_seen);
+ empty_base_seen,
+ zero_width_bf_seen);
if (sub_count < 0)
return -1;
count += sub_count;
@@ -6381,7 +6389,8 @@ rs6000_aggregate_candidate (const_tree type, machine_mode
*modep,
continue;
sub_count = rs6000_aggregate_candidate (TREE_TYPE (field), modep,
- empty_base_seen);
+ empty_base_seen,
+ zero_width_bf_seen);
if (sub_count < 0)
return -1;
count = count > sub_count ? count : sub_count;
@@ -6423,8 +6432,10 @@ rs6000_discover_homogeneous_aggregate (machine_mode
mode, const_tree type,
{
machine_mode field_mode = VOIDmode;
int empty_base_seen = 0;
+ int zero_width_bf_seen = 0;
int field_count = rs6000_aggregate_candidate (type, &field_mode,
- &empty_base_seen);
+ &empty_base_seen,
+ &zero_width_bf_seen);
That appears to be all of the callers of rs6000_aggregate_candidate.
(ok).
if (field_count > 0)
{
@@ -6460,6 +6471,24 @@ rs6000_discover_homogeneous_aggregate (machine_mode
mode, const_tree type,
last_reported_type_uid = uid;
}
}
+ if (zero_width_bf_seen && warn_psabi)
+ {
+ static unsigned last_reported_type_uid;
+ unsigned uid = TYPE_UID (TYPE_MAIN_VARIANT (type));
+ if (uid != last_reported_type_uid)
+ {
+ inform (input_location,
+ "parameter passing for an argument containing "
+ "zero-width bit fields but that is otherwise a "
+ "homogeneous aggregate changed in GCC 12.1");
+ last_reported_type_uid = uid;
+ }
+ if (elt_mode)
+ *elt_mode = mode;
+ if (n_elts)
+ *n_elts = 1;
+ return false;
+ }
In comparison to the other nearby warn_psabi logic, this seems
reasonable. (ok)
return true;
}
}
diff --git a/gcc/testsuite/g++.target/powerpc/pr102024.C
b/gcc/testsuite/g++.target/powerpc/pr102024.C
new file mode 100644
index 00000000000..29c9678acfd
--- /dev/null
+++ b/gcc/testsuite/g++.target/powerpc/pr102024.C
@@ -0,0 +1,23 @@
+// PR target/102024
+// { dg-do compile { target powerpc_elfv2 } }
+// { dg-options "-O2" }
+
+// Test that a zero-width bit field in an otherwise homogeneous aggregate
+// generates a psabi warning and passes arguments in GPRs.
+
+// { dg-final { scan-assembler-times {\mstd\M} 4 } }
+
+struct a_thing
+{
+ double x;
+ double y;
+ double z;
+ int : 0;
+ double w;
+};
+
+double
+foo (a_thing a) // { dg-message "parameter passing for an argument containing
zero-width bit fields but that is otherwise a homogeneous aggregate changed in GCC
12.1" }
+{
+ return a.x * a.y + a.z - a.w;
+}
lgtm
thanks
-Will