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