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