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