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/ADT/Triple.h" 18 #include "llvm/Support/Compiler.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 const char *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 145 // SPARC v8 is the 32-bit mode selected by Triple::sparc. 146 class LLVM_LIBRARY_VISIBILITY SparcV8TargetInfo : public SparcTargetInfo { 147 public: 148 SparcV8TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) 149 : SparcTargetInfo(Triple, Opts) { 150 resetDataLayout("E-m:e-p:32:32-i64:64-f128:64-n32-S64"); 151 // NetBSD / OpenBSD use long (same as llvm default); everyone else uses int. 152 switch (getTriple().getOS()) { 153 default: 154 SizeType = UnsignedInt; 155 IntPtrType = SignedInt; 156 PtrDiffType = SignedInt; 157 break; 158 case llvm::Triple::NetBSD: 159 case llvm::Triple::OpenBSD: 160 SizeType = UnsignedLong; 161 IntPtrType = SignedLong; 162 PtrDiffType = SignedLong; 163 break; 164 } 165 // Up to 32 bits (V8) or 64 bits (V9) are lock-free atomic, but we're 166 // willing to do atomic ops on up to 64 bits. 167 MaxAtomicPromoteWidth = 64; 168 if (getCPUGeneration(CPU) == CG_V9) 169 MaxAtomicInlineWidth = 64; 170 else 171 // FIXME: This isn't correct for plain V8 which lacks CAS, 172 // only for LEON 3+ and Myriad. 173 MaxAtomicInlineWidth = 32; 174 } 175 176 void getTargetDefines(const LangOptions &Opts, 177 MacroBuilder &Builder) const override; 178 179 bool hasBitIntType() const override { return true; } 180 }; 181 182 // SPARCV8el is the 32-bit little-endian mode selected by Triple::sparcel. 183 class LLVM_LIBRARY_VISIBILITY SparcV8elTargetInfo : public SparcV8TargetInfo { 184 public: 185 SparcV8elTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) 186 : SparcV8TargetInfo(Triple, Opts) { 187 resetDataLayout("e-m:e-p:32:32-i64:64-f128:64-n32-S64"); 188 } 189 }; 190 191 // SPARC v9 is the 64-bit mode selected by Triple::sparcv9. 192 class LLVM_LIBRARY_VISIBILITY SparcV9TargetInfo : public SparcTargetInfo { 193 public: 194 SparcV9TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) 195 : SparcTargetInfo(Triple, Opts) { 196 // FIXME: Support Sparc quad-precision long double? 197 resetDataLayout("E-m:e-i64:64-n32:64-S128"); 198 // This is an LP64 platform. 199 LongWidth = LongAlign = PointerWidth = PointerAlign = 64; 200 201 // OpenBSD uses long long for int64_t and intmax_t. 202 if (getTriple().isOSOpenBSD()) 203 IntMaxType = SignedLongLong; 204 else 205 IntMaxType = SignedLong; 206 Int64Type = IntMaxType; 207 208 // The SPARCv8 System V ABI has long double 128-bits in size, but 64-bit 209 // aligned. The SPARCv9 SCD 2.4.1 says 16-byte aligned. 210 LongDoubleWidth = 128; 211 LongDoubleAlign = 128; 212 SuitableAlign = 128; 213 LongDoubleFormat = &llvm::APFloat::IEEEquad(); 214 MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; 215 } 216 217 void getTargetDefines(const LangOptions &Opts, 218 MacroBuilder &Builder) const override; 219 220 bool isValidCPUName(StringRef Name) const override { 221 return getCPUGeneration(SparcTargetInfo::getCPUKind(Name)) == CG_V9; 222 } 223 224 void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; 225 226 bool setCPU(const std::string &Name) override { 227 if (!SparcTargetInfo::setCPU(Name)) 228 return false; 229 return getCPUGeneration(CPU) == CG_V9; 230 } 231 232 bool hasBitIntType() const override { return true; } 233 }; 234 } // namespace targets 235 } // namespace clang 236 #endif // LLVM_CLANG_LIB_BASIC_TARGETS_SPARC_H 237