/src/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 | 0 | StringRef &CPUName, StringRef &ABIName) { |
26 | 0 | const char *DefMips32CPU = "mips32r2"; |
27 | 0 | 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 | 0 | if (Triple.getVendor() == llvm::Triple::ImaginationTechnologies && |
32 | 0 | Triple.isGNUEnvironment()) { |
33 | 0 | DefMips32CPU = "mips32r6"; |
34 | 0 | DefMips64CPU = "mips64r6"; |
35 | 0 | } |
36 | |
|
37 | 0 | if (Triple.getSubArch() == llvm::Triple::MipsSubArch_r6) { |
38 | 0 | DefMips32CPU = "mips32r6"; |
39 | 0 | DefMips64CPU = "mips64r6"; |
40 | 0 | } |
41 | | |
42 | | // MIPS3 is the default for mips64*-unknown-openbsd. |
43 | 0 | if (Triple.isOSOpenBSD()) |
44 | 0 | DefMips64CPU = "mips3"; |
45 | | |
46 | | // MIPS2 is the default for mips(el)?-unknown-freebsd. |
47 | | // MIPS3 is the default for mips64(el)?-unknown-freebsd. |
48 | 0 | if (Triple.isOSFreeBSD()) { |
49 | 0 | DefMips32CPU = "mips2"; |
50 | 0 | DefMips64CPU = "mips3"; |
51 | 0 | } |
52 | |
|
53 | 0 | if (Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ, |
54 | 0 | options::OPT_mcpu_EQ)) |
55 | 0 | CPUName = A->getValue(); |
56 | |
|
57 | 0 | if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { |
58 | 0 | ABIName = A->getValue(); |
59 | | // Convert a GNU style Mips ABI name to the name |
60 | | // accepted by LLVM Mips backend. |
61 | 0 | ABIName = llvm::StringSwitch<llvm::StringRef>(ABIName) |
62 | 0 | .Case("32", "o32") |
63 | 0 | .Case("64", "n64") |
64 | 0 | .Default(ABIName); |
65 | 0 | } |
66 | | |
67 | | // Setup default CPU and ABI names. |
68 | 0 | if (CPUName.empty() && ABIName.empty()) { |
69 | 0 | switch (Triple.getArch()) { |
70 | 0 | default: |
71 | 0 | llvm_unreachable("Unexpected triple arch name"); |
72 | 0 | case llvm::Triple::mips: |
73 | 0 | case llvm::Triple::mipsel: |
74 | 0 | CPUName = DefMips32CPU; |
75 | 0 | break; |
76 | 0 | case llvm::Triple::mips64: |
77 | 0 | case llvm::Triple::mips64el: |
78 | 0 | CPUName = DefMips64CPU; |
79 | 0 | break; |
80 | 0 | } |
81 | 0 | } |
82 | | |
83 | 0 | if (ABIName.empty() && (Triple.getEnvironment() == llvm::Triple::GNUABIN32)) |
84 | 0 | ABIName = "n32"; |
85 | |
|
86 | 0 | if (ABIName.empty() && |
87 | 0 | (Triple.getVendor() == llvm::Triple::MipsTechnologies || |
88 | 0 | Triple.getVendor() == llvm::Triple::ImaginationTechnologies)) { |
89 | 0 | ABIName = llvm::StringSwitch<const char *>(CPUName) |
90 | 0 | .Case("mips1", "o32") |
91 | 0 | .Case("mips2", "o32") |
92 | 0 | .Case("mips3", "n64") |
93 | 0 | .Case("mips4", "n64") |
94 | 0 | .Case("mips5", "n64") |
95 | 0 | .Case("mips32", "o32") |
96 | 0 | .Case("mips32r2", "o32") |
97 | 0 | .Case("mips32r3", "o32") |
98 | 0 | .Case("mips32r5", "o32") |
99 | 0 | .Case("mips32r6", "o32") |
100 | 0 | .Case("mips64", "n64") |
101 | 0 | .Case("mips64r2", "n64") |
102 | 0 | .Case("mips64r3", "n64") |
103 | 0 | .Case("mips64r5", "n64") |
104 | 0 | .Case("mips64r6", "n64") |
105 | 0 | .Case("octeon", "n64") |
106 | 0 | .Case("p5600", "o32") |
107 | 0 | .Default(""); |
108 | 0 | } |
109 | |
|
110 | 0 | if (ABIName.empty()) { |
111 | | // Deduce ABI name from the target triple. |
112 | 0 | ABIName = Triple.isMIPS32() ? "o32" : "n64"; |
113 | 0 | } |
114 | |
|
115 | 0 | if (CPUName.empty()) { |
116 | | // Deduce CPU name from ABI name. |
117 | 0 | CPUName = llvm::StringSwitch<const char *>(ABIName) |
118 | 0 | .Case("o32", DefMips32CPU) |
119 | 0 | .Cases("n32", "n64", DefMips64CPU) |
120 | 0 | .Default(""); |
121 | 0 | } |
122 | | |
123 | | // FIXME: Warn on inconsistent use of -march and -mabi. |
124 | 0 | } |
125 | | |
126 | | std::string mips::getMipsABILibSuffix(const ArgList &Args, |
127 | 0 | const llvm::Triple &Triple) { |
128 | 0 | StringRef CPUName, ABIName; |
129 | 0 | tools::mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName); |
130 | 0 | return llvm::StringSwitch<std::string>(ABIName) |
131 | 0 | .Case("o32", "") |
132 | 0 | .Case("n32", "32") |
133 | 0 | .Case("n64", "64"); |
134 | 0 | } |
135 | | |
136 | | // Convert ABI name to the GNU tools acceptable variant. |
137 | 0 | StringRef mips::getGnuCompatibleMipsABIName(StringRef ABI) { |
138 | 0 | return llvm::StringSwitch<llvm::StringRef>(ABI) |
139 | 0 | .Case("o32", "32") |
140 | 0 | .Case("n64", "64") |
141 | 0 | .Default(ABI); |
142 | 0 | } |
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 | 0 | const llvm::Triple &Triple) { |
148 | 0 | mips::FloatABI ABI = mips::FloatABI::Invalid; |
149 | 0 | if (Arg *A = |
150 | 0 | Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, |
151 | 0 | options::OPT_mfloat_abi_EQ)) { |
152 | 0 | if (A->getOption().matches(options::OPT_msoft_float)) |
153 | 0 | ABI = mips::FloatABI::Soft; |
154 | 0 | else if (A->getOption().matches(options::OPT_mhard_float)) |
155 | 0 | ABI = mips::FloatABI::Hard; |
156 | 0 | else { |
157 | 0 | ABI = llvm::StringSwitch<mips::FloatABI>(A->getValue()) |
158 | 0 | .Case("soft", mips::FloatABI::Soft) |
159 | 0 | .Case("hard", mips::FloatABI::Hard) |
160 | 0 | .Default(mips::FloatABI::Invalid); |
161 | 0 | if (ABI == mips::FloatABI::Invalid && !StringRef(A->getValue()).empty()) { |
162 | 0 | D.Diag(clang::diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args); |
163 | 0 | ABI = mips::FloatABI::Hard; |
164 | 0 | } |
165 | 0 | } |
166 | 0 | } |
167 | | |
168 | | // If unspecified, choose the default based on the platform. |
169 | 0 | if (ABI == mips::FloatABI::Invalid) { |
170 | 0 | if (Triple.isOSFreeBSD()) { |
171 | | // For FreeBSD, assume "soft" on all flavors of MIPS. |
172 | 0 | ABI = mips::FloatABI::Soft; |
173 | 0 | } 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 | 0 | ABI = mips::FloatABI::Hard; |
178 | 0 | } |
179 | 0 | } |
180 | |
|
181 | 0 | assert(ABI != mips::FloatABI::Invalid && "must select an ABI"); |
182 | 0 | return ABI; |
183 | 0 | } |
184 | | |
185 | | void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple, |
186 | | const ArgList &Args, |
187 | 0 | std::vector<StringRef> &Features) { |
188 | 0 | StringRef CPUName; |
189 | 0 | StringRef ABIName; |
190 | 0 | getMipsCPUAndABI(Args, Triple, CPUName, ABIName); |
191 | 0 | 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 | 0 | bool IsN64 = ABIName == "64"; |
222 | 0 | bool IsPIC = false; |
223 | 0 | bool NonPIC = false; |
224 | 0 | bool HasNaN2008Opt = false; |
225 | |
|
226 | 0 | Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC, |
227 | 0 | options::OPT_fpic, options::OPT_fno_pic, |
228 | 0 | options::OPT_fPIE, options::OPT_fno_PIE, |
229 | 0 | options::OPT_fpie, options::OPT_fno_pie); |
230 | 0 | if (LastPICArg) { |
231 | 0 | Option O = LastPICArg->getOption(); |
232 | 0 | NonPIC = |
233 | 0 | (O.matches(options::OPT_fno_PIC) || O.matches(options::OPT_fno_pic) || |
234 | 0 | O.matches(options::OPT_fno_PIE) || O.matches(options::OPT_fno_pie)); |
235 | 0 | IsPIC = |
236 | 0 | (O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic) || |
237 | 0 | O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie)); |
238 | 0 | } |
239 | |
|
240 | 0 | bool UseAbiCalls = false; |
241 | |
|
242 | 0 | Arg *ABICallsArg = |
243 | 0 | Args.getLastArg(options::OPT_mabicalls, options::OPT_mno_abicalls); |
244 | 0 | UseAbiCalls = |
245 | 0 | !ABICallsArg || ABICallsArg->getOption().matches(options::OPT_mabicalls); |
246 | |
|
247 | 0 | if (IsN64 && NonPIC && (!ABICallsArg || UseAbiCalls)) { |
248 | 0 | D.Diag(diag::warn_drv_unsupported_pic_with_mabicalls) |
249 | 0 | << LastPICArg->getAsString(Args) << (!ABICallsArg ? 0 : 1); |
250 | 0 | } |
251 | |
|
252 | 0 | if (ABICallsArg && !UseAbiCalls && IsPIC) { |
253 | 0 | D.Diag(diag::err_drv_unsupported_noabicalls_pic); |
254 | 0 | } |
255 | |
|
256 | 0 | if (!UseAbiCalls) |
257 | 0 | Features.push_back("+noabicalls"); |
258 | 0 | else |
259 | 0 | Features.push_back("-noabicalls"); |
260 | |
|
261 | 0 | if (Arg *A = Args.getLastArg(options::OPT_mlong_calls, |
262 | 0 | options::OPT_mno_long_calls)) { |
263 | 0 | if (A->getOption().matches(options::OPT_mno_long_calls)) |
264 | 0 | Features.push_back("-long-calls"); |
265 | 0 | else if (!UseAbiCalls) |
266 | 0 | Features.push_back("+long-calls"); |
267 | 0 | else |
268 | 0 | D.Diag(diag::warn_drv_unsupported_longcalls) << (ABICallsArg ? 0 : 1); |
269 | 0 | } |
270 | |
|
271 | 0 | if (Arg *A = Args.getLastArg(options::OPT_mxgot, options::OPT_mno_xgot)) { |
272 | 0 | if (A->getOption().matches(options::OPT_mxgot)) |
273 | 0 | Features.push_back("+xgot"); |
274 | 0 | else |
275 | 0 | Features.push_back("-xgot"); |
276 | 0 | } |
277 | |
|
278 | 0 | mips::FloatABI FloatABI = mips::getMipsFloatABI(D, Args, Triple); |
279 | 0 | if (FloatABI == mips::FloatABI::Soft) { |
280 | | // FIXME: Note, this is a hack. We need to pass the selected float |
281 | | // mode to the MipsTargetInfoBase to define appropriate macros there. |
282 | | // Now it is the only method. |
283 | 0 | Features.push_back("+soft-float"); |
284 | 0 | } |
285 | |
|
286 | 0 | if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) { |
287 | 0 | StringRef Val = StringRef(A->getValue()); |
288 | 0 | if (Val == "2008") { |
289 | 0 | if (mips::getIEEE754Standard(CPUName) & mips::Std2008) { |
290 | 0 | Features.push_back("+nan2008"); |
291 | 0 | HasNaN2008Opt = true; |
292 | 0 | } else { |
293 | 0 | Features.push_back("-nan2008"); |
294 | 0 | D.Diag(diag::warn_target_unsupported_nan2008) << CPUName; |
295 | 0 | } |
296 | 0 | } else if (Val == "legacy") { |
297 | 0 | if (mips::getIEEE754Standard(CPUName) & mips::Legacy) |
298 | 0 | Features.push_back("-nan2008"); |
299 | 0 | else { |
300 | 0 | Features.push_back("+nan2008"); |
301 | 0 | D.Diag(diag::warn_target_unsupported_nanlegacy) << CPUName; |
302 | 0 | } |
303 | 0 | } else |
304 | 0 | D.Diag(diag::err_drv_unsupported_option_argument) |
305 | 0 | << A->getSpelling() << Val; |
306 | 0 | } |
307 | |
|
308 | 0 | if (Arg *A = Args.getLastArg(options::OPT_mabs_EQ)) { |
309 | 0 | StringRef Val = StringRef(A->getValue()); |
310 | 0 | if (Val == "2008") { |
311 | 0 | if (mips::getIEEE754Standard(CPUName) & mips::Std2008) { |
312 | 0 | Features.push_back("+abs2008"); |
313 | 0 | } else { |
314 | 0 | Features.push_back("-abs2008"); |
315 | 0 | D.Diag(diag::warn_target_unsupported_abs2008) << CPUName; |
316 | 0 | } |
317 | 0 | } else if (Val == "legacy") { |
318 | 0 | if (mips::getIEEE754Standard(CPUName) & mips::Legacy) { |
319 | 0 | Features.push_back("-abs2008"); |
320 | 0 | } else { |
321 | 0 | Features.push_back("+abs2008"); |
322 | 0 | D.Diag(diag::warn_target_unsupported_abslegacy) << CPUName; |
323 | 0 | } |
324 | 0 | } else { |
325 | 0 | D.Diag(diag::err_drv_unsupported_option_argument) |
326 | 0 | << A->getSpelling() << Val; |
327 | 0 | } |
328 | 0 | } else if (HasNaN2008Opt) { |
329 | 0 | Features.push_back("+abs2008"); |
330 | 0 | } |
331 | |
|
332 | 0 | AddTargetFeature(Args, Features, options::OPT_msingle_float, |
333 | 0 | options::OPT_mdouble_float, "single-float"); |
334 | 0 | AddTargetFeature(Args, Features, options::OPT_mips16, options::OPT_mno_mips16, |
335 | 0 | "mips16"); |
336 | 0 | AddTargetFeature(Args, Features, options::OPT_mmicromips, |
337 | 0 | options::OPT_mno_micromips, "micromips"); |
338 | 0 | AddTargetFeature(Args, Features, options::OPT_mdsp, options::OPT_mno_dsp, |
339 | 0 | "dsp"); |
340 | 0 | AddTargetFeature(Args, Features, options::OPT_mdspr2, options::OPT_mno_dspr2, |
341 | 0 | "dspr2"); |
342 | 0 | AddTargetFeature(Args, Features, options::OPT_mmsa, options::OPT_mno_msa, |
343 | 0 | "msa"); |
344 | | |
345 | | // Add the last -mfp32/-mfpxx/-mfp64, if none are given and the ABI is O32 |
346 | | // pass -mfpxx, or if none are given and fp64a is default, pass fp64 and |
347 | | // nooddspreg. |
348 | 0 | if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx, |
349 | 0 | options::OPT_mfp64)) { |
350 | 0 | if (A->getOption().matches(options::OPT_mfp32)) |
351 | 0 | Features.push_back("-fp64"); |
352 | 0 | else if (A->getOption().matches(options::OPT_mfpxx)) { |
353 | 0 | Features.push_back("+fpxx"); |
354 | 0 | Features.push_back("+nooddspreg"); |
355 | 0 | } else |
356 | 0 | Features.push_back("+fp64"); |
357 | 0 | } else if (mips::shouldUseFPXX(Args, Triple, CPUName, ABIName, FloatABI)) { |
358 | 0 | Features.push_back("+fpxx"); |
359 | 0 | Features.push_back("+nooddspreg"); |
360 | 0 | } else if (mips::isFP64ADefault(Triple, CPUName)) { |
361 | 0 | Features.push_back("+fp64"); |
362 | 0 | Features.push_back("+nooddspreg"); |
363 | 0 | } |
364 | |
|
365 | 0 | AddTargetFeature(Args, Features, options::OPT_mno_odd_spreg, |
366 | 0 | options::OPT_modd_spreg, "nooddspreg"); |
367 | 0 | AddTargetFeature(Args, Features, options::OPT_mno_madd4, options::OPT_mmadd4, |
368 | 0 | "nomadd4"); |
369 | 0 | AddTargetFeature(Args, Features, options::OPT_mmt, options::OPT_mno_mt, "mt"); |
370 | 0 | AddTargetFeature(Args, Features, options::OPT_mcrc, options::OPT_mno_crc, |
371 | 0 | "crc"); |
372 | 0 | AddTargetFeature(Args, Features, options::OPT_mvirt, options::OPT_mno_virt, |
373 | 0 | "virt"); |
374 | 0 | AddTargetFeature(Args, Features, options::OPT_mginv, options::OPT_mno_ginv, |
375 | 0 | "ginv"); |
376 | |
|
377 | 0 | if (Arg *A = Args.getLastArg(options::OPT_mindirect_jump_EQ)) { |
378 | 0 | StringRef Val = StringRef(A->getValue()); |
379 | 0 | if (Val == "hazard") { |
380 | 0 | Arg *B = |
381 | 0 | Args.getLastArg(options::OPT_mmicromips, options::OPT_mno_micromips); |
382 | 0 | Arg *C = Args.getLastArg(options::OPT_mips16, options::OPT_mno_mips16); |
383 | |
|
384 | 0 | if (B && B->getOption().matches(options::OPT_mmicromips)) |
385 | 0 | D.Diag(diag::err_drv_unsupported_indirect_jump_opt) |
386 | 0 | << "hazard" << "micromips"; |
387 | 0 | else if (C && C->getOption().matches(options::OPT_mips16)) |
388 | 0 | D.Diag(diag::err_drv_unsupported_indirect_jump_opt) |
389 | 0 | << "hazard" << "mips16"; |
390 | 0 | else if (mips::supportsIndirectJumpHazardBarrier(CPUName)) |
391 | 0 | Features.push_back("+use-indirect-jump-hazard"); |
392 | 0 | else |
393 | 0 | D.Diag(diag::err_drv_unsupported_indirect_jump_opt) |
394 | 0 | << "hazard" << CPUName; |
395 | 0 | } else |
396 | 0 | D.Diag(diag::err_drv_unknown_indirect_jump_opt) << Val; |
397 | 0 | } |
398 | 0 | } |
399 | | |
400 | 0 | mips::IEEE754Standard mips::getIEEE754Standard(StringRef &CPU) { |
401 | | // Strictly speaking, mips32r2 and mips64r2 do not conform to the |
402 | | // IEEE754-2008 standard. Support for this standard was first introduced |
403 | | // in Release 3. However, other compilers have traditionally allowed it |
404 | | // for Release 2 so we should do the same. |
405 | 0 | return (IEEE754Standard)llvm::StringSwitch<int>(CPU) |
406 | 0 | .Case("mips1", Legacy) |
407 | 0 | .Case("mips2", Legacy) |
408 | 0 | .Case("mips3", Legacy) |
409 | 0 | .Case("mips4", Legacy) |
410 | 0 | .Case("mips5", Legacy) |
411 | 0 | .Case("mips32", Legacy) |
412 | 0 | .Case("mips32r2", Legacy | Std2008) |
413 | 0 | .Case("mips32r3", Legacy | Std2008) |
414 | 0 | .Case("mips32r5", Legacy | Std2008) |
415 | 0 | .Case("mips32r6", Std2008) |
416 | 0 | .Case("mips64", Legacy) |
417 | 0 | .Case("mips64r2", Legacy | Std2008) |
418 | 0 | .Case("mips64r3", Legacy | Std2008) |
419 | 0 | .Case("mips64r5", Legacy | Std2008) |
420 | 0 | .Case("mips64r6", Std2008) |
421 | 0 | .Default(Std2008); |
422 | 0 | } |
423 | | |
424 | 0 | bool mips::hasCompactBranches(StringRef &CPU) { |
425 | | // mips32r6 and mips64r6 have compact branches. |
426 | 0 | return llvm::StringSwitch<bool>(CPU) |
427 | 0 | .Case("mips32r6", true) |
428 | 0 | .Case("mips64r6", true) |
429 | 0 | .Default(false); |
430 | 0 | } |
431 | | |
432 | 0 | bool mips::hasMipsAbiArg(const ArgList &Args, const char *Value) { |
433 | 0 | Arg *A = Args.getLastArg(options::OPT_mabi_EQ); |
434 | 0 | return A && (A->getValue() == StringRef(Value)); |
435 | 0 | } |
436 | | |
437 | 0 | bool mips::isUCLibc(const ArgList &Args) { |
438 | 0 | Arg *A = Args.getLastArg(options::OPT_m_libc_Group); |
439 | 0 | return A && A->getOption().matches(options::OPT_muclibc); |
440 | 0 | } |
441 | | |
442 | | bool mips::isNaN2008(const Driver &D, const ArgList &Args, |
443 | 0 | const llvm::Triple &Triple) { |
444 | 0 | if (Arg *NaNArg = Args.getLastArg(options::OPT_mnan_EQ)) |
445 | 0 | return llvm::StringSwitch<bool>(NaNArg->getValue()) |
446 | 0 | .Case("2008", true) |
447 | 0 | .Case("legacy", false) |
448 | 0 | .Default(false); |
449 | | |
450 | | // NaN2008 is the default for MIPS32r6/MIPS64r6. |
451 | 0 | return llvm::StringSwitch<bool>(getCPUName(D, Args, Triple)) |
452 | 0 | .Cases("mips32r6", "mips64r6", true) |
453 | 0 | .Default(false); |
454 | 0 | } |
455 | | |
456 | 0 | bool mips::isFP64ADefault(const llvm::Triple &Triple, StringRef CPUName) { |
457 | 0 | if (!Triple.isAndroid()) |
458 | 0 | return false; |
459 | | |
460 | | // Android MIPS32R6 defaults to FP64A. |
461 | 0 | return llvm::StringSwitch<bool>(CPUName) |
462 | 0 | .Case("mips32r6", true) |
463 | 0 | .Default(false); |
464 | 0 | } |
465 | | |
466 | | bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName, |
467 | 0 | StringRef ABIName, mips::FloatABI FloatABI) { |
468 | 0 | if (ABIName != "32") |
469 | 0 | return false; |
470 | | |
471 | | // FPXX shouldn't be used if either -msoft-float or -mfloat-abi=soft is |
472 | | // present. |
473 | 0 | if (FloatABI == mips::FloatABI::Soft) |
474 | 0 | return false; |
475 | | |
476 | 0 | return llvm::StringSwitch<bool>(CPUName) |
477 | 0 | .Cases("mips2", "mips3", "mips4", "mips5", true) |
478 | 0 | .Cases("mips32", "mips32r2", "mips32r3", "mips32r5", true) |
479 | 0 | .Cases("mips64", "mips64r2", "mips64r3", "mips64r5", true) |
480 | 0 | .Default(false); |
481 | 0 | } |
482 | | |
483 | | bool mips::shouldUseFPXX(const ArgList &Args, const llvm::Triple &Triple, |
484 | | StringRef CPUName, StringRef ABIName, |
485 | 0 | mips::FloatABI FloatABI) { |
486 | 0 | bool UseFPXX = isFPXXDefault(Triple, CPUName, ABIName, FloatABI); |
487 | | |
488 | | // FPXX shouldn't be used if -msingle-float is present. |
489 | 0 | if (Arg *A = Args.getLastArg(options::OPT_msingle_float, |
490 | 0 | options::OPT_mdouble_float)) |
491 | 0 | if (A->getOption().matches(options::OPT_msingle_float)) |
492 | 0 | UseFPXX = false; |
493 | |
|
494 | 0 | return UseFPXX; |
495 | 0 | } |
496 | | |
497 | 0 | bool mips::supportsIndirectJumpHazardBarrier(StringRef &CPU) { |
498 | | // Supporting the hazard barrier method of dealing with indirect |
499 | | // jumps requires MIPSR2 support. |
500 | 0 | return llvm::StringSwitch<bool>(CPU) |
501 | 0 | .Case("mips32r2", true) |
502 | 0 | .Case("mips32r3", true) |
503 | 0 | .Case("mips32r5", true) |
504 | 0 | .Case("mips32r6", true) |
505 | 0 | .Case("mips64r2", true) |
506 | 0 | .Case("mips64r3", true) |
507 | 0 | .Case("mips64r5", true) |
508 | 0 | .Case("mips64r6", true) |
509 | 0 | .Case("octeon", true) |
510 | 0 | .Case("p5600", true) |
511 | 0 | .Default(false); |
512 | 0 | } |