On 21/12/20 11:58 -0500, Patrick Palka via Libstdc++ wrote:
This patch conditionally disables the floating-point std::to_chars
implementation on targets whose float/double are not IEEE binary32 and
binary64 respectively, until a proper fallback can be added for such
targets. This fixes a bootstrap failure on non-IEEE-754 FP targets such
as vax-netbsdelf.
The preprocessor conditions that define the new internal libstdc++
macros for detecting the binary32 and binary64 formats were copied from
the test gcc/testsuite/gcc.dg/float-exact-1.c.
Tested on x86_64-pc-linux-gnu, with and without -m32, and also when
artifically undefining the below new macros. Does this look OK for
trunk?
libstdc++-v3/ChangeLog:
* include/bits/c++config (_GLIBCXX_FLOAT_IS_IEEE_BINARY_32):
Define this macro.
(_GLIBCXX_DOUBLE_IS_IEEE_BINARY_64): Likewise.
* include/std/charconv (to_chars): Use the macros to
conditionally hide the overloads for floating-point types.
* src/c++17/floating_to_chars.cc: Use the macros to
conditionally disable this file.
(floating_type_traits<float>): Remove redundant static assert.
(floating_type_traits<double>): Likewise.
* testsuite/20_util/to_chars/double.cc: Use the macros to
conditionally disable this test.
* testsuite/20_util/to_chars/float.cc: Likewise.
* testsuite/20_util/to_chars/long_double.cc: Likewise. Adjust
dg-do directives so that we don't execute this test on targets
with a large long double type and without int128.
---
libstdc++-v3/include/bits/c++config | 14 ++++++++++++++
libstdc++-v3/include/std/charconv | 2 ++
libstdc++-v3/src/c++17/floating_to_chars.cc | 9 +++++----
.../testsuite/20_util/to_chars/double.cc | 2 ++
.../testsuite/20_util/to_chars/float.cc | 2 ++
.../testsuite/20_util/to_chars/long_double.cc | 17 +++++++++++++----
6 files changed, 38 insertions(+), 8 deletions(-)
diff --git a/libstdc++-v3/include/bits/c++config
b/libstdc++-v3/include/bits/c++config
index 8cce88aa87b..f54074a2c04 100644
--- a/libstdc++-v3/include/bits/c++config
+++ b/libstdc++-v3/include/bits/c++config
@@ -688,6 +688,20 @@ namespace std
# endif
#endif
+// Define if float has the IEEE binary32 format.
+#if __FLT_MANT_DIG__ == 24 \
+ && __FLT_MIN_EXP__ == -125 \
+ && __FLT_MAX_EXP == 128
+# define _GLIBCXX_FLOAT_IS_IEEE_BINARY32 1
+#endif
+
+// Define if double has the IEEE binary64 format.
+#if __DBL_MANT_DIG__ == 53 \
+ && __DBL_MIN_EXP__ == -1021 \
+ && __DBL_MAX_EXP__ == 1024
+# define _GLIBCXX_DOUBLE_IS_IEEE_BINARY64 1
+#endif
+
#ifdef __has_builtin
# ifdef __is_identifier
// Intel and older Clang require !__is_identifier for some built-ins:
diff --git a/libstdc++-v3/include/std/charconv
b/libstdc++-v3/include/std/charconv
index b57b0a16db2..1f005be47b1 100644
--- a/libstdc++-v3/include/std/charconv
+++ b/libstdc++-v3/include/std/charconv
@@ -704,6 +704,7 @@ namespace __detail
// Floating-point std::to_chars
+#if _GLIBCXX_FLOAT_IS_IEEE_BINARY32 && _GLIBCXX_DOUBLE_IS_IEEE_BINARY64
// Overloads for float.
to_chars_result to_chars(char* __first, char* __last, float __value) noexcept;
to_chars_result to_chars(char* __first, char* __last, float __value,
@@ -725,6 +726,7 @@ namespace __detail
chars_format __fmt) noexcept;
to_chars_result to_chars(char* __first, char* __last, long double __value,
chars_format __fmt, int __precision) noexcept;
+#endif
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
diff --git a/libstdc++-v3/src/c++17/floating_to_chars.cc
b/libstdc++-v3/src/c++17/floating_to_chars.cc
index b7c31c746cc..6d94d46cc0a 100644
--- a/libstdc++-v3/src/c++17/floating_to_chars.cc
+++ b/libstdc++-v3/src/c++17/floating_to_chars.cc
@@ -22,6 +22,10 @@
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
+// This implementation crucially assumes float/double have the
+// IEEE binary32/binary64 formats.
+#if _GLIBCXX_FLOAT_IS_IEEE_BINARY32 && _GLIBCXX_DOUBLE_IS_IEEE_BINARY64
+
// Activate __glibcxx_assert within this file to shake out any bugs.
#define _GLIBCXX_ASSERTIONS 1
@@ -109,8 +113,6 @@ namespace
template<>
struct floating_type_traits<float>
{
- // We (and Ryu) assume float has the IEEE binary32 format.
- static_assert(__FLT_MANT_DIG__ == 24);
static constexpr int mantissa_bits = 23;
static constexpr int exponent_bits = 8;
static constexpr bool has_implicit_leading_bit = true;
@@ -124,8 +126,6 @@ namespace
template<>
struct floating_type_traits<double>
{
- // We (and Ryu) assume double has the IEEE binary64 format.
- static_assert(__DBL_MANT_DIG__ == 53);
static constexpr int mantissa_bits = 52;
static constexpr int exponent_bits = 11;
static constexpr bool has_implicit_leading_bit = true;
@@ -1565,3 +1565,4 @@ _ZSt8to_charsPcS_eSt12chars_formati(char* first, char*
last, double value,
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
+#endif // _GLIBCXX_FLOAT_IS_IEEE_BINARY32 && _GLIBCXX_DOUBLE_IS_IEEE_BINARY64
diff --git a/libstdc++-v3/testsuite/20_util/to_chars/double.cc
b/libstdc++-v3/testsuite/20_util/to_chars/double.cc
index 9d1f37d3026..a52d7e7cd61 100644
--- a/libstdc++-v3/testsuite/20_util/to_chars/double.cc
+++ b/libstdc++-v3/testsuite/20_util/to_chars/double.cc
@@ -56952,6 +56952,7 @@ inline constexpr double_to_chars_testcase
double_hex_precision_to_chars_test_cas
void
test01()
{
+#if _GLIBCXX_FLOAT_IS_IEEE_BINARY32 && _GLIBCXX_DOUBLE_IS_IEEE_BINARY64
auto handle_testcases = [] (const auto& testcases) {
for (const auto [value,fmt,precision,correct] : testcases)
{
@@ -56991,6 +56992,7 @@ test01()
handle_testcases(double_general_precision_to_chars_test_cases);
handle_testcases(double_hex_precision_to_chars_test_cases);
+#endif
If I'm reading this right, the compiler is going to churn through
50000 lines defining arrays of numbers, and then do nothing with them.
This would mean you could { dg-require-effective-targets ieee-floats }
so the whole testcase is skipped:
--- a/libstdc++-v3/testsuite/lib/libstdc++.exp
+++ b/libstdc++-v3/testsuite/lib/libstdc++.exp
@@ -1323,6 +1323,14 @@ proc check_effective_target_futex { } {
}]
}
+# Return 1 if float and double have the IEEE binary32 and binary64 formats.
+proc check_effective_target_ieee-floats { } {
+ return [check_v3_target_prop_cached et_ieee_floats {
+ set cond "_GLIBCXX_FLOAT_IS_IEEE_BINARY32 &&
_GLIBCXX_DOUBLE_IS_IEEE_BINARY64"
+ return [v3_check_preprocessor_condition ieee_floats $cond]
+ }]
+}
+
set additional_prunes ""
if { [info exists env(GCC_RUNTEST_PARALLELIZE_DIR)] \
If something like that works, please do that.
OK for trunk with that if it works, and as in your patch otherwise.