clang 22.0.0git
Mips.cpp
Go to the documentation of this file.
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"
11#include "clang/Driver/Driver.h"
13#include "llvm/ADT/StringSwitch.h"
14#include "llvm/Option/ArgList.h"
15
16using namespace clang::driver;
17using namespace clang::driver::tools;
18using namespace clang;
19using namespace llvm::opt;
20
21// Get CPU and ABI names. They are not independent
22// so we have to calculate them together.
23void 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
127std::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.
138StringRef 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=.
147mips::FloatABI mips::getMipsFloatABI(const Driver &D, const ArgList &Args,
148 const llvm::Triple &Triple) {
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))
155 else if (A->getOption().matches(options::OPT_mhard_float))
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);
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.
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.
179 }
180 }
181
182 assert(ABI != mips::FloatABI::Invalid && "must select an ABI");
183 return ABI;
184}
185
186void 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
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") {
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") {
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") {
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";
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
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
440bool 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
448bool 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
453bool 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
458bool 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
472bool 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.
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
489bool 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
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}
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
Definition Driver.h:99
DiagnosticBuilder Diag(unsigned DiagID) const
Definition Driver.h:169
void getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args, std::vector< StringRef > &Features)
StringRef getGnuCompatibleMipsABIName(StringRef ABI)
Definition Mips.cpp:138
bool isNaN2008(const Driver &D, const llvm::opt::ArgList &Args, const llvm::Triple &Triple)
bool hasMipsAbiArg(const llvm::opt::ArgList &Args, const char *Value)
mips::FloatABI getMipsFloatABI(const Driver &D, const llvm::opt::ArgList &Args, const llvm::Triple &Triple)
std::string getMipsABILibSuffix(const llvm::opt::ArgList &Args, const llvm::Triple &Triple)
bool shouldUseFPXX(const llvm::opt::ArgList &Args, const llvm::Triple &Triple, StringRef CPUName, StringRef ABIName, mips::FloatABI FloatABI)
bool hasCompactBranches(StringRef &CPU)
Definition Mips.cpp:440
bool isUCLibc(const llvm::opt::ArgList &Args)
void getMipsCPUAndABI(const llvm::opt::ArgList &Args, const llvm::Triple &Triple, StringRef &CPUName, StringRef &ABIName)
bool isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName, StringRef ABIName, mips::FloatABI FloatABI)
Definition Mips.cpp:472
IEEE754Standard getIEEE754Standard(StringRef &CPU)
Definition Mips.cpp:416
bool supportsIndirectJumpHazardBarrier(StringRef &CPU)
Definition Mips.cpp:510
std::string getCPUName(const Driver &D, const llvm::opt::ArgList &Args, const llvm::Triple &T, bool FromAs=false)
void AddTargetFeature(const llvm::opt::ArgList &Args, std::vector< StringRef > &Features, llvm::opt::OptSpecifier OnOpt, llvm::opt::OptSpecifier OffOpt, StringRef FeatureName)
The JSON file list parser is used to communicate input to InstallAPI.