Bug Summary

File:build/llvm-toolchain-snapshot-15~++20220224100907+19e37a7415b3/mlir/lib/Parser/Parser.cpp
Warning:line 1683, column 9
Value stored to 'dialect' is never read

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