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