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