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: |
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 | ArrayRef<Builtin::Info> getTargetBuiltins() const override { |
52 | // FIXME: Implement! |
53 | return std::nullopt; |
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 | } 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 | |
133 | bool isValidCPUName(StringRef Name) const override { |
134 | return getCPUKind(Name) != CK_GENERIC; |
135 | } |
136 | |
137 | void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; |
138 | |
139 | bool setCPU(const std::string &Name) override { |
140 | CPU = getCPUKind(Name); |
141 | return CPU != CK_GENERIC; |
142 | } |
143 | |
144 | std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override { |
145 | return std::make_pair(x: 32, y: 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: |
152 | SparcV8TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) |
153 | : SparcTargetInfo(Triple, Opts) { |
154 | resetDataLayout(DL: "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(Kind: 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 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: |
189 | SparcV8elTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) |
190 | : SparcV8TargetInfo(Triple, Opts) { |
191 | resetDataLayout(DL: "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: |
198 | SparcV9TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) |
199 | : SparcTargetInfo(Triple, Opts) { |
200 | // FIXME: Support Sparc quad-precision long double? |
201 | resetDataLayout(DL: "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 | |
224 | bool isValidCPUName(StringRef Name) const override { |
225 | return getCPUGeneration(Kind: SparcTargetInfo::getCPUKind(Name)) == CG_V9; |
226 | } |
227 | |
228 | void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; |
229 | |
230 | bool setCPU(const std::string &Name) override { |
231 | if (!SparcTargetInfo::setCPU(Name)) |
232 | return false; |
233 | return getCPUGeneration(Kind: CPU) == CG_V9; |
234 | } |
235 | |
236 | bool hasBitIntType() const override { return true; } |
237 | }; |
238 | } // namespace targets |
239 | } // namespace clang |
240 | #endif // LLVM_CLANG_LIB_BASIC_TARGETS_SPARC_H |
241 | |