-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[utils][TableGen] Clean up code in DirectiveEmitter #140772
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Remove most redundant function calls. Unify enum identifier name generation (via getIdentifierName), and namespace qualification (via getQualifier).
|
@llvm/pr-subscribers-tablegen Author: Krzysztof Parzyszek (kparzysz) ChangesRemove 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:
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]
|
tblah
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, nice cleanup
clementval
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Remove most redundant function calls. Unify enum identifier name generation (via getIdentifierName), and namespace qualification (via getQualifier).