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?

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.
---
 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;
+             }
+
            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);
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;
+               }
              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;
+}
--
2.25.1


Reply via email to