MLIR 24.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 = nullptr;
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 void printOptionalAttrDict(DictionaryAttr attrs,
506 ArrayRef<StringRef> elidedAttrs = {}) {
507 printOptionalAttrDict(attrs.getValue(), elidedAttrs);
508 }
509
510 /// If the specified operation has attributes, print out an attribute
511 /// dictionary prefixed with 'attributes'.
512 virtual void
514 ArrayRef<StringRef> elidedAttrs = {}) = 0;
515
516 /// Prints the entire operation with the custom assembly form, if available,
517 /// or the generic assembly form, otherwise.
518 virtual void printCustomOrGenericOp(Operation *op) = 0;
519
520 /// Print the entire operation with the default generic assembly form.
521 /// If `printOpName` is true, then the operation name is printed (the default)
522 /// otherwise it is omitted and the print will start with the operand list.
523 virtual void printGenericOp(Operation *op, bool printOpName = true) = 0;
524
525 /// Prints a region.
526 /// If 'printEntryBlockArgs' is false, the arguments of the
527 /// block are not printed. If 'printBlockTerminator' is false, the terminator
528 /// operation of the block is not printed. If printEmptyBlock is true, then
529 /// the block header is printed even if the block is empty.
530 virtual void printRegion(Region &blocks, bool printEntryBlockArgs = true,
531 bool printBlockTerminators = true,
532 bool printEmptyBlock = false) = 0;
533
534 /// Renumber the arguments for the specified region to the same names as the
535 /// SSA values in namesToUse. This may only be used for IsolatedFromAbove
536 /// operations. If any entry in namesToUse is null, the corresponding
537 /// argument name is left alone.
538 virtual void shadowRegionArgs(Region &region, ValueRange namesToUse) = 0;
539
540 /// Prints an affine map of SSA ids, where SSA id names are used in place
541 /// of dims/symbols.
542 /// Operand values must come from single-result sources, and be valid
543 /// dimensions/symbol identifiers according to mlir::isValidDim/Symbol.
544 virtual void printAffineMapOfSSAIds(AffineMapAttr mapAttr,
545 ValueRange operands) = 0;
546
547 /// Prints an affine expression of SSA ids with SSA id names used instead of
548 /// dims and symbols.
549 /// Operand values must come from single-result sources, and be valid
550 /// dimensions/symbol identifiers according to mlir::isValidDim/Symbol.
551 virtual void printAffineExprOfSSAIds(AffineExpr expr, ValueRange dimOperands,
552 ValueRange symOperands) = 0;
553
554 /// Print the complete type of an operation in functional form.
557};
558
559// Make the implementations convenient to use.
561 p.printOperand(value);
562 return p;
563}
564
565template <typename T,
566 std::enable_if_t<std::is_convertible<T &, ValueRange>::value &&
567 !std::is_convertible<T &, Value &>::value,
568 T> * = nullptr>
569inline OpAsmPrinter &operator<<(OpAsmPrinter &p, const T &values) {
570 p.printOperands(values);
571 return p;
572}
573
575 p.printSuccessor(value);
576 return p;
577}
578
579//===----------------------------------------------------------------------===//
580// AsmParser
581//===----------------------------------------------------------------------===//
582
583/// This base class exposes generic asm parser hooks, usable across the various
584/// derived parsers.
586public:
587 AsmParser() = default;
588 virtual ~AsmParser();
589
590 MLIRContext *getContext() const;
591
592 /// Return the location of the original name token.
593 virtual SMLoc getNameLoc() const = 0;
594
595 //===--------------------------------------------------------------------===//
596 // Utilities
597 //===--------------------------------------------------------------------===//
598
599 /// Emit a diagnostic at the specified location and return failure.
600 virtual InFlightDiagnostic emitError(SMLoc loc,
601 const Twine &message = {}) = 0;
602
603 /// Return a builder which provides useful access to MLIRContext, global
604 /// objects like types and attributes.
605 virtual Builder &getBuilder() const = 0;
606
607 /// Get the location of the next token and store it into the argument. This
608 /// always succeeds.
609 virtual SMLoc getCurrentLocation() = 0;
610 ParseResult getCurrentLocation(SMLoc *loc) {
611 *loc = getCurrentLocation();
612 return success();
613 }
614
615 /// Re-encode the given source location as an MLIR location and return it.
616 /// Note: This method should only be used when a `Location` is necessary, as
617 /// the encoding process is not efficient.
618 virtual Location getEncodedSourceLoc(SMLoc loc) = 0;
619
620 //===--------------------------------------------------------------------===//
621 // Token Parsing
622 //===--------------------------------------------------------------------===//
623
624 /// Parse a '->' token.
625 virtual ParseResult parseArrow() = 0;
626
627 /// Parse a '->' token if present
628 virtual ParseResult parseOptionalArrow() = 0;
629
630 /// Parse a `{` token.
631 virtual ParseResult parseLBrace() = 0;
632
633 /// Parse a `{` token if present.
634 virtual ParseResult parseOptionalLBrace() = 0;
635
636 /// Parse a `}` token.
637 virtual ParseResult parseRBrace() = 0;
638
639 /// Parse a `}` token if present.
640 virtual ParseResult parseOptionalRBrace() = 0;
641
642 /// Parse a `:` token.
643 virtual ParseResult parseColon() = 0;
644
645 /// Parse a `:` token if present.
646 virtual ParseResult parseOptionalColon() = 0;
647
648 /// Parse a `,` token.
649 virtual ParseResult parseComma() = 0;
650
651 /// Parse a `,` token if present.
652 virtual ParseResult parseOptionalComma() = 0;
653
654 /// Parse a `=` token.
655 virtual ParseResult parseEqual() = 0;
656
657 /// Parse a `=` token if present.
658 virtual ParseResult parseOptionalEqual() = 0;
659
660 /// Parse a '<' token.
661 virtual ParseResult parseLess() = 0;
662
663 /// Parse a '<' token if present.
664 virtual ParseResult parseOptionalLess() = 0;
665
666 /// Parse a '>' token.
667 virtual ParseResult parseGreater() = 0;
668
669 /// Parse a '>' token if present.
670 virtual ParseResult parseOptionalGreater() = 0;
671
672 /// Parse a '?' token.
673 virtual ParseResult parseQuestion() = 0;
674
675 /// Parse a '?' token if present.
676 virtual ParseResult parseOptionalQuestion() = 0;
677
678 /// Parse a '+' token.
679 virtual ParseResult parsePlus() = 0;
680
681 /// Parse a '+' token if present.
682 virtual ParseResult parseOptionalPlus() = 0;
683
684 /// Parse a '/' token.
685 virtual ParseResult parseSlash() = 0;
686
687 /// Parse a '/' token if present.
688 virtual ParseResult parseOptionalSlash() = 0;
689
690 /// Parse a '-' token.
691 virtual ParseResult parseMinus() = 0;
692
693 /// Parse a '-' token if present.
694 virtual ParseResult parseOptionalMinus() = 0;
695
696 /// Parse a '*' token.
697 virtual ParseResult parseStar() = 0;
698
699 /// Parse a '*' token if present.
700 virtual ParseResult parseOptionalStar() = 0;
701
702 /// Parse a '|' token.
703 virtual ParseResult parseVerticalBar() = 0;
704
705 /// Parse a '|' token if present.
706 virtual ParseResult parseOptionalVerticalBar() = 0;
707
708 /// Parse a quoted string token.
709 ParseResult parseString(std::string *string) {
710 auto loc = getCurrentLocation();
711 if (parseOptionalString(string))
712 return emitError(loc, "expected string");
713 return success();
714 }
715
716 /// Parse a quoted string token if present.
717 virtual ParseResult parseOptionalString(std::string *string) = 0;
718
719 /// Parses a Base64 encoded string of bytes.
720 virtual ParseResult parseBase64Bytes(std::vector<char> *bytes) = 0;
721
722 /// Parse a `(` token.
723 virtual ParseResult parseLParen() = 0;
724
725 /// Parse a `(` token if present.
726 virtual ParseResult parseOptionalLParen() = 0;
727
728 /// Parse a `)` token.
729 virtual ParseResult parseRParen() = 0;
730
731 /// Parse a `)` token if present.
732 virtual ParseResult parseOptionalRParen() = 0;
733
734 /// Parse a `[` token.
735 virtual ParseResult parseLSquare() = 0;
736
737 /// Parse a `[` token if present.
738 virtual ParseResult parseOptionalLSquare() = 0;
739
740 /// Parse a `]` token.
741 virtual ParseResult parseRSquare() = 0;
742
743 /// Parse a `]` token if present.
744 virtual ParseResult parseOptionalRSquare() = 0;
745
746 /// Parse a `...` token.
747 virtual ParseResult parseEllipsis() = 0;
748
749 /// Parse a `...` token if present;
750 virtual ParseResult parseOptionalEllipsis() = 0;
751
752 /// Parse a floating point value from the stream.
753 virtual ParseResult parseFloat(double &result) = 0;
754
755 /// Parse a floating point value into APFloat from the stream.
756 virtual ParseResult parseFloat(const llvm::fltSemantics &semantics,
757 APFloat &result) = 0;
758
759 /// Parse an integer value from the stream.
760 template <typename IntT>
761 ParseResult parseInteger(IntT &result) {
762 auto loc = getCurrentLocation();
764 if (!parseResult.has_value())
765 return emitError(loc, "expected integer value");
766 return *parseResult;
767 }
768
769 /// Parse a decimal integer value from the stream.
770 template <typename IntT>
771 ParseResult parseDecimalInteger(IntT &result) {
772 auto loc = getCurrentLocation();
774 if (!parseResult.has_value())
775 return emitError(loc, "expected decimal integer value");
776 return *parseResult;
777 }
778
779 /// Parse an optional integer value from the stream.
782
783private:
784 template <typename IntT, typename ParseFn>
785 OptionalParseResult parseOptionalIntegerAndCheck(IntT &result,
786 ParseFn &&parseFn) {
787 auto loc = getCurrentLocation();
788 APInt uintResult;
789 OptionalParseResult parseResult = parseFn(uintResult);
790 if (!parseResult.has_value() || failed(*parseResult))
791 return parseResult;
792
793 // Try to convert to the provided integer type. sextOrTrunc is correct even
794 // for unsigned types because parseOptionalInteger ensures the sign bit is
795 // zero for non-negated integers.
796 result =
797 (IntT)uintResult.sextOrTrunc(sizeof(IntT) * CHAR_BIT).getLimitedValue();
798 if (APInt(uintResult.getBitWidth(), result,
799 /*isSigned=*/std::is_signed_v<IntT>,
800 /*implicitTrunc=*/true) != uintResult)
801 return emitError(loc, "integer value too large");
802 return success();
803 }
804
805public:
806 template <typename IntT>
808 return parseOptionalIntegerAndCheck(
809 result, [&](APInt &result) { return parseOptionalInteger(result); });
810 }
811
812 template <typename IntT>
814 return parseOptionalIntegerAndCheck(result, [&](APInt &result) {
816 });
817 }
818
819 /// These are the supported delimiters around operand lists and region
820 /// argument lists, used by parseOperandList.
821 enum class Delimiter {
822 /// Zero or more operands with no delimiters.
824 /// Parens surrounding zero or more operands.
826 /// Square brackets surrounding zero or more operands.
828 /// <> brackets surrounding zero or more operands.
830 /// {} brackets surrounding zero or more operands.
832 /// Parens supporting zero or more operands, or nothing.
834 /// Square brackets supporting zero or more ops, or nothing.
836 /// <> brackets supporting zero or more ops, or nothing.
838 /// {} brackets surrounding zero or more operands, or nothing.
840 };
841
842 /// Parse a list of comma-separated items with an optional delimiter. If a
843 /// delimiter is provided, then an empty list is allowed. If not, then at
844 /// least one element will be parsed.
845 ///
846 /// contextMessage is an optional message appended to "expected '('" sorts of
847 /// diagnostics when parsing the delimeters.
848 virtual ParseResult
850 function_ref<ParseResult()> parseElementFn,
851 StringRef contextMessage = StringRef()) = 0;
852
853 /// Parse a comma separated list of elements that must have at least one entry
854 /// in it.
855 ParseResult
856 parseCommaSeparatedList(function_ref<ParseResult()> parseElementFn) {
857 return parseCommaSeparatedList(Delimiter::None, parseElementFn);
858 }
859
860 //===--------------------------------------------------------------------===//
861 // Keyword Parsing
862 //===--------------------------------------------------------------------===//
863
864 /// This class represents a StringSwitch like class that is useful for parsing
865 /// expected keywords. On construction, unless a non-empty keyword is
866 /// provided, it invokes `parseKeyword` and processes each of the provided
867 /// cases statements until a match is hit. The provided `ResultT` must be
868 /// assignable from `failure()`.
869 template <typename ResultT = ParseResult>
871 public:
872 KeywordSwitch(AsmParser &parser, StringRef *keyword = nullptr)
873 : parser(parser), loc(parser.getCurrentLocation()) {
874 if (keyword && !keyword->empty())
875 this->keyword = *keyword;
876 else if (failed(parser.parseKeywordOrCompletion(&this->keyword)))
877 result = failure();
878 }
879 /// Case that uses the provided value when true.
880 KeywordSwitch &Case(StringLiteral str, ResultT value) {
881 return Case(str, [&](StringRef, SMLoc) { return std::move(value); });
882 }
883 KeywordSwitch &Default(ResultT value) {
884 return Default([&](StringRef, SMLoc) { return std::move(value); });
885 }
886 /// Case that invokes the provided functor when true. The parameters passed
887 /// to the functor are the keyword, and the location of the keyword (in case
888 /// any errors need to be emitted).
889 template <typename FnT, typename = std::enable_if_t<
890 !std::is_convertible<FnT, ResultT>::value>>
891 KeywordSwitch &Case(StringLiteral str, FnT &&fn) {
892 if (result)
893 return *this;
894
895 // If the word was empty, record this as a completion.
896 if (keyword.empty())
897 parser.codeCompleteExpectedTokens(str);
898 else if (keyword == str)
899 result.emplace(std::move(fn(keyword, loc)));
900 return *this;
901 }
902 template <typename FnT, typename = std::enable_if_t<
903 !std::is_convertible<FnT, ResultT>::value>>
905 if (!result)
906 result.emplace(fn(keyword, loc));
907 return *this;
908 }
909
910 /// Returns true if this switch has a value yet.
911 bool hasValue() const { return result.has_value(); }
912
913 /// Return the result of the switch.
914 [[nodiscard]] operator ResultT() {
915 if (!result)
916 return parser.emitError(loc, "unexpected keyword: ") << keyword;
917 return std::move(*result);
918 }
919
920 private:
921 /// The parser used to construct this switch.
922 AsmParser &parser;
923
924 /// The location of the keyword, used to emit errors as necessary.
925 SMLoc loc;
926
927 /// The parsed keyword itself.
928 StringRef keyword;
929
930 /// The result of the switch statement or std::nullopt if currently unknown.
931 std::optional<ResultT> result;
932 };
933
934 /// Parse a given keyword.
935 ParseResult parseKeyword(StringRef keyword) {
936 return parseKeyword(keyword, "");
937 }
938 virtual ParseResult parseKeyword(StringRef keyword, const Twine &msg) = 0;
939
940 /// Parse a keyword into 'keyword'.
941 ParseResult parseKeyword(StringRef *keyword) {
942 auto loc = getCurrentLocation();
943 if (parseOptionalKeyword(keyword))
944 return emitError(loc, "expected valid keyword");
945 return success();
946 }
947
948 /// Parse the given keyword if present.
949 virtual ParseResult parseOptionalKeyword(StringRef keyword) = 0;
950
951 /// Parse a keyword, if present, into 'keyword'.
952 virtual ParseResult parseOptionalKeyword(StringRef *keyword) = 0;
953
954 /// Parse a keyword, if present, and if one of the 'allowedValues',
955 /// into 'keyword'
956 virtual ParseResult
957 parseOptionalKeyword(StringRef *keyword,
958 ArrayRef<StringRef> allowedValues) = 0;
959
960 /// Parse a string into 'string' if it is present and one of the
961 /// 'allowedValues'.
962 virtual ParseResult
963 parseOptionalString(std::string *string,
964 ArrayRef<StringRef> allowedValues) = 0;
965
966 /// Parse a keyword or a quoted string.
967 ParseResult parseKeywordOrString(std::string *result) {
970 << "expected valid keyword or string";
971 return success();
972 }
973
974 /// Parse an optional keyword or string.
975 virtual ParseResult parseOptionalKeywordOrString(std::string *result) = 0;
976
977 /// Parse an optional keyword or string into `result` if it is present and one
978 /// of the 'allowedValues'.
979 virtual ParseResult
981 ArrayRef<StringRef> allowedValues) = 0;
982
983 //===--------------------------------------------------------------------===//
984 // Attribute/Type Parsing
985 //===--------------------------------------------------------------------===//
986
987 /// Invoke the `getChecked` method of the given Attribute or Type class, using
988 /// the provided location to emit errors in the case of failure. Note that
989 /// unlike `OpBuilder::getType`, this method does not implicitly insert a
990 /// context parameter.
991 template <typename T, typename... ParamsT>
992 auto getChecked(SMLoc loc, ParamsT &&...params) {
993 return T::getChecked([&] { return emitError(loc); },
994 std::forward<ParamsT>(params)...);
995 }
996 /// A variant of `getChecked` that uses the result of `getNameLoc` to emit
997 /// errors.
998 template <typename T, typename... ParamsT>
999 auto getChecked(ParamsT &&...params) {
1000 return T::getChecked([&] { return emitError(getNameLoc()); },
1001 std::forward<ParamsT>(params)...);
1002 }
1003
1004 //===--------------------------------------------------------------------===//
1005 // Attribute Parsing
1006 //===--------------------------------------------------------------------===//
1007
1008 /// Parse an arbitrary attribute of a given type and return it in result.
1009 virtual ParseResult parseAttribute(Attribute &result, Type type = {}) = 0;
1010
1011 /// Parse a custom attribute with the provided callback, unless the next
1012 /// token is `#`, in which case the generic parser is invoked.
1014 Attribute &result, Type type,
1015 function_ref<ParseResult(Attribute &result, Type type)>
1016 parseAttribute) = 0;
1017
1018 /// Parse an attribute of a specific kind and type.
1019 template <typename AttrType>
1020 ParseResult parseAttribute(AttrType &result, Type type = {}) {
1021 SMLoc loc = getCurrentLocation();
1022
1023 // Parse any kind of attribute.
1024 Attribute attr;
1025 if (parseAttribute(attr, type))
1026 return failure();
1027
1028 // Check for the right kind of attribute.
1029 if (!(result = llvm::dyn_cast<AttrType>(attr)))
1030 return emitError(loc, "invalid kind of attribute specified");
1031
1032 return success();
1033 }
1034
1035 /// Parse an arbitrary attribute and return it in result. This also adds the
1036 /// attribute to the specified attribute list with the specified name.
1037 ParseResult parseAttribute(Attribute &result, StringRef attrName,
1038 NamedAttrList &attrs) {
1039 return parseAttribute(result, Type(), attrName, attrs);
1040 }
1041
1042 /// Parse an attribute of a specific kind and type.
1043 template <typename AttrType>
1044 ParseResult parseAttribute(AttrType &result, StringRef attrName,
1045 NamedAttrList &attrs) {
1046 return parseAttribute(result, Type(), attrName, attrs);
1047 }
1048
1049 /// Parse an arbitrary attribute of a given type and populate it in `result`.
1050 /// This also adds the attribute to the specified attribute list with the
1051 /// specified name.
1052 template <typename AttrType>
1053 ParseResult parseAttribute(AttrType &result, Type type, StringRef attrName,
1054 NamedAttrList &attrs) {
1055 SMLoc loc = getCurrentLocation();
1056
1057 // Parse any kind of attribute.
1058 Attribute attr;
1059 if (parseAttribute(attr, type))
1060 return failure();
1061
1062 // Check for the right kind of attribute.
1063 result = llvm::dyn_cast<AttrType>(attr);
1064 if (!result)
1065 return emitError(loc, "invalid kind of attribute specified");
1066
1067 attrs.append(attrName, result);
1068 return success();
1069 }
1070
1071 /// Trait to check if `AttrType` provides a `parse` method.
1072 template <typename AttrType>
1073 using has_parse_method = decltype(AttrType::parse(std::declval<AsmParser &>(),
1074 std::declval<Type>()));
1075 template <typename AttrType>
1076 using detect_has_parse_method = llvm::is_detected<has_parse_method, AttrType>;
1077
1078 /// Parse a custom attribute of a given type unless the next token is `#`, in
1079 /// which case the generic parser is invoked. The parsed attribute is
1080 /// populated in `result` and also added to the specified attribute list with
1081 /// the specified name.
1082 template <typename AttrType>
1083 std::enable_if_t<detect_has_parse_method<AttrType>::value, ParseResult>
1085 StringRef attrName, NamedAttrList &attrs) {
1086 SMLoc loc = getCurrentLocation();
1087
1088 // Parse any kind of attribute.
1089 Attribute attr;
1091 attr, type, [&](Attribute &result, Type type) -> ParseResult {
1092 result = AttrType::parse(*this, type);
1093 if (!result)
1094 return failure();
1095 return success();
1096 }))
1097 return failure();
1098
1099 // Check for the right kind of attribute.
1100 result = llvm::dyn_cast<AttrType>(attr);
1101 if (!result)
1102 return emitError(loc, "invalid kind of attribute specified");
1103
1104 attrs.append(attrName, result);
1105 return success();
1106 }
1107
1108 /// SFINAE parsing method for Attribute that don't implement a parse method.
1109 template <typename AttrType>
1110 std::enable_if_t<!detect_has_parse_method<AttrType>::value, ParseResult>
1112 StringRef attrName, NamedAttrList &attrs) {
1113 return parseAttribute(result, type, attrName, attrs);
1114 }
1115
1116 /// Parse a custom attribute of a given type unless the next token is `#`, in
1117 /// which case the generic parser is invoked. The parsed attribute is
1118 /// populated in `result`.
1119 template <typename AttrType>
1120 std::enable_if_t<detect_has_parse_method<AttrType>::value, ParseResult>
1122 SMLoc loc = getCurrentLocation();
1123
1124 // Parse any kind of attribute.
1125 Attribute attr;
1127 attr, type, [&](Attribute &result, Type type) -> ParseResult {
1128 result = AttrType::parse(*this, type);
1129 return success(!!result);
1130 }))
1131 return failure();
1132
1133 // Check for the right kind of attribute.
1134 result = llvm::dyn_cast<AttrType>(attr);
1135 if (!result)
1136 return emitError(loc, "invalid kind of attribute specified");
1137 return success();
1138 }
1139
1140 /// SFINAE parsing method for Attribute that don't implement a parse method.
1141 template <typename AttrType>
1142 std::enable_if_t<!detect_has_parse_method<AttrType>::value, ParseResult>
1144 return parseAttribute(result, type);
1145 }
1146
1147 /// Parse an arbitrary optional attribute of a given type and return it in
1148 /// result.
1150 Type type = {}) = 0;
1151
1152 /// Parse an optional array attribute and return it in result.
1154 Type type = {}) = 0;
1155
1156 /// Parse an optional string attribute and return it in result.
1158 Type type = {}) = 0;
1159
1160 /// Parse an optional symbol ref attribute and return it in result.
1162 Type type = {}) = 0;
1163
1164 /// Parse an optional attribute of a specific typed result. This overload
1165 /// handles concrete attribute types (e.g. FloatAttr) that are not covered by
1166 /// a dedicated virtual overload. It parses any attribute and then validates
1167 /// that the result is of the expected type, emitting an error if not.
1168 template <
1169 typename AttrType,
1170 typename = std::enable_if_t<!llvm::is_one_of<
1171 AttrType, Attribute, ArrayAttr, StringAttr, SymbolRefAttr>::value>>
1173 llvm::SMLoc loc = getCurrentLocation();
1174 Attribute attr;
1175 OptionalParseResult parseResult = parseOptionalAttribute(attr, type);
1176 if (!parseResult.has_value() || failed(*parseResult))
1177 return parseResult;
1178 result = dyn_cast<AttrType>(attr);
1179 if (!result)
1180 return emitError(loc) << "expected attribute of type '" << AttrType::name
1181 << "', but found attribute '" << attr << "'";
1182 return success();
1183 }
1184
1185 /// Parse an optional attribute of a specific type and add it to the list with
1186 /// the specified name.
1187 template <typename AttrType>
1189 StringRef attrName,
1190 NamedAttrList &attrs) {
1191 return parseOptionalAttribute(result, Type(), attrName, attrs);
1192 }
1193
1194 /// Parse an optional attribute of a specific type and add it to the list with
1195 /// the specified name.
1196 template <typename AttrType>
1198 StringRef attrName,
1199 NamedAttrList &attrs) {
1201 if (parseResult.has_value() && succeeded(*parseResult))
1202 attrs.append(attrName, result);
1203 return parseResult;
1204 }
1205
1206 /// Parse a named dictionary into 'result' if it is present.
1207 virtual ParseResult parseOptionalAttrDict(NamedAttrList &result) = 0;
1208
1209 /// Parse a named dictionary into 'result' if the `attributes` keyword is
1210 /// present.
1211 virtual ParseResult
1213
1214 /// Parse an affine map instance into 'map'.
1215 virtual ParseResult parseAffineMap(AffineMap &map) = 0;
1216
1217 /// Parse an affine expr instance into 'expr' using the already computed
1218 /// mapping from symbols to affine expressions in 'symbolSet'.
1219 virtual ParseResult
1220 parseAffineExpr(ArrayRef<std::pair<StringRef, AffineExpr>> symbolSet,
1221 AffineExpr &expr) = 0;
1222
1223 /// Parse an integer set instance into 'set'.
1224 virtual ParseResult parseIntegerSet(IntegerSet &set) = 0;
1225
1226 //===--------------------------------------------------------------------===//
1227 // Identifier Parsing
1228 //===--------------------------------------------------------------------===//
1229
1230 /// Parse an @-identifier and store it (without the '@' symbol) in a string
1231 /// attribute.
1232 ParseResult parseSymbolName(StringAttr &result) {
1233 if (failed(parseOptionalSymbolName(result)))
1235 << "expected valid '@'-identifier for symbol name";
1236 return success();
1237 }
1238
1239 /// Parse an @-identifier and store it (without the '@' symbol) in a string
1240 /// attribute named 'attrName'.
1241 ParseResult parseSymbolName(StringAttr &result, StringRef attrName,
1242 NamedAttrList &attrs) {
1244 return failure();
1245 attrs.append(attrName, result);
1246 return success();
1247 }
1248
1249 /// Parse an optional @-identifier and store it (without the '@' symbol) in a
1250 /// string attribute.
1251 virtual ParseResult parseOptionalSymbolName(StringAttr &result) = 0;
1252
1253 /// Parse an optional @-identifier and store it (without the '@' symbol) in a
1254 /// string attribute named 'attrName'.
1255 ParseResult parseOptionalSymbolName(StringAttr &result, StringRef attrName,
1256 NamedAttrList &attrs) {
1257 if (succeeded(parseOptionalSymbolName(result))) {
1258 attrs.append(attrName, result);
1259 return success();
1260 }
1261 return failure();
1262 }
1263
1264 //===--------------------------------------------------------------------===//
1265 // Resource Parsing
1266 //===--------------------------------------------------------------------===//
1267
1268 /// Parse a handle to a resource within the assembly format.
1269 template <typename ResourceT>
1270 FailureOr<ResourceT> parseResourceHandle() {
1271 SMLoc handleLoc = getCurrentLocation();
1272
1273 // Try to load the dialect that owns the handle.
1274 auto *dialect =
1275 getContext()->getOrLoadDialect<typename ResourceT::Dialect>();
1276 if (!dialect) {
1277 return emitError(handleLoc)
1278 << "dialect '" << ResourceT::Dialect::getDialectNamespace()
1279 << "' is unknown";
1280 }
1281
1282 FailureOr<AsmDialectResourceHandle> handle = parseResourceHandle(dialect);
1283 if (failed(handle))
1284 return failure();
1285 if (auto *result = dyn_cast<ResourceT>(&*handle))
1286 return std::move(*result);
1287 return emitError(handleLoc) << "provided resource handle differs from the "
1288 "expected resource type";
1289 }
1290
1291 //===--------------------------------------------------------------------===//
1292 // Type Parsing
1293 //===--------------------------------------------------------------------===//
1294
1295 /// Parse a type.
1296 virtual ParseResult parseType(Type &result) = 0;
1297
1298 /// Parse a custom type with the provided callback, unless the next
1299 /// token is `#`, in which case the generic parser is invoked.
1300 virtual ParseResult parseCustomTypeWithFallback(
1301 Type &result, function_ref<ParseResult(Type &result)> parseType) = 0;
1302
1303 /// Parse an optional type.
1305
1306 /// Parse a type of a specific type.
1307 template <typename TypeT>
1308 ParseResult parseType(TypeT &result) {
1309 SMLoc loc = getCurrentLocation();
1310
1311 // Parse any kind of type.
1312 Type type;
1313 if (parseType(type))
1314 return failure();
1315
1316 // Check for the right kind of type.
1317 result = llvm::dyn_cast<TypeT>(type);
1318 if (!result) {
1320 emitError(loc, "invalid kind of type specified");
1321 if constexpr (HasStaticName<TypeT>::value)
1322 diag << ": expected " << TypeT::name << ", but found " << type;
1323 return diag;
1324 }
1325
1326 return success();
1327 }
1328
1329 /// Trait to check if `TypeT` provides a `parse` method.
1330 template <typename TypeT>
1332 decltype(TypeT::parse(std::declval<AsmParser &>()));
1333 template <typename TypeT>
1335 llvm::is_detected<type_has_parse_method, TypeT>;
1336
1337 /// Parse a custom Type of a given type unless the next token is `#`, in
1338 /// which case the generic parser is invoked. The parsed Type is
1339 /// populated in `result`.
1340 template <typename TypeT>
1341 std::enable_if_t<detect_type_has_parse_method<TypeT>::value, ParseResult>
1343 SMLoc loc = getCurrentLocation();
1344
1345 // Parse any kind of Type.
1346 Type type;
1347 if (parseCustomTypeWithFallback(type, [&](Type &result) -> ParseResult {
1348 result = TypeT::parse(*this);
1349 return success(!!result);
1350 }))
1351 return failure();
1352
1353 // Check for the right kind of Type.
1354 result = llvm::dyn_cast<TypeT>(type);
1355 if (!result) {
1357 emitError(loc, "invalid kind of type specified");
1358 if constexpr (HasStaticName<TypeT>::value)
1359 diag << ": expected " << TypeT::name << ", but found " << type;
1360 return diag;
1361 }
1362 return success();
1363 }
1364
1365 /// SFINAE parsing method for Type that don't implement a parse method.
1366 template <typename TypeT>
1367 std::enable_if_t<!detect_type_has_parse_method<TypeT>::value, ParseResult>
1369 return parseType(result);
1370 }
1371
1372 /// Parse a type list.
1374
1375 /// Parse an arrow followed by a type list.
1377
1378 /// Parse an optional arrow followed by a type list.
1379 virtual ParseResult
1381
1382 /// Parse a colon followed by a type.
1383 virtual ParseResult parseColonType(Type &result) = 0;
1384
1385 /// Parse a colon followed by a type of a specific kind, e.g. a FunctionType.
1386 template <typename TypeType>
1387 ParseResult parseColonType(TypeType &result) {
1388 SMLoc loc = getCurrentLocation();
1389
1390 // Parse any kind of type.
1391 Type type;
1392 if (parseColonType(type))
1393 return failure();
1394
1395 // Check for the right kind of type.
1396 result = llvm::dyn_cast<TypeType>(type);
1397 if (!result) {
1399 emitError(loc, "invalid kind of type specified");
1400 if constexpr (HasStaticName<TypeType>::value)
1401 diag << ": expected " << TypeType::name << ", but found " << type;
1402 return diag;
1403 }
1404
1405 return success();
1406 }
1407
1408 /// Parse a colon followed by a type list, which must have at least one type.
1410
1411 /// Parse an optional colon followed by a type list, which if present must
1412 /// have at least one type.
1413 virtual ParseResult
1415
1416 /// Parse a keyword followed by a type.
1417 ParseResult parseKeywordType(const char *keyword, Type &result) {
1418 return failure(parseKeyword(keyword) || parseType(result));
1419 }
1420
1421 /// Add the specified type to the end of the specified type list and return
1422 /// success. This is a helper designed to allow parse methods to be simple
1423 /// and chain through || operators.
1425 result.push_back(type);
1426 return success();
1427 }
1428
1429 /// Add the specified types to the end of the specified type list and return
1430 /// success. This is a helper designed to allow parse methods to be simple
1431 /// and chain through || operators.
1434 result.append(types.begin(), types.end());
1435 return success();
1436 }
1437
1438 /// Parse a dimension list of a tensor or memref type. This populates the
1439 /// dimension list, using ShapedType::kDynamic for the `?` dimensions if
1440 /// `allowDynamic` is set and errors out on `?` otherwise. Parsing the
1441 /// trailing `x` is configurable.
1442 ///
1443 /// dimension-list ::= eps | dimension (`x` dimension)*
1444 /// dimension-list-with-trailing-x ::= (dimension `x`)*
1445 /// dimension ::= `?` | decimal-literal
1446 ///
1447 /// When `allowDynamic` is not set, this is used to parse:
1448 ///
1449 /// static-dimension-list ::= eps | decimal-literal (`x` decimal-literal)*
1450 /// static-dimension-list-with-trailing-x ::= (dimension `x`)*
1451 virtual ParseResult parseDimensionList(SmallVectorImpl<int64_t> &dimensions,
1452 bool allowDynamic = true,
1453 bool withTrailingX = true) = 0;
1454
1455 /// Parse an 'x' token in a dimension list, handling the case where the x is
1456 /// juxtaposed with an element type, as in "xf32", leaving the "f32" as the
1457 /// next token.
1458 virtual ParseResult parseXInDimensionList() = 0;
1459
1460 /// Class used to automatically end a cyclic region on destruction.
1462 public:
1463 explicit CyclicParseReset(AsmParser *parser) : parser(parser) {}
1464
1466 if (parser)
1467 parser->popCyclicParsing();
1468 }
1469
1473 : parser(std::exchange(rhs.parser, nullptr)) {}
1475 parser = std::exchange(rhs.parser, nullptr);
1476 return *this;
1477 }
1478
1479 private:
1480 AsmParser *parser;
1481 };
1482
1483 /// Attempts to start a cyclic parsing region for `attrOrType`.
1484 /// A cyclic parsing region starts with this call and ends with the
1485 /// destruction of the returned `CyclicParseReset`. During this time,
1486 /// calling `tryStartCyclicParse` with the same attribute in any parser
1487 /// will lead to returning failure.
1488 ///
1489 /// This makes it possible to parse cyclic attributes or types by parsing a
1490 /// short from if nested within itself.
1491 template <class AttrOrTypeT>
1492 FailureOr<CyclicParseReset> tryStartCyclicParse(AttrOrTypeT attrOrType) {
1493 static_assert(
1494 std::is_base_of_v<AttributeTrait::IsMutable<AttrOrTypeT>,
1495 AttrOrTypeT> ||
1496 std::is_base_of_v<TypeTrait::IsMutable<AttrOrTypeT>, AttrOrTypeT>,
1497 "Only mutable attributes or types can be cyclic");
1498 if (failed(pushCyclicParsing(attrOrType.getAsOpaquePointer())))
1499 return failure();
1500
1501 return CyclicParseReset(this);
1502 }
1503
1504protected:
1505 /// Parse a handle to a resource within the assembly format for the given
1506 /// dialect.
1507 virtual FailureOr<AsmDialectResourceHandle>
1509
1510 /// Pushes a new attribute or type in the form of a type erased pointer
1511 /// into an internal set.
1512 /// Returns success if the type or attribute was inserted in the set or
1513 /// failure if it was already contained.
1514 virtual LogicalResult pushCyclicParsing(const void *opaquePointer) = 0;
1515
1516 /// Removes the element that was last inserted with a successful call to
1517 /// `pushCyclicParsing`. There must be exactly one `popCyclicParsing` call
1518 /// in reverse order of all successful `pushCyclicParsing`.
1519 virtual void popCyclicParsing() = 0;
1520
1521 //===--------------------------------------------------------------------===//
1522 // Code Completion
1523 //===--------------------------------------------------------------------===//
1524
1525 /// Parse a keyword, or an empty string if the current location signals a code
1526 /// completion.
1527 virtual ParseResult parseKeywordOrCompletion(StringRef *keyword) = 0;
1528
1529 /// Signal the code completion of a set of expected tokens.
1531
1532private:
1533 AsmParser(const AsmParser &) = delete;
1534 void operator=(const AsmParser &) = delete;
1535};
1536
1537//===----------------------------------------------------------------------===//
1538// OpAsmParser
1539//===----------------------------------------------------------------------===//
1540
1541/// The OpAsmParser has methods for interacting with the asm parser: parsing
1542/// things from it, emitting errors etc. It has an intentionally high-level API
1543/// that is designed to reduce/constrain syntax innovation in individual
1544/// operations.
1545///
1546/// For example, consider an op like this:
1547///
1548/// %x = load %p[%1, %2] : memref<...>
1549///
1550/// The "%x = load" tokens are already parsed and therefore invisible to the
1551/// custom op parser. This can be supported by calling `parseOperandList` to
1552/// parse the %p, then calling `parseOperandList` with a `SquareDelimiter` to
1553/// parse the indices, then calling `parseColonTypeList` to parse the result
1554/// type.
1555///
1556class OpAsmParser : public AsmParser {
1557public:
1559 ~OpAsmParser() override;
1560
1561 /// Parse a loc(...) specifier if present, filling in result if so.
1562 /// Location for BlockArgument and Operation may be deferred with an alias, in
1563 /// which case an OpaqueLoc is set and will be resolved when parsing
1564 /// completes.
1565 virtual ParseResult
1566 parseOptionalLocationSpecifier(std::optional<Location> &result) = 0;
1567
1568 /// Return the name of the specified result in the specified syntax, as well
1569 /// as the sub-element in the name. It returns an empty string and ~0U for
1570 /// invalid result numbers. For example, in this operation:
1571 ///
1572 /// %x, %y:2, %z = foo.op
1573 ///
1574 /// getResultName(0) == {"x", 0 }
1575 /// getResultName(1) == {"y", 0 }
1576 /// getResultName(2) == {"y", 1 }
1577 /// getResultName(3) == {"z", 0 }
1578 /// getResultName(4) == {"", ~0U }
1579 virtual std::pair<StringRef, unsigned>
1580 getResultName(unsigned resultNo) const = 0;
1581
1582 /// Return the number of declared SSA results. This returns 4 for the foo.op
1583 /// example in the comment for `getResultName`.
1584 virtual size_t getNumResults() const = 0;
1585
1586 // These methods emit an error and return failure or success. This allows
1587 // these to be chained together into a linear sequence of || expressions in
1588 // many cases.
1589
1590 /// Parse an operation in its generic form.
1591 /// The parsed operation is parsed in the current context and inserted in the
1592 /// provided block and insertion point. The results produced by this operation
1593 /// aren't mapped to any named value in the parser. Returns nullptr on
1594 /// failure.
1596 Block::iterator insertPt) = 0;
1597
1598 /// Parse the name of an operation, in the custom form. On success, return a
1599 /// an object of type 'OperationName'. Otherwise, failure is returned.
1600 virtual FailureOr<OperationName> parseCustomOperationName() = 0;
1601
1602 //===--------------------------------------------------------------------===//
1603 // Operand Parsing
1604 //===--------------------------------------------------------------------===//
1605
1606 /// This is the representation of an operand reference.
1608 SMLoc location; // Location of the token.
1609 StringRef name; // Value name, e.g. %42 or %abc
1610 unsigned number; // Number, e.g. 12 for an operand like %xyz#12
1611 };
1612
1613 /// Parse different components, viz., use-info of operand(s), successor(s),
1614 /// region(s), attribute(s) and function-type, of the generic form of an
1615 /// operation instance and populate the input operation-state 'result' with
1616 /// those components. If any of the components is explicitly provided, then
1617 /// skip parsing that component.
1620 std::optional<ArrayRef<UnresolvedOperand>> parsedOperandType =
1621 std::nullopt,
1622 std::optional<ArrayRef<Block *>> parsedSuccessors = std::nullopt,
1623 std::optional<MutableArrayRef<std::unique_ptr<Region>>> parsedRegions =
1624 std::nullopt,
1625 std::optional<ArrayRef<NamedAttribute>> parsedAttributes = std::nullopt,
1626 std::optional<Attribute> parsedPropertiesAttribute = std::nullopt,
1627 std::optional<FunctionType> parsedFnType = std::nullopt) = 0;
1628
1629 /// Parse a single SSA value operand name along with a result number if
1630 /// `allowResultNumber` is true.
1632 bool allowResultNumber = true) = 0;
1633
1634 /// Parse a single operand if present.
1635 virtual OptionalParseResult
1637 bool allowResultNumber = true) = 0;
1638
1639 /// Parse zero or more SSA comma-separated operand references with a specified
1640 /// surrounding delimiter, and an optional required operand count.
1641 virtual ParseResult
1643 Delimiter delimiter = Delimiter::None,
1644 bool allowResultNumber = true,
1645 int requiredOperandCount = -1) = 0;
1646
1647 /// Parse a specified number of comma separated operands.
1649 int requiredOperandCount,
1650 Delimiter delimiter = Delimiter::None) {
1651 return parseOperandList(result, delimiter,
1652 /*allowResultNumber=*/true, requiredOperandCount);
1653 }
1654
1655 /// Parse zero or more trailing SSA comma-separated trailing operand
1656 /// references with a specified surrounding delimiter, and an optional
1657 /// required operand count. A leading comma is expected before the
1658 /// operands.
1659 ParseResult
1661 Delimiter delimiter = Delimiter::None) {
1662 if (failed(parseOptionalComma()))
1663 return success(); // The comma is optional.
1664 return parseOperandList(result, delimiter);
1665 }
1666
1667 /// Resolve an operand to an SSA value, emitting an error on failure.
1668 virtual ParseResult resolveOperand(const UnresolvedOperand &operand,
1669 Type type,
1671
1672 /// Resolve a list of operands to SSA values, emitting an error on failure, or
1673 /// appending the results to the list on success. This method should be used
1674 /// when all operands have the same type.
1675 template <typename Operands = ArrayRef<UnresolvedOperand>>
1676 ParseResult resolveOperands(Operands &&operands, Type type,
1678 for (const UnresolvedOperand &operand : operands)
1679 if (resolveOperand(operand, type, result))
1680 return failure();
1681 return success();
1682 }
1683 template <typename Operands = ArrayRef<UnresolvedOperand>>
1684 ParseResult resolveOperands(Operands &&operands, Type type, SMLoc loc,
1686 return resolveOperands(std::forward<Operands>(operands), type, result);
1687 }
1688
1689 /// Resolve a list of operands and a list of operand types to SSA values,
1690 /// emitting an error and returning failure, or appending the results
1691 /// to the list on success.
1692 template <
1693 typename Operands = ArrayRef<UnresolvedOperand>,
1694 typename Types = ArrayRef<Type>,
1695 typename = std::enable_if_t<!std::is_convertible<Types, Type>::value>>
1696 ParseResult resolveOperands(Operands &&operands, Types &&types, SMLoc loc,
1698 size_t operandSize = llvm::range_size(operands);
1699 size_t typeSize = llvm::range_size(types);
1700 if (operandSize != typeSize) {
1701 // If no location was provided, report errors at the beginning of the op.
1702 return emitError(loc.isValid() ? loc : getNameLoc())
1703 << "number of operands and types do not match: got " << operandSize
1704 << " operands and " << typeSize << " types";
1705 }
1706
1707 for (auto [operand, type] : llvm::zip_equal(operands, types))
1708 if (resolveOperand(operand, type, result))
1709 return failure();
1710 return success();
1711 }
1712
1713 /// Parses an affine map attribute where dims and symbols are SSA operands.
1714 /// Operand values must come from single-result sources, and be valid
1715 /// dimensions/symbol identifiers according to mlir::isValidDim/Symbol.
1716 virtual ParseResult
1718 Attribute &map, StringRef attrName,
1719 NamedAttrList &attrs,
1720 Delimiter delimiter = Delimiter::Square) = 0;
1721
1722 /// Parses an affine expression where dims and symbols are SSA operands.
1723 /// Operand values must come from single-result sources, and be valid
1724 /// dimensions/symbol identifiers according to mlir::isValidDim/Symbol.
1725 virtual ParseResult
1728 AffineExpr &expr) = 0;
1729
1730 //===--------------------------------------------------------------------===//
1731 // Argument Parsing
1732 //===--------------------------------------------------------------------===//
1733
1734 struct Argument {
1735 UnresolvedOperand ssaName; // SourceLoc, SSA name, result #.
1736 Type type; // Type.
1737 DictionaryAttr attrs; // Attributes if present.
1738 std::optional<Location> sourceLoc; // Source location specifier if present.
1739 };
1740
1741 /// Parse a single argument with the following syntax:
1742 ///
1743 /// `%ssaName : !type { optionalAttrDict} loc(optionalSourceLoc)`
1744 ///
1745 /// If `allowType` is false or `allowAttrs` are false then the respective
1746 /// parts of the grammar are not parsed.
1747 virtual ParseResult parseArgument(Argument &result, bool allowType = false,
1748 bool allowAttrs = false) = 0;
1749
1750 /// Parse a single argument if present.
1751 virtual OptionalParseResult
1752 parseOptionalArgument(Argument &result, bool allowType = false,
1753 bool allowAttrs = false) = 0;
1754
1755 /// Parse zero or more arguments with a specified surrounding delimiter.
1757 Delimiter delimiter = Delimiter::None,
1758 bool allowType = false,
1759 bool allowAttrs = false) = 0;
1760
1761 //===--------------------------------------------------------------------===//
1762 // Region Parsing
1763 //===--------------------------------------------------------------------===//
1764
1765 /// Parses a region. Any parsed blocks are appended to 'region' and must be
1766 /// moved to the op regions after the op is created. The first block of the
1767 /// region takes 'arguments'.
1768 ///
1769 /// If 'enableNameShadowing' is set to true, the argument names are allowed to
1770 /// shadow the names of other existing SSA values defined above the region
1771 /// scope. 'enableNameShadowing' can only be set to true for regions attached
1772 /// to operations that are 'IsolatedFromAbove'.
1773 virtual ParseResult parseRegion(Region &region,
1774 ArrayRef<Argument> arguments = {},
1775 bool enableNameShadowing = false) = 0;
1776
1777 /// Parses a region if present.
1778 virtual OptionalParseResult
1780 bool enableNameShadowing = false) = 0;
1781
1782 /// Parses a region if present. If the region is present, a new region is
1783 /// allocated and placed in `region`. If no region is present or on failure,
1784 /// `region` remains untouched.
1785 virtual OptionalParseResult
1786 parseOptionalRegion(std::unique_ptr<Region> &region,
1787 ArrayRef<Argument> arguments = {},
1788 bool enableNameShadowing = false) = 0;
1789
1790 //===--------------------------------------------------------------------===//
1791 // Successor Parsing
1792 //===--------------------------------------------------------------------===//
1793
1794 /// Parse a single operation successor.
1795 virtual ParseResult parseSuccessor(Block *&dest) = 0;
1796
1797 /// Parse an optional operation successor.
1799
1800 /// Parse a single operation successor and its operand list.
1801 virtual ParseResult
1803
1804 //===--------------------------------------------------------------------===//
1805 // Type Parsing
1806 //===--------------------------------------------------------------------===//
1807
1808 /// Parse a list of assignments of the form
1809 /// (%x1 = %y1, %x2 = %y2, ...)
1813 if (!result.has_value())
1814 return emitError(getCurrentLocation(), "expected '('");
1815 return result.value();
1816 }
1817
1818 virtual OptionalParseResult
1821};
1822
1823//===--------------------------------------------------------------------===//
1824// Custom printers and parsers.
1825//===--------------------------------------------------------------------===//
1826
1827// Handles custom<DimensionList>(...) in TableGen.
1828void printDimensionList(OpAsmPrinter &printer, Operation *op,
1829 ArrayRef<int64_t> dimensions);
1830ParseResult parseDimensionList(OpAsmParser &parser,
1831 DenseI64ArrayAttr &dimensions);
1832
1833} // namespace mlir
1834
1835//===--------------------------------------------------------------------===//
1836// Operation OpAsm interface.
1837//===--------------------------------------------------------------------===//
1838
1839/// The OpAsmOpInterface, see OpAsmInterface.td for more details.
1840#include "mlir/IR/OpAsmOpInterface.h.inc"
1841
1842//===--------------------------------------------------------------------===//
1843// Dialect OpAsm interface.
1844//===--------------------------------------------------------------------===//
1845
1846/// The OpAsmDialectInterface, see OpAsmDialectInterface.td
1847#include "mlir/IR/OpAsmDialectInterface.h.inc"
1848
1849namespace llvm {
1850template <>
1851struct DenseMapInfo<mlir::AsmDialectResourceHandle> {
1852 static unsigned getHashValue(const mlir::AsmDialectResourceHandle &handle) {
1853 return DenseMapInfo<void *>::getHashValue(handle.getResource());
1854 }
1856 const mlir::AsmDialectResourceHandle &rhs) {
1857 return lhs.getResource() == rhs.getResource();
1858 }
1859};
1860} // namespace llvm
1861
1862#endif
return success()
if(failed(verifyVectorMemoryOp(getOperation(), memrefType, getVectorType()))) return failure()
ArrayAttr()
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:164
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...
void printOptionalAttrDict(DictionaryAttr attrs, ArrayRef< StringRef > elidedAttrs={})
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:87
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:227
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 unsigned getHashValue(const mlir::AsmDialectResourceHandle &handle)
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.