Skip to content

Commit aef4142

Browse files
committed
[DirectX][HLSL] Add /Qsource_in_debug_module to llc and Clang DXC driver
dx.source metadata nodes contain shader source code information, such as source files content, macro definitions used to compile shader, and compiler arguments. PR for Clang to produce them is currently on review llvm/llvm-project#199689. Original DXC has two modes to handle these nodes: 1. If /Qsource_in_debug_module is not specified, Source Info part (SRCI) is created inside shader's debug PDB file, and dx.source metadata nodes are replaced with empty nodes. 2. If /Qsource_in_debug_module is specified, dx.source nodes are preserved in debug bitcode module, for debug info consumers to use them directly. This patch reimplements the behavior described in item 2. /Qsource_in_debug_module is added to Clang DXC driver, and the corresponding flag is added to llc. In DXILWriterPass, this flag is used to determine how dx.source metadata nodes should be handled.
1 parent 574243d commit aef4142

6 files changed

Lines changed: 105 additions & 4 deletions

File tree

clang/include/clang/Options/Options.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9624,6 +9624,11 @@ def dxc_Fc : DXCJoinedOrSeparate<"Fc">,
96249624
HelpText<"Output assembly listing file">;
96259625
def dxc_Frs : DXCJoinedOrSeparate<"Frs">,
96269626
HelpText<"Output additional root signature object file">;
9627+
def dxc_source_in_debug_module
9628+
: Option<["/", "-"], "Qsource_in_debug_module", KIND_FLAG>,
9629+
Group<dxc_Group>,
9630+
Visibility<[DXCOption]>,
9631+
HelpText<"Embed source code into debug module on DirectX target">;
96279632
def dxil_validator_version : Option<["/", "-"], "validator-version", KIND_SEPARATE>,
96289633
Group<dxc_Group>, Flags<[HelpHidden]>,
96299634
Visibility<[DXCOption, ClangOption, CC1Option]>,

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3832,6 +3832,11 @@ static void RenderHLSLOptions(const ArgList &Args, ArgStringList &CmdArgs,
38323832
if (!Args.hasArg(options::OPT_dxc_no_stdinc) &&
38333833
!Args.hasArg(options::OPT_nostdinc))
38343834
CmdArgs.push_back("-finclude-default-header");
3835+
3836+
if (Args.hasArg(options::OPT_dxc_source_in_debug_module)) {
3837+
CmdArgs.push_back("-mllvm");
3838+
CmdArgs.push_back("--dx-source-in-debug-module");
3839+
}
38353840
}
38363841

38373842
static void RenderOpenACCOptions(const Driver &D, const ArgList &Args,
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// RUN: %clang_dxc -Tlib_6_7 -### /Zi /Qsource_in_debug_module %s 2>&1 | FileCheck %s
2+
// RUN: %clang_dxc -Tlib_6_7 -### /Zi -Qsource_in_debug_module %s 2>&1 | FileCheck %s
3+
// RUN: %clang_dxc -Tlib_6_7 -### /Zi %s 2>&1 | FileCheck %s --check-prefix=NOFLAG
4+
5+
// CHECK: "-mllvm" "--dx-source-in-debug-module"
6+
// NOFLAG-NOT: --dx-source-in-debug-module

llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -514,15 +514,18 @@ static void cleanModuleFlags(Module &M) {
514514
M.addModuleFlag(Flag.Behavior, Flag.Key->getString(), Flag.Val);
515515
}
516516

517-
using GlobalMDList = std::array<StringLiteral, 7>;
517+
using GlobalMDList = std::array<StringLiteral, 11>;
518518

519519
// The following are compatible with DXIL but not emit with clang, they can
520520
// be added when applicable:
521521
// dx.typeAnnotations, dx.viewIDState, dx.dxrPayloadAnnotations
522522
static GlobalMDList CompatibleNamedModuleMDs = {
523-
"llvm.ident", "llvm.module.flags", "dx.resources", "dx.valver",
524-
"dx.shaderModel", "dx.version", "dx.entryPoints",
525-
};
523+
"llvm.ident", "llvm.module.flags",
524+
"dx.resources", "dx.valver",
525+
"dx.shaderModel", "dx.version",
526+
"dx.entryPoints", "dx.source.contents",
527+
"dx.source.defines", "dx.source.mainFileName",
528+
"dx.source.args"};
526529

527530
static void translateGlobalMetadata(Module &M, DXILResourceMap &DRM,
528531
DXILResourceTypeMap &DRTM,

llvm/lib/Target/DirectX/DXILWriter/DXILWriterPass.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,17 @@
2828
#include "llvm/InitializePasses.h"
2929
#include "llvm/Pass.h"
3030
#include "llvm/Support/Alignment.h"
31+
#include "llvm/Support/CommandLine.h"
3132
#include "llvm/Transforms/Utils/ModuleUtils.h"
3233

3334
using namespace llvm;
3435
using namespace llvm::dxil;
3536

37+
static cl::opt<bool> SourceInDebugModule(
38+
"dx-source-in-debug-module",
39+
cl::desc("Embed source code into debug module on DirectX target"),
40+
cl::init(false));
41+
3642
namespace {
3743
class WriteDXILPass : public llvm::ModulePass {
3844
raw_ostream &OS; // raw_ostream to print on
@@ -138,6 +144,16 @@ static void removeLifetimeIntrinsics(Module &M) {
138144
}
139145
}
140146

147+
static void replaceNamedMetadataArray(Module &M, StringRef Name,
148+
ArrayRef<Metadata *> NewOps) {
149+
NamedMDNode *NMD = M.getNamedMetadata(Name);
150+
if (!NMD)
151+
return;
152+
NMD->eraseFromParent();
153+
M.getOrInsertNamedMetadata(Name)->addOperand(
154+
MDTuple::get(M.getContext(), NewOps));
155+
}
156+
141157
class EmbedDXILPass : public llvm::ModulePass {
142158
public:
143159
static char ID; // Pass identification, replacement for typeid
@@ -155,6 +171,16 @@ class EmbedDXILPass : public llvm::ModulePass {
155171
// fail the Module Verifier if performed in an earlier pass
156172
legalizeLifetimeIntrinsics(M);
157173

174+
// Replace dx.source metadata nodes with stubs.
175+
if (!SourceInDebugModule) {
176+
LLVMContext &Ctx = M.getContext();
177+
MDString *EmptyString = MDString::get(Ctx, "");
178+
replaceNamedMetadataArray(M, "dx.source.contents",
179+
{EmptyString, EmptyString});
180+
replaceNamedMetadataArray(M, "dx.source.defines", {});
181+
replaceNamedMetadataArray(M, "dx.source.mainFileName", {EmptyString});
182+
replaceNamedMetadataArray(M, "dx.source.args", {});
183+
}
158184
const auto DIMap = DXILDebugInfoPass::run(M);
159185
WriteDXILToFile(M, OS, DIMap);
160186

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
; Compare source info emission with and without --dx-source-in-debug-module flag.
2+
3+
; RUN: llc %s --filetype=obj -o %t.dxbc
4+
; RUN: llvm-objcopy --dump-section=DXIL=%t.dxil.bc %t.dxbc
5+
; RUN: llvm-dis %t.dxil.bc -o - | FileCheck %s --check-prefix=ILDB-DIS
6+
7+
; RUN: llc %s --filetype=obj -o %t.dxbc --dx-source-in-debug-module
8+
; RUN: llvm-objcopy --dump-section=DXIL=%t.dxil.bc %t.dxbc
9+
; RUN: llvm-dis %t.dxil.bc -o - | FileCheck %s --check-prefix=ILDB-SOURCE-DIS
10+
11+
; Without the flag, dx.source should be replaced with dummy metadata.
12+
; ILDB-DIS: !dx.source.contents = !{![[CONTENTS:[0-9]+]]}
13+
; ILDB-DIS: !dx.source.defines = !{![[EMPTY_ARR:[0-9]+]]}
14+
; ILDB-DIS: !dx.source.mainFileName = !{![[MAIN:[0-9]+]]}
15+
; ILDB-DIS: !dx.source.args = !{![[EMPTY_ARR]]}
16+
; ILDB-DIS: ![[CONTENTS]] = !{!"", !""}
17+
; ILDB-DIS: ![[EMPTY_ARR]] = !{}
18+
; ILDB-DIS: ![[MAIN]] = !{!""}
19+
20+
; With the flag, dx.source should be be preserved.
21+
; ILDB-SOURCE-DIS: !dx.source.args = !{![[ARGS:[0-9]+]]}
22+
; ILDB-SOURCE-DIS: !dx.source.contents = !{![[FILE1:[0-9]+]], ![[FILE2:[0-9]+]], ![[FILE3:[0-9]+]]}
23+
; ILDB-SOURCE-DIS: !dx.source.mainFileName = !{![[MAIN:[0-9]+]]}
24+
; ILDB-SOURCE-DIS: !dx.source.defines = !{![[DEFINES:[0-9]+]]}
25+
; ILDB-SOURCE-DIS: ![[FILE1]] = !{!"C:\\dx-source-metadata.hlsl",
26+
; ILDB-SOURCE-DIS: ![[FILE2]] = !{!"C:\\a.hlsl"
27+
; ILDB-SOURCE-DIS: ![[FILE3]] = !{!"C:\\b.hlsl"
28+
; ILDB-SOURCE-DIS: ![[MAIN]] = !{!"C:\\dx-source-metadata.hlsl"}
29+
; ILDB-SOURCE-DIS: ![[DEFINES]] = !{!"USER_DEF0=42", !"USER_DEF1=43"}
30+
31+
target triple = "dxilv1.3-pc-shadermodel6.3-library"
32+
33+
define float @_Z3fooff(float %a, float %b) {
34+
entry:
35+
%add = fadd float %a, %b
36+
ret float %add
37+
}
38+
39+
!llvm.dbg.cu = !{!4}
40+
!llvm.module.flags = !{!6, !7}
41+
42+
!dx.source.args = !{!0}
43+
!dx.source.contents = !{!1, !2, !3}
44+
!dx.source.mainFileName = !{!8}
45+
!dx.source.defines = !{!9}
46+
47+
!0 = !{!"-g", !"-Tlib_6_3", !"-DUSER_DEF0=42", !"-DUSER_DEF1=43", !"C:\\\\dx-source-metadata.hlsl"}
48+
!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"}
49+
!2 = !{!"C:\\a.hlsl", !"#include \22b.hlsl\22\0A"}
50+
!3 = !{!"C:\\b.hlsl", !"#include <c.hlsl>\0A"}
51+
!4 = distinct !DICompileUnit(language: DW_LANG_C99, file: !5, emissionKind: FullDebug)
52+
!5 = !DIFile(filename: "dx-source-metadata.hlsl", directory: "C:\\")
53+
!6 = !{i32 2, !"Dwarf Version", i32 4}
54+
!7 = !{i32 2, !"Debug Info Version", i32 3}
55+
!8 = !{!"C:\\dx-source-metadata.hlsl"}
56+
!9 = !{!"USER_DEF0=42", !"USER_DEF1=43"}

0 commit comments

Comments
 (0)