LLVM 22.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"
23#include <string>
24#include <vector>
25
26namespace llvm {
27
28// Wrapper class that contains DirectiveLanguage's information defined in
29// DirectiveBase.td and provides helper methods for accessing it.
31public:
32 explicit DirectiveLanguage(const RecordKeeper &Records) : Records(Records) {
33 const auto &DirectiveLanguages = getDirectiveLanguages();
34 Def = DirectiveLanguages[0];
35 }
36
37 StringRef getName() const { return Def->getValueAsString("name"); }
38
40 return Def->getValueAsString("cppNamespace");
41 }
42
44 return Def->getValueAsString("directivePrefix");
45 }
46
48 return Def->getValueAsString("clausePrefix");
49 }
50
52 return Def->getValueAsString("clauseEnumSetClass");
53 }
54
56 return Def->getValueAsString("flangClauseBaseClass");
57 }
58
60 return Def->getValueAsBit("makeEnumAvailableInNamespace");
61 }
62
64 return Def->getValueAsBit("enableBitmaskEnumInNamespace");
65 }
66
68 return Records.getAllDerivedDefinitions("Association");
69 }
70
72 return Records.getAllDerivedDefinitions("Category");
73 }
74
76 return Records.getAllDerivedDefinitions("SourceLanguage");
77 }
78
80 return Records.getAllDerivedDefinitions("Directive");
81 }
82
84 return Records.getAllDerivedDefinitions("Clause");
85 }
86
87 bool HasValidityErrors() const;
88
89private:
90 const Record *Def;
91 const RecordKeeper &Records;
92
93 ArrayRef<const Record *> getDirectiveLanguages() const {
94 return Records.getAllDerivedDefinitions("DirectiveLanguage");
95 }
96};
97
98class Versioned {
99public:
100 int getMinVersion(const Record *R) const {
101 int64_t Min = R->getValueAsInt("minVersion");
102 assert(llvm::isInt<IntWidth>(Min) && "Value out of range of 'int'");
103 return Min;
104 }
105
106 int getMaxVersion(const Record *R) const {
107 int64_t Max = R->getValueAsInt("maxVersion");
108 assert(llvm::isInt<IntWidth>(Max) && "Value out of range of 'int'");
109 return Max;
110 }
111
112private:
113 constexpr static int IntWidth = 8 * sizeof(int);
114};
115
116class Spelling : public Versioned {
117public:
119
120 Spelling(const Record *Def) : Def(Def) {}
121
122 StringRef getText() const { return Def->getValueAsString("spelling"); }
127
128 Value get() const { return Value{getText(), getVersions()}; }
129
130private:
131 const Record *Def;
132};
133
134// Note: In all the classes below, allow implicit construction from Record *,
135// to allow writing code like:
136// for (const Directive D : getDirectives()) {
137//
138// instead of:
139//
140// for (const Record *R : getDirectives()) {
141// Directive D(R);
142
143// Base record class used for Directive and Clause class defined in
144// DirectiveBase.td.
146public:
148
149 std::vector<Spelling::Value> getSpellings() const {
150 std::vector<Spelling::Value> List;
151 llvm::transform(Def->getValueAsListOfDefs("spellings"),
152 std::back_inserter(List),
153 [](const Record *R) { return Spelling(R).get(); });
154 return List;
155 }
156
158 // From all spellings, pick the first one with the minimum version
159 // (i.e. pick the first from all the oldest ones). This guarantees
160 // that given several equivalent (in terms of versions) names, the
161 // first one is used, e.g. given
162 // Clause<[Spelling<"foo">, Spelling<"bar">]> ...
163 // "foo" will be the selected spelling.
164 //
165 // This is a suitable spelling for generating an identifier name,
166 // since it will remain unchanged when any potential new spellings
167 // are added.
168 Spelling::Value Oldest{"not found", {/*Min=*/INT_MAX, 0}};
169 for (auto V : getSpellings())
170 if (V.Versions.Min < Oldest.Versions.Min)
171 Oldest = V;
172 return Oldest.Name;
173 }
174
175 // Returns the name of the directive formatted for output. Whitespace are
176 // replaced with underscores.
177 static std::string getSnakeName(StringRef Name) {
178 std::string N = Name.str();
179 llvm::replace(N, ' ', '_');
180 return N;
181 }
182
183 // Take a string Name with sub-words separated with characters from Sep,
184 // and return a string with each of the sub-words capitalized, and the
185 // separators removed, e.g.
186 // Name = "some_directive^name", Sep = "_^" -> "SomeDirectiveName".
187 static std::string getUpperCamelName(StringRef Name, StringRef Sep) {
188 std::string Camel = Name.str();
189 // Convert to uppercase
190 bool Cap = true;
191 llvm::transform(Camel, Camel.begin(), [&](unsigned char C) {
192 if (Sep.contains(C)) {
193 assert(!Cap && "No initial or repeated separators");
194 Cap = true;
195 } else if (Cap) {
196 C = llvm::toUpper(C);
197 Cap = false;
198 }
199 return C;
200 });
201 size_t Out = 0;
202 // Remove separators
203 for (size_t In = 0, End = Camel.size(); In != End; ++In) {
204 unsigned char C = Camel[In];
205 if (!Sep.contains(C))
206 Camel[Out++] = C;
207 }
208 Camel.resize(Out);
209 return Camel;
210 }
211
212 std::string getFormattedName() const {
213 if (auto maybeName = Def->getValueAsOptionalString("name"))
214 return getSnakeName(*maybeName);
216 }
217
218 bool isDefault() const { return Def->getValueAsBit("isDefault"); }
219
220 // Returns the record name.
221 StringRef getRecordName() const { return Def->getName(); }
222
223 const Record *getRecord() const { return Def; }
224
225protected:
226 const Record *Def;
227};
228
229// Wrapper class that contains a Directive's information defined in
230// DirectiveBase.td and provides helper methods for accessing it.
231class Directive : public BaseRecord {
232public:
234
235 std::vector<const Record *> getAllowedClauses() const {
236 return Def->getValueAsListOfDefs("allowedClauses");
237 }
238
239 std::vector<const Record *> getAllowedOnceClauses() const {
240 return Def->getValueAsListOfDefs("allowedOnceClauses");
241 }
242
243 std::vector<const Record *> getAllowedExclusiveClauses() const {
244 return Def->getValueAsListOfDefs("allowedExclusiveClauses");
245 }
246
247 std::vector<const Record *> getRequiredClauses() const {
248 return Def->getValueAsListOfDefs("requiredClauses");
249 }
250
251 std::vector<const Record *> getLeafConstructs() const {
252 return Def->getValueAsListOfDefs("leafConstructs");
253 }
254
255 const Record *getAssociation() const {
256 return Def->getValueAsDef("association");
257 }
258
259 const Record *getCategory() const { return Def->getValueAsDef("category"); }
260
261 std::vector<const Record *> getSourceLanguages() const {
262 return Def->getValueAsListOfDefs("languages");
263 }
264
265 // Clang uses a different format for names of its directives enum.
266 std::string getClangAccSpelling() const {
268
269 // Clang calls the 'unknown' value 'invalid'.
270 if (Name == "unknown")
271 return "Invalid";
272
273 return BaseRecord::getUpperCamelName(Name, " _");
274 }
275};
276
277// Wrapper class that contains Clause's information defined in DirectiveBase.td
278// and provides helper methods for accessing it.
279class Clause : public BaseRecord {
280public:
282
283 // Optional field.
285 return Def->getValueAsString("clangClass");
286 }
287
288 // Optional field.
290 return Def->getValueAsString("flangClass");
291 }
292
293 // Get the formatted name for Flang parser class. The generic formatted class
294 // name is constructed from the name were the first letter of each word is
295 // captitalized and the underscores are removed.
296 // ex: async -> Async
297 // num_threads -> NumThreads
298 std::string getFormattedParserClassName() const {
300 return BaseRecord::getUpperCamelName(Name, "_");
301 }
302
303 // Clang uses a different format for names of its clause enum, which can be
304 // overwritten with the `clangSpelling` value. So get the proper spelling
305 // here.
306 std::string getClangAccSpelling() const {
307 if (StringRef ClangSpelling = Def->getValueAsString("clangAccSpelling");
308 !ClangSpelling.empty())
309 return ClangSpelling.str();
310
312 return BaseRecord::getUpperCamelName(Name, "_");
313 }
314
315 // Optional field.
317 return Def->getValueAsString("enumClauseValue");
318 }
319
320 std::vector<const Record *> getClauseVals() const {
321 return Def->getValueAsListOfDefs("allowedClauseValues");
322 }
323
324 bool skipFlangUnparser() const {
325 return Def->getValueAsBit("skipFlangUnparser");
326 }
327
328 bool isValueOptional() const { return Def->getValueAsBit("isValueOptional"); }
329
330 bool isValueList() const { return Def->getValueAsBit("isValueList"); }
331
333 return Def->getValueAsString("defaultValue");
334 }
335
336 bool isImplicit() const { return Def->getValueAsBit("isImplicit"); }
337
338 std::vector<StringRef> getAliases() const {
339 return Def->getValueAsListOfStrings("aliases");
340 }
341
342 StringRef getPrefix() const { return Def->getValueAsString("prefix"); }
343
344 bool isPrefixOptional() const {
345 return Def->getValueAsBit("isPrefixOptional");
346 }
347};
348
349// Wrapper class that contains VersionedClause's information defined in
350// DirectiveBase.td and provides helper methods for accessing it.
352public:
353 VersionedClause(const Record *Def) : Def(Def) {}
354
355 // Return the specific clause record wrapped in the Clause class.
356 Clause getClause() const { return Clause(Def->getValueAsDef("clause")); }
357
358 int64_t getMinVersion() const { return Def->getValueAsInt("minVersion"); }
359
360 int64_t getMaxVersion() const { return Def->getValueAsInt("maxVersion"); }
361
362private:
363 const Record *Def;
364};
365
366class EnumVal : public BaseRecord {
367public:
369
370 int getValue() const { return Def->getValueAsInt("value"); }
371
372 bool isUserVisible() const { return Def->getValueAsBit("isUserValue"); }
373};
374
375} // namespace llvm
376
377#endif // LLVM_TABLEGEN_DIRECTIVEEMITTER_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:41
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
ArrayRef< const Record * > getDirectives() const
ArrayRef< const Record * > getClauses() 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::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
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
int64_t getMinVersion() const
int64_t getMaxVersion() const
VersionedClause(const Record *Def)
int getMinVersion(const Record *R) const
int getMaxVersion(const Record *R) const
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
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:165
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:1968
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:1860
char toUpper(char x)
Returns the corresponding uppercase character if x is lowercase.
#define N
VersionRange Versions
Definition Spelling.h:34