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