[clang] [Clang][HLSL][DebugInfo] Emit dx.source metadata nodes (PR #199689)
via cfe-commits
cfe-commits at lists.llvm.org
Tue May 26 07:15:27 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-hlsl
Author: Vladislav Dzhidzhoev (dzhidzhoev)
<details>
<summary>Changes</summary>
Add HLSL debug metadata emission for DXIL by embedding non-system source files (including included headers) into dx.source.contents, recording the main file name and user defines, and serializing the dxc-style command line into dx.source.args.
This metadata nodes are needed for emitting SRCI part of a debug DXContainer in llc.
Introduce -fdx-record-command-line option to cc1 to carry the escaped driver command line into cc1.
Introduce -fdx-no-source-metadata CodeGen option to cc1, to be able to disable dx.source metadata nodes emission. This comes in handy for writing debug info tests, so that CHECK-NOT lines do not match themselves in LLVM IR. For example, without this option, in `clang/test/CodeGenHLSL/debug/source-language.hlsl`, CHECK-V4-NOT line gets a match on the line with dx.source.contents node.
---
Patch is 27.25 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/199689.diff
23 Files Affected:
- (modified) clang/include/clang/Basic/CodeGenOptions.def (+3)
- (modified) clang/include/clang/Basic/CodeGenOptions.h (+4)
- (modified) clang/include/clang/Driver/CommonArgs.h (+2-2)
- (modified) clang/include/clang/Options/OptionUtils.h (+4)
- (modified) clang/include/clang/Options/Options.td (+13)
- (modified) clang/lib/CodeGen/CGHLSLRuntime.cpp (+111)
- (modified) clang/lib/CodeGen/CMakeLists.txt (+1)
- (modified) clang/lib/Driver/ToolChains/Clang.cpp (+7-1)
- (modified) clang/lib/Driver/ToolChains/CommonArgs.cpp (+5-2)
- (modified) clang/lib/Driver/ToolChains/Flang.cpp (+3-1)
- (modified) clang/lib/Options/OptionUtils.cpp (+32)
- (added) clang/test/CodeGenHLSL/Inputs/a.hlsl (+10)
- (added) clang/test/CodeGenHLSL/Inputs/b.hlsl (+3)
- (added) clang/test/CodeGenHLSL/SysInputs/c.hlsl (+3)
- (modified) clang/test/CodeGenHLSL/debug/source-language.hlsl (+4)
- (added) clang/test/CodeGenHLSL/dx-source-metadata-disabled.hlsl (+12)
- (added) clang/test/CodeGenHLSL/dx-source-metadata-includes.hlsl (+21)
- (added) clang/test/CodeGenHLSL/dx-source-metadata-mailformed-command-line.hlsl (+10)
- (added) clang/test/CodeGenHLSL/dx-source-metadata.hlsl (+28)
- (modified) clang/test/CodeGenHLSL/lit.local.cfg (+1)
- (modified) clang/test/Driver/dxc_debug.hlsl (+4-1)
- (modified) clang/unittests/Driver/CMakeLists.txt (+2)
- (added) clang/unittests/Driver/EscapedCommandLineTest.cpp (+135)
``````````diff
diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def
index aa36de6edecbf..b121e7cb46601 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -520,6 +520,9 @@ CODEGENOPT(ResMayAlias, 1, 0, Benign)
/// Assume that all resources are bound if enabled
CODEGENOPT(AllResourcesBound, 1, 0, Benign)
+/// Do not embed dx.source.* metadata in HLSL modules.
+CODEGENOPT(DisableDXSourceMetadata, 1, 0, Benign)
+
/// Controls how unwind v2 (epilog) information should be generated for x64
/// Windows.
ENUM_CODEGENOPT(WinX64EHUnwindV2, WinX64EHUnwindV2Mode,
diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h
index e43112b4bb98b..33991827eb061 100644
--- a/clang/include/clang/Basic/CodeGenOptions.h
+++ b/clang/include/clang/Basic/CodeGenOptions.h
@@ -268,6 +268,10 @@ class CodeGenOptions : public CodeGenOptionsBase {
/// if non-empty.
std::string RecordCommandLine;
+ /// The string containing the commandline for the dx.source.args metadata,
+ /// if non-empty.
+ std::string HLSLRecordCommandLine;
+
llvm::SmallVector<std::pair<std::string, std::string>, 0> DebugPrefixMap;
/// Prefix replacement map for source-based code coverage to remap source
diff --git a/clang/include/clang/Driver/CommonArgs.h b/clang/include/clang/Driver/CommonArgs.h
index 0af1b89425227..51ae3b13b5550 100644
--- a/clang/include/clang/Driver/CommonArgs.h
+++ b/clang/include/clang/Driver/CommonArgs.h
@@ -275,8 +275,8 @@ const char *renderEscapedCommandLine(const ToolChain &TC,
/// line options that were passed.
bool shouldRecordCommandLine(const ToolChain &TC,
const llvm::opt::ArgList &Args,
- bool &FRecordCommandLine,
- bool &GRecordCommandLine);
+ bool &FRecordCommandLine, bool &GRecordCommandLine,
+ bool &DXRecordCommandLine);
void renderGlobalISelOptions(const Driver &D, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs,
diff --git a/clang/include/clang/Options/OptionUtils.h b/clang/include/clang/Options/OptionUtils.h
index 02c9c27554db1..4305cdd134bf4 100644
--- a/clang/include/clang/Options/OptionUtils.h
+++ b/clang/include/clang/Options/OptionUtils.h
@@ -77,6 +77,10 @@ std::string GetResourcesPath(StringRef BinaryPath);
/// executable), for finding the builtin compiler path.
std::string GetResourcesPath(const char *Argv0, void *MainAddr);
+/// Parse a space-separated command line with escaped spaces and backslashes.
+llvm::Expected<llvm::SmallVector<llvm::SmallString<8>>>
+parseEscapedCommandLine(const char *CommandLine);
+
} // namespace clang
#endif // LLVM_CLANG_OPTIONS_OPTIONUTILS_H
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index 753e3ac1b74a5..f448a986038cb 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -9670,6 +9670,19 @@ def dxc_rootsig_define :
Alias<fdx_rootsignature_define>,
Group<dxc_Group>,
Visibility<[DXCOption]>;
+def dxc_record_command_line
+ : Separate<["-"], "fdx-record-command-line">,
+ Group<dxc_Group>,
+ Visibility<[CC1Option]>,
+ MarshallingInfoString<CodeGenOpts<"HLSLRecordCommandLine">>,
+ HelpText<
+ "Command line arguments to embed in the dx.source.args metadata">;
+def dxc_no_source_metadata
+ : Flag<["-"], "fdx-no-source-metadata">,
+ Group<dxc_Group>,
+ Visibility<[CC1Option]>,
+ MarshallingInfoFlag<CodeGenOpts<"DisableDXSourceMetadata">>,
+ HelpText<"Do not embed source info metadata in HLSL modules">;
def hlsl_entrypoint : Option<["-"], "hlsl-entry", KIND_SEPARATE>,
Group<dxc_Group>,
Visibility<[ClangOption, CC1Option]>,
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index 98d65715d45b9..a21b96f4acb7c 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -27,8 +27,11 @@
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/Type.h"
#include "clang/Basic/DiagnosticFrontend.h"
+#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetOptions.h"
+#include "clang/Options/OptionUtils.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
@@ -45,6 +48,7 @@
#include "llvm/Support/Alignment.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/Path.h"
#include <cstdint>
#include <optional>
@@ -189,6 +193,109 @@ findAssociatedResourceDeclForStruct(ASTContext &AST, const MemberExpr *ME) {
return nullptr;
}
+void addSourceInfo(CodeGenModule &CGM, llvm::Module &M) {
+ auto &SM = CGM.getContext().getSourceManager();
+ auto &Macros = CGM.getPreprocessorOpts().Macros;
+ auto &Ctx = M.getContext();
+
+ // Names and content of shader source code files.
+ llvm::NamedMDNode *DXContents =
+ M.getOrInsertNamedMetadata("dx.source.contents");
+ auto addFile = [&](const std::pair<StringRef, StringRef> &NameContent) {
+ llvm::MDTuple *FileInfo =
+ llvm::MDNode::get(Ctx, {llvm::MDString::get(Ctx, NameContent.first),
+ llvm::MDString::get(Ctx, NameContent.second)});
+ DXContents->addOperand(FileInfo);
+ };
+
+ bool Invalid = false;
+ const SrcMgr::SLocEntry *MainLocEntry =
+ &SM.getSLocEntry(SM.getMainFileID(), &Invalid);
+ assert(!Invalid && "Main file SLocEntry must not be invalid!");
+ const SrcMgr::ContentCache &MainCCEntry =
+ MainLocEntry->getFile().getContentCache();
+
+ SmallVector<std::pair<std::string, StringRef>> Files;
+ std::optional<SmallString<256>> MainFileName;
+ Files.reserve(SM.local_sloc_entry_size());
+ for (unsigned I : llvm::seq(SM.local_sloc_entry_size())) {
+ const SrcMgr::SLocEntry &LocEntry = SM.getLocalSLocEntry(I);
+ if (!LocEntry.isFile())
+ continue;
+
+ const SrcMgr::FileInfo &FInfo = LocEntry.getFile();
+ if (isSystem(FInfo.getFileCharacteristic()))
+ continue;
+
+ const SrcMgr::ContentCache &CCEntry = FInfo.getContentCache();
+ OptionalFileEntryRef FEntry = CCEntry.OrigEntry;
+ if (!FEntry)
+ continue;
+
+ llvm::SmallString<256> Path = FEntry->getName();
+ llvm::sys::path::native(Path);
+ std::optional<llvm::MemoryBufferRef> Buffer = CCEntry.getBufferOrNone(
+ SM.getDiagnostics(), SM.getFileManager(), SourceLocation());
+ if (!Buffer) {
+ unsigned ID = SM.getDiagnostics().getCustomDiagID(
+ clang::DiagnosticsEngine::Warning,
+ "failed to embed source for \"%0\" into dx.source.contents");
+ SM.getDiagnostics().Report(ID) << Path;
+ continue;
+ }
+
+ if (&MainCCEntry != &CCEntry) {
+ Files.emplace_back(Path, Buffer->getBuffer());
+ } else {
+ // Main file should be at first position.
+ addFile(std::make_pair(Path, Buffer->getBuffer()));
+ MainFileName.emplace(Path);
+ }
+ }
+ assert(MainFileName && "Main file not found.");
+
+ // Files other that main one should be sorted by name.
+ llvm::sort(Files);
+#ifndef NDEBUG
+ for (unsigned I = 1; I < Files.size(); ++I)
+ assert((Files[I - 1].first != Files[I].first) &&
+ "duplicate files in dx.source.contents");
+#endif
+ llvm::for_each(Files, addFile);
+
+ SmallVector<llvm::Metadata *> Defines;
+ Defines.reserve(Macros.size());
+ for (const auto &Macro : Macros) {
+ // Ignore undefs.
+ if (!Macro.second)
+ Defines.emplace_back(llvm::MDString::get(Ctx, Macro.first));
+ }
+ M.getOrInsertNamedMetadata("dx.source.defines")
+ ->addOperand(llvm::MDNode::get(Ctx, Defines));
+
+ if (!CGM.getCodeGenOpts().MainFileName.empty())
+ llvm::sys::path::native(CGM.getCodeGenOpts().MainFileName, *MainFileName);
+ M.getOrInsertNamedMetadata("dx.source.mainFileName")
+ ->addOperand(
+ llvm::MDNode::get(Ctx, llvm::MDString::get(Ctx, *MainFileName)));
+
+ auto ParsedArgs = clang::parseEscapedCommandLine(
+ CGM.getCodeGenOpts().HLSLRecordCommandLine.c_str());
+ if (!ParsedArgs) {
+ unsigned DiagID = CGM.getDiags().getCustomDiagID(
+ DiagnosticsEngine::Error, "invalid escaped command line: %0");
+ CGM.getDiags().Report(DiagID) << llvm::toString(ParsedArgs.takeError());
+ return;
+ }
+ SmallVector<llvm::Metadata *> Args;
+ Args.reserve(ParsedArgs->size());
+ if (!ParsedArgs->empty())
+ for (const auto &Arg : llvm::drop_begin(*ParsedArgs))
+ Args.push_back(llvm::MDString::get(Ctx, Arg));
+ M.getOrInsertNamedMetadata("dx.source.args")
+ ->addOperand(llvm::MDNode::get(Ctx, Args));
+}
+
// Find array variable declaration from DeclRef expression
static const ValueDecl *getArrayDecl(ASTContext &AST, const Expr *E) {
E = E->IgnoreImpCasts();
@@ -576,6 +683,10 @@ void CGHLSLRuntime::finishCodeGen() {
Triple T(M.getTargetTriple());
if (T.getArch() == Triple::ArchType::dxil)
addDxilValVersion(TargetOpts.DxilValidatorVersion, M);
+ if (!CodeGenOpts.DisableDXSourceMetadata &&
+ CodeGenOpts.getDebugInfo() >=
+ llvm::codegenoptions::DebugInfoKind::DebugInfoConstructor)
+ addSourceInfo(CGM, M);
if (CodeGenOpts.ResMayAlias)
M.setModuleFlag(llvm::Module::ModFlagBehavior::Error, "dx.resmayalias", 1);
if (CodeGenOpts.AllResourcesBound)
diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt
index 117438c616ab5..54498de279f42 100644
--- a/clang/lib/CodeGen/CMakeLists.txt
+++ b/clang/lib/CodeGen/CMakeLists.txt
@@ -173,5 +173,6 @@ add_clang_library(clangCodeGen
clangBasic
clangFrontend
clangLex
+ clangOptions
clangSerialization
)
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 8d8e00bbaf7d0..1372798b45cb9 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -8058,7 +8058,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// By default, -gno-record-gcc-switches is set on and no recording.
auto GRecordSwitches = false;
auto FRecordSwitches = false;
- if (shouldRecordCommandLine(TC, Args, FRecordSwitches, GRecordSwitches)) {
+ bool DXRecordSwitches = false;
+ if (shouldRecordCommandLine(TC, Args, FRecordSwitches, GRecordSwitches,
+ DXRecordSwitches)) {
auto FlagsArgString = renderEscapedCommandLine(TC, Args);
if (TC.UseDwarfDebugFlags() || GRecordSwitches) {
CmdArgs.push_back("-dwarf-debug-flags");
@@ -8068,6 +8070,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-record-command-line");
CmdArgs.push_back(FlagsArgString);
}
+ if (DXRecordSwitches) {
+ CmdArgs.push_back("-fdx-record-command-line");
+ CmdArgs.push_back(FlagsArgString);
+ }
}
// Host-side offloading compilation receives all device-side outputs. Include
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 2ef7c1506e18d..dae0c67ad69c9 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -3338,7 +3338,8 @@ const char *tools::renderEscapedCommandLine(const ToolChain &TC,
bool tools::shouldRecordCommandLine(const ToolChain &TC,
const llvm::opt::ArgList &Args,
bool &FRecordCommandLine,
- bool &GRecordCommandLine) {
+ bool &GRecordCommandLine,
+ bool &DXRecordCommandLine) {
const Driver &D = TC.getDriver();
const llvm::Triple &Triple = TC.getEffectiveTriple();
const std::string &TripleStr = Triple.getTriple();
@@ -3349,13 +3350,15 @@ bool tools::shouldRecordCommandLine(const ToolChain &TC,
GRecordCommandLine =
Args.hasFlag(options::OPT_grecord_command_line,
options::OPT_gno_record_command_line, false);
+ DXRecordCommandLine = Triple.isDXIL() && Args.hasArg(options::OPT_g_Flag);
if (FRecordCommandLine && !Triple.isOSBinFormatELF() &&
!Triple.isOSBinFormatXCOFF() && !Triple.isOSBinFormatMachO())
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< Args.getLastArg(options::OPT_frecord_command_line)->getAsString(Args)
<< TripleStr;
- return FRecordCommandLine || TC.UseDwarfDebugFlags() || GRecordCommandLine;
+ return FRecordCommandLine || TC.UseDwarfDebugFlags() || GRecordCommandLine ||
+ DXRecordCommandLine;
}
void tools::renderGlobalISelOptions(const Driver &D, const ArgList &Args,
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index 4c722a2e021eb..3620961b4c3b1 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -1284,7 +1284,9 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
bool FRecordCmdLine = false;
bool GRecordCmdLine = false;
- if (shouldRecordCommandLine(TC, Args, FRecordCmdLine, GRecordCmdLine)) {
+ bool DXRecordCmdLine = false;
+ if (shouldRecordCommandLine(TC, Args, FRecordCmdLine, GRecordCmdLine,
+ DXRecordCmdLine)) {
const char *CmdLine = renderEscapedCommandLine(TC, Args);
if (FRecordCmdLine) {
CmdArgs.push_back("-record-command-line");
diff --git a/clang/lib/Options/OptionUtils.cpp b/clang/lib/Options/OptionUtils.cpp
index e5aefa012f679..77f89552e852a 100644
--- a/clang/lib/Options/OptionUtils.cpp
+++ b/clang/lib/Options/OptionUtils.cpp
@@ -244,3 +244,35 @@ std::string clang::GetResourcesPath(const char *Argv0, void *MainAddr) {
llvm::sys::fs::getMainExecutable(Argv0, MainAddr);
return GetResourcesPath(ClangExecutable);
}
+
+static bool isSpaceOrNull(char c) { return !c || c == ' '; }
+
+static Expected<const char *> unescapeUntilSpace(const char *Arg,
+ SmallVectorImpl<char> &Res) {
+ for (; !isSpaceOrNull(*Arg); ++Arg) {
+ if (*Arg == '\\') {
+ ++Arg;
+ if (*Arg != '\\' && *Arg != ' ')
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "only escaped backslashes and spaces are supported");
+ }
+ Res.push_back(*Arg);
+ }
+ return Arg;
+}
+
+Expected<SmallVector<SmallString<8>>>
+clang::parseEscapedCommandLine(const char *CommandLine) {
+ SmallVector<SmallString<8>> Res;
+ while (*CommandLine) {
+ Expected<const char *> ArgEnd =
+ unescapeUntilSpace(CommandLine, Res.emplace_back());
+ if (!ArgEnd)
+ return ArgEnd.takeError();
+ CommandLine = *ArgEnd;
+ if (*CommandLine == ' ')
+ ++CommandLine;
+ }
+ return Res;
+}
diff --git a/clang/test/CodeGenHLSL/Inputs/a.hlsl b/clang/test/CodeGenHLSL/Inputs/a.hlsl
new file mode 100644
index 0000000000000..9c132672dea82
--- /dev/null
+++ b/clang/test/CodeGenHLSL/Inputs/a.hlsl
@@ -0,0 +1,10 @@
+#ifndef GUARD
+#define GUARD
+
+#include "b.hlsl"
+
+float helper1_add(float a, float b) {
+ return a + b;
+}
+
+#endif
diff --git a/clang/test/CodeGenHLSL/Inputs/b.hlsl b/clang/test/CodeGenHLSL/Inputs/b.hlsl
new file mode 100644
index 0000000000000..798909fa50569
--- /dev/null
+++ b/clang/test/CodeGenHLSL/Inputs/b.hlsl
@@ -0,0 +1,3 @@
+float helper2_mul(float a, float b) {
+ return a * b;
+}
diff --git a/clang/test/CodeGenHLSL/SysInputs/c.hlsl b/clang/test/CodeGenHLSL/SysInputs/c.hlsl
new file mode 100644
index 0000000000000..30223007e1920
--- /dev/null
+++ b/clang/test/CodeGenHLSL/SysInputs/c.hlsl
@@ -0,0 +1,3 @@
+float sys_helper(float a, float b) {
+ return a * b;
+}
diff --git a/clang/test/CodeGenHLSL/debug/source-language.hlsl b/clang/test/CodeGenHLSL/debug/source-language.hlsl
index f1e63d17724ee..83099b288853f 100644
--- a/clang/test/CodeGenHLSL/debug/source-language.hlsl
+++ b/clang/test/CodeGenHLSL/debug/source-language.hlsl
@@ -5,24 +5,28 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-compute -x hlsl -emit-llvm \
// RUN: -disable-llvm-passes -hlsl-entry main \
// RUN: -debug-info-kind=standalone -dwarf-version=4 -o - %s \
+// RUN: -fdx-no-source-metadata \
// RUN: | FileCheck %s --check-prefix=CHECK-V4
// SPIR-V target, DWARFv4
// RUN: %clang_cc1 -triple spirv-unknown-vulkan-compute -x hlsl -emit-llvm \
// RUN: -disable-llvm-passes -hlsl-entry main \
// RUN: -debug-info-kind=standalone -dwarf-version=4 -o - %s \
+// RUN: -fdx-no-source-metadata \
// RUN: | FileCheck %s --check-prefix=CHECK-V4
// DXIL target, DWARFv6
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-compute -x hlsl -emit-llvm \
// RUN: -disable-llvm-passes -hlsl-entry main \
// RUN: -debug-info-kind=standalone -dwarf-version=6 -o - %s \
+// RUN: -fdx-no-source-metadata \
// RUN: | FileCheck %s --check-prefix=CHECK-V6
// SPIR-V target, DWARFv6
// RUN: %clang_cc1 -triple spirv-unknown-vulkan-compute -x hlsl -emit-llvm \
// RUN: -disable-llvm-passes -hlsl-entry main \
// RUN: -debug-info-kind=standalone -dwarf-version=6 -o - %s \
+// RUN: -fdx-no-source-metadata \
// RUN: | FileCheck %s --check-prefix=CHECK-V6
// CHECK-V4: !DICompileUnit(language: DW_LANG_HLSL,
diff --git a/clang/test/CodeGenHLSL/dx-source-metadata-disabled.hlsl b/clang/test/CodeGenHLSL/dx-source-metadata-disabled.hlsl
new file mode 100644
index 0000000000000..aa26a49feeef6
--- /dev/null
+++ b/clang/test/CodeGenHLSL/dx-source-metadata-disabled.hlsl
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm \
+// RUN: -debug-info-kind=constructor -fdx-no-source-metadata -o - \
+// RUN: -disable-llvm-passes %s | FileCheck %s
+
+// CHECK-NOT: !dx.source.contents
+// CHECK-NOT: !dx.source.defines
+// CHECK-NOT: !dx.source.mainFileName
+// CHECK-NOT: !dx.source.args
+
+float foo(float a, float b) {
+ return a + b;
+}
diff --git a/clang/test/CodeGenHLSL/dx-source-metadata-includes.hlsl b/clang/test/CodeGenHLSL/dx-source-metadata-includes.hlsl
new file mode 100644
index 0000000000000..65861f5a50fdc
--- /dev/null
+++ b/clang/test/CodeGenHLSL/dx-source-metadata-includes.hlsl
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm \
+// RUN: -debug-info-kind=constructor -I %S/Inputs -isystem %S/SysInputs \
+// RUN: -o - %s | FileCheck %s
+
+#include "a.hlsl"
+#include "a.hlsl"
+#include <c.hlsl>
+
+// The main file appears first in dx.source.contents; included files are
+// appended in sorted order afterwards. Duplicate and system includes are ignored.
+
+// CHECK: !dx.source.contents = !{![[MAIN:[0-9]+]], ![[H1:[0-9]+]], ![[H2:[0-9]+]]}
+// CHECK: !dx.source.mainFileName = !{![[MAIN_FILE_NAME:[0-9]+]]}
+// CHECK: ![[MAIN]] = !{!"{{.*[\\/]dx-source-metadata-includes.hlsl}}", !"{{.*}}"}
+// CHECK: ![[H1]] = !{!"{{.*[\\/]a.hlsl}}", !"{{.*}}"}
+// CHECK: ![[H2]] = !{!"{{.*[\\/]b.hlsl}}", !"{{.*}}"}
+// CHECK: ![[MAIN_FILE_NAME]] = !{!"{{.*[\\/]dx-source-metadata-includes.hlsl}}"}
+
+float foo(float a, float b) {
+ return helper1_add(a, b) + helper2_mul(a, b) + sys_helper(a, b);
+}
diff --git a/clang/test/CodeGenHLSL/dx-source-metadata-mailformed-command-line.hlsl b/clang/test/CodeGenHLSL/dx-source-metadata-mailformed-command-line.hlsl
new file mode 100644
index 0000000000000..b6557503ab118
--- /dev/null
+++ b/clang/test/CodeGenHLSL/dx-source-metadata-mailformed-command-line.hlsl
@@ -0,0 +1,10 @@
+// RUN: not %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm \
+// RUN: -debug-info-kind=constructor \
+// RUN: -fdx-record-command-line "clang_dxc \\" \
+// RUN: -o - %s 2>&1 | FileCheck %s
+
+// CHECK: error: invalid escaped command line: only escaped backslashes and spaces are supported
+
+float foo(float a, float b) {
+ return a + b;
+}
diff --git a/clang/test/CodeGenHLSL/dx-source-metadata.hlsl b/clang/test/CodeGenHLSL/dx-source-metadata.hlsl
new file mode 100644
index 0000000000000..c523f36cc69b6
--- /dev/null
+++ b/clang/test/CodeGenHLSL/dx-source-metadata.hlsl
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm \
+// RUN: -debug-info-kind=constructor -DUSER_DEF0=42 -DUSER_DEF1=43 -...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/199689
More information about the cfe-commits
mailing list