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/Support/AArch64TargetParser.h"
16 #include "llvm/Support/TargetParser.h"
17 #include "llvm/Support/Host.h"
18
19 using namespace clang::driver;
20 using namespace clang::driver::tools;
21 using namespace clang;
22 using namespace llvm::opt;
23
24 /// \returns true if the given triple can determine the default CPU type even
25 /// if -arch is not specified.
isCPUDeterminedByTriple(const llvm::Triple & Triple)26 static bool isCPUDeterminedByTriple(const llvm::Triple &Triple) {
27 return Triple.isOSDarwin();
28 }
29
30 /// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are
31 /// targeting. Set \p A to the Arg corresponding to the -mcpu argument if it is
32 /// provided, or to nullptr otherwise.
getAArch64TargetCPU(const ArgList & Args,const llvm::Triple & Triple,Arg * & A)33 std::string aarch64::getAArch64TargetCPU(const ArgList &Args,
34 const llvm::Triple &Triple, Arg *&A) {
35 std::string CPU;
36 // If we have -mcpu, use that.
37 if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) {
38 StringRef Mcpu = A->getValue();
39 CPU = Mcpu.split("+").first.lower();
40 }
41
42 CPU = llvm::AArch64::resolveCPUAlias(CPU);
43
44 // Handle CPU name is 'native'.
45 if (CPU == "native")
46 return std::string(llvm::sys::getHostCPUName());
47
48 if (CPU.size())
49 return CPU;
50
51 if (Triple.isTargetMachineMac() &&
52 Triple.getArch() == llvm::Triple::aarch64) {
53 // Apple Silicon macs default to M1 CPUs.
54 return "apple-m1";
55 }
56
57 // arm64e requires v8.3a and only runs on apple-a12 and later CPUs.
58 if (Triple.isArm64e())
59 return "apple-a12";
60
61 // Make sure we pick the appropriate Apple CPU if -arch is used or when
62 // targetting a Darwin OS.
63 if (Args.getLastArg(options::OPT_arch) || Triple.isOSDarwin())
64 return Triple.getArch() == llvm::Triple::aarch64_32 ? "apple-s4"
65 : "apple-a7";
66
67 return "generic";
68 }
69
70 // Decode AArch64 features from string like +[no]featureA+[no]featureB+...
DecodeAArch64Features(const Driver & D,StringRef text,std::vector<StringRef> & Features,const llvm::AArch64::ArchInfo & ArchInfo)71 static bool DecodeAArch64Features(const Driver &D, StringRef text,
72 std::vector<StringRef> &Features,
73 const llvm::AArch64::ArchInfo &ArchInfo) {
74 SmallVector<StringRef, 8> Split;
75 text.split(Split, StringRef("+"), -1, false);
76
77 for (StringRef Feature : Split) {
78 StringRef FeatureName = llvm::AArch64::getArchExtFeature(Feature);
79 if (!FeatureName.empty())
80 Features.push_back(FeatureName);
81 else if (Feature == "neon" || Feature == "noneon")
82 D.Diag(clang::diag::err_drv_no_neon_modifier);
83 else
84 return false;
85
86 if (Feature == "sve2")
87 Features.push_back("+sve");
88 else if (Feature == "sve2-bitperm" || Feature == "sve2-sha3" ||
89 Feature == "sve2-aes" || Feature == "sve2-sm4") {
90 Features.push_back("+sve");
91 Features.push_back("+sve2");
92 } else if (Feature == "nosve") {
93 Features.push_back("-sve2");
94 Features.push_back("-sve2-bitperm");
95 Features.push_back("-sve2-sha3");
96 Features.push_back("-sve2-aes");
97 Features.push_back("-sve2-sm4");
98 } else if (Feature == "nosve2") {
99 Features.push_back("-sve2-bitperm");
100 Features.push_back("-sve2-sha3");
101 Features.push_back("-sve2-aes");
102 Features.push_back("-sve2-sm4");
103 }
104
105 // +sve implies +f32mm if the base architecture is >= v8.6A (except v9A)
106 // It isn't the case in general that sve implies both f64mm and f32mm
107 if ((ArchInfo == llvm::AArch64::ARMV8_6A ||
108 ArchInfo == llvm::AArch64::ARMV8_7A ||
109 ArchInfo == llvm::AArch64::ARMV8_8A ||
110 ArchInfo == llvm::AArch64::ARMV8_9A ||
111 ArchInfo == llvm::AArch64::ARMV9_1A ||
112 ArchInfo == llvm::AArch64::ARMV9_2A ||
113 ArchInfo == llvm::AArch64::ARMV9_3A ||
114 ArchInfo == llvm::AArch64::ARMV9_4A) &&
115 Feature == "sve")
116 Features.push_back("+f32mm");
117 }
118 return true;
119 }
120
121 // Check if the CPU name and feature modifiers in -mcpu are legal. If yes,
122 // decode CPU and feature.
DecodeAArch64Mcpu(const Driver & D,StringRef Mcpu,StringRef & CPU,std::vector<StringRef> & Features)123 static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU,
124 std::vector<StringRef> &Features) {
125 std::pair<StringRef, StringRef> Split = Mcpu.split("+");
126 const llvm::AArch64::ArchInfo *ArchInfo = &llvm::AArch64::ARMV8A;
127 CPU = llvm::AArch64::resolveCPUAlias(Split.first);
128
129 if (CPU == "native")
130 CPU = llvm::sys::getHostCPUName();
131
132 if (CPU == "generic") {
133 Features.push_back("+neon");
134 } else {
135 ArchInfo = &llvm::AArch64::parseCpu(CPU).Arch;
136 if (*ArchInfo == llvm::AArch64::INVALID)
137 return false;
138 Features.push_back(ArchInfo->ArchFeature);
139
140 uint64_t Extension = llvm::AArch64::getDefaultExtensions(CPU, *ArchInfo);
141 if (!llvm::AArch64::getExtensionFeatures(Extension, Features))
142 return false;
143 }
144
145 if (Split.second.size() &&
146 !DecodeAArch64Features(D, Split.second, Features, *ArchInfo))
147 return false;
148
149 return true;
150 }
151
152 static bool
getAArch64ArchFeaturesFromMarch(const Driver & D,StringRef March,const ArgList & Args,std::vector<StringRef> & Features)153 getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March,
154 const ArgList &Args,
155 std::vector<StringRef> &Features) {
156 std::string MarchLowerCase = March.lower();
157 std::pair<StringRef, StringRef> Split = StringRef(MarchLowerCase).split("+");
158
159 const llvm::AArch64::ArchInfo *ArchInfo =
160 &llvm::AArch64::parseArch(Split.first);
161 if (Split.first == "native")
162 ArchInfo = &llvm::AArch64::getArchForCpu(llvm::sys::getHostCPUName().str());
163 if (*ArchInfo == llvm::AArch64::INVALID)
164 return false;
165 Features.push_back(ArchInfo->ArchFeature);
166
167 // Enable SVE2 by default on Armv9-A.
168 // It can still be disabled if +nosve2 is present.
169 // We must do this early so that DecodeAArch64Features has the correct state
170 if ((*ArchInfo == llvm::AArch64::ARMV9A ||
171 *ArchInfo == llvm::AArch64::ARMV9_1A ||
172 *ArchInfo == llvm::AArch64::ARMV9_2A)) {
173 Features.push_back("+sve");
174 Features.push_back("+sve2");
175 }
176
177 if ((Split.second.size() &&
178 !DecodeAArch64Features(D, Split.second, Features, *ArchInfo)))
179 return false;
180
181 return true;
182 }
183
184 static bool
getAArch64ArchFeaturesFromMcpu(const Driver & D,StringRef Mcpu,const ArgList & Args,std::vector<StringRef> & Features)185 getAArch64ArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
186 const ArgList &Args,
187 std::vector<StringRef> &Features) {
188 StringRef CPU;
189 std::string McpuLowerCase = Mcpu.lower();
190 if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, Features))
191 return false;
192
193 return true;
194 }
195
196 static bool
getAArch64MicroArchFeaturesFromMtune(const Driver & D,StringRef Mtune,const ArgList & Args,std::vector<StringRef> & Features)197 getAArch64MicroArchFeaturesFromMtune(const Driver &D, StringRef Mtune,
198 const ArgList &Args,
199 std::vector<StringRef> &Features) {
200 std::string MtuneLowerCase = Mtune.lower();
201 // Check CPU name is valid
202 std::vector<StringRef> MtuneFeatures;
203 StringRef Tune;
204 if (!DecodeAArch64Mcpu(D, MtuneLowerCase, Tune, MtuneFeatures))
205 return false;
206
207 // Handle CPU name is 'native'.
208 if (MtuneLowerCase == "native")
209 MtuneLowerCase = std::string(llvm::sys::getHostCPUName());
210 if (MtuneLowerCase == "cyclone" ||
211 StringRef(MtuneLowerCase).startswith("apple")) {
212 Features.push_back("+zcm");
213 Features.push_back("+zcz");
214 }
215 return true;
216 }
217
218 static bool
getAArch64MicroArchFeaturesFromMcpu(const Driver & D,StringRef Mcpu,const ArgList & Args,std::vector<StringRef> & Features)219 getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
220 const ArgList &Args,
221 std::vector<StringRef> &Features) {
222 StringRef CPU;
223 std::vector<StringRef> DecodedFeature;
224 std::string McpuLowerCase = Mcpu.lower();
225 if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, DecodedFeature))
226 return false;
227
228 return getAArch64MicroArchFeaturesFromMtune(D, CPU, Args, Features);
229 }
230
getAArch64TargetFeatures(const Driver & D,const llvm::Triple & Triple,const ArgList & Args,std::vector<StringRef> & Features,bool ForAS)231 void aarch64::getAArch64TargetFeatures(const Driver &D,
232 const llvm::Triple &Triple,
233 const ArgList &Args,
234 std::vector<StringRef> &Features,
235 bool ForAS) {
236 Arg *A;
237 bool success = true;
238 // Enable NEON by default.
239 Features.push_back("+neon");
240 llvm::StringRef WaMArch;
241 if (ForAS)
242 for (const auto *A :
243 Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler))
244 for (StringRef Value : A->getValues())
245 if (Value.startswith("-march="))
246 WaMArch = Value.substr(7);
247 // Call getAArch64ArchFeaturesFromMarch only if "-Wa,-march=" or
248 // "-Xassembler -march" is detected. Otherwise it may return false
249 // and causes Clang to error out.
250 if (!WaMArch.empty())
251 success = getAArch64ArchFeaturesFromMarch(D, WaMArch, Args, Features);
252 else if ((A = Args.getLastArg(options::OPT_march_EQ)))
253 success = getAArch64ArchFeaturesFromMarch(D, A->getValue(), Args, Features);
254 else if ((A = Args.getLastArg(options::OPT_mcpu_EQ)))
255 success = getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Features);
256 else if (Args.hasArg(options::OPT_arch) || isCPUDeterminedByTriple(Triple))
257 success = getAArch64ArchFeaturesFromMcpu(
258 D, getAArch64TargetCPU(Args, Triple, A), Args, Features);
259 else
260 // Default to 'A' profile if the architecture is not specified.
261 success = getAArch64ArchFeaturesFromMarch(D, "armv8-a", Args, Features);
262
263 if (success && (A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)))
264 success =
265 getAArch64MicroArchFeaturesFromMtune(D, A->getValue(), Args, Features);
266 else if (success && (A = Args.getLastArg(options::OPT_mcpu_EQ)))
267 success =
268 getAArch64MicroArchFeaturesFromMcpu(D, A->getValue(), Args, Features);
269 else if (success &&
270 (Args.hasArg(options::OPT_arch) || isCPUDeterminedByTriple(Triple)))
271 success = getAArch64MicroArchFeaturesFromMcpu(
272 D, getAArch64TargetCPU(Args, Triple, A), Args, Features);
273
274 if (!success) {
275 auto Diag = D.Diag(diag::err_drv_unsupported_option_argument);
276 // If "-Wa,-march=" is used, 'WaMArch' will contain the argument's value,
277 // while 'A' is uninitialized. Only dereference 'A' in the other case.
278 if (!WaMArch.empty())
279 Diag << "-march=" << WaMArch;
280 else
281 Diag << A->getSpelling() << A->getValue();
282 }
283
284 if (Args.getLastArg(options::OPT_mgeneral_regs_only)) {
285 Features.push_back("-fp-armv8");
286 Features.push_back("-crypto");
287 Features.push_back("-neon");
288 }
289
290 if (Arg *A = Args.getLastArg(options::OPT_mtp_mode_EQ)) {
291 StringRef Mtp = A->getValue();
292 if (Mtp == "el3")
293 Features.push_back("+tpidr-el3");
294 else if (Mtp == "el2")
295 Features.push_back("+tpidr-el2");
296 else if (Mtp == "el1")
297 Features.push_back("+tpidr-el1");
298 else if (Mtp != "el0")
299 D.Diag(diag::err_drv_invalid_mtp) << A->getAsString(Args);
300 }
301
302 // Enable/disable straight line speculation hardening.
303 if (Arg *A = Args.getLastArg(options::OPT_mharden_sls_EQ)) {
304 StringRef Scope = A->getValue();
305 bool EnableRetBr = false;
306 bool EnableBlr = false;
307 bool DisableComdat = false;
308 if (Scope != "none") {
309 SmallVector<StringRef, 4> Opts;
310 Scope.split(Opts, ",");
311 for (auto Opt : Opts) {
312 Opt = Opt.trim();
313 if (Opt == "all") {
314 EnableBlr = true;
315 EnableRetBr = true;
316 continue;
317 }
318 if (Opt == "retbr") {
319 EnableRetBr = true;
320 continue;
321 }
322 if (Opt == "blr") {
323 EnableBlr = true;
324 continue;
325 }
326 if (Opt == "comdat") {
327 DisableComdat = false;
328 continue;
329 }
330 if (Opt == "nocomdat") {
331 DisableComdat = true;
332 continue;
333 }
334 D.Diag(diag::err_drv_unsupported_option_argument)
335 << A->getSpelling() << Scope;
336 break;
337 }
338 }
339
340 if (EnableRetBr)
341 Features.push_back("+harden-sls-retbr");
342 if (EnableBlr)
343 Features.push_back("+harden-sls-blr");
344 if (DisableComdat) {
345 Features.push_back("+harden-sls-nocomdat");
346 }
347 }
348
349 // En/disable crc
350 if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) {
351 if (A->getOption().matches(options::OPT_mcrc))
352 Features.push_back("+crc");
353 else
354 Features.push_back("-crc");
355 }
356
357 int V8Version = -1;
358 int V9Version = -1;
359 bool HasNoSM4 = false;
360 bool HasNoSHA3 = false;
361 bool HasNoSHA2 = false;
362 bool HasNoAES = false;
363 bool HasSM4 = false;
364 bool HasSHA3 = false;
365 bool HasSHA2 = false;
366 bool HasAES = false;
367 bool HasCrypto = false;
368 bool HasNoCrypto = false;
369 int FullFP16Pos = -1;
370 int NoFullFP16Pos = -1;
371 int FP16FMLPos = -1;
372 int NoFP16FMLPos = -1;
373 int ArchFeatPos = -1;
374
375 for (auto I = Features.begin(), E = Features.end(); I != E; I++) {
376 if (*I == "+v8a") V8Version = 0;
377 else if (*I == "+v8.1a") V8Version = 1;
378 else if (*I == "+v8.2a") V8Version = 2;
379 else if (*I == "+v8.3a") V8Version = 3;
380 else if (*I == "+v8.4a") V8Version = 4;
381 else if (*I == "+v8.5a") V8Version = 5;
382 else if (*I == "+v8.6a") V8Version = 6;
383 else if (*I == "+v8.7a") V8Version = 7;
384 else if (*I == "+v8.8a") V8Version = 8;
385 else if (*I == "+v8.9a") V8Version = 9;
386 else if (*I == "+v9a") V9Version = 0;
387 else if (*I == "+v9.1a") V9Version = 1;
388 else if (*I == "+v9.2a") V9Version = 2;
389 else if (*I == "+v9.3a") V9Version = 3;
390 else if (*I == "+v9.4a") V9Version = 4;
391 else if (*I == "+sm4") HasSM4 = true;
392 else if (*I == "+sha3") HasSHA3 = true;
393 else if (*I == "+sha2") HasSHA2 = true;
394 else if (*I == "+aes") HasAES = true;
395 else if (*I == "-sm4") HasNoSM4 = true;
396 else if (*I == "-sha3") HasNoSHA3 = true;
397 else if (*I == "-sha2") HasNoSHA2 = true;
398 else if (*I == "-aes") HasNoAES = true;
399 else if (*I == "+fp16fml") FP16FMLPos = I - Features.begin();
400 else if (*I == "-fp16fml") NoFP16FMLPos = I - Features.begin();
401 else if (*I == "-fullfp16") NoFullFP16Pos = I - Features.begin();
402 else if (*I == "+fullfp16") FullFP16Pos = I - Features.begin();
403 // Whichever option comes after (right-most option) will win
404 else if (*I == "+crypto") {
405 HasCrypto = true;
406 HasNoCrypto = false;
407 } else if (*I == "-crypto") {
408 HasCrypto = false;
409 HasNoCrypto = true;
410 }
411 // Register the iterator position if this is an architecture feature
412 if (ArchFeatPos == -1 && (V8Version != -1 || V9Version != -1))
413 ArchFeatPos = I - Features.begin();
414 }
415
416 // Handle (arch-dependent) fp16fml/fullfp16 relationship.
417 // FIXME: this fp16fml option handling will be reimplemented after the
418 // TargetParser rewrite.
419 if (V8Version >= 4) {
420 // "-fullfp16" "+fullfp16" && "+fp16fml" "+fullfp16" && no "+fullfp16" "-fp16fml" = "+fp16fml"
421 if (FullFP16Pos > NoFullFP16Pos && FullFP16Pos > FP16FMLPos && FullFP16Pos > NoFP16FMLPos)
422 // Only entangled feature that can be to the right of this +fullfp16 is -fp16fml.
423 // Only append the +fp16fml if there is no -fp16fml after the +fullfp16.
424 Features.push_back("+fp16fml");
425 else
426 goto fp16_fml_fallthrough;
427 } else {
428 fp16_fml_fallthrough:
429 // In both of these cases, putting the 'other' feature on the end of the vector will
430 // result in the same effect as placing it immediately after the current feature.
431 // "+fp16fml" "-fullfp16" = "-fp16fml"
432 if (NoFullFP16Pos > FP16FMLPos)
433 Features.push_back("-fp16fml");
434 // "-fullfp16" "+fp16fml" = "+fullfp16"
435 else if (NoFullFP16Pos < FP16FMLPos)
436 Features.push_back("+fullfp16");
437 }
438
439 // FIXME: this needs reimplementation too after the TargetParser rewrite
440 //
441 // Context sensitive meaning of Crypto:
442 // 1) For Arch >= ARMv8.4a: crypto = sm4 + sha3 + sha2 + aes
443 // 2) For Arch <= ARMv8.3a: crypto = sha2 + aes
444 if (V8Version >= 4 || V9Version >= 0) {
445 if (HasCrypto && !HasNoCrypto) {
446 // Check if we have NOT disabled an algorithm with something like:
447 // +crypto, -algorithm
448 // And if "-algorithm" does not occur, we enable that crypto algorithm.
449 if (!HasNoSM4)
450 Features.push_back("+sm4");
451 if (!HasNoSHA3)
452 Features.push_back("+sha3");
453 if (!HasNoSHA2)
454 Features.push_back("+sha2");
455 if (!HasNoAES)
456 Features.push_back("+aes");
457 } else if (HasNoCrypto) {
458 // Check if we have NOT enabled a crypto algorithm with something like:
459 // -crypto, +algorithm
460 // And if "+algorithm" does not occur, we disable that crypto algorithm.
461 if (!HasSM4)
462 Features.push_back("-sm4");
463 if (!HasSHA3)
464 Features.push_back("-sha3");
465 if (!HasSHA2)
466 Features.push_back("-sha2");
467 if (!HasAES)
468 Features.push_back("-aes");
469 }
470 } else {
471 if (HasCrypto && !HasNoCrypto) {
472 if (!HasNoSHA2)
473 Features.push_back("+sha2");
474 if (!HasNoAES)
475 Features.push_back("+aes");
476 } else if (HasNoCrypto) {
477 if (!HasSHA2)
478 Features.push_back("-sha2");
479 if (!HasAES)
480 Features.push_back("-aes");
481 if (V8Version == 2 || V8Version == 3) {
482 Features.push_back("-sm4");
483 Features.push_back("-sha3");
484 }
485 }
486 }
487
488 if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
489 options::OPT_munaligned_access)) {
490 if (A->getOption().matches(options::OPT_mno_unaligned_access))
491 Features.push_back("+strict-align");
492 } else if (Triple.isOSOpenBSD())
493 Features.push_back("+strict-align");
494
495 if (Args.hasArg(options::OPT_ffixed_x1))
496 Features.push_back("+reserve-x1");
497
498 if (Args.hasArg(options::OPT_ffixed_x2))
499 Features.push_back("+reserve-x2");
500
501 if (Args.hasArg(options::OPT_ffixed_x3))
502 Features.push_back("+reserve-x3");
503
504 if (Args.hasArg(options::OPT_ffixed_x4))
505 Features.push_back("+reserve-x4");
506
507 if (Args.hasArg(options::OPT_ffixed_x5))
508 Features.push_back("+reserve-x5");
509
510 if (Args.hasArg(options::OPT_ffixed_x6))
511 Features.push_back("+reserve-x6");
512
513 if (Args.hasArg(options::OPT_ffixed_x7))
514 Features.push_back("+reserve-x7");
515
516 if (Args.hasArg(options::OPT_ffixed_x9))
517 Features.push_back("+reserve-x9");
518
519 if (Args.hasArg(options::OPT_ffixed_x10))
520 Features.push_back("+reserve-x10");
521
522 if (Args.hasArg(options::OPT_ffixed_x11))
523 Features.push_back("+reserve-x11");
524
525 if (Args.hasArg(options::OPT_ffixed_x12))
526 Features.push_back("+reserve-x12");
527
528 if (Args.hasArg(options::OPT_ffixed_x13))
529 Features.push_back("+reserve-x13");
530
531 if (Args.hasArg(options::OPT_ffixed_x14))
532 Features.push_back("+reserve-x14");
533
534 if (Args.hasArg(options::OPT_ffixed_x15))
535 Features.push_back("+reserve-x15");
536
537 if (Args.hasArg(options::OPT_ffixed_x18))
538 Features.push_back("+reserve-x18");
539
540 if (Args.hasArg(options::OPT_ffixed_x20))
541 Features.push_back("+reserve-x20");
542
543 if (Args.hasArg(options::OPT_ffixed_x21))
544 Features.push_back("+reserve-x21");
545
546 if (Args.hasArg(options::OPT_ffixed_x22))
547 Features.push_back("+reserve-x22");
548
549 if (Args.hasArg(options::OPT_ffixed_x23))
550 Features.push_back("+reserve-x23");
551
552 if (Args.hasArg(options::OPT_ffixed_x24))
553 Features.push_back("+reserve-x24");
554
555 if (Args.hasArg(options::OPT_ffixed_x25))
556 Features.push_back("+reserve-x25");
557
558 if (Args.hasArg(options::OPT_ffixed_x26))
559 Features.push_back("+reserve-x26");
560
561 if (Args.hasArg(options::OPT_ffixed_x27))
562 Features.push_back("+reserve-x27");
563
564 if (Args.hasArg(options::OPT_ffixed_x28))
565 Features.push_back("+reserve-x28");
566
567 if (Args.hasArg(options::OPT_ffixed_x30))
568 Features.push_back("+reserve-x30");
569
570 if (Args.hasArg(options::OPT_fcall_saved_x8))
571 Features.push_back("+call-saved-x8");
572
573 if (Args.hasArg(options::OPT_fcall_saved_x9))
574 Features.push_back("+call-saved-x9");
575
576 if (Args.hasArg(options::OPT_fcall_saved_x10))
577 Features.push_back("+call-saved-x10");
578
579 if (Args.hasArg(options::OPT_fcall_saved_x11))
580 Features.push_back("+call-saved-x11");
581
582 if (Args.hasArg(options::OPT_fcall_saved_x12))
583 Features.push_back("+call-saved-x12");
584
585 if (Args.hasArg(options::OPT_fcall_saved_x13))
586 Features.push_back("+call-saved-x13");
587
588 if (Args.hasArg(options::OPT_fcall_saved_x14))
589 Features.push_back("+call-saved-x14");
590
591 if (Args.hasArg(options::OPT_fcall_saved_x15))
592 Features.push_back("+call-saved-x15");
593
594 if (Args.hasArg(options::OPT_fcall_saved_x18))
595 Features.push_back("+call-saved-x18");
596
597 if (Args.hasArg(options::OPT_mno_neg_immediates))
598 Features.push_back("+no-neg-immediates");
599
600 if (Arg *A = Args.getLastArg(options::OPT_mfix_cortex_a53_835769,
601 options::OPT_mno_fix_cortex_a53_835769)) {
602 if (A->getOption().matches(options::OPT_mfix_cortex_a53_835769))
603 Features.push_back("+fix-cortex-a53-835769");
604 else
605 Features.push_back("-fix-cortex-a53-835769");
606 } else if (Triple.isAndroid()) {
607 // Enabled A53 errata (835769) workaround by default on android
608 Features.push_back("+fix-cortex-a53-835769");
609 } else if (Triple.isOSFuchsia()) {
610 std::string CPU = getCPUName(D, Args, Triple);
611 if (CPU.empty() || CPU == "generic" || CPU == "cortex-a53")
612 Features.push_back("+fix-cortex-a53-835769");
613 }
614
615 if (Args.getLastArg(options::OPT_mno_bti_at_return_twice))
616 Features.push_back("+no-bti-at-return-twice");
617 }
618