1 //===- Parser.cpp - MLIR Parser Implementation ----------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements the parser for the MLIR textual form.
11 //===----------------------------------------------------------------------===//
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"
68 using namespace mlir::detail
;
70 //===----------------------------------------------------------------------===//
72 //===----------------------------------------------------------------------===//
74 AsmParserCodeCompleteContext::~AsmParserCodeCompleteContext() = default;
76 //===----------------------------------------------------------------------===//
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.
84 Parser::parseCommaSeparatedList(Delimiter delimiter
,
85 function_ref
<ParseResult()> parseElementFn
,
86 StringRef contextMessage
) {
90 case Delimiter::OptionalParen
:
91 if (getToken().isNot(Token::l_paren
))
94 case Delimiter::Paren
:
95 if (parseToken(Token::l_paren
, "expected '('" + contextMessage
))
97 // Check for empty list.
98 if (consumeIf(Token::r_paren
))
101 case Delimiter::OptionalLessGreater
:
102 // Check for absent list.
103 if (getToken().isNot(Token::less
))
106 case Delimiter::LessGreater
:
107 if (parseToken(Token::less
, "expected '<'" + contextMessage
))
109 // Check for empty list.
110 if (consumeIf(Token::greater
))
113 case Delimiter::OptionalSquare
:
114 if (getToken().isNot(Token::l_square
))
117 case Delimiter::Square
:
118 if (parseToken(Token::l_square
, "expected '['" + contextMessage
))
120 // Check for empty list.
121 if (consumeIf(Token::r_square
))
124 case Delimiter::OptionalBraces
:
125 if (getToken().isNot(Token::l_brace
))
128 case Delimiter::Braces
:
129 if (parseToken(Token::l_brace
, "expected '{'" + contextMessage
))
131 // Check for empty list.
132 if (consumeIf(Token::r_brace
))
137 // Non-empty case starts with an element.
138 if (parseElementFn())
141 // Otherwise we have a list of comma separated elements.
142 while (consumeIf(Token::comma
)) {
143 if (parseElementFn())
148 case Delimiter::None
:
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
173 Parser::parseCommaSeparatedListUntil(Token::Kind rightToken
,
174 function_ref
<ParseResult()> parseElement
,
175 bool allowEmptyList
) {
176 // Handle the empty case.
177 if (getToken().is(rightToken
)) {
179 return emitWrongTokenError("expected list element");
180 consumeToken(rightToken
);
184 if (parseCommaSeparatedList(parseElement
) ||
185 parseToken(rightToken
, "expected ',' or '" +
186 Token::getTokenSpelling(rightToken
) + "'"))
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
))
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.
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
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
))
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
)) {
281 if (consumeIf(Token::kw_true
)) {
286 Token curToken
= getToken();
287 if (curToken
.isNot(Token::integer
, Token::minus
))
290 bool negative
= consumeIf(Token::minus
);
291 Token curTok
= getToken();
292 if (parseToken(Token::integer
, "expected integer value"))
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.
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
)) {
318 bool negative
= consumeIf(Token::minus
);
319 Token curTok
= getToken();
320 if (parseToken(Token::integer
, "expected integer value")) {
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') {
331 state
.lex
.resetPointer(spelling
.data() + 1);
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.
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();
357 return emitError(tok
.getLoc()) << "floating point value too large";
359 result
.emplace(isNegative
? -*val
: *val
);
361 result
->convert(semantics
, APFloat::rmNearestTiesToEven
, &unused
);
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.
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';
380 return emitError(tok
.getLoc(), "unexpected decimal integer literal for a "
381 "floating point value")
383 << "add a trailing dot to make the literal a float";
386 return emitError(tok
.getLoc(),
387 "hexadecimal float literal should not have a "
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
);
405 ParseResult
Parser::parseOptionalKeyword(StringRef
*keyword
) {
406 // Check that the current token is a keyword.
407 if (!isCurrentTokenAKeyword())
410 *keyword
= getTokenSpelling();
415 //===----------------------------------------------------------------------===//
418 FailureOr
<AsmDialectResourceHandle
>
419 Parser::parseResourceHandle(const OpAsmDialectInterface
*dialect
,
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
;
447 FailureOr
<AsmDialectResourceHandle
>
448 Parser::parseResourceHandle(Dialect
*dialect
) {
449 const auto *interface
= dyn_cast
<OpAsmDialectInterface
>(dialect
);
451 return emitError() << "dialect '" << dialect
->getNamespace()
452 << "' does not expect resource handles";
454 StringRef resourceName
;
455 return parseResourceHandle(interface
, resourceName
);
458 //===----------------------------------------------------------------------===//
461 ParseResult
Parser::codeCompleteDialectName() {
462 state
.codeCompleteContext
->completeDialectName();
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('.'))
472 state
.codeCompleteContext
->completeOperationName(dialectName
);
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
))
489 if (shouldIgnoreOpCompletion())
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
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
);
512 ParseResult
Parser::codeCompleteExpectedTokens(ArrayRef
<StringRef
> tokens
) {
513 state
.codeCompleteContext
->completeExpectedTokens(tokens
, /*optional=*/false);
516 ParseResult
Parser::codeCompleteOptionalTokens(ArrayRef
<StringRef
> tokens
) {
517 state
.codeCompleteContext
->completeExpectedTokens(tokens
, /*optional=*/true);
521 Attribute
Parser::codeCompleteAttribute() {
522 state
.codeCompleteContext
->completeAttribute(
523 state
.symbols
.attributeAliasDefinitions
);
526 Type
Parser::codeCompleteType() {
527 state
.codeCompleteContext
->completeType(state
.symbols
.typeAliasDefinitions
);
532 Parser::codeCompleteDialectSymbol(const llvm::StringMap
<Attribute
> &aliases
) {
533 state
.codeCompleteContext
->completeDialectAttributeOrAlias(aliases
);
536 Type
Parser::codeCompleteDialectSymbol(const llvm::StringMap
<Type
> &aliases
) {
537 state
.codeCompleteContext
->completeDialectTypeOrAlias(aliases
);
541 //===----------------------------------------------------------------------===//
543 //===----------------------------------------------------------------------===//
546 /// This class provides support for parsing operations and regions of
548 class OperationParser
: public Parser
{
550 OperationParser(ParserState
&state
, ModuleOp topLevelOp
);
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
{
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'.
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())
602 if (values
[name
][number
].value
)
603 return values
[name
][number
].loc
;
607 //===--------------------------------------------------------------------===//
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
=
632 std::optional
<ArrayRef
<Block
*>> parsedSuccessors
= std::nullopt
,
633 std::optional
<MutableArrayRef
<std::unique_ptr
<Region
>>> parsedRegions
=
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
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 //===--------------------------------------------------------------------===//
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
®ion
, ArrayRef
<Argument
> entryArguments
,
682 bool isIsolatedNameScope
= false);
684 /// Parse a region body into 'region'.
685 ParseResult
parseRegionBody(Region
®ion
, SMLoc startLoc
,
686 ArrayRef
<Argument
> entryArguments
,
687 bool isIsolatedNameScope
);
689 //===--------------------------------------------------------------------===//
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 //===--------------------------------------------------------------------===//
709 //===--------------------------------------------------------------------===//
711 /// The set of various code completion methods. Every completion method
712 /// returns `failure` to stop the parsing process after providing completion
715 ParseResult
codeCompleteSSAUse();
716 ParseResult
codeCompleteBlock();
719 /// This class represents a definition of a Block.
720 struct BlockDefinition
{
721 /// A pointer to the defined Block.
723 /// The location that the Block was defined at.
726 /// This class represents a definition of a Value.
727 struct ValueDefinition
{
728 /// A pointer to the defined Value.
730 /// The location that the Value was defined at.
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
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.
810 /// The top level operation that holds all of the parsed operations.
811 Operation
*topLevelOp
;
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.
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();
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
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");
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
)
871 auto locInfo
= deferredLocsReferences
[fwdLoc
.getUnderlyingLocation()];
872 Attribute attr
= attributeAliases
.lookup(locInfo
.identifier
);
874 return this->emitError(locInfo
.loc
)
875 << "operation location alias was never defined";
876 auto locAttr
= dyn_cast
<LocationAttr
>(attr
);
878 return this->emitError(locInfo
.loc
)
879 << "expected location, but found '" << attr
<< "'";
880 opOrArgument
.setLoc(locAttr
);
884 auto walkRes
= topLevelOp
->walk([&](Operation
*op
) {
885 if (failed(resolveLocation(*op
)))
886 return WalkResult::interrupt();
887 for (Region
®ion
: op
->getRegions())
888 for (Block
&block
: region
.getBlocks())
889 for (BlockArgument arg
: block
.getArguments())
890 if (failed(resolveLocation(arg
)))
891 return WalkResult::interrupt();
892 return WalkResult::advance();
894 if (walkRes
.wasInterrupted())
897 // Pop the top level name scope.
898 if (failed(popSSANameScope()))
901 // Verify that the parsed operations are valid.
902 if (state
.config
.shouldVerifyAfterParse() && failed(verify(topLevelOp
)))
905 // If we are populating the parser state, finalize the top-level operation.
907 state
.asmState
->finalize(topLevelOp
);
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.
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");
946 // Pop the next nested namescope. If there is only one internal namescope,
947 // just pop the isolated scope.
948 auto ¤tNameScope
= isolatedNameScopes
.back();
949 if (currentNameScope
.definitionsPerScope
.size() == 1)
950 isolatedNameScopes
.pop_back();
952 currentNameScope
.popSSANameScope();
954 blocksByName
.pop_back();
958 /// Register a definition of a value with the symbol table.
959 ParseResult
OperationParser::addDefinition(UnresolvedOperand useInfo
,
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
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
);
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
))
1013 return parseCommaSeparatedList([&]() -> ParseResult
{
1014 UnresolvedOperand result
;
1015 if (parseSSAUse(result
))
1017 results
.push_back(result
);
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();
1033 result
.location
= getToken().getLoc();
1034 if (parseToken(Token::percent_identifier
, "expected SSA operand"))
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
;
1045 return emitError("invalid SSA value result number");
1046 consumeToken(Token::hash_identifier
);
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
) {
1061 state
.asmState
->addUses(value
, useInfo
.location
);
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 ",
1076 .attachNote(getEncodedSourceLocation(entries
[useInfo
.number
].loc
))
1077 .append("prior use here");
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"),
1091 // Otherwise, this is a forward reference. Create a placeholder and remember
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"))
1108 auto type
= parseType();
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
))
1127 // If there were no operands, then there is no colon or type lists.
1128 if (valueIDs
.empty())
1131 SmallVector
<Type
, 4> types
;
1132 if (parseToken(Token::colon
, "expected ':' in operand list") ||
1133 parseTypeListNoParens(types
))
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
);
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
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=*/{},
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"))
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)
1219 "expected named operation to have at least 1 result");
1220 consumeToken(Token::integer
);
1221 expectedSubResults
= *val
;
1224 resultIDs
.emplace_back(nameTok
.getSpelling(), expectedSubResults
,
1226 numExpectedResults
+= expectedSubResults
;
1229 if (parseCommaSeparatedList(parseNextResult
))
1232 if (parseToken(Token::equal
, "expected '=' after SSA name"))
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
);
1247 return emitWrongTokenError("expected operation name in quotes");
1249 // If parsing of the basic operation failed, then this whole thing fails.
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(),
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
++)))
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());
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());
1312 /// Parse a comma-separated list of operation successors in brackets.
1314 /// successor-list ::= `[` successor (`,` successor )* `]`
1317 OperationParser::parseSuccessors(SmallVectorImpl
<Block
*> &destinations
) {
1318 if (parseToken(Token::l_square
, "expected '['"))
1321 auto parseElt
= [this, &destinations
] {
1323 ParseResult res
= parseSuccessor(dest
);
1324 destinations
.push_back(dest
);
1327 return parseCommaSeparatedListUntil(Token::r_square
, parseElt
,
1328 /*allowEmptyList=*/false);
1332 // RAII-style guard for cleaning up the regions in the operation state before
1333 // deleting them. Within the parser, regions may get deleted if parsing failed,
1334 // and other errors may be present, in particular undominated uses. This makes
1335 // sure such uses are deleted.
1336 struct CleanupOpStateRegions
{
1337 ~CleanupOpStateRegions() {
1338 SmallVector
<Region
*, 4> regionsToClean
;
1339 regionsToClean
.reserve(state
.regions
.size());
1340 for (auto ®ion
: state
.regions
)
1342 for (auto &block
: *region
)
1343 block
.dropAllDefinedValueUses();
1345 OperationState
&state
;
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")) {
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
))
1379 result
.addSuccessors(successors
);
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
)
1392 if (parseToken(Token::greater
, "expected '>' to close properties"))
1395 // Parse the region list, if not explicitly provided.
1396 if (!parsedRegions
) {
1397 if (consumeIf(Token::l_paren
)) {
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=*/{}))
1403 } while (consumeIf(Token::comma
));
1404 if (parseToken(Token::r_paren
, "expected ')' to end region list"))
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
))
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"))
1427 typeLoc
= getEncodedSourceLocation(getToken().getLoc());
1428 auto type
= parseType();
1431 auto fnType
= dyn_cast
<FunctionType
>(type
);
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())
1460 Operation
*OperationParser::parseGenericOperation() {
1461 // Get location information for the operation.
1462 auto srcLocation
= getEncodedSourceLocation(getToken().getLoc());
1464 std::string name
= getToken().getStringValue();
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");
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.
1496 state
.asmState
->startOperationDefinition(result
.name
);
1498 if (parseGenericOperationAfterOpName(result
))
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();
1525 if (failed(info
->verifyInherentAttrs(result
.attributes
, [&]() {
1526 return mlir::emitError(srcLocation
) << "'" << name
<< "' op ";
1532 // Create the operation and try to parse a location for it.
1533 Operation
*op
= opBuilder
.create(result
);
1534 if (parseTrailingLocationSpecifier(op
))
1537 // Try setting the properties for the operation, using a diagnostic to print
1540 auto emitError
= [&]() {
1541 return mlir::emitError(srcLocation
, "invalid properties ")
1542 << properties
<< " for op " << name
<< ": ";
1544 if (failed(op
->setPropertiesFromAttribute(properties
, emitError
)))
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();
1561 // If we are populating the parser asm state, finalize this operation
1564 state
.asmState
->finalizeOperationDefinition(
1565 op
, nameToken
.getLocRange(),
1566 /*endLoc=*/getLastToken().getEndLoc());
1571 class CustomOpAsmParser
: public AsmParserImpl
<OpAsmParser
> {
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
))
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();
1595 return emitError(getNameLoc(), "attribute '")
1596 << duplicate
->getName().getValue()
1597 << "' occurs more than once in the attribute list";
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 //===--------------------------------------------------------------------===//
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.
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
{
1655 for (auto &entry
: resultIDs
)
1656 count
+= std::get
<1>(entry
);
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
+
1666 //===--------------------------------------------------------------------===//
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
))
1677 result
= {useInfo
.location
, useInfo
.name
, useInfo
.number
};
1681 /// Parse a single operand if present.
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)
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"))
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";
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
);
1740 /// Parse an AffineMap of SSA ids.
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
))
1753 symOperands
.push_back(operand
);
1755 dimOperands
.push_back(operand
);
1760 if (parser
.parseAffineMapOfSSAIds(map
, parseElement
, delimiter
))
1762 // Add AffineMap attribute.
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());
1774 /// Parse an AffineExpr of SSA ids.
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
))
1784 symbOperands
.push_back(operand
);
1786 dimOperands
.push_back(operand
);
1790 return parser
.parseAffineExprOfSSAIds(expr
, parseElement
);
1793 //===--------------------------------------------------------------------===//
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
))
1811 result
.attrs
= attrs
.getDictionary(getContext());
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
))
1831 auto parseOneArgument
= [&]() -> ParseResult
{
1832 return parseArgument(result
.emplace_back(), allowType
, allowAttrs
);
1834 return parseCommaSeparatedList(delimiter
, parseOneArgument
,
1835 " in argument list");
1838 //===--------------------------------------------------------------------===//
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
®ion
, ArrayRef
<Argument
> arguments
,
1845 bool enableNameShadowing
) override
{
1846 // Try to parse the region.
1847 (void)isIsolatedFromAbove
;
1848 assert((!enableNameShadowing
|| isIsolatedFromAbove
) &&
1849 "name shadowing is only allowed on isolated regions");
1850 if (parser
.parseRegion(region
, arguments
, enableNameShadowing
))
1855 /// Parses a region if present.
1856 OptionalParseResult
parseOptionalRegion(Region
®ion
,
1857 ArrayRef
<Argument
> arguments
,
1858 bool enableNameShadowing
) override
{
1859 if (parser
.getToken().isNot(Token::l_brace
))
1860 return std::nullopt
;
1861 return parseRegion(region
, arguments
, enableNameShadowing
);
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.
1868 parseOptionalRegion(std::unique_ptr
<Region
> ®ion
,
1869 ArrayRef
<Argument
> arguments
,
1870 bool enableNameShadowing
= false) override
{
1871 if (parser
.getToken().isNot(Token::l_brace
))
1872 return std::nullopt
;
1873 std::unique_ptr
<Region
> newRegion
= std::make_unique
<Region
>();
1874 if (parseRegion(*newRegion
, arguments
, enableNameShadowing
))
1877 region
= std::move(newRegion
);
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.
1899 parseSuccessorAndUseList(Block
*&dest
,
1900 SmallVectorImpl
<Value
> &operands
) override
{
1901 if (parseSuccessor(dest
))
1904 // Handle optional arguments.
1905 if (succeeded(parseOptionalLParen()) &&
1906 (parser
.parseOptionalSSAUseAndTypeList(operands
) || parseRParen())) {
1912 //===--------------------------------------------------------------------===//
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()))
1930 return parser
.parseCommaSeparatedListUntil(Token::r_paren
, parseElt
);
1933 /// Parse a loc(...) specifier if present, filling in result if so.
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
))
1939 LocationAttr directLoc
;
1940 if (parser
.parseToken(Token::l_paren
, "expected '(' in location"))
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
1949 if (tok
.is(Token::hash_identifier
) && !tok
.getSpelling().contains('.')) {
1950 if (parser
.parseLocationAlias(directLoc
))
1952 } else if (parser
.parseLocationInstance(directLoc
)) {
1956 if (parser
.parseToken(Token::r_paren
, "expected ')' in location"))
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
;
1972 /// The backing operation parser.
1973 OperationParser
&parser
;
1977 FailureOr
<OperationName
> OperationParser::parseCustomOperationName() {
1978 Token nameTok
= getToken();
1979 StringRef opName
= nameTok
.getSpelling();
1981 return (emitError("empty operation name is invalid"), failure());
1984 // Check to see if this operation name is already registered.
1985 std::optional
<RegisteredOperationName
> opInfo
=
1986 RegisteredOperationName::lookup(opName
, getContext());
1990 // If the operation doesn't have a dialect prefix try using the default
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());
2012 OperationParser::parseCustomOperation(ArrayRef
<ResultRecord
> resultIDs
) {
2013 SMLoc opLoc
= getToken().getLoc();
2014 StringRef originalOpName
= getTokenSpelling();
2016 FailureOr
<OperationName
> opNameInfo
= parseCustomOperationName();
2017 if (failed(opNameInfo
))
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();
2035 std::optional
<Dialect::ParseOpHook
> dialectHook
;
2036 Dialect
*dialect
= opNameInfo
->getDialect();
2038 InFlightDiagnostic diag
=
2039 emitError(opLoc
) << "Dialect `" << opNameInfo
->getDialectNamespace()
2040 << "' not found for custom op '" << originalOpName
2042 if (originalOpName
!= opName
)
2043 diag
<< " (tried '" << opName
<< "' as well)";
2044 auto ¬e
= diag
.attachNote();
2045 note
<< "Registered dialects: ";
2046 llvm::interleaveComma(getContext()->getAvailableDialects(), note
,
2047 [&](StringRef dialect
) { note
<< dialect
; });
2048 note
<< " ; for more info on dialect registration see "
2049 "https://mlir.llvm.org/getting_started/Faq/"
2050 "#registered-loaded-dependent-whats-up-with-dialects-management";
2053 dialectHook
= dialect
->getParseOperationHook(opName
);
2055 InFlightDiagnostic diag
=
2056 emitError(opLoc
) << "custom op '" << originalOpName
<< "' is unknown";
2057 if (originalOpName
!= opName
)
2058 diag
<< " (tried '" << opName
<< "' as well)";
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
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.
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
))
2087 // If it emitted an error, we failed.
2088 if (opAsmParser
.didEmitError())
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
))
2099 // Try setting the properties for the operation.
2101 auto emitError
= [&]() {
2102 return mlir::emitError(srcLocation
, "invalid properties ")
2103 << properties
<< " for op " << op
->getName().getStringRef()
2106 if (failed(op
->setPropertiesFromAttribute(properties
, emitError
)))
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");
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
);
2125 if (!(loc
= dyn_cast
<LocationAttr
>(attr
)))
2126 return emitError(tok
.getLoc())
2127 << "expected location, but found '" << attr
<< "'";
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
});
2140 OperationParser::parseTrailingLocationSpecifier(OpOrArgument opOrArgument
) {
2141 // If there is a 'loc' we parse a trailing location.
2142 if (!consumeIf(Token::kw_loc
))
2144 if (parseToken(Token::l_paren
, "expected '(' in location"))
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
))
2155 } else if (parseLocationInstance(directLoc
)) {
2159 if (parseToken(Token::r_paren
, "expected ')' in location"))
2162 if (auto *op
= llvm::dyn_cast_if_present
<Operation
*>(opOrArgument
))
2163 op
->setLoc(directLoc
);
2165 opOrArgument
.get
<BlockArgument
>().setLoc(directLoc
);
2169 //===----------------------------------------------------------------------===//
2171 //===----------------------------------------------------------------------===//
2173 ParseResult
OperationParser::parseRegion(Region
®ion
,
2174 ArrayRef
<Argument
> entryArguments
,
2175 bool isIsolatedNameScope
) {
2177 Token lBraceTok
= getToken();
2178 if (parseToken(Token::l_brace
, "expected '{' to begin a region"))
2181 // If we are populating the parser state, start a new region definition.
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
)) {
2191 consumeToken(Token::r_brace
);
2193 // If we are populating the parser state, finalize this region.
2195 state
.asmState
->finalizeRegionDefinition();
2200 ParseResult
OperationParser::parseRegionBody(Region
®ion
, 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
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 '" +
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.
2242 state
.asmState
->addDefinition(arg
, argInfo
.location
);
2244 // Record the definition for this argument.
2245 if (addDefinition(argInfo
, arg
))
2250 if (parseBlock(block
))
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
))
2265 region
.push_back(newBlock
);
2268 // Pop the SSA value scope for this region.
2269 if (popSSANameScope())
2272 // Reset the original insertion point.
2273 opBuilder
.restoreInsertionPoint(currentPt
);
2277 //===----------------------------------------------------------------------===//
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"))
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([&] {
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
) {
2316 blockAndLoc
.block
= block
;
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
<< "'";
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.
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
))
2343 if (parseToken(Token::colon
, "expected ':' after block name"))
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.
2352 (void)inflightBlock
.release();
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())
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.
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
))
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
{
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");
2417 auto loc
= getEncodedSourceLocation(useInfo
.location
);
2418 arg
= owner
->addArgument(type
, loc
);
2421 // If the argument has an explicit loc(...) specifier, parse and apply
2423 if (parseTrailingLocationSpecifier(arg
))
2426 // Mark this block argument definition in the parser state if it was
2429 state
.asmState
->addDefinition(arg
, useInfo
.location
);
2431 return addDefinition(useInfo
, arg
);
2436 //===----------------------------------------------------------------------===//
2438 //===----------------------------------------------------------------------===//
2440 ParseResult
OperationParser::codeCompleteSSAUse() {
2441 for (IsolatedSSANameScope
&scope
: isolatedNameScopes
) {
2442 for (auto &it
: scope
.values
) {
2443 if (it
.second
.empty())
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
2452 if (auto result
= dyn_cast
<OpResult
>(frontValue
)) {
2453 if (!forwardRefPlaceholders
.count(result
))
2454 detailOS
<< result
.getOwner()->getName() << ": ";
2456 detailOS
<< "arg #" << cast
<BlockArgument
>(frontValue
).getArgNumber()
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
));
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
== "^"))
2484 for (const auto &it
: blocksByName
.back())
2485 state
.codeCompleteContext
->appendBlockCompletion(it
.getFirst());
2489 //===----------------------------------------------------------------------===//
2490 // Top-level entity parsing.
2491 //===----------------------------------------------------------------------===//
2494 /// This parser handles entities that are only valid at the top level of the
2496 class TopLevelOperationParser
: public Parser
{
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
);
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
2531 class ParsedResourceEntry
: public AsmParsedResourceEntry
{
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
))
2552 if (value
.is(Token::kw_false
))
2554 return p
.emitError(value
.getLoc(),
2555 "expected 'true' or 'false' value for key '" + key
+
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
;
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: " +
2594 // Get the data portion of the blob.
2595 StringRef data
= StringRef(*blobData
).drop_front(sizeof(uint32_t));
2597 return AsmResourceBlob();
2599 // Allocate memory for the blob using the provided allocator and copy the
2601 AsmResourceBlob blob
= allocator(data
.size(), align
);
2602 assert(llvm::isAddrAligned(llvm::Align(align
), blob
.getData().data()) &&
2604 "blob allocator did not return a properly aligned address");
2605 memcpy(blob
.getMutableData().data(), data
.data(), data
.size());
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
);
2634 if (parseToken(Token::equal
, "expected '=' in attribute alias definition"))
2637 // Parse the attribute value.
2638 Attribute attr
= parseAttribute();
2642 // Register this alias with the parser state.
2644 state
.asmState
->addAttrAliasDefinition(aliasName
, location
, attr
);
2645 state
.symbols
.attributeAliasDefinitions
[aliasName
] = attr
;
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
);
2666 if (parseToken(Token::equal
, "expected '=' in type alias definition"))
2670 Type aliasedType
= parseType();
2674 // Register this alias with the parser state.
2676 state
.asmState
->addTypeAliasDefinition(aliasName
, location
, aliasedType
);
2677 state
.symbols
.typeAliasDefinitions
.try_emplace(aliasName
, aliasedType
);
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();
2688 if (failed(parseOptionalKeyword(&key
)))
2689 return emitError("expected identifier key in file "
2690 "metadata dictionary");
2691 if (parseToken(Token::colon
, "expected ':'"))
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 '{'"))
2709 return parseCommaSeparatedListUntil(Token::r_brace
, [&]() -> ParseResult
{
2710 // Parse the top-level name entry.
2711 SMLoc nameLoc
= getToken().getLoc();
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 '{'"))
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
);
2729 return emitError(nameLoc
, "dialect '" + name
+ "' is unknown");
2730 const auto *handler
= dyn_cast
<OpAsmDialectInterface
>(dialect
);
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();
2740 if (failed(parseResourceHandle(handler
, key
)) ||
2741 parseToken(Token::colon
, "expected ':'"))
2743 Token valueTok
= getToken();
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?
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();
2767 if (failed(parseOptionalKeyword(&key
)))
2769 "expected identifier key for 'external_resources' entry");
2770 if (parseToken(Token::colon
, "expected ':'"))
2772 Token valueTok
= getToken();
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());
2789 switch (getToken().getKind()) {
2791 // Parse a top-level operation.
2792 if (opParser
.parseOperation())
2796 // If we got to the end of the file, then we're done.
2798 if (opParser
.finalize())
2801 // Splice the blocks of the parsed operation over to the provided
2803 auto &parsedOps
= topLevelOp
->getBody()->getOperations();
2804 auto &destOps
= topLevelBlock
->getOperations();
2805 destOps
.splice(destOps
.end(), parsedOps
, parsedOps
.begin(),
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
2816 // Parse an attribute alias.
2817 case Token::hash_identifier
:
2818 if (parseAttributeAliasDef())
2822 // Parse a type alias.
2823 case Token::exclamation_identifier
:
2824 if (parseTypeAliasDef())
2828 // Parse a file-level metadata dictionary.
2829 case Token::file_metadata_begin
:
2830 if (parseFileMetadataDictionary())
2837 //===----------------------------------------------------------------------===//
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
);