From 0d4b97f1ee5213dffce107bc9f260a22fb23b4b1 Mon Sep 17 00:00:00 2001 From: Xi Ruoyao Date: Wed, 30 Mar 2022 22:22:45 +0800 Subject: [PATCH] mips: Emit psabi diagnostic for return values affected by C++ zero-width bit-field ABI change [PR 102024] gcc/ PR target/102024 * config/mips/mips.cc (mips_fpr_return_fields): Detect C++ zero-width bit-fields and set up an indicator. (mips_return_in_msb): Adapt for mips_fpr_return_fields change. (mips_function_value_1): Diagnose when the presense of a C++ zero-width bit-field changes function returning in GCC 12. gcc/testsuite/ PR target/102024 * g++.target/mips/mips.exp: New test supporting file. * g++.target/mips/pr102024.C: New test. --- gcc/config/mips/mips.cc | 58 +++++++++++++++++++++++++++----- gcc/testsuite/g++.target/mips/mips.exp | 34 +++++++++++++++++++ gcc/testsuite/g++.target/mips/pr102024.C | 20 +++++++++++ 3 files changed, 104 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/g++.target/mips/mips.exp create mode 100644 gcc/testsuite/g++.target/mips/pr102024.C diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc index 91e1e96..83860b5 100644 --- a/gcc/config/mips/mips.cc +++ b/gcc/config/mips/mips.cc @@ -6274,10 +6274,17 @@ mips_callee_copies (cumulative_args_t, const function_arg_info &arg) For n32 & n64, a structure with one or two fields is returned in floating-point registers as long as every field has a floating-point - type. */ + type. + + The C++ FE used to remove zero-width bit-fields in GCC 11 and earlier. + To make a proper diagnostic, this function will set + HAS_CXX_ZERO_WIDTH_BF to true once a C++ zero-width bit-field shows up, + and then ignore it. Then the caller can determine if this zero-width + bit-field will make a difference and emit a -Wpsabi inform. */ static int -mips_fpr_return_fields (const_tree valtype, tree *fields) +mips_fpr_return_fields (const_tree valtype, tree *fields, + bool *has_cxx_zero_width_bf) { tree field; int i; @@ -6294,6 +6301,12 @@ mips_fpr_return_fields (const_tree valtype, tree *fields) if (TREE_CODE (field) != FIELD_DECL) continue; + if (DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD (field)) + { + *has_cxx_zero_width_bf = true; + continue; + } + if (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (field))) return 0; @@ -6318,12 +6331,14 @@ mips_fpr_return_fields (const_tree valtype, tree *fields) static bool mips_return_in_msb (const_tree valtype) { - tree fields[2]; + if (!TARGET_NEWABI || !TARGET_BIG_ENDIAN || !AGGREGATE_TYPE_P (valtype)) + return false; - return (TARGET_NEWABI - && TARGET_BIG_ENDIAN - && AGGREGATE_TYPE_P (valtype) - && mips_fpr_return_fields (valtype, fields) == 0); + tree fields[2]; + bool has_cxx_zero_width_bf = false; + return (mips_fpr_return_fields (valtype, fields, + &has_cxx_zero_width_bf) == 0 + || has_cxx_zero_width_bf); } /* Return true if the function return value MODE will get returned in a @@ -6418,8 +6433,35 @@ mips_function_value_1 (const_tree valtype, const_tree fn_decl_or_type, return values, promote the mode here too. */ mode = promote_function_mode (valtype, mode, &unsigned_p, func, 1); + bool has_cxx_zero_width_bf = false; + int use_fpr = mips_fpr_return_fields (valtype, fields, + &has_cxx_zero_width_bf); + if (TARGET_HARD_FLOAT + && warn_psabi + && has_cxx_zero_width_bf + && use_fpr != 0) + { + static unsigned last_reported_type_uid; + unsigned uid = TYPE_UID (TYPE_MAIN_VARIANT (valtype)); + if (uid != last_reported_type_uid) + { + static const char *url + = CHANGES_ROOT_URL + "gcc-12/changes.html#zero_width_bitfields"; + inform (input_location, + "the ABI for returning a value containing " + "zero-width bit-fields but otherwise an aggregate " + "with only one or two floating-point fields was " + "changed in GCC %{12.1%}", url); + last_reported_type_uid = uid; + } + } + + if (has_cxx_zero_width_bf) + use_fpr = 0; + /* Handle structures whose fields are returned in $f0/$f2. */ - switch (mips_fpr_return_fields (valtype, fields)) + switch (use_fpr) { case 1: return mips_return_fpr_single (mode, diff --git a/gcc/testsuite/g++.target/mips/mips.exp b/gcc/testsuite/g++.target/mips/mips.exp new file mode 100644 index 0000000..9fa7e77 --- /dev/null +++ b/gcc/testsuite/g++.target/mips/mips.exp @@ -0,0 +1,34 @@ +# Copyright (C) 2019-2022 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# . + +# GCC testsuite that uses the `dg.exp' driver. + +# Exit immediately if this isn't a MIPS target. +if ![istarget mips*-*-*] then { + return +} + +# Load support procs. +load_lib g++-dg.exp + +# Initialize `dg'. +dg-init + +# Main loop. +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C]] "" "" + +# All done. +dg-finish diff --git a/gcc/testsuite/g++.target/mips/pr102024.C b/gcc/testsuite/g++.target/mips/pr102024.C new file mode 100644 index 0000000..331e6ca --- /dev/null +++ b/gcc/testsuite/g++.target/mips/pr102024.C @@ -0,0 +1,20 @@ +// PR target/102024 +// { dg-do compile } +// { dg-options "-O2 -mabi=64 -mhard-float" } +// { dg-final { scan-assembler-not "\\\$f0" } } + +struct foo +{ + double a; + int : 0; + double b; +}; + +struct foo +make_foo(void) // { dg-message "the ABI for returning a value containing zero-width bit-fields but otherwise an aggregate with only one or two floating-point fields was changed in GCC 12.1" } +{ + struct foo ret; + ret.a = 114; + ret.b = 514; + return ret; +} -- 2.7.4