ARMTargetParser.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640
  1. //===-- ARMTargetParser - Parser for ARM target features --------*- 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. //
  9. // This file implements a target parser to recognise ARM hardware features
  10. // such as FPU/CPU/ARCH/extensions and specific support such as HWDIV.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm/Support/ARMTargetParser.h"
  14. #include "llvm/ADT/StringSwitch.h"
  15. #include "llvm/ADT/Triple.h"
  16. #include <cctype>
  17. using namespace llvm;
  18. static StringRef getHWDivSynonym(StringRef HWDiv) {
  19. return StringSwitch<StringRef>(HWDiv)
  20. .Case("thumb,arm", "arm,thumb")
  21. .Default(HWDiv);
  22. }
  23. // Allows partial match, ex. "v7a" matches "armv7a".
  24. ARM::ArchKind ARM::parseArch(StringRef Arch) {
  25. Arch = getCanonicalArchName(Arch);
  26. StringRef Syn = getArchSynonym(Arch);
  27. for (const auto &A : ARCHNames) {
  28. if (A.getName().endswith(Syn))
  29. return A.ID;
  30. }
  31. return ArchKind::INVALID;
  32. }
  33. // Version number (ex. v7 = 7).
  34. unsigned ARM::parseArchVersion(StringRef Arch) {
  35. Arch = getCanonicalArchName(Arch);
  36. switch (parseArch(Arch)) {
  37. case ArchKind::ARMV2:
  38. case ArchKind::ARMV2A:
  39. return 2;
  40. case ArchKind::ARMV3:
  41. case ArchKind::ARMV3M:
  42. return 3;
  43. case ArchKind::ARMV4:
  44. case ArchKind::ARMV4T:
  45. return 4;
  46. case ArchKind::ARMV5T:
  47. case ArchKind::ARMV5TE:
  48. case ArchKind::IWMMXT:
  49. case ArchKind::IWMMXT2:
  50. case ArchKind::XSCALE:
  51. case ArchKind::ARMV5TEJ:
  52. return 5;
  53. case ArchKind::ARMV6:
  54. case ArchKind::ARMV6K:
  55. case ArchKind::ARMV6T2:
  56. case ArchKind::ARMV6KZ:
  57. case ArchKind::ARMV6M:
  58. return 6;
  59. case ArchKind::ARMV7A:
  60. case ArchKind::ARMV7VE:
  61. case ArchKind::ARMV7R:
  62. case ArchKind::ARMV7M:
  63. case ArchKind::ARMV7S:
  64. case ArchKind::ARMV7EM:
  65. case ArchKind::ARMV7K:
  66. return 7;
  67. case ArchKind::ARMV8A:
  68. case ArchKind::ARMV8_1A:
  69. case ArchKind::ARMV8_2A:
  70. case ArchKind::ARMV8_3A:
  71. case ArchKind::ARMV8_4A:
  72. case ArchKind::ARMV8_5A:
  73. case ArchKind::ARMV8_6A:
  74. case ArchKind::ARMV8_7A:
  75. case ArchKind::ARMV8_8A:
  76. case ArchKind::ARMV8R:
  77. case ArchKind::ARMV8MBaseline:
  78. case ArchKind::ARMV8MMainline:
  79. case ArchKind::ARMV8_1MMainline:
  80. return 8;
  81. case ArchKind::ARMV9A:
  82. case ArchKind::ARMV9_1A:
  83. case ArchKind::ARMV9_2A:
  84. case ArchKind::ARMV9_3A:
  85. return 9;
  86. case ArchKind::INVALID:
  87. return 0;
  88. }
  89. llvm_unreachable("Unhandled architecture");
  90. }
  91. // Profile A/R/M
  92. ARM::ProfileKind ARM::parseArchProfile(StringRef Arch) {
  93. Arch = getCanonicalArchName(Arch);
  94. switch (parseArch(Arch)) {
  95. case ArchKind::ARMV6M:
  96. case ArchKind::ARMV7M:
  97. case ArchKind::ARMV7EM:
  98. case ArchKind::ARMV8MMainline:
  99. case ArchKind::ARMV8MBaseline:
  100. case ArchKind::ARMV8_1MMainline:
  101. return ProfileKind::M;
  102. case ArchKind::ARMV7R:
  103. case ArchKind::ARMV8R:
  104. return ProfileKind::R;
  105. case ArchKind::ARMV7A:
  106. case ArchKind::ARMV7VE:
  107. case ArchKind::ARMV7K:
  108. case ArchKind::ARMV8A:
  109. case ArchKind::ARMV8_1A:
  110. case ArchKind::ARMV8_2A:
  111. case ArchKind::ARMV8_3A:
  112. case ArchKind::ARMV8_4A:
  113. case ArchKind::ARMV8_5A:
  114. case ArchKind::ARMV8_6A:
  115. case ArchKind::ARMV8_7A:
  116. case ArchKind::ARMV8_8A:
  117. case ArchKind::ARMV9A:
  118. case ArchKind::ARMV9_1A:
  119. case ArchKind::ARMV9_2A:
  120. case ArchKind::ARMV9_3A:
  121. return ProfileKind::A;
  122. case ArchKind::ARMV2:
  123. case ArchKind::ARMV2A:
  124. case ArchKind::ARMV3:
  125. case ArchKind::ARMV3M:
  126. case ArchKind::ARMV4:
  127. case ArchKind::ARMV4T:
  128. case ArchKind::ARMV5T:
  129. case ArchKind::ARMV5TE:
  130. case ArchKind::ARMV5TEJ:
  131. case ArchKind::ARMV6:
  132. case ArchKind::ARMV6K:
  133. case ArchKind::ARMV6T2:
  134. case ArchKind::ARMV6KZ:
  135. case ArchKind::ARMV7S:
  136. case ArchKind::IWMMXT:
  137. case ArchKind::IWMMXT2:
  138. case ArchKind::XSCALE:
  139. case ArchKind::INVALID:
  140. return ProfileKind::INVALID;
  141. }
  142. llvm_unreachable("Unhandled architecture");
  143. }
  144. StringRef ARM::getArchSynonym(StringRef Arch) {
  145. return StringSwitch<StringRef>(Arch)
  146. .Case("v5", "v5t")
  147. .Case("v5e", "v5te")
  148. .Case("v6j", "v6")
  149. .Case("v6hl", "v6k")
  150. .Cases("v6m", "v6sm", "v6s-m", "v6-m")
  151. .Cases("v6z", "v6zk", "v6kz")
  152. .Cases("v7", "v7a", "v7hl", "v7l", "v7-a")
  153. .Case("v7r", "v7-r")
  154. .Case("v7m", "v7-m")
  155. .Case("v7em", "v7e-m")
  156. .Cases("v8", "v8a", "v8l", "aarch64", "arm64", "v8-a")
  157. .Case("v8.1a", "v8.1-a")
  158. .Case("v8.2a", "v8.2-a")
  159. .Case("v8.3a", "v8.3-a")
  160. .Case("v8.4a", "v8.4-a")
  161. .Case("v8.5a", "v8.5-a")
  162. .Case("v8.6a", "v8.6-a")
  163. .Case("v8.7a", "v8.7-a")
  164. .Case("v8.8a", "v8.8-a")
  165. .Case("v8r", "v8-r")
  166. .Cases("v9", "v9a", "v9-a")
  167. .Case("v9.1a", "v9.1-a")
  168. .Case("v9.2a", "v9.2-a")
  169. .Case("v9.3a", "v9.3-a")
  170. .Case("v8m.base", "v8-m.base")
  171. .Case("v8m.main", "v8-m.main")
  172. .Case("v8.1m.main", "v8.1-m.main")
  173. .Default(Arch);
  174. }
  175. bool ARM::getFPUFeatures(unsigned FPUKind, std::vector<StringRef> &Features) {
  176. if (FPUKind >= FK_LAST || FPUKind == FK_INVALID)
  177. return false;
  178. static const struct FPUFeatureNameInfo {
  179. const char *PlusName, *MinusName;
  180. FPUVersion MinVersion;
  181. FPURestriction MaxRestriction;
  182. } FPUFeatureInfoList[] = {
  183. // We have to specify the + and - versions of the name in full so
  184. // that we can return them as static StringRefs.
  185. //
  186. // Also, the SubtargetFeatures ending in just "sp" are listed here
  187. // under FPURestriction::None, which is the only FPURestriction in
  188. // which they would be valid (since FPURestriction::SP doesn't
  189. // exist).
  190. {"+vfp2", "-vfp2", FPUVersion::VFPV2, FPURestriction::D16},
  191. {"+vfp2sp", "-vfp2sp", FPUVersion::VFPV2, FPURestriction::SP_D16},
  192. {"+vfp3", "-vfp3", FPUVersion::VFPV3, FPURestriction::None},
  193. {"+vfp3d16", "-vfp3d16", FPUVersion::VFPV3, FPURestriction::D16},
  194. {"+vfp3d16sp", "-vfp3d16sp", FPUVersion::VFPV3, FPURestriction::SP_D16},
  195. {"+vfp3sp", "-vfp3sp", FPUVersion::VFPV3, FPURestriction::None},
  196. {"+fp16", "-fp16", FPUVersion::VFPV3_FP16, FPURestriction::SP_D16},
  197. {"+vfp4", "-vfp4", FPUVersion::VFPV4, FPURestriction::None},
  198. {"+vfp4d16", "-vfp4d16", FPUVersion::VFPV4, FPURestriction::D16},
  199. {"+vfp4d16sp", "-vfp4d16sp", FPUVersion::VFPV4, FPURestriction::SP_D16},
  200. {"+vfp4sp", "-vfp4sp", FPUVersion::VFPV4, FPURestriction::None},
  201. {"+fp-armv8", "-fp-armv8", FPUVersion::VFPV5, FPURestriction::None},
  202. {"+fp-armv8d16", "-fp-armv8d16", FPUVersion::VFPV5, FPURestriction::D16},
  203. {"+fp-armv8d16sp", "-fp-armv8d16sp", FPUVersion::VFPV5, FPURestriction::SP_D16},
  204. {"+fp-armv8sp", "-fp-armv8sp", FPUVersion::VFPV5, FPURestriction::None},
  205. {"+fullfp16", "-fullfp16", FPUVersion::VFPV5_FULLFP16, FPURestriction::SP_D16},
  206. {"+fp64", "-fp64", FPUVersion::VFPV2, FPURestriction::D16},
  207. {"+d32", "-d32", FPUVersion::VFPV3, FPURestriction::None},
  208. };
  209. for (const auto &Info: FPUFeatureInfoList) {
  210. if (FPUNames[FPUKind].FPUVer >= Info.MinVersion &&
  211. FPUNames[FPUKind].Restriction <= Info.MaxRestriction)
  212. Features.push_back(Info.PlusName);
  213. else
  214. Features.push_back(Info.MinusName);
  215. }
  216. static const struct NeonFeatureNameInfo {
  217. const char *PlusName, *MinusName;
  218. NeonSupportLevel MinSupportLevel;
  219. } NeonFeatureInfoList[] = {
  220. {"+neon", "-neon", NeonSupportLevel::Neon},
  221. {"+sha2", "-sha2", NeonSupportLevel::Crypto},
  222. {"+aes", "-aes", NeonSupportLevel::Crypto},
  223. };
  224. for (const auto &Info: NeonFeatureInfoList) {
  225. if (FPUNames[FPUKind].NeonSupport >= Info.MinSupportLevel)
  226. Features.push_back(Info.PlusName);
  227. else
  228. Features.push_back(Info.MinusName);
  229. }
  230. return true;
  231. }
  232. // Little/Big endian
  233. ARM::EndianKind ARM::parseArchEndian(StringRef Arch) {
  234. if (Arch.startswith("armeb") || Arch.startswith("thumbeb") ||
  235. Arch.startswith("aarch64_be"))
  236. return EndianKind::BIG;
  237. if (Arch.startswith("arm") || Arch.startswith("thumb")) {
  238. if (Arch.endswith("eb"))
  239. return EndianKind::BIG;
  240. else
  241. return EndianKind::LITTLE;
  242. }
  243. if (Arch.startswith("aarch64") || Arch.startswith("aarch64_32"))
  244. return EndianKind::LITTLE;
  245. return EndianKind::INVALID;
  246. }
  247. // ARM, Thumb, AArch64
  248. ARM::ISAKind ARM::parseArchISA(StringRef Arch) {
  249. return StringSwitch<ISAKind>(Arch)
  250. .StartsWith("aarch64", ISAKind::AARCH64)
  251. .StartsWith("arm64", ISAKind::AARCH64)
  252. .StartsWith("thumb", ISAKind::THUMB)
  253. .StartsWith("arm", ISAKind::ARM)
  254. .Default(ISAKind::INVALID);
  255. }
  256. unsigned ARM::parseFPU(StringRef FPU) {
  257. StringRef Syn = getFPUSynonym(FPU);
  258. for (const auto &F : FPUNames) {
  259. if (Syn == F.getName())
  260. return F.ID;
  261. }
  262. return FK_INVALID;
  263. }
  264. ARM::NeonSupportLevel ARM::getFPUNeonSupportLevel(unsigned FPUKind) {
  265. if (FPUKind >= FK_LAST)
  266. return NeonSupportLevel::None;
  267. return FPUNames[FPUKind].NeonSupport;
  268. }
  269. // MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but
  270. // (iwmmxt|xscale)(eb)? is also permitted. If the former, return
  271. // "v.+", if the latter, return unmodified string, minus 'eb'.
  272. // If invalid, return empty string.
  273. StringRef ARM::getCanonicalArchName(StringRef Arch) {
  274. size_t offset = StringRef::npos;
  275. StringRef A = Arch;
  276. StringRef Error = "";
  277. // Begins with "arm" / "thumb", move past it.
  278. if (A.startswith("arm64_32"))
  279. offset = 8;
  280. else if (A.startswith("arm64e"))
  281. offset = 6;
  282. else if (A.startswith("arm64"))
  283. offset = 5;
  284. else if (A.startswith("aarch64_32"))
  285. offset = 10;
  286. else if (A.startswith("arm"))
  287. offset = 3;
  288. else if (A.startswith("thumb"))
  289. offset = 5;
  290. else if (A.startswith("aarch64")) {
  291. offset = 7;
  292. // AArch64 uses "_be", not "eb" suffix.
  293. if (A.contains("eb"))
  294. return Error;
  295. if (A.substr(offset, 3) == "_be")
  296. offset += 3;
  297. }
  298. // Ex. "armebv7", move past the "eb".
  299. if (offset != StringRef::npos && A.substr(offset, 2) == "eb")
  300. offset += 2;
  301. // Or, if it ends with eb ("armv7eb"), chop it off.
  302. else if (A.endswith("eb"))
  303. A = A.substr(0, A.size() - 2);
  304. // Trim the head
  305. if (offset != StringRef::npos)
  306. A = A.substr(offset);
  307. // Empty string means offset reached the end, which means it's valid.
  308. if (A.empty())
  309. return Arch;
  310. // Only match non-marketing names
  311. if (offset != StringRef::npos) {
  312. // Must start with 'vN'.
  313. if (A.size() >= 2 && (A[0] != 'v' || !std::isdigit(A[1])))
  314. return Error;
  315. // Can't have an extra 'eb'.
  316. if (A.contains("eb"))
  317. return Error;
  318. }
  319. // Arch will either be a 'v' name (v7a) or a marketing name (xscale).
  320. return A;
  321. }
  322. StringRef ARM::getFPUSynonym(StringRef FPU) {
  323. return StringSwitch<StringRef>(FPU)
  324. .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported
  325. .Case("vfp2", "vfpv2")
  326. .Case("vfp3", "vfpv3")
  327. .Case("vfp4", "vfpv4")
  328. .Case("vfp3-d16", "vfpv3-d16")
  329. .Case("vfp4-d16", "vfpv4-d16")
  330. .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16")
  331. .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16")
  332. .Case("fp5-sp-d16", "fpv5-sp-d16")
  333. .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16")
  334. // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3.
  335. .Case("neon-vfpv3", "neon")
  336. .Default(FPU);
  337. }
  338. StringRef ARM::getFPUName(unsigned FPUKind) {
  339. if (FPUKind >= FK_LAST)
  340. return StringRef();
  341. return FPUNames[FPUKind].getName();
  342. }
  343. ARM::FPUVersion ARM::getFPUVersion(unsigned FPUKind) {
  344. if (FPUKind >= FK_LAST)
  345. return FPUVersion::NONE;
  346. return FPUNames[FPUKind].FPUVer;
  347. }
  348. ARM::FPURestriction ARM::getFPURestriction(unsigned FPUKind) {
  349. if (FPUKind >= FK_LAST)
  350. return FPURestriction::None;
  351. return FPUNames[FPUKind].Restriction;
  352. }
  353. unsigned ARM::getDefaultFPU(StringRef CPU, ARM::ArchKind AK) {
  354. if (CPU == "generic")
  355. return ARM::ARCHNames[static_cast<unsigned>(AK)].DefaultFPU;
  356. return StringSwitch<unsigned>(CPU)
  357. #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
  358. .Case(NAME, DEFAULT_FPU)
  359. #include "llvm/Support/ARMTargetParser.def"
  360. .Default(ARM::FK_INVALID);
  361. }
  362. uint64_t ARM::getDefaultExtensions(StringRef CPU, ARM::ArchKind AK) {
  363. if (CPU == "generic")
  364. return ARM::ARCHNames[static_cast<unsigned>(AK)].ArchBaseExtensions;
  365. return StringSwitch<uint64_t>(CPU)
  366. #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
  367. .Case(NAME, \
  368. ARCHNames[static_cast<unsigned>(ArchKind::ID)].ArchBaseExtensions | \
  369. DEFAULT_EXT)
  370. #include "llvm/Support/ARMTargetParser.def"
  371. .Default(ARM::AEK_INVALID);
  372. }
  373. bool ARM::getHWDivFeatures(uint64_t HWDivKind,
  374. std::vector<StringRef> &Features) {
  375. if (HWDivKind == AEK_INVALID)
  376. return false;
  377. if (HWDivKind & AEK_HWDIVARM)
  378. Features.push_back("+hwdiv-arm");
  379. else
  380. Features.push_back("-hwdiv-arm");
  381. if (HWDivKind & AEK_HWDIVTHUMB)
  382. Features.push_back("+hwdiv");
  383. else
  384. Features.push_back("-hwdiv");
  385. return true;
  386. }
  387. bool ARM::getExtensionFeatures(uint64_t Extensions,
  388. std::vector<StringRef> &Features) {
  389. if (Extensions == AEK_INVALID)
  390. return false;
  391. for (const auto &AE : ARCHExtNames) {
  392. if ((Extensions & AE.ID) == AE.ID && AE.Feature)
  393. Features.push_back(AE.Feature);
  394. else if (AE.NegFeature)
  395. Features.push_back(AE.NegFeature);
  396. }
  397. return getHWDivFeatures(Extensions, Features);
  398. }
  399. StringRef ARM::getArchName(ARM::ArchKind AK) {
  400. return ARCHNames[static_cast<unsigned>(AK)].getName();
  401. }
  402. StringRef ARM::getCPUAttr(ARM::ArchKind AK) {
  403. return ARCHNames[static_cast<unsigned>(AK)].getCPUAttr();
  404. }
  405. StringRef ARM::getSubArch(ARM::ArchKind AK) {
  406. return ARCHNames[static_cast<unsigned>(AK)].getSubArch();
  407. }
  408. unsigned ARM::getArchAttr(ARM::ArchKind AK) {
  409. return ARCHNames[static_cast<unsigned>(AK)].ArchAttr;
  410. }
  411. StringRef ARM::getArchExtName(uint64_t ArchExtKind) {
  412. for (const auto &AE : ARCHExtNames) {
  413. if (ArchExtKind == AE.ID)
  414. return AE.getName();
  415. }
  416. return StringRef();
  417. }
  418. static bool stripNegationPrefix(StringRef &Name) {
  419. if (Name.startswith("no")) {
  420. Name = Name.substr(2);
  421. return true;
  422. }
  423. return false;
  424. }
  425. StringRef ARM::getArchExtFeature(StringRef ArchExt) {
  426. bool Negated = stripNegationPrefix(ArchExt);
  427. for (const auto &AE : ARCHExtNames) {
  428. if (AE.Feature && ArchExt == AE.getName())
  429. return StringRef(Negated ? AE.NegFeature : AE.Feature);
  430. }
  431. return StringRef();
  432. }
  433. static unsigned findDoublePrecisionFPU(unsigned InputFPUKind) {
  434. const ARM::FPUName &InputFPU = ARM::FPUNames[InputFPUKind];
  435. // If the input FPU already supports double-precision, then there
  436. // isn't any different FPU we can return here.
  437. //
  438. // The current available FPURestriction values are None (no
  439. // restriction), D16 (only 16 d-regs) and SP_D16 (16 d-regs
  440. // and single precision only); there's no value representing
  441. // SP restriction without D16. So this test just means 'is it
  442. // SP only?'.
  443. if (InputFPU.Restriction != ARM::FPURestriction::SP_D16)
  444. return ARM::FK_INVALID;
  445. // Otherwise, look for an FPU entry with all the same fields, except
  446. // that SP_D16 has been replaced with just D16, representing adding
  447. // double precision and not changing anything else.
  448. for (const ARM::FPUName &CandidateFPU : ARM::FPUNames) {
  449. if (CandidateFPU.FPUVer == InputFPU.FPUVer &&
  450. CandidateFPU.NeonSupport == InputFPU.NeonSupport &&
  451. CandidateFPU.Restriction == ARM::FPURestriction::D16) {
  452. return CandidateFPU.ID;
  453. }
  454. }
  455. // nothing found
  456. return ARM::FK_INVALID;
  457. }
  458. bool ARM::appendArchExtFeatures(StringRef CPU, ARM::ArchKind AK,
  459. StringRef ArchExt,
  460. std::vector<StringRef> &Features,
  461. unsigned &ArgFPUID) {
  462. size_t StartingNumFeatures = Features.size();
  463. const bool Negated = stripNegationPrefix(ArchExt);
  464. uint64_t ID = parseArchExt(ArchExt);
  465. if (ID == AEK_INVALID)
  466. return false;
  467. for (const auto &AE : ARCHExtNames) {
  468. if (Negated) {
  469. if ((AE.ID & ID) == ID && AE.NegFeature)
  470. Features.push_back(AE.NegFeature);
  471. } else {
  472. if ((AE.ID & ID) == AE.ID && AE.Feature)
  473. Features.push_back(AE.Feature);
  474. }
  475. }
  476. if (CPU == "")
  477. CPU = "generic";
  478. if (ArchExt == "fp" || ArchExt == "fp.dp") {
  479. unsigned FPUKind;
  480. if (ArchExt == "fp.dp") {
  481. if (Negated) {
  482. Features.push_back("-fp64");
  483. return true;
  484. }
  485. FPUKind = findDoublePrecisionFPU(getDefaultFPU(CPU, AK));
  486. } else if (Negated) {
  487. FPUKind = ARM::FK_NONE;
  488. } else {
  489. FPUKind = getDefaultFPU(CPU, AK);
  490. }
  491. ArgFPUID = FPUKind;
  492. return ARM::getFPUFeatures(FPUKind, Features);
  493. }
  494. return StartingNumFeatures != Features.size();
  495. }
  496. StringRef ARM::getDefaultCPU(StringRef Arch) {
  497. ArchKind AK = parseArch(Arch);
  498. if (AK == ArchKind::INVALID)
  499. return StringRef();
  500. // Look for multiple AKs to find the default for pair AK+Name.
  501. for (const auto &CPU : CPUNames) {
  502. if (CPU.ArchID == AK && CPU.Default)
  503. return CPU.getName();
  504. }
  505. // If we can't find a default then target the architecture instead
  506. return "generic";
  507. }
  508. uint64_t ARM::parseHWDiv(StringRef HWDiv) {
  509. StringRef Syn = getHWDivSynonym(HWDiv);
  510. for (const auto &D : HWDivNames) {
  511. if (Syn == D.getName())
  512. return D.ID;
  513. }
  514. return AEK_INVALID;
  515. }
  516. uint64_t ARM::parseArchExt(StringRef ArchExt) {
  517. for (const auto &A : ARCHExtNames) {
  518. if (ArchExt == A.getName())
  519. return A.ID;
  520. }
  521. return AEK_INVALID;
  522. }
  523. ARM::ArchKind ARM::parseCPUArch(StringRef CPU) {
  524. for (const auto &C : CPUNames) {
  525. if (CPU == C.getName())
  526. return C.ArchID;
  527. }
  528. return ArchKind::INVALID;
  529. }
  530. void ARM::fillValidCPUArchList(SmallVectorImpl<StringRef> &Values) {
  531. for (const CpuNames<ArchKind> &Arch : CPUNames) {
  532. if (Arch.ArchID != ArchKind::INVALID)
  533. Values.push_back(Arch.getName());
  534. }
  535. }
  536. StringRef ARM::computeDefaultTargetABI(const Triple &TT, StringRef CPU) {
  537. StringRef ArchName =
  538. CPU.empty() ? TT.getArchName() : getArchName(parseCPUArch(CPU));
  539. if (TT.isOSBinFormatMachO()) {
  540. if (TT.getEnvironment() == Triple::EABI ||
  541. TT.getOS() == Triple::UnknownOS ||
  542. parseArchProfile(ArchName) == ProfileKind::M)
  543. return "aapcs";
  544. if (TT.isWatchABI())
  545. return "aapcs16";
  546. return "apcs-gnu";
  547. } else if (TT.isOSWindows())
  548. // FIXME: this is invalid for WindowsCE.
  549. return "aapcs";
  550. // Select the default based on the platform.
  551. switch (TT.getEnvironment()) {
  552. case Triple::Android:
  553. case Triple::GNUEABI:
  554. case Triple::GNUEABIHF:
  555. case Triple::MuslEABI:
  556. case Triple::MuslEABIHF:
  557. return "aapcs-linux";
  558. case Triple::EABIHF:
  559. case Triple::EABI:
  560. return "aapcs";
  561. default:
  562. if (TT.isOSNetBSD())
  563. return "apcs-gnu";
  564. if (TT.isOSOpenBSD())
  565. return "aapcs-linux";
  566. return "aapcs";
  567. }
  568. }