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