xref: /freebsd-src/contrib/llvm-project/clang/lib/Basic/Targets/ARM.cpp (revision d686ce931cab72612a9e1ada9fe99d65e11a32a3)
10b57cec5SDimitry Andric //===--- ARM.cpp - Implement ARM target feature support -------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements ARM TargetInfo objects.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "ARM.h"
140b57cec5SDimitry Andric #include "clang/Basic/Builtins.h"
150b57cec5SDimitry Andric #include "clang/Basic/Diagnostic.h"
160b57cec5SDimitry Andric #include "clang/Basic/TargetBuiltins.h"
170b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
180b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
190b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
201db9f3b2SDimitry Andric #include "llvm/TargetParser/ARMTargetParser.h"
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric using namespace clang;
230b57cec5SDimitry Andric using namespace clang::targets;
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric void ARMTargetInfo::setABIAAPCS() {
260b57cec5SDimitry Andric   IsAAPCS = true;
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric   DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;
295ffd83dbSDimitry Andric   BFloat16Width = BFloat16Align = 16;
305ffd83dbSDimitry Andric   BFloat16Format = &llvm::APFloat::BFloat();
315ffd83dbSDimitry Andric 
320b57cec5SDimitry Andric   const llvm::Triple &T = getTriple();
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric   bool IsNetBSD = T.isOSNetBSD();
350b57cec5SDimitry Andric   bool IsOpenBSD = T.isOSOpenBSD();
360b57cec5SDimitry Andric   if (!T.isOSWindows() && !IsNetBSD && !IsOpenBSD)
370b57cec5SDimitry Andric     WCharType = UnsignedInt;
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric   UseBitFieldTypeAlignment = true;
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric   ZeroLengthBitfieldBoundary = 0;
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric   // Thumb1 add sp, #imm requires the immediate value be multiple of 4,
440b57cec5SDimitry Andric   // so set preferred for small types to 32.
450b57cec5SDimitry Andric   if (T.isOSBinFormatMachO()) {
460b57cec5SDimitry Andric     resetDataLayout(BigEndian
470b57cec5SDimitry Andric                         ? "E-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
48fe6060f1SDimitry Andric                         : "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64",
49fe6060f1SDimitry Andric                     "_");
500b57cec5SDimitry Andric   } else if (T.isOSWindows()) {
510b57cec5SDimitry Andric     assert(!BigEndian && "Windows on ARM does not support big endian");
520b57cec5SDimitry Andric     resetDataLayout("e"
530b57cec5SDimitry Andric                     "-m:w"
540b57cec5SDimitry Andric                     "-p:32:32"
550b57cec5SDimitry Andric                     "-Fi8"
560b57cec5SDimitry Andric                     "-i64:64"
570b57cec5SDimitry Andric                     "-v128:64:128"
580b57cec5SDimitry Andric                     "-a:0:32"
590b57cec5SDimitry Andric                     "-n32"
600b57cec5SDimitry Andric                     "-S64");
610b57cec5SDimitry Andric   } else if (T.isOSNaCl()) {
620b57cec5SDimitry Andric     assert(!BigEndian && "NaCl on ARM does not support big endian");
630b57cec5SDimitry Andric     resetDataLayout("e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S128");
640b57cec5SDimitry Andric   } else {
650b57cec5SDimitry Andric     resetDataLayout(BigEndian
660b57cec5SDimitry Andric                         ? "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
670b57cec5SDimitry Andric                         : "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64");
680b57cec5SDimitry Andric   }
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric   // FIXME: Enumerated types are variable width in straight AAPCS.
710b57cec5SDimitry Andric }
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric void ARMTargetInfo::setABIAPCS(bool IsAAPCS16) {
740b57cec5SDimitry Andric   const llvm::Triple &T = getTriple();
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric   IsAAPCS = false;
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric   if (IsAAPCS16)
790b57cec5SDimitry Andric     DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;
800b57cec5SDimitry Andric   else
810b57cec5SDimitry Andric     DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 32;
825ffd83dbSDimitry Andric   BFloat16Width = BFloat16Align = 16;
835ffd83dbSDimitry Andric   BFloat16Format = &llvm::APFloat::BFloat();
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   WCharType = SignedInt;
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric   // Do not respect the alignment of bit-field types when laying out
880b57cec5SDimitry Andric   // structures. This corresponds to PCC_BITFIELD_TYPE_MATTERS in gcc.
890b57cec5SDimitry Andric   UseBitFieldTypeAlignment = false;
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric   /// gcc forces the alignment to 4 bytes, regardless of the type of the
920b57cec5SDimitry Andric   /// zero length bitfield.  This corresponds to EMPTY_FIELD_BOUNDARY in
930b57cec5SDimitry Andric   /// gcc.
940b57cec5SDimitry Andric   ZeroLengthBitfieldBoundary = 32;
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   if (T.isOSBinFormatMachO() && IsAAPCS16) {
970b57cec5SDimitry Andric     assert(!BigEndian && "AAPCS16 does not support big-endian");
98fe6060f1SDimitry Andric     resetDataLayout("e-m:o-p:32:32-Fi8-i64:64-a:0:32-n32-S128", "_");
990b57cec5SDimitry Andric   } else if (T.isOSBinFormatMachO())
1000b57cec5SDimitry Andric     resetDataLayout(
1010b57cec5SDimitry Andric         BigEndian
1020b57cec5SDimitry Andric             ? "E-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
103fe6060f1SDimitry Andric             : "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32",
104fe6060f1SDimitry Andric         "_");
1050b57cec5SDimitry Andric   else
1060b57cec5SDimitry Andric     resetDataLayout(
1070b57cec5SDimitry Andric         BigEndian
1080b57cec5SDimitry Andric             ? "E-m:e-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
1090b57cec5SDimitry Andric             : "e-m:e-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32");
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric   // FIXME: Override "preferred align" for double and long long.
1120b57cec5SDimitry Andric }
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric void ARMTargetInfo::setArchInfo() {
1150b57cec5SDimitry Andric   StringRef ArchName = getTriple().getArchName();
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric   ArchISA = llvm::ARM::parseArchISA(ArchName);
1185ffd83dbSDimitry Andric   CPU = std::string(llvm::ARM::getDefaultCPU(ArchName));
1190b57cec5SDimitry Andric   llvm::ARM::ArchKind AK = llvm::ARM::parseArch(ArchName);
1200b57cec5SDimitry Andric   if (AK != llvm::ARM::ArchKind::INVALID)
1210b57cec5SDimitry Andric     ArchKind = AK;
1220b57cec5SDimitry Andric   setArchInfo(ArchKind);
1230b57cec5SDimitry Andric }
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric void ARMTargetInfo::setArchInfo(llvm::ARM::ArchKind Kind) {
1260b57cec5SDimitry Andric   StringRef SubArch;
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric   // cache TargetParser info
1290b57cec5SDimitry Andric   ArchKind = Kind;
1300b57cec5SDimitry Andric   SubArch = llvm::ARM::getSubArch(ArchKind);
1310b57cec5SDimitry Andric   ArchProfile = llvm::ARM::parseArchProfile(SubArch);
1320b57cec5SDimitry Andric   ArchVersion = llvm::ARM::parseArchVersion(SubArch);
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric   // cache CPU related strings
1350b57cec5SDimitry Andric   CPUAttr = getCPUAttr();
1360b57cec5SDimitry Andric   CPUProfile = getCPUProfile();
1370b57cec5SDimitry Andric }
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric void ARMTargetInfo::setAtomic() {
1400b57cec5SDimitry Andric   // when triple does not specify a sub arch,
1410b57cec5SDimitry Andric   // then we are not using inline atomics
1420b57cec5SDimitry Andric   bool ShouldUseInlineAtomic =
1430b57cec5SDimitry Andric       (ArchISA == llvm::ARM::ISAKind::ARM && ArchVersion >= 6) ||
1440b57cec5SDimitry Andric       (ArchISA == llvm::ARM::ISAKind::THUMB && ArchVersion >= 7);
1450b57cec5SDimitry Andric   // Cortex M does not support 8 byte atomics, while general Thumb2 does.
1460b57cec5SDimitry Andric   if (ArchProfile == llvm::ARM::ProfileKind::M) {
1470b57cec5SDimitry Andric     MaxAtomicPromoteWidth = 32;
1480b57cec5SDimitry Andric     if (ShouldUseInlineAtomic)
1490b57cec5SDimitry Andric       MaxAtomicInlineWidth = 32;
1500b57cec5SDimitry Andric   } else {
1510b57cec5SDimitry Andric     MaxAtomicPromoteWidth = 64;
1520b57cec5SDimitry Andric     if (ShouldUseInlineAtomic)
1530b57cec5SDimitry Andric       MaxAtomicInlineWidth = 64;
1540b57cec5SDimitry Andric   }
1550b57cec5SDimitry Andric }
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric bool ARMTargetInfo::hasMVE() const {
1580b57cec5SDimitry Andric   return ArchKind == llvm::ARM::ArchKind::ARMV8_1MMainline && MVE != 0;
1590b57cec5SDimitry Andric }
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric bool ARMTargetInfo::hasMVEFloat() const {
1620b57cec5SDimitry Andric   return hasMVE() && (MVE & MVE_FP);
1630b57cec5SDimitry Andric }
1640b57cec5SDimitry Andric 
1655ffd83dbSDimitry Andric bool ARMTargetInfo::hasCDE() const { return getARMCDECoprocMask() != 0; }
1665ffd83dbSDimitry Andric 
1670b57cec5SDimitry Andric bool ARMTargetInfo::isThumb() const {
1680b57cec5SDimitry Andric   return ArchISA == llvm::ARM::ISAKind::THUMB;
1690b57cec5SDimitry Andric }
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric bool ARMTargetInfo::supportsThumb() const {
1720b57cec5SDimitry Andric   return CPUAttr.count('T') || ArchVersion >= 6;
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric bool ARMTargetInfo::supportsThumb2() const {
1760fca6ea1SDimitry Andric   return CPUAttr == "6T2" || (ArchVersion >= 7 && CPUAttr != "8M_BASE");
1770b57cec5SDimitry Andric }
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric StringRef ARMTargetInfo::getCPUAttr() const {
1800b57cec5SDimitry Andric   // For most sub-arches, the build attribute CPU name is enough.
1810b57cec5SDimitry Andric   // For Cortex variants, it's slightly different.
1820b57cec5SDimitry Andric   switch (ArchKind) {
1830b57cec5SDimitry Andric   default:
1840b57cec5SDimitry Andric     return llvm::ARM::getCPUAttr(ArchKind);
1850b57cec5SDimitry Andric   case llvm::ARM::ArchKind::ARMV6M:
1860b57cec5SDimitry Andric     return "6M";
1870b57cec5SDimitry Andric   case llvm::ARM::ArchKind::ARMV7S:
1880b57cec5SDimitry Andric     return "7S";
1890b57cec5SDimitry Andric   case llvm::ARM::ArchKind::ARMV7A:
1900b57cec5SDimitry Andric     return "7A";
1910b57cec5SDimitry Andric   case llvm::ARM::ArchKind::ARMV7R:
1920b57cec5SDimitry Andric     return "7R";
1930b57cec5SDimitry Andric   case llvm::ARM::ArchKind::ARMV7M:
1940b57cec5SDimitry Andric     return "7M";
1950b57cec5SDimitry Andric   case llvm::ARM::ArchKind::ARMV7EM:
1960b57cec5SDimitry Andric     return "7EM";
1970b57cec5SDimitry Andric   case llvm::ARM::ArchKind::ARMV7VE:
1980b57cec5SDimitry Andric     return "7VE";
1990b57cec5SDimitry Andric   case llvm::ARM::ArchKind::ARMV8A:
2000b57cec5SDimitry Andric     return "8A";
2010b57cec5SDimitry Andric   case llvm::ARM::ArchKind::ARMV8_1A:
2020b57cec5SDimitry Andric     return "8_1A";
2030b57cec5SDimitry Andric   case llvm::ARM::ArchKind::ARMV8_2A:
2040b57cec5SDimitry Andric     return "8_2A";
2050b57cec5SDimitry Andric   case llvm::ARM::ArchKind::ARMV8_3A:
2060b57cec5SDimitry Andric     return "8_3A";
2070b57cec5SDimitry Andric   case llvm::ARM::ArchKind::ARMV8_4A:
2080b57cec5SDimitry Andric     return "8_4A";
2090b57cec5SDimitry Andric   case llvm::ARM::ArchKind::ARMV8_5A:
2100b57cec5SDimitry Andric     return "8_5A";
2115ffd83dbSDimitry Andric   case llvm::ARM::ArchKind::ARMV8_6A:
2125ffd83dbSDimitry Andric     return "8_6A";
213e8d8bef9SDimitry Andric   case llvm::ARM::ArchKind::ARMV8_7A:
214e8d8bef9SDimitry Andric     return "8_7A";
21504eeddc0SDimitry Andric   case llvm::ARM::ArchKind::ARMV8_8A:
21604eeddc0SDimitry Andric     return "8_8A";
217bdd1243dSDimitry Andric   case llvm::ARM::ArchKind::ARMV8_9A:
218bdd1243dSDimitry Andric     return "8_9A";
219349cc55cSDimitry Andric   case llvm::ARM::ArchKind::ARMV9A:
220349cc55cSDimitry Andric     return "9A";
221349cc55cSDimitry Andric   case llvm::ARM::ArchKind::ARMV9_1A:
222349cc55cSDimitry Andric     return "9_1A";
223349cc55cSDimitry Andric   case llvm::ARM::ArchKind::ARMV9_2A:
224349cc55cSDimitry Andric     return "9_2A";
22504eeddc0SDimitry Andric   case llvm::ARM::ArchKind::ARMV9_3A:
22604eeddc0SDimitry Andric     return "9_3A";
227bdd1243dSDimitry Andric   case llvm::ARM::ArchKind::ARMV9_4A:
228bdd1243dSDimitry Andric     return "9_4A";
2297a6dacacSDimitry Andric   case llvm::ARM::ArchKind::ARMV9_5A:
2307a6dacacSDimitry Andric     return "9_5A";
2310b57cec5SDimitry Andric   case llvm::ARM::ArchKind::ARMV8MBaseline:
2320b57cec5SDimitry Andric     return "8M_BASE";
2330b57cec5SDimitry Andric   case llvm::ARM::ArchKind::ARMV8MMainline:
2340b57cec5SDimitry Andric     return "8M_MAIN";
2350b57cec5SDimitry Andric   case llvm::ARM::ArchKind::ARMV8R:
2360b57cec5SDimitry Andric     return "8R";
2370b57cec5SDimitry Andric   case llvm::ARM::ArchKind::ARMV8_1MMainline:
2380b57cec5SDimitry Andric     return "8_1M_MAIN";
2390b57cec5SDimitry Andric   }
2400b57cec5SDimitry Andric }
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric StringRef ARMTargetInfo::getCPUProfile() const {
2430b57cec5SDimitry Andric   switch (ArchProfile) {
2440b57cec5SDimitry Andric   case llvm::ARM::ProfileKind::A:
2450b57cec5SDimitry Andric     return "A";
2460b57cec5SDimitry Andric   case llvm::ARM::ProfileKind::R:
2470b57cec5SDimitry Andric     return "R";
2480b57cec5SDimitry Andric   case llvm::ARM::ProfileKind::M:
2490b57cec5SDimitry Andric     return "M";
2500b57cec5SDimitry Andric   default:
2510b57cec5SDimitry Andric     return "";
2520b57cec5SDimitry Andric   }
2530b57cec5SDimitry Andric }
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple,
2560b57cec5SDimitry Andric                              const TargetOptions &Opts)
2570b57cec5SDimitry Andric     : TargetInfo(Triple), FPMath(FP_Default), IsAAPCS(true), LDREX(0),
2580b57cec5SDimitry Andric       HW_FP(0) {
2591ac55f4cSDimitry Andric   bool IsFreeBSD = Triple.isOSFreeBSD();
2600b57cec5SDimitry Andric   bool IsOpenBSD = Triple.isOSOpenBSD();
2610b57cec5SDimitry Andric   bool IsNetBSD = Triple.isOSNetBSD();
2625f757f3fSDimitry Andric   bool IsHaiku = Triple.isOSHaiku();
2635f757f3fSDimitry Andric   bool IsOHOS = Triple.isOHOSFamily();
2640b57cec5SDimitry Andric 
2650b57cec5SDimitry Andric   // FIXME: the isOSBinFormatMachO is a workaround for identifying a Darwin-like
2660b57cec5SDimitry Andric   // environment where size_t is `unsigned long` rather than `unsigned int`
2670b57cec5SDimitry Andric 
2680b57cec5SDimitry Andric   PtrDiffType = IntPtrType =
2690b57cec5SDimitry Andric       (Triple.isOSDarwin() || Triple.isOSBinFormatMachO() || IsOpenBSD ||
2700b57cec5SDimitry Andric        IsNetBSD)
2710b57cec5SDimitry Andric           ? SignedLong
2720b57cec5SDimitry Andric           : SignedInt;
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric   SizeType = (Triple.isOSDarwin() || Triple.isOSBinFormatMachO() || IsOpenBSD ||
2750b57cec5SDimitry Andric               IsNetBSD)
2760b57cec5SDimitry Andric                  ? UnsignedLong
2770b57cec5SDimitry Andric                  : UnsignedInt;
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric   // ptrdiff_t is inconsistent on Darwin
2800b57cec5SDimitry Andric   if ((Triple.isOSDarwin() || Triple.isOSBinFormatMachO()) &&
2810b57cec5SDimitry Andric       !Triple.isWatchABI())
2820b57cec5SDimitry Andric     PtrDiffType = SignedInt;
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric   // Cache arch related info.
2850b57cec5SDimitry Andric   setArchInfo();
2860b57cec5SDimitry Andric 
2870b57cec5SDimitry Andric   // {} in inline assembly are neon specifiers, not assembly variant
2880b57cec5SDimitry Andric   // specifiers.
2890b57cec5SDimitry Andric   NoAsmVariants = true;
2900b57cec5SDimitry Andric 
2910b57cec5SDimitry Andric   // FIXME: This duplicates code from the driver that sets the -target-abi
2920b57cec5SDimitry Andric   // option - this code is used if -target-abi isn't passed and should
2930b57cec5SDimitry Andric   // be unified in some way.
2940b57cec5SDimitry Andric   if (Triple.isOSBinFormatMachO()) {
2950b57cec5SDimitry Andric     // The backend is hardwired to assume AAPCS for M-class processors, ensure
2960b57cec5SDimitry Andric     // the frontend matches that.
2970b57cec5SDimitry Andric     if (Triple.getEnvironment() == llvm::Triple::EABI ||
2980b57cec5SDimitry Andric         Triple.getOS() == llvm::Triple::UnknownOS ||
2990b57cec5SDimitry Andric         ArchProfile == llvm::ARM::ProfileKind::M) {
3000b57cec5SDimitry Andric       setABI("aapcs");
3010b57cec5SDimitry Andric     } else if (Triple.isWatchABI()) {
3020b57cec5SDimitry Andric       setABI("aapcs16");
3030b57cec5SDimitry Andric     } else {
3040b57cec5SDimitry Andric       setABI("apcs-gnu");
3050b57cec5SDimitry Andric     }
3060b57cec5SDimitry Andric   } else if (Triple.isOSWindows()) {
3070b57cec5SDimitry Andric     // FIXME: this is invalid for WindowsCE
3080b57cec5SDimitry Andric     setABI("aapcs");
3090b57cec5SDimitry Andric   } else {
3100b57cec5SDimitry Andric     // Select the default based on the platform.
3110b57cec5SDimitry Andric     switch (Triple.getEnvironment()) {
3120b57cec5SDimitry Andric     case llvm::Triple::Android:
3130b57cec5SDimitry Andric     case llvm::Triple::GNUEABI:
314*d686ce93SDimitry Andric     case llvm::Triple::GNUEABIT64:
3150b57cec5SDimitry Andric     case llvm::Triple::GNUEABIHF:
316*d686ce93SDimitry Andric     case llvm::Triple::GNUEABIHFT64:
3170b57cec5SDimitry Andric     case llvm::Triple::MuslEABI:
3180b57cec5SDimitry Andric     case llvm::Triple::MuslEABIHF:
31906c3fb27SDimitry Andric     case llvm::Triple::OpenHOS:
3200b57cec5SDimitry Andric       setABI("aapcs-linux");
3210b57cec5SDimitry Andric       break;
3220b57cec5SDimitry Andric     case llvm::Triple::EABIHF:
3230b57cec5SDimitry Andric     case llvm::Triple::EABI:
3240b57cec5SDimitry Andric       setABI("aapcs");
3250b57cec5SDimitry Andric       break;
3260b57cec5SDimitry Andric     case llvm::Triple::GNU:
3270b57cec5SDimitry Andric       setABI("apcs-gnu");
3280b57cec5SDimitry Andric       break;
3290b57cec5SDimitry Andric     default:
3300b57cec5SDimitry Andric       if (IsNetBSD)
3310b57cec5SDimitry Andric         setABI("apcs-gnu");
3325f757f3fSDimitry Andric       else if (IsFreeBSD || IsOpenBSD || IsHaiku || IsOHOS)
3330b57cec5SDimitry Andric         setABI("aapcs-linux");
3340b57cec5SDimitry Andric       else
3350b57cec5SDimitry Andric         setABI("aapcs");
3360b57cec5SDimitry Andric       break;
3370b57cec5SDimitry Andric     }
3380b57cec5SDimitry Andric   }
3390b57cec5SDimitry Andric 
3400b57cec5SDimitry Andric   // ARM targets default to using the ARM C++ ABI.
3410b57cec5SDimitry Andric   TheCXXABI.set(TargetCXXABI::GenericARM);
3420b57cec5SDimitry Andric 
3430b57cec5SDimitry Andric   // ARM has atomics up to 8 bytes
3440b57cec5SDimitry Andric   setAtomic();
3450b57cec5SDimitry Andric 
3460b57cec5SDimitry Andric   // Maximum alignment for ARM NEON data types should be 64-bits (AAPCS)
347a7dea167SDimitry Andric   // as well the default alignment
3485ffd83dbSDimitry Andric   if (IsAAPCS && !Triple.isAndroid())
349a7dea167SDimitry Andric     DefaultAlignForAttributeAligned = MaxVectorAlign = 64;
3500b57cec5SDimitry Andric 
3510b57cec5SDimitry Andric   // Do force alignment of members that follow zero length bitfields.  If
3520b57cec5SDimitry Andric   // the alignment of the zero-length bitfield is greater than the member
3530b57cec5SDimitry Andric   // that follows it, `bar', `bar' will be aligned as the  type of the
3540b57cec5SDimitry Andric   // zero length bitfield.
3550b57cec5SDimitry Andric   UseZeroLengthBitfieldAlignment = true;
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric   if (Triple.getOS() == llvm::Triple::Linux ||
3580b57cec5SDimitry Andric       Triple.getOS() == llvm::Triple::UnknownOS)
3590b57cec5SDimitry Andric     this->MCountName = Opts.EABIVersion == llvm::EABI::GNU
360a7dea167SDimitry Andric                            ? "llvm.arm.gnu.eabi.mcount"
3610b57cec5SDimitry Andric                            : "\01mcount";
3620b57cec5SDimitry Andric 
3630b57cec5SDimitry Andric   SoftFloatABI = llvm::is_contained(Opts.FeaturesAsWritten, "+soft-float-abi");
3640b57cec5SDimitry Andric }
3650b57cec5SDimitry Andric 
3660b57cec5SDimitry Andric StringRef ARMTargetInfo::getABI() const { return ABI; }
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric bool ARMTargetInfo::setABI(const std::string &Name) {
3690b57cec5SDimitry Andric   ABI = Name;
3700b57cec5SDimitry Andric 
3710b57cec5SDimitry Andric   // The defaults (above) are for AAPCS, check if we need to change them.
3720b57cec5SDimitry Andric   //
3730b57cec5SDimitry Andric   // FIXME: We need support for -meabi... we could just mangle it into the
3740b57cec5SDimitry Andric   // name.
3750b57cec5SDimitry Andric   if (Name == "apcs-gnu" || Name == "aapcs16") {
3760b57cec5SDimitry Andric     setABIAPCS(Name == "aapcs16");
3770b57cec5SDimitry Andric     return true;
3780b57cec5SDimitry Andric   }
3790b57cec5SDimitry Andric   if (Name == "aapcs" || Name == "aapcs-vfp" || Name == "aapcs-linux") {
3800b57cec5SDimitry Andric     setABIAAPCS();
3810b57cec5SDimitry Andric     return true;
3820b57cec5SDimitry Andric   }
3830b57cec5SDimitry Andric   return false;
3840b57cec5SDimitry Andric }
3850b57cec5SDimitry Andric 
3861fd87a68SDimitry Andric bool ARMTargetInfo::isBranchProtectionSupportedArch(StringRef Arch) const {
3871fd87a68SDimitry Andric   llvm::ARM::ArchKind CPUArch = llvm::ARM::parseCPUArch(Arch);
3881fd87a68SDimitry Andric   if (CPUArch == llvm::ARM::ArchKind::INVALID)
3891fd87a68SDimitry Andric     CPUArch = llvm::ARM::parseArch(getTriple().getArchName());
3901fd87a68SDimitry Andric 
3911fd87a68SDimitry Andric   if (CPUArch == llvm::ARM::ArchKind::INVALID)
3921fd87a68SDimitry Andric     return false;
3931fd87a68SDimitry Andric 
3941fd87a68SDimitry Andric   StringRef ArchFeature = llvm::ARM::getArchName(CPUArch);
3951fd87a68SDimitry Andric   auto a =
3961fd87a68SDimitry Andric       llvm::Triple(ArchFeature, getTriple().getVendorName(),
3971fd87a68SDimitry Andric                    getTriple().getOSName(), getTriple().getEnvironmentName());
3981fd87a68SDimitry Andric 
3991fd87a68SDimitry Andric   StringRef SubArch = llvm::ARM::getSubArch(CPUArch);
4001fd87a68SDimitry Andric   llvm::ARM::ProfileKind Profile = llvm::ARM::parseArchProfile(SubArch);
4011fd87a68SDimitry Andric   return a.isArmT32() && (Profile == llvm::ARM::ProfileKind::M);
4021fd87a68SDimitry Andric }
4031fd87a68SDimitry Andric 
4041fd87a68SDimitry Andric bool ARMTargetInfo::validateBranchProtection(StringRef Spec, StringRef Arch,
4054824e7fdSDimitry Andric                                              BranchProtectionInfo &BPI,
4064824e7fdSDimitry Andric                                              StringRef &Err) const {
4074824e7fdSDimitry Andric   llvm::ARM::ParsedBranchProtection PBP;
4084824e7fdSDimitry Andric   if (!llvm::ARM::parseBranchProtection(Spec, PBP, Err))
4094824e7fdSDimitry Andric     return false;
4104824e7fdSDimitry Andric 
4111fd87a68SDimitry Andric   if (!isBranchProtectionSupportedArch(Arch))
4121fd87a68SDimitry Andric     return false;
4131fd87a68SDimitry Andric 
4144824e7fdSDimitry Andric   BPI.SignReturnAddr =
4154824e7fdSDimitry Andric       llvm::StringSwitch<LangOptions::SignReturnAddressScopeKind>(PBP.Scope)
4164824e7fdSDimitry Andric           .Case("non-leaf", LangOptions::SignReturnAddressScopeKind::NonLeaf)
4174824e7fdSDimitry Andric           .Case("all", LangOptions::SignReturnAddressScopeKind::All)
4184824e7fdSDimitry Andric           .Default(LangOptions::SignReturnAddressScopeKind::None);
4194824e7fdSDimitry Andric 
4204824e7fdSDimitry Andric   // Don't care for the sign key, beyond issuing a warning.
4214824e7fdSDimitry Andric   if (PBP.Key == "b_key")
4224824e7fdSDimitry Andric     Err = "b-key";
4234824e7fdSDimitry Andric   BPI.SignKey = LangOptions::SignReturnAddressKeyKind::AKey;
4244824e7fdSDimitry Andric 
4254824e7fdSDimitry Andric   BPI.BranchTargetEnforcement = PBP.BranchTargetEnforcement;
426cb14a3feSDimitry Andric   BPI.BranchProtectionPAuthLR = PBP.BranchProtectionPAuthLR;
4274824e7fdSDimitry Andric   return true;
4284824e7fdSDimitry Andric }
4294824e7fdSDimitry Andric 
4300b57cec5SDimitry Andric // FIXME: This should be based on Arch attributes, not CPU names.
4310b57cec5SDimitry Andric bool ARMTargetInfo::initFeatureMap(
4320b57cec5SDimitry Andric     llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
4330b57cec5SDimitry Andric     const std::vector<std::string> &FeaturesVec) const {
4340b57cec5SDimitry Andric 
4350b57cec5SDimitry Andric   std::string ArchFeature;
4360b57cec5SDimitry Andric   std::vector<StringRef> TargetFeatures;
4370b57cec5SDimitry Andric   llvm::ARM::ArchKind Arch = llvm::ARM::parseArch(getTriple().getArchName());
4380b57cec5SDimitry Andric 
4390b57cec5SDimitry Andric   // Map the base architecture to an appropriate target feature, so we don't
4400b57cec5SDimitry Andric   // rely on the target triple.
4410b57cec5SDimitry Andric   llvm::ARM::ArchKind CPUArch = llvm::ARM::parseCPUArch(CPU);
4420b57cec5SDimitry Andric   if (CPUArch == llvm::ARM::ArchKind::INVALID)
4430b57cec5SDimitry Andric     CPUArch = Arch;
4440b57cec5SDimitry Andric   if (CPUArch != llvm::ARM::ArchKind::INVALID) {
4450b57cec5SDimitry Andric     ArchFeature = ("+" + llvm::ARM::getArchName(CPUArch)).str();
4460b57cec5SDimitry Andric     TargetFeatures.push_back(ArchFeature);
447bdd1243dSDimitry Andric 
448bdd1243dSDimitry Andric     // These features are added to allow arm_neon.h target(..) attributes to
449bdd1243dSDimitry Andric     // match with both arm and aarch64. We need to add all previous architecture
450bdd1243dSDimitry Andric     // versions, so that "8.6" also allows "8.1" functions. In case of v9.x the
451bdd1243dSDimitry Andric     // v8.x counterparts are added too. We only need these for anything > 8.0-A.
452bdd1243dSDimitry Andric     for (llvm::ARM::ArchKind I = llvm::ARM::convertV9toV8(CPUArch);
453bdd1243dSDimitry Andric          I != llvm::ARM::ArchKind::INVALID; --I)
454bdd1243dSDimitry Andric       Features[llvm::ARM::getSubArch(I)] = true;
455bdd1243dSDimitry Andric     if (CPUArch > llvm::ARM::ArchKind::ARMV8A &&
456bdd1243dSDimitry Andric         CPUArch <= llvm::ARM::ArchKind::ARMV9_3A)
457bdd1243dSDimitry Andric       for (llvm::ARM::ArchKind I = CPUArch; I != llvm::ARM::ArchKind::INVALID;
458bdd1243dSDimitry Andric            --I)
459bdd1243dSDimitry Andric         Features[llvm::ARM::getSubArch(I)] = true;
4600b57cec5SDimitry Andric   }
4610b57cec5SDimitry Andric 
4620b57cec5SDimitry Andric   // get default FPU features
46306c3fb27SDimitry Andric   llvm::ARM::FPUKind FPUKind = llvm::ARM::getDefaultFPU(CPU, Arch);
4640b57cec5SDimitry Andric   llvm::ARM::getFPUFeatures(FPUKind, TargetFeatures);
4650b57cec5SDimitry Andric 
4660b57cec5SDimitry Andric   // get default Extension features
4675ffd83dbSDimitry Andric   uint64_t Extensions = llvm::ARM::getDefaultExtensions(CPU, Arch);
4680b57cec5SDimitry Andric   llvm::ARM::getExtensionFeatures(Extensions, TargetFeatures);
4690b57cec5SDimitry Andric 
4700b57cec5SDimitry Andric   for (auto Feature : TargetFeatures)
4710b57cec5SDimitry Andric     if (Feature[0] == '+')
4720b57cec5SDimitry Andric       Features[Feature.drop_front(1)] = true;
4730b57cec5SDimitry Andric 
4740b57cec5SDimitry Andric   // Enable or disable thumb-mode explicitly per function to enable mixed
4750b57cec5SDimitry Andric   // ARM and Thumb code generation.
4760b57cec5SDimitry Andric   if (isThumb())
4770b57cec5SDimitry Andric     Features["thumb-mode"] = true;
4780b57cec5SDimitry Andric   else
4790b57cec5SDimitry Andric     Features["thumb-mode"] = false;
4800b57cec5SDimitry Andric 
4810b57cec5SDimitry Andric   // Convert user-provided arm and thumb GNU target attributes to
4820b57cec5SDimitry Andric   // [-|+]thumb-mode target features respectively.
4830b57cec5SDimitry Andric   std::vector<std::string> UpdatedFeaturesVec;
4840b57cec5SDimitry Andric   for (const auto &Feature : FeaturesVec) {
4850b57cec5SDimitry Andric     // Skip soft-float-abi; it's something we only use to initialize a bit of
4860b57cec5SDimitry Andric     // class state, and is otherwise unrecognized.
4870b57cec5SDimitry Andric     if (Feature == "+soft-float-abi")
4880b57cec5SDimitry Andric       continue;
4890b57cec5SDimitry Andric 
4900b57cec5SDimitry Andric     StringRef FixedFeature;
4910b57cec5SDimitry Andric     if (Feature == "+arm")
4920b57cec5SDimitry Andric       FixedFeature = "-thumb-mode";
4930b57cec5SDimitry Andric     else if (Feature == "+thumb")
4940b57cec5SDimitry Andric       FixedFeature = "+thumb-mode";
4950b57cec5SDimitry Andric     else
4960b57cec5SDimitry Andric       FixedFeature = Feature;
4970b57cec5SDimitry Andric     UpdatedFeaturesVec.push_back(FixedFeature.str());
4980b57cec5SDimitry Andric   }
4990b57cec5SDimitry Andric 
5000b57cec5SDimitry Andric   return TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeaturesVec);
5010b57cec5SDimitry Andric }
5020b57cec5SDimitry Andric 
5030b57cec5SDimitry Andric 
5040b57cec5SDimitry Andric bool ARMTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
5050b57cec5SDimitry Andric                                          DiagnosticsEngine &Diags) {
5060b57cec5SDimitry Andric   FPU = 0;
5070b57cec5SDimitry Andric   MVE = 0;
5080b57cec5SDimitry Andric   CRC = 0;
5090b57cec5SDimitry Andric   Crypto = 0;
510fe6060f1SDimitry Andric   SHA2 = 0;
511fe6060f1SDimitry Andric   AES = 0;
5120b57cec5SDimitry Andric   DSP = 0;
5130fca6ea1SDimitry Andric   HasUnalignedAccess = true;
5140b57cec5SDimitry Andric   SoftFloat = false;
5150b57cec5SDimitry Andric   // Note that SoftFloatABI is initialized in our constructor.
5160b57cec5SDimitry Andric   HWDiv = 0;
5170b57cec5SDimitry Andric   DotProd = 0;
5185ffd83dbSDimitry Andric   HasMatMul = 0;
5190eae32dcSDimitry Andric   HasPAC = 0;
5200eae32dcSDimitry Andric   HasBTI = 0;
5210b57cec5SDimitry Andric   HasFloat16 = true;
5225ffd83dbSDimitry Andric   ARMCDECoprocMask = 0;
5235ffd83dbSDimitry Andric   HasBFloat16 = false;
52406c3fb27SDimitry Andric   HasFullBFloat16 = false;
525349cc55cSDimitry Andric   FPRegsDisabled = false;
5260b57cec5SDimitry Andric 
5270b57cec5SDimitry Andric   // This does not diagnose illegal cases like having both
5280b57cec5SDimitry Andric   // "+vfpv2" and "+vfpv3" or having "+neon" and "-fp64".
5290b57cec5SDimitry Andric   for (const auto &Feature : Features) {
5300b57cec5SDimitry Andric     if (Feature == "+soft-float") {
5310b57cec5SDimitry Andric       SoftFloat = true;
532a7dea167SDimitry Andric     } else if (Feature == "+vfp2sp" || Feature == "+vfp2") {
5330b57cec5SDimitry Andric       FPU |= VFP2FPU;
5340b57cec5SDimitry Andric       HW_FP |= HW_FP_SP;
535a7dea167SDimitry Andric       if (Feature == "+vfp2")
5360b57cec5SDimitry Andric           HW_FP |= HW_FP_DP;
5370b57cec5SDimitry Andric     } else if (Feature == "+vfp3sp" || Feature == "+vfp3d16sp" ||
5380b57cec5SDimitry Andric                Feature == "+vfp3" || Feature == "+vfp3d16") {
5390b57cec5SDimitry Andric       FPU |= VFP3FPU;
5400b57cec5SDimitry Andric       HW_FP |= HW_FP_SP;
5410b57cec5SDimitry Andric       if (Feature == "+vfp3" || Feature == "+vfp3d16")
5420b57cec5SDimitry Andric           HW_FP |= HW_FP_DP;
5430b57cec5SDimitry Andric     } else if (Feature == "+vfp4sp" || Feature == "+vfp4d16sp" ||
5440b57cec5SDimitry Andric                Feature == "+vfp4" || Feature == "+vfp4d16") {
5450b57cec5SDimitry Andric       FPU |= VFP4FPU;
5460b57cec5SDimitry Andric       HW_FP |= HW_FP_SP | HW_FP_HP;
5470b57cec5SDimitry Andric       if (Feature == "+vfp4" || Feature == "+vfp4d16")
5480b57cec5SDimitry Andric           HW_FP |= HW_FP_DP;
5490b57cec5SDimitry Andric     } else if (Feature == "+fp-armv8sp" || Feature == "+fp-armv8d16sp" ||
5500b57cec5SDimitry Andric                Feature == "+fp-armv8" || Feature == "+fp-armv8d16") {
5510b57cec5SDimitry Andric       FPU |= FPARMV8;
5520b57cec5SDimitry Andric       HW_FP |= HW_FP_SP | HW_FP_HP;
5530b57cec5SDimitry Andric       if (Feature == "+fp-armv8" || Feature == "+fp-armv8d16")
5540b57cec5SDimitry Andric           HW_FP |= HW_FP_DP;
5550b57cec5SDimitry Andric     } else if (Feature == "+neon") {
5560b57cec5SDimitry Andric       FPU |= NeonFPU;
5570b57cec5SDimitry Andric       HW_FP |= HW_FP_SP;
5580b57cec5SDimitry Andric     } else if (Feature == "+hwdiv") {
5590b57cec5SDimitry Andric       HWDiv |= HWDivThumb;
5600b57cec5SDimitry Andric     } else if (Feature == "+hwdiv-arm") {
5610b57cec5SDimitry Andric       HWDiv |= HWDivARM;
5620b57cec5SDimitry Andric     } else if (Feature == "+crc") {
5630b57cec5SDimitry Andric       CRC = 1;
5640b57cec5SDimitry Andric     } else if (Feature == "+crypto") {
5650b57cec5SDimitry Andric       Crypto = 1;
566fe6060f1SDimitry Andric     } else if (Feature == "+sha2") {
567fe6060f1SDimitry Andric       SHA2 = 1;
568fe6060f1SDimitry Andric     } else if (Feature == "+aes") {
569fe6060f1SDimitry Andric       AES = 1;
5700b57cec5SDimitry Andric     } else if (Feature == "+dsp") {
5710b57cec5SDimitry Andric       DSP = 1;
5720b57cec5SDimitry Andric     } else if (Feature == "+fp64") {
5730b57cec5SDimitry Andric       HW_FP |= HW_FP_DP;
5740b57cec5SDimitry Andric     } else if (Feature == "+8msecext") {
5750b57cec5SDimitry Andric       if (CPUProfile != "M" || ArchVersion != 8) {
5760b57cec5SDimitry Andric         Diags.Report(diag::err_target_unsupported_mcmse) << CPU;
5770b57cec5SDimitry Andric         return false;
5780b57cec5SDimitry Andric       }
5790b57cec5SDimitry Andric     } else if (Feature == "+strict-align") {
5800fca6ea1SDimitry Andric       HasUnalignedAccess = false;
5810b57cec5SDimitry Andric     } else if (Feature == "+fp16") {
5820b57cec5SDimitry Andric       HW_FP |= HW_FP_HP;
5830b57cec5SDimitry Andric     } else if (Feature == "+fullfp16") {
5840b57cec5SDimitry Andric       HasLegalHalfType = true;
5850b57cec5SDimitry Andric     } else if (Feature == "+dotprod") {
5860b57cec5SDimitry Andric       DotProd = true;
5870b57cec5SDimitry Andric     } else if (Feature == "+mve") {
5880b57cec5SDimitry Andric       MVE |= MVE_INT;
5890b57cec5SDimitry Andric     } else if (Feature == "+mve.fp") {
5900b57cec5SDimitry Andric       HasLegalHalfType = true;
5910b57cec5SDimitry Andric       FPU |= FPARMV8;
5920b57cec5SDimitry Andric       MVE |= MVE_INT | MVE_FP;
5930b57cec5SDimitry Andric       HW_FP |= HW_FP_SP | HW_FP_HP;
5945ffd83dbSDimitry Andric     } else if (Feature == "+i8mm") {
5955ffd83dbSDimitry Andric       HasMatMul = 1;
5965ffd83dbSDimitry Andric     } else if (Feature.size() == strlen("+cdecp0") && Feature >= "+cdecp0" &&
5975ffd83dbSDimitry Andric                Feature <= "+cdecp7") {
5985ffd83dbSDimitry Andric       unsigned Coproc = Feature.back() - '0';
5995ffd83dbSDimitry Andric       ARMCDECoprocMask |= (1U << Coproc);
6005ffd83dbSDimitry Andric     } else if (Feature == "+bf16") {
6015ffd83dbSDimitry Andric       HasBFloat16 = true;
602349cc55cSDimitry Andric     } else if (Feature == "-fpregs") {
603349cc55cSDimitry Andric       FPRegsDisabled = true;
6040eae32dcSDimitry Andric     } else if (Feature == "+pacbti") {
6050eae32dcSDimitry Andric       HasPAC = 1;
6060eae32dcSDimitry Andric       HasBTI = 1;
60706c3fb27SDimitry Andric     } else if (Feature == "+fullbf16") {
60806c3fb27SDimitry Andric       HasFullBFloat16 = true;
6090b57cec5SDimitry Andric     }
6100b57cec5SDimitry Andric   }
6110b57cec5SDimitry Andric 
612bdd1243dSDimitry Andric   HalfArgsAndReturns = true;
613bdd1243dSDimitry Andric 
6140b57cec5SDimitry Andric   switch (ArchVersion) {
6150b57cec5SDimitry Andric   case 6:
6160b57cec5SDimitry Andric     if (ArchProfile == llvm::ARM::ProfileKind::M)
6170b57cec5SDimitry Andric       LDREX = 0;
6180b57cec5SDimitry Andric     else if (ArchKind == llvm::ARM::ArchKind::ARMV6K)
6190b57cec5SDimitry Andric       LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
6200b57cec5SDimitry Andric     else
6210b57cec5SDimitry Andric       LDREX = LDREX_W;
6220b57cec5SDimitry Andric     break;
6230b57cec5SDimitry Andric   case 7:
6240b57cec5SDimitry Andric     if (ArchProfile == llvm::ARM::ProfileKind::M)
6250b57cec5SDimitry Andric       LDREX = LDREX_W | LDREX_H | LDREX_B;
6260b57cec5SDimitry Andric     else
6270b57cec5SDimitry Andric       LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
6280b57cec5SDimitry Andric     break;
6290b57cec5SDimitry Andric   case 8:
630349cc55cSDimitry Andric   case 9:
6310b57cec5SDimitry Andric     LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
6320b57cec5SDimitry Andric   }
6330b57cec5SDimitry Andric 
6340b57cec5SDimitry Andric   if (!(FPU & NeonFPU) && FPMath == FP_Neon) {
6350b57cec5SDimitry Andric     Diags.Report(diag::err_target_unsupported_fpmath) << "neon";
6360b57cec5SDimitry Andric     return false;
6370b57cec5SDimitry Andric   }
6380b57cec5SDimitry Andric 
6390b57cec5SDimitry Andric   if (FPMath == FP_Neon)
6400b57cec5SDimitry Andric     Features.push_back("+neonfp");
6410b57cec5SDimitry Andric   else if (FPMath == FP_VFP)
6420b57cec5SDimitry Andric     Features.push_back("-neonfp");
6430b57cec5SDimitry Andric 
6440b57cec5SDimitry Andric   return true;
6450b57cec5SDimitry Andric }
6460b57cec5SDimitry Andric 
6470b57cec5SDimitry Andric bool ARMTargetInfo::hasFeature(StringRef Feature) const {
6480b57cec5SDimitry Andric   return llvm::StringSwitch<bool>(Feature)
6490b57cec5SDimitry Andric       .Case("arm", true)
6500b57cec5SDimitry Andric       .Case("aarch32", true)
6510b57cec5SDimitry Andric       .Case("softfloat", SoftFloat)
6520b57cec5SDimitry Andric       .Case("thumb", isThumb())
6530b57cec5SDimitry Andric       .Case("neon", (FPU & NeonFPU) && !SoftFloat)
6540b57cec5SDimitry Andric       .Case("vfp", FPU && !SoftFloat)
6550b57cec5SDimitry Andric       .Case("hwdiv", HWDiv & HWDivThumb)
6560b57cec5SDimitry Andric       .Case("hwdiv-arm", HWDiv & HWDivARM)
6570b57cec5SDimitry Andric       .Case("mve", hasMVE())
6580b57cec5SDimitry Andric       .Default(false);
6590b57cec5SDimitry Andric }
6600b57cec5SDimitry Andric 
6615ffd83dbSDimitry Andric bool ARMTargetInfo::hasBFloat16Type() const {
662bdd1243dSDimitry Andric   // The __bf16 type is generally available so long as we have any fp registers.
663bdd1243dSDimitry Andric   return HasBFloat16 || (FPU && !SoftFloat);
6645ffd83dbSDimitry Andric }
6655ffd83dbSDimitry Andric 
6660b57cec5SDimitry Andric bool ARMTargetInfo::isValidCPUName(StringRef Name) const {
6670b57cec5SDimitry Andric   return Name == "generic" ||
6680b57cec5SDimitry Andric          llvm::ARM::parseCPUArch(Name) != llvm::ARM::ArchKind::INVALID;
6690b57cec5SDimitry Andric }
6700b57cec5SDimitry Andric 
6710b57cec5SDimitry Andric void ARMTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const {
6720b57cec5SDimitry Andric   llvm::ARM::fillValidCPUArchList(Values);
6730b57cec5SDimitry Andric }
6740b57cec5SDimitry Andric 
6750b57cec5SDimitry Andric bool ARMTargetInfo::setCPU(const std::string &Name) {
6760b57cec5SDimitry Andric   if (Name != "generic")
6770b57cec5SDimitry Andric     setArchInfo(llvm::ARM::parseCPUArch(Name));
6780b57cec5SDimitry Andric 
6790b57cec5SDimitry Andric   if (ArchKind == llvm::ARM::ArchKind::INVALID)
6800b57cec5SDimitry Andric     return false;
6810b57cec5SDimitry Andric   setAtomic();
6820b57cec5SDimitry Andric   CPU = Name;
6830b57cec5SDimitry Andric   return true;
6840b57cec5SDimitry Andric }
6850b57cec5SDimitry Andric 
6860b57cec5SDimitry Andric bool ARMTargetInfo::setFPMath(StringRef Name) {
6870b57cec5SDimitry Andric   if (Name == "neon") {
6880b57cec5SDimitry Andric     FPMath = FP_Neon;
6890b57cec5SDimitry Andric     return true;
6900b57cec5SDimitry Andric   } else if (Name == "vfp" || Name == "vfp2" || Name == "vfp3" ||
6910b57cec5SDimitry Andric              Name == "vfp4") {
6920b57cec5SDimitry Andric     FPMath = FP_VFP;
6930b57cec5SDimitry Andric     return true;
6940b57cec5SDimitry Andric   }
6950b57cec5SDimitry Andric   return false;
6960b57cec5SDimitry Andric }
6970b57cec5SDimitry Andric 
6980b57cec5SDimitry Andric void ARMTargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,
6990b57cec5SDimitry Andric                                             MacroBuilder &Builder) const {
7000b57cec5SDimitry Andric   Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
7010b57cec5SDimitry Andric }
7020b57cec5SDimitry Andric 
7030b57cec5SDimitry Andric void ARMTargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts,
7040b57cec5SDimitry Andric                                             MacroBuilder &Builder) const {
7050b57cec5SDimitry Andric   // Also include the ARMv8.1-A defines
7060b57cec5SDimitry Andric   getTargetDefinesARMV81A(Opts, Builder);
7070b57cec5SDimitry Andric }
7080b57cec5SDimitry Andric 
709480093f4SDimitry Andric void ARMTargetInfo::getTargetDefinesARMV83A(const LangOptions &Opts,
710480093f4SDimitry Andric                                             MacroBuilder &Builder) const {
711480093f4SDimitry Andric   // Also include the ARMv8.2-A defines
712480093f4SDimitry Andric   Builder.defineMacro("__ARM_FEATURE_COMPLEX", "1");
713480093f4SDimitry Andric   getTargetDefinesARMV82A(Opts, Builder);
714480093f4SDimitry Andric }
715480093f4SDimitry Andric 
7160b57cec5SDimitry Andric void ARMTargetInfo::getTargetDefines(const LangOptions &Opts,
7170b57cec5SDimitry Andric                                      MacroBuilder &Builder) const {
7180b57cec5SDimitry Andric   // Target identification.
7190b57cec5SDimitry Andric   Builder.defineMacro("__arm");
7200b57cec5SDimitry Andric   Builder.defineMacro("__arm__");
7210b57cec5SDimitry Andric   // For bare-metal none-eabi.
7220b57cec5SDimitry Andric   if (getTriple().getOS() == llvm::Triple::UnknownOS &&
7230b57cec5SDimitry Andric       (getTriple().getEnvironment() == llvm::Triple::EABI ||
72406c3fb27SDimitry Andric        getTriple().getEnvironment() == llvm::Triple::EABIHF) &&
72506c3fb27SDimitry Andric       Opts.CPlusPlus) {
726bdd1243dSDimitry Andric     Builder.defineMacro("_GNU_SOURCE");
727bdd1243dSDimitry Andric   }
7280b57cec5SDimitry Andric 
7290b57cec5SDimitry Andric   // Target properties.
7300b57cec5SDimitry Andric   Builder.defineMacro("__REGISTER_PREFIX__", "");
7310b57cec5SDimitry Andric 
7320b57cec5SDimitry Andric   // Unfortunately, __ARM_ARCH_7K__ is now more of an ABI descriptor. The CPU
7330b57cec5SDimitry Andric   // happens to be Cortex-A7 though, so it should still get __ARM_ARCH_7A__.
7340b57cec5SDimitry Andric   if (getTriple().isWatchABI())
7350b57cec5SDimitry Andric     Builder.defineMacro("__ARM_ARCH_7K__", "2");
7360b57cec5SDimitry Andric 
7370b57cec5SDimitry Andric   if (!CPUAttr.empty())
7380b57cec5SDimitry Andric     Builder.defineMacro("__ARM_ARCH_" + CPUAttr + "__");
7390b57cec5SDimitry Andric 
7400b57cec5SDimitry Andric   // ACLE 6.4.1 ARM/Thumb instruction set architecture
7410b57cec5SDimitry Andric   // __ARM_ARCH is defined as an integer value indicating the current ARM ISA
7420b57cec5SDimitry Andric   Builder.defineMacro("__ARM_ARCH", Twine(ArchVersion));
7430b57cec5SDimitry Andric 
7440b57cec5SDimitry Andric   if (ArchVersion >= 8) {
7450b57cec5SDimitry Andric     // ACLE 6.5.7 Crypto Extension
746fe6060f1SDimitry Andric     // The __ARM_FEATURE_CRYPTO is deprecated in favor of finer grained
747fe6060f1SDimitry Andric     // feature macros for AES and SHA2
748fe6060f1SDimitry Andric     if (SHA2 && AES)
7490b57cec5SDimitry Andric       Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
750fe6060f1SDimitry Andric     if (SHA2)
751fe6060f1SDimitry Andric       Builder.defineMacro("__ARM_FEATURE_SHA2", "1");
752fe6060f1SDimitry Andric     if (AES)
753fe6060f1SDimitry Andric       Builder.defineMacro("__ARM_FEATURE_AES", "1");
7540b57cec5SDimitry Andric     // ACLE 6.5.8 CRC32 Extension
7550b57cec5SDimitry Andric     if (CRC)
7560b57cec5SDimitry Andric       Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
7570b57cec5SDimitry Andric     // ACLE 6.5.10 Numeric Maximum and Minimum
7580b57cec5SDimitry Andric     Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");
7590b57cec5SDimitry Andric     // ACLE 6.5.9 Directed Rounding
7600b57cec5SDimitry Andric     Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");
7610b57cec5SDimitry Andric   }
7620b57cec5SDimitry Andric 
7630b57cec5SDimitry Andric   // __ARM_ARCH_ISA_ARM is defined to 1 if the core supports the ARM ISA.  It
7640b57cec5SDimitry Andric   // is not defined for the M-profile.
7650b57cec5SDimitry Andric   // NOTE that the default profile is assumed to be 'A'
7660b57cec5SDimitry Andric   if (CPUProfile.empty() || ArchProfile != llvm::ARM::ProfileKind::M)
7670b57cec5SDimitry Andric     Builder.defineMacro("__ARM_ARCH_ISA_ARM", "1");
7680b57cec5SDimitry Andric 
7690b57cec5SDimitry Andric   // __ARM_ARCH_ISA_THUMB is defined to 1 if the core supports the original
7700b57cec5SDimitry Andric   // Thumb ISA (including v6-M and v8-M Baseline).  It is set to 2 if the
7710b57cec5SDimitry Andric   // core supports the Thumb-2 ISA as found in the v6T2 architecture and all
7720b57cec5SDimitry Andric   // v7 and v8 architectures excluding v8-M Baseline.
7730b57cec5SDimitry Andric   if (supportsThumb2())
7740b57cec5SDimitry Andric     Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "2");
7750b57cec5SDimitry Andric   else if (supportsThumb())
7760b57cec5SDimitry Andric     Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "1");
7770b57cec5SDimitry Andric 
7780b57cec5SDimitry Andric   // __ARM_32BIT_STATE is defined to 1 if code is being generated for a 32-bit
7790b57cec5SDimitry Andric   // instruction set such as ARM or Thumb.
7800b57cec5SDimitry Andric   Builder.defineMacro("__ARM_32BIT_STATE", "1");
7810b57cec5SDimitry Andric 
7820b57cec5SDimitry Andric   // ACLE 6.4.2 Architectural Profile (A, R, M or pre-Cortex)
7830b57cec5SDimitry Andric 
7840b57cec5SDimitry Andric   // __ARM_ARCH_PROFILE is defined as 'A', 'R', 'M' or 'S', or unset.
7850b57cec5SDimitry Andric   if (!CPUProfile.empty())
7860b57cec5SDimitry Andric     Builder.defineMacro("__ARM_ARCH_PROFILE", "'" + CPUProfile + "'");
7870b57cec5SDimitry Andric 
7880b57cec5SDimitry Andric   // ACLE 6.4.3 Unaligned access supported in hardware
7890fca6ea1SDimitry Andric   if (HasUnalignedAccess)
7900b57cec5SDimitry Andric     Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
7910b57cec5SDimitry Andric 
7920b57cec5SDimitry Andric   // ACLE 6.4.4 LDREX/STREX
7930b57cec5SDimitry Andric   if (LDREX)
7940b57cec5SDimitry Andric     Builder.defineMacro("__ARM_FEATURE_LDREX", "0x" + Twine::utohexstr(LDREX));
7950b57cec5SDimitry Andric 
7960b57cec5SDimitry Andric   // ACLE 6.4.5 CLZ
7970b57cec5SDimitry Andric   if (ArchVersion == 5 || (ArchVersion == 6 && CPUProfile != "M") ||
7980b57cec5SDimitry Andric       ArchVersion > 6)
7990b57cec5SDimitry Andric     Builder.defineMacro("__ARM_FEATURE_CLZ", "1");
8000b57cec5SDimitry Andric 
8010b57cec5SDimitry Andric   // ACLE 6.5.1 Hardware Floating Point
8020b57cec5SDimitry Andric   if (HW_FP)
8030b57cec5SDimitry Andric     Builder.defineMacro("__ARM_FP", "0x" + Twine::utohexstr(HW_FP));
8040b57cec5SDimitry Andric 
8050b57cec5SDimitry Andric   // ACLE predefines.
8060b57cec5SDimitry Andric   Builder.defineMacro("__ARM_ACLE", "200");
8070b57cec5SDimitry Andric 
8080b57cec5SDimitry Andric   // FP16 support (we currently only support IEEE format).
8090b57cec5SDimitry Andric   Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
8100b57cec5SDimitry Andric   Builder.defineMacro("__ARM_FP16_ARGS", "1");
8110b57cec5SDimitry Andric 
8120b57cec5SDimitry Andric   // ACLE 6.5.3 Fused multiply-accumulate (FMA)
8130b57cec5SDimitry Andric   if (ArchVersion >= 7 && (FPU & VFP4FPU))
8140b57cec5SDimitry Andric     Builder.defineMacro("__ARM_FEATURE_FMA", "1");
8150b57cec5SDimitry Andric 
8160b57cec5SDimitry Andric   // Subtarget options.
8170b57cec5SDimitry Andric 
8180b57cec5SDimitry Andric   // FIXME: It's more complicated than this and we don't really support
8190b57cec5SDimitry Andric   // interworking.
8200b57cec5SDimitry Andric   // Windows on ARM does not "support" interworking
8210b57cec5SDimitry Andric   if (5 <= ArchVersion && ArchVersion <= 8 && !getTriple().isOSWindows())
8220b57cec5SDimitry Andric     Builder.defineMacro("__THUMB_INTERWORK__");
8230b57cec5SDimitry Andric 
8240b57cec5SDimitry Andric   if (ABI == "aapcs" || ABI == "aapcs-linux" || ABI == "aapcs-vfp") {
8250b57cec5SDimitry Andric     // Embedded targets on Darwin follow AAPCS, but not EABI.
8260b57cec5SDimitry Andric     // Windows on ARM follows AAPCS VFP, but does not conform to EABI.
8270b57cec5SDimitry Andric     if (!getTriple().isOSBinFormatMachO() && !getTriple().isOSWindows())
8280b57cec5SDimitry Andric       Builder.defineMacro("__ARM_EABI__");
8290b57cec5SDimitry Andric     Builder.defineMacro("__ARM_PCS", "1");
8300b57cec5SDimitry Andric   }
8310b57cec5SDimitry Andric 
8320b57cec5SDimitry Andric   if ((!SoftFloat && !SoftFloatABI) || ABI == "aapcs-vfp" || ABI == "aapcs16")
8330b57cec5SDimitry Andric     Builder.defineMacro("__ARM_PCS_VFP", "1");
8340b57cec5SDimitry Andric 
835bdd1243dSDimitry Andric   if (SoftFloat || (SoftFloatABI && !FPU))
8360b57cec5SDimitry Andric     Builder.defineMacro("__SOFTFP__");
8370b57cec5SDimitry Andric 
8380b57cec5SDimitry Andric   // ACLE position independent code macros.
8390b57cec5SDimitry Andric   if (Opts.ROPI)
8400b57cec5SDimitry Andric     Builder.defineMacro("__ARM_ROPI", "1");
8410b57cec5SDimitry Andric   if (Opts.RWPI)
8420b57cec5SDimitry Andric     Builder.defineMacro("__ARM_RWPI", "1");
8430b57cec5SDimitry Andric 
8441db9f3b2SDimitry Andric   // Macros for enabling co-proc intrinsics
8451db9f3b2SDimitry Andric   uint64_t FeatureCoprocBF = 0;
8461db9f3b2SDimitry Andric   switch (ArchKind) {
8471db9f3b2SDimitry Andric   default:
8481db9f3b2SDimitry Andric     break;
8491db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV4:
8501db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV4T:
8511db9f3b2SDimitry Andric     // Filter __arm_ldcl and __arm_stcl in acle.h
8521db9f3b2SDimitry Andric     FeatureCoprocBF = isThumb() ? 0 : FEATURE_COPROC_B1;
8531db9f3b2SDimitry Andric     break;
8541db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV5T:
8551db9f3b2SDimitry Andric     FeatureCoprocBF = isThumb() ? 0 : FEATURE_COPROC_B1 | FEATURE_COPROC_B2;
8561db9f3b2SDimitry Andric     break;
8571db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV5TE:
8581db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV5TEJ:
8591db9f3b2SDimitry Andric     if (!isThumb())
8601db9f3b2SDimitry Andric       FeatureCoprocBF =
8611db9f3b2SDimitry Andric           FEATURE_COPROC_B1 | FEATURE_COPROC_B2 | FEATURE_COPROC_B3;
8621db9f3b2SDimitry Andric     break;
8631db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV6:
8641db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV6K:
8651db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV6KZ:
8661db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV6T2:
8671db9f3b2SDimitry Andric     if (!isThumb() || ArchKind == llvm::ARM::ArchKind::ARMV6T2)
8681db9f3b2SDimitry Andric       FeatureCoprocBF = FEATURE_COPROC_B1 | FEATURE_COPROC_B2 |
8691db9f3b2SDimitry Andric                         FEATURE_COPROC_B3 | FEATURE_COPROC_B4;
8701db9f3b2SDimitry Andric     break;
8711db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV7A:
8721db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV7R:
8731db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV7M:
8741db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV7S:
8751db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV7EM:
8761db9f3b2SDimitry Andric     FeatureCoprocBF = FEATURE_COPROC_B1 | FEATURE_COPROC_B2 |
8771db9f3b2SDimitry Andric                       FEATURE_COPROC_B3 | FEATURE_COPROC_B4;
8781db9f3b2SDimitry Andric     break;
8791db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV8A:
8801db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV8R:
8811db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV8_1A:
8821db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV8_2A:
8831db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV8_3A:
8841db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV8_4A:
8851db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV8_5A:
8861db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV8_6A:
8871db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV8_7A:
8881db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV8_8A:
8891db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV8_9A:
8901db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV9A:
8911db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV9_1A:
8921db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV9_2A:
8931db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV9_3A:
8941db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV9_4A:
8957a6dacacSDimitry Andric   case llvm::ARM::ArchKind::ARMV9_5A:
8961db9f3b2SDimitry Andric     // Filter __arm_cdp, __arm_ldcl, __arm_stcl in arm_acle.h
8971db9f3b2SDimitry Andric     FeatureCoprocBF = FEATURE_COPROC_B1 | FEATURE_COPROC_B3;
8981db9f3b2SDimitry Andric     break;
8991db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV8MMainline:
9001db9f3b2SDimitry Andric   case llvm::ARM::ArchKind::ARMV8_1MMainline:
9011db9f3b2SDimitry Andric     FeatureCoprocBF = FEATURE_COPROC_B1 | FEATURE_COPROC_B2 |
9021db9f3b2SDimitry Andric                       FEATURE_COPROC_B3 | FEATURE_COPROC_B4;
9031db9f3b2SDimitry Andric     break;
9041db9f3b2SDimitry Andric   }
9051db9f3b2SDimitry Andric   Builder.defineMacro("__ARM_FEATURE_COPROC",
9061db9f3b2SDimitry Andric                       "0x" + Twine::utohexstr(FeatureCoprocBF));
9071db9f3b2SDimitry Andric 
9080b57cec5SDimitry Andric   if (ArchKind == llvm::ARM::ArchKind::XSCALE)
9090b57cec5SDimitry Andric     Builder.defineMacro("__XSCALE__");
9100b57cec5SDimitry Andric 
9110b57cec5SDimitry Andric   if (isThumb()) {
9120b57cec5SDimitry Andric     Builder.defineMacro("__THUMBEL__");
9130b57cec5SDimitry Andric     Builder.defineMacro("__thumb__");
9140b57cec5SDimitry Andric     if (supportsThumb2())
9150b57cec5SDimitry Andric       Builder.defineMacro("__thumb2__");
9160b57cec5SDimitry Andric   }
9170b57cec5SDimitry Andric 
9180b57cec5SDimitry Andric   // ACLE 6.4.9 32-bit SIMD instructions
9190b57cec5SDimitry Andric   if ((CPUProfile != "M" && ArchVersion >= 6) || (CPUProfile == "M" && DSP))
9200b57cec5SDimitry Andric     Builder.defineMacro("__ARM_FEATURE_SIMD32", "1");
9210b57cec5SDimitry Andric 
9220b57cec5SDimitry Andric   // ACLE 6.4.10 Hardware Integer Divide
9230b57cec5SDimitry Andric   if (((HWDiv & HWDivThumb) && isThumb()) ||
9240b57cec5SDimitry Andric       ((HWDiv & HWDivARM) && !isThumb())) {
9250b57cec5SDimitry Andric     Builder.defineMacro("__ARM_FEATURE_IDIV", "1");
9260b57cec5SDimitry Andric     Builder.defineMacro("__ARM_ARCH_EXT_IDIV__", "1");
9270b57cec5SDimitry Andric   }
9280b57cec5SDimitry Andric 
9290b57cec5SDimitry Andric   // Note, this is always on in gcc, even though it doesn't make sense.
9300b57cec5SDimitry Andric   Builder.defineMacro("__APCS_32__");
9310b57cec5SDimitry Andric 
932fe6060f1SDimitry Andric   // __VFP_FP__ means that the floating-point format is VFP, not that a hardware
933fe6060f1SDimitry Andric   // FPU is present. Moreover, the VFP format is the only one supported by
934fe6060f1SDimitry Andric   // clang. For these reasons, this macro is always defined.
9350b57cec5SDimitry Andric   Builder.defineMacro("__VFP_FP__");
936fe6060f1SDimitry Andric 
937fe6060f1SDimitry Andric   if (FPUModeIsVFP((FPUMode)FPU)) {
9380b57cec5SDimitry Andric     if (FPU & VFP2FPU)
9390b57cec5SDimitry Andric       Builder.defineMacro("__ARM_VFPV2__");
9400b57cec5SDimitry Andric     if (FPU & VFP3FPU)
9410b57cec5SDimitry Andric       Builder.defineMacro("__ARM_VFPV3__");
9420b57cec5SDimitry Andric     if (FPU & VFP4FPU)
9430b57cec5SDimitry Andric       Builder.defineMacro("__ARM_VFPV4__");
9440b57cec5SDimitry Andric     if (FPU & FPARMV8)
9450b57cec5SDimitry Andric       Builder.defineMacro("__ARM_FPV5__");
9460b57cec5SDimitry Andric   }
9470b57cec5SDimitry Andric 
9480b57cec5SDimitry Andric   // This only gets set when Neon instructions are actually available, unlike
9490b57cec5SDimitry Andric   // the VFP define, hence the soft float and arch check. This is subtly
9500b57cec5SDimitry Andric   // different from gcc, we follow the intent which was that it should be set
9510b57cec5SDimitry Andric   // when Neon instructions are actually available.
9520b57cec5SDimitry Andric   if ((FPU & NeonFPU) && !SoftFloat && ArchVersion >= 7) {
9530b57cec5SDimitry Andric     Builder.defineMacro("__ARM_NEON", "1");
9540b57cec5SDimitry Andric     Builder.defineMacro("__ARM_NEON__");
9550b57cec5SDimitry Andric     // current AArch32 NEON implementations do not support double-precision
9560b57cec5SDimitry Andric     // floating-point even when it is present in VFP.
9570b57cec5SDimitry Andric     Builder.defineMacro("__ARM_NEON_FP",
9580b57cec5SDimitry Andric                         "0x" + Twine::utohexstr(HW_FP & ~HW_FP_DP));
9590b57cec5SDimitry Andric   }
9600b57cec5SDimitry Andric 
9610b57cec5SDimitry Andric   if (hasMVE()) {
9620b57cec5SDimitry Andric     Builder.defineMacro("__ARM_FEATURE_MVE", hasMVEFloat() ? "3" : "1");
9630b57cec5SDimitry Andric   }
9640b57cec5SDimitry Andric 
9655ffd83dbSDimitry Andric   if (hasCDE()) {
9665ffd83dbSDimitry Andric     Builder.defineMacro("__ARM_FEATURE_CDE", "1");
9675ffd83dbSDimitry Andric     Builder.defineMacro("__ARM_FEATURE_CDE_COPROC",
9685ffd83dbSDimitry Andric                         "0x" + Twine::utohexstr(getARMCDECoprocMask()));
9695ffd83dbSDimitry Andric   }
9705ffd83dbSDimitry Andric 
9710b57cec5SDimitry Andric   Builder.defineMacro("__ARM_SIZEOF_WCHAR_T",
9720b57cec5SDimitry Andric                       Twine(Opts.WCharSize ? Opts.WCharSize : 4));
9730b57cec5SDimitry Andric 
9740b57cec5SDimitry Andric   Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4");
9750b57cec5SDimitry Andric 
9760b57cec5SDimitry Andric   // CMSE
9770b57cec5SDimitry Andric   if (ArchVersion == 8 && ArchProfile == llvm::ARM::ProfileKind::M)
9780b57cec5SDimitry Andric     Builder.defineMacro("__ARM_FEATURE_CMSE", Opts.Cmse ? "3" : "1");
9790b57cec5SDimitry Andric 
9800b57cec5SDimitry Andric   if (ArchVersion >= 6 && CPUAttr != "6M" && CPUAttr != "8M_BASE") {
9810b57cec5SDimitry Andric     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
9820b57cec5SDimitry Andric     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
9830b57cec5SDimitry Andric     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
9840b57cec5SDimitry Andric     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
9850b57cec5SDimitry Andric   }
9860b57cec5SDimitry Andric 
9870b57cec5SDimitry Andric   // ACLE 6.4.7 DSP instructions
9880b57cec5SDimitry Andric   if (DSP) {
9890b57cec5SDimitry Andric     Builder.defineMacro("__ARM_FEATURE_DSP", "1");
9900b57cec5SDimitry Andric   }
9910b57cec5SDimitry Andric 
9920b57cec5SDimitry Andric   // ACLE 6.4.8 Saturation instructions
9930b57cec5SDimitry Andric   bool SAT = false;
9940b57cec5SDimitry Andric   if ((ArchVersion == 6 && CPUProfile != "M") || ArchVersion > 6) {
9950b57cec5SDimitry Andric     Builder.defineMacro("__ARM_FEATURE_SAT", "1");
9960b57cec5SDimitry Andric     SAT = true;
9970b57cec5SDimitry Andric   }
9980b57cec5SDimitry Andric 
9990b57cec5SDimitry Andric   // ACLE 6.4.6 Q (saturation) flag
10000b57cec5SDimitry Andric   if (DSP || SAT)
10010b57cec5SDimitry Andric     Builder.defineMacro("__ARM_FEATURE_QBIT", "1");
10020b57cec5SDimitry Andric 
10030b57cec5SDimitry Andric   if (Opts.UnsafeFPMath)
10040b57cec5SDimitry Andric     Builder.defineMacro("__ARM_FP_FAST", "1");
10050b57cec5SDimitry Andric 
10060b57cec5SDimitry Andric   // Armv8.2-A FP16 vector intrinsic
10070b57cec5SDimitry Andric   if ((FPU & NeonFPU) && HasLegalHalfType)
10080b57cec5SDimitry Andric     Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1");
10090b57cec5SDimitry Andric 
10100b57cec5SDimitry Andric   // Armv8.2-A FP16 scalar intrinsics
10110b57cec5SDimitry Andric   if (HasLegalHalfType)
10120b57cec5SDimitry Andric     Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1");
10130b57cec5SDimitry Andric 
10140b57cec5SDimitry Andric   // Armv8.2-A dot product intrinsics
10150b57cec5SDimitry Andric   if (DotProd)
10160b57cec5SDimitry Andric     Builder.defineMacro("__ARM_FEATURE_DOTPROD", "1");
10170b57cec5SDimitry Andric 
10185ffd83dbSDimitry Andric   if (HasMatMul)
10195ffd83dbSDimitry Andric     Builder.defineMacro("__ARM_FEATURE_MATMUL_INT8", "1");
10205ffd83dbSDimitry Andric 
10210eae32dcSDimitry Andric   if (HasPAC)
10220eae32dcSDimitry Andric     Builder.defineMacro("__ARM_FEATURE_PAUTH", "1");
10230eae32dcSDimitry Andric 
10240eae32dcSDimitry Andric   if (HasBTI)
10250eae32dcSDimitry Andric     Builder.defineMacro("__ARM_FEATURE_BTI", "1");
10260eae32dcSDimitry Andric 
10275ffd83dbSDimitry Andric   if (HasBFloat16) {
10285ffd83dbSDimitry Andric     Builder.defineMacro("__ARM_FEATURE_BF16", "1");
10295ffd83dbSDimitry Andric     Builder.defineMacro("__ARM_FEATURE_BF16_VECTOR_ARITHMETIC", "1");
10305ffd83dbSDimitry Andric     Builder.defineMacro("__ARM_BF16_FORMAT_ALTERNATIVE", "1");
10315ffd83dbSDimitry Andric   }
10325ffd83dbSDimitry Andric 
10334824e7fdSDimitry Andric   if (Opts.BranchTargetEnforcement)
10344824e7fdSDimitry Andric     Builder.defineMacro("__ARM_FEATURE_BTI_DEFAULT", "1");
10354824e7fdSDimitry Andric 
10364824e7fdSDimitry Andric   if (Opts.hasSignReturnAddress()) {
10370eae32dcSDimitry Andric     unsigned Value = 1;
10384824e7fdSDimitry Andric     if (Opts.isSignReturnAddressScopeAll())
10394824e7fdSDimitry Andric       Value |= 1 << 2;
10404824e7fdSDimitry Andric     Builder.defineMacro("__ARM_FEATURE_PAC_DEFAULT", Twine(Value));
10414824e7fdSDimitry Andric   }
10424824e7fdSDimitry Andric 
10430b57cec5SDimitry Andric   switch (ArchKind) {
10440b57cec5SDimitry Andric   default:
10450b57cec5SDimitry Andric     break;
10460b57cec5SDimitry Andric   case llvm::ARM::ArchKind::ARMV8_1A:
10470b57cec5SDimitry Andric     getTargetDefinesARMV81A(Opts, Builder);
10480b57cec5SDimitry Andric     break;
10490b57cec5SDimitry Andric   case llvm::ARM::ArchKind::ARMV8_2A:
10500b57cec5SDimitry Andric     getTargetDefinesARMV82A(Opts, Builder);
10510b57cec5SDimitry Andric     break;
1052480093f4SDimitry Andric   case llvm::ARM::ArchKind::ARMV8_3A:
1053480093f4SDimitry Andric   case llvm::ARM::ArchKind::ARMV8_4A:
1054480093f4SDimitry Andric   case llvm::ARM::ArchKind::ARMV8_5A:
10555ffd83dbSDimitry Andric   case llvm::ARM::ArchKind::ARMV8_6A:
105681ad6265SDimitry Andric   case llvm::ARM::ArchKind::ARMV8_7A:
105704eeddc0SDimitry Andric   case llvm::ARM::ArchKind::ARMV8_8A:
1058bdd1243dSDimitry Andric   case llvm::ARM::ArchKind::ARMV8_9A:
1059349cc55cSDimitry Andric   case llvm::ARM::ArchKind::ARMV9A:
1060349cc55cSDimitry Andric   case llvm::ARM::ArchKind::ARMV9_1A:
1061349cc55cSDimitry Andric   case llvm::ARM::ArchKind::ARMV9_2A:
106204eeddc0SDimitry Andric   case llvm::ARM::ArchKind::ARMV9_3A:
1063bdd1243dSDimitry Andric   case llvm::ARM::ArchKind::ARMV9_4A:
10647a6dacacSDimitry Andric   case llvm::ARM::ArchKind::ARMV9_5A:
1065480093f4SDimitry Andric     getTargetDefinesARMV83A(Opts, Builder);
1066480093f4SDimitry Andric     break;
10670b57cec5SDimitry Andric   }
10680b57cec5SDimitry Andric }
10690b57cec5SDimitry Andric 
1070bdd1243dSDimitry Andric static constexpr Builtin::Info BuiltinInfo[] = {
10710b57cec5SDimitry Andric #define BUILTIN(ID, TYPE, ATTRS)                                               \
1072bdd1243dSDimitry Andric   {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
10730b57cec5SDimitry Andric #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER)                                    \
1074bdd1243dSDimitry Andric   {#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, ALL_LANGUAGES},
1075bdd1243dSDimitry Andric #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE)                               \
1076bdd1243dSDimitry Andric   {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
10770b57cec5SDimitry Andric #include "clang/Basic/BuiltinsNEON.def"
10780b57cec5SDimitry Andric 
10790b57cec5SDimitry Andric #define BUILTIN(ID, TYPE, ATTRS)                                               \
1080bdd1243dSDimitry Andric   {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
10810b57cec5SDimitry Andric #define LANGBUILTIN(ID, TYPE, ATTRS, LANG)                                     \
1082bdd1243dSDimitry Andric   {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, LANG},
10830b57cec5SDimitry Andric #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER)                                    \
1084bdd1243dSDimitry Andric   {#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, ALL_LANGUAGES},
10858792c038SDimitry Andric #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE)                               \
1086bdd1243dSDimitry Andric   {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
10870b57cec5SDimitry Andric #define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE)         \
1088bdd1243dSDimitry Andric   {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::HEADER, LANGS},
10890b57cec5SDimitry Andric #include "clang/Basic/BuiltinsARM.def"
10900b57cec5SDimitry Andric };
10910b57cec5SDimitry Andric 
10920b57cec5SDimitry Andric ArrayRef<Builtin::Info> ARMTargetInfo::getTargetBuiltins() const {
1093bdd1243dSDimitry Andric   return llvm::ArrayRef(BuiltinInfo,
1094bdd1243dSDimitry Andric                         clang::ARM::LastTSBuiltin - Builtin::FirstTSBuiltin);
10950b57cec5SDimitry Andric }
10960b57cec5SDimitry Andric 
10970b57cec5SDimitry Andric bool ARMTargetInfo::isCLZForZeroUndef() const { return false; }
10980b57cec5SDimitry Andric TargetInfo::BuiltinVaListKind ARMTargetInfo::getBuiltinVaListKind() const {
10990b57cec5SDimitry Andric   return IsAAPCS
11000b57cec5SDimitry Andric              ? AAPCSABIBuiltinVaList
11010b57cec5SDimitry Andric              : (getTriple().isWatchABI() ? TargetInfo::CharPtrBuiltinVaList
11020b57cec5SDimitry Andric                                          : TargetInfo::VoidPtrBuiltinVaList);
11030b57cec5SDimitry Andric }
11040b57cec5SDimitry Andric 
11050b57cec5SDimitry Andric const char *const ARMTargetInfo::GCCRegNames[] = {
11060b57cec5SDimitry Andric     // Integer registers
11070b57cec5SDimitry Andric     "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",
11080b57cec5SDimitry Andric     "r12", "sp", "lr", "pc",
11090b57cec5SDimitry Andric 
11100b57cec5SDimitry Andric     // Float registers
11110b57cec5SDimitry Andric     "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
11120b57cec5SDimitry Andric     "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
11130b57cec5SDimitry Andric     "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
11140b57cec5SDimitry Andric 
11150b57cec5SDimitry Andric     // Double registers
11160b57cec5SDimitry Andric     "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",
11170b57cec5SDimitry Andric     "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",
11180b57cec5SDimitry Andric     "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
11190b57cec5SDimitry Andric 
11200b57cec5SDimitry Andric     // Quad registers
11210b57cec5SDimitry Andric     "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11",
11220b57cec5SDimitry Andric     "q12", "q13", "q14", "q15"};
11230b57cec5SDimitry Andric 
11240b57cec5SDimitry Andric ArrayRef<const char *> ARMTargetInfo::getGCCRegNames() const {
1125bdd1243dSDimitry Andric   return llvm::ArrayRef(GCCRegNames);
11260b57cec5SDimitry Andric }
11270b57cec5SDimitry Andric 
11280b57cec5SDimitry Andric const TargetInfo::GCCRegAlias ARMTargetInfo::GCCRegAliases[] = {
11290b57cec5SDimitry Andric     {{"a1"}, "r0"},  {{"a2"}, "r1"},        {{"a3"}, "r2"},  {{"a4"}, "r3"},
11300b57cec5SDimitry Andric     {{"v1"}, "r4"},  {{"v2"}, "r5"},        {{"v3"}, "r6"},  {{"v4"}, "r7"},
11310b57cec5SDimitry Andric     {{"v5"}, "r8"},  {{"v6", "rfp"}, "r9"}, {{"sl"}, "r10"}, {{"fp"}, "r11"},
11320b57cec5SDimitry Andric     {{"ip"}, "r12"}, {{"r13"}, "sp"},       {{"r14"}, "lr"}, {{"r15"}, "pc"},
11330b57cec5SDimitry Andric     // The S, D and Q registers overlap, but aren't really aliases; we
11340b57cec5SDimitry Andric     // don't want to substitute one of these for a different-sized one.
11350b57cec5SDimitry Andric };
11360b57cec5SDimitry Andric 
11370b57cec5SDimitry Andric ArrayRef<TargetInfo::GCCRegAlias> ARMTargetInfo::getGCCRegAliases() const {
1138bdd1243dSDimitry Andric   return llvm::ArrayRef(GCCRegAliases);
11390b57cec5SDimitry Andric }
11400b57cec5SDimitry Andric 
11410b57cec5SDimitry Andric bool ARMTargetInfo::validateAsmConstraint(
11420b57cec5SDimitry Andric     const char *&Name, TargetInfo::ConstraintInfo &Info) const {
11430b57cec5SDimitry Andric   switch (*Name) {
11440b57cec5SDimitry Andric   default:
11450b57cec5SDimitry Andric     break;
1146a7dea167SDimitry Andric   case 'l': // r0-r7 if thumb, r0-r15 if ARM
11470b57cec5SDimitry Andric     Info.setAllowsRegister();
11480b57cec5SDimitry Andric     return true;
1149a7dea167SDimitry Andric   case 'h': // r8-r15, thumb only
1150a7dea167SDimitry Andric     if (isThumb()) {
1151a7dea167SDimitry Andric       Info.setAllowsRegister();
11520b57cec5SDimitry Andric       return true;
1153a7dea167SDimitry Andric     }
1154a7dea167SDimitry Andric     break;
1155a7dea167SDimitry Andric   case 's': // An integer constant, but allowing only relocatable values.
1156a7dea167SDimitry Andric     return true;
1157a7dea167SDimitry Andric   case 't': // s0-s31, d0-d31, or q0-q15
1158a7dea167SDimitry Andric   case 'w': // s0-s15, d0-d7, or q0-q3
1159a7dea167SDimitry Andric   case 'x': // s0-s31, d0-d15, or q0-q7
1160349cc55cSDimitry Andric     if (FPRegsDisabled)
1161349cc55cSDimitry Andric       return false;
1162a7dea167SDimitry Andric     Info.setAllowsRegister();
1163a7dea167SDimitry Andric     return true;
1164a7dea167SDimitry Andric   case 'j': // An immediate integer between 0 and 65535 (valid for MOVW)
1165a7dea167SDimitry Andric     // only available in ARMv6T2 and above
11660fca6ea1SDimitry Andric     if (CPUAttr == "6T2" || ArchVersion >= 7) {
1167a7dea167SDimitry Andric       Info.setRequiresImmediate(0, 65535);
1168a7dea167SDimitry Andric       return true;
1169a7dea167SDimitry Andric     }
1170a7dea167SDimitry Andric     break;
1171a7dea167SDimitry Andric   case 'I':
1172a7dea167SDimitry Andric     if (isThumb()) {
1173a7dea167SDimitry Andric       if (!supportsThumb2())
1174a7dea167SDimitry Andric         Info.setRequiresImmediate(0, 255);
1175a7dea167SDimitry Andric       else
1176a7dea167SDimitry Andric         // FIXME: should check if immediate value would be valid for a Thumb2
1177a7dea167SDimitry Andric         // data-processing instruction
1178a7dea167SDimitry Andric         Info.setRequiresImmediate();
1179a7dea167SDimitry Andric     } else
1180a7dea167SDimitry Andric       // FIXME: should check if immediate value would be valid for an ARM
1181a7dea167SDimitry Andric       // data-processing instruction
1182a7dea167SDimitry Andric       Info.setRequiresImmediate();
1183a7dea167SDimitry Andric     return true;
1184a7dea167SDimitry Andric   case 'J':
1185a7dea167SDimitry Andric     if (isThumb() && !supportsThumb2())
1186a7dea167SDimitry Andric       Info.setRequiresImmediate(-255, -1);
1187a7dea167SDimitry Andric     else
1188a7dea167SDimitry Andric       Info.setRequiresImmediate(-4095, 4095);
1189a7dea167SDimitry Andric     return true;
1190a7dea167SDimitry Andric   case 'K':
1191a7dea167SDimitry Andric     if (isThumb()) {
1192a7dea167SDimitry Andric       if (!supportsThumb2())
1193a7dea167SDimitry Andric         // FIXME: should check if immediate value can be obtained from shifting
1194a7dea167SDimitry Andric         // a value between 0 and 255 left by any amount
1195a7dea167SDimitry Andric         Info.setRequiresImmediate();
1196a7dea167SDimitry Andric       else
1197a7dea167SDimitry Andric         // FIXME: should check if immediate value would be valid for a Thumb2
1198a7dea167SDimitry Andric         // data-processing instruction when inverted
1199a7dea167SDimitry Andric         Info.setRequiresImmediate();
1200a7dea167SDimitry Andric     } else
1201a7dea167SDimitry Andric       // FIXME: should check if immediate value would be valid for an ARM
1202a7dea167SDimitry Andric       // data-processing instruction when inverted
1203a7dea167SDimitry Andric       Info.setRequiresImmediate();
1204a7dea167SDimitry Andric     return true;
1205a7dea167SDimitry Andric   case 'L':
1206a7dea167SDimitry Andric     if (isThumb()) {
1207a7dea167SDimitry Andric       if (!supportsThumb2())
1208a7dea167SDimitry Andric         Info.setRequiresImmediate(-7, 7);
1209a7dea167SDimitry Andric       else
1210a7dea167SDimitry Andric         // FIXME: should check if immediate value would be valid for a Thumb2
1211a7dea167SDimitry Andric         // data-processing instruction when negated
1212a7dea167SDimitry Andric         Info.setRequiresImmediate();
1213a7dea167SDimitry Andric     } else
1214a7dea167SDimitry Andric       // FIXME: should check if immediate value  would be valid for an ARM
1215a7dea167SDimitry Andric       // data-processing instruction when negated
1216a7dea167SDimitry Andric       Info.setRequiresImmediate();
1217a7dea167SDimitry Andric     return true;
1218a7dea167SDimitry Andric   case 'M':
1219a7dea167SDimitry Andric     if (isThumb() && !supportsThumb2())
1220a7dea167SDimitry Andric       // FIXME: should check if immediate value is a multiple of 4 between 0 and
1221a7dea167SDimitry Andric       // 1020
1222a7dea167SDimitry Andric       Info.setRequiresImmediate();
1223a7dea167SDimitry Andric     else
1224a7dea167SDimitry Andric       // FIXME: should check if immediate value is a power of two or a integer
1225a7dea167SDimitry Andric       // between 0 and 32
1226a7dea167SDimitry Andric       Info.setRequiresImmediate();
1227a7dea167SDimitry Andric     return true;
1228a7dea167SDimitry Andric   case 'N':
1229a7dea167SDimitry Andric     // Thumb1 only
1230a7dea167SDimitry Andric     if (isThumb() && !supportsThumb2()) {
1231a7dea167SDimitry Andric       Info.setRequiresImmediate(0, 31);
1232a7dea167SDimitry Andric       return true;
1233a7dea167SDimitry Andric     }
1234a7dea167SDimitry Andric     break;
1235a7dea167SDimitry Andric   case 'O':
1236a7dea167SDimitry Andric     // Thumb1 only
1237a7dea167SDimitry Andric     if (isThumb() && !supportsThumb2()) {
1238a7dea167SDimitry Andric       // FIXME: should check if immediate value is a multiple of 4 between -508
1239a7dea167SDimitry Andric       // and 508
1240a7dea167SDimitry Andric       Info.setRequiresImmediate();
1241a7dea167SDimitry Andric       return true;
1242a7dea167SDimitry Andric     }
1243a7dea167SDimitry Andric     break;
12440b57cec5SDimitry Andric   case 'Q': // A memory address that is a single base register.
12450b57cec5SDimitry Andric     Info.setAllowsMemory();
12460b57cec5SDimitry Andric     return true;
12470b57cec5SDimitry Andric   case 'T':
12480b57cec5SDimitry Andric     switch (Name[1]) {
12490b57cec5SDimitry Andric     default:
12500b57cec5SDimitry Andric       break;
12510b57cec5SDimitry Andric     case 'e': // Even general-purpose register
12520b57cec5SDimitry Andric     case 'o': // Odd general-purpose register
12530b57cec5SDimitry Andric       Info.setAllowsRegister();
12540b57cec5SDimitry Andric       Name++;
12550b57cec5SDimitry Andric       return true;
12560b57cec5SDimitry Andric     }
12570b57cec5SDimitry Andric     break;
12580b57cec5SDimitry Andric   case 'U': // a memory reference...
12590b57cec5SDimitry Andric     switch (Name[1]) {
12600b57cec5SDimitry Andric     case 'q': // ...ARMV4 ldrsb
12610b57cec5SDimitry Andric     case 'v': // ...VFP load/store (reg+constant offset)
12620b57cec5SDimitry Andric     case 'y': // ...iWMMXt load/store
12630b57cec5SDimitry Andric     case 't': // address valid for load/store opaque types wider
12640b57cec5SDimitry Andric               // than 128-bits
12650b57cec5SDimitry Andric     case 'n': // valid address for Neon doubleword vector load/store
12660b57cec5SDimitry Andric     case 'm': // valid address for Neon element and structure load/store
12670b57cec5SDimitry Andric     case 's': // valid address for non-offset loads/stores of quad-word
12680b57cec5SDimitry Andric               // values in four ARM registers
12690b57cec5SDimitry Andric       Info.setAllowsMemory();
12700b57cec5SDimitry Andric       Name++;
12710b57cec5SDimitry Andric       return true;
12720b57cec5SDimitry Andric     }
12730b57cec5SDimitry Andric     break;
12740b57cec5SDimitry Andric   }
12750b57cec5SDimitry Andric   return false;
12760b57cec5SDimitry Andric }
12770b57cec5SDimitry Andric 
12780b57cec5SDimitry Andric std::string ARMTargetInfo::convertConstraint(const char *&Constraint) const {
12790b57cec5SDimitry Andric   std::string R;
12800b57cec5SDimitry Andric   switch (*Constraint) {
12810b57cec5SDimitry Andric   case 'U': // Two-character constraint; add "^" hint for later parsing.
12820b57cec5SDimitry Andric   case 'T':
12830b57cec5SDimitry Andric     R = std::string("^") + std::string(Constraint, 2);
12840b57cec5SDimitry Andric     Constraint++;
12850b57cec5SDimitry Andric     break;
12860b57cec5SDimitry Andric   case 'p': // 'p' should be translated to 'r' by default.
12870b57cec5SDimitry Andric     R = std::string("r");
12880b57cec5SDimitry Andric     break;
12890b57cec5SDimitry Andric   default:
12900b57cec5SDimitry Andric     return std::string(1, *Constraint);
12910b57cec5SDimitry Andric   }
12920b57cec5SDimitry Andric   return R;
12930b57cec5SDimitry Andric }
12940b57cec5SDimitry Andric 
12950b57cec5SDimitry Andric bool ARMTargetInfo::validateConstraintModifier(
12960b57cec5SDimitry Andric     StringRef Constraint, char Modifier, unsigned Size,
12970b57cec5SDimitry Andric     std::string &SuggestedModifier) const {
12980b57cec5SDimitry Andric   bool isOutput = (Constraint[0] == '=');
12990b57cec5SDimitry Andric   bool isInOut = (Constraint[0] == '+');
13000b57cec5SDimitry Andric 
13010b57cec5SDimitry Andric   // Strip off constraint modifiers.
1302647cbc5dSDimitry Andric   Constraint = Constraint.ltrim("=+&");
13030b57cec5SDimitry Andric 
13040b57cec5SDimitry Andric   switch (Constraint[0]) {
13050b57cec5SDimitry Andric   default:
13060b57cec5SDimitry Andric     break;
13070b57cec5SDimitry Andric   case 'r': {
13080b57cec5SDimitry Andric     switch (Modifier) {
13090b57cec5SDimitry Andric     default:
13100b57cec5SDimitry Andric       return (isInOut || isOutput || Size <= 64);
13110b57cec5SDimitry Andric     case 'q':
13120b57cec5SDimitry Andric       // A register of size 32 cannot fit a vector type.
13130b57cec5SDimitry Andric       return false;
13140b57cec5SDimitry Andric     }
13150b57cec5SDimitry Andric   }
13160b57cec5SDimitry Andric   }
13170b57cec5SDimitry Andric 
13180b57cec5SDimitry Andric   return true;
13190b57cec5SDimitry Andric }
132006c3fb27SDimitry Andric std::string_view ARMTargetInfo::getClobbers() const {
13210b57cec5SDimitry Andric   // FIXME: Is this really right?
13220b57cec5SDimitry Andric   return "";
13230b57cec5SDimitry Andric }
13240b57cec5SDimitry Andric 
13250b57cec5SDimitry Andric TargetInfo::CallingConvCheckResult
13260b57cec5SDimitry Andric ARMTargetInfo::checkCallingConvention(CallingConv CC) const {
13270b57cec5SDimitry Andric   switch (CC) {
13280b57cec5SDimitry Andric   case CC_AAPCS:
13290b57cec5SDimitry Andric   case CC_AAPCS_VFP:
13300b57cec5SDimitry Andric   case CC_Swift:
1331fe6060f1SDimitry Andric   case CC_SwiftAsync:
13320b57cec5SDimitry Andric   case CC_OpenCLKernel:
13330b57cec5SDimitry Andric     return CCCR_OK;
13340b57cec5SDimitry Andric   default:
13350b57cec5SDimitry Andric     return CCCR_Warning;
13360b57cec5SDimitry Andric   }
13370b57cec5SDimitry Andric }
13380b57cec5SDimitry Andric 
13390b57cec5SDimitry Andric int ARMTargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
13400b57cec5SDimitry Andric   if (RegNo == 0)
13410b57cec5SDimitry Andric     return 0;
13420b57cec5SDimitry Andric   if (RegNo == 1)
13430b57cec5SDimitry Andric     return 1;
13440b57cec5SDimitry Andric   return -1;
13450b57cec5SDimitry Andric }
13460b57cec5SDimitry Andric 
13470b57cec5SDimitry Andric bool ARMTargetInfo::hasSjLjLowering() const { return true; }
13480b57cec5SDimitry Andric 
13490b57cec5SDimitry Andric ARMleTargetInfo::ARMleTargetInfo(const llvm::Triple &Triple,
13500b57cec5SDimitry Andric                                  const TargetOptions &Opts)
13510b57cec5SDimitry Andric     : ARMTargetInfo(Triple, Opts) {}
13520b57cec5SDimitry Andric 
13530b57cec5SDimitry Andric void ARMleTargetInfo::getTargetDefines(const LangOptions &Opts,
13540b57cec5SDimitry Andric                                        MacroBuilder &Builder) const {
13550b57cec5SDimitry Andric   Builder.defineMacro("__ARMEL__");
13560b57cec5SDimitry Andric   ARMTargetInfo::getTargetDefines(Opts, Builder);
13570b57cec5SDimitry Andric }
13580b57cec5SDimitry Andric 
13590b57cec5SDimitry Andric ARMbeTargetInfo::ARMbeTargetInfo(const llvm::Triple &Triple,
13600b57cec5SDimitry Andric                                  const TargetOptions &Opts)
13610b57cec5SDimitry Andric     : ARMTargetInfo(Triple, Opts) {}
13620b57cec5SDimitry Andric 
13630b57cec5SDimitry Andric void ARMbeTargetInfo::getTargetDefines(const LangOptions &Opts,
13640b57cec5SDimitry Andric                                        MacroBuilder &Builder) const {
13650b57cec5SDimitry Andric   Builder.defineMacro("__ARMEB__");
13660b57cec5SDimitry Andric   Builder.defineMacro("__ARM_BIG_ENDIAN");
13670b57cec5SDimitry Andric   ARMTargetInfo::getTargetDefines(Opts, Builder);
13680b57cec5SDimitry Andric }
13690b57cec5SDimitry Andric 
13700b57cec5SDimitry Andric WindowsARMTargetInfo::WindowsARMTargetInfo(const llvm::Triple &Triple,
13710b57cec5SDimitry Andric                                            const TargetOptions &Opts)
13720b57cec5SDimitry Andric     : WindowsTargetInfo<ARMleTargetInfo>(Triple, Opts), Triple(Triple) {
13730b57cec5SDimitry Andric }
13740b57cec5SDimitry Andric 
13750b57cec5SDimitry Andric void WindowsARMTargetInfo::getVisualStudioDefines(const LangOptions &Opts,
13760b57cec5SDimitry Andric                                                   MacroBuilder &Builder) const {
13770b57cec5SDimitry Andric   // FIXME: this is invalid for WindowsCE
13780b57cec5SDimitry Andric   Builder.defineMacro("_M_ARM_NT", "1");
13790b57cec5SDimitry Andric   Builder.defineMacro("_M_ARMT", "_M_ARM");
13800b57cec5SDimitry Andric   Builder.defineMacro("_M_THUMB", "_M_ARM");
13810b57cec5SDimitry Andric 
13820b57cec5SDimitry Andric   assert((Triple.getArch() == llvm::Triple::arm ||
13830b57cec5SDimitry Andric           Triple.getArch() == llvm::Triple::thumb) &&
13840b57cec5SDimitry Andric          "invalid architecture for Windows ARM target info");
13850b57cec5SDimitry Andric   unsigned Offset = Triple.getArch() == llvm::Triple::arm ? 4 : 6;
13860b57cec5SDimitry Andric   Builder.defineMacro("_M_ARM", Triple.getArchName().substr(Offset));
13870b57cec5SDimitry Andric 
13880b57cec5SDimitry Andric   // TODO map the complete set of values
13890b57cec5SDimitry Andric   // 31: VFPv3 40: VFPv4
13900b57cec5SDimitry Andric   Builder.defineMacro("_M_ARM_FP", "31");
13910b57cec5SDimitry Andric }
13920b57cec5SDimitry Andric 
13930b57cec5SDimitry Andric TargetInfo::BuiltinVaListKind
13940b57cec5SDimitry Andric WindowsARMTargetInfo::getBuiltinVaListKind() const {
13950b57cec5SDimitry Andric   return TargetInfo::CharPtrBuiltinVaList;
13960b57cec5SDimitry Andric }
13970b57cec5SDimitry Andric 
13980b57cec5SDimitry Andric TargetInfo::CallingConvCheckResult
13990b57cec5SDimitry Andric WindowsARMTargetInfo::checkCallingConvention(CallingConv CC) const {
14000b57cec5SDimitry Andric   switch (CC) {
14010b57cec5SDimitry Andric   case CC_X86StdCall:
14020b57cec5SDimitry Andric   case CC_X86ThisCall:
14030b57cec5SDimitry Andric   case CC_X86FastCall:
14040b57cec5SDimitry Andric   case CC_X86VectorCall:
14050b57cec5SDimitry Andric     return CCCR_Ignore;
14060b57cec5SDimitry Andric   case CC_C:
14070b57cec5SDimitry Andric   case CC_OpenCLKernel:
14080b57cec5SDimitry Andric   case CC_PreserveMost:
14090b57cec5SDimitry Andric   case CC_PreserveAll:
14100b57cec5SDimitry Andric   case CC_Swift:
1411fe6060f1SDimitry Andric   case CC_SwiftAsync:
14120b57cec5SDimitry Andric     return CCCR_OK;
14130b57cec5SDimitry Andric   default:
14140b57cec5SDimitry Andric     return CCCR_Warning;
14150b57cec5SDimitry Andric   }
14160b57cec5SDimitry Andric }
14170b57cec5SDimitry Andric 
14180b57cec5SDimitry Andric // Windows ARM + Itanium C++ ABI Target
14190b57cec5SDimitry Andric ItaniumWindowsARMleTargetInfo::ItaniumWindowsARMleTargetInfo(
14200b57cec5SDimitry Andric     const llvm::Triple &Triple, const TargetOptions &Opts)
14210b57cec5SDimitry Andric     : WindowsARMTargetInfo(Triple, Opts) {
14220b57cec5SDimitry Andric   TheCXXABI.set(TargetCXXABI::GenericARM);
14230b57cec5SDimitry Andric }
14240b57cec5SDimitry Andric 
14250b57cec5SDimitry Andric void ItaniumWindowsARMleTargetInfo::getTargetDefines(
14260b57cec5SDimitry Andric     const LangOptions &Opts, MacroBuilder &Builder) const {
14270b57cec5SDimitry Andric   WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
14280b57cec5SDimitry Andric 
14290b57cec5SDimitry Andric   if (Opts.MSVCCompat)
14300b57cec5SDimitry Andric     WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
14310b57cec5SDimitry Andric }
14320b57cec5SDimitry Andric 
14330b57cec5SDimitry Andric // Windows ARM, MS (C++) ABI
14340b57cec5SDimitry Andric MicrosoftARMleTargetInfo::MicrosoftARMleTargetInfo(const llvm::Triple &Triple,
14350b57cec5SDimitry Andric                                                    const TargetOptions &Opts)
14360b57cec5SDimitry Andric     : WindowsARMTargetInfo(Triple, Opts) {
14370b57cec5SDimitry Andric   TheCXXABI.set(TargetCXXABI::Microsoft);
14380b57cec5SDimitry Andric }
14390b57cec5SDimitry Andric 
14400b57cec5SDimitry Andric void MicrosoftARMleTargetInfo::getTargetDefines(const LangOptions &Opts,
14410b57cec5SDimitry Andric                                                 MacroBuilder &Builder) const {
14420b57cec5SDimitry Andric   WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
14430b57cec5SDimitry Andric   WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
14440b57cec5SDimitry Andric }
14450b57cec5SDimitry Andric 
14460b57cec5SDimitry Andric MinGWARMTargetInfo::MinGWARMTargetInfo(const llvm::Triple &Triple,
14470b57cec5SDimitry Andric                                        const TargetOptions &Opts)
14480b57cec5SDimitry Andric     : WindowsARMTargetInfo(Triple, Opts) {
14490b57cec5SDimitry Andric   TheCXXABI.set(TargetCXXABI::GenericARM);
14500b57cec5SDimitry Andric }
14510b57cec5SDimitry Andric 
14520b57cec5SDimitry Andric void MinGWARMTargetInfo::getTargetDefines(const LangOptions &Opts,
14530b57cec5SDimitry Andric                                           MacroBuilder &Builder) const {
14540b57cec5SDimitry Andric   WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
14550b57cec5SDimitry Andric   Builder.defineMacro("_ARM_");
14560b57cec5SDimitry Andric }
14570b57cec5SDimitry Andric 
14580b57cec5SDimitry Andric CygwinARMTargetInfo::CygwinARMTargetInfo(const llvm::Triple &Triple,
14590b57cec5SDimitry Andric                                          const TargetOptions &Opts)
14600b57cec5SDimitry Andric     : ARMleTargetInfo(Triple, Opts) {
14610b57cec5SDimitry Andric   this->WCharType = TargetInfo::UnsignedShort;
14620b57cec5SDimitry Andric   TLSSupported = false;
14630b57cec5SDimitry Andric   DoubleAlign = LongLongAlign = 64;
14640b57cec5SDimitry Andric   resetDataLayout("e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64");
14650b57cec5SDimitry Andric }
14660b57cec5SDimitry Andric 
14670b57cec5SDimitry Andric void CygwinARMTargetInfo::getTargetDefines(const LangOptions &Opts,
14680b57cec5SDimitry Andric                                            MacroBuilder &Builder) const {
14690b57cec5SDimitry Andric   ARMleTargetInfo::getTargetDefines(Opts, Builder);
14700b57cec5SDimitry Andric   Builder.defineMacro("_ARM_");
14710b57cec5SDimitry Andric   Builder.defineMacro("__CYGWIN__");
14720b57cec5SDimitry Andric   Builder.defineMacro("__CYGWIN32__");
14730b57cec5SDimitry Andric   DefineStd(Builder, "unix", Opts);
14740b57cec5SDimitry Andric   if (Opts.CPlusPlus)
14750b57cec5SDimitry Andric     Builder.defineMacro("_GNU_SOURCE");
14760b57cec5SDimitry Andric }
14770b57cec5SDimitry Andric 
14780b57cec5SDimitry Andric DarwinARMTargetInfo::DarwinARMTargetInfo(const llvm::Triple &Triple,
14790b57cec5SDimitry Andric                                          const TargetOptions &Opts)
14800b57cec5SDimitry Andric     : DarwinTargetInfo<ARMleTargetInfo>(Triple, Opts) {
14810b57cec5SDimitry Andric   HasAlignMac68kSupport = true;
14820b57cec5SDimitry Andric   if (Triple.isWatchABI()) {
14830b57cec5SDimitry Andric     // Darwin on iOS uses a variant of the ARM C++ ABI.
14840b57cec5SDimitry Andric     TheCXXABI.set(TargetCXXABI::WatchOS);
14850b57cec5SDimitry Andric 
14860b57cec5SDimitry Andric     // BOOL should be a real boolean on the new ABI
14870b57cec5SDimitry Andric     UseSignedCharForObjCBool = false;
14880b57cec5SDimitry Andric   } else
14890b57cec5SDimitry Andric     TheCXXABI.set(TargetCXXABI::iOS);
14900b57cec5SDimitry Andric }
14910b57cec5SDimitry Andric 
14920b57cec5SDimitry Andric void DarwinARMTargetInfo::getOSDefines(const LangOptions &Opts,
14930b57cec5SDimitry Andric                                        const llvm::Triple &Triple,
14940b57cec5SDimitry Andric                                        MacroBuilder &Builder) const {
14950b57cec5SDimitry Andric   getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
14960b57cec5SDimitry Andric }
14970b57cec5SDimitry Andric 
14980b57cec5SDimitry Andric RenderScript32TargetInfo::RenderScript32TargetInfo(const llvm::Triple &Triple,
14990b57cec5SDimitry Andric                                                    const TargetOptions &Opts)
15000b57cec5SDimitry Andric     : ARMleTargetInfo(llvm::Triple("armv7", Triple.getVendorName(),
15010b57cec5SDimitry Andric                                    Triple.getOSName(),
15020b57cec5SDimitry Andric                                    Triple.getEnvironmentName()),
15030b57cec5SDimitry Andric                       Opts) {
15040b57cec5SDimitry Andric   IsRenderScriptTarget = true;
15050b57cec5SDimitry Andric   LongWidth = LongAlign = 64;
15060b57cec5SDimitry Andric }
15070b57cec5SDimitry Andric 
15080b57cec5SDimitry Andric void RenderScript32TargetInfo::getTargetDefines(const LangOptions &Opts,
15090b57cec5SDimitry Andric                                                 MacroBuilder &Builder) const {
15100b57cec5SDimitry Andric   Builder.defineMacro("__RENDERSCRIPT__");
15110b57cec5SDimitry Andric   ARMleTargetInfo::getTargetDefines(Opts, Builder);
15120b57cec5SDimitry Andric }
1513