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