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