1 //===--- ARM.cpp - ARM (not AArch64) 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 "ARM.h" 10 #include "clang/Driver/Driver.h" 11 #include "clang/Driver/DriverDiagnostic.h" 12 #include "clang/Driver/Options.h" 13 #include "llvm/ADT/StringSwitch.h" 14 #include "llvm/Option/ArgList.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 // Get SubArch (vN). 24 int arm::getARMSubArchVersionNumber(const llvm::Triple &Triple) { 25 llvm::StringRef Arch = Triple.getArchName(); 26 return llvm::ARM::parseArchVersion(Arch); 27 } 28 29 // True if M-profile. 30 bool arm::isARMMProfile(const llvm::Triple &Triple) { 31 llvm::StringRef Arch = Triple.getArchName(); 32 return llvm::ARM::parseArchProfile(Arch) == llvm::ARM::ProfileKind::M; 33 } 34 35 // True if A-profile. 36 bool arm::isARMAProfile(const llvm::Triple &Triple) { 37 llvm::StringRef Arch = Triple.getArchName(); 38 return llvm::ARM::parseArchProfile(Arch) == llvm::ARM::ProfileKind::A; 39 } 40 41 // Get Arch/CPU from args. 42 void arm::getARMArchCPUFromArgs(const ArgList &Args, llvm::StringRef &Arch, 43 llvm::StringRef &CPU, bool FromAs) { 44 if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) 45 CPU = A->getValue(); 46 if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) 47 Arch = A->getValue(); 48 if (!FromAs) 49 return; 50 51 for (const Arg *A : 52 Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) { 53 StringRef Value = A->getValue(); 54 if (Value.startswith("-mcpu=")) 55 CPU = Value.substr(6); 56 if (Value.startswith("-march=")) 57 Arch = Value.substr(7); 58 } 59 } 60 61 // Handle -mhwdiv=. 62 // FIXME: Use ARMTargetParser. 63 static void getARMHWDivFeatures(const Driver &D, const Arg *A, 64 const ArgList &Args, StringRef HWDiv, 65 std::vector<StringRef> &Features) { 66 uint64_t HWDivID = llvm::ARM::parseHWDiv(HWDiv); 67 if (!llvm::ARM::getHWDivFeatures(HWDivID, Features)) 68 D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); 69 } 70 71 // Handle -mfpu=. 72 static unsigned getARMFPUFeatures(const Driver &D, const Arg *A, 73 const ArgList &Args, StringRef FPU, 74 std::vector<StringRef> &Features) { 75 unsigned FPUID = llvm::ARM::parseFPU(FPU); 76 if (!llvm::ARM::getFPUFeatures(FPUID, Features)) 77 D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); 78 return FPUID; 79 } 80 81 // Decode ARM features from string like +[no]featureA+[no]featureB+... 82 static bool DecodeARMFeatures(const Driver &D, StringRef text, StringRef CPU, 83 llvm::ARM::ArchKind ArchKind, 84 std::vector<StringRef> &Features, 85 unsigned &ArgFPUID) { 86 SmallVector<StringRef, 8> Split; 87 text.split(Split, StringRef("+"), -1, false); 88 89 for (StringRef Feature : Split) { 90 if (!appendArchExtFeatures(CPU, ArchKind, Feature, Features, ArgFPUID)) 91 return false; 92 } 93 return true; 94 } 95 96 static void DecodeARMFeaturesFromCPU(const Driver &D, StringRef CPU, 97 std::vector<StringRef> &Features) { 98 CPU = CPU.split("+").first; 99 if (CPU != "generic") { 100 llvm::ARM::ArchKind ArchKind = llvm::ARM::parseCPUArch(CPU); 101 uint64_t Extension = llvm::ARM::getDefaultExtensions(CPU, ArchKind); 102 llvm::ARM::getExtensionFeatures(Extension, Features); 103 } 104 } 105 106 // Check if -march is valid by checking if it can be canonicalised and parsed. 107 // getARMArch is used here instead of just checking the -march value in order 108 // to handle -march=native correctly. 109 static void checkARMArchName(const Driver &D, const Arg *A, const ArgList &Args, 110 llvm::StringRef ArchName, llvm::StringRef CPUName, 111 std::vector<StringRef> &Features, 112 const llvm::Triple &Triple, unsigned &ArgFPUID) { 113 std::pair<StringRef, StringRef> Split = ArchName.split("+"); 114 115 std::string MArch = arm::getARMArch(ArchName, Triple); 116 llvm::ARM::ArchKind ArchKind = llvm::ARM::parseArch(MArch); 117 if (ArchKind == llvm::ARM::ArchKind::INVALID || 118 (Split.second.size() && !DecodeARMFeatures(D, Split.second, CPUName, 119 ArchKind, Features, ArgFPUID))) 120 D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); 121 } 122 123 // Check -mcpu=. Needs ArchName to handle -mcpu=generic. 124 static void checkARMCPUName(const Driver &D, const Arg *A, const ArgList &Args, 125 llvm::StringRef CPUName, llvm::StringRef ArchName, 126 std::vector<StringRef> &Features, 127 const llvm::Triple &Triple, unsigned &ArgFPUID) { 128 std::pair<StringRef, StringRef> Split = CPUName.split("+"); 129 130 std::string CPU = arm::getARMTargetCPU(CPUName, ArchName, Triple); 131 llvm::ARM::ArchKind ArchKind = 132 arm::getLLVMArchKindForARM(CPU, ArchName, Triple); 133 if (ArchKind == llvm::ARM::ArchKind::INVALID || 134 (Split.second.size() && 135 !DecodeARMFeatures(D, Split.second, CPU, ArchKind, Features, ArgFPUID))) 136 D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); 137 } 138 139 bool arm::useAAPCSForMachO(const llvm::Triple &T) { 140 // The backend is hardwired to assume AAPCS for M-class processors, ensure 141 // the frontend matches that. 142 return T.getEnvironment() == llvm::Triple::EABI || 143 T.getEnvironment() == llvm::Triple::EABIHF || 144 T.getOS() == llvm::Triple::UnknownOS || isARMMProfile(T); 145 } 146 147 // Select mode for reading thread pointer (-mtp=soft/cp15). 148 arm::ReadTPMode arm::getReadTPMode(const Driver &D, const ArgList &Args) { 149 if (Arg *A = Args.getLastArg(options::OPT_mtp_mode_EQ)) { 150 arm::ReadTPMode ThreadPointer = 151 llvm::StringSwitch<arm::ReadTPMode>(A->getValue()) 152 .Case("cp15", ReadTPMode::Cp15) 153 .Case("soft", ReadTPMode::Soft) 154 .Default(ReadTPMode::Invalid); 155 if (ThreadPointer != ReadTPMode::Invalid) 156 return ThreadPointer; 157 if (StringRef(A->getValue()).empty()) 158 D.Diag(diag::err_drv_missing_arg_mtp) << A->getAsString(Args); 159 else 160 D.Diag(diag::err_drv_invalid_mtp) << A->getAsString(Args); 161 return ReadTPMode::Invalid; 162 } 163 return ReadTPMode::Soft; 164 } 165 166 arm::FloatABI arm::getARMFloatABI(const ToolChain &TC, const ArgList &Args) { 167 return arm::getARMFloatABI(TC.getDriver(), TC.getEffectiveTriple(), Args); 168 } 169 170 arm::FloatABI arm::getDefaultFloatABI(const llvm::Triple &Triple) { 171 auto SubArch = getARMSubArchVersionNumber(Triple); 172 switch (Triple.getOS()) { 173 case llvm::Triple::Darwin: 174 case llvm::Triple::MacOSX: 175 case llvm::Triple::IOS: 176 case llvm::Triple::TvOS: 177 // Darwin defaults to "softfp" for v6 and v7. 178 if (Triple.isWatchABI()) 179 return FloatABI::Hard; 180 else 181 return (SubArch == 6 || SubArch == 7) ? FloatABI::SoftFP : FloatABI::Soft; 182 183 case llvm::Triple::WatchOS: 184 return FloatABI::Hard; 185 186 // FIXME: this is invalid for WindowsCE 187 case llvm::Triple::Win32: 188 return FloatABI::Hard; 189 190 case llvm::Triple::NetBSD: 191 switch (Triple.getEnvironment()) { 192 case llvm::Triple::EABIHF: 193 case llvm::Triple::GNUEABIHF: 194 return FloatABI::Hard; 195 default: 196 return FloatABI::Soft; 197 } 198 break; 199 200 case llvm::Triple::FreeBSD: 201 switch (Triple.getEnvironment()) { 202 case llvm::Triple::GNUEABIHF: 203 return FloatABI::Hard; 204 default: 205 // FreeBSD defaults to soft float 206 return FloatABI::Soft; 207 } 208 break; 209 210 case llvm::Triple::OpenBSD: 211 return FloatABI::SoftFP; 212 213 default: 214 switch (Triple.getEnvironment()) { 215 case llvm::Triple::GNUEABIHF: 216 case llvm::Triple::MuslEABIHF: 217 case llvm::Triple::EABIHF: 218 return FloatABI::Hard; 219 case llvm::Triple::GNUEABI: 220 case llvm::Triple::MuslEABI: 221 case llvm::Triple::EABI: 222 // EABI is always AAPCS, and if it was not marked 'hard', it's softfp 223 return FloatABI::SoftFP; 224 case llvm::Triple::Android: 225 return (SubArch >= 7) ? FloatABI::SoftFP : FloatABI::Soft; 226 default: 227 return FloatABI::Invalid; 228 } 229 } 230 return FloatABI::Invalid; 231 } 232 233 // Select the float ABI as determined by -msoft-float, -mhard-float, and 234 // -mfloat-abi=. 235 arm::FloatABI arm::getARMFloatABI(const Driver &D, const llvm::Triple &Triple, 236 const ArgList &Args) { 237 arm::FloatABI ABI = FloatABI::Invalid; 238 if (Arg *A = 239 Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, 240 options::OPT_mfloat_abi_EQ)) { 241 if (A->getOption().matches(options::OPT_msoft_float)) { 242 ABI = FloatABI::Soft; 243 } else if (A->getOption().matches(options::OPT_mhard_float)) { 244 ABI = FloatABI::Hard; 245 } else { 246 ABI = llvm::StringSwitch<arm::FloatABI>(A->getValue()) 247 .Case("soft", FloatABI::Soft) 248 .Case("softfp", FloatABI::SoftFP) 249 .Case("hard", FloatABI::Hard) 250 .Default(FloatABI::Invalid); 251 if (ABI == FloatABI::Invalid && !StringRef(A->getValue()).empty()) { 252 D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args); 253 ABI = FloatABI::Soft; 254 } 255 } 256 } 257 258 // If unspecified, choose the default based on the platform. 259 if (ABI == FloatABI::Invalid) 260 ABI = arm::getDefaultFloatABI(Triple); 261 262 if (ABI == FloatABI::Invalid) { 263 // Assume "soft", but warn the user we are guessing. 264 if (Triple.isOSBinFormatMachO() && 265 Triple.getSubArch() == llvm::Triple::ARMSubArch_v7em) 266 ABI = FloatABI::Hard; 267 else 268 ABI = FloatABI::Soft; 269 270 if (Triple.getOS() != llvm::Triple::UnknownOS || 271 !Triple.isOSBinFormatMachO()) 272 D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft"; 273 } 274 275 assert(ABI != FloatABI::Invalid && "must select an ABI"); 276 return ABI; 277 } 278 279 static bool hasIntegerMVE(const std::vector<StringRef> &F) { 280 auto MVE = llvm::find(llvm::reverse(F), "+mve"); 281 auto NoMVE = llvm::find(llvm::reverse(F), "-mve"); 282 return MVE != F.rend() && 283 (NoMVE == F.rend() || std::distance(MVE, NoMVE) > 0); 284 } 285 286 void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple, 287 const ArgList &Args, ArgStringList &CmdArgs, 288 std::vector<StringRef> &Features, bool ForAS) { 289 bool KernelOrKext = 290 Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext); 291 arm::FloatABI ABI = arm::getARMFloatABI(D, Triple, Args); 292 arm::ReadTPMode ThreadPointer = arm::getReadTPMode(D, Args); 293 const Arg *WaCPU = nullptr, *WaFPU = nullptr; 294 const Arg *WaHDiv = nullptr, *WaArch = nullptr; 295 296 // This vector will accumulate features from the architecture 297 // extension suffixes on -mcpu and -march (e.g. the 'bar' in 298 // -mcpu=foo+bar). We want to apply those after the features derived 299 // from the FPU, in case -mfpu generates a negative feature which 300 // the +bar is supposed to override. 301 std::vector<StringRef> ExtensionFeatures; 302 303 if (!ForAS) { 304 // FIXME: Note, this is a hack, the LLVM backend doesn't actually use these 305 // yet (it uses the -mfloat-abi and -msoft-float options), and it is 306 // stripped out by the ARM target. We should probably pass this a new 307 // -target-option, which is handled by the -cc1/-cc1as invocation. 308 // 309 // FIXME2: For consistency, it would be ideal if we set up the target 310 // machine state the same when using the frontend or the assembler. We don't 311 // currently do that for the assembler, we pass the options directly to the 312 // backend and never even instantiate the frontend TargetInfo. If we did, 313 // and used its handleTargetFeatures hook, then we could ensure the 314 // assembler and the frontend behave the same. 315 316 // Use software floating point operations? 317 if (ABI == arm::FloatABI::Soft) 318 Features.push_back("+soft-float"); 319 320 // Use software floating point argument passing? 321 if (ABI != arm::FloatABI::Hard) 322 Features.push_back("+soft-float-abi"); 323 } else { 324 // Here, we make sure that -Wa,-mfpu/cpu/arch/hwdiv will be passed down 325 // to the assembler correctly. 326 for (const Arg *A : 327 Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) { 328 StringRef Value = A->getValue(); 329 if (Value.startswith("-mfpu=")) { 330 WaFPU = A; 331 } else if (Value.startswith("-mcpu=")) { 332 WaCPU = A; 333 } else if (Value.startswith("-mhwdiv=")) { 334 WaHDiv = A; 335 } else if (Value.startswith("-march=")) { 336 WaArch = A; 337 } 338 } 339 } 340 341 if (ThreadPointer == arm::ReadTPMode::Cp15) 342 Features.push_back("+read-tp-hard"); 343 344 const Arg *ArchArg = Args.getLastArg(options::OPT_march_EQ); 345 const Arg *CPUArg = Args.getLastArg(options::OPT_mcpu_EQ); 346 StringRef ArchName; 347 StringRef CPUName; 348 unsigned ArchArgFPUID = llvm::ARM::FK_INVALID; 349 unsigned CPUArgFPUID = llvm::ARM::FK_INVALID; 350 351 // Check -mcpu. ClangAs gives preference to -Wa,-mcpu=. 352 if (WaCPU) { 353 if (CPUArg) 354 D.Diag(clang::diag::warn_drv_unused_argument) 355 << CPUArg->getAsString(Args); 356 CPUName = StringRef(WaCPU->getValue()).substr(6); 357 CPUArg = WaCPU; 358 } else if (CPUArg) 359 CPUName = CPUArg->getValue(); 360 361 // Check -march. ClangAs gives preference to -Wa,-march=. 362 if (WaArch) { 363 if (ArchArg) 364 D.Diag(clang::diag::warn_drv_unused_argument) 365 << ArchArg->getAsString(Args); 366 ArchName = StringRef(WaArch->getValue()).substr(7); 367 checkARMArchName(D, WaArch, Args, ArchName, CPUName, ExtensionFeatures, 368 Triple, ArchArgFPUID); 369 // FIXME: Set Arch. 370 D.Diag(clang::diag::warn_drv_unused_argument) << WaArch->getAsString(Args); 371 } else if (ArchArg) { 372 ArchName = ArchArg->getValue(); 373 checkARMArchName(D, ArchArg, Args, ArchName, CPUName, ExtensionFeatures, 374 Triple, ArchArgFPUID); 375 } 376 377 // Add CPU features for generic CPUs 378 if (CPUName == "native") { 379 llvm::StringMap<bool> HostFeatures; 380 if (llvm::sys::getHostCPUFeatures(HostFeatures)) 381 for (auto &F : HostFeatures) 382 Features.push_back( 383 Args.MakeArgString((F.second ? "+" : "-") + F.first())); 384 } else if (!CPUName.empty()) { 385 // This sets the default features for the specified CPU. We certainly don't 386 // want to override the features that have been explicitly specified on the 387 // command line. Therefore, process them directly instead of appending them 388 // at the end later. 389 DecodeARMFeaturesFromCPU(D, CPUName, Features); 390 } 391 392 if (CPUArg) 393 checkARMCPUName(D, CPUArg, Args, CPUName, ArchName, ExtensionFeatures, 394 Triple, CPUArgFPUID); 395 // Honor -mfpu=. ClangAs gives preference to -Wa,-mfpu=. 396 unsigned FPUID = llvm::ARM::FK_INVALID; 397 const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ); 398 if (WaFPU) { 399 if (FPUArg) 400 D.Diag(clang::diag::warn_drv_unused_argument) 401 << FPUArg->getAsString(Args); 402 (void)getARMFPUFeatures(D, WaFPU, Args, StringRef(WaFPU->getValue()).substr(6), 403 Features); 404 } else if (FPUArg) { 405 FPUID = getARMFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features); 406 } else if (Triple.isAndroid() && getARMSubArchVersionNumber(Triple) >= 7) { 407 const char *AndroidFPU = "neon"; 408 FPUID = llvm::ARM::parseFPU(AndroidFPU); 409 if (!llvm::ARM::getFPUFeatures(FPUID, Features)) 410 D.Diag(clang::diag::err_drv_clang_unsupported) 411 << std::string("-mfpu=") + AndroidFPU; 412 } 413 414 // Now we've finished accumulating features from arch, cpu and fpu, 415 // we can append the ones for architecture extensions that we 416 // collected separately. 417 Features.insert(std::end(Features), 418 std::begin(ExtensionFeatures), std::end(ExtensionFeatures)); 419 420 // Honor -mhwdiv=. ClangAs gives preference to -Wa,-mhwdiv=. 421 const Arg *HDivArg = Args.getLastArg(options::OPT_mhwdiv_EQ); 422 if (WaHDiv) { 423 if (HDivArg) 424 D.Diag(clang::diag::warn_drv_unused_argument) 425 << HDivArg->getAsString(Args); 426 getARMHWDivFeatures(D, WaHDiv, Args, 427 StringRef(WaHDiv->getValue()).substr(8), Features); 428 } else if (HDivArg) 429 getARMHWDivFeatures(D, HDivArg, Args, HDivArg->getValue(), Features); 430 431 // Handle (arch-dependent) fp16fml/fullfp16 relationship. 432 // Must happen before any features are disabled due to soft-float. 433 // FIXME: this fp16fml option handling will be reimplemented after the 434 // TargetParser rewrite. 435 const auto ItRNoFullFP16 = std::find(Features.rbegin(), Features.rend(), "-fullfp16"); 436 const auto ItRFP16FML = std::find(Features.rbegin(), Features.rend(), "+fp16fml"); 437 if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8_4a) { 438 const auto ItRFullFP16 = std::find(Features.rbegin(), Features.rend(), "+fullfp16"); 439 if (ItRFullFP16 < ItRNoFullFP16 && ItRFullFP16 < ItRFP16FML) { 440 // Only entangled feature that can be to the right of this +fullfp16 is -fp16fml. 441 // Only append the +fp16fml if there is no -fp16fml after the +fullfp16. 442 if (std::find(Features.rbegin(), ItRFullFP16, "-fp16fml") == ItRFullFP16) 443 Features.push_back("+fp16fml"); 444 } 445 else 446 goto fp16_fml_fallthrough; 447 } 448 else { 449 fp16_fml_fallthrough: 450 // In both of these cases, putting the 'other' feature on the end of the vector will 451 // result in the same effect as placing it immediately after the current feature. 452 if (ItRNoFullFP16 < ItRFP16FML) 453 Features.push_back("-fp16fml"); 454 else if (ItRNoFullFP16 > ItRFP16FML) 455 Features.push_back("+fullfp16"); 456 } 457 458 // Setting -msoft-float/-mfloat-abi=soft, -mfpu=none, or adding +nofp to 459 // -march/-mcpu effectively disables the FPU (GCC ignores the -mfpu options in 460 // this case). Note that the ABI can also be set implicitly by the target 461 // selected. 462 if (ABI == arm::FloatABI::Soft) { 463 llvm::ARM::getFPUFeatures(llvm::ARM::FK_NONE, Features); 464 465 // Disable all features relating to hardware FP, not already disabled by the 466 // above call. 467 Features.insert(Features.end(), {"-dotprod", "-fp16fml", "-bf16", "-mve", 468 "-mve.fp", "-fpregs"}); 469 } else if (FPUID == llvm::ARM::FK_NONE || 470 ArchArgFPUID == llvm::ARM::FK_NONE || 471 CPUArgFPUID == llvm::ARM::FK_NONE) { 472 // -mfpu=none, -march=armvX+nofp or -mcpu=X+nofp is *very* similar to 473 // -mfloat-abi=soft, only that it should not disable MVE-I. They disable the 474 // FPU, but not the FPU registers, thus MVE-I, which depends only on the 475 // latter, is still supported. 476 Features.insert(Features.end(), 477 {"-dotprod", "-fp16fml", "-bf16", "-mve.fp"}); 478 if (!hasIntegerMVE(Features)) 479 Features.emplace_back("-fpregs"); 480 } 481 482 // En/disable crc code generation. 483 if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) { 484 if (A->getOption().matches(options::OPT_mcrc)) 485 Features.push_back("+crc"); 486 else 487 Features.push_back("-crc"); 488 } 489 490 // For Arch >= ARMv8.0 && A profile: crypto = sha2 + aes 491 // FIXME: this needs reimplementation after the TargetParser rewrite 492 auto CryptoIt = llvm::find_if(llvm::reverse(Features), [](const StringRef F) { 493 return F.contains("crypto"); 494 }); 495 if (CryptoIt != Features.rend()) { 496 if (CryptoIt->take_front() == "+") { 497 StringRef ArchSuffix = arm::getLLVMArchSuffixForARM( 498 arm::getARMTargetCPU(CPUName, ArchName, Triple), ArchName, Triple); 499 if (llvm::ARM::parseArchVersion(ArchSuffix) >= 8 && 500 llvm::ARM::parseArchProfile(ArchSuffix) == 501 llvm::ARM::ProfileKind::A) { 502 if (ArchName.find_lower("+nosha2") == StringRef::npos && 503 CPUName.find_lower("+nosha2") == StringRef::npos) 504 Features.push_back("+sha2"); 505 if (ArchName.find_lower("+noaes") == StringRef::npos && 506 CPUName.find_lower("+noaes") == StringRef::npos) 507 Features.push_back("+aes"); 508 } else { 509 D.Diag(clang::diag::warn_target_unsupported_extension) 510 << "crypto" 511 << llvm::ARM::getArchName(llvm::ARM::parseArch(ArchSuffix)); 512 // With -fno-integrated-as -mfpu=crypto-neon-fp-armv8 some assemblers such as the GNU assembler 513 // will permit the use of crypto instructions as the fpu will override the architecture. 514 // We keep the crypto feature in this case to preserve compatibility. 515 // In all other cases we remove the crypto feature. 516 if (!Args.hasArg(options::OPT_fno_integrated_as)) 517 Features.push_back("-crypto"); 518 } 519 } 520 } 521 522 // CMSE: Check for target 8M (for -mcmse to be applicable) is performed later. 523 if (Args.getLastArg(options::OPT_mcmse)) 524 Features.push_back("+8msecext"); 525 526 // Look for the last occurrence of -mlong-calls or -mno-long-calls. If 527 // neither options are specified, see if we are compiling for kernel/kext and 528 // decide whether to pass "+long-calls" based on the OS and its version. 529 if (Arg *A = Args.getLastArg(options::OPT_mlong_calls, 530 options::OPT_mno_long_calls)) { 531 if (A->getOption().matches(options::OPT_mlong_calls)) 532 Features.push_back("+long-calls"); 533 } else if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6)) && 534 !Triple.isWatchOS()) { 535 Features.push_back("+long-calls"); 536 } 537 538 // Generate execute-only output (no data access to code sections). 539 // This only makes sense for the compiler, not for the assembler. 540 if (!ForAS) { 541 // Supported only on ARMv6T2 and ARMv7 and above. 542 // Cannot be combined with -mno-movt or -mlong-calls 543 if (Arg *A = Args.getLastArg(options::OPT_mexecute_only, options::OPT_mno_execute_only)) { 544 if (A->getOption().matches(options::OPT_mexecute_only)) { 545 if (getARMSubArchVersionNumber(Triple) < 7 && 546 llvm::ARM::parseArch(Triple.getArchName()) != llvm::ARM::ArchKind::ARMV6T2) 547 D.Diag(diag::err_target_unsupported_execute_only) << Triple.getArchName(); 548 else if (Arg *B = Args.getLastArg(options::OPT_mno_movt)) 549 D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args); 550 // Long calls create constant pool entries and have not yet been fixed up 551 // to play nicely with execute-only. Hence, they cannot be used in 552 // execute-only code for now 553 else if (Arg *B = Args.getLastArg(options::OPT_mlong_calls, options::OPT_mno_long_calls)) { 554 if (B->getOption().matches(options::OPT_mlong_calls)) 555 D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args); 556 } 557 Features.push_back("+execute-only"); 558 } 559 } 560 } 561 562 // Kernel code has more strict alignment requirements. 563 if (KernelOrKext) 564 Features.push_back("+strict-align"); 565 else if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access, 566 options::OPT_munaligned_access)) { 567 if (A->getOption().matches(options::OPT_munaligned_access)) { 568 // No v6M core supports unaligned memory access (v6M ARM ARM A3.2). 569 if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m) 570 D.Diag(diag::err_target_unsupported_unaligned) << "v6m"; 571 // v8M Baseline follows on from v6M, so doesn't support unaligned memory 572 // access either. 573 else if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8m_baseline) 574 D.Diag(diag::err_target_unsupported_unaligned) << "v8m.base"; 575 } else 576 Features.push_back("+strict-align"); 577 } else { 578 // Assume pre-ARMv6 doesn't support unaligned accesses. 579 // 580 // ARMv6 may or may not support unaligned accesses depending on the 581 // SCTLR.U bit, which is architecture-specific. We assume ARMv6 582 // Darwin and NetBSD targets support unaligned accesses, and others don't. 583 // 584 // ARMv7 always has SCTLR.U set to 1, but it has a new SCTLR.A bit 585 // which raises an alignment fault on unaligned accesses. Linux 586 // defaults this bit to 0 and handles it as a system-wide (not 587 // per-process) setting. It is therefore safe to assume that ARMv7+ 588 // Linux targets support unaligned accesses. The same goes for NaCl. 589 // 590 // The above behavior is consistent with GCC. 591 int VersionNum = getARMSubArchVersionNumber(Triple); 592 if (Triple.isOSDarwin() || Triple.isOSNetBSD()) { 593 if (VersionNum < 6 || 594 Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m) 595 Features.push_back("+strict-align"); 596 } else if (Triple.isOSLinux() || Triple.isOSNaCl()) { 597 if (VersionNum < 7) 598 Features.push_back("+strict-align"); 599 } else 600 Features.push_back("+strict-align"); 601 } 602 603 // llvm does not support reserving registers in general. There is support 604 // for reserving r9 on ARM though (defined as a platform-specific register 605 // in ARM EABI). 606 if (Args.hasArg(options::OPT_ffixed_r9)) 607 Features.push_back("+reserve-r9"); 608 609 // The kext linker doesn't know how to deal with movw/movt. 610 if (KernelOrKext || Args.hasArg(options::OPT_mno_movt)) 611 Features.push_back("+no-movt"); 612 613 if (Args.hasArg(options::OPT_mno_neg_immediates)) 614 Features.push_back("+no-neg-immediates"); 615 616 // Enable/disable straight line speculation hardening. 617 if (Arg *A = Args.getLastArg(options::OPT_mharden_sls_EQ)) { 618 StringRef Scope = A->getValue(); 619 bool EnableRetBr = false; 620 bool EnableBlr = false; 621 if (Scope != "none" && Scope != "all") { 622 SmallVector<StringRef, 4> Opts; 623 Scope.split(Opts, ","); 624 for (auto Opt : Opts) { 625 Opt = Opt.trim(); 626 if (Opt == "retbr") { 627 EnableRetBr = true; 628 continue; 629 } 630 if (Opt == "blr") { 631 EnableBlr = true; 632 continue; 633 } 634 D.Diag(diag::err_invalid_sls_hardening) 635 << Scope << A->getAsString(Args); 636 break; 637 } 638 } else if (Scope == "all") { 639 EnableRetBr = true; 640 EnableBlr = true; 641 } 642 643 if (EnableRetBr || EnableBlr) 644 if (!(isARMAProfile(Triple) && getARMSubArchVersionNumber(Triple) >= 7)) 645 D.Diag(diag::err_sls_hardening_arm_not_supported) 646 << Scope << A->getAsString(Args); 647 648 if (EnableRetBr) 649 Features.push_back("+harden-sls-retbr"); 650 if (EnableBlr) 651 Features.push_back("+harden-sls-blr"); 652 } 653 654 } 655 656 const std::string arm::getARMArch(StringRef Arch, const llvm::Triple &Triple) { 657 std::string MArch; 658 if (!Arch.empty()) 659 MArch = std::string(Arch); 660 else 661 MArch = std::string(Triple.getArchName()); 662 MArch = StringRef(MArch).split("+").first.lower(); 663 664 // Handle -march=native. 665 if (MArch == "native") { 666 std::string CPU = std::string(llvm::sys::getHostCPUName()); 667 if (CPU != "generic") { 668 // Translate the native cpu into the architecture suffix for that CPU. 669 StringRef Suffix = arm::getLLVMArchSuffixForARM(CPU, MArch, Triple); 670 // If there is no valid architecture suffix for this CPU we don't know how 671 // to handle it, so return no architecture. 672 if (Suffix.empty()) 673 MArch = ""; 674 else 675 MArch = std::string("arm") + Suffix.str(); 676 } 677 } 678 679 return MArch; 680 } 681 682 /// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting. 683 StringRef arm::getARMCPUForMArch(StringRef Arch, const llvm::Triple &Triple) { 684 std::string MArch = getARMArch(Arch, Triple); 685 // getARMCPUForArch defaults to the triple if MArch is empty, but empty MArch 686 // here means an -march=native that we can't handle, so instead return no CPU. 687 if (MArch.empty()) 688 return StringRef(); 689 690 // We need to return an empty string here on invalid MArch values as the 691 // various places that call this function can't cope with a null result. 692 return Triple.getARMCPUForArch(MArch); 693 } 694 695 /// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting. 696 std::string arm::getARMTargetCPU(StringRef CPU, StringRef Arch, 697 const llvm::Triple &Triple) { 698 // FIXME: Warn on inconsistent use of -mcpu and -march. 699 // If we have -mcpu=, use that. 700 if (!CPU.empty()) { 701 std::string MCPU = StringRef(CPU).split("+").first.lower(); 702 // Handle -mcpu=native. 703 if (MCPU == "native") 704 return std::string(llvm::sys::getHostCPUName()); 705 else 706 return MCPU; 707 } 708 709 return std::string(getARMCPUForMArch(Arch, Triple)); 710 } 711 712 /// getLLVMArchSuffixForARM - Get the LLVM ArchKind value to use for a 713 /// particular CPU (or Arch, if CPU is generic). This is needed to 714 /// pass to functions like llvm::ARM::getDefaultFPU which need an 715 /// ArchKind as well as a CPU name. 716 llvm::ARM::ArchKind arm::getLLVMArchKindForARM(StringRef CPU, StringRef Arch, 717 const llvm::Triple &Triple) { 718 llvm::ARM::ArchKind ArchKind; 719 if (CPU == "generic" || CPU.empty()) { 720 std::string ARMArch = tools::arm::getARMArch(Arch, Triple); 721 ArchKind = llvm::ARM::parseArch(ARMArch); 722 if (ArchKind == llvm::ARM::ArchKind::INVALID) 723 // In case of generic Arch, i.e. "arm", 724 // extract arch from default cpu of the Triple 725 ArchKind = llvm::ARM::parseCPUArch(Triple.getARMCPUForArch(ARMArch)); 726 } else { 727 // FIXME: horrible hack to get around the fact that Cortex-A7 is only an 728 // armv7k triple if it's actually been specified via "-arch armv7k". 729 ArchKind = (Arch == "armv7k" || Arch == "thumbv7k") 730 ? llvm::ARM::ArchKind::ARMV7K 731 : llvm::ARM::parseCPUArch(CPU); 732 } 733 return ArchKind; 734 } 735 736 /// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular 737 /// CPU (or Arch, if CPU is generic). 738 // FIXME: This is redundant with -mcpu, why does LLVM use this. 739 StringRef arm::getLLVMArchSuffixForARM(StringRef CPU, StringRef Arch, 740 const llvm::Triple &Triple) { 741 llvm::ARM::ArchKind ArchKind = getLLVMArchKindForARM(CPU, Arch, Triple); 742 if (ArchKind == llvm::ARM::ArchKind::INVALID) 743 return ""; 744 return llvm::ARM::getSubArch(ArchKind); 745 } 746 747 void arm::appendBE8LinkFlag(const ArgList &Args, ArgStringList &CmdArgs, 748 const llvm::Triple &Triple) { 749 if (Args.hasArg(options::OPT_r)) 750 return; 751 752 // ARMv7 (and later) and ARMv6-M do not support BE-32, so instruct the linker 753 // to generate BE-8 executables. 754 if (arm::getARMSubArchVersionNumber(Triple) >= 7 || arm::isARMMProfile(Triple)) 755 CmdArgs.push_back("--be8"); 756 } 757