[Mlir-commits] [mlir] c51e4c4 - [mlir][IR] Use tablegen for the BuiltinDialect and operations
River Riddle
llvmlistbot at llvm.org
Tue Nov 17 01:03:00 PST 2020
Author: River Riddle
Date: 2020-11-17T00:53:40-08:00
New Revision: c51e4c4f012d89b8693c79ec855769e7e18b55a1
URL: https://github.com/llvm/llvm-project/commit/c51e4c4f012d89b8693c79ec855769e7e18b55a1
DIFF: https://github.com/llvm/llvm-project/commit/c51e4c4f012d89b8693c79ec855769e7e18b55a1.diff
LOG: [mlir][IR] Use tablegen for the BuiltinDialect and operations
This has been a long standing TODO, and cleans up a bit of IR/. This will also make it easier to move FuncOp out of IR/ at some point in the future. For now, Module.h and Function.h just forward BuiltinDialect.h. These files will be removed in a followup.
Differential Revision: https://reviews.llvm.org/D91571
Added:
mlir/include/mlir/IR/BuiltinDialect.h
mlir/include/mlir/IR/BuiltinOps.td
mlir/lib/IR/BuiltinDialect.cpp
Modified:
mlir/include/mlir/IR/CMakeLists.txt
mlir/include/mlir/IR/Function.h
mlir/include/mlir/IR/Module.h
mlir/include/mlir/IR/OpDefinition.h
mlir/include/mlir/IR/Operation.h
mlir/lib/IR/CMakeLists.txt
mlir/lib/IR/MLIRContext.cpp
mlir/lib/TableGen/OpClass.cpp
Removed:
mlir/lib/IR/Function.cpp
mlir/lib/IR/Module.cpp
################################################################################
diff --git a/mlir/include/mlir/IR/BuiltinDialect.h b/mlir/include/mlir/IR/BuiltinDialect.h
new file mode 100644
index 000000000000..06d20cbda399
--- /dev/null
+++ b/mlir/include/mlir/IR/BuiltinDialect.h
@@ -0,0 +1,93 @@
+//===- BuiltinDialect.h - MLIR Builtin Dialect ------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the Builtin dialect and its operations.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_IR_BUILTINDIALECT_H_
+#define MLIR_IR_BUILTINDIALECT_H_
+
+#include "mlir/IR/Dialect.h"
+#include "mlir/IR/FunctionSupport.h"
+#include "mlir/IR/OwningOpRefBase.h"
+#include "mlir/IR/SymbolTable.h"
+#include "mlir/Interfaces/CallInterfaces.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
+
+//===----------------------------------------------------------------------===//
+// Dialect
+//===----------------------------------------------------------------------===//
+
+#include "mlir/IR/BuiltinDialect.h.inc"
+
+//===----------------------------------------------------------------------===//
+// Dialect Operations
+//===----------------------------------------------------------------------===//
+
+#define GET_OP_CLASSES
+#include "mlir/IR/BuiltinOps.h.inc"
+
+//===----------------------------------------------------------------------===//
+// Dialect Utilities
+//===----------------------------------------------------------------------===//
+
+namespace mlir {
+/// This class acts as an owning reference to a module, and will automatically
+/// destroy the held module on destruction if the held module is valid.
+class OwningModuleRef : public OwningOpRefBase<ModuleOp> {
+public:
+ using OwningOpRefBase<ModuleOp>::OwningOpRefBase;
+};
+} // end namespace mlir
+
+namespace llvm {
+// Functions hash just like pointers.
+template <>
+struct DenseMapInfo<mlir::FuncOp> {
+ static mlir::FuncOp getEmptyKey() {
+ auto *pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
+ return mlir::FuncOp::getFromOpaquePointer(pointer);
+ }
+ static mlir::FuncOp getTombstoneKey() {
+ auto *pointer = llvm::DenseMapInfo<void *>::getTombstoneKey();
+ return mlir::FuncOp::getFromOpaquePointer(pointer);
+ }
+ static unsigned getHashValue(mlir::FuncOp val) {
+ return hash_value(val.getAsOpaquePointer());
+ }
+ static bool isEqual(mlir::FuncOp lhs, mlir::FuncOp rhs) { return lhs == rhs; }
+};
+
+/// Allow stealing the low bits of FuncOp.
+template <>
+struct PointerLikeTypeTraits<mlir::FuncOp> {
+ static inline void *getAsVoidPointer(mlir::FuncOp val) {
+ return const_cast<void *>(val.getAsOpaquePointer());
+ }
+ static inline mlir::FuncOp getFromVoidPointer(void *p) {
+ return mlir::FuncOp::getFromOpaquePointer(p);
+ }
+ static constexpr int NumLowBitsAvailable = 3;
+};
+
+/// Allow stealing the low bits of ModuleOp.
+template <>
+struct PointerLikeTypeTraits<mlir::ModuleOp> {
+public:
+ static inline void *getAsVoidPointer(mlir::ModuleOp val) {
+ return const_cast<void *>(val.getAsOpaquePointer());
+ }
+ static inline mlir::ModuleOp getFromVoidPointer(void *p) {
+ return mlir::ModuleOp::getFromOpaquePointer(p);
+ }
+ static constexpr int NumLowBitsAvailable = 3;
+};
+} // end namespace llvm
+
+#endif // MLIR_IR_BUILTINDIALECT_H_
diff --git a/mlir/include/mlir/IR/BuiltinOps.td b/mlir/include/mlir/IR/BuiltinOps.td
new file mode 100644
index 000000000000..bc573e0423d3
--- /dev/null
+++ b/mlir/include/mlir/IR/BuiltinOps.td
@@ -0,0 +1,235 @@
+//===- BuiltinOps.td - Builtin operation definitions -------*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the set of builtin MLIR operations.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef BUILTIN_OPS
+#define BUILTIN_OPS
+
+include "mlir/IR/SymbolInterfaces.td"
+include "mlir/Interfaces/CallInterfaces.td"
+
+def Builtin_Dialect : Dialect {
+ let summary =
+ "A dialect containing the builtin Attributes, Operations, and Types";
+
+ let name = "";
+ let cppNamespace = "::mlir";
+}
+
+// Base class for Builtin dialect ops.
+class Builtin_Op<string mnemonic, list<OpTrait> traits = []> :
+ Op<Builtin_Dialect, mnemonic, traits>;
+
+//===----------------------------------------------------------------------===//
+// FuncOp
+//===----------------------------------------------------------------------===//
+
+def FuncOp : Builtin_Op<"func", [
+ AffineScope, AutomaticAllocationScope, CallableOpInterface, FunctionLike,
+ IsolatedFromAbove, Symbol
+]> {
+ let summary = "An operation with a name containing a single `SSACFG` region";
+ let description = [{
+ Operations within the function cannot implicitly capture values defined
+ outside of the function, i.e. Functions are `IsolatedFromAbove`. All
+ external references must use function arguments or attributes that establish
+ a symbolic connection (e.g. symbols referenced by name via a string
+ attribute like SymbolRefAttr). An external function declaration (used when
+ referring to a function declared in some other module) has no body. While
+ the MLIR textual form provides a nice inline syntax for function arguments,
+ they are internally represented as “block arguments” to the first block in
+ the region.
+
+ Only dialect attribute names may be specified in the attribute dictionaries
+ for function arguments, results, or the function itself.
+
+ Example:
+
+ ```mlir
+ // External function definitions.
+ func @abort()
+ func @scribble(i32, i64, memref<? x 128 x f32, #layout_map0>) -> f64
+
+ // A function that returns its argument twice:
+ func @count(%x: i64) -> (i64, i64)
+ attributes {fruit: "banana"} {
+ return %x, %x: i64, i64
+ }
+
+ // A function with an argument attribute
+ func @example_fn_arg(%x: i32 {swift.self = unit})
+
+ // A function with a result attribute
+ func @example_fn_result() -> (f64 {dialectName.attrName = 0 : i64})
+
+ // A function with an attribute
+ func @example_fn_attr() attributes {dialectName.attrName = false}
+ ```
+ }];
+
+ let arguments = (ins SymbolNameAttr:$sym_name,
+ TypeAttr:$type,
+ OptionalAttr<StrAttr>:$sym_visibility);
+ let regions = (region AnyRegion:$body);
+
+ let builders = [OpBuilderDAG<(ins
+ "StringRef":$name, "FunctionType":$type,
+ CArg<"ArrayRef<NamedAttribute>", "{}">:$attrs,
+ CArg<"ArrayRef<MutableDictionaryAttr>", "{}">:$argAttrs)
+ >];
+ let extraClassDeclaration = [{
+ static FuncOp create(Location location, StringRef name, FunctionType type,
+ ArrayRef<NamedAttribute> attrs = {});
+ static FuncOp create(Location location, StringRef name, FunctionType type,
+ iterator_range<dialect_attr_iterator> attrs);
+ static FuncOp create(Location location, StringRef name, FunctionType type,
+ ArrayRef<NamedAttribute> attrs,
+ ArrayRef<MutableDictionaryAttr> argAttrs);
+
+ /// Create a deep copy of this function and all of its blocks, remapping any
+ /// operands that use values outside of the function using the map that is
+ /// provided (leaving them alone if no entry is present). If the mapper
+ /// contains entries for function arguments, these arguments are not
+ /// included in the new function. Replaces references to cloned sub-values
+ /// with the corresponding value that is copied, and adds those mappings to
+ /// the mapper.
+ FuncOp clone(BlockAndValueMapping &mapper);
+ FuncOp clone();
+
+ /// Clone the internal blocks and attributes from this function into dest.
+ /// Any cloned blocks are appended to the back of dest. This function
+ /// asserts that the attributes of the current function and dest are
+ /// compatible.
+ void cloneInto(FuncOp dest, BlockAndValueMapping &mapper);
+
+ //===------------------------------------------------------------------===//
+ // CallableOpInterface
+ //===------------------------------------------------------------------===//
+
+ /// Returns the region on the current operation that is callable. This may
+ /// return null in the case of an external callable object, e.g. an external
+ /// function.
+ Region *getCallableRegion() { return isExternal() ? nullptr : &getBody(); }
+
+ /// Returns the results types that the callable region produces when
+ /// executed.
+ ArrayRef<Type> getCallableResults() { return getType().getResults(); }
+
+ //===------------------------------------------------------------------===//
+ // SymbolOpInterface Methods
+ //===------------------------------------------------------------------===//
+
+ bool isDeclaration() { return isExternal(); }
+
+ private:
+ // This trait needs access to the hooks defined below.
+ friend class OpTrait::FunctionLike<FuncOp>;
+
+ /// Returns the number of arguments. This is a hook for
+ /// OpTrait::FunctionLike.
+ unsigned getNumFuncArguments() { return getType().getInputs().size(); }
+
+ /// Returns the number of results. This is a hook for OpTrait::FunctionLike.
+ unsigned getNumFuncResults() { return getType().getResults().size(); }
+
+ /// Hook for OpTrait::FunctionLike, called after verifying that the 'type'
+ /// attribute is present and checks if it holds a function type. Ensures
+ /// getType, getNumFuncArguments, and getNumFuncResults can be called
+ /// safely.
+ LogicalResult verifyType() {
+ auto type = getTypeAttr().getValue();
+ if (!type.isa<FunctionType>())
+ return emitOpError("requires '" + getTypeAttrName() +
+ "' attribute of function type");
+ return success();
+ }
+ }];
+ let parser = [{ return ::parseFuncOp(parser, result); }];
+ let printer = [{ return ::print(*this, p); }];
+ let verifier = [{ return ::verify(*this); }];
+}
+
+//===----------------------------------------------------------------------===//
+// ModuleOp
+//===----------------------------------------------------------------------===//
+
+def ModuleOp : Builtin_Op<"module", [
+ AffineScope, IsolatedFromAbove, NoRegionArguments, SymbolTable, Symbol,
+ SingleBlockImplicitTerminator<"ModuleTerminatorOp">
+]> {
+ let summary = "A top level container operation";
+ let description = [{
+ A `module` represents a top-level container operation. It contains a single
+ SSACFG region containing a single block which can contain any
+ operations. Operations within this region cannot implicitly capture values
+ defined outside the module, i.e. Modules are `IsolatedFromAbove`. Modules
+ have an optional symbol name which can be used to refer to them in
+ operations.
+
+ Example:
+
+ ```mlir
+ module {
+ func @foo()
+ }
+ ```
+ }];
+
+ let arguments = (ins OptionalAttr<SymbolNameAttr>:$sym_name,
+ OptionalAttr<StrAttr>:$sym_visibility);
+ let regions = (region SizedRegion<1>:$body);
+
+ let assemblyFormat = "($sym_name^)? attr-dict-with-keyword $body";
+ let builders = [OpBuilderDAG<(ins CArg<"Optional<StringRef>", "{}">:$name)>];
+ let extraClassDeclaration = [{
+ /// Construct a module from the given location with an optional name.
+ static ModuleOp create(Location loc, Optional<StringRef> name = llvm::None);
+
+ /// Return the name of this module if present.
+ Optional<StringRef> getName() { return sym_name(); }
+
+ /// Print the this module in the custom top-level form.
+ void print(raw_ostream &os, OpPrintingFlags flags = llvm::None);
+ void print(raw_ostream &os, AsmState &state,
+ OpPrintingFlags flags = llvm::None);
+ void dump();
+
+ //===------------------------------------------------------------------===//
+ // SymbolOpInterface Methods
+ //===------------------------------------------------------------------===//
+
+ /// A ModuleOp may optionally define a symbol.
+ bool isOptionalSymbol() { return true; }
+ }];
+ let verifier = [{ return ::verify(*this); }];
+
+ // We need to ensure the block inside the region is properly terminated;
+ // the auto-generated builders do not guarantee that.
+ let skipDefaultBuilders = 1;
+}
+
+//===----------------------------------------------------------------------===//
+// ModuleTerminatorOp
+//===----------------------------------------------------------------------===//
+
+def ModuleTerminatorOp : Builtin_Op<"module_terminator", [
+ Terminator, HasParent<"ModuleOp">
+]> {
+ let summary = "A pseudo op that marks the end of a module";
+ let description = [{
+ `module_terminator` is a special terminator operation for the body of a
+ `module`, it has no semantic meaning beyond keeping the body of a `module`
+ well-formed.
+ }];
+ let assemblyFormat = "attr-dict";
+}
+
+#endif // BUILTIN_OPS
diff --git a/mlir/include/mlir/IR/CMakeLists.txt b/mlir/include/mlir/IR/CMakeLists.txt
index c65616ff8eca..45649b3e7598 100644
--- a/mlir/include/mlir/IR/CMakeLists.txt
+++ b/mlir/include/mlir/IR/CMakeLists.txt
@@ -1,3 +1,11 @@
add_mlir_interface(OpAsmInterface)
add_mlir_interface(SymbolInterfaces)
add_mlir_interface(RegionKindInterface)
+
+set(LLVM_TARGET_DEFINITIONS BuiltinOps.td)
+mlir_tablegen(BuiltinOps.h.inc -gen-op-decls)
+mlir_tablegen(BuiltinOps.cpp.inc -gen-op-defs)
+mlir_tablegen(BuiltinDialect.h.inc -gen-dialect-decls)
+add_public_tablegen_target(MLIRBuiltinOpsIncGen)
+
+add_mlir_doc(BuiltinOps -gen-op-doc Builtin Dialects/)
diff --git a/mlir/include/mlir/IR/Function.h b/mlir/include/mlir/IR/Function.h
index 3ff2700a3380..e8d19de677c4 100644
--- a/mlir/include/mlir/IR/Function.h
+++ b/mlir/include/mlir/IR/Function.h
@@ -13,137 +13,7 @@
#ifndef MLIR_IR_FUNCTION_H
#define MLIR_IR_FUNCTION_H
-#include "mlir/IR/Block.h"
-#include "mlir/IR/FunctionSupport.h"
-#include "mlir/IR/OpDefinition.h"
-#include "mlir/IR/SymbolTable.h"
-#include "mlir/Interfaces/CallInterfaces.h"
-#include "llvm/Support/PointerLikeTypeTraits.h"
-
-namespace mlir {
-//===--------------------------------------------------------------------===//
-// Function Operation.
-//===--------------------------------------------------------------------===//
-
-/// FuncOp represents a function, or an operation containing one region that
-/// forms a CFG(Control Flow Graph). The region of a function is not allowed to
-/// implicitly capture global values, and all external references must use
-/// Function arguments or attributes that establish a symbolic connection(e.g.
-/// symbols referenced by name via a string attribute).
-class FuncOp
- : public Op<FuncOp, OpTrait::ZeroOperands, OpTrait::ZeroResult,
- OpTrait::OneRegion, OpTrait::IsIsolatedFromAbove,
- OpTrait::FunctionLike, OpTrait::AutomaticAllocationScope,
- OpTrait::AffineScope, CallableOpInterface::Trait,
- SymbolOpInterface::Trait> {
-public:
- using Op::Op;
- using Op::print;
-
- static StringRef getOperationName() { return "func"; }
-
- static FuncOp create(Location location, StringRef name, FunctionType type,
- ArrayRef<NamedAttribute> attrs = {});
- static FuncOp create(Location location, StringRef name, FunctionType type,
- iterator_range<dialect_attr_iterator> attrs);
- static FuncOp create(Location location, StringRef name, FunctionType type,
- ArrayRef<NamedAttribute> attrs,
- ArrayRef<MutableDictionaryAttr> argAttrs);
-
- static void build(OpBuilder &builder, OperationState &result, StringRef name,
- FunctionType type, ArrayRef<NamedAttribute> attrs = {},
- ArrayRef<MutableDictionaryAttr> argAttrs = {});
-
- /// Operation hooks.
- static ParseResult parse(OpAsmParser &parser, OperationState &result);
- void print(OpAsmPrinter &p);
- LogicalResult verify();
-
- /// Create a deep copy of this function and all of its blocks, remapping
- /// any operands that use values outside of the function using the map that is
- /// provided (leaving them alone if no entry is present). If the mapper
- /// contains entries for function arguments, these arguments are not included
- /// in the new function. Replaces references to cloned sub-values with the
- /// corresponding value that is copied, and adds those mappings to the mapper.
- FuncOp clone(BlockAndValueMapping &mapper);
- FuncOp clone();
-
- /// Clone the internal blocks and attributes from this function into dest. Any
- /// cloned blocks are appended to the back of dest. This function asserts that
- /// the attributes of the current function and dest are compatible.
- void cloneInto(FuncOp dest, BlockAndValueMapping &mapper);
-
- //===--------------------------------------------------------------------===//
- // CallableOpInterface
- //===--------------------------------------------------------------------===//
-
- /// Returns the region on the current operation that is callable. This may
- /// return null in the case of an external callable object, e.g. an external
- /// function.
- Region *getCallableRegion() { return isExternal() ? nullptr : &getBody(); }
-
- /// Returns the results types that the callable region produces when executed.
- ArrayRef<Type> getCallableResults() { return getType().getResults(); }
-
- //===--------------------------------------------------------------------===//
- // SymbolOpInterface Methods
- //===--------------------------------------------------------------------===//
-
- bool isDeclaration() { return isExternal(); }
-
-private:
- // This trait needs access to the hooks defined below.
- friend class OpTrait::FunctionLike<FuncOp>;
-
- /// Returns the number of arguments. This is a hook for OpTrait::FunctionLike.
- unsigned getNumFuncArguments() { return getType().getInputs().size(); }
-
- /// Returns the number of results. This is a hook for OpTrait::FunctionLike.
- unsigned getNumFuncResults() { return getType().getResults().size(); }
-
- /// Hook for OpTrait::FunctionLike, called after verifying that the 'type'
- /// attribute is present and checks if it holds a function type. Ensures
- /// getType, getNumFuncArguments, and getNumFuncResults can be called safely.
- LogicalResult verifyType() {
- auto type = getTypeAttr().getValue();
- if (!type.isa<FunctionType>())
- return emitOpError("requires '" + getTypeAttrName() +
- "' attribute of function type");
- return success();
- }
-};
-} // end namespace mlir
-
-namespace llvm {
-
-// Functions hash just like pointers.
-template <> struct DenseMapInfo<mlir::FuncOp> {
- static mlir::FuncOp getEmptyKey() {
- auto pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
- return mlir::FuncOp::getFromOpaquePointer(pointer);
- }
- static mlir::FuncOp getTombstoneKey() {
- auto pointer = llvm::DenseMapInfo<void *>::getTombstoneKey();
- return mlir::FuncOp::getFromOpaquePointer(pointer);
- }
- static unsigned getHashValue(mlir::FuncOp val) {
- return hash_value(val.getAsOpaquePointer());
- }
- static bool isEqual(mlir::FuncOp LHS, mlir::FuncOp RHS) { return LHS == RHS; }
-};
-
-/// Allow stealing the low bits of FuncOp.
-template <> struct PointerLikeTypeTraits<mlir::FuncOp> {
-public:
- static inline void *getAsVoidPointer(mlir::FuncOp I) {
- return const_cast<void *>(I.getAsOpaquePointer());
- }
- static inline mlir::FuncOp getFromVoidPointer(void *P) {
- return mlir::FuncOp::getFromOpaquePointer(P);
- }
- static constexpr int NumLowBitsAvailable = 3;
-};
-
-} // namespace llvm
+// TODO: This is a temporary forward until Function.h is removed.
+#include "mlir/IR/BuiltinDialect.h"
#endif // MLIR_IR_FUNCTION_H
diff --git a/mlir/include/mlir/IR/Module.h b/mlir/include/mlir/IR/Module.h
index 8a5101337586..facbaff5a033 100644
--- a/mlir/include/mlir/IR/Module.h
+++ b/mlir/include/mlir/IR/Module.h
@@ -13,138 +13,7 @@
#ifndef MLIR_IR_MODULE_H
#define MLIR_IR_MODULE_H
-#include "mlir/IR/OwningOpRefBase.h"
-#include "mlir/IR/SymbolTable.h"
-#include "llvm/Support/PointerLikeTypeTraits.h"
-
-namespace mlir {
-class ModuleTerminatorOp;
-
-//===----------------------------------------------------------------------===//
-// Module Operation.
-//===----------------------------------------------------------------------===//
-
-/// ModuleOp represents a module, or an operation containing one region with a
-/// single block containing opaque operations. The region of a module is not
-/// allowed to implicitly capture global values, and all external references
-/// must use symbolic references via attributes(e.g. via a string name).
-class ModuleOp
- : public Op<
- ModuleOp, OpTrait::ZeroOperands, OpTrait::ZeroResult,
- OpTrait::IsIsolatedFromAbove, OpTrait::AffineScope,
- OpTrait::SymbolTable,
- OpTrait::SingleBlockImplicitTerminator<ModuleTerminatorOp>::Impl,
- SymbolOpInterface::Trait, OpTrait::NoRegionArguments> {
-public:
- using Op::Op;
- using Op::print;
-
- static StringRef getOperationName() { return "module"; }
-
- static void build(OpBuilder &builder, OperationState &result,
- Optional<StringRef> name = llvm::None);
-
- /// Construct a module from the given location with an optional name.
- static ModuleOp create(Location loc, Optional<StringRef> name = llvm::None);
-
- /// Operation hooks.
- static ParseResult parse(OpAsmParser &parser, OperationState &result);
- void print(OpAsmPrinter &p);
- LogicalResult verify();
-
- /// Return body of this module.
- Region &getBodyRegion();
- Block *getBody();
-
- /// Return the name of this module if present.
- Optional<StringRef> getName();
-
- /// Print the this module in the custom top-level form.
- void print(raw_ostream &os, OpPrintingFlags flags = llvm::None);
- void print(raw_ostream &os, AsmState &state,
- OpPrintingFlags flags = llvm::None);
- void dump();
-
- //===--------------------------------------------------------------------===//
- // Body Management.
- //===--------------------------------------------------------------------===//
-
- /// Iteration over the operations in the module.
- using iterator = Block::iterator;
-
- iterator begin() { return getBody()->begin(); }
- iterator end() { return getBody()->end(); }
- Operation &front() { return *begin(); }
-
- /// This returns a range of operations of the given type 'T' held within the
- /// module.
- template <typename T> iterator_range<Block::op_iterator<T>> getOps() {
- return getBody()->getOps<T>();
- }
-
- /// Insert the operation into the back of the body, before the terminator.
- void push_back(Operation *op) {
- insert(Block::iterator(getBody()->getTerminator()), op);
- }
-
- /// Insert the operation at the given insertion point. Note: The operation is
- /// never inserted after the terminator, even if the insertion point is end().
- void insert(Operation *insertPt, Operation *op) {
- insert(Block::iterator(insertPt), op);
- }
- void insert(Block::iterator insertPt, Operation *op) {
- auto *body = getBody();
- if (insertPt == body->end())
- insertPt = Block::iterator(body->getTerminator());
- body->getOperations().insert(insertPt, op);
- }
-
- //===--------------------------------------------------------------------===//
- // SymbolOpInterface Methods
- //===--------------------------------------------------------------------===//
-
- /// A ModuleOp may optionally define a symbol.
- bool isOptionalSymbol() { return true; }
-};
-
-/// The ModuleTerminatorOp is a special terminator operation for the body of a
-/// ModuleOp, it has no semantic meaning beyond keeping the body of a ModuleOp
-/// well-formed.
-///
-/// This operation does _not_ have a custom syntax. However, ModuleOp will omit
-/// the terminator in their custom syntax for brevity.
-class ModuleTerminatorOp
- : public Op<ModuleTerminatorOp, OpTrait::ZeroOperands, OpTrait::ZeroResult,
- OpTrait::HasParent<ModuleOp>::Impl, OpTrait::IsTerminator> {
-public:
- using Op::Op;
- static StringRef getOperationName() { return "module_terminator"; }
- static void build(OpBuilder &, OperationState &) {}
-};
-
-/// This class acts as an owning reference to a module, and will automatically
-/// destroy the held module on destruction if the held module is valid.
-class OwningModuleRef : public OwningOpRefBase<ModuleOp> {
-public:
- using OwningOpRefBase<ModuleOp>::OwningOpRefBase;
-};
-
-} // end namespace mlir
-
-namespace llvm {
-
-/// Allow stealing the low bits of ModuleOp.
-template <> struct PointerLikeTypeTraits<mlir::ModuleOp> {
-public:
- static inline void *getAsVoidPointer(mlir::ModuleOp I) {
- return const_cast<void *>(I.getAsOpaquePointer());
- }
- static inline mlir::ModuleOp getFromVoidPointer(void *P) {
- return mlir::ModuleOp::getFromOpaquePointer(P);
- }
- static constexpr int NumLowBitsAvailable = 3;
-};
-
-} // end namespace llvm
+// TODO: This is a temporary forward until Module.h is removed.
+#include "mlir/IR/BuiltinDialect.h"
#endif // MLIR_IR_MODULE_H
diff --git a/mlir/include/mlir/IR/OpDefinition.h b/mlir/include/mlir/IR/OpDefinition.h
index d673b2b8161a..e594c7ff1d20 100644
--- a/mlir/include/mlir/IR/OpDefinition.h
+++ b/mlir/include/mlir/IR/OpDefinition.h
@@ -786,6 +786,132 @@ class VariadicSuccessors
: public detail::MultiSuccessorTraitBase<ConcreteType, VariadicSuccessors> {
};
+//===----------------------------------------------------------------------===//
+// SingleBlockImplicitTerminator
+
+/// This class provides APIs and verifiers for ops with regions having a single
+/// block that must terminate with `TerminatorOpType`.
+template <typename TerminatorOpType>
+struct SingleBlockImplicitTerminator {
+ template <typename ConcreteType>
+ class Impl : public TraitBase<ConcreteType, Impl> {
+ private:
+ /// Builds a terminator operation without relying on OpBuilder APIs to avoid
+ /// cyclic header inclusion.
+ static Operation *buildTerminator(OpBuilder &builder, Location loc) {
+ OperationState state(loc, TerminatorOpType::getOperationName());
+ TerminatorOpType::build(builder, state);
+ return Operation::create(state);
+ }
+
+ public:
+ static LogicalResult verifyTrait(Operation *op) {
+ for (unsigned i = 0, e = op->getNumRegions(); i < e; ++i) {
+ Region ®ion = op->getRegion(i);
+
+ // Empty regions are fine.
+ if (region.empty())
+ continue;
+
+ // Non-empty regions must contain a single basic block.
+ if (std::next(region.begin()) != region.end())
+ return op->emitOpError("expects region #")
+ << i << " to have 0 or 1 blocks";
+
+ Block &block = region.front();
+ if (block.empty())
+ return op->emitOpError() << "expects a non-empty block";
+ Operation &terminator = block.back();
+ if (isa<TerminatorOpType>(terminator))
+ continue;
+
+ return op->emitOpError("expects regions to end with '" +
+ TerminatorOpType::getOperationName() +
+ "', found '" +
+ terminator.getName().getStringRef() + "'")
+ .attachNote()
+ << "in custom textual format, the absence of terminator implies "
+ "'"
+ << TerminatorOpType::getOperationName() << '\'';
+ }
+
+ return success();
+ }
+
+ /// Ensure that the given region has the terminator required by this trait.
+ /// If OpBuilder is provided, use it to build the terminator and notify the
+ /// OpBuilder litsteners accordingly. If only a Builder is provided, locally
+ /// construct an OpBuilder with no listeners; this should only be used if no
+ /// OpBuilder is available at the call site, e.g., in the parser.
+ static void ensureTerminator(Region ®ion, Builder &builder,
+ Location loc) {
+ ::mlir::impl::ensureRegionTerminator(region, builder, loc,
+ buildTerminator);
+ }
+ static void ensureTerminator(Region ®ion, OpBuilder &builder,
+ Location loc) {
+ ::mlir::impl::ensureRegionTerminator(region, builder, loc,
+ buildTerminator);
+ }
+
+ Block *getBody(unsigned idx = 0) {
+ Region ®ion = this->getOperation()->getRegion(idx);
+ assert(!region.empty() && "unexpected empty region");
+ return ®ion.front();
+ }
+ Region &getBodyRegion(unsigned idx = 0) {
+ return this->getOperation()->getRegion(idx);
+ }
+
+ //===------------------------------------------------------------------===//
+ // Single Region Utilities
+ //===------------------------------------------------------------------===//
+
+ /// The following are a set of methods only enabled when the parent
+ /// operation has a single region. Each of these methods take an additional
+ /// template parameter that represents the concrete operation so that we
+ /// can use SFINAE to disable the methods for non-single region operations.
+ template <typename OpT, typename T = void>
+ using enable_if_single_region =
+ typename std::enable_if_t<OpT::template hasTrait<OneRegion>(), T>;
+
+ template <typename OpT = ConcreteType>
+ enable_if_single_region<OpT, Block::iterator> begin() {
+ return getBody()->begin();
+ }
+ template <typename OpT = ConcreteType>
+ enable_if_single_region<OpT, Block::iterator> end() {
+ return getBody()->end();
+ }
+ template <typename OpT = ConcreteType>
+ enable_if_single_region<OpT, Operation &> front() {
+ return *begin();
+ }
+
+ /// Insert the operation into the back of the body, before the terminator.
+ template <typename OpT = ConcreteType>
+ enable_if_single_region<OpT> push_back(Operation *op) {
+ insert(Block::iterator(getBody()->getTerminator()), op);
+ }
+
+ /// Insert the operation at the given insertion point. Note: The operation
+ /// is never inserted after the terminator, even if the insertion point is
+ /// end().
+ template <typename OpT = ConcreteType>
+ enable_if_single_region<OpT> insert(Operation *insertPt, Operation *op) {
+ insert(Block::iterator(insertPt), op);
+ }
+ template <typename OpT = ConcreteType>
+ enable_if_single_region<OpT> insert(Block::iterator insertPt,
+ Operation *op) {
+ auto *body = getBody();
+ if (insertPt == body->end())
+ insertPt = Block::iterator(body->getTerminator());
+ body->getOperations().insert(insertPt, op);
+ }
+ };
+};
+
//===----------------------------------------------------------------------===//
// Misc Traits
@@ -1036,78 +1162,6 @@ class AutomaticAllocationScope
}
};
-/// This class provides APIs and verifiers for ops with regions having a single
-/// block that must terminate with `TerminatorOpType`.
-template <typename TerminatorOpType> struct SingleBlockImplicitTerminator {
- template <typename ConcreteType>
- class Impl : public TraitBase<ConcreteType, Impl> {
- private:
- /// Builds a terminator operation without relying on OpBuilder APIs to avoid
- /// cyclic header inclusion.
- static Operation *buildTerminator(OpBuilder &builder, Location loc) {
- OperationState state(loc, TerminatorOpType::getOperationName());
- TerminatorOpType::build(builder, state);
- return Operation::create(state);
- }
-
- public:
- static LogicalResult verifyTrait(Operation *op) {
- for (unsigned i = 0, e = op->getNumRegions(); i < e; ++i) {
- Region ®ion = op->getRegion(i);
-
- // Empty regions are fine.
- if (region.empty())
- continue;
-
- // Non-empty regions must contain a single basic block.
- if (std::next(region.begin()) != region.end())
- return op->emitOpError("expects region #")
- << i << " to have 0 or 1 blocks";
-
- Block &block = region.front();
- if (block.empty())
- return op->emitOpError() << "expects a non-empty block";
- Operation &terminator = block.back();
- if (isa<TerminatorOpType>(terminator))
- continue;
-
- return op->emitOpError("expects regions to end with '" +
- TerminatorOpType::getOperationName() +
- "', found '" +
- terminator.getName().getStringRef() + "'")
- .attachNote()
- << "in custom textual format, the absence of terminator implies "
- "'"
- << TerminatorOpType::getOperationName() << '\'';
- }
-
- return success();
- }
-
- /// Ensure that the given region has the terminator required by this trait.
- /// If OpBuilder is provided, use it to build the terminator and notify the
- /// OpBuilder litsteners accordingly. If only a Builder is provided, locally
- /// construct an OpBuilder with no listeners; this should only be used if no
- /// OpBuilder is available at the call site, e.g., in the parser.
- static void ensureTerminator(Region ®ion, Builder &builder,
- Location loc) {
- ::mlir::impl::ensureRegionTerminator(region, builder, loc,
- buildTerminator);
- }
- static void ensureTerminator(Region ®ion, OpBuilder &builder,
- Location loc) {
- ::mlir::impl::ensureRegionTerminator(region, builder, loc,
- buildTerminator);
- }
-
- Block *getBody(unsigned idx = 0) {
- Region ®ion = this->getOperation()->getRegion(idx);
- assert(!region.empty() && "unexpected empty region");
- return ®ion.front();
- }
- };
-};
-
/// This class provides a verifier for ops that are expecting their parent
/// to be one of the given parent ops
template <typename... ParentOpTypes>
diff --git a/mlir/include/mlir/IR/Operation.h b/mlir/include/mlir/IR/Operation.h
index fa54cb608cf5..5b3c44868db2 100644
--- a/mlir/include/mlir/IR/Operation.h
+++ b/mlir/include/mlir/IR/Operation.h
@@ -147,9 +147,9 @@ class Operation final
void replaceUsesOfWith(Value from, Value to);
/// Replace all uses of results of this operation with the provided 'values'.
- template <typename ValuesT,
- typename = decltype(std::declval<ValuesT>().begin())>
- void replaceAllUsesWith(ValuesT &&values) {
+ template <typename ValuesT>
+ std::enable_if_t<!std::is_convertible<ValuesT, Operation *>::value>
+ replaceAllUsesWith(ValuesT &&values) {
assert(std::distance(values.begin(), values.end()) == getNumResults() &&
"expected 'values' to correspond 1-1 with the number of results");
diff --git a/mlir/lib/IR/Function.cpp b/mlir/lib/IR/BuiltinDialect.cpp
similarity index 54%
rename from mlir/lib/IR/Function.cpp
rename to mlir/lib/IR/BuiltinDialect.cpp
index 03378f21f638..ca080eb17e67 100644
--- a/mlir/lib/IR/Function.cpp
+++ b/mlir/lib/IR/BuiltinDialect.cpp
@@ -1,4 +1,4 @@
-//===- Function.cpp - MLIR Function Classes -------------------------------===//
+//===- BuiltinDialect.cpp - MLIR Builtin Dialect --------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -6,19 +6,65 @@
//
//===----------------------------------------------------------------------===//
-#include "mlir/IR/Function.h"
+#include "mlir/IR/BuiltinDialect.h"
#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/FunctionImplementation.h"
-#include "llvm/ADT/BitVector.h"
+#include "mlir/IR/OpImplementation.h"
+#include "mlir/IR/StandardTypes.h"
#include "llvm/ADT/MapVector.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/Twine.h"
using namespace mlir;
//===----------------------------------------------------------------------===//
-// Function Operation.
+// Builtin Dialect
+//===----------------------------------------------------------------------===//
+
+namespace {
+struct BuiltinOpAsmDialectInterface : public OpAsmDialectInterface {
+ using OpAsmDialectInterface::OpAsmDialectInterface;
+
+ LogicalResult getAlias(Attribute attr, raw_ostream &os) const override {
+ if (attr.isa<AffineMapAttr>()) {
+ os << "map";
+ return success();
+ }
+ if (attr.isa<IntegerSetAttr>()) {
+ os << "set";
+ return success();
+ }
+ if (attr.isa<LocationAttr>()) {
+ os << "loc";
+ return success();
+ }
+ return failure();
+ }
+};
+} // end anonymous namespace.
+
+/// A builtin dialect to define types/etc that are necessary for the validity of
+/// the IR.
+void BuiltinDialect::initialize() {
+ addTypes<ComplexType, BFloat16Type, Float16Type, Float32Type, Float64Type,
+ FunctionType, IndexType, IntegerType, MemRefType, UnrankedMemRefType,
+ NoneType, OpaqueType, RankedTensorType, TupleType,
+ UnrankedTensorType, VectorType>();
+ addAttributes<AffineMapAttr, ArrayAttr, DenseIntOrFPElementsAttr,
+ DenseStringElementsAttr, DictionaryAttr, FloatAttr,
+ SymbolRefAttr, IntegerAttr, IntegerSetAttr, OpaqueAttr,
+ OpaqueElementsAttr, SparseElementsAttr, StringAttr, TypeAttr,
+ UnitAttr>();
+ addAttributes<CallSiteLoc, FileLineColLoc, FusedLoc, NameLoc, OpaqueLoc,
+ UnknownLoc>();
+ addOperations<
+#define GET_OP_LIST
+#include "mlir/IR/BuiltinOps.cpp.inc"
+ >();
+ addInterfaces<BuiltinOpAsmDialectInterface>();
+}
+
+//===----------------------------------------------------------------------===//
+// FuncOp
//===----------------------------------------------------------------------===//
FuncOp FuncOp::create(Location location, StringRef name, FunctionType type,
@@ -41,14 +87,14 @@ FuncOp FuncOp::create(Location location, StringRef name, FunctionType type,
return func;
}
-void FuncOp::build(OpBuilder &builder, OperationState &result, StringRef name,
+void FuncOp::build(OpBuilder &builder, OperationState &state, StringRef name,
FunctionType type, ArrayRef<NamedAttribute> attrs,
ArrayRef<MutableDictionaryAttr> argAttrs) {
- result.addAttribute(SymbolTable::getSymbolAttrName(),
- builder.getStringAttr(name));
- result.addAttribute(getTypeAttrName(), TypeAttr::get(type));
- result.attributes.append(attrs.begin(), attrs.end());
- result.addRegion();
+ state.addAttribute(SymbolTable::getSymbolAttrName(),
+ builder.getStringAttr(name));
+ state.addAttribute(getTypeAttrName(), TypeAttr::get(type));
+ state.attributes.append(attrs.begin(), attrs.end());
+ state.addRegion();
if (argAttrs.empty())
return;
@@ -56,12 +102,10 @@ void FuncOp::build(OpBuilder &builder, OperationState &result, StringRef name,
SmallString<8> argAttrName;
for (unsigned i = 0, e = type.getNumInputs(); i != e; ++i)
if (auto argDict = argAttrs[i].getDictionary(builder.getContext()))
- result.addAttribute(getArgAttrName(i, argAttrName), argDict);
+ state.addAttribute(getArgAttrName(i, argAttrName), argDict);
}
-/// Parsing/Printing methods.
-
-ParseResult FuncOp::parse(OpAsmParser &parser, OperationState &result) {
+static ParseResult parseFuncOp(OpAsmParser &parser, OperationState &result) {
auto buildFuncType = [](Builder &builder, ArrayRef<Type> argTypes,
ArrayRef<Type> results, impl::VariadicFlag,
std::string &) {
@@ -72,25 +116,25 @@ ParseResult FuncOp::parse(OpAsmParser &parser, OperationState &result) {
buildFuncType);
}
-void FuncOp::print(OpAsmPrinter &p) {
- FunctionType fnType = getType();
- impl::printFunctionLikeOp(p, *this, fnType.getInputs(), /*isVariadic=*/false,
+static void print(FuncOp op, OpAsmPrinter &p) {
+ FunctionType fnType = op.getType();
+ impl::printFunctionLikeOp(p, op, fnType.getInputs(), /*isVariadic=*/false,
fnType.getResults());
}
-LogicalResult FuncOp::verify() {
+static LogicalResult verify(FuncOp op) {
// If this function is external there is nothing to do.
- if (isExternal())
+ if (op.isExternal())
return success();
// Verify that the argument list of the function and the arg list of the entry
// block line up. The trait already verified that the number of arguments is
// the same between the signature and the block.
- auto fnInputTypes = getType().getInputs();
- Block &entryBlock = front();
+ auto fnInputTypes = op.getType().getInputs();
+ Block &entryBlock = op.front();
for (unsigned i = 0, e = entryBlock.getNumArguments(); i != e; ++i)
if (fnInputTypes[i] != entryBlock.getArgument(i).getType())
- return emitOpError("type of entry block argument #")
+ return op.emitOpError("type of entry block argument #")
<< i << '(' << entryBlock.getArgument(i).getType()
<< ") must match the type of the corresponding argument in "
<< "function signature(" << fnInputTypes[i] << ')';
@@ -152,3 +196,46 @@ FuncOp FuncOp::clone() {
BlockAndValueMapping mapper;
return clone(mapper);
}
+
+//===----------------------------------------------------------------------===//
+// ModuleOp
+//===----------------------------------------------------------------------===//
+
+void ModuleOp::build(OpBuilder &builder, OperationState &state,
+ Optional<StringRef> name) {
+ ensureTerminator(*state.addRegion(), builder, state.location);
+ if (name) {
+ state.attributes.push_back(builder.getNamedAttr(
+ mlir::SymbolTable::getSymbolAttrName(), builder.getStringAttr(*name)));
+ }
+}
+
+/// Construct a module from the given context.
+ModuleOp ModuleOp::create(Location loc, Optional<StringRef> name) {
+ OpBuilder builder(loc->getContext());
+ return builder.create<ModuleOp>(loc, name);
+}
+
+static LogicalResult verify(ModuleOp op) {
+ // Check that none of the attributes are non-dialect attributes, except for
+ // the symbol related attributes.
+ for (auto attr : op.getAttrs()) {
+ if (!attr.first.strref().contains('.') &&
+ !llvm::is_contained(
+ ArrayRef<StringRef>{mlir::SymbolTable::getSymbolAttrName(),
+ mlir::SymbolTable::getVisibilityAttrName()},
+ attr.first.strref()))
+ return op.emitOpError()
+ << "can only contain dialect-specific attributes, found: '"
+ << attr.first << "'";
+ }
+
+ return success();
+}
+
+//===----------------------------------------------------------------------===//
+// TableGen'd op method definitions
+//===----------------------------------------------------------------------===//
+
+#define GET_OP_CLASSES
+#include "mlir/IR/BuiltinOps.cpp.inc"
diff --git a/mlir/lib/IR/CMakeLists.txt b/mlir/lib/IR/CMakeLists.txt
index 1305e1156490..5a8d3e20df6a 100644
--- a/mlir/lib/IR/CMakeLists.txt
+++ b/mlir/lib/IR/CMakeLists.txt
@@ -5,16 +5,15 @@ add_mlir_library(MLIRIR
Attributes.cpp
Block.cpp
Builders.cpp
+ BuiltinDialect.cpp
Diagnostics.cpp
Dialect.cpp
Dominance.cpp
- Function.cpp
FunctionImplementation.cpp
FunctionSupport.cpp
IntegerSet.cpp
Location.cpp
MLIRContext.cpp
- Module.cpp
Operation.cpp
OperationSupport.cpp
PatternMatch.cpp
@@ -33,10 +32,11 @@ add_mlir_library(MLIRIR
${MLIR_MAIN_INCLUDE_DIR}/mlir/IR
DEPENDS
+ MLIRBuiltinOpsIncGen
MLIRCallInterfacesIncGen
MLIROpAsmInterfaceIncGen
- MLIRSymbolInterfacesIncGen
MLIRRegionKindInterfaceIncGen
+ MLIRSymbolInterfacesIncGen
LINK_LIBS PUBLIC
MLIRSupport
diff --git a/mlir/lib/IR/MLIRContext.cpp b/mlir/lib/IR/MLIRContext.cpp
index cdebb2a5a8d0..a803914c7c33 100644
--- a/mlir/lib/IR/MLIRContext.cpp
+++ b/mlir/lib/IR/MLIRContext.cpp
@@ -82,57 +82,6 @@ void mlir::registerMLIRContextCLOptions() {
*clOptions;
}
-//===----------------------------------------------------------------------===//
-// Builtin Dialect
-//===----------------------------------------------------------------------===//
-
-namespace {
-struct BuiltinOpAsmDialectInterface : public OpAsmDialectInterface {
- using OpAsmDialectInterface::OpAsmDialectInterface;
-
- LogicalResult getAlias(Attribute attr, raw_ostream &os) const override {
- if (attr.isa<AffineMapAttr>()) {
- os << "map";
- return success();
- }
- if (attr.isa<IntegerSetAttr>()) {
- os << "set";
- return success();
- }
- if (attr.isa<LocationAttr>()) {
- os << "loc";
- return success();
- }
- return failure();
- }
-};
-
-/// A builtin dialect to define types/etc that are necessary for the validity of
-/// the IR.
-struct BuiltinDialect : public Dialect {
- BuiltinDialect(MLIRContext *context)
- : Dialect(/*name=*/"", context, TypeID::get<BuiltinDialect>()) {
- addTypes<ComplexType, BFloat16Type, Float16Type, Float32Type, Float64Type,
- FunctionType, IndexType, IntegerType, MemRefType,
- UnrankedMemRefType, NoneType, OpaqueType, RankedTensorType,
- TupleType, UnrankedTensorType, VectorType>();
- addAttributes<AffineMapAttr, ArrayAttr, DenseIntOrFPElementsAttr,
- DenseStringElementsAttr, DictionaryAttr, FloatAttr,
- SymbolRefAttr, IntegerAttr, IntegerSetAttr, OpaqueAttr,
- OpaqueElementsAttr, SparseElementsAttr, StringAttr, TypeAttr,
- UnitAttr>();
- addAttributes<CallSiteLoc, FileLineColLoc, FusedLoc, NameLoc, OpaqueLoc,
- UnknownLoc>();
- addInterfaces<BuiltinOpAsmDialectInterface>();
-
- // TODO: These operations should be moved to a
diff erent dialect when they
- // have been fully decoupled from the core.
- addOperations<FuncOp, ModuleOp, ModuleTerminatorOp>();
- }
- static StringRef getDialectNamespace() { return ""; }
-};
-} // end anonymous namespace.
-
//===----------------------------------------------------------------------===//
// Locking Utilities
//===----------------------------------------------------------------------===//
diff --git a/mlir/lib/IR/Module.cpp b/mlir/lib/IR/Module.cpp
deleted file mode 100644
index 1f1e3aa2d56e..000000000000
--- a/mlir/lib/IR/Module.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-//===- Module.cpp - MLIR Module Operation ---------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "mlir/IR/Module.h"
-#include "mlir/IR/Builders.h"
-#include "mlir/IR/OpImplementation.h"
-
-using namespace mlir;
-
-//===----------------------------------------------------------------------===//
-// Module Operation.
-//===----------------------------------------------------------------------===//
-
-void ModuleOp::build(OpBuilder &builder, OperationState &result,
- Optional<StringRef> name) {
- ensureTerminator(*result.addRegion(), builder, result.location);
- if (name)
- result.attributes.push_back(builder.getNamedAttr(
- mlir::SymbolTable::getSymbolAttrName(), builder.getStringAttr(*name)));
-}
-
-/// Construct a module from the given context.
-ModuleOp ModuleOp::create(Location loc, Optional<StringRef> name) {
- OperationState state(loc, "module");
- OpBuilder builder(loc->getContext());
- ModuleOp::build(builder, state, name);
- return cast<ModuleOp>(Operation::create(state));
-}
-
-ParseResult ModuleOp::parse(OpAsmParser &parser, OperationState &result) {
- // If the name is present, parse it.
- StringAttr nameAttr;
- (void)parser.parseOptionalSymbolName(
- nameAttr, mlir::SymbolTable::getSymbolAttrName(), result.attributes);
-
- // If module attributes are present, parse them.
- if (parser.parseOptionalAttrDictWithKeyword(result.attributes))
- return failure();
-
- // Parse the module body.
- auto *body = result.addRegion();
- if (parser.parseRegion(*body, llvm::None, llvm::None))
- return failure();
-
- // Ensure that this module has a valid terminator.
- ensureTerminator(*body, parser.getBuilder(), result.location);
- return success();
-}
-
-void ModuleOp::print(OpAsmPrinter &p) {
- p << "module";
-
- if (Optional<StringRef> name = getName()) {
- p << ' ';
- p.printSymbolName(*name);
- }
-
- // Print the module attributes.
- p.printOptionalAttrDictWithKeyword(getAttrs(),
- {mlir::SymbolTable::getSymbolAttrName()});
-
- // Print the region.
- p.printRegion(getOperation()->getRegion(0), /*printEntryBlockArgs=*/false,
- /*printBlockTerminators=*/false);
-}
-
-LogicalResult ModuleOp::verify() {
- auto &bodyRegion = getOperation()->getRegion(0);
-
- // The body must contain a single basic block.
- if (!llvm::hasSingleElement(bodyRegion))
- return emitOpError("expected body region to have a single block");
-
- // Check that none of the attributes are non-dialect attributes, except for
- // the symbol related attributes.
- for (auto attr : getOperation()->getMutableAttrDict().getAttrs()) {
- if (!attr.first.strref().contains('.') &&
- !llvm::is_contained(
- ArrayRef<StringRef>{mlir::SymbolTable::getSymbolAttrName(),
- mlir::SymbolTable::getVisibilityAttrName()},
- attr.first.strref()))
- return emitOpError(
- "can only contain dialect-specific attributes, found: '")
- << attr.first << "'";
- }
-
- return success();
-}
-
-/// Return body of this module.
-Region &ModuleOp::getBodyRegion() { return getOperation()->getRegion(0); }
-Block *ModuleOp::getBody() { return &getBodyRegion().front(); }
-
-Optional<StringRef> ModuleOp::getName() {
- if (auto nameAttr =
- getAttrOfType<StringAttr>(mlir::SymbolTable::getSymbolAttrName()))
- return nameAttr.getValue();
- return llvm::None;
-}
diff --git a/mlir/lib/TableGen/OpClass.cpp b/mlir/lib/TableGen/OpClass.cpp
index ceb4f5ae82a3..2fad62ea81c2 100644
--- a/mlir/lib/TableGen/OpClass.cpp
+++ b/mlir/lib/TableGen/OpClass.cpp
@@ -303,9 +303,10 @@ void OpClass::writeDeclTo(raw_ostream &os) const {
os << "class " << className << " : public ::mlir::Op<" << className;
for (const auto &trait : traitsVec)
os << ", " << trait;
- os << "> {\npublic:\n";
- os << " using Op::Op;\n";
- os << " using Adaptor = " << className << "Adaptor;\n";
+ os << "> {\npublic:\n"
+ << " using Op::Op;\n"
+ << " using Op::print;\n"
+ << " using Adaptor = " << className << "Adaptor;\n";
bool hasPrivateMethod = false;
forAllMethods([&](const OpMethod &method) {
More information about the Mlir-commits
mailing list