brintos

brintos / llvm-project-archived public Read only

0
0
Text · 16.2 KiB · d6fb2a5 Raw
483 lines · cpp
1//===--- AArch64.cpp - AArch64 (not ARM) Helpers for Tools ------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "AArch64.h"10#include "clang/Driver/CommonArgs.h"11#include "clang/Driver/Driver.h"12#include "clang/Options/Options.h"13#include "llvm/Option/ArgList.h"14#include "llvm/TargetParser/AArch64TargetParser.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/// \returns true if the given triple can determine the default CPU type even23/// if -arch is not specified.24static bool isCPUDeterminedByTriple(const llvm::Triple &Triple) {25  return Triple.isOSDarwin();26}27 28/// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are29/// targeting. Set \p A to the Arg corresponding to the -mcpu argument if it is30/// provided, or to nullptr otherwise.31std::string aarch64::getAArch64TargetCPU(const ArgList &Args,32                                         const llvm::Triple &Triple, Arg *&A) {33  std::string CPU;34  // If we have -mcpu, use that.35  if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) {36    StringRef Mcpu = A->getValue();37    CPU = Mcpu.split("+").first.lower();38  }39 40  CPU = llvm::AArch64::resolveCPUAlias(CPU);41 42  // Handle CPU name is 'native'.43  if (CPU == "native")44    return std::string(llvm::sys::getHostCPUName());45 46  if (CPU.size())47    return CPU;48 49  if (Triple.isTargetMachineMac() &&50      Triple.getArch() == llvm::Triple::aarch64) {51    // Apple Silicon macs default to M1 CPUs.52    return "apple-m1";53  }54 55  if (Triple.getOS() == llvm::Triple::IOS) {56    assert(!Triple.isSimulatorEnvironment() && "iossim should be mac-like");57    // iOS 26 only runs on apple-a12 and later CPUs.58    if (!Triple.isOSVersionLT(26))59      return "apple-a12";60    // arm64 (non-e) iOS 18 only runs on apple-a10 and later CPUs.61    if (!Triple.isOSVersionLT(18) && !Triple.isArm64e())62      return "apple-a10";63  }64 65  if (Triple.isWatchOS()) {66    assert(!Triple.isSimulatorEnvironment() && "watchossim should be mac-like");67    // arm64_32/arm64e watchOS requires S4 before watchOS 26, S6 after.68    if (Triple.getArch() == llvm::Triple::aarch64_32 || Triple.isArm64e())69      return Triple.isOSVersionLT(26) ? "apple-s4" : "apple-s6";70    // arm64 (non-e, non-32) watchOS comes later, and requires S9 anyway.71    return "apple-s9";72  }73 74  if (Triple.isXROS()) {75    // The xrOS simulator runs on M1 as well, it should have been covered above.76    assert(!Triple.isSimulatorEnvironment() && "xrossim should be mac-like");77    return "apple-a12";78  }79  // arm64e requires v8.3a and only runs on apple-a12 and later CPUs.80  if (Triple.isArm64e())81    return "apple-a12";82 83  // Make sure we pick the appropriate Apple CPU when targetting a Darwin OS.84  if (Triple.isOSDarwin())85    return Triple.getArch() == llvm::Triple::aarch64_32 ? "apple-s4"86                                                        : "apple-a7";87 88  return "generic";89}90 91// Decode AArch64 features from string like +[no]featureA+[no]featureB+...92static bool DecodeAArch64Features(const Driver &D, StringRef text,93                                  llvm::AArch64::ExtensionSet &Extensions) {94  SmallVector<StringRef, 8> Split;95  text.split(Split, StringRef("+"), -1, false);96 97  for (StringRef Feature : Split) {98    if (Feature == "neon" || Feature == "noneon") {99      D.Diag(clang::diag::err_drv_no_neon_modifier);100      continue;101    }102    if (!Extensions.parseModifier(Feature))103      return false;104  }105 106  return true;107}108 109// Check if the CPU name and feature modifiers in -mcpu are legal. If yes,110// decode CPU and feature.111static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU,112                              llvm::AArch64::ExtensionSet &Extensions) {113  std::pair<StringRef, StringRef> Split = Mcpu.split("+");114  CPU = Split.first;115 116  if (CPU == "native")117    CPU = llvm::sys::getHostCPUName();118 119  const std::optional<llvm::AArch64::CpuInfo> CpuInfo =120      llvm::AArch64::parseCpu(CPU);121  if (!CpuInfo)122    return false;123 124  Extensions.addCPUDefaults(*CpuInfo);125 126  if (Split.second.size() &&127      !DecodeAArch64Features(D, Split.second, Extensions))128    return false;129 130  return true;131}132 133static bool134getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March,135                                const ArgList &Args,136                                llvm::AArch64::ExtensionSet &Extensions) {137  std::string MarchLowerCase = March.lower();138  std::pair<StringRef, StringRef> Split = StringRef(MarchLowerCase).split("+");139 140  const llvm::AArch64::ArchInfo *ArchInfo =141      llvm::AArch64::parseArch(Split.first);142  if (Split.first == "native")143    ArchInfo = llvm::AArch64::getArchForCpu(llvm::sys::getHostCPUName().str());144  if (!ArchInfo)145    return false;146 147  Extensions.addArchDefaults(*ArchInfo);148 149  if ((Split.second.size() &&150       !DecodeAArch64Features(D, Split.second, Extensions)))151    return false;152 153  return true;154}155 156static bool getAArch64ArchFeaturesFromMcpu(157    const Driver &D, StringRef Mcpu, const ArgList &Args,158    llvm::AArch64::ExtensionSet &Extensions, std::vector<StringRef> &Features) {159  StringRef CPU;160  std::string McpuLowerCase = Mcpu.lower();161  if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, Extensions))162    return false;163 164  if (Mcpu == "native") {165    llvm::StringMap<bool> HostFeatures = llvm::sys::getHostCPUFeatures();166    for (auto &[Feature, Enabled] : HostFeatures) {167      Features.push_back(Args.MakeArgString((Enabled ? "+" : "-") + Feature));168    }169  }170 171  return true;172}173 174static bool175getAArch64MicroArchFeaturesFromMtune(const Driver &D, StringRef Mtune,176                                     const ArgList &Args,177                                     std::vector<StringRef> &Features) {178  // Check CPU name is valid, but ignore any extensions on it.179  std::string MtuneLowerCase = Mtune.lower();180  llvm::AArch64::ExtensionSet Extensions;181  StringRef Tune;182  return DecodeAArch64Mcpu(D, MtuneLowerCase, Tune, Extensions);183}184 185static bool186getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,187                                    const ArgList &Args,188                                    std::vector<StringRef> &Features) {189  return getAArch64MicroArchFeaturesFromMtune(D, Mcpu, Args, Features);190}191 192void aarch64::getAArch64TargetFeatures(const Driver &D,193                                       const llvm::Triple &Triple,194                                       const ArgList &Args,195                                       std::vector<StringRef> &Features,196                                       bool ForAS, bool ForMultilib) {197  Arg *A;198  bool success = true;199  llvm::StringRef WaMArch;200  llvm::AArch64::ExtensionSet Extensions;201  if (ForAS)202    for (const auto *A :203         Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler))204      for (StringRef Value : A->getValues())205        if (Value.starts_with("-march="))206          WaMArch = Value.substr(7);207  // Call getAArch64ArchFeaturesFromMarch only if "-Wa,-march=" or208  // "-Xassembler -march" is detected. Otherwise it may return false209  // and causes Clang to error out.210  if (!WaMArch.empty())211    success = getAArch64ArchFeaturesFromMarch(D, WaMArch, Args, Extensions);212  else if ((A = Args.getLastArg(options::OPT_march_EQ)))213    success =214        getAArch64ArchFeaturesFromMarch(D, A->getValue(), Args, Extensions);215  else if ((A = Args.getLastArg(options::OPT_mcpu_EQ)))216    success = getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Extensions,217                                             Features);218  else if (isCPUDeterminedByTriple(Triple))219    success = getAArch64ArchFeaturesFromMcpu(220        D, getAArch64TargetCPU(Args, Triple, A), Args, Extensions, Features);221  else222    // Default to 'A' profile if the architecture is not specified.223    success = getAArch64ArchFeaturesFromMarch(D, "armv8-a", Args, Extensions);224 225  if (success && (A = Args.getLastArg(options::OPT_mtune_EQ)))226    success =227        getAArch64MicroArchFeaturesFromMtune(D, A->getValue(), Args, Features);228  else if (success && (A = Args.getLastArg(options::OPT_mcpu_EQ)))229    success =230        getAArch64MicroArchFeaturesFromMcpu(D, A->getValue(), Args, Features);231  else if (success && isCPUDeterminedByTriple(Triple))232    success = getAArch64MicroArchFeaturesFromMcpu(233        D, getAArch64TargetCPU(Args, Triple, A), Args, Features);234 235  if (!success) {236    auto Diag = D.Diag(diag::err_drv_unsupported_option_argument);237    // If "-Wa,-march=" is used, 'WaMArch' will contain the argument's value,238    // while 'A' is uninitialized. Only dereference 'A' in the other case.239    if (!WaMArch.empty())240      Diag << "-march=" << WaMArch;241    else242      Diag << A->getSpelling() << A->getValue();243  }244 245  // -mgeneral-regs-only disables all floating-point features.246  if (Args.getLastArg(options::OPT_mgeneral_regs_only)) {247    Extensions.disable(llvm::AArch64::AEK_FP);248  }249 250  // En/disable crc251  if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) {252    if (A->getOption().matches(options::OPT_mcrc))253      Extensions.enable(llvm::AArch64::AEK_CRC);254    else255      Extensions.disable(llvm::AArch64::AEK_CRC);256  }257 258  // At this point all hardware features are decided, so convert the extensions259  // set to a feature list.260  Extensions.toLLVMFeatureList(Features);261 262  if (Arg *A = Args.getLastArg(options::OPT_mtp_mode_EQ)) {263    StringRef Mtp = A->getValue();264    if (Mtp == "el3" || Mtp == "tpidr_el3")265      Features.push_back("+tpidr-el3");266    else if (Mtp == "el2" || Mtp == "tpidr_el2")267      Features.push_back("+tpidr-el2");268    else if (Mtp == "el1" || Mtp == "tpidr_el1")269      Features.push_back("+tpidr-el1");270    else if (Mtp == "tpidrro_el0")271      Features.push_back("+tpidrro-el0");272    else if (Mtp != "el0" && Mtp != "tpidr_el0")273      D.Diag(diag::err_drv_invalid_mtp) << A->getAsString(Args);274  }275 276  // Enable/disable straight line speculation hardening.277  if (Arg *A = Args.getLastArg(options::OPT_mharden_sls_EQ)) {278    StringRef Scope = A->getValue();279    bool EnableRetBr = false;280    bool EnableBlr = false;281    bool DisableComdat = false;282    if (Scope != "none") {283      SmallVector<StringRef, 4> Opts;284      Scope.split(Opts, ",");285      for (auto Opt : Opts) {286        Opt = Opt.trim();287        if (Opt == "all") {288          EnableBlr = true;289          EnableRetBr = true;290          continue;291        }292        if (Opt == "retbr") {293          EnableRetBr = true;294          continue;295        }296        if (Opt == "blr") {297          EnableBlr = true;298          continue;299        }300        if (Opt == "comdat") {301          DisableComdat = false;302          continue;303        }304        if (Opt == "nocomdat") {305          DisableComdat = true;306          continue;307        }308        D.Diag(diag::err_drv_unsupported_option_argument)309            << A->getSpelling() << Scope;310        break;311      }312    }313 314    if (EnableRetBr)315      Features.push_back("+harden-sls-retbr");316    if (EnableBlr)317      Features.push_back("+harden-sls-blr");318    if (DisableComdat) {319      Features.push_back("+harden-sls-nocomdat");320    }321  }322 323  if (Arg *A = Args.getLastArg(324          options::OPT_mstrict_align, options::OPT_mno_strict_align,325          options::OPT_mno_unaligned_access, options::OPT_munaligned_access)) {326    if (A->getOption().matches(options::OPT_mstrict_align) ||327        A->getOption().matches(options::OPT_mno_unaligned_access))328      Features.push_back("+strict-align");329  } else if (Triple.isOSOpenBSD())330    Features.push_back("+strict-align");331 332  // Generate execute-only output (no data access to code sections).333  // This only makes sense for the compiler, not for the assembler.334  // It's not needed for multilib selection and may hide an unused335  // argument diagnostic if the code is always run.336  if (!ForAS && !ForMultilib) {337    if (Arg *A = Args.getLastArg(options::OPT_mexecute_only,338                                 options::OPT_mno_execute_only)) {339      if (A->getOption().matches(options::OPT_mexecute_only)) {340        Features.push_back("+execute-only");341      }342    }343  }344 345  if (Args.hasArg(options::OPT_ffixed_x1))346    Features.push_back("+reserve-x1");347 348  if (Args.hasArg(options::OPT_ffixed_x2))349    Features.push_back("+reserve-x2");350 351  if (Args.hasArg(options::OPT_ffixed_x3))352    Features.push_back("+reserve-x3");353 354  if (Args.hasArg(options::OPT_ffixed_x4))355    Features.push_back("+reserve-x4");356 357  if (Args.hasArg(options::OPT_ffixed_x5))358    Features.push_back("+reserve-x5");359 360  if (Args.hasArg(options::OPT_ffixed_x6))361    Features.push_back("+reserve-x6");362 363  if (Args.hasArg(options::OPT_ffixed_x7))364    Features.push_back("+reserve-x7");365 366  if (Args.hasArg(options::OPT_ffixed_x9))367    Features.push_back("+reserve-x9");368 369  if (Args.hasArg(options::OPT_ffixed_x10))370    Features.push_back("+reserve-x10");371 372  if (Args.hasArg(options::OPT_ffixed_x11))373    Features.push_back("+reserve-x11");374 375  if (Args.hasArg(options::OPT_ffixed_x12))376    Features.push_back("+reserve-x12");377 378  if (Args.hasArg(options::OPT_ffixed_x13))379    Features.push_back("+reserve-x13");380 381  if (Args.hasArg(options::OPT_ffixed_x14))382    Features.push_back("+reserve-x14");383 384  if (Args.hasArg(options::OPT_ffixed_x15))385    Features.push_back("+reserve-x15");386 387  if (Args.hasArg(options::OPT_ffixed_x18))388    Features.push_back("+reserve-x18");389 390  if (Args.hasArg(options::OPT_ffixed_x20))391    Features.push_back("+reserve-x20");392 393  if (Args.hasArg(options::OPT_ffixed_x21))394    Features.push_back("+reserve-x21");395 396  if (Args.hasArg(options::OPT_ffixed_x22))397    Features.push_back("+reserve-x22");398 399  if (Args.hasArg(options::OPT_ffixed_x23))400    Features.push_back("+reserve-x23");401 402  if (Args.hasArg(options::OPT_ffixed_x24))403    Features.push_back("+reserve-x24");404 405  if (Args.hasArg(options::OPT_ffixed_x25))406    Features.push_back("+reserve-x25");407 408  if (Args.hasArg(options::OPT_ffixed_x26))409    Features.push_back("+reserve-x26");410 411  if (Args.hasArg(options::OPT_ffixed_x27))412    Features.push_back("+reserve-x27");413 414  if (Args.hasArg(options::OPT_ffixed_x28))415    Features.push_back("+reserve-x28");416 417  if (Args.hasArg(options::OPT_mlr_for_calls_only))418    Features.push_back("+reserve-lr-for-ra");419 420  if (Args.hasArg(options::OPT_fcall_saved_x8))421    Features.push_back("+call-saved-x8");422 423  if (Args.hasArg(options::OPT_fcall_saved_x9))424    Features.push_back("+call-saved-x9");425 426  if (Args.hasArg(options::OPT_fcall_saved_x10))427    Features.push_back("+call-saved-x10");428 429  if (Args.hasArg(options::OPT_fcall_saved_x11))430    Features.push_back("+call-saved-x11");431 432  if (Args.hasArg(options::OPT_fcall_saved_x12))433    Features.push_back("+call-saved-x12");434 435  if (Args.hasArg(options::OPT_fcall_saved_x13))436    Features.push_back("+call-saved-x13");437 438  if (Args.hasArg(options::OPT_fcall_saved_x14))439    Features.push_back("+call-saved-x14");440 441  if (Args.hasArg(options::OPT_fcall_saved_x15))442    Features.push_back("+call-saved-x15");443 444  if (Args.hasArg(options::OPT_fcall_saved_x18))445    Features.push_back("+call-saved-x18");446 447  if (Args.hasArg(options::OPT_mno_neg_immediates))448    Features.push_back("+no-neg-immediates");449 450  if (Arg *A = Args.getLastArg(options::OPT_mfix_cortex_a53_835769,451                               options::OPT_mno_fix_cortex_a53_835769)) {452    if (A->getOption().matches(options::OPT_mfix_cortex_a53_835769))453      Features.push_back("+fix-cortex-a53-835769");454    else455      Features.push_back("-fix-cortex-a53-835769");456  } else if (Triple.isAndroid() || Triple.isOHOSFamily()) {457    // Enabled A53 errata (835769) workaround by default on android458    Features.push_back("+fix-cortex-a53-835769");459  } else if (Triple.isOSFuchsia()) {460    std::string CPU = getCPUName(D, Args, Triple);461    if (CPU.empty() || CPU == "generic" || CPU == "cortex-a53")462      Features.push_back("+fix-cortex-a53-835769");463  }464 465  if (Args.getLastArg(options::OPT_mno_bti_at_return_twice))466    Features.push_back("+no-bti-at-return-twice");467}468 469/// Is the triple {aarch64.aarch64_be}-none-elf?470bool aarch64::isAArch64BareMetal(const llvm::Triple &Triple) {471  if (Triple.getArch() != llvm::Triple::aarch64 &&472      Triple.getArch() != llvm::Triple::aarch64_be)473    return false;474 475  if (Triple.getVendor() != llvm::Triple::UnknownVendor)476    return false;477 478  if (Triple.getOS() != llvm::Triple::UnknownOS)479    return false;480 481  return Triple.getEnvironmentName() == "elf";482}483