xref: /llvm-project/llvm/utils/TableGen/Basic/ARMTargetDefEmitter.cpp (revision 8e65940161cd5a7dea5896fe4ae057d4cc07c703)
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