blob: 90e3dd3827bb3cf1bbf628507b90fe289d97a68d [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"
30#include "mlir/IR/OperationSet.h"
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -070031#include "mlir/IR/Statements.h"
Chris Lattnerf7e22732018-06-22 22:03:48 -070032#include "mlir/IR/Types.h"
Chris Lattner6119d382018-07-20 18:41:34 -070033#include "llvm/ADT/DenseMap.h"
Chris Lattnere79379a2018-06-22 10:39:19 -070034#include "llvm/Support/SourceMgr.h"
35using namespace mlir;
Chris Lattner4c95a502018-06-23 16:03:42 -070036using llvm::SMLoc;
James Molloy0ff71542018-07-23 16:56:32 -070037using llvm::SourceMgr;
Chris Lattnere79379a2018-06-22 10:39:19 -070038
Chris Lattnerf7e22732018-06-22 22:03:48 -070039/// Simple enum to make code read better in cases that would otherwise return a
40/// bool value. Failure is "true" in a boolean context.
James Molloy0ff71542018-07-23 16:56:32 -070041enum ParseResult { ParseSuccess, ParseFailure };
Chris Lattnere79379a2018-06-22 10:39:19 -070042
Chris Lattner48af7d12018-07-09 19:05:38 -070043namespace {
44class Parser;
45
46/// This class refers to all of the state maintained globally by the parser,
47/// such as the current lexer position etc. The Parser base class provides
48/// methods to access this.
49class ParserState {
Chris Lattnered65a732018-06-28 20:45:33 -070050public:
Chris Lattner2e595eb2018-07-10 10:08:27 -070051 ParserState(llvm::SourceMgr &sourceMgr, Module *module,
Chris Lattner48af7d12018-07-09 19:05:38 -070052 SMDiagnosticHandlerTy errorReporter)
Chris Lattner2e595eb2018-07-10 10:08:27 -070053 : context(module->getContext()), module(module),
54 lex(sourceMgr, errorReporter), curToken(lex.lexToken()),
Jacques Pienaard4c784e2018-07-11 00:07:36 -070055 errorReporter(errorReporter) {}
Chris Lattner2e595eb2018-07-10 10:08:27 -070056
57 // A map from affine map identifier to AffineMap.
58 llvm::StringMap<AffineMap *> affineMapDefinitions;
Chris Lattnere79379a2018-06-22 10:39:19 -070059
Chris Lattnere79379a2018-06-22 10:39:19 -070060private:
Chris Lattner48af7d12018-07-09 19:05:38 -070061 ParserState(const ParserState &) = delete;
62 void operator=(const ParserState &) = delete;
63
64 friend class Parser;
65
66 // The context we're parsing into.
Chris Lattner2e595eb2018-07-10 10:08:27 -070067 MLIRContext *const context;
68
69 // This is the module we are parsing into.
70 Module *const module;
Chris Lattnerf7e22732018-06-22 22:03:48 -070071
72 // The lexer for the source file we're parsing.
Chris Lattnere79379a2018-06-22 10:39:19 -070073 Lexer lex;
74
75 // This is the next token that hasn't been consumed yet.
76 Token curToken;
77
Jacques Pienaar9c411be2018-06-24 19:17:35 -070078 // The diagnostic error reporter.
Chris Lattner2e595eb2018-07-10 10:08:27 -070079 SMDiagnosticHandlerTy const errorReporter;
Chris Lattner48af7d12018-07-09 19:05:38 -070080};
81} // end anonymous namespace
MLIR Teamf85a6262018-06-27 11:03:08 -070082
Chris Lattner48af7d12018-07-09 19:05:38 -070083namespace {
84
Chris Lattner7f9cc272018-07-19 08:35:28 -070085typedef std::function<Operation *(Identifier, ArrayRef<SSAValue *>,
86 ArrayRef<Type *>, ArrayRef<NamedAttribute>)>
Tatiana Shpeisman565b9642018-07-16 11:47:09 -070087 CreateOperationFunction;
88
Chris Lattner48af7d12018-07-09 19:05:38 -070089/// This class implement support for parsing global entities like types and
90/// shared entities like SSA names. It is intended to be subclassed by
91/// specialized subparsers that include state, e.g. when a local symbol table.
92class Parser {
93public:
Chris Lattner2e595eb2018-07-10 10:08:27 -070094 Builder builder;
Chris Lattner48af7d12018-07-09 19:05:38 -070095
Chris Lattner2e595eb2018-07-10 10:08:27 -070096 Parser(ParserState &state) : builder(state.context), state(state) {}
97
98 // Helper methods to get stuff from the parser-global state.
99 ParserState &getState() const { return state; }
Chris Lattner48af7d12018-07-09 19:05:38 -0700100 MLIRContext *getContext() const { return state.context; }
Chris Lattner2e595eb2018-07-10 10:08:27 -0700101 Module *getModule() { return state.module; }
Chris Lattner48af7d12018-07-09 19:05:38 -0700102
103 /// Return the current token the parser is inspecting.
104 const Token &getToken() const { return state.curToken; }
105 StringRef getTokenSpelling() const { return state.curToken.getSpelling(); }
Chris Lattnere79379a2018-06-22 10:39:19 -0700106
107 /// Emit an error and return failure.
Chris Lattner4c95a502018-06-23 16:03:42 -0700108 ParseResult emitError(const Twine &message) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700109 return emitError(state.curToken.getLoc(), message);
Chris Lattner4c95a502018-06-23 16:03:42 -0700110 }
111 ParseResult emitError(SMLoc loc, const Twine &message);
Chris Lattnere79379a2018-06-22 10:39:19 -0700112
113 /// Advance the current lexer onto the next token.
114 void consumeToken() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700115 assert(state.curToken.isNot(Token::eof, Token::error) &&
Chris Lattnere79379a2018-06-22 10:39:19 -0700116 "shouldn't advance past EOF or errors");
Chris Lattner48af7d12018-07-09 19:05:38 -0700117 state.curToken = state.lex.lexToken();
Chris Lattnere79379a2018-06-22 10:39:19 -0700118 }
119
120 /// Advance the current lexer onto the next token, asserting what the expected
121 /// current token is. This is preferred to the above method because it leads
122 /// to more self-documenting code with better checking.
Chris Lattner8da0c282018-06-29 11:15:56 -0700123 void consumeToken(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700124 assert(state.curToken.is(kind) && "consumed an unexpected token");
Chris Lattnere79379a2018-06-22 10:39:19 -0700125 consumeToken();
126 }
127
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700128 /// If the current token has the specified kind, consume it and return true.
129 /// If not, return false.
Chris Lattner8da0c282018-06-29 11:15:56 -0700130 bool consumeIf(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700131 if (state.curToken.isNot(kind))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700132 return false;
133 consumeToken(kind);
134 return true;
135 }
136
Chris Lattnerf7702a62018-07-23 17:30:01 -0700137 /// Consume the specified token if present and return success. On failure,
138 /// output a diagnostic and return failure.
139 ParseResult parseToken(Token::Kind expectedToken, const Twine &message);
140
Chris Lattner40746442018-07-21 14:32:09 -0700141 /// Parse a comma-separated list of elements up until the specified end token.
142 ParseResult
143 parseCommaSeparatedListUntil(Token::Kind rightToken,
144 const std::function<ParseResult()> &parseElement,
145 bool allowEmptyList = true);
146
147 /// Parse a comma separated list of elements that must have at least one entry
148 /// in it.
149 ParseResult
150 parseCommaSeparatedList(const std::function<ParseResult()> &parseElement);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700151
Chris Lattnerf7e22732018-06-22 22:03:48 -0700152 // We have two forms of parsing methods - those that return a non-null
153 // pointer on success, and those that return a ParseResult to indicate whether
154 // they returned a failure. The second class fills in by-reference arguments
155 // as the results of their action.
156
Chris Lattnere79379a2018-06-22 10:39:19 -0700157 // Type parsing.
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700158 Type *parsePrimitiveType();
Chris Lattnerf7e22732018-06-22 22:03:48 -0700159 Type *parseElementType();
160 VectorType *parseVectorType();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700161 ParseResult parseDimensionListRanked(SmallVectorImpl<int> &dimensions);
Chris Lattnerf7e22732018-06-22 22:03:48 -0700162 Type *parseTensorType();
163 Type *parseMemRefType();
164 Type *parseFunctionType();
165 Type *parseType();
Chris Lattner1604e472018-07-23 08:42:19 -0700166 ParseResult parseTypeListNoParens(SmallVectorImpl<Type *> &elements);
James Molloy0ff71542018-07-23 16:56:32 -0700167 ParseResult parseTypeList(SmallVectorImpl<Type *> &elements);
Chris Lattnere79379a2018-06-22 10:39:19 -0700168
Chris Lattner7121b802018-07-04 20:45:39 -0700169 // Attribute parsing.
170 Attribute *parseAttribute();
171 ParseResult parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes);
172
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700173 // Polyhedral structures.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700174 AffineMap *parseAffineMapInline();
MLIR Team718c82f2018-07-16 09:45:22 -0700175 AffineMap *parseAffineMapReference();
MLIR Teamf85a6262018-06-27 11:03:08 -0700176
Chris Lattner48af7d12018-07-09 19:05:38 -0700177private:
178 // The Parser is subclassed and reinstantiated. Do not add additional
179 // non-trivial state here, add it to the ParserState class.
180 ParserState &state;
Chris Lattnere79379a2018-06-22 10:39:19 -0700181};
182} // end anonymous namespace
183
184//===----------------------------------------------------------------------===//
185// Helper methods.
186//===----------------------------------------------------------------------===//
187
Chris Lattner4c95a502018-06-23 16:03:42 -0700188ParseResult Parser::emitError(SMLoc loc, const Twine &message) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700189 // If we hit a parse error in response to a lexer error, then the lexer
Jacques Pienaar9c411be2018-06-24 19:17:35 -0700190 // already reported the error.
Chris Lattner48af7d12018-07-09 19:05:38 -0700191 if (getToken().is(Token::error))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700192 return ParseFailure;
193
Chris Lattner48af7d12018-07-09 19:05:38 -0700194 auto &sourceMgr = state.lex.getSourceMgr();
195 state.errorReporter(sourceMgr.GetMessage(loc, SourceMgr::DK_Error, message));
Chris Lattnere79379a2018-06-22 10:39:19 -0700196 return ParseFailure;
197}
198
Chris Lattnerf7702a62018-07-23 17:30:01 -0700199/// Consume the specified token if present and return success. On failure,
200/// output a diagnostic and return failure.
201ParseResult Parser::parseToken(Token::Kind expectedToken,
202 const Twine &message) {
203 if (consumeIf(expectedToken))
204 return ParseSuccess;
205 return emitError(message);
206}
207
Chris Lattner40746442018-07-21 14:32:09 -0700208/// Parse a comma separated list of elements that must have at least one entry
209/// in it.
210ParseResult Parser::parseCommaSeparatedList(
211 const std::function<ParseResult()> &parseElement) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700212 // Non-empty case starts with an element.
213 if (parseElement())
214 return ParseFailure;
215
216 // Otherwise we have a list of comma separated elements.
217 while (consumeIf(Token::comma)) {
218 if (parseElement())
219 return ParseFailure;
220 }
Chris Lattner40746442018-07-21 14:32:09 -0700221 return ParseSuccess;
222}
223
224/// Parse a comma-separated list of elements, terminated with an arbitrary
225/// token. This allows empty lists if allowEmptyList is true.
226///
227/// abstract-list ::= rightToken // if allowEmptyList == true
228/// abstract-list ::= element (',' element)* rightToken
229///
230ParseResult Parser::parseCommaSeparatedListUntil(
231 Token::Kind rightToken, const std::function<ParseResult()> &parseElement,
232 bool allowEmptyList) {
233 // Handle the empty case.
234 if (getToken().is(rightToken)) {
235 if (!allowEmptyList)
236 return emitError("expected list element");
237 consumeToken(rightToken);
238 return ParseSuccess;
239 }
240
Chris Lattnerf7702a62018-07-23 17:30:01 -0700241 if (parseCommaSeparatedList(parseElement) ||
242 parseToken(rightToken, "expected ',' or '" +
243 Token::getTokenSpelling(rightToken) + "'"))
Chris Lattner40746442018-07-21 14:32:09 -0700244 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700245
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700246 return ParseSuccess;
247}
Chris Lattnere79379a2018-06-22 10:39:19 -0700248
249//===----------------------------------------------------------------------===//
250// Type Parsing
251//===----------------------------------------------------------------------===//
252
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700253/// Parse the low-level fixed dtypes in the system.
254///
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700255/// primitive-type ::= `f16` | `bf16` | `f32` | `f64`
256/// primitive-type ::= integer-type
257/// primitive-type ::= `affineint`
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700258///
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700259Type *Parser::parsePrimitiveType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700260 switch (getToken().getKind()) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700261 default:
262 return (emitError("expected type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700263 case Token::kw_bf16:
264 consumeToken(Token::kw_bf16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700265 return builder.getBF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700266 case Token::kw_f16:
267 consumeToken(Token::kw_f16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700268 return builder.getF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700269 case Token::kw_f32:
270 consumeToken(Token::kw_f32);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700271 return builder.getF32Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700272 case Token::kw_f64:
273 consumeToken(Token::kw_f64);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700274 return builder.getF64Type();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700275 case Token::kw_affineint:
276 consumeToken(Token::kw_affineint);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700277 return builder.getAffineIntType();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700278 case Token::inttype: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700279 auto width = getToken().getIntTypeBitwidth();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700280 if (!width.hasValue())
281 return (emitError("invalid integer width"), nullptr);
282 consumeToken(Token::inttype);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700283 return builder.getIntegerType(width.getValue());
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700284 }
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700285 }
286}
287
288/// Parse the element type of a tensor or memref type.
289///
290/// element-type ::= primitive-type | vector-type
291///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700292Type *Parser::parseElementType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700293 if (getToken().is(Token::kw_vector))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700294 return parseVectorType();
295
296 return parsePrimitiveType();
297}
298
299/// Parse a vector type.
300///
301/// vector-type ::= `vector` `<` const-dimension-list primitive-type `>`
302/// const-dimension-list ::= (integer-literal `x`)+
303///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700304VectorType *Parser::parseVectorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700305 consumeToken(Token::kw_vector);
306
Chris Lattnerf7702a62018-07-23 17:30:01 -0700307 if (parseToken(Token::less, "expected '<' in vector type"))
308 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700309
Chris Lattner48af7d12018-07-09 19:05:38 -0700310 if (getToken().isNot(Token::integer))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700311 return (emitError("expected dimension size in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700312
313 SmallVector<unsigned, 4> dimensions;
Chris Lattner48af7d12018-07-09 19:05:38 -0700314 while (getToken().is(Token::integer)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700315 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700316 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700317 if (!dimension.hasValue())
Chris Lattnerf7e22732018-06-22 22:03:48 -0700318 return (emitError("invalid dimension in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700319 dimensions.push_back(dimension.getValue());
320
321 consumeToken(Token::integer);
322
323 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700324 if (getToken().isNot(Token::bare_identifier) ||
325 getTokenSpelling()[0] != 'x')
Chris Lattnerf7e22732018-06-22 22:03:48 -0700326 return (emitError("expected 'x' in vector dimension list"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700327
328 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700329 if (getTokenSpelling().size() != 1)
330 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700331
332 // Consume the 'x'.
333 consumeToken(Token::bare_identifier);
334 }
335
336 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700337 auto *elementType = parsePrimitiveType();
338 if (!elementType)
339 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700340
Chris Lattnerf7702a62018-07-23 17:30:01 -0700341 if (parseToken(Token::greater, "expected '>' in vector type"))
342 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700343
Chris Lattnerf7e22732018-06-22 22:03:48 -0700344 return VectorType::get(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700345}
346
347/// Parse a dimension list of a tensor or memref type. This populates the
348/// dimension list, returning -1 for the '?' dimensions.
349///
350/// dimension-list-ranked ::= (dimension `x`)*
351/// dimension ::= `?` | integer-literal
352///
353ParseResult Parser::parseDimensionListRanked(SmallVectorImpl<int> &dimensions) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700354 while (getToken().isAny(Token::integer, Token::question)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700355 if (consumeIf(Token::question)) {
356 dimensions.push_back(-1);
357 } else {
358 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700359 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700360 if (!dimension.hasValue() || (int)dimension.getValue() < 0)
361 return emitError("invalid dimension");
362 dimensions.push_back((int)dimension.getValue());
363 consumeToken(Token::integer);
364 }
365
366 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700367 if (getToken().isNot(Token::bare_identifier) ||
368 getTokenSpelling()[0] != 'x')
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700369 return emitError("expected 'x' in dimension list");
370
371 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700372 if (getTokenSpelling().size() != 1)
373 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700374
375 // Consume the 'x'.
376 consumeToken(Token::bare_identifier);
377 }
378
379 return ParseSuccess;
380}
381
382/// Parse a tensor type.
383///
384/// tensor-type ::= `tensor` `<` dimension-list element-type `>`
385/// dimension-list ::= dimension-list-ranked | `??`
386///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700387Type *Parser::parseTensorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700388 consumeToken(Token::kw_tensor);
389
Chris Lattnerf7702a62018-07-23 17:30:01 -0700390 if (parseToken(Token::less, "expected '<' in tensor type"))
391 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700392
393 bool isUnranked;
394 SmallVector<int, 4> dimensions;
395
396 if (consumeIf(Token::questionquestion)) {
397 isUnranked = true;
398 } else {
399 isUnranked = false;
400 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700401 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700402 }
403
404 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700405 auto elementType = parseElementType();
406 if (!elementType)
407 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700408
Chris Lattnerf7702a62018-07-23 17:30:01 -0700409 if (parseToken(Token::greater, "expected '>' in tensor type"))
410 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700411
MLIR Team355ec862018-06-23 18:09:09 -0700412 if (isUnranked)
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700413 return builder.getTensorType(elementType);
414 return builder.getTensorType(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700415}
416
417/// Parse a memref type.
418///
419/// memref-type ::= `memref` `<` dimension-list-ranked element-type
420/// (`,` semi-affine-map-composition)? (`,` memory-space)? `>`
421///
422/// semi-affine-map-composition ::= (semi-affine-map `,` )* semi-affine-map
423/// memory-space ::= integer-literal /* | TODO: address-space-id */
424///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700425Type *Parser::parseMemRefType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700426 consumeToken(Token::kw_memref);
427
Chris Lattnerf7702a62018-07-23 17:30:01 -0700428 if (parseToken(Token::less, "expected '<' in memref type"))
429 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700430
431 SmallVector<int, 4> dimensions;
432 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700433 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700434
435 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700436 auto elementType = parseElementType();
437 if (!elementType)
438 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700439
Chris Lattnerf7702a62018-07-23 17:30:01 -0700440 if (parseToken(Token::comma, "expected ',' in memref type"))
441 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700442
MLIR Team718c82f2018-07-16 09:45:22 -0700443 // Parse semi-affine-map-composition.
James Molloy0ff71542018-07-23 16:56:32 -0700444 SmallVector<AffineMap *, 2> affineMapComposition;
MLIR Team718c82f2018-07-16 09:45:22 -0700445 unsigned memorySpace;
446 bool parsedMemorySpace = false;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700447
MLIR Team718c82f2018-07-16 09:45:22 -0700448 auto parseElt = [&]() -> ParseResult {
449 if (getToken().is(Token::integer)) {
450 // Parse memory space.
451 if (parsedMemorySpace)
452 return emitError("multiple memory spaces specified in memref type");
453 auto v = getToken().getUnsignedIntegerValue();
454 if (!v.hasValue())
455 return emitError("invalid memory space in memref type");
456 memorySpace = v.getValue();
457 consumeToken(Token::integer);
458 parsedMemorySpace = true;
459 } else {
460 // Parse affine map.
461 if (parsedMemorySpace)
462 return emitError("affine map after memory space in memref type");
James Molloy0ff71542018-07-23 16:56:32 -0700463 auto *affineMap = parseAffineMapReference();
MLIR Team718c82f2018-07-16 09:45:22 -0700464 if (affineMap == nullptr)
465 return ParseFailure;
466 affineMapComposition.push_back(affineMap);
467 }
468 return ParseSuccess;
469 };
470
471 // Parse comma separated list of affine maps, followed by memory space.
Chris Lattner40746442018-07-21 14:32:09 -0700472 if (parseCommaSeparatedListUntil(Token::greater, parseElt,
473 /*allowEmptyList=*/false)) {
MLIR Team718c82f2018-07-16 09:45:22 -0700474 return nullptr;
475 }
476 // Check that MemRef type specifies at least one affine map in composition.
477 if (affineMapComposition.empty())
478 return (emitError("expected semi-affine-map in memref type"), nullptr);
479 if (!parsedMemorySpace)
480 return (emitError("expected memory space in memref type"), nullptr);
481
482 return MemRefType::get(dimensions, elementType, affineMapComposition,
483 memorySpace);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700484}
485
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700486/// Parse a function type.
487///
488/// function-type ::= type-list-parens `->` type-list
489///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700490Type *Parser::parseFunctionType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700491 assert(getToken().is(Token::l_paren));
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700492
Chris Lattnerf7702a62018-07-23 17:30:01 -0700493 SmallVector<Type *, 4> arguments, results;
494 if (parseTypeList(arguments) ||
495 parseToken(Token::arrow, "expected '->' in function type") ||
496 parseTypeList(results))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700497 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700498
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700499 return builder.getFunctionType(arguments, results);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700500}
501
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700502/// Parse an arbitrary type.
503///
504/// type ::= primitive-type
505/// | vector-type
506/// | tensor-type
507/// | memref-type
508/// | function-type
509/// element-type ::= primitive-type | vector-type
510///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700511Type *Parser::parseType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700512 switch (getToken().getKind()) {
James Molloy0ff71542018-07-23 16:56:32 -0700513 case Token::kw_memref:
514 return parseMemRefType();
515 case Token::kw_tensor:
516 return parseTensorType();
517 case Token::kw_vector:
518 return parseVectorType();
519 case Token::l_paren:
520 return parseFunctionType();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700521 default:
522 return parsePrimitiveType();
523 }
524}
525
Chris Lattner1604e472018-07-23 08:42:19 -0700526/// Parse a list of types without an enclosing parenthesis. The list must have
527/// at least one member.
528///
529/// type-list-no-parens ::= type (`,` type)*
530///
531ParseResult Parser::parseTypeListNoParens(SmallVectorImpl<Type *> &elements) {
532 auto parseElt = [&]() -> ParseResult {
533 auto elt = parseType();
534 elements.push_back(elt);
535 return elt ? ParseSuccess : ParseFailure;
536 };
537
538 return parseCommaSeparatedList(parseElt);
539}
540
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700541/// Parse a "type list", which is a singular type, or a parenthesized list of
542/// types.
543///
544/// type-list ::= type-list-parens | type
545/// type-list-parens ::= `(` `)`
Chris Lattner1604e472018-07-23 08:42:19 -0700546/// | `(` type-list-no-parens `)`
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700547///
James Molloy0ff71542018-07-23 16:56:32 -0700548ParseResult Parser::parseTypeList(SmallVectorImpl<Type *> &elements) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700549 auto parseElt = [&]() -> ParseResult {
550 auto elt = parseType();
551 elements.push_back(elt);
552 return elt ? ParseSuccess : ParseFailure;
553 };
554
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700555 // If there is no parens, then it must be a singular type.
556 if (!consumeIf(Token::l_paren))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700557 return parseElt();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700558
Chris Lattner40746442018-07-21 14:32:09 -0700559 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700560 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700561
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700562 return ParseSuccess;
563}
564
Chris Lattner4c95a502018-06-23 16:03:42 -0700565//===----------------------------------------------------------------------===//
Chris Lattner7121b802018-07-04 20:45:39 -0700566// Attribute parsing.
567//===----------------------------------------------------------------------===//
568
Chris Lattner7121b802018-07-04 20:45:39 -0700569/// Attribute parsing.
570///
571/// attribute-value ::= bool-literal
572/// | integer-literal
573/// | float-literal
574/// | string-literal
575/// | `[` (attribute-value (`,` attribute-value)*)? `]`
576///
577Attribute *Parser::parseAttribute() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700578 switch (getToken().getKind()) {
Chris Lattner7121b802018-07-04 20:45:39 -0700579 case Token::kw_true:
580 consumeToken(Token::kw_true);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700581 return builder.getBoolAttr(true);
Chris Lattner7121b802018-07-04 20:45:39 -0700582 case Token::kw_false:
583 consumeToken(Token::kw_false);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700584 return builder.getBoolAttr(false);
Chris Lattner7121b802018-07-04 20:45:39 -0700585
586 case Token::integer: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700587 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700588 if (!val.hasValue() || (int64_t)val.getValue() < 0)
589 return (emitError("integer too large for attribute"), nullptr);
590 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700591 return builder.getIntegerAttr((int64_t)val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700592 }
593
594 case Token::minus: {
595 consumeToken(Token::minus);
Chris Lattner48af7d12018-07-09 19:05:38 -0700596 if (getToken().is(Token::integer)) {
597 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700598 if (!val.hasValue() || (int64_t)-val.getValue() >= 0)
599 return (emitError("integer too large for attribute"), nullptr);
600 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700601 return builder.getIntegerAttr((int64_t)-val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700602 }
603
604 return (emitError("expected constant integer or floating point value"),
605 nullptr);
606 }
607
608 case Token::string: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700609 auto val = getToken().getStringValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700610 consumeToken(Token::string);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700611 return builder.getStringAttr(val);
Chris Lattner7121b802018-07-04 20:45:39 -0700612 }
613
614 case Token::l_bracket: {
615 consumeToken(Token::l_bracket);
James Molloy0ff71542018-07-23 16:56:32 -0700616 SmallVector<Attribute *, 4> elements;
Chris Lattner7121b802018-07-04 20:45:39 -0700617
618 auto parseElt = [&]() -> ParseResult {
619 elements.push_back(parseAttribute());
620 return elements.back() ? ParseSuccess : ParseFailure;
621 };
622
Chris Lattner40746442018-07-21 14:32:09 -0700623 if (parseCommaSeparatedListUntil(Token::r_bracket, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700624 return nullptr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700625 return builder.getArrayAttr(elements);
Chris Lattner7121b802018-07-04 20:45:39 -0700626 }
627 default:
MLIR Teamb61885d2018-07-18 16:29:21 -0700628 // Try to parse affine map reference.
James Molloy0ff71542018-07-23 16:56:32 -0700629 auto *affineMap = parseAffineMapReference();
MLIR Teamb61885d2018-07-18 16:29:21 -0700630 if (affineMap != nullptr)
631 return builder.getAffineMapAttr(affineMap);
632
Chris Lattner7121b802018-07-04 20:45:39 -0700633 // TODO: Handle floating point.
634 return (emitError("expected constant attribute value"), nullptr);
635 }
636}
637
Chris Lattner7121b802018-07-04 20:45:39 -0700638/// Attribute dictionary.
639///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700640/// attribute-dict ::= `{` `}`
641/// | `{` attribute-entry (`,` attribute-entry)* `}`
642/// attribute-entry ::= bare-id `:` attribute-value
Chris Lattner7121b802018-07-04 20:45:39 -0700643///
James Molloy0ff71542018-07-23 16:56:32 -0700644ParseResult
645Parser::parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes) {
Chris Lattner7121b802018-07-04 20:45:39 -0700646 consumeToken(Token::l_brace);
647
648 auto parseElt = [&]() -> ParseResult {
649 // We allow keywords as attribute names.
Chris Lattner48af7d12018-07-09 19:05:38 -0700650 if (getToken().isNot(Token::bare_identifier, Token::inttype) &&
651 !getToken().isKeyword())
Chris Lattner7121b802018-07-04 20:45:39 -0700652 return emitError("expected attribute name");
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700653 auto nameId = builder.getIdentifier(getTokenSpelling());
Chris Lattner7121b802018-07-04 20:45:39 -0700654 consumeToken();
655
Chris Lattnerf7702a62018-07-23 17:30:01 -0700656 if (parseToken(Token::colon, "expected ':' in attribute list"))
657 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700658
659 auto attr = parseAttribute();
James Molloy0ff71542018-07-23 16:56:32 -0700660 if (!attr)
661 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700662
663 attributes.push_back({nameId, attr});
664 return ParseSuccess;
665 };
666
Chris Lattner40746442018-07-21 14:32:09 -0700667 if (parseCommaSeparatedListUntil(Token::r_brace, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700668 return ParseFailure;
669
670 return ParseSuccess;
671}
672
673//===----------------------------------------------------------------------===//
MLIR Teamf85a6262018-06-27 11:03:08 -0700674// Polyhedral structures.
675//===----------------------------------------------------------------------===//
676
Chris Lattner2e595eb2018-07-10 10:08:27 -0700677/// Lower precedence ops (all at the same precedence level). LNoOp is false in
678/// the boolean sense.
679enum AffineLowPrecOp {
680 /// Null value.
681 LNoOp,
682 Add,
683 Sub
684};
MLIR Teamf85a6262018-06-27 11:03:08 -0700685
Chris Lattner2e595eb2018-07-10 10:08:27 -0700686/// Higher precedence ops - all at the same precedence level. HNoOp is false in
687/// the boolean sense.
688enum AffineHighPrecOp {
689 /// Null value.
690 HNoOp,
691 Mul,
692 FloorDiv,
693 CeilDiv,
694 Mod
695};
Chris Lattner7121b802018-07-04 20:45:39 -0700696
Chris Lattner2e595eb2018-07-10 10:08:27 -0700697namespace {
698/// This is a specialized parser for AffineMap's, maintaining the state
699/// transient to their bodies.
700class AffineMapParser : public Parser {
701public:
702 explicit AffineMapParser(ParserState &state) : Parser(state) {}
Chris Lattner7121b802018-07-04 20:45:39 -0700703
Chris Lattner2e595eb2018-07-10 10:08:27 -0700704 AffineMap *parseAffineMapInline();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700705
Chris Lattner2e595eb2018-07-10 10:08:27 -0700706private:
707 unsigned getNumDims() const { return dims.size(); }
708 unsigned getNumSymbols() const { return symbols.size(); }
MLIR Teamf85a6262018-06-27 11:03:08 -0700709
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700710 /// Returns true if the only identifiers the parser accepts in affine
711 /// expressions are symbolic identifiers.
712 bool isPureSymbolic() const { return pureSymbolic; }
713 void setSymbolicParsing(bool val) { pureSymbolic = val; }
714
Chris Lattner2e595eb2018-07-10 10:08:27 -0700715 // Binary affine op parsing.
716 AffineLowPrecOp consumeIfLowPrecOp();
717 AffineHighPrecOp consumeIfHighPrecOp();
MLIR Teamf85a6262018-06-27 11:03:08 -0700718
Chris Lattner2e595eb2018-07-10 10:08:27 -0700719 // Identifier lists for polyhedral structures.
720 ParseResult parseDimIdList();
721 ParseResult parseSymbolIdList();
722 ParseResult parseDimOrSymbolId(bool isDim);
723
724 AffineExpr *parseAffineExpr();
725 AffineExpr *parseParentheticalExpr();
726 AffineExpr *parseNegateExpression(AffineExpr *lhs);
727 AffineExpr *parseIntegerExpr();
728 AffineExpr *parseBareIdExpr();
729
730 AffineExpr *getBinaryAffineOpExpr(AffineHighPrecOp op, AffineExpr *lhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700731 AffineExpr *rhs, SMLoc opLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700732 AffineExpr *getBinaryAffineOpExpr(AffineLowPrecOp op, AffineExpr *lhs,
733 AffineExpr *rhs);
734 AffineExpr *parseAffineOperandExpr(AffineExpr *lhs);
735 AffineExpr *parseAffineLowPrecOpExpr(AffineExpr *llhs,
736 AffineLowPrecOp llhsOp);
737 AffineExpr *parseAffineHighPrecOpExpr(AffineExpr *llhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700738 AffineHighPrecOp llhsOp,
739 SMLoc llhsOpLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700740
741private:
742 // TODO(bondhugula): could just use an vector/ArrayRef and scan the numbers.
743 llvm::StringMap<unsigned> dims;
744 llvm::StringMap<unsigned> symbols;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700745 /// True if the parser should allow only symbolic identifiers in affine
746 /// expressions.
747 bool pureSymbolic = false;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700748};
749} // end anonymous namespace
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700750
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700751/// Create an affine binary high precedence op expression (mul's, div's, mod).
752/// opLoc is the location of the op token to be used to report errors
753/// for non-conforming expressions.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700754AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineHighPrecOp op,
755 AffineExpr *lhs,
Chris Lattner40746442018-07-21 14:32:09 -0700756 AffineExpr *rhs,
757 SMLoc opLoc) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700758 // TODO: make the error location info accurate.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700759 switch (op) {
760 case Mul:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700761 if (!lhs->isSymbolicOrConstant() && !rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700762 emitError(opLoc, "non-affine expression: at least one of the multiply "
763 "operands has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700764 return nullptr;
765 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700766 return builder.getMulExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700767 case FloorDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700768 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700769 emitError(opLoc, "non-affine expression: right operand of floordiv "
770 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700771 return nullptr;
772 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700773 return builder.getFloorDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700774 case CeilDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700775 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700776 emitError(opLoc, "non-affine expression: right operand of ceildiv "
777 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700778 return nullptr;
779 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700780 return builder.getCeilDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700781 case Mod:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700782 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700783 emitError(opLoc, "non-affine expression: right operand of mod "
784 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700785 return nullptr;
786 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700787 return builder.getModExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700788 case HNoOp:
789 llvm_unreachable("can't create affine expression for null high prec op");
790 return nullptr;
791 }
792}
793
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700794/// Create an affine binary low precedence op expression (add, sub).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700795AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineLowPrecOp op,
796 AffineExpr *lhs,
797 AffineExpr *rhs) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700798 switch (op) {
799 case AffineLowPrecOp::Add:
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700800 return builder.getAddExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700801 case AffineLowPrecOp::Sub:
Uday Bondhugulac1faf662018-07-19 14:08:50 -0700802 return builder.getAddExpr(
803 lhs, builder.getMulExpr(rhs, builder.getConstantExpr(-1)));
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700804 case AffineLowPrecOp::LNoOp:
805 llvm_unreachable("can't create affine expression for null low prec op");
806 return nullptr;
807 }
808}
809
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700810/// Consume this token if it is a lower precedence affine op (there are only two
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700811/// precedence levels).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700812AffineLowPrecOp AffineMapParser::consumeIfLowPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700813 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700814 case Token::plus:
815 consumeToken(Token::plus);
816 return AffineLowPrecOp::Add;
817 case Token::minus:
818 consumeToken(Token::minus);
819 return AffineLowPrecOp::Sub;
820 default:
821 return AffineLowPrecOp::LNoOp;
822 }
823}
824
825/// Consume this token if it is a higher precedence affine op (there are only
826/// two precedence levels)
Chris Lattner2e595eb2018-07-10 10:08:27 -0700827AffineHighPrecOp AffineMapParser::consumeIfHighPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700828 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700829 case Token::star:
830 consumeToken(Token::star);
831 return Mul;
832 case Token::kw_floordiv:
833 consumeToken(Token::kw_floordiv);
834 return FloorDiv;
835 case Token::kw_ceildiv:
836 consumeToken(Token::kw_ceildiv);
837 return CeilDiv;
838 case Token::kw_mod:
839 consumeToken(Token::kw_mod);
840 return Mod;
841 default:
842 return HNoOp;
843 }
844}
845
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700846/// Parse a high precedence op expression list: mul, div, and mod are high
847/// precedence binary ops, i.e., parse a
848/// expr_1 op_1 expr_2 op_2 ... expr_n
849/// where op_1, op_2 are all a AffineHighPrecOp (mul, div, mod).
850/// All affine binary ops are left associative.
851/// Given llhs, returns (llhs llhsOp lhs) op rhs, or (lhs op rhs) if llhs is
852/// null. If no rhs can be found, returns (llhs llhsOp lhs) or lhs if llhs is
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700853/// null. llhsOpLoc is the location of the llhsOp token that will be used to
854/// report an error for non-conforming expressions.
855AffineExpr *AffineMapParser::parseAffineHighPrecOpExpr(AffineExpr *llhs,
856 AffineHighPrecOp llhsOp,
857 SMLoc llhsOpLoc) {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700858 AffineExpr *lhs = parseAffineOperandExpr(llhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700859 if (!lhs)
860 return nullptr;
861
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700862 // Found an LHS. Parse the remaining expression.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700863 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -0700864 if (AffineHighPrecOp op = consumeIfHighPrecOp()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700865 if (llhs) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700866 AffineExpr *expr = getBinaryAffineOpExpr(llhsOp, llhs, lhs, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700867 if (!expr)
868 return nullptr;
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700869 return parseAffineHighPrecOpExpr(expr, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700870 }
871 // No LLHS, get RHS
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700872 return parseAffineHighPrecOpExpr(lhs, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700873 }
874
875 // This is the last operand in this expression.
876 if (llhs)
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700877 return getBinaryAffineOpExpr(llhsOp, llhs, lhs, llhsOpLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700878
879 // No llhs, 'lhs' itself is the expression.
880 return lhs;
881}
882
883/// Parse an affine expression inside parentheses.
884///
885/// affine-expr ::= `(` affine-expr `)`
Chris Lattner2e595eb2018-07-10 10:08:27 -0700886AffineExpr *AffineMapParser::parseParentheticalExpr() {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700887 if (parseToken(Token::l_paren, "expected '('"))
888 return nullptr;
Chris Lattner48af7d12018-07-09 19:05:38 -0700889 if (getToken().is(Token::r_paren))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700890 return (emitError("no expression inside parentheses"), nullptr);
Chris Lattnerf7702a62018-07-23 17:30:01 -0700891
Chris Lattner2e595eb2018-07-10 10:08:27 -0700892 auto *expr = parseAffineExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700893 if (!expr)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700894 return nullptr;
Chris Lattnerf7702a62018-07-23 17:30:01 -0700895 if (parseToken(Token::r_paren, "expected ')'"))
896 return nullptr;
897
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700898 return expr;
899}
900
901/// Parse the negation expression.
902///
903/// affine-expr ::= `-` affine-expr
Chris Lattner2e595eb2018-07-10 10:08:27 -0700904AffineExpr *AffineMapParser::parseNegateExpression(AffineExpr *lhs) {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700905 if (parseToken(Token::minus, "expected '-'"))
906 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700907
Chris Lattner2e595eb2018-07-10 10:08:27 -0700908 AffineExpr *operand = parseAffineOperandExpr(lhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700909 // Since negation has the highest precedence of all ops (including high
910 // precedence ops) but lower than parentheses, we are only going to use
911 // parseAffineOperandExpr instead of parseAffineExpr here.
912 if (!operand)
913 // Extra error message although parseAffineOperandExpr would have
914 // complained. Leads to a better diagnostic.
915 return (emitError("missing operand of negation"), nullptr);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700916 auto *minusOne = builder.getConstantExpr(-1);
917 return builder.getMulExpr(minusOne, operand);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700918}
919
920/// Parse a bare id that may appear in an affine expression.
921///
922/// affine-expr ::= bare-id
Chris Lattner2e595eb2018-07-10 10:08:27 -0700923AffineExpr *AffineMapParser::parseBareIdExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700924 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700925 return (emitError("expected bare identifier"), nullptr);
926
Chris Lattner48af7d12018-07-09 19:05:38 -0700927 StringRef sRef = getTokenSpelling();
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700928 // dims, symbols are all pairwise distinct.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700929 if (dims.count(sRef)) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700930 if (isPureSymbolic())
931 return (emitError("identifier used is not a symbolic identifier"),
932 nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700933 consumeToken(Token::bare_identifier);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700934 return builder.getDimExpr(dims.lookup(sRef));
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700935 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700936
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700937 if (symbols.count(sRef)) {
938 consumeToken(Token::bare_identifier);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700939 return builder.getSymbolExpr(symbols.lookup(sRef));
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700940 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700941
942 return (emitError("use of undeclared identifier"), nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700943}
944
945/// Parse a positive integral constant appearing in an affine expression.
946///
947/// affine-expr ::= integer-literal
Chris Lattner2e595eb2018-07-10 10:08:27 -0700948AffineExpr *AffineMapParser::parseIntegerExpr() {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700949 // No need to handle negative numbers separately here. They are naturally
950 // handled via the unary negation operator, although (FIXME) MININT_64 still
951 // not correctly handled.
Chris Lattner48af7d12018-07-09 19:05:38 -0700952 if (getToken().isNot(Token::integer))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700953 return (emitError("expected integer"), nullptr);
954
Chris Lattner48af7d12018-07-09 19:05:38 -0700955 auto val = getToken().getUInt64IntegerValue();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700956 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
957 return (emitError("constant too large for affineint"), nullptr);
958 }
959 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700960 return builder.getConstantExpr((int64_t)val.getValue());
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700961}
962
963/// Parses an expression that can be a valid operand of an affine expression.
Uday Bondhugula76345202018-07-09 13:47:52 -0700964/// lhs: if non-null, lhs is an affine expression that is the lhs of a binary
965/// operator, the rhs of which is being parsed. This is used to determine
966/// whether an error should be emitted for a missing right operand.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700967// Eg: for an expression without parentheses (like i + j + k + l), each
968// of the four identifiers is an operand. For i + j*k + l, j*k is not an
969// operand expression, it's an op expression and will be parsed via
970// parseAffineHighPrecOpExpression(). However, for i + (j*k) + -l, (j*k) and -l
971// are valid operands that will be parsed by this function.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700972AffineExpr *AffineMapParser::parseAffineOperandExpr(AffineExpr *lhs) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700973 switch (getToken().getKind()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700974 case Token::bare_identifier:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700975 return parseBareIdExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700976 case Token::integer:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700977 return parseIntegerExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700978 case Token::l_paren:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700979 return parseParentheticalExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700980 case Token::minus:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700981 return parseNegateExpression(lhs);
Uday Bondhugula76345202018-07-09 13:47:52 -0700982 case Token::kw_ceildiv:
983 case Token::kw_floordiv:
984 case Token::kw_mod:
985 case Token::plus:
986 case Token::star:
987 if (lhs)
988 emitError("missing right operand of binary operator");
989 else
990 emitError("missing left operand of binary operator");
991 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700992 default:
993 if (lhs)
Uday Bondhugula76345202018-07-09 13:47:52 -0700994 emitError("missing right operand of binary operator");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700995 else
996 emitError("expected affine expression");
997 return nullptr;
998 }
999}
1000
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001001/// Parse affine expressions that are bare-id's, integer constants,
1002/// parenthetical affine expressions, and affine op expressions that are a
1003/// composition of those.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001004///
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001005/// All binary op's associate from left to right.
1006///
1007/// {add, sub} have lower precedence than {mul, div, and mod}.
1008///
Uday Bondhugula76345202018-07-09 13:47:52 -07001009/// Add, sub'are themselves at the same precedence level. Mul, floordiv,
1010/// ceildiv, and mod are at the same higher precedence level. Negation has
1011/// higher precedence than any binary op.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001012///
1013/// llhs: the affine expression appearing on the left of the one being parsed.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001014/// This function will return ((llhs llhsOp lhs) op rhs) if llhs is non null,
1015/// and lhs op rhs otherwise; if there is no rhs, llhs llhsOp lhs is returned if
1016/// llhs is non-null; otherwise lhs is returned. This is to deal with left
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001017/// associativity.
1018///
1019/// Eg: when the expression is e1 + e2*e3 + e4, with e1 as llhs, this function
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001020/// will return the affine expr equivalent of (e1 + (e2*e3)) + e4, where (e2*e3)
1021/// will be parsed using parseAffineHighPrecOpExpr().
Chris Lattner2e595eb2018-07-10 10:08:27 -07001022AffineExpr *AffineMapParser::parseAffineLowPrecOpExpr(AffineExpr *llhs,
1023 AffineLowPrecOp llhsOp) {
Uday Bondhugula76345202018-07-09 13:47:52 -07001024 AffineExpr *lhs;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001025 if (!(lhs = parseAffineOperandExpr(llhs)))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001026 return nullptr;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001027
1028 // Found an LHS. Deal with the ops.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001029 if (AffineLowPrecOp lOp = consumeIfLowPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001030 if (llhs) {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001031 AffineExpr *sum = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001032 return parseAffineLowPrecOpExpr(sum, lOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001033 }
1034 // No LLHS, get RHS and form the expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001035 return parseAffineLowPrecOpExpr(lhs, lOp);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001036 }
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001037 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07001038 if (AffineHighPrecOp hOp = consumeIfHighPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001039 // We have a higher precedence op here. Get the rhs operand for the llhs
1040 // through parseAffineHighPrecOpExpr.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001041 AffineExpr *highRes = parseAffineHighPrecOpExpr(lhs, hOp, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001042 if (!highRes)
1043 return nullptr;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001044
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001045 // If llhs is null, the product forms the first operand of the yet to be
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001046 // found expression. If non-null, the op to associate with llhs is llhsOp.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001047 AffineExpr *expr =
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001048 llhs ? getBinaryAffineOpExpr(llhsOp, llhs, highRes) : highRes;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001049
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001050 // Recurse for subsequent low prec op's after the affine high prec op
1051 // expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001052 if (AffineLowPrecOp nextOp = consumeIfLowPrecOp())
1053 return parseAffineLowPrecOpExpr(expr, nextOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001054 return expr;
1055 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001056 // Last operand in the expression list.
1057 if (llhs)
1058 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
1059 // No llhs, 'lhs' itself is the expression.
1060 return lhs;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001061}
1062
1063/// Parse an affine expression.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001064/// affine-expr ::= `(` affine-expr `)`
1065/// | `-` affine-expr
1066/// | affine-expr `+` affine-expr
1067/// | affine-expr `-` affine-expr
1068/// | affine-expr `*` affine-expr
1069/// | affine-expr `floordiv` affine-expr
1070/// | affine-expr `ceildiv` affine-expr
1071/// | affine-expr `mod` affine-expr
1072/// | bare-id
1073/// | integer-literal
1074///
1075/// Additional conditions are checked depending on the production. For eg., one
1076/// of the operands for `*` has to be either constant/symbolic; the second
1077/// operand for floordiv, ceildiv, and mod has to be a positive integer.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001078AffineExpr *AffineMapParser::parseAffineExpr() {
1079 return parseAffineLowPrecOpExpr(nullptr, AffineLowPrecOp::LNoOp);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001080}
1081
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001082/// Parse a dim or symbol from the lists appearing before the actual expressions
Chris Lattner2e595eb2018-07-10 10:08:27 -07001083/// of the affine map. Update our state to store the dimensional/symbolic
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001084/// identifier. 'dim': whether it's the dim list or symbol list that is being
1085/// parsed.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001086ParseResult AffineMapParser::parseDimOrSymbolId(bool isDim) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001087 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001088 return emitError("expected bare identifier");
Chris Lattner48af7d12018-07-09 19:05:38 -07001089 auto sRef = getTokenSpelling();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001090 consumeToken(Token::bare_identifier);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001091 if (dims.count(sRef))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001092 return emitError("dimensional identifier name reused");
Chris Lattner2e595eb2018-07-10 10:08:27 -07001093 if (symbols.count(sRef))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001094 return emitError("symbolic identifier name reused");
Chris Lattner2e595eb2018-07-10 10:08:27 -07001095 if (isDim)
1096 dims.insert({sRef, dims.size()});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001097 else
Chris Lattner2e595eb2018-07-10 10:08:27 -07001098 symbols.insert({sRef, symbols.size()});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001099 return ParseSuccess;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001100}
1101
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001102/// Parse the list of symbolic identifiers to an affine map.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001103ParseResult AffineMapParser::parseSymbolIdList() {
Chris Lattnerf7702a62018-07-23 17:30:01 -07001104 if (parseToken(Token::l_bracket, "expected '['"))
1105 return ParseFailure;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001106
Chris Lattner2e595eb2018-07-10 10:08:27 -07001107 auto parseElt = [&]() -> ParseResult { return parseDimOrSymbolId(false); };
Chris Lattner40746442018-07-21 14:32:09 -07001108 return parseCommaSeparatedListUntil(Token::r_bracket, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001109}
1110
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001111/// Parse the list of dimensional identifiers to an affine map.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001112ParseResult AffineMapParser::parseDimIdList() {
Chris Lattnerf7702a62018-07-23 17:30:01 -07001113 if (parseToken(Token::l_paren,
1114 "expected '(' at start of dimensional identifiers list"))
1115 return ParseFailure;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001116
Chris Lattner2e595eb2018-07-10 10:08:27 -07001117 auto parseElt = [&]() -> ParseResult { return parseDimOrSymbolId(true); };
Chris Lattner40746442018-07-21 14:32:09 -07001118 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001119}
1120
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001121/// Parse an affine map definition.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001122///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001123/// affine-map-inline ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
1124/// (`size` `(` dim-size (`,` dim-size)* `)`)?
1125/// dim-size ::= affine-expr | `min` `(` affine-expr ( `,` affine-expr)+ `)`
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001126///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001127/// multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner2e595eb2018-07-10 10:08:27 -07001128AffineMap *AffineMapParser::parseAffineMapInline() {
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001129 // List of dimensional identifiers.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001130 if (parseDimIdList())
Chris Lattner7121b802018-07-04 20:45:39 -07001131 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001132
1133 // Symbols are optional.
Chris Lattner48af7d12018-07-09 19:05:38 -07001134 if (getToken().is(Token::l_bracket)) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001135 if (parseSymbolIdList())
Chris Lattner7121b802018-07-04 20:45:39 -07001136 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001137 }
Chris Lattnerf7702a62018-07-23 17:30:01 -07001138
1139 if (parseToken(Token::arrow, "expected '->' or '['") ||
1140 parseToken(Token::l_paren, "expected '(' at start of affine map range"))
Chris Lattner7121b802018-07-04 20:45:39 -07001141 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001142
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001143 SmallVector<AffineExpr *, 4> exprs;
1144 auto parseElt = [&]() -> ParseResult {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001145 auto *elt = parseAffineExpr();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001146 ParseResult res = elt ? ParseSuccess : ParseFailure;
1147 exprs.push_back(elt);
1148 return res;
1149 };
1150
1151 // Parse a multi-dimensional affine expression (a comma-separated list of 1-d
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001152 // affine expressions); the list cannot be empty.
1153 // Grammar: multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner40746442018-07-21 14:32:09 -07001154 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt, false))
Chris Lattner7121b802018-07-04 20:45:39 -07001155 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001156
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001157 // Parse optional range sizes.
Uday Bondhugula1e500b42018-07-12 18:04:04 -07001158 // range-sizes ::= (`size` `(` dim-size (`,` dim-size)* `)`)?
1159 // dim-size ::= affine-expr | `min` `(` affine-expr (`,` affine-expr)+ `)`
1160 // TODO(bondhugula): support for min of several affine expressions.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001161 // TODO: check if sizes are non-negative whenever they are constant.
1162 SmallVector<AffineExpr *, 4> rangeSizes;
1163 if (consumeIf(Token::kw_size)) {
1164 // Location of the l_paren token (if it exists) for error reporting later.
1165 auto loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001166 if (parseToken(Token::l_paren, "expected '(' at start of affine map range"))
1167 return nullptr;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001168
1169 auto parseRangeSize = [&]() -> ParseResult {
1170 auto *elt = parseAffineExpr();
1171 ParseResult res = elt ? ParseSuccess : ParseFailure;
1172 rangeSizes.push_back(elt);
1173 return res;
1174 };
1175
1176 setSymbolicParsing(true);
Chris Lattner40746442018-07-21 14:32:09 -07001177 if (parseCommaSeparatedListUntil(Token::r_paren, parseRangeSize, false))
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001178 return nullptr;
1179 if (exprs.size() > rangeSizes.size())
1180 return (emitError(loc, "fewer range sizes than range expressions"),
1181 nullptr);
1182 if (exprs.size() < rangeSizes.size())
1183 return (emitError(loc, "more range sizes than range expressions"),
1184 nullptr);
1185 }
1186
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001187 // Parsed a valid affine map.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001188 return builder.getAffineMap(dims.size(), symbols.size(), exprs, rangeSizes);
MLIR Teamf85a6262018-06-27 11:03:08 -07001189}
1190
Chris Lattner2e595eb2018-07-10 10:08:27 -07001191AffineMap *Parser::parseAffineMapInline() {
1192 return AffineMapParser(state).parseAffineMapInline();
1193}
1194
MLIR Team718c82f2018-07-16 09:45:22 -07001195AffineMap *Parser::parseAffineMapReference() {
1196 if (getToken().is(Token::hash_identifier)) {
1197 // Parse affine map identifier and verify that it exists.
1198 StringRef affineMapId = getTokenSpelling().drop_front();
1199 if (getState().affineMapDefinitions.count(affineMapId) == 0)
1200 return (emitError("undefined affine map id '" + affineMapId + "'"),
1201 nullptr);
1202 consumeToken(Token::hash_identifier);
1203 return getState().affineMapDefinitions[affineMapId];
1204 }
1205 // Try to parse inline affine map.
1206 return parseAffineMapInline();
1207}
1208
MLIR Teamf85a6262018-06-27 11:03:08 -07001209//===----------------------------------------------------------------------===//
Chris Lattner7f9cc272018-07-19 08:35:28 -07001210// FunctionParser
Chris Lattner4c95a502018-06-23 16:03:42 -07001211//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001212
Chris Lattner7f9cc272018-07-19 08:35:28 -07001213namespace {
1214/// This class contains parser state that is common across CFG and ML functions,
1215/// notably for dealing with operations and SSA values.
1216class FunctionParser : public Parser {
1217public:
1218 FunctionParser(ParserState &state) : Parser(state) {}
1219
Chris Lattner6119d382018-07-20 18:41:34 -07001220 /// After the function is finished parsing, this function checks to see if
1221 /// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001222 ParseResult finalizeFunction(Function *func, SMLoc loc);
Chris Lattner6119d382018-07-20 18:41:34 -07001223
1224 /// This represents a use of an SSA value in the program. The first two
1225 /// entries in the tuple are the name and result number of a reference. The
1226 /// third is the location of the reference, which is used in case this ends up
1227 /// being a use of an undefined value.
1228 struct SSAUseInfo {
1229 StringRef name; // Value name, e.g. %42 or %abc
1230 unsigned number; // Number, specified with #12
1231 SMLoc loc; // Location of first definition or use.
1232 };
Chris Lattner7f9cc272018-07-19 08:35:28 -07001233
1234 /// Given a reference to an SSA value and its type, return a reference. This
1235 /// returns null on failure.
1236 SSAValue *resolveSSAUse(SSAUseInfo useInfo, Type *type);
1237
1238 /// Register a definition of a value with the symbol table.
1239 ParseResult addDefinition(SSAUseInfo useInfo, SSAValue *value);
1240
1241 // SSA parsing productions.
1242 ParseResult parseSSAUse(SSAUseInfo &result);
Chris Lattner40746442018-07-21 14:32:09 -07001243 ParseResult parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results);
James Molloy61a656c2018-07-22 15:45:24 -07001244
1245 template <typename ResultType>
1246 ResultType parseSSADefOrUseAndType(
1247 const std::function<ResultType(SSAUseInfo, Type *)> &action);
1248
1249 SSAValue *parseSSAUseAndType() {
1250 return parseSSADefOrUseAndType<SSAValue *>(
1251 [&](SSAUseInfo useInfo, Type *type) -> SSAValue * {
1252 return resolveSSAUse(useInfo, type);
1253 });
1254 }
Chris Lattner40746442018-07-21 14:32:09 -07001255
1256 template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001257 ParseResult
Chris Lattner2c402672018-07-23 11:56:17 -07001258 parseOptionalSSAUseAndTypeList(SmallVectorImpl<ValueTy *> &results,
1259 bool isParenthesized);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001260
1261 // Operations
1262 ParseResult parseOperation(const CreateOperationFunction &createOpFunc);
1263
1264private:
1265 /// This keeps track of all of the SSA values we are tracking, indexed by
Chris Lattner6119d382018-07-20 18:41:34 -07001266 /// their name. This has one entry per result number.
1267 llvm::StringMap<SmallVector<std::pair<SSAValue *, SMLoc>, 1>> values;
1268
1269 /// These are all of the placeholders we've made along with the location of
1270 /// their first reference, to allow checking for use of undefined values.
1271 DenseMap<SSAValue *, SMLoc> forwardReferencePlaceholders;
1272
1273 SSAValue *createForwardReferencePlaceholder(SMLoc loc, Type *type);
1274
1275 /// Return true if this is a forward reference.
1276 bool isForwardReferencePlaceholder(SSAValue *value) {
1277 return forwardReferencePlaceholders.count(value);
1278 }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001279};
1280} // end anonymous namespace
1281
Chris Lattner6119d382018-07-20 18:41:34 -07001282/// Create and remember a new placeholder for a forward reference.
1283SSAValue *FunctionParser::createForwardReferencePlaceholder(SMLoc loc,
1284 Type *type) {
1285 // Forward references are always created as instructions, even in ML
1286 // functions, because we just need something with a def/use chain.
1287 //
1288 // We create these placeholders as having an empty name, which we know cannot
1289 // be created through normal user input, allowing us to distinguish them.
1290 auto name = Identifier::get("placeholder", getContext());
1291 auto *inst = OperationInst::create(name, /*operands*/ {}, type, /*attrs*/ {},
1292 getContext());
1293 forwardReferencePlaceholders[inst->getResult(0)] = loc;
1294 return inst->getResult(0);
1295}
1296
Chris Lattner7f9cc272018-07-19 08:35:28 -07001297/// Given an unbound reference to an SSA value and its type, return a the value
1298/// it specifies. This returns null on failure.
1299SSAValue *FunctionParser::resolveSSAUse(SSAUseInfo useInfo, Type *type) {
Chris Lattner6119d382018-07-20 18:41:34 -07001300 auto &entries = values[useInfo.name];
1301
Chris Lattner7f9cc272018-07-19 08:35:28 -07001302 // If we have already seen a value of this name, return it.
Chris Lattner6119d382018-07-20 18:41:34 -07001303 if (useInfo.number < entries.size() && entries[useInfo.number].first) {
1304 auto *result = entries[useInfo.number].first;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001305 // Check that the type matches the other uses.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001306 if (result->getType() == type)
1307 return result;
1308
Chris Lattner6119d382018-07-20 18:41:34 -07001309 emitError(useInfo.loc, "use of value '" + useInfo.name.str() +
1310 "' expects different type than prior uses");
1311 emitError(entries[useInfo.number].second, "prior use here");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001312 return nullptr;
1313 }
1314
Chris Lattner6119d382018-07-20 18:41:34 -07001315 // Make sure we have enough slots for this.
1316 if (entries.size() <= useInfo.number)
1317 entries.resize(useInfo.number + 1);
1318
1319 // If the value has already been defined and this is an overly large result
1320 // number, diagnose that.
1321 if (entries[0].first && !isForwardReferencePlaceholder(entries[0].first))
1322 return (emitError(useInfo.loc, "reference to invalid result number"),
1323 nullptr);
1324
1325 // Otherwise, this is a forward reference. Create a placeholder and remember
1326 // that we did so.
1327 auto *result = createForwardReferencePlaceholder(useInfo.loc, type);
1328 entries[useInfo.number].first = result;
1329 entries[useInfo.number].second = useInfo.loc;
1330 return result;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001331}
1332
1333/// Register a definition of a value with the symbol table.
1334ParseResult FunctionParser::addDefinition(SSAUseInfo useInfo, SSAValue *value) {
Chris Lattner6119d382018-07-20 18:41:34 -07001335 auto &entries = values[useInfo.name];
Chris Lattner7f9cc272018-07-19 08:35:28 -07001336
Chris Lattner6119d382018-07-20 18:41:34 -07001337 // Make sure there is a slot for this value.
1338 if (entries.size() <= useInfo.number)
1339 entries.resize(useInfo.number + 1);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001340
Chris Lattner6119d382018-07-20 18:41:34 -07001341 // If we already have an entry for this, check to see if it was a definition
1342 // or a forward reference.
1343 if (auto *existing = entries[useInfo.number].first) {
1344 if (!isForwardReferencePlaceholder(existing)) {
1345 emitError(useInfo.loc,
1346 "redefinition of SSA value '" + useInfo.name + "'");
1347 return emitError(entries[useInfo.number].second,
1348 "previously defined here");
1349 }
1350
1351 // If it was a forward reference, update everything that used it to use the
1352 // actual definition instead, delete the forward ref, and remove it from our
1353 // set of forward references we track.
1354 existing->replaceAllUsesWith(value);
1355 existing->getDefiningInst()->destroy();
1356 forwardReferencePlaceholders.erase(existing);
1357 }
1358
1359 entries[useInfo.number].first = value;
1360 entries[useInfo.number].second = useInfo.loc;
1361 return ParseSuccess;
1362}
1363
1364/// After the function is finished parsing, this function checks to see if
1365/// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001366ParseResult FunctionParser::finalizeFunction(Function *func, SMLoc loc) {
Chris Lattner6119d382018-07-20 18:41:34 -07001367 // Check for any forward references that are left. If we find any, error out.
1368 if (!forwardReferencePlaceholders.empty()) {
1369 SmallVector<std::pair<const char *, SSAValue *>, 4> errors;
1370 // Iteration over the map isn't determinstic, so sort by source location.
1371 for (auto entry : forwardReferencePlaceholders)
1372 errors.push_back({entry.second.getPointer(), entry.first});
1373 llvm::array_pod_sort(errors.begin(), errors.end());
1374
1375 for (auto entry : errors)
1376 emitError(SMLoc::getFromPointer(entry.first),
1377 "use of undeclared SSA value name");
1378 return ParseFailure;
1379 }
1380
Chris Lattner40746442018-07-21 14:32:09 -07001381 // Run the verifier on this function. If an error is detected, report it.
1382 std::string errorString;
1383 if (func->verify(&errorString))
1384 return emitError(loc, errorString);
1385
Chris Lattner6119d382018-07-20 18:41:34 -07001386 return ParseSuccess;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001387}
1388
Chris Lattner78276e32018-07-07 15:48:26 -07001389/// Parse a SSA operand for an instruction or statement.
1390///
James Molloy61a656c2018-07-22 15:45:24 -07001391/// ssa-use ::= ssa-id
Chris Lattner78276e32018-07-07 15:48:26 -07001392///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001393ParseResult FunctionParser::parseSSAUse(SSAUseInfo &result) {
Chris Lattner6119d382018-07-20 18:41:34 -07001394 result.name = getTokenSpelling();
1395 result.number = 0;
1396 result.loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001397 if (parseToken(Token::percent_identifier, "expected SSA operand"))
1398 return ParseFailure;
Chris Lattner6119d382018-07-20 18:41:34 -07001399
1400 // If we have an affine map ID, it is a result number.
1401 if (getToken().is(Token::hash_identifier)) {
1402 if (auto value = getToken().getHashIdentifierNumber())
1403 result.number = value.getValue();
1404 else
1405 return emitError("invalid SSA value result number");
1406 consumeToken(Token::hash_identifier);
1407 }
1408
Chris Lattner7f9cc272018-07-19 08:35:28 -07001409 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001410}
1411
1412/// Parse a (possibly empty) list of SSA operands.
1413///
1414/// ssa-use-list ::= ssa-use (`,` ssa-use)*
1415/// ssa-use-list-opt ::= ssa-use-list?
1416///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001417ParseResult
Chris Lattner40746442018-07-21 14:32:09 -07001418FunctionParser::parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results) {
1419 if (!getToken().is(Token::percent_identifier))
1420 return ParseSuccess;
1421 return parseCommaSeparatedList([&]() -> ParseResult {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001422 SSAUseInfo result;
1423 if (parseSSAUse(result))
1424 return ParseFailure;
1425 results.push_back(result);
1426 return ParseSuccess;
1427 });
Chris Lattner78276e32018-07-07 15:48:26 -07001428}
1429
1430/// Parse an SSA use with an associated type.
1431///
1432/// ssa-use-and-type ::= ssa-use `:` type
James Molloy61a656c2018-07-22 15:45:24 -07001433template <typename ResultType>
1434ResultType FunctionParser::parseSSADefOrUseAndType(
1435 const std::function<ResultType(SSAUseInfo, Type *)> &action) {
Chris Lattner78276e32018-07-07 15:48:26 -07001436
Chris Lattnerf7702a62018-07-23 17:30:01 -07001437 SSAUseInfo useInfo;
1438 if (parseSSAUse(useInfo) ||
1439 parseToken(Token::colon, "expected ':' and type for SSA operand"))
1440 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001441
Chris Lattner7f9cc272018-07-19 08:35:28 -07001442 auto *type = parseType();
1443 if (!type)
1444 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001445
James Molloy61a656c2018-07-22 15:45:24 -07001446 return action(useInfo, type);
Chris Lattner78276e32018-07-07 15:48:26 -07001447}
1448
Chris Lattner2c402672018-07-23 11:56:17 -07001449/// Parse a (possibly empty) list of SSA operands, followed by a colon, then
1450/// followed by a type list. If hasParens is true, then the operands are
1451/// surrounded by parens.
Chris Lattner78276e32018-07-07 15:48:26 -07001452///
Chris Lattner2c402672018-07-23 11:56:17 -07001453/// ssa-use-and-type-list[parens]
1454/// ::= `(` ssa-use-list `)` ':' type-list-no-parens
1455///
1456/// ssa-use-and-type-list[!parens]
1457/// ::= ssa-use-list ':' type-list-no-parens
Chris Lattner78276e32018-07-07 15:48:26 -07001458///
Chris Lattner40746442018-07-21 14:32:09 -07001459template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001460ParseResult FunctionParser::parseOptionalSSAUseAndTypeList(
Chris Lattner2c402672018-07-23 11:56:17 -07001461 SmallVectorImpl<ValueTy *> &results, bool isParenthesized) {
1462
1463 // If we are in the parenthesized form and no paren exists, then we succeed
1464 // with an empty list.
1465 if (isParenthesized && !consumeIf(Token::l_paren))
Chris Lattner40746442018-07-21 14:32:09 -07001466 return ParseSuccess;
1467
Chris Lattner2c402672018-07-23 11:56:17 -07001468 SmallVector<SSAUseInfo, 4> valueIDs;
1469 if (parseOptionalSSAUseList(valueIDs))
Chris Lattner7f9cc272018-07-19 08:35:28 -07001470 return ParseFailure;
Chris Lattner2c402672018-07-23 11:56:17 -07001471
1472 if (isParenthesized && !consumeIf(Token::r_paren))
1473 return emitError("expected ')' in operand list");
1474
1475 // If there were no operands, then there is no colon or type lists.
1476 if (valueIDs.empty())
1477 return ParseSuccess;
1478
Chris Lattner2c402672018-07-23 11:56:17 -07001479 SmallVector<Type *, 4> types;
Chris Lattnerf7702a62018-07-23 17:30:01 -07001480 if (parseToken(Token::colon, "expected ':' in operand list") ||
1481 parseTypeListNoParens(types))
Chris Lattner2c402672018-07-23 11:56:17 -07001482 return ParseFailure;
1483
1484 if (valueIDs.size() != types.size())
1485 return emitError("expected " + Twine(valueIDs.size()) +
1486 " types to match operand list");
1487
1488 results.reserve(valueIDs.size());
1489 for (unsigned i = 0, e = valueIDs.size(); i != e; ++i) {
1490 if (auto *value = resolveSSAUse(valueIDs[i], types[i]))
1491 results.push_back(cast<ValueTy>(value));
1492 else
1493 return ParseFailure;
1494 }
1495
1496 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001497}
1498
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001499/// Parse the CFG or MLFunc operation.
1500///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001501/// operation ::=
1502/// (ssa-id `=`)? string '(' ssa-use-list? ')' attribute-dict?
1503/// `:` function-type
1504///
1505ParseResult
Chris Lattner7f9cc272018-07-19 08:35:28 -07001506FunctionParser::parseOperation(const CreateOperationFunction &createOpFunc) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001507 auto loc = getToken().getLoc();
1508
1509 StringRef resultID;
1510 if (getToken().is(Token::percent_identifier)) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001511 resultID = getTokenSpelling();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001512 consumeToken(Token::percent_identifier);
Chris Lattnerf7702a62018-07-23 17:30:01 -07001513 if (parseToken(Token::equal, "expected '=' after SSA name"))
1514 return ParseFailure;
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001515 }
1516
1517 if (getToken().isNot(Token::string))
1518 return emitError("expected operation name in quotes");
1519
1520 auto name = getToken().getStringValue();
1521 if (name.empty())
1522 return emitError("empty operation name is invalid");
1523
1524 consumeToken(Token::string);
1525
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001526 // Parse the operand list.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001527 SmallVector<SSAUseInfo, 8> operandInfos;
Chris Lattner40746442018-07-21 14:32:09 -07001528
Chris Lattnerf7702a62018-07-23 17:30:01 -07001529 if (parseToken(Token::l_paren, "expected '(' to start operand list") ||
1530 parseOptionalSSAUseList(operandInfos) ||
1531 parseToken(Token::r_paren, "expected ')' to end operand list")) {
1532 return ParseFailure;
1533 }
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001534
1535 SmallVector<NamedAttribute, 4> attributes;
1536 if (getToken().is(Token::l_brace)) {
1537 if (parseAttributeDict(attributes))
1538 return ParseFailure;
1539 }
1540
Chris Lattnerf7702a62018-07-23 17:30:01 -07001541 if (parseToken(Token::colon, "expected ':' followed by instruction type"))
1542 return ParseFailure;
Chris Lattner3b2ef762018-07-18 15:31:25 -07001543
1544 auto typeLoc = getToken().getLoc();
1545 auto type = parseType();
1546 if (!type)
1547 return ParseFailure;
1548 auto fnType = dyn_cast<FunctionType>(type);
1549 if (!fnType)
1550 return emitError(typeLoc, "expected function type");
1551
Chris Lattner7f9cc272018-07-19 08:35:28 -07001552 // Check that we have the right number of types for the operands.
1553 auto operandTypes = fnType->getInputs();
1554 if (operandTypes.size() != operandInfos.size()) {
1555 auto plural = "s"[operandInfos.size() == 1];
1556 return emitError(typeLoc, "expected " + llvm::utostr(operandInfos.size()) +
Chris Lattnerf8cce872018-07-20 09:28:54 -07001557 " operand type" + plural + " but had " +
Chris Lattner7f9cc272018-07-19 08:35:28 -07001558 llvm::utostr(operandTypes.size()));
1559 }
1560
1561 // Resolve all of the operands.
1562 SmallVector<SSAValue *, 8> operands;
1563 for (unsigned i = 0, e = operandInfos.size(); i != e; ++i) {
1564 operands.push_back(resolveSSAUse(operandInfos[i], operandTypes[i]));
1565 if (!operands.back())
1566 return ParseFailure;
1567 }
1568
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001569 auto nameId = builder.getIdentifier(name);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001570 auto op = createOpFunc(nameId, operands, fnType->getResults(), attributes);
1571 if (!op)
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001572 return ParseFailure;
1573
1574 // We just parsed an operation. If it is a recognized one, verify that it
1575 // is structurally as we expect. If not, produce an error with a reasonable
1576 // source location.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001577 if (auto *opInfo = op->getAbstractOperation(builder.getContext())) {
1578 if (auto error = opInfo->verifyInvariants(op))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001579 return emitError(loc, error);
1580 }
1581
Chris Lattner7f9cc272018-07-19 08:35:28 -07001582 // If the instruction had a name, register it.
1583 if (!resultID.empty()) {
1584 // FIXME: Add result infra to handle Stmt results as well to make this
1585 // generic.
1586 if (auto *inst = dyn_cast<OperationInst>(op)) {
Chris Lattnerf8cce872018-07-20 09:28:54 -07001587 if (inst->getNumResults() == 0)
Chris Lattner7f9cc272018-07-19 08:35:28 -07001588 return emitError(loc, "cannot name an operation with no results");
1589
Chris Lattner6119d382018-07-20 18:41:34 -07001590 for (unsigned i = 0, e = inst->getNumResults(); i != e; ++i)
1591 addDefinition({resultID, i, loc}, inst->getResult(i));
Chris Lattner7f9cc272018-07-19 08:35:28 -07001592 }
1593 }
1594
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001595 return ParseSuccess;
1596}
Chris Lattnere79379a2018-06-22 10:39:19 -07001597
Chris Lattner48af7d12018-07-09 19:05:38 -07001598//===----------------------------------------------------------------------===//
1599// CFG Functions
1600//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001601
Chris Lattner4c95a502018-06-23 16:03:42 -07001602namespace {
Chris Lattner48af7d12018-07-09 19:05:38 -07001603/// This is a specialized parser for CFGFunction's, maintaining the state
1604/// transient to their bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001605class CFGFunctionParser : public FunctionParser {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001606public:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001607 CFGFunctionParser(ParserState &state, CFGFunction *function)
Chris Lattner7f9cc272018-07-19 08:35:28 -07001608 : FunctionParser(state), function(function), builder(function) {}
Chris Lattner2e595eb2018-07-10 10:08:27 -07001609
1610 ParseResult parseFunctionBody();
1611
1612private:
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001613 CFGFunction *function;
James Molloy0ff71542018-07-23 16:56:32 -07001614 llvm::StringMap<std::pair<BasicBlock *, SMLoc>> blocksByName;
Chris Lattner48af7d12018-07-09 19:05:38 -07001615
1616 /// This builder intentionally shadows the builder in the base class, with a
1617 /// more specific builder type.
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001618 CFGFuncBuilder builder;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001619
Chris Lattner4c95a502018-06-23 16:03:42 -07001620 /// Get the basic block with the specified name, creating it if it doesn't
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001621 /// already exist. The location specified is the point of use, which allows
1622 /// us to diagnose references to blocks that are not defined precisely.
1623 BasicBlock *getBlockNamed(StringRef name, SMLoc loc) {
1624 auto &blockAndLoc = blocksByName[name];
1625 if (!blockAndLoc.first) {
Chris Lattner3a467cc2018-07-01 20:28:00 -07001626 blockAndLoc.first = new BasicBlock();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001627 blockAndLoc.second = loc;
Chris Lattner4c95a502018-06-23 16:03:42 -07001628 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001629 return blockAndLoc.first;
Chris Lattner4c95a502018-06-23 16:03:42 -07001630 }
Chris Lattner48af7d12018-07-09 19:05:38 -07001631
James Molloy61a656c2018-07-22 15:45:24 -07001632 ParseResult
1633 parseOptionalBasicBlockArgList(SmallVectorImpl<BBArgument *> &results,
1634 BasicBlock *owner);
1635
Chris Lattner48af7d12018-07-09 19:05:38 -07001636 ParseResult parseBasicBlock();
1637 OperationInst *parseCFGOperation();
1638 TerminatorInst *parseTerminator();
Chris Lattner4c95a502018-06-23 16:03:42 -07001639};
1640} // end anonymous namespace
1641
James Molloy61a656c2018-07-22 15:45:24 -07001642/// Parse a (possibly empty) list of SSA operands with types as basic block
Chris Lattner2c402672018-07-23 11:56:17 -07001643/// arguments.
James Molloy61a656c2018-07-22 15:45:24 -07001644///
1645/// ssa-id-and-type-list ::= ssa-id-and-type (`,` ssa-id-and-type)*
1646///
1647ParseResult CFGFunctionParser::parseOptionalBasicBlockArgList(
1648 SmallVectorImpl<BBArgument *> &results, BasicBlock *owner) {
1649 if (getToken().is(Token::r_brace))
1650 return ParseSuccess;
1651
1652 return parseCommaSeparatedList([&]() -> ParseResult {
1653 auto type = parseSSADefOrUseAndType<Type *>(
1654 [&](SSAUseInfo useInfo, Type *type) -> Type * {
1655 BBArgument *arg = owner->addArgument(type);
1656 if (addDefinition(useInfo, arg) == ParseFailure)
1657 return nullptr;
1658 return type;
1659 });
1660 return type ? ParseSuccess : ParseFailure;
1661 });
1662}
1663
Chris Lattner48af7d12018-07-09 19:05:38 -07001664ParseResult CFGFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07001665 auto braceLoc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001666 if (parseToken(Token::l_brace, "expected '{' in CFG function"))
1667 return ParseFailure;
Chris Lattner48af7d12018-07-09 19:05:38 -07001668
1669 // Make sure we have at least one block.
1670 if (getToken().is(Token::r_brace))
1671 return emitError("CFG functions must have at least one basic block");
Chris Lattner4c95a502018-06-23 16:03:42 -07001672
1673 // Parse the list of blocks.
1674 while (!consumeIf(Token::r_brace))
Chris Lattner48af7d12018-07-09 19:05:38 -07001675 if (parseBasicBlock())
Chris Lattner4c95a502018-06-23 16:03:42 -07001676 return ParseFailure;
1677
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001678 // Verify that all referenced blocks were defined. Iteration over a
1679 // StringMap isn't determinstic, but this is good enough for our purposes.
Chris Lattner48af7d12018-07-09 19:05:38 -07001680 for (auto &elt : blocksByName) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001681 auto *bb = elt.second.first;
Chris Lattner3a467cc2018-07-01 20:28:00 -07001682 if (!bb->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001683 return emitError(elt.second.second,
James Molloy0ff71542018-07-23 16:56:32 -07001684 "reference to an undefined basic block '" + elt.first() +
1685 "'");
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001686 }
1687
Chris Lattner48af7d12018-07-09 19:05:38 -07001688 getModule()->functionList.push_back(function);
Chris Lattner6119d382018-07-20 18:41:34 -07001689
Chris Lattner40746442018-07-21 14:32:09 -07001690 return finalizeFunction(function, braceLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001691}
1692
1693/// Basic block declaration.
1694///
1695/// basic-block ::= bb-label instruction* terminator-stmt
1696/// bb-label ::= bb-id bb-arg-list? `:`
1697/// bb-id ::= bare-id
1698/// bb-arg-list ::= `(` ssa-id-and-type-list? `)`
1699///
Chris Lattner48af7d12018-07-09 19:05:38 -07001700ParseResult CFGFunctionParser::parseBasicBlock() {
1701 SMLoc nameLoc = getToken().getLoc();
1702 auto name = getTokenSpelling();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001703 if (parseToken(Token::bare_identifier, "expected basic block name"))
1704 return ParseFailure;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001705
Chris Lattner48af7d12018-07-09 19:05:38 -07001706 auto *block = getBlockNamed(name, nameLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001707
1708 // If this block has already been parsed, then this is a redefinition with the
1709 // same block name.
Chris Lattner3a467cc2018-07-01 20:28:00 -07001710 if (block->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001711 return emitError(nameLoc, "redefinition of block '" + name.str() + "'");
1712
Chris Lattner78276e32018-07-07 15:48:26 -07001713 // If an argument list is present, parse it.
1714 if (consumeIf(Token::l_paren)) {
James Molloy61a656c2018-07-22 15:45:24 -07001715 SmallVector<BBArgument *, 8> bbArgs;
Chris Lattnerf7702a62018-07-23 17:30:01 -07001716 if (parseOptionalBasicBlockArgList(bbArgs, block) ||
1717 parseToken(Token::r_paren, "expected ')' to end argument list"))
Chris Lattner78276e32018-07-07 15:48:26 -07001718 return ParseFailure;
Chris Lattner78276e32018-07-07 15:48:26 -07001719 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001720
James Molloy61a656c2018-07-22 15:45:24 -07001721 // Add the block to the function.
1722 function->push_back(block);
1723
Chris Lattnerf7702a62018-07-23 17:30:01 -07001724 if (parseToken(Token::colon, "expected ':' after basic block name"))
1725 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07001726
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001727 // Set the insertion point to the block we want to insert new operations into.
Chris Lattner48af7d12018-07-09 19:05:38 -07001728 builder.setInsertionPoint(block);
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001729
Chris Lattner7f9cc272018-07-19 08:35:28 -07001730 auto createOpFunc = [&](Identifier name, ArrayRef<SSAValue *> operands,
1731 ArrayRef<Type *> resultTypes,
1732 ArrayRef<NamedAttribute> attrs) -> Operation * {
1733 SmallVector<CFGValue *, 8> cfgOperands;
1734 cfgOperands.reserve(operands.size());
1735 for (auto *op : operands)
1736 cfgOperands.push_back(cast<CFGValue>(op));
1737 return builder.createOperation(name, cfgOperands, resultTypes, attrs);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001738 };
1739
Chris Lattnered65a732018-06-28 20:45:33 -07001740 // Parse the list of operations that make up the body of the block.
Chris Lattner48af7d12018-07-09 19:05:38 -07001741 while (getToken().isNot(Token::kw_return, Token::kw_br)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001742 if (parseOperation(createOpFunc))
Chris Lattnered65a732018-06-28 20:45:33 -07001743 return ParseFailure;
1744 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001745
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001746 if (!parseTerminator())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001747 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07001748
1749 return ParseSuccess;
1750}
1751
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001752/// Parse the terminator instruction for a basic block.
1753///
1754/// terminator-stmt ::= `br` bb-id branch-use-list?
Chris Lattner1604e472018-07-23 08:42:19 -07001755/// branch-use-list ::= `(` ssa-use-list `)` ':' type-list-no-parens
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001756/// terminator-stmt ::=
1757/// `cond_br` ssa-use `,` bb-id branch-use-list? `,` bb-id branch-use-list?
1758/// terminator-stmt ::= `return` ssa-use-and-type-list?
1759///
Chris Lattner48af7d12018-07-09 19:05:38 -07001760TerminatorInst *CFGFunctionParser::parseTerminator() {
1761 switch (getToken().getKind()) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001762 default:
Chris Lattner3a467cc2018-07-01 20:28:00 -07001763 return (emitError("expected terminator at end of basic block"), nullptr);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001764
Chris Lattner40746442018-07-21 14:32:09 -07001765 case Token::kw_return: {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001766 consumeToken(Token::kw_return);
Chris Lattner40746442018-07-21 14:32:09 -07001767
Chris Lattner2c402672018-07-23 11:56:17 -07001768 // Parse any operands.
1769 SmallVector<CFGValue *, 8> operands;
1770 if (parseOptionalSSAUseAndTypeList(operands, /*isParenthesized*/ false))
1771 return nullptr;
1772 return builder.createReturnInst(operands);
Chris Lattner40746442018-07-21 14:32:09 -07001773 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001774
1775 case Token::kw_br: {
1776 consumeToken(Token::kw_br);
Chris Lattner48af7d12018-07-09 19:05:38 -07001777 auto destBB = getBlockNamed(getTokenSpelling(), getToken().getLoc());
Chris Lattnerf7702a62018-07-23 17:30:01 -07001778 if (parseToken(Token::bare_identifier, "expected basic block name"))
1779 return nullptr;
1780
Chris Lattner1604e472018-07-23 08:42:19 -07001781 auto branch = builder.createBranchInst(destBB);
1782
Chris Lattner2c402672018-07-23 11:56:17 -07001783 SmallVector<CFGValue *, 8> operands;
1784 if (parseOptionalSSAUseAndTypeList(operands, /*isParenthesized*/ true))
Chris Lattner1604e472018-07-23 08:42:19 -07001785 return nullptr;
Chris Lattner2c402672018-07-23 11:56:17 -07001786 branch->addOperands(operands);
Chris Lattner1604e472018-07-23 08:42:19 -07001787 return branch;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001788 }
Chris Lattner78276e32018-07-07 15:48:26 -07001789 // TODO: cond_br.
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001790 }
1791}
1792
Chris Lattner48af7d12018-07-09 19:05:38 -07001793//===----------------------------------------------------------------------===//
1794// ML Functions
1795//===----------------------------------------------------------------------===//
1796
1797namespace {
1798/// Refined parser for MLFunction bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001799class MLFunctionParser : public FunctionParser {
Chris Lattner48af7d12018-07-09 19:05:38 -07001800public:
Chris Lattner48af7d12018-07-09 19:05:38 -07001801 MLFunctionParser(ParserState &state, MLFunction *function)
Chris Lattner7f9cc272018-07-19 08:35:28 -07001802 : FunctionParser(state), function(function), builder(function) {}
Chris Lattner48af7d12018-07-09 19:05:38 -07001803
1804 ParseResult parseFunctionBody();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001805
1806private:
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001807 MLFunction *function;
1808
1809 /// This builder intentionally shadows the builder in the base class, with a
1810 /// more specific builder type.
1811 MLFuncBuilder builder;
1812
1813 ParseResult parseForStmt();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001814 AffineConstantExpr *parseIntConstant();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001815 ParseResult parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001816 ParseResult parseElseClause(IfClause *elseClause);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001817 ParseResult parseStatements(StmtBlock *block);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001818 ParseResult parseStmtBlock(StmtBlock *block);
Chris Lattner48af7d12018-07-09 19:05:38 -07001819};
1820} // end anonymous namespace
1821
Chris Lattner48af7d12018-07-09 19:05:38 -07001822ParseResult MLFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07001823 auto braceLoc = getToken().getLoc();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001824 // Parse statements in this function
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001825
Chris Lattnerf7702a62018-07-23 17:30:01 -07001826 if (parseToken(Token::l_brace, "expected '{' in ML function") ||
1827 parseStatements(function)) {
1828 return ParseFailure;
1829 }
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001830
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001831 // TODO: store return operands in the IR.
1832 SmallVector<SSAUseInfo, 4> dummyUseInfo;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001833
Chris Lattnerf7702a62018-07-23 17:30:01 -07001834 if (parseToken(Token::kw_return,
1835 "ML function must end with return statement") ||
1836 parseOptionalSSAUseList(dummyUseInfo) ||
1837 parseToken(Token::r_brace, "expected '}' to end mlfunc"))
1838 return ParseFailure;
Chris Lattner40746442018-07-21 14:32:09 -07001839
Chris Lattner48af7d12018-07-09 19:05:38 -07001840 getModule()->functionList.push_back(function);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001841
Chris Lattner40746442018-07-21 14:32:09 -07001842 return finalizeFunction(function, braceLoc);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001843}
1844
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001845/// For statement.
1846///
Chris Lattner48af7d12018-07-09 19:05:38 -07001847/// ml-for-stmt ::= `for` ssa-id `=` lower-bound `to` upper-bound
1848/// (`step` integer-literal)? `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001849///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001850ParseResult MLFunctionParser::parseForStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001851 consumeToken(Token::kw_for);
1852
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001853 // Parse induction variable
1854 if (getToken().isNot(Token::percent_identifier))
1855 return emitError("expected SSA identifier for the loop variable");
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001856
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001857 // TODO: create SSA value definition from name
1858 StringRef name = getTokenSpelling().drop_front();
1859 (void)name;
1860
1861 consumeToken(Token::percent_identifier);
1862
Chris Lattnerf7702a62018-07-23 17:30:01 -07001863 if (parseToken(Token::equal, "expected ="))
1864 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001865
1866 // Parse loop bounds
1867 AffineConstantExpr *lowerBound = parseIntConstant();
1868 if (!lowerBound)
1869 return ParseFailure;
1870
Chris Lattnerf7702a62018-07-23 17:30:01 -07001871 if (parseToken(Token::kw_to, "expected 'to' between bounds"))
1872 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001873
1874 AffineConstantExpr *upperBound = parseIntConstant();
1875 if (!upperBound)
1876 return ParseFailure;
1877
1878 // Parse step
1879 AffineConstantExpr *step = nullptr;
1880 if (consumeIf(Token::kw_step)) {
1881 step = parseIntConstant();
1882 if (!step)
1883 return ParseFailure;
1884 }
1885
1886 // Create for statement.
1887 ForStmt *stmt = builder.createFor(lowerBound, upperBound, step);
1888
1889 // If parsing of the for statement body fails,
1890 // MLIR contains for statement with those nested statements that have been
1891 // successfully parsed.
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001892 if (parseStmtBlock(static_cast<StmtBlock *>(stmt)))
1893 return ParseFailure;
1894
1895 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001896}
1897
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001898// This method is temporary workaround to parse simple loop bounds and
1899// step.
1900// TODO: remove this method once it's no longer used.
1901AffineConstantExpr *MLFunctionParser::parseIntConstant() {
1902 if (getToken().isNot(Token::integer))
1903 return (emitError("expected non-negative integer for now"), nullptr);
1904
1905 auto val = getToken().getUInt64IntegerValue();
1906 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
1907 return (emitError("constant too large for affineint"), nullptr);
1908 }
1909 consumeToken(Token::integer);
1910 return builder.getConstantExpr((int64_t)val.getValue());
1911}
1912
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001913/// If statement.
1914///
Chris Lattner48af7d12018-07-09 19:05:38 -07001915/// ml-if-head ::= `if` ml-if-cond `{` ml-stmt* `}`
1916/// | ml-if-head `else` `if` ml-if-cond `{` ml-stmt* `}`
1917/// ml-if-stmt ::= ml-if-head
1918/// | ml-if-head `else` `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001919///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001920ParseResult MLFunctionParser::parseIfStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001921 consumeToken(Token::kw_if);
Chris Lattnerf7702a62018-07-23 17:30:01 -07001922 if (parseToken(Token::l_paren, "expected ("))
1923 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001924
James Molloy0ff71542018-07-23 16:56:32 -07001925 // TODO: parse condition
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001926
Chris Lattnerf7702a62018-07-23 17:30:01 -07001927 if (parseToken(Token::r_paren, "expected )"))
1928 return ParseFailure;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001929
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001930 IfStmt *ifStmt = builder.createIf();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001931 IfClause *thenClause = ifStmt->getThenClause();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001932
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001933 // When parsing of an if statement body fails, the IR contains
1934 // the if statement with the portion of the body that has been
1935 // successfully parsed.
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001936 if (parseStmtBlock(thenClause))
1937 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001938
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001939 if (consumeIf(Token::kw_else)) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07001940 auto *elseClause = ifStmt->createElseClause();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001941 if (parseElseClause(elseClause))
1942 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001943 }
1944
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001945 return ParseSuccess;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001946}
1947
1948ParseResult MLFunctionParser::parseElseClause(IfClause *elseClause) {
1949 if (getToken().is(Token::kw_if)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001950 builder.setInsertionPoint(elseClause);
1951 return parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001952 }
1953
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001954 return parseStmtBlock(elseClause);
1955}
1956
1957///
1958/// Parse a list of statements ending with `return` or `}`
1959///
1960ParseResult MLFunctionParser::parseStatements(StmtBlock *block) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001961 auto createOpFunc = [&](Identifier name, ArrayRef<SSAValue *> operands,
1962 ArrayRef<Type *> resultTypes,
1963 ArrayRef<NamedAttribute> attrs) -> Operation * {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001964 return builder.createOperation(name, attrs);
1965 };
1966
1967 builder.setInsertionPoint(block);
1968
1969 while (getToken().isNot(Token::kw_return, Token::r_brace)) {
1970 switch (getToken().getKind()) {
1971 default:
1972 if (parseOperation(createOpFunc))
1973 return ParseFailure;
1974 break;
1975 case Token::kw_for:
1976 if (parseForStmt())
1977 return ParseFailure;
1978 break;
1979 case Token::kw_if:
1980 if (parseIfStmt())
1981 return ParseFailure;
1982 break;
1983 } // end switch
1984 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001985
1986 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001987}
1988
1989///
1990/// Parse `{` ml-stmt* `}`
1991///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001992ParseResult MLFunctionParser::parseStmtBlock(StmtBlock *block) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07001993 if (parseToken(Token::l_brace, "expected '{' before statement list") ||
1994 parseStatements(block) ||
1995 parseToken(Token::r_brace,
1996 "expected '}' at the end of the statement block"))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001997 return ParseFailure;
1998
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001999 return ParseSuccess;
2000}
2001
Chris Lattner4c95a502018-06-23 16:03:42 -07002002//===----------------------------------------------------------------------===//
2003// Top-level entity parsing.
2004//===----------------------------------------------------------------------===//
2005
Chris Lattner2e595eb2018-07-10 10:08:27 -07002006namespace {
2007/// This parser handles entities that are only valid at the top level of the
2008/// file.
2009class ModuleParser : public Parser {
2010public:
2011 explicit ModuleParser(ParserState &state) : Parser(state) {}
2012
2013 ParseResult parseModule();
2014
2015private:
2016 ParseResult parseAffineMapDef();
2017
2018 // Functions.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002019 ParseResult parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2020 SmallVectorImpl<StringRef> &argNames);
2021 ParseResult parseFunctionSignature(StringRef &name, FunctionType *&type,
2022 SmallVectorImpl<StringRef> *argNames);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002023 ParseResult parseExtFunc();
2024 ParseResult parseCFGFunc();
2025 ParseResult parseMLFunc();
2026};
2027} // end anonymous namespace
2028
2029/// Affine map declaration.
2030///
2031/// affine-map-def ::= affine-map-id `=` affine-map-inline
2032///
2033ParseResult ModuleParser::parseAffineMapDef() {
2034 assert(getToken().is(Token::hash_identifier));
2035
2036 StringRef affineMapId = getTokenSpelling().drop_front();
2037
2038 // Check for redefinitions.
2039 auto *&entry = getState().affineMapDefinitions[affineMapId];
2040 if (entry)
2041 return emitError("redefinition of affine map id '" + affineMapId + "'");
2042
2043 consumeToken(Token::hash_identifier);
2044
2045 // Parse the '='
Chris Lattnerf7702a62018-07-23 17:30:01 -07002046 if (parseToken(Token::equal,
2047 "expected '=' in affine map outlined definition"))
2048 return ParseFailure;
Chris Lattner2e595eb2018-07-10 10:08:27 -07002049
2050 entry = parseAffineMapInline();
2051 if (!entry)
2052 return ParseFailure;
2053
Chris Lattner2e595eb2018-07-10 10:08:27 -07002054 return ParseSuccess;
2055}
2056
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002057/// Parse a (possibly empty) list of MLFunction arguments with types.
2058///
2059/// ml-argument ::= ssa-id `:` type
2060/// ml-argument-list ::= ml-argument (`,` ml-argument)* | /*empty*/
2061///
2062ParseResult
2063ModuleParser::parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2064 SmallVectorImpl<StringRef> &argNames) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002065 consumeToken(Token::l_paren);
2066
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002067 auto parseElt = [&]() -> ParseResult {
2068 // Parse argument name
2069 if (getToken().isNot(Token::percent_identifier))
2070 return emitError("expected SSA identifier");
2071
2072 StringRef name = getTokenSpelling().drop_front();
2073 consumeToken(Token::percent_identifier);
2074 argNames.push_back(name);
2075
Chris Lattnerf7702a62018-07-23 17:30:01 -07002076 if (parseToken(Token::colon, "expected ':'"))
2077 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002078
2079 // Parse argument type
2080 auto elt = parseType();
2081 if (!elt)
2082 return ParseFailure;
2083 argTypes.push_back(elt);
2084
2085 return ParseSuccess;
2086 };
2087
Chris Lattner40746442018-07-21 14:32:09 -07002088 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002089}
2090
Chris Lattner2e595eb2018-07-10 10:08:27 -07002091/// Parse a function signature, starting with a name and including the parameter
2092/// list.
2093///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002094/// argument-list ::= type (`,` type)* | /*empty*/ | ml-argument-list
Chris Lattner2e595eb2018-07-10 10:08:27 -07002095/// function-signature ::= function-id `(` argument-list `)` (`->` type-list)?
2096///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002097ParseResult
2098ModuleParser::parseFunctionSignature(StringRef &name, FunctionType *&type,
2099 SmallVectorImpl<StringRef> *argNames) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002100 if (getToken().isNot(Token::at_identifier))
2101 return emitError("expected a function identifier like '@foo'");
2102
2103 name = getTokenSpelling().drop_front();
2104 consumeToken(Token::at_identifier);
2105
2106 if (getToken().isNot(Token::l_paren))
2107 return emitError("expected '(' in function signature");
2108
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002109 SmallVector<Type *, 4> argTypes;
2110 ParseResult parseResult;
2111
2112 if (argNames)
2113 parseResult = parseMLArgumentList(argTypes, *argNames);
2114 else
2115 parseResult = parseTypeList(argTypes);
2116
2117 if (parseResult)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002118 return ParseFailure;
2119
2120 // Parse the return type if present.
2121 SmallVector<Type *, 4> results;
2122 if (consumeIf(Token::arrow)) {
2123 if (parseTypeList(results))
2124 return ParseFailure;
2125 }
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002126 type = builder.getFunctionType(argTypes, results);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002127 return ParseSuccess;
2128}
2129
2130/// External function declarations.
2131///
2132/// ext-func ::= `extfunc` function-signature
2133///
2134ParseResult ModuleParser::parseExtFunc() {
2135 consumeToken(Token::kw_extfunc);
2136
2137 StringRef name;
2138 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002139 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002140 return ParseFailure;
2141
2142 // Okay, the external function definition was parsed correctly.
2143 getModule()->functionList.push_back(new ExtFunction(name, type));
2144 return ParseSuccess;
2145}
2146
2147/// CFG function declarations.
2148///
2149/// cfg-func ::= `cfgfunc` function-signature `{` basic-block+ `}`
2150///
2151ParseResult ModuleParser::parseCFGFunc() {
2152 consumeToken(Token::kw_cfgfunc);
2153
2154 StringRef name;
2155 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002156 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002157 return ParseFailure;
2158
2159 // Okay, the CFG function signature was parsed correctly, create the function.
2160 auto function = new CFGFunction(name, type);
2161
2162 return CFGFunctionParser(getState(), function).parseFunctionBody();
2163}
2164
2165/// ML function declarations.
2166///
2167/// ml-func ::= `mlfunc` ml-func-signature `{` ml-stmt* ml-return-stmt `}`
2168///
2169ParseResult ModuleParser::parseMLFunc() {
2170 consumeToken(Token::kw_mlfunc);
2171
2172 StringRef name;
2173 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002174 SmallVector<StringRef, 4> argNames;
Chris Lattner2e595eb2018-07-10 10:08:27 -07002175 // FIXME: Parse ML function signature (args + types)
2176 // by passing pointer to SmallVector<identifier> into parseFunctionSignature
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002177
2178 if (parseFunctionSignature(name, type, &argNames))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002179 return ParseFailure;
2180
2181 // Okay, the ML function signature was parsed correctly, create the function.
2182 auto function = new MLFunction(name, type);
2183
2184 return MLFunctionParser(getState(), function).parseFunctionBody();
2185}
2186
Chris Lattnere79379a2018-06-22 10:39:19 -07002187/// This is the top-level module parser.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002188ParseResult ModuleParser::parseModule() {
Chris Lattnere79379a2018-06-22 10:39:19 -07002189 while (1) {
Chris Lattner48af7d12018-07-09 19:05:38 -07002190 switch (getToken().getKind()) {
Chris Lattnere79379a2018-06-22 10:39:19 -07002191 default:
2192 emitError("expected a top level entity");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002193 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002194
Uday Bondhugula015cbb12018-07-03 20:16:08 -07002195 // If we got to the end of the file, then we're done.
Chris Lattnere79379a2018-06-22 10:39:19 -07002196 case Token::eof:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002197 return ParseSuccess;
Chris Lattnere79379a2018-06-22 10:39:19 -07002198
2199 // If we got an error token, then the lexer already emitted an error, just
2200 // stop. Someday we could introduce error recovery if there was demand for
2201 // it.
2202 case Token::error:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002203 return ParseFailure;
2204
2205 case Token::hash_identifier:
2206 if (parseAffineMapDef())
2207 return ParseFailure;
2208 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002209
2210 case Token::kw_extfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002211 if (parseExtFunc())
2212 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002213 break;
2214
Chris Lattner4c95a502018-06-23 16:03:42 -07002215 case Token::kw_cfgfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002216 if (parseCFGFunc())
2217 return ParseFailure;
MLIR Teamf85a6262018-06-27 11:03:08 -07002218 break;
Chris Lattner4c95a502018-06-23 16:03:42 -07002219
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002220 case Token::kw_mlfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002221 if (parseMLFunc())
2222 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002223 break;
2224
Uday Bondhugula015cbb12018-07-03 20:16:08 -07002225 // TODO: affine entity declarations, etc.
Chris Lattnere79379a2018-06-22 10:39:19 -07002226 }
2227 }
2228}
2229
2230//===----------------------------------------------------------------------===//
2231
Jacques Pienaar7b829702018-07-03 13:24:09 -07002232void mlir::defaultErrorReporter(const llvm::SMDiagnostic &error) {
2233 const auto &sourceMgr = *error.getSourceMgr();
2234 sourceMgr.PrintMessage(error.getLoc(), error.getKind(), error.getMessage());
2235}
2236
Chris Lattnere79379a2018-06-22 10:39:19 -07002237/// This parses the file specified by the indicated SourceMgr and returns an
2238/// MLIR module if it was valid. If not, it emits diagnostics and returns null.
Jacques Pienaar9c411be2018-06-24 19:17:35 -07002239Module *mlir::parseSourceFile(llvm::SourceMgr &sourceMgr, MLIRContext *context,
Jacques Pienaar7b829702018-07-03 13:24:09 -07002240 SMDiagnosticHandlerTy errorReporter) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002241 // This is the result module we are parsing into.
2242 std::unique_ptr<Module> module(new Module(context));
2243
2244 ParserState state(sourceMgr, module.get(),
Jacques Pienaar0bffd862018-07-11 13:26:23 -07002245 errorReporter ? errorReporter : defaultErrorReporter);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002246 if (ModuleParser(state).parseModule())
2247 return nullptr;
Chris Lattner21e67f62018-07-06 10:46:19 -07002248
2249 // Make sure the parse module has no other structural problems detected by the
2250 // verifier.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002251 module->verify();
2252 return module.release();
Chris Lattnere79379a2018-06-22 10:39:19 -07002253}