Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/Mips.cpp
35294 views
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
17
using namespace clang::driver;
18
using namespace clang::driver::tools;
19
using namespace clang;
20
using namespace llvm::opt;
21
22
// Get CPU and ABI names. They are not independent
23
// so we have to calculate them together.
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
// 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
126
std::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.
137
StringRef 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=.
146
mips::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
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
// 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::OPT_fno_PIC) || O.matches(options::OPT_fno_pic) ||
234
O.matches(options::OPT_fno_PIE) || O.matches(options::OPT_fno_pie));
235
IsPIC =
236
(O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic) ||
237
O.matches(options::OPT_fPIE) || O.matches(options::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::OPT_mabicalls);
246
247
if (IsN64 && NonPIC && (!ABICallsArg || UseAbiCalls)) {
248
D.Diag(diag::warn_drv_unsupported_pic_with_mabicalls)
249
<< LastPICArg->getAsString(Args) << (!ABICallsArg ? 0 : 1);
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
if (Arg *A = Args.getLastArg(options::OPT_mxgot, options::OPT_mno_xgot)) {
272
if (A->getOption().matches(options::OPT_mxgot))
273
Features.push_back("+xgot");
274
else
275
Features.push_back("-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("+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(CPUName) & mips::Std2008) {
290
Features.push_back("+nan2008");
291
HasNaN2008Opt = true;
292
} else {
293
Features.push_back("-nan2008");
294
D.Diag(diag::warn_target_unsupported_nan2008) << CPUName;
295
}
296
} else if (Val == "legacy") {
297
if (mips::getIEEE754Standard(CPUName) & mips::Legacy)
298
Features.push_back("-nan2008");
299
else {
300
Features.push_back("+nan2008");
301
D.Diag(diag::warn_target_unsupported_nanlegacy) << CPUName;
302
}
303
} else
304
D.Diag(diag::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(CPUName) & mips::Std2008) {
312
Features.push_back("+abs2008");
313
} else {
314
Features.push_back("-abs2008");
315
D.Diag(diag::warn_target_unsupported_abs2008) << CPUName;
316
}
317
} else if (Val == "legacy") {
318
if (mips::getIEEE754Standard(CPUName) & mips::Legacy) {
319
Features.push_back("-abs2008");
320
} else {
321
Features.push_back("+abs2008");
322
D.Diag(diag::warn_target_unsupported_abslegacy) << CPUName;
323
}
324
} else {
325
D.Diag(diag::err_drv_unsupported_option_argument)
326
<< A->getSpelling() << Val;
327
}
328
} else if (HasNaN2008Opt) {
329
Features.push_back("+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(Args.MakeArgString("+strict-align"));
350
else
351
Features.push_back(Args.MakeArgString("-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("-fp64");
361
else if (A->getOption().matches(options::OPT_mfpxx)) {
362
Features.push_back("+fpxx");
363
Features.push_back("+nooddspreg");
364
} else
365
Features.push_back("+fp64");
366
} else if (mips::shouldUseFPXX(Args, Triple, CPUName, ABIName, FloatABI)) {
367
Features.push_back("+fpxx");
368
Features.push_back("+nooddspreg");
369
} else if (mips::isFP64ADefault(Triple, CPUName)) {
370
Features.push_back("+fp64");
371
Features.push_back("+nooddspreg");
372
} else if (Arg *A = Args.getLastArg(options::OPT_mmsa)) {
373
if (A->getOption().matches(options::OPT_mmsa))
374
Features.push_back("+fp64");
375
}
376
377
AddTargetFeature(Args, Features, options::OPT_mno_odd_spreg,
378
options::OPT_modd_spreg, "nooddspreg");
379
AddTargetFeature(Args, Features, options::OPT_mno_madd4, options::OPT_mmadd4,
380
"nomadd4");
381
AddTargetFeature(Args, Features, options::OPT_mmt, options::OPT_mno_mt, "mt");
382
AddTargetFeature(Args, Features, options::OPT_mcrc, options::OPT_mno_crc,
383
"crc");
384
AddTargetFeature(Args, Features, options::OPT_mvirt, options::OPT_mno_virt,
385
"virt");
386
AddTargetFeature(Args, Features, options::OPT_mginv, options::OPT_mno_ginv,
387
"ginv");
388
389
if (Arg *A = Args.getLastArg(options::OPT_mindirect_jump_EQ)) {
390
StringRef Val = StringRef(A->getValue());
391
if (Val == "hazard") {
392
Arg *B =
393
Args.getLastArg(options::OPT_mmicromips, options::OPT_mno_micromips);
394
Arg *C = Args.getLastArg(options::OPT_mips16, options::OPT_mno_mips16);
395
396
if (B && B->getOption().matches(options::OPT_mmicromips))
397
D.Diag(diag::err_drv_unsupported_indirect_jump_opt)
398
<< "hazard" << "micromips";
399
else if (C && C->getOption().matches(options::OPT_mips16))
400
D.Diag(diag::err_drv_unsupported_indirect_jump_opt)
401
<< "hazard" << "mips16";
402
else if (mips::supportsIndirectJumpHazardBarrier(CPUName))
403
Features.push_back("+use-indirect-jump-hazard");
404
else
405
D.Diag(diag::err_drv_unsupported_indirect_jump_opt)
406
<< "hazard" << CPUName;
407
} else
408
D.Diag(diag::err_drv_unknown_indirect_jump_opt) << Val;
409
}
410
}
411
412
mips::IEEE754Standard mips::getIEEE754Standard(StringRef &CPU) {
413
// Strictly speaking, mips32r2 and mips64r2 do not conform to the
414
// IEEE754-2008 standard. Support for this standard was first introduced
415
// in Release 3. However, other compilers have traditionally allowed it
416
// for Release 2 so we should do the same.
417
return (IEEE754Standard)llvm::StringSwitch<int>(CPU)
418
.Case("mips1", Legacy)
419
.Case("mips2", Legacy)
420
.Case("mips3", Legacy)
421
.Case("mips4", Legacy)
422
.Case("mips5", Legacy)
423
.Case("mips32", Legacy)
424
.Case("mips32r2", Legacy | Std2008)
425
.Case("mips32r3", Legacy | Std2008)
426
.Case("mips32r5", Legacy | Std2008)
427
.Case("mips32r6", Std2008)
428
.Case("mips64", Legacy)
429
.Case("mips64r2", Legacy | Std2008)
430
.Case("mips64r3", Legacy | Std2008)
431
.Case("mips64r5", Legacy | Std2008)
432
.Case("mips64r6", Std2008)
433
.Default(Std2008);
434
}
435
436
bool mips::hasCompactBranches(StringRef &CPU) {
437
// mips32r6 and mips64r6 have compact branches.
438
return llvm::StringSwitch<bool>(CPU)
439
.Case("mips32r6", true)
440
.Case("mips64r6", true)
441
.Default(false);
442
}
443
444
bool mips::hasMipsAbiArg(const ArgList &Args, const char *Value) {
445
Arg *A = Args.getLastArg(options::OPT_mabi_EQ);
446
return A && (A->getValue() == StringRef(Value));
447
}
448
449
bool mips::isUCLibc(const ArgList &Args) {
450
Arg *A = Args.getLastArg(options::OPT_m_libc_Group);
451
return A && A->getOption().matches(options::OPT_muclibc);
452
}
453
454
bool mips::isNaN2008(const Driver &D, const ArgList &Args,
455
const llvm::Triple &Triple) {
456
if (Arg *NaNArg = Args.getLastArg(options::OPT_mnan_EQ))
457
return llvm::StringSwitch<bool>(NaNArg->getValue())
458
.Case("2008", true)
459
.Case("legacy", false)
460
.Default(false);
461
462
// NaN2008 is the default for MIPS32r6/MIPS64r6.
463
return llvm::StringSwitch<bool>(getCPUName(D, Args, Triple))
464
.Cases("mips32r6", "mips64r6", true)
465
.Default(false);
466
}
467
468
bool mips::isFP64ADefault(const llvm::Triple &Triple, StringRef CPUName) {
469
if (!Triple.isAndroid())
470
return false;
471
472
// Android MIPS32R6 defaults to FP64A.
473
return llvm::StringSwitch<bool>(CPUName)
474
.Case("mips32r6", true)
475
.Default(false);
476
}
477
478
bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName,
479
StringRef ABIName, mips::FloatABI FloatABI) {
480
if (ABIName != "32")
481
return false;
482
483
// FPXX shouldn't be used if either -msoft-float or -mfloat-abi=soft is
484
// present.
485
if (FloatABI == mips::FloatABI::Soft)
486
return false;
487
488
return llvm::StringSwitch<bool>(CPUName)
489
.Cases("mips2", "mips3", "mips4", "mips5", true)
490
.Cases("mips32", "mips32r2", "mips32r3", "mips32r5", true)
491
.Cases("mips64", "mips64r2", "mips64r3", "mips64r5", true)
492
.Default(false);
493
}
494
495
bool mips::shouldUseFPXX(const ArgList &Args, const llvm::Triple &Triple,
496
StringRef CPUName, StringRef ABIName,
497
mips::FloatABI FloatABI) {
498
bool UseFPXX = isFPXXDefault(Triple, CPUName, ABIName, FloatABI);
499
500
// FPXX shouldn't be used if -msingle-float is present.
501
if (Arg *A = Args.getLastArg(options::OPT_msingle_float,
502
options::OPT_mdouble_float))
503
if (A->getOption().matches(options::OPT_msingle_float))
504
UseFPXX = false;
505
// FP64 should be used for MSA.
506
if (Arg *A = Args.getLastArg(options::OPT_mmsa))
507
if (A->getOption().matches(options::OPT_mmsa))
508
UseFPXX = llvm::StringSwitch<bool>(CPUName)
509
.Cases("mips32r2", "mips32r3", "mips32r5", false)
510
.Cases("mips64r2", "mips64r3", "mips64r5", false)
511
.Default(UseFPXX);
512
513
return UseFPXX;
514
}
515
516
bool mips::supportsIndirectJumpHazardBarrier(StringRef &CPU) {
517
// Supporting the hazard barrier method of dealing with indirect
518
// jumps requires MIPSR2 support.
519
return llvm::StringSwitch<bool>(CPU)
520
.Case("mips32r2", true)
521
.Case("mips32r3", true)
522
.Case("mips32r5", true)
523
.Case("mips32r6", true)
524
.Case("mips64r2", true)
525
.Case("mips64r3", true)
526
.Case("mips64r5", true)
527
.Case("mips64r6", true)
528
.Case("octeon", true)
529
.Case("p5600", true)
530
.Default(false);
531
}
532
533