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