1 //===- ARMTargetDefEmitter.cpp - Generate data about ARM Architectures ----===// 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 tablegen backend exports information about CPUs, FPUs, architectures, 10 // and features into a common format that can be used by both TargetParser and 11 // the ARM and AArch64 backends. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/ADT/StringSet.h" 16 #include "llvm/Support/Format.h" 17 #include "llvm/Support/FormatVariadic.h" 18 #include "llvm/TableGen/Error.h" 19 #include "llvm/TableGen/Record.h" 20 #include "llvm/TableGen/TableGenBackend.h" 21 #include <cstdint> 22 #include <set> 23 #include <string> 24 25 using namespace llvm; 26 27 /// Collect the full set of implied features for a SubtargetFeature. 28 static void CollectImpliedFeatures(std::set<Record *> &SeenFeats, Record *Rec) { 29 assert(Rec->isSubClassOf("SubtargetFeature") && 30 "Rec is not a SubtargetFeature"); 31 32 SeenFeats.insert(Rec); 33 for (Record *Implied : Rec->getValueAsListOfDefs("Implies")) 34 CollectImpliedFeatures(SeenFeats, Implied); 35 } 36 37 static void CheckFeatureTree(Record *Root) { 38 std::set<Record *> SeenFeats; 39 CollectImpliedFeatures(SeenFeats, Root); 40 41 // Check that each of the mandatory (implied) features which is an 42 // ExtensionWithMArch is also enabled by default. 43 auto DefaultExtsVec = Root->getValueAsListOfDefs("DefaultExts"); 44 std::set<Record *> DefaultExts{DefaultExtsVec.begin(), DefaultExtsVec.end()}; 45 for (auto *Feat : SeenFeats) { 46 if (Feat->isSubClassOf("ExtensionWithMArch") && !DefaultExts.count(Feat)) 47 PrintFatalError(Root->getLoc(), 48 "ExtensionWithMArch " + Feat->getName() + 49 " is implied (mandatory) as a SubtargetFeature, but " 50 "is not present in DefaultExts"); 51 } 52 } 53 54 static void EmitARMTargetDef(RecordKeeper &RK, raw_ostream &OS) { 55 OS << "// Autogenerated by ARMTargetDefEmitter.cpp\n\n"; 56 57 // Look through all SubtargetFeature defs with the given FieldName, and 58 // collect the set of all Values that that FieldName is set to. 59 auto gatherSubtargetFeatureFieldValues = [&RK](StringRef FieldName) { 60 llvm::StringSet<> Set; 61 for (const Record *Rec : RK.getAllDerivedDefinitions("SubtargetFeature")) { 62 if (Rec->getValueAsString("FieldName") == FieldName) { 63 Set.insert(Rec->getValueAsString("Value")); 64 } 65 } 66 return Set; 67 }; 68 69 // Sort the extensions alphabetically, so they don't appear in tablegen order. 70 std::vector<Record *> SortedExtensions = 71 RK.getAllDerivedDefinitions("Extension"); 72 auto Alphabetical = [](Record *A, Record *B) -> bool { 73 const auto NameA = A->getValueAsString("Name"); 74 const auto NameB = B->getValueAsString("Name"); 75 return NameA.compare(NameB) < 0; // A lexographically less than B 76 }; 77 std::sort(SortedExtensions.begin(), SortedExtensions.end(), Alphabetical); 78 79 // The ARMProcFamilyEnum values are initialised by SubtargetFeature defs 80 // which set the ARMProcFamily field. We can generate the enum from these defs 81 // which look like this: 82 // 83 // def ProcA5 : SubtargetFeature<"a5", "ARMProcFamily", "CortexA5", 84 // "Cortex-A5 ARM processors", []>; 85 OS << "#ifndef ARM_PROCESSOR_FAMILY\n" 86 << "#define ARM_PROCESSOR_FAMILY(ENUM)\n" 87 << "#endif\n\n"; 88 const StringSet<> ARMProcFamilyVals = 89 gatherSubtargetFeatureFieldValues("ARMProcFamily"); 90 for (const StringRef &Family : ARMProcFamilyVals.keys()) 91 OS << "ARM_PROCESSOR_FAMILY(" << Family << ")\n"; 92 OS << "\n#undef ARM_PROCESSOR_FAMILY\n\n"; 93 94 OS << "#ifndef ARM_ARCHITECTURE\n" 95 << "#define ARM_ARCHITECTURE(ENUM)\n" 96 << "#endif\n\n"; 97 // This should correspond to instances of the Architecture tablegen class. 98 const StringSet<> ARMArchVals = gatherSubtargetFeatureFieldValues("ARMArch"); 99 for (const StringRef &Arch : ARMArchVals.keys()) 100 OS << "ARM_ARCHITECTURE(" << Arch << ")\n"; 101 OS << "\n#undef ARM_ARCHITECTURE\n\n"; 102 103 // Currently only AArch64 (not ARM) is handled beyond this point. 104 if (!RK.getClass("Architecture64")) 105 return; 106 107 // Emit the ArchExtKind enum 108 OS << "#ifdef EMIT_ARCHEXTKIND_ENUM\n" 109 << "enum ArchExtKind : unsigned {\n"; 110 for (const Record *Rec : SortedExtensions) { 111 auto AEK = Rec->getValueAsString("ArchExtKindSpelling").upper(); 112 OS << " " << AEK << ",\n"; 113 } 114 OS << " AEK_NUM_EXTENSIONS\n" 115 << "};\n" 116 << "#undef EMIT_ARCHEXTKIND_ENUM\n" 117 << "#endif // EMIT_ARCHEXTKIND_ENUM\n"; 118 119 // Emit information for each defined Extension; used to build ArmExtKind. 120 OS << "#ifdef EMIT_EXTENSIONS\n" 121 << "inline constexpr ExtensionInfo Extensions[] = {\n"; 122 for (const Record *Rec : SortedExtensions) { 123 auto AEK = Rec->getValueAsString("ArchExtKindSpelling").upper(); 124 OS << " "; 125 OS << "{\"" << Rec->getValueAsString("UserVisibleName") << "\""; 126 if (auto Alias = Rec->getValueAsString("UserVisibleAlias"); Alias.empty()) 127 OS << ", {}"; 128 else 129 OS << ", \"" << Alias << "\""; 130 OS << ", AArch64::" << AEK; 131 OS << ", \"" << Rec->getValueAsString("ArchFeatureName") << "\""; 132 OS << ", \"" << Rec->getValueAsString("Desc") << "\""; 133 OS << ", \"+" << Rec->getValueAsString("Name") << "\""; // posfeature 134 OS << ", \"-" << Rec->getValueAsString("Name") << "\""; // negfeature 135 OS << "},\n"; 136 }; 137 OS << "};\n" 138 << "#undef EMIT_EXTENSIONS\n" 139 << "#endif // EMIT_EXTENSIONS\n" 140 << "\n"; 141 142 // Emit FMV information 143 auto FMVExts = RK.getAllDerivedDefinitionsIfDefined("FMVExtension"); 144 OS << "#ifdef EMIT_FMV_INFO\n" 145 << "const std::vector<llvm::AArch64::FMVInfo>& " 146 "llvm::AArch64::getFMVInfo() {\n" 147 << " static std::vector<FMVInfo> I;\n" 148 << " if(I.size()) return I;\n" 149 << " I.reserve(" << FMVExts.size() << ");\n"; 150 for (const Record *Rec : FMVExts) { 151 OS << " I.emplace_back("; 152 OS << "\"" << Rec->getValueAsString("Name") << "\""; 153 OS << ", " << Rec->getValueAsString("Bit"); 154 OS << ", \"" << Rec->getValueAsString("BackendFeatures") << "\""; 155 OS << ", " << (uint64_t)Rec->getValueAsInt("Priority"); 156 OS << ");\n"; 157 }; 158 OS << " return I;\n" 159 << "}\n" 160 << "#undef EMIT_FMV_INFO\n" 161 << "#endif // EMIT_FMV_INFO\n" 162 << "\n"; 163 164 // Emit extension dependencies 165 OS << "#ifdef EMIT_EXTENSION_DEPENDENCIES\n" 166 << "inline constexpr ExtensionDependency ExtensionDependencies[] = {\n"; 167 for (const Record *Rec : SortedExtensions) { 168 auto LaterAEK = Rec->getValueAsString("ArchExtKindSpelling").upper(); 169 for (const Record *I : Rec->getValueAsListOfDefs("Implies")) 170 if (auto EarlierAEK = I->getValueAsOptionalString("ArchExtKindSpelling")) 171 OS << " {" << EarlierAEK->upper() << ", " << LaterAEK << "},\n"; 172 } 173 // FIXME: Tablegen has the Subtarget Feature FeatureRCPC_IMMO which is implied 174 // by FeatureRCPC3 and in turn implies FeatureRCPC. The proper fix is to make 175 // FeatureRCPC_IMMO an Extension but that will expose it to the command line. 176 OS << " {AEK_RCPC, AEK_RCPC3},\n"; 177 OS << "};\n" 178 << "#undef EMIT_EXTENSION_DEPENDENCIES\n" 179 << "#endif // EMIT_EXTENSION_DEPENDENCIES\n" 180 << "\n"; 181 182 // Emit architecture information 183 OS << "#ifdef EMIT_ARCHITECTURES\n"; 184 185 // Return the C++ name of the of an ArchInfo object 186 auto ArchInfoName = [](int Major, int Minor, 187 StringRef Profile) -> std::string { 188 return Minor == 0 ? "ARMV" + std::to_string(Major) + Profile.upper() 189 : "ARMV" + std::to_string(Major) + "_" + 190 std::to_string(Minor) + Profile.upper(); 191 }; 192 193 auto Architectures = RK.getAllDerivedDefinitionsIfDefined("Architecture64"); 194 std::vector<std::string> CppSpellings; 195 for (const Record *Rec : Architectures) { 196 const int Major = Rec->getValueAsInt("Major"); 197 const int Minor = Rec->getValueAsInt("Minor"); 198 const std::string ProfileLower = Rec->getValueAsString("Profile").str(); 199 const std::string ProfileUpper = Rec->getValueAsString("Profile").upper(); 200 201 if (ProfileLower != "a" && ProfileLower != "r") 202 PrintFatalError(Rec->getLoc(), 203 "error: Profile must be one of 'a' or 'r', got '" + 204 ProfileLower + "'"); 205 206 // Name of the object in C++ 207 const std::string CppSpelling = ArchInfoName(Major, Minor, ProfileUpper); 208 OS << "inline constexpr ArchInfo " << CppSpelling << " = {\n"; 209 CppSpellings.push_back(CppSpelling); 210 211 OS << llvm::format(" VersionTuple{%d, %d},\n", Major, Minor); 212 OS << llvm::format(" %sProfile,\n", ProfileUpper.c_str()); 213 214 // Name as spelled for -march. 215 if (Minor == 0) 216 OS << llvm::format(" \"armv%d-%s\",\n", Major, ProfileLower.c_str()); 217 else 218 OS << llvm::format(" \"armv%d.%d-%s\",\n", Major, Minor, 219 ProfileLower.c_str()); 220 221 // SubtargetFeature::Name, used for -target-feature. Here the "+" is added. 222 const auto TargetFeatureName = Rec->getValueAsString("Name"); 223 OS << " \"+" << TargetFeatureName << "\",\n"; 224 225 // Construct the list of default extensions 226 OS << " (AArch64::ExtensionBitset({"; 227 for (auto *E : Rec->getValueAsListOfDefs("DefaultExts")) { 228 OS << "AArch64::" << E->getValueAsString("ArchExtKindSpelling").upper() 229 << ", "; 230 } 231 OS << "}))\n"; 232 233 OS << "};\n"; 234 } 235 236 OS << "\n" 237 << "/// The set of all architectures\n" 238 << "static constexpr std::array<const ArchInfo *, " << CppSpellings.size() 239 << "> ArchInfos = {\n"; 240 for (StringRef CppSpelling : CppSpellings) 241 OS << " &" << CppSpelling << ",\n"; 242 OS << "};\n"; 243 244 OS << "#undef EMIT_ARCHITECTURES\n" 245 << "#endif // EMIT_ARCHITECTURES\n" 246 << "\n"; 247 248 // Emit CPU Aliases 249 OS << "#ifdef EMIT_CPU_ALIAS\n" 250 << "inline constexpr Alias CpuAliases[] = {\n"; 251 252 llvm::StringSet<> Processors; 253 for (const Record *Rec : RK.getAllDerivedDefinitions("ProcessorModel")) 254 Processors.insert(Rec->getValueAsString("Name")); 255 256 llvm::StringSet<> Aliases; 257 for (const Record *Rec : RK.getAllDerivedDefinitions("ProcessorAlias")) { 258 auto Name = Rec->getValueAsString("Name"); 259 auto Alias = Rec->getValueAsString("Alias"); 260 if (!Processors.contains(Alias)) 261 PrintFatalError( 262 Rec, "Alias '" + Name + "' references a non-existent ProcessorModel '" + Alias + "'"); 263 if (Processors.contains(Name)) 264 PrintFatalError( 265 Rec, "Alias '" + Name + "' duplicates an existing ProcessorModel"); 266 if (!Aliases.insert(Name).second) 267 PrintFatalError( 268 Rec, "Alias '" + Name + "' duplicates an existing ProcessorAlias"); 269 270 OS << llvm::formatv(R"( { "{0}", "{1}" },)", Name, Alias) << '\n'; 271 } 272 273 OS << "};\n" 274 << "#undef EMIT_CPU_ALIAS\n" 275 << "#endif // EMIT_CPU_ALIAS\n" 276 << "\n"; 277 278 // Emit CPU information 279 OS << "#ifdef EMIT_CPU_INFO\n" 280 << "inline constexpr CpuInfo CpuInfos[] = {\n"; 281 282 for (const Record *Rec : RK.getAllDerivedDefinitions("ProcessorModel")) { 283 auto Name = Rec->getValueAsString("Name"); 284 auto Features = Rec->getValueAsListOfDefs("Features"); 285 286 // "apple-latest" is backend-only, should not be accepted by TargetParser. 287 if (Name == "apple-latest") 288 continue; 289 290 Record *Arch; 291 if (Name == "generic") { 292 // "generic" is an exception. It does not have an architecture, and there 293 // are tests that depend on e.g. -mattr=-v8.4a meaning HasV8_0aOps==false. 294 // However, in TargetParser CPUInfo, it is written as 8.0-A. 295 Arch = RK.getDef("HasV8_0aOps"); 296 } else { 297 // Search for an Architecture64 in the list of features. 298 auto IsArch = [](Record *F) { return F->isSubClassOf("Architecture64"); }; 299 auto ArchIter = llvm::find_if(Features, IsArch); 300 if (ArchIter == Features.end()) 301 PrintFatalError(Rec, "Features must include an Architecture64."); 302 Arch = *ArchIter; 303 304 // Check there is only one Architecture in the list. 305 if (llvm::count_if(Features, IsArch) > 1) 306 PrintFatalError(Rec, "Features has multiple Architecture64 entries"); 307 } 308 309 auto Major = Arch->getValueAsInt("Major"); 310 auto Minor = Arch->getValueAsInt("Minor"); 311 auto Profile = Arch->getValueAsString("Profile"); 312 auto ArchInfo = ArchInfoName(Major, Minor, Profile); 313 314 CheckFeatureTree(Arch); 315 316 OS << " {\n" 317 << " \"" << Name << "\",\n" 318 << " " << ArchInfo << ",\n" 319 << " AArch64::ExtensionBitset({\n"; 320 321 // Keep track of extensions we have seen 322 StringSet<> SeenExts; 323 for (auto *E : Rec->getValueAsListOfDefs("Features")) 324 // Only process subclasses of Extension 325 if (E->isSubClassOf("Extension")) { 326 const auto AEK = E->getValueAsString("ArchExtKindSpelling").upper(); 327 if (!SeenExts.insert(AEK).second) 328 PrintFatalError(Rec, "feature already added: " + E->getName()); 329 OS << " AArch64::" << AEK << ",\n"; 330 } 331 OS << " })\n" 332 << " },\n"; 333 } 334 OS << "};\n"; 335 336 OS << "#undef EMIT_CPU_INFO\n" 337 << "#endif // EMIT_CPU_INFO\n" 338 << "\n"; 339 } 340 341 static TableGen::Emitter::Opt 342 X("gen-arm-target-def", EmitARMTargetDef, 343 "Generate the ARM or AArch64 Architecture information header."); 344