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