ARMTargetParser.cpp 18 KB

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