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