10b57cec5SDimitry Andric //===--- ARM.h - Declare ARM target feature support -------------*- C++ -*-===//
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 declares ARM TargetInfo objects.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_ARM_H
140b57cec5SDimitry Andric #define LLVM_CLANG_LIB_BASIC_TARGETS_ARM_H
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include "OSTargets.h"
170b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h"
180b57cec5SDimitry Andric #include "clang/Basic/TargetOptions.h"
19bdd1243dSDimitry Andric #include "llvm/Support/Compiler.h"
2006c3fb27SDimitry Andric #include "llvm/TargetParser/ARMTargetParser.h"
2106c3fb27SDimitry Andric #include "llvm/TargetParser/ARMTargetParserCommon.h"
2206c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric namespace clang {
250b57cec5SDimitry Andric namespace targets {
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY ARMTargetInfo : public TargetInfo {
280b57cec5SDimitry Andric   // Possible FPU choices.
290b57cec5SDimitry Andric   enum FPUMode {
300b57cec5SDimitry Andric     VFP2FPU = (1 << 0),
310b57cec5SDimitry Andric     VFP3FPU = (1 << 1),
320b57cec5SDimitry Andric     VFP4FPU = (1 << 2),
330b57cec5SDimitry Andric     NeonFPU = (1 << 3),
340b57cec5SDimitry Andric     FPARMV8 = (1 << 4)
350b57cec5SDimitry Andric   };
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric   enum MVEMode {
380b57cec5SDimitry Andric       MVE_INT = (1 << 0),
390b57cec5SDimitry Andric       MVE_FP  = (1 << 1)
400b57cec5SDimitry Andric   };
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric   // Possible HWDiv features.
430b57cec5SDimitry Andric   enum HWDivMode { HWDivThumb = (1 << 0), HWDivARM = (1 << 1) };
440b57cec5SDimitry Andric 
FPUModeIsVFP(FPUMode Mode)450b57cec5SDimitry Andric   static bool FPUModeIsVFP(FPUMode Mode) {
460b57cec5SDimitry Andric     return Mode & (VFP2FPU | VFP3FPU | VFP4FPU | NeonFPU | FPARMV8);
470b57cec5SDimitry Andric   }
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric   static const TargetInfo::GCCRegAlias GCCRegAliases[];
500b57cec5SDimitry Andric   static const char *const GCCRegNames[];
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric   std::string ABI, CPU;
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric   StringRef CPUProfile;
550b57cec5SDimitry Andric   StringRef CPUAttr;
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric   enum { FP_Default, FP_VFP, FP_Neon } FPMath;
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric   llvm::ARM::ISAKind ArchISA;
600b57cec5SDimitry Andric   llvm::ARM::ArchKind ArchKind = llvm::ARM::ArchKind::ARMV4T;
610b57cec5SDimitry Andric   llvm::ARM::ProfileKind ArchProfile;
620b57cec5SDimitry Andric   unsigned ArchVersion;
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric   unsigned FPU : 5;
650b57cec5SDimitry Andric   unsigned MVE : 2;
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric   unsigned IsAAPCS : 1;
680b57cec5SDimitry Andric   unsigned HWDiv : 2;
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric   // Initialized via features.
710b57cec5SDimitry Andric   unsigned SoftFloat : 1;
720b57cec5SDimitry Andric   unsigned SoftFloatABI : 1;
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric   unsigned CRC : 1;
750b57cec5SDimitry Andric   unsigned Crypto : 1;
76fe6060f1SDimitry Andric   unsigned SHA2 : 1;
77fe6060f1SDimitry Andric   unsigned AES : 1;
780b57cec5SDimitry Andric   unsigned DSP : 1;
790b57cec5SDimitry Andric   unsigned Unaligned : 1;
800b57cec5SDimitry Andric   unsigned DotProd : 1;
815ffd83dbSDimitry Andric   unsigned HasMatMul : 1;
82349cc55cSDimitry Andric   unsigned FPRegsDisabled : 1;
830eae32dcSDimitry Andric   unsigned HasPAC : 1;
840eae32dcSDimitry Andric   unsigned HasBTI : 1;
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   enum {
870b57cec5SDimitry Andric     LDREX_B = (1 << 0), /// byte (8-bit)
880b57cec5SDimitry Andric     LDREX_H = (1 << 1), /// half (16-bit)
890b57cec5SDimitry Andric     LDREX_W = (1 << 2), /// word (32-bit)
900b57cec5SDimitry Andric     LDREX_D = (1 << 3), /// double (64-bit)
910b57cec5SDimitry Andric   };
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric   uint32_t LDREX;
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric   // ACLE 6.5.1 Hardware floating point
960b57cec5SDimitry Andric   enum {
970b57cec5SDimitry Andric     HW_FP_HP = (1 << 1), /// half (16-bit)
980b57cec5SDimitry Andric     HW_FP_SP = (1 << 2), /// single (32-bit)
990b57cec5SDimitry Andric     HW_FP_DP = (1 << 3), /// double (64-bit)
1000b57cec5SDimitry Andric   };
1010b57cec5SDimitry Andric   uint32_t HW_FP;
1020b57cec5SDimitry Andric 
1031db9f3b2SDimitry Andric   enum {
1041db9f3b2SDimitry Andric     /// __arm_cdp __arm_ldc, __arm_ldcl, __arm_stc,
1051db9f3b2SDimitry Andric     /// __arm_stcl, __arm_mcr and __arm_mrc
1061db9f3b2SDimitry Andric     FEATURE_COPROC_B1 = (1 << 0),
1071db9f3b2SDimitry Andric     /// __arm_cdp2, __arm_ldc2, __arm_stc2, __arm_ldc2l,
1081db9f3b2SDimitry Andric     /// __arm_stc2l, __arm_mcr2 and __arm_mrc2
1091db9f3b2SDimitry Andric     FEATURE_COPROC_B2 = (1 << 1),
1101db9f3b2SDimitry Andric     /// __arm_mcrr, __arm_mrrc
1111db9f3b2SDimitry Andric     FEATURE_COPROC_B3 = (1 << 2),
1121db9f3b2SDimitry Andric     /// __arm_mcrr2,  __arm_mrrc2
1131db9f3b2SDimitry Andric     FEATURE_COPROC_B4 = (1 << 3),
1141db9f3b2SDimitry Andric   };
1151db9f3b2SDimitry Andric 
1160b57cec5SDimitry Andric   void setABIAAPCS();
1170b57cec5SDimitry Andric   void setABIAPCS(bool IsAAPCS16);
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric   void setArchInfo();
1200b57cec5SDimitry Andric   void setArchInfo(llvm::ARM::ArchKind Kind);
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric   void setAtomic();
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric   bool isThumb() const;
1250b57cec5SDimitry Andric   bool supportsThumb() const;
1260b57cec5SDimitry Andric   bool supportsThumb2() const;
1270b57cec5SDimitry Andric   bool hasMVE() const;
1280b57cec5SDimitry Andric   bool hasMVEFloat() const;
1295ffd83dbSDimitry Andric   bool hasCDE() const;
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   StringRef getCPUAttr() const;
1320b57cec5SDimitry Andric   StringRef getCPUProfile() const;
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric public:
1350b57cec5SDimitry Andric   ARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric   StringRef getABI() const override;
1380b57cec5SDimitry Andric   bool setABI(const std::string &Name) override;
1390b57cec5SDimitry Andric 
1401fd87a68SDimitry Andric   bool isBranchProtectionSupportedArch(StringRef Arch) const override;
1411fd87a68SDimitry Andric   bool validateBranchProtection(StringRef Spec, StringRef Arch,
1421fd87a68SDimitry Andric                                 BranchProtectionInfo &BPI,
1431fd87a68SDimitry Andric                                 StringRef &Err) const override;
1444824e7fdSDimitry Andric 
1450b57cec5SDimitry Andric   // FIXME: This should be based on Arch attributes, not CPU names.
1460b57cec5SDimitry Andric   bool
1470b57cec5SDimitry Andric   initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
1480b57cec5SDimitry Andric                  StringRef CPU,
1490b57cec5SDimitry Andric                  const std::vector<std::string> &FeaturesVec) const override;
1500b57cec5SDimitry Andric 
isValidFeatureName(StringRef Feature)1510b57cec5SDimitry Andric   bool isValidFeatureName(StringRef Feature) const override {
1520b57cec5SDimitry Andric     // We pass soft-float-abi in as a -target-feature, but the backend figures
1530b57cec5SDimitry Andric     // this out through other means.
1540b57cec5SDimitry Andric     return Feature != "soft-float-abi";
1550b57cec5SDimitry Andric   }
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric   bool handleTargetFeatures(std::vector<std::string> &Features,
1580b57cec5SDimitry Andric                             DiagnosticsEngine &Diags) override;
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric   bool hasFeature(StringRef Feature) const override;
1610b57cec5SDimitry Andric 
1625ffd83dbSDimitry Andric   bool hasBFloat16Type() const override;
1635ffd83dbSDimitry Andric 
1640b57cec5SDimitry Andric   bool isValidCPUName(StringRef Name) const override;
1650b57cec5SDimitry Andric   void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric   bool setCPU(const std::string &Name) override;
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric   bool setFPMath(StringRef Name) override;
1700b57cec5SDimitry Andric 
useFP16ConversionIntrinsics()1710b57cec5SDimitry Andric   bool useFP16ConversionIntrinsics() const override {
1720b57cec5SDimitry Andric     return false;
1730b57cec5SDimitry Andric   }
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric   void getTargetDefinesARMV81A(const LangOptions &Opts,
1760b57cec5SDimitry Andric                                MacroBuilder &Builder) const;
1770b57cec5SDimitry Andric   void getTargetDefinesARMV82A(const LangOptions &Opts,
1780b57cec5SDimitry Andric                                MacroBuilder &Builder) const;
179480093f4SDimitry Andric   void getTargetDefinesARMV83A(const LangOptions &Opts,
180480093f4SDimitry Andric                                  MacroBuilder &Builder) const;
1810b57cec5SDimitry Andric   void getTargetDefines(const LangOptions &Opts,
1820b57cec5SDimitry Andric                         MacroBuilder &Builder) const override;
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric   ArrayRef<Builtin::Info> getTargetBuiltins() const override;
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric   bool isCLZForZeroUndef() const override;
1870b57cec5SDimitry Andric   BuiltinVaListKind getBuiltinVaListKind() const override;
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric   ArrayRef<const char *> getGCCRegNames() const override;
1900b57cec5SDimitry Andric   ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
1910b57cec5SDimitry Andric   bool validateAsmConstraint(const char *&Name,
1920b57cec5SDimitry Andric                              TargetInfo::ConstraintInfo &Info) const override;
1930b57cec5SDimitry Andric   std::string convertConstraint(const char *&Constraint) const override;
1940b57cec5SDimitry Andric   bool
1950b57cec5SDimitry Andric   validateConstraintModifier(StringRef Constraint, char Modifier, unsigned Size,
1960b57cec5SDimitry Andric                              std::string &SuggestedModifier) const override;
19706c3fb27SDimitry Andric   std::string_view getClobbers() const override;
1980b57cec5SDimitry Andric 
getConstraintRegister(StringRef Constraint,StringRef Expression)1990b57cec5SDimitry Andric   StringRef getConstraintRegister(StringRef Constraint,
2000b57cec5SDimitry Andric                                   StringRef Expression) const override {
2010b57cec5SDimitry Andric     return Expression;
2020b57cec5SDimitry Andric   }
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric   CallingConvCheckResult checkCallingConvention(CallingConv CC) const override;
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric   int getEHDataRegisterNumber(unsigned RegNo) const override;
2070b57cec5SDimitry Andric 
2080b57cec5SDimitry Andric   bool hasSjLjLowering() const override;
2095ffd83dbSDimitry Andric 
hasBitIntType()2100eae32dcSDimitry Andric   bool hasBitIntType() const override { return true; }
2115ffd83dbSDimitry Andric 
getBFloat16Mangling()2125ffd83dbSDimitry Andric   const char *getBFloat16Mangling() const override { return "u6__bf16"; };
2130b57cec5SDimitry Andric };
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY ARMleTargetInfo : public ARMTargetInfo {
2160b57cec5SDimitry Andric public:
2170b57cec5SDimitry Andric   ARMleTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
2180b57cec5SDimitry Andric   void getTargetDefines(const LangOptions &Opts,
2190b57cec5SDimitry Andric                         MacroBuilder &Builder) const override;
2200b57cec5SDimitry Andric };
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY ARMbeTargetInfo : public ARMTargetInfo {
2230b57cec5SDimitry Andric public:
2240b57cec5SDimitry Andric   ARMbeTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
2250b57cec5SDimitry Andric   void getTargetDefines(const LangOptions &Opts,
2260b57cec5SDimitry Andric                         MacroBuilder &Builder) const override;
2270b57cec5SDimitry Andric };
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY WindowsARMTargetInfo
2300b57cec5SDimitry Andric     : public WindowsTargetInfo<ARMleTargetInfo> {
2310b57cec5SDimitry Andric   const llvm::Triple Triple;
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric public:
2340b57cec5SDimitry Andric   WindowsARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric   void getVisualStudioDefines(const LangOptions &Opts,
2370b57cec5SDimitry Andric                               MacroBuilder &Builder) const;
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric   BuiltinVaListKind getBuiltinVaListKind() const override;
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric   CallingConvCheckResult checkCallingConvention(CallingConv CC) const override;
2420b57cec5SDimitry Andric };
2430b57cec5SDimitry Andric 
2440b57cec5SDimitry Andric // Windows ARM + Itanium C++ ABI Target
2450b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY ItaniumWindowsARMleTargetInfo
2460b57cec5SDimitry Andric     : public WindowsARMTargetInfo {
2470b57cec5SDimitry Andric public:
2480b57cec5SDimitry Andric   ItaniumWindowsARMleTargetInfo(const llvm::Triple &Triple,
2490b57cec5SDimitry Andric                                 const TargetOptions &Opts);
2500b57cec5SDimitry Andric 
2510b57cec5SDimitry Andric   void getTargetDefines(const LangOptions &Opts,
2520b57cec5SDimitry Andric                         MacroBuilder &Builder) const override;
2530b57cec5SDimitry Andric };
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric // Windows ARM, MS (C++) ABI
2560b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY MicrosoftARMleTargetInfo
2570b57cec5SDimitry Andric     : public WindowsARMTargetInfo {
2580b57cec5SDimitry Andric public:
2590b57cec5SDimitry Andric   MicrosoftARMleTargetInfo(const llvm::Triple &Triple,
2600b57cec5SDimitry Andric                            const TargetOptions &Opts);
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric   void getTargetDefines(const LangOptions &Opts,
2630b57cec5SDimitry Andric                         MacroBuilder &Builder) const override;
2640b57cec5SDimitry Andric };
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric // ARM MinGW target
2670b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY MinGWARMTargetInfo : public WindowsARMTargetInfo {
2680b57cec5SDimitry Andric public:
2690b57cec5SDimitry Andric   MinGWARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric   void getTargetDefines(const LangOptions &Opts,
2720b57cec5SDimitry Andric                         MacroBuilder &Builder) const override;
2730b57cec5SDimitry Andric };
2740b57cec5SDimitry Andric 
2750b57cec5SDimitry Andric // ARM Cygwin target
2760b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY CygwinARMTargetInfo : public ARMleTargetInfo {
2770b57cec5SDimitry Andric public:
2780b57cec5SDimitry Andric   CygwinARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
2790b57cec5SDimitry Andric 
2800b57cec5SDimitry Andric   void getTargetDefines(const LangOptions &Opts,
2810b57cec5SDimitry Andric                         MacroBuilder &Builder) const override;
2820b57cec5SDimitry Andric };
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY DarwinARMTargetInfo
2850b57cec5SDimitry Andric     : public DarwinTargetInfo<ARMleTargetInfo> {
2860b57cec5SDimitry Andric protected:
2870b57cec5SDimitry Andric   void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
2880b57cec5SDimitry Andric                     MacroBuilder &Builder) const override;
2890b57cec5SDimitry Andric 
2900b57cec5SDimitry Andric public:
2910b57cec5SDimitry Andric   DarwinARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
2920b57cec5SDimitry Andric };
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric // 32-bit RenderScript is armv7 with width and align of 'long' set to 8-bytes
2950b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY RenderScript32TargetInfo
2960b57cec5SDimitry Andric     : public ARMleTargetInfo {
2970b57cec5SDimitry Andric public:
2980b57cec5SDimitry Andric   RenderScript32TargetInfo(const llvm::Triple &Triple,
2990b57cec5SDimitry Andric                            const TargetOptions &Opts);
3000b57cec5SDimitry Andric 
3010b57cec5SDimitry Andric   void getTargetDefines(const LangOptions &Opts,
3020b57cec5SDimitry Andric                         MacroBuilder &Builder) const override;
3030b57cec5SDimitry Andric };
3040b57cec5SDimitry Andric 
3050b57cec5SDimitry Andric } // namespace targets
3060b57cec5SDimitry Andric } // namespace clang
3070b57cec5SDimitry Andric 
3080b57cec5SDimitry Andric #endif // LLVM_CLANG_LIB_BASIC_TARGETS_ARM_H
309