StringRef getNamespace() const { return name; }
+ /// Returns true if this dialect allows for unregistered operations, i.e.
+ /// operations prefixed with the dialect namespace but not registered with
+ /// addOperation.
+ bool allowsUnknownOperations() const { return allowUnknownOps; }
+
/// Registered fallback constant fold hook for the dialect. Like the constant
/// fold hook of each operation, it attempts to constant fold the operation
/// with the specified constant operand values - the elements in "operands"
// Register a type with its given unqiue type identifer.
void addType(const TypeID *const typeID);
+ // Enable support for unregistered operations.
+ void allowUnknownOperations(bool allow = true) { allowUnknownOps = allow; }
+
private:
Dialect(const Dialect &) = delete;
void operator=(Dialect &) = delete;
/// This is the context that owns this Dialect object.
MLIRContext *context;
+
+ /// Flag that toggles if this dialect supports unregistered operations, i.e.
+ /// operations prefixed with the dialect namespace but not registered with
+ /// addOperation.
+ bool allowUnknownOps;
};
using DialectAllocatorFunction = std::function<void(MLIRContext *)>;
}
/// Returns the registered dialect for a dialect-specific attribute.
- template <typename ErrorContext>
- Dialect *getDialectForAttribute(const NamedAttribute &attr,
- const ErrorContext &ctx) {
+ Dialect *getDialectForAttribute(const NamedAttribute &attr) {
assert(attr.first.strref().contains('.') && "expected dialect attribute");
auto dialectNamePair = attr.first.strref().split('.');
return fn.getContext()->getRegisteredDialect(dialectNamePair.first);
/// Regex checker for attribute names.
llvm::Regex identifierRegex;
+
+ /// Mapping between dialect namespace and if that dialect supports
+ /// unregistered operations.
+ llvm::StringMap<bool> dialectAllowsUnknownOps;
};
} // end anonymous namespace
return failure("functions may only have dialect attributes", fn);
// Verify this attribute with the defining dialect.
- if (auto *dialect = getDialectForAttribute(attr, fn))
+ if (auto *dialect = getDialectForAttribute(attr))
if (dialect->verifyFunctionAttribute(&fn, attr))
return true;
}
fn);
// Verify this attribute with the defining dialect.
- if (auto *dialect = getDialectForAttribute(attr, fn))
+ if (auto *dialect = getDialectForAttribute(attr))
if (dialect->verifyFunctionArgAttribute(&fn, i, attr))
return true;
}
// Check for any optional dialect specific attributes.
if (!attr.first.strref().contains('.'))
continue;
- if (auto *dialect = getDialectForAttribute(attr, op))
+ if (auto *dialect = getDialectForAttribute(attr))
if (dialect->verifyOperationAttribute(&op, attr))
return true;
}
// If we can get operation info for this, check the custom hook.
- if (auto *opInfo = op.getAbstractOperation()) {
- if (opInfo->verifyInvariants(&op))
- return true;
- }
+ auto *opInfo = op.getAbstractOperation();
+ if (opInfo && opInfo->verifyInvariants(&op))
+ return true;
// Verify that all child blocks are ok.
for (auto ®ion : op.getRegions())
if (verifyBlock(b, /*isTopLevel=*/false))
return true;
+ // If this is a registered operation, there is nothing left to do.
+ if (opInfo)
+ return false;
+
+ // Otherwise, verify that the parent dialect allows un-registered operations.
+ auto opName = op.getName().getStringRef();
+ auto dialectPrefix = opName.split('.').first;
+
+ // Check for an existing answer for the operation dialect.
+ auto it = dialectAllowsUnknownOps.find(dialectPrefix);
+ if (it == dialectAllowsUnknownOps.end()) {
+ // If the operation dialect is registered, query it directly.
+ if (auto *dialect = fn.getContext()->getRegisteredDialect(dialectPrefix))
+ it = dialectAllowsUnknownOps
+ .try_emplace(dialectPrefix, dialect->allowsUnknownOperations())
+ .first;
+ // Otherwise, conservatively allow unknown operations.
+ else
+ it = dialectAllowsUnknownOps.try_emplace(dialectPrefix, true).first;
+ }
+
+ if (!it->second) {
+ return failure("unregistered operation '" + opName +
+ "' found in dialect ('" + dialectPrefix +
+ "') that does not allow unknown operations",
+ op);
+ }
+
return false;
}