[llvm] Fix AsmWriter to account for dynamic bit offsets (PR #146704)

Tom Tromey via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 2 13:24:36 PDT 2025


https://github.com/tromey updated https://github.com/llvm/llvm-project/pull/146704

>From 16f9ec04edc8088e38229bef63837f6e5695605e Mon Sep 17 00:00:00 2001
From: Tom Tromey <tromey at adacore.com>
Date: Tue, 1 Jul 2025 14:17:27 -0600
Subject: [PATCH] Fix AsmWriter to account for dynamic bit offsets

PR #141106 changed the debug metadata to allow dynamic bit offsets and
sizes.  In that patch, I forgot to update AsmWriter to handle this
case.

This patch corrects the oversight.
---
 llvm/lib/IR/AsmWriter.cpp                   | 82 ++++++++++-----------
 llvm/test/DebugInfo/X86/dynamic-bitfield.ll |  4 +-
 2 files changed, 44 insertions(+), 42 deletions(-)

diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index af268b4fc6941..6d66e6402031c 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -1914,6 +1914,8 @@ struct MDFieldPrinter {
                    bool ShouldSkipEmpty = true);
   void printMetadata(StringRef Name, const Metadata *MD,
                      bool ShouldSkipNull = true);
+  void printMetadataOrInt(StringRef Name, const Metadata *MD, bool IsUnsigned,
+                          bool ShouldSkipZero = true);
   template <class IntTy>
   void printInt(StringRef Name, IntTy Int, bool ShouldSkipZero = true);
   void printAPInt(StringRef Name, const APInt &Int, bool IsUnsigned,
@@ -1986,6 +1988,21 @@ void MDFieldPrinter::printMetadata(StringRef Name, const Metadata *MD,
   writeMetadataAsOperand(Out, MD, WriterCtx);
 }
 
+void MDFieldPrinter::printMetadataOrInt(StringRef Name, const Metadata *MD,
+                                        bool IsUnsigned, bool ShouldSkipZero) {
+  if (!MD)
+    return;
+
+  if (auto *CI = dyn_cast<ConstantAsMetadata>(MD)) {
+    auto *CV = cast<ConstantInt>(CI->getValue());
+    if (IsUnsigned)
+      printInt(Name, CV->getZExtValue(), ShouldSkipZero);
+    else
+      printInt(Name, CV->getSExtValue(), ShouldSkipZero);
+  } else
+    printMetadata(Name, MD);
+}
+
 template <class IntTy>
 void MDFieldPrinter::printInt(StringRef Name, IntTy Int, bool ShouldSkipZero) {
   if (ShouldSkipZero && !Int)
@@ -2129,38 +2146,21 @@ static void writeDISubrange(raw_ostream &Out, const DISubrange *N,
   Out << "!DISubrange(";
   MDFieldPrinter Printer(Out, WriterCtx);
 
-  auto *Count = N->getRawCountNode();
-  if (auto *CE = dyn_cast_or_null<ConstantAsMetadata>(Count)) {
-    auto *CV = cast<ConstantInt>(CE->getValue());
-    Printer.printInt("count", CV->getSExtValue(),
-                     /* ShouldSkipZero */ false);
-  } else
-    Printer.printMetadata("count", Count, /*ShouldSkipNull */ true);
+  Printer.printMetadataOrInt("count", N->getRawCountNode(),
+                             /* IsUnsigned */ false,
+                             /* ShouldSkipZero */ false);
 
   // A lowerBound of constant 0 should not be skipped, since it is different
   // from an unspecified lower bound (= nullptr).
-  auto *LBound = N->getRawLowerBound();
-  if (auto *LE = dyn_cast_or_null<ConstantAsMetadata>(LBound)) {
-    auto *LV = cast<ConstantInt>(LE->getValue());
-    Printer.printInt("lowerBound", LV->getSExtValue(),
-                     /* ShouldSkipZero */ false);
-  } else
-    Printer.printMetadata("lowerBound", LBound, /*ShouldSkipNull */ true);
-
-  auto *UBound = N->getRawUpperBound();
-  if (auto *UE = dyn_cast_or_null<ConstantAsMetadata>(UBound)) {
-    auto *UV = cast<ConstantInt>(UE->getValue());
-    Printer.printInt("upperBound", UV->getSExtValue(),
-                     /* ShouldSkipZero */ false);
-  } else
-    Printer.printMetadata("upperBound", UBound, /*ShouldSkipNull */ true);
-
-  auto *Stride = N->getRawStride();
-  if (auto *SE = dyn_cast_or_null<ConstantAsMetadata>(Stride)) {
-    auto *SV = cast<ConstantInt>(SE->getValue());
-    Printer.printInt("stride", SV->getSExtValue(), /* ShouldSkipZero */ false);
-  } else
-    Printer.printMetadata("stride", Stride, /*ShouldSkipNull */ true);
+  Printer.printMetadataOrInt("lowerBound", N->getRawLowerBound(),
+                             /* IsUnsigned */ false,
+                             /* ShouldSkipZero */ false);
+  Printer.printMetadataOrInt("upperBound", N->getRawUpperBound(),
+                             /* IsUnsigned */ false,
+                             /* ShouldSkipZero */ false);
+  Printer.printMetadataOrInt("stride", N->getRawStride(),
+                             /* IsUnsigned */ false,
+                             /* ShouldSkipZero */ false);
 
   Out << ")";
 }
@@ -2226,13 +2226,13 @@ static void writeDIEnumerator(raw_ostream &Out, const DIEnumerator *N,
 }
 
 static void writeDIBasicType(raw_ostream &Out, const DIBasicType *N,
-                             AsmWriterContext &) {
+                             AsmWriterContext &WriterCtx) {
   Out << "!DIBasicType(";
-  MDFieldPrinter Printer(Out);
+  MDFieldPrinter Printer(Out, WriterCtx);
   if (N->getTag() != dwarf::DW_TAG_base_type)
     Printer.printTag(N);
   Printer.printString("name", N->getName());
-  Printer.printInt("size", N->getSizeInBits());
+  Printer.printMetadataOrInt("size", N->getRawSizeInBits(), true);
   Printer.printInt("align", N->getAlignInBits());
   Printer.printDwarfEnum("encoding", N->getEncoding(),
                          dwarf::AttributeEncodingString);
@@ -2242,13 +2242,13 @@ static void writeDIBasicType(raw_ostream &Out, const DIBasicType *N,
 }
 
 static void writeDIFixedPointType(raw_ostream &Out, const DIFixedPointType *N,
-                                  AsmWriterContext &) {
+                                  AsmWriterContext &WriterCtx) {
   Out << "!DIFixedPointType(";
-  MDFieldPrinter Printer(Out);
+  MDFieldPrinter Printer(Out, WriterCtx);
   if (N->getTag() != dwarf::DW_TAG_base_type)
     Printer.printTag(N);
   Printer.printString("name", N->getName());
-  Printer.printInt("size", N->getSizeInBits());
+  Printer.printMetadataOrInt("size", N->getRawSizeInBits(), true);
   Printer.printInt("align", N->getAlignInBits());
   Printer.printDwarfEnum("encoding", N->getEncoding(),
                          dwarf::AttributeEncodingString);
@@ -2275,7 +2275,7 @@ static void writeDIStringType(raw_ostream &Out, const DIStringType *N,
   Printer.printMetadata("stringLengthExpression", N->getRawStringLengthExp());
   Printer.printMetadata("stringLocationExpression",
                         N->getRawStringLocationExp());
-  Printer.printInt("size", N->getSizeInBits());
+  Printer.printMetadataOrInt("size", N->getRawSizeInBits(), true);
   Printer.printInt("align", N->getAlignInBits());
   Printer.printDwarfEnum("encoding", N->getEncoding(),
                          dwarf::AttributeEncodingString);
@@ -2293,9 +2293,9 @@ static void writeDIDerivedType(raw_ostream &Out, const DIDerivedType *N,
   Printer.printInt("line", N->getLine());
   Printer.printMetadata("baseType", N->getRawBaseType(),
                         /* ShouldSkipNull */ false);
-  Printer.printInt("size", N->getSizeInBits());
+  Printer.printMetadataOrInt("size", N->getRawSizeInBits(), true);
   Printer.printInt("align", N->getAlignInBits());
-  Printer.printInt("offset", N->getOffsetInBits());
+  Printer.printMetadataOrInt("offset", N->getRawOffsetInBits(), true);
   Printer.printDIFlags("flags", N->getFlags());
   Printer.printMetadata("extraData", N->getRawExtraData());
   if (const auto &DWARFAddressSpace = N->getDWARFAddressSpace())
@@ -2323,7 +2323,7 @@ static void writeDISubrangeType(raw_ostream &Out, const DISubrangeType *N,
   Printer.printMetadata("scope", N->getRawScope());
   Printer.printMetadata("file", N->getRawFile());
   Printer.printInt("line", N->getLine());
-  Printer.printInt("size", N->getSizeInBits());
+  Printer.printMetadataOrInt("size", N->getRawSizeInBits(), true);
   Printer.printInt("align", N->getAlignInBits());
   Printer.printDIFlags("flags", N->getFlags());
   Printer.printMetadata("baseType", N->getRawBaseType(),
@@ -2345,9 +2345,9 @@ static void writeDICompositeType(raw_ostream &Out, const DICompositeType *N,
   Printer.printMetadata("file", N->getRawFile());
   Printer.printInt("line", N->getLine());
   Printer.printMetadata("baseType", N->getRawBaseType());
-  Printer.printInt("size", N->getSizeInBits());
+  Printer.printMetadataOrInt("size", N->getRawSizeInBits(), true);
   Printer.printInt("align", N->getAlignInBits());
-  Printer.printInt("offset", N->getOffsetInBits());
+  Printer.printMetadataOrInt("offset", N->getRawOffsetInBits(), true);
   Printer.printInt("num_extra_inhabitants", N->getNumExtraInhabitants());
   Printer.printDIFlags("flags", N->getFlags());
   Printer.printMetadata("elements", N->getRawElements());
diff --git a/llvm/test/DebugInfo/X86/dynamic-bitfield.ll b/llvm/test/DebugInfo/X86/dynamic-bitfield.ll
index eda4ff0f8f6d1..c9148ca4582f6 100644
--- a/llvm/test/DebugInfo/X86/dynamic-bitfield.ll
+++ b/llvm/test/DebugInfo/X86/dynamic-bitfield.ll
@@ -1,4 +1,6 @@
-; RUN: llc -mtriple=x86_64 -O0 -filetype=obj -o - %s | llvm-dwarfdump -v -debug-info - | FileCheck %s
+; The use of llvm-dis here tests that round-tripping the IR works
+; correctly for the expression case.
+; RUN: llvm-as < %s | llvm-dis | llc -mtriple=x86_64 -O0 -filetype=obj -o - | llvm-dwarfdump -v -debug-info - | FileCheck %s
 
 ; A basic test of using a DIExpression for DW_AT_data_bit_offset and
 ; DW_AT_bit_size.



More information about the llvm-commits mailing list