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