13#include "llvm/ADT/StringSwitch.h"
14#include "llvm/TargetParser/Triple.h"
26const unsigned OfflineLibMinor = 0xF;
28bool isLegalShaderModel(Triple &
T) {
29 if (
T.getOS() != Triple::OSType::ShaderModel)
32 auto Version =
T.getOSVersion();
33 if (Version.getBuild())
35 if (Version.getSubminor())
38 auto Kind =
T.getEnvironment();
43 case Triple::EnvironmentType::Vertex:
44 case Triple::EnvironmentType::Hull:
45 case Triple::EnvironmentType::Domain:
46 case Triple::EnvironmentType::Geometry:
47 case Triple::EnvironmentType::Pixel:
48 case Triple::EnvironmentType::Compute: {
49 VersionTuple MinVer(4, 0);
50 return MinVer <= Version;
52 case Triple::EnvironmentType::Library: {
53 VersionTuple SM6x(6, OfflineLibMinor);
57 VersionTuple MinVer(6, 3);
58 return MinVer <= Version;
60 case Triple::EnvironmentType::Amplification:
61 case Triple::EnvironmentType::Mesh: {
62 VersionTuple MinVer(6, 5);
63 return MinVer <= Version;
69std::optional<std::string> tryParseProfile(StringRef Profile) {
72 Profile.split(Parts,
"_");
73 if (Parts.size() != 3)
76 Triple::EnvironmentType
Kind =
77 StringSwitch<Triple::EnvironmentType>(Parts[0])
78 .Case(
"ps", Triple::EnvironmentType::Pixel)
79 .Case(
"vs", Triple::EnvironmentType::Vertex)
80 .Case(
"gs", Triple::EnvironmentType::Geometry)
81 .Case(
"hs", Triple::EnvironmentType::Hull)
82 .Case(
"ds", Triple::EnvironmentType::Domain)
83 .Case(
"cs", Triple::EnvironmentType::Compute)
84 .Case(
"lib", Triple::EnvironmentType::Library)
85 .Case(
"ms", Triple::EnvironmentType::Mesh)
86 .Case(
"as", Triple::EnvironmentType::Amplification)
87 .Default(Triple::EnvironmentType::UnknownEnvironment);
88 if (Kind == Triple::EnvironmentType::UnknownEnvironment)
91 unsigned long long Major = 0;
92 if (llvm::getAsUnsignedInteger(Parts[1], 0, Major))
95 unsigned long long Minor = 0;
96 if (Parts[2] ==
"x" && Kind == Triple::EnvironmentType::Library)
97 Minor = OfflineLibMinor;
98 else if (llvm::getAsUnsignedInteger(Parts[2], 0, Minor))
106 Triple::SubArchType SubArch = llvm::Triple::NoSubArch;
109 SubArch = llvm::Triple::DXILSubArch_v1_0;
112 SubArch = llvm::Triple::DXILSubArch_v1_1;
115 SubArch = llvm::Triple::DXILSubArch_v1_2;
118 SubArch = llvm::Triple::DXILSubArch_v1_3;
121 SubArch = llvm::Triple::DXILSubArch_v1_4;
124 SubArch = llvm::Triple::DXILSubArch_v1_5;
127 SubArch = llvm::Triple::DXILSubArch_v1_6;
130 SubArch = llvm::Triple::DXILSubArch_v1_7;
133 SubArch = llvm::Triple::DXILSubArch_v1_8;
135 case OfflineLibMinor:
137 SubArch = llvm::Triple::LatestDXILSubArch;
143 T.setArch(Triple::ArchType::dxil, SubArch);
144 T.setOSName(Triple::getOSTypeName(Triple::OSType::ShaderModel).str() +
146 T.setEnvironment(Kind);
147 if (isLegalShaderModel(
T))
148 return T.getTriple();
153bool isLegalValidatorVersion(StringRef ValVersionStr,
const Driver &
D) {
154 VersionTuple Version;
155 if (Version.tryParse(ValVersionStr) || Version.getBuild() ||
156 Version.getSubminor() || !Version.getMinor()) {
157 D.Diag(diag::err_drv_invalid_format_dxil_validator_version)
162 uint64_t Major = Version.getMajor();
163 uint64_t Minor = *Version.getMinor();
164 if (Major == 0 && Minor != 0) {
165 D.Diag(diag::err_drv_invalid_empty_dxil_validator_version) << ValVersionStr;
168 VersionTuple MinVer(1, 0);
169 if (Version < MinVer) {
170 D.Diag(diag::err_drv_invalid_range_dxil_validator_version) << ValVersionStr;
176void getSpirvExtOperand(StringRef SpvExtensionArg, raw_ostream &
out) {
179 static const std::vector<StringRef> DxcSupportedExtensions = {
180 "SPV_KHR_16bit_storage",
"SPV_KHR_device_group",
181 "SPV_KHR_fragment_shading_rate",
"SPV_KHR_multiview",
182 "SPV_KHR_post_depth_coverage",
"SPV_KHR_non_semantic_info",
183 "SPV_KHR_shader_draw_parameters",
"SPV_KHR_ray_tracing",
184 "SPV_KHR_shader_clock",
"SPV_EXT_demote_to_helper_invocation",
185 "SPV_EXT_descriptor_indexing",
"SPV_EXT_fragment_fully_covered",
186 "SPV_EXT_fragment_invocation_density",
187 "SPV_EXT_fragment_shader_interlock",
"SPV_EXT_mesh_shader",
188 "SPV_EXT_shader_stencil_export",
"SPV_EXT_shader_viewport_index_layer",
190 "SPV_GOOGLE_hlsl_functionality1",
"SPV_GOOGLE_user_type",
191 "SPV_KHR_ray_query",
"SPV_EXT_shader_image_int64",
192 "SPV_KHR_fragment_shader_barycentric",
"SPV_KHR_physical_storage_buffer",
193 "SPV_KHR_vulkan_memory_model",
196 "SPV_KHR_float_controls",
"SPV_NV_shader_subgroup_partitioned",
200 if (SpvExtensionArg.starts_with(
"SPV_")) {
201 out <<
"+" << SpvExtensionArg;
205 if (SpvExtensionArg.compare_insensitive(
"DXC") == 0) {
208 for (StringRef
E : DxcSupportedExtensions) {
217 out << SpvExtensionArg;
221 if (SpvExtensionArgs.empty()) {
222 return StringRef(
"-spirv-ext=all");
226 raw_svector_ostream
out(LlvmOption);
228 out <<
"-spirv-ext=";
229 getSpirvExtOperand(SpvExtensionArgs[0],
out);
231 SpvExtensionArgs = SpvExtensionArgs.slice(1);
232 for (StringRef Extension : SpvExtensionArgs) {
234 getSpirvExtOperand(Extension,
out);
239bool isValidSPIRVExtensionName(
const std::string &str) {
240 std::regex pattern(
"dxc|DXC|khr|KHR|SPV_[a-zA-Z0-9_]+");
241 return std::regex_match(str, pattern);
248 bool AllValid =
true;
249 for (
auto Extension : SpvExtensionArgs) {
250 if (!isValidSPIRVExtensionName(Extension)) {
264 const char *LinkingOutput)
const {
266 assert(DxvPath !=
"dxv" &&
"cannot find dxv");
268 ArgStringList CmdArgs;
269 assert(Inputs.size() == 1 &&
"Unable to handle multiple inputs.");
272 CmdArgs.push_back(
"-o");
275 const char *Exec = Args.MakeArgString(DxvPath);
277 Exec, CmdArgs, Inputs, Input));
283 const char *LinkingOutput)
const {
284 std::string MSCPath = getToolChain().GetProgramPath(
"metal-shaderconverter");
285 ArgStringList CmdArgs;
286 assert(Inputs.size() == 1 &&
"Unable to handle multiple inputs.");
289 CmdArgs.push_back(
"-o");
292 const char *Exec = Args.MakeArgString(MSCPath);
294 Exec, CmdArgs, Inputs, Input));
301 const char *LinkingOutput)
const {
303 std::string ObjcopyPath = getToolChain().GetProgramPath(
"llvm-objcopy");
304 const char *Exec = Args.MakeArgString(ObjcopyPath);
306 ArgStringList CmdArgs;
307 assert(Inputs.size() == 1 &&
"Unable to handle multiple inputs.");
312 if (Args.hasArg(options::OPT_dxc_strip_rootsignature)) {
313 const char *Frs = Args.MakeArgString(
"--remove-section=RTS0");
314 CmdArgs.push_back(Frs);
317 assert(CmdArgs.size() > 2 &&
"Unnecessary invocation of objcopy.");
320 Exec, CmdArgs, Inputs, Input));
327 if (Args.hasArg(options::OPT_dxc_validator_path_EQ))
329 Args.getLastArgValue(options::OPT_dxc_validator_path_EQ).str());
338 return Validator.get();
342 return MetalConverter.get();
346 return LLVMObjcopy.get();
352std::optional<std::string>
354 StringRef TargetProfile) {
355 return tryParseProfile(TargetProfile);
361 DerivedArgList *DAL =
new DerivedArgList(Args.getBaseArgs());
365 for (Arg *A : Args) {
366 if (A->getOption().getID() == options::OPT_dxil_validator_version) {
367 StringRef ValVerStr = A->getValue();
368 if (!isLegalValidatorVersion(ValVerStr,
getDriver()))
371 if (A->getOption().getID() == options::OPT_dxc_entrypoint) {
372 DAL->AddSeparateArg(
nullptr, Opts.getOption(options::OPT_hlsl_entrypoint),
377 if (A->getOption().getID() == options::OPT_dxc_rootsig_ver) {
378 DAL->AddJoinedArg(
nullptr,
379 Opts.getOption(options::OPT_fdx_rootsignature_version),
384 if (A->getOption().getID() == options::OPT_dxc_rootsig_define) {
385 DAL->AddJoinedArg(
nullptr,
386 Opts.getOption(options::OPT_fdx_rootsignature_define),
391 if (A->getOption().getID() == options::OPT__SLASH_O) {
392 StringRef OStr = A->getValue();
394 DAL->AddFlagArg(
nullptr, Opts.getOption(options::OPT_O0));
398 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_O), OStr);
403 if (A->getOption().getID() == options::OPT_emit_pristine_llvm) {
405 DAL->AddFlagArg(
nullptr, Opts.getOption(options::OPT_emit_llvm));
406 DAL->AddFlagArg(
nullptr,
407 Opts.getOption(options::OPT_disable_llvm_passes));
411 if (A->getOption().getID() == options::OPT_dxc_hlsl_version) {
417 DAL->AddSeparateArg(
nullptr, Opts.getOption(options::OPT_std_EQ),
420 getDriver().
Diag(diag::err_drv_invalid_value) <<
"HV" << A->getValue();
426 if (A->getOption().getID() == options::OPT_dxc_gis) {
428 DAL->AddSeparateArg(
nullptr, Opts.getOption(options::OPT_ffp_model_EQ),
433 if (A->getOption().getID() == options::OPT_fvk_use_dx_layout) {
439 if (A->getOption().getID() == options::OPT_fvk_use_scalar_layout) {
440 getDriver().
Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
445 if (A->getOption().getID() == options::OPT_fvk_use_gl_layout) {
446 getDriver().
Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
454 if (
getArch() == llvm::Triple::spirv) {
455 std::vector<std::string> SpvExtensionArgs =
456 Args.getAllArgValues(options::OPT_fspv_extension_EQ);
457 if (checkExtensionArgsAreValid(SpvExtensionArgs,
getDriver())) {
459 DAL->AddSeparateArg(
nullptr, Opts.getOption(options::OPT_mllvm),
462 Args.claimAllArgs(options::OPT_fspv_extension_EQ);
465 if (!DAL->hasArg(options::OPT_O_Group)) {
466 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_O),
"3");
473 if (!Args.hasArg(options::OPT_dxc_Fo))
476 if (Args.getLastArg(options::OPT_dxc_disable_validation))
480 if (DxvPath !=
"dxv")
488 return Args.hasArg(options::OPT_metal) && Args.hasArg(options::OPT_dxc_Fo);
492 return Args.hasArg(options::OPT_dxc_Fo) &&
493 Args.hasArg(options::OPT_dxc_strip_rootsignature);
500 return AC == Action::Action::BinaryTranslatorJobClass;
502 return AC == Action::Action::BinaryAnalyzeJobClass;
504 return AC == Action::Action::ObjcopyJobClass;
@ BinaryTranslatorJobClass
Compilation - A set of tasks to perform for a single driver invocation.
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
DiagnosticBuilder Diag(unsigned DiagID) const
const llvm::opt::OptTable & getOpts() const
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T
llvm::StringRef getAsString(SyncScope S)
Diagnostic wrappers for TextAPI types for error reporting.
LangStandard - Information about the properties of a particular language standard.
static Kind getHLSLLangKind(StringRef Name)
static const LangStandard & getLangStandardForKind(Kind K)
const char * getName() const
getName - Get the name of this standard.
static constexpr ResponseFileSupport None()
Returns a ResponseFileSupport indicating that response files are not supported.