17330f729Sjoerg //===--- ARM.cpp - ARM (not AArch64) Helpers for Tools ----------*- C++ -*-===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg
97330f729Sjoerg #include "ARM.h"
107330f729Sjoerg #include "clang/Driver/Driver.h"
117330f729Sjoerg #include "clang/Driver/DriverDiagnostic.h"
127330f729Sjoerg #include "clang/Driver/Options.h"
137330f729Sjoerg #include "llvm/ADT/StringSwitch.h"
147330f729Sjoerg #include "llvm/Option/ArgList.h"
157330f729Sjoerg #include "llvm/Support/TargetParser.h"
167330f729Sjoerg #include "llvm/Support/Host.h"
177330f729Sjoerg
187330f729Sjoerg using namespace clang::driver;
197330f729Sjoerg using namespace clang::driver::tools;
207330f729Sjoerg using namespace clang;
217330f729Sjoerg using namespace llvm::opt;
227330f729Sjoerg
237330f729Sjoerg // Get SubArch (vN).
getARMSubArchVersionNumber(const llvm::Triple & Triple)247330f729Sjoerg int arm::getARMSubArchVersionNumber(const llvm::Triple &Triple) {
257330f729Sjoerg llvm::StringRef Arch = Triple.getArchName();
267330f729Sjoerg return llvm::ARM::parseArchVersion(Arch);
277330f729Sjoerg }
287330f729Sjoerg
297330f729Sjoerg // True if M-profile.
isARMMProfile(const llvm::Triple & Triple)307330f729Sjoerg bool arm::isARMMProfile(const llvm::Triple &Triple) {
317330f729Sjoerg llvm::StringRef Arch = Triple.getArchName();
327330f729Sjoerg return llvm::ARM::parseArchProfile(Arch) == llvm::ARM::ProfileKind::M;
337330f729Sjoerg }
347330f729Sjoerg
35*e038c9c4Sjoerg // True if A-profile.
isARMAProfile(const llvm::Triple & Triple)36*e038c9c4Sjoerg bool arm::isARMAProfile(const llvm::Triple &Triple) {
37*e038c9c4Sjoerg llvm::StringRef Arch = Triple.getArchName();
38*e038c9c4Sjoerg return llvm::ARM::parseArchProfile(Arch) == llvm::ARM::ProfileKind::A;
39*e038c9c4Sjoerg }
40*e038c9c4Sjoerg
417330f729Sjoerg // Get Arch/CPU from args.
getARMArchCPUFromArgs(const ArgList & Args,llvm::StringRef & Arch,llvm::StringRef & CPU,bool FromAs)427330f729Sjoerg void arm::getARMArchCPUFromArgs(const ArgList &Args, llvm::StringRef &Arch,
437330f729Sjoerg llvm::StringRef &CPU, bool FromAs) {
447330f729Sjoerg if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ))
457330f729Sjoerg CPU = A->getValue();
467330f729Sjoerg if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
477330f729Sjoerg Arch = A->getValue();
487330f729Sjoerg if (!FromAs)
497330f729Sjoerg return;
507330f729Sjoerg
517330f729Sjoerg for (const Arg *A :
527330f729Sjoerg Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {
53*e038c9c4Sjoerg // Use getValues because -Wa can have multiple arguments
54*e038c9c4Sjoerg // e.g. -Wa,-mcpu=foo,-mcpu=bar
55*e038c9c4Sjoerg for (StringRef Value : A->getValues()) {
567330f729Sjoerg if (Value.startswith("-mcpu="))
577330f729Sjoerg CPU = Value.substr(6);
587330f729Sjoerg if (Value.startswith("-march="))
597330f729Sjoerg Arch = Value.substr(7);
607330f729Sjoerg }
617330f729Sjoerg }
62*e038c9c4Sjoerg }
637330f729Sjoerg
647330f729Sjoerg // Handle -mhwdiv=.
657330f729Sjoerg // FIXME: Use ARMTargetParser.
getARMHWDivFeatures(const Driver & D,const Arg * A,const ArgList & Args,StringRef HWDiv,std::vector<StringRef> & Features)667330f729Sjoerg static void getARMHWDivFeatures(const Driver &D, const Arg *A,
677330f729Sjoerg const ArgList &Args, StringRef HWDiv,
687330f729Sjoerg std::vector<StringRef> &Features) {
69*e038c9c4Sjoerg uint64_t HWDivID = llvm::ARM::parseHWDiv(HWDiv);
707330f729Sjoerg if (!llvm::ARM::getHWDivFeatures(HWDivID, Features))
717330f729Sjoerg D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
727330f729Sjoerg }
737330f729Sjoerg
747330f729Sjoerg // Handle -mfpu=.
getARMFPUFeatures(const Driver & D,const Arg * A,const ArgList & Args,StringRef FPU,std::vector<StringRef> & Features)75*e038c9c4Sjoerg static unsigned getARMFPUFeatures(const Driver &D, const Arg *A,
767330f729Sjoerg const ArgList &Args, StringRef FPU,
777330f729Sjoerg std::vector<StringRef> &Features) {
787330f729Sjoerg unsigned FPUID = llvm::ARM::parseFPU(FPU);
797330f729Sjoerg if (!llvm::ARM::getFPUFeatures(FPUID, Features))
807330f729Sjoerg D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
81*e038c9c4Sjoerg return FPUID;
827330f729Sjoerg }
837330f729Sjoerg
847330f729Sjoerg // Decode ARM features from string like +[no]featureA+[no]featureB+...
DecodeARMFeatures(const Driver & D,StringRef text,StringRef CPU,llvm::ARM::ArchKind ArchKind,std::vector<StringRef> & Features,unsigned & ArgFPUID)85*e038c9c4Sjoerg static bool DecodeARMFeatures(const Driver &D, StringRef text, StringRef CPU,
86*e038c9c4Sjoerg llvm::ARM::ArchKind ArchKind,
87*e038c9c4Sjoerg std::vector<StringRef> &Features,
88*e038c9c4Sjoerg unsigned &ArgFPUID) {
897330f729Sjoerg SmallVector<StringRef, 8> Split;
907330f729Sjoerg text.split(Split, StringRef("+"), -1, false);
917330f729Sjoerg
927330f729Sjoerg for (StringRef Feature : Split) {
93*e038c9c4Sjoerg if (!appendArchExtFeatures(CPU, ArchKind, Feature, Features, ArgFPUID))
947330f729Sjoerg return false;
957330f729Sjoerg }
967330f729Sjoerg return true;
977330f729Sjoerg }
987330f729Sjoerg
DecodeARMFeaturesFromCPU(const Driver & D,StringRef CPU,std::vector<StringRef> & Features)997330f729Sjoerg static void DecodeARMFeaturesFromCPU(const Driver &D, StringRef CPU,
1007330f729Sjoerg std::vector<StringRef> &Features) {
1017330f729Sjoerg CPU = CPU.split("+").first;
1027330f729Sjoerg if (CPU != "generic") {
1037330f729Sjoerg llvm::ARM::ArchKind ArchKind = llvm::ARM::parseCPUArch(CPU);
104*e038c9c4Sjoerg uint64_t Extension = llvm::ARM::getDefaultExtensions(CPU, ArchKind);
1057330f729Sjoerg llvm::ARM::getExtensionFeatures(Extension, Features);
1067330f729Sjoerg }
1077330f729Sjoerg }
1087330f729Sjoerg
1097330f729Sjoerg // Check if -march is valid by checking if it can be canonicalised and parsed.
1107330f729Sjoerg // getARMArch is used here instead of just checking the -march value in order
1117330f729Sjoerg // to handle -march=native correctly.
checkARMArchName(const Driver & D,const Arg * A,const ArgList & Args,llvm::StringRef ArchName,llvm::StringRef CPUName,std::vector<StringRef> & Features,const llvm::Triple & Triple,unsigned & ArgFPUID)1127330f729Sjoerg static void checkARMArchName(const Driver &D, const Arg *A, const ArgList &Args,
1137330f729Sjoerg llvm::StringRef ArchName, llvm::StringRef CPUName,
1147330f729Sjoerg std::vector<StringRef> &Features,
115*e038c9c4Sjoerg const llvm::Triple &Triple, unsigned &ArgFPUID) {
1167330f729Sjoerg std::pair<StringRef, StringRef> Split = ArchName.split("+");
1177330f729Sjoerg
1187330f729Sjoerg std::string MArch = arm::getARMArch(ArchName, Triple);
1197330f729Sjoerg llvm::ARM::ArchKind ArchKind = llvm::ARM::parseArch(MArch);
1207330f729Sjoerg if (ArchKind == llvm::ARM::ArchKind::INVALID ||
121*e038c9c4Sjoerg (Split.second.size() && !DecodeARMFeatures(D, Split.second, CPUName,
122*e038c9c4Sjoerg ArchKind, Features, ArgFPUID)))
1237330f729Sjoerg D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
1247330f729Sjoerg }
1257330f729Sjoerg
1267330f729Sjoerg // Check -mcpu=. Needs ArchName to handle -mcpu=generic.
checkARMCPUName(const Driver & D,const Arg * A,const ArgList & Args,llvm::StringRef CPUName,llvm::StringRef ArchName,std::vector<StringRef> & Features,const llvm::Triple & Triple,unsigned & ArgFPUID)1277330f729Sjoerg static void checkARMCPUName(const Driver &D, const Arg *A, const ArgList &Args,
1287330f729Sjoerg llvm::StringRef CPUName, llvm::StringRef ArchName,
1297330f729Sjoerg std::vector<StringRef> &Features,
130*e038c9c4Sjoerg const llvm::Triple &Triple, unsigned &ArgFPUID) {
1317330f729Sjoerg std::pair<StringRef, StringRef> Split = CPUName.split("+");
1327330f729Sjoerg
1337330f729Sjoerg std::string CPU = arm::getARMTargetCPU(CPUName, ArchName, Triple);
1347330f729Sjoerg llvm::ARM::ArchKind ArchKind =
1357330f729Sjoerg arm::getLLVMArchKindForARM(CPU, ArchName, Triple);
1367330f729Sjoerg if (ArchKind == llvm::ARM::ArchKind::INVALID ||
137*e038c9c4Sjoerg (Split.second.size() &&
138*e038c9c4Sjoerg !DecodeARMFeatures(D, Split.second, CPU, ArchKind, Features, ArgFPUID)))
1397330f729Sjoerg D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
1407330f729Sjoerg }
1417330f729Sjoerg
useAAPCSForMachO(const llvm::Triple & T)1427330f729Sjoerg bool arm::useAAPCSForMachO(const llvm::Triple &T) {
1437330f729Sjoerg // The backend is hardwired to assume AAPCS for M-class processors, ensure
1447330f729Sjoerg // the frontend matches that.
1457330f729Sjoerg return T.getEnvironment() == llvm::Triple::EABI ||
146*e038c9c4Sjoerg T.getEnvironment() == llvm::Triple::EABIHF ||
1477330f729Sjoerg T.getOS() == llvm::Triple::UnknownOS || isARMMProfile(T);
1487330f729Sjoerg }
1497330f729Sjoerg
1507330f729Sjoerg // Select mode for reading thread pointer (-mtp=soft/cp15).
getReadTPMode(const Driver & D,const ArgList & Args)151*e038c9c4Sjoerg arm::ReadTPMode arm::getReadTPMode(const Driver &D, const ArgList &Args) {
1527330f729Sjoerg if (Arg *A = Args.getLastArg(options::OPT_mtp_mode_EQ)) {
1537330f729Sjoerg arm::ReadTPMode ThreadPointer =
1547330f729Sjoerg llvm::StringSwitch<arm::ReadTPMode>(A->getValue())
1557330f729Sjoerg .Case("cp15", ReadTPMode::Cp15)
1567330f729Sjoerg .Case("soft", ReadTPMode::Soft)
1577330f729Sjoerg .Default(ReadTPMode::Invalid);
1587330f729Sjoerg if (ThreadPointer != ReadTPMode::Invalid)
1597330f729Sjoerg return ThreadPointer;
1607330f729Sjoerg if (StringRef(A->getValue()).empty())
1617330f729Sjoerg D.Diag(diag::err_drv_missing_arg_mtp) << A->getAsString(Args);
1627330f729Sjoerg else
1637330f729Sjoerg D.Diag(diag::err_drv_invalid_mtp) << A->getAsString(Args);
1647330f729Sjoerg return ReadTPMode::Invalid;
1657330f729Sjoerg }
1667330f729Sjoerg return ReadTPMode::Soft;
1677330f729Sjoerg }
1687330f729Sjoerg
setArchNameInTriple(const Driver & D,const ArgList & Args,types::ID InputType,llvm::Triple & Triple)169*e038c9c4Sjoerg void arm::setArchNameInTriple(const Driver &D, const ArgList &Args,
170*e038c9c4Sjoerg types::ID InputType, llvm::Triple &Triple) {
171*e038c9c4Sjoerg StringRef MCPU, MArch;
172*e038c9c4Sjoerg if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
173*e038c9c4Sjoerg MCPU = A->getValue();
174*e038c9c4Sjoerg if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
175*e038c9c4Sjoerg MArch = A->getValue();
176*e038c9c4Sjoerg
177*e038c9c4Sjoerg std::string CPU = Triple.isOSBinFormatMachO()
178*e038c9c4Sjoerg ? tools::arm::getARMCPUForMArch(MArch, Triple).str()
179*e038c9c4Sjoerg : tools::arm::getARMTargetCPU(MCPU, MArch, Triple);
180*e038c9c4Sjoerg StringRef Suffix = tools::arm::getLLVMArchSuffixForARM(CPU, MArch, Triple);
181*e038c9c4Sjoerg
182*e038c9c4Sjoerg bool IsBigEndian = Triple.getArch() == llvm::Triple::armeb ||
183*e038c9c4Sjoerg Triple.getArch() == llvm::Triple::thumbeb;
184*e038c9c4Sjoerg // Handle pseudo-target flags '-mlittle-endian'/'-EL' and
185*e038c9c4Sjoerg // '-mbig-endian'/'-EB'.
186*e038c9c4Sjoerg if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
187*e038c9c4Sjoerg options::OPT_mbig_endian)) {
188*e038c9c4Sjoerg IsBigEndian = !A->getOption().matches(options::OPT_mlittle_endian);
189*e038c9c4Sjoerg }
190*e038c9c4Sjoerg std::string ArchName = IsBigEndian ? "armeb" : "arm";
191*e038c9c4Sjoerg
192*e038c9c4Sjoerg // FIXME: Thumb should just be another -target-feaure, not in the triple.
193*e038c9c4Sjoerg bool IsMProfile =
194*e038c9c4Sjoerg llvm::ARM::parseArchProfile(Suffix) == llvm::ARM::ProfileKind::M;
195*e038c9c4Sjoerg bool ThumbDefault = IsMProfile ||
196*e038c9c4Sjoerg // Thumb2 is the default for V7 on Darwin.
197*e038c9c4Sjoerg (llvm::ARM::parseArchVersion(Suffix) == 7 &&
198*e038c9c4Sjoerg Triple.isOSBinFormatMachO()) ||
199*e038c9c4Sjoerg // FIXME: this is invalid for WindowsCE
200*e038c9c4Sjoerg Triple.isOSWindows();
201*e038c9c4Sjoerg
202*e038c9c4Sjoerg // Check if ARM ISA was explicitly selected (using -mno-thumb or -marm) for
203*e038c9c4Sjoerg // M-Class CPUs/architecture variants, which is not supported.
204*e038c9c4Sjoerg bool ARMModeRequested =
205*e038c9c4Sjoerg !Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, ThumbDefault);
206*e038c9c4Sjoerg if (IsMProfile && ARMModeRequested) {
207*e038c9c4Sjoerg if (MCPU.size())
208*e038c9c4Sjoerg D.Diag(diag::err_cpu_unsupported_isa) << CPU << "ARM";
209*e038c9c4Sjoerg else
210*e038c9c4Sjoerg D.Diag(diag::err_arch_unsupported_isa)
211*e038c9c4Sjoerg << tools::arm::getARMArch(MArch, Triple) << "ARM";
212*e038c9c4Sjoerg }
213*e038c9c4Sjoerg
214*e038c9c4Sjoerg // Check to see if an explicit choice to use thumb has been made via
215*e038c9c4Sjoerg // -mthumb. For assembler files we must check for -mthumb in the options
216*e038c9c4Sjoerg // passed to the assembler via -Wa or -Xassembler.
217*e038c9c4Sjoerg bool IsThumb = false;
218*e038c9c4Sjoerg if (InputType != types::TY_PP_Asm)
219*e038c9c4Sjoerg IsThumb =
220*e038c9c4Sjoerg Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, ThumbDefault);
221*e038c9c4Sjoerg else {
222*e038c9c4Sjoerg // Ideally we would check for these flags in
223*e038c9c4Sjoerg // CollectArgsForIntegratedAssembler but we can't change the ArchName at
224*e038c9c4Sjoerg // that point.
225*e038c9c4Sjoerg llvm::StringRef WaMArch, WaMCPU;
226*e038c9c4Sjoerg for (const auto *A :
227*e038c9c4Sjoerg Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {
228*e038c9c4Sjoerg for (StringRef Value : A->getValues()) {
229*e038c9c4Sjoerg // There is no assembler equivalent of -mno-thumb, -marm, or -mno-arm.
230*e038c9c4Sjoerg if (Value == "-mthumb")
231*e038c9c4Sjoerg IsThumb = true;
232*e038c9c4Sjoerg else if (Value.startswith("-march="))
233*e038c9c4Sjoerg WaMArch = Value.substr(7);
234*e038c9c4Sjoerg else if (Value.startswith("-mcpu="))
235*e038c9c4Sjoerg WaMCPU = Value.substr(6);
236*e038c9c4Sjoerg }
237*e038c9c4Sjoerg }
238*e038c9c4Sjoerg
239*e038c9c4Sjoerg if (WaMCPU.size() || WaMArch.size()) {
240*e038c9c4Sjoerg // The way this works means that we prefer -Wa,-mcpu's architecture
241*e038c9c4Sjoerg // over -Wa,-march. Which matches the compiler behaviour.
242*e038c9c4Sjoerg Suffix = tools::arm::getLLVMArchSuffixForARM(WaMCPU, WaMArch, Triple);
243*e038c9c4Sjoerg }
244*e038c9c4Sjoerg }
245*e038c9c4Sjoerg
246*e038c9c4Sjoerg // Assembly files should start in ARM mode, unless arch is M-profile, or
247*e038c9c4Sjoerg // -mthumb has been passed explicitly to the assembler. Windows is always
248*e038c9c4Sjoerg // thumb.
249*e038c9c4Sjoerg if (IsThumb || IsMProfile || Triple.isOSWindows()) {
250*e038c9c4Sjoerg if (IsBigEndian)
251*e038c9c4Sjoerg ArchName = "thumbeb";
252*e038c9c4Sjoerg else
253*e038c9c4Sjoerg ArchName = "thumb";
254*e038c9c4Sjoerg }
255*e038c9c4Sjoerg Triple.setArchName(ArchName + Suffix.str());
256*e038c9c4Sjoerg }
257*e038c9c4Sjoerg
setFloatABIInTriple(const Driver & D,const ArgList & Args,llvm::Triple & Triple)258*e038c9c4Sjoerg void arm::setFloatABIInTriple(const Driver &D, const ArgList &Args,
259*e038c9c4Sjoerg llvm::Triple &Triple) {
260*e038c9c4Sjoerg bool isHardFloat =
261*e038c9c4Sjoerg (arm::getARMFloatABI(D, Triple, Args) == arm::FloatABI::Hard);
262*e038c9c4Sjoerg
263*e038c9c4Sjoerg switch (Triple.getEnvironment()) {
264*e038c9c4Sjoerg case llvm::Triple::GNUEABI:
265*e038c9c4Sjoerg case llvm::Triple::GNUEABIHF:
266*e038c9c4Sjoerg Triple.setEnvironment(isHardFloat ? llvm::Triple::GNUEABIHF
267*e038c9c4Sjoerg : llvm::Triple::GNUEABI);
268*e038c9c4Sjoerg break;
269*e038c9c4Sjoerg case llvm::Triple::EABI:
270*e038c9c4Sjoerg case llvm::Triple::EABIHF:
271*e038c9c4Sjoerg Triple.setEnvironment(isHardFloat ? llvm::Triple::EABIHF
272*e038c9c4Sjoerg : llvm::Triple::EABI);
273*e038c9c4Sjoerg break;
274*e038c9c4Sjoerg case llvm::Triple::MuslEABI:
275*e038c9c4Sjoerg case llvm::Triple::MuslEABIHF:
276*e038c9c4Sjoerg Triple.setEnvironment(isHardFloat ? llvm::Triple::MuslEABIHF
277*e038c9c4Sjoerg : llvm::Triple::MuslEABI);
278*e038c9c4Sjoerg break;
279*e038c9c4Sjoerg default: {
280*e038c9c4Sjoerg arm::FloatABI DefaultABI = arm::getDefaultFloatABI(Triple);
281*e038c9c4Sjoerg if (DefaultABI != arm::FloatABI::Invalid &&
282*e038c9c4Sjoerg isHardFloat != (DefaultABI == arm::FloatABI::Hard)) {
283*e038c9c4Sjoerg Arg *ABIArg =
284*e038c9c4Sjoerg Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
285*e038c9c4Sjoerg options::OPT_mfloat_abi_EQ);
286*e038c9c4Sjoerg assert(ABIArg && "Non-default float abi expected to be from arg");
287*e038c9c4Sjoerg D.Diag(diag::err_drv_unsupported_opt_for_target)
288*e038c9c4Sjoerg << ABIArg->getAsString(Args) << Triple.getTriple();
289*e038c9c4Sjoerg }
290*e038c9c4Sjoerg break;
291*e038c9c4Sjoerg }
292*e038c9c4Sjoerg }
293*e038c9c4Sjoerg }
294*e038c9c4Sjoerg
getARMFloatABI(const ToolChain & TC,const ArgList & Args)295*e038c9c4Sjoerg arm::FloatABI arm::getARMFloatABI(const ToolChain &TC, const ArgList &Args) {
296*e038c9c4Sjoerg return arm::getARMFloatABI(TC.getDriver(), TC.getEffectiveTriple(), Args);
297*e038c9c4Sjoerg }
298*e038c9c4Sjoerg
getDefaultFloatABI(const llvm::Triple & Triple)299*e038c9c4Sjoerg arm::FloatABI arm::getDefaultFloatABI(const llvm::Triple &Triple) {
300*e038c9c4Sjoerg auto SubArch = getARMSubArchVersionNumber(Triple);
301*e038c9c4Sjoerg switch (Triple.getOS()) {
302*e038c9c4Sjoerg case llvm::Triple::Darwin:
303*e038c9c4Sjoerg case llvm::Triple::MacOSX:
304*e038c9c4Sjoerg case llvm::Triple::IOS:
305*e038c9c4Sjoerg case llvm::Triple::TvOS:
306*e038c9c4Sjoerg // Darwin defaults to "softfp" for v6 and v7.
307*e038c9c4Sjoerg if (Triple.isWatchABI())
308*e038c9c4Sjoerg return FloatABI::Hard;
309*e038c9c4Sjoerg else
310*e038c9c4Sjoerg return (SubArch == 6 || SubArch == 7) ? FloatABI::SoftFP : FloatABI::Soft;
311*e038c9c4Sjoerg
312*e038c9c4Sjoerg case llvm::Triple::WatchOS:
313*e038c9c4Sjoerg return FloatABI::Hard;
314*e038c9c4Sjoerg
315*e038c9c4Sjoerg // FIXME: this is invalid for WindowsCE
316*e038c9c4Sjoerg case llvm::Triple::Win32:
317*e038c9c4Sjoerg return FloatABI::Hard;
318*e038c9c4Sjoerg
319*e038c9c4Sjoerg case llvm::Triple::NetBSD:
320*e038c9c4Sjoerg switch (Triple.getEnvironment()) {
321*e038c9c4Sjoerg case llvm::Triple::EABIHF:
322*e038c9c4Sjoerg case llvm::Triple::GNUEABIHF:
323*e038c9c4Sjoerg return FloatABI::Hard;
324*e038c9c4Sjoerg default:
325*e038c9c4Sjoerg return FloatABI::Soft;
326*e038c9c4Sjoerg }
327*e038c9c4Sjoerg break;
328*e038c9c4Sjoerg
329*e038c9c4Sjoerg case llvm::Triple::FreeBSD:
330*e038c9c4Sjoerg switch (Triple.getEnvironment()) {
331*e038c9c4Sjoerg case llvm::Triple::GNUEABIHF:
332*e038c9c4Sjoerg return FloatABI::Hard;
333*e038c9c4Sjoerg default:
334*e038c9c4Sjoerg // FreeBSD defaults to soft float
335*e038c9c4Sjoerg return FloatABI::Soft;
336*e038c9c4Sjoerg }
337*e038c9c4Sjoerg break;
338*e038c9c4Sjoerg
339*e038c9c4Sjoerg case llvm::Triple::OpenBSD:
340*e038c9c4Sjoerg return FloatABI::SoftFP;
341*e038c9c4Sjoerg
342*e038c9c4Sjoerg default:
343*e038c9c4Sjoerg switch (Triple.getEnvironment()) {
344*e038c9c4Sjoerg case llvm::Triple::GNUEABIHF:
345*e038c9c4Sjoerg case llvm::Triple::MuslEABIHF:
346*e038c9c4Sjoerg case llvm::Triple::EABIHF:
347*e038c9c4Sjoerg return FloatABI::Hard;
348*e038c9c4Sjoerg case llvm::Triple::GNUEABI:
349*e038c9c4Sjoerg case llvm::Triple::MuslEABI:
350*e038c9c4Sjoerg case llvm::Triple::EABI:
351*e038c9c4Sjoerg // EABI is always AAPCS, and if it was not marked 'hard', it's softfp
352*e038c9c4Sjoerg return FloatABI::SoftFP;
353*e038c9c4Sjoerg case llvm::Triple::Android:
354*e038c9c4Sjoerg return (SubArch >= 7) ? FloatABI::SoftFP : FloatABI::Soft;
355*e038c9c4Sjoerg default:
356*e038c9c4Sjoerg return FloatABI::Invalid;
357*e038c9c4Sjoerg }
358*e038c9c4Sjoerg }
359*e038c9c4Sjoerg return FloatABI::Invalid;
360*e038c9c4Sjoerg }
361*e038c9c4Sjoerg
3627330f729Sjoerg // Select the float ABI as determined by -msoft-float, -mhard-float, and
3637330f729Sjoerg // -mfloat-abi=.
getARMFloatABI(const Driver & D,const llvm::Triple & Triple,const ArgList & Args)364*e038c9c4Sjoerg arm::FloatABI arm::getARMFloatABI(const Driver &D, const llvm::Triple &Triple,
365*e038c9c4Sjoerg const ArgList &Args) {
3667330f729Sjoerg arm::FloatABI ABI = FloatABI::Invalid;
3677330f729Sjoerg if (Arg *A =
3687330f729Sjoerg Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
3697330f729Sjoerg options::OPT_mfloat_abi_EQ)) {
3707330f729Sjoerg if (A->getOption().matches(options::OPT_msoft_float)) {
3717330f729Sjoerg ABI = FloatABI::Soft;
3727330f729Sjoerg } else if (A->getOption().matches(options::OPT_mhard_float)) {
3737330f729Sjoerg ABI = FloatABI::Hard;
3747330f729Sjoerg } else {
3757330f729Sjoerg ABI = llvm::StringSwitch<arm::FloatABI>(A->getValue())
3767330f729Sjoerg .Case("soft", FloatABI::Soft)
3777330f729Sjoerg .Case("softfp", FloatABI::SoftFP)
3787330f729Sjoerg .Case("hard", FloatABI::Hard)
3797330f729Sjoerg .Default(FloatABI::Invalid);
3807330f729Sjoerg if (ABI == FloatABI::Invalid && !StringRef(A->getValue()).empty()) {
3817330f729Sjoerg D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
3827330f729Sjoerg ABI = FloatABI::Soft;
3837330f729Sjoerg }
3847330f729Sjoerg }
3857330f729Sjoerg }
3867330f729Sjoerg
3877330f729Sjoerg // If unspecified, choose the default based on the platform.
388*e038c9c4Sjoerg if (ABI == FloatABI::Invalid)
389*e038c9c4Sjoerg ABI = arm::getDefaultFloatABI(Triple);
390*e038c9c4Sjoerg
3917330f729Sjoerg if (ABI == FloatABI::Invalid) {
3927330f729Sjoerg // Assume "soft", but warn the user we are guessing.
3937330f729Sjoerg if (Triple.isOSBinFormatMachO() &&
3947330f729Sjoerg Triple.getSubArch() == llvm::Triple::ARMSubArch_v7em)
3957330f729Sjoerg ABI = FloatABI::Hard;
3967330f729Sjoerg else
3977330f729Sjoerg ABI = FloatABI::Soft;
3987330f729Sjoerg
3997330f729Sjoerg if (Triple.getOS() != llvm::Triple::UnknownOS ||
4007330f729Sjoerg !Triple.isOSBinFormatMachO())
4017330f729Sjoerg D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft";
4027330f729Sjoerg }
4037330f729Sjoerg
4047330f729Sjoerg assert(ABI != FloatABI::Invalid && "must select an ABI");
4057330f729Sjoerg return ABI;
4067330f729Sjoerg }
4077330f729Sjoerg
hasIntegerMVE(const std::vector<StringRef> & F)408*e038c9c4Sjoerg static bool hasIntegerMVE(const std::vector<StringRef> &F) {
409*e038c9c4Sjoerg auto MVE = llvm::find(llvm::reverse(F), "+mve");
410*e038c9c4Sjoerg auto NoMVE = llvm::find(llvm::reverse(F), "-mve");
411*e038c9c4Sjoerg return MVE != F.rend() &&
412*e038c9c4Sjoerg (NoMVE == F.rend() || std::distance(MVE, NoMVE) > 0);
413*e038c9c4Sjoerg }
4147330f729Sjoerg
getARMTargetFeatures(const Driver & D,const llvm::Triple & Triple,const ArgList & Args,ArgStringList & CmdArgs,std::vector<StringRef> & Features,bool ForAS)415*e038c9c4Sjoerg void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
416*e038c9c4Sjoerg const ArgList &Args, ArgStringList &CmdArgs,
417*e038c9c4Sjoerg std::vector<StringRef> &Features, bool ForAS) {
4187330f729Sjoerg bool KernelOrKext =
4197330f729Sjoerg Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
420*e038c9c4Sjoerg arm::FloatABI ABI = arm::getARMFloatABI(D, Triple, Args);
421*e038c9c4Sjoerg arm::ReadTPMode ThreadPointer = arm::getReadTPMode(D, Args);
422*e038c9c4Sjoerg llvm::Optional<std::pair<const Arg *, StringRef>> WaCPU, WaFPU, WaHDiv,
423*e038c9c4Sjoerg WaArch;
4247330f729Sjoerg
4257330f729Sjoerg // This vector will accumulate features from the architecture
4267330f729Sjoerg // extension suffixes on -mcpu and -march (e.g. the 'bar' in
4277330f729Sjoerg // -mcpu=foo+bar). We want to apply those after the features derived
4287330f729Sjoerg // from the FPU, in case -mfpu generates a negative feature which
4297330f729Sjoerg // the +bar is supposed to override.
4307330f729Sjoerg std::vector<StringRef> ExtensionFeatures;
4317330f729Sjoerg
4327330f729Sjoerg if (!ForAS) {
4337330f729Sjoerg // FIXME: Note, this is a hack, the LLVM backend doesn't actually use these
4347330f729Sjoerg // yet (it uses the -mfloat-abi and -msoft-float options), and it is
4357330f729Sjoerg // stripped out by the ARM target. We should probably pass this a new
4367330f729Sjoerg // -target-option, which is handled by the -cc1/-cc1as invocation.
4377330f729Sjoerg //
4387330f729Sjoerg // FIXME2: For consistency, it would be ideal if we set up the target
4397330f729Sjoerg // machine state the same when using the frontend or the assembler. We don't
4407330f729Sjoerg // currently do that for the assembler, we pass the options directly to the
4417330f729Sjoerg // backend and never even instantiate the frontend TargetInfo. If we did,
4427330f729Sjoerg // and used its handleTargetFeatures hook, then we could ensure the
4437330f729Sjoerg // assembler and the frontend behave the same.
4447330f729Sjoerg
4457330f729Sjoerg // Use software floating point operations?
4467330f729Sjoerg if (ABI == arm::FloatABI::Soft)
4477330f729Sjoerg Features.push_back("+soft-float");
4487330f729Sjoerg
4497330f729Sjoerg // Use software floating point argument passing?
4507330f729Sjoerg if (ABI != arm::FloatABI::Hard)
4517330f729Sjoerg Features.push_back("+soft-float-abi");
4527330f729Sjoerg } else {
4537330f729Sjoerg // Here, we make sure that -Wa,-mfpu/cpu/arch/hwdiv will be passed down
4547330f729Sjoerg // to the assembler correctly.
4557330f729Sjoerg for (const Arg *A :
4567330f729Sjoerg Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {
457*e038c9c4Sjoerg // We use getValues here because you can have many options per -Wa
458*e038c9c4Sjoerg // We will keep the last one we find for each of these
459*e038c9c4Sjoerg for (StringRef Value : A->getValues()) {
4607330f729Sjoerg if (Value.startswith("-mfpu=")) {
461*e038c9c4Sjoerg WaFPU = std::make_pair(A, Value.substr(6));
4627330f729Sjoerg } else if (Value.startswith("-mcpu=")) {
463*e038c9c4Sjoerg WaCPU = std::make_pair(A, Value.substr(6));
4647330f729Sjoerg } else if (Value.startswith("-mhwdiv=")) {
465*e038c9c4Sjoerg WaHDiv = std::make_pair(A, Value.substr(8));
4667330f729Sjoerg } else if (Value.startswith("-march=")) {
467*e038c9c4Sjoerg WaArch = std::make_pair(A, Value.substr(7));
468*e038c9c4Sjoerg }
4697330f729Sjoerg }
4707330f729Sjoerg }
4717330f729Sjoerg }
4727330f729Sjoerg
4737330f729Sjoerg if (ThreadPointer == arm::ReadTPMode::Cp15)
4747330f729Sjoerg Features.push_back("+read-tp-hard");
4757330f729Sjoerg
4767330f729Sjoerg const Arg *ArchArg = Args.getLastArg(options::OPT_march_EQ);
4777330f729Sjoerg const Arg *CPUArg = Args.getLastArg(options::OPT_mcpu_EQ);
4787330f729Sjoerg StringRef ArchName;
4797330f729Sjoerg StringRef CPUName;
480*e038c9c4Sjoerg unsigned ArchArgFPUID = llvm::ARM::FK_INVALID;
481*e038c9c4Sjoerg unsigned CPUArgFPUID = llvm::ARM::FK_INVALID;
4827330f729Sjoerg
4837330f729Sjoerg // Check -mcpu. ClangAs gives preference to -Wa,-mcpu=.
4847330f729Sjoerg if (WaCPU) {
4857330f729Sjoerg if (CPUArg)
4867330f729Sjoerg D.Diag(clang::diag::warn_drv_unused_argument)
4877330f729Sjoerg << CPUArg->getAsString(Args);
488*e038c9c4Sjoerg CPUName = WaCPU->second;
489*e038c9c4Sjoerg CPUArg = WaCPU->first;
4907330f729Sjoerg } else if (CPUArg)
4917330f729Sjoerg CPUName = CPUArg->getValue();
4927330f729Sjoerg
4937330f729Sjoerg // Check -march. ClangAs gives preference to -Wa,-march=.
4947330f729Sjoerg if (WaArch) {
4957330f729Sjoerg if (ArchArg)
4967330f729Sjoerg D.Diag(clang::diag::warn_drv_unused_argument)
4977330f729Sjoerg << ArchArg->getAsString(Args);
498*e038c9c4Sjoerg ArchName = WaArch->second;
499*e038c9c4Sjoerg // This will set any features after the base architecture.
500*e038c9c4Sjoerg checkARMArchName(D, WaArch->first, Args, ArchName, CPUName,
501*e038c9c4Sjoerg ExtensionFeatures, Triple, ArchArgFPUID);
502*e038c9c4Sjoerg // The base architecture was handled in ToolChain::ComputeLLVMTriple because
503*e038c9c4Sjoerg // triple is read only by this point.
5047330f729Sjoerg } else if (ArchArg) {
5057330f729Sjoerg ArchName = ArchArg->getValue();
506*e038c9c4Sjoerg checkARMArchName(D, ArchArg, Args, ArchName, CPUName, ExtensionFeatures,
507*e038c9c4Sjoerg Triple, ArchArgFPUID);
5087330f729Sjoerg }
5097330f729Sjoerg
5107330f729Sjoerg // Add CPU features for generic CPUs
5117330f729Sjoerg if (CPUName == "native") {
5127330f729Sjoerg llvm::StringMap<bool> HostFeatures;
5137330f729Sjoerg if (llvm::sys::getHostCPUFeatures(HostFeatures))
5147330f729Sjoerg for (auto &F : HostFeatures)
5157330f729Sjoerg Features.push_back(
5167330f729Sjoerg Args.MakeArgString((F.second ? "+" : "-") + F.first()));
5177330f729Sjoerg } else if (!CPUName.empty()) {
5187330f729Sjoerg // This sets the default features for the specified CPU. We certainly don't
5197330f729Sjoerg // want to override the features that have been explicitly specified on the
5207330f729Sjoerg // command line. Therefore, process them directly instead of appending them
5217330f729Sjoerg // at the end later.
5227330f729Sjoerg DecodeARMFeaturesFromCPU(D, CPUName, Features);
5237330f729Sjoerg }
5247330f729Sjoerg
5257330f729Sjoerg if (CPUArg)
526*e038c9c4Sjoerg checkARMCPUName(D, CPUArg, Args, CPUName, ArchName, ExtensionFeatures,
527*e038c9c4Sjoerg Triple, CPUArgFPUID);
5287330f729Sjoerg // Honor -mfpu=. ClangAs gives preference to -Wa,-mfpu=.
529*e038c9c4Sjoerg unsigned FPUID = llvm::ARM::FK_INVALID;
5307330f729Sjoerg const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ);
5317330f729Sjoerg if (WaFPU) {
5327330f729Sjoerg if (FPUArg)
5337330f729Sjoerg D.Diag(clang::diag::warn_drv_unused_argument)
5347330f729Sjoerg << FPUArg->getAsString(Args);
535*e038c9c4Sjoerg (void)getARMFPUFeatures(D, WaFPU->first, Args, WaFPU->second, Features);
5367330f729Sjoerg } else if (FPUArg) {
537*e038c9c4Sjoerg FPUID = getARMFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features);
5387330f729Sjoerg } else if (Triple.isAndroid() && getARMSubArchVersionNumber(Triple) >= 7) {
5397330f729Sjoerg const char *AndroidFPU = "neon";
540*e038c9c4Sjoerg FPUID = llvm::ARM::parseFPU(AndroidFPU);
541*e038c9c4Sjoerg if (!llvm::ARM::getFPUFeatures(FPUID, Features))
5427330f729Sjoerg D.Diag(clang::diag::err_drv_clang_unsupported)
5437330f729Sjoerg << std::string("-mfpu=") + AndroidFPU;
544*e038c9c4Sjoerg } else {
545*e038c9c4Sjoerg if (!ForAS) {
546*e038c9c4Sjoerg std::string CPU = arm::getARMTargetCPU(CPUName, ArchName, Triple);
547*e038c9c4Sjoerg llvm::ARM::ArchKind ArchKind =
548*e038c9c4Sjoerg arm::getLLVMArchKindForARM(CPU, ArchName, Triple);
549*e038c9c4Sjoerg FPUID = llvm::ARM::getDefaultFPU(CPU, ArchKind);
550*e038c9c4Sjoerg (void)llvm::ARM::getFPUFeatures(FPUID, Features);
551*e038c9c4Sjoerg }
5527330f729Sjoerg }
5537330f729Sjoerg
5547330f729Sjoerg // Now we've finished accumulating features from arch, cpu and fpu,
5557330f729Sjoerg // we can append the ones for architecture extensions that we
5567330f729Sjoerg // collected separately.
5577330f729Sjoerg Features.insert(std::end(Features),
5587330f729Sjoerg std::begin(ExtensionFeatures), std::end(ExtensionFeatures));
5597330f729Sjoerg
5607330f729Sjoerg // Honor -mhwdiv=. ClangAs gives preference to -Wa,-mhwdiv=.
5617330f729Sjoerg const Arg *HDivArg = Args.getLastArg(options::OPT_mhwdiv_EQ);
5627330f729Sjoerg if (WaHDiv) {
5637330f729Sjoerg if (HDivArg)
5647330f729Sjoerg D.Diag(clang::diag::warn_drv_unused_argument)
5657330f729Sjoerg << HDivArg->getAsString(Args);
566*e038c9c4Sjoerg getARMHWDivFeatures(D, WaHDiv->first, Args, WaHDiv->second, Features);
5677330f729Sjoerg } else if (HDivArg)
5687330f729Sjoerg getARMHWDivFeatures(D, HDivArg, Args, HDivArg->getValue(), Features);
5697330f729Sjoerg
5707330f729Sjoerg // Handle (arch-dependent) fp16fml/fullfp16 relationship.
5717330f729Sjoerg // Must happen before any features are disabled due to soft-float.
5727330f729Sjoerg // FIXME: this fp16fml option handling will be reimplemented after the
5737330f729Sjoerg // TargetParser rewrite.
5747330f729Sjoerg const auto ItRNoFullFP16 = std::find(Features.rbegin(), Features.rend(), "-fullfp16");
5757330f729Sjoerg const auto ItRFP16FML = std::find(Features.rbegin(), Features.rend(), "+fp16fml");
5767330f729Sjoerg if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8_4a) {
5777330f729Sjoerg const auto ItRFullFP16 = std::find(Features.rbegin(), Features.rend(), "+fullfp16");
5787330f729Sjoerg if (ItRFullFP16 < ItRNoFullFP16 && ItRFullFP16 < ItRFP16FML) {
5797330f729Sjoerg // Only entangled feature that can be to the right of this +fullfp16 is -fp16fml.
5807330f729Sjoerg // Only append the +fp16fml if there is no -fp16fml after the +fullfp16.
5817330f729Sjoerg if (std::find(Features.rbegin(), ItRFullFP16, "-fp16fml") == ItRFullFP16)
5827330f729Sjoerg Features.push_back("+fp16fml");
5837330f729Sjoerg }
5847330f729Sjoerg else
5857330f729Sjoerg goto fp16_fml_fallthrough;
5867330f729Sjoerg }
5877330f729Sjoerg else {
5887330f729Sjoerg fp16_fml_fallthrough:
5897330f729Sjoerg // In both of these cases, putting the 'other' feature on the end of the vector will
5907330f729Sjoerg // result in the same effect as placing it immediately after the current feature.
5917330f729Sjoerg if (ItRNoFullFP16 < ItRFP16FML)
5927330f729Sjoerg Features.push_back("-fp16fml");
5937330f729Sjoerg else if (ItRNoFullFP16 > ItRFP16FML)
5947330f729Sjoerg Features.push_back("+fullfp16");
5957330f729Sjoerg }
5967330f729Sjoerg
597*e038c9c4Sjoerg // Setting -msoft-float/-mfloat-abi=soft, -mfpu=none, or adding +nofp to
598*e038c9c4Sjoerg // -march/-mcpu effectively disables the FPU (GCC ignores the -mfpu options in
599*e038c9c4Sjoerg // this case). Note that the ABI can also be set implicitly by the target
600*e038c9c4Sjoerg // selected.
6017330f729Sjoerg if (ABI == arm::FloatABI::Soft) {
6027330f729Sjoerg llvm::ARM::getFPUFeatures(llvm::ARM::FK_NONE, Features);
6037330f729Sjoerg
604*e038c9c4Sjoerg // Disable all features relating to hardware FP, not already disabled by the
605*e038c9c4Sjoerg // above call.
606*e038c9c4Sjoerg Features.insert(Features.end(), {"-dotprod", "-fp16fml", "-bf16", "-mve",
607*e038c9c4Sjoerg "-mve.fp", "-fpregs"});
608*e038c9c4Sjoerg } else if (FPUID == llvm::ARM::FK_NONE ||
609*e038c9c4Sjoerg ArchArgFPUID == llvm::ARM::FK_NONE ||
610*e038c9c4Sjoerg CPUArgFPUID == llvm::ARM::FK_NONE) {
611*e038c9c4Sjoerg // -mfpu=none, -march=armvX+nofp or -mcpu=X+nofp is *very* similar to
612*e038c9c4Sjoerg // -mfloat-abi=soft, only that it should not disable MVE-I. They disable the
613*e038c9c4Sjoerg // FPU, but not the FPU registers, thus MVE-I, which depends only on the
614*e038c9c4Sjoerg // latter, is still supported.
615*e038c9c4Sjoerg Features.insert(Features.end(),
616*e038c9c4Sjoerg {"-dotprod", "-fp16fml", "-bf16", "-mve.fp"});
617*e038c9c4Sjoerg if (!hasIntegerMVE(Features))
618*e038c9c4Sjoerg Features.emplace_back("-fpregs");
6197330f729Sjoerg }
6207330f729Sjoerg
6217330f729Sjoerg // En/disable crc code generation.
6227330f729Sjoerg if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) {
6237330f729Sjoerg if (A->getOption().matches(options::OPT_mcrc))
6247330f729Sjoerg Features.push_back("+crc");
6257330f729Sjoerg else
6267330f729Sjoerg Features.push_back("-crc");
6277330f729Sjoerg }
6287330f729Sjoerg
629*e038c9c4Sjoerg // For Arch >= ARMv8.0 && A or R profile: crypto = sha2 + aes
630*e038c9c4Sjoerg // Rather than replace within the feature vector, determine whether each
631*e038c9c4Sjoerg // algorithm is enabled and append this to the end of the vector.
632*e038c9c4Sjoerg // The algorithms can be controlled by their specific feature or the crypto
633*e038c9c4Sjoerg // feature, so their status can be determined by the last occurance of
634*e038c9c4Sjoerg // either in the vector. This allows one to supercede the other.
635*e038c9c4Sjoerg // e.g. +crypto+noaes in -march/-mcpu should enable sha2, but not aes
6367330f729Sjoerg // FIXME: this needs reimplementation after the TargetParser rewrite
637*e038c9c4Sjoerg bool HasSHA2 = false;
638*e038c9c4Sjoerg bool HasAES = false;
639*e038c9c4Sjoerg const auto ItCrypto =
640*e038c9c4Sjoerg llvm::find_if(llvm::reverse(Features), [](const StringRef F) {
6417330f729Sjoerg return F.contains("crypto");
6427330f729Sjoerg });
643*e038c9c4Sjoerg const auto ItSHA2 =
644*e038c9c4Sjoerg llvm::find_if(llvm::reverse(Features), [](const StringRef F) {
645*e038c9c4Sjoerg return F.contains("crypto") || F.contains("sha2");
646*e038c9c4Sjoerg });
647*e038c9c4Sjoerg const auto ItAES =
648*e038c9c4Sjoerg llvm::find_if(llvm::reverse(Features), [](const StringRef F) {
649*e038c9c4Sjoerg return F.contains("crypto") || F.contains("aes");
650*e038c9c4Sjoerg });
651*e038c9c4Sjoerg const bool FoundSHA2 = ItSHA2 != Features.rend();
652*e038c9c4Sjoerg const bool FoundAES = ItAES != Features.rend();
653*e038c9c4Sjoerg if (FoundSHA2)
654*e038c9c4Sjoerg HasSHA2 = ItSHA2->take_front() == "+";
655*e038c9c4Sjoerg if (FoundAES)
656*e038c9c4Sjoerg HasAES = ItAES->take_front() == "+";
657*e038c9c4Sjoerg if (ItCrypto != Features.rend()) {
658*e038c9c4Sjoerg if (HasSHA2 && HasAES)
659*e038c9c4Sjoerg Features.push_back("+crypto");
660*e038c9c4Sjoerg else
661*e038c9c4Sjoerg Features.push_back("-crypto");
662*e038c9c4Sjoerg if (HasSHA2)
663*e038c9c4Sjoerg Features.push_back("+sha2");
664*e038c9c4Sjoerg else
665*e038c9c4Sjoerg Features.push_back("-sha2");
666*e038c9c4Sjoerg if (HasAES)
667*e038c9c4Sjoerg Features.push_back("+aes");
668*e038c9c4Sjoerg else
669*e038c9c4Sjoerg Features.push_back("-aes");
670*e038c9c4Sjoerg }
671*e038c9c4Sjoerg
672*e038c9c4Sjoerg if (HasSHA2 || HasAES) {
6737330f729Sjoerg StringRef ArchSuffix = arm::getLLVMArchSuffixForARM(
6747330f729Sjoerg arm::getARMTargetCPU(CPUName, ArchName, Triple), ArchName, Triple);
675*e038c9c4Sjoerg llvm::ARM::ProfileKind ArchProfile =
676*e038c9c4Sjoerg llvm::ARM::parseArchProfile(ArchSuffix);
677*e038c9c4Sjoerg if (!((llvm::ARM::parseArchVersion(ArchSuffix) >= 8) &&
678*e038c9c4Sjoerg (ArchProfile == llvm::ARM::ProfileKind::A ||
679*e038c9c4Sjoerg ArchProfile == llvm::ARM::ProfileKind::R))) {
680*e038c9c4Sjoerg if (HasSHA2)
6817330f729Sjoerg D.Diag(clang::diag::warn_target_unsupported_extension)
682*e038c9c4Sjoerg << "sha2"
6837330f729Sjoerg << llvm::ARM::getArchName(llvm::ARM::parseArch(ArchSuffix));
684*e038c9c4Sjoerg if (HasAES)
685*e038c9c4Sjoerg D.Diag(clang::diag::warn_target_unsupported_extension)
686*e038c9c4Sjoerg << "aes"
687*e038c9c4Sjoerg << llvm::ARM::getArchName(llvm::ARM::parseArch(ArchSuffix));
688*e038c9c4Sjoerg // With -fno-integrated-as -mfpu=crypto-neon-fp-armv8 some assemblers such
689*e038c9c4Sjoerg // as the GNU assembler will permit the use of crypto instructions as the
690*e038c9c4Sjoerg // fpu will override the architecture. We keep the crypto feature in this
691*e038c9c4Sjoerg // case to preserve compatibility. In all other cases we remove the crypto
692*e038c9c4Sjoerg // feature.
693*e038c9c4Sjoerg if (!Args.hasArg(options::OPT_fno_integrated_as)) {
694*e038c9c4Sjoerg Features.push_back("-sha2");
695*e038c9c4Sjoerg Features.push_back("-aes");
6967330f729Sjoerg }
6977330f729Sjoerg }
6987330f729Sjoerg }
6997330f729Sjoerg
7007330f729Sjoerg // CMSE: Check for target 8M (for -mcmse to be applicable) is performed later.
7017330f729Sjoerg if (Args.getLastArg(options::OPT_mcmse))
7027330f729Sjoerg Features.push_back("+8msecext");
7037330f729Sjoerg
7047330f729Sjoerg // Look for the last occurrence of -mlong-calls or -mno-long-calls. If
7057330f729Sjoerg // neither options are specified, see if we are compiling for kernel/kext and
7067330f729Sjoerg // decide whether to pass "+long-calls" based on the OS and its version.
7077330f729Sjoerg if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,
7087330f729Sjoerg options::OPT_mno_long_calls)) {
7097330f729Sjoerg if (A->getOption().matches(options::OPT_mlong_calls))
7107330f729Sjoerg Features.push_back("+long-calls");
7117330f729Sjoerg } else if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6)) &&
7127330f729Sjoerg !Triple.isWatchOS()) {
7137330f729Sjoerg Features.push_back("+long-calls");
7147330f729Sjoerg }
7157330f729Sjoerg
7167330f729Sjoerg // Generate execute-only output (no data access to code sections).
7177330f729Sjoerg // This only makes sense for the compiler, not for the assembler.
7187330f729Sjoerg if (!ForAS) {
7197330f729Sjoerg // Supported only on ARMv6T2 and ARMv7 and above.
7207330f729Sjoerg // Cannot be combined with -mno-movt or -mlong-calls
7217330f729Sjoerg if (Arg *A = Args.getLastArg(options::OPT_mexecute_only, options::OPT_mno_execute_only)) {
7227330f729Sjoerg if (A->getOption().matches(options::OPT_mexecute_only)) {
7237330f729Sjoerg if (getARMSubArchVersionNumber(Triple) < 7 &&
7247330f729Sjoerg llvm::ARM::parseArch(Triple.getArchName()) != llvm::ARM::ArchKind::ARMV6T2)
7257330f729Sjoerg D.Diag(diag::err_target_unsupported_execute_only) << Triple.getArchName();
7267330f729Sjoerg else if (Arg *B = Args.getLastArg(options::OPT_mno_movt))
7277330f729Sjoerg D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args);
7287330f729Sjoerg // Long calls create constant pool entries and have not yet been fixed up
7297330f729Sjoerg // to play nicely with execute-only. Hence, they cannot be used in
7307330f729Sjoerg // execute-only code for now
7317330f729Sjoerg else if (Arg *B = Args.getLastArg(options::OPT_mlong_calls, options::OPT_mno_long_calls)) {
7327330f729Sjoerg if (B->getOption().matches(options::OPT_mlong_calls))
7337330f729Sjoerg D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args);
7347330f729Sjoerg }
7357330f729Sjoerg Features.push_back("+execute-only");
7367330f729Sjoerg }
7377330f729Sjoerg }
7387330f729Sjoerg }
7397330f729Sjoerg
7407330f729Sjoerg // Kernel code has more strict alignment requirements.
7417330f729Sjoerg if (KernelOrKext)
7427330f729Sjoerg Features.push_back("+strict-align");
7437330f729Sjoerg else if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
7447330f729Sjoerg options::OPT_munaligned_access)) {
7457330f729Sjoerg if (A->getOption().matches(options::OPT_munaligned_access)) {
7467330f729Sjoerg // No v6M core supports unaligned memory access (v6M ARM ARM A3.2).
7477330f729Sjoerg if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m)
7487330f729Sjoerg D.Diag(diag::err_target_unsupported_unaligned) << "v6m";
7497330f729Sjoerg // v8M Baseline follows on from v6M, so doesn't support unaligned memory
7507330f729Sjoerg // access either.
7517330f729Sjoerg else if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8m_baseline)
7527330f729Sjoerg D.Diag(diag::err_target_unsupported_unaligned) << "v8m.base";
7537330f729Sjoerg } else
7547330f729Sjoerg Features.push_back("+strict-align");
7557330f729Sjoerg } else {
7567330f729Sjoerg // Assume pre-ARMv6 doesn't support unaligned accesses.
7577330f729Sjoerg //
7587330f729Sjoerg // ARMv6 may or may not support unaligned accesses depending on the
7597330f729Sjoerg // SCTLR.U bit, which is architecture-specific. We assume ARMv6
7607330f729Sjoerg // Darwin and NetBSD targets support unaligned accesses, and others don't.
7617330f729Sjoerg //
7627330f729Sjoerg // ARMv7 always has SCTLR.U set to 1, but it has a new SCTLR.A bit
7637330f729Sjoerg // which raises an alignment fault on unaligned accesses. Linux
7647330f729Sjoerg // defaults this bit to 0 and handles it as a system-wide (not
7657330f729Sjoerg // per-process) setting. It is therefore safe to assume that ARMv7+
7667330f729Sjoerg // Linux targets support unaligned accesses. The same goes for NaCl.
7677330f729Sjoerg //
7687330f729Sjoerg // The above behavior is consistent with GCC.
7697330f729Sjoerg int VersionNum = getARMSubArchVersionNumber(Triple);
7707330f729Sjoerg if (Triple.isOSDarwin() || Triple.isOSNetBSD()) {
7717330f729Sjoerg if (VersionNum < 6 ||
7727330f729Sjoerg Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m)
7737330f729Sjoerg Features.push_back("+strict-align");
7747330f729Sjoerg } else if (Triple.isOSLinux() || Triple.isOSNaCl()) {
7757330f729Sjoerg if (VersionNum < 7)
7767330f729Sjoerg Features.push_back("+strict-align");
7777330f729Sjoerg } else
7787330f729Sjoerg Features.push_back("+strict-align");
7797330f729Sjoerg }
7807330f729Sjoerg
7817330f729Sjoerg // llvm does not support reserving registers in general. There is support
7827330f729Sjoerg // for reserving r9 on ARM though (defined as a platform-specific register
7837330f729Sjoerg // in ARM EABI).
7847330f729Sjoerg if (Args.hasArg(options::OPT_ffixed_r9))
7857330f729Sjoerg Features.push_back("+reserve-r9");
7867330f729Sjoerg
7877330f729Sjoerg // The kext linker doesn't know how to deal with movw/movt.
7887330f729Sjoerg if (KernelOrKext || Args.hasArg(options::OPT_mno_movt))
7897330f729Sjoerg Features.push_back("+no-movt");
7907330f729Sjoerg
7917330f729Sjoerg if (Args.hasArg(options::OPT_mno_neg_immediates))
7927330f729Sjoerg Features.push_back("+no-neg-immediates");
793*e038c9c4Sjoerg
794*e038c9c4Sjoerg // Enable/disable straight line speculation hardening.
795*e038c9c4Sjoerg if (Arg *A = Args.getLastArg(options::OPT_mharden_sls_EQ)) {
796*e038c9c4Sjoerg StringRef Scope = A->getValue();
797*e038c9c4Sjoerg bool EnableRetBr = false;
798*e038c9c4Sjoerg bool EnableBlr = false;
799*e038c9c4Sjoerg bool DisableComdat = false;
800*e038c9c4Sjoerg if (Scope != "none") {
801*e038c9c4Sjoerg SmallVector<StringRef, 4> Opts;
802*e038c9c4Sjoerg Scope.split(Opts, ",");
803*e038c9c4Sjoerg for (auto Opt : Opts) {
804*e038c9c4Sjoerg Opt = Opt.trim();
805*e038c9c4Sjoerg if (Opt == "all") {
806*e038c9c4Sjoerg EnableBlr = true;
807*e038c9c4Sjoerg EnableRetBr = true;
808*e038c9c4Sjoerg continue;
809*e038c9c4Sjoerg }
810*e038c9c4Sjoerg if (Opt == "retbr") {
811*e038c9c4Sjoerg EnableRetBr = true;
812*e038c9c4Sjoerg continue;
813*e038c9c4Sjoerg }
814*e038c9c4Sjoerg if (Opt == "blr") {
815*e038c9c4Sjoerg EnableBlr = true;
816*e038c9c4Sjoerg continue;
817*e038c9c4Sjoerg }
818*e038c9c4Sjoerg if (Opt == "comdat") {
819*e038c9c4Sjoerg DisableComdat = false;
820*e038c9c4Sjoerg continue;
821*e038c9c4Sjoerg }
822*e038c9c4Sjoerg if (Opt == "nocomdat") {
823*e038c9c4Sjoerg DisableComdat = true;
824*e038c9c4Sjoerg continue;
825*e038c9c4Sjoerg }
826*e038c9c4Sjoerg D.Diag(diag::err_invalid_sls_hardening)
827*e038c9c4Sjoerg << Scope << A->getAsString(Args);
828*e038c9c4Sjoerg break;
829*e038c9c4Sjoerg }
830*e038c9c4Sjoerg }
831*e038c9c4Sjoerg
832*e038c9c4Sjoerg if (EnableRetBr || EnableBlr)
833*e038c9c4Sjoerg if (!(isARMAProfile(Triple) && getARMSubArchVersionNumber(Triple) >= 7))
834*e038c9c4Sjoerg D.Diag(diag::err_sls_hardening_arm_not_supported)
835*e038c9c4Sjoerg << Scope << A->getAsString(Args);
836*e038c9c4Sjoerg
837*e038c9c4Sjoerg if (EnableRetBr)
838*e038c9c4Sjoerg Features.push_back("+harden-sls-retbr");
839*e038c9c4Sjoerg if (EnableBlr)
840*e038c9c4Sjoerg Features.push_back("+harden-sls-blr");
841*e038c9c4Sjoerg if (DisableComdat) {
842*e038c9c4Sjoerg Features.push_back("+harden-sls-nocomdat");
843*e038c9c4Sjoerg }
844*e038c9c4Sjoerg }
845*e038c9c4Sjoerg
8467330f729Sjoerg }
8477330f729Sjoerg
getARMArch(StringRef Arch,const llvm::Triple & Triple)8487330f729Sjoerg const std::string arm::getARMArch(StringRef Arch, const llvm::Triple &Triple) {
8497330f729Sjoerg std::string MArch;
8507330f729Sjoerg if (!Arch.empty())
851*e038c9c4Sjoerg MArch = std::string(Arch);
8527330f729Sjoerg else
853*e038c9c4Sjoerg MArch = std::string(Triple.getArchName());
8547330f729Sjoerg MArch = StringRef(MArch).split("+").first.lower();
8557330f729Sjoerg
8567330f729Sjoerg // Handle -march=native.
8577330f729Sjoerg if (MArch == "native") {
858*e038c9c4Sjoerg std::string CPU = std::string(llvm::sys::getHostCPUName());
8597330f729Sjoerg if (CPU != "generic") {
8607330f729Sjoerg // Translate the native cpu into the architecture suffix for that CPU.
8617330f729Sjoerg StringRef Suffix = arm::getLLVMArchSuffixForARM(CPU, MArch, Triple);
8627330f729Sjoerg // If there is no valid architecture suffix for this CPU we don't know how
8637330f729Sjoerg // to handle it, so return no architecture.
8647330f729Sjoerg if (Suffix.empty())
8657330f729Sjoerg MArch = "";
8667330f729Sjoerg else
8677330f729Sjoerg MArch = std::string("arm") + Suffix.str();
8687330f729Sjoerg }
8697330f729Sjoerg }
8707330f729Sjoerg
8717330f729Sjoerg return MArch;
8727330f729Sjoerg }
8737330f729Sjoerg
8747330f729Sjoerg /// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting.
getARMCPUForMArch(StringRef Arch,const llvm::Triple & Triple)8757330f729Sjoerg StringRef arm::getARMCPUForMArch(StringRef Arch, const llvm::Triple &Triple) {
8767330f729Sjoerg std::string MArch = getARMArch(Arch, Triple);
8777330f729Sjoerg // getARMCPUForArch defaults to the triple if MArch is empty, but empty MArch
8787330f729Sjoerg // here means an -march=native that we can't handle, so instead return no CPU.
8797330f729Sjoerg if (MArch.empty())
8807330f729Sjoerg return StringRef();
8817330f729Sjoerg
8827330f729Sjoerg // We need to return an empty string here on invalid MArch values as the
8837330f729Sjoerg // various places that call this function can't cope with a null result.
8847330f729Sjoerg return Triple.getARMCPUForArch(MArch);
8857330f729Sjoerg }
8867330f729Sjoerg
8877330f729Sjoerg /// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting.
getARMTargetCPU(StringRef CPU,StringRef Arch,const llvm::Triple & Triple)8887330f729Sjoerg std::string arm::getARMTargetCPU(StringRef CPU, StringRef Arch,
8897330f729Sjoerg const llvm::Triple &Triple) {
8907330f729Sjoerg // FIXME: Warn on inconsistent use of -mcpu and -march.
8917330f729Sjoerg // If we have -mcpu=, use that.
8927330f729Sjoerg if (!CPU.empty()) {
8937330f729Sjoerg std::string MCPU = StringRef(CPU).split("+").first.lower();
8947330f729Sjoerg // Handle -mcpu=native.
8957330f729Sjoerg if (MCPU == "native")
896*e038c9c4Sjoerg return std::string(llvm::sys::getHostCPUName());
8977330f729Sjoerg else
8987330f729Sjoerg return MCPU;
8997330f729Sjoerg }
9007330f729Sjoerg
901*e038c9c4Sjoerg return std::string(getARMCPUForMArch(Arch, Triple));
9027330f729Sjoerg }
9037330f729Sjoerg
9047330f729Sjoerg /// getLLVMArchSuffixForARM - Get the LLVM ArchKind value to use for a
9057330f729Sjoerg /// particular CPU (or Arch, if CPU is generic). This is needed to
9067330f729Sjoerg /// pass to functions like llvm::ARM::getDefaultFPU which need an
9077330f729Sjoerg /// ArchKind as well as a CPU name.
getLLVMArchKindForARM(StringRef CPU,StringRef Arch,const llvm::Triple & Triple)9087330f729Sjoerg llvm::ARM::ArchKind arm::getLLVMArchKindForARM(StringRef CPU, StringRef Arch,
9097330f729Sjoerg const llvm::Triple &Triple) {
9107330f729Sjoerg llvm::ARM::ArchKind ArchKind;
9117330f729Sjoerg if (CPU == "generic" || CPU.empty()) {
9127330f729Sjoerg std::string ARMArch = tools::arm::getARMArch(Arch, Triple);
9137330f729Sjoerg ArchKind = llvm::ARM::parseArch(ARMArch);
9147330f729Sjoerg if (ArchKind == llvm::ARM::ArchKind::INVALID)
9157330f729Sjoerg // In case of generic Arch, i.e. "arm",
9167330f729Sjoerg // extract arch from default cpu of the Triple
9177330f729Sjoerg ArchKind = llvm::ARM::parseCPUArch(Triple.getARMCPUForArch(ARMArch));
9187330f729Sjoerg } else {
9197330f729Sjoerg // FIXME: horrible hack to get around the fact that Cortex-A7 is only an
9207330f729Sjoerg // armv7k triple if it's actually been specified via "-arch armv7k".
9217330f729Sjoerg ArchKind = (Arch == "armv7k" || Arch == "thumbv7k")
9227330f729Sjoerg ? llvm::ARM::ArchKind::ARMV7K
9237330f729Sjoerg : llvm::ARM::parseCPUArch(CPU);
9247330f729Sjoerg }
9257330f729Sjoerg return ArchKind;
9267330f729Sjoerg }
9277330f729Sjoerg
9287330f729Sjoerg /// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular
9297330f729Sjoerg /// CPU (or Arch, if CPU is generic).
9307330f729Sjoerg // FIXME: This is redundant with -mcpu, why does LLVM use this.
getLLVMArchSuffixForARM(StringRef CPU,StringRef Arch,const llvm::Triple & Triple)9317330f729Sjoerg StringRef arm::getLLVMArchSuffixForARM(StringRef CPU, StringRef Arch,
9327330f729Sjoerg const llvm::Triple &Triple) {
9337330f729Sjoerg llvm::ARM::ArchKind ArchKind = getLLVMArchKindForARM(CPU, Arch, Triple);
9347330f729Sjoerg if (ArchKind == llvm::ARM::ArchKind::INVALID)
9357330f729Sjoerg return "";
9367330f729Sjoerg return llvm::ARM::getSubArch(ArchKind);
9377330f729Sjoerg }
9387330f729Sjoerg
appendBE8LinkFlag(const ArgList & Args,ArgStringList & CmdArgs,const llvm::Triple & Triple)9397330f729Sjoerg void arm::appendBE8LinkFlag(const ArgList &Args, ArgStringList &CmdArgs,
9407330f729Sjoerg const llvm::Triple &Triple) {
9417330f729Sjoerg if (Args.hasArg(options::OPT_r))
9427330f729Sjoerg return;
9437330f729Sjoerg
9447330f729Sjoerg // ARMv7 (and later) and ARMv6-M do not support BE-32, so instruct the linker
9457330f729Sjoerg // to generate BE-8 executables.
9467330f729Sjoerg if (arm::getARMSubArchVersionNumber(Triple) >= 7 || arm::isARMMProfile(Triple))
9477330f729Sjoerg CmdArgs.push_back("--be8");
9487330f729Sjoerg }
949