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 if (Extensions & ARM::AEK_DSP) 193 Features.push_back("+t2dsp"); 194 else 195 Features.push_back("-t2dsp"); 196 197 return getHWDivFeatures(Extensions, Features); 198 } 199 200 bool llvm::ARM::getFPUFeatures(unsigned FPUKind, 201 std::vector<const char *> &Features) { 202 203 if (FPUKind >= ARM::FK_LAST || FPUKind == ARM::FK_INVALID) 204 return false; 205 206 // fp-only-sp and d16 subtarget features are independent of each other, so we 207 // must enable/disable both. 208 switch (FPUNames[FPUKind].Restriction) { 209 case ARM::FR_SP_D16: 210 Features.push_back("+fp-only-sp"); 211 Features.push_back("+d16"); 212 break; 213 case ARM::FR_D16: 214 Features.push_back("-fp-only-sp"); 215 Features.push_back("+d16"); 216 break; 217 case ARM::FR_None: 218 Features.push_back("-fp-only-sp"); 219 Features.push_back("-d16"); 220 break; 221 } 222 223 // FPU version subtarget features are inclusive of lower-numbered ones, so 224 // enable the one corresponding to this version and disable all that are 225 // higher. We also have to make sure to disable fp16 when vfp4 is disabled, 226 // as +vfp4 implies +fp16 but -vfp4 does not imply -fp16. 227 switch (FPUNames[FPUKind].FPUVersion) { 228 case ARM::FV_VFPV5: 229 Features.push_back("+fp-armv8"); 230 break; 231 case ARM::FV_VFPV4: 232 Features.push_back("+vfp4"); 233 Features.push_back("-fp-armv8"); 234 break; 235 case ARM::FV_VFPV3_FP16: 236 Features.push_back("+vfp3"); 237 Features.push_back("+fp16"); 238 Features.push_back("-vfp4"); 239 Features.push_back("-fp-armv8"); 240 break; 241 case ARM::FV_VFPV3: 242 Features.push_back("+vfp3"); 243 Features.push_back("-fp16"); 244 Features.push_back("-vfp4"); 245 Features.push_back("-fp-armv8"); 246 break; 247 case ARM::FV_VFPV2: 248 Features.push_back("+vfp2"); 249 Features.push_back("-vfp3"); 250 Features.push_back("-fp16"); 251 Features.push_back("-vfp4"); 252 Features.push_back("-fp-armv8"); 253 break; 254 case ARM::FV_NONE: 255 Features.push_back("-vfp2"); 256 Features.push_back("-vfp3"); 257 Features.push_back("-fp16"); 258 Features.push_back("-vfp4"); 259 Features.push_back("-fp-armv8"); 260 break; 261 } 262 263 // crypto includes neon, so we handle this similarly to FPU version. 264 switch (FPUNames[FPUKind].NeonSupport) { 265 case ARM::NS_Crypto: 266 Features.push_back("+neon"); 267 Features.push_back("+crypto"); 268 break; 269 case ARM::NS_Neon: 270 Features.push_back("+neon"); 271 Features.push_back("-crypto"); 272 break; 273 case ARM::NS_None: 274 Features.push_back("-neon"); 275 Features.push_back("-crypto"); 276 break; 277 } 278 279 return true; 280 } 281 282 StringRef llvm::ARM::getArchName(unsigned ArchKind) { 283 if (ArchKind >= ARM::AK_LAST) 284 return StringRef(); 285 return ARCHNames[ArchKind].getName(); 286 } 287 288 StringRef llvm::ARM::getCPUAttr(unsigned ArchKind) { 289 if (ArchKind >= ARM::AK_LAST) 290 return StringRef(); 291 return ARCHNames[ArchKind].getCPUAttr(); 292 } 293 294 StringRef llvm::ARM::getSubArch(unsigned ArchKind) { 295 if (ArchKind >= ARM::AK_LAST) 296 return StringRef(); 297 return ARCHNames[ArchKind].getSubArch(); 298 } 299 300 unsigned llvm::ARM::getArchAttr(unsigned ArchKind) { 301 if (ArchKind >= ARM::AK_LAST) 302 return ARMBuildAttrs::CPUArch::Pre_v4; 303 return ARCHNames[ArchKind].ArchAttr; 304 } 305 306 StringRef llvm::ARM::getArchExtName(unsigned ArchExtKind) { 307 for (const auto AE : ARCHExtNames) { 308 if (ArchExtKind == AE.ID) 309 return AE.getName(); 310 } 311 return StringRef(); 312 } 313 314 StringRef llvm::ARM::getHWDivName(unsigned HWDivKind) { 315 for (const auto D : HWDivNames) { 316 if (HWDivKind == D.ID) 317 return D.getName(); 318 } 319 return StringRef(); 320 } 321 322 unsigned llvm::ARM::getDefaultExtensions(StringRef CPU) { 323 for (const auto C : CPUNames) { 324 if (CPU == C.getName()) 325 return (ARCHNames[C.ArchID].ArchBaseExtensions | C.DefaultExtensions); 326 } 327 return ARM::AEK_INVALID; 328 } 329 330 StringRef llvm::ARM::getDefaultCPU(StringRef Arch) { 331 unsigned AK = parseArch(Arch); 332 if (AK == ARM::AK_INVALID) 333 return StringRef(); 334 335 // Look for multiple AKs to find the default for pair AK+Name. 336 for (const auto CPU : CPUNames) { 337 if (CPU.ArchID == AK && CPU.Default) 338 return CPU.getName(); 339 } 340 return StringRef(); 341 } 342 343 // ======================================================= // 344 // Parsers 345 // ======================================================= // 346 347 static StringRef getHWDivSynonym(StringRef HWDiv) { 348 return StringSwitch<StringRef>(HWDiv) 349 .Case("thumb,arm", "arm,thumb") 350 .Default(HWDiv); 351 } 352 353 static StringRef getFPUSynonym(StringRef FPU) { 354 return StringSwitch<StringRef>(FPU) 355 .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported 356 .Case("vfp2", "vfpv2") 357 .Case("vfp3", "vfpv3") 358 .Case("vfp4", "vfpv4") 359 .Case("vfp3-d16", "vfpv3-d16") 360 .Case("vfp4-d16", "vfpv4-d16") 361 .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16") 362 .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16") 363 .Case("fp5-sp-d16", "fpv5-sp-d16") 364 .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16") 365 // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3. 366 .Case("neon-vfpv3", "neon") 367 .Default(FPU); 368 } 369 370 static StringRef getArchSynonym(StringRef Arch) { 371 return StringSwitch<StringRef>(Arch) 372 .Case("v6sm", "v6s-m") 373 .Case("v6m", "v6-m") 374 .Case("v7a", "v7-a") 375 .Case("v7r", "v7-r") 376 .Case("v7m", "v7-m") 377 .Case("v7em", "v7e-m") 378 .Cases("v8", "v8a", "aarch64", "arm64", "v8-a") 379 .Case("v8.1a", "v8.1-a") 380 .Default(Arch); 381 } 382 383 // MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but 384 // (iwmmxt|xscale)(eb)? is also permitted. If the former, return 385 // "v.+", if the latter, return unmodified string, minus 'eb'. 386 // If invalid, return empty string. 387 StringRef llvm::ARM::getCanonicalArchName(StringRef Arch) { 388 size_t offset = StringRef::npos; 389 StringRef A = Arch; 390 StringRef Error = ""; 391 392 // Begins with "arm" / "thumb", move past it. 393 if (A.startswith("arm64")) 394 offset = 5; 395 else if (A.startswith("arm")) 396 offset = 3; 397 else if (A.startswith("thumb")) 398 offset = 5; 399 else if (A.startswith("aarch64")) { 400 offset = 7; 401 // AArch64 uses "_be", not "eb" suffix. 402 if (A.find("eb") != StringRef::npos) 403 return Error; 404 if (A.substr(offset, 3) == "_be") 405 offset += 3; 406 } 407 408 // Ex. "armebv7", move past the "eb". 409 if (offset != StringRef::npos && A.substr(offset, 2) == "eb") 410 offset += 2; 411 // Or, if it ends with eb ("armv7eb"), chop it off. 412 else if (A.endswith("eb")) 413 A = A.substr(0, A.size() - 2); 414 // Trim the head 415 if (offset != StringRef::npos) 416 A = A.substr(offset); 417 418 // Empty string means offset reached the end, which means it's valid. 419 if (A.empty()) 420 return Arch; 421 422 // Only match non-marketing names 423 if (offset != StringRef::npos) { 424 // Must start with 'vN'. 425 if (A[0] != 'v' || !std::isdigit(A[1])) 426 return Error; 427 // Can't have an extra 'eb'. 428 if (A.find("eb") != StringRef::npos) 429 return Error; 430 } 431 432 // Arch will either be a 'v' name (v7a) or a marketing name (xscale). 433 return A; 434 } 435 436 unsigned llvm::ARM::parseHWDiv(StringRef HWDiv) { 437 StringRef Syn = getHWDivSynonym(HWDiv); 438 for (const auto D : HWDivNames) { 439 if (Syn == D.getName()) 440 return D.ID; 441 } 442 return ARM::AEK_INVALID; 443 } 444 445 unsigned llvm::ARM::parseFPU(StringRef FPU) { 446 StringRef Syn = getFPUSynonym(FPU); 447 for (const auto F : FPUNames) { 448 if (Syn == F.getName()) 449 return F.ID; 450 } 451 return ARM::FK_INVALID; 452 } 453 454 // Allows partial match, ex. "v7a" matches "armv7a". 455 unsigned llvm::ARM::parseArch(StringRef Arch) { 456 Arch = getCanonicalArchName(Arch); 457 StringRef Syn = getArchSynonym(Arch); 458 for (const auto A : ARCHNames) { 459 if (A.getName().endswith(Syn)) 460 return A.ID; 461 } 462 return ARM::AK_INVALID; 463 } 464 465 unsigned llvm::ARM::parseArchExt(StringRef ArchExt) { 466 for (const auto A : ARCHExtNames) { 467 if (ArchExt == A.getName()) 468 return A.ID; 469 } 470 return ARM::AEK_INVALID; 471 } 472 473 unsigned llvm::ARM::parseCPUArch(StringRef CPU) { 474 for (const auto C : CPUNames) { 475 if (CPU == C.getName()) 476 return C.ArchID; 477 } 478 return ARM::AK_INVALID; 479 } 480 481 // ARM, Thumb, AArch64 482 unsigned llvm::ARM::parseArchISA(StringRef Arch) { 483 return StringSwitch<unsigned>(Arch) 484 .StartsWith("aarch64", ARM::IK_AARCH64) 485 .StartsWith("arm64", ARM::IK_AARCH64) 486 .StartsWith("thumb", ARM::IK_THUMB) 487 .StartsWith("arm", ARM::IK_ARM) 488 .Default(ARM::EK_INVALID); 489 } 490 491 // Little/Big endian 492 unsigned llvm::ARM::parseArchEndian(StringRef Arch) { 493 if (Arch.startswith("armeb") || Arch.startswith("thumbeb") || 494 Arch.startswith("aarch64_be")) 495 return ARM::EK_BIG; 496 497 if (Arch.startswith("arm") || Arch.startswith("thumb")) { 498 if (Arch.endswith("eb")) 499 return ARM::EK_BIG; 500 else 501 return ARM::EK_LITTLE; 502 } 503 504 if (Arch.startswith("aarch64")) 505 return ARM::EK_LITTLE; 506 507 return ARM::EK_INVALID; 508 } 509 510 // Profile A/R/M 511 unsigned llvm::ARM::parseArchProfile(StringRef Arch) { 512 Arch = getCanonicalArchName(Arch); 513 switch (parseArch(Arch)) { 514 case ARM::AK_ARMV6M: 515 case ARM::AK_ARMV7M: 516 case ARM::AK_ARMV6SM: 517 case ARM::AK_ARMV7EM: 518 return ARM::PK_M; 519 case ARM::AK_ARMV7R: 520 return ARM::PK_R; 521 case ARM::AK_ARMV7: 522 case ARM::AK_ARMV7A: 523 case ARM::AK_ARMV7L: 524 case ARM::AK_ARMV8A: 525 case ARM::AK_ARMV8_1A: 526 return ARM::PK_A; 527 } 528 return ARM::PK_INVALID; 529 } 530 531 // Version number (ex. v7 = 7). 532 unsigned llvm::ARM::parseArchVersion(StringRef Arch) { 533 Arch = getCanonicalArchName(Arch); 534 switch (parseArch(Arch)) { 535 case ARM::AK_ARMV2: 536 case ARM::AK_ARMV2A: 537 return 2; 538 case ARM::AK_ARMV3: 539 case ARM::AK_ARMV3M: 540 return 3; 541 case ARM::AK_ARMV4: 542 case ARM::AK_ARMV4T: 543 return 4; 544 case ARM::AK_ARMV5: 545 case ARM::AK_ARMV5T: 546 case ARM::AK_ARMV5TE: 547 case ARM::AK_IWMMXT: 548 case ARM::AK_IWMMXT2: 549 case ARM::AK_XSCALE: 550 case ARM::AK_ARMV5E: 551 case ARM::AK_ARMV5TEJ: 552 return 5; 553 case ARM::AK_ARMV6: 554 case ARM::AK_ARMV6J: 555 case ARM::AK_ARMV6K: 556 case ARM::AK_ARMV6T2: 557 case ARM::AK_ARMV6Z: 558 case ARM::AK_ARMV6ZK: 559 case ARM::AK_ARMV6M: 560 case ARM::AK_ARMV6SM: 561 case ARM::AK_ARMV6HL: 562 return 6; 563 case ARM::AK_ARMV7: 564 case ARM::AK_ARMV7A: 565 case ARM::AK_ARMV7R: 566 case ARM::AK_ARMV7M: 567 case ARM::AK_ARMV7L: 568 case ARM::AK_ARMV7HL: 569 case ARM::AK_ARMV7S: 570 case ARM::AK_ARMV7EM: 571 case ARM::AK_ARMV7K: 572 return 7; 573 case ARM::AK_ARMV8A: 574 case ARM::AK_ARMV8_1A: 575 return 8; 576 } 577 return 0; 578 } 579