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