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