Path: blob/main/contrib/llvm-project/clang/lib/Basic/Targets/ARM.cpp
35266 views
//===--- ARM.cpp - Implement ARM target feature support -------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements ARM TargetInfo objects.9//10//===----------------------------------------------------------------------===//1112#include "ARM.h"13#include "clang/Basic/Builtins.h"14#include "clang/Basic/Diagnostic.h"15#include "clang/Basic/TargetBuiltins.h"16#include "llvm/ADT/StringExtras.h"17#include "llvm/ADT/StringRef.h"18#include "llvm/ADT/StringSwitch.h"19#include "llvm/TargetParser/ARMTargetParser.h"2021using namespace clang;22using namespace clang::targets;2324void ARMTargetInfo::setABIAAPCS() {25IsAAPCS = true;2627DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;28BFloat16Width = BFloat16Align = 16;29BFloat16Format = &llvm::APFloat::BFloat();3031const llvm::Triple &T = getTriple();3233bool IsNetBSD = T.isOSNetBSD();34bool IsOpenBSD = T.isOSOpenBSD();35if (!T.isOSWindows() && !IsNetBSD && !IsOpenBSD)36WCharType = UnsignedInt;3738UseBitFieldTypeAlignment = true;3940ZeroLengthBitfieldBoundary = 0;4142// Thumb1 add sp, #imm requires the immediate value be multiple of 4,43// so set preferred for small types to 32.44if (T.isOSBinFormatMachO()) {45resetDataLayout(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()) {50assert(!BigEndian && "Windows on ARM does not support big endian");51resetDataLayout("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 if (T.isOSNaCl()) {61assert(!BigEndian && "NaCl on ARM does not support big endian");62resetDataLayout("e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S128");63} else {64resetDataLayout(BigEndian65? "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"66: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64");67}6869// FIXME: Enumerated types are variable width in straight AAPCS.70}7172void ARMTargetInfo::setABIAPCS(bool IsAAPCS16) {73const llvm::Triple &T = getTriple();7475IsAAPCS = false;7677if (IsAAPCS16)78DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;79else80DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 32;81BFloat16Width = BFloat16Align = 16;82BFloat16Format = &llvm::APFloat::BFloat();8384WCharType = SignedInt;8586// Do not respect the alignment of bit-field types when laying out87// structures. This corresponds to PCC_BITFIELD_TYPE_MATTERS in gcc.88UseBitFieldTypeAlignment = false;8990/// gcc forces the alignment to 4 bytes, regardless of the type of the91/// zero length bitfield. This corresponds to EMPTY_FIELD_BOUNDARY in92/// gcc.93ZeroLengthBitfieldBoundary = 32;9495if (T.isOSBinFormatMachO() && IsAAPCS16) {96assert(!BigEndian && "AAPCS16 does not support big-endian");97resetDataLayout("e-m:o-p:32:32-Fi8-i64:64-a:0:32-n32-S128", "_");98} else if (T.isOSBinFormatMachO())99resetDataLayout(100BigEndian101? "E-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"102: "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32",103"_");104else105resetDataLayout(106BigEndian107? "E-m:e-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"108: "e-m:e-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32");109110// FIXME: Override "preferred align" for double and long long.111}112113void ARMTargetInfo::setArchInfo() {114StringRef ArchName = getTriple().getArchName();115116ArchISA = llvm::ARM::parseArchISA(ArchName);117CPU = std::string(llvm::ARM::getDefaultCPU(ArchName));118llvm::ARM::ArchKind AK = llvm::ARM::parseArch(ArchName);119if (AK != llvm::ARM::ArchKind::INVALID)120ArchKind = AK;121setArchInfo(ArchKind);122}123124void ARMTargetInfo::setArchInfo(llvm::ARM::ArchKind Kind) {125StringRef SubArch;126127// cache TargetParser info128ArchKind = Kind;129SubArch = llvm::ARM::getSubArch(ArchKind);130ArchProfile = llvm::ARM::parseArchProfile(SubArch);131ArchVersion = llvm::ARM::parseArchVersion(SubArch);132133// cache CPU related strings134CPUAttr = getCPUAttr();135CPUProfile = getCPUProfile();136}137138void ARMTargetInfo::setAtomic() {139// when triple does not specify a sub arch,140// then we are not using inline atomics141bool ShouldUseInlineAtomic =142(ArchISA == llvm::ARM::ISAKind::ARM && ArchVersion >= 6) ||143(ArchISA == llvm::ARM::ISAKind::THUMB && ArchVersion >= 7);144// Cortex M does not support 8 byte atomics, while general Thumb2 does.145if (ArchProfile == llvm::ARM::ProfileKind::M) {146MaxAtomicPromoteWidth = 32;147if (ShouldUseInlineAtomic)148MaxAtomicInlineWidth = 32;149} else {150MaxAtomicPromoteWidth = 64;151if (ShouldUseInlineAtomic)152MaxAtomicInlineWidth = 64;153}154}155156bool ARMTargetInfo::hasMVE() const {157return ArchKind == llvm::ARM::ArchKind::ARMV8_1MMainline && MVE != 0;158}159160bool ARMTargetInfo::hasMVEFloat() const {161return hasMVE() && (MVE & MVE_FP);162}163164bool ARMTargetInfo::hasCDE() const { return getARMCDECoprocMask() != 0; }165166bool ARMTargetInfo::isThumb() const {167return ArchISA == llvm::ARM::ISAKind::THUMB;168}169170bool ARMTargetInfo::supportsThumb() const {171return CPUAttr.count('T') || ArchVersion >= 6;172}173174bool ARMTargetInfo::supportsThumb2() const {175return CPUAttr == "6T2" || (ArchVersion >= 7 && CPUAttr != "8M_BASE");176}177178StringRef ARMTargetInfo::getCPUAttr() const {179// For most sub-arches, the build attribute CPU name is enough.180// For Cortex variants, it's slightly different.181switch (ArchKind) {182default:183return llvm::ARM::getCPUAttr(ArchKind);184case llvm::ARM::ArchKind::ARMV6M:185return "6M";186case llvm::ARM::ArchKind::ARMV7S:187return "7S";188case llvm::ARM::ArchKind::ARMV7A:189return "7A";190case llvm::ARM::ArchKind::ARMV7R:191return "7R";192case llvm::ARM::ArchKind::ARMV7M:193return "7M";194case llvm::ARM::ArchKind::ARMV7EM:195return "7EM";196case llvm::ARM::ArchKind::ARMV7VE:197return "7VE";198case llvm::ARM::ArchKind::ARMV8A:199return "8A";200case llvm::ARM::ArchKind::ARMV8_1A:201return "8_1A";202case llvm::ARM::ArchKind::ARMV8_2A:203return "8_2A";204case llvm::ARM::ArchKind::ARMV8_3A:205return "8_3A";206case llvm::ARM::ArchKind::ARMV8_4A:207return "8_4A";208case llvm::ARM::ArchKind::ARMV8_5A:209return "8_5A";210case llvm::ARM::ArchKind::ARMV8_6A:211return "8_6A";212case llvm::ARM::ArchKind::ARMV8_7A:213return "8_7A";214case llvm::ARM::ArchKind::ARMV8_8A:215return "8_8A";216case llvm::ARM::ArchKind::ARMV8_9A:217return "8_9A";218case llvm::ARM::ArchKind::ARMV9A:219return "9A";220case llvm::ARM::ArchKind::ARMV9_1A:221return "9_1A";222case llvm::ARM::ArchKind::ARMV9_2A:223return "9_2A";224case llvm::ARM::ArchKind::ARMV9_3A:225return "9_3A";226case llvm::ARM::ArchKind::ARMV9_4A:227return "9_4A";228case llvm::ARM::ArchKind::ARMV9_5A:229return "9_5A";230case llvm::ARM::ArchKind::ARMV8MBaseline:231return "8M_BASE";232case llvm::ARM::ArchKind::ARMV8MMainline:233return "8M_MAIN";234case llvm::ARM::ArchKind::ARMV8R:235return "8R";236case llvm::ARM::ArchKind::ARMV8_1MMainline:237return "8_1M_MAIN";238}239}240241StringRef ARMTargetInfo::getCPUProfile() const {242switch (ArchProfile) {243case llvm::ARM::ProfileKind::A:244return "A";245case llvm::ARM::ProfileKind::R:246return "R";247case llvm::ARM::ProfileKind::M:248return "M";249default:250return "";251}252}253254ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple,255const TargetOptions &Opts)256: TargetInfo(Triple), FPMath(FP_Default), IsAAPCS(true), LDREX(0),257HW_FP(0) {258bool IsFreeBSD = Triple.isOSFreeBSD();259bool IsOpenBSD = Triple.isOSOpenBSD();260bool IsNetBSD = Triple.isOSNetBSD();261bool IsHaiku = Triple.isOSHaiku();262bool IsOHOS = Triple.isOHOSFamily();263264// FIXME: the isOSBinFormatMachO is a workaround for identifying a Darwin-like265// environment where size_t is `unsigned long` rather than `unsigned int`266267PtrDiffType = IntPtrType =268(Triple.isOSDarwin() || Triple.isOSBinFormatMachO() || IsOpenBSD ||269IsNetBSD)270? SignedLong271: SignedInt;272273SizeType = (Triple.isOSDarwin() || Triple.isOSBinFormatMachO() || IsOpenBSD ||274IsNetBSD)275? UnsignedLong276: UnsignedInt;277278// ptrdiff_t is inconsistent on Darwin279if ((Triple.isOSDarwin() || Triple.isOSBinFormatMachO()) &&280!Triple.isWatchABI())281PtrDiffType = SignedInt;282283// Cache arch related info.284setArchInfo();285286// {} in inline assembly are neon specifiers, not assembly variant287// specifiers.288NoAsmVariants = true;289290// FIXME: This duplicates code from the driver that sets the -target-abi291// option - this code is used if -target-abi isn't passed and should292// be unified in some way.293if (Triple.isOSBinFormatMachO()) {294// The backend is hardwired to assume AAPCS for M-class processors, ensure295// the frontend matches that.296if (Triple.getEnvironment() == llvm::Triple::EABI ||297Triple.getOS() == llvm::Triple::UnknownOS ||298ArchProfile == llvm::ARM::ProfileKind::M) {299setABI("aapcs");300} else if (Triple.isWatchABI()) {301setABI("aapcs16");302} else {303setABI("apcs-gnu");304}305} else if (Triple.isOSWindows()) {306// FIXME: this is invalid for WindowsCE307setABI("aapcs");308} else {309// Select the default based on the platform.310switch (Triple.getEnvironment()) {311case llvm::Triple::Android:312case llvm::Triple::GNUEABI:313case llvm::Triple::GNUEABIT64:314case llvm::Triple::GNUEABIHF:315case llvm::Triple::GNUEABIHFT64:316case llvm::Triple::MuslEABI:317case llvm::Triple::MuslEABIHF:318case llvm::Triple::OpenHOS:319setABI("aapcs-linux");320break;321case llvm::Triple::EABIHF:322case llvm::Triple::EABI:323setABI("aapcs");324break;325case llvm::Triple::GNU:326setABI("apcs-gnu");327break;328default:329if (IsNetBSD)330setABI("apcs-gnu");331else if (IsFreeBSD || IsOpenBSD || IsHaiku || IsOHOS)332setABI("aapcs-linux");333else334setABI("aapcs");335break;336}337}338339// ARM targets default to using the ARM C++ ABI.340TheCXXABI.set(TargetCXXABI::GenericARM);341342// ARM has atomics up to 8 bytes343setAtomic();344345// Maximum alignment for ARM NEON data types should be 64-bits (AAPCS)346// as well the default alignment347if (IsAAPCS && !Triple.isAndroid())348DefaultAlignForAttributeAligned = MaxVectorAlign = 64;349350// Do force alignment of members that follow zero length bitfields. If351// the alignment of the zero-length bitfield is greater than the member352// that follows it, `bar', `bar' will be aligned as the type of the353// zero length bitfield.354UseZeroLengthBitfieldAlignment = true;355356if (Triple.getOS() == llvm::Triple::Linux ||357Triple.getOS() == llvm::Triple::UnknownOS)358this->MCountName = Opts.EABIVersion == llvm::EABI::GNU359? "llvm.arm.gnu.eabi.mcount"360: "\01mcount";361362SoftFloatABI = llvm::is_contained(Opts.FeaturesAsWritten, "+soft-float-abi");363}364365StringRef ARMTargetInfo::getABI() const { return ABI; }366367bool ARMTargetInfo::setABI(const std::string &Name) {368ABI = Name;369370// The defaults (above) are for AAPCS, check if we need to change them.371//372// FIXME: We need support for -meabi... we could just mangle it into the373// name.374if (Name == "apcs-gnu" || Name == "aapcs16") {375setABIAPCS(Name == "aapcs16");376return true;377}378if (Name == "aapcs" || Name == "aapcs-vfp" || Name == "aapcs-linux") {379setABIAAPCS();380return true;381}382return false;383}384385bool ARMTargetInfo::isBranchProtectionSupportedArch(StringRef Arch) const {386llvm::ARM::ArchKind CPUArch = llvm::ARM::parseCPUArch(Arch);387if (CPUArch == llvm::ARM::ArchKind::INVALID)388CPUArch = llvm::ARM::parseArch(getTriple().getArchName());389390if (CPUArch == llvm::ARM::ArchKind::INVALID)391return false;392393StringRef ArchFeature = llvm::ARM::getArchName(CPUArch);394auto a =395llvm::Triple(ArchFeature, getTriple().getVendorName(),396getTriple().getOSName(), getTriple().getEnvironmentName());397398StringRef SubArch = llvm::ARM::getSubArch(CPUArch);399llvm::ARM::ProfileKind Profile = llvm::ARM::parseArchProfile(SubArch);400return a.isArmT32() && (Profile == llvm::ARM::ProfileKind::M);401}402403bool ARMTargetInfo::validateBranchProtection(StringRef Spec, StringRef Arch,404BranchProtectionInfo &BPI,405StringRef &Err) const {406llvm::ARM::ParsedBranchProtection PBP;407if (!llvm::ARM::parseBranchProtection(Spec, PBP, Err))408return false;409410if (!isBranchProtectionSupportedArch(Arch))411return false;412413BPI.SignReturnAddr =414llvm::StringSwitch<LangOptions::SignReturnAddressScopeKind>(PBP.Scope)415.Case("non-leaf", LangOptions::SignReturnAddressScopeKind::NonLeaf)416.Case("all", LangOptions::SignReturnAddressScopeKind::All)417.Default(LangOptions::SignReturnAddressScopeKind::None);418419// Don't care for the sign key, beyond issuing a warning.420if (PBP.Key == "b_key")421Err = "b-key";422BPI.SignKey = LangOptions::SignReturnAddressKeyKind::AKey;423424BPI.BranchTargetEnforcement = PBP.BranchTargetEnforcement;425BPI.BranchProtectionPAuthLR = PBP.BranchProtectionPAuthLR;426return true;427}428429// FIXME: This should be based on Arch attributes, not CPU names.430bool ARMTargetInfo::initFeatureMap(431llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,432const std::vector<std::string> &FeaturesVec) const {433434std::string ArchFeature;435std::vector<StringRef> TargetFeatures;436llvm::ARM::ArchKind Arch = llvm::ARM::parseArch(getTriple().getArchName());437438// Map the base architecture to an appropriate target feature, so we don't439// rely on the target triple.440llvm::ARM::ArchKind CPUArch = llvm::ARM::parseCPUArch(CPU);441if (CPUArch == llvm::ARM::ArchKind::INVALID)442CPUArch = Arch;443if (CPUArch != llvm::ARM::ArchKind::INVALID) {444ArchFeature = ("+" + llvm::ARM::getArchName(CPUArch)).str();445TargetFeatures.push_back(ArchFeature);446447// These features are added to allow arm_neon.h target(..) attributes to448// match with both arm and aarch64. We need to add all previous architecture449// versions, so that "8.6" also allows "8.1" functions. In case of v9.x the450// v8.x counterparts are added too. We only need these for anything > 8.0-A.451for (llvm::ARM::ArchKind I = llvm::ARM::convertV9toV8(CPUArch);452I != llvm::ARM::ArchKind::INVALID; --I)453Features[llvm::ARM::getSubArch(I)] = true;454if (CPUArch > llvm::ARM::ArchKind::ARMV8A &&455CPUArch <= llvm::ARM::ArchKind::ARMV9_3A)456for (llvm::ARM::ArchKind I = CPUArch; I != llvm::ARM::ArchKind::INVALID;457--I)458Features[llvm::ARM::getSubArch(I)] = true;459}460461// get default FPU features462llvm::ARM::FPUKind FPUKind = llvm::ARM::getDefaultFPU(CPU, Arch);463llvm::ARM::getFPUFeatures(FPUKind, TargetFeatures);464465// get default Extension features466uint64_t Extensions = llvm::ARM::getDefaultExtensions(CPU, Arch);467llvm::ARM::getExtensionFeatures(Extensions, TargetFeatures);468469for (auto Feature : TargetFeatures)470if (Feature[0] == '+')471Features[Feature.drop_front(1)] = true;472473// Enable or disable thumb-mode explicitly per function to enable mixed474// ARM and Thumb code generation.475if (isThumb())476Features["thumb-mode"] = true;477else478Features["thumb-mode"] = false;479480// Convert user-provided arm and thumb GNU target attributes to481// [-|+]thumb-mode target features respectively.482std::vector<std::string> UpdatedFeaturesVec;483for (const auto &Feature : FeaturesVec) {484// Skip soft-float-abi; it's something we only use to initialize a bit of485// class state, and is otherwise unrecognized.486if (Feature == "+soft-float-abi")487continue;488489StringRef FixedFeature;490if (Feature == "+arm")491FixedFeature = "-thumb-mode";492else if (Feature == "+thumb")493FixedFeature = "+thumb-mode";494else495FixedFeature = Feature;496UpdatedFeaturesVec.push_back(FixedFeature.str());497}498499return TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeaturesVec);500}501502503bool ARMTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,504DiagnosticsEngine &Diags) {505FPU = 0;506MVE = 0;507CRC = 0;508Crypto = 0;509SHA2 = 0;510AES = 0;511DSP = 0;512HasUnalignedAccess = true;513SoftFloat = false;514// Note that SoftFloatABI is initialized in our constructor.515HWDiv = 0;516DotProd = 0;517HasMatMul = 0;518HasPAC = 0;519HasBTI = 0;520HasFloat16 = true;521ARMCDECoprocMask = 0;522HasBFloat16 = false;523HasFullBFloat16 = false;524FPRegsDisabled = false;525526// This does not diagnose illegal cases like having both527// "+vfpv2" and "+vfpv3" or having "+neon" and "-fp64".528for (const auto &Feature : Features) {529if (Feature == "+soft-float") {530SoftFloat = true;531} else if (Feature == "+vfp2sp" || Feature == "+vfp2") {532FPU |= VFP2FPU;533HW_FP |= HW_FP_SP;534if (Feature == "+vfp2")535HW_FP |= HW_FP_DP;536} else if (Feature == "+vfp3sp" || Feature == "+vfp3d16sp" ||537Feature == "+vfp3" || Feature == "+vfp3d16") {538FPU |= VFP3FPU;539HW_FP |= HW_FP_SP;540if (Feature == "+vfp3" || Feature == "+vfp3d16")541HW_FP |= HW_FP_DP;542} else if (Feature == "+vfp4sp" || Feature == "+vfp4d16sp" ||543Feature == "+vfp4" || Feature == "+vfp4d16") {544FPU |= VFP4FPU;545HW_FP |= HW_FP_SP | HW_FP_HP;546if (Feature == "+vfp4" || Feature == "+vfp4d16")547HW_FP |= HW_FP_DP;548} else if (Feature == "+fp-armv8sp" || Feature == "+fp-armv8d16sp" ||549Feature == "+fp-armv8" || Feature == "+fp-armv8d16") {550FPU |= FPARMV8;551HW_FP |= HW_FP_SP | HW_FP_HP;552if (Feature == "+fp-armv8" || Feature == "+fp-armv8d16")553HW_FP |= HW_FP_DP;554} else if (Feature == "+neon") {555FPU |= NeonFPU;556HW_FP |= HW_FP_SP;557} else if (Feature == "+hwdiv") {558HWDiv |= HWDivThumb;559} else if (Feature == "+hwdiv-arm") {560HWDiv |= HWDivARM;561} else if (Feature == "+crc") {562CRC = 1;563} else if (Feature == "+crypto") {564Crypto = 1;565} else if (Feature == "+sha2") {566SHA2 = 1;567} else if (Feature == "+aes") {568AES = 1;569} else if (Feature == "+dsp") {570DSP = 1;571} else if (Feature == "+fp64") {572HW_FP |= HW_FP_DP;573} else if (Feature == "+8msecext") {574if (CPUProfile != "M" || ArchVersion != 8) {575Diags.Report(diag::err_target_unsupported_mcmse) << CPU;576return false;577}578} else if (Feature == "+strict-align") {579HasUnalignedAccess = false;580} else if (Feature == "+fp16") {581HW_FP |= HW_FP_HP;582} else if (Feature == "+fullfp16") {583HasLegalHalfType = true;584} else if (Feature == "+dotprod") {585DotProd = true;586} else if (Feature == "+mve") {587MVE |= MVE_INT;588} else if (Feature == "+mve.fp") {589HasLegalHalfType = true;590FPU |= FPARMV8;591MVE |= MVE_INT | MVE_FP;592HW_FP |= HW_FP_SP | HW_FP_HP;593} else if (Feature == "+i8mm") {594HasMatMul = 1;595} else if (Feature.size() == strlen("+cdecp0") && Feature >= "+cdecp0" &&596Feature <= "+cdecp7") {597unsigned Coproc = Feature.back() - '0';598ARMCDECoprocMask |= (1U << Coproc);599} else if (Feature == "+bf16") {600HasBFloat16 = true;601} else if (Feature == "-fpregs") {602FPRegsDisabled = true;603} else if (Feature == "+pacbti") {604HasPAC = 1;605HasBTI = 1;606} else if (Feature == "+fullbf16") {607HasFullBFloat16 = true;608}609}610611HalfArgsAndReturns = true;612613switch (ArchVersion) {614case 6:615if (ArchProfile == llvm::ARM::ProfileKind::M)616LDREX = 0;617else if (ArchKind == llvm::ARM::ArchKind::ARMV6K)618LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;619else620LDREX = LDREX_W;621break;622case 7:623if (ArchProfile == llvm::ARM::ProfileKind::M)624LDREX = LDREX_W | LDREX_H | LDREX_B;625else626LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;627break;628case 8:629case 9:630LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;631}632633if (!(FPU & NeonFPU) && FPMath == FP_Neon) {634Diags.Report(diag::err_target_unsupported_fpmath) << "neon";635return false;636}637638if (FPMath == FP_Neon)639Features.push_back("+neonfp");640else if (FPMath == FP_VFP)641Features.push_back("-neonfp");642643return true;644}645646bool ARMTargetInfo::hasFeature(StringRef Feature) const {647return llvm::StringSwitch<bool>(Feature)648.Case("arm", true)649.Case("aarch32", true)650.Case("softfloat", SoftFloat)651.Case("thumb", isThumb())652.Case("neon", (FPU & NeonFPU) && !SoftFloat)653.Case("vfp", FPU && !SoftFloat)654.Case("hwdiv", HWDiv & HWDivThumb)655.Case("hwdiv-arm", HWDiv & HWDivARM)656.Case("mve", hasMVE())657.Default(false);658}659660bool ARMTargetInfo::hasBFloat16Type() const {661// The __bf16 type is generally available so long as we have any fp registers.662return HasBFloat16 || (FPU && !SoftFloat);663}664665bool ARMTargetInfo::isValidCPUName(StringRef Name) const {666return Name == "generic" ||667llvm::ARM::parseCPUArch(Name) != llvm::ARM::ArchKind::INVALID;668}669670void ARMTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const {671llvm::ARM::fillValidCPUArchList(Values);672}673674bool ARMTargetInfo::setCPU(const std::string &Name) {675if (Name != "generic")676setArchInfo(llvm::ARM::parseCPUArch(Name));677678if (ArchKind == llvm::ARM::ArchKind::INVALID)679return false;680setAtomic();681CPU = Name;682return true;683}684685bool ARMTargetInfo::setFPMath(StringRef Name) {686if (Name == "neon") {687FPMath = FP_Neon;688return true;689} else if (Name == "vfp" || Name == "vfp2" || Name == "vfp3" ||690Name == "vfp4") {691FPMath = FP_VFP;692return true;693}694return false;695}696697void ARMTargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,698MacroBuilder &Builder) const {699Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");700}701702void ARMTargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts,703MacroBuilder &Builder) const {704// Also include the ARMv8.1-A defines705getTargetDefinesARMV81A(Opts, Builder);706}707708void ARMTargetInfo::getTargetDefinesARMV83A(const LangOptions &Opts,709MacroBuilder &Builder) const {710// Also include the ARMv8.2-A defines711Builder.defineMacro("__ARM_FEATURE_COMPLEX", "1");712getTargetDefinesARMV82A(Opts, Builder);713}714715void ARMTargetInfo::getTargetDefines(const LangOptions &Opts,716MacroBuilder &Builder) const {717// Target identification.718Builder.defineMacro("__arm");719Builder.defineMacro("__arm__");720// For bare-metal none-eabi.721if (getTriple().getOS() == llvm::Triple::UnknownOS &&722(getTriple().getEnvironment() == llvm::Triple::EABI ||723getTriple().getEnvironment() == llvm::Triple::EABIHF) &&724Opts.CPlusPlus) {725Builder.defineMacro("_GNU_SOURCE");726}727728// Target properties.729Builder.defineMacro("__REGISTER_PREFIX__", "");730731// Unfortunately, __ARM_ARCH_7K__ is now more of an ABI descriptor. The CPU732// happens to be Cortex-A7 though, so it should still get __ARM_ARCH_7A__.733if (getTriple().isWatchABI())734Builder.defineMacro("__ARM_ARCH_7K__", "2");735736if (!CPUAttr.empty())737Builder.defineMacro("__ARM_ARCH_" + CPUAttr + "__");738739// ACLE 6.4.1 ARM/Thumb instruction set architecture740// __ARM_ARCH is defined as an integer value indicating the current ARM ISA741Builder.defineMacro("__ARM_ARCH", Twine(ArchVersion));742743if (ArchVersion >= 8) {744// ACLE 6.5.7 Crypto Extension745// The __ARM_FEATURE_CRYPTO is deprecated in favor of finer grained746// feature macros for AES and SHA2747if (SHA2 && AES)748Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");749if (SHA2)750Builder.defineMacro("__ARM_FEATURE_SHA2", "1");751if (AES)752Builder.defineMacro("__ARM_FEATURE_AES", "1");753// ACLE 6.5.8 CRC32 Extension754if (CRC)755Builder.defineMacro("__ARM_FEATURE_CRC32", "1");756// ACLE 6.5.10 Numeric Maximum and Minimum757Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");758// ACLE 6.5.9 Directed Rounding759Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");760}761762// __ARM_ARCH_ISA_ARM is defined to 1 if the core supports the ARM ISA. It763// is not defined for the M-profile.764// NOTE that the default profile is assumed to be 'A'765if (CPUProfile.empty() || ArchProfile != llvm::ARM::ProfileKind::M)766Builder.defineMacro("__ARM_ARCH_ISA_ARM", "1");767768// __ARM_ARCH_ISA_THUMB is defined to 1 if the core supports the original769// Thumb ISA (including v6-M and v8-M Baseline). It is set to 2 if the770// core supports the Thumb-2 ISA as found in the v6T2 architecture and all771// v7 and v8 architectures excluding v8-M Baseline.772if (supportsThumb2())773Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "2");774else if (supportsThumb())775Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "1");776777// __ARM_32BIT_STATE is defined to 1 if code is being generated for a 32-bit778// instruction set such as ARM or Thumb.779Builder.defineMacro("__ARM_32BIT_STATE", "1");780781// ACLE 6.4.2 Architectural Profile (A, R, M or pre-Cortex)782783// __ARM_ARCH_PROFILE is defined as 'A', 'R', 'M' or 'S', or unset.784if (!CPUProfile.empty())785Builder.defineMacro("__ARM_ARCH_PROFILE", "'" + CPUProfile + "'");786787// ACLE 6.4.3 Unaligned access supported in hardware788if (HasUnalignedAccess)789Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");790791// ACLE 6.4.4 LDREX/STREX792if (LDREX)793Builder.defineMacro("__ARM_FEATURE_LDREX", "0x" + Twine::utohexstr(LDREX));794795// ACLE 6.4.5 CLZ796if (ArchVersion == 5 || (ArchVersion == 6 && CPUProfile != "M") ||797ArchVersion > 6)798Builder.defineMacro("__ARM_FEATURE_CLZ", "1");799800// ACLE 6.5.1 Hardware Floating Point801if (HW_FP)802Builder.defineMacro("__ARM_FP", "0x" + Twine::utohexstr(HW_FP));803804// ACLE predefines.805Builder.defineMacro("__ARM_ACLE", "200");806807// FP16 support (we currently only support IEEE format).808Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");809Builder.defineMacro("__ARM_FP16_ARGS", "1");810811// ACLE 6.5.3 Fused multiply-accumulate (FMA)812if (ArchVersion >= 7 && (FPU & VFP4FPU))813Builder.defineMacro("__ARM_FEATURE_FMA", "1");814815// Subtarget options.816817// FIXME: It's more complicated than this and we don't really support818// interworking.819// Windows on ARM does not "support" interworking820if (5 <= ArchVersion && ArchVersion <= 8 && !getTriple().isOSWindows())821Builder.defineMacro("__THUMB_INTERWORK__");822823if (ABI == "aapcs" || ABI == "aapcs-linux" || ABI == "aapcs-vfp") {824// Embedded targets on Darwin follow AAPCS, but not EABI.825// Windows on ARM follows AAPCS VFP, but does not conform to EABI.826if (!getTriple().isOSBinFormatMachO() && !getTriple().isOSWindows())827Builder.defineMacro("__ARM_EABI__");828Builder.defineMacro("__ARM_PCS", "1");829}830831if ((!SoftFloat && !SoftFloatABI) || ABI == "aapcs-vfp" || ABI == "aapcs16")832Builder.defineMacro("__ARM_PCS_VFP", "1");833834if (SoftFloat || (SoftFloatABI && !FPU))835Builder.defineMacro("__SOFTFP__");836837// ACLE position independent code macros.838if (Opts.ROPI)839Builder.defineMacro("__ARM_ROPI", "1");840if (Opts.RWPI)841Builder.defineMacro("__ARM_RWPI", "1");842843// Macros for enabling co-proc intrinsics844uint64_t FeatureCoprocBF = 0;845switch (ArchKind) {846default:847break;848case llvm::ARM::ArchKind::ARMV4:849case llvm::ARM::ArchKind::ARMV4T:850// Filter __arm_ldcl and __arm_stcl in acle.h851FeatureCoprocBF = isThumb() ? 0 : FEATURE_COPROC_B1;852break;853case llvm::ARM::ArchKind::ARMV5T:854FeatureCoprocBF = isThumb() ? 0 : FEATURE_COPROC_B1 | FEATURE_COPROC_B2;855break;856case llvm::ARM::ArchKind::ARMV5TE:857case llvm::ARM::ArchKind::ARMV5TEJ:858if (!isThumb())859FeatureCoprocBF =860FEATURE_COPROC_B1 | FEATURE_COPROC_B2 | FEATURE_COPROC_B3;861break;862case llvm::ARM::ArchKind::ARMV6:863case llvm::ARM::ArchKind::ARMV6K:864case llvm::ARM::ArchKind::ARMV6KZ:865case llvm::ARM::ArchKind::ARMV6T2:866if (!isThumb() || ArchKind == llvm::ARM::ArchKind::ARMV6T2)867FeatureCoprocBF = FEATURE_COPROC_B1 | FEATURE_COPROC_B2 |868FEATURE_COPROC_B3 | FEATURE_COPROC_B4;869break;870case llvm::ARM::ArchKind::ARMV7A:871case llvm::ARM::ArchKind::ARMV7R:872case llvm::ARM::ArchKind::ARMV7M:873case llvm::ARM::ArchKind::ARMV7S:874case llvm::ARM::ArchKind::ARMV7EM:875FeatureCoprocBF = FEATURE_COPROC_B1 | FEATURE_COPROC_B2 |876FEATURE_COPROC_B3 | FEATURE_COPROC_B4;877break;878case llvm::ARM::ArchKind::ARMV8A:879case llvm::ARM::ArchKind::ARMV8R:880case llvm::ARM::ArchKind::ARMV8_1A:881case llvm::ARM::ArchKind::ARMV8_2A:882case llvm::ARM::ArchKind::ARMV8_3A:883case llvm::ARM::ArchKind::ARMV8_4A:884case llvm::ARM::ArchKind::ARMV8_5A:885case llvm::ARM::ArchKind::ARMV8_6A:886case llvm::ARM::ArchKind::ARMV8_7A:887case llvm::ARM::ArchKind::ARMV8_8A:888case llvm::ARM::ArchKind::ARMV8_9A:889case llvm::ARM::ArchKind::ARMV9A:890case llvm::ARM::ArchKind::ARMV9_1A:891case llvm::ARM::ArchKind::ARMV9_2A:892case llvm::ARM::ArchKind::ARMV9_3A:893case llvm::ARM::ArchKind::ARMV9_4A:894case llvm::ARM::ArchKind::ARMV9_5A:895// Filter __arm_cdp, __arm_ldcl, __arm_stcl in arm_acle.h896FeatureCoprocBF = FEATURE_COPROC_B1 | FEATURE_COPROC_B3;897break;898case llvm::ARM::ArchKind::ARMV8MMainline:899case llvm::ARM::ArchKind::ARMV8_1MMainline:900FeatureCoprocBF = FEATURE_COPROC_B1 | FEATURE_COPROC_B2 |901FEATURE_COPROC_B3 | FEATURE_COPROC_B4;902break;903}904Builder.defineMacro("__ARM_FEATURE_COPROC",905"0x" + Twine::utohexstr(FeatureCoprocBF));906907if (ArchKind == llvm::ARM::ArchKind::XSCALE)908Builder.defineMacro("__XSCALE__");909910if (isThumb()) {911Builder.defineMacro("__THUMBEL__");912Builder.defineMacro("__thumb__");913if (supportsThumb2())914Builder.defineMacro("__thumb2__");915}916917// ACLE 6.4.9 32-bit SIMD instructions918if ((CPUProfile != "M" && ArchVersion >= 6) || (CPUProfile == "M" && DSP))919Builder.defineMacro("__ARM_FEATURE_SIMD32", "1");920921// ACLE 6.4.10 Hardware Integer Divide922if (((HWDiv & HWDivThumb) && isThumb()) ||923((HWDiv & HWDivARM) && !isThumb())) {924Builder.defineMacro("__ARM_FEATURE_IDIV", "1");925Builder.defineMacro("__ARM_ARCH_EXT_IDIV__", "1");926}927928// Note, this is always on in gcc, even though it doesn't make sense.929Builder.defineMacro("__APCS_32__");930931// __VFP_FP__ means that the floating-point format is VFP, not that a hardware932// FPU is present. Moreover, the VFP format is the only one supported by933// clang. For these reasons, this macro is always defined.934Builder.defineMacro("__VFP_FP__");935936if (FPUModeIsVFP((FPUMode)FPU)) {937if (FPU & VFP2FPU)938Builder.defineMacro("__ARM_VFPV2__");939if (FPU & VFP3FPU)940Builder.defineMacro("__ARM_VFPV3__");941if (FPU & VFP4FPU)942Builder.defineMacro("__ARM_VFPV4__");943if (FPU & FPARMV8)944Builder.defineMacro("__ARM_FPV5__");945}946947// This only gets set when Neon instructions are actually available, unlike948// the VFP define, hence the soft float and arch check. This is subtly949// different from gcc, we follow the intent which was that it should be set950// when Neon instructions are actually available.951if ((FPU & NeonFPU) && !SoftFloat && ArchVersion >= 7) {952Builder.defineMacro("__ARM_NEON", "1");953Builder.defineMacro("__ARM_NEON__");954// current AArch32 NEON implementations do not support double-precision955// floating-point even when it is present in VFP.956Builder.defineMacro("__ARM_NEON_FP",957"0x" + Twine::utohexstr(HW_FP & ~HW_FP_DP));958}959960if (hasMVE()) {961Builder.defineMacro("__ARM_FEATURE_MVE", hasMVEFloat() ? "3" : "1");962}963964if (hasCDE()) {965Builder.defineMacro("__ARM_FEATURE_CDE", "1");966Builder.defineMacro("__ARM_FEATURE_CDE_COPROC",967"0x" + Twine::utohexstr(getARMCDECoprocMask()));968}969970Builder.defineMacro("__ARM_SIZEOF_WCHAR_T",971Twine(Opts.WCharSize ? Opts.WCharSize : 4));972973Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4");974975// CMSE976if (ArchVersion == 8 && ArchProfile == llvm::ARM::ProfileKind::M)977Builder.defineMacro("__ARM_FEATURE_CMSE", Opts.Cmse ? "3" : "1");978979if (ArchVersion >= 6 && CPUAttr != "6M" && CPUAttr != "8M_BASE") {980Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");981Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");982Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");983Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");984}985986// ACLE 6.4.7 DSP instructions987if (DSP) {988Builder.defineMacro("__ARM_FEATURE_DSP", "1");989}990991// ACLE 6.4.8 Saturation instructions992bool SAT = false;993if ((ArchVersion == 6 && CPUProfile != "M") || ArchVersion > 6) {994Builder.defineMacro("__ARM_FEATURE_SAT", "1");995SAT = true;996}997998// ACLE 6.4.6 Q (saturation) flag999if (DSP || SAT)1000Builder.defineMacro("__ARM_FEATURE_QBIT", "1");10011002if (Opts.UnsafeFPMath)1003Builder.defineMacro("__ARM_FP_FAST", "1");10041005// Armv8.2-A FP16 vector intrinsic1006if ((FPU & NeonFPU) && HasLegalHalfType)1007Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1");10081009// Armv8.2-A FP16 scalar intrinsics1010if (HasLegalHalfType)1011Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1");10121013// Armv8.2-A dot product intrinsics1014if (DotProd)1015Builder.defineMacro("__ARM_FEATURE_DOTPROD", "1");10161017if (HasMatMul)1018Builder.defineMacro("__ARM_FEATURE_MATMUL_INT8", "1");10191020if (HasPAC)1021Builder.defineMacro("__ARM_FEATURE_PAUTH", "1");10221023if (HasBTI)1024Builder.defineMacro("__ARM_FEATURE_BTI", "1");10251026if (HasBFloat16) {1027Builder.defineMacro("__ARM_FEATURE_BF16", "1");1028Builder.defineMacro("__ARM_FEATURE_BF16_VECTOR_ARITHMETIC", "1");1029Builder.defineMacro("__ARM_BF16_FORMAT_ALTERNATIVE", "1");1030}10311032if (Opts.BranchTargetEnforcement)1033Builder.defineMacro("__ARM_FEATURE_BTI_DEFAULT", "1");10341035if (Opts.hasSignReturnAddress()) {1036unsigned Value = 1;1037if (Opts.isSignReturnAddressScopeAll())1038Value |= 1 << 2;1039Builder.defineMacro("__ARM_FEATURE_PAC_DEFAULT", Twine(Value));1040}10411042switch (ArchKind) {1043default:1044break;1045case llvm::ARM::ArchKind::ARMV8_1A:1046getTargetDefinesARMV81A(Opts, Builder);1047break;1048case llvm::ARM::ArchKind::ARMV8_2A:1049getTargetDefinesARMV82A(Opts, Builder);1050break;1051case llvm::ARM::ArchKind::ARMV8_3A:1052case llvm::ARM::ArchKind::ARMV8_4A:1053case llvm::ARM::ArchKind::ARMV8_5A:1054case llvm::ARM::ArchKind::ARMV8_6A:1055case llvm::ARM::ArchKind::ARMV8_7A:1056case llvm::ARM::ArchKind::ARMV8_8A:1057case llvm::ARM::ArchKind::ARMV8_9A:1058case llvm::ARM::ArchKind::ARMV9A:1059case llvm::ARM::ArchKind::ARMV9_1A:1060case llvm::ARM::ArchKind::ARMV9_2A:1061case llvm::ARM::ArchKind::ARMV9_3A:1062case llvm::ARM::ArchKind::ARMV9_4A:1063case llvm::ARM::ArchKind::ARMV9_5A:1064getTargetDefinesARMV83A(Opts, Builder);1065break;1066}1067}10681069static constexpr Builtin::Info BuiltinInfo[] = {1070#define BUILTIN(ID, TYPE, ATTRS) \1071{#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},1072#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \1073{#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, ALL_LANGUAGES},1074#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \1075{#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},1076#include "clang/Basic/BuiltinsNEON.def"10771078#define BUILTIN(ID, TYPE, ATTRS) \1079{#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},1080#define LANGBUILTIN(ID, TYPE, ATTRS, LANG) \1081{#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, LANG},1082#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \1083{#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, ALL_LANGUAGES},1084#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \1085{#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},1086#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \1087{#ID, TYPE, ATTRS, FEATURE, HeaderDesc::HEADER, LANGS},1088#include "clang/Basic/BuiltinsARM.def"1089};10901091ArrayRef<Builtin::Info> ARMTargetInfo::getTargetBuiltins() const {1092return llvm::ArrayRef(BuiltinInfo,1093clang::ARM::LastTSBuiltin - Builtin::FirstTSBuiltin);1094}10951096bool ARMTargetInfo::isCLZForZeroUndef() const { return false; }1097TargetInfo::BuiltinVaListKind ARMTargetInfo::getBuiltinVaListKind() const {1098return IsAAPCS1099? AAPCSABIBuiltinVaList1100: (getTriple().isWatchABI() ? TargetInfo::CharPtrBuiltinVaList1101: TargetInfo::VoidPtrBuiltinVaList);1102}11031104const char *const ARMTargetInfo::GCCRegNames[] = {1105// Integer registers1106"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",1107"r12", "sp", "lr", "pc",11081109// Float registers1110"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",1111"s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",1112"s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",11131114// Double registers1115"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",1116"d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",1117"d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",11181119// Quad registers1120"q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11",1121"q12", "q13", "q14", "q15"};11221123ArrayRef<const char *> ARMTargetInfo::getGCCRegNames() const {1124return llvm::ArrayRef(GCCRegNames);1125}11261127const TargetInfo::GCCRegAlias ARMTargetInfo::GCCRegAliases[] = {1128{{"a1"}, "r0"}, {{"a2"}, "r1"}, {{"a3"}, "r2"}, {{"a4"}, "r3"},1129{{"v1"}, "r4"}, {{"v2"}, "r5"}, {{"v3"}, "r6"}, {{"v4"}, "r7"},1130{{"v5"}, "r8"}, {{"v6", "rfp"}, "r9"}, {{"sl"}, "r10"}, {{"fp"}, "r11"},1131{{"ip"}, "r12"}, {{"r13"}, "sp"}, {{"r14"}, "lr"}, {{"r15"}, "pc"},1132// The S, D and Q registers overlap, but aren't really aliases; we1133// don't want to substitute one of these for a different-sized one.1134};11351136ArrayRef<TargetInfo::GCCRegAlias> ARMTargetInfo::getGCCRegAliases() const {1137return llvm::ArrayRef(GCCRegAliases);1138}11391140bool ARMTargetInfo::validateAsmConstraint(1141const char *&Name, TargetInfo::ConstraintInfo &Info) const {1142switch (*Name) {1143default:1144break;1145case 'l': // r0-r7 if thumb, r0-r15 if ARM1146Info.setAllowsRegister();1147return true;1148case 'h': // r8-r15, thumb only1149if (isThumb()) {1150Info.setAllowsRegister();1151return true;1152}1153break;1154case 's': // An integer constant, but allowing only relocatable values.1155return true;1156case 't': // s0-s31, d0-d31, or q0-q151157case 'w': // s0-s15, d0-d7, or q0-q31158case 'x': // s0-s31, d0-d15, or q0-q71159if (FPRegsDisabled)1160return false;1161Info.setAllowsRegister();1162return true;1163case 'j': // An immediate integer between 0 and 65535 (valid for MOVW)1164// only available in ARMv6T2 and above1165if (CPUAttr == "6T2" || ArchVersion >= 7) {1166Info.setRequiresImmediate(0, 65535);1167return true;1168}1169break;1170case 'I':1171if (isThumb()) {1172if (!supportsThumb2())1173Info.setRequiresImmediate(0, 255);1174else1175// FIXME: should check if immediate value would be valid for a Thumb21176// data-processing instruction1177Info.setRequiresImmediate();1178} else1179// FIXME: should check if immediate value would be valid for an ARM1180// data-processing instruction1181Info.setRequiresImmediate();1182return true;1183case 'J':1184if (isThumb() && !supportsThumb2())1185Info.setRequiresImmediate(-255, -1);1186else1187Info.setRequiresImmediate(-4095, 4095);1188return true;1189case 'K':1190if (isThumb()) {1191if (!supportsThumb2())1192// FIXME: should check if immediate value can be obtained from shifting1193// a value between 0 and 255 left by any amount1194Info.setRequiresImmediate();1195else1196// FIXME: should check if immediate value would be valid for a Thumb21197// data-processing instruction when inverted1198Info.setRequiresImmediate();1199} else1200// FIXME: should check if immediate value would be valid for an ARM1201// data-processing instruction when inverted1202Info.setRequiresImmediate();1203return true;1204case 'L':1205if (isThumb()) {1206if (!supportsThumb2())1207Info.setRequiresImmediate(-7, 7);1208else1209// FIXME: should check if immediate value would be valid for a Thumb21210// data-processing instruction when negated1211Info.setRequiresImmediate();1212} else1213// FIXME: should check if immediate value would be valid for an ARM1214// data-processing instruction when negated1215Info.setRequiresImmediate();1216return true;1217case 'M':1218if (isThumb() && !supportsThumb2())1219// FIXME: should check if immediate value is a multiple of 4 between 0 and1220// 10201221Info.setRequiresImmediate();1222else1223// FIXME: should check if immediate value is a power of two or a integer1224// between 0 and 321225Info.setRequiresImmediate();1226return true;1227case 'N':1228// Thumb1 only1229if (isThumb() && !supportsThumb2()) {1230Info.setRequiresImmediate(0, 31);1231return true;1232}1233break;1234case 'O':1235// Thumb1 only1236if (isThumb() && !supportsThumb2()) {1237// FIXME: should check if immediate value is a multiple of 4 between -5081238// and 5081239Info.setRequiresImmediate();1240return true;1241}1242break;1243case 'Q': // A memory address that is a single base register.1244Info.setAllowsMemory();1245return true;1246case 'T':1247switch (Name[1]) {1248default:1249break;1250case 'e': // Even general-purpose register1251case 'o': // Odd general-purpose register1252Info.setAllowsRegister();1253Name++;1254return true;1255}1256break;1257case 'U': // a memory reference...1258switch (Name[1]) {1259case 'q': // ...ARMV4 ldrsb1260case 'v': // ...VFP load/store (reg+constant offset)1261case 'y': // ...iWMMXt load/store1262case 't': // address valid for load/store opaque types wider1263// than 128-bits1264case 'n': // valid address for Neon doubleword vector load/store1265case 'm': // valid address for Neon element and structure load/store1266case 's': // valid address for non-offset loads/stores of quad-word1267// values in four ARM registers1268Info.setAllowsMemory();1269Name++;1270return true;1271}1272break;1273}1274return false;1275}12761277std::string ARMTargetInfo::convertConstraint(const char *&Constraint) const {1278std::string R;1279switch (*Constraint) {1280case 'U': // Two-character constraint; add "^" hint for later parsing.1281case 'T':1282R = std::string("^") + std::string(Constraint, 2);1283Constraint++;1284break;1285case 'p': // 'p' should be translated to 'r' by default.1286R = std::string("r");1287break;1288default:1289return std::string(1, *Constraint);1290}1291return R;1292}12931294bool ARMTargetInfo::validateConstraintModifier(1295StringRef Constraint, char Modifier, unsigned Size,1296std::string &SuggestedModifier) const {1297bool isOutput = (Constraint[0] == '=');1298bool isInOut = (Constraint[0] == '+');12991300// Strip off constraint modifiers.1301Constraint = Constraint.ltrim("=+&");13021303switch (Constraint[0]) {1304default:1305break;1306case 'r': {1307switch (Modifier) {1308default:1309return (isInOut || isOutput || Size <= 64);1310case 'q':1311// A register of size 32 cannot fit a vector type.1312return false;1313}1314}1315}13161317return true;1318}1319std::string_view ARMTargetInfo::getClobbers() const {1320// FIXME: Is this really right?1321return "";1322}13231324TargetInfo::CallingConvCheckResult1325ARMTargetInfo::checkCallingConvention(CallingConv CC) const {1326switch (CC) {1327case CC_AAPCS:1328case CC_AAPCS_VFP:1329case CC_Swift:1330case CC_SwiftAsync:1331case CC_OpenCLKernel:1332return CCCR_OK;1333default:1334return CCCR_Warning;1335}1336}13371338int ARMTargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {1339if (RegNo == 0)1340return 0;1341if (RegNo == 1)1342return 1;1343return -1;1344}13451346bool ARMTargetInfo::hasSjLjLowering() const { return true; }13471348ARMleTargetInfo::ARMleTargetInfo(const llvm::Triple &Triple,1349const TargetOptions &Opts)1350: ARMTargetInfo(Triple, Opts) {}13511352void ARMleTargetInfo::getTargetDefines(const LangOptions &Opts,1353MacroBuilder &Builder) const {1354Builder.defineMacro("__ARMEL__");1355ARMTargetInfo::getTargetDefines(Opts, Builder);1356}13571358ARMbeTargetInfo::ARMbeTargetInfo(const llvm::Triple &Triple,1359const TargetOptions &Opts)1360: ARMTargetInfo(Triple, Opts) {}13611362void ARMbeTargetInfo::getTargetDefines(const LangOptions &Opts,1363MacroBuilder &Builder) const {1364Builder.defineMacro("__ARMEB__");1365Builder.defineMacro("__ARM_BIG_ENDIAN");1366ARMTargetInfo::getTargetDefines(Opts, Builder);1367}13681369WindowsARMTargetInfo::WindowsARMTargetInfo(const llvm::Triple &Triple,1370const TargetOptions &Opts)1371: WindowsTargetInfo<ARMleTargetInfo>(Triple, Opts), Triple(Triple) {1372}13731374void WindowsARMTargetInfo::getVisualStudioDefines(const LangOptions &Opts,1375MacroBuilder &Builder) const {1376// FIXME: this is invalid for WindowsCE1377Builder.defineMacro("_M_ARM_NT", "1");1378Builder.defineMacro("_M_ARMT", "_M_ARM");1379Builder.defineMacro("_M_THUMB", "_M_ARM");13801381assert((Triple.getArch() == llvm::Triple::arm ||1382Triple.getArch() == llvm::Triple::thumb) &&1383"invalid architecture for Windows ARM target info");1384unsigned Offset = Triple.getArch() == llvm::Triple::arm ? 4 : 6;1385Builder.defineMacro("_M_ARM", Triple.getArchName().substr(Offset));13861387// TODO map the complete set of values1388// 31: VFPv3 40: VFPv41389Builder.defineMacro("_M_ARM_FP", "31");1390}13911392TargetInfo::BuiltinVaListKind1393WindowsARMTargetInfo::getBuiltinVaListKind() const {1394return TargetInfo::CharPtrBuiltinVaList;1395}13961397TargetInfo::CallingConvCheckResult1398WindowsARMTargetInfo::checkCallingConvention(CallingConv CC) const {1399switch (CC) {1400case CC_X86StdCall:1401case CC_X86ThisCall:1402case CC_X86FastCall:1403case CC_X86VectorCall:1404return CCCR_Ignore;1405case CC_C:1406case CC_OpenCLKernel:1407case CC_PreserveMost:1408case CC_PreserveAll:1409case CC_Swift:1410case CC_SwiftAsync:1411return CCCR_OK;1412default:1413return CCCR_Warning;1414}1415}14161417// Windows ARM + Itanium C++ ABI Target1418ItaniumWindowsARMleTargetInfo::ItaniumWindowsARMleTargetInfo(1419const llvm::Triple &Triple, const TargetOptions &Opts)1420: WindowsARMTargetInfo(Triple, Opts) {1421TheCXXABI.set(TargetCXXABI::GenericARM);1422}14231424void ItaniumWindowsARMleTargetInfo::getTargetDefines(1425const LangOptions &Opts, MacroBuilder &Builder) const {1426WindowsARMTargetInfo::getTargetDefines(Opts, Builder);14271428if (Opts.MSVCCompat)1429WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);1430}14311432// Windows ARM, MS (C++) ABI1433MicrosoftARMleTargetInfo::MicrosoftARMleTargetInfo(const llvm::Triple &Triple,1434const TargetOptions &Opts)1435: WindowsARMTargetInfo(Triple, Opts) {1436TheCXXABI.set(TargetCXXABI::Microsoft);1437}14381439void MicrosoftARMleTargetInfo::getTargetDefines(const LangOptions &Opts,1440MacroBuilder &Builder) const {1441WindowsARMTargetInfo::getTargetDefines(Opts, Builder);1442WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);1443}14441445MinGWARMTargetInfo::MinGWARMTargetInfo(const llvm::Triple &Triple,1446const TargetOptions &Opts)1447: WindowsARMTargetInfo(Triple, Opts) {1448TheCXXABI.set(TargetCXXABI::GenericARM);1449}14501451void MinGWARMTargetInfo::getTargetDefines(const LangOptions &Opts,1452MacroBuilder &Builder) const {1453WindowsARMTargetInfo::getTargetDefines(Opts, Builder);1454Builder.defineMacro("_ARM_");1455}14561457CygwinARMTargetInfo::CygwinARMTargetInfo(const llvm::Triple &Triple,1458const TargetOptions &Opts)1459: ARMleTargetInfo(Triple, Opts) {1460this->WCharType = TargetInfo::UnsignedShort;1461TLSSupported = false;1462DoubleAlign = LongLongAlign = 64;1463resetDataLayout("e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64");1464}14651466void CygwinARMTargetInfo::getTargetDefines(const LangOptions &Opts,1467MacroBuilder &Builder) const {1468ARMleTargetInfo::getTargetDefines(Opts, Builder);1469Builder.defineMacro("_ARM_");1470Builder.defineMacro("__CYGWIN__");1471Builder.defineMacro("__CYGWIN32__");1472DefineStd(Builder, "unix", Opts);1473if (Opts.CPlusPlus)1474Builder.defineMacro("_GNU_SOURCE");1475}14761477DarwinARMTargetInfo::DarwinARMTargetInfo(const llvm::Triple &Triple,1478const TargetOptions &Opts)1479: DarwinTargetInfo<ARMleTargetInfo>(Triple, Opts) {1480HasAlignMac68kSupport = true;1481if (Triple.isWatchABI()) {1482// Darwin on iOS uses a variant of the ARM C++ ABI.1483TheCXXABI.set(TargetCXXABI::WatchOS);14841485// BOOL should be a real boolean on the new ABI1486UseSignedCharForObjCBool = false;1487} else1488TheCXXABI.set(TargetCXXABI::iOS);1489}14901491void DarwinARMTargetInfo::getOSDefines(const LangOptions &Opts,1492const llvm::Triple &Triple,1493MacroBuilder &Builder) const {1494getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);1495}14961497RenderScript32TargetInfo::RenderScript32TargetInfo(const llvm::Triple &Triple,1498const TargetOptions &Opts)1499: ARMleTargetInfo(llvm::Triple("armv7", Triple.getVendorName(),1500Triple.getOSName(),1501Triple.getEnvironmentName()),1502Opts) {1503IsRenderScriptTarget = true;1504LongWidth = LongAlign = 64;1505}15061507void RenderScript32TargetInfo::getTargetDefines(const LangOptions &Opts,1508MacroBuilder &Builder) const {1509Builder.defineMacro("__RENDERSCRIPT__");1510ARMleTargetInfo::getTargetDefines(Opts, Builder);1511}151215131514