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