[mlir] Use StringRef::{starts,ends}_with (NFC)
[llvm-project.git] / mlir / lib / AsmParser / Parser.cpp
blob3aa9adcbe1c5dfaaf3d1bced3f9e9add1d0e41eb
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.
11 //===----------------------------------------------------------------------===//
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/LogicalResult.h"
38 #include "mlir/Support/TypeID.h"
39 #include "llvm/ADT/APFloat.h"
40 #include "llvm/ADT/DenseMap.h"
41 #include "llvm/ADT/PointerUnion.h"
42 #include "llvm/ADT/STLExtras.h"
43 #include "llvm/ADT/ScopeExit.h"
44 #include "llvm/ADT/Sequence.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>
67 using namespace mlir;
68 using namespace mlir::detail;
70 //===----------------------------------------------------------------------===//
71 // CodeComplete
72 //===----------------------------------------------------------------------===//
74 AsmParserCodeCompleteContext::~AsmParserCodeCompleteContext() = default;
76 //===----------------------------------------------------------------------===//
77 // Parser
78 //===----------------------------------------------------------------------===//
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;
137 // Non-empty case starts with an element.
138 if (parseElementFn())
139 return failure();
141 // Otherwise we have a list of comma separated elements.
142 while (consumeIf(Token::comma)) {
143 if (parseElementFn())
144 return failure();
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);
163 llvm_unreachable("Unknown delimiter");
166 /// Parse a comma-separated list of elements, terminated with an arbitrary
167 /// token. This allows empty lists if allowEmptyList is true.
169 /// abstract-list ::= rightToken // if allowEmptyList == true
170 /// abstract-list ::= element (',' element)* rightToken
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();
184 if (parseCommaSeparatedList(parseElement) ||
185 parseToken(rightToken, "expected ',' or '" +
186 Token::getTokenSpelling(rightToken) + "'"))
187 return failure();
189 return success();
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);
197 // If the error is to be emitted at EOF, move it back one character.
198 return emitError(SMLoc::getFromPointer(loc.getPointer() - 1), message);
201 InFlightDiagnostic Parser::emitError(SMLoc loc, const Twine &message) {
202 auto diag = mlir::emitError(getEncodedSourceLocation(loc), message);
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;
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();
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);
222 // This is the location we were originally asked to report the error at.
223 auto originalLoc = loc;
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();
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);
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");
238 // For tokens with no preceding source line, just emit at the original
239 // location.
240 if (startOfBuffer.empty())
241 return emitError(originalLoc, message);
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);
247 // Drop the \n so we emit the diagnostic at the end of the line.
248 startOfBuffer = startOfBuffer.drop_back();
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);
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);
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);
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();
281 if (consumeIf(Token::kw_true)) {
282 result = true;
283 return success();
286 Token curToken = getToken();
287 if (curToken.isNot(Token::integer, Token::minus))
288 return std::nullopt;
290 bool negative = consumeIf(Token::minus);
291 Token curTok = getToken();
292 if (parseToken(Token::integer, "expected integer value"))
293 return failure();
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");
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);
304 // Process the negative sign if present.
305 if (negative)
306 result.negate();
308 return success();
311 /// Parse a floating point value from an integer literal token.
312 ParseResult Parser::parseFloatFromIntegerLiteral(
313 std::optional<APFloat> &result, const Token &tok, bool isNegative,
314 const llvm::fltSemantics &semantics, size_t typeSizeInBits) {
315 SMLoc loc = tok.getLoc();
316 StringRef spelling = tok.getSpelling();
317 bool isHex = spelling.size() > 1 && spelling[1] == 'x';
318 if (!isHex) {
319 return emitError(loc, "unexpected decimal integer literal for a "
320 "floating point value")
321 .attachNote()
322 << "add a trailing dot to make the literal a float";
324 if (isNegative) {
325 return emitError(loc, "hexadecimal float literal should not have a "
326 "leading minus");
329 std::optional<uint64_t> value = tok.getUInt64IntegerValue();
330 if (!value)
331 return emitError(loc, "hexadecimal float constant out of range for type");
333 if (&semantics == &APFloat::IEEEdouble()) {
334 result = APFloat(semantics, APInt(typeSizeInBits, *value));
335 return success();
338 APInt apInt(typeSizeInBits, *value);
339 if (apInt != *value)
340 return emitError(loc, "hexadecimal float constant out of range for type");
341 result = APFloat(semantics, apInt);
343 return success();
346 ParseResult Parser::parseOptionalKeyword(StringRef *keyword) {
347 // Check that the current token is a keyword.
348 if (!isCurrentTokenAKeyword())
349 return failure();
351 *keyword = getTokenSpelling();
352 consumeToken();
353 return success();
356 //===----------------------------------------------------------------------===//
357 // Resource Parsing
359 FailureOr<AsmDialectResourceHandle>
360 Parser::parseResourceHandle(const OpAsmDialectInterface *dialect,
361 StringRef &name) {
362 assert(dialect && "expected valid dialect interface");
363 SMLoc nameLoc = getToken().getLoc();
364 if (failed(parseOptionalKeyword(&name)))
365 return emitError("expected identifier key for 'resource' entry");
366 auto &resources = getState().symbols.dialectResources;
368 // If this is the first time encountering this handle, ask the dialect to
369 // resolve a reference to this handle. This allows for us to remap the name of
370 // the handle if necessary.
371 std::pair<std::string, AsmDialectResourceHandle> &entry =
372 resources[dialect][name];
373 if (entry.first.empty()) {
374 FailureOr<AsmDialectResourceHandle> result = dialect->declareResource(name);
375 if (failed(result)) {
376 return emitError(nameLoc)
377 << "unknown 'resource' key '" << name << "' for dialect '"
378 << dialect->getDialect()->getNamespace() << "'";
380 entry.first = dialect->getResourceKey(*result);
381 entry.second = *result;
384 name = entry.first;
385 return entry.second;
388 FailureOr<AsmDialectResourceHandle>
389 Parser::parseResourceHandle(Dialect *dialect) {
390 const auto *interface = dyn_cast<OpAsmDialectInterface>(dialect);
391 if (!interface) {
392 return emitError() << "dialect '" << dialect->getNamespace()
393 << "' does not expect resource handles";
395 StringRef resourceName;
396 return parseResourceHandle(interface, resourceName);
399 //===----------------------------------------------------------------------===//
400 // Code Completion
402 ParseResult Parser::codeCompleteDialectName() {
403 state.codeCompleteContext->completeDialectName();
404 return failure();
407 ParseResult Parser::codeCompleteOperationName(StringRef dialectName) {
408 // Perform some simple validation on the dialect name. This doesn't need to be
409 // extensive, it's more of an optimization (to avoid checking completion
410 // results when we know they will fail).
411 if (dialectName.empty() || dialectName.contains('.'))
412 return failure();
413 state.codeCompleteContext->completeOperationName(dialectName);
414 return failure();
417 ParseResult Parser::codeCompleteDialectOrElidedOpName(SMLoc loc) {
418 // Check to see if there is anything else on the current line. This check
419 // isn't strictly necessary, but it does avoid unnecessarily triggering
420 // completions for operations and dialects in situations where we don't want
421 // them (e.g. at the end of an operation).
422 auto shouldIgnoreOpCompletion = [&]() {
423 const char *bufBegin = state.lex.getBufferBegin();
424 const char *it = loc.getPointer() - 1;
425 for (; it > bufBegin && *it != '\n'; --it)
426 if (!StringRef(" \t\r").contains(*it))
427 return true;
428 return false;
430 if (shouldIgnoreOpCompletion())
431 return failure();
433 // The completion here is either for a dialect name, or an operation name
434 // whose dialect prefix was elided. For this we simply invoke both of the
435 // individual completion methods.
436 (void)codeCompleteDialectName();
437 return codeCompleteOperationName(state.defaultDialectStack.back());
440 ParseResult Parser::codeCompleteStringDialectOrOperationName(StringRef name) {
441 // If the name is empty, this is the start of the string and contains the
442 // dialect.
443 if (name.empty())
444 return codeCompleteDialectName();
446 // Otherwise, we treat this as completing an operation name. The current name
447 // is used as the dialect namespace.
448 if (name.consume_back("."))
449 return codeCompleteOperationName(name);
450 return failure();
453 ParseResult Parser::codeCompleteExpectedTokens(ArrayRef<StringRef> tokens) {
454 state.codeCompleteContext->completeExpectedTokens(tokens, /*optional=*/false);
455 return failure();
457 ParseResult Parser::codeCompleteOptionalTokens(ArrayRef<StringRef> tokens) {
458 state.codeCompleteContext->completeExpectedTokens(tokens, /*optional=*/true);
459 return failure();
462 Attribute Parser::codeCompleteAttribute() {
463 state.codeCompleteContext->completeAttribute(
464 state.symbols.attributeAliasDefinitions);
465 return {};
467 Type Parser::codeCompleteType() {
468 state.codeCompleteContext->completeType(state.symbols.typeAliasDefinitions);
469 return {};
472 Attribute
473 Parser::codeCompleteDialectSymbol(const llvm::StringMap<Attribute> &aliases) {
474 state.codeCompleteContext->completeDialectAttributeOrAlias(aliases);
475 return {};
477 Type Parser::codeCompleteDialectSymbol(const llvm::StringMap<Type> &aliases) {
478 state.codeCompleteContext->completeDialectTypeOrAlias(aliases);
479 return {};
482 //===----------------------------------------------------------------------===//
483 // OperationParser
484 //===----------------------------------------------------------------------===//
486 namespace {
487 /// This class provides support for parsing operations and regions of
488 /// operations.
489 class OperationParser : public Parser {
490 public:
491 OperationParser(ParserState &state, ModuleOp topLevelOp);
492 ~OperationParser();
494 /// After parsing is finished, this function must be called to see if there
495 /// are any remaining issues.
496 ParseResult finalize();
498 //===--------------------------------------------------------------------===//
499 // SSA Value Handling
500 //===--------------------------------------------------------------------===//
502 using UnresolvedOperand = OpAsmParser::UnresolvedOperand;
503 using Argument = OpAsmParser::Argument;
505 struct DeferredLocInfo {
506 SMLoc loc;
507 StringRef identifier;
510 /// Push a new SSA name scope to the parser.
511 void pushSSANameScope(bool isIsolated);
513 /// Pop the last SSA name scope from the parser.
514 ParseResult popSSANameScope();
516 /// Register a definition of a value with the symbol table.
517 ParseResult addDefinition(UnresolvedOperand useInfo, Value value);
519 /// Parse an optional list of SSA uses into 'results'.
520 ParseResult
521 parseOptionalSSAUseList(SmallVectorImpl<UnresolvedOperand> &results);
523 /// Parse a single SSA use into 'result'. If 'allowResultNumber' is true then
524 /// we allow #42 syntax.
525 ParseResult parseSSAUse(UnresolvedOperand &result,
526 bool allowResultNumber = true);
528 /// Given a reference to an SSA value and its type, return a reference. This
529 /// returns null on failure.
530 Value resolveSSAUse(UnresolvedOperand useInfo, Type type);
532 ParseResult parseSSADefOrUseAndType(
533 function_ref<ParseResult(UnresolvedOperand, Type)> action);
535 ParseResult parseOptionalSSAUseAndTypeList(SmallVectorImpl<Value> &results);
537 /// Return the location of the value identified by its name and number if it
538 /// has been already reference.
539 std::optional<SMLoc> getReferenceLoc(StringRef name, unsigned number) {
540 auto &values = isolatedNameScopes.back().values;
541 if (!values.count(name) || number >= values[name].size())
542 return {};
543 if (values[name][number].value)
544 return values[name][number].loc;
545 return {};
548 //===--------------------------------------------------------------------===//
549 // Operation Parsing
550 //===--------------------------------------------------------------------===//
552 /// Parse an operation instance.
553 ParseResult parseOperation();
555 /// Parse a single operation successor.
556 ParseResult parseSuccessor(Block *&dest);
558 /// Parse a comma-separated list of operation successors in brackets.
559 ParseResult parseSuccessors(SmallVectorImpl<Block *> &destinations);
561 /// Parse an operation instance that is in the generic form.
562 Operation *parseGenericOperation();
564 /// Parse different components, viz., use-info of operand(s), successor(s),
565 /// region(s), attribute(s) and function-type, of the generic form of an
566 /// operation instance and populate the input operation-state 'result' with
567 /// those components. If any of the components is explicitly provided, then
568 /// skip parsing that component.
569 ParseResult parseGenericOperationAfterOpName(
570 OperationState &result,
571 std::optional<ArrayRef<UnresolvedOperand>> parsedOperandUseInfo =
572 std::nullopt,
573 std::optional<ArrayRef<Block *>> parsedSuccessors = std::nullopt,
574 std::optional<MutableArrayRef<std::unique_ptr<Region>>> parsedRegions =
575 std::nullopt,
576 std::optional<ArrayRef<NamedAttribute>> parsedAttributes = std::nullopt,
577 std::optional<Attribute> propertiesAttribute = std::nullopt,
578 std::optional<FunctionType> parsedFnType = std::nullopt);
580 /// Parse an operation instance that is in the generic form and insert it at
581 /// the provided insertion point.
582 Operation *parseGenericOperation(Block *insertBlock,
583 Block::iterator insertPt);
585 /// This type is used to keep track of things that are either an Operation or
586 /// a BlockArgument. We cannot use Value for this, because not all Operations
587 /// have results.
588 using OpOrArgument = llvm::PointerUnion<Operation *, BlockArgument>;
590 /// Parse an optional trailing location and add it to the specifier Operation
591 /// or `UnresolvedOperand` if present.
593 /// trailing-location ::= (`loc` (`(` location `)` | attribute-alias))?
595 ParseResult parseTrailingLocationSpecifier(OpOrArgument opOrArgument);
597 /// Parse a location alias, that is a sequence looking like: #loc42
598 /// The alias may have already be defined or may be defined later, in which
599 /// case an OpaqueLoc is used a placeholder.
600 ParseResult parseLocationAlias(LocationAttr &loc);
602 /// This is the structure of a result specifier in the assembly syntax,
603 /// including the name, number of results, and location.
604 using ResultRecord = std::tuple<StringRef, unsigned, SMLoc>;
606 /// Parse an operation instance that is in the op-defined custom form.
607 /// resultInfo specifies information about the "%name =" specifiers.
608 Operation *parseCustomOperation(ArrayRef<ResultRecord> resultIDs);
610 /// Parse the name of an operation, in the custom form. On success, return a
611 /// an object of type 'OperationName'. Otherwise, failure is returned.
612 FailureOr<OperationName> parseCustomOperationName();
614 //===--------------------------------------------------------------------===//
615 // Region Parsing
616 //===--------------------------------------------------------------------===//
618 /// Parse a region into 'region' with the provided entry block arguments.
619 /// 'isIsolatedNameScope' indicates if the naming scope of this region is
620 /// isolated from those above.
621 ParseResult parseRegion(Region &region, ArrayRef<Argument> entryArguments,
622 bool isIsolatedNameScope = false);
624 /// Parse a region body into 'region'.
625 ParseResult parseRegionBody(Region &region, SMLoc startLoc,
626 ArrayRef<Argument> entryArguments,
627 bool isIsolatedNameScope);
629 //===--------------------------------------------------------------------===//
630 // Block Parsing
631 //===--------------------------------------------------------------------===//
633 /// Parse a new block into 'block'.
634 ParseResult parseBlock(Block *&block);
636 /// Parse a list of operations into 'block'.
637 ParseResult parseBlockBody(Block *block);
639 /// Parse a (possibly empty) list of block arguments.
640 ParseResult parseOptionalBlockArgList(Block *owner);
642 /// Get the block with the specified name, creating it if it doesn't
643 /// already exist. The location specified is the point of use, which allows
644 /// us to diagnose references to blocks that are not defined precisely.
645 Block *getBlockNamed(StringRef name, SMLoc loc);
647 //===--------------------------------------------------------------------===//
648 // Code Completion
649 //===--------------------------------------------------------------------===//
651 /// The set of various code completion methods. Every completion method
652 /// returns `failure` to stop the parsing process after providing completion
653 /// results.
655 ParseResult codeCompleteSSAUse();
656 ParseResult codeCompleteBlock();
658 private:
659 /// This class represents a definition of a Block.
660 struct BlockDefinition {
661 /// A pointer to the defined Block.
662 Block *block;
663 /// The location that the Block was defined at.
664 SMLoc loc;
666 /// This class represents a definition of a Value.
667 struct ValueDefinition {
668 /// A pointer to the defined Value.
669 Value value;
670 /// The location that the Value was defined at.
671 SMLoc loc;
674 /// Returns the info for a block at the current scope for the given name.
675 BlockDefinition &getBlockInfoByName(StringRef name) {
676 return blocksByName.back()[name];
679 /// Insert a new forward reference to the given block.
680 void insertForwardRef(Block *block, SMLoc loc) {
681 forwardRef.back().try_emplace(block, loc);
684 /// Erase any forward reference to the given block.
685 bool eraseForwardRef(Block *block) { return forwardRef.back().erase(block); }
687 /// Record that a definition was added at the current scope.
688 void recordDefinition(StringRef def);
690 /// Get the value entry for the given SSA name.
691 SmallVectorImpl<ValueDefinition> &getSSAValueEntry(StringRef name);
693 /// Create a forward reference placeholder value with the given location and
694 /// result type.
695 Value createForwardRefPlaceholder(SMLoc loc, Type type);
697 /// Return true if this is a forward reference.
698 bool isForwardRefPlaceholder(Value value) {
699 return forwardRefPlaceholders.count(value);
702 /// This struct represents an isolated SSA name scope. This scope may contain
703 /// other nested non-isolated scopes. These scopes are used for operations
704 /// that are known to be isolated to allow for reusing names within their
705 /// regions, even if those names are used above.
706 struct IsolatedSSANameScope {
707 /// Record that a definition was added at the current scope.
708 void recordDefinition(StringRef def) {
709 definitionsPerScope.back().insert(def);
712 /// Push a nested name scope.
713 void pushSSANameScope() { definitionsPerScope.push_back({}); }
715 /// Pop a nested name scope.
716 void popSSANameScope() {
717 for (auto &def : definitionsPerScope.pop_back_val())
718 values.erase(def.getKey());
721 /// This keeps track of all of the SSA values we are tracking for each name
722 /// scope, indexed by their name. This has one entry per result number.
723 llvm::StringMap<SmallVector<ValueDefinition, 1>> values;
725 /// This keeps track of all of the values defined by a specific name scope.
726 SmallVector<llvm::StringSet<>, 2> definitionsPerScope;
729 /// A list of isolated name scopes.
730 SmallVector<IsolatedSSANameScope, 2> isolatedNameScopes;
732 /// This keeps track of the block names as well as the location of the first
733 /// reference for each nested name scope. This is used to diagnose invalid
734 /// block references and memorize them.
735 SmallVector<DenseMap<StringRef, BlockDefinition>, 2> blocksByName;
736 SmallVector<DenseMap<Block *, SMLoc>, 2> forwardRef;
738 /// These are all of the placeholders we've made along with the location of
739 /// their first reference, to allow checking for use of undefined values.
740 DenseMap<Value, SMLoc> forwardRefPlaceholders;
742 /// Deffered locations: when parsing `loc(#loc42)` we add an entry to this
743 /// map. After parsing the definition `#loc42 = ...` we'll patch back users
744 /// of this location.
745 std::vector<DeferredLocInfo> deferredLocsReferences;
747 /// The builder used when creating parsed operation instances.
748 OpBuilder opBuilder;
750 /// The top level operation that holds all of the parsed operations.
751 Operation *topLevelOp;
753 } // namespace
755 MLIR_DECLARE_EXPLICIT_TYPE_ID(OperationParser::DeferredLocInfo *)
756 MLIR_DEFINE_EXPLICIT_TYPE_ID(OperationParser::DeferredLocInfo *)
758 OperationParser::OperationParser(ParserState &state, ModuleOp topLevelOp)
759 : Parser(state), opBuilder(topLevelOp.getRegion()), topLevelOp(topLevelOp) {
760 // The top level operation starts a new name scope.
761 pushSSANameScope(/*isIsolated=*/true);
763 // If we are populating the parser state, prepare it for parsing.
764 if (state.asmState)
765 state.asmState->initialize(topLevelOp);
768 OperationParser::~OperationParser() {
769 for (auto &fwd : forwardRefPlaceholders) {
770 // Drop all uses of undefined forward declared reference and destroy
771 // defining operation.
772 fwd.first.dropAllUses();
773 fwd.first.getDefiningOp()->destroy();
775 for (const auto &scope : forwardRef) {
776 for (const auto &fwd : scope) {
777 // Delete all blocks that were created as forward references but never
778 // included into a region.
779 fwd.first->dropAllUses();
780 delete fwd.first;
785 /// After parsing is finished, this function must be called to see if there are
786 /// any remaining issues.
787 ParseResult OperationParser::finalize() {
788 // Check for any forward references that are left. If we find any, error
789 // out.
790 if (!forwardRefPlaceholders.empty()) {
791 SmallVector<const char *, 4> errors;
792 // Iteration over the map isn't deterministic, so sort by source location.
793 for (auto entry : forwardRefPlaceholders)
794 errors.push_back(entry.second.getPointer());
795 llvm::array_pod_sort(errors.begin(), errors.end());
797 for (const char *entry : errors) {
798 auto loc = SMLoc::getFromPointer(entry);
799 emitError(loc, "use of undeclared SSA value name");
801 return failure();
804 // Resolve the locations of any deferred operations.
805 auto &attributeAliases = state.symbols.attributeAliasDefinitions;
806 auto locID = TypeID::get<DeferredLocInfo *>();
807 auto resolveLocation = [&, this](auto &opOrArgument) -> LogicalResult {
808 auto fwdLoc = dyn_cast<OpaqueLoc>(opOrArgument.getLoc());
809 if (!fwdLoc || fwdLoc.getUnderlyingTypeID() != locID)
810 return success();
811 auto locInfo = deferredLocsReferences[fwdLoc.getUnderlyingLocation()];
812 Attribute attr = attributeAliases.lookup(locInfo.identifier);
813 if (!attr)
814 return this->emitError(locInfo.loc)
815 << "operation location alias was never defined";
816 auto locAttr = dyn_cast<LocationAttr>(attr);
817 if (!locAttr)
818 return this->emitError(locInfo.loc)
819 << "expected location, but found '" << attr << "'";
820 opOrArgument.setLoc(locAttr);
821 return success();
824 auto walkRes = topLevelOp->walk([&](Operation *op) {
825 if (failed(resolveLocation(*op)))
826 return WalkResult::interrupt();
827 for (Region &region : op->getRegions())
828 for (Block &block : region.getBlocks())
829 for (BlockArgument arg : block.getArguments())
830 if (failed(resolveLocation(arg)))
831 return WalkResult::interrupt();
832 return WalkResult::advance();
834 if (walkRes.wasInterrupted())
835 return failure();
837 // Pop the top level name scope.
838 if (failed(popSSANameScope()))
839 return failure();
841 // Verify that the parsed operations are valid.
842 if (state.config.shouldVerifyAfterParse() && failed(verify(topLevelOp)))
843 return failure();
845 // If we are populating the parser state, finalize the top-level operation.
846 if (state.asmState)
847 state.asmState->finalize(topLevelOp);
848 return success();
851 //===----------------------------------------------------------------------===//
852 // SSA Value Handling
853 //===----------------------------------------------------------------------===//
855 void OperationParser::pushSSANameScope(bool isIsolated) {
856 blocksByName.push_back(DenseMap<StringRef, BlockDefinition>());
857 forwardRef.push_back(DenseMap<Block *, SMLoc>());
859 // Push back a new name definition scope.
860 if (isIsolated)
861 isolatedNameScopes.push_back({});
862 isolatedNameScopes.back().pushSSANameScope();
865 ParseResult OperationParser::popSSANameScope() {
866 auto forwardRefInCurrentScope = forwardRef.pop_back_val();
868 // Verify that all referenced blocks were defined.
869 if (!forwardRefInCurrentScope.empty()) {
870 SmallVector<std::pair<const char *, Block *>, 4> errors;
871 // Iteration over the map isn't deterministic, so sort by source location.
872 for (auto entry : forwardRefInCurrentScope) {
873 errors.push_back({entry.second.getPointer(), entry.first});
874 // Add this block to the top-level region to allow for automatic cleanup.
875 topLevelOp->getRegion(0).push_back(entry.first);
877 llvm::array_pod_sort(errors.begin(), errors.end());
879 for (auto entry : errors) {
880 auto loc = SMLoc::getFromPointer(entry.first);
881 emitError(loc, "reference to an undefined block");
883 return failure();
886 // Pop the next nested namescope. If there is only one internal namescope,
887 // just pop the isolated scope.
888 auto &currentNameScope = isolatedNameScopes.back();
889 if (currentNameScope.definitionsPerScope.size() == 1)
890 isolatedNameScopes.pop_back();
891 else
892 currentNameScope.popSSANameScope();
894 blocksByName.pop_back();
895 return success();
898 /// Register a definition of a value with the symbol table.
899 ParseResult OperationParser::addDefinition(UnresolvedOperand useInfo,
900 Value value) {
901 auto &entries = getSSAValueEntry(useInfo.name);
903 // Make sure there is a slot for this value.
904 if (entries.size() <= useInfo.number)
905 entries.resize(useInfo.number + 1);
907 // If we already have an entry for this, check to see if it was a definition
908 // or a forward reference.
909 if (auto existing = entries[useInfo.number].value) {
910 if (!isForwardRefPlaceholder(existing)) {
911 return emitError(useInfo.location)
912 .append("redefinition of SSA value '", useInfo.name, "'")
913 .attachNote(getEncodedSourceLocation(entries[useInfo.number].loc))
914 .append("previously defined here");
917 if (existing.getType() != value.getType()) {
918 return emitError(useInfo.location)
919 .append("definition of SSA value '", useInfo.name, "#",
920 useInfo.number, "' has type ", value.getType())
921 .attachNote(getEncodedSourceLocation(entries[useInfo.number].loc))
922 .append("previously used here with type ", existing.getType());
925 // If it was a forward reference, update everything that used it to use
926 // the actual definition instead, delete the forward ref, and remove it
927 // from our set of forward references we track.
928 existing.replaceAllUsesWith(value);
929 existing.getDefiningOp()->destroy();
930 forwardRefPlaceholders.erase(existing);
932 // If a definition of the value already exists, replace it in the assembly
933 // state.
934 if (state.asmState)
935 state.asmState->refineDefinition(existing, value);
938 /// Record this definition for the current scope.
939 entries[useInfo.number] = {value, useInfo.location};
940 recordDefinition(useInfo.name);
941 return success();
944 /// Parse a (possibly empty) list of SSA operands.
946 /// ssa-use-list ::= ssa-use (`,` ssa-use)*
947 /// ssa-use-list-opt ::= ssa-use-list?
949 ParseResult OperationParser::parseOptionalSSAUseList(
950 SmallVectorImpl<UnresolvedOperand> &results) {
951 if (!getToken().isOrIsCodeCompletionFor(Token::percent_identifier))
952 return success();
953 return parseCommaSeparatedList([&]() -> ParseResult {
954 UnresolvedOperand result;
955 if (parseSSAUse(result))
956 return failure();
957 results.push_back(result);
958 return success();
962 /// Parse a SSA operand for an operation.
964 /// ssa-use ::= ssa-id
966 ParseResult OperationParser::parseSSAUse(UnresolvedOperand &result,
967 bool allowResultNumber) {
968 if (getToken().isCodeCompletion())
969 return codeCompleteSSAUse();
971 result.name = getTokenSpelling();
972 result.number = 0;
973 result.location = getToken().getLoc();
974 if (parseToken(Token::percent_identifier, "expected SSA operand"))
975 return failure();
977 // If we have an attribute ID, it is a result number.
978 if (getToken().is(Token::hash_identifier)) {
979 if (!allowResultNumber)
980 return emitError("result number not allowed in argument list");
982 if (auto value = getToken().getHashIdentifierNumber())
983 result.number = *value;
984 else
985 return emitError("invalid SSA value result number");
986 consumeToken(Token::hash_identifier);
989 return success();
992 /// Given an unbound reference to an SSA value and its type, return the value
993 /// it specifies. This returns null on failure.
994 Value OperationParser::resolveSSAUse(UnresolvedOperand useInfo, Type type) {
995 auto &entries = getSSAValueEntry(useInfo.name);
997 // Functor used to record the use of the given value if the assembly state
998 // field is populated.
999 auto maybeRecordUse = [&](Value value) {
1000 if (state.asmState)
1001 state.asmState->addUses(value, useInfo.location);
1002 return value;
1005 // If we have already seen a value of this name, return it.
1006 if (useInfo.number < entries.size() && entries[useInfo.number].value) {
1007 Value result = entries[useInfo.number].value;
1008 // Check that the type matches the other uses.
1009 if (result.getType() == type)
1010 return maybeRecordUse(result);
1012 emitError(useInfo.location, "use of value '")
1013 .append(useInfo.name,
1014 "' expects different type than prior uses: ", type, " vs ",
1015 result.getType())
1016 .attachNote(getEncodedSourceLocation(entries[useInfo.number].loc))
1017 .append("prior use here");
1018 return nullptr;
1021 // Make sure we have enough slots for this.
1022 if (entries.size() <= useInfo.number)
1023 entries.resize(useInfo.number + 1);
1025 // If the value has already been defined and this is an overly large result
1026 // number, diagnose that.
1027 if (entries[0].value && !isForwardRefPlaceholder(entries[0].value))
1028 return (emitError(useInfo.location, "reference to invalid result number"),
1029 nullptr);
1031 // Otherwise, this is a forward reference. Create a placeholder and remember
1032 // that we did so.
1033 Value result = createForwardRefPlaceholder(useInfo.location, type);
1034 entries[useInfo.number] = {result, useInfo.location};
1035 return maybeRecordUse(result);
1038 /// Parse an SSA use with an associated type.
1040 /// ssa-use-and-type ::= ssa-use `:` type
1041 ParseResult OperationParser::parseSSADefOrUseAndType(
1042 function_ref<ParseResult(UnresolvedOperand, Type)> action) {
1043 UnresolvedOperand useInfo;
1044 if (parseSSAUse(useInfo) ||
1045 parseToken(Token::colon, "expected ':' and type for SSA operand"))
1046 return failure();
1048 auto type = parseType();
1049 if (!type)
1050 return failure();
1052 return action(useInfo, type);
1055 /// Parse a (possibly empty) list of SSA operands, followed by a colon, then
1056 /// followed by a type list.
1058 /// ssa-use-and-type-list
1059 /// ::= ssa-use-list ':' type-list-no-parens
1061 ParseResult OperationParser::parseOptionalSSAUseAndTypeList(
1062 SmallVectorImpl<Value> &results) {
1063 SmallVector<UnresolvedOperand, 4> valueIDs;
1064 if (parseOptionalSSAUseList(valueIDs))
1065 return failure();
1067 // If there were no operands, then there is no colon or type lists.
1068 if (valueIDs.empty())
1069 return success();
1071 SmallVector<Type, 4> types;
1072 if (parseToken(Token::colon, "expected ':' in operand list") ||
1073 parseTypeListNoParens(types))
1074 return failure();
1076 if (valueIDs.size() != types.size())
1077 return emitError("expected ")
1078 << valueIDs.size() << " types to match operand list";
1080 results.reserve(valueIDs.size());
1081 for (unsigned i = 0, e = valueIDs.size(); i != e; ++i) {
1082 if (auto value = resolveSSAUse(valueIDs[i], types[i]))
1083 results.push_back(value);
1084 else
1085 return failure();
1088 return success();
1091 /// Record that a definition was added at the current scope.
1092 void OperationParser::recordDefinition(StringRef def) {
1093 isolatedNameScopes.back().recordDefinition(def);
1096 /// Get the value entry for the given SSA name.
1097 auto OperationParser::getSSAValueEntry(StringRef name)
1098 -> SmallVectorImpl<ValueDefinition> & {
1099 return isolatedNameScopes.back().values[name];
1102 /// Create and remember a new placeholder for a forward reference.
1103 Value OperationParser::createForwardRefPlaceholder(SMLoc loc, Type type) {
1104 // Forward references are always created as operations, because we just need
1105 // something with a def/use chain.
1107 // We create these placeholders as having an empty name, which we know
1108 // cannot be created through normal user input, allowing us to distinguish
1109 // them.
1110 auto name = OperationName("builtin.unrealized_conversion_cast", getContext());
1111 auto *op = Operation::create(
1112 getEncodedSourceLocation(loc), name, type, /*operands=*/{},
1113 /*attributes=*/std::nullopt, /*properties=*/nullptr, /*successors=*/{},
1114 /*numRegions=*/0);
1115 forwardRefPlaceholders[op->getResult(0)] = loc;
1116 return op->getResult(0);
1119 //===----------------------------------------------------------------------===//
1120 // Operation Parsing
1121 //===----------------------------------------------------------------------===//
1123 /// Parse an operation.
1125 /// operation ::= op-result-list?
1126 /// (generic-operation | custom-operation)
1127 /// trailing-location?
1128 /// generic-operation ::= string-literal `(` ssa-use-list? `)`
1129 /// successor-list? (`(` region-list `)`)?
1130 /// attribute-dict? `:` function-type
1131 /// custom-operation ::= bare-id custom-operation-format
1132 /// op-result-list ::= op-result (`,` op-result)* `=`
1133 /// op-result ::= ssa-id (`:` integer-literal)
1135 ParseResult OperationParser::parseOperation() {
1136 auto loc = getToken().getLoc();
1137 SmallVector<ResultRecord, 1> resultIDs;
1138 size_t numExpectedResults = 0;
1139 if (getToken().is(Token::percent_identifier)) {
1140 // Parse the group of result ids.
1141 auto parseNextResult = [&]() -> ParseResult {
1142 // Parse the next result id.
1143 Token nameTok = getToken();
1144 if (parseToken(Token::percent_identifier,
1145 "expected valid ssa identifier"))
1146 return failure();
1148 // If the next token is a ':', we parse the expected result count.
1149 size_t expectedSubResults = 1;
1150 if (consumeIf(Token::colon)) {
1151 // Check that the next token is an integer.
1152 if (!getToken().is(Token::integer))
1153 return emitWrongTokenError("expected integer number of results");
1155 // Check that number of results is > 0.
1156 auto val = getToken().getUInt64IntegerValue();
1157 if (!val || *val < 1)
1158 return emitError(
1159 "expected named operation to have at least 1 result");
1160 consumeToken(Token::integer);
1161 expectedSubResults = *val;
1164 resultIDs.emplace_back(nameTok.getSpelling(), expectedSubResults,
1165 nameTok.getLoc());
1166 numExpectedResults += expectedSubResults;
1167 return success();
1169 if (parseCommaSeparatedList(parseNextResult))
1170 return failure();
1172 if (parseToken(Token::equal, "expected '=' after SSA name"))
1173 return failure();
1176 Operation *op;
1177 Token nameTok = getToken();
1178 if (nameTok.is(Token::bare_identifier) || nameTok.isKeyword())
1179 op = parseCustomOperation(resultIDs);
1180 else if (nameTok.is(Token::string))
1181 op = parseGenericOperation();
1182 else if (nameTok.isCodeCompletionFor(Token::string))
1183 return codeCompleteStringDialectOrOperationName(nameTok.getStringValue());
1184 else if (nameTok.isCodeCompletion())
1185 return codeCompleteDialectOrElidedOpName(loc);
1186 else
1187 return emitWrongTokenError("expected operation name in quotes");
1189 // If parsing of the basic operation failed, then this whole thing fails.
1190 if (!op)
1191 return failure();
1193 // If the operation had a name, register it.
1194 if (!resultIDs.empty()) {
1195 if (op->getNumResults() == 0)
1196 return emitError(loc, "cannot name an operation with no results");
1197 if (numExpectedResults != op->getNumResults())
1198 return emitError(loc, "operation defines ")
1199 << op->getNumResults() << " results but was provided "
1200 << numExpectedResults << " to bind";
1202 // Add this operation to the assembly state if it was provided to populate.
1203 if (state.asmState) {
1204 unsigned resultIt = 0;
1205 SmallVector<std::pair<unsigned, SMLoc>> asmResultGroups;
1206 asmResultGroups.reserve(resultIDs.size());
1207 for (ResultRecord &record : resultIDs) {
1208 asmResultGroups.emplace_back(resultIt, std::get<2>(record));
1209 resultIt += std::get<1>(record);
1211 state.asmState->finalizeOperationDefinition(
1212 op, nameTok.getLocRange(), /*endLoc=*/getToken().getLoc(),
1213 asmResultGroups);
1216 // Add definitions for each of the result groups.
1217 unsigned opResI = 0;
1218 for (ResultRecord &resIt : resultIDs) {
1219 for (unsigned subRes : llvm::seq<unsigned>(0, std::get<1>(resIt))) {
1220 if (addDefinition({std::get<2>(resIt), std::get<0>(resIt), subRes},
1221 op->getResult(opResI++)))
1222 return failure();
1226 // Add this operation to the assembly state if it was provided to populate.
1227 } else if (state.asmState) {
1228 state.asmState->finalizeOperationDefinition(op, nameTok.getLocRange(),
1229 /*endLoc=*/getToken().getLoc());
1232 return success();
1235 /// Parse a single operation successor.
1237 /// successor ::= block-id
1239 ParseResult OperationParser::parseSuccessor(Block *&dest) {
1240 if (getToken().isCodeCompletion())
1241 return codeCompleteBlock();
1243 // Verify branch is identifier and get the matching block.
1244 if (!getToken().is(Token::caret_identifier))
1245 return emitWrongTokenError("expected block name");
1246 dest = getBlockNamed(getTokenSpelling(), getToken().getLoc());
1247 consumeToken();
1248 return success();
1251 /// Parse a comma-separated list of operation successors in brackets.
1253 /// successor-list ::= `[` successor (`,` successor )* `]`
1255 ParseResult
1256 OperationParser::parseSuccessors(SmallVectorImpl<Block *> &destinations) {
1257 if (parseToken(Token::l_square, "expected '['"))
1258 return failure();
1260 auto parseElt = [this, &destinations] {
1261 Block *dest;
1262 ParseResult res = parseSuccessor(dest);
1263 destinations.push_back(dest);
1264 return res;
1266 return parseCommaSeparatedListUntil(Token::r_square, parseElt,
1267 /*allowEmptyList=*/false);
1270 namespace {
1271 // RAII-style guard for cleaning up the regions in the operation state before
1272 // deleting them. Within the parser, regions may get deleted if parsing failed,
1273 // and other errors may be present, in particular undominated uses. This makes
1274 // sure such uses are deleted.
1275 struct CleanupOpStateRegions {
1276 ~CleanupOpStateRegions() {
1277 SmallVector<Region *, 4> regionsToClean;
1278 regionsToClean.reserve(state.regions.size());
1279 for (auto &region : state.regions)
1280 if (region)
1281 for (auto &block : *region)
1282 block.dropAllDefinedValueUses();
1284 OperationState &state;
1286 } // namespace
1288 ParseResult OperationParser::parseGenericOperationAfterOpName(
1289 OperationState &result,
1290 std::optional<ArrayRef<UnresolvedOperand>> parsedOperandUseInfo,
1291 std::optional<ArrayRef<Block *>> parsedSuccessors,
1292 std::optional<MutableArrayRef<std::unique_ptr<Region>>> parsedRegions,
1293 std::optional<ArrayRef<NamedAttribute>> parsedAttributes,
1294 std::optional<Attribute> propertiesAttribute,
1295 std::optional<FunctionType> parsedFnType) {
1297 // Parse the operand list, if not explicitly provided.
1298 SmallVector<UnresolvedOperand, 8> opInfo;
1299 if (!parsedOperandUseInfo) {
1300 if (parseToken(Token::l_paren, "expected '(' to start operand list") ||
1301 parseOptionalSSAUseList(opInfo) ||
1302 parseToken(Token::r_paren, "expected ')' to end operand list")) {
1303 return failure();
1305 parsedOperandUseInfo = opInfo;
1308 // Parse the successor list, if not explicitly provided.
1309 if (!parsedSuccessors) {
1310 if (getToken().is(Token::l_square)) {
1311 // Check if the operation is not a known terminator.
1312 if (!result.name.mightHaveTrait<OpTrait::IsTerminator>())
1313 return emitError("successors in non-terminator");
1315 SmallVector<Block *, 2> successors;
1316 if (parseSuccessors(successors))
1317 return failure();
1318 result.addSuccessors(successors);
1320 } else {
1321 result.addSuccessors(*parsedSuccessors);
1324 // Parse the properties, if not explicitly provided.
1325 if (propertiesAttribute) {
1326 result.propertiesAttr = *propertiesAttribute;
1327 } else if (consumeIf(Token::less)) {
1328 result.propertiesAttr = parseAttribute();
1329 if (!result.propertiesAttr)
1330 return failure();
1331 if (parseToken(Token::greater, "expected '>' to close properties"))
1332 return failure();
1334 // Parse the region list, if not explicitly provided.
1335 if (!parsedRegions) {
1336 if (consumeIf(Token::l_paren)) {
1337 do {
1338 // Create temporary regions with the top level region as parent.
1339 result.regions.emplace_back(new Region(topLevelOp));
1340 if (parseRegion(*result.regions.back(), /*entryArguments=*/{}))
1341 return failure();
1342 } while (consumeIf(Token::comma));
1343 if (parseToken(Token::r_paren, "expected ')' to end region list"))
1344 return failure();
1346 } else {
1347 result.addRegions(*parsedRegions);
1350 // Parse the attributes, if not explicitly provided.
1351 if (!parsedAttributes) {
1352 if (getToken().is(Token::l_brace)) {
1353 if (parseAttributeDict(result.attributes))
1354 return failure();
1356 } else {
1357 result.addAttributes(*parsedAttributes);
1360 // Parse the operation type, if not explicitly provided.
1361 Location typeLoc = result.location;
1362 if (!parsedFnType) {
1363 if (parseToken(Token::colon, "expected ':' followed by operation type"))
1364 return failure();
1366 typeLoc = getEncodedSourceLocation(getToken().getLoc());
1367 auto type = parseType();
1368 if (!type)
1369 return failure();
1370 auto fnType = dyn_cast<FunctionType>(type);
1371 if (!fnType)
1372 return mlir::emitError(typeLoc, "expected function type");
1374 parsedFnType = fnType;
1377 result.addTypes(parsedFnType->getResults());
1379 // Check that we have the right number of types for the operands.
1380 ArrayRef<Type> operandTypes = parsedFnType->getInputs();
1381 if (operandTypes.size() != parsedOperandUseInfo->size()) {
1382 auto plural = "s"[parsedOperandUseInfo->size() == 1];
1383 return mlir::emitError(typeLoc, "expected ")
1384 << parsedOperandUseInfo->size() << " operand type" << plural
1385 << " but had " << operandTypes.size();
1388 // Resolve all of the operands.
1389 for (unsigned i = 0, e = parsedOperandUseInfo->size(); i != e; ++i) {
1390 result.operands.push_back(
1391 resolveSSAUse((*parsedOperandUseInfo)[i], operandTypes[i]));
1392 if (!result.operands.back())
1393 return failure();
1396 return success();
1399 Operation *OperationParser::parseGenericOperation() {
1400 // Get location information for the operation.
1401 auto srcLocation = getEncodedSourceLocation(getToken().getLoc());
1403 std::string name = getToken().getStringValue();
1404 if (name.empty())
1405 return (emitError("empty operation name is invalid"), nullptr);
1406 if (name.find('\0') != StringRef::npos)
1407 return (emitError("null character not allowed in operation name"), nullptr);
1409 consumeToken(Token::string);
1411 OperationState result(srcLocation, name);
1412 CleanupOpStateRegions guard{result};
1414 // Lazy load dialects in the context as needed.
1415 if (!result.name.isRegistered()) {
1416 StringRef dialectName = StringRef(name).split('.').first;
1417 if (!getContext()->getLoadedDialect(dialectName) &&
1418 !getContext()->getOrLoadDialect(dialectName)) {
1419 if (!getContext()->allowsUnregisteredDialects()) {
1420 // Emit an error if the dialect couldn't be loaded (i.e., it was not
1421 // registered) and unregistered dialects aren't allowed.
1422 emitError("operation being parsed with an unregistered dialect. If "
1423 "this is intended, please use -allow-unregistered-dialect "
1424 "with the MLIR tool used");
1425 return nullptr;
1427 } else {
1428 // Reload the OperationName now that the dialect is loaded.
1429 result.name = OperationName(name, getContext());
1433 // If we are populating the parser state, start a new operation definition.
1434 if (state.asmState)
1435 state.asmState->startOperationDefinition(result.name);
1437 if (parseGenericOperationAfterOpName(result))
1438 return nullptr;
1440 // Operation::create() is not allowed to fail, however setting the properties
1441 // from an attribute is a failable operation. So we save the attribute here
1442 // and set it on the operation post-parsing.
1443 Attribute properties;
1444 std::swap(properties, result.propertiesAttr);
1446 // If we don't have properties in the textual IR, but the operation now has
1447 // support for properties, we support some backward-compatible generic syntax
1448 // for the operation and as such we accept inherent attributes mixed in the
1449 // dictionary of discardable attributes. We pre-validate these here because
1450 // invalid attributes can't be casted to the properties storage and will be
1451 // silently dropped. For example an attribute { foo = 0 : i32 } that is
1452 // declared as F32Attr in ODS would have a C++ type of FloatAttr in the
1453 // properties array. When setting it we would do something like:
1455 // properties.foo = dyn_cast<FloatAttr>(fooAttr);
1457 // which would end up with a null Attribute. The diagnostic from the verifier
1458 // would be "missing foo attribute" instead of something like "expects a 32
1459 // bits float attribute but got a 32 bits integer attribute".
1460 if (!properties && !result.getRawProperties()) {
1461 std::optional<RegisteredOperationName> info =
1462 result.name.getRegisteredInfo();
1463 if (info) {
1464 if (failed(info->verifyInherentAttrs(result.attributes, [&]() {
1465 return mlir::emitError(srcLocation) << "'" << name << "' op ";
1466 })))
1467 return nullptr;
1471 // Create the operation and try to parse a location for it.
1472 Operation *op = opBuilder.create(result);
1473 if (parseTrailingLocationSpecifier(op))
1474 return nullptr;
1476 // Try setting the properties for the operation, using a diagnostic to print
1477 // errors.
1478 if (properties) {
1479 auto emitError = [&]() {
1480 return mlir::emitError(srcLocation, "invalid properties ")
1481 << properties << " for op " << name << ": ";
1483 if (failed(op->setPropertiesFromAttribute(properties, emitError)))
1484 return nullptr;
1487 return op;
1490 Operation *OperationParser::parseGenericOperation(Block *insertBlock,
1491 Block::iterator insertPt) {
1492 Token nameToken = getToken();
1494 OpBuilder::InsertionGuard restoreInsertionPoint(opBuilder);
1495 opBuilder.setInsertionPoint(insertBlock, insertPt);
1496 Operation *op = parseGenericOperation();
1497 if (!op)
1498 return nullptr;
1500 // If we are populating the parser asm state, finalize this operation
1501 // definition.
1502 if (state.asmState)
1503 state.asmState->finalizeOperationDefinition(op, nameToken.getLocRange(),
1504 /*endLoc=*/getToken().getLoc());
1505 return op;
1508 namespace {
1509 class CustomOpAsmParser : public AsmParserImpl<OpAsmParser> {
1510 public:
1511 CustomOpAsmParser(
1512 SMLoc nameLoc, ArrayRef<OperationParser::ResultRecord> resultIDs,
1513 function_ref<ParseResult(OpAsmParser &, OperationState &)> parseAssembly,
1514 bool isIsolatedFromAbove, StringRef opName, OperationParser &parser)
1515 : AsmParserImpl<OpAsmParser>(nameLoc, parser), resultIDs(resultIDs),
1516 parseAssembly(parseAssembly), isIsolatedFromAbove(isIsolatedFromAbove),
1517 opName(opName), parser(parser) {
1518 (void)isIsolatedFromAbove; // Only used in assert, silence unused warning.
1521 /// Parse an instance of the operation described by 'opDefinition' into the
1522 /// provided operation state.
1523 ParseResult parseOperation(OperationState &opState) {
1524 if (parseAssembly(*this, opState))
1525 return failure();
1526 // Verify that the parsed attributes does not have duplicate attributes.
1527 // This can happen if an attribute set during parsing is also specified in
1528 // the attribute dictionary in the assembly, or the attribute is set
1529 // multiple during parsing.
1530 std::optional<NamedAttribute> duplicate =
1531 opState.attributes.findDuplicate();
1532 if (duplicate)
1533 return emitError(getNameLoc(), "attribute '")
1534 << duplicate->getName().getValue()
1535 << "' occurs more than once in the attribute list";
1536 return success();
1539 Operation *parseGenericOperation(Block *insertBlock,
1540 Block::iterator insertPt) final {
1541 return parser.parseGenericOperation(insertBlock, insertPt);
1544 FailureOr<OperationName> parseCustomOperationName() final {
1545 return parser.parseCustomOperationName();
1548 ParseResult parseGenericOperationAfterOpName(
1549 OperationState &result,
1550 std::optional<ArrayRef<UnresolvedOperand>> parsedUnresolvedOperands,
1551 std::optional<ArrayRef<Block *>> parsedSuccessors,
1552 std::optional<MutableArrayRef<std::unique_ptr<Region>>> parsedRegions,
1553 std::optional<ArrayRef<NamedAttribute>> parsedAttributes,
1554 std::optional<Attribute> parsedPropertiesAttribute,
1555 std::optional<FunctionType> parsedFnType) final {
1556 return parser.parseGenericOperationAfterOpName(
1557 result, parsedUnresolvedOperands, parsedSuccessors, parsedRegions,
1558 parsedAttributes, parsedPropertiesAttribute, parsedFnType);
1560 //===--------------------------------------------------------------------===//
1561 // Utilities
1562 //===--------------------------------------------------------------------===//
1564 /// Return the name of the specified result in the specified syntax, as well
1565 /// as the subelement in the name. For example, in this operation:
1567 /// %x, %y:2, %z = foo.op
1569 /// getResultName(0) == {"x", 0 }
1570 /// getResultName(1) == {"y", 0 }
1571 /// getResultName(2) == {"y", 1 }
1572 /// getResultName(3) == {"z", 0 }
1573 std::pair<StringRef, unsigned>
1574 getResultName(unsigned resultNo) const override {
1575 // Scan for the resultID that contains this result number.
1576 for (const auto &entry : resultIDs) {
1577 if (resultNo < std::get<1>(entry)) {
1578 // Don't pass on the leading %.
1579 StringRef name = std::get<0>(entry).drop_front();
1580 return {name, resultNo};
1582 resultNo -= std::get<1>(entry);
1585 // Invalid result number.
1586 return {"", ~0U};
1589 /// Return the number of declared SSA results. This returns 4 for the foo.op
1590 /// example in the comment for getResultName.
1591 size_t getNumResults() const override {
1592 size_t count = 0;
1593 for (auto &entry : resultIDs)
1594 count += std::get<1>(entry);
1595 return count;
1598 /// Emit a diagnostic at the specified location and return failure.
1599 InFlightDiagnostic emitError(SMLoc loc, const Twine &message) override {
1600 return AsmParserImpl<OpAsmParser>::emitError(loc, "custom op '" + opName +
1601 "' " + message);
1604 //===--------------------------------------------------------------------===//
1605 // Operand Parsing
1606 //===--------------------------------------------------------------------===//
1608 /// Parse a single operand.
1609 ParseResult parseOperand(UnresolvedOperand &result,
1610 bool allowResultNumber = true) override {
1611 OperationParser::UnresolvedOperand useInfo;
1612 if (parser.parseSSAUse(useInfo, allowResultNumber))
1613 return failure();
1615 result = {useInfo.location, useInfo.name, useInfo.number};
1616 return success();
1619 /// Parse a single operand if present.
1620 OptionalParseResult
1621 parseOptionalOperand(UnresolvedOperand &result,
1622 bool allowResultNumber = true) override {
1623 if (parser.getToken().isOrIsCodeCompletionFor(Token::percent_identifier))
1624 return parseOperand(result, allowResultNumber);
1625 return std::nullopt;
1628 /// Parse zero or more SSA comma-separated operand references with a specified
1629 /// surrounding delimiter, and an optional required operand count.
1630 ParseResult parseOperandList(SmallVectorImpl<UnresolvedOperand> &result,
1631 Delimiter delimiter = Delimiter::None,
1632 bool allowResultNumber = true,
1633 int requiredOperandCount = -1) override {
1634 // The no-delimiter case has some special handling for better diagnostics.
1635 if (delimiter == Delimiter::None) {
1636 // parseCommaSeparatedList doesn't handle the missing case for "none",
1637 // so we handle it custom here.
1638 Token tok = parser.getToken();
1639 if (!tok.isOrIsCodeCompletionFor(Token::percent_identifier)) {
1640 // If we didn't require any operands or required exactly zero (weird)
1641 // then this is success.
1642 if (requiredOperandCount == -1 || requiredOperandCount == 0)
1643 return success();
1645 // Otherwise, try to produce a nice error message.
1646 if (tok.isAny(Token::l_paren, Token::l_square))
1647 return parser.emitError("unexpected delimiter");
1648 return parser.emitWrongTokenError("expected operand");
1652 auto parseOneOperand = [&]() -> ParseResult {
1653 return parseOperand(result.emplace_back(), allowResultNumber);
1656 auto startLoc = parser.getToken().getLoc();
1657 if (parseCommaSeparatedList(delimiter, parseOneOperand, " in operand list"))
1658 return failure();
1660 // Check that we got the expected # of elements.
1661 if (requiredOperandCount != -1 &&
1662 result.size() != static_cast<size_t>(requiredOperandCount))
1663 return emitError(startLoc, "expected ")
1664 << requiredOperandCount << " operands";
1665 return success();
1668 /// Resolve an operand to an SSA value, emitting an error on failure.
1669 ParseResult resolveOperand(const UnresolvedOperand &operand, Type type,
1670 SmallVectorImpl<Value> &result) override {
1671 if (auto value = parser.resolveSSAUse(operand, type)) {
1672 result.push_back(value);
1673 return success();
1675 return failure();
1678 /// Parse an AffineMap of SSA ids.
1679 ParseResult
1680 parseAffineMapOfSSAIds(SmallVectorImpl<UnresolvedOperand> &operands,
1681 Attribute &mapAttr, StringRef attrName,
1682 NamedAttrList &attrs, Delimiter delimiter) override {
1683 SmallVector<UnresolvedOperand, 2> dimOperands;
1684 SmallVector<UnresolvedOperand, 1> symOperands;
1686 auto parseElement = [&](bool isSymbol) -> ParseResult {
1687 UnresolvedOperand operand;
1688 if (parseOperand(operand))
1689 return failure();
1690 if (isSymbol)
1691 symOperands.push_back(operand);
1692 else
1693 dimOperands.push_back(operand);
1694 return success();
1697 AffineMap map;
1698 if (parser.parseAffineMapOfSSAIds(map, parseElement, delimiter))
1699 return failure();
1700 // Add AffineMap attribute.
1701 if (map) {
1702 mapAttr = AffineMapAttr::get(map);
1703 attrs.push_back(parser.builder.getNamedAttr(attrName, mapAttr));
1706 // Add dim operands before symbol operands in 'operands'.
1707 operands.assign(dimOperands.begin(), dimOperands.end());
1708 operands.append(symOperands.begin(), symOperands.end());
1709 return success();
1712 /// Parse an AffineExpr of SSA ids.
1713 ParseResult
1714 parseAffineExprOfSSAIds(SmallVectorImpl<UnresolvedOperand> &dimOperands,
1715 SmallVectorImpl<UnresolvedOperand> &symbOperands,
1716 AffineExpr &expr) override {
1717 auto parseElement = [&](bool isSymbol) -> ParseResult {
1718 UnresolvedOperand operand;
1719 if (parseOperand(operand))
1720 return failure();
1721 if (isSymbol)
1722 symbOperands.push_back(operand);
1723 else
1724 dimOperands.push_back(operand);
1725 return success();
1728 return parser.parseAffineExprOfSSAIds(expr, parseElement);
1731 //===--------------------------------------------------------------------===//
1732 // Argument Parsing
1733 //===--------------------------------------------------------------------===//
1735 /// Parse a single argument with the following syntax:
1737 /// `%ssaname : !type { optionalAttrDict} loc(optionalSourceLoc)`
1739 /// If `allowType` is false or `allowAttrs` are false then the respective
1740 /// parts of the grammar are not parsed.
1741 ParseResult parseArgument(Argument &result, bool allowType = false,
1742 bool allowAttrs = false) override {
1743 NamedAttrList attrs;
1744 if (parseOperand(result.ssaName, /*allowResultNumber=*/false) ||
1745 (allowType && parseColonType(result.type)) ||
1746 (allowAttrs && parseOptionalAttrDict(attrs)) ||
1747 parseOptionalLocationSpecifier(result.sourceLoc))
1748 return failure();
1749 result.attrs = attrs.getDictionary(getContext());
1750 return success();
1753 /// Parse a single argument if present.
1754 OptionalParseResult parseOptionalArgument(Argument &result, bool allowType,
1755 bool allowAttrs) override {
1756 if (parser.getToken().is(Token::percent_identifier))
1757 return parseArgument(result, allowType, allowAttrs);
1758 return std::nullopt;
1761 ParseResult parseArgumentList(SmallVectorImpl<Argument> &result,
1762 Delimiter delimiter, bool allowType,
1763 bool allowAttrs) override {
1764 // The no-delimiter case has some special handling for the empty case.
1765 if (delimiter == Delimiter::None &&
1766 parser.getToken().isNot(Token::percent_identifier))
1767 return success();
1769 auto parseOneArgument = [&]() -> ParseResult {
1770 return parseArgument(result.emplace_back(), allowType, allowAttrs);
1772 return parseCommaSeparatedList(delimiter, parseOneArgument,
1773 " in argument list");
1776 //===--------------------------------------------------------------------===//
1777 // Region Parsing
1778 //===--------------------------------------------------------------------===//
1780 /// Parse a region that takes `arguments` of `argTypes` types. This
1781 /// effectively defines the SSA values of `arguments` and assigns their type.
1782 ParseResult parseRegion(Region &region, ArrayRef<Argument> arguments,
1783 bool enableNameShadowing) override {
1784 // Try to parse the region.
1785 (void)isIsolatedFromAbove;
1786 assert((!enableNameShadowing || isIsolatedFromAbove) &&
1787 "name shadowing is only allowed on isolated regions");
1788 if (parser.parseRegion(region, arguments, enableNameShadowing))
1789 return failure();
1790 return success();
1793 /// Parses a region if present.
1794 OptionalParseResult parseOptionalRegion(Region &region,
1795 ArrayRef<Argument> arguments,
1796 bool enableNameShadowing) override {
1797 if (parser.getToken().isNot(Token::l_brace))
1798 return std::nullopt;
1799 return parseRegion(region, arguments, enableNameShadowing);
1802 /// Parses a region if present. If the region is present, a new region is
1803 /// allocated and placed in `region`. If no region is present, `region`
1804 /// remains untouched.
1805 OptionalParseResult
1806 parseOptionalRegion(std::unique_ptr<Region> &region,
1807 ArrayRef<Argument> arguments,
1808 bool enableNameShadowing = false) override {
1809 if (parser.getToken().isNot(Token::l_brace))
1810 return std::nullopt;
1811 std::unique_ptr<Region> newRegion = std::make_unique<Region>();
1812 if (parseRegion(*newRegion, arguments, enableNameShadowing))
1813 return failure();
1815 region = std::move(newRegion);
1816 return success();
1819 //===--------------------------------------------------------------------===//
1820 // Successor Parsing
1821 //===--------------------------------------------------------------------===//
1823 /// Parse a single operation successor.
1824 ParseResult parseSuccessor(Block *&dest) override {
1825 return parser.parseSuccessor(dest);
1828 /// Parse an optional operation successor and its operand list.
1829 OptionalParseResult parseOptionalSuccessor(Block *&dest) override {
1830 if (!parser.getToken().isOrIsCodeCompletionFor(Token::caret_identifier))
1831 return std::nullopt;
1832 return parseSuccessor(dest);
1835 /// Parse a single operation successor and its operand list.
1836 ParseResult
1837 parseSuccessorAndUseList(Block *&dest,
1838 SmallVectorImpl<Value> &operands) override {
1839 if (parseSuccessor(dest))
1840 return failure();
1842 // Handle optional arguments.
1843 if (succeeded(parseOptionalLParen()) &&
1844 (parser.parseOptionalSSAUseAndTypeList(operands) || parseRParen())) {
1845 return failure();
1847 return success();
1850 //===--------------------------------------------------------------------===//
1851 // Type Parsing
1852 //===--------------------------------------------------------------------===//
1854 /// Parse a list of assignments of the form
1855 /// (%x1 = %y1, %x2 = %y2, ...).
1856 OptionalParseResult parseOptionalAssignmentList(
1857 SmallVectorImpl<Argument> &lhs,
1858 SmallVectorImpl<UnresolvedOperand> &rhs) override {
1859 if (failed(parseOptionalLParen()))
1860 return std::nullopt;
1862 auto parseElt = [&]() -> ParseResult {
1863 if (parseArgument(lhs.emplace_back()) || parseEqual() ||
1864 parseOperand(rhs.emplace_back()))
1865 return failure();
1866 return success();
1868 return parser.parseCommaSeparatedListUntil(Token::r_paren, parseElt);
1871 /// Parse a loc(...) specifier if present, filling in result if so.
1872 ParseResult
1873 parseOptionalLocationSpecifier(std::optional<Location> &result) override {
1874 // If there is a 'loc' we parse a trailing location.
1875 if (!parser.consumeIf(Token::kw_loc))
1876 return success();
1877 LocationAttr directLoc;
1878 if (parser.parseToken(Token::l_paren, "expected '(' in location"))
1879 return failure();
1881 Token tok = parser.getToken();
1883 // Check to see if we are parsing a location alias.
1884 // Otherwise, we parse the location directly.
1885 if (tok.is(Token::hash_identifier)) {
1886 if (parser.parseLocationAlias(directLoc))
1887 return failure();
1888 } else if (parser.parseLocationInstance(directLoc)) {
1889 return failure();
1892 if (parser.parseToken(Token::r_paren, "expected ')' in location"))
1893 return failure();
1895 result = directLoc;
1896 return success();
1899 private:
1900 /// Information about the result name specifiers.
1901 ArrayRef<OperationParser::ResultRecord> resultIDs;
1903 /// The abstract information of the operation.
1904 function_ref<ParseResult(OpAsmParser &, OperationState &)> parseAssembly;
1905 bool isIsolatedFromAbove;
1906 StringRef opName;
1908 /// The backing operation parser.
1909 OperationParser &parser;
1911 } // namespace
1913 FailureOr<OperationName> OperationParser::parseCustomOperationName() {
1914 Token nameTok = getToken();
1915 StringRef opName = nameTok.getSpelling();
1916 if (opName.empty())
1917 return (emitError("empty operation name is invalid"), failure());
1918 consumeToken();
1920 // Check to see if this operation name is already registered.
1921 std::optional<RegisteredOperationName> opInfo =
1922 RegisteredOperationName::lookup(opName, getContext());
1923 if (opInfo)
1924 return *opInfo;
1926 // If the operation doesn't have a dialect prefix try using the default
1927 // dialect.
1928 auto opNameSplit = opName.split('.');
1929 StringRef dialectName = opNameSplit.first;
1930 std::string opNameStorage;
1931 if (opNameSplit.second.empty()) {
1932 // If the name didn't have a prefix, check for a code completion request.
1933 if (getToken().isCodeCompletion() && opName.back() == '.')
1934 return codeCompleteOperationName(dialectName);
1936 dialectName = getState().defaultDialectStack.back();
1937 opNameStorage = (dialectName + "." + opName).str();
1938 opName = opNameStorage;
1941 // Try to load the dialect before returning the operation name to make sure
1942 // the operation has a chance to be registered.
1943 getContext()->getOrLoadDialect(dialectName);
1944 return OperationName(opName, getContext());
1947 Operation *
1948 OperationParser::parseCustomOperation(ArrayRef<ResultRecord> resultIDs) {
1949 SMLoc opLoc = getToken().getLoc();
1950 StringRef originalOpName = getTokenSpelling();
1952 FailureOr<OperationName> opNameInfo = parseCustomOperationName();
1953 if (failed(opNameInfo))
1954 return nullptr;
1955 StringRef opName = opNameInfo->getStringRef();
1957 // This is the actual hook for the custom op parsing, usually implemented by
1958 // the op itself (`Op::parse()`). We retrieve it either from the
1959 // RegisteredOperationName or from the Dialect.
1960 OperationName::ParseAssemblyFn parseAssemblyFn;
1961 bool isIsolatedFromAbove = false;
1963 StringRef defaultDialect = "";
1964 if (auto opInfo = opNameInfo->getRegisteredInfo()) {
1965 parseAssemblyFn = opInfo->getParseAssemblyFn();
1966 isIsolatedFromAbove = opInfo->hasTrait<OpTrait::IsIsolatedFromAbove>();
1967 auto *iface = opInfo->getInterface<OpAsmOpInterface>();
1968 if (iface && !iface->getDefaultDialect().empty())
1969 defaultDialect = iface->getDefaultDialect();
1970 } else {
1971 std::optional<Dialect::ParseOpHook> dialectHook;
1972 Dialect *dialect = opNameInfo->getDialect();
1973 if (!dialect) {
1974 InFlightDiagnostic diag =
1975 emitError(opLoc) << "Dialect `" << opNameInfo->getDialectNamespace()
1976 << "' not found for custom op '" << originalOpName
1977 << "' ";
1978 if (originalOpName != opName)
1979 diag << " (tried '" << opName << "' as well)";
1980 auto &note = diag.attachNote();
1981 note << "Registered dialects: ";
1982 llvm::interleaveComma(getContext()->getAvailableDialects(), note,
1983 [&](StringRef dialect) { note << dialect; });
1984 note << " ; for more info on dialect registration see "
1985 "https://mlir.llvm.org/getting_started/Faq/"
1986 "#registered-loaded-dependent-whats-up-with-dialects-management";
1987 return nullptr;
1989 dialectHook = dialect->getParseOperationHook(opName);
1990 if (!dialectHook) {
1991 InFlightDiagnostic diag =
1992 emitError(opLoc) << "custom op '" << originalOpName << "' is unknown";
1993 if (originalOpName != opName)
1994 diag << " (tried '" << opName << "' as well)";
1995 return nullptr;
1997 parseAssemblyFn = *dialectHook;
1999 getState().defaultDialectStack.push_back(defaultDialect);
2000 auto restoreDefaultDialect = llvm::make_scope_exit(
2001 [&]() { getState().defaultDialectStack.pop_back(); });
2003 // If the custom op parser crashes, produce some indication to help
2004 // debugging.
2005 llvm::PrettyStackTraceFormat fmt("MLIR Parser: custom op parser '%s'",
2006 opNameInfo->getIdentifier().data());
2008 // Get location information for the operation.
2009 auto srcLocation = getEncodedSourceLocation(opLoc);
2010 OperationState opState(srcLocation, *opNameInfo);
2012 // If we are populating the parser state, start a new operation definition.
2013 if (state.asmState)
2014 state.asmState->startOperationDefinition(opState.name);
2016 // Have the op implementation take a crack and parsing this.
2017 CleanupOpStateRegions guard{opState};
2018 CustomOpAsmParser opAsmParser(opLoc, resultIDs, parseAssemblyFn,
2019 isIsolatedFromAbove, opName, *this);
2020 if (opAsmParser.parseOperation(opState))
2021 return nullptr;
2023 // If it emitted an error, we failed.
2024 if (opAsmParser.didEmitError())
2025 return nullptr;
2027 Attribute properties = opState.propertiesAttr;
2028 opState.propertiesAttr = Attribute{};
2030 // Otherwise, create the operation and try to parse a location for it.
2031 Operation *op = opBuilder.create(opState);
2032 if (parseTrailingLocationSpecifier(op))
2033 return nullptr;
2035 // Try setting the properties for the operation.
2036 if (properties) {
2037 auto emitError = [&]() {
2038 return mlir::emitError(srcLocation, "invalid properties ")
2039 << properties << " for op " << op->getName().getStringRef()
2040 << ": ";
2042 if (failed(op->setPropertiesFromAttribute(properties, emitError)))
2043 return nullptr;
2045 return op;
2048 ParseResult OperationParser::parseLocationAlias(LocationAttr &loc) {
2049 Token tok = getToken();
2050 consumeToken(Token::hash_identifier);
2051 StringRef identifier = tok.getSpelling().drop_front();
2052 if (identifier.contains('.')) {
2053 return emitError(tok.getLoc())
2054 << "expected location, but found dialect attribute: '#" << identifier
2055 << "'";
2057 if (state.asmState)
2058 state.asmState->addAttrAliasUses(identifier, tok.getLocRange());
2060 // If this alias can be resolved, do it now.
2061 Attribute attr = state.symbols.attributeAliasDefinitions.lookup(identifier);
2062 if (attr) {
2063 if (!(loc = dyn_cast<LocationAttr>(attr)))
2064 return emitError(tok.getLoc())
2065 << "expected location, but found '" << attr << "'";
2066 } else {
2067 // Otherwise, remember this operation and resolve its location later.
2068 // In the meantime, use a special OpaqueLoc as a marker.
2069 loc = OpaqueLoc::get(deferredLocsReferences.size(),
2070 TypeID::get<DeferredLocInfo *>(),
2071 UnknownLoc::get(getContext()));
2072 deferredLocsReferences.push_back(DeferredLocInfo{tok.getLoc(), identifier});
2074 return success();
2077 ParseResult
2078 OperationParser::parseTrailingLocationSpecifier(OpOrArgument opOrArgument) {
2079 // If there is a 'loc' we parse a trailing location.
2080 if (!consumeIf(Token::kw_loc))
2081 return success();
2082 if (parseToken(Token::l_paren, "expected '(' in location"))
2083 return failure();
2084 Token tok = getToken();
2086 // Check to see if we are parsing a location alias.
2087 // Otherwise, we parse the location directly.
2088 LocationAttr directLoc;
2089 if (tok.is(Token::hash_identifier)) {
2090 if (parseLocationAlias(directLoc))
2091 return failure();
2092 } else if (parseLocationInstance(directLoc)) {
2093 return failure();
2096 if (parseToken(Token::r_paren, "expected ')' in location"))
2097 return failure();
2099 if (auto *op = llvm::dyn_cast_if_present<Operation *>(opOrArgument))
2100 op->setLoc(directLoc);
2101 else
2102 opOrArgument.get<BlockArgument>().setLoc(directLoc);
2103 return success();
2106 //===----------------------------------------------------------------------===//
2107 // Region Parsing
2108 //===----------------------------------------------------------------------===//
2110 ParseResult OperationParser::parseRegion(Region &region,
2111 ArrayRef<Argument> entryArguments,
2112 bool isIsolatedNameScope) {
2113 // Parse the '{'.
2114 Token lBraceTok = getToken();
2115 if (parseToken(Token::l_brace, "expected '{' to begin a region"))
2116 return failure();
2118 // If we are populating the parser state, start a new region definition.
2119 if (state.asmState)
2120 state.asmState->startRegionDefinition();
2122 // Parse the region body.
2123 if ((!entryArguments.empty() || getToken().isNot(Token::r_brace)) &&
2124 parseRegionBody(region, lBraceTok.getLoc(), entryArguments,
2125 isIsolatedNameScope)) {
2126 return failure();
2128 consumeToken(Token::r_brace);
2130 // If we are populating the parser state, finalize this region.
2131 if (state.asmState)
2132 state.asmState->finalizeRegionDefinition();
2134 return success();
2137 ParseResult OperationParser::parseRegionBody(Region &region, SMLoc startLoc,
2138 ArrayRef<Argument> entryArguments,
2139 bool isIsolatedNameScope) {
2140 auto currentPt = opBuilder.saveInsertionPoint();
2142 // Push a new named value scope.
2143 pushSSANameScope(isIsolatedNameScope);
2145 // Parse the first block directly to allow for it to be unnamed.
2146 auto owningBlock = std::make_unique<Block>();
2147 Block *block = owningBlock.get();
2149 // If this block is not defined in the source file, add a definition for it
2150 // now in the assembly state. Blocks with a name will be defined when the name
2151 // is parsed.
2152 if (state.asmState && getToken().isNot(Token::caret_identifier))
2153 state.asmState->addDefinition(block, startLoc);
2155 // Add arguments to the entry block if we had the form with explicit names.
2156 if (!entryArguments.empty() && !entryArguments[0].ssaName.name.empty()) {
2157 // If we had named arguments, then don't allow a block name.
2158 if (getToken().is(Token::caret_identifier))
2159 return emitError("invalid block name in region with named arguments");
2161 for (auto &entryArg : entryArguments) {
2162 auto &argInfo = entryArg.ssaName;
2164 // Ensure that the argument was not already defined.
2165 if (auto defLoc = getReferenceLoc(argInfo.name, argInfo.number)) {
2166 return emitError(argInfo.location, "region entry argument '" +
2167 argInfo.name +
2168 "' is already in use")
2169 .attachNote(getEncodedSourceLocation(*defLoc))
2170 << "previously referenced here";
2172 Location loc = entryArg.sourceLoc.has_value()
2173 ? *entryArg.sourceLoc
2174 : getEncodedSourceLocation(argInfo.location);
2175 BlockArgument arg = block->addArgument(entryArg.type, loc);
2177 // Add a definition of this arg to the assembly state if provided.
2178 if (state.asmState)
2179 state.asmState->addDefinition(arg, argInfo.location);
2181 // Record the definition for this argument.
2182 if (addDefinition(argInfo, arg))
2183 return failure();
2187 if (parseBlock(block))
2188 return failure();
2190 // Verify that no other arguments were parsed.
2191 if (!entryArguments.empty() &&
2192 block->getNumArguments() > entryArguments.size()) {
2193 return emitError("entry block arguments were already defined");
2196 // Parse the rest of the region.
2197 region.push_back(owningBlock.release());
2198 while (getToken().isNot(Token::r_brace)) {
2199 Block *newBlock = nullptr;
2200 if (parseBlock(newBlock))
2201 return failure();
2202 region.push_back(newBlock);
2205 // Pop the SSA value scope for this region.
2206 if (popSSANameScope())
2207 return failure();
2209 // Reset the original insertion point.
2210 opBuilder.restoreInsertionPoint(currentPt);
2211 return success();
2214 //===----------------------------------------------------------------------===//
2215 // Block Parsing
2216 //===----------------------------------------------------------------------===//
2218 /// Block declaration.
2220 /// block ::= block-label? operation*
2221 /// block-label ::= block-id block-arg-list? `:`
2222 /// block-id ::= caret-id
2223 /// block-arg-list ::= `(` ssa-id-and-type-list? `)`
2225 ParseResult OperationParser::parseBlock(Block *&block) {
2226 // The first block of a region may already exist, if it does the caret
2227 // identifier is optional.
2228 if (block && getToken().isNot(Token::caret_identifier))
2229 return parseBlockBody(block);
2231 SMLoc nameLoc = getToken().getLoc();
2232 auto name = getTokenSpelling();
2233 if (parseToken(Token::caret_identifier, "expected block name"))
2234 return failure();
2236 // Define the block with the specified name.
2237 auto &blockAndLoc = getBlockInfoByName(name);
2238 blockAndLoc.loc = nameLoc;
2240 // Use a unique pointer for in-flight block being parsed. Release ownership
2241 // only in the case of a successful parse. This ensures that the Block
2242 // allocated is released if the parse fails and control returns early.
2243 std::unique_ptr<Block> inflightBlock;
2244 auto cleanupOnFailure = llvm::make_scope_exit([&] {
2245 if (inflightBlock)
2246 inflightBlock->dropAllDefinedValueUses();
2249 // If a block has yet to be set, this is a new definition. If the caller
2250 // provided a block, use it. Otherwise create a new one.
2251 if (!blockAndLoc.block) {
2252 if (block) {
2253 blockAndLoc.block = block;
2254 } else {
2255 inflightBlock = std::make_unique<Block>();
2256 blockAndLoc.block = inflightBlock.get();
2259 // Otherwise, the block has a forward declaration. Forward declarations are
2260 // removed once defined, so if we are defining a existing block and it is
2261 // not a forward declaration, then it is a redeclaration. Fail if the block
2262 // was already defined.
2263 } else if (!eraseForwardRef(blockAndLoc.block)) {
2264 return emitError(nameLoc, "redefinition of block '") << name << "'";
2265 } else {
2266 // This was a forward reference block that is now floating. Keep track of it
2267 // as inflight in case of error, so that it gets cleaned up properly.
2268 inflightBlock.reset(blockAndLoc.block);
2271 // Populate the high level assembly state if necessary.
2272 if (state.asmState)
2273 state.asmState->addDefinition(blockAndLoc.block, nameLoc);
2274 block = blockAndLoc.block;
2276 // If an argument list is present, parse it.
2277 if (getToken().is(Token::l_paren))
2278 if (parseOptionalBlockArgList(block))
2279 return failure();
2280 if (parseToken(Token::colon, "expected ':' after block name"))
2281 return failure();
2283 // Parse the body of the block.
2284 ParseResult res = parseBlockBody(block);
2286 // If parsing was successful, drop the inflight block. We relinquish ownership
2287 // back up to the caller.
2288 if (succeeded(res))
2289 (void)inflightBlock.release();
2290 return res;
2293 ParseResult OperationParser::parseBlockBody(Block *block) {
2294 // Set the insertion point to the end of the block to parse.
2295 opBuilder.setInsertionPointToEnd(block);
2297 // Parse the list of operations that make up the body of the block.
2298 while (getToken().isNot(Token::caret_identifier, Token::r_brace))
2299 if (parseOperation())
2300 return failure();
2302 return success();
2305 /// Get the block with the specified name, creating it if it doesn't already
2306 /// exist. The location specified is the point of use, which allows
2307 /// us to diagnose references to blocks that are not defined precisely.
2308 Block *OperationParser::getBlockNamed(StringRef name, SMLoc loc) {
2309 BlockDefinition &blockDef = getBlockInfoByName(name);
2310 if (!blockDef.block) {
2311 blockDef = {new Block(), loc};
2312 insertForwardRef(blockDef.block, blockDef.loc);
2315 // Populate the high level assembly state if necessary.
2316 if (state.asmState)
2317 state.asmState->addUses(blockDef.block, loc);
2319 return blockDef.block;
2322 /// Parse a (possibly empty) list of SSA operands with types as block arguments
2323 /// enclosed in parentheses.
2325 /// value-id-and-type-list ::= value-id-and-type (`,` ssa-id-and-type)*
2326 /// block-arg-list ::= `(` value-id-and-type-list? `)`
2328 ParseResult OperationParser::parseOptionalBlockArgList(Block *owner) {
2329 if (getToken().is(Token::r_brace))
2330 return success();
2332 // If the block already has arguments, then we're handling the entry block.
2333 // Parse and register the names for the arguments, but do not add them.
2334 bool definingExistingArgs = owner->getNumArguments() != 0;
2335 unsigned nextArgument = 0;
2337 return parseCommaSeparatedList(Delimiter::Paren, [&]() -> ParseResult {
2338 return parseSSADefOrUseAndType(
2339 [&](UnresolvedOperand useInfo, Type type) -> ParseResult {
2340 BlockArgument arg;
2342 // If we are defining existing arguments, ensure that the argument
2343 // has already been created with the right type.
2344 if (definingExistingArgs) {
2345 // Otherwise, ensure that this argument has already been created.
2346 if (nextArgument >= owner->getNumArguments())
2347 return emitError("too many arguments specified in argument list");
2349 // Finally, make sure the existing argument has the correct type.
2350 arg = owner->getArgument(nextArgument++);
2351 if (arg.getType() != type)
2352 return emitError("argument and block argument type mismatch");
2353 } else {
2354 auto loc = getEncodedSourceLocation(useInfo.location);
2355 arg = owner->addArgument(type, loc);
2358 // If the argument has an explicit loc(...) specifier, parse and apply
2359 // it.
2360 if (parseTrailingLocationSpecifier(arg))
2361 return failure();
2363 // Mark this block argument definition in the parser state if it was
2364 // provided.
2365 if (state.asmState)
2366 state.asmState->addDefinition(arg, useInfo.location);
2368 return addDefinition(useInfo, arg);
2373 //===----------------------------------------------------------------------===//
2374 // Code Completion
2375 //===----------------------------------------------------------------------===//
2377 ParseResult OperationParser::codeCompleteSSAUse() {
2378 std::string detailData;
2379 llvm::raw_string_ostream detailOS(detailData);
2380 for (IsolatedSSANameScope &scope : isolatedNameScopes) {
2381 for (auto &it : scope.values) {
2382 if (it.second.empty())
2383 continue;
2384 Value frontValue = it.second.front().value;
2386 // If the value isn't a forward reference, we also add the name of the op
2387 // to the detail.
2388 if (auto result = dyn_cast<OpResult>(frontValue)) {
2389 if (!forwardRefPlaceholders.count(result))
2390 detailOS << result.getOwner()->getName() << ": ";
2391 } else {
2392 detailOS << "arg #" << cast<BlockArgument>(frontValue).getArgNumber()
2393 << ": ";
2396 // Emit the type of the values to aid with completion selection.
2397 detailOS << frontValue.getType();
2399 // FIXME: We should define a policy for packed values, e.g. with a limit
2400 // on the detail size, but it isn't clear what would be useful right now.
2401 // For now we just only emit the first type.
2402 if (it.second.size() > 1)
2403 detailOS << ", ...";
2405 state.codeCompleteContext->appendSSAValueCompletion(
2406 it.getKey(), std::move(detailOS.str()));
2410 return failure();
2413 ParseResult OperationParser::codeCompleteBlock() {
2414 // Don't provide completions if the token isn't empty, e.g. this avoids
2415 // weirdness when we encounter a `.` within the identifier.
2416 StringRef spelling = getTokenSpelling();
2417 if (!(spelling.empty() || spelling == "^"))
2418 return failure();
2420 for (const auto &it : blocksByName.back())
2421 state.codeCompleteContext->appendBlockCompletion(it.getFirst());
2422 return failure();
2425 //===----------------------------------------------------------------------===//
2426 // Top-level entity parsing.
2427 //===----------------------------------------------------------------------===//
2429 namespace {
2430 /// This parser handles entities that are only valid at the top level of the
2431 /// file.
2432 class TopLevelOperationParser : public Parser {
2433 public:
2434 explicit TopLevelOperationParser(ParserState &state) : Parser(state) {}
2436 /// Parse a set of operations into the end of the given Block.
2437 ParseResult parse(Block *topLevelBlock, Location parserLoc);
2439 private:
2440 /// Parse an attribute alias declaration.
2442 /// attribute-alias-def ::= '#' alias-name `=` attribute-value
2444 ParseResult parseAttributeAliasDef();
2446 /// Parse a type alias declaration.
2448 /// type-alias-def ::= '!' alias-name `=` type
2450 ParseResult parseTypeAliasDef();
2452 /// Parse a top-level file metadata dictionary.
2454 /// file-metadata-dict ::= '{-#' file-metadata-entry* `#-}'
2456 ParseResult parseFileMetadataDictionary();
2458 /// Parse a resource metadata dictionary.
2459 ParseResult parseResourceFileMetadata(
2460 function_ref<ParseResult(StringRef, SMLoc)> parseBody);
2461 ParseResult parseDialectResourceFileMetadata();
2462 ParseResult parseExternalResourceFileMetadata();
2465 /// This class represents an implementation of a resource entry for the MLIR
2466 /// textual format.
2467 class ParsedResourceEntry : public AsmParsedResourceEntry {
2468 public:
2469 ParsedResourceEntry(StringRef key, SMLoc keyLoc, Token value, Parser &p)
2470 : key(key), keyLoc(keyLoc), value(value), p(p) {}
2471 ~ParsedResourceEntry() override = default;
2473 StringRef getKey() const final { return key; }
2475 InFlightDiagnostic emitError() const final { return p.emitError(keyLoc); }
2477 AsmResourceEntryKind getKind() const final {
2478 if (value.isAny(Token::kw_true, Token::kw_false))
2479 return AsmResourceEntryKind::Bool;
2480 return value.getSpelling().starts_with("\"0x")
2481 ? AsmResourceEntryKind::Blob
2482 : AsmResourceEntryKind::String;
2485 FailureOr<bool> parseAsBool() const final {
2486 if (value.is(Token::kw_true))
2487 return true;
2488 if (value.is(Token::kw_false))
2489 return false;
2490 return p.emitError(value.getLoc(),
2491 "expected 'true' or 'false' value for key '" + key +
2492 "'");
2495 FailureOr<std::string> parseAsString() const final {
2496 if (value.isNot(Token::string))
2497 return p.emitError(value.getLoc(),
2498 "expected string value for key '" + key + "'");
2499 return value.getStringValue();
2502 FailureOr<AsmResourceBlob>
2503 parseAsBlob(BlobAllocatorFn allocator) const final {
2504 // Blob data within then textual format is represented as a hex string.
2505 // TODO: We could avoid an additional alloc+copy here if we pre-allocated
2506 // the buffer to use during hex processing.
2507 std::optional<std::string> blobData =
2508 value.is(Token::string) ? value.getHexStringValue() : std::nullopt;
2509 if (!blobData)
2510 return p.emitError(value.getLoc(),
2511 "expected hex string blob for key '" + key + "'");
2513 // Extract the alignment of the blob data, which gets stored at the
2514 // beginning of the string.
2515 if (blobData->size() < sizeof(uint32_t)) {
2516 return p.emitError(value.getLoc(),
2517 "expected hex string blob for key '" + key +
2518 "' to encode alignment in first 4 bytes");
2520 llvm::support::ulittle32_t align;
2521 memcpy(&align, blobData->data(), sizeof(uint32_t));
2522 if (align && !llvm::isPowerOf2_32(align)) {
2523 return p.emitError(value.getLoc(),
2524 "expected hex string blob for key '" + key +
2525 "' to encode alignment in first 4 bytes, but got "
2526 "non-power-of-2 value: " +
2527 Twine(align));
2530 // Get the data portion of the blob.
2531 StringRef data = StringRef(*blobData).drop_front(sizeof(uint32_t));
2532 if (data.empty())
2533 return AsmResourceBlob();
2535 // Allocate memory for the blob using the provided allocator and copy the
2536 // data into it.
2537 AsmResourceBlob blob = allocator(data.size(), align);
2538 assert(llvm::isAddrAligned(llvm::Align(align), blob.getData().data()) &&
2539 blob.isMutable() &&
2540 "blob allocator did not return a properly aligned address");
2541 memcpy(blob.getMutableData().data(), data.data(), data.size());
2542 return blob;
2545 private:
2546 StringRef key;
2547 SMLoc keyLoc;
2548 Token value;
2549 Parser &p;
2551 } // namespace
2553 ParseResult TopLevelOperationParser::parseAttributeAliasDef() {
2554 assert(getToken().is(Token::hash_identifier));
2555 StringRef aliasName = getTokenSpelling().drop_front();
2557 // Check for redefinitions.
2558 if (state.symbols.attributeAliasDefinitions.count(aliasName) > 0)
2559 return emitError("redefinition of attribute alias id '" + aliasName + "'");
2561 // Make sure this isn't invading the dialect attribute namespace.
2562 if (aliasName.contains('.'))
2563 return emitError("attribute names with a '.' are reserved for "
2564 "dialect-defined names");
2566 SMRange location = getToken().getLocRange();
2567 consumeToken(Token::hash_identifier);
2569 // Parse the '='.
2570 if (parseToken(Token::equal, "expected '=' in attribute alias definition"))
2571 return failure();
2573 // Parse the attribute value.
2574 Attribute attr = parseAttribute();
2575 if (!attr)
2576 return failure();
2578 // Register this alias with the parser state.
2579 if (state.asmState)
2580 state.asmState->addAttrAliasDefinition(aliasName, location, attr);
2581 state.symbols.attributeAliasDefinitions[aliasName] = attr;
2582 return success();
2585 ParseResult TopLevelOperationParser::parseTypeAliasDef() {
2586 assert(getToken().is(Token::exclamation_identifier));
2587 StringRef aliasName = getTokenSpelling().drop_front();
2589 // Check for redefinitions.
2590 if (state.symbols.typeAliasDefinitions.count(aliasName) > 0)
2591 return emitError("redefinition of type alias id '" + aliasName + "'");
2593 // Make sure this isn't invading the dialect type namespace.
2594 if (aliasName.contains('.'))
2595 return emitError("type names with a '.' are reserved for "
2596 "dialect-defined names");
2598 SMRange location = getToken().getLocRange();
2599 consumeToken(Token::exclamation_identifier);
2601 // Parse the '='.
2602 if (parseToken(Token::equal, "expected '=' in type alias definition"))
2603 return failure();
2605 // Parse the type.
2606 Type aliasedType = parseType();
2607 if (!aliasedType)
2608 return failure();
2610 // Register this alias with the parser state.
2611 if (state.asmState)
2612 state.asmState->addTypeAliasDefinition(aliasName, location, aliasedType);
2613 state.symbols.typeAliasDefinitions.try_emplace(aliasName, aliasedType);
2614 return success();
2617 ParseResult TopLevelOperationParser::parseFileMetadataDictionary() {
2618 consumeToken(Token::file_metadata_begin);
2619 return parseCommaSeparatedListUntil(
2620 Token::file_metadata_end, [&]() -> ParseResult {
2621 // Parse the key of the metadata dictionary.
2622 SMLoc keyLoc = getToken().getLoc();
2623 StringRef key;
2624 if (failed(parseOptionalKeyword(&key)))
2625 return emitError("expected identifier key in file "
2626 "metadata dictionary");
2627 if (parseToken(Token::colon, "expected ':'"))
2628 return failure();
2630 // Process the metadata entry.
2631 if (key == "dialect_resources")
2632 return parseDialectResourceFileMetadata();
2633 if (key == "external_resources")
2634 return parseExternalResourceFileMetadata();
2635 return emitError(keyLoc, "unknown key '" + key +
2636 "' in file metadata dictionary");
2640 ParseResult TopLevelOperationParser::parseResourceFileMetadata(
2641 function_ref<ParseResult(StringRef, SMLoc)> parseBody) {
2642 if (parseToken(Token::l_brace, "expected '{'"))
2643 return failure();
2645 return parseCommaSeparatedListUntil(Token::r_brace, [&]() -> ParseResult {
2646 // Parse the top-level name entry.
2647 SMLoc nameLoc = getToken().getLoc();
2648 StringRef name;
2649 if (failed(parseOptionalKeyword(&name)))
2650 return emitError("expected identifier key for 'resource' entry");
2652 if (parseToken(Token::colon, "expected ':'") ||
2653 parseToken(Token::l_brace, "expected '{'"))
2654 return failure();
2655 return parseBody(name, nameLoc);
2659 ParseResult TopLevelOperationParser::parseDialectResourceFileMetadata() {
2660 return parseResourceFileMetadata([&](StringRef name,
2661 SMLoc nameLoc) -> ParseResult {
2662 // Lookup the dialect and check that it can handle a resource entry.
2663 Dialect *dialect = getContext()->getOrLoadDialect(name);
2664 if (!dialect)
2665 return emitError(nameLoc, "dialect '" + name + "' is unknown");
2666 const auto *handler = dyn_cast<OpAsmDialectInterface>(dialect);
2667 if (!handler) {
2668 return emitError() << "unexpected 'resource' section for dialect '"
2669 << dialect->getNamespace() << "'";
2672 return parseCommaSeparatedListUntil(Token::r_brace, [&]() -> ParseResult {
2673 // Parse the name of the resource entry.
2674 SMLoc keyLoc = getToken().getLoc();
2675 StringRef key;
2676 if (failed(parseResourceHandle(handler, key)) ||
2677 parseToken(Token::colon, "expected ':'"))
2678 return failure();
2679 Token valueTok = getToken();
2680 consumeToken();
2682 ParsedResourceEntry entry(key, keyLoc, valueTok, *this);
2683 return handler->parseResource(entry);
2688 ParseResult TopLevelOperationParser::parseExternalResourceFileMetadata() {
2689 return parseResourceFileMetadata([&](StringRef name,
2690 SMLoc nameLoc) -> ParseResult {
2691 AsmResourceParser *handler = state.config.getResourceParser(name);
2693 // TODO: Should we require handling external resources in some scenarios?
2694 if (!handler) {
2695 emitWarning(getEncodedSourceLocation(nameLoc))
2696 << "ignoring unknown external resources for '" << name << "'";
2699 return parseCommaSeparatedListUntil(Token::r_brace, [&]() -> ParseResult {
2700 // Parse the name of the resource entry.
2701 SMLoc keyLoc = getToken().getLoc();
2702 StringRef key;
2703 if (failed(parseOptionalKeyword(&key)))
2704 return emitError(
2705 "expected identifier key for 'external_resources' entry");
2706 if (parseToken(Token::colon, "expected ':'"))
2707 return failure();
2708 Token valueTok = getToken();
2709 consumeToken();
2711 if (!handler)
2712 return success();
2713 ParsedResourceEntry entry(key, keyLoc, valueTok, *this);
2714 return handler->parseResource(entry);
2719 ParseResult TopLevelOperationParser::parse(Block *topLevelBlock,
2720 Location parserLoc) {
2721 // Create a top-level operation to contain the parsed state.
2722 OwningOpRef<ModuleOp> topLevelOp(ModuleOp::create(parserLoc));
2723 OperationParser opParser(state, topLevelOp.get());
2724 while (true) {
2725 switch (getToken().getKind()) {
2726 default:
2727 // Parse a top-level operation.
2728 if (opParser.parseOperation())
2729 return failure();
2730 break;
2732 // If we got to the end of the file, then we're done.
2733 case Token::eof: {
2734 if (opParser.finalize())
2735 return failure();
2737 // Splice the blocks of the parsed operation over to the provided
2738 // top-level block.
2739 auto &parsedOps = topLevelOp->getBody()->getOperations();
2740 auto &destOps = topLevelBlock->getOperations();
2741 destOps.splice(destOps.end(), parsedOps, parsedOps.begin(),
2742 parsedOps.end());
2743 return success();
2746 // If we got an error token, then the lexer already emitted an error, just
2747 // stop. Someday we could introduce error recovery if there was demand
2748 // for it.
2749 case Token::error:
2750 return failure();
2752 // Parse an attribute alias.
2753 case Token::hash_identifier:
2754 if (parseAttributeAliasDef())
2755 return failure();
2756 break;
2758 // Parse a type alias.
2759 case Token::exclamation_identifier:
2760 if (parseTypeAliasDef())
2761 return failure();
2762 break;
2764 // Parse a file-level metadata dictionary.
2765 case Token::file_metadata_begin:
2766 if (parseFileMetadataDictionary())
2767 return failure();
2768 break;
2773 //===----------------------------------------------------------------------===//
2775 LogicalResult
2776 mlir::parseAsmSourceFile(const llvm::SourceMgr &sourceMgr, Block *block,
2777 const ParserConfig &config, AsmParserState *asmState,
2778 AsmParserCodeCompleteContext *codeCompleteContext) {
2779 const auto *sourceBuf = sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID());
2781 Location parserLoc =
2782 FileLineColLoc::get(config.getContext(), sourceBuf->getBufferIdentifier(),
2783 /*line=*/0, /*column=*/0);
2785 SymbolState aliasState;
2786 ParserState state(sourceMgr, config, aliasState, asmState,
2787 codeCompleteContext);
2788 return TopLevelOperationParser(state).parse(block, parserLoc);