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