xref: /src/contrib/llvm-project/llvm/lib/TargetParser/AArch64TargetParser.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1e3b55780SDimitry Andric //===-- AArch64TargetParser - Parser for AArch64 features -------*- C++ -*-===//
2e3b55780SDimitry Andric //
3e3b55780SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e3b55780SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e3b55780SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e3b55780SDimitry Andric //
7e3b55780SDimitry Andric //===----------------------------------------------------------------------===//
8e3b55780SDimitry Andric //
9e3b55780SDimitry Andric // This file implements a target parser to recognise AArch64 hardware features
10e3b55780SDimitry Andric // such as FPU/CPU/ARCH and extension names.
11e3b55780SDimitry Andric //
12e3b55780SDimitry Andric //===----------------------------------------------------------------------===//
13e3b55780SDimitry Andric 
14e3b55780SDimitry Andric #include "llvm/TargetParser/AArch64TargetParser.h"
154df029ccSDimitry Andric #include "llvm/Support/Debug.h"
16b1c73532SDimitry Andric #include "llvm/Support/Format.h"
17b1c73532SDimitry Andric #include "llvm/Support/raw_ostream.h"
18e3b55780SDimitry Andric #include "llvm/TargetParser/ARMTargetParserCommon.h"
19e3b55780SDimitry Andric #include "llvm/TargetParser/Triple.h"
20e3b55780SDimitry Andric #include <cctype>
21ac9a064cSDimitry Andric #include <vector>
22e3b55780SDimitry Andric 
234df029ccSDimitry Andric #define DEBUG_TYPE "target-parser"
244df029ccSDimitry Andric 
25e3b55780SDimitry Andric using namespace llvm;
26e3b55780SDimitry Andric 
27ac9a064cSDimitry Andric #define EMIT_FMV_INFO
28ac9a064cSDimitry Andric #include "llvm/TargetParser/AArch64TargetParserDef.inc"
29ac9a064cSDimitry Andric 
checkArchVersion(llvm::StringRef Arch)30e3b55780SDimitry Andric static unsigned checkArchVersion(llvm::StringRef Arch) {
31e3b55780SDimitry Andric   if (Arch.size() >= 2 && Arch[0] == 'v' && std::isdigit(Arch[1]))
32e3b55780SDimitry Andric     return (Arch[1] - 48);
33e3b55780SDimitry Andric   return 0;
34e3b55780SDimitry Andric }
35e3b55780SDimitry Andric 
getArchForCpu(StringRef CPU)364df029ccSDimitry Andric const AArch64::ArchInfo *AArch64::getArchForCpu(StringRef CPU) {
37e3b55780SDimitry Andric   // Note: this now takes cpu aliases into account
387fa27ce4SDimitry Andric   std::optional<CpuInfo> Cpu = parseCpu(CPU);
397fa27ce4SDimitry Andric   if (!Cpu)
404df029ccSDimitry Andric     return nullptr;
414df029ccSDimitry Andric   return &Cpu->Arch;
42e3b55780SDimitry Andric }
43e3b55780SDimitry Andric 
findBySubArch(StringRef SubArch)447fa27ce4SDimitry Andric std::optional<AArch64::ArchInfo> AArch64::ArchInfo::findBySubArch(StringRef SubArch) {
45e3b55780SDimitry Andric   for (const auto *A : AArch64::ArchInfos)
46e3b55780SDimitry Andric     if (A->getSubArch() == SubArch)
47e3b55780SDimitry Andric       return *A;
487fa27ce4SDimitry Andric   return {};
49e3b55780SDimitry Andric }
50e3b55780SDimitry Andric 
getCpuSupportsMask(ArrayRef<StringRef> FeatureStrs)51e3b55780SDimitry Andric uint64_t AArch64::getCpuSupportsMask(ArrayRef<StringRef> FeatureStrs) {
52e3b55780SDimitry Andric   uint64_t FeaturesMask = 0;
53e3b55780SDimitry Andric   for (const StringRef &FeatureStr : FeatureStrs) {
54ac9a064cSDimitry Andric     if (auto Ext = parseFMVExtension(FeatureStr))
55ac9a064cSDimitry Andric       FeaturesMask |= (1ULL << Ext->Bit);
56e3b55780SDimitry Andric   }
57e3b55780SDimitry Andric   return FeaturesMask;
58e3b55780SDimitry Andric }
59e3b55780SDimitry Andric 
getExtensionFeatures(const AArch64::ExtensionBitset & InputExts,std::vector<StringRef> & Features)60b1c73532SDimitry Andric bool AArch64::getExtensionFeatures(
61b1c73532SDimitry Andric     const AArch64::ExtensionBitset &InputExts,
62e3b55780SDimitry Andric     std::vector<StringRef> &Features) {
63e3b55780SDimitry Andric   for (const auto &E : Extensions)
64e3b55780SDimitry Andric     /* INVALID and NONE have no feature name. */
65ac9a064cSDimitry Andric     if (InputExts.test(E.ID) && !E.PosTargetFeature.empty())
66ac9a064cSDimitry Andric       Features.push_back(E.PosTargetFeature);
67e3b55780SDimitry Andric 
68e3b55780SDimitry Andric   return true;
69e3b55780SDimitry Andric }
70e3b55780SDimitry Andric 
resolveCPUAlias(StringRef Name)71e3b55780SDimitry Andric StringRef AArch64::resolveCPUAlias(StringRef Name) {
72e3b55780SDimitry Andric   for (const auto &A : CpuAliases)
73ac9a064cSDimitry Andric     if (A.AltName == Name)
74e3b55780SDimitry Andric       return A.Name;
75e3b55780SDimitry Andric   return Name;
76e3b55780SDimitry Andric }
77e3b55780SDimitry Andric 
getArchExtFeature(StringRef ArchExt)78e3b55780SDimitry Andric StringRef AArch64::getArchExtFeature(StringRef ArchExt) {
794df029ccSDimitry Andric   bool IsNegated = ArchExt.starts_with("no");
804df029ccSDimitry Andric   StringRef ArchExtBase = IsNegated ? ArchExt.drop_front(2) : ArchExt;
814df029ccSDimitry Andric 
824df029ccSDimitry Andric   if (auto AE = parseArchExtension(ArchExtBase)) {
83ac9a064cSDimitry Andric     assert(!(AE.has_value() && AE->NegTargetFeature.empty()));
84ac9a064cSDimitry Andric     return IsNegated ? AE->NegTargetFeature : AE->PosTargetFeature;
85e3b55780SDimitry Andric   }
86e3b55780SDimitry Andric 
87e3b55780SDimitry Andric   return StringRef();
88e3b55780SDimitry Andric }
89e3b55780SDimitry Andric 
fillValidCPUArchList(SmallVectorImpl<StringRef> & Values)90e3b55780SDimitry Andric void AArch64::fillValidCPUArchList(SmallVectorImpl<StringRef> &Values) {
91e3b55780SDimitry Andric   for (const auto &C : CpuInfos)
92e3b55780SDimitry Andric     Values.push_back(C.Name);
93e3b55780SDimitry Andric 
94e3b55780SDimitry Andric   for (const auto &Alias : CpuAliases)
95ac9a064cSDimitry Andric     // The apple-latest alias is backend only, do not expose it to clang's -mcpu.
96ac9a064cSDimitry Andric     if (Alias.AltName != "apple-latest")
97ac9a064cSDimitry Andric       Values.push_back(Alias.AltName);
98ac9a064cSDimitry Andric 
99ac9a064cSDimitry Andric   llvm::sort(Values);
100e3b55780SDimitry Andric }
101e3b55780SDimitry Andric 
isX18ReservedByDefault(const Triple & TT)102e3b55780SDimitry Andric bool AArch64::isX18ReservedByDefault(const Triple &TT) {
103e3b55780SDimitry Andric   return TT.isAndroid() || TT.isOSDarwin() || TT.isOSFuchsia() ||
1047fa27ce4SDimitry Andric          TT.isOSWindows() || TT.isOHOSFamily();
105e3b55780SDimitry Andric }
106e3b55780SDimitry Andric 
107e3b55780SDimitry Andric // Allows partial match, ex. "v8a" matches "armv8a".
parseArch(StringRef Arch)1084df029ccSDimitry Andric const AArch64::ArchInfo *AArch64::parseArch(StringRef Arch) {
109e3b55780SDimitry Andric   Arch = llvm::ARM::getCanonicalArchName(Arch);
110e3b55780SDimitry Andric   if (checkArchVersion(Arch) < 8)
1117fa27ce4SDimitry Andric     return {};
112e3b55780SDimitry Andric 
113e3b55780SDimitry Andric   StringRef Syn = llvm::ARM::getArchSynonym(Arch);
114e3b55780SDimitry Andric   for (const auto *A : ArchInfos) {
115312c0ed1SDimitry Andric     if (A->Name.ends_with(Syn))
1164df029ccSDimitry Andric       return A;
117e3b55780SDimitry Andric   }
1187fa27ce4SDimitry Andric   return {};
119e3b55780SDimitry Andric }
120e3b55780SDimitry Andric 
121ac9a064cSDimitry Andric std::optional<AArch64::ExtensionInfo>
parseArchExtension(StringRef ArchExt)122ac9a064cSDimitry Andric AArch64::parseArchExtension(StringRef ArchExt) {
123ac9a064cSDimitry Andric   if (ArchExt.empty())
124ac9a064cSDimitry Andric     return {};
125e3b55780SDimitry Andric   for (const auto &A : Extensions) {
126ac9a064cSDimitry Andric     if (ArchExt == A.UserVisibleName || ArchExt == A.Alias)
1277fa27ce4SDimitry Andric       return A;
128e3b55780SDimitry Andric   }
1297fa27ce4SDimitry Andric   return {};
130e3b55780SDimitry Andric }
131e3b55780SDimitry Andric 
parseFMVExtension(StringRef FMVExt)132ac9a064cSDimitry Andric std::optional<AArch64::FMVInfo> AArch64::parseFMVExtension(StringRef FMVExt) {
133ac9a064cSDimitry Andric   // FIXME introduce general alias functionality, or remove this exception.
134ac9a064cSDimitry Andric   if (FMVExt == "rdma")
135ac9a064cSDimitry Andric     FMVExt = "rdm";
136ac9a064cSDimitry Andric 
137ac9a064cSDimitry Andric   for (const auto &I : getFMVInfo()) {
138ac9a064cSDimitry Andric     if (FMVExt == I.Name)
139ac9a064cSDimitry Andric       return I;
140ac9a064cSDimitry Andric   }
141ac9a064cSDimitry Andric   return {};
142ac9a064cSDimitry Andric }
143ac9a064cSDimitry Andric 
144ac9a064cSDimitry Andric std::optional<AArch64::ExtensionInfo>
targetFeatureToExtension(StringRef TargetFeature)145ac9a064cSDimitry Andric AArch64::targetFeatureToExtension(StringRef TargetFeature) {
146ac9a064cSDimitry Andric   for (const auto &E : Extensions)
147ac9a064cSDimitry Andric     if (TargetFeature == E.PosTargetFeature)
148ac9a064cSDimitry Andric       return E;
149ac9a064cSDimitry Andric   return {};
150ac9a064cSDimitry Andric }
151ac9a064cSDimitry Andric 
parseCpu(StringRef Name)1527fa27ce4SDimitry Andric std::optional<AArch64::CpuInfo> AArch64::parseCpu(StringRef Name) {
153e3b55780SDimitry Andric   // Resolve aliases first.
154e3b55780SDimitry Andric   Name = resolveCPUAlias(Name);
155e3b55780SDimitry Andric 
156e3b55780SDimitry Andric   // Then find the CPU name.
157e3b55780SDimitry Andric   for (const auto &C : CpuInfos)
158e3b55780SDimitry Andric     if (Name == C.Name)
159e3b55780SDimitry Andric       return C;
160e3b55780SDimitry Andric 
1617fa27ce4SDimitry Andric   return {};
162e3b55780SDimitry Andric }
163b1c73532SDimitry Andric 
PrintSupportedExtensions()164ac9a064cSDimitry Andric void AArch64::PrintSupportedExtensions() {
165b1c73532SDimitry Andric   outs() << "All available -march extensions for AArch64\n\n"
166b1c73532SDimitry Andric          << "    " << left_justify("Name", 20)
167ac9a064cSDimitry Andric          << left_justify("Architecture Feature(s)", 55)
168ac9a064cSDimitry Andric          << "Description\n";
169b1c73532SDimitry Andric   for (const auto &Ext : Extensions) {
170b1c73532SDimitry Andric     // Extensions without a feature cannot be used with -march.
171ac9a064cSDimitry Andric     if (!Ext.UserVisibleName.empty() && !Ext.PosTargetFeature.empty()) {
172b1c73532SDimitry Andric       outs() << "    "
173ac9a064cSDimitry Andric              << format(Ext.Description.empty() ? "%-20s%s\n" : "%-20s%-55s%s\n",
174ac9a064cSDimitry Andric                        Ext.UserVisibleName.str().c_str(),
175ac9a064cSDimitry Andric                        Ext.ArchFeatureName.str().c_str(),
176ac9a064cSDimitry Andric                        Ext.Description.str().c_str());
177b1c73532SDimitry Andric     }
178b1c73532SDimitry Andric   }
179b1c73532SDimitry Andric }
1804df029ccSDimitry Andric 
181ac9a064cSDimitry Andric void
printEnabledExtensions(const std::set<StringRef> & EnabledFeatureNames)182ac9a064cSDimitry Andric AArch64::printEnabledExtensions(const std::set<StringRef> &EnabledFeatureNames) {
183ac9a064cSDimitry Andric   outs() << "Extensions enabled for the given AArch64 target\n\n"
184ac9a064cSDimitry Andric          << "    " << left_justify("Architecture Feature(s)", 55)
185ac9a064cSDimitry Andric          << "Description\n";
186ac9a064cSDimitry Andric   std::vector<ExtensionInfo> EnabledExtensionsInfo;
187ac9a064cSDimitry Andric   for (const auto &FeatureName : EnabledFeatureNames) {
188ac9a064cSDimitry Andric     std::string PosFeatureName = '+' + FeatureName.str();
189ac9a064cSDimitry Andric     if (auto ExtInfo = targetFeatureToExtension(PosFeatureName))
190ac9a064cSDimitry Andric       EnabledExtensionsInfo.push_back(*ExtInfo);
191ac9a064cSDimitry Andric   }
192ac9a064cSDimitry Andric 
193ac9a064cSDimitry Andric   std::sort(EnabledExtensionsInfo.begin(), EnabledExtensionsInfo.end(),
194ac9a064cSDimitry Andric             [](const ExtensionInfo &Lhs, const ExtensionInfo &Rhs) {
195ac9a064cSDimitry Andric               return Lhs.ArchFeatureName < Rhs.ArchFeatureName;
196ac9a064cSDimitry Andric             });
197ac9a064cSDimitry Andric 
198ac9a064cSDimitry Andric   for (const auto &Ext : EnabledExtensionsInfo) {
199ac9a064cSDimitry Andric     outs() << "    "
200ac9a064cSDimitry Andric            << format("%-55s%s\n",
201ac9a064cSDimitry Andric                      Ext.ArchFeatureName.str().c_str(),
202ac9a064cSDimitry Andric                      Ext.Description.str().c_str());
203ac9a064cSDimitry Andric   }
204ac9a064cSDimitry Andric }
205ac9a064cSDimitry Andric 
2064df029ccSDimitry Andric const llvm::AArch64::ExtensionInfo &
lookupExtensionByID(llvm::AArch64::ArchExtKind ExtID)2074df029ccSDimitry Andric lookupExtensionByID(llvm::AArch64::ArchExtKind ExtID) {
2084df029ccSDimitry Andric   for (const auto &E : llvm::AArch64::Extensions)
2094df029ccSDimitry Andric     if (E.ID == ExtID)
2104df029ccSDimitry Andric       return E;
2114df029ccSDimitry Andric   llvm_unreachable("Invalid extension ID");
2124df029ccSDimitry Andric }
2134df029ccSDimitry Andric 
enable(ArchExtKind E)2144df029ccSDimitry Andric void AArch64::ExtensionSet::enable(ArchExtKind E) {
2154df029ccSDimitry Andric   if (Enabled.test(E))
2164df029ccSDimitry Andric     return;
2174df029ccSDimitry Andric 
218ac9a064cSDimitry Andric   LLVM_DEBUG(llvm::dbgs() << "Enable " << lookupExtensionByID(E).UserVisibleName << "\n");
2194df029ccSDimitry Andric 
2204df029ccSDimitry Andric   Touched.set(E);
2214df029ccSDimitry Andric   Enabled.set(E);
2224df029ccSDimitry Andric 
2234df029ccSDimitry Andric   // Recursively enable all features that this one depends on. This handles all
2244df029ccSDimitry Andric   // of the simple cases, where the behaviour doesn't depend on the base
2254df029ccSDimitry Andric   // architecture version.
2264df029ccSDimitry Andric   for (auto Dep : ExtensionDependencies)
2274df029ccSDimitry Andric     if (E == Dep.Later)
2284df029ccSDimitry Andric       enable(Dep.Earlier);
2294df029ccSDimitry Andric 
2304df029ccSDimitry Andric   // Special cases for dependencies which vary depending on the base
2314df029ccSDimitry Andric   // architecture version.
2324df029ccSDimitry Andric   if (BaseArch) {
2334df029ccSDimitry Andric     // +fp16 implies +fp16fml for v8.4A+, but not v9.0-A+
2344df029ccSDimitry Andric     if (E == AEK_FP16 && BaseArch->is_superset(ARMV8_4A) &&
2354df029ccSDimitry Andric         !BaseArch->is_superset(ARMV9A))
2364df029ccSDimitry Andric       enable(AEK_FP16FML);
2374df029ccSDimitry Andric 
2384df029ccSDimitry Andric     // For v8.4A+ and v9.0A+, +crypto also enables +sha3 and +sm4.
2394df029ccSDimitry Andric     if (E == AEK_CRYPTO && BaseArch->is_superset(ARMV8_4A)) {
2404df029ccSDimitry Andric       enable(AEK_SHA3);
2414df029ccSDimitry Andric       enable(AEK_SM4);
2424df029ccSDimitry Andric     }
2434df029ccSDimitry Andric   }
2444df029ccSDimitry Andric }
2454df029ccSDimitry Andric 
disable(ArchExtKind E)2464df029ccSDimitry Andric void AArch64::ExtensionSet::disable(ArchExtKind E) {
2474df029ccSDimitry Andric   // -crypto always disables aes, sha2, sha3 and sm4, even for architectures
2484df029ccSDimitry Andric   // where the latter two would not be enabled by +crypto.
2494df029ccSDimitry Andric   if (E == AEK_CRYPTO) {
2504df029ccSDimitry Andric     disable(AEK_AES);
2514df029ccSDimitry Andric     disable(AEK_SHA2);
2524df029ccSDimitry Andric     disable(AEK_SHA3);
2534df029ccSDimitry Andric     disable(AEK_SM4);
2544df029ccSDimitry Andric   }
2554df029ccSDimitry Andric 
2564df029ccSDimitry Andric   if (!Enabled.test(E))
2574df029ccSDimitry Andric     return;
2584df029ccSDimitry Andric 
259ac9a064cSDimitry Andric   LLVM_DEBUG(llvm::dbgs() << "Disable " << lookupExtensionByID(E).UserVisibleName << "\n");
2604df029ccSDimitry Andric 
2614df029ccSDimitry Andric   Touched.set(E);
2624df029ccSDimitry Andric   Enabled.reset(E);
2634df029ccSDimitry Andric 
2644df029ccSDimitry Andric   // Recursively disable all features that depends on this one.
2654df029ccSDimitry Andric   for (auto Dep : ExtensionDependencies)
2664df029ccSDimitry Andric     if (E == Dep.Earlier)
2674df029ccSDimitry Andric       disable(Dep.Later);
2684df029ccSDimitry Andric }
2694df029ccSDimitry Andric 
addCPUDefaults(const CpuInfo & CPU)2704df029ccSDimitry Andric void AArch64::ExtensionSet::addCPUDefaults(const CpuInfo &CPU) {
2714df029ccSDimitry Andric   LLVM_DEBUG(llvm::dbgs() << "addCPUDefaults(" << CPU.Name << ")\n");
2724df029ccSDimitry Andric   BaseArch = &CPU.Arch;
2734df029ccSDimitry Andric 
2744df029ccSDimitry Andric   AArch64::ExtensionBitset CPUExtensions = CPU.getImpliedExtensions();
2754df029ccSDimitry Andric   for (const auto &E : Extensions)
2764df029ccSDimitry Andric     if (CPUExtensions.test(E.ID))
2774df029ccSDimitry Andric       enable(E.ID);
2784df029ccSDimitry Andric }
2794df029ccSDimitry Andric 
addArchDefaults(const ArchInfo & Arch)2804df029ccSDimitry Andric void AArch64::ExtensionSet::addArchDefaults(const ArchInfo &Arch) {
2814df029ccSDimitry Andric   LLVM_DEBUG(llvm::dbgs() << "addArchDefaults(" << Arch.Name << ")\n");
2824df029ccSDimitry Andric   BaseArch = &Arch;
2834df029ccSDimitry Andric 
2844df029ccSDimitry Andric   for (const auto &E : Extensions)
2854df029ccSDimitry Andric     if (Arch.DefaultExts.test(E.ID))
2864df029ccSDimitry Andric       enable(E.ID);
2874df029ccSDimitry Andric }
2884df029ccSDimitry Andric 
parseModifier(StringRef Modifier,const bool AllowNoDashForm)289ac9a064cSDimitry Andric bool AArch64::ExtensionSet::parseModifier(StringRef Modifier,
290ac9a064cSDimitry Andric                                           const bool AllowNoDashForm) {
2914df029ccSDimitry Andric   LLVM_DEBUG(llvm::dbgs() << "parseModifier(" << Modifier << ")\n");
2924df029ccSDimitry Andric 
293ac9a064cSDimitry Andric   size_t NChars = 0;
294ac9a064cSDimitry Andric   // The "no-feat" form is allowed in the target attribute but nowhere else.
295ac9a064cSDimitry Andric   if (AllowNoDashForm && Modifier.starts_with("no-"))
296ac9a064cSDimitry Andric     NChars = 3;
297ac9a064cSDimitry Andric   else if (Modifier.starts_with("no"))
298ac9a064cSDimitry Andric     NChars = 2;
299ac9a064cSDimitry Andric   bool IsNegated = NChars != 0;
300ac9a064cSDimitry Andric   StringRef ArchExt = Modifier.drop_front(NChars);
3014df029ccSDimitry Andric 
302ac9a064cSDimitry Andric   if (auto AE = parseArchExtension(ArchExt)) {
303ac9a064cSDimitry Andric     if (AE->PosTargetFeature.empty() || AE->NegTargetFeature.empty())
3044df029ccSDimitry Andric       return false;
305ac9a064cSDimitry Andric     if (IsNegated)
306ac9a064cSDimitry Andric       disable(AE->ID);
307ac9a064cSDimitry Andric     else
308ac9a064cSDimitry Andric       enable(AE->ID);
309ac9a064cSDimitry Andric     return true;
310ac9a064cSDimitry Andric   }
311ac9a064cSDimitry Andric   return false;
312ac9a064cSDimitry Andric }
313ac9a064cSDimitry Andric 
reconstructFromParsedFeatures(const std::vector<std::string> & Features,std::vector<std::string> & NonExtensions)314ac9a064cSDimitry Andric void AArch64::ExtensionSet::reconstructFromParsedFeatures(
315ac9a064cSDimitry Andric     const std::vector<std::string> &Features,
316ac9a064cSDimitry Andric     std::vector<std::string> &NonExtensions) {
317ac9a064cSDimitry Andric   assert(Touched.none() && "Bitset already initialized");
318ac9a064cSDimitry Andric   for (auto &F : Features) {
319ac9a064cSDimitry Andric     bool IsNegated = F[0] == '-';
320ac9a064cSDimitry Andric     if (auto AE = targetFeatureToExtension(F)) {
321ac9a064cSDimitry Andric       Touched.set(AE->ID);
322ac9a064cSDimitry Andric       if (IsNegated)
323ac9a064cSDimitry Andric         Enabled.reset(AE->ID);
324ac9a064cSDimitry Andric       else
325ac9a064cSDimitry Andric         Enabled.set(AE->ID);
326ac9a064cSDimitry Andric       continue;
327ac9a064cSDimitry Andric     }
328ac9a064cSDimitry Andric     NonExtensions.push_back(F);
329ac9a064cSDimitry Andric   }
330ac9a064cSDimitry Andric }
331ac9a064cSDimitry Andric 
dump() const332ac9a064cSDimitry Andric void AArch64::ExtensionSet::dump() const {
333ac9a064cSDimitry Andric   std::vector<StringRef> Features;
334ac9a064cSDimitry Andric   toLLVMFeatureList(Features);
335ac9a064cSDimitry Andric   for (StringRef F : Features)
336ac9a064cSDimitry Andric     llvm::outs() << F << " ";
337ac9a064cSDimitry Andric   llvm::outs() << "\n";
338ac9a064cSDimitry Andric }
339ac9a064cSDimitry Andric 
340ac9a064cSDimitry Andric const AArch64::ExtensionInfo &
getExtensionByID(AArch64::ArchExtKind ExtID)341ac9a064cSDimitry Andric AArch64::getExtensionByID(AArch64::ArchExtKind ExtID) {
342ac9a064cSDimitry Andric   return lookupExtensionByID(ExtID);
3434df029ccSDimitry Andric }
344