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