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