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