brintos

brintos / llvm-project-archived public Read only

0
0
Text · 47.8 KiB · 55eb2dc Raw
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