[llvm] [DirectX][ObjectYAML] Add ILDN part support (PR #194508)

Vladislav Dzhidzhoev via llvm-commits llvm-commits at lists.llvm.org
Sun May 3 14:28:05 PDT 2026


https://github.com/dzhidzhoev updated https://github.com/llvm/llvm-project/pull/194508

>From 02e0e19542a1ffff2d0c5358ef18a540d3339a5d Mon Sep 17 00:00:00 2001
From: Vladislav Dzhidzhoev <vdzhidzhoev at accesssoftek.com>
Date: Wed, 1 Apr 2026 14:31:42 +0200
Subject: [PATCH 1/2] [DirectX][ObjectYAML] Add ILDN part support

Add support for DXContainer ILDN part in the ObjectYAML pipeline
so it can be represented in structured YAML and round-tripped
through yaml2obj/obj2yaml.

ILDN part is meant to store the name of PDB file that contains shader debug info.
---
 llvm/include/llvm/BinaryFormat/DXContainer.h  | 13 ++++
 .../BinaryFormat/DXContainerConstants.def     |  1 +
 llvm/include/llvm/Object/DXContainer.h        |  5 ++
 .../include/llvm/ObjectYAML/DXContainerYAML.h | 11 ++++
 llvm/lib/Object/DXContainer.cpp               | 48 +++++++++++++-
 llvm/lib/ObjectYAML/DXContainerEmitter.cpp    | 15 +++++
 llvm/lib/ObjectYAML/DXContainerYAML.cpp       |  8 +++
 .../tools/obj2yaml/DXContainer/ILDNPart.yaml  | 64 +++++++++++++++++++
 llvm/tools/obj2yaml/dxcontainer2yaml.cpp      | 10 +++
 llvm/unittests/Object/DXContainerTest.cpp     | 39 +++++++++++
 .../ObjectYAML/DXContainerYAMLTest.cpp        | 36 +++++++++++
 11 files changed, 248 insertions(+), 2 deletions(-)
 create mode 100644 llvm/test/tools/obj2yaml/DXContainer/ILDNPart.yaml

diff --git a/llvm/include/llvm/BinaryFormat/DXContainer.h b/llvm/include/llvm/BinaryFormat/DXContainer.h
index 1756ab0b555ff..edcaaaf630fdb 100644
--- a/llvm/include/llvm/BinaryFormat/DXContainer.h
+++ b/llvm/include/llvm/BinaryFormat/DXContainer.h
@@ -803,6 +803,19 @@ enum class RootSignatureVersion {
   V1_2 = 0x3,
 };
 
+struct DebugNameHeader {
+  uint16_t Flags;
+  /// Debug file name length, without null terminator.
+  uint16_t NameLength;
+
+  void swapBytes() {
+    sys::swapByteOrder(Flags);
+    sys::swapByteOrder(NameLength);
+  }
+};
+
+static_assert(sizeof(DebugNameHeader) == 4, "DebugNameHeader size incorrect.");
+
 } // namespace dxbc
 } // namespace llvm
 
diff --git a/llvm/include/llvm/BinaryFormat/DXContainerConstants.def b/llvm/include/llvm/BinaryFormat/DXContainerConstants.def
index f576d958037cd..4c5070d18578c 100644
--- a/llvm/include/llvm/BinaryFormat/DXContainerConstants.def
+++ b/llvm/include/llvm/BinaryFormat/DXContainerConstants.def
@@ -1,6 +1,7 @@
 
 #ifdef CONTAINER_PART
 CONTAINER_PART(DXIL)
+CONTAINER_PART(ILDN)
 CONTAINER_PART(SFI0)
 CONTAINER_PART(HASH)
 CONTAINER_PART(PSV0)
diff --git a/llvm/include/llvm/Object/DXContainer.h b/llvm/include/llvm/Object/DXContainer.h
index c5888b87d6ad7..f2ce39770b097 100644
--- a/llvm/include/llvm/Object/DXContainer.h
+++ b/llvm/include/llvm/Object/DXContainer.h
@@ -460,6 +460,7 @@ class Signature {
 class DXContainer {
 public:
   using DXILData = std::pair<dxbc::ProgramHeader, const char *>;
+  using ILDNData = std::pair<dxbc::DebugNameHeader, StringRef>;
 
 private:
   DXContainer(MemoryBufferRef O);
@@ -475,10 +476,12 @@ class DXContainer {
   DirectX::Signature InputSignature;
   DirectX::Signature OutputSignature;
   DirectX::Signature PatchConstantSignature;
+  std::optional<ILDNData> DebugName;
 
   Error parseHeader();
   Error parsePartOffsets();
   Error parseDXILHeader(StringRef Part);
+  Error parseDebugName(StringRef Part);
   Error parseShaderFeatureFlags(StringRef Part);
   Error parseHash(StringRef Part);
   Error parseRootSignature(StringRef Part);
@@ -563,6 +566,8 @@ class DXContainer {
 
   const std::optional<DXILData> &getDXIL() const { return DXIL; }
 
+  const std::optional<ILDNData> getDebugName() const { return DebugName; }
+
   std::optional<uint64_t> getShaderFeatureFlags() const {
     return ShaderFeatureFlags;
   }
diff --git a/llvm/include/llvm/ObjectYAML/DXContainerYAML.h b/llvm/include/llvm/ObjectYAML/DXContainerYAML.h
index fbfe3069566d3..bead4292b002f 100644
--- a/llvm/include/llvm/ObjectYAML/DXContainerYAML.h
+++ b/llvm/include/llvm/ObjectYAML/DXContainerYAML.h
@@ -287,6 +287,12 @@ struct Signature {
   llvm::SmallVector<SignatureParameter> Parameters;
 };
 
+struct DebugName {
+  uint16_t Flags;
+  uint16_t NameLength;
+  std::string DebugName;
+};
+
 struct Part {
   Part() = default;
   Part(std::string N, uint32_t S) : Name(N), Size(S) {}
@@ -298,6 +304,7 @@ struct Part {
   std::optional<PSVInfo> Info;
   std::optional<DXContainerYAML::Signature> Signature;
   std::optional<DXContainerYAML::RootSignatureYamlDesc> RootSignature;
+  std::optional<DXContainerYAML::DebugName> DebugName;
 };
 
 struct Object {
@@ -363,6 +370,10 @@ template <> struct MappingTraits<DXContainerYAML::PSVInfo> {
   LLVM_ABI static void mapping(IO &IO, DXContainerYAML::PSVInfo &PSV);
 };
 
+template <> struct MappingTraits<DXContainerYAML::DebugName> {
+  LLVM_ABI static void mapping(IO &IO, DXContainerYAML::DebugName &DebugName);
+};
+
 template <> struct MappingTraits<DXContainerYAML::Part> {
   LLVM_ABI static void mapping(IO &IO, DXContainerYAML::Part &Version);
 };
diff --git a/llvm/lib/Object/DXContainer.cpp b/llvm/lib/Object/DXContainer.cpp
index 7b7b8d88c63fc..bb06af6d7c9c3 100644
--- a/llvm/lib/Object/DXContainer.cpp
+++ b/llvm/lib/Object/DXContainer.cpp
@@ -20,10 +20,14 @@ static Error parseFailed(const Twine &Msg) {
   return make_error<GenericBinaryError>(Msg.str(), object_error::parse_failed);
 }
 
+static bool readOutOfBounds(StringRef Buffer, const char *Src, size_t Size) {
+  return Src < Buffer.begin() || Src + Size > Buffer.end();
+}
+
 template <typename T>
 static Error readStruct(StringRef Buffer, const char *Src, T &Struct) {
   // Don't read before the beginning or past the end of the file
-  if (Src < Buffer.begin() || Src + sizeof(T) > Buffer.end())
+  if (readOutOfBounds(Buffer, Src, sizeof(T)))
     return parseFailed("Reading structure out of file bounds");
 
   memcpy(&Struct, Src, sizeof(T));
@@ -39,7 +43,7 @@ static Error readInteger(StringRef Buffer, const char *Src, T &Val,
   static_assert(std::is_integral_v<T>,
                 "Cannot call readInteger on non-integral type.");
   // Don't read before the beginning or past the end of the file
-  if (Src < Buffer.begin() || Src + sizeof(T) > Buffer.end())
+  if (readOutOfBounds(Buffer, Src, sizeof(T)))
     return parseFailed(Twine("Reading ") + Str + " out of file bounds");
 
   // The DXContainer offset table is comprised of uint32_t values but not padded
@@ -55,6 +59,22 @@ static Error readInteger(StringRef Buffer, const char *Src, T &Val,
   return Error::success();
 }
 
+static Error readString(StringRef Buffer, const char *&Src, size_t MaxSize,
+                        StringRef &Val, Twine Desc) {
+  if (readOutOfBounds(Buffer, Src, MaxSize))
+    return parseFailed(Desc + " is out of file bounds");
+
+  // Ensure that the null-terminator is somewhere within MaxSize bytes.
+  Buffer = Buffer.substr(Src - Buffer.data(), MaxSize);
+  size_t Length = Buffer.find('\0');
+  if (Length == Buffer.npos)
+    return parseFailed(Desc + " does not end with null-terminator");
+
+  Val = StringRef(Buffer.data(), Length);
+  Src += Length + 1;
+  return Error::success();
+}
+
 DXContainer::DXContainer(MemoryBufferRef O) : Data(O) {}
 
 Error DXContainer::parseHeader() {
@@ -73,6 +93,26 @@ Error DXContainer::parseDXILHeader(StringRef Part) {
   return Error::success();
 }
 
+Error DXContainer::parseDebugName(StringRef Part) {
+  if (DebugName)
+    return parseFailed("More than one ILDN part is present in the file");
+  const char *Current = Part.begin();
+  dxbc::DebugNameHeader Header;
+  if (Error Err = readStruct(Part, Current, Header))
+    return Err;
+  Current += sizeof(Header);
+
+  StringRef Name;
+  if (Error Err = readString(Part, Current, Header.NameLength + 1, Name,
+                             "Debug file name"))
+    return Err;
+  if (Name.size() != Header.NameLength)
+    return parseFailed("Debug file name length mismatch");
+  DebugName.emplace(Header, Name.data());
+
+  return Error::success();
+}
+
 Error DXContainer::parseShaderFeatureFlags(StringRef Part) {
   if (ShaderFeatureFlags)
     return parseFailed("More than one SFI0 part is present in the file");
@@ -177,6 +217,10 @@ Error DXContainer::parsePartOffsets() {
       if (Error Err = parseDXILHeader(PartData))
         return Err;
       break;
+    case dxbc::PartType::ILDN:
+      if (Error Err = parseDebugName(PartData))
+        return Err;
+      break;
     case dxbc::PartType::SFI0:
       if (Error Err = parseShaderFeatureFlags(PartData))
         return Err;
diff --git a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
index b00e45d912be1..044ecacddde27 100644
--- a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
@@ -172,6 +172,21 @@ Error DXContainerWriter::writeParts(raw_ostream &OS) {
       }
       break;
     }
+    case dxbc::PartType::ILDN: {
+      if (!P.DebugName)
+        continue;
+
+      dxbc::DebugNameHeader Header;
+      Header.Flags = P.DebugName->Flags;
+      Header.NameLength = P.DebugName->NameLength;
+
+      if (sys::IsBigEndianHost)
+        Header.swapBytes();
+      OS.write(reinterpret_cast<const char *>(&Header),
+               sizeof(dxbc::DebugNameHeader));
+      OS.write(P.DebugName->DebugName.c_str(), P.DebugName->NameLength + 1);
+      break;
+    }
     case dxbc::PartType::SFI0: {
       // If we don't have any flags we can continue here and the data will be
       // zeroed out.
diff --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
index 15f614871f57e..d91d5a83e7b3e 100644
--- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
@@ -531,6 +531,13 @@ void MappingTraits<llvm::DXContainerYAML::StaticSamplerYamlDesc>::mapping(
 #include "llvm/BinaryFormat/DXContainerConstants.def"
 }
 
+void MappingTraits<DXContainerYAML::DebugName>::mapping(
+    IO &IO, DXContainerYAML::DebugName &DebugName) {
+  IO.mapRequired("Flags", DebugName.Flags);
+  IO.mapRequired("NameLength", DebugName.NameLength);
+  IO.mapRequired("DebugName", DebugName.DebugName);
+}
+
 void MappingTraits<DXContainerYAML::Part>::mapping(IO &IO,
                                                    DXContainerYAML::Part &P) {
   IO.mapRequired("Name", P.Name);
@@ -541,6 +548,7 @@ void MappingTraits<DXContainerYAML::Part>::mapping(IO &IO,
   IO.mapOptional("PSVInfo", P.Info);
   IO.mapOptional("Signature", P.Signature);
   IO.mapOptional("RootSignature", P.RootSignature);
+  IO.mapOptional("DebugName", P.DebugName);
 }
 
 void MappingTraits<DXContainerYAML::Object>::mapping(
diff --git a/llvm/test/tools/obj2yaml/DXContainer/ILDNPart.yaml b/llvm/test/tools/obj2yaml/DXContainer/ILDNPart.yaml
new file mode 100644
index 0000000000000..02e42417f39d8
--- /dev/null
+++ b/llvm/test/tools/obj2yaml/DXContainer/ILDNPart.yaml
@@ -0,0 +1,64 @@
+# RUN: yaml2obj %s 2>&1 | obj2yaml 2>&1 | FileCheck %s
+
+--- !dxcontainer
+Header:
+  Hash:            [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+                     0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]
+  Version:
+    Major:           1
+    Minor:           0
+  FileSize:        3600
+  PartCount:       8
+  PartOffsets:     [64, 80, 96, 112, 240, 1936, 1964, 2016]
+Parts:
+  - Name:            FKE0
+    Size:            8
+  - Name:            FKE1
+    Size:            8
+  - Name:            FKE2
+    Size:            8
+  - Name:            FKE3
+    Size:            120
+  - Name:            FKE4
+    Size:            1688
+  - Name:            FKE5
+    Size:            20
+  - Name:            ILDN
+    Size:            44
+    DebugName:
+      Flags:           0
+      NameLength:      36
+      DebugName:       0b40fc8650d90fa2e9fd5cadc8eaaace.pdb
+  - Name:            DXIL
+    Size:            28
+    Program:
+      MajorVersion:    6
+      MinorVersion:    5
+      ShaderKind:      5
+      Size:            7
+      DXILMajorVersion: 1
+      DXILMinorVersion: 5
+      DXILSize:        4
+      DXIL:            [ 0x42, 0x43, 0xC0, 0xDE, ]
+...
+
+
+
+
+#CHECK:        - Name:            ILDN
+#CHECK-NEXT:     Size:            44
+#CHECK-NEXT:     DebugName:
+#CHECK-NEXT:       Flags:           0
+#CHECK-NEXT:       NameLength:      36
+#CHECK-NEXT:       DebugName:       0b40fc8650d90fa2e9fd5cadc8eaaace.pdb
+#CHECK-NEXT:   - Name:            DXIL
+#CHECK-NEXT:     Size:            28
+#CHECK-NEXT:     Program:
+#CHECK-NEXT:       MajorVersion:    6
+#CHECK-NEXT:       MinorVersion:    5
+#CHECK-NEXT:       ShaderKind:      5
+#CHECK-NEXT:       Size:            7
+#CHECK-NEXT:       DXILMajorVersion: 1
+#CHECK-NEXT:       DXILMinorVersion: 5
+#CHECK-NEXT:       DXILSize:        4
+#CHECK-NEXT:       DXIL:            [ 0x42, 0x43, 0xC0, 0xDE
diff --git a/llvm/tools/obj2yaml/dxcontainer2yaml.cpp b/llvm/tools/obj2yaml/dxcontainer2yaml.cpp
index c727595406767..584c75b4478c4 100644
--- a/llvm/tools/obj2yaml/dxcontainer2yaml.cpp
+++ b/llvm/tools/obj2yaml/dxcontainer2yaml.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "obj2yaml.h"
+#include "llvm/BinaryFormat/DXContainer.h"
 #include "llvm/Object/DXContainer.h"
 #include "llvm/ObjectYAML/DXContainerYAML.h"
 #include "llvm/Support/Error.h"
@@ -70,6 +71,15 @@ dumpDXContainer(MemoryBufferRef Source) {
               DXIL->second, DXIL->second + DXIL->first.Bitcode.Size)};
       break;
     }
+    case dxbc::PartType::ILDN: {
+      std::optional<DXContainer::ILDNData> DebugName = Container.getDebugName();
+      assert(DebugName && "Since we are iterating and found a ILDN part, this "
+                          "should never not have a value");
+      NewPart.DebugName = DXContainerYAML::DebugName{
+          DebugName->first.Flags, DebugName->first.NameLength,
+          DebugName->second.str()};
+      break;
+    }
     case dxbc::PartType::SFI0: {
       std::optional<uint64_t> Flags = Container.getShaderFeatureFlags();
       // Omit the flags in the YAML if they are missing or zero.
diff --git a/llvm/unittests/Object/DXContainerTest.cpp b/llvm/unittests/Object/DXContainerTest.cpp
index d6f7b26b99cd7..72a995117fdc9 100644
--- a/llvm/unittests/Object/DXContainerTest.cpp
+++ b/llvm/unittests/Object/DXContainerTest.cpp
@@ -220,6 +220,45 @@ TEST(DXCFile, ParseDXILPart) {
   EXPECT_EQ(Header.Bitcode.MinorVersion, 5u);
 }
 
+// This test verifies that ILDN part is correctly parsed.
+// This test is based on the binary output constructed from this yaml.
+// --- !dxcontainer
+// Header:
+//   Hash:            [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+//                      0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]
+//   Version:
+//     Major:           1
+//     Minor:           0
+//   PartCount:       1
+// Parts:
+//   - Name:            ILDN
+//     Size:            44
+//     DebugName:
+//      Flags:           0
+//      NameLength:      36
+//      DebugName:       49405c8bb27f1f8733cbf9f29b1d100c.pdb
+// ...
+TEST(DXCFile, ParseILDNPart) {
+  uint8_t Buffer[] = {
+      0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+      0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24,
+      0x00, 0x00, 0x00, 0x49, 0x4c, 0x44, 0x4e, 0x2c, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x24, 0x00, 0x34, 0x39, 0x34, 0x30, 0x35, 0x63, 0x38,
+      0x62, 0x62, 0x32, 0x37, 0x66, 0x31, 0x66, 0x38, 0x37, 0x33, 0x33,
+      0x63, 0x62, 0x66, 0x39, 0x66, 0x32, 0x39, 0x62, 0x31, 0x64, 0x31,
+      0x30, 0x30, 0x63, 0x2E, 0x70, 0x64, 0x62, 0x00, 0x00, 0x00, 0x00};
+  DXContainer C =
+      llvm::cantFail(DXContainer::create(getMemoryBuffer<116>(Buffer)));
+  EXPECT_EQ(C.getHeader().PartCount, 1u);
+  const std::optional<object::DXContainer::ILDNData> &ILDN = C.getDebugName();
+  EXPECT_TRUE(ILDN.has_value());
+  dxbc::DebugNameHeader Header = ILDN->first;
+  EXPECT_EQ(Header.Flags, 0u);
+  EXPECT_EQ(Header.NameLength, 36u);
+  EXPECT_EQ(ILDN->second, "49405c8bb27f1f8733cbf9f29b1d100c.pdb");
+}
+
 static Expected<DXContainer>
 generateDXContainer(StringRef Yaml, SmallVectorImpl<char> &BinaryData) {
   DXContainerYAML::Object Obj;
diff --git a/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp b/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp
index 1b21fe01dfca9..a690992ab49ca 100644
--- a/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp
+++ b/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp
@@ -577,3 +577,39 @@ TEST(RootSignature, ParseStaticSamplersV13) {
   EXPECT_EQ(Storage.size(), 148U);
   EXPECT_TRUE(memcmp(Buffer, Storage.data(), 148U) == 0);
 }
+
+TEST(DXCFile, ParseILDNPart) {
+  SmallString<128> Storage;
+
+  // First read a fully explicit yaml with all sizes and offsets provided
+  ASSERT_TRUE(convert(Storage, R"(--- !dxcontainer
+  Header:
+      Hash:            [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+                         0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]
+      Version:
+        Major:           1
+        Minor:           0
+      PartCount:       1
+      PartOffsets:     [ 36 ]
+  Parts:
+  - Name:            ILDN
+    Size:            44
+    DebugName:
+     Flags:           0
+     NameLength:      36
+     DebugName:       49405c8bb27f1f8733cbf9f29b1d100c.pdb
+    )"));
+
+  uint8_t Buffer[] = {
+      0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+      0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24,
+      0x00, 0x00, 0x00, 0x49, 0x4c, 0x44, 0x4e, 0x2c, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x24, 0x00, 0x34, 0x39, 0x34, 0x30, 0x35, 0x63, 0x38,
+      0x62, 0x62, 0x32, 0x37, 0x66, 0x31, 0x66, 0x38, 0x37, 0x33, 0x33,
+      0x63, 0x62, 0x66, 0x39, 0x66, 0x32, 0x39, 0x62, 0x31, 0x64, 0x31,
+      0x30, 0x30, 0x63, 0x2E, 0x70, 0x64, 0x62, 0x00, 0x00, 0x00, 0x00};
+
+  EXPECT_EQ(Storage.size(), 88u);
+  EXPECT_TRUE(memcmp(Buffer, Storage.data(), 88u) == 0);
+}

>From 14d66ef4df006fc672ee76e3a76d6a26ceebbb52 Mon Sep 17 00:00:00 2001
From: Vladislav Dzhidzhoev <vdzhidzhoev at accesssoftek.com>
Date: Sun, 3 May 2026 01:00:41 +0200
Subject: [PATCH 2/2] Make ILDN fields optional, move ILDN writer to MC

---
 llvm/include/llvm/MC/DXContainerInfo.h        | 32 +++++++++++++++
 .../include/llvm/ObjectYAML/DXContainerYAML.h |  4 +-
 llvm/lib/MC/CMakeLists.txt                    |  1 +
 llvm/lib/MC/DXContainerInfo.cpp               | 41 +++++++++++++++++++
 llvm/lib/ObjectYAML/DXContainerEmitter.cpp    | 19 +++++----
 llvm/lib/ObjectYAML/DXContainerYAML.cpp       |  4 +-
 .../DXContainer/ILDNPart-compute-flags.yaml   | 26 ++++++++++++
 .../DXContainer/ILDNPart-compute-length.yaml  | 26 ++++++++++++
 .../DXContainer/ILDNPart-compute.yaml         | 25 +++++++++++
 9 files changed, 165 insertions(+), 13 deletions(-)
 create mode 100644 llvm/include/llvm/MC/DXContainerInfo.h
 create mode 100644 llvm/lib/MC/DXContainerInfo.cpp
 create mode 100644 llvm/test/tools/obj2yaml/DXContainer/ILDNPart-compute-flags.yaml
 create mode 100644 llvm/test/tools/obj2yaml/DXContainer/ILDNPart-compute-length.yaml
 create mode 100644 llvm/test/tools/obj2yaml/DXContainer/ILDNPart-compute.yaml

diff --git a/llvm/include/llvm/MC/DXContainerInfo.h b/llvm/include/llvm/MC/DXContainerInfo.h
new file mode 100644
index 0000000000000..78d4b4da45558
--- /dev/null
+++ b/llvm/include/llvm/MC/DXContainerInfo.h
@@ -0,0 +1,32 @@
+//===----- llvm/MC/DXContainerInfo.h - DXContainer Info ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_MC_DXCONTAINERINFO_H
+#define LLVM_MC_DXCONTAINERINFO_H
+
+#include "llvm/Object/DXContainer.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+namespace mcdxbc {
+
+struct DebugName {
+  object::DXContainer::ILDNData BaseData;
+
+  DebugName() { BaseData.first.Flags = 0; }
+
+  void setFileName(StringRef FileName);
+  void write(raw_ostream &OS) const;
+};
+
+} // namespace mcdxbc
+} // namespace llvm
+
+#endif // LLVM_MC_DXCONTAINERINFO_H
diff --git a/llvm/include/llvm/ObjectYAML/DXContainerYAML.h b/llvm/include/llvm/ObjectYAML/DXContainerYAML.h
index bead4292b002f..036890248a989 100644
--- a/llvm/include/llvm/ObjectYAML/DXContainerYAML.h
+++ b/llvm/include/llvm/ObjectYAML/DXContainerYAML.h
@@ -288,8 +288,8 @@ struct Signature {
 };
 
 struct DebugName {
-  uint16_t Flags;
-  uint16_t NameLength;
+  std::optional<uint16_t> Flags;
+  std::optional<uint16_t> NameLength;
   std::string DebugName;
 };
 
diff --git a/llvm/lib/MC/CMakeLists.txt b/llvm/lib/MC/CMakeLists.txt
index 7a9e26af415c6..b85cbaa08a653 100644
--- a/llvm/lib/MC/CMakeLists.txt
+++ b/llvm/lib/MC/CMakeLists.txt
@@ -1,5 +1,6 @@
 add_llvm_component_library(LLVMMC
   ConstantPools.cpp
+  DXContainerInfo.cpp
   DXContainerPSVInfo.cpp
   DXContainerRootSignature.cpp
   ELFObjectWriter.cpp
diff --git a/llvm/lib/MC/DXContainerInfo.cpp b/llvm/lib/MC/DXContainerInfo.cpp
new file mode 100644
index 0000000000000..d96dfd65cbd15
--- /dev/null
+++ b/llvm/lib/MC/DXContainerInfo.cpp
@@ -0,0 +1,41 @@
+//===- llvm/MC/DXContainerInfo.cpp - DXContainer Info -----*- C++ -------*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/DXContainerInfo.h"
+#include "llvm/BinaryFormat/DXContainer.h"
+#include "llvm/Object/DXContainer.h"
+#include "llvm/Support/SwapByteOrder.h"
+#include <type_traits>
+
+using namespace llvm;
+using namespace llvm::mcdxbc;
+
+template <typename StructT>
+static void writeStruct(raw_ostream &OS, StructT S) {
+  static_assert(std::is_class<StructT>() &&
+                "This method must be used for writing structure types.");
+  if (sys::IsBigEndianHost)
+    S.swapBytes();
+  OS.write(reinterpret_cast<const char *>(&S), sizeof(StructT));
+}
+
+static void writeString(raw_ostream &OS, StringRef S) {
+  OS.write(S.data(), S.size());
+  // Write null terminator.
+  OS.write_zeros(1);
+}
+
+void DebugName::setFileName(StringRef DebugFileName) {
+  BaseData.first.NameLength = DebugFileName.size();
+  BaseData.second = DebugFileName;
+}
+
+void DebugName::write(raw_ostream &OS) const {
+  writeStruct(OS, BaseData.first);
+  writeString(OS, BaseData.second.substr(0, BaseData.first.NameLength));
+}
diff --git a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
index 044ecacddde27..e141c1db521e3 100644
--- a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/BinaryFormat/DXContainer.h"
+#include "llvm/MC/DXContainerInfo.h"
 #include "llvm/MC/DXContainerPSVInfo.h"
 #include "llvm/MC/DXContainerRootSignature.h"
 #include "llvm/ObjectYAML/ObjectYAML.h"
@@ -176,15 +177,15 @@ Error DXContainerWriter::writeParts(raw_ostream &OS) {
       if (!P.DebugName)
         continue;
 
-      dxbc::DebugNameHeader Header;
-      Header.Flags = P.DebugName->Flags;
-      Header.NameLength = P.DebugName->NameLength;
-
-      if (sys::IsBigEndianHost)
-        Header.swapBytes();
-      OS.write(reinterpret_cast<const char *>(&Header),
-               sizeof(dxbc::DebugNameHeader));
-      OS.write(P.DebugName->DebugName.c_str(), P.DebugName->NameLength + 1);
+      mcdxbc::DebugName DebugName;
+      DebugName.setFileName(P.DebugName->DebugName);
+      // Override default flags with value from YAML.
+      if (P.DebugName->Flags)
+        DebugName.BaseData.first.Flags = *P.DebugName->Flags;
+      // Override computed filename length with value from YAML.
+      if (P.DebugName->NameLength)
+        DebugName.BaseData.first.NameLength = *P.DebugName->NameLength;
+      DebugName.write(OS);
       break;
     }
     case dxbc::PartType::SFI0: {
diff --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
index d91d5a83e7b3e..497ae6b152dd9 100644
--- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
@@ -533,8 +533,8 @@ void MappingTraits<llvm::DXContainerYAML::StaticSamplerYamlDesc>::mapping(
 
 void MappingTraits<DXContainerYAML::DebugName>::mapping(
     IO &IO, DXContainerYAML::DebugName &DebugName) {
-  IO.mapRequired("Flags", DebugName.Flags);
-  IO.mapRequired("NameLength", DebugName.NameLength);
+  IO.mapOptional("Flags", DebugName.Flags);
+  IO.mapOptional("NameLength", DebugName.NameLength);
   IO.mapRequired("DebugName", DebugName.DebugName);
 }
 
diff --git a/llvm/test/tools/obj2yaml/DXContainer/ILDNPart-compute-flags.yaml b/llvm/test/tools/obj2yaml/DXContainer/ILDNPart-compute-flags.yaml
new file mode 100644
index 0000000000000..ea92645b28436
--- /dev/null
+++ b/llvm/test/tools/obj2yaml/DXContainer/ILDNPart-compute-flags.yaml
@@ -0,0 +1,26 @@
+# RUN: yaml2obj %s 2>&1 | obj2yaml 2>&1 | FileCheck %s
+
+--- !dxcontainer
+Header:
+  Hash:            [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+                     0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]
+  Version:
+    Major:           1
+    Minor:           0
+  FileSize:        88
+  PartCount:       1
+  PartOffsets:     [36]
+Parts:
+  - Name:            ILDN
+    Size:            44
+    DebugName:
+      NameLength:      36
+      DebugName:       0b40fc8650d90fa2e9fd5cadc8eaaace.pdb
+...
+
+#CHECK:       - Name:            ILDN
+#CHECK-NEXT:    Size:            44
+#CHECK-NEXT:    DebugName:
+#CHECK-NEXT:      Flags:           0
+#CHECK-NEXT:      NameLength:      36
+#CHECK-NEXT:      DebugName:       0b40fc8650d90fa2e9fd5cadc8eaaace.pdb
diff --git a/llvm/test/tools/obj2yaml/DXContainer/ILDNPart-compute-length.yaml b/llvm/test/tools/obj2yaml/DXContainer/ILDNPart-compute-length.yaml
new file mode 100644
index 0000000000000..128135ed91188
--- /dev/null
+++ b/llvm/test/tools/obj2yaml/DXContainer/ILDNPart-compute-length.yaml
@@ -0,0 +1,26 @@
+# RUN: yaml2obj %s 2>&1 | obj2yaml 2>&1 | FileCheck %s
+
+--- !dxcontainer
+Header:
+  Hash:            [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+                     0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]
+  Version:
+    Major:           1
+    Minor:           0
+  FileSize:        88
+  PartCount:       1
+  PartOffsets:     [36]
+Parts:
+  - Name:            ILDN
+    Size:            44
+    DebugName:
+      Flags:           0
+      DebugName:       0b40fc8650d90fa2e9fd5cadc8eaaace.pdb
+...
+
+#CHECK:       - Name:            ILDN
+#CHECK-NEXT:    Size:            44
+#CHECK-NEXT:    DebugName:
+#CHECK-NEXT:      Flags:           0
+#CHECK-NEXT:      NameLength:      36
+#CHECK-NEXT:      DebugName:       0b40fc8650d90fa2e9fd5cadc8eaaace.pdb
diff --git a/llvm/test/tools/obj2yaml/DXContainer/ILDNPart-compute.yaml b/llvm/test/tools/obj2yaml/DXContainer/ILDNPart-compute.yaml
new file mode 100644
index 0000000000000..f6f47f1809c97
--- /dev/null
+++ b/llvm/test/tools/obj2yaml/DXContainer/ILDNPart-compute.yaml
@@ -0,0 +1,25 @@
+# RUN: yaml2obj %s 2>&1 | obj2yaml 2>&1 | FileCheck %s
+
+--- !dxcontainer
+Header:
+  Hash:            [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+                     0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]
+  Version:
+    Major:           1
+    Minor:           0
+  FileSize:        88
+  PartCount:       1
+  PartOffsets:     [36]
+Parts:
+  - Name:            ILDN
+    Size:            44
+    DebugName:
+      DebugName:       0b40fc8650d90fa2e9fd5cadc8eaaace.pdb
+...
+
+#CHECK:       - Name:            ILDN
+#CHECK-NEXT:    Size:            44
+#CHECK-NEXT:    DebugName:
+#CHECK-NEXT:      Flags:           0
+#CHECK-NEXT:      NameLength:      36
+#CHECK-NEXT:      DebugName:       0b40fc8650d90fa2e9fd5cadc8eaaace.pdb



More information about the llvm-commits mailing list