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