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 bool hasSjLjLowering() const override { return true; } 52 53 ArrayRef<Builtin::Info> getTargetBuiltins() const override { 54 // FIXME: Implement! 55 return None; 56 } 57 BuiltinVaListKind getBuiltinVaListKind() const override { 58 return TargetInfo::VoidPtrBuiltinVaList; 59 } 60 ArrayRef<const char *> getGCCRegNames() const override; 61 ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override; 62 bool validateAsmConstraint(const char *&Name, 63 TargetInfo::ConstraintInfo &info) const override { 64 // FIXME: Implement! 65 switch (*Name) { 66 case 'I': // Signed 13-bit constant 67 case 'J': // Zero 68 case 'K': // 32-bit constant with the low 12 bits clear 69 case 'L': // A constant in the range supported by movcc (11-bit signed imm) 70 case 'M': // A constant in the range supported by movrcc (19-bit signed imm) 71 case 'N': // Same as 'K' but zext (required for SIMode) 72 case 'O': // The constant 4096 73 return true; 74 75 case 'f': 76 case 'e': 77 info.setAllowsRegister(); 78 return true; 79 } 80 return false; 81 } 82 const char *getClobbers() const override { 83 // FIXME: Implement! 84 return ""; 85 } 86 87 // No Sparc V7 for now, the backend doesn't support it anyway. 88 enum CPUKind { 89 CK_GENERIC, 90 CK_V8, 91 CK_SUPERSPARC, 92 CK_SPARCLITE, 93 CK_F934, 94 CK_HYPERSPARC, 95 CK_SPARCLITE86X, 96 CK_SPARCLET, 97 CK_TSC701, 98 CK_V9, 99 CK_ULTRASPARC, 100 CK_ULTRASPARC3, 101 CK_NIAGARA, 102 CK_NIAGARA2, 103 CK_NIAGARA3, 104 CK_NIAGARA4, 105 CK_MYRIAD2100, 106 CK_MYRIAD2150, 107 CK_MYRIAD2155, 108 CK_MYRIAD2450, 109 CK_MYRIAD2455, 110 CK_MYRIAD2x5x, 111 CK_MYRIAD2080, 112 CK_MYRIAD2085, 113 CK_MYRIAD2480, 114 CK_MYRIAD2485, 115 CK_MYRIAD2x8x, 116 CK_LEON2, 117 CK_LEON2_AT697E, 118 CK_LEON2_AT697F, 119 CK_LEON3, 120 CK_LEON3_UT699, 121 CK_LEON3_GR712RC, 122 CK_LEON4, 123 CK_LEON4_GR740 124 } CPU = CK_GENERIC; 125 126 enum CPUGeneration { 127 CG_V8, 128 CG_V9, 129 }; 130 131 CPUGeneration getCPUGeneration(CPUKind Kind) const; 132 133 CPUKind getCPUKind(StringRef Name) const; 134 135 bool isValidCPUName(StringRef Name) const override { 136 return getCPUKind(Name) != CK_GENERIC; 137 } 138 139 void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; 140 141 bool setCPU(const std::string &Name) override { 142 CPU = getCPUKind(Name); 143 return CPU != CK_GENERIC; 144 } 145 }; 146 147 // SPARC v8 is the 32-bit mode selected by Triple::sparc. 148 class LLVM_LIBRARY_VISIBILITY SparcV8TargetInfo : public SparcTargetInfo { 149 public: 150 SparcV8TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) 151 : SparcTargetInfo(Triple, Opts) { 152 resetDataLayout("E-m:e-p:32:32-i64:64-f128:64-n32-S64"); 153 // NetBSD / OpenBSD use long (same as llvm default); everyone else uses int. 154 switch (getTriple().getOS()) { 155 default: 156 SizeType = UnsignedInt; 157 IntPtrType = SignedInt; 158 PtrDiffType = SignedInt; 159 break; 160 case llvm::Triple::NetBSD: 161 case llvm::Triple::OpenBSD: 162 SizeType = UnsignedLong; 163 IntPtrType = SignedLong; 164 PtrDiffType = SignedLong; 165 break; 166 } 167 // Up to 32 bits (V8) or 64 bits (V9) are lock-free atomic, but we're 168 // willing to do atomic ops on up to 64 bits. 169 MaxAtomicPromoteWidth = 64; 170 if (getCPUGeneration(CPU) == CG_V9) 171 MaxAtomicInlineWidth = 64; 172 else 173 // FIXME: This isn't correct for plain V8 which lacks CAS, 174 // only for LEON 3+ and Myriad. 175 MaxAtomicInlineWidth = 32; 176 } 177 178 void getTargetDefines(const LangOptions &Opts, 179 MacroBuilder &Builder) const override; 180 181 bool hasSjLjLowering() const override { return true; } 182 bool hasExtIntType() const override { return true; } 183 }; 184 185 // SPARCV8el is the 32-bit little-endian mode selected by Triple::sparcel. 186 class LLVM_LIBRARY_VISIBILITY SparcV8elTargetInfo : public SparcV8TargetInfo { 187 public: 188 SparcV8elTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) 189 : SparcV8TargetInfo(Triple, Opts) { 190 resetDataLayout("e-m:e-p:32:32-i64:64-f128:64-n32-S64"); 191 } 192 }; 193 194 // SPARC v9 is the 64-bit mode selected by Triple::sparcv9. 195 class LLVM_LIBRARY_VISIBILITY SparcV9TargetInfo : public SparcTargetInfo { 196 public: 197 SparcV9TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) 198 : SparcTargetInfo(Triple, Opts) { 199 // FIXME: Support Sparc quad-precision long double? 200 resetDataLayout("E-m:e-i64:64-n32:64-S128"); 201 // This is an LP64 platform. 202 LongWidth = LongAlign = PointerWidth = PointerAlign = 64; 203 204 // OpenBSD uses long long for int64_t and intmax_t. 205 if (getTriple().isOSOpenBSD()) 206 IntMaxType = SignedLongLong; 207 else 208 IntMaxType = SignedLong; 209 Int64Type = IntMaxType; 210 211 // The SPARCv8 System V ABI has long double 128-bits in size, but 64-bit 212 // aligned. The SPARCv9 SCD 2.4.1 says 16-byte aligned. 213 LongDoubleWidth = 128; 214 LongDoubleAlign = 128; 215 SuitableAlign = 128; 216 LongDoubleFormat = &llvm::APFloat::IEEEquad(); 217 MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; 218 } 219 220 void getTargetDefines(const LangOptions &Opts, 221 MacroBuilder &Builder) const override; 222 223 bool isValidCPUName(StringRef Name) const override { 224 return getCPUGeneration(SparcTargetInfo::getCPUKind(Name)) == CG_V9; 225 } 226 227 void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; 228 229 bool setCPU(const std::string &Name) override { 230 if (!SparcTargetInfo::setCPU(Name)) 231 return false; 232 return getCPUGeneration(CPU) == CG_V9; 233 } 234 235 bool hasExtIntType() const override { return true; } 236 }; 237 } // namespace targets 238 } // namespace clang 239 #endif // LLVM_CLANG_LIB_BASIC_TARGETS_SPARC_H 240