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