Bug Summary

File:build/llvm-toolchain-snapshot-16~++20221003111214+1fa2019828ca/mlir/lib/AsmParser/Parser.cpp
Warning:line 1225, column 5
1st function call argument is an uninitialized value

Annotated Source Code

Press '?' to see keyboard shortcuts

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