[llvm] [DirectX] Generate PDB file with debug info (PR #202762)

Ilia Kuklin via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 11 10:49:41 PDT 2026


https://github.com/kuilpd updated https://github.com/llvm/llvm-project/pull/202762

>From ddf1900fd9fe3824f5c1ca5f9b7b35ced3190fdd Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Tue, 9 Jun 2026 23:37:50 +0500
Subject: [PATCH 1/6] [DirectX] Generate PDB file with debug info

---
 llvm/include/llvm/MC/MCDXContainerWriter.h    |  40 +++-
 llvm/lib/MC/MCDXContainerWriter.cpp           |  62 ++++--
 llvm/lib/Target/DirectX/CMakeLists.txt        |   3 +
 .../lib/Target/DirectX/DXContainerGlobals.cpp |  36 ++++
 llvm/lib/Target/DirectX/DXContainerPDB.cpp    | 181 ++++++++++++++++++
 llvm/lib/Target/DirectX/DirectX.h             |   6 +
 .../Target/DirectX/DirectXTargetMachine.cpp   |   2 +
 .../DebugName-default-output.test             |  17 ++
 .../DebugName-user-directory.test             |  16 ++
 .../ContainerData/Inputs/check_pdb_exists.py  |  25 +++
 .../DirectX/ContainerData/PDBParts-dxil.ll    |  16 ++
 .../CodeGen/DirectX/ContainerData/PDBParts.ll |  26 +++
 .../DirectX/ContainerData/PDBParts.test       |  12 ++
 llvm/test/CodeGen/DirectX/embed-ildb.ll       |  14 +-
 llvm/test/CodeGen/DirectX/llc-pipeline.ll     |   1 +
 15 files changed, 435 insertions(+), 22 deletions(-)
 create mode 100644 llvm/lib/Target/DirectX/DXContainerPDB.cpp
 create mode 100644 llvm/test/CodeGen/DirectX/ContainerData/DebugName-default-output.test
 create mode 100644 llvm/test/CodeGen/DirectX/ContainerData/DebugName-user-directory.test
 create mode 100644 llvm/test/CodeGen/DirectX/ContainerData/Inputs/check_pdb_exists.py
 create mode 100644 llvm/test/CodeGen/DirectX/ContainerData/PDBParts-dxil.ll
 create mode 100644 llvm/test/CodeGen/DirectX/ContainerData/PDBParts.ll
 create mode 100644 llvm/test/CodeGen/DirectX/ContainerData/PDBParts.test

diff --git a/llvm/include/llvm/MC/MCDXContainerWriter.h b/llvm/include/llvm/MC/MCDXContainerWriter.h
index a734d01392011..5692a64792bb9 100644
--- a/llvm/include/llvm/MC/MCDXContainerWriter.h
+++ b/llvm/include/llvm/MC/MCDXContainerWriter.h
@@ -33,9 +33,46 @@ class LLVM_ABI MCDXContainerTargetWriter : public MCObjectTargetWriter {
   }
 };
 
-class LLVM_ABI DXContainerObjectWriter final : public MCObjectWriter {
+/// Contains PDB output file name.
+static constexpr StringLiteral PdbFileNameSectionName = "PDBNAME";
+/// Contains module hash.
+static constexpr StringLiteral ModuleHashSectionName = "PDBHASH";
+
+struct MCDXContainerPart {
+  StringRef Name;
+  StringRef Data;
+};
+
+class MCDXContainerBaseWriter {
+protected:
+  virtual ArrayRef<MCDXContainerPart> getParts() {
+    llvm_unreachable("Unimplemented");
+  }
+
+  virtual bool shouldSkipSection(StringRef SectionName, size_t SectionSize) {
+    // Skip empty and auxiliary sections.
+    return SectionSize == 0 || SectionName == PdbFileNameSectionName ||
+           SectionName == ModuleHashSectionName;
+  }
+
+public:
+  MCDXContainerBaseWriter() {}
+  virtual ~MCDXContainerBaseWriter();
+
+  void write(raw_ostream &OS, const Triple &TT);
+};
+
+class LLVM_ABI DXContainerObjectWriter final : public MCDXContainerBaseWriter,
+                                               public MCObjectWriter {
   support::endian::Writer W;
   std::unique_ptr<MCDXContainerTargetWriter> TargetObjectWriter;
+  SmallVector<MCDXContainerPart> Parts;
+  SmallVector<SmallString<0>> SectionBuffers;
+
+  void clearParts();
+
+protected:
+  ArrayRef<MCDXContainerPart> getParts() override;
 
 public:
   DXContainerObjectWriter(std::unique_ptr<MCDXContainerTargetWriter> MOTW,
@@ -44,6 +81,7 @@ class LLVM_ABI DXContainerObjectWriter final : public MCObjectWriter {
 
   uint64_t writeObject() override;
 };
+
 } // end namespace llvm
 
 #endif // LLVM_MC_MCDXCONTAINERWRITER_H
diff --git a/llvm/lib/MC/MCDXContainerWriter.cpp b/llvm/lib/MC/MCDXContainerWriter.cpp
index e027d543ce5d8..5c3ade7281d1d 100644
--- a/llvm/lib/MC/MCDXContainerWriter.cpp
+++ b/llvm/lib/MC/MCDXContainerWriter.cpp
@@ -18,19 +18,20 @@ using namespace llvm;
 
 MCDXContainerTargetWriter::~MCDXContainerTargetWriter() = default;
 
-uint64_t DXContainerObjectWriter::writeObject() {
-  auto &Asm = *this->Asm;
+MCDXContainerBaseWriter::~MCDXContainerBaseWriter() = default;
+
+void MCDXContainerBaseWriter::write(raw_ostream &OS, const Triple &TT) {
+  ArrayRef<MCDXContainerPart> Parts = getParts();
+
+  support::endian::Writer W(OS, llvm::endianness::little);
+
   // Start the file size as the header plus the size of the part offsets.
   // Presently DXContainer files usually contain 7-10 parts. Reserving space for
   // 16 part offsets gives us a little room for growth.
   llvm::SmallVector<uint64_t, 16> PartOffsets;
   uint64_t PartOffset = 0;
-  for (const MCSection &Sec : Asm) {
-    uint64_t SectionSize = Asm.getSectionAddressSize(Sec);
-    // Skip empty sections.
-    if (SectionSize == 0)
-      continue;
-
+  for (const MCDXContainerPart &Part : Parts) {
+    uint64_t SectionSize = Part.Data.size();
     assert(SectionSize < std::numeric_limits<uint32_t>::max() &&
            "Section size too large for DXContainer");
 
@@ -39,7 +40,7 @@ uint64_t DXContainerObjectWriter::writeObject() {
     PartOffset = alignTo(PartOffset, Align(4ul));
     // The DXIL part also writes a program header, so we need to include its
     // size when computing the offset for a part after the DXIL part.
-    if (dxbc::isProgramPart(Sec.getName()))
+    if (dxbc::isProgramPart(Part.Name))
       PartOffset += sizeof(dxbc::ProgramHeader);
   }
   assert(PartOffset < std::numeric_limits<uint32_t>::max() &&
@@ -66,28 +67,23 @@ uint64_t DXContainerObjectWriter::writeObject() {
   for (uint64_t Offset : PartOffsets)
     W.write<uint32_t>(static_cast<uint32_t>(PartStart + Offset));
 
-  for (const MCSection &Sec : Asm) {
-    uint64_t SectionSize = Asm.getSectionAddressSize(Sec);
-    // Skip empty sections.
-    if (SectionSize == 0)
-      continue;
-
+  for (const MCDXContainerPart &Part : Parts) {
+    uint64_t SectionSize = Part.Data.size();
     unsigned Start = W.OS.tell();
     // Write section header.
-    W.write<char>(ArrayRef<char>(Sec.getName().data(), 4));
+    W.write<char>(ArrayRef<char>(Part.Name.data(), 4));
 
     uint64_t PartSize = SectionSize;
 
-    if (dxbc::isProgramPart(Sec.getName()))
+    if (dxbc::isProgramPart(Part.Name))
       PartSize += sizeof(dxbc::ProgramHeader);
     // DXContainer parts should be 4-byte aligned.
     PartSize = alignTo(PartSize, Align(4));
     W.write<uint32_t>(static_cast<uint32_t>(PartSize));
-    if (dxbc::isProgramPart(Sec.getName())) {
+    if (dxbc::isProgramPart(Part.Name)) {
       dxbc::ProgramHeader Header;
       memset(reinterpret_cast<void *>(&Header), 0, sizeof(dxbc::ProgramHeader));
 
-      const Triple &TT = getContext().getTargetTriple();
       VersionTuple Version = TT.getOSVersion();
       uint8_t MajorVersion = static_cast<uint8_t>(Version.getMajor());
       uint8_t MinorVersion =
@@ -111,9 +107,35 @@ uint64_t DXContainerObjectWriter::writeObject() {
       W.write<char>(ArrayRef<char>(reinterpret_cast<char *>(&Header),
                                    sizeof(dxbc::ProgramHeader)));
     }
-    Asm.writeSectionData(W.OS, &Sec);
+    W.write<char>(Part.Data);
     unsigned Size = W.OS.tell() - Start;
     W.OS.write_zeros(offsetToAlignment(Size, Align(4)));
   }
+}
+
+void DXContainerObjectWriter::clearParts() {
+  Parts.clear();
+  SectionBuffers.clear();
+}
+
+ArrayRef<MCDXContainerPart> DXContainerObjectWriter::getParts() {
+  clearParts();
+  for (const MCSection &Sec : *Asm) {
+    if (shouldSkipSection(Sec.getName(), Asm->getSectionAddressSize(Sec)))
+      continue;
+
+    SectionBuffers.emplace_back();
+    raw_svector_ostream OS(SectionBuffers.back());
+    Asm->writeSectionData(OS, &Sec);
+    Parts.push_back({Sec.getName(), StringRef(SectionBuffers.back())});
+  }
+  return Parts;
+}
+
+uint64_t DXContainerObjectWriter::writeObject() {
+  // TODO write only necessary sections.
+  write(W.OS, getContext().getTargetTriple());
+  clearParts();
+
   return 0;
 }
diff --git a/llvm/lib/Target/DirectX/CMakeLists.txt b/llvm/lib/Target/DirectX/CMakeLists.txt
index 436b7499f8dca..df90c36a2bdaa 100644
--- a/llvm/lib/Target/DirectX/CMakeLists.txt
+++ b/llvm/lib/Target/DirectX/CMakeLists.txt
@@ -20,6 +20,7 @@ add_llvm_target(DirectXCodeGen
   DirectXTargetMachine.cpp
   DirectXTargetTransformInfo.cpp
   DXContainerGlobals.cpp
+  DXContainerPDB.cpp
   DXILCBufferAccess.cpp
   DXILDataScalarization.cpp
   DXILFinalizeLinkage.cpp
@@ -46,6 +47,8 @@ add_llvm_target(DirectXCodeGen
   CodeGen
   CodeGenTypes
   Core
+  DebugInfoMSF
+  DebugInfoPDB
   DXILBitWriter
   DirectXDesc
   DirectXInfo
diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
index 9404ed963f2f1..bae8ce17e0696 100644
--- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
+++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
@@ -25,9 +25,11 @@
 #include "llvm/InitializePasses.h"
 #include "llvm/MC/DXContainerInfo.h"
 #include "llvm/MC/DXContainerPSVInfo.h"
+#include "llvm/MC/MCDXContainerWriter.h"
 #include "llvm/Pass.h"
 #include "llvm/Support/Compression.h"
 #include "llvm/Support/MD5.h"
+#include "llvm/Support/Path.h"
 #include "llvm/TargetParser/Triple.h"
 #include "llvm/Transforms/Utils/ModuleUtils.h"
 #include <cstdint>
@@ -36,6 +38,16 @@ using namespace llvm;
 using namespace llvm::dxil;
 using namespace llvm::mcdxbc;
 
+static cl::opt<std::string>
+    PdbFileName("dx-pdb-file",
+                cl::desc("Specify the PDB output file path for DirectX target"),
+                cl::value_desc("filename"));
+static cl::opt<std::string> PdbOutputDir(
+    "dx-pdb-dir",
+    cl::desc("Specify the PDB output directory for DirectX target. The file "
+             "name is derived from the shader hash"),
+    cl::value_desc("directory"));
+
 namespace {
 class DXContainerGlobals : public llvm::ModulePass {
 
@@ -140,17 +152,41 @@ void DXContainerGlobals::computeShaderHashAndDebugName(
   if (M.debug_compile_units().empty())
     return;
 
+  if (!PdbFileName.empty() && !PdbOutputDir.empty())
+    report_fatal_error(
+        "--dx-pdb-file and --dx-pdb-dir are mutually exclusive options");
+
   SmallString<40> DebugNameStr;
   Digest.stringifyResult(Result, DebugNameStr);
   DebugNameStr += ".pdb";
 
   mcdxbc::DebugName DebugName;
+  if (PdbFileName.empty()) {
+    // TODO Add an option to compute hash based on ILDB.
+    Digest.stringifyResult(Result, DebugNameStr);
+    DebugNameStr += ".pdb";
+  } else {
+    // Use user-provided PDB file name.
+    DebugNameStr = PdbFileName;
+  }
   DebugName.setFilename(DebugNameStr);
 
+  SmallString<256> AbsoluteDebugName(PdbOutputDir);
+  sys::path::append(AbsoluteDebugName, DebugNameStr);
+
   SmallString<64> ILDNData;
   raw_svector_ostream OS(ILDNData);
   DebugName.write(OS);
   addSection(M, Globals, ILDNData, "dx.ildn", "ILDN");
+
+  // TODO Do not create PDB in embedded mode.
+  // Pass PDB name to DXContainerPDBPass via PDBNAME section.
+  addSection(M, Globals, AbsoluteDebugName, "dx.pdb.name",
+             PdbFileNameSectionName);
+  // Pass module hash to DXContainerPDBPass.
+  Globals.emplace_back(buildContainerGlobal(
+      M, ConstantDataArray::get(M.getContext(), ArrayRef(HashData.Digest)),
+      "dx.pdb.hash", ModuleHashSectionName));
 }
 
 GlobalVariable *DXContainerGlobals::buildContainerGlobal(
diff --git a/llvm/lib/Target/DirectX/DXContainerPDB.cpp b/llvm/lib/Target/DirectX/DXContainerPDB.cpp
new file mode 100644
index 0000000000000..99187300504fb
--- /dev/null
+++ b/llvm/lib/Target/DirectX/DXContainerPDB.cpp
@@ -0,0 +1,181 @@
+//===- DXContainerPDB.cpp - DirectX PDB writer pass -----------------------===//
+//
+// 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 "DirectX.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/BinaryFormat/DXContainer.h"
+#include "llvm/DebugInfo/CodeView/GUID.h"
+#include "llvm/DebugInfo/MSF/MSFBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/Module.h"
+#include "llvm/MC/MCDXContainerWriter.h"
+#include "llvm/Pass.h"
+
+using namespace llvm;
+
+namespace {
+
+class DXContainerPDB : public ModulePass, MCDXContainerBaseWriter {
+  StringRef BitcodeSectionForPDB;
+  Module *M = nullptr;
+  SmallVector<MCDXContainerPart> Parts;
+
+  void reset() {
+    BitcodeSectionForPDB = "";
+    M = nullptr;
+    Parts.clear();
+  }
+
+public:
+  static char ID;
+  DXContainerPDB() : ModulePass(ID) {}
+
+  StringRef getPassName() const override { return "DirectX PDB Emitter"; }
+
+  bool runOnModule(Module &M) override;
+
+  void getAnalysisUsage(AnalysisUsage &AU) const override {
+    AU.setPreservesAll();
+  }
+
+  bool shouldSkipSection(StringRef SectionName, size_t SectionSize) override;
+  ArrayRef<MCDXContainerPart> getParts() override;
+};
+
+} // namespace
+
+bool DXContainerPDB::shouldSkipSection(StringRef SectionName,
+                                       size_t SectionSize) {
+  if (MCDXContainerBaseWriter::shouldSkipSection(SectionName, SectionSize))
+    return true;
+
+  // Skip sections that are irrelevant for debug info.
+  static const StringSet<> DebugSections{"DXIL", "ILDB", "ILDN", "HASH", "PDBI",
+                                         "SRCI", "STAT", "RDAT", "VERS"};
+  if (!DebugSections.contains(SectionName))
+    return true;
+
+  // Emit either DXIL or ILDB, but not both of them.
+  return dxbc::isProgramPart(SectionName) &&
+         SectionName != BitcodeSectionForPDB;
+}
+
+static StringRef getGlobalData(const GlobalVariable &GV) {
+  if (GV.hasInitializer())
+    if (const auto *Data =
+            dyn_cast<ConstantDataSequential>(GV.getInitializer()))
+      return Data->getRawDataValues();
+  return {};
+}
+
+ArrayRef<MCDXContainerPart> DXContainerPDB::getParts() {
+  Parts.clear();
+  for (const GlobalVariable &GV : M->globals()) {
+    StringRef Name = GV.getSection();
+    StringRef Data = getGlobalData(GV);
+
+    if (Data.empty())
+      continue;
+    if (shouldSkipSection(Name, Data.size()))
+      continue;
+
+    Parts.push_back({Name, Data});
+  }
+  return Parts;
+}
+
+bool DXContainerPDB::runOnModule(Module &M) {
+  this->M = &M;
+
+  StringRef DebugFileName;
+  ArrayRef<char> ModuleHash;
+  const GlobalVariable *DXIL = nullptr;
+  const GlobalVariable *ILDB = nullptr;
+  for (const GlobalVariable &GV : M.globals()) {
+    if (GV.getSection() == PdbFileNameSectionName) {
+      assert(DebugFileName.empty() && "Duplicate PDBNAME section");
+      DebugFileName = getGlobalData(GV);
+    } else if (GV.getSection() == ModuleHashSectionName) {
+      assert(ModuleHash.empty() && "Duplicate PBDHASH section");
+      StringRef Data = getGlobalData(GV);
+      ModuleHash = ArrayRef(Data.data(), Data.size());
+    } else if (GV.getSection() == "ILDB") {
+      assert(!ILDB && "Duplicate ILDB section");
+      ILDB = &GV;
+    } else if (GV.getSection() == "DXIL") {
+      assert(!DXIL && "Duplicate DXIL section");
+      DXIL = &GV;
+    }
+  }
+
+  // PDB emission was not requested.
+  if (DebugFileName.empty())
+    return false;
+  if (!DXIL && !ILDB)
+    report_fatal_error(
+        "Neither DXIL nor ILDB part was found for emitting PDB file");
+  if (ModuleHash.empty())
+    report_fatal_error("Module hash for PDB not found");
+
+  BitcodeSectionForPDB = DXIL ? DXIL->getSection() : "";
+  // Prioritize ILDB part over DXIL part.
+  if (ILDB)
+    BitcodeSectionForPDB = ILDB->getSection();
+
+  BumpPtrAllocator Allocator;
+  pdb::PDBFileBuilder Builder(Allocator);
+
+  // DirectXShaderCompiler uses block size 512.
+  if (Error Err = Builder.initialize(512))
+    reportFatalInternalError(std::move(Err));
+
+  // Reserved streams that should be empty.
+  static_assert(pdb::kSpecialStreamCount == 5 &&
+                "First 5 streams should be empty in DirectX PDB file");
+  for (uint32_t I = 0; I < pdb::kSpecialStreamCount; ++I) {
+    if (auto Err = Builder.getMsfBuilder().addStream(0).takeError())
+      reportFatalInternalError(std::move(Err));
+  }
+
+  // Add DXContainer stream.
+  if (auto Err = Builder.getMsfBuilder().addStream(0).takeError())
+    reportFatalInternalError(std::move(Err));
+
+  // InfoStream must be filled. Bitcode hash from HASH part is used for PDB
+  // GUID.
+  codeview::GUID PdbGuid;
+  assert(ModuleHash.size() == std::size(PdbGuid.Guid) &&
+         "Module hash length must be match GUID length");
+  std::copy_n(ModuleHash.begin(), std::size(PdbGuid.Guid), PdbGuid.Guid);
+
+  auto &InfoBuilder = Builder.getInfoBuilder();
+  InfoBuilder.setAge(1);
+  InfoBuilder.setGuid(PdbGuid);
+  InfoBuilder.setSignature(0);
+  InfoBuilder.setVersion(pdb::PdbRaw_ImplVer::PdbImplVC70);
+
+  // Write DXContainer.
+  raw_svector_ostream OS(*Builder.getDXContainerData());
+  write(OS, M.getTargetTriple());
+
+  // Write PDB file.
+  codeview::GUID IgnoredOutGuid;
+  if (Error Err = Builder.commit(DebugFileName, &IgnoredOutGuid))
+    reportFatalUsageError(std::move(Err));
+
+  reset();
+
+  return false;
+}
+
+char DXContainerPDB::ID = 0;
+INITIALIZE_PASS(DXContainerPDB, "dxil-pdb", "DirectX PDB Emitter", false, true)
+
+ModulePass *llvm::createDXContainerPDBPass() { return new DXContainerPDB(); }
diff --git a/llvm/lib/Target/DirectX/DirectX.h b/llvm/lib/Target/DirectX/DirectX.h
index 55a12e9f458b6..0dc4ee24525b8 100644
--- a/llvm/lib/Target/DirectX/DirectX.h
+++ b/llvm/lib/Target/DirectX/DirectX.h
@@ -121,6 +121,12 @@ void initializeDXContainerGlobalsPass(PassRegistry &);
 /// Pass for generating DXContainer part globals.
 ModulePass *createDXContainerGlobalsPass();
 
+/// Initializer for DXContainerPDB pass.
+void initializeDXContainerPDBPass(PassRegistry &);
+
+/// Pass for emitting DirectX PDB files.
+ModulePass *createDXContainerPDBPass();
+
 /// Initializer for DXILFinalizeLinkage pass.
 void initializeDXILFinalizeLinkageLegacyPass(PassRegistry &);
 
diff --git a/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp b/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp
index ab264d82e0c80..11e7f2062bdad 100644
--- a/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp
+++ b/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp
@@ -69,6 +69,7 @@ LLVMInitializeDirectXTarget() {
   initializeEmbedDXILPassPass(*PR);
   initializeWriteDXILPassPass(*PR);
   initializeDXContainerGlobalsPass(*PR);
+  initializeDXContainerPDBPass(*PR);
   initializeGlobalDCELegacyPassPass(*PR);
   initializeDXILOpLoweringLegacyPass(*PR);
   initializeDXILResourceAccessLegacyPass(*PR);
@@ -178,6 +179,7 @@ bool DirectXTargetMachine::addPassesToEmitFile(
       // We embed the other DXContainer globals after embedding DXIL so that the
       // globals don't pollute the DXIL.
       PM.add(createDXContainerGlobalsPass());
+      PM.add(createDXContainerPDBPass());
 
       if (!MMIWP)
         MMIWP = new MachineModuleInfoWrapperPass(this);
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/DebugName-default-output.test b/llvm/test/CodeGen/DirectX/ContainerData/DebugName-default-output.test
new file mode 100644
index 0000000000000..bb96005ed0947
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ContainerData/DebugName-default-output.test
@@ -0,0 +1,17 @@
+RUN: llc %S/Inputs/SourceInfo.ll --filetype=obj -o %t.dxbc
+RUN: llvm-objcopy --dump-section=ILDB=%t0.bc %t.dxbc
+RUN: %md5sum %t0.bc >%t0.bc.md5
+RUN: obj2yaml %t.dxbc >%t.yaml
+RUN: cat %t.yaml %t0.bc.md5 | FileCheck %s
+RUN: %python %S/Inputs/check_pdb_exists.py "" "%t0.bc.md5"
+
+CHECK-NOT:   - Name:            PDBN
+CHECK-NOT:   - Name:            PDBH
+CHECK:       - Name:            ILDN
+CHECK-NEXT:    Size:            44
+CHECK-NEXT:    DebugName:
+CHECK-NEXT:      Flags:           0
+CHECK-NEXT:      NameLength:      36
+CHECK-NEXT:      DebugName:       [[MD5:[0-9a-f]+]].pdb
+CHECK:       ...
+CHECK-NEXT:  [[MD5]]
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/DebugName-user-directory.test b/llvm/test/CodeGen/DirectX/ContainerData/DebugName-user-directory.test
new file mode 100644
index 0000000000000..002a94bcd5801
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ContainerData/DebugName-user-directory.test
@@ -0,0 +1,16 @@
+RUN: rm -rf %t && mkdir %t
+RUN: llc %S/Inputs/SourceInfo.ll --filetype=obj -o %t.dxbc --dx-pdb-dir=%t
+RUN: llvm-objcopy --dump-section=ILDB=%t0.bc %t.dxbc
+RUN: %md5sum %t0.bc >%t0.bc.md5
+RUN: obj2yaml %t.dxbc >%t.yaml
+RUN: cat %t.yaml %t0.bc.md5 | FileCheck %s --implicit-check-not PDBN --implicit-check-not PDBH
+RUN: %python %S/Inputs/check_pdb_exists.py "%t" "%t0.bc.md5"
+
+CHECK:       - Name:            ILDN
+CHECK-NEXT:    Size:            {{.*}}
+CHECK-NEXT:    DebugName:
+CHECK-NEXT:      Flags:           0
+CHECK-NEXT:      NameLength:      {{.*}}
+CHECK-NEXT:      DebugName:       [[MD5:[0-9a-f]+]].pdb
+CHECK:       ...
+CHECK-NEXT:  [[MD5]]
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/Inputs/check_pdb_exists.py b/llvm/test/CodeGen/DirectX/ContainerData/Inputs/check_pdb_exists.py
new file mode 100644
index 0000000000000..9c66e179cc6f0
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ContainerData/Inputs/check_pdb_exists.py
@@ -0,0 +1,25 @@
+#!/usr/bin/env python3
+
+import pathlib
+import sys
+
+
+def main() -> int:
+    if len(sys.argv) != 3:
+        print(
+            "usage: check_pdb_exists.py <directory> <name-file>",
+            file=sys.stderr,
+        )
+        return 2
+
+    directory = pathlib.Path(sys.argv[1])
+    name_file = pathlib.Path(sys.argv[2])
+
+    name = name_file.read_text().strip()
+    path = directory / (name + ".pdb")
+    assert path.is_file(), f"missing file: {path}"
+    return 0
+
+
+if __name__ == "__main__":
+    raise SystemExit(main())
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/PDBParts-dxil.ll b/llvm/test/CodeGen/DirectX/ContainerData/PDBParts-dxil.ll
new file mode 100644
index 0000000000000..f67b8fe732de4
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ContainerData/PDBParts-dxil.ll
@@ -0,0 +1,16 @@
+; RUN: opt %s -dxil-pdb -o /dev/null
+; RUN: llvm-pdbutil dump --streams --dxcontainer PDBPartsTest-dxil.pdb | FileCheck %s
+
+; Check that PDB file contains only debug-info relevant parts.
+; CHECK:              PartCount: 2
+; CHECK-NEXT:         Parts:
+; CHECK-NEXT:           DXIL |
+; CHECK-NEXT:           ILDN |
+
+target triple = "dxilv1.3-pc-shadermodel6.3-library"
+
+ at dx.dxil = private constant [4 x i8] c"BC\C0\DE", section "DXIL", align 4
+ at dx.ildn = private constant [26 x i8] c"\00\00\15\00PDBPartsTest-dxil.pdb\00", section "ILDN", align 4
+ at dx.pdb.name = private constant [21 x i8] c"PDBPartsTest-dxil.pdb", section "PDBNAME", align 4
+ at dx.pdb.hash = private constant [16 x i8] c"?\B9Z\96(\94D*{\AA&\A0P\B3\C9\D7", section "PDBHASH", align 4
+ at llvm.compiler.used = appending global [4 x ptr] [ptr @dx.dxil, ptr @dx.ildn, ptr @dx.pdb.name, ptr @dx.pdb.hash], section "llvm.metadata"
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/PDBParts.ll b/llvm/test/CodeGen/DirectX/ContainerData/PDBParts.ll
new file mode 100644
index 0000000000000..467954d2cea56
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ContainerData/PDBParts.ll
@@ -0,0 +1,26 @@
+; RUN: opt %s -dxil-pdb -o /dev/null
+; RUN: llvm-pdbutil dump --streams --dxcontainer PDBPartsTest.pdb | FileCheck %s
+
+; Check that PDB file contains only debug-info relevant parts.
+; CHECK:              PartCount: 5
+; CHECK-NEXT:         Parts:
+; CHECK-NEXT:           ILDB |
+; CHECK-NEXT:           ILDN |
+; CHECK-NEXT:           HASH |
+; CHECK-NEXT:           SRCI |
+; CHECK-NEXT:           VERS |
+
+target triple = "dxilv1.3-pc-shadermodel6.3-library"
+
+ at dx.dxil = private constant [4 x i8] c"BC\C0\DE", section "DXIL", align 4
+ at dx.ildb = private constant [4 x i8] c"BC\C0\DE", section "ILDB", align 4
+ at dx.ildn = private constant [21 x i8] c"\00\00\10\00PDBPartsTest.pdb\00", section "ILDN", align 4
+ at dx.hash = private constant [20 x i8] c"\01\00\00\00?\B9Z\96(\94D*{\AA&\A0P\B3\C9\D7", section "HASH", align 4
+ at dx.srci = private constant [76 x i8] c"\4C\00\00\00\00\00\03\00\14\00\00\00\00\00\01\00\00\00\00\00\00\00\00\00\00\00\00\00\1C\00\00\00\00\00\00\00\1C\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\14\00\00\00\00\00\02\00\00\00\00\00\00\00\00\00\00\00\00\00", section "SRCI", align 4
+ at dx.vers = private constant [64 x i8] c"\16\00\01\00\01\00\00\00\EE\A0\08\000\00\00\0026814cdaaa210c3e8aeea9112be2768964e6bdec\0022.1.1\00", section "VERS", align 4
+ at dx.pdb.name = private constant [16 x i8] c"PDBPartsTest.pdb", section "PDBNAME", align 4
+ at dx.pdb.hash = private constant [16 x i8] c"?\B9Z\96(\94D*{\AA&\A0P\B3\C9\D7", section "PDBHASH", align 4
+ at dx.sfi0 = private constant i64 0, section "SFI0", align 4
+ at dx.isg1 = private constant [8 x i8] c"\00\00\00\00\08\00\00\00", section "ISG1", align 4
+ at dx.osg1 = private constant [8 x i8] c"\00\00\00\00\08\00\00\00", section "OSG1", align 4
+ at llvm.compiler.used = appending global [11 x ptr] [ptr @dx.dxil, ptr @dx.ildb, ptr @dx.ildn, ptr @dx.hash, ptr @dx.srci, ptr @dx.vers, ptr @dx.pdb.name, ptr @dx.pdb.hash, ptr @dx.sfi0, ptr @dx.isg1, ptr @dx.osg1], section "llvm.metadata"
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/PDBParts.test b/llvm/test/CodeGen/DirectX/ContainerData/PDBParts.test
new file mode 100644
index 0000000000000..c4128a8b20ba5
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ContainerData/PDBParts.test
@@ -0,0 +1,12 @@
+RUN: rm -rf %t && mkdir %t
+RUN: llc %S/Inputs/SourceInfo.ll --filetype=obj -o %t.dxbc --dx-pdb-file=%t/parts.pdb
+RUN: llvm-pdbutil dump --streams --dxcontainer %t/parts.pdb | FileCheck %s --check-prefix=PDB
+
+# Check that debug-related container parts are emitted into companion PDB file.
+PDB:              PartCount: 5
+PDB-NEXT:         Parts:
+PDB-NEXT:           ILDB |
+PDB-NEXT:           HASH |
+PDB-NEXT:           ILDN |
+PDB-NEXT:           SRCI |
+PDB-NEXT:           VERS |
diff --git a/llvm/test/CodeGen/DirectX/embed-ildb.ll b/llvm/test/CodeGen/DirectX/embed-ildb.ll
index ee9700df40c2c..634bd3dc43946 100644
--- a/llvm/test/CodeGen/DirectX/embed-ildb.ll
+++ b/llvm/test/CodeGen/DirectX/embed-ildb.ll
@@ -1,10 +1,16 @@
+; RUN: rm -f %t.pdb
 ; RUN: opt %s -dxil-embed -dxil-globals -S -o - | FileCheck %s
-; RUN: llc %s --filetype=obj -o %t.bc
+; RUN: llc %s --filetype=obj -o %t.bc --dx-pdb-file=%t.pdb
 ; RUN: obj2yaml %t.bc | FileCheck %s --check-prefix=YAML
 ; RUN: llvm-objcopy --dump-section=ILDB=%t.ildb %t.bc
 ; RUN: llvm-objcopy --dump-section=DXIL=%t.dxil %t.bc
 ; RUN: llvm-dis %t.ildb -o - | FileCheck %s --check-prefix=ILDB-DIS
 ; RUN: llvm-dis %t.dxil -o - | FileCheck %s --check-prefix=DXIL-DIS
+; RUN: llvm-pdbutil dump --streams --dxcontainer %t.pdb | FileCheck %s --check-prefix=PDB
+; Check that ILDB is written to PDB.
+; RUN: llvm-pdbutil export --dxcontainer --out=%t.pdb.dxbc %t.pdb
+; RUN: llvm-objcopy --dump-section=ILDB=%t.pdb.ildb %t.pdb.dxbc
+; RUN: diff %t.ildb %t.pdb.ildb
 
 target triple = "dxil-unknown-shadermodel6.5-library"
 ; CHECK: target triple = "dxil-unknown-shadermodel6.5-library"
@@ -100,3 +106,9 @@ define i32 @add(i32 %a, i32 %b) {
 ; DXIL-DIS-NOT: !"Dwarf Version"
 ; DXIL-DIS-NOT: !"Debug Info Version"
 ; DXIL-DIS-NOT: "hlsl.hlsl"
+
+; Check that a companion PDB file is emitted and that it keeps ILDB but not DXIL.
+; PDB:            Stream 5 {{.*}} [DXContainer Stream]
+; PDB:            Parts:
+; PDB:            ILDB |
+; PDB-NOT:        DXIL |
diff --git a/llvm/test/CodeGen/DirectX/llc-pipeline.ll b/llvm/test/CodeGen/DirectX/llc-pipeline.ll
index 8419548bda78e..ab461848d705e 100644
--- a/llvm/test/CodeGen/DirectX/llc-pipeline.ll
+++ b/llvm/test/CodeGen/DirectX/llc-pipeline.ll
@@ -56,6 +56,7 @@
 
 ; CHECK-OBJ-NEXT: DXIL Embedder
 ; CHECK-OBJ-NEXT: DXContainer Global Emitter
+; CHECK-OBJ-NEXT: DirectX PDB Emitter
 ; CHECK-OBJ-NEXT: FunctionPass Manager
 ; CHECK-OBJ-NEXT:   Lazy Machine Block Frequency Analysis
 ; CHECK-OBJ-NEXT:   Machine Optimization Remark Emitter

>From 0bd172e27644db238042e7cef2607bec92680405 Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Tue, 9 Jun 2026 23:39:38 +0500
Subject: [PATCH 2/6] Rewrite tests using only pdb2yaml

---
 .../DirectX/ContainerData/PDBParts-dxil.ll       | 10 +++++-----
 .../CodeGen/DirectX/ContainerData/PDBParts.ll    | 16 ++++++++--------
 .../CodeGen/DirectX/ContainerData/PDBParts.test  | 16 ++++++++--------
 llvm/test/CodeGen/DirectX/embed-ildb.ll          | 15 ++++++++-------
 4 files changed, 29 insertions(+), 28 deletions(-)

diff --git a/llvm/test/CodeGen/DirectX/ContainerData/PDBParts-dxil.ll b/llvm/test/CodeGen/DirectX/ContainerData/PDBParts-dxil.ll
index f67b8fe732de4..db824985ea6d7 100644
--- a/llvm/test/CodeGen/DirectX/ContainerData/PDBParts-dxil.ll
+++ b/llvm/test/CodeGen/DirectX/ContainerData/PDBParts-dxil.ll
@@ -1,11 +1,11 @@
 ; RUN: opt %s -dxil-pdb -o /dev/null
-; RUN: llvm-pdbutil dump --streams --dxcontainer PDBPartsTest-dxil.pdb | FileCheck %s
+; RUN: llvm-pdbutil pdb2yaml --dxcontainer PDBPartsTest-dxil.pdb | FileCheck %s
 
 ; Check that PDB file contains only debug-info relevant parts.
-; CHECK:              PartCount: 2
-; CHECK-NEXT:         Parts:
-; CHECK-NEXT:           DXIL |
-; CHECK-NEXT:           ILDN |
+; CHECK:       PartCount:       2
+; CHECK:     Parts:
+; CHECK:       - Name:            DXIL
+; CHECK:       - Name:            ILDN
 
 target triple = "dxilv1.3-pc-shadermodel6.3-library"
 
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/PDBParts.ll b/llvm/test/CodeGen/DirectX/ContainerData/PDBParts.ll
index 467954d2cea56..e7480d8f33f5b 100644
--- a/llvm/test/CodeGen/DirectX/ContainerData/PDBParts.ll
+++ b/llvm/test/CodeGen/DirectX/ContainerData/PDBParts.ll
@@ -1,14 +1,14 @@
 ; RUN: opt %s -dxil-pdb -o /dev/null
-; RUN: llvm-pdbutil dump --streams --dxcontainer PDBPartsTest.pdb | FileCheck %s
+; RUN: llvm-pdbutil pdb2yaml --dxcontainer PDBPartsTest.pdb | FileCheck %s
 
 ; Check that PDB file contains only debug-info relevant parts.
-; CHECK:              PartCount: 5
-; CHECK-NEXT:         Parts:
-; CHECK-NEXT:           ILDB |
-; CHECK-NEXT:           ILDN |
-; CHECK-NEXT:           HASH |
-; CHECK-NEXT:           SRCI |
-; CHECK-NEXT:           VERS |
+; CHECK:       PartCount:       5
+; CHECK:     Parts:
+; CHECK-DAG:       - Name:            ILDB
+; CHECK-DAG:       - Name:            ILDN
+; CHECK-DAG:       - Name:            HASH
+; CHECK-DAG:       - Name:            SRCI
+; CHECK-DAG:       - Name:            VERS
 
 target triple = "dxilv1.3-pc-shadermodel6.3-library"
 
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/PDBParts.test b/llvm/test/CodeGen/DirectX/ContainerData/PDBParts.test
index c4128a8b20ba5..8fc7f5adb4e9c 100644
--- a/llvm/test/CodeGen/DirectX/ContainerData/PDBParts.test
+++ b/llvm/test/CodeGen/DirectX/ContainerData/PDBParts.test
@@ -1,12 +1,12 @@
 RUN: rm -rf %t && mkdir %t
 RUN: llc %S/Inputs/SourceInfo.ll --filetype=obj -o %t.dxbc --dx-pdb-file=%t/parts.pdb
-RUN: llvm-pdbutil dump --streams --dxcontainer %t/parts.pdb | FileCheck %s --check-prefix=PDB
+RUN: llvm-pdbutil pdb2yaml --dxcontainer %t/parts.pdb | FileCheck %s
 
 # Check that debug-related container parts are emitted into companion PDB file.
-PDB:              PartCount: 5
-PDB-NEXT:         Parts:
-PDB-NEXT:           ILDB |
-PDB-NEXT:           HASH |
-PDB-NEXT:           ILDN |
-PDB-NEXT:           SRCI |
-PDB-NEXT:           VERS |
+; CHECK:           PartCount:       5
+; CHECK:         Parts:
+; CHECK-DAG:       - Name:            ILDB
+; CHECK-DAG:       - Name:            HASH
+; CHECK-DAG:       - Name:            ILDN
+; CHECK-DAG:       - Name:            VERS
+; CHECK-DAG:       - Name:            SRCI
diff --git a/llvm/test/CodeGen/DirectX/embed-ildb.ll b/llvm/test/CodeGen/DirectX/embed-ildb.ll
index 634bd3dc43946..5f1b17e0e1e56 100644
--- a/llvm/test/CodeGen/DirectX/embed-ildb.ll
+++ b/llvm/test/CodeGen/DirectX/embed-ildb.ll
@@ -6,9 +6,12 @@
 ; RUN: llvm-objcopy --dump-section=DXIL=%t.dxil %t.bc
 ; RUN: llvm-dis %t.ildb -o - | FileCheck %s --check-prefix=ILDB-DIS
 ; RUN: llvm-dis %t.dxil -o - | FileCheck %s --check-prefix=DXIL-DIS
-; RUN: llvm-pdbutil dump --streams --dxcontainer %t.pdb | FileCheck %s --check-prefix=PDB
+
+; Check that a companion PDB file is emitted and that it keeps ILDB but not DXIL.
+; RUN: llvm-pdbutil pdb2yaml --dxcontainer %t.pdb | FileCheck %s --check-prefix=PDB
+
 ; Check that ILDB is written to PDB.
-; RUN: llvm-pdbutil export --dxcontainer --out=%t.pdb.dxbc %t.pdb
+; RUN: llvm-pdbutil export --stream=5 --out=%t.pdb.dxbc %t.pdb
 ; RUN: llvm-objcopy --dump-section=ILDB=%t.pdb.ildb %t.pdb.dxbc
 ; RUN: diff %t.ildb %t.pdb.ildb
 
@@ -107,8 +110,6 @@ define i32 @add(i32 %a, i32 %b) {
 ; DXIL-DIS-NOT: !"Debug Info Version"
 ; DXIL-DIS-NOT: "hlsl.hlsl"
 
-; Check that a companion PDB file is emitted and that it keeps ILDB but not DXIL.
-; PDB:            Stream 5 {{.*}} [DXContainer Stream]
-; PDB:            Parts:
-; PDB:            ILDB |
-; PDB-NOT:        DXIL |
+; PDB:     Parts:
+; PDB:       - Name:            ILDB
+; PDB-NOT:   - Name:            DXIL

>From 98372d7eb8417bb10a72d013a66fe43fd7aa5dcc Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Wed, 10 Jun 2026 00:09:11 +0500
Subject: [PATCH 3/6] Calculate hash from DXIL by default in tests

---
 .../CodeGen/DirectX/ContainerData/DebugName-default-output.test | 2 +-
 .../CodeGen/DirectX/ContainerData/DebugName-user-directory.test | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/test/CodeGen/DirectX/ContainerData/DebugName-default-output.test b/llvm/test/CodeGen/DirectX/ContainerData/DebugName-default-output.test
index bb96005ed0947..3914a3250df7d 100644
--- a/llvm/test/CodeGen/DirectX/ContainerData/DebugName-default-output.test
+++ b/llvm/test/CodeGen/DirectX/ContainerData/DebugName-default-output.test
@@ -1,5 +1,5 @@
 RUN: llc %S/Inputs/SourceInfo.ll --filetype=obj -o %t.dxbc
-RUN: llvm-objcopy --dump-section=ILDB=%t0.bc %t.dxbc
+RUN: llvm-objcopy --dump-section=DXIL=%t0.bc %t.dxbc
 RUN: %md5sum %t0.bc >%t0.bc.md5
 RUN: obj2yaml %t.dxbc >%t.yaml
 RUN: cat %t.yaml %t0.bc.md5 | FileCheck %s
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/DebugName-user-directory.test b/llvm/test/CodeGen/DirectX/ContainerData/DebugName-user-directory.test
index 002a94bcd5801..3a6fb6c0476f2 100644
--- a/llvm/test/CodeGen/DirectX/ContainerData/DebugName-user-directory.test
+++ b/llvm/test/CodeGen/DirectX/ContainerData/DebugName-user-directory.test
@@ -1,6 +1,6 @@
 RUN: rm -rf %t && mkdir %t
 RUN: llc %S/Inputs/SourceInfo.ll --filetype=obj -o %t.dxbc --dx-pdb-dir=%t
-RUN: llvm-objcopy --dump-section=ILDB=%t0.bc %t.dxbc
+RUN: llvm-objcopy --dump-section=DXIL=%t0.bc %t.dxbc
 RUN: %md5sum %t0.bc >%t0.bc.md5
 RUN: obj2yaml %t.dxbc >%t.yaml
 RUN: cat %t.yaml %t0.bc.md5 | FileCheck %s --implicit-check-not PDBN --implicit-check-not PDBH

>From 192cf7fd455b740883443a198f64f3c93d3e9dae Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Wed, 10 Jun 2026 01:11:48 +0500
Subject: [PATCH 4/6] Cleanup comments

---
 llvm/lib/MC/MCDXContainerWriter.cpp            | 1 -
 llvm/lib/Target/DirectX/DXContainerGlobals.cpp | 4 ++--
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/MC/MCDXContainerWriter.cpp b/llvm/lib/MC/MCDXContainerWriter.cpp
index 5c3ade7281d1d..c5715664091ec 100644
--- a/llvm/lib/MC/MCDXContainerWriter.cpp
+++ b/llvm/lib/MC/MCDXContainerWriter.cpp
@@ -133,7 +133,6 @@ ArrayRef<MCDXContainerPart> DXContainerObjectWriter::getParts() {
 }
 
 uint64_t DXContainerObjectWriter::writeObject() {
-  // TODO write only necessary sections.
   write(W.OS, getContext().getTargetTriple());
   clearParts();
 
diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
index bae8ce17e0696..322ed232bbcb2 100644
--- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
+++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
@@ -162,7 +162,7 @@ void DXContainerGlobals::computeShaderHashAndDebugName(
 
   mcdxbc::DebugName DebugName;
   if (PdbFileName.empty()) {
-    // TODO Add an option to compute hash based on ILDB.
+    // Use the MD5 hash as the file name.
     Digest.stringifyResult(Result, DebugNameStr);
     DebugNameStr += ".pdb";
   } else {
@@ -179,7 +179,7 @@ void DXContainerGlobals::computeShaderHashAndDebugName(
   DebugName.write(OS);
   addSection(M, Globals, ILDNData, "dx.ildn", "ILDN");
 
-  // TODO Do not create PDB in embedded mode.
+  // TODO: Do not create PDB in embedded mode.
   // Pass PDB name to DXContainerPDBPass via PDBNAME section.
   addSection(M, Globals, AbsoluteDebugName, "dx.pdb.name",
              PdbFileNameSectionName);

>From d29e738a292641d89e44afa776692daf76f1213c Mon Sep 17 00:00:00 2001
From: Vladislav Dzhidzhoev <vdzhidzhoev at accesssoftek.com>
Date: Fri, 29 May 2026 01:27:26 +0200
Subject: [PATCH 5/6] Remove unncecessary DXIL processing

---
 llvm/lib/Target/DirectX/DXContainerPDB.cpp    | 23 ++-----------------
 .../DirectX/ContainerData/PDBParts-dxil.ll    | 16 -------------
 2 files changed, 2 insertions(+), 37 deletions(-)
 delete mode 100644 llvm/test/CodeGen/DirectX/ContainerData/PDBParts-dxil.ll

diff --git a/llvm/lib/Target/DirectX/DXContainerPDB.cpp b/llvm/lib/Target/DirectX/DXContainerPDB.cpp
index 99187300504fb..cd10a2aa27a73 100644
--- a/llvm/lib/Target/DirectX/DXContainerPDB.cpp
+++ b/llvm/lib/Target/DirectX/DXContainerPDB.cpp
@@ -23,12 +23,10 @@ using namespace llvm;
 namespace {
 
 class DXContainerPDB : public ModulePass, MCDXContainerBaseWriter {
-  StringRef BitcodeSectionForPDB;
   Module *M = nullptr;
   SmallVector<MCDXContainerPart> Parts;
 
   void reset() {
-    BitcodeSectionForPDB = "";
     M = nullptr;
     Parts.clear();
   }
@@ -57,14 +55,9 @@ bool DXContainerPDB::shouldSkipSection(StringRef SectionName,
     return true;
 
   // Skip sections that are irrelevant for debug info.
-  static const StringSet<> DebugSections{"DXIL", "ILDB", "ILDN", "HASH", "PDBI",
+  static const StringSet<> DebugSections{"ILDB", "ILDN", "HASH", "PDBI",
                                          "SRCI", "STAT", "RDAT", "VERS"};
-  if (!DebugSections.contains(SectionName))
-    return true;
-
-  // Emit either DXIL or ILDB, but not both of them.
-  return dxbc::isProgramPart(SectionName) &&
-         SectionName != BitcodeSectionForPDB;
+  return !DebugSections.contains(SectionName);
 }
 
 static StringRef getGlobalData(const GlobalVariable &GV) {
@@ -96,7 +89,6 @@ bool DXContainerPDB::runOnModule(Module &M) {
 
   StringRef DebugFileName;
   ArrayRef<char> ModuleHash;
-  const GlobalVariable *DXIL = nullptr;
   const GlobalVariable *ILDB = nullptr;
   for (const GlobalVariable &GV : M.globals()) {
     if (GV.getSection() == PdbFileNameSectionName) {
@@ -109,26 +101,15 @@ bool DXContainerPDB::runOnModule(Module &M) {
     } else if (GV.getSection() == "ILDB") {
       assert(!ILDB && "Duplicate ILDB section");
       ILDB = &GV;
-    } else if (GV.getSection() == "DXIL") {
-      assert(!DXIL && "Duplicate DXIL section");
-      DXIL = &GV;
     }
   }
 
   // PDB emission was not requested.
   if (DebugFileName.empty())
     return false;
-  if (!DXIL && !ILDB)
-    report_fatal_error(
-        "Neither DXIL nor ILDB part was found for emitting PDB file");
   if (ModuleHash.empty())
     report_fatal_error("Module hash for PDB not found");
 
-  BitcodeSectionForPDB = DXIL ? DXIL->getSection() : "";
-  // Prioritize ILDB part over DXIL part.
-  if (ILDB)
-    BitcodeSectionForPDB = ILDB->getSection();
-
   BumpPtrAllocator Allocator;
   pdb::PDBFileBuilder Builder(Allocator);
 
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/PDBParts-dxil.ll b/llvm/test/CodeGen/DirectX/ContainerData/PDBParts-dxil.ll
deleted file mode 100644
index db824985ea6d7..0000000000000
--- a/llvm/test/CodeGen/DirectX/ContainerData/PDBParts-dxil.ll
+++ /dev/null
@@ -1,16 +0,0 @@
-; RUN: opt %s -dxil-pdb -o /dev/null
-; RUN: llvm-pdbutil pdb2yaml --dxcontainer PDBPartsTest-dxil.pdb | FileCheck %s
-
-; Check that PDB file contains only debug-info relevant parts.
-; CHECK:       PartCount:       2
-; CHECK:     Parts:
-; CHECK:       - Name:            DXIL
-; CHECK:       - Name:            ILDN
-
-target triple = "dxilv1.3-pc-shadermodel6.3-library"
-
- at dx.dxil = private constant [4 x i8] c"BC\C0\DE", section "DXIL", align 4
- at dx.ildn = private constant [26 x i8] c"\00\00\15\00PDBPartsTest-dxil.pdb\00", section "ILDN", align 4
- at dx.pdb.name = private constant [21 x i8] c"PDBPartsTest-dxil.pdb", section "PDBNAME", align 4
- at dx.pdb.hash = private constant [16 x i8] c"?\B9Z\96(\94D*{\AA&\A0P\B3\C9\D7", section "PDBHASH", align 4
- at llvm.compiler.used = appending global [4 x ptr] [ptr @dx.dxil, ptr @dx.ildn, ptr @dx.pdb.name, ptr @dx.pdb.hash], section "llvm.metadata"

>From f647e0d8b8a734afc9cf3e9b0e6383f2a23961dd Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Thu, 11 Jun 2026 22:49:16 +0500
Subject: [PATCH 6/6] Address HLSL Tests issues

---
 llvm/lib/Target/DirectX/DXContainerGlobals.cpp | 1 +
 llvm/lib/Target/DirectX/DXContainerPDB.cpp     | 4 ----
 2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
index 322ed232bbcb2..49a02d82bd108 100644
--- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
+++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
@@ -27,6 +27,7 @@
 #include "llvm/MC/DXContainerPSVInfo.h"
 #include "llvm/MC/MCDXContainerWriter.h"
 #include "llvm/Pass.h"
+#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Compression.h"
 #include "llvm/Support/MD5.h"
 #include "llvm/Support/Path.h"
diff --git a/llvm/lib/Target/DirectX/DXContainerPDB.cpp b/llvm/lib/Target/DirectX/DXContainerPDB.cpp
index cd10a2aa27a73..9fb67baa994d1 100644
--- a/llvm/lib/Target/DirectX/DXContainerPDB.cpp
+++ b/llvm/lib/Target/DirectX/DXContainerPDB.cpp
@@ -89,7 +89,6 @@ bool DXContainerPDB::runOnModule(Module &M) {
 
   StringRef DebugFileName;
   ArrayRef<char> ModuleHash;
-  const GlobalVariable *ILDB = nullptr;
   for (const GlobalVariable &GV : M.globals()) {
     if (GV.getSection() == PdbFileNameSectionName) {
       assert(DebugFileName.empty() && "Duplicate PDBNAME section");
@@ -98,9 +97,6 @@ bool DXContainerPDB::runOnModule(Module &M) {
       assert(ModuleHash.empty() && "Duplicate PBDHASH section");
       StringRef Data = getGlobalData(GV);
       ModuleHash = ArrayRef(Data.data(), Data.size());
-    } else if (GV.getSection() == "ILDB") {
-      assert(!ILDB && "Duplicate ILDB section");
-      ILDB = &GV;
     }
   }
 



More information about the llvm-commits mailing list