1 //===--- ARM.cpp - ARM (not AArch64) Helpers for Tools ----------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "ARM.h"
10 #include "clang/Driver/Driver.h"
11 #include "clang/Driver/DriverDiagnostic.h"
12 #include "clang/Driver/Options.h"
13 #include "llvm/ADT/StringSwitch.h"
14 #include "llvm/Option/ArgList.h"
15 #include "llvm/TargetParser/ARMTargetParser.h"
16 #include "llvm/TargetParser/Host.h"
17
18 using namespace clang::driver;
19 using namespace clang::driver::tools;
20 using namespace clang;
21 using namespace llvm::opt;
22
23 // Get SubArch (vN).
getARMSubArchVersionNumber(const llvm::Triple & Triple)24 int arm::getARMSubArchVersionNumber(const llvm::Triple &Triple) {
25 llvm::StringRef Arch = Triple.getArchName();
26 return llvm::ARM::parseArchVersion(Arch);
27 }
28
29 // True if M-profile.
isARMMProfile(const llvm::Triple & Triple)30 bool arm::isARMMProfile(const llvm::Triple &Triple) {
31 llvm::StringRef Arch = Triple.getArchName();
32 return llvm::ARM::parseArchProfile(Arch) == llvm::ARM::ProfileKind::M;
33 }
34
35 // On Arm the endianness of the output file is determined by the target and
36 // can be overridden by the pseudo-target flags '-mlittle-endian'/'-EL' and
37 // '-mbig-endian'/'-EB'. Unlike other targets the flag does not result in a
38 // normalized triple so we must handle the flag here.
isARMBigEndian(const llvm::Triple & Triple,const ArgList & Args)39 bool arm::isARMBigEndian(const llvm::Triple &Triple, const ArgList &Args) {
40 if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
41 options::OPT_mbig_endian)) {
42 return !A->getOption().matches(options::OPT_mlittle_endian);
43 }
44
45 return Triple.getArch() == llvm::Triple::armeb ||
46 Triple.getArch() == llvm::Triple::thumbeb;
47 }
48
49 // True if A-profile.
isARMAProfile(const llvm::Triple & Triple)50 bool arm::isARMAProfile(const llvm::Triple &Triple) {
51 llvm::StringRef Arch = Triple.getArchName();
52 return llvm::ARM::parseArchProfile(Arch) == llvm::ARM::ProfileKind::A;
53 }
54
55 // Get Arch/CPU from args.
getARMArchCPUFromArgs(const ArgList & Args,llvm::StringRef & Arch,llvm::StringRef & CPU,bool FromAs)56 void arm::getARMArchCPUFromArgs(const ArgList &Args, llvm::StringRef &Arch,
57 llvm::StringRef &CPU, bool FromAs) {
58 if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ))
59 CPU = A->getValue();
60 if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
61 Arch = A->getValue();
62 if (!FromAs)
63 return;
64
65 for (const Arg *A :
66 Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {
67 // Use getValues because -Wa can have multiple arguments
68 // e.g. -Wa,-mcpu=foo,-mcpu=bar
69 for (StringRef Value : A->getValues()) {
70 if (Value.starts_with("-mcpu="))
71 CPU = Value.substr(6);
72 if (Value.starts_with("-march="))
73 Arch = Value.substr(7);
74 }
75 }
76 }
77
78 // Handle -mhwdiv=.
79 // FIXME: Use ARMTargetParser.
getARMHWDivFeatures(const Driver & D,const Arg * A,const ArgList & Args,StringRef HWDiv,std::vector<StringRef> & Features)80 static void getARMHWDivFeatures(const Driver &D, const Arg *A,
81 const ArgList &Args, StringRef HWDiv,
82 std::vector<StringRef> &Features) {
83 uint64_t HWDivID = llvm::ARM::parseHWDiv(HWDiv);
84 if (!llvm::ARM::getHWDivFeatures(HWDivID, Features))
85 D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
86 }
87
88 // Handle -mfpu=.
getARMFPUFeatures(const Driver & D,const Arg * A,const ArgList & Args,StringRef FPU,std::vector<StringRef> & Features)89 static llvm::ARM::FPUKind getARMFPUFeatures(const Driver &D, const Arg *A,
90 const ArgList &Args, StringRef FPU,
91 std::vector<StringRef> &Features) {
92 llvm::ARM::FPUKind FPUKind = llvm::ARM::parseFPU(FPU);
93 if (!llvm::ARM::getFPUFeatures(FPUKind, Features))
94 D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
95 return FPUKind;
96 }
97
98 // 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,llvm::ARM::FPUKind & ArgFPUKind)99 static bool DecodeARMFeatures(const Driver &D, StringRef text, StringRef CPU,
100 llvm::ARM::ArchKind ArchKind,
101 std::vector<StringRef> &Features,
102 llvm::ARM::FPUKind &ArgFPUKind) {
103 SmallVector<StringRef, 8> Split;
104 text.split(Split, StringRef("+"), -1, false);
105
106 for (StringRef Feature : Split) {
107 if (!appendArchExtFeatures(CPU, ArchKind, Feature, Features, ArgFPUKind))
108 return false;
109 }
110 return true;
111 }
112
DecodeARMFeaturesFromCPU(const Driver & D,StringRef CPU,std::vector<StringRef> & Features)113 static void DecodeARMFeaturesFromCPU(const Driver &D, StringRef CPU,
114 std::vector<StringRef> &Features) {
115 CPU = CPU.split("+").first;
116 if (CPU != "generic") {
117 llvm::ARM::ArchKind ArchKind = llvm::ARM::parseCPUArch(CPU);
118 uint64_t Extension = llvm::ARM::getDefaultExtensions(CPU, ArchKind);
119 llvm::ARM::getExtensionFeatures(Extension, Features);
120 }
121 }
122
123 // Check if -march is valid by checking if it can be canonicalised and parsed.
124 // getARMArch is used here instead of just checking the -march value in order
125 // 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,llvm::ARM::FPUKind & ArgFPUKind)126 static void checkARMArchName(const Driver &D, const Arg *A, const ArgList &Args,
127 llvm::StringRef ArchName, llvm::StringRef CPUName,
128 std::vector<StringRef> &Features,
129 const llvm::Triple &Triple,
130 llvm::ARM::FPUKind &ArgFPUKind) {
131 std::pair<StringRef, StringRef> Split = ArchName.split("+");
132
133 std::string MArch = arm::getARMArch(ArchName, Triple);
134 llvm::ARM::ArchKind ArchKind = llvm::ARM::parseArch(MArch);
135 if (ArchKind == llvm::ARM::ArchKind::INVALID ||
136 (Split.second.size() &&
137 !DecodeARMFeatures(D, Split.second, CPUName, ArchKind, Features,
138 ArgFPUKind)))
139 D.Diag(clang::diag::err_drv_unsupported_option_argument)
140 << A->getSpelling() << A->getValue();
141 }
142
143 // 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,llvm::ARM::FPUKind & ArgFPUKind)144 static void checkARMCPUName(const Driver &D, const Arg *A, const ArgList &Args,
145 llvm::StringRef CPUName, llvm::StringRef ArchName,
146 std::vector<StringRef> &Features,
147 const llvm::Triple &Triple,
148 llvm::ARM::FPUKind &ArgFPUKind) {
149 std::pair<StringRef, StringRef> Split = CPUName.split("+");
150
151 std::string CPU = arm::getARMTargetCPU(CPUName, ArchName, Triple);
152 llvm::ARM::ArchKind ArchKind =
153 arm::getLLVMArchKindForARM(CPU, ArchName, Triple);
154 if (ArchKind == llvm::ARM::ArchKind::INVALID ||
155 (Split.second.size() && !DecodeARMFeatures(D, Split.second, CPU, ArchKind,
156 Features, ArgFPUKind)))
157 D.Diag(clang::diag::err_drv_unsupported_option_argument)
158 << A->getSpelling() << A->getValue();
159 }
160
161 // If -mfloat-abi=hard or -mhard-float are specified explicitly then check that
162 // floating point registers are available on the target CPU.
checkARMFloatABI(const Driver & D,const ArgList & Args,bool HasFPRegs)163 static void checkARMFloatABI(const Driver &D, const ArgList &Args,
164 bool HasFPRegs) {
165 if (HasFPRegs)
166 return;
167 const Arg *A =
168 Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
169 options::OPT_mfloat_abi_EQ);
170 if (A && (A->getOption().matches(options::OPT_mhard_float) ||
171 (A->getOption().matches(options::OPT_mfloat_abi_EQ) &&
172 A->getValue() == StringRef("hard"))))
173 D.Diag(clang::diag::warn_drv_no_floating_point_registers)
174 << A->getAsString(Args);
175 }
176
useAAPCSForMachO(const llvm::Triple & T)177 bool arm::useAAPCSForMachO(const llvm::Triple &T) {
178 // The backend is hardwired to assume AAPCS for M-class processors, ensure
179 // the frontend matches that.
180 return T.getEnvironment() == llvm::Triple::EABI ||
181 T.getEnvironment() == llvm::Triple::EABIHF ||
182 T.getOS() == llvm::Triple::UnknownOS || isARMMProfile(T);
183 }
184
185 // We follow GCC and support when the backend has support for the MRC/MCR
186 // instructions that are used to set the hard thread pointer ("CP15 C13
187 // Thread id").
isHardTPSupported(const llvm::Triple & Triple)188 bool arm::isHardTPSupported(const llvm::Triple &Triple) {
189 int Ver = getARMSubArchVersionNumber(Triple);
190 llvm::ARM::ArchKind AK = llvm::ARM::parseArch(Triple.getArchName());
191 return Triple.isARM() || AK == llvm::ARM::ArchKind::ARMV6T2 ||
192 (Ver >= 7 && AK != llvm::ARM::ArchKind::ARMV8MBaseline);
193 }
194
195 // Select mode for reading thread pointer (-mtp=soft/cp15).
getReadTPMode(const Driver & D,const ArgList & Args,const llvm::Triple & Triple,bool ForAS)196 arm::ReadTPMode arm::getReadTPMode(const Driver &D, const ArgList &Args,
197 const llvm::Triple &Triple, bool ForAS) {
198 if (Arg *A = Args.getLastArg(options::OPT_mtp_mode_EQ)) {
199 arm::ReadTPMode ThreadPointer =
200 llvm::StringSwitch<arm::ReadTPMode>(A->getValue())
201 .Case("cp15", ReadTPMode::TPIDRURO)
202 .Case("tpidrurw", ReadTPMode::TPIDRURW)
203 .Case("tpidruro", ReadTPMode::TPIDRURO)
204 .Case("tpidrprw", ReadTPMode::TPIDRPRW)
205 .Case("soft", ReadTPMode::Soft)
206 .Default(ReadTPMode::Invalid);
207 if ((ThreadPointer == ReadTPMode::TPIDRURW ||
208 ThreadPointer == ReadTPMode::TPIDRURO ||
209 ThreadPointer == ReadTPMode::TPIDRPRW) &&
210 !isHardTPSupported(Triple) && !ForAS) {
211 D.Diag(diag::err_target_unsupported_tp_hard) << Triple.getArchName();
212 return ReadTPMode::Invalid;
213 }
214 if (ThreadPointer != ReadTPMode::Invalid)
215 return ThreadPointer;
216 if (StringRef(A->getValue()).empty())
217 D.Diag(diag::err_drv_missing_arg_mtp) << A->getAsString(Args);
218 else
219 D.Diag(diag::err_drv_invalid_mtp) << A->getAsString(Args);
220 return ReadTPMode::Invalid;
221 }
222 return ReadTPMode::Soft;
223 }
224
setArchNameInTriple(const Driver & D,const ArgList & Args,types::ID InputType,llvm::Triple & Triple)225 void arm::setArchNameInTriple(const Driver &D, const ArgList &Args,
226 types::ID InputType, llvm::Triple &Triple) {
227 StringRef MCPU, MArch;
228 if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
229 MCPU = A->getValue();
230 if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
231 MArch = A->getValue();
232
233 std::string CPU = Triple.isOSBinFormatMachO()
234 ? tools::arm::getARMCPUForMArch(MArch, Triple).str()
235 : tools::arm::getARMTargetCPU(MCPU, MArch, Triple);
236 StringRef Suffix = tools::arm::getLLVMArchSuffixForARM(CPU, MArch, Triple);
237
238 bool IsBigEndian = Triple.getArch() == llvm::Triple::armeb ||
239 Triple.getArch() == llvm::Triple::thumbeb;
240 // Handle pseudo-target flags '-mlittle-endian'/'-EL' and
241 // '-mbig-endian'/'-EB'.
242 if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
243 options::OPT_mbig_endian)) {
244 IsBigEndian = !A->getOption().matches(options::OPT_mlittle_endian);
245 }
246 std::string ArchName = IsBigEndian ? "armeb" : "arm";
247
248 // FIXME: Thumb should just be another -target-feaure, not in the triple.
249 bool IsMProfile =
250 llvm::ARM::parseArchProfile(Suffix) == llvm::ARM::ProfileKind::M;
251 bool ThumbDefault = IsMProfile ||
252 // Thumb2 is the default for V7 on Darwin.
253 (llvm::ARM::parseArchVersion(Suffix) == 7 &&
254 Triple.isOSBinFormatMachO()) ||
255 // FIXME: this is invalid for WindowsCE
256 Triple.isOSWindows();
257
258 // Check if ARM ISA was explicitly selected (using -mno-thumb or -marm) for
259 // M-Class CPUs/architecture variants, which is not supported.
260 bool ARMModeRequested =
261 !Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, ThumbDefault);
262 if (IsMProfile && ARMModeRequested) {
263 if (MCPU.size())
264 D.Diag(diag::err_cpu_unsupported_isa) << CPU << "ARM";
265 else
266 D.Diag(diag::err_arch_unsupported_isa)
267 << tools::arm::getARMArch(MArch, Triple) << "ARM";
268 }
269
270 // Check to see if an explicit choice to use thumb has been made via
271 // -mthumb. For assembler files we must check for -mthumb in the options
272 // passed to the assembler via -Wa or -Xassembler.
273 bool IsThumb = false;
274 if (InputType != types::TY_PP_Asm)
275 IsThumb =
276 Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, ThumbDefault);
277 else {
278 // Ideally we would check for these flags in
279 // CollectArgsForIntegratedAssembler but we can't change the ArchName at
280 // that point.
281 llvm::StringRef WaMArch, WaMCPU;
282 for (const auto *A :
283 Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {
284 for (StringRef Value : A->getValues()) {
285 // There is no assembler equivalent of -mno-thumb, -marm, or -mno-arm.
286 if (Value == "-mthumb")
287 IsThumb = true;
288 else if (Value.starts_with("-march="))
289 WaMArch = Value.substr(7);
290 else if (Value.starts_with("-mcpu="))
291 WaMCPU = Value.substr(6);
292 }
293 }
294
295 if (WaMCPU.size() || WaMArch.size()) {
296 // The way this works means that we prefer -Wa,-mcpu's architecture
297 // over -Wa,-march. Which matches the compiler behaviour.
298 Suffix = tools::arm::getLLVMArchSuffixForARM(WaMCPU, WaMArch, Triple);
299 }
300 }
301
302 // Assembly files should start in ARM mode, unless arch is M-profile, or
303 // -mthumb has been passed explicitly to the assembler. Windows is always
304 // thumb.
305 if (IsThumb || IsMProfile || Triple.isOSWindows()) {
306 if (IsBigEndian)
307 ArchName = "thumbeb";
308 else
309 ArchName = "thumb";
310 }
311 Triple.setArchName(ArchName + Suffix.str());
312 }
313
setFloatABIInTriple(const Driver & D,const ArgList & Args,llvm::Triple & Triple)314 void arm::setFloatABIInTriple(const Driver &D, const ArgList &Args,
315 llvm::Triple &Triple) {
316 if (Triple.isOSLiteOS()) {
317 Triple.setEnvironment(llvm::Triple::OpenHOS);
318 return;
319 }
320
321 bool isHardFloat =
322 (arm::getARMFloatABI(D, Triple, Args) == arm::FloatABI::Hard);
323
324 switch (Triple.getEnvironment()) {
325 case llvm::Triple::GNUEABI:
326 case llvm::Triple::GNUEABIHF:
327 Triple.setEnvironment(isHardFloat ? llvm::Triple::GNUEABIHF
328 : llvm::Triple::GNUEABI);
329 break;
330 case llvm::Triple::GNUEABIT64:
331 case llvm::Triple::GNUEABIHFT64:
332 Triple.setEnvironment(isHardFloat ? llvm::Triple::GNUEABIHFT64
333 : llvm::Triple::GNUEABIT64);
334 break;
335 case llvm::Triple::EABI:
336 case llvm::Triple::EABIHF:
337 Triple.setEnvironment(isHardFloat ? llvm::Triple::EABIHF
338 : llvm::Triple::EABI);
339 break;
340 case llvm::Triple::MuslEABI:
341 case llvm::Triple::MuslEABIHF:
342 Triple.setEnvironment(isHardFloat ? llvm::Triple::MuslEABIHF
343 : llvm::Triple::MuslEABI);
344 break;
345 case llvm::Triple::OpenHOS:
346 break;
347 default: {
348 arm::FloatABI DefaultABI = arm::getDefaultFloatABI(Triple);
349 if (DefaultABI != arm::FloatABI::Invalid &&
350 isHardFloat != (DefaultABI == arm::FloatABI::Hard)) {
351 Arg *ABIArg =
352 Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
353 options::OPT_mfloat_abi_EQ);
354 assert(ABIArg && "Non-default float abi expected to be from arg");
355 D.Diag(diag::err_drv_unsupported_opt_for_target)
356 << ABIArg->getAsString(Args) << Triple.getTriple();
357 }
358 break;
359 }
360 }
361 }
362
getARMFloatABI(const ToolChain & TC,const ArgList & Args)363 arm::FloatABI arm::getARMFloatABI(const ToolChain &TC, const ArgList &Args) {
364 return arm::getARMFloatABI(TC.getDriver(), TC.getEffectiveTriple(), Args);
365 }
366
getDefaultFloatABI(const llvm::Triple & Triple)367 arm::FloatABI arm::getDefaultFloatABI(const llvm::Triple &Triple) {
368 auto SubArch = getARMSubArchVersionNumber(Triple);
369 switch (Triple.getOS()) {
370 case llvm::Triple::Darwin:
371 case llvm::Triple::MacOSX:
372 case llvm::Triple::IOS:
373 case llvm::Triple::TvOS:
374 case llvm::Triple::DriverKit:
375 case llvm::Triple::XROS:
376 // Darwin defaults to "softfp" for v6 and v7.
377 if (Triple.isWatchABI())
378 return FloatABI::Hard;
379 else
380 return (SubArch == 6 || SubArch == 7) ? FloatABI::SoftFP : FloatABI::Soft;
381
382 case llvm::Triple::WatchOS:
383 return FloatABI::Hard;
384
385 // FIXME: this is invalid for WindowsCE
386 case llvm::Triple::Win32:
387 // It is incorrect to select hard float ABI on MachO platforms if the ABI is
388 // "apcs-gnu".
389 if (Triple.isOSBinFormatMachO() && !useAAPCSForMachO(Triple))
390 return FloatABI::Soft;
391 return FloatABI::Hard;
392
393 case llvm::Triple::NetBSD:
394 switch (Triple.getEnvironment()) {
395 case llvm::Triple::EABIHF:
396 case llvm::Triple::GNUEABIHF:
397 return FloatABI::Hard;
398 default:
399 return FloatABI::Soft;
400 }
401 break;
402
403 case llvm::Triple::FreeBSD:
404 switch (Triple.getEnvironment()) {
405 case llvm::Triple::GNUEABIHF:
406 return FloatABI::Hard;
407 default:
408 // FreeBSD defaults to soft float
409 return FloatABI::Soft;
410 }
411 break;
412
413 case llvm::Triple::Haiku:
414 case llvm::Triple::OpenBSD:
415 return FloatABI::SoftFP;
416
417 default:
418 if (Triple.isOHOSFamily())
419 return FloatABI::Soft;
420 switch (Triple.getEnvironment()) {
421 case llvm::Triple::GNUEABIHF:
422 case llvm::Triple::GNUEABIHFT64:
423 case llvm::Triple::MuslEABIHF:
424 case llvm::Triple::EABIHF:
425 return FloatABI::Hard;
426 case llvm::Triple::GNUEABI:
427 case llvm::Triple::GNUEABIT64:
428 case llvm::Triple::MuslEABI:
429 case llvm::Triple::EABI:
430 // EABI is always AAPCS, and if it was not marked 'hard', it's softfp
431 return FloatABI::SoftFP;
432 case llvm::Triple::Android:
433 return (SubArch >= 7) ? FloatABI::SoftFP : FloatABI::Soft;
434 default:
435 return FloatABI::Invalid;
436 }
437 }
438 return FloatABI::Invalid;
439 }
440
441 // Select the float ABI as determined by -msoft-float, -mhard-float, and
442 // -mfloat-abi=.
getARMFloatABI(const Driver & D,const llvm::Triple & Triple,const ArgList & Args)443 arm::FloatABI arm::getARMFloatABI(const Driver &D, const llvm::Triple &Triple,
444 const ArgList &Args) {
445 arm::FloatABI ABI = FloatABI::Invalid;
446 if (Arg *A =
447 Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
448 options::OPT_mfloat_abi_EQ)) {
449 if (A->getOption().matches(options::OPT_msoft_float)) {
450 ABI = FloatABI::Soft;
451 } else if (A->getOption().matches(options::OPT_mhard_float)) {
452 ABI = FloatABI::Hard;
453 } else {
454 ABI = llvm::StringSwitch<arm::FloatABI>(A->getValue())
455 .Case("soft", FloatABI::Soft)
456 .Case("softfp", FloatABI::SoftFP)
457 .Case("hard", FloatABI::Hard)
458 .Default(FloatABI::Invalid);
459 if (ABI == FloatABI::Invalid && !StringRef(A->getValue()).empty()) {
460 D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
461 ABI = FloatABI::Soft;
462 }
463 }
464 }
465
466 // If unspecified, choose the default based on the platform.
467 if (ABI == FloatABI::Invalid)
468 ABI = arm::getDefaultFloatABI(Triple);
469
470 if (ABI == FloatABI::Invalid) {
471 // Assume "soft", but warn the user we are guessing.
472 if (Triple.isOSBinFormatMachO() &&
473 Triple.getSubArch() == llvm::Triple::ARMSubArch_v7em)
474 ABI = FloatABI::Hard;
475 else
476 ABI = FloatABI::Soft;
477
478 if (Triple.getOS() != llvm::Triple::UnknownOS ||
479 !Triple.isOSBinFormatMachO())
480 D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft";
481 }
482
483 assert(ABI != FloatABI::Invalid && "must select an ABI");
484 return ABI;
485 }
486
hasIntegerMVE(const std::vector<StringRef> & F)487 static bool hasIntegerMVE(const std::vector<StringRef> &F) {
488 auto MVE = llvm::find(llvm::reverse(F), "+mve");
489 auto NoMVE = llvm::find(llvm::reverse(F), "-mve");
490 return MVE != F.rend() &&
491 (NoMVE == F.rend() || std::distance(MVE, NoMVE) > 0);
492 }
493
getARMTargetFeatures(const Driver & D,const llvm::Triple & Triple,const ArgList & Args,std::vector<StringRef> & Features,bool ForAS,bool ForMultilib)494 llvm::ARM::FPUKind arm::getARMTargetFeatures(const Driver &D,
495 const llvm::Triple &Triple,
496 const ArgList &Args,
497 std::vector<StringRef> &Features,
498 bool ForAS, bool ForMultilib) {
499 bool KernelOrKext =
500 Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
501 arm::FloatABI ABI = arm::getARMFloatABI(D, Triple, Args);
502 std::optional<std::pair<const Arg *, StringRef>> WaCPU, WaFPU, WaHDiv, WaArch;
503
504 // This vector will accumulate features from the architecture
505 // extension suffixes on -mcpu and -march (e.g. the 'bar' in
506 // -mcpu=foo+bar). We want to apply those after the features derived
507 // from the FPU, in case -mfpu generates a negative feature which
508 // the +bar is supposed to override.
509 std::vector<StringRef> ExtensionFeatures;
510
511 if (!ForAS) {
512 // FIXME: Note, this is a hack, the LLVM backend doesn't actually use these
513 // yet (it uses the -mfloat-abi and -msoft-float options), and it is
514 // stripped out by the ARM target. We should probably pass this a new
515 // -target-option, which is handled by the -cc1/-cc1as invocation.
516 //
517 // FIXME2: For consistency, it would be ideal if we set up the target
518 // machine state the same when using the frontend or the assembler. We don't
519 // currently do that for the assembler, we pass the options directly to the
520 // backend and never even instantiate the frontend TargetInfo. If we did,
521 // and used its handleTargetFeatures hook, then we could ensure the
522 // assembler and the frontend behave the same.
523
524 // Use software floating point operations?
525 if (ABI == arm::FloatABI::Soft)
526 Features.push_back("+soft-float");
527
528 // Use software floating point argument passing?
529 if (ABI != arm::FloatABI::Hard)
530 Features.push_back("+soft-float-abi");
531 } else {
532 // Here, we make sure that -Wa,-mfpu/cpu/arch/hwdiv will be passed down
533 // to the assembler correctly.
534 for (const Arg *A :
535 Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {
536 // We use getValues here because you can have many options per -Wa
537 // We will keep the last one we find for each of these
538 for (StringRef Value : A->getValues()) {
539 if (Value.starts_with("-mfpu=")) {
540 WaFPU = std::make_pair(A, Value.substr(6));
541 } else if (Value.starts_with("-mcpu=")) {
542 WaCPU = std::make_pair(A, Value.substr(6));
543 } else if (Value.starts_with("-mhwdiv=")) {
544 WaHDiv = std::make_pair(A, Value.substr(8));
545 } else if (Value.starts_with("-march=")) {
546 WaArch = std::make_pair(A, Value.substr(7));
547 }
548 }
549 }
550
551 // The integrated assembler doesn't implement e_flags setting behavior for
552 // -meabi=gnu (gcc -mabi={apcs-gnu,atpcs} passes -meabi=gnu to gas). For
553 // compatibility we accept but warn.
554 if (Arg *A = Args.getLastArgNoClaim(options::OPT_mabi_EQ))
555 A->ignoreTargetSpecific();
556 }
557
558 if (getReadTPMode(D, Args, Triple, ForAS) == ReadTPMode::TPIDRURW)
559 Features.push_back("+read-tp-tpidrurw");
560 if (getReadTPMode(D, Args, Triple, ForAS) == ReadTPMode::TPIDRURO)
561 Features.push_back("+read-tp-tpidruro");
562 if (getReadTPMode(D, Args, Triple, ForAS) == ReadTPMode::TPIDRPRW)
563 Features.push_back("+read-tp-tpidrprw");
564
565 const Arg *ArchArg = Args.getLastArg(options::OPT_march_EQ);
566 const Arg *CPUArg = Args.getLastArg(options::OPT_mcpu_EQ);
567 StringRef ArchName;
568 StringRef CPUName;
569 llvm::ARM::FPUKind ArchArgFPUKind = llvm::ARM::FK_INVALID;
570 llvm::ARM::FPUKind CPUArgFPUKind = llvm::ARM::FK_INVALID;
571
572 // Check -mcpu. ClangAs gives preference to -Wa,-mcpu=.
573 if (WaCPU) {
574 if (CPUArg)
575 D.Diag(clang::diag::warn_drv_unused_argument)
576 << CPUArg->getAsString(Args);
577 CPUName = WaCPU->second;
578 CPUArg = WaCPU->first;
579 } else if (CPUArg)
580 CPUName = CPUArg->getValue();
581
582 // Check -march. ClangAs gives preference to -Wa,-march=.
583 if (WaArch) {
584 if (ArchArg)
585 D.Diag(clang::diag::warn_drv_unused_argument)
586 << ArchArg->getAsString(Args);
587 ArchName = WaArch->second;
588 // This will set any features after the base architecture.
589 checkARMArchName(D, WaArch->first, Args, ArchName, CPUName,
590 ExtensionFeatures, Triple, ArchArgFPUKind);
591 // The base architecture was handled in ToolChain::ComputeLLVMTriple because
592 // triple is read only by this point.
593 } else if (ArchArg) {
594 ArchName = ArchArg->getValue();
595 checkARMArchName(D, ArchArg, Args, ArchName, CPUName, ExtensionFeatures,
596 Triple, ArchArgFPUKind);
597 }
598
599 // Add CPU features for generic CPUs
600 if (CPUName == "native") {
601 for (auto &F : llvm::sys::getHostCPUFeatures())
602 Features.push_back(
603 Args.MakeArgString((F.second ? "+" : "-") + F.first()));
604 } else if (!CPUName.empty()) {
605 // This sets the default features for the specified CPU. We certainly don't
606 // want to override the features that have been explicitly specified on the
607 // command line. Therefore, process them directly instead of appending them
608 // at the end later.
609 DecodeARMFeaturesFromCPU(D, CPUName, Features);
610 }
611
612 if (CPUArg)
613 checkARMCPUName(D, CPUArg, Args, CPUName, ArchName, ExtensionFeatures,
614 Triple, CPUArgFPUKind);
615
616 // TODO Handle -mtune=. Suppress -Wunused-command-line-argument as a
617 // longstanding behavior.
618 (void)Args.getLastArg(options::OPT_mtune_EQ);
619
620 // Honor -mfpu=. ClangAs gives preference to -Wa,-mfpu=.
621 llvm::ARM::FPUKind FPUKind = llvm::ARM::FK_INVALID;
622 const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ);
623 if (WaFPU) {
624 if (FPUArg)
625 D.Diag(clang::diag::warn_drv_unused_argument)
626 << FPUArg->getAsString(Args);
627 (void)getARMFPUFeatures(D, WaFPU->first, Args, WaFPU->second, Features);
628 } else if (FPUArg) {
629 FPUKind = getARMFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features);
630 } else if (Triple.isAndroid() && getARMSubArchVersionNumber(Triple) >= 7) {
631 const char *AndroidFPU = "neon";
632 FPUKind = llvm::ARM::parseFPU(AndroidFPU);
633 if (!llvm::ARM::getFPUFeatures(FPUKind, Features))
634 D.Diag(clang::diag::err_drv_clang_unsupported)
635 << std::string("-mfpu=") + AndroidFPU;
636 } else if (ArchArgFPUKind != llvm::ARM::FK_INVALID ||
637 CPUArgFPUKind != llvm::ARM::FK_INVALID) {
638 FPUKind =
639 CPUArgFPUKind != llvm::ARM::FK_INVALID ? CPUArgFPUKind : ArchArgFPUKind;
640 (void)llvm::ARM::getFPUFeatures(FPUKind, Features);
641 } else {
642 if (!ForAS) {
643 std::string CPU = arm::getARMTargetCPU(CPUName, ArchName, Triple);
644 llvm::ARM::ArchKind ArchKind =
645 arm::getLLVMArchKindForARM(CPU, ArchName, Triple);
646 FPUKind = llvm::ARM::getDefaultFPU(CPU, ArchKind);
647 (void)llvm::ARM::getFPUFeatures(FPUKind, Features);
648 }
649 }
650
651 // Now we've finished accumulating features from arch, cpu and fpu,
652 // we can append the ones for architecture extensions that we
653 // collected separately.
654 Features.insert(std::end(Features),
655 std::begin(ExtensionFeatures), std::end(ExtensionFeatures));
656
657 // Honor -mhwdiv=. ClangAs gives preference to -Wa,-mhwdiv=.
658 const Arg *HDivArg = Args.getLastArg(options::OPT_mhwdiv_EQ);
659 if (WaHDiv) {
660 if (HDivArg)
661 D.Diag(clang::diag::warn_drv_unused_argument)
662 << HDivArg->getAsString(Args);
663 getARMHWDivFeatures(D, WaHDiv->first, Args, WaHDiv->second, Features);
664 } else if (HDivArg)
665 getARMHWDivFeatures(D, HDivArg, Args, HDivArg->getValue(), Features);
666
667 // Handle (arch-dependent) fp16fml/fullfp16 relationship.
668 // Must happen before any features are disabled due to soft-float.
669 // FIXME: this fp16fml option handling will be reimplemented after the
670 // TargetParser rewrite.
671 const auto ItRNoFullFP16 = std::find(Features.rbegin(), Features.rend(), "-fullfp16");
672 const auto ItRFP16FML = std::find(Features.rbegin(), Features.rend(), "+fp16fml");
673 if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8_4a) {
674 const auto ItRFullFP16 = std::find(Features.rbegin(), Features.rend(), "+fullfp16");
675 if (ItRFullFP16 < ItRNoFullFP16 && ItRFullFP16 < ItRFP16FML) {
676 // Only entangled feature that can be to the right of this +fullfp16 is -fp16fml.
677 // Only append the +fp16fml if there is no -fp16fml after the +fullfp16.
678 if (std::find(Features.rbegin(), ItRFullFP16, "-fp16fml") == ItRFullFP16)
679 Features.push_back("+fp16fml");
680 }
681 else
682 goto fp16_fml_fallthrough;
683 }
684 else {
685 fp16_fml_fallthrough:
686 // In both of these cases, putting the 'other' feature on the end of the vector will
687 // result in the same effect as placing it immediately after the current feature.
688 if (ItRNoFullFP16 < ItRFP16FML)
689 Features.push_back("-fp16fml");
690 else if (ItRNoFullFP16 > ItRFP16FML)
691 Features.push_back("+fullfp16");
692 }
693
694 // Setting -msoft-float/-mfloat-abi=soft, -mfpu=none, or adding +nofp to
695 // -march/-mcpu effectively disables the FPU (GCC ignores the -mfpu options in
696 // this case). Note that the ABI can also be set implicitly by the target
697 // selected.
698 bool HasFPRegs = true;
699 if (ABI == arm::FloatABI::Soft) {
700 llvm::ARM::getFPUFeatures(llvm::ARM::FK_NONE, Features);
701
702 // Disable all features relating to hardware FP, not already disabled by the
703 // above call.
704 Features.insert(Features.end(),
705 {"-dotprod", "-fp16fml", "-bf16", "-mve", "-mve.fp"});
706 HasFPRegs = false;
707 FPUKind = llvm::ARM::FK_NONE;
708 } else if (FPUKind == llvm::ARM::FK_NONE ||
709 ArchArgFPUKind == llvm::ARM::FK_NONE ||
710 CPUArgFPUKind == llvm::ARM::FK_NONE) {
711 // -mfpu=none, -march=armvX+nofp or -mcpu=X+nofp is *very* similar to
712 // -mfloat-abi=soft, only that it should not disable MVE-I. They disable the
713 // FPU, but not the FPU registers, thus MVE-I, which depends only on the
714 // latter, is still supported.
715 Features.insert(Features.end(),
716 {"-dotprod", "-fp16fml", "-bf16", "-mve.fp"});
717 HasFPRegs = hasIntegerMVE(Features);
718 FPUKind = llvm::ARM::FK_NONE;
719 }
720 if (!HasFPRegs)
721 Features.emplace_back("-fpregs");
722
723 // En/disable crc code generation.
724 if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) {
725 if (A->getOption().matches(options::OPT_mcrc))
726 Features.push_back("+crc");
727 else
728 Features.push_back("-crc");
729 }
730
731 // For Arch >= ARMv8.0 && A or R profile: crypto = sha2 + aes
732 // Rather than replace within the feature vector, determine whether each
733 // algorithm is enabled and append this to the end of the vector.
734 // The algorithms can be controlled by their specific feature or the crypto
735 // feature, so their status can be determined by the last occurance of
736 // either in the vector. This allows one to supercede the other.
737 // e.g. +crypto+noaes in -march/-mcpu should enable sha2, but not aes
738 // FIXME: this needs reimplementation after the TargetParser rewrite
739 bool HasSHA2 = false;
740 bool HasAES = false;
741 const auto ItCrypto =
742 llvm::find_if(llvm::reverse(Features), [](const StringRef F) {
743 return F.contains("crypto");
744 });
745 const auto ItSHA2 =
746 llvm::find_if(llvm::reverse(Features), [](const StringRef F) {
747 return F.contains("crypto") || F.contains("sha2");
748 });
749 const auto ItAES =
750 llvm::find_if(llvm::reverse(Features), [](const StringRef F) {
751 return F.contains("crypto") || F.contains("aes");
752 });
753 const bool FoundSHA2 = ItSHA2 != Features.rend();
754 const bool FoundAES = ItAES != Features.rend();
755 if (FoundSHA2)
756 HasSHA2 = ItSHA2->take_front() == "+";
757 if (FoundAES)
758 HasAES = ItAES->take_front() == "+";
759 if (ItCrypto != Features.rend()) {
760 if (HasSHA2 && HasAES)
761 Features.push_back("+crypto");
762 else
763 Features.push_back("-crypto");
764 if (HasSHA2)
765 Features.push_back("+sha2");
766 else
767 Features.push_back("-sha2");
768 if (HasAES)
769 Features.push_back("+aes");
770 else
771 Features.push_back("-aes");
772 }
773
774 if (HasSHA2 || HasAES) {
775 StringRef ArchSuffix = arm::getLLVMArchSuffixForARM(
776 arm::getARMTargetCPU(CPUName, ArchName, Triple), ArchName, Triple);
777 llvm::ARM::ProfileKind ArchProfile =
778 llvm::ARM::parseArchProfile(ArchSuffix);
779 if (!((llvm::ARM::parseArchVersion(ArchSuffix) >= 8) &&
780 (ArchProfile == llvm::ARM::ProfileKind::A ||
781 ArchProfile == llvm::ARM::ProfileKind::R))) {
782 if (HasSHA2)
783 D.Diag(clang::diag::warn_target_unsupported_extension)
784 << "sha2"
785 << llvm::ARM::getArchName(llvm::ARM::parseArch(ArchSuffix));
786 if (HasAES)
787 D.Diag(clang::diag::warn_target_unsupported_extension)
788 << "aes"
789 << llvm::ARM::getArchName(llvm::ARM::parseArch(ArchSuffix));
790 // With -fno-integrated-as -mfpu=crypto-neon-fp-armv8 some assemblers such
791 // as the GNU assembler will permit the use of crypto instructions as the
792 // fpu will override the architecture. We keep the crypto feature in this
793 // case to preserve compatibility. In all other cases we remove the crypto
794 // feature.
795 if (!Args.hasArg(options::OPT_fno_integrated_as)) {
796 Features.push_back("-sha2");
797 Features.push_back("-aes");
798 }
799 }
800 }
801
802 // Propagate frame-chain model selection
803 if (Arg *A = Args.getLastArg(options::OPT_mframe_chain)) {
804 StringRef FrameChainOption = A->getValue();
805 if (FrameChainOption.starts_with("aapcs"))
806 Features.push_back("+aapcs-frame-chain");
807 }
808
809 // CMSE: Check for target 8M (for -mcmse to be applicable) is performed later.
810 if (Args.getLastArg(options::OPT_mcmse))
811 Features.push_back("+8msecext");
812
813 if (Arg *A = Args.getLastArg(options::OPT_mfix_cmse_cve_2021_35465,
814 options::OPT_mno_fix_cmse_cve_2021_35465)) {
815 if (!Args.getLastArg(options::OPT_mcmse))
816 D.Diag(diag::err_opt_not_valid_without_opt)
817 << A->getOption().getName() << "-mcmse";
818
819 if (A->getOption().matches(options::OPT_mfix_cmse_cve_2021_35465))
820 Features.push_back("+fix-cmse-cve-2021-35465");
821 else
822 Features.push_back("-fix-cmse-cve-2021-35465");
823 }
824
825 // This also handles the -m(no-)fix-cortex-a72-1655431 arguments via aliases.
826 if (Arg *A = Args.getLastArg(options::OPT_mfix_cortex_a57_aes_1742098,
827 options::OPT_mno_fix_cortex_a57_aes_1742098)) {
828 if (A->getOption().matches(options::OPT_mfix_cortex_a57_aes_1742098)) {
829 Features.push_back("+fix-cortex-a57-aes-1742098");
830 } else {
831 Features.push_back("-fix-cortex-a57-aes-1742098");
832 }
833 }
834
835 // Look for the last occurrence of -mlong-calls or -mno-long-calls. If
836 // neither options are specified, see if we are compiling for kernel/kext and
837 // decide whether to pass "+long-calls" based on the OS and its version.
838 if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,
839 options::OPT_mno_long_calls)) {
840 if (A->getOption().matches(options::OPT_mlong_calls))
841 Features.push_back("+long-calls");
842 } else if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6)) &&
843 !Triple.isWatchOS() && !Triple.isXROS()) {
844 Features.push_back("+long-calls");
845 }
846
847 // Generate execute-only output (no data access to code sections).
848 // This only makes sense for the compiler, not for the assembler.
849 // It's not needed for multilib selection and may hide an unused
850 // argument diagnostic if the code is always run.
851 if (!ForAS && !ForMultilib) {
852 // Supported only on ARMv6T2 and ARMv7 and above.
853 // Cannot be combined with -mno-movt.
854 if (Arg *A = Args.getLastArg(options::OPT_mexecute_only, options::OPT_mno_execute_only)) {
855 if (A->getOption().matches(options::OPT_mexecute_only)) {
856 if (getARMSubArchVersionNumber(Triple) < 7 &&
857 llvm::ARM::parseArch(Triple.getArchName()) != llvm::ARM::ArchKind::ARMV6T2 &&
858 llvm::ARM::parseArch(Triple.getArchName()) != llvm::ARM::ArchKind::ARMV6M)
859 D.Diag(diag::err_target_unsupported_execute_only) << Triple.getArchName();
860 else if (llvm::ARM::parseArch(Triple.getArchName()) == llvm::ARM::ArchKind::ARMV6M) {
861 if (Arg *PIArg = Args.getLastArg(options::OPT_fropi, options::OPT_frwpi,
862 options::OPT_fpic, options::OPT_fpie,
863 options::OPT_fPIC, options::OPT_fPIE))
864 D.Diag(diag::err_opt_not_valid_with_opt_on_target)
865 << A->getAsString(Args) << PIArg->getAsString(Args) << Triple.getArchName();
866 } else if (Arg *B = Args.getLastArg(options::OPT_mno_movt))
867 D.Diag(diag::err_opt_not_valid_with_opt)
868 << A->getAsString(Args) << B->getAsString(Args);
869 Features.push_back("+execute-only");
870 }
871 }
872 }
873
874 if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
875 options::OPT_munaligned_access,
876 options::OPT_mstrict_align,
877 options::OPT_mno_strict_align)) {
878 // Kernel code has more strict alignment requirements.
879 if (KernelOrKext ||
880 A->getOption().matches(options::OPT_mno_unaligned_access) ||
881 A->getOption().matches(options::OPT_mstrict_align)) {
882 Features.push_back("+strict-align");
883 } else {
884 // No v6M core supports unaligned memory access (v6M ARM ARM A3.2).
885 if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m)
886 D.Diag(diag::err_target_unsupported_unaligned) << "v6m";
887 // v8M Baseline follows on from v6M, so doesn't support unaligned memory
888 // access either.
889 else if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8m_baseline)
890 D.Diag(diag::err_target_unsupported_unaligned) << "v8m.base";
891 }
892 } else {
893 // Assume pre-ARMv6 doesn't support unaligned accesses.
894 //
895 // ARMv6 may or may not support unaligned accesses depending on the
896 // SCTLR.U bit, which is architecture-specific. We assume ARMv6
897 // Darwin and NetBSD targets support unaligned accesses, and others don't.
898 //
899 // ARMv7 always has SCTLR.U set to 1, but it has a new SCTLR.A bit which
900 // raises an alignment fault on unaligned accesses. Assume ARMv7+ supports
901 // unaligned accesses, except ARMv6-M, and ARMv8-M without the Main
902 // Extension. This aligns with the default behavior of ARM's downstream
903 // versions of GCC and Clang.
904 //
905 // Users can change the default behavior via -m[no-]unaliged-access.
906 int VersionNum = getARMSubArchVersionNumber(Triple);
907 if (Triple.isOSDarwin() || Triple.isOSNetBSD()) {
908 if (VersionNum < 6 ||
909 Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m)
910 Features.push_back("+strict-align");
911 } else if (VersionNum < 7 ||
912 Triple.getSubArch() ==
913 llvm::Triple::SubArchType::ARMSubArch_v6m ||
914 Triple.getSubArch() ==
915 llvm::Triple::SubArchType::ARMSubArch_v8m_baseline) {
916 Features.push_back("+strict-align");
917 }
918 }
919
920 // llvm does not support reserving registers in general. There is support
921 // for reserving r9 on ARM though (defined as a platform-specific register
922 // in ARM EABI).
923 if (Args.hasArg(options::OPT_ffixed_r9))
924 Features.push_back("+reserve-r9");
925
926 // The kext linker doesn't know how to deal with movw/movt.
927 if (KernelOrKext || Args.hasArg(options::OPT_mno_movt))
928 Features.push_back("+no-movt");
929
930 if (Args.hasArg(options::OPT_mno_neg_immediates))
931 Features.push_back("+no-neg-immediates");
932
933 // Enable/disable straight line speculation hardening.
934 if (Arg *A = Args.getLastArg(options::OPT_mharden_sls_EQ)) {
935 StringRef Scope = A->getValue();
936 bool EnableRetBr = false;
937 bool EnableBlr = false;
938 bool DisableComdat = false;
939 if (Scope != "none") {
940 SmallVector<StringRef, 4> Opts;
941 Scope.split(Opts, ",");
942 for (auto Opt : Opts) {
943 Opt = Opt.trim();
944 if (Opt == "all") {
945 EnableBlr = true;
946 EnableRetBr = true;
947 continue;
948 }
949 if (Opt == "retbr") {
950 EnableRetBr = true;
951 continue;
952 }
953 if (Opt == "blr") {
954 EnableBlr = true;
955 continue;
956 }
957 if (Opt == "comdat") {
958 DisableComdat = false;
959 continue;
960 }
961 if (Opt == "nocomdat") {
962 DisableComdat = true;
963 continue;
964 }
965 D.Diag(diag::err_drv_unsupported_option_argument)
966 << A->getSpelling() << Scope;
967 break;
968 }
969 }
970
971 if (EnableRetBr || EnableBlr)
972 if (!(isARMAProfile(Triple) && getARMSubArchVersionNumber(Triple) >= 7))
973 D.Diag(diag::err_sls_hardening_arm_not_supported)
974 << Scope << A->getAsString(Args);
975
976 if (EnableRetBr)
977 Features.push_back("+harden-sls-retbr");
978 if (EnableBlr)
979 Features.push_back("+harden-sls-blr");
980 if (DisableComdat) {
981 Features.push_back("+harden-sls-nocomdat");
982 }
983 }
984
985 if (Args.getLastArg(options::OPT_mno_bti_at_return_twice))
986 Features.push_back("+no-bti-at-return-twice");
987
988 checkARMFloatABI(D, Args, HasFPRegs);
989
990 return FPUKind;
991 }
992
getARMArch(StringRef Arch,const llvm::Triple & Triple)993 std::string arm::getARMArch(StringRef Arch, const llvm::Triple &Triple) {
994 std::string MArch;
995 if (!Arch.empty())
996 MArch = std::string(Arch);
997 else
998 MArch = std::string(Triple.getArchName());
999 MArch = StringRef(MArch).split("+").first.lower();
1000
1001 // Handle -march=native.
1002 if (MArch == "native") {
1003 std::string CPU = std::string(llvm::sys::getHostCPUName());
1004 if (CPU != "generic") {
1005 // Translate the native cpu into the architecture suffix for that CPU.
1006 StringRef Suffix = arm::getLLVMArchSuffixForARM(CPU, MArch, Triple);
1007 // If there is no valid architecture suffix for this CPU we don't know how
1008 // to handle it, so return no architecture.
1009 if (Suffix.empty())
1010 MArch = "";
1011 else
1012 MArch = std::string("arm") + Suffix.str();
1013 }
1014 }
1015
1016 return MArch;
1017 }
1018
1019 /// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting.
getARMCPUForMArch(StringRef Arch,const llvm::Triple & Triple)1020 StringRef arm::getARMCPUForMArch(StringRef Arch, const llvm::Triple &Triple) {
1021 std::string MArch = getARMArch(Arch, Triple);
1022 // getARMCPUForArch defaults to the triple if MArch is empty, but empty MArch
1023 // here means an -march=native that we can't handle, so instead return no CPU.
1024 if (MArch.empty())
1025 return StringRef();
1026
1027 // We need to return an empty string here on invalid MArch values as the
1028 // various places that call this function can't cope with a null result.
1029 return llvm::ARM::getARMCPUForArch(Triple, MArch);
1030 }
1031
1032 /// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting.
getARMTargetCPU(StringRef CPU,StringRef Arch,const llvm::Triple & Triple)1033 std::string arm::getARMTargetCPU(StringRef CPU, StringRef Arch,
1034 const llvm::Triple &Triple) {
1035 // FIXME: Warn on inconsistent use of -mcpu and -march.
1036 // If we have -mcpu=, use that.
1037 if (!CPU.empty()) {
1038 std::string MCPU = StringRef(CPU).split("+").first.lower();
1039 // Handle -mcpu=native.
1040 if (MCPU == "native")
1041 return std::string(llvm::sys::getHostCPUName());
1042 else
1043 return MCPU;
1044 }
1045
1046 return std::string(getARMCPUForMArch(Arch, Triple));
1047 }
1048
1049 /// getLLVMArchSuffixForARM - Get the LLVM ArchKind value to use for a
1050 /// particular CPU (or Arch, if CPU is generic). This is needed to
1051 /// pass to functions like llvm::ARM::getDefaultFPU which need an
1052 /// ArchKind as well as a CPU name.
getLLVMArchKindForARM(StringRef CPU,StringRef Arch,const llvm::Triple & Triple)1053 llvm::ARM::ArchKind arm::getLLVMArchKindForARM(StringRef CPU, StringRef Arch,
1054 const llvm::Triple &Triple) {
1055 llvm::ARM::ArchKind ArchKind;
1056 if (CPU == "generic" || CPU.empty()) {
1057 std::string ARMArch = tools::arm::getARMArch(Arch, Triple);
1058 ArchKind = llvm::ARM::parseArch(ARMArch);
1059 if (ArchKind == llvm::ARM::ArchKind::INVALID)
1060 // In case of generic Arch, i.e. "arm",
1061 // extract arch from default cpu of the Triple
1062 ArchKind =
1063 llvm::ARM::parseCPUArch(llvm::ARM::getARMCPUForArch(Triple, ARMArch));
1064 } else {
1065 // FIXME: horrible hack to get around the fact that Cortex-A7 is only an
1066 // armv7k triple if it's actually been specified via "-arch armv7k".
1067 ArchKind = (Arch == "armv7k" || Arch == "thumbv7k")
1068 ? llvm::ARM::ArchKind::ARMV7K
1069 : llvm::ARM::parseCPUArch(CPU);
1070 }
1071 return ArchKind;
1072 }
1073
1074 /// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular
1075 /// CPU (or Arch, if CPU is generic).
1076 // FIXME: This is redundant with -mcpu, why does LLVM use this.
getLLVMArchSuffixForARM(StringRef CPU,StringRef Arch,const llvm::Triple & Triple)1077 StringRef arm::getLLVMArchSuffixForARM(StringRef CPU, StringRef Arch,
1078 const llvm::Triple &Triple) {
1079 llvm::ARM::ArchKind ArchKind = getLLVMArchKindForARM(CPU, Arch, Triple);
1080 if (ArchKind == llvm::ARM::ArchKind::INVALID)
1081 return "";
1082 return llvm::ARM::getSubArch(ArchKind);
1083 }
1084
appendBE8LinkFlag(const ArgList & Args,ArgStringList & CmdArgs,const llvm::Triple & Triple)1085 void arm::appendBE8LinkFlag(const ArgList &Args, ArgStringList &CmdArgs,
1086 const llvm::Triple &Triple) {
1087 if (Args.hasArg(options::OPT_r))
1088 return;
1089
1090 // ARMv7 (and later) and ARMv6-M do not support BE-32, so instruct the linker
1091 // to generate BE-8 executables.
1092 if (arm::getARMSubArchVersionNumber(Triple) >= 7 || arm::isARMMProfile(Triple))
1093 CmdArgs.push_back("--be8");
1094 }
1095