Skip to content

Commit 50e1db7

Browse files
[HLSL][SPIRV] Add CLI option -fspv-extension (#137985)
This commit implements DXC's `-fspv-extension` options. It is implemented by replaced it with the equivalent `-spirv-ext` option. Note that if the option is not used, that is the same as enabling all extension, so `-spirv-ext=all` is used. Fixes #137647 --------- Co-authored-by: Cassandra Beckley <cbeckley@google.com>
1 parent 123758b commit 50e1db7

File tree

3 files changed

+75
-0
lines changed

3 files changed

+75
-0
lines changed

clang/include/clang/Driver/Options.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9221,6 +9221,11 @@ def metal : DXCFlag<"metal">, HelpText<"Generate Metal library">;
92219221
def fspv_target_env_EQ : Joined<["-"], "fspv-target-env=">, Group<dxc_Group>,
92229222
HelpText<"Specify the target environment">,
92239223
Values<"vulkan1.2, vulkan1.3">;
9224+
def fspv_extension_EQ
9225+
: Joined<["-"], "fspv-extension=">,
9226+
Group<dxc_Group>,
9227+
HelpText<"Specify the available SPIR-V extensions. If this option is not "
9228+
"specified, then all extensions are available.">;
92249229
def no_wasm_opt : Flag<["--"], "no-wasm-opt">,
92259230
Group<m_Group>,
92269231
HelpText<"Disable the wasm-opt optimizer">,

clang/lib/Driver/ToolChains/HLSL.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "clang/Driver/Job.h"
1414
#include "llvm/ADT/StringSwitch.h"
1515
#include "llvm/TargetParser/Triple.h"
16+
#include <regex>
1617

1718
using namespace clang::driver;
1819
using namespace clang::driver::tools;
@@ -173,6 +174,39 @@ bool isLegalValidatorVersion(StringRef ValVersionStr, const Driver &D) {
173174
return true;
174175
}
175176

177+
std::string getSpirvExtArg(ArrayRef<std::string> SpvExtensionArgs) {
178+
if (SpvExtensionArgs.empty()) {
179+
return "-spirv-ext=all";
180+
}
181+
182+
std::string LlvmOption =
183+
(Twine("-spirv-ext=+") + SpvExtensionArgs.front()).str();
184+
SpvExtensionArgs = SpvExtensionArgs.slice(1);
185+
for (auto Extension : SpvExtensionArgs) {
186+
LlvmOption = (Twine(LlvmOption) + ",+" + Extension).str();
187+
}
188+
return LlvmOption;
189+
}
190+
191+
bool isValidSPIRVExtensionName(const std::string &str) {
192+
std::regex pattern("SPV_[a-zA-Z0-9_]+");
193+
return std::regex_match(str, pattern);
194+
}
195+
196+
// SPIRV extension names are of the form `SPV_[a-zA-Z0-9_]+`. We want to
197+
// disallow obviously invalid names to avoid issues when parsing `spirv-ext`.
198+
bool checkExtensionArgsAreValid(ArrayRef<std::string> SpvExtensionArgs,
199+
const Driver &Driver) {
200+
bool AllValid = true;
201+
for (auto Extension : SpvExtensionArgs) {
202+
if (!isValidSPIRVExtensionName(Extension)) {
203+
Driver.Diag(diag::err_drv_invalid_value)
204+
<< "-fspv_extension" << Extension;
205+
AllValid = false;
206+
}
207+
}
208+
return AllValid;
209+
}
176210
} // namespace
177211

178212
void tools::hlsl::Validator::ConstructJob(Compilation &C, const JobAction &JA,
@@ -301,6 +335,17 @@ HLSLToolChain::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
301335
DAL->append(A);
302336
}
303337

338+
if (getArch() == llvm::Triple::spirv) {
339+
std::vector<std::string> SpvExtensionArgs =
340+
Args.getAllArgValues(options::OPT_fspv_extension_EQ);
341+
if (checkExtensionArgsAreValid(SpvExtensionArgs, getDriver())) {
342+
std::string LlvmOption = getSpirvExtArg(SpvExtensionArgs);
343+
DAL->AddSeparateArg(nullptr, Opts.getOption(options::OPT_mllvm),
344+
LlvmOption);
345+
}
346+
Args.claimAllArgs(options::OPT_fspv_extension_EQ);
347+
}
348+
304349
if (!DAL->hasArg(options::OPT_O_Group)) {
305350
DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_O), "3");
306351
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// If there is no `-fspv-extension`, enable all extensions.
2+
// RUN: %clang_dxc -spirv -Tlib_6_7 -### %s 2>&1 | FileCheck %s -check-prefix=ALL
3+
// ALL: "-spirv-ext=all"
4+
5+
// Convert the `-fspv-extension` into `spirv-ext`.
6+
// RUN: %clang_dxc -spirv -Tlib_6_7 -### %s -fspv-extension=SPV_TEST1 2>&1 | FileCheck %s -check-prefix=TEST1
7+
// TEST1: "-spirv-ext=+SPV_TEST1"
8+
9+
// Merge multiple extensions into a single `spirv-ext` option.
10+
// RUN: %clang_dxc -spirv -Tlib_6_7 -### %s -fspv-extension=SPV_TEST1 -fspv-extension=SPV_TEST2 2>&1 | FileCheck %s -check-prefix=TEST2
11+
// TEST2: "-spirv-ext=+SPV_TEST1,+SPV_TEST2"
12+
13+
// Check for the error message if the extension name is not properly formed.
14+
// RUN: not %clang_dxc -spirv -Tlib_6_7 -### %s -fspv-extension=TEST1 -fspv-extension=SPV_GOOD -fspv-extension=TEST2 2>&1 | FileCheck %s -check-prefix=FAIL
15+
// FAIL: invalid value 'TEST1' in '-fspv_extension'
16+
// FAIL: invalid value 'TEST2' in '-fspv_extension'
17+
18+
// If targeting DXIL, the `-spirv-ext` should not be passed to the backend.
19+
// RUN: %clang_dxc -Tlib_6_7 -### %s 2>&1 | FileCheck %s -check-prefix=DXIL
20+
// DXIL-NOT: spirv-ext
21+
22+
// If targeting DXIL, the `-fspv-extension` option is meaningless, and there should be a warning.
23+
// RUN: %clang_dxc -Tlib_6_7 -### %s -fspv-extension=SPV_TEST 2>&1 | FileCheck %s -check-prefix=WARN
24+
// WARN: warning: argument unused during compilation: '-fspv-extension=SPV_TEST'
25+
// WARN-NOT: spirv-ext

0 commit comments

Comments
 (0)