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