1 //===- Parser.cpp - MLIR Parser Implementation ----------------------------===// 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 // This file implements the parser for the MLIR textual form. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "Parser.h" 14 #include "AsmParserImpl.h" 15 #include "mlir/AsmParser/AsmParser.h" 16 #include "mlir/AsmParser/AsmParserState.h" 17 #include "mlir/AsmParser/CodeComplete.h" 18 #include "mlir/IR/AffineExpr.h" 19 #include "mlir/IR/AffineMap.h" 20 #include "mlir/IR/AsmState.h" 21 #include "mlir/IR/Attributes.h" 22 #include "mlir/IR/BuiltinAttributes.h" 23 #include "mlir/IR/BuiltinOps.h" 24 #include "mlir/IR/BuiltinTypes.h" 25 #include "mlir/IR/Diagnostics.h" 26 #include "mlir/IR/Dialect.h" 27 #include "mlir/IR/Location.h" 28 #include "mlir/IR/OpDefinition.h" 29 #include "mlir/IR/OpImplementation.h" 30 #include "mlir/IR/OperationSupport.h" 31 #include "mlir/IR/OwningOpRef.h" 32 #include "mlir/IR/Region.h" 33 #include "mlir/IR/Value.h" 34 #include "mlir/IR/Verifier.h" 35 #include "mlir/IR/Visitors.h" 36 #include "mlir/Support/LLVM.h" 37 #include "mlir/Support/TypeID.h" 38 #include "llvm/ADT/APFloat.h" 39 #include "llvm/ADT/DenseMap.h" 40 #include "llvm/ADT/PointerUnion.h" 41 #include "llvm/ADT/STLExtras.h" 42 #include "llvm/ADT/ScopeExit.h" 43 #include "llvm/ADT/Sequence.h" 44 #include "llvm/ADT/StringExtras.h" 45 #include "llvm/ADT/StringMap.h" 46 #include "llvm/ADT/StringSet.h" 47 #include "llvm/Support/Alignment.h" 48 #include "llvm/Support/Casting.h" 49 #include "llvm/Support/Endian.h" 50 #include "llvm/Support/ErrorHandling.h" 51 #include "llvm/Support/MathExtras.h" 52 #include "llvm/Support/PrettyStackTrace.h" 53 #include "llvm/Support/SourceMgr.h" 54 #include "llvm/Support/raw_ostream.h" 55 #include <algorithm> 56 #include <cassert> 57 #include <cstddef> 58 #include <cstdint> 59 #include <cstring> 60 #include <memory> 61 #include <optional> 62 #include <string> 63 #include <tuple> 64 #include <utility> 65 #include <vector> 66 67 using namespace mlir; 68 using namespace mlir::detail; 69 70 //===----------------------------------------------------------------------===// 71 // CodeComplete 72 //===----------------------------------------------------------------------===// 73 74 AsmParserCodeCompleteContext::~AsmParserCodeCompleteContext() = default; 75 76 //===----------------------------------------------------------------------===// 77 // Parser 78 //===----------------------------------------------------------------------===// 79 80 /// Parse a list of comma-separated items with an optional delimiter. If a 81 /// delimiter is provided, then an empty list is allowed. If not, then at 82 /// least one element will be parsed. 83 ParseResult 84 Parser::parseCommaSeparatedList(Delimiter delimiter, 85 function_ref<ParseResult()> parseElementFn, 86 StringRef contextMessage) { 87 switch (delimiter) { 88 case Delimiter::None: 89 break; 90 case Delimiter::OptionalParen: 91 if (getToken().isNot(Token::l_paren)) 92 return success(); 93 [[fallthrough]]; 94 case Delimiter::Paren: 95 if (parseToken(Token::l_paren, "expected '('" + contextMessage)) 96 return failure(); 97 // Check for empty list. 98 if (consumeIf(Token::r_paren)) 99 return success(); 100 break; 101 case Delimiter::OptionalLessGreater: 102 // Check for absent list. 103 if (getToken().isNot(Token::less)) 104 return success(); 105 [[fallthrough]]; 106 case Delimiter::LessGreater: 107 if (parseToken(Token::less, "expected '<'" + contextMessage)) 108 return success(); 109 // Check for empty list. 110 if (consumeIf(Token::greater)) 111 return success(); 112 break; 113 case Delimiter::OptionalSquare: 114 if (getToken().isNot(Token::l_square)) 115 return success(); 116 [[fallthrough]]; 117 case Delimiter::Square: 118 if (parseToken(Token::l_square, "expected '['" + contextMessage)) 119 return failure(); 120 // Check for empty list. 121 if (consumeIf(Token::r_square)) 122 return success(); 123 break; 124 case Delimiter::OptionalBraces: 125 if (getToken().isNot(Token::l_brace)) 126 return success(); 127 [[fallthrough]]; 128 case Delimiter::Braces: 129 if (parseToken(Token::l_brace, "expected '{'" + contextMessage)) 130 return failure(); 131 // Check for empty list. 132 if (consumeIf(Token::r_brace)) 133 return success(); 134 break; 135 } 136 137 // Non-empty case starts with an element. 138 if (parseElementFn()) 139 return failure(); 140 141 // Otherwise we have a list of comma separated elements. 142 while (consumeIf(Token::comma)) { 143 if (parseElementFn()) 144 return failure(); 145 } 146 147 switch (delimiter) { 148 case Delimiter::None: 149 return success(); 150 case Delimiter::OptionalParen: 151 case Delimiter::Paren: 152 return parseToken(Token::r_paren, "expected ')'" + contextMessage); 153 case Delimiter::OptionalLessGreater: 154 case Delimiter::LessGreater: 155 return parseToken(Token::greater, "expected '>'" + contextMessage); 156 case Delimiter::OptionalSquare: 157 case Delimiter::Square: 158 return parseToken(Token::r_square, "expected ']'" + contextMessage); 159 case Delimiter::OptionalBraces: 160 case Delimiter::Braces: 161 return parseToken(Token::r_brace, "expected '}'" + contextMessage); 162 } 163 llvm_unreachable("Unknown delimiter"); 164 } 165 166 /// Parse a comma-separated list of elements, terminated with an arbitrary 167 /// token. This allows empty lists if allowEmptyList is true. 168 /// 169 /// abstract-list ::= rightToken // if allowEmptyList == true 170 /// abstract-list ::= element (',' element)* rightToken 171 /// 172 ParseResult 173 Parser::parseCommaSeparatedListUntil(Token::Kind rightToken, 174 function_ref<ParseResult()> parseElement, 175 bool allowEmptyList) { 176 // Handle the empty case. 177 if (getToken().is(rightToken)) { 178 if (!allowEmptyList) 179 return emitWrongTokenError("expected list element"); 180 consumeToken(rightToken); 181 return success(); 182 } 183 184 if (parseCommaSeparatedList(parseElement) || 185 parseToken(rightToken, "expected ',' or '" + 186 Token::getTokenSpelling(rightToken) + "'")) 187 return failure(); 188 189 return success(); 190 } 191 192 InFlightDiagnostic Parser::emitError(const Twine &message) { 193 auto loc = state.curToken.getLoc(); 194 if (state.curToken.isNot(Token::eof)) 195 return emitError(loc, message); 196 197 // If the error is to be emitted at EOF, move it back one character. 198 return emitError(SMLoc::getFromPointer(loc.getPointer() - 1), message); 199 } 200 201 InFlightDiagnostic Parser::emitError(SMLoc loc, const Twine &message) { 202 auto diag = mlir::emitError(getEncodedSourceLocation(loc), message); 203 204 // If we hit a parse error in response to a lexer error, then the lexer 205 // already reported the error. 206 if (getToken().is(Token::error)) 207 diag.abandon(); 208 return diag; 209 } 210 211 /// Emit an error about a "wrong token". If the current token is at the 212 /// start of a source line, this will apply heuristics to back up and report 213 /// the error at the end of the previous line, which is where the expected 214 /// token is supposed to be. 215 InFlightDiagnostic Parser::emitWrongTokenError(const Twine &message) { 216 auto loc = state.curToken.getLoc(); 217 218 // If the error is to be emitted at EOF, move it back one character. 219 if (state.curToken.is(Token::eof)) 220 loc = SMLoc::getFromPointer(loc.getPointer() - 1); 221 222 // This is the location we were originally asked to report the error at. 223 auto originalLoc = loc; 224 225 // Determine if the token is at the start of the current line. 226 const char *bufferStart = state.lex.getBufferBegin(); 227 const char *curPtr = loc.getPointer(); 228 229 // Use this StringRef to keep track of what we are going to back up through, 230 // it provides nicer string search functions etc. 231 StringRef startOfBuffer(bufferStart, curPtr - bufferStart); 232 233 // Back up over entirely blank lines. 234 while (true) { 235 // Back up until we see a \n, but don't look past the buffer start. 236 startOfBuffer = startOfBuffer.rtrim(" \t"); 237 238 // For tokens with no preceding source line, just emit at the original 239 // location. 240 if (startOfBuffer.empty()) 241 return emitError(originalLoc, message); 242 243 // If we found something that isn't the end of line, then we're done. 244 if (startOfBuffer.back() != '\n' && startOfBuffer.back() != '\r') 245 return emitError(SMLoc::getFromPointer(startOfBuffer.end()), message); 246 247 // Drop the \n so we emit the diagnostic at the end of the line. 248 startOfBuffer = startOfBuffer.drop_back(); 249 250 // Check to see if the preceding line has a comment on it. We assume that a 251 // `//` is the start of a comment, which is mostly correct. 252 // TODO: This will do the wrong thing for // in a string literal. 253 auto prevLine = startOfBuffer; 254 size_t newLineIndex = prevLine.find_last_of("\n\r"); 255 if (newLineIndex != StringRef::npos) 256 prevLine = prevLine.drop_front(newLineIndex); 257 258 // If we find a // in the current line, then emit the diagnostic before it. 259 size_t commentStart = prevLine.find("//"); 260 if (commentStart != StringRef::npos) 261 startOfBuffer = startOfBuffer.drop_back(prevLine.size() - commentStart); 262 } 263 } 264 265 /// Consume the specified token if present and return success. On failure, 266 /// output a diagnostic and return failure. 267 ParseResult Parser::parseToken(Token::Kind expectedToken, 268 const Twine &message) { 269 if (consumeIf(expectedToken)) 270 return success(); 271 return emitWrongTokenError(message); 272 } 273 274 /// Parse an optional integer value from the stream. 275 OptionalParseResult Parser::parseOptionalInteger(APInt &result) { 276 // Parse `false` and `true` keywords as 0 and 1 respectively. 277 if (consumeIf(Token::kw_false)) { 278 result = false; 279 return success(); 280 } 281 if (consumeIf(Token::kw_true)) { 282 result = true; 283 return success(); 284 } 285 286 Token curToken = getToken(); 287 if (curToken.isNot(Token::integer, Token::minus)) 288 return std::nullopt; 289 290 bool negative = consumeIf(Token::minus); 291 Token curTok = getToken(); 292 if (parseToken(Token::integer, "expected integer value")) 293 return failure(); 294 295 StringRef spelling = curTok.getSpelling(); 296 bool isHex = spelling.size() > 1 && spelling[1] == 'x'; 297 if (spelling.getAsInteger(isHex ? 0 : 10, result)) 298 return emitError(curTok.getLoc(), "integer value too large"); 299 300 // Make sure we have a zero at the top so we return the right signedness. 301 if (result.isNegative()) 302 result = result.zext(result.getBitWidth() + 1); 303 304 // Process the negative sign if present. 305 if (negative) 306 result.negate(); 307 308 return success(); 309 } 310 311 /// Parse an optional integer value only in decimal format from the stream. 312 OptionalParseResult Parser::parseOptionalDecimalInteger(APInt &result) { 313 Token curToken = getToken(); 314 if (curToken.isNot(Token::integer, Token::minus)) { 315 return std::nullopt; 316 } 317 318 bool negative = consumeIf(Token::minus); 319 Token curTok = getToken(); 320 if (parseToken(Token::integer, "expected integer value")) { 321 return failure(); 322 } 323 324 StringRef spelling = curTok.getSpelling(); 325 // If the integer is in hexadecimal return only the 0. The lexer has already 326 // moved past the entire hexidecimal encoded integer so we reset the lex 327 // pointer to just past the 0 we actualy want to consume. 328 if (spelling[0] == '0' && spelling.size() > 1 && 329 llvm::toLower(spelling[1]) == 'x') { 330 result = 0; 331 state.lex.resetPointer(spelling.data() + 1); 332 consumeToken(); 333 return success(); 334 } 335 336 if (spelling.getAsInteger(10, result)) 337 return emitError(curTok.getLoc(), "integer value too large"); 338 339 // Make sure we have a zero at the top so we return the right signedness. 340 if (result.isNegative()) 341 result = result.zext(result.getBitWidth() + 1); 342 343 // Process the negative sign if present. 344 if (negative) 345 result.negate(); 346 347 return success(); 348 } 349 350 ParseResult Parser::parseFloatFromLiteral(std::optional<APFloat> &result, 351 const Token &tok, bool isNegative, 352 const llvm::fltSemantics &semantics) { 353 // Check for a floating point value. 354 if (tok.is(Token::floatliteral)) { 355 auto val = tok.getFloatingPointValue(); 356 if (!val) 357 return emitError(tok.getLoc()) << "floating point value too large"; 358 359 result.emplace(isNegative ? -*val : *val); 360 bool unused; 361 result->convert(semantics, APFloat::rmNearestTiesToEven, &unused); 362 return success(); 363 } 364 365 // Check for a hexadecimal float value. 366 if (tok.is(Token::integer)) 367 return parseFloatFromIntegerLiteral(result, tok, isNegative, semantics); 368 369 return emitError(tok.getLoc()) << "expected floating point literal"; 370 } 371 372 /// Parse a floating point value from an integer literal token. 373 ParseResult 374 Parser::parseFloatFromIntegerLiteral(std::optional<APFloat> &result, 375 const Token &tok, bool isNegative, 376 const llvm::fltSemantics &semantics) { 377 StringRef spelling = tok.getSpelling(); 378 bool isHex = spelling.size() > 1 && spelling[1] == 'x'; 379 if (!isHex) { 380 return emitError(tok.getLoc(), "unexpected decimal integer literal for a " 381 "floating point value") 382 .attachNote() 383 << "add a trailing dot to make the literal a float"; 384 } 385 if (isNegative) { 386 return emitError(tok.getLoc(), 387 "hexadecimal float literal should not have a " 388 "leading minus"); 389 } 390 391 APInt intValue; 392 tok.getSpelling().getAsInteger(isHex ? 0 : 10, intValue); 393 auto typeSizeInBits = APFloat::semanticsSizeInBits(semantics); 394 if (intValue.getActiveBits() > typeSizeInBits) { 395 return emitError(tok.getLoc(), 396 "hexadecimal float constant out of range for type"); 397 } 398 399 APInt truncatedValue(typeSizeInBits, intValue.getNumWords(), 400 intValue.getRawData()); 401 result.emplace(semantics, truncatedValue); 402 return success(); 403 } 404 405 ParseResult Parser::parseOptionalKeyword(StringRef *keyword) { 406 // Check that the current token is a keyword. 407 if (!isCurrentTokenAKeyword()) 408 return failure(); 409 410 *keyword = getTokenSpelling(); 411 consumeToken(); 412 return success(); 413 } 414 415 //===----------------------------------------------------------------------===// 416 // Resource Parsing 417 418 FailureOr<AsmDialectResourceHandle> 419 Parser::parseResourceHandle(const OpAsmDialectInterface *dialect, 420 StringRef &name) { 421 assert(dialect && "expected valid dialect interface"); 422 SMLoc nameLoc = getToken().getLoc(); 423 if (failed(parseOptionalKeyword(&name))) 424 return emitError("expected identifier key for 'resource' entry"); 425 auto &resources = getState().symbols.dialectResources; 426 427 // If this is the first time encountering this handle, ask the dialect to 428 // resolve a reference to this handle. This allows for us to remap the name of 429 // the handle if necessary. 430 std::pair<std::string, AsmDialectResourceHandle> &entry = 431 resources[dialect][name]; 432 if (entry.first.empty()) { 433 FailureOr<AsmDialectResourceHandle> result = dialect->declareResource(name); 434 if (failed(result)) { 435 return emitError(nameLoc) 436 << "unknown 'resource' key '" << name << "' for dialect '" 437 << dialect->getDialect()->getNamespace() << "'"; 438 } 439 entry.first = dialect->getResourceKey(*result); 440 entry.second = *result; 441 } 442 443 name = entry.first; 444 return entry.second; 445 } 446 447 FailureOr<AsmDialectResourceHandle> 448 Parser::parseResourceHandle(Dialect *dialect) { 449 const auto *interface = dyn_cast<OpAsmDialectInterface>(dialect); 450 if (!interface) { 451 return emitError() << "dialect '" << dialect->getNamespace() 452 << "' does not expect resource handles"; 453 } 454 StringRef resourceName; 455 return parseResourceHandle(interface, resourceName); 456 } 457 458 //===----------------------------------------------------------------------===// 459 // Code Completion 460 461 ParseResult Parser::codeCompleteDialectName() { 462 state.codeCompleteContext->completeDialectName(); 463 return failure(); 464 } 465 466 ParseResult Parser::codeCompleteOperationName(StringRef dialectName) { 467 // Perform some simple validation on the dialect name. This doesn't need to be 468 // extensive, it's more of an optimization (to avoid checking completion 469 // results when we know they will fail). 470 if (dialectName.empty() || dialectName.contains('.')) 471 return failure(); 472 state.codeCompleteContext->completeOperationName(dialectName); 473 return failure(); 474 } 475 476 ParseResult Parser::codeCompleteDialectOrElidedOpName(SMLoc loc) { 477 // Check to see if there is anything else on the current line. This check 478 // isn't strictly necessary, but it does avoid unnecessarily triggering 479 // completions for operations and dialects in situations where we don't want 480 // them (e.g. at the end of an operation). 481 auto shouldIgnoreOpCompletion = [&]() { 482 const char *bufBegin = state.lex.getBufferBegin(); 483 const char *it = loc.getPointer() - 1; 484 for (; it > bufBegin && *it != '\n'; --it) 485 if (!StringRef(" \t\r").contains(*it)) 486 return true; 487 return false; 488 }; 489 if (shouldIgnoreOpCompletion()) 490 return failure(); 491 492 // The completion here is either for a dialect name, or an operation name 493 // whose dialect prefix was elided. For this we simply invoke both of the 494 // individual completion methods. 495 (void)codeCompleteDialectName(); 496 return codeCompleteOperationName(state.defaultDialectStack.back()); 497 } 498 499 ParseResult Parser::codeCompleteStringDialectOrOperationName(StringRef name) { 500 // If the name is empty, this is the start of the string and contains the 501 // dialect. 502 if (name.empty()) 503 return codeCompleteDialectName(); 504 505 // Otherwise, we treat this as completing an operation name. The current name 506 // is used as the dialect namespace. 507 if (name.consume_back(".")) 508 return codeCompleteOperationName(name); 509 return failure(); 510 } 511 512 ParseResult Parser::codeCompleteExpectedTokens(ArrayRef<StringRef> tokens) { 513 state.codeCompleteContext->completeExpectedTokens(tokens, /*optional=*/false); 514 return failure(); 515 } 516 ParseResult Parser::codeCompleteOptionalTokens(ArrayRef<StringRef> tokens) { 517 state.codeCompleteContext->completeExpectedTokens(tokens, /*optional=*/true); 518 return failure(); 519 } 520 521 Attribute Parser::codeCompleteAttribute() { 522 state.codeCompleteContext->completeAttribute( 523 state.symbols.attributeAliasDefinitions); 524 return {}; 525 } 526 Type Parser::codeCompleteType() { 527 state.codeCompleteContext->completeType(state.symbols.typeAliasDefinitions); 528 return {}; 529 } 530 531 Attribute 532 Parser::codeCompleteDialectSymbol(const llvm::StringMap<Attribute> &aliases) { 533 state.codeCompleteContext->completeDialectAttributeOrAlias(aliases); 534 return {}; 535 } 536 Type Parser::codeCompleteDialectSymbol(const llvm::StringMap<Type> &aliases) { 537 state.codeCompleteContext->completeDialectTypeOrAlias(aliases); 538 return {}; 539 } 540 541 //===----------------------------------------------------------------------===// 542 // OperationParser 543 //===----------------------------------------------------------------------===// 544 545 namespace { 546 /// This class provides support for parsing operations and regions of 547 /// operations. 548 class OperationParser : public Parser { 549 public: 550 OperationParser(ParserState &state, ModuleOp topLevelOp); 551 ~OperationParser(); 552 553 /// After parsing is finished, this function must be called to see if there 554 /// are any remaining issues. 555 ParseResult finalize(); 556 557 //===--------------------------------------------------------------------===// 558 // SSA Value Handling 559 //===--------------------------------------------------------------------===// 560 561 using UnresolvedOperand = OpAsmParser::UnresolvedOperand; 562 using Argument = OpAsmParser::Argument; 563 564 struct DeferredLocInfo { 565 SMLoc loc; 566 StringRef identifier; 567 }; 568 569 /// Push a new SSA name scope to the parser. 570 void pushSSANameScope(bool isIsolated); 571 572 /// Pop the last SSA name scope from the parser. 573 ParseResult popSSANameScope(); 574 575 /// Register a definition of a value with the symbol table. 576 ParseResult addDefinition(UnresolvedOperand useInfo, Value value); 577 578 /// Parse an optional list of SSA uses into 'results'. 579 ParseResult 580 parseOptionalSSAUseList(SmallVectorImpl<UnresolvedOperand> &results); 581 582 /// Parse a single SSA use into 'result'. If 'allowResultNumber' is true then 583 /// we allow #42 syntax. 584 ParseResult parseSSAUse(UnresolvedOperand &result, 585 bool allowResultNumber = true); 586 587 /// Given a reference to an SSA value and its type, return a reference. This 588 /// returns null on failure. 589 Value resolveSSAUse(UnresolvedOperand useInfo, Type type); 590 591 ParseResult parseSSADefOrUseAndType( 592 function_ref<ParseResult(UnresolvedOperand, Type)> action); 593 594 ParseResult parseOptionalSSAUseAndTypeList(SmallVectorImpl<Value> &results); 595 596 /// Return the location of the value identified by its name and number if it 597 /// has been already reference. 598 std::optional<SMLoc> getReferenceLoc(StringRef name, unsigned number) { 599 auto &values = isolatedNameScopes.back().values; 600 if (!values.count(name) || number >= values[name].size()) 601 return {}; 602 if (values[name][number].value) 603 return values[name][number].loc; 604 return {}; 605 } 606 607 //===--------------------------------------------------------------------===// 608 // Operation Parsing 609 //===--------------------------------------------------------------------===// 610 611 /// Parse an operation instance. 612 ParseResult parseOperation(); 613 614 /// Parse a single operation successor. 615 ParseResult parseSuccessor(Block *&dest); 616 617 /// Parse a comma-separated list of operation successors in brackets. 618 ParseResult parseSuccessors(SmallVectorImpl<Block *> &destinations); 619 620 /// Parse an operation instance that is in the generic form. 621 Operation *parseGenericOperation(); 622 623 /// Parse different components, viz., use-info of operand(s), successor(s), 624 /// region(s), attribute(s) and function-type, of the generic form of an 625 /// operation instance and populate the input operation-state 'result' with 626 /// those components. If any of the components is explicitly provided, then 627 /// skip parsing that component. 628 ParseResult parseGenericOperationAfterOpName( 629 OperationState &result, 630 std::optional<ArrayRef<UnresolvedOperand>> parsedOperandUseInfo = 631 std::nullopt, 632 std::optional<ArrayRef<Block *>> parsedSuccessors = std::nullopt, 633 std::optional<MutableArrayRef<std::unique_ptr<Region>>> parsedRegions = 634 std::nullopt, 635 std::optional<ArrayRef<NamedAttribute>> parsedAttributes = std::nullopt, 636 std::optional<Attribute> propertiesAttribute = std::nullopt, 637 std::optional<FunctionType> parsedFnType = std::nullopt); 638 639 /// Parse an operation instance that is in the generic form and insert it at 640 /// the provided insertion point. 641 Operation *parseGenericOperation(Block *insertBlock, 642 Block::iterator insertPt); 643 644 /// This type is used to keep track of things that are either an Operation or 645 /// a BlockArgument. We cannot use Value for this, because not all Operations 646 /// have results. 647 using OpOrArgument = llvm::PointerUnion<Operation *, BlockArgument>; 648 649 /// Parse an optional trailing location and add it to the specifier Operation 650 /// or `UnresolvedOperand` if present. 651 /// 652 /// trailing-location ::= (`loc` (`(` location `)` | attribute-alias))? 653 /// 654 ParseResult parseTrailingLocationSpecifier(OpOrArgument opOrArgument); 655 656 /// Parse a location alias, that is a sequence looking like: #loc42 657 /// The alias may have already be defined or may be defined later, in which 658 /// case an OpaqueLoc is used a placeholder. The caller must ensure that the 659 /// token is actually an alias, which means it must not contain a dot. 660 ParseResult parseLocationAlias(LocationAttr &loc); 661 662 /// This is the structure of a result specifier in the assembly syntax, 663 /// including the name, number of results, and location. 664 using ResultRecord = std::tuple<StringRef, unsigned, SMLoc>; 665 666 /// Parse an operation instance that is in the op-defined custom form. 667 /// resultInfo specifies information about the "%name =" specifiers. 668 Operation *parseCustomOperation(ArrayRef<ResultRecord> resultIDs); 669 670 /// Parse the name of an operation, in the custom form. On success, return a 671 /// an object of type 'OperationName'. Otherwise, failure is returned. 672 FailureOr<OperationName> parseCustomOperationName(); 673 674 //===--------------------------------------------------------------------===// 675 // Region Parsing 676 //===--------------------------------------------------------------------===// 677 678 /// Parse a region into 'region' with the provided entry block arguments. 679 /// 'isIsolatedNameScope' indicates if the naming scope of this region is 680 /// isolated from those above. 681 ParseResult parseRegion(Region ®ion, ArrayRef<Argument> entryArguments, 682 bool isIsolatedNameScope = false); 683 684 /// Parse a region body into 'region'. 685 ParseResult parseRegionBody(Region ®ion, SMLoc startLoc, 686 ArrayRef<Argument> entryArguments, 687 bool isIsolatedNameScope); 688 689 //===--------------------------------------------------------------------===// 690 // Block Parsing 691 //===--------------------------------------------------------------------===// 692 693 /// Parse a new block into 'block'. 694 ParseResult parseBlock(Block *&block); 695 696 /// Parse a list of operations into 'block'. 697 ParseResult parseBlockBody(Block *block); 698 699 /// Parse a (possibly empty) list of block arguments. 700 ParseResult parseOptionalBlockArgList(Block *owner); 701 702 /// Get the block with the specified name, creating it if it doesn't 703 /// already exist. The location specified is the point of use, which allows 704 /// us to diagnose references to blocks that are not defined precisely. 705 Block *getBlockNamed(StringRef name, SMLoc loc); 706 707 //===--------------------------------------------------------------------===// 708 // Code Completion 709 //===--------------------------------------------------------------------===// 710 711 /// The set of various code completion methods. Every completion method 712 /// returns `failure` to stop the parsing process after providing completion 713 /// results. 714 715 ParseResult codeCompleteSSAUse(); 716 ParseResult codeCompleteBlock(); 717 718 private: 719 /// This class represents a definition of a Block. 720 struct BlockDefinition { 721 /// A pointer to the defined Block. 722 Block *block; 723 /// The location that the Block was defined at. 724 SMLoc loc; 725 }; 726 /// This class represents a definition of a Value. 727 struct ValueDefinition { 728 /// A pointer to the defined Value. 729 Value value; 730 /// The location that the Value was defined at. 731 SMLoc loc; 732 }; 733 734 /// Returns the info for a block at the current scope for the given name. 735 BlockDefinition &getBlockInfoByName(StringRef name) { 736 return blocksByName.back()[name]; 737 } 738 739 /// Insert a new forward reference to the given block. 740 void insertForwardRef(Block *block, SMLoc loc) { 741 forwardRef.back().try_emplace(block, loc); 742 } 743 744 /// Erase any forward reference to the given block. 745 bool eraseForwardRef(Block *block) { return forwardRef.back().erase(block); } 746 747 /// Record that a definition was added at the current scope. 748 void recordDefinition(StringRef def); 749 750 /// Get the value entry for the given SSA name. 751 SmallVectorImpl<ValueDefinition> &getSSAValueEntry(StringRef name); 752 753 /// Create a forward reference placeholder value with the given location and 754 /// result type. 755 Value createForwardRefPlaceholder(SMLoc loc, Type type); 756 757 /// Return true if this is a forward reference. 758 bool isForwardRefPlaceholder(Value value) { 759 return forwardRefPlaceholders.count(value); 760 } 761 762 /// This struct represents an isolated SSA name scope. This scope may contain 763 /// other nested non-isolated scopes. These scopes are used for operations 764 /// that are known to be isolated to allow for reusing names within their 765 /// regions, even if those names are used above. 766 struct IsolatedSSANameScope { 767 /// Record that a definition was added at the current scope. 768 void recordDefinition(StringRef def) { 769 definitionsPerScope.back().insert(def); 770 } 771 772 /// Push a nested name scope. 773 void pushSSANameScope() { definitionsPerScope.push_back({}); } 774 775 /// Pop a nested name scope. 776 void popSSANameScope() { 777 for (auto &def : definitionsPerScope.pop_back_val()) 778 values.erase(def.getKey()); 779 } 780 781 /// This keeps track of all of the SSA values we are tracking for each name 782 /// scope, indexed by their name. This has one entry per result number. 783 llvm::StringMap<SmallVector<ValueDefinition, 1>> values; 784 785 /// This keeps track of all of the values defined by a specific name scope. 786 SmallVector<llvm::StringSet<>, 2> definitionsPerScope; 787 }; 788 789 /// A list of isolated name scopes. 790 SmallVector<IsolatedSSANameScope, 2> isolatedNameScopes; 791 792 /// This keeps track of the block names as well as the location of the first 793 /// reference for each nested name scope. This is used to diagnose invalid 794 /// block references and memorize them. 795 SmallVector<DenseMap<StringRef, BlockDefinition>, 2> blocksByName; 796 SmallVector<DenseMap<Block *, SMLoc>, 2> forwardRef; 797 798 /// These are all of the placeholders we've made along with the location of 799 /// their first reference, to allow checking for use of undefined values. 800 DenseMap<Value, SMLoc> forwardRefPlaceholders; 801 802 /// Deffered locations: when parsing `loc(#loc42)` we add an entry to this 803 /// map. After parsing the definition `#loc42 = ...` we'll patch back users 804 /// of this location. 805 std::vector<DeferredLocInfo> deferredLocsReferences; 806 807 /// The builder used when creating parsed operation instances. 808 OpBuilder opBuilder; 809 810 /// The top level operation that holds all of the parsed operations. 811 Operation *topLevelOp; 812 }; 813 } // namespace 814 815 MLIR_DECLARE_EXPLICIT_TYPE_ID(OperationParser::DeferredLocInfo *) 816 MLIR_DEFINE_EXPLICIT_TYPE_ID(OperationParser::DeferredLocInfo *) 817 818 OperationParser::OperationParser(ParserState &state, ModuleOp topLevelOp) 819 : Parser(state), opBuilder(topLevelOp.getRegion()), topLevelOp(topLevelOp) { 820 // The top level operation starts a new name scope. 821 pushSSANameScope(/*isIsolated=*/true); 822 823 // If we are populating the parser state, prepare it for parsing. 824 if (state.asmState) 825 state.asmState->initialize(topLevelOp); 826 } 827 828 OperationParser::~OperationParser() { 829 for (auto &fwd : forwardRefPlaceholders) { 830 // Drop all uses of undefined forward declared reference and destroy 831 // defining operation. 832 fwd.first.dropAllUses(); 833 fwd.first.getDefiningOp()->destroy(); 834 } 835 for (const auto &scope : forwardRef) { 836 for (const auto &fwd : scope) { 837 // Delete all blocks that were created as forward references but never 838 // included into a region. 839 fwd.first->dropAllUses(); 840 delete fwd.first; 841 } 842 } 843 } 844 845 /// After parsing is finished, this function must be called to see if there are 846 /// any remaining issues. 847 ParseResult OperationParser::finalize() { 848 // Check for any forward references that are left. If we find any, error 849 // out. 850 if (!forwardRefPlaceholders.empty()) { 851 SmallVector<const char *, 4> errors; 852 // Iteration over the map isn't deterministic, so sort by source location. 853 for (auto entry : forwardRefPlaceholders) 854 errors.push_back(entry.second.getPointer()); 855 llvm::array_pod_sort(errors.begin(), errors.end()); 856 857 for (const char *entry : errors) { 858 auto loc = SMLoc::getFromPointer(entry); 859 emitError(loc, "use of undeclared SSA value name"); 860 } 861 return failure(); 862 } 863 864 // Resolve the locations of any deferred operations. 865 auto &attributeAliases = state.symbols.attributeAliasDefinitions; 866 auto locID = TypeID::get<DeferredLocInfo *>(); 867 auto resolveLocation = [&, this](auto &opOrArgument) -> LogicalResult { 868 auto fwdLoc = dyn_cast<OpaqueLoc>(opOrArgument.getLoc()); 869 if (!fwdLoc || fwdLoc.getUnderlyingTypeID() != locID) 870 return success(); 871 auto locInfo = deferredLocsReferences[fwdLoc.getUnderlyingLocation()]; 872 Attribute attr = attributeAliases.lookup(locInfo.identifier); 873 if (!attr) 874 return this->emitError(locInfo.loc) 875 << "operation location alias was never defined"; 876 auto locAttr = dyn_cast<LocationAttr>(attr); 877 if (!locAttr) 878 return this->emitError(locInfo.loc) 879 << "expected location, but found '" << attr << "'"; 880 opOrArgument.setLoc(locAttr); 881 return success(); 882 }; 883 884 auto walkRes = topLevelOp->walk([&](Operation *op) { 885 if (failed(resolveLocation(*op))) 886 return WalkResult::interrupt(); 887 for (Region ®ion : op->getRegions()) 888 for (Block &block : region.getBlocks()) 889 for (BlockArgument arg : block.getArguments()) 890 if (failed(resolveLocation(arg))) 891 return WalkResult::interrupt(); 892 return WalkResult::advance(); 893 }); 894 if (walkRes.wasInterrupted()) 895 return failure(); 896 897 // Pop the top level name scope. 898 if (failed(popSSANameScope())) 899 return failure(); 900 901 // Verify that the parsed operations are valid. 902 if (state.config.shouldVerifyAfterParse() && failed(verify(topLevelOp))) 903 return failure(); 904 905 // If we are populating the parser state, finalize the top-level operation. 906 if (state.asmState) 907 state.asmState->finalize(topLevelOp); 908 return success(); 909 } 910 911 //===----------------------------------------------------------------------===// 912 // SSA Value Handling 913 //===----------------------------------------------------------------------===// 914 915 void OperationParser::pushSSANameScope(bool isIsolated) { 916 blocksByName.push_back(DenseMap<StringRef, BlockDefinition>()); 917 forwardRef.push_back(DenseMap<Block *, SMLoc>()); 918 919 // Push back a new name definition scope. 920 if (isIsolated) 921 isolatedNameScopes.push_back({}); 922 isolatedNameScopes.back().pushSSANameScope(); 923 } 924 925 ParseResult OperationParser::popSSANameScope() { 926 auto forwardRefInCurrentScope = forwardRef.pop_back_val(); 927 928 // Verify that all referenced blocks were defined. 929 if (!forwardRefInCurrentScope.empty()) { 930 SmallVector<std::pair<const char *, Block *>, 4> errors; 931 // Iteration over the map isn't deterministic, so sort by source location. 932 for (auto entry : forwardRefInCurrentScope) { 933 errors.push_back({entry.second.getPointer(), entry.first}); 934 // Add this block to the top-level region to allow for automatic cleanup. 935 topLevelOp->getRegion(0).push_back(entry.first); 936 } 937 llvm::array_pod_sort(errors.begin(), errors.end()); 938 939 for (auto entry : errors) { 940 auto loc = SMLoc::getFromPointer(entry.first); 941 emitError(loc, "reference to an undefined block"); 942 } 943 return failure(); 944 } 945 946 // Pop the next nested namescope. If there is only one internal namescope, 947 // just pop the isolated scope. 948 auto ¤tNameScope = isolatedNameScopes.back(); 949 if (currentNameScope.definitionsPerScope.size() == 1) 950 isolatedNameScopes.pop_back(); 951 else 952 currentNameScope.popSSANameScope(); 953 954 blocksByName.pop_back(); 955 return success(); 956 } 957 958 /// Register a definition of a value with the symbol table. 959 ParseResult OperationParser::addDefinition(UnresolvedOperand useInfo, 960 Value value) { 961 auto &entries = getSSAValueEntry(useInfo.name); 962 963 // Make sure there is a slot for this value. 964 if (entries.size() <= useInfo.number) 965 entries.resize(useInfo.number + 1); 966 967 // If we already have an entry for this, check to see if it was a definition 968 // or a forward reference. 969 if (auto existing = entries[useInfo.number].value) { 970 if (!isForwardRefPlaceholder(existing)) { 971 return emitError(useInfo.location) 972 .append("redefinition of SSA value '", useInfo.name, "'") 973 .attachNote(getEncodedSourceLocation(entries[useInfo.number].loc)) 974 .append("previously defined here"); 975 } 976 977 if (existing.getType() != value.getType()) { 978 return emitError(useInfo.location) 979 .append("definition of SSA value '", useInfo.name, "#", 980 useInfo.number, "' has type ", value.getType()) 981 .attachNote(getEncodedSourceLocation(entries[useInfo.number].loc)) 982 .append("previously used here with type ", existing.getType()); 983 } 984 985 // If it was a forward reference, update everything that used it to use 986 // the actual definition instead, delete the forward ref, and remove it 987 // from our set of forward references we track. 988 existing.replaceAllUsesWith(value); 989 existing.getDefiningOp()->destroy(); 990 forwardRefPlaceholders.erase(existing); 991 992 // If a definition of the value already exists, replace it in the assembly 993 // state. 994 if (state.asmState) 995 state.asmState->refineDefinition(existing, value); 996 } 997 998 /// Record this definition for the current scope. 999 entries[useInfo.number] = {value, useInfo.location}; 1000 recordDefinition(useInfo.name); 1001 return success(); 1002 } 1003 1004 /// Parse a (possibly empty) list of SSA operands. 1005 /// 1006 /// ssa-use-list ::= ssa-use (`,` ssa-use)* 1007 /// ssa-use-list-opt ::= ssa-use-list? 1008 /// 1009 ParseResult OperationParser::parseOptionalSSAUseList( 1010 SmallVectorImpl<UnresolvedOperand> &results) { 1011 if (!getToken().isOrIsCodeCompletionFor(Token::percent_identifier)) 1012 return success(); 1013 return parseCommaSeparatedList([&]() -> ParseResult { 1014 UnresolvedOperand result; 1015 if (parseSSAUse(result)) 1016 return failure(); 1017 results.push_back(result); 1018 return success(); 1019 }); 1020 } 1021 1022 /// Parse a SSA operand for an operation. 1023 /// 1024 /// ssa-use ::= ssa-id 1025 /// 1026 ParseResult OperationParser::parseSSAUse(UnresolvedOperand &result, 1027 bool allowResultNumber) { 1028 if (getToken().isCodeCompletion()) 1029 return codeCompleteSSAUse(); 1030 1031 result.name = getTokenSpelling(); 1032 result.number = 0; 1033 result.location = getToken().getLoc(); 1034 if (parseToken(Token::percent_identifier, "expected SSA operand")) 1035 return failure(); 1036 1037 // If we have an attribute ID, it is a result number. 1038 if (getToken().is(Token::hash_identifier)) { 1039 if (!allowResultNumber) 1040 return emitError("result number not allowed in argument list"); 1041 1042 if (auto value = getToken().getHashIdentifierNumber()) 1043 result.number = *value; 1044 else 1045 return emitError("invalid SSA value result number"); 1046 consumeToken(Token::hash_identifier); 1047 } 1048 1049 return success(); 1050 } 1051 1052 /// Given an unbound reference to an SSA value and its type, return the value 1053 /// it specifies. This returns null on failure. 1054 Value OperationParser::resolveSSAUse(UnresolvedOperand useInfo, Type type) { 1055 auto &entries = getSSAValueEntry(useInfo.name); 1056 1057 // Functor used to record the use of the given value if the assembly state 1058 // field is populated. 1059 auto maybeRecordUse = [&](Value value) { 1060 if (state.asmState) 1061 state.asmState->addUses(value, useInfo.location); 1062 return value; 1063 }; 1064 1065 // If we have already seen a value of this name, return it. 1066 if (useInfo.number < entries.size() && entries[useInfo.number].value) { 1067 Value result = entries[useInfo.number].value; 1068 // Check that the type matches the other uses. 1069 if (result.getType() == type) 1070 return maybeRecordUse(result); 1071 1072 emitError(useInfo.location, "use of value '") 1073 .append(useInfo.name, 1074 "' expects different type than prior uses: ", type, " vs ", 1075 result.getType()) 1076 .attachNote(getEncodedSourceLocation(entries[useInfo.number].loc)) 1077 .append("prior use here"); 1078 return nullptr; 1079 } 1080 1081 // Make sure we have enough slots for this. 1082 if (entries.size() <= useInfo.number) 1083 entries.resize(useInfo.number + 1); 1084 1085 // If the value has already been defined and this is an overly large result 1086 // number, diagnose that. 1087 if (entries[0].value && !isForwardRefPlaceholder(entries[0].value)) 1088 return (emitError(useInfo.location, "reference to invalid result number"), 1089 nullptr); 1090 1091 // Otherwise, this is a forward reference. Create a placeholder and remember 1092 // that we did so. 1093 Value result = createForwardRefPlaceholder(useInfo.location, type); 1094 entries[useInfo.number] = {result, useInfo.location}; 1095 return maybeRecordUse(result); 1096 } 1097 1098 /// Parse an SSA use with an associated type. 1099 /// 1100 /// ssa-use-and-type ::= ssa-use `:` type 1101 ParseResult OperationParser::parseSSADefOrUseAndType( 1102 function_ref<ParseResult(UnresolvedOperand, Type)> action) { 1103 UnresolvedOperand useInfo; 1104 if (parseSSAUse(useInfo) || 1105 parseToken(Token::colon, "expected ':' and type for SSA operand")) 1106 return failure(); 1107 1108 auto type = parseType(); 1109 if (!type) 1110 return failure(); 1111 1112 return action(useInfo, type); 1113 } 1114 1115 /// Parse a (possibly empty) list of SSA operands, followed by a colon, then 1116 /// followed by a type list. 1117 /// 1118 /// ssa-use-and-type-list 1119 /// ::= ssa-use-list ':' type-list-no-parens 1120 /// 1121 ParseResult OperationParser::parseOptionalSSAUseAndTypeList( 1122 SmallVectorImpl<Value> &results) { 1123 SmallVector<UnresolvedOperand, 4> valueIDs; 1124 if (parseOptionalSSAUseList(valueIDs)) 1125 return failure(); 1126 1127 // If there were no operands, then there is no colon or type lists. 1128 if (valueIDs.empty()) 1129 return success(); 1130 1131 SmallVector<Type, 4> types; 1132 if (parseToken(Token::colon, "expected ':' in operand list") || 1133 parseTypeListNoParens(types)) 1134 return failure(); 1135 1136 if (valueIDs.size() != types.size()) 1137 return emitError("expected ") 1138 << valueIDs.size() << " types to match operand list"; 1139 1140 results.reserve(valueIDs.size()); 1141 for (unsigned i = 0, e = valueIDs.size(); i != e; ++i) { 1142 if (auto value = resolveSSAUse(valueIDs[i], types[i])) 1143 results.push_back(value); 1144 else 1145 return failure(); 1146 } 1147 1148 return success(); 1149 } 1150 1151 /// Record that a definition was added at the current scope. 1152 void OperationParser::recordDefinition(StringRef def) { 1153 isolatedNameScopes.back().recordDefinition(def); 1154 } 1155 1156 /// Get the value entry for the given SSA name. 1157 auto OperationParser::getSSAValueEntry(StringRef name) 1158 -> SmallVectorImpl<ValueDefinition> & { 1159 return isolatedNameScopes.back().values[name]; 1160 } 1161 1162 /// Create and remember a new placeholder for a forward reference. 1163 Value OperationParser::createForwardRefPlaceholder(SMLoc loc, Type type) { 1164 // Forward references are always created as operations, because we just need 1165 // something with a def/use chain. 1166 // 1167 // We create these placeholders as having an empty name, which we know 1168 // cannot be created through normal user input, allowing us to distinguish 1169 // them. 1170 auto name = OperationName("builtin.unrealized_conversion_cast", getContext()); 1171 auto *op = Operation::create( 1172 getEncodedSourceLocation(loc), name, type, /*operands=*/{}, 1173 /*attributes=*/std::nullopt, /*properties=*/nullptr, /*successors=*/{}, 1174 /*numRegions=*/0); 1175 forwardRefPlaceholders[op->getResult(0)] = loc; 1176 return op->getResult(0); 1177 } 1178 1179 //===----------------------------------------------------------------------===// 1180 // Operation Parsing 1181 //===----------------------------------------------------------------------===// 1182 1183 /// Parse an operation. 1184 /// 1185 /// operation ::= op-result-list? 1186 /// (generic-operation | custom-operation) 1187 /// trailing-location? 1188 /// generic-operation ::= string-literal `(` ssa-use-list? `)` 1189 /// successor-list? (`(` region-list `)`)? 1190 /// attribute-dict? `:` function-type 1191 /// custom-operation ::= bare-id custom-operation-format 1192 /// op-result-list ::= op-result (`,` op-result)* `=` 1193 /// op-result ::= ssa-id (`:` integer-literal) 1194 /// 1195 ParseResult OperationParser::parseOperation() { 1196 auto loc = getToken().getLoc(); 1197 SmallVector<ResultRecord, 1> resultIDs; 1198 size_t numExpectedResults = 0; 1199 if (getToken().is(Token::percent_identifier)) { 1200 // Parse the group of result ids. 1201 auto parseNextResult = [&]() -> ParseResult { 1202 // Parse the next result id. 1203 Token nameTok = getToken(); 1204 if (parseToken(Token::percent_identifier, 1205 "expected valid ssa identifier")) 1206 return failure(); 1207 1208 // If the next token is a ':', we parse the expected result count. 1209 size_t expectedSubResults = 1; 1210 if (consumeIf(Token::colon)) { 1211 // Check that the next token is an integer. 1212 if (!getToken().is(Token::integer)) 1213 return emitWrongTokenError("expected integer number of results"); 1214 1215 // Check that number of results is > 0. 1216 auto val = getToken().getUInt64IntegerValue(); 1217 if (!val || *val < 1) 1218 return emitError( 1219 "expected named operation to have at least 1 result"); 1220 consumeToken(Token::integer); 1221 expectedSubResults = *val; 1222 } 1223 1224 resultIDs.emplace_back(nameTok.getSpelling(), expectedSubResults, 1225 nameTok.getLoc()); 1226 numExpectedResults += expectedSubResults; 1227 return success(); 1228 }; 1229 if (parseCommaSeparatedList(parseNextResult)) 1230 return failure(); 1231 1232 if (parseToken(Token::equal, "expected '=' after SSA name")) 1233 return failure(); 1234 } 1235 1236 Operation *op; 1237 Token nameTok = getToken(); 1238 if (nameTok.is(Token::bare_identifier) || nameTok.isKeyword()) 1239 op = parseCustomOperation(resultIDs); 1240 else if (nameTok.is(Token::string)) 1241 op = parseGenericOperation(); 1242 else if (nameTok.isCodeCompletionFor(Token::string)) 1243 return codeCompleteStringDialectOrOperationName(nameTok.getStringValue()); 1244 else if (nameTok.isCodeCompletion()) 1245 return codeCompleteDialectOrElidedOpName(loc); 1246 else 1247 return emitWrongTokenError("expected operation name in quotes"); 1248 1249 // If parsing of the basic operation failed, then this whole thing fails. 1250 if (!op) 1251 return failure(); 1252 1253 // If the operation had a name, register it. 1254 if (!resultIDs.empty()) { 1255 if (op->getNumResults() == 0) 1256 return emitError(loc, "cannot name an operation with no results"); 1257 if (numExpectedResults != op->getNumResults()) 1258 return emitError(loc, "operation defines ") 1259 << op->getNumResults() << " results but was provided " 1260 << numExpectedResults << " to bind"; 1261 1262 // Add this operation to the assembly state if it was provided to populate. 1263 if (state.asmState) { 1264 unsigned resultIt = 0; 1265 SmallVector<std::pair<unsigned, SMLoc>> asmResultGroups; 1266 asmResultGroups.reserve(resultIDs.size()); 1267 for (ResultRecord &record : resultIDs) { 1268 asmResultGroups.emplace_back(resultIt, std::get<2>(record)); 1269 resultIt += std::get<1>(record); 1270 } 1271 state.asmState->finalizeOperationDefinition( 1272 op, nameTok.getLocRange(), /*endLoc=*/getLastToken().getEndLoc(), 1273 asmResultGroups); 1274 } 1275 1276 // Add definitions for each of the result groups. 1277 unsigned opResI = 0; 1278 for (ResultRecord &resIt : resultIDs) { 1279 for (unsigned subRes : llvm::seq<unsigned>(0, std::get<1>(resIt))) { 1280 if (addDefinition({std::get<2>(resIt), std::get<0>(resIt), subRes}, 1281 op->getResult(opResI++))) 1282 return failure(); 1283 } 1284 } 1285 1286 // Add this operation to the assembly state if it was provided to populate. 1287 } else if (state.asmState) { 1288 state.asmState->finalizeOperationDefinition( 1289 op, nameTok.getLocRange(), 1290 /*endLoc=*/getLastToken().getEndLoc()); 1291 } 1292 1293 return success(); 1294 } 1295 1296 /// Parse a single operation successor. 1297 /// 1298 /// successor ::= block-id 1299 /// 1300 ParseResult OperationParser::parseSuccessor(Block *&dest) { 1301 if (getToken().isCodeCompletion()) 1302 return codeCompleteBlock(); 1303 1304 // Verify branch is identifier and get the matching block. 1305 if (!getToken().is(Token::caret_identifier)) 1306 return emitWrongTokenError("expected block name"); 1307 dest = getBlockNamed(getTokenSpelling(), getToken().getLoc()); 1308 consumeToken(); 1309 return success(); 1310 } 1311 1312 /// Parse a comma-separated list of operation successors in brackets. 1313 /// 1314 /// successor-list ::= `[` successor (`,` successor )* `]` 1315 /// 1316 ParseResult 1317 OperationParser::parseSuccessors(SmallVectorImpl<Block *> &destinations) { 1318 if (parseToken(Token::l_square, "expected '['")) 1319 return failure(); 1320 1321 auto parseElt = [this, &destinations] { 1322 Block *dest; 1323 ParseResult res = parseSuccessor(dest); 1324 destinations.push_back(dest); 1325 return res; 1326 }; 1327 return parseCommaSeparatedListUntil(Token::r_square, parseElt, 1328 /*allowEmptyList=*/false); 1329 } 1330 1331 namespace { 1332 // RAII-style guard for cleaning up the regions in the operation state before 1333 // deleting them. Within the parser, regions may get deleted if parsing failed, 1334 // and other errors may be present, in particular undominated uses. This makes 1335 // sure such uses are deleted. 1336 struct CleanupOpStateRegions { 1337 ~CleanupOpStateRegions() { 1338 SmallVector<Region *, 4> regionsToClean; 1339 regionsToClean.reserve(state.regions.size()); 1340 for (auto ®ion : state.regions) 1341 if (region) 1342 for (auto &block : *region) 1343 block.dropAllDefinedValueUses(); 1344 } 1345 OperationState &state; 1346 }; 1347 } // namespace 1348 1349 ParseResult OperationParser::parseGenericOperationAfterOpName( 1350 OperationState &result, 1351 std::optional<ArrayRef<UnresolvedOperand>> parsedOperandUseInfo, 1352 std::optional<ArrayRef<Block *>> parsedSuccessors, 1353 std::optional<MutableArrayRef<std::unique_ptr<Region>>> parsedRegions, 1354 std::optional<ArrayRef<NamedAttribute>> parsedAttributes, 1355 std::optional<Attribute> propertiesAttribute, 1356 std::optional<FunctionType> parsedFnType) { 1357 1358 // Parse the operand list, if not explicitly provided. 1359 SmallVector<UnresolvedOperand, 8> opInfo; 1360 if (!parsedOperandUseInfo) { 1361 if (parseToken(Token::l_paren, "expected '(' to start operand list") || 1362 parseOptionalSSAUseList(opInfo) || 1363 parseToken(Token::r_paren, "expected ')' to end operand list")) { 1364 return failure(); 1365 } 1366 parsedOperandUseInfo = opInfo; 1367 } 1368 1369 // Parse the successor list, if not explicitly provided. 1370 if (!parsedSuccessors) { 1371 if (getToken().is(Token::l_square)) { 1372 // Check if the operation is not a known terminator. 1373 if (!result.name.mightHaveTrait<OpTrait::IsTerminator>()) 1374 return emitError("successors in non-terminator"); 1375 1376 SmallVector<Block *, 2> successors; 1377 if (parseSuccessors(successors)) 1378 return failure(); 1379 result.addSuccessors(successors); 1380 } 1381 } else { 1382 result.addSuccessors(*parsedSuccessors); 1383 } 1384 1385 // Parse the properties, if not explicitly provided. 1386 if (propertiesAttribute) { 1387 result.propertiesAttr = *propertiesAttribute; 1388 } else if (consumeIf(Token::less)) { 1389 result.propertiesAttr = parseAttribute(); 1390 if (!result.propertiesAttr) 1391 return failure(); 1392 if (parseToken(Token::greater, "expected '>' to close properties")) 1393 return failure(); 1394 } 1395 // Parse the region list, if not explicitly provided. 1396 if (!parsedRegions) { 1397 if (consumeIf(Token::l_paren)) { 1398 do { 1399 // Create temporary regions with the top level region as parent. 1400 result.regions.emplace_back(new Region(topLevelOp)); 1401 if (parseRegion(*result.regions.back(), /*entryArguments=*/{})) 1402 return failure(); 1403 } while (consumeIf(Token::comma)); 1404 if (parseToken(Token::r_paren, "expected ')' to end region list")) 1405 return failure(); 1406 } 1407 } else { 1408 result.addRegions(*parsedRegions); 1409 } 1410 1411 // Parse the attributes, if not explicitly provided. 1412 if (!parsedAttributes) { 1413 if (getToken().is(Token::l_brace)) { 1414 if (parseAttributeDict(result.attributes)) 1415 return failure(); 1416 } 1417 } else { 1418 result.addAttributes(*parsedAttributes); 1419 } 1420 1421 // Parse the operation type, if not explicitly provided. 1422 Location typeLoc = result.location; 1423 if (!parsedFnType) { 1424 if (parseToken(Token::colon, "expected ':' followed by operation type")) 1425 return failure(); 1426 1427 typeLoc = getEncodedSourceLocation(getToken().getLoc()); 1428 auto type = parseType(); 1429 if (!type) 1430 return failure(); 1431 auto fnType = dyn_cast<FunctionType>(type); 1432 if (!fnType) 1433 return mlir::emitError(typeLoc, "expected function type"); 1434 1435 parsedFnType = fnType; 1436 } 1437 1438 result.addTypes(parsedFnType->getResults()); 1439 1440 // Check that we have the right number of types for the operands. 1441 ArrayRef<Type> operandTypes = parsedFnType->getInputs(); 1442 if (operandTypes.size() != parsedOperandUseInfo->size()) { 1443 auto plural = "s"[parsedOperandUseInfo->size() == 1]; 1444 return mlir::emitError(typeLoc, "expected ") 1445 << parsedOperandUseInfo->size() << " operand type" << plural 1446 << " but had " << operandTypes.size(); 1447 } 1448 1449 // Resolve all of the operands. 1450 for (unsigned i = 0, e = parsedOperandUseInfo->size(); i != e; ++i) { 1451 result.operands.push_back( 1452 resolveSSAUse((*parsedOperandUseInfo)[i], operandTypes[i])); 1453 if (!result.operands.back()) 1454 return failure(); 1455 } 1456 1457 return success(); 1458 } 1459 1460 Operation *OperationParser::parseGenericOperation() { 1461 // Get location information for the operation. 1462 auto srcLocation = getEncodedSourceLocation(getToken().getLoc()); 1463 1464 std::string name = getToken().getStringValue(); 1465 if (name.empty()) 1466 return (emitError("empty operation name is invalid"), nullptr); 1467 if (name.find('\0') != StringRef::npos) 1468 return (emitError("null character not allowed in operation name"), nullptr); 1469 1470 consumeToken(Token::string); 1471 1472 OperationState result(srcLocation, name); 1473 CleanupOpStateRegions guard{result}; 1474 1475 // Lazy load dialects in the context as needed. 1476 if (!result.name.isRegistered()) { 1477 StringRef dialectName = StringRef(name).split('.').first; 1478 if (!getContext()->getLoadedDialect(dialectName) && 1479 !getContext()->getOrLoadDialect(dialectName)) { 1480 if (!getContext()->allowsUnregisteredDialects()) { 1481 // Emit an error if the dialect couldn't be loaded (i.e., it was not 1482 // registered) and unregistered dialects aren't allowed. 1483 emitError("operation being parsed with an unregistered dialect. If " 1484 "this is intended, please use -allow-unregistered-dialect " 1485 "with the MLIR tool used"); 1486 return nullptr; 1487 } 1488 } else { 1489 // Reload the OperationName now that the dialect is loaded. 1490 result.name = OperationName(name, getContext()); 1491 } 1492 } 1493 1494 // If we are populating the parser state, start a new operation definition. 1495 if (state.asmState) 1496 state.asmState->startOperationDefinition(result.name); 1497 1498 if (parseGenericOperationAfterOpName(result)) 1499 return nullptr; 1500 1501 // Operation::create() is not allowed to fail, however setting the properties 1502 // from an attribute is a failable operation. So we save the attribute here 1503 // and set it on the operation post-parsing. 1504 Attribute properties; 1505 std::swap(properties, result.propertiesAttr); 1506 1507 // If we don't have properties in the textual IR, but the operation now has 1508 // support for properties, we support some backward-compatible generic syntax 1509 // for the operation and as such we accept inherent attributes mixed in the 1510 // dictionary of discardable attributes. We pre-validate these here because 1511 // invalid attributes can't be casted to the properties storage and will be 1512 // silently dropped. For example an attribute { foo = 0 : i32 } that is 1513 // declared as F32Attr in ODS would have a C++ type of FloatAttr in the 1514 // properties array. When setting it we would do something like: 1515 // 1516 // properties.foo = dyn_cast<FloatAttr>(fooAttr); 1517 // 1518 // which would end up with a null Attribute. The diagnostic from the verifier 1519 // would be "missing foo attribute" instead of something like "expects a 32 1520 // bits float attribute but got a 32 bits integer attribute". 1521 if (!properties && !result.getRawProperties()) { 1522 std::optional<RegisteredOperationName> info = 1523 result.name.getRegisteredInfo(); 1524 if (info) { 1525 if (failed(info->verifyInherentAttrs(result.attributes, [&]() { 1526 return mlir::emitError(srcLocation) << "'" << name << "' op "; 1527 }))) 1528 return nullptr; 1529 } 1530 } 1531 1532 // Create the operation and try to parse a location for it. 1533 Operation *op = opBuilder.create(result); 1534 if (parseTrailingLocationSpecifier(op)) 1535 return nullptr; 1536 1537 // Try setting the properties for the operation, using a diagnostic to print 1538 // errors. 1539 if (properties) { 1540 auto emitError = [&]() { 1541 return mlir::emitError(srcLocation, "invalid properties ") 1542 << properties << " for op " << name << ": "; 1543 }; 1544 if (failed(op->setPropertiesFromAttribute(properties, emitError))) 1545 return nullptr; 1546 } 1547 1548 return op; 1549 } 1550 1551 Operation *OperationParser::parseGenericOperation(Block *insertBlock, 1552 Block::iterator insertPt) { 1553 Token nameToken = getToken(); 1554 1555 OpBuilder::InsertionGuard restoreInsertionPoint(opBuilder); 1556 opBuilder.setInsertionPoint(insertBlock, insertPt); 1557 Operation *op = parseGenericOperation(); 1558 if (!op) 1559 return nullptr; 1560 1561 // If we are populating the parser asm state, finalize this operation 1562 // definition. 1563 if (state.asmState) 1564 state.asmState->finalizeOperationDefinition( 1565 op, nameToken.getLocRange(), 1566 /*endLoc=*/getLastToken().getEndLoc()); 1567 return op; 1568 } 1569 1570 namespace { 1571 class CustomOpAsmParser : public AsmParserImpl<OpAsmParser> { 1572 public: 1573 CustomOpAsmParser( 1574 SMLoc nameLoc, ArrayRef<OperationParser::ResultRecord> resultIDs, 1575 function_ref<ParseResult(OpAsmParser &, OperationState &)> parseAssembly, 1576 bool isIsolatedFromAbove, StringRef opName, OperationParser &parser) 1577 : AsmParserImpl<OpAsmParser>(nameLoc, parser), resultIDs(resultIDs), 1578 parseAssembly(parseAssembly), isIsolatedFromAbove(isIsolatedFromAbove), 1579 opName(opName), parser(parser) { 1580 (void)isIsolatedFromAbove; // Only used in assert, silence unused warning. 1581 } 1582 1583 /// Parse an instance of the operation described by 'opDefinition' into the 1584 /// provided operation state. 1585 ParseResult parseOperation(OperationState &opState) { 1586 if (parseAssembly(*this, opState)) 1587 return failure(); 1588 // Verify that the parsed attributes does not have duplicate attributes. 1589 // This can happen if an attribute set during parsing is also specified in 1590 // the attribute dictionary in the assembly, or the attribute is set 1591 // multiple during parsing. 1592 std::optional<NamedAttribute> duplicate = 1593 opState.attributes.findDuplicate(); 1594 if (duplicate) 1595 return emitError(getNameLoc(), "attribute '") 1596 << duplicate->getName().getValue() 1597 << "' occurs more than once in the attribute list"; 1598 return success(); 1599 } 1600 1601 Operation *parseGenericOperation(Block *insertBlock, 1602 Block::iterator insertPt) final { 1603 return parser.parseGenericOperation(insertBlock, insertPt); 1604 } 1605 1606 FailureOr<OperationName> parseCustomOperationName() final { 1607 return parser.parseCustomOperationName(); 1608 } 1609 1610 ParseResult parseGenericOperationAfterOpName( 1611 OperationState &result, 1612 std::optional<ArrayRef<UnresolvedOperand>> parsedUnresolvedOperands, 1613 std::optional<ArrayRef<Block *>> parsedSuccessors, 1614 std::optional<MutableArrayRef<std::unique_ptr<Region>>> parsedRegions, 1615 std::optional<ArrayRef<NamedAttribute>> parsedAttributes, 1616 std::optional<Attribute> parsedPropertiesAttribute, 1617 std::optional<FunctionType> parsedFnType) final { 1618 return parser.parseGenericOperationAfterOpName( 1619 result, parsedUnresolvedOperands, parsedSuccessors, parsedRegions, 1620 parsedAttributes, parsedPropertiesAttribute, parsedFnType); 1621 } 1622 //===--------------------------------------------------------------------===// 1623 // Utilities 1624 //===--------------------------------------------------------------------===// 1625 1626 /// Return the name of the specified result in the specified syntax, as well 1627 /// as the subelement in the name. For example, in this operation: 1628 /// 1629 /// %x, %y:2, %z = foo.op 1630 /// 1631 /// getResultName(0) == {"x", 0 } 1632 /// getResultName(1) == {"y", 0 } 1633 /// getResultName(2) == {"y", 1 } 1634 /// getResultName(3) == {"z", 0 } 1635 std::pair<StringRef, unsigned> 1636 getResultName(unsigned resultNo) const override { 1637 // Scan for the resultID that contains this result number. 1638 for (const auto &entry : resultIDs) { 1639 if (resultNo < std::get<1>(entry)) { 1640 // Don't pass on the leading %. 1641 StringRef name = std::get<0>(entry).drop_front(); 1642 return {name, resultNo}; 1643 } 1644 resultNo -= std::get<1>(entry); 1645 } 1646 1647 // Invalid result number. 1648 return {"", ~0U}; 1649 } 1650 1651 /// Return the number of declared SSA results. This returns 4 for the foo.op 1652 /// example in the comment for getResultName. 1653 size_t getNumResults() const override { 1654 size_t count = 0; 1655 for (auto &entry : resultIDs) 1656 count += std::get<1>(entry); 1657 return count; 1658 } 1659 1660 /// Emit a diagnostic at the specified location and return failure. 1661 InFlightDiagnostic emitError(SMLoc loc, const Twine &message) override { 1662 return AsmParserImpl<OpAsmParser>::emitError(loc, "custom op '" + opName + 1663 "' " + message); 1664 } 1665 1666 //===--------------------------------------------------------------------===// 1667 // Operand Parsing 1668 //===--------------------------------------------------------------------===// 1669 1670 /// Parse a single operand. 1671 ParseResult parseOperand(UnresolvedOperand &result, 1672 bool allowResultNumber = true) override { 1673 OperationParser::UnresolvedOperand useInfo; 1674 if (parser.parseSSAUse(useInfo, allowResultNumber)) 1675 return failure(); 1676 1677 result = {useInfo.location, useInfo.name, useInfo.number}; 1678 return success(); 1679 } 1680 1681 /// Parse a single operand if present. 1682 OptionalParseResult 1683 parseOptionalOperand(UnresolvedOperand &result, 1684 bool allowResultNumber = true) override { 1685 if (parser.getToken().isOrIsCodeCompletionFor(Token::percent_identifier)) 1686 return parseOperand(result, allowResultNumber); 1687 return std::nullopt; 1688 } 1689 1690 /// Parse zero or more SSA comma-separated operand references with a specified 1691 /// surrounding delimiter, and an optional required operand count. 1692 ParseResult parseOperandList(SmallVectorImpl<UnresolvedOperand> &result, 1693 Delimiter delimiter = Delimiter::None, 1694 bool allowResultNumber = true, 1695 int requiredOperandCount = -1) override { 1696 // The no-delimiter case has some special handling for better diagnostics. 1697 if (delimiter == Delimiter::None) { 1698 // parseCommaSeparatedList doesn't handle the missing case for "none", 1699 // so we handle it custom here. 1700 Token tok = parser.getToken(); 1701 if (!tok.isOrIsCodeCompletionFor(Token::percent_identifier)) { 1702 // If we didn't require any operands or required exactly zero (weird) 1703 // then this is success. 1704 if (requiredOperandCount == -1 || requiredOperandCount == 0) 1705 return success(); 1706 1707 // Otherwise, try to produce a nice error message. 1708 if (tok.isAny(Token::l_paren, Token::l_square)) 1709 return parser.emitError("unexpected delimiter"); 1710 return parser.emitWrongTokenError("expected operand"); 1711 } 1712 } 1713 1714 auto parseOneOperand = [&]() -> ParseResult { 1715 return parseOperand(result.emplace_back(), allowResultNumber); 1716 }; 1717 1718 auto startLoc = parser.getToken().getLoc(); 1719 if (parseCommaSeparatedList(delimiter, parseOneOperand, " in operand list")) 1720 return failure(); 1721 1722 // Check that we got the expected # of elements. 1723 if (requiredOperandCount != -1 && 1724 result.size() != static_cast<size_t>(requiredOperandCount)) 1725 return emitError(startLoc, "expected ") 1726 << requiredOperandCount << " operands"; 1727 return success(); 1728 } 1729 1730 /// Resolve an operand to an SSA value, emitting an error on failure. 1731 ParseResult resolveOperand(const UnresolvedOperand &operand, Type type, 1732 SmallVectorImpl<Value> &result) override { 1733 if (auto value = parser.resolveSSAUse(operand, type)) { 1734 result.push_back(value); 1735 return success(); 1736 } 1737 return failure(); 1738 } 1739 1740 /// Parse an AffineMap of SSA ids. 1741 ParseResult 1742 parseAffineMapOfSSAIds(SmallVectorImpl<UnresolvedOperand> &operands, 1743 Attribute &mapAttr, StringRef attrName, 1744 NamedAttrList &attrs, Delimiter delimiter) override { 1745 SmallVector<UnresolvedOperand, 2> dimOperands; 1746 SmallVector<UnresolvedOperand, 1> symOperands; 1747 1748 auto parseElement = [&](bool isSymbol) -> ParseResult { 1749 UnresolvedOperand operand; 1750 if (parseOperand(operand)) 1751 return failure(); 1752 if (isSymbol) 1753 symOperands.push_back(operand); 1754 else 1755 dimOperands.push_back(operand); 1756 return success(); 1757 }; 1758 1759 AffineMap map; 1760 if (parser.parseAffineMapOfSSAIds(map, parseElement, delimiter)) 1761 return failure(); 1762 // Add AffineMap attribute. 1763 if (map) { 1764 mapAttr = AffineMapAttr::get(map); 1765 attrs.push_back(parser.builder.getNamedAttr(attrName, mapAttr)); 1766 } 1767 1768 // Add dim operands before symbol operands in 'operands'. 1769 operands.assign(dimOperands.begin(), dimOperands.end()); 1770 operands.append(symOperands.begin(), symOperands.end()); 1771 return success(); 1772 } 1773 1774 /// Parse an AffineExpr of SSA ids. 1775 ParseResult 1776 parseAffineExprOfSSAIds(SmallVectorImpl<UnresolvedOperand> &dimOperands, 1777 SmallVectorImpl<UnresolvedOperand> &symbOperands, 1778 AffineExpr &expr) override { 1779 auto parseElement = [&](bool isSymbol) -> ParseResult { 1780 UnresolvedOperand operand; 1781 if (parseOperand(operand)) 1782 return failure(); 1783 if (isSymbol) 1784 symbOperands.push_back(operand); 1785 else 1786 dimOperands.push_back(operand); 1787 return success(); 1788 }; 1789 1790 return parser.parseAffineExprOfSSAIds(expr, parseElement); 1791 } 1792 1793 //===--------------------------------------------------------------------===// 1794 // Argument Parsing 1795 //===--------------------------------------------------------------------===// 1796 1797 /// Parse a single argument with the following syntax: 1798 /// 1799 /// `%ssaname : !type { optionalAttrDict} loc(optionalSourceLoc)` 1800 /// 1801 /// If `allowType` is false or `allowAttrs` are false then the respective 1802 /// parts of the grammar are not parsed. 1803 ParseResult parseArgument(Argument &result, bool allowType = false, 1804 bool allowAttrs = false) override { 1805 NamedAttrList attrs; 1806 if (parseOperand(result.ssaName, /*allowResultNumber=*/false) || 1807 (allowType && parseColonType(result.type)) || 1808 (allowAttrs && parseOptionalAttrDict(attrs)) || 1809 parseOptionalLocationSpecifier(result.sourceLoc)) 1810 return failure(); 1811 result.attrs = attrs.getDictionary(getContext()); 1812 return success(); 1813 } 1814 1815 /// Parse a single argument if present. 1816 OptionalParseResult parseOptionalArgument(Argument &result, bool allowType, 1817 bool allowAttrs) override { 1818 if (parser.getToken().is(Token::percent_identifier)) 1819 return parseArgument(result, allowType, allowAttrs); 1820 return std::nullopt; 1821 } 1822 1823 ParseResult parseArgumentList(SmallVectorImpl<Argument> &result, 1824 Delimiter delimiter, bool allowType, 1825 bool allowAttrs) override { 1826 // The no-delimiter case has some special handling for the empty case. 1827 if (delimiter == Delimiter::None && 1828 parser.getToken().isNot(Token::percent_identifier)) 1829 return success(); 1830 1831 auto parseOneArgument = [&]() -> ParseResult { 1832 return parseArgument(result.emplace_back(), allowType, allowAttrs); 1833 }; 1834 return parseCommaSeparatedList(delimiter, parseOneArgument, 1835 " in argument list"); 1836 } 1837 1838 //===--------------------------------------------------------------------===// 1839 // Region Parsing 1840 //===--------------------------------------------------------------------===// 1841 1842 /// Parse a region that takes `arguments` of `argTypes` types. This 1843 /// effectively defines the SSA values of `arguments` and assigns their type. 1844 ParseResult parseRegion(Region ®ion, ArrayRef<Argument> arguments, 1845 bool enableNameShadowing) override { 1846 // Try to parse the region. 1847 (void)isIsolatedFromAbove; 1848 assert((!enableNameShadowing || isIsolatedFromAbove) && 1849 "name shadowing is only allowed on isolated regions"); 1850 if (parser.parseRegion(region, arguments, enableNameShadowing)) 1851 return failure(); 1852 return success(); 1853 } 1854 1855 /// Parses a region if present. 1856 OptionalParseResult parseOptionalRegion(Region ®ion, 1857 ArrayRef<Argument> arguments, 1858 bool enableNameShadowing) override { 1859 if (parser.getToken().isNot(Token::l_brace)) 1860 return std::nullopt; 1861 return parseRegion(region, arguments, enableNameShadowing); 1862 } 1863 1864 /// Parses a region if present. If the region is present, a new region is 1865 /// allocated and placed in `region`. If no region is present, `region` 1866 /// remains untouched. 1867 OptionalParseResult 1868 parseOptionalRegion(std::unique_ptr<Region> ®ion, 1869 ArrayRef<Argument> arguments, 1870 bool enableNameShadowing = false) override { 1871 if (parser.getToken().isNot(Token::l_brace)) 1872 return std::nullopt; 1873 std::unique_ptr<Region> newRegion = std::make_unique<Region>(); 1874 if (parseRegion(*newRegion, arguments, enableNameShadowing)) 1875 return failure(); 1876 1877 region = std::move(newRegion); 1878 return success(); 1879 } 1880 1881 //===--------------------------------------------------------------------===// 1882 // Successor Parsing 1883 //===--------------------------------------------------------------------===// 1884 1885 /// Parse a single operation successor. 1886 ParseResult parseSuccessor(Block *&dest) override { 1887 return parser.parseSuccessor(dest); 1888 } 1889 1890 /// Parse an optional operation successor and its operand list. 1891 OptionalParseResult parseOptionalSuccessor(Block *&dest) override { 1892 if (!parser.getToken().isOrIsCodeCompletionFor(Token::caret_identifier)) 1893 return std::nullopt; 1894 return parseSuccessor(dest); 1895 } 1896 1897 /// Parse a single operation successor and its operand list. 1898 ParseResult 1899 parseSuccessorAndUseList(Block *&dest, 1900 SmallVectorImpl<Value> &operands) override { 1901 if (parseSuccessor(dest)) 1902 return failure(); 1903 1904 // Handle optional arguments. 1905 if (succeeded(parseOptionalLParen()) && 1906 (parser.parseOptionalSSAUseAndTypeList(operands) || parseRParen())) { 1907 return failure(); 1908 } 1909 return success(); 1910 } 1911 1912 //===--------------------------------------------------------------------===// 1913 // Type Parsing 1914 //===--------------------------------------------------------------------===// 1915 1916 /// Parse a list of assignments of the form 1917 /// (%x1 = %y1, %x2 = %y2, ...). 1918 OptionalParseResult parseOptionalAssignmentList( 1919 SmallVectorImpl<Argument> &lhs, 1920 SmallVectorImpl<UnresolvedOperand> &rhs) override { 1921 if (failed(parseOptionalLParen())) 1922 return std::nullopt; 1923 1924 auto parseElt = [&]() -> ParseResult { 1925 if (parseArgument(lhs.emplace_back()) || parseEqual() || 1926 parseOperand(rhs.emplace_back())) 1927 return failure(); 1928 return success(); 1929 }; 1930 return parser.parseCommaSeparatedListUntil(Token::r_paren, parseElt); 1931 } 1932 1933 /// Parse a loc(...) specifier if present, filling in result if so. 1934 ParseResult 1935 parseOptionalLocationSpecifier(std::optional<Location> &result) override { 1936 // If there is a 'loc' we parse a trailing location. 1937 if (!parser.consumeIf(Token::kw_loc)) 1938 return success(); 1939 LocationAttr directLoc; 1940 if (parser.parseToken(Token::l_paren, "expected '(' in location")) 1941 return failure(); 1942 1943 Token tok = parser.getToken(); 1944 1945 // Check to see if we are parsing a location alias. We are parsing a 1946 // location alias if the token is a hash identifier *without* a dot in it - 1947 // the dot signifies a dialect attribute. Otherwise, we parse the location 1948 // directly. 1949 if (tok.is(Token::hash_identifier) && !tok.getSpelling().contains('.')) { 1950 if (parser.parseLocationAlias(directLoc)) 1951 return failure(); 1952 } else if (parser.parseLocationInstance(directLoc)) { 1953 return failure(); 1954 } 1955 1956 if (parser.parseToken(Token::r_paren, "expected ')' in location")) 1957 return failure(); 1958 1959 result = directLoc; 1960 return success(); 1961 } 1962 1963 private: 1964 /// Information about the result name specifiers. 1965 ArrayRef<OperationParser::ResultRecord> resultIDs; 1966 1967 /// The abstract information of the operation. 1968 function_ref<ParseResult(OpAsmParser &, OperationState &)> parseAssembly; 1969 bool isIsolatedFromAbove; 1970 StringRef opName; 1971 1972 /// The backing operation parser. 1973 OperationParser &parser; 1974 }; 1975 } // namespace 1976 1977 FailureOr<OperationName> OperationParser::parseCustomOperationName() { 1978 Token nameTok = getToken(); 1979 StringRef opName = nameTok.getSpelling(); 1980 if (opName.empty()) 1981 return (emitError("empty operation name is invalid"), failure()); 1982 consumeToken(); 1983 1984 // Check to see if this operation name is already registered. 1985 std::optional<RegisteredOperationName> opInfo = 1986 RegisteredOperationName::lookup(opName, getContext()); 1987 if (opInfo) 1988 return *opInfo; 1989 1990 // If the operation doesn't have a dialect prefix try using the default 1991 // dialect. 1992 auto opNameSplit = opName.split('.'); 1993 StringRef dialectName = opNameSplit.first; 1994 std::string opNameStorage; 1995 if (opNameSplit.second.empty()) { 1996 // If the name didn't have a prefix, check for a code completion request. 1997 if (getToken().isCodeCompletion() && opName.back() == '.') 1998 return codeCompleteOperationName(dialectName); 1999 2000 dialectName = getState().defaultDialectStack.back(); 2001 opNameStorage = (dialectName + "." + opName).str(); 2002 opName = opNameStorage; 2003 } 2004 2005 // Try to load the dialect before returning the operation name to make sure 2006 // the operation has a chance to be registered. 2007 getContext()->getOrLoadDialect(dialectName); 2008 return OperationName(opName, getContext()); 2009 } 2010 2011 Operation * 2012 OperationParser::parseCustomOperation(ArrayRef<ResultRecord> resultIDs) { 2013 SMLoc opLoc = getToken().getLoc(); 2014 StringRef originalOpName = getTokenSpelling(); 2015 2016 FailureOr<OperationName> opNameInfo = parseCustomOperationName(); 2017 if (failed(opNameInfo)) 2018 return nullptr; 2019 StringRef opName = opNameInfo->getStringRef(); 2020 2021 // This is the actual hook for the custom op parsing, usually implemented by 2022 // the op itself (`Op::parse()`). We retrieve it either from the 2023 // RegisteredOperationName or from the Dialect. 2024 OperationName::ParseAssemblyFn parseAssemblyFn; 2025 bool isIsolatedFromAbove = false; 2026 2027 StringRef defaultDialect = ""; 2028 if (auto opInfo = opNameInfo->getRegisteredInfo()) { 2029 parseAssemblyFn = opInfo->getParseAssemblyFn(); 2030 isIsolatedFromAbove = opInfo->hasTrait<OpTrait::IsIsolatedFromAbove>(); 2031 auto *iface = opInfo->getInterface<OpAsmOpInterface>(); 2032 if (iface && !iface->getDefaultDialect().empty()) 2033 defaultDialect = iface->getDefaultDialect(); 2034 } else { 2035 std::optional<Dialect::ParseOpHook> dialectHook; 2036 Dialect *dialect = opNameInfo->getDialect(); 2037 if (!dialect) { 2038 InFlightDiagnostic diag = 2039 emitError(opLoc) << "Dialect `" << opNameInfo->getDialectNamespace() 2040 << "' not found for custom op '" << originalOpName 2041 << "' "; 2042 if (originalOpName != opName) 2043 diag << " (tried '" << opName << "' as well)"; 2044 auto ¬e = diag.attachNote(); 2045 note << "Registered dialects: "; 2046 llvm::interleaveComma(getContext()->getAvailableDialects(), note, 2047 [&](StringRef dialect) { note << dialect; }); 2048 note << " ; for more info on dialect registration see " 2049 "https://mlir.llvm.org/getting_started/Faq/" 2050 "#registered-loaded-dependent-whats-up-with-dialects-management"; 2051 return nullptr; 2052 } 2053 dialectHook = dialect->getParseOperationHook(opName); 2054 if (!dialectHook) { 2055 InFlightDiagnostic diag = 2056 emitError(opLoc) << "custom op '" << originalOpName << "' is unknown"; 2057 if (originalOpName != opName) 2058 diag << " (tried '" << opName << "' as well)"; 2059 return nullptr; 2060 } 2061 parseAssemblyFn = *dialectHook; 2062 } 2063 getState().defaultDialectStack.push_back(defaultDialect); 2064 auto restoreDefaultDialect = llvm::make_scope_exit( 2065 [&]() { getState().defaultDialectStack.pop_back(); }); 2066 2067 // If the custom op parser crashes, produce some indication to help 2068 // debugging. 2069 llvm::PrettyStackTraceFormat fmt("MLIR Parser: custom op parser '%s'", 2070 opNameInfo->getIdentifier().data()); 2071 2072 // Get location information for the operation. 2073 auto srcLocation = getEncodedSourceLocation(opLoc); 2074 OperationState opState(srcLocation, *opNameInfo); 2075 2076 // If we are populating the parser state, start a new operation definition. 2077 if (state.asmState) 2078 state.asmState->startOperationDefinition(opState.name); 2079 2080 // Have the op implementation take a crack and parsing this. 2081 CleanupOpStateRegions guard{opState}; 2082 CustomOpAsmParser opAsmParser(opLoc, resultIDs, parseAssemblyFn, 2083 isIsolatedFromAbove, opName, *this); 2084 if (opAsmParser.parseOperation(opState)) 2085 return nullptr; 2086 2087 // If it emitted an error, we failed. 2088 if (opAsmParser.didEmitError()) 2089 return nullptr; 2090 2091 Attribute properties = opState.propertiesAttr; 2092 opState.propertiesAttr = Attribute{}; 2093 2094 // Otherwise, create the operation and try to parse a location for it. 2095 Operation *op = opBuilder.create(opState); 2096 if (parseTrailingLocationSpecifier(op)) 2097 return nullptr; 2098 2099 // Try setting the properties for the operation. 2100 if (properties) { 2101 auto emitError = [&]() { 2102 return mlir::emitError(srcLocation, "invalid properties ") 2103 << properties << " for op " << op->getName().getStringRef() 2104 << ": "; 2105 }; 2106 if (failed(op->setPropertiesFromAttribute(properties, emitError))) 2107 return nullptr; 2108 } 2109 return op; 2110 } 2111 2112 ParseResult OperationParser::parseLocationAlias(LocationAttr &loc) { 2113 Token tok = getToken(); 2114 consumeToken(Token::hash_identifier); 2115 StringRef identifier = tok.getSpelling().drop_front(); 2116 assert(!identifier.contains('.') && 2117 "unexpected dialect attribute token, expected alias"); 2118 2119 if (state.asmState) 2120 state.asmState->addAttrAliasUses(identifier, tok.getLocRange()); 2121 2122 // If this alias can be resolved, do it now. 2123 Attribute attr = state.symbols.attributeAliasDefinitions.lookup(identifier); 2124 if (attr) { 2125 if (!(loc = dyn_cast<LocationAttr>(attr))) 2126 return emitError(tok.getLoc()) 2127 << "expected location, but found '" << attr << "'"; 2128 } else { 2129 // Otherwise, remember this operation and resolve its location later. 2130 // In the meantime, use a special OpaqueLoc as a marker. 2131 loc = OpaqueLoc::get(deferredLocsReferences.size(), 2132 TypeID::get<DeferredLocInfo *>(), 2133 UnknownLoc::get(getContext())); 2134 deferredLocsReferences.push_back(DeferredLocInfo{tok.getLoc(), identifier}); 2135 } 2136 return success(); 2137 } 2138 2139 ParseResult 2140 OperationParser::parseTrailingLocationSpecifier(OpOrArgument opOrArgument) { 2141 // If there is a 'loc' we parse a trailing location. 2142 if (!consumeIf(Token::kw_loc)) 2143 return success(); 2144 if (parseToken(Token::l_paren, "expected '(' in location")) 2145 return failure(); 2146 Token tok = getToken(); 2147 2148 // Check to see if we are parsing a location alias. We are parsing a location 2149 // alias if the token is a hash identifier *without* a dot in it - the dot 2150 // signifies a dialect attribute. Otherwise, we parse the location directly. 2151 LocationAttr directLoc; 2152 if (tok.is(Token::hash_identifier) && !tok.getSpelling().contains('.')) { 2153 if (parseLocationAlias(directLoc)) 2154 return failure(); 2155 } else if (parseLocationInstance(directLoc)) { 2156 return failure(); 2157 } 2158 2159 if (parseToken(Token::r_paren, "expected ')' in location")) 2160 return failure(); 2161 2162 if (auto *op = llvm::dyn_cast_if_present<Operation *>(opOrArgument)) 2163 op->setLoc(directLoc); 2164 else 2165 cast<BlockArgument>(opOrArgument).setLoc(directLoc); 2166 return success(); 2167 } 2168 2169 //===----------------------------------------------------------------------===// 2170 // Region Parsing 2171 //===----------------------------------------------------------------------===// 2172 2173 ParseResult OperationParser::parseRegion(Region ®ion, 2174 ArrayRef<Argument> entryArguments, 2175 bool isIsolatedNameScope) { 2176 // Parse the '{'. 2177 Token lBraceTok = getToken(); 2178 if (parseToken(Token::l_brace, "expected '{' to begin a region")) 2179 return failure(); 2180 2181 // If we are populating the parser state, start a new region definition. 2182 if (state.asmState) 2183 state.asmState->startRegionDefinition(); 2184 2185 // Parse the region body. 2186 if ((!entryArguments.empty() || getToken().isNot(Token::r_brace)) && 2187 parseRegionBody(region, lBraceTok.getLoc(), entryArguments, 2188 isIsolatedNameScope)) { 2189 return failure(); 2190 } 2191 consumeToken(Token::r_brace); 2192 2193 // If we are populating the parser state, finalize this region. 2194 if (state.asmState) 2195 state.asmState->finalizeRegionDefinition(); 2196 2197 return success(); 2198 } 2199 2200 ParseResult OperationParser::parseRegionBody(Region ®ion, SMLoc startLoc, 2201 ArrayRef<Argument> entryArguments, 2202 bool isIsolatedNameScope) { 2203 auto currentPt = opBuilder.saveInsertionPoint(); 2204 2205 // Push a new named value scope. 2206 pushSSANameScope(isIsolatedNameScope); 2207 2208 // Parse the first block directly to allow for it to be unnamed. 2209 auto owningBlock = std::make_unique<Block>(); 2210 Block *block = owningBlock.get(); 2211 2212 // If this block is not defined in the source file, add a definition for it 2213 // now in the assembly state. Blocks with a name will be defined when the name 2214 // is parsed. 2215 if (state.asmState && getToken().isNot(Token::caret_identifier)) 2216 state.asmState->addDefinition(block, startLoc); 2217 2218 // Add arguments to the entry block if we had the form with explicit names. 2219 if (!entryArguments.empty() && !entryArguments[0].ssaName.name.empty()) { 2220 // If we had named arguments, then don't allow a block name. 2221 if (getToken().is(Token::caret_identifier)) 2222 return emitError("invalid block name in region with named arguments"); 2223 2224 for (auto &entryArg : entryArguments) { 2225 auto &argInfo = entryArg.ssaName; 2226 2227 // Ensure that the argument was not already defined. 2228 if (auto defLoc = getReferenceLoc(argInfo.name, argInfo.number)) { 2229 return emitError(argInfo.location, "region entry argument '" + 2230 argInfo.name + 2231 "' is already in use") 2232 .attachNote(getEncodedSourceLocation(*defLoc)) 2233 << "previously referenced here"; 2234 } 2235 Location loc = entryArg.sourceLoc.has_value() 2236 ? *entryArg.sourceLoc 2237 : getEncodedSourceLocation(argInfo.location); 2238 BlockArgument arg = block->addArgument(entryArg.type, loc); 2239 2240 // Add a definition of this arg to the assembly state if provided. 2241 if (state.asmState) 2242 state.asmState->addDefinition(arg, argInfo.location); 2243 2244 // Record the definition for this argument. 2245 if (addDefinition(argInfo, arg)) 2246 return failure(); 2247 } 2248 } 2249 2250 if (parseBlock(block)) 2251 return failure(); 2252 2253 // Verify that no other arguments were parsed. 2254 if (!entryArguments.empty() && 2255 block->getNumArguments() > entryArguments.size()) { 2256 return emitError("entry block arguments were already defined"); 2257 } 2258 2259 // Parse the rest of the region. 2260 region.push_back(owningBlock.release()); 2261 while (getToken().isNot(Token::r_brace)) { 2262 Block *newBlock = nullptr; 2263 if (parseBlock(newBlock)) 2264 return failure(); 2265 region.push_back(newBlock); 2266 } 2267 2268 // Pop the SSA value scope for this region. 2269 if (popSSANameScope()) 2270 return failure(); 2271 2272 // Reset the original insertion point. 2273 opBuilder.restoreInsertionPoint(currentPt); 2274 return success(); 2275 } 2276 2277 //===----------------------------------------------------------------------===// 2278 // Block Parsing 2279 //===----------------------------------------------------------------------===// 2280 2281 /// Block declaration. 2282 /// 2283 /// block ::= block-label? operation* 2284 /// block-label ::= block-id block-arg-list? `:` 2285 /// block-id ::= caret-id 2286 /// block-arg-list ::= `(` ssa-id-and-type-list? `)` 2287 /// 2288 ParseResult OperationParser::parseBlock(Block *&block) { 2289 // The first block of a region may already exist, if it does the caret 2290 // identifier is optional. 2291 if (block && getToken().isNot(Token::caret_identifier)) 2292 return parseBlockBody(block); 2293 2294 SMLoc nameLoc = getToken().getLoc(); 2295 auto name = getTokenSpelling(); 2296 if (parseToken(Token::caret_identifier, "expected block name")) 2297 return failure(); 2298 2299 // Define the block with the specified name. 2300 auto &blockAndLoc = getBlockInfoByName(name); 2301 blockAndLoc.loc = nameLoc; 2302 2303 // Use a unique pointer for in-flight block being parsed. Release ownership 2304 // only in the case of a successful parse. This ensures that the Block 2305 // allocated is released if the parse fails and control returns early. 2306 std::unique_ptr<Block> inflightBlock; 2307 auto cleanupOnFailure = llvm::make_scope_exit([&] { 2308 if (inflightBlock) 2309 inflightBlock->dropAllDefinedValueUses(); 2310 }); 2311 2312 // If a block has yet to be set, this is a new definition. If the caller 2313 // provided a block, use it. Otherwise create a new one. 2314 if (!blockAndLoc.block) { 2315 if (block) { 2316 blockAndLoc.block = block; 2317 } else { 2318 inflightBlock = std::make_unique<Block>(); 2319 blockAndLoc.block = inflightBlock.get(); 2320 } 2321 2322 // Otherwise, the block has a forward declaration. Forward declarations are 2323 // removed once defined, so if we are defining a existing block and it is 2324 // not a forward declaration, then it is a redeclaration. Fail if the block 2325 // was already defined. 2326 } else if (!eraseForwardRef(blockAndLoc.block)) { 2327 return emitError(nameLoc, "redefinition of block '") << name << "'"; 2328 } else { 2329 // This was a forward reference block that is now floating. Keep track of it 2330 // as inflight in case of error, so that it gets cleaned up properly. 2331 inflightBlock.reset(blockAndLoc.block); 2332 } 2333 2334 // Populate the high level assembly state if necessary. 2335 if (state.asmState) 2336 state.asmState->addDefinition(blockAndLoc.block, nameLoc); 2337 block = blockAndLoc.block; 2338 2339 // If an argument list is present, parse it. 2340 if (getToken().is(Token::l_paren)) 2341 if (parseOptionalBlockArgList(block)) 2342 return failure(); 2343 if (parseToken(Token::colon, "expected ':' after block name")) 2344 return failure(); 2345 2346 // Parse the body of the block. 2347 ParseResult res = parseBlockBody(block); 2348 2349 // If parsing was successful, drop the inflight block. We relinquish ownership 2350 // back up to the caller. 2351 if (succeeded(res)) 2352 (void)inflightBlock.release(); 2353 return res; 2354 } 2355 2356 ParseResult OperationParser::parseBlockBody(Block *block) { 2357 // Set the insertion point to the end of the block to parse. 2358 opBuilder.setInsertionPointToEnd(block); 2359 2360 // Parse the list of operations that make up the body of the block. 2361 while (getToken().isNot(Token::caret_identifier, Token::r_brace)) 2362 if (parseOperation()) 2363 return failure(); 2364 2365 return success(); 2366 } 2367 2368 /// Get the block with the specified name, creating it if it doesn't already 2369 /// exist. The location specified is the point of use, which allows 2370 /// us to diagnose references to blocks that are not defined precisely. 2371 Block *OperationParser::getBlockNamed(StringRef name, SMLoc loc) { 2372 BlockDefinition &blockDef = getBlockInfoByName(name); 2373 if (!blockDef.block) { 2374 blockDef = {new Block(), loc}; 2375 insertForwardRef(blockDef.block, blockDef.loc); 2376 } 2377 2378 // Populate the high level assembly state if necessary. 2379 if (state.asmState) 2380 state.asmState->addUses(blockDef.block, loc); 2381 2382 return blockDef.block; 2383 } 2384 2385 /// Parse a (possibly empty) list of SSA operands with types as block arguments 2386 /// enclosed in parentheses. 2387 /// 2388 /// value-id-and-type-list ::= value-id-and-type (`,` ssa-id-and-type)* 2389 /// block-arg-list ::= `(` value-id-and-type-list? `)` 2390 /// 2391 ParseResult OperationParser::parseOptionalBlockArgList(Block *owner) { 2392 if (getToken().is(Token::r_brace)) 2393 return success(); 2394 2395 // If the block already has arguments, then we're handling the entry block. 2396 // Parse and register the names for the arguments, but do not add them. 2397 bool definingExistingArgs = owner->getNumArguments() != 0; 2398 unsigned nextArgument = 0; 2399 2400 return parseCommaSeparatedList(Delimiter::Paren, [&]() -> ParseResult { 2401 return parseSSADefOrUseAndType( 2402 [&](UnresolvedOperand useInfo, Type type) -> ParseResult { 2403 BlockArgument arg; 2404 2405 // If we are defining existing arguments, ensure that the argument 2406 // has already been created with the right type. 2407 if (definingExistingArgs) { 2408 // Otherwise, ensure that this argument has already been created. 2409 if (nextArgument >= owner->getNumArguments()) 2410 return emitError("too many arguments specified in argument list"); 2411 2412 // Finally, make sure the existing argument has the correct type. 2413 arg = owner->getArgument(nextArgument++); 2414 if (arg.getType() != type) 2415 return emitError("argument and block argument type mismatch"); 2416 } else { 2417 auto loc = getEncodedSourceLocation(useInfo.location); 2418 arg = owner->addArgument(type, loc); 2419 } 2420 2421 // If the argument has an explicit loc(...) specifier, parse and apply 2422 // it. 2423 if (parseTrailingLocationSpecifier(arg)) 2424 return failure(); 2425 2426 // Mark this block argument definition in the parser state if it was 2427 // provided. 2428 if (state.asmState) 2429 state.asmState->addDefinition(arg, useInfo.location); 2430 2431 return addDefinition(useInfo, arg); 2432 }); 2433 }); 2434 } 2435 2436 //===----------------------------------------------------------------------===// 2437 // Code Completion 2438 //===----------------------------------------------------------------------===// 2439 2440 ParseResult OperationParser::codeCompleteSSAUse() { 2441 for (IsolatedSSANameScope &scope : isolatedNameScopes) { 2442 for (auto &it : scope.values) { 2443 if (it.second.empty()) 2444 continue; 2445 Value frontValue = it.second.front().value; 2446 2447 std::string detailData; 2448 llvm::raw_string_ostream detailOS(detailData); 2449 2450 // If the value isn't a forward reference, we also add the name of the op 2451 // to the detail. 2452 if (auto result = dyn_cast<OpResult>(frontValue)) { 2453 if (!forwardRefPlaceholders.count(result)) 2454 detailOS << result.getOwner()->getName() << ": "; 2455 } else { 2456 detailOS << "arg #" << cast<BlockArgument>(frontValue).getArgNumber() 2457 << ": "; 2458 } 2459 2460 // Emit the type of the values to aid with completion selection. 2461 detailOS << frontValue.getType(); 2462 2463 // FIXME: We should define a policy for packed values, e.g. with a limit 2464 // on the detail size, but it isn't clear what would be useful right now. 2465 // For now we just only emit the first type. 2466 if (it.second.size() > 1) 2467 detailOS << ", ..."; 2468 2469 state.codeCompleteContext->appendSSAValueCompletion( 2470 it.getKey(), std::move(detailData)); 2471 } 2472 } 2473 2474 return failure(); 2475 } 2476 2477 ParseResult OperationParser::codeCompleteBlock() { 2478 // Don't provide completions if the token isn't empty, e.g. this avoids 2479 // weirdness when we encounter a `.` within the identifier. 2480 StringRef spelling = getTokenSpelling(); 2481 if (!(spelling.empty() || spelling == "^")) 2482 return failure(); 2483 2484 for (const auto &it : blocksByName.back()) 2485 state.codeCompleteContext->appendBlockCompletion(it.getFirst()); 2486 return failure(); 2487 } 2488 2489 //===----------------------------------------------------------------------===// 2490 // Top-level entity parsing. 2491 //===----------------------------------------------------------------------===// 2492 2493 namespace { 2494 /// This parser handles entities that are only valid at the top level of the 2495 /// file. 2496 class TopLevelOperationParser : public Parser { 2497 public: 2498 explicit TopLevelOperationParser(ParserState &state) : Parser(state) {} 2499 2500 /// Parse a set of operations into the end of the given Block. 2501 ParseResult parse(Block *topLevelBlock, Location parserLoc); 2502 2503 private: 2504 /// Parse an attribute alias declaration. 2505 /// 2506 /// attribute-alias-def ::= '#' alias-name `=` attribute-value 2507 /// 2508 ParseResult parseAttributeAliasDef(); 2509 2510 /// Parse a type alias declaration. 2511 /// 2512 /// type-alias-def ::= '!' alias-name `=` type 2513 /// 2514 ParseResult parseTypeAliasDef(); 2515 2516 /// Parse a top-level file metadata dictionary. 2517 /// 2518 /// file-metadata-dict ::= '{-#' file-metadata-entry* `#-}' 2519 /// 2520 ParseResult parseFileMetadataDictionary(); 2521 2522 /// Parse a resource metadata dictionary. 2523 ParseResult parseResourceFileMetadata( 2524 function_ref<ParseResult(StringRef, SMLoc)> parseBody); 2525 ParseResult parseDialectResourceFileMetadata(); 2526 ParseResult parseExternalResourceFileMetadata(); 2527 }; 2528 2529 /// This class represents an implementation of a resource entry for the MLIR 2530 /// textual format. 2531 class ParsedResourceEntry : public AsmParsedResourceEntry { 2532 public: 2533 ParsedResourceEntry(StringRef key, SMLoc keyLoc, Token value, Parser &p) 2534 : key(key), keyLoc(keyLoc), value(value), p(p) {} 2535 ~ParsedResourceEntry() override = default; 2536 2537 StringRef getKey() const final { return key; } 2538 2539 InFlightDiagnostic emitError() const final { return p.emitError(keyLoc); } 2540 2541 AsmResourceEntryKind getKind() const final { 2542 if (value.isAny(Token::kw_true, Token::kw_false)) 2543 return AsmResourceEntryKind::Bool; 2544 return value.getSpelling().starts_with("\"0x") 2545 ? AsmResourceEntryKind::Blob 2546 : AsmResourceEntryKind::String; 2547 } 2548 2549 FailureOr<bool> parseAsBool() const final { 2550 if (value.is(Token::kw_true)) 2551 return true; 2552 if (value.is(Token::kw_false)) 2553 return false; 2554 return p.emitError(value.getLoc(), 2555 "expected 'true' or 'false' value for key '" + key + 2556 "'"); 2557 } 2558 2559 FailureOr<std::string> parseAsString() const final { 2560 if (value.isNot(Token::string)) 2561 return p.emitError(value.getLoc(), 2562 "expected string value for key '" + key + "'"); 2563 return value.getStringValue(); 2564 } 2565 2566 FailureOr<AsmResourceBlob> 2567 parseAsBlob(BlobAllocatorFn allocator) const final { 2568 // Blob data within then textual format is represented as a hex string. 2569 // TODO: We could avoid an additional alloc+copy here if we pre-allocated 2570 // the buffer to use during hex processing. 2571 std::optional<std::string> blobData = 2572 value.is(Token::string) ? value.getHexStringValue() : std::nullopt; 2573 if (!blobData) 2574 return p.emitError(value.getLoc(), 2575 "expected hex string blob for key '" + key + "'"); 2576 2577 // Extract the alignment of the blob data, which gets stored at the 2578 // beginning of the string. 2579 if (blobData->size() < sizeof(uint32_t)) { 2580 return p.emitError(value.getLoc(), 2581 "expected hex string blob for key '" + key + 2582 "' to encode alignment in first 4 bytes"); 2583 } 2584 llvm::support::ulittle32_t align; 2585 memcpy(&align, blobData->data(), sizeof(uint32_t)); 2586 if (align && !llvm::isPowerOf2_32(align)) { 2587 return p.emitError(value.getLoc(), 2588 "expected hex string blob for key '" + key + 2589 "' to encode alignment in first 4 bytes, but got " 2590 "non-power-of-2 value: " + 2591 Twine(align)); 2592 } 2593 2594 // Get the data portion of the blob. 2595 StringRef data = StringRef(*blobData).drop_front(sizeof(uint32_t)); 2596 if (data.empty()) 2597 return AsmResourceBlob(); 2598 2599 // Allocate memory for the blob using the provided allocator and copy the 2600 // data into it. 2601 AsmResourceBlob blob = allocator(data.size(), align); 2602 assert(llvm::isAddrAligned(llvm::Align(align), blob.getData().data()) && 2603 blob.isMutable() && 2604 "blob allocator did not return a properly aligned address"); 2605 memcpy(blob.getMutableData().data(), data.data(), data.size()); 2606 return blob; 2607 } 2608 2609 private: 2610 StringRef key; 2611 SMLoc keyLoc; 2612 Token value; 2613 Parser &p; 2614 }; 2615 } // namespace 2616 2617 ParseResult TopLevelOperationParser::parseAttributeAliasDef() { 2618 assert(getToken().is(Token::hash_identifier)); 2619 StringRef aliasName = getTokenSpelling().drop_front(); 2620 2621 // Check for redefinitions. 2622 if (state.symbols.attributeAliasDefinitions.count(aliasName) > 0) 2623 return emitError("redefinition of attribute alias id '" + aliasName + "'"); 2624 2625 // Make sure this isn't invading the dialect attribute namespace. 2626 if (aliasName.contains('.')) 2627 return emitError("attribute names with a '.' are reserved for " 2628 "dialect-defined names"); 2629 2630 SMRange location = getToken().getLocRange(); 2631 consumeToken(Token::hash_identifier); 2632 2633 // Parse the '='. 2634 if (parseToken(Token::equal, "expected '=' in attribute alias definition")) 2635 return failure(); 2636 2637 // Parse the attribute value. 2638 Attribute attr = parseAttribute(); 2639 if (!attr) 2640 return failure(); 2641 2642 // Register this alias with the parser state. 2643 if (state.asmState) 2644 state.asmState->addAttrAliasDefinition(aliasName, location, attr); 2645 state.symbols.attributeAliasDefinitions[aliasName] = attr; 2646 return success(); 2647 } 2648 2649 ParseResult TopLevelOperationParser::parseTypeAliasDef() { 2650 assert(getToken().is(Token::exclamation_identifier)); 2651 StringRef aliasName = getTokenSpelling().drop_front(); 2652 2653 // Check for redefinitions. 2654 if (state.symbols.typeAliasDefinitions.count(aliasName) > 0) 2655 return emitError("redefinition of type alias id '" + aliasName + "'"); 2656 2657 // Make sure this isn't invading the dialect type namespace. 2658 if (aliasName.contains('.')) 2659 return emitError("type names with a '.' are reserved for " 2660 "dialect-defined names"); 2661 2662 SMRange location = getToken().getLocRange(); 2663 consumeToken(Token::exclamation_identifier); 2664 2665 // Parse the '='. 2666 if (parseToken(Token::equal, "expected '=' in type alias definition")) 2667 return failure(); 2668 2669 // Parse the type. 2670 Type aliasedType = parseType(); 2671 if (!aliasedType) 2672 return failure(); 2673 2674 // Register this alias with the parser state. 2675 if (state.asmState) 2676 state.asmState->addTypeAliasDefinition(aliasName, location, aliasedType); 2677 state.symbols.typeAliasDefinitions.try_emplace(aliasName, aliasedType); 2678 return success(); 2679 } 2680 2681 ParseResult TopLevelOperationParser::parseFileMetadataDictionary() { 2682 consumeToken(Token::file_metadata_begin); 2683 return parseCommaSeparatedListUntil( 2684 Token::file_metadata_end, [&]() -> ParseResult { 2685 // Parse the key of the metadata dictionary. 2686 SMLoc keyLoc = getToken().getLoc(); 2687 StringRef key; 2688 if (failed(parseOptionalKeyword(&key))) 2689 return emitError("expected identifier key in file " 2690 "metadata dictionary"); 2691 if (parseToken(Token::colon, "expected ':'")) 2692 return failure(); 2693 2694 // Process the metadata entry. 2695 if (key == "dialect_resources") 2696 return parseDialectResourceFileMetadata(); 2697 if (key == "external_resources") 2698 return parseExternalResourceFileMetadata(); 2699 return emitError(keyLoc, "unknown key '" + key + 2700 "' in file metadata dictionary"); 2701 }); 2702 } 2703 2704 ParseResult TopLevelOperationParser::parseResourceFileMetadata( 2705 function_ref<ParseResult(StringRef, SMLoc)> parseBody) { 2706 if (parseToken(Token::l_brace, "expected '{'")) 2707 return failure(); 2708 2709 return parseCommaSeparatedListUntil(Token::r_brace, [&]() -> ParseResult { 2710 // Parse the top-level name entry. 2711 SMLoc nameLoc = getToken().getLoc(); 2712 StringRef name; 2713 if (failed(parseOptionalKeyword(&name))) 2714 return emitError("expected identifier key for 'resource' entry"); 2715 2716 if (parseToken(Token::colon, "expected ':'") || 2717 parseToken(Token::l_brace, "expected '{'")) 2718 return failure(); 2719 return parseBody(name, nameLoc); 2720 }); 2721 } 2722 2723 ParseResult TopLevelOperationParser::parseDialectResourceFileMetadata() { 2724 return parseResourceFileMetadata([&](StringRef name, 2725 SMLoc nameLoc) -> ParseResult { 2726 // Lookup the dialect and check that it can handle a resource entry. 2727 Dialect *dialect = getContext()->getOrLoadDialect(name); 2728 if (!dialect) 2729 return emitError(nameLoc, "dialect '" + name + "' is unknown"); 2730 const auto *handler = dyn_cast<OpAsmDialectInterface>(dialect); 2731 if (!handler) { 2732 return emitError() << "unexpected 'resource' section for dialect '" 2733 << dialect->getNamespace() << "'"; 2734 } 2735 2736 return parseCommaSeparatedListUntil(Token::r_brace, [&]() -> ParseResult { 2737 // Parse the name of the resource entry. 2738 SMLoc keyLoc = getToken().getLoc(); 2739 StringRef key; 2740 if (failed(parseResourceHandle(handler, key)) || 2741 parseToken(Token::colon, "expected ':'")) 2742 return failure(); 2743 Token valueTok = getToken(); 2744 consumeToken(); 2745 2746 ParsedResourceEntry entry(key, keyLoc, valueTok, *this); 2747 return handler->parseResource(entry); 2748 }); 2749 }); 2750 } 2751 2752 ParseResult TopLevelOperationParser::parseExternalResourceFileMetadata() { 2753 return parseResourceFileMetadata([&](StringRef name, 2754 SMLoc nameLoc) -> ParseResult { 2755 AsmResourceParser *handler = state.config.getResourceParser(name); 2756 2757 // TODO: Should we require handling external resources in some scenarios? 2758 if (!handler) { 2759 emitWarning(getEncodedSourceLocation(nameLoc)) 2760 << "ignoring unknown external resources for '" << name << "'"; 2761 } 2762 2763 return parseCommaSeparatedListUntil(Token::r_brace, [&]() -> ParseResult { 2764 // Parse the name of the resource entry. 2765 SMLoc keyLoc = getToken().getLoc(); 2766 StringRef key; 2767 if (failed(parseOptionalKeyword(&key))) 2768 return emitError( 2769 "expected identifier key for 'external_resources' entry"); 2770 if (parseToken(Token::colon, "expected ':'")) 2771 return failure(); 2772 Token valueTok = getToken(); 2773 consumeToken(); 2774 2775 if (!handler) 2776 return success(); 2777 ParsedResourceEntry entry(key, keyLoc, valueTok, *this); 2778 return handler->parseResource(entry); 2779 }); 2780 }); 2781 } 2782 2783 ParseResult TopLevelOperationParser::parse(Block *topLevelBlock, 2784 Location parserLoc) { 2785 // Create a top-level operation to contain the parsed state. 2786 OwningOpRef<ModuleOp> topLevelOp(ModuleOp::create(parserLoc)); 2787 OperationParser opParser(state, topLevelOp.get()); 2788 while (true) { 2789 switch (getToken().getKind()) { 2790 default: 2791 // Parse a top-level operation. 2792 if (opParser.parseOperation()) 2793 return failure(); 2794 break; 2795 2796 // If we got to the end of the file, then we're done. 2797 case Token::eof: { 2798 if (opParser.finalize()) 2799 return failure(); 2800 2801 // Splice the blocks of the parsed operation over to the provided 2802 // top-level block. 2803 auto &parsedOps = topLevelOp->getBody()->getOperations(); 2804 auto &destOps = topLevelBlock->getOperations(); 2805 destOps.splice(destOps.end(), parsedOps, parsedOps.begin(), 2806 parsedOps.end()); 2807 return success(); 2808 } 2809 2810 // If we got an error token, then the lexer already emitted an error, just 2811 // stop. Someday we could introduce error recovery if there was demand 2812 // for it. 2813 case Token::error: 2814 return failure(); 2815 2816 // Parse an attribute alias. 2817 case Token::hash_identifier: 2818 if (parseAttributeAliasDef()) 2819 return failure(); 2820 break; 2821 2822 // Parse a type alias. 2823 case Token::exclamation_identifier: 2824 if (parseTypeAliasDef()) 2825 return failure(); 2826 break; 2827 2828 // Parse a file-level metadata dictionary. 2829 case Token::file_metadata_begin: 2830 if (parseFileMetadataDictionary()) 2831 return failure(); 2832 break; 2833 } 2834 } 2835 } 2836 2837 //===----------------------------------------------------------------------===// 2838 2839 LogicalResult 2840 mlir::parseAsmSourceFile(const llvm::SourceMgr &sourceMgr, Block *block, 2841 const ParserConfig &config, AsmParserState *asmState, 2842 AsmParserCodeCompleteContext *codeCompleteContext) { 2843 const auto *sourceBuf = sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID()); 2844 2845 Location parserLoc = 2846 FileLineColLoc::get(config.getContext(), sourceBuf->getBufferIdentifier(), 2847 /*line=*/0, /*column=*/0); 2848 2849 SymbolState aliasState; 2850 ParserState state(sourceMgr, config, aliasState, asmState, 2851 codeCompleteContext); 2852 return TopLevelOperationParser(state).parse(block, parserLoc); 2853 } 2854