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