[Frontend] Remove unused includes (NFC) (#116927)
[llvm-project.git] / llvm / utils / TableGen / ARMTargetDefEmitter.cpp
blobadb5f1d95b5722a3f78b356e2c953d1a41a30345
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.
13 //===----------------------------------------------------------------------===//
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>
26 using namespace llvm;
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");
34 SeenFeats.insert(Rec);
35 for (const Record *Implied : Rec->getValueAsListOfDefs("Implies"))
36 collectImpliedFeatures(SeenFeats, Implied);
39 static void checkFeatureTree(const Record *Root) {
40 std::set<const Record *> SeenFeats;
41 collectImpliedFeatures(SeenFeats, Root);
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");
57 static void emitARMTargetDef(const RecordKeeper &RK, raw_ostream &OS) {
58 OS << "// Autogenerated by ARMTargetDefEmitter.cpp\n\n";
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"));
69 return Set;
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
80 sort(SortedExtensions, Alphabetical);
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;
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:
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";
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";
115 // Currently only AArch64 (not ARM) is handled beyond this point.
116 if (!RK.getClass("Architecture64"))
117 return;
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";
126 OS << " AEK_NUM_EXTENSIONS\n"
127 << "};\n"
128 << "#undef EMIT_ARCHEXTKIND_ENUM\n"
129 << "#endif // EMIT_ARCHEXTKIND_ENUM\n";
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";
149 OS << "};\n"
150 << "#undef EMIT_EXTENSIONS\n"
151 << "#endif // EMIT_EXTENSIONS\n"
152 << "\n";
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("Bit");
166 auto FeatName = Rec->getValueAsString("BackendFeature");
167 const Record *FeatRec = ExtensionMap[FeatName];
168 if (FeatRec)
169 OS << ", " << FeatRec->getValueAsString("ArchExtKindSpelling").upper();
170 else
171 OS << ", std::nullopt";
172 OS << ", " << (uint64_t)Rec->getValueAsInt("Priority");
173 OS << ");\n";
175 OS << " return I;\n"
176 << "}\n"
177 << "#undef EMIT_FMV_INFO\n"
178 << "#endif // EMIT_FMV_INFO\n"
179 << "\n";
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";
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";
199 // Emit architecture information
200 OS << "#ifdef EMIT_ARCHITECTURES\n";
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();
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();
218 if (ProfileLower != "a" && ProfileLower != "r")
219 PrintFatalError(Rec->getLoc(),
220 "error: Profile must be one of 'a' or 'r', got '" +
221 ProfileLower + "'");
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(CppSpelling);
228 OS << llvm::format(" VersionTuple{%d, %d},\n", Major, Minor);
229 OS << llvm::format(" %sProfile,\n", ProfileUpper.c_str());
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());
238 // SubtargetFeature::Name, used for -target-feature. Here the "+" is added.
239 const auto TargetFeatureName = Rec->getValueAsString("Name");
240 OS << " \"+" << TargetFeatureName << "\",\n";
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 << ", ";
248 OS << "}))\n";
250 OS << "};\n";
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";
261 OS << "#undef EMIT_ARCHITECTURES\n"
262 << "#endif // EMIT_ARCHITECTURES\n"
263 << "\n";
265 // Emit CPU Aliases
266 OS << "#ifdef EMIT_CPU_ALIAS\n"
267 << "inline constexpr Alias CpuAliases[] = {\n";
269 llvm::StringSet<> Processors;
270 for (const Record *Rec : RK.getAllDerivedDefinitions("ProcessorModel"))
271 Processors.insert(Rec->getValueAsString("Name"));
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");
287 OS << llvm::formatv(R"( { "{0}", "{1}" },)", Name, Alias) << '\n';
290 OS << "};\n"
291 << "#undef EMIT_CPU_ALIAS\n"
292 << "#endif // EMIT_CPU_ALIAS\n"
293 << "\n";
295 // Emit CPU information
296 OS << "#ifdef EMIT_CPU_INFO\n"
297 << "inline constexpr CpuInfo CpuInfos[] = {\n";
299 for (const Record *Rec : RK.getAllDerivedDefinitions("ProcessorModel")) {
300 auto Name = Rec->getValueAsString("Name");
301 auto Features = Rec->getValueAsListOfDefs("Features");
303 // "apple-latest" is backend-only, should not be accepted by TargetParser.
304 if (Name == "apple-latest")
305 continue;
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");
318 auto ArchIter = llvm::find_if(Features, IsArch);
319 if (ArchIter == Features.end())
320 PrintFatalError(Rec, "Features must include an Architecture64.");
321 Arch = *ArchIter;
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");
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);
333 checkFeatureTree(Arch);
335 OS << " {\n"
336 << " \"" << Name << "\",\n"
337 << " " << ArchInfo << ",\n"
338 << " AArch64::ExtensionBitset({\n";
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";
350 OS << " })\n"
351 << " },\n";
353 OS << "};\n";
355 OS << "#undef EMIT_CPU_INFO\n"
356 << "#endif // EMIT_CPU_INFO\n"
357 << "\n";
360 static TableGen::Emitter::Opt
361 X("gen-arm-target-def", emitARMTargetDef,
362 "Generate the ARM or AArch64 Architecture information header.");