1 //===- DirectiveEmitter.cpp - Directive Language Emitter ------------------===// 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 #include "llvm/TableGen/DirectiveEmitter.h" 15 #include "llvm/ADT/DenseMap.h" 16 #include "llvm/ADT/DenseSet.h" 17 #include "llvm/ADT/STLExtras.h" 18 #include "llvm/ADT/SmallVector.h" 19 #include "llvm/ADT/StringSet.h" 20 #include "llvm/ADT/StringSwitch.h" 21 #include "llvm/TableGen/Error.h" 22 #include "llvm/TableGen/Record.h" 23 #include "llvm/TableGen/TableGenBackend.h" 24 25 #include <numeric> 26 #include <vector> 27 28 using namespace llvm; 29 30 namespace { 31 // Simple RAII helper for defining ifdef-undef-endif scopes. 32 class IfDefScope { 33 public: 34 IfDefScope(StringRef Name, raw_ostream &OS) : Name(Name), OS(OS) { 35 OS << "#ifdef " << Name << "\n" 36 << "#undef " << Name << "\n"; 37 } 38 39 ~IfDefScope() { OS << "\n#endif // " << Name << "\n\n"; } 40 41 private: 42 StringRef Name; 43 raw_ostream &OS; 44 }; 45 } // namespace 46 47 // Generate enum class. Entries are emitted in the order in which they appear 48 // in the `Records` vector. 49 static void GenerateEnumClass(const std::vector<Record *> &Records, 50 raw_ostream &OS, StringRef Enum, StringRef Prefix, 51 const DirectiveLanguage &DirLang, 52 bool ExportEnums) { 53 OS << "\n"; 54 OS << "enum class " << Enum << " {\n"; 55 for (const auto &R : Records) { 56 BaseRecord Rec{R}; 57 OS << " " << Prefix << Rec.getFormattedName() << ",\n"; 58 } 59 OS << "};\n"; 60 OS << "\n"; 61 OS << "static constexpr std::size_t " << Enum 62 << "_enumSize = " << Records.size() << ";\n"; 63 64 // Make the enum values available in the defined namespace. This allows us to 65 // write something like Enum_X if we have a `using namespace <CppNamespace>`. 66 // At the same time we do not loose the strong type guarantees of the enum 67 // class, that is we cannot pass an unsigned as Directive without an explicit 68 // cast. 69 if (ExportEnums) { 70 OS << "\n"; 71 for (const auto &R : Records) { 72 BaseRecord Rec{R}; 73 OS << "constexpr auto " << Prefix << Rec.getFormattedName() << " = " 74 << "llvm::" << DirLang.getCppNamespace() << "::" << Enum 75 << "::" << Prefix << Rec.getFormattedName() << ";\n"; 76 } 77 } 78 } 79 80 // Generate enums for values that clauses can take. 81 // Also generate function declarations for get<Enum>Name(StringRef Str). 82 static void GenerateEnumClauseVal(const std::vector<Record *> &Records, 83 raw_ostream &OS, 84 const DirectiveLanguage &DirLang, 85 std::string &EnumHelperFuncs) { 86 for (const auto &R : Records) { 87 Clause C{R}; 88 const auto &ClauseVals = C.getClauseVals(); 89 if (ClauseVals.size() <= 0) 90 continue; 91 92 const auto &EnumName = C.getEnumName(); 93 if (EnumName.size() == 0) { 94 PrintError("enumClauseValue field not set in Clause" + 95 C.getFormattedName() + "."); 96 return; 97 } 98 99 OS << "\n"; 100 OS << "enum class " << EnumName << " {\n"; 101 for (const auto &CV : ClauseVals) { 102 ClauseVal CVal{CV}; 103 OS << " " << CV->getName() << "=" << CVal.getValue() << ",\n"; 104 } 105 OS << "};\n"; 106 107 if (DirLang.hasMakeEnumAvailableInNamespace()) { 108 OS << "\n"; 109 for (const auto &CV : ClauseVals) { 110 OS << "constexpr auto " << CV->getName() << " = " 111 << "llvm::" << DirLang.getCppNamespace() << "::" << EnumName 112 << "::" << CV->getName() << ";\n"; 113 } 114 EnumHelperFuncs += (llvm::Twine(EnumName) + llvm::Twine(" get") + 115 llvm::Twine(EnumName) + llvm::Twine("(StringRef);\n")) 116 .str(); 117 118 EnumHelperFuncs += 119 (llvm::Twine("llvm::StringRef get") + llvm::Twine(DirLang.getName()) + 120 llvm::Twine(EnumName) + llvm::Twine("Name(") + 121 llvm::Twine(EnumName) + llvm::Twine(");\n")) 122 .str(); 123 } 124 } 125 } 126 127 static bool HasDuplicateClauses(const std::vector<Record *> &Clauses, 128 const Directive &Directive, 129 llvm::StringSet<> &CrtClauses) { 130 bool HasError = false; 131 for (const auto &C : Clauses) { 132 VersionedClause VerClause{C}; 133 const auto insRes = CrtClauses.insert(VerClause.getClause().getName()); 134 if (!insRes.second) { 135 PrintError("Clause " + VerClause.getClause().getRecordName() + 136 " already defined on directive " + Directive.getRecordName()); 137 HasError = true; 138 } 139 } 140 return HasError; 141 } 142 143 // Check for duplicate clauses in lists. Clauses cannot appear twice in the 144 // three allowed list. Also, since required implies allowed, clauses cannot 145 // appear in both the allowedClauses and requiredClauses lists. 146 static bool 147 HasDuplicateClausesInDirectives(const std::vector<Record *> &Directives) { 148 bool HasDuplicate = false; 149 for (const auto &D : Directives) { 150 Directive Dir{D}; 151 llvm::StringSet<> Clauses; 152 // Check for duplicates in the three allowed lists. 153 if (HasDuplicateClauses(Dir.getAllowedClauses(), Dir, Clauses) || 154 HasDuplicateClauses(Dir.getAllowedOnceClauses(), Dir, Clauses) || 155 HasDuplicateClauses(Dir.getAllowedExclusiveClauses(), Dir, Clauses)) { 156 HasDuplicate = true; 157 } 158 // Check for duplicate between allowedClauses and required 159 Clauses.clear(); 160 if (HasDuplicateClauses(Dir.getAllowedClauses(), Dir, Clauses) || 161 HasDuplicateClauses(Dir.getRequiredClauses(), Dir, Clauses)) { 162 HasDuplicate = true; 163 } 164 if (HasDuplicate) 165 PrintFatalError("One or more clauses are defined multiple times on" 166 " directive " + 167 Dir.getRecordName()); 168 } 169 170 return HasDuplicate; 171 } 172 173 // Check consitency of records. Return true if an error has been detected. 174 // Return false if the records are valid. 175 bool DirectiveLanguage::HasValidityErrors() const { 176 if (getDirectiveLanguages().size() != 1) { 177 PrintFatalError("A single definition of DirectiveLanguage is needed."); 178 return true; 179 } 180 181 return HasDuplicateClausesInDirectives(getDirectives()); 182 } 183 184 // Count the maximum number of leaf constituents per construct. 185 static size_t GetMaxLeafCount(const DirectiveLanguage &DirLang) { 186 size_t MaxCount = 0; 187 for (Record *R : DirLang.getDirectives()) { 188 size_t Count = Directive{R}.getLeafConstructs().size(); 189 MaxCount = std::max(MaxCount, Count); 190 } 191 return MaxCount; 192 } 193 194 // Generate the declaration section for the enumeration in the directive 195 // language 196 static void EmitDirectivesDecl(RecordKeeper &Records, raw_ostream &OS) { 197 const auto DirLang = DirectiveLanguage{Records}; 198 if (DirLang.HasValidityErrors()) 199 return; 200 201 OS << "#ifndef LLVM_" << DirLang.getName() << "_INC\n"; 202 OS << "#define LLVM_" << DirLang.getName() << "_INC\n"; 203 OS << "\n#include \"llvm/ADT/ArrayRef.h\"\n"; 204 205 if (DirLang.hasEnableBitmaskEnumInNamespace()) 206 OS << "#include \"llvm/ADT/BitmaskEnum.h\"\n"; 207 208 OS << "#include <cstddef>\n"; // for size_t 209 OS << "\n"; 210 OS << "namespace llvm {\n"; 211 OS << "class StringRef;\n"; 212 213 // Open namespaces defined in the directive language 214 llvm::SmallVector<StringRef, 2> Namespaces; 215 llvm::SplitString(DirLang.getCppNamespace(), Namespaces, "::"); 216 for (auto Ns : Namespaces) 217 OS << "namespace " << Ns << " {\n"; 218 219 if (DirLang.hasEnableBitmaskEnumInNamespace()) 220 OS << "\nLLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();\n"; 221 222 // Emit Directive associations 223 std::vector<Record *> associations; 224 llvm::copy_if( 225 DirLang.getAssociations(), std::back_inserter(associations), 226 // Skip the "special" value 227 [](const Record *Def) { return Def->getName() != "AS_FromLeaves"; }); 228 GenerateEnumClass(associations, OS, "Association", 229 /*Prefix=*/"", DirLang, /*ExportEnums=*/false); 230 231 GenerateEnumClass(DirLang.getCategories(), OS, "Category", /*Prefix=*/"", 232 DirLang, /*ExportEnums=*/false); 233 234 // Emit Directive enumeration 235 GenerateEnumClass(DirLang.getDirectives(), OS, "Directive", 236 DirLang.getDirectivePrefix(), DirLang, 237 DirLang.hasMakeEnumAvailableInNamespace()); 238 239 // Emit Clause enumeration 240 GenerateEnumClass(DirLang.getClauses(), OS, "Clause", 241 DirLang.getClausePrefix(), DirLang, 242 DirLang.hasMakeEnumAvailableInNamespace()); 243 244 // Emit ClauseVal enumeration 245 std::string EnumHelperFuncs; 246 GenerateEnumClauseVal(DirLang.getClauses(), OS, DirLang, EnumHelperFuncs); 247 248 // Generic function signatures 249 OS << "\n"; 250 OS << "// Enumeration helper functions\n"; 251 OS << "Directive get" << DirLang.getName() 252 << "DirectiveKind(llvm::StringRef Str);\n"; 253 OS << "\n"; 254 OS << "llvm::StringRef get" << DirLang.getName() 255 << "DirectiveName(Directive D);\n"; 256 OS << "\n"; 257 OS << "Clause get" << DirLang.getName() 258 << "ClauseKind(llvm::StringRef Str);\n"; 259 OS << "\n"; 260 OS << "llvm::StringRef get" << DirLang.getName() << "ClauseName(Clause C);\n"; 261 OS << "\n"; 262 OS << "/// Return true if \\p C is a valid clause for \\p D in version \\p " 263 << "Version.\n"; 264 OS << "bool isAllowedClauseForDirective(Directive D, " 265 << "Clause C, unsigned Version);\n"; 266 OS << "\n"; 267 OS << "constexpr std::size_t getMaxLeafCount() { return " 268 << GetMaxLeafCount(DirLang) << "; }\n"; 269 OS << "Association getDirectiveAssociation(Directive D);\n"; 270 OS << "Category getDirectiveCategory(Directive D);\n"; 271 if (EnumHelperFuncs.length() > 0) { 272 OS << EnumHelperFuncs; 273 OS << "\n"; 274 } 275 276 // Closing namespaces 277 for (auto Ns : llvm::reverse(Namespaces)) 278 OS << "} // namespace " << Ns << "\n"; 279 280 OS << "} // namespace llvm\n"; 281 282 OS << "#endif // LLVM_" << DirLang.getName() << "_INC\n"; 283 } 284 285 // Generate function implementation for get<Enum>Name(StringRef Str) 286 static void GenerateGetName(const std::vector<Record *> &Records, 287 raw_ostream &OS, StringRef Enum, 288 const DirectiveLanguage &DirLang, 289 StringRef Prefix) { 290 OS << "\n"; 291 OS << "llvm::StringRef llvm::" << DirLang.getCppNamespace() << "::get" 292 << DirLang.getName() << Enum << "Name(" << Enum << " Kind) {\n"; 293 OS << " switch (Kind) {\n"; 294 for (const auto &R : Records) { 295 BaseRecord Rec{R}; 296 OS << " case " << Prefix << Rec.getFormattedName() << ":\n"; 297 OS << " return \""; 298 if (Rec.getAlternativeName().empty()) 299 OS << Rec.getName(); 300 else 301 OS << Rec.getAlternativeName(); 302 OS << "\";\n"; 303 } 304 OS << " }\n"; // switch 305 OS << " llvm_unreachable(\"Invalid " << DirLang.getName() << " " << Enum 306 << " kind\");\n"; 307 OS << "}\n"; 308 } 309 310 // Generate function implementation for get<Enum>Kind(StringRef Str) 311 static void GenerateGetKind(const std::vector<Record *> &Records, 312 raw_ostream &OS, StringRef Enum, 313 const DirectiveLanguage &DirLang, StringRef Prefix, 314 bool ImplicitAsUnknown) { 315 316 auto DefaultIt = llvm::find_if( 317 Records, [](Record *R) { return R->getValueAsBit("isDefault") == true; }); 318 319 if (DefaultIt == Records.end()) { 320 PrintError("At least one " + Enum + " must be defined as default."); 321 return; 322 } 323 324 BaseRecord DefaultRec{(*DefaultIt)}; 325 326 OS << "\n"; 327 OS << Enum << " llvm::" << DirLang.getCppNamespace() << "::get" 328 << DirLang.getName() << Enum << "Kind(llvm::StringRef Str) {\n"; 329 OS << " return llvm::StringSwitch<" << Enum << ">(Str)\n"; 330 331 for (const auto &R : Records) { 332 BaseRecord Rec{R}; 333 if (ImplicitAsUnknown && R->getValueAsBit("isImplicit")) { 334 OS << " .Case(\"" << Rec.getName() << "\"," << Prefix 335 << DefaultRec.getFormattedName() << ")\n"; 336 } else { 337 OS << " .Case(\"" << Rec.getName() << "\"," << Prefix 338 << Rec.getFormattedName() << ")\n"; 339 } 340 } 341 OS << " .Default(" << Prefix << DefaultRec.getFormattedName() << ");\n"; 342 OS << "}\n"; 343 } 344 345 // Generate function implementation for get<ClauseVal>Kind(StringRef Str) 346 static void GenerateGetKindClauseVal(const DirectiveLanguage &DirLang, 347 raw_ostream &OS) { 348 for (const auto &R : DirLang.getClauses()) { 349 Clause C{R}; 350 const auto &ClauseVals = C.getClauseVals(); 351 if (ClauseVals.size() <= 0) 352 continue; 353 354 auto DefaultIt = llvm::find_if(ClauseVals, [](Record *CV) { 355 return CV->getValueAsBit("isDefault") == true; 356 }); 357 358 if (DefaultIt == ClauseVals.end()) { 359 PrintError("At least one val in Clause " + C.getFormattedName() + 360 " must be defined as default."); 361 return; 362 } 363 const auto DefaultName = (*DefaultIt)->getName(); 364 365 const auto &EnumName = C.getEnumName(); 366 if (EnumName.size() == 0) { 367 PrintError("enumClauseValue field not set in Clause" + 368 C.getFormattedName() + "."); 369 return; 370 } 371 372 OS << "\n"; 373 OS << EnumName << " llvm::" << DirLang.getCppNamespace() << "::get" 374 << EnumName << "(llvm::StringRef Str) {\n"; 375 OS << " return llvm::StringSwitch<" << EnumName << ">(Str)\n"; 376 for (const auto &CV : ClauseVals) { 377 ClauseVal CVal{CV}; 378 OS << " .Case(\"" << CVal.getFormattedName() << "\"," << CV->getName() 379 << ")\n"; 380 } 381 OS << " .Default(" << DefaultName << ");\n"; 382 OS << "}\n"; 383 384 OS << "\n"; 385 OS << "llvm::StringRef llvm::" << DirLang.getCppNamespace() << "::get" 386 << DirLang.getName() << EnumName 387 << "Name(llvm::" << DirLang.getCppNamespace() << "::" << EnumName 388 << " x) {\n"; 389 OS << " switch (x) {\n"; 390 for (const auto &CV : ClauseVals) { 391 ClauseVal CVal{CV}; 392 OS << " case " << CV->getName() << ":\n"; 393 OS << " return \"" << CVal.getFormattedName() << "\";\n"; 394 } 395 OS << " }\n"; // switch 396 OS << " llvm_unreachable(\"Invalid " << DirLang.getName() << " " 397 << EnumName << " kind\");\n"; 398 OS << "}\n"; 399 } 400 } 401 402 static void 403 GenerateCaseForVersionedClauses(const std::vector<Record *> &Clauses, 404 raw_ostream &OS, StringRef DirectiveName, 405 const DirectiveLanguage &DirLang, 406 llvm::StringSet<> &Cases) { 407 for (const auto &C : Clauses) { 408 VersionedClause VerClause{C}; 409 410 const auto ClauseFormattedName = VerClause.getClause().getFormattedName(); 411 412 if (Cases.insert(ClauseFormattedName).second) { 413 OS << " case " << DirLang.getClausePrefix() << ClauseFormattedName 414 << ":\n"; 415 OS << " return " << VerClause.getMinVersion() 416 << " <= Version && " << VerClause.getMaxVersion() << " >= Version;\n"; 417 } 418 } 419 } 420 421 static std::string GetDirectiveName(const DirectiveLanguage &DirLang, 422 const Record *Rec) { 423 Directive Dir{Rec}; 424 return (llvm::Twine("llvm::") + DirLang.getCppNamespace() + 425 "::" + DirLang.getDirectivePrefix() + Dir.getFormattedName()) 426 .str(); 427 } 428 429 static std::string GetDirectiveType(const DirectiveLanguage &DirLang) { 430 return (llvm::Twine("llvm::") + DirLang.getCppNamespace() + "::Directive") 431 .str(); 432 } 433 434 // Generate the isAllowedClauseForDirective function implementation. 435 static void GenerateIsAllowedClause(const DirectiveLanguage &DirLang, 436 raw_ostream &OS) { 437 OS << "\n"; 438 OS << "bool llvm::" << DirLang.getCppNamespace() 439 << "::isAllowedClauseForDirective(" 440 << "Directive D, Clause C, unsigned Version) {\n"; 441 OS << " assert(unsigned(D) <= llvm::" << DirLang.getCppNamespace() 442 << "::Directive_enumSize);\n"; 443 OS << " assert(unsigned(C) <= llvm::" << DirLang.getCppNamespace() 444 << "::Clause_enumSize);\n"; 445 446 OS << " switch (D) {\n"; 447 448 for (const auto &D : DirLang.getDirectives()) { 449 Directive Dir{D}; 450 451 OS << " case " << DirLang.getDirectivePrefix() << Dir.getFormattedName() 452 << ":\n"; 453 if (Dir.getAllowedClauses().size() == 0 && 454 Dir.getAllowedOnceClauses().size() == 0 && 455 Dir.getAllowedExclusiveClauses().size() == 0 && 456 Dir.getRequiredClauses().size() == 0) { 457 OS << " return false;\n"; 458 } else { 459 OS << " switch (C) {\n"; 460 461 llvm::StringSet<> Cases; 462 463 GenerateCaseForVersionedClauses(Dir.getAllowedClauses(), OS, 464 Dir.getName(), DirLang, Cases); 465 466 GenerateCaseForVersionedClauses(Dir.getAllowedOnceClauses(), OS, 467 Dir.getName(), DirLang, Cases); 468 469 GenerateCaseForVersionedClauses(Dir.getAllowedExclusiveClauses(), OS, 470 Dir.getName(), DirLang, Cases); 471 472 GenerateCaseForVersionedClauses(Dir.getRequiredClauses(), OS, 473 Dir.getName(), DirLang, Cases); 474 475 OS << " default:\n"; 476 OS << " return false;\n"; 477 OS << " }\n"; // End of clauses switch 478 } 479 OS << " break;\n"; 480 } 481 482 OS << " }\n"; // End of directives switch 483 OS << " llvm_unreachable(\"Invalid " << DirLang.getName() 484 << " Directive kind\");\n"; 485 OS << "}\n"; // End of function isAllowedClauseForDirective 486 } 487 488 static void EmitLeafTable(const DirectiveLanguage &DirLang, raw_ostream &OS, 489 StringRef TableName) { 490 // The leaf constructs are emitted in a form of a 2D table, where each 491 // row corresponds to a directive (and there is a row for each directive). 492 // 493 // Each row consists of 494 // - the id of the directive itself, 495 // - number of leaf constructs that will follow (0 for leafs), 496 // - ids of the leaf constructs (none if the directive is itself a leaf). 497 // The total number of these entries is at most MaxLeafCount+2. If this 498 // number is less than that, it is padded to occupy exactly MaxLeafCount+2 499 // entries in memory. 500 // 501 // The rows are stored in the table in the lexicographical order. This 502 // is intended to enable binary search when mapping a sequence of leafs 503 // back to the compound directive. 504 // The consequence of that is that in order to find a row corresponding 505 // to the given directive, we'd need to scan the first element of each 506 // row. To avoid this, an auxiliary ordering table is created, such that 507 // row for Dir_A = table[auxiliary[Dir_A]]. 508 509 std::vector<Record *> Directives = DirLang.getDirectives(); 510 DenseMap<Record *, int> DirId; // Record * -> llvm::omp::Directive 511 512 for (auto [Idx, Rec] : llvm::enumerate(Directives)) 513 DirId.insert(std::make_pair(Rec, Idx)); 514 515 using LeafList = std::vector<int>; 516 int MaxLeafCount = GetMaxLeafCount(DirLang); 517 518 // The initial leaf table, rows order is same as directive order. 519 std::vector<LeafList> LeafTable(Directives.size()); 520 for (auto [Idx, Rec] : llvm::enumerate(Directives)) { 521 Directive Dir{Rec}; 522 std::vector<Record *> Leaves = Dir.getLeafConstructs(); 523 524 auto &List = LeafTable[Idx]; 525 List.resize(MaxLeafCount + 2); 526 List[0] = Idx; // The id of the directive itself. 527 List[1] = Leaves.size(); // The number of leaves to follow. 528 529 for (int I = 0; I != MaxLeafCount; ++I) 530 List[I + 2] = 531 static_cast<size_t>(I) < Leaves.size() ? DirId.at(Leaves[I]) : -1; 532 } 533 534 // Some Fortran directives are delimited, i.e. they have the form of 535 // "directive"---"end directive". If "directive" is a compound construct, 536 // then the set of leaf constituents will be nonempty and the same for 537 // both directives. Given this set of leafs, looking up the corresponding 538 // compound directive should return "directive", and not "end directive". 539 // To avoid this problem, gather all "end directives" at the end of the 540 // leaf table, and only do the search on the initial segment of the table 541 // that excludes the "end directives". 542 // It's safe to find all directives whose names begin with "end ". The 543 // problem only exists for compound directives, like "end do simd". 544 // All existing directives with names starting with "end " are either 545 // "end directives" for an existing "directive", or leaf directives 546 // (such as "end declare target"). 547 DenseSet<int> EndDirectives; 548 for (auto [Rec, Id] : DirId) { 549 if (Directive{Rec}.getName().starts_with_insensitive("end ")) 550 EndDirectives.insert(Id); 551 } 552 553 // Avoid sorting the vector<vector> array, instead sort an index array. 554 // It will also be useful later to create the auxiliary indexing array. 555 std::vector<int> Ordering(Directives.size()); 556 std::iota(Ordering.begin(), Ordering.end(), 0); 557 558 llvm::sort(Ordering, [&](int A, int B) { 559 auto &LeavesA = LeafTable[A]; 560 auto &LeavesB = LeafTable[B]; 561 int DirA = LeavesA[0], DirB = LeavesB[0]; 562 // First of all, end directives compare greater than non-end directives. 563 int IsEndA = EndDirectives.count(DirA), IsEndB = EndDirectives.count(DirB); 564 if (IsEndA != IsEndB) 565 return IsEndA < IsEndB; 566 if (LeavesA[1] == 0 && LeavesB[1] == 0) 567 return DirA < DirB; 568 return std::lexicographical_compare(&LeavesA[2], &LeavesA[2] + LeavesA[1], 569 &LeavesB[2], &LeavesB[2] + LeavesB[1]); 570 }); 571 572 // Emit the table 573 574 // The directives are emitted into a scoped enum, for which the underlying 575 // type is `int` (by default). The code above uses `int` to store directive 576 // ids, so make sure that we catch it when something changes in the 577 // underlying type. 578 std::string DirectiveType = GetDirectiveType(DirLang); 579 OS << "\nstatic_assert(sizeof(" << DirectiveType << ") == sizeof(int));\n"; 580 581 OS << "[[maybe_unused]] static const " << DirectiveType << ' ' << TableName 582 << "[][" << MaxLeafCount + 2 << "] = {\n"; 583 for (size_t I = 0, E = Directives.size(); I != E; ++I) { 584 auto &Leaves = LeafTable[Ordering[I]]; 585 OS << " {" << GetDirectiveName(DirLang, Directives[Leaves[0]]); 586 OS << ", static_cast<" << DirectiveType << ">(" << Leaves[1] << "),"; 587 for (size_t I = 2, E = Leaves.size(); I != E; ++I) { 588 int Idx = Leaves[I]; 589 if (Idx >= 0) 590 OS << ' ' << GetDirectiveName(DirLang, Directives[Leaves[I]]) << ','; 591 else 592 OS << " static_cast<" << DirectiveType << ">(-1),"; 593 } 594 OS << "},\n"; 595 } 596 OS << "};\n\n"; 597 598 // Emit a marker where the first "end directive" is. 599 auto FirstE = llvm::find_if(Ordering, [&](int RowIdx) { 600 return EndDirectives.count(LeafTable[RowIdx][0]); 601 }); 602 OS << "[[maybe_unused]] static auto " << TableName 603 << "EndDirective = " << TableName << " + " 604 << std::distance(Ordering.begin(), FirstE) << ";\n\n"; 605 606 // Emit the auxiliary index table: it's the inverse of the `Ordering` 607 // table above. 608 OS << "[[maybe_unused]] static const int " << TableName << "Ordering[] = {\n"; 609 OS << " "; 610 std::vector<int> Reverse(Ordering.size()); 611 for (int I = 0, E = Ordering.size(); I != E; ++I) 612 Reverse[Ordering[I]] = I; 613 for (int Idx : Reverse) 614 OS << ' ' << Idx << ','; 615 OS << "\n};\n"; 616 } 617 618 static void GenerateGetDirectiveAssociation(const DirectiveLanguage &DirLang, 619 raw_ostream &OS) { 620 enum struct Association { 621 None = 0, // None should be the smallest value. 622 Block, // The values of the rest don't matter. 623 Declaration, 624 Delimited, 625 Loop, 626 Separating, 627 FromLeaves, 628 Invalid, 629 }; 630 631 std::vector<Record *> associations = DirLang.getAssociations(); 632 633 auto getAssocValue = [](StringRef name) -> Association { 634 return StringSwitch<Association>(name) 635 .Case("AS_Block", Association::Block) 636 .Case("AS_Declaration", Association::Declaration) 637 .Case("AS_Delimited", Association::Delimited) 638 .Case("AS_Loop", Association::Loop) 639 .Case("AS_None", Association::None) 640 .Case("AS_Separating", Association::Separating) 641 .Case("AS_FromLeaves", Association::FromLeaves) 642 .Default(Association::Invalid); 643 }; 644 645 auto getAssocName = [&](Association A) -> StringRef { 646 if (A != Association::Invalid && A != Association::FromLeaves) { 647 auto F = llvm::find_if(associations, [&](const Record *R) { 648 return getAssocValue(R->getName()) == A; 649 }); 650 if (F != associations.end()) 651 return (*F)->getValueAsString("name"); // enum name 652 } 653 llvm_unreachable("Unexpected association value"); 654 }; 655 656 auto errorPrefixFor = [&](Directive D) -> std::string { 657 return (Twine("Directive '") + D.getName() + "' in namespace '" + 658 DirLang.getCppNamespace() + "' ") 659 .str(); 660 }; 661 662 auto reduce = [&](Association A, Association B) -> Association { 663 if (A > B) 664 std::swap(A, B); 665 666 // Calculate the result using the following rules: 667 // x + x = x 668 // AS_None + x = x 669 // AS_Block + AS_Loop = AS_Loop 670 if (A == Association::None || A == B) 671 return B; 672 if (A == Association::Block && B == Association::Loop) 673 return B; 674 if (A == Association::Loop && B == Association::Block) 675 return A; 676 return Association::Invalid; 677 }; 678 679 llvm::DenseMap<const Record *, Association> AsMap; 680 681 auto compAssocImpl = [&](const Record *R, auto &&Self) -> Association { 682 if (auto F = AsMap.find(R); F != AsMap.end()) 683 return F->second; 684 685 Directive D{R}; 686 Association AS = getAssocValue(D.getAssociation()->getName()); 687 if (AS == Association::Invalid) { 688 PrintFatalError(errorPrefixFor(D) + 689 "has an unrecognized value for association: '" + 690 D.getAssociation()->getName() + "'"); 691 } 692 if (AS != Association::FromLeaves) { 693 AsMap.insert(std::make_pair(R, AS)); 694 return AS; 695 } 696 // Compute the association from leaf constructs. 697 std::vector<Record *> leaves = D.getLeafConstructs(); 698 if (leaves.empty()) { 699 llvm::errs() << D.getName() << '\n'; 700 PrintFatalError(errorPrefixFor(D) + 701 "requests association to be computed from leaves, " 702 "but it has no leaves"); 703 } 704 705 Association Result = Self(leaves[0], Self); 706 for (int I = 1, E = leaves.size(); I < E; ++I) { 707 Association A = Self(leaves[I], Self); 708 Association R = reduce(Result, A); 709 if (R == Association::Invalid) { 710 PrintFatalError(errorPrefixFor(D) + 711 "has leaves with incompatible association values: " + 712 getAssocName(A) + " and " + getAssocName(R)); 713 } 714 Result = R; 715 } 716 717 assert(Result != Association::Invalid); 718 assert(Result != Association::FromLeaves); 719 AsMap.insert(std::make_pair(R, Result)); 720 return Result; 721 }; 722 723 for (Record *R : DirLang.getDirectives()) 724 compAssocImpl(R, compAssocImpl); // Updates AsMap. 725 726 OS << '\n'; 727 728 auto getQualifiedName = [&](StringRef Formatted) -> std::string { 729 return (llvm::Twine("llvm::") + DirLang.getCppNamespace() + 730 "::Directive::" + DirLang.getDirectivePrefix() + Formatted) 731 .str(); 732 }; 733 734 std::string DirectiveTypeName = 735 std::string("llvm::") + DirLang.getCppNamespace().str() + "::Directive"; 736 std::string AssociationTypeName = 737 std::string("llvm::") + DirLang.getCppNamespace().str() + "::Association"; 738 739 OS << AssociationTypeName << " llvm::" << DirLang.getCppNamespace() 740 << "::getDirectiveAssociation(" << DirectiveTypeName << " Dir) {\n"; 741 OS << " switch (Dir) {\n"; 742 for (Record *R : DirLang.getDirectives()) { 743 if (auto F = AsMap.find(R); F != AsMap.end()) { 744 Directive Dir{R}; 745 OS << " case " << getQualifiedName(Dir.getFormattedName()) << ":\n"; 746 OS << " return " << AssociationTypeName 747 << "::" << getAssocName(F->second) << ";\n"; 748 } 749 } 750 OS << " } // switch (Dir)\n"; 751 OS << " llvm_unreachable(\"Unexpected directive\");\n"; 752 OS << "}\n"; 753 } 754 755 static void GenerateGetDirectiveCategory(const DirectiveLanguage &DirLang, 756 raw_ostream &OS) { 757 std::string LangNamespace = "llvm::" + DirLang.getCppNamespace().str(); 758 std::string CategoryTypeName = LangNamespace + "::Category"; 759 std::string CategoryNamespace = CategoryTypeName + "::"; 760 761 OS << '\n'; 762 OS << CategoryTypeName << ' ' << LangNamespace << "::getDirectiveCategory(" 763 << GetDirectiveType(DirLang) << " Dir) {\n"; 764 OS << " switch (Dir) {\n"; 765 766 for (Record *R : DirLang.getDirectives()) { 767 Directive D{R}; 768 OS << " case " << GetDirectiveName(DirLang, R) << ":\n"; 769 OS << " return " << CategoryNamespace 770 << D.getCategory()->getValueAsString("name") << ";\n"; 771 } 772 OS << " } // switch (Dir)\n"; 773 OS << " llvm_unreachable(\"Unexpected directive\");\n"; 774 OS << "}\n"; 775 } 776 777 // Generate a simple enum set with the give clauses. 778 static void GenerateClauseSet(const std::vector<Record *> &Clauses, 779 raw_ostream &OS, StringRef ClauseSetPrefix, 780 Directive &Dir, 781 const DirectiveLanguage &DirLang) { 782 783 OS << "\n"; 784 OS << " static " << DirLang.getClauseEnumSetClass() << " " << ClauseSetPrefix 785 << DirLang.getDirectivePrefix() << Dir.getFormattedName() << " {\n"; 786 787 for (const auto &C : Clauses) { 788 VersionedClause VerClause{C}; 789 OS << " llvm::" << DirLang.getCppNamespace() 790 << "::Clause::" << DirLang.getClausePrefix() 791 << VerClause.getClause().getFormattedName() << ",\n"; 792 } 793 OS << " };\n"; 794 } 795 796 // Generate an enum set for the 4 kinds of clauses linked to a directive. 797 static void GenerateDirectiveClauseSets(const DirectiveLanguage &DirLang, 798 raw_ostream &OS) { 799 800 IfDefScope Scope("GEN_FLANG_DIRECTIVE_CLAUSE_SETS", OS); 801 802 OS << "\n"; 803 OS << "namespace llvm {\n"; 804 805 // Open namespaces defined in the directive language. 806 llvm::SmallVector<StringRef, 2> Namespaces; 807 llvm::SplitString(DirLang.getCppNamespace(), Namespaces, "::"); 808 for (auto Ns : Namespaces) 809 OS << "namespace " << Ns << " {\n"; 810 811 for (const auto &D : DirLang.getDirectives()) { 812 Directive Dir{D}; 813 814 OS << "\n"; 815 OS << " // Sets for " << Dir.getName() << "\n"; 816 817 GenerateClauseSet(Dir.getAllowedClauses(), OS, "allowedClauses_", Dir, 818 DirLang); 819 GenerateClauseSet(Dir.getAllowedOnceClauses(), OS, "allowedOnceClauses_", 820 Dir, DirLang); 821 GenerateClauseSet(Dir.getAllowedExclusiveClauses(), OS, 822 "allowedExclusiveClauses_", Dir, DirLang); 823 GenerateClauseSet(Dir.getRequiredClauses(), OS, "requiredClauses_", Dir, 824 DirLang); 825 } 826 827 // Closing namespaces 828 for (auto Ns : llvm::reverse(Namespaces)) 829 OS << "} // namespace " << Ns << "\n"; 830 831 OS << "} // namespace llvm\n"; 832 } 833 834 // Generate a map of directive (key) with DirectiveClauses struct as values. 835 // The struct holds the 4 sets of enumeration for the 4 kinds of clauses 836 // allowances (allowed, allowed once, allowed exclusive and required). 837 static void GenerateDirectiveClauseMap(const DirectiveLanguage &DirLang, 838 raw_ostream &OS) { 839 840 IfDefScope Scope("GEN_FLANG_DIRECTIVE_CLAUSE_MAP", OS); 841 842 OS << "\n"; 843 OS << "{\n"; 844 845 for (const auto &D : DirLang.getDirectives()) { 846 Directive Dir{D}; 847 OS << " {llvm::" << DirLang.getCppNamespace() 848 << "::Directive::" << DirLang.getDirectivePrefix() 849 << Dir.getFormattedName() << ",\n"; 850 OS << " {\n"; 851 OS << " llvm::" << DirLang.getCppNamespace() << "::allowedClauses_" 852 << DirLang.getDirectivePrefix() << Dir.getFormattedName() << ",\n"; 853 OS << " llvm::" << DirLang.getCppNamespace() << "::allowedOnceClauses_" 854 << DirLang.getDirectivePrefix() << Dir.getFormattedName() << ",\n"; 855 OS << " llvm::" << DirLang.getCppNamespace() 856 << "::allowedExclusiveClauses_" << DirLang.getDirectivePrefix() 857 << Dir.getFormattedName() << ",\n"; 858 OS << " llvm::" << DirLang.getCppNamespace() << "::requiredClauses_" 859 << DirLang.getDirectivePrefix() << Dir.getFormattedName() << ",\n"; 860 OS << " }\n"; 861 OS << " },\n"; 862 } 863 864 OS << "}\n"; 865 } 866 867 // Generate classes entry for Flang clauses in the Flang parse-tree 868 // If the clause as a non-generic class, no entry is generated. 869 // If the clause does not hold a value, an EMPTY_CLASS is used. 870 // If the clause class is generic then a WRAPPER_CLASS is used. When the value 871 // is optional, the value class is wrapped into a std::optional. 872 static void GenerateFlangClauseParserClass(const DirectiveLanguage &DirLang, 873 raw_ostream &OS) { 874 875 IfDefScope Scope("GEN_FLANG_CLAUSE_PARSER_CLASSES", OS); 876 877 OS << "\n"; 878 879 for (const auto &C : DirLang.getClauses()) { 880 Clause Clause{C}; 881 if (!Clause.getFlangClass().empty()) { 882 OS << "WRAPPER_CLASS(" << Clause.getFormattedParserClassName() << ", "; 883 if (Clause.isValueOptional() && Clause.isValueList()) { 884 OS << "std::optional<std::list<" << Clause.getFlangClass() << ">>"; 885 } else if (Clause.isValueOptional()) { 886 OS << "std::optional<" << Clause.getFlangClass() << ">"; 887 } else if (Clause.isValueList()) { 888 OS << "std::list<" << Clause.getFlangClass() << ">"; 889 } else { 890 OS << Clause.getFlangClass(); 891 } 892 } else { 893 OS << "EMPTY_CLASS(" << Clause.getFormattedParserClassName(); 894 } 895 OS << ");\n"; 896 } 897 } 898 899 // Generate a list of the different clause classes for Flang. 900 static void GenerateFlangClauseParserClassList(const DirectiveLanguage &DirLang, 901 raw_ostream &OS) { 902 903 IfDefScope Scope("GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST", OS); 904 905 OS << "\n"; 906 llvm::interleaveComma(DirLang.getClauses(), OS, [&](Record *C) { 907 Clause Clause{C}; 908 OS << Clause.getFormattedParserClassName() << "\n"; 909 }); 910 } 911 912 // Generate dump node list for the clauses holding a generic class name. 913 static void GenerateFlangClauseDump(const DirectiveLanguage &DirLang, 914 raw_ostream &OS) { 915 916 IfDefScope Scope("GEN_FLANG_DUMP_PARSE_TREE_CLAUSES", OS); 917 918 OS << "\n"; 919 for (const auto &C : DirLang.getClauses()) { 920 Clause Clause{C}; 921 OS << "NODE(" << DirLang.getFlangClauseBaseClass() << ", " 922 << Clause.getFormattedParserClassName() << ")\n"; 923 } 924 } 925 926 // Generate Unparse functions for clauses classes in the Flang parse-tree 927 // If the clause is a non-generic class, no entry is generated. 928 static void GenerateFlangClauseUnparse(const DirectiveLanguage &DirLang, 929 raw_ostream &OS) { 930 931 IfDefScope Scope("GEN_FLANG_CLAUSE_UNPARSE", OS); 932 933 OS << "\n"; 934 935 for (const auto &C : DirLang.getClauses()) { 936 Clause Clause{C}; 937 if (!Clause.getFlangClass().empty()) { 938 if (Clause.isValueOptional() && Clause.getDefaultValue().empty()) { 939 OS << "void Unparse(const " << DirLang.getFlangClauseBaseClass() 940 << "::" << Clause.getFormattedParserClassName() << " &x) {\n"; 941 OS << " Word(\"" << Clause.getName().upper() << "\");\n"; 942 943 OS << " Walk(\"(\", x.v, \")\");\n"; 944 OS << "}\n"; 945 } else if (Clause.isValueOptional()) { 946 OS << "void Unparse(const " << DirLang.getFlangClauseBaseClass() 947 << "::" << Clause.getFormattedParserClassName() << " &x) {\n"; 948 OS << " Word(\"" << Clause.getName().upper() << "\");\n"; 949 OS << " Put(\"(\");\n"; 950 OS << " if (x.v.has_value())\n"; 951 if (Clause.isValueList()) 952 OS << " Walk(x.v, \",\");\n"; 953 else 954 OS << " Walk(x.v);\n"; 955 OS << " else\n"; 956 OS << " Put(\"" << Clause.getDefaultValue() << "\");\n"; 957 OS << " Put(\")\");\n"; 958 OS << "}\n"; 959 } else { 960 OS << "void Unparse(const " << DirLang.getFlangClauseBaseClass() 961 << "::" << Clause.getFormattedParserClassName() << " &x) {\n"; 962 OS << " Word(\"" << Clause.getName().upper() << "\");\n"; 963 OS << " Put(\"(\");\n"; 964 if (Clause.isValueList()) 965 OS << " Walk(x.v, \",\");\n"; 966 else 967 OS << " Walk(x.v);\n"; 968 OS << " Put(\")\");\n"; 969 OS << "}\n"; 970 } 971 } else { 972 OS << "void Before(const " << DirLang.getFlangClauseBaseClass() 973 << "::" << Clause.getFormattedParserClassName() << " &) { Word(\"" 974 << Clause.getName().upper() << "\"); }\n"; 975 } 976 } 977 } 978 979 // Generate check in the Enter functions for clauses classes. 980 static void GenerateFlangClauseCheckPrototypes(const DirectiveLanguage &DirLang, 981 raw_ostream &OS) { 982 983 IfDefScope Scope("GEN_FLANG_CLAUSE_CHECK_ENTER", OS); 984 985 OS << "\n"; 986 for (const auto &C : DirLang.getClauses()) { 987 Clause Clause{C}; 988 OS << "void Enter(const parser::" << DirLang.getFlangClauseBaseClass() 989 << "::" << Clause.getFormattedParserClassName() << " &);\n"; 990 } 991 } 992 993 // Generate the mapping for clauses between the parser class and the 994 // corresponding clause Kind 995 static void GenerateFlangClauseParserKindMap(const DirectiveLanguage &DirLang, 996 raw_ostream &OS) { 997 998 IfDefScope Scope("GEN_FLANG_CLAUSE_PARSER_KIND_MAP", OS); 999 1000 OS << "\n"; 1001 for (const auto &C : DirLang.getClauses()) { 1002 Clause Clause{C}; 1003 OS << "if constexpr (std::is_same_v<A, parser::" 1004 << DirLang.getFlangClauseBaseClass() 1005 << "::" << Clause.getFormattedParserClassName(); 1006 OS << ">)\n"; 1007 OS << " return llvm::" << DirLang.getCppNamespace() 1008 << "::Clause::" << DirLang.getClausePrefix() << Clause.getFormattedName() 1009 << ";\n"; 1010 } 1011 1012 OS << "llvm_unreachable(\"Invalid " << DirLang.getName() 1013 << " Parser clause\");\n"; 1014 } 1015 1016 static bool compareClauseName(Record *R1, Record *R2) { 1017 Clause C1{R1}; 1018 Clause C2{R2}; 1019 return (C1.getName() > C2.getName()); 1020 } 1021 1022 // Generate the parser for the clauses. 1023 static void GenerateFlangClausesParser(const DirectiveLanguage &DirLang, 1024 raw_ostream &OS) { 1025 std::vector<Record *> Clauses = DirLang.getClauses(); 1026 // Sort clauses in reverse alphabetical order so with clauses with same 1027 // beginning, the longer option is tried before. 1028 llvm::sort(Clauses, compareClauseName); 1029 IfDefScope Scope("GEN_FLANG_CLAUSES_PARSER", OS); 1030 OS << "\n"; 1031 unsigned index = 0; 1032 unsigned lastClauseIndex = DirLang.getClauses().size() - 1; 1033 OS << "TYPE_PARSER(\n"; 1034 for (const auto &C : Clauses) { 1035 Clause Clause{C}; 1036 if (Clause.getAliases().empty()) { 1037 OS << " \"" << Clause.getName() << "\""; 1038 } else { 1039 OS << " (" 1040 << "\"" << Clause.getName() << "\"_tok"; 1041 for (StringRef alias : Clause.getAliases()) { 1042 OS << " || \"" << alias << "\"_tok"; 1043 } 1044 OS << ")"; 1045 } 1046 1047 OS << " >> construct<" << DirLang.getFlangClauseBaseClass() 1048 << ">(construct<" << DirLang.getFlangClauseBaseClass() 1049 << "::" << Clause.getFormattedParserClassName() << ">("; 1050 if (Clause.getFlangClass().empty()) { 1051 OS << "))"; 1052 if (index != lastClauseIndex) 1053 OS << " ||"; 1054 OS << "\n"; 1055 ++index; 1056 continue; 1057 } 1058 1059 if (Clause.isValueOptional()) 1060 OS << "maybe("; 1061 OS << "parenthesized("; 1062 if (Clause.isValueList()) 1063 OS << "nonemptyList("; 1064 1065 if (!Clause.getPrefix().empty()) 1066 OS << "\"" << Clause.getPrefix() << ":\" >> "; 1067 1068 // The common Flang parser are used directly. Their name is identical to 1069 // the Flang class with first letter as lowercase. If the Flang class is 1070 // not a common class, we assume there is a specific Parser<>{} with the 1071 // Flang class name provided. 1072 llvm::SmallString<128> Scratch; 1073 StringRef Parser = 1074 llvm::StringSwitch<StringRef>(Clause.getFlangClass()) 1075 .Case("Name", "name") 1076 .Case("ScalarIntConstantExpr", "scalarIntConstantExpr") 1077 .Case("ScalarIntExpr", "scalarIntExpr") 1078 .Case("ScalarExpr", "scalarExpr") 1079 .Case("ScalarLogicalExpr", "scalarLogicalExpr") 1080 .Default(("Parser<" + Clause.getFlangClass() + ">{}") 1081 .toStringRef(Scratch)); 1082 OS << Parser; 1083 if (!Clause.getPrefix().empty() && Clause.isPrefixOptional()) 1084 OS << " || " << Parser; 1085 if (Clause.isValueList()) // close nonemptyList(. 1086 OS << ")"; 1087 OS << ")"; // close parenthesized(. 1088 1089 if (Clause.isValueOptional()) // close maybe(. 1090 OS << ")"; 1091 OS << "))"; 1092 if (index != lastClauseIndex) 1093 OS << " ||"; 1094 OS << "\n"; 1095 ++index; 1096 } 1097 OS << ")\n"; 1098 } 1099 1100 // Generate the implementation section for the enumeration in the directive 1101 // language 1102 static void EmitDirectivesFlangImpl(const DirectiveLanguage &DirLang, 1103 raw_ostream &OS) { 1104 1105 GenerateDirectiveClauseSets(DirLang, OS); 1106 1107 GenerateDirectiveClauseMap(DirLang, OS); 1108 1109 GenerateFlangClauseParserClass(DirLang, OS); 1110 1111 GenerateFlangClauseParserClassList(DirLang, OS); 1112 1113 GenerateFlangClauseDump(DirLang, OS); 1114 1115 GenerateFlangClauseUnparse(DirLang, OS); 1116 1117 GenerateFlangClauseCheckPrototypes(DirLang, OS); 1118 1119 GenerateFlangClauseParserKindMap(DirLang, OS); 1120 1121 GenerateFlangClausesParser(DirLang, OS); 1122 } 1123 1124 static void GenerateClauseClassMacro(const DirectiveLanguage &DirLang, 1125 raw_ostream &OS) { 1126 // Generate macros style information for legacy code in clang 1127 IfDefScope Scope("GEN_CLANG_CLAUSE_CLASS", OS); 1128 1129 OS << "\n"; 1130 1131 OS << "#ifndef CLAUSE\n"; 1132 OS << "#define CLAUSE(Enum, Str, Implicit)\n"; 1133 OS << "#endif\n"; 1134 OS << "#ifndef CLAUSE_CLASS\n"; 1135 OS << "#define CLAUSE_CLASS(Enum, Str, Class)\n"; 1136 OS << "#endif\n"; 1137 OS << "#ifndef CLAUSE_NO_CLASS\n"; 1138 OS << "#define CLAUSE_NO_CLASS(Enum, Str)\n"; 1139 OS << "#endif\n"; 1140 OS << "\n"; 1141 OS << "#define __CLAUSE(Name, Class) \\\n"; 1142 OS << " CLAUSE(" << DirLang.getClausePrefix() 1143 << "##Name, #Name, /* Implicit */ false) \\\n"; 1144 OS << " CLAUSE_CLASS(" << DirLang.getClausePrefix() 1145 << "##Name, #Name, Class)\n"; 1146 OS << "#define __CLAUSE_NO_CLASS(Name) \\\n"; 1147 OS << " CLAUSE(" << DirLang.getClausePrefix() 1148 << "##Name, #Name, /* Implicit */ false) \\\n"; 1149 OS << " CLAUSE_NO_CLASS(" << DirLang.getClausePrefix() << "##Name, #Name)\n"; 1150 OS << "#define __IMPLICIT_CLAUSE_CLASS(Name, Str, Class) \\\n"; 1151 OS << " CLAUSE(" << DirLang.getClausePrefix() 1152 << "##Name, Str, /* Implicit */ true) \\\n"; 1153 OS << " CLAUSE_CLASS(" << DirLang.getClausePrefix() 1154 << "##Name, Str, Class)\n"; 1155 OS << "#define __IMPLICIT_CLAUSE_NO_CLASS(Name, Str) \\\n"; 1156 OS << " CLAUSE(" << DirLang.getClausePrefix() 1157 << "##Name, Str, /* Implicit */ true) \\\n"; 1158 OS << " CLAUSE_NO_CLASS(" << DirLang.getClausePrefix() << "##Name, Str)\n"; 1159 OS << "\n"; 1160 1161 for (const auto &R : DirLang.getClauses()) { 1162 Clause C{R}; 1163 if (C.getClangClass().empty()) { // NO_CLASS 1164 if (C.isImplicit()) { 1165 OS << "__IMPLICIT_CLAUSE_NO_CLASS(" << C.getFormattedName() << ", \"" 1166 << C.getFormattedName() << "\")\n"; 1167 } else { 1168 OS << "__CLAUSE_NO_CLASS(" << C.getFormattedName() << ")\n"; 1169 } 1170 } else { // CLASS 1171 if (C.isImplicit()) { 1172 OS << "__IMPLICIT_CLAUSE_CLASS(" << C.getFormattedName() << ", \"" 1173 << C.getFormattedName() << "\", " << C.getClangClass() << ")\n"; 1174 } else { 1175 OS << "__CLAUSE(" << C.getFormattedName() << ", " << C.getClangClass() 1176 << ")\n"; 1177 } 1178 } 1179 } 1180 1181 OS << "\n"; 1182 OS << "#undef __IMPLICIT_CLAUSE_NO_CLASS\n"; 1183 OS << "#undef __IMPLICIT_CLAUSE_CLASS\n"; 1184 OS << "#undef __CLAUSE_NO_CLASS\n"; 1185 OS << "#undef __CLAUSE\n"; 1186 OS << "#undef CLAUSE_NO_CLASS\n"; 1187 OS << "#undef CLAUSE_CLASS\n"; 1188 OS << "#undef CLAUSE\n"; 1189 } 1190 1191 // Generate the implemenation for the enumeration in the directive 1192 // language. This code can be included in library. 1193 void EmitDirectivesBasicImpl(const DirectiveLanguage &DirLang, 1194 raw_ostream &OS) { 1195 IfDefScope Scope("GEN_DIRECTIVES_IMPL", OS); 1196 1197 OS << "\n#include \"llvm/Support/ErrorHandling.h\"\n"; 1198 1199 // getDirectiveKind(StringRef Str) 1200 GenerateGetKind(DirLang.getDirectives(), OS, "Directive", DirLang, 1201 DirLang.getDirectivePrefix(), /*ImplicitAsUnknown=*/false); 1202 1203 // getDirectiveName(Directive Kind) 1204 GenerateGetName(DirLang.getDirectives(), OS, "Directive", DirLang, 1205 DirLang.getDirectivePrefix()); 1206 1207 // getClauseKind(StringRef Str) 1208 GenerateGetKind(DirLang.getClauses(), OS, "Clause", DirLang, 1209 DirLang.getClausePrefix(), 1210 /*ImplicitAsUnknown=*/true); 1211 1212 // getClauseName(Clause Kind) 1213 GenerateGetName(DirLang.getClauses(), OS, "Clause", DirLang, 1214 DirLang.getClausePrefix()); 1215 1216 // get<ClauseVal>Kind(StringRef Str) 1217 GenerateGetKindClauseVal(DirLang, OS); 1218 1219 // isAllowedClauseForDirective(Directive D, Clause C, unsigned Version) 1220 GenerateIsAllowedClause(DirLang, OS); 1221 1222 // getDirectiveAssociation(Directive D) 1223 GenerateGetDirectiveAssociation(DirLang, OS); 1224 1225 // getDirectiveCategory(Directive D) 1226 GenerateGetDirectiveCategory(DirLang, OS); 1227 1228 // Leaf table for getLeafConstructs, etc. 1229 EmitLeafTable(DirLang, OS, "LeafConstructTable"); 1230 } 1231 1232 // Generate the implemenation section for the enumeration in the directive 1233 // language. 1234 static void EmitDirectivesImpl(RecordKeeper &Records, raw_ostream &OS) { 1235 const auto DirLang = DirectiveLanguage{Records}; 1236 if (DirLang.HasValidityErrors()) 1237 return; 1238 1239 EmitDirectivesFlangImpl(DirLang, OS); 1240 1241 GenerateClauseClassMacro(DirLang, OS); 1242 1243 EmitDirectivesBasicImpl(DirLang, OS); 1244 } 1245 1246 static TableGen::Emitter::Opt 1247 X("gen-directive-decl", EmitDirectivesDecl, 1248 "Generate directive related declaration code (header file)"); 1249 1250 static TableGen::Emitter::Opt 1251 Y("gen-directive-impl", EmitDirectivesImpl, 1252 "Generate directive related implementation code"); 1253