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