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