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;
65 case Triple::EnvironmentType::RootSignature:
66 VersionTuple MinVer(1, 0);
67 VersionTuple MaxVer(1, 2);
68 return MinVer <= Version && Version <= MaxVer;
73std::optional<llvm::Triple> tryParseTriple(StringRef Profile) {
76 Profile.split(Parts,
"_");
77 if (Parts.size() != 3)
80 Triple::EnvironmentType Kind =
81 StringSwitch<Triple::EnvironmentType>(Parts[0])
82 .Case(
"ps", Triple::EnvironmentType::Pixel)
83 .Case(
"vs", Triple::EnvironmentType::Vertex)
84 .Case(
"gs", Triple::EnvironmentType::Geometry)
85 .Case(
"hs", Triple::EnvironmentType::Hull)
86 .Case(
"ds", Triple::EnvironmentType::Domain)
87 .Case(
"cs", Triple::EnvironmentType::Compute)
88 .Case(
"lib", Triple::EnvironmentType::Library)
89 .Case(
"ms", Triple::EnvironmentType::Mesh)
90 .Case(
"as", Triple::EnvironmentType::Amplification)
91 .Case(
"rootsig", Triple::EnvironmentType::RootSignature)
92 .Default(Triple::EnvironmentType::UnknownEnvironment);
93 if (Kind == Triple::EnvironmentType::UnknownEnvironment)
96 unsigned long long Major = 0;
97 if (llvm::getAsUnsignedInteger(Parts[1], 0, Major))
100 unsigned long long Minor = 0;
101 if (Parts[2] ==
"x" && Kind == Triple::EnvironmentType::Library)
102 Minor = OfflineLibMinor;
103 else if (llvm::getAsUnsignedInteger(Parts[2], 0, Minor))
111 Triple::SubArchType SubArch = llvm::Triple::NoSubArch;
114 SubArch = llvm::Triple::DXILSubArch_v1_0;
117 SubArch = llvm::Triple::DXILSubArch_v1_1;
120 SubArch = llvm::Triple::DXILSubArch_v1_2;
123 SubArch = llvm::Triple::DXILSubArch_v1_3;
126 SubArch = llvm::Triple::DXILSubArch_v1_4;
129 SubArch = llvm::Triple::DXILSubArch_v1_5;
132 SubArch = llvm::Triple::DXILSubArch_v1_6;
135 SubArch = llvm::Triple::DXILSubArch_v1_7;
138 SubArch = llvm::Triple::DXILSubArch_v1_8;
141 SubArch = llvm::Triple::DXILSubArch_v1_9;
143 case OfflineLibMinor:
145 SubArch = llvm::Triple::LatestDXILSubArch;
151 T.setArch(Triple::ArchType::dxil, SubArch);
152 T.setOSName(Triple::getOSTypeName(Triple::OSType::ShaderModel).str() +
154 T.setEnvironment(Kind);
159std::optional<std::string> tryParseProfile(StringRef Profile) {
160 std::optional<llvm::Triple> MaybeT = tryParseTriple(Profile);
161 if (MaybeT && isLegalShaderModel(*MaybeT))
162 return MaybeT->getTriple();
167bool isLegalValidatorVersion(StringRef ValVersionStr,
const Driver &D) {
168 VersionTuple Version;
169 if (Version.tryParse(ValVersionStr) || Version.getBuild() ||
170 Version.getSubminor() || !Version.getMinor()) {
171 D.
Diag(diag::err_drv_invalid_format_dxil_validator_version)
176 uint64_t Major = Version.getMajor();
177 uint64_t Minor = *Version.getMinor();
178 if (Major == 0 && Minor != 0) {
179 D.
Diag(diag::err_drv_invalid_empty_dxil_validator_version) << ValVersionStr;
182 VersionTuple MinVer(1, 0);
183 if (Version < MinVer) {
184 D.
Diag(diag::err_drv_invalid_range_dxil_validator_version) << ValVersionStr;
190void getSpirvExtOperand(StringRef SpvExtensionArg, raw_ostream &
out) {
193 static const std::vector<StringRef> DxcSupportedExtensions = {
194 "SPV_KHR_16bit_storage",
195 "SPV_KHR_device_group",
196 "SPV_KHR_fragment_shading_rate",
198 "SPV_KHR_post_depth_coverage",
199 "SPV_KHR_non_semantic_info",
200 "SPV_KHR_shader_draw_parameters",
201 "SPV_KHR_ray_tracing",
202 "SPV_KHR_shader_clock",
203 "SPV_EXT_demote_to_helper_invocation",
204 "SPV_EXT_descriptor_indexing",
205 "SPV_EXT_fragment_fully_covered",
206 "SPV_EXT_fragment_invocation_density",
207 "SPV_EXT_fragment_shader_interlock",
208 "SPV_EXT_mesh_shader",
209 "SPV_EXT_shader_stencil_export",
210 "SPV_EXT_shader_viewport_index_layer",
212 "SPV_GOOGLE_hlsl_functionality1",
213 "SPV_GOOGLE_user_type",
215 "SPV_EXT_shader_image_int64",
216 "SPV_KHR_fragment_shader_barycentric",
217 "SPV_KHR_physical_storage_buffer",
218 "SPV_KHR_vulkan_memory_model",
220 "SPV_KHR_maximal_reconvergence",
221 "SPV_KHR_float_controls",
222 "SPV_NV_shader_subgroup_partitioned",
226 if (SpvExtensionArg.starts_with(
"SPV_")) {
227 out <<
"+" << SpvExtensionArg;
231 if (SpvExtensionArg.compare_insensitive(
"DXC") == 0) {
233 for (StringRef E : DxcSupportedExtensions) {
242 out << SpvExtensionArg;
246 if (SpvExtensionArgs.empty()) {
247 return StringRef(
"-spirv-ext=all");
251 raw_svector_ostream
out(LlvmOption);
253 out <<
"-spirv-ext=";
254 getSpirvExtOperand(SpvExtensionArgs[0],
out);
256 SpvExtensionArgs = SpvExtensionArgs.slice(1);
257 for (StringRef Extension : SpvExtensionArgs) {
259 getSpirvExtOperand(Extension,
out);
264bool isValidSPIRVExtensionName(
const std::string &str) {
265 std::regex pattern(
"dxc|DXC|khr|KHR|SPV_[a-zA-Z0-9_]+");
266 return std::regex_match(str, pattern);
273 bool AllValid =
true;
274 for (
auto Extension : SpvExtensionArgs) {
275 if (!isValidSPIRVExtensionName(Extension)) {
277 <<
"-fspv-extension" << Extension;
284bool isRootSignatureTarget(StringRef Profile) {
285 if (std::optional<llvm::Triple> T = tryParseTriple(Profile))
286 return T->getEnvironment() == Triple::EnvironmentType::RootSignature;
290bool isRootSignatureTarget(DerivedArgList &Args) {
291 if (
const Arg *A = Args.getLastArg(options::OPT_target_profile))
292 return isRootSignatureTarget(A->getValue());
302 const char *LinkingOutput)
const {
303 ArgStringList CmdArgs;
304 assert(Inputs.size() == 1 &&
"Unable to handle multiple inputs.");
308 std::string ExecPath;
311 assert(ExecPath !=
"spirv-val" &&
"cannot find spirv-val");
313 CmdArgs.push_back(
"--target-env");
314 CmdArgs.push_back(Args.MakeArgString(T.getOSName()));
315 CmdArgs.push_back(
"--scalar-block-layout");
317 }
else if (T.isDXIL()) {
319 assert(ExecPath !=
"dxv" &&
"cannot find dxv");
322 CmdArgs.push_back(
"-o");
325 llvm_unreachable(
"unexpected triple for HLSL validation");
328 const char *Exec = Args.MakeArgString(ExecPath);
330 Exec, CmdArgs, Inputs, Input));
336 const char *LinkingOutput)
const {
337 std::string MSCPath =
getToolChain().GetProgramPath(
"metal-shaderconverter");
338 ArgStringList CmdArgs;
339 assert(Inputs.size() == 1 &&
"Unable to handle multiple inputs.");
342 CmdArgs.push_back(
"-o");
345 StringRef Reflection = Args.getLastArgValue(options::OPT_dxc_Fre);
346 if (!Reflection.empty()) {
347 const char *ReflectionStr =
348 Args.MakeArgString(StringRef(
"--output-reflection-file=") + Reflection);
349 CmdArgs.push_back(ReflectionStr);
352 const char *Exec = Args.MakeArgString(MSCPath);
354 Exec, CmdArgs, Inputs, Input));
361 const char *LinkingOutput)
const {
363 std::string ObjcopyPath =
getToolChain().GetProgramPath(
"llvm-objcopy");
364 const char *Exec = Args.MakeArgString(ObjcopyPath);
366 ArgStringList CmdArgs;
367 assert(Inputs.size() == 1 &&
"Unable to handle multiple inputs.");
372 if (Args.hasArg(options::OPT_dxc_strip_rootsignature)) {
373 const char *StripRS = Args.MakeArgString(
"--remove-section=RTS0");
374 CmdArgs.push_back(StripRS);
377 if (Arg *Arg = Args.getLastArg(options::OPT_dxc_Frs)) {
379 Args.MakeArgString(
"--extract-section=RTS0=" + Twine(Arg->getValue()));
380 CmdArgs.push_back(Frs);
383 if (
const Arg *A = Args.getLastArg(options::OPT_target_profile))
384 if (isRootSignatureTarget(A->getValue())) {
385 const char *Fos = Args.MakeArgString(
"--only-section=RTS0");
386 CmdArgs.push_back(Fos);
389 assert(CmdArgs.size() > 2 &&
"Unnecessary invocation of objcopy.");
392 Exec, CmdArgs, Inputs, Input));
399 if (Args.hasArg(options::OPT_dxc_validator_path_EQ))
401 Args.getLastArgValue(options::OPT_dxc_validator_path_EQ).str());
402 if (Args.hasArg(options::OPT_spirv_validator_path_EQ))
404 Args.getLastArgValue(options::OPT_spirv_validator_path_EQ).str());
413 return Validator.get();
417 return MetalConverter.get();
421 return LLVMObjcopy.get();
427std::optional<std::string>
429 StringRef TargetProfile) {
430 return tryParseProfile(TargetProfile);
436 DerivedArgList *DAL =
new DerivedArgList(Args.getBaseArgs());
440 if (Args.hasArg(options::OPT_dxc_col_major) &&
441 Args.hasArg(options::OPT_dxc_row_major))
444 for (Arg *A : Args) {
445 if (A->getOption().getID() == options::OPT_dxc_all_resources_bound) {
446 DAL->AddFlagArg(
nullptr,
447 Opts.getOption(options::OPT_hlsl_all_resources_bound));
451 if (A->getOption().getID() == options::OPT_dxil_validator_version) {
452 StringRef ValVerStr = A->getValue();
453 if (!isLegalValidatorVersion(ValVerStr,
getDriver()))
456 if (A->getOption().getID() == options::OPT_dxc_entrypoint) {
457 DAL->AddSeparateArg(
nullptr, Opts.getOption(options::OPT_hlsl_entrypoint),
462 if (A->getOption().getID() == options::OPT_dxc_rootsig_ver) {
463 DAL->AddJoinedArg(
nullptr,
464 Opts.getOption(options::OPT_fdx_rootsignature_version),
469 if (A->getOption().getID() == options::OPT_dxc_rootsig_define) {
470 DAL->AddJoinedArg(
nullptr,
471 Opts.getOption(options::OPT_fdx_rootsignature_define),
476 if (A->getOption().getID() == options::OPT__SLASH_O) {
477 StringRef OStr = A->getValue();
479 DAL->AddFlagArg(
nullptr, Opts.getOption(options::OPT_O0));
483 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_O), OStr);
488 if (A->getOption().getID() == options::OPT_emit_pristine_llvm) {
490 DAL->AddFlagArg(
nullptr, Opts.getOption(options::OPT_emit_llvm));
491 DAL->AddFlagArg(
nullptr,
492 Opts.getOption(options::OPT_disable_llvm_passes));
496 if (A->getOption().getID() == options::OPT_dxc_hlsl_version) {
502 DAL->AddSeparateArg(
nullptr, Opts.getOption(options::OPT_std_EQ),
505 getDriver().
Diag(diag::err_drv_invalid_value) <<
"HV" << A->getValue();
511 if (A->getOption().getID() == options::OPT_dxc_gis) {
513 DAL->AddSeparateArg(
nullptr, Opts.getOption(options::OPT_ffp_model_EQ),
518 if (A->getOption().getID() == options::OPT_fvk_use_dx_layout) {
524 if (A->getOption().getID() == options::OPT_fvk_use_scalar_layout) {
525 getDriver().
Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
530 if (A->getOption().getID() == options::OPT_fvk_use_gl_layout) {
531 getDriver().
Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
536 if (A->getOption().getID() == options::OPT_enable_16bit_types) {
539 DAL->AddFlagArg(
nullptr, Opts.getOption(options::OPT_fnative_half_type));
540 DAL->AddFlagArg(
nullptr, Opts.getOption(options::OPT_fnative_int16_type));
544 if (A->getOption().getID() == options::OPT_dxc_col_major) {
545 DAL->AddJoinedArg(
nullptr,
546 Opts.getOption(options::OPT_fmatrix_memory_layout_EQ),
551 if (A->getOption().getID() == options::OPT_dxc_row_major) {
552 DAL->AddJoinedArg(
nullptr,
553 Opts.getOption(options::OPT_fmatrix_memory_layout_EQ),
561 if (A->getOption().getID() == options::OPT_dxc_Fre) {
562 if (Args.hasArg(options::OPT_metal)) {
563 if (!Args.hasArg(options::OPT_dxc_Fo))
569 DAL->AddSeparateArg(
nullptr, Opts.getOption(options::OPT_dxc_Fre),
577 if (
getArch() == llvm::Triple::spirv) {
578 std::vector<std::string> SpvExtensionArgs =
579 Args.getAllArgValues(options::OPT_fspv_extension_EQ);
580 if (checkExtensionArgsAreValid(SpvExtensionArgs,
getDriver())) {
582 DAL->AddSeparateArg(
nullptr, Opts.getOption(options::OPT_mllvm),
585 Args.claimAllArgs(options::OPT_fspv_extension_EQ);
588 if (!DAL->hasArg(options::OPT_O_Group)) {
589 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_O),
"3");
599 bool HasFo = Args.hasArg(options::OPT_dxc_Fo);
600 bool DisableValidation =
601 Args.getLastArg(options::OPT_dxc_disable_validation) !=
nullptr;
603 if (DisableValidation || !HasFo)
608 if (DxvPath !=
"dxv") {
621 if (SpirvValPath !=
"spirv-val") {
635 return Args.hasArg(options::OPT_metal) && Args.hasArg(options::OPT_dxc_Fo);
639 return Args.hasArg(options::OPT_dxc_Fo) &&
640 (Args.hasArg(options::OPT_dxc_strip_rootsignature) ||
641 Args.hasArg(options::OPT_dxc_Frs) || isRootSignatureTarget(Args));
648 return AC == Action::Action::BinaryTranslatorJobClass;
650 if (ValInfo.NeedsValidation) {
651 if (ValInfo.ProducesOutput)
652 return AC == Action::Action::BinaryAnalyzeJobClass;
653 return AC == Action::Action::AssembleJobClass;
656 return AC == Action::Action::ObjcopyJobClass;
664 CC1Args.push_back(
"-Wconversion");
665 CC1Args.push_back(
"-Wvector-conversion");
666 CC1Args.push_back(
"-Wmatrix-conversion");
@ 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
SmallVector< InputInfo, 4 > InputInfoList
The JSON file list parser is used to communicate input to InstallAPI.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
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.