xref: /freebsd-src/contrib/llvm-project/clang/lib/Basic/Targets/ARM.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 
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 
64*0fca6ea1SDimitry Andric   LLVM_PREFERRED_TYPE(FPUMode)
650b57cec5SDimitry Andric   unsigned FPU : 5;
66*0fca6ea1SDimitry Andric   LLVM_PREFERRED_TYPE(MVEMode)
670b57cec5SDimitry Andric   unsigned MVE : 2;
680b57cec5SDimitry Andric 
69*0fca6ea1SDimitry Andric   LLVM_PREFERRED_TYPE(bool)
700b57cec5SDimitry Andric   unsigned IsAAPCS : 1;
71*0fca6ea1SDimitry Andric   LLVM_PREFERRED_TYPE(HWDivMode)
720b57cec5SDimitry Andric   unsigned HWDiv : 2;
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric   // Initialized via features.
75*0fca6ea1SDimitry Andric   LLVM_PREFERRED_TYPE(bool)
760b57cec5SDimitry Andric   unsigned SoftFloat : 1;
77*0fca6ea1SDimitry Andric   LLVM_PREFERRED_TYPE(bool)
780b57cec5SDimitry Andric   unsigned SoftFloatABI : 1;
790b57cec5SDimitry Andric 
80*0fca6ea1SDimitry Andric   LLVM_PREFERRED_TYPE(bool)
810b57cec5SDimitry Andric   unsigned CRC : 1;
82*0fca6ea1SDimitry Andric   LLVM_PREFERRED_TYPE(bool)
830b57cec5SDimitry Andric   unsigned Crypto : 1;
84*0fca6ea1SDimitry Andric   LLVM_PREFERRED_TYPE(bool)
85fe6060f1SDimitry Andric   unsigned SHA2 : 1;
86*0fca6ea1SDimitry Andric   LLVM_PREFERRED_TYPE(bool)
87fe6060f1SDimitry Andric   unsigned AES : 1;
88*0fca6ea1SDimitry Andric   LLVM_PREFERRED_TYPE(bool)
890b57cec5SDimitry Andric   unsigned DSP : 1;
90*0fca6ea1SDimitry Andric   LLVM_PREFERRED_TYPE(bool)
910b57cec5SDimitry Andric   unsigned DotProd : 1;
92*0fca6ea1SDimitry Andric   LLVM_PREFERRED_TYPE(bool)
935ffd83dbSDimitry Andric   unsigned HasMatMul : 1;
94*0fca6ea1SDimitry Andric   LLVM_PREFERRED_TYPE(bool)
95349cc55cSDimitry Andric   unsigned FPRegsDisabled : 1;
96*0fca6ea1SDimitry Andric   LLVM_PREFERRED_TYPE(bool)
970eae32dcSDimitry Andric   unsigned HasPAC : 1;
98*0fca6ea1SDimitry Andric   LLVM_PREFERRED_TYPE(bool)
990eae32dcSDimitry Andric   unsigned HasBTI : 1;
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   enum {
1020b57cec5SDimitry Andric     LDREX_B = (1 << 0), /// byte (8-bit)
1030b57cec5SDimitry Andric     LDREX_H = (1 << 1), /// half (16-bit)
1040b57cec5SDimitry Andric     LDREX_W = (1 << 2), /// word (32-bit)
1050b57cec5SDimitry Andric     LDREX_D = (1 << 3), /// double (64-bit)
1060b57cec5SDimitry Andric   };
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric   uint32_t LDREX;
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric   // ACLE 6.5.1 Hardware floating point
1110b57cec5SDimitry Andric   enum {
1120b57cec5SDimitry Andric     HW_FP_HP = (1 << 1), /// half (16-bit)
1130b57cec5SDimitry Andric     HW_FP_SP = (1 << 2), /// single (32-bit)
1140b57cec5SDimitry Andric     HW_FP_DP = (1 << 3), /// double (64-bit)
1150b57cec5SDimitry Andric   };
1160b57cec5SDimitry Andric   uint32_t HW_FP;
1170b57cec5SDimitry Andric 
1181db9f3b2SDimitry Andric   enum {
1191db9f3b2SDimitry Andric     /// __arm_cdp __arm_ldc, __arm_ldcl, __arm_stc,
1201db9f3b2SDimitry Andric     /// __arm_stcl, __arm_mcr and __arm_mrc
1211db9f3b2SDimitry Andric     FEATURE_COPROC_B1 = (1 << 0),
1221db9f3b2SDimitry Andric     /// __arm_cdp2, __arm_ldc2, __arm_stc2, __arm_ldc2l,
1231db9f3b2SDimitry Andric     /// __arm_stc2l, __arm_mcr2 and __arm_mrc2
1241db9f3b2SDimitry Andric     FEATURE_COPROC_B2 = (1 << 1),
1251db9f3b2SDimitry Andric     /// __arm_mcrr, __arm_mrrc
1261db9f3b2SDimitry Andric     FEATURE_COPROC_B3 = (1 << 2),
1271db9f3b2SDimitry Andric     /// __arm_mcrr2,  __arm_mrrc2
1281db9f3b2SDimitry Andric     FEATURE_COPROC_B4 = (1 << 3),
1291db9f3b2SDimitry Andric   };
1301db9f3b2SDimitry Andric 
1310b57cec5SDimitry Andric   void setABIAAPCS();
1320b57cec5SDimitry Andric   void setABIAPCS(bool IsAAPCS16);
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric   void setArchInfo();
1350b57cec5SDimitry Andric   void setArchInfo(llvm::ARM::ArchKind Kind);
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric   void setAtomic();
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric   bool isThumb() const;
1400b57cec5SDimitry Andric   bool supportsThumb() const;
1410b57cec5SDimitry Andric   bool supportsThumb2() const;
1420b57cec5SDimitry Andric   bool hasMVE() const;
1430b57cec5SDimitry Andric   bool hasMVEFloat() const;
1445ffd83dbSDimitry Andric   bool hasCDE() const;
1450b57cec5SDimitry Andric 
1460b57cec5SDimitry Andric   StringRef getCPUAttr() const;
1470b57cec5SDimitry Andric   StringRef getCPUProfile() const;
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric public:
1500b57cec5SDimitry Andric   ARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric   StringRef getABI() const override;
1530b57cec5SDimitry Andric   bool setABI(const std::string &Name) override;
1540b57cec5SDimitry Andric 
1551fd87a68SDimitry Andric   bool isBranchProtectionSupportedArch(StringRef Arch) const override;
1561fd87a68SDimitry Andric   bool validateBranchProtection(StringRef Spec, StringRef Arch,
1571fd87a68SDimitry Andric                                 BranchProtectionInfo &BPI,
1581fd87a68SDimitry Andric                                 StringRef &Err) const override;
1594824e7fdSDimitry Andric 
1600b57cec5SDimitry Andric   // FIXME: This should be based on Arch attributes, not CPU names.
1610b57cec5SDimitry Andric   bool
1620b57cec5SDimitry Andric   initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
1630b57cec5SDimitry Andric                  StringRef CPU,
1640b57cec5SDimitry Andric                  const std::vector<std::string> &FeaturesVec) const override;
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric   bool isValidFeatureName(StringRef Feature) const override {
1670b57cec5SDimitry Andric     // We pass soft-float-abi in as a -target-feature, but the backend figures
1680b57cec5SDimitry Andric     // this out through other means.
1690b57cec5SDimitry Andric     return Feature != "soft-float-abi";
1700b57cec5SDimitry Andric   }
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric   bool handleTargetFeatures(std::vector<std::string> &Features,
1730b57cec5SDimitry Andric                             DiagnosticsEngine &Diags) override;
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric   bool hasFeature(StringRef Feature) const override;
1760b57cec5SDimitry Andric 
1775ffd83dbSDimitry Andric   bool hasBFloat16Type() const override;
1785ffd83dbSDimitry Andric 
1790b57cec5SDimitry Andric   bool isValidCPUName(StringRef Name) const override;
1800b57cec5SDimitry Andric   void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric   bool setCPU(const std::string &Name) override;
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric   bool setFPMath(StringRef Name) override;
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric   bool useFP16ConversionIntrinsics() const override {
1870b57cec5SDimitry Andric     return false;
1880b57cec5SDimitry Andric   }
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric   void getTargetDefinesARMV81A(const LangOptions &Opts,
1910b57cec5SDimitry Andric                                MacroBuilder &Builder) const;
1920b57cec5SDimitry Andric   void getTargetDefinesARMV82A(const LangOptions &Opts,
1930b57cec5SDimitry Andric                                MacroBuilder &Builder) const;
194480093f4SDimitry Andric   void getTargetDefinesARMV83A(const LangOptions &Opts,
195480093f4SDimitry Andric                                  MacroBuilder &Builder) const;
1960b57cec5SDimitry Andric   void getTargetDefines(const LangOptions &Opts,
1970b57cec5SDimitry Andric                         MacroBuilder &Builder) const override;
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric   ArrayRef<Builtin::Info> getTargetBuiltins() const override;
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric   bool isCLZForZeroUndef() const override;
2020b57cec5SDimitry Andric   BuiltinVaListKind getBuiltinVaListKind() const override;
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric   ArrayRef<const char *> getGCCRegNames() const override;
2050b57cec5SDimitry Andric   ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
2060b57cec5SDimitry Andric   bool validateAsmConstraint(const char *&Name,
2070b57cec5SDimitry Andric                              TargetInfo::ConstraintInfo &Info) const override;
2080b57cec5SDimitry Andric   std::string convertConstraint(const char *&Constraint) const override;
2090b57cec5SDimitry Andric   bool
2100b57cec5SDimitry Andric   validateConstraintModifier(StringRef Constraint, char Modifier, unsigned Size,
2110b57cec5SDimitry Andric                              std::string &SuggestedModifier) const override;
21206c3fb27SDimitry Andric   std::string_view getClobbers() const override;
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric   StringRef getConstraintRegister(StringRef Constraint,
2150b57cec5SDimitry Andric                                   StringRef Expression) const override {
2160b57cec5SDimitry Andric     return Expression;
2170b57cec5SDimitry Andric   }
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric   CallingConvCheckResult checkCallingConvention(CallingConv CC) const override;
2200b57cec5SDimitry Andric 
2210b57cec5SDimitry Andric   int getEHDataRegisterNumber(unsigned RegNo) const override;
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric   bool hasSjLjLowering() const override;
2245ffd83dbSDimitry Andric 
2250eae32dcSDimitry Andric   bool hasBitIntType() const override { return true; }
2265ffd83dbSDimitry Andric 
2275ffd83dbSDimitry Andric   const char *getBFloat16Mangling() const override { return "u6__bf16"; };
228*0fca6ea1SDimitry Andric 
229*0fca6ea1SDimitry Andric   std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
230*0fca6ea1SDimitry Andric     return std::make_pair(getTriple().isArch64Bit() ? 256 : 64, 64);
231*0fca6ea1SDimitry Andric   }
2320b57cec5SDimitry Andric };
2330b57cec5SDimitry Andric 
2340b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY ARMleTargetInfo : public ARMTargetInfo {
2350b57cec5SDimitry Andric public:
2360b57cec5SDimitry Andric   ARMleTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
2370b57cec5SDimitry Andric   void getTargetDefines(const LangOptions &Opts,
2380b57cec5SDimitry Andric                         MacroBuilder &Builder) const override;
2390b57cec5SDimitry Andric };
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY ARMbeTargetInfo : public ARMTargetInfo {
2420b57cec5SDimitry Andric public:
2430b57cec5SDimitry Andric   ARMbeTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
2440b57cec5SDimitry Andric   void getTargetDefines(const LangOptions &Opts,
2450b57cec5SDimitry Andric                         MacroBuilder &Builder) const override;
2460b57cec5SDimitry Andric };
2470b57cec5SDimitry Andric 
2480b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY WindowsARMTargetInfo
2490b57cec5SDimitry Andric     : public WindowsTargetInfo<ARMleTargetInfo> {
2500b57cec5SDimitry Andric   const llvm::Triple Triple;
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric public:
2530b57cec5SDimitry Andric   WindowsARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric   void getVisualStudioDefines(const LangOptions &Opts,
2560b57cec5SDimitry Andric                               MacroBuilder &Builder) const;
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric   BuiltinVaListKind getBuiltinVaListKind() const override;
2590b57cec5SDimitry Andric 
2600b57cec5SDimitry Andric   CallingConvCheckResult checkCallingConvention(CallingConv CC) const override;
2610b57cec5SDimitry Andric };
2620b57cec5SDimitry Andric 
2630b57cec5SDimitry Andric // Windows ARM + Itanium C++ ABI Target
2640b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY ItaniumWindowsARMleTargetInfo
2650b57cec5SDimitry Andric     : public WindowsARMTargetInfo {
2660b57cec5SDimitry Andric public:
2670b57cec5SDimitry Andric   ItaniumWindowsARMleTargetInfo(const llvm::Triple &Triple,
2680b57cec5SDimitry Andric                                 const TargetOptions &Opts);
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric   void getTargetDefines(const LangOptions &Opts,
2710b57cec5SDimitry Andric                         MacroBuilder &Builder) const override;
2720b57cec5SDimitry Andric };
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric // Windows ARM, MS (C++) ABI
2750b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY MicrosoftARMleTargetInfo
2760b57cec5SDimitry Andric     : public WindowsARMTargetInfo {
2770b57cec5SDimitry Andric public:
2780b57cec5SDimitry Andric   MicrosoftARMleTargetInfo(const llvm::Triple &Triple,
2790b57cec5SDimitry Andric                            const TargetOptions &Opts);
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric   void getTargetDefines(const LangOptions &Opts,
2820b57cec5SDimitry Andric                         MacroBuilder &Builder) const override;
2830b57cec5SDimitry Andric };
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric // ARM MinGW target
2860b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY MinGWARMTargetInfo : public WindowsARMTargetInfo {
2870b57cec5SDimitry Andric public:
2880b57cec5SDimitry Andric   MinGWARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
2890b57cec5SDimitry Andric 
2900b57cec5SDimitry Andric   void getTargetDefines(const LangOptions &Opts,
2910b57cec5SDimitry Andric                         MacroBuilder &Builder) const override;
2920b57cec5SDimitry Andric };
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric // ARM Cygwin target
2950b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY CygwinARMTargetInfo : public ARMleTargetInfo {
2960b57cec5SDimitry Andric public:
2970b57cec5SDimitry Andric   CygwinARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric   void getTargetDefines(const LangOptions &Opts,
3000b57cec5SDimitry Andric                         MacroBuilder &Builder) const override;
3010b57cec5SDimitry Andric };
3020b57cec5SDimitry Andric 
3030b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY DarwinARMTargetInfo
3040b57cec5SDimitry Andric     : public DarwinTargetInfo<ARMleTargetInfo> {
3050b57cec5SDimitry Andric protected:
3060b57cec5SDimitry Andric   void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
3070b57cec5SDimitry Andric                     MacroBuilder &Builder) const override;
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric public:
3100b57cec5SDimitry Andric   DarwinARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
3110b57cec5SDimitry Andric };
3120b57cec5SDimitry Andric 
3130b57cec5SDimitry Andric // 32-bit RenderScript is armv7 with width and align of 'long' set to 8-bytes
3140b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY RenderScript32TargetInfo
3150b57cec5SDimitry Andric     : public ARMleTargetInfo {
3160b57cec5SDimitry Andric public:
3170b57cec5SDimitry Andric   RenderScript32TargetInfo(const llvm::Triple &Triple,
3180b57cec5SDimitry Andric                            const TargetOptions &Opts);
3190b57cec5SDimitry Andric 
3200b57cec5SDimitry Andric   void getTargetDefines(const LangOptions &Opts,
3210b57cec5SDimitry Andric                         MacroBuilder &Builder) const override;
3220b57cec5SDimitry Andric };
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric } // namespace targets
3250b57cec5SDimitry Andric } // namespace clang
3260b57cec5SDimitry Andric 
3270b57cec5SDimitry Andric #endif // LLVM_CLANG_LIB_BASIC_TARGETS_ARM_H
328