xref: /freebsd/contrib/llvm-project/clang/lib/Basic/Targets/Sparc.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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:
SparcTargetInfo(const llvm::Triple & Triple,const TargetOptions &)28   SparcTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
29       : TargetInfo(Triple), SoftFloat(false) {}
30 
getEHDataRegisterNumber(unsigned RegNo)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 
handleTargetFeatures(std::vector<std::string> & Features,DiagnosticsEngine & Diags)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 
getTargetBuiltins()51   ArrayRef<Builtin::Info> getTargetBuiltins() const override {
52     // FIXME: Implement!
53     return std::nullopt;
54   }
getBuiltinVaListKind()55   BuiltinVaListKind getBuiltinVaListKind() const override {
56     return TargetInfo::VoidPtrBuiltinVaList;
57   }
58   ArrayRef<const char *> getGCCRegNames() const override;
59   ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
validateAsmConstraint(const char * & Name,TargetInfo::ConstraintInfo & info)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   }
getClobbers()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 
isValidCPUName(StringRef Name)133   bool isValidCPUName(StringRef Name) const override {
134     return getCPUKind(Name) != CK_GENERIC;
135   }
136 
137   void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
138 
setCPU(const std::string & Name)139   bool setCPU(const std::string &Name) override {
140     CPU = getCPUKind(Name);
141     return CPU != CK_GENERIC;
142   }
143 
hardwareInterferenceSizes()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:
SparcV8TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)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 
hasBitIntType()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:
SparcV8elTargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)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:
SparcV9TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)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 
isValidCPUName(StringRef Name)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 
setCPU(const std::string & Name)230   bool setCPU(const std::string &Name) override {
231     if (!SparcTargetInfo::setCPU(Name))
232       return false;
233     return getCPUGeneration(CPU) == CG_V9;
234   }
235 
hasBitIntType()236   bool hasBitIntType() const override { return true; }
237 };
238 } // namespace targets
239 } // namespace clang
240 #endif // LLVM_CLANG_LIB_BASIC_TARGETS_SPARC_H
241