LLVM 24.0.0git
DirectiveEmitter.h
Go to the documentation of this file.
1//===- DirectiveEmitter.h - Directive Language Emitter ----------*- C++ -*-===//
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// DirectiveEmitter uses the descriptions of directives and clauses to construct
10// common code declarations to be used in Frontends.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_TABLEGEN_DIRECTIVEEMITTER_H
15#define LLVM_TABLEGEN_DIRECTIVEEMITTER_H
16
17#include "llvm/ADT/STLExtras.h"
19#include "llvm/ADT/StringRef.h"
24#include <string>
25#include <vector>
26
27namespace llvm {
28
29// Wrapper class that contains DirectiveLanguage's information defined in
30// DirectiveBase.td and provides helper methods for accessing it.
32public:
33 explicit DirectiveLanguage(const RecordKeeper &Records) : Records(Records) {
34 const auto &DirectiveLanguages = getDirectiveLanguages();
35 Def = DirectiveLanguages[0];
36 }
37
38 StringRef getName() const { return Def->getValueAsString("name"); }
39
41 return Def->getValueAsString("cppNamespace");
42 }
43
45 return Def->getValueAsString("directivePrefix");
46 }
47
49 return Def->getValueAsString("clausePrefix");
50 }
51
53 return Def->getValueAsString("loopModifierPrefix");
54 }
55
57 return Def->getValueAsString("clauseEnumSetClass");
58 }
59
61 return Def->getValueAsString("flangClauseBaseClass");
62 }
63
65 return Def->getValueAsBit("makeEnumAvailableInNamespace");
66 }
67
69 return Def->getValueAsBit("enableBitmaskEnumInNamespace");
70 }
71
73 return Records.getAllDerivedDefinitions("Association");
74 }
75
77 return Records.getAllDerivedDefinitions("Category");
78 }
79
81 return Records.getAllDerivedDefinitions("SourceLanguage");
82 }
83
85 return Records.getAllDerivedDefinitions("Directive");
86 }
87
89 return Records.getAllDerivedDefinitions("Clause");
90 }
91
93 return Records.getAllDerivedDefinitions("LoopModifier");
94 }
95
96 bool HasValidityErrors() const;
97
98private:
99 const Record *Def;
100 const RecordKeeper &Records;
101
102 ArrayRef<const Record *> getDirectiveLanguages() const {
103 return Records.getAllDerivedDefinitions("DirectiveLanguage");
104 }
105};
106
108public:
109 unsigned getMinVersion(const Record *R) const {
110 int64_t Min = R->getValueAsInt("minVersion");
111 assert(Min >= 0 && llvm::isInt<IntWidth>(Min) &&
112 "Value out of range of non-negative 'int'");
113 return Min;
114 }
115
116 unsigned getMaxVersion(const Record *R) const {
117 int64_t Max = R->getValueAsInt("maxVersion");
118 assert(Max >= 0 && llvm::isInt<IntWidth>(Max) &&
119 "Value out of range of non-negative 'int'");
120 return Max;
121 }
122
123private:
124 constexpr static int IntWidth = 8 * sizeof(int);
125};
126
127class Spelling : public Versioned {
128public:
130
131 Spelling(const Record *Def) : Def(Def) {}
132
133 StringRef getText() const { return Def->getValueAsString("spelling"); }
139
140 Value get() const { return Value{getText(), getVersions()}; }
141
142private:
143 const Record *Def;
144};
145
146// Note: In all the classes below, allow implicit construction from Record *,
147// to allow writing code like:
148// for (const Directive D : getDirectives()) {
149//
150// instead of:
151//
152// for (const Record *R : getDirectives()) {
153// Directive D(R);
154
155// Base record class used for Directive and Clause class defined in
156// DirectiveBase.td.
158public:
160
161 std::vector<Spelling::Value> getSpellings() const {
162 std::vector<Spelling::Value> List;
163 llvm::transform(Def->getValueAsListOfDefs("spellings"),
164 std::back_inserter(List),
165 [](const Record *R) { return Spelling(R).get(); });
166 return List;
167 }
168
170 // From all spellings, pick the first one with the minimum version
171 // (i.e. pick the first from all the oldest ones). This guarantees
172 // that given several equivalent (in terms of versions) names, the
173 // first one is used, e.g. given
174 // Clause<[Spelling<"foo">, Spelling<"bar">]> ...
175 // "foo" will be the selected spelling.
176 //
177 // This is a suitable spelling for generating an identifier name,
178 // since it will remain unchanged when any potential new spellings
179 // are added.
181 Spelling::Value Oldest{"not found", {/*Min=*/Version::Max(), Version(0)}};
182 for (auto V : getSpellings())
183 if (V.Versions.Min < Oldest.Versions.Min)
184 Oldest = V;
185 return Oldest.Name;
186 }
187
188 // Returns the name of the directive formatted for output. Whitespace are
189 // replaced with underscores.
190 static std::string getSnakeName(StringRef Name) {
191 std::string N = Name.str();
192 llvm::replace(N, ' ', '_');
193 return N;
194 }
195
196 // Take a string Name with sub-words separated with characters from Sep,
197 // and return a string with each of the sub-words capitalized, and the
198 // separators removed, e.g.
199 // Name = "some_directive^name", Sep = "_^" -> "SomeDirectiveName".
200 static std::string getUpperCamelName(StringRef Name, StringRef Sep) {
201 std::string Camel = Name.str();
202 // Convert to uppercase
203 bool Cap = true;
204 llvm::transform(Camel, Camel.begin(), [&](unsigned char C) {
205 if (Sep.contains(C)) {
206 assert(!Cap && "No initial or repeated separators");
207 Cap = true;
208 } else if (Cap) {
209 C = llvm::toUpper(C);
210 Cap = false;
211 }
212 return C;
213 });
214 size_t Out = 0;
215 // Remove separators
216 for (size_t In = 0, End = Camel.size(); In != End; ++In) {
217 unsigned char C = Camel[In];
218 if (!Sep.contains(C))
219 Camel[Out++] = C;
220 }
221 Camel.resize(Out);
222 return Camel;
223 }
224
225 std::string getFormattedName() const {
226 if (auto maybeName = Def->getValueAsOptionalString("name"))
227 return getSnakeName(*maybeName);
229 }
230
231 bool isDefault() const { return Def->getValueAsBit("isDefault"); }
232
233 // Returns the record name.
234 StringRef getRecordName() const { return Def->getName(); }
235
236 const Record *getRecord() const { return Def; }
237
238protected:
239 const Record *Def;
240};
241
242// Wrapper class that contains a Directive's information defined in
243// DirectiveBase.td and provides helper methods for accessing it.
244class Directive : public BaseRecord {
245public:
247
248 std::vector<const Record *> getAllowedClauses() const {
249 return Def->getValueAsListOfDefs("allowedClauses");
250 }
251
252 std::vector<const Record *> getAllowedOnceClauses() const {
253 return Def->getValueAsListOfDefs("allowedOnceClauses");
254 }
255
256 std::vector<const Record *> getAllowedExclusiveClauses() const {
257 return Def->getValueAsListOfDefs("allowedExclusiveClauses");
258 }
259
260 std::vector<const Record *> getRequiredClauses() const {
261 return Def->getValueAsListOfDefs("requiredClauses");
262 }
263
264 std::vector<const Record *> getLeafConstructs() const {
265 return Def->getValueAsListOfDefs("leafConstructs");
266 }
267
268 const Record *getAssociation() const {
269 return Def->getValueAsDef("association");
270 }
271
272 const Record *getCategory() const { return Def->getValueAsDef("category"); }
273
274 std::vector<const Record *> getSourceLanguages() const {
275 return Def->getValueAsListOfDefs("languages");
276 }
277
278 std::vector<const Record *> getAllowedLoopModifiers() const {
279 return Def->getValueAsListOfDefs("allowedLoopModifiers");
280 }
281
282 int getPureSince() const { return Def->getValueAsInt("pureSince"); }
283
284 // Clang uses a different format for names of its directives enum.
285 std::string getClangAccSpelling() const {
287
288 // Clang calls the 'unknown' value 'invalid'.
289 if (Name == "unknown")
290 return "Invalid";
291
292 return BaseRecord::getUpperCamelName(Name, " _");
293 }
294};
295
296// Wrapper class that contains Clause's information defined in DirectiveBase.td
297// and provides helper methods for accessing it.
298class Clause : public BaseRecord {
299public:
301
302 // Optional field.
304 return Def->getValueAsString("clangClass");
305 }
306
307 // Optional field.
309 return Def->getValueAsString("flangClass");
310 }
311
312 // Get the formatted name for Flang parser class. The generic formatted class
313 // name is constructed from the name were the first letter of each word is
314 // captitalized and the underscores are removed.
315 // ex: async -> Async
316 // num_threads -> NumThreads
317 std::string getFormattedParserClassName() const {
318 std::string Name = getFormattedName();
319 return BaseRecord::getUpperCamelName(Name, "_");
320 }
321
322 // Clang uses a different format for names of its clause enum, which can be
323 // overwritten with the `clangSpelling` value. So get the proper spelling
324 // here.
325 std::string getClangAccSpelling() const {
326 if (StringRef ClangSpelling = Def->getValueAsString("clangAccSpelling");
327 !ClangSpelling.empty())
328 return ClangSpelling.str();
329
331 return BaseRecord::getUpperCamelName(Name, "_");
332 }
333
334 // Optional field.
336 return Def->getValueAsString("enumClauseValue");
337 }
338
339 std::vector<const Record *> getClauseVals() const {
340 return Def->getValueAsListOfDefs("allowedClauseValues");
341 }
342
343 bool skipFlangUnparser() const {
344 return Def->getValueAsBit("skipFlangUnparser");
345 }
346
347 bool isValueOptional() const { return Def->getValueAsBit("isValueOptional"); }
348
349 bool isValueList() const { return Def->getValueAsBit("isValueList"); }
350
352 return Def->getValueAsString("defaultValue");
353 }
354
355 bool isImplicit() const { return Def->getValueAsBit("isImplicit"); }
356
357 std::vector<StringRef> getAliases() const {
358 return Def->getValueAsListOfStrings("aliases");
359 }
360
361 StringRef getPrefix() const { return Def->getValueAsString("prefix"); }
362
363 bool isPrefixOptional() const {
364 return Def->getValueAsBit("isPrefixOptional");
365 }
366};
367
368// Wrapper class that contains VersionedClause's information defined in
369// DirectiveBase.td and provides helper methods for accessing it.
371public:
372 VersionedClause(const Record *Def) : Def(Def) {}
373
374 // Return the specific clause record wrapped in the Clause class.
375 Clause getClause() const { return Clause(Def->getValueAsDef("clause")); }
376
377 int64_t getMinVersion() const { return Def->getValueAsInt("minVersion"); }
378
379 int64_t getMaxVersion() const { return Def->getValueAsInt("maxVersion"); }
380
381private:
382 const Record *Def;
383};
384
385class EnumVal : public BaseRecord {
386public:
388
389 int getValue() const { return Def->getValueAsInt("value"); }
390
391 bool isUserVisible() const { return Def->getValueAsBit("isUserValue"); }
392};
393
394} // namespace llvm
395
396#endif // LLVM_TABLEGEN_DIRECTIVEEMITTER_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
if(PassOpts->AAPipeline)
This file contains some templates that are useful if you are working with the STL at all.
This file contains some functions that are useful when dealing with strings.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
StringRef getSpellingForIdentifier() const
static std::string getSnakeName(StringRef Name)
StringRef getRecordName() const
static std::string getUpperCamelName(StringRef Name, StringRef Sep)
bool isDefault() const
std::string getFormattedName() const
const Record * Def
std::vector< Spelling::Value > getSpellings() const
BaseRecord(const Record *Def)
const Record * getRecord() const
StringRef getClangClass() const
std::vector< const Record * > getClauseVals() const
bool skipFlangUnparser() const
Clause(const Record *Def)
bool isImplicit() const
StringRef getDefaultValue() const
bool isValueOptional() const
bool isValueList() const
StringRef getFlangClass() const
std::vector< StringRef > getAliases() const
std::string getClangAccSpelling() const
StringRef getEnumName() const
bool isPrefixOptional() const
std::string getFormattedParserClassName() const
StringRef getPrefix() const
bool hasMakeEnumAvailableInNamespace() const
bool HasValidityErrors() const
StringRef getClausePrefix() const
StringRef getClauseEnumSetClass() const
DirectiveLanguage(const RecordKeeper &Records)
ArrayRef< const Record * > getAssociations() const
StringRef getLoopModifierPrefix() const
ArrayRef< const Record * > getDirectives() const
ArrayRef< const Record * > getClauses() const
ArrayRef< const Record * > getLoopModifiers() const
StringRef getName() const
ArrayRef< const Record * > getCategories() const
StringRef getDirectivePrefix() const
bool hasEnableBitmaskEnumInNamespace() const
StringRef getCppNamespace() const
ArrayRef< const Record * > getSourceLanguages() const
StringRef getFlangClauseBaseClass() const
const Record * getAssociation() const
std::vector< const Record * > getLeafConstructs() const
const Record * getCategory() const
std::vector< const Record * > getAllowedClauses() const
Directive(const Record *Def)
std::vector< const Record * > getAllowedOnceClauses() const
std::vector< const Record * > getRequiredClauses() const
std::vector< const Record * > getSourceLanguages() const
std::vector< const Record * > getAllowedLoopModifiers() const
int getPureSince() const
std::string getClangAccSpelling() const
std::vector< const Record * > getAllowedExclusiveClauses() const
bool isUserVisible() const
int getValue() const
EnumVal(const Record *Def)
Spelling(const Record *Def)
StringRef getText() const
Value get() const
directive::Spelling Value
llvm::directive::VersionRange getVersions() const
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
int64_t getMinVersion() const
int64_t getMaxVersion() const
VersionedClause(const Record *Def)
unsigned getMinVersion(const Record *R) const
unsigned getMaxVersion(const Record *R) const
This is an optimization pass for GlobalISel generic memory operations.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
OutputIt transform(R &&Range, OutputIt d_first, UnaryFunction F)
Wrapper function around std::transform to apply a function to a range and store the result elsewhere.
Definition STLExtras.h:2042
void replace(R &&Range, const T &OldValue, const T &NewValue)
Provide wrappers to std::replace which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1926
char toUpper(char x)
Returns the corresponding uppercase character if x is lowercase.
@ End
Run the machine verifier once, at the end of the pipeline.
Definition CodeGen.h:320
#define N
VersionRange Versions
Definition Spelling.h:22