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"
19namespace clang {
20namespace targets {
21// Shared base class for SPARC v8 (32-bit) and SPARC v9 (64-bit).
22class LLVM_LIBRARY_VISIBILITY SparcTargetInfo : public TargetInfo {
23 static const TargetInfo::GCCRegAlias GCCRegAliases[];
24 static const char *const GCCRegNames[];
25 bool SoftFloat;
26
27public:
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(Range&: Features, Element: "+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 llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override {
52 // FIXME: Implement!
53 return {};
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 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 CK_LEON5,
123 } CPU = CK_GENERIC;
124
125 enum CPUGeneration {
126 CG_V8,
127 CG_V9,
128 };
129
130 CPUGeneration getCPUGeneration(CPUKind Kind) const;
131
132 CPUKind getCPUKind(StringRef Name) const;
133
134 bool isValidCPUName(StringRef Name) const override {
135 return getCPUKind(Name) != CK_GENERIC;
136 }
137
138 void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
139
140 bool setCPU(StringRef Name) override {
141 CPU = getCPUKind(Name);
142 return CPU != CK_GENERIC;
143 }
144
145 std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
146 return std::make_pair(x: 32, y: 32);
147 }
148};
149
150// SPARC v8 is the 32-bit mode selected by Triple::sparc.
151class LLVM_LIBRARY_VISIBILITY SparcV8TargetInfo : public SparcTargetInfo {
152public:
153 SparcV8TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
154 : SparcTargetInfo(Triple, Opts) {
155 resetDataLayout();
156 // NetBSD / OpenBSD use long (same as llvm default); everyone else uses int.
157 switch (getTriple().getOS()) {
158 default:
159 SizeType = UnsignedInt;
160 IntPtrType = SignedInt;
161 PtrDiffType = SignedInt;
162 break;
163 case llvm::Triple::NetBSD:
164 case llvm::Triple::OpenBSD:
165 SizeType = UnsignedLong;
166 IntPtrType = SignedLong;
167 PtrDiffType = SignedLong;
168 break;
169 }
170
171 // The SPARCv8 System V ABI has long double 128-bits in size, but 64-bit
172 // aligned.
173 LongDoubleWidth = 128;
174 LongDoubleAlign = 64;
175 LongDoubleFormat = &llvm::APFloat::IEEEquad();
176
177 // Up to 32 bits (V8) or 64 bits (V9) are lock-free atomic, but we're
178 // willing to do atomic ops on up to 64 bits.
179 MaxAtomicPromoteWidth = 64;
180 if (getCPUGeneration(Kind: CPU) == CG_V9)
181 MaxAtomicInlineWidth = 64;
182 else
183 // FIXME: This isn't correct for plain V8 which lacks CAS,
184 // only for LEON 3+ and Myriad.
185 MaxAtomicInlineWidth = 32;
186 }
187
188 void getTargetDefines(const LangOptions &Opts,
189 MacroBuilder &Builder) const override;
190
191 bool hasBitIntType() const override { return true; }
192};
193
194// SPARCV8el is the 32-bit little-endian mode selected by Triple::sparcel.
195class LLVM_LIBRARY_VISIBILITY SparcV8elTargetInfo : public SparcV8TargetInfo {
196public:
197 SparcV8elTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
198 : SparcV8TargetInfo(Triple, Opts) {
199 resetDataLayout();
200 }
201};
202
203// SPARC v9 is the 64-bit mode selected by Triple::sparcv9.
204class LLVM_LIBRARY_VISIBILITY SparcV9TargetInfo : public SparcTargetInfo {
205public:
206 SparcV9TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
207 : SparcTargetInfo(Triple, Opts) {
208 // FIXME: Support Sparc quad-precision long double?
209 resetDataLayout();
210 // This is an LP64 platform.
211 LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
212
213 // OpenBSD uses long long for int64_t and intmax_t.
214 if (getTriple().isOSOpenBSD())
215 IntMaxType = SignedLongLong;
216 else
217 IntMaxType = SignedLong;
218 Int64Type = IntMaxType;
219
220 // The SPARCv8 System V ABI has long double 128-bits in size, but 64-bit
221 // aligned. The SPARCv9 SCD 2.4.1 says 16-byte aligned.
222 LongDoubleWidth = 128;
223 LongDoubleAlign = 128;
224 SuitableAlign = 128;
225 LongDoubleFormat = &llvm::APFloat::IEEEquad();
226 MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
227 }
228
229 void getTargetDefines(const LangOptions &Opts,
230 MacroBuilder &Builder) const override;
231
232 bool isValidCPUName(StringRef Name) const override {
233 return getCPUGeneration(Kind: SparcTargetInfo::getCPUKind(Name)) == CG_V9;
234 }
235
236 void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
237
238 bool setCPU(StringRef Name) override {
239 if (!SparcTargetInfo::setCPU(Name))
240 return false;
241 return getCPUGeneration(Kind: CPU) == CG_V9;
242 }
243
244 bool hasBitIntType() const override { return true; }
245};
246} // namespace targets
247} // namespace clang
248#endif // LLVM_CLANG_LIB_BASIC_TARGETS_SPARC_H
249