blob: ae87ad23dcb310e3a63f356c04bcc399f4cb8dd3 [file] [log] [blame]
Chris Lattnere79379a2018-06-22 10:39:19 -07001//===- Parser.cpp - MLIR Parser Implementation ----------------------------===//
2//
3// Copyright 2019 The MLIR Authors.
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16// =============================================================================
17//
18// This file implements the parser for the MLIR textual form.
19//
20//===----------------------------------------------------------------------===//
21
22#include "mlir/Parser.h"
23#include "Lexer.h"
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -070024#include "mlir/IR/AffineExpr.h"
MLIR Teamf85a6262018-06-27 11:03:08 -070025#include "mlir/IR/AffineMap.h"
Chris Lattner7121b802018-07-04 20:45:39 -070026#include "mlir/IR/Attributes.h"
Chris Lattner158e0a3e2018-07-08 20:51:38 -070027#include "mlir/IR/Builders.h"
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -070028#include "mlir/IR/MLFunction.h"
Chris Lattner21e67f62018-07-06 10:46:19 -070029#include "mlir/IR/Module.h"
Chris Lattner85ee1512018-07-25 11:15:20 -070030#include "mlir/IR/OpImplementation.h"
Chris Lattner21e67f62018-07-06 10:46:19 -070031#include "mlir/IR/OperationSet.h"
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -070032#include "mlir/IR/Statements.h"
Chris Lattnerf7e22732018-06-22 22:03:48 -070033#include "mlir/IR/Types.h"
James Molloyf0d2f442018-08-03 01:54:46 -070034#include "llvm/ADT/DenseMap.h"
35#include "llvm/Support/SourceMgr.h"
Chris Lattnere79379a2018-06-22 10:39:19 -070036using namespace mlir;
Chris Lattner4c95a502018-06-23 16:03:42 -070037using llvm::SMLoc;
James Molloy0ff71542018-07-23 16:56:32 -070038using llvm::SourceMgr;
Chris Lattnere79379a2018-06-22 10:39:19 -070039
Chris Lattnerf7e22732018-06-22 22:03:48 -070040/// Simple enum to make code read better in cases that would otherwise return a
41/// bool value. Failure is "true" in a boolean context.
James Molloy0ff71542018-07-23 16:56:32 -070042enum ParseResult { ParseSuccess, ParseFailure };
Chris Lattnere79379a2018-06-22 10:39:19 -070043
Chris Lattner48af7d12018-07-09 19:05:38 -070044namespace {
45class Parser;
46
47/// This class refers to all of the state maintained globally by the parser,
48/// such as the current lexer position etc. The Parser base class provides
49/// methods to access this.
50class ParserState {
Chris Lattnered65a732018-06-28 20:45:33 -070051public:
Chris Lattner2e595eb2018-07-10 10:08:27 -070052 ParserState(llvm::SourceMgr &sourceMgr, Module *module,
Chris Lattner48af7d12018-07-09 19:05:38 -070053 SMDiagnosticHandlerTy errorReporter)
Chris Lattner2e595eb2018-07-10 10:08:27 -070054 : context(module->getContext()), module(module),
55 lex(sourceMgr, errorReporter), curToken(lex.lexToken()),
Chris Lattner85ee1512018-07-25 11:15:20 -070056 errorReporter(errorReporter), operationSet(OperationSet::get(context)) {
57 }
Chris Lattner2e595eb2018-07-10 10:08:27 -070058
59 // A map from affine map identifier to AffineMap.
60 llvm::StringMap<AffineMap *> affineMapDefinitions;
Uday Bondhugulabc535622018-08-07 14:24:38 -070061 // A map from integer set identifier to IntegerSet.
62 llvm::StringMap<IntegerSet *> integerSetDefinitions;
Chris Lattnere79379a2018-06-22 10:39:19 -070063
Chris Lattnere79379a2018-06-22 10:39:19 -070064private:
Chris Lattner48af7d12018-07-09 19:05:38 -070065 ParserState(const ParserState &) = delete;
66 void operator=(const ParserState &) = delete;
67
68 friend class Parser;
69
70 // The context we're parsing into.
Chris Lattner2e595eb2018-07-10 10:08:27 -070071 MLIRContext *const context;
72
73 // This is the module we are parsing into.
74 Module *const module;
Chris Lattnerf7e22732018-06-22 22:03:48 -070075
76 // The lexer for the source file we're parsing.
Chris Lattnere79379a2018-06-22 10:39:19 -070077 Lexer lex;
78
79 // This is the next token that hasn't been consumed yet.
80 Token curToken;
81
Jacques Pienaar9c411be2018-06-24 19:17:35 -070082 // The diagnostic error reporter.
Chris Lattner2e595eb2018-07-10 10:08:27 -070083 SMDiagnosticHandlerTy const errorReporter;
Chris Lattner85ee1512018-07-25 11:15:20 -070084
85 // The active OperationSet we're parsing with.
86 OperationSet &operationSet;
Chris Lattner48af7d12018-07-09 19:05:38 -070087};
88} // end anonymous namespace
MLIR Teamf85a6262018-06-27 11:03:08 -070089
Chris Lattner48af7d12018-07-09 19:05:38 -070090namespace {
91
Chris Lattner992a1272018-08-07 12:02:37 -070092typedef std::function<Operation *(const OperationState &)>
Tatiana Shpeisman565b9642018-07-16 11:47:09 -070093 CreateOperationFunction;
94
Chris Lattner48af7d12018-07-09 19:05:38 -070095/// This class implement support for parsing global entities like types and
96/// shared entities like SSA names. It is intended to be subclassed by
97/// specialized subparsers that include state, e.g. when a local symbol table.
98class Parser {
99public:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700100 Builder builder;
Chris Lattner48af7d12018-07-09 19:05:38 -0700101
Chris Lattner2e595eb2018-07-10 10:08:27 -0700102 Parser(ParserState &state) : builder(state.context), state(state) {}
103
104 // Helper methods to get stuff from the parser-global state.
105 ParserState &getState() const { return state; }
Chris Lattner48af7d12018-07-09 19:05:38 -0700106 MLIRContext *getContext() const { return state.context; }
Chris Lattner2e595eb2018-07-10 10:08:27 -0700107 Module *getModule() { return state.module; }
Chris Lattner85ee1512018-07-25 11:15:20 -0700108 OperationSet &getOperationSet() const { return state.operationSet; }
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700109 llvm::SourceMgr &getSourceMgr() { return state.lex.getSourceMgr(); }
Chris Lattner48af7d12018-07-09 19:05:38 -0700110
111 /// Return the current token the parser is inspecting.
112 const Token &getToken() const { return state.curToken; }
113 StringRef getTokenSpelling() const { return state.curToken.getSpelling(); }
Chris Lattnere79379a2018-06-22 10:39:19 -0700114
115 /// Emit an error and return failure.
Chris Lattner4c95a502018-06-23 16:03:42 -0700116 ParseResult emitError(const Twine &message) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700117 return emitError(state.curToken.getLoc(), message);
Chris Lattner4c95a502018-06-23 16:03:42 -0700118 }
119 ParseResult emitError(SMLoc loc, const Twine &message);
Chris Lattnere79379a2018-06-22 10:39:19 -0700120
121 /// Advance the current lexer onto the next token.
122 void consumeToken() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700123 assert(state.curToken.isNot(Token::eof, Token::error) &&
Chris Lattnere79379a2018-06-22 10:39:19 -0700124 "shouldn't advance past EOF or errors");
Chris Lattner48af7d12018-07-09 19:05:38 -0700125 state.curToken = state.lex.lexToken();
Chris Lattnere79379a2018-06-22 10:39:19 -0700126 }
127
128 /// Advance the current lexer onto the next token, asserting what the expected
129 /// current token is. This is preferred to the above method because it leads
130 /// to more self-documenting code with better checking.
Chris Lattner8da0c282018-06-29 11:15:56 -0700131 void consumeToken(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700132 assert(state.curToken.is(kind) && "consumed an unexpected token");
Chris Lattnere79379a2018-06-22 10:39:19 -0700133 consumeToken();
134 }
135
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700136 /// If the current token has the specified kind, consume it and return true.
137 /// If not, return false.
Chris Lattner8da0c282018-06-29 11:15:56 -0700138 bool consumeIf(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700139 if (state.curToken.isNot(kind))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700140 return false;
141 consumeToken(kind);
142 return true;
143 }
144
Chris Lattnerf7702a62018-07-23 17:30:01 -0700145 /// Consume the specified token if present and return success. On failure,
146 /// output a diagnostic and return failure.
147 ParseResult parseToken(Token::Kind expectedToken, const Twine &message);
148
Chris Lattner40746442018-07-21 14:32:09 -0700149 /// Parse a comma-separated list of elements up until the specified end token.
150 ParseResult
151 parseCommaSeparatedListUntil(Token::Kind rightToken,
152 const std::function<ParseResult()> &parseElement,
153 bool allowEmptyList = true);
154
155 /// Parse a comma separated list of elements that must have at least one entry
156 /// in it.
157 ParseResult
158 parseCommaSeparatedList(const std::function<ParseResult()> &parseElement);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700159
Chris Lattnerf7e22732018-06-22 22:03:48 -0700160 // We have two forms of parsing methods - those that return a non-null
161 // pointer on success, and those that return a ParseResult to indicate whether
162 // they returned a failure. The second class fills in by-reference arguments
163 // as the results of their action.
164
Chris Lattnere79379a2018-06-22 10:39:19 -0700165 // Type parsing.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700166 VectorType *parseVectorType();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700167 ParseResult parseDimensionListRanked(SmallVectorImpl<int> &dimensions);
Chris Lattnerf7e22732018-06-22 22:03:48 -0700168 Type *parseTensorType();
169 Type *parseMemRefType();
170 Type *parseFunctionType();
171 Type *parseType();
Chris Lattner1604e472018-07-23 08:42:19 -0700172 ParseResult parseTypeListNoParens(SmallVectorImpl<Type *> &elements);
James Molloy0ff71542018-07-23 16:56:32 -0700173 ParseResult parseTypeList(SmallVectorImpl<Type *> &elements);
Chris Lattnere79379a2018-06-22 10:39:19 -0700174
Chris Lattner7121b802018-07-04 20:45:39 -0700175 // Attribute parsing.
176 Attribute *parseAttribute();
177 ParseResult parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes);
178
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700179 // Polyhedral structures.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700180 AffineMap *parseAffineMapInline();
MLIR Team718c82f2018-07-16 09:45:22 -0700181 AffineMap *parseAffineMapReference();
Uday Bondhugulabc535622018-08-07 14:24:38 -0700182 IntegerSet *parseIntegerSetInline();
183 IntegerSet *parseIntegerSetReference();
MLIR Teamf85a6262018-06-27 11:03:08 -0700184
Chris Lattner48af7d12018-07-09 19:05:38 -0700185private:
186 // The Parser is subclassed and reinstantiated. Do not add additional
187 // non-trivial state here, add it to the ParserState class.
188 ParserState &state;
Chris Lattnere79379a2018-06-22 10:39:19 -0700189};
190} // end anonymous namespace
191
192//===----------------------------------------------------------------------===//
193// Helper methods.
194//===----------------------------------------------------------------------===//
195
Chris Lattner4c95a502018-06-23 16:03:42 -0700196ParseResult Parser::emitError(SMLoc loc, const Twine &message) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700197 // If we hit a parse error in response to a lexer error, then the lexer
Jacques Pienaar9c411be2018-06-24 19:17:35 -0700198 // already reported the error.
Chris Lattner48af7d12018-07-09 19:05:38 -0700199 if (getToken().is(Token::error))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700200 return ParseFailure;
201
Chris Lattner48af7d12018-07-09 19:05:38 -0700202 auto &sourceMgr = state.lex.getSourceMgr();
203 state.errorReporter(sourceMgr.GetMessage(loc, SourceMgr::DK_Error, message));
Chris Lattnere79379a2018-06-22 10:39:19 -0700204 return ParseFailure;
205}
206
Chris Lattnerf7702a62018-07-23 17:30:01 -0700207/// Consume the specified token if present and return success. On failure,
208/// output a diagnostic and return failure.
209ParseResult Parser::parseToken(Token::Kind expectedToken,
210 const Twine &message) {
211 if (consumeIf(expectedToken))
212 return ParseSuccess;
213 return emitError(message);
214}
215
Chris Lattner40746442018-07-21 14:32:09 -0700216/// Parse a comma separated list of elements that must have at least one entry
217/// in it.
218ParseResult Parser::parseCommaSeparatedList(
219 const std::function<ParseResult()> &parseElement) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700220 // Non-empty case starts with an element.
221 if (parseElement())
222 return ParseFailure;
223
224 // Otherwise we have a list of comma separated elements.
225 while (consumeIf(Token::comma)) {
226 if (parseElement())
227 return ParseFailure;
228 }
Chris Lattner40746442018-07-21 14:32:09 -0700229 return ParseSuccess;
230}
231
232/// Parse a comma-separated list of elements, terminated with an arbitrary
233/// token. This allows empty lists if allowEmptyList is true.
234///
235/// abstract-list ::= rightToken // if allowEmptyList == true
236/// abstract-list ::= element (',' element)* rightToken
237///
238ParseResult Parser::parseCommaSeparatedListUntil(
239 Token::Kind rightToken, const std::function<ParseResult()> &parseElement,
240 bool allowEmptyList) {
241 // Handle the empty case.
242 if (getToken().is(rightToken)) {
243 if (!allowEmptyList)
244 return emitError("expected list element");
245 consumeToken(rightToken);
246 return ParseSuccess;
247 }
248
Chris Lattnerf7702a62018-07-23 17:30:01 -0700249 if (parseCommaSeparatedList(parseElement) ||
250 parseToken(rightToken, "expected ',' or '" +
251 Token::getTokenSpelling(rightToken) + "'"))
Chris Lattner40746442018-07-21 14:32:09 -0700252 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700253
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700254 return ParseSuccess;
255}
Chris Lattnere79379a2018-06-22 10:39:19 -0700256
257//===----------------------------------------------------------------------===//
258// Type Parsing
259//===----------------------------------------------------------------------===//
260
Chris Lattnerc3251192018-07-27 13:09:58 -0700261/// Parse an arbitrary type.
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700262///
Chris Lattnerc3251192018-07-27 13:09:58 -0700263/// type ::= integer-type
264/// | float-type
265/// | other-type
266/// | vector-type
267/// | tensor-type
268/// | memref-type
269/// | function-type
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700270///
Chris Lattnerc3251192018-07-27 13:09:58 -0700271/// float-type ::= `f16` | `bf16` | `f32` | `f64`
272/// other-type ::= `affineint` | `tf_control`
273///
274Type *Parser::parseType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700275 switch (getToken().getKind()) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700276 default:
277 return (emitError("expected type"), nullptr);
Chris Lattnerc3251192018-07-27 13:09:58 -0700278 case Token::kw_memref:
279 return parseMemRefType();
280 case Token::kw_tensor:
281 return parseTensorType();
282 case Token::kw_vector:
283 return parseVectorType();
284 case Token::l_paren:
285 return parseFunctionType();
286 // integer-type
287 case Token::inttype: {
288 auto width = getToken().getIntTypeBitwidth();
289 if (!width.hasValue())
290 return (emitError("invalid integer width"), nullptr);
291 consumeToken(Token::inttype);
292 return builder.getIntegerType(width.getValue());
293 }
294
295 // float-type
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700296 case Token::kw_bf16:
297 consumeToken(Token::kw_bf16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700298 return builder.getBF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700299 case Token::kw_f16:
300 consumeToken(Token::kw_f16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700301 return builder.getF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700302 case Token::kw_f32:
303 consumeToken(Token::kw_f32);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700304 return builder.getF32Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700305 case Token::kw_f64:
306 consumeToken(Token::kw_f64);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700307 return builder.getF64Type();
Chris Lattnerc3251192018-07-27 13:09:58 -0700308
309 // other-type
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700310 case Token::kw_affineint:
311 consumeToken(Token::kw_affineint);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700312 return builder.getAffineIntType();
Jacques Pienaarc0d69302018-07-27 11:07:12 -0700313 case Token::kw_tf_control:
314 consumeToken(Token::kw_tf_control);
315 return builder.getTFControlType();
James Molloy72b0cbe2018-08-01 12:55:27 -0700316 case Token::kw_tf_string:
317 consumeToken(Token::kw_tf_string);
318 return builder.getTFStringType();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700319 }
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700320}
321
322/// Parse a vector type.
323///
324/// vector-type ::= `vector` `<` const-dimension-list primitive-type `>`
325/// const-dimension-list ::= (integer-literal `x`)+
326///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700327VectorType *Parser::parseVectorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700328 consumeToken(Token::kw_vector);
329
Chris Lattnerf7702a62018-07-23 17:30:01 -0700330 if (parseToken(Token::less, "expected '<' in vector type"))
331 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700332
Chris Lattner48af7d12018-07-09 19:05:38 -0700333 if (getToken().isNot(Token::integer))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700334 return (emitError("expected dimension size in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700335
336 SmallVector<unsigned, 4> dimensions;
Chris Lattner48af7d12018-07-09 19:05:38 -0700337 while (getToken().is(Token::integer)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700338 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700339 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700340 if (!dimension.hasValue())
Chris Lattnerf7e22732018-06-22 22:03:48 -0700341 return (emitError("invalid dimension in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700342 dimensions.push_back(dimension.getValue());
343
344 consumeToken(Token::integer);
345
346 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700347 if (getToken().isNot(Token::bare_identifier) ||
348 getTokenSpelling()[0] != 'x')
Chris Lattnerf7e22732018-06-22 22:03:48 -0700349 return (emitError("expected 'x' in vector dimension list"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700350
351 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700352 if (getTokenSpelling().size() != 1)
353 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700354
355 // Consume the 'x'.
356 consumeToken(Token::bare_identifier);
357 }
358
359 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700360 auto typeLoc = getToken().getLoc();
361 auto *elementType = parseType();
362 if (!elementType || parseToken(Token::greater, "expected '>' in vector type"))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700363 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700364
Chris Lattnerc3251192018-07-27 13:09:58 -0700365 if (!isa<FloatType>(elementType) && !isa<IntegerType>(elementType))
366 return (emitError(typeLoc, "invalid vector element type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700367
Chris Lattnerf7e22732018-06-22 22:03:48 -0700368 return VectorType::get(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700369}
370
371/// Parse a dimension list of a tensor or memref type. This populates the
372/// dimension list, returning -1 for the '?' dimensions.
373///
374/// dimension-list-ranked ::= (dimension `x`)*
375/// dimension ::= `?` | integer-literal
376///
377ParseResult Parser::parseDimensionListRanked(SmallVectorImpl<int> &dimensions) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700378 while (getToken().isAny(Token::integer, Token::question)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700379 if (consumeIf(Token::question)) {
380 dimensions.push_back(-1);
381 } else {
382 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700383 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700384 if (!dimension.hasValue() || (int)dimension.getValue() < 0)
385 return emitError("invalid dimension");
386 dimensions.push_back((int)dimension.getValue());
387 consumeToken(Token::integer);
388 }
389
390 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700391 if (getToken().isNot(Token::bare_identifier) ||
392 getTokenSpelling()[0] != 'x')
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700393 return emitError("expected 'x' in dimension list");
394
395 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700396 if (getTokenSpelling().size() != 1)
397 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700398
399 // Consume the 'x'.
400 consumeToken(Token::bare_identifier);
401 }
402
403 return ParseSuccess;
404}
405
406/// Parse a tensor type.
407///
408/// tensor-type ::= `tensor` `<` dimension-list element-type `>`
409/// dimension-list ::= dimension-list-ranked | `??`
410///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700411Type *Parser::parseTensorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700412 consumeToken(Token::kw_tensor);
413
Chris Lattnerf7702a62018-07-23 17:30:01 -0700414 if (parseToken(Token::less, "expected '<' in tensor type"))
415 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700416
417 bool isUnranked;
418 SmallVector<int, 4> dimensions;
419
420 if (consumeIf(Token::questionquestion)) {
421 isUnranked = true;
422 } else {
423 isUnranked = false;
424 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700425 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700426 }
427
428 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700429 auto typeLoc = getToken().getLoc();
430 auto *elementType = parseType();
431 if (!elementType || parseToken(Token::greater, "expected '>' in tensor type"))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700432 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700433
Chris Lattnerc3251192018-07-27 13:09:58 -0700434 if (!isa<IntegerType>(elementType) && !isa<FloatType>(elementType) &&
435 !isa<VectorType>(elementType))
436 return (emitError(typeLoc, "invalid tensor element type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700437
MLIR Team355ec862018-06-23 18:09:09 -0700438 if (isUnranked)
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700439 return builder.getTensorType(elementType);
440 return builder.getTensorType(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700441}
442
443/// Parse a memref type.
444///
445/// memref-type ::= `memref` `<` dimension-list-ranked element-type
446/// (`,` semi-affine-map-composition)? (`,` memory-space)? `>`
447///
448/// semi-affine-map-composition ::= (semi-affine-map `,` )* semi-affine-map
449/// memory-space ::= integer-literal /* | TODO: address-space-id */
450///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700451Type *Parser::parseMemRefType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700452 consumeToken(Token::kw_memref);
453
Chris Lattnerf7702a62018-07-23 17:30:01 -0700454 if (parseToken(Token::less, "expected '<' in memref type"))
455 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700456
457 SmallVector<int, 4> dimensions;
458 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700459 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700460
461 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700462 auto typeLoc = getToken().getLoc();
463 auto *elementType = parseType();
Chris Lattnerf7e22732018-06-22 22:03:48 -0700464 if (!elementType)
465 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700466
Chris Lattnerc3251192018-07-27 13:09:58 -0700467 if (!isa<IntegerType>(elementType) && !isa<FloatType>(elementType) &&
468 !isa<VectorType>(elementType))
469 return (emitError(typeLoc, "invalid memref element type"), nullptr);
470
MLIR Team718c82f2018-07-16 09:45:22 -0700471 // Parse semi-affine-map-composition.
James Molloy0ff71542018-07-23 16:56:32 -0700472 SmallVector<AffineMap *, 2> affineMapComposition;
Chris Lattner413db6a2018-07-25 12:55:50 -0700473 unsigned memorySpace = 0;
MLIR Team718c82f2018-07-16 09:45:22 -0700474 bool parsedMemorySpace = false;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700475
MLIR Team718c82f2018-07-16 09:45:22 -0700476 auto parseElt = [&]() -> ParseResult {
477 if (getToken().is(Token::integer)) {
478 // Parse memory space.
479 if (parsedMemorySpace)
480 return emitError("multiple memory spaces specified in memref type");
481 auto v = getToken().getUnsignedIntegerValue();
482 if (!v.hasValue())
483 return emitError("invalid memory space in memref type");
484 memorySpace = v.getValue();
485 consumeToken(Token::integer);
486 parsedMemorySpace = true;
487 } else {
488 // Parse affine map.
489 if (parsedMemorySpace)
490 return emitError("affine map after memory space in memref type");
James Molloy0ff71542018-07-23 16:56:32 -0700491 auto *affineMap = parseAffineMapReference();
MLIR Team718c82f2018-07-16 09:45:22 -0700492 if (affineMap == nullptr)
493 return ParseFailure;
494 affineMapComposition.push_back(affineMap);
495 }
496 return ParseSuccess;
497 };
498
Chris Lattner413db6a2018-07-25 12:55:50 -0700499 // Parse a list of mappings and address space if present.
500 if (consumeIf(Token::comma)) {
501 // Parse comma separated list of affine maps, followed by memory space.
502 if (parseCommaSeparatedListUntil(Token::greater, parseElt,
503 /*allowEmptyList=*/false)) {
504 return nullptr;
505 }
506 } else {
507 if (parseToken(Token::greater, "expected ',' or '>' in memref type"))
508 return nullptr;
MLIR Team718c82f2018-07-16 09:45:22 -0700509 }
MLIR Team718c82f2018-07-16 09:45:22 -0700510
511 return MemRefType::get(dimensions, elementType, affineMapComposition,
512 memorySpace);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700513}
514
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700515/// Parse a function type.
516///
517/// function-type ::= type-list-parens `->` type-list
518///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700519Type *Parser::parseFunctionType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700520 assert(getToken().is(Token::l_paren));
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700521
Chris Lattnerf7702a62018-07-23 17:30:01 -0700522 SmallVector<Type *, 4> arguments, results;
523 if (parseTypeList(arguments) ||
524 parseToken(Token::arrow, "expected '->' in function type") ||
525 parseTypeList(results))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700526 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700527
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700528 return builder.getFunctionType(arguments, results);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700529}
530
Chris Lattner1604e472018-07-23 08:42:19 -0700531/// Parse a list of types without an enclosing parenthesis. The list must have
532/// at least one member.
533///
534/// type-list-no-parens ::= type (`,` type)*
535///
536ParseResult Parser::parseTypeListNoParens(SmallVectorImpl<Type *> &elements) {
537 auto parseElt = [&]() -> ParseResult {
538 auto elt = parseType();
539 elements.push_back(elt);
540 return elt ? ParseSuccess : ParseFailure;
541 };
542
543 return parseCommaSeparatedList(parseElt);
544}
545
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700546/// Parse a "type list", which is a singular type, or a parenthesized list of
547/// types.
548///
549/// type-list ::= type-list-parens | type
550/// type-list-parens ::= `(` `)`
Chris Lattner1604e472018-07-23 08:42:19 -0700551/// | `(` type-list-no-parens `)`
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700552///
James Molloy0ff71542018-07-23 16:56:32 -0700553ParseResult Parser::parseTypeList(SmallVectorImpl<Type *> &elements) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700554 auto parseElt = [&]() -> ParseResult {
555 auto elt = parseType();
556 elements.push_back(elt);
557 return elt ? ParseSuccess : ParseFailure;
558 };
559
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700560 // If there is no parens, then it must be a singular type.
561 if (!consumeIf(Token::l_paren))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700562 return parseElt();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700563
Chris Lattner40746442018-07-21 14:32:09 -0700564 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700565 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700566
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700567 return ParseSuccess;
568}
569
Chris Lattner4c95a502018-06-23 16:03:42 -0700570//===----------------------------------------------------------------------===//
Chris Lattner7121b802018-07-04 20:45:39 -0700571// Attribute parsing.
572//===----------------------------------------------------------------------===//
573
Chris Lattner7121b802018-07-04 20:45:39 -0700574/// Attribute parsing.
575///
576/// attribute-value ::= bool-literal
577/// | integer-literal
578/// | float-literal
579/// | string-literal
James Molloyf0d2f442018-08-03 01:54:46 -0700580/// | type
Chris Lattner7121b802018-07-04 20:45:39 -0700581/// | `[` (attribute-value (`,` attribute-value)*)? `]`
582///
583Attribute *Parser::parseAttribute() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700584 switch (getToken().getKind()) {
Chris Lattner7121b802018-07-04 20:45:39 -0700585 case Token::kw_true:
586 consumeToken(Token::kw_true);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700587 return builder.getBoolAttr(true);
Chris Lattner7121b802018-07-04 20:45:39 -0700588 case Token::kw_false:
589 consumeToken(Token::kw_false);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700590 return builder.getBoolAttr(false);
Chris Lattner7121b802018-07-04 20:45:39 -0700591
Jacques Pienaar84491092018-07-31 17:15:15 -0700592 case Token::floatliteral: {
593 auto val = getToken().getFloatingPointValue();
594 if (!val.hasValue())
595 return (emitError("floating point value too large for attribute"),
596 nullptr);
597 consumeToken(Token::floatliteral);
598 return builder.getFloatAttr(val.getValue());
599 }
Chris Lattner7121b802018-07-04 20:45:39 -0700600 case Token::integer: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700601 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700602 if (!val.hasValue() || (int64_t)val.getValue() < 0)
603 return (emitError("integer too large for attribute"), nullptr);
604 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700605 return builder.getIntegerAttr((int64_t)val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700606 }
607
608 case Token::minus: {
609 consumeToken(Token::minus);
Chris Lattner48af7d12018-07-09 19:05:38 -0700610 if (getToken().is(Token::integer)) {
611 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700612 if (!val.hasValue() || (int64_t)-val.getValue() >= 0)
613 return (emitError("integer too large for attribute"), nullptr);
614 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700615 return builder.getIntegerAttr((int64_t)-val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700616 }
Jacques Pienaar84491092018-07-31 17:15:15 -0700617 if (getToken().is(Token::floatliteral)) {
618 auto val = getToken().getFloatingPointValue();
619 if (!val.hasValue())
620 return (emitError("floating point value too large for attribute"),
621 nullptr);
622 consumeToken(Token::floatliteral);
623 return builder.getFloatAttr(-val.getValue());
624 }
Chris Lattner7121b802018-07-04 20:45:39 -0700625
626 return (emitError("expected constant integer or floating point value"),
627 nullptr);
628 }
629
630 case Token::string: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700631 auto val = getToken().getStringValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700632 consumeToken(Token::string);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700633 return builder.getStringAttr(val);
Chris Lattner7121b802018-07-04 20:45:39 -0700634 }
635
Chris Lattner85ee1512018-07-25 11:15:20 -0700636 case Token::l_square: {
637 consumeToken(Token::l_square);
James Molloy0ff71542018-07-23 16:56:32 -0700638 SmallVector<Attribute *, 4> elements;
Chris Lattner7121b802018-07-04 20:45:39 -0700639
640 auto parseElt = [&]() -> ParseResult {
641 elements.push_back(parseAttribute());
642 return elements.back() ? ParseSuccess : ParseFailure;
643 };
644
Chris Lattner85ee1512018-07-25 11:15:20 -0700645 if (parseCommaSeparatedListUntil(Token::r_square, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700646 return nullptr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700647 return builder.getArrayAttr(elements);
Chris Lattner7121b802018-07-04 20:45:39 -0700648 }
James Molloyf0d2f442018-08-03 01:54:46 -0700649 case Token::hash_identifier:
650 case Token::l_paren: {
MLIR Teamb61885d2018-07-18 16:29:21 -0700651 // Try to parse affine map reference.
James Molloyf0d2f442018-08-03 01:54:46 -0700652 if (auto *affineMap = parseAffineMapReference())
MLIR Teamb61885d2018-07-18 16:29:21 -0700653 return builder.getAffineMapAttr(affineMap);
Chris Lattner7121b802018-07-04 20:45:39 -0700654 return (emitError("expected constant attribute value"), nullptr);
655 }
James Molloyf0d2f442018-08-03 01:54:46 -0700656 default: {
657 if (Type *type = parseType())
658 return builder.getTypeAttr(type);
659 return nullptr;
660 }
661 }
Chris Lattner7121b802018-07-04 20:45:39 -0700662}
663
Chris Lattner7121b802018-07-04 20:45:39 -0700664/// Attribute dictionary.
665///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700666/// attribute-dict ::= `{` `}`
667/// | `{` attribute-entry (`,` attribute-entry)* `}`
668/// attribute-entry ::= bare-id `:` attribute-value
Chris Lattner7121b802018-07-04 20:45:39 -0700669///
James Molloy0ff71542018-07-23 16:56:32 -0700670ParseResult
671Parser::parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes) {
Chris Lattner7121b802018-07-04 20:45:39 -0700672 consumeToken(Token::l_brace);
673
674 auto parseElt = [&]() -> ParseResult {
675 // We allow keywords as attribute names.
Chris Lattner48af7d12018-07-09 19:05:38 -0700676 if (getToken().isNot(Token::bare_identifier, Token::inttype) &&
677 !getToken().isKeyword())
Chris Lattner7121b802018-07-04 20:45:39 -0700678 return emitError("expected attribute name");
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700679 auto nameId = builder.getIdentifier(getTokenSpelling());
Chris Lattner7121b802018-07-04 20:45:39 -0700680 consumeToken();
681
Chris Lattnerf7702a62018-07-23 17:30:01 -0700682 if (parseToken(Token::colon, "expected ':' in attribute list"))
683 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700684
685 auto attr = parseAttribute();
James Molloy0ff71542018-07-23 16:56:32 -0700686 if (!attr)
687 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700688
689 attributes.push_back({nameId, attr});
690 return ParseSuccess;
691 };
692
Chris Lattner40746442018-07-21 14:32:09 -0700693 if (parseCommaSeparatedListUntil(Token::r_brace, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700694 return ParseFailure;
695
696 return ParseSuccess;
697}
698
699//===----------------------------------------------------------------------===//
MLIR Teamf85a6262018-06-27 11:03:08 -0700700// Polyhedral structures.
701//===----------------------------------------------------------------------===//
702
Chris Lattner2e595eb2018-07-10 10:08:27 -0700703/// Lower precedence ops (all at the same precedence level). LNoOp is false in
704/// the boolean sense.
705enum AffineLowPrecOp {
706 /// Null value.
707 LNoOp,
708 Add,
709 Sub
710};
MLIR Teamf85a6262018-06-27 11:03:08 -0700711
Chris Lattner2e595eb2018-07-10 10:08:27 -0700712/// Higher precedence ops - all at the same precedence level. HNoOp is false in
713/// the boolean sense.
714enum AffineHighPrecOp {
715 /// Null value.
716 HNoOp,
717 Mul,
718 FloorDiv,
719 CeilDiv,
720 Mod
721};
Chris Lattner7121b802018-07-04 20:45:39 -0700722
Chris Lattner2e595eb2018-07-10 10:08:27 -0700723namespace {
Uday Bondhugulabc535622018-08-07 14:24:38 -0700724/// This is a specialized parser for affine structures (affine maps, affine
725/// expressions, and integer sets), maintaining the state transient to their
726/// bodies.
727class AffineParser : public Parser {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700728public:
Uday Bondhugulabc535622018-08-07 14:24:38 -0700729 explicit AffineParser(ParserState &state) : Parser(state) {}
Chris Lattner7121b802018-07-04 20:45:39 -0700730
Chris Lattner2e595eb2018-07-10 10:08:27 -0700731 AffineMap *parseAffineMapInline();
Uday Bondhugulabc535622018-08-07 14:24:38 -0700732 IntegerSet *parseIntegerSetInline();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700733
Chris Lattner2e595eb2018-07-10 10:08:27 -0700734private:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700735 // Binary affine op parsing.
736 AffineLowPrecOp consumeIfLowPrecOp();
737 AffineHighPrecOp consumeIfHighPrecOp();
MLIR Teamf85a6262018-06-27 11:03:08 -0700738
Chris Lattner2e595eb2018-07-10 10:08:27 -0700739 // Identifier lists for polyhedral structures.
Chris Lattner413db6a2018-07-25 12:55:50 -0700740 ParseResult parseDimIdList(unsigned &numDims);
741 ParseResult parseSymbolIdList(unsigned &numSymbols);
742 ParseResult parseIdentifierDefinition(AffineExpr *idExpr);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700743
744 AffineExpr *parseAffineExpr();
745 AffineExpr *parseParentheticalExpr();
746 AffineExpr *parseNegateExpression(AffineExpr *lhs);
747 AffineExpr *parseIntegerExpr();
748 AffineExpr *parseBareIdExpr();
749
750 AffineExpr *getBinaryAffineOpExpr(AffineHighPrecOp op, AffineExpr *lhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700751 AffineExpr *rhs, SMLoc opLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700752 AffineExpr *getBinaryAffineOpExpr(AffineLowPrecOp op, AffineExpr *lhs,
753 AffineExpr *rhs);
754 AffineExpr *parseAffineOperandExpr(AffineExpr *lhs);
755 AffineExpr *parseAffineLowPrecOpExpr(AffineExpr *llhs,
756 AffineLowPrecOp llhsOp);
757 AffineExpr *parseAffineHighPrecOpExpr(AffineExpr *llhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700758 AffineHighPrecOp llhsOp,
759 SMLoc llhsOpLoc);
Uday Bondhugulabc535622018-08-07 14:24:38 -0700760 AffineExpr *parseAffineConstraint(bool *isEq);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700761
762private:
Chris Lattner413db6a2018-07-25 12:55:50 -0700763 SmallVector<std::pair<StringRef, AffineExpr *>, 4> dimsAndSymbols;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700764};
765} // end anonymous namespace
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700766
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700767/// Create an affine binary high precedence op expression (mul's, div's, mod).
768/// opLoc is the location of the op token to be used to report errors
769/// for non-conforming expressions.
Uday Bondhugulabc535622018-08-07 14:24:38 -0700770AffineExpr *AffineParser::getBinaryAffineOpExpr(AffineHighPrecOp op,
771 AffineExpr *lhs,
772 AffineExpr *rhs, SMLoc opLoc) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700773 // TODO: make the error location info accurate.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700774 switch (op) {
775 case Mul:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700776 if (!lhs->isSymbolicOrConstant() && !rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700777 emitError(opLoc, "non-affine expression: at least one of the multiply "
778 "operands has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700779 return nullptr;
780 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700781 return builder.getMulExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700782 case FloorDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700783 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700784 emitError(opLoc, "non-affine expression: right operand of floordiv "
785 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700786 return nullptr;
787 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700788 return builder.getFloorDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700789 case CeilDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700790 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700791 emitError(opLoc, "non-affine expression: right operand of ceildiv "
792 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700793 return nullptr;
794 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700795 return builder.getCeilDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700796 case Mod:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700797 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700798 emitError(opLoc, "non-affine expression: right operand of mod "
799 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700800 return nullptr;
801 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700802 return builder.getModExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700803 case HNoOp:
804 llvm_unreachable("can't create affine expression for null high prec op");
805 return nullptr;
806 }
807}
808
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700809/// Create an affine binary low precedence op expression (add, sub).
Uday Bondhugulabc535622018-08-07 14:24:38 -0700810AffineExpr *AffineParser::getBinaryAffineOpExpr(AffineLowPrecOp op,
811 AffineExpr *lhs,
812 AffineExpr *rhs) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700813 switch (op) {
814 case AffineLowPrecOp::Add:
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700815 return builder.getAddExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700816 case AffineLowPrecOp::Sub:
Uday Bondhugulac1faf662018-07-19 14:08:50 -0700817 return builder.getAddExpr(
818 lhs, builder.getMulExpr(rhs, builder.getConstantExpr(-1)));
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700819 case AffineLowPrecOp::LNoOp:
820 llvm_unreachable("can't create affine expression for null low prec op");
821 return nullptr;
822 }
823}
824
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700825/// Consume this token if it is a lower precedence affine op (there are only two
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700826/// precedence levels).
Uday Bondhugulabc535622018-08-07 14:24:38 -0700827AffineLowPrecOp AffineParser::consumeIfLowPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700828 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700829 case Token::plus:
830 consumeToken(Token::plus);
831 return AffineLowPrecOp::Add;
832 case Token::minus:
833 consumeToken(Token::minus);
834 return AffineLowPrecOp::Sub;
835 default:
836 return AffineLowPrecOp::LNoOp;
837 }
838}
839
840/// Consume this token if it is a higher precedence affine op (there are only
841/// two precedence levels)
Uday Bondhugulabc535622018-08-07 14:24:38 -0700842AffineHighPrecOp AffineParser::consumeIfHighPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700843 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700844 case Token::star:
845 consumeToken(Token::star);
846 return Mul;
847 case Token::kw_floordiv:
848 consumeToken(Token::kw_floordiv);
849 return FloorDiv;
850 case Token::kw_ceildiv:
851 consumeToken(Token::kw_ceildiv);
852 return CeilDiv;
853 case Token::kw_mod:
854 consumeToken(Token::kw_mod);
855 return Mod;
856 default:
857 return HNoOp;
858 }
859}
860
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700861/// Parse a high precedence op expression list: mul, div, and mod are high
862/// precedence binary ops, i.e., parse a
863/// expr_1 op_1 expr_2 op_2 ... expr_n
864/// where op_1, op_2 are all a AffineHighPrecOp (mul, div, mod).
865/// All affine binary ops are left associative.
866/// Given llhs, returns (llhs llhsOp lhs) op rhs, or (lhs op rhs) if llhs is
867/// null. If no rhs can be found, returns (llhs llhsOp lhs) or lhs if llhs is
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700868/// null. llhsOpLoc is the location of the llhsOp token that will be used to
869/// report an error for non-conforming expressions.
Uday Bondhugulabc535622018-08-07 14:24:38 -0700870AffineExpr *AffineParser::parseAffineHighPrecOpExpr(AffineExpr *llhs,
871 AffineHighPrecOp llhsOp,
872 SMLoc llhsOpLoc) {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700873 AffineExpr *lhs = parseAffineOperandExpr(llhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700874 if (!lhs)
875 return nullptr;
876
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700877 // Found an LHS. Parse the remaining expression.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700878 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -0700879 if (AffineHighPrecOp op = consumeIfHighPrecOp()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700880 if (llhs) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700881 AffineExpr *expr = getBinaryAffineOpExpr(llhsOp, llhs, lhs, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700882 if (!expr)
883 return nullptr;
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700884 return parseAffineHighPrecOpExpr(expr, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700885 }
886 // No LLHS, get RHS
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700887 return parseAffineHighPrecOpExpr(lhs, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700888 }
889
890 // This is the last operand in this expression.
891 if (llhs)
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700892 return getBinaryAffineOpExpr(llhsOp, llhs, lhs, llhsOpLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700893
894 // No llhs, 'lhs' itself is the expression.
895 return lhs;
896}
897
898/// Parse an affine expression inside parentheses.
899///
900/// affine-expr ::= `(` affine-expr `)`
Uday Bondhugulabc535622018-08-07 14:24:38 -0700901AffineExpr *AffineParser::parseParentheticalExpr() {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700902 if (parseToken(Token::l_paren, "expected '('"))
903 return nullptr;
Chris Lattner48af7d12018-07-09 19:05:38 -0700904 if (getToken().is(Token::r_paren))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700905 return (emitError("no expression inside parentheses"), nullptr);
Chris Lattnerf7702a62018-07-23 17:30:01 -0700906
Chris Lattner2e595eb2018-07-10 10:08:27 -0700907 auto *expr = parseAffineExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700908 if (!expr)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700909 return nullptr;
Chris Lattnerf7702a62018-07-23 17:30:01 -0700910 if (parseToken(Token::r_paren, "expected ')'"))
911 return nullptr;
912
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700913 return expr;
914}
915
916/// Parse the negation expression.
917///
918/// affine-expr ::= `-` affine-expr
Uday Bondhugulabc535622018-08-07 14:24:38 -0700919AffineExpr *AffineParser::parseNegateExpression(AffineExpr *lhs) {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700920 if (parseToken(Token::minus, "expected '-'"))
921 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700922
Chris Lattner2e595eb2018-07-10 10:08:27 -0700923 AffineExpr *operand = parseAffineOperandExpr(lhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700924 // Since negation has the highest precedence of all ops (including high
925 // precedence ops) but lower than parentheses, we are only going to use
926 // parseAffineOperandExpr instead of parseAffineExpr here.
927 if (!operand)
928 // Extra error message although parseAffineOperandExpr would have
929 // complained. Leads to a better diagnostic.
930 return (emitError("missing operand of negation"), nullptr);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700931 auto *minusOne = builder.getConstantExpr(-1);
932 return builder.getMulExpr(minusOne, operand);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700933}
934
935/// Parse a bare id that may appear in an affine expression.
936///
937/// affine-expr ::= bare-id
Uday Bondhugulabc535622018-08-07 14:24:38 -0700938AffineExpr *AffineParser::parseBareIdExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700939 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700940 return (emitError("expected bare identifier"), nullptr);
941
Chris Lattner48af7d12018-07-09 19:05:38 -0700942 StringRef sRef = getTokenSpelling();
Chris Lattner413db6a2018-07-25 12:55:50 -0700943 for (auto entry : dimsAndSymbols) {
Chris Lattnera8e47672018-07-25 14:08:16 -0700944 if (entry.first == sRef) {
945 consumeToken(Token::bare_identifier);
946 return entry.second;
947 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700948 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700949
950 return (emitError("use of undeclared identifier"), nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700951}
952
953/// Parse a positive integral constant appearing in an affine expression.
954///
955/// affine-expr ::= integer-literal
Uday Bondhugulabc535622018-08-07 14:24:38 -0700956AffineExpr *AffineParser::parseIntegerExpr() {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700957 // No need to handle negative numbers separately here. They are naturally
958 // handled via the unary negation operator, although (FIXME) MININT_64 still
959 // not correctly handled.
Chris Lattner48af7d12018-07-09 19:05:38 -0700960 if (getToken().isNot(Token::integer))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700961 return (emitError("expected integer"), nullptr);
962
Chris Lattner48af7d12018-07-09 19:05:38 -0700963 auto val = getToken().getUInt64IntegerValue();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700964 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
965 return (emitError("constant too large for affineint"), nullptr);
966 }
967 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700968 return builder.getConstantExpr((int64_t)val.getValue());
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700969}
970
971/// Parses an expression that can be a valid operand of an affine expression.
Uday Bondhugula76345202018-07-09 13:47:52 -0700972/// lhs: if non-null, lhs is an affine expression that is the lhs of a binary
973/// operator, the rhs of which is being parsed. This is used to determine
974/// whether an error should be emitted for a missing right operand.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700975// Eg: for an expression without parentheses (like i + j + k + l), each
976// of the four identifiers is an operand. For i + j*k + l, j*k is not an
977// operand expression, it's an op expression and will be parsed via
978// parseAffineHighPrecOpExpression(). However, for i + (j*k) + -l, (j*k) and -l
979// are valid operands that will be parsed by this function.
Uday Bondhugulabc535622018-08-07 14:24:38 -0700980AffineExpr *AffineParser::parseAffineOperandExpr(AffineExpr *lhs) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700981 switch (getToken().getKind()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700982 case Token::bare_identifier:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700983 return parseBareIdExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700984 case Token::integer:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700985 return parseIntegerExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700986 case Token::l_paren:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700987 return parseParentheticalExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700988 case Token::minus:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700989 return parseNegateExpression(lhs);
Uday Bondhugula76345202018-07-09 13:47:52 -0700990 case Token::kw_ceildiv:
991 case Token::kw_floordiv:
992 case Token::kw_mod:
993 case Token::plus:
994 case Token::star:
995 if (lhs)
996 emitError("missing right operand of binary operator");
997 else
998 emitError("missing left operand of binary operator");
999 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001000 default:
1001 if (lhs)
Uday Bondhugula76345202018-07-09 13:47:52 -07001002 emitError("missing right operand of binary operator");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001003 else
1004 emitError("expected affine expression");
1005 return nullptr;
1006 }
1007}
1008
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001009/// Parse affine expressions that are bare-id's, integer constants,
1010/// parenthetical affine expressions, and affine op expressions that are a
1011/// composition of those.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001012///
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001013/// All binary op's associate from left to right.
1014///
1015/// {add, sub} have lower precedence than {mul, div, and mod}.
1016///
Uday Bondhugula76345202018-07-09 13:47:52 -07001017/// Add, sub'are themselves at the same precedence level. Mul, floordiv,
1018/// ceildiv, and mod are at the same higher precedence level. Negation has
1019/// higher precedence than any binary op.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001020///
1021/// llhs: the affine expression appearing on the left of the one being parsed.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001022/// This function will return ((llhs llhsOp lhs) op rhs) if llhs is non null,
1023/// and lhs op rhs otherwise; if there is no rhs, llhs llhsOp lhs is returned if
1024/// llhs is non-null; otherwise lhs is returned. This is to deal with left
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001025/// associativity.
1026///
1027/// Eg: when the expression is e1 + e2*e3 + e4, with e1 as llhs, this function
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001028/// will return the affine expr equivalent of (e1 + (e2*e3)) + e4, where (e2*e3)
1029/// will be parsed using parseAffineHighPrecOpExpr().
Uday Bondhugulabc535622018-08-07 14:24:38 -07001030AffineExpr *AffineParser::parseAffineLowPrecOpExpr(AffineExpr *llhs,
1031 AffineLowPrecOp llhsOp) {
Uday Bondhugula76345202018-07-09 13:47:52 -07001032 AffineExpr *lhs;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001033 if (!(lhs = parseAffineOperandExpr(llhs)))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001034 return nullptr;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001035
1036 // Found an LHS. Deal with the ops.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001037 if (AffineLowPrecOp lOp = consumeIfLowPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001038 if (llhs) {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001039 AffineExpr *sum = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001040 return parseAffineLowPrecOpExpr(sum, lOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001041 }
1042 // No LLHS, get RHS and form the expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001043 return parseAffineLowPrecOpExpr(lhs, lOp);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001044 }
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001045 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07001046 if (AffineHighPrecOp hOp = consumeIfHighPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001047 // We have a higher precedence op here. Get the rhs operand for the llhs
1048 // through parseAffineHighPrecOpExpr.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001049 AffineExpr *highRes = parseAffineHighPrecOpExpr(lhs, hOp, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001050 if (!highRes)
1051 return nullptr;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001052
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001053 // If llhs is null, the product forms the first operand of the yet to be
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001054 // found expression. If non-null, the op to associate with llhs is llhsOp.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001055 AffineExpr *expr =
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001056 llhs ? getBinaryAffineOpExpr(llhsOp, llhs, highRes) : highRes;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001057
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001058 // Recurse for subsequent low prec op's after the affine high prec op
1059 // expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001060 if (AffineLowPrecOp nextOp = consumeIfLowPrecOp())
1061 return parseAffineLowPrecOpExpr(expr, nextOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001062 return expr;
1063 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001064 // Last operand in the expression list.
1065 if (llhs)
1066 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
1067 // No llhs, 'lhs' itself is the expression.
1068 return lhs;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001069}
1070
1071/// Parse an affine expression.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001072/// affine-expr ::= `(` affine-expr `)`
1073/// | `-` affine-expr
1074/// | affine-expr `+` affine-expr
1075/// | affine-expr `-` affine-expr
1076/// | affine-expr `*` affine-expr
1077/// | affine-expr `floordiv` affine-expr
1078/// | affine-expr `ceildiv` affine-expr
1079/// | affine-expr `mod` affine-expr
1080/// | bare-id
1081/// | integer-literal
1082///
1083/// Additional conditions are checked depending on the production. For eg., one
1084/// of the operands for `*` has to be either constant/symbolic; the second
1085/// operand for floordiv, ceildiv, and mod has to be a positive integer.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001086AffineExpr *AffineParser::parseAffineExpr() {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001087 return parseAffineLowPrecOpExpr(nullptr, AffineLowPrecOp::LNoOp);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001088}
1089
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001090/// Parse a dim or symbol from the lists appearing before the actual expressions
Chris Lattner2e595eb2018-07-10 10:08:27 -07001091/// of the affine map. Update our state to store the dimensional/symbolic
Chris Lattner413db6a2018-07-25 12:55:50 -07001092/// identifier.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001093ParseResult AffineParser::parseIdentifierDefinition(AffineExpr *idExpr) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001094 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001095 return emitError("expected bare identifier");
Chris Lattner413db6a2018-07-25 12:55:50 -07001096
1097 auto name = getTokenSpelling();
1098 for (auto entry : dimsAndSymbols) {
1099 if (entry.first == name)
1100 return emitError("redefinition of identifier '" + Twine(name) + "'");
1101 }
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001102 consumeToken(Token::bare_identifier);
Chris Lattner413db6a2018-07-25 12:55:50 -07001103
1104 dimsAndSymbols.push_back({name, idExpr});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001105 return ParseSuccess;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001106}
1107
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001108/// Parse the list of symbolic identifiers to an affine map.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001109ParseResult AffineParser::parseSymbolIdList(unsigned &numSymbols) {
Chris Lattner413db6a2018-07-25 12:55:50 -07001110 consumeToken(Token::l_square);
1111 auto parseElt = [&]() -> ParseResult {
1112 auto *symbol = AffineSymbolExpr::get(numSymbols++, getContext());
1113 return parseIdentifierDefinition(symbol);
1114 };
Chris Lattner85ee1512018-07-25 11:15:20 -07001115 return parseCommaSeparatedListUntil(Token::r_square, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001116}
1117
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001118/// Parse the list of dimensional identifiers to an affine map.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001119ParseResult AffineParser::parseDimIdList(unsigned &numDims) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07001120 if (parseToken(Token::l_paren,
1121 "expected '(' at start of dimensional identifiers list"))
1122 return ParseFailure;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001123
Chris Lattner413db6a2018-07-25 12:55:50 -07001124 auto parseElt = [&]() -> ParseResult {
1125 auto *dimension = AffineDimExpr::get(numDims++, getContext());
1126 return parseIdentifierDefinition(dimension);
1127 };
Chris Lattner40746442018-07-21 14:32:09 -07001128 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001129}
1130
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001131/// Parse an affine map definition.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001132///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001133/// affine-map-inline ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
1134/// (`size` `(` dim-size (`,` dim-size)* `)`)?
1135/// dim-size ::= affine-expr | `min` `(` affine-expr ( `,` affine-expr)+ `)`
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001136///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001137/// multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Uday Bondhugulabc535622018-08-07 14:24:38 -07001138AffineMap *AffineParser::parseAffineMapInline() {
Chris Lattner413db6a2018-07-25 12:55:50 -07001139 unsigned numDims = 0, numSymbols = 0;
1140
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001141 // List of dimensional identifiers.
Chris Lattner413db6a2018-07-25 12:55:50 -07001142 if (parseDimIdList(numDims))
Chris Lattner7121b802018-07-04 20:45:39 -07001143 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001144
1145 // Symbols are optional.
Chris Lattner85ee1512018-07-25 11:15:20 -07001146 if (getToken().is(Token::l_square)) {
Chris Lattner413db6a2018-07-25 12:55:50 -07001147 if (parseSymbolIdList(numSymbols))
Chris Lattner7121b802018-07-04 20:45:39 -07001148 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001149 }
Chris Lattnerf7702a62018-07-23 17:30:01 -07001150
1151 if (parseToken(Token::arrow, "expected '->' or '['") ||
1152 parseToken(Token::l_paren, "expected '(' at start of affine map range"))
Chris Lattner7121b802018-07-04 20:45:39 -07001153 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001154
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001155 SmallVector<AffineExpr *, 4> exprs;
1156 auto parseElt = [&]() -> ParseResult {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001157 auto *elt = parseAffineExpr();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001158 ParseResult res = elt ? ParseSuccess : ParseFailure;
1159 exprs.push_back(elt);
1160 return res;
1161 };
1162
1163 // Parse a multi-dimensional affine expression (a comma-separated list of 1-d
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001164 // affine expressions); the list cannot be empty.
1165 // Grammar: multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner40746442018-07-21 14:32:09 -07001166 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt, false))
Chris Lattner7121b802018-07-04 20:45:39 -07001167 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001168
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001169 // Parse optional range sizes.
Uday Bondhugula1e500b42018-07-12 18:04:04 -07001170 // range-sizes ::= (`size` `(` dim-size (`,` dim-size)* `)`)?
1171 // dim-size ::= affine-expr | `min` `(` affine-expr (`,` affine-expr)+ `)`
1172 // TODO(bondhugula): support for min of several affine expressions.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001173 // TODO: check if sizes are non-negative whenever they are constant.
1174 SmallVector<AffineExpr *, 4> rangeSizes;
1175 if (consumeIf(Token::kw_size)) {
1176 // Location of the l_paren token (if it exists) for error reporting later.
1177 auto loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001178 if (parseToken(Token::l_paren, "expected '(' at start of affine map range"))
1179 return nullptr;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001180
1181 auto parseRangeSize = [&]() -> ParseResult {
Chris Lattner413db6a2018-07-25 12:55:50 -07001182 auto loc = getToken().getLoc();
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001183 auto *elt = parseAffineExpr();
Chris Lattner413db6a2018-07-25 12:55:50 -07001184 if (!elt)
1185 return ParseFailure;
1186
1187 if (!elt->isSymbolicOrConstant())
1188 return emitError(loc,
1189 "size expressions cannot refer to dimension values");
1190
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001191 rangeSizes.push_back(elt);
Chris Lattner413db6a2018-07-25 12:55:50 -07001192 return ParseSuccess;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001193 };
1194
Chris Lattner40746442018-07-21 14:32:09 -07001195 if (parseCommaSeparatedListUntil(Token::r_paren, parseRangeSize, false))
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001196 return nullptr;
1197 if (exprs.size() > rangeSizes.size())
1198 return (emitError(loc, "fewer range sizes than range expressions"),
1199 nullptr);
1200 if (exprs.size() < rangeSizes.size())
1201 return (emitError(loc, "more range sizes than range expressions"),
1202 nullptr);
1203 }
1204
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001205 // Parsed a valid affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001206 return builder.getAffineMap(numDims, numSymbols, exprs, rangeSizes);
MLIR Teamf85a6262018-06-27 11:03:08 -07001207}
1208
Chris Lattner2e595eb2018-07-10 10:08:27 -07001209AffineMap *Parser::parseAffineMapInline() {
Uday Bondhugulabc535622018-08-07 14:24:38 -07001210 return AffineParser(state).parseAffineMapInline();
Chris Lattner2e595eb2018-07-10 10:08:27 -07001211}
1212
MLIR Team718c82f2018-07-16 09:45:22 -07001213AffineMap *Parser::parseAffineMapReference() {
1214 if (getToken().is(Token::hash_identifier)) {
1215 // Parse affine map identifier and verify that it exists.
1216 StringRef affineMapId = getTokenSpelling().drop_front();
1217 if (getState().affineMapDefinitions.count(affineMapId) == 0)
1218 return (emitError("undefined affine map id '" + affineMapId + "'"),
1219 nullptr);
1220 consumeToken(Token::hash_identifier);
1221 return getState().affineMapDefinitions[affineMapId];
1222 }
1223 // Try to parse inline affine map.
1224 return parseAffineMapInline();
1225}
1226
MLIR Teamf85a6262018-06-27 11:03:08 -07001227//===----------------------------------------------------------------------===//
Chris Lattner7f9cc272018-07-19 08:35:28 -07001228// FunctionParser
Chris Lattner4c95a502018-06-23 16:03:42 -07001229//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001230
Chris Lattner7f9cc272018-07-19 08:35:28 -07001231namespace {
1232/// This class contains parser state that is common across CFG and ML functions,
1233/// notably for dealing with operations and SSA values.
1234class FunctionParser : public Parser {
1235public:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001236 enum class Kind { CFGFunc, MLFunc };
1237
1238 Kind getKind() const { return kind; }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001239
Chris Lattner6119d382018-07-20 18:41:34 -07001240 /// After the function is finished parsing, this function checks to see if
1241 /// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001242 ParseResult finalizeFunction(Function *func, SMLoc loc);
Chris Lattner6119d382018-07-20 18:41:34 -07001243
1244 /// This represents a use of an SSA value in the program. The first two
1245 /// entries in the tuple are the name and result number of a reference. The
1246 /// third is the location of the reference, which is used in case this ends up
1247 /// being a use of an undefined value.
1248 struct SSAUseInfo {
1249 StringRef name; // Value name, e.g. %42 or %abc
1250 unsigned number; // Number, specified with #12
1251 SMLoc loc; // Location of first definition or use.
1252 };
Chris Lattner7f9cc272018-07-19 08:35:28 -07001253
1254 /// Given a reference to an SSA value and its type, return a reference. This
1255 /// returns null on failure.
1256 SSAValue *resolveSSAUse(SSAUseInfo useInfo, Type *type);
1257
1258 /// Register a definition of a value with the symbol table.
1259 ParseResult addDefinition(SSAUseInfo useInfo, SSAValue *value);
1260
1261 // SSA parsing productions.
1262 ParseResult parseSSAUse(SSAUseInfo &result);
Chris Lattner40746442018-07-21 14:32:09 -07001263 ParseResult parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results);
James Molloy61a656c2018-07-22 15:45:24 -07001264
1265 template <typename ResultType>
1266 ResultType parseSSADefOrUseAndType(
1267 const std::function<ResultType(SSAUseInfo, Type *)> &action);
1268
1269 SSAValue *parseSSAUseAndType() {
1270 return parseSSADefOrUseAndType<SSAValue *>(
1271 [&](SSAUseInfo useInfo, Type *type) -> SSAValue * {
1272 return resolveSSAUse(useInfo, type);
1273 });
1274 }
Chris Lattner40746442018-07-21 14:32:09 -07001275
1276 template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001277 ParseResult
Chris Lattner2c402672018-07-23 11:56:17 -07001278 parseOptionalSSAUseAndTypeList(SmallVectorImpl<ValueTy *> &results,
1279 bool isParenthesized);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001280
1281 // Operations
1282 ParseResult parseOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner85ee1512018-07-25 11:15:20 -07001283 Operation *parseVerboseOperation(const CreateOperationFunction &createOpFunc);
1284 Operation *parseCustomOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001285
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001286protected:
1287 FunctionParser(ParserState &state, Kind kind) : Parser(state), kind(kind) {}
1288
Chris Lattner7f9cc272018-07-19 08:35:28 -07001289private:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001290 /// Kind indicates if this is CFG or ML function parser.
1291 Kind kind;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001292 /// This keeps track of all of the SSA values we are tracking, indexed by
Chris Lattner6119d382018-07-20 18:41:34 -07001293 /// their name. This has one entry per result number.
1294 llvm::StringMap<SmallVector<std::pair<SSAValue *, SMLoc>, 1>> values;
1295
1296 /// These are all of the placeholders we've made along with the location of
1297 /// their first reference, to allow checking for use of undefined values.
1298 DenseMap<SSAValue *, SMLoc> forwardReferencePlaceholders;
1299
1300 SSAValue *createForwardReferencePlaceholder(SMLoc loc, Type *type);
1301
1302 /// Return true if this is a forward reference.
1303 bool isForwardReferencePlaceholder(SSAValue *value) {
1304 return forwardReferencePlaceholders.count(value);
1305 }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001306};
1307} // end anonymous namespace
1308
Chris Lattner6119d382018-07-20 18:41:34 -07001309/// Create and remember a new placeholder for a forward reference.
1310SSAValue *FunctionParser::createForwardReferencePlaceholder(SMLoc loc,
1311 Type *type) {
1312 // Forward references are always created as instructions, even in ML
1313 // functions, because we just need something with a def/use chain.
1314 //
1315 // We create these placeholders as having an empty name, which we know cannot
1316 // be created through normal user input, allowing us to distinguish them.
1317 auto name = Identifier::get("placeholder", getContext());
1318 auto *inst = OperationInst::create(name, /*operands*/ {}, type, /*attrs*/ {},
1319 getContext());
1320 forwardReferencePlaceholders[inst->getResult(0)] = loc;
1321 return inst->getResult(0);
1322}
1323
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001324/// Given an unbound reference to an SSA value and its type, return the value
Chris Lattner7f9cc272018-07-19 08:35:28 -07001325/// it specifies. This returns null on failure.
1326SSAValue *FunctionParser::resolveSSAUse(SSAUseInfo useInfo, Type *type) {
Chris Lattner6119d382018-07-20 18:41:34 -07001327 auto &entries = values[useInfo.name];
1328
Chris Lattner7f9cc272018-07-19 08:35:28 -07001329 // If we have already seen a value of this name, return it.
Chris Lattner6119d382018-07-20 18:41:34 -07001330 if (useInfo.number < entries.size() && entries[useInfo.number].first) {
1331 auto *result = entries[useInfo.number].first;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001332 // Check that the type matches the other uses.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001333 if (result->getType() == type)
1334 return result;
1335
Chris Lattner6119d382018-07-20 18:41:34 -07001336 emitError(useInfo.loc, "use of value '" + useInfo.name.str() +
1337 "' expects different type than prior uses");
1338 emitError(entries[useInfo.number].second, "prior use here");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001339 return nullptr;
1340 }
1341
Chris Lattner6119d382018-07-20 18:41:34 -07001342 // Make sure we have enough slots for this.
1343 if (entries.size() <= useInfo.number)
1344 entries.resize(useInfo.number + 1);
1345
1346 // If the value has already been defined and this is an overly large result
1347 // number, diagnose that.
1348 if (entries[0].first && !isForwardReferencePlaceholder(entries[0].first))
1349 return (emitError(useInfo.loc, "reference to invalid result number"),
1350 nullptr);
1351
Tatiana Shpeismand880b352018-07-31 23:14:16 -07001352 // Otherwise, this is a forward reference. If we are in ML function return
1353 // an error. In CFG function, create a placeholder and remember
1354 // that we did so.
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001355 if (getKind() == Kind::MLFunc)
1356 return (
1357 emitError(useInfo.loc, "use of undefined SSA value " + useInfo.name),
1358 nullptr);
1359
Chris Lattner6119d382018-07-20 18:41:34 -07001360 auto *result = createForwardReferencePlaceholder(useInfo.loc, type);
1361 entries[useInfo.number].first = result;
1362 entries[useInfo.number].second = useInfo.loc;
1363 return result;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001364}
1365
1366/// Register a definition of a value with the symbol table.
1367ParseResult FunctionParser::addDefinition(SSAUseInfo useInfo, SSAValue *value) {
Chris Lattner6119d382018-07-20 18:41:34 -07001368 auto &entries = values[useInfo.name];
Chris Lattner7f9cc272018-07-19 08:35:28 -07001369
Chris Lattner6119d382018-07-20 18:41:34 -07001370 // Make sure there is a slot for this value.
1371 if (entries.size() <= useInfo.number)
1372 entries.resize(useInfo.number + 1);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001373
Chris Lattner6119d382018-07-20 18:41:34 -07001374 // If we already have an entry for this, check to see if it was a definition
1375 // or a forward reference.
1376 if (auto *existing = entries[useInfo.number].first) {
1377 if (!isForwardReferencePlaceholder(existing)) {
1378 emitError(useInfo.loc,
1379 "redefinition of SSA value '" + useInfo.name + "'");
1380 return emitError(entries[useInfo.number].second,
1381 "previously defined here");
1382 }
1383
1384 // If it was a forward reference, update everything that used it to use the
1385 // actual definition instead, delete the forward ref, and remove it from our
1386 // set of forward references we track.
1387 existing->replaceAllUsesWith(value);
1388 existing->getDefiningInst()->destroy();
1389 forwardReferencePlaceholders.erase(existing);
1390 }
1391
1392 entries[useInfo.number].first = value;
1393 entries[useInfo.number].second = useInfo.loc;
1394 return ParseSuccess;
1395}
1396
1397/// After the function is finished parsing, this function checks to see if
1398/// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001399ParseResult FunctionParser::finalizeFunction(Function *func, SMLoc loc) {
Chris Lattner6119d382018-07-20 18:41:34 -07001400 // Check for any forward references that are left. If we find any, error out.
1401 if (!forwardReferencePlaceholders.empty()) {
1402 SmallVector<std::pair<const char *, SSAValue *>, 4> errors;
1403 // Iteration over the map isn't determinstic, so sort by source location.
1404 for (auto entry : forwardReferencePlaceholders)
1405 errors.push_back({entry.second.getPointer(), entry.first});
1406 llvm::array_pod_sort(errors.begin(), errors.end());
1407
1408 for (auto entry : errors)
1409 emitError(SMLoc::getFromPointer(entry.first),
1410 "use of undeclared SSA value name");
1411 return ParseFailure;
1412 }
1413
Chris Lattner40746442018-07-21 14:32:09 -07001414 // Run the verifier on this function. If an error is detected, report it.
1415 std::string errorString;
1416 if (func->verify(&errorString))
1417 return emitError(loc, errorString);
1418
Chris Lattner6119d382018-07-20 18:41:34 -07001419 return ParseSuccess;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001420}
1421
Chris Lattner78276e32018-07-07 15:48:26 -07001422/// Parse a SSA operand for an instruction or statement.
1423///
James Molloy61a656c2018-07-22 15:45:24 -07001424/// ssa-use ::= ssa-id
Chris Lattner78276e32018-07-07 15:48:26 -07001425///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001426ParseResult FunctionParser::parseSSAUse(SSAUseInfo &result) {
Chris Lattner6119d382018-07-20 18:41:34 -07001427 result.name = getTokenSpelling();
1428 result.number = 0;
1429 result.loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001430 if (parseToken(Token::percent_identifier, "expected SSA operand"))
1431 return ParseFailure;
Chris Lattner6119d382018-07-20 18:41:34 -07001432
1433 // If we have an affine map ID, it is a result number.
1434 if (getToken().is(Token::hash_identifier)) {
1435 if (auto value = getToken().getHashIdentifierNumber())
1436 result.number = value.getValue();
1437 else
1438 return emitError("invalid SSA value result number");
1439 consumeToken(Token::hash_identifier);
1440 }
1441
Chris Lattner7f9cc272018-07-19 08:35:28 -07001442 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001443}
1444
1445/// Parse a (possibly empty) list of SSA operands.
1446///
1447/// ssa-use-list ::= ssa-use (`,` ssa-use)*
1448/// ssa-use-list-opt ::= ssa-use-list?
1449///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001450ParseResult
Chris Lattner40746442018-07-21 14:32:09 -07001451FunctionParser::parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results) {
Chris Lattner85ee1512018-07-25 11:15:20 -07001452 if (getToken().isNot(Token::percent_identifier))
Chris Lattner40746442018-07-21 14:32:09 -07001453 return ParseSuccess;
1454 return parseCommaSeparatedList([&]() -> ParseResult {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001455 SSAUseInfo result;
1456 if (parseSSAUse(result))
1457 return ParseFailure;
1458 results.push_back(result);
1459 return ParseSuccess;
1460 });
Chris Lattner78276e32018-07-07 15:48:26 -07001461}
1462
1463/// Parse an SSA use with an associated type.
1464///
1465/// ssa-use-and-type ::= ssa-use `:` type
James Molloy61a656c2018-07-22 15:45:24 -07001466template <typename ResultType>
1467ResultType FunctionParser::parseSSADefOrUseAndType(
1468 const std::function<ResultType(SSAUseInfo, Type *)> &action) {
Chris Lattner78276e32018-07-07 15:48:26 -07001469
Chris Lattnerf7702a62018-07-23 17:30:01 -07001470 SSAUseInfo useInfo;
1471 if (parseSSAUse(useInfo) ||
1472 parseToken(Token::colon, "expected ':' and type for SSA operand"))
1473 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001474
Chris Lattner7f9cc272018-07-19 08:35:28 -07001475 auto *type = parseType();
1476 if (!type)
1477 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001478
James Molloy61a656c2018-07-22 15:45:24 -07001479 return action(useInfo, type);
Chris Lattner78276e32018-07-07 15:48:26 -07001480}
1481
Chris Lattner2c402672018-07-23 11:56:17 -07001482/// Parse a (possibly empty) list of SSA operands, followed by a colon, then
1483/// followed by a type list. If hasParens is true, then the operands are
1484/// surrounded by parens.
Chris Lattner78276e32018-07-07 15:48:26 -07001485///
Chris Lattner2c402672018-07-23 11:56:17 -07001486/// ssa-use-and-type-list[parens]
1487/// ::= `(` ssa-use-list `)` ':' type-list-no-parens
1488///
1489/// ssa-use-and-type-list[!parens]
1490/// ::= ssa-use-list ':' type-list-no-parens
Chris Lattner78276e32018-07-07 15:48:26 -07001491///
Chris Lattner40746442018-07-21 14:32:09 -07001492template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001493ParseResult FunctionParser::parseOptionalSSAUseAndTypeList(
Chris Lattner2c402672018-07-23 11:56:17 -07001494 SmallVectorImpl<ValueTy *> &results, bool isParenthesized) {
1495
1496 // If we are in the parenthesized form and no paren exists, then we succeed
1497 // with an empty list.
1498 if (isParenthesized && !consumeIf(Token::l_paren))
Chris Lattner40746442018-07-21 14:32:09 -07001499 return ParseSuccess;
1500
Chris Lattner2c402672018-07-23 11:56:17 -07001501 SmallVector<SSAUseInfo, 4> valueIDs;
1502 if (parseOptionalSSAUseList(valueIDs))
Chris Lattner7f9cc272018-07-19 08:35:28 -07001503 return ParseFailure;
Chris Lattner2c402672018-07-23 11:56:17 -07001504
1505 if (isParenthesized && !consumeIf(Token::r_paren))
1506 return emitError("expected ')' in operand list");
1507
1508 // If there were no operands, then there is no colon or type lists.
1509 if (valueIDs.empty())
1510 return ParseSuccess;
1511
Chris Lattner2c402672018-07-23 11:56:17 -07001512 SmallVector<Type *, 4> types;
Chris Lattnerf7702a62018-07-23 17:30:01 -07001513 if (parseToken(Token::colon, "expected ':' in operand list") ||
1514 parseTypeListNoParens(types))
Chris Lattner2c402672018-07-23 11:56:17 -07001515 return ParseFailure;
1516
1517 if (valueIDs.size() != types.size())
1518 return emitError("expected " + Twine(valueIDs.size()) +
1519 " types to match operand list");
1520
1521 results.reserve(valueIDs.size());
1522 for (unsigned i = 0, e = valueIDs.size(); i != e; ++i) {
1523 if (auto *value = resolveSSAUse(valueIDs[i], types[i]))
1524 results.push_back(cast<ValueTy>(value));
1525 else
1526 return ParseFailure;
1527 }
1528
1529 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001530}
1531
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001532/// Parse the CFG or MLFunc operation.
1533///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001534/// operation ::=
1535/// (ssa-id `=`)? string '(' ssa-use-list? ')' attribute-dict?
1536/// `:` function-type
1537///
1538ParseResult
Chris Lattner7f9cc272018-07-19 08:35:28 -07001539FunctionParser::parseOperation(const CreateOperationFunction &createOpFunc) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001540 auto loc = getToken().getLoc();
1541
1542 StringRef resultID;
1543 if (getToken().is(Token::percent_identifier)) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001544 resultID = getTokenSpelling();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001545 consumeToken(Token::percent_identifier);
Chris Lattnerf7702a62018-07-23 17:30:01 -07001546 if (parseToken(Token::equal, "expected '=' after SSA name"))
1547 return ParseFailure;
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001548 }
1549
Chris Lattner85ee1512018-07-25 11:15:20 -07001550 Operation *op;
1551 if (getToken().is(Token::bare_identifier) || getToken().isKeyword())
1552 op = parseCustomOperation(createOpFunc);
1553 else if (getToken().is(Token::string))
1554 op = parseVerboseOperation(createOpFunc);
1555 else
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001556 return emitError("expected operation name in quotes");
1557
Chris Lattner85ee1512018-07-25 11:15:20 -07001558 // If parsing of the basic operation failed, then this whole thing fails.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001559 if (!op)
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001560 return ParseFailure;
1561
Chris Lattnerf7bdf952018-08-05 21:12:29 -07001562 // Apply location information to the instruction.
1563 // TODO(clattner): make this more principled. We shouldn't overwrite existing
1564 // location info, we should use a better serialized form, and we shouldn't
1565 // be using the :location attribute. This is also pretty inefficient.
1566 {
1567 auto &sourceMgr = getSourceMgr();
1568 auto fileID = sourceMgr.FindBufferContainingLoc(loc);
1569 auto *srcBuffer = sourceMgr.getMemoryBuffer(fileID);
1570 unsigned locationEncoding = loc.getPointer() - srcBuffer->getBufferStart();
1571 op->setAttr(builder.getIdentifier(":location"),
1572 builder.getIntegerAttr(locationEncoding));
1573 }
1574
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001575 // We just parsed an operation. If it is a recognized one, verify that it
1576 // is structurally as we expect. If not, produce an error with a reasonable
1577 // source location.
Chris Lattner95865062018-08-01 10:18:59 -07001578 if (auto *opInfo = op->getAbstractOperation()) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001579 if (auto error = opInfo->verifyInvariants(op))
Chris Lattner9361fb32018-07-24 08:34:58 -07001580 return emitError(loc, Twine("'") + op->getName().str() + "' op " + error);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001581 }
1582
Chris Lattner7f9cc272018-07-19 08:35:28 -07001583 // If the instruction had a name, register it.
1584 if (!resultID.empty()) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001585 if (op->getNumResults() == 0)
1586 return emitError(loc, "cannot name an operation with no results");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001587
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001588 for (unsigned i = 0, e = op->getNumResults(); i != e; ++i)
Chris Lattner2b97d502018-08-06 14:19:46 -07001589 if (addDefinition({resultID, i, loc}, op->getResult(i)))
1590 return ParseFailure;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001591 }
1592
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001593 return ParseSuccess;
1594}
Chris Lattnere79379a2018-06-22 10:39:19 -07001595
Chris Lattner85ee1512018-07-25 11:15:20 -07001596Operation *FunctionParser::parseVerboseOperation(
1597 const CreateOperationFunction &createOpFunc) {
1598 auto name = getToken().getStringValue();
1599 if (name.empty())
1600 return (emitError("empty operation name is invalid"), nullptr);
1601
1602 consumeToken(Token::string);
1603
Chris Lattner992a1272018-08-07 12:02:37 -07001604 OperationState result(builder.getIdentifier(name));
1605
Chris Lattner85ee1512018-07-25 11:15:20 -07001606 // Parse the operand list.
1607 SmallVector<SSAUseInfo, 8> operandInfos;
1608
1609 if (parseToken(Token::l_paren, "expected '(' to start operand list") ||
1610 parseOptionalSSAUseList(operandInfos) ||
1611 parseToken(Token::r_paren, "expected ')' to end operand list")) {
1612 return nullptr;
1613 }
1614
Chris Lattner85ee1512018-07-25 11:15:20 -07001615 if (getToken().is(Token::l_brace)) {
Chris Lattner992a1272018-08-07 12:02:37 -07001616 if (parseAttributeDict(result.attributes))
Chris Lattner85ee1512018-07-25 11:15:20 -07001617 return nullptr;
1618 }
1619
1620 if (parseToken(Token::colon, "expected ':' followed by instruction type"))
1621 return nullptr;
1622
1623 auto typeLoc = getToken().getLoc();
1624 auto type = parseType();
1625 if (!type)
1626 return nullptr;
1627 auto fnType = dyn_cast<FunctionType>(type);
1628 if (!fnType)
1629 return (emitError(typeLoc, "expected function type"), nullptr);
1630
Chris Lattner992a1272018-08-07 12:02:37 -07001631 result.types.append(fnType->getResults().begin(), fnType->getResults().end());
1632
Chris Lattner85ee1512018-07-25 11:15:20 -07001633 // Check that we have the right number of types for the operands.
1634 auto operandTypes = fnType->getInputs();
1635 if (operandTypes.size() != operandInfos.size()) {
1636 auto plural = "s"[operandInfos.size() == 1];
1637 return (emitError(typeLoc, "expected " + llvm::utostr(operandInfos.size()) +
1638 " operand type" + plural + " but had " +
1639 llvm::utostr(operandTypes.size())),
1640 nullptr);
1641 }
1642
1643 // Resolve all of the operands.
Chris Lattner85ee1512018-07-25 11:15:20 -07001644 for (unsigned i = 0, e = operandInfos.size(); i != e; ++i) {
Chris Lattner992a1272018-08-07 12:02:37 -07001645 result.operands.push_back(resolveSSAUse(operandInfos[i], operandTypes[i]));
1646 if (!result.operands.back())
Chris Lattner85ee1512018-07-25 11:15:20 -07001647 return nullptr;
1648 }
1649
Chris Lattner992a1272018-08-07 12:02:37 -07001650 return createOpFunc(result);
Chris Lattner85ee1512018-07-25 11:15:20 -07001651}
1652
1653namespace {
1654class CustomOpAsmParser : public OpAsmParser {
1655public:
1656 CustomOpAsmParser(SMLoc nameLoc, StringRef opName, FunctionParser &parser)
1657 : nameLoc(nameLoc), opName(opName), parser(parser) {}
1658
1659 /// This is an internal helper to parser a colon, we don't want to expose
1660 /// this to clients.
1661 bool internalParseColon(llvm::SMLoc *loc) {
1662 if (loc)
1663 *loc = parser.getToken().getLoc();
1664 return parser.parseToken(Token::colon, "expected ':'");
1665 }
1666
1667 //===--------------------------------------------------------------------===//
1668 // High level parsing methods.
1669 //===--------------------------------------------------------------------===//
1670
1671 bool parseComma(llvm::SMLoc *loc = nullptr) override {
1672 if (loc)
1673 *loc = parser.getToken().getLoc();
1674 return parser.parseToken(Token::comma, "expected ','");
1675 }
1676
1677 bool parseColonType(Type *&result, llvm::SMLoc *loc = nullptr) override {
1678 return internalParseColon(loc) || !(result = parser.parseType());
1679 }
1680
1681 bool parseColonTypeList(SmallVectorImpl<Type *> &result,
1682 llvm::SMLoc *loc = nullptr) override {
1683 if (internalParseColon(loc))
1684 return true;
1685
1686 do {
1687 if (auto *type = parser.parseType())
1688 result.push_back(type);
1689 else
1690 return true;
1691
1692 } while (parser.consumeIf(Token::comma));
1693 return false;
1694 }
1695
Chris Lattner85cf26d2018-08-02 16:54:36 -07001696 /// Parse an arbitrary attribute and return it in result. This also adds the
1697 /// attribute to the specified attribute list with the specified name. this
1698 /// captures the location of the attribute in 'loc' if it is non-null.
1699 bool parseAttribute(Attribute *&result, const char *attrName,
1700 SmallVectorImpl<NamedAttribute> &attrs,
1701 llvm::SMLoc *loc = nullptr) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001702 if (loc)
1703 *loc = parser.getToken().getLoc();
1704 result = parser.parseAttribute();
Chris Lattner85cf26d2018-08-02 16:54:36 -07001705 if (!result)
1706 return true;
1707
1708 attrs.push_back(
1709 NamedAttribute(parser.builder.getIdentifier(attrName), result));
1710 return false;
1711 }
1712
1713 /// If a named attribute list is present, parse is into result.
1714 bool parseOptionalAttributeDict(SmallVectorImpl<NamedAttribute> &result,
1715 llvm::SMLoc *loc = nullptr) override {
1716 if (parser.getToken().isNot(Token::l_brace))
1717 return false;
1718 if (loc)
1719 *loc = parser.getToken().getLoc();
1720 return parser.parseAttributeDict(result) == ParseFailure;
Chris Lattner85ee1512018-07-25 11:15:20 -07001721 }
1722
1723 bool parseOperand(OperandType &result) override {
1724 FunctionParser::SSAUseInfo useInfo;
1725 if (parser.parseSSAUse(useInfo))
1726 return true;
1727
1728 result = {useInfo.loc, useInfo.name, useInfo.number};
1729 return false;
1730 }
1731
1732 bool parseOperandList(SmallVectorImpl<OperandType> &result,
1733 int requiredOperandCount = -1,
Chris Lattner85cf26d2018-08-02 16:54:36 -07001734 Delimiter delimiter = Delimiter::None) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001735 auto startLoc = parser.getToken().getLoc();
1736
Chris Lattner85cf26d2018-08-02 16:54:36 -07001737 // Handle delimiters.
1738 switch (delimiter) {
1739 case Delimiter::None:
Chris Lattner85ee1512018-07-25 11:15:20 -07001740 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001741 case Delimiter::OptionalParen:
Chris Lattner3164ae62018-07-28 09:36:25 -07001742 if (parser.getToken().isNot(Token::l_paren))
1743 return false;
1744 LLVM_FALLTHROUGH;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001745 case Delimiter::Paren:
Chris Lattner85ee1512018-07-25 11:15:20 -07001746 if (parser.parseToken(Token::l_paren, "expected '(' in operand list"))
1747 return true;
1748 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001749 case Delimiter::OptionalSquare:
Chris Lattner3164ae62018-07-28 09:36:25 -07001750 if (parser.getToken().isNot(Token::l_square))
1751 return false;
1752 LLVM_FALLTHROUGH;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001753 case Delimiter::Square:
Chris Lattner85ee1512018-07-25 11:15:20 -07001754 if (parser.parseToken(Token::l_square, "expected '[' in operand list"))
1755 return true;
1756 break;
1757 }
1758
1759 // Check for zero operands.
1760 if (parser.getToken().is(Token::percent_identifier)) {
1761 do {
1762 OperandType operand;
1763 if (parseOperand(operand))
1764 return true;
1765 result.push_back(operand);
1766 } while (parser.consumeIf(Token::comma));
1767 }
1768
Chris Lattner85cf26d2018-08-02 16:54:36 -07001769 // Handle delimiters. If we reach here, the optional delimiters were
Chris Lattner3164ae62018-07-28 09:36:25 -07001770 // present, so we need to parse their closing one.
Chris Lattner85cf26d2018-08-02 16:54:36 -07001771 switch (delimiter) {
1772 case Delimiter::None:
Chris Lattner85ee1512018-07-25 11:15:20 -07001773 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001774 case Delimiter::OptionalParen:
1775 case Delimiter::Paren:
Chris Lattner85ee1512018-07-25 11:15:20 -07001776 if (parser.parseToken(Token::r_paren, "expected ')' in operand list"))
1777 return true;
1778 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001779 case Delimiter::OptionalSquare:
1780 case Delimiter::Square:
Chris Lattner85ee1512018-07-25 11:15:20 -07001781 if (parser.parseToken(Token::r_square, "expected ']' in operand list"))
1782 return true;
1783 break;
1784 }
1785
1786 if (requiredOperandCount != -1 && result.size() != requiredOperandCount)
1787 emitError(startLoc,
1788 "expected " + Twine(requiredOperandCount) + " operands");
1789 return false;
1790 }
1791
1792 //===--------------------------------------------------------------------===//
1793 // Methods for interacting with the parser
1794 //===--------------------------------------------------------------------===//
1795
1796 Builder &getBuilder() const override { return parser.builder; }
1797
1798 llvm::SMLoc getNameLoc() const override { return nameLoc; }
1799
1800 bool resolveOperand(OperandType operand, Type *type,
Chris Lattner8bdbebf2018-08-08 11:02:58 -07001801 SmallVectorImpl<SSAValue *> &result) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001802 FunctionParser::SSAUseInfo operandInfo = {operand.name, operand.number,
1803 operand.location};
Chris Lattner8bdbebf2018-08-08 11:02:58 -07001804 if (auto *value = parser.resolveSSAUse(operandInfo, type)) {
1805 result.push_back(value);
1806 return false;
1807 }
1808 return true;
Chris Lattner85ee1512018-07-25 11:15:20 -07001809 }
1810
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001811 /// Emit a diagnostic at the specified location and return true.
1812 bool emitError(llvm::SMLoc loc, const Twine &message) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001813 parser.emitError(loc, "custom op '" + Twine(opName) + "' " + message);
1814 emittedError = true;
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001815 return true;
Chris Lattner85ee1512018-07-25 11:15:20 -07001816 }
1817
1818 bool didEmitError() const { return emittedError; }
1819
1820private:
1821 SMLoc nameLoc;
1822 StringRef opName;
1823 FunctionParser &parser;
1824 bool emittedError = false;
1825};
1826} // end anonymous namespace.
1827
1828Operation *FunctionParser::parseCustomOperation(
1829 const CreateOperationFunction &createOpFunc) {
1830 auto opLoc = getToken().getLoc();
1831 auto opName = getTokenSpelling();
1832 CustomOpAsmParser opAsmParser(opLoc, opName, *this);
1833
1834 auto *opDefinition = getOperationSet().lookup(opName);
1835 if (!opDefinition) {
1836 opAsmParser.emitError(opLoc, "is unknown");
1837 return nullptr;
1838 }
1839
1840 consumeToken();
1841
1842 // Have the op implementation take a crack and parsing this.
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001843 OperationState opState(builder.getIdentifier(opName));
1844 if (opDefinition->parseAssembly(&opAsmParser, &opState))
1845 return nullptr;
Chris Lattner85ee1512018-07-25 11:15:20 -07001846
1847 // If it emitted an error, we failed.
1848 if (opAsmParser.didEmitError())
1849 return nullptr;
1850
1851 // Otherwise, we succeeded. Use the state it parsed as our op information.
Chris Lattner992a1272018-08-07 12:02:37 -07001852 return createOpFunc(opState);
Chris Lattner85ee1512018-07-25 11:15:20 -07001853}
1854
Chris Lattner48af7d12018-07-09 19:05:38 -07001855//===----------------------------------------------------------------------===//
1856// CFG Functions
1857//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001858
Chris Lattner4c95a502018-06-23 16:03:42 -07001859namespace {
Chris Lattner48af7d12018-07-09 19:05:38 -07001860/// This is a specialized parser for CFGFunction's, maintaining the state
1861/// transient to their bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001862class CFGFunctionParser : public FunctionParser {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001863public:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001864 CFGFunctionParser(ParserState &state, CFGFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001865 : FunctionParser(state, Kind::CFGFunc), function(function),
1866 builder(function) {}
Chris Lattner2e595eb2018-07-10 10:08:27 -07001867
1868 ParseResult parseFunctionBody();
1869
1870private:
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001871 CFGFunction *function;
James Molloy0ff71542018-07-23 16:56:32 -07001872 llvm::StringMap<std::pair<BasicBlock *, SMLoc>> blocksByName;
Chris Lattner48af7d12018-07-09 19:05:38 -07001873
1874 /// This builder intentionally shadows the builder in the base class, with a
1875 /// more specific builder type.
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001876 CFGFuncBuilder builder;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001877
Chris Lattner4c95a502018-06-23 16:03:42 -07001878 /// Get the basic block with the specified name, creating it if it doesn't
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001879 /// already exist. The location specified is the point of use, which allows
1880 /// us to diagnose references to blocks that are not defined precisely.
1881 BasicBlock *getBlockNamed(StringRef name, SMLoc loc) {
1882 auto &blockAndLoc = blocksByName[name];
1883 if (!blockAndLoc.first) {
Chris Lattner3a467cc2018-07-01 20:28:00 -07001884 blockAndLoc.first = new BasicBlock();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001885 blockAndLoc.second = loc;
Chris Lattner4c95a502018-06-23 16:03:42 -07001886 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001887 return blockAndLoc.first;
Chris Lattner4c95a502018-06-23 16:03:42 -07001888 }
Chris Lattner48af7d12018-07-09 19:05:38 -07001889
James Molloy61a656c2018-07-22 15:45:24 -07001890 ParseResult
1891 parseOptionalBasicBlockArgList(SmallVectorImpl<BBArgument *> &results,
1892 BasicBlock *owner);
James Molloy4f788372018-07-24 15:01:27 -07001893 ParseResult parseBranchBlockAndUseList(BasicBlock *&block,
1894 SmallVectorImpl<CFGValue *> &values);
James Molloy61a656c2018-07-22 15:45:24 -07001895
Chris Lattner48af7d12018-07-09 19:05:38 -07001896 ParseResult parseBasicBlock();
1897 OperationInst *parseCFGOperation();
1898 TerminatorInst *parseTerminator();
Chris Lattner4c95a502018-06-23 16:03:42 -07001899};
1900} // end anonymous namespace
1901
James Molloy61a656c2018-07-22 15:45:24 -07001902/// Parse a (possibly empty) list of SSA operands with types as basic block
Chris Lattner2c402672018-07-23 11:56:17 -07001903/// arguments.
James Molloy61a656c2018-07-22 15:45:24 -07001904///
1905/// ssa-id-and-type-list ::= ssa-id-and-type (`,` ssa-id-and-type)*
1906///
1907ParseResult CFGFunctionParser::parseOptionalBasicBlockArgList(
1908 SmallVectorImpl<BBArgument *> &results, BasicBlock *owner) {
1909 if (getToken().is(Token::r_brace))
1910 return ParseSuccess;
1911
1912 return parseCommaSeparatedList([&]() -> ParseResult {
1913 auto type = parseSSADefOrUseAndType<Type *>(
1914 [&](SSAUseInfo useInfo, Type *type) -> Type * {
1915 BBArgument *arg = owner->addArgument(type);
Chris Lattner2b97d502018-08-06 14:19:46 -07001916 if (addDefinition(useInfo, arg))
James Molloy61a656c2018-07-22 15:45:24 -07001917 return nullptr;
1918 return type;
1919 });
1920 return type ? ParseSuccess : ParseFailure;
1921 });
1922}
1923
Chris Lattner48af7d12018-07-09 19:05:38 -07001924ParseResult CFGFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07001925 auto braceLoc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001926 if (parseToken(Token::l_brace, "expected '{' in CFG function"))
1927 return ParseFailure;
Chris Lattner48af7d12018-07-09 19:05:38 -07001928
1929 // Make sure we have at least one block.
1930 if (getToken().is(Token::r_brace))
1931 return emitError("CFG functions must have at least one basic block");
Chris Lattner4c95a502018-06-23 16:03:42 -07001932
1933 // Parse the list of blocks.
1934 while (!consumeIf(Token::r_brace))
Chris Lattner48af7d12018-07-09 19:05:38 -07001935 if (parseBasicBlock())
Chris Lattner4c95a502018-06-23 16:03:42 -07001936 return ParseFailure;
1937
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001938 // Verify that all referenced blocks were defined. Iteration over a
1939 // StringMap isn't determinstic, but this is good enough for our purposes.
Chris Lattner48af7d12018-07-09 19:05:38 -07001940 for (auto &elt : blocksByName) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001941 auto *bb = elt.second.first;
Chris Lattner3a467cc2018-07-01 20:28:00 -07001942 if (!bb->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001943 return emitError(elt.second.second,
James Molloy0ff71542018-07-23 16:56:32 -07001944 "reference to an undefined basic block '" + elt.first() +
1945 "'");
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001946 }
1947
Chris Lattner40746442018-07-21 14:32:09 -07001948 return finalizeFunction(function, braceLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001949}
1950
1951/// Basic block declaration.
1952///
1953/// basic-block ::= bb-label instruction* terminator-stmt
1954/// bb-label ::= bb-id bb-arg-list? `:`
1955/// bb-id ::= bare-id
1956/// bb-arg-list ::= `(` ssa-id-and-type-list? `)`
1957///
Chris Lattner48af7d12018-07-09 19:05:38 -07001958ParseResult CFGFunctionParser::parseBasicBlock() {
1959 SMLoc nameLoc = getToken().getLoc();
1960 auto name = getTokenSpelling();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001961 if (parseToken(Token::bare_identifier, "expected basic block name"))
1962 return ParseFailure;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001963
Chris Lattner48af7d12018-07-09 19:05:38 -07001964 auto *block = getBlockNamed(name, nameLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001965
1966 // If this block has already been parsed, then this is a redefinition with the
1967 // same block name.
Chris Lattner3a467cc2018-07-01 20:28:00 -07001968 if (block->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001969 return emitError(nameLoc, "redefinition of block '" + name.str() + "'");
1970
Chris Lattner78276e32018-07-07 15:48:26 -07001971 // If an argument list is present, parse it.
1972 if (consumeIf(Token::l_paren)) {
James Molloy61a656c2018-07-22 15:45:24 -07001973 SmallVector<BBArgument *, 8> bbArgs;
Chris Lattnerf7702a62018-07-23 17:30:01 -07001974 if (parseOptionalBasicBlockArgList(bbArgs, block) ||
1975 parseToken(Token::r_paren, "expected ')' to end argument list"))
Chris Lattner78276e32018-07-07 15:48:26 -07001976 return ParseFailure;
Chris Lattner78276e32018-07-07 15:48:26 -07001977 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001978
James Molloy61a656c2018-07-22 15:45:24 -07001979 // Add the block to the function.
1980 function->push_back(block);
1981
Chris Lattnerf7702a62018-07-23 17:30:01 -07001982 if (parseToken(Token::colon, "expected ':' after basic block name"))
1983 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07001984
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001985 // Set the insertion point to the block we want to insert new operations into.
Chris Lattner48af7d12018-07-09 19:05:38 -07001986 builder.setInsertionPoint(block);
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001987
Chris Lattner992a1272018-08-07 12:02:37 -07001988 auto createOpFunc = [&](const OperationState &result) -> Operation * {
1989 return builder.createOperation(result);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001990 };
1991
Chris Lattnered65a732018-06-28 20:45:33 -07001992 // Parse the list of operations that make up the body of the block.
James Molloy4f788372018-07-24 15:01:27 -07001993 while (getToken().isNot(Token::kw_return, Token::kw_br, Token::kw_cond_br)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001994 if (parseOperation(createOpFunc))
Chris Lattnered65a732018-06-28 20:45:33 -07001995 return ParseFailure;
1996 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001997
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001998 if (!parseTerminator())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001999 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07002000
2001 return ParseSuccess;
2002}
2003
James Molloy4f788372018-07-24 15:01:27 -07002004ParseResult CFGFunctionParser::parseBranchBlockAndUseList(
2005 BasicBlock *&block, SmallVectorImpl<CFGValue *> &values) {
2006 block = getBlockNamed(getTokenSpelling(), getToken().getLoc());
2007 if (parseToken(Token::bare_identifier, "expected basic block name"))
2008 return ParseFailure;
2009
2010 if (!consumeIf(Token::l_paren))
2011 return ParseSuccess;
2012 if (parseOptionalSSAUseAndTypeList(values, /*isParenthesized*/ false) ||
2013 parseToken(Token::r_paren, "expected ')' to close argument list"))
2014 return ParseFailure;
2015 return ParseSuccess;
2016}
2017
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002018/// Parse the terminator instruction for a basic block.
2019///
2020/// terminator-stmt ::= `br` bb-id branch-use-list?
Chris Lattner1604e472018-07-23 08:42:19 -07002021/// branch-use-list ::= `(` ssa-use-list `)` ':' type-list-no-parens
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002022/// terminator-stmt ::=
2023/// `cond_br` ssa-use `,` bb-id branch-use-list? `,` bb-id branch-use-list?
2024/// terminator-stmt ::= `return` ssa-use-and-type-list?
2025///
Chris Lattner48af7d12018-07-09 19:05:38 -07002026TerminatorInst *CFGFunctionParser::parseTerminator() {
2027 switch (getToken().getKind()) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002028 default:
Chris Lattner3a467cc2018-07-01 20:28:00 -07002029 return (emitError("expected terminator at end of basic block"), nullptr);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002030
Chris Lattner40746442018-07-21 14:32:09 -07002031 case Token::kw_return: {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002032 consumeToken(Token::kw_return);
Chris Lattner40746442018-07-21 14:32:09 -07002033
Chris Lattner2c402672018-07-23 11:56:17 -07002034 // Parse any operands.
2035 SmallVector<CFGValue *, 8> operands;
2036 if (parseOptionalSSAUseAndTypeList(operands, /*isParenthesized*/ false))
2037 return nullptr;
2038 return builder.createReturnInst(operands);
Chris Lattner40746442018-07-21 14:32:09 -07002039 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002040
2041 case Token::kw_br: {
2042 consumeToken(Token::kw_br);
James Molloy4f788372018-07-24 15:01:27 -07002043 BasicBlock *destBB;
2044 SmallVector<CFGValue *, 4> values;
2045 if (parseBranchBlockAndUseList(destBB, values))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002046 return nullptr;
Chris Lattner1604e472018-07-23 08:42:19 -07002047 auto branch = builder.createBranchInst(destBB);
James Molloy4f788372018-07-24 15:01:27 -07002048 branch->addOperands(values);
Chris Lattner1604e472018-07-23 08:42:19 -07002049 return branch;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002050 }
James Molloy4f788372018-07-24 15:01:27 -07002051
2052 case Token::kw_cond_br: {
2053 consumeToken(Token::kw_cond_br);
2054 SSAUseInfo ssaUse;
2055 if (parseSSAUse(ssaUse))
2056 return nullptr;
2057 auto *cond = resolveSSAUse(ssaUse, builder.getIntegerType(1));
2058 if (!cond)
2059 return (emitError("expected type was boolean (i1)"), nullptr);
2060 if (parseToken(Token::comma, "expected ',' in conditional branch"))
2061 return nullptr;
2062
2063 BasicBlock *trueBlock;
2064 SmallVector<CFGValue *, 4> trueOperands;
2065 if (parseBranchBlockAndUseList(trueBlock, trueOperands))
2066 return nullptr;
2067
2068 if (parseToken(Token::comma, "expected ',' in conditional branch"))
2069 return nullptr;
2070
2071 BasicBlock *falseBlock;
2072 SmallVector<CFGValue *, 4> falseOperands;
2073 if (parseBranchBlockAndUseList(falseBlock, falseOperands))
2074 return nullptr;
2075
2076 auto branch = builder.createCondBranchInst(cast<CFGValue>(cond), trueBlock,
2077 falseBlock);
2078 branch->addTrueOperands(trueOperands);
2079 branch->addFalseOperands(falseOperands);
2080 return branch;
2081 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002082 }
2083}
2084
Chris Lattner48af7d12018-07-09 19:05:38 -07002085//===----------------------------------------------------------------------===//
2086// ML Functions
2087//===----------------------------------------------------------------------===//
2088
2089namespace {
2090/// Refined parser for MLFunction bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07002091class MLFunctionParser : public FunctionParser {
Chris Lattner48af7d12018-07-09 19:05:38 -07002092public:
Chris Lattner48af7d12018-07-09 19:05:38 -07002093 MLFunctionParser(ParserState &state, MLFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07002094 : FunctionParser(state, Kind::MLFunc), function(function),
Chris Lattnere787b322018-08-08 11:14:57 -07002095 builder(function, function->end()) {}
Chris Lattner48af7d12018-07-09 19:05:38 -07002096
2097 ParseResult parseFunctionBody();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002098
2099private:
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002100 MLFunction *function;
2101
2102 /// This builder intentionally shadows the builder in the base class, with a
2103 /// more specific builder type.
2104 MLFuncBuilder builder;
2105
2106 ParseResult parseForStmt();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002107 AffineConstantExpr *parseIntConstant();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002108 ParseResult parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002109 ParseResult parseElseClause(IfClause *elseClause);
Uday Bondhugulabc535622018-08-07 14:24:38 -07002110 IntegerSet *parseCondition();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002111 ParseResult parseStatements(StmtBlock *block);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002112 ParseResult parseStmtBlock(StmtBlock *block);
Chris Lattner48af7d12018-07-09 19:05:38 -07002113};
2114} // end anonymous namespace
2115
Chris Lattner48af7d12018-07-09 19:05:38 -07002116ParseResult MLFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07002117 auto braceLoc = getToken().getLoc();
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002118
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002119 // Parse statements in this function.
2120 if (parseStmtBlock(function))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002121 return ParseFailure;
Chris Lattner40746442018-07-21 14:32:09 -07002122
Chris Lattner40746442018-07-21 14:32:09 -07002123 return finalizeFunction(function, braceLoc);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002124}
2125
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002126/// For statement.
2127///
Chris Lattner48af7d12018-07-09 19:05:38 -07002128/// ml-for-stmt ::= `for` ssa-id `=` lower-bound `to` upper-bound
2129/// (`step` integer-literal)? `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002130///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002131ParseResult MLFunctionParser::parseForStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002132 consumeToken(Token::kw_for);
2133
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002134 // Parse induction variable
2135 if (getToken().isNot(Token::percent_identifier))
2136 return emitError("expected SSA identifier for the loop variable");
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002137
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002138 auto loc = getToken().getLoc();
Tatiana Shpeismand880b352018-07-31 23:14:16 -07002139 StringRef inductionVariableName = getTokenSpelling();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002140 consumeToken(Token::percent_identifier);
2141
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002142 if (parseToken(Token::equal, "expected '='"))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002143 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002144
2145 // Parse loop bounds
2146 AffineConstantExpr *lowerBound = parseIntConstant();
2147 if (!lowerBound)
2148 return ParseFailure;
2149
Chris Lattnerf7702a62018-07-23 17:30:01 -07002150 if (parseToken(Token::kw_to, "expected 'to' between bounds"))
2151 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002152
2153 AffineConstantExpr *upperBound = parseIntConstant();
2154 if (!upperBound)
2155 return ParseFailure;
2156
2157 // Parse step
2158 AffineConstantExpr *step = nullptr;
2159 if (consumeIf(Token::kw_step)) {
2160 step = parseIntConstant();
2161 if (!step)
2162 return ParseFailure;
2163 }
2164
2165 // Create for statement.
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002166 ForStmt *forStmt = builder.createFor(lowerBound, upperBound, step);
2167
2168 // Create SSA value definition for the induction variable.
Chris Lattner2b97d502018-08-06 14:19:46 -07002169 if (addDefinition({inductionVariableName, 0, loc}, forStmt))
2170 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002171
2172 // If parsing of the for statement body fails,
2173 // MLIR contains for statement with those nested statements that have been
2174 // successfully parsed.
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002175 if (parseStmtBlock(forStmt))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002176 return ParseFailure;
2177
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002178 // Reset insertion point to the current block.
Chris Lattnere787b322018-08-08 11:14:57 -07002179 builder.setInsertionPointToEnd(forStmt->getBlock());
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002180
Tatiana Shpeismand880b352018-07-31 23:14:16 -07002181 // TODO: remove definition of the induction variable.
2182
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002183 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002184}
2185
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002186// This method is temporary workaround to parse simple loop bounds and
2187// step.
2188// TODO: remove this method once it's no longer used.
2189AffineConstantExpr *MLFunctionParser::parseIntConstant() {
2190 if (getToken().isNot(Token::integer))
2191 return (emitError("expected non-negative integer for now"), nullptr);
2192
2193 auto val = getToken().getUInt64IntegerValue();
2194 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
2195 return (emitError("constant too large for affineint"), nullptr);
2196 }
2197 consumeToken(Token::integer);
2198 return builder.getConstantExpr((int64_t)val.getValue());
2199}
2200
Uday Bondhugulabc535622018-08-07 14:24:38 -07002201/// Parse condition.
2202IntegerSet *MLFunctionParser::parseCondition() {
2203 return parseIntegerSetReference();
2204
2205 // TODO: Parse operands to the integer set.
2206}
2207
2208/// Parse an affine constraint.
2209/// affine-constraint ::= affine-expr `>=` `0`
2210/// | affine-expr `==` `0`
2211///
2212/// isEq is set to true if the parsed constraint is an equality, false if it is
2213/// an inequality (greater than or equal).
2214///
2215AffineExpr *AffineParser::parseAffineConstraint(bool *isEq) {
2216 AffineExpr *expr = parseAffineExpr();
2217 if (!expr)
2218 return nullptr;
2219
2220 if (consumeIf(Token::greater) && consumeIf(Token::equal) &&
2221 getToken().is(Token::integer)) {
2222 auto dim = getToken().getUnsignedIntegerValue();
2223 if (dim.hasValue() && dim.getValue() == 0) {
2224 consumeToken(Token::integer);
2225 *isEq = false;
2226 return expr;
2227 }
2228 return (emitError("expected '0' after '>='"), nullptr);
2229 }
2230
2231 if (consumeIf(Token::equal) && consumeIf(Token::equal) &&
2232 getToken().is(Token::integer)) {
2233 auto dim = getToken().getUnsignedIntegerValue();
2234 if (dim.hasValue() && dim.getValue() == 0) {
2235 consumeToken(Token::integer);
2236 *isEq = true;
2237 return expr;
2238 }
2239 return (emitError("expected '0' after '=='"), nullptr);
2240 }
2241
2242 return (emitError("expected '== 0' or '>= 0' at end of affine constraint"),
2243 nullptr);
2244}
2245
2246/// Parse an integer set definition.
2247/// integer-set-inline
2248/// ::= dim-and-symbol-id-lists `:` affine-constraint-conjunction
2249/// affine-constraint-conjunction ::= /*empty*/
2250/// | affine-constraint (`,` affine-constraint)*
2251///
2252IntegerSet *AffineParser::parseIntegerSetInline() {
2253 unsigned numDims = 0, numSymbols = 0;
2254
2255 // List of dimensional identifiers.
2256 if (parseDimIdList(numDims))
2257 return nullptr;
2258
2259 // Symbols are optional.
2260 if (getToken().is(Token::l_square)) {
2261 if (parseSymbolIdList(numSymbols))
2262 return nullptr;
2263 }
2264
2265 if (parseToken(Token::colon, "expected ':' or '['") ||
2266 parseToken(Token::l_paren,
2267 "expected '(' at start of integer set constraint list"))
2268 return nullptr;
2269
2270 SmallVector<AffineExpr *, 4> constraints;
2271 SmallVector<bool, 4> isEqs;
2272 auto parseElt = [&]() -> ParseResult {
2273 bool isEq;
2274 auto *elt = parseAffineConstraint(&isEq);
2275 ParseResult res = elt ? ParseSuccess : ParseFailure;
2276 if (elt) {
2277 constraints.push_back(elt);
2278 isEqs.push_back(isEq);
2279 }
2280 return res;
2281 };
2282
2283 // Parse a list of affine constraints (comma-separated) .
2284 // Grammar: affine-constraint-conjunct ::= `(` affine-constraint (`,`
2285 // affine-constraint)* `)
2286 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt, true))
2287 return nullptr;
2288
2289 // Parsed a valid integer set.
2290 return builder.getIntegerSet(numDims, numSymbols, constraints, isEqs);
2291}
2292
2293IntegerSet *Parser::parseIntegerSetInline() {
2294 return AffineParser(state).parseIntegerSetInline();
2295}
2296
2297/// Parse a reference to an integer set.
2298/// integer-set ::= integer-set-id | integer-set-inline
2299/// integer-set-id ::= `@@` suffix-id
2300///
2301IntegerSet *Parser::parseIntegerSetReference() {
2302 if (getToken().is(Token::double_at_identifier)) {
2303 // Parse integer set identifier and verify that it exists.
2304 StringRef integerSetId = getTokenSpelling().drop_front(2);
2305 if (getState().integerSetDefinitions.count(integerSetId) == 0)
2306 return (emitError("undefined integer set id '" + integerSetId + "'"),
2307 nullptr);
2308 consumeToken(Token::double_at_identifier);
2309 return getState().integerSetDefinitions[integerSetId];
2310 }
2311 // Try to parse an inline integer set definition.
2312 return parseIntegerSetInline();
2313}
2314
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002315/// If statement.
2316///
Chris Lattner48af7d12018-07-09 19:05:38 -07002317/// ml-if-head ::= `if` ml-if-cond `{` ml-stmt* `}`
2318/// | ml-if-head `else` `if` ml-if-cond `{` ml-stmt* `}`
2319/// ml-if-stmt ::= ml-if-head
2320/// | ml-if-head `else` `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002321///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002322ParseResult MLFunctionParser::parseIfStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002323 consumeToken(Token::kw_if);
Uday Bondhugulabc535622018-08-07 14:24:38 -07002324
2325 if (parseToken(Token::l_paren, "expected '('"))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002326 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002327
Uday Bondhugulabc535622018-08-07 14:24:38 -07002328 IntegerSet *condition = parseCondition();
2329 if (!condition)
Chris Lattnerf7702a62018-07-23 17:30:01 -07002330 return ParseFailure;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002331
Uday Bondhugulabc535622018-08-07 14:24:38 -07002332 if (parseToken(Token::r_paren, "expected ')'"))
2333 return ParseFailure;
2334
2335 IfStmt *ifStmt = builder.createIf(condition);
Chris Lattnere787b322018-08-08 11:14:57 -07002336 IfClause *thenClause = ifStmt->getThen();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002337
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002338 // When parsing of an if statement body fails, the IR contains
2339 // the if statement with the portion of the body that has been
2340 // successfully parsed.
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002341 if (parseStmtBlock(thenClause))
2342 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002343
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002344 if (consumeIf(Token::kw_else)) {
Chris Lattnere787b322018-08-08 11:14:57 -07002345 auto *elseClause = ifStmt->createElse();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002346 if (parseElseClause(elseClause))
2347 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002348 }
2349
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002350 // Reset insertion point to the current block.
Chris Lattnere787b322018-08-08 11:14:57 -07002351 builder.setInsertionPointToEnd(ifStmt->getBlock());
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002352
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002353 return ParseSuccess;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002354}
2355
2356ParseResult MLFunctionParser::parseElseClause(IfClause *elseClause) {
2357 if (getToken().is(Token::kw_if)) {
Chris Lattnere787b322018-08-08 11:14:57 -07002358 builder.setInsertionPointToEnd(elseClause);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002359 return parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002360 }
2361
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002362 return parseStmtBlock(elseClause);
2363}
2364
2365///
2366/// Parse a list of statements ending with `return` or `}`
2367///
2368ParseResult MLFunctionParser::parseStatements(StmtBlock *block) {
Chris Lattner992a1272018-08-07 12:02:37 -07002369 auto createOpFunc = [&](const OperationState &state) -> Operation * {
2370 return builder.createOperation(state);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002371 };
2372
Chris Lattnere787b322018-08-08 11:14:57 -07002373 builder.setInsertionPointToEnd(block);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002374
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002375 // Parse statements till we see '}' or 'return'.
2376 // Return statement is parsed separately to emit a more intuitive error
2377 // when '}' is missing after the return statement.
2378 while (getToken().isNot(Token::r_brace, Token::kw_return)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002379 switch (getToken().getKind()) {
2380 default:
2381 if (parseOperation(createOpFunc))
2382 return ParseFailure;
2383 break;
2384 case Token::kw_for:
2385 if (parseForStmt())
2386 return ParseFailure;
2387 break;
2388 case Token::kw_if:
2389 if (parseIfStmt())
2390 return ParseFailure;
2391 break;
2392 } // end switch
2393 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002394
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002395 // Parse the return statement.
2396 if (getToken().is(Token::kw_return))
2397 if (parseOperation(createOpFunc))
2398 return ParseFailure;
2399
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002400 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002401}
2402
2403///
2404/// Parse `{` ml-stmt* `}`
2405///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002406ParseResult MLFunctionParser::parseStmtBlock(StmtBlock *block) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002407 if (parseToken(Token::l_brace, "expected '{' before statement list") ||
2408 parseStatements(block) ||
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002409 parseToken(Token::r_brace, "expected '}' after statement list"))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002410 return ParseFailure;
2411
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002412 return ParseSuccess;
2413}
2414
Chris Lattner4c95a502018-06-23 16:03:42 -07002415//===----------------------------------------------------------------------===//
2416// Top-level entity parsing.
2417//===----------------------------------------------------------------------===//
2418
Chris Lattner2e595eb2018-07-10 10:08:27 -07002419namespace {
2420/// This parser handles entities that are only valid at the top level of the
2421/// file.
2422class ModuleParser : public Parser {
2423public:
2424 explicit ModuleParser(ParserState &state) : Parser(state) {}
2425
2426 ParseResult parseModule();
2427
2428private:
2429 ParseResult parseAffineMapDef();
Uday Bondhugulabc535622018-08-07 14:24:38 -07002430 ParseResult parseIntegerSetDef();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002431
2432 // Functions.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002433 ParseResult parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2434 SmallVectorImpl<StringRef> &argNames);
2435 ParseResult parseFunctionSignature(StringRef &name, FunctionType *&type,
2436 SmallVectorImpl<StringRef> *argNames);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002437 ParseResult parseExtFunc();
2438 ParseResult parseCFGFunc();
2439 ParseResult parseMLFunc();
2440};
2441} // end anonymous namespace
2442
2443/// Affine map declaration.
2444///
2445/// affine-map-def ::= affine-map-id `=` affine-map-inline
2446///
2447ParseResult ModuleParser::parseAffineMapDef() {
2448 assert(getToken().is(Token::hash_identifier));
2449
2450 StringRef affineMapId = getTokenSpelling().drop_front();
2451
2452 // Check for redefinitions.
Uday Bondhugulabc535622018-08-07 14:24:38 -07002453 auto **entry = &getState().affineMapDefinitions[affineMapId];
2454 if (*entry)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002455 return emitError("redefinition of affine map id '" + affineMapId + "'");
2456
2457 consumeToken(Token::hash_identifier);
2458
2459 // Parse the '='
Chris Lattnerf7702a62018-07-23 17:30:01 -07002460 if (parseToken(Token::equal,
2461 "expected '=' in affine map outlined definition"))
2462 return ParseFailure;
Chris Lattner2e595eb2018-07-10 10:08:27 -07002463
Uday Bondhugulabc535622018-08-07 14:24:38 -07002464 *entry = parseAffineMapInline();
2465 if (!*entry)
2466 return ParseFailure;
2467
2468 return ParseSuccess;
2469}
2470
2471/// Integer set declaration.
2472///
2473/// integer-set-decl ::= integer-set-id `=` integer-set-inline
2474///
2475ParseResult ModuleParser::parseIntegerSetDef() {
2476 assert(getToken().is(Token::double_at_identifier));
2477
2478 StringRef integerSetId = getTokenSpelling().drop_front(2);
2479
2480 // Check for redefinitions (a default entry is created if one doesn't exist)
2481 auto **entry = &getState().integerSetDefinitions[integerSetId];
2482 if (*entry)
2483 return emitError("redefinition of integer set id '" + integerSetId + "'");
2484
2485 consumeToken(Token::double_at_identifier);
2486
2487 // Parse the '='
2488 if (parseToken(Token::equal,
2489 "expected '=' in outlined integer set definition"))
2490 return ParseFailure;
2491
2492 *entry = parseIntegerSetInline();
2493 if (!*entry)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002494 return ParseFailure;
2495
Chris Lattner2e595eb2018-07-10 10:08:27 -07002496 return ParseSuccess;
2497}
2498
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002499/// Parse a (possibly empty) list of MLFunction arguments with types.
2500///
2501/// ml-argument ::= ssa-id `:` type
2502/// ml-argument-list ::= ml-argument (`,` ml-argument)* | /*empty*/
2503///
2504ParseResult
2505ModuleParser::parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2506 SmallVectorImpl<StringRef> &argNames) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002507 consumeToken(Token::l_paren);
2508
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002509 auto parseElt = [&]() -> ParseResult {
2510 // Parse argument name
2511 if (getToken().isNot(Token::percent_identifier))
2512 return emitError("expected SSA identifier");
2513
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002514 StringRef name = getTokenSpelling();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002515 consumeToken(Token::percent_identifier);
2516 argNames.push_back(name);
2517
Chris Lattnerf7702a62018-07-23 17:30:01 -07002518 if (parseToken(Token::colon, "expected ':'"))
2519 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002520
2521 // Parse argument type
2522 auto elt = parseType();
2523 if (!elt)
2524 return ParseFailure;
2525 argTypes.push_back(elt);
2526
2527 return ParseSuccess;
2528 };
2529
Chris Lattner40746442018-07-21 14:32:09 -07002530 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002531}
2532
Chris Lattner2e595eb2018-07-10 10:08:27 -07002533/// Parse a function signature, starting with a name and including the parameter
2534/// list.
2535///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002536/// argument-list ::= type (`,` type)* | /*empty*/ | ml-argument-list
Chris Lattner2e595eb2018-07-10 10:08:27 -07002537/// function-signature ::= function-id `(` argument-list `)` (`->` type-list)?
2538///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002539ParseResult
2540ModuleParser::parseFunctionSignature(StringRef &name, FunctionType *&type,
2541 SmallVectorImpl<StringRef> *argNames) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002542 if (getToken().isNot(Token::at_identifier))
2543 return emitError("expected a function identifier like '@foo'");
2544
2545 name = getTokenSpelling().drop_front();
2546 consumeToken(Token::at_identifier);
2547
2548 if (getToken().isNot(Token::l_paren))
2549 return emitError("expected '(' in function signature");
2550
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002551 SmallVector<Type *, 4> argTypes;
2552 ParseResult parseResult;
2553
2554 if (argNames)
2555 parseResult = parseMLArgumentList(argTypes, *argNames);
2556 else
2557 parseResult = parseTypeList(argTypes);
2558
2559 if (parseResult)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002560 return ParseFailure;
2561
2562 // Parse the return type if present.
2563 SmallVector<Type *, 4> results;
2564 if (consumeIf(Token::arrow)) {
2565 if (parseTypeList(results))
2566 return ParseFailure;
2567 }
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002568 type = builder.getFunctionType(argTypes, results);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002569 return ParseSuccess;
2570}
2571
2572/// External function declarations.
2573///
2574/// ext-func ::= `extfunc` function-signature
2575///
2576ParseResult ModuleParser::parseExtFunc() {
2577 consumeToken(Token::kw_extfunc);
Chris Lattner974a8762018-08-17 16:49:42 -07002578 auto loc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002579
2580 StringRef name;
2581 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002582 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002583 return ParseFailure;
2584
2585 // Okay, the external function definition was parsed correctly.
Chris Lattner974a8762018-08-17 16:49:42 -07002586 auto *function = new ExtFunction(name, type);
2587 getModule()->getFunctions().push_back(function);
2588
2589 // Verify no name collision / redefinition.
2590 if (function->getName().ref() != name)
2591 return emitError(loc,
2592 "redefinition of function named '" + name.str() + "'");
2593
Chris Lattner2e595eb2018-07-10 10:08:27 -07002594 return ParseSuccess;
2595}
2596
2597/// CFG function declarations.
2598///
2599/// cfg-func ::= `cfgfunc` function-signature `{` basic-block+ `}`
2600///
2601ParseResult ModuleParser::parseCFGFunc() {
2602 consumeToken(Token::kw_cfgfunc);
Chris Lattner974a8762018-08-17 16:49:42 -07002603 auto loc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002604
2605 StringRef name;
2606 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002607 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002608 return ParseFailure;
2609
2610 // Okay, the CFG function signature was parsed correctly, create the function.
Chris Lattner974a8762018-08-17 16:49:42 -07002611 auto *function = new CFGFunction(name, type);
2612 getModule()->getFunctions().push_back(function);
2613
2614 // Verify no name collision / redefinition.
2615 if (function->getName().ref() != name)
2616 return emitError(loc,
2617 "redefinition of function named '" + name.str() + "'");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002618
2619 return CFGFunctionParser(getState(), function).parseFunctionBody();
2620}
2621
2622/// ML function declarations.
2623///
2624/// ml-func ::= `mlfunc` ml-func-signature `{` ml-stmt* ml-return-stmt `}`
2625///
2626ParseResult ModuleParser::parseMLFunc() {
2627 consumeToken(Token::kw_mlfunc);
2628
2629 StringRef name;
2630 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002631 SmallVector<StringRef, 4> argNames;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002632
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002633 auto loc = getToken().getLoc();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002634 if (parseFunctionSignature(name, type, &argNames))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002635 return ParseFailure;
2636
2637 // Okay, the ML function signature was parsed correctly, create the function.
Chris Lattner974a8762018-08-17 16:49:42 -07002638 auto *function = MLFunction::create(name, type);
2639 getModule()->getFunctions().push_back(function);
2640
2641 // Verify no name collision / redefinition.
2642 if (function->getName().ref() != name)
2643 return emitError(loc,
2644 "redefinition of function named '" + name.str() + "'");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002645
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002646 // Create the parser.
2647 auto parser = MLFunctionParser(getState(), function);
2648
2649 // Add definitions of the function arguments.
2650 for (unsigned i = 0, e = function->getNumArguments(); i != e; ++i) {
2651 if (parser.addDefinition({argNames[i], 0, loc}, function->getArgument(i)))
2652 return ParseFailure;
2653 }
2654
2655 return parser.parseFunctionBody();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002656}
2657
Chris Lattnere79379a2018-06-22 10:39:19 -07002658/// This is the top-level module parser.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002659ParseResult ModuleParser::parseModule() {
Chris Lattnere79379a2018-06-22 10:39:19 -07002660 while (1) {
Chris Lattner48af7d12018-07-09 19:05:38 -07002661 switch (getToken().getKind()) {
Chris Lattnere79379a2018-06-22 10:39:19 -07002662 default:
2663 emitError("expected a top level entity");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002664 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002665
Uday Bondhugula015cbb12018-07-03 20:16:08 -07002666 // If we got to the end of the file, then we're done.
Chris Lattnere79379a2018-06-22 10:39:19 -07002667 case Token::eof:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002668 return ParseSuccess;
Chris Lattnere79379a2018-06-22 10:39:19 -07002669
2670 // If we got an error token, then the lexer already emitted an error, just
2671 // stop. Someday we could introduce error recovery if there was demand for
2672 // it.
2673 case Token::error:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002674 return ParseFailure;
2675
2676 case Token::hash_identifier:
2677 if (parseAffineMapDef())
2678 return ParseFailure;
2679 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002680
Uday Bondhugulabc535622018-08-07 14:24:38 -07002681 case Token::double_at_identifier:
2682 if (parseIntegerSetDef())
2683 return ParseFailure;
2684 break;
2685
Chris Lattnere79379a2018-06-22 10:39:19 -07002686 case Token::kw_extfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002687 if (parseExtFunc())
2688 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002689 break;
2690
Chris Lattner4c95a502018-06-23 16:03:42 -07002691 case Token::kw_cfgfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002692 if (parseCFGFunc())
2693 return ParseFailure;
MLIR Teamf85a6262018-06-27 11:03:08 -07002694 break;
Chris Lattner4c95a502018-06-23 16:03:42 -07002695
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002696 case Token::kw_mlfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002697 if (parseMLFunc())
2698 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002699 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002700 }
2701 }
2702}
2703
2704//===----------------------------------------------------------------------===//
2705
Jacques Pienaar7b829702018-07-03 13:24:09 -07002706void mlir::defaultErrorReporter(const llvm::SMDiagnostic &error) {
2707 const auto &sourceMgr = *error.getSourceMgr();
2708 sourceMgr.PrintMessage(error.getLoc(), error.getKind(), error.getMessage());
2709}
2710
Chris Lattnere79379a2018-06-22 10:39:19 -07002711/// This parses the file specified by the indicated SourceMgr and returns an
2712/// MLIR module if it was valid. If not, it emits diagnostics and returns null.
Jacques Pienaar9c411be2018-06-24 19:17:35 -07002713Module *mlir::parseSourceFile(llvm::SourceMgr &sourceMgr, MLIRContext *context,
Jacques Pienaar7b829702018-07-03 13:24:09 -07002714 SMDiagnosticHandlerTy errorReporter) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002715 // This is the result module we are parsing into.
2716 std::unique_ptr<Module> module(new Module(context));
2717
2718 ParserState state(sourceMgr, module.get(),
Jacques Pienaar0bffd862018-07-11 13:26:23 -07002719 errorReporter ? errorReporter : defaultErrorReporter);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002720 if (ModuleParser(state).parseModule())
2721 return nullptr;
Chris Lattner21e67f62018-07-06 10:46:19 -07002722
2723 // Make sure the parse module has no other structural problems detected by the
2724 // verifier.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002725 module->verify();
2726 return module.release();
Chris Lattnere79379a2018-06-22 10:39:19 -07002727}