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