xref: /llvm-project/llvm/include/llvm/TableGen/DirectiveEmitter.h (revision d256b9e88b7aa9155380a4e70d39a2a0121ff917)
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"
18 #include "llvm/ADT/StringExtras.h"
19 #include "llvm/ADT/StringRef.h"
20 #include "llvm/TableGen/Record.h"
21 #include <algorithm>
22 #include <string>
23 #include <vector>
24 
25 namespace llvm {
26 
27 // Wrapper class that contains DirectiveLanguage's information defined in
28 // DirectiveBase.td and provides helper methods for accessing it.
29 class DirectiveLanguage {
30 public:
31   explicit DirectiveLanguage(const RecordKeeper &Records) : Records(Records) {
32     const auto &DirectiveLanguages = getDirectiveLanguages();
33     Def = DirectiveLanguages[0];
34   }
35 
36   StringRef getName() const { return Def->getValueAsString("name"); }
37 
38   StringRef getCppNamespace() const {
39     return Def->getValueAsString("cppNamespace");
40   }
41 
42   StringRef getDirectivePrefix() const {
43     return Def->getValueAsString("directivePrefix");
44   }
45 
46   StringRef getClausePrefix() const {
47     return Def->getValueAsString("clausePrefix");
48   }
49 
50   StringRef getClauseEnumSetClass() const {
51     return Def->getValueAsString("clauseEnumSetClass");
52   }
53 
54   StringRef getFlangClauseBaseClass() const {
55     return Def->getValueAsString("flangClauseBaseClass");
56   }
57 
58   bool hasMakeEnumAvailableInNamespace() const {
59     return Def->getValueAsBit("makeEnumAvailableInNamespace");
60   }
61 
62   bool hasEnableBitmaskEnumInNamespace() const {
63     return Def->getValueAsBit("enableBitmaskEnumInNamespace");
64   }
65 
66   ArrayRef<const Record *> getAssociations() const {
67     return Records.getAllDerivedDefinitions("Association");
68   }
69 
70   ArrayRef<const Record *> getCategories() const {
71     return Records.getAllDerivedDefinitions("Category");
72   }
73 
74   ArrayRef<const Record *> getDirectives() const {
75     return Records.getAllDerivedDefinitions("Directive");
76   }
77 
78   ArrayRef<const Record *> getClauses() const {
79     return Records.getAllDerivedDefinitions("Clause");
80   }
81 
82   bool HasValidityErrors() const;
83 
84 private:
85   const Record *Def;
86   const RecordKeeper &Records;
87 
88   ArrayRef<const Record *> getDirectiveLanguages() const {
89     return Records.getAllDerivedDefinitions("DirectiveLanguage");
90   }
91 };
92 
93 // Note: In all the classes below, allow implicit construction from Record *,
94 // to allow writing code like:
95 //  for (const Directive D : getDirectives()) {
96 //
97 //  instead of:
98 //
99 //  for (const Record *R : getDirectives()) {
100 //    Directive D(R);
101 
102 // Base record class used for Directive and Clause class defined in
103 // DirectiveBase.td.
104 class BaseRecord {
105 public:
106   BaseRecord(const Record *Def) : Def(Def) {}
107 
108   StringRef getName() const { return Def->getValueAsString("name"); }
109 
110   StringRef getAlternativeName() const {
111     return Def->getValueAsString("alternativeName");
112   }
113 
114   // Returns the name of the directive formatted for output. Whitespace are
115   // replaced with underscores.
116   std::string getFormattedName() const {
117     StringRef Name = Def->getValueAsString("name");
118     std::string N = Name.str();
119     std::replace(N.begin(), N.end(), ' ', '_');
120     return N;
121   }
122 
123   bool isDefault() const { return Def->getValueAsBit("isDefault"); }
124 
125   // Returns the record name.
126   StringRef getRecordName() const { return Def->getName(); }
127 
128 protected:
129   const Record *Def;
130 };
131 
132 // Wrapper class that contains a Directive's information defined in
133 // DirectiveBase.td and provides helper methods for accessing it.
134 class Directive : public BaseRecord {
135 public:
136   Directive(const Record *Def) : BaseRecord(Def) {}
137 
138   std::vector<const Record *> getAllowedClauses() const {
139     return Def->getValueAsListOfDefs("allowedClauses");
140   }
141 
142   std::vector<const Record *> getAllowedOnceClauses() const {
143     return Def->getValueAsListOfDefs("allowedOnceClauses");
144   }
145 
146   std::vector<const Record *> getAllowedExclusiveClauses() const {
147     return Def->getValueAsListOfDefs("allowedExclusiveClauses");
148   }
149 
150   std::vector<const Record *> getRequiredClauses() const {
151     return Def->getValueAsListOfDefs("requiredClauses");
152   }
153 
154   std::vector<const Record *> getLeafConstructs() const {
155     return Def->getValueAsListOfDefs("leafConstructs");
156   }
157 
158   const Record *getAssociation() const {
159     return Def->getValueAsDef("association");
160   }
161 
162   const Record *getCategory() const { return Def->getValueAsDef("category"); }
163 };
164 
165 // Wrapper class that contains Clause's information defined in DirectiveBase.td
166 // and provides helper methods for accessing it.
167 class Clause : public BaseRecord {
168 public:
169   Clause(const Record *Def) : BaseRecord(Def) {}
170 
171   // Optional field.
172   StringRef getClangClass() const {
173     return Def->getValueAsString("clangClass");
174   }
175 
176   // Optional field.
177   StringRef getFlangClass() const {
178     return Def->getValueAsString("flangClass");
179   }
180 
181   // Get the formatted name for Flang parser class. The generic formatted class
182   // name is constructed from the name were the first letter of each word is
183   // captitalized and the underscores are removed.
184   // ex: async -> Async
185   //     num_threads -> NumThreads
186   std::string getFormattedParserClassName() const {
187     StringRef Name = Def->getValueAsString("name");
188     std::string N = Name.str();
189     bool Cap = true;
190     std::transform(N.begin(), N.end(), N.begin(), [&Cap](unsigned char C) {
191       if (Cap == true) {
192         C = toUpper(C);
193         Cap = false;
194       } else if (C == '_') {
195         Cap = true;
196       }
197       return C;
198     });
199     erase(N, '_');
200     return N;
201   }
202 
203   // Optional field.
204   StringRef getEnumName() const {
205     return Def->getValueAsString("enumClauseValue");
206   }
207 
208   std::vector<const Record *> getClauseVals() const {
209     return Def->getValueAsListOfDefs("allowedClauseValues");
210   }
211 
212   bool isValueOptional() const { return Def->getValueAsBit("isValueOptional"); }
213 
214   bool isValueList() const { return Def->getValueAsBit("isValueList"); }
215 
216   StringRef getDefaultValue() const {
217     return Def->getValueAsString("defaultValue");
218   }
219 
220   bool isImplicit() const { return Def->getValueAsBit("isImplicit"); }
221 
222   std::vector<StringRef> getAliases() const {
223     return Def->getValueAsListOfStrings("aliases");
224   }
225 
226   StringRef getPrefix() const { return Def->getValueAsString("prefix"); }
227 
228   bool isPrefixOptional() const {
229     return Def->getValueAsBit("isPrefixOptional");
230   }
231 };
232 
233 // Wrapper class that contains VersionedClause's information defined in
234 // DirectiveBase.td and provides helper methods for accessing it.
235 class VersionedClause {
236 public:
237   VersionedClause(const Record *Def) : Def(Def) {}
238 
239   // Return the specific clause record wrapped in the Clause class.
240   Clause getClause() const { return Clause(Def->getValueAsDef("clause")); }
241 
242   int64_t getMinVersion() const { return Def->getValueAsInt("minVersion"); }
243 
244   int64_t getMaxVersion() const { return Def->getValueAsInt("maxVersion"); }
245 
246 private:
247   const Record *Def;
248 };
249 
250 class ClauseVal : public BaseRecord {
251 public:
252   ClauseVal(const Record *Def) : BaseRecord(Def) {}
253 
254   int getValue() const { return Def->getValueAsInt("value"); }
255 
256   bool isUserVisible() const { return Def->getValueAsBit("isUserValue"); }
257 };
258 
259 } // namespace llvm
260 
261 #endif // LLVM_TABLEGEN_DIRECTIVEEMITTER_H
262