Skip to content

Commit 3f343bb

Browse files
committed
[NFC][TableGen] Migrate IfDef/Namespace emitter from MLIR to LLVM
Migrate IfDef and Namespace emitters from MLIR to LLVM TableGen. Introduce a `DialectNamespaceEmitter` for MLIR specific use, and do a minimal adoption these emitters in LLVM TableGen. Eliminate duplicated version of IfDef emitter in DirectiveEmitter.
1 parent 9345b59 commit 3f343bb

File tree

11 files changed

+124
-115
lines changed

11 files changed

+124
-115
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//===----------------------------------------------------------------------===//
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+
// This file defines common utilities for generating C++ code.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef LLVM_TABLEGEN_CODEGENHELPERS_H
14+
#define LLVM_TABLEGEN_CODEGENHELPERS_H
15+
16+
#include "llvm/ADT/STLExtras.h"
17+
#include "llvm/ADT/StringExtras.h"
18+
#include "llvm/ADT/StringRef.h"
19+
#include "llvm/Support/raw_ostream.h"
20+
#include <string>
21+
22+
namespace llvm {
23+
// Simple RAII helper for emitting ifdef-undef-endif scope.
24+
class IfDefEmitter {
25+
public:
26+
IfDefEmitter(raw_ostream &OS, StringRef Name) : Name(Name.str()), OS(OS) {
27+
OS << "#ifdef " << Name << "\n"
28+
<< "#undef " << Name << "\n\n";
29+
}
30+
~IfDefEmitter() { OS << "\n#endif // " << Name << "\n\n"; }
31+
32+
private:
33+
std::string Name;
34+
raw_ostream &OS;
35+
};
36+
37+
// Simple RAII helper for emitting namespace scope. Name can be a single
38+
// namespace (empty for anonymous namespace) or nested namespace.
39+
class NamespaceEmitter {
40+
public:
41+
NamespaceEmitter(raw_ostream &OS, StringRef Name) : OS(OS) {
42+
emitNamespaceStarts(Name);
43+
}
44+
45+
~NamespaceEmitter() {
46+
for (StringRef NS : llvm::reverse(Namespaces))
47+
OS << "} // namespace " << NS << "\n";
48+
}
49+
50+
private:
51+
void emitNamespaceStarts(StringRef Name) {
52+
llvm::SplitString(Name, Namespaces, "::");
53+
for (StringRef NS : Namespaces)
54+
OS << "namespace " << NS << " {\n";
55+
}
56+
57+
SmallVector<StringRef, 2> Namespaces;
58+
raw_ostream &OS;
59+
};
60+
61+
} // end namespace llvm
62+
63+
#endif // LLVM_TABLEGEN_CODEGENHELPERS_H

llvm/utils/TableGen/Basic/DirectiveEmitter.cpp

Lines changed: 14 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
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"
@@ -29,27 +30,11 @@
2930

3031
using 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-
4933
namespace {
5034
enum 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.
6650
static std::string getQualifier(const DirectiveLanguage &DirLang,
@@ -971,11 +955,10 @@ static void generateDirectiveClauseSets(const DirectiveLanguage &DirLang,
971955
std::string IfDefName{"GEN_"};
972956
IfDefName += getFESpelling(FE).upper();
973957
IfDefName += "_DIRECTIVE_CLAUSE_SETS";
974-
IfDefScope Scope(IfDefName, OS);
958+
IfDefEmitter Scope(OS, IfDefName);
975959

976960
StringRef Namespace =
977961
getFESpelling(FE == Frontend::Flang ? Frontend::LLVM : FE);
978-
OS << "\n";
979962
// The namespace has to be different for clang vs flang, as 2 structs with the
980963
// same name but different layout is UB. So just put the 'clang' on in the
981964
// clang namespace.
@@ -1016,9 +999,8 @@ static void generateDirectiveClauseMap(const DirectiveLanguage &DirLang,
1016999
std::string IfDefName{"GEN_"};
10171000
IfDefName += getFESpelling(FE).upper();
10181001
IfDefName += "_DIRECTIVE_CLAUSE_MAP";
1019-
IfDefScope Scope(IfDefName, OS);
1002+
IfDefEmitter Scope(OS, IfDefName);
10201003

1021-
OS << "\n";
10221004
OS << "{\n";
10231005

10241006
// The namespace has to be different for clang vs flang, as 2 structs with the
@@ -1062,9 +1044,7 @@ static void generateDirectiveClauseMap(const DirectiveLanguage &DirLang,
10621044
static void generateFlangClauseParserClass(const DirectiveLanguage &DirLang,
10631045
raw_ostream &OS) {
10641046

1065-
IfDefScope Scope("GEN_FLANG_CLAUSE_PARSER_CLASSES", OS);
1066-
1067-
OS << "\n";
1047+
IfDefEmitter Scope(OS, "GEN_FLANG_CLAUSE_PARSER_CLASSES");
10681048

10691049
for (const Clause Clause : DirLang.getClauses()) {
10701050
if (!Clause.getFlangClass().empty()) {
@@ -1089,9 +1069,8 @@ static void generateFlangClauseParserClass(const DirectiveLanguage &DirLang,
10891069
static void generateFlangClauseParserClassList(const DirectiveLanguage &DirLang,
10901070
raw_ostream &OS) {
10911071

1092-
IfDefScope Scope("GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST", OS);
1072+
IfDefEmitter Scope(OS, "GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST");
10931073

1094-
OS << "\n";
10951074
interleaveComma(DirLang.getClauses(), OS, [&](const Record *C) {
10961075
Clause Clause(C);
10971076
OS << Clause.getFormattedParserClassName() << "\n";
@@ -1102,9 +1081,8 @@ static void generateFlangClauseParserClassList(const DirectiveLanguage &DirLang,
11021081
static void generateFlangClauseDump(const DirectiveLanguage &DirLang,
11031082
raw_ostream &OS) {
11041083

1105-
IfDefScope Scope("GEN_FLANG_DUMP_PARSE_TREE_CLAUSES", OS);
1084+
IfDefEmitter Scope(OS, "GEN_FLANG_DUMP_PARSE_TREE_CLAUSES");
11061085

1107-
OS << "\n";
11081086
for (const Clause Clause : DirLang.getClauses()) {
11091087
OS << "NODE(" << DirLang.getFlangClauseBaseClass() << ", "
11101088
<< Clause.getFormattedParserClassName() << ")\n";
@@ -1116,10 +1094,9 @@ static void generateFlangClauseDump(const DirectiveLanguage &DirLang,
11161094
static void generateFlangClauseUnparse(const DirectiveLanguage &DirLang,
11171095
raw_ostream &OS) {
11181096

1119-
IfDefScope Scope("GEN_FLANG_CLAUSE_UNPARSE", OS);
1097+
IfDefEmitter Scope(OS, "GEN_FLANG_CLAUSE_UNPARSE");
11201098

11211099
StringRef Base = DirLang.getFlangClauseBaseClass();
1122-
OS << "\n";
11231100

11241101
for (const Clause Clause : DirLang.getClauses()) {
11251102
if (Clause.skipFlangUnparser())
@@ -1172,9 +1149,8 @@ static void generateFlangClauseUnparse(const DirectiveLanguage &DirLang,
11721149
static void generateFlangClauseCheckPrototypes(const DirectiveLanguage &DirLang,
11731150
raw_ostream &OS) {
11741151

1175-
IfDefScope Scope("GEN_FLANG_CLAUSE_CHECK_ENTER", OS);
1152+
IfDefEmitter Scope(OS, "GEN_FLANG_CLAUSE_CHECK_ENTER");
11761153

1177-
OS << "\n";
11781154
for (const Clause Clause : DirLang.getClauses()) {
11791155
OS << "void Enter(const parser::" << DirLang.getFlangClauseBaseClass()
11801156
<< "::" << Clause.getFormattedParserClassName() << " &);\n";
@@ -1186,12 +1162,11 @@ static void generateFlangClauseCheckPrototypes(const DirectiveLanguage &DirLang,
11861162
static void generateFlangClauseParserKindMap(const DirectiveLanguage &DirLang,
11871163
raw_ostream &OS) {
11881164

1189-
IfDefScope Scope("GEN_FLANG_CLAUSE_PARSER_KIND_MAP", OS);
1165+
IfDefEmitter Scope(OS, "GEN_FLANG_CLAUSE_PARSER_KIND_MAP");
11901166

11911167
StringRef Prefix = DirLang.getClausePrefix();
11921168
std::string Qual = getQualifier(DirLang);
11931169

1194-
OS << "\n";
11951170
for (const Record *R : DirLang.getClauses()) {
11961171
Clause C(R);
11971172
OS << "if constexpr (std::is_same_v<A, parser::"
@@ -1216,11 +1191,10 @@ static void generateFlangClausesParser(const DirectiveLanguage &DirLang,
12161191
llvm::sort(Names, [](const auto &A, const auto &B) {
12171192
return A.second.Name > B.second.Name;
12181193
});
1219-
IfDefScope Scope("GEN_FLANG_CLAUSES_PARSER", OS);
1194+
IfDefEmitter Scope(OS, "GEN_FLANG_CLAUSES_PARSER");
12201195
StringRef Base = DirLang.getFlangClauseBaseClass();
12211196

12221197
unsigned LastIndex = Names.size() - 1;
1223-
OS << "\n";
12241198
OS << "TYPE_PARSER(\n";
12251199
for (auto [Index, RecSp] : llvm::enumerate(Names)) {
12261200
auto [R, S] = RecSp;
@@ -1313,10 +1287,9 @@ static void emitDirectivesFlangImpl(const DirectiveLanguage &DirLang,
13131287
static void generateClauseClassMacro(const DirectiveLanguage &DirLang,
13141288
raw_ostream &OS) {
13151289
// Generate macros style information for legacy code in clang
1316-
IfDefScope Scope("GEN_CLANG_CLAUSE_CLASS", OS);
1290+
IfDefEmitter Scope(OS, "GEN_CLANG_CLAUSE_CLASS");
13171291

13181292
StringRef Prefix = DirLang.getClausePrefix();
1319-
OS << "\n";
13201293

13211294
OS << "#ifndef CLAUSE\n";
13221295
OS << "#define CLAUSE(Enum, Str, Implicit)\n";
@@ -1375,12 +1348,11 @@ static void generateClauseClassMacro(const DirectiveLanguage &DirLang,
13751348
// language. This code can be included in library.
13761349
void emitDirectivesBasicImpl(const DirectiveLanguage &DirLang,
13771350
raw_ostream &OS) {
1378-
IfDefScope Scope("GEN_DIRECTIVES_IMPL", OS);
1351+
IfDefEmitter Scope(OS, "GEN_DIRECTIVES_IMPL");
13791352

13801353
StringRef DPrefix = DirLang.getDirectivePrefix();
13811354
StringRef CPrefix = DirLang.getClausePrefix();
13821355

1383-
OS << "\n";
13841356
OS << "#include \"llvm/Frontend/Directive/Spelling.h\"\n";
13851357
OS << "#include \"llvm/Support/ErrorHandling.h\"\n";
13861358
OS << "#include <utility>\n";

llvm/utils/TableGen/Basic/TargetFeaturesEmitter.cpp

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
//===----------------------------------------------------------------------===//
1313

1414
#include "TargetFeaturesEmitter.h"
15+
#include "llvm/TableGen/CodeGenHelpers.h"
1516
#include "llvm/TableGen/Error.h"
1617
#include "llvm/TableGen/TableGenBackend.h"
1718
#include "llvm/TargetParser/SubtargetFeature.h"
@@ -43,7 +44,7 @@ FeatureMapTy TargetFeaturesEmitter::enumeration(raw_ostream &OS) {
4344
PrintFatalError(
4445
"Too many subtarget features! Bump MAX_SUBTARGET_FEATURES.");
4546

46-
OS << "namespace " << Target << " {\n";
47+
NamespaceEmitter NS(OS, Target);
4748

4849
OS << "enum {\n";
4950

@@ -58,9 +59,8 @@ FeatureMapTy TargetFeaturesEmitter::enumeration(raw_ostream &OS) {
5859

5960
OS << " " << "NumSubtargetFeatures = " << N << "\n";
6061

61-
// Close enumeration and namespace
62+
// Close enumeration.
6263
OS << "};\n";
63-
OS << "} // end namespace " << Target << "\n";
6464
return FeatureMap;
6565
}
6666

@@ -149,25 +149,23 @@ void TargetFeaturesEmitter::printCPUKeyValues(raw_ostream &OS,
149149
void TargetFeaturesEmitter::run(raw_ostream &OS) {
150150
OS << "// Autogenerated by TargetFeatureEmitter.cpp\n\n";
151151

152-
OS << "\n#ifdef GET_SUBTARGETFEATURES_ENUM\n";
153-
OS << "#undef GET_SUBTARGETFEATURES_ENUM\n\n";
154-
155-
OS << "namespace llvm {\n";
156-
auto FeatureMap = enumeration(OS);
157-
OS << "} // end namespace llvm\n\n";
158-
OS << "#endif // GET_SUBTARGETFEATURES_ENUM\n\n";
152+
FeatureMapTy FeatureMap;
153+
{
154+
IfDefEmitter IfDef(OS, "GET_SUBTARGETFEATURES_ENUM");
155+
NamespaceEmitter NS(OS, "llvm");
156+
FeatureMap = enumeration(OS);
157+
}
159158

160-
OS << "\n#ifdef GET_SUBTARGETFEATURES_KV\n";
161-
OS << "#undef GET_SUBTARGETFEATURES_KV\n\n";
159+
{
160+
IfDefEmitter IfDef(OS, "GET_SUBTARGETFEATURES_KV");
161+
NamespaceEmitter NS(OS, "llvm");
162162

163-
OS << "namespace llvm {\n";
164-
printFeatureKeyValues(OS, FeatureMap);
165-
OS << "\n";
163+
printFeatureKeyValues(OS, FeatureMap);
164+
OS << "\n";
166165

167-
printCPUKeyValues(OS, FeatureMap);
168-
OS << "\n";
169-
OS << "} // end namespace llvm\n\n";
170-
OS << "#endif // GET_SUBTARGETFEATURES_KV\n\n";
166+
printCPUKeyValues(OS, FeatureMap);
167+
OS << "\n";
168+
}
171169
}
172170

173171
static TableGen::Emitter::OptClass<TargetFeaturesEmitter>

mlir/include/mlir/TableGen/CodeGenHelpers.h

Lines changed: 8 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
//===----------------------------------------------------------------------===//
12
//
23
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
34
// See https://llvm.org/LICENSE.txt for license information.
@@ -20,6 +21,8 @@
2021
#include "llvm/ADT/MapVector.h"
2122
#include "llvm/ADT/StringExtras.h"
2223
#include "llvm/ADT/StringRef.h"
24+
#include "llvm/TableGen/CodeGenHelpers.h"
25+
#include <utility>
2326

2427
namespace llvm {
2528
class RecordKeeper;
@@ -36,46 +39,17 @@ std::string strfmt(const char *fmt, Parameters &&...parameters) {
3639
return llvm::formatv(fmt, std::forward<Parameters>(parameters)...).str();
3740
}
3841

39-
// Simple RAII helper for defining ifdef-undef-endif scopes.
40-
class IfDefScope {
41-
public:
42-
IfDefScope(llvm::StringRef name, llvm::raw_ostream &os)
43-
: name(name.str()), os(os) {
44-
os << "#ifdef " << name << "\n"
45-
<< "#undef " << name << "\n\n";
46-
}
47-
~IfDefScope() { os << "\n#endif // " << name << "\n\n"; }
48-
49-
private:
50-
std::string name;
51-
llvm::raw_ostream &os;
52-
};
53-
54-
// A helper RAII class to emit nested namespaces for this op.
55-
class NamespaceEmitter {
42+
// A helper RAII class to emit nested namespaces for a dialect.
43+
class DialectNamespaceEmitter {
5644
public:
57-
NamespaceEmitter(raw_ostream &os, const Dialect &dialect) : os(os) {
45+
DialectNamespaceEmitter(raw_ostream &os, const Dialect &dialect) {
5846
if (!dialect)
5947
return;
60-
emitNamespaceStarts(os, dialect.getCppNamespace());
61-
}
62-
NamespaceEmitter(raw_ostream &os, StringRef cppNamespace) : os(os) {
63-
emitNamespaceStarts(os, cppNamespace);
64-
}
65-
66-
~NamespaceEmitter() {
67-
for (StringRef ns : llvm::reverse(namespaces))
68-
os << "} // namespace " << ns << "\n";
48+
nsEmitter.emplace(os, dialect.getCppNamespace());
6949
}
7050

7151
private:
72-
void emitNamespaceStarts(raw_ostream &os, StringRef cppNamespace) {
73-
llvm::SplitString(cppNamespace, namespaces, "::");
74-
for (StringRef ns : namespaces)
75-
os << "namespace " << ns << " {\n";
76-
}
77-
raw_ostream &os;
78-
SmallVector<StringRef, 2> namespaces;
52+
std::optional<llvm::NamespaceEmitter> nsEmitter;
7953
};
8054

8155
/// This class deduplicates shared operation verification code by emitting

mlir/include/mlir/TableGen/Dialect.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ class Dialect {
107107

108108
// Returns whether the dialect is defined.
109109
explicit operator bool() const { return def != nullptr; }
110+
bool isDefined() const { return def != nullptr; }
110111

111112
private:
112113
const llvm::Record *def;

mlir/lib/TableGen/CodeGenHelpers.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "mlir/TableGen/Pattern.h"
1717
#include "llvm/Support/FormatVariadic.h"
1818
#include "llvm/Support/Path.h"
19+
#include "llvm/TableGen/CodeGenHelpers.h"
1920
#include "llvm/TableGen/Record.h"
2021

2122
using namespace llvm;

0 commit comments

Comments
 (0)