/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Driver/ToolChains/Arch/Mips.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- Mips.cpp - Tools Implementations -----------------------*- 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 | | #include "Mips.h" |
10 | | #include "ToolChains/CommonArgs.h" |
11 | | #include "clang/Driver/Driver.h" |
12 | | #include "clang/Driver/DriverDiagnostic.h" |
13 | | #include "clang/Driver/Options.h" |
14 | | #include "llvm/ADT/StringSwitch.h" |
15 | | #include "llvm/Option/ArgList.h" |
16 | | |
17 | | using namespace clang::driver; |
18 | | using namespace clang::driver::tools; |
19 | | using namespace clang; |
20 | | using namespace llvm::opt; |
21 | | |
22 | | // Get CPU and ABI names. They are not independent |
23 | | // so we have to calculate them together. |
24 | | void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple, |
25 | 2.53k | StringRef &CPUName, StringRef &ABIName) { |
26 | 2.53k | const char *DefMips32CPU = "mips32r2"; |
27 | 2.53k | const char *DefMips64CPU = "mips64r2"; |
28 | | |
29 | | // MIPS32r6 is the default for mips(el)?-img-linux-gnu and MIPS64r6 is the |
30 | | // default for mips64(el)?-img-linux-gnu. |
31 | 2.53k | if (Triple.getVendor() == llvm::Triple::ImaginationTechnologies && |
32 | 2.53k | Triple.isGNUEnvironment()88 ) { |
33 | 88 | DefMips32CPU = "mips32r6"; |
34 | 88 | DefMips64CPU = "mips64r6"; |
35 | 88 | } |
36 | | |
37 | 2.53k | if (Triple.getSubArch() == llvm::Triple::MipsSubArch_r6) { |
38 | 40 | DefMips32CPU = "mips32r6"; |
39 | 40 | DefMips64CPU = "mips64r6"; |
40 | 40 | } |
41 | | |
42 | | // MIPS3 is the default for mips64*-unknown-openbsd. |
43 | 2.53k | if (Triple.isOSOpenBSD()) |
44 | 63 | DefMips64CPU = "mips3"; |
45 | | |
46 | | // MIPS2 is the default for mips(el)?-unknown-freebsd. |
47 | | // MIPS3 is the default for mips64(el)?-unknown-freebsd. |
48 | 2.53k | if (Triple.isOSFreeBSD()) { |
49 | 239 | DefMips32CPU = "mips2"; |
50 | 239 | DefMips64CPU = "mips3"; |
51 | 239 | } |
52 | | |
53 | 2.53k | if (Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ, |
54 | 2.53k | options::OPT_mcpu_EQ)) |
55 | 502 | CPUName = A->getValue(); |
56 | | |
57 | 2.53k | if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { |
58 | 290 | ABIName = A->getValue(); |
59 | | // Convert a GNU style Mips ABI name to the name |
60 | | // accepted by LLVM Mips backend. |
61 | 290 | ABIName = llvm::StringSwitch<llvm::StringRef>(ABIName) |
62 | 290 | .Case("32", "o32") |
63 | 290 | .Case("64", "n64") |
64 | 290 | .Default(ABIName); |
65 | 290 | } |
66 | | |
67 | | // Setup default CPU and ABI names. |
68 | 2.53k | if (CPUName.empty() && ABIName.empty()2.03k ) { |
69 | 1.79k | switch (Triple.getArch()) { |
70 | 0 | default: |
71 | 0 | llvm_unreachable("Unexpected triple arch name"); |
72 | 1.19k | case llvm::Triple::mips: |
73 | 1.40k | case llvm::Triple::mipsel: |
74 | 1.40k | CPUName = DefMips32CPU; |
75 | 1.40k | break; |
76 | 208 | case llvm::Triple::mips64: |
77 | 392 | case llvm::Triple::mips64el: |
78 | 392 | CPUName = DefMips64CPU; |
79 | 392 | break; |
80 | 1.79k | } |
81 | 1.79k | } |
82 | | |
83 | 2.53k | if (ABIName.empty() && (Triple.getEnvironment() == llvm::Triple::GNUABIN32)2.24k ) |
84 | 27 | ABIName = "n32"; |
85 | | |
86 | 2.53k | if (ABIName.empty() && |
87 | 2.53k | (2.22k Triple.getVendor() == llvm::Triple::MipsTechnologies2.22k || |
88 | 2.22k | Triple.getVendor() == llvm::Triple::ImaginationTechnologies2.05k )) { |
89 | 251 | ABIName = llvm::StringSwitch<const char *>(CPUName) |
90 | 251 | .Case("mips1", "o32") |
91 | 251 | .Case("mips2", "o32") |
92 | 251 | .Case("mips3", "n64") |
93 | 251 | .Case("mips4", "n64") |
94 | 251 | .Case("mips5", "n64") |
95 | 251 | .Case("mips32", "o32") |
96 | 251 | .Case("mips32r2", "o32") |
97 | 251 | .Case("mips32r3", "o32") |
98 | 251 | .Case("mips32r5", "o32") |
99 | 251 | .Case("mips32r6", "o32") |
100 | 251 | .Case("mips64", "n64") |
101 | 251 | .Case("mips64r2", "n64") |
102 | 251 | .Case("mips64r3", "n64") |
103 | 251 | .Case("mips64r5", "n64") |
104 | 251 | .Case("mips64r6", "n64") |
105 | 251 | .Case("octeon", "n64") |
106 | 251 | .Case("p5600", "o32") |
107 | 251 | .Default(""); |
108 | 251 | } |
109 | | |
110 | 2.53k | if (ABIName.empty()) { |
111 | | // Deduce ABI name from the target triple. |
112 | 1.97k | ABIName = Triple.isMIPS32() ? "o32"1.41k : "n64"559 ; |
113 | 1.97k | } |
114 | | |
115 | 2.53k | if (CPUName.empty()) { |
116 | | // Deduce CPU name from ABI name. |
117 | 245 | CPUName = llvm::StringSwitch<const char *>(ABIName) |
118 | 245 | .Case("o32", DefMips32CPU) |
119 | 245 | .Cases("n32", "n64", DefMips64CPU) |
120 | 245 | .Default(""); |
121 | 245 | } |
122 | | |
123 | | // FIXME: Warn on inconsistent use of -march and -mabi. |
124 | 2.53k | } |
125 | | |
126 | | std::string mips::getMipsABILibSuffix(const ArgList &Args, |
127 | 51 | const llvm::Triple &Triple) { |
128 | 51 | StringRef CPUName, ABIName; |
129 | 51 | tools::mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName); |
130 | 51 | return llvm::StringSwitch<std::string>(ABIName) |
131 | 51 | .Case("o32", "") |
132 | 51 | .Case("n32", "32") |
133 | 51 | .Case("n64", "64"); |
134 | 51 | } |
135 | | |
136 | | // Convert ABI name to the GNU tools acceptable variant. |
137 | 543 | StringRef mips::getGnuCompatibleMipsABIName(StringRef ABI) { |
138 | 543 | return llvm::StringSwitch<llvm::StringRef>(ABI) |
139 | 543 | .Case("o32", "32") |
140 | 543 | .Case("n64", "64") |
141 | 543 | .Default(ABI); |
142 | 543 | } |
143 | | |
144 | | // Select the MIPS float ABI as determined by -msoft-float, -mhard-float, |
145 | | // and -mfloat-abi=. |
146 | | mips::FloatABI mips::getMipsFloatABI(const Driver &D, const ArgList &Args, |
147 | 862 | const llvm::Triple &Triple) { |
148 | 862 | mips::FloatABI ABI = mips::FloatABI::Invalid; |
149 | 862 | if (Arg *A = |
150 | 862 | Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, |
151 | 862 | options::OPT_mfloat_abi_EQ)) { |
152 | 91 | if (A->getOption().matches(options::OPT_msoft_float)) |
153 | 49 | ABI = mips::FloatABI::Soft; |
154 | 42 | else if (A->getOption().matches(options::OPT_mhard_float)) |
155 | 34 | ABI = mips::FloatABI::Hard; |
156 | 8 | else { |
157 | 8 | ABI = llvm::StringSwitch<mips::FloatABI>(A->getValue()) |
158 | 8 | .Case("soft", mips::FloatABI::Soft) |
159 | 8 | .Case("hard", mips::FloatABI::Hard) |
160 | 8 | .Default(mips::FloatABI::Invalid); |
161 | 8 | if (ABI == mips::FloatABI::Invalid && !StringRef(A->getValue()).empty()0 ) { |
162 | 0 | D.Diag(clang::diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args); |
163 | 0 | ABI = mips::FloatABI::Hard; |
164 | 0 | } |
165 | 8 | } |
166 | 91 | } |
167 | | |
168 | | // If unspecified, choose the default based on the platform. |
169 | 862 | if (ABI == mips::FloatABI::Invalid) { |
170 | 771 | if (Triple.isOSFreeBSD()) { |
171 | | // For FreeBSD, assume "soft" on all flavors of MIPS. |
172 | 82 | ABI = mips::FloatABI::Soft; |
173 | 689 | } else { |
174 | | // Assume "hard", because it's a default value used by gcc. |
175 | | // When we start to recognize specific target MIPS processors, |
176 | | // we will be able to select the default more correctly. |
177 | 689 | ABI = mips::FloatABI::Hard; |
178 | 689 | } |
179 | 771 | } |
180 | | |
181 | 862 | assert(ABI != mips::FloatABI::Invalid && "must select an ABI"); |
182 | 862 | return ABI; |
183 | 862 | } |
184 | | |
185 | | void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple, |
186 | | const ArgList &Args, |
187 | 437 | std::vector<StringRef> &Features) { |
188 | 437 | StringRef CPUName; |
189 | 437 | StringRef ABIName; |
190 | 437 | getMipsCPUAndABI(Args, Triple, CPUName, ABIName); |
191 | 437 | ABIName = getGnuCompatibleMipsABIName(ABIName); |
192 | | |
193 | | // Historically, PIC code for MIPS was associated with -mabicalls, a.k.a |
194 | | // SVR4 abicalls. Static code does not use SVR4 calling sequences. An ABI |
195 | | // extension was developed by Richard Sandiford & Code Sourcery to support |
196 | | // static code calling PIC code (CPIC). For O32 and N32 this means we have |
197 | | // several combinations of PIC/static and abicalls. Pure static, static |
198 | | // with the CPIC extension, and pure PIC code. |
199 | | |
200 | | // At final link time, O32 and N32 with CPIC will have another section |
201 | | // added to the binary which contains the stub functions to perform |
202 | | // any fixups required for PIC code. |
203 | | |
204 | | // For N64, the situation is more regular: code can either be static |
205 | | // (non-abicalls) or PIC (abicalls). GCC has traditionally picked PIC code |
206 | | // code for N64. Since Clang has already built the relocation model portion |
207 | | // of the commandline, we pick add +noabicalls feature in the N64 static |
208 | | // case. |
209 | | |
210 | | // The is another case to be accounted for: -msym32, which enforces that all |
211 | | // symbols have 32 bits in size. In this case, N64 can in theory use CPIC |
212 | | // but it is unsupported. |
213 | | |
214 | | // The combinations for N64 are: |
215 | | // a) Static without abicalls and 64bit symbols. |
216 | | // b) Static with abicalls and 32bit symbols. |
217 | | // c) PIC with abicalls and 64bit symbols. |
218 | | |
219 | | // For case (a) we need to add +noabicalls for N64. |
220 | | |
221 | 437 | bool IsN64 = ABIName == "64"; |
222 | 437 | bool IsPIC = false; |
223 | 437 | bool NonPIC = false; |
224 | | |
225 | 437 | Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC, |
226 | 437 | options::OPT_fpic, options::OPT_fno_pic, |
227 | 437 | options::OPT_fPIE, options::OPT_fno_PIE, |
228 | 437 | options::OPT_fpie, options::OPT_fno_pie); |
229 | 437 | if (LastPICArg) { |
230 | 71 | Option O = LastPICArg->getOption(); |
231 | 71 | NonPIC = |
232 | 71 | (O.matches(options::OPT_fno_PIC) || O.matches(options::OPT_fno_pic)70 || |
233 | 71 | O.matches(options::OPT_fno_PIE)8 || O.matches(options::OPT_fno_pie)8 ); |
234 | 71 | IsPIC = |
235 | 71 | (O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic)66 || |
236 | 71 | O.matches(options::OPT_fPIE)65 || O.matches(options::OPT_fpie)64 ); |
237 | 71 | } |
238 | | |
239 | 437 | bool UseAbiCalls = false; |
240 | | |
241 | 437 | Arg *ABICallsArg = |
242 | 437 | Args.getLastArg(options::OPT_mabicalls, options::OPT_mno_abicalls); |
243 | 437 | UseAbiCalls = |
244 | 437 | !ABICallsArg || ABICallsArg->getOption().matches(options::OPT_mabicalls)32 ; |
245 | | |
246 | 437 | if (IsN64 && NonPIC103 && (26 !ABICallsArg26 || UseAbiCalls12 )) { |
247 | 14 | D.Diag(diag::warn_drv_unsupported_pic_with_mabicalls) |
248 | 14 | << LastPICArg->getAsString(Args) << (!ABICallsArg ? 0 : 10 ); |
249 | 14 | } |
250 | | |
251 | 437 | if (ABICallsArg && !UseAbiCalls32 && IsPIC29 ) { |
252 | 1 | D.Diag(diag::err_drv_unsupported_noabicalls_pic); |
253 | 1 | } |
254 | | |
255 | 437 | if (!UseAbiCalls) |
256 | 29 | Features.push_back("+noabicalls"); |
257 | 408 | else |
258 | 408 | Features.push_back("-noabicalls"); |
259 | | |
260 | 437 | if (Arg *A = Args.getLastArg(options::OPT_mlong_calls, |
261 | 437 | options::OPT_mno_long_calls)) { |
262 | 3 | if (A->getOption().matches(options::OPT_mno_long_calls)) |
263 | 1 | Features.push_back("-long-calls"); |
264 | 2 | else if (!UseAbiCalls) |
265 | 1 | Features.push_back("+long-calls"); |
266 | 1 | else |
267 | 1 | D.Diag(diag::warn_drv_unsupported_longcalls) << (ABICallsArg ? 00 : 1); |
268 | 3 | } |
269 | | |
270 | 437 | if (Arg *A = Args.getLastArg(options::OPT_mxgot, options::OPT_mno_xgot)) { |
271 | 4 | if (A->getOption().matches(options::OPT_mxgot)) |
272 | 2 | Features.push_back("+xgot"); |
273 | 2 | else |
274 | 2 | Features.push_back("-xgot"); |
275 | 4 | } |
276 | | |
277 | 437 | mips::FloatABI FloatABI = mips::getMipsFloatABI(D, Args, Triple); |
278 | 437 | if (FloatABI == mips::FloatABI::Soft) { |
279 | | // FIXME: Note, this is a hack. We need to pass the selected float |
280 | | // mode to the MipsTargetInfoBase to define appropriate macros there. |
281 | | // Now it is the only method. |
282 | 69 | Features.push_back("+soft-float"); |
283 | 69 | } |
284 | | |
285 | 437 | if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) { |
286 | 25 | StringRef Val = StringRef(A->getValue()); |
287 | 25 | if (Val == "2008") { |
288 | 19 | if (mips::getIEEE754Standard(CPUName) & mips::Std2008) |
289 | 14 | Features.push_back("+nan2008"); |
290 | 5 | else { |
291 | 5 | Features.push_back("-nan2008"); |
292 | 5 | D.Diag(diag::warn_target_unsupported_nan2008) << CPUName; |
293 | 5 | } |
294 | 19 | } else if (6 Val == "legacy"6 ) { |
295 | 6 | if (mips::getIEEE754Standard(CPUName) & mips::Legacy) |
296 | 4 | Features.push_back("-nan2008"); |
297 | 2 | else { |
298 | 2 | Features.push_back("+nan2008"); |
299 | 2 | D.Diag(diag::warn_target_unsupported_nanlegacy) << CPUName; |
300 | 2 | } |
301 | 6 | } else |
302 | 0 | D.Diag(diag::err_drv_unsupported_option_argument) |
303 | 0 | << A->getSpelling() << Val; |
304 | 25 | } |
305 | | |
306 | 437 | if (Arg *A = Args.getLastArg(options::OPT_mabs_EQ)) { |
307 | 4 | StringRef Val = StringRef(A->getValue()); |
308 | 4 | if (Val == "2008") { |
309 | 2 | if (mips::getIEEE754Standard(CPUName) & mips::Std2008) { |
310 | 1 | Features.push_back("+abs2008"); |
311 | 1 | } else { |
312 | 1 | Features.push_back("-abs2008"); |
313 | 1 | D.Diag(diag::warn_target_unsupported_abs2008) << CPUName; |
314 | 1 | } |
315 | 2 | } else if (Val == "legacy") { |
316 | 2 | if (mips::getIEEE754Standard(CPUName) & mips::Legacy) { |
317 | 1 | Features.push_back("-abs2008"); |
318 | 1 | } else { |
319 | 1 | Features.push_back("+abs2008"); |
320 | 1 | D.Diag(diag::warn_target_unsupported_abslegacy) << CPUName; |
321 | 1 | } |
322 | 2 | } else { |
323 | 0 | D.Diag(diag::err_drv_unsupported_option_argument) |
324 | 0 | << A->getSpelling() << Val; |
325 | 0 | } |
326 | 4 | } |
327 | | |
328 | 437 | AddTargetFeature(Args, Features, options::OPT_msingle_float, |
329 | 437 | options::OPT_mdouble_float, "single-float"); |
330 | 437 | AddTargetFeature(Args, Features, options::OPT_mips16, options::OPT_mno_mips16, |
331 | 437 | "mips16"); |
332 | 437 | AddTargetFeature(Args, Features, options::OPT_mmicromips, |
333 | 437 | options::OPT_mno_micromips, "micromips"); |
334 | 437 | AddTargetFeature(Args, Features, options::OPT_mdsp, options::OPT_mno_dsp, |
335 | 437 | "dsp"); |
336 | 437 | AddTargetFeature(Args, Features, options::OPT_mdspr2, options::OPT_mno_dspr2, |
337 | 437 | "dspr2"); |
338 | 437 | AddTargetFeature(Args, Features, options::OPT_mmsa, options::OPT_mno_msa, |
339 | 437 | "msa"); |
340 | | |
341 | | // Add the last -mfp32/-mfpxx/-mfp64, if none are given and the ABI is O32 |
342 | | // pass -mfpxx, or if none are given and fp64a is default, pass fp64 and |
343 | | // nooddspreg. |
344 | 437 | if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx, |
345 | 437 | options::OPT_mfp64)) { |
346 | 29 | if (A->getOption().matches(options::OPT_mfp32)) |
347 | 3 | Features.push_back("-fp64"); |
348 | 26 | else if (A->getOption().matches(options::OPT_mfpxx)) { |
349 | 23 | Features.push_back("+fpxx"); |
350 | 23 | Features.push_back("+nooddspreg"); |
351 | 23 | } else |
352 | 3 | Features.push_back("+fp64"); |
353 | 408 | } else if (mips::shouldUseFPXX(Args, Triple, CPUName, ABIName, FloatABI)) { |
354 | 208 | Features.push_back("+fpxx"); |
355 | 208 | Features.push_back("+nooddspreg"); |
356 | 208 | } else if (200 mips::isFP64ADefault(Triple, CPUName)200 ) { |
357 | 0 | Features.push_back("+fp64"); |
358 | 0 | Features.push_back("+nooddspreg"); |
359 | 0 | } |
360 | | |
361 | 437 | AddTargetFeature(Args, Features, options::OPT_mno_odd_spreg, |
362 | 437 | options::OPT_modd_spreg, "nooddspreg"); |
363 | 437 | AddTargetFeature(Args, Features, options::OPT_mno_madd4, options::OPT_mmadd4, |
364 | 437 | "nomadd4"); |
365 | 437 | AddTargetFeature(Args, Features, options::OPT_mmt, options::OPT_mno_mt, "mt"); |
366 | 437 | AddTargetFeature(Args, Features, options::OPT_mcrc, options::OPT_mno_crc, |
367 | 437 | "crc"); |
368 | 437 | AddTargetFeature(Args, Features, options::OPT_mvirt, options::OPT_mno_virt, |
369 | 437 | "virt"); |
370 | 437 | AddTargetFeature(Args, Features, options::OPT_mginv, options::OPT_mno_ginv, |
371 | 437 | "ginv"); |
372 | | |
373 | 437 | if (Arg *A = Args.getLastArg(options::OPT_mindirect_jump_EQ)) { |
374 | 1 | StringRef Val = StringRef(A->getValue()); |
375 | 1 | if (Val == "hazard") { |
376 | 1 | Arg *B = |
377 | 1 | Args.getLastArg(options::OPT_mmicromips, options::OPT_mno_micromips); |
378 | 1 | Arg *C = Args.getLastArg(options::OPT_mips16, options::OPT_mno_mips16); |
379 | | |
380 | 1 | if (B && B->getOption().matches(options::OPT_mmicromips)0 ) |
381 | 0 | D.Diag(diag::err_drv_unsupported_indirect_jump_opt) |
382 | 0 | << "hazard" << "micromips"; |
383 | 1 | else if (C && C->getOption().matches(options::OPT_mips16)0 ) |
384 | 0 | D.Diag(diag::err_drv_unsupported_indirect_jump_opt) |
385 | 0 | << "hazard" << "mips16"; |
386 | 1 | else if (mips::supportsIndirectJumpHazardBarrier(CPUName)) |
387 | 1 | Features.push_back("+use-indirect-jump-hazard"); |
388 | 0 | else |
389 | 0 | D.Diag(diag::err_drv_unsupported_indirect_jump_opt) |
390 | 0 | << "hazard" << CPUName; |
391 | 1 | } else |
392 | 0 | D.Diag(diag::err_drv_unknown_indirect_jump_opt) << Val; |
393 | 1 | } |
394 | 437 | } |
395 | | |
396 | 29 | mips::IEEE754Standard mips::getIEEE754Standard(StringRef &CPU) { |
397 | | // Strictly speaking, mips32r2 and mips64r2 do not conform to the |
398 | | // IEEE754-2008 standard. Support for this standard was first introduced |
399 | | // in Release 3. However, other compilers have traditionally allowed it |
400 | | // for Release 2 so we should do the same. |
401 | 29 | return (IEEE754Standard)llvm::StringSwitch<int>(CPU) |
402 | 29 | .Case("mips1", Legacy) |
403 | 29 | .Case("mips2", Legacy) |
404 | 29 | .Case("mips3", Legacy) |
405 | 29 | .Case("mips4", Legacy) |
406 | 29 | .Case("mips5", Legacy) |
407 | 29 | .Case("mips32", Legacy) |
408 | 29 | .Case("mips32r2", Legacy | Std2008) |
409 | 29 | .Case("mips32r3", Legacy | Std2008) |
410 | 29 | .Case("mips32r5", Legacy | Std2008) |
411 | 29 | .Case("mips32r6", Std2008) |
412 | 29 | .Case("mips64", Legacy) |
413 | 29 | .Case("mips64r2", Legacy | Std2008) |
414 | 29 | .Case("mips64r3", Legacy | Std2008) |
415 | 29 | .Case("mips64r5", Legacy | Std2008) |
416 | 29 | .Case("mips64r6", Std2008) |
417 | 29 | .Default(Std2008); |
418 | 29 | } |
419 | | |
420 | 3 | bool mips::hasCompactBranches(StringRef &CPU) { |
421 | | // mips32r6 and mips64r6 have compact branches. |
422 | 3 | return llvm::StringSwitch<bool>(CPU) |
423 | 3 | .Case("mips32r6", true) |
424 | 3 | .Case("mips64r6", true) |
425 | 3 | .Default(false); |
426 | 3 | } |
427 | | |
428 | 419 | bool mips::hasMipsAbiArg(const ArgList &Args, const char *Value) { |
429 | 419 | Arg *A = Args.getLastArg(options::OPT_mabi_EQ); |
430 | 419 | return A && (A->getValue() == StringRef(Value))49 ; |
431 | 419 | } |
432 | | |
433 | 79 | bool mips::isUCLibc(const ArgList &Args) { |
434 | 79 | Arg *A = Args.getLastArg(options::OPT_m_libc_Group); |
435 | 79 | return A && A->getOption().matches(options::OPT_muclibc)8 ; |
436 | 79 | } |
437 | | |
438 | | bool mips::isNaN2008(const Driver &D, const ArgList &Args, |
439 | 79 | const llvm::Triple &Triple) { |
440 | 79 | if (Arg *NaNArg = Args.getLastArg(options::OPT_mnan_EQ)) |
441 | 13 | return llvm::StringSwitch<bool>(NaNArg->getValue()) |
442 | 13 | .Case("2008", true) |
443 | 13 | .Case("legacy", false) |
444 | 13 | .Default(false); |
445 | | |
446 | | // NaN2008 is the default for MIPS32r6/MIPS64r6. |
447 | 66 | return llvm::StringSwitch<bool>(getCPUName(D, Args, Triple)) |
448 | 66 | .Cases("mips32r6", "mips64r6", true) |
449 | 66 | .Default(false); |
450 | 79 | } |
451 | | |
452 | 200 | bool mips::isFP64ADefault(const llvm::Triple &Triple, StringRef CPUName) { |
453 | 200 | if (!Triple.isAndroid()) |
454 | 200 | return false; |
455 | | |
456 | | // Android MIPS32R6 defaults to FP64A. |
457 | 0 | return llvm::StringSwitch<bool>(CPUName) |
458 | 0 | .Case("mips32r6", true) |
459 | 0 | .Default(false); |
460 | 200 | } |
461 | | |
462 | | bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName, |
463 | 484 | StringRef ABIName, mips::FloatABI FloatABI) { |
464 | 484 | if (ABIName != "32") |
465 | 153 | return false; |
466 | | |
467 | | // FPXX shouldn't be used if either -msoft-float or -mfloat-abi=soft is |
468 | | // present. |
469 | 331 | if (FloatABI == mips::FloatABI::Soft) |
470 | 45 | return false; |
471 | | |
472 | 286 | return llvm::StringSwitch<bool>(CPUName) |
473 | 286 | .Cases("mips2", "mips3", "mips4", "mips5", true) |
474 | 286 | .Cases("mips32", "mips32r2", "mips32r3", "mips32r5", true) |
475 | 286 | .Cases("mips64", "mips64r2", "mips64r3", "mips64r5", true) |
476 | 286 | .Default(false); |
477 | 331 | } |
478 | | |
479 | | bool mips::shouldUseFPXX(const ArgList &Args, const llvm::Triple &Triple, |
480 | | StringRef CPUName, StringRef ABIName, |
481 | 484 | mips::FloatABI FloatABI) { |
482 | 484 | bool UseFPXX = isFPXXDefault(Triple, CPUName, ABIName, FloatABI); |
483 | | |
484 | | // FPXX shouldn't be used if -msingle-float is present. |
485 | 484 | if (Arg *A = Args.getLastArg(options::OPT_msingle_float, |
486 | 484 | options::OPT_mdouble_float)) |
487 | 21 | if (A->getOption().matches(options::OPT_msingle_float)) |
488 | 17 | UseFPXX = false; |
489 | | |
490 | 484 | return UseFPXX; |
491 | 484 | } |
492 | | |
493 | 1 | bool mips::supportsIndirectJumpHazardBarrier(StringRef &CPU) { |
494 | | // Supporting the hazard barrier method of dealing with indirect |
495 | | // jumps requires MIPSR2 support. |
496 | 1 | return llvm::StringSwitch<bool>(CPU) |
497 | 1 | .Case("mips32r2", true) |
498 | 1 | .Case("mips32r3", true) |
499 | 1 | .Case("mips32r5", true) |
500 | 1 | .Case("mips32r6", true) |
501 | 1 | .Case("mips64r2", true) |
502 | 1 | .Case("mips64r3", true) |
503 | 1 | .Case("mips64r5", true) |
504 | 1 | .Case("mips64r6", true) |
505 | 1 | .Case("octeon", true) |
506 | 1 | .Case("p5600", true) |
507 | 1 | .Default(false); |
508 | 1 | } |