[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