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