TargetParser.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603
  1. //===-- TargetParser - Parser for target features ---------------*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file implements a target parser to recognise hardware features such as
  11. // FPU/CPU/ARCH names as well as specific support such as HDIV, etc.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "llvm/Support/ARMBuildAttributes.h"
  15. #include "llvm/Support/TargetParser.h"
  16. #include "llvm/ADT/StringExtras.h"
  17. #include "llvm/ADT/StringSwitch.h"
  18. #include <cctype>
  19. using namespace llvm;
  20. namespace {
  21. // List of canonical FPU names (use getFPUSynonym) and which architectural
  22. // features they correspond to (use getFPUFeatures).
  23. // FIXME: TableGen this.
  24. // The entries must appear in the order listed in ARM::FPUKind for correct indexing
  25. struct {
  26. const char * Name;
  27. ARM::FPUKind ID;
  28. ARM::FPUVersion FPUVersion;
  29. ARM::NeonSupportLevel NeonSupport;
  30. ARM::FPURestriction Restriction;
  31. } FPUNames[] = {
  32. { "invalid", ARM::FK_INVALID, ARM::FV_NONE, ARM::NS_None, ARM::FR_None},
  33. { "none", ARM::FK_NONE, ARM::FV_NONE, ARM::NS_None, ARM::FR_None},
  34. { "vfp", ARM::FK_VFP, ARM::FV_VFPV2, ARM::NS_None, ARM::FR_None},
  35. { "vfpv2", ARM::FK_VFPV2, ARM::FV_VFPV2, ARM::NS_None, ARM::FR_None},
  36. { "vfpv3", ARM::FK_VFPV3, ARM::FV_VFPV3, ARM::NS_None, ARM::FR_None},
  37. { "vfpv3-fp16", ARM::FK_VFPV3_FP16, ARM::FV_VFPV3_FP16, ARM::NS_None, ARM::FR_None},
  38. { "vfpv3-d16", ARM::FK_VFPV3_D16, ARM::FV_VFPV3, ARM::NS_None, ARM::FR_D16},
  39. { "vfpv3-d16-fp16", ARM::FK_VFPV3_D16_FP16, ARM::FV_VFPV3_FP16, ARM::NS_None, ARM::FR_D16},
  40. { "vfpv3xd", ARM::FK_VFPV3XD, ARM::FV_VFPV3, ARM::NS_None, ARM::FR_SP_D16},
  41. { "vfpv3xd-fp16", ARM::FK_VFPV3XD_FP16, ARM::FV_VFPV3_FP16, ARM::NS_None, ARM::FR_SP_D16},
  42. { "vfpv4", ARM::FK_VFPV4, ARM::FV_VFPV4, ARM::NS_None, ARM::FR_None},
  43. { "vfpv4-d16", ARM::FK_VFPV4_D16, ARM::FV_VFPV4, ARM::NS_None, ARM::FR_D16},
  44. { "fpv4-sp-d16", ARM::FK_FPV4_SP_D16, ARM::FV_VFPV4, ARM::NS_None, ARM::FR_SP_D16},
  45. { "fpv5-d16", ARM::FK_FPV5_D16, ARM::FV_VFPV5, ARM::NS_None, ARM::FR_D16},
  46. { "fpv5-sp-d16", ARM::FK_FPV5_SP_D16, ARM::FV_VFPV5, ARM::NS_None, ARM::FR_SP_D16},
  47. { "fp-armv8", ARM::FK_FP_ARMV8, ARM::FV_VFPV5, ARM::NS_None, ARM::FR_None},
  48. { "neon", ARM::FK_NEON, ARM::FV_VFPV3, ARM::NS_Neon, ARM::FR_None},
  49. { "neon-fp16", ARM::FK_NEON_FP16, ARM::FV_VFPV3_FP16, ARM::NS_Neon, ARM::FR_None},
  50. { "neon-vfpv4", ARM::FK_NEON_VFPV4, ARM::FV_VFPV4, ARM::NS_Neon, ARM::FR_None},
  51. { "neon-fp-armv8", ARM::FK_NEON_FP_ARMV8, ARM::FV_VFPV5, ARM::NS_Neon, ARM::FR_None},
  52. { "crypto-neon-fp-armv8",
  53. ARM::FK_CRYPTO_NEON_FP_ARMV8, ARM::FV_VFPV5, ARM::NS_Crypto, ARM::FR_None},
  54. { "softvfp", ARM::FK_SOFTVFP, ARM::FV_NONE, ARM::NS_None, ARM::FR_None},
  55. };
  56. // List of canonical arch names (use getArchSynonym).
  57. // This table also provides the build attribute fields for CPU arch
  58. // and Arch ID, according to the Addenda to the ARM ABI, chapters
  59. // 2.4 and 2.3.5.2 respectively.
  60. // FIXME: SubArch values were simplified to fit into the expectations
  61. // of the triples and are not conforming with their official names.
  62. // Check to see if the expectation should be changed.
  63. // FIXME: TableGen this.
  64. struct {
  65. const char *Name;
  66. ARM::ArchKind ID;
  67. const char *CPUAttr; // CPU class in build attributes.
  68. const char *SubArch; // Sub-Arch name.
  69. ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes.
  70. } ARCHNames[] = {
  71. { "invalid", ARM::AK_INVALID, nullptr, nullptr, ARMBuildAttrs::CPUArch::Pre_v4 },
  72. { "armv2", ARM::AK_ARMV2, "2", "v2", ARMBuildAttrs::CPUArch::Pre_v4 },
  73. { "armv2a", ARM::AK_ARMV2A, "2A", "v2a", ARMBuildAttrs::CPUArch::Pre_v4 },
  74. { "armv3", ARM::AK_ARMV3, "3", "v3", ARMBuildAttrs::CPUArch::Pre_v4 },
  75. { "armv3m", ARM::AK_ARMV3M, "3M", "v3m", ARMBuildAttrs::CPUArch::Pre_v4 },
  76. { "armv4", ARM::AK_ARMV4, "4", "v4", ARMBuildAttrs::CPUArch::v4 },
  77. { "armv4t", ARM::AK_ARMV4T, "4T", "v4t", ARMBuildAttrs::CPUArch::v4T },
  78. { "armv5t", ARM::AK_ARMV5T, "5T", "v5", ARMBuildAttrs::CPUArch::v5T },
  79. { "armv5te", ARM::AK_ARMV5TE, "5TE", "v5e", ARMBuildAttrs::CPUArch::v5TE },
  80. { "armv5tej", ARM::AK_ARMV5TEJ, "5TEJ", "v5e", ARMBuildAttrs::CPUArch::v5TEJ },
  81. { "armv6", ARM::AK_ARMV6, "6", "v6", ARMBuildAttrs::CPUArch::v6 },
  82. { "armv6k", ARM::AK_ARMV6K, "6K", "v6k", ARMBuildAttrs::CPUArch::v6K },
  83. { "armv6t2", ARM::AK_ARMV6T2, "6T2", "v6t2", ARMBuildAttrs::CPUArch::v6T2 },
  84. { "armv6z", ARM::AK_ARMV6Z, "6Z", "v6z", ARMBuildAttrs::CPUArch::v6KZ },
  85. { "armv6zk", ARM::AK_ARMV6ZK, "6ZK", "v6zk", ARMBuildAttrs::CPUArch::v6KZ },
  86. { "armv6-m", ARM::AK_ARMV6M, "6-M", "v6m", ARMBuildAttrs::CPUArch::v6_M },
  87. { "armv6s-m", ARM::AK_ARMV6SM, "6S-M", "v6sm", ARMBuildAttrs::CPUArch::v6S_M },
  88. { "armv7-a", ARM::AK_ARMV7A, "7-A", "v7", ARMBuildAttrs::CPUArch::v7 },
  89. { "armv7-r", ARM::AK_ARMV7R, "7-R", "v7r", ARMBuildAttrs::CPUArch::v7 },
  90. { "armv7-m", ARM::AK_ARMV7M, "7-M", "v7m", ARMBuildAttrs::CPUArch::v7 },
  91. { "armv7e-m", ARM::AK_ARMV7EM, "7E-M", "v7em", ARMBuildAttrs::CPUArch::v7E_M },
  92. { "armv8-a", ARM::AK_ARMV8A, "8-A", "v8", ARMBuildAttrs::CPUArch::v8 },
  93. { "armv8.1-a", ARM::AK_ARMV8_1A, "8.1-A", "v8.1a", ARMBuildAttrs::CPUArch::v8 },
  94. // Non-standard Arch names.
  95. { "iwmmxt", ARM::AK_IWMMXT, "iwmmxt", "", ARMBuildAttrs::CPUArch::v5TE },
  96. { "iwmmxt2", ARM::AK_IWMMXT2, "iwmmxt2", "", ARMBuildAttrs::CPUArch::v5TE },
  97. { "xscale", ARM::AK_XSCALE, "xscale", "", ARMBuildAttrs::CPUArch::v5TE },
  98. { "armv5", ARM::AK_ARMV5, "5T", "v5", ARMBuildAttrs::CPUArch::v5T },
  99. { "armv5e", ARM::AK_ARMV5E, "5TE", "v5e", ARMBuildAttrs::CPUArch::v5TE },
  100. { "armv6j", ARM::AK_ARMV6J, "6J", "v6", ARMBuildAttrs::CPUArch::v6 },
  101. { "armv6hl", ARM::AK_ARMV6HL, "6-M", "v6hl", ARMBuildAttrs::CPUArch::v6_M },
  102. { "armv7", ARM::AK_ARMV7, "7", "v7", ARMBuildAttrs::CPUArch::v7 },
  103. { "armv7l", ARM::AK_ARMV7L, "7-L", "v7l", ARMBuildAttrs::CPUArch::v7 },
  104. { "armv7hl", ARM::AK_ARMV7HL, "7-L", "v7hl", ARMBuildAttrs::CPUArch::v7 },
  105. { "armv7s", ARM::AK_ARMV7S, "7-S", "v7s", ARMBuildAttrs::CPUArch::v7 }
  106. };
  107. // List of Arch Extension names.
  108. // FIXME: TableGen this.
  109. struct {
  110. const char *Name;
  111. ARM::ArchExtKind ID;
  112. } ARCHExtNames[] = {
  113. { "invalid", ARM::AEK_INVALID },
  114. { "crc", ARM::AEK_CRC },
  115. { "crypto", ARM::AEK_CRYPTO },
  116. { "fp", ARM::AEK_FP },
  117. { "idiv", ARM::AEK_HWDIV },
  118. { "mp", ARM::AEK_MP },
  119. { "simd", ARM::AEK_SIMD },
  120. { "sec", ARM::AEK_SEC },
  121. { "virt", ARM::AEK_VIRT },
  122. { "os", ARM::AEK_OS },
  123. { "iwmmxt", ARM::AEK_IWMMXT },
  124. { "iwmmxt2", ARM::AEK_IWMMXT2 },
  125. { "maverick", ARM::AEK_MAVERICK },
  126. { "xscale", ARM::AEK_XSCALE }
  127. };
  128. // List of CPU names and their arches.
  129. // The same CPU can have multiple arches and can be default on multiple arches.
  130. // When finding the Arch for a CPU, first-found prevails. Sort them accordingly.
  131. // When this becomes table-generated, we'd probably need two tables.
  132. // FIXME: TableGen this.
  133. struct {
  134. const char *Name;
  135. ARM::ArchKind ArchID;
  136. bool Default;
  137. } CPUNames[] = {
  138. { "arm2", ARM::AK_ARMV2, true },
  139. { "arm3", ARM::AK_ARMV2A, true },
  140. { "arm6", ARM::AK_ARMV3, true },
  141. { "arm7m", ARM::AK_ARMV3M, true },
  142. { "arm8", ARM::AK_ARMV4, false },
  143. { "arm810", ARM::AK_ARMV4, false },
  144. { "strongarm", ARM::AK_ARMV4, true },
  145. { "strongarm110", ARM::AK_ARMV4, false },
  146. { "strongarm1100", ARM::AK_ARMV4, false },
  147. { "strongarm1110", ARM::AK_ARMV4, false },
  148. { "arm7tdmi", ARM::AK_ARMV4T, true },
  149. { "arm7tdmi-s", ARM::AK_ARMV4T, false },
  150. { "arm710t", ARM::AK_ARMV4T, false },
  151. { "arm720t", ARM::AK_ARMV4T, false },
  152. { "arm9", ARM::AK_ARMV4T, false },
  153. { "arm9tdmi", ARM::AK_ARMV4T, false },
  154. { "arm920", ARM::AK_ARMV4T, false },
  155. { "arm920t", ARM::AK_ARMV4T, false },
  156. { "arm922t", ARM::AK_ARMV4T, false },
  157. { "arm9312", ARM::AK_ARMV4T, false },
  158. { "arm940t", ARM::AK_ARMV4T, false },
  159. { "ep9312", ARM::AK_ARMV4T, false },
  160. { "arm10tdmi", ARM::AK_ARMV5T, true },
  161. { "arm1020t", ARM::AK_ARMV5T, false },
  162. { "arm9e", ARM::AK_ARMV5TE, false },
  163. { "arm946e-s", ARM::AK_ARMV5TE, false },
  164. { "arm966e-s", ARM::AK_ARMV5TE, false },
  165. { "arm968e-s", ARM::AK_ARMV5TE, false },
  166. { "arm10e", ARM::AK_ARMV5TE, false },
  167. { "arm1020e", ARM::AK_ARMV5TE, false },
  168. { "arm1022e", ARM::AK_ARMV5TE, true },
  169. { "iwmmxt", ARM::AK_ARMV5TE, false },
  170. { "xscale", ARM::AK_ARMV5TE, false },
  171. { "arm926ej-s", ARM::AK_ARMV5TEJ, true },
  172. { "arm1136jf-s", ARM::AK_ARMV6, true },
  173. { "arm1176j-s", ARM::AK_ARMV6K, false },
  174. { "arm1176jz-s", ARM::AK_ARMV6K, false },
  175. { "mpcore", ARM::AK_ARMV6K, false },
  176. { "mpcorenovfp", ARM::AK_ARMV6K, false },
  177. { "arm1176jzf-s", ARM::AK_ARMV6K, true },
  178. { "arm1176jzf-s", ARM::AK_ARMV6Z, true },
  179. { "arm1176jzf-s", ARM::AK_ARMV6ZK, true },
  180. { "arm1156t2-s", ARM::AK_ARMV6T2, true },
  181. { "arm1156t2f-s", ARM::AK_ARMV6T2, false },
  182. { "cortex-m0", ARM::AK_ARMV6M, true },
  183. { "cortex-m0plus", ARM::AK_ARMV6M, false },
  184. { "cortex-m1", ARM::AK_ARMV6M, false },
  185. { "sc000", ARM::AK_ARMV6M, false },
  186. { "cortex-a5", ARM::AK_ARMV7A, false },
  187. { "cortex-a7", ARM::AK_ARMV7A, false },
  188. { "cortex-a8", ARM::AK_ARMV7A, true },
  189. { "cortex-a9", ARM::AK_ARMV7A, false },
  190. { "cortex-a12", ARM::AK_ARMV7A, false },
  191. { "cortex-a15", ARM::AK_ARMV7A, false },
  192. { "cortex-a17", ARM::AK_ARMV7A, false },
  193. { "krait", ARM::AK_ARMV7A, false },
  194. { "cortex-r4", ARM::AK_ARMV7R, true },
  195. { "cortex-r4f", ARM::AK_ARMV7R, false },
  196. { "cortex-r5", ARM::AK_ARMV7R, false },
  197. { "cortex-r7", ARM::AK_ARMV7R, false },
  198. { "sc300", ARM::AK_ARMV7M, false },
  199. { "cortex-m3", ARM::AK_ARMV7M, true },
  200. { "cortex-m4", ARM::AK_ARMV7EM, true },
  201. { "cortex-m7", ARM::AK_ARMV7EM, false },
  202. { "cortex-a53", ARM::AK_ARMV8A, true },
  203. { "cortex-a57", ARM::AK_ARMV8A, false },
  204. { "cortex-a72", ARM::AK_ARMV8A, false },
  205. { "cyclone", ARM::AK_ARMV8A, false },
  206. { "generic", ARM::AK_ARMV8_1A, true },
  207. // Non-standard Arch names.
  208. { "iwmmxt", ARM::AK_IWMMXT, true },
  209. { "xscale", ARM::AK_XSCALE, true },
  210. { "arm10tdmi", ARM::AK_ARMV5, true },
  211. { "arm1022e", ARM::AK_ARMV5E, true },
  212. { "arm1136j-s", ARM::AK_ARMV6J, true },
  213. { "arm1136jz-s", ARM::AK_ARMV6J, false },
  214. { "cortex-m0", ARM::AK_ARMV6SM, true },
  215. { "arm1176jzf-s", ARM::AK_ARMV6HL, true },
  216. { "cortex-a8", ARM::AK_ARMV7, true },
  217. { "cortex-a8", ARM::AK_ARMV7L, true },
  218. { "cortex-a8", ARM::AK_ARMV7HL, true },
  219. { "cortex-m4", ARM::AK_ARMV7EM, true },
  220. { "swift", ARM::AK_ARMV7S, true },
  221. // Invalid CPU
  222. { "invalid", ARM::AK_INVALID, true }
  223. };
  224. } // namespace
  225. // ======================================================= //
  226. // Information by ID
  227. // ======================================================= //
  228. const char *ARMTargetParser::getFPUName(unsigned FPUKind) {
  229. if (FPUKind >= ARM::FK_LAST)
  230. return nullptr;
  231. return FPUNames[FPUKind].Name;
  232. }
  233. unsigned ARMTargetParser::getFPUVersion(unsigned FPUKind) {
  234. if (FPUKind >= ARM::FK_LAST)
  235. return 0;
  236. return FPUNames[FPUKind].FPUVersion;
  237. }
  238. unsigned ARMTargetParser::getFPUNeonSupportLevel(unsigned FPUKind) {
  239. if (FPUKind >= ARM::FK_LAST)
  240. return 0;
  241. return FPUNames[FPUKind].NeonSupport;
  242. }
  243. unsigned ARMTargetParser::getFPURestriction(unsigned FPUKind) {
  244. if (FPUKind >= ARM::FK_LAST)
  245. return 0;
  246. return FPUNames[FPUKind].Restriction;
  247. }
  248. bool ARMTargetParser::getFPUFeatures(unsigned FPUKind,
  249. std::vector<const char *> &Features) {
  250. if (FPUKind >= ARM::FK_LAST || FPUKind == ARM::FK_INVALID)
  251. return false;
  252. // fp-only-sp and d16 subtarget features are independent of each other, so we
  253. // must enable/disable both.
  254. switch (FPUNames[FPUKind].Restriction) {
  255. case ARM::FR_SP_D16:
  256. Features.push_back("+fp-only-sp");
  257. Features.push_back("+d16");
  258. break;
  259. case ARM::FR_D16:
  260. Features.push_back("-fp-only-sp");
  261. Features.push_back("+d16");
  262. break;
  263. case ARM::FR_None:
  264. Features.push_back("-fp-only-sp");
  265. Features.push_back("-d16");
  266. break;
  267. }
  268. // FPU version subtarget features are inclusive of lower-numbered ones, so
  269. // enable the one corresponding to this version and disable all that are
  270. // higher. We also have to make sure to disable fp16 when vfp4 is disabled,
  271. // as +vfp4 implies +fp16 but -vfp4 does not imply -fp16.
  272. switch (FPUNames[FPUKind].FPUVersion) {
  273. case ARM::FV_VFPV5:
  274. Features.push_back("+fp-armv8");
  275. break;
  276. case ARM::FV_VFPV4:
  277. Features.push_back("+vfp4");
  278. Features.push_back("-fp-armv8");
  279. break;
  280. case ARM::FV_VFPV3_FP16:
  281. Features.push_back("+vfp3");
  282. Features.push_back("+fp16");
  283. Features.push_back("-vfp4");
  284. Features.push_back("-fp-armv8");
  285. break;
  286. case ARM::FV_VFPV3:
  287. Features.push_back("+vfp3");
  288. Features.push_back("-fp16");
  289. Features.push_back("-vfp4");
  290. Features.push_back("-fp-armv8");
  291. break;
  292. case ARM::FV_VFPV2:
  293. Features.push_back("+vfp2");
  294. Features.push_back("-vfp3");
  295. Features.push_back("-fp16");
  296. Features.push_back("-vfp4");
  297. Features.push_back("-fp-armv8");
  298. break;
  299. case ARM::FV_NONE:
  300. Features.push_back("-vfp2");
  301. Features.push_back("-vfp3");
  302. Features.push_back("-fp16");
  303. Features.push_back("-vfp4");
  304. Features.push_back("-fp-armv8");
  305. break;
  306. }
  307. // crypto includes neon, so we handle this similarly to FPU version.
  308. switch (FPUNames[FPUKind].NeonSupport) {
  309. case ARM::NS_Crypto:
  310. Features.push_back("+crypto");
  311. break;
  312. case ARM::NS_Neon:
  313. Features.push_back("+neon");
  314. Features.push_back("-crypto");
  315. break;
  316. case ARM::NS_None:
  317. Features.push_back("-neon");
  318. Features.push_back("-crypto");
  319. break;
  320. }
  321. return true;
  322. }
  323. const char *ARMTargetParser::getArchName(unsigned ArchKind) {
  324. if (ArchKind >= ARM::AK_LAST)
  325. return nullptr;
  326. return ARCHNames[ArchKind].Name;
  327. }
  328. const char *ARMTargetParser::getCPUAttr(unsigned ArchKind) {
  329. if (ArchKind >= ARM::AK_LAST)
  330. return nullptr;
  331. return ARCHNames[ArchKind].CPUAttr;
  332. }
  333. const char *ARMTargetParser::getSubArch(unsigned ArchKind) {
  334. if (ArchKind >= ARM::AK_LAST)
  335. return nullptr;
  336. return ARCHNames[ArchKind].SubArch;
  337. }
  338. unsigned ARMTargetParser::getArchAttr(unsigned ArchKind) {
  339. if (ArchKind >= ARM::AK_LAST)
  340. return ARMBuildAttrs::CPUArch::Pre_v4;
  341. return ARCHNames[ArchKind].ArchAttr;
  342. }
  343. const char *ARMTargetParser::getArchExtName(unsigned ArchExtKind) {
  344. if (ArchExtKind >= ARM::AEK_LAST)
  345. return nullptr;
  346. return ARCHExtNames[ArchExtKind].Name;
  347. }
  348. const char *ARMTargetParser::getDefaultCPU(StringRef Arch) {
  349. unsigned AK = parseArch(Arch);
  350. if (AK == ARM::AK_INVALID)
  351. return nullptr;
  352. // Look for multiple AKs to find the default for pair AK+Name.
  353. for (const auto CPU : CPUNames) {
  354. if (CPU.ArchID == AK && CPU.Default)
  355. return CPU.Name;
  356. }
  357. return nullptr;
  358. }
  359. // ======================================================= //
  360. // Parsers
  361. // ======================================================= //
  362. StringRef ARMTargetParser::getFPUSynonym(StringRef FPU) {
  363. return StringSwitch<StringRef>(FPU)
  364. .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported
  365. .Case("vfp2", "vfpv2")
  366. .Case("vfp3", "vfpv3")
  367. .Case("vfp4", "vfpv4")
  368. .Case("vfp3-d16", "vfpv3-d16")
  369. .Case("vfp4-d16", "vfpv4-d16")
  370. .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16")
  371. .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16")
  372. .Case("fp5-sp-d16", "fpv5-sp-d16")
  373. .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16")
  374. // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3.
  375. .Case("neon-vfpv3", "neon")
  376. .Default(FPU);
  377. }
  378. StringRef ARMTargetParser::getArchSynonym(StringRef Arch) {
  379. return StringSwitch<StringRef>(Arch)
  380. .Case("v6sm", "v6s-m")
  381. .Case("v6m", "v6-m")
  382. .Case("v7a", "v7-a")
  383. .Case("v7r", "v7-r")
  384. .Case("v7m", "v7-m")
  385. .Case("v7em", "v7e-m")
  386. .Cases("v8", "v8a", "aarch64", "arm64", "v8-a")
  387. .Case("v8.1a", "v8.1-a")
  388. .Default(Arch);
  389. }
  390. // MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but
  391. // (iwmmxt|xscale)(eb)? is also permitted. If the former, return
  392. // "v.+", if the latter, return unmodified string, minus 'eb'.
  393. // If invalid, return empty string.
  394. StringRef ARMTargetParser::getCanonicalArchName(StringRef Arch) {
  395. size_t offset = StringRef::npos;
  396. StringRef A = Arch;
  397. StringRef Error = "";
  398. // Begins with "arm" / "thumb", move past it.
  399. if (A.startswith("arm64"))
  400. offset = 5;
  401. else if (A.startswith("arm"))
  402. offset = 3;
  403. else if (A.startswith("thumb"))
  404. offset = 5;
  405. else if (A.startswith("aarch64")) {
  406. offset = 7;
  407. // AArch64 uses "_be", not "eb" suffix.
  408. if (A.find("eb") != StringRef::npos)
  409. return Error;
  410. if (A.substr(offset,3) == "_be")
  411. offset += 3;
  412. }
  413. // Ex. "armebv7", move past the "eb".
  414. if (offset != StringRef::npos && A.substr(offset, 2) == "eb")
  415. offset += 2;
  416. // Or, if it ends with eb ("armv7eb"), chop it off.
  417. else if (A.endswith("eb"))
  418. A = A.substr(0, A.size() - 2);
  419. // Trim the head
  420. if (offset != StringRef::npos)
  421. A = A.substr(offset);
  422. // Empty string means offset reached the end, which means it's valid.
  423. if (A.empty())
  424. return Arch;
  425. // Only match non-marketing names
  426. if (offset != StringRef::npos) {
  427. // Must start with 'vN'.
  428. if (A[0] != 'v' || !std::isdigit(A[1]))
  429. return Error;
  430. // Can't have an extra 'eb'.
  431. if (A.find("eb") != StringRef::npos)
  432. return Error;
  433. }
  434. // Arch will either be a 'v' name (v7a) or a marketing name (xscale).
  435. return A;
  436. }
  437. unsigned ARMTargetParser::parseFPU(StringRef FPU) {
  438. StringRef Syn = getFPUSynonym(FPU);
  439. for (const auto F : FPUNames) {
  440. if (Syn == F.Name)
  441. return F.ID;
  442. }
  443. return ARM::FK_INVALID;
  444. }
  445. // Allows partial match, ex. "v7a" matches "armv7a".
  446. unsigned ARMTargetParser::parseArch(StringRef Arch) {
  447. Arch = getCanonicalArchName(Arch);
  448. StringRef Syn = getArchSynonym(Arch);
  449. for (const auto A : ARCHNames) {
  450. if (StringRef(A.Name).endswith(Syn))
  451. return A.ID;
  452. }
  453. return ARM::AK_INVALID;
  454. }
  455. unsigned ARMTargetParser::parseArchExt(StringRef ArchExt) {
  456. for (const auto A : ARCHExtNames) {
  457. if (ArchExt == A.Name)
  458. return A.ID;
  459. }
  460. return ARM::AEK_INVALID;
  461. }
  462. unsigned ARMTargetParser::parseCPUArch(StringRef CPU) {
  463. for (const auto C : CPUNames) {
  464. if (CPU == C.Name)
  465. return C.ArchID;
  466. }
  467. return ARM::AK_INVALID;
  468. }
  469. // ARM, Thumb, AArch64
  470. unsigned ARMTargetParser::parseArchISA(StringRef Arch) {
  471. return StringSwitch<unsigned>(Arch)
  472. .StartsWith("aarch64", ARM::IK_AARCH64)
  473. .StartsWith("arm64", ARM::IK_AARCH64)
  474. .StartsWith("thumb", ARM::IK_THUMB)
  475. .StartsWith("arm", ARM::IK_ARM)
  476. .Default(ARM::EK_INVALID);
  477. }
  478. // Little/Big endian
  479. unsigned ARMTargetParser::parseArchEndian(StringRef Arch) {
  480. if (Arch.startswith("armeb") ||
  481. Arch.startswith("thumbeb") ||
  482. Arch.startswith("aarch64_be"))
  483. return ARM::EK_BIG;
  484. if (Arch.startswith("arm") || Arch.startswith("thumb")) {
  485. if (Arch.endswith("eb"))
  486. return ARM::EK_BIG;
  487. else
  488. return ARM::EK_LITTLE;
  489. }
  490. if (Arch.startswith("aarch64"))
  491. return ARM::EK_LITTLE;
  492. return ARM::EK_INVALID;
  493. }
  494. // Profile A/R/M
  495. unsigned ARMTargetParser::parseArchProfile(StringRef Arch) {
  496. Arch = getCanonicalArchName(Arch);
  497. switch(parseArch(Arch)) {
  498. case ARM::AK_ARMV6M:
  499. case ARM::AK_ARMV7M:
  500. case ARM::AK_ARMV6SM:
  501. case ARM::AK_ARMV7EM:
  502. return ARM::PK_M;
  503. case ARM::AK_ARMV7R:
  504. return ARM::PK_R;
  505. case ARM::AK_ARMV7:
  506. case ARM::AK_ARMV7A:
  507. case ARM::AK_ARMV8A:
  508. case ARM::AK_ARMV8_1A:
  509. return ARM::PK_A;
  510. }
  511. return ARM::PK_INVALID;
  512. }
  513. // Version number (ex. v7 = 7).
  514. unsigned ARMTargetParser::parseArchVersion(StringRef Arch) {
  515. Arch = getCanonicalArchName(Arch);
  516. switch(parseArch(Arch)) {
  517. case ARM::AK_ARMV2:
  518. case ARM::AK_ARMV2A:
  519. return 2;
  520. case ARM::AK_ARMV3:
  521. case ARM::AK_ARMV3M:
  522. return 3;
  523. case ARM::AK_ARMV4:
  524. case ARM::AK_ARMV4T:
  525. return 4;
  526. case ARM::AK_ARMV5:
  527. case ARM::AK_ARMV5T:
  528. case ARM::AK_ARMV5TE:
  529. case ARM::AK_IWMMXT:
  530. case ARM::AK_IWMMXT2:
  531. case ARM::AK_XSCALE:
  532. case ARM::AK_ARMV5E:
  533. case ARM::AK_ARMV5TEJ:
  534. return 5;
  535. case ARM::AK_ARMV6:
  536. case ARM::AK_ARMV6J:
  537. case ARM::AK_ARMV6K:
  538. case ARM::AK_ARMV6T2:
  539. case ARM::AK_ARMV6Z:
  540. case ARM::AK_ARMV6ZK:
  541. case ARM::AK_ARMV6M:
  542. case ARM::AK_ARMV6SM:
  543. case ARM::AK_ARMV6HL:
  544. return 6;
  545. case ARM::AK_ARMV7:
  546. case ARM::AK_ARMV7A:
  547. case ARM::AK_ARMV7R:
  548. case ARM::AK_ARMV7M:
  549. case ARM::AK_ARMV7L:
  550. case ARM::AK_ARMV7HL:
  551. case ARM::AK_ARMV7S:
  552. case ARM::AK_ARMV7EM:
  553. return 7;
  554. case ARM::AK_ARMV8A:
  555. case ARM::AK_ARMV8_1A:
  556. return 8;
  557. }
  558. return 0;
  559. }