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