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