[lldb] Add support for displaying __float128 variables (#98369)

This commit is contained in:
beetrees 2025-08-01 02:04:48 +01:00 committed by GitHub
parent 03bb10bea6
commit e15b3ef704
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 70 additions and 14 deletions

View File

@ -594,6 +594,7 @@ def is_numeric_type(basic_type):
if basic_type == eBasicTypeFloat: return (True,True)
if basic_type == eBasicTypeDouble: return (True,True)
if basic_type == eBasicTypeLongDouble: return (True,True)
if basic_type == eBasicTypeFloat128: return (True,True)
if basic_type == eBasicTypeFloatComplex: return (True,True)
if basic_type == eBasicTypeDoubleComplex: return (True,True)
if basic_type == eBasicTypeLongDoubleComplex: return (True,True)

View File

@ -321,6 +321,7 @@ Format
.. py:data:: eFormatInstruction
.. py:data:: eFormatVoid
.. py:data:: eFormatUnicode8
.. py:data:: eFormatFloat128
.. _DescriptionLevel:
@ -1045,6 +1046,7 @@ BasicType
.. py:data:: eBasicTypeObjCSel
.. py:data:: eBasicTypeNullPtr
.. py:data:: eBasicTypeOther
.. py:data:: eBasicTypeFloat128
.. _TraceType:

View File

@ -310,7 +310,8 @@ public:
// Exploring the type
virtual const llvm::fltSemantics &GetFloatTypeSemantics(size_t byte_size) = 0;
virtual const llvm::fltSemantics &
GetFloatTypeSemantics(size_t byte_size, lldb::Format format) = 0;
virtual llvm::Expected<uint64_t>
GetBitSize(lldb::opaque_compiler_type_t type,

View File

@ -198,11 +198,15 @@ enum Format {
///< character arrays that can contain non printable
///< characters
eFormatAddressInfo, ///< Describe what an address points to (func + offset
///< with file/line, symbol + offset, data, etc)
eFormatHexFloat, ///< ISO C99 hex float string
eFormatInstruction, ///< Disassemble an opcode
eFormatVoid, ///< Do not print this
///< with file/line, symbol + offset, data, etc)
eFormatHexFloat, ///< ISO C99 hex float string
eFormatInstruction, ///< Disassemble an opcode
eFormatVoid, ///< Do not print this
eFormatUnicode8,
eFormatFloat128, ///< Disambiguate between 128-bit `long double` (which uses
///< `eFormatFloat`) and `__float128` (which uses
///< `eFormatFloat128`). If the value being formatted is not
///< 128 bits, then this is identical to `eFormatFloat`.
kNumFormats
};
@ -838,7 +842,8 @@ enum BasicType {
eBasicTypeObjCClass,
eBasicTypeObjCSel,
eBasicTypeNullPtr,
eBasicTypeOther
eBasicTypeOther,
eBasicTypeFloat128
};
/// Deprecated

View File

@ -156,6 +156,7 @@ public:
case eFormatBinary:
case eFormatFloat:
case eFormatFloat128:
case eFormatOctal:
case eFormatDecimal:
case eFormatEnum:
@ -1356,6 +1357,7 @@ protected:
switch (m_format_options.GetFormat()) {
case kNumFormats:
case eFormatFloat: // TODO: add support for floats soon
case eFormatFloat128:
case eFormatCharPrintable:
case eFormatBytesWithASCII:
case eFormatComplex:

View File

@ -318,14 +318,15 @@ static void printMemoryTags(const DataExtractor &DE, Stream *s,
}
static const llvm::fltSemantics &GetFloatSemantics(const TargetSP &target_sp,
size_t byte_size) {
size_t byte_size,
lldb::Format format) {
if (target_sp) {
auto type_system_or_err =
target_sp->GetScratchTypeSystemForLanguage(eLanguageTypeC);
if (!type_system_or_err)
llvm::consumeError(type_system_or_err.takeError());
else if (auto ts = *type_system_or_err)
return ts->GetFloatTypeSemantics(byte_size);
return ts->GetFloatTypeSemantics(byte_size, format);
}
// No target, just make a reasonable guess
switch(byte_size) {
@ -335,7 +336,13 @@ static const llvm::fltSemantics &GetFloatSemantics(const TargetSP &target_sp,
return llvm::APFloat::IEEEsingle();
case 8:
return llvm::APFloat::IEEEdouble();
}
case 16:
if (format == eFormatFloat128) {
return llvm::APFloat::IEEEquad();
}
// Otherwise it's ambigious whether a 16-byte float is a float128 or a
// target-specific long double.
}
return llvm::APFloat::Bogus();
}
@ -653,6 +660,7 @@ lldb::offset_t lldb_private::DumpDataExtractor(
}
} break;
case eFormatFloat128:
case eFormatFloat: {
TargetSP target_sp;
if (exe_scope)
@ -666,7 +674,7 @@ lldb::offset_t lldb_private::DumpDataExtractor(
const unsigned format_precision = 0;
const llvm::fltSemantics &semantics =
GetFloatSemantics(target_sp, item_byte_size);
GetFloatSemantics(target_sp, item_byte_size, item_format);
// Recalculate the byte size in case of a difference. This is possible
// when item_byte_size is 16 (128-bit), because you could get back the

View File

@ -72,6 +72,7 @@ static constexpr FormatInfo g_format_infos[] = {
{eFormatInstruction, 'i', "instruction"},
{eFormatVoid, 'v', "void"},
{eFormatUnicode8, 'u', "unicode8"},
{eFormatFloat128, '\0', "float128"},
};
static_assert((sizeof(g_format_infos) / sizeof(g_format_infos[0])) ==

View File

@ -55,6 +55,8 @@ static CompilerType GetCompilerTypeForFormat(lldb::Format format,
case lldb::eFormatFloat:
return type_system->GetBasicTypeFromAST(lldb::eBasicTypeFloat);
case lldb::eFormatFloat128:
return type_system->GetBasicTypeFromAST(lldb::eBasicTypeFloat128);
case lldb::eFormatHex:
case lldb::eFormatHexUppercase:

View File

@ -795,6 +795,8 @@ TypeSystemClang::GetBuiltinTypeForEncodingAndBitSize(Encoding encoding,
return GetType(ast.LongDoubleTy);
if (QualTypeMatchesBitSize(bit_size, ast, ast.HalfTy))
return GetType(ast.HalfTy);
if (QualTypeMatchesBitSize(bit_size, ast, ast.Float128Ty))
return GetType(ast.Float128Ty);
break;
case eEncodingVector:
@ -956,6 +958,13 @@ CompilerType TypeSystemClang::GetBuiltinTypeForDWARFEncodingAndBitSize(
if (type_name == "long double" &&
QualTypeMatchesBitSize(bit_size, ast, ast.LongDoubleTy))
return GetType(ast.LongDoubleTy);
// As Rust currently uses `TypeSystemClang`, match `f128` here as well so it
// doesn't get misinterpreted as `long double` on targets where they are
// the same size but different formats.
if ((type_name == "__float128" || type_name == "_Float128" ||
type_name == "f128") &&
QualTypeMatchesBitSize(bit_size, ast, ast.Float128Ty))
return GetType(ast.Float128Ty);
// Fall back to not requiring a name match
if (QualTypeMatchesBitSize(bit_size, ast, ast.FloatTy))
return GetType(ast.FloatTy);
@ -965,6 +974,8 @@ CompilerType TypeSystemClang::GetBuiltinTypeForDWARFEncodingAndBitSize(
return GetType(ast.LongDoubleTy);
if (QualTypeMatchesBitSize(bit_size, ast, ast.HalfTy))
return GetType(ast.HalfTy);
if (QualTypeMatchesBitSize(bit_size, ast, ast.Float128Ty))
return GetType(ast.Float128Ty);
break;
case DW_ATE_signed:
@ -2054,6 +2065,8 @@ TypeSystemClang::GetOpaqueCompilerType(clang::ASTContext *ast,
return ast->DoubleTy.getAsOpaquePtr();
case eBasicTypeLongDouble:
return ast->LongDoubleTy.getAsOpaquePtr();
case eBasicTypeFloat128:
return ast->Float128Ty.getAsOpaquePtr();
case eBasicTypeFloatComplex:
return ast->getComplexType(ast->FloatTy).getAsOpaquePtr();
case eBasicTypeDoubleComplex:
@ -4742,19 +4755,24 @@ CompilerType TypeSystemClang::CreateGenericFunctionPrototype() {
// Exploring the type
const llvm::fltSemantics &
TypeSystemClang::GetFloatTypeSemantics(size_t byte_size) {
TypeSystemClang::GetFloatTypeSemantics(size_t byte_size, lldb::Format format) {
clang::ASTContext &ast = getASTContext();
const size_t bit_size = byte_size * 8;
if (bit_size == ast.getTypeSize(ast.FloatTy))
return ast.getFloatTypeSemantics(ast.FloatTy);
else if (bit_size == ast.getTypeSize(ast.DoubleTy))
return ast.getFloatTypeSemantics(ast.DoubleTy);
else if (format == eFormatFloat128 &&
bit_size == ast.getTypeSize(ast.Float128Ty))
return ast.getFloatTypeSemantics(ast.Float128Ty);
else if (bit_size == ast.getTypeSize(ast.LongDoubleTy) ||
bit_size == llvm::APFloat::semanticsSizeInBits(
ast.getFloatTypeSemantics(ast.LongDoubleTy)))
return ast.getFloatTypeSemantics(ast.LongDoubleTy);
else if (bit_size == ast.getTypeSize(ast.HalfTy))
return ast.getFloatTypeSemantics(ast.HalfTy);
else if (bit_size == ast.getTypeSize(ast.Float128Ty))
return ast.getFloatTypeSemantics(ast.Float128Ty);
return llvm::APFloatBase::Bogus();
}
@ -5232,6 +5250,8 @@ lldb::Format TypeSystemClang::GetFormat(lldb::opaque_compiler_type_t type) {
case clang::BuiltinType::Double:
case clang::BuiltinType::LongDouble:
return lldb::eFormatFloat;
case clang::BuiltinType::Float128:
return lldb::eFormatFloat128;
default:
return lldb::eFormatHex;
}
@ -5529,6 +5549,8 @@ TypeSystemClang::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) {
return eBasicTypeDouble;
case clang::BuiltinType::LongDouble:
return eBasicTypeLongDouble;
case clang::BuiltinType::Float128:
return eBasicTypeFloat128;
case clang::BuiltinType::NullPtr:
return eBasicTypeNullPtr;
@ -6090,6 +6112,7 @@ uint32_t TypeSystemClang::GetNumPointeeChildren(clang::QualType type) {
case clang::BuiltinType::Float:
case clang::BuiltinType::Double:
case clang::BuiltinType::LongDouble:
case clang::BuiltinType::Float128:
case clang::BuiltinType::Dependent:
case clang::BuiltinType::Overload:
case clang::BuiltinType::ObjCId:
@ -8733,6 +8756,7 @@ bool TypeSystemClang::DumpTypeValue(
case eFormatHex:
case eFormatHexUppercase:
case eFormatFloat:
case eFormatFloat128:
case eFormatOctal:
case eFormatOSType:
case eFormatUnsigned:

View File

@ -823,7 +823,8 @@ public:
// Exploring the type
const llvm::fltSemantics &GetFloatTypeSemantics(size_t byte_size) override;
const llvm::fltSemantics &GetFloatTypeSemantics(size_t byte_size,
lldb::Format format) override;
llvm::Expected<uint64_t> GetByteSize(lldb::opaque_compiler_type_t type,
ExecutionContextScope *exe_scope) {

View File

@ -1466,8 +1466,9 @@ bool ValueObject::DumpPrintableRepresentation(
(custom_format == eFormatComplexFloat) ||
(custom_format == eFormatDecimal) || (custom_format == eFormatHex) ||
(custom_format == eFormatHexUppercase) ||
(custom_format == eFormatFloat) || (custom_format == eFormatOctal) ||
(custom_format == eFormatOSType) ||
(custom_format == eFormatFloat) ||
(custom_format == eFormatFloat128) ||
(custom_format == eFormatOctal) || (custom_format == eFormatOSType) ||
(custom_format == eFormatUnicode16) ||
(custom_format == eFormatUnicode32) ||
(custom_format == eFormatUnsigned) ||

View File

@ -163,6 +163,9 @@ TEST_F(DumpDataExtractorTest, Formats) {
TestDump(0xcafef00d, lldb::Format::eFormatHex, "0xcafef00d");
TestDump(0xcafef00d, lldb::Format::eFormatHexUppercase, "0xCAFEF00D");
TestDump(0.456, lldb::Format::eFormatFloat, "0.45600000000000002");
TestDump(std::vector<uint64_t>{0x47ae147ae147ae14, 0x40011147ae147ae1},
lldb::Format::eFormatFloat128,
"4.26999999999999999999999999999999963");
TestDump(9, lldb::Format::eFormatOctal, "011");
// Chars packed into an integer.
TestDump<uint32_t>(0x4C4C4442, lldb::Format::eFormatOSType, "'LLDB'");
@ -388,6 +391,9 @@ TEST_F(DumpDataExtractorTest, ItemByteSizeErrors) {
TestDumpWithItemByteSize(
18, lldb::Format::eFormatFloat,
"error: unsupported byte size (18) for float format");
TestDumpWithItemByteSize(
17, lldb::Format::eFormatFloat128,
"error: unsupported byte size (17) for float format");
// We want sizes to exactly match one of float/double.
TestDumpWithItemByteSize(

View File

@ -76,6 +76,8 @@ TEST_F(TestTypeSystemClang, TestGetBasicTypeFromEnum) {
context.getComplexType(context.FloatTy)));
EXPECT_TRUE(
context.hasSameType(GetBasicQualType(eBasicTypeHalf), context.HalfTy));
EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeFloat128),
context.Float128Ty));
EXPECT_TRUE(
context.hasSameType(GetBasicQualType(eBasicTypeInt), context.IntTy));
EXPECT_TRUE(context.hasSameType(GetBasicQualType(eBasicTypeInt128),