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