HLSLOptions.cpp 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018
  1. //===--- HLSLOptions.cpp - Driver Options Table ---------------------------===//
  2. ///////////////////////////////////////////////////////////////////////////////
  3. // //
  4. // HLSLOptions.cpp //
  5. // Copyright (C) Microsoft Corporation. All rights reserved. //
  6. // This file is distributed under the University of Illinois Open Source //
  7. // License. See LICENSE.TXT for details. //
  8. // //
  9. ///////////////////////////////////////////////////////////////////////////////
  10. #include "llvm/ADT/STLExtras.h"
  11. #include "llvm/Option/OptTable.h"
  12. #include "llvm/Option/Option.h"
  13. #include "llvm/Support/raw_ostream.h"
  14. #include "llvm/Support/Path.h"
  15. #include "llvm/ADT/APInt.h"
  16. #include "dxc/Support/Global.h"
  17. #include "dxc/Support/WinIncludes.h"
  18. #include "dxc/Support/HLSLOptions.h"
  19. #include "dxc/Support/Unicode.h"
  20. #include "dxc/Support/dxcapi.use.h"
  21. #include "dxc/DXIL/DxilShaderModel.h"
  22. using namespace llvm::opt;
  23. using namespace dxc;
  24. using namespace hlsl;
  25. using namespace hlsl::options;
  26. #define PREFIX(NAME, VALUE) static const char *const NAME[] = VALUE;
  27. #include "dxc/Support/HLSLOptions.inc"
  28. #undef PREFIX
  29. static const OptTable::Info HlslInfoTable[] = {
  30. #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
  31. HELPTEXT, METAVAR) \
  32. { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, Option::KIND##Class, PARAM, \
  33. FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS },
  34. #include "dxc/Support/HLSLOptions.inc"
  35. #undef OPTION
  36. };
  37. namespace {
  38. class HlslOptTable : public OptTable {
  39. public:
  40. HlslOptTable()
  41. : OptTable(HlslInfoTable, llvm::array_lengthof(HlslInfoTable)) {}
  42. };
  43. }
  44. static HlslOptTable *g_HlslOptTable;
  45. std::error_code hlsl::options::initHlslOptTable() {
  46. DXASSERT(g_HlslOptTable == nullptr, "else double-init");
  47. g_HlslOptTable = new (std::nothrow) HlslOptTable();
  48. if (g_HlslOptTable == nullptr)
  49. return std::error_code(E_OUTOFMEMORY, std::system_category());
  50. return std::error_code();
  51. }
  52. void hlsl::options::cleanupHlslOptTable() {
  53. delete g_HlslOptTable;
  54. g_HlslOptTable = nullptr;
  55. }
  56. const OptTable * hlsl::options::getHlslOptTable() {
  57. return g_HlslOptTable;
  58. }
  59. void DxcDefines::push_back(llvm::StringRef value) {
  60. // Skip empty defines.
  61. if (value.size() > 0) {
  62. DefineStrings.push_back(value);
  63. }
  64. }
  65. UINT32 DxcDefines::ComputeNumberOfWCharsNeededForDefines() {
  66. UINT32 wcharSize = 0;
  67. for (llvm::StringRef &S : DefineStrings) {
  68. DXASSERT(S.size() > 0,
  69. "else DxcDefines::push_back should not have added this");
  70. const int utf16Length = ::MultiByteToWideChar(
  71. CP_UTF8, MB_ERR_INVALID_CHARS, S.data(), S.size(), nullptr, 0);
  72. IFTARG(utf16Length != 0);
  73. wcharSize += utf16Length + 1; // adding null terminated character
  74. }
  75. return wcharSize;
  76. }
  77. void DxcDefines::BuildDefines() {
  78. // Calculate and prepare the size of the backing buffer.
  79. DXASSERT(DefineValues == nullptr, "else DxcDefines is already built");
  80. UINT32 wcharSize = ComputeNumberOfWCharsNeededForDefines();
  81. DefineValues = new wchar_t[wcharSize];
  82. DefineVector.resize(DefineStrings.size());
  83. // Build up the define structures while filling in the backing buffer.
  84. UINT32 remaining = wcharSize;
  85. LPWSTR pWriteCursor = DefineValues;
  86. for (size_t i = 0; i < DefineStrings.size(); ++i) {
  87. llvm::StringRef &S = DefineStrings[i];
  88. DxcDefine &D = DefineVector[i];
  89. const int utf16Length =
  90. ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, S.data(), S.size(),
  91. pWriteCursor, remaining);
  92. DXASSERT(utf16Length > 0,
  93. "else it should have failed during size calculation");
  94. LPWSTR pDefineEnd = pWriteCursor + utf16Length;
  95. D.Name = pWriteCursor;
  96. LPWSTR pEquals = std::find(pWriteCursor, pDefineEnd, L'=');
  97. if (pEquals == pDefineEnd) {
  98. D.Value = nullptr;
  99. } else {
  100. *pEquals = L'\0';
  101. D.Value = pEquals + 1;
  102. }
  103. // Advance past converted characters and include the null terminator.
  104. pWriteCursor += utf16Length;
  105. *pWriteCursor = L'\0';
  106. ++pWriteCursor;
  107. DXASSERT(pWriteCursor <= DefineValues + wcharSize,
  108. "else this function is calculating this incorrectly");
  109. remaining -= (utf16Length + 1);
  110. }
  111. }
  112. bool DxcOpts::IsRootSignatureProfile() {
  113. return TargetProfile == "rootsig_1_0" ||
  114. TargetProfile == "rootsig_1_1";
  115. }
  116. bool DxcOpts::IsLibraryProfile() {
  117. return TargetProfile.startswith("lib_");
  118. }
  119. bool DxcOpts::GenerateFullDebugInfo() {
  120. return DebugInfo;
  121. }
  122. bool DxcOpts::GeneratePDB() {
  123. return DebugInfo || SourceOnlyDebug;
  124. }
  125. bool DxcOpts::EmbedDebugInfo() {
  126. return EmbedDebug;
  127. }
  128. bool DxcOpts::EmbedPDBName() {
  129. return GeneratePDB() || !DebugFile.empty();
  130. }
  131. bool DxcOpts::DebugFileIsDirectory() {
  132. return !DebugFile.empty() && llvm::sys::path::is_separator(DebugFile[DebugFile.size() - 1]);
  133. }
  134. llvm::StringRef DxcOpts::GetPDBName() {
  135. if (!DebugFileIsDirectory())
  136. return DebugFile;
  137. return llvm::StringRef();
  138. }
  139. MainArgs::MainArgs(int argc, const wchar_t **argv, int skipArgCount) {
  140. if (argc > skipArgCount) {
  141. Utf8StringVector.reserve(argc - skipArgCount);
  142. Utf8CharPtrVector.reserve(argc - skipArgCount);
  143. for (int i = skipArgCount; i < argc; ++i) {
  144. Utf8StringVector.emplace_back(Unicode::UTF16ToUTF8StringOrThrow(argv[i]));
  145. Utf8CharPtrVector.push_back(Utf8StringVector.back().data());
  146. }
  147. }
  148. }
  149. MainArgs::MainArgs(int argc, const char **argv, int skipArgCount) {
  150. if (argc > skipArgCount) {
  151. Utf8StringVector.reserve(argc - skipArgCount);
  152. Utf8CharPtrVector.reserve(argc - skipArgCount);
  153. for (int i = skipArgCount; i < argc; ++i) {
  154. Utf8StringVector.emplace_back(argv[i]);
  155. Utf8CharPtrVector.push_back(Utf8StringVector.back().data());
  156. }
  157. }
  158. }
  159. MainArgs::MainArgs(llvm::ArrayRef<llvm::StringRef> args) {
  160. Utf8StringVector.reserve(args.size());
  161. Utf8CharPtrVector.reserve(args.size());
  162. for (llvm::StringRef str : args) {
  163. Utf8StringVector.emplace_back(str.str());
  164. Utf8CharPtrVector.push_back(Utf8StringVector.back().data());
  165. }
  166. }
  167. MainArgs& MainArgs::operator=(const MainArgs &other) {
  168. Utf8StringVector.clear();
  169. Utf8CharPtrVector.clear();
  170. Utf8StringVector.reserve(other.Utf8StringVector.size());
  171. Utf8CharPtrVector.reserve(other.Utf8StringVector.size());
  172. for (const std::string &str : other.Utf8StringVector) {
  173. Utf8StringVector.emplace_back(str);
  174. Utf8CharPtrVector.push_back(Utf8StringVector.back().data());
  175. }
  176. return *this;
  177. }
  178. StringRefUtf16::StringRefUtf16(llvm::StringRef value) {
  179. if (!value.empty())
  180. m_value = Unicode::UTF8ToUTF16StringOrThrow(value.data());
  181. }
  182. static bool GetTargetVersionFromString(llvm::StringRef ref, unsigned *major, unsigned *minor) {
  183. *major = *minor = -1;
  184. unsigned len = ref.size();
  185. if (len < 6 || len > 11) // length: ps_6_0 to rootsig_1_0
  186. return false;
  187. if (ref[len - 4] != '_' || ref[len - 2] != '_')
  188. return false;
  189. char cMajor = ref[len - 3];
  190. char cMinor = ref[len - 1];
  191. if (cMajor >= '0' && cMajor <= '9')
  192. *major = cMajor - '0';
  193. else
  194. return false;
  195. if (cMinor == 'x')
  196. *minor = 0xF;
  197. else if (cMinor >= '0' && cMinor <= '9')
  198. *minor = cMinor - '0';
  199. else
  200. return false;
  201. return true;
  202. }
  203. // Copied from CompilerInvocation since we parse our own diagnostic arguments
  204. static void addDiagnosticArgs(ArgList &Args, OptSpecifier Group,
  205. OptSpecifier GroupWithValue,
  206. std::vector<std::string> &Diagnostics) {
  207. for (Arg *A : Args.filtered(Group)) {
  208. if (A->getOption().getKind() == Option::FlagClass) {
  209. // The argument is a pure flag (such as OPT_Wall or OPT_Wdeprecated). Add
  210. // its name (minus the "W" or "R" at the beginning) to the warning list.
  211. Diagnostics.push_back(A->getOption().getName().drop_front(1));
  212. } else if (A->getOption().matches(GroupWithValue)) {
  213. // This is -Wfoo= or -Rfoo=, where foo is the name of the diagnostic group.
  214. Diagnostics.push_back(A->getOption().getName().drop_front(1).rtrim("=-"));
  215. } else {
  216. // Otherwise, add its value (for OPT_W_Joined and similar).
  217. for (const char *Arg : A->getValues())
  218. Diagnostics.emplace_back(Arg);
  219. }
  220. }
  221. }
  222. // SPIRV Change Starts
  223. #ifdef ENABLE_SPIRV_CODEGEN
  224. /// Checks and collects the arguments for -fvk-{b|s|t|u}-shift into *shifts.
  225. static bool handleVkShiftArgs(const InputArgList &args, OptSpecifier id,
  226. const char *name,
  227. llvm::SmallVectorImpl<int32_t> *shifts,
  228. llvm::raw_ostream &errors) {
  229. const auto values = args.getAllArgValues(id);
  230. if (values.empty())
  231. return true;
  232. if (!args.hasArg(OPT_spirv)) {
  233. errors << "-fvk-" << name << "-shift requires -spirv";
  234. return false;
  235. }
  236. if (!args.getLastArgValue(OPT_fvk_bind_register).empty()) {
  237. errors << "-fvk-" << name
  238. << "-shift cannot be used together with -fvk-bind-register";
  239. return false;
  240. }
  241. shifts->clear();
  242. bool setForAll = false;
  243. for (const auto &val : values) {
  244. int32_t number = 0;
  245. if (val == "all") {
  246. number = -1;
  247. setForAll = true;
  248. } else {
  249. if (llvm::StringRef(val).getAsInteger(10, number)) {
  250. errors << "invalid -fvk-" << name << "-shift argument: " << val;
  251. return false;
  252. }
  253. if (number < 0) {
  254. errors << "negative -fvk-" << name << "-shift argument: " << val;
  255. return false;
  256. }
  257. }
  258. shifts->push_back(number);
  259. }
  260. if (setForAll && shifts->size() > 2) {
  261. errors << "setting all sets via -fvk-" << name
  262. << "-shift argument should be used alone";
  263. return false;
  264. }
  265. return true;
  266. }
  267. #endif
  268. // SPIRV Change Ends
  269. namespace hlsl {
  270. namespace options {
  271. /// Reads all options from the given argument strings, populates opts, and
  272. /// validates reporting errors and warnings.
  273. int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
  274. const MainArgs &argStrings, DxcOpts &opts,
  275. llvm::raw_ostream &errors) {
  276. DXASSERT_NOMSG(optionTable != nullptr);
  277. opts.DefaultTextCodePage = DXC_CP_UTF8;
  278. unsigned missingArgIndex = 0, missingArgCount = 0;
  279. InputArgList Args = optionTable->ParseArgs(
  280. argStrings.getArrayRef(), missingArgIndex, missingArgCount, flagsToInclude);
  281. // Set DefaultTextCodePage early so it may influence error buffer
  282. // Default to UTF8 for compatibility
  283. llvm::StringRef encoding = Args.getLastArgValue(OPT_encoding);
  284. if (!encoding.empty()) {
  285. if (encoding.equals_lower("utf8")) {
  286. opts.DefaultTextCodePage = DXC_CP_UTF8;
  287. } else if (encoding.equals_lower("utf16")) {
  288. opts.DefaultTextCodePage = DXC_CP_UTF16;
  289. } else {
  290. errors << "Unsupported value '" << encoding
  291. << "for -encoding option. Allowed values: utf8, utf16.";
  292. return 1;
  293. }
  294. }
  295. // Verify consistency for external library support.
  296. opts.ExternalLib = Args.getLastArgValue(OPT_external_lib);
  297. opts.ExternalFn = Args.getLastArgValue(OPT_external_fn);
  298. if (opts.ExternalLib.empty()) {
  299. if (!opts.ExternalFn.empty()) {
  300. errors << "External function cannot be specified without an external "
  301. "library name.";
  302. return 1;
  303. }
  304. }
  305. else {
  306. if (opts.ExternalFn.empty()) {
  307. errors << "External library name requires specifying an external "
  308. "function name.";
  309. return 1;
  310. }
  311. }
  312. opts.ShowHelp = Args.hasFlag(OPT_help, OPT_INVALID, false);
  313. opts.ShowHelp |= (opts.ShowHelpHidden = Args.hasFlag(OPT__help_hidden, OPT_INVALID, false));
  314. if (opts.ShowHelp) {
  315. return 0;
  316. }
  317. if (missingArgCount) {
  318. errors << "Argument to '" << Args.getArgString(missingArgIndex)
  319. << "' is missing.";
  320. return 1;
  321. }
  322. if (!Args.hasArg(hlsl::options::OPT_Qunused_arguments)) {
  323. for (const Arg *A : Args.filtered(OPT_UNKNOWN)) {
  324. errors << "Unknown argument: '" << A->getAsString(Args).c_str() << "'";
  325. return 1;
  326. }
  327. }
  328. // Add macros from the command line.
  329. for (const Arg *A : Args.filtered(OPT_D)) {
  330. opts.Defines.push_back(A->getValue());
  331. // If supporting OPT_U and included in filter, handle undefs.
  332. }
  333. opts.Defines.BuildDefines(); // Must be called after all defines are pushed back
  334. DXASSERT(opts.ExternalLib.empty() == opts.ExternalFn.empty(),
  335. "else flow above is incorrect");
  336. opts.PreciseOutputs = Args.getAllArgValues(OPT_precise_output);
  337. // when no-warnings option is present, do not output warnings.
  338. opts.OutputWarnings = Args.hasFlag(OPT_INVALID, OPT_no_warnings, true);
  339. opts.EntryPoint = Args.getLastArgValue(OPT_entrypoint);
  340. // Entry point is required in arguments only for drivers; APIs take this through an argument.
  341. // The value should default to 'main', but we let the caller apply this policy.
  342. if (opts.TargetProfile.empty()) {
  343. opts.TargetProfile = Args.getLastArgValue(OPT_target_profile);
  344. }
  345. if (opts.IsLibraryProfile()) {
  346. // Don't bother erroring out when entry is specified. We weren't always
  347. // doing this before, so doing so will break existing code.
  348. // Set entry point to impossible name.
  349. opts.EntryPoint = "lib.no::entry";
  350. } else {
  351. if (Args.getLastArg(OPT_exports)) {
  352. errors << "library profile required when using -exports option";
  353. return 1;
  354. } else if (Args.hasFlag(OPT_export_shaders_only, OPT_INVALID, false)) {
  355. errors << "library profile required when using -export-shaders-only option";
  356. return 1;
  357. } else if (Args.getLastArg(OPT_default_linkage)) {
  358. errors << "library profile required when using -default-linkage option";
  359. return 1;
  360. }
  361. }
  362. opts.EnableDX9CompatMode = Args.hasFlag(OPT_Gec, OPT_INVALID, false);
  363. llvm::StringRef ver = Args.getLastArgValue(OPT_hlsl_version);
  364. if (ver.empty()) {
  365. if (opts.EnableDX9CompatMode)
  366. opts.HLSLVersion = 2016; // Default to max supported version with /Gec flag
  367. else
  368. opts.HLSLVersion = 2018; // Default to latest version
  369. } else {
  370. try {
  371. opts.HLSLVersion = std::stoul(std::string(ver));
  372. if (opts.HLSLVersion < 2015 || opts.HLSLVersion > 2018) {
  373. errors << "Unknown HLSL version: " << opts.HLSLVersion;
  374. return 1;
  375. }
  376. }
  377. catch (const std::invalid_argument &) {
  378. errors << "Invalid HLSL Version";
  379. return 1;
  380. }
  381. catch (const std::out_of_range &) {
  382. errors << "Invalid HLSL Version";
  383. return 1;
  384. }
  385. }
  386. if (opts.HLSLVersion == 2015 && !(flagsToInclude & HlslFlags::ISenseOption)) {
  387. errors << "HLSL Version 2015 is only supported for language services";
  388. return 1;
  389. }
  390. if (opts.EnableDX9CompatMode && opts.HLSLVersion > 2016) {
  391. errors << "/Gec is not supported with HLSLVersion " << opts.HLSLVersion;
  392. return 1;
  393. }
  394. if (opts.HLSLVersion <= 2016) {
  395. opts.EnableFXCCompatMode = true;
  396. }
  397. // AssemblyCodeHex not supported (Fx)
  398. // OutputLibrary not supported (Fl)
  399. opts.AssemblyCode = Args.getLastArgValue(OPT_Fc);
  400. opts.DebugFile = Args.getLastArgValue(OPT_Fd);
  401. opts.ExtractPrivateFile = Args.getLastArgValue(OPT_getprivate);
  402. opts.Enable16BitTypes = Args.hasFlag(OPT_enable_16bit_types, OPT_INVALID, false);
  403. opts.EnableTemplates = Args.hasFlag(OPT_enable_templates, OPT_INVALID, false);
  404. opts.OutputObject = Args.getLastArgValue(OPT_Fo);
  405. opts.OutputHeader = Args.getLastArgValue(OPT_Fh);
  406. opts.OutputWarningsFile = Args.getLastArgValue(OPT_Fe);
  407. opts.OutputReflectionFile = Args.getLastArgValue(OPT_Fre);
  408. opts.OutputRootSigFile = Args.getLastArgValue(OPT_Frs);
  409. opts.OutputShaderHashFile = Args.getLastArgValue(OPT_Fsh);
  410. opts.ShowOptionNames = Args.hasFlag(OPT_fdiagnostics_show_option, OPT_fno_diagnostics_show_option, true);
  411. opts.UseColor = Args.hasFlag(OPT_Cc, OPT_INVALID, false);
  412. opts.UseInstructionNumbers = Args.hasFlag(OPT_Ni, OPT_INVALID, false);
  413. opts.UseInstructionByteOffsets = Args.hasFlag(OPT_No, OPT_INVALID, false);
  414. opts.UseHexLiterals = Args.hasFlag(OPT_Lx, OPT_INVALID, false);
  415. opts.Preprocess = Args.getLastArgValue(OPT_P);
  416. opts.AstDump = Args.hasFlag(OPT_ast_dump, OPT_INVALID, false);
  417. opts.CodeGenHighLevel = Args.hasFlag(OPT_fcgl, OPT_INVALID, false);
  418. opts.AllowPreserveValues = Args.hasFlag(OPT_preserve_intermediate_values, OPT_INVALID, false);
  419. opts.DebugInfo = Args.hasFlag(OPT__SLASH_Zi, OPT_INVALID, false);
  420. opts.DebugNameForBinary = Args.hasFlag(OPT_Zsb, OPT_INVALID, false);
  421. opts.DebugNameForSource = Args.hasFlag(OPT_Zss, OPT_INVALID, false);
  422. opts.VariableName = Args.getLastArgValue(OPT_Vn);
  423. opts.InputFile = Args.getLastArgValue(OPT_INPUT);
  424. opts.ForceRootSigVer = Args.getLastArgValue(OPT_force_rootsig_ver);
  425. if (opts.ForceRootSigVer.empty())
  426. opts.ForceRootSigVer = Args.getLastArgValue(OPT_force_rootsig_ver_);
  427. opts.PrivateSource = Args.getLastArgValue(OPT_setprivate);
  428. opts.RootSignatureSource = Args.getLastArgValue(OPT_setrootsignature);
  429. opts.VerifyRootSignatureSource = Args.getLastArgValue(OPT_verifyrootsignature);
  430. opts.RootSignatureDefine = Args.getLastArgValue(OPT_rootsig_define);
  431. opts.ScanLimit = 0;
  432. llvm::StringRef limit = Args.getLastArgValue(OPT_memdep_block_scan_limit);
  433. if (!limit.empty())
  434. opts.ScanLimit = std::stoul(std::string(limit));
  435. for (std::string opt : Args.getAllArgValues(OPT_opt_disable))
  436. opts.DxcOptimizationToggles[llvm::StringRef(opt).lower()] = false;
  437. for (std::string opt : Args.getAllArgValues(OPT_opt_enable)) {
  438. if (!opts.DxcOptimizationToggles.insert ( {llvm::StringRef(opt).lower(), true} ).second) {
  439. errors << "Contradictory use of -opt-disable and -opt-enable with \""
  440. << llvm::StringRef(opt).lower() << "\"";
  441. return 1;
  442. }
  443. }
  444. std::vector<std::string> optSelects = Args.getAllArgValues(OPT_opt_select);
  445. for (unsigned i = 0; i + 1 < optSelects.size(); i+=2) {
  446. std::string optimization = llvm::StringRef(optSelects[i]).lower();
  447. std::string selection = optSelects[i+1];
  448. if (opts.DxcOptimizationSelects.count(optimization) &&
  449. selection.compare(opts.DxcOptimizationSelects[optimization])) {
  450. errors << "Contradictory -opt-selects for \""
  451. << optimization << "\"";
  452. return 1;
  453. }
  454. opts.DxcOptimizationSelects[optimization] = selection;
  455. }
  456. if (!opts.ForceRootSigVer.empty() && opts.ForceRootSigVer != "rootsig_1_0" &&
  457. opts.ForceRootSigVer != "rootsig_1_1") {
  458. errors << "Unsupported value '" << opts.ForceRootSigVer
  459. << "' for root signature profile.";
  460. return 1;
  461. }
  462. opts.IEEEStrict = Args.hasFlag(OPT_Gis, OPT_INVALID, false);
  463. opts.IgnoreLineDirectives = Args.hasFlag(OPT_ignore_line_directives, OPT_INVALID, false);
  464. opts.FloatDenormalMode = Args.getLastArgValue(OPT_denorm);
  465. // Check if a given denormalized value is valid
  466. if (!opts.FloatDenormalMode.empty()) {
  467. if (!(opts.FloatDenormalMode.equals_lower("preserve") ||
  468. opts.FloatDenormalMode.equals_lower("ftz") ||
  469. opts.FloatDenormalMode.equals_lower("any"))) {
  470. errors << "Unsupported value '" << opts.FloatDenormalMode
  471. << "' for denorm option.";
  472. return 1;
  473. }
  474. }
  475. llvm::StringRef auto_binding_space = Args.getLastArgValue(OPT_auto_binding_space);
  476. if (!auto_binding_space.empty()) {
  477. if (auto_binding_space.getAsInteger(10, opts.AutoBindingSpace)) {
  478. errors << "Unsupported value '" << auto_binding_space << "' for auto binding space.";
  479. return 1;
  480. }
  481. }
  482. opts.Exports = Args.getAllArgValues(OPT_exports);
  483. opts.DefaultLinkage = Args.getLastArgValue(OPT_default_linkage);
  484. if (!opts.DefaultLinkage.empty()) {
  485. if (!(opts.DefaultLinkage.equals_lower("internal") ||
  486. opts.DefaultLinkage.equals_lower("external"))) {
  487. errors << "Unsupported value '" << opts.DefaultLinkage
  488. << "for -default-linkage option.";
  489. return 1;
  490. }
  491. }
  492. // Check options only allowed in shader model >= 6.2FPDenormalMode
  493. unsigned Major = 0;
  494. unsigned Minor = 0;
  495. if (!opts.TargetProfile.empty()) {
  496. if (!GetTargetVersionFromString(opts.TargetProfile, &Major, &Minor)) {
  497. errors << "unable to parse shader model.";
  498. return 1;
  499. }
  500. }
  501. if (opts.TargetProfile.empty() || Major < 6 || (Major == 6 && Minor < 2)) {
  502. if (!opts.FloatDenormalMode.empty()) {
  503. errors << "denorm option is only allowed for shader model 6.2 and above.";
  504. return 1;
  505. }
  506. }
  507. // /enable-16bit-types only allowed for HLSL 2018 and shader model 6.2
  508. if (opts.Enable16BitTypes) {
  509. if (opts.TargetProfile.empty() || opts.HLSLVersion < 2018
  510. || Major < 6 || (Major == 6 && Minor < 2)) {
  511. errors << "enable-16bit-types is only allowed for shader model >= 6.2 and HLSL Language >= 2018.";
  512. return 1;
  513. }
  514. }
  515. opts.DisableOptimizations = false;
  516. if (Arg *A = Args.getLastArg(OPT_O0, OPT_O1, OPT_O2, OPT_O3, OPT_Od)) {
  517. if (A->getOption().matches(OPT_O0))
  518. opts.OptLevel = 0;
  519. if (A->getOption().matches(OPT_O1))
  520. opts.OptLevel = 1;
  521. if (A->getOption().matches(OPT_O2))
  522. opts.OptLevel = 2;
  523. if (A->getOption().matches(OPT_O3))
  524. opts.OptLevel = 3;
  525. if (A->getOption().matches(OPT_Od)) {
  526. opts.DisableOptimizations = true;
  527. opts.OptLevel = 0;
  528. }
  529. }
  530. else
  531. opts.OptLevel = 3;
  532. opts.OptDump = Args.hasFlag(OPT_Odump, OPT_INVALID, false);
  533. opts.DisableValidation = Args.hasFlag(OPT_VD, OPT_INVALID, false);
  534. opts.AllResourcesBound = Args.hasFlag(OPT_all_resources_bound, OPT_INVALID, false);
  535. opts.AllResourcesBound = Args.hasFlag(OPT_all_resources_bound_, OPT_INVALID, opts.AllResourcesBound);
  536. opts.ColorCodeAssembly = Args.hasFlag(OPT_Cc, OPT_INVALID, false);
  537. opts.DefaultRowMajor = Args.hasFlag(OPT_Zpr, OPT_INVALID, false);
  538. opts.DefaultColMajor = Args.hasFlag(OPT_Zpc, OPT_INVALID, false);
  539. opts.DumpBin = Args.hasFlag(OPT_dumpbin, OPT_INVALID, false);
  540. opts.Link = Args.hasFlag(OPT_link, OPT_INVALID, false);
  541. opts.NotUseLegacyCBufLoad = Args.hasFlag(OPT_no_legacy_cbuf_layout, OPT_INVALID, false);
  542. opts.NotUseLegacyCBufLoad = Args.hasFlag(OPT_not_use_legacy_cbuf_load_, OPT_INVALID, opts.NotUseLegacyCBufLoad);
  543. opts.PackPrefixStable = Args.hasFlag(OPT_pack_prefix_stable, OPT_INVALID, false);
  544. opts.PackPrefixStable = Args.hasFlag(OPT_pack_prefix_stable_, OPT_INVALID, opts.PackPrefixStable);
  545. opts.PackOptimized = Args.hasFlag(OPT_pack_optimized, OPT_INVALID, false);
  546. opts.PackOptimized = Args.hasFlag(OPT_pack_optimized_, OPT_INVALID, opts.PackOptimized);
  547. opts.DisplayIncludeProcess = Args.hasFlag(OPT_H, OPT_INVALID, false);
  548. opts.WarningAsError = Args.hasFlag(OPT__SLASH_WX, OPT_INVALID, false);
  549. opts.AvoidFlowControl = Args.hasFlag(OPT_Gfa, OPT_INVALID, false);
  550. opts.PreferFlowControl = Args.hasFlag(OPT_Gfp, OPT_INVALID, false);
  551. opts.RecompileFromBinary = Args.hasFlag(OPT_recompile, OPT_INVALID, false);
  552. opts.StripDebug = Args.hasFlag(OPT_Qstrip_debug, OPT_INVALID, false);
  553. opts.EmbedDebug = Args.hasFlag(OPT_Qembed_debug, OPT_INVALID, false);
  554. opts.SourceInDebugModule = Args.hasFlag(OPT_Qsource_in_debug_module, OPT_INVALID, false);
  555. opts.SourceOnlyDebug = Args.hasFlag(OPT_Zs, OPT_INVALID, false);
  556. opts.PdbInPrivate = Args.hasFlag(OPT_Qpdb_in_private, OPT_INVALID, false);
  557. opts.StripRootSignature = Args.hasFlag(OPT_Qstrip_rootsignature, OPT_INVALID, false);
  558. opts.StripPrivate = Args.hasFlag(OPT_Qstrip_priv, OPT_INVALID, false);
  559. opts.StripReflection = Args.hasFlag(OPT_Qstrip_reflect, OPT_INVALID, false);
  560. opts.KeepReflectionInDxil = Args.hasFlag(OPT_Qkeep_reflect_in_dxil, OPT_INVALID, false);
  561. opts.StripReflectionFromDxil = Args.hasFlag(OPT_Qstrip_reflect_from_dxil, OPT_INVALID, false);
  562. opts.ExtractRootSignature = Args.hasFlag(OPT_extractrootsignature, OPT_INVALID, false);
  563. opts.DisassembleColorCoded = Args.hasFlag(OPT_Cc, OPT_INVALID, false);
  564. opts.DisassembleInstNumbers = Args.hasFlag(OPT_Ni, OPT_INVALID, false);
  565. opts.DisassembleByteOffset = Args.hasFlag(OPT_No, OPT_INVALID, false);
  566. opts.DisaseembleHex = Args.hasFlag(OPT_Lx, OPT_INVALID, false);
  567. opts.LegacyMacroExpansion = Args.hasFlag(OPT_flegacy_macro_expansion, OPT_INVALID, false);
  568. opts.LegacyResourceReservation = Args.hasFlag(OPT_flegacy_resource_reservation, OPT_INVALID, false);
  569. opts.ExportShadersOnly = Args.hasFlag(OPT_export_shaders_only, OPT_INVALID, false);
  570. opts.PrintAfterAll = Args.hasFlag(OPT_print_after_all, OPT_INVALID, false);
  571. opts.ResMayAlias = Args.hasFlag(OPT_res_may_alias, OPT_INVALID, false);
  572. opts.ResMayAlias = Args.hasFlag(OPT_res_may_alias_, OPT_INVALID, opts.ResMayAlias);
  573. opts.ForceZeroStoreLifetimes = Args.hasFlag(OPT_force_zero_store_lifetimes, OPT_INVALID, false);
  574. // Lifetime markers on by default in 6.6 unless disabled explicitly
  575. opts.EnableLifetimeMarkers = Args.hasFlag(OPT_enable_lifetime_markers, OPT_INVALID,
  576. DXIL::CompareVersions(Major, Minor, 6, 6) >= 0) &&
  577. !Args.hasFlag(OPT_disable_lifetime_markers, OPT_INVALID, false);
  578. opts.EnablePayloadQualifiers = Args.hasFlag(OPT_enable_payload_qualifiers, OPT_INVALID,
  579. DXIL::CompareVersions(Major, Minor, 6, 7) >= 0);
  580. if (DXIL::CompareVersions(Major, Minor, 6, 8) < 0) {
  581. opts.EnablePayloadQualifiers &= !Args.hasFlag(OPT_disable_payload_qualifiers, OPT_INVALID, false);
  582. }
  583. if (opts.EnablePayloadQualifiers && DXIL::CompareVersions(Major, Minor, 6, 6) < 0) {
  584. errors << "Invalid target for payload access qualifiers. Only lib_6_6 and beyond are supported.";
  585. return 1;
  586. }
  587. opts.HandleExceptions = !Args.hasFlag(OPT_disable_exception_handling, OPT_INVALID, false);
  588. if (opts.DefaultColMajor && opts.DefaultRowMajor) {
  589. errors << "Cannot specify /Zpr and /Zpc together, use /? to get usage information";
  590. return 1;
  591. }
  592. if (opts.AvoidFlowControl && opts.PreferFlowControl) {
  593. errors << "Cannot specify /Gfa and /Gfp together, use /? to get usage information";
  594. return 1;
  595. }
  596. if (opts.PackPrefixStable && opts.PackOptimized) {
  597. errors << "Cannot specify /pack_prefix_stable and /pack_optimized together, use /? to get usage information";
  598. return 1;
  599. }
  600. // TODO: more fxc option check.
  601. // ERR_RES_MAY_ALIAS_ONLY_IN_CS_5
  602. // ERR_NOT_ABLE_TO_FLATTEN on if that contain side effects
  603. // TODO: other front-end error.
  604. // ERR_RESOURCE_NOT_IN_TEMPLATE
  605. // ERR_COMPLEX_TEMPLATE_RESOURCE
  606. // ERR_RESOURCE_BIND_CONFLICT
  607. // ERR_TEMPLATE_VAR_CONFLICT
  608. // ERR_ATTRIBUTE_PARAM_SIDE_EFFECT
  609. if ((flagsToInclude & hlsl::options::DriverOption) && opts.InputFile.empty()) {
  610. // Input file is required in arguments only for drivers; APIs take this through an argument.
  611. errors << "Required input file argument is missing. use -help to get more information.";
  612. return 1;
  613. }
  614. if (opts.OutputHeader.empty() && !opts.VariableName.empty()) {
  615. errors << "Cannot specify a header variable name when not writing a header.";
  616. return 1;
  617. }
  618. if (!opts.Preprocess.empty() &&
  619. (!opts.OutputHeader.empty() || !opts.OutputObject.empty() ||
  620. !opts.OutputWarnings || !opts.OutputWarningsFile.empty() ||
  621. !opts.OutputReflectionFile.empty() ||
  622. !opts.OutputRootSigFile.empty() ||
  623. !opts.OutputShaderHashFile.empty())) {
  624. opts.OutputHeader = "";
  625. opts.OutputObject = "";
  626. opts.OutputWarnings = true;
  627. opts.OutputWarningsFile = "";
  628. opts.OutputReflectionFile = "";
  629. opts.OutputRootSigFile = "";
  630. opts.OutputShaderHashFile = "";
  631. errors << "Warning: compiler options ignored with Preprocess.";
  632. }
  633. if (opts.DumpBin) {
  634. if (opts.DisplayIncludeProcess || opts.AstDump) {
  635. errors << "Cannot perform actions related to sources from a binary file.";
  636. return 1;
  637. }
  638. if (opts.AllResourcesBound || opts.AvoidFlowControl ||
  639. opts.CodeGenHighLevel || opts.DebugInfo || opts.DefaultColMajor ||
  640. opts.DefaultRowMajor || opts.Defines.size() != 0 ||
  641. opts.DisableOptimizations ||
  642. !opts.EntryPoint.empty() || !opts.ForceRootSigVer.empty() ||
  643. opts.PreferFlowControl || !opts.TargetProfile.empty()) {
  644. errors << "Cannot specify compilation options when reading a binary file.";
  645. return 1;
  646. }
  647. }
  648. // XXX TODO: Sort this out, since it's required for new API, but a separate argument for old APIs.
  649. if ((flagsToInclude & hlsl::options::DriverOption) &&
  650. !(flagsToInclude & hlsl::options::RewriteOption) &&
  651. opts.TargetProfile.empty() && !opts.DumpBin && opts.Preprocess.empty() && !opts.RecompileFromBinary
  652. ) {
  653. // Target profile is required in arguments only for drivers when compiling;
  654. // APIs take this through an argument.
  655. errors << "Target profile argument is missing";
  656. return 1;
  657. }
  658. llvm::StringRef valVersionStr = Args.getLastArgValue(OPT_validator_version);
  659. if (!valVersionStr.empty()) {
  660. // Parse "major.minor" version string
  661. auto verPair = valVersionStr.split(".");
  662. llvm::APInt major, minor;
  663. if (verPair.first.getAsInteger(0, major) || verPair.second.getAsInteger(0, minor)) {
  664. errors << "Format of validator version is \"<major>.<minor>\" (ex: \"1.4\").";
  665. return 1;
  666. }
  667. uint64_t major64 = major.getLimitedValue();
  668. uint64_t minor64 = minor.getLimitedValue();
  669. if (major64 > DXIL::kDxilMajor ||
  670. (major64 == DXIL::kDxilMajor && minor64 > DXIL::kDxilMinor)) {
  671. errors << "Validator version must be less than or equal to current internal version.";
  672. return 1;
  673. }
  674. if (major64 == 0 && minor64 != 0) {
  675. errors << "If validator major version is 0, minor version must also be 0.";
  676. return 1;
  677. }
  678. opts.ValVerMajor = (unsigned long)major64;
  679. opts.ValVerMinor = (unsigned long)minor64;
  680. }
  681. if (opts.IsLibraryProfile() && Minor == 0xF) {
  682. if (opts.ValVerMajor != UINT_MAX && opts.ValVerMajor != 0) {
  683. errors << "Offline library profile cannot be used with non-zero -validator-version.";
  684. return 1;
  685. }
  686. // Disable validation for offline link only target
  687. opts.DisableValidation = true;
  688. // ValVerMajor == 0 means that the module is not meant to ever be validated.
  689. opts.ValVerMajor = 0;
  690. opts.ValVerMinor = 0;
  691. }
  692. // These targets are only useful as an intermediate step towards linking to matching
  693. // shader targets without going through target downgrading at link time.
  694. // Disable lib_6_1 and lib_6_2 if /Vd is not present
  695. if (opts.IsLibraryProfile() && (Major < 6 || (Major == 6 && Minor < 3))) {
  696. if (!opts.DisableValidation) {
  697. errors << "Must disable validation for unsupported lib_6_1 or lib_6_2 "
  698. "targets.";
  699. return 1;
  700. }
  701. if (opts.ValVerMajor != UINT_MAX && opts.ValVerMajor != 0) {
  702. errors << "non-zero -validator-version cannot be used with library profiles lib_6_1 or lib_6_2.";
  703. return 1;
  704. }
  705. // ValVerMajor == 0 means that the module is not meant to ever be validated.
  706. opts.ValVerMajor = 0;
  707. opts.ValVerMinor = 0;
  708. }
  709. if (opts.KeepReflectionInDxil && opts.StripReflectionFromDxil) {
  710. errors << "-Qstrip_reflect_from_dxil mutually exclusive with -Qkeep_reflect_in_dxil.";
  711. return 1;
  712. }
  713. addDiagnosticArgs(Args, OPT_W_Group, OPT_W_value_Group, opts.Warnings);
  714. // SPIRV Change Starts
  715. #ifdef ENABLE_SPIRV_CODEGEN
  716. opts.GenSPIRV = Args.hasFlag(OPT_spirv, OPT_INVALID, false);
  717. opts.SpirvOptions.invertY = Args.hasFlag(OPT_fvk_invert_y, OPT_INVALID, false);
  718. opts.SpirvOptions.invertW = Args.hasFlag(OPT_fvk_use_dx_position_w, OPT_INVALID, false);
  719. opts.SpirvOptions.supportNonzeroBaseInstance =
  720. Args.hasFlag(OPT_fvk_support_nonzero_base_instance, OPT_INVALID, false);
  721. opts.SpirvOptions.useGlLayout = Args.hasFlag(OPT_fvk_use_gl_layout, OPT_INVALID, false);
  722. opts.SpirvOptions.useDxLayout = Args.hasFlag(OPT_fvk_use_dx_layout, OPT_INVALID, false);
  723. opts.SpirvOptions.useScalarLayout = Args.hasFlag(OPT_fvk_use_scalar_layout, OPT_INVALID, false);
  724. opts.SpirvOptions.enableReflect = Args.hasFlag(OPT_fspv_reflect, OPT_INVALID, false);
  725. opts.SpirvOptions.noWarnIgnoredFeatures = Args.hasFlag(OPT_Wno_vk_ignored_features, OPT_INVALID, false);
  726. opts.SpirvOptions.noWarnEmulatedFeatures = Args.hasFlag(OPT_Wno_vk_emulated_features, OPT_INVALID, false);
  727. opts.SpirvOptions.flattenResourceArrays =
  728. Args.hasFlag(OPT_fspv_flatten_resource_arrays, OPT_INVALID, false);
  729. opts.SpirvOptions.autoShiftBindings = Args.hasFlag(OPT_fvk_auto_shift_bindings, OPT_INVALID, false);
  730. if (!handleVkShiftArgs(Args, OPT_fvk_b_shift, "b", &opts.SpirvOptions.bShift, errors) ||
  731. !handleVkShiftArgs(Args, OPT_fvk_t_shift, "t", &opts.SpirvOptions.tShift, errors) ||
  732. !handleVkShiftArgs(Args, OPT_fvk_s_shift, "s", &opts.SpirvOptions.sShift, errors) ||
  733. !handleVkShiftArgs(Args, OPT_fvk_u_shift, "u", &opts.SpirvOptions.uShift, errors))
  734. return 1;
  735. opts.SpirvOptions.bindRegister = Args.getAllArgValues(OPT_fvk_bind_register);
  736. opts.SpirvOptions.bindGlobals = Args.getAllArgValues(OPT_fvk_bind_globals);
  737. opts.SpirvOptions.stageIoOrder = Args.getLastArgValue(OPT_fvk_stage_io_order_EQ, "decl");
  738. if (opts.SpirvOptions.stageIoOrder != "alpha" && opts.SpirvOptions.stageIoOrder != "decl") {
  739. errors << "unknown Vulkan stage I/O location assignment order: "
  740. << opts.SpirvOptions.stageIoOrder;
  741. return 1;
  742. }
  743. for (const Arg *A : Args.filtered(OPT_fspv_extension_EQ)) {
  744. opts.SpirvOptions.allowedExtensions.push_back(A->getValue());
  745. }
  746. opts.SpirvOptions.debugInfoFile = opts.SpirvOptions.debugInfoSource = false;
  747. opts.SpirvOptions.debugInfoLine = opts.SpirvOptions.debugInfoTool = false;
  748. opts.SpirvOptions.debugInfoRich = false;
  749. if (Args.hasArg(OPT_fspv_debug_EQ)) {
  750. opts.DebugInfo = true;
  751. for (const Arg *A : Args.filtered(OPT_fspv_debug_EQ)) {
  752. const llvm::StringRef v = A->getValue();
  753. if (v == "file") {
  754. opts.SpirvOptions.debugInfoFile = true;
  755. } else if (v == "source") {
  756. opts.SpirvOptions.debugInfoFile = true;
  757. opts.SpirvOptions.debugInfoSource = true;
  758. } else if (v == "line") {
  759. opts.SpirvOptions.debugInfoFile = true;
  760. opts.SpirvOptions.debugInfoSource = true;
  761. opts.SpirvOptions.debugInfoLine = true;
  762. } else if (v == "tool") {
  763. opts.SpirvOptions.debugInfoTool = true;
  764. } else if (v == "rich") {
  765. opts.SpirvOptions.debugInfoFile = true;
  766. opts.SpirvOptions.debugInfoSource = false;
  767. opts.SpirvOptions.debugInfoLine = true;
  768. opts.SpirvOptions.debugInfoRich = true;
  769. } else if (v == "rich-with-source") {
  770. opts.SpirvOptions.debugInfoFile = true;
  771. opts.SpirvOptions.debugInfoSource = true;
  772. opts.SpirvOptions.debugInfoLine = true;
  773. opts.SpirvOptions.debugInfoRich = true;
  774. } else {
  775. errors << "unknown SPIR-V debug info control parameter: " << v;
  776. return 1;
  777. }
  778. }
  779. } else if (opts.DebugInfo) {
  780. // By default turn on all categories
  781. opts.SpirvOptions.debugInfoFile = opts.SpirvOptions.debugInfoSource = true;
  782. opts.SpirvOptions.debugInfoLine = opts.SpirvOptions.debugInfoTool = true;
  783. }
  784. opts.SpirvOptions.targetEnv = Args.getLastArgValue(OPT_fspv_target_env_EQ, "vulkan1.0");
  785. // Handle -Oconfig=<comma-separated-list> option.
  786. uint32_t numOconfigs = 0;
  787. for (const Arg *A : Args.filtered(OPT_Oconfig)) {
  788. ++numOconfigs;
  789. if (numOconfigs > 1) {
  790. errors << "-Oconfig should not be specified more than once";
  791. return 1;
  792. }
  793. if (Args.getLastArg(OPT_O0, OPT_O1, OPT_O2, OPT_O3)) {
  794. errors << "-Oconfig should not be used together with -O";
  795. return 1;
  796. }
  797. for (const auto v : A->getValues()) {
  798. opts.SpirvOptions.optConfig.push_back(v);
  799. }
  800. }
  801. #else
  802. if (Args.hasFlag(OPT_spirv, OPT_INVALID, false) ||
  803. Args.hasFlag(OPT_fvk_invert_y, OPT_INVALID, false) ||
  804. Args.hasFlag(OPT_fvk_use_dx_position_w, OPT_INVALID, false) ||
  805. Args.hasFlag(OPT_fvk_support_nonzero_base_instance, OPT_INVALID, false) ||
  806. Args.hasFlag(OPT_fvk_use_gl_layout, OPT_INVALID, false) ||
  807. Args.hasFlag(OPT_fvk_use_dx_layout, OPT_INVALID, false) ||
  808. Args.hasFlag(OPT_fvk_use_scalar_layout, OPT_INVALID, false) ||
  809. Args.hasFlag(OPT_fspv_flatten_resource_arrays, OPT_INVALID, false) ||
  810. Args.hasFlag(OPT_fspv_reflect, OPT_INVALID, false) ||
  811. Args.hasFlag(OPT_Wno_vk_ignored_features, OPT_INVALID, false) ||
  812. Args.hasFlag(OPT_Wno_vk_emulated_features, OPT_INVALID, false) ||
  813. Args.hasFlag(OPT_fvk_auto_shift_bindings, OPT_INVALID, false) ||
  814. !Args.getLastArgValue(OPT_fvk_stage_io_order_EQ).empty() ||
  815. !Args.getLastArgValue(OPT_fspv_debug_EQ).empty() ||
  816. !Args.getLastArgValue(OPT_fspv_extension_EQ).empty() ||
  817. !Args.getLastArgValue(OPT_fspv_target_env_EQ).empty() ||
  818. !Args.getLastArgValue(OPT_Oconfig).empty() ||
  819. !Args.getLastArgValue(OPT_fvk_bind_register).empty() ||
  820. !Args.getLastArgValue(OPT_fvk_bind_globals).empty() ||
  821. !Args.getLastArgValue(OPT_fvk_b_shift).empty() ||
  822. !Args.getLastArgValue(OPT_fvk_t_shift).empty() ||
  823. !Args.getLastArgValue(OPT_fvk_s_shift).empty() ||
  824. !Args.getLastArgValue(OPT_fvk_u_shift).empty()) {
  825. errors << "SPIR-V CodeGen not available. "
  826. "Please recompile with -DENABLE_SPIRV_CODEGEN=ON.";
  827. return 1;
  828. }
  829. #endif // ENABLE_SPIRV_CODEGEN
  830. // SPIRV Change Ends
  831. // Validation for DebugInfo here because spirv uses same DebugInfo opt,
  832. // and legacy wrappers will add EmbedDebug in this case, leading to this
  833. // failing if placed before spirv path sets DebugInfo to true.
  834. if (opts.EmbedDebug && !opts.DebugInfo) {
  835. errors << "Must enable debug info with /Zi for /Qembed_debug";
  836. return 1;
  837. }
  838. if (opts.DebugInfo && opts.SourceOnlyDebug) {
  839. errors << "Cannot specify both /Zi and /Zs";
  840. return 1;
  841. }
  842. if (opts.SourceInDebugModule && opts.SourceOnlyDebug) {
  843. errors << "Cannot specify both /Qsource_in_debug_module and /Zs";
  844. return 1;
  845. }
  846. if (opts.DebugInfo && !opts.DebugNameForBinary && !opts.DebugNameForSource) {
  847. opts.DebugNameForBinary = true;
  848. } else if (opts.DebugNameForBinary && opts.DebugNameForSource) {
  849. errors << "Cannot specify both /Zss and /Zsb";
  850. return 1;
  851. }
  852. if (opts.DebugNameForSource && (!opts.DebugInfo && !opts.SourceOnlyDebug)) {
  853. errors << "/Zss requires debug info (/Zi or /Zs)";
  854. return 1;
  855. }
  856. // Rewriter Options
  857. if (flagsToInclude & hlsl::options::RewriteOption) {
  858. opts.RWOpt.Unchanged = Args.hasFlag(OPT_rw_unchanged, OPT_INVALID, false);
  859. opts.RWOpt.SkipFunctionBody = Args.hasFlag(OPT_rw_skip_function_body, OPT_INVALID, false);
  860. opts.RWOpt.SkipStatic = Args.hasFlag(OPT_rw_skip_static, OPT_INVALID, false);
  861. opts.RWOpt.GlobalExternByDefault = Args.hasFlag(OPT_rw_global_extern_by_default, OPT_INVALID, false);
  862. opts.RWOpt.KeepUserMacro = Args.hasFlag(OPT_rw_keep_user_macro, OPT_INVALID, false);
  863. opts.RWOpt.ExtractEntryUniforms = Args.hasFlag(OPT_rw_extract_entry_uniforms, OPT_INVALID, false);
  864. opts.RWOpt.RemoveUnusedGlobals = Args.hasFlag(OPT_rw_remove_unused_globals, OPT_INVALID, false);
  865. opts.RWOpt.RemoveUnusedFunctions = Args.hasFlag(OPT_rw_remove_unused_functions, OPT_INVALID, false);
  866. opts.RWOpt.WithLineDirective = Args.hasFlag(OPT_rw_line_directive, OPT_INVALID, false);
  867. if (opts.EntryPoint.empty() &&
  868. (opts.RWOpt.RemoveUnusedGlobals || opts.RWOpt.ExtractEntryUniforms ||
  869. opts.RWOpt.RemoveUnusedFunctions)) {
  870. errors << "-remove-unused-globals, -remove-unused-functions and -extract-entry-uniforms requires entry point (-E) to be specified.";
  871. return 1;
  872. }
  873. }
  874. opts.Args = std::move(Args);
  875. return 0;
  876. }
  877. /// Sets up the specified DxcDllSupport instance as per the given options.
  878. int SetupDxcDllSupport(const DxcOpts &opts, dxc::DxcDllSupport &dxcSupport,
  879. llvm::raw_ostream &errors) {
  880. if (!opts.ExternalLib.empty()) {
  881. DXASSERT(!opts.ExternalFn.empty(), "else ReadDxcOpts should have failed");
  882. StringRefUtf16 externalLib(opts.ExternalLib);
  883. HRESULT hrLoad =
  884. dxcSupport.InitializeForDll(externalLib, opts.ExternalFn.data());
  885. if (DXC_FAILED(hrLoad)) {
  886. errors << "Unable to load support for external DLL " << opts.ExternalLib
  887. << " with function " << opts.ExternalFn << " - error 0x";
  888. errors.write_hex(hrLoad);
  889. return 1;
  890. }
  891. }
  892. return 0;
  893. }
  894. void CopyArgsToWStrings(const InputArgList &inArgs, unsigned flagsToInclude,
  895. std::vector<std::wstring> &outArgs) {
  896. ArgStringList stringList;
  897. for (const Arg *A : inArgs) {
  898. if (A->getOption().hasFlag(flagsToInclude)) {
  899. A->renderAsInput(inArgs, stringList);
  900. }
  901. }
  902. for (const char *argText : stringList) {
  903. outArgs.emplace_back(Unicode::UTF8ToUTF16StringOrThrow(argText));
  904. }
  905. }
  906. } } // hlsl::options