xref: /freebsd/contrib/llvm-project/clang/lib/Basic/Targets/Sparc.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===--- Sparc.h - declare sparc 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 Sparc TargetInfo objects.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_SPARC_H
140b57cec5SDimitry Andric #define LLVM_CLANG_LIB_BASIC_TARGETS_SPARC_H
150b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h"
160b57cec5SDimitry Andric #include "clang/Basic/TargetOptions.h"
170b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
1806c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
190b57cec5SDimitry Andric namespace clang {
200b57cec5SDimitry Andric namespace targets {
210b57cec5SDimitry Andric // Shared base class for SPARC v8 (32-bit) and SPARC v9 (64-bit).
220b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY SparcTargetInfo : public TargetInfo {
230b57cec5SDimitry Andric   static const TargetInfo::GCCRegAlias GCCRegAliases[];
240b57cec5SDimitry Andric   static const char *const GCCRegNames[];
250b57cec5SDimitry Andric   bool SoftFloat;
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric public:
SparcTargetInfo(const llvm::Triple & Triple,const TargetOptions &)280b57cec5SDimitry Andric   SparcTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
290b57cec5SDimitry Andric       : TargetInfo(Triple), SoftFloat(false) {}
300b57cec5SDimitry Andric 
getEHDataRegisterNumber(unsigned RegNo)310b57cec5SDimitry Andric   int getEHDataRegisterNumber(unsigned RegNo) const override {
320b57cec5SDimitry Andric     if (RegNo == 0)
330b57cec5SDimitry Andric       return 24;
340b57cec5SDimitry Andric     if (RegNo == 1)
350b57cec5SDimitry Andric       return 25;
360b57cec5SDimitry Andric     return -1;
370b57cec5SDimitry Andric   }
380b57cec5SDimitry Andric 
handleTargetFeatures(std::vector<std::string> & Features,DiagnosticsEngine & Diags)390b57cec5SDimitry Andric   bool handleTargetFeatures(std::vector<std::string> &Features,
400b57cec5SDimitry Andric                             DiagnosticsEngine &Diags) override {
410b57cec5SDimitry Andric     // Check if software floating point is enabled
42349cc55cSDimitry Andric     if (llvm::is_contained(Features, "+soft-float"))
430b57cec5SDimitry Andric       SoftFloat = true;
440b57cec5SDimitry Andric     return true;
450b57cec5SDimitry Andric   }
460b57cec5SDimitry Andric   void getTargetDefines(const LangOptions &Opts,
470b57cec5SDimitry Andric                         MacroBuilder &Builder) const override;
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric   bool hasFeature(StringRef Feature) const override;
500b57cec5SDimitry Andric 
getTargetBuiltins()510b57cec5SDimitry Andric   ArrayRef<Builtin::Info> getTargetBuiltins() const override {
520b57cec5SDimitry Andric     // FIXME: Implement!
53bdd1243dSDimitry Andric     return std::nullopt;
540b57cec5SDimitry Andric   }
getBuiltinVaListKind()550b57cec5SDimitry Andric   BuiltinVaListKind getBuiltinVaListKind() const override {
560b57cec5SDimitry Andric     return TargetInfo::VoidPtrBuiltinVaList;
570b57cec5SDimitry Andric   }
580b57cec5SDimitry Andric   ArrayRef<const char *> getGCCRegNames() const override;
590b57cec5SDimitry Andric   ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
validateAsmConstraint(const char * & Name,TargetInfo::ConstraintInfo & info)600b57cec5SDimitry Andric   bool validateAsmConstraint(const char *&Name,
610b57cec5SDimitry Andric                              TargetInfo::ConstraintInfo &info) const override {
620b57cec5SDimitry Andric     // FIXME: Implement!
630b57cec5SDimitry Andric     switch (*Name) {
640b57cec5SDimitry Andric     case 'I': // Signed 13-bit constant
650b57cec5SDimitry Andric     case 'J': // Zero
660b57cec5SDimitry Andric     case 'K': // 32-bit constant with the low 12 bits clear
670b57cec5SDimitry Andric     case 'L': // A constant in the range supported by movcc (11-bit signed imm)
680b57cec5SDimitry Andric     case 'M': // A constant in the range supported by movrcc (19-bit signed imm)
690b57cec5SDimitry Andric     case 'N': // Same as 'K' but zext (required for SIMode)
700b57cec5SDimitry Andric     case 'O': // The constant 4096
710b57cec5SDimitry Andric       return true;
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric     case 'f':
740b57cec5SDimitry Andric     case 'e':
750b57cec5SDimitry Andric       info.setAllowsRegister();
760b57cec5SDimitry Andric       return true;
770b57cec5SDimitry Andric     }
780b57cec5SDimitry Andric     return false;
790b57cec5SDimitry Andric   }
getClobbers()8006c3fb27SDimitry Andric   std::string_view getClobbers() const override {
810b57cec5SDimitry Andric     // FIXME: Implement!
820b57cec5SDimitry Andric     return "";
830b57cec5SDimitry Andric   }
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   // No Sparc V7 for now, the backend doesn't support it anyway.
860b57cec5SDimitry Andric   enum CPUKind {
870b57cec5SDimitry Andric     CK_GENERIC,
880b57cec5SDimitry Andric     CK_V8,
890b57cec5SDimitry Andric     CK_SUPERSPARC,
900b57cec5SDimitry Andric     CK_SPARCLITE,
910b57cec5SDimitry Andric     CK_F934,
920b57cec5SDimitry Andric     CK_HYPERSPARC,
930b57cec5SDimitry Andric     CK_SPARCLITE86X,
940b57cec5SDimitry Andric     CK_SPARCLET,
950b57cec5SDimitry Andric     CK_TSC701,
960b57cec5SDimitry Andric     CK_V9,
970b57cec5SDimitry Andric     CK_ULTRASPARC,
980b57cec5SDimitry Andric     CK_ULTRASPARC3,
990b57cec5SDimitry Andric     CK_NIAGARA,
1000b57cec5SDimitry Andric     CK_NIAGARA2,
1010b57cec5SDimitry Andric     CK_NIAGARA3,
1020b57cec5SDimitry Andric     CK_NIAGARA4,
1030b57cec5SDimitry Andric     CK_MYRIAD2100,
1040b57cec5SDimitry Andric     CK_MYRIAD2150,
1050b57cec5SDimitry Andric     CK_MYRIAD2155,
1060b57cec5SDimitry Andric     CK_MYRIAD2450,
1070b57cec5SDimitry Andric     CK_MYRIAD2455,
1080b57cec5SDimitry Andric     CK_MYRIAD2x5x,
1090b57cec5SDimitry Andric     CK_MYRIAD2080,
1100b57cec5SDimitry Andric     CK_MYRIAD2085,
1110b57cec5SDimitry Andric     CK_MYRIAD2480,
1120b57cec5SDimitry Andric     CK_MYRIAD2485,
1130b57cec5SDimitry Andric     CK_MYRIAD2x8x,
1140b57cec5SDimitry Andric     CK_LEON2,
1150b57cec5SDimitry Andric     CK_LEON2_AT697E,
1160b57cec5SDimitry Andric     CK_LEON2_AT697F,
1170b57cec5SDimitry Andric     CK_LEON3,
1180b57cec5SDimitry Andric     CK_LEON3_UT699,
1190b57cec5SDimitry Andric     CK_LEON3_GR712RC,
1200b57cec5SDimitry Andric     CK_LEON4,
1210b57cec5SDimitry Andric     CK_LEON4_GR740
1220b57cec5SDimitry Andric   } CPU = CK_GENERIC;
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric   enum CPUGeneration {
1250b57cec5SDimitry Andric     CG_V8,
1260b57cec5SDimitry Andric     CG_V9,
1270b57cec5SDimitry Andric   };
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric   CPUGeneration getCPUGeneration(CPUKind Kind) const;
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   CPUKind getCPUKind(StringRef Name) const;
1320b57cec5SDimitry Andric 
isValidCPUName(StringRef Name)1330b57cec5SDimitry Andric   bool isValidCPUName(StringRef Name) const override {
1340b57cec5SDimitry Andric     return getCPUKind(Name) != CK_GENERIC;
1350b57cec5SDimitry Andric   }
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric   void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
1380b57cec5SDimitry Andric 
setCPU(const std::string & Name)1390b57cec5SDimitry Andric   bool setCPU(const std::string &Name) override {
1400b57cec5SDimitry Andric     CPU = getCPUKind(Name);
1410b57cec5SDimitry Andric     return CPU != CK_GENERIC;
1420b57cec5SDimitry Andric   }
143*0fca6ea1SDimitry Andric 
hardwareInterferenceSizes()144*0fca6ea1SDimitry Andric   std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
145*0fca6ea1SDimitry Andric     return std::make_pair(32, 32);
146*0fca6ea1SDimitry Andric   }
1470b57cec5SDimitry Andric };
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric // SPARC v8 is the 32-bit mode selected by Triple::sparc.
1500b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY SparcV8TargetInfo : public SparcTargetInfo {
1510b57cec5SDimitry Andric public:
SparcV8TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)1520b57cec5SDimitry Andric   SparcV8TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
1530b57cec5SDimitry Andric       : SparcTargetInfo(Triple, Opts) {
1540b57cec5SDimitry Andric     resetDataLayout("E-m:e-p:32:32-i64:64-f128:64-n32-S64");
1550b57cec5SDimitry Andric     // NetBSD / OpenBSD use long (same as llvm default); everyone else uses int.
1560b57cec5SDimitry Andric     switch (getTriple().getOS()) {
1570b57cec5SDimitry Andric     default:
1580b57cec5SDimitry Andric       SizeType = UnsignedInt;
1590b57cec5SDimitry Andric       IntPtrType = SignedInt;
1600b57cec5SDimitry Andric       PtrDiffType = SignedInt;
1610b57cec5SDimitry Andric       break;
1620b57cec5SDimitry Andric     case llvm::Triple::NetBSD:
1630b57cec5SDimitry Andric     case llvm::Triple::OpenBSD:
1640b57cec5SDimitry Andric       SizeType = UnsignedLong;
1650b57cec5SDimitry Andric       IntPtrType = SignedLong;
1660b57cec5SDimitry Andric       PtrDiffType = SignedLong;
1670b57cec5SDimitry Andric       break;
1680b57cec5SDimitry Andric     }
169e8d8bef9SDimitry Andric     // Up to 32 bits (V8) or 64 bits (V9) are lock-free atomic, but we're
170e8d8bef9SDimitry Andric     // willing to do atomic ops on up to 64 bits.
1710b57cec5SDimitry Andric     MaxAtomicPromoteWidth = 64;
172e8d8bef9SDimitry Andric     if (getCPUGeneration(CPU) == CG_V9)
173e8d8bef9SDimitry Andric       MaxAtomicInlineWidth = 64;
174e8d8bef9SDimitry Andric     else
175e8d8bef9SDimitry Andric       // FIXME: This isn't correct for plain V8 which lacks CAS,
176e8d8bef9SDimitry Andric       // only for LEON 3+ and Myriad.
1770b57cec5SDimitry Andric       MaxAtomicInlineWidth = 32;
1780b57cec5SDimitry Andric   }
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric   void getTargetDefines(const LangOptions &Opts,
1810b57cec5SDimitry Andric                         MacroBuilder &Builder) const override;
1820b57cec5SDimitry Andric 
hasBitIntType()1830eae32dcSDimitry Andric   bool hasBitIntType() const override { return true; }
1840b57cec5SDimitry Andric };
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric // SPARCV8el is the 32-bit little-endian mode selected by Triple::sparcel.
1870b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY SparcV8elTargetInfo : public SparcV8TargetInfo {
1880b57cec5SDimitry Andric public:
SparcV8elTargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)1890b57cec5SDimitry Andric   SparcV8elTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
1900b57cec5SDimitry Andric       : SparcV8TargetInfo(Triple, Opts) {
1910b57cec5SDimitry Andric     resetDataLayout("e-m:e-p:32:32-i64:64-f128:64-n32-S64");
1920b57cec5SDimitry Andric   }
1930b57cec5SDimitry Andric };
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric // SPARC v9 is the 64-bit mode selected by Triple::sparcv9.
1960b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY SparcV9TargetInfo : public SparcTargetInfo {
1970b57cec5SDimitry Andric public:
SparcV9TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)1980b57cec5SDimitry Andric   SparcV9TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
1990b57cec5SDimitry Andric       : SparcTargetInfo(Triple, Opts) {
2000b57cec5SDimitry Andric     // FIXME: Support Sparc quad-precision long double?
2010b57cec5SDimitry Andric     resetDataLayout("E-m:e-i64:64-n32:64-S128");
2020b57cec5SDimitry Andric     // This is an LP64 platform.
2030b57cec5SDimitry Andric     LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric     // OpenBSD uses long long for int64_t and intmax_t.
2060b57cec5SDimitry Andric     if (getTriple().isOSOpenBSD())
2070b57cec5SDimitry Andric       IntMaxType = SignedLongLong;
2080b57cec5SDimitry Andric     else
2090b57cec5SDimitry Andric       IntMaxType = SignedLong;
2100b57cec5SDimitry Andric     Int64Type = IntMaxType;
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric     // The SPARCv8 System V ABI has long double 128-bits in size, but 64-bit
2130b57cec5SDimitry Andric     // aligned. The SPARCv9 SCD 2.4.1 says 16-byte aligned.
2140b57cec5SDimitry Andric     LongDoubleWidth = 128;
2150b57cec5SDimitry Andric     LongDoubleAlign = 128;
216a7dea167SDimitry Andric     SuitableAlign = 128;
2170b57cec5SDimitry Andric     LongDoubleFormat = &llvm::APFloat::IEEEquad();
2180b57cec5SDimitry Andric     MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
2190b57cec5SDimitry Andric   }
2200b57cec5SDimitry Andric 
2210b57cec5SDimitry Andric   void getTargetDefines(const LangOptions &Opts,
2220b57cec5SDimitry Andric                         MacroBuilder &Builder) const override;
2230b57cec5SDimitry Andric 
isValidCPUName(StringRef Name)2240b57cec5SDimitry Andric   bool isValidCPUName(StringRef Name) const override {
2250b57cec5SDimitry Andric     return getCPUGeneration(SparcTargetInfo::getCPUKind(Name)) == CG_V9;
2260b57cec5SDimitry Andric   }
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric   void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
2290b57cec5SDimitry Andric 
setCPU(const std::string & Name)2300b57cec5SDimitry Andric   bool setCPU(const std::string &Name) override {
2310b57cec5SDimitry Andric     if (!SparcTargetInfo::setCPU(Name))
2320b57cec5SDimitry Andric       return false;
2330b57cec5SDimitry Andric     return getCPUGeneration(CPU) == CG_V9;
2340b57cec5SDimitry Andric   }
2355ffd83dbSDimitry Andric 
hasBitIntType()2360eae32dcSDimitry Andric   bool hasBitIntType() const override { return true; }
2370b57cec5SDimitry Andric };
2380b57cec5SDimitry Andric } // namespace targets
2390b57cec5SDimitry Andric } // namespace clang
2400b57cec5SDimitry Andric #endif // LLVM_CLANG_LIB_BASIC_TARGETS_SPARC_H
241