1 | //===--- Mips.cpp - Implement Mips target feature support -----------------===// |
---|---|
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 implements Mips TargetInfo objects. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "Mips.h" |
14 | #include "clang/Basic/Diagnostic.h" |
15 | #include "clang/Basic/MacroBuilder.h" |
16 | #include "clang/Basic/TargetBuiltins.h" |
17 | #include "llvm/ADT/StringSwitch.h" |
18 | |
19 | using namespace clang; |
20 | using namespace clang::targets; |
21 | |
22 | static constexpr int NumBuiltins = |
23 | clang::Mips::LastTSBuiltin - Builtin::FirstTSBuiltin; |
24 | |
25 | static constexpr llvm::StringTable BuiltinStrings = |
26 | CLANG_BUILTIN_STR_TABLE_START |
27 | #define BUILTIN CLANG_BUILTIN_STR_TABLE |
28 | #include "clang/Basic/BuiltinsMips.def" |
29 | ; |
30 | |
31 | static constexpr auto BuiltinInfos = Builtin::MakeInfos<NumBuiltins>(Infos: { |
32 | #define BUILTIN CLANG_BUILTIN_ENTRY |
33 | #define LIBBUILTIN CLANG_LIBBUILTIN_ENTRY |
34 | #include "clang/Basic/BuiltinsMips.def" |
35 | }); |
36 | |
37 | bool MipsTargetInfo::processorSupportsGPR64() const { |
38 | return llvm::StringSwitch<bool>(CPU) |
39 | .Case(S: "mips3", Value: true) |
40 | .Case(S: "mips4", Value: true) |
41 | .Case(S: "mips5", Value: true) |
42 | .Case(S: "mips64", Value: true) |
43 | .Case(S: "mips64r2", Value: true) |
44 | .Case(S: "mips64r3", Value: true) |
45 | .Case(S: "mips64r5", Value: true) |
46 | .Case(S: "mips64r6", Value: true) |
47 | .Case(S: "octeon", Value: true) |
48 | .Case(S: "octeon+", Value: true) |
49 | .Case(S: "i6400", Value: true) |
50 | .Case(S: "i6500", Value: true) |
51 | .Default(Value: false); |
52 | } |
53 | |
54 | static constexpr llvm::StringLiteral ValidCPUNames[] = { |
55 | {"mips1"}, { "mips2"}, { "mips3"}, { "mips4"}, { "mips5"}, |
56 | {"mips32"}, { "mips32r2"}, { "mips32r3"}, { "mips32r5"}, { "mips32r6"}, |
57 | {"mips64"}, { "mips64r2"}, { "mips64r3"}, { "mips64r5"}, { "mips64r6"}, |
58 | {"octeon"}, { "octeon+"}, { "p5600"}, { "i6400"}, { "i6500"}}; |
59 | |
60 | bool MipsTargetInfo::isValidCPUName(StringRef Name) const { |
61 | return llvm::is_contained(Range: ValidCPUNames, Element: Name); |
62 | } |
63 | |
64 | void MipsTargetInfo::fillValidCPUList( |
65 | SmallVectorImpl<StringRef> &Values) const { |
66 | Values.append(in_start: std::begin(arr: ValidCPUNames), in_end: std::end(arr: ValidCPUNames)); |
67 | } |
68 | |
69 | unsigned MipsTargetInfo::getISARev() const { |
70 | return llvm::StringSwitch<unsigned>(getCPU()) |
71 | .Cases(S0: "mips32", S1: "mips64", Value: 1) |
72 | .Cases(S0: "mips32r2", S1: "mips64r2", S2: "octeon", S3: "octeon+", Value: 2) |
73 | .Cases(S0: "mips32r3", S1: "mips64r3", Value: 3) |
74 | .Cases(S0: "mips32r5", S1: "mips64r5", S2: "p5600", Value: 5) |
75 | .Cases(S0: "mips32r6", S1: "mips64r6", Value: 6) |
76 | .Default(Value: 0); |
77 | } |
78 | |
79 | void MipsTargetInfo::getTargetDefines(const LangOptions &Opts, |
80 | MacroBuilder &Builder) const { |
81 | if (BigEndian) { |
82 | DefineStd(Builder, MacroName: "MIPSEB", Opts); |
83 | Builder.defineMacro(Name: "_MIPSEB"); |
84 | } else { |
85 | DefineStd(Builder, MacroName: "MIPSEL", Opts); |
86 | Builder.defineMacro(Name: "_MIPSEL"); |
87 | } |
88 | |
89 | Builder.defineMacro(Name: "__mips__"); |
90 | Builder.defineMacro(Name: "_mips"); |
91 | if (Opts.GNUMode) |
92 | Builder.defineMacro(Name: "mips"); |
93 | |
94 | if (ABI == "o32") { |
95 | Builder.defineMacro(Name: "__mips", Value: "32"); |
96 | Builder.defineMacro(Name: "_MIPS_ISA", Value: "_MIPS_ISA_MIPS32"); |
97 | } else { |
98 | Builder.defineMacro(Name: "__mips", Value: "64"); |
99 | Builder.defineMacro(Name: "__mips64"); |
100 | Builder.defineMacro(Name: "__mips64__"); |
101 | Builder.defineMacro(Name: "_MIPS_ISA", Value: "_MIPS_ISA_MIPS64"); |
102 | } |
103 | |
104 | const std::string ISARev = std::to_string(val: getISARev()); |
105 | |
106 | if (!ISARev.empty()) |
107 | Builder.defineMacro(Name: "__mips_isa_rev", Value: ISARev); |
108 | |
109 | if (ABI == "o32") { |
110 | Builder.defineMacro(Name: "__mips_o32"); |
111 | Builder.defineMacro(Name: "_ABIO32", Value: "1"); |
112 | Builder.defineMacro(Name: "_MIPS_SIM", Value: "_ABIO32"); |
113 | } else if (ABI == "n32") { |
114 | Builder.defineMacro(Name: "__mips_n32"); |
115 | Builder.defineMacro(Name: "_ABIN32", Value: "2"); |
116 | Builder.defineMacro(Name: "_MIPS_SIM", Value: "_ABIN32"); |
117 | } else if (ABI == "n64") { |
118 | Builder.defineMacro(Name: "__mips_n64"); |
119 | Builder.defineMacro(Name: "_ABI64", Value: "3"); |
120 | Builder.defineMacro(Name: "_MIPS_SIM", Value: "_ABI64"); |
121 | } else |
122 | llvm_unreachable("Invalid ABI."); |
123 | |
124 | if (!IsNoABICalls) { |
125 | Builder.defineMacro(Name: "__mips_abicalls"); |
126 | if (CanUseBSDABICalls) |
127 | Builder.defineMacro(Name: "__ABICALLS__"); |
128 | } |
129 | |
130 | Builder.defineMacro(Name: "__REGISTER_PREFIX__", Value: ""); |
131 | |
132 | switch (FloatABI) { |
133 | case HardFloat: |
134 | Builder.defineMacro(Name: "__mips_hard_float", Value: Twine(1)); |
135 | break; |
136 | case SoftFloat: |
137 | Builder.defineMacro(Name: "__mips_soft_float", Value: Twine(1)); |
138 | break; |
139 | } |
140 | |
141 | if (IsSingleFloat) |
142 | Builder.defineMacro(Name: "__mips_single_float", Value: Twine(1)); |
143 | |
144 | switch (FPMode) { |
145 | case FPXX: |
146 | Builder.defineMacro(Name: "__mips_fpr", Value: Twine(0)); |
147 | break; |
148 | case FP32: |
149 | Builder.defineMacro(Name: "__mips_fpr", Value: Twine(32)); |
150 | break; |
151 | case FP64: |
152 | Builder.defineMacro(Name: "__mips_fpr", Value: Twine(64)); |
153 | break; |
154 | } |
155 | |
156 | if (FPMode == FP64 || IsSingleFloat) |
157 | Builder.defineMacro(Name: "_MIPS_FPSET", Value: Twine(32)); |
158 | else |
159 | Builder.defineMacro(Name: "_MIPS_FPSET", Value: Twine(16)); |
160 | if (NoOddSpreg) |
161 | Builder.defineMacro(Name: "_MIPS_SPFPSET", Value: Twine(16)); |
162 | else |
163 | Builder.defineMacro(Name: "_MIPS_SPFPSET", Value: Twine(32)); |
164 | |
165 | if (IsMips16) |
166 | Builder.defineMacro(Name: "__mips16", Value: Twine(1)); |
167 | |
168 | if (IsMicromips) |
169 | Builder.defineMacro(Name: "__mips_micromips", Value: Twine(1)); |
170 | |
171 | if (IsNan2008) |
172 | Builder.defineMacro(Name: "__mips_nan2008", Value: Twine(1)); |
173 | |
174 | if (IsAbs2008) |
175 | Builder.defineMacro(Name: "__mips_abs2008", Value: Twine(1)); |
176 | |
177 | switch (DspRev) { |
178 | default: |
179 | break; |
180 | case DSP1: |
181 | Builder.defineMacro(Name: "__mips_dsp_rev", Value: Twine(1)); |
182 | Builder.defineMacro(Name: "__mips_dsp", Value: Twine(1)); |
183 | break; |
184 | case DSP2: |
185 | Builder.defineMacro(Name: "__mips_dsp_rev", Value: Twine(2)); |
186 | Builder.defineMacro(Name: "__mips_dspr2", Value: Twine(1)); |
187 | Builder.defineMacro(Name: "__mips_dsp", Value: Twine(1)); |
188 | break; |
189 | } |
190 | |
191 | if (HasMSA) |
192 | Builder.defineMacro(Name: "__mips_msa", Value: Twine(1)); |
193 | |
194 | if (DisableMadd4) |
195 | Builder.defineMacro(Name: "__mips_no_madd4", Value: Twine(1)); |
196 | |
197 | Builder.defineMacro(Name: "_MIPS_SZPTR", Value: Twine(getPointerWidth(AddrSpace: LangAS::Default))); |
198 | Builder.defineMacro(Name: "_MIPS_SZINT", Value: Twine(getIntWidth())); |
199 | Builder.defineMacro(Name: "_MIPS_SZLONG", Value: Twine(getLongWidth())); |
200 | |
201 | Builder.defineMacro(Name: "_MIPS_ARCH", Value: "\""+ CPU + "\""); |
202 | if (CPU == "octeon+") |
203 | Builder.defineMacro(Name: "_MIPS_ARCH_OCTEONP"); |
204 | else |
205 | Builder.defineMacro(Name: "_MIPS_ARCH_"+ StringRef(CPU).upper()); |
206 | |
207 | if (StringRef(CPU).starts_with(Prefix: "octeon")) |
208 | Builder.defineMacro(Name: "__OCTEON__"); |
209 | |
210 | if (CPU != "mips1") { |
211 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); |
212 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); |
213 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); |
214 | } |
215 | |
216 | // 32-bit MIPS processors don't have the necessary lld/scd instructions |
217 | // found in 64-bit processors. In the case of O32 on a 64-bit processor, |
218 | // the instructions exist but using them violates the ABI since they |
219 | // require 64-bit GPRs and O32 only supports 32-bit GPRs. |
220 | if (ABI == "n32"|| ABI == "n64") |
221 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); |
222 | } |
223 | |
224 | bool MipsTargetInfo::hasFeature(StringRef Feature) const { |
225 | return llvm::StringSwitch<bool>(Feature) |
226 | .Case(S: "mips", Value: true) |
227 | .Case(S: "dsp", Value: DspRev >= DSP1) |
228 | .Case(S: "dspr2", Value: DspRev >= DSP2) |
229 | .Case(S: "fp64", Value: FPMode == FP64) |
230 | .Case(S: "msa", Value: HasMSA) |
231 | .Default(Value: false); |
232 | } |
233 | |
234 | llvm::SmallVector<Builtin::InfosShard> |
235 | MipsTargetInfo::getTargetBuiltins() const { |
236 | return {{&BuiltinStrings, BuiltinInfos}}; |
237 | } |
238 | |
239 | unsigned MipsTargetInfo::getUnwindWordWidth() const { |
240 | return llvm::StringSwitch<unsigned>(ABI) |
241 | .Case(S: "o32", Value: 32) |
242 | .Case(S: "n32", Value: 64) |
243 | .Case(S: "n64", Value: 64) |
244 | .Default(Value: getPointerWidth(AddrSpace: LangAS::Default)); |
245 | } |
246 | |
247 | bool MipsTargetInfo::validateTarget(DiagnosticsEngine &Diags) const { |
248 | // microMIPS64R6 backend was removed. |
249 | if (getTriple().isMIPS64() && IsMicromips && (ABI == "n32"|| ABI == "n64")) { |
250 | Diags.Report(diag::err_target_unsupported_cpu_for_micromips) << CPU; |
251 | return false; |
252 | } |
253 | |
254 | // 64-bit ABI's require 64-bit CPU's. |
255 | if (!processorSupportsGPR64() && (ABI == "n32"|| ABI == "n64")) { |
256 | Diags.Report(diag::err_target_unsupported_abi) << ABI << CPU; |
257 | return false; |
258 | } |
259 | |
260 | // -fpxx is valid only for the o32 ABI |
261 | if (FPMode == FPXX && (ABI == "n32"|| ABI == "n64")) { |
262 | Diags.Report(diag::err_unsupported_abi_for_opt) << "-mfpxx"<< "o32"; |
263 | return false; |
264 | } |
265 | |
266 | // -mfp32 and n32/n64 ABIs are incompatible |
267 | if (FPMode != FP64 && FPMode != FPXX && !IsSingleFloat && |
268 | (ABI == "n32"|| ABI == "n64")) { |
269 | Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfpxx"<< CPU; |
270 | return false; |
271 | } |
272 | // Mips revision 6 and -mfp32 are incompatible |
273 | if (FPMode != FP64 && FPMode != FPXX && (CPU == "mips32r6"|| |
274 | CPU == "mips64r6")) { |
275 | Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfp32"<< CPU; |
276 | return false; |
277 | } |
278 | // Option -mfp64 permitted on Mips32 iff revision 2 or higher is present |
279 | if (FPMode == FP64 && (CPU == "mips1"|| CPU == "mips2"|| |
280 | getISARev() < 2) && ABI == "o32") { |
281 | Diags.Report(diag::err_mips_fp64_req) << "-mfp64"; |
282 | return false; |
283 | } |
284 | // FPXX requires mips2+ |
285 | if (FPMode == FPXX && CPU == "mips1") { |
286 | Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfpxx"<< CPU; |
287 | return false; |
288 | } |
289 | // -mmsa with -msoft-float makes nonsense |
290 | if (FloatABI == SoftFloat && HasMSA) { |
291 | Diags.Report(diag::err_opt_not_valid_with_opt) << "-msoft-float" |
292 | << "-mmsa"; |
293 | return false; |
294 | } |
295 | // Option -mmsa permitted on Mips32 iff revision 2 or higher is present |
296 | if (HasMSA && (CPU == "mips1"|| CPU == "mips2"|| getISARev() < 2) && |
297 | ABI == "o32") { |
298 | Diags.Report(diag::err_mips_fp64_req) << "-mmsa"; |
299 | return false; |
300 | } |
301 | // MSA requires FP64 |
302 | if (FPMode == FPXX && HasMSA) { |
303 | Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfpxx" |
304 | << "-mmsa"; |
305 | return false; |
306 | } |
307 | if (FPMode == FP32 && HasMSA) { |
308 | Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfp32" |
309 | << "-mmsa"; |
310 | return false; |
311 | } |
312 | |
313 | return true; |
314 | } |
315 | |
316 | WindowsMipsTargetInfo::WindowsMipsTargetInfo(const llvm::Triple &Triple, |
317 | const TargetOptions &Opts) |
318 | : WindowsTargetInfo<MipsTargetInfo>(Triple, Opts), Triple(Triple) {} |
319 | |
320 | void WindowsMipsTargetInfo::getVisualStudioDefines( |
321 | const LangOptions &Opts, MacroBuilder &Builder) const { |
322 | Builder.defineMacro(Name: "_M_MRX000", Value: "4000"); |
323 | } |
324 | |
325 | TargetInfo::BuiltinVaListKind |
326 | WindowsMipsTargetInfo::getBuiltinVaListKind() const { |
327 | return TargetInfo::CharPtrBuiltinVaList; |
328 | } |
329 | |
330 | TargetInfo::CallingConvCheckResult |
331 | WindowsMipsTargetInfo::checkCallingConvention(CallingConv CC) const { |
332 | switch (CC) { |
333 | case CC_X86StdCall: |
334 | case CC_X86ThisCall: |
335 | case CC_X86FastCall: |
336 | case CC_X86VectorCall: |
337 | return CCCR_Ignore; |
338 | case CC_C: |
339 | case CC_DeviceKernel: |
340 | case CC_PreserveMost: |
341 | case CC_PreserveAll: |
342 | case CC_Swift: |
343 | case CC_SwiftAsync: |
344 | return CCCR_OK; |
345 | default: |
346 | return CCCR_Warning; |
347 | } |
348 | } |
349 | |
350 | // Windows MIPS, MS (C++) ABI |
351 | MicrosoftMipsTargetInfo::MicrosoftMipsTargetInfo(const llvm::Triple &Triple, |
352 | const TargetOptions &Opts) |
353 | : WindowsMipsTargetInfo(Triple, Opts) { |
354 | TheCXXABI.set(TargetCXXABI::Microsoft); |
355 | } |
356 | |
357 | void MicrosoftMipsTargetInfo::getTargetDefines(const LangOptions &Opts, |
358 | MacroBuilder &Builder) const { |
359 | WindowsMipsTargetInfo::getTargetDefines(Opts, Builder); |
360 | WindowsMipsTargetInfo::getVisualStudioDefines(Opts, Builder); |
361 | } |
362 | |
363 | MinGWMipsTargetInfo::MinGWMipsTargetInfo(const llvm::Triple &Triple, |
364 | const TargetOptions &Opts) |
365 | : WindowsMipsTargetInfo(Triple, Opts) { |
366 | TheCXXABI.set(TargetCXXABI::GenericMIPS); |
367 | } |
368 | |
369 | void MinGWMipsTargetInfo::getTargetDefines(const LangOptions &Opts, |
370 | MacroBuilder &Builder) const { |
371 | WindowsMipsTargetInfo::getTargetDefines(Opts, Builder); |
372 | Builder.defineMacro(Name: "_MIPS_"); |
373 | } |
374 |
Definitions
- NumBuiltins
- BuiltinStrings
- BuiltinInfos
- processorSupportsGPR64
- ValidCPUNames
- isValidCPUName
- fillValidCPUList
- getISARev
- getTargetDefines
- hasFeature
- getTargetBuiltins
- getUnwindWordWidth
- validateTarget
- WindowsMipsTargetInfo
- getVisualStudioDefines
- getBuiltinVaListKind
- checkCallingConvention
- MicrosoftMipsTargetInfo
- getTargetDefines
- MinGWMipsTargetInfo
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more