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/ADT/TypeSwitch.h" 11 #include "mlir/Support/LogicalResult.h" 12 #include "mlir/Support/STLExtras.h" 13 #include "mlir/TableGen/Format.h" 14 #include "mlir/TableGen/GenInfo.h" 15 #include "mlir/TableGen/OpClass.h" 16 #include "mlir/TableGen/OpInterfaces.h" 17 #include "mlir/TableGen/OpTrait.h" 18 #include "mlir/TableGen/Operator.h" 19 #include "llvm/ADT/MapVector.h" 20 #include "llvm/ADT/Sequence.h" 21 #include "llvm/ADT/SmallBitVector.h" 22 #include "llvm/ADT/StringExtras.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 //===----------------------------------------------------------------------===// 39 // Element 40 //===----------------------------------------------------------------------===// 41 42 namespace { 43 /// This class represents a single format element. 44 class Element { 45 public: 46 enum class Kind { 47 /// This element is a directive. 48 AttrDictDirective, 49 FunctionalTypeDirective, 50 OperandsDirective, 51 ResultsDirective, 52 SuccessorsDirective, 53 TypeDirective, 54 55 /// This element is a literal. 56 Literal, 57 58 /// This element is an variable value. 59 AttributeVariable, 60 OperandVariable, 61 ResultVariable, 62 SuccessorVariable, 63 64 /// This element is an optional element. 65 Optional, 66 }; 67 Element(Kind kind) : kind(kind) {} 68 virtual ~Element() = default; 69 70 /// Return the kind of this element. 71 Kind getKind() const { return kind; } 72 73 private: 74 /// The kind of this element. 75 Kind kind; 76 }; 77 } // namespace 78 79 //===----------------------------------------------------------------------===// 80 // VariableElement 81 82 namespace { 83 /// This class represents an instance of an variable element. A variable refers 84 /// to something registered on the operation itself, e.g. an argument, result, 85 /// etc. 86 template <typename VarT, Element::Kind kindVal> 87 class VariableElement : public Element { 88 public: 89 VariableElement(const VarT *var) : Element(kindVal), var(var) {} 90 static bool classof(const Element *element) { 91 return element->getKind() == kindVal; 92 } 93 const VarT *getVar() { return var; } 94 95 protected: 96 const VarT *var; 97 }; 98 99 /// This class represents a variable that refers to an attribute argument. 100 struct AttributeVariable 101 : public VariableElement<NamedAttribute, Element::Kind::AttributeVariable> { 102 using VariableElement<NamedAttribute, 103 Element::Kind::AttributeVariable>::VariableElement; 104 105 /// Return the constant builder call for the type of this attribute, or None 106 /// if it doesn't have one. 107 Optional<StringRef> getTypeBuilder() const { 108 Optional<Type> attrType = var->attr.getValueType(); 109 return attrType ? attrType->getBuilderCall() : llvm::None; 110 } 111 }; 112 113 /// This class represents a variable that refers to an operand argument. 114 using OperandVariable = 115 VariableElement<NamedTypeConstraint, Element::Kind::OperandVariable>; 116 117 /// This class represents a variable that refers to a result. 118 using ResultVariable = 119 VariableElement<NamedTypeConstraint, Element::Kind::ResultVariable>; 120 121 /// This class represents a variable that refers to a successor. 122 using SuccessorVariable = 123 VariableElement<NamedSuccessor, Element::Kind::SuccessorVariable>; 124 } // end anonymous namespace 125 126 //===----------------------------------------------------------------------===// 127 // DirectiveElement 128 129 namespace { 130 /// This class implements single kind directives. 131 template <Element::Kind type> 132 class DirectiveElement : public Element { 133 public: 134 DirectiveElement() : Element(type){}; 135 static bool classof(const Element *ele) { return ele->getKind() == type; } 136 }; 137 /// This class represents the `operands` directive. This directive represents 138 /// all of the operands of an operation. 139 using OperandsDirective = DirectiveElement<Element::Kind::OperandsDirective>; 140 141 /// This class represents the `results` directive. This directive represents 142 /// all of the results of an operation. 143 using ResultsDirective = DirectiveElement<Element::Kind::ResultsDirective>; 144 145 /// This class represents the `successors` directive. This directive represents 146 /// all of the successors of an operation. 147 using SuccessorsDirective = 148 DirectiveElement<Element::Kind::SuccessorsDirective>; 149 150 /// This class represents the `attr-dict` directive. This directive represents 151 /// the attribute dictionary of the operation. 152 class AttrDictDirective 153 : public DirectiveElement<Element::Kind::AttrDictDirective> { 154 public: 155 explicit AttrDictDirective(bool withKeyword) : withKeyword(withKeyword) {} 156 bool isWithKeyword() const { return withKeyword; } 157 158 private: 159 /// If the dictionary should be printed with the 'attributes' keyword. 160 bool withKeyword; 161 }; 162 163 /// This class represents the `functional-type` directive. This directive takes 164 /// two arguments and formats them, respectively, as the inputs and results of a 165 /// FunctionType. 166 class FunctionalTypeDirective 167 : public DirectiveElement<Element::Kind::FunctionalTypeDirective> { 168 public: 169 FunctionalTypeDirective(std::unique_ptr<Element> inputs, 170 std::unique_ptr<Element> results) 171 : inputs(std::move(inputs)), results(std::move(results)) {} 172 Element *getInputs() const { return inputs.get(); } 173 Element *getResults() const { return results.get(); } 174 175 private: 176 /// The input and result arguments. 177 std::unique_ptr<Element> inputs, results; 178 }; 179 180 /// This class represents the `type` directive. 181 class TypeDirective : public DirectiveElement<Element::Kind::TypeDirective> { 182 public: 183 TypeDirective(std::unique_ptr<Element> arg) : operand(std::move(arg)) {} 184 Element *getOperand() const { return operand.get(); } 185 186 private: 187 /// The operand that is used to format the directive. 188 std::unique_ptr<Element> operand; 189 }; 190 } // end anonymous namespace 191 192 //===----------------------------------------------------------------------===// 193 // LiteralElement 194 195 namespace { 196 /// This class represents an instance of a literal element. 197 class LiteralElement : public Element { 198 public: 199 LiteralElement(StringRef literal) 200 : Element{Kind::Literal}, literal(literal) {} 201 static bool classof(const Element *element) { 202 return element->getKind() == Kind::Literal; 203 } 204 205 /// Return the literal for this element. 206 StringRef getLiteral() const { return literal; } 207 208 /// Returns true if the given string is a valid literal. 209 static bool isValidLiteral(StringRef value); 210 211 private: 212 /// The spelling of the literal for this element. 213 StringRef literal; 214 }; 215 } // end anonymous namespace 216 217 bool LiteralElement::isValidLiteral(StringRef value) { 218 if (value.empty()) 219 return false; 220 char front = value.front(); 221 222 // If there is only one character, this must either be punctuation or a 223 // single character bare identifier. 224 if (value.size() == 1) 225 return isalpha(front) || StringRef("_:,=<>()[]").contains(front); 226 227 // Check the punctuation that are larger than a single character. 228 if (value == "->") 229 return true; 230 231 // Otherwise, this must be an identifier. 232 if (!isalpha(front) && front != '_') 233 return false; 234 return llvm::all_of(value.drop_front(), [](char c) { 235 return isalnum(c) || c == '_' || c == '$' || c == '.'; 236 }); 237 } 238 239 //===----------------------------------------------------------------------===// 240 // OptionalElement 241 242 namespace { 243 /// This class represents a group of elements that are optionally emitted based 244 /// upon an optional variable of the operation. 245 class OptionalElement : public Element { 246 public: 247 OptionalElement(std::vector<std::unique_ptr<Element>> &&elements, 248 unsigned anchor) 249 : Element{Kind::Optional}, elements(std::move(elements)), anchor(anchor) { 250 } 251 static bool classof(const Element *element) { 252 return element->getKind() == Kind::Optional; 253 } 254 255 /// Return the nested elements of this grouping. 256 auto getElements() const { return llvm::make_pointee_range(elements); } 257 258 /// Return the anchor of this optional group. 259 Element *getAnchor() const { return elements[anchor].get(); } 260 261 private: 262 /// The child elements of this optional. 263 std::vector<std::unique_ptr<Element>> elements; 264 /// The index of the element that acts as the anchor for the optional group. 265 unsigned anchor; 266 }; 267 } // end anonymous namespace 268 269 //===----------------------------------------------------------------------===// 270 // OperationFormat 271 //===----------------------------------------------------------------------===// 272 273 namespace { 274 struct OperationFormat { 275 /// This class represents a specific resolver for an operand or result type. 276 class TypeResolution { 277 public: 278 TypeResolution() = default; 279 280 /// Get the index into the buildable types for this type, or None. 281 Optional<int> getBuilderIdx() const { return builderIdx; } 282 void setBuilderIdx(int idx) { builderIdx = idx; } 283 284 /// Get the variable this type is resolved to, or None. 285 const NamedTypeConstraint *getVariable() const { return variable; } 286 Optional<StringRef> getVarTransformer() const { 287 return variableTransformer; 288 } 289 void setVariable(const NamedTypeConstraint *var, 290 Optional<StringRef> transformer) { 291 variable = var; 292 variableTransformer = transformer; 293 } 294 295 private: 296 /// If the type is resolved with a buildable type, this is the index into 297 /// 'buildableTypes' in the parent format. 298 Optional<int> builderIdx; 299 /// If the type is resolved based upon another operand or result, this is 300 /// the variable that this type is resolved to. 301 const NamedTypeConstraint *variable; 302 /// If the type is resolved based upon another operand or result, this is 303 /// a transformer to apply to the variable when resolving. 304 Optional<StringRef> variableTransformer; 305 }; 306 307 OperationFormat(const Operator &op) 308 : allOperands(false), allOperandTypes(false), allResultTypes(false) { 309 operandTypes.resize(op.getNumOperands(), TypeResolution()); 310 resultTypes.resize(op.getNumResults(), TypeResolution()); 311 } 312 313 /// Generate the operation parser from this format. 314 void genParser(Operator &op, OpClass &opClass); 315 /// Generate the c++ to resolve the types of operands and results during 316 /// parsing. 317 void genParserTypeResolution(Operator &op, OpMethodBody &body); 318 /// Generate the c++ to resolve successors during parsing. 319 void genParserSuccessorResolution(Operator &op, OpMethodBody &body); 320 /// Generate the c++ to handling variadic segment size traits. 321 void genParserVariadicSegmentResolution(Operator &op, OpMethodBody &body); 322 323 /// Generate the operation printer from this format. 324 void genPrinter(Operator &op, OpClass &opClass); 325 326 /// The various elements in this format. 327 std::vector<std::unique_ptr<Element>> elements; 328 329 /// A flag indicating if all operand/result types were seen. If the format 330 /// contains these, it can not contain individual type resolvers. 331 bool allOperands, allOperandTypes, allResultTypes; 332 333 /// A map of buildable types to indices. 334 llvm::MapVector<StringRef, int, llvm::StringMap<int>> buildableTypes; 335 336 /// The index of the buildable type, if valid, for every operand and result. 337 std::vector<TypeResolution> operandTypes, resultTypes; 338 }; 339 } // end anonymous namespace 340 341 //===----------------------------------------------------------------------===// 342 // Parser Gen 343 344 /// Returns if we can format the given attribute as an EnumAttr in the parser 345 /// format. 346 static bool canFormatEnumAttr(const NamedAttribute *attr) { 347 const EnumAttr *enumAttr = dyn_cast<EnumAttr>(&attr->attr); 348 if (!enumAttr) 349 return false; 350 351 // The attribute must have a valid underlying type and a constant builder. 352 return !enumAttr->getUnderlyingType().empty() && 353 !enumAttr->getConstBuilderTemplate().empty(); 354 } 355 356 /// The code snippet used to generate a parser call for an attribute. 357 /// 358 /// {0}: The storage type of the attribute. 359 /// {1}: The name of the attribute. 360 /// {2}: The type for the attribute. 361 const char *const attrParserCode = R"( 362 {0} {1}Attr; 363 if (parser.parseAttribute({1}Attr{2}, "{1}", result.attributes)) 364 return failure(); 365 )"; 366 367 /// The code snippet used to generate a parser call for an enum attribute. 368 /// 369 /// {0}: The name of the attribute. 370 /// {1}: The c++ namespace for the enum symbolize functions. 371 /// {2}: The function to symbolize a string of the enum. 372 /// {3}: The constant builder call to create an attribute of the enum type. 373 const char *const enumAttrParserCode = R"( 374 { 375 StringAttr attrVal; 376 SmallVector<NamedAttribute, 1> attrStorage; 377 auto loc = parser.getCurrentLocation(); 378 if (parser.parseAttribute(attrVal, parser.getBuilder().getNoneType(), 379 "{0}", attrStorage)) 380 return failure(); 381 382 auto attrOptional = {1}::{2}(attrVal.getValue()); 383 if (!attrOptional) 384 return parser.emitError(loc, "invalid ") 385 << "{0} attribute specification: " << attrVal; 386 387 result.addAttribute("{0}", {3}); 388 } 389 )"; 390 391 /// The code snippet used to generate a parser call for an operand. 392 /// 393 /// {0}: The name of the operand. 394 const char *const variadicOperandParserCode = R"( 395 if (parser.parseOperandList({0}Operands)) 396 return failure(); 397 )"; 398 const char *const operandParserCode = R"( 399 if (parser.parseOperand({0}RawOperands[0])) 400 return failure(); 401 )"; 402 403 /// The code snippet used to generate a parser call for a type list. 404 /// 405 /// {0}: The name for the type list. 406 const char *const variadicTypeParserCode = R"( 407 if (parser.parseTypeList({0}Types)) 408 return failure(); 409 )"; 410 const char *const typeParserCode = R"( 411 if (parser.parseType({0}RawTypes[0])) 412 return failure(); 413 )"; 414 415 /// The code snippet used to generate a parser call for a functional type. 416 /// 417 /// {0}: The name for the input type list. 418 /// {1}: The name for the result type list. 419 const char *const functionalTypeParserCode = R"( 420 FunctionType {0}__{1}_functionType; 421 if (parser.parseType({0}__{1}_functionType)) 422 return failure(); 423 {0}Types = {0}__{1}_functionType.getInputs(); 424 {1}Types = {0}__{1}_functionType.getResults(); 425 )"; 426 427 /// The code snippet used to generate a parser call for a successor list. 428 /// 429 /// {0}: The name for the successor list. 430 const char *successorListParserCode = R"( 431 SmallVector<Block *, 2> {0}Successors; 432 { 433 Block *succ; 434 auto firstSucc = parser.parseOptionalSuccessor(succ); 435 if (firstSucc.hasValue()) { 436 if (failed(*firstSucc)) 437 return failure(); 438 {0}Successors.emplace_back(succ); 439 440 // Parse any trailing successors. 441 while (succeeded(parser.parseOptionalComma())) { 442 if (parser.parseSuccessor(succ)) 443 return failure(); 444 {0}Successors.emplace_back(succ); 445 } 446 } 447 } 448 )"; 449 450 /// The code snippet used to generate a parser call for a successor. 451 /// 452 /// {0}: The name of the successor. 453 const char *successorParserCode = R"( 454 Block *{0}Successor = nullptr; 455 if (parser.parseSuccessor({0}Successor)) 456 return failure(); 457 )"; 458 459 /// Get the name used for the type list for the given type directive operand. 460 /// 'isVariadic' is set to true if the operand has variadic types. 461 static StringRef getTypeListName(Element *arg, bool &isVariadic) { 462 if (auto *operand = dyn_cast<OperandVariable>(arg)) { 463 isVariadic = operand->getVar()->isVariadic(); 464 return operand->getVar()->name; 465 } 466 if (auto *result = dyn_cast<ResultVariable>(arg)) { 467 isVariadic = result->getVar()->isVariadic(); 468 return result->getVar()->name; 469 } 470 isVariadic = true; 471 if (isa<OperandsDirective>(arg)) 472 return "allOperand"; 473 if (isa<ResultsDirective>(arg)) 474 return "allResult"; 475 llvm_unreachable("unknown 'type' directive argument"); 476 } 477 478 /// Generate the parser for a literal value. 479 static void genLiteralParser(StringRef value, OpMethodBody &body) { 480 // Handle the case of a keyword/identifier. 481 if (value.front() == '_' || isalpha(value.front())) { 482 body << "Keyword(\"" << value << "\")"; 483 return; 484 } 485 body << (StringRef)llvm::StringSwitch<StringRef>(value) 486 .Case("->", "Arrow()") 487 .Case(":", "Colon()") 488 .Case(",", "Comma()") 489 .Case("=", "Equal()") 490 .Case("<", "Less()") 491 .Case(">", "Greater()") 492 .Case("(", "LParen()") 493 .Case(")", "RParen()") 494 .Case("[", "LSquare()") 495 .Case("]", "RSquare()"); 496 } 497 498 /// Generate the storage code required for parsing the given element. 499 static void genElementParserStorage(Element *element, OpMethodBody &body) { 500 if (auto *optional = dyn_cast<OptionalElement>(element)) { 501 for (auto &childElement : optional->getElements()) 502 genElementParserStorage(&childElement, body); 503 } else if (auto *operand = dyn_cast<OperandVariable>(element)) { 504 StringRef name = operand->getVar()->name; 505 if (operand->getVar()->isVariadic()) { 506 body << " SmallVector<OpAsmParser::OperandType, 4> " << name 507 << "Operands;\n"; 508 } else { 509 body << " OpAsmParser::OperandType " << name << "RawOperands[1];\n" 510 << " ArrayRef<OpAsmParser::OperandType> " << name << "Operands(" 511 << name << "RawOperands);"; 512 } 513 body << llvm::formatv( 514 " llvm::SMLoc {0}OperandsLoc = parser.getCurrentLocation();\n" 515 " (void){0}OperandsLoc;\n", 516 name); 517 } else if (auto *dir = dyn_cast<TypeDirective>(element)) { 518 bool variadic = false; 519 StringRef name = getTypeListName(dir->getOperand(), variadic); 520 if (variadic) 521 body << " SmallVector<Type, 1> " << name << "Types;\n"; 522 else 523 body << llvm::formatv(" Type {0}RawTypes[1];\n", name) 524 << llvm::formatv(" ArrayRef<Type> {0}Types({0}RawTypes);\n", name); 525 } else if (auto *dir = dyn_cast<FunctionalTypeDirective>(element)) { 526 bool ignored = false; 527 body << " ArrayRef<Type> " << getTypeListName(dir->getInputs(), ignored) 528 << "Types;\n"; 529 body << " ArrayRef<Type> " << getTypeListName(dir->getResults(), ignored) 530 << "Types;\n"; 531 } 532 } 533 534 /// Generate the parser for a single format element. 535 static void genElementParser(Element *element, OpMethodBody &body, 536 FmtContext &attrTypeCtx) { 537 /// Optional Group. 538 if (auto *optional = dyn_cast<OptionalElement>(element)) { 539 auto elements = optional->getElements(); 540 541 // Generate a special optional parser for the first element to gate the 542 // parsing of the rest of the elements. 543 if (auto *literal = dyn_cast<LiteralElement>(&*elements.begin())) { 544 body << " if (succeeded(parser.parseOptional"; 545 genLiteralParser(literal->getLiteral(), body); 546 body << ")) {\n"; 547 } else if (auto *opVar = dyn_cast<OperandVariable>(&*elements.begin())) { 548 genElementParser(opVar, body, attrTypeCtx); 549 body << " if (!" << opVar->getVar()->name << "Operands.empty()) {\n"; 550 } 551 552 // Generate the rest of the elements normally. 553 for (auto &childElement : llvm::drop_begin(elements, 1)) 554 genElementParser(&childElement, body, attrTypeCtx); 555 body << " }\n"; 556 557 /// Literals. 558 } else if (LiteralElement *literal = dyn_cast<LiteralElement>(element)) { 559 body << " if (parser.parse"; 560 genLiteralParser(literal->getLiteral(), body); 561 body << ")\n return failure();\n"; 562 563 /// Arguments. 564 } else if (auto *attr = dyn_cast<AttributeVariable>(element)) { 565 const NamedAttribute *var = attr->getVar(); 566 567 // Check to see if we can parse this as an enum attribute. 568 if (canFormatEnumAttr(var)) { 569 const EnumAttr &enumAttr = cast<EnumAttr>(var->attr); 570 571 // Generate the code for building an attribute for this enum. 572 std::string attrBuilderStr; 573 { 574 llvm::raw_string_ostream os(attrBuilderStr); 575 os << tgfmt(enumAttr.getConstBuilderTemplate(), &attrTypeCtx, 576 "attrOptional.getValue()"); 577 } 578 579 body << formatv(enumAttrParserCode, var->name, enumAttr.getCppNamespace(), 580 enumAttr.getStringToSymbolFnName(), attrBuilderStr); 581 return; 582 } 583 584 // If this attribute has a buildable type, use that when parsing the 585 // attribute. 586 std::string attrTypeStr; 587 if (Optional<StringRef> typeBuilder = attr->getTypeBuilder()) { 588 llvm::raw_string_ostream os(attrTypeStr); 589 os << ", " << tgfmt(*typeBuilder, &attrTypeCtx); 590 } 591 592 body << formatv(attrParserCode, var->attr.getStorageType(), var->name, 593 attrTypeStr); 594 } else if (auto *operand = dyn_cast<OperandVariable>(element)) { 595 bool isVariadic = operand->getVar()->isVariadic(); 596 body << formatv(isVariadic ? variadicOperandParserCode : operandParserCode, 597 operand->getVar()->name); 598 } else if (auto *successor = dyn_cast<SuccessorVariable>(element)) { 599 bool isVariadic = successor->getVar()->isVariadic(); 600 body << formatv(isVariadic ? successorListParserCode : successorParserCode, 601 successor->getVar()->name); 602 603 /// Directives. 604 } else if (auto *attrDict = dyn_cast<AttrDictDirective>(element)) { 605 body << " if (parser.parseOptionalAttrDict" 606 << (attrDict->isWithKeyword() ? "WithKeyword" : "") 607 << "(result.attributes))\n" 608 << " return failure();\n"; 609 } else if (isa<OperandsDirective>(element)) { 610 body << " llvm::SMLoc allOperandLoc = parser.getCurrentLocation();\n" 611 << " SmallVector<OpAsmParser::OperandType, 4> allOperands;\n" 612 << " if (parser.parseOperandList(allOperands))\n" 613 << " return failure();\n"; 614 } else if (isa<SuccessorsDirective>(element)) { 615 body << llvm::formatv(successorListParserCode, "full"); 616 } else if (auto *dir = dyn_cast<TypeDirective>(element)) { 617 bool isVariadic = false; 618 StringRef listName = getTypeListName(dir->getOperand(), isVariadic); 619 body << formatv(isVariadic ? variadicTypeParserCode : typeParserCode, 620 listName); 621 } else if (auto *dir = dyn_cast<FunctionalTypeDirective>(element)) { 622 bool ignored = false; 623 body << formatv(functionalTypeParserCode, 624 getTypeListName(dir->getInputs(), ignored), 625 getTypeListName(dir->getResults(), ignored)); 626 } else { 627 llvm_unreachable("unknown format element"); 628 } 629 } 630 631 void OperationFormat::genParser(Operator &op, OpClass &opClass) { 632 auto &method = opClass.newMethod( 633 "ParseResult", "parse", "OpAsmParser &parser, OperationState &result", 634 OpMethod::MP_Static); 635 auto &body = method.body(); 636 637 // Generate variables to store the operands and type within the format. This 638 // allows for referencing these variables in the presence of optional 639 // groupings. 640 for (auto &element : elements) 641 genElementParserStorage(&*element, body); 642 643 // A format context used when parsing attributes with buildable types. 644 FmtContext attrTypeCtx; 645 attrTypeCtx.withBuilder("parser.getBuilder()"); 646 647 // Generate parsers for each of the elements. 648 for (auto &element : elements) 649 genElementParser(element.get(), body, attrTypeCtx); 650 651 // Generate the code to resolve the operand/result types and successors now 652 // that they have been parsed. 653 genParserTypeResolution(op, body); 654 genParserSuccessorResolution(op, body); 655 genParserVariadicSegmentResolution(op, body); 656 657 body << " return success();\n"; 658 } 659 660 void OperationFormat::genParserTypeResolution(Operator &op, 661 OpMethodBody &body) { 662 // If any of type resolutions use transformed variables, make sure that the 663 // types of those variables are resolved. 664 SmallPtrSet<const NamedTypeConstraint *, 8> verifiedVariables; 665 FmtContext verifierFCtx; 666 for (TypeResolution &resolver : 667 llvm::concat<TypeResolution>(resultTypes, operandTypes)) { 668 Optional<StringRef> transformer = resolver.getVarTransformer(); 669 if (!transformer) 670 continue; 671 // Ensure that we don't verify the same variables twice. 672 const NamedTypeConstraint *variable = resolver.getVariable(); 673 if (!verifiedVariables.insert(variable).second) 674 continue; 675 676 auto constraint = variable->constraint; 677 body << " for (Type type : " << variable->name << "Types) {\n" 678 << " (void)type;\n" 679 << " if (!(" 680 << tgfmt(constraint.getConditionTemplate(), 681 &verifierFCtx.withSelf("type")) 682 << ")) {\n" 683 << formatv(" return parser.emitError(parser.getNameLoc()) << " 684 "\"'{0}' must be {1}, but got \" << type;\n", 685 variable->name, constraint.getDescription()) 686 << " }\n" 687 << " }\n"; 688 } 689 690 // Initialize the set of buildable types. 691 if (!buildableTypes.empty()) { 692 body << " Builder &builder = parser.getBuilder();\n"; 693 694 FmtContext typeBuilderCtx; 695 typeBuilderCtx.withBuilder("builder"); 696 for (auto &it : buildableTypes) 697 body << " Type odsBuildableType" << it.second << " = " 698 << tgfmt(it.first, &typeBuilderCtx) << ";\n"; 699 } 700 701 // Emit the code necessary for a type resolver. 702 auto emitTypeResolver = [&](TypeResolution &resolver, StringRef curVar) { 703 if (Optional<int> val = resolver.getBuilderIdx()) { 704 body << "odsBuildableType" << *val; 705 } else if (const NamedTypeConstraint *var = resolver.getVariable()) { 706 if (Optional<StringRef> tform = resolver.getVarTransformer()) 707 body << tgfmt(*tform, &FmtContext().withSelf(var->name + "Types[0]")); 708 else 709 body << var->name << "Types"; 710 } else { 711 body << curVar << "Types"; 712 } 713 }; 714 715 // Resolve each of the result types. 716 if (allResultTypes) { 717 body << " result.addTypes(allResultTypes);\n"; 718 } else { 719 for (unsigned i = 0, e = op.getNumResults(); i != e; ++i) { 720 body << " result.addTypes("; 721 emitTypeResolver(resultTypes[i], op.getResultName(i)); 722 body << ");\n"; 723 } 724 } 725 726 // Early exit if there are no operands. 727 if (op.getNumOperands() == 0) 728 return; 729 730 // Handle the case where all operand types are in one group. 731 if (allOperandTypes) { 732 // If we have all operands together, use the full operand list directly. 733 if (allOperands) { 734 body << " if (parser.resolveOperands(allOperands, allOperandTypes, " 735 "allOperandLoc, result.operands))\n" 736 " return failure();\n"; 737 return; 738 } 739 740 // Otherwise, use llvm::concat to merge the disjoint operand lists together. 741 // llvm::concat does not allow the case of a single range, so guard it here. 742 body << " if (parser.resolveOperands("; 743 if (op.getNumOperands() > 1) { 744 body << "llvm::concat<const OpAsmParser::OperandType>("; 745 interleaveComma(op.getOperands(), body, [&](auto &operand) { 746 body << operand.name << "Operands"; 747 }); 748 body << ")"; 749 } else { 750 body << op.operand_begin()->name << "Operands"; 751 } 752 body << ", allOperandTypes, parser.getNameLoc(), result.operands))\n" 753 << " return failure();\n"; 754 return; 755 } 756 // Handle the case where all of the operands were grouped together. 757 if (allOperands) { 758 body << " if (parser.resolveOperands(allOperands, "; 759 760 // Group all of the operand types together to perform the resolution all at 761 // once. Use llvm::concat to perform the merge. llvm::concat does not allow 762 // the case of a single range, so guard it here. 763 if (op.getNumOperands() > 1) { 764 body << "llvm::concat<const Type>("; 765 interleaveComma(llvm::seq<int>(0, op.getNumOperands()), body, [&](int i) { 766 body << "ArrayRef<Type>("; 767 emitTypeResolver(operandTypes[i], op.getOperand(i).name); 768 body << ")"; 769 }); 770 body << ")"; 771 } else { 772 emitTypeResolver(operandTypes.front(), op.getOperand(0).name); 773 } 774 775 body << ", allOperandLoc, result.operands))\n" 776 << " return failure();\n"; 777 return; 778 } 779 780 // The final case is the one where each of the operands types are resolved 781 // separately. 782 for (unsigned i = 0, e = op.getNumOperands(); i != e; ++i) { 783 NamedTypeConstraint &operand = op.getOperand(i); 784 body << " if (parser.resolveOperands(" << operand.name << "Operands, "; 785 emitTypeResolver(operandTypes[i], operand.name); 786 787 // If this isn't a buildable type, verify the sizes match by adding the loc. 788 if (!operandTypes[i].getBuilderIdx()) 789 body << ", " << operand.name << "OperandsLoc"; 790 body << ", result.operands))\n return failure();\n"; 791 } 792 } 793 794 void OperationFormat::genParserSuccessorResolution(Operator &op, 795 OpMethodBody &body) { 796 // Check for the case where all successors were parsed. 797 bool hasAllSuccessors = llvm::any_of( 798 elements, [](auto &elt) { return isa<SuccessorsDirective>(elt.get()); }); 799 if (hasAllSuccessors) { 800 body << " result.addSuccessors(fullSuccessors);\n"; 801 return; 802 } 803 804 // Otherwise, handle each successor individually. 805 for (const NamedSuccessor &successor : op.getSuccessors()) { 806 if (successor.isVariadic()) 807 body << " result.addSuccessors(" << successor.name << "Successors);\n"; 808 else 809 body << " result.addSuccessors(" << successor.name << "Successor);\n"; 810 } 811 } 812 813 void OperationFormat::genParserVariadicSegmentResolution(Operator &op, 814 OpMethodBody &body) { 815 if (!allOperands && op.getTrait("OpTrait::AttrSizedOperandSegments")) { 816 body << " result.addAttribute(\"operand_segment_sizes\", " 817 << "builder.getI32VectorAttr({"; 818 auto interleaveFn = [&](const NamedTypeConstraint &operand) { 819 // If the operand is variadic emit the parsed size. 820 if (operand.isVariadic()) 821 body << "static_cast<int32_t>(" << operand.name << "Operands.size())"; 822 else 823 body << "1"; 824 }; 825 interleaveComma(op.getOperands(), body, interleaveFn); 826 body << "}));\n"; 827 } 828 } 829 830 //===----------------------------------------------------------------------===// 831 // PrinterGen 832 833 /// Generate the printer for the 'attr-dict' directive. 834 static void genAttrDictPrinter(OperationFormat &fmt, Operator &op, 835 OpMethodBody &body, bool withKeyword) { 836 // Collect all of the attributes used in the format, these will be elided. 837 SmallVector<const NamedAttribute *, 1> usedAttributes; 838 for (auto &it : fmt.elements) 839 if (auto *attr = dyn_cast<AttributeVariable>(it.get())) 840 usedAttributes.push_back(attr->getVar()); 841 842 body << " p.printOptionalAttrDict" << (withKeyword ? "WithKeyword" : "") 843 << "(getAttrs(), /*elidedAttrs=*/{"; 844 // Elide the variadic segment size attributes if necessary. 845 if (!fmt.allOperands && op.getTrait("OpTrait::AttrSizedOperandSegments")) 846 body << "\"operand_segment_sizes\", "; 847 interleaveComma(usedAttributes, body, [&](const NamedAttribute *attr) { 848 body << "\"" << attr->name << "\""; 849 }); 850 body << "});\n"; 851 } 852 853 /// Generate the printer for a literal value. `shouldEmitSpace` is true if a 854 /// space should be emitted before this element. `lastWasPunctuation` is true if 855 /// the previous element was a punctuation literal. 856 static void genLiteralPrinter(StringRef value, OpMethodBody &body, 857 bool &shouldEmitSpace, bool &lastWasPunctuation) { 858 body << " p"; 859 860 // Don't insert a space for certain punctuation. 861 auto shouldPrintSpaceBeforeLiteral = [&] { 862 if (value.size() != 1 && value != "->") 863 return true; 864 if (lastWasPunctuation) 865 return !StringRef(">)}],").contains(value.front()); 866 return !StringRef("<>(){}[],").contains(value.front()); 867 }; 868 if (shouldEmitSpace && shouldPrintSpaceBeforeLiteral()) 869 body << " << \" \""; 870 body << " << \"" << value << "\";\n"; 871 872 // Insert a space after certain literals. 873 shouldEmitSpace = 874 value.size() != 1 || !StringRef("<({[").contains(value.front()); 875 lastWasPunctuation = !(value.front() == '_' || isalpha(value.front())); 876 } 877 878 /// Generate the C++ for an operand to a (*-)type directive. 879 static OpMethodBody &genTypeOperandPrinter(Element *arg, OpMethodBody &body) { 880 if (isa<OperandsDirective>(arg)) 881 return body << "getOperation()->getOperandTypes()"; 882 if (isa<ResultsDirective>(arg)) 883 return body << "getOperation()->getResultTypes()"; 884 auto *operand = dyn_cast<OperandVariable>(arg); 885 auto *var = operand ? operand->getVar() : cast<ResultVariable>(arg)->getVar(); 886 if (var->isVariadic()) 887 return body << var->name << "().getTypes()"; 888 return body << "ArrayRef<Type>(" << var->name << "().getType())"; 889 } 890 891 /// Generate the code for printing the given element. 892 static void genElementPrinter(Element *element, OpMethodBody &body, 893 OperationFormat &fmt, Operator &op, 894 bool &shouldEmitSpace, bool &lastWasPunctuation) { 895 if (LiteralElement *literal = dyn_cast<LiteralElement>(element)) 896 return genLiteralPrinter(literal->getLiteral(), body, shouldEmitSpace, 897 lastWasPunctuation); 898 899 // Emit an optional group. 900 if (OptionalElement *optional = dyn_cast<OptionalElement>(element)) { 901 // Emit the check for the presence of the anchor element. 902 Element *anchor = optional->getAnchor(); 903 if (AttributeVariable *attrVar = dyn_cast<AttributeVariable>(anchor)) 904 body << " if (getAttr(\"" << attrVar->getVar()->name << "\")) {\n"; 905 else 906 body << " if (!" << cast<OperandVariable>(anchor)->getVar()->name 907 << "().empty()) {\n"; 908 909 // Emit each of the elements. 910 for (Element &childElement : optional->getElements()) 911 genElementPrinter(&childElement, body, fmt, op, shouldEmitSpace, 912 lastWasPunctuation); 913 body << " }\n"; 914 return; 915 } 916 917 // Emit the attribute dictionary. 918 if (auto *attrDict = dyn_cast<AttrDictDirective>(element)) { 919 genAttrDictPrinter(fmt, op, body, attrDict->isWithKeyword()); 920 lastWasPunctuation = false; 921 return; 922 } 923 924 // Optionally insert a space before the next element. The AttrDict printer 925 // already adds a space as necessary. 926 if (shouldEmitSpace || !lastWasPunctuation) 927 body << " p << \" \";\n"; 928 lastWasPunctuation = false; 929 shouldEmitSpace = true; 930 931 if (auto *attr = dyn_cast<AttributeVariable>(element)) { 932 const NamedAttribute *var = attr->getVar(); 933 934 // If we are formatting as an enum, symbolize the attribute as a string. 935 if (canFormatEnumAttr(var)) { 936 const EnumAttr &enumAttr = cast<EnumAttr>(var->attr); 937 body << " p << \"\\\"\" << " << enumAttr.getSymbolToStringFnName() << "(" 938 << var->name << "()) << \"\\\"\";\n"; 939 return; 940 } 941 942 // Elide the attribute type if it is buildable. 943 if (attr->getTypeBuilder()) 944 body << " p.printAttributeWithoutType(" << var->name << "Attr());\n"; 945 else 946 body << " p.printAttribute(" << var->name << "Attr());\n"; 947 } else if (auto *operand = dyn_cast<OperandVariable>(element)) { 948 body << " p << " << operand->getVar()->name << "();\n"; 949 } else if (auto *successor = dyn_cast<SuccessorVariable>(element)) { 950 const NamedSuccessor *var = successor->getVar(); 951 if (var->isVariadic()) 952 body << " interleaveComma(" << var->name << "(), p);\n"; 953 else 954 body << " p << " << var->name << "();\n"; 955 } else if (isa<OperandsDirective>(element)) { 956 body << " p << getOperation()->getOperands();\n"; 957 } else if (isa<SuccessorsDirective>(element)) { 958 body << " interleaveComma(getOperation()->getSuccessors(), p);\n"; 959 } else if (auto *dir = dyn_cast<TypeDirective>(element)) { 960 body << " p << "; 961 genTypeOperandPrinter(dir->getOperand(), body) << ";\n"; 962 } else if (auto *dir = dyn_cast<FunctionalTypeDirective>(element)) { 963 body << " p.printFunctionalType("; 964 genTypeOperandPrinter(dir->getInputs(), body) << ", "; 965 genTypeOperandPrinter(dir->getResults(), body) << ");\n"; 966 } else { 967 llvm_unreachable("unknown format element"); 968 } 969 } 970 971 void OperationFormat::genPrinter(Operator &op, OpClass &opClass) { 972 auto &method = opClass.newMethod("void", "print", "OpAsmPrinter &p"); 973 auto &body = method.body(); 974 975 // Emit the operation name, trimming the prefix if this is the standard 976 // dialect. 977 body << " p << \""; 978 std::string opName = op.getOperationName(); 979 if (op.getDialectName() == "std") 980 body << StringRef(opName).drop_front(4); 981 else 982 body << opName; 983 body << "\";\n"; 984 985 // Flags for if we should emit a space, and if the last element was 986 // punctuation. 987 bool shouldEmitSpace = true, lastWasPunctuation = false; 988 for (auto &element : elements) 989 genElementPrinter(element.get(), body, *this, op, shouldEmitSpace, 990 lastWasPunctuation); 991 } 992 993 //===----------------------------------------------------------------------===// 994 // FormatLexer 995 //===----------------------------------------------------------------------===// 996 997 namespace { 998 /// This class represents a specific token in the input format. 999 class Token { 1000 public: 1001 enum Kind { 1002 // Markers. 1003 eof, 1004 error, 1005 1006 // Tokens with no info. 1007 l_paren, 1008 r_paren, 1009 caret, 1010 comma, 1011 equal, 1012 question, 1013 1014 // Keywords. 1015 keyword_start, 1016 kw_attr_dict, 1017 kw_attr_dict_w_keyword, 1018 kw_functional_type, 1019 kw_operands, 1020 kw_results, 1021 kw_successors, 1022 kw_type, 1023 keyword_end, 1024 1025 // String valued tokens. 1026 identifier, 1027 literal, 1028 variable, 1029 }; 1030 Token(Kind kind, StringRef spelling) : kind(kind), spelling(spelling) {} 1031 1032 /// Return the bytes that make up this token. 1033 StringRef getSpelling() const { return spelling; } 1034 1035 /// Return the kind of this token. 1036 Kind getKind() const { return kind; } 1037 1038 /// Return a location for this token. 1039 llvm::SMLoc getLoc() const { 1040 return llvm::SMLoc::getFromPointer(spelling.data()); 1041 } 1042 1043 /// Return if this token is a keyword. 1044 bool isKeyword() const { return kind > keyword_start && kind < keyword_end; } 1045 1046 private: 1047 /// Discriminator that indicates the kind of token this is. 1048 Kind kind; 1049 1050 /// A reference to the entire token contents; this is always a pointer into 1051 /// a memory buffer owned by the source manager. 1052 StringRef spelling; 1053 }; 1054 1055 /// This class implements a simple lexer for operation assembly format strings. 1056 class FormatLexer { 1057 public: 1058 FormatLexer(llvm::SourceMgr &mgr); 1059 1060 /// Lex the next token and return it. 1061 Token lexToken(); 1062 1063 /// Emit an error to the lexer with the given location and message. 1064 Token emitError(llvm::SMLoc loc, const Twine &msg); 1065 Token emitError(const char *loc, const Twine &msg); 1066 1067 private: 1068 Token formToken(Token::Kind kind, const char *tokStart) { 1069 return Token(kind, StringRef(tokStart, curPtr - tokStart)); 1070 } 1071 1072 /// Return the next character in the stream. 1073 int getNextChar(); 1074 1075 /// Lex an identifier, literal, or variable. 1076 Token lexIdentifier(const char *tokStart); 1077 Token lexLiteral(const char *tokStart); 1078 Token lexVariable(const char *tokStart); 1079 1080 llvm::SourceMgr &srcMgr; 1081 StringRef curBuffer; 1082 const char *curPtr; 1083 }; 1084 } // end anonymous namespace 1085 1086 FormatLexer::FormatLexer(llvm::SourceMgr &mgr) : srcMgr(mgr) { 1087 curBuffer = srcMgr.getMemoryBuffer(mgr.getMainFileID())->getBuffer(); 1088 curPtr = curBuffer.begin(); 1089 } 1090 1091 Token FormatLexer::emitError(llvm::SMLoc loc, const Twine &msg) { 1092 srcMgr.PrintMessage(loc, llvm::SourceMgr::DK_Error, msg); 1093 return formToken(Token::error, loc.getPointer()); 1094 } 1095 Token FormatLexer::emitError(const char *loc, const Twine &msg) { 1096 return emitError(llvm::SMLoc::getFromPointer(loc), msg); 1097 } 1098 1099 int FormatLexer::getNextChar() { 1100 char curChar = *curPtr++; 1101 switch (curChar) { 1102 default: 1103 return (unsigned char)curChar; 1104 case 0: { 1105 // A nul character in the stream is either the end of the current buffer or 1106 // a random nul in the file. Disambiguate that here. 1107 if (curPtr - 1 != curBuffer.end()) 1108 return 0; 1109 1110 // Otherwise, return end of file. 1111 --curPtr; 1112 return EOF; 1113 } 1114 case '\n': 1115 case '\r': 1116 // Handle the newline character by ignoring it and incrementing the line 1117 // count. However, be careful about 'dos style' files with \n\r in them. 1118 // Only treat a \n\r or \r\n as a single line. 1119 if ((*curPtr == '\n' || (*curPtr == '\r')) && *curPtr != curChar) 1120 ++curPtr; 1121 return '\n'; 1122 } 1123 } 1124 1125 Token FormatLexer::lexToken() { 1126 const char *tokStart = curPtr; 1127 1128 // This always consumes at least one character. 1129 int curChar = getNextChar(); 1130 switch (curChar) { 1131 default: 1132 // Handle identifiers: [a-zA-Z_] 1133 if (isalpha(curChar) || curChar == '_') 1134 return lexIdentifier(tokStart); 1135 1136 // Unknown character, emit an error. 1137 return emitError(tokStart, "unexpected character"); 1138 case EOF: 1139 // Return EOF denoting the end of lexing. 1140 return formToken(Token::eof, tokStart); 1141 1142 // Lex punctuation. 1143 case '^': 1144 return formToken(Token::caret, tokStart); 1145 case ',': 1146 return formToken(Token::comma, tokStart); 1147 case '=': 1148 return formToken(Token::equal, tokStart); 1149 case '?': 1150 return formToken(Token::question, tokStart); 1151 case '(': 1152 return formToken(Token::l_paren, tokStart); 1153 case ')': 1154 return formToken(Token::r_paren, tokStart); 1155 1156 // Ignore whitespace characters. 1157 case 0: 1158 case ' ': 1159 case '\t': 1160 case '\n': 1161 return lexToken(); 1162 1163 case '`': 1164 return lexLiteral(tokStart); 1165 case '$': 1166 return lexVariable(tokStart); 1167 } 1168 } 1169 1170 Token FormatLexer::lexLiteral(const char *tokStart) { 1171 assert(curPtr[-1] == '`'); 1172 1173 // Lex a literal surrounded by ``. 1174 while (const char curChar = *curPtr++) { 1175 if (curChar == '`') 1176 return formToken(Token::literal, tokStart); 1177 } 1178 return emitError(curPtr - 1, "unexpected end of file in literal"); 1179 } 1180 1181 Token FormatLexer::lexVariable(const char *tokStart) { 1182 if (!isalpha(curPtr[0]) && curPtr[0] != '_') 1183 return emitError(curPtr - 1, "expected variable name"); 1184 1185 // Otherwise, consume the rest of the characters. 1186 while (isalnum(*curPtr) || *curPtr == '_') 1187 ++curPtr; 1188 return formToken(Token::variable, tokStart); 1189 } 1190 1191 Token FormatLexer::lexIdentifier(const char *tokStart) { 1192 // Match the rest of the identifier regex: [0-9a-zA-Z_\-]* 1193 while (isalnum(*curPtr) || *curPtr == '_' || *curPtr == '-') 1194 ++curPtr; 1195 1196 // Check to see if this identifier is a keyword. 1197 StringRef str(tokStart, curPtr - tokStart); 1198 Token::Kind kind = 1199 llvm::StringSwitch<Token::Kind>(str) 1200 .Case("attr-dict", Token::kw_attr_dict) 1201 .Case("attr-dict-with-keyword", Token::kw_attr_dict_w_keyword) 1202 .Case("functional-type", Token::kw_functional_type) 1203 .Case("operands", Token::kw_operands) 1204 .Case("results", Token::kw_results) 1205 .Case("successors", Token::kw_successors) 1206 .Case("type", Token::kw_type) 1207 .Default(Token::identifier); 1208 return Token(kind, str); 1209 } 1210 1211 //===----------------------------------------------------------------------===// 1212 // FormatParser 1213 //===----------------------------------------------------------------------===// 1214 1215 /// Function to find an element within the given range that has the same name as 1216 /// 'name'. 1217 template <typename RangeT> static auto findArg(RangeT &&range, StringRef name) { 1218 auto it = llvm::find_if(range, [=](auto &arg) { return arg.name == name; }); 1219 return it != range.end() ? &*it : nullptr; 1220 } 1221 1222 namespace { 1223 /// This class implements a parser for an instance of an operation assembly 1224 /// format. 1225 class FormatParser { 1226 public: 1227 FormatParser(llvm::SourceMgr &mgr, OperationFormat &format, Operator &op) 1228 : lexer(mgr), curToken(lexer.lexToken()), fmt(format), op(op), 1229 seenOperandTypes(op.getNumOperands()), 1230 seenResultTypes(op.getNumResults()) {} 1231 1232 /// Parse the operation assembly format. 1233 LogicalResult parse(); 1234 1235 private: 1236 /// This struct represents a type resolution instance. It includes a specific 1237 /// type as well as an optional transformer to apply to that type in order to 1238 /// properly resolve the type of a variable. 1239 struct TypeResolutionInstance { 1240 const NamedTypeConstraint *type; 1241 Optional<StringRef> transformer; 1242 }; 1243 1244 /// Verify the state of operation attributes within the format. 1245 LogicalResult verifyAttributes(llvm::SMLoc loc); 1246 1247 /// Verify the state of operation operands within the format. 1248 LogicalResult 1249 verifyOperands(llvm::SMLoc loc, 1250 llvm::StringMap<TypeResolutionInstance> &variableTyResolver); 1251 1252 /// Verify the state of operation results within the format. 1253 LogicalResult 1254 verifyResults(llvm::SMLoc loc, 1255 llvm::StringMap<TypeResolutionInstance> &variableTyResolver); 1256 1257 /// Verify the state of operation successors within the format. 1258 LogicalResult verifySuccessors(llvm::SMLoc loc); 1259 1260 /// Given the values of an `AllTypesMatch` trait, check for inferable type 1261 /// resolution. 1262 void handleAllTypesMatchConstraint( 1263 ArrayRef<StringRef> values, 1264 llvm::StringMap<TypeResolutionInstance> &variableTyResolver); 1265 /// Check for inferable type resolution given all operands, and or results, 1266 /// have the same type. If 'includeResults' is true, the results also have the 1267 /// same type as all of the operands. 1268 void handleSameTypesConstraint( 1269 llvm::StringMap<TypeResolutionInstance> &variableTyResolver, 1270 bool includeResults); 1271 1272 /// Returns an argument with the given name that has been seen within the 1273 /// format. 1274 const NamedTypeConstraint *findSeenArg(StringRef name); 1275 1276 /// Parse a specific element. 1277 LogicalResult parseElement(std::unique_ptr<Element> &element, 1278 bool isTopLevel); 1279 LogicalResult parseVariable(std::unique_ptr<Element> &element, 1280 bool isTopLevel); 1281 LogicalResult parseDirective(std::unique_ptr<Element> &element, 1282 bool isTopLevel); 1283 LogicalResult parseLiteral(std::unique_ptr<Element> &element); 1284 LogicalResult parseOptional(std::unique_ptr<Element> &element, 1285 bool isTopLevel); 1286 LogicalResult parseOptionalChildElement( 1287 std::vector<std::unique_ptr<Element>> &childElements, 1288 SmallPtrSetImpl<const NamedTypeConstraint *> &seenVariables, 1289 Optional<unsigned> &anchorIdx); 1290 1291 /// Parse the various different directives. 1292 LogicalResult parseAttrDictDirective(std::unique_ptr<Element> &element, 1293 llvm::SMLoc loc, bool isTopLevel, 1294 bool withKeyword); 1295 LogicalResult parseFunctionalTypeDirective(std::unique_ptr<Element> &element, 1296 Token tok, bool isTopLevel); 1297 LogicalResult parseOperandsDirective(std::unique_ptr<Element> &element, 1298 llvm::SMLoc loc, bool isTopLevel); 1299 LogicalResult parseResultsDirective(std::unique_ptr<Element> &element, 1300 llvm::SMLoc loc, bool isTopLevel); 1301 LogicalResult parseSuccessorsDirective(std::unique_ptr<Element> &element, 1302 llvm::SMLoc loc, bool isTopLevel); 1303 LogicalResult parseTypeDirective(std::unique_ptr<Element> &element, Token tok, 1304 bool isTopLevel); 1305 LogicalResult parseTypeDirectiveOperand(std::unique_ptr<Element> &element); 1306 1307 //===--------------------------------------------------------------------===// 1308 // Lexer Utilities 1309 //===--------------------------------------------------------------------===// 1310 1311 /// Advance the current lexer onto the next token. 1312 void consumeToken() { 1313 assert(curToken.getKind() != Token::eof && 1314 curToken.getKind() != Token::error && 1315 "shouldn't advance past EOF or errors"); 1316 curToken = lexer.lexToken(); 1317 } 1318 LogicalResult parseToken(Token::Kind kind, const Twine &msg) { 1319 if (curToken.getKind() != kind) 1320 return emitError(curToken.getLoc(), msg); 1321 consumeToken(); 1322 return success(); 1323 } 1324 LogicalResult emitError(llvm::SMLoc loc, const Twine &msg) { 1325 lexer.emitError(loc, msg); 1326 return failure(); 1327 } 1328 1329 //===--------------------------------------------------------------------===// 1330 // Fields 1331 //===--------------------------------------------------------------------===// 1332 1333 FormatLexer lexer; 1334 Token curToken; 1335 OperationFormat &fmt; 1336 Operator &op; 1337 1338 // The following are various bits of format state used for verification 1339 // during parsing. 1340 bool hasAllOperands = false, hasAttrDict = false; 1341 bool hasAllSuccessors = false; 1342 llvm::SmallBitVector seenOperandTypes, seenResultTypes; 1343 llvm::DenseSet<const NamedTypeConstraint *> seenOperands; 1344 llvm::DenseSet<const NamedAttribute *> seenAttrs; 1345 llvm::DenseSet<const NamedSuccessor *> seenSuccessors; 1346 llvm::DenseSet<const NamedTypeConstraint *> optionalVariables; 1347 }; 1348 } // end anonymous namespace 1349 1350 LogicalResult FormatParser::parse() { 1351 llvm::SMLoc loc = curToken.getLoc(); 1352 1353 // Parse each of the format elements into the main format. 1354 while (curToken.getKind() != Token::eof) { 1355 std::unique_ptr<Element> element; 1356 if (failed(parseElement(element, /*isTopLevel=*/true))) 1357 return failure(); 1358 fmt.elements.push_back(std::move(element)); 1359 } 1360 1361 // Check that the attribute dictionary is in the format. 1362 if (!hasAttrDict) 1363 return emitError(loc, "format missing 'attr-dict' directive"); 1364 1365 // Check for any type traits that we can use for inferring types. 1366 llvm::StringMap<TypeResolutionInstance> variableTyResolver; 1367 for (const OpTrait &trait : op.getTraits()) { 1368 const llvm::Record &def = trait.getDef(); 1369 if (def.isSubClassOf("AllTypesMatch")) { 1370 handleAllTypesMatchConstraint(def.getValueAsListOfStrings("values"), 1371 variableTyResolver); 1372 } else if (def.getName() == "SameTypeOperands") { 1373 handleSameTypesConstraint(variableTyResolver, /*includeResults=*/false); 1374 } else if (def.getName() == "SameOperandsAndResultType") { 1375 handleSameTypesConstraint(variableTyResolver, /*includeResults=*/true); 1376 } else if (def.isSubClassOf("TypesMatchWith")) { 1377 if (const auto *lhsArg = findSeenArg(def.getValueAsString("lhs"))) 1378 variableTyResolver[def.getValueAsString("rhs")] = { 1379 lhsArg, def.getValueAsString("transformer")}; 1380 } 1381 } 1382 1383 // Verify the state of the various operation components. 1384 if (failed(verifyAttributes(loc)) || 1385 failed(verifyResults(loc, variableTyResolver)) || 1386 failed(verifyOperands(loc, variableTyResolver)) || 1387 failed(verifySuccessors(loc))) 1388 return failure(); 1389 1390 // Check to see if we are formatting all of the operands. 1391 fmt.allOperands = llvm::any_of(fmt.elements, [](auto &elt) { 1392 return isa<OperandsDirective>(elt.get()); 1393 }); 1394 return success(); 1395 } 1396 1397 LogicalResult FormatParser::verifyAttributes(llvm::SMLoc loc) { 1398 // Check that there are no `:` literals after an attribute without a constant 1399 // type. The attribute grammar contains an optional trailing colon type, which 1400 // can lead to unexpected and generally unintended behavior. Given that, it is 1401 // better to just error out here instead. 1402 using ElementsIterT = llvm::pointee_iterator< 1403 std::vector<std::unique_ptr<Element>>::const_iterator>; 1404 SmallVector<std::pair<ElementsIterT, ElementsIterT>, 1> iteratorStack; 1405 iteratorStack.emplace_back(fmt.elements.begin(), fmt.elements.end()); 1406 while (!iteratorStack.empty()) { 1407 auto &stackIt = iteratorStack.back(); 1408 ElementsIterT &it = stackIt.first, e = stackIt.second; 1409 while (it != e) { 1410 Element *element = &*(it++); 1411 1412 // Traverse into optional groups. 1413 if (auto *optional = dyn_cast<OptionalElement>(element)) { 1414 auto elements = optional->getElements(); 1415 iteratorStack.emplace_back(elements.begin(), elements.end()); 1416 break; 1417 } 1418 1419 // We are checking for an attribute element followed by a `:`, so there is 1420 // no need to check the end. 1421 if (it == e && iteratorStack.size() == 1) 1422 break; 1423 1424 // Check for an attribute with a constant type builder, followed by a `:`. 1425 auto *prevAttr = dyn_cast<AttributeVariable>(element); 1426 if (!prevAttr || prevAttr->getTypeBuilder()) 1427 continue; 1428 1429 // Check the next iterator within the stack for literal elements. 1430 for (auto &nextItPair : iteratorStack) { 1431 ElementsIterT nextIt = nextItPair.first, nextE = nextItPair.second; 1432 for (; nextIt != nextE; ++nextIt) { 1433 // Skip any trailing optional groups or attribute dictionaries. 1434 if (isa<AttrDictDirective>(*nextIt) || isa<OptionalElement>(*nextIt)) 1435 continue; 1436 1437 // We are only interested in `:` literals. 1438 auto *literal = dyn_cast<LiteralElement>(&*nextIt); 1439 if (!literal || literal->getLiteral() != ":") 1440 break; 1441 1442 // TODO: Use the location of the literal element itself. 1443 return emitError( 1444 loc, llvm::formatv("format ambiguity caused by `:` literal found " 1445 "after attribute `{0}` which does not have " 1446 "a buildable type", 1447 prevAttr->getVar()->name)); 1448 } 1449 } 1450 } 1451 if (it == e) 1452 iteratorStack.pop_back(); 1453 } 1454 return success(); 1455 } 1456 1457 LogicalResult FormatParser::verifyOperands( 1458 llvm::SMLoc loc, 1459 llvm::StringMap<TypeResolutionInstance> &variableTyResolver) { 1460 // Check that all of the operands are within the format, and their types can 1461 // be inferred. 1462 auto &buildableTypes = fmt.buildableTypes; 1463 for (unsigned i = 0, e = op.getNumOperands(); i != e; ++i) { 1464 NamedTypeConstraint &operand = op.getOperand(i); 1465 1466 // Check that the operand itself is in the format. 1467 if (!hasAllOperands && !seenOperands.count(&operand)) { 1468 return emitError(loc, "format missing instance of operand #" + Twine(i) + 1469 "('" + operand.name + "')"); 1470 } 1471 1472 // Check that the operand type is in the format, or that it can be inferred. 1473 if (fmt.allOperandTypes || seenOperandTypes.test(i)) 1474 continue; 1475 1476 // Check to see if we can infer this type from another variable. 1477 auto varResolverIt = variableTyResolver.find(op.getOperand(i).name); 1478 if (varResolverIt != variableTyResolver.end()) { 1479 fmt.operandTypes[i].setVariable(varResolverIt->second.type, 1480 varResolverIt->second.transformer); 1481 continue; 1482 } 1483 1484 // Similarly to results, allow a custom builder for resolving the type if 1485 // we aren't using the 'operands' directive. 1486 Optional<StringRef> builder = operand.constraint.getBuilderCall(); 1487 if (!builder || (hasAllOperands && operand.isVariadic())) { 1488 return emitError(loc, "format missing instance of operand #" + Twine(i) + 1489 "('" + operand.name + "') type"); 1490 } 1491 auto it = buildableTypes.insert({*builder, buildableTypes.size()}); 1492 fmt.operandTypes[i].setBuilderIdx(it.first->second); 1493 } 1494 return success(); 1495 } 1496 1497 LogicalResult FormatParser::verifyResults( 1498 llvm::SMLoc loc, 1499 llvm::StringMap<TypeResolutionInstance> &variableTyResolver) { 1500 // If we format all of the types together, there is nothing to check. 1501 if (fmt.allResultTypes) 1502 return success(); 1503 1504 // Check that all of the result types can be inferred. 1505 auto &buildableTypes = fmt.buildableTypes; 1506 for (unsigned i = 0, e = op.getNumResults(); i != e; ++i) { 1507 if (seenResultTypes.test(i)) 1508 continue; 1509 1510 // Check to see if we can infer this type from another variable. 1511 auto varResolverIt = variableTyResolver.find(op.getResultName(i)); 1512 if (varResolverIt != variableTyResolver.end()) { 1513 fmt.resultTypes[i].setVariable(varResolverIt->second.type, 1514 varResolverIt->second.transformer); 1515 continue; 1516 } 1517 1518 // If the result is not variadic, allow for the case where the type has a 1519 // builder that we can use. 1520 NamedTypeConstraint &result = op.getResult(i); 1521 Optional<StringRef> builder = result.constraint.getBuilderCall(); 1522 if (!builder || result.constraint.isVariadic()) { 1523 return emitError(loc, "format missing instance of result #" + Twine(i) + 1524 "('" + result.name + "') type"); 1525 } 1526 // Note in the format that this result uses the custom builder. 1527 auto it = buildableTypes.insert({*builder, buildableTypes.size()}); 1528 fmt.resultTypes[i].setBuilderIdx(it.first->second); 1529 } 1530 return success(); 1531 } 1532 1533 LogicalResult FormatParser::verifySuccessors(llvm::SMLoc loc) { 1534 // Check that all of the successors are within the format. 1535 if (hasAllSuccessors) 1536 return success(); 1537 1538 for (unsigned i = 0, e = op.getNumSuccessors(); i != e; ++i) { 1539 const NamedSuccessor &successor = op.getSuccessor(i); 1540 if (!seenSuccessors.count(&successor)) { 1541 return emitError(loc, "format missing instance of successor #" + 1542 Twine(i) + "('" + successor.name + "')"); 1543 } 1544 } 1545 return success(); 1546 } 1547 1548 void FormatParser::handleAllTypesMatchConstraint( 1549 ArrayRef<StringRef> values, 1550 llvm::StringMap<TypeResolutionInstance> &variableTyResolver) { 1551 for (unsigned i = 0, e = values.size(); i != e; ++i) { 1552 // Check to see if this value matches a resolved operand or result type. 1553 const NamedTypeConstraint *arg = findSeenArg(values[i]); 1554 if (!arg) 1555 continue; 1556 1557 // Mark this value as the type resolver for the other variables. 1558 for (unsigned j = 0; j != i; ++j) 1559 variableTyResolver[values[j]] = {arg, llvm::None}; 1560 for (unsigned j = i + 1; j != e; ++j) 1561 variableTyResolver[values[j]] = {arg, llvm::None}; 1562 } 1563 } 1564 1565 void FormatParser::handleSameTypesConstraint( 1566 llvm::StringMap<TypeResolutionInstance> &variableTyResolver, 1567 bool includeResults) { 1568 const NamedTypeConstraint *resolver = nullptr; 1569 int resolvedIt = -1; 1570 1571 // Check to see if there is an operand or result to use for the resolution. 1572 if ((resolvedIt = seenOperandTypes.find_first()) != -1) 1573 resolver = &op.getOperand(resolvedIt); 1574 else if (includeResults && (resolvedIt = seenResultTypes.find_first()) != -1) 1575 resolver = &op.getResult(resolvedIt); 1576 else 1577 return; 1578 1579 // Set the resolvers for each operand and result. 1580 for (unsigned i = 0, e = op.getNumOperands(); i != e; ++i) 1581 if (!seenOperandTypes.test(i) && !op.getOperand(i).name.empty()) 1582 variableTyResolver[op.getOperand(i).name] = {resolver, llvm::None}; 1583 if (includeResults) { 1584 for (unsigned i = 0, e = op.getNumResults(); i != e; ++i) 1585 if (!seenResultTypes.test(i) && !op.getResultName(i).empty()) 1586 variableTyResolver[op.getResultName(i)] = {resolver, llvm::None}; 1587 } 1588 } 1589 1590 const NamedTypeConstraint *FormatParser::findSeenArg(StringRef name) { 1591 if (auto *arg = findArg(op.getOperands(), name)) 1592 return seenOperandTypes.test(arg - op.operand_begin()) ? arg : nullptr; 1593 if (auto *arg = findArg(op.getResults(), name)) 1594 return seenResultTypes.test(arg - op.result_begin()) ? arg : nullptr; 1595 return nullptr; 1596 } 1597 1598 LogicalResult FormatParser::parseElement(std::unique_ptr<Element> &element, 1599 bool isTopLevel) { 1600 // Directives. 1601 if (curToken.isKeyword()) 1602 return parseDirective(element, isTopLevel); 1603 // Literals. 1604 if (curToken.getKind() == Token::literal) 1605 return parseLiteral(element); 1606 // Optionals. 1607 if (curToken.getKind() == Token::l_paren) 1608 return parseOptional(element, isTopLevel); 1609 // Variables. 1610 if (curToken.getKind() == Token::variable) 1611 return parseVariable(element, isTopLevel); 1612 return emitError(curToken.getLoc(), 1613 "expected directive, literal, variable, or optional group"); 1614 } 1615 1616 LogicalResult FormatParser::parseVariable(std::unique_ptr<Element> &element, 1617 bool isTopLevel) { 1618 Token varTok = curToken; 1619 consumeToken(); 1620 1621 StringRef name = varTok.getSpelling().drop_front(); 1622 llvm::SMLoc loc = varTok.getLoc(); 1623 1624 // Check that the parsed argument is something actually registered on the 1625 // op. 1626 /// Attributes 1627 if (const NamedAttribute *attr = findArg(op.getAttributes(), name)) { 1628 if (isTopLevel && !seenAttrs.insert(attr).second) 1629 return emitError(loc, "attribute '" + name + "' is already bound"); 1630 element = std::make_unique<AttributeVariable>(attr); 1631 return success(); 1632 } 1633 /// Operands 1634 if (const NamedTypeConstraint *operand = findArg(op.getOperands(), name)) { 1635 if (isTopLevel) { 1636 if (hasAllOperands || !seenOperands.insert(operand).second) 1637 return emitError(loc, "operand '" + name + "' is already bound"); 1638 } 1639 element = std::make_unique<OperandVariable>(operand); 1640 return success(); 1641 } 1642 /// Results. 1643 if (const auto *result = findArg(op.getResults(), name)) { 1644 if (isTopLevel) 1645 return emitError(loc, "results can not be used at the top level"); 1646 element = std::make_unique<ResultVariable>(result); 1647 return success(); 1648 } 1649 /// Successors. 1650 if (const auto *successor = findArg(op.getSuccessors(), name)) { 1651 if (!isTopLevel) 1652 return emitError(loc, "successors can only be used at the top level"); 1653 if (hasAllSuccessors || !seenSuccessors.insert(successor).second) 1654 return emitError(loc, "successor '" + name + "' is already bound"); 1655 element = std::make_unique<SuccessorVariable>(successor); 1656 return success(); 1657 } 1658 return emitError( 1659 loc, "expected variable to refer to an argument, result, or successor"); 1660 } 1661 1662 LogicalResult FormatParser::parseDirective(std::unique_ptr<Element> &element, 1663 bool isTopLevel) { 1664 Token dirTok = curToken; 1665 consumeToken(); 1666 1667 switch (dirTok.getKind()) { 1668 case Token::kw_attr_dict: 1669 return parseAttrDictDirective(element, dirTok.getLoc(), isTopLevel, 1670 /*withKeyword=*/false); 1671 case Token::kw_attr_dict_w_keyword: 1672 return parseAttrDictDirective(element, dirTok.getLoc(), isTopLevel, 1673 /*withKeyword=*/true); 1674 case Token::kw_functional_type: 1675 return parseFunctionalTypeDirective(element, dirTok, isTopLevel); 1676 case Token::kw_operands: 1677 return parseOperandsDirective(element, dirTok.getLoc(), isTopLevel); 1678 case Token::kw_results: 1679 return parseResultsDirective(element, dirTok.getLoc(), isTopLevel); 1680 case Token::kw_successors: 1681 return parseSuccessorsDirective(element, dirTok.getLoc(), isTopLevel); 1682 case Token::kw_type: 1683 return parseTypeDirective(element, dirTok, isTopLevel); 1684 1685 default: 1686 llvm_unreachable("unknown directive token"); 1687 } 1688 } 1689 1690 LogicalResult FormatParser::parseLiteral(std::unique_ptr<Element> &element) { 1691 Token literalTok = curToken; 1692 consumeToken(); 1693 1694 // Check that the parsed literal is valid. 1695 StringRef value = literalTok.getSpelling().drop_front().drop_back(); 1696 if (!LiteralElement::isValidLiteral(value)) 1697 return emitError(literalTok.getLoc(), "expected valid literal"); 1698 1699 element = std::make_unique<LiteralElement>(value); 1700 return success(); 1701 } 1702 1703 LogicalResult FormatParser::parseOptional(std::unique_ptr<Element> &element, 1704 bool isTopLevel) { 1705 llvm::SMLoc curLoc = curToken.getLoc(); 1706 if (!isTopLevel) 1707 return emitError(curLoc, "optional groups can only be used as top-level " 1708 "elements"); 1709 consumeToken(); 1710 1711 // Parse the child elements for this optional group. 1712 std::vector<std::unique_ptr<Element>> elements; 1713 SmallPtrSet<const NamedTypeConstraint *, 8> seenVariables; 1714 Optional<unsigned> anchorIdx; 1715 do { 1716 if (failed(parseOptionalChildElement(elements, seenVariables, anchorIdx))) 1717 return failure(); 1718 } while (curToken.getKind() != Token::r_paren); 1719 consumeToken(); 1720 if (failed(parseToken(Token::question, "expected '?' after optional group"))) 1721 return failure(); 1722 1723 // The optional group is required to have an anchor. 1724 if (!anchorIdx) 1725 return emitError(curLoc, "optional group specified no anchor element"); 1726 1727 // The first element of the group must be one that can be parsed/printed in an 1728 // optional fashion. 1729 if (!isa<LiteralElement>(&*elements.front()) && 1730 !isa<OperandVariable>(&*elements.front())) 1731 return emitError(curLoc, "first element of an operand group must be a " 1732 "literal or operand"); 1733 1734 // After parsing all of the elements, ensure that all type directives refer 1735 // only to elements within the group. 1736 auto checkTypeOperand = [&](Element *typeEle) { 1737 auto *opVar = dyn_cast<OperandVariable>(typeEle); 1738 const NamedTypeConstraint *var = opVar ? opVar->getVar() : nullptr; 1739 if (!seenVariables.count(var)) 1740 return emitError(curLoc, "type directive can only refer to variables " 1741 "within the optional group"); 1742 return success(); 1743 }; 1744 for (auto &ele : elements) { 1745 if (auto *typeEle = dyn_cast<TypeDirective>(ele.get())) { 1746 if (failed(checkTypeOperand(typeEle->getOperand()))) 1747 return failure(); 1748 } else if (auto *typeEle = dyn_cast<FunctionalTypeDirective>(ele.get())) { 1749 if (failed(checkTypeOperand(typeEle->getInputs())) || 1750 failed(checkTypeOperand(typeEle->getResults()))) 1751 return failure(); 1752 } 1753 } 1754 1755 optionalVariables.insert(seenVariables.begin(), seenVariables.end()); 1756 element = std::make_unique<OptionalElement>(std::move(elements), *anchorIdx); 1757 return success(); 1758 } 1759 1760 LogicalResult FormatParser::parseOptionalChildElement( 1761 std::vector<std::unique_ptr<Element>> &childElements, 1762 SmallPtrSetImpl<const NamedTypeConstraint *> &seenVariables, 1763 Optional<unsigned> &anchorIdx) { 1764 llvm::SMLoc childLoc = curToken.getLoc(); 1765 childElements.push_back({}); 1766 if (failed(parseElement(childElements.back(), /*isTopLevel=*/true))) 1767 return failure(); 1768 1769 // Check to see if this element is the anchor of the optional group. 1770 bool isAnchor = curToken.getKind() == Token::caret; 1771 if (isAnchor) { 1772 if (anchorIdx) 1773 return emitError(childLoc, "only one element can be marked as the anchor " 1774 "of an optional group"); 1775 anchorIdx = childElements.size() - 1; 1776 consumeToken(); 1777 } 1778 1779 return TypeSwitch<Element *, LogicalResult>(childElements.back().get()) 1780 // All attributes can be within the optional group, but only optional 1781 // attributes can be the anchor. 1782 .Case([&](AttributeVariable *attrEle) { 1783 if (isAnchor && !attrEle->getVar()->attr.isOptional()) 1784 return emitError(childLoc, "only optional attributes can be used to " 1785 "anchor an optional group"); 1786 return success(); 1787 }) 1788 // Only optional-like(i.e. variadic) operands can be within an optional 1789 // group. 1790 .Case<OperandVariable>([&](OperandVariable *ele) { 1791 if (!ele->getVar()->isVariadic()) 1792 return emitError(childLoc, "only variadic operands can be used within" 1793 " an optional group"); 1794 seenVariables.insert(ele->getVar()); 1795 return success(); 1796 }) 1797 // Literals and type directives may be used, but they can't anchor the 1798 // group. 1799 .Case<LiteralElement, TypeDirective, FunctionalTypeDirective>( 1800 [&](Element *) { 1801 if (isAnchor) 1802 return emitError(childLoc, "only variables can be used to anchor " 1803 "an optional group"); 1804 return success(); 1805 }) 1806 .Default([&](Element *) { 1807 return emitError(childLoc, "only literals, types, and variables can be " 1808 "used within an optional group"); 1809 }); 1810 } 1811 1812 LogicalResult 1813 FormatParser::parseAttrDictDirective(std::unique_ptr<Element> &element, 1814 llvm::SMLoc loc, bool isTopLevel, 1815 bool withKeyword) { 1816 if (!isTopLevel) 1817 return emitError(loc, "'attr-dict' directive can only be used as a " 1818 "top-level directive"); 1819 if (hasAttrDict) 1820 return emitError(loc, "'attr-dict' directive has already been seen"); 1821 1822 hasAttrDict = true; 1823 element = std::make_unique<AttrDictDirective>(withKeyword); 1824 return success(); 1825 } 1826 1827 LogicalResult 1828 FormatParser::parseFunctionalTypeDirective(std::unique_ptr<Element> &element, 1829 Token tok, bool isTopLevel) { 1830 llvm::SMLoc loc = tok.getLoc(); 1831 if (!isTopLevel) 1832 return emitError( 1833 loc, "'functional-type' is only valid as a top-level directive"); 1834 1835 // Parse the main operand. 1836 std::unique_ptr<Element> inputs, results; 1837 if (failed(parseToken(Token::l_paren, "expected '(' before argument list")) || 1838 failed(parseTypeDirectiveOperand(inputs)) || 1839 failed(parseToken(Token::comma, "expected ',' after inputs argument")) || 1840 failed(parseTypeDirectiveOperand(results)) || 1841 failed(parseToken(Token::r_paren, "expected ')' after argument list"))) 1842 return failure(); 1843 element = std::make_unique<FunctionalTypeDirective>(std::move(inputs), 1844 std::move(results)); 1845 return success(); 1846 } 1847 1848 LogicalResult 1849 FormatParser::parseOperandsDirective(std::unique_ptr<Element> &element, 1850 llvm::SMLoc loc, bool isTopLevel) { 1851 if (isTopLevel && (hasAllOperands || !seenOperands.empty())) 1852 return emitError(loc, "'operands' directive creates overlap in format"); 1853 hasAllOperands = true; 1854 element = std::make_unique<OperandsDirective>(); 1855 return success(); 1856 } 1857 1858 LogicalResult 1859 FormatParser::parseResultsDirective(std::unique_ptr<Element> &element, 1860 llvm::SMLoc loc, bool isTopLevel) { 1861 if (isTopLevel) 1862 return emitError(loc, "'results' directive can not be used as a " 1863 "top-level directive"); 1864 element = std::make_unique<ResultsDirective>(); 1865 return success(); 1866 } 1867 1868 LogicalResult 1869 FormatParser::parseSuccessorsDirective(std::unique_ptr<Element> &element, 1870 llvm::SMLoc loc, bool isTopLevel) { 1871 if (!isTopLevel) 1872 return emitError(loc, 1873 "'successors' is only valid as a top-level directive"); 1874 if (hasAllSuccessors || !seenSuccessors.empty()) 1875 return emitError(loc, "'successors' directive creates overlap in format"); 1876 hasAllSuccessors = true; 1877 element = std::make_unique<SuccessorsDirective>(); 1878 return success(); 1879 } 1880 1881 LogicalResult 1882 FormatParser::parseTypeDirective(std::unique_ptr<Element> &element, Token tok, 1883 bool isTopLevel) { 1884 llvm::SMLoc loc = tok.getLoc(); 1885 if (!isTopLevel) 1886 return emitError(loc, "'type' is only valid as a top-level directive"); 1887 1888 std::unique_ptr<Element> operand; 1889 if (failed(parseToken(Token::l_paren, "expected '(' before argument list")) || 1890 failed(parseTypeDirectiveOperand(operand)) || 1891 failed(parseToken(Token::r_paren, "expected ')' after argument list"))) 1892 return failure(); 1893 element = std::make_unique<TypeDirective>(std::move(operand)); 1894 return success(); 1895 } 1896 1897 LogicalResult 1898 FormatParser::parseTypeDirectiveOperand(std::unique_ptr<Element> &element) { 1899 llvm::SMLoc loc = curToken.getLoc(); 1900 if (failed(parseElement(element, /*isTopLevel=*/false))) 1901 return failure(); 1902 if (isa<LiteralElement>(element.get())) 1903 return emitError( 1904 loc, "'type' directive operand expects variable or directive operand"); 1905 1906 if (auto *var = dyn_cast<OperandVariable>(element.get())) { 1907 unsigned opIdx = var->getVar() - op.operand_begin(); 1908 if (fmt.allOperandTypes || seenOperandTypes.test(opIdx)) 1909 return emitError(loc, "'type' of '" + var->getVar()->name + 1910 "' is already bound"); 1911 seenOperandTypes.set(opIdx); 1912 } else if (auto *var = dyn_cast<ResultVariable>(element.get())) { 1913 unsigned resIdx = var->getVar() - op.result_begin(); 1914 if (fmt.allResultTypes || seenResultTypes.test(resIdx)) 1915 return emitError(loc, "'type' of '" + var->getVar()->name + 1916 "' is already bound"); 1917 seenResultTypes.set(resIdx); 1918 } else if (isa<OperandsDirective>(&*element)) { 1919 if (fmt.allOperandTypes || seenOperandTypes.any()) 1920 return emitError(loc, "'operands' 'type' is already bound"); 1921 fmt.allOperandTypes = true; 1922 } else if (isa<ResultsDirective>(&*element)) { 1923 if (fmt.allResultTypes || seenResultTypes.any()) 1924 return emitError(loc, "'results' 'type' is already bound"); 1925 fmt.allResultTypes = true; 1926 } else { 1927 return emitError(loc, "invalid argument to 'type' directive"); 1928 } 1929 return success(); 1930 } 1931 1932 //===----------------------------------------------------------------------===// 1933 // Interface 1934 //===----------------------------------------------------------------------===// 1935 1936 void mlir::tblgen::generateOpFormat(const Operator &constOp, OpClass &opClass) { 1937 // TODO(riverriddle) Operator doesn't expose all necessary functionality via 1938 // the const interface. 1939 Operator &op = const_cast<Operator &>(constOp); 1940 if (!op.hasAssemblyFormat()) 1941 return; 1942 1943 // Parse the format description. 1944 llvm::SourceMgr mgr; 1945 mgr.AddNewSourceBuffer( 1946 llvm::MemoryBuffer::getMemBuffer(op.getAssemblyFormat()), llvm::SMLoc()); 1947 OperationFormat format(op); 1948 if (failed(FormatParser(mgr, format, op).parse())) { 1949 // Exit the process if format errors are treated as fatal. 1950 if (formatErrorIsFatal) { 1951 // Invoke the interrupt handlers to run the file cleanup handlers. 1952 llvm::sys::RunInterruptHandlers(); 1953 std::exit(1); 1954 } 1955 return; 1956 } 1957 1958 // Generate the printer and parser based on the parsed format. 1959 format.genParser(op, opClass); 1960 format.genPrinter(op, opClass); 1961 } 1962