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