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