10b57cec5SDimitry Andric //===--- AArch64.cpp - AArch64 (not ARM) Helpers for Tools ------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "AArch64.h"
10bdd1243dSDimitry Andric #include "../CommonArgs.h"
110b57cec5SDimitry Andric #include "clang/Driver/Driver.h"
120b57cec5SDimitry Andric #include "clang/Driver/DriverDiagnostic.h"
130b57cec5SDimitry Andric #include "clang/Driver/Options.h"
140b57cec5SDimitry Andric #include "llvm/Option/ArgList.h"
1506c3fb27SDimitry Andric #include "llvm/TargetParser/AArch64TargetParser.h"
1606c3fb27SDimitry Andric #include "llvm/TargetParser/Host.h"
170b57cec5SDimitry Andric
180b57cec5SDimitry Andric using namespace clang::driver;
190b57cec5SDimitry Andric using namespace clang::driver::tools;
200b57cec5SDimitry Andric using namespace clang;
210b57cec5SDimitry Andric using namespace llvm::opt;
220b57cec5SDimitry Andric
230b57cec5SDimitry Andric /// \returns true if the given triple can determine the default CPU type even
240b57cec5SDimitry Andric /// if -arch is not specified.
isCPUDeterminedByTriple(const llvm::Triple & Triple)250b57cec5SDimitry Andric static bool isCPUDeterminedByTriple(const llvm::Triple &Triple) {
260b57cec5SDimitry Andric return Triple.isOSDarwin();
270b57cec5SDimitry Andric }
280b57cec5SDimitry Andric
290b57cec5SDimitry Andric /// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are
300b57cec5SDimitry Andric /// targeting. Set \p A to the Arg corresponding to the -mcpu argument if it is
310b57cec5SDimitry Andric /// provided, or to nullptr otherwise.
getAArch64TargetCPU(const ArgList & Args,const llvm::Triple & Triple,Arg * & A)320b57cec5SDimitry Andric std::string aarch64::getAArch64TargetCPU(const ArgList &Args,
330b57cec5SDimitry Andric const llvm::Triple &Triple, Arg *&A) {
340b57cec5SDimitry Andric std::string CPU;
350b57cec5SDimitry Andric // If we have -mcpu, use that.
360b57cec5SDimitry Andric if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) {
370b57cec5SDimitry Andric StringRef Mcpu = A->getValue();
380b57cec5SDimitry Andric CPU = Mcpu.split("+").first.lower();
390b57cec5SDimitry Andric }
400b57cec5SDimitry Andric
41bdd1243dSDimitry Andric CPU = llvm::AArch64::resolveCPUAlias(CPU);
42bdd1243dSDimitry Andric
430b57cec5SDimitry Andric // Handle CPU name is 'native'.
440b57cec5SDimitry Andric if (CPU == "native")
455ffd83dbSDimitry Andric return std::string(llvm::sys::getHostCPUName());
46e8d8bef9SDimitry Andric
47e8d8bef9SDimitry Andric if (CPU.size())
480b57cec5SDimitry Andric return CPU;
490b57cec5SDimitry Andric
50e8d8bef9SDimitry Andric if (Triple.isTargetMachineMac() &&
51e8d8bef9SDimitry Andric Triple.getArch() == llvm::Triple::aarch64) {
52fe6060f1SDimitry Andric // Apple Silicon macs default to M1 CPUs.
53fe6060f1SDimitry Andric return "apple-m1";
54e8d8bef9SDimitry Andric }
55e8d8bef9SDimitry Andric
567a6dacacSDimitry Andric if (Triple.isXROS()) {
577a6dacacSDimitry Andric // The xrOS simulator runs on M1 as well, it should have been covered above.
587a6dacacSDimitry Andric assert(!Triple.isSimulatorEnvironment() && "xrossim should be mac-like");
597a6dacacSDimitry Andric return "apple-a12";
607a6dacacSDimitry Andric }
61fe6060f1SDimitry Andric // arm64e requires v8.3a and only runs on apple-a12 and later CPUs.
62fe6060f1SDimitry Andric if (Triple.isArm64e())
63fe6060f1SDimitry Andric return "apple-a12";
64fe6060f1SDimitry Andric
655f757f3fSDimitry Andric // Make sure we pick the appropriate Apple CPU when targetting a Darwin OS.
665f757f3fSDimitry Andric if (Triple.isOSDarwin())
67480093f4SDimitry Andric return Triple.getArch() == llvm::Triple::aarch64_32 ? "apple-s4"
68480093f4SDimitry Andric : "apple-a7";
690b57cec5SDimitry Andric
700b57cec5SDimitry Andric return "generic";
710b57cec5SDimitry Andric }
720b57cec5SDimitry Andric
730b57cec5SDimitry Andric // Decode AArch64 features from string like +[no]featureA+[no]featureB+...
DecodeAArch64Features(const Driver & D,StringRef text,llvm::AArch64::ExtensionSet & Extensions)740b57cec5SDimitry Andric static bool DecodeAArch64Features(const Driver &D, StringRef text,
757a6dacacSDimitry Andric llvm::AArch64::ExtensionSet &Extensions) {
760b57cec5SDimitry Andric SmallVector<StringRef, 8> Split;
770b57cec5SDimitry Andric text.split(Split, StringRef("+"), -1, false);
780b57cec5SDimitry Andric
790b57cec5SDimitry Andric for (StringRef Feature : Split) {
807a6dacacSDimitry Andric if (Feature == "neon" || Feature == "noneon") {
810b57cec5SDimitry Andric D.Diag(clang::diag::err_drv_no_neon_modifier);
827a6dacacSDimitry Andric continue;
837a6dacacSDimitry Andric }
847a6dacacSDimitry Andric if (!Extensions.parseModifier(Feature))
850b57cec5SDimitry Andric return false;
8606c3fb27SDimitry Andric }
8706c3fb27SDimitry Andric
880b57cec5SDimitry Andric return true;
890b57cec5SDimitry Andric }
900b57cec5SDimitry Andric
910b57cec5SDimitry Andric // Check if the CPU name and feature modifiers in -mcpu are legal. If yes,
920b57cec5SDimitry Andric // decode CPU and feature.
DecodeAArch64Mcpu(const Driver & D,StringRef Mcpu,StringRef & CPU,llvm::AArch64::ExtensionSet & Extensions)930b57cec5SDimitry Andric static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU,
947a6dacacSDimitry Andric llvm::AArch64::ExtensionSet &Extensions) {
950b57cec5SDimitry Andric std::pair<StringRef, StringRef> Split = Mcpu.split("+");
9606c3fb27SDimitry Andric CPU = Split.first;
970b57cec5SDimitry Andric
980b57cec5SDimitry Andric if (CPU == "native")
990b57cec5SDimitry Andric CPU = llvm::sys::getHostCPUName();
1000b57cec5SDimitry Andric
10106c3fb27SDimitry Andric const std::optional<llvm::AArch64::CpuInfo> CpuInfo =
10206c3fb27SDimitry Andric llvm::AArch64::parseCpu(CPU);
10306c3fb27SDimitry Andric if (!CpuInfo)
1040b57cec5SDimitry Andric return false;
10506c3fb27SDimitry Andric
1067a6dacacSDimitry Andric Extensions.addCPUDefaults(*CpuInfo);
1070b57cec5SDimitry Andric
1085ffd83dbSDimitry Andric if (Split.second.size() &&
1097a6dacacSDimitry Andric !DecodeAArch64Features(D, Split.second, Extensions))
1100b57cec5SDimitry Andric return false;
1110b57cec5SDimitry Andric
1120b57cec5SDimitry Andric return true;
1130b57cec5SDimitry Andric }
1140b57cec5SDimitry Andric
1150b57cec5SDimitry Andric static bool
getAArch64ArchFeaturesFromMarch(const Driver & D,StringRef March,const ArgList & Args,llvm::AArch64::ExtensionSet & Extensions)1160b57cec5SDimitry Andric getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March,
1170b57cec5SDimitry Andric const ArgList &Args,
1187a6dacacSDimitry Andric llvm::AArch64::ExtensionSet &Extensions) {
1190b57cec5SDimitry Andric std::string MarchLowerCase = March.lower();
1200b57cec5SDimitry Andric std::pair<StringRef, StringRef> Split = StringRef(MarchLowerCase).split("+");
1210b57cec5SDimitry Andric
1227a6dacacSDimitry Andric const llvm::AArch64::ArchInfo *ArchInfo =
12306c3fb27SDimitry Andric llvm::AArch64::parseArch(Split.first);
12481ad6265SDimitry Andric if (Split.first == "native")
12506c3fb27SDimitry Andric ArchInfo = llvm::AArch64::getArchForCpu(llvm::sys::getHostCPUName().str());
12606c3fb27SDimitry Andric if (!ArchInfo)
127349cc55cSDimitry Andric return false;
128349cc55cSDimitry Andric
1297a6dacacSDimitry Andric Extensions.addArchDefaults(*ArchInfo);
130349cc55cSDimitry Andric
131349cc55cSDimitry Andric if ((Split.second.size() &&
1327a6dacacSDimitry Andric !DecodeAArch64Features(D, Split.second, Extensions)))
1330b57cec5SDimitry Andric return false;
1340b57cec5SDimitry Andric
1350b57cec5SDimitry Andric return true;
1360b57cec5SDimitry Andric }
1370b57cec5SDimitry Andric
1380b57cec5SDimitry Andric static bool
getAArch64ArchFeaturesFromMcpu(const Driver & D,StringRef Mcpu,const ArgList & Args,llvm::AArch64::ExtensionSet & Extensions)1390b57cec5SDimitry Andric getAArch64ArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
1400b57cec5SDimitry Andric const ArgList &Args,
1417a6dacacSDimitry Andric llvm::AArch64::ExtensionSet &Extensions) {
1420b57cec5SDimitry Andric StringRef CPU;
1430b57cec5SDimitry Andric std::string McpuLowerCase = Mcpu.lower();
1447a6dacacSDimitry Andric if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, Extensions))
1450b57cec5SDimitry Andric return false;
1460b57cec5SDimitry Andric
1470b57cec5SDimitry Andric return true;
1480b57cec5SDimitry Andric }
1490b57cec5SDimitry Andric
1500b57cec5SDimitry Andric static bool
getAArch64MicroArchFeaturesFromMtune(const Driver & D,StringRef Mtune,const ArgList & Args,std::vector<StringRef> & Features)1510b57cec5SDimitry Andric getAArch64MicroArchFeaturesFromMtune(const Driver &D, StringRef Mtune,
1520b57cec5SDimitry Andric const ArgList &Args,
1530b57cec5SDimitry Andric std::vector<StringRef> &Features) {
1540b57cec5SDimitry Andric std::string MtuneLowerCase = Mtune.lower();
1557a6dacacSDimitry Andric // Check CPU name is valid, but ignore any extensions on it.
1567a6dacacSDimitry Andric llvm::AArch64::ExtensionSet Extensions;
1570b57cec5SDimitry Andric StringRef Tune;
1587a6dacacSDimitry Andric if (!DecodeAArch64Mcpu(D, MtuneLowerCase, Tune, Extensions))
1590b57cec5SDimitry Andric return false;
1600b57cec5SDimitry Andric
1610b57cec5SDimitry Andric // Handle CPU name is 'native'.
1620b57cec5SDimitry Andric if (MtuneLowerCase == "native")
1635ffd83dbSDimitry Andric MtuneLowerCase = std::string(llvm::sys::getHostCPUName());
164*0fca6ea1SDimitry Andric
165*0fca6ea1SDimitry Andric // 'cyclone' and later have zero-cycle register moves and zeroing.
1665ffd83dbSDimitry Andric if (MtuneLowerCase == "cyclone" ||
1675f757f3fSDimitry Andric StringRef(MtuneLowerCase).starts_with("apple")) {
1680b57cec5SDimitry Andric Features.push_back("+zcm");
1690b57cec5SDimitry Andric Features.push_back("+zcz");
1700b57cec5SDimitry Andric }
171*0fca6ea1SDimitry Andric
1720b57cec5SDimitry Andric return true;
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric
1750b57cec5SDimitry Andric static bool
getAArch64MicroArchFeaturesFromMcpu(const Driver & D,StringRef Mcpu,const ArgList & Args,std::vector<StringRef> & Features)1760b57cec5SDimitry Andric getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
1770b57cec5SDimitry Andric const ArgList &Args,
1780b57cec5SDimitry Andric std::vector<StringRef> &Features) {
1790b57cec5SDimitry Andric StringRef CPU;
1807a6dacacSDimitry Andric // Check CPU name is valid, but ignore any extensions on it.
1817a6dacacSDimitry Andric llvm::AArch64::ExtensionSet DecodedFeature;
1820b57cec5SDimitry Andric std::string McpuLowerCase = Mcpu.lower();
1830b57cec5SDimitry Andric if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, DecodedFeature))
1840b57cec5SDimitry Andric return false;
1850b57cec5SDimitry Andric
1860b57cec5SDimitry Andric return getAArch64MicroArchFeaturesFromMtune(D, CPU, Args, Features);
1870b57cec5SDimitry Andric }
1880b57cec5SDimitry Andric
getAArch64TargetFeatures(const Driver & D,const llvm::Triple & Triple,const ArgList & Args,std::vector<StringRef> & Features,bool ForAS)1890b57cec5SDimitry Andric void aarch64::getAArch64TargetFeatures(const Driver &D,
1900b57cec5SDimitry Andric const llvm::Triple &Triple,
1910b57cec5SDimitry Andric const ArgList &Args,
192fe6060f1SDimitry Andric std::vector<StringRef> &Features,
193fe6060f1SDimitry Andric bool ForAS) {
1940b57cec5SDimitry Andric Arg *A;
1950b57cec5SDimitry Andric bool success = true;
196a9cd5c30SDimitry Andric llvm::StringRef WaMArch;
1977a6dacacSDimitry Andric llvm::AArch64::ExtensionSet Extensions;
198fe6060f1SDimitry Andric if (ForAS)
199fe6060f1SDimitry Andric for (const auto *A :
200fe6060f1SDimitry Andric Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler))
201fe6060f1SDimitry Andric for (StringRef Value : A->getValues())
2025f757f3fSDimitry Andric if (Value.starts_with("-march="))
203fe6060f1SDimitry Andric WaMArch = Value.substr(7);
204fe6060f1SDimitry Andric // Call getAArch64ArchFeaturesFromMarch only if "-Wa,-march=" or
205fe6060f1SDimitry Andric // "-Xassembler -march" is detected. Otherwise it may return false
206fe6060f1SDimitry Andric // and causes Clang to error out.
207a9cd5c30SDimitry Andric if (!WaMArch.empty())
2087a6dacacSDimitry Andric success = getAArch64ArchFeaturesFromMarch(D, WaMArch, Args, Extensions);
209fe6060f1SDimitry Andric else if ((A = Args.getLastArg(options::OPT_march_EQ)))
2107a6dacacSDimitry Andric success =
2117a6dacacSDimitry Andric getAArch64ArchFeaturesFromMarch(D, A->getValue(), Args, Extensions);
2120b57cec5SDimitry Andric else if ((A = Args.getLastArg(options::OPT_mcpu_EQ)))
2137a6dacacSDimitry Andric success =
2147a6dacacSDimitry Andric getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Extensions);
2155f757f3fSDimitry Andric else if (isCPUDeterminedByTriple(Triple))
2160b57cec5SDimitry Andric success = getAArch64ArchFeaturesFromMcpu(
2177a6dacacSDimitry Andric D, getAArch64TargetCPU(Args, Triple, A), Args, Extensions);
218349cc55cSDimitry Andric else
219349cc55cSDimitry Andric // Default to 'A' profile if the architecture is not specified.
2207a6dacacSDimitry Andric success = getAArch64ArchFeaturesFromMarch(D, "armv8-a", Args, Extensions);
2210b57cec5SDimitry Andric
2220b57cec5SDimitry Andric if (success && (A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)))
2230b57cec5SDimitry Andric success =
2240b57cec5SDimitry Andric getAArch64MicroArchFeaturesFromMtune(D, A->getValue(), Args, Features);
2250b57cec5SDimitry Andric else if (success && (A = Args.getLastArg(options::OPT_mcpu_EQ)))
2260b57cec5SDimitry Andric success =
2270b57cec5SDimitry Andric getAArch64MicroArchFeaturesFromMcpu(D, A->getValue(), Args, Features);
2285f757f3fSDimitry Andric else if (success && isCPUDeterminedByTriple(Triple))
2290b57cec5SDimitry Andric success = getAArch64MicroArchFeaturesFromMcpu(
2300b57cec5SDimitry Andric D, getAArch64TargetCPU(Args, Triple, A), Args, Features);
2310b57cec5SDimitry Andric
232a9cd5c30SDimitry Andric if (!success) {
23381ad6265SDimitry Andric auto Diag = D.Diag(diag::err_drv_unsupported_option_argument);
234a9cd5c30SDimitry Andric // If "-Wa,-march=" is used, 'WaMArch' will contain the argument's value,
235a9cd5c30SDimitry Andric // while 'A' is uninitialized. Only dereference 'A' in the other case.
236a9cd5c30SDimitry Andric if (!WaMArch.empty())
237bdd1243dSDimitry Andric Diag << "-march=" << WaMArch;
238a9cd5c30SDimitry Andric else
239bdd1243dSDimitry Andric Diag << A->getSpelling() << A->getValue();
240a9cd5c30SDimitry Andric }
2410b57cec5SDimitry Andric
2427a6dacacSDimitry Andric // -mgeneral-regs-only disables all floating-point features.
2430b57cec5SDimitry Andric if (Args.getLastArg(options::OPT_mgeneral_regs_only)) {
2447a6dacacSDimitry Andric Extensions.disable(llvm::AArch64::AEK_FP);
2450b57cec5SDimitry Andric }
2460b57cec5SDimitry Andric
2477a6dacacSDimitry Andric // En/disable crc
2487a6dacacSDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) {
2497a6dacacSDimitry Andric if (A->getOption().matches(options::OPT_mcrc))
2507a6dacacSDimitry Andric Extensions.enable(llvm::AArch64::AEK_CRC);
2517a6dacacSDimitry Andric else
2527a6dacacSDimitry Andric Extensions.disable(llvm::AArch64::AEK_CRC);
2537a6dacacSDimitry Andric }
2547a6dacacSDimitry Andric
2557a6dacacSDimitry Andric // At this point all hardware features are decided, so convert the extensions
2567a6dacacSDimitry Andric // set to a feature list.
2577a6dacacSDimitry Andric Extensions.toLLVMFeatureList(Features);
2587a6dacacSDimitry Andric
2590b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_mtp_mode_EQ)) {
2600b57cec5SDimitry Andric StringRef Mtp = A->getValue();
26106c3fb27SDimitry Andric if (Mtp == "el3" || Mtp == "tpidr_el3")
2620b57cec5SDimitry Andric Features.push_back("+tpidr-el3");
26306c3fb27SDimitry Andric else if (Mtp == "el2" || Mtp == "tpidr_el2")
2640b57cec5SDimitry Andric Features.push_back("+tpidr-el2");
26506c3fb27SDimitry Andric else if (Mtp == "el1" || Mtp == "tpidr_el1")
2660b57cec5SDimitry Andric Features.push_back("+tpidr-el1");
26706c3fb27SDimitry Andric else if (Mtp == "tpidrro_el0")
26806c3fb27SDimitry Andric Features.push_back("+tpidrro-el0");
26906c3fb27SDimitry Andric else if (Mtp != "el0" && Mtp != "tpidr_el0")
2700b57cec5SDimitry Andric D.Diag(diag::err_drv_invalid_mtp) << A->getAsString(Args);
2710b57cec5SDimitry Andric }
2720b57cec5SDimitry Andric
2735ffd83dbSDimitry Andric // Enable/disable straight line speculation hardening.
2745ffd83dbSDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_mharden_sls_EQ)) {
2755ffd83dbSDimitry Andric StringRef Scope = A->getValue();
2765ffd83dbSDimitry Andric bool EnableRetBr = false;
2775ffd83dbSDimitry Andric bool EnableBlr = false;
278fe6060f1SDimitry Andric bool DisableComdat = false;
279fe6060f1SDimitry Andric if (Scope != "none") {
2805ffd83dbSDimitry Andric SmallVector<StringRef, 4> Opts;
2815ffd83dbSDimitry Andric Scope.split(Opts, ",");
2825ffd83dbSDimitry Andric for (auto Opt : Opts) {
2835ffd83dbSDimitry Andric Opt = Opt.trim();
284fe6060f1SDimitry Andric if (Opt == "all") {
285fe6060f1SDimitry Andric EnableBlr = true;
286fe6060f1SDimitry Andric EnableRetBr = true;
287fe6060f1SDimitry Andric continue;
288fe6060f1SDimitry Andric }
2895ffd83dbSDimitry Andric if (Opt == "retbr") {
2905ffd83dbSDimitry Andric EnableRetBr = true;
2915ffd83dbSDimitry Andric continue;
2925ffd83dbSDimitry Andric }
2935ffd83dbSDimitry Andric if (Opt == "blr") {
2945ffd83dbSDimitry Andric EnableBlr = true;
2955ffd83dbSDimitry Andric continue;
2965ffd83dbSDimitry Andric }
297fe6060f1SDimitry Andric if (Opt == "comdat") {
298fe6060f1SDimitry Andric DisableComdat = false;
299fe6060f1SDimitry Andric continue;
300fe6060f1SDimitry Andric }
301fe6060f1SDimitry Andric if (Opt == "nocomdat") {
302fe6060f1SDimitry Andric DisableComdat = true;
303fe6060f1SDimitry Andric continue;
304fe6060f1SDimitry Andric }
30581ad6265SDimitry Andric D.Diag(diag::err_drv_unsupported_option_argument)
306bdd1243dSDimitry Andric << A->getSpelling() << Scope;
3075ffd83dbSDimitry Andric break;
3085ffd83dbSDimitry Andric }
3095ffd83dbSDimitry Andric }
3105ffd83dbSDimitry Andric
3115ffd83dbSDimitry Andric if (EnableRetBr)
3125ffd83dbSDimitry Andric Features.push_back("+harden-sls-retbr");
3135ffd83dbSDimitry Andric if (EnableBlr)
3145ffd83dbSDimitry Andric Features.push_back("+harden-sls-blr");
315fe6060f1SDimitry Andric if (DisableComdat) {
316fe6060f1SDimitry Andric Features.push_back("+harden-sls-nocomdat");
317fe6060f1SDimitry Andric }
3185ffd83dbSDimitry Andric }
3195ffd83dbSDimitry Andric
320*0fca6ea1SDimitry Andric if (Arg *A = Args.getLastArg(
321*0fca6ea1SDimitry Andric options::OPT_mstrict_align, options::OPT_mno_strict_align,
322*0fca6ea1SDimitry Andric options::OPT_mno_unaligned_access, options::OPT_munaligned_access)) {
323*0fca6ea1SDimitry Andric if (A->getOption().matches(options::OPT_mstrict_align) ||
324*0fca6ea1SDimitry Andric A->getOption().matches(options::OPT_mno_unaligned_access))
3250b57cec5SDimitry Andric Features.push_back("+strict-align");
32681ad6265SDimitry Andric } else if (Triple.isOSOpenBSD())
32775b4d546SDimitry Andric Features.push_back("+strict-align");
3280b57cec5SDimitry Andric
3290b57cec5SDimitry Andric if (Args.hasArg(options::OPT_ffixed_x1))
3300b57cec5SDimitry Andric Features.push_back("+reserve-x1");
3310b57cec5SDimitry Andric
3320b57cec5SDimitry Andric if (Args.hasArg(options::OPT_ffixed_x2))
3330b57cec5SDimitry Andric Features.push_back("+reserve-x2");
3340b57cec5SDimitry Andric
3350b57cec5SDimitry Andric if (Args.hasArg(options::OPT_ffixed_x3))
3360b57cec5SDimitry Andric Features.push_back("+reserve-x3");
3370b57cec5SDimitry Andric
3380b57cec5SDimitry Andric if (Args.hasArg(options::OPT_ffixed_x4))
3390b57cec5SDimitry Andric Features.push_back("+reserve-x4");
3400b57cec5SDimitry Andric
3410b57cec5SDimitry Andric if (Args.hasArg(options::OPT_ffixed_x5))
3420b57cec5SDimitry Andric Features.push_back("+reserve-x5");
3430b57cec5SDimitry Andric
3440b57cec5SDimitry Andric if (Args.hasArg(options::OPT_ffixed_x6))
3450b57cec5SDimitry Andric Features.push_back("+reserve-x6");
3460b57cec5SDimitry Andric
3470b57cec5SDimitry Andric if (Args.hasArg(options::OPT_ffixed_x7))
3480b57cec5SDimitry Andric Features.push_back("+reserve-x7");
3490b57cec5SDimitry Andric
3500b57cec5SDimitry Andric if (Args.hasArg(options::OPT_ffixed_x9))
3510b57cec5SDimitry Andric Features.push_back("+reserve-x9");
3520b57cec5SDimitry Andric
3530b57cec5SDimitry Andric if (Args.hasArg(options::OPT_ffixed_x10))
3540b57cec5SDimitry Andric Features.push_back("+reserve-x10");
3550b57cec5SDimitry Andric
3560b57cec5SDimitry Andric if (Args.hasArg(options::OPT_ffixed_x11))
3570b57cec5SDimitry Andric Features.push_back("+reserve-x11");
3580b57cec5SDimitry Andric
3590b57cec5SDimitry Andric if (Args.hasArg(options::OPT_ffixed_x12))
3600b57cec5SDimitry Andric Features.push_back("+reserve-x12");
3610b57cec5SDimitry Andric
3620b57cec5SDimitry Andric if (Args.hasArg(options::OPT_ffixed_x13))
3630b57cec5SDimitry Andric Features.push_back("+reserve-x13");
3640b57cec5SDimitry Andric
3650b57cec5SDimitry Andric if (Args.hasArg(options::OPT_ffixed_x14))
3660b57cec5SDimitry Andric Features.push_back("+reserve-x14");
3670b57cec5SDimitry Andric
3680b57cec5SDimitry Andric if (Args.hasArg(options::OPT_ffixed_x15))
3690b57cec5SDimitry Andric Features.push_back("+reserve-x15");
3700b57cec5SDimitry Andric
3710b57cec5SDimitry Andric if (Args.hasArg(options::OPT_ffixed_x18))
3720b57cec5SDimitry Andric Features.push_back("+reserve-x18");
3730b57cec5SDimitry Andric
3740b57cec5SDimitry Andric if (Args.hasArg(options::OPT_ffixed_x20))
3750b57cec5SDimitry Andric Features.push_back("+reserve-x20");
3760b57cec5SDimitry Andric
3770b57cec5SDimitry Andric if (Args.hasArg(options::OPT_ffixed_x21))
3780b57cec5SDimitry Andric Features.push_back("+reserve-x21");
3790b57cec5SDimitry Andric
3800b57cec5SDimitry Andric if (Args.hasArg(options::OPT_ffixed_x22))
3810b57cec5SDimitry Andric Features.push_back("+reserve-x22");
3820b57cec5SDimitry Andric
3830b57cec5SDimitry Andric if (Args.hasArg(options::OPT_ffixed_x23))
3840b57cec5SDimitry Andric Features.push_back("+reserve-x23");
3850b57cec5SDimitry Andric
3860b57cec5SDimitry Andric if (Args.hasArg(options::OPT_ffixed_x24))
3870b57cec5SDimitry Andric Features.push_back("+reserve-x24");
3880b57cec5SDimitry Andric
3890b57cec5SDimitry Andric if (Args.hasArg(options::OPT_ffixed_x25))
3900b57cec5SDimitry Andric Features.push_back("+reserve-x25");
3910b57cec5SDimitry Andric
3920b57cec5SDimitry Andric if (Args.hasArg(options::OPT_ffixed_x26))
3930b57cec5SDimitry Andric Features.push_back("+reserve-x26");
3940b57cec5SDimitry Andric
3950b57cec5SDimitry Andric if (Args.hasArg(options::OPT_ffixed_x27))
3960b57cec5SDimitry Andric Features.push_back("+reserve-x27");
3970b57cec5SDimitry Andric
3980b57cec5SDimitry Andric if (Args.hasArg(options::OPT_ffixed_x28))
3990b57cec5SDimitry Andric Features.push_back("+reserve-x28");
4000b57cec5SDimitry Andric
401*0fca6ea1SDimitry Andric if (Args.hasArg(options::OPT_mlr_for_calls_only))
402*0fca6ea1SDimitry Andric Features.push_back("+reserve-lr-for-ra");
4035ffd83dbSDimitry Andric
4040b57cec5SDimitry Andric if (Args.hasArg(options::OPT_fcall_saved_x8))
4050b57cec5SDimitry Andric Features.push_back("+call-saved-x8");
4060b57cec5SDimitry Andric
4070b57cec5SDimitry Andric if (Args.hasArg(options::OPT_fcall_saved_x9))
4080b57cec5SDimitry Andric Features.push_back("+call-saved-x9");
4090b57cec5SDimitry Andric
4100b57cec5SDimitry Andric if (Args.hasArg(options::OPT_fcall_saved_x10))
4110b57cec5SDimitry Andric Features.push_back("+call-saved-x10");
4120b57cec5SDimitry Andric
4130b57cec5SDimitry Andric if (Args.hasArg(options::OPT_fcall_saved_x11))
4140b57cec5SDimitry Andric Features.push_back("+call-saved-x11");
4150b57cec5SDimitry Andric
4160b57cec5SDimitry Andric if (Args.hasArg(options::OPT_fcall_saved_x12))
4170b57cec5SDimitry Andric Features.push_back("+call-saved-x12");
4180b57cec5SDimitry Andric
4190b57cec5SDimitry Andric if (Args.hasArg(options::OPT_fcall_saved_x13))
4200b57cec5SDimitry Andric Features.push_back("+call-saved-x13");
4210b57cec5SDimitry Andric
4220b57cec5SDimitry Andric if (Args.hasArg(options::OPT_fcall_saved_x14))
4230b57cec5SDimitry Andric Features.push_back("+call-saved-x14");
4240b57cec5SDimitry Andric
4250b57cec5SDimitry Andric if (Args.hasArg(options::OPT_fcall_saved_x15))
4260b57cec5SDimitry Andric Features.push_back("+call-saved-x15");
4270b57cec5SDimitry Andric
4280b57cec5SDimitry Andric if (Args.hasArg(options::OPT_fcall_saved_x18))
4290b57cec5SDimitry Andric Features.push_back("+call-saved-x18");
4300b57cec5SDimitry Andric
4310b57cec5SDimitry Andric if (Args.hasArg(options::OPT_mno_neg_immediates))
4320b57cec5SDimitry Andric Features.push_back("+no-neg-immediates");
4330eae32dcSDimitry Andric
4340eae32dcSDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_mfix_cortex_a53_835769,
4350eae32dcSDimitry Andric options::OPT_mno_fix_cortex_a53_835769)) {
4360eae32dcSDimitry Andric if (A->getOption().matches(options::OPT_mfix_cortex_a53_835769))
4370eae32dcSDimitry Andric Features.push_back("+fix-cortex-a53-835769");
4380eae32dcSDimitry Andric else
4390eae32dcSDimitry Andric Features.push_back("-fix-cortex-a53-835769");
44006c3fb27SDimitry Andric } else if (Triple.isAndroid() || Triple.isOHOSFamily()) {
4410eae32dcSDimitry Andric // Enabled A53 errata (835769) workaround by default on android
4420eae32dcSDimitry Andric Features.push_back("+fix-cortex-a53-835769");
443bdd1243dSDimitry Andric } else if (Triple.isOSFuchsia()) {
444bdd1243dSDimitry Andric std::string CPU = getCPUName(D, Args, Triple);
445bdd1243dSDimitry Andric if (CPU.empty() || CPU == "generic" || CPU == "cortex-a53")
446bdd1243dSDimitry Andric Features.push_back("+fix-cortex-a53-835769");
4470eae32dcSDimitry Andric }
4483a9a9c0cSDimitry Andric
4493a9a9c0cSDimitry Andric if (Args.getLastArg(options::OPT_mno_bti_at_return_twice))
4503a9a9c0cSDimitry Andric Features.push_back("+no-bti-at-return-twice");
4510b57cec5SDimitry Andric }
452*0fca6ea1SDimitry Andric
setPAuthABIInTriple(const Driver & D,const ArgList & Args,llvm::Triple & Triple)453*0fca6ea1SDimitry Andric void aarch64::setPAuthABIInTriple(const Driver &D, const ArgList &Args,
454*0fca6ea1SDimitry Andric llvm::Triple &Triple) {
455*0fca6ea1SDimitry Andric Arg *ABIArg = Args.getLastArg(options::OPT_mabi_EQ);
456*0fca6ea1SDimitry Andric bool HasPAuthABI =
457*0fca6ea1SDimitry Andric ABIArg ? (StringRef(ABIArg->getValue()) == "pauthtest") : false;
458*0fca6ea1SDimitry Andric
459*0fca6ea1SDimitry Andric switch (Triple.getEnvironment()) {
460*0fca6ea1SDimitry Andric case llvm::Triple::UnknownEnvironment:
461*0fca6ea1SDimitry Andric if (HasPAuthABI)
462*0fca6ea1SDimitry Andric Triple.setEnvironment(llvm::Triple::PAuthTest);
463*0fca6ea1SDimitry Andric break;
464*0fca6ea1SDimitry Andric case llvm::Triple::PAuthTest:
465*0fca6ea1SDimitry Andric break;
466*0fca6ea1SDimitry Andric default:
467*0fca6ea1SDimitry Andric if (HasPAuthABI)
468*0fca6ea1SDimitry Andric D.Diag(diag::err_drv_unsupported_opt_for_target)
469*0fca6ea1SDimitry Andric << ABIArg->getAsString(Args) << Triple.getTriple();
470*0fca6ea1SDimitry Andric break;
471*0fca6ea1SDimitry Andric }
472*0fca6ea1SDimitry Andric }
473