Skip to content

Commit 407fc9b

Browse files
kuilpddzhidzhoev
authored andcommitted
[Driver][DirectX] Add /Qembed_debug and /Fd flags (#150)
1 parent 05312db commit 407fc9b

19 files changed

Lines changed: 181 additions & 71 deletions

clang/include/clang/Basic/DiagnosticDriverKinds.td

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,16 @@ def err_drv_dxc_Fre_requires_Fo_metal
883883
: Error<"-Fre option requires -Fo option when targeting Metal">;
884884
def err_drv_dxc_invalid_shader_hash
885885
: Error<"cannot specify both /Zss and /Zsb">;
886+
def err_drv_no_debug_info_for_embed_debug
887+
: Error<"must enable debug info with /Zi for /Qembed_debug">;
888+
def err_drv_no_debug_info_for_Fd
889+
: Error<"/Fd specified, but no Debug Info was found in the shader; "
890+
"please use the /Zi or /Zs switch to generate debug information "
891+
"compiling this shader">;
892+
def warn_drv_dxc_no_output_for_debug
893+
: Warning<"no output provided for debug - embedding PDB in shader "
894+
"container; use /Qembed_debug to silence this warning">,
895+
InGroup<DiagGroup<"default-embed-debug">>;
886896
def err_drv_hlsl_unsupported_target : Error<
887897
"HLSL code generation is unsupported for target '%0'">;
888898
def err_drv_hlsl_bad_shader_required_in_target : Error<

clang/include/clang/Options/Options.td

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9319,10 +9319,9 @@ def _SLASH_ZH_SHA1 : CLFlag<"ZH:SHA1">,
93199319
HelpText<"Use SHA1 for file checksums in debug info">,
93209320
Alias<gsrc_hash_EQ>, AliasArgs<["sha1"]>;
93219321
def _SLASH_ZH_SHA_256 : CLFlag<"ZH:SHA_256">,
9322-
HelpText<"Use SHA256 for file checksums in debug info">,
9323-
Alias<gsrc_hash_EQ>, AliasArgs<["sha256"]>;
9324-
def _SLASH_Zi : CLFlag<"Zi", [CLOption, DXCOption]>, Alias<g_Flag>,
9325-
HelpText<"Like /Z7">;
9322+
HelpText<"Use SHA256 for file checksums in debug info">,
9323+
Alias<gsrc_hash_EQ>,
9324+
AliasArgs<["sha256"]>;
93269325
def _SLASH_Zp : CLJoined<"Zp">,
93279326
HelpText<"Set default maximum struct packing alignment">,
93289327
Alias<fpack_struct_EQ>;
@@ -9662,6 +9661,18 @@ def dxc_Fc : DXCJoinedOrSeparate<"Fc">,
96629661
HelpText<"Output assembly listing file">;
96639662
def dxc_Frs : DXCJoinedOrSeparate<"Frs">,
96649663
HelpText<"Output additional root signature object file">;
9664+
def dxc_Fd
9665+
: DXCJoinedOrSeparate<"Fd">,
9666+
HelpText<"Write debug information to the given file, or automatically "
9667+
"named file in directory when ending in '/'">;
9668+
def dxc_Qembed_debug
9669+
: DXCFlag<"Qembed_debug">,
9670+
HelpText<"Embed PDB in shader container (must be used with /Zi)">;
9671+
def dxc_Zi : Option<["/", "-"], "Zi", KIND_FLAG>,
9672+
Group<dxc_Group>,
9673+
Alias<g_Flag>,
9674+
Visibility<[CLOption, DXCOption]>,
9675+
HelpText<"Enable debug information">;
96659676
def dxc_Zss : DXCFlag<"Zss">,
96669677
HelpText<"Compute Shader Hash considering source information">;
96679678
def dxc_Zsb : DXCFlag<"Zsb">,
@@ -9765,11 +9776,9 @@ def spirv_validator_path_EQ : Joined<["--"], "spirv-val-path=">, Group<dxc_Group
97659776
HelpText<"SPIRV validator installation path">;
97669777
def dxc_disable_validation : DXCFlag<"Vd">,
97679778
HelpText<"Disable validation">;
9768-
def dxc_gis : DXCFlag<"Gis">,
9769-
HelpText<"Enable IEEE strict mode (equivalent to -ffp-model=strict)">;
9770-
def : Option<["/", "-"], "Qembed_debug", KIND_FLAG>, Group<dxc_Group>,
9771-
Flags<[Ignored]>, Visibility<[DXCOption]>,
9772-
HelpText<"Embed PDB in shader container (ignored)">;
9779+
def dxc_gis
9780+
: DXCFlag<"Gis">,
9781+
HelpText<"Enable IEEE strict mode (equivalent to -ffp-model=strict)">;
97739782
def spirv : DXCFlag<"spirv">,
97749783
HelpText<"Generate SPIR-V code">;
97759784
def metal : DXCFlag<"metal">, HelpText<"Generate Metal library">;

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3851,6 +3851,25 @@ static void RenderHLSLOptions(const Driver &D, const ArgList &Args,
38513851
CmdArgs.push_back("-mllvm");
38523852
CmdArgs.push_back("--dx-source-in-debug-module");
38533853
}
3854+
bool Zi = Args.hasArg(options::OPT_g_Flag);
3855+
bool Qembed_debug = Args.hasArg(options::OPT_dxc_Qembed_debug);
3856+
Arg *Fd = Args.getLastArg(options::OPT_dxc_Fd);
3857+
if (Zi && !Fd && !Qembed_debug) {
3858+
D.Diag(diag::warn_drv_dxc_no_output_for_debug);
3859+
Qembed_debug = true;
3860+
}
3861+
if (Qembed_debug && !Zi)
3862+
D.Diag(diag::err_drv_no_debug_info_for_embed_debug);
3863+
if (Fd && !Zi)
3864+
D.Diag(diag::err_drv_no_debug_info_for_Fd);
3865+
if (Qembed_debug) {
3866+
CmdArgs.push_back("-mllvm");
3867+
CmdArgs.push_back("--dx-embed-debug");
3868+
}
3869+
if (Fd) {
3870+
CmdArgs.push_back("-mllvm");
3871+
CmdArgs.push_back(Args.MakeArgString("--dx-Fd=" + Twine(Fd->getValue())));
3872+
}
38543873
}
38553874

38563875
static void RenderOpenACCOptions(const Driver &D, const ArgList &Args,

clang/test/Driver/dxc_debug.hlsl

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
// RUN: %clang_dxc -Tlib_6_7 -### -g %s 2>&1 | FileCheck %s --check-prefix=CHECK,CHECK-CMD
22
// RUN: %clang_dxc -Tlib_6_7 -### /Zi %s 2>&1 | FileCheck %s
3-
// RUN: %clang_dxc -Tlib_6_7 -### /Zi /Qembed_debug %s 2>&1 | FileCheck %s
3+
// RUN: %clang_dxc -Tlib_6_7 -### /Zi /Qembed_debug %s 2>&1 | FileCheck %s -check-prefixes=CHECK,CHECK-EMBED
44
// RUN: %clang_dxc -Tlib_6_7 -### -Zi %s 2>&1 | FileCheck %s
5-
// RUN: %clang_dxc -Tlib_6_7 -### -Zi -Qembed_debug %s 2>&1 | FileCheck %s
5+
// RUN: %clang_dxc -Tlib_6_7 -### -Zi -Qembed_debug %s 2>&1 | FileCheck %s -check-prefixes=CHECK,CHECK-EMBED
6+
// RUN: %clang_dxc -Tlib_6_7 -### -Zi /Fd %t.pdb %s 2>&1 | FileCheck %s -check-prefixes=CHECK,CHECK-FD
7+
// RUN: %clang_dxc -Tlib_6_7 -### -Zi -Fd=%t.pdb %s 2>&1 | FileCheck %s -check-prefixes=CHECK,CHECK-FD
68
// RUN: %clang_dxc -Tlib_6_7 -### -Zi -gcodeview %s 2>&1 | FileCheck %s -check-prefixes=CHECK,CHECK-CV
79
// RUN: %clang_dxc -Tlib_6_7 -### -Zi -gdwarf %s 2>&1 | FileCheck %s -check-prefixes=CHECK,CHECK-DWARF
810
// RUN: %clang_dxc -Tlib_6_7 -### -gcodeview -Zi %s 2>&1 | FileCheck %s -check-prefixes=CHECK,CHECK-CV
@@ -13,6 +15,17 @@
1315
// CHECK-SAME: "-debug-info-kind=constructor"
1416
// Make sure dwarf-version is 4.
1517
// CHECK-DWARF-SAME: -dwarf-version=4
18+
// Check that -Qembed_debug and -Fd flags are converted to llc equivalents
19+
// CHECK-EMBED-SAME: --dx-embed-debug
20+
// CHECK-FD-SAME: --dx-Fd=
1621
// Make sure dxc command line arguments are passed to clang invocation.
1722
// CHECK-SAME: -fdx-record-command-line
1823
// CHECK-CMD-SAME: --driver-mode=dxc -T lib_6_7 -### -g {{.*}}dxc_debug.hlsl
24+
25+
// Check errors and warnings
26+
// RUN: %clang_dxc -Tlib_6_7 -### /Zi %s 2>&1 | FileCheck %s --check-prefix=WARN-EMBED
27+
// WARN-EMBED: warning: no output provided for debug - embedding PDB in shader container
28+
// RUN: not %clang_dxc -Tlib_6_7 -### /Qembed_debug %s 2>&1 | FileCheck %s --check-prefix=ERROR-NODBG0
29+
// ERROR-NODBG0: error: must enable debug info with /Zi for /Qembed_debug
30+
// RUN: not %clang_dxc -Tlib_6_7 -### /Fd %t.pdb %s 2>&1 | FileCheck %s --check-prefix=ERROR-NODBG1
31+
// ERROR-NODBG1: error: /Fd specified, but no Debug Info was found in the shader

llvm/include/llvm/MC/MCDXContainerWriter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ class LLVM_ABI DXContainerObjectWriter final : public MCDXContainerBaseWriter,
7373

7474
protected:
7575
ArrayRef<MCDXContainerPart> getParts() override;
76+
bool shouldSkipSection(StringRef SectionName, size_t SectionSize) override;
7677

7778
public:
7879
DXContainerObjectWriter(std::unique_ptr<MCDXContainerTargetWriter> MOTW,

llvm/lib/MC/MCDXContainerWriter.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,13 @@
1313
#include "llvm/MC/MCSection.h"
1414
#include "llvm/MC/MCValue.h"
1515
#include "llvm/Support/Alignment.h"
16+
#include "llvm/Support/CommandLine.h"
1617

1718
using namespace llvm;
1819

20+
cl::opt<bool> EmbedDebug("dx-embed-debug",
21+
cl::desc("Embed PDB in shader container"));
22+
1923
MCDXContainerTargetWriter::~MCDXContainerTargetWriter() = default;
2024

2125
MCDXContainerBaseWriter::~MCDXContainerBaseWriter() = default;
@@ -132,6 +136,16 @@ ArrayRef<MCDXContainerPart> DXContainerObjectWriter::getParts() {
132136
return Parts;
133137
}
134138

139+
bool DXContainerObjectWriter::shouldSkipSection(StringRef SectionName,
140+
size_t SectionSize) {
141+
// Do not write ILDB part if we're not embedding it.
142+
if (!EmbedDebug && SectionName == "ILDB")
143+
return true;
144+
if (SectionName == "SRCI")
145+
return true;
146+
return MCDXContainerBaseWriter::shouldSkipSection(SectionName, SectionSize);
147+
}
148+
135149
uint64_t DXContainerObjectWriter::writeObject() {
136150
write(W.OS, getContext().getTargetTriple());
137151
clearParts();

llvm/lib/Target/DirectX/DXContainerGlobals.cpp

Lines changed: 30 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,11 @@ using namespace llvm;
3939
using namespace llvm::dxil;
4040
using namespace llvm::mcdxbc;
4141

42-
static cl::opt<std::string>
43-
PdbFileName("dx-pdb-file",
44-
cl::desc("Specify the PDB output file path for DirectX target"),
45-
cl::value_desc("filename"));
46-
static cl::opt<std::string> PdbOutputDir(
47-
"dx-pdb-dir",
48-
cl::desc("Specify the PDB output directory for DirectX target. The file "
49-
"name is derived from the shader hash"),
50-
cl::value_desc("directory"));
42+
cl::opt<std::string> PdbDebugPath(
43+
"dx-Fd",
44+
cl::desc("Write debug information to the given file, or automatically "
45+
"named file in directory when ending in '/'"),
46+
cl::value_desc("filename"));
5147
static cl::opt<bool> ShaderHashDependsOnSource(
5248
"dx-Zss", cl::desc("Compute Shader Hash considering source information"));
5349
extern cl::opt<bool> SourceInDebugModule;
@@ -151,9 +147,9 @@ void DXContainerGlobals::computeShaderHashAndDebugName(
151147
}
152148

153149
Digest.update(DXILConstant->getRawDataValues());
154-
MD5::MD5Result Result = Digest.final();
150+
MD5::MD5Result MD5 = Digest.final();
155151

156-
memcpy(reinterpret_cast<void *>(&HashData.Digest), Result.data(), 16);
152+
memcpy(reinterpret_cast<void *>(&HashData.Digest), MD5.data(), 16);
157153
if (sys::IsBigEndianHost)
158154
HashData.swapBytes();
159155
StringRef Data(reinterpret_cast<char *>(&HashData), sizeof(dxbc::ShaderHash));
@@ -163,47 +159,41 @@ void DXContainerGlobals::computeShaderHashAndDebugName(
163159
Globals.emplace_back(
164160
buildContainerGlobal(M, ModuleConstant, "dx.hash", "HASH"));
165161

166-
// Emit ILDN part in debug info mode.
167-
// DXIL bitcode hash is used, which corresponds to DXC behavior with
168-
// `/Zi /Qembed_debug /Zsb` flags.
169162
if (M.debug_compile_units().empty())
170163
return;
171164

172-
if (!PdbFileName.empty() && !PdbOutputDir.empty())
173-
report_fatal_error(
174-
"--dx-pdb-file and --dx-pdb-dir are mutually exclusive options");
175-
176165
SmallString<40> DebugNameStr;
177-
Digest.stringifyResult(Result, DebugNameStr);
166+
Digest.stringifyResult(MD5, DebugNameStr);
178167
DebugNameStr += ".pdb";
168+
if (!PdbDebugPath.empty()) {
169+
StringRef DebugFile = PdbDebugPath.getValue();
170+
SmallString<256> AbsoluteDebugName;
171+
if (sys::path::is_separator(DebugFile.back())) {
172+
// If /Fd was specified as a directory, put the MD5.pdb file there.
173+
AbsoluteDebugName = DebugFile;
174+
sys::path::append(AbsoluteDebugName, DebugNameStr);
175+
} else {
176+
// Otherwise, use /Fd value as a user-provided PDB file name.
177+
DebugNameStr = DebugFile;
178+
AbsoluteDebugName = DebugNameStr;
179+
}
179180

180-
mcdxbc::DebugName DebugName;
181-
if (PdbFileName.empty()) {
182-
// Use the MD5 hash as the file name.
183-
Digest.stringifyResult(Result, DebugNameStr);
184-
DebugNameStr += ".pdb";
185-
} else {
186-
// Use user-provided PDB file name.
187-
DebugNameStr = PdbFileName;
181+
// Pass PDB name to DXContainerPDBPass via PDBNAME section.
182+
addSection(M, Globals, AbsoluteDebugName, "dx.pdb.name",
183+
PdbFileNameSectionName);
184+
// Pass module hash to DXContainerPDBPass.
185+
Globals.emplace_back(buildContainerGlobal(
186+
M, ConstantDataArray::get(M.getContext(), ArrayRef(HashData.Digest)),
187+
"dx.pdb.hash", ModuleHashSectionName));
188188
}
189-
DebugName.setFilename(DebugNameStr);
190-
191-
SmallString<256> AbsoluteDebugName(PdbOutputDir);
192-
sys::path::append(AbsoluteDebugName, DebugNameStr);
193189

190+
// Emit ILDN part in debug info mode.
191+
mcdxbc::DebugName DebugName;
192+
DebugName.setFilename(DebugNameStr);
194193
SmallString<64> ILDNData;
195194
raw_svector_ostream OS(ILDNData);
196195
DebugName.write(OS);
197196
addSection(M, Globals, ILDNData, "dx.ildn", "ILDN");
198-
199-
// TODO: Do not create PDB in embedded mode.
200-
// Pass PDB name to DXContainerPDBPass via PDBNAME section.
201-
addSection(M, Globals, AbsoluteDebugName, "dx.pdb.name",
202-
PdbFileNameSectionName);
203-
// Pass module hash to DXContainerPDBPass.
204-
Globals.emplace_back(buildContainerGlobal(
205-
M, ConstantDataArray::get(M.getContext(), ArrayRef(HashData.Digest)),
206-
"dx.pdb.hash", ModuleHashSectionName));
207197
}
208198

209199
GlobalVariable *DXContainerGlobals::buildContainerGlobal(

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
using namespace llvm;
3737
using namespace llvm::dxil;
3838

39+
extern cl::opt<bool> EmbedDebug;
40+
extern cl::opt<std::string> PdbDebugPath;
3941
// NOLINTNEXTLINE(misc-use-internal-linkage)
4042
cl::opt<bool> SourceInDebugModule(
4143
"dx-source-in-debug-module",
@@ -236,6 +238,18 @@ class EmbedDXILPass : public llvm::ModulePass {
236238
legalizeLifetimeIntrinsics(M);
237239

238240
bool HasDebugInfo = !M.debug_compile_units().empty();
241+
242+
// Enable EmbedDebug if there is debug info, but it is not being written
243+
// to a PDB file.
244+
if (HasDebugInfo && !EmbedDebug && PdbDebugPath.empty())
245+
EmbedDebug = true;
246+
if (!HasDebugInfo && EmbedDebug)
247+
reportFatalUsageError(
248+
"Missing debug info for embedding into the container");
249+
// TODO: move this check to DXContainerPDB.cpp when /Zs is implemented.
250+
if (!HasDebugInfo && !PdbDebugPath.empty())
251+
reportFatalUsageError("Missing debug info for writing to the PDB file");
252+
239253
std::string ILDBData;
240254
if (HasDebugInfo) {
241255
// Write DXIL with debug info to ILDB part.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
;; Check that --dx-embed-debug is enabled by default when debug info is present
2+
; RUN: llc %S/Inputs/SourceInfo.ll --filetype=obj -o %t.cso
3+
; RUN: obj2yaml %t.cso | FileCheck %s --check-prefix=DEFAULT-EMBED
4+
; DEFAULT-EMBED: Parts:
5+
; DEFAULT-EMBED: - Name: ILDB
6+
; DEFAULT-EMBED: - Name: ILDN
7+
8+
;; Check that debug info is not embedded if only the PDB ouput is specified
9+
; RUN: llc %S/Inputs/SourceInfo.ll --filetype=obj --dx-Fd=%t.pdb -o %t.cso
10+
; RUN: obj2yaml %t.cso | FileCheck %s --check-prefix=NO-EMBED
11+
; NO-EMBED: Parts:
12+
; NO-EMBED-NOT: - Name: ILDB
13+
; NO-EMBED: - Name: ILDN
14+
15+
;; Check that debug info is both embedded and output to the PDB
16+
;; if both options are specified
17+
; RUN: llc %S/Inputs/SourceInfo.ll --filetype=obj --dx-embed-debug --dx-Fd=%t.pdb -o %t.cso
18+
; RUN: obj2yaml %t.cso | FileCheck %s --check-prefix=EMBED
19+
; EMBED: Parts:
20+
; EMBED: - Name: ILDB
21+
; EMBED: - Name: ILDN
22+
; RUN: llvm-pdbutil dump --dxcontainer %t.pdb | FileCheck %s --check-prefix=PDB
23+
; Check that PDB file contains only debug-info relevant parts.
24+
; PDB: Parts:
25+
; PDB: ILDB
26+
; PDB: ILDN
27+
28+
;; Check errors when trying to output debug info with no debug info present
29+
; RUN: not llc %s --filetype=obj --dx-embed-debug -o %t.cso 2>&1 | FileCheck %s --check-prefix=ERROR-NODBG
30+
; ERROR-NODBG: Missing debug info for embedding into the container
31+
; RUN: not llc %s --filetype=obj --dx-Fd=%t.pdb -o %t.cso 2>&1 | FileCheck %s --check-prefix=ERROR-NODBG-PDB
32+
; ERROR-NODBG-PDB: Missing debug info for writing to the PDB file
33+
34+
target triple = "dxil-unknown-shadermodel6.5-library"
35+
36+
define i32 @foo(i32 %a) {
37+
ret i32 %a
38+
}

llvm/test/CodeGen/DirectX/ContainerData/DebugName-default-output.test

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
RUN: llc %S/Inputs/SourceInfo.ll -dx-Zss --filetype=obj -o %t.dxbc
1+
RUN: llc %S/Inputs/SourceInfo.ll -dx-Zss --dx-embed-debug --filetype=obj -o %t.dxbc
22
RUN: llvm-objcopy --dump-section=ILDB=%t0.bc %t.dxbc
33
RUN: %md5sum %t0.bc >%t0.bc.md5
44
RUN: obj2yaml %t.dxbc >%t.yaml
55
RUN: cat %t.yaml %t0.bc.md5 | FileCheck %s
6-
RUN: %python %S/Inputs/check_pdb_exists.py "" "%t0.bc.md5"
76

87
CHECK-NOT: - Name: PDBN
98
CHECK-NOT: - Name: PDBH

0 commit comments

Comments
 (0)