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