1191 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "ARM.h"10#include "clang/Driver/Driver.h"11#include "clang/Options/Options.h"12#include "llvm/ADT/StringSwitch.h"13#include "llvm/Option/ArgList.h"14#include "llvm/TargetParser/ARMTargetParser.h"15#include "llvm/TargetParser/Host.h"16 17using namespace clang::driver;18using namespace clang::driver::tools;19using namespace clang;20using namespace llvm::opt;21 22// Get SubArch (vN).23int arm::getARMSubArchVersionNumber(const llvm::Triple &Triple) {24 llvm::StringRef Arch = Triple.getArchName();25 return llvm::ARM::parseArchVersion(Arch);26}27 28// True if M-profile.29bool arm::isARMMProfile(const llvm::Triple &Triple) {30 llvm::StringRef Arch = Triple.getArchName();31 return llvm::ARM::parseArchProfile(Arch) == llvm::ARM::ProfileKind::M;32}33 34// On Arm the endianness of the output file is determined by the target and35// can be overridden by the pseudo-target flags '-mlittle-endian'/'-EL' and36// '-mbig-endian'/'-EB'. Unlike other targets the flag does not result in a37// normalized triple so we must handle the flag here.38bool arm::isARMBigEndian(const llvm::Triple &Triple, const ArgList &Args) {39 if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,40 options::OPT_mbig_endian)) {41 return !A->getOption().matches(options::OPT_mlittle_endian);42 }43 44 return Triple.getArch() == llvm::Triple::armeb ||45 Triple.getArch() == llvm::Triple::thumbeb;46}47 48// True if A-profile.49bool arm::isARMAProfile(const llvm::Triple &Triple) {50 llvm::StringRef Arch = Triple.getArchName();51 return llvm::ARM::parseArchProfile(Arch) == llvm::ARM::ProfileKind::A;52}53 54/// Is the triple {arm,armeb,thumb,thumbeb}-none-none-{eabi,eabihf} ?55bool arm::isARMEABIBareMetal(const llvm::Triple &Triple) {56 auto arch = Triple.getArch();57 if (arch != llvm::Triple::arm && arch != llvm::Triple::thumb &&58 arch != llvm::Triple::armeb && arch != llvm::Triple::thumbeb)59 return false;60 61 if (Triple.getVendor() != llvm::Triple::UnknownVendor)62 return false;63 64 if (Triple.getOS() != llvm::Triple::UnknownOS)65 return false;66 67 if (Triple.getEnvironment() != llvm::Triple::EABI &&68 Triple.getEnvironment() != llvm::Triple::EABIHF)69 return false;70 71 return true;72}73 74// Get Arch/CPU from args.75void arm::getARMArchCPUFromArgs(const ArgList &Args, llvm::StringRef &Arch,76 llvm::StringRef &CPU, bool FromAs) {77 if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))78 CPU = A->getValue();79 if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))80 Arch = A->getValue();81 if (!FromAs)82 return;83 84 for (const Arg *A :85 Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {86 // Use getValues because -Wa can have multiple arguments87 // e.g. -Wa,-mcpu=foo,-mcpu=bar88 for (StringRef Value : A->getValues()) {89 if (Value.starts_with("-mcpu="))90 CPU = Value.substr(6);91 if (Value.starts_with("-march="))92 Arch = Value.substr(7);93 }94 }95}96 97// Handle -mhwdiv=.98// FIXME: Use ARMTargetParser.99static void getARMHWDivFeatures(const Driver &D, const Arg *A,100 const ArgList &Args, StringRef HWDiv,101 std::vector<StringRef> &Features) {102 uint64_t HWDivID = llvm::ARM::parseHWDiv(HWDiv);103 if (!llvm::ARM::getHWDivFeatures(HWDivID, Features))104 D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);105}106 107// Handle -mfpu=.108static llvm::ARM::FPUKind getARMFPUFeatures(const Driver &D, const Arg *A,109 const ArgList &Args, StringRef FPU,110 std::vector<StringRef> &Features) {111 llvm::ARM::FPUKind FPUKind = llvm::ARM::parseFPU(FPU);112 if (!llvm::ARM::getFPUFeatures(FPUKind, Features))113 D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);114 return FPUKind;115}116 117// Decode ARM features from string like +[no]featureA+[no]featureB+...118static bool DecodeARMFeatures(const Driver &D, StringRef text, StringRef CPU,119 llvm::ARM::ArchKind ArchKind,120 std::vector<StringRef> &Features,121 llvm::ARM::FPUKind &ArgFPUKind) {122 SmallVector<StringRef, 8> Split;123 text.split(Split, StringRef("+"), -1, false);124 125 for (StringRef Feature : Split) {126 if (!appendArchExtFeatures(CPU, ArchKind, Feature, Features, ArgFPUKind))127 return false;128 }129 return true;130}131 132static void DecodeARMFeaturesFromCPU(const Driver &D, StringRef CPU,133 std::vector<StringRef> &Features) {134 CPU = CPU.split("+").first;135 if (CPU != "generic") {136 llvm::ARM::ArchKind ArchKind = llvm::ARM::parseCPUArch(CPU);137 uint64_t Extension = llvm::ARM::getDefaultExtensions(CPU, ArchKind);138 llvm::ARM::getExtensionFeatures(Extension, Features);139 }140}141 142// Check if -march is valid by checking if it can be canonicalised and parsed.143// getARMArch is used here instead of just checking the -march value in order144// to handle -march=native correctly.145static void checkARMArchName(const Driver &D, const Arg *A, const ArgList &Args,146 llvm::StringRef ArchName, llvm::StringRef CPUName,147 std::vector<StringRef> &Features,148 const llvm::Triple &Triple,149 llvm::ARM::FPUKind &ArgFPUKind) {150 std::pair<StringRef, StringRef> Split = ArchName.split("+");151 152 std::string MArch = arm::getARMArch(ArchName, Triple);153 llvm::ARM::ArchKind ArchKind = llvm::ARM::parseArch(MArch);154 if (ArchKind == llvm::ARM::ArchKind::INVALID ||155 (Split.second.size() &&156 !DecodeARMFeatures(D, Split.second, CPUName, ArchKind, Features,157 ArgFPUKind)))158 D.Diag(clang::diag::err_drv_unsupported_option_argument)159 << A->getSpelling() << A->getValue();160}161 162// Check -mcpu=. Needs ArchName to handle -mcpu=generic.163static void checkARMCPUName(const Driver &D, const Arg *A, const ArgList &Args,164 llvm::StringRef CPUName, llvm::StringRef ArchName,165 std::vector<StringRef> &Features,166 const llvm::Triple &Triple,167 llvm::ARM::FPUKind &ArgFPUKind) {168 std::pair<StringRef, StringRef> Split = CPUName.split("+");169 170 std::string CPU = arm::getARMTargetCPU(CPUName, ArchName, Triple);171 llvm::ARM::ArchKind ArchKind =172 arm::getLLVMArchKindForARM(CPU, ArchName, Triple);173 if (ArchKind == llvm::ARM::ArchKind::INVALID ||174 (Split.second.size() && !DecodeARMFeatures(D, Split.second, CPU, ArchKind,175 Features, ArgFPUKind)))176 D.Diag(clang::diag::err_drv_unsupported_option_argument)177 << A->getSpelling() << A->getValue();178}179 180// If -mfloat-abi=hard or -mhard-float are specified explicitly then check that181// floating point registers are available on the target CPU.182static void checkARMFloatABI(const Driver &D, const ArgList &Args,183 bool HasFPRegs) {184 if (HasFPRegs)185 return;186 const Arg *A =187 Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,188 options::OPT_mfloat_abi_EQ);189 if (A && (A->getOption().matches(options::OPT_mhard_float) ||190 (A->getOption().matches(options::OPT_mfloat_abi_EQ) &&191 A->getValue() == StringRef("hard"))))192 D.Diag(clang::diag::warn_drv_no_floating_point_registers)193 << A->getAsString(Args);194}195 196bool arm::useAAPCSForMachO(const llvm::Triple &T) {197 // The backend is hardwired to assume AAPCS for M-class processors, ensure198 // the frontend matches that.199 return T.getEnvironment() == llvm::Triple::EABI ||200 T.getEnvironment() == llvm::Triple::EABIHF ||201 T.getOS() == llvm::Triple::UnknownOS || isARMMProfile(T);202}203 204// Check whether the architecture backend has support for the MRC/MCR205// instructions that are used to set the hard thread pointer ("CP15 C13206// Thread id").207// This is not identical to ability to use the instruction, as the ARMV6K208// variants can only use it in Arm mode since they don't support Thumb2209// encoding.210bool arm::isHardTPSupported(const llvm::Triple &Triple) {211 int Ver = getARMSubArchVersionNumber(Triple);212 llvm::ARM::ArchKind AK = llvm::ARM::parseArch(Triple.getArchName());213 return AK == llvm::ARM::ArchKind::ARMV6K ||214 AK == llvm::ARM::ArchKind::ARMV6KZ ||215 (Ver >= 7 && !isARMMProfile(Triple));216}217 218// Checks whether the architecture is capable of supporting the Thumb2 encoding219static bool supportsThumb2Encoding(const llvm::Triple &Triple) {220 int Ver = arm::getARMSubArchVersionNumber(Triple);221 llvm::ARM::ArchKind AK = llvm::ARM::parseArch(Triple.getArchName());222 return AK == llvm::ARM::ArchKind::ARMV6T2 ||223 (Ver >= 7 && AK != llvm::ARM::ArchKind::ARMV8MBaseline);224}225 226// Select mode for reading thread pointer (-mtp=soft/cp15).227arm::ReadTPMode arm::getReadTPMode(const Driver &D, const ArgList &Args,228 const llvm::Triple &Triple, bool ForAS) {229 Arg *A = Args.getLastArg(options::OPT_mtp_mode_EQ);230 if (A && A->getValue() != StringRef("auto")) {231 arm::ReadTPMode ThreadPointer =232 llvm::StringSwitch<arm::ReadTPMode>(A->getValue())233 .Case("cp15", ReadTPMode::TPIDRURO)234 .Case("tpidrurw", ReadTPMode::TPIDRURW)235 .Case("tpidruro", ReadTPMode::TPIDRURO)236 .Case("tpidrprw", ReadTPMode::TPIDRPRW)237 .Case("soft", ReadTPMode::Soft)238 .Default(ReadTPMode::Invalid);239 if ((ThreadPointer == ReadTPMode::TPIDRURW ||240 ThreadPointer == ReadTPMode::TPIDRURO ||241 ThreadPointer == ReadTPMode::TPIDRPRW) &&242 !isHardTPSupported(Triple) && !ForAS) {243 D.Diag(diag::err_target_unsupported_tp_hard) << Triple.getArchName();244 return ReadTPMode::Invalid;245 }246 if (ThreadPointer != ReadTPMode::Invalid)247 return ThreadPointer;248 if (StringRef(A->getValue()).empty())249 D.Diag(diag::err_drv_missing_arg_mtp) << A->getAsString(Args);250 else251 D.Diag(diag::err_drv_invalid_mtp) << A->getAsString(Args);252 return ReadTPMode::Invalid;253 }254 // In auto mode we enable HW mode only if both the hardware supports it and255 // the thumb2 encoding. For example ARMV6T2 supports thumb2, but not hardware.256 // ARMV6K has HW suport, but not thumb2. Otherwise we could enable it for257 // ARMV6K in thumb mode.258 bool autoUseHWTPMode =259 isHardTPSupported(Triple) && supportsThumb2Encoding(Triple);260 return autoUseHWTPMode ? ReadTPMode::TPIDRURO : ReadTPMode::Soft;261}262 263void arm::setArchNameInTriple(const Driver &D, const ArgList &Args,264 types::ID InputType, llvm::Triple &Triple) {265 StringRef MCPU, MArch;266 if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))267 MCPU = A->getValue();268 if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))269 MArch = A->getValue();270 271 std::string CPU = Triple.isOSBinFormatMachO()272 ? tools::arm::getARMCPUForMArch(MArch, Triple).str()273 : tools::arm::getARMTargetCPU(MCPU, MArch, Triple);274 StringRef Suffix = tools::arm::getLLVMArchSuffixForARM(CPU, MArch, Triple);275 276 bool IsBigEndian = Triple.getArch() == llvm::Triple::armeb ||277 Triple.getArch() == llvm::Triple::thumbeb;278 // Handle pseudo-target flags '-mlittle-endian'/'-EL' and279 // '-mbig-endian'/'-EB'.280 if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,281 options::OPT_mbig_endian)) {282 IsBigEndian = !A->getOption().matches(options::OPT_mlittle_endian);283 }284 std::string ArchName = IsBigEndian ? "armeb" : "arm";285 286 // FIXME: Thumb should just be another -target-feaure, not in the triple.287 bool IsMProfile =288 llvm::ARM::parseArchProfile(Suffix) == llvm::ARM::ProfileKind::M;289 bool ThumbDefault = IsMProfile ||290 // Thumb2 is the default for V7 on Darwin.291 (llvm::ARM::parseArchVersion(Suffix) == 7 &&292 Triple.isOSBinFormatMachO()) ||293 // Thumb2 is the default for Fuchsia.294 Triple.isOSFuchsia() ||295 // FIXME: this is invalid for WindowsCE296 Triple.isOSWindows();297 298 // Check if ARM ISA was explicitly selected (using -mno-thumb or -marm) for299 // M-Class CPUs/architecture variants, which is not supported.300 bool ARMModeRequested =301 !Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, ThumbDefault);302 if (IsMProfile && ARMModeRequested) {303 if (MCPU.size())304 D.Diag(diag::err_cpu_unsupported_isa) << CPU << "ARM";305 else306 D.Diag(diag::err_arch_unsupported_isa)307 << tools::arm::getARMArch(MArch, Triple) << "ARM";308 }309 310 // Check to see if an explicit choice to use thumb has been made via311 // -mthumb. For assembler files we must check for -mthumb in the options312 // passed to the assembler via -Wa or -Xassembler.313 bool IsThumb = false;314 if (InputType != types::TY_PP_Asm)315 IsThumb =316 Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, ThumbDefault);317 else {318 // Ideally we would check for these flags in319 // CollectArgsForIntegratedAssembler but we can't change the ArchName at320 // that point.321 llvm::StringRef WaMArch, WaMCPU;322 for (const auto *A :323 Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {324 for (StringRef Value : A->getValues()) {325 // There is no assembler equivalent of -mno-thumb, -marm, or -mno-arm.326 if (Value == "-mthumb")327 IsThumb = true;328 else if (Value.starts_with("-march="))329 WaMArch = Value.substr(7);330 else if (Value.starts_with("-mcpu="))331 WaMCPU = Value.substr(6);332 }333 }334 335 if (WaMCPU.size() || WaMArch.size()) {336 // The way this works means that we prefer -Wa,-mcpu's architecture337 // over -Wa,-march. Which matches the compiler behaviour.338 Suffix = tools::arm::getLLVMArchSuffixForARM(WaMCPU, WaMArch, Triple);339 }340 }341 342 // Assembly files should start in ARM mode, unless arch is M-profile, or343 // -mthumb has been passed explicitly to the assembler. Windows is always344 // thumb.345 if (IsThumb || IsMProfile || Triple.isOSWindows()) {346 if (IsBigEndian)347 ArchName = "thumbeb";348 else349 ArchName = "thumb";350 }351 Triple.setArchName(ArchName + Suffix.str());352}353 354void arm::setFloatABIInTriple(const Driver &D, const ArgList &Args,355 llvm::Triple &Triple) {356 if (Triple.isOSLiteOS()) {357 Triple.setEnvironment(llvm::Triple::OpenHOS);358 return;359 }360 361 bool isHardFloat =362 (arm::getARMFloatABI(D, Triple, Args) == arm::FloatABI::Hard);363 364 switch (Triple.getEnvironment()) {365 case llvm::Triple::GNUEABI:366 case llvm::Triple::GNUEABIHF:367 Triple.setEnvironment(isHardFloat ? llvm::Triple::GNUEABIHF368 : llvm::Triple::GNUEABI);369 break;370 case llvm::Triple::GNUEABIT64:371 case llvm::Triple::GNUEABIHFT64:372 Triple.setEnvironment(isHardFloat ? llvm::Triple::GNUEABIHFT64373 : llvm::Triple::GNUEABIT64);374 break;375 case llvm::Triple::EABI:376 case llvm::Triple::EABIHF:377 Triple.setEnvironment(isHardFloat ? llvm::Triple::EABIHF378 : llvm::Triple::EABI);379 break;380 case llvm::Triple::MuslEABI:381 case llvm::Triple::MuslEABIHF:382 Triple.setEnvironment(isHardFloat ? llvm::Triple::MuslEABIHF383 : llvm::Triple::MuslEABI);384 break;385 case llvm::Triple::OpenHOS:386 break;387 default: {388 arm::FloatABI DefaultABI = arm::getDefaultFloatABI(Triple);389 if (DefaultABI != arm::FloatABI::Invalid &&390 isHardFloat != (DefaultABI == arm::FloatABI::Hard)) {391 Arg *ABIArg =392 Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,393 options::OPT_mfloat_abi_EQ);394 assert(ABIArg && "Non-default float abi expected to be from arg");395 D.Diag(diag::err_drv_unsupported_opt_for_target)396 << ABIArg->getAsString(Args) << Triple.getTriple();397 }398 break;399 }400 }401}402 403arm::FloatABI arm::getARMFloatABI(const ToolChain &TC, const ArgList &Args) {404 return arm::getARMFloatABI(TC.getDriver(), TC.getEffectiveTriple(), Args);405}406 407arm::FloatABI arm::getDefaultFloatABI(const llvm::Triple &Triple) {408 auto SubArch = getARMSubArchVersionNumber(Triple);409 switch (Triple.getOS()) {410 case llvm::Triple::Darwin:411 case llvm::Triple::MacOSX:412 case llvm::Triple::IOS:413 case llvm::Triple::TvOS:414 case llvm::Triple::DriverKit:415 case llvm::Triple::XROS:416 // Darwin defaults to "softfp" for v6 and v7.417 if (Triple.isWatchABI())418 return FloatABI::Hard;419 else420 return (SubArch == 6 || SubArch == 7) ? FloatABI::SoftFP : FloatABI::Soft;421 422 case llvm::Triple::WatchOS:423 return FloatABI::Hard;424 425 // FIXME: this is invalid for WindowsCE426 case llvm::Triple::Win32:427 // It is incorrect to select hard float ABI on MachO platforms if the ABI is428 // "apcs-gnu".429 if (Triple.isOSBinFormatMachO() && !useAAPCSForMachO(Triple))430 return FloatABI::Soft;431 return FloatABI::Hard;432 433 case llvm::Triple::NetBSD:434 switch (Triple.getEnvironment()) {435 case llvm::Triple::EABIHF:436 case llvm::Triple::GNUEABIHF:437 return FloatABI::Hard;438 default:439 return FloatABI::Soft;440 }441 break;442 443 case llvm::Triple::FreeBSD:444 switch (Triple.getEnvironment()) {445 case llvm::Triple::GNUEABIHF:446 return FloatABI::Hard;447 default:448 // FreeBSD defaults to soft float449 return FloatABI::Soft;450 }451 break;452 453 case llvm::Triple::Haiku:454 case llvm::Triple::OpenBSD:455 return FloatABI::SoftFP;456 457 case llvm::Triple::Fuchsia:458 return FloatABI::Hard;459 460 default:461 if (Triple.isOHOSFamily())462 return FloatABI::Soft;463 switch (Triple.getEnvironment()) {464 case llvm::Triple::GNUEABIHF:465 case llvm::Triple::GNUEABIHFT64:466 case llvm::Triple::MuslEABIHF:467 case llvm::Triple::EABIHF:468 return FloatABI::Hard;469 case llvm::Triple::Android:470 case llvm::Triple::GNUEABI:471 case llvm::Triple::GNUEABIT64:472 case llvm::Triple::MuslEABI:473 case llvm::Triple::EABI:474 // EABI is always AAPCS, and if it was not marked 'hard', it's softfp475 return FloatABI::SoftFP;476 default:477 return FloatABI::Invalid;478 }479 }480 return FloatABI::Invalid;481}482 483// Select the float ABI as determined by -msoft-float, -mhard-float, and484// -mfloat-abi=.485arm::FloatABI arm::getARMFloatABI(const Driver &D, const llvm::Triple &Triple,486 const ArgList &Args) {487 arm::FloatABI ABI = FloatABI::Invalid;488 if (Arg *A =489 Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,490 options::OPT_mfloat_abi_EQ)) {491 if (A->getOption().matches(options::OPT_msoft_float)) {492 ABI = FloatABI::Soft;493 } else if (A->getOption().matches(options::OPT_mhard_float)) {494 ABI = FloatABI::Hard;495 } else {496 ABI = llvm::StringSwitch<arm::FloatABI>(A->getValue())497 .Case("soft", FloatABI::Soft)498 .Case("softfp", FloatABI::SoftFP)499 .Case("hard", FloatABI::Hard)500 .Default(FloatABI::Invalid);501 if (ABI == FloatABI::Invalid && !StringRef(A->getValue()).empty()) {502 D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);503 ABI = FloatABI::Soft;504 }505 }506 }507 508 // If unspecified, choose the default based on the platform.509 if (ABI == FloatABI::Invalid)510 ABI = arm::getDefaultFloatABI(Triple);511 512 if (ABI == FloatABI::Invalid) {513 // Assume "soft", but warn the user we are guessing.514 if (Triple.isOSBinFormatMachO() &&515 Triple.getSubArch() == llvm::Triple::ARMSubArch_v7em)516 ABI = FloatABI::Hard;517 else518 ABI = FloatABI::Soft;519 520 if (Triple.getOS() != llvm::Triple::UnknownOS ||521 !Triple.isOSBinFormatMachO())522 D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft";523 }524 525 assert(ABI != FloatABI::Invalid && "must select an ABI");526 return ABI;527}528 529static bool hasIntegerMVE(const std::vector<StringRef> &F) {530 auto MVE = llvm::find(llvm::reverse(F), "+mve");531 auto NoMVE = llvm::find(llvm::reverse(F), "-mve");532 return MVE != F.rend() &&533 (NoMVE == F.rend() || std::distance(MVE, NoMVE) > 0);534}535 536llvm::ARM::FPUKind arm::getARMTargetFeatures(const Driver &D,537 const llvm::Triple &Triple,538 const ArgList &Args,539 std::vector<StringRef> &Features,540 bool ForAS, bool ForMultilib) {541 bool KernelOrKext =542 Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);543 arm::FloatABI ABI = arm::getARMFloatABI(D, Triple, Args);544 std::optional<std::pair<const Arg *, StringRef>> WaCPU, WaFPU, WaHDiv, WaArch;545 546 // This vector will accumulate features from the architecture547 // extension suffixes on -mcpu and -march (e.g. the 'bar' in548 // -mcpu=foo+bar). We want to apply those after the features derived549 // from the FPU, in case -mfpu generates a negative feature which550 // the +bar is supposed to override.551 std::vector<StringRef> ExtensionFeatures;552 553 if (!ForAS) {554 // FIXME: Note, this is a hack, the LLVM backend doesn't actually use these555 // yet (it uses the -mfloat-abi and -msoft-float options), and it is556 // stripped out by the ARM target. We should probably pass this a new557 // -target-option, which is handled by the -cc1/-cc1as invocation.558 //559 // FIXME2: For consistency, it would be ideal if we set up the target560 // machine state the same when using the frontend or the assembler. We don't561 // currently do that for the assembler, we pass the options directly to the562 // backend and never even instantiate the frontend TargetInfo. If we did,563 // and used its handleTargetFeatures hook, then we could ensure the564 // assembler and the frontend behave the same.565 566 // Use software floating point operations?567 if (ABI == arm::FloatABI::Soft)568 Features.push_back("+soft-float");569 570 // Use software floating point argument passing?571 if (ABI != arm::FloatABI::Hard)572 Features.push_back("+soft-float-abi");573 } else {574 // Here, we make sure that -Wa,-mfpu/cpu/arch/hwdiv will be passed down575 // to the assembler correctly.576 for (const Arg *A :577 Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {578 // We use getValues here because you can have many options per -Wa579 // We will keep the last one we find for each of these580 for (StringRef Value : A->getValues()) {581 if (Value.starts_with("-mfpu=")) {582 WaFPU = std::make_pair(A, Value.substr(6));583 } else if (Value.starts_with("-mcpu=")) {584 WaCPU = std::make_pair(A, Value.substr(6));585 } else if (Value.starts_with("-mhwdiv=")) {586 WaHDiv = std::make_pair(A, Value.substr(8));587 } else if (Value.starts_with("-march=")) {588 WaArch = std::make_pair(A, Value.substr(7));589 }590 }591 }592 593 // The integrated assembler doesn't implement e_flags setting behavior for594 // -meabi=gnu (gcc -mabi={apcs-gnu,atpcs} passes -meabi=gnu to gas). For595 // compatibility we accept but warn.596 if (Arg *A = Args.getLastArgNoClaim(options::OPT_mabi_EQ))597 A->ignoreTargetSpecific();598 }599 600 arm::ReadTPMode TPMode = getReadTPMode(D, Args, Triple, ForAS);601 602 if (TPMode == ReadTPMode::TPIDRURW)603 Features.push_back("+read-tp-tpidrurw");604 else if (TPMode == ReadTPMode::TPIDRPRW)605 Features.push_back("+read-tp-tpidrprw");606 else if (TPMode == ReadTPMode::TPIDRURO)607 Features.push_back("+read-tp-tpidruro");608 609 const Arg *ArchArg = Args.getLastArg(options::OPT_march_EQ);610 const Arg *CPUArg = Args.getLastArg(options::OPT_mcpu_EQ);611 StringRef ArchName;612 StringRef CPUName;613 llvm::ARM::FPUKind ArchArgFPUKind = llvm::ARM::FK_INVALID;614 llvm::ARM::FPUKind CPUArgFPUKind = llvm::ARM::FK_INVALID;615 616 // Check -mcpu. ClangAs gives preference to -Wa,-mcpu=.617 if (WaCPU) {618 if (CPUArg)619 D.Diag(clang::diag::warn_drv_unused_argument)620 << CPUArg->getAsString(Args);621 CPUName = WaCPU->second;622 CPUArg = WaCPU->first;623 } else if (CPUArg)624 CPUName = CPUArg->getValue();625 626 // Check -march. ClangAs gives preference to -Wa,-march=.627 if (WaArch) {628 if (ArchArg)629 D.Diag(clang::diag::warn_drv_unused_argument)630 << ArchArg->getAsString(Args);631 ArchName = WaArch->second;632 // This will set any features after the base architecture.633 checkARMArchName(D, WaArch->first, Args, ArchName, CPUName,634 ExtensionFeatures, Triple, ArchArgFPUKind);635 // The base architecture was handled in ToolChain::ComputeLLVMTriple because636 // triple is read only by this point.637 } else if (ArchArg) {638 ArchName = ArchArg->getValue();639 checkARMArchName(D, ArchArg, Args, ArchName, CPUName, ExtensionFeatures,640 Triple, ArchArgFPUKind);641 }642 643 // Add CPU features for generic CPUs644 if (CPUName == "native") {645 for (auto &F : llvm::sys::getHostCPUFeatures())646 Features.push_back(647 Args.MakeArgString((F.second ? "+" : "-") + F.first()));648 } else if (!CPUName.empty()) {649 // This sets the default features for the specified CPU. We certainly don't650 // want to override the features that have been explicitly specified on the651 // command line. Therefore, process them directly instead of appending them652 // at the end later.653 DecodeARMFeaturesFromCPU(D, CPUName, Features);654 }655 656 if (CPUArg)657 checkARMCPUName(D, CPUArg, Args, CPUName, ArchName, ExtensionFeatures,658 Triple, CPUArgFPUKind);659 660 // TODO Handle -mtune=. Suppress -Wunused-command-line-argument as a661 // longstanding behavior.662 (void)Args.getLastArg(options::OPT_mtune_EQ);663 664 // Honor -mfpu=. ClangAs gives preference to -Wa,-mfpu=.665 llvm::ARM::FPUKind FPUKind = llvm::ARM::FK_INVALID;666 const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ);667 if (WaFPU) {668 if (FPUArg)669 D.Diag(clang::diag::warn_drv_unused_argument)670 << FPUArg->getAsString(Args);671 (void)getARMFPUFeatures(D, WaFPU->first, Args, WaFPU->second, Features);672 } else if (FPUArg) {673 FPUKind = getARMFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features);674 } else if (Triple.isAndroid() && getARMSubArchVersionNumber(Triple) == 7) {675 const char *AndroidFPU = "neon";676 FPUKind = llvm::ARM::parseFPU(AndroidFPU);677 if (!llvm::ARM::getFPUFeatures(FPUKind, Features))678 D.Diag(clang::diag::err_drv_clang_unsupported)679 << std::string("-mfpu=") + AndroidFPU;680 } else if (ArchArgFPUKind != llvm::ARM::FK_INVALID ||681 CPUArgFPUKind != llvm::ARM::FK_INVALID) {682 FPUKind =683 CPUArgFPUKind != llvm::ARM::FK_INVALID ? CPUArgFPUKind : ArchArgFPUKind;684 (void)llvm::ARM::getFPUFeatures(FPUKind, Features);685 } else {686 std::string CPU = arm::getARMTargetCPU(CPUName, ArchName, Triple);687 bool Generic = CPU == "generic";688 if (Generic && (Triple.isOSWindows() || Triple.isOSDarwin()) &&689 getARMSubArchVersionNumber(Triple) >= 7) {690 FPUKind = llvm::ARM::parseFPU("neon");691 } else {692 llvm::ARM::ArchKind ArchKind =693 arm::getLLVMArchKindForARM(CPU, ArchName, Triple);694 FPUKind = llvm::ARM::getDefaultFPU(CPU, ArchKind);695 }696 (void)llvm::ARM::getFPUFeatures(FPUKind, Features);697 }698 699 // Now we've finished accumulating features from arch, cpu and fpu,700 // we can append the ones for architecture extensions that we701 // collected separately.702 Features.insert(std::end(Features),703 std::begin(ExtensionFeatures), std::end(ExtensionFeatures));704 705 // Honor -mhwdiv=. ClangAs gives preference to -Wa,-mhwdiv=.706 const Arg *HDivArg = Args.getLastArg(options::OPT_mhwdiv_EQ);707 if (WaHDiv) {708 if (HDivArg)709 D.Diag(clang::diag::warn_drv_unused_argument)710 << HDivArg->getAsString(Args);711 getARMHWDivFeatures(D, WaHDiv->first, Args, WaHDiv->second, Features);712 } else if (HDivArg)713 getARMHWDivFeatures(D, HDivArg, Args, HDivArg->getValue(), Features);714 715 // Handle (arch-dependent) fp16fml/fullfp16 relationship.716 // Must happen before any features are disabled due to soft-float.717 // FIXME: this fp16fml option handling will be reimplemented after the718 // TargetParser rewrite.719 const auto ItRNoFullFP16 = std::find(Features.rbegin(), Features.rend(), "-fullfp16");720 const auto ItRFP16FML = std::find(Features.rbegin(), Features.rend(), "+fp16fml");721 if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8_4a) {722 const auto ItRFullFP16 = std::find(Features.rbegin(), Features.rend(), "+fullfp16");723 if (ItRFullFP16 < ItRNoFullFP16 && ItRFullFP16 < ItRFP16FML) {724 // Only entangled feature that can be to the right of this +fullfp16 is -fp16fml.725 // Only append the +fp16fml if there is no -fp16fml after the +fullfp16.726 if (std::find(Features.rbegin(), ItRFullFP16, "-fp16fml") == ItRFullFP16)727 Features.push_back("+fp16fml");728 }729 else730 goto fp16_fml_fallthrough;731 }732 else {733fp16_fml_fallthrough:734 // In both of these cases, putting the 'other' feature on the end of the vector will735 // result in the same effect as placing it immediately after the current feature.736 if (ItRNoFullFP16 < ItRFP16FML)737 Features.push_back("-fp16fml");738 else if (ItRNoFullFP16 > ItRFP16FML)739 Features.push_back("+fullfp16");740 }741 742 // Setting -msoft-float/-mfloat-abi=soft, -mfpu=none, or adding +nofp to743 // -march/-mcpu effectively disables the FPU (GCC ignores the -mfpu options in744 // this case). Note that the ABI can also be set implicitly by the target745 // selected.746 bool HasFPRegs = true;747 if (ABI == arm::FloatABI::Soft) {748 llvm::ARM::getFPUFeatures(llvm::ARM::FK_NONE, Features);749 750 // Disable all features relating to hardware FP, not already disabled by the751 // above call.752 Features.insert(Features.end(),753 {"-dotprod", "-fp16fml", "-bf16", "-mve", "-mve.fp"});754 HasFPRegs = false;755 FPUKind = llvm::ARM::FK_NONE;756 } else if (FPUKind == llvm::ARM::FK_NONE ||757 ArchArgFPUKind == llvm::ARM::FK_NONE ||758 CPUArgFPUKind == llvm::ARM::FK_NONE) {759 // -mfpu=none, -march=armvX+nofp or -mcpu=X+nofp is *very* similar to760 // -mfloat-abi=soft, only that it should not disable MVE-I. They disable the761 // FPU, but not the FPU registers, thus MVE-I, which depends only on the762 // latter, is still supported.763 Features.insert(Features.end(),764 {"-dotprod", "-fp16fml", "-bf16", "-mve.fp"});765 HasFPRegs = hasIntegerMVE(Features);766 FPUKind = llvm::ARM::FK_NONE;767 }768 if (!HasFPRegs)769 Features.emplace_back("-fpregs");770 771 // En/disable crc code generation.772 if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) {773 if (A->getOption().matches(options::OPT_mcrc))774 Features.push_back("+crc");775 else776 Features.push_back("-crc");777 }778 779 // Invalid value of the __ARM_FEATURE_MVE macro when an explicit -mfpu= option780 // disables MVE-FP -mfpu=fpv5-d16 or -mfpu=fpv5-sp-d16 disables the scalar781 // half-precision floating-point operations feature. Therefore, because the782 // M-profile Vector Extension (MVE) floating-point feature requires the scalar783 // half-precision floating-point operations, this option also disables the MVE784 // floating-point feature: -mve.fp785 if (FPUKind == llvm::ARM::FK_FPV5_D16 || FPUKind == llvm::ARM::FK_FPV5_SP_D16)786 Features.push_back("-mve.fp");787 788 // If SIMD has been disabled and the selected FPU supports NEON, then features789 // that rely on NEON instructions should also be disabled.790 bool HasSimd = false;791 const auto ItSimd =792 llvm::find_if(llvm::reverse(Features),793 [](const StringRef F) { return F.contains("neon"); });794 const bool FPUSupportsNeon = (llvm::ARM::FPUNames[FPUKind].NeonSupport ==795 llvm::ARM::NeonSupportLevel::Neon) ||796 (llvm::ARM::FPUNames[FPUKind].NeonSupport ==797 llvm::ARM::NeonSupportLevel::Crypto);798 if (ItSimd != Features.rend())799 HasSimd = ItSimd->starts_with("+");800 if (!HasSimd && FPUSupportsNeon)801 Features.insert(Features.end(),802 {"-sha2", "-aes", "-crypto", "-dotprod", "-bf16", "-i8mm"});803 804 // For Arch >= ARMv8.0 && A or R profile: crypto = sha2 + aes805 // Rather than replace within the feature vector, determine whether each806 // algorithm is enabled and append this to the end of the vector.807 // The algorithms can be controlled by their specific feature or the crypto808 // feature, so their status can be determined by the last occurance of809 // either in the vector. This allows one to supercede the other.810 // e.g. +crypto+noaes in -march/-mcpu should enable sha2, but not aes811 // FIXME: this needs reimplementation after the TargetParser rewrite812 bool HasSHA2 = false;813 bool HasAES = false;814 bool HasBF16 = false;815 bool HasDotprod = false;816 bool HasI8MM = false;817 const auto ItCrypto =818 llvm::find_if(llvm::reverse(Features), [](const StringRef F) {819 return F.contains("crypto");820 });821 const auto ItSHA2 =822 llvm::find_if(llvm::reverse(Features), [](const StringRef F) {823 return F.contains("crypto") || F.contains("sha2");824 });825 const auto ItAES =826 llvm::find_if(llvm::reverse(Features), [](const StringRef F) {827 return F.contains("crypto") || F.contains("aes");828 });829 const auto ItBF16 =830 llvm::find_if(llvm::reverse(Features),831 [](const StringRef F) { return F.contains("bf16"); });832 const auto ItDotprod =833 llvm::find_if(llvm::reverse(Features),834 [](const StringRef F) { return F.contains("dotprod"); });835 const auto ItI8MM =836 llvm::find_if(llvm::reverse(Features),837 [](const StringRef F) { return F.contains("i8mm"); });838 if (ItSHA2 != Features.rend())839 HasSHA2 = ItSHA2->starts_with("+");840 if (ItAES != Features.rend())841 HasAES = ItAES->starts_with("+");842 if (ItBF16 != Features.rend())843 HasBF16 = ItBF16->starts_with("+");844 if (ItDotprod != Features.rend())845 HasDotprod = ItDotprod->starts_with("+");846 if (ItI8MM != Features.rend())847 HasI8MM = ItI8MM->starts_with("+");848 if (ItCrypto != Features.rend()) {849 if (HasSHA2 && HasAES)850 Features.push_back("+crypto");851 else852 Features.push_back("-crypto");853 if (HasSHA2)854 Features.push_back("+sha2");855 else856 Features.push_back("-sha2");857 if (HasAES)858 Features.push_back("+aes");859 else860 Features.push_back("-aes");861 }862 // If any of these features are enabled, NEON should also be enabled.863 if (HasAES || HasSHA2 || HasBF16 || HasDotprod || HasI8MM)864 Features.push_back("+neon");865 866 if (HasSHA2 || HasAES) {867 StringRef ArchSuffix = arm::getLLVMArchSuffixForARM(868 arm::getARMTargetCPU(CPUName, ArchName, Triple), ArchName, Triple);869 llvm::ARM::ProfileKind ArchProfile =870 llvm::ARM::parseArchProfile(ArchSuffix);871 if (!((llvm::ARM::parseArchVersion(ArchSuffix) >= 8) &&872 (ArchProfile == llvm::ARM::ProfileKind::A ||873 ArchProfile == llvm::ARM::ProfileKind::R))) {874 if (HasSHA2)875 D.Diag(clang::diag::warn_target_unsupported_extension)876 << "sha2"877 << llvm::ARM::getArchName(llvm::ARM::parseArch(ArchSuffix));878 if (HasAES)879 D.Diag(clang::diag::warn_target_unsupported_extension)880 << "aes"881 << llvm::ARM::getArchName(llvm::ARM::parseArch(ArchSuffix));882 // With -fno-integrated-as -mfpu=crypto-neon-fp-armv8 some assemblers such883 // as the GNU assembler will permit the use of crypto instructions as the884 // fpu will override the architecture. We keep the crypto feature in this885 // case to preserve compatibility. In all other cases we remove the crypto886 // feature.887 if (!Args.hasArg(options::OPT_fno_integrated_as)) {888 Features.push_back("-sha2");889 Features.push_back("-aes");890 }891 }892 }893 894 // Propagate frame-chain model selection895 if (Arg *A = Args.getLastArg(options::OPT_mframe_chain)) {896 StringRef FrameChainOption = A->getValue();897 if (FrameChainOption.starts_with("aapcs"))898 Features.push_back("+aapcs-frame-chain");899 }900 901 // CMSE: Check for target 8M (for -mcmse to be applicable) is performed later.902 if (Args.getLastArg(options::OPT_mcmse))903 Features.push_back("+8msecext");904 905 if (Arg *A = Args.getLastArg(options::OPT_mfix_cmse_cve_2021_35465,906 options::OPT_mno_fix_cmse_cve_2021_35465)) {907 if (!Args.getLastArg(options::OPT_mcmse))908 D.Diag(diag::err_opt_not_valid_without_opt)909 << A->getOption().getName() << "-mcmse";910 911 if (A->getOption().matches(options::OPT_mfix_cmse_cve_2021_35465))912 Features.push_back("+fix-cmse-cve-2021-35465");913 else914 Features.push_back("-fix-cmse-cve-2021-35465");915 }916 917 // This also handles the -m(no-)fix-cortex-a72-1655431 arguments via aliases.918 if (Arg *A = Args.getLastArg(options::OPT_mfix_cortex_a57_aes_1742098,919 options::OPT_mno_fix_cortex_a57_aes_1742098)) {920 if (A->getOption().matches(options::OPT_mfix_cortex_a57_aes_1742098)) {921 Features.push_back("+fix-cortex-a57-aes-1742098");922 } else {923 Features.push_back("-fix-cortex-a57-aes-1742098");924 }925 }926 927 // Look for the last occurrence of -mlong-calls or -mno-long-calls. If928 // neither options are specified, see if we are compiling for kernel/kext and929 // decide whether to pass "+long-calls" based on the OS and its version.930 if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,931 options::OPT_mno_long_calls)) {932 if (A->getOption().matches(options::OPT_mlong_calls))933 Features.push_back("+long-calls");934 } else if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6)) &&935 !Triple.isWatchOS() && !Triple.isXROS()) {936 Features.push_back("+long-calls");937 }938 939 // Generate execute-only output (no data access to code sections).940 // This only makes sense for the compiler, not for the assembler.941 // It's not needed for multilib selection and may hide an unused942 // argument diagnostic if the code is always run.943 if (!ForAS && !ForMultilib) {944 // Supported only on ARMv6T2 and ARMv7 and above.945 // Cannot be combined with -mno-movt.946 if (Arg *A = Args.getLastArg(options::OPT_mexecute_only, options::OPT_mno_execute_only)) {947 if (A->getOption().matches(options::OPT_mexecute_only)) {948 if (getARMSubArchVersionNumber(Triple) < 7 &&949 llvm::ARM::parseArch(Triple.getArchName()) != llvm::ARM::ArchKind::ARMV6T2 &&950 llvm::ARM::parseArch(Triple.getArchName()) != llvm::ARM::ArchKind::ARMV6M)951 D.Diag(diag::err_target_unsupported_execute_only) << Triple.getArchName();952 else if (llvm::ARM::parseArch(Triple.getArchName()) == llvm::ARM::ArchKind::ARMV6M) {953 if (Arg *PIArg = Args.getLastArg(options::OPT_fropi, options::OPT_frwpi,954 options::OPT_fpic, options::OPT_fpie,955 options::OPT_fPIC, options::OPT_fPIE))956 D.Diag(diag::err_opt_not_valid_with_opt_on_target)957 << A->getAsString(Args) << PIArg->getAsString(Args) << Triple.getArchName();958 } else if (Arg *B = Args.getLastArg(options::OPT_mno_movt))959 D.Diag(diag::err_opt_not_valid_with_opt)960 << A->getAsString(Args) << B->getAsString(Args);961 Features.push_back("+execute-only");962 }963 }964 }965 966 if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,967 options::OPT_munaligned_access,968 options::OPT_mstrict_align,969 options::OPT_mno_strict_align)) {970 // Kernel code has more strict alignment requirements.971 if (KernelOrKext ||972 A->getOption().matches(options::OPT_mno_unaligned_access) ||973 A->getOption().matches(options::OPT_mstrict_align)) {974 Features.push_back("+strict-align");975 } else {976 // No v6M core supports unaligned memory access (v6M ARM ARM A3.2).977 if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m)978 D.Diag(diag::err_target_unsupported_unaligned) << "v6m";979 // v8M Baseline follows on from v6M, so doesn't support unaligned memory980 // access either.981 else if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8m_baseline)982 D.Diag(diag::err_target_unsupported_unaligned) << "v8m.base";983 }984 } else {985 // Assume pre-ARMv6 doesn't support unaligned accesses.986 //987 // ARMv6 may or may not support unaligned accesses depending on the988 // SCTLR.U bit, which is architecture-specific. We assume ARMv6989 // Darwin and NetBSD targets support unaligned accesses, and others don't.990 //991 // ARMv7 always has SCTLR.U set to 1, but it has a new SCTLR.A bit which992 // raises an alignment fault on unaligned accesses. Assume ARMv7+ supports993 // unaligned accesses, except ARMv6-M, and ARMv8-M without the Main994 // Extension. This aligns with the default behavior of ARM's downstream995 // versions of GCC and Clang.996 //997 // Users can change the default behavior via -m[no-]unaliged-access.998 int VersionNum = getARMSubArchVersionNumber(Triple);999 if (Triple.isOSDarwin() || Triple.isOSNetBSD()) {1000 if (VersionNum < 6 ||1001 Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m)1002 Features.push_back("+strict-align");1003 } else if (Triple.getVendor() == llvm::Triple::Apple &&1004 Triple.isOSBinFormatMachO()) {1005 // Firmwares on Apple platforms are strict-align by default.1006 Features.push_back("+strict-align");1007 } else if (VersionNum < 7 ||1008 Triple.getSubArch() ==1009 llvm::Triple::SubArchType::ARMSubArch_v6m ||1010 Triple.getSubArch() ==1011 llvm::Triple::SubArchType::ARMSubArch_v8m_baseline) {1012 Features.push_back("+strict-align");1013 }1014 }1015 1016 // llvm does not support reserving registers in general. There is support1017 // for reserving r9 on ARM though (defined as a platform-specific register1018 // in ARM EABI).1019 if (Args.hasArg(options::OPT_ffixed_r9))1020 Features.push_back("+reserve-r9");1021 1022 // The kext linker doesn't know how to deal with movw/movt.1023 if (KernelOrKext || Args.hasArg(options::OPT_mno_movt))1024 Features.push_back("+no-movt");1025 1026 if (Args.hasArg(options::OPT_mno_neg_immediates))1027 Features.push_back("+no-neg-immediates");1028 1029 // Enable/disable straight line speculation hardening.1030 if (Arg *A = Args.getLastArg(options::OPT_mharden_sls_EQ)) {1031 StringRef Scope = A->getValue();1032 bool EnableRetBr = false;1033 bool EnableBlr = false;1034 bool DisableComdat = false;1035 if (Scope != "none") {1036 SmallVector<StringRef, 4> Opts;1037 Scope.split(Opts, ",");1038 for (auto Opt : Opts) {1039 Opt = Opt.trim();1040 if (Opt == "all") {1041 EnableBlr = true;1042 EnableRetBr = true;1043 continue;1044 }1045 if (Opt == "retbr") {1046 EnableRetBr = true;1047 continue;1048 }1049 if (Opt == "blr") {1050 EnableBlr = true;1051 continue;1052 }1053 if (Opt == "comdat") {1054 DisableComdat = false;1055 continue;1056 }1057 if (Opt == "nocomdat") {1058 DisableComdat = true;1059 continue;1060 }1061 D.Diag(diag::err_drv_unsupported_option_argument)1062 << A->getSpelling() << Scope;1063 break;1064 }1065 }1066 1067 if (EnableRetBr || EnableBlr)1068 if (!(isARMAProfile(Triple) && getARMSubArchVersionNumber(Triple) >= 7))1069 D.Diag(diag::err_sls_hardening_arm_not_supported)1070 << Scope << A->getAsString(Args);1071 1072 if (EnableRetBr)1073 Features.push_back("+harden-sls-retbr");1074 if (EnableBlr)1075 Features.push_back("+harden-sls-blr");1076 if (DisableComdat) {1077 Features.push_back("+harden-sls-nocomdat");1078 }1079 }1080 1081 if (Args.getLastArg(options::OPT_mno_bti_at_return_twice))1082 Features.push_back("+no-bti-at-return-twice");1083 1084 checkARMFloatABI(D, Args, HasFPRegs);1085 1086 return FPUKind;1087}1088 1089std::string arm::getARMArch(StringRef Arch, const llvm::Triple &Triple) {1090 std::string MArch;1091 if (!Arch.empty())1092 MArch = std::string(Arch);1093 else1094 MArch = std::string(Triple.getArchName());1095 MArch = StringRef(MArch).split("+").first.lower();1096 1097 // Handle -march=native.1098 if (MArch == "native") {1099 std::string CPU = std::string(llvm::sys::getHostCPUName());1100 if (CPU != "generic") {1101 // Translate the native cpu into the architecture suffix for that CPU.1102 StringRef Suffix = arm::getLLVMArchSuffixForARM(CPU, MArch, Triple);1103 // If there is no valid architecture suffix for this CPU we don't know how1104 // to handle it, so return no architecture.1105 if (Suffix.empty())1106 MArch = "";1107 else1108 MArch = std::string("arm") + Suffix.str();1109 }1110 }1111 1112 return MArch;1113}1114 1115/// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting.1116StringRef arm::getARMCPUForMArch(StringRef Arch, const llvm::Triple &Triple) {1117 std::string MArch = getARMArch(Arch, Triple);1118 // getARMCPUForArch defaults to the triple if MArch is empty, but empty MArch1119 // here means an -march=native that we can't handle, so instead return no CPU.1120 if (MArch.empty())1121 return StringRef();1122 1123 // We need to return an empty string here on invalid MArch values as the1124 // various places that call this function can't cope with a null result.1125 return llvm::ARM::getARMCPUForArch(Triple, MArch);1126}1127 1128/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting.1129std::string arm::getARMTargetCPU(StringRef CPU, StringRef Arch,1130 const llvm::Triple &Triple) {1131 // FIXME: Warn on inconsistent use of -mcpu and -march.1132 // If we have -mcpu=, use that.1133 if (!CPU.empty()) {1134 std::string MCPU = StringRef(CPU).split("+").first.lower();1135 // Handle -mcpu=native.1136 if (MCPU == "native")1137 return std::string(llvm::sys::getHostCPUName());1138 else1139 return MCPU;1140 }1141 1142 return std::string(getARMCPUForMArch(Arch, Triple));1143}1144 1145/// getLLVMArchSuffixForARM - Get the LLVM ArchKind value to use for a1146/// particular CPU (or Arch, if CPU is generic). This is needed to1147/// pass to functions like llvm::ARM::getDefaultFPU which need an1148/// ArchKind as well as a CPU name.1149llvm::ARM::ArchKind arm::getLLVMArchKindForARM(StringRef CPU, StringRef Arch,1150 const llvm::Triple &Triple) {1151 llvm::ARM::ArchKind ArchKind;1152 if (CPU == "generic" || CPU.empty()) {1153 std::string ARMArch = tools::arm::getARMArch(Arch, Triple);1154 ArchKind = llvm::ARM::parseArch(ARMArch);1155 if (ArchKind == llvm::ARM::ArchKind::INVALID)1156 // In case of generic Arch, i.e. "arm",1157 // extract arch from default cpu of the Triple1158 ArchKind =1159 llvm::ARM::parseCPUArch(llvm::ARM::getARMCPUForArch(Triple, ARMArch));1160 } else {1161 // FIXME: horrible hack to get around the fact that Cortex-A7 is only an1162 // armv7k triple if it's actually been specified via "-arch armv7k".1163 ArchKind = (Arch == "armv7k" || Arch == "thumbv7k")1164 ? llvm::ARM::ArchKind::ARMV7K1165 : llvm::ARM::parseCPUArch(CPU);1166 }1167 return ArchKind;1168}1169 1170/// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular1171/// CPU (or Arch, if CPU is generic).1172// FIXME: This is redundant with -mcpu, why does LLVM use this.1173StringRef arm::getLLVMArchSuffixForARM(StringRef CPU, StringRef Arch,1174 const llvm::Triple &Triple) {1175 llvm::ARM::ArchKind ArchKind = getLLVMArchKindForARM(CPU, Arch, Triple);1176 if (ArchKind == llvm::ARM::ArchKind::INVALID)1177 return "";1178 return llvm::ARM::getSubArch(ArchKind);1179}1180 1181void arm::appendBE8LinkFlag(const ArgList &Args, ArgStringList &CmdArgs,1182 const llvm::Triple &Triple) {1183 if (Args.hasArg(options::OPT_r))1184 return;1185 1186 // ARMv7 (and later) and ARMv6-M do not support BE-32, so instruct the linker1187 // to generate BE-8 executables.1188 if (arm::getARMSubArchVersionNumber(Triple) >= 7 || arm::isARMMProfile(Triple))1189 CmdArgs.push_back("--be8");1190}1191