Path: blob/main/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
35294 views
//===--- AArch64.cpp - AArch64 (not ARM) Helpers for Tools ------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "AArch64.h"9#include "../CommonArgs.h"10#include "clang/Driver/Driver.h"11#include "clang/Driver/DriverDiagnostic.h"12#include "clang/Driver/Options.h"13#include "llvm/Option/ArgList.h"14#include "llvm/TargetParser/AArch64TargetParser.h"15#include "llvm/TargetParser/Host.h"1617using namespace clang::driver;18using namespace clang::driver::tools;19using namespace clang;20using namespace llvm::opt;2122/// \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) {25return Triple.isOSDarwin();26}2728/// 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,32const llvm::Triple &Triple, Arg *&A) {33std::string CPU;34// If we have -mcpu, use that.35if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) {36StringRef Mcpu = A->getValue();37CPU = Mcpu.split("+").first.lower();38}3940CPU = llvm::AArch64::resolveCPUAlias(CPU);4142// Handle CPU name is 'native'.43if (CPU == "native")44return std::string(llvm::sys::getHostCPUName());4546if (CPU.size())47return CPU;4849if (Triple.isTargetMachineMac() &&50Triple.getArch() == llvm::Triple::aarch64) {51// Apple Silicon macs default to M1 CPUs.52return "apple-m1";53}5455if (Triple.isXROS()) {56// The xrOS simulator runs on M1 as well, it should have been covered above.57assert(!Triple.isSimulatorEnvironment() && "xrossim should be mac-like");58return "apple-a12";59}60// arm64e requires v8.3a and only runs on apple-a12 and later CPUs.61if (Triple.isArm64e())62return "apple-a12";6364// Make sure we pick the appropriate Apple CPU when targetting a Darwin OS.65if (Triple.isOSDarwin())66return Triple.getArch() == llvm::Triple::aarch64_32 ? "apple-s4"67: "apple-a7";6869return "generic";70}7172// Decode AArch64 features from string like +[no]featureA+[no]featureB+...73static bool DecodeAArch64Features(const Driver &D, StringRef text,74llvm::AArch64::ExtensionSet &Extensions) {75SmallVector<StringRef, 8> Split;76text.split(Split, StringRef("+"), -1, false);7778for (StringRef Feature : Split) {79if (Feature == "neon" || Feature == "noneon") {80D.Diag(clang::diag::err_drv_no_neon_modifier);81continue;82}83if (!Extensions.parseModifier(Feature))84return false;85}8687return true;88}8990// Check if the CPU name and feature modifiers in -mcpu are legal. If yes,91// decode CPU and feature.92static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU,93llvm::AArch64::ExtensionSet &Extensions) {94std::pair<StringRef, StringRef> Split = Mcpu.split("+");95CPU = Split.first;9697if (CPU == "native")98CPU = llvm::sys::getHostCPUName();99100const std::optional<llvm::AArch64::CpuInfo> CpuInfo =101llvm::AArch64::parseCpu(CPU);102if (!CpuInfo)103return false;104105Extensions.addCPUDefaults(*CpuInfo);106107if (Split.second.size() &&108!DecodeAArch64Features(D, Split.second, Extensions))109return false;110111return true;112}113114static bool115getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March,116const ArgList &Args,117llvm::AArch64::ExtensionSet &Extensions) {118std::string MarchLowerCase = March.lower();119std::pair<StringRef, StringRef> Split = StringRef(MarchLowerCase).split("+");120121const llvm::AArch64::ArchInfo *ArchInfo =122llvm::AArch64::parseArch(Split.first);123if (Split.first == "native")124ArchInfo = llvm::AArch64::getArchForCpu(llvm::sys::getHostCPUName().str());125if (!ArchInfo)126return false;127128Extensions.addArchDefaults(*ArchInfo);129130if ((Split.second.size() &&131!DecodeAArch64Features(D, Split.second, Extensions)))132return false;133134return true;135}136137static bool138getAArch64ArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,139const ArgList &Args,140llvm::AArch64::ExtensionSet &Extensions) {141StringRef CPU;142std::string McpuLowerCase = Mcpu.lower();143if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, Extensions))144return false;145146return true;147}148149static bool150getAArch64MicroArchFeaturesFromMtune(const Driver &D, StringRef Mtune,151const ArgList &Args,152std::vector<StringRef> &Features) {153std::string MtuneLowerCase = Mtune.lower();154// Check CPU name is valid, but ignore any extensions on it.155llvm::AArch64::ExtensionSet Extensions;156StringRef Tune;157if (!DecodeAArch64Mcpu(D, MtuneLowerCase, Tune, Extensions))158return false;159160// Handle CPU name is 'native'.161if (MtuneLowerCase == "native")162MtuneLowerCase = std::string(llvm::sys::getHostCPUName());163164// 'cyclone' and later have zero-cycle register moves and zeroing.165if (MtuneLowerCase == "cyclone" ||166StringRef(MtuneLowerCase).starts_with("apple")) {167Features.push_back("+zcm");168Features.push_back("+zcz");169}170171return true;172}173174static bool175getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,176const ArgList &Args,177std::vector<StringRef> &Features) {178StringRef CPU;179// Check CPU name is valid, but ignore any extensions on it.180llvm::AArch64::ExtensionSet DecodedFeature;181std::string McpuLowerCase = Mcpu.lower();182if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, DecodedFeature))183return false;184185return getAArch64MicroArchFeaturesFromMtune(D, CPU, Args, Features);186}187188void aarch64::getAArch64TargetFeatures(const Driver &D,189const llvm::Triple &Triple,190const ArgList &Args,191std::vector<StringRef> &Features,192bool ForAS) {193Arg *A;194bool success = true;195llvm::StringRef WaMArch;196llvm::AArch64::ExtensionSet Extensions;197if (ForAS)198for (const auto *A :199Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler))200for (StringRef Value : A->getValues())201if (Value.starts_with("-march="))202WaMArch = Value.substr(7);203// Call getAArch64ArchFeaturesFromMarch only if "-Wa,-march=" or204// "-Xassembler -march" is detected. Otherwise it may return false205// and causes Clang to error out.206if (!WaMArch.empty())207success = getAArch64ArchFeaturesFromMarch(D, WaMArch, Args, Extensions);208else if ((A = Args.getLastArg(options::OPT_march_EQ)))209success =210getAArch64ArchFeaturesFromMarch(D, A->getValue(), Args, Extensions);211else if ((A = Args.getLastArg(options::OPT_mcpu_EQ)))212success =213getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Extensions);214else if (isCPUDeterminedByTriple(Triple))215success = getAArch64ArchFeaturesFromMcpu(216D, getAArch64TargetCPU(Args, Triple, A), Args, Extensions);217else218// Default to 'A' profile if the architecture is not specified.219success = getAArch64ArchFeaturesFromMarch(D, "armv8-a", Args, Extensions);220221if (success && (A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)))222success =223getAArch64MicroArchFeaturesFromMtune(D, A->getValue(), Args, Features);224else if (success && (A = Args.getLastArg(options::OPT_mcpu_EQ)))225success =226getAArch64MicroArchFeaturesFromMcpu(D, A->getValue(), Args, Features);227else if (success && isCPUDeterminedByTriple(Triple))228success = getAArch64MicroArchFeaturesFromMcpu(229D, getAArch64TargetCPU(Args, Triple, A), Args, Features);230231if (!success) {232auto Diag = D.Diag(diag::err_drv_unsupported_option_argument);233// If "-Wa,-march=" is used, 'WaMArch' will contain the argument's value,234// while 'A' is uninitialized. Only dereference 'A' in the other case.235if (!WaMArch.empty())236Diag << "-march=" << WaMArch;237else238Diag << A->getSpelling() << A->getValue();239}240241// -mgeneral-regs-only disables all floating-point features.242if (Args.getLastArg(options::OPT_mgeneral_regs_only)) {243Extensions.disable(llvm::AArch64::AEK_FP);244}245246// En/disable crc247if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) {248if (A->getOption().matches(options::OPT_mcrc))249Extensions.enable(llvm::AArch64::AEK_CRC);250else251Extensions.disable(llvm::AArch64::AEK_CRC);252}253254// At this point all hardware features are decided, so convert the extensions255// set to a feature list.256Extensions.toLLVMFeatureList(Features);257258if (Arg *A = Args.getLastArg(options::OPT_mtp_mode_EQ)) {259StringRef Mtp = A->getValue();260if (Mtp == "el3" || Mtp == "tpidr_el3")261Features.push_back("+tpidr-el3");262else if (Mtp == "el2" || Mtp == "tpidr_el2")263Features.push_back("+tpidr-el2");264else if (Mtp == "el1" || Mtp == "tpidr_el1")265Features.push_back("+tpidr-el1");266else if (Mtp == "tpidrro_el0")267Features.push_back("+tpidrro-el0");268else if (Mtp != "el0" && Mtp != "tpidr_el0")269D.Diag(diag::err_drv_invalid_mtp) << A->getAsString(Args);270}271272// Enable/disable straight line speculation hardening.273if (Arg *A = Args.getLastArg(options::OPT_mharden_sls_EQ)) {274StringRef Scope = A->getValue();275bool EnableRetBr = false;276bool EnableBlr = false;277bool DisableComdat = false;278if (Scope != "none") {279SmallVector<StringRef, 4> Opts;280Scope.split(Opts, ",");281for (auto Opt : Opts) {282Opt = Opt.trim();283if (Opt == "all") {284EnableBlr = true;285EnableRetBr = true;286continue;287}288if (Opt == "retbr") {289EnableRetBr = true;290continue;291}292if (Opt == "blr") {293EnableBlr = true;294continue;295}296if (Opt == "comdat") {297DisableComdat = false;298continue;299}300if (Opt == "nocomdat") {301DisableComdat = true;302continue;303}304D.Diag(diag::err_drv_unsupported_option_argument)305<< A->getSpelling() << Scope;306break;307}308}309310if (EnableRetBr)311Features.push_back("+harden-sls-retbr");312if (EnableBlr)313Features.push_back("+harden-sls-blr");314if (DisableComdat) {315Features.push_back("+harden-sls-nocomdat");316}317}318319if (Arg *A = Args.getLastArg(320options::OPT_mstrict_align, options::OPT_mno_strict_align,321options::OPT_mno_unaligned_access, options::OPT_munaligned_access)) {322if (A->getOption().matches(options::OPT_mstrict_align) ||323A->getOption().matches(options::OPT_mno_unaligned_access))324Features.push_back("+strict-align");325} else if (Triple.isOSOpenBSD())326Features.push_back("+strict-align");327328if (Args.hasArg(options::OPT_ffixed_x1))329Features.push_back("+reserve-x1");330331if (Args.hasArg(options::OPT_ffixed_x2))332Features.push_back("+reserve-x2");333334if (Args.hasArg(options::OPT_ffixed_x3))335Features.push_back("+reserve-x3");336337if (Args.hasArg(options::OPT_ffixed_x4))338Features.push_back("+reserve-x4");339340if (Args.hasArg(options::OPT_ffixed_x5))341Features.push_back("+reserve-x5");342343if (Args.hasArg(options::OPT_ffixed_x6))344Features.push_back("+reserve-x6");345346if (Args.hasArg(options::OPT_ffixed_x7))347Features.push_back("+reserve-x7");348349if (Args.hasArg(options::OPT_ffixed_x9))350Features.push_back("+reserve-x9");351352if (Args.hasArg(options::OPT_ffixed_x10))353Features.push_back("+reserve-x10");354355if (Args.hasArg(options::OPT_ffixed_x11))356Features.push_back("+reserve-x11");357358if (Args.hasArg(options::OPT_ffixed_x12))359Features.push_back("+reserve-x12");360361if (Args.hasArg(options::OPT_ffixed_x13))362Features.push_back("+reserve-x13");363364if (Args.hasArg(options::OPT_ffixed_x14))365Features.push_back("+reserve-x14");366367if (Args.hasArg(options::OPT_ffixed_x15))368Features.push_back("+reserve-x15");369370if (Args.hasArg(options::OPT_ffixed_x18))371Features.push_back("+reserve-x18");372373if (Args.hasArg(options::OPT_ffixed_x20))374Features.push_back("+reserve-x20");375376if (Args.hasArg(options::OPT_ffixed_x21))377Features.push_back("+reserve-x21");378379if (Args.hasArg(options::OPT_ffixed_x22))380Features.push_back("+reserve-x22");381382if (Args.hasArg(options::OPT_ffixed_x23))383Features.push_back("+reserve-x23");384385if (Args.hasArg(options::OPT_ffixed_x24))386Features.push_back("+reserve-x24");387388if (Args.hasArg(options::OPT_ffixed_x25))389Features.push_back("+reserve-x25");390391if (Args.hasArg(options::OPT_ffixed_x26))392Features.push_back("+reserve-x26");393394if (Args.hasArg(options::OPT_ffixed_x27))395Features.push_back("+reserve-x27");396397if (Args.hasArg(options::OPT_ffixed_x28))398Features.push_back("+reserve-x28");399400if (Args.hasArg(options::OPT_mlr_for_calls_only))401Features.push_back("+reserve-lr-for-ra");402403if (Args.hasArg(options::OPT_fcall_saved_x8))404Features.push_back("+call-saved-x8");405406if (Args.hasArg(options::OPT_fcall_saved_x9))407Features.push_back("+call-saved-x9");408409if (Args.hasArg(options::OPT_fcall_saved_x10))410Features.push_back("+call-saved-x10");411412if (Args.hasArg(options::OPT_fcall_saved_x11))413Features.push_back("+call-saved-x11");414415if (Args.hasArg(options::OPT_fcall_saved_x12))416Features.push_back("+call-saved-x12");417418if (Args.hasArg(options::OPT_fcall_saved_x13))419Features.push_back("+call-saved-x13");420421if (Args.hasArg(options::OPT_fcall_saved_x14))422Features.push_back("+call-saved-x14");423424if (Args.hasArg(options::OPT_fcall_saved_x15))425Features.push_back("+call-saved-x15");426427if (Args.hasArg(options::OPT_fcall_saved_x18))428Features.push_back("+call-saved-x18");429430if (Args.hasArg(options::OPT_mno_neg_immediates))431Features.push_back("+no-neg-immediates");432433if (Arg *A = Args.getLastArg(options::OPT_mfix_cortex_a53_835769,434options::OPT_mno_fix_cortex_a53_835769)) {435if (A->getOption().matches(options::OPT_mfix_cortex_a53_835769))436Features.push_back("+fix-cortex-a53-835769");437else438Features.push_back("-fix-cortex-a53-835769");439} else if (Triple.isAndroid() || Triple.isOHOSFamily()) {440// Enabled A53 errata (835769) workaround by default on android441Features.push_back("+fix-cortex-a53-835769");442} else if (Triple.isOSFuchsia()) {443std::string CPU = getCPUName(D, Args, Triple);444if (CPU.empty() || CPU == "generic" || CPU == "cortex-a53")445Features.push_back("+fix-cortex-a53-835769");446}447448if (Args.getLastArg(options::OPT_mno_bti_at_return_twice))449Features.push_back("+no-bti-at-return-twice");450}451452void aarch64::setPAuthABIInTriple(const Driver &D, const ArgList &Args,453llvm::Triple &Triple) {454Arg *ABIArg = Args.getLastArg(options::OPT_mabi_EQ);455bool HasPAuthABI =456ABIArg ? (StringRef(ABIArg->getValue()) == "pauthtest") : false;457458switch (Triple.getEnvironment()) {459case llvm::Triple::UnknownEnvironment:460if (HasPAuthABI)461Triple.setEnvironment(llvm::Triple::PAuthTest);462break;463case llvm::Triple::PAuthTest:464break;465default:466if (HasPAuthABI)467D.Diag(diag::err_drv_unsupported_opt_for_target)468<< ABIArg->getAsString(Args) << Triple.getTriple();469break;470}471}472473474