Bug Summary

File:mlir/lib/Parser/Parser.cpp
Warning:line 1661, column 24
Although the value stored to 'dialect' is used in the enclosing expression, the value is never actually read from 'dialect'

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