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