xref: /llvm-project-15.0.7/mlir/lib/IR/Dialect.cpp (revision 7518006d)
1 //===- Dialect.cpp - Dialect implementation -------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "mlir/IR/Dialect.h"
10 #include "mlir/IR/Diagnostics.h"
11 #include "mlir/IR/DialectImplementation.h"
12 #include "mlir/IR/DialectInterface.h"
13 #include "mlir/IR/MLIRContext.h"
14 #include "mlir/IR/Operation.h"
15 #include "llvm/ADT/MapVector.h"
16 #include "llvm/ADT/Twine.h"
17 #include "llvm/Support/ManagedStatic.h"
18 #include "llvm/Support/Regex.h"
19 
20 using namespace mlir;
21 using namespace detail;
22 
23 DialectAsmParser::~DialectAsmParser() {}
24 
25 //===----------------------------------------------------------------------===//
26 // Dialect Registration
27 //===----------------------------------------------------------------------===//
28 
29 /// Registry for all dialect allocation functions.
30 static llvm::ManagedStatic<DialectRegistry> dialectRegistry;
31 DialectRegistry &mlir::getGlobalDialectRegistry() { return *dialectRegistry; }
32 
33 void mlir::registerAllDialects(MLIRContext *context) {
34   dialectRegistry->appendTo(context->getDialectRegistry());
35 }
36 
37 Dialect *DialectRegistry::loadByName(StringRef name, MLIRContext *context) {
38   auto it = registry.find(name.str());
39   if (it == registry.end())
40     return nullptr;
41   return it->second.second(context);
42 }
43 
44 void DialectRegistry::insert(TypeID typeID, StringRef name,
45                              DialectAllocatorFunction ctor) {
46   auto inserted = registry.insert(
47       std::make_pair(std::string(name), std::make_pair(typeID, ctor)));
48   if (!inserted.second && inserted.first->second.first != typeID) {
49     llvm::report_fatal_error(
50         "Trying to register different dialects for the same namespace: " +
51         name);
52   }
53 }
54 
55 //===----------------------------------------------------------------------===//
56 // Dialect
57 //===----------------------------------------------------------------------===//
58 
59 Dialect::Dialect(StringRef name, MLIRContext *context, TypeID id)
60     : name(name), dialectID(id), context(context) {
61   assert(isValidNamespace(name) && "invalid dialect namespace");
62 }
63 
64 Dialect::~Dialect() {}
65 
66 /// Verify an attribute from this dialect on the argument at 'argIndex' for
67 /// the region at 'regionIndex' on the given operation. Returns failure if
68 /// the verification failed, success otherwise. This hook may optionally be
69 /// invoked from any operation containing a region.
70 LogicalResult Dialect::verifyRegionArgAttribute(Operation *, unsigned, unsigned,
71                                                 NamedAttribute) {
72   return success();
73 }
74 
75 /// Verify an attribute from this dialect on the result at 'resultIndex' for
76 /// the region at 'regionIndex' on the given operation. Returns failure if
77 /// the verification failed, success otherwise. This hook may optionally be
78 /// invoked from any operation containing a region.
79 LogicalResult Dialect::verifyRegionResultAttribute(Operation *, unsigned,
80                                                    unsigned, NamedAttribute) {
81   return success();
82 }
83 
84 /// Parse an attribute registered to this dialect.
85 Attribute Dialect::parseAttribute(DialectAsmParser &parser, Type type) const {
86   parser.emitError(parser.getNameLoc())
87       << "dialect '" << getNamespace()
88       << "' provides no attribute parsing hook";
89   return Attribute();
90 }
91 
92 /// Parse a type registered to this dialect.
93 Type Dialect::parseType(DialectAsmParser &parser) const {
94   // If this dialect allows unknown types, then represent this with OpaqueType.
95   if (allowsUnknownTypes()) {
96     auto ns = Identifier::get(getNamespace(), getContext());
97     return OpaqueType::get(ns, parser.getFullSymbolSpec(), getContext());
98   }
99 
100   parser.emitError(parser.getNameLoc())
101       << "dialect '" << getNamespace() << "' provides no type parsing hook";
102   return Type();
103 }
104 
105 /// Utility function that returns if the given string is a valid dialect
106 /// namespace.
107 bool Dialect::isValidNamespace(StringRef str) {
108   if (str.empty())
109     return true;
110   llvm::Regex dialectNameRegex("^[a-zA-Z_][a-zA-Z_0-9\\$]*$");
111   return dialectNameRegex.match(str);
112 }
113 
114 /// Register a set of dialect interfaces with this dialect instance.
115 void Dialect::addInterface(std::unique_ptr<DialectInterface> interface) {
116   auto it = registeredInterfaces.try_emplace(interface->getID(),
117                                              std::move(interface));
118   (void)it;
119   assert(it.second && "interface kind has already been registered");
120 }
121 
122 //===----------------------------------------------------------------------===//
123 // Dialect Interface
124 //===----------------------------------------------------------------------===//
125 
126 DialectInterface::~DialectInterface() {}
127 
128 DialectInterfaceCollectionBase::DialectInterfaceCollectionBase(
129     MLIRContext *ctx, TypeID interfaceKind) {
130   for (auto *dialect : ctx->getLoadedDialects()) {
131     if (auto *interface = dialect->getRegisteredInterface(interfaceKind)) {
132       interfaces.insert(interface);
133       orderedInterfaces.push_back(interface);
134     }
135   }
136 }
137 
138 DialectInterfaceCollectionBase::~DialectInterfaceCollectionBase() {}
139 
140 /// Get the interface for the dialect of given operation, or null if one
141 /// is not registered.
142 const DialectInterface *
143 DialectInterfaceCollectionBase::getInterfaceFor(Operation *op) const {
144   return getInterfaceFor(op->getDialect());
145 }
146