[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