1f09cf34dSArchibald Elliott //===-- AArch64TargetParser - Parser for AArch64 features -------*- C++ -*-===// 2f09cf34dSArchibald Elliott // 3f09cf34dSArchibald Elliott // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4f09cf34dSArchibald Elliott // See https://llvm.org/LICENSE.txt for license information. 5f09cf34dSArchibald Elliott // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6f09cf34dSArchibald Elliott // 7f09cf34dSArchibald Elliott //===----------------------------------------------------------------------===// 8f09cf34dSArchibald Elliott // 9f09cf34dSArchibald Elliott // This file implements a target parser to recognise AArch64 hardware features 10f09cf34dSArchibald Elliott // such as FPU/CPU/ARCH and extension names. 11f09cf34dSArchibald Elliott // 12f09cf34dSArchibald Elliott //===----------------------------------------------------------------------===// 13f09cf34dSArchibald Elliott 14f09cf34dSArchibald Elliott #include "llvm/TargetParser/AArch64TargetParser.h" 1513e977d1Sostannard #include "llvm/Support/Debug.h" 1673779bb2SBalint Cristian #include "llvm/Support/Format.h" 1790db4193SDavid Spickett #include "llvm/Support/raw_ostream.h" 18f09cf34dSArchibald Elliott #include "llvm/TargetParser/ARMTargetParserCommon.h" 19f09cf34dSArchibald Elliott #include "llvm/TargetParser/Triple.h" 20f09cf34dSArchibald Elliott #include <cctype> 21bb83a3dfSLucas Duarte Prates #include <vector> 22f09cf34dSArchibald Elliott 2313e977d1Sostannard #define DEBUG_TYPE "target-parser" 2413e977d1Sostannard 25f09cf34dSArchibald Elliott using namespace llvm; 26f09cf34dSArchibald Elliott 27fa6d38d6STomas Matheson #define EMIT_FMV_INFO 28fa6d38d6STomas Matheson #include "llvm/TargetParser/AArch64TargetParserDef.inc" 29fa6d38d6STomas Matheson 30f09cf34dSArchibald Elliott static unsigned checkArchVersion(llvm::StringRef Arch) { 31f09cf34dSArchibald Elliott if (Arch.size() >= 2 && Arch[0] == 'v' && std::isdigit(Arch[1])) 32f09cf34dSArchibald Elliott return (Arch[1] - 48); 33f09cf34dSArchibald Elliott return 0; 34f09cf34dSArchibald Elliott } 35f09cf34dSArchibald Elliott 3613e977d1Sostannard const AArch64::ArchInfo *AArch64::getArchForCpu(StringRef CPU) { 37f4225d32STomas Matheson // Note: this now takes cpu aliases into account 389ea00fc7SLucas Prates std::optional<CpuInfo> Cpu = parseCpu(CPU); 399ea00fc7SLucas Prates if (!Cpu) 4013e977d1Sostannard return nullptr; 4113e977d1Sostannard return &Cpu->Arch; 42f09cf34dSArchibald Elliott } 43f09cf34dSArchibald Elliott 449ea00fc7SLucas Prates std::optional<AArch64::ArchInfo> AArch64::ArchInfo::findBySubArch(StringRef SubArch) { 45f4225d32STomas Matheson for (const auto *A : AArch64::ArchInfos) 46f4225d32STomas Matheson if (A->getSubArch() == SubArch) 47f4225d32STomas Matheson return *A; 489ea00fc7SLucas Prates return {}; 49f09cf34dSArchibald Elliott } 50f09cf34dSArchibald Elliott 51*831527a5SAlexandros Lamprineas std::optional<AArch64::FMVInfo> lookupFMVByID(AArch64::ArchExtKind ExtID) { 52*831527a5SAlexandros Lamprineas for (const AArch64::FMVInfo &Info : AArch64::getFMVInfo()) 53*831527a5SAlexandros Lamprineas if (Info.ID && *Info.ID == ExtID) 54*831527a5SAlexandros Lamprineas return Info; 55*831527a5SAlexandros Lamprineas return {}; 56*831527a5SAlexandros Lamprineas } 57*831527a5SAlexandros Lamprineas 588e659401SAlexandros Lamprineas uint64_t AArch64::getFMVPriority(ArrayRef<StringRef> Features) { 59*831527a5SAlexandros Lamprineas // Transitively enable the Arch Extensions which correspond to each feature. 60*831527a5SAlexandros Lamprineas ExtensionSet FeatureBits; 61*831527a5SAlexandros Lamprineas for (const StringRef Feature : Features) { 62*831527a5SAlexandros Lamprineas std::optional<FMVInfo> FMV = parseFMVExtension(Feature); 63*831527a5SAlexandros Lamprineas if (!FMV) { 64*831527a5SAlexandros Lamprineas if (std::optional<ExtensionInfo> Info = targetFeatureToExtension(Feature)) 65*831527a5SAlexandros Lamprineas FMV = lookupFMVByID(Info->ID); 66*831527a5SAlexandros Lamprineas } 67*831527a5SAlexandros Lamprineas if (FMV && FMV->ID) 68*831527a5SAlexandros Lamprineas FeatureBits.enable(*FMV->ID); 69*831527a5SAlexandros Lamprineas } 70*831527a5SAlexandros Lamprineas 71*831527a5SAlexandros Lamprineas // Construct a bitmask for all the transitively enabled Arch Extensions. 72*831527a5SAlexandros Lamprineas uint64_t PriorityMask = 0; 73*831527a5SAlexandros Lamprineas for (const FMVInfo &Info : getFMVInfo()) 74*831527a5SAlexandros Lamprineas if (Info.ID && FeatureBits.Enabled.test(*Info.ID)) 75*831527a5SAlexandros Lamprineas PriorityMask |= (1ULL << Info.PriorityBit); 76*831527a5SAlexandros Lamprineas 77*831527a5SAlexandros Lamprineas return PriorityMask; 7888c2af80SAlexandros Lamprineas } 7988c2af80SAlexandros Lamprineas 806f013dbcSAlexandros Lamprineas uint64_t AArch64::getCpuSupportsMask(ArrayRef<StringRef> Features) { 816f013dbcSAlexandros Lamprineas // Transitively enable the Arch Extensions which correspond to each feature. 826f013dbcSAlexandros Lamprineas ExtensionSet FeatureBits; 836f013dbcSAlexandros Lamprineas for (const StringRef Feature : Features) 846f013dbcSAlexandros Lamprineas if (std::optional<FMVInfo> Info = parseFMVExtension(Feature)) 856f013dbcSAlexandros Lamprineas if (Info->ID) 866f013dbcSAlexandros Lamprineas FeatureBits.enable(*Info->ID); 876f013dbcSAlexandros Lamprineas 886f013dbcSAlexandros Lamprineas // Construct a bitmask for all the transitively enabled Arch Extensions. 89fe5cf480SPavel Iliin uint64_t FeaturesMask = 0; 906f013dbcSAlexandros Lamprineas for (const FMVInfo &Info : getFMVInfo()) 916f013dbcSAlexandros Lamprineas if (Info.ID && FeatureBits.Enabled.test(*Info.ID)) 928e659401SAlexandros Lamprineas FeaturesMask |= (1ULL << Info.FeatureBit); 936f013dbcSAlexandros Lamprineas 94fe5cf480SPavel Iliin return FeaturesMask; 95fe5cf480SPavel Iliin } 96fe5cf480SPavel Iliin 97491a1cd0ShassnaaHamdi bool AArch64::getExtensionFeatures( 98491a1cd0ShassnaaHamdi const AArch64::ExtensionBitset &InputExts, 99f09cf34dSArchibald Elliott std::vector<StringRef> &Features) { 100f4225d32STomas Matheson for (const auto &E : Extensions) 101f4225d32STomas Matheson /* INVALID and NONE have no feature name. */ 102bb83a3dfSLucas Duarte Prates if (InputExts.test(E.ID) && !E.PosTargetFeature.empty()) 103bb83a3dfSLucas Duarte Prates Features.push_back(E.PosTargetFeature); 104f09cf34dSArchibald Elliott 105f09cf34dSArchibald Elliott return true; 106f09cf34dSArchibald Elliott } 107f09cf34dSArchibald Elliott 108f4225d32STomas Matheson StringRef AArch64::resolveCPUAlias(StringRef Name) { 109f4225d32STomas Matheson for (const auto &A : CpuAliases) 110d01576bbSAlexandros Lamprineas if (A.AltName == Name) 111d01576bbSAlexandros Lamprineas return A.Name; 112d01576bbSAlexandros Lamprineas return Name; 113d01576bbSAlexandros Lamprineas } 114d01576bbSAlexandros Lamprineas 115f09cf34dSArchibald Elliott StringRef AArch64::getArchExtFeature(StringRef ArchExt) { 1167f7bbb9bSAnatoly Trosinenko bool IsNegated = ArchExt.starts_with("no"); 1177f7bbb9bSAnatoly Trosinenko StringRef ArchExtBase = IsNegated ? ArchExt.drop_front(2) : ArchExt; 1187f7bbb9bSAnatoly Trosinenko 1197f7bbb9bSAnatoly Trosinenko if (auto AE = parseArchExtension(ArchExtBase)) { 120bb83a3dfSLucas Duarte Prates assert(!(AE.has_value() && AE->NegTargetFeature.empty())); 121bb83a3dfSLucas Duarte Prates return IsNegated ? AE->NegTargetFeature : AE->PosTargetFeature; 122f09cf34dSArchibald Elliott } 123f09cf34dSArchibald Elliott 124f09cf34dSArchibald Elliott return StringRef(); 125f09cf34dSArchibald Elliott } 126f09cf34dSArchibald Elliott 127f09cf34dSArchibald Elliott void AArch64::fillValidCPUArchList(SmallVectorImpl<StringRef> &Values) { 128f4225d32STomas Matheson for (const auto &C : CpuInfos) 129f4225d32STomas Matheson Values.push_back(C.Name); 130f09cf34dSArchibald Elliott 131f4225d32STomas Matheson for (const auto &Alias : CpuAliases) 1326b4a13a1SJon Roelofs // The apple-latest alias is backend only, do not expose it to clang's -mcpu. 1336b4a13a1SJon Roelofs if (Alias.AltName != "apple-latest") 134d01576bbSAlexandros Lamprineas Values.push_back(Alias.AltName); 1356b4a13a1SJon Roelofs 1366b4a13a1SJon Roelofs llvm::sort(Values); 137f09cf34dSArchibald Elliott } 138f09cf34dSArchibald Elliott 139f09cf34dSArchibald Elliott bool AArch64::isX18ReservedByDefault(const Triple &TT) { 140f09cf34dSArchibald Elliott return TT.isAndroid() || TT.isOSDarwin() || TT.isOSFuchsia() || 141c417b7a6SPavel Kosov TT.isOSWindows() || TT.isOHOSFamily(); 142f09cf34dSArchibald Elliott } 143f09cf34dSArchibald Elliott 144f09cf34dSArchibald Elliott // Allows partial match, ex. "v8a" matches "armv8a". 14513e977d1Sostannard const AArch64::ArchInfo *AArch64::parseArch(StringRef Arch) { 146f09cf34dSArchibald Elliott Arch = llvm::ARM::getCanonicalArchName(Arch); 147f09cf34dSArchibald Elliott if (checkArchVersion(Arch) < 8) 1489ea00fc7SLucas Prates return {}; 149f09cf34dSArchibald Elliott 150f09cf34dSArchibald Elliott StringRef Syn = llvm::ARM::getArchSynonym(Arch); 151f4225d32STomas Matheson for (const auto *A : ArchInfos) { 152586ecdf2SKazu Hirata if (A->Name.ends_with(Syn)) 15313e977d1Sostannard return A; 154f09cf34dSArchibald Elliott } 1559ea00fc7SLucas Prates return {}; 156f09cf34dSArchibald Elliott } 157f09cf34dSArchibald Elliott 15812c0024dSTomas Matheson std::optional<AArch64::ExtensionInfo> 15912c0024dSTomas Matheson AArch64::parseArchExtension(StringRef ArchExt) { 160bb83a3dfSLucas Duarte Prates if (ArchExt.empty()) 161bb83a3dfSLucas Duarte Prates return {}; 162f4225d32STomas Matheson for (const auto &A : Extensions) { 163bb83a3dfSLucas Duarte Prates if (ArchExt == A.UserVisibleName || ArchExt == A.Alias) 1649ea00fc7SLucas Prates return A; 165f09cf34dSArchibald Elliott } 1669ea00fc7SLucas Prates return {}; 167f09cf34dSArchibald Elliott } 168f09cf34dSArchibald Elliott 169fa6d38d6STomas Matheson std::optional<AArch64::FMVInfo> AArch64::parseFMVExtension(StringRef FMVExt) { 170fa6d38d6STomas Matheson // FIXME introduce general alias functionality, or remove this exception. 171fa6d38d6STomas Matheson if (FMVExt == "rdma") 172fa6d38d6STomas Matheson FMVExt = "rdm"; 173fa6d38d6STomas Matheson 174fa6d38d6STomas Matheson for (const auto &I : getFMVInfo()) { 175fa6d38d6STomas Matheson if (FMVExt == I.Name) 176fa6d38d6STomas Matheson return I; 177fa6d38d6STomas Matheson } 178fa6d38d6STomas Matheson return {}; 179fa6d38d6STomas Matheson } 180fa6d38d6STomas Matheson 181a03d06a7SAlexandros Lamprineas std::optional<AArch64::ExtensionInfo> 182a03d06a7SAlexandros Lamprineas AArch64::targetFeatureToExtension(StringRef TargetFeature) { 183a03d06a7SAlexandros Lamprineas for (const auto &E : Extensions) 184bb83a3dfSLucas Duarte Prates if (TargetFeature == E.PosTargetFeature) 185a03d06a7SAlexandros Lamprineas return E; 186a03d06a7SAlexandros Lamprineas return {}; 187a03d06a7SAlexandros Lamprineas } 188a03d06a7SAlexandros Lamprineas 1899ea00fc7SLucas Prates std::optional<AArch64::CpuInfo> AArch64::parseCpu(StringRef Name) { 190f09cf34dSArchibald Elliott // Resolve aliases first. 191f4225d32STomas Matheson Name = resolveCPUAlias(Name); 192f09cf34dSArchibald Elliott 193f4225d32STomas Matheson // Then find the CPU name. 194f4225d32STomas Matheson for (const auto &C : CpuInfos) 195f4225d32STomas Matheson if (Name == C.Name) 196f4225d32STomas Matheson return C; 197f4225d32STomas Matheson 1989ea00fc7SLucas Prates return {}; 199f09cf34dSArchibald Elliott } 20090db4193SDavid Spickett 201bb83a3dfSLucas Duarte Prates void AArch64::PrintSupportedExtensions() { 20273779bb2SBalint Cristian outs() << "All available -march extensions for AArch64\n\n" 20373779bb2SBalint Cristian << " " << left_justify("Name", 20) 204bb83a3dfSLucas Duarte Prates << left_justify("Architecture Feature(s)", 55) 205bb83a3dfSLucas Duarte Prates << "Description\n"; 20690db4193SDavid Spickett for (const auto &Ext : Extensions) { 20790db4193SDavid Spickett // Extensions without a feature cannot be used with -march. 208bb83a3dfSLucas Duarte Prates if (!Ext.UserVisibleName.empty() && !Ext.PosTargetFeature.empty()) { 20973779bb2SBalint Cristian outs() << " " 210bb83a3dfSLucas Duarte Prates << format(Ext.Description.empty() ? "%-20s%s\n" : "%-20s%-55s%s\n", 211bb83a3dfSLucas Duarte Prates Ext.UserVisibleName.str().c_str(), 212bb83a3dfSLucas Duarte Prates Ext.ArchFeatureName.str().c_str(), 213bb83a3dfSLucas Duarte Prates Ext.Description.str().c_str()); 21473779bb2SBalint Cristian } 21590db4193SDavid Spickett } 21690db4193SDavid Spickett } 21713e977d1Sostannard 218bb83a3dfSLucas Duarte Prates void 219bb83a3dfSLucas Duarte Prates AArch64::printEnabledExtensions(const std::set<StringRef> &EnabledFeatureNames) { 220bb83a3dfSLucas Duarte Prates outs() << "Extensions enabled for the given AArch64 target\n\n" 221bb83a3dfSLucas Duarte Prates << " " << left_justify("Architecture Feature(s)", 55) 222bb83a3dfSLucas Duarte Prates << "Description\n"; 223bb83a3dfSLucas Duarte Prates std::vector<ExtensionInfo> EnabledExtensionsInfo; 224bb83a3dfSLucas Duarte Prates for (const auto &FeatureName : EnabledFeatureNames) { 225bb83a3dfSLucas Duarte Prates std::string PosFeatureName = '+' + FeatureName.str(); 226bb83a3dfSLucas Duarte Prates if (auto ExtInfo = targetFeatureToExtension(PosFeatureName)) 227bb83a3dfSLucas Duarte Prates EnabledExtensionsInfo.push_back(*ExtInfo); 228bb83a3dfSLucas Duarte Prates } 229bb83a3dfSLucas Duarte Prates 230bb83a3dfSLucas Duarte Prates std::sort(EnabledExtensionsInfo.begin(), EnabledExtensionsInfo.end(), 231bb83a3dfSLucas Duarte Prates [](const ExtensionInfo &Lhs, const ExtensionInfo &Rhs) { 232bb83a3dfSLucas Duarte Prates return Lhs.ArchFeatureName < Rhs.ArchFeatureName; 233bb83a3dfSLucas Duarte Prates }); 234bb83a3dfSLucas Duarte Prates 235bb83a3dfSLucas Duarte Prates for (const auto &Ext : EnabledExtensionsInfo) { 236bb83a3dfSLucas Duarte Prates outs() << " " 237bb83a3dfSLucas Duarte Prates << format("%-55s%s\n", 238bb83a3dfSLucas Duarte Prates Ext.ArchFeatureName.str().c_str(), 239bb83a3dfSLucas Duarte Prates Ext.Description.str().c_str()); 240bb83a3dfSLucas Duarte Prates } 241bb83a3dfSLucas Duarte Prates } 242bb83a3dfSLucas Duarte Prates 24313e977d1Sostannard const llvm::AArch64::ExtensionInfo & 24413e977d1Sostannard lookupExtensionByID(llvm::AArch64::ArchExtKind ExtID) { 24513e977d1Sostannard for (const auto &E : llvm::AArch64::Extensions) 24613e977d1Sostannard if (E.ID == ExtID) 24713e977d1Sostannard return E; 248b647a34cSJie Fu llvm_unreachable("Invalid extension ID"); 24913e977d1Sostannard } 25013e977d1Sostannard 25113e977d1Sostannard void AArch64::ExtensionSet::enable(ArchExtKind E) { 25213e977d1Sostannard if (Enabled.test(E)) 25313e977d1Sostannard return; 25413e977d1Sostannard 255bb83a3dfSLucas Duarte Prates LLVM_DEBUG(llvm::dbgs() << "Enable " << lookupExtensionByID(E).UserVisibleName << "\n"); 25613e977d1Sostannard 25713e977d1Sostannard Touched.set(E); 25813e977d1Sostannard Enabled.set(E); 25913e977d1Sostannard 26013e977d1Sostannard // Recursively enable all features that this one depends on. This handles all 26113e977d1Sostannard // of the simple cases, where the behaviour doesn't depend on the base 26213e977d1Sostannard // architecture version. 26313e977d1Sostannard for (auto Dep : ExtensionDependencies) 26413e977d1Sostannard if (E == Dep.Later) 26513e977d1Sostannard enable(Dep.Earlier); 26613e977d1Sostannard 26713e977d1Sostannard // Special cases for dependencies which vary depending on the base 26813e977d1Sostannard // architecture version. 26913e977d1Sostannard if (BaseArch) { 27013e977d1Sostannard // +fp16 implies +fp16fml for v8.4A+, but not v9.0-A+ 27113e977d1Sostannard if (E == AEK_FP16 && BaseArch->is_superset(ARMV8_4A) && 27213e977d1Sostannard !BaseArch->is_superset(ARMV9A)) 27313e977d1Sostannard enable(AEK_FP16FML); 27413e977d1Sostannard 27513e977d1Sostannard // For v8.4A+ and v9.0A+, +crypto also enables +sha3 and +sm4. 27613e977d1Sostannard if (E == AEK_CRYPTO && BaseArch->is_superset(ARMV8_4A)) { 27713e977d1Sostannard enable(AEK_SHA3); 27813e977d1Sostannard enable(AEK_SM4); 27913e977d1Sostannard } 28013e977d1Sostannard } 28113e977d1Sostannard } 28213e977d1Sostannard 28313e977d1Sostannard void AArch64::ExtensionSet::disable(ArchExtKind E) { 28413e977d1Sostannard // -crypto always disables aes, sha2, sha3 and sm4, even for architectures 28513e977d1Sostannard // where the latter two would not be enabled by +crypto. 28613e977d1Sostannard if (E == AEK_CRYPTO) { 28713e977d1Sostannard disable(AEK_AES); 28813e977d1Sostannard disable(AEK_SHA2); 28913e977d1Sostannard disable(AEK_SHA3); 29013e977d1Sostannard disable(AEK_SM4); 29113e977d1Sostannard } 29213e977d1Sostannard 293748b0285SSpencerAbson // sve2-aes was historically associated with both FEAT_SVE2 and FEAT_SVE_AES, 294748b0285SSpencerAbson // the latter is now associated with sve-aes and sve2-aes has become shorthand 295748b0285SSpencerAbson // for +sve2+sve-aes. For backwards compatibility, when we disable sve2-aes we 296748b0285SSpencerAbson // must also disable sve-aes. 297748b0285SSpencerAbson if (E == AEK_SVE2AES) 298748b0285SSpencerAbson disable(AEK_SVEAES); 299748b0285SSpencerAbson 30092564850SCarolineConcatto if (E == AEK_SVE2BITPERM){ 30192564850SCarolineConcatto disable(AEK_SVEBITPERM); 30292564850SCarolineConcatto disable(AEK_SVE2); 30392564850SCarolineConcatto } 30492564850SCarolineConcatto 30513e977d1Sostannard if (!Enabled.test(E)) 30613e977d1Sostannard return; 30713e977d1Sostannard 308bb83a3dfSLucas Duarte Prates LLVM_DEBUG(llvm::dbgs() << "Disable " << lookupExtensionByID(E).UserVisibleName << "\n"); 30913e977d1Sostannard 31013e977d1Sostannard Touched.set(E); 31113e977d1Sostannard Enabled.reset(E); 31213e977d1Sostannard 31313e977d1Sostannard // Recursively disable all features that depends on this one. 31413e977d1Sostannard for (auto Dep : ExtensionDependencies) 31513e977d1Sostannard if (E == Dep.Earlier) 31613e977d1Sostannard disable(Dep.Later); 31713e977d1Sostannard } 31813e977d1Sostannard 31913e977d1Sostannard void AArch64::ExtensionSet::addCPUDefaults(const CpuInfo &CPU) { 32013e977d1Sostannard LLVM_DEBUG(llvm::dbgs() << "addCPUDefaults(" << CPU.Name << ")\n"); 32113e977d1Sostannard BaseArch = &CPU.Arch; 32213e977d1Sostannard 32313e977d1Sostannard AArch64::ExtensionBitset CPUExtensions = CPU.getImpliedExtensions(); 32413e977d1Sostannard for (const auto &E : Extensions) 32513e977d1Sostannard if (CPUExtensions.test(E.ID)) 32613e977d1Sostannard enable(E.ID); 32713e977d1Sostannard } 32813e977d1Sostannard 32913e977d1Sostannard void AArch64::ExtensionSet::addArchDefaults(const ArchInfo &Arch) { 33013e977d1Sostannard LLVM_DEBUG(llvm::dbgs() << "addArchDefaults(" << Arch.Name << ")\n"); 33113e977d1Sostannard BaseArch = &Arch; 33213e977d1Sostannard 33313e977d1Sostannard for (const auto &E : Extensions) 33413e977d1Sostannard if (Arch.DefaultExts.test(E.ID)) 33513e977d1Sostannard enable(E.ID); 33613e977d1Sostannard } 33713e977d1Sostannard 338a03d06a7SAlexandros Lamprineas bool AArch64::ExtensionSet::parseModifier(StringRef Modifier, 339a03d06a7SAlexandros Lamprineas const bool AllowNoDashForm) { 34013e977d1Sostannard LLVM_DEBUG(llvm::dbgs() << "parseModifier(" << Modifier << ")\n"); 34113e977d1Sostannard 342a03d06a7SAlexandros Lamprineas size_t NChars = 0; 343a03d06a7SAlexandros Lamprineas // The "no-feat" form is allowed in the target attribute but nowhere else. 344a03d06a7SAlexandros Lamprineas if (AllowNoDashForm && Modifier.starts_with("no-")) 345a03d06a7SAlexandros Lamprineas NChars = 3; 346a03d06a7SAlexandros Lamprineas else if (Modifier.starts_with("no")) 347a03d06a7SAlexandros Lamprineas NChars = 2; 348a03d06a7SAlexandros Lamprineas bool IsNegated = NChars != 0; 349a03d06a7SAlexandros Lamprineas StringRef ArchExt = Modifier.drop_front(NChars); 350260fe032SAlexandros Lamprineas 351260fe032SAlexandros Lamprineas if (auto AE = parseArchExtension(ArchExt)) { 352bb83a3dfSLucas Duarte Prates if (AE->PosTargetFeature.empty() || AE->NegTargetFeature.empty()) 353260fe032SAlexandros Lamprineas return false; 354260fe032SAlexandros Lamprineas if (IsNegated) 355260fe032SAlexandros Lamprineas disable(AE->ID); 356260fe032SAlexandros Lamprineas else 357260fe032SAlexandros Lamprineas enable(AE->ID); 35813e977d1Sostannard return true; 35913e977d1Sostannard } 36013e977d1Sostannard return false; 36113e977d1Sostannard } 3626aac30faSJack Styles 363a03d06a7SAlexandros Lamprineas void AArch64::ExtensionSet::reconstructFromParsedFeatures( 364a03d06a7SAlexandros Lamprineas const std::vector<std::string> &Features, 365a03d06a7SAlexandros Lamprineas std::vector<std::string> &NonExtensions) { 366a03d06a7SAlexandros Lamprineas assert(Touched.none() && "Bitset already initialized"); 367a03d06a7SAlexandros Lamprineas for (auto &F : Features) { 368a03d06a7SAlexandros Lamprineas bool IsNegated = F[0] == '-'; 369a03d06a7SAlexandros Lamprineas if (auto AE = targetFeatureToExtension(F)) { 370a03d06a7SAlexandros Lamprineas Touched.set(AE->ID); 371a03d06a7SAlexandros Lamprineas if (IsNegated) 372a03d06a7SAlexandros Lamprineas Enabled.reset(AE->ID); 373a03d06a7SAlexandros Lamprineas else 374a03d06a7SAlexandros Lamprineas Enabled.set(AE->ID); 375a03d06a7SAlexandros Lamprineas continue; 376a03d06a7SAlexandros Lamprineas } 377a03d06a7SAlexandros Lamprineas NonExtensions.push_back(F); 378a03d06a7SAlexandros Lamprineas } 379a03d06a7SAlexandros Lamprineas } 380a03d06a7SAlexandros Lamprineas 381fa6d38d6STomas Matheson void AArch64::ExtensionSet::dump() const { 382fa6d38d6STomas Matheson std::vector<StringRef> Features; 383fa6d38d6STomas Matheson toLLVMFeatureList(Features); 384fa6d38d6STomas Matheson for (StringRef F : Features) 385fa6d38d6STomas Matheson llvm::outs() << F << " "; 386fa6d38d6STomas Matheson llvm::outs() << "\n"; 387fa6d38d6STomas Matheson } 388fa6d38d6STomas Matheson 3896aac30faSJack Styles const AArch64::ExtensionInfo & 3906aac30faSJack Styles AArch64::getExtensionByID(AArch64::ArchExtKind ExtID) { 3916aac30faSJack Styles return lookupExtensionByID(ExtID); 3926aac30faSJack Styles } 393