Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/utils/TableGen/RISCVTargetDefEmitter.cpp
35258 views
1
//===- RISCVTargetDefEmitter.cpp - Generate lists of RISC-V CPUs ----------===//
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 emits the include file needed by RISCVTargetParser.cpp
10
// and RISCVISAInfo.cpp to parse the RISC-V CPUs and extensions.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "llvm/ADT/DenseSet.h"
15
#include "llvm/Support/RISCVISAUtils.h"
16
#include "llvm/TableGen/Record.h"
17
#include "llvm/TableGen/TableGenBackend.h"
18
19
using namespace llvm;
20
21
static StringRef getExtensionName(const Record *R) {
22
StringRef Name = R->getValueAsString("Name");
23
Name.consume_front("experimental-");
24
return Name;
25
}
26
27
static void printExtensionTable(raw_ostream &OS,
28
const std::vector<Record *> &Extensions,
29
bool Experimental) {
30
OS << "static const RISCVSupportedExtension Supported";
31
if (Experimental)
32
OS << "Experimental";
33
OS << "Extensions[] = {\n";
34
35
for (Record *R : Extensions) {
36
if (R->getValueAsBit("Experimental") != Experimental)
37
continue;
38
39
OS << " {\"" << getExtensionName(R) << "\", {"
40
<< R->getValueAsInt("MajorVersion") << ", "
41
<< R->getValueAsInt("MinorVersion") << "}},\n";
42
}
43
44
OS << "};\n\n";
45
}
46
47
static void emitRISCVExtensions(RecordKeeper &Records, raw_ostream &OS) {
48
OS << "#ifdef GET_SUPPORTED_EXTENSIONS\n";
49
OS << "#undef GET_SUPPORTED_EXTENSIONS\n\n";
50
51
std::vector<Record *> Extensions =
52
Records.getAllDerivedDefinitionsIfDefined("RISCVExtension");
53
llvm::sort(Extensions, [](const Record *Rec1, const Record *Rec2) {
54
return getExtensionName(Rec1) < getExtensionName(Rec2);
55
});
56
57
if (!Extensions.empty()) {
58
printExtensionTable(OS, Extensions, /*Experimental=*/false);
59
printExtensionTable(OS, Extensions, /*Experimental=*/true);
60
}
61
62
OS << "#endif // GET_SUPPORTED_EXTENSIONS\n\n";
63
64
OS << "#ifdef GET_IMPLIED_EXTENSIONS\n";
65
OS << "#undef GET_IMPLIED_EXTENSIONS\n\n";
66
67
if (!Extensions.empty()) {
68
OS << "\nstatic constexpr ImpliedExtsEntry ImpliedExts[] = {\n";
69
for (Record *Ext : Extensions) {
70
auto ImpliesList = Ext->getValueAsListOfDefs("Implies");
71
if (ImpliesList.empty())
72
continue;
73
74
StringRef Name = getExtensionName(Ext);
75
76
for (auto *ImpliedExt : ImpliesList) {
77
if (!ImpliedExt->isSubClassOf("RISCVExtension"))
78
continue;
79
80
OS << " { {\"" << Name << "\"}, \"" << getExtensionName(ImpliedExt)
81
<< "\"},\n";
82
}
83
}
84
85
OS << "};\n\n";
86
}
87
88
OS << "#endif // GET_IMPLIED_EXTENSIONS\n\n";
89
}
90
91
// We can generate march string from target features as what has been described
92
// in RISC-V ISA specification (version 20191213) 'Chapter 27. ISA Extension
93
// Naming Conventions'.
94
//
95
// This is almost the same as RISCVFeatures::parseFeatureBits, except that we
96
// get feature name from feature records instead of feature bits.
97
static void printMArch(raw_ostream &OS, const std::vector<Record *> &Features) {
98
RISCVISAUtils::OrderedExtensionMap Extensions;
99
unsigned XLen = 0;
100
101
// Convert features to FeatureVector.
102
for (auto *Feature : Features) {
103
StringRef FeatureName = getExtensionName(Feature);
104
if (Feature->isSubClassOf("RISCVExtension")) {
105
unsigned Major = Feature->getValueAsInt("MajorVersion");
106
unsigned Minor = Feature->getValueAsInt("MinorVersion");
107
Extensions[FeatureName.str()] = {Major, Minor};
108
} else if (FeatureName == "64bit") {
109
assert(XLen == 0 && "Already determined XLen");
110
XLen = 64;
111
} else if (FeatureName == "32bit") {
112
assert(XLen == 0 && "Already determined XLen");
113
XLen = 32;
114
}
115
}
116
117
assert(XLen != 0 && "Unable to determine XLen");
118
119
OS << "rv" << XLen;
120
121
ListSeparator LS("_");
122
for (auto const &Ext : Extensions)
123
OS << LS << Ext.first << Ext.second.Major << 'p' << Ext.second.Minor;
124
}
125
126
static void printProfileTable(raw_ostream &OS,
127
const std::vector<Record *> &Profiles,
128
bool Experimental) {
129
OS << "static constexpr RISCVProfile Supported";
130
if (Experimental)
131
OS << "Experimental";
132
OS << "Profiles[] = {\n";
133
134
for (const Record *Rec : Profiles) {
135
if (Rec->getValueAsBit("Experimental") != Experimental)
136
continue;
137
138
StringRef Name = Rec->getValueAsString("Name");
139
Name.consume_front("experimental-");
140
OS.indent(4) << "{\"" << Name << "\",\"";
141
printMArch(OS, Rec->getValueAsListOfDefs("Implies"));
142
OS << "\"},\n";
143
}
144
145
OS << "};\n\n";
146
}
147
148
static void emitRISCVProfiles(RecordKeeper &Records, raw_ostream &OS) {
149
OS << "#ifdef GET_SUPPORTED_PROFILES\n";
150
OS << "#undef GET_SUPPORTED_PROFILES\n\n";
151
152
auto Profiles = Records.getAllDerivedDefinitionsIfDefined("RISCVProfile");
153
154
if (!Profiles.empty()) {
155
printProfileTable(OS, Profiles, /*Experimental=*/false);
156
bool HasExperimentalProfiles = any_of(Profiles, [&](auto &Rec) {
157
return Rec->getValueAsBit("Experimental");
158
});
159
if (HasExperimentalProfiles)
160
printProfileTable(OS, Profiles, /*Experimental=*/true);
161
}
162
163
OS << "#endif // GET_SUPPORTED_PROFILES\n\n";
164
}
165
166
static void emitRISCVProcs(RecordKeeper &RK, raw_ostream &OS) {
167
OS << "#ifndef PROC\n"
168
<< "#define PROC(ENUM, NAME, DEFAULT_MARCH, FAST_SCALAR_UNALIGN"
169
<< ", FAST_VECTOR_UNALIGN)\n"
170
<< "#endif\n\n";
171
172
// Iterate on all definition records.
173
for (const Record *Rec :
174
RK.getAllDerivedDefinitionsIfDefined("RISCVProcessorModel")) {
175
const std::vector<Record *> &Features =
176
Rec->getValueAsListOfDefs("Features");
177
bool FastScalarUnalignedAccess = any_of(Features, [&](auto &Feature) {
178
return Feature->getValueAsString("Name") == "unaligned-scalar-mem";
179
});
180
181
bool FastVectorUnalignedAccess = any_of(Features, [&](auto &Feature) {
182
return Feature->getValueAsString("Name") == "unaligned-vector-mem";
183
});
184
185
OS << "PROC(" << Rec->getName() << ", {\"" << Rec->getValueAsString("Name")
186
<< "\"}, {\"";
187
188
StringRef MArch = Rec->getValueAsString("DefaultMarch");
189
190
// Compute MArch from features if we don't specify it.
191
if (MArch.empty())
192
printMArch(OS, Features);
193
else
194
OS << MArch;
195
OS << "\"}, " << FastScalarUnalignedAccess << ", "
196
<< FastVectorUnalignedAccess << ")\n";
197
}
198
OS << "\n#undef PROC\n";
199
OS << "\n";
200
OS << "#ifndef TUNE_PROC\n"
201
<< "#define TUNE_PROC(ENUM, NAME)\n"
202
<< "#endif\n\n";
203
204
for (const Record *Rec :
205
RK.getAllDerivedDefinitionsIfDefined("RISCVTuneProcessorModel")) {
206
OS << "TUNE_PROC(" << Rec->getName() << ", "
207
<< "\"" << Rec->getValueAsString("Name") << "\")\n";
208
}
209
210
OS << "\n#undef TUNE_PROC\n";
211
}
212
213
static void emitRISCVExtensionBitmask(RecordKeeper &RK, raw_ostream &OS) {
214
215
std::vector<Record *> Extensions =
216
RK.getAllDerivedDefinitionsIfDefined("RISCVExtensionBitmask");
217
llvm::sort(Extensions, [](const Record *Rec1, const Record *Rec2) {
218
return getExtensionName(Rec1) < getExtensionName(Rec2);
219
});
220
221
#ifndef NDEBUG
222
llvm::DenseSet<std::pair<uint64_t, uint64_t>> Seen;
223
#endif
224
225
OS << "#ifdef GET_RISCVExtensionBitmaskTable_IMPL\n";
226
OS << "static const RISCVExtensionBitmask ExtensionBitmask[]={\n";
227
for (const Record *Rec : Extensions) {
228
unsigned GroupIDVal = Rec->getValueAsInt("GroupID");
229
unsigned BitPosVal = Rec->getValueAsInt("BitPos");
230
231
StringRef ExtName = Rec->getValueAsString("Name");
232
ExtName.consume_front("experimental-");
233
234
#ifndef NDEBUG
235
assert(Seen.insert(std::make_pair(GroupIDVal, BitPosVal)).second &&
236
"duplicated bitmask");
237
#endif
238
239
OS << " {"
240
<< "\"" << ExtName << "\""
241
<< ", " << GroupIDVal << ", " << BitPosVal << "ULL"
242
<< "},\n";
243
}
244
OS << "};\n";
245
OS << "#endif\n";
246
}
247
248
static void EmitRISCVTargetDef(RecordKeeper &RK, raw_ostream &OS) {
249
emitRISCVExtensions(RK, OS);
250
emitRISCVProfiles(RK, OS);
251
emitRISCVProcs(RK, OS);
252
emitRISCVExtensionBitmask(RK, OS);
253
}
254
255
static TableGen::Emitter::Opt X("gen-riscv-target-def", EmitRISCVTargetDef,
256
"Generate the list of CPUs and extensions for "
257
"RISC-V");
258
259