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