MLIR  18.0.0git
OpImplementation.h
Go to the documentation of this file.
1 //===- OpImplementation.h - Classes for implementing Op types ---*- 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 classes used by the implementation details of Op types.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef MLIR_IR_OPIMPLEMENTATION_H
14 #define MLIR_IR_OPIMPLEMENTATION_H
15 
16 #include "mlir/IR/BuiltinTypes.h"
18 #include "mlir/IR/OpDefinition.h"
19 #include "llvm/ADT/Twine.h"
20 #include "llvm/Support/SMLoc.h"
21 #include <optional>
22 
23 namespace mlir {
24 class AsmParsedResourceEntry;
25 class AsmResourceBuilder;
26 class Builder;
27 
28 //===----------------------------------------------------------------------===//
29 // AsmDialectResourceHandle
30 //===----------------------------------------------------------------------===//
31 
32 /// This class represents an opaque handle to a dialect resource entry.
34 public:
36  AsmDialectResourceHandle(void *resource, TypeID resourceID, Dialect *dialect)
37  : resource(resource), opaqueID(resourceID), dialect(dialect) {}
38  bool operator==(const AsmDialectResourceHandle &other) const {
39  return resource == other.resource;
40  }
41 
42  /// Return an opaque pointer to the referenced resource.
43  void *getResource() const { return resource; }
44 
45  /// Return the type ID of the resource.
46  TypeID getTypeID() const { return opaqueID; }
47 
48  /// Return the dialect that owns the resource.
49  Dialect *getDialect() const { return dialect; }
50 
51 private:
52  /// The opaque handle to the dialect resource.
53  void *resource = nullptr;
54  /// The type of the resource referenced.
55  TypeID opaqueID;
56  /// The dialect owning the given resource.
57  Dialect *dialect;
58 };
59 
60 /// This class represents a CRTP base class for dialect resource handles. It
61 /// abstracts away various utilities necessary for defined derived resource
62 /// handles.
63 template <typename DerivedT, typename ResourceT, typename DialectT>
65 public:
66  using Dialect = DialectT;
67 
68  /// Construct a handle from a pointer to the resource. The given pointer
69  /// should be guaranteed to live beyond the life of this handle.
70  AsmDialectResourceHandleBase(ResourceT *resource, DialectT *dialect)
71  : AsmDialectResourceHandle(resource, TypeID::get<DerivedT>(), dialect) {}
73  : AsmDialectResourceHandle(handle) {
74  assert(handle.getTypeID() == TypeID::get<DerivedT>());
75  }
76 
77  /// Return the resource referenced by this handle.
78  ResourceT *getResource() {
79  return static_cast<ResourceT *>(AsmDialectResourceHandle::getResource());
80  }
81  const ResourceT *getResource() const {
82  return const_cast<AsmDialectResourceHandleBase *>(this)->getResource();
83  }
84 
85  /// Return the dialect that owns the resource.
86  DialectT *getDialect() const {
87  return static_cast<DialectT *>(AsmDialectResourceHandle::getDialect());
88  }
89 
90  /// Support llvm style casting.
91  static bool classof(const AsmDialectResourceHandle *handle) {
92  return handle->getTypeID() == TypeID::get<DerivedT>();
93  }
94 };
95 
96 inline llvm::hash_code hash_value(const AsmDialectResourceHandle &param) {
97  return llvm::hash_value(param.getResource());
98 }
99 
100 //===----------------------------------------------------------------------===//
101 // AsmPrinter
102 //===----------------------------------------------------------------------===//
103 
104 /// This base class exposes generic asm printer hooks, usable across the various
105 /// derived printers.
106 class AsmPrinter {
107 public:
108  /// This class contains the internal default implementation of the base
109  /// printer methods.
110  class Impl;
111 
112  /// Initialize the printer with the given internal implementation.
114  virtual ~AsmPrinter();
115 
116  /// Return the raw output stream used by this printer.
117  virtual raw_ostream &getStream() const;
118 
119  /// Print the given floating point value in a stabilized form that can be
120  /// roundtripped through the IR. This is the companion to the 'parseFloat'
121  /// hook on the AsmParser.
122  virtual void printFloat(const APFloat &value);
123 
124  virtual void printType(Type type);
125  virtual void printAttribute(Attribute attr);
126 
127  /// Trait to check if `AttrType` provides a `print` method.
128  template <typename AttrOrType>
130  decltype(std::declval<AttrOrType>().print(std::declval<AsmPrinter &>()));
131  template <typename AttrOrType>
133  llvm::is_detected<has_print_method, AttrOrType>;
134 
135  /// Print the provided attribute in the context of an operation custom
136  /// printer/parser: this will invoke directly the print method on the
137  /// attribute class and skip the `#dialect.mnemonic` prefix in most cases.
138  template <typename AttrOrType,
139  std::enable_if_t<detect_has_print_method<AttrOrType>::value>
140  *sfinae = nullptr>
141  void printStrippedAttrOrType(AttrOrType attrOrType) {
142  if (succeeded(printAlias(attrOrType)))
143  return;
144 
145  raw_ostream &os = getStream();
146  uint64_t posPrior = os.tell();
147  attrOrType.print(*this);
148  if (posPrior != os.tell())
149  return;
150 
151  // Fallback to printing with prefix if the above failed to write anything
152  // to the output stream.
153  *this << attrOrType;
154  }
155 
156  /// Print the provided array of attributes or types in the context of an
157  /// operation custom printer/parser: this will invoke directly the print
158  /// method on the attribute class and skip the `#dialect.mnemonic` prefix in
159  /// most cases.
160  template <typename AttrOrType,
161  std::enable_if_t<detect_has_print_method<AttrOrType>::value>
162  *sfinae = nullptr>
164  llvm::interleaveComma(
165  attrOrTypes, getStream(),
166  [this](AttrOrType attrOrType) { printStrippedAttrOrType(attrOrType); });
167  }
168 
169  /// SFINAE for printing the provided attribute in the context of an operation
170  /// custom printer in the case where the attribute does not define a print
171  /// method.
172  template <typename AttrOrType,
173  std::enable_if_t<!detect_has_print_method<AttrOrType>::value>
174  *sfinae = nullptr>
175  void printStrippedAttrOrType(AttrOrType attrOrType) {
176  *this << attrOrType;
177  }
178 
179  /// Print the given attribute without its type. The corresponding parser must
180  /// provide a valid type for the attribute.
181  virtual void printAttributeWithoutType(Attribute attr);
182 
183  /// Print the given string as a keyword, or a quoted and escaped string if it
184  /// has any special or non-printable characters in it.
185  virtual void printKeywordOrString(StringRef keyword);
186 
187  /// Print the given string as a quoted string, escaping any special or
188  /// non-printable characters in it.
189  virtual void printString(StringRef string);
190 
191  /// Print the given string as a symbol reference, i.e. a form representable by
192  /// a SymbolRefAttr. A symbol reference is represented as a string prefixed
193  /// with '@'. The reference is surrounded with ""'s and escaped if it has any
194  /// special or non-printable characters in it.
195  virtual void printSymbolName(StringRef symbolRef);
196 
197  /// Print a handle to the given dialect resource.
198  virtual void printResourceHandle(const AsmDialectResourceHandle &resource);
199 
200  /// Print an optional arrow followed by a type list.
201  template <typename TypeRange>
203  if (types.begin() != types.end())
204  printArrowTypeList(types);
205  }
206  template <typename TypeRange>
208  auto &os = getStream() << " -> ";
209 
210  bool wrapped = !llvm::hasSingleElement(types) ||
211  llvm::isa<FunctionType>((*types.begin()));
212  if (wrapped)
213  os << '(';
214  llvm::interleaveComma(types, *this);
215  if (wrapped)
216  os << ')';
217  }
218 
219  /// Print the two given type ranges in a functional form.
220  template <typename InputRangeT, typename ResultRangeT>
221  void printFunctionalType(InputRangeT &&inputs, ResultRangeT &&results) {
222  auto &os = getStream();
223  os << '(';
224  llvm::interleaveComma(inputs, *this);
225  os << ')';
226  printArrowTypeList(results);
227  }
228 
229  /// Class used to automatically end a cyclic region on destruction.
231  public:
232  explicit CyclicPrintReset(AsmPrinter *printer) : printer(printer) {}
233 
235  if (printer)
236  printer->popCyclicPrinting();
237  }
238 
240 
242 
244  : printer(std::exchange(rhs.printer, nullptr)) {}
245 
247  printer = std::exchange(rhs.printer, nullptr);
248  return *this;
249  }
250 
251  private:
252  AsmPrinter *printer;
253  };
254 
255  /// Attempts to start a cyclic printing region for `attrOrType`.
256  /// A cyclic printing region starts with this call and ends with the
257  /// destruction of the returned `CyclicPrintReset`. During this time,
258  /// calling `tryStartCyclicPrint` with the same attribute in any printer
259  /// will lead to returning failure.
260  ///
261  /// This makes it possible to break infinite recursions when trying to print
262  /// cyclic attributes or types by printing only immutable parameters if nested
263  /// within itself.
264  template <class AttrOrTypeT>
266  static_assert(
267  std::is_base_of_v<AttributeTrait::IsMutable<AttrOrTypeT>,
268  AttrOrTypeT> ||
269  std::is_base_of_v<TypeTrait::IsMutable<AttrOrTypeT>, AttrOrTypeT>,
270  "Only mutable attributes or types can be cyclic");
271  if (failed(pushCyclicPrinting(attrOrType.getAsOpaquePointer())))
272  return failure();
273  return CyclicPrintReset(this);
274  }
275 
276 protected:
277  /// Initialize the printer with no internal implementation. In this case, all
278  /// virtual methods of this class must be overriden.
279  AsmPrinter() = default;
280 
281  /// Pushes a new attribute or type in the form of a type erased pointer
282  /// into an internal set.
283  /// Returns success if the type or attribute was inserted in the set or
284  /// failure if it was already contained.
285  virtual LogicalResult pushCyclicPrinting(const void *opaquePointer);
286 
287  /// Removes the element that was last inserted with a successful call to
288  /// `pushCyclicPrinting`. There must be exactly one `popCyclicPrinting` call
289  /// in reverse order of all successful `pushCyclicPrinting`.
290  virtual void popCyclicPrinting();
291 
292 private:
293  AsmPrinter(const AsmPrinter &) = delete;
294  void operator=(const AsmPrinter &) = delete;
295 
296  /// Print the alias for the given attribute, return failure if no alias could
297  /// be printed.
298  virtual LogicalResult printAlias(Attribute attr);
299 
300  /// Print the alias for the given type, return failure if no alias could
301  /// be printed.
302  virtual LogicalResult printAlias(Type type);
303 
304  /// The internal implementation of the printer.
305  Impl *impl{nullptr};
306 };
307 
308 template <typename AsmPrinterT>
309 inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value,
310  AsmPrinterT &>
311 operator<<(AsmPrinterT &p, Type type) {
312  p.printType(type);
313  return p;
314 }
315 
316 template <typename AsmPrinterT>
317 inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value,
318  AsmPrinterT &>
319 operator<<(AsmPrinterT &p, Attribute attr) {
320  p.printAttribute(attr);
321  return p;
322 }
323 
324 template <typename AsmPrinterT>
325 inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value,
326  AsmPrinterT &>
327 operator<<(AsmPrinterT &p, const APFloat &value) {
328  p.printFloat(value);
329  return p;
330 }
331 template <typename AsmPrinterT>
332 inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value,
333  AsmPrinterT &>
334 operator<<(AsmPrinterT &p, float value) {
335  return p << APFloat(value);
336 }
337 template <typename AsmPrinterT>
338 inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value,
339  AsmPrinterT &>
340 operator<<(AsmPrinterT &p, double value) {
341  return p << APFloat(value);
342 }
343 
344 // Support printing anything that isn't convertible to one of the other
345 // streamable types, even if it isn't exactly one of them. For example, we want
346 // to print FunctionType with the Type version above, not have it match this.
347 template <typename AsmPrinterT, typename T,
348  std::enable_if_t<!std::is_convertible<T &, Value &>::value &&
349  !std::is_convertible<T &, Type &>::value &&
350  !std::is_convertible<T &, Attribute &>::value &&
351  !std::is_convertible<T &, ValueRange>::value &&
352  !std::is_convertible<T &, APFloat &>::value &&
353  !llvm::is_one_of<T, bool, float, double>::value,
354  T> * = nullptr>
355 inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value,
356  AsmPrinterT &>
357 operator<<(AsmPrinterT &p, const T &other) {
358  p.getStream() << other;
359  return p;
360 }
361 
362 template <typename AsmPrinterT>
363 inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value,
364  AsmPrinterT &>
365 operator<<(AsmPrinterT &p, bool value) {
366  return p << (value ? StringRef("true") : "false");
367 }
368 
369 template <typename AsmPrinterT, typename ValueRangeT>
370 inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value,
371  AsmPrinterT &>
372 operator<<(AsmPrinterT &p, const ValueTypeRange<ValueRangeT> &types) {
373  llvm::interleaveComma(types, p);
374  return p;
375 }
376 
377 template <typename AsmPrinterT>
378 inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value,
379  AsmPrinterT &>
380 operator<<(AsmPrinterT &p, const TypeRange &types) {
381  llvm::interleaveComma(types, p);
382  return p;
383 }
384 
385 // Prevent matching the TypeRange version above for ValueRange
386 // printing through base AsmPrinter. This is needed so that the
387 // ValueRange printing behaviour does not change from printing
388 // the SSA values to printing the types for the operands when
389 // using AsmPrinter instead of OpAsmPrinter.
390 template <typename AsmPrinterT, typename T>
391 inline std::enable_if_t<std::is_same<AsmPrinter, AsmPrinterT>::value &&
392  std::is_convertible<T &, ValueRange>::value,
393  AsmPrinterT &>
394 operator<<(AsmPrinterT &p, const T &other) = delete;
395 
396 template <typename AsmPrinterT, typename ElementT>
397 inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value,
398  AsmPrinterT &>
399 operator<<(AsmPrinterT &p, ArrayRef<ElementT> types) {
400  llvm::interleaveComma(types, p);
401  return p;
402 }
403 
404 //===----------------------------------------------------------------------===//
405 // OpAsmPrinter
406 //===----------------------------------------------------------------------===//
407 
408 /// This is a pure-virtual base class that exposes the asmprinter hooks
409 /// necessary to implement a custom print() method.
410 class OpAsmPrinter : public AsmPrinter {
411 public:
413  ~OpAsmPrinter() override;
414 
415  /// Print a loc(...) specifier if printing debug info is enabled.
417 
418  /// Print a newline and indent the printer to the start of the current
419  /// operation.
420  virtual void printNewline() = 0;
421 
422  /// Increase indentation.
423  virtual void increaseIndent() = 0;
424 
425  /// Decrease indentation.
426  virtual void decreaseIndent() = 0;
427 
428  /// Print a block argument in the usual format of:
429  /// %ssaName : type {attr1=42} loc("here")
430  /// where location printing is controlled by the standard internal option.
431  /// You may pass omitType=true to not print a type, and pass an empty
432  /// attribute list if you don't care for attributes.
434  ArrayRef<NamedAttribute> argAttrs = {},
435  bool omitType = false) = 0;
436 
437  /// Print implementations for various things an operation contains.
438  virtual void printOperand(Value value) = 0;
439  virtual void printOperand(Value value, raw_ostream &os) = 0;
440 
441  /// Print a comma separated list of operands.
442  template <typename ContainerType>
443  void printOperands(const ContainerType &container) {
444  printOperands(container.begin(), container.end());
445  }
446 
447  /// Print a comma separated list of operands.
448  template <typename IteratorType>
449  void printOperands(IteratorType it, IteratorType end) {
450  llvm::interleaveComma(llvm::make_range(it, end), getStream(),
451  [this](Value value) { printOperand(value); });
452  }
453 
454  /// Print the given successor.
455  virtual void printSuccessor(Block *successor) = 0;
456 
457  /// Print the successor and its operands.
458  virtual void printSuccessorAndUseList(Block *successor,
459  ValueRange succOperands) = 0;
460 
461  /// If the specified operation has attributes, print out an attribute
462  /// dictionary with their values. elidedAttrs allows the client to ignore
463  /// specific well known attributes, commonly used if the attribute value is
464  /// printed some other way (like as a fixed operand).
466  ArrayRef<StringRef> elidedAttrs = {}) = 0;
467 
468  /// If the specified operation has attributes, print out an attribute
469  /// dictionary prefixed with 'attributes'.
470  virtual void
472  ArrayRef<StringRef> elidedAttrs = {}) = 0;
473 
474  /// Prints the entire operation with the custom assembly form, if available,
475  /// or the generic assembly form, otherwise.
476  virtual void printCustomOrGenericOp(Operation *op) = 0;
477 
478  /// Print the entire operation with the default generic assembly form.
479  /// If `printOpName` is true, then the operation name is printed (the default)
480  /// otherwise it is omitted and the print will start with the operand list.
481  virtual void printGenericOp(Operation *op, bool printOpName = true) = 0;
482 
483  /// Prints a region.
484  /// If 'printEntryBlockArgs' is false, the arguments of the
485  /// block are not printed. If 'printBlockTerminator' is false, the terminator
486  /// operation of the block is not printed. If printEmptyBlock is true, then
487  /// the block header is printed even if the block is empty.
488  virtual void printRegion(Region &blocks, bool printEntryBlockArgs = true,
489  bool printBlockTerminators = true,
490  bool printEmptyBlock = false) = 0;
491 
492  /// Renumber the arguments for the specified region to the same names as the
493  /// SSA values in namesToUse. This may only be used for IsolatedFromAbove
494  /// operations. If any entry in namesToUse is null, the corresponding
495  /// argument name is left alone.
496  virtual void shadowRegionArgs(Region &region, ValueRange namesToUse) = 0;
497 
498  /// Prints an affine map of SSA ids, where SSA id names are used in place
499  /// of dims/symbols.
500  /// Operand values must come from single-result sources, and be valid
501  /// dimensions/symbol identifiers according to mlir::isValidDim/Symbol.
502  virtual void printAffineMapOfSSAIds(AffineMapAttr mapAttr,
503  ValueRange operands) = 0;
504 
505  /// Prints an affine expression of SSA ids with SSA id names used instead of
506  /// dims and symbols.
507  /// Operand values must come from single-result sources, and be valid
508  /// dimensions/symbol identifiers according to mlir::isValidDim/Symbol.
509  virtual void printAffineExprOfSSAIds(AffineExpr expr, ValueRange dimOperands,
510  ValueRange symOperands) = 0;
511 
512  /// Print the complete type of an operation in functional form.
513  void printFunctionalType(Operation *op);
515 };
516 
517 // Make the implementations convenient to use.
519  p.printOperand(value);
520  return p;
521 }
522 
523 template <typename T,
524  std::enable_if_t<std::is_convertible<T &, ValueRange>::value &&
525  !std::is_convertible<T &, Value &>::value,
526  T> * = nullptr>
527 inline OpAsmPrinter &operator<<(OpAsmPrinter &p, const T &values) {
528  p.printOperands(values);
529  return p;
530 }
531 
533  p.printSuccessor(value);
534  return p;
535 }
536 
537 //===----------------------------------------------------------------------===//
538 // AsmParser
539 //===----------------------------------------------------------------------===//
540 
541 /// This base class exposes generic asm parser hooks, usable across the various
542 /// derived parsers.
543 class AsmParser {
544 public:
545  AsmParser() = default;
546  virtual ~AsmParser();
547 
548  MLIRContext *getContext() const;
549 
550  /// Return the location of the original name token.
551  virtual SMLoc getNameLoc() const = 0;
552 
553  //===--------------------------------------------------------------------===//
554  // Utilities
555  //===--------------------------------------------------------------------===//
556 
557  /// Emit a diagnostic at the specified location and return failure.
558  virtual InFlightDiagnostic emitError(SMLoc loc,
559  const Twine &message = {}) = 0;
560 
561  /// Return a builder which provides useful access to MLIRContext, global
562  /// objects like types and attributes.
563  virtual Builder &getBuilder() const = 0;
564 
565  /// Get the location of the next token and store it into the argument. This
566  /// always succeeds.
567  virtual SMLoc getCurrentLocation() = 0;
569  *loc = getCurrentLocation();
570  return success();
571  }
572 
573  /// Re-encode the given source location as an MLIR location and return it.
574  /// Note: This method should only be used when a `Location` is necessary, as
575  /// the encoding process is not efficient.
576  virtual Location getEncodedSourceLoc(SMLoc loc) = 0;
577 
578  //===--------------------------------------------------------------------===//
579  // Token Parsing
580  //===--------------------------------------------------------------------===//
581 
582  /// Parse a '->' token.
583  virtual ParseResult parseArrow() = 0;
584 
585  /// Parse a '->' token if present
587 
588  /// Parse a `{` token.
589  virtual ParseResult parseLBrace() = 0;
590 
591  /// Parse a `{` token if present.
593 
594  /// Parse a `}` token.
595  virtual ParseResult parseRBrace() = 0;
596 
597  /// Parse a `}` token if present.
599 
600  /// Parse a `:` token.
601  virtual ParseResult parseColon() = 0;
602 
603  /// Parse a `:` token if present.
605 
606  /// Parse a `,` token.
607  virtual ParseResult parseComma() = 0;
608 
609  /// Parse a `,` token if present.
611 
612  /// Parse a `=` token.
613  virtual ParseResult parseEqual() = 0;
614 
615  /// Parse a `=` token if present.
617 
618  /// Parse a '<' token.
619  virtual ParseResult parseLess() = 0;
620 
621  /// Parse a '<' token if present.
623 
624  /// Parse a '>' token.
625  virtual ParseResult parseGreater() = 0;
626 
627  /// Parse a '>' token if present.
629 
630  /// Parse a '?' token.
631  virtual ParseResult parseQuestion() = 0;
632 
633  /// Parse a '?' token if present.
635 
636  /// Parse a '+' token.
637  virtual ParseResult parsePlus() = 0;
638 
639  /// Parse a '+' token if present.
641 
642  /// Parse a '*' token.
643  virtual ParseResult parseStar() = 0;
644 
645  /// Parse a '*' token if present.
647 
648  /// Parse a '|' token.
650 
651  /// Parse a '|' token if present.
653 
654  /// Parse a quoted string token.
655  ParseResult parseString(std::string *string) {
656  auto loc = getCurrentLocation();
657  if (parseOptionalString(string))
658  return emitError(loc, "expected string");
659  return success();
660  }
661 
662  /// Parse a quoted string token if present.
663  virtual ParseResult parseOptionalString(std::string *string) = 0;
664 
665  /// Parses a Base64 encoded string of bytes.
666  virtual ParseResult parseBase64Bytes(std::vector<char> *bytes) = 0;
667 
668  /// Parse a `(` token.
669  virtual ParseResult parseLParen() = 0;
670 
671  /// Parse a `(` token if present.
673 
674  /// Parse a `)` token.
675  virtual ParseResult parseRParen() = 0;
676 
677  /// Parse a `)` token if present.
679 
680  /// Parse a `[` token.
681  virtual ParseResult parseLSquare() = 0;
682 
683  /// Parse a `[` token if present.
685 
686  /// Parse a `]` token.
687  virtual ParseResult parseRSquare() = 0;
688 
689  /// Parse a `]` token if present.
691 
692  /// Parse a `...` token.
693  virtual ParseResult parseEllipsis() = 0;
694 
695  /// Parse a `...` token if present;
697 
698  /// Parse a floating point value from the stream.
699  virtual ParseResult parseFloat(double &result) = 0;
700 
701  /// Parse an integer value from the stream.
702  template <typename IntT>
703  ParseResult parseInteger(IntT &result) {
704  auto loc = getCurrentLocation();
705  OptionalParseResult parseResult = parseOptionalInteger(result);
706  if (!parseResult.has_value())
707  return emitError(loc, "expected integer value");
708  return *parseResult;
709  }
710 
711  /// Parse an optional integer value from the stream.
712  virtual OptionalParseResult parseOptionalInteger(APInt &result) = 0;
713 
714  template <typename IntT>
716  auto loc = getCurrentLocation();
717 
718  // Parse the unsigned variant.
719  APInt uintResult;
720  OptionalParseResult parseResult = parseOptionalInteger(uintResult);
721  if (!parseResult.has_value() || failed(*parseResult))
722  return parseResult;
723 
724  // Try to convert to the provided integer type. sextOrTrunc is correct even
725  // for unsigned types because parseOptionalInteger ensures the sign bit is
726  // zero for non-negated integers.
727  result =
728  (IntT)uintResult.sextOrTrunc(sizeof(IntT) * CHAR_BIT).getLimitedValue();
729  if (APInt(uintResult.getBitWidth(), result) != uintResult)
730  return emitError(loc, "integer value too large");
731  return success();
732  }
733 
734  /// These are the supported delimiters around operand lists and region
735  /// argument lists, used by parseOperandList.
736  enum class Delimiter {
737  /// Zero or more operands with no delimiters.
738  None,
739  /// Parens surrounding zero or more operands.
740  Paren,
741  /// Square brackets surrounding zero or more operands.
742  Square,
743  /// <> brackets surrounding zero or more operands.
744  LessGreater,
745  /// {} brackets surrounding zero or more operands.
746  Braces,
747  /// Parens supporting zero or more operands, or nothing.
749  /// Square brackets supporting zero or more ops, or nothing.
751  /// <> brackets supporting zero or more ops, or nothing.
753  /// {} brackets surrounding zero or more operands, or nothing.
755  };
756 
757  /// Parse a list of comma-separated items with an optional delimiter. If a
758  /// delimiter is provided, then an empty list is allowed. If not, then at
759  /// least one element will be parsed.
760  ///
761  /// contextMessage is an optional message appended to "expected '('" sorts of
762  /// diagnostics when parsing the delimeters.
763  virtual ParseResult
765  function_ref<ParseResult()> parseElementFn,
766  StringRef contextMessage = StringRef()) = 0;
767 
768  /// Parse a comma separated list of elements that must have at least one entry
769  /// in it.
772  return parseCommaSeparatedList(Delimiter::None, parseElementFn);
773  }
774 
775  //===--------------------------------------------------------------------===//
776  // Keyword Parsing
777  //===--------------------------------------------------------------------===//
778 
779  /// This class represents a StringSwitch like class that is useful for parsing
780  /// expected keywords. On construction, unless a non-empty keyword is
781  /// provided, it invokes `parseKeyword` and processes each of the provided
782  /// cases statements until a match is hit. The provided `ResultT` must be
783  /// assignable from `failure()`.
784  template <typename ResultT = ParseResult>
786  public:
787  KeywordSwitch(AsmParser &parser, StringRef *keyword = nullptr)
788  : parser(parser), loc(parser.getCurrentLocation()) {
789  if (keyword && !keyword->empty())
790  this->keyword = *keyword;
791  else if (failed(parser.parseKeywordOrCompletion(&this->keyword)))
792  result = failure();
793  }
794  /// Case that uses the provided value when true.
795  KeywordSwitch &Case(StringLiteral str, ResultT value) {
796  return Case(str, [&](StringRef, SMLoc) { return std::move(value); });
797  }
798  KeywordSwitch &Default(ResultT value) {
799  return Default([&](StringRef, SMLoc) { return std::move(value); });
800  }
801  /// Case that invokes the provided functor when true. The parameters passed
802  /// to the functor are the keyword, and the location of the keyword (in case
803  /// any errors need to be emitted).
804  template <typename FnT>
805  std::enable_if_t<!std::is_convertible<FnT, ResultT>::value, KeywordSwitch &>
806  Case(StringLiteral str, FnT &&fn) {
807  if (result)
808  return *this;
809 
810  // If the word was empty, record this as a completion.
811  if (keyword.empty())
812  parser.codeCompleteExpectedTokens(str);
813  else if (keyword == str)
814  result.emplace(std::move(fn(keyword, loc)));
815  return *this;
816  }
817  template <typename FnT>
818  std::enable_if_t<!std::is_convertible<FnT, ResultT>::value, KeywordSwitch &>
819  Default(FnT &&fn) {
820  if (!result)
821  result.emplace(fn(keyword, loc));
822  return *this;
823  }
824 
825  /// Returns true if this switch has a value yet.
826  bool hasValue() const { return result.has_value(); }
827 
828  /// Return the result of the switch.
829  [[nodiscard]] operator ResultT() {
830  if (!result)
831  return parser.emitError(loc, "unexpected keyword: ") << keyword;
832  return std::move(*result);
833  }
834 
835  private:
836  /// The parser used to construct this switch.
837  AsmParser &parser;
838 
839  /// The location of the keyword, used to emit errors as necessary.
840  SMLoc loc;
841 
842  /// The parsed keyword itself.
843  StringRef keyword;
844 
845  /// The result of the switch statement or std::nullopt if currently unknown.
846  std::optional<ResultT> result;
847  };
848 
849  /// Parse a given keyword.
850  ParseResult parseKeyword(StringRef keyword) {
851  return parseKeyword(keyword, "");
852  }
853  virtual ParseResult parseKeyword(StringRef keyword, const Twine &msg) = 0;
854 
855  /// Parse a keyword into 'keyword'.
856  ParseResult parseKeyword(StringRef *keyword) {
857  auto loc = getCurrentLocation();
858  if (parseOptionalKeyword(keyword))
859  return emitError(loc, "expected valid keyword");
860  return success();
861  }
862 
863  /// Parse the given keyword if present.
864  virtual ParseResult parseOptionalKeyword(StringRef keyword) = 0;
865 
866  /// Parse a keyword, if present, into 'keyword'.
867  virtual ParseResult parseOptionalKeyword(StringRef *keyword) = 0;
868 
869  /// Parse a keyword, if present, and if one of the 'allowedValues',
870  /// into 'keyword'
871  virtual ParseResult
872  parseOptionalKeyword(StringRef *keyword,
873  ArrayRef<StringRef> allowedValues) = 0;
874 
875  /// Parse a keyword or a quoted string.
876  ParseResult parseKeywordOrString(std::string *result) {
878  return emitError(getCurrentLocation())
879  << "expected valid keyword or string";
880  return success();
881  }
882 
883  /// Parse an optional keyword or string.
884  virtual ParseResult parseOptionalKeywordOrString(std::string *result) = 0;
885 
886  //===--------------------------------------------------------------------===//
887  // Attribute/Type Parsing
888  //===--------------------------------------------------------------------===//
889 
890  /// Invoke the `getChecked` method of the given Attribute or Type class, using
891  /// the provided location to emit errors in the case of failure. Note that
892  /// unlike `OpBuilder::getType`, this method does not implicitly insert a
893  /// context parameter.
894  template <typename T, typename... ParamsT>
895  auto getChecked(SMLoc loc, ParamsT &&...params) {
896  return T::getChecked([&] { return emitError(loc); },
897  std::forward<ParamsT>(params)...);
898  }
899  /// A variant of `getChecked` that uses the result of `getNameLoc` to emit
900  /// errors.
901  template <typename T, typename... ParamsT>
902  auto getChecked(ParamsT &&...params) {
903  return T::getChecked([&] { return emitError(getNameLoc()); },
904  std::forward<ParamsT>(params)...);
905  }
906 
907  //===--------------------------------------------------------------------===//
908  // Attribute Parsing
909  //===--------------------------------------------------------------------===//
910 
911  /// Parse an arbitrary attribute of a given type and return it in result.
912  virtual ParseResult parseAttribute(Attribute &result, Type type = {}) = 0;
913 
914  /// Parse a custom attribute with the provided callback, unless the next
915  /// token is `#`, in which case the generic parser is invoked.
917  Attribute &result, Type type,
918  function_ref<ParseResult(Attribute &result, Type type)>
919  parseAttribute) = 0;
920 
921  /// Parse an attribute of a specific kind and type.
922  template <typename AttrType>
923  ParseResult parseAttribute(AttrType &result, Type type = {}) {
924  SMLoc loc = getCurrentLocation();
925 
926  // Parse any kind of attribute.
927  Attribute attr;
928  if (parseAttribute(attr, type))
929  return failure();
930 
931  // Check for the right kind of attribute.
932  if (!(result = llvm::dyn_cast<AttrType>(attr)))
933  return emitError(loc, "invalid kind of attribute specified");
934 
935  return success();
936  }
937 
938  /// Parse an arbitrary attribute and return it in result. This also adds the
939  /// attribute to the specified attribute list with the specified name.
940  ParseResult parseAttribute(Attribute &result, StringRef attrName,
941  NamedAttrList &attrs) {
942  return parseAttribute(result, Type(), attrName, attrs);
943  }
944 
945  /// Parse an attribute of a specific kind and type.
946  template <typename AttrType>
947  ParseResult parseAttribute(AttrType &result, StringRef attrName,
948  NamedAttrList &attrs) {
949  return parseAttribute(result, Type(), attrName, attrs);
950  }
951 
952  /// Parse an arbitrary attribute of a given type and populate it in `result`.
953  /// This also adds the attribute to the specified attribute list with the
954  /// specified name.
955  template <typename AttrType>
956  ParseResult parseAttribute(AttrType &result, Type type, StringRef attrName,
957  NamedAttrList &attrs) {
958  SMLoc loc = getCurrentLocation();
959 
960  // Parse any kind of attribute.
961  Attribute attr;
962  if (parseAttribute(attr, type))
963  return failure();
964 
965  // Check for the right kind of attribute.
966  result = llvm::dyn_cast<AttrType>(attr);
967  if (!result)
968  return emitError(loc, "invalid kind of attribute specified");
969 
970  attrs.append(attrName, result);
971  return success();
972  }
973 
974  /// Trait to check if `AttrType` provides a `parse` method.
975  template <typename AttrType>
976  using has_parse_method = decltype(AttrType::parse(std::declval<AsmParser &>(),
977  std::declval<Type>()));
978  template <typename AttrType>
979  using detect_has_parse_method = llvm::is_detected<has_parse_method, AttrType>;
980 
981  /// Parse a custom attribute of a given type unless the next token is `#`, in
982  /// which case the generic parser is invoked. The parsed attribute is
983  /// populated in `result` and also added to the specified attribute list with
984  /// the specified name.
985  template <typename AttrType>
986  std::enable_if_t<detect_has_parse_method<AttrType>::value, ParseResult>
987  parseCustomAttributeWithFallback(AttrType &result, Type type,
988  StringRef attrName, NamedAttrList &attrs) {
989  SMLoc loc = getCurrentLocation();
990 
991  // Parse any kind of attribute.
992  Attribute attr;
994  attr, type, [&](Attribute &result, Type type) -> ParseResult {
995  result = AttrType::parse(*this, type);
996  if (!result)
997  return failure();
998  return success();
999  }))
1000  return failure();
1001 
1002  // Check for the right kind of attribute.
1003  result = llvm::dyn_cast<AttrType>(attr);
1004  if (!result)
1005  return emitError(loc, "invalid kind of attribute specified");
1006 
1007  attrs.append(attrName, result);
1008  return success();
1009  }
1010 
1011  /// SFINAE parsing method for Attribute that don't implement a parse method.
1012  template <typename AttrType>
1013  std::enable_if_t<!detect_has_parse_method<AttrType>::value, ParseResult>
1014  parseCustomAttributeWithFallback(AttrType &result, Type type,
1015  StringRef attrName, NamedAttrList &attrs) {
1016  return parseAttribute(result, type, attrName, attrs);
1017  }
1018 
1019  /// Parse a custom attribute of a given type unless the next token is `#`, in
1020  /// which case the generic parser is invoked. The parsed attribute is
1021  /// populated in `result`.
1022  template <typename AttrType>
1023  std::enable_if_t<detect_has_parse_method<AttrType>::value, ParseResult>
1024  parseCustomAttributeWithFallback(AttrType &result, Type type = {}) {
1025  SMLoc loc = getCurrentLocation();
1026 
1027  // Parse any kind of attribute.
1028  Attribute attr;
1030  attr, type, [&](Attribute &result, Type type) -> ParseResult {
1031  result = AttrType::parse(*this, type);
1032  return success(!!result);
1033  }))
1034  return failure();
1035 
1036  // Check for the right kind of attribute.
1037  result = llvm::dyn_cast<AttrType>(attr);
1038  if (!result)
1039  return emitError(loc, "invalid kind of attribute specified");
1040  return success();
1041  }
1042 
1043  /// SFINAE parsing method for Attribute that don't implement a parse method.
1044  template <typename AttrType>
1045  std::enable_if_t<!detect_has_parse_method<AttrType>::value, ParseResult>
1046  parseCustomAttributeWithFallback(AttrType &result, Type type = {}) {
1047  return parseAttribute(result, type);
1048  }
1049 
1050  /// Parse an arbitrary optional attribute of a given type and return it in
1051  /// result.
1053  Type type = {}) = 0;
1054 
1055  /// Parse an optional array attribute and return it in result.
1056  virtual OptionalParseResult parseOptionalAttribute(ArrayAttr &result,
1057  Type type = {}) = 0;
1058 
1059  /// Parse an optional string attribute and return it in result.
1060  virtual OptionalParseResult parseOptionalAttribute(StringAttr &result,
1061  Type type = {}) = 0;
1062 
1063  /// Parse an optional symbol ref attribute and return it in result.
1064  virtual OptionalParseResult parseOptionalAttribute(SymbolRefAttr &result,
1065  Type type = {}) = 0;
1066 
1067  /// Parse an optional attribute of a specific type and add it to the list with
1068  /// the specified name.
1069  template <typename AttrType>
1071  StringRef attrName,
1072  NamedAttrList &attrs) {
1073  return parseOptionalAttribute(result, Type(), attrName, attrs);
1074  }
1075 
1076  /// Parse an optional attribute of a specific type and add it to the list with
1077  /// the specified name.
1078  template <typename AttrType>
1080  StringRef attrName,
1081  NamedAttrList &attrs) {
1082  OptionalParseResult parseResult = parseOptionalAttribute(result, type);
1083  if (parseResult.has_value() && succeeded(*parseResult))
1084  attrs.append(attrName, result);
1085  return parseResult;
1086  }
1087 
1088  /// Parse a named dictionary into 'result' if it is present.
1090 
1091  /// Parse a named dictionary into 'result' if the `attributes` keyword is
1092  /// present.
1093  virtual ParseResult
1095 
1096  /// Parse an affine map instance into 'map'.
1098 
1099  /// Parse an affine expr instance into 'expr' using the already computed
1100  /// mapping from symbols to affine expressions in 'symbolSet'.
1101  virtual ParseResult
1102  parseAffineExpr(ArrayRef<std::pair<StringRef, AffineExpr>> symbolSet,
1103  AffineExpr &expr) = 0;
1104 
1105  /// Parse an integer set instance into 'set'.
1107 
1108  //===--------------------------------------------------------------------===//
1109  // Identifier Parsing
1110  //===--------------------------------------------------------------------===//
1111 
1112  /// Parse an @-identifier and store it (without the '@' symbol) in a string
1113  /// attribute.
1114  ParseResult parseSymbolName(StringAttr &result) {
1115  if (failed(parseOptionalSymbolName(result)))
1116  return emitError(getCurrentLocation())
1117  << "expected valid '@'-identifier for symbol name";
1118  return success();
1119  }
1120 
1121  /// Parse an @-identifier and store it (without the '@' symbol) in a string
1122  /// attribute named 'attrName'.
1123  ParseResult parseSymbolName(StringAttr &result, StringRef attrName,
1124  NamedAttrList &attrs) {
1125  if (parseSymbolName(result))
1126  return failure();
1127  attrs.append(attrName, result);
1128  return success();
1129  }
1130 
1131  /// Parse an optional @-identifier and store it (without the '@' symbol) in a
1132  /// string attribute.
1133  virtual ParseResult parseOptionalSymbolName(StringAttr &result) = 0;
1134 
1135  /// Parse an optional @-identifier and store it (without the '@' symbol) in a
1136  /// string attribute named 'attrName'.
1137  ParseResult parseOptionalSymbolName(StringAttr &result, StringRef attrName,
1138  NamedAttrList &attrs) {
1139  if (succeeded(parseOptionalSymbolName(result))) {
1140  attrs.append(attrName, result);
1141  return success();
1142  }
1143  return failure();
1144  }
1145 
1146  //===--------------------------------------------------------------------===//
1147  // Resource Parsing
1148  //===--------------------------------------------------------------------===//
1149 
1150  /// Parse a handle to a resource within the assembly format.
1151  template <typename ResourceT>
1153  SMLoc handleLoc = getCurrentLocation();
1154 
1155  // Try to load the dialect that owns the handle.
1156  auto *dialect =
1157  getContext()->getOrLoadDialect<typename ResourceT::Dialect>();
1158  if (!dialect) {
1159  return emitError(handleLoc)
1160  << "dialect '" << ResourceT::Dialect::getDialectNamespace()
1161  << "' is unknown";
1162  }
1163 
1165  if (failed(handle))
1166  return failure();
1167  if (auto *result = dyn_cast<ResourceT>(&*handle))
1168  return std::move(*result);
1169  return emitError(handleLoc) << "provided resource handle differs from the "
1170  "expected resource type";
1171  }
1172 
1173  //===--------------------------------------------------------------------===//
1174  // Type Parsing
1175  //===--------------------------------------------------------------------===//
1176 
1177  /// Parse a type.
1178  virtual ParseResult parseType(Type &result) = 0;
1179 
1180  /// Parse a custom type with the provided callback, unless the next
1181  /// token is `#`, in which case the generic parser is invoked.
1183  Type &result, function_ref<ParseResult(Type &result)> parseType) = 0;
1184 
1185  /// Parse an optional type.
1187 
1188  /// Parse a type of a specific type.
1189  template <typename TypeT>
1190  ParseResult parseType(TypeT &result) {
1191  SMLoc loc = getCurrentLocation();
1192 
1193  // Parse any kind of type.
1194  Type type;
1195  if (parseType(type))
1196  return failure();
1197 
1198  // Check for the right kind of type.
1199  result = llvm::dyn_cast<TypeT>(type);
1200  if (!result)
1201  return emitError(loc, "invalid kind of type specified");
1202 
1203  return success();
1204  }
1205 
1206  /// Trait to check if `TypeT` provides a `parse` method.
1207  template <typename TypeT>
1209  decltype(TypeT::parse(std::declval<AsmParser &>()));
1210  template <typename TypeT>
1212  llvm::is_detected<type_has_parse_method, TypeT>;
1213 
1214  /// Parse a custom Type of a given type unless the next token is `#`, in
1215  /// which case the generic parser is invoked. The parsed Type is
1216  /// populated in `result`.
1217  template <typename TypeT>
1218  std::enable_if_t<detect_type_has_parse_method<TypeT>::value, ParseResult>
1220  SMLoc loc = getCurrentLocation();
1221 
1222  // Parse any kind of Type.
1223  Type type;
1224  if (parseCustomTypeWithFallback(type, [&](Type &result) -> ParseResult {
1225  result = TypeT::parse(*this);
1226  return success(!!result);
1227  }))
1228  return failure();
1229 
1230  // Check for the right kind of Type.
1231  result = llvm::dyn_cast<TypeT>(type);
1232  if (!result)
1233  return emitError(loc, "invalid kind of Type specified");
1234  return success();
1235  }
1236 
1237  /// SFINAE parsing method for Type that don't implement a parse method.
1238  template <typename TypeT>
1239  std::enable_if_t<!detect_type_has_parse_method<TypeT>::value, ParseResult>
1241  return parseType(result);
1242  }
1243 
1244  /// Parse a type list.
1246 
1247  /// Parse an arrow followed by a type list.
1249 
1250  /// Parse an optional arrow followed by a type list.
1251  virtual ParseResult
1253 
1254  /// Parse a colon followed by a type.
1255  virtual ParseResult parseColonType(Type &result) = 0;
1256 
1257  /// Parse a colon followed by a type of a specific kind, e.g. a FunctionType.
1258  template <typename TypeType>
1259  ParseResult parseColonType(TypeType &result) {
1260  SMLoc loc = getCurrentLocation();
1261 
1262  // Parse any kind of type.
1263  Type type;
1264  if (parseColonType(type))
1265  return failure();
1266 
1267  // Check for the right kind of type.
1268  result = llvm::dyn_cast<TypeType>(type);
1269  if (!result)
1270  return emitError(loc, "invalid kind of type specified");
1271 
1272  return success();
1273  }
1274 
1275  /// Parse a colon followed by a type list, which must have at least one type.
1277 
1278  /// Parse an optional colon followed by a type list, which if present must
1279  /// have at least one type.
1280  virtual ParseResult
1282 
1283  /// Parse a keyword followed by a type.
1284  ParseResult parseKeywordType(const char *keyword, Type &result) {
1285  return failure(parseKeyword(keyword) || parseType(result));
1286  }
1287 
1288  /// Add the specified type to the end of the specified type list and return
1289  /// success. This is a helper designed to allow parse methods to be simple
1290  /// and chain through || operators.
1292  result.push_back(type);
1293  return success();
1294  }
1295 
1296  /// Add the specified types to the end of the specified type list and return
1297  /// success. This is a helper designed to allow parse methods to be simple
1298  /// and chain through || operators.
1300  SmallVectorImpl<Type> &result) {
1301  result.append(types.begin(), types.end());
1302  return success();
1303  }
1304 
1305  /// Parse a dimension list of a tensor or memref type. This populates the
1306  /// dimension list, using ShapedType::kDynamic for the `?` dimensions if
1307  /// `allowDynamic` is set and errors out on `?` otherwise. Parsing the
1308  /// trailing `x` is configurable.
1309  ///
1310  /// dimension-list ::= eps | dimension (`x` dimension)*
1311  /// dimension-list-with-trailing-x ::= (dimension `x`)*
1312  /// dimension ::= `?` | decimal-literal
1313  ///
1314  /// When `allowDynamic` is not set, this is used to parse:
1315  ///
1316  /// static-dimension-list ::= eps | decimal-literal (`x` decimal-literal)*
1317  /// static-dimension-list-with-trailing-x ::= (dimension `x`)*
1319  bool allowDynamic = true,
1320  bool withTrailingX = true) = 0;
1321 
1322  /// Parse an 'x' token in a dimension list, handling the case where the x is
1323  /// juxtaposed with an element type, as in "xf32", leaving the "f32" as the
1324  /// next token.
1326 
1327  /// Class used to automatically end a cyclic region on destruction.
1329  public:
1330  explicit CyclicParseReset(AsmParser *parser) : parser(parser) {}
1331 
1333  if (parser)
1334  parser->popCyclicParsing();
1335  }
1336 
1340  : parser(std::exchange(rhs.parser, nullptr)) {}
1342  parser = std::exchange(rhs.parser, nullptr);
1343  return *this;
1344  }
1345 
1346  private:
1347  AsmParser *parser;
1348  };
1349 
1350  /// Attempts to start a cyclic parsing region for `attrOrType`.
1351  /// A cyclic parsing region starts with this call and ends with the
1352  /// destruction of the returned `CyclicParseReset`. During this time,
1353  /// calling `tryStartCyclicParse` with the same attribute in any parser
1354  /// will lead to returning failure.
1355  ///
1356  /// This makes it possible to parse cyclic attributes or types by parsing a
1357  /// short from if nested within itself.
1358  template <class AttrOrTypeT>
1360  static_assert(
1361  std::is_base_of_v<AttributeTrait::IsMutable<AttrOrTypeT>,
1362  AttrOrTypeT> ||
1363  std::is_base_of_v<TypeTrait::IsMutable<AttrOrTypeT>, AttrOrTypeT>,
1364  "Only mutable attributes or types can be cyclic");
1365  if (failed(pushCyclicParsing(attrOrType.getAsOpaquePointer())))
1366  return failure();
1367 
1368  return CyclicParseReset(this);
1369  }
1370 
1371 protected:
1372  /// Parse a handle to a resource within the assembly format for the given
1373  /// dialect.
1376 
1377  /// Pushes a new attribute or type in the form of a type erased pointer
1378  /// into an internal set.
1379  /// Returns success if the type or attribute was inserted in the set or
1380  /// failure if it was already contained.
1381  virtual LogicalResult pushCyclicParsing(const void *opaquePointer) = 0;
1382 
1383  /// Removes the element that was last inserted with a successful call to
1384  /// `pushCyclicParsing`. There must be exactly one `popCyclicParsing` call
1385  /// in reverse order of all successful `pushCyclicParsing`.
1386  virtual void popCyclicParsing() = 0;
1387 
1388  //===--------------------------------------------------------------------===//
1389  // Code Completion
1390  //===--------------------------------------------------------------------===//
1391 
1392  /// Parse a keyword, or an empty string if the current location signals a code
1393  /// completion.
1394  virtual ParseResult parseKeywordOrCompletion(StringRef *keyword) = 0;
1395 
1396  /// Signal the code completion of a set of expected tokens.
1398 
1399 private:
1400  AsmParser(const AsmParser &) = delete;
1401  void operator=(const AsmParser &) = delete;
1402 };
1403 
1404 //===----------------------------------------------------------------------===//
1405 // OpAsmParser
1406 //===----------------------------------------------------------------------===//
1407 
1408 /// The OpAsmParser has methods for interacting with the asm parser: parsing
1409 /// things from it, emitting errors etc. It has an intentionally high-level API
1410 /// that is designed to reduce/constrain syntax innovation in individual
1411 /// operations.
1412 ///
1413 /// For example, consider an op like this:
1414 ///
1415 /// %x = load %p[%1, %2] : memref<...>
1416 ///
1417 /// The "%x = load" tokens are already parsed and therefore invisible to the
1418 /// custom op parser. This can be supported by calling `parseOperandList` to
1419 /// parse the %p, then calling `parseOperandList` with a `SquareDelimiter` to
1420 /// parse the indices, then calling `parseColonTypeList` to parse the result
1421 /// type.
1422 ///
1423 class OpAsmParser : public AsmParser {
1424 public:
1425  using AsmParser::AsmParser;
1426  ~OpAsmParser() override;
1427 
1428  /// Parse a loc(...) specifier if present, filling in result if so.
1429  /// Location for BlockArgument and Operation may be deferred with an alias, in
1430  /// which case an OpaqueLoc is set and will be resolved when parsing
1431  /// completes.
1432  virtual ParseResult
1433  parseOptionalLocationSpecifier(std::optional<Location> &result) = 0;
1434 
1435  /// Return the name of the specified result in the specified syntax, as well
1436  /// as the sub-element in the name. It returns an empty string and ~0U for
1437  /// invalid result numbers. For example, in this operation:
1438  ///
1439  /// %x, %y:2, %z = foo.op
1440  ///
1441  /// getResultName(0) == {"x", 0 }
1442  /// getResultName(1) == {"y", 0 }
1443  /// getResultName(2) == {"y", 1 }
1444  /// getResultName(3) == {"z", 0 }
1445  /// getResultName(4) == {"", ~0U }
1446  virtual std::pair<StringRef, unsigned>
1447  getResultName(unsigned resultNo) const = 0;
1448 
1449  /// Return the number of declared SSA results. This returns 4 for the foo.op
1450  /// example in the comment for `getResultName`.
1451  virtual size_t getNumResults() const = 0;
1452 
1453  // These methods emit an error and return failure or success. This allows
1454  // these to be chained together into a linear sequence of || expressions in
1455  // many cases.
1456 
1457  /// Parse an operation in its generic form.
1458  /// The parsed operation is parsed in the current context and inserted in the
1459  /// provided block and insertion point. The results produced by this operation
1460  /// aren't mapped to any named value in the parser. Returns nullptr on
1461  /// failure.
1462  virtual Operation *parseGenericOperation(Block *insertBlock,
1463  Block::iterator insertPt) = 0;
1464 
1465  /// Parse the name of an operation, in the custom form. On success, return a
1466  /// an object of type 'OperationName'. Otherwise, failure is returned.
1468 
1469  //===--------------------------------------------------------------------===//
1470  // Operand Parsing
1471  //===--------------------------------------------------------------------===//
1472 
1473  /// This is the representation of an operand reference.
1475  SMLoc location; // Location of the token.
1476  StringRef name; // Value name, e.g. %42 or %abc
1477  unsigned number; // Number, e.g. 12 for an operand like %xyz#12
1478  };
1479 
1480  /// Parse different components, viz., use-info of operand(s), successor(s),
1481  /// region(s), attribute(s) and function-type, of the generic form of an
1482  /// operation instance and populate the input operation-state 'result' with
1483  /// those components. If any of the components is explicitly provided, then
1484  /// skip parsing that component.
1486  OperationState &result,
1487  std::optional<ArrayRef<UnresolvedOperand>> parsedOperandType =
1488  std::nullopt,
1489  std::optional<ArrayRef<Block *>> parsedSuccessors = std::nullopt,
1490  std::optional<MutableArrayRef<std::unique_ptr<Region>>> parsedRegions =
1491  std::nullopt,
1492  std::optional<ArrayRef<NamedAttribute>> parsedAttributes = std::nullopt,
1493  std::optional<Attribute> parsedPropertiesAttribute = std::nullopt,
1494  std::optional<FunctionType> parsedFnType = std::nullopt) = 0;
1495 
1496  /// Parse a single SSA value operand name along with a result number if
1497  /// `allowResultNumber` is true.
1499  bool allowResultNumber = true) = 0;
1500 
1501  /// Parse a single operand if present.
1502  virtual OptionalParseResult
1504  bool allowResultNumber = true) = 0;
1505 
1506  /// Parse zero or more SSA comma-separated operand references with a specified
1507  /// surrounding delimiter, and an optional required operand count.
1508  virtual ParseResult
1510  Delimiter delimiter = Delimiter::None,
1511  bool allowResultNumber = true,
1512  int requiredOperandCount = -1) = 0;
1513 
1514  /// Parse a specified number of comma separated operands.
1516  int requiredOperandCount,
1517  Delimiter delimiter = Delimiter::None) {
1518  return parseOperandList(result, delimiter,
1519  /*allowResultNumber=*/true, requiredOperandCount);
1520  }
1521 
1522  /// Parse zero or more trailing SSA comma-separated trailing operand
1523  /// references with a specified surrounding delimiter, and an optional
1524  /// required operand count. A leading comma is expected before the
1525  /// operands.
1526  ParseResult
1528  Delimiter delimiter = Delimiter::None) {
1529  if (failed(parseOptionalComma()))
1530  return success(); // The comma is optional.
1531  return parseOperandList(result, delimiter);
1532  }
1533 
1534  /// Resolve an operand to an SSA value, emitting an error on failure.
1536  Type type,
1537  SmallVectorImpl<Value> &result) = 0;
1538 
1539  /// Resolve a list of operands to SSA values, emitting an error on failure, or
1540  /// appending the results to the list on success. This method should be used
1541  /// when all operands have the same type.
1542  template <typename Operands = ArrayRef<UnresolvedOperand>>
1543  ParseResult resolveOperands(Operands &&operands, Type type,
1544  SmallVectorImpl<Value> &result) {
1545  for (const UnresolvedOperand &operand : operands)
1546  if (resolveOperand(operand, type, result))
1547  return failure();
1548  return success();
1549  }
1550  template <typename Operands = ArrayRef<UnresolvedOperand>>
1551  ParseResult resolveOperands(Operands &&operands, Type type, SMLoc loc,
1552  SmallVectorImpl<Value> &result) {
1553  return resolveOperands(std::forward<Operands>(operands), type, result);
1554  }
1555 
1556  /// Resolve a list of operands and a list of operand types to SSA values,
1557  /// emitting an error and returning failure, or appending the results
1558  /// to the list on success.
1559  template <typename Operands = ArrayRef<UnresolvedOperand>,
1560  typename Types = ArrayRef<Type>>
1561  std::enable_if_t<!std::is_convertible<Types, Type>::value, ParseResult>
1562  resolveOperands(Operands &&operands, Types &&types, SMLoc loc,
1563  SmallVectorImpl<Value> &result) {
1564  size_t operandSize = llvm::range_size(operands);
1565  size_t typeSize = llvm::range_size(types);
1566  if (operandSize != typeSize)
1567  return emitError(loc)
1568  << operandSize << " operands present, but expected " << typeSize;
1569 
1570  for (auto [operand, type] : llvm::zip_equal(operands, types))
1571  if (resolveOperand(operand, type, result))
1572  return failure();
1573  return success();
1574  }
1575 
1576  /// Parses an affine map attribute where dims and symbols are SSA operands.
1577  /// Operand values must come from single-result sources, and be valid
1578  /// dimensions/symbol identifiers according to mlir::isValidDim/Symbol.
1579  virtual ParseResult
1581  Attribute &map, StringRef attrName,
1582  NamedAttrList &attrs,
1583  Delimiter delimiter = Delimiter::Square) = 0;
1584 
1585  /// Parses an affine expression where dims and symbols are SSA operands.
1586  /// Operand values must come from single-result sources, and be valid
1587  /// dimensions/symbol identifiers according to mlir::isValidDim/Symbol.
1588  virtual ParseResult
1590  SmallVectorImpl<UnresolvedOperand> &symbOperands,
1591  AffineExpr &expr) = 0;
1592 
1593  //===--------------------------------------------------------------------===//
1594  // Argument Parsing
1595  //===--------------------------------------------------------------------===//
1596 
1597  struct Argument {
1598  UnresolvedOperand ssaName; // SourceLoc, SSA name, result #.
1599  Type type; // Type.
1600  DictionaryAttr attrs; // Attributes if present.
1601  std::optional<Location> sourceLoc; // Source location specifier if present.
1602  };
1603 
1604  /// Parse a single argument with the following syntax:
1605  ///
1606  /// `%ssaName : !type { optionalAttrDict} loc(optionalSourceLoc)`
1607  ///
1608  /// If `allowType` is false or `allowAttrs` are false then the respective
1609  /// parts of the grammar are not parsed.
1610  virtual ParseResult parseArgument(Argument &result, bool allowType = false,
1611  bool allowAttrs = false) = 0;
1612 
1613  /// Parse a single argument if present.
1614  virtual OptionalParseResult
1615  parseOptionalArgument(Argument &result, bool allowType = false,
1616  bool allowAttrs = false) = 0;
1617 
1618  /// Parse zero or more arguments with a specified surrounding delimiter.
1620  Delimiter delimiter = Delimiter::None,
1621  bool allowType = false,
1622  bool allowAttrs = false) = 0;
1623 
1624  //===--------------------------------------------------------------------===//
1625  // Region Parsing
1626  //===--------------------------------------------------------------------===//
1627 
1628  /// Parses a region. Any parsed blocks are appended to 'region' and must be
1629  /// moved to the op regions after the op is created. The first block of the
1630  /// region takes 'arguments'.
1631  ///
1632  /// If 'enableNameShadowing' is set to true, the argument names are allowed to
1633  /// shadow the names of other existing SSA values defined above the region
1634  /// scope. 'enableNameShadowing' can only be set to true for regions attached
1635  /// to operations that are 'IsolatedFromAbove'.
1636  virtual ParseResult parseRegion(Region &region,
1637  ArrayRef<Argument> arguments = {},
1638  bool enableNameShadowing = false) = 0;
1639 
1640  /// Parses a region if present.
1641  virtual OptionalParseResult
1643  bool enableNameShadowing = false) = 0;
1644 
1645  /// Parses a region if present. If the region is present, a new region is
1646  /// allocated and placed in `region`. If no region is present or on failure,
1647  /// `region` remains untouched.
1648  virtual OptionalParseResult
1649  parseOptionalRegion(std::unique_ptr<Region> &region,
1650  ArrayRef<Argument> arguments = {},
1651  bool enableNameShadowing = false) = 0;
1652 
1653  //===--------------------------------------------------------------------===//
1654  // Successor Parsing
1655  //===--------------------------------------------------------------------===//
1656 
1657  /// Parse a single operation successor.
1658  virtual ParseResult parseSuccessor(Block *&dest) = 0;
1659 
1660  /// Parse an optional operation successor.
1662 
1663  /// Parse a single operation successor and its operand list.
1664  virtual ParseResult
1666 
1667  //===--------------------------------------------------------------------===//
1668  // Type Parsing
1669  //===--------------------------------------------------------------------===//
1670 
1671  /// Parse a list of assignments of the form
1672  /// (%x1 = %y1, %x2 = %y2, ...)
1676  if (!result.has_value())
1677  return emitError(getCurrentLocation(), "expected '('");
1678  return result.value();
1679  }
1680 
1681  virtual OptionalParseResult
1684 };
1685 
1686 //===--------------------------------------------------------------------===//
1687 // Dialect OpAsm interface.
1688 //===--------------------------------------------------------------------===//
1689 
1690 /// A functor used to set the name of the start of a result group of an
1691 /// operation. See 'getAsmResultNames' below for more details.
1692 using OpAsmSetValueNameFn = function_ref<void(Value, StringRef)>;
1693 
1694 /// A functor used to set the name of blocks in regions directly nested under
1695 /// an operation.
1696 using OpAsmSetBlockNameFn = function_ref<void(Block *, StringRef)>;
1697 
1699  : public DialectInterface::Base<OpAsmDialectInterface> {
1700 public:
1701  OpAsmDialectInterface(Dialect *dialect) : Base(dialect) {}
1702 
1703  //===------------------------------------------------------------------===//
1704  // Aliases
1705  //===------------------------------------------------------------------===//
1706 
1707  /// Holds the result of `getAlias` hook call.
1708  enum class AliasResult {
1709  /// The object (type or attribute) is not supported by the hook
1710  /// and an alias was not provided.
1711  NoAlias,
1712  /// An alias was provided, but it might be overriden by other hook.
1714  /// An alias was provided and it should be used
1715  /// (no other hooks will be checked).
1716  FinalAlias
1717  };
1718 
1719  /// Hooks for getting an alias identifier alias for a given symbol, that is
1720  /// not necessarily a part of this dialect. The identifier is used in place of
1721  /// the symbol when printing textual IR. These aliases must not contain `.` or
1722  /// end with a numeric digit([0-9]+).
1723  virtual AliasResult getAlias(Attribute attr, raw_ostream &os) const {
1724  return AliasResult::NoAlias;
1725  }
1726  virtual AliasResult getAlias(Type type, raw_ostream &os) const {
1727  return AliasResult::NoAlias;
1728  }
1729 
1730  //===--------------------------------------------------------------------===//
1731  // Resources
1732  //===--------------------------------------------------------------------===//
1733 
1734  /// Declare a resource with the given key, returning a handle to use for any
1735  /// references of this resource key within the IR during parsing. The result
1736  /// of `getResourceKey` on the returned handle is permitted to be different
1737  /// than `key`.
1739  declareResource(StringRef key) const {
1740  return failure();
1741  }
1742 
1743  /// Return a key to use for the given resource. This key should uniquely
1744  /// identify this resource within the dialect.
1745  virtual std::string
1747  llvm_unreachable(
1748  "Dialect must implement `getResourceKey` when defining resources");
1749  }
1750 
1751  /// Hook for parsing resource entries. Returns failure if the entry was not
1752  /// valid, or could otherwise not be processed correctly. Any necessary errors
1753  /// can be emitted via the provided entry.
1754  virtual LogicalResult parseResource(AsmParsedResourceEntry &entry) const;
1755 
1756  /// Hook for building resources to use during printing. The given `op` may be
1757  /// inspected to help determine what information to include.
1758  /// `referencedResources` contains all of the resources detected when printing
1759  /// 'op'.
1760  virtual void
1762  const SetVector<AsmDialectResourceHandle> &referencedResources,
1763  AsmResourceBuilder &builder) const {}
1764 };
1765 } // namespace mlir
1766 
1767 //===--------------------------------------------------------------------===//
1768 // Operation OpAsm interface.
1769 //===--------------------------------------------------------------------===//
1770 
1771 /// The OpAsmOpInterface, see OpAsmInterface.td for more details.
1772 #include "mlir/IR/OpAsmInterface.h.inc"
1773 
1774 namespace llvm {
1775 template <>
1776 struct DenseMapInfo<mlir::AsmDialectResourceHandle> {
1780  }
1784  }
1785  static unsigned getHashValue(const mlir::AsmDialectResourceHandle &handle) {
1787  }
1788  static bool isEqual(const mlir::AsmDialectResourceHandle &lhs,
1789  const mlir::AsmDialectResourceHandle &rhs) {
1790  return lhs.getResource() == rhs.getResource();
1791  }
1792 };
1793 } // namespace llvm
1794 
1795 #endif
static void print(spirv::VerCapExtAttr triple, DialectAsmPrinter &printer)
Base type for affine expression.
Definition: AffineExpr.h:68
A multi-dimensional affine map Affine map's are immutable like Type's, and they are uniqued.
Definition: AffineMap.h:44
This class represents a CRTP base class for dialect resource handles.
const ResourceT * getResource() const
AsmDialectResourceHandleBase(AsmDialectResourceHandle handle)
ResourceT * getResource()
Return the resource referenced by this handle.
static bool classof(const AsmDialectResourceHandle *handle)
Support llvm style casting.
AsmDialectResourceHandleBase(ResourceT *resource, DialectT *dialect)
Construct a handle from a pointer to the resource.
DialectT * getDialect() const
Return the dialect that owns the resource.
This class represents an opaque handle to a dialect resource entry.
Dialect * getDialect() const
Return the dialect that owns the resource.
TypeID getTypeID() const
Return the type ID of the resource.
bool operator==(const AsmDialectResourceHandle &other) const
AsmDialectResourceHandle(void *resource, TypeID resourceID, Dialect *dialect)
void * getResource() const
Return an opaque pointer to the referenced resource.
This class represents a single parsed resource entry.
Definition: AsmState.h:283
Class used to automatically end a cyclic region on destruction.
CyclicParseReset & operator=(CyclicParseReset &&rhs)
CyclicParseReset & operator=(const CyclicParseReset &)=delete
CyclicParseReset(const CyclicParseReset &)=delete
CyclicParseReset(CyclicParseReset &&rhs)
This class represents a StringSwitch like class that is useful for parsing expected keywords.
std::enable_if_t<!std::is_convertible< FnT, ResultT >::value, KeywordSwitch & > Default(FnT &&fn)
KeywordSwitch & Case(StringLiteral str, ResultT value)
Case that uses the provided value when true.
bool hasValue() const
Returns true if this switch has a value yet.
std::enable_if_t<!std::is_convertible< FnT, ResultT >::value, KeywordSwitch & > Case(StringLiteral str, FnT &&fn)
Case that invokes the provided functor when true.
KeywordSwitch & Default(ResultT value)
KeywordSwitch(AsmParser &parser, StringRef *keyword=nullptr)
This base class exposes generic asm parser hooks, usable across the various derived parsers.
llvm::is_detected< has_parse_method, AttrType > detect_has_parse_method
ParseResult parseSymbolName(StringAttr &result)
Parse an -identifier and store it (without the '@' symbol) in a string attribute.
virtual ParseResult parseLBrace()=0
Parse a { token.
Delimiter
These are the supported delimiters around operand lists and region argument lists,...
@ Paren
Parens surrounding zero or more operands.
@ None
Zero or more operands with no delimiters.
@ OptionalLessGreater
<> brackets supporting zero or more ops, or nothing.
@ Braces
{} brackets surrounding zero or more operands.
@ OptionalBraces
{} brackets surrounding zero or more operands, or nothing.
@ OptionalParen
Parens supporting zero or more operands, or nothing.
@ Square
Square brackets surrounding zero or more operands.
@ LessGreater
<> brackets surrounding zero or more operands.
@ OptionalSquare
Square brackets supporting zero or more ops, or nothing.
virtual OptionalParseResult parseOptionalInteger(APInt &result)=0
Parse an optional integer value from the stream.
AsmParser()=default
virtual ParseResult parseColonTypeList(SmallVectorImpl< Type > &result)=0
Parse a colon followed by a type list, which must have at least one type.
virtual ParseResult parseIntegerSet(IntegerSet &set)=0
Parse an integer set instance into 'set'.
virtual ParseResult parseOptionalKeywordOrString(std::string *result)=0
Parse an optional keyword or string.
virtual ParseResult parseOptionalSymbolName(StringAttr &result)=0
Parse an optional -identifier and store it (without the '@' symbol) in a string attribute.
FailureOr< CyclicParseReset > tryStartCyclicParse(AttrOrTypeT attrOrType)
Attempts to start a cyclic parsing region for attrOrType.
virtual ParseResult parseOptionalRBrace()=0
Parse a } token if present.
virtual ParseResult parsePlus()=0
Parse a '+' token.
ParseResult parseKeyword(StringRef *keyword)
Parse a keyword into 'keyword'.
virtual ParseResult parseCommaSeparatedList(Delimiter delimiter, function_ref< ParseResult()> parseElementFn, StringRef contextMessage=StringRef())=0
Parse a list of comma-separated items with an optional delimiter.
decltype(AttrType::parse(std::declval< AsmParser & >(), std::declval< Type >())) has_parse_method
Trait to check if AttrType provides a parse method.
virtual void popCyclicParsing()=0
Removes the element that was last inserted with a successful call to pushCyclicParsing.
virtual Builder & getBuilder() const =0
Return a builder which provides useful access to MLIRContext, global objects like types and attribute...
virtual ParseResult parseOptionalAttrDict(NamedAttrList &result)=0
Parse a named dictionary into 'result' if it is present.
virtual ParseResult parseOptionalEqual()=0
Parse a = token if present.
virtual ParseResult parseOptionalKeyword(StringRef keyword)=0
Parse the given keyword if present.
virtual OptionalParseResult parseOptionalType(Type &result)=0
Parse an optional type.
MLIRContext * getContext() const
Definition: AsmPrinter.cpp:68
virtual Location getEncodedSourceLoc(SMLoc loc)=0
Re-encode the given source location as an MLIR location and return it.
std::enable_if_t<!detect_type_has_parse_method< TypeT >::value, ParseResult > parseCustomTypeWithFallback(TypeT &result)
SFINAE parsing method for Type that don't implement a parse method.
virtual ParseResult parseRParen()=0
Parse a ) token.
virtual InFlightDiagnostic emitError(SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
virtual ParseResult parseOptionalColon()=0
Parse a : token if present.
virtual ParseResult parseLSquare()=0
Parse a [ token.
virtual ParseResult parseRSquare()=0
Parse a ] token.
virtual ParseResult parseOptionalColonTypeList(SmallVectorImpl< Type > &result)=0
Parse an optional colon followed by a type list, which if present must have at least one type.
ParseResult parseInteger(IntT &result)
Parse an integer value from the stream.
virtual ParseResult parseOptionalArrow()=0
Parse a '->' token if present.
ParseResult parseOptionalSymbolName(StringAttr &result, StringRef attrName, NamedAttrList &attrs)
Parse an optional -identifier and store it (without the '@' symbol) in a string attribute named 'attr...
ParseResult parseAttribute(AttrType &result, Type type, StringRef attrName, NamedAttrList &attrs)
Parse an arbitrary attribute of a given type and populate it in result.
ParseResult parseAttribute(AttrType &result, Type type={})
Parse an attribute of a specific kind and type.
ParseResult parseKeywordOrString(std::string *result)
Parse a keyword or a quoted string.
virtual void codeCompleteExpectedTokens(ArrayRef< StringRef > tokens)=0
Signal the code completion of a set of expected tokens.
virtual ParseResult parseRBrace()=0
Parse a } token.
virtual ParseResult parseAffineMap(AffineMap &map)=0
Parse an affine map instance into 'map'.
ParseResult addTypeToList(Type type, SmallVectorImpl< Type > &result)
Add the specified type to the end of the specified type list and return success.
virtual ParseResult parseOptionalRParen()=0
Parse a ) token if present.
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...
virtual ParseResult parseLess()=0
Parse a '<' token.
virtual ParseResult parseDimensionList(SmallVectorImpl< int64_t > &dimensions, bool allowDynamic=true, bool withTrailingX=true)=0
Parse a dimension list of a tensor or memref type.
ParseResult parseString(std::string *string)
Parse a quoted string token.
virtual ParseResult parseOptionalPlus()=0
Parse a '+' token if present.
virtual ParseResult parseOptionalKeyword(StringRef *keyword, ArrayRef< StringRef > allowedValues)=0
Parse a keyword, if present, and if one of the 'allowedValues', into 'keyword'.
virtual ParseResult parseOptionalGreater()=0
Parse a '>' token if present.
virtual ParseResult parseEqual()=0
Parse a = token.
std::enable_if_t<!detect_has_parse_method< AttrType >::value, ParseResult > parseCustomAttributeWithFallback(AttrType &result, Type type, StringRef attrName, NamedAttrList &attrs)
SFINAE parsing method for Attribute that don't implement a parse method.
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(ArrayAttr &result, Type type={})=0
Parse an optional array attribute and return it in result.
virtual ParseResult parseStar()=0
Parse a '*' token.
virtual ParseResult parseOptionalAttrDictWithKeyword(NamedAttrList &result)=0
Parse a named dictionary into 'result' if the attributes keyword is present.
virtual ParseResult parseColonType(Type &result)=0
Parse a colon followed by a type.
virtual OptionalParseResult parseOptionalAttribute(Attribute &result, Type type={})=0
Parse an arbitrary optional attribute of a given type and return it in result.
std::enable_if_t< detect_has_parse_method< AttrType >::value, ParseResult > parseCustomAttributeWithFallback(AttrType &result, Type type={})
Parse a custom attribute of a given type unless the next token is #, in which case the generic parser...
ParseResult parseCommaSeparatedList(function_ref< ParseResult()> parseElementFn)
Parse a comma separated list of elements that must have at least one entry in it.
virtual ParseResult parseVerticalBar()=0
Parse a '|' token.
virtual SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
virtual ParseResult parseOptionalComma()=0
Parse a , token if present.
OptionalParseResult parseOptionalAttribute(AttrType &result, StringRef attrName, NamedAttrList &attrs)
Parse an optional attribute of a specific type and add it to the list with the specified name.
auto getChecked(SMLoc loc, ParamsT &&...params)
Invoke the getChecked method of the given Attribute or Type class, using the provided location to emi...
virtual ParseResult parseColon()=0
Parse a : token.
ParseResult addTypesToList(ArrayRef< Type > types, SmallVectorImpl< Type > &result)
Add the specified types to the end of the specified type list and return success.
std::enable_if_t< detect_type_has_parse_method< TypeT >::value, ParseResult > parseCustomTypeWithFallback(TypeT &result)
Parse a custom Type of a given type unless the next token is #, in which case the generic parser is i...
ParseResult parseAttribute(Attribute &result, StringRef attrName, NamedAttrList &attrs)
Parse an arbitrary attribute and return it in result.
virtual OptionalParseResult parseOptionalAttribute(StringAttr &result, Type type={})=0
Parse an optional string attribute and return it in result.
virtual SMLoc getNameLoc() const =0
Return the location of the original name token.
virtual ParseResult parseOptionalString(std::string *string)=0
Parse a quoted string token if present.
OptionalParseResult parseOptionalInteger(IntT &result)
ParseResult getCurrentLocation(SMLoc *loc)
virtual ParseResult parseOptionalLess()=0
Parse a '<' token if present.
virtual ParseResult parseOptionalStar()=0
Parse a '*' token if present.
OptionalParseResult parseOptionalAttribute(AttrType &result, Type type, StringRef attrName, NamedAttrList &attrs)
Parse an optional attribute of a specific type and add it to the list with the specified name.
virtual OptionalParseResult parseOptionalAttribute(SymbolRefAttr &result, Type type={})=0
Parse an optional symbol ref attribute and return it in result.
virtual ParseResult parseQuestion()=0
Parse a '?' token.
ParseResult parseType(TypeT &result)
Parse a type of a specific type.
virtual ParseResult parseOptionalRSquare()=0
Parse a ] token if present.
virtual ParseResult parseArrow()=0
Parse a '->' token.
ParseResult parseColonType(TypeType &result)
Parse a colon followed by a type of a specific kind, e.g. a FunctionType.
virtual ParseResult parseGreater()=0
Parse a '>' token.
virtual ParseResult parseLParen()=0
Parse a ( token.
virtual ParseResult parseOptionalEllipsis()=0
Parse a ... token if present;.
std::enable_if_t<!detect_has_parse_method< AttrType >::value, ParseResult > parseCustomAttributeWithFallback(AttrType &result, Type type={})
SFINAE parsing method for Attribute that don't implement a parse method.
virtual ParseResult parseType(Type &result)=0
Parse a type.
ParseResult parseAttribute(AttrType &result, StringRef attrName, NamedAttrList &attrs)
Parse an attribute of a specific kind and type.
virtual ParseResult parseEllipsis()=0
Parse a ... token.
auto getChecked(ParamsT &&...params)
A variant of getChecked that uses the result of getNameLoc to emit errors.
virtual ParseResult parseAffineExpr(ArrayRef< std::pair< StringRef, AffineExpr >> symbolSet, AffineExpr &expr)=0
Parse an affine expr instance into 'expr' using the already computed mapping from symbols to affine e...
virtual ParseResult parseComma()=0
Parse a , token.
virtual ParseResult parseOptionalArrowTypeList(SmallVectorImpl< Type > &result)=0
Parse an optional arrow followed by a type list.
virtual ParseResult parseOptionalLParen()=0
Parse a ( token if present.
ParseResult parseKeywordType(const char *keyword, Type &result)
Parse a keyword followed by a type.
virtual ParseResult parseArrowTypeList(SmallVectorImpl< Type > &result)=0
Parse an arrow followed by a type list.
virtual ~AsmParser()
virtual ParseResult parseOptionalVerticalBar()=0
Parse a '|' token if present.
ParseResult parseTypeList(SmallVectorImpl< Type > &result)
Parse a type list.
Definition: AsmPrinter.cpp:72
virtual ParseResult parseBase64Bytes(std::vector< char > *bytes)=0
Parses a Base64 encoded string of bytes.
llvm::is_detected< type_has_parse_method, TypeT > detect_type_has_parse_method
virtual ParseResult parseKeywordOrCompletion(StringRef *keyword)=0
Parse a keyword, or an empty string if the current location signals a code completion.
virtual ParseResult parseFloat(double &result)=0
Parse a floating point value from the stream.
ParseResult parseSymbolName(StringAttr &result, StringRef attrName, NamedAttrList &attrs)
Parse an -identifier and store it (without the '@' symbol) in a string attribute named 'attrName'.
virtual ParseResult parseOptionalKeyword(StringRef *keyword)=0
Parse a keyword, if present, into 'keyword'.
decltype(TypeT::parse(std::declval< AsmParser & >())) type_has_parse_method
Trait to check if TypeT provides a parse method.
ParseResult parseKeyword(StringRef keyword)
Parse a given keyword.
virtual ParseResult parseOptionalLSquare()=0
Parse a [ token if present.
virtual LogicalResult pushCyclicParsing(const void *opaquePointer)=0
Pushes a new attribute or type in the form of a type erased pointer into an internal set.
virtual FailureOr< AsmDialectResourceHandle > parseResourceHandle(Dialect *dialect)=0
Parse a handle to a resource within the assembly format for the given dialect.
virtual ParseResult parseOptionalQuestion()=0
Parse a '?' token if present.
std::enable_if_t< detect_has_parse_method< AttrType >::value, ParseResult > parseCustomAttributeWithFallback(AttrType &result, Type type, StringRef attrName, NamedAttrList &attrs)
Parse a custom attribute of a given type unless the next token is #, in which case the generic parser...
FailureOr< ResourceT > parseResourceHandle()
Parse a handle to a resource within the assembly format.
virtual ParseResult parseAttribute(Attribute &result, Type type={})=0
Parse an arbitrary attribute of a given type and return it in result.
virtual ParseResult parseXInDimensionList()=0
Parse an 'x' token in a dimension list, handling the case where the x is juxtaposed with an element t...
virtual ParseResult parseOptionalLBrace()=0
Parse a { token if present.
virtual ParseResult parseKeyword(StringRef keyword, const Twine &msg)=0
Class used to automatically end a cyclic region on destruction.
CyclicPrintReset & operator=(const CyclicPrintReset &)=delete
CyclicPrintReset(const CyclicPrintReset &)=delete
CyclicPrintReset & operator=(CyclicPrintReset &&rhs)
CyclicPrintReset(CyclicPrintReset &&rhs)
This base class exposes generic asm printer hooks, usable across the various derived printers.
void printStrippedAttrOrType(ArrayRef< AttrOrType > attrOrTypes)
Print the provided array of attributes or types in the context of an operation custom printer/parser:...
FailureOr< CyclicPrintReset > tryStartCyclicPrint(AttrOrTypeT attrOrType)
Attempts to start a cyclic printing region for attrOrType.
virtual void printAttributeWithoutType(Attribute attr)
Print the given attribute without its type.
virtual void popCyclicPrinting()
Removes the element that was last inserted with a successful call to pushCyclicPrinting.
AsmPrinter()=default
Initialize the printer with no internal implementation.
void printFunctionalType(InputRangeT &&inputs, ResultRangeT &&results)
Print the two given type ranges in a functional form.
virtual LogicalResult pushCyclicPrinting(const void *opaquePointer)
Pushes a new attribute or type in the form of a type erased pointer into an internal set.
virtual void printType(Type type)
virtual void printKeywordOrString(StringRef keyword)
Print the given string as a keyword, or a quoted and escaped string if it has any special or non-prin...
llvm::is_detected< has_print_method, AttrOrType > detect_has_print_method
virtual void printSymbolName(StringRef symbolRef)
Print the given string as a symbol reference, i.e.
virtual void printString(StringRef string)
Print the given string as a quoted string, escaping any special or non-printable characters in it.
void printOptionalArrowTypeList(TypeRange &&types)
Print an optional arrow followed by a type list.
virtual void printAttribute(Attribute attr)
void printArrowTypeList(TypeRange &&types)
virtual ~AsmPrinter()
virtual raw_ostream & getStream() const
Return the raw output stream used by this printer.
virtual void printResourceHandle(const AsmDialectResourceHandle &resource)
Print a handle to the given dialect resource.
decltype(std::declval< AttrOrType >().print(std::declval< AsmPrinter & >())) has_print_method
Trait to check if AttrType provides a print method.
virtual void printFloat(const APFloat &value)
Print the given floating point value in a stabilized form that can be roundtripped through the IR.
void printStrippedAttrOrType(AttrOrType attrOrType)
Print the provided attribute in the context of an operation custom printer/parser: this will invoke d...
AsmPrinter(Impl &impl)
Initialize the printer with the given internal implementation.
This class is used to build resource entries for use by the printer.
Definition: AsmState.h:239
Attributes are known-constant values of operations.
Definition: Attributes.h:25
This class represents an argument of a Block.
Definition: Value.h:310
Block represents an ordered list of Operations.
Definition: Block.h:30
OpListType::iterator iterator
Definition: Block.h:133
This class is a general helper class for creating context-global objects like types,...
Definition: Builders.h:50
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
Definition: Dialect.h:41
This class provides support for representing a failure result, or a valid value of type T.
Definition: LogicalResult.h:78
This class represents a diagnostic that is inflight and set to be reported.
Definition: Diagnostics.h:308
An integer set representing a conjunction of one or more affine equalities and inequalities.
Definition: IntegerSet.h:44
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:63
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:60
T * getOrLoadDialect()
Get (or create) a dialect for the given derived dialect type.
Definition: MLIRContext.h:97
NamedAttrList is array of NamedAttributes that tracks whether it is sorted and does some basic work t...
void append(StringRef name, Attribute attr)
Add an attribute with the specified name.
virtual void buildResources(Operation *op, const SetVector< AsmDialectResourceHandle > &referencedResources, AsmResourceBuilder &builder) const
Hook for building resources to use during printing.
virtual AliasResult getAlias(Attribute attr, raw_ostream &os) const
Hooks for getting an alias identifier alias for a given symbol, that is not necessarily a part of thi...
OpAsmDialectInterface(Dialect *dialect)
virtual AliasResult getAlias(Type type, raw_ostream &os) const
virtual std::string getResourceKey(const AsmDialectResourceHandle &handle) const
Return a key to use for the given resource.
virtual FailureOr< AsmDialectResourceHandle > declareResource(StringRef key) const
Declare a resource with the given key, returning a handle to use for any references of this resource ...
virtual LogicalResult parseResource(AsmParsedResourceEntry &entry) const
Hook for parsing resource entries.
Definition: AsmPrinter.cpp:127
AliasResult
Holds the result of getAlias hook call.
@ FinalAlias
An alias was provided and it should be used (no other hooks will be checked).
@ NoAlias
The object (type or attribute) is not supported by the hook and an alias was not provided.
@ OverridableAlias
An alias was provided, but it might be overriden by other hook.
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
virtual std::pair< StringRef, unsigned > getResultName(unsigned resultNo) const =0
Return the name of the specified result in the specified syntax, as well as the sub-element in the na...
virtual size_t getNumResults() const =0
Return the number of declared SSA results.
virtual OptionalParseResult parseOptionalAssignmentList(SmallVectorImpl< Argument > &lhs, SmallVectorImpl< UnresolvedOperand > &rhs)=0
virtual ParseResult parseRegion(Region &region, ArrayRef< Argument > arguments={}, bool enableNameShadowing=false)=0
Parses a region.
~OpAsmParser() override
virtual ParseResult parseSuccessor(Block *&dest)=0
Parse a single operation successor.
virtual ParseResult parseArgument(Argument &result, bool allowType=false, bool allowAttrs=false)=0
Parse a single argument with the following syntax:
virtual ParseResult parseGenericOperationAfterOpName(OperationState &result, std::optional< ArrayRef< UnresolvedOperand >> parsedOperandType=std::nullopt, std::optional< ArrayRef< Block * >> parsedSuccessors=std::nullopt, std::optional< MutableArrayRef< std::unique_ptr< Region >>> parsedRegions=std::nullopt, std::optional< ArrayRef< NamedAttribute >> parsedAttributes=std::nullopt, std::optional< Attribute > parsedPropertiesAttribute=std::nullopt, std::optional< FunctionType > parsedFnType=std::nullopt)=0
Parse different components, viz., use-info of operand(s), successor(s), region(s),...
ParseResult parseTrailingOperandList(SmallVectorImpl< UnresolvedOperand > &result, Delimiter delimiter=Delimiter::None)
Parse zero or more trailing SSA comma-separated trailing operand references with a specified surround...
ParseResult resolveOperands(Operands &&operands, Type type, SMLoc loc, SmallVectorImpl< Value > &result)
virtual ParseResult parseArgumentList(SmallVectorImpl< Argument > &result, Delimiter delimiter=Delimiter::None, bool allowType=false, bool allowAttrs=false)=0
Parse zero or more arguments with a specified surrounding delimiter.
virtual ParseResult parseAffineMapOfSSAIds(SmallVectorImpl< UnresolvedOperand > &operands, Attribute &map, StringRef attrName, NamedAttrList &attrs, Delimiter delimiter=Delimiter::Square)=0
Parses an affine map attribute where dims and symbols are SSA operands.
virtual OptionalParseResult parseOptionalArgument(Argument &result, bool allowType=false, bool allowAttrs=false)=0
Parse a single argument if present.
virtual ParseResult parseOptionalLocationSpecifier(std::optional< Location > &result)=0
Parse a loc(...) specifier if present, filling in result if so.
ParseResult parseAssignmentList(SmallVectorImpl< Argument > &lhs, SmallVectorImpl< UnresolvedOperand > &rhs)
Parse a list of assignments of the form (x1 = y1, x2 = y2, ...)
virtual ParseResult resolveOperand(const UnresolvedOperand &operand, Type type, SmallVectorImpl< Value > &result)=0
Resolve an operand to an SSA value, emitting an error on failure.
virtual OptionalParseResult parseOptionalOperand(UnresolvedOperand &result, bool allowResultNumber=true)=0
Parse a single operand if present.
virtual ParseResult parseSuccessorAndUseList(Block *&dest, SmallVectorImpl< Value > &operands)=0
Parse a single operation successor and its operand list.
virtual OptionalParseResult parseOptionalRegion(Region &region, ArrayRef< Argument > arguments={}, bool enableNameShadowing=false)=0
Parses a region if present.
virtual FailureOr< OperationName > parseCustomOperationName()=0
Parse the name of an operation, in the custom form.
ParseResult parseOperandList(SmallVectorImpl< UnresolvedOperand > &result, int requiredOperandCount, Delimiter delimiter=Delimiter::None)
Parse a specified number of comma separated operands.
ParseResult resolveOperands(Operands &&operands, Type type, SmallVectorImpl< Value > &result)
Resolve a list of operands to SSA values, emitting an error on failure, or appending the results to t...
virtual Operation * parseGenericOperation(Block *insertBlock, Block::iterator insertPt)=0
Parse an operation in its generic form.
virtual ParseResult parseOperand(UnresolvedOperand &result, bool allowResultNumber=true)=0
Parse a single SSA value operand name along with a result number if allowResultNumber is true.
virtual ParseResult parseAffineExprOfSSAIds(SmallVectorImpl< UnresolvedOperand > &dimOperands, SmallVectorImpl< UnresolvedOperand > &symbOperands, AffineExpr &expr)=0
Parses an affine expression where dims and symbols are SSA operands.
virtual OptionalParseResult parseOptionalSuccessor(Block *&dest)=0
Parse an optional operation successor.
std::enable_if_t<!std::is_convertible< Types, Type >::value, ParseResult > resolveOperands(Operands &&operands, Types &&types, SMLoc loc, SmallVectorImpl< Value > &result)
Resolve a list of operands and a list of operand types to SSA values, emitting an error and returning...
virtual OptionalParseResult parseOptionalRegion(std::unique_ptr< Region > &region, ArrayRef< Argument > arguments={}, bool enableNameShadowing=false)=0
Parses a region if present.
virtual ParseResult parseOperandList(SmallVectorImpl< UnresolvedOperand > &result, Delimiter delimiter=Delimiter::None, bool allowResultNumber=true, int requiredOperandCount=-1)=0
Parse zero or more SSA comma-separated operand references with a specified surrounding delimiter,...
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
void printOperands(IteratorType it, IteratorType end)
Print a comma separated list of operands.
virtual void shadowRegionArgs(Region &region, ValueRange namesToUse)=0
Renumber the arguments for the specified region to the same names as the SSA values in namesToUse.
virtual void printNewline()=0
Print a newline and indent the printer to the start of the current operation.
virtual void increaseIndent()=0
Increase indentation.
virtual void printSuccessorAndUseList(Block *successor, ValueRange succOperands)=0
Print the successor and its operands.
void printOperands(const ContainerType &container)
Print a comma separated list of operands.
virtual void printOptionalAttrDictWithKeyword(ArrayRef< NamedAttribute > attrs, ArrayRef< StringRef > elidedAttrs={})=0
If the specified operation has attributes, print out an attribute dictionary prefixed with 'attribute...
virtual void printOptionalAttrDict(ArrayRef< NamedAttribute > attrs, ArrayRef< StringRef > elidedAttrs={})=0
If the specified operation has attributes, print out an attribute dictionary with their values.
virtual void printOptionalLocationSpecifier(Location loc)=0
Print a loc(...) specifier if printing debug info is enabled.
virtual void printCustomOrGenericOp(Operation *op)=0
Prints the entire operation with the custom assembly form, if available, or the generic assembly form...
virtual void decreaseIndent()=0
Decrease indentation.
virtual void printOperand(Value value, raw_ostream &os)=0
virtual void printSuccessor(Block *successor)=0
Print the given successor.
virtual void printAffineExprOfSSAIds(AffineExpr expr, ValueRange dimOperands, ValueRange symOperands)=0
Prints an affine expression of SSA ids with SSA id names used instead of dims and symbols.
void printFunctionalType(Operation *op)
Print the complete type of an operation in functional form.
Definition: AsmPrinter.cpp:91
virtual void printAffineMapOfSSAIds(AffineMapAttr mapAttr, ValueRange operands)=0
Prints an affine map of SSA ids, where SSA id names are used in place of dims/symbols.
virtual void printGenericOp(Operation *op, bool printOpName=true)=0
Print the entire operation with the default generic assembly form.
~OpAsmPrinter() override
virtual void printRegion(Region &blocks, bool printEntryBlockArgs=true, bool printBlockTerminators=true, bool printEmptyBlock=false)=0
Prints a region.
virtual void printRegionArgument(BlockArgument arg, ArrayRef< NamedAttribute > argAttrs={}, bool omitType=false)=0
Print a block argument in the usual format of: ssaName : type {attr1=42} loc("here") where location p...
virtual void printOperand(Value value)=0
Print implementations for various things an operation contains.
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
This class implements Optional functionality for ParseResult.
Definition: OpDefinition.h:39
ParseResult value() const
Access the internal ParseResult value.
Definition: OpDefinition.h:52
bool has_value() const
Returns true if we contain a valid ParseResult value.
Definition: OpDefinition.h:49
This class represents success/failure for parsing-like operations that find it important to chain tog...
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition: Region.h:26
This class provides an efficient unique identifier for a specific C++ type.
Definition: TypeID.h:104
This class provides an abstraction over the various different ranges of value types.
Definition: TypeRange.h:36
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:74
This class provides an abstraction over the different types of ranges over Values.
Definition: ValueRange.h:372
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:93
The base class used for all derived interface types.
Include the generated interface declarations.
Definition: CallGraph.h:229
This header declares functions that assist transformations in the MemRef dialect.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:62
bool succeeded(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a success value.
Definition: LogicalResult.h:68
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
llvm::hash_code hash_value(const AsmDialectResourceHandle &param)
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
inline ::llvm::hash_code hash_value(AffineExpr arg)
Make AffineExpr hashable.
Definition: AffineExpr.h:240
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
Definition: LogicalResult.h:72
raw_ostream & operator<<(raw_ostream &os, const AliasResult &result)
Definition: AliasAnalysis.h:78
static mlir::AsmDialectResourceHandle getTombstoneKey()
static unsigned getHashValue(const mlir::AsmDialectResourceHandle &handle)
static mlir::AsmDialectResourceHandle getEmptyKey()
static bool isEqual(const mlir::AsmDialectResourceHandle &lhs, const mlir::AsmDialectResourceHandle &rhs)
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26
std::optional< Location > sourceLoc
This is the representation of an operand reference.
This represents an operation in an abstracted form, suitable for use with the builder APIs.
This trait is used to determine if a storage user, like Type, is mutable or not.