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