[clang] f48b09b - [Driver][DirectX] Add `/Qsource_in_debug_module` flag (#204415)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jul 15 02:52:34 PDT 2026
Author: Ilia Kuklin
Date: 2026-07-15T14:52:28+05:00
New Revision: f48b09bbe0654fcd7ddf6b8a8aec807d8552a816
URL: https://github.com/llvm/llvm-project/commit/f48b09bbe0654fcd7ddf6b8a8aec807d8552a816
DIFF: https://github.com/llvm/llvm-project/commit/f48b09bbe0654fcd7ddf6b8a8aec807d8552a816.diff
LOG: [Driver][DirectX] Add `/Qsource_in_debug_module` flag (#204415)
Adds a flag that embeds the source code info into `dx.source` nodes in
bitcode, for both main DXContainer and PDB file output. For the PDB
file, it also removes the `SRCI` part from the output.
Added:
llvm/test/CodeGen/DirectX/ContainerData/SourceInfo-Strip.ll
Modified:
clang/include/clang/Options/Options.td
clang/lib/Driver/ToolChains/Clang.cpp
clang/test/Driver/dxc_debug.hlsl
llvm/lib/Target/DirectX/DXContainerGlobals.cpp
llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp
llvm/lib/Target/DirectX/DXILWriter/DXILWriterPass.cpp
llvm/test/CodeGen/DirectX/embed-ildb.ll
Removed:
################################################################################
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index 4974209b8db30..e6868e6b9a4ba 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -9753,6 +9753,9 @@ def dxc_Zss : DXCFlag<"Zss">,
HelpText<"Compute Shader Hash considering source information">;
def dxc_Zsb : DXCFlag<"Zsb">,
HelpText<"Compute Shader Hash considering only output binary">;
+def dxc_source_in_debug_module
+ : DXCFlag<"Qsource_in_debug_module">,
+ HelpText<"Embed source code into PDB debug module">;
def dxil_validator_version : Option<["/", "-"], "validator-version", KIND_SEPARATE>,
Group<dxc_Group>, Flags<[HelpHidden]>,
Visibility<[DXCOption, ClangOption, CC1Option]>,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 1d6877ffbd8a7..c2b44919c1305 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -3982,6 +3982,10 @@ static void RenderHLSLOptions(const Driver &D, const ArgList &Args,
}
if (Arg *A = Args.getLastArg(options::OPT_dxc_Zsb))
A->claim(); // /Zsb is the default behavior, no need to forward it to llc.
+ if (Args.hasArg(options::OPT_dxc_source_in_debug_module)) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("--dx-source-in-debug-module");
+ }
}
static void RenderOpenACCOptions(const Driver &D, const ArgList &Args,
diff --git a/clang/test/Driver/dxc_debug.hlsl b/clang/test/Driver/dxc_debug.hlsl
index 1a6c26c80750b..6f37e59d4cf32 100644
--- a/clang/test/Driver/dxc_debug.hlsl
+++ b/clang/test/Driver/dxc_debug.hlsl
@@ -4,6 +4,7 @@
// RUN: %clang_dxc -Tlib_6_7 -### -Zi %s 2>&1 | FileCheck %s
// RUN: %clang_dxc -Tlib_6_7 -### -Zi -Qembed_debug %s 2>&1 | FileCheck %s
// RUN: %clang_dxc -Tlib_6_7 -### -Zi -Zss %s 2>&1 | FileCheck %s --check-prefix=CHECK,CHECK-ZSS
+// RUN: %clang_dxc -Tlib_6_7 -### /Zi -Qsource_in_debug_module %s 2>&1 | FileCheck %s --check-prefix=CHECK,CHECK-SIDM
// RUN: %clang_dxc -Tlib_6_7 -### -Zi -gcodeview %s 2>&1 | FileCheck %s -check-prefixes=CHECK,CHECK-CV
// RUN: %clang_dxc -Tlib_6_7 -### -Zi -gdwarf %s 2>&1 | FileCheck %s -check-prefixes=CHECK,CHECK-DWARF
// RUN: %clang_dxc -Tlib_6_7 -### -gcodeview -Zi %s 2>&1 | FileCheck %s -check-prefixes=CHECK,CHECK-CV
@@ -16,6 +17,7 @@
// CHECK-DWARF-SAME: -dwarf-version=4
// Check that the flags are converted to their llc equivalents.
// CHECK-ZSS-SAME: -dx-Zss
+// CHECK-SIDM-SAME: --dx-source-in-debug-module
// Make sure dxc command line arguments are passed to clang invocation.
// CHECK-SAME: -fdx-record-command-line
// CHECK-CMD-SAME: --driver-mode=dxc -T lib_6_7 -### -g {{.*}}dxc_debug.hlsl
diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
index 47396b8c33580..7b033c3249008 100644
--- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
+++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
@@ -46,6 +46,7 @@ cl::opt<std::string> PdbDebugPath(
cl::desc("Write debug information to the given file, or automatically "
"named file in directory when ending in '/'"),
cl::value_desc("filename"));
+extern cl::opt<bool> SourceInDebugModule;
namespace {
class DXContainerGlobals : public llvm::ModulePass {
@@ -397,7 +398,7 @@ void DXContainerGlobals::addSourceInfo(Module &M,
dxil::ModuleMetadataInfo &MMI =
getAnalysis<DXILMetadataAnalysisWrapperPass>().getModuleMetadata();
- if (!MMI.SourceInfo)
+ if (!MMI.SourceInfo || SourceInDebugModule)
return;
MMI.SourceInfo->computeEntries();
diff --git a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp
index 49a20e2f7517a..240d5814d33d4 100644
--- a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp
+++ b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp
@@ -514,15 +514,18 @@ static void cleanModuleFlags(Module &M) {
M.addModuleFlag(Flag.Behavior, Flag.Key->getString(), Flag.Val);
}
-using GlobalMDList = std::array<StringLiteral, 7>;
+using GlobalMDList = std::array<StringLiteral, 11>;
// The following are compatible with DXIL but not emit with clang, they can
// be added when applicable:
// dx.typeAnnotations, dx.viewIDState, dx.dxrPayloadAnnotations
static GlobalMDList CompatibleNamedModuleMDs = {
- "llvm.ident", "llvm.module.flags", "dx.resources", "dx.valver",
- "dx.shaderModel", "dx.version", "dx.entryPoints",
-};
+ "llvm.ident", "llvm.module.flags",
+ "dx.resources", "dx.valver",
+ "dx.shaderModel", "dx.version",
+ "dx.entryPoints", "dx.source.contents",
+ "dx.source.defines", "dx.source.mainFileName",
+ "dx.source.args"};
static void translateGlobalMetadata(Module &M, DXILResourceMap &DRM,
DXILResourceTypeMap &DRTM,
diff --git a/llvm/lib/Target/DirectX/DXILWriter/DXILWriterPass.cpp b/llvm/lib/Target/DirectX/DXILWriter/DXILWriterPass.cpp
index 9bbb87327d749..c17b571d41ce3 100644
--- a/llvm/lib/Target/DirectX/DXILWriter/DXILWriterPass.cpp
+++ b/llvm/lib/Target/DirectX/DXILWriter/DXILWriterPass.cpp
@@ -29,6 +29,7 @@
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/Support/Alignment.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
@@ -37,6 +38,10 @@ using namespace llvm::dxil;
extern cl::opt<bool> EmbedDebug;
extern cl::opt<std::string> PdbDebugPath;
+cl::opt<bool> SourceInDebugModule(
+ "dx-source-in-debug-module",
+ cl::desc("Embed source code into debug module on DirectX target"),
+ cl::init(false));
namespace {
class WriteDXILPass : public llvm::ModulePass {
@@ -160,15 +165,16 @@ class EmbedDXILPass : public llvm::ModulePass {
if (HasDebugInfo) {
if (WriteDebug) {
- // Replace dx.source metadata nodes with stubs.
- // TODO: Add /Qsource_in_debug_module flag to enable/disable this.
- LLVMContext &Ctx = M.getContext();
- MDString *EmptyString = MDString::get(Ctx, "");
- replaceNamedMetadataArray(M, "dx.source.contents",
- {EmptyString, EmptyString});
- replaceNamedMetadataArray(M, "dx.source.defines", {});
- replaceNamedMetadataArray(M, "dx.source.mainFileName", {EmptyString});
- replaceNamedMetadataArray(M, "dx.source.args", {});
+ if (!SourceInDebugModule) {
+ // Replace dx.source metadata nodes with stubs.
+ LLVMContext &Ctx = M.getContext();
+ MDString *EmptyString = MDString::get(Ctx, "");
+ replaceNamedMetadataArray(M, "dx.source.contents",
+ {EmptyString, EmptyString});
+ replaceNamedMetadataArray(M, "dx.source.defines", {});
+ replaceNamedMetadataArray(M, "dx.source.mainFileName", {EmptyString});
+ replaceNamedMetadataArray(M, "dx.source.args", {});
+ }
} else {
// If we have an ILDB part, strip DXIL from all debug info.
StripDebugInfo(M);
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/SourceInfo-Strip.ll b/llvm/test/CodeGen/DirectX/ContainerData/SourceInfo-Strip.ll
new file mode 100644
index 0000000000000..f7792b38e04c5
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ContainerData/SourceInfo-Strip.ll
@@ -0,0 +1,109 @@
+; Compare source info emission with and without --dx-source-in-debug-module flag.
+
+; RUN: llc %s --filetype=obj -o %t.dxbc --dx-pdb-path=%t.pdb
+; RUN: llvm-pdbutil export --stream=5 --out=%t.pdb.dxbc %t.pdb
+; RUN: obj2yaml %t.pdb.dxbc | FileCheck %s --check-prefix=DXC
+; RUN: llvm-objcopy --dump-section=DXIL=%t.dxil.bc %t.dxbc
+; RUN: llvm-dis %t.dxil.bc -o - | FileCheck %s --check-prefix=DXIL-DIS
+; RUN: llvm-objcopy --dump-section=ILDB=%t.ildb.bc %t.pdb.dxbc
+; RUN: llvm-dis %t.ildb.bc -o - | FileCheck %s --check-prefix=ILDB-DIS
+
+; RUN: llc %s --filetype=obj -o %t.dxbc --dx-source-in-debug-module --dx-pdb-path=%t.pdb
+; RUN: llvm-pdbutil export --stream=5 --out=%t.pdb.dxbc %t.pdb
+; RUN: obj2yaml %t.pdb.dxbc | FileCheck %s --check-prefix=DXC-SOURCE
+; RUN: llvm-objcopy --dump-section=DXIL=%t.dxil.bc %t.dxbc
+; RUN: llvm-dis %t.dxil.bc -o - | FileCheck %s --check-prefix=DXIL-SOURCE-DIS
+; RUN: llvm-objcopy --dump-section=ILDB=%t.ildb.bc %t.pdb.dxbc
+; RUN: llvm-dis %t.ildb.bc -o - | FileCheck %s --check-prefix=ILDB-SOURCE-DIS
+
+; Without the flag, dx.source should be stripped away from DXIL, and replaced
+; with dummy metadata in ILDB.
+; DXIL-DIS-NOT: dx.source
+; ILDB-DIS: !dx.source.contents = !{![[CONTENTS:[0-9]+]]}
+; ILDB-DIS: !dx.source.defines = !{![[EMPTY_ARR:[0-9]+]]}
+; ILDB-DIS: !dx.source.mainFileName = !{![[MAIN:[0-9]+]]}
+; ILDB-DIS: !dx.source.args = !{![[EMPTY_ARR]]}
+; ILDB-DIS: ![[CONTENTS]] = !{!"", !""}
+; ILDB-DIS: ![[EMPTY_ARR]] = !{}
+; ILDB-DIS: ![[MAIN]] = !{!""}
+
+; Without the flag, SRCI should be emitted.
+; DXC: - Name: SRCI
+; DXC: SourceInfo:
+; DXC-NEXT: Header:
+; DXC: SectionCount: 3
+; DXC-NEXT: Names:
+; DXC-NEXT: SectionHeader:
+; DXC: Type: SourceNames
+; DXC-NEXT: Header:
+; DXC: Count: 3
+; DXC: Entries:
+; DXC: FileName: 'C:\dx-source-metadata.hlsl'
+; DXC: FileName: 'C:\a.hlsl'
+; DXC: FileName: 'C:\b.hlsl'
+; DXC-NEXT: Contents:
+; DXC-NEXT: SectionHeader:
+; DXC: Type: SourceContents
+; DXC-NEXT: Header:
+; DXC: Count: 3
+; DXC: Entries:
+; DXC: FileContent: "#include \"a.hlsl\"\n#include \"b.hlsl\"\n\nfloat foo(float a, float b) {\n return a + b;\n}\n"
+; DXC: FileContent: "#include \"b.hlsl\"\n"
+; DXC: FileContent: "#include <c.hlsl>\n"
+; DXC: Args:
+; DXC: SectionHeader:
+; DXC: Header:
+; DXC: Count: 5
+; DXC: Args:
+; DXC-NEXT: - Arg: '-g'
+; DXC-NEXT: Value: ''
+; DXC-NEXT: - Arg: '-Tlib_6_3'
+; DXC-NEXT: Value: ''
+; DXC-NEXT: - Arg: '-DUSER_DEF0=42'
+; DXC-NEXT: Value: ''
+; DXC-NEXT: - Arg: '-DUSER_DEF1=43'
+; DXC-NEXT: Value: ''
+; DXC-NEXT: - Arg: 'C:\\dx-source-metadata.hlsl'
+; DXC-NEXT: Value: ''
+
+; With the flag, dx.source should be stripped away from DXIL, and kept untouched in ILDB.
+; DXIL-SOURCE-DIS-NOT: dx.source
+; ILDB-SOURCE-DIS: !dx.source.args = !{![[ARGS:[0-9]+]]}
+; ILDB-SOURCE-DIS: !dx.source.contents = !{![[FILE1:[0-9]+]], ![[FILE2:[0-9]+]], ![[FILE3:[0-9]+]]}
+; ILDB-SOURCE-DIS: !dx.source.mainFileName = !{![[MAIN:[0-9]+]]}
+; ILDB-SOURCE-DIS: !dx.source.defines = !{![[DEFINES:[0-9]+]]}
+; ILDB-SOURCE-DIS: ![[FILE1]] = !{!"C:\\dx-source-metadata.hlsl",
+; ILDB-SOURCE-DIS: ![[FILE2]] = !{!"C:\\a.hlsl"
+; ILDB-SOURCE-DIS: ![[FILE3]] = !{!"C:\\b.hlsl"
+; ILDB-SOURCE-DIS: ![[MAIN]] = !{!"C:\\dx-source-metadata.hlsl"}
+; ILDB-SOURCE-DIS: ![[DEFINES]] = !{!"USER_DEF0=42", !"USER_DEF1=43"}
+
+; With the flag, SRCI should not be emitted.
+; DXC-SOURCE-NOT: - Name: SRCI
+
+target triple = "dxilv1.3-pc-shadermodel6.3-library"
+
+define float @_Z3fooff(float %a, float %b) {
+entry:
+ %add = fadd float %a, %b
+ ret float %add
+}
+
+!llvm.dbg.cu = !{!4}
+!llvm.module.flags = !{!6, !7}
+
+!dx.source.args = !{!0}
+!dx.source.contents = !{!1, !2, !3}
+!dx.source.mainFileName = !{!8}
+!dx.source.defines = !{!9}
+
+!0 = !{!"-g", !"-Tlib_6_3", !"-DUSER_DEF0=42", !"-DUSER_DEF1=43", !"C:\\\\dx-source-metadata.hlsl"}
+!1 = !{!"C:\\dx-source-metadata.hlsl", !"#include \22a.hlsl\22\0A#include \22b.hlsl\22\0A\0Afloat foo(float a, float b) {\0A return a + b;\0A}\0A"}
+!2 = !{!"C:\\a.hlsl", !"#include \22b.hlsl\22\0A"}
+!3 = !{!"C:\\b.hlsl", !"#include <c.hlsl>\0A"}
+!4 = distinct !DICompileUnit(language: DW_LANG_C99, file: !5, emissionKind: FullDebug)
+!5 = !DIFile(filename: "dx-source-metadata.hlsl", directory: "C:\\")
+!6 = !{i32 2, !"Dwarf Version", i32 4}
+!7 = !{i32 2, !"Debug Info Version", i32 3}
+!8 = !{!"C:\\dx-source-metadata.hlsl"}
+!9 = !{!"USER_DEF0=42", !"USER_DEF1=43"}
diff --git a/llvm/test/CodeGen/DirectX/embed-ildb.ll b/llvm/test/CodeGen/DirectX/embed-ildb.ll
index b1203bb1b3fcf..c0c9545017944 100644
--- a/llvm/test/CodeGen/DirectX/embed-ildb.ll
+++ b/llvm/test/CodeGen/DirectX/embed-ildb.ll
@@ -93,6 +93,10 @@ define i32 @add(i32 %a, i32 %b) {
; ILDB-DIS: define i32 @add(i32 %a, i32 %b)
; ILDB-DIS: !llvm.dbg.cu
+; ILDB-DIS: !dx.source.contents
+; ILDB-DIS: !dx.source.defines
+; ILDB-DIS: !dx.source.mainFileName
+; ILDB-DIS: !dx.source.args
; ILDB-DIS: !DICompileUnit
; ILDB-DIS: !DIFile
; ILDB-DIS: !"Dwarf Version"
More information about the cfe-commits
mailing list