//===- DialectImplementation.h ----------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file contains utilities classes for implementing dialect attributes and // types. // //===----------------------------------------------------------------------===// #ifndef MLIR_IR_DIALECTIMPLEMENTATION_H #define MLIR_IR_DIALECTIMPLEMENTATION_H #include "mlir/IR/OpImplementation.h" #include namespace { // reference https://stackoverflow.com/a/16000226 template struct HasStaticDialectName : std::false_type {}; template struct HasStaticDialectName< T, typename std::enable_if< std::is_same<::llvm::StringLiteral, std::decay_t>::value, void>::type> : std::true_type {}; } // namespace namespace mlir { //===----------------------------------------------------------------------===// // DialectAsmPrinter //===----------------------------------------------------------------------===// /// This is a pure-virtual base class that exposes the asmprinter hooks /// necessary to implement a custom printAttribute/printType() method on a /// dialect. class DialectAsmPrinter : public AsmPrinter { public: using AsmPrinter::AsmPrinter; ~DialectAsmPrinter() override; }; //===----------------------------------------------------------------------===// // DialectAsmParser //===----------------------------------------------------------------------===// /// The DialectAsmParser has methods for interacting with the asm parser when /// parsing attributes and types. class DialectAsmParser : public AsmParser { public: using AsmParser::AsmParser; ~DialectAsmParser() override; /// Returns the full specification of the symbol being parsed. This allows for /// using a separate parser if necessary. virtual StringRef getFullSymbolSpec() const = 0; }; //===----------------------------------------------------------------------===// // Parse Fields //===----------------------------------------------------------------------===// /// Provide a template class that can be specialized by users to dispatch to /// parsers. Auto-generated parsers generate calls to `FieldParser::parse`, /// where `T` is the parameter storage type, to parse custom types. template struct FieldParser; /// Parse an attribute. template struct FieldParser< AttributeT, std::enable_if_t::value, AttributeT>> { static FailureOr parse(AsmParser &parser) { if constexpr (HasStaticDialectName::value) { parser.getContext()->getOrLoadDialect(AttributeT::dialectName); } AttributeT value; if (parser.parseCustomAttributeWithFallback(value)) return failure(); return value; } }; /// Parse a type. template struct FieldParser< TypeT, std::enable_if_t::value, TypeT>> { static FailureOr parse(AsmParser &parser) { TypeT value; if (parser.parseCustomTypeWithFallback(value)) return failure(); return value; } }; /// Parse any integer. template struct FieldParser::value || std::is_same_v), IntT>> { static FailureOr parse(AsmParser &parser) { IntT value{}; if (parser.parseInteger(value)) return failure(); return value; } }; /// Parse a string. template <> struct FieldParser { static FailureOr parse(AsmParser &parser) { std::string value; if (parser.parseString(&value)) return failure(); return value; } }; /// Parse an Optional attribute. template struct FieldParser< std::optional, std::enable_if_t::value, std::optional>> { static FailureOr> parse(AsmParser &parser) { if constexpr (HasStaticDialectName::value) { parser.getContext()->getOrLoadDialect(AttributeT::dialectName); } AttributeT attr; OptionalParseResult result = parser.parseOptionalAttribute(attr); if (result.has_value()) { if (succeeded(*result)) return {std::optional(attr)}; return failure(); } return {std::nullopt}; } }; /// Parse an Optional integer. template struct FieldParser< std::optional, std::enable_if_t::value, std::optional>> { static FailureOr> parse(AsmParser &parser) { IntT value; OptionalParseResult result = parser.parseOptionalInteger(value); if (result.has_value()) { if (succeeded(*result)) return {std::optional(value)}; return failure(); } return {std::nullopt}; } }; namespace detail { template using has_push_back_t = decltype(std::declval().push_back( std::declval())); } // namespace detail /// Parse any container that supports back insertion as a list. template struct FieldParser::value, ContainerT>> { using ElementT = typename ContainerT::value_type; static FailureOr parse(AsmParser &parser) { ContainerT elements; auto elementParser = [&]() { auto element = FieldParser::parse(parser); if (failed(element)) return failure(); elements.push_back(std::move(*element)); return success(); }; if (parser.parseCommaSeparatedList(elementParser)) return failure(); return elements; } }; /// Parse an affine map. template <> struct FieldParser { static FailureOr parse(AsmParser &parser) { AffineMap map; if (failed(parser.parseAffineMap(map))) return failure(); return map; } }; } // namespace mlir #endif // MLIR_IR_DIALECTIMPLEMENTATION_H