[llvm] [DirectX][ObjectYAML] Add ILDB program part support (PR #189685)

Vladislav Dzhidzhoev via llvm-commits llvm-commits at lists.llvm.org
Wed May 13 06:13:40 PDT 2026


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

>From 783e7f8d5889ef01df7ee6281312bfcfc44031d5 Mon Sep 17 00:00:00 2001
From: Vladislav Dzhidzhoev <vdzhidzhoev at accesssoftek.com>
Date: Fri, 27 Mar 2026 00:05:58 +0100
Subject: [PATCH 1/5] [DirectX][ObjectYAML] Add ILDB program part support

Add support for DXContainer ILDB parts in the ObjectYAML pipeline
so they can be represented in structured YAML and round-tripped
through yaml2obj/obj2yaml.

ILDB payloads use the same layout as DXIL, but contain debug IR.
This change treats ILDB as a DXIL-shaped program part.

FileSize and DXIL ProgramHeader Size values in DXILPart.yaml were
modified to make output binary correct/parseable by dxa utility.
---
 llvm/include/llvm/BinaryFormat/DXContainer.h  |  4 ++
 .../BinaryFormat/DXContainerConstants.def     |  1 +
 llvm/include/llvm/Object/DXContainer.h        |  7 ++-
 llvm/lib/BinaryFormat/DXContainer.cpp         |  6 +++
 llvm/lib/Object/DXContainer.cpp               | 12 +++--
 llvm/lib/ObjectYAML/DXContainerEmitter.cpp    |  2 +
 .../tools/obj2yaml/DXContainer/DXILPart.yaml  | 32 +++++++++++--
 llvm/tools/obj2yaml/dxcontainer2yaml.cpp      | 13 +++--
 llvm/unittests/Object/DXContainerTest.cpp     | 48 ++++++++++++++++++-
 9 files changed, 109 insertions(+), 16 deletions(-)

diff --git a/llvm/include/llvm/BinaryFormat/DXContainer.h b/llvm/include/llvm/BinaryFormat/DXContainer.h
index 1756ab0b555ff..3da36f6da525d 100644
--- a/llvm/include/llvm/BinaryFormat/DXContainer.h
+++ b/llvm/include/llvm/BinaryFormat/DXContainer.h
@@ -258,6 +258,10 @@ LLVM_ABI ArrayRef<EnumEntry<StaticBorderColor>> getStaticBorderColors();
 
 LLVM_ABI PartType parsePartType(StringRef S);
 
+bool isDebugProgramPart(PartType PT);
+
+const char *getProgramPartName(bool IsDebug);
+
 struct VertexPSVInfo {
   uint8_t OutputPositionPresent;
   uint8_t Unused[3];
diff --git a/llvm/include/llvm/BinaryFormat/DXContainerConstants.def b/llvm/include/llvm/BinaryFormat/DXContainerConstants.def
index f576d958037cd..f9f4472b0ebce 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(ILDB)
 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..b70d6a960c130 100644
--- a/llvm/include/llvm/Object/DXContainer.h
+++ b/llvm/include/llvm/Object/DXContainer.h
@@ -468,6 +468,7 @@ class DXContainer {
   dxbc::Header Header;
   SmallVector<uint32_t, 4> PartOffsets;
   std::optional<DXILData> DXIL;
+  std::optional<DXILData> DebugDXIL;
   std::optional<uint64_t> ShaderFeatureFlags;
   std::optional<dxbc::ShaderHash> Hash;
   std::optional<DirectX::PSVRuntimeInfo> PSVInfo;
@@ -478,7 +479,7 @@ class DXContainer {
 
   Error parseHeader();
   Error parsePartOffsets();
-  Error parseDXILHeader(StringRef Part);
+  Error parseDXILHeader(dxbc::PartType PT, StringRef Part);
   Error parseShaderFeatureFlags(StringRef Part);
   Error parseHash(StringRef Part);
   Error parseRootSignature(StringRef Part);
@@ -561,7 +562,9 @@ class DXContainer {
 
   const dxbc::Header &getHeader() const { return Header; }
 
-  const std::optional<DXILData> &getDXIL() const { return DXIL; }
+  const std::optional<DXILData> &getDXIL(bool Debug) const {
+    return Debug ? DebugDXIL : DXIL;
+  }
 
   std::optional<uint64_t> getShaderFeatureFlags() const {
     return ShaderFeatureFlags;
diff --git a/llvm/lib/BinaryFormat/DXContainer.cpp b/llvm/lib/BinaryFormat/DXContainer.cpp
index 22f518067b318..384ef6811346c 100644
--- a/llvm/lib/BinaryFormat/DXContainer.cpp
+++ b/llvm/lib/BinaryFormat/DXContainer.cpp
@@ -110,6 +110,12 @@ dxbc::PartType dxbc::parsePartType(StringRef S) {
       .Default(dxbc::PartType::Unknown);
 }
 
+bool dxbc::isDebugProgramPart(PartType PT) { return PT == PartType::ILDB; }
+
+const char *dxbc::getProgramPartName(bool IsDebug) {
+  return IsDebug ? "ILDB" : "DXIL";
+}
+
 bool ShaderHash::isPopulated() {
   static uint8_t Zeros[16] = {0};
   return Flags > 0 || 0 != memcmp(&Digest, &Zeros, 16);
diff --git a/llvm/lib/Object/DXContainer.cpp b/llvm/lib/Object/DXContainer.cpp
index 7b7b8d88c63fc..bcc692f51405a 100644
--- a/llvm/lib/Object/DXContainer.cpp
+++ b/llvm/lib/Object/DXContainer.cpp
@@ -61,9 +61,13 @@ Error DXContainer::parseHeader() {
   return readStruct(Data.getBuffer(), Data.getBuffer().data(), Header);
 }
 
-Error DXContainer::parseDXILHeader(StringRef Part) {
+Error DXContainer::parseDXILHeader(dxbc::PartType PT, StringRef Part) {
+  bool IsDebug = dxbc::isDebugProgramPart(PT);
+  std::optional<DXILData> &DXIL = IsDebug ? this->DebugDXIL : this->DXIL;
+
   if (DXIL)
-    return parseFailed("More than one DXIL part is present in the file");
+    return parseFailed(formatv("More than one {0} part is present in the file",
+                               dxbc::getProgramPartName(IsDebug)));
   const char *Current = Part.begin();
   dxbc::ProgramHeader Header;
   if (Error Err = readStruct(Part, Current, Header))
@@ -173,8 +177,10 @@ Error DXContainer::parsePartOffsets() {
     StringRef PartData = Data.getBuffer().substr(PartDataStart, PartSize);
     LastOffset = PartOffset + PartSize;
     switch (PT) {
+    case dxbc::PartType::ILDB:
+      [[fallthrough]];
     case dxbc::PartType::DXIL:
-      if (Error Err = parseDXILHeader(PartData))
+      if (Error Err = parseDXILHeader(PT, PartData))
         return Err;
       break;
     case dxbc::PartType::SFI0:
diff --git a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
index b00e45d912be1..225ab0ef39bb4 100644
--- a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
@@ -128,6 +128,8 @@ Error DXContainerWriter::writeParts(raw_ostream &OS) {
 
     uint64_t DataStart = OS.tell();
     switch (PT) {
+    case dxbc::PartType::ILDB:
+      [[fallthrough]];
     case dxbc::PartType::DXIL: {
       if (!P.Program)
         continue;
diff --git a/llvm/test/tools/obj2yaml/DXContainer/DXILPart.yaml b/llvm/test/tools/obj2yaml/DXContainer/DXILPart.yaml
index 58508f2dcc1e4..1749c7bd44d48 100644
--- a/llvm/test/tools/obj2yaml/DXContainer/DXILPart.yaml
+++ b/llvm/test/tools/obj2yaml/DXContainer/DXILPart.yaml
@@ -11,9 +11,9 @@ Header:
   Version:
     Major:           1
     Minor:           0
-  FileSize:        3548
-  PartCount:       7
-  PartOffsets:     [ 60, 76, 92, 108, 236, 1932, 1960 ]
+  FileSize:        2040
+  PartCount:       8
+  PartOffsets:     [ 64, 80, 96, 112, 240, 1936, 1964, 2000 ]
 Parts:
   - Name:            FKE0
     Size:            8
@@ -33,11 +33,22 @@ Parts:
       MajorVersion:    6
       MinorVersion:    5
       ShaderKind:      5
-      Size:            8
+      Size:            7
       DXILMajorVersion: 1
       DXILMinorVersion: 5
       DXILSize:        4
       DXIL:            [ 0x42, 0x43, 0xC0, 0xDE, ]
+  - Name:            ILDB
+    Size:            32
+    Program:
+      MajorVersion:    6
+      MinorVersion:    5
+      ShaderKind:      5
+      Size:            8
+      DXILMajorVersion: 1
+      DXILMinorVersion: 5
+      DXILSize:        8
+      DXIL:            [ 0x42, 0x43, 0xC0, 0xDE, 0x21, 0x0C, 0x00, 0x00, ]
 ...
 
 
@@ -49,8 +60,19 @@ Parts:
 #CHECK-NEXT:       MajorVersion:    6
 #CHECK-NEXT:       MinorVersion:    5
 #CHECK-NEXT:       ShaderKind:      5
-#CHECK-NEXT:       Size:            8
+#CHECK-NEXT:       Size:            7
 #CHECK-NEXT:       DXILMajorVersion: 1
 #CHECK-NEXT:       DXILMinorVersion: 5
 #CHECK-NEXT:       DXILSize:        4
 #CHECK-NEXT:       DXIL:            [ 0x42, 0x43, 0xC0, 0xDE
+#CHECK:        - Name:            ILDB
+#CHECK-NEXT:     Size:            32
+#CHECK-NEXT:     Program:
+#CHECK-NEXT:       MajorVersion:    6
+#CHECK-NEXT:       MinorVersion:    5
+#CHECK-NEXT:       ShaderKind:      5
+#CHECK-NEXT:       Size:            8
+#CHECK-NEXT:       DXILMajorVersion: 1
+#CHECK-NEXT:       DXILMinorVersion: 5
+#CHECK-NEXT:       DXILSize:        8
+#CHECK-NEXT:       DXIL:            [ 0x42, 0x43, 0xC0, 0xDE, 0x21, 0xC, 0x0, 0x0
diff --git a/llvm/tools/obj2yaml/dxcontainer2yaml.cpp b/llvm/tools/obj2yaml/dxcontainer2yaml.cpp
index c727595406767..99a4fed92c139 100644
--- a/llvm/tools/obj2yaml/dxcontainer2yaml.cpp
+++ b/llvm/tools/obj2yaml/dxcontainer2yaml.cpp
@@ -53,9 +53,12 @@ dumpDXContainer(MemoryBufferRef Source) {
     DXContainerYAML::Part &NewPart = Obj->Parts.back();
     dxbc::PartType PT = dxbc::parsePartType(P.Part.getName());
     switch (PT) {
+    case dxbc::PartType::ILDB:
+      [[fallthrough]];
     case dxbc::PartType::DXIL: {
-      std::optional<DXContainer::DXILData> DXIL = Container.getDXIL();
-      assert(DXIL && "Since we are iterating and found a DXIL part, "
+      std::optional<DXContainer::DXILData> DXIL =
+          Container.getDXIL(dxbc::isDebugProgramPart(PT));
+      assert(DXIL && "Since we are iterating and found a DXIL/ILDB part, "
                      "this should never not have a value");
       NewPart.Program = DXContainerYAML::DXILProgram{
           DXIL->first.getMajorVersion(),
@@ -89,10 +92,10 @@ dumpDXContainer(MemoryBufferRef Source) {
         break;
       if (const auto *P =
               std::get_if<dxbc::PSV::v0::RuntimeInfo>(&PSVInfo->getInfo())) {
-        if (!Container.getDXIL())
+        if (!Container.getDXIL(false))
           break;
-        NewPart.Info =
-            DXContainerYAML::PSVInfo(P, Container.getDXIL()->first.ShaderKind);
+        NewPart.Info = DXContainerYAML::PSVInfo(
+            P, Container.getDXIL(false)->first.ShaderKind);
       } else if (const auto *P = std::get_if<dxbc::PSV::v1::RuntimeInfo>(
                      &PSVInfo->getInfo()))
         NewPart.Info = DXContainerYAML::PSVInfo(P);
diff --git a/llvm/unittests/Object/DXContainerTest.cpp b/llvm/unittests/Object/DXContainerTest.cpp
index d6f7b26b99cd7..309063631ec99 100644
--- a/llvm/unittests/Object/DXContainerTest.cpp
+++ b/llvm/unittests/Object/DXContainerTest.cpp
@@ -209,7 +209,7 @@ TEST(DXCFile, ParseDXILPart) {
   DXContainer C =
       llvm::cantFail(DXContainer::create(getMemoryBuffer<116>(Buffer)));
   EXPECT_EQ(C.getHeader().PartCount, 1u);
-  const std::optional<object::DXContainer::DXILData> &DXIL = C.getDXIL();
+  const std::optional<object::DXContainer::DXILData> &DXIL = C.getDXIL(false);
   EXPECT_TRUE(DXIL.has_value());
   dxbc::ProgramHeader Header = DXIL->first;
   EXPECT_EQ(Header.getMajorVersion(), 6u);
@@ -220,6 +220,52 @@ TEST(DXCFile, ParseDXILPart) {
   EXPECT_EQ(Header.Bitcode.MinorVersion, 5u);
 }
 
+// This test verifies that ILDB 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:            ILDB
+//     Size:            28
+//     Program:
+//       MajorVersion:    6
+//       MinorVersion:    5
+//       ShaderKind:      5
+//       Size:            8
+//       DXILMajorVersion: 1
+//       DXILMinorVersion: 5
+//       DXILSize:        4
+//       DXIL:            [ 0x42, 0x43, 0xC0, 0xDE, ]
+// ...
+TEST(DXCFile, ParseILDBPart) {
+  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, 0x42, 0x1c, 0x00, 0x00, 0x00, 0x65, 0x00, 0x05, 0x00,
+      0x08, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x05, 0x01, 0x00, 0x00,
+      0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde};
+  DXContainer C =
+      llvm::cantFail(DXContainer::create(getMemoryBuffer<116>(Buffer)));
+  EXPECT_EQ(C.getHeader().PartCount, 1u);
+  const std::optional<object::DXContainer::DXILData> &DXIL = C.getDXIL(true);
+  EXPECT_TRUE(DXIL.has_value());
+  dxbc::ProgramHeader Header = DXIL->first;
+  EXPECT_EQ(Header.getMajorVersion(), 6u);
+  EXPECT_EQ(Header.getMinorVersion(), 5u);
+  EXPECT_EQ(Header.ShaderKind, 5u);
+  EXPECT_EQ(Header.Size, 8u);
+  EXPECT_EQ(Header.Bitcode.MajorVersion, 1u);
+  EXPECT_EQ(Header.Bitcode.MinorVersion, 5u);
+  EXPECT_TRUE(memcmp(DXIL->second, "\x42\x43\xc0\xde", 4) == 0);
+}
+
 static Expected<DXContainer>
 generateDXContainer(StringRef Yaml, SmallVectorImpl<char> &BinaryData) {
   DXContainerYAML::Object Obj;

>From 5adb81da784b71bbc45911021ce0af641cd96c15 Mon Sep 17 00:00:00 2001
From: Vladislav Dzhidzhoev <vdzhidzhoev at accesssoftek.com>
Date: Wed, 29 Apr 2026 14:02:32 +0200
Subject: [PATCH 2/5] PSV YAML fix

---
 llvm/include/llvm/Object/DXContainer.h        |  7 +++
 llvm/lib/Object/DXContainer.cpp               | 12 +++-
 .../DXContainer/ILDB-ShaderKind-mismatch.yaml | 33 +++++++++++
 .../ObjectYAML/DXContainer/PSVv0-ILDB.yaml    | 57 +++++++++++++++++++
 llvm/tools/obj2yaml/dxcontainer2yaml.cpp      |  6 +-
 5 files changed, 109 insertions(+), 6 deletions(-)
 create mode 100644 llvm/test/ObjectYAML/DXContainer/ILDB-ShaderKind-mismatch.yaml
 create mode 100644 llvm/test/ObjectYAML/DXContainer/PSVv0-ILDB.yaml

diff --git a/llvm/include/llvm/Object/DXContainer.h b/llvm/include/llvm/Object/DXContainer.h
index b70d6a960c130..8d1b17844227e 100644
--- a/llvm/include/llvm/Object/DXContainer.h
+++ b/llvm/include/llvm/Object/DXContainer.h
@@ -566,6 +566,13 @@ class DXContainer {
     return Debug ? DebugDXIL : DXIL;
   }
 
+  std::optional<uint16_t> getShaderKind() const {
+    const auto &ProgramPart = DXIL ? DXIL : DebugDXIL;
+    if (!ProgramPart)
+      return std::nullopt;
+    return ProgramPart->first.ShaderKind;
+  }
+
   std::optional<uint64_t> getShaderFeatureFlags() const {
     return ShaderFeatureFlags;
   }
diff --git a/llvm/lib/Object/DXContainer.cpp b/llvm/lib/Object/DXContainer.cpp
index bcc692f51405a..0779c8079af9b 100644
--- a/llvm/lib/Object/DXContainer.cpp
+++ b/llvm/lib/Object/DXContainer.cpp
@@ -216,13 +216,19 @@ Error DXContainer::parsePartOffsets() {
     }
   }
 
+  if (DXIL && DebugDXIL &&
+      DXIL->first.ShaderKind != DebugDXIL->first.ShaderKind)
+    return parseFailed(
+        "ILDB part shader kind does not match DXIL part shader kind");
+
   // Fully parsing the PSVInfo requires knowing the shader kind which we read
   // out of the program header in the DXIL part.
   if (PSVInfo) {
-    if (!DXIL)
+    auto ShaderKind = getShaderKind();
+    if (!ShaderKind)
       return parseFailed("Cannot fully parse pipeline state validation "
-                         "information without DXIL part.");
-    if (Error Err = PSVInfo->parse(DXIL->first.ShaderKind))
+                         "information without DXIL or ILDB part");
+    if (Error Err = PSVInfo->parse(*ShaderKind))
       return Err;
   }
   return Error::success();
diff --git a/llvm/test/ObjectYAML/DXContainer/ILDB-ShaderKind-mismatch.yaml b/llvm/test/ObjectYAML/DXContainer/ILDB-ShaderKind-mismatch.yaml
new file mode 100644
index 0000000000000..e1462a27b4c7f
--- /dev/null
+++ b/llvm/test/ObjectYAML/DXContainer/ILDB-ShaderKind-mismatch.yaml
@@ -0,0 +1,33 @@
+# RUN: yaml2obj %s | obj2yaml
+# XFAIL: *
+
+--- !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:         2
+Parts:
+  - Name:            DXIL
+    Size:            24
+    Program:
+      MajorVersion:    6
+      MinorVersion:    0
+      ShaderKind:      4
+      Size:            6
+      DXILMajorVersion: 0
+      DXILMinorVersion: 1
+      DXILSize:        0
+  - Name:            ILDB
+    Size:            24
+    Program:
+      MajorVersion:    6
+      MinorVersion:    0
+      ShaderKind:      5
+      Size:            6
+      DXILMajorVersion: 0
+      DXILMinorVersion: 1
+      DXILSize:        0
+...
diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv0-ILDB.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv0-ILDB.yaml
new file mode 100644
index 0000000000000..13c47ae0ae250
--- /dev/null
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv0-ILDB.yaml
@@ -0,0 +1,57 @@
+# RUN: yaml2obj %s | obj2yaml | 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
+  PartCount:         2
+Parts:
+  - Name:            PSV0
+    Size:            144
+    PSVInfo:
+      Version:         0
+      ShaderStage:     5
+      MinimumWaveLaneCount: 0
+      MaximumWaveLaneCount: 4294967295
+      ResourceStride:       16
+      Resources:
+        - Type:            Sampler
+          Space:           2
+          LowerBound:      3
+          UpperBound:      4
+        - Type:            Invalid
+          Space:           32768
+          LowerBound:      8388608
+          UpperBound:      2147483648
+  - Name:            ILDB
+    Size:            24
+    Program:
+      MajorVersion:    6
+      MinorVersion:    0
+      ShaderKind:      5
+      Size:            6
+      DXILMajorVersion: 0
+      DXILMinorVersion: 1
+      DXILSize:        0
+...
+
+# CHECK: Name:            PSV0
+# CHECK: PSVInfo:
+# CHECK-NEXT: Version:         0
+# CHECK-NEXT: ShaderStage:     5
+# CHECK-NEXT: MinimumWaveLaneCount: 0
+# CHECK-NEXT: MaximumWaveLaneCount: 4294967295
+# CHECK-NEXT: ResourceStride: 16
+# CHECK-NEXT: Resources:
+# CHECK-NEXT: - Type:            Sampler
+# CHECK-NEXT: Space:           2
+# CHECK-NEXT: LowerBound:      3
+# CHECK-NEXT: UpperBound:      4
+# CHECK-NEXT: - Type:            Invalid
+# CHECK-NEXT: Space:           32768
+# CHECK-NEXT: LowerBound:      8388608
+# CHECK-NEXT: UpperBound:      2147483648
+# CHECK-NEXT: Name
diff --git a/llvm/tools/obj2yaml/dxcontainer2yaml.cpp b/llvm/tools/obj2yaml/dxcontainer2yaml.cpp
index 99a4fed92c139..05912ce31ab6d 100644
--- a/llvm/tools/obj2yaml/dxcontainer2yaml.cpp
+++ b/llvm/tools/obj2yaml/dxcontainer2yaml.cpp
@@ -92,10 +92,10 @@ dumpDXContainer(MemoryBufferRef Source) {
         break;
       if (const auto *P =
               std::get_if<dxbc::PSV::v0::RuntimeInfo>(&PSVInfo->getInfo())) {
-        if (!Container.getDXIL(false))
+        auto ShaderKind = Container.getShaderKind();
+        if (!ShaderKind)
           break;
-        NewPart.Info = DXContainerYAML::PSVInfo(
-            P, Container.getDXIL(false)->first.ShaderKind);
+        NewPart.Info = DXContainerYAML::PSVInfo(P, *ShaderKind);
       } else if (const auto *P = std::get_if<dxbc::PSV::v1::RuntimeInfo>(
                      &PSVInfo->getInfo()))
         NewPart.Info = DXContainerYAML::PSVInfo(P);

>From 0ce5c8d2ae8451a4d1bdf6ecda51d81c54785794 Mon Sep 17 00:00:00 2001
From: Vladislav Dzhidzhoev <vdzhidzhoev at accesssoftek.com>
Date: Wed, 6 May 2026 13:18:26 +0200
Subject: [PATCH 3/5] Address review comments.

---
 llvm/lib/Object/DXContainer.cpp               |  5 ++-
 llvm/lib/ObjectYAML/DXContainerEmitter.cpp    |  5 ++-
 .../DXContainer/ILDB-ShaderKind-mismatch.yaml |  3 ++
 .../ObjectYAML/DXContainer/PSVv0-ILDB.yaml    | 33 +++++++++----------
 llvm/tools/obj2yaml/dxcontainer2yaml.cpp      |  7 ++--
 5 files changed, 26 insertions(+), 27 deletions(-)

diff --git a/llvm/lib/Object/DXContainer.cpp b/llvm/lib/Object/DXContainer.cpp
index 0779c8079af9b..db2d4ad513abe 100644
--- a/llvm/lib/Object/DXContainer.cpp
+++ b/llvm/lib/Object/DXContainer.cpp
@@ -177,9 +177,8 @@ Error DXContainer::parsePartOffsets() {
     StringRef PartData = Data.getBuffer().substr(PartDataStart, PartSize);
     LastOffset = PartOffset + PartSize;
     switch (PT) {
-    case dxbc::PartType::ILDB:
-      [[fallthrough]];
     case dxbc::PartType::DXIL:
+    case dxbc::PartType::ILDB:
       if (Error Err = parseDXILHeader(PT, PartData))
         return Err;
       break;
@@ -224,7 +223,7 @@ Error DXContainer::parsePartOffsets() {
   // Fully parsing the PSVInfo requires knowing the shader kind which we read
   // out of the program header in the DXIL part.
   if (PSVInfo) {
-    auto ShaderKind = getShaderKind();
+    std::optional<uint16_t> ShaderKind = getShaderKind();
     if (!ShaderKind)
       return parseFailed("Cannot fully parse pipeline state validation "
                          "information without DXIL or ILDB part");
diff --git a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
index 225ab0ef39bb4..b8c7fe6a6cf8c 100644
--- a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
@@ -128,9 +128,8 @@ Error DXContainerWriter::writeParts(raw_ostream &OS) {
 
     uint64_t DataStart = OS.tell();
     switch (PT) {
-    case dxbc::PartType::ILDB:
-      [[fallthrough]];
-    case dxbc::PartType::DXIL: {
+    case dxbc::PartType::DXIL:
+    case dxbc::PartType::ILDB: {
       if (!P.Program)
         continue;
       dxbc::ProgramHeader Header;
diff --git a/llvm/test/ObjectYAML/DXContainer/ILDB-ShaderKind-mismatch.yaml b/llvm/test/ObjectYAML/DXContainer/ILDB-ShaderKind-mismatch.yaml
index e1462a27b4c7f..0ac5b48f2c29f 100644
--- a/llvm/test/ObjectYAML/DXContainer/ILDB-ShaderKind-mismatch.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/ILDB-ShaderKind-mismatch.yaml
@@ -1,3 +1,6 @@
+# Check that ObjectYAML throws an error if shader kind in DXIL ProgramHeader
+# differs from shader kind in ILDB ProgramHeader
+
 # RUN: yaml2obj %s | obj2yaml
 # XFAIL: *
 
diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv0-ILDB.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv0-ILDB.yaml
index 13c47ae0ae250..f378c7bf0ec60 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv0-ILDB.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv0-ILDB.yaml
@@ -38,20 +38,19 @@ Parts:
       DXILSize:        0
 ...
 
-# CHECK: Name:            PSV0
-# CHECK: PSVInfo:
-# CHECK-NEXT: Version:         0
-# CHECK-NEXT: ShaderStage:     5
-# CHECK-NEXT: MinimumWaveLaneCount: 0
-# CHECK-NEXT: MaximumWaveLaneCount: 4294967295
-# CHECK-NEXT: ResourceStride: 16
-# CHECK-NEXT: Resources:
-# CHECK-NEXT: - Type:            Sampler
-# CHECK-NEXT: Space:           2
-# CHECK-NEXT: LowerBound:      3
-# CHECK-NEXT: UpperBound:      4
-# CHECK-NEXT: - Type:            Invalid
-# CHECK-NEXT: Space:           32768
-# CHECK-NEXT: LowerBound:      8388608
-# CHECK-NEXT: UpperBound:      2147483648
-# CHECK-NEXT: Name
+# CHECK:       - Name:            PSV0
+# CHECK:         PSVInfo:
+# CHECK-NEXT:      Version:         0
+# CHECK-NEXT:      ShaderStage:     5
+# CHECK-NEXT:      MinimumWaveLaneCount: 0
+# CHECK-NEXT:      MaximumWaveLaneCount: 4294967295
+# CHECK-NEXT:      ResourceStride:       16
+# CHECK-NEXT:      Resources:
+# CHECK-NEXT:        - Type:            Sampler
+# CHECK-NEXT:          Space:           2
+# CHECK-NEXT:          LowerBound:      3
+# CHECK-NEXT:          UpperBound:      4
+# CHECK-NEXT:        - Type:            Invalid
+# CHECK-NEXT:          Space:           32768
+# CHECK-NEXT:          LowerBound:      8388608
+# CHECK-NEXT:          UpperBound:      2147483648
diff --git a/llvm/tools/obj2yaml/dxcontainer2yaml.cpp b/llvm/tools/obj2yaml/dxcontainer2yaml.cpp
index 05912ce31ab6d..d4a4223a5daac 100644
--- a/llvm/tools/obj2yaml/dxcontainer2yaml.cpp
+++ b/llvm/tools/obj2yaml/dxcontainer2yaml.cpp
@@ -53,9 +53,8 @@ dumpDXContainer(MemoryBufferRef Source) {
     DXContainerYAML::Part &NewPart = Obj->Parts.back();
     dxbc::PartType PT = dxbc::parsePartType(P.Part.getName());
     switch (PT) {
-    case dxbc::PartType::ILDB:
-      [[fallthrough]];
-    case dxbc::PartType::DXIL: {
+    case dxbc::PartType::DXIL:
+    case dxbc::PartType::ILDB: {
       std::optional<DXContainer::DXILData> DXIL =
           Container.getDXIL(dxbc::isDebugProgramPart(PT));
       assert(DXIL && "Since we are iterating and found a DXIL/ILDB part, "
@@ -92,7 +91,7 @@ dumpDXContainer(MemoryBufferRef Source) {
         break;
       if (const auto *P =
               std::get_if<dxbc::PSV::v0::RuntimeInfo>(&PSVInfo->getInfo())) {
-        auto ShaderKind = Container.getShaderKind();
+        std::optional<uint16_t> ShaderKind = Container.getShaderKind();
         if (!ShaderKind)
           break;
         NewPart.Info = DXContainerYAML::PSVInfo(P, *ShaderKind);

>From a6858e2f57834306ff7e131b121963aedc240cfe Mon Sep 17 00:00:00 2001
From: Vladislav Dzhidzhoev <vdzhidzhoev at accesssoftek.com>
Date: Wed, 6 May 2026 23:36:09 +0200
Subject: [PATCH 4/5] Fix error messages style

---
 llvm/lib/Object/DXContainer.cpp                            | 4 ++--
 llvm/test/tools/llvm-objcopy/DXContainer/reading-errs.yaml | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Object/DXContainer.cpp b/llvm/lib/Object/DXContainer.cpp
index db2d4ad513abe..3d72ba4ad5b96 100644
--- a/llvm/lib/Object/DXContainer.cpp
+++ b/llvm/lib/Object/DXContainer.cpp
@@ -66,7 +66,7 @@ Error DXContainer::parseDXILHeader(dxbc::PartType PT, StringRef Part) {
   std::optional<DXILData> &DXIL = IsDebug ? this->DebugDXIL : this->DXIL;
 
   if (DXIL)
-    return parseFailed(formatv("More than one {0} part is present in the file",
+    return parseFailed(formatv("more than one {0} part is present in the file",
                                dxbc::getProgramPartName(IsDebug)));
   const char *Current = Part.begin();
   dxbc::ProgramHeader Header;
@@ -225,7 +225,7 @@ Error DXContainer::parsePartOffsets() {
   if (PSVInfo) {
     std::optional<uint16_t> ShaderKind = getShaderKind();
     if (!ShaderKind)
-      return parseFailed("Cannot fully parse pipeline state validation "
+      return parseFailed("cannot fully parse pipeline state validation "
                          "information without DXIL or ILDB part");
     if (Error Err = PSVInfo->parse(*ShaderKind))
       return Err;
diff --git a/llvm/test/tools/llvm-objcopy/DXContainer/reading-errs.yaml b/llvm/test/tools/llvm-objcopy/DXContainer/reading-errs.yaml
index 32099552a4525..a049724b5a638 100644
--- a/llvm/test/tools/llvm-objcopy/DXContainer/reading-errs.yaml
+++ b/llvm/test/tools/llvm-objcopy/DXContainer/reading-errs.yaml
@@ -5,7 +5,7 @@
 # RUN: yaml2obj %s --docnum=1 -o %t1
 # RUN: not llvm-objcopy %t1 %t1.out 2>&1 | FileCheck %s -DFILE=%t1 --check-prefix=ERROR1
 
-# ERROR1: error: '[[FILE]]': More than one DXIL part is present in the file
+# ERROR1: error: '[[FILE]]': more than one DXIL part is present in the file
 
 --- !dxcontainer
 Header:

>From 431ad58582c6443bde77bb7c2d7a22cfe448e7bc Mon Sep 17 00:00:00 2001
From: Vladislav Dzhidzhoev <vdzhidzhoev at accesssoftek.com>
Date: Wed, 13 May 2026 15:13:22 +0200
Subject: [PATCH 5/5] Fix IDLB-ShaderKind-mismatch.yaml

---
 .../ObjectYAML/DXContainer/ILDB-ShaderKind-mismatch.yaml     | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/llvm/test/ObjectYAML/DXContainer/ILDB-ShaderKind-mismatch.yaml b/llvm/test/ObjectYAML/DXContainer/ILDB-ShaderKind-mismatch.yaml
index 0ac5b48f2c29f..8d5e985cde035 100644
--- a/llvm/test/ObjectYAML/DXContainer/ILDB-ShaderKind-mismatch.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/ILDB-ShaderKind-mismatch.yaml
@@ -1,8 +1,9 @@
 # Check that ObjectYAML throws an error if shader kind in DXIL ProgramHeader
 # differs from shader kind in ILDB ProgramHeader
 
-# RUN: yaml2obj %s | obj2yaml
-# XFAIL: *
+# RUN: yaml2obj %s | not obj2yaml -o /dev/null 2>&1 | FileCheck %s
+
+# CHECK: ILDB part shader kind does not match DXIL part shader kind
 
 --- !dxcontainer
 Header:



More information about the llvm-commits mailing list