15ffd83dbSDimitry Andric //===- DirectiveEmitter.cpp - Directive Language Emitter ------------------===// 25ffd83dbSDimitry Andric // 35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ffd83dbSDimitry Andric // 75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 85ffd83dbSDimitry Andric // 95ffd83dbSDimitry Andric // DirectiveEmitter uses the descriptions of directives and clauses to construct 105ffd83dbSDimitry Andric // common code declarations to be used in Frontends. 115ffd83dbSDimitry Andric // 125ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 135ffd83dbSDimitry Andric 14*e8d8bef9SDimitry Andric #include "llvm/TableGen/DirectiveEmitter.h" 155ffd83dbSDimitry Andric #include "llvm/ADT/STLExtras.h" 165ffd83dbSDimitry Andric #include "llvm/ADT/SmallVector.h" 175ffd83dbSDimitry Andric #include "llvm/ADT/StringSet.h" 185ffd83dbSDimitry Andric #include "llvm/TableGen/Error.h" 195ffd83dbSDimitry Andric #include "llvm/TableGen/Record.h" 205ffd83dbSDimitry Andric #include "llvm/TableGen/TableGenBackend.h" 215ffd83dbSDimitry Andric 225ffd83dbSDimitry Andric using namespace llvm; 235ffd83dbSDimitry Andric 245ffd83dbSDimitry Andric namespace { 255ffd83dbSDimitry Andric // Simple RAII helper for defining ifdef-undef-endif scopes. 265ffd83dbSDimitry Andric class IfDefScope { 275ffd83dbSDimitry Andric public: 285ffd83dbSDimitry Andric IfDefScope(StringRef Name, raw_ostream &OS) : Name(Name), OS(OS) { 295ffd83dbSDimitry Andric OS << "#ifdef " << Name << "\n" 305ffd83dbSDimitry Andric << "#undef " << Name << "\n"; 315ffd83dbSDimitry Andric } 325ffd83dbSDimitry Andric 335ffd83dbSDimitry Andric ~IfDefScope() { OS << "\n#endif // " << Name << "\n\n"; } 345ffd83dbSDimitry Andric 355ffd83dbSDimitry Andric private: 365ffd83dbSDimitry Andric StringRef Name; 375ffd83dbSDimitry Andric raw_ostream &OS; 385ffd83dbSDimitry Andric }; 395ffd83dbSDimitry Andric } // end anonymous namespace 405ffd83dbSDimitry Andric 415ffd83dbSDimitry Andric namespace llvm { 425ffd83dbSDimitry Andric 435ffd83dbSDimitry Andric // Generate enum class 445ffd83dbSDimitry Andric void GenerateEnumClass(const std::vector<Record *> &Records, raw_ostream &OS, 45*e8d8bef9SDimitry Andric StringRef Enum, StringRef Prefix, 46*e8d8bef9SDimitry Andric const DirectiveLanguage &DirLang) { 475ffd83dbSDimitry Andric OS << "\n"; 485ffd83dbSDimitry Andric OS << "enum class " << Enum << " {\n"; 495ffd83dbSDimitry Andric for (const auto &R : Records) { 50*e8d8bef9SDimitry Andric BaseRecord Rec{R}; 51*e8d8bef9SDimitry Andric OS << " " << Prefix << Rec.getFormattedName() << ",\n"; 525ffd83dbSDimitry Andric } 535ffd83dbSDimitry Andric OS << "};\n"; 545ffd83dbSDimitry Andric OS << "\n"; 555ffd83dbSDimitry Andric OS << "static constexpr std::size_t " << Enum 565ffd83dbSDimitry Andric << "_enumSize = " << Records.size() << ";\n"; 575ffd83dbSDimitry Andric 585ffd83dbSDimitry Andric // Make the enum values available in the defined namespace. This allows us to 595ffd83dbSDimitry Andric // write something like Enum_X if we have a `using namespace <CppNamespace>`. 605ffd83dbSDimitry Andric // At the same time we do not loose the strong type guarantees of the enum 615ffd83dbSDimitry Andric // class, that is we cannot pass an unsigned as Directive without an explicit 625ffd83dbSDimitry Andric // cast. 63*e8d8bef9SDimitry Andric if (DirLang.hasMakeEnumAvailableInNamespace()) { 645ffd83dbSDimitry Andric OS << "\n"; 655ffd83dbSDimitry Andric for (const auto &R : Records) { 66*e8d8bef9SDimitry Andric BaseRecord Rec{R}; 67*e8d8bef9SDimitry Andric OS << "constexpr auto " << Prefix << Rec.getFormattedName() << " = " 68*e8d8bef9SDimitry Andric << "llvm::" << DirLang.getCppNamespace() << "::" << Enum 69*e8d8bef9SDimitry Andric << "::" << Prefix << Rec.getFormattedName() << ";\n"; 705ffd83dbSDimitry Andric } 715ffd83dbSDimitry Andric } 725ffd83dbSDimitry Andric } 735ffd83dbSDimitry Andric 74*e8d8bef9SDimitry Andric // Generate enums for values that clauses can take. 75*e8d8bef9SDimitry Andric // Also generate function declarations for get<Enum>Name(StringRef Str). 76*e8d8bef9SDimitry Andric void GenerateEnumClauseVal(const std::vector<Record *> &Records, 77*e8d8bef9SDimitry Andric raw_ostream &OS, const DirectiveLanguage &DirLang, 78*e8d8bef9SDimitry Andric std::string &EnumHelperFuncs) { 79*e8d8bef9SDimitry Andric for (const auto &R : Records) { 80*e8d8bef9SDimitry Andric Clause C{R}; 81*e8d8bef9SDimitry Andric const auto &ClauseVals = C.getClauseVals(); 82*e8d8bef9SDimitry Andric if (ClauseVals.size() <= 0) 83*e8d8bef9SDimitry Andric continue; 84*e8d8bef9SDimitry Andric 85*e8d8bef9SDimitry Andric const auto &EnumName = C.getEnumName(); 86*e8d8bef9SDimitry Andric if (EnumName.size() == 0) { 87*e8d8bef9SDimitry Andric PrintError("enumClauseValue field not set in Clause" + 88*e8d8bef9SDimitry Andric C.getFormattedName() + "."); 89*e8d8bef9SDimitry Andric return; 90*e8d8bef9SDimitry Andric } 91*e8d8bef9SDimitry Andric 92*e8d8bef9SDimitry Andric OS << "\n"; 93*e8d8bef9SDimitry Andric OS << "enum class " << EnumName << " {\n"; 94*e8d8bef9SDimitry Andric for (const auto &CV : ClauseVals) { 95*e8d8bef9SDimitry Andric ClauseVal CVal{CV}; 96*e8d8bef9SDimitry Andric OS << " " << CV->getName() << "=" << CVal.getValue() << ",\n"; 97*e8d8bef9SDimitry Andric } 98*e8d8bef9SDimitry Andric OS << "};\n"; 99*e8d8bef9SDimitry Andric 100*e8d8bef9SDimitry Andric if (DirLang.hasMakeEnumAvailableInNamespace()) { 101*e8d8bef9SDimitry Andric OS << "\n"; 102*e8d8bef9SDimitry Andric for (const auto &CV : ClauseVals) { 103*e8d8bef9SDimitry Andric OS << "constexpr auto " << CV->getName() << " = " 104*e8d8bef9SDimitry Andric << "llvm::" << DirLang.getCppNamespace() << "::" << EnumName 105*e8d8bef9SDimitry Andric << "::" << CV->getName() << ";\n"; 106*e8d8bef9SDimitry Andric } 107*e8d8bef9SDimitry Andric EnumHelperFuncs += (llvm::Twine(EnumName) + llvm::Twine(" get") + 108*e8d8bef9SDimitry Andric llvm::Twine(EnumName) + llvm::Twine("(StringRef);\n")) 109*e8d8bef9SDimitry Andric .str(); 110*e8d8bef9SDimitry Andric 111*e8d8bef9SDimitry Andric EnumHelperFuncs += 112*e8d8bef9SDimitry Andric (llvm::Twine("llvm::StringRef get") + llvm::Twine(DirLang.getName()) + 113*e8d8bef9SDimitry Andric llvm::Twine(EnumName) + llvm::Twine("Name(") + 114*e8d8bef9SDimitry Andric llvm::Twine(EnumName) + llvm::Twine(");\n")) 115*e8d8bef9SDimitry Andric .str(); 116*e8d8bef9SDimitry Andric } 117*e8d8bef9SDimitry Andric } 118*e8d8bef9SDimitry Andric } 119*e8d8bef9SDimitry Andric 120*e8d8bef9SDimitry Andric bool HasDuplicateClauses(const std::vector<Record *> &Clauses, 121*e8d8bef9SDimitry Andric const Directive &Directive, 122*e8d8bef9SDimitry Andric llvm::StringSet<> &CrtClauses) { 123*e8d8bef9SDimitry Andric bool HasError = false; 124*e8d8bef9SDimitry Andric for (const auto &C : Clauses) { 125*e8d8bef9SDimitry Andric VersionedClause VerClause{C}; 126*e8d8bef9SDimitry Andric const auto insRes = CrtClauses.insert(VerClause.getClause().getName()); 127*e8d8bef9SDimitry Andric if (!insRes.second) { 128*e8d8bef9SDimitry Andric PrintError("Clause " + VerClause.getClause().getRecordName() + 129*e8d8bef9SDimitry Andric " already defined on directive " + Directive.getRecordName()); 130*e8d8bef9SDimitry Andric HasError = true; 131*e8d8bef9SDimitry Andric } 132*e8d8bef9SDimitry Andric } 133*e8d8bef9SDimitry Andric return HasError; 134*e8d8bef9SDimitry Andric } 135*e8d8bef9SDimitry Andric 136*e8d8bef9SDimitry Andric // Check for duplicate clauses in lists. Clauses cannot appear twice in the 137*e8d8bef9SDimitry Andric // three allowed list. Also, since required implies allowed, clauses cannot 138*e8d8bef9SDimitry Andric // appear in both the allowedClauses and requiredClauses lists. 139*e8d8bef9SDimitry Andric bool HasDuplicateClausesInDirectives(const std::vector<Record *> &Directives) { 140*e8d8bef9SDimitry Andric bool HasDuplicate = false; 141*e8d8bef9SDimitry Andric for (const auto &D : Directives) { 142*e8d8bef9SDimitry Andric Directive Dir{D}; 143*e8d8bef9SDimitry Andric llvm::StringSet<> Clauses; 144*e8d8bef9SDimitry Andric // Check for duplicates in the three allowed lists. 145*e8d8bef9SDimitry Andric if (HasDuplicateClauses(Dir.getAllowedClauses(), Dir, Clauses) || 146*e8d8bef9SDimitry Andric HasDuplicateClauses(Dir.getAllowedOnceClauses(), Dir, Clauses) || 147*e8d8bef9SDimitry Andric HasDuplicateClauses(Dir.getAllowedExclusiveClauses(), Dir, Clauses)) { 148*e8d8bef9SDimitry Andric HasDuplicate = true; 149*e8d8bef9SDimitry Andric } 150*e8d8bef9SDimitry Andric // Check for duplicate between allowedClauses and required 151*e8d8bef9SDimitry Andric Clauses.clear(); 152*e8d8bef9SDimitry Andric if (HasDuplicateClauses(Dir.getAllowedClauses(), Dir, Clauses) || 153*e8d8bef9SDimitry Andric HasDuplicateClauses(Dir.getRequiredClauses(), Dir, Clauses)) { 154*e8d8bef9SDimitry Andric HasDuplicate = true; 155*e8d8bef9SDimitry Andric } 156*e8d8bef9SDimitry Andric if (HasDuplicate) 157*e8d8bef9SDimitry Andric PrintFatalError("One or more clauses are defined multiple times on" 158*e8d8bef9SDimitry Andric " directive " + 159*e8d8bef9SDimitry Andric Dir.getRecordName()); 160*e8d8bef9SDimitry Andric } 161*e8d8bef9SDimitry Andric 162*e8d8bef9SDimitry Andric return HasDuplicate; 163*e8d8bef9SDimitry Andric } 164*e8d8bef9SDimitry Andric 165*e8d8bef9SDimitry Andric // Check consitency of records. Return true if an error has been detected. 166*e8d8bef9SDimitry Andric // Return false if the records are valid. 167*e8d8bef9SDimitry Andric bool DirectiveLanguage::HasValidityErrors() const { 168*e8d8bef9SDimitry Andric if (getDirectiveLanguages().size() != 1) { 169*e8d8bef9SDimitry Andric PrintFatalError("A single definition of DirectiveLanguage is needed."); 170*e8d8bef9SDimitry Andric return true; 171*e8d8bef9SDimitry Andric } 172*e8d8bef9SDimitry Andric 173*e8d8bef9SDimitry Andric return HasDuplicateClausesInDirectives(getDirectives()); 174*e8d8bef9SDimitry Andric } 175*e8d8bef9SDimitry Andric 1765ffd83dbSDimitry Andric // Generate the declaration section for the enumeration in the directive 1775ffd83dbSDimitry Andric // language 1785ffd83dbSDimitry Andric void EmitDirectivesDecl(RecordKeeper &Records, raw_ostream &OS) { 179*e8d8bef9SDimitry Andric const auto DirLang = DirectiveLanguage{Records}; 180*e8d8bef9SDimitry Andric if (DirLang.HasValidityErrors()) 1815ffd83dbSDimitry Andric return; 1825ffd83dbSDimitry Andric 183*e8d8bef9SDimitry Andric OS << "#ifndef LLVM_" << DirLang.getName() << "_INC\n"; 184*e8d8bef9SDimitry Andric OS << "#define LLVM_" << DirLang.getName() << "_INC\n"; 1855ffd83dbSDimitry Andric 186*e8d8bef9SDimitry Andric if (DirLang.hasEnableBitmaskEnumInNamespace()) 1875ffd83dbSDimitry Andric OS << "\n#include \"llvm/ADT/BitmaskEnum.h\"\n"; 1885ffd83dbSDimitry Andric 1895ffd83dbSDimitry Andric OS << "\n"; 1905ffd83dbSDimitry Andric OS << "namespace llvm {\n"; 1915ffd83dbSDimitry Andric OS << "class StringRef;\n"; 1925ffd83dbSDimitry Andric 1935ffd83dbSDimitry Andric // Open namespaces defined in the directive language 1945ffd83dbSDimitry Andric llvm::SmallVector<StringRef, 2> Namespaces; 195*e8d8bef9SDimitry Andric llvm::SplitString(DirLang.getCppNamespace(), Namespaces, "::"); 1965ffd83dbSDimitry Andric for (auto Ns : Namespaces) 1975ffd83dbSDimitry Andric OS << "namespace " << Ns << " {\n"; 1985ffd83dbSDimitry Andric 199*e8d8bef9SDimitry Andric if (DirLang.hasEnableBitmaskEnumInNamespace()) 2005ffd83dbSDimitry Andric OS << "\nLLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();\n"; 2015ffd83dbSDimitry Andric 2025ffd83dbSDimitry Andric // Emit Directive enumeration 203*e8d8bef9SDimitry Andric GenerateEnumClass(DirLang.getDirectives(), OS, "Directive", 204*e8d8bef9SDimitry Andric DirLang.getDirectivePrefix(), DirLang); 2055ffd83dbSDimitry Andric 2065ffd83dbSDimitry Andric // Emit Clause enumeration 207*e8d8bef9SDimitry Andric GenerateEnumClass(DirLang.getClauses(), OS, "Clause", 208*e8d8bef9SDimitry Andric DirLang.getClausePrefix(), DirLang); 209*e8d8bef9SDimitry Andric 210*e8d8bef9SDimitry Andric // Emit ClauseVal enumeration 211*e8d8bef9SDimitry Andric std::string EnumHelperFuncs; 212*e8d8bef9SDimitry Andric GenerateEnumClauseVal(DirLang.getClauses(), OS, DirLang, EnumHelperFuncs); 2135ffd83dbSDimitry Andric 2145ffd83dbSDimitry Andric // Generic function signatures 2155ffd83dbSDimitry Andric OS << "\n"; 2165ffd83dbSDimitry Andric OS << "// Enumeration helper functions\n"; 217*e8d8bef9SDimitry Andric OS << "Directive get" << DirLang.getName() 2185ffd83dbSDimitry Andric << "DirectiveKind(llvm::StringRef Str);\n"; 2195ffd83dbSDimitry Andric OS << "\n"; 220*e8d8bef9SDimitry Andric OS << "llvm::StringRef get" << DirLang.getName() 2215ffd83dbSDimitry Andric << "DirectiveName(Directive D);\n"; 2225ffd83dbSDimitry Andric OS << "\n"; 223*e8d8bef9SDimitry Andric OS << "Clause get" << DirLang.getName() 224*e8d8bef9SDimitry Andric << "ClauseKind(llvm::StringRef Str);\n"; 2255ffd83dbSDimitry Andric OS << "\n"; 226*e8d8bef9SDimitry Andric OS << "llvm::StringRef get" << DirLang.getName() << "ClauseName(Clause C);\n"; 2275ffd83dbSDimitry Andric OS << "\n"; 2285ffd83dbSDimitry Andric OS << "/// Return true if \\p C is a valid clause for \\p D in version \\p " 2295ffd83dbSDimitry Andric << "Version.\n"; 2305ffd83dbSDimitry Andric OS << "bool isAllowedClauseForDirective(Directive D, " 2315ffd83dbSDimitry Andric << "Clause C, unsigned Version);\n"; 2325ffd83dbSDimitry Andric OS << "\n"; 233*e8d8bef9SDimitry Andric if (EnumHelperFuncs.length() > 0) { 234*e8d8bef9SDimitry Andric OS << EnumHelperFuncs; 235*e8d8bef9SDimitry Andric OS << "\n"; 236*e8d8bef9SDimitry Andric } 2375ffd83dbSDimitry Andric 2385ffd83dbSDimitry Andric // Closing namespaces 2395ffd83dbSDimitry Andric for (auto Ns : llvm::reverse(Namespaces)) 2405ffd83dbSDimitry Andric OS << "} // namespace " << Ns << "\n"; 2415ffd83dbSDimitry Andric 2425ffd83dbSDimitry Andric OS << "} // namespace llvm\n"; 2435ffd83dbSDimitry Andric 244*e8d8bef9SDimitry Andric OS << "#endif // LLVM_" << DirLang.getName() << "_INC\n"; 2455ffd83dbSDimitry Andric } 2465ffd83dbSDimitry Andric 2475ffd83dbSDimitry Andric // Generate function implementation for get<Enum>Name(StringRef Str) 2485ffd83dbSDimitry Andric void GenerateGetName(const std::vector<Record *> &Records, raw_ostream &OS, 249*e8d8bef9SDimitry Andric StringRef Enum, const DirectiveLanguage &DirLang, 250*e8d8bef9SDimitry Andric StringRef Prefix) { 2515ffd83dbSDimitry Andric OS << "\n"; 252*e8d8bef9SDimitry Andric OS << "llvm::StringRef llvm::" << DirLang.getCppNamespace() << "::get" 253*e8d8bef9SDimitry Andric << DirLang.getName() << Enum << "Name(" << Enum << " Kind) {\n"; 2545ffd83dbSDimitry Andric OS << " switch (Kind) {\n"; 2555ffd83dbSDimitry Andric for (const auto &R : Records) { 256*e8d8bef9SDimitry Andric BaseRecord Rec{R}; 257*e8d8bef9SDimitry Andric OS << " case " << Prefix << Rec.getFormattedName() << ":\n"; 2585ffd83dbSDimitry Andric OS << " return \""; 259*e8d8bef9SDimitry Andric if (Rec.getAlternativeName().empty()) 260*e8d8bef9SDimitry Andric OS << Rec.getName(); 2615ffd83dbSDimitry Andric else 262*e8d8bef9SDimitry Andric OS << Rec.getAlternativeName(); 2635ffd83dbSDimitry Andric OS << "\";\n"; 2645ffd83dbSDimitry Andric } 2655ffd83dbSDimitry Andric OS << " }\n"; // switch 266*e8d8bef9SDimitry Andric OS << " llvm_unreachable(\"Invalid " << DirLang.getName() << " " << Enum 2675ffd83dbSDimitry Andric << " kind\");\n"; 2685ffd83dbSDimitry Andric OS << "}\n"; 2695ffd83dbSDimitry Andric } 2705ffd83dbSDimitry Andric 2715ffd83dbSDimitry Andric // Generate function implementation for get<Enum>Kind(StringRef Str) 2725ffd83dbSDimitry Andric void GenerateGetKind(const std::vector<Record *> &Records, raw_ostream &OS, 273*e8d8bef9SDimitry Andric StringRef Enum, const DirectiveLanguage &DirLang, 274*e8d8bef9SDimitry Andric StringRef Prefix, bool ImplicitAsUnknown) { 2755ffd83dbSDimitry Andric 276*e8d8bef9SDimitry Andric auto DefaultIt = llvm::find_if( 277*e8d8bef9SDimitry Andric Records, [](Record *R) { return R->getValueAsBit("isDefault") == true; }); 2785ffd83dbSDimitry Andric 2795ffd83dbSDimitry Andric if (DefaultIt == Records.end()) { 280*e8d8bef9SDimitry Andric PrintError("At least one " + Enum + " must be defined as default."); 2815ffd83dbSDimitry Andric return; 2825ffd83dbSDimitry Andric } 2835ffd83dbSDimitry Andric 284*e8d8bef9SDimitry Andric BaseRecord DefaultRec{(*DefaultIt)}; 2855ffd83dbSDimitry Andric 2865ffd83dbSDimitry Andric OS << "\n"; 287*e8d8bef9SDimitry Andric OS << Enum << " llvm::" << DirLang.getCppNamespace() << "::get" 288*e8d8bef9SDimitry Andric << DirLang.getName() << Enum << "Kind(llvm::StringRef Str) {\n"; 2895ffd83dbSDimitry Andric OS << " return llvm::StringSwitch<" << Enum << ">(Str)\n"; 2905ffd83dbSDimitry Andric 2915ffd83dbSDimitry Andric for (const auto &R : Records) { 292*e8d8bef9SDimitry Andric BaseRecord Rec{R}; 2935ffd83dbSDimitry Andric if (ImplicitAsUnknown && R->getValueAsBit("isImplicit")) { 294*e8d8bef9SDimitry Andric OS << " .Case(\"" << Rec.getName() << "\"," << Prefix 295*e8d8bef9SDimitry Andric << DefaultRec.getFormattedName() << ")\n"; 2965ffd83dbSDimitry Andric } else { 297*e8d8bef9SDimitry Andric OS << " .Case(\"" << Rec.getName() << "\"," << Prefix 298*e8d8bef9SDimitry Andric << Rec.getFormattedName() << ")\n"; 299*e8d8bef9SDimitry Andric } 300*e8d8bef9SDimitry Andric } 301*e8d8bef9SDimitry Andric OS << " .Default(" << Prefix << DefaultRec.getFormattedName() << ");\n"; 302*e8d8bef9SDimitry Andric OS << "}\n"; 303*e8d8bef9SDimitry Andric } 304*e8d8bef9SDimitry Andric 305*e8d8bef9SDimitry Andric // Generate function implementation for get<ClauseVal>Kind(StringRef Str) 306*e8d8bef9SDimitry Andric void GenerateGetKindClauseVal(const DirectiveLanguage &DirLang, 307*e8d8bef9SDimitry Andric raw_ostream &OS) { 308*e8d8bef9SDimitry Andric for (const auto &R : DirLang.getClauses()) { 309*e8d8bef9SDimitry Andric Clause C{R}; 310*e8d8bef9SDimitry Andric const auto &ClauseVals = C.getClauseVals(); 311*e8d8bef9SDimitry Andric if (ClauseVals.size() <= 0) 312*e8d8bef9SDimitry Andric continue; 313*e8d8bef9SDimitry Andric 314*e8d8bef9SDimitry Andric auto DefaultIt = llvm::find_if(ClauseVals, [](Record *CV) { 315*e8d8bef9SDimitry Andric return CV->getValueAsBit("isDefault") == true; 316*e8d8bef9SDimitry Andric }); 317*e8d8bef9SDimitry Andric 318*e8d8bef9SDimitry Andric if (DefaultIt == ClauseVals.end()) { 319*e8d8bef9SDimitry Andric PrintError("At least one val in Clause " + C.getFormattedName() + 320*e8d8bef9SDimitry Andric " must be defined as default."); 321*e8d8bef9SDimitry Andric return; 322*e8d8bef9SDimitry Andric } 323*e8d8bef9SDimitry Andric const auto DefaultName = (*DefaultIt)->getName(); 324*e8d8bef9SDimitry Andric 325*e8d8bef9SDimitry Andric const auto &EnumName = C.getEnumName(); 326*e8d8bef9SDimitry Andric if (EnumName.size() == 0) { 327*e8d8bef9SDimitry Andric PrintError("enumClauseValue field not set in Clause" + 328*e8d8bef9SDimitry Andric C.getFormattedName() + "."); 329*e8d8bef9SDimitry Andric return; 330*e8d8bef9SDimitry Andric } 331*e8d8bef9SDimitry Andric 332*e8d8bef9SDimitry Andric OS << "\n"; 333*e8d8bef9SDimitry Andric OS << EnumName << " llvm::" << DirLang.getCppNamespace() << "::get" 334*e8d8bef9SDimitry Andric << EnumName << "(llvm::StringRef Str) {\n"; 335*e8d8bef9SDimitry Andric OS << " return llvm::StringSwitch<" << EnumName << ">(Str)\n"; 336*e8d8bef9SDimitry Andric for (const auto &CV : ClauseVals) { 337*e8d8bef9SDimitry Andric ClauseVal CVal{CV}; 338*e8d8bef9SDimitry Andric OS << " .Case(\"" << CVal.getFormattedName() << "\"," << CV->getName() 3395ffd83dbSDimitry Andric << ")\n"; 3405ffd83dbSDimitry Andric } 341*e8d8bef9SDimitry Andric OS << " .Default(" << DefaultName << ");\n"; 3425ffd83dbSDimitry Andric OS << "}\n"; 343*e8d8bef9SDimitry Andric 344*e8d8bef9SDimitry Andric OS << "\n"; 345*e8d8bef9SDimitry Andric OS << "llvm::StringRef llvm::" << DirLang.getCppNamespace() << "::get" 346*e8d8bef9SDimitry Andric << DirLang.getName() << EnumName 347*e8d8bef9SDimitry Andric << "Name(llvm::" << DirLang.getCppNamespace() << "::" << EnumName 348*e8d8bef9SDimitry Andric << " x) {\n"; 349*e8d8bef9SDimitry Andric OS << " switch (x) {\n"; 350*e8d8bef9SDimitry Andric for (const auto &CV : ClauseVals) { 351*e8d8bef9SDimitry Andric ClauseVal CVal{CV}; 352*e8d8bef9SDimitry Andric OS << " case " << CV->getName() << ":\n"; 353*e8d8bef9SDimitry Andric OS << " return \"" << CVal.getFormattedName() << "\";\n"; 354*e8d8bef9SDimitry Andric } 355*e8d8bef9SDimitry Andric OS << " }\n"; // switch 356*e8d8bef9SDimitry Andric OS << " llvm_unreachable(\"Invalid " << DirLang.getName() << " " 357*e8d8bef9SDimitry Andric << EnumName << " kind\");\n"; 358*e8d8bef9SDimitry Andric OS << "}\n"; 359*e8d8bef9SDimitry Andric } 3605ffd83dbSDimitry Andric } 3615ffd83dbSDimitry Andric 3625ffd83dbSDimitry Andric void GenerateCaseForVersionedClauses(const std::vector<Record *> &Clauses, 3635ffd83dbSDimitry Andric raw_ostream &OS, StringRef DirectiveName, 364*e8d8bef9SDimitry Andric const DirectiveLanguage &DirLang, 3655ffd83dbSDimitry Andric llvm::StringSet<> &Cases) { 3665ffd83dbSDimitry Andric for (const auto &C : Clauses) { 367*e8d8bef9SDimitry Andric VersionedClause VerClause{C}; 3685ffd83dbSDimitry Andric 369*e8d8bef9SDimitry Andric const auto ClauseFormattedName = VerClause.getClause().getFormattedName(); 370*e8d8bef9SDimitry Andric 371*e8d8bef9SDimitry Andric if (Cases.find(ClauseFormattedName) == Cases.end()) { 372*e8d8bef9SDimitry Andric Cases.insert(ClauseFormattedName); 373*e8d8bef9SDimitry Andric OS << " case " << DirLang.getClausePrefix() << ClauseFormattedName 374*e8d8bef9SDimitry Andric << ":\n"; 375*e8d8bef9SDimitry Andric OS << " return " << VerClause.getMinVersion() 376*e8d8bef9SDimitry Andric << " <= Version && " << VerClause.getMaxVersion() << " >= Version;\n"; 3775ffd83dbSDimitry Andric } 3785ffd83dbSDimitry Andric } 3795ffd83dbSDimitry Andric } 3805ffd83dbSDimitry Andric 3815ffd83dbSDimitry Andric // Generate the isAllowedClauseForDirective function implementation. 382*e8d8bef9SDimitry Andric void GenerateIsAllowedClause(const DirectiveLanguage &DirLang, 383*e8d8bef9SDimitry Andric raw_ostream &OS) { 3845ffd83dbSDimitry Andric OS << "\n"; 385*e8d8bef9SDimitry Andric OS << "bool llvm::" << DirLang.getCppNamespace() 386*e8d8bef9SDimitry Andric << "::isAllowedClauseForDirective(" 3875ffd83dbSDimitry Andric << "Directive D, Clause C, unsigned Version) {\n"; 388*e8d8bef9SDimitry Andric OS << " assert(unsigned(D) <= llvm::" << DirLang.getCppNamespace() 3895ffd83dbSDimitry Andric << "::Directive_enumSize);\n"; 390*e8d8bef9SDimitry Andric OS << " assert(unsigned(C) <= llvm::" << DirLang.getCppNamespace() 3915ffd83dbSDimitry Andric << "::Clause_enumSize);\n"; 3925ffd83dbSDimitry Andric 3935ffd83dbSDimitry Andric OS << " switch (D) {\n"; 3945ffd83dbSDimitry Andric 395*e8d8bef9SDimitry Andric for (const auto &D : DirLang.getDirectives()) { 396*e8d8bef9SDimitry Andric Directive Dir{D}; 3975ffd83dbSDimitry Andric 398*e8d8bef9SDimitry Andric OS << " case " << DirLang.getDirectivePrefix() << Dir.getFormattedName() 3995ffd83dbSDimitry Andric << ":\n"; 400*e8d8bef9SDimitry Andric if (Dir.getAllowedClauses().size() == 0 && 401*e8d8bef9SDimitry Andric Dir.getAllowedOnceClauses().size() == 0 && 402*e8d8bef9SDimitry Andric Dir.getAllowedExclusiveClauses().size() == 0 && 403*e8d8bef9SDimitry Andric Dir.getRequiredClauses().size() == 0) { 4045ffd83dbSDimitry Andric OS << " return false;\n"; 4055ffd83dbSDimitry Andric } else { 4065ffd83dbSDimitry Andric OS << " switch (C) {\n"; 4075ffd83dbSDimitry Andric 4085ffd83dbSDimitry Andric llvm::StringSet<> Cases; 4095ffd83dbSDimitry Andric 410*e8d8bef9SDimitry Andric GenerateCaseForVersionedClauses(Dir.getAllowedClauses(), OS, 411*e8d8bef9SDimitry Andric Dir.getName(), DirLang, Cases); 4125ffd83dbSDimitry Andric 413*e8d8bef9SDimitry Andric GenerateCaseForVersionedClauses(Dir.getAllowedOnceClauses(), OS, 414*e8d8bef9SDimitry Andric Dir.getName(), DirLang, Cases); 4155ffd83dbSDimitry Andric 416*e8d8bef9SDimitry Andric GenerateCaseForVersionedClauses(Dir.getAllowedExclusiveClauses(), OS, 417*e8d8bef9SDimitry Andric Dir.getName(), DirLang, Cases); 4185ffd83dbSDimitry Andric 419*e8d8bef9SDimitry Andric GenerateCaseForVersionedClauses(Dir.getRequiredClauses(), OS, 420*e8d8bef9SDimitry Andric Dir.getName(), DirLang, Cases); 4215ffd83dbSDimitry Andric 4225ffd83dbSDimitry Andric OS << " default:\n"; 4235ffd83dbSDimitry Andric OS << " return false;\n"; 4245ffd83dbSDimitry Andric OS << " }\n"; // End of clauses switch 4255ffd83dbSDimitry Andric } 4265ffd83dbSDimitry Andric OS << " break;\n"; 4275ffd83dbSDimitry Andric } 4285ffd83dbSDimitry Andric 4295ffd83dbSDimitry Andric OS << " }\n"; // End of directives switch 430*e8d8bef9SDimitry Andric OS << " llvm_unreachable(\"Invalid " << DirLang.getName() 4315ffd83dbSDimitry Andric << " Directive kind\");\n"; 4325ffd83dbSDimitry Andric OS << "}\n"; // End of function isAllowedClauseForDirective 4335ffd83dbSDimitry Andric } 4345ffd83dbSDimitry Andric 4355ffd83dbSDimitry Andric // Generate a simple enum set with the give clauses. 4365ffd83dbSDimitry Andric void GenerateClauseSet(const std::vector<Record *> &Clauses, raw_ostream &OS, 437*e8d8bef9SDimitry Andric StringRef ClauseSetPrefix, Directive &Dir, 438*e8d8bef9SDimitry Andric const DirectiveLanguage &DirLang) { 4395ffd83dbSDimitry Andric 4405ffd83dbSDimitry Andric OS << "\n"; 441*e8d8bef9SDimitry Andric OS << " static " << DirLang.getClauseEnumSetClass() << " " << ClauseSetPrefix 442*e8d8bef9SDimitry Andric << DirLang.getDirectivePrefix() << Dir.getFormattedName() << " {\n"; 4435ffd83dbSDimitry Andric 4445ffd83dbSDimitry Andric for (const auto &C : Clauses) { 445*e8d8bef9SDimitry Andric VersionedClause VerClause{C}; 446*e8d8bef9SDimitry Andric OS << " llvm::" << DirLang.getCppNamespace() 447*e8d8bef9SDimitry Andric << "::Clause::" << DirLang.getClausePrefix() 448*e8d8bef9SDimitry Andric << VerClause.getClause().getFormattedName() << ",\n"; 4495ffd83dbSDimitry Andric } 4505ffd83dbSDimitry Andric OS << " };\n"; 4515ffd83dbSDimitry Andric } 4525ffd83dbSDimitry Andric 4535ffd83dbSDimitry Andric // Generate an enum set for the 4 kinds of clauses linked to a directive. 454*e8d8bef9SDimitry Andric void GenerateDirectiveClauseSets(const DirectiveLanguage &DirLang, 455*e8d8bef9SDimitry Andric raw_ostream &OS) { 4565ffd83dbSDimitry Andric 4575ffd83dbSDimitry Andric IfDefScope Scope("GEN_FLANG_DIRECTIVE_CLAUSE_SETS", OS); 4585ffd83dbSDimitry Andric 4595ffd83dbSDimitry Andric OS << "\n"; 4605ffd83dbSDimitry Andric OS << "namespace llvm {\n"; 4615ffd83dbSDimitry Andric 4625ffd83dbSDimitry Andric // Open namespaces defined in the directive language. 4635ffd83dbSDimitry Andric llvm::SmallVector<StringRef, 2> Namespaces; 464*e8d8bef9SDimitry Andric llvm::SplitString(DirLang.getCppNamespace(), Namespaces, "::"); 4655ffd83dbSDimitry Andric for (auto Ns : Namespaces) 4665ffd83dbSDimitry Andric OS << "namespace " << Ns << " {\n"; 4675ffd83dbSDimitry Andric 468*e8d8bef9SDimitry Andric for (const auto &D : DirLang.getDirectives()) { 469*e8d8bef9SDimitry Andric Directive Dir{D}; 4705ffd83dbSDimitry Andric 4715ffd83dbSDimitry Andric OS << "\n"; 472*e8d8bef9SDimitry Andric OS << " // Sets for " << Dir.getName() << "\n"; 4735ffd83dbSDimitry Andric 474*e8d8bef9SDimitry Andric GenerateClauseSet(Dir.getAllowedClauses(), OS, "allowedClauses_", Dir, 475*e8d8bef9SDimitry Andric DirLang); 476*e8d8bef9SDimitry Andric GenerateClauseSet(Dir.getAllowedOnceClauses(), OS, "allowedOnceClauses_", 477*e8d8bef9SDimitry Andric Dir, DirLang); 478*e8d8bef9SDimitry Andric GenerateClauseSet(Dir.getAllowedExclusiveClauses(), OS, 479*e8d8bef9SDimitry Andric "allowedExclusiveClauses_", Dir, DirLang); 480*e8d8bef9SDimitry Andric GenerateClauseSet(Dir.getRequiredClauses(), OS, "requiredClauses_", Dir, 481*e8d8bef9SDimitry Andric DirLang); 4825ffd83dbSDimitry Andric } 4835ffd83dbSDimitry Andric 4845ffd83dbSDimitry Andric // Closing namespaces 4855ffd83dbSDimitry Andric for (auto Ns : llvm::reverse(Namespaces)) 4865ffd83dbSDimitry Andric OS << "} // namespace " << Ns << "\n"; 4875ffd83dbSDimitry Andric 4885ffd83dbSDimitry Andric OS << "} // namespace llvm\n"; 4895ffd83dbSDimitry Andric } 4905ffd83dbSDimitry Andric 4915ffd83dbSDimitry Andric // Generate a map of directive (key) with DirectiveClauses struct as values. 4925ffd83dbSDimitry Andric // The struct holds the 4 sets of enumeration for the 4 kinds of clauses 4935ffd83dbSDimitry Andric // allowances (allowed, allowed once, allowed exclusive and required). 494*e8d8bef9SDimitry Andric void GenerateDirectiveClauseMap(const DirectiveLanguage &DirLang, 495*e8d8bef9SDimitry Andric raw_ostream &OS) { 4965ffd83dbSDimitry Andric 4975ffd83dbSDimitry Andric IfDefScope Scope("GEN_FLANG_DIRECTIVE_CLAUSE_MAP", OS); 4985ffd83dbSDimitry Andric 4995ffd83dbSDimitry Andric OS << "\n"; 5005ffd83dbSDimitry Andric OS << "{\n"; 501*e8d8bef9SDimitry Andric 502*e8d8bef9SDimitry Andric for (const auto &D : DirLang.getDirectives()) { 503*e8d8bef9SDimitry Andric Directive Dir{D}; 504*e8d8bef9SDimitry Andric OS << " {llvm::" << DirLang.getCppNamespace() 505*e8d8bef9SDimitry Andric << "::Directive::" << DirLang.getDirectivePrefix() 506*e8d8bef9SDimitry Andric << Dir.getFormattedName() << ",\n"; 507*e8d8bef9SDimitry Andric OS << " {\n"; 508*e8d8bef9SDimitry Andric OS << " llvm::" << DirLang.getCppNamespace() << "::allowedClauses_" 509*e8d8bef9SDimitry Andric << DirLang.getDirectivePrefix() << Dir.getFormattedName() << ",\n"; 510*e8d8bef9SDimitry Andric OS << " llvm::" << DirLang.getCppNamespace() << "::allowedOnceClauses_" 511*e8d8bef9SDimitry Andric << DirLang.getDirectivePrefix() << Dir.getFormattedName() << ",\n"; 512*e8d8bef9SDimitry Andric OS << " llvm::" << DirLang.getCppNamespace() 513*e8d8bef9SDimitry Andric << "::allowedExclusiveClauses_" << DirLang.getDirectivePrefix() 514*e8d8bef9SDimitry Andric << Dir.getFormattedName() << ",\n"; 515*e8d8bef9SDimitry Andric OS << " llvm::" << DirLang.getCppNamespace() << "::requiredClauses_" 516*e8d8bef9SDimitry Andric << DirLang.getDirectivePrefix() << Dir.getFormattedName() << ",\n"; 5175ffd83dbSDimitry Andric OS << " }\n"; 5185ffd83dbSDimitry Andric OS << " },\n"; 5195ffd83dbSDimitry Andric } 5205ffd83dbSDimitry Andric 521*e8d8bef9SDimitry Andric OS << "}\n"; 5225ffd83dbSDimitry Andric } 5235ffd83dbSDimitry Andric 524*e8d8bef9SDimitry Andric // Generate classes entry for Flang clauses in the Flang parse-tree 525*e8d8bef9SDimitry Andric // If the clause as a non-generic class, no entry is generated. 526*e8d8bef9SDimitry Andric // If the clause does not hold a value, an EMPTY_CLASS is used. 527*e8d8bef9SDimitry Andric // If the clause class is generic then a WRAPPER_CLASS is used. When the value 528*e8d8bef9SDimitry Andric // is optional, the value class is wrapped into a std::optional. 529*e8d8bef9SDimitry Andric void GenerateFlangClauseParserClass(const DirectiveLanguage &DirLang, 530*e8d8bef9SDimitry Andric raw_ostream &OS) { 531*e8d8bef9SDimitry Andric 532*e8d8bef9SDimitry Andric IfDefScope Scope("GEN_FLANG_CLAUSE_PARSER_CLASSES", OS); 533*e8d8bef9SDimitry Andric 534*e8d8bef9SDimitry Andric OS << "\n"; 535*e8d8bef9SDimitry Andric 536*e8d8bef9SDimitry Andric for (const auto &C : DirLang.getClauses()) { 537*e8d8bef9SDimitry Andric Clause Clause{C}; 538*e8d8bef9SDimitry Andric if (!Clause.getFlangClass().empty()) { 539*e8d8bef9SDimitry Andric OS << "WRAPPER_CLASS(" << Clause.getFormattedParserClassName() << ", "; 540*e8d8bef9SDimitry Andric if (Clause.isValueOptional() && Clause.isValueList()) { 541*e8d8bef9SDimitry Andric OS << "std::optional<std::list<" << Clause.getFlangClass() << ">>"; 542*e8d8bef9SDimitry Andric } else if (Clause.isValueOptional()) { 543*e8d8bef9SDimitry Andric OS << "std::optional<" << Clause.getFlangClass() << ">"; 544*e8d8bef9SDimitry Andric } else if (Clause.isValueList()) { 545*e8d8bef9SDimitry Andric OS << "std::list<" << Clause.getFlangClass() << ">"; 546*e8d8bef9SDimitry Andric } else { 547*e8d8bef9SDimitry Andric OS << Clause.getFlangClass(); 548*e8d8bef9SDimitry Andric } 549*e8d8bef9SDimitry Andric } else { 550*e8d8bef9SDimitry Andric OS << "EMPTY_CLASS(" << Clause.getFormattedParserClassName(); 551*e8d8bef9SDimitry Andric } 552*e8d8bef9SDimitry Andric OS << ");\n"; 553*e8d8bef9SDimitry Andric } 554*e8d8bef9SDimitry Andric } 555*e8d8bef9SDimitry Andric 556*e8d8bef9SDimitry Andric // Generate a list of the different clause classes for Flang. 557*e8d8bef9SDimitry Andric void GenerateFlangClauseParserClassList(const DirectiveLanguage &DirLang, 558*e8d8bef9SDimitry Andric raw_ostream &OS) { 559*e8d8bef9SDimitry Andric 560*e8d8bef9SDimitry Andric IfDefScope Scope("GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST", OS); 561*e8d8bef9SDimitry Andric 562*e8d8bef9SDimitry Andric OS << "\n"; 563*e8d8bef9SDimitry Andric llvm::interleaveComma(DirLang.getClauses(), OS, [&](Record *C) { 564*e8d8bef9SDimitry Andric Clause Clause{C}; 565*e8d8bef9SDimitry Andric OS << Clause.getFormattedParserClassName() << "\n"; 566*e8d8bef9SDimitry Andric }); 567*e8d8bef9SDimitry Andric } 568*e8d8bef9SDimitry Andric 569*e8d8bef9SDimitry Andric // Generate dump node list for the clauses holding a generic class name. 570*e8d8bef9SDimitry Andric void GenerateFlangClauseDump(const DirectiveLanguage &DirLang, 571*e8d8bef9SDimitry Andric raw_ostream &OS) { 572*e8d8bef9SDimitry Andric 573*e8d8bef9SDimitry Andric IfDefScope Scope("GEN_FLANG_DUMP_PARSE_TREE_CLAUSES", OS); 574*e8d8bef9SDimitry Andric 575*e8d8bef9SDimitry Andric OS << "\n"; 576*e8d8bef9SDimitry Andric for (const auto &C : DirLang.getClauses()) { 577*e8d8bef9SDimitry Andric Clause Clause{C}; 578*e8d8bef9SDimitry Andric OS << "NODE(" << DirLang.getFlangClauseBaseClass() << ", " 579*e8d8bef9SDimitry Andric << Clause.getFormattedParserClassName() << ")\n"; 580*e8d8bef9SDimitry Andric } 581*e8d8bef9SDimitry Andric } 582*e8d8bef9SDimitry Andric 583*e8d8bef9SDimitry Andric // Generate Unparse functions for clauses classes in the Flang parse-tree 584*e8d8bef9SDimitry Andric // If the clause is a non-generic class, no entry is generated. 585*e8d8bef9SDimitry Andric void GenerateFlangClauseUnparse(const DirectiveLanguage &DirLang, 586*e8d8bef9SDimitry Andric raw_ostream &OS) { 587*e8d8bef9SDimitry Andric 588*e8d8bef9SDimitry Andric IfDefScope Scope("GEN_FLANG_CLAUSE_UNPARSE", OS); 589*e8d8bef9SDimitry Andric 590*e8d8bef9SDimitry Andric OS << "\n"; 591*e8d8bef9SDimitry Andric 592*e8d8bef9SDimitry Andric for (const auto &C : DirLang.getClauses()) { 593*e8d8bef9SDimitry Andric Clause Clause{C}; 594*e8d8bef9SDimitry Andric if (!Clause.getFlangClass().empty()) { 595*e8d8bef9SDimitry Andric if (Clause.isValueOptional() && Clause.getDefaultValue().empty()) { 596*e8d8bef9SDimitry Andric OS << "void Unparse(const " << DirLang.getFlangClauseBaseClass() 597*e8d8bef9SDimitry Andric << "::" << Clause.getFormattedParserClassName() << " &x) {\n"; 598*e8d8bef9SDimitry Andric OS << " Word(\"" << Clause.getName().upper() << "\");\n"; 599*e8d8bef9SDimitry Andric 600*e8d8bef9SDimitry Andric OS << " Walk(\"(\", x.v, \")\");\n"; 601*e8d8bef9SDimitry Andric OS << "}\n"; 602*e8d8bef9SDimitry Andric } else if (Clause.isValueOptional()) { 603*e8d8bef9SDimitry Andric OS << "void Unparse(const " << DirLang.getFlangClauseBaseClass() 604*e8d8bef9SDimitry Andric << "::" << Clause.getFormattedParserClassName() << " &x) {\n"; 605*e8d8bef9SDimitry Andric OS << " Word(\"" << Clause.getName().upper() << "\");\n"; 606*e8d8bef9SDimitry Andric OS << " Put(\"(\");\n"; 607*e8d8bef9SDimitry Andric OS << " if (x.v.has_value())\n"; 608*e8d8bef9SDimitry Andric if (Clause.isValueList()) 609*e8d8bef9SDimitry Andric OS << " Walk(x.v, \",\");\n"; 610*e8d8bef9SDimitry Andric else 611*e8d8bef9SDimitry Andric OS << " Walk(x.v);\n"; 612*e8d8bef9SDimitry Andric OS << " else\n"; 613*e8d8bef9SDimitry Andric OS << " Put(\"" << Clause.getDefaultValue() << "\");\n"; 614*e8d8bef9SDimitry Andric OS << " Put(\")\");\n"; 615*e8d8bef9SDimitry Andric OS << "}\n"; 616*e8d8bef9SDimitry Andric } else { 617*e8d8bef9SDimitry Andric OS << "void Unparse(const " << DirLang.getFlangClauseBaseClass() 618*e8d8bef9SDimitry Andric << "::" << Clause.getFormattedParserClassName() << " &x) {\n"; 619*e8d8bef9SDimitry Andric OS << " Word(\"" << Clause.getName().upper() << "\");\n"; 620*e8d8bef9SDimitry Andric OS << " Put(\"(\");\n"; 621*e8d8bef9SDimitry Andric if (Clause.isValueList()) 622*e8d8bef9SDimitry Andric OS << " Walk(x.v, \",\");\n"; 623*e8d8bef9SDimitry Andric else 624*e8d8bef9SDimitry Andric OS << " Walk(x.v);\n"; 625*e8d8bef9SDimitry Andric OS << " Put(\")\");\n"; 626*e8d8bef9SDimitry Andric OS << "}\n"; 627*e8d8bef9SDimitry Andric } 628*e8d8bef9SDimitry Andric } else { 629*e8d8bef9SDimitry Andric OS << "void Before(const " << DirLang.getFlangClauseBaseClass() 630*e8d8bef9SDimitry Andric << "::" << Clause.getFormattedParserClassName() << " &) { Word(\"" 631*e8d8bef9SDimitry Andric << Clause.getName().upper() << "\"); }\n"; 632*e8d8bef9SDimitry Andric } 633*e8d8bef9SDimitry Andric } 634*e8d8bef9SDimitry Andric } 635*e8d8bef9SDimitry Andric 636*e8d8bef9SDimitry Andric // Generate the implementation section for the enumeration in the directive 6375ffd83dbSDimitry Andric // language 638*e8d8bef9SDimitry Andric void EmitDirectivesFlangImpl(const DirectiveLanguage &DirLang, 639*e8d8bef9SDimitry Andric raw_ostream &OS) { 6405ffd83dbSDimitry Andric 641*e8d8bef9SDimitry Andric GenerateDirectiveClauseSets(DirLang, OS); 6425ffd83dbSDimitry Andric 643*e8d8bef9SDimitry Andric GenerateDirectiveClauseMap(DirLang, OS); 644*e8d8bef9SDimitry Andric 645*e8d8bef9SDimitry Andric GenerateFlangClauseParserClass(DirLang, OS); 646*e8d8bef9SDimitry Andric 647*e8d8bef9SDimitry Andric GenerateFlangClauseParserClassList(DirLang, OS); 648*e8d8bef9SDimitry Andric 649*e8d8bef9SDimitry Andric GenerateFlangClauseDump(DirLang, OS); 650*e8d8bef9SDimitry Andric 651*e8d8bef9SDimitry Andric GenerateFlangClauseUnparse(DirLang, OS); 6525ffd83dbSDimitry Andric } 6535ffd83dbSDimitry Andric 654*e8d8bef9SDimitry Andric void GenerateClauseClassMacro(const DirectiveLanguage &DirLang, 655*e8d8bef9SDimitry Andric raw_ostream &OS) { 656*e8d8bef9SDimitry Andric // Generate macros style information for legacy code in clang 657*e8d8bef9SDimitry Andric IfDefScope Scope("GEN_CLANG_CLAUSE_CLASS", OS); 658*e8d8bef9SDimitry Andric 659*e8d8bef9SDimitry Andric OS << "\n"; 660*e8d8bef9SDimitry Andric 661*e8d8bef9SDimitry Andric OS << "#ifndef CLAUSE\n"; 662*e8d8bef9SDimitry Andric OS << "#define CLAUSE(Enum, Str, Implicit)\n"; 663*e8d8bef9SDimitry Andric OS << "#endif\n"; 664*e8d8bef9SDimitry Andric OS << "#ifndef CLAUSE_CLASS\n"; 665*e8d8bef9SDimitry Andric OS << "#define CLAUSE_CLASS(Enum, Str, Class)\n"; 666*e8d8bef9SDimitry Andric OS << "#endif\n"; 667*e8d8bef9SDimitry Andric OS << "#ifndef CLAUSE_NO_CLASS\n"; 668*e8d8bef9SDimitry Andric OS << "#define CLAUSE_NO_CLASS(Enum, Str)\n"; 669*e8d8bef9SDimitry Andric OS << "#endif\n"; 670*e8d8bef9SDimitry Andric OS << "\n"; 671*e8d8bef9SDimitry Andric OS << "#define __CLAUSE(Name, Class) \\\n"; 672*e8d8bef9SDimitry Andric OS << " CLAUSE(" << DirLang.getClausePrefix() 673*e8d8bef9SDimitry Andric << "##Name, #Name, /* Implicit */ false) \\\n"; 674*e8d8bef9SDimitry Andric OS << " CLAUSE_CLASS(" << DirLang.getClausePrefix() 675*e8d8bef9SDimitry Andric << "##Name, #Name, Class)\n"; 676*e8d8bef9SDimitry Andric OS << "#define __CLAUSE_NO_CLASS(Name) \\\n"; 677*e8d8bef9SDimitry Andric OS << " CLAUSE(" << DirLang.getClausePrefix() 678*e8d8bef9SDimitry Andric << "##Name, #Name, /* Implicit */ false) \\\n"; 679*e8d8bef9SDimitry Andric OS << " CLAUSE_NO_CLASS(" << DirLang.getClausePrefix() << "##Name, #Name)\n"; 680*e8d8bef9SDimitry Andric OS << "#define __IMPLICIT_CLAUSE_CLASS(Name, Str, Class) \\\n"; 681*e8d8bef9SDimitry Andric OS << " CLAUSE(" << DirLang.getClausePrefix() 682*e8d8bef9SDimitry Andric << "##Name, Str, /* Implicit */ true) \\\n"; 683*e8d8bef9SDimitry Andric OS << " CLAUSE_CLASS(" << DirLang.getClausePrefix() 684*e8d8bef9SDimitry Andric << "##Name, Str, Class)\n"; 685*e8d8bef9SDimitry Andric OS << "#define __IMPLICIT_CLAUSE_NO_CLASS(Name, Str) \\\n"; 686*e8d8bef9SDimitry Andric OS << " CLAUSE(" << DirLang.getClausePrefix() 687*e8d8bef9SDimitry Andric << "##Name, Str, /* Implicit */ true) \\\n"; 688*e8d8bef9SDimitry Andric OS << " CLAUSE_NO_CLASS(" << DirLang.getClausePrefix() << "##Name, Str)\n"; 689*e8d8bef9SDimitry Andric OS << "\n"; 690*e8d8bef9SDimitry Andric 691*e8d8bef9SDimitry Andric for (const auto &R : DirLang.getClauses()) { 692*e8d8bef9SDimitry Andric Clause C{R}; 693*e8d8bef9SDimitry Andric if (C.getClangClass().empty()) { // NO_CLASS 694*e8d8bef9SDimitry Andric if (C.isImplicit()) { 695*e8d8bef9SDimitry Andric OS << "__IMPLICIT_CLAUSE_NO_CLASS(" << C.getFormattedName() << ", \"" 696*e8d8bef9SDimitry Andric << C.getFormattedName() << "\")\n"; 697*e8d8bef9SDimitry Andric } else { 698*e8d8bef9SDimitry Andric OS << "__CLAUSE_NO_CLASS(" << C.getFormattedName() << ")\n"; 699*e8d8bef9SDimitry Andric } 700*e8d8bef9SDimitry Andric } else { // CLASS 701*e8d8bef9SDimitry Andric if (C.isImplicit()) { 702*e8d8bef9SDimitry Andric OS << "__IMPLICIT_CLAUSE_CLASS(" << C.getFormattedName() << ", \"" 703*e8d8bef9SDimitry Andric << C.getFormattedName() << "\", " << C.getClangClass() << ")\n"; 704*e8d8bef9SDimitry Andric } else { 705*e8d8bef9SDimitry Andric OS << "__CLAUSE(" << C.getFormattedName() << ", " << C.getClangClass() 706*e8d8bef9SDimitry Andric << ")\n"; 707*e8d8bef9SDimitry Andric } 708*e8d8bef9SDimitry Andric } 709*e8d8bef9SDimitry Andric } 710*e8d8bef9SDimitry Andric 711*e8d8bef9SDimitry Andric OS << "\n"; 712*e8d8bef9SDimitry Andric OS << "#undef __IMPLICIT_CLAUSE_NO_CLASS\n"; 713*e8d8bef9SDimitry Andric OS << "#undef __IMPLICIT_CLAUSE_CLASS\n"; 714*e8d8bef9SDimitry Andric OS << "#undef __CLAUSE\n"; 715*e8d8bef9SDimitry Andric OS << "#undef CLAUSE_NO_CLASS\n"; 716*e8d8bef9SDimitry Andric OS << "#undef CLAUSE_CLASS\n"; 717*e8d8bef9SDimitry Andric OS << "#undef CLAUSE\n"; 718*e8d8bef9SDimitry Andric } 719*e8d8bef9SDimitry Andric 720*e8d8bef9SDimitry Andric // Generate the implementation section for the enumeration in the directive 7215ffd83dbSDimitry Andric // language. 7225ffd83dbSDimitry Andric void EmitDirectivesGen(RecordKeeper &Records, raw_ostream &OS) { 723*e8d8bef9SDimitry Andric const auto DirLang = DirectiveLanguage{Records}; 724*e8d8bef9SDimitry Andric if (DirLang.HasValidityErrors()) 7255ffd83dbSDimitry Andric return; 726*e8d8bef9SDimitry Andric 727*e8d8bef9SDimitry Andric EmitDirectivesFlangImpl(DirLang, OS); 728*e8d8bef9SDimitry Andric 729*e8d8bef9SDimitry Andric GenerateClauseClassMacro(DirLang, OS); 7305ffd83dbSDimitry Andric } 7315ffd83dbSDimitry Andric 732*e8d8bef9SDimitry Andric // Generate the implementation for the enumeration in the directive 7335ffd83dbSDimitry Andric // language. This code can be included in library. 7345ffd83dbSDimitry Andric void EmitDirectivesImpl(RecordKeeper &Records, raw_ostream &OS) { 735*e8d8bef9SDimitry Andric const auto DirLang = DirectiveLanguage{Records}; 736*e8d8bef9SDimitry Andric if (DirLang.HasValidityErrors()) 7375ffd83dbSDimitry Andric return; 7385ffd83dbSDimitry Andric 739*e8d8bef9SDimitry Andric if (!DirLang.getIncludeHeader().empty()) 740*e8d8bef9SDimitry Andric OS << "#include \"" << DirLang.getIncludeHeader() << "\"\n\n"; 7415ffd83dbSDimitry Andric 7425ffd83dbSDimitry Andric OS << "#include \"llvm/ADT/StringRef.h\"\n"; 7435ffd83dbSDimitry Andric OS << "#include \"llvm/ADT/StringSwitch.h\"\n"; 7445ffd83dbSDimitry Andric OS << "#include \"llvm/Support/ErrorHandling.h\"\n"; 7455ffd83dbSDimitry Andric OS << "\n"; 7465ffd83dbSDimitry Andric OS << "using namespace llvm;\n"; 7475ffd83dbSDimitry Andric llvm::SmallVector<StringRef, 2> Namespaces; 748*e8d8bef9SDimitry Andric llvm::SplitString(DirLang.getCppNamespace(), Namespaces, "::"); 7495ffd83dbSDimitry Andric for (auto Ns : Namespaces) 7505ffd83dbSDimitry Andric OS << "using namespace " << Ns << ";\n"; 7515ffd83dbSDimitry Andric 7525ffd83dbSDimitry Andric // getDirectiveKind(StringRef Str) 753*e8d8bef9SDimitry Andric GenerateGetKind(DirLang.getDirectives(), OS, "Directive", DirLang, 754*e8d8bef9SDimitry Andric DirLang.getDirectivePrefix(), /*ImplicitAsUnknown=*/false); 7555ffd83dbSDimitry Andric 7565ffd83dbSDimitry Andric // getDirectiveName(Directive Kind) 757*e8d8bef9SDimitry Andric GenerateGetName(DirLang.getDirectives(), OS, "Directive", DirLang, 758*e8d8bef9SDimitry Andric DirLang.getDirectivePrefix()); 7595ffd83dbSDimitry Andric 7605ffd83dbSDimitry Andric // getClauseKind(StringRef Str) 761*e8d8bef9SDimitry Andric GenerateGetKind(DirLang.getClauses(), OS, "Clause", DirLang, 762*e8d8bef9SDimitry Andric DirLang.getClausePrefix(), 763*e8d8bef9SDimitry Andric /*ImplicitAsUnknown=*/true); 7645ffd83dbSDimitry Andric 7655ffd83dbSDimitry Andric // getClauseName(Clause Kind) 766*e8d8bef9SDimitry Andric GenerateGetName(DirLang.getClauses(), OS, "Clause", DirLang, 767*e8d8bef9SDimitry Andric DirLang.getClausePrefix()); 768*e8d8bef9SDimitry Andric 769*e8d8bef9SDimitry Andric // get<ClauseVal>Kind(StringRef Str) 770*e8d8bef9SDimitry Andric GenerateGetKindClauseVal(DirLang, OS); 7715ffd83dbSDimitry Andric 7725ffd83dbSDimitry Andric // isAllowedClauseForDirective(Directive D, Clause C, unsigned Version) 773*e8d8bef9SDimitry Andric GenerateIsAllowedClause(DirLang, OS); 7745ffd83dbSDimitry Andric } 7755ffd83dbSDimitry Andric 7765ffd83dbSDimitry Andric } // namespace llvm 777