Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/utils/TableGen/ARMTargetDefEmitter.cpp
35258 views
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
345