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 #include "mlir/Support/LogicalResult.h"
159e0b5533SMathieu Fehr 
169e0b5533SMathieu Fehr using namespace mlir;
179e0b5533SMathieu Fehr 
189e0b5533SMathieu Fehr //===----------------------------------------------------------------------===//
199e0b5533SMathieu Fehr // Dynamic types and attributes shared functions
209e0b5533SMathieu Fehr //===----------------------------------------------------------------------===//
219e0b5533SMathieu Fehr 
229e0b5533SMathieu Fehr /// Default parser for dynamic attribute or type parameters.
239e0b5533SMathieu Fehr /// Parse in the format '(<>)?' or '<attr (,attr)*>'.
249e0b5533SMathieu Fehr static LogicalResult
typeOrAttrParser(AsmParser & parser,SmallVectorImpl<Attribute> & parsedParams)259e0b5533SMathieu Fehr typeOrAttrParser(AsmParser &parser, SmallVectorImpl<Attribute> &parsedParams) {
269e0b5533SMathieu Fehr   // No parameters
279e0b5533SMathieu Fehr   if (parser.parseOptionalLess() || !parser.parseOptionalGreater())
289e0b5533SMathieu Fehr     return success();
299e0b5533SMathieu Fehr 
309e0b5533SMathieu Fehr   Attribute attr;
319e0b5533SMathieu Fehr   if (parser.parseAttribute(attr))
329e0b5533SMathieu Fehr     return failure();
339e0b5533SMathieu Fehr   parsedParams.push_back(attr);
349e0b5533SMathieu Fehr 
359e0b5533SMathieu Fehr   while (parser.parseOptionalGreater()) {
369e0b5533SMathieu Fehr     Attribute attr;
379e0b5533SMathieu Fehr     if (parser.parseComma() || parser.parseAttribute(attr))
389e0b5533SMathieu Fehr       return failure();
399e0b5533SMathieu Fehr     parsedParams.push_back(attr);
409e0b5533SMathieu Fehr   }
419e0b5533SMathieu Fehr 
429e0b5533SMathieu Fehr   return success();
439e0b5533SMathieu Fehr }
449e0b5533SMathieu Fehr 
459e0b5533SMathieu Fehr /// Default printer for dynamic attribute or type parameters.
469e0b5533SMathieu Fehr /// Print in the format '(<>)?' or '<attr (,attr)*>'.
typeOrAttrPrinter(AsmPrinter & printer,ArrayRef<Attribute> params)479e0b5533SMathieu Fehr static void typeOrAttrPrinter(AsmPrinter &printer, ArrayRef<Attribute> params) {
489e0b5533SMathieu Fehr   if (params.empty())
499e0b5533SMathieu Fehr     return;
509e0b5533SMathieu Fehr 
519e0b5533SMathieu Fehr   printer << "<";
529e0b5533SMathieu Fehr   interleaveComma(params, printer.getStream());
539e0b5533SMathieu Fehr   printer << ">";
549e0b5533SMathieu Fehr }
559e0b5533SMathieu Fehr 
569e0b5533SMathieu Fehr //===----------------------------------------------------------------------===//
579e0b5533SMathieu Fehr // Dynamic type
589e0b5533SMathieu Fehr //===----------------------------------------------------------------------===//
599e0b5533SMathieu Fehr 
609e0b5533SMathieu Fehr std::unique_ptr<DynamicTypeDefinition>
get(StringRef name,ExtensibleDialect * dialect,VerifierFn && verifier)619e0b5533SMathieu Fehr DynamicTypeDefinition::get(StringRef name, ExtensibleDialect *dialect,
629e0b5533SMathieu Fehr                            VerifierFn &&verifier) {
639e0b5533SMathieu Fehr   return DynamicTypeDefinition::get(name, dialect, std::move(verifier),
649e0b5533SMathieu Fehr                                     typeOrAttrParser, typeOrAttrPrinter);
659e0b5533SMathieu Fehr }
669e0b5533SMathieu Fehr 
679e0b5533SMathieu Fehr std::unique_ptr<DynamicTypeDefinition>
get(StringRef name,ExtensibleDialect * dialect,VerifierFn && verifier,ParserFn && parser,PrinterFn && printer)689e0b5533SMathieu Fehr DynamicTypeDefinition::get(StringRef name, ExtensibleDialect *dialect,
699e0b5533SMathieu Fehr                            VerifierFn &&verifier, ParserFn &&parser,
709e0b5533SMathieu Fehr                            PrinterFn &&printer) {
719e0b5533SMathieu Fehr   return std::unique_ptr<DynamicTypeDefinition>(
729e0b5533SMathieu Fehr       new DynamicTypeDefinition(name, dialect, std::move(verifier),
739e0b5533SMathieu Fehr                                 std::move(parser), std::move(printer)));
749e0b5533SMathieu Fehr }
759e0b5533SMathieu Fehr 
DynamicTypeDefinition(StringRef nameRef,ExtensibleDialect * dialect,VerifierFn && verifier,ParserFn && parser,PrinterFn && printer)769e0b5533SMathieu Fehr DynamicTypeDefinition::DynamicTypeDefinition(StringRef nameRef,
779e0b5533SMathieu Fehr                                              ExtensibleDialect *dialect,
789e0b5533SMathieu Fehr                                              VerifierFn &&verifier,
799e0b5533SMathieu Fehr                                              ParserFn &&parser,
809e0b5533SMathieu Fehr                                              PrinterFn &&printer)
819e0b5533SMathieu Fehr     : name(nameRef), dialect(dialect), verifier(std::move(verifier)),
829e0b5533SMathieu Fehr       parser(std::move(parser)), printer(std::move(printer)),
839e0b5533SMathieu Fehr       ctx(dialect->getContext()) {}
849e0b5533SMathieu Fehr 
DynamicTypeDefinition(ExtensibleDialect * dialect,StringRef nameRef)859e0b5533SMathieu Fehr DynamicTypeDefinition::DynamicTypeDefinition(ExtensibleDialect *dialect,
869e0b5533SMathieu Fehr                                              StringRef nameRef)
879e0b5533SMathieu Fehr     : name(nameRef), dialect(dialect), ctx(dialect->getContext()) {}
889e0b5533SMathieu Fehr 
registerInTypeUniquer()899e0b5533SMathieu Fehr void DynamicTypeDefinition::registerInTypeUniquer() {
909e0b5533SMathieu Fehr   detail::TypeUniquer::registerType<DynamicType>(&getContext(), getTypeID());
919e0b5533SMathieu Fehr }
929e0b5533SMathieu Fehr 
939e0b5533SMathieu Fehr namespace mlir {
949e0b5533SMathieu Fehr namespace detail {
959e0b5533SMathieu Fehr /// Storage of DynamicType.
969e0b5533SMathieu Fehr /// Contains a pointer to the type definition and type parameters.
979e0b5533SMathieu Fehr struct DynamicTypeStorage : public TypeStorage {
989e0b5533SMathieu Fehr 
999e0b5533SMathieu Fehr   using KeyTy = std::pair<DynamicTypeDefinition *, ArrayRef<Attribute>>;
1009e0b5533SMathieu Fehr 
DynamicTypeStoragemlir::detail::DynamicTypeStorage1019e0b5533SMathieu Fehr   explicit DynamicTypeStorage(DynamicTypeDefinition *typeDef,
1029e0b5533SMathieu Fehr                               ArrayRef<Attribute> params)
1039e0b5533SMathieu Fehr       : typeDef(typeDef), params(params) {}
1049e0b5533SMathieu Fehr 
operator ==mlir::detail::DynamicTypeStorage1059e0b5533SMathieu Fehr   bool operator==(const KeyTy &key) const {
1069e0b5533SMathieu Fehr     return typeDef == key.first && params == key.second;
1079e0b5533SMathieu Fehr   }
1089e0b5533SMathieu Fehr 
hashKeymlir::detail::DynamicTypeStorage1099e0b5533SMathieu Fehr   static llvm::hash_code hashKey(const KeyTy &key) {
1109e0b5533SMathieu Fehr     return llvm::hash_value(key);
1119e0b5533SMathieu Fehr   }
1129e0b5533SMathieu Fehr 
constructmlir::detail::DynamicTypeStorage1139e0b5533SMathieu Fehr   static DynamicTypeStorage *construct(TypeStorageAllocator &alloc,
1149e0b5533SMathieu Fehr                                        const KeyTy &key) {
1159e0b5533SMathieu Fehr     return new (alloc.allocate<DynamicTypeStorage>())
1169e0b5533SMathieu Fehr         DynamicTypeStorage(key.first, alloc.copyInto(key.second));
1179e0b5533SMathieu Fehr   }
1189e0b5533SMathieu Fehr 
1199e0b5533SMathieu Fehr   /// Definition of the type.
1209e0b5533SMathieu Fehr   DynamicTypeDefinition *typeDef;
1219e0b5533SMathieu Fehr 
1229e0b5533SMathieu Fehr   /// The type parameters.
1239e0b5533SMathieu Fehr   ArrayRef<Attribute> params;
1249e0b5533SMathieu Fehr };
1259e0b5533SMathieu Fehr } // namespace detail
1269e0b5533SMathieu Fehr } // namespace mlir
1279e0b5533SMathieu Fehr 
get(DynamicTypeDefinition * typeDef,ArrayRef<Attribute> params)1289e0b5533SMathieu Fehr DynamicType DynamicType::get(DynamicTypeDefinition *typeDef,
1299e0b5533SMathieu Fehr                              ArrayRef<Attribute> params) {
1309e0b5533SMathieu Fehr   auto &ctx = typeDef->getContext();
1319e0b5533SMathieu Fehr   auto emitError = detail::getDefaultDiagnosticEmitFn(&ctx);
1329e0b5533SMathieu Fehr   assert(succeeded(typeDef->verify(emitError, params)));
1339e0b5533SMathieu Fehr   return detail::TypeUniquer::getWithTypeID<DynamicType>(
1349e0b5533SMathieu Fehr       &ctx, typeDef->getTypeID(), typeDef, params);
1359e0b5533SMathieu Fehr }
1369e0b5533SMathieu Fehr 
1379e0b5533SMathieu Fehr DynamicType
getChecked(function_ref<InFlightDiagnostic ()> emitError,DynamicTypeDefinition * typeDef,ArrayRef<Attribute> params)1389e0b5533SMathieu Fehr DynamicType::getChecked(function_ref<InFlightDiagnostic()> emitError,
1399e0b5533SMathieu Fehr                         DynamicTypeDefinition *typeDef,
1409e0b5533SMathieu Fehr                         ArrayRef<Attribute> params) {
1419e0b5533SMathieu Fehr   if (failed(typeDef->verify(emitError, params)))
1429e0b5533SMathieu Fehr     return {};
1439e0b5533SMathieu Fehr   auto &ctx = typeDef->getContext();
1449e0b5533SMathieu Fehr   return detail::TypeUniquer::getWithTypeID<DynamicType>(
1459e0b5533SMathieu Fehr       &ctx, typeDef->getTypeID(), typeDef, params);
1469e0b5533SMathieu Fehr }
1479e0b5533SMathieu Fehr 
getTypeDef()1489e0b5533SMathieu Fehr DynamicTypeDefinition *DynamicType::getTypeDef() { return getImpl()->typeDef; }
1499e0b5533SMathieu Fehr 
getParams()1509e0b5533SMathieu Fehr ArrayRef<Attribute> DynamicType::getParams() { return getImpl()->params; }
1519e0b5533SMathieu Fehr 
classof(Type type)1529e0b5533SMathieu Fehr bool DynamicType::classof(Type type) {
1539e0b5533SMathieu Fehr   return type.hasTrait<TypeTrait::IsDynamicType>();
1549e0b5533SMathieu Fehr }
1559e0b5533SMathieu Fehr 
parse(AsmParser & parser,DynamicTypeDefinition * typeDef,DynamicType & parsedType)1569e0b5533SMathieu Fehr ParseResult DynamicType::parse(AsmParser &parser,
1579e0b5533SMathieu Fehr                                DynamicTypeDefinition *typeDef,
1589e0b5533SMathieu Fehr                                DynamicType &parsedType) {
1599e0b5533SMathieu Fehr   SmallVector<Attribute> params;
1609e0b5533SMathieu Fehr   if (failed(typeDef->parser(parser, params)))
1619e0b5533SMathieu Fehr     return failure();
1629e0b5533SMathieu Fehr   parsedType = parser.getChecked<DynamicType>(typeDef, params);
1639e0b5533SMathieu Fehr   if (!parsedType)
1649e0b5533SMathieu Fehr     return failure();
1659e0b5533SMathieu Fehr   return success();
1669e0b5533SMathieu Fehr }
1679e0b5533SMathieu Fehr 
print(AsmPrinter & printer)1689e0b5533SMathieu Fehr void DynamicType::print(AsmPrinter &printer) {
1699e0b5533SMathieu Fehr   printer << getTypeDef()->getName();
1709e0b5533SMathieu Fehr   getTypeDef()->printer(printer, getParams());
1719e0b5533SMathieu Fehr }
1729e0b5533SMathieu Fehr 
1739e0b5533SMathieu Fehr //===----------------------------------------------------------------------===//
1749e0b5533SMathieu Fehr // Dynamic attribute
1759e0b5533SMathieu Fehr //===----------------------------------------------------------------------===//
1769e0b5533SMathieu Fehr 
1779e0b5533SMathieu Fehr std::unique_ptr<DynamicAttrDefinition>
get(StringRef name,ExtensibleDialect * dialect,VerifierFn && verifier)1789e0b5533SMathieu Fehr DynamicAttrDefinition::get(StringRef name, ExtensibleDialect *dialect,
1799e0b5533SMathieu Fehr                            VerifierFn &&verifier) {
1809e0b5533SMathieu Fehr   return DynamicAttrDefinition::get(name, dialect, std::move(verifier),
1819e0b5533SMathieu Fehr                                     typeOrAttrParser, typeOrAttrPrinter);
1829e0b5533SMathieu Fehr }
1839e0b5533SMathieu Fehr 
1849e0b5533SMathieu Fehr std::unique_ptr<DynamicAttrDefinition>
get(StringRef name,ExtensibleDialect * dialect,VerifierFn && verifier,ParserFn && parser,PrinterFn && printer)1859e0b5533SMathieu Fehr DynamicAttrDefinition::get(StringRef name, ExtensibleDialect *dialect,
1869e0b5533SMathieu Fehr                            VerifierFn &&verifier, ParserFn &&parser,
1879e0b5533SMathieu Fehr                            PrinterFn &&printer) {
1889e0b5533SMathieu Fehr   return std::unique_ptr<DynamicAttrDefinition>(
1899e0b5533SMathieu Fehr       new DynamicAttrDefinition(name, dialect, std::move(verifier),
1909e0b5533SMathieu Fehr                                 std::move(parser), std::move(printer)));
1919e0b5533SMathieu Fehr }
1929e0b5533SMathieu Fehr 
DynamicAttrDefinition(StringRef nameRef,ExtensibleDialect * dialect,VerifierFn && verifier,ParserFn && parser,PrinterFn && printer)1939e0b5533SMathieu Fehr DynamicAttrDefinition::DynamicAttrDefinition(StringRef nameRef,
1949e0b5533SMathieu Fehr                                              ExtensibleDialect *dialect,
1959e0b5533SMathieu Fehr                                              VerifierFn &&verifier,
1969e0b5533SMathieu Fehr                                              ParserFn &&parser,
1979e0b5533SMathieu Fehr                                              PrinterFn &&printer)
1989e0b5533SMathieu Fehr     : name(nameRef), dialect(dialect), verifier(std::move(verifier)),
1999e0b5533SMathieu Fehr       parser(std::move(parser)), printer(std::move(printer)),
2009e0b5533SMathieu Fehr       ctx(dialect->getContext()) {}
2019e0b5533SMathieu Fehr 
DynamicAttrDefinition(ExtensibleDialect * dialect,StringRef nameRef)2029e0b5533SMathieu Fehr DynamicAttrDefinition::DynamicAttrDefinition(ExtensibleDialect *dialect,
2039e0b5533SMathieu Fehr                                              StringRef nameRef)
2049e0b5533SMathieu Fehr     : name(nameRef), dialect(dialect), ctx(dialect->getContext()) {}
2059e0b5533SMathieu Fehr 
registerInAttrUniquer()2069e0b5533SMathieu Fehr void DynamicAttrDefinition::registerInAttrUniquer() {
2079e0b5533SMathieu Fehr   detail::AttributeUniquer::registerAttribute<DynamicAttr>(&getContext(),
2089e0b5533SMathieu Fehr                                                            getTypeID());
2099e0b5533SMathieu Fehr }
2109e0b5533SMathieu Fehr 
2119e0b5533SMathieu Fehr namespace mlir {
2129e0b5533SMathieu Fehr namespace detail {
2139e0b5533SMathieu Fehr /// Storage of DynamicAttr.
2149e0b5533SMathieu Fehr /// Contains a pointer to the attribute definition and attribute parameters.
2159e0b5533SMathieu Fehr struct DynamicAttrStorage : public AttributeStorage {
2169e0b5533SMathieu Fehr   using KeyTy = std::pair<DynamicAttrDefinition *, ArrayRef<Attribute>>;
2179e0b5533SMathieu Fehr 
DynamicAttrStoragemlir::detail::DynamicAttrStorage2189e0b5533SMathieu Fehr   explicit DynamicAttrStorage(DynamicAttrDefinition *attrDef,
2199e0b5533SMathieu Fehr                               ArrayRef<Attribute> params)
2209e0b5533SMathieu Fehr       : attrDef(attrDef), params(params) {}
2219e0b5533SMathieu Fehr 
operator ==mlir::detail::DynamicAttrStorage2229e0b5533SMathieu Fehr   bool operator==(const KeyTy &key) const {
2239e0b5533SMathieu Fehr     return attrDef == key.first && params == key.second;
2249e0b5533SMathieu Fehr   }
2259e0b5533SMathieu Fehr 
hashKeymlir::detail::DynamicAttrStorage2269e0b5533SMathieu Fehr   static llvm::hash_code hashKey(const KeyTy &key) {
2279e0b5533SMathieu Fehr     return llvm::hash_value(key);
2289e0b5533SMathieu Fehr   }
2299e0b5533SMathieu Fehr 
constructmlir::detail::DynamicAttrStorage2309e0b5533SMathieu Fehr   static DynamicAttrStorage *construct(AttributeStorageAllocator &alloc,
2319e0b5533SMathieu Fehr                                        const KeyTy &key) {
2329e0b5533SMathieu Fehr     return new (alloc.allocate<DynamicAttrStorage>())
2339e0b5533SMathieu Fehr         DynamicAttrStorage(key.first, alloc.copyInto(key.second));
2349e0b5533SMathieu Fehr   }
2359e0b5533SMathieu Fehr 
2369e0b5533SMathieu Fehr   /// Definition of the type.
2379e0b5533SMathieu Fehr   DynamicAttrDefinition *attrDef;
2389e0b5533SMathieu Fehr 
2399e0b5533SMathieu Fehr   /// The type parameters.
2409e0b5533SMathieu Fehr   ArrayRef<Attribute> params;
2419e0b5533SMathieu Fehr };
2429e0b5533SMathieu Fehr } // namespace detail
2439e0b5533SMathieu Fehr } // namespace mlir
2449e0b5533SMathieu Fehr 
get(DynamicAttrDefinition * attrDef,ArrayRef<Attribute> params)2459e0b5533SMathieu Fehr DynamicAttr DynamicAttr::get(DynamicAttrDefinition *attrDef,
2469e0b5533SMathieu Fehr                              ArrayRef<Attribute> params) {
2479e0b5533SMathieu Fehr   auto &ctx = attrDef->getContext();
2489e0b5533SMathieu Fehr   return detail::AttributeUniquer::getWithTypeID<DynamicAttr>(
2499e0b5533SMathieu Fehr       &ctx, attrDef->getTypeID(), attrDef, params);
2509e0b5533SMathieu Fehr }
2519e0b5533SMathieu Fehr 
2529e0b5533SMathieu Fehr DynamicAttr
getChecked(function_ref<InFlightDiagnostic ()> emitError,DynamicAttrDefinition * attrDef,ArrayRef<Attribute> params)2539e0b5533SMathieu Fehr DynamicAttr::getChecked(function_ref<InFlightDiagnostic()> emitError,
2549e0b5533SMathieu Fehr                         DynamicAttrDefinition *attrDef,
2559e0b5533SMathieu Fehr                         ArrayRef<Attribute> params) {
2569e0b5533SMathieu Fehr   if (failed(attrDef->verify(emitError, params)))
2579e0b5533SMathieu Fehr     return {};
2589e0b5533SMathieu Fehr   return get(attrDef, params);
2599e0b5533SMathieu Fehr }
2609e0b5533SMathieu Fehr 
getAttrDef()2619e0b5533SMathieu Fehr DynamicAttrDefinition *DynamicAttr::getAttrDef() { return getImpl()->attrDef; }
2629e0b5533SMathieu Fehr 
getParams()2639e0b5533SMathieu Fehr ArrayRef<Attribute> DynamicAttr::getParams() { return getImpl()->params; }
2649e0b5533SMathieu Fehr 
classof(Attribute attr)2659e0b5533SMathieu Fehr bool DynamicAttr::classof(Attribute attr) {
2669e0b5533SMathieu Fehr   return attr.hasTrait<AttributeTrait::IsDynamicAttr>();
2679e0b5533SMathieu Fehr }
2689e0b5533SMathieu Fehr 
parse(AsmParser & parser,DynamicAttrDefinition * attrDef,DynamicAttr & parsedAttr)2699e0b5533SMathieu Fehr ParseResult DynamicAttr::parse(AsmParser &parser,
2709e0b5533SMathieu Fehr                                DynamicAttrDefinition *attrDef,
2719e0b5533SMathieu Fehr                                DynamicAttr &parsedAttr) {
2729e0b5533SMathieu Fehr   SmallVector<Attribute> params;
2739e0b5533SMathieu Fehr   if (failed(attrDef->parser(parser, params)))
2749e0b5533SMathieu Fehr     return failure();
2759e0b5533SMathieu Fehr   parsedAttr = parser.getChecked<DynamicAttr>(attrDef, params);
2769e0b5533SMathieu Fehr   if (!parsedAttr)
2779e0b5533SMathieu Fehr     return failure();
2789e0b5533SMathieu Fehr   return success();
2799e0b5533SMathieu Fehr }
2809e0b5533SMathieu Fehr 
print(AsmPrinter & printer)2819e0b5533SMathieu Fehr void DynamicAttr::print(AsmPrinter &printer) {
2829e0b5533SMathieu Fehr   printer << getAttrDef()->getName();
2839e0b5533SMathieu Fehr   getAttrDef()->printer(printer, getParams());
2849e0b5533SMathieu Fehr }
2859e0b5533SMathieu Fehr 
2869e0b5533SMathieu Fehr //===----------------------------------------------------------------------===//
2879e0b5533SMathieu Fehr // Dynamic operation
2889e0b5533SMathieu Fehr //===----------------------------------------------------------------------===//
2899e0b5533SMathieu Fehr 
DynamicOpDefinition(StringRef name,ExtensibleDialect * dialect,OperationName::VerifyInvariantsFn && verifyFn,OperationName::VerifyRegionInvariantsFn && verifyRegionFn,OperationName::ParseAssemblyFn && parseFn,OperationName::PrintAssemblyFn && printFn,OperationName::FoldHookFn && foldHookFn,OperationName::GetCanonicalizationPatternsFn && getCanonicalizationPatternsFn,OperationName::PopulateDefaultAttrsFn && populateDefaultAttrsFn)2909e0b5533SMathieu Fehr DynamicOpDefinition::DynamicOpDefinition(
2919e0b5533SMathieu Fehr     StringRef name, ExtensibleDialect *dialect,
2929e0b5533SMathieu Fehr     OperationName::VerifyInvariantsFn &&verifyFn,
2939e0b5533SMathieu Fehr     OperationName::VerifyRegionInvariantsFn &&verifyRegionFn,
2949e0b5533SMathieu Fehr     OperationName::ParseAssemblyFn &&parseFn,
2959e0b5533SMathieu Fehr     OperationName::PrintAssemblyFn &&printFn,
2969e0b5533SMathieu Fehr     OperationName::FoldHookFn &&foldHookFn,
2979e0b5533SMathieu Fehr     OperationName::GetCanonicalizationPatternsFn
298*69b6454fSJacques Pienaar         &&getCanonicalizationPatternsFn,
299*69b6454fSJacques Pienaar     OperationName::PopulateDefaultAttrsFn &&populateDefaultAttrsFn)
3009e0b5533SMathieu Fehr     : typeID(dialect->allocateTypeID()),
3019e0b5533SMathieu Fehr       name((dialect->getNamespace() + "." + name).str()), dialect(dialect),
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)),
305*69b6454fSJacques Pienaar       getCanonicalizationPatternsFn(std::move(getCanonicalizationPatternsFn)),
306*69b6454fSJacques Pienaar       populateDefaultAttrsFn(std::move(populateDefaultAttrsFn)) {}
3079e0b5533SMathieu Fehr 
get(StringRef name,ExtensibleDialect * dialect,OperationName::VerifyInvariantsFn && verifyFn,OperationName::VerifyRegionInvariantsFn && verifyRegionFn)3089e0b5533SMathieu Fehr std::unique_ptr<DynamicOpDefinition> DynamicOpDefinition::get(
3099e0b5533SMathieu Fehr     StringRef name, ExtensibleDialect *dialect,
3109e0b5533SMathieu Fehr     OperationName::VerifyInvariantsFn &&verifyFn,
3119e0b5533SMathieu Fehr     OperationName::VerifyRegionInvariantsFn &&verifyRegionFn) {
3129e0b5533SMathieu Fehr   auto parseFn = [](OpAsmParser &parser, OperationState &result) {
3139e0b5533SMathieu Fehr     return parser.emitError(
3149e0b5533SMathieu Fehr         parser.getCurrentLocation(),
3159e0b5533SMathieu Fehr         "dynamic operation do not define any parser function");
3169e0b5533SMathieu Fehr   };
3179e0b5533SMathieu Fehr 
3189e0b5533SMathieu Fehr   auto printFn = [](Operation *op, OpAsmPrinter &printer, StringRef) {
3199e0b5533SMathieu Fehr     printer.printGenericOp(op);
3209e0b5533SMathieu Fehr   };
3219e0b5533SMathieu Fehr 
3229e0b5533SMathieu Fehr   return DynamicOpDefinition::get(name, dialect, std::move(verifyFn),
3239e0b5533SMathieu Fehr                                   std::move(verifyRegionFn), std::move(parseFn),
3249e0b5533SMathieu Fehr                                   std::move(printFn));
3259e0b5533SMathieu Fehr }
3269e0b5533SMathieu Fehr 
get(StringRef name,ExtensibleDialect * dialect,OperationName::VerifyInvariantsFn && verifyFn,OperationName::VerifyRegionInvariantsFn && verifyRegionFn,OperationName::ParseAssemblyFn && parseFn,OperationName::PrintAssemblyFn && printFn)3279e0b5533SMathieu Fehr std::unique_ptr<DynamicOpDefinition> DynamicOpDefinition::get(
3289e0b5533SMathieu Fehr     StringRef name, ExtensibleDialect *dialect,
3299e0b5533SMathieu Fehr     OperationName::VerifyInvariantsFn &&verifyFn,
3309e0b5533SMathieu Fehr     OperationName::VerifyRegionInvariantsFn &&verifyRegionFn,
3319e0b5533SMathieu Fehr     OperationName::ParseAssemblyFn &&parseFn,
3329e0b5533SMathieu Fehr     OperationName::PrintAssemblyFn &&printFn) {
3339e0b5533SMathieu Fehr   auto foldHookFn = [](Operation *op, ArrayRef<Attribute> operands,
3349e0b5533SMathieu Fehr                        SmallVectorImpl<OpFoldResult> &results) {
3359e0b5533SMathieu Fehr     return failure();
3369e0b5533SMathieu Fehr   };
3379e0b5533SMathieu Fehr 
3389e0b5533SMathieu Fehr   auto getCanonicalizationPatternsFn = [](RewritePatternSet &, MLIRContext *) {
3399e0b5533SMathieu Fehr   };
3409e0b5533SMathieu Fehr 
341*69b6454fSJacques Pienaar   auto populateDefaultAttrsFn = [](const RegisteredOperationName &,
342*69b6454fSJacques Pienaar                                    NamedAttrList &) {};
343*69b6454fSJacques Pienaar 
3449e0b5533SMathieu Fehr   return DynamicOpDefinition::get(name, dialect, std::move(verifyFn),
3459e0b5533SMathieu Fehr                                   std::move(verifyRegionFn), std::move(parseFn),
3469e0b5533SMathieu Fehr                                   std::move(printFn), std::move(foldHookFn),
347*69b6454fSJacques Pienaar                                   std::move(getCanonicalizationPatternsFn),
348*69b6454fSJacques Pienaar                                   std::move(populateDefaultAttrsFn));
3499e0b5533SMathieu Fehr }
3509e0b5533SMathieu Fehr 
get(StringRef name,ExtensibleDialect * dialect,OperationName::VerifyInvariantsFn && verifyFn,OperationName::VerifyInvariantsFn && verifyRegionFn,OperationName::ParseAssemblyFn && parseFn,OperationName::PrintAssemblyFn && printFn,OperationName::FoldHookFn && foldHookFn,OperationName::GetCanonicalizationPatternsFn && getCanonicalizationPatternsFn,OperationName::PopulateDefaultAttrsFn && populateDefaultAttrsFn)351*69b6454fSJacques Pienaar std::unique_ptr<DynamicOpDefinition> DynamicOpDefinition::get(
352*69b6454fSJacques Pienaar     StringRef name, ExtensibleDialect *dialect,
3539e0b5533SMathieu Fehr     OperationName::VerifyInvariantsFn &&verifyFn,
3549e0b5533SMathieu Fehr     OperationName::VerifyInvariantsFn &&verifyRegionFn,
3559e0b5533SMathieu Fehr     OperationName::ParseAssemblyFn &&parseFn,
3569e0b5533SMathieu Fehr     OperationName::PrintAssemblyFn &&printFn,
3579e0b5533SMathieu Fehr     OperationName::FoldHookFn &&foldHookFn,
3589e0b5533SMathieu Fehr     OperationName::GetCanonicalizationPatternsFn
359*69b6454fSJacques Pienaar         &&getCanonicalizationPatternsFn,
360*69b6454fSJacques 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),
364*69b6454fSJacques Pienaar       std::move(getCanonicalizationPatternsFn),
365*69b6454fSJacques 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 
4099e0b5533SMathieu Fehr   auto abstractType =
4109e0b5533SMathieu Fehr       AbstractType::get(*dialect, DynamicAttr::getInterfaceMap(),
4119e0b5533SMathieu Fehr                         DynamicType::getHasTraitFn(), typeID);
4129e0b5533SMathieu Fehr 
4139e0b5533SMathieu Fehr   /// Add the type to the dialect and the type uniquer.
4149e0b5533SMathieu Fehr   addType(typeID, std::move(abstractType));
4159e0b5533SMathieu Fehr   typePtr->registerInTypeUniquer();
4169e0b5533SMathieu Fehr }
4179e0b5533SMathieu Fehr 
registerDynamicAttr(std::unique_ptr<DynamicAttrDefinition> && attr)4189e0b5533SMathieu Fehr void ExtensibleDialect::registerDynamicAttr(
4199e0b5533SMathieu Fehr     std::unique_ptr<DynamicAttrDefinition> &&attr) {
4209e0b5533SMathieu Fehr   auto *attrPtr = attr.get();
4219e0b5533SMathieu Fehr   auto typeID = attr->getTypeID();
4229e0b5533SMathieu Fehr   auto name = attr->getName();
4239e0b5533SMathieu Fehr   auto *dialect = attr->getDialect();
4249e0b5533SMathieu Fehr 
4259e0b5533SMathieu Fehr   assert(dialect == this &&
4269e0b5533SMathieu Fehr          "trying to register a dynamic attribute in the wrong dialect");
4279e0b5533SMathieu Fehr 
4289e0b5533SMathieu Fehr   // If an attribute with the same name is already defined, fail.
4299e0b5533SMathieu Fehr   auto registered = dynAttrs.try_emplace(typeID, std::move(attr)).second;
4309e0b5533SMathieu Fehr   (void)registered;
4319e0b5533SMathieu Fehr   assert(registered && "attribute TypeID was not unique");
4329e0b5533SMathieu Fehr 
4339e0b5533SMathieu Fehr   registered = nameToDynAttrs.insert({name, attrPtr}).second;
4349e0b5533SMathieu Fehr   (void)registered;
4359e0b5533SMathieu Fehr   assert(registered &&
4369e0b5533SMathieu Fehr          "Trying to create a new dynamic attribute with an existing name");
4379e0b5533SMathieu Fehr 
4389e0b5533SMathieu Fehr   auto abstractAttr =
4399e0b5533SMathieu Fehr       AbstractAttribute::get(*dialect, DynamicAttr::getInterfaceMap(),
4409e0b5533SMathieu Fehr                              DynamicAttr::getHasTraitFn(), typeID);
4419e0b5533SMathieu Fehr 
4429e0b5533SMathieu Fehr   /// Add the type to the dialect and the type uniquer.
4439e0b5533SMathieu Fehr   addAttribute(typeID, std::move(abstractAttr));
4449e0b5533SMathieu Fehr   attrPtr->registerInAttrUniquer();
4459e0b5533SMathieu Fehr }
4469e0b5533SMathieu Fehr 
registerDynamicOp(std::unique_ptr<DynamicOpDefinition> && op)4479e0b5533SMathieu Fehr void ExtensibleDialect::registerDynamicOp(
4489e0b5533SMathieu Fehr     std::unique_ptr<DynamicOpDefinition> &&op) {
4499e0b5533SMathieu Fehr   assert(op->dialect == this &&
4509e0b5533SMathieu Fehr          "trying to register a dynamic op in the wrong dialect");
4519e0b5533SMathieu Fehr   auto hasTraitFn = [](TypeID traitId) { return false; };
4529e0b5533SMathieu Fehr 
4539e0b5533SMathieu Fehr   RegisteredOperationName::insert(
4549e0b5533SMathieu Fehr       op->name, *op->dialect, op->typeID, std::move(op->parseFn),
4559e0b5533SMathieu Fehr       std::move(op->printFn), std::move(op->verifyFn),
4569e0b5533SMathieu Fehr       std::move(op->verifyRegionFn), std::move(op->foldHookFn),
4579e0b5533SMathieu Fehr       std::move(op->getCanonicalizationPatternsFn),
45882140ad7SJacques Pienaar       detail::InterfaceMap::get<>(), std::move(hasTraitFn), {},
459*69b6454fSJacques Pienaar       std::move(op->populateDefaultAttrsFn));
4609e0b5533SMathieu Fehr }
4619e0b5533SMathieu Fehr 
classof(const Dialect * dialect)4629e0b5533SMathieu Fehr bool ExtensibleDialect::classof(const Dialect *dialect) {
4639e0b5533SMathieu Fehr   return const_cast<Dialect *>(dialect)
4649e0b5533SMathieu Fehr       ->getRegisteredInterface<IsExtensibleDialect>();
4659e0b5533SMathieu Fehr }
4669e0b5533SMathieu Fehr 
parseOptionalDynamicType(StringRef typeName,AsmParser & parser,Type & resultType) const4679e0b5533SMathieu Fehr OptionalParseResult ExtensibleDialect::parseOptionalDynamicType(
4689e0b5533SMathieu Fehr     StringRef typeName, AsmParser &parser, Type &resultType) const {
4699e0b5533SMathieu Fehr   DynamicTypeDefinition *typeDef = lookupTypeDefinition(typeName);
4709e0b5533SMathieu Fehr   if (!typeDef)
4719e0b5533SMathieu Fehr     return llvm::None;
4729e0b5533SMathieu Fehr 
4739e0b5533SMathieu Fehr   DynamicType dynType;
4749e0b5533SMathieu Fehr   if (DynamicType::parse(parser, typeDef, dynType))
4759e0b5533SMathieu Fehr     return failure();
4769e0b5533SMathieu Fehr   resultType = dynType;
4779e0b5533SMathieu Fehr   return success();
4789e0b5533SMathieu Fehr }
4799e0b5533SMathieu Fehr 
printIfDynamicType(Type type,AsmPrinter & printer)4809e0b5533SMathieu Fehr LogicalResult ExtensibleDialect::printIfDynamicType(Type type,
4819e0b5533SMathieu Fehr                                                     AsmPrinter &printer) {
4829e0b5533SMathieu Fehr   if (auto dynType = type.dyn_cast<DynamicType>()) {
4839e0b5533SMathieu Fehr     dynType.print(printer);
4849e0b5533SMathieu Fehr     return success();
4859e0b5533SMathieu Fehr   }
4869e0b5533SMathieu Fehr   return failure();
4879e0b5533SMathieu Fehr }
4889e0b5533SMathieu Fehr 
parseOptionalDynamicAttr(StringRef attrName,AsmParser & parser,Attribute & resultAttr) const4899e0b5533SMathieu Fehr OptionalParseResult ExtensibleDialect::parseOptionalDynamicAttr(
4909e0b5533SMathieu Fehr     StringRef attrName, AsmParser &parser, Attribute &resultAttr) const {
4919e0b5533SMathieu Fehr   DynamicAttrDefinition *attrDef = lookupAttrDefinition(attrName);
4929e0b5533SMathieu Fehr   if (!attrDef)
4939e0b5533SMathieu Fehr     return llvm::None;
4949e0b5533SMathieu Fehr 
4959e0b5533SMathieu Fehr   DynamicAttr dynAttr;
4969e0b5533SMathieu Fehr   if (DynamicAttr::parse(parser, attrDef, dynAttr))
4979e0b5533SMathieu Fehr     return failure();
4989e0b5533SMathieu Fehr   resultAttr = dynAttr;
4999e0b5533SMathieu Fehr   return success();
5009e0b5533SMathieu Fehr }
5019e0b5533SMathieu Fehr 
printIfDynamicAttr(Attribute attribute,AsmPrinter & printer)5029e0b5533SMathieu Fehr LogicalResult ExtensibleDialect::printIfDynamicAttr(Attribute attribute,
5039e0b5533SMathieu Fehr                                                     AsmPrinter &printer) {
5049e0b5533SMathieu Fehr   if (auto dynAttr = attribute.dyn_cast<DynamicAttr>()) {
5059e0b5533SMathieu Fehr     dynAttr.print(printer);
5069e0b5533SMathieu Fehr     return success();
5079e0b5533SMathieu Fehr   }
5089e0b5533SMathieu Fehr   return failure();
5099e0b5533SMathieu Fehr }
510