diff --git a/llvm/include/llvm/TableGen/DirectiveEmitter.h b/llvm/include/llvm/TableGen/DirectiveEmitter.h --- a/llvm/include/llvm/TableGen/DirectiveEmitter.h +++ b/llvm/include/llvm/TableGen/DirectiveEmitter.h @@ -10,7 +10,11 @@ // DirectiveBase.td and provides helper methods for accessing it. class DirectiveLanguage { public: - explicit DirectiveLanguage(const llvm::Record *Def) : Def(Def) {} + explicit DirectiveLanguage(const llvm::RecordKeeper &Records) + : Records(Records) { + const auto &DirectiveLanguages = getDirectiveLanguages(); + Def = DirectiveLanguages[0]; + } StringRef getName() const { return Def->getValueAsString("name"); } @@ -46,8 +50,23 @@ return Def->getValueAsBit("enableBitmaskEnumInNamespace"); } + const std::vector getDirectives() const { + return Records.getAllDerivedDefinitions("Directive"); + } + + const std::vector getClauses() const { + return Records.getAllDerivedDefinitions("Clause"); + } + + bool CheckRecordsValidity() const; + private: const llvm::Record *Def; + const llvm::RecordKeeper &Records; + + const std::vector getDirectiveLanguages() const { + return Records.getAllDerivedDefinitions("DirectiveLanguage"); + } }; // Base record class used for Directive and Clause class defined in diff --git a/llvm/utils/TableGen/DirectiveEmitter.cpp b/llvm/utils/TableGen/DirectiveEmitter.cpp --- a/llvm/utils/TableGen/DirectiveEmitter.cpp +++ b/llvm/utils/TableGen/DirectiveEmitter.cpp @@ -43,7 +43,7 @@ // Generate enum class void GenerateEnumClass(const std::vector &Records, raw_ostream &OS, StringRef Enum, StringRef Prefix, - DirectiveLanguage &DirLang) { + const DirectiveLanguage &DirLang) { OS << "\n"; OS << "enum class " << Enum << " {\n"; for (const auto &R : Records) { @@ -74,7 +74,7 @@ // Generate enums for values that clauses can take. // Also generate function declarations for getName(StringRef Str). void GenerateEnumClauseVal(const std::vector &Records, - raw_ostream &OS, DirectiveLanguage &DirLang, + raw_ostream &OS, const DirectiveLanguage &DirLang, std::string &EnumHelperFuncs) { for (const auto &R : Records) { Clause C{R}; @@ -146,32 +146,22 @@ // Check consitency of records. Return true if an error has been detected. // Return false if the records are valid. -bool CheckRecordsValidity(RecordKeeper &Records) { - const auto &DirectiveLanguages = - Records.getAllDerivedDefinitions("DirectiveLanguage"); - - if (DirectiveLanguages.size() != 1) { +bool DirectiveLanguage::CheckRecordsValidity() const { + if (getDirectiveLanguages().size() != 1) { PrintError("A single definition of DirectiveLanguage is needed."); return true; } - const auto &Directives = Records.getAllDerivedDefinitions("Directive"); - return HasDuplicateClausesInDirectives(Directives); + return HasDuplicateClausesInDirectives(getDirectives()); } // Generate the declaration section for the enumeration in the directive // language void EmitDirectivesDecl(RecordKeeper &Records, raw_ostream &OS) { - - if (CheckRecordsValidity(Records)) + const auto DirLang = DirectiveLanguage{Records}; + if (DirLang.CheckRecordsValidity()) return; - const auto &DirectiveLanguages = - Records.getAllDerivedDefinitions("DirectiveLanguage"); - - DirectiveLanguage DirLang{DirectiveLanguages[0]}; - const auto &Directives = Records.getAllDerivedDefinitions("Directive"); - OS << "#ifndef LLVM_" << DirLang.getName() << "_INC\n"; OS << "#define LLVM_" << DirLang.getName() << "_INC\n"; @@ -192,16 +182,16 @@ OS << "\nLLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();\n"; // Emit Directive enumeration - GenerateEnumClass(Directives, OS, "Directive", DirLang.getDirectivePrefix(), - DirLang); + GenerateEnumClass(DirLang.getDirectives(), OS, "Directive", + DirLang.getDirectivePrefix(), DirLang); // Emit Clause enumeration - const auto &Clauses = Records.getAllDerivedDefinitions("Clause"); - GenerateEnumClass(Clauses, OS, "Clause", DirLang.getClausePrefix(), DirLang); + GenerateEnumClass(DirLang.getClauses(), OS, "Clause", + DirLang.getClausePrefix(), DirLang); // Emit ClauseVal enumeration std::string EnumHelperFuncs; - GenerateEnumClauseVal(Clauses, OS, DirLang, EnumHelperFuncs); + GenerateEnumClauseVal(DirLang.getClauses(), OS, DirLang, EnumHelperFuncs); // Generic function signatures OS << "\n"; @@ -238,7 +228,7 @@ // Generate function implementation for getName(StringRef Str) void GenerateGetName(const std::vector &Records, raw_ostream &OS, - StringRef Enum, DirectiveLanguage &DirLang, + StringRef Enum, const DirectiveLanguage &DirLang, StringRef Prefix) { OS << "\n"; OS << "llvm::StringRef llvm::" << DirLang.getCppNamespace() << "::get" @@ -262,7 +252,7 @@ // Generate function implementation for getKind(StringRef Str) void GenerateGetKind(const std::vector &Records, raw_ostream &OS, - StringRef Enum, DirectiveLanguage &DirLang, + StringRef Enum, const DirectiveLanguage &DirLang, StringRef Prefix, bool ImplicitAsUnknown) { auto DefaultIt = std::find_if(Records.begin(), Records.end(), [](Record *R) { @@ -296,10 +286,9 @@ } // Generate function implementation for getKind(StringRef Str) -void GenerateGetKindClauseVal(const std::vector &Records, - raw_ostream &OS, StringRef Namespace) { - - for (const auto &R : Records) { +void GenerateGetKindClauseVal(const DirectiveLanguage &DirLang, + raw_ostream &OS) { + for (const auto &R : DirLang.getClauses()) { Clause C{R}; const auto &ClauseVals = C.getClauseVals(); if (ClauseVals.size() <= 0) @@ -325,8 +314,8 @@ } OS << "\n"; - OS << EnumName << " llvm::" << Namespace << "::get" << EnumName - << "(llvm::StringRef Str) {\n"; + OS << EnumName << " llvm::" << DirLang.getCppNamespace() << "::get" + << EnumName << "(llvm::StringRef Str) {\n"; OS << " return llvm::StringSwitch<" << EnumName << ">(Str)\n"; for (const auto &CV : ClauseVals) { ClauseVal CVal{CV}; @@ -340,7 +329,7 @@ void GenerateCaseForVersionedClauses(const std::vector &Clauses, raw_ostream &OS, StringRef DirectiveName, - DirectiveLanguage &DirLang, + const DirectiveLanguage &DirLang, llvm::StringSet<> &Cases) { for (const auto &C : Clauses) { VersionedClause VerClause{C}; @@ -358,8 +347,8 @@ } // Generate the isAllowedClauseForDirective function implementation. -void GenerateIsAllowedClause(const std::vector &Directives, - raw_ostream &OS, DirectiveLanguage &DirLang) { +void GenerateIsAllowedClause(const DirectiveLanguage &DirLang, + raw_ostream &OS) { OS << "\n"; OS << "bool llvm::" << DirLang.getCppNamespace() << "::isAllowedClauseForDirective(" @@ -371,7 +360,7 @@ OS << " switch (D) {\n"; - for (const auto &D : Directives) { + for (const auto &D : DirLang.getDirectives()) { Directive Dir{D}; OS << " case " << DirLang.getDirectivePrefix() << Dir.getFormattedName() @@ -414,7 +403,7 @@ // Generate a simple enum set with the give clauses. void GenerateClauseSet(const std::vector &Clauses, raw_ostream &OS, StringRef ClauseSetPrefix, Directive &Dir, - DirectiveLanguage &DirLang) { + const DirectiveLanguage &DirLang) { OS << "\n"; OS << " static " << DirLang.getClauseEnumSetClass() << " " << ClauseSetPrefix @@ -430,8 +419,8 @@ } // Generate an enum set for the 4 kinds of clauses linked to a directive. -void GenerateDirectiveClauseSets(const std::vector &Directives, - raw_ostream &OS, DirectiveLanguage &DirLang) { +void GenerateDirectiveClauseSets(const DirectiveLanguage &DirLang, + raw_ostream &OS) { IfDefScope Scope("GEN_FLANG_DIRECTIVE_CLAUSE_SETS", OS); @@ -444,7 +433,7 @@ for (auto Ns : Namespaces) OS << "namespace " << Ns << " {\n"; - for (const auto &D : Directives) { + for (const auto &D : DirLang.getDirectives()) { Directive Dir{D}; OS << "\n"; @@ -470,15 +459,15 @@ // Generate a map of directive (key) with DirectiveClauses struct as values. // The struct holds the 4 sets of enumeration for the 4 kinds of clauses // allowances (allowed, allowed once, allowed exclusive and required). -void GenerateDirectiveClauseMap(const std::vector &Directives, - raw_ostream &OS, DirectiveLanguage &DirLang) { +void GenerateDirectiveClauseMap(const DirectiveLanguage &DirLang, + raw_ostream &OS) { IfDefScope Scope("GEN_FLANG_DIRECTIVE_CLAUSE_MAP", OS); OS << "\n"; OS << "{\n"; - for (const auto &D : Directives) { + for (const auto &D : DirLang.getDirectives()) { Directive Dir{D}; OS << " {llvm::" << DirLang.getCppNamespace() << "::Directive::" << DirLang.getDirectivePrefix() @@ -505,14 +494,14 @@ // If the clause does not hold a value, an EMPTY_CLASS is used. // If the clause class is generic then a WRAPPER_CLASS is used. When the value // is optional, the value class is wrapped into a std::optional. -void GenerateFlangClauseParserClass(const std::vector &Clauses, +void GenerateFlangClauseParserClass(const DirectiveLanguage &DirLang, raw_ostream &OS) { IfDefScope Scope("GEN_FLANG_CLAUSE_PARSER_CLASSES", OS); OS << "\n"; - for (const auto &C : Clauses) { + for (const auto &C : DirLang.getClauses()) { Clause Clause{C}; // Clause has a non generic class. if (!Clause.getFlangClass().empty()) @@ -537,13 +526,13 @@ } // Generate a list of the different clause classes for Flang. -void GenerateFlangClauseParserClassList(const std::vector &Clauses, +void GenerateFlangClauseParserClassList(const DirectiveLanguage &DirLang, raw_ostream &OS) { IfDefScope Scope("GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST", OS); OS << "\n"; - llvm::interleaveComma(Clauses, OS, [&](Record *C) { + llvm::interleaveComma(DirLang.getClauses(), OS, [&](Record *C) { Clause Clause{C}; if (Clause.getFlangClass().empty()) OS << Clause.getFormattedParserClassName() << "\n"; @@ -553,14 +542,13 @@ } // Generate dump node list for the clauses holding a generic class name. -void GenerateFlangClauseDump(const std::vector &Clauses, - const DirectiveLanguage &DirLang, +void GenerateFlangClauseDump(const DirectiveLanguage &DirLang, raw_ostream &OS) { IfDefScope Scope("GEN_FLANG_DUMP_PARSE_TREE_CLAUSES", OS); OS << "\n"; - for (const auto &C : Clauses) { + for (const auto &C : DirLang.getClauses()) { Clause Clause{C}; // Clause has a non generic class. if (!Clause.getFlangClass().empty()) @@ -573,15 +561,14 @@ // Generate Unparse functions for clauses classes in the Flang parse-tree // If the clause is a non-generic class, no entry is generated. -void GenerateFlangClauseUnparse(const std::vector &Clauses, - const DirectiveLanguage &DirLang, +void GenerateFlangClauseUnparse(const DirectiveLanguage &DirLang, raw_ostream &OS) { IfDefScope Scope("GEN_FLANG_CLAUSE_UNPARSE", OS); OS << "\n"; - for (const auto &C : Clauses) { + for (const auto &C : DirLang.getClauses()) { Clause Clause{C}; // Clause has a non generic class. if (!Clause.getFlangClass().empty()) @@ -630,51 +617,39 @@ // Generate the implemenation section for the enumeration in the directive // language -void EmitDirectivesFlangImpl(const std::vector &Directives, - const std::vector &Clauses, - raw_ostream &OS, - DirectiveLanguage &DirectiveLanguage) { +void EmitDirectivesFlangImpl(const DirectiveLanguage &DirLang, + raw_ostream &OS) { - GenerateDirectiveClauseSets(Directives, OS, DirectiveLanguage); + GenerateDirectiveClauseSets(DirLang, OS); - GenerateDirectiveClauseMap(Directives, OS, DirectiveLanguage); + GenerateDirectiveClauseMap(DirLang, OS); - GenerateFlangClauseParserClass(Clauses, OS); + GenerateFlangClauseParserClass(DirLang, OS); - GenerateFlangClauseParserClassList(Clauses, OS); + GenerateFlangClauseParserClassList(DirLang, OS); - GenerateFlangClauseDump(Clauses, DirectiveLanguage, OS); + GenerateFlangClauseDump(DirLang, OS); - GenerateFlangClauseUnparse(Clauses, DirectiveLanguage, OS); + GenerateFlangClauseUnparse(DirLang, OS); } // Generate the implemenation section for the enumeration in the directive // language. void EmitDirectivesGen(RecordKeeper &Records, raw_ostream &OS) { - if (CheckRecordsValidity(Records)) + const auto DirLang = DirectiveLanguage{Records}; + if (DirLang.CheckRecordsValidity()) return; - const auto &DirectiveLanguages = - Records.getAllDerivedDefinitions("DirectiveLanguage"); - const auto &Directives = Records.getAllDerivedDefinitions("Directive"); - const auto &Clauses = Records.getAllDerivedDefinitions("Clause"); - DirectiveLanguage DirectiveLanguage{DirectiveLanguages[0]}; - EmitDirectivesFlangImpl(Directives, Clauses, OS, DirectiveLanguage); + EmitDirectivesFlangImpl(DirLang, OS); } // Generate the implemenation for the enumeration in the directive // language. This code can be included in library. void EmitDirectivesImpl(RecordKeeper &Records, raw_ostream &OS) { - if (CheckRecordsValidity(Records)) + const auto DirLang = DirectiveLanguage{Records}; + if (DirLang.CheckRecordsValidity()) return; - const auto &DirectiveLanguages = - Records.getAllDerivedDefinitions("DirectiveLanguage"); - const auto &Directives = Records.getAllDerivedDefinitions("Directive"); - DirectiveLanguage DirLang = DirectiveLanguage{DirectiveLanguages[0]}; - - const auto &Clauses = Records.getAllDerivedDefinitions("Clause"); - if (!DirLang.getIncludeHeader().empty()) OS << "#include \"" << DirLang.getIncludeHeader() << "\"\n\n"; @@ -689,25 +664,27 @@ OS << "using namespace " << Ns << ";\n"; // getDirectiveKind(StringRef Str) - GenerateGetKind(Directives, OS, "Directive", DirLang, + GenerateGetKind(DirLang.getDirectives(), OS, "Directive", DirLang, DirLang.getDirectivePrefix(), /*ImplicitAsUnknown=*/false); // getDirectiveName(Directive Kind) - GenerateGetName(Directives, OS, "Directive", DirLang, + GenerateGetName(DirLang.getDirectives(), OS, "Directive", DirLang, DirLang.getDirectivePrefix()); // getClauseKind(StringRef Str) - GenerateGetKind(Clauses, OS, "Clause", DirLang, DirLang.getClausePrefix(), + GenerateGetKind(DirLang.getClauses(), OS, "Clause", DirLang, + DirLang.getClausePrefix(), /*ImplicitAsUnknown=*/true); // getClauseName(Clause Kind) - GenerateGetName(Clauses, OS, "Clause", DirLang, DirLang.getClausePrefix()); + GenerateGetName(DirLang.getClauses(), OS, "Clause", DirLang, + DirLang.getClausePrefix()); // getKind(StringRef Str) - GenerateGetKindClauseVal(Clauses, OS, DirLang.getCppNamespace()); + GenerateGetKindClauseVal(DirLang, OS); // isAllowedClauseForDirective(Directive D, Clause C, unsigned Version) - GenerateIsAllowedClause(Directives, OS, DirLang); + GenerateIsAllowedClause(DirLang, OS); } } // namespace llvm