1 //===--- ARM.cpp - Implement ARM target feature support -------------------===// 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 ARM TargetInfo objects. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "ARM.h" 14 #include "clang/Basic/Builtins.h" 15 #include "clang/Basic/Diagnostic.h" 16 #include "clang/Basic/TargetBuiltins.h" 17 #include "llvm/ADT/StringExtras.h" 18 #include "llvm/ADT/StringRef.h" 19 #include "llvm/ADT/StringSwitch.h" 20 21 using namespace clang; 22 using namespace clang::targets; 23 24 void ARMTargetInfo::setABIAAPCS() { 25 IsAAPCS = true; 26 27 DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64; 28 const llvm::Triple &T = getTriple(); 29 30 bool IsNetBSD = T.isOSNetBSD(); 31 bool IsOpenBSD = T.isOSOpenBSD(); 32 if (!T.isOSWindows() && !IsNetBSD && !IsOpenBSD) 33 WCharType = UnsignedInt; 34 35 UseBitFieldTypeAlignment = true; 36 37 ZeroLengthBitfieldBoundary = 0; 38 39 // Thumb1 add sp, #imm requires the immediate value be multiple of 4, 40 // so set preferred for small types to 32. 41 if (T.isOSBinFormatMachO()) { 42 resetDataLayout(BigEndian 43 ? "E-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" 44 : "e-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"); 45 } else if (T.isOSWindows()) { 46 assert(!BigEndian && "Windows on ARM does not support big endian"); 47 resetDataLayout("e" 48 "-m:w" 49 "-p:32:32" 50 "-i64:64" 51 "-v128:64:128" 52 "-a:0:32" 53 "-n32" 54 "-S64"); 55 } else if (T.isOSNaCl()) { 56 assert(!BigEndian && "NaCl on ARM does not support big endian"); 57 resetDataLayout("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S128"); 58 } else { 59 resetDataLayout(BigEndian 60 ? "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" 61 : "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"); 62 } 63 64 // FIXME: Enumerated types are variable width in straight AAPCS. 65 } 66 67 void ARMTargetInfo::setABIAPCS(bool IsAAPCS16) { 68 const llvm::Triple &T = getTriple(); 69 70 IsAAPCS = false; 71 72 if (IsAAPCS16) 73 DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64; 74 else 75 DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 32; 76 77 WCharType = SignedInt; 78 79 // Do not respect the alignment of bit-field types when laying out 80 // structures. This corresponds to PCC_BITFIELD_TYPE_MATTERS in gcc. 81 UseBitFieldTypeAlignment = false; 82 83 /// gcc forces the alignment to 4 bytes, regardless of the type of the 84 /// zero length bitfield. This corresponds to EMPTY_FIELD_BOUNDARY in 85 /// gcc. 86 ZeroLengthBitfieldBoundary = 32; 87 88 if (T.isOSBinFormatMachO() && IsAAPCS16) { 89 assert(!BigEndian && "AAPCS16 does not support big-endian"); 90 resetDataLayout("e-m:o-p:32:32-i64:64-a:0:32-n32-S128"); 91 } else if (T.isOSBinFormatMachO()) 92 resetDataLayout( 93 BigEndian 94 ? "E-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" 95 : "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"); 96 else 97 resetDataLayout( 98 BigEndian 99 ? "E-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" 100 : "e-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"); 101 102 // FIXME: Override "preferred align" for double and long long. 103 } 104 105 void ARMTargetInfo::setArchInfo() { 106 StringRef ArchName = getTriple().getArchName(); 107 108 ArchISA = llvm::ARM::parseArchISA(ArchName); 109 CPU = llvm::ARM::getDefaultCPU(ArchName); 110 llvm::ARM::ArchKind AK = llvm::ARM::parseArch(ArchName); 111 if (AK != llvm::ARM::ArchKind::INVALID) 112 ArchKind = AK; 113 setArchInfo(ArchKind); 114 } 115 116 void ARMTargetInfo::setArchInfo(llvm::ARM::ArchKind Kind) { 117 StringRef SubArch; 118 119 // cache TargetParser info 120 ArchKind = Kind; 121 SubArch = llvm::ARM::getSubArch(ArchKind); 122 ArchProfile = llvm::ARM::parseArchProfile(SubArch); 123 ArchVersion = llvm::ARM::parseArchVersion(SubArch); 124 125 // cache CPU related strings 126 CPUAttr = getCPUAttr(); 127 CPUProfile = getCPUProfile(); 128 } 129 130 void ARMTargetInfo::setAtomic() { 131 // when triple does not specify a sub arch, 132 // then we are not using inline atomics 133 bool ShouldUseInlineAtomic = 134 (ArchISA == llvm::ARM::ISAKind::ARM && ArchVersion >= 6) || 135 (ArchISA == llvm::ARM::ISAKind::THUMB && ArchVersion >= 7); 136 // Cortex M does not support 8 byte atomics, while general Thumb2 does. 137 if (ArchProfile == llvm::ARM::ProfileKind::M) { 138 MaxAtomicPromoteWidth = 32; 139 if (ShouldUseInlineAtomic) 140 MaxAtomicInlineWidth = 32; 141 } else { 142 MaxAtomicPromoteWidth = 64; 143 if (ShouldUseInlineAtomic) 144 MaxAtomicInlineWidth = 64; 145 } 146 } 147 148 bool ARMTargetInfo::isThumb() const { 149 return ArchISA == llvm::ARM::ISAKind::THUMB; 150 } 151 152 bool ARMTargetInfo::supportsThumb() const { 153 return CPUAttr.count('T') || ArchVersion >= 6; 154 } 155 156 bool ARMTargetInfo::supportsThumb2() const { 157 return CPUAttr.equals("6T2") || 158 (ArchVersion >= 7 && !CPUAttr.equals("8M_BASE")); 159 } 160 161 StringRef ARMTargetInfo::getCPUAttr() const { 162 // For most sub-arches, the build attribute CPU name is enough. 163 // For Cortex variants, it's slightly different. 164 switch (ArchKind) { 165 default: 166 return llvm::ARM::getCPUAttr(ArchKind); 167 case llvm::ARM::ArchKind::ARMV6M: 168 return "6M"; 169 case llvm::ARM::ArchKind::ARMV7S: 170 return "7S"; 171 case llvm::ARM::ArchKind::ARMV7A: 172 return "7A"; 173 case llvm::ARM::ArchKind::ARMV7R: 174 return "7R"; 175 case llvm::ARM::ArchKind::ARMV7M: 176 return "7M"; 177 case llvm::ARM::ArchKind::ARMV7EM: 178 return "7EM"; 179 case llvm::ARM::ArchKind::ARMV7VE: 180 return "7VE"; 181 case llvm::ARM::ArchKind::ARMV8A: 182 return "8A"; 183 case llvm::ARM::ArchKind::ARMV8_1A: 184 return "8_1A"; 185 case llvm::ARM::ArchKind::ARMV8_2A: 186 return "8_2A"; 187 case llvm::ARM::ArchKind::ARMV8_3A: 188 return "8_3A"; 189 case llvm::ARM::ArchKind::ARMV8_4A: 190 return "8_4A"; 191 case llvm::ARM::ArchKind::ARMV8_5A: 192 return "8_5A"; 193 case llvm::ARM::ArchKind::ARMV8MBaseline: 194 return "8M_BASE"; 195 case llvm::ARM::ArchKind::ARMV8MMainline: 196 return "8M_MAIN"; 197 case llvm::ARM::ArchKind::ARMV8R: 198 return "8R"; 199 } 200 } 201 202 StringRef ARMTargetInfo::getCPUProfile() const { 203 switch (ArchProfile) { 204 case llvm::ARM::ProfileKind::A: 205 return "A"; 206 case llvm::ARM::ProfileKind::R: 207 return "R"; 208 case llvm::ARM::ProfileKind::M: 209 return "M"; 210 default: 211 return ""; 212 } 213 } 214 215 ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple, 216 const TargetOptions &Opts) 217 : TargetInfo(Triple), FPMath(FP_Default), IsAAPCS(true), LDREX(0), 218 HW_FP(0) { 219 bool IsOpenBSD = Triple.isOSOpenBSD(); 220 bool IsNetBSD = Triple.isOSNetBSD(); 221 222 // FIXME: the isOSBinFormatMachO is a workaround for identifying a Darwin-like 223 // environment where size_t is `unsigned long` rather than `unsigned int` 224 225 PtrDiffType = IntPtrType = 226 (Triple.isOSDarwin() || Triple.isOSBinFormatMachO() || IsOpenBSD || 227 IsNetBSD) 228 ? SignedLong 229 : SignedInt; 230 231 SizeType = (Triple.isOSDarwin() || Triple.isOSBinFormatMachO() || IsOpenBSD || 232 IsNetBSD) 233 ? UnsignedLong 234 : UnsignedInt; 235 236 // ptrdiff_t is inconsistent on Darwin 237 if ((Triple.isOSDarwin() || Triple.isOSBinFormatMachO()) && 238 !Triple.isWatchABI()) 239 PtrDiffType = SignedInt; 240 241 // Cache arch related info. 242 setArchInfo(); 243 244 // {} in inline assembly are neon specifiers, not assembly variant 245 // specifiers. 246 NoAsmVariants = true; 247 248 // FIXME: This duplicates code from the driver that sets the -target-abi 249 // option - this code is used if -target-abi isn't passed and should 250 // be unified in some way. 251 if (Triple.isOSBinFormatMachO()) { 252 // The backend is hardwired to assume AAPCS for M-class processors, ensure 253 // the frontend matches that. 254 if (Triple.getEnvironment() == llvm::Triple::EABI || 255 Triple.getOS() == llvm::Triple::UnknownOS || 256 ArchProfile == llvm::ARM::ProfileKind::M) { 257 setABI("aapcs"); 258 } else if (Triple.isWatchABI()) { 259 setABI("aapcs16"); 260 } else { 261 setABI("apcs-gnu"); 262 } 263 } else if (Triple.isOSWindows()) { 264 // FIXME: this is invalid for WindowsCE 265 setABI("aapcs"); 266 } else { 267 // Select the default based on the platform. 268 switch (Triple.getEnvironment()) { 269 case llvm::Triple::Android: 270 case llvm::Triple::GNUEABI: 271 case llvm::Triple::GNUEABIHF: 272 case llvm::Triple::MuslEABI: 273 case llvm::Triple::MuslEABIHF: 274 setABI("aapcs-linux"); 275 break; 276 case llvm::Triple::EABIHF: 277 case llvm::Triple::EABI: 278 setABI("aapcs"); 279 break; 280 case llvm::Triple::GNU: 281 setABI("apcs-gnu"); 282 break; 283 default: 284 if (IsNetBSD) 285 setABI("apcs-gnu"); 286 else if (IsOpenBSD) 287 setABI("aapcs-linux"); 288 else 289 setABI("aapcs"); 290 break; 291 } 292 } 293 294 // ARM targets default to using the ARM C++ ABI. 295 TheCXXABI.set(TargetCXXABI::GenericARM); 296 297 // ARM has atomics up to 8 bytes 298 setAtomic(); 299 300 // Maximum alignment for ARM NEON data types should be 64-bits (AAPCS) 301 if (IsAAPCS && (Triple.getEnvironment() != llvm::Triple::Android)) 302 MaxVectorAlign = 64; 303 304 // Do force alignment of members that follow zero length bitfields. If 305 // the alignment of the zero-length bitfield is greater than the member 306 // that follows it, `bar', `bar' will be aligned as the type of the 307 // zero length bitfield. 308 UseZeroLengthBitfieldAlignment = true; 309 310 if (Triple.getOS() == llvm::Triple::Linux || 311 Triple.getOS() == llvm::Triple::UnknownOS) 312 this->MCountName = Opts.EABIVersion == llvm::EABI::GNU 313 ? "\01__gnu_mcount_nc" 314 : "\01mcount"; 315 } 316 317 StringRef ARMTargetInfo::getABI() const { return ABI; } 318 319 bool ARMTargetInfo::setABI(const std::string &Name) { 320 ABI = Name; 321 322 // The defaults (above) are for AAPCS, check if we need to change them. 323 // 324 // FIXME: We need support for -meabi... we could just mangle it into the 325 // name. 326 if (Name == "apcs-gnu" || Name == "aapcs16") { 327 setABIAPCS(Name == "aapcs16"); 328 return true; 329 } 330 if (Name == "aapcs" || Name == "aapcs-vfp" || Name == "aapcs-linux") { 331 setABIAAPCS(); 332 return true; 333 } 334 return false; 335 } 336 337 // FIXME: This should be based on Arch attributes, not CPU names. 338 bool ARMTargetInfo::initFeatureMap( 339 llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU, 340 const std::vector<std::string> &FeaturesVec) const { 341 342 std::string ArchFeature; 343 std::vector<StringRef> TargetFeatures; 344 llvm::ARM::ArchKind Arch = llvm::ARM::parseArch(getTriple().getArchName()); 345 346 // Map the base architecture to an appropriate target feature, so we don't 347 // rely on the target triple. 348 llvm::ARM::ArchKind CPUArch = llvm::ARM::parseCPUArch(CPU); 349 if (CPUArch == llvm::ARM::ArchKind::INVALID) 350 CPUArch = Arch; 351 if (CPUArch != llvm::ARM::ArchKind::INVALID) { 352 ArchFeature = ("+" + llvm::ARM::getArchName(CPUArch)).str(); 353 TargetFeatures.push_back(ArchFeature); 354 } 355 356 // get default FPU features 357 unsigned FPUKind = llvm::ARM::getDefaultFPU(CPU, Arch); 358 llvm::ARM::getFPUFeatures(FPUKind, TargetFeatures); 359 360 // get default Extension features 361 unsigned Extensions = llvm::ARM::getDefaultExtensions(CPU, Arch); 362 llvm::ARM::getExtensionFeatures(Extensions, TargetFeatures); 363 364 for (auto Feature : TargetFeatures) 365 if (Feature[0] == '+') 366 Features[Feature.drop_front(1)] = true; 367 368 // Enable or disable thumb-mode explicitly per function to enable mixed 369 // ARM and Thumb code generation. 370 if (isThumb()) 371 Features["thumb-mode"] = true; 372 else 373 Features["thumb-mode"] = false; 374 375 // Convert user-provided arm and thumb GNU target attributes to 376 // [-|+]thumb-mode target features respectively. 377 std::vector<std::string> UpdatedFeaturesVec(FeaturesVec); 378 for (auto &Feature : UpdatedFeaturesVec) { 379 if (Feature.compare("+arm") == 0) 380 Feature = "-thumb-mode"; 381 else if (Feature.compare("+thumb") == 0) 382 Feature = "+thumb-mode"; 383 } 384 385 return TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeaturesVec); 386 } 387 388 389 bool ARMTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, 390 DiagnosticsEngine &Diags) { 391 FPU = 0; 392 CRC = 0; 393 Crypto = 0; 394 DSP = 0; 395 Unaligned = 1; 396 SoftFloat = SoftFloatABI = false; 397 HWDiv = 0; 398 DotProd = 0; 399 HasFloat16 = true; 400 401 // This does not diagnose illegal cases like having both 402 // "+vfpv2" and "+vfpv3" or having "+neon" and "+fp-only-sp". 403 uint32_t HW_FP_remove = 0; 404 for (const auto &Feature : Features) { 405 if (Feature == "+soft-float") { 406 SoftFloat = true; 407 } else if (Feature == "+soft-float-abi") { 408 SoftFloatABI = true; 409 } else if (Feature == "+vfp2") { 410 FPU |= VFP2FPU; 411 HW_FP |= HW_FP_SP | HW_FP_DP; 412 } else if (Feature == "+vfp3") { 413 FPU |= VFP3FPU; 414 HW_FP |= HW_FP_SP | HW_FP_DP; 415 } else if (Feature == "+vfp4") { 416 FPU |= VFP4FPU; 417 HW_FP |= HW_FP_SP | HW_FP_DP | HW_FP_HP; 418 } else if (Feature == "+fp-armv8") { 419 FPU |= FPARMV8; 420 HW_FP |= HW_FP_SP | HW_FP_DP | HW_FP_HP; 421 } else if (Feature == "+neon") { 422 FPU |= NeonFPU; 423 HW_FP |= HW_FP_SP | HW_FP_DP; 424 } else if (Feature == "+hwdiv") { 425 HWDiv |= HWDivThumb; 426 } else if (Feature == "+hwdiv-arm") { 427 HWDiv |= HWDivARM; 428 } else if (Feature == "+crc") { 429 CRC = 1; 430 } else if (Feature == "+crypto") { 431 Crypto = 1; 432 } else if (Feature == "+dsp") { 433 DSP = 1; 434 } else if (Feature == "+fp-only-sp") { 435 HW_FP_remove |= HW_FP_DP; 436 } else if (Feature == "+strict-align") { 437 Unaligned = 0; 438 } else if (Feature == "+fp16") { 439 HW_FP |= HW_FP_HP; 440 } else if (Feature == "+fullfp16") { 441 HasLegalHalfType = true; 442 } else if (Feature == "+dotprod") { 443 DotProd = true; 444 } 445 } 446 HW_FP &= ~HW_FP_remove; 447 448 switch (ArchVersion) { 449 case 6: 450 if (ArchProfile == llvm::ARM::ProfileKind::M) 451 LDREX = 0; 452 else if (ArchKind == llvm::ARM::ArchKind::ARMV6K) 453 LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B; 454 else 455 LDREX = LDREX_W; 456 break; 457 case 7: 458 if (ArchProfile == llvm::ARM::ProfileKind::M) 459 LDREX = LDREX_W | LDREX_H | LDREX_B; 460 else 461 LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B; 462 break; 463 case 8: 464 LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B; 465 } 466 467 if (!(FPU & NeonFPU) && FPMath == FP_Neon) { 468 Diags.Report(diag::err_target_unsupported_fpmath) << "neon"; 469 return false; 470 } 471 472 if (FPMath == FP_Neon) 473 Features.push_back("+neonfp"); 474 else if (FPMath == FP_VFP) 475 Features.push_back("-neonfp"); 476 477 // Remove front-end specific options which the backend handles differently. 478 auto Feature = std::find(Features.begin(), Features.end(), "+soft-float-abi"); 479 if (Feature != Features.end()) 480 Features.erase(Feature); 481 482 return true; 483 } 484 485 bool ARMTargetInfo::hasFeature(StringRef Feature) const { 486 return llvm::StringSwitch<bool>(Feature) 487 .Case("arm", true) 488 .Case("aarch32", true) 489 .Case("softfloat", SoftFloat) 490 .Case("thumb", isThumb()) 491 .Case("neon", (FPU & NeonFPU) && !SoftFloat) 492 .Case("vfp", FPU && !SoftFloat) 493 .Case("hwdiv", HWDiv & HWDivThumb) 494 .Case("hwdiv-arm", HWDiv & HWDivARM) 495 .Default(false); 496 } 497 498 bool ARMTargetInfo::isValidCPUName(StringRef Name) const { 499 return Name == "generic" || 500 llvm::ARM::parseCPUArch(Name) != llvm::ARM::ArchKind::INVALID; 501 } 502 503 void ARMTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const { 504 llvm::ARM::fillValidCPUArchList(Values); 505 } 506 507 bool ARMTargetInfo::setCPU(const std::string &Name) { 508 if (Name != "generic") 509 setArchInfo(llvm::ARM::parseCPUArch(Name)); 510 511 if (ArchKind == llvm::ARM::ArchKind::INVALID) 512 return false; 513 setAtomic(); 514 CPU = Name; 515 return true; 516 } 517 518 bool ARMTargetInfo::setFPMath(StringRef Name) { 519 if (Name == "neon") { 520 FPMath = FP_Neon; 521 return true; 522 } else if (Name == "vfp" || Name == "vfp2" || Name == "vfp3" || 523 Name == "vfp4") { 524 FPMath = FP_VFP; 525 return true; 526 } 527 return false; 528 } 529 530 void ARMTargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts, 531 MacroBuilder &Builder) const { 532 Builder.defineMacro("__ARM_FEATURE_QRDMX", "1"); 533 } 534 535 void ARMTargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts, 536 MacroBuilder &Builder) const { 537 // Also include the ARMv8.1-A defines 538 getTargetDefinesARMV81A(Opts, Builder); 539 } 540 541 void ARMTargetInfo::getTargetDefines(const LangOptions &Opts, 542 MacroBuilder &Builder) const { 543 // Target identification. 544 Builder.defineMacro("__arm"); 545 Builder.defineMacro("__arm__"); 546 // For bare-metal none-eabi. 547 if (getTriple().getOS() == llvm::Triple::UnknownOS && 548 (getTriple().getEnvironment() == llvm::Triple::EABI || 549 getTriple().getEnvironment() == llvm::Triple::EABIHF)) 550 Builder.defineMacro("__ELF__"); 551 552 // Target properties. 553 Builder.defineMacro("__REGISTER_PREFIX__", ""); 554 555 // Unfortunately, __ARM_ARCH_7K__ is now more of an ABI descriptor. The CPU 556 // happens to be Cortex-A7 though, so it should still get __ARM_ARCH_7A__. 557 if (getTriple().isWatchABI()) 558 Builder.defineMacro("__ARM_ARCH_7K__", "2"); 559 560 if (!CPUAttr.empty()) 561 Builder.defineMacro("__ARM_ARCH_" + CPUAttr + "__"); 562 563 // ACLE 6.4.1 ARM/Thumb instruction set architecture 564 // __ARM_ARCH is defined as an integer value indicating the current ARM ISA 565 Builder.defineMacro("__ARM_ARCH", Twine(ArchVersion)); 566 567 if (ArchVersion >= 8) { 568 // ACLE 6.5.7 Crypto Extension 569 if (Crypto) 570 Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1"); 571 // ACLE 6.5.8 CRC32 Extension 572 if (CRC) 573 Builder.defineMacro("__ARM_FEATURE_CRC32", "1"); 574 // ACLE 6.5.10 Numeric Maximum and Minimum 575 Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1"); 576 // ACLE 6.5.9 Directed Rounding 577 Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1"); 578 } 579 580 // __ARM_ARCH_ISA_ARM is defined to 1 if the core supports the ARM ISA. It 581 // is not defined for the M-profile. 582 // NOTE that the default profile is assumed to be 'A' 583 if (CPUProfile.empty() || ArchProfile != llvm::ARM::ProfileKind::M) 584 Builder.defineMacro("__ARM_ARCH_ISA_ARM", "1"); 585 586 // __ARM_ARCH_ISA_THUMB is defined to 1 if the core supports the original 587 // Thumb ISA (including v6-M and v8-M Baseline). It is set to 2 if the 588 // core supports the Thumb-2 ISA as found in the v6T2 architecture and all 589 // v7 and v8 architectures excluding v8-M Baseline. 590 if (supportsThumb2()) 591 Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "2"); 592 else if (supportsThumb()) 593 Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "1"); 594 595 // __ARM_32BIT_STATE is defined to 1 if code is being generated for a 32-bit 596 // instruction set such as ARM or Thumb. 597 Builder.defineMacro("__ARM_32BIT_STATE", "1"); 598 599 // ACLE 6.4.2 Architectural Profile (A, R, M or pre-Cortex) 600 601 // __ARM_ARCH_PROFILE is defined as 'A', 'R', 'M' or 'S', or unset. 602 if (!CPUProfile.empty()) 603 Builder.defineMacro("__ARM_ARCH_PROFILE", "'" + CPUProfile + "'"); 604 605 // ACLE 6.4.3 Unaligned access supported in hardware 606 if (Unaligned) 607 Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1"); 608 609 // ACLE 6.4.4 LDREX/STREX 610 if (LDREX) 611 Builder.defineMacro("__ARM_FEATURE_LDREX", "0x" + Twine::utohexstr(LDREX)); 612 613 // ACLE 6.4.5 CLZ 614 if (ArchVersion == 5 || (ArchVersion == 6 && CPUProfile != "M") || 615 ArchVersion > 6) 616 Builder.defineMacro("__ARM_FEATURE_CLZ", "1"); 617 618 // ACLE 6.5.1 Hardware Floating Point 619 if (HW_FP) 620 Builder.defineMacro("__ARM_FP", "0x" + Twine::utohexstr(HW_FP)); 621 622 // ACLE predefines. 623 Builder.defineMacro("__ARM_ACLE", "200"); 624 625 // FP16 support (we currently only support IEEE format). 626 Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1"); 627 Builder.defineMacro("__ARM_FP16_ARGS", "1"); 628 629 // ACLE 6.5.3 Fused multiply-accumulate (FMA) 630 if (ArchVersion >= 7 && (FPU & VFP4FPU)) 631 Builder.defineMacro("__ARM_FEATURE_FMA", "1"); 632 633 // Subtarget options. 634 635 // FIXME: It's more complicated than this and we don't really support 636 // interworking. 637 // Windows on ARM does not "support" interworking 638 if (5 <= ArchVersion && ArchVersion <= 8 && !getTriple().isOSWindows()) 639 Builder.defineMacro("__THUMB_INTERWORK__"); 640 641 if (ABI == "aapcs" || ABI == "aapcs-linux" || ABI == "aapcs-vfp") { 642 // Embedded targets on Darwin follow AAPCS, but not EABI. 643 // Windows on ARM follows AAPCS VFP, but does not conform to EABI. 644 if (!getTriple().isOSBinFormatMachO() && !getTriple().isOSWindows()) 645 Builder.defineMacro("__ARM_EABI__"); 646 Builder.defineMacro("__ARM_PCS", "1"); 647 } 648 649 if ((!SoftFloat && !SoftFloatABI) || ABI == "aapcs-vfp" || ABI == "aapcs16") 650 Builder.defineMacro("__ARM_PCS_VFP", "1"); 651 652 if (SoftFloat) 653 Builder.defineMacro("__SOFTFP__"); 654 655 // ACLE position independent code macros. 656 if (Opts.ROPI) 657 Builder.defineMacro("__ARM_ROPI", "1"); 658 if (Opts.RWPI) 659 Builder.defineMacro("__ARM_RWPI", "1"); 660 661 if (ArchKind == llvm::ARM::ArchKind::XSCALE) 662 Builder.defineMacro("__XSCALE__"); 663 664 if (isThumb()) { 665 Builder.defineMacro("__THUMBEL__"); 666 Builder.defineMacro("__thumb__"); 667 if (supportsThumb2()) 668 Builder.defineMacro("__thumb2__"); 669 } 670 671 // ACLE 6.4.9 32-bit SIMD instructions 672 if ((CPUProfile != "M" && ArchVersion >= 6) || (CPUProfile == "M" && DSP)) 673 Builder.defineMacro("__ARM_FEATURE_SIMD32", "1"); 674 675 // ACLE 6.4.10 Hardware Integer Divide 676 if (((HWDiv & HWDivThumb) && isThumb()) || 677 ((HWDiv & HWDivARM) && !isThumb())) { 678 Builder.defineMacro("__ARM_FEATURE_IDIV", "1"); 679 Builder.defineMacro("__ARM_ARCH_EXT_IDIV__", "1"); 680 } 681 682 // Note, this is always on in gcc, even though it doesn't make sense. 683 Builder.defineMacro("__APCS_32__"); 684 685 if (FPUModeIsVFP((FPUMode)FPU)) { 686 Builder.defineMacro("__VFP_FP__"); 687 if (FPU & VFP2FPU) 688 Builder.defineMacro("__ARM_VFPV2__"); 689 if (FPU & VFP3FPU) 690 Builder.defineMacro("__ARM_VFPV3__"); 691 if (FPU & VFP4FPU) 692 Builder.defineMacro("__ARM_VFPV4__"); 693 if (FPU & FPARMV8) 694 Builder.defineMacro("__ARM_FPV5__"); 695 } 696 697 // This only gets set when Neon instructions are actually available, unlike 698 // the VFP define, hence the soft float and arch check. This is subtly 699 // different from gcc, we follow the intent which was that it should be set 700 // when Neon instructions are actually available. 701 if ((FPU & NeonFPU) && !SoftFloat && ArchVersion >= 7) { 702 Builder.defineMacro("__ARM_NEON", "1"); 703 Builder.defineMacro("__ARM_NEON__"); 704 // current AArch32 NEON implementations do not support double-precision 705 // floating-point even when it is present in VFP. 706 Builder.defineMacro("__ARM_NEON_FP", 707 "0x" + Twine::utohexstr(HW_FP & ~HW_FP_DP)); 708 } 709 710 Builder.defineMacro("__ARM_SIZEOF_WCHAR_T", 711 Twine(Opts.WCharSize ? Opts.WCharSize : 4)); 712 713 Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4"); 714 715 if (ArchVersion >= 6 && CPUAttr != "6M" && CPUAttr != "8M_BASE") { 716 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); 717 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); 718 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); 719 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); 720 } 721 722 // ACLE 6.4.7 DSP instructions 723 if (DSP) { 724 Builder.defineMacro("__ARM_FEATURE_DSP", "1"); 725 } 726 727 // ACLE 6.4.8 Saturation instructions 728 bool SAT = false; 729 if ((ArchVersion == 6 && CPUProfile != "M") || ArchVersion > 6) { 730 Builder.defineMacro("__ARM_FEATURE_SAT", "1"); 731 SAT = true; 732 } 733 734 // ACLE 6.4.6 Q (saturation) flag 735 if (DSP || SAT) 736 Builder.defineMacro("__ARM_FEATURE_QBIT", "1"); 737 738 if (Opts.UnsafeFPMath) 739 Builder.defineMacro("__ARM_FP_FAST", "1"); 740 741 // Armv8.2-A FP16 vector intrinsic 742 if ((FPU & NeonFPU) && HasLegalHalfType) 743 Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1"); 744 745 // Armv8.2-A FP16 scalar intrinsics 746 if (HasLegalHalfType) 747 Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1"); 748 749 // Armv8.2-A dot product intrinsics 750 if (DotProd) 751 Builder.defineMacro("__ARM_FEATURE_DOTPROD", "1"); 752 753 switch (ArchKind) { 754 default: 755 break; 756 case llvm::ARM::ArchKind::ARMV8_1A: 757 getTargetDefinesARMV81A(Opts, Builder); 758 break; 759 case llvm::ARM::ArchKind::ARMV8_2A: 760 getTargetDefinesARMV82A(Opts, Builder); 761 break; 762 } 763 } 764 765 const Builtin::Info ARMTargetInfo::BuiltinInfo[] = { 766 #define BUILTIN(ID, TYPE, ATTRS) \ 767 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, 768 #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ 769 {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr}, 770 #include "clang/Basic/BuiltinsNEON.def" 771 772 #define BUILTIN(ID, TYPE, ATTRS) \ 773 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, 774 #define LANGBUILTIN(ID, TYPE, ATTRS, LANG) \ 775 {#ID, TYPE, ATTRS, nullptr, LANG, nullptr}, 776 #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ 777 {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr}, 778 #define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \ 779 {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE}, 780 #include "clang/Basic/BuiltinsARM.def" 781 }; 782 783 ArrayRef<Builtin::Info> ARMTargetInfo::getTargetBuiltins() const { 784 return llvm::makeArrayRef(BuiltinInfo, clang::ARM::LastTSBuiltin - 785 Builtin::FirstTSBuiltin); 786 } 787 788 bool ARMTargetInfo::isCLZForZeroUndef() const { return false; } 789 TargetInfo::BuiltinVaListKind ARMTargetInfo::getBuiltinVaListKind() const { 790 return IsAAPCS 791 ? AAPCSABIBuiltinVaList 792 : (getTriple().isWatchABI() ? TargetInfo::CharPtrBuiltinVaList 793 : TargetInfo::VoidPtrBuiltinVaList); 794 } 795 796 const char *const ARMTargetInfo::GCCRegNames[] = { 797 // Integer registers 798 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", 799 "r12", "sp", "lr", "pc", 800 801 // Float registers 802 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", 803 "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22", 804 "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", 805 806 // Double registers 807 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11", 808 "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22", 809 "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31", 810 811 // Quad registers 812 "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11", 813 "q12", "q13", "q14", "q15"}; 814 815 ArrayRef<const char *> ARMTargetInfo::getGCCRegNames() const { 816 return llvm::makeArrayRef(GCCRegNames); 817 } 818 819 const TargetInfo::GCCRegAlias ARMTargetInfo::GCCRegAliases[] = { 820 {{"a1"}, "r0"}, {{"a2"}, "r1"}, {{"a3"}, "r2"}, {{"a4"}, "r3"}, 821 {{"v1"}, "r4"}, {{"v2"}, "r5"}, {{"v3"}, "r6"}, {{"v4"}, "r7"}, 822 {{"v5"}, "r8"}, {{"v6", "rfp"}, "r9"}, {{"sl"}, "r10"}, {{"fp"}, "r11"}, 823 {{"ip"}, "r12"}, {{"r13"}, "sp"}, {{"r14"}, "lr"}, {{"r15"}, "pc"}, 824 // The S, D and Q registers overlap, but aren't really aliases; we 825 // don't want to substitute one of these for a different-sized one. 826 }; 827 828 ArrayRef<TargetInfo::GCCRegAlias> ARMTargetInfo::getGCCRegAliases() const { 829 return llvm::makeArrayRef(GCCRegAliases); 830 } 831 832 bool ARMTargetInfo::validateAsmConstraint( 833 const char *&Name, TargetInfo::ConstraintInfo &Info) const { 834 switch (*Name) { 835 default: 836 break; 837 case 'l': // r0-r7 838 case 'h': // r8-r15 839 case 't': // VFP Floating point register single precision 840 case 'w': // VFP Floating point register double precision 841 Info.setAllowsRegister(); 842 return true; 843 case 'I': 844 case 'J': 845 case 'K': 846 case 'L': 847 case 'M': 848 // FIXME 849 return true; 850 case 'Q': // A memory address that is a single base register. 851 Info.setAllowsMemory(); 852 return true; 853 case 'U': // a memory reference... 854 switch (Name[1]) { 855 case 'q': // ...ARMV4 ldrsb 856 case 'v': // ...VFP load/store (reg+constant offset) 857 case 'y': // ...iWMMXt load/store 858 case 't': // address valid for load/store opaque types wider 859 // than 128-bits 860 case 'n': // valid address for Neon doubleword vector load/store 861 case 'm': // valid address for Neon element and structure load/store 862 case 's': // valid address for non-offset loads/stores of quad-word 863 // values in four ARM registers 864 Info.setAllowsMemory(); 865 Name++; 866 return true; 867 } 868 } 869 return false; 870 } 871 872 std::string ARMTargetInfo::convertConstraint(const char *&Constraint) const { 873 std::string R; 874 switch (*Constraint) { 875 case 'U': // Two-character constraint; add "^" hint for later parsing. 876 R = std::string("^") + std::string(Constraint, 2); 877 Constraint++; 878 break; 879 case 'p': // 'p' should be translated to 'r' by default. 880 R = std::string("r"); 881 break; 882 default: 883 return std::string(1, *Constraint); 884 } 885 return R; 886 } 887 888 bool ARMTargetInfo::validateConstraintModifier( 889 StringRef Constraint, char Modifier, unsigned Size, 890 std::string &SuggestedModifier) const { 891 bool isOutput = (Constraint[0] == '='); 892 bool isInOut = (Constraint[0] == '+'); 893 894 // Strip off constraint modifiers. 895 while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&') 896 Constraint = Constraint.substr(1); 897 898 switch (Constraint[0]) { 899 default: 900 break; 901 case 'r': { 902 switch (Modifier) { 903 default: 904 return (isInOut || isOutput || Size <= 64); 905 case 'q': 906 // A register of size 32 cannot fit a vector type. 907 return false; 908 } 909 } 910 } 911 912 return true; 913 } 914 const char *ARMTargetInfo::getClobbers() const { 915 // FIXME: Is this really right? 916 return ""; 917 } 918 919 TargetInfo::CallingConvCheckResult 920 ARMTargetInfo::checkCallingConvention(CallingConv CC) const { 921 switch (CC) { 922 case CC_AAPCS: 923 case CC_AAPCS_VFP: 924 case CC_Swift: 925 case CC_OpenCLKernel: 926 return CCCR_OK; 927 default: 928 return CCCR_Warning; 929 } 930 } 931 932 int ARMTargetInfo::getEHDataRegisterNumber(unsigned RegNo) const { 933 if (RegNo == 0) 934 return 0; 935 if (RegNo == 1) 936 return 1; 937 return -1; 938 } 939 940 bool ARMTargetInfo::hasSjLjLowering() const { return true; } 941 942 ARMleTargetInfo::ARMleTargetInfo(const llvm::Triple &Triple, 943 const TargetOptions &Opts) 944 : ARMTargetInfo(Triple, Opts) {} 945 946 void ARMleTargetInfo::getTargetDefines(const LangOptions &Opts, 947 MacroBuilder &Builder) const { 948 Builder.defineMacro("__ARMEL__"); 949 ARMTargetInfo::getTargetDefines(Opts, Builder); 950 } 951 952 ARMbeTargetInfo::ARMbeTargetInfo(const llvm::Triple &Triple, 953 const TargetOptions &Opts) 954 : ARMTargetInfo(Triple, Opts) {} 955 956 void ARMbeTargetInfo::getTargetDefines(const LangOptions &Opts, 957 MacroBuilder &Builder) const { 958 Builder.defineMacro("__ARMEB__"); 959 Builder.defineMacro("__ARM_BIG_ENDIAN"); 960 ARMTargetInfo::getTargetDefines(Opts, Builder); 961 } 962 963 WindowsARMTargetInfo::WindowsARMTargetInfo(const llvm::Triple &Triple, 964 const TargetOptions &Opts) 965 : WindowsTargetInfo<ARMleTargetInfo>(Triple, Opts), Triple(Triple) { 966 } 967 968 void WindowsARMTargetInfo::getVisualStudioDefines(const LangOptions &Opts, 969 MacroBuilder &Builder) const { 970 WindowsTargetInfo<ARMleTargetInfo>::getVisualStudioDefines(Opts, Builder); 971 972 // FIXME: this is invalid for WindowsCE 973 Builder.defineMacro("_M_ARM_NT", "1"); 974 Builder.defineMacro("_M_ARMT", "_M_ARM"); 975 Builder.defineMacro("_M_THUMB", "_M_ARM"); 976 977 assert((Triple.getArch() == llvm::Triple::arm || 978 Triple.getArch() == llvm::Triple::thumb) && 979 "invalid architecture for Windows ARM target info"); 980 unsigned Offset = Triple.getArch() == llvm::Triple::arm ? 4 : 6; 981 Builder.defineMacro("_M_ARM", Triple.getArchName().substr(Offset)); 982 983 // TODO map the complete set of values 984 // 31: VFPv3 40: VFPv4 985 Builder.defineMacro("_M_ARM_FP", "31"); 986 } 987 988 TargetInfo::BuiltinVaListKind 989 WindowsARMTargetInfo::getBuiltinVaListKind() const { 990 return TargetInfo::CharPtrBuiltinVaList; 991 } 992 993 TargetInfo::CallingConvCheckResult 994 WindowsARMTargetInfo::checkCallingConvention(CallingConv CC) const { 995 switch (CC) { 996 case CC_X86StdCall: 997 case CC_X86ThisCall: 998 case CC_X86FastCall: 999 case CC_X86VectorCall: 1000 return CCCR_Ignore; 1001 case CC_C: 1002 case CC_OpenCLKernel: 1003 case CC_PreserveMost: 1004 case CC_PreserveAll: 1005 case CC_Swift: 1006 return CCCR_OK; 1007 default: 1008 return CCCR_Warning; 1009 } 1010 } 1011 1012 // Windows ARM + Itanium C++ ABI Target 1013 ItaniumWindowsARMleTargetInfo::ItaniumWindowsARMleTargetInfo( 1014 const llvm::Triple &Triple, const TargetOptions &Opts) 1015 : WindowsARMTargetInfo(Triple, Opts) { 1016 TheCXXABI.set(TargetCXXABI::GenericARM); 1017 } 1018 1019 void ItaniumWindowsARMleTargetInfo::getTargetDefines( 1020 const LangOptions &Opts, MacroBuilder &Builder) const { 1021 WindowsARMTargetInfo::getTargetDefines(Opts, Builder); 1022 1023 if (Opts.MSVCCompat) 1024 WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder); 1025 } 1026 1027 // Windows ARM, MS (C++) ABI 1028 MicrosoftARMleTargetInfo::MicrosoftARMleTargetInfo(const llvm::Triple &Triple, 1029 const TargetOptions &Opts) 1030 : WindowsARMTargetInfo(Triple, Opts) { 1031 TheCXXABI.set(TargetCXXABI::Microsoft); 1032 } 1033 1034 void MicrosoftARMleTargetInfo::getTargetDefines(const LangOptions &Opts, 1035 MacroBuilder &Builder) const { 1036 WindowsARMTargetInfo::getTargetDefines(Opts, Builder); 1037 WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder); 1038 } 1039 1040 MinGWARMTargetInfo::MinGWARMTargetInfo(const llvm::Triple &Triple, 1041 const TargetOptions &Opts) 1042 : WindowsARMTargetInfo(Triple, Opts) { 1043 TheCXXABI.set(TargetCXXABI::GenericARM); 1044 } 1045 1046 void MinGWARMTargetInfo::getTargetDefines(const LangOptions &Opts, 1047 MacroBuilder &Builder) const { 1048 WindowsARMTargetInfo::getTargetDefines(Opts, Builder); 1049 Builder.defineMacro("_ARM_"); 1050 } 1051 1052 CygwinARMTargetInfo::CygwinARMTargetInfo(const llvm::Triple &Triple, 1053 const TargetOptions &Opts) 1054 : ARMleTargetInfo(Triple, Opts) { 1055 this->WCharType = TargetInfo::UnsignedShort; 1056 TLSSupported = false; 1057 DoubleAlign = LongLongAlign = 64; 1058 resetDataLayout("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"); 1059 } 1060 1061 void CygwinARMTargetInfo::getTargetDefines(const LangOptions &Opts, 1062 MacroBuilder &Builder) const { 1063 ARMleTargetInfo::getTargetDefines(Opts, Builder); 1064 Builder.defineMacro("_ARM_"); 1065 Builder.defineMacro("__CYGWIN__"); 1066 Builder.defineMacro("__CYGWIN32__"); 1067 DefineStd(Builder, "unix", Opts); 1068 if (Opts.CPlusPlus) 1069 Builder.defineMacro("_GNU_SOURCE"); 1070 } 1071 1072 DarwinARMTargetInfo::DarwinARMTargetInfo(const llvm::Triple &Triple, 1073 const TargetOptions &Opts) 1074 : DarwinTargetInfo<ARMleTargetInfo>(Triple, Opts) { 1075 HasAlignMac68kSupport = true; 1076 // iOS always has 64-bit atomic instructions. 1077 // FIXME: This should be based off of the target features in 1078 // ARMleTargetInfo. 1079 MaxAtomicInlineWidth = 64; 1080 1081 if (Triple.isWatchABI()) { 1082 // Darwin on iOS uses a variant of the ARM C++ ABI. 1083 TheCXXABI.set(TargetCXXABI::WatchOS); 1084 1085 // BOOL should be a real boolean on the new ABI 1086 UseSignedCharForObjCBool = false; 1087 } else 1088 TheCXXABI.set(TargetCXXABI::iOS); 1089 } 1090 1091 void DarwinARMTargetInfo::getOSDefines(const LangOptions &Opts, 1092 const llvm::Triple &Triple, 1093 MacroBuilder &Builder) const { 1094 getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion); 1095 } 1096 1097 RenderScript32TargetInfo::RenderScript32TargetInfo(const llvm::Triple &Triple, 1098 const TargetOptions &Opts) 1099 : ARMleTargetInfo(llvm::Triple("armv7", Triple.getVendorName(), 1100 Triple.getOSName(), 1101 Triple.getEnvironmentName()), 1102 Opts) { 1103 IsRenderScriptTarget = true; 1104 LongWidth = LongAlign = 64; 1105 } 1106 1107 void RenderScript32TargetInfo::getTargetDefines(const LangOptions &Opts, 1108 MacroBuilder &Builder) const { 1109 Builder.defineMacro("__RENDERSCRIPT__"); 1110 ARMleTargetInfo::getTargetDefines(Opts, Builder); 1111 } 1112