Skip to content

Conversation

tgs-sc
Copy link
Contributor

@tgs-sc tgs-sc commented Sep 9, 2025

During debugging applization with __bf16 and _Float16 float types it was discovered that lldb creates the same CompilerType for them. This can cause an infinite recursion error, if one tries to create two struct specializations with these types and then inherit one specialization from another.

@tgs-sc tgs-sc requested a review from JDevlieghere as a code owner September 9, 2025 13:49
@llvmbot llvmbot added the lldb label Sep 9, 2025
@llvmbot
Copy link
Member

llvmbot commented Sep 9, 2025

@llvm/pr-subscribers-lldb

Author: None (tgs-sc)

Changes

During debugging applization with __bf16 and _Float16 float types it was discovered that lldb creates the same CompilerType for them. This can cause an infinite recursion error, if one tries to create two struct specializations with these types and then inherit one specialization from another. This is an example, provided by @Michael137:

template <typename T> struct Foo;

template <> struct Foo<__bf16> {};

template <> struct Foo<_Float16> : Foo<__bf16> {};

int main() {
  Foo<_Float16> f1;
  return 0;
}

Full diff: https://github.com/llvm/llvm-project/pull/157674.diff

2 Files Affected:

  • (modified) lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp (+7)
  • (modified) lldb/test/API/lang/cpp/template-arguments/TestCppTemplateArguments.py (+1-1)
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index c4a917f59fb88..804ddd042574e 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -959,6 +959,12 @@ CompilerType TypeSystemClang::GetBuiltinTypeForDWARFEncodingAndBitSize(
     if (type_name == "long double" &&
         QualTypeMatchesBitSize(bit_size, ast, ast.LongDoubleTy))
       return GetType(ast.LongDoubleTy);
+    if (type_name == "__bf16" &&
+        QualTypeMatchesBitSize(bit_size, ast, ast.BFloat16Ty))
+      return GetType(ast.BFloat16Ty);
+    if (type_name == "_Float16" &&
+        QualTypeMatchesBitSize(bit_size, ast, ast.Float16Ty))
+      return GetType(ast.Float16Ty);
     // 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.
@@ -1791,6 +1797,7 @@ bool TypeSystemClang::RecordHasFields(const RecordDecl *record_decl) {
     for (base_class = cxx_record_decl->bases_begin(),
         base_class_end = cxx_record_decl->bases_end();
          base_class != base_class_end; ++base_class) {
+      assert(record_decl != base_class->getType()->getAsCXXRecordDecl());
       if (RecordHasFields(base_class->getType()->getAsCXXRecordDecl()))
         return true;
     }
diff --git a/lldb/test/API/lang/cpp/template-arguments/TestCppTemplateArguments.py b/lldb/test/API/lang/cpp/template-arguments/TestCppTemplateArguments.py
index eac7b5ef1099a..f26d382bf8582 100644
--- a/lldb/test/API/lang/cpp/template-arguments/TestCppTemplateArguments.py
+++ b/lldb/test/API/lang/cpp/template-arguments/TestCppTemplateArguments.py
@@ -82,7 +82,7 @@ def test(self):
         value = self.expect_expr("temp7", result_type="Foo<__fp16, __fp16>")
         self.assertFalse(value.GetType().GetTemplateArgumentValue(target, 1))
 
-        value = self.expect_expr("temp8", result_type="Foo<__fp16, __fp16>")
+        value = self.expect_expr("temp8", result_type="Foo<__bf16, __bf16>")
         self.assertFalse(value.GetType().GetTemplateArgumentValue(target, 1))
 
         value = self.expect_expr("temp9", result_type="Bar<double, 1.200000e+00>")

@tgs-sc tgs-sc force-pushed the users/tgs-sc/lldb-add-unique-builtins-for-some-float-types branch 4 times, most recently from 9ee07b2 to a18616f Compare September 10, 2025 10:00
@tgs-sc
Copy link
Contributor Author

tgs-sc commented Sep 10, 2025

@Michael137, Hi, I have added here a test you proposed. Can you please look at this patch as it is blocking merging PR(#154123).

@tgs-sc
Copy link
Contributor Author

tgs-sc commented Sep 10, 2025

@JDevlieghere, hi! Can you also please look at this patch? I think it is pretty obvious.

@tgs-sc
Copy link
Contributor Author

tgs-sc commented Sep 16, 2025

@Michael137, Hi! Sorry for disturbing you. A week has passed, can you please look at this patch?

@@ -1791,6 +1797,7 @@ bool TypeSystemClang::RecordHasFields(const RecordDecl *record_decl) {
for (base_class = cxx_record_decl->bases_begin(),
base_class_end = cxx_record_decl->bases_end();
base_class != base_class_end; ++base_class) {
assert(record_decl != base_class->getType()->getAsCXXRecordDecl());
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
assert(record_decl != base_class->getType()->getAsCXXRecordDecl());
assert(record_decl != base_class->getType()->getAsCXXRecordDecl() && "Base can't inherit from itself.");

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed

@@ -82,7 +82,7 @@ def test(self):
value = self.expect_expr("temp7", result_type="Foo<__fp16, __fp16>")
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't this one show up as _Float16 now? Or is there some other place we're missing support for 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.

There is a mapping in clang/include/clang/AST/BuiltinTypes.def that maps Float16 to HalfTy, so actually it shouldn't be displayed as _Float16.

Copy link
Contributor Author

@tgs-sc tgs-sc Sep 23, 2025

Choose a reason for hiding this comment

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

I can make such change:

clang/include/clang/AST/BuiltinTypes.def

// '_Float16'
FLOATING_TYPE(Float16, HalfTy)

->

clang/include/clang/AST/BuiltinTypes.def

// '_Float16'
FLOATING_TYPE(Float16, Float16Ty)

But I am not sure that it won't break anything. Probably we should ask someone on the clang side why this is made in such way.

…loat16

During debugging applization with __bf16 and _Float16 float types it
was discovered that lldb creates the same CompilerType for them. This
can cause an infinite recursion error, if one tries to create two
struct specializations with these types and then inherit one
specialization from another.
@tgs-sc tgs-sc force-pushed the users/tgs-sc/lldb-add-unique-builtins-for-some-float-types branch from a18616f to 7461016 Compare September 23, 2025 13:42
@tgs-sc
Copy link
Contributor Author

tgs-sc commented Sep 30, 2025

@Michael137, can you please look at this?

@tgs-sc
Copy link
Contributor Author

tgs-sc commented Oct 1, 2025

@Michael137, can you please then merge this patch? Because I don't have corresponding rights.

@Michael137 Michael137 merged commit 0a0d497 into llvm:main Oct 1, 2025
9 checks passed
@DavidSpickett
Copy link
Collaborator

This is failing on Arm 32-bit: https://lab.llvm.org/buildbot/#/builders/18/builds/21624

--
UNSUPPORTED: LLDB (/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/bin/clang-arm) :: test_dsym (TestCppFloatingTypesSpecialization.TestCase) (test case does not fall in any category of interest for this run) 
FAIL: LLDB (/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/bin/clang-arm) :: test_dwarf (TestCppFloatingTypesSpecialization.TestCase)
FAIL: LLDB (/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/bin/clang-arm) :: test_dwo (TestCppFloatingTypesSpecialization.TestCase)
======================================================================
FAIL: test_dwarf (TestCppFloatingTypesSpecialization.TestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/tcwg-buildbot/worker/lldb-arm-ubuntu/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 1804, in test_method
    return attrvalue(self)
  File "/home/tcwg-buildbot/worker/lldb-arm-ubuntu/llvm-project/lldb/test/API/lang/cpp/floating-types-specialization/TestCppFloatingTypesSpecialization.py", line 14, in test
    self.expect_expr("f0", result_type="Foo<__bf16>")
  File "/home/tcwg-buildbot/worker/lldb-arm-ubuntu/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 2572, in expect_expr
    value_check.check_value(self, eval_result, str(eval_result))
  File "/home/tcwg-buildbot/worker/lldb-arm-ubuntu/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 315, in check_value
    test_base.assertEqual(
AssertionError: 'Foo<__bf16>' != 'Foo<__fp16>'
- Foo<__bf16>
?       -
+ Foo<__fp16>
?        +
 : (Foo<__fp16>) $0 = {}
Checking SBValue: (Foo<__fp16>) $0 = {}
Config=arm-/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/bin/clang
======================================================================
FAIL: test_dwo (TestCppFloatingTypesSpecialization.TestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/tcwg-buildbot/worker/lldb-arm-ubuntu/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 1804, in test_method
    return attrvalue(self)
  File "/home/tcwg-buildbot/worker/lldb-arm-ubuntu/llvm-project/lldb/test/API/lang/cpp/floating-types-specialization/TestCppFloatingTypesSpecialization.py", line 14, in test
    self.expect_expr("f0", result_type="Foo<__bf16>")
  File "/home/tcwg-buildbot/worker/lldb-arm-ubuntu/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 2572, in expect_expr
    value_check.check_value(self, eval_result, str(eval_result))
  File "/home/tcwg-buildbot/worker/lldb-arm-ubuntu/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 315, in check_value
    test_base.assertEqual(
AssertionError: 'Foo<__bf16>' != 'Foo<__fp16>'
- Foo<__bf16>
?       -
+ Foo<__fp16>
?        +
 : (Foo<__fp16>) $0 = {}
Checking SBValue: (Foo<__fp16>) $0 = {}
Config=arm-/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/bin/clang
----------------------------------------------------------------------
Ran 3 tests in 2.714s

FAILED (failures=2, skipped=1)

AArch64 is fine - https://lab.llvm.org/buildbot/#/builders/59/builds/25028

Gonna look at the test case a bit more to see why.

@DavidSpickett
Copy link
Collaborator

A few printfs later:

(lldb) p f0
Typename::::::::::>>>>>>> __bf16
has bfloat16?: 0
HasBfloat16: 0
FPU: 0
SoftFloat: 0
Qual type: __bf16
qual_type_bit_size = 0, bit_size = 16
Qual type: float
qual_type_bit_size = 32, bit_size = 16
Qual type: double
qual_type_bit_size = 64, bit_size = 16
Qual type: long double
qual_type_bit_size = 64, bit_size = 16
Qual type: __fp16
qual_type_bit_size = 16, bit_size = 16
(Foo<__fp16>)  {}

ARM has a bf16 type in the AST context only if this is true:

bool ARMTargetInfo::hasBFloat16Type() const {
  // The __bf16 type is generally available so long as we have any fp registers.
  return HasBFloat16 || (FPU && !SoftFloat);
}

And for whatever reason, the lookup is set to a target without bf16 or an FPU. Not sure where we pull the target setting from (istr some triple to core details mapping) but regardless, we're missing FPU (which my host does have) and bfloat16 (which my host does not have).

For AArch64 this method just returns true.

I'll find the source of the target type but in the meantime I'll skip or work around this failure.

DavidSpickett added a commit that referenced this pull request Oct 1, 2025
Fixes #157674

On ARM, the presence of a specific bf16 type in the AST is gated by: 
```
bool ARMTargetInfo::hasBFloat16Type() const {
  // The __bf16 type is generally available so long as we have any fp registers.
  return HasBFloat16 || (FPU && !SoftFloat);
}
```

And the target we use when evaluating symbols (derived from the program
file, I think, haven't found it yet) does not enable any of this.

This means that we fall back to __fp16.

So for parts of the testing we just need to expect __fp16 instead, and
others we need to skip because now a class looks like it inherits from
itself.

There's a proper fix here somewhere but I don't know what it is yet.
mahesh-attarde pushed a commit to mahesh-attarde/llvm-project that referenced this pull request Oct 3, 2025
…loat16 (llvm#157674)

During debugging applization with __bf16 and _Float16 float types it was
discovered that lldb creates the same CompilerType for them. This can
cause an infinite recursion error, if one tries to create two struct
specializations with these types and then inherit one specialization
from another.
mahesh-attarde pushed a commit to mahesh-attarde/llvm-project that referenced this pull request Oct 3, 2025
Fixes llvm#157674

On ARM, the presence of a specific bf16 type in the AST is gated by: 
```
bool ARMTargetInfo::hasBFloat16Type() const {
  // The __bf16 type is generally available so long as we have any fp registers.
  return HasBFloat16 || (FPU && !SoftFloat);
}
```

And the target we use when evaluating symbols (derived from the program
file, I think, haven't found it yet) does not enable any of this.

This means that we fall back to __fp16.

So for parts of the testing we just need to expect __fp16 instead, and
others we need to skip because now a class looks like it inherits from
itself.

There's a proper fix here somewhere but I don't know what it is yet.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants