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