1 //===--- Sparc.h - declare sparc target feature support ---------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file declares Sparc TargetInfo objects. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_SPARC_H 14 #define LLVM_CLANG_LIB_BASIC_TARGETS_SPARC_H 15 #include "clang/Basic/TargetInfo.h" 16 #include "clang/Basic/TargetOptions.h" 17 #include "llvm/Support/Compiler.h" 18 #include "llvm/TargetParser/Triple.h" 19 namespace clang { 20 namespace targets { 21 // Shared base class for SPARC v8 (32-bit) and SPARC v9 (64-bit). 22 class LLVM_LIBRARY_VISIBILITY SparcTargetInfo : public TargetInfo { 23 static const TargetInfo::GCCRegAlias GCCRegAliases[]; 24 static const char *const GCCRegNames[]; 25 bool SoftFloat; 26 27 public: 28 SparcTargetInfo(const llvm::Triple &Triple, const TargetOptions &) 29 : TargetInfo(Triple), SoftFloat(false) {} 30 31 int getEHDataRegisterNumber(unsigned RegNo) const override { 32 if (RegNo == 0) 33 return 24; 34 if (RegNo == 1) 35 return 25; 36 return -1; 37 } 38 39 bool handleTargetFeatures(std::vector<std::string> &Features, 40 DiagnosticsEngine &Diags) override { 41 // Check if software floating point is enabled 42 if (llvm::is_contained(Features, "+soft-float")) 43 SoftFloat = true; 44 return true; 45 } 46 void getTargetDefines(const LangOptions &Opts, 47 MacroBuilder &Builder) const override; 48 49 bool hasFeature(StringRef Feature) const override; 50 51 ArrayRef<Builtin::Info> getTargetBuiltins() const override { 52 // FIXME: Implement! 53 return std::nullopt; 54 } 55 BuiltinVaListKind getBuiltinVaListKind() const override { 56 return TargetInfo::VoidPtrBuiltinVaList; 57 } 58 ArrayRef<const char *> getGCCRegNames() const override; 59 ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override; 60 bool validateAsmConstraint(const char *&Name, 61 TargetInfo::ConstraintInfo &info) const override { 62 // FIXME: Implement! 63 switch (*Name) { 64 case 'I': // Signed 13-bit constant 65 case 'J': // Zero 66 case 'K': // 32-bit constant with the low 12 bits clear 67 case 'L': // A constant in the range supported by movcc (11-bit signed imm) 68 case 'M': // A constant in the range supported by movrcc (19-bit signed imm) 69 case 'N': // Same as 'K' but zext (required for SIMode) 70 case 'O': // The constant 4096 71 return true; 72 73 case 'f': 74 case 'e': 75 info.setAllowsRegister(); 76 return true; 77 } 78 return false; 79 } 80 std::string_view getClobbers() const override { 81 // FIXME: Implement! 82 return ""; 83 } 84 85 // No Sparc V7 for now, the backend doesn't support it anyway. 86 enum CPUKind { 87 CK_GENERIC, 88 CK_V8, 89 CK_SUPERSPARC, 90 CK_SPARCLITE, 91 CK_F934, 92 CK_HYPERSPARC, 93 CK_SPARCLITE86X, 94 CK_SPARCLET, 95 CK_TSC701, 96 CK_V9, 97 CK_ULTRASPARC, 98 CK_ULTRASPARC3, 99 CK_NIAGARA, 100 CK_NIAGARA2, 101 CK_NIAGARA3, 102 CK_NIAGARA4, 103 CK_MYRIAD2100, 104 CK_MYRIAD2150, 105 CK_MYRIAD2155, 106 CK_MYRIAD2450, 107 CK_MYRIAD2455, 108 CK_MYRIAD2x5x, 109 CK_MYRIAD2080, 110 CK_MYRIAD2085, 111 CK_MYRIAD2480, 112 CK_MYRIAD2485, 113 CK_MYRIAD2x8x, 114 CK_LEON2, 115 CK_LEON2_AT697E, 116 CK_LEON2_AT697F, 117 CK_LEON3, 118 CK_LEON3_UT699, 119 CK_LEON3_GR712RC, 120 CK_LEON4, 121 CK_LEON4_GR740 122 } CPU = CK_GENERIC; 123 124 enum CPUGeneration { 125 CG_V8, 126 CG_V9, 127 }; 128 129 CPUGeneration getCPUGeneration(CPUKind Kind) const; 130 131 CPUKind getCPUKind(StringRef Name) const; 132 133 bool isValidCPUName(StringRef Name) const override { 134 return getCPUKind(Name) != CK_GENERIC; 135 } 136 137 void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; 138 139 bool setCPU(const std::string &Name) override { 140 CPU = getCPUKind(Name); 141 return CPU != CK_GENERIC; 142 } 143 144 std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override { 145 return std::make_pair(32, 32); 146 } 147 }; 148 149 // SPARC v8 is the 32-bit mode selected by Triple::sparc. 150 class LLVM_LIBRARY_VISIBILITY SparcV8TargetInfo : public SparcTargetInfo { 151 public: 152 SparcV8TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) 153 : SparcTargetInfo(Triple, Opts) { 154 resetDataLayout("E-m:e-p:32:32-i64:64-f128:64-n32-S64"); 155 // NetBSD / OpenBSD use long (same as llvm default); everyone else uses int. 156 switch (getTriple().getOS()) { 157 default: 158 SizeType = UnsignedInt; 159 IntPtrType = SignedInt; 160 PtrDiffType = SignedInt; 161 break; 162 case llvm::Triple::NetBSD: 163 case llvm::Triple::OpenBSD: 164 SizeType = UnsignedLong; 165 IntPtrType = SignedLong; 166 PtrDiffType = SignedLong; 167 break; 168 } 169 // Up to 32 bits (V8) or 64 bits (V9) are lock-free atomic, but we're 170 // willing to do atomic ops on up to 64 bits. 171 MaxAtomicPromoteWidth = 64; 172 if (getCPUGeneration(CPU) == CG_V9) 173 MaxAtomicInlineWidth = 64; 174 else 175 // FIXME: This isn't correct for plain V8 which lacks CAS, 176 // only for LEON 3+ and Myriad. 177 MaxAtomicInlineWidth = 32; 178 } 179 180 void getTargetDefines(const LangOptions &Opts, 181 MacroBuilder &Builder) const override; 182 183 bool hasBitIntType() const override { return true; } 184 }; 185 186 // SPARCV8el is the 32-bit little-endian mode selected by Triple::sparcel. 187 class LLVM_LIBRARY_VISIBILITY SparcV8elTargetInfo : public SparcV8TargetInfo { 188 public: 189 SparcV8elTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) 190 : SparcV8TargetInfo(Triple, Opts) { 191 resetDataLayout("e-m:e-p:32:32-i64:64-f128:64-n32-S64"); 192 } 193 }; 194 195 // SPARC v9 is the 64-bit mode selected by Triple::sparcv9. 196 class LLVM_LIBRARY_VISIBILITY SparcV9TargetInfo : public SparcTargetInfo { 197 public: 198 SparcV9TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) 199 : SparcTargetInfo(Triple, Opts) { 200 // FIXME: Support Sparc quad-precision long double? 201 resetDataLayout("E-m:e-i64:64-n32:64-S128"); 202 // This is an LP64 platform. 203 LongWidth = LongAlign = PointerWidth = PointerAlign = 64; 204 205 // OpenBSD uses long long for int64_t and intmax_t. 206 if (getTriple().isOSOpenBSD()) 207 IntMaxType = SignedLongLong; 208 else 209 IntMaxType = SignedLong; 210 Int64Type = IntMaxType; 211 212 // The SPARCv8 System V ABI has long double 128-bits in size, but 64-bit 213 // aligned. The SPARCv9 SCD 2.4.1 says 16-byte aligned. 214 LongDoubleWidth = 128; 215 LongDoubleAlign = 128; 216 SuitableAlign = 128; 217 LongDoubleFormat = &llvm::APFloat::IEEEquad(); 218 MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; 219 } 220 221 void getTargetDefines(const LangOptions &Opts, 222 MacroBuilder &Builder) const override; 223 224 bool isValidCPUName(StringRef Name) const override { 225 return getCPUGeneration(SparcTargetInfo::getCPUKind(Name)) == CG_V9; 226 } 227 228 void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; 229 230 bool setCPU(const std::string &Name) override { 231 if (!SparcTargetInfo::setCPU(Name)) 232 return false; 233 return getCPUGeneration(CPU) == CG_V9; 234 } 235 236 bool hasBitIntType() const override { return true; } 237 }; 238 } // namespace targets 239 } // namespace clang 240 #endif // LLVM_CLANG_LIB_BASIC_TARGETS_SPARC_H 241