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