Skip to content

Conversation

@Michael137
Copy link
Member

As of recent, LLVM includes the bit-size as a DW_AT_bit_size (and as part of DW_AT_name) of _BitInts in DWARF. This allows us to mark _BitInts as "reconstitutable" when compiling with -gsimple-template-names. However, before doing so we need to make sure the DWARFTypePrinter can reconstruct template parameter values that have _BitInt type. This patch adds support for printing DW_TAG_template_value_parameters that have _BitInt type. Since -gsimple-template-names only omits template parameters that are <= 64 bit wide, we don't support _BitInts larger than 64 bits.

@llvmbot
Copy link
Member

llvmbot commented Nov 17, 2025

@llvm/pr-subscribers-debuginfo

Author: Michael Buch (Michael137)

Changes

As of recent, LLVM includes the bit-size as a DW_AT_bit_size (and as part of DW_AT_name) of _BitInts in DWARF. This allows us to mark _BitInts as "reconstitutable" when compiling with -gsimple-template-names. However, before doing so we need to make sure the DWARFTypePrinter can reconstruct template parameter values that have _BitInt type. This patch adds support for printing DW_TAG_template_value_parameters that have _BitInt type. Since -gsimple-template-names only omits template parameters that are &lt;= 64 bit wide, we don't support _BitInts larger than 64 bits.


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

2 Files Affected:

  • (modified) llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h (+40-4)
  • (modified) llvm/unittests/DebugInfo/DWARF/DWARFDieTest.cpp (+140)
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h
index a760f773055d2..9f6bcfb873b4d 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h
@@ -13,6 +13,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/Support/Error.h"
+#include "llvm/Support/FormatVariadic.h"
 
 #include <string>
 
@@ -78,6 +79,12 @@ template <typename DieType> struct DWARFTypePrinter {
     }
     return false;
   }
+
+  /// If FormValue is a valid constant Form, print into \c OS the integral value
+  /// casted to the type referred to by \c Cast.
+  template <typename FormValueType>
+  void appendCastedValue(const FormValueType &FormValue, DieType Cast,
+                         bool IsUnsigned);
 };
 
 template <typename DieType>
@@ -413,6 +420,31 @@ DieType DWARFTypePrinter<DieType>::appendQualifiedNameBefore(DieType D) {
   return appendUnqualifiedNameBefore(D);
 }
 
+template <typename DieType>
+template <typename FormValueType>
+void DWARFTypePrinter<DieType>::appendCastedValue(
+    const FormValueType &FormValue, DieType Cast, bool IsUnsigned) {
+  std::string ValStr;
+  if (IsUnsigned) {
+    std::optional<uint64_t> UVal = FormValue.getAsUnsignedConstant();
+    if (!UVal)
+      return;
+
+    ValStr = std::to_string(*UVal);
+  } else {
+    std::optional<int64_t> SVal = FormValue.getAsSignedConstant();
+    if (!SVal)
+      return;
+
+    ValStr = std::to_string(*SVal);
+  }
+
+  OS << '(';
+  appendQualifiedName(Cast);
+  OS << ')';
+  OS << std::move(ValStr);
+}
+
 template <typename DieType>
 bool DWARFTypePrinter<DieType>::appendTemplateParameters(DieType D,
                                                          bool *FirstParameter) {
@@ -438,13 +470,11 @@ bool DWARFTypePrinter<DieType>::appendTemplateParameters(DieType D,
       DieType T = detail::resolveReferencedType(C);
       Sep();
       if (T.getTag() == dwarf::DW_TAG_enumeration_type) {
-        OS << '(';
-        appendQualifiedName(T);
-        OS << ')';
         auto V = C.find(dwarf::DW_AT_const_value);
-        OS << std::to_string(*V->getAsSignedConstant());
+        appendCastedValue(*V, T, /*IsUnsigned=*/false);
         continue;
       }
+
       // /Maybe/ we could do pointer/reference type parameters, looking for the
       // symbol in the ELF symbol table to get back to the variable...
       // but probably not worth it.
@@ -539,6 +569,12 @@ bool DWARFTypePrinter<DieType>::appendTemplateParameters(DieType D,
           else
             OS << llvm::format("'\\U%08" PRIx64 "'", Val);
         }
+        // FIXME: Handle _BitInt's larger than 64-bits which are emitted as
+        // block data.
+      } else if (Name.starts_with("_BitInt")) {
+        appendCastedValue(*V, T, /*IsUnsigned=*/false);
+      } else if (Name.starts_with("unsigned _BitInt")) {
+        appendCastedValue(*V, T, /*IsUnsigned=*/true);
       }
       continue;
     }
diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDieTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDieTest.cpp
index f566bee170236..a3fafec9e7813 100644
--- a/llvm/unittests/DebugInfo/DWARF/DWARFDieTest.cpp
+++ b/llvm/unittests/DebugInfo/DWARF/DWARFDieTest.cpp
@@ -839,4 +839,144 @@ TEST(DWARFDie, DWARFTypePrinterTest) {
   testAppendQualifiedName(Ctx->getDIEForOffset(0x1a), "t1<t3<int> >::t2");
   testAppendQualifiedName(Ctx->getDIEForOffset(0x28), "t3<int>::my_int");
 }
+
+TEST(DWARFDie, DWARFTypePrinterTest_BitInt) {
+  // Make sure we can reconstruct the case where a template value parameter
+  // is a _BitInt.
+
+  // DW_TAG_compile_unit
+  //   DW_TAG_base_type
+  //     DW_AT_name      ("_BitInt(2)")
+  //     DW_AT_bit_size ("2")
+  //   DW_TAG_base_type
+  //     DW_AT_name      ("_BitInt(65)")
+  //     DW_AT_bit_size ("65")
+  //   DW_TAG_base_type
+  //     DW_AT_name      ("unsigned _BitInt(2)")
+  //     DW_AT_bit_size ("2")
+  //   DW_TAG_base_type
+  //     DW_AT_name      ("unsigned _BitInt(65)")
+  //     DW_AT_bit_size ("65")
+  //   DW_TAG_structure_type
+  //     DW_AT_name      ("foo")
+  //     DW_TAG_template_value_parameter
+  //       DW_AT_type    ("_BitInt(2)")
+  //       DW_AT_const_value (DW_FORM_sdata "-1")
+  //     DW_TAG_template_value_parameter
+  //       DW_AT_type    ("unsigned _BitInt(2)")
+  //       DW_AT_const_value (DW_FORM_udata "12")
+  //     DW_TAG_template_value_parameter
+  //       DW_AT_type    ("_BitInt(65)")
+  //       DW_AT_const_value (DW_FORM_block1 "1")
+  //     DW_TAG_template_value_parameter
+  //       DW_AT_type    ("unsigned _BitInt(65)")
+  //       DW_AT_const_value (DW_FORM_block1 "1")
+  //     NULL
+  //   NULL
+  const char *yamldata = R"(
+  debug_abbrev:
+    - ID:              0
+      Table:
+        - Code:            0x1
+          Tag:             DW_TAG_compile_unit
+          Children:        DW_CHILDREN_yes
+        - Code:            0x2
+          Tag:             DW_TAG_base_type
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_string
+        - Code:            0x3
+          Tag:             DW_TAG_structure_type
+          Children:        DW_CHILDREN_yes
+          Attributes:
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_string
+        - Code:            0x4
+          Tag:             DW_TAG_template_value_parameter
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_type
+              Form:            DW_FORM_ref4
+            - Attribute:       DW_AT_const_value
+              Form:            DW_FORM_sdata
+        - Code:            0x5
+          Tag:             DW_TAG_template_value_parameter
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_type
+              Form:            DW_FORM_ref4
+            - Attribute:       DW_AT_const_value
+              Form:            DW_FORM_udata
+        - Code:            0x6
+          Tag:             DW_TAG_template_value_parameter
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_type
+              Form:            DW_FORM_ref4
+            - Attribute:       DW_AT_const_value
+              Form:            DW_FORM_block1
+  debug_info:
+    - Version:         4
+      AddrSize:        8
+      Entries:
+        - AbbrCode:        0x1
+        - AbbrCode:        0x2
+          Values:
+            - Value:           0xDEADBEEFDEADBEEF
+              CStr:            _BitInt(2)
+        - AbbrCode:        0x2
+          Values:
+            - Value:           0xDEADBEEFDEADBEEF
+              CStr:            _BitInt(65)
+        - AbbrCode:        0x2
+          Values:
+            - Value:           0xDEADBEEFDEADBEEF
+              CStr:            unsigned _BitInt(2)
+        - AbbrCode:        0x2
+          Values:
+            - Value:           0xDEADBEEFDEADBEEF
+              CStr:            unsigned _BitInt(65)
+        - AbbrCode:        0x3
+          Values:
+            - Value:           0xDEADBEEFDEADBEEF
+              CStr:            foo
+        - AbbrCode:        0x4
+          Values:
+            - Value:            0x0000000c
+            - Value:            0xffffffffffffffff
+        - AbbrCode:        0x5
+          Values:
+            - Value:            0x00000025
+            - Value:            12
+        - AbbrCode:        0x6
+          Values:
+            - Value:            0x00000018
+            - Value:            0x0F
+              BlockData:       [ 0x22, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+                                 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]     
+        - AbbrCode:        0x6
+          Values:
+            - Value:            0x0000003a
+            - Value:            0x0F
+              BlockData:       [ 0x22, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+                                 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]     
+        - AbbrCode:        0x0
+        - AbbrCode:        0x0
+)";
+  Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections =
+      DWARFYAML::emitDebugSections(StringRef(yamldata),
+                                   /*IsLittleEndian=*/true,
+                                   /*Is64BitAddrSize=*/true);
+  ASSERT_THAT_EXPECTED(Sections, Succeeded());
+  std::unique_ptr<DWARFContext> Ctx =
+      DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true);
+
+  // FIXME: support _BitInt's with block forms. Currently they are just omitted.
+  // Will be necessary once -gsimple-template-names emit template value
+  // parameters with bit-width larger than 64.
+  testAppendAndTerminateTemplateParameters(
+      Ctx->getDIEForOffset(0x50),
+      "<(_BitInt(2))-1, (unsigned _BitInt(2))12, , >");
+}
 } // end anonymous namespace

Michael137 added a commit to Michael137/llvm-project that referenced this pull request Nov 17, 2025
…simple-template-names

Depends on:
* llvm#168382

As of recent, LLVM includes the bit-size as a `DW_AT_bit_size` (and as part of `DW_AT_name`) of `_BitInt`s in DWARF. This allows us to mark `_BitInt`s as "reconstitutable" when compiling with `-gsimple-template-names`. We still only omits template parameters that are `<= 64` bit wide. So support `_BitInt`s larger than 64 bits is not part of this patch.
Michael137 added a commit to Michael137/llvm-project that referenced this pull request Nov 17, 2025
…simple-template-names

Depends on:
* llvm#168382

As of recent, LLVM includes the bit-size as a `DW_AT_bit_size` (and as part of `DW_AT_name`) of `_BitInt`s in DWARF. This allows us to mark `_BitInt`s as "reconstitutable" when compiling with `-gsimple-template-names`. We still only omits template parameters that are `<= 64` bit wide. So support `_BitInt`s larger than 64 bits is not part of this patch.
@@ -839,4 +839,144 @@ TEST(DWARFDie, DWARFTypePrinterTest) {
testAppendQualifiedName(Ctx->getDIEForOffset(0x1a), "t1<t3<int> >::t2");
testAppendQualifiedName(Ctx->getDIEForOffset(0x28), "t3<int>::my_int");
}

TEST(DWARFDie, DWARFTypePrinterTest_BitInt) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Most of the testing for the printing roundtripping is happening in llvm/test/tools/llvm-dwarfdump/X86/simplified-template-names.s - could this testing be added there (& in the cross-project-tests that it depends on)

Copy link
Member Author

Choose a reason for hiding this comment

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

Yea I was going to change those but realised they don't run on Darwin (not sure why). But I don't have a Linux machine handy to test it on. I could test it via PR CI (by trial and error).

Do you want me to remove the unit-test if we add it to simplified-template-names.s?

@Michael137 Michael137 force-pushed the llvm/dwarf-type-printer-bitint branch from 7864dc3 to 8b2f10e Compare November 17, 2025 21:39
@github-actions
Copy link

github-actions bot commented Nov 17, 2025

🐧 Linux x64 Test Results

  • 186260 tests passed
  • 4852 tests skipped

@Michael137 Michael137 force-pushed the llvm/dwarf-type-printer-bitint branch from d1b4a69 to baac83d Compare November 17, 2025 22:20
Michael137 added a commit to Michael137/llvm-project that referenced this pull request Nov 19, 2025
…simple-template-names

Depends on:
* llvm#168382

As of recent, LLVM includes the bit-size as a `DW_AT_bit_size` (and as part of `DW_AT_name`) of `_BitInt`s in DWARF. This allows us to mark `_BitInt`s as "reconstitutable" when compiling with `-gsimple-template-names`. We still only omits template parameters that are `<= 64` bit wide. So support `_BitInt`s larger than 64 bits is not part of this patch.
Michael137 added a commit to Michael137/llvm-project that referenced this pull request Nov 19, 2025
…simple-template-names

Depends on:
* llvm#168382

As of recent, LLVM includes the bit-size as a `DW_AT_bit_size` (and as part of `DW_AT_name`) of `_BitInt`s in DWARF. This allows us to mark `_BitInt`s as "reconstitutable" when compiling with `-gsimple-template-names`. We still only omits template parameters that are `<= 64` bit wide. So support `_BitInt`s larger than 64 bits is not part of this patch.
As of recent, LLVM includes the bit-size as a `DW_AT_bit_size` (and as part of `DW_AT_name`) of `_BitInt`s in DWARF. This allows us to mark `_BitInt`s as "reconstitutable" when compiling with `-gsimple-template-names`.  However, before doing so we need to make sure the `DWARFTypePrinter` can reconstruct template parameter values that have `_BitInt` type. This patch adds support for printing `DW_TAG_template_value_parameter`s that have `_BitInt` type. Since `-gsimple-template-names` only omits template parameters that are `<= 64` bit wide, we don't support `_BitInt`s larger than 64 bits.
@Michael137 Michael137 force-pushed the llvm/dwarf-type-printer-bitint branch from baac83d to cce8b0d Compare November 19, 2025 22:25
@Michael137
Copy link
Member Author

Merging based on approval in #168383 (review)

@Michael137 Michael137 enabled auto-merge (squash) November 19, 2025 22:49
Michael137 added a commit to Michael137/llvm-project that referenced this pull request Nov 19, 2025
…simple-template-names

Depends on:
* llvm#168382

As of recent, LLVM includes the bit-size as a `DW_AT_bit_size` (and as part of `DW_AT_name`) of `_BitInt`s in DWARF. This allows us to mark `_BitInt`s as "reconstitutable" when compiling with `-gsimple-template-names`. We still only omits template parameters that are `<= 64` bit wide. So support `_BitInt`s larger than 64 bits is not part of this patch.
@Michael137 Michael137 merged commit e99c83f into llvm:main Nov 19, 2025
7 of 9 checks passed
@Michael137 Michael137 deleted the llvm/dwarf-type-printer-bitint branch November 19, 2025 23:20
Michael137 added a commit that referenced this pull request Nov 19, 2025
…simple-template-names (#168383)

Depends on:
* #168382

As of recent, LLVM includes the bit-size as a `DW_AT_bit_size` (and as
part of `DW_AT_name`) of `_BitInt`s in DWARF. This allows us to mark
`_BitInt`s as "reconstitutable" when compiling with
`-gsimple-template-names`. We still only omit template parameters that
are `<= 64` bit wide. So support `_BitInt`s larger than 64 bits is not
part of this patch.
llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request Nov 20, 2025
…emitting -gsimple-template-names (#168383)

Depends on:
* llvm/llvm-project#168382

As of recent, LLVM includes the bit-size as a `DW_AT_bit_size` (and as
part of `DW_AT_name`) of `_BitInt`s in DWARF. This allows us to mark
`_BitInt`s as "reconstitutable" when compiling with
`-gsimple-template-names`. We still only omit template parameters that
are `<= 64` bit wide. So support `_BitInt`s larger than 64 bits is not
part of this patch.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants