[llvm] [mlir] [MLIR] convert OpAsmDialectInterface using ODS (PR #171488)

via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 18 03:15:43 PST 2025


https://github.com/aidint updated https://github.com/llvm/llvm-project/pull/171488

>From 5f2d23e6c7e18ab6439b934b831840909028da1e Mon Sep 17 00:00:00 2001
From: aidint <at.aidin at gmail.com>
Date: Tue, 9 Dec 2025 18:28:24 +0100
Subject: [PATCH 1/7] convert OpAsmDialectInterface using ODS

---
 mlir/include/mlir/IR/CMakeLists.txt           |  5 ++
 mlir/include/mlir/IR/Interfaces.td            | 20 ++++-
 mlir/include/mlir/IR/OpAsmDialectInterface.td | 78 +++++++++++++++++++
 mlir/include/mlir/IR/OpImplementation.h       | 65 ++--------------
 mlir/include/mlir/TableGen/Interfaces.h       |  9 +++
 mlir/lib/IR/CMakeLists.txt                    |  1 +
 mlir/lib/TableGen/Interfaces.cpp              | 24 ++++++
 .../mlir-tblgen/DialectInterfacesGen.cpp      | 37 +++++++--
 8 files changed, 175 insertions(+), 64 deletions(-)
 create mode 100644 mlir/include/mlir/IR/OpAsmDialectInterface.td

diff --git a/mlir/include/mlir/IR/CMakeLists.txt b/mlir/include/mlir/IR/CMakeLists.txt
index 683e2feaddef2..22358d7b09616 100644
--- a/mlir/include/mlir/IR/CMakeLists.txt
+++ b/mlir/include/mlir/IR/CMakeLists.txt
@@ -57,6 +57,11 @@ mlir_tablegen(TensorEncInterfaces.h.inc -gen-attr-interface-decls)
 mlir_tablegen(TensorEncInterfaces.cpp.inc -gen-attr-interface-defs)
 add_mlir_generic_tablegen_target(MLIRTensorEncodingIncGen)
 
+set(LLVM_TARGET_DEFINITIONS OpAsmDialectInterface.td)
+mlir_tablegen(OpAsmDialectInterface.h.inc -gen-dialect-interface-decls)
+add_mlir_generic_tablegen_target(MLIROpAsmDialectInterfaceIncGen)
+
+
 add_mlir_doc(BuiltinAttributes BuiltinAttributes Dialects/ -gen-attrdef-doc)
 add_mlir_doc(BuiltinLocationAttributes BuiltinLocationAttributes Dialects/ -gen-attrdef-doc)
 add_mlir_doc(BuiltinOps BuiltinOps Dialects/ -gen-op-doc)
diff --git a/mlir/include/mlir/IR/Interfaces.td b/mlir/include/mlir/IR/Interfaces.td
index e51bbd5620280..51c5a69fabcd5 100644
--- a/mlir/include/mlir/IR/Interfaces.td
+++ b/mlir/include/mlir/IR/Interfaces.td
@@ -85,6 +85,16 @@ class StaticInterfaceMethod<string desc, string retTy, string methodName,
     : InterfaceMethod<desc, retTy, methodName, args, methodBody,
                       defaultImplementation>;
 
+// This class represents a pure virtual interface method.
+class PureVirtualInterfaceMethod<string desc, string retTy, string methodName,
+                            dag args = (ins)>
+    : InterfaceMethod<desc, retTy, methodName, args>;
+
+// This class represents a interface method declaration.
+class InterfaceMethodDeclaration<string desc, string retTy, string methodName,
+                            dag args = (ins)>
+    : InterfaceMethod<desc, retTy, methodName, args>;
+
 // Interface represents a base interface.
 class Interface<string name, list<Interface> baseInterfacesArg = []> {
   // A human-readable description of what this interface does.
@@ -147,9 +157,17 @@ class TypeInterface<string name, list<Interface> baseInterfaces = []>
 			!if(!empty(cppNamespace),"", cppNamespace # "::") # name
     >;
 
+// AliasDeclaration represents an Alias Declaration in a Dialect Interface
+class AliasDeclaration<string alias, string typeId> {
+	string name = alias;
+  string aliased = typeId;
+}
+
 // DialectInterface represents a Dialect Interface.
 class DialectInterface<string name, list<Interface> baseInterfaces = []>
-  : Interface<name, baseInterfaces>, OpInterfaceTrait<name>;
+  : Interface<name, baseInterfaces>, OpInterfaceTrait<name> {
+  list<AliasDeclaration> aliasDeclarations = [];
+}
 
 
 // Whether to declare the interface methods in the user entity's header. This
diff --git a/mlir/include/mlir/IR/OpAsmDialectInterface.td b/mlir/include/mlir/IR/OpAsmDialectInterface.td
new file mode 100644
index 0000000000000..892bf6c768be1
--- /dev/null
+++ b/mlir/include/mlir/IR/OpAsmDialectInterface.td
@@ -0,0 +1,78 @@
+#ifndef MLIR_INTERFACES_OPASMDIALECTINTERFACE
+#define MLIR_INTERFACES_OPASMDIALECTINTERFACE
+
+include "mlir/IR/Interfaces.td"
+
+def OpAsmDialectInterface : DialectInterface<"OpAsmDialectInterface"> {
+  let description = [{
+    Dialect OpAsm interface
+  }];
+  let cppNamespace = "::mlir";
+  let aliasDeclarations = [AliasDeclaration<"AliasResult", "OpAsmAliasResult">];
+
+  let methods = [
+    InterfaceMethod<[{
+        Hooks for getting an alias identifier alias for a given symbol, that is
+        not necessarily a part of this dialect. The identifier is used in place of
+        the symbol when printing textual IR. These aliases must not contain `.` or
+        end with a numeric digit([0-9]+).
+      }],
+      "AliasResult", "getAlias",
+      (ins "::mlir::Attribute":$attr, "::llvm::raw_ostream &":$os),
+      [{
+        return AliasResult::NoAlias;
+      }]
+    >,
+    InterfaceMethod<[{}], "AliasResult", "getAlias",
+      (ins "::mlir::Type":$type, "::llvm::raw_ostream &":$os),
+      [{
+        return AliasResult::NoAlias;
+      }]
+    >,
+    InterfaceMethod<[{
+        Declare a resource with the given key, returning a handle to use for any
+        references of this resource key within the IR during parsing. The result
+        of `getResourceKey` on the returned handle is permitted to be different
+        than `key`.
+      }],
+      "::mlir::FailureOr<AsmDialectResourceHandle>", "declareResource",
+      (ins "::mlir::StringRef":$key),
+      [{
+        return failure();
+      }]
+    >,
+    InterfaceMethod<[{
+        Return a key to use for the given resource. This key should uniquely
+        identify this resource within the dialect.
+      }],
+      "std::string", "getResourceKey",
+      (ins "const ::mlir::AsmDialectResourceHandle &":$handle),
+      [{
+        llvm_unreachable(
+            "Dialect must implement `getResourceKey` when defining resources");
+      }]
+    >,
+    InterfaceMethodDeclaration<[{
+        Hook for parsing resource entries. Returns failure if the entry was not
+        valid, or could otherwise not be processed correctly. Any necessary errors
+        can be emitted via the provided entry.
+      }],
+      "::llvm::LogicalResult", "parseResource",
+      (ins "::mlir::AsmParsedResourceEntry &":$entry)
+    >,
+    InterfaceMethod<[{
+        Hook for building resources to use during printing. The given `op` may be
+        inspected to help determine what information to include.
+        `referencedResources` contains all of the resources detected when printing
+        'op'.
+      }],
+      "void", "buildResources",
+      (ins "::mlir::Operation *":$op, 
+            "const ::mlir::SetVector<::mlir::AsmDialectResourceHandle> &":$referencedResources,
+            "::mlir::AsmResourceBuilder &":$builder)
+    >  
+  ];
+}
+
+
+#endif
diff --git a/mlir/include/mlir/IR/OpImplementation.h b/mlir/include/mlir/IR/OpImplementation.h
index d70aa346eaa1f..1d2229a402614 100644
--- a/mlir/include/mlir/IR/OpImplementation.h
+++ b/mlir/include/mlir/IR/OpImplementation.h
@@ -1777,64 +1777,6 @@ class OpAsmParser : public AsmParser {
                               SmallVectorImpl<UnresolvedOperand> &rhs) = 0;
 };
 
-//===--------------------------------------------------------------------===//
-// Dialect OpAsm interface.
-//===--------------------------------------------------------------------===//
-
-class OpAsmDialectInterface
-    : public DialectInterface::Base<OpAsmDialectInterface> {
-public:
-  OpAsmDialectInterface(Dialect *dialect) : Base(dialect) {}
-
-  using AliasResult = OpAsmAliasResult;
-
-  /// Hooks for getting an alias identifier alias for a given symbol, that is
-  /// not necessarily a part of this dialect. The identifier is used in place of
-  /// the symbol when printing textual IR. These aliases must not contain `.` or
-  /// end with a numeric digit([0-9]+).
-  virtual AliasResult getAlias(Attribute attr, raw_ostream &os) const {
-    return AliasResult::NoAlias;
-  }
-  virtual AliasResult getAlias(Type type, raw_ostream &os) const {
-    return AliasResult::NoAlias;
-  }
-
-  //===--------------------------------------------------------------------===//
-  // Resources
-  //===--------------------------------------------------------------------===//
-
-  /// Declare a resource with the given key, returning a handle to use for any
-  /// references of this resource key within the IR during parsing. The result
-  /// of `getResourceKey` on the returned handle is permitted to be different
-  /// than `key`.
-  virtual FailureOr<AsmDialectResourceHandle>
-  declareResource(StringRef key) const {
-    return failure();
-  }
-
-  /// Return a key to use for the given resource. This key should uniquely
-  /// identify this resource within the dialect.
-  virtual std::string
-  getResourceKey(const AsmDialectResourceHandle &handle) const {
-    llvm_unreachable(
-        "Dialect must implement `getResourceKey` when defining resources");
-  }
-
-  /// Hook for parsing resource entries. Returns failure if the entry was not
-  /// valid, or could otherwise not be processed correctly. Any necessary errors
-  /// can be emitted via the provided entry.
-  virtual LogicalResult parseResource(AsmParsedResourceEntry &entry) const;
-
-  /// Hook for building resources to use during printing. The given `op` may be
-  /// inspected to help determine what information to include.
-  /// `referencedResources` contains all of the resources detected when printing
-  /// 'op'.
-  virtual void
-  buildResources(Operation *op,
-                 const SetVector<AsmDialectResourceHandle> &referencedResources,
-                 AsmResourceBuilder &builder) const {}
-};
-
 //===--------------------------------------------------------------------===//
 // Custom printers and parsers.
 //===--------------------------------------------------------------------===//
@@ -1854,6 +1796,13 @@ ParseResult parseDimensionList(OpAsmParser &parser,
 /// The OpAsmOpInterface, see OpAsmInterface.td for more details.
 #include "mlir/IR/OpAsmOpInterface.h.inc"
 
+//===--------------------------------------------------------------------===//
+// Dialect OpAsm interface.
+//===--------------------------------------------------------------------===//
+
+/// The OpAsmDialectInterface, see OpAsmDialectInterface.td
+#include "mlir/IR/OpAsmDialectInterface.h.inc"
+
 namespace llvm {
 template <>
 struct DenseMapInfo<mlir::AsmDialectResourceHandle> {
diff --git a/mlir/include/mlir/TableGen/Interfaces.h b/mlir/include/mlir/TableGen/Interfaces.h
index f62d21da467a1..28b2844a91470 100644
--- a/mlir/include/mlir/TableGen/Interfaces.h
+++ b/mlir/include/mlir/TableGen/Interfaces.h
@@ -46,6 +46,12 @@ class InterfaceMethod {
   // Return if this method is static.
   bool isStatic() const;
 
+  // Return if the method is a pure virtual one.
+  bool isPureVirtual() const;
+
+  // Return if the method is only a declaration.
+  bool isDeclaration() const;
+
   // Return the body for this method if it has one.
   std::optional<StringRef> getBody() const;
 
@@ -161,6 +167,9 @@ struct TypeInterface : public Interface {
 struct DialectInterface : public Interface {
   using Interface::Interface;
 
+  // Return alias declarations
+  SmallVector<std::pair<StringRef, StringRef>> getAliasDeclarations() const;
+
   static bool classof(const Interface *interface);
 };
 
diff --git a/mlir/lib/IR/CMakeLists.txt b/mlir/lib/IR/CMakeLists.txt
index d95bdc957e3c2..563c8c6285ef3 100644
--- a/mlir/lib/IR/CMakeLists.txt
+++ b/mlir/lib/IR/CMakeLists.txt
@@ -67,6 +67,7 @@ add_mlir_library(MLIRIR
   MLIRSideEffectInterfacesIncGen
   MLIRSymbolInterfacesIncGen
   MLIRTensorEncodingIncGen
+  MLIROpAsmDialectInterfaceIncGen
 
   LINK_LIBS PUBLIC
   MLIRSupport
diff --git a/mlir/lib/TableGen/Interfaces.cpp b/mlir/lib/TableGen/Interfaces.cpp
index 77a6cecebbeaf..cc888d921cc4c 100644
--- a/mlir/lib/TableGen/Interfaces.cpp
+++ b/mlir/lib/TableGen/Interfaces.cpp
@@ -11,6 +11,7 @@
 #include "llvm/ADT/StringSet.h"
 #include "llvm/TableGen/Error.h"
 #include "llvm/TableGen/Record.h"
+#include <utility>
 
 using namespace mlir;
 using namespace mlir::tblgen;
@@ -51,6 +52,16 @@ bool InterfaceMethod::isStatic() const {
   return def->isSubClassOf("StaticInterfaceMethod");
 }
 
+// Return if the method is a pure virtual one.
+bool InterfaceMethod::isPureVirtual() const {
+  return def->isSubClassOf("PureVirtualInterfaceMethod");
+}
+
+// Return if the method is only a declaration.
+bool InterfaceMethod::isDeclaration() const {
+  return def->isSubClassOf("InterfaceMethodDeclaration");
+}
+
 // Return the body for this method if it has one.
 std::optional<StringRef> InterfaceMethod::getBody() const {
   // Trim leading and trailing spaces from the default implementation.
@@ -216,3 +227,16 @@ bool TypeInterface::classof(const Interface *interface) {
 bool DialectInterface::classof(const Interface *interface) {
   return interface->getDef().isSubClassOf("DialectInterface");
 }
+
+// Return the interfaces extra class declaration code.
+SmallVector<std::pair<StringRef, StringRef>>
+DialectInterface::getAliasDeclarations() const {
+  SmallVector<std::pair<StringRef, StringRef>, 1> aliasDeclarations;
+
+  for (auto &aliasDef : getDef().getValueAsListOfDefs("aliasDeclarations")) {
+    auto alias = aliasDef->getValueAsString("name");
+    auto typeId = aliasDef->getValueAsString("aliased");
+    aliasDeclarations.push_back(std::make_pair(alias, typeId));
+  }
+  return aliasDeclarations;
+}
diff --git a/mlir/tools/mlir-tblgen/DialectInterfacesGen.cpp b/mlir/tools/mlir-tblgen/DialectInterfacesGen.cpp
index 1d3b24a7aee15..963dd24753c5d 100644
--- a/mlir/tools/mlir-tblgen/DialectInterfacesGen.cpp
+++ b/mlir/tools/mlir-tblgen/DialectInterfacesGen.cpp
@@ -26,7 +26,7 @@
 using namespace mlir;
 using llvm::Record;
 using llvm::RecordKeeper;
-using mlir::tblgen::Interface;
+using mlir::tblgen::DialectInterface;
 using mlir::tblgen::InterfaceMethod;
 
 /// Emit a string corresponding to a C++ type, followed by a space if necessary.
@@ -74,7 +74,7 @@ class DialectInterfaceGenerator {
   bool emitInterfaceDecls();
 
 protected:
-  void emitInterfaceDecl(const Interface &interface);
+  void emitInterfaceDecl(const DialectInterface &interface);
 
   /// The set of interface records to emit.
   std::vector<const Record *> defs;
@@ -91,9 +91,11 @@ static void emitInterfaceMethodDoc(const InterfaceMethod &method,
                                    raw_ostream &os, StringRef prefix = "") {
   if (std::optional<StringRef> description = method.getDescription())
     tblgen::emitDescriptionComment(*description, os, prefix);
+  else
+    os << "\n";
 }
 
-static void emitInterfaceMethodsDef(const Interface &interface,
+static void emitInterfaceMethodsDef(const DialectInterface &interface,
                                     raw_ostream &os) {
 
   raw_indented_ostream ios(os);
@@ -104,6 +106,18 @@ static void emitInterfaceMethodsDef(const Interface &interface,
     ios << "virtual ";
     emitCPPType(method.getReturnType(), ios);
     emitMethodNameAndArgs(method, method.getName(), ios);
+
+    if (method.isDeclaration()) {
+      ios << ";\n";
+      continue;
+    }
+
+    if (method.isPureVirtual()) {
+      ios << " = 0;\n";
+      continue;
+    }
+
+    // Otherwise it's a normal interface method
     ios << " {";
 
     if (auto body = method.getBody()) {
@@ -116,7 +130,18 @@ static void emitInterfaceMethodsDef(const Interface &interface,
   }
 }
 
-void DialectInterfaceGenerator::emitInterfaceDecl(const Interface &interface) {
+static void emitInterfaceAliasDeclarations(const DialectInterface &interface,
+                                           raw_ostream &os) {
+  raw_indented_ostream ios(os);
+  ios.indent(2);
+
+  for (auto [alias, typeId] : interface.getAliasDeclarations()) {
+    ios << "using " << alias << " = " << typeId << ";\n";
+  }
+}
+
+void DialectInterfaceGenerator::emitInterfaceDecl(
+    const DialectInterface &interface) {
   llvm::NamespaceEmitter ns(os, interface.getCppNamespace());
 
   StringRef interfaceName = interface.getName();
@@ -131,6 +156,8 @@ void DialectInterfaceGenerator::emitInterfaceDecl(const Interface &interface) {
       "  {0}(::mlir::Dialect *dialect) : Base(dialect) {{}\n",
       interfaceName);
 
+  emitInterfaceAliasDeclarations(interface, os);
+
   emitInterfaceMethodsDef(interface, os);
 
   os << "};\n";
@@ -148,7 +175,7 @@ bool DialectInterfaceGenerator::emitInterfaceDecls() {
   });
 
   for (const Record *def : sortedDefs)
-    emitInterfaceDecl(Interface(def));
+    emitInterfaceDecl(DialectInterface(def));
 
   return false;
 }

>From 38891edd28f417dafc39b087e4f8dda2211ba77a Mon Sep 17 00:00:00 2001
From: Jacques Pienaar <jacques+gh at japienaar.info>
Date: Thu, 11 Dec 2025 13:27:58 +0000
Subject: [PATCH 2/7] Add corresponding bazel changes

---
 utils/bazel/llvm-project-overlay/mlir/BUILD.bazel | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
index 9967aa8e08fd9..82bfd2cb08223 100644
--- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
@@ -111,6 +111,16 @@ gentbl_cc_library(
     deps = [":OpBaseTdFiles"],
 )
 
+gentbl_cc_library(
+    name = "OpAsmDialectInterfaceIncGen",
+    tbl_outs = {
+        "include/mlir/IR/OpAsmDialectInterface.h.inc": ["-gen-dialect-interface-decls"],
+    },
+    tblgen = ":mlir-tblgen",
+    td_file = "include/mlir/IR/OpAsmDialectInterface.td",
+    deps = [":OpBaseTdFiles"],
+)
+
 gentbl_cc_library(
     name = "TensorEncodingIncGen",
     tbl_outs = {
@@ -395,6 +405,7 @@ cc_library(
         "lib/Bytecode/Writer/*.h",
         "include/mlir/Bytecode/*.h",
     ]) + [
+        "include/mlir/IR/OpAsmDialectInterface.h.inc",
         "include/mlir/IR/OpAsmOpInterface.h.inc",
         "include/mlir/Interfaces/DataLayoutInterfaces.h",
         "include/mlir/Interfaces/InferIntRangeInterface.h",

>From fd498a6ecedfcb2b7a65959c8d99cd0b3704573e Mon Sep 17 00:00:00 2001
From: aidint <at.aidin at gmail.com>
Date: Sat, 13 Dec 2025 01:34:10 +0100
Subject: [PATCH 3/7] change aliasDeclarations to StringMap

---
 mlir/include/mlir/IR/Interfaces.td              | 4 ++--
 mlir/include/mlir/IR/OpAsmDialectInterface.td   | 4 ++--
 mlir/include/mlir/TableGen/Interfaces.h         | 3 ++-
 mlir/lib/TableGen/Interfaces.cpp                | 6 +++---
 mlir/tools/mlir-tblgen/DialectInterfacesGen.cpp | 5 +++--
 5 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/mlir/include/mlir/IR/Interfaces.td b/mlir/include/mlir/IR/Interfaces.td
index 51c5a69fabcd5..966854bf5cf29 100644
--- a/mlir/include/mlir/IR/Interfaces.td
+++ b/mlir/include/mlir/IR/Interfaces.td
@@ -157,9 +157,9 @@ class TypeInterface<string name, list<Interface> baseInterfaces = []>
 			!if(!empty(cppNamespace),"", cppNamespace # "::") # name
     >;
 
-// AliasDeclaration represents an Alias Declaration in a Dialect Interface
+// AliasDeclaration represents an Alias Declaration in a Dialect Interface.
 class AliasDeclaration<string alias, string typeId> {
-	string name = alias;
+  string name = alias;
   string aliased = typeId;
 }
 
diff --git a/mlir/include/mlir/IR/OpAsmDialectInterface.td b/mlir/include/mlir/IR/OpAsmDialectInterface.td
index 892bf6c768be1..d29b94453fe67 100644
--- a/mlir/include/mlir/IR/OpAsmDialectInterface.td
+++ b/mlir/include/mlir/IR/OpAsmDialectInterface.td
@@ -15,7 +15,7 @@ def OpAsmDialectInterface : DialectInterface<"OpAsmDialectInterface"> {
         Hooks for getting an alias identifier alias for a given symbol, that is
         not necessarily a part of this dialect. The identifier is used in place of
         the symbol when printing textual IR. These aliases must not contain `.` or
-        end with a numeric digit([0-9]+).
+        end with a numeric digit ([0-9]+).
       }],
       "AliasResult", "getAlias",
       (ins "::mlir::Attribute":$attr, "::llvm::raw_ostream &":$os),
@@ -35,7 +35,7 @@ def OpAsmDialectInterface : DialectInterface<"OpAsmDialectInterface"> {
         of `getResourceKey` on the returned handle is permitted to be different
         than `key`.
       }],
-      "::mlir::FailureOr<AsmDialectResourceHandle>", "declareResource",
+      "::mlir::FailureOr<::mlir::AsmDialectResourceHandle>", "declareResource",
       (ins "::mlir::StringRef":$key),
       [{
         return failure();
diff --git a/mlir/include/mlir/TableGen/Interfaces.h b/mlir/include/mlir/TableGen/Interfaces.h
index 28b2844a91470..03b11dc02e4dd 100644
--- a/mlir/include/mlir/TableGen/Interfaces.h
+++ b/mlir/include/mlir/TableGen/Interfaces.h
@@ -11,6 +11,7 @@
 
 #include "mlir/Support/LLVM.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/iterator.h"
 
@@ -168,7 +169,7 @@ struct DialectInterface : public Interface {
   using Interface::Interface;
 
   // Return alias declarations
-  SmallVector<std::pair<StringRef, StringRef>> getAliasDeclarations() const;
+  llvm::StringMap<StringRef> getAliasDeclarations() const;
 
   static bool classof(const Interface *interface);
 };
diff --git a/mlir/lib/TableGen/Interfaces.cpp b/mlir/lib/TableGen/Interfaces.cpp
index cc888d921cc4c..f93ef375131dc 100644
--- a/mlir/lib/TableGen/Interfaces.cpp
+++ b/mlir/lib/TableGen/Interfaces.cpp
@@ -229,14 +229,14 @@ bool DialectInterface::classof(const Interface *interface) {
 }
 
 // Return the interfaces extra class declaration code.
-SmallVector<std::pair<StringRef, StringRef>>
+llvm::StringMap<StringRef>
 DialectInterface::getAliasDeclarations() const {
-  SmallVector<std::pair<StringRef, StringRef>, 1> aliasDeclarations;
+  llvm::StringMap<StringRef> aliasDeclarations;
 
   for (auto &aliasDef : getDef().getValueAsListOfDefs("aliasDeclarations")) {
     auto alias = aliasDef->getValueAsString("name");
     auto typeId = aliasDef->getValueAsString("aliased");
-    aliasDeclarations.push_back(std::make_pair(alias, typeId));
+    aliasDeclarations[alias] = typeId;
   }
   return aliasDeclarations;
 }
diff --git a/mlir/tools/mlir-tblgen/DialectInterfacesGen.cpp b/mlir/tools/mlir-tblgen/DialectInterfacesGen.cpp
index 963dd24753c5d..a2b91c2dd8958 100644
--- a/mlir/tools/mlir-tblgen/DialectInterfacesGen.cpp
+++ b/mlir/tools/mlir-tblgen/DialectInterfacesGen.cpp
@@ -135,8 +135,9 @@ static void emitInterfaceAliasDeclarations(const DialectInterface &interface,
   raw_indented_ostream ios(os);
   ios.indent(2);
 
-  for (auto [alias, typeId] : interface.getAliasDeclarations()) {
-    ios << "using " << alias << " = " << typeId << ";\n";
+
+  for (auto &alias : interface.getAliasDeclarations()) {
+    ios << "using " << alias.getKey() << " = " << alias.getValue() << ";\n";
   }
 }
 

>From f7651965c734a0ddddf9972f471b3595f608fb5a Mon Sep 17 00:00:00 2001
From: aidint <at.aidin at gmail.com>
Date: Sat, 13 Dec 2025 01:38:17 +0100
Subject: [PATCH 4/7] resolve clang-format issue

---
 mlir/lib/TableGen/Interfaces.cpp                | 3 +--
 mlir/tools/mlir-tblgen/DialectInterfacesGen.cpp | 1 -
 2 files changed, 1 insertion(+), 3 deletions(-)

diff --git a/mlir/lib/TableGen/Interfaces.cpp b/mlir/lib/TableGen/Interfaces.cpp
index f93ef375131dc..e20cdba5f7e0c 100644
--- a/mlir/lib/TableGen/Interfaces.cpp
+++ b/mlir/lib/TableGen/Interfaces.cpp
@@ -229,8 +229,7 @@ bool DialectInterface::classof(const Interface *interface) {
 }
 
 // Return the interfaces extra class declaration code.
-llvm::StringMap<StringRef>
-DialectInterface::getAliasDeclarations() const {
+llvm::StringMap<StringRef> DialectInterface::getAliasDeclarations() const {
   llvm::StringMap<StringRef> aliasDeclarations;
 
   for (auto &aliasDef : getDef().getValueAsListOfDefs("aliasDeclarations")) {
diff --git a/mlir/tools/mlir-tblgen/DialectInterfacesGen.cpp b/mlir/tools/mlir-tblgen/DialectInterfacesGen.cpp
index a2b91c2dd8958..0c16514179c32 100644
--- a/mlir/tools/mlir-tblgen/DialectInterfacesGen.cpp
+++ b/mlir/tools/mlir-tblgen/DialectInterfacesGen.cpp
@@ -135,7 +135,6 @@ static void emitInterfaceAliasDeclarations(const DialectInterface &interface,
   raw_indented_ostream ios(os);
   ios.indent(2);
 
-
   for (auto &alias : interface.getAliasDeclarations()) {
     ios << "using " << alias.getKey() << " = " << alias.getValue() << ";\n";
   }

>From d784b8535a055eea0b2b348e68372d44a90f8c39 Mon Sep 17 00:00:00 2001
From: aidint <at.aidin at gmail.com>
Date: Wed, 17 Dec 2025 12:50:58 +0100
Subject: [PATCH 5/7] change to protected constructor for pure virtual methods

---
 mlir/test/mlir-tblgen/dialect-interface.td    | 53 ++++++++++++++++---
 .../mlir-tblgen/DialectInterfacesGen.cpp      | 36 ++++++++++---
 2 files changed, 77 insertions(+), 12 deletions(-)

diff --git a/mlir/test/mlir-tblgen/dialect-interface.td b/mlir/test/mlir-tblgen/dialect-interface.td
index ff39fd941f300..c24dfe6ed140d 100644
--- a/mlir/test/mlir-tblgen/dialect-interface.td
+++ b/mlir/test/mlir-tblgen/dialect-interface.td
@@ -10,7 +10,7 @@ def NoDefaultMethod : DialectInterface<"NoDefaultMethod"> {
   let cppNamespace = "::mlir::example";
 
   let methods = [
-    InterfaceMethod<
+      InterfaceMethod<
       /*desc=*/        "Check if it's an example dialect",
       /*returnType=*/  "bool",
       /*methodName=*/  "isExampleDialect",
@@ -28,9 +28,9 @@ def NoDefaultMethod : DialectInterface<"NoDefaultMethod"> {
 
 // DECL:   class NoDefaultMethod : public {{.*}}DialectInterface::Base<NoDefaultMethod>
 // DECL:   public:
-// DECL-NEXT:   NoDefaultMethod(::mlir::Dialect *dialect) : Base(dialect) {}
 // DECL:   virtual bool isExampleDialect() const {}
 // DECL:   virtual unsigned supportSecondMethod(::mlir::Type type) const {}
+// DECL:   NoDefaultMethod(::mlir::Dialect *dialect) : Base(dialect) {}
 
 def WithDefaultMethodInterface : DialectInterface<"WithDefaultMethodInterface"> {
   let description = [{
@@ -40,7 +40,7 @@ def WithDefaultMethodInterface : DialectInterface<"WithDefaultMethodInterface">
   let cppNamespace = "::mlir::example";
 
   let methods = [
-    InterfaceMethod<
+      InterfaceMethod<
       /*desc=*/        "Check if it's an example dialect",
       /*returnType=*/  "bool",
       /*methodName=*/  "isExampleDialect",
@@ -59,7 +59,48 @@ def WithDefaultMethodInterface : DialectInterface<"WithDefaultMethodInterface">
   ];
 }
 
-// DECL:  virtual bool isExampleDialect() const {
-// DECL-NEXT:  return true;
-// DECL-NEXT: }
+// DECL:   virtual bool isExampleDialect() const {
+// DECL-NEXT:   return true;
+// DECL-NEXT:   }
+
+def PureVirtualInterface : DialectInterface<"PureVirtualInterface"> {
+  let description = [{
+    This is an example dialect interface with pure virtual methods.
+  }];
+
+  let cppNamespace = "::mlir::example";
+
+  let aliasDeclarations = [
+      AliasDeclaration<"FirstAlias", "unsigned">];
+
+  let methods = [
+      PureVirtualInterfaceMethod<
+      /*desc=*/        "Check if it's an example dialect",
+      /*returnType=*/  "bool",
+      /*methodName=*/  "isExampleDialect",
+      /*args=*/        (ins)
+      >,
+      InterfaceMethod<
+      /*desc=*/        "second method to check if multiple methods supported",
+      /*returnType=*/  "FirstAlias",
+      /*methodName=*/  "supportSecondMethod",
+      /*args=*/        (ins "::mlir::Type":$type)
+      >,
+      InterfaceMethodDeclaration<
+      /*desc=*/        "a method declaration",
+      /*returnType=*/  "::mlir::Type",
+      /*methodName=*/  "exampleMethodDeclaration",
+      /*args=*/        (ins "::mlir::Type":$type)
+      >
+  ];
+}
+
+// DECL:   class PureVirtualInterface : public {{.*}}DialectInterface::Base<PureVirtualInterface>
+// DECL:   public:
+// DECL:   using FirstAlias = unsigned;
+// DECL:   virtual bool isExampleDialect() const = 0;
+// DECL:   virtual FirstAlias supportSecondMethod(::mlir::Type type) const {}
+// DECL:   virtual ::mlir::Type exampleMethodDeclaration(::mlir::Type type) const;
+// DECL:   protected:
+// DECL-NEXT:   PureVirtualInterface(::mlir::Dialect *dialect) : Base(dialect) {}
 
diff --git a/mlir/tools/mlir-tblgen/DialectInterfacesGen.cpp b/mlir/tools/mlir-tblgen/DialectInterfacesGen.cpp
index 0c16514179c32..c14ca9e6fe058 100644
--- a/mlir/tools/mlir-tblgen/DialectInterfacesGen.cpp
+++ b/mlir/tools/mlir-tblgen/DialectInterfacesGen.cpp
@@ -15,6 +15,8 @@
 #include "mlir/Support/IndentedOstream.h"
 #include "mlir/TableGen/GenInfo.h"
 #include "mlir/TableGen/Interfaces.h"
+#include "llvm/ADT/BitmaskEnum.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/raw_ostream.h"
@@ -140,26 +142,48 @@ static void emitInterfaceAliasDeclarations(const DialectInterface &interface,
   }
 }
 
+static void emitConstructor(const DialectInterface &interface,
+                            raw_ostream &os) {
+
+  raw_indented_ostream ios(os);
+
+  // We consider a constructor protected if interface has at least one pure
+  // virtual method
+  auto hasProtectedConstructor =
+      llvm::any_of(interface.getMethods(), [](const InterfaceMethod &method) {
+        return method.isPureVirtual();
+      });
+
+  ios.indent(0);
+  if (hasProtectedConstructor)
+    ios << "protected:\n";
+
+  ios.indent(2);
+  ios << llvm::formatv("{0}(::mlir::Dialect *dialect) : Base(dialect) {{}\n",
+                      interface.getName());
+}
+
 void DialectInterfaceGenerator::emitInterfaceDecl(
     const DialectInterface &interface) {
   llvm::NamespaceEmitter ns(os, interface.getCppNamespace());
 
-  StringRef interfaceName = interface.getName();
-
   tblgen::emitSummaryAndDescComments(os, "",
                                      interface.getDescription().value_or(""));
 
   // Emit the main interface class declaration.
   os << llvm::formatv(
-      "class {0} : public ::mlir::DialectInterface::Base<{0}> {\n"
-      "public:\n"
-      "  {0}(::mlir::Dialect *dialect) : Base(dialect) {{}\n",
-      interfaceName);
+      "class {0} : public ::mlir::DialectInterface::Base<{0}> {{\n"
+      "public:\n",
+      interface.getName());
 
   emitInterfaceAliasDeclarations(interface, os);
 
   emitInterfaceMethodsDef(interface, os);
 
+  os << "\n";
+
+  emitConstructor(interface, os);
+
   os << "};\n";
 }
 

>From c5a2c3cb4132509f1a13057b0528076c4b9f3286 Mon Sep 17 00:00:00 2001
From: aidint <at.aidin at gmail.com>
Date: Wed, 17 Dec 2025 12:53:45 +0100
Subject: [PATCH 6/7] resolve clang-format issue

---
 mlir/tools/mlir-tblgen/DialectInterfacesGen.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/tools/mlir-tblgen/DialectInterfacesGen.cpp b/mlir/tools/mlir-tblgen/DialectInterfacesGen.cpp
index c14ca9e6fe058..884a5bee15441 100644
--- a/mlir/tools/mlir-tblgen/DialectInterfacesGen.cpp
+++ b/mlir/tools/mlir-tblgen/DialectInterfacesGen.cpp
@@ -160,7 +160,7 @@ static void emitConstructor(const DialectInterface &interface,
 
   ios.indent(2);
   ios << llvm::formatv("{0}(::mlir::Dialect *dialect) : Base(dialect) {{}\n",
-                      interface.getName());
+                       interface.getName());
 }
 
 void DialectInterfaceGenerator::emitInterfaceDecl(

>From 048d3a3fbbdf3e596d7817880919a3774e9350b4 Mon Sep 17 00:00:00 2001
From: aidint <at.aidin at gmail.com>
Date: Thu, 18 Dec 2025 12:15:22 +0100
Subject: [PATCH 7/7] remove pure virtual methods support

---
 mlir/include/mlir/TableGen/Interfaces.h       |  3 -
 mlir/lib/TableGen/Interfaces.cpp              |  5 --
 mlir/test/mlir-tblgen/dialect-interface.td    | 68 +++++--------------
 .../mlir-tblgen/DialectInterfacesGen.cpp      | 35 +---------
 4 files changed, 21 insertions(+), 90 deletions(-)

diff --git a/mlir/include/mlir/TableGen/Interfaces.h b/mlir/include/mlir/TableGen/Interfaces.h
index 03b11dc02e4dd..f70a74fccb0bb 100644
--- a/mlir/include/mlir/TableGen/Interfaces.h
+++ b/mlir/include/mlir/TableGen/Interfaces.h
@@ -47,9 +47,6 @@ class InterfaceMethod {
   // Return if this method is static.
   bool isStatic() const;
 
-  // Return if the method is a pure virtual one.
-  bool isPureVirtual() const;
-
   // Return if the method is only a declaration.
   bool isDeclaration() const;
 
diff --git a/mlir/lib/TableGen/Interfaces.cpp b/mlir/lib/TableGen/Interfaces.cpp
index e20cdba5f7e0c..08c0f43213c27 100644
--- a/mlir/lib/TableGen/Interfaces.cpp
+++ b/mlir/lib/TableGen/Interfaces.cpp
@@ -52,11 +52,6 @@ bool InterfaceMethod::isStatic() const {
   return def->isSubClassOf("StaticInterfaceMethod");
 }
 
-// Return if the method is a pure virtual one.
-bool InterfaceMethod::isPureVirtual() const {
-  return def->isSubClassOf("PureVirtualInterfaceMethod");
-}
-
 // Return if the method is only a declaration.
 bool InterfaceMethod::isDeclaration() const {
   return def->isSubClassOf("InterfaceMethodDeclaration");
diff --git a/mlir/test/mlir-tblgen/dialect-interface.td b/mlir/test/mlir-tblgen/dialect-interface.td
index c24dfe6ed140d..f11fbb26d40cc 100644
--- a/mlir/test/mlir-tblgen/dialect-interface.td
+++ b/mlir/test/mlir-tblgen/dialect-interface.td
@@ -10,27 +10,21 @@ def NoDefaultMethod : DialectInterface<"NoDefaultMethod"> {
   let cppNamespace = "::mlir::example";
 
   let methods = [
-      InterfaceMethod<
-      /*desc=*/        "Check if it's an example dialect",
-      /*returnType=*/  "bool",
-      /*methodName=*/  "isExampleDialect",
-      /*args=*/        (ins)
-      >,
-      InterfaceMethod<
-      /*desc=*/        "second method to check if multiple methods supported",
-      /*returnType=*/  "unsigned",
-      /*methodName=*/  "supportSecondMethod",
-      /*args=*/        (ins "::mlir::Type":$type)
+    InterfaceMethod<
+      "Check if it's an example dialect", "bool", "isExampleDialect", (ins)
+    >,
+    InterfaceMethod<
+      "second method to check if multiple methods supported",
+      "unsigned", "supportSecondMethod", (ins "::mlir::Type":$type)
       >
-
   ];
 }
 
 // DECL:   class NoDefaultMethod : public {{.*}}DialectInterface::Base<NoDefaultMethod>
 // DECL:   public:
+/// DECL:   NoDefaultMethod(::mlir::Dialect *dialect) : Base(dialect) {}
 // DECL:   virtual bool isExampleDialect() const {}
 // DECL:   virtual unsigned supportSecondMethod(::mlir::Type type) const {}
-// DECL:   NoDefaultMethod(::mlir::Dialect *dialect) : Base(dialect) {}
 
 def WithDefaultMethodInterface : DialectInterface<"WithDefaultMethodInterface"> {
   let description = [{
@@ -41,21 +35,15 @@ def WithDefaultMethodInterface : DialectInterface<"WithDefaultMethodInterface">
 
   let methods = [
       InterfaceMethod<
-      /*desc=*/        "Check if it's an example dialect",
-      /*returnType=*/  "bool",
-      /*methodName=*/  "isExampleDialect",
-      /*args=*/        (ins),
-      /*methodBody=*/  [{
+        "Check if it's an example dialect", "bool", "isExampleDialect", (ins),
+        [{
           return true;
-         }]
+        }]
       >,
       InterfaceMethod<
-      /*desc=*/        "second method to check if multiple methods supported",
-      /*returnType=*/  "unsigned",
-      /*methodName=*/  "supportSecondMethod",
-      /*args=*/        (ins "::mlir::Type":$type)
+        "second method to check if multiple methods supported",
+        "unsigned", "supportSecondMethod", (ins "::mlir::Type":$type)
       >
-
   ];
 }
 
@@ -63,9 +51,9 @@ def WithDefaultMethodInterface : DialectInterface<"WithDefaultMethodInterface">
 // DECL-NEXT:   return true;
 // DECL-NEXT:   }
 
-def PureVirtualInterface : DialectInterface<"PureVirtualInterface"> {
+def OnlyDeclarationInterface : DialectInterface<"OnlyDeclarationInterface"> {
   let description = [{
-    This is an example dialect interface with pure virtual methods.
+    This is an example dialect interface with only declarations.
   }];
 
   let cppNamespace = "::mlir::example";
@@ -74,33 +62,13 @@ def PureVirtualInterface : DialectInterface<"PureVirtualInterface"> {
       AliasDeclaration<"FirstAlias", "unsigned">];
 
   let methods = [
-      PureVirtualInterfaceMethod<
-      /*desc=*/        "Check if it's an example dialect",
-      /*returnType=*/  "bool",
-      /*methodName=*/  "isExampleDialect",
-      /*args=*/        (ins)
-      >,
-      InterfaceMethod<
-      /*desc=*/        "second method to check if multiple methods supported",
-      /*returnType=*/  "FirstAlias",
-      /*methodName=*/  "supportSecondMethod",
-      /*args=*/        (ins "::mlir::Type":$type)
-      >,
       InterfaceMethodDeclaration<
-      /*desc=*/        "a method declaration",
-      /*returnType=*/  "::mlir::Type",
-      /*methodName=*/  "exampleMethodDeclaration",
-      /*args=*/        (ins "::mlir::Type":$type)
+        "a method declaration", "FirstAlias", "exampleMethodDeclaration", 
+        (ins "::mlir::Type":$type)
       >
   ];
 }
 
-// DECL:   class PureVirtualInterface : public {{.*}}DialectInterface::Base<PureVirtualInterface>
-// DECL:   public:
+// DECL:   class OnlyDeclarationInterface : public {{.*}}DialectInterface::Base<OnlyDeclarationInterface>
 // DECL:   using FirstAlias = unsigned;
-// DECL:   virtual bool isExampleDialect() const = 0;
-// DECL:   virtual FirstAlias supportSecondMethod(::mlir::Type type) const {}
-// DECL:   virtual ::mlir::Type exampleMethodDeclaration(::mlir::Type type) const;
-// DECL:   protected:
-// DECL-NEXT:   PureVirtualInterface(::mlir::Dialect *dialect) : Base(dialect) {}
-
+// DECL:   virtual FirstAlias exampleMethodDeclaration(::mlir::Type type) const;
diff --git a/mlir/tools/mlir-tblgen/DialectInterfacesGen.cpp b/mlir/tools/mlir-tblgen/DialectInterfacesGen.cpp
index 884a5bee15441..91006f135f10d 100644
--- a/mlir/tools/mlir-tblgen/DialectInterfacesGen.cpp
+++ b/mlir/tools/mlir-tblgen/DialectInterfacesGen.cpp
@@ -114,11 +114,6 @@ static void emitInterfaceMethodsDef(const DialectInterface &interface,
       continue;
     }
 
-    if (method.isPureVirtual()) {
-      ios << " = 0;\n";
-      continue;
-    }
-
     // Otherwise it's a normal interface method
     ios << " {";
 
@@ -142,27 +137,6 @@ static void emitInterfaceAliasDeclarations(const DialectInterface &interface,
   }
 }
 
-static void emitConstructor(const DialectInterface &interface,
-                            raw_ostream &os) {
-
-  raw_indented_ostream ios(os);
-
-  // We consider a constructor protected if interface has at least one pure
-  // virtual method
-  auto hasProtectedConstructor =
-      llvm::any_of(interface.getMethods(), [](const InterfaceMethod &method) {
-        return method.isPureVirtual();
-      });
-
-  ios.indent(0);
-  if (hasProtectedConstructor)
-    ios << "protected:\n";
-
-  ios.indent(2);
-  ios << llvm::formatv("{0}(::mlir::Dialect *dialect) : Base(dialect) {{}\n",
-                       interface.getName());
-}
-
 void DialectInterfaceGenerator::emitInterfaceDecl(
     const DialectInterface &interface) {
   llvm::NamespaceEmitter ns(os, interface.getCppNamespace());
@@ -172,18 +146,15 @@ void DialectInterfaceGenerator::emitInterfaceDecl(
 
   // Emit the main interface class declaration.
   os << llvm::formatv(
-      "class {0} : public ::mlir::DialectInterface::Base<{0}> {{\n"
-      "public:\n",
+      "class {0} : public ::mlir::DialectInterface::Base<{0}> {\n"
+      "public:\n"
+      "  {0}(::mlir::Dialect *dialect) : Base(dialect) {{}\n",
       interface.getName());
 
   emitInterfaceAliasDeclarations(interface, os);
 
   emitInterfaceMethodsDef(interface, os);
 
-  os << "\n";
-
-  emitConstructor(interface, os);
-
   os << "};\n";
 }
 



More information about the llvm-commits mailing list