xref: /llvm-project/mlir/include/mlir/IR/Dialect.h (revision 9ce8f4b70b31b031ac9b4818a268bfc8c67a7a8e)
19eedf6adSChris Lattner //===- Dialect.h - IR Dialect Description -----------------------*- C++ -*-===//
29eedf6adSChris Lattner //
330857107SMehdi Amini // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
456222a06SMehdi Amini // See https://llvm.org/LICENSE.txt for license information.
556222a06SMehdi Amini // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
69eedf6adSChris Lattner //
756222a06SMehdi Amini //===----------------------------------------------------------------------===//
89eedf6adSChris Lattner //
99eedf6adSChris Lattner // This file defines the 'dialect' abstraction.
109eedf6adSChris Lattner //
119eedf6adSChris Lattner //===----------------------------------------------------------------------===//
129eedf6adSChris Lattner 
139eedf6adSChris Lattner #ifndef MLIR_IR_DIALECT_H
149eedf6adSChris Lattner #define MLIR_IR_DIALECT_H
159eedf6adSChris Lattner 
1677eee579SRiver Riddle #include "mlir/IR/DialectRegistry.h"
179eedf6adSChris Lattner #include "mlir/IR/OperationSupport.h"
18575b22b5SMehdi Amini #include "mlir/Support/TypeID.h"
199eedf6adSChris Lattner 
209eedf6adSChris Lattner namespace mlir {
21445cc3f6SRiver Riddle class DialectAsmParser;
22445cc3f6SRiver Riddle class DialectAsmPrinter;
2392a7b108SRiver Riddle class DialectInterface;
24bcacef1aSRiver Riddle class OpBuilder;
258abc06f3SRiver Riddle class Type;
269eedf6adSChris Lattner 
2777eee579SRiver Riddle //===----------------------------------------------------------------------===//
2877eee579SRiver Riddle // Dialect
2977eee579SRiver Riddle //===----------------------------------------------------------------------===//
30a9d3e5eeSFeng Liu 
31f6aceb72SMehdi Amini /// Dialects are groups of MLIR operations, types and attributes, as well as
32f6aceb72SMehdi Amini /// behavior associated with the entire group.  For example, hooks into other
33f6aceb72SMehdi Amini /// systems for constant folding, interfaces, default named types for asm
34f6aceb72SMehdi Amini /// printing, etc.
359eedf6adSChris Lattner ///
36f6aceb72SMehdi Amini /// Instances of the dialect object are loaded in a specific MLIRContext.
379eedf6adSChris Lattner ///
389eedf6adSChris Lattner class Dialect {
399eedf6adSChris Lattner public:
40a0c776fcSMehdi Amini   /// Type for a callback provided by the dialect to parse a custom operation.
41a0c776fcSMehdi Amini   /// This is used for the dialect to provide an alternative way to parse custom
42a0c776fcSMehdi Amini   /// operations, including unregistered ones.
43a0c776fcSMehdi Amini   using ParseOpHook =
44a0c776fcSMehdi Amini       function_ref<ParseResult(OpAsmParser &parser, OperationState &result)>;
45a0c776fcSMehdi Amini 
46bcacef1aSRiver Riddle   virtual ~Dialect();
47bcacef1aSRiver Riddle 
48bcacef1aSRiver Riddle   /// Utility function that returns if the given string is a valid dialect
49be0a7e9fSMehdi Amini   /// namespace
50bcacef1aSRiver Riddle   static bool isValidNamespace(StringRef str);
51bcacef1aSRiver Riddle 
529eedf6adSChris Lattner   MLIRContext *getContext() const { return context; }
539eedf6adSChris Lattner 
54dfc58742SRiver Riddle   StringRef getNamespace() const { return name; }
559eedf6adSChris Lattner 
56575b22b5SMehdi Amini   /// Returns the unique identifier that corresponds to this dialect.
57575b22b5SMehdi Amini   TypeID getTypeID() const { return dialectID; }
58575b22b5SMehdi Amini 
59082016d4SRiver Riddle   /// Returns true if this dialect allows for unregistered operations, i.e.
60082016d4SRiver Riddle   /// operations prefixed with the dialect namespace but not registered with
61082016d4SRiver Riddle   /// addOperation.
62a477fbafSChris Lattner   bool allowsUnknownOperations() const { return unknownOpsAllowed; }
63a477fbafSChris Lattner 
64a477fbafSChris Lattner   /// Return true if this dialect allows for unregistered types, i.e., types
65a477fbafSChris Lattner   /// prefixed with the dialect namespace but not registered with addType.
66a477fbafSChris Lattner   /// These are represented with OpaqueType.
67a477fbafSChris Lattner   bool allowsUnknownTypes() const { return unknownTypesAllowed; }
68082016d4SRiver Riddle 
69108ca7a7SMatthias Springer   /// Register dialect-wide canonicalization patterns. This method should only
70108ca7a7SMatthias Springer   /// be used to register canonicalization patterns that do not conceptually
71108ca7a7SMatthias Springer   /// belong to any single operation in the dialect. (In that case, use the op's
72108ca7a7SMatthias Springer   /// canonicalizer.) E.g., canonicalization patterns for op interfaces should
73108ca7a7SMatthias Springer   /// be registered here.
74108ca7a7SMatthias Springer   virtual void getCanonicalizationPatterns(RewritePatternSet &results) const {}
75108ca7a7SMatthias Springer 
76bcacef1aSRiver Riddle   /// Registered hook to materialize a single constant operation from a given
77bcacef1aSRiver Riddle   /// attribute value with the desired resultant type. This method should use
78bcacef1aSRiver Riddle   /// the provided builder to create the operation without changing the
79bcacef1aSRiver Riddle   /// insertion position. The generated operation is expected to be constant
80bcacef1aSRiver Riddle   /// like, i.e. single result, zero operands, non side-effecting, etc. On
81bcacef1aSRiver Riddle   /// success, this hook should return the value generated to represent the
82bcacef1aSRiver Riddle   /// constant value. Otherwise, it should return null on failure.
83bcacef1aSRiver Riddle   virtual Operation *materializeConstant(OpBuilder &builder, Attribute value,
84bcacef1aSRiver Riddle                                          Type type, Location loc) {
85bcacef1aSRiver Riddle     return nullptr;
86bcacef1aSRiver Riddle   }
87bcacef1aSRiver Riddle 
88bcacef1aSRiver Riddle   //===--------------------------------------------------------------------===//
89bcacef1aSRiver Riddle   // Parsing Hooks
90bcacef1aSRiver Riddle   //===--------------------------------------------------------------------===//
91bcacef1aSRiver Riddle 
92d097cc61SRiver Riddle   /// Parse an attribute registered to this dialect. If 'type' is nonnull, it
93d097cc61SRiver Riddle   /// refers to the expected type of the attribute.
942ba4d802SRiver Riddle   virtual Attribute parseAttribute(DialectAsmParser &parser, Type type) const;
958d5bd823SRiver Riddle 
96d097cc61SRiver Riddle   /// Print an attribute registered to this dialect. Note: The type of the
97d097cc61SRiver Riddle   /// attribute need not be printed by this method as it is always printed by
98d097cc61SRiver Riddle   /// the caller.
99445cc3f6SRiver Riddle   virtual void printAttribute(Attribute, DialectAsmPrinter &) const {
1008d5bd823SRiver Riddle     llvm_unreachable("dialect has no registered attribute printing hook");
1018d5bd823SRiver Riddle   }
1028d5bd823SRiver Riddle 
103b4f033f6SRiver Riddle   /// Parse a type registered to this dialect.
1042ba4d802SRiver Riddle   virtual Type parseType(DialectAsmParser &parser) const;
105b4f033f6SRiver Riddle 
106b4f033f6SRiver Riddle   /// Print a type registered to this dialect.
107445cc3f6SRiver Riddle   virtual void printType(Type, DialectAsmPrinter &) const {
1088d5bd823SRiver Riddle     llvm_unreachable("dialect has no registered type printing hook");
109b4f033f6SRiver Riddle   }
1109eedf6adSChris Lattner 
111a0c776fcSMehdi Amini   /// Return the hook to parse an operation registered to this dialect, if any.
112a0c776fcSMehdi Amini   /// By default this will lookup for registered operations and return the
113edc6c0ecSRiver Riddle   /// `parse()` method registered on the RegisteredOperationName. Dialects can
114a0c776fcSMehdi Amini   /// override this behavior and handle unregistered operations as well.
11522426110SRamkumar Ramachandra   virtual std::optional<ParseOpHook>
11622426110SRamkumar Ramachandra   getParseOperationHook(StringRef opName) const;
117a0c776fcSMehdi Amini 
118a0c776fcSMehdi Amini   /// Print an operation registered to this dialect.
119a0c776fcSMehdi Amini   /// This hook is invoked for registered operation which don't override the
120a0c776fcSMehdi Amini   /// `print()` method to define their own custom assembly.
121fd87963eSMehdi Amini   virtual llvm::unique_function<void(Operation *, OpAsmPrinter &printer)>
122fd87963eSMehdi Amini   getOperationPrinter(Operation *op) const;
123a0c776fcSMehdi Amini 
124bcacef1aSRiver Riddle   //===--------------------------------------------------------------------===//
125bcacef1aSRiver Riddle   // Verification Hooks
126bcacef1aSRiver Riddle   //===--------------------------------------------------------------------===//
127bcacef1aSRiver Riddle 
128a495f960SRiver Riddle   /// Verify an attribute from this dialect on the argument at 'argIndex' for
129136ccd49SRiver Riddle   /// the region at 'regionIndex' on the given operation. Returns failure if
130136ccd49SRiver Riddle   /// the verification failed, success otherwise. This hook may optionally be
131136ccd49SRiver Riddle   /// invoked from any operation containing a region.
132136ccd49SRiver Riddle   virtual LogicalResult verifyRegionArgAttribute(Operation *,
133136ccd49SRiver Riddle                                                  unsigned regionIndex,
134136ccd49SRiver Riddle                                                  unsigned argIndex,
13554cd6a7eSRiver Riddle                                                  NamedAttribute);
136a495f960SRiver Riddle 
1379c9a7e92SSean Silva   /// Verify an attribute from this dialect on the result at 'resultIndex' for
1389c9a7e92SSean Silva   /// the region at 'regionIndex' on the given operation. Returns failure if
1399c9a7e92SSean Silva   /// the verification failed, success otherwise. This hook may optionally be
1409c9a7e92SSean Silva   /// invoked from any operation containing a region.
1419c9a7e92SSean Silva   virtual LogicalResult verifyRegionResultAttribute(Operation *,
1429c9a7e92SSean Silva                                                     unsigned regionIndex,
1439c9a7e92SSean Silva                                                     unsigned resultIndex,
1449c9a7e92SSean Silva                                                     NamedAttribute);
1459c9a7e92SSean Silva 
146f9d91531SRiver Riddle   /// Verify an attribute from this dialect on the given operation. Returns
1477fa28649SRiver Riddle   /// failure if the verification failed, success otherwise.
1487fa28649SRiver Riddle   virtual LogicalResult verifyOperationAttribute(Operation *, NamedAttribute) {
1497fa28649SRiver Riddle     return success();
150a495f960SRiver Riddle   }
151a495f960SRiver Riddle 
15292a7b108SRiver Riddle   //===--------------------------------------------------------------------===//
15392a7b108SRiver Riddle   // Interfaces
15492a7b108SRiver Riddle   //===--------------------------------------------------------------------===//
15592a7b108SRiver Riddle 
15692a7b108SRiver Riddle   /// Lookup an interface for the given ID if one is registered, otherwise
15792a7b108SRiver Riddle   /// nullptr.
1585f58e14bSRiver Riddle   DialectInterface *getRegisteredInterface(TypeID interfaceID) {
159a5ef51d7SRiver Riddle #ifndef NDEBUG
160d0e6fd99SFabian Mora     handleUseOfUndefinedPromisedInterface(getTypeID(), interfaceID);
161a5ef51d7SRiver Riddle #endif
162a5ef51d7SRiver Riddle 
16392a7b108SRiver Riddle     auto it = registeredInterfaces.find(interfaceID);
16492a7b108SRiver Riddle     return it != registeredInterfaces.end() ? it->getSecond().get() : nullptr;
16592a7b108SRiver Riddle   }
166b7f93c28SJeff Niu   template <typename InterfaceT>
1675f58e14bSRiver Riddle   InterfaceT *getRegisteredInterface() {
168a5ef51d7SRiver Riddle #ifndef NDEBUG
169d0e6fd99SFabian Mora     handleUseOfUndefinedPromisedInterface(getTypeID(),
170d0e6fd99SFabian Mora                                           InterfaceT::getInterfaceID(),
171a5ef51d7SRiver Riddle                                           llvm::getTypeName<InterfaceT>());
172a5ef51d7SRiver Riddle #endif
173a5ef51d7SRiver Riddle 
1745f58e14bSRiver Riddle     return static_cast<InterfaceT *>(
17592a7b108SRiver Riddle         getRegisteredInterface(InterfaceT::getInterfaceID()));
17692a7b108SRiver Riddle   }
17792a7b108SRiver Riddle 
178d905c103SMehdi Amini   /// Lookup an op interface for the given ID if one is registered, otherwise
179d905c103SMehdi Amini   /// nullptr.
180d905c103SMehdi Amini   virtual void *getRegisteredInterfaceForOp(TypeID interfaceID,
181d905c103SMehdi Amini                                             OperationName opName) {
182d905c103SMehdi Amini     return nullptr;
183d905c103SMehdi Amini   }
184d905c103SMehdi Amini   template <typename InterfaceT>
185d905c103SMehdi Amini   typename InterfaceT::Concept *
186d905c103SMehdi Amini   getRegisteredInterfaceForOp(OperationName opName) {
187d905c103SMehdi Amini     return static_cast<typename InterfaceT::Concept *>(
188d905c103SMehdi Amini         getRegisteredInterfaceForOp(InterfaceT::getInterfaceID(), opName));
189d905c103SMehdi Amini   }
190d905c103SMehdi Amini 
19177eee579SRiver Riddle   /// Register a dialect interface with this dialect instance.
19277eee579SRiver Riddle   void addInterface(std::unique_ptr<DialectInterface> interface);
19377eee579SRiver Riddle 
19477eee579SRiver Riddle   /// Register a set of dialect interfaces with this dialect instance.
19577eee579SRiver Riddle   template <typename... Args>
19677eee579SRiver Riddle   void addInterfaces() {
19726d811b3SMarkus Böck     (addInterface(std::make_unique<Args>(this)), ...);
19877eee579SRiver Riddle   }
1995f58e14bSRiver Riddle   template <typename InterfaceT, typename... Args>
2005f58e14bSRiver Riddle   InterfaceT &addInterface(Args &&...args) {
2015f58e14bSRiver Riddle     InterfaceT *interface = new InterfaceT(this, std::forward<Args>(args)...);
2025f58e14bSRiver Riddle     addInterface(std::unique_ptr<DialectInterface>(interface));
2035f58e14bSRiver Riddle     return *interface;
2045f58e14bSRiver Riddle   }
20577eee579SRiver Riddle 
206a5ef51d7SRiver Riddle   /// Declare that the given interface will be implemented, but has a delayed
207a5ef51d7SRiver Riddle   /// registration. The promised interface type can be an interface of any type
208a5ef51d7SRiver Riddle   /// not just a dialect interface, i.e. it may also be an
209a5ef51d7SRiver Riddle   /// AttributeInterface/OpInterface/TypeInterface/etc.
210*35d55f28SJustin Fargnoli   template <typename InterfaceT, typename ConcreteT>
211a5ef51d7SRiver Riddle   void declarePromisedInterface() {
212d0e6fd99SFabian Mora     unresolvedPromisedInterfaces.insert(
213d0e6fd99SFabian Mora         {TypeID::get<ConcreteT>(), InterfaceT::getInterfaceID()});
214a5ef51d7SRiver Riddle   }
215a5ef51d7SRiver Riddle 
216fb582b6aSBoian Petkantchin   // Declare the same interface for multiple types.
217fb582b6aSBoian Petkantchin   // Example:
218fb582b6aSBoian Petkantchin   // declarePromisedInterfaces<FunctionOpInterface, MyFuncType1, MyFuncType2>()
219fb582b6aSBoian Petkantchin   template <typename InterfaceT, typename... ConcreteT>
220fb582b6aSBoian Petkantchin   void declarePromisedInterfaces() {
221*35d55f28SJustin Fargnoli     (declarePromisedInterface<InterfaceT, ConcreteT>(), ...);
222fb582b6aSBoian Petkantchin   }
223fb582b6aSBoian Petkantchin 
224a5ef51d7SRiver Riddle   /// Checks if the given interface, which is attempting to be used, is a
225a5ef51d7SRiver Riddle   /// promised interface of this dialect that has yet to be implemented. If so,
226a5ef51d7SRiver Riddle   /// emits a fatal error. `interfaceName` is an optional string that contains a
227a5ef51d7SRiver Riddle   /// more user readable name for the interface (such as the class name).
228d0e6fd99SFabian Mora   void handleUseOfUndefinedPromisedInterface(TypeID interfaceRequestorID,
229d0e6fd99SFabian Mora                                              TypeID interfaceID,
230a5ef51d7SRiver Riddle                                              StringRef interfaceName = "") {
231d0e6fd99SFabian Mora     if (unresolvedPromisedInterfaces.count(
232d0e6fd99SFabian Mora             {interfaceRequestorID, interfaceID})) {
233a5ef51d7SRiver Riddle       llvm::report_fatal_error(
234a5ef51d7SRiver Riddle           "checking for an interface (`" + interfaceName +
235a5ef51d7SRiver Riddle           "`) that was promised by dialect '" + getNamespace() +
236a5ef51d7SRiver Riddle           "' but never implemented. This is generally an indication "
237a5ef51d7SRiver Riddle           "that the dialect extension implementing the interface was never "
238a5ef51d7SRiver Riddle           "registered.");
239a5ef51d7SRiver Riddle     }
240a5ef51d7SRiver Riddle   }
241d0e6fd99SFabian Mora 
242a5ef51d7SRiver Riddle   /// Checks if the given interface, which is attempting to be attached to a
243a5ef51d7SRiver Riddle   /// construct owned by this dialect, is a promised interface of this dialect
244a5ef51d7SRiver Riddle   /// that has yet to be implemented. If so, it resolves the interface promise.
245d0e6fd99SFabian Mora   void handleAdditionOfUndefinedPromisedInterface(TypeID interfaceRequestorID,
246d0e6fd99SFabian Mora                                                   TypeID interfaceID) {
247d0e6fd99SFabian Mora     unresolvedPromisedInterfaces.erase({interfaceRequestorID, interfaceID});
248d0e6fd99SFabian Mora   }
249d0e6fd99SFabian Mora 
250d0e6fd99SFabian Mora   /// Checks if a promise has been made for the interface/requestor pair.
251d0e6fd99SFabian Mora   bool hasPromisedInterface(TypeID interfaceRequestorID,
252d0e6fd99SFabian Mora                             TypeID interfaceID) const {
253d0e6fd99SFabian Mora     return unresolvedPromisedInterfaces.count(
254d0e6fd99SFabian Mora         {interfaceRequestorID, interfaceID});
255d0e6fd99SFabian Mora   }
256d0e6fd99SFabian Mora 
257d0e6fd99SFabian Mora   /// Checks if a promise has been made for the interface/requestor pair.
258d0e6fd99SFabian Mora   template <typename ConcreteT, typename InterfaceT>
259d0e6fd99SFabian Mora   bool hasPromisedInterface() const {
260d0e6fd99SFabian Mora     return hasPromisedInterface(TypeID::get<ConcreteT>(),
261d0e6fd99SFabian Mora                                 InterfaceT::getInterfaceID());
262a5ef51d7SRiver Riddle   }
263a5ef51d7SRiver Riddle 
2649eedf6adSChris Lattner protected:
265dfc58742SRiver Riddle   /// The constructor takes a unique namespace for this dialect as well as the
266dfc58742SRiver Riddle   /// context to bind to.
267dfc58742SRiver Riddle   /// Note: The namespace must not contain '.' characters.
268dfc58742SRiver Riddle   /// Note: All operations belonging to this dialect must have names starting
269dfc58742SRiver Riddle   ///       with the namespace followed by '.'.
270ae3f8a79SRiver Riddle   /// Example:
271ae3f8a79SRiver Riddle   ///       - "tf" for the TensorFlow ops like "tf.add".
272575b22b5SMehdi Amini   Dialect(StringRef name, MLIRContext *context, TypeID id);
2739eedf6adSChris Lattner 
2749eedf6adSChris Lattner   /// This method is used by derived classes to add their operations to the set.
2759eedf6adSChris Lattner   ///
276b7f93c28SJeff Niu   template <typename... Args>
277b7f93c28SJeff Niu   void addOperations() {
27826d811b3SMarkus Böck     // This initializer_list argument pack expansion is essentially equal to
27926d811b3SMarkus Böck     // using a fold expression with a comma operator. Clang however, refuses
28026d811b3SMarkus Böck     // to compile a fold expression with a depth of more than 256 by default.
28126d811b3SMarkus Böck     // There seem to be no such limitations for initializer_list.
282b870d9ecSRiver Riddle     (void)std::initializer_list<int>{
283edc6c0ecSRiver Riddle         0, (RegisteredOperationName::insert<Args>(*this), 0)...};
2849eedf6adSChris Lattner   }
2859eedf6adSChris Lattner 
286250f43d3SRiver Riddle   /// Register a set of type classes with this dialect.
287b7f93c28SJeff Niu   template <typename... Args>
288b7f93c28SJeff Niu   void addTypes() {
289e3a38a75SAndrei Golubev     // This initializer_list argument pack expansion is essentially equal to
290e3a38a75SAndrei Golubev     // using a fold expression with a comma operator. Clang however, refuses
291e3a38a75SAndrei Golubev     // to compile a fold expression with a depth of more than 256 by default.
292e3a38a75SAndrei Golubev     // There seem to be no such limitations for initializer_list.
293e3a38a75SAndrei Golubev     (void)std::initializer_list<int>{0, (addType<Args>(), 0)...};
29453a3483cSRiver Riddle   }
29553a3483cSRiver Riddle 
29698dceed6SMathieu Fehr   /// Register a type instance with this dialect.
29798dceed6SMathieu Fehr   /// The use of this method is in general discouraged in favor of
29898dceed6SMathieu Fehr   /// 'addTypes<CustomType>()'.
29998dceed6SMathieu Fehr   void addType(TypeID typeID, AbstractType &&typeInfo);
30098dceed6SMathieu Fehr 
301250f43d3SRiver Riddle   /// Register a set of attribute classes with this dialect.
302b7f93c28SJeff Niu   template <typename... Args>
303b7f93c28SJeff Niu   void addAttributes() {
304e3a38a75SAndrei Golubev     // This initializer_list argument pack expansion is essentially equal to
305e3a38a75SAndrei Golubev     // using a fold expression with a comma operator. Clang however, refuses
306e3a38a75SAndrei Golubev     // to compile a fold expression with a depth of more than 256 by default.
307e3a38a75SAndrei Golubev     // There seem to be no such limitations for initializer_list.
308e3a38a75SAndrei Golubev     (void)std::initializer_list<int>{0, (addAttribute<Args>(), 0)...};
3098abc06f3SRiver Riddle   }
3108abc06f3SRiver Riddle 
3119e0b5533SMathieu Fehr   /// Register an attribute instance with this dialect.
3129e0b5533SMathieu Fehr   /// The use of this method is in general discouraged in favor of
3139e0b5533SMathieu Fehr   /// 'addAttributes<CustomAttr>()'.
3149e0b5533SMathieu Fehr   void addAttribute(TypeID typeID, AbstractAttribute &&attrInfo);
3159e0b5533SMathieu Fehr 
316a477fbafSChris Lattner   /// Enable support for unregistered operations.
317a477fbafSChris Lattner   void allowUnknownOperations(bool allow = true) { unknownOpsAllowed = allow; }
318a477fbafSChris Lattner 
319a477fbafSChris Lattner   /// Enable support for unregistered types.
320a477fbafSChris Lattner   void allowUnknownTypes(bool allow = true) { unknownTypesAllowed = allow; }
321082016d4SRiver Riddle 
3229eedf6adSChris Lattner private:
3239eedf6adSChris Lattner   Dialect(const Dialect &) = delete;
3249eedf6adSChris Lattner   void operator=(Dialect &) = delete;
3259eedf6adSChris Lattner 
326250f43d3SRiver Riddle   /// Register an attribute instance with this dialect.
327b7f93c28SJeff Niu   template <typename T>
328b7f93c28SJeff Niu   void addAttribute() {
329250f43d3SRiver Riddle     // Add this attribute to the dialect and register it with the uniquer.
330250f43d3SRiver Riddle     addAttribute(T::getTypeID(), AbstractAttribute::get<T>(*this));
331250f43d3SRiver Riddle     detail::AttributeUniquer::registerAttribute<T>(context);
332250f43d3SRiver Riddle   }
333250f43d3SRiver Riddle 
334250f43d3SRiver Riddle   /// Register a type instance with this dialect.
335b7f93c28SJeff Niu   template <typename T>
336b7f93c28SJeff Niu   void addType() {
337250f43d3SRiver Riddle     // Add this type to the dialect and register it with the uniquer.
338250f43d3SRiver Riddle     addType(T::getTypeID(), AbstractType::get<T>(*this));
339250f43d3SRiver Riddle     detail::TypeUniquer::registerType<T>(context);
340250f43d3SRiver Riddle   }
341250f43d3SRiver Riddle 
342dfc58742SRiver Riddle   /// The namespace of this dialect.
343dfc58742SRiver Riddle   StringRef name;
3449eedf6adSChris Lattner 
345575b22b5SMehdi Amini   /// The unique identifier of the derived Op class, this is used in the context
346575b22b5SMehdi Amini   /// to allow registering multiple times the same dialect.
347575b22b5SMehdi Amini   TypeID dialectID;
348575b22b5SMehdi Amini 
3499eedf6adSChris Lattner   /// This is the context that owns this Dialect object.
3509eedf6adSChris Lattner   MLIRContext *context;
351082016d4SRiver Riddle 
352a477fbafSChris Lattner   /// Flag that specifies whether this dialect supports unregistered operations,
353a477fbafSChris Lattner   /// i.e. operations prefixed with the dialect namespace but not registered
354a477fbafSChris Lattner   /// with addOperation.
355a477fbafSChris Lattner   bool unknownOpsAllowed = false;
356a477fbafSChris Lattner 
357a477fbafSChris Lattner   /// Flag that specifies whether this dialect allows unregistered types, i.e.
358a477fbafSChris Lattner   /// types prefixed with the dialect namespace but not registered with addType.
359a477fbafSChris Lattner   /// These types are represented with OpaqueType.
360a477fbafSChris Lattner   bool unknownTypesAllowed = false;
36192a7b108SRiver Riddle 
36292a7b108SRiver Riddle   /// A collection of registered dialect interfaces.
363a517191aSRiver Riddle   DenseMap<TypeID, std::unique_ptr<DialectInterface>> registeredInterfaces;
364b72e13c2SGeoffrey Martin-Noble 
365a5ef51d7SRiver Riddle   /// A set of interfaces that the dialect (or its constructs, i.e.
366a5ef51d7SRiver Riddle   /// Attributes/Operations/Types/etc.) has promised to implement, but has yet
367a5ef51d7SRiver Riddle   /// to provide an implementation for.
368d0e6fd99SFabian Mora   DenseSet<std::pair<TypeID, TypeID>> unresolvedPromisedInterfaces;
369a5ef51d7SRiver Riddle 
3703da51522SAlex Zinenko   friend class DialectRegistry;
371575b22b5SMehdi Amini   friend class MLIRContext;
3729eedf6adSChris Lattner };
373575b22b5SMehdi Amini 
3749eedf6adSChris Lattner } // namespace mlir
3759eedf6adSChris Lattner 
37670619fa8STres Popp namespace llvm {
37770619fa8STres Popp /// Provide isa functionality for Dialects.
37858e7bf78SRiver Riddle template <typename T>
37958e7bf78SRiver Riddle struct isa_impl<T, ::mlir::Dialect,
38058e7bf78SRiver Riddle                 std::enable_if_t<std::is_base_of<::mlir::Dialect, T>::value>> {
38170619fa8STres Popp   static inline bool doit(const ::mlir::Dialect &dialect) {
382575b22b5SMehdi Amini     return mlir::TypeID::get<T>() == dialect.getTypeID();
38370619fa8STres Popp   }
38470619fa8STres Popp };
38558e7bf78SRiver Riddle template <typename T>
38658e7bf78SRiver Riddle struct isa_impl<
38758e7bf78SRiver Riddle     T, ::mlir::Dialect,
38858e7bf78SRiver Riddle     std::enable_if_t<std::is_base_of<::mlir::DialectInterface, T>::value>> {
38958e7bf78SRiver Riddle   static inline bool doit(const ::mlir::Dialect &dialect) {
39058e7bf78SRiver Riddle     return const_cast<::mlir::Dialect &>(dialect).getRegisteredInterface<T>();
39158e7bf78SRiver Riddle   }
39258e7bf78SRiver Riddle };
39358e7bf78SRiver Riddle template <typename T>
39458e7bf78SRiver Riddle struct cast_retty_impl<T, ::mlir::Dialect *> {
3955f58e14bSRiver Riddle   using ret_type = T *;
39658e7bf78SRiver Riddle };
39758e7bf78SRiver Riddle template <typename T>
39858e7bf78SRiver Riddle struct cast_retty_impl<T, ::mlir::Dialect> {
3995f58e14bSRiver Riddle   using ret_type = T &;
40058e7bf78SRiver Riddle };
40158e7bf78SRiver Riddle 
40258e7bf78SRiver Riddle template <typename T>
40358e7bf78SRiver Riddle struct cast_convert_val<T, ::mlir::Dialect, ::mlir::Dialect> {
40458e7bf78SRiver Riddle   template <typename To>
40558e7bf78SRiver Riddle   static std::enable_if_t<std::is_base_of<::mlir::Dialect, To>::value, To &>
40658e7bf78SRiver Riddle   doitImpl(::mlir::Dialect &dialect) {
40758e7bf78SRiver Riddle     return static_cast<To &>(dialect);
40858e7bf78SRiver Riddle   }
40958e7bf78SRiver Riddle   template <typename To>
41058e7bf78SRiver Riddle   static std::enable_if_t<std::is_base_of<::mlir::DialectInterface, To>::value,
4115f58e14bSRiver Riddle                           To &>
41258e7bf78SRiver Riddle   doitImpl(::mlir::Dialect &dialect) {
41358e7bf78SRiver Riddle     return *dialect.getRegisteredInterface<To>();
41458e7bf78SRiver Riddle   }
41558e7bf78SRiver Riddle 
41658e7bf78SRiver Riddle   static auto &doit(::mlir::Dialect &dialect) { return doitImpl<T>(dialect); }
41758e7bf78SRiver Riddle };
41858e7bf78SRiver Riddle template <class T>
41958e7bf78SRiver Riddle struct cast_convert_val<T, ::mlir::Dialect *, ::mlir::Dialect *> {
42058e7bf78SRiver Riddle   static auto doit(::mlir::Dialect *dialect) {
42158e7bf78SRiver Riddle     return &cast_convert_val<T, ::mlir::Dialect, ::mlir::Dialect>::doit(
42258e7bf78SRiver Riddle         *dialect);
42358e7bf78SRiver Riddle   }
42458e7bf78SRiver Riddle };
42558e7bf78SRiver Riddle 
42670619fa8STres Popp } // namespace llvm
42770619fa8STres Popp 
4289eedf6adSChris Lattner #endif
429