xref: /llvm-project/mlir/lib/IR/ExtensibleDialect.cpp (revision db791b278a414fb6df1acc1799adcf11d8fb9169)
19e0b5533SMathieu Fehr //===- ExtensibleDialect.cpp - Extensible dialect ---------------*- C++ -*-===//
29e0b5533SMathieu Fehr //
39e0b5533SMathieu Fehr // This file is licensed under the Apache License v2.0 with LLVM Exceptions.
49e0b5533SMathieu Fehr // See https://llvm.org/LICENSE.txt for license information.
59e0b5533SMathieu Fehr // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
69e0b5533SMathieu Fehr //
79e0b5533SMathieu Fehr //===----------------------------------------------------------------------===//
89e0b5533SMathieu Fehr 
99e0b5533SMathieu Fehr #include "mlir/IR/ExtensibleDialect.h"
109e0b5533SMathieu Fehr #include "mlir/IR/AttributeSupport.h"
119e0b5533SMathieu Fehr #include "mlir/IR/DialectImplementation.h"
129e0b5533SMathieu Fehr #include "mlir/IR/OperationSupport.h"
139e0b5533SMathieu Fehr #include "mlir/IR/StorageUniquerSupport.h"
149e0b5533SMathieu Fehr 
159e0b5533SMathieu Fehr using namespace mlir;
169e0b5533SMathieu Fehr 
179e0b5533SMathieu Fehr //===----------------------------------------------------------------------===//
189e0b5533SMathieu Fehr // Dynamic types and attributes shared functions
199e0b5533SMathieu Fehr //===----------------------------------------------------------------------===//
209e0b5533SMathieu Fehr 
219e0b5533SMathieu Fehr /// Default parser for dynamic attribute or type parameters.
229e0b5533SMathieu Fehr /// Parse in the format '(<>)?' or '<attr (,attr)*>'.
239e0b5533SMathieu Fehr static LogicalResult
typeOrAttrParser(AsmParser & parser,SmallVectorImpl<Attribute> & parsedParams)249e0b5533SMathieu Fehr typeOrAttrParser(AsmParser &parser, SmallVectorImpl<Attribute> &parsedParams) {
259e0b5533SMathieu Fehr   // No parameters
269e0b5533SMathieu Fehr   if (parser.parseOptionalLess() || !parser.parseOptionalGreater())
279e0b5533SMathieu Fehr     return success();
289e0b5533SMathieu Fehr 
299e0b5533SMathieu Fehr   Attribute attr;
309e0b5533SMathieu Fehr   if (parser.parseAttribute(attr))
319e0b5533SMathieu Fehr     return failure();
329e0b5533SMathieu Fehr   parsedParams.push_back(attr);
339e0b5533SMathieu Fehr 
349e0b5533SMathieu Fehr   while (parser.parseOptionalGreater()) {
359e0b5533SMathieu Fehr     Attribute attr;
369e0b5533SMathieu Fehr     if (parser.parseComma() || parser.parseAttribute(attr))
379e0b5533SMathieu Fehr       return failure();
389e0b5533SMathieu Fehr     parsedParams.push_back(attr);
399e0b5533SMathieu Fehr   }
409e0b5533SMathieu Fehr 
419e0b5533SMathieu Fehr   return success();
429e0b5533SMathieu Fehr }
439e0b5533SMathieu Fehr 
449e0b5533SMathieu Fehr /// Default printer for dynamic attribute or type parameters.
459e0b5533SMathieu Fehr /// Print in the format '(<>)?' or '<attr (,attr)*>'.
typeOrAttrPrinter(AsmPrinter & printer,ArrayRef<Attribute> params)469e0b5533SMathieu Fehr static void typeOrAttrPrinter(AsmPrinter &printer, ArrayRef<Attribute> params) {
479e0b5533SMathieu Fehr   if (params.empty())
489e0b5533SMathieu Fehr     return;
499e0b5533SMathieu Fehr 
509e0b5533SMathieu Fehr   printer << "<";
519e0b5533SMathieu Fehr   interleaveComma(params, printer.getStream());
529e0b5533SMathieu Fehr   printer << ">";
539e0b5533SMathieu Fehr }
549e0b5533SMathieu Fehr 
559e0b5533SMathieu Fehr //===----------------------------------------------------------------------===//
569e0b5533SMathieu Fehr // Dynamic type
579e0b5533SMathieu Fehr //===----------------------------------------------------------------------===//
589e0b5533SMathieu Fehr 
599e0b5533SMathieu Fehr std::unique_ptr<DynamicTypeDefinition>
get(StringRef name,ExtensibleDialect * dialect,VerifierFn && verifier)609e0b5533SMathieu Fehr DynamicTypeDefinition::get(StringRef name, ExtensibleDialect *dialect,
619e0b5533SMathieu Fehr                            VerifierFn &&verifier) {
629e0b5533SMathieu Fehr   return DynamicTypeDefinition::get(name, dialect, std::move(verifier),
639e0b5533SMathieu Fehr                                     typeOrAttrParser, typeOrAttrPrinter);
649e0b5533SMathieu Fehr }
659e0b5533SMathieu Fehr 
669e0b5533SMathieu Fehr std::unique_ptr<DynamicTypeDefinition>
get(StringRef name,ExtensibleDialect * dialect,VerifierFn && verifier,ParserFn && parser,PrinterFn && printer)679e0b5533SMathieu Fehr DynamicTypeDefinition::get(StringRef name, ExtensibleDialect *dialect,
689e0b5533SMathieu Fehr                            VerifierFn &&verifier, ParserFn &&parser,
699e0b5533SMathieu Fehr                            PrinterFn &&printer) {
709e0b5533SMathieu Fehr   return std::unique_ptr<DynamicTypeDefinition>(
719e0b5533SMathieu Fehr       new DynamicTypeDefinition(name, dialect, std::move(verifier),
729e0b5533SMathieu Fehr                                 std::move(parser), std::move(printer)));
739e0b5533SMathieu Fehr }
749e0b5533SMathieu Fehr 
DynamicTypeDefinition(StringRef nameRef,ExtensibleDialect * dialect,VerifierFn && verifier,ParserFn && parser,PrinterFn && printer)759e0b5533SMathieu Fehr DynamicTypeDefinition::DynamicTypeDefinition(StringRef nameRef,
769e0b5533SMathieu Fehr                                              ExtensibleDialect *dialect,
779e0b5533SMathieu Fehr                                              VerifierFn &&verifier,
789e0b5533SMathieu Fehr                                              ParserFn &&parser,
799e0b5533SMathieu Fehr                                              PrinterFn &&printer)
809e0b5533SMathieu Fehr     : name(nameRef), dialect(dialect), verifier(std::move(verifier)),
819e0b5533SMathieu Fehr       parser(std::move(parser)), printer(std::move(printer)),
829e0b5533SMathieu Fehr       ctx(dialect->getContext()) {}
839e0b5533SMathieu Fehr 
DynamicTypeDefinition(ExtensibleDialect * dialect,StringRef nameRef)849e0b5533SMathieu Fehr DynamicTypeDefinition::DynamicTypeDefinition(ExtensibleDialect *dialect,
859e0b5533SMathieu Fehr                                              StringRef nameRef)
869e0b5533SMathieu Fehr     : name(nameRef), dialect(dialect), ctx(dialect->getContext()) {}
879e0b5533SMathieu Fehr 
registerInTypeUniquer()889e0b5533SMathieu Fehr void DynamicTypeDefinition::registerInTypeUniquer() {
899e0b5533SMathieu Fehr   detail::TypeUniquer::registerType<DynamicType>(&getContext(), getTypeID());
909e0b5533SMathieu Fehr }
919e0b5533SMathieu Fehr 
929e0b5533SMathieu Fehr namespace mlir {
939e0b5533SMathieu Fehr namespace detail {
949e0b5533SMathieu Fehr /// Storage of DynamicType.
959e0b5533SMathieu Fehr /// Contains a pointer to the type definition and type parameters.
969e0b5533SMathieu Fehr struct DynamicTypeStorage : public TypeStorage {
979e0b5533SMathieu Fehr 
989e0b5533SMathieu Fehr   using KeyTy = std::pair<DynamicTypeDefinition *, ArrayRef<Attribute>>;
999e0b5533SMathieu Fehr 
DynamicTypeStoragemlir::detail::DynamicTypeStorage1009e0b5533SMathieu Fehr   explicit DynamicTypeStorage(DynamicTypeDefinition *typeDef,
1019e0b5533SMathieu Fehr                               ArrayRef<Attribute> params)
1029e0b5533SMathieu Fehr       : typeDef(typeDef), params(params) {}
1039e0b5533SMathieu Fehr 
operator ==mlir::detail::DynamicTypeStorage1049e0b5533SMathieu Fehr   bool operator==(const KeyTy &key) const {
1059e0b5533SMathieu Fehr     return typeDef == key.first && params == key.second;
1069e0b5533SMathieu Fehr   }
1079e0b5533SMathieu Fehr 
hashKeymlir::detail::DynamicTypeStorage1089e0b5533SMathieu Fehr   static llvm::hash_code hashKey(const KeyTy &key) {
1099e0b5533SMathieu Fehr     return llvm::hash_value(key);
1109e0b5533SMathieu Fehr   }
1119e0b5533SMathieu Fehr 
constructmlir::detail::DynamicTypeStorage1129e0b5533SMathieu Fehr   static DynamicTypeStorage *construct(TypeStorageAllocator &alloc,
1139e0b5533SMathieu Fehr                                        const KeyTy &key) {
1149e0b5533SMathieu Fehr     return new (alloc.allocate<DynamicTypeStorage>())
1159e0b5533SMathieu Fehr         DynamicTypeStorage(key.first, alloc.copyInto(key.second));
1169e0b5533SMathieu Fehr   }
1179e0b5533SMathieu Fehr 
1189e0b5533SMathieu Fehr   /// Definition of the type.
1199e0b5533SMathieu Fehr   DynamicTypeDefinition *typeDef;
1209e0b5533SMathieu Fehr 
1219e0b5533SMathieu Fehr   /// The type parameters.
1229e0b5533SMathieu Fehr   ArrayRef<Attribute> params;
1239e0b5533SMathieu Fehr };
1249e0b5533SMathieu Fehr } // namespace detail
1259e0b5533SMathieu Fehr } // namespace mlir
1269e0b5533SMathieu Fehr 
get(DynamicTypeDefinition * typeDef,ArrayRef<Attribute> params)1279e0b5533SMathieu Fehr DynamicType DynamicType::get(DynamicTypeDefinition *typeDef,
1289e0b5533SMathieu Fehr                              ArrayRef<Attribute> params) {
1299e0b5533SMathieu Fehr   auto &ctx = typeDef->getContext();
1309e0b5533SMathieu Fehr   auto emitError = detail::getDefaultDiagnosticEmitFn(&ctx);
1319e0b5533SMathieu Fehr   assert(succeeded(typeDef->verify(emitError, params)));
1329e0b5533SMathieu Fehr   return detail::TypeUniquer::getWithTypeID<DynamicType>(
1339e0b5533SMathieu Fehr       &ctx, typeDef->getTypeID(), typeDef, params);
1349e0b5533SMathieu Fehr }
1359e0b5533SMathieu Fehr 
1369e0b5533SMathieu Fehr DynamicType
getChecked(function_ref<InFlightDiagnostic ()> emitError,DynamicTypeDefinition * typeDef,ArrayRef<Attribute> params)1379e0b5533SMathieu Fehr DynamicType::getChecked(function_ref<InFlightDiagnostic()> emitError,
1389e0b5533SMathieu Fehr                         DynamicTypeDefinition *typeDef,
1399e0b5533SMathieu Fehr                         ArrayRef<Attribute> params) {
1409e0b5533SMathieu Fehr   if (failed(typeDef->verify(emitError, params)))
1419e0b5533SMathieu Fehr     return {};
1429e0b5533SMathieu Fehr   auto &ctx = typeDef->getContext();
1439e0b5533SMathieu Fehr   return detail::TypeUniquer::getWithTypeID<DynamicType>(
1449e0b5533SMathieu Fehr       &ctx, typeDef->getTypeID(), typeDef, params);
1459e0b5533SMathieu Fehr }
1469e0b5533SMathieu Fehr 
getTypeDef()1479e0b5533SMathieu Fehr DynamicTypeDefinition *DynamicType::getTypeDef() { return getImpl()->typeDef; }
1489e0b5533SMathieu Fehr 
getParams()1499e0b5533SMathieu Fehr ArrayRef<Attribute> DynamicType::getParams() { return getImpl()->params; }
1509e0b5533SMathieu Fehr 
classof(Type type)1519e0b5533SMathieu Fehr bool DynamicType::classof(Type type) {
1529e0b5533SMathieu Fehr   return type.hasTrait<TypeTrait::IsDynamicType>();
1539e0b5533SMathieu Fehr }
1549e0b5533SMathieu Fehr 
parse(AsmParser & parser,DynamicTypeDefinition * typeDef,DynamicType & parsedType)1559e0b5533SMathieu Fehr ParseResult DynamicType::parse(AsmParser &parser,
1569e0b5533SMathieu Fehr                                DynamicTypeDefinition *typeDef,
1579e0b5533SMathieu Fehr                                DynamicType &parsedType) {
1589e0b5533SMathieu Fehr   SmallVector<Attribute> params;
1599e0b5533SMathieu Fehr   if (failed(typeDef->parser(parser, params)))
1609e0b5533SMathieu Fehr     return failure();
1619e0b5533SMathieu Fehr   parsedType = parser.getChecked<DynamicType>(typeDef, params);
1629e0b5533SMathieu Fehr   if (!parsedType)
1639e0b5533SMathieu Fehr     return failure();
1649e0b5533SMathieu Fehr   return success();
1659e0b5533SMathieu Fehr }
1669e0b5533SMathieu Fehr 
print(AsmPrinter & printer)1679e0b5533SMathieu Fehr void DynamicType::print(AsmPrinter &printer) {
1689e0b5533SMathieu Fehr   printer << getTypeDef()->getName();
1699e0b5533SMathieu Fehr   getTypeDef()->printer(printer, getParams());
1709e0b5533SMathieu Fehr }
1719e0b5533SMathieu Fehr 
1729e0b5533SMathieu Fehr //===----------------------------------------------------------------------===//
1739e0b5533SMathieu Fehr // Dynamic attribute
1749e0b5533SMathieu Fehr //===----------------------------------------------------------------------===//
1759e0b5533SMathieu Fehr 
1769e0b5533SMathieu Fehr std::unique_ptr<DynamicAttrDefinition>
get(StringRef name,ExtensibleDialect * dialect,VerifierFn && verifier)1779e0b5533SMathieu Fehr DynamicAttrDefinition::get(StringRef name, ExtensibleDialect *dialect,
1789e0b5533SMathieu Fehr                            VerifierFn &&verifier) {
1799e0b5533SMathieu Fehr   return DynamicAttrDefinition::get(name, dialect, std::move(verifier),
1809e0b5533SMathieu Fehr                                     typeOrAttrParser, typeOrAttrPrinter);
1819e0b5533SMathieu Fehr }
1829e0b5533SMathieu Fehr 
1839e0b5533SMathieu Fehr std::unique_ptr<DynamicAttrDefinition>
get(StringRef name,ExtensibleDialect * dialect,VerifierFn && verifier,ParserFn && parser,PrinterFn && printer)1849e0b5533SMathieu Fehr DynamicAttrDefinition::get(StringRef name, ExtensibleDialect *dialect,
1859e0b5533SMathieu Fehr                            VerifierFn &&verifier, ParserFn &&parser,
1869e0b5533SMathieu Fehr                            PrinterFn &&printer) {
1879e0b5533SMathieu Fehr   return std::unique_ptr<DynamicAttrDefinition>(
1889e0b5533SMathieu Fehr       new DynamicAttrDefinition(name, dialect, std::move(verifier),
1899e0b5533SMathieu Fehr                                 std::move(parser), std::move(printer)));
1909e0b5533SMathieu Fehr }
1919e0b5533SMathieu Fehr 
DynamicAttrDefinition(StringRef nameRef,ExtensibleDialect * dialect,VerifierFn && verifier,ParserFn && parser,PrinterFn && printer)1929e0b5533SMathieu Fehr DynamicAttrDefinition::DynamicAttrDefinition(StringRef nameRef,
1939e0b5533SMathieu Fehr                                              ExtensibleDialect *dialect,
1949e0b5533SMathieu Fehr                                              VerifierFn &&verifier,
1959e0b5533SMathieu Fehr                                              ParserFn &&parser,
1969e0b5533SMathieu Fehr                                              PrinterFn &&printer)
1979e0b5533SMathieu Fehr     : name(nameRef), dialect(dialect), verifier(std::move(verifier)),
1989e0b5533SMathieu Fehr       parser(std::move(parser)), printer(std::move(printer)),
1999e0b5533SMathieu Fehr       ctx(dialect->getContext()) {}
2009e0b5533SMathieu Fehr 
DynamicAttrDefinition(ExtensibleDialect * dialect,StringRef nameRef)2019e0b5533SMathieu Fehr DynamicAttrDefinition::DynamicAttrDefinition(ExtensibleDialect *dialect,
2029e0b5533SMathieu Fehr                                              StringRef nameRef)
2039e0b5533SMathieu Fehr     : name(nameRef), dialect(dialect), ctx(dialect->getContext()) {}
2049e0b5533SMathieu Fehr 
registerInAttrUniquer()2059e0b5533SMathieu Fehr void DynamicAttrDefinition::registerInAttrUniquer() {
2069e0b5533SMathieu Fehr   detail::AttributeUniquer::registerAttribute<DynamicAttr>(&getContext(),
2079e0b5533SMathieu Fehr                                                            getTypeID());
2089e0b5533SMathieu Fehr }
2099e0b5533SMathieu Fehr 
2109e0b5533SMathieu Fehr namespace mlir {
2119e0b5533SMathieu Fehr namespace detail {
2129e0b5533SMathieu Fehr /// Storage of DynamicAttr.
2139e0b5533SMathieu Fehr /// Contains a pointer to the attribute definition and attribute parameters.
2149e0b5533SMathieu Fehr struct DynamicAttrStorage : public AttributeStorage {
2159e0b5533SMathieu Fehr   using KeyTy = std::pair<DynamicAttrDefinition *, ArrayRef<Attribute>>;
2169e0b5533SMathieu Fehr 
DynamicAttrStoragemlir::detail::DynamicAttrStorage2179e0b5533SMathieu Fehr   explicit DynamicAttrStorage(DynamicAttrDefinition *attrDef,
2189e0b5533SMathieu Fehr                               ArrayRef<Attribute> params)
2199e0b5533SMathieu Fehr       : attrDef(attrDef), params(params) {}
2209e0b5533SMathieu Fehr 
operator ==mlir::detail::DynamicAttrStorage2219e0b5533SMathieu Fehr   bool operator==(const KeyTy &key) const {
2229e0b5533SMathieu Fehr     return attrDef == key.first && params == key.second;
2239e0b5533SMathieu Fehr   }
2249e0b5533SMathieu Fehr 
hashKeymlir::detail::DynamicAttrStorage2259e0b5533SMathieu Fehr   static llvm::hash_code hashKey(const KeyTy &key) {
2269e0b5533SMathieu Fehr     return llvm::hash_value(key);
2279e0b5533SMathieu Fehr   }
2289e0b5533SMathieu Fehr 
constructmlir::detail::DynamicAttrStorage2299e0b5533SMathieu Fehr   static DynamicAttrStorage *construct(AttributeStorageAllocator &alloc,
2309e0b5533SMathieu Fehr                                        const KeyTy &key) {
2319e0b5533SMathieu Fehr     return new (alloc.allocate<DynamicAttrStorage>())
2329e0b5533SMathieu Fehr         DynamicAttrStorage(key.first, alloc.copyInto(key.second));
2339e0b5533SMathieu Fehr   }
2349e0b5533SMathieu Fehr 
2359e0b5533SMathieu Fehr   /// Definition of the type.
2369e0b5533SMathieu Fehr   DynamicAttrDefinition *attrDef;
2379e0b5533SMathieu Fehr 
2389e0b5533SMathieu Fehr   /// The type parameters.
2399e0b5533SMathieu Fehr   ArrayRef<Attribute> params;
2409e0b5533SMathieu Fehr };
2419e0b5533SMathieu Fehr } // namespace detail
2429e0b5533SMathieu Fehr } // namespace mlir
2439e0b5533SMathieu Fehr 
get(DynamicAttrDefinition * attrDef,ArrayRef<Attribute> params)2449e0b5533SMathieu Fehr DynamicAttr DynamicAttr::get(DynamicAttrDefinition *attrDef,
2459e0b5533SMathieu Fehr                              ArrayRef<Attribute> params) {
2469e0b5533SMathieu Fehr   auto &ctx = attrDef->getContext();
2479e0b5533SMathieu Fehr   return detail::AttributeUniquer::getWithTypeID<DynamicAttr>(
2489e0b5533SMathieu Fehr       &ctx, attrDef->getTypeID(), attrDef, params);
2499e0b5533SMathieu Fehr }
2509e0b5533SMathieu Fehr 
2519e0b5533SMathieu Fehr DynamicAttr
getChecked(function_ref<InFlightDiagnostic ()> emitError,DynamicAttrDefinition * attrDef,ArrayRef<Attribute> params)2529e0b5533SMathieu Fehr DynamicAttr::getChecked(function_ref<InFlightDiagnostic()> emitError,
2539e0b5533SMathieu Fehr                         DynamicAttrDefinition *attrDef,
2549e0b5533SMathieu Fehr                         ArrayRef<Attribute> params) {
2559e0b5533SMathieu Fehr   if (failed(attrDef->verify(emitError, params)))
2569e0b5533SMathieu Fehr     return {};
2579e0b5533SMathieu Fehr   return get(attrDef, params);
2589e0b5533SMathieu Fehr }
2599e0b5533SMathieu Fehr 
getAttrDef()2609e0b5533SMathieu Fehr DynamicAttrDefinition *DynamicAttr::getAttrDef() { return getImpl()->attrDef; }
2619e0b5533SMathieu Fehr 
getParams()2629e0b5533SMathieu Fehr ArrayRef<Attribute> DynamicAttr::getParams() { return getImpl()->params; }
2639e0b5533SMathieu Fehr 
classof(Attribute attr)2649e0b5533SMathieu Fehr bool DynamicAttr::classof(Attribute attr) {
2659e0b5533SMathieu Fehr   return attr.hasTrait<AttributeTrait::IsDynamicAttr>();
2669e0b5533SMathieu Fehr }
2679e0b5533SMathieu Fehr 
parse(AsmParser & parser,DynamicAttrDefinition * attrDef,DynamicAttr & parsedAttr)2689e0b5533SMathieu Fehr ParseResult DynamicAttr::parse(AsmParser &parser,
2699e0b5533SMathieu Fehr                                DynamicAttrDefinition *attrDef,
2709e0b5533SMathieu Fehr                                DynamicAttr &parsedAttr) {
2719e0b5533SMathieu Fehr   SmallVector<Attribute> params;
2729e0b5533SMathieu Fehr   if (failed(attrDef->parser(parser, params)))
2739e0b5533SMathieu Fehr     return failure();
2749e0b5533SMathieu Fehr   parsedAttr = parser.getChecked<DynamicAttr>(attrDef, params);
2759e0b5533SMathieu Fehr   if (!parsedAttr)
2769e0b5533SMathieu Fehr     return failure();
2779e0b5533SMathieu Fehr   return success();
2789e0b5533SMathieu Fehr }
2799e0b5533SMathieu Fehr 
print(AsmPrinter & printer)2809e0b5533SMathieu Fehr void DynamicAttr::print(AsmPrinter &printer) {
2819e0b5533SMathieu Fehr   printer << getAttrDef()->getName();
2829e0b5533SMathieu Fehr   getAttrDef()->printer(printer, getParams());
2839e0b5533SMathieu Fehr }
2849e0b5533SMathieu Fehr 
2859e0b5533SMathieu Fehr //===----------------------------------------------------------------------===//
2869e0b5533SMathieu Fehr // Dynamic operation
2879e0b5533SMathieu Fehr //===----------------------------------------------------------------------===//
2889e0b5533SMathieu Fehr 
DynamicOpDefinition(StringRef name,ExtensibleDialect * dialect,OperationName::VerifyInvariantsFn && verifyFn,OperationName::VerifyRegionInvariantsFn && verifyRegionFn,OperationName::ParseAssemblyFn && parseFn,OperationName::PrintAssemblyFn && printFn,OperationName::FoldHookFn && foldHookFn,GetCanonicalizationPatternsFn && getCanonicalizationPatternsFn,OperationName::PopulateDefaultAttrsFn && populateDefaultAttrsFn)2899e0b5533SMathieu Fehr DynamicOpDefinition::DynamicOpDefinition(
2909e0b5533SMathieu Fehr     StringRef name, ExtensibleDialect *dialect,
2919e0b5533SMathieu Fehr     OperationName::VerifyInvariantsFn &&verifyFn,
2929e0b5533SMathieu Fehr     OperationName::VerifyRegionInvariantsFn &&verifyRegionFn,
2939e0b5533SMathieu Fehr     OperationName::ParseAssemblyFn &&parseFn,
2949e0b5533SMathieu Fehr     OperationName::PrintAssemblyFn &&printFn,
2959e0b5533SMathieu Fehr     OperationName::FoldHookFn &&foldHookFn,
2960441272cSMehdi Amini     GetCanonicalizationPatternsFn &&getCanonicalizationPatternsFn,
29769b6454fSJacques Pienaar     OperationName::PopulateDefaultAttrsFn &&populateDefaultAttrsFn)
2980441272cSMehdi Amini     : Impl(StringAttr::get(dialect->getContext(),
2990441272cSMehdi Amini                            (dialect->getNamespace() + "." + name).str()),
3000441272cSMehdi Amini            dialect, dialect->allocateTypeID(),
30183a635c0SRiver Riddle            /*interfaceMap=*/detail::InterfaceMap()),
3029e0b5533SMathieu Fehr       verifyFn(std::move(verifyFn)), verifyRegionFn(std::move(verifyRegionFn)),
3039e0b5533SMathieu Fehr       parseFn(std::move(parseFn)), printFn(std::move(printFn)),
3049e0b5533SMathieu Fehr       foldHookFn(std::move(foldHookFn)),
30569b6454fSJacques Pienaar       getCanonicalizationPatternsFn(std::move(getCanonicalizationPatternsFn)),
3060441272cSMehdi Amini       populateDefaultAttrsFn(std::move(populateDefaultAttrsFn)) {
3070441272cSMehdi Amini   typeID = dialect->allocateTypeID();
3080441272cSMehdi Amini }
3099e0b5533SMathieu Fehr 
get(StringRef name,ExtensibleDialect * dialect,OperationName::VerifyInvariantsFn && verifyFn,OperationName::VerifyRegionInvariantsFn && verifyRegionFn)3109e0b5533SMathieu Fehr std::unique_ptr<DynamicOpDefinition> DynamicOpDefinition::get(
3119e0b5533SMathieu Fehr     StringRef name, ExtensibleDialect *dialect,
3129e0b5533SMathieu Fehr     OperationName::VerifyInvariantsFn &&verifyFn,
3139e0b5533SMathieu Fehr     OperationName::VerifyRegionInvariantsFn &&verifyRegionFn) {
3149e0b5533SMathieu Fehr   auto parseFn = [](OpAsmParser &parser, OperationState &result) {
3159e0b5533SMathieu Fehr     return parser.emitError(
3169e0b5533SMathieu Fehr         parser.getCurrentLocation(),
3179e0b5533SMathieu Fehr         "dynamic operation do not define any parser function");
3189e0b5533SMathieu Fehr   };
3199e0b5533SMathieu Fehr 
3209e0b5533SMathieu Fehr   auto printFn = [](Operation *op, OpAsmPrinter &printer, StringRef) {
3219e0b5533SMathieu Fehr     printer.printGenericOp(op);
3229e0b5533SMathieu Fehr   };
3239e0b5533SMathieu Fehr 
3249e0b5533SMathieu Fehr   return DynamicOpDefinition::get(name, dialect, std::move(verifyFn),
3259e0b5533SMathieu Fehr                                   std::move(verifyRegionFn), std::move(parseFn),
3269e0b5533SMathieu Fehr                                   std::move(printFn));
3279e0b5533SMathieu Fehr }
3289e0b5533SMathieu Fehr 
get(StringRef name,ExtensibleDialect * dialect,OperationName::VerifyInvariantsFn && verifyFn,OperationName::VerifyRegionInvariantsFn && verifyRegionFn,OperationName::ParseAssemblyFn && parseFn,OperationName::PrintAssemblyFn && printFn)3299e0b5533SMathieu Fehr std::unique_ptr<DynamicOpDefinition> DynamicOpDefinition::get(
3309e0b5533SMathieu Fehr     StringRef name, ExtensibleDialect *dialect,
3319e0b5533SMathieu Fehr     OperationName::VerifyInvariantsFn &&verifyFn,
3329e0b5533SMathieu Fehr     OperationName::VerifyRegionInvariantsFn &&verifyRegionFn,
3339e0b5533SMathieu Fehr     OperationName::ParseAssemblyFn &&parseFn,
3349e0b5533SMathieu Fehr     OperationName::PrintAssemblyFn &&printFn) {
3359e0b5533SMathieu Fehr   auto foldHookFn = [](Operation *op, ArrayRef<Attribute> operands,
3369e0b5533SMathieu Fehr                        SmallVectorImpl<OpFoldResult> &results) {
3379e0b5533SMathieu Fehr     return failure();
3389e0b5533SMathieu Fehr   };
3399e0b5533SMathieu Fehr 
3409e0b5533SMathieu Fehr   auto getCanonicalizationPatternsFn = [](RewritePatternSet &, MLIRContext *) {
3419e0b5533SMathieu Fehr   };
3429e0b5533SMathieu Fehr 
3430441272cSMehdi Amini   auto populateDefaultAttrsFn = [](const OperationName &, NamedAttrList &) {};
34469b6454fSJacques Pienaar 
3459e0b5533SMathieu Fehr   return DynamicOpDefinition::get(name, dialect, std::move(verifyFn),
3469e0b5533SMathieu Fehr                                   std::move(verifyRegionFn), std::move(parseFn),
3479e0b5533SMathieu Fehr                                   std::move(printFn), std::move(foldHookFn),
34869b6454fSJacques Pienaar                                   std::move(getCanonicalizationPatternsFn),
34969b6454fSJacques Pienaar                                   std::move(populateDefaultAttrsFn));
3509e0b5533SMathieu Fehr }
3519e0b5533SMathieu Fehr 
get(StringRef name,ExtensibleDialect * dialect,OperationName::VerifyInvariantsFn && verifyFn,OperationName::VerifyInvariantsFn && verifyRegionFn,OperationName::ParseAssemblyFn && parseFn,OperationName::PrintAssemblyFn && printFn,OperationName::FoldHookFn && foldHookFn,GetCanonicalizationPatternsFn && getCanonicalizationPatternsFn,OperationName::PopulateDefaultAttrsFn && populateDefaultAttrsFn)35269b6454fSJacques Pienaar std::unique_ptr<DynamicOpDefinition> DynamicOpDefinition::get(
35369b6454fSJacques Pienaar     StringRef name, ExtensibleDialect *dialect,
3549e0b5533SMathieu Fehr     OperationName::VerifyInvariantsFn &&verifyFn,
3559e0b5533SMathieu Fehr     OperationName::VerifyInvariantsFn &&verifyRegionFn,
3569e0b5533SMathieu Fehr     OperationName::ParseAssemblyFn &&parseFn,
3579e0b5533SMathieu Fehr     OperationName::PrintAssemblyFn &&printFn,
3589e0b5533SMathieu Fehr     OperationName::FoldHookFn &&foldHookFn,
3590441272cSMehdi Amini     GetCanonicalizationPatternsFn &&getCanonicalizationPatternsFn,
36069b6454fSJacques Pienaar     OperationName::PopulateDefaultAttrsFn &&populateDefaultAttrsFn) {
3619e0b5533SMathieu Fehr   return std::unique_ptr<DynamicOpDefinition>(new DynamicOpDefinition(
3629e0b5533SMathieu Fehr       name, dialect, std::move(verifyFn), std::move(verifyRegionFn),
3639e0b5533SMathieu Fehr       std::move(parseFn), std::move(printFn), std::move(foldHookFn),
36469b6454fSJacques Pienaar       std::move(getCanonicalizationPatternsFn),
36569b6454fSJacques Pienaar       std::move(populateDefaultAttrsFn)));
3669e0b5533SMathieu Fehr }
3679e0b5533SMathieu Fehr 
3689e0b5533SMathieu Fehr //===----------------------------------------------------------------------===//
3699e0b5533SMathieu Fehr // Extensible dialect
3709e0b5533SMathieu Fehr //===----------------------------------------------------------------------===//
3719e0b5533SMathieu Fehr 
3729e0b5533SMathieu Fehr namespace {
3739e0b5533SMathieu Fehr /// Interface that can only be implemented by extensible dialects.
3749e0b5533SMathieu Fehr /// The interface is used to check if a dialect is extensible or not.
3759e0b5533SMathieu Fehr class IsExtensibleDialect : public DialectInterface::Base<IsExtensibleDialect> {
3769e0b5533SMathieu Fehr public:
IsExtensibleDialect(Dialect * dialect)3779e0b5533SMathieu Fehr   IsExtensibleDialect(Dialect *dialect) : Base(dialect) {}
3789e0b5533SMathieu Fehr 
3799e0b5533SMathieu Fehr   MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(IsExtensibleDialect)
3809e0b5533SMathieu Fehr };
3819e0b5533SMathieu Fehr } // namespace
3829e0b5533SMathieu Fehr 
ExtensibleDialect(StringRef name,MLIRContext * ctx,TypeID typeID)3839e0b5533SMathieu Fehr ExtensibleDialect::ExtensibleDialect(StringRef name, MLIRContext *ctx,
3849e0b5533SMathieu Fehr                                      TypeID typeID)
3859e0b5533SMathieu Fehr     : Dialect(name, ctx, typeID) {
3869e0b5533SMathieu Fehr   addInterfaces<IsExtensibleDialect>();
3879e0b5533SMathieu Fehr }
3889e0b5533SMathieu Fehr 
registerDynamicType(std::unique_ptr<DynamicTypeDefinition> && type)3899e0b5533SMathieu Fehr void ExtensibleDialect::registerDynamicType(
3909e0b5533SMathieu Fehr     std::unique_ptr<DynamicTypeDefinition> &&type) {
3919e0b5533SMathieu Fehr   DynamicTypeDefinition *typePtr = type.get();
3929e0b5533SMathieu Fehr   TypeID typeID = type->getTypeID();
3939e0b5533SMathieu Fehr   StringRef name = type->getName();
3949e0b5533SMathieu Fehr   ExtensibleDialect *dialect = type->getDialect();
3959e0b5533SMathieu Fehr 
3969e0b5533SMathieu Fehr   assert(dialect == this &&
3979e0b5533SMathieu Fehr          "trying to register a dynamic type in the wrong dialect");
3989e0b5533SMathieu Fehr 
3999e0b5533SMathieu Fehr   // If a type with the same name is already defined, fail.
4009e0b5533SMathieu Fehr   auto registered = dynTypes.try_emplace(typeID, std::move(type)).second;
4019e0b5533SMathieu Fehr   (void)registered;
4029e0b5533SMathieu Fehr   assert(registered && "type TypeID was not unique");
4039e0b5533SMathieu Fehr 
4049e0b5533SMathieu Fehr   registered = nameToDynTypes.insert({name, typePtr}).second;
4059e0b5533SMathieu Fehr   (void)registered;
4069e0b5533SMathieu Fehr   assert(registered &&
4079e0b5533SMathieu Fehr          "Trying to create a new dynamic type with an existing name");
4089e0b5533SMathieu Fehr 
409*3dbac2c0SFehr Mathieu   // The StringAttr allocates the type name StringRef for the duration of the
410*3dbac2c0SFehr Mathieu   // MLIR context.
411*3dbac2c0SFehr Mathieu   MLIRContext *ctx = getContext();
412*3dbac2c0SFehr Mathieu   auto nameAttr =
413*3dbac2c0SFehr Mathieu       StringAttr::get(ctx, getNamespace() + "." + typePtr->getName());
414*3dbac2c0SFehr Mathieu 
41503d136cfSRiver Riddle   auto abstractType = AbstractType::get(
41603d136cfSRiver Riddle       *dialect, DynamicAttr::getInterfaceMap(), DynamicType::getHasTraitFn(),
41703d136cfSRiver Riddle       DynamicType::getWalkImmediateSubElementsFn(),
418*3dbac2c0SFehr Mathieu       DynamicType::getReplaceImmediateSubElementsFn(), typeID, nameAttr);
4199e0b5533SMathieu Fehr 
4209e0b5533SMathieu Fehr   /// Add the type to the dialect and the type uniquer.
4219e0b5533SMathieu Fehr   addType(typeID, std::move(abstractType));
4229e0b5533SMathieu Fehr   typePtr->registerInTypeUniquer();
4239e0b5533SMathieu Fehr }
4249e0b5533SMathieu Fehr 
registerDynamicAttr(std::unique_ptr<DynamicAttrDefinition> && attr)4259e0b5533SMathieu Fehr void ExtensibleDialect::registerDynamicAttr(
4269e0b5533SMathieu Fehr     std::unique_ptr<DynamicAttrDefinition> &&attr) {
4279e0b5533SMathieu Fehr   auto *attrPtr = attr.get();
4289e0b5533SMathieu Fehr   auto typeID = attr->getTypeID();
4299e0b5533SMathieu Fehr   auto name = attr->getName();
4309e0b5533SMathieu Fehr   auto *dialect = attr->getDialect();
4319e0b5533SMathieu Fehr 
4329e0b5533SMathieu Fehr   assert(dialect == this &&
4339e0b5533SMathieu Fehr          "trying to register a dynamic attribute in the wrong dialect");
4349e0b5533SMathieu Fehr 
4359e0b5533SMathieu Fehr   // If an attribute with the same name is already defined, fail.
4369e0b5533SMathieu Fehr   auto registered = dynAttrs.try_emplace(typeID, std::move(attr)).second;
4379e0b5533SMathieu Fehr   (void)registered;
4389e0b5533SMathieu Fehr   assert(registered && "attribute TypeID was not unique");
4399e0b5533SMathieu Fehr 
4409e0b5533SMathieu Fehr   registered = nameToDynAttrs.insert({name, attrPtr}).second;
4419e0b5533SMathieu Fehr   (void)registered;
4429e0b5533SMathieu Fehr   assert(registered &&
4439e0b5533SMathieu Fehr          "Trying to create a new dynamic attribute with an existing name");
4449e0b5533SMathieu Fehr 
445*3dbac2c0SFehr Mathieu   // The StringAttr allocates the attribute name StringRef for the duration of
446*3dbac2c0SFehr Mathieu   // the MLIR context.
447*3dbac2c0SFehr Mathieu   MLIRContext *ctx = getContext();
448*3dbac2c0SFehr Mathieu   auto nameAttr =
449*3dbac2c0SFehr Mathieu       StringAttr::get(ctx, getNamespace() + "." + attrPtr->getName());
450*3dbac2c0SFehr Mathieu 
45103d136cfSRiver Riddle   auto abstractAttr = AbstractAttribute::get(
45203d136cfSRiver Riddle       *dialect, DynamicAttr::getInterfaceMap(), DynamicAttr::getHasTraitFn(),
45303d136cfSRiver Riddle       DynamicAttr::getWalkImmediateSubElementsFn(),
454*3dbac2c0SFehr Mathieu       DynamicAttr::getReplaceImmediateSubElementsFn(), typeID, nameAttr);
4559e0b5533SMathieu Fehr 
4569e0b5533SMathieu Fehr   /// Add the type to the dialect and the type uniquer.
4579e0b5533SMathieu Fehr   addAttribute(typeID, std::move(abstractAttr));
4589e0b5533SMathieu Fehr   attrPtr->registerInAttrUniquer();
4599e0b5533SMathieu Fehr }
4609e0b5533SMathieu Fehr 
registerDynamicOp(std::unique_ptr<DynamicOpDefinition> && op)4619e0b5533SMathieu Fehr void ExtensibleDialect::registerDynamicOp(
4629e0b5533SMathieu Fehr     std::unique_ptr<DynamicOpDefinition> &&op) {
4639e0b5533SMathieu Fehr   assert(op->dialect == this &&
4649e0b5533SMathieu Fehr          "trying to register a dynamic op in the wrong dialect");
4650441272cSMehdi Amini   RegisteredOperationName::insert(std::move(op), /*attrNames=*/{});
4669e0b5533SMathieu Fehr }
4679e0b5533SMathieu Fehr 
classof(const Dialect * dialect)4689e0b5533SMathieu Fehr bool ExtensibleDialect::classof(const Dialect *dialect) {
4699e0b5533SMathieu Fehr   return const_cast<Dialect *>(dialect)
4709e0b5533SMathieu Fehr       ->getRegisteredInterface<IsExtensibleDialect>();
4719e0b5533SMathieu Fehr }
4729e0b5533SMathieu Fehr 
parseOptionalDynamicType(StringRef typeName,AsmParser & parser,Type & resultType) const4739e0b5533SMathieu Fehr OptionalParseResult ExtensibleDialect::parseOptionalDynamicType(
4749e0b5533SMathieu Fehr     StringRef typeName, AsmParser &parser, Type &resultType) const {
4759e0b5533SMathieu Fehr   DynamicTypeDefinition *typeDef = lookupTypeDefinition(typeName);
4769e0b5533SMathieu Fehr   if (!typeDef)
4771a36588eSKazu Hirata     return std::nullopt;
4789e0b5533SMathieu Fehr 
4799e0b5533SMathieu Fehr   DynamicType dynType;
4809e0b5533SMathieu Fehr   if (DynamicType::parse(parser, typeDef, dynType))
4819e0b5533SMathieu Fehr     return failure();
4829e0b5533SMathieu Fehr   resultType = dynType;
4839e0b5533SMathieu Fehr   return success();
4849e0b5533SMathieu Fehr }
4859e0b5533SMathieu Fehr 
printIfDynamicType(Type type,AsmPrinter & printer)4869e0b5533SMathieu Fehr LogicalResult ExtensibleDialect::printIfDynamicType(Type type,
4879e0b5533SMathieu Fehr                                                     AsmPrinter &printer) {
488c1fa60b4STres Popp   if (auto dynType = llvm::dyn_cast<DynamicType>(type)) {
4899e0b5533SMathieu Fehr     dynType.print(printer);
4909e0b5533SMathieu Fehr     return success();
4919e0b5533SMathieu Fehr   }
4929e0b5533SMathieu Fehr   return failure();
4939e0b5533SMathieu Fehr }
4949e0b5533SMathieu Fehr 
parseOptionalDynamicAttr(StringRef attrName,AsmParser & parser,Attribute & resultAttr) const4959e0b5533SMathieu Fehr OptionalParseResult ExtensibleDialect::parseOptionalDynamicAttr(
4969e0b5533SMathieu Fehr     StringRef attrName, AsmParser &parser, Attribute &resultAttr) const {
4979e0b5533SMathieu Fehr   DynamicAttrDefinition *attrDef = lookupAttrDefinition(attrName);
4989e0b5533SMathieu Fehr   if (!attrDef)
4991a36588eSKazu Hirata     return std::nullopt;
5009e0b5533SMathieu Fehr 
5019e0b5533SMathieu Fehr   DynamicAttr dynAttr;
5029e0b5533SMathieu Fehr   if (DynamicAttr::parse(parser, attrDef, dynAttr))
5039e0b5533SMathieu Fehr     return failure();
5049e0b5533SMathieu Fehr   resultAttr = dynAttr;
5059e0b5533SMathieu Fehr   return success();
5069e0b5533SMathieu Fehr }
5079e0b5533SMathieu Fehr 
printIfDynamicAttr(Attribute attribute,AsmPrinter & printer)5089e0b5533SMathieu Fehr LogicalResult ExtensibleDialect::printIfDynamicAttr(Attribute attribute,
5099e0b5533SMathieu Fehr                                                     AsmPrinter &printer) {
510c1fa60b4STres Popp   if (auto dynAttr = llvm::dyn_cast<DynamicAttr>(attribute)) {
5119e0b5533SMathieu Fehr     dynAttr.print(printer);
5129e0b5533SMathieu Fehr     return success();
5139e0b5533SMathieu Fehr   }
5149e0b5533SMathieu Fehr   return failure();
5159e0b5533SMathieu Fehr }
516ba8424a2SMathieu Fehr 
517ba8424a2SMathieu Fehr //===----------------------------------------------------------------------===//
518ba8424a2SMathieu Fehr // Dynamic dialect
519ba8424a2SMathieu Fehr //===----------------------------------------------------------------------===//
520ba8424a2SMathieu Fehr 
521ba8424a2SMathieu Fehr namespace {
522ba8424a2SMathieu Fehr /// Interface that can only be implemented by extensible dialects.
523ba8424a2SMathieu Fehr /// The interface is used to check if a dialect is extensible or not.
524ba8424a2SMathieu Fehr class IsDynamicDialect : public DialectInterface::Base<IsDynamicDialect> {
525ba8424a2SMathieu Fehr public:
IsDynamicDialect(Dialect * dialect)526ba8424a2SMathieu Fehr   IsDynamicDialect(Dialect *dialect) : Base(dialect) {}
527ba8424a2SMathieu Fehr 
528ba8424a2SMathieu Fehr   MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(IsDynamicDialect)
529ba8424a2SMathieu Fehr };
530ba8424a2SMathieu Fehr } // namespace
531ba8424a2SMathieu Fehr 
DynamicDialect(StringRef name,MLIRContext * ctx)532ba8424a2SMathieu Fehr DynamicDialect::DynamicDialect(StringRef name, MLIRContext *ctx)
533ba8424a2SMathieu Fehr     : SelfOwningTypeID(),
534ba8424a2SMathieu Fehr       ExtensibleDialect(name, ctx, SelfOwningTypeID::getTypeID()) {
535ba8424a2SMathieu Fehr   addInterfaces<IsDynamicDialect>();
536ba8424a2SMathieu Fehr }
537ba8424a2SMathieu Fehr 
classof(const Dialect * dialect)538ba8424a2SMathieu Fehr bool DynamicDialect::classof(const Dialect *dialect) {
539ba8424a2SMathieu Fehr   return const_cast<Dialect *>(dialect)
540ba8424a2SMathieu Fehr       ->getRegisteredInterface<IsDynamicDialect>();
541ba8424a2SMathieu Fehr }
542ba8424a2SMathieu Fehr 
parseType(DialectAsmParser & parser) const543ba8424a2SMathieu Fehr Type DynamicDialect::parseType(DialectAsmParser &parser) const {
544ba8424a2SMathieu Fehr   auto loc = parser.getCurrentLocation();
545ba8424a2SMathieu Fehr   StringRef typeTag;
546ba8424a2SMathieu Fehr   if (failed(parser.parseKeyword(&typeTag)))
547ba8424a2SMathieu Fehr     return Type();
548ba8424a2SMathieu Fehr 
549ba8424a2SMathieu Fehr   {
550ba8424a2SMathieu Fehr     Type dynType;
551ba8424a2SMathieu Fehr     auto parseResult = parseOptionalDynamicType(typeTag, parser, dynType);
552ba8424a2SMathieu Fehr     if (parseResult.has_value()) {
553ba8424a2SMathieu Fehr       if (succeeded(parseResult.value()))
554ba8424a2SMathieu Fehr         return dynType;
555ba8424a2SMathieu Fehr       return Type();
556ba8424a2SMathieu Fehr     }
557ba8424a2SMathieu Fehr   }
558ba8424a2SMathieu Fehr 
559ba8424a2SMathieu Fehr   parser.emitError(loc, "expected dynamic type");
560ba8424a2SMathieu Fehr   return Type();
561ba8424a2SMathieu Fehr }
562ba8424a2SMathieu Fehr 
printType(Type type,DialectAsmPrinter & printer) const563ba8424a2SMathieu Fehr void DynamicDialect::printType(Type type, DialectAsmPrinter &printer) const {
564ba8424a2SMathieu Fehr   auto wasDynamic = printIfDynamicType(type, printer);
565ba8424a2SMathieu Fehr   (void)wasDynamic;
566ba8424a2SMathieu Fehr   assert(succeeded(wasDynamic) &&
567ba8424a2SMathieu Fehr          "non-dynamic type defined in dynamic dialect");
568ba8424a2SMathieu Fehr }
569ba8424a2SMathieu Fehr 
parseAttribute(DialectAsmParser & parser,Type type) const570ba8424a2SMathieu Fehr Attribute DynamicDialect::parseAttribute(DialectAsmParser &parser,
571ba8424a2SMathieu Fehr                                          Type type) const {
572ba8424a2SMathieu Fehr   auto loc = parser.getCurrentLocation();
573ba8424a2SMathieu Fehr   StringRef typeTag;
574ba8424a2SMathieu Fehr   if (failed(parser.parseKeyword(&typeTag)))
575ba8424a2SMathieu Fehr     return Attribute();
576ba8424a2SMathieu Fehr 
577ba8424a2SMathieu Fehr   {
578ba8424a2SMathieu Fehr     Attribute dynAttr;
579ba8424a2SMathieu Fehr     auto parseResult = parseOptionalDynamicAttr(typeTag, parser, dynAttr);
580ba8424a2SMathieu Fehr     if (parseResult.has_value()) {
581ba8424a2SMathieu Fehr       if (succeeded(parseResult.value()))
582ba8424a2SMathieu Fehr         return dynAttr;
583ba8424a2SMathieu Fehr       return Attribute();
584ba8424a2SMathieu Fehr     }
585ba8424a2SMathieu Fehr   }
586ba8424a2SMathieu Fehr 
587ba8424a2SMathieu Fehr   parser.emitError(loc, "expected dynamic attribute");
588ba8424a2SMathieu Fehr   return Attribute();
589ba8424a2SMathieu Fehr }
printAttribute(Attribute attr,DialectAsmPrinter & printer) const590ba8424a2SMathieu Fehr void DynamicDialect::printAttribute(Attribute attr,
591ba8424a2SMathieu Fehr                                     DialectAsmPrinter &printer) const {
592ba8424a2SMathieu Fehr   auto wasDynamic = printIfDynamicAttr(attr, printer);
593ba8424a2SMathieu Fehr   (void)wasDynamic;
594ba8424a2SMathieu Fehr   assert(succeeded(wasDynamic) &&
595ba8424a2SMathieu Fehr          "non-dynamic attribute defined in dynamic dialect");
596ba8424a2SMathieu Fehr }
597