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 15 #include "llvm/Support/ARMBuildAttributes.h" 16 #include "llvm/Support/TargetParser.h" 17 #include "llvm/ADT/StringExtras.h" 18 #include "llvm/ADT/StringSwitch.h" 19 #include <cctype> 20 21 using namespace llvm; 22 using namespace ARM; 23 24 namespace { 25 26 // List of canonical FPU names (use getFPUSynonym) and which architectural 27 // features they correspond to (use getFPUFeatures). 28 // FIXME: TableGen this. 29 // The entries must appear in the order listed in ARM::FPUKind for correct indexing 30 struct { 31 const char *NameCStr; 32 size_t NameLength; 33 ARM::FPUKind ID; 34 ARM::FPUVersion FPUVersion; 35 ARM::NeonSupportLevel NeonSupport; 36 ARM::FPURestriction Restriction; 37 38 StringRef getName() const { return StringRef(NameCStr, NameLength); } 39 } FPUNames[] = { 40 #define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \ 41 { NAME, sizeof(NAME) - 1, KIND, VERSION, NEON_SUPPORT, RESTRICTION }, 42 #include "llvm/Support/ARMTargetParser.def" 43 }; 44 45 // List of canonical arch names (use getArchSynonym). 46 // This table also provides the build attribute fields for CPU arch 47 // and Arch ID, according to the Addenda to the ARM ABI, chapters 48 // 2.4 and 2.3.5.2 respectively. 49 // FIXME: SubArch values were simplified to fit into the expectations 50 // of the triples and are not conforming with their official names. 51 // Check to see if the expectation should be changed. 52 // FIXME: TableGen this. 53 struct { 54 const char *NameCStr; 55 size_t NameLength; 56 ARM::ArchKind ID; 57 const char *CPUAttrCStr; 58 size_t CPUAttrLength; 59 const char *SubArchCStr; 60 size_t SubArchLength; 61 ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes. 62 unsigned ArchBaseExtensions; 63 64 StringRef getName() const { return StringRef(NameCStr, NameLength); } 65 66 // CPU class in build attributes. 67 StringRef getCPUAttr() const { return StringRef(CPUAttrCStr, CPUAttrLength); } 68 69 // Sub-Arch name. 70 StringRef getSubArch() const { return StringRef(SubArchCStr, SubArchLength); } 71 } ARCHNames[] = { 72 #define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_BASE_EXT) \ 73 {NAME, sizeof(NAME) - 1, ID, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH, \ 74 sizeof(SUB_ARCH) - 1, ARCH_ATTR, ARCH_BASE_EXT}, 75 #include "llvm/Support/ARMTargetParser.def" 76 }; 77 78 // List of Arch Extension names. 79 // FIXME: TableGen this. 80 struct { 81 const char *NameCStr; 82 size_t NameLength; 83 unsigned ID; 84 85 StringRef getName() const { return StringRef(NameCStr, NameLength); } 86 } ARCHExtNames[] = { 87 #define ARM_ARCH_EXT_NAME(NAME, ID) { NAME, sizeof(NAME) - 1, ID }, 88 #include "llvm/Support/ARMTargetParser.def" 89 }; 90 91 // List of HWDiv names (use getHWDivSynonym) and which architectural 92 // features they correspond to (use getHWDivFeatures). 93 // FIXME: TableGen this. 94 struct { 95 const char *NameCStr; 96 size_t NameLength; 97 unsigned ID; 98 99 StringRef getName() const { return StringRef(NameCStr, NameLength); } 100 } HWDivNames[] = { 101 #define ARM_HW_DIV_NAME(NAME, ID) { NAME, sizeof(NAME) - 1, ID }, 102 #include "llvm/Support/ARMTargetParser.def" 103 }; 104 105 // List of CPU names and their arches. 106 // The same CPU can have multiple arches and can be default on multiple arches. 107 // When finding the Arch for a CPU, first-found prevails. Sort them accordingly. 108 // When this becomes table-generated, we'd probably need two tables. 109 // FIXME: TableGen this. 110 struct { 111 const char *NameCStr; 112 size_t NameLength; 113 ARM::ArchKind ArchID; 114 bool Default; // is $Name the default CPU for $ArchID ? 115 unsigned DefaultExtensions; 116 117 StringRef getName() const { return StringRef(NameCStr, NameLength); } 118 } CPUNames[] = { 119 #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ 120 { NAME, sizeof(NAME) - 1, ID, IS_DEFAULT, DEFAULT_EXT }, 121 #include "llvm/Support/ARMTargetParser.def" 122 }; 123 124 } // namespace 125 126 // ======================================================= // 127 // Information by ID 128 // ======================================================= // 129 130 StringRef llvm::ARM::getFPUName(unsigned FPUKind) { 131 if (FPUKind >= ARM::FK_LAST) 132 return StringRef(); 133 return FPUNames[FPUKind].getName(); 134 } 135 136 unsigned llvm::ARM::getFPUVersion(unsigned FPUKind) { 137 if (FPUKind >= ARM::FK_LAST) 138 return 0; 139 return FPUNames[FPUKind].FPUVersion; 140 } 141 142 unsigned llvm::ARM::getFPUNeonSupportLevel(unsigned FPUKind) { 143 if (FPUKind >= ARM::FK_LAST) 144 return 0; 145 return FPUNames[FPUKind].NeonSupport; 146 } 147 148 unsigned llvm::ARM::getFPURestriction(unsigned FPUKind) { 149 if (FPUKind >= ARM::FK_LAST) 150 return 0; 151 return FPUNames[FPUKind].Restriction; 152 } 153 154 unsigned llvm::ARM::getDefaultFPU(StringRef CPU) { 155 return StringSwitch<unsigned>(CPU) 156 #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ 157 .Case(NAME, DEFAULT_FPU) 158 #include "llvm/Support/ARMTargetParser.def" 159 .Default(ARM::FK_INVALID); 160 } 161 162 bool llvm::ARM::getHWDivFeatures(unsigned HWDivKind, 163 std::vector<const char *> &Features) { 164 165 if (HWDivKind == ARM::AEK_INVALID) 166 return false; 167 168 if (HWDivKind & ARM::AEK_HWDIVARM) 169 Features.push_back("+hwdiv-arm"); 170 else 171 Features.push_back("-hwdiv-arm"); 172 173 if (HWDivKind & ARM::AEK_HWDIV) 174 Features.push_back("+hwdiv"); 175 else 176 Features.push_back("-hwdiv"); 177 178 return true; 179 } 180 181 bool llvm::ARM::getExtensionFeatures(unsigned Extensions, 182 std::vector<const char *> &Features) { 183 184 if (Extensions == ARM::AEK_INVALID) 185 return false; 186 187 if (Extensions & ARM::AEK_CRC) 188 Features.push_back("+crc"); 189 else 190 Features.push_back("-crc"); 191 192 return getHWDivFeatures(Extensions, Features); 193 } 194 195 bool llvm::ARM::getFPUFeatures(unsigned FPUKind, 196 std::vector<const char *> &Features) { 197 198 if (FPUKind >= ARM::FK_LAST || FPUKind == ARM::FK_INVALID) 199 return false; 200 201 // fp-only-sp and d16 subtarget features are independent of each other, so we 202 // must enable/disable both. 203 switch (FPUNames[FPUKind].Restriction) { 204 case ARM::FR_SP_D16: 205 Features.push_back("+fp-only-sp"); 206 Features.push_back("+d16"); 207 break; 208 case ARM::FR_D16: 209 Features.push_back("-fp-only-sp"); 210 Features.push_back("+d16"); 211 break; 212 case ARM::FR_None: 213 Features.push_back("-fp-only-sp"); 214 Features.push_back("-d16"); 215 break; 216 } 217 218 // FPU version subtarget features are inclusive of lower-numbered ones, so 219 // enable the one corresponding to this version and disable all that are 220 // higher. We also have to make sure to disable fp16 when vfp4 is disabled, 221 // as +vfp4 implies +fp16 but -vfp4 does not imply -fp16. 222 switch (FPUNames[FPUKind].FPUVersion) { 223 case ARM::FV_VFPV5: 224 Features.push_back("+fp-armv8"); 225 break; 226 case ARM::FV_VFPV4: 227 Features.push_back("+vfp4"); 228 Features.push_back("-fp-armv8"); 229 break; 230 case ARM::FV_VFPV3_FP16: 231 Features.push_back("+vfp3"); 232 Features.push_back("+fp16"); 233 Features.push_back("-vfp4"); 234 Features.push_back("-fp-armv8"); 235 break; 236 case ARM::FV_VFPV3: 237 Features.push_back("+vfp3"); 238 Features.push_back("-fp16"); 239 Features.push_back("-vfp4"); 240 Features.push_back("-fp-armv8"); 241 break; 242 case ARM::FV_VFPV2: 243 Features.push_back("+vfp2"); 244 Features.push_back("-vfp3"); 245 Features.push_back("-fp16"); 246 Features.push_back("-vfp4"); 247 Features.push_back("-fp-armv8"); 248 break; 249 case ARM::FV_NONE: 250 Features.push_back("-vfp2"); 251 Features.push_back("-vfp3"); 252 Features.push_back("-fp16"); 253 Features.push_back("-vfp4"); 254 Features.push_back("-fp-armv8"); 255 break; 256 } 257 258 // crypto includes neon, so we handle this similarly to FPU version. 259 switch (FPUNames[FPUKind].NeonSupport) { 260 case ARM::NS_Crypto: 261 Features.push_back("+neon"); 262 Features.push_back("+crypto"); 263 break; 264 case ARM::NS_Neon: 265 Features.push_back("+neon"); 266 Features.push_back("-crypto"); 267 break; 268 case ARM::NS_None: 269 Features.push_back("-neon"); 270 Features.push_back("-crypto"); 271 break; 272 } 273 274 return true; 275 } 276 277 StringRef llvm::ARM::getArchName(unsigned ArchKind) { 278 if (ArchKind >= ARM::AK_LAST) 279 return StringRef(); 280 return ARCHNames[ArchKind].getName(); 281 } 282 283 StringRef llvm::ARM::getCPUAttr(unsigned ArchKind) { 284 if (ArchKind >= ARM::AK_LAST) 285 return StringRef(); 286 return ARCHNames[ArchKind].getCPUAttr(); 287 } 288 289 StringRef llvm::ARM::getSubArch(unsigned ArchKind) { 290 if (ArchKind >= ARM::AK_LAST) 291 return StringRef(); 292 return ARCHNames[ArchKind].getSubArch(); 293 } 294 295 unsigned llvm::ARM::getArchAttr(unsigned ArchKind) { 296 if (ArchKind >= ARM::AK_LAST) 297 return ARMBuildAttrs::CPUArch::Pre_v4; 298 return ARCHNames[ArchKind].ArchAttr; 299 } 300 301 StringRef llvm::ARM::getArchExtName(unsigned ArchExtKind) { 302 for (const auto AE : ARCHExtNames) { 303 if (ArchExtKind == AE.ID) 304 return AE.getName(); 305 } 306 return StringRef(); 307 } 308 309 StringRef llvm::ARM::getHWDivName(unsigned HWDivKind) { 310 for (const auto D : HWDivNames) { 311 if (HWDivKind == D.ID) 312 return D.getName(); 313 } 314 return StringRef(); 315 } 316 317 unsigned llvm::ARM::getDefaultExtensions(StringRef CPU) { 318 for (const auto C : CPUNames) { 319 if (CPU == C.getName()) 320 return (ARCHNames[C.ArchID].ArchBaseExtensions | C.DefaultExtensions); 321 } 322 return ARM::AEK_INVALID; 323 } 324 325 StringRef llvm::ARM::getDefaultCPU(StringRef Arch) { 326 unsigned AK = parseArch(Arch); 327 if (AK == ARM::AK_INVALID) 328 return StringRef(); 329 330 // Look for multiple AKs to find the default for pair AK+Name. 331 for (const auto CPU : CPUNames) { 332 if (CPU.ArchID == AK && CPU.Default) 333 return CPU.getName(); 334 } 335 return StringRef(); 336 } 337 338 // ======================================================= // 339 // Parsers 340 // ======================================================= // 341 342 static StringRef getHWDivSynonym(StringRef HWDiv) { 343 return StringSwitch<StringRef>(HWDiv) 344 .Case("thumb,arm", "arm,thumb") 345 .Default(HWDiv); 346 } 347 348 static StringRef getFPUSynonym(StringRef FPU) { 349 return StringSwitch<StringRef>(FPU) 350 .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported 351 .Case("vfp2", "vfpv2") 352 .Case("vfp3", "vfpv3") 353 .Case("vfp4", "vfpv4") 354 .Case("vfp3-d16", "vfpv3-d16") 355 .Case("vfp4-d16", "vfpv4-d16") 356 .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16") 357 .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16") 358 .Case("fp5-sp-d16", "fpv5-sp-d16") 359 .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16") 360 // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3. 361 .Case("neon-vfpv3", "neon") 362 .Default(FPU); 363 } 364 365 static StringRef getArchSynonym(StringRef Arch) { 366 return StringSwitch<StringRef>(Arch) 367 .Case("v6sm", "v6s-m") 368 .Case("v6m", "v6-m") 369 .Case("v7a", "v7-a") 370 .Case("v7r", "v7-r") 371 .Case("v7m", "v7-m") 372 .Case("v7em", "v7e-m") 373 .Cases("v8", "v8a", "aarch64", "arm64", "v8-a") 374 .Case("v8.1a", "v8.1-a") 375 .Default(Arch); 376 } 377 378 // MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but 379 // (iwmmxt|xscale)(eb)? is also permitted. If the former, return 380 // "v.+", if the latter, return unmodified string, minus 'eb'. 381 // If invalid, return empty string. 382 StringRef llvm::ARM::getCanonicalArchName(StringRef Arch) { 383 size_t offset = StringRef::npos; 384 StringRef A = Arch; 385 StringRef Error = ""; 386 387 // Begins with "arm" / "thumb", move past it. 388 if (A.startswith("arm64")) 389 offset = 5; 390 else if (A.startswith("arm")) 391 offset = 3; 392 else if (A.startswith("thumb")) 393 offset = 5; 394 else if (A.startswith("aarch64")) { 395 offset = 7; 396 // AArch64 uses "_be", not "eb" suffix. 397 if (A.find("eb") != StringRef::npos) 398 return Error; 399 if (A.substr(offset, 3) == "_be") 400 offset += 3; 401 } 402 403 // Ex. "armebv7", move past the "eb". 404 if (offset != StringRef::npos && A.substr(offset, 2) == "eb") 405 offset += 2; 406 // Or, if it ends with eb ("armv7eb"), chop it off. 407 else if (A.endswith("eb")) 408 A = A.substr(0, A.size() - 2); 409 // Trim the head 410 if (offset != StringRef::npos) 411 A = A.substr(offset); 412 413 // Empty string means offset reached the end, which means it's valid. 414 if (A.empty()) 415 return Arch; 416 417 // Only match non-marketing names 418 if (offset != StringRef::npos) { 419 // Must start with 'vN'. 420 if (A[0] != 'v' || !std::isdigit(A[1])) 421 return Error; 422 // Can't have an extra 'eb'. 423 if (A.find("eb") != StringRef::npos) 424 return Error; 425 } 426 427 // Arch will either be a 'v' name (v7a) or a marketing name (xscale). 428 return A; 429 } 430 431 unsigned llvm::ARM::parseHWDiv(StringRef HWDiv) { 432 StringRef Syn = getHWDivSynonym(HWDiv); 433 for (const auto D : HWDivNames) { 434 if (Syn == D.getName()) 435 return D.ID; 436 } 437 return ARM::AEK_INVALID; 438 } 439 440 unsigned llvm::ARM::parseFPU(StringRef FPU) { 441 StringRef Syn = getFPUSynonym(FPU); 442 for (const auto F : FPUNames) { 443 if (Syn == F.getName()) 444 return F.ID; 445 } 446 return ARM::FK_INVALID; 447 } 448 449 // Allows partial match, ex. "v7a" matches "armv7a". 450 unsigned llvm::ARM::parseArch(StringRef Arch) { 451 Arch = getCanonicalArchName(Arch); 452 StringRef Syn = getArchSynonym(Arch); 453 for (const auto A : ARCHNames) { 454 if (A.getName().endswith(Syn)) 455 return A.ID; 456 } 457 return ARM::AK_INVALID; 458 } 459 460 unsigned llvm::ARM::parseArchExt(StringRef ArchExt) { 461 for (const auto A : ARCHExtNames) { 462 if (ArchExt == A.getName()) 463 return A.ID; 464 } 465 return ARM::AEK_INVALID; 466 } 467 468 unsigned llvm::ARM::parseCPUArch(StringRef CPU) { 469 for (const auto C : CPUNames) { 470 if (CPU == C.getName()) 471 return C.ArchID; 472 } 473 return ARM::AK_INVALID; 474 } 475 476 // ARM, Thumb, AArch64 477 unsigned llvm::ARM::parseArchISA(StringRef Arch) { 478 return StringSwitch<unsigned>(Arch) 479 .StartsWith("aarch64", ARM::IK_AARCH64) 480 .StartsWith("arm64", ARM::IK_AARCH64) 481 .StartsWith("thumb", ARM::IK_THUMB) 482 .StartsWith("arm", ARM::IK_ARM) 483 .Default(ARM::EK_INVALID); 484 } 485 486 // Little/Big endian 487 unsigned llvm::ARM::parseArchEndian(StringRef Arch) { 488 if (Arch.startswith("armeb") || Arch.startswith("thumbeb") || 489 Arch.startswith("aarch64_be")) 490 return ARM::EK_BIG; 491 492 if (Arch.startswith("arm") || Arch.startswith("thumb")) { 493 if (Arch.endswith("eb")) 494 return ARM::EK_BIG; 495 else 496 return ARM::EK_LITTLE; 497 } 498 499 if (Arch.startswith("aarch64")) 500 return ARM::EK_LITTLE; 501 502 return ARM::EK_INVALID; 503 } 504 505 // Profile A/R/M 506 unsigned llvm::ARM::parseArchProfile(StringRef Arch) { 507 Arch = getCanonicalArchName(Arch); 508 switch (parseArch(Arch)) { 509 case ARM::AK_ARMV6M: 510 case ARM::AK_ARMV7M: 511 case ARM::AK_ARMV6SM: 512 case ARM::AK_ARMV7EM: 513 return ARM::PK_M; 514 case ARM::AK_ARMV7R: 515 return ARM::PK_R; 516 case ARM::AK_ARMV7: 517 case ARM::AK_ARMV7A: 518 case ARM::AK_ARMV7L: 519 case ARM::AK_ARMV8A: 520 case ARM::AK_ARMV8_1A: 521 return ARM::PK_A; 522 } 523 return ARM::PK_INVALID; 524 } 525 526 // Version number (ex. v7 = 7). 527 unsigned llvm::ARM::parseArchVersion(StringRef Arch) { 528 Arch = getCanonicalArchName(Arch); 529 switch (parseArch(Arch)) { 530 case ARM::AK_ARMV2: 531 case ARM::AK_ARMV2A: 532 return 2; 533 case ARM::AK_ARMV3: 534 case ARM::AK_ARMV3M: 535 return 3; 536 case ARM::AK_ARMV4: 537 case ARM::AK_ARMV4T: 538 return 4; 539 case ARM::AK_ARMV5: 540 case ARM::AK_ARMV5T: 541 case ARM::AK_ARMV5TE: 542 case ARM::AK_IWMMXT: 543 case ARM::AK_IWMMXT2: 544 case ARM::AK_XSCALE: 545 case ARM::AK_ARMV5E: 546 case ARM::AK_ARMV5TEJ: 547 return 5; 548 case ARM::AK_ARMV6: 549 case ARM::AK_ARMV6J: 550 case ARM::AK_ARMV6K: 551 case ARM::AK_ARMV6T2: 552 case ARM::AK_ARMV6Z: 553 case ARM::AK_ARMV6ZK: 554 case ARM::AK_ARMV6M: 555 case ARM::AK_ARMV6SM: 556 case ARM::AK_ARMV6HL: 557 return 6; 558 case ARM::AK_ARMV7: 559 case ARM::AK_ARMV7A: 560 case ARM::AK_ARMV7R: 561 case ARM::AK_ARMV7M: 562 case ARM::AK_ARMV7L: 563 case ARM::AK_ARMV7HL: 564 case ARM::AK_ARMV7S: 565 case ARM::AK_ARMV7EM: 566 case ARM::AK_ARMV7K: 567 return 7; 568 case ARM::AK_ARMV8A: 569 case ARM::AK_ARMV8_1A: 570 return 8; 571 } 572 return 0; 573 } 574