1 | |
2 | |
3 | |
4 | |
5 | |
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 | |
23 | |
24 | void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple, |
25 | StringRef &CPUName, StringRef &ABIName) { |
26 | const char *DefMips32CPU = "mips32r2"; |
27 | const char *DefMips64CPU = "mips64r2"; |
28 | |
29 | |
30 | |
31 | if (Triple.getVendor() == llvm::Triple::ImaginationTechnologies && |
32 | Triple.isGNUEnvironment()) { |
33 | DefMips32CPU = "mips32r6"; |
34 | DefMips64CPU = "mips64r6"; |
35 | } |
36 | |
37 | if (Triple.getSubArch() == llvm::Triple::MipsSubArch_r6) { |
38 | DefMips32CPU = "mips32r6"; |
39 | DefMips64CPU = "mips64r6"; |
40 | } |
41 | |
42 | |
43 | if (Triple.isAndroid()) { |
44 | DefMips32CPU = "mips32"; |
45 | DefMips64CPU = "mips64r6"; |
46 | } |
47 | |
48 | |
49 | if (Triple.isOSOpenBSD()) |
50 | DefMips64CPU = "mips3"; |
51 | |
52 | |
53 | |
54 | if (Triple.isOSFreeBSD()) { |
55 | DefMips32CPU = "mips2"; |
56 | DefMips64CPU = "mips3"; |
57 | } |
58 | |
59 | if (Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ, |
60 | options::OPT_mcpu_EQ)) |
61 | CPUName = A->getValue(); |
62 | |
63 | if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { |
64 | ABIName = A->getValue(); |
65 | |
66 | |
67 | ABIName = llvm::StringSwitch<llvm::StringRef>(ABIName) |
68 | .Case("32", "o32") |
69 | .Case("64", "n64") |
70 | .Default(ABIName); |
71 | } |
72 | |
73 | |
74 | if (CPUName.empty() && ABIName.empty()) { |
75 | switch (Triple.getArch()) { |
76 | default: |
77 | llvm_unreachable("Unexpected triple arch name"); |
78 | case llvm::Triple::mips: |
79 | case llvm::Triple::mipsel: |
80 | CPUName = DefMips32CPU; |
81 | break; |
82 | case llvm::Triple::mips64: |
83 | case llvm::Triple::mips64el: |
84 | CPUName = DefMips64CPU; |
85 | break; |
86 | } |
87 | } |
88 | |
89 | if (ABIName.empty() && (Triple.getEnvironment() == llvm::Triple::GNUABIN32)) |
90 | ABIName = "n32"; |
91 | |
92 | if (ABIName.empty() && |
93 | (Triple.getVendor() == llvm::Triple::MipsTechnologies || |
94 | Triple.getVendor() == llvm::Triple::ImaginationTechnologies)) { |
95 | ABIName = llvm::StringSwitch<const char *>(CPUName) |
96 | .Case("mips1", "o32") |
97 | .Case("mips2", "o32") |
98 | .Case("mips3", "n64") |
99 | .Case("mips4", "n64") |
100 | .Case("mips5", "n64") |
101 | .Case("mips32", "o32") |
102 | .Case("mips32r2", "o32") |
103 | .Case("mips32r3", "o32") |
104 | .Case("mips32r5", "o32") |
105 | .Case("mips32r6", "o32") |
106 | .Case("mips64", "n64") |
107 | .Case("mips64r2", "n64") |
108 | .Case("mips64r3", "n64") |
109 | .Case("mips64r5", "n64") |
110 | .Case("mips64r6", "n64") |
111 | .Case("octeon", "n64") |
112 | .Case("p5600", "o32") |
113 | .Default(""); |
114 | } |
115 | |
116 | if (ABIName.empty()) { |
117 | |
118 | ABIName = Triple.isMIPS32() ? "o32" : "n64"; |
119 | } |
120 | |
121 | if (CPUName.empty()) { |
122 | |
123 | CPUName = llvm::StringSwitch<const char *>(ABIName) |
124 | .Case("o32", DefMips32CPU) |
125 | .Cases("n32", "n64", DefMips64CPU) |
126 | .Default(""); |
127 | } |
128 | |
129 | |
130 | } |
131 | |
132 | std::string mips::getMipsABILibSuffix(const ArgList &Args, |
133 | const llvm::Triple &Triple) { |
134 | StringRef CPUName, ABIName; |
135 | tools::mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName); |
136 | return llvm::StringSwitch<std::string>(ABIName) |
137 | .Case("o32", "") |
138 | .Case("n32", "32") |
139 | .Case("n64", "64"); |
140 | } |
141 | |
142 | |
143 | StringRef mips::getGnuCompatibleMipsABIName(StringRef ABI) { |
144 | return llvm::StringSwitch<llvm::StringRef>(ABI) |
145 | .Case("o32", "32") |
146 | .Case("n64", "64") |
147 | .Default(ABI); |
148 | } |
149 | |
150 | |
151 | |
152 | mips::FloatABI mips::getMipsFloatABI(const Driver &D, const ArgList &Args) { |
153 | mips::FloatABI ABI = mips::FloatABI::Invalid; |
154 | if (Arg *A = |
155 | Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, |
156 | options::OPT_mfloat_abi_EQ)) { |
157 | if (A->getOption().matches(options::OPT_msoft_float)) |
158 | ABI = mips::FloatABI::Soft; |
159 | else if (A->getOption().matches(options::OPT_mhard_float)) |
160 | ABI = mips::FloatABI::Hard; |
161 | else { |
162 | ABI = llvm::StringSwitch<mips::FloatABI>(A->getValue()) |
163 | .Case("soft", mips::FloatABI::Soft) |
164 | .Case("hard", mips::FloatABI::Hard) |
165 | .Default(mips::FloatABI::Invalid); |
166 | if (ABI == mips::FloatABI::Invalid && !StringRef(A->getValue()).empty()) { |
167 | D.Diag(clang::diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args); |
168 | ABI = mips::FloatABI::Hard; |
169 | } |
170 | } |
171 | } |
172 | |
173 | |
174 | if (ABI == mips::FloatABI::Invalid) { |
175 | |
176 | |
177 | |
178 | ABI = mips::FloatABI::Hard; |
179 | } |
180 | |
181 | (0) . __assert_fail ("ABI != mips..FloatABI..Invalid && \"must select an ABI\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/ToolChains/Arch/Mips.cpp", 181, __PRETTY_FUNCTION__))" file_link="../../../../../include/assert.h.html#88" macro="true">assert(ABI != mips::FloatABI::Invalid && "must select an ABI"); |
182 | return ABI; |
183 | } |
184 | |
185 | void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple, |
186 | const ArgList &Args, |
187 | std::vector<StringRef> &Features) { |
188 | StringRef CPUName; |
189 | StringRef ABIName; |
190 | getMipsCPUAndABI(Args, Triple, CPUName, ABIName); |
191 | ABIName = getGnuCompatibleMipsABIName(ABIName); |
192 | |
193 | |
194 | |
195 | |
196 | |
197 | |
198 | |
199 | |
200 | |
201 | |
202 | |
203 | |
204 | |
205 | |
206 | |
207 | |
208 | |
209 | |
210 | |
211 | |
212 | |
213 | |
214 | |
215 | |
216 | |
217 | |
218 | |
219 | |
220 | |
221 | bool IsN64 = ABIName == "64"; |
222 | bool IsPIC = false; |
223 | bool NonPIC = false; |
224 | |
225 | Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC, |
226 | options::OPT_fpic, options::OPT_fno_pic, |
227 | options::OPT_fPIE, options::OPT_fno_PIE, |
228 | options::OPT_fpie, options::OPT_fno_pie); |
229 | if (LastPICArg) { |
230 | Option O = LastPICArg->getOption(); |
231 | NonPIC = |
232 | (O.matches(options::OPT_fno_PIC) || O.matches(options::OPT_fno_pic) || |
233 | O.matches(options::OPT_fno_PIE) || O.matches(options::OPT_fno_pie)); |
234 | IsPIC = |
235 | (O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic) || |
236 | O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie)); |
237 | } |
238 | |
239 | bool UseAbiCalls = false; |
240 | |
241 | Arg *ABICallsArg = |
242 | Args.getLastArg(options::OPT_mabicalls, options::OPT_mno_abicalls); |
243 | UseAbiCalls = |
244 | !ABICallsArg || ABICallsArg->getOption().matches(options::OPT_mabicalls); |
245 | |
246 | if (IsN64 && NonPIC && (!ABICallsArg || UseAbiCalls)) { |
247 | D.Diag(diag::warn_drv_unsupported_pic_with_mabicalls) |
248 | << LastPICArg->getAsString(Args) << (!ABICallsArg ? 0 : 1); |
249 | NonPIC = false; |
250 | } |
251 | |
252 | if (ABICallsArg && !UseAbiCalls && IsPIC) { |
253 | D.Diag(diag::err_drv_unsupported_noabicalls_pic); |
254 | } |
255 | |
256 | if (!UseAbiCalls) |
257 | Features.push_back("+noabicalls"); |
258 | else |
259 | Features.push_back("-noabicalls"); |
260 | |
261 | if (Arg *A = Args.getLastArg(options::OPT_mlong_calls, |
262 | options::OPT_mno_long_calls)) { |
263 | if (A->getOption().matches(options::OPT_mno_long_calls)) |
264 | Features.push_back("-long-calls"); |
265 | else if (!UseAbiCalls) |
266 | Features.push_back("+long-calls"); |
267 | else |
268 | D.Diag(diag::warn_drv_unsupported_longcalls) << (ABICallsArg ? 0 : 1); |
269 | } |
270 | |
271 | mips::FloatABI FloatABI = mips::getMipsFloatABI(D, Args); |
272 | if (FloatABI == mips::FloatABI::Soft) { |
273 | |
274 | |
275 | |
276 | Features.push_back("+soft-float"); |
277 | } |
278 | |
279 | if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) { |
280 | StringRef Val = StringRef(A->getValue()); |
281 | if (Val == "2008") { |
282 | if (mips::getIEEE754Standard(CPUName) & mips::Std2008) |
283 | Features.push_back("+nan2008"); |
284 | else { |
285 | Features.push_back("-nan2008"); |
286 | D.Diag(diag::warn_target_unsupported_nan2008) << CPUName; |
287 | } |
288 | } else if (Val == "legacy") { |
289 | if (mips::getIEEE754Standard(CPUName) & mips::Legacy) |
290 | Features.push_back("-nan2008"); |
291 | else { |
292 | Features.push_back("+nan2008"); |
293 | D.Diag(diag::warn_target_unsupported_nanlegacy) << CPUName; |
294 | } |
295 | } else |
296 | D.Diag(diag::err_drv_unsupported_option_argument) |
297 | << A->getOption().getName() << Val; |
298 | } |
299 | |
300 | if (Arg *A = Args.getLastArg(options::OPT_mabs_EQ)) { |
301 | StringRef Val = StringRef(A->getValue()); |
302 | if (Val == "2008") { |
303 | if (mips::getIEEE754Standard(CPUName) & mips::Std2008) { |
304 | Features.push_back("+abs2008"); |
305 | } else { |
306 | Features.push_back("-abs2008"); |
307 | D.Diag(diag::warn_target_unsupported_abs2008) << CPUName; |
308 | } |
309 | } else if (Val == "legacy") { |
310 | if (mips::getIEEE754Standard(CPUName) & mips::Legacy) { |
311 | Features.push_back("-abs2008"); |
312 | } else { |
313 | Features.push_back("+abs2008"); |
314 | D.Diag(diag::warn_target_unsupported_abslegacy) << CPUName; |
315 | } |
316 | } else { |
317 | D.Diag(diag::err_drv_unsupported_option_argument) |
318 | << A->getOption().getName() << Val; |
319 | } |
320 | } |
321 | |
322 | AddTargetFeature(Args, Features, options::OPT_msingle_float, |
323 | options::OPT_mdouble_float, "single-float"); |
324 | AddTargetFeature(Args, Features, options::OPT_mips16, options::OPT_mno_mips16, |
325 | "mips16"); |
326 | AddTargetFeature(Args, Features, options::OPT_mmicromips, |
327 | options::OPT_mno_micromips, "micromips"); |
328 | AddTargetFeature(Args, Features, options::OPT_mdsp, options::OPT_mno_dsp, |
329 | "dsp"); |
330 | AddTargetFeature(Args, Features, options::OPT_mdspr2, options::OPT_mno_dspr2, |
331 | "dspr2"); |
332 | AddTargetFeature(Args, Features, options::OPT_mmsa, options::OPT_mno_msa, |
333 | "msa"); |
334 | |
335 | |
336 | |
337 | |
338 | if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx, |
339 | options::OPT_mfp64)) { |
340 | if (A->getOption().matches(options::OPT_mfp32)) |
341 | Features.push_back("-fp64"); |
342 | else if (A->getOption().matches(options::OPT_mfpxx)) { |
343 | Features.push_back("+fpxx"); |
344 | Features.push_back("+nooddspreg"); |
345 | } else |
346 | Features.push_back("+fp64"); |
347 | } else if (mips::shouldUseFPXX(Args, Triple, CPUName, ABIName, FloatABI)) { |
348 | Features.push_back("+fpxx"); |
349 | Features.push_back("+nooddspreg"); |
350 | } else if (mips::isFP64ADefault(Triple, CPUName)) { |
351 | Features.push_back("+fp64"); |
352 | Features.push_back("+nooddspreg"); |
353 | } |
354 | |
355 | AddTargetFeature(Args, Features, options::OPT_mno_odd_spreg, |
356 | options::OPT_modd_spreg, "nooddspreg"); |
357 | AddTargetFeature(Args, Features, options::OPT_mno_madd4, options::OPT_mmadd4, |
358 | "nomadd4"); |
359 | AddTargetFeature(Args, Features, options::OPT_mmt, options::OPT_mno_mt, "mt"); |
360 | AddTargetFeature(Args, Features, options::OPT_mcrc, options::OPT_mno_crc, |
361 | "crc"); |
362 | AddTargetFeature(Args, Features, options::OPT_mvirt, options::OPT_mno_virt, |
363 | "virt"); |
364 | AddTargetFeature(Args, Features, options::OPT_mginv, options::OPT_mno_ginv, |
365 | "ginv"); |
366 | |
367 | if (Arg *A = Args.getLastArg(options::OPT_mindirect_jump_EQ)) { |
368 | StringRef Val = StringRef(A->getValue()); |
369 | if (Val == "hazard") { |
370 | Arg *B = |
371 | Args.getLastArg(options::OPT_mmicromips, options::OPT_mno_micromips); |
372 | Arg *C = Args.getLastArg(options::OPT_mips16, options::OPT_mno_mips16); |
373 | |
374 | if (B && B->getOption().matches(options::OPT_mmicromips)) |
375 | D.Diag(diag::err_drv_unsupported_indirect_jump_opt) |
376 | << "hazard" << "micromips"; |
377 | else if (C && C->getOption().matches(options::OPT_mips16)) |
378 | D.Diag(diag::err_drv_unsupported_indirect_jump_opt) |
379 | << "hazard" << "mips16"; |
380 | else if (mips::supportsIndirectJumpHazardBarrier(CPUName)) |
381 | Features.push_back("+use-indirect-jump-hazard"); |
382 | else |
383 | D.Diag(diag::err_drv_unsupported_indirect_jump_opt) |
384 | << "hazard" << CPUName; |
385 | } else |
386 | D.Diag(diag::err_drv_unknown_indirect_jump_opt) << Val; |
387 | } |
388 | } |
389 | |
390 | mips::IEEE754Standard mips::getIEEE754Standard(StringRef &CPU) { |
391 | |
392 | |
393 | |
394 | |
395 | return (IEEE754Standard)llvm::StringSwitch<int>(CPU) |
396 | .Case("mips1", Legacy) |
397 | .Case("mips2", Legacy) |
398 | .Case("mips3", Legacy) |
399 | .Case("mips4", Legacy) |
400 | .Case("mips5", Legacy) |
401 | .Case("mips32", Legacy) |
402 | .Case("mips32r2", Legacy | Std2008) |
403 | .Case("mips32r3", Legacy | Std2008) |
404 | .Case("mips32r5", Legacy | Std2008) |
405 | .Case("mips32r6", Std2008) |
406 | .Case("mips64", Legacy) |
407 | .Case("mips64r2", Legacy | Std2008) |
408 | .Case("mips64r3", Legacy | Std2008) |
409 | .Case("mips64r5", Legacy | Std2008) |
410 | .Case("mips64r6", Std2008) |
411 | .Default(Std2008); |
412 | } |
413 | |
414 | bool mips::hasCompactBranches(StringRef &CPU) { |
415 | |
416 | return llvm::StringSwitch<bool>(CPU) |
417 | .Case("mips32r6", true) |
418 | .Case("mips64r6", true) |
419 | .Default(false); |
420 | } |
421 | |
422 | bool mips::hasMipsAbiArg(const ArgList &Args, const char *Value) { |
423 | Arg *A = Args.getLastArg(options::OPT_mabi_EQ); |
424 | return A && (A->getValue() == StringRef(Value)); |
425 | } |
426 | |
427 | bool mips::isUCLibc(const ArgList &Args) { |
428 | Arg *A = Args.getLastArg(options::OPT_m_libc_Group); |
429 | return A && A->getOption().matches(options::OPT_muclibc); |
430 | } |
431 | |
432 | bool mips::isNaN2008(const ArgList &Args, const llvm::Triple &Triple) { |
433 | if (Arg *NaNArg = Args.getLastArg(options::OPT_mnan_EQ)) |
434 | return llvm::StringSwitch<bool>(NaNArg->getValue()) |
435 | .Case("2008", true) |
436 | .Case("legacy", false) |
437 | .Default(false); |
438 | |
439 | |
440 | return llvm::StringSwitch<bool>(getCPUName(Args, Triple)) |
441 | .Cases("mips32r6", "mips64r6", true) |
442 | .Default(false); |
443 | |
444 | return false; |
445 | } |
446 | |
447 | bool mips::isFP64ADefault(const llvm::Triple &Triple, StringRef CPUName) { |
448 | if (!Triple.isAndroid()) |
449 | return false; |
450 | |
451 | |
452 | return llvm::StringSwitch<bool>(CPUName) |
453 | .Case("mips32r6", true) |
454 | .Default(false); |
455 | } |
456 | |
457 | bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName, |
458 | StringRef ABIName, mips::FloatABI FloatABI) { |
459 | if (Triple.getVendor() != llvm::Triple::ImaginationTechnologies && |
460 | Triple.getVendor() != llvm::Triple::MipsTechnologies && |
461 | !Triple.isAndroid()) |
462 | return false; |
463 | |
464 | if (ABIName != "32") |
465 | return false; |
466 | |
467 | |
468 | |
469 | if (FloatABI == mips::FloatABI::Soft) |
470 | return false; |
471 | |
472 | return llvm::StringSwitch<bool>(CPUName) |
473 | .Cases("mips2", "mips3", "mips4", "mips5", true) |
474 | .Cases("mips32", "mips32r2", "mips32r3", "mips32r5", true) |
475 | .Cases("mips64", "mips64r2", "mips64r3", "mips64r5", true) |
476 | .Default(false); |
477 | } |
478 | |
479 | bool mips::shouldUseFPXX(const ArgList &Args, const llvm::Triple &Triple, |
480 | StringRef CPUName, StringRef ABIName, |
481 | mips::FloatABI FloatABI) { |
482 | bool UseFPXX = isFPXXDefault(Triple, CPUName, ABIName, FloatABI); |
483 | |
484 | |
485 | if (Arg *A = Args.getLastArg(options::OPT_msingle_float, |
486 | options::OPT_mdouble_float)) |
487 | if (A->getOption().matches(options::OPT_msingle_float)) |
488 | UseFPXX = false; |
489 | |
490 | return UseFPXX; |
491 | } |
492 | |
493 | bool mips::supportsIndirectJumpHazardBarrier(StringRef &CPU) { |
494 | |
495 | |
496 | return llvm::StringSwitch<bool>(CPU) |
497 | .Case("mips32r2", true) |
498 | .Case("mips32r3", true) |
499 | .Case("mips32r5", true) |
500 | .Case("mips32r6", true) |
501 | .Case("mips64r2", true) |
502 | .Case("mips64r3", true) |
503 | .Case("mips64r5", true) |
504 | .Case("mips64r6", true) |
505 | .Case("octeon", true) |
506 | .Case("p5600", true) |
507 | .Default(false); |
508 | } |
509 | |