17 #include "llvm/ADT/MapVector.h"
18 #include "llvm/ADT/Twine.h"
19 #include "llvm/Support/Debug.h"
20 #include "llvm/Support/ManagedStatic.h"
21 #include "llvm/Support/Regex.h"
23 #define DEBUG_TYPE "dialect"
26 using namespace detail;
33 : name(name), dialectID(id), context(context) {
61 <<
"' provides no attribute parsing hook";
74 <<
"dialect '" <<
getNamespace() <<
"' provides no type parsing hook";
78 std::optional<Dialect::ParseOpHook>
86 "Dialect hook invoked on non-dialect owned operation");
93 llvm::Regex dialectNameRegex(
"^[a-zA-Z_][a-zA-Z_0-9\\$]*$");
94 return dialectNameRegex.match(str);
102 auto it = registeredInterfaces.try_emplace(interface->getID(),
103 std::move(interface));
107 llvm::dbgs() <<
"[" DEBUG_TYPE
108 "] repeated interface registration for dialect "
124 DialectInterfaceCollectionBase::DialectInterfaceCollectionBase(
128 dialect->handleUseOfUndefinedPromisedInterface(
129 dialect->getTypeID(), interfaceKind, interfaceName);
131 if (
auto *interface = dialect->getRegisteredInterface(interfaceKind)) {
132 interfaces.insert(interface);
133 orderedInterfaces.push_back(interface);
138 DialectInterfaceCollectionBase::~DialectInterfaceCollectionBase() =
default;
143 DialectInterfaceCollectionBase::getInterfaceFor(
Operation *op)
const {
155 StringRef interfaceName) {
157 interfaceID, interfaceName);
167 TypeID interfaceRequestorID,
180 auto it = registry.find(name.str());
181 if (it == registry.end())
183 return it->second.second;
188 auto inserted = registry.insert(
189 std::make_pair(std::string(name), std::make_pair(typeID, ctor)));
190 if (!inserted.second && inserted.first->second.first != typeID) {
191 llvm::report_fatal_error(
192 "Trying to register different dialects for the same namespace: " +
202 TypeID typeID = TypeID::get<void>();
205 auto constructor = [nameStr = name.str(), ctor](
MLIRContext *ctx) {
206 auto *dynDialect = ctx->getOrLoadDynamicDialect(
207 nameStr, [ctx, ctor](
DynamicDialect *dialect) { ctor(ctx, dialect); });
208 assert(dynDialect &&
"Dynamic dialect creation unexpectedly failed");
212 insert(typeID, name, constructor);
223 if (dialectNames.empty()) {
224 extension.apply(ctx, dialect);
230 if (dialectNames.size() == 1) {
231 if (dialectNames.front() == dialectName)
232 extension.apply(ctx, dialect);
237 const StringRef *nameIt = llvm::find(dialectNames, dialectName);
238 if (nameIt == dialectNames.end())
244 requiredDialects.reserve(dialectNames.size());
245 for (
auto it = dialectNames.begin(), e = dialectNames.end(); it != e;
249 requiredDialects.push_back(dialect);
256 requiredDialects.push_back(loadedDialect);
258 extension.apply(ctx, requiredDialects);
262 for (
int i = 0; i < static_cast<int>(extensions.size()); ++i)
263 applyExtension(*extensions[i]);
270 if (dialectNames.empty()) {
272 extension.apply(ctx, loadedDialects);
278 requiredDialects.reserve(dialectNames.size());
279 for (StringRef dialectName : dialectNames) {
283 requiredDialects.push_back(loadedDialect);
285 extension.apply(ctx, requiredDialects);
289 for (
int i = 0; i < static_cast<int>(extensions.size()); ++i)
290 applyExtension(*extensions[i]);
295 if (!extensions.empty())
299 registry, [&](
const auto &it) {
return rhs.registry.count(it.first); });
virtual InFlightDiagnostic emitError(SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
virtual SMLoc getNameLoc() const =0
Return the location of the original name token.
Attributes are known-constant values of operations.
The DialectAsmParser has methods for interacting with the asm parser when parsing attributes and type...
virtual StringRef getFullSymbolSpec() const =0
Returns the full specification of the symbol being parsed.
This class represents an opaque dialect extension.
virtual ~DialectExtensionBase()
This class represents an interface overridden for a single dialect.
virtual ~DialectInterface()
MLIRContext * getContext() const
Return the context that holds the parent dialect of this interface.
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
bool isSubsetOf(const DialectRegistry &rhs) const
Returns true if the current registry is a subset of 'rhs', i.e.
DialectAllocatorFunctionRef getDialectAllocator(StringRef name) const
Return an allocation function for constructing the dialect identified by its namespace,...
void insertDynamic(StringRef name, const DynamicDialectPopulationFunction &ctor)
Add a new dynamic dialect constructor in the registry.
void applyExtensions(Dialect *dialect) const
Apply any held extensions that require the given dialect.
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
virtual Type parseType(DialectAsmParser &parser) const
Parse a type registered to this dialect.
virtual std::optional< ParseOpHook > getParseOperationHook(StringRef opName) const
Return the hook to parse an operation registered to this dialect, if any.
void handleUseOfUndefinedPromisedInterface(TypeID interfaceRequestorID, TypeID interfaceID, StringRef interfaceName="")
Checks if the given interface, which is attempting to be used, is a promised interface of this dialec...
StringRef getNamespace() const
static bool isValidNamespace(StringRef str)
Utility function that returns if the given string is a valid dialect namespace.
virtual LogicalResult verifyRegionResultAttribute(Operation *, unsigned regionIndex, unsigned resultIndex, NamedAttribute)
Verify an attribute from this dialect on the result at 'resultIndex' for the region at 'regionIndex' ...
virtual LogicalResult verifyRegionArgAttribute(Operation *, unsigned regionIndex, unsigned argIndex, NamedAttribute)
Verify an attribute from this dialect on the argument at 'argIndex' for the region at 'regionIndex' o...
virtual llvm::unique_function< void(Operation *, OpAsmPrinter &printer)> getOperationPrinter(Operation *op) const
Print an operation registered to this dialect.
void handleAdditionOfUndefinedPromisedInterface(TypeID interfaceRequestorID, TypeID interfaceID)
Checks if the given interface, which is attempting to be attached to a construct owned by this dialec...
bool allowsUnknownTypes() const
Return true if this dialect allows for unregistered types, i.e., types prefixed with the dialect name...
MLIRContext * getContext() const
virtual Attribute parseAttribute(DialectAsmParser &parser, Type type) const
Parse an attribute registered to this dialect.
void addInterface(std::unique_ptr< DialectInterface > interface)
Register a dialect interface with this dialect instance.
TypeID getTypeID() const
Returns the unique identifier that corresponds to this dialect.
bool hasPromisedInterface(TypeID interfaceRequestorID, TypeID interfaceID) const
Checks if a promise has been made for the interface/requestor pair.
Dialect(StringRef name, MLIRContext *context, TypeID id)
The constructor takes a unique namespace for this dialect as well as the context to bind to.
A dialect that can be defined at runtime.
MLIRContext is the top-level object for a collection of MLIR operations.
Dialect * getLoadedDialect(StringRef name)
Get a registered IR dialect with the given namespace.
std::vector< Dialect * > getLoadedDialects()
Return information about all IR dialects loaded in the context.
NamedAttribute represents a combination of a name and an Attribute value.
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
Operation is the basic unit of execution within MLIR.
Dialect * getDialect()
Return the dialect this operation is associated with, or nullptr if the associated dialect is not loa...
This class provides an efficient unique identifier for a specific C++ type.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
bool hasPromisedInterface(Dialect &dialect, TypeID interfaceRequestorID, TypeID interfaceID)
Checks if a promise has been made for the interface/requestor pair.
void handleAdditionOfUndefinedPromisedInterface(Dialect &dialect, TypeID interfaceRequestorID, TypeID interfaceID)
Checks if the given interface, which is attempting to be attached, is a promised interface of this di...
void handleUseOfUndefinedPromisedInterface(Dialect &dialect, TypeID interfaceRequestorID, TypeID interfaceID, StringRef interfaceName)
Checks if the given interface, which is attempting to be used, is a promised interface of this dialec...
Include the generated interface declarations.
std::function< void(MLIRContext *, DynamicDialect *)> DynamicDialectPopulationFunction
std::function< Dialect *(MLIRContext *)> DialectAllocatorFunction
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
This class represents an efficient way to signal success or failure.