1591 lines · cpp
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-exception6//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/StringRef.h"18#include "llvm/ADT/StringSwitch.h"19#include "llvm/TargetParser/ARMTargetParser.h"20 21using namespace clang;22using namespace clang::targets;23 24void ARMTargetInfo::setABIAAPCS() {25 IsAAPCS = true;26 27 DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;28 BFloat16Width = BFloat16Align = 16;29 BFloat16Format = &llvm::APFloat::BFloat();30 31 const llvm::Triple &T = getTriple();32 33 bool IsNetBSD = T.isOSNetBSD();34 bool IsOpenBSD = T.isOSOpenBSD();35 if (!T.isOSWindows() && !IsNetBSD && !IsOpenBSD)36 WCharType = UnsignedInt;37 38 UseBitFieldTypeAlignment = true;39 40 ZeroLengthBitfieldBoundary = 0;41 42 // Thumb1 add sp, #imm requires the immediate value be multiple of 4,43 // so set preferred for small types to 32.44 if (T.isOSBinFormatMachO()) {45 resetDataLayout(BigEndian46 ? "E-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"47 : "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64",48 "_");49 } else if (T.isOSWindows()) {50 assert(!BigEndian && "Windows on ARM does not support big endian");51 resetDataLayout("e"52 "-m:w"53 "-p:32:32"54 "-Fi8"55 "-i64:64"56 "-v128:64:128"57 "-a:0:32"58 "-n32"59 "-S64");60 } else {61 resetDataLayout(BigEndian62 ? "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"63 : "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64");64 }65 66 // FIXME: Enumerated types are variable width in straight AAPCS.67}68 69void ARMTargetInfo::setABIAPCS(bool IsAAPCS16) {70 const llvm::Triple &T = getTriple();71 72 IsAAPCS = false;73 74 if (IsAAPCS16)75 DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;76 else77 DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 32;78 BFloat16Width = BFloat16Align = 16;79 BFloat16Format = &llvm::APFloat::BFloat();80 81 WCharType = SignedInt;82 83 // Do not respect the alignment of bit-field types when laying out84 // structures. This corresponds to PCC_BITFIELD_TYPE_MATTERS in gcc.85 UseBitFieldTypeAlignment = false;86 87 /// gcc forces the alignment to 4 bytes, regardless of the type of the88 /// zero length bitfield. This corresponds to EMPTY_FIELD_BOUNDARY in89 /// gcc.90 ZeroLengthBitfieldBoundary = 32;91 92 if (T.isOSBinFormatMachO() && IsAAPCS16) {93 assert(!BigEndian && "AAPCS16 does not support big-endian");94 resetDataLayout("e-m:o-p:32:32-Fi8-i64:64-a:0:32-n32-S128", "_");95 } else if (T.isOSBinFormatMachO())96 resetDataLayout(97 BigEndian98 ? "E-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"99 : "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32",100 "_");101 else102 resetDataLayout(103 BigEndian104 ? "E-m:e-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"105 : "e-m:e-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32");106 107 // FIXME: Override "preferred align" for double and long long.108}109 110void ARMTargetInfo::setArchInfo() {111 StringRef ArchName = getTriple().getArchName();112 113 ArchISA = llvm::ARM::parseArchISA(ArchName);114 CPU = std::string(llvm::ARM::getDefaultCPU(ArchName));115 llvm::ARM::ArchKind AK = llvm::ARM::parseArch(ArchName);116 if (AK != llvm::ARM::ArchKind::INVALID)117 ArchKind = AK;118 setArchInfo(ArchKind);119}120 121void ARMTargetInfo::setArchInfo(llvm::ARM::ArchKind Kind) {122 StringRef SubArch;123 124 // cache TargetParser info125 ArchKind = Kind;126 SubArch = llvm::ARM::getSubArch(ArchKind);127 ArchProfile = llvm::ARM::parseArchProfile(SubArch);128 ArchVersion = llvm::ARM::parseArchVersion(SubArch);129 130 // cache CPU related strings131 CPUAttr = getCPUAttr();132 CPUProfile = getCPUProfile();133}134 135void ARMTargetInfo::setAtomic() {136 if (ArchProfile == llvm::ARM::ProfileKind::M) {137 // M-class only ever supports 32-bit atomics. Cortex-M0 doesn't have138 // any atomics.139 MaxAtomicPromoteWidth = 32;140 if (ArchVersion >= 7)141 MaxAtomicInlineWidth = 32;142 } else {143 // A-class targets have up to 64-bit atomics.144 //145 // On Linux, 64-bit atomics are always available through kernel helpers146 // (which are lock-free). Otherwise, atomics are available on v6 or later.147 //148 // (Thumb doesn't matter; for Thumbv6, we just use a library call which149 // switches out of Thumb mode.)150 //151 // This should match setMaxAtomicSizeInBitsSupported() in the backend.152 MaxAtomicPromoteWidth = 64;153 if (getTriple().getOS() == llvm::Triple::Linux || ArchVersion >= 6)154 MaxAtomicInlineWidth = 64;155 }156}157 158bool ARMTargetInfo::hasMVE() const {159 return ArchKind == llvm::ARM::ArchKind::ARMV8_1MMainline && MVE != 0;160}161 162bool ARMTargetInfo::hasMVEFloat() const {163 return hasMVE() && (MVE & MVE_FP);164}165 166bool ARMTargetInfo::hasCDE() const { return getARMCDECoprocMask() != 0; }167 168bool ARMTargetInfo::isThumb() const {169 return ArchISA == llvm::ARM::ISAKind::THUMB;170}171 172bool ARMTargetInfo::supportsThumb() const {173 return CPUAttr.count('T') || ArchVersion >= 6;174}175 176bool ARMTargetInfo::supportsThumb2() const {177 return CPUAttr == "6T2" || (ArchVersion >= 7 && CPUAttr != "8M_BASE");178}179 180StringRef ARMTargetInfo::getCPUAttr() const {181 // For most sub-arches, the build attribute CPU name is enough.182 // For Cortex variants, it's slightly different.183 switch (ArchKind) {184 default:185 return llvm::ARM::getCPUAttr(ArchKind);186 case llvm::ARM::ArchKind::ARMV6M:187 return "6M";188 case llvm::ARM::ArchKind::ARMV7S:189 return "7S";190 case llvm::ARM::ArchKind::ARMV7A:191 return "7A";192 case llvm::ARM::ArchKind::ARMV7R:193 return "7R";194 case llvm::ARM::ArchKind::ARMV7M:195 return "7M";196 case llvm::ARM::ArchKind::ARMV7EM:197 return "7EM";198 case llvm::ARM::ArchKind::ARMV7VE:199 return "7VE";200 case llvm::ARM::ArchKind::ARMV8A:201 return "8A";202 case llvm::ARM::ArchKind::ARMV8_1A:203 return "8_1A";204 case llvm::ARM::ArchKind::ARMV8_2A:205 return "8_2A";206 case llvm::ARM::ArchKind::ARMV8_3A:207 return "8_3A";208 case llvm::ARM::ArchKind::ARMV8_4A:209 return "8_4A";210 case llvm::ARM::ArchKind::ARMV8_5A:211 return "8_5A";212 case llvm::ARM::ArchKind::ARMV8_6A:213 return "8_6A";214 case llvm::ARM::ArchKind::ARMV8_7A:215 return "8_7A";216 case llvm::ARM::ArchKind::ARMV8_8A:217 return "8_8A";218 case llvm::ARM::ArchKind::ARMV8_9A:219 return "8_9A";220 case llvm::ARM::ArchKind::ARMV9A:221 return "9A";222 case llvm::ARM::ArchKind::ARMV9_1A:223 return "9_1A";224 case llvm::ARM::ArchKind::ARMV9_2A:225 return "9_2A";226 case llvm::ARM::ArchKind::ARMV9_3A:227 return "9_3A";228 case llvm::ARM::ArchKind::ARMV9_4A:229 return "9_4A";230 case llvm::ARM::ArchKind::ARMV9_5A:231 return "9_5A";232 case llvm::ARM::ArchKind::ARMV9_6A:233 return "9_6A";234 case llvm::ARM::ArchKind::ARMV9_7A:235 return "9_7A";236 case llvm::ARM::ArchKind::ARMV8MBaseline:237 return "8M_BASE";238 case llvm::ARM::ArchKind::ARMV8MMainline:239 return "8M_MAIN";240 case llvm::ARM::ArchKind::ARMV8R:241 return "8R";242 case llvm::ARM::ArchKind::ARMV8_1MMainline:243 return "8_1M_MAIN";244 }245}246 247StringRef ARMTargetInfo::getCPUProfile() const {248 switch (ArchProfile) {249 case llvm::ARM::ProfileKind::A:250 return "A";251 case llvm::ARM::ProfileKind::R:252 return "R";253 case llvm::ARM::ProfileKind::M:254 return "M";255 default:256 return "";257 }258}259 260ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple,261 const TargetOptions &Opts)262 : TargetInfo(Triple), FPMath(FP_Default), IsAAPCS(true), LDREX(0),263 HW_FP(0) {264 bool IsFreeBSD = Triple.isOSFreeBSD();265 bool IsFuchsia = Triple.isOSFuchsia();266 bool IsOpenBSD = Triple.isOSOpenBSD();267 bool IsNetBSD = Triple.isOSNetBSD();268 bool IsHaiku = Triple.isOSHaiku();269 bool IsOHOS = Triple.isOHOSFamily();270 271 // FIXME: the isOSBinFormatMachO is a workaround for identifying a Darwin-like272 // environment where size_t is `unsigned long` rather than `unsigned int`273 274 PtrDiffType = IntPtrType =275 (Triple.isOSDarwin() || Triple.isOSBinFormatMachO() || IsOpenBSD ||276 IsNetBSD)277 ? SignedLong278 : SignedInt;279 280 SizeType = (Triple.isOSDarwin() || Triple.isOSBinFormatMachO() || IsOpenBSD ||281 IsNetBSD)282 ? UnsignedLong283 : UnsignedInt;284 285 // ptrdiff_t is inconsistent on Darwin286 if ((Triple.isOSDarwin() || Triple.isOSBinFormatMachO()) &&287 !Triple.isWatchABI())288 PtrDiffType = SignedInt;289 290 // Cache arch related info.291 setArchInfo();292 293 // {} in inline assembly are neon specifiers, not assembly variant294 // specifiers.295 NoAsmVariants = true;296 297 // FIXME: This duplicates code from the driver that sets the -target-abi298 // option - this code is used if -target-abi isn't passed and should299 // be unified in some way.300 if (Triple.isOSBinFormatMachO()) {301 // The backend is hardwired to assume AAPCS for M-class processors, ensure302 // the frontend matches that.303 if (Triple.getEnvironment() == llvm::Triple::EABI ||304 Triple.getOS() == llvm::Triple::UnknownOS ||305 ArchProfile == llvm::ARM::ProfileKind::M) {306 setABI("aapcs");307 } else if (Triple.isWatchABI()) {308 setABI("aapcs16");309 } else {310 setABI("apcs-gnu");311 }312 } else if (Triple.isOSWindows()) {313 // FIXME: this is invalid for WindowsCE314 setABI("aapcs");315 } else {316 // Select the default based on the platform.317 switch (Triple.getEnvironment()) {318 case llvm::Triple::Android:319 case llvm::Triple::GNUEABI:320 case llvm::Triple::GNUEABIT64:321 case llvm::Triple::GNUEABIHF:322 case llvm::Triple::GNUEABIHFT64:323 case llvm::Triple::MuslEABI:324 case llvm::Triple::MuslEABIHF:325 case llvm::Triple::OpenHOS:326 setABI("aapcs-linux");327 break;328 case llvm::Triple::EABIHF:329 case llvm::Triple::EABI:330 setABI("aapcs");331 break;332 case llvm::Triple::GNU:333 setABI("apcs-gnu");334 break;335 default:336 if (IsNetBSD)337 setABI("apcs-gnu");338 else if (IsFreeBSD || IsFuchsia || IsOpenBSD || IsHaiku || IsOHOS)339 setABI("aapcs-linux");340 else341 setABI("aapcs");342 break;343 }344 }345 346 // ARM targets default to using the ARM C++ ABI.347 TheCXXABI.set(TargetCXXABI::GenericARM);348 349 // ARM has atomics up to 8 bytes350 setAtomic();351 352 // Maximum alignment for ARM NEON data types should be 64-bits (AAPCS)353 // as well the default alignment354 if (IsAAPCS && !Triple.isAndroid())355 DefaultAlignForAttributeAligned = MaxVectorAlign = 64;356 357 // Do force alignment of members that follow zero length bitfields. If358 // the alignment of the zero-length bitfield is greater than the member359 // that follows it, `bar', `bar' will be aligned as the type of the360 // zero length bitfield.361 UseZeroLengthBitfieldAlignment = true;362 363 if (Triple.getOS() == llvm::Triple::Linux ||364 Triple.getOS() == llvm::Triple::UnknownOS)365 this->MCountName = Opts.EABIVersion == llvm::EABI::GNU366 ? "llvm.arm.gnu.eabi.mcount"367 : "\01mcount";368 369 SoftFloatABI = llvm::is_contained(Opts.FeaturesAsWritten, "+soft-float-abi");370}371 372StringRef ARMTargetInfo::getABI() const { return ABI; }373 374bool ARMTargetInfo::setABI(const std::string &Name) {375 ABI = Name;376 377 // The defaults (above) are for AAPCS, check if we need to change them.378 //379 // FIXME: We need support for -meabi... we could just mangle it into the380 // name.381 if (Name == "apcs-gnu" || Name == "aapcs16") {382 setABIAPCS(Name == "aapcs16");383 return true;384 }385 if (Name == "aapcs" || Name == "aapcs-vfp" || Name == "aapcs-linux") {386 setABIAAPCS();387 return true;388 }389 return false;390}391 392bool ARMTargetInfo::isBranchProtectionSupportedArch(StringRef Arch) const {393 llvm::ARM::ArchKind CPUArch = llvm::ARM::parseCPUArch(Arch);394 if (CPUArch == llvm::ARM::ArchKind::INVALID)395 CPUArch = llvm::ARM::parseArch(getTriple().getArchName());396 397 if (CPUArch == llvm::ARM::ArchKind::INVALID)398 return false;399 400 StringRef ArchFeature = llvm::ARM::getArchName(CPUArch);401 auto a =402 llvm::Triple(ArchFeature, getTriple().getVendorName(),403 getTriple().getOSName(), getTriple().getEnvironmentName());404 405 StringRef SubArch = llvm::ARM::getSubArch(CPUArch);406 llvm::ARM::ProfileKind Profile = llvm::ARM::parseArchProfile(SubArch);407 return a.isArmT32() && (Profile == llvm::ARM::ProfileKind::M);408}409 410bool ARMTargetInfo::validateBranchProtection(StringRef Spec, StringRef Arch,411 BranchProtectionInfo &BPI,412 const LangOptions &LO,413 StringRef &Err) const {414 llvm::ARM::ParsedBranchProtection PBP;415 if (!llvm::ARM::parseBranchProtection(Spec, PBP, Err))416 return false;417 418 if (!isBranchProtectionSupportedArch(Arch))419 return false;420 421 BPI.SignReturnAddr =422 llvm::StringSwitch<LangOptions::SignReturnAddressScopeKind>(PBP.Scope)423 .Case("non-leaf", LangOptions::SignReturnAddressScopeKind::NonLeaf)424 .Case("all", LangOptions::SignReturnAddressScopeKind::All)425 .Default(LangOptions::SignReturnAddressScopeKind::None);426 427 // Don't care for the sign key, beyond issuing a warning.428 if (PBP.Key == "b_key")429 Err = "b-key";430 BPI.SignKey = LangOptions::SignReturnAddressKeyKind::AKey;431 432 BPI.BranchTargetEnforcement = PBP.BranchTargetEnforcement;433 BPI.BranchProtectionPAuthLR = PBP.BranchProtectionPAuthLR;434 return true;435}436 437// FIXME: This should be based on Arch attributes, not CPU names.438bool ARMTargetInfo::initFeatureMap(439 llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,440 const std::vector<std::string> &FeaturesVec) const {441 442 std::string ArchFeature;443 std::vector<StringRef> TargetFeatures;444 llvm::ARM::ArchKind Arch = llvm::ARM::parseArch(getTriple().getArchName());445 446 // Map the base architecture to an appropriate target feature, so we don't447 // rely on the target triple.448 llvm::ARM::ArchKind CPUArch = llvm::ARM::parseCPUArch(CPU);449 if (CPUArch == llvm::ARM::ArchKind::INVALID)450 CPUArch = Arch;451 if (CPUArch != llvm::ARM::ArchKind::INVALID) {452 ArchFeature = ("+" + llvm::ARM::getArchName(CPUArch)).str();453 TargetFeatures.push_back(ArchFeature);454 455 // These features are added to allow arm_neon.h target(..) attributes to456 // match with both arm and aarch64. We need to add all previous architecture457 // versions, so that "8.6" also allows "8.1" functions. In case of v9.x the458 // v8.x counterparts are added too. We only need these for anything > 8.0-A.459 for (llvm::ARM::ArchKind I = llvm::ARM::convertV9toV8(CPUArch);460 I != llvm::ARM::ArchKind::INVALID; --I)461 Features[llvm::ARM::getSubArch(I)] = true;462 if (CPUArch > llvm::ARM::ArchKind::ARMV8A &&463 CPUArch <= llvm::ARM::ArchKind::ARMV9_3A)464 for (llvm::ARM::ArchKind I = CPUArch; I != llvm::ARM::ArchKind::INVALID;465 --I)466 Features[llvm::ARM::getSubArch(I)] = true;467 }468 469 // get default FPU features470 llvm::ARM::FPUKind FPUKind = llvm::ARM::getDefaultFPU(CPU, Arch);471 llvm::ARM::getFPUFeatures(FPUKind, TargetFeatures);472 473 // get default Extension features474 uint64_t Extensions = llvm::ARM::getDefaultExtensions(CPU, Arch);475 llvm::ARM::getExtensionFeatures(Extensions, TargetFeatures);476 477 for (auto Feature : TargetFeatures)478 if (Feature[0] == '+')479 Features[Feature.drop_front(1)] = true;480 481 // Enable or disable thumb-mode explicitly per function to enable mixed482 // ARM and Thumb code generation.483 if (isThumb())484 Features["thumb-mode"] = true;485 else486 Features["thumb-mode"] = false;487 488 // Convert user-provided arm and thumb GNU target attributes to489 // [-|+]thumb-mode target features respectively.490 std::vector<std::string> UpdatedFeaturesVec;491 for (const auto &Feature : FeaturesVec) {492 // Skip soft-float-abi; it's something we only use to initialize a bit of493 // class state, and is otherwise unrecognized.494 if (Feature == "+soft-float-abi")495 continue;496 497 StringRef FixedFeature;498 if (Feature == "+arm")499 FixedFeature = "-thumb-mode";500 else if (Feature == "+thumb")501 FixedFeature = "+thumb-mode";502 else503 FixedFeature = Feature;504 UpdatedFeaturesVec.push_back(FixedFeature.str());505 }506 507 return TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeaturesVec);508}509 510 511bool ARMTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,512 DiagnosticsEngine &Diags) {513 FPU = 0;514 MVE = 0;515 CRC = 0;516 Crypto = 0;517 SHA2 = 0;518 AES = 0;519 DSP = 0;520 HasUnalignedAccess = true;521 SoftFloat = false;522 // Note that SoftFloatABI is initialized in our constructor.523 HWDiv = 0;524 DotProd = 0;525 HasMatMul = 0;526 HasPAC = 0;527 HasBTI = 0;528 HasFloat16 = true;529 ARMCDECoprocMask = 0;530 HasBFloat16 = false;531 HasFullBFloat16 = false;532 FPRegsDisabled = false;533 534 // This does not diagnose illegal cases like having both535 // "+vfpv2" and "+vfpv3" or having "+neon" and "-fp64".536 for (const auto &Feature : Features) {537 if (Feature == "+soft-float") {538 SoftFloat = true;539 } else if (Feature == "+vfp2sp" || Feature == "+vfp2") {540 FPU |= VFP2FPU;541 HW_FP |= HW_FP_SP;542 if (Feature == "+vfp2")543 HW_FP |= HW_FP_DP;544 } else if (Feature == "+vfp3sp" || Feature == "+vfp3d16sp" ||545 Feature == "+vfp3" || Feature == "+vfp3d16") {546 FPU |= VFP3FPU;547 HW_FP |= HW_FP_SP;548 if (Feature == "+vfp3" || Feature == "+vfp3d16")549 HW_FP |= HW_FP_DP;550 } else if (Feature == "+vfp4sp" || Feature == "+vfp4d16sp" ||551 Feature == "+vfp4" || Feature == "+vfp4d16") {552 FPU |= VFP4FPU;553 HW_FP |= HW_FP_SP | HW_FP_HP;554 if (Feature == "+vfp4" || Feature == "+vfp4d16")555 HW_FP |= HW_FP_DP;556 } else if (Feature == "+fp-armv8sp" || Feature == "+fp-armv8d16sp" ||557 Feature == "+fp-armv8" || Feature == "+fp-armv8d16") {558 FPU |= FPARMV8;559 HW_FP |= HW_FP_SP | HW_FP_HP;560 if (Feature == "+fp-armv8" || Feature == "+fp-armv8d16")561 HW_FP |= HW_FP_DP;562 } else if (Feature == "+neon") {563 FPU |= NeonFPU;564 HW_FP |= HW_FP_SP;565 } else if (Feature == "+hwdiv") {566 HWDiv |= HWDivThumb;567 } else if (Feature == "+hwdiv-arm") {568 HWDiv |= HWDivARM;569 } else if (Feature == "+crc") {570 CRC = 1;571 } else if (Feature == "+crypto") {572 Crypto = 1;573 } else if (Feature == "+sha2") {574 SHA2 = 1;575 } else if (Feature == "+aes") {576 AES = 1;577 } else if (Feature == "+dsp") {578 DSP = 1;579 } else if (Feature == "+fp64") {580 HW_FP |= HW_FP_DP;581 } else if (Feature == "+8msecext") {582 if (CPUProfile != "M" || ArchVersion != 8) {583 Diags.Report(diag::err_target_unsupported_mcmse) << CPU;584 return false;585 }586 } else if (Feature == "+strict-align") {587 HasUnalignedAccess = false;588 } else if (Feature == "+fp16") {589 HW_FP |= HW_FP_HP;590 } else if (Feature == "+fullfp16") {591 HasFastHalfType = true;592 } else if (Feature == "+dotprod") {593 DotProd = true;594 } else if (Feature == "+mve") {595 MVE |= MVE_INT;596 } else if (Feature == "+mve.fp") {597 HasFastHalfType = true;598 FPU |= FPARMV8;599 MVE |= MVE_INT | MVE_FP;600 HW_FP |= HW_FP_SP | HW_FP_HP;601 } else if (Feature == "+i8mm") {602 HasMatMul = 1;603 } else if (Feature.size() == strlen("+cdecp0") && Feature >= "+cdecp0" &&604 Feature <= "+cdecp7") {605 unsigned Coproc = Feature.back() - '0';606 ARMCDECoprocMask |= (1U << Coproc);607 } else if (Feature == "+bf16") {608 HasBFloat16 = true;609 } else if (Feature == "-fpregs") {610 FPRegsDisabled = true;611 } else if (Feature == "+pacbti") {612 HasPAC = 1;613 HasBTI = 1;614 } else if (Feature == "+fullbf16") {615 HasFullBFloat16 = true;616 } else if (Feature == "+execute-only") {617 TLSSupported = false;618 }619 }620 621 HalfArgsAndReturns = true;622 623 switch (ArchVersion) {624 case 6:625 if (ArchProfile == llvm::ARM::ProfileKind::M)626 LDREX = 0;627 else if (ArchKind == llvm::ARM::ArchKind::ARMV6K ||628 ArchKind == llvm::ARM::ArchKind::ARMV6KZ)629 LDREX = ARM_LDREX_D | ARM_LDREX_W | ARM_LDREX_H | ARM_LDREX_B;630 else631 LDREX = ARM_LDREX_W;632 break;633 case 7:634 case 8:635 if (ArchProfile == llvm::ARM::ProfileKind::M)636 LDREX = ARM_LDREX_W | ARM_LDREX_H | ARM_LDREX_B;637 else638 LDREX = ARM_LDREX_D | ARM_LDREX_W | ARM_LDREX_H | ARM_LDREX_B;639 break;640 case 9:641 assert(ArchProfile != llvm::ARM::ProfileKind::M &&642 "No Armv9-M architectures defined");643 LDREX = ARM_LDREX_D | ARM_LDREX_W | ARM_LDREX_H | ARM_LDREX_B;644 }645 646 if (!(FPU & NeonFPU) && FPMath == FP_Neon) {647 Diags.Report(diag::err_target_unsupported_fpmath) << "neon";648 return false;649 }650 651 if (FPMath == FP_Neon)652 Features.push_back("+neonfp");653 else if (FPMath == FP_VFP)654 Features.push_back("-neonfp");655 656 return true;657}658 659bool ARMTargetInfo::hasFeature(StringRef Feature) const {660 return llvm::StringSwitch<bool>(Feature)661 .Case("arm", true)662 .Case("aarch32", true)663 .Case("softfloat", SoftFloat)664 .Case("thumb", isThumb())665 .Case("neon", (FPU & NeonFPU) && !SoftFloat)666 .Case("vfp", FPU && !SoftFloat)667 .Case("hwdiv", HWDiv & HWDivThumb)668 .Case("hwdiv-arm", HWDiv & HWDivARM)669 .Case("mve", hasMVE())670 .Default(false);671}672 673bool ARMTargetInfo::hasBFloat16Type() const {674 // The __bf16 type is generally available so long as we have any fp registers.675 return HasBFloat16 || (FPU && !SoftFloat);676}677 678bool ARMTargetInfo::isValidCPUName(StringRef Name) const {679 return Name == "generic" ||680 llvm::ARM::parseCPUArch(Name) != llvm::ARM::ArchKind::INVALID;681}682 683void ARMTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const {684 llvm::ARM::fillValidCPUArchList(Values);685}686 687bool ARMTargetInfo::setCPU(const std::string &Name) {688 if (Name != "generic")689 setArchInfo(llvm::ARM::parseCPUArch(Name));690 691 if (ArchKind == llvm::ARM::ArchKind::INVALID)692 return false;693 setAtomic();694 CPU = Name;695 return true;696}697 698bool ARMTargetInfo::setFPMath(StringRef Name) {699 if (Name == "neon") {700 FPMath = FP_Neon;701 return true;702 } else if (Name == "vfp" || Name == "vfp2" || Name == "vfp3" ||703 Name == "vfp4") {704 FPMath = FP_VFP;705 return true;706 }707 return false;708}709 710void ARMTargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,711 MacroBuilder &Builder) const {712 Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");713}714 715void ARMTargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts,716 MacroBuilder &Builder) const {717 // Also include the ARMv8.1-A defines718 getTargetDefinesARMV81A(Opts, Builder);719}720 721void ARMTargetInfo::getTargetDefinesARMV83A(const LangOptions &Opts,722 MacroBuilder &Builder) const {723 // Also include the ARMv8.2-A defines724 Builder.defineMacro("__ARM_FEATURE_COMPLEX", "1");725 getTargetDefinesARMV82A(Opts, Builder);726}727 728void ARMTargetInfo::getTargetDefines(const LangOptions &Opts,729 MacroBuilder &Builder) const {730 // Target identification.731 Builder.defineMacro("__arm");732 Builder.defineMacro("__arm__");733 // For bare-metal none-eabi.734 if (getTriple().getOS() == llvm::Triple::UnknownOS &&735 (getTriple().getEnvironment() == llvm::Triple::EABI ||736 getTriple().getEnvironment() == llvm::Triple::EABIHF) &&737 Opts.CPlusPlus) {738 Builder.defineMacro("_GNU_SOURCE");739 }740 741 // Target properties.742 Builder.defineMacro("__REGISTER_PREFIX__", "");743 744 // Unfortunately, __ARM_ARCH_7K__ is now more of an ABI descriptor. The CPU745 // happens to be Cortex-A7 though, so it should still get __ARM_ARCH_7A__.746 if (getTriple().isWatchABI())747 Builder.defineMacro("__ARM_ARCH_7K__", "2");748 749 if (!CPUAttr.empty())750 Builder.defineMacro("__ARM_ARCH_" + CPUAttr + "__");751 752 // ACLE 6.4.1 ARM/Thumb instruction set architecture753 // __ARM_ARCH is defined as an integer value indicating the current ARM ISA754 Builder.defineMacro("__ARM_ARCH", Twine(ArchVersion));755 756 if (ArchVersion >= 8) {757 // ACLE 6.5.7 Crypto Extension758 // The __ARM_FEATURE_CRYPTO is deprecated in favor of finer grained759 // feature macros for AES and SHA2760 if (SHA2 && AES)761 Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");762 if (SHA2)763 Builder.defineMacro("__ARM_FEATURE_SHA2", "1");764 if (AES)765 Builder.defineMacro("__ARM_FEATURE_AES", "1");766 // ACLE 6.5.8 CRC32 Extension767 if (CRC)768 Builder.defineMacro("__ARM_FEATURE_CRC32", "1");769 // ACLE 6.5.10 Numeric Maximum and Minimum770 Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");771 // ACLE 6.5.9 Directed Rounding772 Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");773 }774 775 // __ARM_ARCH_ISA_ARM is defined to 1 if the core supports the ARM ISA. It776 // is not defined for the M-profile.777 // NOTE that the default profile is assumed to be 'A'778 if (CPUProfile.empty() || ArchProfile != llvm::ARM::ProfileKind::M)779 Builder.defineMacro("__ARM_ARCH_ISA_ARM", "1");780 781 // __ARM_ARCH_ISA_THUMB is defined to 1 if the core supports the original782 // Thumb ISA (including v6-M and v8-M Baseline). It is set to 2 if the783 // core supports the Thumb-2 ISA as found in the v6T2 architecture and all784 // v7 and v8 architectures excluding v8-M Baseline.785 if (supportsThumb2())786 Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "2");787 else if (supportsThumb())788 Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "1");789 790 // __ARM_32BIT_STATE is defined to 1 if code is being generated for a 32-bit791 // instruction set such as ARM or Thumb.792 Builder.defineMacro("__ARM_32BIT_STATE", "1");793 794 // ACLE 6.4.2 Architectural Profile (A, R, M or pre-Cortex)795 796 // __ARM_ARCH_PROFILE is defined as 'A', 'R', 'M' or 'S', or unset.797 if (!CPUProfile.empty())798 Builder.defineMacro("__ARM_ARCH_PROFILE", "'" + CPUProfile + "'");799 800 // ACLE 6.4.3 Unaligned access supported in hardware801 if (HasUnalignedAccess)802 Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");803 804 // ACLE 6.4.4 LDREX/STREX805 if (LDREX)806 Builder.defineMacro("__ARM_FEATURE_LDREX", "0x" + Twine::utohexstr(LDREX));807 808 // ACLE 6.4.5 CLZ809 if (ArchVersion == 5 || (ArchVersion == 6 && CPUProfile != "M") ||810 ArchVersion > 6)811 Builder.defineMacro("__ARM_FEATURE_CLZ", "1");812 813 // ACLE 6.5.1 Hardware Floating Point814 if (HW_FP)815 Builder.defineMacro("__ARM_FP", "0x" + Twine::utohexstr(HW_FP));816 817 // ACLE predefines.818 Builder.defineMacro("__ARM_ACLE", "200");819 820 // FP16 support (we currently only support IEEE format).821 Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");822 Builder.defineMacro("__ARM_FP16_ARGS", "1");823 824 // ACLE 6.5.3 Fused multiply-accumulate (FMA)825 if (ArchVersion >= 7 && (FPU & VFP4FPU))826 Builder.defineMacro("__ARM_FEATURE_FMA", "1");827 828 // Subtarget options.829 830 // FIXME: It's more complicated than this and we don't really support831 // interworking.832 // Windows on ARM does not "support" interworking833 if (5 <= ArchVersion && ArchVersion <= 8 && !getTriple().isOSWindows())834 Builder.defineMacro("__THUMB_INTERWORK__");835 836 if (ABI == "aapcs" || ABI == "aapcs-linux" || ABI == "aapcs-vfp") {837 // Embedded targets on Darwin follow AAPCS, but not EABI.838 // Windows on ARM follows AAPCS VFP, but does not conform to EABI.839 if (!getTriple().isOSBinFormatMachO() && !getTriple().isOSWindows())840 Builder.defineMacro("__ARM_EABI__");841 Builder.defineMacro("__ARM_PCS", "1");842 }843 844 if ((!SoftFloat && !SoftFloatABI) || ABI == "aapcs-vfp" || ABI == "aapcs16")845 Builder.defineMacro("__ARM_PCS_VFP", "1");846 847 if (SoftFloat || (SoftFloatABI && !FPU))848 Builder.defineMacro("__SOFTFP__");849 850 // ACLE position independent code macros.851 if (Opts.ROPI)852 Builder.defineMacro("__ARM_ROPI", "1");853 if (Opts.RWPI)854 Builder.defineMacro("__ARM_RWPI", "1");855 856 // Macros for enabling co-proc intrinsics857 uint64_t FeatureCoprocBF = 0;858 switch (ArchKind) {859 default:860 break;861 case llvm::ARM::ArchKind::ARMV4:862 case llvm::ARM::ArchKind::ARMV4T:863 // Filter __arm_ldcl and __arm_stcl in acle.h864 FeatureCoprocBF = isThumb() ? 0 : FEATURE_COPROC_B1;865 break;866 case llvm::ARM::ArchKind::ARMV5T:867 FeatureCoprocBF = isThumb() ? 0 : FEATURE_COPROC_B1 | FEATURE_COPROC_B2;868 break;869 case llvm::ARM::ArchKind::ARMV5TE:870 case llvm::ARM::ArchKind::ARMV5TEJ:871 if (!isThumb())872 FeatureCoprocBF =873 FEATURE_COPROC_B1 | FEATURE_COPROC_B2 | FEATURE_COPROC_B3;874 break;875 case llvm::ARM::ArchKind::ARMV6:876 case llvm::ARM::ArchKind::ARMV6K:877 case llvm::ARM::ArchKind::ARMV6KZ:878 case llvm::ARM::ArchKind::ARMV6T2:879 if (!isThumb() || ArchKind == llvm::ARM::ArchKind::ARMV6T2)880 FeatureCoprocBF = FEATURE_COPROC_B1 | FEATURE_COPROC_B2 |881 FEATURE_COPROC_B3 | FEATURE_COPROC_B4;882 break;883 case llvm::ARM::ArchKind::ARMV7A:884 case llvm::ARM::ArchKind::ARMV7R:885 case llvm::ARM::ArchKind::ARMV7M:886 case llvm::ARM::ArchKind::ARMV7S:887 case llvm::ARM::ArchKind::ARMV7EM:888 FeatureCoprocBF = FEATURE_COPROC_B1 | FEATURE_COPROC_B2 |889 FEATURE_COPROC_B3 | FEATURE_COPROC_B4;890 break;891 case llvm::ARM::ArchKind::ARMV8A:892 case llvm::ARM::ArchKind::ARMV8R:893 case llvm::ARM::ArchKind::ARMV8_1A:894 case llvm::ARM::ArchKind::ARMV8_2A:895 case llvm::ARM::ArchKind::ARMV8_3A:896 case llvm::ARM::ArchKind::ARMV8_4A:897 case llvm::ARM::ArchKind::ARMV8_5A:898 case llvm::ARM::ArchKind::ARMV8_6A:899 case llvm::ARM::ArchKind::ARMV8_7A:900 case llvm::ARM::ArchKind::ARMV8_8A:901 case llvm::ARM::ArchKind::ARMV8_9A:902 case llvm::ARM::ArchKind::ARMV9A:903 case llvm::ARM::ArchKind::ARMV9_1A:904 case llvm::ARM::ArchKind::ARMV9_2A:905 case llvm::ARM::ArchKind::ARMV9_3A:906 case llvm::ARM::ArchKind::ARMV9_4A:907 case llvm::ARM::ArchKind::ARMV9_5A:908 case llvm::ARM::ArchKind::ARMV9_6A:909 case llvm::ARM::ArchKind::ARMV9_7A:910 // Filter __arm_cdp, __arm_ldcl, __arm_stcl in arm_acle.h911 FeatureCoprocBF = FEATURE_COPROC_B1 | FEATURE_COPROC_B3;912 break;913 case llvm::ARM::ArchKind::ARMV8MMainline:914 case llvm::ARM::ArchKind::ARMV8_1MMainline:915 FeatureCoprocBF = FEATURE_COPROC_B1 | FEATURE_COPROC_B2 |916 FEATURE_COPROC_B3 | FEATURE_COPROC_B4;917 break;918 }919 Builder.defineMacro("__ARM_FEATURE_COPROC",920 "0x" + Twine::utohexstr(FeatureCoprocBF));921 922 if (ArchKind == llvm::ARM::ArchKind::XSCALE)923 Builder.defineMacro("__XSCALE__");924 925 if (isThumb()) {926 Builder.defineMacro("__THUMBEL__");927 Builder.defineMacro("__thumb__");928 if (supportsThumb2())929 Builder.defineMacro("__thumb2__");930 }931 932 // ACLE 6.4.9 32-bit SIMD instructions933 if ((CPUProfile != "M" && ArchVersion >= 6) || (CPUProfile == "M" && DSP))934 Builder.defineMacro("__ARM_FEATURE_SIMD32", "1");935 936 // ACLE 6.4.10 Hardware Integer Divide937 if (((HWDiv & HWDivThumb) && isThumb()) ||938 ((HWDiv & HWDivARM) && !isThumb())) {939 Builder.defineMacro("__ARM_FEATURE_IDIV", "1");940 Builder.defineMacro("__ARM_ARCH_EXT_IDIV__", "1");941 }942 943 // Note, this is always on in gcc, even though it doesn't make sense.944 Builder.defineMacro("__APCS_32__");945 946 // __VFP_FP__ means that the floating-point format is VFP, not that a hardware947 // FPU is present. Moreover, the VFP format is the only one supported by948 // clang. For these reasons, this macro is always defined.949 Builder.defineMacro("__VFP_FP__");950 951 if (FPUModeIsVFP((FPUMode)FPU)) {952 if (FPU & VFP2FPU)953 Builder.defineMacro("__ARM_VFPV2__");954 if (FPU & VFP3FPU)955 Builder.defineMacro("__ARM_VFPV3__");956 if (FPU & VFP4FPU)957 Builder.defineMacro("__ARM_VFPV4__");958 if (FPU & FPARMV8)959 Builder.defineMacro("__ARM_FPV5__");960 }961 962 // This only gets set when Neon instructions are actually available, unlike963 // the VFP define, hence the soft float and arch check. This is subtly964 // different from gcc, we follow the intent which was that it should be set965 // when Neon instructions are actually available.966 if ((FPU & NeonFPU) && !SoftFloat && ArchVersion >= 7) {967 Builder.defineMacro("__ARM_NEON", "1");968 Builder.defineMacro("__ARM_NEON__");969 // current AArch32 NEON implementations do not support double-precision970 // floating-point even when it is present in VFP.971 Builder.defineMacro("__ARM_NEON_FP",972 "0x" + Twine::utohexstr(HW_FP & ~HW_FP_DP));973 }974 975 if (hasMVE()) {976 Builder.defineMacro("__ARM_FEATURE_MVE", hasMVEFloat() ? "3" : "1");977 }978 979 if (hasCDE()) {980 Builder.defineMacro("__ARM_FEATURE_CDE", "1");981 Builder.defineMacro("__ARM_FEATURE_CDE_COPROC",982 "0x" + Twine::utohexstr(getARMCDECoprocMask()));983 }984 985 Builder.defineMacro("__ARM_SIZEOF_WCHAR_T",986 Twine(Opts.WCharSize ? Opts.WCharSize : 4));987 988 Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4");989 990 // CMSE991 if (ArchVersion == 8 && ArchProfile == llvm::ARM::ProfileKind::M)992 Builder.defineMacro("__ARM_FEATURE_CMSE", Opts.Cmse ? "3" : "1");993 994 if (ArchVersion >= 6 && CPUAttr != "6M" && CPUAttr != "8M_BASE") {995 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");996 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");997 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");998 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");999 }1000 1001 // ACLE 6.4.7 DSP instructions1002 if (DSP) {1003 Builder.defineMacro("__ARM_FEATURE_DSP", "1");1004 }1005 1006 // ACLE 6.4.8 Saturation instructions1007 bool SAT = false;1008 if ((ArchVersion == 6 && CPUProfile != "M") || ArchVersion > 6) {1009 Builder.defineMacro("__ARM_FEATURE_SAT", "1");1010 SAT = true;1011 }1012 1013 // ACLE 6.4.6 Q (saturation) flag1014 if (DSP || SAT)1015 Builder.defineMacro("__ARM_FEATURE_QBIT", "1");1016 1017 if (Opts.UnsafeFPMath)1018 Builder.defineMacro("__ARM_FP_FAST", "1");1019 1020 // Armv8.2-A FP16 vector intrinsic1021 if ((FPU & NeonFPU) && HasFastHalfType)1022 Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1");1023 1024 // Armv8.2-A FP16 scalar intrinsics1025 if (HasFastHalfType)1026 Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1");1027 1028 // Armv8.2-A dot product intrinsics1029 if (DotProd)1030 Builder.defineMacro("__ARM_FEATURE_DOTPROD", "1");1031 1032 if (HasMatMul)1033 Builder.defineMacro("__ARM_FEATURE_MATMUL_INT8", "1");1034 1035 if (HasPAC)1036 Builder.defineMacro("__ARM_FEATURE_PAUTH", "1");1037 1038 if (HasBTI)1039 Builder.defineMacro("__ARM_FEATURE_BTI", "1");1040 1041 if (HasBFloat16) {1042 Builder.defineMacro("__ARM_FEATURE_BF16", "1");1043 Builder.defineMacro("__ARM_FEATURE_BF16_VECTOR_ARITHMETIC", "1");1044 Builder.defineMacro("__ARM_BF16_FORMAT_ALTERNATIVE", "1");1045 }1046 1047 if (Opts.BranchTargetEnforcement)1048 Builder.defineMacro("__ARM_FEATURE_BTI_DEFAULT", "1");1049 1050 if (Opts.hasSignReturnAddress()) {1051 unsigned Value = 1;1052 if (Opts.isSignReturnAddressScopeAll())1053 Value |= 1 << 2;1054 Builder.defineMacro("__ARM_FEATURE_PAC_DEFAULT", Twine(Value));1055 }1056 1057 switch (ArchKind) {1058 default:1059 break;1060 case llvm::ARM::ArchKind::ARMV8_1A:1061 getTargetDefinesARMV81A(Opts, Builder);1062 break;1063 case llvm::ARM::ArchKind::ARMV8_2A:1064 getTargetDefinesARMV82A(Opts, Builder);1065 break;1066 case llvm::ARM::ArchKind::ARMV8_3A:1067 case llvm::ARM::ArchKind::ARMV8_4A:1068 case llvm::ARM::ArchKind::ARMV8_5A:1069 case llvm::ARM::ArchKind::ARMV8_6A:1070 case llvm::ARM::ArchKind::ARMV8_7A:1071 case llvm::ARM::ArchKind::ARMV8_8A:1072 case llvm::ARM::ArchKind::ARMV8_9A:1073 case llvm::ARM::ArchKind::ARMV9A:1074 case llvm::ARM::ArchKind::ARMV9_1A:1075 case llvm::ARM::ArchKind::ARMV9_2A:1076 case llvm::ARM::ArchKind::ARMV9_3A:1077 case llvm::ARM::ArchKind::ARMV9_4A:1078 case llvm::ARM::ArchKind::ARMV9_5A:1079 case llvm::ARM::ArchKind::ARMV9_6A:1080 case llvm::ARM::ArchKind::ARMV9_7A:1081 getTargetDefinesARMV83A(Opts, Builder);1082 break;1083 }1084}1085 1086static constexpr int NumBuiltins = ARM::LastTSBuiltin - Builtin::FirstTSBuiltin;1087static constexpr int NumNeonBuiltins =1088 NEON::FirstFp16Builtin - Builtin::FirstTSBuiltin;1089static constexpr int NumFp16Builtins =1090 NEON::FirstTSBuiltin - NEON::FirstFp16Builtin;1091static constexpr int NumMVEBuiltins =1092 ARM::FirstCDEBuiltin - NEON::FirstTSBuiltin;1093static constexpr int NumCDEBuiltins =1094 ARM::FirstARMBuiltin - ARM::FirstCDEBuiltin;1095static constexpr int NumARMBuiltins = ARM::LastTSBuiltin - ARM::FirstARMBuiltin;1096static_assert(NumBuiltins ==1097 (NumNeonBuiltins + NumFp16Builtins + NumMVEBuiltins +1098 NumCDEBuiltins + NumARMBuiltins));1099 1100namespace clang {1101namespace NEON {1102#define GET_NEON_BUILTIN_STR_TABLE1103#include "clang/Basic/arm_neon.inc"1104#undef GET_NEON_BUILTIN_STR_TABLE1105 1106static constexpr std::array<Builtin::Info, NumNeonBuiltins> BuiltinInfos = {1107#define GET_NEON_BUILTIN_INFOS1108#include "clang/Basic/arm_neon.inc"1109#undef GET_NEON_BUILTIN_INFOS1110};1111 1112namespace FP16 {1113#define GET_NEON_BUILTIN_STR_TABLE1114#include "clang/Basic/arm_fp16.inc"1115#undef GET_NEON_BUILTIN_STR_TABLE1116 1117static constexpr std::array<Builtin::Info, NumFp16Builtins> BuiltinInfos = {1118#define GET_NEON_BUILTIN_INFOS1119#include "clang/Basic/arm_fp16.inc"1120#undef GET_NEON_BUILTIN_INFOS1121};1122} // namespace FP161123} // namespace NEON1124} // namespace clang1125 1126namespace {1127namespace MVE {1128#define GET_MVE_BUILTIN_STR_TABLE1129#include "clang/Basic/arm_mve_builtins.inc"1130#undef GET_MVE_BUILTIN_STR_TABLE1131 1132static constexpr std::array<Builtin::Info, NumMVEBuiltins> BuiltinInfos = {1133#define GET_MVE_BUILTIN_INFOS1134#include "clang/Basic/arm_mve_builtins.inc"1135#undef GET_MVE_BUILTIN_INFOS1136};1137} // namespace MVE1138 1139namespace CDE {1140#define GET_CDE_BUILTIN_STR_TABLE1141#include "clang/Basic/arm_cde_builtins.inc"1142#undef GET_CDE_BUILTIN_STR_TABLE1143 1144static constexpr std::array<Builtin::Info, NumCDEBuiltins> BuiltinInfos = {1145#define GET_CDE_BUILTIN_INFOS1146#include "clang/Basic/arm_cde_builtins.inc"1147#undef GET_CDE_BUILTIN_INFOS1148};1149} // namespace CDE1150} // namespace1151 1152static constexpr llvm::StringTable BuiltinStrings =1153 CLANG_BUILTIN_STR_TABLE_START1154#define BUILTIN CLANG_BUILTIN_STR_TABLE1155#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE1156#define TARGET_HEADER_BUILTIN CLANG_TARGET_HEADER_BUILTIN_STR_TABLE1157#include "clang/Basic/BuiltinsARM.def"1158 ; // namespace clang1159 1160static constexpr auto BuiltinInfos = Builtin::MakeInfos<NumARMBuiltins>({1161#define BUILTIN CLANG_BUILTIN_ENTRY1162#define LANGBUILTIN CLANG_LANGBUILTIN_ENTRY1163#define LIBBUILTIN CLANG_LIBBUILTIN_ENTRY1164#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY1165#define TARGET_HEADER_BUILTIN CLANG_TARGET_HEADER_BUILTIN_ENTRY1166#include "clang/Basic/BuiltinsARM.def"1167});1168 1169llvm::SmallVector<Builtin::InfosShard>1170ARMTargetInfo::getTargetBuiltins() const {1171 return {1172 {&NEON::BuiltinStrings, NEON::BuiltinInfos, "__builtin_neon_"},1173 {&NEON::FP16::BuiltinStrings, NEON::FP16::BuiltinInfos,1174 "__builtin_neon_"},1175 {&MVE::BuiltinStrings, MVE::BuiltinInfos, "__builtin_arm_mve_"},1176 {&CDE::BuiltinStrings, CDE::BuiltinInfos, "__builtin_arm_cde_"},1177 {&BuiltinStrings, BuiltinInfos},1178 };1179}1180 1181bool ARMTargetInfo::isCLZForZeroUndef() const { return false; }1182TargetInfo::BuiltinVaListKind ARMTargetInfo::getBuiltinVaListKind() const {1183 return IsAAPCS1184 ? AAPCSABIBuiltinVaList1185 : (getTriple().isWatchABI() ? TargetInfo::CharPtrBuiltinVaList1186 : TargetInfo::VoidPtrBuiltinVaList);1187}1188 1189const char *const ARMTargetInfo::GCCRegNames[] = {1190 // Integer registers1191 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",1192 "r12", "sp", "lr", "pc",1193 1194 // Float registers1195 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",1196 "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",1197 "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",1198 1199 // Double registers1200 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",1201 "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",1202 "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",1203 1204 // Quad registers1205 "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11",1206 "q12", "q13", "q14", "q15"};1207 1208ArrayRef<const char *> ARMTargetInfo::getGCCRegNames() const {1209 return llvm::ArrayRef(GCCRegNames);1210}1211 1212const TargetInfo::GCCRegAlias ARMTargetInfo::GCCRegAliases[] = {1213 {{"a1"}, "r0"}, {{"a2"}, "r1"}, {{"a3"}, "r2"}, {{"a4"}, "r3"},1214 {{"v1"}, "r4"}, {{"v2"}, "r5"}, {{"v3"}, "r6"}, {{"v4"}, "r7"},1215 {{"v5"}, "r8"}, {{"v6", "rfp"}, "r9"}, {{"sl"}, "r10"}, {{"fp"}, "r11"},1216 {{"ip"}, "r12"}, {{"r13"}, "sp"}, {{"r14"}, "lr"}, {{"r15"}, "pc"},1217 // The S, D and Q registers overlap, but aren't really aliases; we1218 // don't want to substitute one of these for a different-sized one.1219};1220 1221ArrayRef<TargetInfo::GCCRegAlias> ARMTargetInfo::getGCCRegAliases() const {1222 return llvm::ArrayRef(GCCRegAliases);1223}1224 1225bool ARMTargetInfo::validateAsmConstraint(1226 const char *&Name, TargetInfo::ConstraintInfo &Info) const {1227 switch (*Name) {1228 default:1229 break;1230 case 'l': // r0-r7 if thumb, r0-r15 if ARM1231 Info.setAllowsRegister();1232 return true;1233 case 'h': // r8-r15, thumb only1234 if (isThumb()) {1235 Info.setAllowsRegister();1236 return true;1237 }1238 break;1239 case 's': // An integer constant, but allowing only relocatable values.1240 return true;1241 case 't': // s0-s31, d0-d31, or q0-q151242 case 'w': // s0-s15, d0-d7, or q0-q31243 case 'x': // s0-s31, d0-d15, or q0-q71244 if (FPRegsDisabled)1245 return false;1246 Info.setAllowsRegister();1247 return true;1248 case 'j': // An immediate integer between 0 and 65535 (valid for MOVW)1249 // only available in ARMv6T2 and above1250 if (CPUAttr == "6T2" || ArchVersion >= 7) {1251 Info.setRequiresImmediate(0, 65535);1252 return true;1253 }1254 break;1255 case 'I':1256 if (isThumb()) {1257 if (!supportsThumb2())1258 Info.setRequiresImmediate(0, 255);1259 else1260 // FIXME: should check if immediate value would be valid for a Thumb21261 // data-processing instruction1262 Info.setRequiresImmediate();1263 } else1264 // FIXME: should check if immediate value would be valid for an ARM1265 // data-processing instruction1266 Info.setRequiresImmediate();1267 return true;1268 case 'J':1269 if (isThumb() && !supportsThumb2())1270 Info.setRequiresImmediate(-255, -1);1271 else1272 Info.setRequiresImmediate(-4095, 4095);1273 return true;1274 case 'K':1275 if (isThumb()) {1276 if (!supportsThumb2())1277 // FIXME: should check if immediate value can be obtained from shifting1278 // a value between 0 and 255 left by any amount1279 Info.setRequiresImmediate();1280 else1281 // FIXME: should check if immediate value would be valid for a Thumb21282 // data-processing instruction when inverted1283 Info.setRequiresImmediate();1284 } else1285 // FIXME: should check if immediate value would be valid for an ARM1286 // data-processing instruction when inverted1287 Info.setRequiresImmediate();1288 return true;1289 case 'L':1290 if (isThumb()) {1291 if (!supportsThumb2())1292 Info.setRequiresImmediate(-7, 7);1293 else1294 // FIXME: should check if immediate value would be valid for a Thumb21295 // data-processing instruction when negated1296 Info.setRequiresImmediate();1297 } else1298 // FIXME: should check if immediate value would be valid for an ARM1299 // data-processing instruction when negated1300 Info.setRequiresImmediate();1301 return true;1302 case 'M':1303 if (isThumb() && !supportsThumb2())1304 // FIXME: should check if immediate value is a multiple of 4 between 0 and1305 // 10201306 Info.setRequiresImmediate();1307 else1308 // FIXME: should check if immediate value is a power of two or a integer1309 // between 0 and 321310 Info.setRequiresImmediate();1311 return true;1312 case 'N':1313 // Thumb1 only1314 if (isThumb() && !supportsThumb2()) {1315 Info.setRequiresImmediate(0, 31);1316 return true;1317 }1318 break;1319 case 'O':1320 // Thumb1 only1321 if (isThumb() && !supportsThumb2()) {1322 // FIXME: should check if immediate value is a multiple of 4 between -5081323 // and 5081324 Info.setRequiresImmediate();1325 return true;1326 }1327 break;1328 case 'Q': // A memory address that is a single base register.1329 Info.setAllowsMemory();1330 return true;1331 case 'T':1332 switch (Name[1]) {1333 default:1334 break;1335 case 'e': // Even general-purpose register1336 case 'o': // Odd general-purpose register1337 Info.setAllowsRegister();1338 Name++;1339 return true;1340 }1341 break;1342 case 'U': // a memory reference...1343 switch (Name[1]) {1344 case 'q': // ...ARMV4 ldrsb1345 case 'v': // ...VFP load/store (reg+constant offset)1346 case 'y': // ...iWMMXt load/store1347 case 't': // address valid for load/store opaque types wider1348 // than 128-bits1349 case 'n': // valid address for Neon doubleword vector load/store1350 case 'm': // valid address for Neon element and structure load/store1351 case 's': // valid address for non-offset loads/stores of quad-word1352 // values in four ARM registers1353 Info.setAllowsMemory();1354 Name++;1355 return true;1356 }1357 break;1358 }1359 return false;1360}1361 1362std::string ARMTargetInfo::convertConstraint(const char *&Constraint) const {1363 std::string R;1364 switch (*Constraint) {1365 case 'U': // Two-character constraint; add "^" hint for later parsing.1366 case 'T':1367 R = std::string("^") + std::string(Constraint, 2);1368 Constraint++;1369 break;1370 case 'p': // 'p' should be translated to 'r' by default.1371 R = std::string("r");1372 break;1373 default:1374 return std::string(1, *Constraint);1375 }1376 return R;1377}1378 1379bool ARMTargetInfo::validateConstraintModifier(1380 StringRef Constraint, char Modifier, unsigned Size,1381 std::string &SuggestedModifier) const {1382 bool isOutput = (Constraint[0] == '=');1383 bool isInOut = (Constraint[0] == '+');1384 1385 // Strip off constraint modifiers.1386 Constraint = Constraint.ltrim("=+&");1387 1388 switch (Constraint[0]) {1389 default:1390 break;1391 case 'r': {1392 switch (Modifier) {1393 default:1394 return (isInOut || isOutput || Size <= 64);1395 case 'q':1396 // A register of size 32 cannot fit a vector type.1397 return false;1398 }1399 }1400 }1401 1402 return true;1403}1404std::string_view ARMTargetInfo::getClobbers() const {1405 // FIXME: Is this really right?1406 return "";1407}1408 1409TargetInfo::CallingConvCheckResult1410ARMTargetInfo::checkCallingConvention(CallingConv CC) const {1411 switch (CC) {1412 case CC_AAPCS:1413 case CC_AAPCS_VFP:1414 case CC_Swift:1415 case CC_SwiftAsync:1416 case CC_DeviceKernel:1417 return CCCR_OK;1418 default:1419 return CCCR_Warning;1420 }1421}1422 1423int ARMTargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {1424 if (RegNo == 0)1425 return 0;1426 if (RegNo == 1)1427 return 1;1428 return -1;1429}1430 1431bool ARMTargetInfo::hasSjLjLowering() const { return true; }1432 1433ARMleTargetInfo::ARMleTargetInfo(const llvm::Triple &Triple,1434 const TargetOptions &Opts)1435 : ARMTargetInfo(Triple, Opts) {}1436 1437void ARMleTargetInfo::getTargetDefines(const LangOptions &Opts,1438 MacroBuilder &Builder) const {1439 Builder.defineMacro("__ARMEL__");1440 ARMTargetInfo::getTargetDefines(Opts, Builder);1441}1442 1443ARMbeTargetInfo::ARMbeTargetInfo(const llvm::Triple &Triple,1444 const TargetOptions &Opts)1445 : ARMTargetInfo(Triple, Opts) {}1446 1447void ARMbeTargetInfo::getTargetDefines(const LangOptions &Opts,1448 MacroBuilder &Builder) const {1449 Builder.defineMacro("__ARMEB__");1450 Builder.defineMacro("__ARM_BIG_ENDIAN");1451 ARMTargetInfo::getTargetDefines(Opts, Builder);1452}1453 1454WindowsARMTargetInfo::WindowsARMTargetInfo(const llvm::Triple &Triple,1455 const TargetOptions &Opts)1456 : WindowsTargetInfo<ARMleTargetInfo>(Triple, Opts), Triple(Triple) {1457}1458 1459void WindowsARMTargetInfo::getVisualStudioDefines(const LangOptions &Opts,1460 MacroBuilder &Builder) const {1461 // FIXME: this is invalid for WindowsCE1462 Builder.defineMacro("_M_ARM_NT", "1");1463 Builder.defineMacro("_M_ARMT", "_M_ARM");1464 Builder.defineMacro("_M_THUMB", "_M_ARM");1465 1466 assert((Triple.getArch() == llvm::Triple::arm ||1467 Triple.getArch() == llvm::Triple::thumb) &&1468 "invalid architecture for Windows ARM target info");1469 unsigned Offset = Triple.getArch() == llvm::Triple::arm ? 4 : 6;1470 Builder.defineMacro("_M_ARM", Triple.getArchName().substr(Offset));1471 1472 // TODO map the complete set of values1473 // 31: VFPv3 40: VFPv41474 Builder.defineMacro("_M_ARM_FP", "31");1475}1476 1477TargetInfo::BuiltinVaListKind1478WindowsARMTargetInfo::getBuiltinVaListKind() const {1479 return TargetInfo::CharPtrBuiltinVaList;1480}1481 1482TargetInfo::CallingConvCheckResult1483WindowsARMTargetInfo::checkCallingConvention(CallingConv CC) const {1484 switch (CC) {1485 case CC_X86StdCall:1486 case CC_X86ThisCall:1487 case CC_X86FastCall:1488 case CC_X86VectorCall:1489 return CCCR_Ignore;1490 case CC_C:1491 case CC_DeviceKernel:1492 case CC_PreserveMost:1493 case CC_PreserveAll:1494 case CC_Swift:1495 case CC_SwiftAsync:1496 return CCCR_OK;1497 default:1498 return CCCR_Warning;1499 }1500}1501 1502// Windows ARM + Itanium C++ ABI Target1503ItaniumWindowsARMleTargetInfo::ItaniumWindowsARMleTargetInfo(1504 const llvm::Triple &Triple, const TargetOptions &Opts)1505 : WindowsARMTargetInfo(Triple, Opts) {1506 TheCXXABI.set(TargetCXXABI::GenericARM);1507}1508 1509void ItaniumWindowsARMleTargetInfo::getTargetDefines(1510 const LangOptions &Opts, MacroBuilder &Builder) const {1511 WindowsARMTargetInfo::getTargetDefines(Opts, Builder);1512 1513 if (Opts.MSVCCompat)1514 WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);1515}1516 1517// Windows ARM, MS (C++) ABI1518MicrosoftARMleTargetInfo::MicrosoftARMleTargetInfo(const llvm::Triple &Triple,1519 const TargetOptions &Opts)1520 : WindowsARMTargetInfo(Triple, Opts) {1521 TheCXXABI.set(TargetCXXABI::Microsoft);1522}1523 1524void MicrosoftARMleTargetInfo::getTargetDefines(const LangOptions &Opts,1525 MacroBuilder &Builder) const {1526 WindowsARMTargetInfo::getTargetDefines(Opts, Builder);1527 WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);1528}1529 1530MinGWARMTargetInfo::MinGWARMTargetInfo(const llvm::Triple &Triple,1531 const TargetOptions &Opts)1532 : WindowsARMTargetInfo(Triple, Opts) {1533 TheCXXABI.set(TargetCXXABI::GenericARM);1534}1535 1536void MinGWARMTargetInfo::getTargetDefines(const LangOptions &Opts,1537 MacroBuilder &Builder) const {1538 WindowsARMTargetInfo::getTargetDefines(Opts, Builder);1539 Builder.defineMacro("_ARM_");1540}1541 1542CygwinARMTargetInfo::CygwinARMTargetInfo(const llvm::Triple &Triple,1543 const TargetOptions &Opts)1544 : ARMleTargetInfo(Triple, Opts) {1545 this->WCharType = TargetInfo::UnsignedShort;1546 TLSSupported = false;1547 DoubleAlign = LongLongAlign = 64;1548 resetDataLayout("e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64");1549}1550 1551void CygwinARMTargetInfo::getTargetDefines(const LangOptions &Opts,1552 MacroBuilder &Builder) const {1553 ARMleTargetInfo::getTargetDefines(Opts, Builder);1554 Builder.defineMacro("_ARM_");1555 Builder.defineMacro("__CYGWIN__");1556 Builder.defineMacro("__CYGWIN32__");1557 DefineStd(Builder, "unix", Opts);1558 if (Opts.CPlusPlus)1559 Builder.defineMacro("_GNU_SOURCE");1560}1561 1562AppleMachOARMTargetInfo::AppleMachOARMTargetInfo(const llvm::Triple &Triple,1563 const TargetOptions &Opts)1564 : AppleMachOTargetInfo<ARMleTargetInfo>(Triple, Opts) {}1565 1566void AppleMachOARMTargetInfo::getOSDefines(const LangOptions &Opts,1567 const llvm::Triple &Triple,1568 MacroBuilder &Builder) const {1569 getAppleMachODefines(Builder, Opts, Triple);1570}1571 1572DarwinARMTargetInfo::DarwinARMTargetInfo(const llvm::Triple &Triple,1573 const TargetOptions &Opts)1574 : DarwinTargetInfo<ARMleTargetInfo>(Triple, Opts) {1575 HasAlignMac68kSupport = true;1576 if (Triple.isWatchABI()) {1577 // Darwin on iOS uses a variant of the ARM C++ ABI.1578 TheCXXABI.set(TargetCXXABI::WatchOS);1579 1580 // BOOL should be a real boolean on the new ABI1581 UseSignedCharForObjCBool = false;1582 } else1583 TheCXXABI.set(TargetCXXABI::iOS);1584}1585 1586void DarwinARMTargetInfo::getOSDefines(const LangOptions &Opts,1587 const llvm::Triple &Triple,1588 MacroBuilder &Builder) const {1589 getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);1590}1591