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

Jacques Pienaar via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 11 07:06:59 PST 2025


https://github.com/jpienaar 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/2] 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/2] 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",



More information about the llvm-commits mailing list