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