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