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/AArch64.cpp
35294 views
1
//===--- AArch64.cpp - AArch64 (not ARM) Helpers for Tools ------*- 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 "AArch64.h"
10
#include "../CommonArgs.h"
11
#include "clang/Driver/Driver.h"
12
#include "clang/Driver/DriverDiagnostic.h"
13
#include "clang/Driver/Options.h"
14
#include "llvm/Option/ArgList.h"
15
#include "llvm/TargetParser/AArch64TargetParser.h"
16
#include "llvm/TargetParser/Host.h"
17
18
using namespace clang::driver;
19
using namespace clang::driver::tools;
20
using namespace clang;
21
using namespace llvm::opt;
22
23
/// \returns true if the given triple can determine the default CPU type even
24
/// if -arch is not specified.
25
static bool isCPUDeterminedByTriple(const llvm::Triple &Triple) {
26
return Triple.isOSDarwin();
27
}
28
29
/// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are
30
/// targeting. Set \p A to the Arg corresponding to the -mcpu argument if it is
31
/// provided, or to nullptr otherwise.
32
std::string aarch64::getAArch64TargetCPU(const ArgList &Args,
33
const llvm::Triple &Triple, Arg *&A) {
34
std::string CPU;
35
// If we have -mcpu, use that.
36
if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) {
37
StringRef Mcpu = A->getValue();
38
CPU = Mcpu.split("+").first.lower();
39
}
40
41
CPU = llvm::AArch64::resolveCPUAlias(CPU);
42
43
// Handle CPU name is 'native'.
44
if (CPU == "native")
45
return std::string(llvm::sys::getHostCPUName());
46
47
if (CPU.size())
48
return CPU;
49
50
if (Triple.isTargetMachineMac() &&
51
Triple.getArch() == llvm::Triple::aarch64) {
52
// Apple Silicon macs default to M1 CPUs.
53
return "apple-m1";
54
}
55
56
if (Triple.isXROS()) {
57
// The xrOS simulator runs on M1 as well, it should have been covered above.
58
assert(!Triple.isSimulatorEnvironment() && "xrossim should be mac-like");
59
return "apple-a12";
60
}
61
// arm64e requires v8.3a and only runs on apple-a12 and later CPUs.
62
if (Triple.isArm64e())
63
return "apple-a12";
64
65
// Make sure we pick the appropriate Apple CPU when targetting a Darwin OS.
66
if (Triple.isOSDarwin())
67
return Triple.getArch() == llvm::Triple::aarch64_32 ? "apple-s4"
68
: "apple-a7";
69
70
return "generic";
71
}
72
73
// Decode AArch64 features from string like +[no]featureA+[no]featureB+...
74
static bool DecodeAArch64Features(const Driver &D, StringRef text,
75
llvm::AArch64::ExtensionSet &Extensions) {
76
SmallVector<StringRef, 8> Split;
77
text.split(Split, StringRef("+"), -1, false);
78
79
for (StringRef Feature : Split) {
80
if (Feature == "neon" || Feature == "noneon") {
81
D.Diag(clang::diag::err_drv_no_neon_modifier);
82
continue;
83
}
84
if (!Extensions.parseModifier(Feature))
85
return false;
86
}
87
88
return true;
89
}
90
91
// Check if the CPU name and feature modifiers in -mcpu are legal. If yes,
92
// decode CPU and feature.
93
static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU,
94
llvm::AArch64::ExtensionSet &Extensions) {
95
std::pair<StringRef, StringRef> Split = Mcpu.split("+");
96
CPU = Split.first;
97
98
if (CPU == "native")
99
CPU = llvm::sys::getHostCPUName();
100
101
const std::optional<llvm::AArch64::CpuInfo> CpuInfo =
102
llvm::AArch64::parseCpu(CPU);
103
if (!CpuInfo)
104
return false;
105
106
Extensions.addCPUDefaults(*CpuInfo);
107
108
if (Split.second.size() &&
109
!DecodeAArch64Features(D, Split.second, Extensions))
110
return false;
111
112
return true;
113
}
114
115
static bool
116
getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March,
117
const ArgList &Args,
118
llvm::AArch64::ExtensionSet &Extensions) {
119
std::string MarchLowerCase = March.lower();
120
std::pair<StringRef, StringRef> Split = StringRef(MarchLowerCase).split("+");
121
122
const llvm::AArch64::ArchInfo *ArchInfo =
123
llvm::AArch64::parseArch(Split.first);
124
if (Split.first == "native")
125
ArchInfo = llvm::AArch64::getArchForCpu(llvm::sys::getHostCPUName().str());
126
if (!ArchInfo)
127
return false;
128
129
Extensions.addArchDefaults(*ArchInfo);
130
131
if ((Split.second.size() &&
132
!DecodeAArch64Features(D, Split.second, Extensions)))
133
return false;
134
135
return true;
136
}
137
138
static bool
139
getAArch64ArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
140
const ArgList &Args,
141
llvm::AArch64::ExtensionSet &Extensions) {
142
StringRef CPU;
143
std::string McpuLowerCase = Mcpu.lower();
144
if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, Extensions))
145
return false;
146
147
return true;
148
}
149
150
static bool
151
getAArch64MicroArchFeaturesFromMtune(const Driver &D, StringRef Mtune,
152
const ArgList &Args,
153
std::vector<StringRef> &Features) {
154
std::string MtuneLowerCase = Mtune.lower();
155
// Check CPU name is valid, but ignore any extensions on it.
156
llvm::AArch64::ExtensionSet Extensions;
157
StringRef Tune;
158
if (!DecodeAArch64Mcpu(D, MtuneLowerCase, Tune, Extensions))
159
return false;
160
161
// Handle CPU name is 'native'.
162
if (MtuneLowerCase == "native")
163
MtuneLowerCase = std::string(llvm::sys::getHostCPUName());
164
165
// 'cyclone' and later have zero-cycle register moves and zeroing.
166
if (MtuneLowerCase == "cyclone" ||
167
StringRef(MtuneLowerCase).starts_with("apple")) {
168
Features.push_back("+zcm");
169
Features.push_back("+zcz");
170
}
171
172
return true;
173
}
174
175
static bool
176
getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
177
const ArgList &Args,
178
std::vector<StringRef> &Features) {
179
StringRef CPU;
180
// Check CPU name is valid, but ignore any extensions on it.
181
llvm::AArch64::ExtensionSet DecodedFeature;
182
std::string McpuLowerCase = Mcpu.lower();
183
if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, DecodedFeature))
184
return false;
185
186
return getAArch64MicroArchFeaturesFromMtune(D, CPU, Args, Features);
187
}
188
189
void aarch64::getAArch64TargetFeatures(const Driver &D,
190
const llvm::Triple &Triple,
191
const ArgList &Args,
192
std::vector<StringRef> &Features,
193
bool ForAS) {
194
Arg *A;
195
bool success = true;
196
llvm::StringRef WaMArch;
197
llvm::AArch64::ExtensionSet Extensions;
198
if (ForAS)
199
for (const auto *A :
200
Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler))
201
for (StringRef Value : A->getValues())
202
if (Value.starts_with("-march="))
203
WaMArch = Value.substr(7);
204
// Call getAArch64ArchFeaturesFromMarch only if "-Wa,-march=" or
205
// "-Xassembler -march" is detected. Otherwise it may return false
206
// and causes Clang to error out.
207
if (!WaMArch.empty())
208
success = getAArch64ArchFeaturesFromMarch(D, WaMArch, Args, Extensions);
209
else if ((A = Args.getLastArg(options::OPT_march_EQ)))
210
success =
211
getAArch64ArchFeaturesFromMarch(D, A->getValue(), Args, Extensions);
212
else if ((A = Args.getLastArg(options::OPT_mcpu_EQ)))
213
success =
214
getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Extensions);
215
else if (isCPUDeterminedByTriple(Triple))
216
success = getAArch64ArchFeaturesFromMcpu(
217
D, getAArch64TargetCPU(Args, Triple, A), Args, Extensions);
218
else
219
// Default to 'A' profile if the architecture is not specified.
220
success = getAArch64ArchFeaturesFromMarch(D, "armv8-a", Args, Extensions);
221
222
if (success && (A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)))
223
success =
224
getAArch64MicroArchFeaturesFromMtune(D, A->getValue(), Args, Features);
225
else if (success && (A = Args.getLastArg(options::OPT_mcpu_EQ)))
226
success =
227
getAArch64MicroArchFeaturesFromMcpu(D, A->getValue(), Args, Features);
228
else if (success && isCPUDeterminedByTriple(Triple))
229
success = getAArch64MicroArchFeaturesFromMcpu(
230
D, getAArch64TargetCPU(Args, Triple, A), Args, Features);
231
232
if (!success) {
233
auto Diag = D.Diag(diag::err_drv_unsupported_option_argument);
234
// If "-Wa,-march=" is used, 'WaMArch' will contain the argument's value,
235
// while 'A' is uninitialized. Only dereference 'A' in the other case.
236
if (!WaMArch.empty())
237
Diag << "-march=" << WaMArch;
238
else
239
Diag << A->getSpelling() << A->getValue();
240
}
241
242
// -mgeneral-regs-only disables all floating-point features.
243
if (Args.getLastArg(options::OPT_mgeneral_regs_only)) {
244
Extensions.disable(llvm::AArch64::AEK_FP);
245
}
246
247
// En/disable crc
248
if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) {
249
if (A->getOption().matches(options::OPT_mcrc))
250
Extensions.enable(llvm::AArch64::AEK_CRC);
251
else
252
Extensions.disable(llvm::AArch64::AEK_CRC);
253
}
254
255
// At this point all hardware features are decided, so convert the extensions
256
// set to a feature list.
257
Extensions.toLLVMFeatureList(Features);
258
259
if (Arg *A = Args.getLastArg(options::OPT_mtp_mode_EQ)) {
260
StringRef Mtp = A->getValue();
261
if (Mtp == "el3" || Mtp == "tpidr_el3")
262
Features.push_back("+tpidr-el3");
263
else if (Mtp == "el2" || Mtp == "tpidr_el2")
264
Features.push_back("+tpidr-el2");
265
else if (Mtp == "el1" || Mtp == "tpidr_el1")
266
Features.push_back("+tpidr-el1");
267
else if (Mtp == "tpidrro_el0")
268
Features.push_back("+tpidrro-el0");
269
else if (Mtp != "el0" && Mtp != "tpidr_el0")
270
D.Diag(diag::err_drv_invalid_mtp) << A->getAsString(Args);
271
}
272
273
// Enable/disable straight line speculation hardening.
274
if (Arg *A = Args.getLastArg(options::OPT_mharden_sls_EQ)) {
275
StringRef Scope = A->getValue();
276
bool EnableRetBr = false;
277
bool EnableBlr = false;
278
bool DisableComdat = false;
279
if (Scope != "none") {
280
SmallVector<StringRef, 4> Opts;
281
Scope.split(Opts, ",");
282
for (auto Opt : Opts) {
283
Opt = Opt.trim();
284
if (Opt == "all") {
285
EnableBlr = true;
286
EnableRetBr = true;
287
continue;
288
}
289
if (Opt == "retbr") {
290
EnableRetBr = true;
291
continue;
292
}
293
if (Opt == "blr") {
294
EnableBlr = true;
295
continue;
296
}
297
if (Opt == "comdat") {
298
DisableComdat = false;
299
continue;
300
}
301
if (Opt == "nocomdat") {
302
DisableComdat = true;
303
continue;
304
}
305
D.Diag(diag::err_drv_unsupported_option_argument)
306
<< A->getSpelling() << Scope;
307
break;
308
}
309
}
310
311
if (EnableRetBr)
312
Features.push_back("+harden-sls-retbr");
313
if (EnableBlr)
314
Features.push_back("+harden-sls-blr");
315
if (DisableComdat) {
316
Features.push_back("+harden-sls-nocomdat");
317
}
318
}
319
320
if (Arg *A = Args.getLastArg(
321
options::OPT_mstrict_align, options::OPT_mno_strict_align,
322
options::OPT_mno_unaligned_access, options::OPT_munaligned_access)) {
323
if (A->getOption().matches(options::OPT_mstrict_align) ||
324
A->getOption().matches(options::OPT_mno_unaligned_access))
325
Features.push_back("+strict-align");
326
} else if (Triple.isOSOpenBSD())
327
Features.push_back("+strict-align");
328
329
if (Args.hasArg(options::OPT_ffixed_x1))
330
Features.push_back("+reserve-x1");
331
332
if (Args.hasArg(options::OPT_ffixed_x2))
333
Features.push_back("+reserve-x2");
334
335
if (Args.hasArg(options::OPT_ffixed_x3))
336
Features.push_back("+reserve-x3");
337
338
if (Args.hasArg(options::OPT_ffixed_x4))
339
Features.push_back("+reserve-x4");
340
341
if (Args.hasArg(options::OPT_ffixed_x5))
342
Features.push_back("+reserve-x5");
343
344
if (Args.hasArg(options::OPT_ffixed_x6))
345
Features.push_back("+reserve-x6");
346
347
if (Args.hasArg(options::OPT_ffixed_x7))
348
Features.push_back("+reserve-x7");
349
350
if (Args.hasArg(options::OPT_ffixed_x9))
351
Features.push_back("+reserve-x9");
352
353
if (Args.hasArg(options::OPT_ffixed_x10))
354
Features.push_back("+reserve-x10");
355
356
if (Args.hasArg(options::OPT_ffixed_x11))
357
Features.push_back("+reserve-x11");
358
359
if (Args.hasArg(options::OPT_ffixed_x12))
360
Features.push_back("+reserve-x12");
361
362
if (Args.hasArg(options::OPT_ffixed_x13))
363
Features.push_back("+reserve-x13");
364
365
if (Args.hasArg(options::OPT_ffixed_x14))
366
Features.push_back("+reserve-x14");
367
368
if (Args.hasArg(options::OPT_ffixed_x15))
369
Features.push_back("+reserve-x15");
370
371
if (Args.hasArg(options::OPT_ffixed_x18))
372
Features.push_back("+reserve-x18");
373
374
if (Args.hasArg(options::OPT_ffixed_x20))
375
Features.push_back("+reserve-x20");
376
377
if (Args.hasArg(options::OPT_ffixed_x21))
378
Features.push_back("+reserve-x21");
379
380
if (Args.hasArg(options::OPT_ffixed_x22))
381
Features.push_back("+reserve-x22");
382
383
if (Args.hasArg(options::OPT_ffixed_x23))
384
Features.push_back("+reserve-x23");
385
386
if (Args.hasArg(options::OPT_ffixed_x24))
387
Features.push_back("+reserve-x24");
388
389
if (Args.hasArg(options::OPT_ffixed_x25))
390
Features.push_back("+reserve-x25");
391
392
if (Args.hasArg(options::OPT_ffixed_x26))
393
Features.push_back("+reserve-x26");
394
395
if (Args.hasArg(options::OPT_ffixed_x27))
396
Features.push_back("+reserve-x27");
397
398
if (Args.hasArg(options::OPT_ffixed_x28))
399
Features.push_back("+reserve-x28");
400
401
if (Args.hasArg(options::OPT_mlr_for_calls_only))
402
Features.push_back("+reserve-lr-for-ra");
403
404
if (Args.hasArg(options::OPT_fcall_saved_x8))
405
Features.push_back("+call-saved-x8");
406
407
if (Args.hasArg(options::OPT_fcall_saved_x9))
408
Features.push_back("+call-saved-x9");
409
410
if (Args.hasArg(options::OPT_fcall_saved_x10))
411
Features.push_back("+call-saved-x10");
412
413
if (Args.hasArg(options::OPT_fcall_saved_x11))
414
Features.push_back("+call-saved-x11");
415
416
if (Args.hasArg(options::OPT_fcall_saved_x12))
417
Features.push_back("+call-saved-x12");
418
419
if (Args.hasArg(options::OPT_fcall_saved_x13))
420
Features.push_back("+call-saved-x13");
421
422
if (Args.hasArg(options::OPT_fcall_saved_x14))
423
Features.push_back("+call-saved-x14");
424
425
if (Args.hasArg(options::OPT_fcall_saved_x15))
426
Features.push_back("+call-saved-x15");
427
428
if (Args.hasArg(options::OPT_fcall_saved_x18))
429
Features.push_back("+call-saved-x18");
430
431
if (Args.hasArg(options::OPT_mno_neg_immediates))
432
Features.push_back("+no-neg-immediates");
433
434
if (Arg *A = Args.getLastArg(options::OPT_mfix_cortex_a53_835769,
435
options::OPT_mno_fix_cortex_a53_835769)) {
436
if (A->getOption().matches(options::OPT_mfix_cortex_a53_835769))
437
Features.push_back("+fix-cortex-a53-835769");
438
else
439
Features.push_back("-fix-cortex-a53-835769");
440
} else if (Triple.isAndroid() || Triple.isOHOSFamily()) {
441
// Enabled A53 errata (835769) workaround by default on android
442
Features.push_back("+fix-cortex-a53-835769");
443
} else if (Triple.isOSFuchsia()) {
444
std::string CPU = getCPUName(D, Args, Triple);
445
if (CPU.empty() || CPU == "generic" || CPU == "cortex-a53")
446
Features.push_back("+fix-cortex-a53-835769");
447
}
448
449
if (Args.getLastArg(options::OPT_mno_bti_at_return_twice))
450
Features.push_back("+no-bti-at-return-twice");
451
}
452
453
void aarch64::setPAuthABIInTriple(const Driver &D, const ArgList &Args,
454
llvm::Triple &Triple) {
455
Arg *ABIArg = Args.getLastArg(options::OPT_mabi_EQ);
456
bool HasPAuthABI =
457
ABIArg ? (StringRef(ABIArg->getValue()) == "pauthtest") : false;
458
459
switch (Triple.getEnvironment()) {
460
case llvm::Triple::UnknownEnvironment:
461
if (HasPAuthABI)
462
Triple.setEnvironment(llvm::Triple::PAuthTest);
463
break;
464
case llvm::Triple::PAuthTest:
465
break;
466
default:
467
if (HasPAuthABI)
468
D.Diag(diag::err_drv_unsupported_opt_for_target)
469
<< ABIArg->getAsString(Args) << Triple.getTriple();
470
break;
471
}
472
}
473
474