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