1919#include " llvm/ADT/SmallVector.h"
2020#include " llvm/ADT/StringSet.h"
2121#include " llvm/ADT/StringSwitch.h"
22+ #include " llvm/TableGen/CodeGenHelpers.h"
2223#include " llvm/TableGen/Error.h"
2324#include " llvm/TableGen/Record.h"
2425#include " llvm/TableGen/TableGenBackend.h"
2930
3031using namespace llvm ;
3132
32- namespace {
33- // Simple RAII helper for defining ifdef-undef-endif scopes.
34- class IfDefScope {
35- public:
36- IfDefScope (StringRef Name, raw_ostream &OS) : Name(Name), OS(OS) {
37- OS << " #ifdef " << Name << " \n "
38- << " #undef " << Name << " \n " ;
39- }
40-
41- ~IfDefScope () { OS << " \n #endif // " << Name << " \n\n " ; }
42-
43- private:
44- StringRef Name;
45- raw_ostream &OS;
46- };
47- } // namespace
48-
4933namespace {
5034enum class Frontend { LLVM, Flang, Clang };
35+ } // namespace
5136
52- StringRef getFESpelling (Frontend FE) {
37+ static StringRef getFESpelling (Frontend FE) {
5338 switch (FE) {
5439 case Frontend::LLVM:
5540 return " llvm" ;
@@ -60,7 +45,6 @@ StringRef getFESpelling(Frontend FE) {
6045 }
6146 llvm_unreachable (" unknown FE kind" );
6247}
63- } // namespace
6448
6549// Get the full namespace qualifier for the directive language.
6650static std::string getQualifier (const DirectiveLanguage &DirLang,
@@ -297,13 +281,8 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
297281 OS << " #include <cstddef>\n " ; // for size_t
298282 OS << " #include <utility>\n " ; // for std::pair
299283 OS << " \n " ;
300- OS << " namespace llvm {\n " ;
301-
302- // Open namespaces defined in the directive language
303- SmallVector<StringRef, 2 > Namespaces;
304- SplitString (DirLang.getCppNamespace (), Namespaces, " ::" );
305- for (auto Ns : Namespaces)
306- OS << " namespace " << Ns << " {\n " ;
284+ NamespaceEmitter LlvmNS (OS, " llvm" );
285+ NamespaceEmitter DirLangNS (OS, DirLang.getCppNamespace ());
307286
308287 if (DirLang.hasEnableBitmaskEnumInNamespace ())
309288 OS << " \n LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();\n " ;
@@ -380,9 +359,7 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
380359 OS << " \n " ;
381360 }
382361
383- // Closing namespaces
384- for (auto Ns : reverse (Namespaces))
385- OS << " } // namespace " << Ns << " \n " ;
362+ DirLangNS.close ();
386363
387364 // These specializations need to be in ::llvm.
388365 for (StringRef Enum : {" Association" , " Category" , " Directive" , " Clause" }) {
@@ -392,9 +369,7 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
392369 OS << " static constexpr bool is_iterable = true;\n " ;
393370 OS << " };\n " ;
394371 }
395-
396- OS << " } // namespace llvm\n " ;
397-
372+ LlvmNS.close ();
398373 OS << " #endif // LLVM_" << Lang << " _INC\n " ;
399374}
400375
@@ -971,11 +946,10 @@ static void generateDirectiveClauseSets(const DirectiveLanguage &DirLang,
971946 std::string IfDefName{" GEN_" };
972947 IfDefName += getFESpelling (FE).upper ();
973948 IfDefName += " _DIRECTIVE_CLAUSE_SETS" ;
974- IfDefScope Scope (IfDefName, OS );
949+ IfDefEmitter Scope (OS, IfDefName );
975950
976951 StringRef Namespace =
977952 getFESpelling (FE == Frontend::Flang ? Frontend::LLVM : FE);
978- OS << " \n " ;
979953 // The namespace has to be different for clang vs flang, as 2 structs with the
980954 // same name but different layout is UB. So just put the 'clang' on in the
981955 // clang namespace.
@@ -1016,9 +990,8 @@ static void generateDirectiveClauseMap(const DirectiveLanguage &DirLang,
1016990 std::string IfDefName{" GEN_" };
1017991 IfDefName += getFESpelling (FE).upper ();
1018992 IfDefName += " _DIRECTIVE_CLAUSE_MAP" ;
1019- IfDefScope Scope (IfDefName, OS );
993+ IfDefEmitter Scope (OS, IfDefName );
1020994
1021- OS << " \n " ;
1022995 OS << " {\n " ;
1023996
1024997 // The namespace has to be different for clang vs flang, as 2 structs with the
@@ -1062,9 +1035,7 @@ static void generateDirectiveClauseMap(const DirectiveLanguage &DirLang,
10621035static void generateFlangClauseParserClass (const DirectiveLanguage &DirLang,
10631036 raw_ostream &OS) {
10641037
1065- IfDefScope Scope (" GEN_FLANG_CLAUSE_PARSER_CLASSES" , OS);
1066-
1067- OS << " \n " ;
1038+ IfDefEmitter Scope (OS, " GEN_FLANG_CLAUSE_PARSER_CLASSES" );
10681039
10691040 for (const Clause Clause : DirLang.getClauses ()) {
10701041 if (!Clause.getFlangClass ().empty ()) {
@@ -1089,9 +1060,8 @@ static void generateFlangClauseParserClass(const DirectiveLanguage &DirLang,
10891060static void generateFlangClauseParserClassList (const DirectiveLanguage &DirLang,
10901061 raw_ostream &OS) {
10911062
1092- IfDefScope Scope (" GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST" , OS );
1063+ IfDefEmitter Scope (OS, " GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST" );
10931064
1094- OS << " \n " ;
10951065 interleaveComma (DirLang.getClauses (), OS, [&](const Record *C) {
10961066 Clause Clause (C);
10971067 OS << Clause.getFormattedParserClassName () << " \n " ;
@@ -1102,9 +1072,8 @@ static void generateFlangClauseParserClassList(const DirectiveLanguage &DirLang,
11021072static void generateFlangClauseDump (const DirectiveLanguage &DirLang,
11031073 raw_ostream &OS) {
11041074
1105- IfDefScope Scope (" GEN_FLANG_DUMP_PARSE_TREE_CLAUSES" , OS );
1075+ IfDefEmitter Scope (OS, " GEN_FLANG_DUMP_PARSE_TREE_CLAUSES" );
11061076
1107- OS << " \n " ;
11081077 for (const Clause Clause : DirLang.getClauses ()) {
11091078 OS << " NODE(" << DirLang.getFlangClauseBaseClass () << " , "
11101079 << Clause.getFormattedParserClassName () << " )\n " ;
@@ -1116,10 +1085,9 @@ static void generateFlangClauseDump(const DirectiveLanguage &DirLang,
11161085static void generateFlangClauseUnparse (const DirectiveLanguage &DirLang,
11171086 raw_ostream &OS) {
11181087
1119- IfDefScope Scope (" GEN_FLANG_CLAUSE_UNPARSE" , OS );
1088+ IfDefEmitter Scope (OS, " GEN_FLANG_CLAUSE_UNPARSE" );
11201089
11211090 StringRef Base = DirLang.getFlangClauseBaseClass ();
1122- OS << " \n " ;
11231091
11241092 for (const Clause Clause : DirLang.getClauses ()) {
11251093 if (Clause.skipFlangUnparser ())
@@ -1172,9 +1140,8 @@ static void generateFlangClauseUnparse(const DirectiveLanguage &DirLang,
11721140static void generateFlangClauseCheckPrototypes (const DirectiveLanguage &DirLang,
11731141 raw_ostream &OS) {
11741142
1175- IfDefScope Scope (" GEN_FLANG_CLAUSE_CHECK_ENTER" , OS );
1143+ IfDefEmitter Scope (OS, " GEN_FLANG_CLAUSE_CHECK_ENTER" );
11761144
1177- OS << " \n " ;
11781145 for (const Clause Clause : DirLang.getClauses ()) {
11791146 OS << " void Enter(const parser::" << DirLang.getFlangClauseBaseClass ()
11801147 << " ::" << Clause.getFormattedParserClassName () << " &);\n " ;
@@ -1186,12 +1153,11 @@ static void generateFlangClauseCheckPrototypes(const DirectiveLanguage &DirLang,
11861153static void generateFlangClauseParserKindMap (const DirectiveLanguage &DirLang,
11871154 raw_ostream &OS) {
11881155
1189- IfDefScope Scope (" GEN_FLANG_CLAUSE_PARSER_KIND_MAP" , OS );
1156+ IfDefEmitter Scope (OS, " GEN_FLANG_CLAUSE_PARSER_KIND_MAP" );
11901157
11911158 StringRef Prefix = DirLang.getClausePrefix ();
11921159 std::string Qual = getQualifier (DirLang);
11931160
1194- OS << " \n " ;
11951161 for (const Record *R : DirLang.getClauses ()) {
11961162 Clause C (R);
11971163 OS << " if constexpr (std::is_same_v<A, parser::"
@@ -1216,11 +1182,10 @@ static void generateFlangClausesParser(const DirectiveLanguage &DirLang,
12161182 llvm::sort (Names, [](const auto &A, const auto &B) {
12171183 return A.second .Name > B.second .Name ;
12181184 });
1219- IfDefScope Scope (" GEN_FLANG_CLAUSES_PARSER" , OS );
1185+ IfDefEmitter Scope (OS, " GEN_FLANG_CLAUSES_PARSER" );
12201186 StringRef Base = DirLang.getFlangClauseBaseClass ();
12211187
12221188 unsigned LastIndex = Names.size () - 1 ;
1223- OS << " \n " ;
12241189 OS << " TYPE_PARSER(\n " ;
12251190 for (auto [Index, RecSp] : llvm::enumerate (Names)) {
12261191 auto [R, S] = RecSp;
@@ -1313,10 +1278,9 @@ static void emitDirectivesFlangImpl(const DirectiveLanguage &DirLang,
13131278static void generateClauseClassMacro (const DirectiveLanguage &DirLang,
13141279 raw_ostream &OS) {
13151280 // Generate macros style information for legacy code in clang
1316- IfDefScope Scope (" GEN_CLANG_CLAUSE_CLASS" , OS );
1281+ IfDefEmitter Scope (OS, " GEN_CLANG_CLAUSE_CLASS" );
13171282
13181283 StringRef Prefix = DirLang.getClausePrefix ();
1319- OS << " \n " ;
13201284
13211285 OS << " #ifndef CLAUSE\n " ;
13221286 OS << " #define CLAUSE(Enum, Str, Implicit)\n " ;
@@ -1375,12 +1339,11 @@ static void generateClauseClassMacro(const DirectiveLanguage &DirLang,
13751339// language. This code can be included in library.
13761340void emitDirectivesBasicImpl (const DirectiveLanguage &DirLang,
13771341 raw_ostream &OS) {
1378- IfDefScope Scope (" GEN_DIRECTIVES_IMPL" , OS );
1342+ IfDefEmitter Scope (OS, " GEN_DIRECTIVES_IMPL" );
13791343
13801344 StringRef DPrefix = DirLang.getDirectivePrefix ();
13811345 StringRef CPrefix = DirLang.getClausePrefix ();
13821346
1383- OS << " \n " ;
13841347 OS << " #include \" llvm/Frontend/Directive/Spelling.h\"\n " ;
13851348 OS << " #include \" llvm/Support/ErrorHandling.h\"\n " ;
13861349 OS << " #include <utility>\n " ;
0 commit comments