Author: Vladislav Dzhidzhoev
Date: 2026-05-28T12:12:20+02:00
New Revision: a554a1989f60ebb292b198bbbe084b5a34f880c5

URL: 
https://github.com/llvm/llvm-project/commit/a554a1989f60ebb292b198bbbe084b5a34f880c5
DIFF: 
https://github.com/llvm/llvm-project/commit/a554a1989f60ebb292b198bbbe084b5a34f880c5.diff

LOG: [DirectX] Generate shader debug file name part in llc (#199555)

This change modifies DXContainerGlobals pass to generate debug name
(ILDN) part in DXContainer. ILDN part allows consumers to find PDB file
containing shader debug info.

As ILDB emission PR is not merged yet, and PDB file creation is not
upstreamed yet, debug name is generated based on MD5-hash of bitcode
module in DXIL part.
This corresponds to DXC behavior when a shader is compiled with `/Zi
/Qembed_debug /Zsb` flags (with `/Qembed_debug`, DXC does not produce an
actual PDB file, but still emits ILDN, `/Zsb` tells DXC to use bitcode
from DXIL to compute hash).
However, here ILDN is emitted for any debug info flag configuration.
assuming that it won't break debug info consumers, and that PDB creation
will be added later.

Added: 
    clang/test/Driver/dxc_section_emission.hlsl
    llvm/test/CodeGen/DirectX/ContainerData/DebugName-DXIL.ll

Modified: 
    llvm/lib/Target/DirectX/DXContainerGlobals.cpp
    llvm/test/CodeGen/DirectX/lit.local.cfg

Removed: 
    


################################################################################
diff  --git a/clang/test/Driver/dxc_section_emission.hlsl 
b/clang/test/Driver/dxc_section_emission.hlsl
new file mode 100644
index 0000000000000..b27232f6b7d27
--- /dev/null
+++ b/clang/test/Driver/dxc_section_emission.hlsl
@@ -0,0 +1,25 @@
+// Check that debug-info-related parts are emitted when clang-dxc is invoked 
with debug option.
+
+// REQUIRES: directx-registered-target
+// RUN: %clang_dxc -Tlib_6_7 /Fo %t.dxbc -g %s 2>&1
+// RUN: obj2yaml %t.dxbc | FileCheck %s
+// RUN: %clang_dxc -Tlib_6_7 /Fo %t.dxbc /Zi %s 2>&1
+// RUN: obj2yaml %t.dxbc | FileCheck %s
+// RUN: %clang_dxc -Tlib_6_7 /Fo %t.dxbc /Zi /Qembed_debug %s 2>&1
+// RUN: obj2yaml %t.dxbc | FileCheck %s
+// RUN: %clang_dxc -Tlib_6_7 /Fo %t.dxbc -Zi %s 2>&1
+// RUN: obj2yaml %t.dxbc | FileCheck %s
+// RUN: %clang_dxc -Tlib_6_7 /Fo %t.dxbc -Zi -Qembed_debug %s 2>&1
+// RUN: obj2yaml %t.dxbc | FileCheck %s
+// RUN: %clang_dxc -Tlib_6_7 /Fo %t.dxbc -Zi -gcodeview %s 2>&1
+// RUN: obj2yaml %t.dxbc | FileCheck %s
+// RUN: %clang_dxc -Tlib_6_7 /Fo %t.dxbc -Zi -gdwarf %s 2>&1
+// RUN: obj2yaml %t.dxbc | FileCheck %s
+// RUN: %clang_dxc -Tlib_6_7 /Fo %t.dxbc -gcodeview -Zi %s 2>&1
+// RUN: obj2yaml %t.dxbc | FileCheck %s
+// RUN: %clang_dxc -Tlib_6_7 /Fo %t.dxbc -gdwarf -Zi %s 2>&1
+// RUN: obj2yaml %t.dxbc | FileCheck %s
+
+// CHECK: - Name: ILDN
+
+[numthreads(1, 1, 1)] void main() {}

diff  --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp 
b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
index 5fdc498db57e1..cd1a526539f31 100644
--- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
+++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
@@ -23,6 +23,7 @@
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/Module.h"
 #include "llvm/InitializePasses.h"
+#include "llvm/MC/DXContainerInfo.h"
 #include "llvm/MC/DXContainerPSVInfo.h"
 #include "llvm/Pass.h"
 #include "llvm/Support/MD5.h"
@@ -39,8 +40,12 @@ class DXContainerGlobals : public llvm::ModulePass {
 
   GlobalVariable *buildContainerGlobal(Module &M, Constant *Content,
                                        StringRef Name, StringRef SectionName);
+  void addSection(Module &M, SmallVector<GlobalValue *> &Globals,
+                  StringRef SectionData, StringRef MetadataName,
+                  StringRef SectionName);
   GlobalVariable *getFeatureFlags(Module &M);
-  GlobalVariable *computeShaderHash(Module &M);
+  void computeShaderHashAndDebugName(Module &M,
+                                     SmallVector<GlobalValue *> &Globals);
   GlobalVariable *buildSignature(Module &M, Signature &Sig, StringRef Name,
                                  StringRef SectionName);
   void addSignature(Module &M, SmallVector<GlobalValue *> &Globals);
@@ -74,7 +79,7 @@ class DXContainerGlobals : public llvm::ModulePass {
 bool DXContainerGlobals::runOnModule(Module &M) {
   llvm::SmallVector<GlobalValue *> Globals;
   Globals.push_back(getFeatureFlags(M));
-  Globals.push_back(computeShaderHash(M));
+  computeShaderHashAndDebugName(M, Globals);
   addSignature(M, Globals);
   addRootSignature(M, Globals);
   addPipelineStateValidationInfo(M, Globals);
@@ -93,7 +98,19 @@ GlobalVariable *DXContainerGlobals::getFeatureFlags(Module 
&M) {
   return buildContainerGlobal(M, FeatureFlagsConstant, "dx.sfi0", "SFI0");
 }
 
-GlobalVariable *DXContainerGlobals::computeShaderHash(Module &M) {
+void DXContainerGlobals::addSection(Module &M,
+                                    SmallVector<GlobalValue *> &Globals,
+                                    StringRef SectionData,
+                                    StringRef MetadataName,
+                                    StringRef SectionName) {
+  Constant *SectionConstant = ConstantDataArray::getString(
+      M.getContext(), SectionData, /*AddNull*/ false);
+  Globals.emplace_back(
+      buildContainerGlobal(M, SectionConstant, MetadataName, SectionName));
+}
+
+void DXContainerGlobals::computeShaderHashAndDebugName(
+    Module &M, SmallVector<GlobalValue *> &Globals) {
   auto *DXILConstant =
       cast<ConstantDataArray>(M.getNamedGlobal("dx.dxil")->getInitializer());
   MD5 Digest;
@@ -113,7 +130,26 @@ GlobalVariable 
*DXContainerGlobals::computeShaderHash(Module &M) {
 
   Constant *ModuleConstant =
       ConstantDataArray::get(M.getContext(), arrayRefFromStringRef(Data));
-  return buildContainerGlobal(M, ModuleConstant, "dx.hash", "HASH");
+  Globals.emplace_back(
+      buildContainerGlobal(M, ModuleConstant, "dx.hash", "HASH"));
+
+  // Emit ILDN part in debug info mode.
+  // DXIL bitcode hash is used, which corresponds to DXC behavior with
+  // `/Zi /Qembed_debug /Zsb` flags.
+  if (M.debug_compile_units().empty())
+    return;
+
+  SmallString<40> DebugNameStr;
+  Digest.stringifyResult(Result, DebugNameStr);
+  DebugNameStr += ".pdb";
+
+  mcdxbc::DebugName DebugName;
+  DebugName.setFilename(DebugNameStr);
+
+  SmallString<64> ILDNData;
+  raw_svector_ostream OS(ILDNData);
+  DebugName.write(OS);
+  addSection(M, Globals, ILDNData, "dx.ildn", "ILDN");
 }
 
 GlobalVariable *DXContainerGlobals::buildContainerGlobal(
@@ -175,9 +211,7 @@ void DXContainerGlobals::addRootSignature(Module &M,
 
   RS->write(OS);
 
-  Constant *Constant =
-      ConstantDataArray::getString(M.getContext(), Data, /*AddNull*/ false);
-  Globals.emplace_back(buildContainerGlobal(M, Constant, "dx.rts0", "RTS0"));
+  addSection(M, Globals, Data, "dx.rts0", "RTS0");
 }
 
 void DXContainerGlobals::addResourcesForPSV(Module &M, PSVRuntimeInfo &PSV) {
@@ -302,9 +336,7 @@ void DXContainerGlobals::addPipelineStateValidationInfo(
 
   PSV.finalize(MMI.ShaderProfile);
   PSV.write(OS);
-  Constant *Constant =
-      ConstantDataArray::getString(M.getContext(), Data, /*AddNull*/ false);
-  Globals.emplace_back(buildContainerGlobal(M, Constant, "dx.psv0", "PSV0"));
+  addSection(M, Globals, Data, "dx.psv0", "PSV0");
 }
 
 char DXContainerGlobals::ID = 0;

diff  --git a/llvm/test/CodeGen/DirectX/ContainerData/DebugName-DXIL.ll 
b/llvm/test/CodeGen/DirectX/ContainerData/DebugName-DXIL.ll
new file mode 100644
index 0000000000000..0a22e65e59af3
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ContainerData/DebugName-DXIL.ll
@@ -0,0 +1,38 @@
+; Verify that ILDN part is created when debug info is on.
+
+; RUN: llc %s --filetype=obj -o %t.dxbc
+; RUN: obj2yaml %t.dxbc >%t.yaml
+; RUN: llvm-objcopy --dump-section=DXIL=%t0.bc %t.dxbc
+; RUN: %md5sum %t0.bc >%t0.bc.md5
+; RUN: cat %t.yaml %t0.bc.md5 | FileCheck %s
+
+; Verify that ILDN part is not created when debug info is off.
+; RUN: opt -strip-debug < %s | llc --filetype=obj | obj2yaml | \
+; RUN:   FileCheck --implicit-check-not=ILDN --check-prefix=NODEBUG %s
+
+; 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]]
+
+; NODEBUG:     - Name: DXIL
+
+target triple = "dxilv1.3-pc-shadermodel6.3-library"
+
+define float @_Z3fooff(float %a, float %b) {
+entry1:
+  %add = fadd float %a, %b
+  ret float %add
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, emissionKind: 
FullDebug)
+!1 = !DIFile(filename: "dx-source-metadata.hlsl", directory: "C:\\")
+!2 = !{i32 2, !"Dwarf Version", i32 4}
+!3 = !{i32 2, !"Debug Info Version", i32 3}

diff  --git a/llvm/test/CodeGen/DirectX/lit.local.cfg 
b/llvm/test/CodeGen/DirectX/lit.local.cfg
index 72de724f06d79..d40234d1e598c 100644
--- a/llvm/test/CodeGen/DirectX/lit.local.cfg
+++ b/llvm/test/CodeGen/DirectX/lit.local.cfg
@@ -1,2 +1,14 @@
 if not "DirectX" in config.root.targets:
     config.unsupported = True
+
+# Insert at 0 to prevent '%p' from being substituted with test directory in 
'%python'.
+config.substitutions.insert(
+    0,
+    (
+        "%md5sum",
+        '%python -c "import sys,hashlib; '
+        "p=sys.argv[1]; "
+        "h=hashlib.md5(open(p,'rb').read()).hexdigest(); "
+        'print(h)"',
+    ),
+)


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to