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