1 //===- OpFormatGen.cpp - MLIR operation asm format generator --------------===//
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 #include "OpFormatGen.h"
10 #include "mlir/Support/LogicalResult.h"
11 #include "mlir/TableGen/Format.h"
12 #include "mlir/TableGen/GenInfo.h"
13 #include "mlir/TableGen/Interfaces.h"
14 #include "mlir/TableGen/OpClass.h"
15 #include "mlir/TableGen/OpTrait.h"
16 #include "mlir/TableGen/Operator.h"
17 #include "llvm/ADT/MapVector.h"
18 #include "llvm/ADT/Sequence.h"
19 #include "llvm/ADT/SetVector.h"
20 #include "llvm/ADT/SmallBitVector.h"
21 #include "llvm/ADT/StringExtras.h"
22 #include "llvm/ADT/TypeSwitch.h"
23 #include "llvm/Support/CommandLine.h"
24 #include "llvm/Support/Signals.h"
25 #include "llvm/TableGen/Error.h"
26 #include "llvm/TableGen/Record.h"
27 
28 #define DEBUG_TYPE "mlir-tblgen-opformatgen"
29 
30 using namespace mlir;
31 using namespace mlir::tblgen;
32 
33 static llvm::cl::opt<bool> formatErrorIsFatal(
34     "asmformat-error-is-fatal",
35     llvm::cl::desc("Emit a fatal error if format parsing fails"),
36     llvm::cl::init(true));
37 
38 /// Returns true if the given string can be formatted as a keyword.
39 static bool canFormatStringAsKeyword(StringRef value) {
40   if (!isalpha(value.front()) && value.front() != '_')
41     return false;
42   return llvm::all_of(value.drop_front(), [](char c) {
43     return isalnum(c) || c == '_' || c == '$' || c == '.';
44   });
45 }
46 
47 //===----------------------------------------------------------------------===//
48 // Element
49 //===----------------------------------------------------------------------===//
50 
51 namespace {
52 /// This class represents a single format element.
53 class Element {
54 public:
55   enum class Kind {
56     /// This element is a directive.
57     AttrDictDirective,
58     CustomDirective,
59     FunctionalTypeDirective,
60     OperandsDirective,
61     RefDirective,
62     RegionsDirective,
63     ResultsDirective,
64     SuccessorsDirective,
65     TypeDirective,
66 
67     /// This element is a literal.
68     Literal,
69 
70     /// This element is a whitespace.
71     Newline,
72     Space,
73 
74     /// This element is an variable value.
75     AttributeVariable,
76     OperandVariable,
77     RegionVariable,
78     ResultVariable,
79     SuccessorVariable,
80 
81     /// This element is an optional element.
82     Optional,
83   };
84   Element(Kind kind) : kind(kind) {}
85   virtual ~Element() = default;
86 
87   /// Return the kind of this element.
88   Kind getKind() const { return kind; }
89 
90 private:
91   /// The kind of this element.
92   Kind kind;
93 };
94 } // namespace
95 
96 //===----------------------------------------------------------------------===//
97 // VariableElement
98 
99 namespace {
100 /// This class represents an instance of an variable element. A variable refers
101 /// to something registered on the operation itself, e.g. an argument, result,
102 /// etc.
103 template <typename VarT, Element::Kind kindVal>
104 class VariableElement : public Element {
105 public:
106   VariableElement(const VarT *var) : Element(kindVal), var(var) {}
107   static bool classof(const Element *element) {
108     return element->getKind() == kindVal;
109   }
110   const VarT *getVar() { return var; }
111 
112 protected:
113   const VarT *var;
114 };
115 
116 /// This class represents a variable that refers to an attribute argument.
117 struct AttributeVariable
118     : public VariableElement<NamedAttribute, Element::Kind::AttributeVariable> {
119   using VariableElement<NamedAttribute,
120                         Element::Kind::AttributeVariable>::VariableElement;
121 
122   /// Return the constant builder call for the type of this attribute, or None
123   /// if it doesn't have one.
124   Optional<StringRef> getTypeBuilder() const {
125     Optional<Type> attrType = var->attr.getValueType();
126     return attrType ? attrType->getBuilderCall() : llvm::None;
127   }
128 
129   /// Return if this attribute refers to a UnitAttr.
130   bool isUnitAttr() const {
131     return var->attr.getBaseAttr().getAttrDefName() == "UnitAttr";
132   }
133 };
134 
135 /// This class represents a variable that refers to an operand argument.
136 using OperandVariable =
137     VariableElement<NamedTypeConstraint, Element::Kind::OperandVariable>;
138 
139 /// This class represents a variable that refers to a region.
140 using RegionVariable =
141     VariableElement<NamedRegion, Element::Kind::RegionVariable>;
142 
143 /// This class represents a variable that refers to a result.
144 using ResultVariable =
145     VariableElement<NamedTypeConstraint, Element::Kind::ResultVariable>;
146 
147 /// This class represents a variable that refers to a successor.
148 using SuccessorVariable =
149     VariableElement<NamedSuccessor, Element::Kind::SuccessorVariable>;
150 } // end anonymous namespace
151 
152 //===----------------------------------------------------------------------===//
153 // DirectiveElement
154 
155 namespace {
156 /// This class implements single kind directives.
157 template <Element::Kind type>
158 class DirectiveElement : public Element {
159 public:
160   DirectiveElement() : Element(type){};
161   static bool classof(const Element *ele) { return ele->getKind() == type; }
162 };
163 /// This class represents the `operands` directive. This directive represents
164 /// all of the operands of an operation.
165 using OperandsDirective = DirectiveElement<Element::Kind::OperandsDirective>;
166 
167 /// This class represents the `regions` directive. This directive represents
168 /// all of the regions of an operation.
169 using RegionsDirective = DirectiveElement<Element::Kind::RegionsDirective>;
170 
171 /// This class represents the `results` directive. This directive represents
172 /// all of the results of an operation.
173 using ResultsDirective = DirectiveElement<Element::Kind::ResultsDirective>;
174 
175 /// This class represents the `successors` directive. This directive represents
176 /// all of the successors of an operation.
177 using SuccessorsDirective =
178     DirectiveElement<Element::Kind::SuccessorsDirective>;
179 
180 /// This class represents the `attr-dict` directive. This directive represents
181 /// the attribute dictionary of the operation.
182 class AttrDictDirective
183     : public DirectiveElement<Element::Kind::AttrDictDirective> {
184 public:
185   explicit AttrDictDirective(bool withKeyword) : withKeyword(withKeyword) {}
186   bool isWithKeyword() const { return withKeyword; }
187 
188 private:
189   /// If the dictionary should be printed with the 'attributes' keyword.
190   bool withKeyword;
191 };
192 
193 /// This class represents a custom format directive that is implemented by the
194 /// user in C++.
195 class CustomDirective : public Element {
196 public:
197   CustomDirective(StringRef name,
198                   std::vector<std::unique_ptr<Element>> &&arguments)
199       : Element{Kind::CustomDirective}, name(name),
200         arguments(std::move(arguments)) {}
201 
202   static bool classof(const Element *element) {
203     return element->getKind() == Kind::CustomDirective;
204   }
205 
206   /// Return the name of this optional element.
207   StringRef getName() const { return name; }
208 
209   /// Return the arguments to the custom directive.
210   auto getArguments() const { return llvm::make_pointee_range(arguments); }
211 
212 private:
213   /// The user provided name of the directive.
214   StringRef name;
215 
216   /// The arguments to the custom directive.
217   std::vector<std::unique_ptr<Element>> arguments;
218 };
219 
220 /// This class represents the `functional-type` directive. This directive takes
221 /// two arguments and formats them, respectively, as the inputs and results of a
222 /// FunctionType.
223 class FunctionalTypeDirective
224     : public DirectiveElement<Element::Kind::FunctionalTypeDirective> {
225 public:
226   FunctionalTypeDirective(std::unique_ptr<Element> inputs,
227                           std::unique_ptr<Element> results)
228       : inputs(std::move(inputs)), results(std::move(results)) {}
229   Element *getInputs() const { return inputs.get(); }
230   Element *getResults() const { return results.get(); }
231 
232 private:
233   /// The input and result arguments.
234   std::unique_ptr<Element> inputs, results;
235 };
236 
237 /// This class represents the `ref` directive.
238 class RefDirective : public DirectiveElement<Element::Kind::RefDirective> {
239 public:
240   RefDirective(std::unique_ptr<Element> arg) : operand(std::move(arg)) {}
241   Element *getOperand() const { return operand.get(); }
242 
243 private:
244   /// The operand that is used to format the directive.
245   std::unique_ptr<Element> operand;
246 };
247 
248 /// This class represents the `type` directive.
249 class TypeDirective : public DirectiveElement<Element::Kind::TypeDirective> {
250 public:
251   TypeDirective(std::unique_ptr<Element> arg) : operand(std::move(arg)) {}
252   Element *getOperand() const { return operand.get(); }
253 
254 private:
255   /// The operand that is used to format the directive.
256   std::unique_ptr<Element> operand;
257 };
258 } // namespace
259 
260 //===----------------------------------------------------------------------===//
261 // LiteralElement
262 
263 namespace {
264 /// This class represents an instance of a literal element.
265 class LiteralElement : public Element {
266 public:
267   LiteralElement(StringRef literal)
268       : Element{Kind::Literal}, literal(literal) {}
269   static bool classof(const Element *element) {
270     return element->getKind() == Kind::Literal;
271   }
272 
273   /// Return the literal for this element.
274   StringRef getLiteral() const { return literal; }
275 
276   /// Returns true if the given string is a valid literal.
277   static bool isValidLiteral(StringRef value);
278 
279 private:
280   /// The spelling of the literal for this element.
281   StringRef literal;
282 };
283 } // end anonymous namespace
284 
285 bool LiteralElement::isValidLiteral(StringRef value) {
286   if (value.empty())
287     return false;
288   char front = value.front();
289 
290   // If there is only one character, this must either be punctuation or a
291   // single character bare identifier.
292   if (value.size() == 1)
293     return isalpha(front) || StringRef("_:,=<>()[]{}?+*").contains(front);
294 
295   // Check the punctuation that are larger than a single character.
296   if (value == "->")
297     return true;
298 
299   // Otherwise, this must be an identifier.
300   return canFormatStringAsKeyword(value);
301 }
302 
303 //===----------------------------------------------------------------------===//
304 // WhitespaceElement
305 
306 namespace {
307 /// This class represents a whitespace element, e.g. newline or space. It's a
308 /// literal that is printed but never parsed.
309 class WhitespaceElement : public Element {
310 public:
311   WhitespaceElement(Kind kind) : Element{kind} {}
312   static bool classof(const Element *element) {
313     Kind kind = element->getKind();
314     return kind == Kind::Newline || kind == Kind::Space;
315   }
316 };
317 
318 /// This class represents an instance of a newline element. It's a literal that
319 /// prints a newline. It is ignored by the parser.
320 class NewlineElement : public WhitespaceElement {
321 public:
322   NewlineElement() : WhitespaceElement(Kind::Newline) {}
323   static bool classof(const Element *element) {
324     return element->getKind() == Kind::Newline;
325   }
326 };
327 
328 /// This class represents an instance of a space element. It's a literal that
329 /// prints or omits printing a space. It is ignored by the parser.
330 class SpaceElement : public WhitespaceElement {
331 public:
332   SpaceElement(bool value) : WhitespaceElement(Kind::Space), value(value) {}
333   static bool classof(const Element *element) {
334     return element->getKind() == Kind::Space;
335   }
336 
337   /// Returns true if this element should print as a space. Otherwise, the
338   /// element should omit printing a space between the surrounding elements.
339   bool getValue() const { return value; }
340 
341 private:
342   bool value;
343 };
344 } // end anonymous namespace
345 
346 //===----------------------------------------------------------------------===//
347 // OptionalElement
348 
349 namespace {
350 /// This class represents a group of elements that are optionally emitted based
351 /// upon an optional variable of the operation, and a group of elements that are
352 /// emotted when the anchor element is not present.
353 class OptionalElement : public Element {
354 public:
355   OptionalElement(std::vector<std::unique_ptr<Element>> &&thenElements,
356                   std::vector<std::unique_ptr<Element>> &&elseElements,
357                   unsigned anchor, unsigned parseStart)
358       : Element{Kind::Optional}, thenElements(std::move(thenElements)),
359         elseElements(std::move(elseElements)), anchor(anchor),
360         parseStart(parseStart) {}
361   static bool classof(const Element *element) {
362     return element->getKind() == Kind::Optional;
363   }
364 
365   /// Return the `then` elements of this grouping.
366   auto getThenElements() const {
367     return llvm::make_pointee_range(thenElements);
368   }
369 
370   /// Return the `else` elements of this grouping.
371   auto getElseElements() const {
372     return llvm::make_pointee_range(elseElements);
373   }
374 
375   /// Return the anchor of this optional group.
376   Element *getAnchor() const { return thenElements[anchor].get(); }
377 
378   /// Return the index of the first element that needs to be parsed.
379   unsigned getParseStart() const { return parseStart; }
380 
381 private:
382   /// The child elements of `then` branch of this optional.
383   std::vector<std::unique_ptr<Element>> thenElements;
384   /// The child elements of `else` branch of this optional.
385   std::vector<std::unique_ptr<Element>> elseElements;
386   /// The index of the element that acts as the anchor for the optional group.
387   unsigned anchor;
388   /// The index of the first element that is parsed (is not a
389   /// WhitespaceElement).
390   unsigned parseStart;
391 };
392 } // end anonymous namespace
393 
394 //===----------------------------------------------------------------------===//
395 // OperationFormat
396 //===----------------------------------------------------------------------===//
397 
398 namespace {
399 
400 using ConstArgument =
401     llvm::PointerUnion<const NamedAttribute *, const NamedTypeConstraint *>;
402 
403 struct OperationFormat {
404   /// This class represents a specific resolver for an operand or result type.
405   class TypeResolution {
406   public:
407     TypeResolution() = default;
408 
409     /// Get the index into the buildable types for this type, or None.
410     Optional<int> getBuilderIdx() const { return builderIdx; }
411     void setBuilderIdx(int idx) { builderIdx = idx; }
412 
413     /// Get the variable this type is resolved to, or nullptr.
414     const NamedTypeConstraint *getVariable() const {
415       return resolver.dyn_cast<const NamedTypeConstraint *>();
416     }
417     /// Get the attribute this type is resolved to, or nullptr.
418     const NamedAttribute *getAttribute() const {
419       return resolver.dyn_cast<const NamedAttribute *>();
420     }
421     /// Get the transformer for the type of the variable, or None.
422     Optional<StringRef> getVarTransformer() const {
423       return variableTransformer;
424     }
425     void setResolver(ConstArgument arg, Optional<StringRef> transformer) {
426       resolver = arg;
427       variableTransformer = transformer;
428       assert(getVariable() || getAttribute());
429     }
430 
431   private:
432     /// If the type is resolved with a buildable type, this is the index into
433     /// 'buildableTypes' in the parent format.
434     Optional<int> builderIdx;
435     /// If the type is resolved based upon another operand or result, this is
436     /// the variable or the attribute that this type is resolved to.
437     ConstArgument resolver;
438     /// If the type is resolved based upon another operand or result, this is
439     /// a transformer to apply to the variable when resolving.
440     Optional<StringRef> variableTransformer;
441   };
442 
443   OperationFormat(const Operator &op)
444       : allOperands(false), allOperandTypes(false), allResultTypes(false) {
445     operandTypes.resize(op.getNumOperands(), TypeResolution());
446     resultTypes.resize(op.getNumResults(), TypeResolution());
447 
448     hasImplicitTermTrait =
449         llvm::any_of(op.getTraits(), [](const OpTrait &trait) {
450           return trait.getDef().isSubClassOf("SingleBlockImplicitTerminator");
451         });
452   }
453 
454   /// Generate the operation parser from this format.
455   void genParser(Operator &op, OpClass &opClass);
456   /// Generate the parser code for a specific format element.
457   void genElementParser(Element *element, OpMethodBody &body,
458                         FmtContext &attrTypeCtx);
459   /// Generate the c++ to resolve the types of operands and results during
460   /// parsing.
461   void genParserTypeResolution(Operator &op, OpMethodBody &body);
462   /// Generate the c++ to resolve regions during parsing.
463   void genParserRegionResolution(Operator &op, OpMethodBody &body);
464   /// Generate the c++ to resolve successors during parsing.
465   void genParserSuccessorResolution(Operator &op, OpMethodBody &body);
466   /// Generate the c++ to handling variadic segment size traits.
467   void genParserVariadicSegmentResolution(Operator &op, OpMethodBody &body);
468 
469   /// Generate the operation printer from this format.
470   void genPrinter(Operator &op, OpClass &opClass);
471 
472   /// Generate the printer code for a specific format element.
473   void genElementPrinter(Element *element, OpMethodBody &body, Operator &op,
474                          bool &shouldEmitSpace, bool &lastWasPunctuation);
475 
476   /// The various elements in this format.
477   std::vector<std::unique_ptr<Element>> elements;
478 
479   /// A flag indicating if all operand/result types were seen. If the format
480   /// contains these, it can not contain individual type resolvers.
481   bool allOperands, allOperandTypes, allResultTypes;
482 
483   /// A flag indicating if this operation has the SingleBlockImplicitTerminator
484   /// trait.
485   bool hasImplicitTermTrait;
486 
487   /// A map of buildable types to indices.
488   llvm::MapVector<StringRef, int, llvm::StringMap<int>> buildableTypes;
489 
490   /// The index of the buildable type, if valid, for every operand and result.
491   std::vector<TypeResolution> operandTypes, resultTypes;
492 
493   /// The set of attributes explicitly used within the format.
494   SmallVector<const NamedAttribute *, 8> usedAttributes;
495 };
496 } // end anonymous namespace
497 
498 //===----------------------------------------------------------------------===//
499 // Parser Gen
500 
501 /// Returns true if we can format the given attribute as an EnumAttr in the
502 /// parser format.
503 static bool canFormatEnumAttr(const NamedAttribute *attr) {
504   Attribute baseAttr = attr->attr.getBaseAttr();
505   const EnumAttr *enumAttr = dyn_cast<EnumAttr>(&baseAttr);
506   if (!enumAttr)
507     return false;
508 
509   // The attribute must have a valid underlying type and a constant builder.
510   return !enumAttr->getUnderlyingType().empty() &&
511          !enumAttr->getConstBuilderTemplate().empty();
512 }
513 
514 /// Returns if we should format the given attribute as an SymbolNameAttr.
515 static bool shouldFormatSymbolNameAttr(const NamedAttribute *attr) {
516   return attr->attr.getBaseAttr().getAttrDefName() == "SymbolNameAttr";
517 }
518 
519 /// The code snippet used to generate a parser call for an attribute.
520 ///
521 /// {0}: The name of the attribute.
522 /// {1}: The type for the attribute.
523 const char *const attrParserCode = R"(
524   if (parser.parseAttribute({0}Attr{1}, "{0}", result.attributes))
525     return ::mlir::failure();
526 )";
527 const char *const optionalAttrParserCode = R"(
528   {
529     ::mlir::OptionalParseResult parseResult =
530       parser.parseOptionalAttribute({0}Attr{1}, "{0}", result.attributes);
531     if (parseResult.hasValue() && failed(*parseResult))
532       return ::mlir::failure();
533   }
534 )";
535 
536 /// The code snippet used to generate a parser call for a symbol name attribute.
537 ///
538 /// {0}: The name of the attribute.
539 const char *const symbolNameAttrParserCode = R"(
540   if (parser.parseSymbolName({0}Attr, "{0}", result.attributes))
541     return ::mlir::failure();
542 )";
543 const char *const optionalSymbolNameAttrParserCode = R"(
544   // Parsing an optional symbol name doesn't fail, so no need to check the
545   // result.
546   (void)parser.parseOptionalSymbolName({0}Attr, "{0}", result.attributes);
547 )";
548 
549 /// The code snippet used to generate a parser call for an enum attribute.
550 ///
551 /// {0}: The name of the attribute.
552 /// {1}: The c++ namespace for the enum symbolize functions.
553 /// {2}: The function to symbolize a string of the enum.
554 /// {3}: The constant builder call to create an attribute of the enum type.
555 /// {4}: The set of allowed enum keywords.
556 /// {5}: The error message on failure when the enum isn't present.
557 const char *const enumAttrParserCode = R"(
558   {
559     ::llvm::StringRef attrStr;
560     ::mlir::NamedAttrList attrStorage;
561     auto loc = parser.getCurrentLocation();
562     if (parser.parseOptionalKeyword(&attrStr, {4})) {
563       ::mlir::StringAttr attrVal;
564       ::mlir::OptionalParseResult parseResult =
565         parser.parseOptionalAttribute(attrVal,
566                                       parser.getBuilder().getNoneType(),
567                                       "{0}", attrStorage);
568       if (parseResult.hasValue()) {{
569         if (failed(*parseResult))
570           return ::mlir::failure();
571         attrStr = attrVal.getValue();
572       } else {
573         {5}
574       }
575     }
576     if (!attrStr.empty()) {
577       auto attrOptional = {1}::{2}(attrStr);
578       if (!attrOptional)
579         return parser.emitError(loc, "invalid ")
580                << "{0} attribute specification: \"" << attrStr << '"';;
581 
582       {0}Attr = {3};
583       result.addAttribute("{0}", {0}Attr);
584     }
585   }
586 )";
587 
588 /// The code snippet used to generate a parser call for an operand.
589 ///
590 /// {0}: The name of the operand.
591 const char *const variadicOperandParserCode = R"(
592   {0}OperandsLoc = parser.getCurrentLocation();
593   if (parser.parseOperandList({0}Operands))
594     return ::mlir::failure();
595 )";
596 const char *const optionalOperandParserCode = R"(
597   {
598     {0}OperandsLoc = parser.getCurrentLocation();
599     ::mlir::OpAsmParser::OperandType operand;
600     ::mlir::OptionalParseResult parseResult =
601                                     parser.parseOptionalOperand(operand);
602     if (parseResult.hasValue()) {
603       if (failed(*parseResult))
604         return ::mlir::failure();
605       {0}Operands.push_back(operand);
606     }
607   }
608 )";
609 const char *const operandParserCode = R"(
610   {0}OperandsLoc = parser.getCurrentLocation();
611   if (parser.parseOperand({0}RawOperands[0]))
612     return ::mlir::failure();
613 )";
614 
615 /// The code snippet used to generate a parser call for a type list.
616 ///
617 /// {0}: The name for the type list.
618 const char *const variadicTypeParserCode = R"(
619   if (parser.parseTypeList({0}Types))
620     return ::mlir::failure();
621 )";
622 const char *const optionalTypeParserCode = R"(
623   {
624     ::mlir::Type optionalType;
625     ::mlir::OptionalParseResult parseResult =
626                                     parser.parseOptionalType(optionalType);
627     if (parseResult.hasValue()) {
628       if (failed(*parseResult))
629         return ::mlir::failure();
630       {0}Types.push_back(optionalType);
631     }
632   }
633 )";
634 const char *const typeParserCode = R"(
635   if (parser.parseType({0}RawTypes[0]))
636     return ::mlir::failure();
637 )";
638 
639 /// The code snippet used to generate a parser call for a functional type.
640 ///
641 /// {0}: The name for the input type list.
642 /// {1}: The name for the result type list.
643 const char *const functionalTypeParserCode = R"(
644   ::mlir::FunctionType {0}__{1}_functionType;
645   if (parser.parseType({0}__{1}_functionType))
646     return ::mlir::failure();
647   {0}Types = {0}__{1}_functionType.getInputs();
648   {1}Types = {0}__{1}_functionType.getResults();
649 )";
650 
651 /// The code snippet used to generate a parser call for a region list.
652 ///
653 /// {0}: The name for the region list.
654 const char *regionListParserCode = R"(
655   {
656     std::unique_ptr<::mlir::Region> region;
657     auto firstRegionResult = parser.parseOptionalRegion(region);
658     if (firstRegionResult.hasValue()) {
659       if (failed(*firstRegionResult))
660         return ::mlir::failure();
661       {0}Regions.emplace_back(std::move(region));
662 
663       // Parse any trailing regions.
664       while (succeeded(parser.parseOptionalComma())) {
665         region = std::make_unique<::mlir::Region>();
666         if (parser.parseRegion(*region))
667           return ::mlir::failure();
668         {0}Regions.emplace_back(std::move(region));
669       }
670     }
671   }
672 )";
673 
674 /// The code snippet used to ensure a list of regions have terminators.
675 ///
676 /// {0}: The name of the region list.
677 const char *regionListEnsureTerminatorParserCode = R"(
678   for (auto &region : {0}Regions)
679     ensureTerminator(*region, parser.getBuilder(), result.location);
680 )";
681 
682 /// The code snippet used to generate a parser call for an optional region.
683 ///
684 /// {0}: The name of the region.
685 const char *optionalRegionParserCode = R"(
686   {
687      auto parseResult = parser.parseOptionalRegion(*{0}Region);
688      if (parseResult.hasValue() && failed(*parseResult))
689        return ::mlir::failure();
690   }
691 )";
692 
693 /// The code snippet used to generate a parser call for a region.
694 ///
695 /// {0}: The name of the region.
696 const char *regionParserCode = R"(
697   if (parser.parseRegion(*{0}Region))
698     return ::mlir::failure();
699 )";
700 
701 /// The code snippet used to ensure a region has a terminator.
702 ///
703 /// {0}: The name of the region.
704 const char *regionEnsureTerminatorParserCode = R"(
705   ensureTerminator(*{0}Region, parser.getBuilder(), result.location);
706 )";
707 
708 /// The code snippet used to generate a parser call for a successor list.
709 ///
710 /// {0}: The name for the successor list.
711 const char *successorListParserCode = R"(
712   {
713     ::mlir::Block *succ;
714     auto firstSucc = parser.parseOptionalSuccessor(succ);
715     if (firstSucc.hasValue()) {
716       if (failed(*firstSucc))
717         return ::mlir::failure();
718       {0}Successors.emplace_back(succ);
719 
720       // Parse any trailing successors.
721       while (succeeded(parser.parseOptionalComma())) {
722         if (parser.parseSuccessor(succ))
723           return ::mlir::failure();
724         {0}Successors.emplace_back(succ);
725       }
726     }
727   }
728 )";
729 
730 /// The code snippet used to generate a parser call for a successor.
731 ///
732 /// {0}: The name of the successor.
733 const char *successorParserCode = R"(
734   if (parser.parseSuccessor({0}Successor))
735     return ::mlir::failure();
736 )";
737 
738 namespace {
739 /// The type of length for a given parse argument.
740 enum class ArgumentLengthKind {
741   /// The argument is variadic, and may contain 0->N elements.
742   Variadic,
743   /// The argument is optional, and may contain 0 or 1 elements.
744   Optional,
745   /// The argument is a single element, i.e. always represents 1 element.
746   Single
747 };
748 } // end anonymous namespace
749 
750 /// Get the length kind for the given constraint.
751 static ArgumentLengthKind
752 getArgumentLengthKind(const NamedTypeConstraint *var) {
753   if (var->isOptional())
754     return ArgumentLengthKind::Optional;
755   if (var->isVariadic())
756     return ArgumentLengthKind::Variadic;
757   return ArgumentLengthKind::Single;
758 }
759 
760 /// Get the name used for the type list for the given type directive operand.
761 /// 'lengthKind' to the corresponding kind for the given argument.
762 static StringRef getTypeListName(Element *arg, ArgumentLengthKind &lengthKind) {
763   if (auto *operand = dyn_cast<OperandVariable>(arg)) {
764     lengthKind = getArgumentLengthKind(operand->getVar());
765     return operand->getVar()->name;
766   }
767   if (auto *result = dyn_cast<ResultVariable>(arg)) {
768     lengthKind = getArgumentLengthKind(result->getVar());
769     return result->getVar()->name;
770   }
771   lengthKind = ArgumentLengthKind::Variadic;
772   if (isa<OperandsDirective>(arg))
773     return "allOperand";
774   if (isa<ResultsDirective>(arg))
775     return "allResult";
776   llvm_unreachable("unknown 'type' directive argument");
777 }
778 
779 /// Generate the parser for a literal value.
780 static void genLiteralParser(StringRef value, OpMethodBody &body) {
781   // Handle the case of a keyword/identifier.
782   if (value.front() == '_' || isalpha(value.front())) {
783     body << "Keyword(\"" << value << "\")";
784     return;
785   }
786   body << (StringRef)StringSwitch<StringRef>(value)
787               .Case("->", "Arrow()")
788               .Case(":", "Colon()")
789               .Case(",", "Comma()")
790               .Case("=", "Equal()")
791               .Case("<", "Less()")
792               .Case(">", "Greater()")
793               .Case("{", "LBrace()")
794               .Case("}", "RBrace()")
795               .Case("(", "LParen()")
796               .Case(")", "RParen()")
797               .Case("[", "LSquare()")
798               .Case("]", "RSquare()")
799               .Case("?", "Question()")
800               .Case("+", "Plus()")
801               .Case("*", "Star()");
802 }
803 
804 /// Generate the storage code required for parsing the given element.
805 static void genElementParserStorage(Element *element, OpMethodBody &body) {
806   if (auto *optional = dyn_cast<OptionalElement>(element)) {
807     auto elements = optional->getThenElements();
808 
809     // If the anchor is a unit attribute, it won't be parsed directly so elide
810     // it.
811     auto *anchor = dyn_cast<AttributeVariable>(optional->getAnchor());
812     Element *elidedAnchorElement = nullptr;
813     if (anchor && anchor != &*elements.begin() && anchor->isUnitAttr())
814       elidedAnchorElement = anchor;
815     for (auto &childElement : elements)
816       if (&childElement != elidedAnchorElement)
817         genElementParserStorage(&childElement, body);
818     for (auto &childElement : optional->getElseElements())
819       genElementParserStorage(&childElement, body);
820 
821   } else if (auto *custom = dyn_cast<CustomDirective>(element)) {
822     for (auto &paramElement : custom->getArguments())
823       genElementParserStorage(&paramElement, body);
824 
825   } else if (isa<OperandsDirective>(element)) {
826     body << "  ::mlir::SmallVector<::mlir::OpAsmParser::OperandType, 4> "
827             "allOperands;\n";
828 
829   } else if (isa<RegionsDirective>(element)) {
830     body << "  ::llvm::SmallVector<std::unique_ptr<::mlir::Region>, 2> "
831             "fullRegions;\n";
832 
833   } else if (isa<SuccessorsDirective>(element)) {
834     body << "  ::llvm::SmallVector<::mlir::Block *, 2> fullSuccessors;\n";
835 
836   } else if (auto *attr = dyn_cast<AttributeVariable>(element)) {
837     const NamedAttribute *var = attr->getVar();
838     body << llvm::formatv("  {0} {1}Attr;\n", var->attr.getStorageType(),
839                           var->name);
840 
841   } else if (auto *operand = dyn_cast<OperandVariable>(element)) {
842     StringRef name = operand->getVar()->name;
843     if (operand->getVar()->isVariableLength()) {
844       body << "  ::mlir::SmallVector<::mlir::OpAsmParser::OperandType, 4> "
845            << name << "Operands;\n";
846     } else {
847       body << "  ::mlir::OpAsmParser::OperandType " << name
848            << "RawOperands[1];\n"
849            << "  ::llvm::ArrayRef<::mlir::OpAsmParser::OperandType> " << name
850            << "Operands(" << name << "RawOperands);";
851     }
852     body << llvm::formatv("  ::llvm::SMLoc {0}OperandsLoc;\n"
853                           "  (void){0}OperandsLoc;\n",
854                           name);
855 
856   } else if (auto *region = dyn_cast<RegionVariable>(element)) {
857     StringRef name = region->getVar()->name;
858     if (region->getVar()->isVariadic()) {
859       body << llvm::formatv(
860           "  ::llvm::SmallVector<std::unique_ptr<::mlir::Region>, 2> "
861           "{0}Regions;\n",
862           name);
863     } else {
864       body << llvm::formatv("  std::unique_ptr<::mlir::Region> {0}Region = "
865                             "std::make_unique<::mlir::Region>();\n",
866                             name);
867     }
868 
869   } else if (auto *successor = dyn_cast<SuccessorVariable>(element)) {
870     StringRef name = successor->getVar()->name;
871     if (successor->getVar()->isVariadic()) {
872       body << llvm::formatv("  ::llvm::SmallVector<::mlir::Block *, 2> "
873                             "{0}Successors;\n",
874                             name);
875     } else {
876       body << llvm::formatv("  ::mlir::Block *{0}Successor = nullptr;\n", name);
877     }
878 
879   } else if (auto *dir = dyn_cast<TypeDirective>(element)) {
880     ArgumentLengthKind lengthKind;
881     StringRef name = getTypeListName(dir->getOperand(), lengthKind);
882     if (lengthKind != ArgumentLengthKind::Single)
883       body << "  ::mlir::SmallVector<::mlir::Type, 1> " << name << "Types;\n";
884     else
885       body << llvm::formatv("  ::mlir::Type {0}RawTypes[1];\n", name)
886            << llvm::formatv(
887                   "  ::llvm::ArrayRef<::mlir::Type> {0}Types({0}RawTypes);\n",
888                   name);
889   } else if (auto *dir = dyn_cast<FunctionalTypeDirective>(element)) {
890     ArgumentLengthKind ignored;
891     body << "  ::llvm::ArrayRef<::mlir::Type> "
892          << getTypeListName(dir->getInputs(), ignored) << "Types;\n";
893     body << "  ::llvm::ArrayRef<::mlir::Type> "
894          << getTypeListName(dir->getResults(), ignored) << "Types;\n";
895   }
896 }
897 
898 /// Generate the parser for a parameter to a custom directive.
899 static void genCustomParameterParser(Element &param, OpMethodBody &body) {
900   if (auto *attr = dyn_cast<AttributeVariable>(&param)) {
901     body << attr->getVar()->name << "Attr";
902   } else if (isa<AttrDictDirective>(&param)) {
903     body << "result.attributes";
904   } else if (auto *operand = dyn_cast<OperandVariable>(&param)) {
905     StringRef name = operand->getVar()->name;
906     ArgumentLengthKind lengthKind = getArgumentLengthKind(operand->getVar());
907     if (lengthKind == ArgumentLengthKind::Variadic)
908       body << llvm::formatv("{0}Operands", name);
909     else if (lengthKind == ArgumentLengthKind::Optional)
910       body << llvm::formatv("{0}Operand", name);
911     else
912       body << formatv("{0}RawOperands[0]", name);
913 
914   } else if (auto *region = dyn_cast<RegionVariable>(&param)) {
915     StringRef name = region->getVar()->name;
916     if (region->getVar()->isVariadic())
917       body << llvm::formatv("{0}Regions", name);
918     else
919       body << llvm::formatv("*{0}Region", name);
920 
921   } else if (auto *successor = dyn_cast<SuccessorVariable>(&param)) {
922     StringRef name = successor->getVar()->name;
923     if (successor->getVar()->isVariadic())
924       body << llvm::formatv("{0}Successors", name);
925     else
926       body << llvm::formatv("{0}Successor", name);
927 
928   } else if (auto *dir = dyn_cast<RefDirective>(&param)) {
929     genCustomParameterParser(*dir->getOperand(), body);
930 
931   } else if (auto *dir = dyn_cast<TypeDirective>(&param)) {
932     ArgumentLengthKind lengthKind;
933     StringRef listName = getTypeListName(dir->getOperand(), lengthKind);
934     if (lengthKind == ArgumentLengthKind::Variadic)
935       body << llvm::formatv("{0}Types", listName);
936     else if (lengthKind == ArgumentLengthKind::Optional)
937       body << llvm::formatv("{0}Type", listName);
938     else
939       body << formatv("{0}RawTypes[0]", listName);
940   } else {
941     llvm_unreachable("unknown custom directive parameter");
942   }
943 }
944 
945 /// Generate the parser for a custom directive.
946 static void genCustomDirectiveParser(CustomDirective *dir, OpMethodBody &body) {
947   body << "  {\n";
948 
949   // Preprocess the directive variables.
950   // * Add a local variable for optional operands and types. This provides a
951   //   better API to the user defined parser methods.
952   // * Set the location of operand variables.
953   for (Element &param : dir->getArguments()) {
954     if (auto *operand = dyn_cast<OperandVariable>(&param)) {
955       body << "    " << operand->getVar()->name
956            << "OperandsLoc = parser.getCurrentLocation();\n";
957       if (operand->getVar()->isOptional()) {
958         body << llvm::formatv(
959             "    llvm::Optional<::mlir::OpAsmParser::OperandType> "
960             "{0}Operand;\n",
961             operand->getVar()->name);
962       }
963     } else if (auto *dir = dyn_cast<TypeDirective>(&param)) {
964       ArgumentLengthKind lengthKind;
965       StringRef listName = getTypeListName(dir->getOperand(), lengthKind);
966       if (lengthKind == ArgumentLengthKind::Optional)
967         body << llvm::formatv("    ::mlir::Type {0}Type;\n", listName);
968     } else if (auto *dir = dyn_cast<RefDirective>(&param)) {
969       Element *input = dir->getOperand();
970       if (auto *operand = dyn_cast<OperandVariable>(input)) {
971         if (!operand->getVar()->isOptional())
972           continue;
973         body << llvm::formatv(
974             "    {0} {1}Operand = {1}Operands.empty() ? {0}() : "
975             "{1}Operands[0];\n",
976             "llvm::Optional<::mlir::OpAsmParser::OperandType>",
977             operand->getVar()->name);
978 
979       } else if (auto *type = dyn_cast<TypeDirective>(input)) {
980         ArgumentLengthKind lengthKind;
981         StringRef listName = getTypeListName(type->getOperand(), lengthKind);
982         if (lengthKind == ArgumentLengthKind::Optional) {
983           body << llvm::formatv("    ::mlir::Type {0}Type = {0}Types.empty() ? "
984                                 "::mlir::Type() : {0}Types[0];\n",
985                                 listName);
986         }
987       }
988     }
989   }
990 
991   body << "    if (parse" << dir->getName() << "(parser";
992   for (Element &param : dir->getArguments()) {
993     body << ", ";
994     genCustomParameterParser(param, body);
995   }
996 
997   body << "))\n"
998        << "      return ::mlir::failure();\n";
999 
1000   // After parsing, add handling for any of the optional constructs.
1001   for (Element &param : dir->getArguments()) {
1002     if (auto *attr = dyn_cast<AttributeVariable>(&param)) {
1003       const NamedAttribute *var = attr->getVar();
1004       if (var->attr.isOptional())
1005         body << llvm::formatv("    if ({0}Attr)\n  ", var->name);
1006 
1007       body << llvm::formatv("    result.addAttribute(\"{0}\", {0}Attr);\n",
1008                             var->name);
1009     } else if (auto *operand = dyn_cast<OperandVariable>(&param)) {
1010       const NamedTypeConstraint *var = operand->getVar();
1011       if (!var->isOptional())
1012         continue;
1013       body << llvm::formatv("    if ({0}Operand.hasValue())\n"
1014                             "      {0}Operands.push_back(*{0}Operand);\n",
1015                             var->name);
1016     } else if (auto *dir = dyn_cast<TypeDirective>(&param)) {
1017       ArgumentLengthKind lengthKind;
1018       StringRef listName = getTypeListName(dir->getOperand(), lengthKind);
1019       if (lengthKind == ArgumentLengthKind::Optional) {
1020         body << llvm::formatv("    if ({0}Type)\n"
1021                               "      {0}Types.push_back({0}Type);\n",
1022                               listName);
1023       }
1024     }
1025   }
1026 
1027   body << "  }\n";
1028 }
1029 
1030 /// Generate the parser for a enum attribute.
1031 static void genEnumAttrParser(const NamedAttribute *var, OpMethodBody &body,
1032                               FmtContext &attrTypeCtx) {
1033   Attribute baseAttr = var->attr.getBaseAttr();
1034   const EnumAttr &enumAttr = cast<EnumAttr>(baseAttr);
1035   std::vector<EnumAttrCase> cases = enumAttr.getAllCases();
1036 
1037   // Generate the code for building an attribute for this enum.
1038   std::string attrBuilderStr;
1039   {
1040     llvm::raw_string_ostream os(attrBuilderStr);
1041     os << tgfmt(enumAttr.getConstBuilderTemplate(), &attrTypeCtx,
1042                 "attrOptional.getValue()");
1043   }
1044 
1045   // Build a string containing the cases that can be formatted as a keyword.
1046   std::string validCaseKeywordsStr = "{";
1047   llvm::raw_string_ostream validCaseKeywordsOS(validCaseKeywordsStr);
1048   for (const EnumAttrCase &attrCase : cases)
1049     if (canFormatStringAsKeyword(attrCase.getStr()))
1050       validCaseKeywordsOS << '"' << attrCase.getStr() << "\",";
1051   validCaseKeywordsOS.str().back() = '}';
1052 
1053   // If the attribute is not optional, build an error message for the missing
1054   // attribute.
1055   std::string errorMessage;
1056   if (!var->attr.isOptional()) {
1057     llvm::raw_string_ostream errorMessageOS(errorMessage);
1058     errorMessageOS
1059         << "return parser.emitError(loc, \"expected string or "
1060            "keyword containing one of the following enum values for attribute '"
1061         << var->name << "' [";
1062     llvm::interleaveComma(cases, errorMessageOS, [&](const auto &attrCase) {
1063       errorMessageOS << attrCase.getStr();
1064     });
1065     errorMessageOS << "]\");";
1066   }
1067 
1068   body << formatv(enumAttrParserCode, var->name, enumAttr.getCppNamespace(),
1069                   enumAttr.getStringToSymbolFnName(), attrBuilderStr,
1070                   validCaseKeywordsStr, errorMessage);
1071 }
1072 
1073 void OperationFormat::genParser(Operator &op, OpClass &opClass) {
1074   llvm::SmallVector<OpMethodParameter, 4> paramList;
1075   paramList.emplace_back("::mlir::OpAsmParser &", "parser");
1076   paramList.emplace_back("::mlir::OperationState &", "result");
1077 
1078   auto *method =
1079       opClass.addMethodAndPrune("::mlir::ParseResult", "parse",
1080                                 OpMethod::MP_Static, std::move(paramList));
1081   auto &body = method->body();
1082 
1083   // Generate variables to store the operands and type within the format. This
1084   // allows for referencing these variables in the presence of optional
1085   // groupings.
1086   for (auto &element : elements)
1087     genElementParserStorage(&*element, body);
1088 
1089   // A format context used when parsing attributes with buildable types.
1090   FmtContext attrTypeCtx;
1091   attrTypeCtx.withBuilder("parser.getBuilder()");
1092 
1093   // Generate parsers for each of the elements.
1094   for (auto &element : elements)
1095     genElementParser(element.get(), body, attrTypeCtx);
1096 
1097   // Generate the code to resolve the operand/result types and successors now
1098   // that they have been parsed.
1099   genParserTypeResolution(op, body);
1100   genParserRegionResolution(op, body);
1101   genParserSuccessorResolution(op, body);
1102   genParserVariadicSegmentResolution(op, body);
1103 
1104   body << "  return ::mlir::success();\n";
1105 }
1106 
1107 void OperationFormat::genElementParser(Element *element, OpMethodBody &body,
1108                                        FmtContext &attrTypeCtx) {
1109   /// Optional Group.
1110   if (auto *optional = dyn_cast<OptionalElement>(element)) {
1111     auto elements = llvm::drop_begin(optional->getThenElements(),
1112                                      optional->getParseStart());
1113 
1114     // Generate a special optional parser for the first element to gate the
1115     // parsing of the rest of the elements.
1116     Element *firstElement = &*elements.begin();
1117     if (auto *attrVar = dyn_cast<AttributeVariable>(firstElement)) {
1118       genElementParser(attrVar, body, attrTypeCtx);
1119       body << "  if (" << attrVar->getVar()->name << "Attr) {\n";
1120     } else if (auto *literal = dyn_cast<LiteralElement>(firstElement)) {
1121       body << "  if (succeeded(parser.parseOptional";
1122       genLiteralParser(literal->getLiteral(), body);
1123       body << ")) {\n";
1124     } else if (auto *opVar = dyn_cast<OperandVariable>(firstElement)) {
1125       genElementParser(opVar, body, attrTypeCtx);
1126       body << "  if (!" << opVar->getVar()->name << "Operands.empty()) {\n";
1127     } else if (auto *regionVar = dyn_cast<RegionVariable>(firstElement)) {
1128       const NamedRegion *region = regionVar->getVar();
1129       if (region->isVariadic()) {
1130         genElementParser(regionVar, body, attrTypeCtx);
1131         body << "  if (!" << region->name << "Regions.empty()) {\n";
1132       } else {
1133         body << llvm::formatv(optionalRegionParserCode, region->name);
1134         body << "  if (!" << region->name << "Region->empty()) {\n  ";
1135         if (hasImplicitTermTrait)
1136           body << llvm::formatv(regionEnsureTerminatorParserCode, region->name);
1137       }
1138     }
1139 
1140     // If the anchor is a unit attribute, we don't need to print it. When
1141     // parsing, we will add this attribute if this group is present.
1142     Element *elidedAnchorElement = nullptr;
1143     auto *anchorAttr = dyn_cast<AttributeVariable>(optional->getAnchor());
1144     if (anchorAttr && anchorAttr != firstElement && anchorAttr->isUnitAttr()) {
1145       elidedAnchorElement = anchorAttr;
1146 
1147       // Add the anchor unit attribute to the operation state.
1148       body << "    result.addAttribute(\"" << anchorAttr->getVar()->name
1149            << "\", parser.getBuilder().getUnitAttr());\n";
1150     }
1151 
1152     // Generate the rest of the elements normally.
1153     for (Element &childElement : llvm::drop_begin(elements, 1)) {
1154       if (&childElement != elidedAnchorElement)
1155         genElementParser(&childElement, body, attrTypeCtx);
1156     }
1157     body << "  }";
1158 
1159     // Generate the else elements.
1160     auto elseElements = optional->getElseElements();
1161     if (!elseElements.empty()) {
1162       body << " else {\n";
1163       for (Element &childElement : elseElements)
1164         genElementParser(&childElement, body, attrTypeCtx);
1165       body << "  }";
1166     }
1167     body << "\n";
1168 
1169     /// Literals.
1170   } else if (LiteralElement *literal = dyn_cast<LiteralElement>(element)) {
1171     body << "  if (parser.parse";
1172     genLiteralParser(literal->getLiteral(), body);
1173     body << ")\n    return ::mlir::failure();\n";
1174 
1175     /// Whitespaces.
1176   } else if (isa<WhitespaceElement>(element)) {
1177     // Nothing to parse.
1178 
1179     /// Arguments.
1180   } else if (auto *attr = dyn_cast<AttributeVariable>(element)) {
1181     const NamedAttribute *var = attr->getVar();
1182 
1183     // Check to see if we can parse this as an enum attribute.
1184     if (canFormatEnumAttr(var))
1185       return genEnumAttrParser(var, body, attrTypeCtx);
1186 
1187     // Check to see if we should parse this as a symbol name attribute.
1188     if (shouldFormatSymbolNameAttr(var)) {
1189       body << formatv(var->attr.isOptional() ? optionalSymbolNameAttrParserCode
1190                                              : symbolNameAttrParserCode,
1191                       var->name);
1192       return;
1193     }
1194 
1195     // If this attribute has a buildable type, use that when parsing the
1196     // attribute.
1197     std::string attrTypeStr;
1198     if (Optional<StringRef> typeBuilder = attr->getTypeBuilder()) {
1199       llvm::raw_string_ostream os(attrTypeStr);
1200       os << ", " << tgfmt(*typeBuilder, &attrTypeCtx);
1201     }
1202 
1203     body << formatv(var->attr.isOptional() ? optionalAttrParserCode
1204                                            : attrParserCode,
1205                     var->name, attrTypeStr);
1206   } else if (auto *operand = dyn_cast<OperandVariable>(element)) {
1207     ArgumentLengthKind lengthKind = getArgumentLengthKind(operand->getVar());
1208     StringRef name = operand->getVar()->name;
1209     if (lengthKind == ArgumentLengthKind::Variadic)
1210       body << llvm::formatv(variadicOperandParserCode, name);
1211     else if (lengthKind == ArgumentLengthKind::Optional)
1212       body << llvm::formatv(optionalOperandParserCode, name);
1213     else
1214       body << formatv(operandParserCode, name);
1215 
1216   } else if (auto *region = dyn_cast<RegionVariable>(element)) {
1217     bool isVariadic = region->getVar()->isVariadic();
1218     body << llvm::formatv(isVariadic ? regionListParserCode : regionParserCode,
1219                           region->getVar()->name);
1220     if (hasImplicitTermTrait) {
1221       body << llvm::formatv(isVariadic ? regionListEnsureTerminatorParserCode
1222                                        : regionEnsureTerminatorParserCode,
1223                             region->getVar()->name);
1224     }
1225 
1226   } else if (auto *successor = dyn_cast<SuccessorVariable>(element)) {
1227     bool isVariadic = successor->getVar()->isVariadic();
1228     body << formatv(isVariadic ? successorListParserCode : successorParserCode,
1229                     successor->getVar()->name);
1230 
1231     /// Directives.
1232   } else if (auto *attrDict = dyn_cast<AttrDictDirective>(element)) {
1233     body << "  if (parser.parseOptionalAttrDict"
1234          << (attrDict->isWithKeyword() ? "WithKeyword" : "")
1235          << "(result.attributes))\n"
1236          << "    return ::mlir::failure();\n";
1237   } else if (auto *customDir = dyn_cast<CustomDirective>(element)) {
1238     genCustomDirectiveParser(customDir, body);
1239 
1240   } else if (isa<OperandsDirective>(element)) {
1241     body << "  ::llvm::SMLoc allOperandLoc = parser.getCurrentLocation();\n"
1242          << "  if (parser.parseOperandList(allOperands))\n"
1243          << "    return ::mlir::failure();\n";
1244 
1245   } else if (isa<RegionsDirective>(element)) {
1246     body << llvm::formatv(regionListParserCode, "full");
1247     if (hasImplicitTermTrait)
1248       body << llvm::formatv(regionListEnsureTerminatorParserCode, "full");
1249 
1250   } else if (isa<SuccessorsDirective>(element)) {
1251     body << llvm::formatv(successorListParserCode, "full");
1252 
1253   } else if (auto *dir = dyn_cast<TypeDirective>(element)) {
1254     ArgumentLengthKind lengthKind;
1255     StringRef listName = getTypeListName(dir->getOperand(), lengthKind);
1256     if (lengthKind == ArgumentLengthKind::Variadic)
1257       body << llvm::formatv(variadicTypeParserCode, listName);
1258     else if (lengthKind == ArgumentLengthKind::Optional)
1259       body << llvm::formatv(optionalTypeParserCode, listName);
1260     else
1261       body << formatv(typeParserCode, listName);
1262   } else if (auto *dir = dyn_cast<FunctionalTypeDirective>(element)) {
1263     ArgumentLengthKind ignored;
1264     body << formatv(functionalTypeParserCode,
1265                     getTypeListName(dir->getInputs(), ignored),
1266                     getTypeListName(dir->getResults(), ignored));
1267   } else {
1268     llvm_unreachable("unknown format element");
1269   }
1270 }
1271 
1272 void OperationFormat::genParserTypeResolution(Operator &op,
1273                                               OpMethodBody &body) {
1274   // If any of type resolutions use transformed variables, make sure that the
1275   // types of those variables are resolved.
1276   SmallPtrSet<const NamedTypeConstraint *, 8> verifiedVariables;
1277   FmtContext verifierFCtx;
1278   for (TypeResolution &resolver :
1279        llvm::concat<TypeResolution>(resultTypes, operandTypes)) {
1280     Optional<StringRef> transformer = resolver.getVarTransformer();
1281     if (!transformer)
1282       continue;
1283     // Ensure that we don't verify the same variables twice.
1284     const NamedTypeConstraint *variable = resolver.getVariable();
1285     if (!variable || !verifiedVariables.insert(variable).second)
1286       continue;
1287 
1288     auto constraint = variable->constraint;
1289     body << "  for (::mlir::Type type : " << variable->name << "Types) {\n"
1290          << "    (void)type;\n"
1291          << "    if (!("
1292          << tgfmt(constraint.getConditionTemplate(),
1293                   &verifierFCtx.withSelf("type"))
1294          << ")) {\n"
1295          << formatv("      return parser.emitError(parser.getNameLoc()) << "
1296                     "\"'{0}' must be {1}, but got \" << type;\n",
1297                     variable->name, constraint.getSummary())
1298          << "    }\n"
1299          << "  }\n";
1300   }
1301 
1302   // Initialize the set of buildable types.
1303   if (!buildableTypes.empty()) {
1304     FmtContext typeBuilderCtx;
1305     typeBuilderCtx.withBuilder("parser.getBuilder()");
1306     for (auto &it : buildableTypes)
1307       body << "  ::mlir::Type odsBuildableType" << it.second << " = "
1308            << tgfmt(it.first, &typeBuilderCtx) << ";\n";
1309   }
1310 
1311   // Emit the code necessary for a type resolver.
1312   auto emitTypeResolver = [&](TypeResolution &resolver, StringRef curVar) {
1313     if (Optional<int> val = resolver.getBuilderIdx()) {
1314       body << "odsBuildableType" << *val;
1315     } else if (const NamedTypeConstraint *var = resolver.getVariable()) {
1316       if (Optional<StringRef> tform = resolver.getVarTransformer()) {
1317         FmtContext fmtContext;
1318         if (var->isVariadic())
1319           fmtContext.withSelf(var->name + "Types");
1320         else
1321           fmtContext.withSelf(var->name + "Types[0]");
1322         body << tgfmt(*tform, &fmtContext);
1323       } else {
1324         body << var->name << "Types";
1325       }
1326     } else if (const NamedAttribute *attr = resolver.getAttribute()) {
1327       if (Optional<StringRef> tform = resolver.getVarTransformer())
1328         body << tgfmt(*tform,
1329                       &FmtContext().withSelf(attr->name + "Attr.getType()"));
1330       else
1331         body << attr->name << "Attr.getType()";
1332     } else {
1333       body << curVar << "Types";
1334     }
1335   };
1336 
1337   // Resolve each of the result types.
1338   if (allResultTypes) {
1339     body << "  result.addTypes(allResultTypes);\n";
1340   } else {
1341     for (unsigned i = 0, e = op.getNumResults(); i != e; ++i) {
1342       body << "  result.addTypes(";
1343       emitTypeResolver(resultTypes[i], op.getResultName(i));
1344       body << ");\n";
1345     }
1346   }
1347 
1348   // Early exit if there are no operands.
1349   if (op.getNumOperands() == 0)
1350     return;
1351 
1352   // Handle the case where all operand types are in one group.
1353   if (allOperandTypes) {
1354     // If we have all operands together, use the full operand list directly.
1355     if (allOperands) {
1356       body << "  if (parser.resolveOperands(allOperands, allOperandTypes, "
1357               "allOperandLoc, result.operands))\n"
1358               "    return ::mlir::failure();\n";
1359       return;
1360     }
1361 
1362     // Otherwise, use llvm::concat to merge the disjoint operand lists together.
1363     // llvm::concat does not allow the case of a single range, so guard it here.
1364     body << "  if (parser.resolveOperands(";
1365     if (op.getNumOperands() > 1) {
1366       body << "::llvm::concat<const ::mlir::OpAsmParser::OperandType>(";
1367       llvm::interleaveComma(op.getOperands(), body, [&](auto &operand) {
1368         body << operand.name << "Operands";
1369       });
1370       body << ")";
1371     } else {
1372       body << op.operand_begin()->name << "Operands";
1373     }
1374     body << ", allOperandTypes, parser.getNameLoc(), result.operands))\n"
1375          << "    return ::mlir::failure();\n";
1376     return;
1377   }
1378   // Handle the case where all of the operands were grouped together.
1379   if (allOperands) {
1380     body << "  if (parser.resolveOperands(allOperands, ";
1381 
1382     // Group all of the operand types together to perform the resolution all at
1383     // once. Use llvm::concat to perform the merge. llvm::concat does not allow
1384     // the case of a single range, so guard it here.
1385     if (op.getNumOperands() > 1) {
1386       body << "::llvm::concat<const Type>(";
1387       llvm::interleaveComma(
1388           llvm::seq<int>(0, op.getNumOperands()), body, [&](int i) {
1389             body << "::llvm::ArrayRef<::mlir::Type>(";
1390             emitTypeResolver(operandTypes[i], op.getOperand(i).name);
1391             body << ")";
1392           });
1393       body << ")";
1394     } else {
1395       emitTypeResolver(operandTypes.front(), op.getOperand(0).name);
1396     }
1397 
1398     body << ", allOperandLoc, result.operands))\n"
1399          << "    return ::mlir::failure();\n";
1400     return;
1401   }
1402 
1403   // The final case is the one where each of the operands types are resolved
1404   // separately.
1405   for (unsigned i = 0, e = op.getNumOperands(); i != e; ++i) {
1406     NamedTypeConstraint &operand = op.getOperand(i);
1407     body << "  if (parser.resolveOperands(" << operand.name << "Operands, ";
1408 
1409     // Resolve the type of this operand.
1410     TypeResolution &operandType = operandTypes[i];
1411     emitTypeResolver(operandType, operand.name);
1412 
1413     // If the type is resolved by a non-variadic variable, index into the
1414     // resolved type list. This allows for resolving the types of a variadic
1415     // operand list from a non-variadic variable.
1416     bool verifyOperandAndTypeSize = true;
1417     if (auto *resolverVar = operandType.getVariable()) {
1418       if (!resolverVar->isVariadic() && !operandType.getVarTransformer()) {
1419         body << "[0]";
1420         verifyOperandAndTypeSize = false;
1421       }
1422     } else {
1423       verifyOperandAndTypeSize = !operandType.getBuilderIdx();
1424     }
1425 
1426     // Check to see if the sizes between the types and operands must match. If
1427     // they do, provide the operand location to select the proper resolution
1428     // overload.
1429     if (verifyOperandAndTypeSize)
1430       body << ", " << operand.name << "OperandsLoc";
1431     body << ", result.operands))\n    return ::mlir::failure();\n";
1432   }
1433 }
1434 
1435 void OperationFormat::genParserRegionResolution(Operator &op,
1436                                                 OpMethodBody &body) {
1437   // Check for the case where all regions were parsed.
1438   bool hasAllRegions = llvm::any_of(
1439       elements, [](auto &elt) { return isa<RegionsDirective>(elt.get()); });
1440   if (hasAllRegions) {
1441     body << "  result.addRegions(fullRegions);\n";
1442     return;
1443   }
1444 
1445   // Otherwise, handle each region individually.
1446   for (const NamedRegion &region : op.getRegions()) {
1447     if (region.isVariadic())
1448       body << "  result.addRegions(" << region.name << "Regions);\n";
1449     else
1450       body << "  result.addRegion(std::move(" << region.name << "Region));\n";
1451   }
1452 }
1453 
1454 void OperationFormat::genParserSuccessorResolution(Operator &op,
1455                                                    OpMethodBody &body) {
1456   // Check for the case where all successors were parsed.
1457   bool hasAllSuccessors = llvm::any_of(
1458       elements, [](auto &elt) { return isa<SuccessorsDirective>(elt.get()); });
1459   if (hasAllSuccessors) {
1460     body << "  result.addSuccessors(fullSuccessors);\n";
1461     return;
1462   }
1463 
1464   // Otherwise, handle each successor individually.
1465   for (const NamedSuccessor &successor : op.getSuccessors()) {
1466     if (successor.isVariadic())
1467       body << "  result.addSuccessors(" << successor.name << "Successors);\n";
1468     else
1469       body << "  result.addSuccessors(" << successor.name << "Successor);\n";
1470   }
1471 }
1472 
1473 void OperationFormat::genParserVariadicSegmentResolution(Operator &op,
1474                                                          OpMethodBody &body) {
1475   if (!allOperands &&
1476       op.getTrait("::mlir::OpTrait::AttrSizedOperandSegments")) {
1477     body << "  result.addAttribute(\"operand_segment_sizes\", "
1478          << "parser.getBuilder().getI32VectorAttr({";
1479     auto interleaveFn = [&](const NamedTypeConstraint &operand) {
1480       // If the operand is variadic emit the parsed size.
1481       if (operand.isVariableLength())
1482         body << "static_cast<int32_t>(" << operand.name << "Operands.size())";
1483       else
1484         body << "1";
1485     };
1486     llvm::interleaveComma(op.getOperands(), body, interleaveFn);
1487     body << "}));\n";
1488   }
1489 
1490   if (!allResultTypes &&
1491       op.getTrait("::mlir::OpTrait::AttrSizedResultSegments")) {
1492     body << "  result.addAttribute(\"result_segment_sizes\", "
1493          << "parser.getBuilder().getI32VectorAttr({";
1494     auto interleaveFn = [&](const NamedTypeConstraint &result) {
1495       // If the result is variadic emit the parsed size.
1496       if (result.isVariableLength())
1497         body << "static_cast<int32_t>(" << result.name << "Types.size())";
1498       else
1499         body << "1";
1500     };
1501     llvm::interleaveComma(op.getResults(), body, interleaveFn);
1502     body << "}));\n";
1503   }
1504 }
1505 
1506 //===----------------------------------------------------------------------===//
1507 // PrinterGen
1508 
1509 /// The code snippet used to generate a printer call for a region of an
1510 // operation that has the SingleBlockImplicitTerminator trait.
1511 ///
1512 /// {0}: The name of the region.
1513 const char *regionSingleBlockImplicitTerminatorPrinterCode = R"(
1514   {
1515     bool printTerminator = true;
1516     if (auto *term = {0}.empty() ? nullptr : {0}.begin()->getTerminator()) {{
1517       printTerminator = !term->getAttrDictionary().empty() ||
1518                         term->getNumOperands() != 0 ||
1519                         term->getNumResults() != 0;
1520     }
1521     p.printRegion({0}, /*printEntryBlockArgs=*/true,
1522                   /*printBlockTerminators=*/printTerminator);
1523   }
1524 )";
1525 
1526 /// The code snippet used to generate a printer call for an enum that has cases
1527 /// that can't be represented with a keyword.
1528 ///
1529 /// {0}: The name of the enum attribute.
1530 /// {1}: The name of the enum attributes symbolToString function.
1531 const char *enumAttrBeginPrinterCode = R"(
1532   {
1533     auto caseValue = {0}();
1534     auto caseValueStr = {1}(caseValue);
1535 )";
1536 
1537 /// Generate the printer for the 'attr-dict' directive.
1538 static void genAttrDictPrinter(OperationFormat &fmt, Operator &op,
1539                                OpMethodBody &body, bool withKeyword) {
1540   body << "  p.printOptionalAttrDict" << (withKeyword ? "WithKeyword" : "")
1541        << "((*this)->getAttrs(), /*elidedAttrs=*/{";
1542   // Elide the variadic segment size attributes if necessary.
1543   if (!fmt.allOperands &&
1544       op.getTrait("::mlir::OpTrait::AttrSizedOperandSegments"))
1545     body << "\"operand_segment_sizes\", ";
1546   if (!fmt.allResultTypes &&
1547       op.getTrait("::mlir::OpTrait::AttrSizedResultSegments"))
1548     body << "\"result_segment_sizes\", ";
1549   llvm::interleaveComma(
1550       fmt.usedAttributes, body,
1551       [&](const NamedAttribute *attr) { body << "\"" << attr->name << "\""; });
1552   body << "});\n";
1553 }
1554 
1555 /// Generate the printer for a literal value. `shouldEmitSpace` is true if a
1556 /// space should be emitted before this element. `lastWasPunctuation` is true if
1557 /// the previous element was a punctuation literal.
1558 static void genLiteralPrinter(StringRef value, OpMethodBody &body,
1559                               bool &shouldEmitSpace, bool &lastWasPunctuation) {
1560   body << "  p";
1561 
1562   // Don't insert a space for certain punctuation.
1563   auto shouldPrintSpaceBeforeLiteral = [&] {
1564     if (value.size() != 1 && value != "->")
1565       return true;
1566     if (lastWasPunctuation)
1567       return !StringRef(">)}],").contains(value.front());
1568     return !StringRef("<>(){}[],").contains(value.front());
1569   };
1570   if (shouldEmitSpace && shouldPrintSpaceBeforeLiteral())
1571     body << " << ' '";
1572   body << " << \"" << value << "\";\n";
1573 
1574   // Insert a space after certain literals.
1575   shouldEmitSpace =
1576       value.size() != 1 || !StringRef("<({[").contains(value.front());
1577   lastWasPunctuation = !(value.front() == '_' || isalpha(value.front()));
1578 }
1579 
1580 /// Generate the printer for a space. `shouldEmitSpace` and `lastWasPunctuation`
1581 /// are set to false.
1582 static void genSpacePrinter(bool value, OpMethodBody &body,
1583                             bool &shouldEmitSpace, bool &lastWasPunctuation) {
1584   if (value) {
1585     body << "  p << ' ';\n";
1586     lastWasPunctuation = false;
1587   } else {
1588     lastWasPunctuation = true;
1589   }
1590   shouldEmitSpace = false;
1591 }
1592 
1593 /// Generate the printer for a custom directive parameter.
1594 static void genCustomDirectiveParameterPrinter(Element *element,
1595                                                OpMethodBody &body) {
1596   if (auto *attr = dyn_cast<AttributeVariable>(element)) {
1597     body << attr->getVar()->name << "Attr()";
1598 
1599   } else if (isa<AttrDictDirective>(element)) {
1600     body << "getOperation()->getAttrDictionary()";
1601 
1602   } else if (auto *operand = dyn_cast<OperandVariable>(element)) {
1603     body << operand->getVar()->name << "()";
1604 
1605   } else if (auto *region = dyn_cast<RegionVariable>(element)) {
1606     body << region->getVar()->name << "()";
1607 
1608   } else if (auto *successor = dyn_cast<SuccessorVariable>(element)) {
1609     body << successor->getVar()->name << "()";
1610 
1611   } else if (auto *dir = dyn_cast<RefDirective>(element)) {
1612     genCustomDirectiveParameterPrinter(dir->getOperand(), body);
1613 
1614   } else if (auto *dir = dyn_cast<TypeDirective>(element)) {
1615     auto *typeOperand = dir->getOperand();
1616     auto *operand = dyn_cast<OperandVariable>(typeOperand);
1617     auto *var = operand ? operand->getVar()
1618                         : cast<ResultVariable>(typeOperand)->getVar();
1619     if (var->isVariadic())
1620       body << var->name << "().getTypes()";
1621     else if (var->isOptional())
1622       body << llvm::formatv("({0}() ? {0}().getType() : Type())", var->name);
1623     else
1624       body << var->name << "().getType()";
1625   } else {
1626     llvm_unreachable("unknown custom directive parameter");
1627   }
1628 }
1629 
1630 /// Generate the printer for a custom directive.
1631 static void genCustomDirectivePrinter(CustomDirective *customDir,
1632                                       OpMethodBody &body) {
1633   body << "  print" << customDir->getName() << "(p, *this";
1634   for (Element &param : customDir->getArguments()) {
1635     body << ", ";
1636     genCustomDirectiveParameterPrinter(&param, body);
1637   }
1638   body << ");\n";
1639 }
1640 
1641 /// Generate the printer for a region with the given variable name.
1642 static void genRegionPrinter(const Twine &regionName, OpMethodBody &body,
1643                              bool hasImplicitTermTrait) {
1644   if (hasImplicitTermTrait)
1645     body << llvm::formatv(regionSingleBlockImplicitTerminatorPrinterCode,
1646                           regionName);
1647   else
1648     body << "  p.printRegion(" << regionName << ");\n";
1649 }
1650 static void genVariadicRegionPrinter(const Twine &regionListName,
1651                                      OpMethodBody &body,
1652                                      bool hasImplicitTermTrait) {
1653   body << "    llvm::interleaveComma(" << regionListName
1654        << ", p, [&](::mlir::Region &region) {\n      ";
1655   genRegionPrinter("region", body, hasImplicitTermTrait);
1656   body << "    });\n";
1657 }
1658 
1659 /// Generate the C++ for an operand to a (*-)type directive.
1660 static OpMethodBody &genTypeOperandPrinter(Element *arg, OpMethodBody &body) {
1661   if (isa<OperandsDirective>(arg))
1662     return body << "getOperation()->getOperandTypes()";
1663   if (isa<ResultsDirective>(arg))
1664     return body << "getOperation()->getResultTypes()";
1665   auto *operand = dyn_cast<OperandVariable>(arg);
1666   auto *var = operand ? operand->getVar() : cast<ResultVariable>(arg)->getVar();
1667   if (var->isVariadic())
1668     return body << var->name << "().getTypes()";
1669   if (var->isOptional())
1670     return body << llvm::formatv(
1671                "({0}() ? ::llvm::ArrayRef<::mlir::Type>({0}().getType()) : "
1672                "::llvm::ArrayRef<::mlir::Type>())",
1673                var->name);
1674   return body << "::llvm::ArrayRef<::mlir::Type>(" << var->name
1675               << "().getType())";
1676 }
1677 
1678 /// Generate the printer for an enum attribute.
1679 static void genEnumAttrPrinter(const NamedAttribute *var, OpMethodBody &body) {
1680   Attribute baseAttr = var->attr.getBaseAttr();
1681   const EnumAttr &enumAttr = cast<EnumAttr>(baseAttr);
1682   std::vector<EnumAttrCase> cases = enumAttr.getAllCases();
1683 
1684   body << llvm::formatv(enumAttrBeginPrinterCode,
1685                         (var->attr.isOptional() ? "*" : "") + var->name,
1686                         enumAttr.getSymbolToStringFnName());
1687 
1688   // Get a string containing all of the cases that can't be represented with a
1689   // keyword.
1690   llvm::BitVector nonKeywordCases(cases.size());
1691   bool hasStrCase = false;
1692   for (auto it : llvm::enumerate(cases)) {
1693     hasStrCase = it.value().isStrCase();
1694     if (!canFormatStringAsKeyword(it.value().getStr()))
1695       nonKeywordCases.set(it.index());
1696   }
1697 
1698   // If this is a string enum, use the case string to determine which cases
1699   // need to use the string form.
1700   if (hasStrCase) {
1701     if (nonKeywordCases.any()) {
1702       body << "    if (llvm::is_contained(llvm::ArrayRef<llvm::StringRef>(";
1703       llvm::interleaveComma(nonKeywordCases.set_bits(), body, [&](unsigned it) {
1704         body << '"' << cases[it].getStr() << '"';
1705       });
1706       body << ")))\n"
1707               "      p << '\"' << caseValueStr << '\"';\n"
1708               "    else\n  ";
1709     }
1710     body << "    p << caseValueStr;\n"
1711             "  }\n";
1712     return;
1713   }
1714 
1715   // Otherwise if this is a bit enum attribute, don't allow cases that may
1716   // overlap with other cases. For simplicity sake, only allow cases with a
1717   // single bit value.
1718   if (enumAttr.isBitEnum()) {
1719     for (auto it : llvm::enumerate(cases)) {
1720       int64_t value = it.value().getValue();
1721       if (value < 0 || !llvm::isPowerOf2_64(value))
1722         nonKeywordCases.set(it.index());
1723     }
1724   }
1725 
1726   // If there are any cases that can't be used with a keyword, switch on the
1727   // case value to determine when to print in the string form.
1728   if (nonKeywordCases.any()) {
1729     body << "    switch (caseValue) {\n";
1730     StringRef cppNamespace = enumAttr.getCppNamespace();
1731     StringRef enumName = enumAttr.getEnumClassName();
1732     for (auto it : llvm::enumerate(cases)) {
1733       if (nonKeywordCases.test(it.index()))
1734         continue;
1735       StringRef symbol = it.value().getSymbol();
1736       body << llvm::formatv("    case {0}::{1}::{2}:\n", cppNamespace, enumName,
1737                             llvm::isDigit(symbol.front()) ? ("_" + symbol)
1738                                                           : symbol);
1739     }
1740     body << "      p << caseValueStr;\n"
1741             "      break;\n"
1742             "    default:\n"
1743             "      p << '\"' << caseValueStr << '\"';\n"
1744             "      break;\n"
1745             "    }\n"
1746             "  }\n";
1747     return;
1748   }
1749 
1750   body << "    p << caseValueStr;\n"
1751           "  }\n";
1752 }
1753 
1754 /// Generate the check for the anchor of an optional group.
1755 static void genOptionalGroupPrinterAnchor(Element *anchor, OpMethodBody &body) {
1756   TypeSwitch<Element *>(anchor)
1757       .Case<OperandVariable, ResultVariable>([&](auto *element) {
1758         const NamedTypeConstraint *var = element->getVar();
1759         if (var->isOptional())
1760           body << "  if (" << var->name << "()) {\n";
1761         else if (var->isVariadic())
1762           body << "  if (!" << var->name << "().empty()) {\n";
1763       })
1764       .Case<RegionVariable>([&](RegionVariable *element) {
1765         const NamedRegion *var = element->getVar();
1766         // TODO: Add a check for optional regions here when ODS supports it.
1767         body << "  if (!" << var->name << "().empty()) {\n";
1768       })
1769       .Case<TypeDirective>([&](TypeDirective *element) {
1770         genOptionalGroupPrinterAnchor(element->getOperand(), body);
1771       })
1772       .Case<FunctionalTypeDirective>([&](FunctionalTypeDirective *element) {
1773         genOptionalGroupPrinterAnchor(element->getInputs(), body);
1774       })
1775       .Case<AttributeVariable>([&](AttributeVariable *attr) {
1776         body << "  if ((*this)->getAttr(\"" << attr->getVar()->name
1777              << "\")) {\n";
1778       });
1779 }
1780 
1781 void OperationFormat::genElementPrinter(Element *element, OpMethodBody &body,
1782                                         Operator &op, bool &shouldEmitSpace,
1783                                         bool &lastWasPunctuation) {
1784   if (LiteralElement *literal = dyn_cast<LiteralElement>(element))
1785     return genLiteralPrinter(literal->getLiteral(), body, shouldEmitSpace,
1786                              lastWasPunctuation);
1787 
1788   // Emit a whitespace element.
1789   if (isa<NewlineElement>(element)) {
1790     body << "  p.printNewline();\n";
1791     return;
1792   }
1793   if (SpaceElement *space = dyn_cast<SpaceElement>(element))
1794     return genSpacePrinter(space->getValue(), body, shouldEmitSpace,
1795                            lastWasPunctuation);
1796 
1797   // Emit an optional group.
1798   if (OptionalElement *optional = dyn_cast<OptionalElement>(element)) {
1799     // Emit the check for the presence of the anchor element.
1800     Element *anchor = optional->getAnchor();
1801     genOptionalGroupPrinterAnchor(anchor, body);
1802 
1803     // If the anchor is a unit attribute, we don't need to print it. When
1804     // parsing, we will add this attribute if this group is present.
1805     auto elements = optional->getThenElements();
1806     Element *elidedAnchorElement = nullptr;
1807     auto *anchorAttr = dyn_cast<AttributeVariable>(anchor);
1808     if (anchorAttr && anchorAttr != &*elements.begin() &&
1809         anchorAttr->isUnitAttr()) {
1810       elidedAnchorElement = anchorAttr;
1811     }
1812 
1813     // Emit each of the elements.
1814     for (Element &childElement : elements) {
1815       if (&childElement != elidedAnchorElement) {
1816         genElementPrinter(&childElement, body, op, shouldEmitSpace,
1817                           lastWasPunctuation);
1818       }
1819     }
1820     body << "  }";
1821 
1822     // Emit each of the else elements.
1823     auto elseElements = optional->getElseElements();
1824     if (!elseElements.empty()) {
1825       body << " else {\n";
1826       for (Element &childElement : elseElements) {
1827         genElementPrinter(&childElement, body, op, shouldEmitSpace,
1828                           lastWasPunctuation);
1829       }
1830       body << "  }";
1831     }
1832 
1833     body << "\n";
1834     return;
1835   }
1836 
1837   // Emit the attribute dictionary.
1838   if (auto *attrDict = dyn_cast<AttrDictDirective>(element)) {
1839     genAttrDictPrinter(*this, op, body, attrDict->isWithKeyword());
1840     lastWasPunctuation = false;
1841     return;
1842   }
1843 
1844   // Optionally insert a space before the next element. The AttrDict printer
1845   // already adds a space as necessary.
1846   if (shouldEmitSpace || !lastWasPunctuation)
1847     body << "  p << ' ';\n";
1848   lastWasPunctuation = false;
1849   shouldEmitSpace = true;
1850 
1851   if (auto *attr = dyn_cast<AttributeVariable>(element)) {
1852     const NamedAttribute *var = attr->getVar();
1853 
1854     // If we are formatting as an enum, symbolize the attribute as a string.
1855     if (canFormatEnumAttr(var))
1856       return genEnumAttrPrinter(var, body);
1857 
1858     // If we are formatting as a symbol name, handle it as a symbol name.
1859     if (shouldFormatSymbolNameAttr(var)) {
1860       body << "  p.printSymbolName(" << var->name << "Attr().getValue());\n";
1861       return;
1862     }
1863 
1864     // Elide the attribute type if it is buildable.
1865     if (attr->getTypeBuilder())
1866       body << "  p.printAttributeWithoutType(" << var->name << "Attr());\n";
1867     else
1868       body << "  p.printAttribute(" << var->name << "Attr());\n";
1869   } else if (auto *operand = dyn_cast<OperandVariable>(element)) {
1870     if (operand->getVar()->isOptional()) {
1871       body << "  if (::mlir::Value value = " << operand->getVar()->name
1872            << "())\n"
1873            << "    p << value;\n";
1874     } else {
1875       body << "  p << " << operand->getVar()->name << "();\n";
1876     }
1877   } else if (auto *region = dyn_cast<RegionVariable>(element)) {
1878     const NamedRegion *var = region->getVar();
1879     if (var->isVariadic()) {
1880       genVariadicRegionPrinter(var->name + "()", body, hasImplicitTermTrait);
1881     } else {
1882       genRegionPrinter(var->name + "()", body, hasImplicitTermTrait);
1883     }
1884   } else if (auto *successor = dyn_cast<SuccessorVariable>(element)) {
1885     const NamedSuccessor *var = successor->getVar();
1886     if (var->isVariadic())
1887       body << "  ::llvm::interleaveComma(" << var->name << "(), p);\n";
1888     else
1889       body << "  p << " << var->name << "();\n";
1890   } else if (auto *dir = dyn_cast<CustomDirective>(element)) {
1891     genCustomDirectivePrinter(dir, body);
1892   } else if (isa<OperandsDirective>(element)) {
1893     body << "  p << getOperation()->getOperands();\n";
1894   } else if (isa<RegionsDirective>(element)) {
1895     genVariadicRegionPrinter("getOperation()->getRegions()", body,
1896                              hasImplicitTermTrait);
1897   } else if (isa<SuccessorsDirective>(element)) {
1898     body << "  ::llvm::interleaveComma(getOperation()->getSuccessors(), p);\n";
1899   } else if (auto *dir = dyn_cast<TypeDirective>(element)) {
1900     body << "  p << ";
1901     genTypeOperandPrinter(dir->getOperand(), body) << ";\n";
1902   } else if (auto *dir = dyn_cast<FunctionalTypeDirective>(element)) {
1903     body << "  p.printFunctionalType(";
1904     genTypeOperandPrinter(dir->getInputs(), body) << ", ";
1905     genTypeOperandPrinter(dir->getResults(), body) << ");\n";
1906   } else {
1907     llvm_unreachable("unknown format element");
1908   }
1909 }
1910 
1911 void OperationFormat::genPrinter(Operator &op, OpClass &opClass) {
1912   auto *method =
1913       opClass.addMethodAndPrune("void", "print", "::mlir::OpAsmPrinter &p");
1914   auto &body = method->body();
1915 
1916   // Emit the operation name, trimming the prefix if this is the standard
1917   // dialect.
1918   body << "  p << \"";
1919   std::string opName = op.getOperationName();
1920   if (op.getDialectName() == "std")
1921     body << StringRef(opName).drop_front(4);
1922   else
1923     body << opName;
1924   body << "\";\n";
1925 
1926   // Flags for if we should emit a space, and if the last element was
1927   // punctuation.
1928   bool shouldEmitSpace = true, lastWasPunctuation = false;
1929   for (auto &element : elements)
1930     genElementPrinter(element.get(), body, op, shouldEmitSpace,
1931                       lastWasPunctuation);
1932 }
1933 
1934 //===----------------------------------------------------------------------===//
1935 // FormatLexer
1936 //===----------------------------------------------------------------------===//
1937 
1938 namespace {
1939 /// This class represents a specific token in the input format.
1940 class Token {
1941 public:
1942   enum Kind {
1943     // Markers.
1944     eof,
1945     error,
1946 
1947     // Tokens with no info.
1948     l_paren,
1949     r_paren,
1950     caret,
1951     colon,
1952     comma,
1953     equal,
1954     less,
1955     greater,
1956     question,
1957 
1958     // Keywords.
1959     keyword_start,
1960     kw_attr_dict,
1961     kw_attr_dict_w_keyword,
1962     kw_custom,
1963     kw_functional_type,
1964     kw_operands,
1965     kw_ref,
1966     kw_regions,
1967     kw_results,
1968     kw_successors,
1969     kw_type,
1970     keyword_end,
1971 
1972     // String valued tokens.
1973     identifier,
1974     literal,
1975     variable,
1976   };
1977   Token(Kind kind, StringRef spelling) : kind(kind), spelling(spelling) {}
1978 
1979   /// Return the bytes that make up this token.
1980   StringRef getSpelling() const { return spelling; }
1981 
1982   /// Return the kind of this token.
1983   Kind getKind() const { return kind; }
1984 
1985   /// Return a location for this token.
1986   llvm::SMLoc getLoc() const {
1987     return llvm::SMLoc::getFromPointer(spelling.data());
1988   }
1989 
1990   /// Return if this token is a keyword.
1991   bool isKeyword() const { return kind > keyword_start && kind < keyword_end; }
1992 
1993 private:
1994   /// Discriminator that indicates the kind of token this is.
1995   Kind kind;
1996 
1997   /// A reference to the entire token contents; this is always a pointer into
1998   /// a memory buffer owned by the source manager.
1999   StringRef spelling;
2000 };
2001 
2002 /// This class implements a simple lexer for operation assembly format strings.
2003 class FormatLexer {
2004 public:
2005   FormatLexer(llvm::SourceMgr &mgr, Operator &op);
2006 
2007   /// Lex the next token and return it.
2008   Token lexToken();
2009 
2010   /// Emit an error to the lexer with the given location and message.
2011   Token emitError(llvm::SMLoc loc, const Twine &msg);
2012   Token emitError(const char *loc, const Twine &msg);
2013 
2014   Token emitErrorAndNote(llvm::SMLoc loc, const Twine &msg, const Twine &note);
2015 
2016 private:
2017   Token formToken(Token::Kind kind, const char *tokStart) {
2018     return Token(kind, StringRef(tokStart, curPtr - tokStart));
2019   }
2020 
2021   /// Return the next character in the stream.
2022   int getNextChar();
2023 
2024   /// Lex an identifier, literal, or variable.
2025   Token lexIdentifier(const char *tokStart);
2026   Token lexLiteral(const char *tokStart);
2027   Token lexVariable(const char *tokStart);
2028 
2029   llvm::SourceMgr &srcMgr;
2030   Operator &op;
2031   StringRef curBuffer;
2032   const char *curPtr;
2033 };
2034 } // end anonymous namespace
2035 
2036 FormatLexer::FormatLexer(llvm::SourceMgr &mgr, Operator &op)
2037     : srcMgr(mgr), op(op) {
2038   curBuffer = srcMgr.getMemoryBuffer(mgr.getMainFileID())->getBuffer();
2039   curPtr = curBuffer.begin();
2040 }
2041 
2042 Token FormatLexer::emitError(llvm::SMLoc loc, const Twine &msg) {
2043   srcMgr.PrintMessage(loc, llvm::SourceMgr::DK_Error, msg);
2044   llvm::SrcMgr.PrintMessage(op.getLoc()[0], llvm::SourceMgr::DK_Note,
2045                             "in custom assembly format for this operation");
2046   return formToken(Token::error, loc.getPointer());
2047 }
2048 Token FormatLexer::emitErrorAndNote(llvm::SMLoc loc, const Twine &msg,
2049                                     const Twine &note) {
2050   srcMgr.PrintMessage(loc, llvm::SourceMgr::DK_Error, msg);
2051   llvm::SrcMgr.PrintMessage(op.getLoc()[0], llvm::SourceMgr::DK_Note,
2052                             "in custom assembly format for this operation");
2053   srcMgr.PrintMessage(loc, llvm::SourceMgr::DK_Note, note);
2054   return formToken(Token::error, loc.getPointer());
2055 }
2056 Token FormatLexer::emitError(const char *loc, const Twine &msg) {
2057   return emitError(llvm::SMLoc::getFromPointer(loc), msg);
2058 }
2059 
2060 int FormatLexer::getNextChar() {
2061   char curChar = *curPtr++;
2062   switch (curChar) {
2063   default:
2064     return (unsigned char)curChar;
2065   case 0: {
2066     // A nul character in the stream is either the end of the current buffer or
2067     // a random nul in the file. Disambiguate that here.
2068     if (curPtr - 1 != curBuffer.end())
2069       return 0;
2070 
2071     // Otherwise, return end of file.
2072     --curPtr;
2073     return EOF;
2074   }
2075   case '\n':
2076   case '\r':
2077     // Handle the newline character by ignoring it and incrementing the line
2078     // count. However, be careful about 'dos style' files with \n\r in them.
2079     // Only treat a \n\r or \r\n as a single line.
2080     if ((*curPtr == '\n' || (*curPtr == '\r')) && *curPtr != curChar)
2081       ++curPtr;
2082     return '\n';
2083   }
2084 }
2085 
2086 Token FormatLexer::lexToken() {
2087   const char *tokStart = curPtr;
2088 
2089   // This always consumes at least one character.
2090   int curChar = getNextChar();
2091   switch (curChar) {
2092   default:
2093     // Handle identifiers: [a-zA-Z_]
2094     if (isalpha(curChar) || curChar == '_')
2095       return lexIdentifier(tokStart);
2096 
2097     // Unknown character, emit an error.
2098     return emitError(tokStart, "unexpected character");
2099   case EOF:
2100     // Return EOF denoting the end of lexing.
2101     return formToken(Token::eof, tokStart);
2102 
2103   // Lex punctuation.
2104   case '^':
2105     return formToken(Token::caret, tokStart);
2106   case ':':
2107     return formToken(Token::colon, tokStart);
2108   case ',':
2109     return formToken(Token::comma, tokStart);
2110   case '=':
2111     return formToken(Token::equal, tokStart);
2112   case '<':
2113     return formToken(Token::less, tokStart);
2114   case '>':
2115     return formToken(Token::greater, tokStart);
2116   case '?':
2117     return formToken(Token::question, tokStart);
2118   case '(':
2119     return formToken(Token::l_paren, tokStart);
2120   case ')':
2121     return formToken(Token::r_paren, tokStart);
2122 
2123   // Ignore whitespace characters.
2124   case 0:
2125   case ' ':
2126   case '\t':
2127   case '\n':
2128     return lexToken();
2129 
2130   case '`':
2131     return lexLiteral(tokStart);
2132   case '$':
2133     return lexVariable(tokStart);
2134   }
2135 }
2136 
2137 Token FormatLexer::lexLiteral(const char *tokStart) {
2138   assert(curPtr[-1] == '`');
2139 
2140   // Lex a literal surrounded by ``.
2141   while (const char curChar = *curPtr++) {
2142     if (curChar == '`')
2143       return formToken(Token::literal, tokStart);
2144   }
2145   return emitError(curPtr - 1, "unexpected end of file in literal");
2146 }
2147 
2148 Token FormatLexer::lexVariable(const char *tokStart) {
2149   if (!isalpha(curPtr[0]) && curPtr[0] != '_')
2150     return emitError(curPtr - 1, "expected variable name");
2151 
2152   // Otherwise, consume the rest of the characters.
2153   while (isalnum(*curPtr) || *curPtr == '_')
2154     ++curPtr;
2155   return formToken(Token::variable, tokStart);
2156 }
2157 
2158 Token FormatLexer::lexIdentifier(const char *tokStart) {
2159   // Match the rest of the identifier regex: [0-9a-zA-Z_\-]*
2160   while (isalnum(*curPtr) || *curPtr == '_' || *curPtr == '-')
2161     ++curPtr;
2162 
2163   // Check to see if this identifier is a keyword.
2164   StringRef str(tokStart, curPtr - tokStart);
2165   Token::Kind kind =
2166       StringSwitch<Token::Kind>(str)
2167           .Case("attr-dict", Token::kw_attr_dict)
2168           .Case("attr-dict-with-keyword", Token::kw_attr_dict_w_keyword)
2169           .Case("custom", Token::kw_custom)
2170           .Case("functional-type", Token::kw_functional_type)
2171           .Case("operands", Token::kw_operands)
2172           .Case("ref", Token::kw_ref)
2173           .Case("regions", Token::kw_regions)
2174           .Case("results", Token::kw_results)
2175           .Case("successors", Token::kw_successors)
2176           .Case("type", Token::kw_type)
2177           .Default(Token::identifier);
2178   return Token(kind, str);
2179 }
2180 
2181 //===----------------------------------------------------------------------===//
2182 // FormatParser
2183 //===----------------------------------------------------------------------===//
2184 
2185 /// Function to find an element within the given range that has the same name as
2186 /// 'name'.
2187 template <typename RangeT>
2188 static auto findArg(RangeT &&range, StringRef name) {
2189   auto it = llvm::find_if(range, [=](auto &arg) { return arg.name == name; });
2190   return it != range.end() ? &*it : nullptr;
2191 }
2192 
2193 namespace {
2194 /// This class implements a parser for an instance of an operation assembly
2195 /// format.
2196 class FormatParser {
2197 public:
2198   FormatParser(llvm::SourceMgr &mgr, OperationFormat &format, Operator &op)
2199       : lexer(mgr, op), curToken(lexer.lexToken()), fmt(format), op(op),
2200         seenOperandTypes(op.getNumOperands()),
2201         seenResultTypes(op.getNumResults()) {}
2202 
2203   /// Parse the operation assembly format.
2204   LogicalResult parse();
2205 
2206 private:
2207   /// The current context of the parser when parsing an element.
2208   enum ParserContext {
2209     /// The element is being parsed in a "top-level" context, i.e. at the top of
2210     /// the format or in an optional group.
2211     TopLevelContext,
2212     /// The element is being parsed as a custom directive child.
2213     CustomDirectiveContext,
2214     /// The element is being parsed as a type directive child.
2215     TypeDirectiveContext,
2216     /// The element is being parsed as a reference directive child.
2217     RefDirectiveContext
2218   };
2219 
2220   /// This struct represents a type resolution instance. It includes a specific
2221   /// type as well as an optional transformer to apply to that type in order to
2222   /// properly resolve the type of a variable.
2223   struct TypeResolutionInstance {
2224     ConstArgument resolver;
2225     Optional<StringRef> transformer;
2226   };
2227 
2228   /// An iterator over the elements of a format group.
2229   using ElementsIterT = llvm::pointee_iterator<
2230       std::vector<std::unique_ptr<Element>>::const_iterator>;
2231 
2232   /// Verify the state of operation attributes within the format.
2233   LogicalResult verifyAttributes(llvm::SMLoc loc);
2234   /// Verify the attribute elements at the back of the given stack of iterators.
2235   LogicalResult verifyAttributes(
2236       llvm::SMLoc loc,
2237       SmallVectorImpl<std::pair<ElementsIterT, ElementsIterT>> &iteratorStack);
2238 
2239   /// Verify the state of operation operands within the format.
2240   LogicalResult
2241   verifyOperands(llvm::SMLoc loc,
2242                  llvm::StringMap<TypeResolutionInstance> &variableTyResolver);
2243 
2244   /// Verify the state of operation regions within the format.
2245   LogicalResult verifyRegions(llvm::SMLoc loc);
2246 
2247   /// Verify the state of operation results within the format.
2248   LogicalResult
2249   verifyResults(llvm::SMLoc loc,
2250                 llvm::StringMap<TypeResolutionInstance> &variableTyResolver);
2251 
2252   /// Verify the state of operation successors within the format.
2253   LogicalResult verifySuccessors(llvm::SMLoc loc);
2254 
2255   /// Given the values of an `AllTypesMatch` trait, check for inferable type
2256   /// resolution.
2257   void handleAllTypesMatchConstraint(
2258       ArrayRef<StringRef> values,
2259       llvm::StringMap<TypeResolutionInstance> &variableTyResolver);
2260   /// Check for inferable type resolution given all operands, and or results,
2261   /// have the same type. If 'includeResults' is true, the results also have the
2262   /// same type as all of the operands.
2263   void handleSameTypesConstraint(
2264       llvm::StringMap<TypeResolutionInstance> &variableTyResolver,
2265       bool includeResults);
2266   /// Check for inferable type resolution based on another operand, result, or
2267   /// attribute.
2268   void handleTypesMatchConstraint(
2269       llvm::StringMap<TypeResolutionInstance> &variableTyResolver,
2270       llvm::Record def);
2271 
2272   /// Returns an argument or attribute with the given name that has been seen
2273   /// within the format.
2274   ConstArgument findSeenArg(StringRef name);
2275 
2276   /// Parse a specific element.
2277   LogicalResult parseElement(std::unique_ptr<Element> &element,
2278                              ParserContext context);
2279   LogicalResult parseVariable(std::unique_ptr<Element> &element,
2280                               ParserContext context);
2281   LogicalResult parseDirective(std::unique_ptr<Element> &element,
2282                                ParserContext context);
2283   LogicalResult parseLiteral(std::unique_ptr<Element> &element,
2284                              ParserContext context);
2285   LogicalResult parseOptional(std::unique_ptr<Element> &element,
2286                               ParserContext context);
2287   LogicalResult parseOptionalChildElement(
2288       std::vector<std::unique_ptr<Element>> &childElements,
2289       Optional<unsigned> &anchorIdx);
2290   LogicalResult verifyOptionalChildElement(Element *element,
2291                                            llvm::SMLoc childLoc, bool isAnchor);
2292 
2293   /// Parse the various different directives.
2294   LogicalResult parseAttrDictDirective(std::unique_ptr<Element> &element,
2295                                        llvm::SMLoc loc, ParserContext context,
2296                                        bool withKeyword);
2297   LogicalResult parseCustomDirective(std::unique_ptr<Element> &element,
2298                                      llvm::SMLoc loc, ParserContext context);
2299   LogicalResult parseCustomDirectiveParameter(
2300       std::vector<std::unique_ptr<Element>> &parameters);
2301   LogicalResult parseFunctionalTypeDirective(std::unique_ptr<Element> &element,
2302                                              Token tok, ParserContext context);
2303   LogicalResult parseOperandsDirective(std::unique_ptr<Element> &element,
2304                                        llvm::SMLoc loc, ParserContext context);
2305   LogicalResult parseReferenceDirective(std::unique_ptr<Element> &element,
2306                                         llvm::SMLoc loc, ParserContext context);
2307   LogicalResult parseRegionsDirective(std::unique_ptr<Element> &element,
2308                                       llvm::SMLoc loc, ParserContext context);
2309   LogicalResult parseResultsDirective(std::unique_ptr<Element> &element,
2310                                       llvm::SMLoc loc, ParserContext context);
2311   LogicalResult parseSuccessorsDirective(std::unique_ptr<Element> &element,
2312                                          llvm::SMLoc loc,
2313                                          ParserContext context);
2314   LogicalResult parseTypeDirective(std::unique_ptr<Element> &element, Token tok,
2315                                    ParserContext context);
2316   LogicalResult parseTypeDirectiveOperand(std::unique_ptr<Element> &element,
2317                                           bool isRefChild = false);
2318 
2319   //===--------------------------------------------------------------------===//
2320   // Lexer Utilities
2321   //===--------------------------------------------------------------------===//
2322 
2323   /// Advance the current lexer onto the next token.
2324   void consumeToken() {
2325     assert(curToken.getKind() != Token::eof &&
2326            curToken.getKind() != Token::error &&
2327            "shouldn't advance past EOF or errors");
2328     curToken = lexer.lexToken();
2329   }
2330   LogicalResult parseToken(Token::Kind kind, const Twine &msg) {
2331     if (curToken.getKind() != kind)
2332       return emitError(curToken.getLoc(), msg);
2333     consumeToken();
2334     return ::mlir::success();
2335   }
2336   LogicalResult emitError(llvm::SMLoc loc, const Twine &msg) {
2337     lexer.emitError(loc, msg);
2338     return ::mlir::failure();
2339   }
2340   LogicalResult emitErrorAndNote(llvm::SMLoc loc, const Twine &msg,
2341                                  const Twine &note) {
2342     lexer.emitErrorAndNote(loc, msg, note);
2343     return ::mlir::failure();
2344   }
2345 
2346   //===--------------------------------------------------------------------===//
2347   // Fields
2348   //===--------------------------------------------------------------------===//
2349 
2350   FormatLexer lexer;
2351   Token curToken;
2352   OperationFormat &fmt;
2353   Operator &op;
2354 
2355   // The following are various bits of format state used for verification
2356   // during parsing.
2357   bool hasAttrDict = false;
2358   bool hasAllRegions = false, hasAllSuccessors = false;
2359   llvm::SmallBitVector seenOperandTypes, seenResultTypes;
2360   llvm::SmallSetVector<const NamedAttribute *, 8> seenAttrs;
2361   llvm::DenseSet<const NamedTypeConstraint *> seenOperands;
2362   llvm::DenseSet<const NamedRegion *> seenRegions;
2363   llvm::DenseSet<const NamedSuccessor *> seenSuccessors;
2364 };
2365 } // end anonymous namespace
2366 
2367 LogicalResult FormatParser::parse() {
2368   llvm::SMLoc loc = curToken.getLoc();
2369 
2370   // Parse each of the format elements into the main format.
2371   while (curToken.getKind() != Token::eof) {
2372     std::unique_ptr<Element> element;
2373     if (failed(parseElement(element, TopLevelContext)))
2374       return ::mlir::failure();
2375     fmt.elements.push_back(std::move(element));
2376   }
2377 
2378   // Check that the attribute dictionary is in the format.
2379   if (!hasAttrDict)
2380     return emitError(loc, "'attr-dict' directive not found in "
2381                           "custom assembly format");
2382 
2383   // Check for any type traits that we can use for inferring types.
2384   llvm::StringMap<TypeResolutionInstance> variableTyResolver;
2385   for (const OpTrait &trait : op.getTraits()) {
2386     const llvm::Record &def = trait.getDef();
2387     if (def.isSubClassOf("AllTypesMatch")) {
2388       handleAllTypesMatchConstraint(def.getValueAsListOfStrings("values"),
2389                                     variableTyResolver);
2390     } else if (def.getName() == "SameTypeOperands") {
2391       handleSameTypesConstraint(variableTyResolver, /*includeResults=*/false);
2392     } else if (def.getName() == "SameOperandsAndResultType") {
2393       handleSameTypesConstraint(variableTyResolver, /*includeResults=*/true);
2394     } else if (def.isSubClassOf("TypesMatchWith")) {
2395       handleTypesMatchConstraint(variableTyResolver, def);
2396     }
2397   }
2398 
2399   // Verify the state of the various operation components.
2400   if (failed(verifyAttributes(loc)) ||
2401       failed(verifyResults(loc, variableTyResolver)) ||
2402       failed(verifyOperands(loc, variableTyResolver)) ||
2403       failed(verifyRegions(loc)) || failed(verifySuccessors(loc)))
2404     return ::mlir::failure();
2405 
2406   // Collect the set of used attributes in the format.
2407   fmt.usedAttributes = seenAttrs.takeVector();
2408   return ::mlir::success();
2409 }
2410 
2411 LogicalResult FormatParser::verifyAttributes(llvm::SMLoc loc) {
2412   // Check that there are no `:` literals after an attribute without a constant
2413   // type. The attribute grammar contains an optional trailing colon type, which
2414   // can lead to unexpected and generally unintended behavior. Given that, it is
2415   // better to just error out here instead.
2416   using ElementsIterT = llvm::pointee_iterator<
2417       std::vector<std::unique_ptr<Element>>::const_iterator>;
2418   SmallVector<std::pair<ElementsIterT, ElementsIterT>, 1> iteratorStack;
2419   iteratorStack.emplace_back(fmt.elements.begin(), fmt.elements.end());
2420   while (!iteratorStack.empty())
2421     if (failed(verifyAttributes(loc, iteratorStack)))
2422       return ::mlir::failure();
2423   return ::mlir::success();
2424 }
2425 /// Verify the attribute elements at the back of the given stack of iterators.
2426 LogicalResult FormatParser::verifyAttributes(
2427     llvm::SMLoc loc,
2428     SmallVectorImpl<std::pair<ElementsIterT, ElementsIterT>> &iteratorStack) {
2429   auto &stackIt = iteratorStack.back();
2430   ElementsIterT &it = stackIt.first, e = stackIt.second;
2431   while (it != e) {
2432     Element *element = &*(it++);
2433 
2434     // Traverse into optional groups.
2435     if (auto *optional = dyn_cast<OptionalElement>(element)) {
2436       auto thenElements = optional->getThenElements();
2437       iteratorStack.emplace_back(thenElements.begin(), thenElements.end());
2438 
2439       auto elseElements = optional->getElseElements();
2440       iteratorStack.emplace_back(elseElements.begin(), elseElements.end());
2441       return ::mlir::success();
2442     }
2443 
2444     // We are checking for an attribute element followed by a `:`, so there is
2445     // no need to check the end.
2446     if (it == e && iteratorStack.size() == 1)
2447       break;
2448 
2449     // Check for an attribute with a constant type builder, followed by a `:`.
2450     auto *prevAttr = dyn_cast<AttributeVariable>(element);
2451     if (!prevAttr || prevAttr->getTypeBuilder())
2452       continue;
2453 
2454     // Check the next iterator within the stack for literal elements.
2455     for (auto &nextItPair : iteratorStack) {
2456       ElementsIterT nextIt = nextItPair.first, nextE = nextItPair.second;
2457       for (; nextIt != nextE; ++nextIt) {
2458         // Skip any trailing whitespace, attribute dictionaries, or optional
2459         // groups.
2460         if (isa<WhitespaceElement>(*nextIt) ||
2461             isa<AttrDictDirective>(*nextIt) || isa<OptionalElement>(*nextIt))
2462           continue;
2463 
2464         // We are only interested in `:` literals.
2465         auto *literal = dyn_cast<LiteralElement>(&*nextIt);
2466         if (!literal || literal->getLiteral() != ":")
2467           break;
2468 
2469         // TODO: Use the location of the literal element itself.
2470         return emitError(
2471             loc, llvm::formatv("format ambiguity caused by `:` literal found "
2472                                "after attribute `{0}` which does not have "
2473                                "a buildable type",
2474                                prevAttr->getVar()->name));
2475       }
2476     }
2477   }
2478   iteratorStack.pop_back();
2479   return ::mlir::success();
2480 }
2481 
2482 LogicalResult FormatParser::verifyOperands(
2483     llvm::SMLoc loc,
2484     llvm::StringMap<TypeResolutionInstance> &variableTyResolver) {
2485   // Check that all of the operands are within the format, and their types can
2486   // be inferred.
2487   auto &buildableTypes = fmt.buildableTypes;
2488   for (unsigned i = 0, e = op.getNumOperands(); i != e; ++i) {
2489     NamedTypeConstraint &operand = op.getOperand(i);
2490 
2491     // Check that the operand itself is in the format.
2492     if (!fmt.allOperands && !seenOperands.count(&operand)) {
2493       return emitErrorAndNote(loc,
2494                               "operand #" + Twine(i) + ", named '" +
2495                                   operand.name + "', not found",
2496                               "suggest adding a '$" + operand.name +
2497                                   "' directive to the custom assembly format");
2498     }
2499 
2500     // Check that the operand type is in the format, or that it can be inferred.
2501     if (fmt.allOperandTypes || seenOperandTypes.test(i))
2502       continue;
2503 
2504     // Check to see if we can infer this type from another variable.
2505     auto varResolverIt = variableTyResolver.find(op.getOperand(i).name);
2506     if (varResolverIt != variableTyResolver.end()) {
2507       TypeResolutionInstance &resolver = varResolverIt->second;
2508       fmt.operandTypes[i].setResolver(resolver.resolver, resolver.transformer);
2509       continue;
2510     }
2511 
2512     // Similarly to results, allow a custom builder for resolving the type if
2513     // we aren't using the 'operands' directive.
2514     Optional<StringRef> builder = operand.constraint.getBuilderCall();
2515     if (!builder || (fmt.allOperands && operand.isVariableLength())) {
2516       return emitErrorAndNote(
2517           loc,
2518           "type of operand #" + Twine(i) + ", named '" + operand.name +
2519               "', is not buildable and a buildable type cannot be inferred",
2520           "suggest adding a type constraint to the operation or adding a "
2521           "'type($" +
2522               operand.name + ")' directive to the " + "custom assembly format");
2523     }
2524     auto it = buildableTypes.insert({*builder, buildableTypes.size()});
2525     fmt.operandTypes[i].setBuilderIdx(it.first->second);
2526   }
2527   return ::mlir::success();
2528 }
2529 
2530 LogicalResult FormatParser::verifyRegions(llvm::SMLoc loc) {
2531   // Check that all of the regions are within the format.
2532   if (hasAllRegions)
2533     return ::mlir::success();
2534 
2535   for (unsigned i = 0, e = op.getNumRegions(); i != e; ++i) {
2536     const NamedRegion &region = op.getRegion(i);
2537     if (!seenRegions.count(&region)) {
2538       return emitErrorAndNote(loc,
2539                               "region #" + Twine(i) + ", named '" +
2540                                   region.name + "', not found",
2541                               "suggest adding a '$" + region.name +
2542                                   "' directive to the custom assembly format");
2543     }
2544   }
2545   return ::mlir::success();
2546 }
2547 
2548 LogicalResult FormatParser::verifyResults(
2549     llvm::SMLoc loc,
2550     llvm::StringMap<TypeResolutionInstance> &variableTyResolver) {
2551   // If we format all of the types together, there is nothing to check.
2552   if (fmt.allResultTypes)
2553     return ::mlir::success();
2554 
2555   // Check that all of the result types can be inferred.
2556   auto &buildableTypes = fmt.buildableTypes;
2557   for (unsigned i = 0, e = op.getNumResults(); i != e; ++i) {
2558     if (seenResultTypes.test(i))
2559       continue;
2560 
2561     // Check to see if we can infer this type from another variable.
2562     auto varResolverIt = variableTyResolver.find(op.getResultName(i));
2563     if (varResolverIt != variableTyResolver.end()) {
2564       TypeResolutionInstance resolver = varResolverIt->second;
2565       fmt.resultTypes[i].setResolver(resolver.resolver, resolver.transformer);
2566       continue;
2567     }
2568 
2569     // If the result is not variable length, allow for the case where the type
2570     // has a builder that we can use.
2571     NamedTypeConstraint &result = op.getResult(i);
2572     Optional<StringRef> builder = result.constraint.getBuilderCall();
2573     if (!builder || result.isVariableLength()) {
2574       return emitErrorAndNote(
2575           loc,
2576           "type of result #" + Twine(i) + ", named '" + result.name +
2577               "', is not buildable and a buildable type cannot be inferred",
2578           "suggest adding a type constraint to the operation or adding a "
2579           "'type($" +
2580               result.name + ")' directive to the " + "custom assembly format");
2581     }
2582     // Note in the format that this result uses the custom builder.
2583     auto it = buildableTypes.insert({*builder, buildableTypes.size()});
2584     fmt.resultTypes[i].setBuilderIdx(it.first->second);
2585   }
2586   return ::mlir::success();
2587 }
2588 
2589 LogicalResult FormatParser::verifySuccessors(llvm::SMLoc loc) {
2590   // Check that all of the successors are within the format.
2591   if (hasAllSuccessors)
2592     return ::mlir::success();
2593 
2594   for (unsigned i = 0, e = op.getNumSuccessors(); i != e; ++i) {
2595     const NamedSuccessor &successor = op.getSuccessor(i);
2596     if (!seenSuccessors.count(&successor)) {
2597       return emitErrorAndNote(loc,
2598                               "successor #" + Twine(i) + ", named '" +
2599                                   successor.name + "', not found",
2600                               "suggest adding a '$" + successor.name +
2601                                   "' directive to the custom assembly format");
2602     }
2603   }
2604   return ::mlir::success();
2605 }
2606 
2607 void FormatParser::handleAllTypesMatchConstraint(
2608     ArrayRef<StringRef> values,
2609     llvm::StringMap<TypeResolutionInstance> &variableTyResolver) {
2610   for (unsigned i = 0, e = values.size(); i != e; ++i) {
2611     // Check to see if this value matches a resolved operand or result type.
2612     ConstArgument arg = findSeenArg(values[i]);
2613     if (!arg)
2614       continue;
2615 
2616     // Mark this value as the type resolver for the other variables.
2617     for (unsigned j = 0; j != i; ++j)
2618       variableTyResolver[values[j]] = {arg, llvm::None};
2619     for (unsigned j = i + 1; j != e; ++j)
2620       variableTyResolver[values[j]] = {arg, llvm::None};
2621   }
2622 }
2623 
2624 void FormatParser::handleSameTypesConstraint(
2625     llvm::StringMap<TypeResolutionInstance> &variableTyResolver,
2626     bool includeResults) {
2627   const NamedTypeConstraint *resolver = nullptr;
2628   int resolvedIt = -1;
2629 
2630   // Check to see if there is an operand or result to use for the resolution.
2631   if ((resolvedIt = seenOperandTypes.find_first()) != -1)
2632     resolver = &op.getOperand(resolvedIt);
2633   else if (includeResults && (resolvedIt = seenResultTypes.find_first()) != -1)
2634     resolver = &op.getResult(resolvedIt);
2635   else
2636     return;
2637 
2638   // Set the resolvers for each operand and result.
2639   for (unsigned i = 0, e = op.getNumOperands(); i != e; ++i)
2640     if (!seenOperandTypes.test(i) && !op.getOperand(i).name.empty())
2641       variableTyResolver[op.getOperand(i).name] = {resolver, llvm::None};
2642   if (includeResults) {
2643     for (unsigned i = 0, e = op.getNumResults(); i != e; ++i)
2644       if (!seenResultTypes.test(i) && !op.getResultName(i).empty())
2645         variableTyResolver[op.getResultName(i)] = {resolver, llvm::None};
2646   }
2647 }
2648 
2649 void FormatParser::handleTypesMatchConstraint(
2650     llvm::StringMap<TypeResolutionInstance> &variableTyResolver,
2651     llvm::Record def) {
2652   StringRef lhsName = def.getValueAsString("lhs");
2653   StringRef rhsName = def.getValueAsString("rhs");
2654   StringRef transformer = def.getValueAsString("transformer");
2655   if (ConstArgument arg = findSeenArg(lhsName))
2656     variableTyResolver[rhsName] = {arg, transformer};
2657 }
2658 
2659 ConstArgument FormatParser::findSeenArg(StringRef name) {
2660   if (const NamedTypeConstraint *arg = findArg(op.getOperands(), name))
2661     return seenOperandTypes.test(arg - op.operand_begin()) ? arg : nullptr;
2662   if (const NamedTypeConstraint *arg = findArg(op.getResults(), name))
2663     return seenResultTypes.test(arg - op.result_begin()) ? arg : nullptr;
2664   if (const NamedAttribute *attr = findArg(op.getAttributes(), name))
2665     return seenAttrs.count(attr) ? attr : nullptr;
2666   return nullptr;
2667 }
2668 
2669 LogicalResult FormatParser::parseElement(std::unique_ptr<Element> &element,
2670                                          ParserContext context) {
2671   // Directives.
2672   if (curToken.isKeyword())
2673     return parseDirective(element, context);
2674   // Literals.
2675   if (curToken.getKind() == Token::literal)
2676     return parseLiteral(element, context);
2677   // Optionals.
2678   if (curToken.getKind() == Token::l_paren)
2679     return parseOptional(element, context);
2680   // Variables.
2681   if (curToken.getKind() == Token::variable)
2682     return parseVariable(element, context);
2683   return emitError(curToken.getLoc(),
2684                    "expected directive, literal, variable, or optional group");
2685 }
2686 
2687 LogicalResult FormatParser::parseVariable(std::unique_ptr<Element> &element,
2688                                           ParserContext context) {
2689   Token varTok = curToken;
2690   consumeToken();
2691 
2692   StringRef name = varTok.getSpelling().drop_front();
2693   llvm::SMLoc loc = varTok.getLoc();
2694 
2695   // Check that the parsed argument is something actually registered on the
2696   // op.
2697   /// Attributes
2698   if (const NamedAttribute *attr = findArg(op.getAttributes(), name)) {
2699     if (context == TypeDirectiveContext)
2700       return emitError(
2701           loc, "attributes cannot be used as children to a `type` directive");
2702     if (context == RefDirectiveContext) {
2703       if (!seenAttrs.count(attr))
2704         return emitError(loc, "attribute '" + name +
2705                                   "' must be bound before it is referenced");
2706     } else if (!seenAttrs.insert(attr)) {
2707       return emitError(loc, "attribute '" + name + "' is already bound");
2708     }
2709 
2710     element = std::make_unique<AttributeVariable>(attr);
2711     return ::mlir::success();
2712   }
2713   /// Operands
2714   if (const NamedTypeConstraint *operand = findArg(op.getOperands(), name)) {
2715     if (context == TopLevelContext || context == CustomDirectiveContext) {
2716       if (fmt.allOperands || !seenOperands.insert(operand).second)
2717         return emitError(loc, "operand '" + name + "' is already bound");
2718     } else if (context == RefDirectiveContext && !seenOperands.count(operand)) {
2719       return emitError(loc, "operand '" + name +
2720                                 "' must be bound before it is referenced");
2721     }
2722     element = std::make_unique<OperandVariable>(operand);
2723     return ::mlir::success();
2724   }
2725   /// Regions
2726   if (const NamedRegion *region = findArg(op.getRegions(), name)) {
2727     if (context == TopLevelContext || context == CustomDirectiveContext) {
2728       if (hasAllRegions || !seenRegions.insert(region).second)
2729         return emitError(loc, "region '" + name + "' is already bound");
2730     } else if (context == RefDirectiveContext && !seenRegions.count(region)) {
2731       return emitError(loc, "region '" + name +
2732                                 "' must be bound before it is referenced");
2733     } else {
2734       return emitError(loc, "regions can only be used at the top level");
2735     }
2736     element = std::make_unique<RegionVariable>(region);
2737     return ::mlir::success();
2738   }
2739   /// Results.
2740   if (const auto *result = findArg(op.getResults(), name)) {
2741     if (context != TypeDirectiveContext)
2742       return emitError(loc, "result variables can can only be used as a child "
2743                             "to a 'type' directive");
2744     element = std::make_unique<ResultVariable>(result);
2745     return ::mlir::success();
2746   }
2747   /// Successors.
2748   if (const auto *successor = findArg(op.getSuccessors(), name)) {
2749     if (context == TopLevelContext || context == CustomDirectiveContext) {
2750       if (hasAllSuccessors || !seenSuccessors.insert(successor).second)
2751         return emitError(loc, "successor '" + name + "' is already bound");
2752     } else if (context == RefDirectiveContext &&
2753                !seenSuccessors.count(successor)) {
2754       return emitError(loc, "successor '" + name +
2755                                 "' must be bound before it is referenced");
2756     } else {
2757       return emitError(loc, "successors can only be used at the top level");
2758     }
2759 
2760     element = std::make_unique<SuccessorVariable>(successor);
2761     return ::mlir::success();
2762   }
2763   return emitError(loc, "expected variable to refer to an argument, region, "
2764                         "result, or successor");
2765 }
2766 
2767 LogicalResult FormatParser::parseDirective(std::unique_ptr<Element> &element,
2768                                            ParserContext context) {
2769   Token dirTok = curToken;
2770   consumeToken();
2771 
2772   switch (dirTok.getKind()) {
2773   case Token::kw_attr_dict:
2774     return parseAttrDictDirective(element, dirTok.getLoc(), context,
2775                                   /*withKeyword=*/false);
2776   case Token::kw_attr_dict_w_keyword:
2777     return parseAttrDictDirective(element, dirTok.getLoc(), context,
2778                                   /*withKeyword=*/true);
2779   case Token::kw_custom:
2780     return parseCustomDirective(element, dirTok.getLoc(), context);
2781   case Token::kw_functional_type:
2782     return parseFunctionalTypeDirective(element, dirTok, context);
2783   case Token::kw_operands:
2784     return parseOperandsDirective(element, dirTok.getLoc(), context);
2785   case Token::kw_regions:
2786     return parseRegionsDirective(element, dirTok.getLoc(), context);
2787   case Token::kw_results:
2788     return parseResultsDirective(element, dirTok.getLoc(), context);
2789   case Token::kw_successors:
2790     return parseSuccessorsDirective(element, dirTok.getLoc(), context);
2791   case Token::kw_ref:
2792     return parseReferenceDirective(element, dirTok.getLoc(), context);
2793   case Token::kw_type:
2794     return parseTypeDirective(element, dirTok, context);
2795 
2796   default:
2797     llvm_unreachable("unknown directive token");
2798   }
2799 }
2800 
2801 LogicalResult FormatParser::parseLiteral(std::unique_ptr<Element> &element,
2802                                          ParserContext context) {
2803   Token literalTok = curToken;
2804   if (context != TopLevelContext) {
2805     return emitError(
2806         literalTok.getLoc(),
2807         "literals may only be used in a top-level section of the format");
2808   }
2809   consumeToken();
2810 
2811   StringRef value = literalTok.getSpelling().drop_front().drop_back();
2812 
2813   // The parsed literal is a space element (`` or ` `).
2814   if (value.empty() || (value.size() == 1 && value.front() == ' ')) {
2815     element = std::make_unique<SpaceElement>(!value.empty());
2816     return ::mlir::success();
2817   }
2818   // The parsed literal is a newline element.
2819   if (value == "\\n") {
2820     element = std::make_unique<NewlineElement>();
2821     return ::mlir::success();
2822   }
2823 
2824   // Check that the parsed literal is valid.
2825   if (!LiteralElement::isValidLiteral(value))
2826     return emitError(literalTok.getLoc(), "expected valid literal");
2827 
2828   element = std::make_unique<LiteralElement>(value);
2829   return ::mlir::success();
2830 }
2831 
2832 LogicalResult FormatParser::parseOptional(std::unique_ptr<Element> &element,
2833                                           ParserContext context) {
2834   llvm::SMLoc curLoc = curToken.getLoc();
2835   if (context != TopLevelContext)
2836     return emitError(curLoc, "optional groups can only be used as top-level "
2837                              "elements");
2838   consumeToken();
2839 
2840   // Parse the child elements for this optional group.
2841   std::vector<std::unique_ptr<Element>> thenElements, elseElements;
2842   Optional<unsigned> anchorIdx;
2843   do {
2844     if (failed(parseOptionalChildElement(thenElements, anchorIdx)))
2845       return ::mlir::failure();
2846   } while (curToken.getKind() != Token::r_paren);
2847   consumeToken();
2848 
2849   // Parse the `else` elements of this optional group.
2850   if (curToken.getKind() == Token::colon) {
2851     consumeToken();
2852     if (failed(parseToken(Token::l_paren, "expected '(' to start else branch "
2853                                           "of optional group")))
2854       return failure();
2855     do {
2856       llvm::SMLoc childLoc = curToken.getLoc();
2857       elseElements.push_back({});
2858       if (failed(parseElement(elseElements.back(), TopLevelContext)) ||
2859           failed(verifyOptionalChildElement(elseElements.back().get(), childLoc,
2860                                             /*isAnchor=*/false)))
2861         return failure();
2862     } while (curToken.getKind() != Token::r_paren);
2863     consumeToken();
2864   }
2865 
2866   if (failed(parseToken(Token::question, "expected '?' after optional group")))
2867     return ::mlir::failure();
2868 
2869   // The optional group is required to have an anchor.
2870   if (!anchorIdx)
2871     return emitError(curLoc, "optional group specified no anchor element");
2872 
2873   // The first parsable element of the group must be able to be parsed in an
2874   // optional fashion.
2875   auto parseBegin = llvm::find_if_not(thenElements, [](auto &element) {
2876     return isa<WhitespaceElement>(element.get());
2877   });
2878   Element *firstElement = parseBegin->get();
2879   if (!isa<AttributeVariable>(firstElement) &&
2880       !isa<LiteralElement>(firstElement) &&
2881       !isa<OperandVariable>(firstElement) && !isa<RegionVariable>(firstElement))
2882     return emitError(curLoc,
2883                      "first parsable element of an operand group must be "
2884                      "an attribute, literal, operand, or region");
2885 
2886   auto parseStart = parseBegin - thenElements.begin();
2887   element = std::make_unique<OptionalElement>(
2888       std::move(thenElements), std::move(elseElements), *anchorIdx, parseStart);
2889   return ::mlir::success();
2890 }
2891 
2892 LogicalResult FormatParser::parseOptionalChildElement(
2893     std::vector<std::unique_ptr<Element>> &childElements,
2894     Optional<unsigned> &anchorIdx) {
2895   llvm::SMLoc childLoc = curToken.getLoc();
2896   childElements.push_back({});
2897   if (failed(parseElement(childElements.back(), TopLevelContext)))
2898     return ::mlir::failure();
2899 
2900   // Check to see if this element is the anchor of the optional group.
2901   bool isAnchor = curToken.getKind() == Token::caret;
2902   if (isAnchor) {
2903     if (anchorIdx)
2904       return emitError(childLoc, "only one element can be marked as the anchor "
2905                                  "of an optional group");
2906     anchorIdx = childElements.size() - 1;
2907     consumeToken();
2908   }
2909 
2910   return verifyOptionalChildElement(childElements.back().get(), childLoc,
2911                                     isAnchor);
2912 }
2913 
2914 LogicalResult FormatParser::verifyOptionalChildElement(Element *element,
2915                                                        llvm::SMLoc childLoc,
2916                                                        bool isAnchor) {
2917   return TypeSwitch<Element *, LogicalResult>(element)
2918       // All attributes can be within the optional group, but only optional
2919       // attributes can be the anchor.
2920       .Case([&](AttributeVariable *attrEle) {
2921         if (isAnchor && !attrEle->getVar()->attr.isOptional())
2922           return emitError(childLoc, "only optional attributes can be used to "
2923                                      "anchor an optional group");
2924         return ::mlir::success();
2925       })
2926       // Only optional-like(i.e. variadic) operands can be within an optional
2927       // group.
2928       .Case([&](OperandVariable *ele) {
2929         if (!ele->getVar()->isVariableLength())
2930           return emitError(childLoc, "only variable length operands can be "
2931                                      "used within an optional group");
2932         return ::mlir::success();
2933       })
2934       // Only optional-like(i.e. variadic) results can be within an optional
2935       // group.
2936       .Case([&](ResultVariable *ele) {
2937         if (!ele->getVar()->isVariableLength())
2938           return emitError(childLoc, "only variable length results can be "
2939                                      "used within an optional group");
2940         return ::mlir::success();
2941       })
2942       .Case([&](RegionVariable *) {
2943         // TODO: When ODS has proper support for marking "optional" regions, add
2944         // a check here.
2945         return ::mlir::success();
2946       })
2947       .Case([&](TypeDirective *ele) {
2948         return verifyOptionalChildElement(ele->getOperand(), childLoc,
2949                                           /*isAnchor=*/false);
2950       })
2951       .Case([&](FunctionalTypeDirective *ele) {
2952         if (failed(verifyOptionalChildElement(ele->getInputs(), childLoc,
2953                                               /*isAnchor=*/false)))
2954           return failure();
2955         return verifyOptionalChildElement(ele->getResults(), childLoc,
2956                                           /*isAnchor=*/false);
2957       })
2958       // Literals, whitespace, and custom directives may be used, but they can't
2959       // anchor the group.
2960       .Case<LiteralElement, WhitespaceElement, CustomDirective,
2961             FunctionalTypeDirective, OptionalElement>([&](Element *) {
2962         if (isAnchor)
2963           return emitError(childLoc, "only variables and types can be used "
2964                                      "to anchor an optional group");
2965         return ::mlir::success();
2966       })
2967       .Default([&](Element *) {
2968         return emitError(childLoc, "only literals, types, and variables can be "
2969                                    "used within an optional group");
2970       });
2971 }
2972 
2973 LogicalResult
2974 FormatParser::parseAttrDictDirective(std::unique_ptr<Element> &element,
2975                                      llvm::SMLoc loc, ParserContext context,
2976                                      bool withKeyword) {
2977   if (context == TypeDirectiveContext)
2978     return emitError(loc, "'attr-dict' directive can only be used as a "
2979                           "top-level directive");
2980 
2981   if (context == RefDirectiveContext) {
2982     if (!hasAttrDict)
2983       return emitError(loc, "'ref' of 'attr-dict' is not bound by a prior "
2984                             "'attr-dict' directive");
2985 
2986     // Otherwise, this is a top-level context.
2987   } else {
2988     if (hasAttrDict)
2989       return emitError(loc, "'attr-dict' directive has already been seen");
2990     hasAttrDict = true;
2991   }
2992 
2993   element = std::make_unique<AttrDictDirective>(withKeyword);
2994   return ::mlir::success();
2995 }
2996 
2997 LogicalResult
2998 FormatParser::parseCustomDirective(std::unique_ptr<Element> &element,
2999                                    llvm::SMLoc loc, ParserContext context) {
3000   llvm::SMLoc curLoc = curToken.getLoc();
3001   if (context != TopLevelContext)
3002     return emitError(loc, "'custom' is only valid as a top-level directive");
3003 
3004   // Parse the custom directive name.
3005   if (failed(
3006           parseToken(Token::less, "expected '<' before custom directive name")))
3007     return ::mlir::failure();
3008 
3009   Token nameTok = curToken;
3010   if (failed(parseToken(Token::identifier,
3011                         "expected custom directive name identifier")) ||
3012       failed(parseToken(Token::greater,
3013                         "expected '>' after custom directive name")) ||
3014       failed(parseToken(Token::l_paren,
3015                         "expected '(' before custom directive parameters")))
3016     return ::mlir::failure();
3017 
3018   // Parse the child elements for this optional group.=
3019   std::vector<std::unique_ptr<Element>> elements;
3020   do {
3021     if (failed(parseCustomDirectiveParameter(elements)))
3022       return ::mlir::failure();
3023     if (curToken.getKind() != Token::comma)
3024       break;
3025     consumeToken();
3026   } while (true);
3027 
3028   if (failed(parseToken(Token::r_paren,
3029                         "expected ')' after custom directive parameters")))
3030     return ::mlir::failure();
3031 
3032   // After parsing all of the elements, ensure that all type directives refer
3033   // only to variables.
3034   for (auto &ele : elements) {
3035     if (auto *typeEle = dyn_cast<TypeDirective>(ele.get())) {
3036       if (!isa<OperandVariable, ResultVariable>(typeEle->getOperand())) {
3037         return emitError(curLoc, "type directives within a custom directive "
3038                                  "may only refer to variables");
3039       }
3040     }
3041   }
3042 
3043   element = std::make_unique<CustomDirective>(nameTok.getSpelling(),
3044                                               std::move(elements));
3045   return ::mlir::success();
3046 }
3047 
3048 LogicalResult FormatParser::parseCustomDirectiveParameter(
3049     std::vector<std::unique_ptr<Element>> &parameters) {
3050   llvm::SMLoc childLoc = curToken.getLoc();
3051   parameters.push_back({});
3052   if (failed(parseElement(parameters.back(), CustomDirectiveContext)))
3053     return ::mlir::failure();
3054 
3055   // Verify that the element can be placed within a custom directive.
3056   if (!isa<RefDirective, TypeDirective, AttrDictDirective, AttributeVariable,
3057            OperandVariable, RegionVariable, SuccessorVariable>(
3058           parameters.back().get())) {
3059     return emitError(childLoc, "only variables and types may be used as "
3060                                "parameters to a custom directive");
3061   }
3062   return ::mlir::success();
3063 }
3064 
3065 LogicalResult
3066 FormatParser::parseFunctionalTypeDirective(std::unique_ptr<Element> &element,
3067                                            Token tok, ParserContext context) {
3068   llvm::SMLoc loc = tok.getLoc();
3069   if (context != TopLevelContext)
3070     return emitError(
3071         loc, "'functional-type' is only valid as a top-level directive");
3072 
3073   // Parse the main operand.
3074   std::unique_ptr<Element> inputs, results;
3075   if (failed(parseToken(Token::l_paren, "expected '(' before argument list")) ||
3076       failed(parseTypeDirectiveOperand(inputs)) ||
3077       failed(parseToken(Token::comma, "expected ',' after inputs argument")) ||
3078       failed(parseTypeDirectiveOperand(results)) ||
3079       failed(parseToken(Token::r_paren, "expected ')' after argument list")))
3080     return ::mlir::failure();
3081   element = std::make_unique<FunctionalTypeDirective>(std::move(inputs),
3082                                                       std::move(results));
3083   return ::mlir::success();
3084 }
3085 
3086 LogicalResult
3087 FormatParser::parseOperandsDirective(std::unique_ptr<Element> &element,
3088                                      llvm::SMLoc loc, ParserContext context) {
3089   if (context == RefDirectiveContext) {
3090     if (!fmt.allOperands)
3091       return emitError(loc, "'ref' of 'operands' is not bound by a prior "
3092                             "'operands' directive");
3093 
3094   } else if (context == TopLevelContext || context == CustomDirectiveContext) {
3095     if (fmt.allOperands || !seenOperands.empty())
3096       return emitError(loc, "'operands' directive creates overlap in format");
3097     fmt.allOperands = true;
3098   }
3099   element = std::make_unique<OperandsDirective>();
3100   return ::mlir::success();
3101 }
3102 
3103 LogicalResult
3104 FormatParser::parseReferenceDirective(std::unique_ptr<Element> &element,
3105                                       llvm::SMLoc loc, ParserContext context) {
3106   if (context != CustomDirectiveContext)
3107     return emitError(loc, "'ref' is only valid within a `custom` directive");
3108 
3109   std::unique_ptr<Element> operand;
3110   if (failed(parseToken(Token::l_paren, "expected '(' before argument list")) ||
3111       failed(parseElement(operand, RefDirectiveContext)) ||
3112       failed(parseToken(Token::r_paren, "expected ')' after argument list")))
3113     return ::mlir::failure();
3114 
3115   element = std::make_unique<RefDirective>(std::move(operand));
3116   return ::mlir::success();
3117 }
3118 
3119 LogicalResult
3120 FormatParser::parseRegionsDirective(std::unique_ptr<Element> &element,
3121                                     llvm::SMLoc loc, ParserContext context) {
3122   if (context == TypeDirectiveContext)
3123     return emitError(loc, "'regions' is only valid as a top-level directive");
3124   if (context == RefDirectiveContext) {
3125     if (!hasAllRegions)
3126       return emitError(loc, "'ref' of 'regions' is not bound by a prior "
3127                             "'regions' directive");
3128 
3129     // Otherwise, this is a TopLevel directive.
3130   } else {
3131     if (hasAllRegions || !seenRegions.empty())
3132       return emitError(loc, "'regions' directive creates overlap in format");
3133     hasAllRegions = true;
3134   }
3135   element = std::make_unique<RegionsDirective>();
3136   return ::mlir::success();
3137 }
3138 
3139 LogicalResult
3140 FormatParser::parseResultsDirective(std::unique_ptr<Element> &element,
3141                                     llvm::SMLoc loc, ParserContext context) {
3142   if (context != TypeDirectiveContext)
3143     return emitError(loc, "'results' directive can can only be used as a child "
3144                           "to a 'type' directive");
3145   element = std::make_unique<ResultsDirective>();
3146   return ::mlir::success();
3147 }
3148 
3149 LogicalResult
3150 FormatParser::parseSuccessorsDirective(std::unique_ptr<Element> &element,
3151                                        llvm::SMLoc loc, ParserContext context) {
3152   if (context == TypeDirectiveContext)
3153     return emitError(loc,
3154                      "'successors' is only valid as a top-level directive");
3155   if (context == RefDirectiveContext) {
3156     if (!hasAllSuccessors)
3157       return emitError(loc, "'ref' of 'successors' is not bound by a prior "
3158                             "'successors' directive");
3159 
3160     // Otherwise, this is a TopLevel directive.
3161   } else {
3162     if (hasAllSuccessors || !seenSuccessors.empty())
3163       return emitError(loc, "'successors' directive creates overlap in format");
3164     hasAllSuccessors = true;
3165   }
3166   element = std::make_unique<SuccessorsDirective>();
3167   return ::mlir::success();
3168 }
3169 
3170 LogicalResult
3171 FormatParser::parseTypeDirective(std::unique_ptr<Element> &element, Token tok,
3172                                  ParserContext context) {
3173   llvm::SMLoc loc = tok.getLoc();
3174   if (context == TypeDirectiveContext)
3175     return emitError(loc, "'type' cannot be used as a child of another `type`");
3176 
3177   bool isRefChild = context == RefDirectiveContext;
3178   std::unique_ptr<Element> operand;
3179   if (failed(parseToken(Token::l_paren, "expected '(' before argument list")) ||
3180       failed(parseTypeDirectiveOperand(operand, isRefChild)) ||
3181       failed(parseToken(Token::r_paren, "expected ')' after argument list")))
3182     return ::mlir::failure();
3183 
3184   element = std::make_unique<TypeDirective>(std::move(operand));
3185   return ::mlir::success();
3186 }
3187 
3188 LogicalResult
3189 FormatParser::parseTypeDirectiveOperand(std::unique_ptr<Element> &element,
3190                                         bool isRefChild) {
3191   llvm::SMLoc loc = curToken.getLoc();
3192   if (failed(parseElement(element, TypeDirectiveContext)))
3193     return ::mlir::failure();
3194   if (isa<LiteralElement>(element.get()))
3195     return emitError(
3196         loc, "'type' directive operand expects variable or directive operand");
3197 
3198   if (auto *var = dyn_cast<OperandVariable>(element.get())) {
3199     unsigned opIdx = var->getVar() - op.operand_begin();
3200     if (!isRefChild && (fmt.allOperandTypes || seenOperandTypes.test(opIdx)))
3201       return emitError(loc, "'type' of '" + var->getVar()->name +
3202                                 "' is already bound");
3203     if (isRefChild && !(fmt.allOperandTypes || seenOperandTypes.test(opIdx)))
3204       return emitError(loc, "'ref' of 'type($" + var->getVar()->name +
3205                                 ")' is not bound by a prior 'type' directive");
3206     seenOperandTypes.set(opIdx);
3207   } else if (auto *var = dyn_cast<ResultVariable>(element.get())) {
3208     unsigned resIdx = var->getVar() - op.result_begin();
3209     if (!isRefChild && (fmt.allResultTypes || seenResultTypes.test(resIdx)))
3210       return emitError(loc, "'type' of '" + var->getVar()->name +
3211                                 "' is already bound");
3212     if (isRefChild && !(fmt.allResultTypes || seenResultTypes.test(resIdx)))
3213       return emitError(loc, "'ref' of 'type($" + var->getVar()->name +
3214                                 ")' is not bound by a prior 'type' directive");
3215     seenResultTypes.set(resIdx);
3216   } else if (isa<OperandsDirective>(&*element)) {
3217     if (!isRefChild && (fmt.allOperandTypes || seenOperandTypes.any()))
3218       return emitError(loc, "'operands' 'type' is already bound");
3219     if (isRefChild && !fmt.allOperandTypes)
3220       return emitError(loc, "'ref' of 'type(operands)' is not bound by a prior "
3221                             "'type' directive");
3222     fmt.allOperandTypes = true;
3223   } else if (isa<ResultsDirective>(&*element)) {
3224     if (!isRefChild && (fmt.allResultTypes || seenResultTypes.any()))
3225       return emitError(loc, "'results' 'type' is already bound");
3226     if (isRefChild && !fmt.allResultTypes)
3227       return emitError(loc, "'ref' of 'type(results)' is not bound by a prior "
3228                             "'type' directive");
3229     fmt.allResultTypes = true;
3230   } else {
3231     return emitError(loc, "invalid argument to 'type' directive");
3232   }
3233   return ::mlir::success();
3234 }
3235 
3236 //===----------------------------------------------------------------------===//
3237 // Interface
3238 //===----------------------------------------------------------------------===//
3239 
3240 void mlir::tblgen::generateOpFormat(const Operator &constOp, OpClass &opClass) {
3241   // TODO: Operator doesn't expose all necessary functionality via
3242   // the const interface.
3243   Operator &op = const_cast<Operator &>(constOp);
3244   if (!op.hasAssemblyFormat())
3245     return;
3246 
3247   // Parse the format description.
3248   llvm::SourceMgr mgr;
3249   mgr.AddNewSourceBuffer(
3250       llvm::MemoryBuffer::getMemBuffer(op.getAssemblyFormat()), llvm::SMLoc());
3251   OperationFormat format(op);
3252   if (failed(FormatParser(mgr, format, op).parse())) {
3253     // Exit the process if format errors are treated as fatal.
3254     if (formatErrorIsFatal) {
3255       // Invoke the interrupt handlers to run the file cleanup handlers.
3256       llvm::sys::RunInterruptHandlers();
3257       std::exit(1);
3258     }
3259     return;
3260   }
3261 
3262   // Generate the printer and parser based on the parsed format.
3263   format.genParser(op, opClass);
3264   format.genPrinter(op, opClass);
3265 }
3266