[llvm] bc0af99 - [TableGen] Allow specification of underlying type for GenericEnum (#183769)

via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 2 07:09:29 PST 2026


Author: Nick Sarnie
Date: 2026-03-02T15:09:23Z
New Revision: bc0af9901b5178204ece0658a0a0b0f57aef6aac

URL: https://github.com/llvm/llvm-project/commit/bc0af9901b5178204ece0658a0a0b0f57aef6aac
DIFF: https://github.com/llvm/llvm-project/commit/bc0af9901b5178204ece0658a0a0b0f57aef6aac.diff

LOG: [TableGen] Allow specification of underlying type for GenericEnum (#183769)

Allow specification of the underlying C++ data type for `GenericEnum`.

I ran into this because I was trying to use a TableGen-genered enum in
`DenseSet` which requires the underlying type be specified.

Signed-off-by: Nick Sarnie <nick.sarnie at intel.com>

Added: 
    

Modified: 
    llvm/docs/TableGen/BackEnds.rst
    llvm/include/llvm/TableGen/SearchableTable.td
    llvm/test/TableGen/generic-tables.td
    llvm/utils/TableGen/SearchableTableEmitter.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/docs/TableGen/BackEnds.rst b/llvm/docs/TableGen/BackEnds.rst
index 1e3cb8783df16..ea74dfd217b2e 100644
--- a/llvm/docs/TableGen/BackEnds.rst
+++ b/llvm/docs/TableGen/BackEnds.rst
@@ -629,6 +629,10 @@ using the ``let`` statement.
   field, it will be assigned an integer value. Values are assigned in
   alphabetical order starting with 0.
 
+* ``string UnderlyingType``. The name of the underlying C++ data type
+  of the enum. If a record has no such field, there will be no specification
+  in the generated enum.
+
 Here is an example where the values of the elements are specified
 explicitly, as a template argument to the ``BEntry`` class. The resulting
 C++ code is shown.
@@ -670,6 +674,7 @@ by element name.
 
   def CEnum : GenericEnum {
     let FilterClass = "CEnum";
+    let UnderlyingType = "uint32_t";
   }
 
   class CEnum;
@@ -681,7 +686,7 @@ by element name.
 .. code-block:: text
 
   #ifdef GET_CEnum_DECL
-  enum CEnum {
+  enum CEnum : uint32_t {
     CBar = 0,
     CBaz = 1,
     CFoo = 2,

diff  --git a/llvm/include/llvm/TableGen/SearchableTable.td b/llvm/include/llvm/TableGen/SearchableTable.td
index f10e1597d8da7..71b837731c440 100644
--- a/llvm/include/llvm/TableGen/SearchableTable.td
+++ b/llvm/include/llvm/TableGen/SearchableTable.td
@@ -47,6 +47,12 @@ class GenericEnum {
   // If ValueField is not set, enum values will be assigned automatically,
   // starting at 0, according to a lexicographical sort of the entry names.
   string ValueField;
+
+  // (Optional) Underlying C++ data type of the enum.
+  //
+  // If UnderlyingType is not set, there will be no specification in
+  // the generated enum.
+  string UnderlyingType;
 }
 
 // Define a record derived from this class to generate a generic table. This

diff  --git a/llvm/test/TableGen/generic-tables.td b/llvm/test/TableGen/generic-tables.td
index 6b72a3e807e7d..ca29dcff75c0e 100644
--- a/llvm/test/TableGen/generic-tables.td
+++ b/llvm/test/TableGen/generic-tables.td
@@ -13,7 +13,7 @@ include "llvm/TableGen/SearchableTable.td"
 // CHECK: }
 
 // CHECK-LABEL: GET_CEnum_DECL
-// CHECK: enum CEnum {
+// CHECK: enum CEnum : uint64_t {
 // CHECK:   CBar
 // CHECK:   CBaz
 // CHECK:   CFoo
@@ -130,6 +130,7 @@ def CBaz : CEnum;
 
 def CEnum : GenericEnum {
   let FilterClass = "CEnum";
+  let UnderlyingType = "uint64_t";
 }
 
 class CEntry<string name, CEnum kind, int enc> {

diff  --git a/llvm/utils/TableGen/SearchableTableEmitter.cpp b/llvm/utils/TableGen/SearchableTableEmitter.cpp
index 88aa6bf8e9242..e100682bbcec3 100644
--- a/llvm/utils/TableGen/SearchableTableEmitter.cpp
+++ b/llvm/utils/TableGen/SearchableTableEmitter.cpp
@@ -55,6 +55,7 @@ struct GenericEnum {
   const Record *Class = nullptr;
   std::string PreprocessorGuard;
   MapVector<const Record *, Entry> Entries;
+  std::string UnderlyingType;
 
   const Entry *getEntry(const Record *Def) const {
     auto II = Entries.find(Def);
@@ -336,7 +337,10 @@ void SearchableTableEmitter::emitGenericEnum(const GenericEnum &Enum,
                                              raw_ostream &OS) {
   emitIfdef((Twine("GET_") + Enum.PreprocessorGuard + "_DECL").str(), OS);
 
-  OS << "enum " << Enum.Name << " {\n";
+  OS << "enum " << Enum.Name;
+  if (!Enum.UnderlyingType.empty())
+    OS << " : " << Enum.UnderlyingType;
+  OS << " {\n";
   for (const auto &[Name, Value] :
        make_second_range(Enum.Entries.getArrayRef()))
     OS << "  " << Name << " = " << Value << ",\n";
@@ -763,6 +767,9 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
                       Twine("Enum FilterClass '") + FilterClass +
                           "' does not exist");
 
+    if (!EnumRec->isValueUnset("UnderlyingType"))
+      Enum->UnderlyingType = EnumRec->getValueAsString("UnderlyingType");
+
     collectEnumEntries(*Enum, NameField, ValueField,
                        Records.getAllDerivedDefinitions(FilterClass));
     EnumMap.try_emplace(EnumRec, Enum.get());


        


More information about the llvm-commits mailing list