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
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(S: "32", Value: "o32")
63 .Case(S: "64", Value: "n64")
64 .Default(Value: 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(S: "mips1", Value: "o32")
91 .Case(S: "mips2", Value: "o32")
92 .Case(S: "mips3", Value: "n64")
93 .Case(S: "mips4", Value: "n64")
94 .Case(S: "mips5", Value: "n64")
95 .Case(S: "mips32", Value: "o32")
96 .Case(S: "mips32r2", Value: "o32")
97 .Case(S: "mips32r3", Value: "o32")
98 .Case(S: "mips32r5", Value: "o32")
99 .Case(S: "mips32r6", Value: "o32")
100 .Case(S: "mips64", Value: "n64")
101 .Case(S: "mips64r2", Value: "n64")
102 .Case(S: "mips64r3", Value: "n64")
103 .Case(S: "mips64r5", Value: "n64")
104 .Case(S: "mips64r6", Value: "n64")
105 .Case(S: "octeon", Value: "n64")
106 .Case(S: "p5600", Value: "o32")
107 .Default(Value: "");
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(S: "o32", Value: DefMips32CPU)
119 .Cases(S0: "n32", S1: "n64", Value: DefMips64CPU)
120 .Default(Value: "");
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(S: "o32", Value: "")
132 .Case(S: "n32", Value: "32")
133 .Case(S: "n64", Value: "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(S: "o32", Value: "32")
140 .Case(S: "n64", Value: "64")
141 .Default(Value: 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::ID: OPT_msoft_float))
153 ABI = mips::FloatABI::Soft;
154 else if (A->getOption().matches(options::ID: OPT_mhard_float))
155 ABI = mips::FloatABI::Hard;
156 else {
157 ABI = llvm::StringSwitch<mips::FloatABI>(A->getValue())
158 .Case(S: "soft", Value: mips::FloatABI::Soft)
159 .Case(S: "hard", Value: mips::FloatABI::Hard)
160 .Default(Value: mips::FloatABI::Invalid);
161 if (ABI == mips::FloatABI::Invalid && !StringRef(A->getValue()).empty()) {
162 D.Diag(clang::diag::DiagID: 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(ABI: 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 bool HasNaN2008Opt = false;
225
226 Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
227 options::OPT_fpic, options::OPT_fno_pic,
228 options::OPT_fPIE, options::OPT_fno_PIE,
229 options::OPT_fpie, options::OPT_fno_pie);
230 if (LastPICArg) {
231 Option O = LastPICArg->getOption();
232 NonPIC =
233 (O.matches(options::ID: OPT_fno_PIC) || O.matches(options::ID: OPT_fno_pic) ||
234 O.matches(options::ID: OPT_fno_PIE) || O.matches(options::ID: OPT_fno_pie));
235 IsPIC =
236 (O.matches(options::ID: OPT_fPIC) || O.matches(options::ID: OPT_fpic) ||
237 O.matches(options::ID: OPT_fPIE) || O.matches(options::ID: OPT_fpie));
238 }
239
240 bool UseAbiCalls = false;
241
242 Arg *ABICallsArg =
243 Args.getLastArg(options::OPT_mabicalls, options::OPT_mno_abicalls);
244 UseAbiCalls =
245 !ABICallsArg || ABICallsArg->getOption().matches(options::ID: OPT_mabicalls);
246
247 if (IsN64 && NonPIC && (!ABICallsArg || UseAbiCalls)) {
248 D.Diag(diag::DiagID: warn_drv_unsupported_pic_with_mabicalls)
249 << LastPICArg->getAsString(Args) << (!ABICallsArg ? 0 : 1);
250 }
251
252 if (ABICallsArg && !UseAbiCalls && IsPIC) {
253 D.Diag(diag::DiagID: err_drv_unsupported_noabicalls_pic);
254 }
255
256 if (!UseAbiCalls)
257 Features.push_back(x: "+noabicalls");
258 else
259 Features.push_back(x: "-noabicalls");
260
261 if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,
262 options::OPT_mno_long_calls)) {
263 if (A->getOption().matches(options::ID: OPT_mno_long_calls))
264 Features.push_back(x: "-long-calls");
265 else if (!UseAbiCalls)
266 Features.push_back(x: "+long-calls");
267 else
268 D.Diag(diag::DiagID: warn_drv_unsupported_longcalls) << (ABICallsArg ? 0 : 1);
269 }
270
271 if (Arg *A = Args.getLastArg(options::OPT_mxgot, options::OPT_mno_xgot)) {
272 if (A->getOption().matches(options::ID: OPT_mxgot))
273 Features.push_back(x: "+xgot");
274 else
275 Features.push_back(x: "-xgot");
276 }
277
278 mips::FloatABI FloatABI = mips::getMipsFloatABI(D, Args, Triple);
279 if (FloatABI == mips::FloatABI::Soft) {
280 // FIXME: Note, this is a hack. We need to pass the selected float
281 // mode to the MipsTargetInfoBase to define appropriate macros there.
282 // Now it is the only method.
283 Features.push_back(x: "+soft-float");
284 }
285
286 if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) {
287 StringRef Val = StringRef(A->getValue());
288 if (Val == "2008") {
289 if (mips::getIEEE754Standard(CPU&: CPUName) & mips::Std2008) {
290 Features.push_back(x: "+nan2008");
291 HasNaN2008Opt = true;
292 } else {
293 Features.push_back(x: "-nan2008");
294 D.Diag(diag::DiagID: warn_target_unsupported_nan2008) << CPUName;
295 }
296 } else if (Val == "legacy") {
297 if (mips::getIEEE754Standard(CPU&: CPUName) & mips::Legacy)
298 Features.push_back(x: "-nan2008");
299 else {
300 Features.push_back(x: "+nan2008");
301 D.Diag(diag::DiagID: warn_target_unsupported_nanlegacy) << CPUName;
302 }
303 } else
304 D.Diag(diag::DiagID: err_drv_unsupported_option_argument)
305 << A->getSpelling() << Val;
306 }
307
308 if (Arg *A = Args.getLastArg(options::OPT_mabs_EQ)) {
309 StringRef Val = StringRef(A->getValue());
310 if (Val == "2008") {
311 if (mips::getIEEE754Standard(CPU&: CPUName) & mips::Std2008) {
312 Features.push_back(x: "+abs2008");
313 } else {
314 Features.push_back(x: "-abs2008");
315 D.Diag(diag::DiagID: warn_target_unsupported_abs2008) << CPUName;
316 }
317 } else if (Val == "legacy") {
318 if (mips::getIEEE754Standard(CPU&: CPUName) & mips::Legacy) {
319 Features.push_back(x: "-abs2008");
320 } else {
321 Features.push_back(x: "+abs2008");
322 D.Diag(diag::DiagID: warn_target_unsupported_abslegacy) << CPUName;
323 }
324 } else {
325 D.Diag(diag::DiagID: err_drv_unsupported_option_argument)
326 << A->getSpelling() << Val;
327 }
328 } else if (HasNaN2008Opt) {
329 Features.push_back(x: "+abs2008");
330 }
331
332 AddTargetFeature(Args, Features, options::OPT_msingle_float,
333 options::OPT_mdouble_float, "single-float");
334 AddTargetFeature(Args, Features, options::OPT_mips16, options::OPT_mno_mips16,
335 "mips16");
336 AddTargetFeature(Args, Features, options::OPT_mmicromips,
337 options::OPT_mno_micromips, "micromips");
338 AddTargetFeature(Args, Features, options::OPT_mdsp, options::OPT_mno_dsp,
339 "dsp");
340 AddTargetFeature(Args, Features, options::OPT_mdspr2, options::OPT_mno_dspr2,
341 "dspr2");
342 AddTargetFeature(Args, Features, options::OPT_mmsa, options::OPT_mno_msa,
343 "msa");
344 if (Arg *A = Args.getLastArg(
345 options::OPT_mstrict_align, options::OPT_mno_strict_align,
346 options::OPT_mno_unaligned_access, options::OPT_munaligned_access)) {
347 if (A->getOption().matches(options::OPT_mstrict_align) ||
348 A->getOption().matches(options::OPT_mno_unaligned_access))
349 Features.push_back(x: Args.MakeArgString(Str: "+strict-align"));
350 else
351 Features.push_back(x: Args.MakeArgString(Str: "-strict-align"));
352 }
353
354 // Add the last -mfp32/-mfpxx/-mfp64, if none are given and the ABI is O32
355 // pass -mfpxx, or if none are given and fp64a is default, pass fp64 and
356 // nooddspreg.
357 if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx,
358 options::OPT_mfp64)) {
359 if (A->getOption().matches(options::OPT_mfp32))
360 Features.push_back(x: "-fp64");
361 else if (A->getOption().matches(options::OPT_mfpxx)) {
362 Features.push_back(x: "+fpxx");
363 Features.push_back(x: "+nooddspreg");
364 } else
365 Features.push_back(x: "+fp64");
366 } else if (mips::shouldUseFPXX(Args, Triple, CPUName, ABIName, FloatABI)) {
367 Features.push_back(x: "+fpxx");
368 Features.push_back(x: "+nooddspreg");
369 } else if (mips::isFP64ADefault(Triple, CPUName)) {
370 Features.push_back(x: "+fp64");
371 Features.push_back(x: "+nooddspreg");
372 }
373
374 AddTargetFeature(Args, Features, options::OPT_mno_odd_spreg,
375 options::OPT_modd_spreg, "nooddspreg");
376 AddTargetFeature(Args, Features, options::OPT_mno_madd4, options::OPT_mmadd4,
377 "nomadd4");
378 AddTargetFeature(Args, Features, options::OPT_mmt, options::OPT_mno_mt, "mt");
379 AddTargetFeature(Args, Features, options::OPT_mcrc, options::OPT_mno_crc,
380 "crc");
381 AddTargetFeature(Args, Features, options::OPT_mvirt, options::OPT_mno_virt,
382 "virt");
383 AddTargetFeature(Args, Features, options::OPT_mginv, options::OPT_mno_ginv,
384 "ginv");
385
386 if (Arg *A = Args.getLastArg(options::OPT_mindirect_jump_EQ)) {
387 StringRef Val = StringRef(A->getValue());
388 if (Val == "hazard") {
389 Arg *B =
390 Args.getLastArg(options::OPT_mmicromips, options::OPT_mno_micromips);
391 Arg *C = Args.getLastArg(options::OPT_mips16, options::OPT_mno_mips16);
392
393 if (B && B->getOption().matches(options::OPT_mmicromips))
394 D.Diag(diag::err_drv_unsupported_indirect_jump_opt)
395 << "hazard" << "micromips";
396 else if (C && C->getOption().matches(options::OPT_mips16))
397 D.Diag(diag::err_drv_unsupported_indirect_jump_opt)
398 << "hazard" << "mips16";
399 else if (mips::supportsIndirectJumpHazardBarrier(CPU&: CPUName))
400 Features.push_back(x: "+use-indirect-jump-hazard");
401 else
402 D.Diag(diag::err_drv_unsupported_indirect_jump_opt)
403 << "hazard" << CPUName;
404 } else
405 D.Diag(diag::err_drv_unknown_indirect_jump_opt) << Val;
406 }
407}
408
409mips::IEEE754Standard mips::getIEEE754Standard(StringRef &CPU) {
410 // Strictly speaking, mips32r2 and mips64r2 do not conform to the
411 // IEEE754-2008 standard. Support for this standard was first introduced
412 // in Release 3. However, other compilers have traditionally allowed it
413 // for Release 2 so we should do the same.
414 return (IEEE754Standard)llvm::StringSwitch<int>(CPU)
415 .Case(S: "mips1", Value: Legacy)
416 .Case(S: "mips2", Value: Legacy)
417 .Case(S: "mips3", Value: Legacy)
418 .Case(S: "mips4", Value: Legacy)
419 .Case(S: "mips5", Value: Legacy)
420 .Case(S: "mips32", Value: Legacy)
421 .Case(S: "mips32r2", Value: Legacy | Std2008)
422 .Case(S: "mips32r3", Value: Legacy | Std2008)
423 .Case(S: "mips32r5", Value: Legacy | Std2008)
424 .Case(S: "mips32r6", Value: Std2008)
425 .Case(S: "mips64", Value: Legacy)
426 .Case(S: "mips64r2", Value: Legacy | Std2008)
427 .Case(S: "mips64r3", Value: Legacy | Std2008)
428 .Case(S: "mips64r5", Value: Legacy | Std2008)
429 .Case(S: "mips64r6", Value: Std2008)
430 .Default(Value: Std2008);
431}
432
433bool mips::hasCompactBranches(StringRef &CPU) {
434 // mips32r6 and mips64r6 have compact branches.
435 return llvm::StringSwitch<bool>(CPU)
436 .Case(S: "mips32r6", Value: true)
437 .Case(S: "mips64r6", Value: true)
438 .Default(Value: false);
439}
440
441bool mips::hasMipsAbiArg(const ArgList &Args, const char *Value) {
442 Arg *A = Args.getLastArg(options::OPT_mabi_EQ);
443 return A && (A->getValue() == StringRef(Value));
444}
445
446bool mips::isUCLibc(const ArgList &Args) {
447 Arg *A = Args.getLastArg(options::OPT_m_libc_Group);
448 return A && A->getOption().matches(options::OPT_muclibc);
449}
450
451bool mips::isNaN2008(const Driver &D, const ArgList &Args,
452 const llvm::Triple &Triple) {
453 if (Arg *NaNArg = Args.getLastArg(options::OPT_mnan_EQ))
454 return llvm::StringSwitch<bool>(NaNArg->getValue())
455 .Case(S: "2008", Value: true)
456 .Case(S: "legacy", Value: false)
457 .Default(Value: false);
458
459 // NaN2008 is the default for MIPS32r6/MIPS64r6.
460 return llvm::StringSwitch<bool>(getCPUName(D, Args, T: Triple))
461 .Cases(S0: "mips32r6", S1: "mips64r6", Value: true)
462 .Default(Value: false);
463}
464
465bool mips::isFP64ADefault(const llvm::Triple &Triple, StringRef CPUName) {
466 if (!Triple.isAndroid())
467 return false;
468
469 // Android MIPS32R6 defaults to FP64A.
470 return llvm::StringSwitch<bool>(CPUName)
471 .Case(S: "mips32r6", Value: true)
472 .Default(Value: false);
473}
474
475bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName,
476 StringRef ABIName, mips::FloatABI FloatABI) {
477 if (ABIName != "32")
478 return false;
479
480 // FPXX shouldn't be used if either -msoft-float or -mfloat-abi=soft is
481 // present.
482 if (FloatABI == mips::FloatABI::Soft)
483 return false;
484
485 return llvm::StringSwitch<bool>(CPUName)
486 .Cases(S0: "mips2", S1: "mips3", S2: "mips4", S3: "mips5", Value: true)
487 .Cases(S0: "mips32", S1: "mips32r2", S2: "mips32r3", S3: "mips32r5", Value: true)
488 .Cases(S0: "mips64", S1: "mips64r2", S2: "mips64r3", S3: "mips64r5", Value: true)
489 .Default(Value: false);
490}
491
492bool mips::shouldUseFPXX(const ArgList &Args, const llvm::Triple &Triple,
493 StringRef CPUName, StringRef ABIName,
494 mips::FloatABI FloatABI) {
495 bool UseFPXX = isFPXXDefault(Triple, CPUName, ABIName, FloatABI);
496
497 // FPXX shouldn't be used if -msingle-float is present.
498 if (Arg *A = Args.getLastArg(options::OPT_msingle_float,
499 options::OPT_mdouble_float))
500 if (A->getOption().matches(options::OPT_msingle_float))
501 UseFPXX = false;
502
503 return UseFPXX;
504}
505
506bool mips::supportsIndirectJumpHazardBarrier(StringRef &CPU) {
507 // Supporting the hazard barrier method of dealing with indirect
508 // jumps requires MIPSR2 support.
509 return llvm::StringSwitch<bool>(CPU)
510 .Case(S: "mips32r2", Value: true)
511 .Case(S: "mips32r3", Value: true)
512 .Case(S: "mips32r5", Value: true)
513 .Case(S: "mips32r6", Value: true)
514 .Case(S: "mips64r2", Value: true)
515 .Case(S: "mips64r3", Value: true)
516 .Case(S: "mips64r5", Value: true)
517 .Case(S: "mips64r6", Value: true)
518 .Case(S: "octeon", Value: true)
519 .Case(S: "p5600", Value: true)
520 .Default(Value: false);
521}
522

source code of clang/lib/Driver/ToolChains/Arch/Mips.cpp