AArch64TargetParser.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. //===-- AArch64TargetParser - Parser for AArch64 features -------*- 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. // This file implements a target parser to recognise AArch64 hardware features
  10. // such as FPU/CPU/ARCH and extension names.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm/TargetParser/AArch64TargetParser.h"
  14. #include "llvm/ADT/StringSwitch.h"
  15. #include "llvm/TargetParser/ARMTargetParserCommon.h"
  16. #include "llvm/TargetParser/Triple.h"
  17. #include <cctype>
  18. using namespace llvm;
  19. static unsigned checkArchVersion(llvm::StringRef Arch) {
  20. if (Arch.size() >= 2 && Arch[0] == 'v' && std::isdigit(Arch[1]))
  21. return (Arch[1] - 48);
  22. return 0;
  23. }
  24. uint64_t AArch64::getDefaultExtensions(StringRef CPU,
  25. const AArch64::ArchInfo &AI) {
  26. if (CPU == "generic")
  27. return AI.DefaultExts;
  28. // Note: this now takes cpu aliases into account
  29. const CpuInfo &Cpu = parseCpu(CPU);
  30. return Cpu.Arch.DefaultExts | Cpu.DefaultExtensions;
  31. }
  32. void AArch64::getFeatureOption(StringRef Name, std::string &Feature) {
  33. for (const auto &E : llvm::AArch64::Extensions) {
  34. if (Name == E.Name) {
  35. Feature = E.Feature;
  36. return;
  37. }
  38. }
  39. Feature = Name.str();
  40. }
  41. const AArch64::ArchInfo &AArch64::getArchForCpu(StringRef CPU) {
  42. if (CPU == "generic")
  43. return ARMV8A;
  44. // Note: this now takes cpu aliases into account
  45. const CpuInfo &Cpu = parseCpu(CPU);
  46. return Cpu.Arch;
  47. }
  48. const AArch64::ArchInfo &AArch64::ArchInfo::findBySubArch(StringRef SubArch) {
  49. for (const auto *A : AArch64::ArchInfos)
  50. if (A->getSubArch() == SubArch)
  51. return *A;
  52. return AArch64::INVALID;
  53. }
  54. uint64_t AArch64::getCpuSupportsMask(ArrayRef<StringRef> FeatureStrs) {
  55. uint64_t FeaturesMask = 0;
  56. for (const StringRef &FeatureStr : FeatureStrs) {
  57. for (const auto &E : llvm::AArch64::Extensions)
  58. if (FeatureStr == E.Name) {
  59. FeaturesMask |= (1ULL << E.CPUFeature);
  60. break;
  61. }
  62. }
  63. return FeaturesMask;
  64. }
  65. bool AArch64::getExtensionFeatures(uint64_t InputExts,
  66. std::vector<StringRef> &Features) {
  67. if (InputExts == AArch64::AEK_INVALID)
  68. return false;
  69. for (const auto &E : Extensions)
  70. /* INVALID and NONE have no feature name. */
  71. if ((InputExts & E.ID) && !E.Feature.empty())
  72. Features.push_back(E.Feature);
  73. return true;
  74. }
  75. StringRef AArch64::resolveCPUAlias(StringRef Name) {
  76. for (const auto &A : CpuAliases)
  77. if (A.Alias == Name)
  78. return A.Name;
  79. return Name;
  80. }
  81. StringRef AArch64::getArchExtFeature(StringRef ArchExt) {
  82. if (ArchExt.startswith("no")) {
  83. StringRef ArchExtBase(ArchExt.substr(2));
  84. for (const auto &AE : Extensions) {
  85. if (!AE.NegFeature.empty() && ArchExtBase == AE.Name)
  86. return AE.NegFeature;
  87. }
  88. }
  89. for (const auto &AE : Extensions)
  90. if (!AE.Feature.empty() && ArchExt == AE.Name)
  91. return AE.Feature;
  92. return StringRef();
  93. }
  94. void AArch64::fillValidCPUArchList(SmallVectorImpl<StringRef> &Values) {
  95. for (const auto &C : CpuInfos)
  96. if (C.Arch != INVALID)
  97. Values.push_back(C.Name);
  98. for (const auto &Alias : CpuAliases)
  99. Values.push_back(Alias.Alias);
  100. }
  101. bool AArch64::isX18ReservedByDefault(const Triple &TT) {
  102. return TT.isAndroid() || TT.isOSDarwin() || TT.isOSFuchsia() ||
  103. TT.isOSWindows();
  104. }
  105. // Allows partial match, ex. "v8a" matches "armv8a".
  106. const AArch64::ArchInfo &AArch64::parseArch(StringRef Arch) {
  107. Arch = llvm::ARM::getCanonicalArchName(Arch);
  108. if (checkArchVersion(Arch) < 8)
  109. return AArch64::INVALID;
  110. StringRef Syn = llvm::ARM::getArchSynonym(Arch);
  111. for (const auto *A : ArchInfos) {
  112. if (A->Name.endswith(Syn))
  113. return *A;
  114. }
  115. return AArch64::INVALID;
  116. }
  117. AArch64::ArchExtKind AArch64::parseArchExt(StringRef ArchExt) {
  118. for (const auto &A : Extensions) {
  119. if (ArchExt == A.Name)
  120. return static_cast<ArchExtKind>(A.ID);
  121. }
  122. return AArch64::AEK_INVALID;
  123. }
  124. const AArch64::CpuInfo &AArch64::parseCpu(StringRef Name) {
  125. // Resolve aliases first.
  126. Name = resolveCPUAlias(Name);
  127. // Then find the CPU name.
  128. for (const auto &C : CpuInfos)
  129. if (Name == C.Name)
  130. return C;
  131. // "generic" returns invalid.
  132. assert(Name != "invalid" && "Unexpected recursion.");
  133. return parseCpu("invalid");
  134. }