HLSLOptions.cpp 49 KB

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