MLIR  22.0.0git
DialectImplementation.h
Go to the documentation of this file.
1 //===- DialectImplementation.h ----------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains utilities classes for implementing dialect attributes and
10 // types.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef MLIR_IR_DIALECTIMPLEMENTATION_H
15 #define MLIR_IR_DIALECTIMPLEMENTATION_H
16 
18 #include <type_traits>
19 
20 namespace {
21 
22 // reference https://stackoverflow.com/a/16000226
23 template <typename T, typename = void>
24 struct HasStaticDialectName : std::false_type {};
25 
26 template <typename T>
27 struct HasStaticDialectName<
28  T, typename std::enable_if<
29  std::is_same<::llvm::StringLiteral,
30  std::decay_t<decltype(T::dialectName)>>::value,
31  void>::type> : std::true_type {};
32 
33 } // namespace
34 
35 namespace mlir {
36 
37 //===----------------------------------------------------------------------===//
38 // DialectAsmPrinter
39 //===----------------------------------------------------------------------===//
40 
41 /// This is a pure-virtual base class that exposes the asmprinter hooks
42 /// necessary to implement a custom printAttribute/printType() method on a
43 /// dialect.
44 class DialectAsmPrinter : public AsmPrinter {
45 public:
47  ~DialectAsmPrinter() override;
48 };
49 
50 //===----------------------------------------------------------------------===//
51 // DialectAsmParser
52 //===----------------------------------------------------------------------===//
53 
54 /// The DialectAsmParser has methods for interacting with the asm parser when
55 /// parsing attributes and types.
56 class DialectAsmParser : public AsmParser {
57 public:
59  ~DialectAsmParser() override;
60 
61  /// Returns the full specification of the symbol being parsed. This allows for
62  /// using a separate parser if necessary.
63  virtual StringRef getFullSymbolSpec() const = 0;
64 };
65 
66 //===----------------------------------------------------------------------===//
67 // Parse Fields
68 //===----------------------------------------------------------------------===//
69 
70 /// Provide a template class that can be specialized by users to dispatch to
71 /// parsers. Auto-generated parsers generate calls to `FieldParser<T>::parse`,
72 /// where `T` is the parameter storage type, to parse custom types.
73 template <typename T, typename = T>
74 struct FieldParser;
75 
76 /// Parse an attribute.
77 template <typename AttributeT>
78 struct FieldParser<
79  AttributeT, std::enable_if_t<std::is_base_of<Attribute, AttributeT>::value,
80  AttributeT>> {
81  static FailureOr<AttributeT> parse(AsmParser &parser) {
82  if constexpr (HasStaticDialectName<AttributeT>::value) {
83  parser.getContext()->getOrLoadDialect(AttributeT::dialectName);
84  }
85  AttributeT value;
86  if (parser.parseCustomAttributeWithFallback(value))
87  return failure();
88  return value;
89  }
90 };
91 
92 /// Parse a type.
93 template <typename TypeT>
94 struct FieldParser<
95  TypeT, std::enable_if_t<std::is_base_of<Type, TypeT>::value, TypeT>> {
96  static FailureOr<TypeT> parse(AsmParser &parser) {
97  TypeT value;
98  if (parser.parseCustomTypeWithFallback(value))
99  return failure();
100  return value;
101  }
102 };
103 
104 /// Parse any integer.
105 template <typename IntT>
106 struct FieldParser<IntT, std::enable_if_t<(std::is_integral<IntT>::value ||
107  std::is_same_v<IntT, llvm::APInt>),
108  IntT>> {
109  static FailureOr<IntT> parse(AsmParser &parser) {
110  IntT value{};
111  if (parser.parseInteger(value))
112  return failure();
113  return value;
114  }
115 };
116 
117 /// Parse a string.
118 template <>
119 struct FieldParser<std::string> {
120  static FailureOr<std::string> parse(AsmParser &parser) {
121  std::string value;
122  if (parser.parseString(&value))
123  return failure();
124  return value;
125  }
126 };
127 
128 /// Parse an Optional attribute.
129 template <typename AttributeT>
130 struct FieldParser<
131  std::optional<AttributeT>,
132  std::enable_if_t<std::is_base_of<Attribute, AttributeT>::value,
133  std::optional<AttributeT>>> {
134  static FailureOr<std::optional<AttributeT>> parse(AsmParser &parser) {
135  if constexpr (HasStaticDialectName<AttributeT>::value) {
136  parser.getContext()->getOrLoadDialect(AttributeT::dialectName);
137  }
138  AttributeT attr;
139  OptionalParseResult result = parser.parseOptionalAttribute(attr);
140  if (result.has_value()) {
141  if (succeeded(*result))
142  return {std::optional<AttributeT>(attr)};
143  return failure();
144  }
145  return {std::nullopt};
146  }
147 };
148 
149 /// Parse an Optional integer.
150 template <typename IntT>
151 struct FieldParser<
152  std::optional<IntT>,
153  std::enable_if_t<std::is_integral<IntT>::value, std::optional<IntT>>> {
154  static FailureOr<std::optional<IntT>> parse(AsmParser &parser) {
155  IntT value;
156  OptionalParseResult result = parser.parseOptionalInteger(value);
157  if (result.has_value()) {
158  if (succeeded(*result))
159  return {std::optional<IntT>(value)};
160  return failure();
161  }
162  return {std::nullopt};
163  }
164 };
165 
166 namespace detail {
167 template <typename T>
168 using has_push_back_t = decltype(std::declval<T>().push_back(
169  std::declval<typename T::value_type &&>()));
170 } // namespace detail
171 
172 /// Parse any container that supports back insertion as a list.
173 template <typename ContainerT>
174 struct FieldParser<ContainerT,
175  std::enable_if_t<llvm::is_detected<detail::has_push_back_t,
176  ContainerT>::value,
177  ContainerT>> {
178  using ElementT = typename ContainerT::value_type;
179  static FailureOr<ContainerT> parse(AsmParser &parser) {
180  ContainerT elements;
181  auto elementParser = [&]() {
182  auto element = FieldParser<ElementT>::parse(parser);
183  if (failed(element))
184  return failure();
185  elements.push_back(std::move(*element));
186  return success();
187  };
188  if (parser.parseCommaSeparatedList(elementParser))
189  return failure();
190  return elements;
191  }
192 };
193 
194 /// Parse an affine map.
195 template <>
197  static FailureOr<AffineMap> parse(AsmParser &parser) {
198  AffineMap map;
199  if (failed(parser.parseAffineMap(map)))
200  return failure();
201  return map;
202  }
203 };
204 
205 } // namespace mlir
206 
207 #endif // MLIR_IR_DIALECTIMPLEMENTATION_H
A multi-dimensional affine map Affine map's are immutable like Type's, and they are uniqued.
Definition: AffineMap.h:46
This base class exposes generic asm parser hooks, usable across the various derived parsers.
virtual OptionalParseResult parseOptionalInteger(APInt &result)=0
Parse an optional integer value from the stream.
AsmParser()=default
virtual ParseResult parseCommaSeparatedList(Delimiter delimiter, function_ref< ParseResult()> parseElementFn, StringRef contextMessage=StringRef())=0
Parse a list of comma-separated items with an optional delimiter.
MLIRContext * getContext() const
Definition: AsmPrinter.cpp:72
ParseResult parseInteger(IntT &result)
Parse an integer value from the stream.
virtual ParseResult parseAffineMap(AffineMap &map)=0
Parse an affine map instance into 'map'.
virtual ParseResult parseCustomAttributeWithFallback(Attribute &result, Type type, function_ref< ParseResult(Attribute &result, Type type)> parseAttribute)=0
Parse a custom attribute with the provided callback, unless the next token is #, in which case the ge...
ParseResult parseString(std::string *string)
Parse a quoted string token.
virtual ParseResult parseCustomTypeWithFallback(Type &result, function_ref< ParseResult(Type &result)> parseType)=0
Parse a custom type with the provided callback, unless the next token is #, in which case the generic...
virtual OptionalParseResult parseOptionalAttribute(Attribute &result, Type type={})=0
Parse an arbitrary optional attribute of a given type and return it in result.
This base class exposes generic asm printer hooks, usable across the various derived printers.
AsmPrinter()=default
Initialize the printer with no internal implementation.
The DialectAsmParser has methods for interacting with the asm parser when parsing attributes and type...
virtual StringRef getFullSymbolSpec() const =0
Returns the full specification of the symbol being parsed.
~DialectAsmParser() override
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
~DialectAsmPrinter() override
T * getOrLoadDialect()
Get (or create) a dialect for the given derived dialect type.
Definition: MLIRContext.h:100
This class implements Optional functionality for ParseResult.
Definition: OpDefinition.h:40
bool has_value() const
Returns true if we contain a valid ParseResult value.
Definition: OpDefinition.h:50
decltype(std::declval< T >().push_back(std::declval< typename T::value_type && >())) has_push_back_t
QueryRef parse(llvm::StringRef line, const QuerySession &qs)
Definition: Query.cpp:21
detail::InFlightRemark failed(Location loc, RemarkOpts opts)
Report an optimization remark that failed.
Definition: Remarks.h:491
Include the generated interface declarations.
static FailureOr< AffineMap > parse(AsmParser &parser)
static FailureOr< std::string > parse(AsmParser &parser)
Provide a template class that can be specialized by users to dispatch to parsers.