AArch64.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. //===--- AArch64.cpp - AArch64 (not ARM) Helpers for Tools ------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "AArch64.h"
  9. #include "clang/Driver/Driver.h"
  10. #include "clang/Driver/DriverDiagnostic.h"
  11. #include "clang/Driver/Options.h"
  12. #include "llvm/Option/ArgList.h"
  13. #include "llvm/Support/AArch64TargetParser.h"
  14. #include "llvm/Support/TargetParser.h"
  15. #include "llvm/Support/Host.h"
  16. using namespace clang::driver;
  17. using namespace clang::driver::tools;
  18. using namespace clang;
  19. using namespace llvm::opt;
  20. /// \returns true if the given triple can determine the default CPU type even
  21. /// if -arch is not specified.
  22. static bool isCPUDeterminedByTriple(const llvm::Triple &Triple) {
  23. return Triple.isOSDarwin();
  24. }
  25. /// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are
  26. /// targeting. Set \p A to the Arg corresponding to the -mcpu argument if it is
  27. /// provided, or to nullptr otherwise.
  28. std::string aarch64::getAArch64TargetCPU(const ArgList &Args,
  29. const llvm::Triple &Triple, Arg *&A) {
  30. std::string CPU;
  31. // If we have -mcpu, use that.
  32. if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) {
  33. StringRef Mcpu = A->getValue();
  34. CPU = Mcpu.split("+").first.lower();
  35. }
  36. // Handle CPU name is 'native'.
  37. if (CPU == "native")
  38. return std::string(llvm::sys::getHostCPUName());
  39. if (CPU.size())
  40. return CPU;
  41. if (Triple.isTargetMachineMac() &&
  42. Triple.getArch() == llvm::Triple::aarch64) {
  43. // Apple Silicon macs default to M1 CPUs.
  44. return "apple-m1";
  45. }
  46. // arm64e requires v8.3a and only runs on apple-a12 and later CPUs.
  47. if (Triple.isArm64e())
  48. return "apple-a12";
  49. // Make sure we pick the appropriate Apple CPU if -arch is used or when
  50. // targetting a Darwin OS.
  51. if (Args.getLastArg(options::OPT_arch) || Triple.isOSDarwin())
  52. return Triple.getArch() == llvm::Triple::aarch64_32 ? "apple-s4"
  53. : "apple-a7";
  54. return "generic";
  55. }
  56. // Decode AArch64 features from string like +[no]featureA+[no]featureB+...
  57. static bool DecodeAArch64Features(const Driver &D, StringRef text,
  58. std::vector<StringRef> &Features,
  59. llvm::AArch64::ArchKind ArchKind) {
  60. SmallVector<StringRef, 8> Split;
  61. text.split(Split, StringRef("+"), -1, false);
  62. for (StringRef Feature : Split) {
  63. StringRef FeatureName = llvm::AArch64::getArchExtFeature(Feature);
  64. if (!FeatureName.empty())
  65. Features.push_back(FeatureName);
  66. else if (Feature == "neon" || Feature == "noneon")
  67. D.Diag(clang::diag::err_drv_no_neon_modifier);
  68. else
  69. return false;
  70. if (Feature == "sve2")
  71. Features.push_back("+sve");
  72. else if (Feature == "sve2-bitperm" || Feature == "sve2-sha3" ||
  73. Feature == "sve2-aes" || Feature == "sve2-sm4") {
  74. Features.push_back("+sve");
  75. Features.push_back("+sve2");
  76. } else if (Feature == "nosve") {
  77. Features.push_back("-sve2");
  78. Features.push_back("-sve2-bitperm");
  79. Features.push_back("-sve2-sha3");
  80. Features.push_back("-sve2-aes");
  81. Features.push_back("-sve2-sm4");
  82. } else if (Feature == "nosve2") {
  83. Features.push_back("-sve2-bitperm");
  84. Features.push_back("-sve2-sha3");
  85. Features.push_back("-sve2-aes");
  86. Features.push_back("-sve2-sm4");
  87. }
  88. // +sve implies +f32mm if the base architecture is >= v8.6A (except v9A)
  89. // It isn't the case in general that sve implies both f64mm and f32mm
  90. if ((ArchKind == llvm::AArch64::ArchKind::ARMV8_6A ||
  91. ArchKind == llvm::AArch64::ArchKind::ARMV8_7A ||
  92. ArchKind == llvm::AArch64::ArchKind::ARMV8_8A ||
  93. ArchKind == llvm::AArch64::ArchKind::ARMV9_1A ||
  94. ArchKind == llvm::AArch64::ArchKind::ARMV9_2A ||
  95. ArchKind == llvm::AArch64::ArchKind::ARMV9_3A) &&
  96. Feature == "sve")
  97. Features.push_back("+f32mm");
  98. }
  99. return true;
  100. }
  101. // Check if the CPU name and feature modifiers in -mcpu are legal. If yes,
  102. // decode CPU and feature.
  103. static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU,
  104. std::vector<StringRef> &Features) {
  105. std::pair<StringRef, StringRef> Split = Mcpu.split("+");
  106. CPU = Split.first;
  107. llvm::AArch64::ArchKind ArchKind = llvm::AArch64::ArchKind::ARMV8A;
  108. if (CPU == "native")
  109. CPU = llvm::sys::getHostCPUName();
  110. if (CPU == "generic") {
  111. Features.push_back("+neon");
  112. } else {
  113. ArchKind = llvm::AArch64::parseCPUArch(CPU);
  114. if (!llvm::AArch64::getArchFeatures(ArchKind, Features))
  115. return false;
  116. uint64_t Extension = llvm::AArch64::getDefaultExtensions(CPU, ArchKind);
  117. if (!llvm::AArch64::getExtensionFeatures(Extension, Features))
  118. return false;
  119. }
  120. if (Split.second.size() &&
  121. !DecodeAArch64Features(D, Split.second, Features, ArchKind))
  122. return false;
  123. return true;
  124. }
  125. static bool
  126. getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March,
  127. const ArgList &Args,
  128. std::vector<StringRef> &Features) {
  129. std::string MarchLowerCase = March.lower();
  130. std::pair<StringRef, StringRef> Split = StringRef(MarchLowerCase).split("+");
  131. llvm::AArch64::ArchKind ArchKind = llvm::AArch64::parseArch(Split.first);
  132. if (ArchKind == llvm::AArch64::ArchKind::INVALID ||
  133. !llvm::AArch64::getArchFeatures(ArchKind, Features))
  134. return false;
  135. // Enable SVE2 by default on Armv9-A.
  136. // It can still be disabled if +nosve2 is present.
  137. // We must do this early so that DecodeAArch64Features has the correct state
  138. if ((ArchKind == llvm::AArch64::ArchKind::ARMV9A ||
  139. ArchKind == llvm::AArch64::ArchKind::ARMV9_1A ||
  140. ArchKind == llvm::AArch64::ArchKind::ARMV9_2A)) {
  141. Features.push_back("+sve");
  142. Features.push_back("+sve2");
  143. }
  144. if ((Split.second.size() &&
  145. !DecodeAArch64Features(D, Split.second, Features, ArchKind)))
  146. return false;
  147. return true;
  148. }
  149. static bool
  150. getAArch64ArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
  151. const ArgList &Args,
  152. std::vector<StringRef> &Features) {
  153. StringRef CPU;
  154. std::string McpuLowerCase = Mcpu.lower();
  155. if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, Features))
  156. return false;
  157. return true;
  158. }
  159. static bool
  160. getAArch64MicroArchFeaturesFromMtune(const Driver &D, StringRef Mtune,
  161. const ArgList &Args,
  162. std::vector<StringRef> &Features) {
  163. std::string MtuneLowerCase = Mtune.lower();
  164. // Check CPU name is valid
  165. std::vector<StringRef> MtuneFeatures;
  166. StringRef Tune;
  167. if (!DecodeAArch64Mcpu(D, MtuneLowerCase, Tune, MtuneFeatures))
  168. return false;
  169. // Handle CPU name is 'native'.
  170. if (MtuneLowerCase == "native")
  171. MtuneLowerCase = std::string(llvm::sys::getHostCPUName());
  172. if (MtuneLowerCase == "cyclone" ||
  173. StringRef(MtuneLowerCase).startswith("apple")) {
  174. Features.push_back("+zcm");
  175. Features.push_back("+zcz");
  176. }
  177. return true;
  178. }
  179. static bool
  180. getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
  181. const ArgList &Args,
  182. std::vector<StringRef> &Features) {
  183. StringRef CPU;
  184. std::vector<StringRef> DecodedFeature;
  185. std::string McpuLowerCase = Mcpu.lower();
  186. if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, DecodedFeature))
  187. return false;
  188. return getAArch64MicroArchFeaturesFromMtune(D, CPU, Args, Features);
  189. }
  190. void aarch64::getAArch64TargetFeatures(const Driver &D,
  191. const llvm::Triple &Triple,
  192. const ArgList &Args,
  193. llvm::opt::ArgStringList &CmdArgs,
  194. std::vector<StringRef> &Features,
  195. bool ForAS) {
  196. Arg *A;
  197. bool success = true;
  198. // Enable NEON by default.
  199. Features.push_back("+neon");
  200. llvm::StringRef WaMArch;
  201. if (ForAS)
  202. for (const auto *A :
  203. Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler))
  204. for (StringRef Value : A->getValues())
  205. if (Value.startswith("-march="))
  206. WaMArch = Value.substr(7);
  207. // Call getAArch64ArchFeaturesFromMarch only if "-Wa,-march=" or
  208. // "-Xassembler -march" is detected. Otherwise it may return false
  209. // and causes Clang to error out.
  210. if (!WaMArch.empty())
  211. success = getAArch64ArchFeaturesFromMarch(D, WaMArch, Args, Features);
  212. else if ((A = Args.getLastArg(options::OPT_march_EQ)))
  213. success = getAArch64ArchFeaturesFromMarch(D, A->getValue(), Args, Features);
  214. else if ((A = Args.getLastArg(options::OPT_mcpu_EQ)))
  215. success = getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Features);
  216. else if (Args.hasArg(options::OPT_arch) || isCPUDeterminedByTriple(Triple))
  217. success = getAArch64ArchFeaturesFromMcpu(
  218. D, getAArch64TargetCPU(Args, Triple, A), Args, Features);
  219. else
  220. // Default to 'A' profile if the architecture is not specified.
  221. success = getAArch64ArchFeaturesFromMarch(D, "armv8-a", Args, Features);
  222. if (success && (A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)))
  223. success =
  224. getAArch64MicroArchFeaturesFromMtune(D, A->getValue(), Args, Features);
  225. else if (success && (A = Args.getLastArg(options::OPT_mcpu_EQ)))
  226. success =
  227. getAArch64MicroArchFeaturesFromMcpu(D, A->getValue(), Args, Features);
  228. else if (success &&
  229. (Args.hasArg(options::OPT_arch) || isCPUDeterminedByTriple(Triple)))
  230. success = getAArch64MicroArchFeaturesFromMcpu(
  231. D, getAArch64TargetCPU(Args, Triple, A), Args, Features);
  232. if (!success) {
  233. auto Diag = D.Diag(diag::err_drv_clang_unsupported);
  234. // If "-Wa,-march=" is used, 'WaMArch' will contain the argument's value,
  235. // while 'A' is uninitialized. Only dereference 'A' in the other case.
  236. if (!WaMArch.empty())
  237. Diag << "-march=" + WaMArch.str();
  238. else
  239. Diag << A->getAsString(Args);
  240. }
  241. if (Args.getLastArg(options::OPT_mgeneral_regs_only)) {
  242. Features.push_back("-fp-armv8");
  243. Features.push_back("-crypto");
  244. Features.push_back("-neon");
  245. }
  246. if (Arg *A = Args.getLastArg(options::OPT_mtp_mode_EQ)) {
  247. StringRef Mtp = A->getValue();
  248. if (Mtp == "el3")
  249. Features.push_back("+tpidr-el3");
  250. else if (Mtp == "el2")
  251. Features.push_back("+tpidr-el2");
  252. else if (Mtp == "el1")
  253. Features.push_back("+tpidr-el1");
  254. else if (Mtp != "el0")
  255. D.Diag(diag::err_drv_invalid_mtp) << A->getAsString(Args);
  256. }
  257. // Enable/disable straight line speculation hardening.
  258. if (Arg *A = Args.getLastArg(options::OPT_mharden_sls_EQ)) {
  259. StringRef Scope = A->getValue();
  260. bool EnableRetBr = false;
  261. bool EnableBlr = false;
  262. bool DisableComdat = false;
  263. if (Scope != "none") {
  264. SmallVector<StringRef, 4> Opts;
  265. Scope.split(Opts, ",");
  266. for (auto Opt : Opts) {
  267. Opt = Opt.trim();
  268. if (Opt == "all") {
  269. EnableBlr = true;
  270. EnableRetBr = true;
  271. continue;
  272. }
  273. if (Opt == "retbr") {
  274. EnableRetBr = true;
  275. continue;
  276. }
  277. if (Opt == "blr") {
  278. EnableBlr = true;
  279. continue;
  280. }
  281. if (Opt == "comdat") {
  282. DisableComdat = false;
  283. continue;
  284. }
  285. if (Opt == "nocomdat") {
  286. DisableComdat = true;
  287. continue;
  288. }
  289. D.Diag(diag::err_invalid_sls_hardening)
  290. << Scope << A->getAsString(Args);
  291. break;
  292. }
  293. }
  294. if (EnableRetBr)
  295. Features.push_back("+harden-sls-retbr");
  296. if (EnableBlr)
  297. Features.push_back("+harden-sls-blr");
  298. if (DisableComdat) {
  299. Features.push_back("+harden-sls-nocomdat");
  300. }
  301. }
  302. // En/disable crc
  303. if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) {
  304. if (A->getOption().matches(options::OPT_mcrc))
  305. Features.push_back("+crc");
  306. else
  307. Features.push_back("-crc");
  308. }
  309. // Handle (arch-dependent) fp16fml/fullfp16 relationship.
  310. // FIXME: this fp16fml option handling will be reimplemented after the
  311. // TargetParser rewrite.
  312. const auto ItRNoFullFP16 = std::find(Features.rbegin(), Features.rend(), "-fullfp16");
  313. const auto ItRFP16FML = std::find(Features.rbegin(), Features.rend(), "+fp16fml");
  314. if (llvm::is_contained(Features, "+v8.4a")) {
  315. const auto ItRFullFP16 = std::find(Features.rbegin(), Features.rend(), "+fullfp16");
  316. if (ItRFullFP16 < ItRNoFullFP16 && ItRFullFP16 < ItRFP16FML) {
  317. // Only entangled feature that can be to the right of this +fullfp16 is -fp16fml.
  318. // Only append the +fp16fml if there is no -fp16fml after the +fullfp16.
  319. if (std::find(Features.rbegin(), ItRFullFP16, "-fp16fml") == ItRFullFP16)
  320. Features.push_back("+fp16fml");
  321. }
  322. else
  323. goto fp16_fml_fallthrough;
  324. } else {
  325. fp16_fml_fallthrough:
  326. // In both of these cases, putting the 'other' feature on the end of the vector will
  327. // result in the same effect as placing it immediately after the current feature.
  328. if (ItRNoFullFP16 < ItRFP16FML)
  329. Features.push_back("-fp16fml");
  330. else if (ItRNoFullFP16 > ItRFP16FML)
  331. Features.push_back("+fullfp16");
  332. }
  333. // FIXME: this needs reimplementation too after the TargetParser rewrite
  334. //
  335. // Context sensitive meaning of Crypto:
  336. // 1) For Arch >= ARMv8.4a: crypto = sm4 + sha3 + sha2 + aes
  337. // 2) For Arch <= ARMv8.3a: crypto = sha2 + aes
  338. const auto ItBegin = Features.begin();
  339. const auto ItEnd = Features.end();
  340. const auto ItRBegin = Features.rbegin();
  341. const auto ItREnd = Features.rend();
  342. const auto ItRCrypto = std::find(ItRBegin, ItREnd, "+crypto");
  343. const auto ItRNoCrypto = std::find(ItRBegin, ItREnd, "-crypto");
  344. const auto HasCrypto = ItRCrypto != ItREnd;
  345. const auto HasNoCrypto = ItRNoCrypto != ItREnd;
  346. const ptrdiff_t PosCrypto = ItRCrypto - ItRBegin;
  347. const ptrdiff_t PosNoCrypto = ItRNoCrypto - ItRBegin;
  348. bool NoCrypto = false;
  349. if (HasCrypto && HasNoCrypto) {
  350. if (PosNoCrypto < PosCrypto)
  351. NoCrypto = true;
  352. }
  353. if (std::find(ItBegin, ItEnd, "+v8.4a") != ItEnd ||
  354. std::find(ItBegin, ItEnd, "+v8.8a") != ItEnd ||
  355. std::find(ItBegin, ItEnd, "+v9a") != ItEnd ||
  356. std::find(ItBegin, ItEnd, "+v9.1a") != ItEnd ||
  357. std::find(ItBegin, ItEnd, "+v9.2a") != ItEnd ||
  358. std::find(ItBegin, ItEnd, "+v9.3a") != ItEnd) {
  359. if (HasCrypto && !NoCrypto) {
  360. // Check if we have NOT disabled an algorithm with something like:
  361. // +crypto, -algorithm
  362. // And if "-algorithm" does not occur, we enable that crypto algorithm.
  363. const bool HasSM4 = (std::find(ItBegin, ItEnd, "-sm4") == ItEnd);
  364. const bool HasSHA3 = (std::find(ItBegin, ItEnd, "-sha3") == ItEnd);
  365. const bool HasSHA2 = (std::find(ItBegin, ItEnd, "-sha2") == ItEnd);
  366. const bool HasAES = (std::find(ItBegin, ItEnd, "-aes") == ItEnd);
  367. if (HasSM4)
  368. Features.push_back("+sm4");
  369. if (HasSHA3)
  370. Features.push_back("+sha3");
  371. if (HasSHA2)
  372. Features.push_back("+sha2");
  373. if (HasAES)
  374. Features.push_back("+aes");
  375. } else if (HasNoCrypto) {
  376. // Check if we have NOT enabled a crypto algorithm with something like:
  377. // -crypto, +algorithm
  378. // And if "+algorithm" does not occur, we disable that crypto algorithm.
  379. const bool HasSM4 = (std::find(ItBegin, ItEnd, "+sm4") != ItEnd);
  380. const bool HasSHA3 = (std::find(ItBegin, ItEnd, "+sha3") != ItEnd);
  381. const bool HasSHA2 = (std::find(ItBegin, ItEnd, "+sha2") != ItEnd);
  382. const bool HasAES = (std::find(ItBegin, ItEnd, "+aes") != ItEnd);
  383. if (!HasSM4)
  384. Features.push_back("-sm4");
  385. if (!HasSHA3)
  386. Features.push_back("-sha3");
  387. if (!HasSHA2)
  388. Features.push_back("-sha2");
  389. if (!HasAES)
  390. Features.push_back("-aes");
  391. }
  392. } else {
  393. if (HasCrypto && !NoCrypto) {
  394. const bool HasSHA2 = (std::find(ItBegin, ItEnd, "-sha2") == ItEnd);
  395. const bool HasAES = (std::find(ItBegin, ItEnd, "-aes") == ItEnd);
  396. if (HasSHA2)
  397. Features.push_back("+sha2");
  398. if (HasAES)
  399. Features.push_back("+aes");
  400. } else if (HasNoCrypto) {
  401. const bool HasSHA2 = (std::find(ItBegin, ItEnd, "+sha2") != ItEnd);
  402. const bool HasAES = (std::find(ItBegin, ItEnd, "+aes") != ItEnd);
  403. const bool HasV82a = (std::find(ItBegin, ItEnd, "+v8.2a") != ItEnd);
  404. const bool HasV83a = (std::find(ItBegin, ItEnd, "+v8.3a") != ItEnd);
  405. const bool HasV84a = (std::find(ItBegin, ItEnd, "+v8.4a") != ItEnd);
  406. if (!HasSHA2)
  407. Features.push_back("-sha2");
  408. if (!HasAES)
  409. Features.push_back("-aes");
  410. if (HasV82a || HasV83a || HasV84a) {
  411. Features.push_back("-sm4");
  412. Features.push_back("-sha3");
  413. }
  414. }
  415. }
  416. const char *Archs[] = {"+v8.6a", "+v8.7a", "+v8.8a",
  417. "+v9.1a", "+v9.2a", "+v9.3a"};
  418. auto Pos = std::find_first_of(Features.begin(), Features.end(),
  419. std::begin(Archs), std::end(Archs));
  420. if (Pos != std::end(Features))
  421. Pos = Features.insert(std::next(Pos), {"+i8mm", "+bf16"});
  422. if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
  423. options::OPT_munaligned_access)) {
  424. if (A->getOption().matches(options::OPT_mno_unaligned_access)) {
  425. Features.push_back("+strict-align");
  426. if (!ForAS)
  427. CmdArgs.push_back("-Wunaligned-access");
  428. }
  429. } else if (Triple.isOSOpenBSD()) {
  430. Features.push_back("+strict-align");
  431. if (!ForAS)
  432. CmdArgs.push_back("-Wunaligned-access");
  433. }
  434. if (Args.hasArg(options::OPT_ffixed_x1))
  435. Features.push_back("+reserve-x1");
  436. if (Args.hasArg(options::OPT_ffixed_x2))
  437. Features.push_back("+reserve-x2");
  438. if (Args.hasArg(options::OPT_ffixed_x3))
  439. Features.push_back("+reserve-x3");
  440. if (Args.hasArg(options::OPT_ffixed_x4))
  441. Features.push_back("+reserve-x4");
  442. if (Args.hasArg(options::OPT_ffixed_x5))
  443. Features.push_back("+reserve-x5");
  444. if (Args.hasArg(options::OPT_ffixed_x6))
  445. Features.push_back("+reserve-x6");
  446. if (Args.hasArg(options::OPT_ffixed_x7))
  447. Features.push_back("+reserve-x7");
  448. if (Args.hasArg(options::OPT_ffixed_x9))
  449. Features.push_back("+reserve-x9");
  450. if (Args.hasArg(options::OPT_ffixed_x10))
  451. Features.push_back("+reserve-x10");
  452. if (Args.hasArg(options::OPT_ffixed_x11))
  453. Features.push_back("+reserve-x11");
  454. if (Args.hasArg(options::OPT_ffixed_x12))
  455. Features.push_back("+reserve-x12");
  456. if (Args.hasArg(options::OPT_ffixed_x13))
  457. Features.push_back("+reserve-x13");
  458. if (Args.hasArg(options::OPT_ffixed_x14))
  459. Features.push_back("+reserve-x14");
  460. if (Args.hasArg(options::OPT_ffixed_x15))
  461. Features.push_back("+reserve-x15");
  462. if (Args.hasArg(options::OPT_ffixed_x18))
  463. Features.push_back("+reserve-x18");
  464. if (Args.hasArg(options::OPT_ffixed_x20))
  465. Features.push_back("+reserve-x20");
  466. if (Args.hasArg(options::OPT_ffixed_x21))
  467. Features.push_back("+reserve-x21");
  468. if (Args.hasArg(options::OPT_ffixed_x22))
  469. Features.push_back("+reserve-x22");
  470. if (Args.hasArg(options::OPT_ffixed_x23))
  471. Features.push_back("+reserve-x23");
  472. if (Args.hasArg(options::OPT_ffixed_x24))
  473. Features.push_back("+reserve-x24");
  474. if (Args.hasArg(options::OPT_ffixed_x25))
  475. Features.push_back("+reserve-x25");
  476. if (Args.hasArg(options::OPT_ffixed_x26))
  477. Features.push_back("+reserve-x26");
  478. if (Args.hasArg(options::OPT_ffixed_x27))
  479. Features.push_back("+reserve-x27");
  480. if (Args.hasArg(options::OPT_ffixed_x28))
  481. Features.push_back("+reserve-x28");
  482. if (Args.hasArg(options::OPT_ffixed_x30))
  483. Features.push_back("+reserve-x30");
  484. if (Args.hasArg(options::OPT_fcall_saved_x8))
  485. Features.push_back("+call-saved-x8");
  486. if (Args.hasArg(options::OPT_fcall_saved_x9))
  487. Features.push_back("+call-saved-x9");
  488. if (Args.hasArg(options::OPT_fcall_saved_x10))
  489. Features.push_back("+call-saved-x10");
  490. if (Args.hasArg(options::OPT_fcall_saved_x11))
  491. Features.push_back("+call-saved-x11");
  492. if (Args.hasArg(options::OPT_fcall_saved_x12))
  493. Features.push_back("+call-saved-x12");
  494. if (Args.hasArg(options::OPT_fcall_saved_x13))
  495. Features.push_back("+call-saved-x13");
  496. if (Args.hasArg(options::OPT_fcall_saved_x14))
  497. Features.push_back("+call-saved-x14");
  498. if (Args.hasArg(options::OPT_fcall_saved_x15))
  499. Features.push_back("+call-saved-x15");
  500. if (Args.hasArg(options::OPT_fcall_saved_x18))
  501. Features.push_back("+call-saved-x18");
  502. if (Args.hasArg(options::OPT_mno_neg_immediates))
  503. Features.push_back("+no-neg-immediates");
  504. if (Arg *A = Args.getLastArg(options::OPT_mfix_cortex_a53_835769,
  505. options::OPT_mno_fix_cortex_a53_835769)) {
  506. if (A->getOption().matches(options::OPT_mfix_cortex_a53_835769))
  507. Features.push_back("+fix-cortex-a53-835769");
  508. else
  509. Features.push_back("-fix-cortex-a53-835769");
  510. } else if (Triple.isAndroid()) {
  511. // Enabled A53 errata (835769) workaround by default on android
  512. Features.push_back("+fix-cortex-a53-835769");
  513. }
  514. if (Args.getLastArg(options::OPT_mno_bti_at_return_twice))
  515. Features.push_back("+no-bti-at-return-twice");
  516. }