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