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 auto Feature = llvm::find(Features, "+soft-float"); 43 if (Feature != Features.end()) { 44 SoftFloat = true; 45 } 46 return true; 47 } 48 void getTargetDefines(const LangOptions &Opts, 49 MacroBuilder &Builder) const override; 50 51 bool hasFeature(StringRef Feature) const override; 52 53 bool hasSjLjLowering() const override { return true; } 54 55 ArrayRef<Builtin::Info> getTargetBuiltins() const override { 56 // FIXME: Implement! 57 return None; 58 } 59 BuiltinVaListKind getBuiltinVaListKind() const override { 60 return TargetInfo::VoidPtrBuiltinVaList; 61 } 62 ArrayRef<const char *> getGCCRegNames() const override; 63 ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override; 64 bool validateAsmConstraint(const char *&Name, 65 TargetInfo::ConstraintInfo &info) const override { 66 // FIXME: Implement! 67 switch (*Name) { 68 case 'I': // Signed 13-bit constant 69 case 'J': // Zero 70 case 'K': // 32-bit constant with the low 12 bits clear 71 case 'L': // A constant in the range supported by movcc (11-bit signed imm) 72 case 'M': // A constant in the range supported by movrcc (19-bit signed imm) 73 case 'N': // Same as 'K' but zext (required for SIMode) 74 case 'O': // The constant 4096 75 return true; 76 77 case 'f': 78 case 'e': 79 info.setAllowsRegister(); 80 return true; 81 } 82 return false; 83 } 84 const char *getClobbers() const override { 85 // FIXME: Implement! 86 return ""; 87 } 88 89 // No Sparc V7 for now, the backend doesn't support it anyway. 90 enum CPUKind { 91 CK_GENERIC, 92 CK_V8, 93 CK_SUPERSPARC, 94 CK_SPARCLITE, 95 CK_F934, 96 CK_HYPERSPARC, 97 CK_SPARCLITE86X, 98 CK_SPARCLET, 99 CK_TSC701, 100 CK_V9, 101 CK_ULTRASPARC, 102 CK_ULTRASPARC3, 103 CK_NIAGARA, 104 CK_NIAGARA2, 105 CK_NIAGARA3, 106 CK_NIAGARA4, 107 CK_MYRIAD2100, 108 CK_MYRIAD2150, 109 CK_MYRIAD2155, 110 CK_MYRIAD2450, 111 CK_MYRIAD2455, 112 CK_MYRIAD2x5x, 113 CK_MYRIAD2080, 114 CK_MYRIAD2085, 115 CK_MYRIAD2480, 116 CK_MYRIAD2485, 117 CK_MYRIAD2x8x, 118 CK_LEON2, 119 CK_LEON2_AT697E, 120 CK_LEON2_AT697F, 121 CK_LEON3, 122 CK_LEON3_UT699, 123 CK_LEON3_GR712RC, 124 CK_LEON4, 125 CK_LEON4_GR740 126 } CPU = CK_GENERIC; 127 128 enum CPUGeneration { 129 CG_V8, 130 CG_V9, 131 }; 132 133 CPUGeneration getCPUGeneration(CPUKind Kind) const; 134 135 CPUKind getCPUKind(StringRef Name) const; 136 137 bool isValidCPUName(StringRef Name) const override { 138 return getCPUKind(Name) != CK_GENERIC; 139 } 140 141 void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; 142 143 bool setCPU(const std::string &Name) override { 144 CPU = getCPUKind(Name); 145 return CPU != CK_GENERIC; 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 hasSjLjLowering() const override { return true; } 184 bool hasExtIntType() const override { return true; } 185 }; 186 187 // SPARCV8el is the 32-bit little-endian mode selected by Triple::sparcel. 188 class LLVM_LIBRARY_VISIBILITY SparcV8elTargetInfo : public SparcV8TargetInfo { 189 public: 190 SparcV8elTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) 191 : SparcV8TargetInfo(Triple, Opts) { 192 resetDataLayout("e-m:e-p:32:32-i64:64-f128:64-n32-S64"); 193 } 194 }; 195 196 // SPARC v9 is the 64-bit mode selected by Triple::sparcv9. 197 class LLVM_LIBRARY_VISIBILITY SparcV9TargetInfo : public SparcTargetInfo { 198 public: 199 SparcV9TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) 200 : SparcTargetInfo(Triple, Opts) { 201 // FIXME: Support Sparc quad-precision long double? 202 resetDataLayout("E-m:e-i64:64-n32:64-S128"); 203 // This is an LP64 platform. 204 LongWidth = LongAlign = PointerWidth = PointerAlign = 64; 205 206 // OpenBSD uses long long for int64_t and intmax_t. 207 if (getTriple().isOSOpenBSD()) 208 IntMaxType = SignedLongLong; 209 else 210 IntMaxType = SignedLong; 211 Int64Type = IntMaxType; 212 213 // The SPARCv8 System V ABI has long double 128-bits in size, but 64-bit 214 // aligned. The SPARCv9 SCD 2.4.1 says 16-byte aligned. 215 LongDoubleWidth = 128; 216 LongDoubleAlign = 128; 217 SuitableAlign = 128; 218 LongDoubleFormat = &llvm::APFloat::IEEEquad(); 219 MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; 220 } 221 222 void getTargetDefines(const LangOptions &Opts, 223 MacroBuilder &Builder) const override; 224 225 bool isValidCPUName(StringRef Name) const override { 226 return getCPUGeneration(SparcTargetInfo::getCPUKind(Name)) == CG_V9; 227 } 228 229 void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; 230 231 bool setCPU(const std::string &Name) override { 232 if (!SparcTargetInfo::setCPU(Name)) 233 return false; 234 return getCPUGeneration(CPU) == CG_V9; 235 } 236 237 bool hasExtIntType() const override { return true; } 238 }; 239 } // namespace targets 240 } // namespace clang 241 #endif // LLVM_CLANG_LIB_BASIC_TARGETS_SPARC_H 242