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. 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. 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+... 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. 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 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 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 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 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 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