[rtsan] Remove mkfifoat interceptor (#116997)
[llvm-project.git] / mlir / lib / AsmParser / Parser.cpp
blobe3db248164672cd5ef4144b0387d474e76f12e38
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/TypeID.h"
38 #include "llvm/ADT/APFloat.h"
39 #include "llvm/ADT/DenseMap.h"
40 #include "llvm/ADT/PointerUnion.h"
41 #include "llvm/ADT/STLExtras.h"
42 #include "llvm/ADT/ScopeExit.h"
43 #include "llvm/ADT/Sequence.h"
44 #include "llvm/ADT/StringExtras.h"
45 #include "llvm/ADT/StringMap.h"
46 #include "llvm/ADT/StringSet.h"
47 #include "llvm/Support/Alignment.h"
48 #include "llvm/Support/Casting.h"
49 #include "llvm/Support/Endian.h"
50 #include "llvm/Support/ErrorHandling.h"
51 #include "llvm/Support/MathExtras.h"
52 #include "llvm/Support/PrettyStackTrace.h"
53 #include "llvm/Support/SourceMgr.h"
54 #include "llvm/Support/raw_ostream.h"
55 #include <algorithm>
56 #include <cassert>
57 #include <cstddef>
58 #include <cstdint>
59 #include <cstring>
60 #include <memory>
61 #include <optional>
62 #include <string>
63 #include <tuple>
64 #include <utility>
65 #include <vector>
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 an optional integer value only in decimal format from the stream.
312 OptionalParseResult Parser::parseOptionalDecimalInteger(APInt &result) {
313 Token curToken = getToken();
314 if (curToken.isNot(Token::integer, Token::minus)) {
315 return std::nullopt;
318 bool negative = consumeIf(Token::minus);
319 Token curTok = getToken();
320 if (parseToken(Token::integer, "expected integer value")) {
321 return failure();
324 StringRef spelling = curTok.getSpelling();
325 // If the integer is in hexadecimal return only the 0. The lexer has already
326 // moved past the entire hexidecimal encoded integer so we reset the lex
327 // pointer to just past the 0 we actualy want to consume.
328 if (spelling[0] == '0' && spelling.size() > 1 &&
329 llvm::toLower(spelling[1]) == 'x') {
330 result = 0;
331 state.lex.resetPointer(spelling.data() + 1);
332 consumeToken();
333 return success();
336 if (spelling.getAsInteger(10, result))
337 return emitError(curTok.getLoc(), "integer value too large");
339 // Make sure we have a zero at the top so we return the right signedness.
340 if (result.isNegative())
341 result = result.zext(result.getBitWidth() + 1);
343 // Process the negative sign if present.
344 if (negative)
345 result.negate();
347 return success();
350 ParseResult Parser::parseFloatFromLiteral(std::optional<APFloat> &result,
351 const Token &tok, bool isNegative,
352 const llvm::fltSemantics &semantics) {
353 // Check for a floating point value.
354 if (tok.is(Token::floatliteral)) {
355 auto val = tok.getFloatingPointValue();
356 if (!val)
357 return emitError(tok.getLoc()) << "floating point value too large";
359 result.emplace(isNegative ? -*val : *val);
360 bool unused;
361 result->convert(semantics, APFloat::rmNearestTiesToEven, &unused);
362 return success();
365 // Check for a hexadecimal float value.
366 if (tok.is(Token::integer))
367 return parseFloatFromIntegerLiteral(result, tok, isNegative, semantics);
369 return emitError(tok.getLoc()) << "expected floating point literal";
372 /// Parse a floating point value from an integer literal token.
373 ParseResult
374 Parser::parseFloatFromIntegerLiteral(std::optional<APFloat> &result,
375 const Token &tok, bool isNegative,
376 const llvm::fltSemantics &semantics) {
377 StringRef spelling = tok.getSpelling();
378 bool isHex = spelling.size() > 1 && spelling[1] == 'x';
379 if (!isHex) {
380 return emitError(tok.getLoc(), "unexpected decimal integer literal for a "
381 "floating point value")
382 .attachNote()
383 << "add a trailing dot to make the literal a float";
385 if (isNegative) {
386 return emitError(tok.getLoc(),
387 "hexadecimal float literal should not have a "
388 "leading minus");
391 APInt intValue;
392 tok.getSpelling().getAsInteger(isHex ? 0 : 10, intValue);
393 auto typeSizeInBits = APFloat::semanticsSizeInBits(semantics);
394 if (intValue.getActiveBits() > typeSizeInBits) {
395 return emitError(tok.getLoc(),
396 "hexadecimal float constant out of range for type");
399 APInt truncatedValue(typeSizeInBits, intValue.getNumWords(),
400 intValue.getRawData());
401 result.emplace(semantics, truncatedValue);
402 return success();
405 ParseResult Parser::parseOptionalKeyword(StringRef *keyword) {
406 // Check that the current token is a keyword.
407 if (!isCurrentTokenAKeyword())
408 return failure();
410 *keyword = getTokenSpelling();
411 consumeToken();
412 return success();
415 //===----------------------------------------------------------------------===//
416 // Resource Parsing
418 FailureOr<AsmDialectResourceHandle>
419 Parser::parseResourceHandle(const OpAsmDialectInterface *dialect,
420 StringRef &name) {
421 assert(dialect && "expected valid dialect interface");
422 SMLoc nameLoc = getToken().getLoc();
423 if (failed(parseOptionalKeyword(&name)))
424 return emitError("expected identifier key for 'resource' entry");
425 auto &resources = getState().symbols.dialectResources;
427 // If this is the first time encountering this handle, ask the dialect to
428 // resolve a reference to this handle. This allows for us to remap the name of
429 // the handle if necessary.
430 std::pair<std::string, AsmDialectResourceHandle> &entry =
431 resources[dialect][name];
432 if (entry.first.empty()) {
433 FailureOr<AsmDialectResourceHandle> result = dialect->declareResource(name);
434 if (failed(result)) {
435 return emitError(nameLoc)
436 << "unknown 'resource' key '" << name << "' for dialect '"
437 << dialect->getDialect()->getNamespace() << "'";
439 entry.first = dialect->getResourceKey(*result);
440 entry.second = *result;
443 name = entry.first;
444 return entry.second;
447 FailureOr<AsmDialectResourceHandle>
448 Parser::parseResourceHandle(Dialect *dialect) {
449 const auto *interface = dyn_cast<OpAsmDialectInterface>(dialect);
450 if (!interface) {
451 return emitError() << "dialect '" << dialect->getNamespace()
452 << "' does not expect resource handles";
454 StringRef resourceName;
455 return parseResourceHandle(interface, resourceName);
458 //===----------------------------------------------------------------------===//
459 // Code Completion
461 ParseResult Parser::codeCompleteDialectName() {
462 state.codeCompleteContext->completeDialectName();
463 return failure();
466 ParseResult Parser::codeCompleteOperationName(StringRef dialectName) {
467 // Perform some simple validation on the dialect name. This doesn't need to be
468 // extensive, it's more of an optimization (to avoid checking completion
469 // results when we know they will fail).
470 if (dialectName.empty() || dialectName.contains('.'))
471 return failure();
472 state.codeCompleteContext->completeOperationName(dialectName);
473 return failure();
476 ParseResult Parser::codeCompleteDialectOrElidedOpName(SMLoc loc) {
477 // Check to see if there is anything else on the current line. This check
478 // isn't strictly necessary, but it does avoid unnecessarily triggering
479 // completions for operations and dialects in situations where we don't want
480 // them (e.g. at the end of an operation).
481 auto shouldIgnoreOpCompletion = [&]() {
482 const char *bufBegin = state.lex.getBufferBegin();
483 const char *it = loc.getPointer() - 1;
484 for (; it > bufBegin && *it != '\n'; --it)
485 if (!StringRef(" \t\r").contains(*it))
486 return true;
487 return false;
489 if (shouldIgnoreOpCompletion())
490 return failure();
492 // The completion here is either for a dialect name, or an operation name
493 // whose dialect prefix was elided. For this we simply invoke both of the
494 // individual completion methods.
495 (void)codeCompleteDialectName();
496 return codeCompleteOperationName(state.defaultDialectStack.back());
499 ParseResult Parser::codeCompleteStringDialectOrOperationName(StringRef name) {
500 // If the name is empty, this is the start of the string and contains the
501 // dialect.
502 if (name.empty())
503 return codeCompleteDialectName();
505 // Otherwise, we treat this as completing an operation name. The current name
506 // is used as the dialect namespace.
507 if (name.consume_back("."))
508 return codeCompleteOperationName(name);
509 return failure();
512 ParseResult Parser::codeCompleteExpectedTokens(ArrayRef<StringRef> tokens) {
513 state.codeCompleteContext->completeExpectedTokens(tokens, /*optional=*/false);
514 return failure();
516 ParseResult Parser::codeCompleteOptionalTokens(ArrayRef<StringRef> tokens) {
517 state.codeCompleteContext->completeExpectedTokens(tokens, /*optional=*/true);
518 return failure();
521 Attribute Parser::codeCompleteAttribute() {
522 state.codeCompleteContext->completeAttribute(
523 state.symbols.attributeAliasDefinitions);
524 return {};
526 Type Parser::codeCompleteType() {
527 state.codeCompleteContext->completeType(state.symbols.typeAliasDefinitions);
528 return {};
531 Attribute
532 Parser::codeCompleteDialectSymbol(const llvm::StringMap<Attribute> &aliases) {
533 state.codeCompleteContext->completeDialectAttributeOrAlias(aliases);
534 return {};
536 Type Parser::codeCompleteDialectSymbol(const llvm::StringMap<Type> &aliases) {
537 state.codeCompleteContext->completeDialectTypeOrAlias(aliases);
538 return {};
541 //===----------------------------------------------------------------------===//
542 // OperationParser
543 //===----------------------------------------------------------------------===//
545 namespace {
546 /// This class provides support for parsing operations and regions of
547 /// operations.
548 class OperationParser : public Parser {
549 public:
550 OperationParser(ParserState &state, ModuleOp topLevelOp);
551 ~OperationParser();
553 /// After parsing is finished, this function must be called to see if there
554 /// are any remaining issues.
555 ParseResult finalize();
557 //===--------------------------------------------------------------------===//
558 // SSA Value Handling
559 //===--------------------------------------------------------------------===//
561 using UnresolvedOperand = OpAsmParser::UnresolvedOperand;
562 using Argument = OpAsmParser::Argument;
564 struct DeferredLocInfo {
565 SMLoc loc;
566 StringRef identifier;
569 /// Push a new SSA name scope to the parser.
570 void pushSSANameScope(bool isIsolated);
572 /// Pop the last SSA name scope from the parser.
573 ParseResult popSSANameScope();
575 /// Register a definition of a value with the symbol table.
576 ParseResult addDefinition(UnresolvedOperand useInfo, Value value);
578 /// Parse an optional list of SSA uses into 'results'.
579 ParseResult
580 parseOptionalSSAUseList(SmallVectorImpl<UnresolvedOperand> &results);
582 /// Parse a single SSA use into 'result'. If 'allowResultNumber' is true then
583 /// we allow #42 syntax.
584 ParseResult parseSSAUse(UnresolvedOperand &result,
585 bool allowResultNumber = true);
587 /// Given a reference to an SSA value and its type, return a reference. This
588 /// returns null on failure.
589 Value resolveSSAUse(UnresolvedOperand useInfo, Type type);
591 ParseResult parseSSADefOrUseAndType(
592 function_ref<ParseResult(UnresolvedOperand, Type)> action);
594 ParseResult parseOptionalSSAUseAndTypeList(SmallVectorImpl<Value> &results);
596 /// Return the location of the value identified by its name and number if it
597 /// has been already reference.
598 std::optional<SMLoc> getReferenceLoc(StringRef name, unsigned number) {
599 auto &values = isolatedNameScopes.back().values;
600 if (!values.count(name) || number >= values[name].size())
601 return {};
602 if (values[name][number].value)
603 return values[name][number].loc;
604 return {};
607 //===--------------------------------------------------------------------===//
608 // Operation Parsing
609 //===--------------------------------------------------------------------===//
611 /// Parse an operation instance.
612 ParseResult parseOperation();
614 /// Parse a single operation successor.
615 ParseResult parseSuccessor(Block *&dest);
617 /// Parse a comma-separated list of operation successors in brackets.
618 ParseResult parseSuccessors(SmallVectorImpl<Block *> &destinations);
620 /// Parse an operation instance that is in the generic form.
621 Operation *parseGenericOperation();
623 /// Parse different components, viz., use-info of operand(s), successor(s),
624 /// region(s), attribute(s) and function-type, of the generic form of an
625 /// operation instance and populate the input operation-state 'result' with
626 /// those components. If any of the components is explicitly provided, then
627 /// skip parsing that component.
628 ParseResult parseGenericOperationAfterOpName(
629 OperationState &result,
630 std::optional<ArrayRef<UnresolvedOperand>> parsedOperandUseInfo =
631 std::nullopt,
632 std::optional<ArrayRef<Block *>> parsedSuccessors = std::nullopt,
633 std::optional<MutableArrayRef<std::unique_ptr<Region>>> parsedRegions =
634 std::nullopt,
635 std::optional<ArrayRef<NamedAttribute>> parsedAttributes = std::nullopt,
636 std::optional<Attribute> propertiesAttribute = std::nullopt,
637 std::optional<FunctionType> parsedFnType = std::nullopt);
639 /// Parse an operation instance that is in the generic form and insert it at
640 /// the provided insertion point.
641 Operation *parseGenericOperation(Block *insertBlock,
642 Block::iterator insertPt);
644 /// This type is used to keep track of things that are either an Operation or
645 /// a BlockArgument. We cannot use Value for this, because not all Operations
646 /// have results.
647 using OpOrArgument = llvm::PointerUnion<Operation *, BlockArgument>;
649 /// Parse an optional trailing location and add it to the specifier Operation
650 /// or `UnresolvedOperand` if present.
652 /// trailing-location ::= (`loc` (`(` location `)` | attribute-alias))?
654 ParseResult parseTrailingLocationSpecifier(OpOrArgument opOrArgument);
656 /// Parse a location alias, that is a sequence looking like: #loc42
657 /// The alias may have already be defined or may be defined later, in which
658 /// case an OpaqueLoc is used a placeholder. The caller must ensure that the
659 /// token is actually an alias, which means it must not contain a dot.
660 ParseResult parseLocationAlias(LocationAttr &loc);
662 /// This is the structure of a result specifier in the assembly syntax,
663 /// including the name, number of results, and location.
664 using ResultRecord = std::tuple<StringRef, unsigned, SMLoc>;
666 /// Parse an operation instance that is in the op-defined custom form.
667 /// resultInfo specifies information about the "%name =" specifiers.
668 Operation *parseCustomOperation(ArrayRef<ResultRecord> resultIDs);
670 /// Parse the name of an operation, in the custom form. On success, return a
671 /// an object of type 'OperationName'. Otherwise, failure is returned.
672 FailureOr<OperationName> parseCustomOperationName();
674 //===--------------------------------------------------------------------===//
675 // Region Parsing
676 //===--------------------------------------------------------------------===//
678 /// Parse a region into 'region' with the provided entry block arguments.
679 /// 'isIsolatedNameScope' indicates if the naming scope of this region is
680 /// isolated from those above.
681 ParseResult parseRegion(Region &region, ArrayRef<Argument> entryArguments,
682 bool isIsolatedNameScope = false);
684 /// Parse a region body into 'region'.
685 ParseResult parseRegionBody(Region &region, SMLoc startLoc,
686 ArrayRef<Argument> entryArguments,
687 bool isIsolatedNameScope);
689 //===--------------------------------------------------------------------===//
690 // Block Parsing
691 //===--------------------------------------------------------------------===//
693 /// Parse a new block into 'block'.
694 ParseResult parseBlock(Block *&block);
696 /// Parse a list of operations into 'block'.
697 ParseResult parseBlockBody(Block *block);
699 /// Parse a (possibly empty) list of block arguments.
700 ParseResult parseOptionalBlockArgList(Block *owner);
702 /// Get the block with the specified name, creating it if it doesn't
703 /// already exist. The location specified is the point of use, which allows
704 /// us to diagnose references to blocks that are not defined precisely.
705 Block *getBlockNamed(StringRef name, SMLoc loc);
707 //===--------------------------------------------------------------------===//
708 // Code Completion
709 //===--------------------------------------------------------------------===//
711 /// The set of various code completion methods. Every completion method
712 /// returns `failure` to stop the parsing process after providing completion
713 /// results.
715 ParseResult codeCompleteSSAUse();
716 ParseResult codeCompleteBlock();
718 private:
719 /// This class represents a definition of a Block.
720 struct BlockDefinition {
721 /// A pointer to the defined Block.
722 Block *block;
723 /// The location that the Block was defined at.
724 SMLoc loc;
726 /// This class represents a definition of a Value.
727 struct ValueDefinition {
728 /// A pointer to the defined Value.
729 Value value;
730 /// The location that the Value was defined at.
731 SMLoc loc;
734 /// Returns the info for a block at the current scope for the given name.
735 BlockDefinition &getBlockInfoByName(StringRef name) {
736 return blocksByName.back()[name];
739 /// Insert a new forward reference to the given block.
740 void insertForwardRef(Block *block, SMLoc loc) {
741 forwardRef.back().try_emplace(block, loc);
744 /// Erase any forward reference to the given block.
745 bool eraseForwardRef(Block *block) { return forwardRef.back().erase(block); }
747 /// Record that a definition was added at the current scope.
748 void recordDefinition(StringRef def);
750 /// Get the value entry for the given SSA name.
751 SmallVectorImpl<ValueDefinition> &getSSAValueEntry(StringRef name);
753 /// Create a forward reference placeholder value with the given location and
754 /// result type.
755 Value createForwardRefPlaceholder(SMLoc loc, Type type);
757 /// Return true if this is a forward reference.
758 bool isForwardRefPlaceholder(Value value) {
759 return forwardRefPlaceholders.count(value);
762 /// This struct represents an isolated SSA name scope. This scope may contain
763 /// other nested non-isolated scopes. These scopes are used for operations
764 /// that are known to be isolated to allow for reusing names within their
765 /// regions, even if those names are used above.
766 struct IsolatedSSANameScope {
767 /// Record that a definition was added at the current scope.
768 void recordDefinition(StringRef def) {
769 definitionsPerScope.back().insert(def);
772 /// Push a nested name scope.
773 void pushSSANameScope() { definitionsPerScope.push_back({}); }
775 /// Pop a nested name scope.
776 void popSSANameScope() {
777 for (auto &def : definitionsPerScope.pop_back_val())
778 values.erase(def.getKey());
781 /// This keeps track of all of the SSA values we are tracking for each name
782 /// scope, indexed by their name. This has one entry per result number.
783 llvm::StringMap<SmallVector<ValueDefinition, 1>> values;
785 /// This keeps track of all of the values defined by a specific name scope.
786 SmallVector<llvm::StringSet<>, 2> definitionsPerScope;
789 /// A list of isolated name scopes.
790 SmallVector<IsolatedSSANameScope, 2> isolatedNameScopes;
792 /// This keeps track of the block names as well as the location of the first
793 /// reference for each nested name scope. This is used to diagnose invalid
794 /// block references and memorize them.
795 SmallVector<DenseMap<StringRef, BlockDefinition>, 2> blocksByName;
796 SmallVector<DenseMap<Block *, SMLoc>, 2> forwardRef;
798 /// These are all of the placeholders we've made along with the location of
799 /// their first reference, to allow checking for use of undefined values.
800 DenseMap<Value, SMLoc> forwardRefPlaceholders;
802 /// Deffered locations: when parsing `loc(#loc42)` we add an entry to this
803 /// map. After parsing the definition `#loc42 = ...` we'll patch back users
804 /// of this location.
805 std::vector<DeferredLocInfo> deferredLocsReferences;
807 /// The builder used when creating parsed operation instances.
808 OpBuilder opBuilder;
810 /// The top level operation that holds all of the parsed operations.
811 Operation *topLevelOp;
813 } // namespace
815 MLIR_DECLARE_EXPLICIT_TYPE_ID(OperationParser::DeferredLocInfo *)
816 MLIR_DEFINE_EXPLICIT_TYPE_ID(OperationParser::DeferredLocInfo *)
818 OperationParser::OperationParser(ParserState &state, ModuleOp topLevelOp)
819 : Parser(state), opBuilder(topLevelOp.getRegion()), topLevelOp(topLevelOp) {
820 // The top level operation starts a new name scope.
821 pushSSANameScope(/*isIsolated=*/true);
823 // If we are populating the parser state, prepare it for parsing.
824 if (state.asmState)
825 state.asmState->initialize(topLevelOp);
828 OperationParser::~OperationParser() {
829 for (auto &fwd : forwardRefPlaceholders) {
830 // Drop all uses of undefined forward declared reference and destroy
831 // defining operation.
832 fwd.first.dropAllUses();
833 fwd.first.getDefiningOp()->destroy();
835 for (const auto &scope : forwardRef) {
836 for (const auto &fwd : scope) {
837 // Delete all blocks that were created as forward references but never
838 // included into a region.
839 fwd.first->dropAllUses();
840 delete fwd.first;
845 /// After parsing is finished, this function must be called to see if there are
846 /// any remaining issues.
847 ParseResult OperationParser::finalize() {
848 // Check for any forward references that are left. If we find any, error
849 // out.
850 if (!forwardRefPlaceholders.empty()) {
851 SmallVector<const char *, 4> errors;
852 // Iteration over the map isn't deterministic, so sort by source location.
853 for (auto entry : forwardRefPlaceholders)
854 errors.push_back(entry.second.getPointer());
855 llvm::array_pod_sort(errors.begin(), errors.end());
857 for (const char *entry : errors) {
858 auto loc = SMLoc::getFromPointer(entry);
859 emitError(loc, "use of undeclared SSA value name");
861 return failure();
864 // Resolve the locations of any deferred operations.
865 auto &attributeAliases = state.symbols.attributeAliasDefinitions;
866 auto locID = TypeID::get<DeferredLocInfo *>();
867 auto resolveLocation = [&, this](auto &opOrArgument) -> LogicalResult {
868 auto fwdLoc = dyn_cast<OpaqueLoc>(opOrArgument.getLoc());
869 if (!fwdLoc || fwdLoc.getUnderlyingTypeID() != locID)
870 return success();
871 auto locInfo = deferredLocsReferences[fwdLoc.getUnderlyingLocation()];
872 Attribute attr = attributeAliases.lookup(locInfo.identifier);
873 if (!attr)
874 return this->emitError(locInfo.loc)
875 << "operation location alias was never defined";
876 auto locAttr = dyn_cast<LocationAttr>(attr);
877 if (!locAttr)
878 return this->emitError(locInfo.loc)
879 << "expected location, but found '" << attr << "'";
880 opOrArgument.setLoc(locAttr);
881 return success();
884 auto walkRes = topLevelOp->walk([&](Operation *op) {
885 if (failed(resolveLocation(*op)))
886 return WalkResult::interrupt();
887 for (Region &region : op->getRegions())
888 for (Block &block : region.getBlocks())
889 for (BlockArgument arg : block.getArguments())
890 if (failed(resolveLocation(arg)))
891 return WalkResult::interrupt();
892 return WalkResult::advance();
894 if (walkRes.wasInterrupted())
895 return failure();
897 // Pop the top level name scope.
898 if (failed(popSSANameScope()))
899 return failure();
901 // Verify that the parsed operations are valid.
902 if (state.config.shouldVerifyAfterParse() && failed(verify(topLevelOp)))
903 return failure();
905 // If we are populating the parser state, finalize the top-level operation.
906 if (state.asmState)
907 state.asmState->finalize(topLevelOp);
908 return success();
911 //===----------------------------------------------------------------------===//
912 // SSA Value Handling
913 //===----------------------------------------------------------------------===//
915 void OperationParser::pushSSANameScope(bool isIsolated) {
916 blocksByName.push_back(DenseMap<StringRef, BlockDefinition>());
917 forwardRef.push_back(DenseMap<Block *, SMLoc>());
919 // Push back a new name definition scope.
920 if (isIsolated)
921 isolatedNameScopes.push_back({});
922 isolatedNameScopes.back().pushSSANameScope();
925 ParseResult OperationParser::popSSANameScope() {
926 auto forwardRefInCurrentScope = forwardRef.pop_back_val();
928 // Verify that all referenced blocks were defined.
929 if (!forwardRefInCurrentScope.empty()) {
930 SmallVector<std::pair<const char *, Block *>, 4> errors;
931 // Iteration over the map isn't deterministic, so sort by source location.
932 for (auto entry : forwardRefInCurrentScope) {
933 errors.push_back({entry.second.getPointer(), entry.first});
934 // Add this block to the top-level region to allow for automatic cleanup.
935 topLevelOp->getRegion(0).push_back(entry.first);
937 llvm::array_pod_sort(errors.begin(), errors.end());
939 for (auto entry : errors) {
940 auto loc = SMLoc::getFromPointer(entry.first);
941 emitError(loc, "reference to an undefined block");
943 return failure();
946 // Pop the next nested namescope. If there is only one internal namescope,
947 // just pop the isolated scope.
948 auto &currentNameScope = isolatedNameScopes.back();
949 if (currentNameScope.definitionsPerScope.size() == 1)
950 isolatedNameScopes.pop_back();
951 else
952 currentNameScope.popSSANameScope();
954 blocksByName.pop_back();
955 return success();
958 /// Register a definition of a value with the symbol table.
959 ParseResult OperationParser::addDefinition(UnresolvedOperand useInfo,
960 Value value) {
961 auto &entries = getSSAValueEntry(useInfo.name);
963 // Make sure there is a slot for this value.
964 if (entries.size() <= useInfo.number)
965 entries.resize(useInfo.number + 1);
967 // If we already have an entry for this, check to see if it was a definition
968 // or a forward reference.
969 if (auto existing = entries[useInfo.number].value) {
970 if (!isForwardRefPlaceholder(existing)) {
971 return emitError(useInfo.location)
972 .append("redefinition of SSA value '", useInfo.name, "'")
973 .attachNote(getEncodedSourceLocation(entries[useInfo.number].loc))
974 .append("previously defined here");
977 if (existing.getType() != value.getType()) {
978 return emitError(useInfo.location)
979 .append("definition of SSA value '", useInfo.name, "#",
980 useInfo.number, "' has type ", value.getType())
981 .attachNote(getEncodedSourceLocation(entries[useInfo.number].loc))
982 .append("previously used here with type ", existing.getType());
985 // If it was a forward reference, update everything that used it to use
986 // the actual definition instead, delete the forward ref, and remove it
987 // from our set of forward references we track.
988 existing.replaceAllUsesWith(value);
989 existing.getDefiningOp()->destroy();
990 forwardRefPlaceholders.erase(existing);
992 // If a definition of the value already exists, replace it in the assembly
993 // state.
994 if (state.asmState)
995 state.asmState->refineDefinition(existing, value);
998 /// Record this definition for the current scope.
999 entries[useInfo.number] = {value, useInfo.location};
1000 recordDefinition(useInfo.name);
1001 return success();
1004 /// Parse a (possibly empty) list of SSA operands.
1006 /// ssa-use-list ::= ssa-use (`,` ssa-use)*
1007 /// ssa-use-list-opt ::= ssa-use-list?
1009 ParseResult OperationParser::parseOptionalSSAUseList(
1010 SmallVectorImpl<UnresolvedOperand> &results) {
1011 if (!getToken().isOrIsCodeCompletionFor(Token::percent_identifier))
1012 return success();
1013 return parseCommaSeparatedList([&]() -> ParseResult {
1014 UnresolvedOperand result;
1015 if (parseSSAUse(result))
1016 return failure();
1017 results.push_back(result);
1018 return success();
1022 /// Parse a SSA operand for an operation.
1024 /// ssa-use ::= ssa-id
1026 ParseResult OperationParser::parseSSAUse(UnresolvedOperand &result,
1027 bool allowResultNumber) {
1028 if (getToken().isCodeCompletion())
1029 return codeCompleteSSAUse();
1031 result.name = getTokenSpelling();
1032 result.number = 0;
1033 result.location = getToken().getLoc();
1034 if (parseToken(Token::percent_identifier, "expected SSA operand"))
1035 return failure();
1037 // If we have an attribute ID, it is a result number.
1038 if (getToken().is(Token::hash_identifier)) {
1039 if (!allowResultNumber)
1040 return emitError("result number not allowed in argument list");
1042 if (auto value = getToken().getHashIdentifierNumber())
1043 result.number = *value;
1044 else
1045 return emitError("invalid SSA value result number");
1046 consumeToken(Token::hash_identifier);
1049 return success();
1052 /// Given an unbound reference to an SSA value and its type, return the value
1053 /// it specifies. This returns null on failure.
1054 Value OperationParser::resolveSSAUse(UnresolvedOperand useInfo, Type type) {
1055 auto &entries = getSSAValueEntry(useInfo.name);
1057 // Functor used to record the use of the given value if the assembly state
1058 // field is populated.
1059 auto maybeRecordUse = [&](Value value) {
1060 if (state.asmState)
1061 state.asmState->addUses(value, useInfo.location);
1062 return value;
1065 // If we have already seen a value of this name, return it.
1066 if (useInfo.number < entries.size() && entries[useInfo.number].value) {
1067 Value result = entries[useInfo.number].value;
1068 // Check that the type matches the other uses.
1069 if (result.getType() == type)
1070 return maybeRecordUse(result);
1072 emitError(useInfo.location, "use of value '")
1073 .append(useInfo.name,
1074 "' expects different type than prior uses: ", type, " vs ",
1075 result.getType())
1076 .attachNote(getEncodedSourceLocation(entries[useInfo.number].loc))
1077 .append("prior use here");
1078 return nullptr;
1081 // Make sure we have enough slots for this.
1082 if (entries.size() <= useInfo.number)
1083 entries.resize(useInfo.number + 1);
1085 // If the value has already been defined and this is an overly large result
1086 // number, diagnose that.
1087 if (entries[0].value && !isForwardRefPlaceholder(entries[0].value))
1088 return (emitError(useInfo.location, "reference to invalid result number"),
1089 nullptr);
1091 // Otherwise, this is a forward reference. Create a placeholder and remember
1092 // that we did so.
1093 Value result = createForwardRefPlaceholder(useInfo.location, type);
1094 entries[useInfo.number] = {result, useInfo.location};
1095 return maybeRecordUse(result);
1098 /// Parse an SSA use with an associated type.
1100 /// ssa-use-and-type ::= ssa-use `:` type
1101 ParseResult OperationParser::parseSSADefOrUseAndType(
1102 function_ref<ParseResult(UnresolvedOperand, Type)> action) {
1103 UnresolvedOperand useInfo;
1104 if (parseSSAUse(useInfo) ||
1105 parseToken(Token::colon, "expected ':' and type for SSA operand"))
1106 return failure();
1108 auto type = parseType();
1109 if (!type)
1110 return failure();
1112 return action(useInfo, type);
1115 /// Parse a (possibly empty) list of SSA operands, followed by a colon, then
1116 /// followed by a type list.
1118 /// ssa-use-and-type-list
1119 /// ::= ssa-use-list ':' type-list-no-parens
1121 ParseResult OperationParser::parseOptionalSSAUseAndTypeList(
1122 SmallVectorImpl<Value> &results) {
1123 SmallVector<UnresolvedOperand, 4> valueIDs;
1124 if (parseOptionalSSAUseList(valueIDs))
1125 return failure();
1127 // If there were no operands, then there is no colon or type lists.
1128 if (valueIDs.empty())
1129 return success();
1131 SmallVector<Type, 4> types;
1132 if (parseToken(Token::colon, "expected ':' in operand list") ||
1133 parseTypeListNoParens(types))
1134 return failure();
1136 if (valueIDs.size() != types.size())
1137 return emitError("expected ")
1138 << valueIDs.size() << " types to match operand list";
1140 results.reserve(valueIDs.size());
1141 for (unsigned i = 0, e = valueIDs.size(); i != e; ++i) {
1142 if (auto value = resolveSSAUse(valueIDs[i], types[i]))
1143 results.push_back(value);
1144 else
1145 return failure();
1148 return success();
1151 /// Record that a definition was added at the current scope.
1152 void OperationParser::recordDefinition(StringRef def) {
1153 isolatedNameScopes.back().recordDefinition(def);
1156 /// Get the value entry for the given SSA name.
1157 auto OperationParser::getSSAValueEntry(StringRef name)
1158 -> SmallVectorImpl<ValueDefinition> & {
1159 return isolatedNameScopes.back().values[name];
1162 /// Create and remember a new placeholder for a forward reference.
1163 Value OperationParser::createForwardRefPlaceholder(SMLoc loc, Type type) {
1164 // Forward references are always created as operations, because we just need
1165 // something with a def/use chain.
1167 // We create these placeholders as having an empty name, which we know
1168 // cannot be created through normal user input, allowing us to distinguish
1169 // them.
1170 auto name = OperationName("builtin.unrealized_conversion_cast", getContext());
1171 auto *op = Operation::create(
1172 getEncodedSourceLocation(loc), name, type, /*operands=*/{},
1173 /*attributes=*/std::nullopt, /*properties=*/nullptr, /*successors=*/{},
1174 /*numRegions=*/0);
1175 forwardRefPlaceholders[op->getResult(0)] = loc;
1176 return op->getResult(0);
1179 //===----------------------------------------------------------------------===//
1180 // Operation Parsing
1181 //===----------------------------------------------------------------------===//
1183 /// Parse an operation.
1185 /// operation ::= op-result-list?
1186 /// (generic-operation | custom-operation)
1187 /// trailing-location?
1188 /// generic-operation ::= string-literal `(` ssa-use-list? `)`
1189 /// successor-list? (`(` region-list `)`)?
1190 /// attribute-dict? `:` function-type
1191 /// custom-operation ::= bare-id custom-operation-format
1192 /// op-result-list ::= op-result (`,` op-result)* `=`
1193 /// op-result ::= ssa-id (`:` integer-literal)
1195 ParseResult OperationParser::parseOperation() {
1196 auto loc = getToken().getLoc();
1197 SmallVector<ResultRecord, 1> resultIDs;
1198 size_t numExpectedResults = 0;
1199 if (getToken().is(Token::percent_identifier)) {
1200 // Parse the group of result ids.
1201 auto parseNextResult = [&]() -> ParseResult {
1202 // Parse the next result id.
1203 Token nameTok = getToken();
1204 if (parseToken(Token::percent_identifier,
1205 "expected valid ssa identifier"))
1206 return failure();
1208 // If the next token is a ':', we parse the expected result count.
1209 size_t expectedSubResults = 1;
1210 if (consumeIf(Token::colon)) {
1211 // Check that the next token is an integer.
1212 if (!getToken().is(Token::integer))
1213 return emitWrongTokenError("expected integer number of results");
1215 // Check that number of results is > 0.
1216 auto val = getToken().getUInt64IntegerValue();
1217 if (!val || *val < 1)
1218 return emitError(
1219 "expected named operation to have at least 1 result");
1220 consumeToken(Token::integer);
1221 expectedSubResults = *val;
1224 resultIDs.emplace_back(nameTok.getSpelling(), expectedSubResults,
1225 nameTok.getLoc());
1226 numExpectedResults += expectedSubResults;
1227 return success();
1229 if (parseCommaSeparatedList(parseNextResult))
1230 return failure();
1232 if (parseToken(Token::equal, "expected '=' after SSA name"))
1233 return failure();
1236 Operation *op;
1237 Token nameTok = getToken();
1238 if (nameTok.is(Token::bare_identifier) || nameTok.isKeyword())
1239 op = parseCustomOperation(resultIDs);
1240 else if (nameTok.is(Token::string))
1241 op = parseGenericOperation();
1242 else if (nameTok.isCodeCompletionFor(Token::string))
1243 return codeCompleteStringDialectOrOperationName(nameTok.getStringValue());
1244 else if (nameTok.isCodeCompletion())
1245 return codeCompleteDialectOrElidedOpName(loc);
1246 else
1247 return emitWrongTokenError("expected operation name in quotes");
1249 // If parsing of the basic operation failed, then this whole thing fails.
1250 if (!op)
1251 return failure();
1253 // If the operation had a name, register it.
1254 if (!resultIDs.empty()) {
1255 if (op->getNumResults() == 0)
1256 return emitError(loc, "cannot name an operation with no results");
1257 if (numExpectedResults != op->getNumResults())
1258 return emitError(loc, "operation defines ")
1259 << op->getNumResults() << " results but was provided "
1260 << numExpectedResults << " to bind";
1262 // Add this operation to the assembly state if it was provided to populate.
1263 if (state.asmState) {
1264 unsigned resultIt = 0;
1265 SmallVector<std::pair<unsigned, SMLoc>> asmResultGroups;
1266 asmResultGroups.reserve(resultIDs.size());
1267 for (ResultRecord &record : resultIDs) {
1268 asmResultGroups.emplace_back(resultIt, std::get<2>(record));
1269 resultIt += std::get<1>(record);
1271 state.asmState->finalizeOperationDefinition(
1272 op, nameTok.getLocRange(), /*endLoc=*/getLastToken().getEndLoc(),
1273 asmResultGroups);
1276 // Add definitions for each of the result groups.
1277 unsigned opResI = 0;
1278 for (ResultRecord &resIt : resultIDs) {
1279 for (unsigned subRes : llvm::seq<unsigned>(0, std::get<1>(resIt))) {
1280 if (addDefinition({std::get<2>(resIt), std::get<0>(resIt), subRes},
1281 op->getResult(opResI++)))
1282 return failure();
1286 // Add this operation to the assembly state if it was provided to populate.
1287 } else if (state.asmState) {
1288 state.asmState->finalizeOperationDefinition(
1289 op, nameTok.getLocRange(),
1290 /*endLoc=*/getLastToken().getEndLoc());
1293 return success();
1296 /// Parse a single operation successor.
1298 /// successor ::= block-id
1300 ParseResult OperationParser::parseSuccessor(Block *&dest) {
1301 if (getToken().isCodeCompletion())
1302 return codeCompleteBlock();
1304 // Verify branch is identifier and get the matching block.
1305 if (!getToken().is(Token::caret_identifier))
1306 return emitWrongTokenError("expected block name");
1307 dest = getBlockNamed(getTokenSpelling(), getToken().getLoc());
1308 consumeToken();
1309 return success();
1312 /// Parse a comma-separated list of operation successors in brackets.
1314 /// successor-list ::= `[` successor (`,` successor )* `]`
1316 ParseResult
1317 OperationParser::parseSuccessors(SmallVectorImpl<Block *> &destinations) {
1318 if (parseToken(Token::l_square, "expected '['"))
1319 return failure();
1321 auto parseElt = [this, &destinations] {
1322 Block *dest;
1323 ParseResult res = parseSuccessor(dest);
1324 destinations.push_back(dest);
1325 return res;
1327 return parseCommaSeparatedListUntil(Token::r_square, parseElt,
1328 /*allowEmptyList=*/false);
1331 namespace {
1332 // RAII-style guard for cleaning up the regions in the operation state before
1333 // deleting them. Within the parser, regions may get deleted if parsing failed,
1334 // and other errors may be present, in particular undominated uses. This makes
1335 // sure such uses are deleted.
1336 struct CleanupOpStateRegions {
1337 ~CleanupOpStateRegions() {
1338 SmallVector<Region *, 4> regionsToClean;
1339 regionsToClean.reserve(state.regions.size());
1340 for (auto &region : state.regions)
1341 if (region)
1342 for (auto &block : *region)
1343 block.dropAllDefinedValueUses();
1345 OperationState &state;
1347 } // namespace
1349 ParseResult OperationParser::parseGenericOperationAfterOpName(
1350 OperationState &result,
1351 std::optional<ArrayRef<UnresolvedOperand>> parsedOperandUseInfo,
1352 std::optional<ArrayRef<Block *>> parsedSuccessors,
1353 std::optional<MutableArrayRef<std::unique_ptr<Region>>> parsedRegions,
1354 std::optional<ArrayRef<NamedAttribute>> parsedAttributes,
1355 std::optional<Attribute> propertiesAttribute,
1356 std::optional<FunctionType> parsedFnType) {
1358 // Parse the operand list, if not explicitly provided.
1359 SmallVector<UnresolvedOperand, 8> opInfo;
1360 if (!parsedOperandUseInfo) {
1361 if (parseToken(Token::l_paren, "expected '(' to start operand list") ||
1362 parseOptionalSSAUseList(opInfo) ||
1363 parseToken(Token::r_paren, "expected ')' to end operand list")) {
1364 return failure();
1366 parsedOperandUseInfo = opInfo;
1369 // Parse the successor list, if not explicitly provided.
1370 if (!parsedSuccessors) {
1371 if (getToken().is(Token::l_square)) {
1372 // Check if the operation is not a known terminator.
1373 if (!result.name.mightHaveTrait<OpTrait::IsTerminator>())
1374 return emitError("successors in non-terminator");
1376 SmallVector<Block *, 2> successors;
1377 if (parseSuccessors(successors))
1378 return failure();
1379 result.addSuccessors(successors);
1381 } else {
1382 result.addSuccessors(*parsedSuccessors);
1385 // Parse the properties, if not explicitly provided.
1386 if (propertiesAttribute) {
1387 result.propertiesAttr = *propertiesAttribute;
1388 } else if (consumeIf(Token::less)) {
1389 result.propertiesAttr = parseAttribute();
1390 if (!result.propertiesAttr)
1391 return failure();
1392 if (parseToken(Token::greater, "expected '>' to close properties"))
1393 return failure();
1395 // Parse the region list, if not explicitly provided.
1396 if (!parsedRegions) {
1397 if (consumeIf(Token::l_paren)) {
1398 do {
1399 // Create temporary regions with the top level region as parent.
1400 result.regions.emplace_back(new Region(topLevelOp));
1401 if (parseRegion(*result.regions.back(), /*entryArguments=*/{}))
1402 return failure();
1403 } while (consumeIf(Token::comma));
1404 if (parseToken(Token::r_paren, "expected ')' to end region list"))
1405 return failure();
1407 } else {
1408 result.addRegions(*parsedRegions);
1411 // Parse the attributes, if not explicitly provided.
1412 if (!parsedAttributes) {
1413 if (getToken().is(Token::l_brace)) {
1414 if (parseAttributeDict(result.attributes))
1415 return failure();
1417 } else {
1418 result.addAttributes(*parsedAttributes);
1421 // Parse the operation type, if not explicitly provided.
1422 Location typeLoc = result.location;
1423 if (!parsedFnType) {
1424 if (parseToken(Token::colon, "expected ':' followed by operation type"))
1425 return failure();
1427 typeLoc = getEncodedSourceLocation(getToken().getLoc());
1428 auto type = parseType();
1429 if (!type)
1430 return failure();
1431 auto fnType = dyn_cast<FunctionType>(type);
1432 if (!fnType)
1433 return mlir::emitError(typeLoc, "expected function type");
1435 parsedFnType = fnType;
1438 result.addTypes(parsedFnType->getResults());
1440 // Check that we have the right number of types for the operands.
1441 ArrayRef<Type> operandTypes = parsedFnType->getInputs();
1442 if (operandTypes.size() != parsedOperandUseInfo->size()) {
1443 auto plural = "s"[parsedOperandUseInfo->size() == 1];
1444 return mlir::emitError(typeLoc, "expected ")
1445 << parsedOperandUseInfo->size() << " operand type" << plural
1446 << " but had " << operandTypes.size();
1449 // Resolve all of the operands.
1450 for (unsigned i = 0, e = parsedOperandUseInfo->size(); i != e; ++i) {
1451 result.operands.push_back(
1452 resolveSSAUse((*parsedOperandUseInfo)[i], operandTypes[i]));
1453 if (!result.operands.back())
1454 return failure();
1457 return success();
1460 Operation *OperationParser::parseGenericOperation() {
1461 // Get location information for the operation.
1462 auto srcLocation = getEncodedSourceLocation(getToken().getLoc());
1464 std::string name = getToken().getStringValue();
1465 if (name.empty())
1466 return (emitError("empty operation name is invalid"), nullptr);
1467 if (name.find('\0') != StringRef::npos)
1468 return (emitError("null character not allowed in operation name"), nullptr);
1470 consumeToken(Token::string);
1472 OperationState result(srcLocation, name);
1473 CleanupOpStateRegions guard{result};
1475 // Lazy load dialects in the context as needed.
1476 if (!result.name.isRegistered()) {
1477 StringRef dialectName = StringRef(name).split('.').first;
1478 if (!getContext()->getLoadedDialect(dialectName) &&
1479 !getContext()->getOrLoadDialect(dialectName)) {
1480 if (!getContext()->allowsUnregisteredDialects()) {
1481 // Emit an error if the dialect couldn't be loaded (i.e., it was not
1482 // registered) and unregistered dialects aren't allowed.
1483 emitError("operation being parsed with an unregistered dialect. If "
1484 "this is intended, please use -allow-unregistered-dialect "
1485 "with the MLIR tool used");
1486 return nullptr;
1488 } else {
1489 // Reload the OperationName now that the dialect is loaded.
1490 result.name = OperationName(name, getContext());
1494 // If we are populating the parser state, start a new operation definition.
1495 if (state.asmState)
1496 state.asmState->startOperationDefinition(result.name);
1498 if (parseGenericOperationAfterOpName(result))
1499 return nullptr;
1501 // Operation::create() is not allowed to fail, however setting the properties
1502 // from an attribute is a failable operation. So we save the attribute here
1503 // and set it on the operation post-parsing.
1504 Attribute properties;
1505 std::swap(properties, result.propertiesAttr);
1507 // If we don't have properties in the textual IR, but the operation now has
1508 // support for properties, we support some backward-compatible generic syntax
1509 // for the operation and as such we accept inherent attributes mixed in the
1510 // dictionary of discardable attributes. We pre-validate these here because
1511 // invalid attributes can't be casted to the properties storage and will be
1512 // silently dropped. For example an attribute { foo = 0 : i32 } that is
1513 // declared as F32Attr in ODS would have a C++ type of FloatAttr in the
1514 // properties array. When setting it we would do something like:
1516 // properties.foo = dyn_cast<FloatAttr>(fooAttr);
1518 // which would end up with a null Attribute. The diagnostic from the verifier
1519 // would be "missing foo attribute" instead of something like "expects a 32
1520 // bits float attribute but got a 32 bits integer attribute".
1521 if (!properties && !result.getRawProperties()) {
1522 std::optional<RegisteredOperationName> info =
1523 result.name.getRegisteredInfo();
1524 if (info) {
1525 if (failed(info->verifyInherentAttrs(result.attributes, [&]() {
1526 return mlir::emitError(srcLocation) << "'" << name << "' op ";
1527 })))
1528 return nullptr;
1532 // Create the operation and try to parse a location for it.
1533 Operation *op = opBuilder.create(result);
1534 if (parseTrailingLocationSpecifier(op))
1535 return nullptr;
1537 // Try setting the properties for the operation, using a diagnostic to print
1538 // errors.
1539 if (properties) {
1540 auto emitError = [&]() {
1541 return mlir::emitError(srcLocation, "invalid properties ")
1542 << properties << " for op " << name << ": ";
1544 if (failed(op->setPropertiesFromAttribute(properties, emitError)))
1545 return nullptr;
1548 return op;
1551 Operation *OperationParser::parseGenericOperation(Block *insertBlock,
1552 Block::iterator insertPt) {
1553 Token nameToken = getToken();
1555 OpBuilder::InsertionGuard restoreInsertionPoint(opBuilder);
1556 opBuilder.setInsertionPoint(insertBlock, insertPt);
1557 Operation *op = parseGenericOperation();
1558 if (!op)
1559 return nullptr;
1561 // If we are populating the parser asm state, finalize this operation
1562 // definition.
1563 if (state.asmState)
1564 state.asmState->finalizeOperationDefinition(
1565 op, nameToken.getLocRange(),
1566 /*endLoc=*/getLastToken().getEndLoc());
1567 return op;
1570 namespace {
1571 class CustomOpAsmParser : public AsmParserImpl<OpAsmParser> {
1572 public:
1573 CustomOpAsmParser(
1574 SMLoc nameLoc, ArrayRef<OperationParser::ResultRecord> resultIDs,
1575 function_ref<ParseResult(OpAsmParser &, OperationState &)> parseAssembly,
1576 bool isIsolatedFromAbove, StringRef opName, OperationParser &parser)
1577 : AsmParserImpl<OpAsmParser>(nameLoc, parser), resultIDs(resultIDs),
1578 parseAssembly(parseAssembly), isIsolatedFromAbove(isIsolatedFromAbove),
1579 opName(opName), parser(parser) {
1580 (void)isIsolatedFromAbove; // Only used in assert, silence unused warning.
1583 /// Parse an instance of the operation described by 'opDefinition' into the
1584 /// provided operation state.
1585 ParseResult parseOperation(OperationState &opState) {
1586 if (parseAssembly(*this, opState))
1587 return failure();
1588 // Verify that the parsed attributes does not have duplicate attributes.
1589 // This can happen if an attribute set during parsing is also specified in
1590 // the attribute dictionary in the assembly, or the attribute is set
1591 // multiple during parsing.
1592 std::optional<NamedAttribute> duplicate =
1593 opState.attributes.findDuplicate();
1594 if (duplicate)
1595 return emitError(getNameLoc(), "attribute '")
1596 << duplicate->getName().getValue()
1597 << "' occurs more than once in the attribute list";
1598 return success();
1601 Operation *parseGenericOperation(Block *insertBlock,
1602 Block::iterator insertPt) final {
1603 return parser.parseGenericOperation(insertBlock, insertPt);
1606 FailureOr<OperationName> parseCustomOperationName() final {
1607 return parser.parseCustomOperationName();
1610 ParseResult parseGenericOperationAfterOpName(
1611 OperationState &result,
1612 std::optional<ArrayRef<UnresolvedOperand>> parsedUnresolvedOperands,
1613 std::optional<ArrayRef<Block *>> parsedSuccessors,
1614 std::optional<MutableArrayRef<std::unique_ptr<Region>>> parsedRegions,
1615 std::optional<ArrayRef<NamedAttribute>> parsedAttributes,
1616 std::optional<Attribute> parsedPropertiesAttribute,
1617 std::optional<FunctionType> parsedFnType) final {
1618 return parser.parseGenericOperationAfterOpName(
1619 result, parsedUnresolvedOperands, parsedSuccessors, parsedRegions,
1620 parsedAttributes, parsedPropertiesAttribute, parsedFnType);
1622 //===--------------------------------------------------------------------===//
1623 // Utilities
1624 //===--------------------------------------------------------------------===//
1626 /// Return the name of the specified result in the specified syntax, as well
1627 /// as the subelement in the name. For example, in this operation:
1629 /// %x, %y:2, %z = foo.op
1631 /// getResultName(0) == {"x", 0 }
1632 /// getResultName(1) == {"y", 0 }
1633 /// getResultName(2) == {"y", 1 }
1634 /// getResultName(3) == {"z", 0 }
1635 std::pair<StringRef, unsigned>
1636 getResultName(unsigned resultNo) const override {
1637 // Scan for the resultID that contains this result number.
1638 for (const auto &entry : resultIDs) {
1639 if (resultNo < std::get<1>(entry)) {
1640 // Don't pass on the leading %.
1641 StringRef name = std::get<0>(entry).drop_front();
1642 return {name, resultNo};
1644 resultNo -= std::get<1>(entry);
1647 // Invalid result number.
1648 return {"", ~0U};
1651 /// Return the number of declared SSA results. This returns 4 for the foo.op
1652 /// example in the comment for getResultName.
1653 size_t getNumResults() const override {
1654 size_t count = 0;
1655 for (auto &entry : resultIDs)
1656 count += std::get<1>(entry);
1657 return count;
1660 /// Emit a diagnostic at the specified location and return failure.
1661 InFlightDiagnostic emitError(SMLoc loc, const Twine &message) override {
1662 return AsmParserImpl<OpAsmParser>::emitError(loc, "custom op '" + opName +
1663 "' " + message);
1666 //===--------------------------------------------------------------------===//
1667 // Operand Parsing
1668 //===--------------------------------------------------------------------===//
1670 /// Parse a single operand.
1671 ParseResult parseOperand(UnresolvedOperand &result,
1672 bool allowResultNumber = true) override {
1673 OperationParser::UnresolvedOperand useInfo;
1674 if (parser.parseSSAUse(useInfo, allowResultNumber))
1675 return failure();
1677 result = {useInfo.location, useInfo.name, useInfo.number};
1678 return success();
1681 /// Parse a single operand if present.
1682 OptionalParseResult
1683 parseOptionalOperand(UnresolvedOperand &result,
1684 bool allowResultNumber = true) override {
1685 if (parser.getToken().isOrIsCodeCompletionFor(Token::percent_identifier))
1686 return parseOperand(result, allowResultNumber);
1687 return std::nullopt;
1690 /// Parse zero or more SSA comma-separated operand references with a specified
1691 /// surrounding delimiter, and an optional required operand count.
1692 ParseResult parseOperandList(SmallVectorImpl<UnresolvedOperand> &result,
1693 Delimiter delimiter = Delimiter::None,
1694 bool allowResultNumber = true,
1695 int requiredOperandCount = -1) override {
1696 // The no-delimiter case has some special handling for better diagnostics.
1697 if (delimiter == Delimiter::None) {
1698 // parseCommaSeparatedList doesn't handle the missing case for "none",
1699 // so we handle it custom here.
1700 Token tok = parser.getToken();
1701 if (!tok.isOrIsCodeCompletionFor(Token::percent_identifier)) {
1702 // If we didn't require any operands or required exactly zero (weird)
1703 // then this is success.
1704 if (requiredOperandCount == -1 || requiredOperandCount == 0)
1705 return success();
1707 // Otherwise, try to produce a nice error message.
1708 if (tok.isAny(Token::l_paren, Token::l_square))
1709 return parser.emitError("unexpected delimiter");
1710 return parser.emitWrongTokenError("expected operand");
1714 auto parseOneOperand = [&]() -> ParseResult {
1715 return parseOperand(result.emplace_back(), allowResultNumber);
1718 auto startLoc = parser.getToken().getLoc();
1719 if (parseCommaSeparatedList(delimiter, parseOneOperand, " in operand list"))
1720 return failure();
1722 // Check that we got the expected # of elements.
1723 if (requiredOperandCount != -1 &&
1724 result.size() != static_cast<size_t>(requiredOperandCount))
1725 return emitError(startLoc, "expected ")
1726 << requiredOperandCount << " operands";
1727 return success();
1730 /// Resolve an operand to an SSA value, emitting an error on failure.
1731 ParseResult resolveOperand(const UnresolvedOperand &operand, Type type,
1732 SmallVectorImpl<Value> &result) override {
1733 if (auto value = parser.resolveSSAUse(operand, type)) {
1734 result.push_back(value);
1735 return success();
1737 return failure();
1740 /// Parse an AffineMap of SSA ids.
1741 ParseResult
1742 parseAffineMapOfSSAIds(SmallVectorImpl<UnresolvedOperand> &operands,
1743 Attribute &mapAttr, StringRef attrName,
1744 NamedAttrList &attrs, Delimiter delimiter) override {
1745 SmallVector<UnresolvedOperand, 2> dimOperands;
1746 SmallVector<UnresolvedOperand, 1> symOperands;
1748 auto parseElement = [&](bool isSymbol) -> ParseResult {
1749 UnresolvedOperand operand;
1750 if (parseOperand(operand))
1751 return failure();
1752 if (isSymbol)
1753 symOperands.push_back(operand);
1754 else
1755 dimOperands.push_back(operand);
1756 return success();
1759 AffineMap map;
1760 if (parser.parseAffineMapOfSSAIds(map, parseElement, delimiter))
1761 return failure();
1762 // Add AffineMap attribute.
1763 if (map) {
1764 mapAttr = AffineMapAttr::get(map);
1765 attrs.push_back(parser.builder.getNamedAttr(attrName, mapAttr));
1768 // Add dim operands before symbol operands in 'operands'.
1769 operands.assign(dimOperands.begin(), dimOperands.end());
1770 operands.append(symOperands.begin(), symOperands.end());
1771 return success();
1774 /// Parse an AffineExpr of SSA ids.
1775 ParseResult
1776 parseAffineExprOfSSAIds(SmallVectorImpl<UnresolvedOperand> &dimOperands,
1777 SmallVectorImpl<UnresolvedOperand> &symbOperands,
1778 AffineExpr &expr) override {
1779 auto parseElement = [&](bool isSymbol) -> ParseResult {
1780 UnresolvedOperand operand;
1781 if (parseOperand(operand))
1782 return failure();
1783 if (isSymbol)
1784 symbOperands.push_back(operand);
1785 else
1786 dimOperands.push_back(operand);
1787 return success();
1790 return parser.parseAffineExprOfSSAIds(expr, parseElement);
1793 //===--------------------------------------------------------------------===//
1794 // Argument Parsing
1795 //===--------------------------------------------------------------------===//
1797 /// Parse a single argument with the following syntax:
1799 /// `%ssaname : !type { optionalAttrDict} loc(optionalSourceLoc)`
1801 /// If `allowType` is false or `allowAttrs` are false then the respective
1802 /// parts of the grammar are not parsed.
1803 ParseResult parseArgument(Argument &result, bool allowType = false,
1804 bool allowAttrs = false) override {
1805 NamedAttrList attrs;
1806 if (parseOperand(result.ssaName, /*allowResultNumber=*/false) ||
1807 (allowType && parseColonType(result.type)) ||
1808 (allowAttrs && parseOptionalAttrDict(attrs)) ||
1809 parseOptionalLocationSpecifier(result.sourceLoc))
1810 return failure();
1811 result.attrs = attrs.getDictionary(getContext());
1812 return success();
1815 /// Parse a single argument if present.
1816 OptionalParseResult parseOptionalArgument(Argument &result, bool allowType,
1817 bool allowAttrs) override {
1818 if (parser.getToken().is(Token::percent_identifier))
1819 return parseArgument(result, allowType, allowAttrs);
1820 return std::nullopt;
1823 ParseResult parseArgumentList(SmallVectorImpl<Argument> &result,
1824 Delimiter delimiter, bool allowType,
1825 bool allowAttrs) override {
1826 // The no-delimiter case has some special handling for the empty case.
1827 if (delimiter == Delimiter::None &&
1828 parser.getToken().isNot(Token::percent_identifier))
1829 return success();
1831 auto parseOneArgument = [&]() -> ParseResult {
1832 return parseArgument(result.emplace_back(), allowType, allowAttrs);
1834 return parseCommaSeparatedList(delimiter, parseOneArgument,
1835 " in argument list");
1838 //===--------------------------------------------------------------------===//
1839 // Region Parsing
1840 //===--------------------------------------------------------------------===//
1842 /// Parse a region that takes `arguments` of `argTypes` types. This
1843 /// effectively defines the SSA values of `arguments` and assigns their type.
1844 ParseResult parseRegion(Region &region, ArrayRef<Argument> arguments,
1845 bool enableNameShadowing) override {
1846 // Try to parse the region.
1847 (void)isIsolatedFromAbove;
1848 assert((!enableNameShadowing || isIsolatedFromAbove) &&
1849 "name shadowing is only allowed on isolated regions");
1850 if (parser.parseRegion(region, arguments, enableNameShadowing))
1851 return failure();
1852 return success();
1855 /// Parses a region if present.
1856 OptionalParseResult parseOptionalRegion(Region &region,
1857 ArrayRef<Argument> arguments,
1858 bool enableNameShadowing) override {
1859 if (parser.getToken().isNot(Token::l_brace))
1860 return std::nullopt;
1861 return parseRegion(region, arguments, enableNameShadowing);
1864 /// Parses a region if present. If the region is present, a new region is
1865 /// allocated and placed in `region`. If no region is present, `region`
1866 /// remains untouched.
1867 OptionalParseResult
1868 parseOptionalRegion(std::unique_ptr<Region> &region,
1869 ArrayRef<Argument> arguments,
1870 bool enableNameShadowing = false) override {
1871 if (parser.getToken().isNot(Token::l_brace))
1872 return std::nullopt;
1873 std::unique_ptr<Region> newRegion = std::make_unique<Region>();
1874 if (parseRegion(*newRegion, arguments, enableNameShadowing))
1875 return failure();
1877 region = std::move(newRegion);
1878 return success();
1881 //===--------------------------------------------------------------------===//
1882 // Successor Parsing
1883 //===--------------------------------------------------------------------===//
1885 /// Parse a single operation successor.
1886 ParseResult parseSuccessor(Block *&dest) override {
1887 return parser.parseSuccessor(dest);
1890 /// Parse an optional operation successor and its operand list.
1891 OptionalParseResult parseOptionalSuccessor(Block *&dest) override {
1892 if (!parser.getToken().isOrIsCodeCompletionFor(Token::caret_identifier))
1893 return std::nullopt;
1894 return parseSuccessor(dest);
1897 /// Parse a single operation successor and its operand list.
1898 ParseResult
1899 parseSuccessorAndUseList(Block *&dest,
1900 SmallVectorImpl<Value> &operands) override {
1901 if (parseSuccessor(dest))
1902 return failure();
1904 // Handle optional arguments.
1905 if (succeeded(parseOptionalLParen()) &&
1906 (parser.parseOptionalSSAUseAndTypeList(operands) || parseRParen())) {
1907 return failure();
1909 return success();
1912 //===--------------------------------------------------------------------===//
1913 // Type Parsing
1914 //===--------------------------------------------------------------------===//
1916 /// Parse a list of assignments of the form
1917 /// (%x1 = %y1, %x2 = %y2, ...).
1918 OptionalParseResult parseOptionalAssignmentList(
1919 SmallVectorImpl<Argument> &lhs,
1920 SmallVectorImpl<UnresolvedOperand> &rhs) override {
1921 if (failed(parseOptionalLParen()))
1922 return std::nullopt;
1924 auto parseElt = [&]() -> ParseResult {
1925 if (parseArgument(lhs.emplace_back()) || parseEqual() ||
1926 parseOperand(rhs.emplace_back()))
1927 return failure();
1928 return success();
1930 return parser.parseCommaSeparatedListUntil(Token::r_paren, parseElt);
1933 /// Parse a loc(...) specifier if present, filling in result if so.
1934 ParseResult
1935 parseOptionalLocationSpecifier(std::optional<Location> &result) override {
1936 // If there is a 'loc' we parse a trailing location.
1937 if (!parser.consumeIf(Token::kw_loc))
1938 return success();
1939 LocationAttr directLoc;
1940 if (parser.parseToken(Token::l_paren, "expected '(' in location"))
1941 return failure();
1943 Token tok = parser.getToken();
1945 // Check to see if we are parsing a location alias. We are parsing a
1946 // location alias if the token is a hash identifier *without* a dot in it -
1947 // the dot signifies a dialect attribute. Otherwise, we parse the location
1948 // directly.
1949 if (tok.is(Token::hash_identifier) && !tok.getSpelling().contains('.')) {
1950 if (parser.parseLocationAlias(directLoc))
1951 return failure();
1952 } else if (parser.parseLocationInstance(directLoc)) {
1953 return failure();
1956 if (parser.parseToken(Token::r_paren, "expected ')' in location"))
1957 return failure();
1959 result = directLoc;
1960 return success();
1963 private:
1964 /// Information about the result name specifiers.
1965 ArrayRef<OperationParser::ResultRecord> resultIDs;
1967 /// The abstract information of the operation.
1968 function_ref<ParseResult(OpAsmParser &, OperationState &)> parseAssembly;
1969 bool isIsolatedFromAbove;
1970 StringRef opName;
1972 /// The backing operation parser.
1973 OperationParser &parser;
1975 } // namespace
1977 FailureOr<OperationName> OperationParser::parseCustomOperationName() {
1978 Token nameTok = getToken();
1979 StringRef opName = nameTok.getSpelling();
1980 if (opName.empty())
1981 return (emitError("empty operation name is invalid"), failure());
1982 consumeToken();
1984 // Check to see if this operation name is already registered.
1985 std::optional<RegisteredOperationName> opInfo =
1986 RegisteredOperationName::lookup(opName, getContext());
1987 if (opInfo)
1988 return *opInfo;
1990 // If the operation doesn't have a dialect prefix try using the default
1991 // dialect.
1992 auto opNameSplit = opName.split('.');
1993 StringRef dialectName = opNameSplit.first;
1994 std::string opNameStorage;
1995 if (opNameSplit.second.empty()) {
1996 // If the name didn't have a prefix, check for a code completion request.
1997 if (getToken().isCodeCompletion() && opName.back() == '.')
1998 return codeCompleteOperationName(dialectName);
2000 dialectName = getState().defaultDialectStack.back();
2001 opNameStorage = (dialectName + "." + opName).str();
2002 opName = opNameStorage;
2005 // Try to load the dialect before returning the operation name to make sure
2006 // the operation has a chance to be registered.
2007 getContext()->getOrLoadDialect(dialectName);
2008 return OperationName(opName, getContext());
2011 Operation *
2012 OperationParser::parseCustomOperation(ArrayRef<ResultRecord> resultIDs) {
2013 SMLoc opLoc = getToken().getLoc();
2014 StringRef originalOpName = getTokenSpelling();
2016 FailureOr<OperationName> opNameInfo = parseCustomOperationName();
2017 if (failed(opNameInfo))
2018 return nullptr;
2019 StringRef opName = opNameInfo->getStringRef();
2021 // This is the actual hook for the custom op parsing, usually implemented by
2022 // the op itself (`Op::parse()`). We retrieve it either from the
2023 // RegisteredOperationName or from the Dialect.
2024 OperationName::ParseAssemblyFn parseAssemblyFn;
2025 bool isIsolatedFromAbove = false;
2027 StringRef defaultDialect = "";
2028 if (auto opInfo = opNameInfo->getRegisteredInfo()) {
2029 parseAssemblyFn = opInfo->getParseAssemblyFn();
2030 isIsolatedFromAbove = opInfo->hasTrait<OpTrait::IsIsolatedFromAbove>();
2031 auto *iface = opInfo->getInterface<OpAsmOpInterface>();
2032 if (iface && !iface->getDefaultDialect().empty())
2033 defaultDialect = iface->getDefaultDialect();
2034 } else {
2035 std::optional<Dialect::ParseOpHook> dialectHook;
2036 Dialect *dialect = opNameInfo->getDialect();
2037 if (!dialect) {
2038 InFlightDiagnostic diag =
2039 emitError(opLoc) << "Dialect `" << opNameInfo->getDialectNamespace()
2040 << "' not found for custom op '" << originalOpName
2041 << "' ";
2042 if (originalOpName != opName)
2043 diag << " (tried '" << opName << "' as well)";
2044 auto &note = diag.attachNote();
2045 note << "Registered dialects: ";
2046 llvm::interleaveComma(getContext()->getAvailableDialects(), note,
2047 [&](StringRef dialect) { note << dialect; });
2048 note << " ; for more info on dialect registration see "
2049 "https://mlir.llvm.org/getting_started/Faq/"
2050 "#registered-loaded-dependent-whats-up-with-dialects-management";
2051 return nullptr;
2053 dialectHook = dialect->getParseOperationHook(opName);
2054 if (!dialectHook) {
2055 InFlightDiagnostic diag =
2056 emitError(opLoc) << "custom op '" << originalOpName << "' is unknown";
2057 if (originalOpName != opName)
2058 diag << " (tried '" << opName << "' as well)";
2059 return nullptr;
2061 parseAssemblyFn = *dialectHook;
2063 getState().defaultDialectStack.push_back(defaultDialect);
2064 auto restoreDefaultDialect = llvm::make_scope_exit(
2065 [&]() { getState().defaultDialectStack.pop_back(); });
2067 // If the custom op parser crashes, produce some indication to help
2068 // debugging.
2069 llvm::PrettyStackTraceFormat fmt("MLIR Parser: custom op parser '%s'",
2070 opNameInfo->getIdentifier().data());
2072 // Get location information for the operation.
2073 auto srcLocation = getEncodedSourceLocation(opLoc);
2074 OperationState opState(srcLocation, *opNameInfo);
2076 // If we are populating the parser state, start a new operation definition.
2077 if (state.asmState)
2078 state.asmState->startOperationDefinition(opState.name);
2080 // Have the op implementation take a crack and parsing this.
2081 CleanupOpStateRegions guard{opState};
2082 CustomOpAsmParser opAsmParser(opLoc, resultIDs, parseAssemblyFn,
2083 isIsolatedFromAbove, opName, *this);
2084 if (opAsmParser.parseOperation(opState))
2085 return nullptr;
2087 // If it emitted an error, we failed.
2088 if (opAsmParser.didEmitError())
2089 return nullptr;
2091 Attribute properties = opState.propertiesAttr;
2092 opState.propertiesAttr = Attribute{};
2094 // Otherwise, create the operation and try to parse a location for it.
2095 Operation *op = opBuilder.create(opState);
2096 if (parseTrailingLocationSpecifier(op))
2097 return nullptr;
2099 // Try setting the properties for the operation.
2100 if (properties) {
2101 auto emitError = [&]() {
2102 return mlir::emitError(srcLocation, "invalid properties ")
2103 << properties << " for op " << op->getName().getStringRef()
2104 << ": ";
2106 if (failed(op->setPropertiesFromAttribute(properties, emitError)))
2107 return nullptr;
2109 return op;
2112 ParseResult OperationParser::parseLocationAlias(LocationAttr &loc) {
2113 Token tok = getToken();
2114 consumeToken(Token::hash_identifier);
2115 StringRef identifier = tok.getSpelling().drop_front();
2116 assert(!identifier.contains('.') &&
2117 "unexpected dialect attribute token, expected alias");
2119 if (state.asmState)
2120 state.asmState->addAttrAliasUses(identifier, tok.getLocRange());
2122 // If this alias can be resolved, do it now.
2123 Attribute attr = state.symbols.attributeAliasDefinitions.lookup(identifier);
2124 if (attr) {
2125 if (!(loc = dyn_cast<LocationAttr>(attr)))
2126 return emitError(tok.getLoc())
2127 << "expected location, but found '" << attr << "'";
2128 } else {
2129 // Otherwise, remember this operation and resolve its location later.
2130 // In the meantime, use a special OpaqueLoc as a marker.
2131 loc = OpaqueLoc::get(deferredLocsReferences.size(),
2132 TypeID::get<DeferredLocInfo *>(),
2133 UnknownLoc::get(getContext()));
2134 deferredLocsReferences.push_back(DeferredLocInfo{tok.getLoc(), identifier});
2136 return success();
2139 ParseResult
2140 OperationParser::parseTrailingLocationSpecifier(OpOrArgument opOrArgument) {
2141 // If there is a 'loc' we parse a trailing location.
2142 if (!consumeIf(Token::kw_loc))
2143 return success();
2144 if (parseToken(Token::l_paren, "expected '(' in location"))
2145 return failure();
2146 Token tok = getToken();
2148 // Check to see if we are parsing a location alias. We are parsing a location
2149 // alias if the token is a hash identifier *without* a dot in it - the dot
2150 // signifies a dialect attribute. Otherwise, we parse the location directly.
2151 LocationAttr directLoc;
2152 if (tok.is(Token::hash_identifier) && !tok.getSpelling().contains('.')) {
2153 if (parseLocationAlias(directLoc))
2154 return failure();
2155 } else if (parseLocationInstance(directLoc)) {
2156 return failure();
2159 if (parseToken(Token::r_paren, "expected ')' in location"))
2160 return failure();
2162 if (auto *op = llvm::dyn_cast_if_present<Operation *>(opOrArgument))
2163 op->setLoc(directLoc);
2164 else
2165 opOrArgument.get<BlockArgument>().setLoc(directLoc);
2166 return success();
2169 //===----------------------------------------------------------------------===//
2170 // Region Parsing
2171 //===----------------------------------------------------------------------===//
2173 ParseResult OperationParser::parseRegion(Region &region,
2174 ArrayRef<Argument> entryArguments,
2175 bool isIsolatedNameScope) {
2176 // Parse the '{'.
2177 Token lBraceTok = getToken();
2178 if (parseToken(Token::l_brace, "expected '{' to begin a region"))
2179 return failure();
2181 // If we are populating the parser state, start a new region definition.
2182 if (state.asmState)
2183 state.asmState->startRegionDefinition();
2185 // Parse the region body.
2186 if ((!entryArguments.empty() || getToken().isNot(Token::r_brace)) &&
2187 parseRegionBody(region, lBraceTok.getLoc(), entryArguments,
2188 isIsolatedNameScope)) {
2189 return failure();
2191 consumeToken(Token::r_brace);
2193 // If we are populating the parser state, finalize this region.
2194 if (state.asmState)
2195 state.asmState->finalizeRegionDefinition();
2197 return success();
2200 ParseResult OperationParser::parseRegionBody(Region &region, SMLoc startLoc,
2201 ArrayRef<Argument> entryArguments,
2202 bool isIsolatedNameScope) {
2203 auto currentPt = opBuilder.saveInsertionPoint();
2205 // Push a new named value scope.
2206 pushSSANameScope(isIsolatedNameScope);
2208 // Parse the first block directly to allow for it to be unnamed.
2209 auto owningBlock = std::make_unique<Block>();
2210 Block *block = owningBlock.get();
2212 // If this block is not defined in the source file, add a definition for it
2213 // now in the assembly state. Blocks with a name will be defined when the name
2214 // is parsed.
2215 if (state.asmState && getToken().isNot(Token::caret_identifier))
2216 state.asmState->addDefinition(block, startLoc);
2218 // Add arguments to the entry block if we had the form with explicit names.
2219 if (!entryArguments.empty() && !entryArguments[0].ssaName.name.empty()) {
2220 // If we had named arguments, then don't allow a block name.
2221 if (getToken().is(Token::caret_identifier))
2222 return emitError("invalid block name in region with named arguments");
2224 for (auto &entryArg : entryArguments) {
2225 auto &argInfo = entryArg.ssaName;
2227 // Ensure that the argument was not already defined.
2228 if (auto defLoc = getReferenceLoc(argInfo.name, argInfo.number)) {
2229 return emitError(argInfo.location, "region entry argument '" +
2230 argInfo.name +
2231 "' is already in use")
2232 .attachNote(getEncodedSourceLocation(*defLoc))
2233 << "previously referenced here";
2235 Location loc = entryArg.sourceLoc.has_value()
2236 ? *entryArg.sourceLoc
2237 : getEncodedSourceLocation(argInfo.location);
2238 BlockArgument arg = block->addArgument(entryArg.type, loc);
2240 // Add a definition of this arg to the assembly state if provided.
2241 if (state.asmState)
2242 state.asmState->addDefinition(arg, argInfo.location);
2244 // Record the definition for this argument.
2245 if (addDefinition(argInfo, arg))
2246 return failure();
2250 if (parseBlock(block))
2251 return failure();
2253 // Verify that no other arguments were parsed.
2254 if (!entryArguments.empty() &&
2255 block->getNumArguments() > entryArguments.size()) {
2256 return emitError("entry block arguments were already defined");
2259 // Parse the rest of the region.
2260 region.push_back(owningBlock.release());
2261 while (getToken().isNot(Token::r_brace)) {
2262 Block *newBlock = nullptr;
2263 if (parseBlock(newBlock))
2264 return failure();
2265 region.push_back(newBlock);
2268 // Pop the SSA value scope for this region.
2269 if (popSSANameScope())
2270 return failure();
2272 // Reset the original insertion point.
2273 opBuilder.restoreInsertionPoint(currentPt);
2274 return success();
2277 //===----------------------------------------------------------------------===//
2278 // Block Parsing
2279 //===----------------------------------------------------------------------===//
2281 /// Block declaration.
2283 /// block ::= block-label? operation*
2284 /// block-label ::= block-id block-arg-list? `:`
2285 /// block-id ::= caret-id
2286 /// block-arg-list ::= `(` ssa-id-and-type-list? `)`
2288 ParseResult OperationParser::parseBlock(Block *&block) {
2289 // The first block of a region may already exist, if it does the caret
2290 // identifier is optional.
2291 if (block && getToken().isNot(Token::caret_identifier))
2292 return parseBlockBody(block);
2294 SMLoc nameLoc = getToken().getLoc();
2295 auto name = getTokenSpelling();
2296 if (parseToken(Token::caret_identifier, "expected block name"))
2297 return failure();
2299 // Define the block with the specified name.
2300 auto &blockAndLoc = getBlockInfoByName(name);
2301 blockAndLoc.loc = nameLoc;
2303 // Use a unique pointer for in-flight block being parsed. Release ownership
2304 // only in the case of a successful parse. This ensures that the Block
2305 // allocated is released if the parse fails and control returns early.
2306 std::unique_ptr<Block> inflightBlock;
2307 auto cleanupOnFailure = llvm::make_scope_exit([&] {
2308 if (inflightBlock)
2309 inflightBlock->dropAllDefinedValueUses();
2312 // If a block has yet to be set, this is a new definition. If the caller
2313 // provided a block, use it. Otherwise create a new one.
2314 if (!blockAndLoc.block) {
2315 if (block) {
2316 blockAndLoc.block = block;
2317 } else {
2318 inflightBlock = std::make_unique<Block>();
2319 blockAndLoc.block = inflightBlock.get();
2322 // Otherwise, the block has a forward declaration. Forward declarations are
2323 // removed once defined, so if we are defining a existing block and it is
2324 // not a forward declaration, then it is a redeclaration. Fail if the block
2325 // was already defined.
2326 } else if (!eraseForwardRef(blockAndLoc.block)) {
2327 return emitError(nameLoc, "redefinition of block '") << name << "'";
2328 } else {
2329 // This was a forward reference block that is now floating. Keep track of it
2330 // as inflight in case of error, so that it gets cleaned up properly.
2331 inflightBlock.reset(blockAndLoc.block);
2334 // Populate the high level assembly state if necessary.
2335 if (state.asmState)
2336 state.asmState->addDefinition(blockAndLoc.block, nameLoc);
2337 block = blockAndLoc.block;
2339 // If an argument list is present, parse it.
2340 if (getToken().is(Token::l_paren))
2341 if (parseOptionalBlockArgList(block))
2342 return failure();
2343 if (parseToken(Token::colon, "expected ':' after block name"))
2344 return failure();
2346 // Parse the body of the block.
2347 ParseResult res = parseBlockBody(block);
2349 // If parsing was successful, drop the inflight block. We relinquish ownership
2350 // back up to the caller.
2351 if (succeeded(res))
2352 (void)inflightBlock.release();
2353 return res;
2356 ParseResult OperationParser::parseBlockBody(Block *block) {
2357 // Set the insertion point to the end of the block to parse.
2358 opBuilder.setInsertionPointToEnd(block);
2360 // Parse the list of operations that make up the body of the block.
2361 while (getToken().isNot(Token::caret_identifier, Token::r_brace))
2362 if (parseOperation())
2363 return failure();
2365 return success();
2368 /// Get the block with the specified name, creating it if it doesn't already
2369 /// exist. The location specified is the point of use, which allows
2370 /// us to diagnose references to blocks that are not defined precisely.
2371 Block *OperationParser::getBlockNamed(StringRef name, SMLoc loc) {
2372 BlockDefinition &blockDef = getBlockInfoByName(name);
2373 if (!blockDef.block) {
2374 blockDef = {new Block(), loc};
2375 insertForwardRef(blockDef.block, blockDef.loc);
2378 // Populate the high level assembly state if necessary.
2379 if (state.asmState)
2380 state.asmState->addUses(blockDef.block, loc);
2382 return blockDef.block;
2385 /// Parse a (possibly empty) list of SSA operands with types as block arguments
2386 /// enclosed in parentheses.
2388 /// value-id-and-type-list ::= value-id-and-type (`,` ssa-id-and-type)*
2389 /// block-arg-list ::= `(` value-id-and-type-list? `)`
2391 ParseResult OperationParser::parseOptionalBlockArgList(Block *owner) {
2392 if (getToken().is(Token::r_brace))
2393 return success();
2395 // If the block already has arguments, then we're handling the entry block.
2396 // Parse and register the names for the arguments, but do not add them.
2397 bool definingExistingArgs = owner->getNumArguments() != 0;
2398 unsigned nextArgument = 0;
2400 return parseCommaSeparatedList(Delimiter::Paren, [&]() -> ParseResult {
2401 return parseSSADefOrUseAndType(
2402 [&](UnresolvedOperand useInfo, Type type) -> ParseResult {
2403 BlockArgument arg;
2405 // If we are defining existing arguments, ensure that the argument
2406 // has already been created with the right type.
2407 if (definingExistingArgs) {
2408 // Otherwise, ensure that this argument has already been created.
2409 if (nextArgument >= owner->getNumArguments())
2410 return emitError("too many arguments specified in argument list");
2412 // Finally, make sure the existing argument has the correct type.
2413 arg = owner->getArgument(nextArgument++);
2414 if (arg.getType() != type)
2415 return emitError("argument and block argument type mismatch");
2416 } else {
2417 auto loc = getEncodedSourceLocation(useInfo.location);
2418 arg = owner->addArgument(type, loc);
2421 // If the argument has an explicit loc(...) specifier, parse and apply
2422 // it.
2423 if (parseTrailingLocationSpecifier(arg))
2424 return failure();
2426 // Mark this block argument definition in the parser state if it was
2427 // provided.
2428 if (state.asmState)
2429 state.asmState->addDefinition(arg, useInfo.location);
2431 return addDefinition(useInfo, arg);
2436 //===----------------------------------------------------------------------===//
2437 // Code Completion
2438 //===----------------------------------------------------------------------===//
2440 ParseResult OperationParser::codeCompleteSSAUse() {
2441 for (IsolatedSSANameScope &scope : isolatedNameScopes) {
2442 for (auto &it : scope.values) {
2443 if (it.second.empty())
2444 continue;
2445 Value frontValue = it.second.front().value;
2447 std::string detailData;
2448 llvm::raw_string_ostream detailOS(detailData);
2450 // If the value isn't a forward reference, we also add the name of the op
2451 // to the detail.
2452 if (auto result = dyn_cast<OpResult>(frontValue)) {
2453 if (!forwardRefPlaceholders.count(result))
2454 detailOS << result.getOwner()->getName() << ": ";
2455 } else {
2456 detailOS << "arg #" << cast<BlockArgument>(frontValue).getArgNumber()
2457 << ": ";
2460 // Emit the type of the values to aid with completion selection.
2461 detailOS << frontValue.getType();
2463 // FIXME: We should define a policy for packed values, e.g. with a limit
2464 // on the detail size, but it isn't clear what would be useful right now.
2465 // For now we just only emit the first type.
2466 if (it.second.size() > 1)
2467 detailOS << ", ...";
2469 state.codeCompleteContext->appendSSAValueCompletion(
2470 it.getKey(), std::move(detailData));
2474 return failure();
2477 ParseResult OperationParser::codeCompleteBlock() {
2478 // Don't provide completions if the token isn't empty, e.g. this avoids
2479 // weirdness when we encounter a `.` within the identifier.
2480 StringRef spelling = getTokenSpelling();
2481 if (!(spelling.empty() || spelling == "^"))
2482 return failure();
2484 for (const auto &it : blocksByName.back())
2485 state.codeCompleteContext->appendBlockCompletion(it.getFirst());
2486 return failure();
2489 //===----------------------------------------------------------------------===//
2490 // Top-level entity parsing.
2491 //===----------------------------------------------------------------------===//
2493 namespace {
2494 /// This parser handles entities that are only valid at the top level of the
2495 /// file.
2496 class TopLevelOperationParser : public Parser {
2497 public:
2498 explicit TopLevelOperationParser(ParserState &state) : Parser(state) {}
2500 /// Parse a set of operations into the end of the given Block.
2501 ParseResult parse(Block *topLevelBlock, Location parserLoc);
2503 private:
2504 /// Parse an attribute alias declaration.
2506 /// attribute-alias-def ::= '#' alias-name `=` attribute-value
2508 ParseResult parseAttributeAliasDef();
2510 /// Parse a type alias declaration.
2512 /// type-alias-def ::= '!' alias-name `=` type
2514 ParseResult parseTypeAliasDef();
2516 /// Parse a top-level file metadata dictionary.
2518 /// file-metadata-dict ::= '{-#' file-metadata-entry* `#-}'
2520 ParseResult parseFileMetadataDictionary();
2522 /// Parse a resource metadata dictionary.
2523 ParseResult parseResourceFileMetadata(
2524 function_ref<ParseResult(StringRef, SMLoc)> parseBody);
2525 ParseResult parseDialectResourceFileMetadata();
2526 ParseResult parseExternalResourceFileMetadata();
2529 /// This class represents an implementation of a resource entry for the MLIR
2530 /// textual format.
2531 class ParsedResourceEntry : public AsmParsedResourceEntry {
2532 public:
2533 ParsedResourceEntry(StringRef key, SMLoc keyLoc, Token value, Parser &p)
2534 : key(key), keyLoc(keyLoc), value(value), p(p) {}
2535 ~ParsedResourceEntry() override = default;
2537 StringRef getKey() const final { return key; }
2539 InFlightDiagnostic emitError() const final { return p.emitError(keyLoc); }
2541 AsmResourceEntryKind getKind() const final {
2542 if (value.isAny(Token::kw_true, Token::kw_false))
2543 return AsmResourceEntryKind::Bool;
2544 return value.getSpelling().starts_with("\"0x")
2545 ? AsmResourceEntryKind::Blob
2546 : AsmResourceEntryKind::String;
2549 FailureOr<bool> parseAsBool() const final {
2550 if (value.is(Token::kw_true))
2551 return true;
2552 if (value.is(Token::kw_false))
2553 return false;
2554 return p.emitError(value.getLoc(),
2555 "expected 'true' or 'false' value for key '" + key +
2556 "'");
2559 FailureOr<std::string> parseAsString() const final {
2560 if (value.isNot(Token::string))
2561 return p.emitError(value.getLoc(),
2562 "expected string value for key '" + key + "'");
2563 return value.getStringValue();
2566 FailureOr<AsmResourceBlob>
2567 parseAsBlob(BlobAllocatorFn allocator) const final {
2568 // Blob data within then textual format is represented as a hex string.
2569 // TODO: We could avoid an additional alloc+copy here if we pre-allocated
2570 // the buffer to use during hex processing.
2571 std::optional<std::string> blobData =
2572 value.is(Token::string) ? value.getHexStringValue() : std::nullopt;
2573 if (!blobData)
2574 return p.emitError(value.getLoc(),
2575 "expected hex string blob for key '" + key + "'");
2577 // Extract the alignment of the blob data, which gets stored at the
2578 // beginning of the string.
2579 if (blobData->size() < sizeof(uint32_t)) {
2580 return p.emitError(value.getLoc(),
2581 "expected hex string blob for key '" + key +
2582 "' to encode alignment in first 4 bytes");
2584 llvm::support::ulittle32_t align;
2585 memcpy(&align, blobData->data(), sizeof(uint32_t));
2586 if (align && !llvm::isPowerOf2_32(align)) {
2587 return p.emitError(value.getLoc(),
2588 "expected hex string blob for key '" + key +
2589 "' to encode alignment in first 4 bytes, but got "
2590 "non-power-of-2 value: " +
2591 Twine(align));
2594 // Get the data portion of the blob.
2595 StringRef data = StringRef(*blobData).drop_front(sizeof(uint32_t));
2596 if (data.empty())
2597 return AsmResourceBlob();
2599 // Allocate memory for the blob using the provided allocator and copy the
2600 // data into it.
2601 AsmResourceBlob blob = allocator(data.size(), align);
2602 assert(llvm::isAddrAligned(llvm::Align(align), blob.getData().data()) &&
2603 blob.isMutable() &&
2604 "blob allocator did not return a properly aligned address");
2605 memcpy(blob.getMutableData().data(), data.data(), data.size());
2606 return blob;
2609 private:
2610 StringRef key;
2611 SMLoc keyLoc;
2612 Token value;
2613 Parser &p;
2615 } // namespace
2617 ParseResult TopLevelOperationParser::parseAttributeAliasDef() {
2618 assert(getToken().is(Token::hash_identifier));
2619 StringRef aliasName = getTokenSpelling().drop_front();
2621 // Check for redefinitions.
2622 if (state.symbols.attributeAliasDefinitions.count(aliasName) > 0)
2623 return emitError("redefinition of attribute alias id '" + aliasName + "'");
2625 // Make sure this isn't invading the dialect attribute namespace.
2626 if (aliasName.contains('.'))
2627 return emitError("attribute names with a '.' are reserved for "
2628 "dialect-defined names");
2630 SMRange location = getToken().getLocRange();
2631 consumeToken(Token::hash_identifier);
2633 // Parse the '='.
2634 if (parseToken(Token::equal, "expected '=' in attribute alias definition"))
2635 return failure();
2637 // Parse the attribute value.
2638 Attribute attr = parseAttribute();
2639 if (!attr)
2640 return failure();
2642 // Register this alias with the parser state.
2643 if (state.asmState)
2644 state.asmState->addAttrAliasDefinition(aliasName, location, attr);
2645 state.symbols.attributeAliasDefinitions[aliasName] = attr;
2646 return success();
2649 ParseResult TopLevelOperationParser::parseTypeAliasDef() {
2650 assert(getToken().is(Token::exclamation_identifier));
2651 StringRef aliasName = getTokenSpelling().drop_front();
2653 // Check for redefinitions.
2654 if (state.symbols.typeAliasDefinitions.count(aliasName) > 0)
2655 return emitError("redefinition of type alias id '" + aliasName + "'");
2657 // Make sure this isn't invading the dialect type namespace.
2658 if (aliasName.contains('.'))
2659 return emitError("type names with a '.' are reserved for "
2660 "dialect-defined names");
2662 SMRange location = getToken().getLocRange();
2663 consumeToken(Token::exclamation_identifier);
2665 // Parse the '='.
2666 if (parseToken(Token::equal, "expected '=' in type alias definition"))
2667 return failure();
2669 // Parse the type.
2670 Type aliasedType = parseType();
2671 if (!aliasedType)
2672 return failure();
2674 // Register this alias with the parser state.
2675 if (state.asmState)
2676 state.asmState->addTypeAliasDefinition(aliasName, location, aliasedType);
2677 state.symbols.typeAliasDefinitions.try_emplace(aliasName, aliasedType);
2678 return success();
2681 ParseResult TopLevelOperationParser::parseFileMetadataDictionary() {
2682 consumeToken(Token::file_metadata_begin);
2683 return parseCommaSeparatedListUntil(
2684 Token::file_metadata_end, [&]() -> ParseResult {
2685 // Parse the key of the metadata dictionary.
2686 SMLoc keyLoc = getToken().getLoc();
2687 StringRef key;
2688 if (failed(parseOptionalKeyword(&key)))
2689 return emitError("expected identifier key in file "
2690 "metadata dictionary");
2691 if (parseToken(Token::colon, "expected ':'"))
2692 return failure();
2694 // Process the metadata entry.
2695 if (key == "dialect_resources")
2696 return parseDialectResourceFileMetadata();
2697 if (key == "external_resources")
2698 return parseExternalResourceFileMetadata();
2699 return emitError(keyLoc, "unknown key '" + key +
2700 "' in file metadata dictionary");
2704 ParseResult TopLevelOperationParser::parseResourceFileMetadata(
2705 function_ref<ParseResult(StringRef, SMLoc)> parseBody) {
2706 if (parseToken(Token::l_brace, "expected '{'"))
2707 return failure();
2709 return parseCommaSeparatedListUntil(Token::r_brace, [&]() -> ParseResult {
2710 // Parse the top-level name entry.
2711 SMLoc nameLoc = getToken().getLoc();
2712 StringRef name;
2713 if (failed(parseOptionalKeyword(&name)))
2714 return emitError("expected identifier key for 'resource' entry");
2716 if (parseToken(Token::colon, "expected ':'") ||
2717 parseToken(Token::l_brace, "expected '{'"))
2718 return failure();
2719 return parseBody(name, nameLoc);
2723 ParseResult TopLevelOperationParser::parseDialectResourceFileMetadata() {
2724 return parseResourceFileMetadata([&](StringRef name,
2725 SMLoc nameLoc) -> ParseResult {
2726 // Lookup the dialect and check that it can handle a resource entry.
2727 Dialect *dialect = getContext()->getOrLoadDialect(name);
2728 if (!dialect)
2729 return emitError(nameLoc, "dialect '" + name + "' is unknown");
2730 const auto *handler = dyn_cast<OpAsmDialectInterface>(dialect);
2731 if (!handler) {
2732 return emitError() << "unexpected 'resource' section for dialect '"
2733 << dialect->getNamespace() << "'";
2736 return parseCommaSeparatedListUntil(Token::r_brace, [&]() -> ParseResult {
2737 // Parse the name of the resource entry.
2738 SMLoc keyLoc = getToken().getLoc();
2739 StringRef key;
2740 if (failed(parseResourceHandle(handler, key)) ||
2741 parseToken(Token::colon, "expected ':'"))
2742 return failure();
2743 Token valueTok = getToken();
2744 consumeToken();
2746 ParsedResourceEntry entry(key, keyLoc, valueTok, *this);
2747 return handler->parseResource(entry);
2752 ParseResult TopLevelOperationParser::parseExternalResourceFileMetadata() {
2753 return parseResourceFileMetadata([&](StringRef name,
2754 SMLoc nameLoc) -> ParseResult {
2755 AsmResourceParser *handler = state.config.getResourceParser(name);
2757 // TODO: Should we require handling external resources in some scenarios?
2758 if (!handler) {
2759 emitWarning(getEncodedSourceLocation(nameLoc))
2760 << "ignoring unknown external resources for '" << name << "'";
2763 return parseCommaSeparatedListUntil(Token::r_brace, [&]() -> ParseResult {
2764 // Parse the name of the resource entry.
2765 SMLoc keyLoc = getToken().getLoc();
2766 StringRef key;
2767 if (failed(parseOptionalKeyword(&key)))
2768 return emitError(
2769 "expected identifier key for 'external_resources' entry");
2770 if (parseToken(Token::colon, "expected ':'"))
2771 return failure();
2772 Token valueTok = getToken();
2773 consumeToken();
2775 if (!handler)
2776 return success();
2777 ParsedResourceEntry entry(key, keyLoc, valueTok, *this);
2778 return handler->parseResource(entry);
2783 ParseResult TopLevelOperationParser::parse(Block *topLevelBlock,
2784 Location parserLoc) {
2785 // Create a top-level operation to contain the parsed state.
2786 OwningOpRef<ModuleOp> topLevelOp(ModuleOp::create(parserLoc));
2787 OperationParser opParser(state, topLevelOp.get());
2788 while (true) {
2789 switch (getToken().getKind()) {
2790 default:
2791 // Parse a top-level operation.
2792 if (opParser.parseOperation())
2793 return failure();
2794 break;
2796 // If we got to the end of the file, then we're done.
2797 case Token::eof: {
2798 if (opParser.finalize())
2799 return failure();
2801 // Splice the blocks of the parsed operation over to the provided
2802 // top-level block.
2803 auto &parsedOps = topLevelOp->getBody()->getOperations();
2804 auto &destOps = topLevelBlock->getOperations();
2805 destOps.splice(destOps.end(), parsedOps, parsedOps.begin(),
2806 parsedOps.end());
2807 return success();
2810 // If we got an error token, then the lexer already emitted an error, just
2811 // stop. Someday we could introduce error recovery if there was demand
2812 // for it.
2813 case Token::error:
2814 return failure();
2816 // Parse an attribute alias.
2817 case Token::hash_identifier:
2818 if (parseAttributeAliasDef())
2819 return failure();
2820 break;
2822 // Parse a type alias.
2823 case Token::exclamation_identifier:
2824 if (parseTypeAliasDef())
2825 return failure();
2826 break;
2828 // Parse a file-level metadata dictionary.
2829 case Token::file_metadata_begin:
2830 if (parseFileMetadataDictionary())
2831 return failure();
2832 break;
2837 //===----------------------------------------------------------------------===//
2839 LogicalResult
2840 mlir::parseAsmSourceFile(const llvm::SourceMgr &sourceMgr, Block *block,
2841 const ParserConfig &config, AsmParserState *asmState,
2842 AsmParserCodeCompleteContext *codeCompleteContext) {
2843 const auto *sourceBuf = sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID());
2845 Location parserLoc =
2846 FileLineColLoc::get(config.getContext(), sourceBuf->getBufferIdentifier(),
2847 /*line=*/0, /*column=*/0);
2849 SymbolState aliasState;
2850 ParserState state(sourceMgr, config, aliasState, asmState,
2851 codeCompleteContext);
2852 return TopLevelOperationParser(state).parse(block, parserLoc);