1326941Sdim//===--- ARM.cpp - Implement ARM target feature support -------------------===// 2326941Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6326941Sdim// 7326941Sdim//===----------------------------------------------------------------------===// 8326941Sdim// 9326941Sdim// This file implements ARM TargetInfo objects. 10326941Sdim// 11326941Sdim//===----------------------------------------------------------------------===// 12326941Sdim 13326941Sdim#include "ARM.h" 14326941Sdim#include "clang/Basic/Builtins.h" 15326941Sdim#include "clang/Basic/Diagnostic.h" 16326941Sdim#include "clang/Basic/TargetBuiltins.h" 17326941Sdim#include "llvm/ADT/StringExtras.h" 18326941Sdim#include "llvm/ADT/StringRef.h" 19326941Sdim#include "llvm/ADT/StringSwitch.h" 20326941Sdim 21326941Sdimusing namespace clang; 22326941Sdimusing namespace clang::targets; 23326941Sdim 24326941Sdimvoid ARMTargetInfo::setABIAAPCS() { 25326941Sdim IsAAPCS = true; 26326941Sdim 27326941Sdim DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64; 28326941Sdim const llvm::Triple &T = getTriple(); 29326941Sdim 30344779Sdim bool IsNetBSD = T.isOSNetBSD(); 31344779Sdim bool IsOpenBSD = T.isOSOpenBSD(); 32326941Sdim if (!T.isOSWindows() && !IsNetBSD && !IsOpenBSD) 33326941Sdim WCharType = UnsignedInt; 34326941Sdim 35326941Sdim UseBitFieldTypeAlignment = true; 36326941Sdim 37326941Sdim ZeroLengthBitfieldBoundary = 0; 38326941Sdim 39326941Sdim // Thumb1 add sp, #imm requires the immediate value be multiple of 4, 40326941Sdim // so set preferred for small types to 32. 41326941Sdim if (T.isOSBinFormatMachO()) { 42326941Sdim resetDataLayout(BigEndian 43353358Sdim ? "E-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" 44353358Sdim : "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"); 45326941Sdim } else if (T.isOSWindows()) { 46326941Sdim assert(!BigEndian && "Windows on ARM does not support big endian"); 47326941Sdim resetDataLayout("e" 48326941Sdim "-m:w" 49326941Sdim "-p:32:32" 50353358Sdim "-Fi8" 51326941Sdim "-i64:64" 52326941Sdim "-v128:64:128" 53326941Sdim "-a:0:32" 54326941Sdim "-n32" 55326941Sdim "-S64"); 56326941Sdim } else if (T.isOSNaCl()) { 57326941Sdim assert(!BigEndian && "NaCl on ARM does not support big endian"); 58353358Sdim resetDataLayout("e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S128"); 59326941Sdim } else { 60326941Sdim resetDataLayout(BigEndian 61353358Sdim ? "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" 62353358Sdim : "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"); 63326941Sdim } 64326941Sdim 65326941Sdim // FIXME: Enumerated types are variable width in straight AAPCS. 66326941Sdim} 67326941Sdim 68326941Sdimvoid ARMTargetInfo::setABIAPCS(bool IsAAPCS16) { 69326941Sdim const llvm::Triple &T = getTriple(); 70326941Sdim 71326941Sdim IsAAPCS = false; 72326941Sdim 73326941Sdim if (IsAAPCS16) 74326941Sdim DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64; 75326941Sdim else 76326941Sdim DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 32; 77326941Sdim 78326941Sdim WCharType = SignedInt; 79326941Sdim 80326941Sdim // Do not respect the alignment of bit-field types when laying out 81326941Sdim // structures. This corresponds to PCC_BITFIELD_TYPE_MATTERS in gcc. 82326941Sdim UseBitFieldTypeAlignment = false; 83326941Sdim 84326941Sdim /// gcc forces the alignment to 4 bytes, regardless of the type of the 85326941Sdim /// zero length bitfield. This corresponds to EMPTY_FIELD_BOUNDARY in 86326941Sdim /// gcc. 87326941Sdim ZeroLengthBitfieldBoundary = 32; 88326941Sdim 89326941Sdim if (T.isOSBinFormatMachO() && IsAAPCS16) { 90326941Sdim assert(!BigEndian && "AAPCS16 does not support big-endian"); 91353358Sdim resetDataLayout("e-m:o-p:32:32-Fi8-i64:64-a:0:32-n32-S128"); 92326941Sdim } else if (T.isOSBinFormatMachO()) 93326941Sdim resetDataLayout( 94326941Sdim BigEndian 95353358Sdim ? "E-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" 96353358Sdim : "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"); 97326941Sdim else 98326941Sdim resetDataLayout( 99326941Sdim BigEndian 100353358Sdim ? "E-m:e-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" 101353358Sdim : "e-m:e-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"); 102326941Sdim 103326941Sdim // FIXME: Override "preferred align" for double and long long. 104326941Sdim} 105326941Sdim 106326941Sdimvoid ARMTargetInfo::setArchInfo() { 107326941Sdim StringRef ArchName = getTriple().getArchName(); 108326941Sdim 109326941Sdim ArchISA = llvm::ARM::parseArchISA(ArchName); 110326941Sdim CPU = llvm::ARM::getDefaultCPU(ArchName); 111326941Sdim llvm::ARM::ArchKind AK = llvm::ARM::parseArch(ArchName); 112326941Sdim if (AK != llvm::ARM::ArchKind::INVALID) 113326941Sdim ArchKind = AK; 114326941Sdim setArchInfo(ArchKind); 115326941Sdim} 116326941Sdim 117326941Sdimvoid ARMTargetInfo::setArchInfo(llvm::ARM::ArchKind Kind) { 118326941Sdim StringRef SubArch; 119326941Sdim 120326941Sdim // cache TargetParser info 121326941Sdim ArchKind = Kind; 122326941Sdim SubArch = llvm::ARM::getSubArch(ArchKind); 123326941Sdim ArchProfile = llvm::ARM::parseArchProfile(SubArch); 124326941Sdim ArchVersion = llvm::ARM::parseArchVersion(SubArch); 125326941Sdim 126326941Sdim // cache CPU related strings 127326941Sdim CPUAttr = getCPUAttr(); 128326941Sdim CPUProfile = getCPUProfile(); 129326941Sdim} 130326941Sdim 131326941Sdimvoid ARMTargetInfo::setAtomic() { 132326941Sdim // when triple does not specify a sub arch, 133326941Sdim // then we are not using inline atomics 134326941Sdim bool ShouldUseInlineAtomic = 135326941Sdim (ArchISA == llvm::ARM::ISAKind::ARM && ArchVersion >= 6) || 136326941Sdim (ArchISA == llvm::ARM::ISAKind::THUMB && ArchVersion >= 7); 137326941Sdim // Cortex M does not support 8 byte atomics, while general Thumb2 does. 138326941Sdim if (ArchProfile == llvm::ARM::ProfileKind::M) { 139326941Sdim MaxAtomicPromoteWidth = 32; 140326941Sdim if (ShouldUseInlineAtomic) 141326941Sdim MaxAtomicInlineWidth = 32; 142326941Sdim } else { 143326941Sdim MaxAtomicPromoteWidth = 64; 144326941Sdim if (ShouldUseInlineAtomic) 145326941Sdim MaxAtomicInlineWidth = 64; 146326941Sdim } 147326941Sdim} 148326941Sdim 149353358Sdimbool ARMTargetInfo::hasMVE() const { 150353358Sdim return ArchKind == llvm::ARM::ArchKind::ARMV8_1MMainline && MVE != 0; 151353358Sdim} 152353358Sdim 153353358Sdimbool ARMTargetInfo::hasMVEFloat() const { 154353358Sdim return hasMVE() && (MVE & MVE_FP); 155353358Sdim} 156353358Sdim 157326941Sdimbool ARMTargetInfo::isThumb() const { 158326941Sdim return ArchISA == llvm::ARM::ISAKind::THUMB; 159326941Sdim} 160326941Sdim 161326941Sdimbool ARMTargetInfo::supportsThumb() const { 162326941Sdim return CPUAttr.count('T') || ArchVersion >= 6; 163326941Sdim} 164326941Sdim 165326941Sdimbool ARMTargetInfo::supportsThumb2() const { 166326941Sdim return CPUAttr.equals("6T2") || 167326941Sdim (ArchVersion >= 7 && !CPUAttr.equals("8M_BASE")); 168326941Sdim} 169326941Sdim 170326941SdimStringRef ARMTargetInfo::getCPUAttr() const { 171326941Sdim // For most sub-arches, the build attribute CPU name is enough. 172326941Sdim // For Cortex variants, it's slightly different. 173326941Sdim switch (ArchKind) { 174326941Sdim default: 175326941Sdim return llvm::ARM::getCPUAttr(ArchKind); 176326941Sdim case llvm::ARM::ArchKind::ARMV6M: 177326941Sdim return "6M"; 178326941Sdim case llvm::ARM::ArchKind::ARMV7S: 179326941Sdim return "7S"; 180326941Sdim case llvm::ARM::ArchKind::ARMV7A: 181326941Sdim return "7A"; 182326941Sdim case llvm::ARM::ArchKind::ARMV7R: 183326941Sdim return "7R"; 184326941Sdim case llvm::ARM::ArchKind::ARMV7M: 185326941Sdim return "7M"; 186326941Sdim case llvm::ARM::ArchKind::ARMV7EM: 187326941Sdim return "7EM"; 188326941Sdim case llvm::ARM::ArchKind::ARMV7VE: 189326941Sdim return "7VE"; 190326941Sdim case llvm::ARM::ArchKind::ARMV8A: 191326941Sdim return "8A"; 192326941Sdim case llvm::ARM::ArchKind::ARMV8_1A: 193326941Sdim return "8_1A"; 194326941Sdim case llvm::ARM::ArchKind::ARMV8_2A: 195326941Sdim return "8_2A"; 196341825Sdim case llvm::ARM::ArchKind::ARMV8_3A: 197341825Sdim return "8_3A"; 198341825Sdim case llvm::ARM::ArchKind::ARMV8_4A: 199341825Sdim return "8_4A"; 200344779Sdim case llvm::ARM::ArchKind::ARMV8_5A: 201344779Sdim return "8_5A"; 202326941Sdim case llvm::ARM::ArchKind::ARMV8MBaseline: 203326941Sdim return "8M_BASE"; 204326941Sdim case llvm::ARM::ArchKind::ARMV8MMainline: 205326941Sdim return "8M_MAIN"; 206326941Sdim case llvm::ARM::ArchKind::ARMV8R: 207326941Sdim return "8R"; 208353358Sdim case llvm::ARM::ArchKind::ARMV8_1MMainline: 209353358Sdim return "8_1M_MAIN"; 210326941Sdim } 211326941Sdim} 212326941Sdim 213326941SdimStringRef ARMTargetInfo::getCPUProfile() const { 214326941Sdim switch (ArchProfile) { 215326941Sdim case llvm::ARM::ProfileKind::A: 216326941Sdim return "A"; 217326941Sdim case llvm::ARM::ProfileKind::R: 218326941Sdim return "R"; 219326941Sdim case llvm::ARM::ProfileKind::M: 220326941Sdim return "M"; 221326941Sdim default: 222326941Sdim return ""; 223326941Sdim } 224326941Sdim} 225326941Sdim 226326941SdimARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple, 227326941Sdim const TargetOptions &Opts) 228326941Sdim : TargetInfo(Triple), FPMath(FP_Default), IsAAPCS(true), LDREX(0), 229326941Sdim HW_FP(0) { 230344779Sdim bool IsOpenBSD = Triple.isOSOpenBSD(); 231344779Sdim bool IsNetBSD = Triple.isOSNetBSD(); 232326941Sdim 233326941Sdim // FIXME: the isOSBinFormatMachO is a workaround for identifying a Darwin-like 234326941Sdim // environment where size_t is `unsigned long` rather than `unsigned int` 235326941Sdim 236326941Sdim PtrDiffType = IntPtrType = 237326941Sdim (Triple.isOSDarwin() || Triple.isOSBinFormatMachO() || IsOpenBSD || 238326941Sdim IsNetBSD) 239326941Sdim ? SignedLong 240326941Sdim : SignedInt; 241326941Sdim 242326941Sdim SizeType = (Triple.isOSDarwin() || Triple.isOSBinFormatMachO() || IsOpenBSD || 243326941Sdim IsNetBSD) 244326941Sdim ? UnsignedLong 245326941Sdim : UnsignedInt; 246326941Sdim 247326941Sdim // ptrdiff_t is inconsistent on Darwin 248326941Sdim if ((Triple.isOSDarwin() || Triple.isOSBinFormatMachO()) && 249326941Sdim !Triple.isWatchABI()) 250326941Sdim PtrDiffType = SignedInt; 251326941Sdim 252326941Sdim // Cache arch related info. 253326941Sdim setArchInfo(); 254326941Sdim 255326941Sdim // {} in inline assembly are neon specifiers, not assembly variant 256326941Sdim // specifiers. 257326941Sdim NoAsmVariants = true; 258326941Sdim 259326941Sdim // FIXME: This duplicates code from the driver that sets the -target-abi 260326941Sdim // option - this code is used if -target-abi isn't passed and should 261326941Sdim // be unified in some way. 262326941Sdim if (Triple.isOSBinFormatMachO()) { 263326941Sdim // The backend is hardwired to assume AAPCS for M-class processors, ensure 264326941Sdim // the frontend matches that. 265326941Sdim if (Triple.getEnvironment() == llvm::Triple::EABI || 266326941Sdim Triple.getOS() == llvm::Triple::UnknownOS || 267326941Sdim ArchProfile == llvm::ARM::ProfileKind::M) { 268326941Sdim setABI("aapcs"); 269326941Sdim } else if (Triple.isWatchABI()) { 270326941Sdim setABI("aapcs16"); 271326941Sdim } else { 272326941Sdim setABI("apcs-gnu"); 273326941Sdim } 274326941Sdim } else if (Triple.isOSWindows()) { 275326941Sdim // FIXME: this is invalid for WindowsCE 276326941Sdim setABI("aapcs"); 277326941Sdim } else { 278326941Sdim // Select the default based on the platform. 279326941Sdim switch (Triple.getEnvironment()) { 280326941Sdim case llvm::Triple::Android: 281326941Sdim case llvm::Triple::GNUEABI: 282326941Sdim case llvm::Triple::GNUEABIHF: 283326941Sdim case llvm::Triple::MuslEABI: 284326941Sdim case llvm::Triple::MuslEABIHF: 285326941Sdim setABI("aapcs-linux"); 286326941Sdim break; 287326941Sdim case llvm::Triple::EABIHF: 288326941Sdim case llvm::Triple::EABI: 289326941Sdim setABI("aapcs"); 290326941Sdim break; 291326941Sdim case llvm::Triple::GNU: 292326941Sdim setABI("apcs-gnu"); 293326941Sdim break; 294326941Sdim default: 295344779Sdim if (IsNetBSD) 296326941Sdim setABI("apcs-gnu"); 297344779Sdim else if (IsOpenBSD) 298326941Sdim setABI("aapcs-linux"); 299326941Sdim else 300326941Sdim setABI("aapcs"); 301326941Sdim break; 302326941Sdim } 303326941Sdim } 304326941Sdim 305326941Sdim // ARM targets default to using the ARM C++ ABI. 306326941Sdim TheCXXABI.set(TargetCXXABI::GenericARM); 307326941Sdim 308326941Sdim // ARM has atomics up to 8 bytes 309326941Sdim setAtomic(); 310326941Sdim 311326941Sdim // Maximum alignment for ARM NEON data types should be 64-bits (AAPCS) 312360784Sdim // as well the default alignment 313326941Sdim if (IsAAPCS && (Triple.getEnvironment() != llvm::Triple::Android)) 314360784Sdim DefaultAlignForAttributeAligned = MaxVectorAlign = 64; 315326941Sdim 316326941Sdim // Do force alignment of members that follow zero length bitfields. If 317326941Sdim // the alignment of the zero-length bitfield is greater than the member 318326941Sdim // that follows it, `bar', `bar' will be aligned as the type of the 319326941Sdim // zero length bitfield. 320326941Sdim UseZeroLengthBitfieldAlignment = true; 321326941Sdim 322326941Sdim if (Triple.getOS() == llvm::Triple::Linux || 323326941Sdim Triple.getOS() == llvm::Triple::UnknownOS) 324326941Sdim this->MCountName = Opts.EABIVersion == llvm::EABI::GNU 325360784Sdim ? "llvm.arm.gnu.eabi.mcount" 326326941Sdim : "\01mcount"; 327353358Sdim 328353358Sdim SoftFloatABI = llvm::is_contained(Opts.FeaturesAsWritten, "+soft-float-abi"); 329326941Sdim} 330326941Sdim 331326941SdimStringRef ARMTargetInfo::getABI() const { return ABI; } 332326941Sdim 333326941Sdimbool ARMTargetInfo::setABI(const std::string &Name) { 334326941Sdim ABI = Name; 335326941Sdim 336326941Sdim // The defaults (above) are for AAPCS, check if we need to change them. 337326941Sdim // 338326941Sdim // FIXME: We need support for -meabi... we could just mangle it into the 339326941Sdim // name. 340326941Sdim if (Name == "apcs-gnu" || Name == "aapcs16") { 341326941Sdim setABIAPCS(Name == "aapcs16"); 342326941Sdim return true; 343326941Sdim } 344326941Sdim if (Name == "aapcs" || Name == "aapcs-vfp" || Name == "aapcs-linux") { 345326941Sdim setABIAAPCS(); 346326941Sdim return true; 347326941Sdim } 348326941Sdim return false; 349326941Sdim} 350326941Sdim 351326941Sdim// FIXME: This should be based on Arch attributes, not CPU names. 352326941Sdimbool ARMTargetInfo::initFeatureMap( 353326941Sdim llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU, 354326941Sdim const std::vector<std::string> &FeaturesVec) const { 355326941Sdim 356341825Sdim std::string ArchFeature; 357326941Sdim std::vector<StringRef> TargetFeatures; 358326941Sdim llvm::ARM::ArchKind Arch = llvm::ARM::parseArch(getTriple().getArchName()); 359326941Sdim 360341825Sdim // Map the base architecture to an appropriate target feature, so we don't 361341825Sdim // rely on the target triple. 362341825Sdim llvm::ARM::ArchKind CPUArch = llvm::ARM::parseCPUArch(CPU); 363341825Sdim if (CPUArch == llvm::ARM::ArchKind::INVALID) 364341825Sdim CPUArch = Arch; 365341825Sdim if (CPUArch != llvm::ARM::ArchKind::INVALID) { 366341825Sdim ArchFeature = ("+" + llvm::ARM::getArchName(CPUArch)).str(); 367341825Sdim TargetFeatures.push_back(ArchFeature); 368341825Sdim } 369341825Sdim 370326941Sdim // get default FPU features 371326941Sdim unsigned FPUKind = llvm::ARM::getDefaultFPU(CPU, Arch); 372326941Sdim llvm::ARM::getFPUFeatures(FPUKind, TargetFeatures); 373326941Sdim 374326941Sdim // get default Extension features 375326941Sdim unsigned Extensions = llvm::ARM::getDefaultExtensions(CPU, Arch); 376326941Sdim llvm::ARM::getExtensionFeatures(Extensions, TargetFeatures); 377326941Sdim 378326941Sdim for (auto Feature : TargetFeatures) 379326941Sdim if (Feature[0] == '+') 380326941Sdim Features[Feature.drop_front(1)] = true; 381326941Sdim 382326941Sdim // Enable or disable thumb-mode explicitly per function to enable mixed 383326941Sdim // ARM and Thumb code generation. 384326941Sdim if (isThumb()) 385326941Sdim Features["thumb-mode"] = true; 386326941Sdim else 387326941Sdim Features["thumb-mode"] = false; 388326941Sdim 389326941Sdim // Convert user-provided arm and thumb GNU target attributes to 390326941Sdim // [-|+]thumb-mode target features respectively. 391353358Sdim std::vector<std::string> UpdatedFeaturesVec; 392353358Sdim for (const auto &Feature : FeaturesVec) { 393353358Sdim // Skip soft-float-abi; it's something we only use to initialize a bit of 394353358Sdim // class state, and is otherwise unrecognized. 395353358Sdim if (Feature == "+soft-float-abi") 396353358Sdim continue; 397353358Sdim 398353358Sdim StringRef FixedFeature; 399353358Sdim if (Feature == "+arm") 400353358Sdim FixedFeature = "-thumb-mode"; 401353358Sdim else if (Feature == "+thumb") 402353358Sdim FixedFeature = "+thumb-mode"; 403353358Sdim else 404353358Sdim FixedFeature = Feature; 405353358Sdim UpdatedFeaturesVec.push_back(FixedFeature.str()); 406326941Sdim } 407326941Sdim 408326941Sdim return TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeaturesVec); 409326941Sdim} 410326941Sdim 411326941Sdim 412326941Sdimbool ARMTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, 413326941Sdim DiagnosticsEngine &Diags) { 414326941Sdim FPU = 0; 415353358Sdim MVE = 0; 416326941Sdim CRC = 0; 417326941Sdim Crypto = 0; 418326941Sdim DSP = 0; 419326941Sdim Unaligned = 1; 420353358Sdim SoftFloat = false; 421353358Sdim // Note that SoftFloatABI is initialized in our constructor. 422326941Sdim HWDiv = 0; 423341825Sdim DotProd = 0; 424344779Sdim HasFloat16 = true; 425326941Sdim 426326941Sdim // This does not diagnose illegal cases like having both 427353358Sdim // "+vfpv2" and "+vfpv3" or having "+neon" and "-fp64". 428326941Sdim for (const auto &Feature : Features) { 429326941Sdim if (Feature == "+soft-float") { 430326941Sdim SoftFloat = true; 431360784Sdim } else if (Feature == "+vfp2sp" || Feature == "+vfp2") { 432326941Sdim FPU |= VFP2FPU; 433353358Sdim HW_FP |= HW_FP_SP; 434360784Sdim if (Feature == "+vfp2") 435353358Sdim HW_FP |= HW_FP_DP; 436353358Sdim } else if (Feature == "+vfp3sp" || Feature == "+vfp3d16sp" || 437353358Sdim Feature == "+vfp3" || Feature == "+vfp3d16") { 438326941Sdim FPU |= VFP3FPU; 439353358Sdim HW_FP |= HW_FP_SP; 440353358Sdim if (Feature == "+vfp3" || Feature == "+vfp3d16") 441353358Sdim HW_FP |= HW_FP_DP; 442353358Sdim } else if (Feature == "+vfp4sp" || Feature == "+vfp4d16sp" || 443353358Sdim Feature == "+vfp4" || Feature == "+vfp4d16") { 444326941Sdim FPU |= VFP4FPU; 445353358Sdim HW_FP |= HW_FP_SP | HW_FP_HP; 446353358Sdim if (Feature == "+vfp4" || Feature == "+vfp4d16") 447353358Sdim HW_FP |= HW_FP_DP; 448353358Sdim } else if (Feature == "+fp-armv8sp" || Feature == "+fp-armv8d16sp" || 449353358Sdim Feature == "+fp-armv8" || Feature == "+fp-armv8d16") { 450326941Sdim FPU |= FPARMV8; 451353358Sdim HW_FP |= HW_FP_SP | HW_FP_HP; 452353358Sdim if (Feature == "+fp-armv8" || Feature == "+fp-armv8d16") 453353358Sdim HW_FP |= HW_FP_DP; 454326941Sdim } else if (Feature == "+neon") { 455326941Sdim FPU |= NeonFPU; 456353358Sdim HW_FP |= HW_FP_SP; 457326941Sdim } else if (Feature == "+hwdiv") { 458326941Sdim HWDiv |= HWDivThumb; 459326941Sdim } else if (Feature == "+hwdiv-arm") { 460326941Sdim HWDiv |= HWDivARM; 461326941Sdim } else if (Feature == "+crc") { 462326941Sdim CRC = 1; 463326941Sdim } else if (Feature == "+crypto") { 464326941Sdim Crypto = 1; 465326941Sdim } else if (Feature == "+dsp") { 466326941Sdim DSP = 1; 467353358Sdim } else if (Feature == "+fp64") { 468353358Sdim HW_FP |= HW_FP_DP; 469353358Sdim } else if (Feature == "+8msecext") { 470353358Sdim if (CPUProfile != "M" || ArchVersion != 8) { 471353358Sdim Diags.Report(diag::err_target_unsupported_mcmse) << CPU; 472353358Sdim return false; 473353358Sdim } 474326941Sdim } else if (Feature == "+strict-align") { 475326941Sdim Unaligned = 0; 476326941Sdim } else if (Feature == "+fp16") { 477326941Sdim HW_FP |= HW_FP_HP; 478341825Sdim } else if (Feature == "+fullfp16") { 479341825Sdim HasLegalHalfType = true; 480341825Sdim } else if (Feature == "+dotprod") { 481341825Sdim DotProd = true; 482353358Sdim } else if (Feature == "+mve") { 483353358Sdim DSP = 1; 484353358Sdim MVE |= MVE_INT; 485353358Sdim } else if (Feature == "+mve.fp") { 486353358Sdim DSP = 1; 487353358Sdim HasLegalHalfType = true; 488353358Sdim FPU |= FPARMV8; 489353358Sdim MVE |= MVE_INT | MVE_FP; 490353358Sdim HW_FP |= HW_FP_SP | HW_FP_HP; 491326941Sdim } 492326941Sdim } 493326941Sdim 494326941Sdim switch (ArchVersion) { 495326941Sdim case 6: 496326941Sdim if (ArchProfile == llvm::ARM::ProfileKind::M) 497326941Sdim LDREX = 0; 498326941Sdim else if (ArchKind == llvm::ARM::ArchKind::ARMV6K) 499326941Sdim LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B; 500326941Sdim else 501326941Sdim LDREX = LDREX_W; 502326941Sdim break; 503326941Sdim case 7: 504326941Sdim if (ArchProfile == llvm::ARM::ProfileKind::M) 505326941Sdim LDREX = LDREX_W | LDREX_H | LDREX_B; 506326941Sdim else 507326941Sdim LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B; 508326941Sdim break; 509326941Sdim case 8: 510326941Sdim LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B; 511326941Sdim } 512326941Sdim 513326941Sdim if (!(FPU & NeonFPU) && FPMath == FP_Neon) { 514326941Sdim Diags.Report(diag::err_target_unsupported_fpmath) << "neon"; 515326941Sdim return false; 516326941Sdim } 517326941Sdim 518326941Sdim if (FPMath == FP_Neon) 519326941Sdim Features.push_back("+neonfp"); 520326941Sdim else if (FPMath == FP_VFP) 521326941Sdim Features.push_back("-neonfp"); 522326941Sdim 523326941Sdim return true; 524326941Sdim} 525326941Sdim 526326941Sdimbool ARMTargetInfo::hasFeature(StringRef Feature) const { 527326941Sdim return llvm::StringSwitch<bool>(Feature) 528326941Sdim .Case("arm", true) 529326941Sdim .Case("aarch32", true) 530326941Sdim .Case("softfloat", SoftFloat) 531326941Sdim .Case("thumb", isThumb()) 532326941Sdim .Case("neon", (FPU & NeonFPU) && !SoftFloat) 533326941Sdim .Case("vfp", FPU && !SoftFloat) 534326941Sdim .Case("hwdiv", HWDiv & HWDivThumb) 535326941Sdim .Case("hwdiv-arm", HWDiv & HWDivARM) 536353358Sdim .Case("mve", hasMVE()) 537326941Sdim .Default(false); 538326941Sdim} 539326941Sdim 540326941Sdimbool ARMTargetInfo::isValidCPUName(StringRef Name) const { 541326941Sdim return Name == "generic" || 542326941Sdim llvm::ARM::parseCPUArch(Name) != llvm::ARM::ArchKind::INVALID; 543326941Sdim} 544326941Sdim 545341825Sdimvoid ARMTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const { 546341825Sdim llvm::ARM::fillValidCPUArchList(Values); 547341825Sdim} 548341825Sdim 549326941Sdimbool ARMTargetInfo::setCPU(const std::string &Name) { 550326941Sdim if (Name != "generic") 551326941Sdim setArchInfo(llvm::ARM::parseCPUArch(Name)); 552326941Sdim 553326941Sdim if (ArchKind == llvm::ARM::ArchKind::INVALID) 554326941Sdim return false; 555326941Sdim setAtomic(); 556326941Sdim CPU = Name; 557326941Sdim return true; 558326941Sdim} 559326941Sdim 560326941Sdimbool ARMTargetInfo::setFPMath(StringRef Name) { 561326941Sdim if (Name == "neon") { 562326941Sdim FPMath = FP_Neon; 563326941Sdim return true; 564326941Sdim } else if (Name == "vfp" || Name == "vfp2" || Name == "vfp3" || 565326941Sdim Name == "vfp4") { 566326941Sdim FPMath = FP_VFP; 567326941Sdim return true; 568326941Sdim } 569326941Sdim return false; 570326941Sdim} 571326941Sdim 572326941Sdimvoid ARMTargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts, 573326941Sdim MacroBuilder &Builder) const { 574326941Sdim Builder.defineMacro("__ARM_FEATURE_QRDMX", "1"); 575326941Sdim} 576326941Sdim 577326941Sdimvoid ARMTargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts, 578326941Sdim MacroBuilder &Builder) const { 579326941Sdim // Also include the ARMv8.1-A defines 580326941Sdim getTargetDefinesARMV81A(Opts, Builder); 581326941Sdim} 582326941Sdim 583360784Sdimvoid ARMTargetInfo::getTargetDefinesARMV83A(const LangOptions &Opts, 584360784Sdim MacroBuilder &Builder) const { 585360784Sdim // Also include the ARMv8.2-A defines 586360784Sdim Builder.defineMacro("__ARM_FEATURE_COMPLEX", "1"); 587360784Sdim getTargetDefinesARMV82A(Opts, Builder); 588360784Sdim} 589360784Sdim 590326941Sdimvoid ARMTargetInfo::getTargetDefines(const LangOptions &Opts, 591326941Sdim MacroBuilder &Builder) const { 592326941Sdim // Target identification. 593326941Sdim Builder.defineMacro("__arm"); 594326941Sdim Builder.defineMacro("__arm__"); 595326941Sdim // For bare-metal none-eabi. 596326941Sdim if (getTriple().getOS() == llvm::Triple::UnknownOS && 597326941Sdim (getTriple().getEnvironment() == llvm::Triple::EABI || 598326941Sdim getTriple().getEnvironment() == llvm::Triple::EABIHF)) 599326941Sdim Builder.defineMacro("__ELF__"); 600326941Sdim 601326941Sdim // Target properties. 602326941Sdim Builder.defineMacro("__REGISTER_PREFIX__", ""); 603326941Sdim 604326941Sdim // Unfortunately, __ARM_ARCH_7K__ is now more of an ABI descriptor. The CPU 605326941Sdim // happens to be Cortex-A7 though, so it should still get __ARM_ARCH_7A__. 606326941Sdim if (getTriple().isWatchABI()) 607326941Sdim Builder.defineMacro("__ARM_ARCH_7K__", "2"); 608326941Sdim 609326941Sdim if (!CPUAttr.empty()) 610326941Sdim Builder.defineMacro("__ARM_ARCH_" + CPUAttr + "__"); 611326941Sdim 612326941Sdim // ACLE 6.4.1 ARM/Thumb instruction set architecture 613326941Sdim // __ARM_ARCH is defined as an integer value indicating the current ARM ISA 614326941Sdim Builder.defineMacro("__ARM_ARCH", Twine(ArchVersion)); 615326941Sdim 616326941Sdim if (ArchVersion >= 8) { 617326941Sdim // ACLE 6.5.7 Crypto Extension 618326941Sdim if (Crypto) 619326941Sdim Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1"); 620326941Sdim // ACLE 6.5.8 CRC32 Extension 621326941Sdim if (CRC) 622326941Sdim Builder.defineMacro("__ARM_FEATURE_CRC32", "1"); 623326941Sdim // ACLE 6.5.10 Numeric Maximum and Minimum 624326941Sdim Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1"); 625326941Sdim // ACLE 6.5.9 Directed Rounding 626326941Sdim Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1"); 627326941Sdim } 628326941Sdim 629326941Sdim // __ARM_ARCH_ISA_ARM is defined to 1 if the core supports the ARM ISA. It 630326941Sdim // is not defined for the M-profile. 631326941Sdim // NOTE that the default profile is assumed to be 'A' 632326941Sdim if (CPUProfile.empty() || ArchProfile != llvm::ARM::ProfileKind::M) 633326941Sdim Builder.defineMacro("__ARM_ARCH_ISA_ARM", "1"); 634326941Sdim 635326941Sdim // __ARM_ARCH_ISA_THUMB is defined to 1 if the core supports the original 636326941Sdim // Thumb ISA (including v6-M and v8-M Baseline). It is set to 2 if the 637326941Sdim // core supports the Thumb-2 ISA as found in the v6T2 architecture and all 638326941Sdim // v7 and v8 architectures excluding v8-M Baseline. 639326941Sdim if (supportsThumb2()) 640326941Sdim Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "2"); 641326941Sdim else if (supportsThumb()) 642326941Sdim Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "1"); 643326941Sdim 644326941Sdim // __ARM_32BIT_STATE is defined to 1 if code is being generated for a 32-bit 645326941Sdim // instruction set such as ARM or Thumb. 646326941Sdim Builder.defineMacro("__ARM_32BIT_STATE", "1"); 647326941Sdim 648326941Sdim // ACLE 6.4.2 Architectural Profile (A, R, M or pre-Cortex) 649326941Sdim 650326941Sdim // __ARM_ARCH_PROFILE is defined as 'A', 'R', 'M' or 'S', or unset. 651326941Sdim if (!CPUProfile.empty()) 652326941Sdim Builder.defineMacro("__ARM_ARCH_PROFILE", "'" + CPUProfile + "'"); 653326941Sdim 654326941Sdim // ACLE 6.4.3 Unaligned access supported in hardware 655326941Sdim if (Unaligned) 656326941Sdim Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1"); 657326941Sdim 658326941Sdim // ACLE 6.4.4 LDREX/STREX 659326941Sdim if (LDREX) 660327330Sdim Builder.defineMacro("__ARM_FEATURE_LDREX", "0x" + Twine::utohexstr(LDREX)); 661326941Sdim 662326941Sdim // ACLE 6.4.5 CLZ 663326941Sdim if (ArchVersion == 5 || (ArchVersion == 6 && CPUProfile != "M") || 664326941Sdim ArchVersion > 6) 665326941Sdim Builder.defineMacro("__ARM_FEATURE_CLZ", "1"); 666326941Sdim 667326941Sdim // ACLE 6.5.1 Hardware Floating Point 668326941Sdim if (HW_FP) 669327330Sdim Builder.defineMacro("__ARM_FP", "0x" + Twine::utohexstr(HW_FP)); 670326941Sdim 671326941Sdim // ACLE predefines. 672326941Sdim Builder.defineMacro("__ARM_ACLE", "200"); 673326941Sdim 674326941Sdim // FP16 support (we currently only support IEEE format). 675326941Sdim Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1"); 676326941Sdim Builder.defineMacro("__ARM_FP16_ARGS", "1"); 677326941Sdim 678326941Sdim // ACLE 6.5.3 Fused multiply-accumulate (FMA) 679326941Sdim if (ArchVersion >= 7 && (FPU & VFP4FPU)) 680326941Sdim Builder.defineMacro("__ARM_FEATURE_FMA", "1"); 681326941Sdim 682326941Sdim // Subtarget options. 683326941Sdim 684326941Sdim // FIXME: It's more complicated than this and we don't really support 685326941Sdim // interworking. 686326941Sdim // Windows on ARM does not "support" interworking 687326941Sdim if (5 <= ArchVersion && ArchVersion <= 8 && !getTriple().isOSWindows()) 688326941Sdim Builder.defineMacro("__THUMB_INTERWORK__"); 689326941Sdim 690326941Sdim if (ABI == "aapcs" || ABI == "aapcs-linux" || ABI == "aapcs-vfp") { 691326941Sdim // Embedded targets on Darwin follow AAPCS, but not EABI. 692326941Sdim // Windows on ARM follows AAPCS VFP, but does not conform to EABI. 693326941Sdim if (!getTriple().isOSBinFormatMachO() && !getTriple().isOSWindows()) 694326941Sdim Builder.defineMacro("__ARM_EABI__"); 695326941Sdim Builder.defineMacro("__ARM_PCS", "1"); 696326941Sdim } 697326941Sdim 698326941Sdim if ((!SoftFloat && !SoftFloatABI) || ABI == "aapcs-vfp" || ABI == "aapcs16") 699326941Sdim Builder.defineMacro("__ARM_PCS_VFP", "1"); 700326941Sdim 701326941Sdim if (SoftFloat) 702326941Sdim Builder.defineMacro("__SOFTFP__"); 703326941Sdim 704353358Sdim // ACLE position independent code macros. 705353358Sdim if (Opts.ROPI) 706353358Sdim Builder.defineMacro("__ARM_ROPI", "1"); 707353358Sdim if (Opts.RWPI) 708353358Sdim Builder.defineMacro("__ARM_RWPI", "1"); 709353358Sdim 710326941Sdim if (ArchKind == llvm::ARM::ArchKind::XSCALE) 711326941Sdim Builder.defineMacro("__XSCALE__"); 712326941Sdim 713326941Sdim if (isThumb()) { 714326941Sdim Builder.defineMacro("__THUMBEL__"); 715326941Sdim Builder.defineMacro("__thumb__"); 716326941Sdim if (supportsThumb2()) 717326941Sdim Builder.defineMacro("__thumb2__"); 718326941Sdim } 719326941Sdim 720326941Sdim // ACLE 6.4.9 32-bit SIMD instructions 721344779Sdim if ((CPUProfile != "M" && ArchVersion >= 6) || (CPUProfile == "M" && DSP)) 722326941Sdim Builder.defineMacro("__ARM_FEATURE_SIMD32", "1"); 723326941Sdim 724326941Sdim // ACLE 6.4.10 Hardware Integer Divide 725326941Sdim if (((HWDiv & HWDivThumb) && isThumb()) || 726326941Sdim ((HWDiv & HWDivARM) && !isThumb())) { 727326941Sdim Builder.defineMacro("__ARM_FEATURE_IDIV", "1"); 728326941Sdim Builder.defineMacro("__ARM_ARCH_EXT_IDIV__", "1"); 729326941Sdim } 730326941Sdim 731326941Sdim // Note, this is always on in gcc, even though it doesn't make sense. 732326941Sdim Builder.defineMacro("__APCS_32__"); 733326941Sdim 734326941Sdim if (FPUModeIsVFP((FPUMode)FPU)) { 735326941Sdim Builder.defineMacro("__VFP_FP__"); 736326941Sdim if (FPU & VFP2FPU) 737326941Sdim Builder.defineMacro("__ARM_VFPV2__"); 738326941Sdim if (FPU & VFP3FPU) 739326941Sdim Builder.defineMacro("__ARM_VFPV3__"); 740326941Sdim if (FPU & VFP4FPU) 741326941Sdim Builder.defineMacro("__ARM_VFPV4__"); 742326941Sdim if (FPU & FPARMV8) 743326941Sdim Builder.defineMacro("__ARM_FPV5__"); 744326941Sdim } 745326941Sdim 746326941Sdim // This only gets set when Neon instructions are actually available, unlike 747326941Sdim // the VFP define, hence the soft float and arch check. This is subtly 748326941Sdim // different from gcc, we follow the intent which was that it should be set 749326941Sdim // when Neon instructions are actually available. 750326941Sdim if ((FPU & NeonFPU) && !SoftFloat && ArchVersion >= 7) { 751326941Sdim Builder.defineMacro("__ARM_NEON", "1"); 752326941Sdim Builder.defineMacro("__ARM_NEON__"); 753326941Sdim // current AArch32 NEON implementations do not support double-precision 754326941Sdim // floating-point even when it is present in VFP. 755326941Sdim Builder.defineMacro("__ARM_NEON_FP", 756327330Sdim "0x" + Twine::utohexstr(HW_FP & ~HW_FP_DP)); 757326941Sdim } 758326941Sdim 759353358Sdim if (hasMVE()) { 760353358Sdim Builder.defineMacro("__ARM_FEATURE_MVE", hasMVEFloat() ? "3" : "1"); 761353358Sdim } 762353358Sdim 763326941Sdim Builder.defineMacro("__ARM_SIZEOF_WCHAR_T", 764327330Sdim Twine(Opts.WCharSize ? Opts.WCharSize : 4)); 765326941Sdim 766326941Sdim Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4"); 767326941Sdim 768353358Sdim // CMSE 769353358Sdim if (ArchVersion == 8 && ArchProfile == llvm::ARM::ProfileKind::M) 770353358Sdim Builder.defineMacro("__ARM_FEATURE_CMSE", Opts.Cmse ? "3" : "1"); 771353358Sdim 772326941Sdim if (ArchVersion >= 6 && CPUAttr != "6M" && CPUAttr != "8M_BASE") { 773326941Sdim Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); 774326941Sdim Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); 775326941Sdim Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); 776326941Sdim Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); 777326941Sdim } 778326941Sdim 779326941Sdim // ACLE 6.4.7 DSP instructions 780326941Sdim if (DSP) { 781326941Sdim Builder.defineMacro("__ARM_FEATURE_DSP", "1"); 782326941Sdim } 783326941Sdim 784326941Sdim // ACLE 6.4.8 Saturation instructions 785326941Sdim bool SAT = false; 786326941Sdim if ((ArchVersion == 6 && CPUProfile != "M") || ArchVersion > 6) { 787326941Sdim Builder.defineMacro("__ARM_FEATURE_SAT", "1"); 788326941Sdim SAT = true; 789326941Sdim } 790326941Sdim 791326941Sdim // ACLE 6.4.6 Q (saturation) flag 792326941Sdim if (DSP || SAT) 793326941Sdim Builder.defineMacro("__ARM_FEATURE_QBIT", "1"); 794326941Sdim 795326941Sdim if (Opts.UnsafeFPMath) 796326941Sdim Builder.defineMacro("__ARM_FP_FAST", "1"); 797326941Sdim 798341825Sdim // Armv8.2-A FP16 vector intrinsic 799341825Sdim if ((FPU & NeonFPU) && HasLegalHalfType) 800341825Sdim Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1"); 801341825Sdim 802341825Sdim // Armv8.2-A FP16 scalar intrinsics 803341825Sdim if (HasLegalHalfType) 804341825Sdim Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1"); 805341825Sdim 806341825Sdim // Armv8.2-A dot product intrinsics 807341825Sdim if (DotProd) 808341825Sdim Builder.defineMacro("__ARM_FEATURE_DOTPROD", "1"); 809341825Sdim 810326941Sdim switch (ArchKind) { 811326941Sdim default: 812326941Sdim break; 813326941Sdim case llvm::ARM::ArchKind::ARMV8_1A: 814326941Sdim getTargetDefinesARMV81A(Opts, Builder); 815326941Sdim break; 816326941Sdim case llvm::ARM::ArchKind::ARMV8_2A: 817326941Sdim getTargetDefinesARMV82A(Opts, Builder); 818326941Sdim break; 819360784Sdim case llvm::ARM::ArchKind::ARMV8_3A: 820360784Sdim case llvm::ARM::ArchKind::ARMV8_4A: 821360784Sdim case llvm::ARM::ArchKind::ARMV8_5A: 822360784Sdim getTargetDefinesARMV83A(Opts, Builder); 823360784Sdim break; 824326941Sdim } 825326941Sdim} 826326941Sdim 827326941Sdimconst Builtin::Info ARMTargetInfo::BuiltinInfo[] = { 828326941Sdim#define BUILTIN(ID, TYPE, ATTRS) \ 829326941Sdim {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, 830326941Sdim#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ 831326941Sdim {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr}, 832326941Sdim#include "clang/Basic/BuiltinsNEON.def" 833326941Sdim 834326941Sdim#define BUILTIN(ID, TYPE, ATTRS) \ 835326941Sdim {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, 836326941Sdim#define LANGBUILTIN(ID, TYPE, ATTRS, LANG) \ 837326941Sdim {#ID, TYPE, ATTRS, nullptr, LANG, nullptr}, 838326941Sdim#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ 839326941Sdim {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr}, 840326941Sdim#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \ 841326941Sdim {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE}, 842326941Sdim#include "clang/Basic/BuiltinsARM.def" 843326941Sdim}; 844326941Sdim 845326941SdimArrayRef<Builtin::Info> ARMTargetInfo::getTargetBuiltins() const { 846326941Sdim return llvm::makeArrayRef(BuiltinInfo, clang::ARM::LastTSBuiltin - 847326941Sdim Builtin::FirstTSBuiltin); 848326941Sdim} 849326941Sdim 850326941Sdimbool ARMTargetInfo::isCLZForZeroUndef() const { return false; } 851326941SdimTargetInfo::BuiltinVaListKind ARMTargetInfo::getBuiltinVaListKind() const { 852326941Sdim return IsAAPCS 853326941Sdim ? AAPCSABIBuiltinVaList 854326941Sdim : (getTriple().isWatchABI() ? TargetInfo::CharPtrBuiltinVaList 855326941Sdim : TargetInfo::VoidPtrBuiltinVaList); 856326941Sdim} 857326941Sdim 858326941Sdimconst char *const ARMTargetInfo::GCCRegNames[] = { 859326941Sdim // Integer registers 860326941Sdim "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", 861326941Sdim "r12", "sp", "lr", "pc", 862326941Sdim 863326941Sdim // Float registers 864326941Sdim "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", 865326941Sdim "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22", 866326941Sdim "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", 867326941Sdim 868326941Sdim // Double registers 869326941Sdim "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11", 870326941Sdim "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22", 871326941Sdim "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31", 872326941Sdim 873326941Sdim // Quad registers 874326941Sdim "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11", 875326941Sdim "q12", "q13", "q14", "q15"}; 876326941Sdim 877326941SdimArrayRef<const char *> ARMTargetInfo::getGCCRegNames() const { 878326941Sdim return llvm::makeArrayRef(GCCRegNames); 879326941Sdim} 880326941Sdim 881326941Sdimconst TargetInfo::GCCRegAlias ARMTargetInfo::GCCRegAliases[] = { 882326941Sdim {{"a1"}, "r0"}, {{"a2"}, "r1"}, {{"a3"}, "r2"}, {{"a4"}, "r3"}, 883326941Sdim {{"v1"}, "r4"}, {{"v2"}, "r5"}, {{"v3"}, "r6"}, {{"v4"}, "r7"}, 884326941Sdim {{"v5"}, "r8"}, {{"v6", "rfp"}, "r9"}, {{"sl"}, "r10"}, {{"fp"}, "r11"}, 885326941Sdim {{"ip"}, "r12"}, {{"r13"}, "sp"}, {{"r14"}, "lr"}, {{"r15"}, "pc"}, 886326941Sdim // The S, D and Q registers overlap, but aren't really aliases; we 887326941Sdim // don't want to substitute one of these for a different-sized one. 888326941Sdim}; 889326941Sdim 890326941SdimArrayRef<TargetInfo::GCCRegAlias> ARMTargetInfo::getGCCRegAliases() const { 891326941Sdim return llvm::makeArrayRef(GCCRegAliases); 892326941Sdim} 893326941Sdim 894326941Sdimbool ARMTargetInfo::validateAsmConstraint( 895326941Sdim const char *&Name, TargetInfo::ConstraintInfo &Info) const { 896326941Sdim switch (*Name) { 897326941Sdim default: 898326941Sdim break; 899360784Sdim case 'l': // r0-r7 if thumb, r0-r15 if ARM 900326941Sdim Info.setAllowsRegister(); 901326941Sdim return true; 902360784Sdim case 'h': // r8-r15, thumb only 903360784Sdim if (isThumb()) { 904360784Sdim Info.setAllowsRegister(); 905360784Sdim return true; 906360784Sdim } 907360784Sdim break; 908360784Sdim case 's': // An integer constant, but allowing only relocatable values. 909360784Sdim return true; 910360784Sdim case 't': // s0-s31, d0-d31, or q0-q15 911360784Sdim case 'w': // s0-s15, d0-d7, or q0-q3 912360784Sdim case 'x': // s0-s31, d0-d15, or q0-q7 913360784Sdim Info.setAllowsRegister(); 914360784Sdim return true; 915360784Sdim case 'j': // An immediate integer between 0 and 65535 (valid for MOVW) 916360784Sdim // only available in ARMv6T2 and above 917360784Sdim if (CPUAttr.equals("6T2") || ArchVersion >= 7) { 918360784Sdim Info.setRequiresImmediate(0, 65535); 919360784Sdim return true; 920360784Sdim } 921360784Sdim break; 922326941Sdim case 'I': 923360784Sdim if (isThumb()) { 924360784Sdim if (!supportsThumb2()) 925360784Sdim Info.setRequiresImmediate(0, 255); 926360784Sdim else 927360784Sdim // FIXME: should check if immediate value would be valid for a Thumb2 928360784Sdim // data-processing instruction 929360784Sdim Info.setRequiresImmediate(); 930360784Sdim } else 931360784Sdim // FIXME: should check if immediate value would be valid for an ARM 932360784Sdim // data-processing instruction 933360784Sdim Info.setRequiresImmediate(); 934360784Sdim return true; 935326941Sdim case 'J': 936360784Sdim if (isThumb() && !supportsThumb2()) 937360784Sdim Info.setRequiresImmediate(-255, -1); 938360784Sdim else 939360784Sdim Info.setRequiresImmediate(-4095, 4095); 940360784Sdim return true; 941326941Sdim case 'K': 942360784Sdim if (isThumb()) { 943360784Sdim if (!supportsThumb2()) 944360784Sdim // FIXME: should check if immediate value can be obtained from shifting 945360784Sdim // a value between 0 and 255 left by any amount 946360784Sdim Info.setRequiresImmediate(); 947360784Sdim else 948360784Sdim // FIXME: should check if immediate value would be valid for a Thumb2 949360784Sdim // data-processing instruction when inverted 950360784Sdim Info.setRequiresImmediate(); 951360784Sdim } else 952360784Sdim // FIXME: should check if immediate value would be valid for an ARM 953360784Sdim // data-processing instruction when inverted 954360784Sdim Info.setRequiresImmediate(); 955360784Sdim return true; 956326941Sdim case 'L': 957360784Sdim if (isThumb()) { 958360784Sdim if (!supportsThumb2()) 959360784Sdim Info.setRequiresImmediate(-7, 7); 960360784Sdim else 961360784Sdim // FIXME: should check if immediate value would be valid for a Thumb2 962360784Sdim // data-processing instruction when negated 963360784Sdim Info.setRequiresImmediate(); 964360784Sdim } else 965360784Sdim // FIXME: should check if immediate value would be valid for an ARM 966360784Sdim // data-processing instruction when negated 967360784Sdim Info.setRequiresImmediate(); 968360784Sdim return true; 969326941Sdim case 'M': 970360784Sdim if (isThumb() && !supportsThumb2()) 971360784Sdim // FIXME: should check if immediate value is a multiple of 4 between 0 and 972360784Sdim // 1020 973360784Sdim Info.setRequiresImmediate(); 974360784Sdim else 975360784Sdim // FIXME: should check if immediate value is a power of two or a integer 976360784Sdim // between 0 and 32 977360784Sdim Info.setRequiresImmediate(); 978326941Sdim return true; 979360784Sdim case 'N': 980360784Sdim // Thumb1 only 981360784Sdim if (isThumb() && !supportsThumb2()) { 982360784Sdim Info.setRequiresImmediate(0, 31); 983360784Sdim return true; 984360784Sdim } 985360784Sdim break; 986360784Sdim case 'O': 987360784Sdim // Thumb1 only 988360784Sdim if (isThumb() && !supportsThumb2()) { 989360784Sdim // FIXME: should check if immediate value is a multiple of 4 between -508 990360784Sdim // and 508 991360784Sdim Info.setRequiresImmediate(); 992360784Sdim return true; 993360784Sdim } 994360784Sdim break; 995326941Sdim case 'Q': // A memory address that is a single base register. 996326941Sdim Info.setAllowsMemory(); 997326941Sdim return true; 998353358Sdim case 'T': 999353358Sdim switch (Name[1]) { 1000353358Sdim default: 1001353358Sdim break; 1002353358Sdim case 'e': // Even general-purpose register 1003353358Sdim case 'o': // Odd general-purpose register 1004353358Sdim Info.setAllowsRegister(); 1005353358Sdim Name++; 1006353358Sdim return true; 1007353358Sdim } 1008353358Sdim break; 1009326941Sdim case 'U': // a memory reference... 1010326941Sdim switch (Name[1]) { 1011326941Sdim case 'q': // ...ARMV4 ldrsb 1012326941Sdim case 'v': // ...VFP load/store (reg+constant offset) 1013326941Sdim case 'y': // ...iWMMXt load/store 1014326941Sdim case 't': // address valid for load/store opaque types wider 1015326941Sdim // than 128-bits 1016326941Sdim case 'n': // valid address for Neon doubleword vector load/store 1017326941Sdim case 'm': // valid address for Neon element and structure load/store 1018326941Sdim case 's': // valid address for non-offset loads/stores of quad-word 1019326941Sdim // values in four ARM registers 1020326941Sdim Info.setAllowsMemory(); 1021326941Sdim Name++; 1022326941Sdim return true; 1023326941Sdim } 1024353358Sdim break; 1025326941Sdim } 1026326941Sdim return false; 1027326941Sdim} 1028326941Sdim 1029326941Sdimstd::string ARMTargetInfo::convertConstraint(const char *&Constraint) const { 1030326941Sdim std::string R; 1031326941Sdim switch (*Constraint) { 1032326941Sdim case 'U': // Two-character constraint; add "^" hint for later parsing. 1033353358Sdim case 'T': 1034326941Sdim R = std::string("^") + std::string(Constraint, 2); 1035326941Sdim Constraint++; 1036326941Sdim break; 1037326941Sdim case 'p': // 'p' should be translated to 'r' by default. 1038326941Sdim R = std::string("r"); 1039326941Sdim break; 1040326941Sdim default: 1041326941Sdim return std::string(1, *Constraint); 1042326941Sdim } 1043326941Sdim return R; 1044326941Sdim} 1045326941Sdim 1046326941Sdimbool ARMTargetInfo::validateConstraintModifier( 1047326941Sdim StringRef Constraint, char Modifier, unsigned Size, 1048326941Sdim std::string &SuggestedModifier) const { 1049326941Sdim bool isOutput = (Constraint[0] == '='); 1050326941Sdim bool isInOut = (Constraint[0] == '+'); 1051326941Sdim 1052326941Sdim // Strip off constraint modifiers. 1053326941Sdim while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&') 1054326941Sdim Constraint = Constraint.substr(1); 1055326941Sdim 1056326941Sdim switch (Constraint[0]) { 1057326941Sdim default: 1058326941Sdim break; 1059326941Sdim case 'r': { 1060326941Sdim switch (Modifier) { 1061326941Sdim default: 1062326941Sdim return (isInOut || isOutput || Size <= 64); 1063326941Sdim case 'q': 1064326941Sdim // A register of size 32 cannot fit a vector type. 1065326941Sdim return false; 1066326941Sdim } 1067326941Sdim } 1068326941Sdim } 1069326941Sdim 1070326941Sdim return true; 1071326941Sdim} 1072326941Sdimconst char *ARMTargetInfo::getClobbers() const { 1073326941Sdim // FIXME: Is this really right? 1074326941Sdim return ""; 1075326941Sdim} 1076326941Sdim 1077326941SdimTargetInfo::CallingConvCheckResult 1078326941SdimARMTargetInfo::checkCallingConvention(CallingConv CC) const { 1079326941Sdim switch (CC) { 1080326941Sdim case CC_AAPCS: 1081326941Sdim case CC_AAPCS_VFP: 1082326941Sdim case CC_Swift: 1083326941Sdim case CC_OpenCLKernel: 1084326941Sdim return CCCR_OK; 1085326941Sdim default: 1086326941Sdim return CCCR_Warning; 1087326941Sdim } 1088326941Sdim} 1089326941Sdim 1090326941Sdimint ARMTargetInfo::getEHDataRegisterNumber(unsigned RegNo) const { 1091326941Sdim if (RegNo == 0) 1092326941Sdim return 0; 1093326941Sdim if (RegNo == 1) 1094326941Sdim return 1; 1095326941Sdim return -1; 1096326941Sdim} 1097326941Sdim 1098326941Sdimbool ARMTargetInfo::hasSjLjLowering() const { return true; } 1099326941Sdim 1100326941SdimARMleTargetInfo::ARMleTargetInfo(const llvm::Triple &Triple, 1101326941Sdim const TargetOptions &Opts) 1102326941Sdim : ARMTargetInfo(Triple, Opts) {} 1103326941Sdim 1104326941Sdimvoid ARMleTargetInfo::getTargetDefines(const LangOptions &Opts, 1105326941Sdim MacroBuilder &Builder) const { 1106326941Sdim Builder.defineMacro("__ARMEL__"); 1107326941Sdim ARMTargetInfo::getTargetDefines(Opts, Builder); 1108326941Sdim} 1109326941Sdim 1110326941SdimARMbeTargetInfo::ARMbeTargetInfo(const llvm::Triple &Triple, 1111326941Sdim const TargetOptions &Opts) 1112326941Sdim : ARMTargetInfo(Triple, Opts) {} 1113326941Sdim 1114326941Sdimvoid ARMbeTargetInfo::getTargetDefines(const LangOptions &Opts, 1115326941Sdim MacroBuilder &Builder) const { 1116326941Sdim Builder.defineMacro("__ARMEB__"); 1117326941Sdim Builder.defineMacro("__ARM_BIG_ENDIAN"); 1118326941Sdim ARMTargetInfo::getTargetDefines(Opts, Builder); 1119326941Sdim} 1120326941Sdim 1121326941SdimWindowsARMTargetInfo::WindowsARMTargetInfo(const llvm::Triple &Triple, 1122326941Sdim const TargetOptions &Opts) 1123326941Sdim : WindowsTargetInfo<ARMleTargetInfo>(Triple, Opts), Triple(Triple) { 1124326941Sdim} 1125326941Sdim 1126326941Sdimvoid WindowsARMTargetInfo::getVisualStudioDefines(const LangOptions &Opts, 1127326941Sdim MacroBuilder &Builder) const { 1128326941Sdim // FIXME: this is invalid for WindowsCE 1129326941Sdim Builder.defineMacro("_M_ARM_NT", "1"); 1130326941Sdim Builder.defineMacro("_M_ARMT", "_M_ARM"); 1131326941Sdim Builder.defineMacro("_M_THUMB", "_M_ARM"); 1132326941Sdim 1133326941Sdim assert((Triple.getArch() == llvm::Triple::arm || 1134326941Sdim Triple.getArch() == llvm::Triple::thumb) && 1135326941Sdim "invalid architecture for Windows ARM target info"); 1136326941Sdim unsigned Offset = Triple.getArch() == llvm::Triple::arm ? 4 : 6; 1137326941Sdim Builder.defineMacro("_M_ARM", Triple.getArchName().substr(Offset)); 1138326941Sdim 1139326941Sdim // TODO map the complete set of values 1140326941Sdim // 31: VFPv3 40: VFPv4 1141326941Sdim Builder.defineMacro("_M_ARM_FP", "31"); 1142326941Sdim} 1143326941Sdim 1144326941SdimTargetInfo::BuiltinVaListKind 1145326941SdimWindowsARMTargetInfo::getBuiltinVaListKind() const { 1146326941Sdim return TargetInfo::CharPtrBuiltinVaList; 1147326941Sdim} 1148326941Sdim 1149326941SdimTargetInfo::CallingConvCheckResult 1150326941SdimWindowsARMTargetInfo::checkCallingConvention(CallingConv CC) const { 1151326941Sdim switch (CC) { 1152326941Sdim case CC_X86StdCall: 1153326941Sdim case CC_X86ThisCall: 1154326941Sdim case CC_X86FastCall: 1155326941Sdim case CC_X86VectorCall: 1156326941Sdim return CCCR_Ignore; 1157326941Sdim case CC_C: 1158326941Sdim case CC_OpenCLKernel: 1159341825Sdim case CC_PreserveMost: 1160341825Sdim case CC_PreserveAll: 1161344779Sdim case CC_Swift: 1162326941Sdim return CCCR_OK; 1163326941Sdim default: 1164326941Sdim return CCCR_Warning; 1165326941Sdim } 1166326941Sdim} 1167326941Sdim 1168326941Sdim// Windows ARM + Itanium C++ ABI Target 1169326941SdimItaniumWindowsARMleTargetInfo::ItaniumWindowsARMleTargetInfo( 1170326941Sdim const llvm::Triple &Triple, const TargetOptions &Opts) 1171326941Sdim : WindowsARMTargetInfo(Triple, Opts) { 1172326941Sdim TheCXXABI.set(TargetCXXABI::GenericARM); 1173326941Sdim} 1174326941Sdim 1175326941Sdimvoid ItaniumWindowsARMleTargetInfo::getTargetDefines( 1176326941Sdim const LangOptions &Opts, MacroBuilder &Builder) const { 1177326941Sdim WindowsARMTargetInfo::getTargetDefines(Opts, Builder); 1178326941Sdim 1179326941Sdim if (Opts.MSVCCompat) 1180326941Sdim WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder); 1181326941Sdim} 1182326941Sdim 1183326941Sdim// Windows ARM, MS (C++) ABI 1184326941SdimMicrosoftARMleTargetInfo::MicrosoftARMleTargetInfo(const llvm::Triple &Triple, 1185326941Sdim const TargetOptions &Opts) 1186326941Sdim : WindowsARMTargetInfo(Triple, Opts) { 1187326941Sdim TheCXXABI.set(TargetCXXABI::Microsoft); 1188326941Sdim} 1189326941Sdim 1190326941Sdimvoid MicrosoftARMleTargetInfo::getTargetDefines(const LangOptions &Opts, 1191326941Sdim MacroBuilder &Builder) const { 1192326941Sdim WindowsARMTargetInfo::getTargetDefines(Opts, Builder); 1193326941Sdim WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder); 1194326941Sdim} 1195326941Sdim 1196326941SdimMinGWARMTargetInfo::MinGWARMTargetInfo(const llvm::Triple &Triple, 1197326941Sdim const TargetOptions &Opts) 1198326941Sdim : WindowsARMTargetInfo(Triple, Opts) { 1199326941Sdim TheCXXABI.set(TargetCXXABI::GenericARM); 1200326941Sdim} 1201326941Sdim 1202326941Sdimvoid MinGWARMTargetInfo::getTargetDefines(const LangOptions &Opts, 1203326941Sdim MacroBuilder &Builder) const { 1204326941Sdim WindowsARMTargetInfo::getTargetDefines(Opts, Builder); 1205326941Sdim Builder.defineMacro("_ARM_"); 1206326941Sdim} 1207326941Sdim 1208326941SdimCygwinARMTargetInfo::CygwinARMTargetInfo(const llvm::Triple &Triple, 1209326941Sdim const TargetOptions &Opts) 1210326941Sdim : ARMleTargetInfo(Triple, Opts) { 1211326941Sdim this->WCharType = TargetInfo::UnsignedShort; 1212326941Sdim TLSSupported = false; 1213326941Sdim DoubleAlign = LongLongAlign = 64; 1214353358Sdim resetDataLayout("e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"); 1215326941Sdim} 1216326941Sdim 1217326941Sdimvoid CygwinARMTargetInfo::getTargetDefines(const LangOptions &Opts, 1218326941Sdim MacroBuilder &Builder) const { 1219326941Sdim ARMleTargetInfo::getTargetDefines(Opts, Builder); 1220326941Sdim Builder.defineMacro("_ARM_"); 1221326941Sdim Builder.defineMacro("__CYGWIN__"); 1222326941Sdim Builder.defineMacro("__CYGWIN32__"); 1223326941Sdim DefineStd(Builder, "unix", Opts); 1224326941Sdim if (Opts.CPlusPlus) 1225326941Sdim Builder.defineMacro("_GNU_SOURCE"); 1226326941Sdim} 1227326941Sdim 1228326941SdimDarwinARMTargetInfo::DarwinARMTargetInfo(const llvm::Triple &Triple, 1229326941Sdim const TargetOptions &Opts) 1230326941Sdim : DarwinTargetInfo<ARMleTargetInfo>(Triple, Opts) { 1231326941Sdim HasAlignMac68kSupport = true; 1232326941Sdim // iOS always has 64-bit atomic instructions. 1233326941Sdim // FIXME: This should be based off of the target features in 1234326941Sdim // ARMleTargetInfo. 1235326941Sdim MaxAtomicInlineWidth = 64; 1236326941Sdim 1237326941Sdim if (Triple.isWatchABI()) { 1238326941Sdim // Darwin on iOS uses a variant of the ARM C++ ABI. 1239326941Sdim TheCXXABI.set(TargetCXXABI::WatchOS); 1240326941Sdim 1241326941Sdim // BOOL should be a real boolean on the new ABI 1242326941Sdim UseSignedCharForObjCBool = false; 1243326941Sdim } else 1244326941Sdim TheCXXABI.set(TargetCXXABI::iOS); 1245326941Sdim} 1246326941Sdim 1247326941Sdimvoid DarwinARMTargetInfo::getOSDefines(const LangOptions &Opts, 1248326941Sdim const llvm::Triple &Triple, 1249326941Sdim MacroBuilder &Builder) const { 1250326941Sdim getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion); 1251326941Sdim} 1252326941Sdim 1253326941SdimRenderScript32TargetInfo::RenderScript32TargetInfo(const llvm::Triple &Triple, 1254326941Sdim const TargetOptions &Opts) 1255326941Sdim : ARMleTargetInfo(llvm::Triple("armv7", Triple.getVendorName(), 1256326941Sdim Triple.getOSName(), 1257326941Sdim Triple.getEnvironmentName()), 1258326941Sdim Opts) { 1259326941Sdim IsRenderScriptTarget = true; 1260326941Sdim LongWidth = LongAlign = 64; 1261326941Sdim} 1262326941Sdim 1263326941Sdimvoid RenderScript32TargetInfo::getTargetDefines(const LangOptions &Opts, 1264326941Sdim MacroBuilder &Builder) const { 1265326941Sdim Builder.defineMacro("__RENDERSCRIPT__"); 1266326941Sdim ARMleTargetInfo::getTargetDefines(Opts, Builder); 1267326941Sdim} 1268