[llvm] [utils][TableGen] Clean up code in DirectiveEmitter (PR #140772)
via llvm-commits
llvm-commits at lists.llvm.org
Tue May 20 10:57:06 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-tablegen
Author: Krzysztof Parzyszek (kparzysz)
<details>
<summary>Changes</summary>
Remove most redundant function calls. Unify enum identifier name generation (via getIdentifierName), and namespace qualification (via getQualifier).
---
Patch is 40.21 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/140772.diff
2 Files Affected:
- (modified) llvm/include/llvm/TableGen/DirectiveEmitter.h (+6-3)
- (modified) llvm/utils/TableGen/Basic/DirectiveEmitter.cpp (+229-226)
``````````diff
diff --git a/llvm/include/llvm/TableGen/DirectiveEmitter.h b/llvm/include/llvm/TableGen/DirectiveEmitter.h
index 234979eebc881..6defc8722d810 100644
--- a/llvm/include/llvm/TableGen/DirectiveEmitter.h
+++ b/llvm/include/llvm/TableGen/DirectiveEmitter.h
@@ -113,20 +113,23 @@ class BaseRecord {
// Returns the name of the directive formatted for output. Whitespace are
// replaced with underscores.
- static std::string getFormattedName(const Record *R) {
- StringRef Name = R->getValueAsString("name");
+ static std::string formatName(StringRef Name) {
std::string N = Name.str();
llvm::replace(N, ' ', '_');
return N;
}
- std::string getFormattedName() const { return getFormattedName(Def); }
+ std::string getFormattedName() const {
+ return formatName(Def->getValueAsString("name"));
+ }
bool isDefault() const { return Def->getValueAsBit("isDefault"); }
// Returns the record name.
StringRef getRecordName() const { return Def->getName(); }
+ const Record *getRecord() const { return Def; }
+
protected:
const Record *Def;
};
diff --git a/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp b/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
index acad5fe6f2cf3..3d1795c5a6ff5 100644
--- a/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
@@ -45,17 +45,55 @@ class IfDefScope {
};
} // namespace
+namespace {
+enum class Frontend { LLVM, Flang, Clang };
+
+StringRef getFESpelling(Frontend FE) {
+ switch (FE) {
+ case Frontend::LLVM:
+ return "llvm";
+ case Frontend::Flang:
+ return "flang";
+ case Frontend::Clang:
+ return "clang";
+ }
+ llvm_unreachable("unknown FE kind");
+}
+} // namespace
+
+// Get the full namespace qualifier for the directive language.
+static std::string getQualifier(const DirectiveLanguage &DirLang,
+ Frontend FE = Frontend::LLVM) {
+ return (Twine(getFESpelling(FE)) + "::" + DirLang.getCppNamespace().str() +
+ "::")
+ .str();
+}
+
+// Get prefixed formatted name, e.g. for "target data", get "OMPD_target_data".
+// This should work for any Record as long as BaseRecord::getFormattedName
+// works.
+static std::string getIdentifierName(const Record *Rec, StringRef Prefix) {
+ return Prefix.str() + BaseRecord(Rec).getFormattedName();
+}
+
+static void generateEnumExports(ArrayRef<const Record *> Records,
+ raw_ostream &OS, StringRef Enum,
+ StringRef Prefix) {
+ for (const Record *R : Records) {
+ std::string N = getIdentifierName(R, Prefix);
+ OS << "constexpr auto " << N << " = " << Enum << "::" << N << ";\n";
+ }
+}
+
// Generate enum class. Entries are emitted in the order in which they appear
// in the `Records` vector.
static void generateEnumClass(ArrayRef<const Record *> Records, raw_ostream &OS,
StringRef Enum, StringRef Prefix,
- const DirectiveLanguage &DirLang,
bool ExportEnums) {
OS << "\n";
OS << "enum class " << Enum << " {\n";
- for (const auto &R : Records) {
- BaseRecord Rec(R);
- OS << " " << Prefix << Rec.getFormattedName() << ",\n";
+ for (const Record *R : Records) {
+ OS << " " << getIdentifierName(R, Prefix) << ",\n";
}
OS << "};\n";
OS << "\n";
@@ -69,11 +107,7 @@ static void generateEnumClass(ArrayRef<const Record *> Records, raw_ostream &OS,
// cast.
if (ExportEnums) {
OS << "\n";
- for (const auto &R : Records) {
- BaseRecord Rec(R);
- OS << "constexpr auto " << Prefix << Rec.getFormattedName() << " = "
- << Enum << "::" << Prefix << Rec.getFormattedName() << ";\n";
- }
+ generateEnumExports(Records, OS, Enum, Prefix);
}
}
@@ -82,9 +116,7 @@ static void generateEnumClass(ArrayRef<const Record *> Records, raw_ostream &OS,
// vector.
static void generateEnumBitmask(ArrayRef<const Record *> Records,
raw_ostream &OS, StringRef Enum,
- StringRef Prefix,
- const DirectiveLanguage &DirLang,
- bool ExportEnums) {
+ StringRef Prefix, bool ExportEnums) {
assert(Records.size() <= 64 && "Too many values for a bitmask");
StringRef Type = Records.size() <= 32 ? "uint32_t" : "uint64_t";
StringRef TypeSuffix = Records.size() <= 32 ? "U" : "ULL";
@@ -93,8 +125,7 @@ static void generateEnumBitmask(ArrayRef<const Record *> Records,
OS << "enum class " << Enum << " : " << Type << " {\n";
std::string LastName;
for (auto [I, R] : llvm::enumerate(Records)) {
- BaseRecord Rec(R);
- LastName = Prefix.str() + Rec.getFormattedName();
+ LastName = getIdentifierName(R, Prefix);
OS << " " << LastName << " = " << (1ull << I) << TypeSuffix << ",\n";
}
OS << " LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/" << LastName << ")\n";
@@ -110,11 +141,7 @@ static void generateEnumBitmask(ArrayRef<const Record *> Records,
// cast.
if (ExportEnums) {
OS << "\n";
- for (const auto &R : Records) {
- BaseRecord Rec(R);
- OS << "constexpr auto " << Prefix << Rec.getFormattedName() << " = "
- << Enum << "::" << Prefix << Rec.getFormattedName() << ";\n";
- }
+ generateEnumExports(Records, OS, Enum, Prefix);
}
}
@@ -124,21 +151,21 @@ static void generateEnumClauseVal(ArrayRef<const Record *> Records,
raw_ostream &OS,
const DirectiveLanguage &DirLang,
std::string &EnumHelperFuncs) {
- for (const auto &R : Records) {
+ for (const Record *R : Records) {
Clause C(R);
const auto &ClauseVals = C.getClauseVals();
if (ClauseVals.size() <= 0)
continue;
- const auto &EnumName = C.getEnumName();
- if (EnumName.empty()) {
+ StringRef Enum = C.getEnumName();
+ if (Enum.empty()) {
PrintError("enumClauseValue field not set in Clause" +
C.getFormattedName() + ".");
return;
}
OS << "\n";
- OS << "enum class " << EnumName << " {\n";
+ OS << "enum class " << Enum << " {\n";
for (const ClauseVal CVal : ClauseVals)
OS << " " << CVal.getRecordName() << "=" << CVal.getValue() << ",\n";
OS << "};\n";
@@ -146,16 +173,16 @@ static void generateEnumClauseVal(ArrayRef<const Record *> Records,
if (DirLang.hasMakeEnumAvailableInNamespace()) {
OS << "\n";
for (const auto &CV : ClauseVals) {
- OS << "constexpr auto " << CV->getName() << " = " << EnumName
+ OS << "constexpr auto " << CV->getName() << " = " << Enum
<< "::" << CV->getName() << ";\n";
}
- EnumHelperFuncs += (Twine("LLVM_ABI ") + Twine(EnumName) + Twine(" get") +
- Twine(EnumName) + Twine("(StringRef Str);\n"))
+ EnumHelperFuncs += (Twine("LLVM_ABI ") + Twine(Enum) + Twine(" get") +
+ Twine(Enum) + Twine("(StringRef Str);\n"))
.str();
EnumHelperFuncs +=
(Twine("LLVM_ABI StringRef get") + Twine(DirLang.getName()) +
- Twine(EnumName) + Twine("Name(") + Twine(EnumName) + Twine(" x);\n"))
+ Twine(Enum) + Twine("Name(") + Twine(Enum) + Twine(" x);\n"))
.str();
}
}
@@ -231,8 +258,10 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
if (DirLang.HasValidityErrors())
return;
- OS << "#ifndef LLVM_" << DirLang.getName() << "_INC\n";
- OS << "#define LLVM_" << DirLang.getName() << "_INC\n";
+ StringRef Lang = DirLang.getName();
+
+ OS << "#ifndef LLVM_" << Lang << "_INC\n";
+ OS << "#define LLVM_" << Lang << "_INC\n";
OS << "\n#include \"llvm/ADT/ArrayRef.h\"\n";
if (DirLang.hasEnableBitmaskEnumInNamespace())
@@ -259,22 +288,22 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
// Skip the "special" value
[](const Record *Def) { return Def->getName() != "AS_FromLeaves"; });
generateEnumClass(Associations, OS, "Association",
- /*Prefix=*/"", DirLang, /*ExportEnums=*/false);
+ /*Prefix=*/"", /*ExportEnums=*/false);
generateEnumClass(DirLang.getCategories(), OS, "Category", /*Prefix=*/"",
- DirLang, /*ExportEnums=*/false);
+ /*ExportEnums=*/false);
generateEnumBitmask(DirLang.getSourceLanguages(), OS, "SourceLanguage",
- /*Prefix=*/"", DirLang, /*ExportEnums=*/false);
+ /*Prefix=*/"", /*ExportEnums=*/false);
// Emit Directive enumeration
generateEnumClass(DirLang.getDirectives(), OS, "Directive",
- DirLang.getDirectivePrefix(), DirLang,
+ DirLang.getDirectivePrefix(),
DirLang.hasMakeEnumAvailableInNamespace());
// Emit Clause enumeration
generateEnumClass(DirLang.getClauses(), OS, "Clause",
- DirLang.getClausePrefix(), DirLang,
+ DirLang.getClausePrefix(),
DirLang.hasMakeEnumAvailableInNamespace());
// Emit ClauseVal enumeration
@@ -284,9 +313,9 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
// Generic function signatures
OS << "\n";
OS << "// Enumeration helper functions\n";
- OS << "LLVM_ABI Directive get" << DirLang.getName()
- << "DirectiveKind(StringRef Str);\n";
+ OS << "LLVM_ABI Directive get" << Lang << "DirectiveKind(StringRef Str);\n";
OS << "\n";
+
// For OpenMP the signature is
// getOpenMPDirectiveName(Directive D, unsigned V)
OS << "LLVM_ABI StringRef get" << DirLang.getName()
@@ -295,11 +324,10 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
OS << ", unsigned = 0";
OS << ");\n";
OS << "\n";
- OS << "LLVM_ABI Clause get" << DirLang.getName()
- << "ClauseKind(StringRef Str);\n";
+
+ OS << "LLVM_ABI Clause get" << Lang << "ClauseKind(StringRef Str);\n";
OS << "\n";
- OS << "LLVM_ABI StringRef get" << DirLang.getName()
- << "ClauseName(Clause C);\n";
+ OS << "LLVM_ABI StringRef get" << Lang << "ClauseName(Clause C);\n";
OS << "\n";
OS << "/// Return true if \\p C is a valid clause for \\p D in version \\p "
<< "Version.\n";
@@ -322,30 +350,30 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
OS << "} // namespace llvm\n";
- OS << "#endif // LLVM_" << DirLang.getName() << "_INC\n";
+ OS << "#endif // LLVM_" << Lang << "_INC\n";
}
// Generate function implementation for get<Enum>Name(StringRef Str)
static void generateGetName(ArrayRef<const Record *> Records, raw_ostream &OS,
StringRef Enum, const DirectiveLanguage &DirLang,
StringRef Prefix) {
+ StringRef Lang = DirLang.getName();
+ std::string Qual = getQualifier(DirLang);
// For OpenMP the "Directive" signature is
// getOpenMPDirectiveName(Directive D, unsigned V)
OS << "\n";
- OS << "llvm::StringRef llvm::" << DirLang.getCppNamespace() << "::get"
- << DirLang.getName() << Enum << "Name(llvm::" << DirLang.getCppNamespace()
- << "::" << Enum << " Kind";
+ OS << "llvm::StringRef " << Qual << "get" << Lang << Enum << "Name(" << Qual
+ << Enum << " Kind";
if (DirLang.getCppNamespace() == "omp" && Enum == "Directive")
OS << ", unsigned";
OS << ") {\n";
OS << " switch (Kind) {\n";
- for (const BaseRecord Rec : Records) {
- OS << " case " << Prefix << Rec.getFormattedName() << ":\n";
- OS << " return \"" << Rec.getName() << "\";\n";
+ for (const Record *R : Records) {
+ OS << " case " << getIdentifierName(R, Prefix) << ":\n";
+ OS << " return \"" << BaseRecord(R).getName() << "\";\n";
}
OS << " }\n"; // switch
- OS << " llvm_unreachable(\"Invalid " << DirLang.getName() << " " << Enum
- << " kind\");\n";
+ OS << " llvm_unreachable(\"Invalid " << Lang << " " << Enum << " kind\");\n";
OS << "}\n";
}
@@ -363,30 +391,33 @@ static void generateGetKind(ArrayRef<const Record *> Records, raw_ostream &OS,
}
BaseRecord DefaultRec(*DefaultIt);
+ std::string Qual = getQualifier(DirLang);
+ std::string DefaultName = getIdentifierName(*DefaultIt, Prefix);
OS << "\n";
- OS << "llvm::" << DirLang.getCppNamespace() << "::" << Enum
- << " llvm::" << DirLang.getCppNamespace() << "::get" << DirLang.getName()
- << Enum << "Kind(llvm::StringRef Str) {\n";
+ OS << Qual << Enum << " " << Qual << "get" << DirLang.getName() << Enum
+ << "Kind(llvm::StringRef Str) {\n";
OS << " return StringSwitch<" << Enum << ">(Str)\n";
- for (const auto &R : Records) {
+ for (const Record *R : Records) {
BaseRecord Rec(R);
if (ImplicitAsUnknown && R->getValueAsBit("isImplicit")) {
- OS << " .Case(\"" << Rec.getName() << "\"," << Prefix
- << DefaultRec.getFormattedName() << ")\n";
+ OS << " .Case(\"" << Rec.getName() << "\"," << DefaultName << ")\n";
} else {
- OS << " .Case(\"" << Rec.getName() << "\"," << Prefix
- << Rec.getFormattedName() << ")\n";
+ OS << " .Case(\"" << Rec.getName() << "\","
+ << getIdentifierName(R, Prefix) << ")\n";
}
}
- OS << " .Default(" << Prefix << DefaultRec.getFormattedName() << ");\n";
+ OS << " .Default(" << DefaultName << ");\n";
OS << "}\n";
}
// Generate function implementation for get<ClauseVal>Kind(StringRef Str)
static void generateGetKindClauseVal(const DirectiveLanguage &DirLang,
raw_ostream &OS) {
+ StringRef Lang = DirLang.getName();
+ std::string Qual = getQualifier(DirLang);
+
for (const Clause C : DirLang.getClauses()) {
const auto &ClauseVals = C.getClauseVals();
if (ClauseVals.size() <= 0)
@@ -403,18 +434,17 @@ static void generateGetKindClauseVal(const DirectiveLanguage &DirLang,
}
const auto DefaultName = (*DefaultIt)->getName();
- const auto &EnumName = C.getEnumName();
- if (EnumName.empty()) {
+ StringRef Enum = C.getEnumName();
+ if (Enum.empty()) {
PrintError("enumClauseValue field not set in Clause" +
C.getFormattedName() + ".");
return;
}
OS << "\n";
- OS << "llvm::" << DirLang.getCppNamespace() << "::" << EnumName
- << " llvm::" << DirLang.getCppNamespace() << "::get" << EnumName
+ OS << Qual << Enum << " " << Qual << "get" << Enum
<< "(llvm::StringRef Str) {\n";
- OS << " return StringSwitch<" << EnumName << ">(Str)\n";
+ OS << " return StringSwitch<" << Enum << ">(Str)\n";
for (const auto &CV : ClauseVals) {
ClauseVal CVal(CV);
OS << " .Case(\"" << CVal.getFormattedName() << "\"," << CV->getName()
@@ -424,10 +454,8 @@ static void generateGetKindClauseVal(const DirectiveLanguage &DirLang,
OS << "}\n";
OS << "\n";
- OS << "llvm::StringRef llvm::" << DirLang.getCppNamespace() << "::get"
- << DirLang.getName() << EnumName
- << "Name(llvm::" << DirLang.getCppNamespace() << "::" << EnumName
- << " x) {\n";
+ OS << "llvm::StringRef " << Qual << "get" << Lang << Enum << "Name(" << Qual
+ << Enum << " x) {\n";
OS << " switch (x) {\n";
for (const auto &CV : ClauseVals) {
ClauseVal CVal(CV);
@@ -435,57 +463,46 @@ static void generateGetKindClauseVal(const DirectiveLanguage &DirLang,
OS << " return \"" << CVal.getFormattedName() << "\";\n";
}
OS << " }\n"; // switch
- OS << " llvm_unreachable(\"Invalid " << DirLang.getName() << " "
- << EnumName << " kind\");\n";
+ OS << " llvm_unreachable(\"Invalid " << Lang << " " << Enum
+ << " kind\");\n";
OS << "}\n";
}
}
-static void generateCaseForVersionedClauses(ArrayRef<const Record *> Clauses,
+static void generateCaseForVersionedClauses(ArrayRef<const Record *> VerClauses,
raw_ostream &OS,
const DirectiveLanguage &DirLang,
StringSet<> &Cases) {
- for (const VersionedClause VerClause : Clauses) {
- const auto ClauseFormattedName = VerClause.getClause().getFormattedName();
-
- if (Cases.insert(ClauseFormattedName).second) {
- OS << " case " << DirLang.getClausePrefix() << ClauseFormattedName
- << ":\n";
+ StringRef Prefix = DirLang.getClausePrefix();
+ for (const Record *R : VerClauses) {
+ VersionedClause VerClause(R);
+ std::string Name =
+ getIdentifierName(VerClause.getClause().getRecord(), Prefix);
+ if (Cases.insert(Name).second) {
+ OS << " case " << Name << ":\n";
OS << " return " << VerClause.getMinVersion()
<< " <= Version && " << VerClause.getMaxVersion() << " >= Version;\n";
}
}
}
-static std::string getDirectiveName(const DirectiveLanguage &DirLang,
- const Record *Rec) {
- Directive Dir(Rec);
- return (Twine("llvm::") + DirLang.getCppNamespace() +
- "::" + DirLang.getDirectivePrefix() + Dir.getFormattedName())
- .str();
-}
-
-static std::string getDirectiveType(const DirectiveLanguage &DirLang) {
- return (Twine("llvm::") + DirLang.getCppNamespace() + "::Directive").str();
-}
-
// Generate the isAllowedClauseForDirective function implementation.
static void generateIsAllowedClause(const DirectiveLanguage &DirLang,
raw_ostream &OS) {
+ std::string Qual = getQualifier(DirLang);
+
OS << "\n";
- OS << "bool llvm::" << DirLang.getCppNamespace()
- << "::isAllowedClauseForDirective("
- << "llvm::" << DirLang.getCppNamespace()
- << "::Directive D, llvm::" << DirLang.getCppNamespace()
- << "::Clause C, unsigned Version) {\n";
+ OS << "bool " << Qual << "isAllowedClauseForDirective(" << Qual
+ << "Directive D, " << Qual << "Clause C, unsigned Version) {\n";
OS << " assert(unsigned(D) <= Directive_enumSize);\n";
OS << " assert(unsigned(C) <= Clause_enumSize);\n";
OS << " switch (D) {\n";
- for (const Directive Dir : DirLang.getDirectives()) {
- OS << " case " << DirLang.getDirectivePrefix() << Dir.getFormattedName()
- << ":\n";
+ StringRef Prefix = DirLang.getDirectivePrefix();
+ for (const Record *R : DirLang.getDirectives()) {
+ Directive Dir(R);
+ OS << " case " << getIdentifierName(R, Prefix) << ":\n";
if (Dir.getAllowedClauses().empty() &&
Dir.getAllowedOnceClauses().empty() &&
Dir.getAllowedExclusiveClauses().empty() &&
@@ -611,19 +628,22 @@ static void emitLeafTable(const DirectiveLanguage &DirLang, raw_ostream &OS,
// type is `int` (by default). The code above uses `int` to store directive
// ids, so make sure that we catch it when something changes in the
// underlying type.
- std::string DirectiveType = getDirectiveType(DirLang);
+ StringRef Prefix = DirLang.getDirectivePrefix();
+ std::string Qual = getQualifier(DirLang);
+ std::string DirectiveType = Qual + "Directive";
OS << "\nstatic_assert(sizeof(" << DirectiveType << ") == sizeof(int));\n";
OS << "[[maybe_unused]] static const " << DirectiveType << ' ' << TableName
<< "[][" << MaxLeafCount + 2 << "] = {\n";
for (size_t I = 0, E = Directives.size(); I != E; ++I) {
auto &Leaves = LeafTable[Ordering[I]];
- OS << " {" << getDirectiveName(DirLang, Directives[Leaves[0]]);
+ OS << " {" << Qual << getIdentifierName(Directives[Leaves[0]], Prefix);
OS << ", static_cast<" << DirectiveType << ">(" << Leaves[1] << "),";
for (size_t I = 2, E = Leaves.size(); I != E; ++I) {
int Idx = Leaves[I];
if (Idx >= 0)
- OS << ' ' << getDirectiveName(DirLang, Directives[Leaves[I]]) << ',';
+ OS << ' ' << Qual << getIdentifierName(Directives[Leaves[I]], Prefix)
+ << ',';
else
OS << " static_cast<" << DirectiveType << ">(-1),";
}
@@ -761,18 +781,15 @@ static void generateGetDirectiveAssociation(const DirectiveLanguage &DirLang,
OS << '\n';
- std::string DirectiveTypeName =
- "llvm::" + DirLang.getCppNamespace().str() + "::Directive";
+ StringRef Prefix = DirLang.g...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/140772
More information about the llvm-commits
mailing list