diff --git a/lldb/source/Core/DumpDataExtractor.cpp b/lldb/source/Core/DumpDataExtractor.cpp --- a/lldb/source/Core/DumpDataExtractor.cpp +++ b/lldb/source/Core/DumpDataExtractor.cpp @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include @@ -230,6 +230,29 @@ s.Printf("\\x%2.2x", c); } +/// Dump a floating point type. +template +void DumpFloatingPoint(std::ostringstream &ss, FloatT f) { + static_assert(std::is_floating_point::value, + "Only floating point types can be dumped."); + // NaN and Inf are potentially implementation defined and on Darwin it + // seems NaNs are printed without their sign. Manually implement dumping them + // here to avoid having to deal with platform differences. + if (std::isnan(f)) { + if (std::signbit(f)) + ss << '-'; + ss << "nan"; + return; + } + if (std::isinf(f)) { + if (std::signbit(f)) + ss << '-'; + ss << "inf"; + return; + } + ss << f; +} + lldb::offset_t lldb_private::DumpDataExtractor( const DataExtractor &DE, Stream *s, offset_t start_offset, lldb::Format item_format, size_t item_byte_size, size_t item_count, @@ -570,14 +593,14 @@ f = DE.GetFloat(&offset); } ss.precision(std::numeric_limits::digits10); - ss << f; + DumpFloatingPoint(ss, f); } else if (item_byte_size == sizeof(double)) { ss.precision(std::numeric_limits::digits10); - ss << DE.GetDouble(&offset); + DumpFloatingPoint(ss, DE.GetDouble(&offset)); } else if (item_byte_size == sizeof(long double) || item_byte_size == 10) { ss.precision(std::numeric_limits::digits10); - ss << DE.GetLongDouble(&offset); + DumpFloatingPoint(ss, DE.GetLongDouble(&offset)); } else { s->Printf("error: unsupported byte size (%" PRIu64 ") for float format", diff --git a/lldb/unittests/Core/DumpDataExtractorTest.cpp b/lldb/unittests/Core/DumpDataExtractorTest.cpp --- a/lldb/unittests/Core/DumpDataExtractorTest.cpp +++ b/lldb/unittests/Core/DumpDataExtractorTest.cpp @@ -13,6 +13,7 @@ #include "lldb/Utility/StreamString.h" #include "gtest/gtest.h" #include +#include using namespace lldb; using namespace lldb_private; @@ -197,13 +198,34 @@ lldb::Format::eFormatVectorOfFloat16, "{6.10352e-05 65504}"); TestDump(std::vector{0xabcd, 0x1234}, lldb::Format::eFormatVectorOfFloat16, "{-0.0609436 0.000757217}"); + + // quiet/signaling NaNs. + TestDump(std::vector{0xffff, 0xffc0, 0x7fff, 0x7fc0}, + lldb::Format::eFormatVectorOfFloat16, "{-nan -nan nan nan}"); + // +/-Inf. + TestDump(std::vector{0xfc00, 0x7c00}, + lldb::Format::eFormatVectorOfFloat16, "{-inf inf}"); + TestDump(std::vector{std::numeric_limits::min(), std::numeric_limits::max()}, lldb::Format::eFormatVectorOfFloat32, "{1.17549e-38 3.40282e+38}"); + TestDump(std::vector{std::numeric_limits::quiet_NaN(), + std::numeric_limits::signaling_NaN(), + -std::numeric_limits::quiet_NaN(), + -std::numeric_limits::signaling_NaN()}, + lldb::Format::eFormatVectorOfFloat32, "{nan nan -nan -nan}"); TestDump(std::vector{std::numeric_limits::min(), std::numeric_limits::max()}, lldb::Format::eFormatVectorOfFloat64, "{2.2250738585072e-308 1.79769313486232e+308}"); + TestDump( + std::vector{ + std::numeric_limits::quiet_NaN(), + std::numeric_limits::signaling_NaN(), + -std::numeric_limits::quiet_NaN(), + -std::numeric_limits::signaling_NaN(), + }, + lldb::Format::eFormatVectorOfFloat64, "{nan nan -nan -nan}"); // Not sure we can rely on having uint128_t everywhere so emulate with // uint64_t.