Skip to content

[lldb] Add support for displaying __float128 variables #98369

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lldb/bindings/python/python-extensions.swig
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions lldb/docs/python_api_enums.rst
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ Format
.. py:data:: eFormatInstruction
.. py:data:: eFormatVoid
.. py:data:: eFormatUnicode8
.. py:data:: eFormatFloat128
.. _DescriptionLevel:
Expand Down Expand Up @@ -1045,6 +1046,7 @@ BasicType
.. py:data:: eBasicTypeObjCSel
.. py:data:: eBasicTypeNullPtr
.. py:data:: eBasicTypeOther
.. py:data:: eBasicTypeFloat128
.. _TraceType:
Expand Down
3 changes: 2 additions & 1 deletion lldb/include/lldb/Symbol/TypeSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,8 @@ class TypeSystem : public PluginInterface,

// 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,
Expand Down
15 changes: 10 additions & 5 deletions lldb/include/lldb/lldb-enumerations.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you remove the formatting changes to this part?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately git clang-format made those changes, and CI will complain if I remove them.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As the codebase isn't 100% formatted, it's fine to ignore the formatter sometimes. Generally I'd push a reformat NFC commit directly before or after the PR changes, but here I think it'd need to be after. This means folks can ignore the NFC change without skipping over functional changes like this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've moved the formatting-only changes to a separate commit.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI that llvm does squash and merge only, so the commits will become one. So you can either push each part of this PR manually or push the formatting change separately after the PR goes in.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy to remove the formatting change from this PR, but that will cause the PR CI to fail. Will that be an issue? (I don't have commit access so I can't push anything directly.)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the format check doesn't block merging.

Copy link
Contributor Author

@beetrees beetrees Jul 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've dropped the formatting change from this PR.

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
};

Expand Down Expand Up @@ -838,7 +842,8 @@ enum BasicType {
eBasicTypeObjCClass,
eBasicTypeObjCSel,
eBasicTypeNullPtr,
eBasicTypeOther
eBasicTypeOther,
eBasicTypeFloat128
};

/// Deprecated
Expand Down
2 changes: 2 additions & 0 deletions lldb/source/Commands/CommandObjectMemory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ class OptionGroupReadMemory : public OptionGroup {

case eFormatBinary:
case eFormatFloat:
case eFormatFloat128:
case eFormatOctal:
case eFormatDecimal:
case eFormatEnum:
Expand Down Expand Up @@ -1356,6 +1357,7 @@ class CommandObjectMemoryWrite : public CommandObjectParsed {
switch (m_format_options.GetFormat()) {
case kNumFormats:
case eFormatFloat: // TODO: add support for floats soon
case eFormatFloat128:
case eFormatCharPrintable:
case eFormatBytesWithASCII:
case eFormatComplex:
Expand Down
16 changes: 12 additions & 4 deletions lldb/source/Core/DumpDataExtractor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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();
}

Expand Down Expand Up @@ -653,6 +660,7 @@ lldb::offset_t lldb_private::DumpDataExtractor(
}
} break;

case eFormatFloat128:
case eFormatFloat: {
TargetSP target_sp;
if (exe_scope)
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions lldb/source/DataFormatters/FormatManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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])) ==
Expand Down
2 changes: 2 additions & 0 deletions lldb/source/DataFormatters/VectorType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
26 changes: 25 additions & 1 deletion lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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);
Expand All @@ -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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this fallback branch?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the user formats a 128-bit value using eFormatFloat on a target where the only 128-bit float is float128 (a.k.a. long double is some other size), then the value should be formatted as a float128. The eFormatFloat128 format is only needed to disambiguate when long double and float128 are both 128 bits.

return ast.getFloatTypeSemantics(ast.Float128Ty);
return llvm::APFloatBase::Bogus();
}

Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -8733,6 +8756,7 @@ bool TypeSystemClang::DumpTypeValue(
case eFormatHex:
case eFormatHexUppercase:
case eFormatFloat:
case eFormatFloat128:
case eFormatOctal:
case eFormatOSType:
case eFormatUnsigned:
Expand Down
3 changes: 2 additions & 1 deletion lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
Original file line number Diff line number Diff line change
Expand Up @@ -823,7 +823,8 @@ class TypeSystemClang : public TypeSystem {

// 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) {
Expand Down
5 changes: 3 additions & 2 deletions lldb/source/ValueObject/ValueObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) ||
Expand Down
6 changes: 6 additions & 0 deletions lldb/unittests/Core/DumpDataExtractorTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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'");
Expand Down Expand Up @@ -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(
Expand Down
2 changes: 2 additions & 0 deletions lldb/unittests/Symbol/TestTypeSystemClang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
Loading