blob: da936dbc79d1ce95e84c6b4a53585e5fed3fcf26 [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 Lattnere79379a2018-06-22 10:39:19 -070033#include "llvm/Support/SourceMgr.h"
34using namespace mlir;
35using llvm::SourceMgr;
Chris Lattner4c95a502018-06-23 16:03:42 -070036using llvm::SMLoc;
Chris Lattnere79379a2018-06-22 10:39:19 -070037
Chris Lattnerf7e22732018-06-22 22:03:48 -070038/// Simple enum to make code read better in cases that would otherwise return a
39/// bool value. Failure is "true" in a boolean context.
Chris Lattnere79379a2018-06-22 10:39:19 -070040enum ParseResult {
41 ParseSuccess,
42 ParseFailure
43};
44
Chris Lattner48af7d12018-07-09 19:05:38 -070045namespace {
46class Parser;
47
48/// This class refers to all of the state maintained globally by the parser,
49/// such as the current lexer position etc. The Parser base class provides
50/// methods to access this.
51class ParserState {
Chris Lattnered65a732018-06-28 20:45:33 -070052public:
Chris Lattner2e595eb2018-07-10 10:08:27 -070053 ParserState(llvm::SourceMgr &sourceMgr, Module *module,
Chris Lattner48af7d12018-07-09 19:05:38 -070054 SMDiagnosticHandlerTy errorReporter)
Chris Lattner2e595eb2018-07-10 10:08:27 -070055 : context(module->getContext()), module(module),
56 lex(sourceMgr, errorReporter), curToken(lex.lexToken()),
Jacques Pienaard4c784e2018-07-11 00:07:36 -070057 errorReporter(errorReporter) {}
Chris Lattner2e595eb2018-07-10 10:08:27 -070058
59 // A map from affine map identifier to AffineMap.
60 llvm::StringMap<AffineMap *> affineMapDefinitions;
Chris Lattnere79379a2018-06-22 10:39:19 -070061
Chris Lattnere79379a2018-06-22 10:39:19 -070062private:
Chris Lattner48af7d12018-07-09 19:05:38 -070063 ParserState(const ParserState &) = delete;
64 void operator=(const ParserState &) = delete;
65
66 friend class Parser;
67
68 // The context we're parsing into.
Chris Lattner2e595eb2018-07-10 10:08:27 -070069 MLIRContext *const context;
70
71 // This is the module we are parsing into.
72 Module *const module;
Chris Lattnerf7e22732018-06-22 22:03:48 -070073
74 // The lexer for the source file we're parsing.
Chris Lattnere79379a2018-06-22 10:39:19 -070075 Lexer lex;
76
77 // This is the next token that hasn't been consumed yet.
78 Token curToken;
79
Jacques Pienaar9c411be2018-06-24 19:17:35 -070080 // The diagnostic error reporter.
Chris Lattner2e595eb2018-07-10 10:08:27 -070081 SMDiagnosticHandlerTy const errorReporter;
Chris Lattner48af7d12018-07-09 19:05:38 -070082};
83} // end anonymous namespace
MLIR Teamf85a6262018-06-27 11:03:08 -070084
Chris Lattner48af7d12018-07-09 19:05:38 -070085namespace {
86
Chris Lattner7f9cc272018-07-19 08:35:28 -070087typedef std::function<Operation *(Identifier, ArrayRef<SSAValue *>,
88 ArrayRef<Type *>, ArrayRef<NamedAttribute>)>
Tatiana Shpeisman565b9642018-07-16 11:47:09 -070089 CreateOperationFunction;
90
Chris Lattner48af7d12018-07-09 19:05:38 -070091/// This class implement support for parsing global entities like types and
92/// shared entities like SSA names. It is intended to be subclassed by
93/// specialized subparsers that include state, e.g. when a local symbol table.
94class Parser {
95public:
Chris Lattner2e595eb2018-07-10 10:08:27 -070096 Builder builder;
Chris Lattner48af7d12018-07-09 19:05:38 -070097
Chris Lattner2e595eb2018-07-10 10:08:27 -070098 Parser(ParserState &state) : builder(state.context), state(state) {}
99
100 // Helper methods to get stuff from the parser-global state.
101 ParserState &getState() const { return state; }
Chris Lattner48af7d12018-07-09 19:05:38 -0700102 MLIRContext *getContext() const { return state.context; }
Chris Lattner2e595eb2018-07-10 10:08:27 -0700103 Module *getModule() { return state.module; }
Chris Lattner48af7d12018-07-09 19:05:38 -0700104
105 /// Return the current token the parser is inspecting.
106 const Token &getToken() const { return state.curToken; }
107 StringRef getTokenSpelling() const { return state.curToken.getSpelling(); }
Chris Lattnere79379a2018-06-22 10:39:19 -0700108
109 /// Emit an error and return failure.
Chris Lattner4c95a502018-06-23 16:03:42 -0700110 ParseResult emitError(const Twine &message) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700111 return emitError(state.curToken.getLoc(), message);
Chris Lattner4c95a502018-06-23 16:03:42 -0700112 }
113 ParseResult emitError(SMLoc loc, const Twine &message);
Chris Lattnere79379a2018-06-22 10:39:19 -0700114
115 /// Advance the current lexer onto the next token.
116 void consumeToken() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700117 assert(state.curToken.isNot(Token::eof, Token::error) &&
Chris Lattnere79379a2018-06-22 10:39:19 -0700118 "shouldn't advance past EOF or errors");
Chris Lattner48af7d12018-07-09 19:05:38 -0700119 state.curToken = state.lex.lexToken();
Chris Lattnere79379a2018-06-22 10:39:19 -0700120 }
121
122 /// Advance the current lexer onto the next token, asserting what the expected
123 /// current token is. This is preferred to the above method because it leads
124 /// to more self-documenting code with better checking.
Chris Lattner8da0c282018-06-29 11:15:56 -0700125 void consumeToken(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700126 assert(state.curToken.is(kind) && "consumed an unexpected token");
Chris Lattnere79379a2018-06-22 10:39:19 -0700127 consumeToken();
128 }
129
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700130 /// If the current token has the specified kind, consume it and return true.
131 /// If not, return false.
Chris Lattner8da0c282018-06-29 11:15:56 -0700132 bool consumeIf(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700133 if (state.curToken.isNot(kind))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700134 return false;
135 consumeToken(kind);
136 return true;
137 }
138
MLIR Team718c82f2018-07-16 09:45:22 -0700139 ParseResult parseCommaSeparatedList(
140 Token::Kind rightToken,
141 const std::function<ParseResult()> &parseElement,
142 bool allowEmptyList = true);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700143
Chris Lattnerf7e22732018-06-22 22:03:48 -0700144 // We have two forms of parsing methods - those that return a non-null
145 // pointer on success, and those that return a ParseResult to indicate whether
146 // they returned a failure. The second class fills in by-reference arguments
147 // as the results of their action.
148
Chris Lattnere79379a2018-06-22 10:39:19 -0700149 // Type parsing.
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700150 Type *parsePrimitiveType();
Chris Lattnerf7e22732018-06-22 22:03:48 -0700151 Type *parseElementType();
152 VectorType *parseVectorType();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700153 ParseResult parseDimensionListRanked(SmallVectorImpl<int> &dimensions);
Chris Lattnerf7e22732018-06-22 22:03:48 -0700154 Type *parseTensorType();
155 Type *parseMemRefType();
156 Type *parseFunctionType();
157 Type *parseType();
158 ParseResult parseTypeList(SmallVectorImpl<Type*> &elements);
Chris Lattnere79379a2018-06-22 10:39:19 -0700159
Chris Lattner7121b802018-07-04 20:45:39 -0700160 // Attribute parsing.
161 Attribute *parseAttribute();
162 ParseResult parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes);
163
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700164 // Polyhedral structures.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700165 AffineMap *parseAffineMapInline();
MLIR Team718c82f2018-07-16 09:45:22 -0700166 AffineMap *parseAffineMapReference();
MLIR Teamf85a6262018-06-27 11:03:08 -0700167
Chris Lattner48af7d12018-07-09 19:05:38 -0700168private:
169 // The Parser is subclassed and reinstantiated. Do not add additional
170 // non-trivial state here, add it to the ParserState class.
171 ParserState &state;
Chris Lattnere79379a2018-06-22 10:39:19 -0700172};
173} // end anonymous namespace
174
175//===----------------------------------------------------------------------===//
176// Helper methods.
177//===----------------------------------------------------------------------===//
178
Chris Lattner4c95a502018-06-23 16:03:42 -0700179ParseResult Parser::emitError(SMLoc loc, const Twine &message) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700180 // If we hit a parse error in response to a lexer error, then the lexer
Jacques Pienaar9c411be2018-06-24 19:17:35 -0700181 // already reported the error.
Chris Lattner48af7d12018-07-09 19:05:38 -0700182 if (getToken().is(Token::error))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700183 return ParseFailure;
184
Chris Lattner48af7d12018-07-09 19:05:38 -0700185 auto &sourceMgr = state.lex.getSourceMgr();
186 state.errorReporter(sourceMgr.GetMessage(loc, SourceMgr::DK_Error, message));
Chris Lattnere79379a2018-06-22 10:39:19 -0700187 return ParseFailure;
188}
189
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700190/// Parse a comma-separated list of elements, terminated with an arbitrary
191/// token. This allows empty lists if allowEmptyList is true.
192///
193/// abstract-list ::= rightToken // if allowEmptyList == true
194/// abstract-list ::= element (',' element)* rightToken
195///
196ParseResult Parser::
Chris Lattner8da0c282018-06-29 11:15:56 -0700197parseCommaSeparatedList(Token::Kind rightToken,
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700198 const std::function<ParseResult()> &parseElement,
199 bool allowEmptyList) {
200 // Handle the empty case.
Chris Lattner48af7d12018-07-09 19:05:38 -0700201 if (getToken().is(rightToken)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700202 if (!allowEmptyList)
203 return emitError("expected list element");
204 consumeToken(rightToken);
205 return ParseSuccess;
206 }
207
208 // Non-empty case starts with an element.
209 if (parseElement())
210 return ParseFailure;
211
212 // Otherwise we have a list of comma separated elements.
213 while (consumeIf(Token::comma)) {
214 if (parseElement())
215 return ParseFailure;
216 }
217
218 // Consume the end character.
219 if (!consumeIf(rightToken))
Chris Lattner8da0c282018-06-29 11:15:56 -0700220 return emitError("expected ',' or '" + Token::getTokenSpelling(rightToken) +
221 "'");
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700222
223 return ParseSuccess;
224}
Chris Lattnere79379a2018-06-22 10:39:19 -0700225
226//===----------------------------------------------------------------------===//
227// Type Parsing
228//===----------------------------------------------------------------------===//
229
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700230/// Parse the low-level fixed dtypes in the system.
231///
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700232/// primitive-type ::= `f16` | `bf16` | `f32` | `f64`
233/// primitive-type ::= integer-type
234/// primitive-type ::= `affineint`
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700235///
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700236Type *Parser::parsePrimitiveType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700237 switch (getToken().getKind()) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700238 default:
239 return (emitError("expected type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700240 case Token::kw_bf16:
241 consumeToken(Token::kw_bf16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700242 return builder.getBF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700243 case Token::kw_f16:
244 consumeToken(Token::kw_f16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700245 return builder.getF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700246 case Token::kw_f32:
247 consumeToken(Token::kw_f32);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700248 return builder.getF32Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700249 case Token::kw_f64:
250 consumeToken(Token::kw_f64);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700251 return builder.getF64Type();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700252 case Token::kw_affineint:
253 consumeToken(Token::kw_affineint);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700254 return builder.getAffineIntType();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700255 case Token::inttype: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700256 auto width = getToken().getIntTypeBitwidth();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700257 if (!width.hasValue())
258 return (emitError("invalid integer width"), nullptr);
259 consumeToken(Token::inttype);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700260 return builder.getIntegerType(width.getValue());
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700261 }
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700262 }
263}
264
265/// Parse the element type of a tensor or memref type.
266///
267/// element-type ::= primitive-type | vector-type
268///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700269Type *Parser::parseElementType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700270 if (getToken().is(Token::kw_vector))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700271 return parseVectorType();
272
273 return parsePrimitiveType();
274}
275
276/// Parse a vector type.
277///
278/// vector-type ::= `vector` `<` const-dimension-list primitive-type `>`
279/// const-dimension-list ::= (integer-literal `x`)+
280///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700281VectorType *Parser::parseVectorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700282 consumeToken(Token::kw_vector);
283
284 if (!consumeIf(Token::less))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700285 return (emitError("expected '<' in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700286
Chris Lattner48af7d12018-07-09 19:05:38 -0700287 if (getToken().isNot(Token::integer))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700288 return (emitError("expected dimension size in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700289
290 SmallVector<unsigned, 4> dimensions;
Chris Lattner48af7d12018-07-09 19:05:38 -0700291 while (getToken().is(Token::integer)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700292 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700293 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700294 if (!dimension.hasValue())
Chris Lattnerf7e22732018-06-22 22:03:48 -0700295 return (emitError("invalid dimension in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700296 dimensions.push_back(dimension.getValue());
297
298 consumeToken(Token::integer);
299
300 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700301 if (getToken().isNot(Token::bare_identifier) ||
302 getTokenSpelling()[0] != 'x')
Chris Lattnerf7e22732018-06-22 22:03:48 -0700303 return (emitError("expected 'x' in vector dimension list"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700304
305 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700306 if (getTokenSpelling().size() != 1)
307 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700308
309 // Consume the 'x'.
310 consumeToken(Token::bare_identifier);
311 }
312
313 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700314 auto *elementType = parsePrimitiveType();
315 if (!elementType)
316 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700317
318 if (!consumeIf(Token::greater))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700319 return (emitError("expected '>' in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700320
Chris Lattnerf7e22732018-06-22 22:03:48 -0700321 return VectorType::get(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700322}
323
324/// Parse a dimension list of a tensor or memref type. This populates the
325/// dimension list, returning -1 for the '?' dimensions.
326///
327/// dimension-list-ranked ::= (dimension `x`)*
328/// dimension ::= `?` | integer-literal
329///
330ParseResult Parser::parseDimensionListRanked(SmallVectorImpl<int> &dimensions) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700331 while (getToken().isAny(Token::integer, Token::question)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700332 if (consumeIf(Token::question)) {
333 dimensions.push_back(-1);
334 } else {
335 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700336 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700337 if (!dimension.hasValue() || (int)dimension.getValue() < 0)
338 return emitError("invalid dimension");
339 dimensions.push_back((int)dimension.getValue());
340 consumeToken(Token::integer);
341 }
342
343 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700344 if (getToken().isNot(Token::bare_identifier) ||
345 getTokenSpelling()[0] != 'x')
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700346 return emitError("expected 'x' in dimension list");
347
348 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700349 if (getTokenSpelling().size() != 1)
350 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700351
352 // Consume the 'x'.
353 consumeToken(Token::bare_identifier);
354 }
355
356 return ParseSuccess;
357}
358
359/// Parse a tensor type.
360///
361/// tensor-type ::= `tensor` `<` dimension-list element-type `>`
362/// dimension-list ::= dimension-list-ranked | `??`
363///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700364Type *Parser::parseTensorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700365 consumeToken(Token::kw_tensor);
366
367 if (!consumeIf(Token::less))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700368 return (emitError("expected '<' in tensor type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700369
370 bool isUnranked;
371 SmallVector<int, 4> dimensions;
372
373 if (consumeIf(Token::questionquestion)) {
374 isUnranked = true;
375 } else {
376 isUnranked = false;
377 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700378 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700379 }
380
381 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700382 auto elementType = parseElementType();
383 if (!elementType)
384 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700385
386 if (!consumeIf(Token::greater))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700387 return (emitError("expected '>' in tensor type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700388
MLIR Team355ec862018-06-23 18:09:09 -0700389 if (isUnranked)
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700390 return builder.getTensorType(elementType);
391 return builder.getTensorType(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700392}
393
394/// Parse a memref type.
395///
396/// memref-type ::= `memref` `<` dimension-list-ranked element-type
397/// (`,` semi-affine-map-composition)? (`,` memory-space)? `>`
398///
399/// semi-affine-map-composition ::= (semi-affine-map `,` )* semi-affine-map
400/// memory-space ::= integer-literal /* | TODO: address-space-id */
401///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700402Type *Parser::parseMemRefType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700403 consumeToken(Token::kw_memref);
404
405 if (!consumeIf(Token::less))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700406 return (emitError("expected '<' in memref type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700407
408 SmallVector<int, 4> dimensions;
409 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700410 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700411
412 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700413 auto elementType = parseElementType();
414 if (!elementType)
415 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700416
MLIR Team718c82f2018-07-16 09:45:22 -0700417 if (!consumeIf(Token::comma))
418 return (emitError("expected ',' in memref type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700419
MLIR Team718c82f2018-07-16 09:45:22 -0700420 // Parse semi-affine-map-composition.
421 SmallVector<AffineMap*, 2> affineMapComposition;
422 unsigned memorySpace;
423 bool parsedMemorySpace = false;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700424
MLIR Team718c82f2018-07-16 09:45:22 -0700425 auto parseElt = [&]() -> ParseResult {
426 if (getToken().is(Token::integer)) {
427 // Parse memory space.
428 if (parsedMemorySpace)
429 return emitError("multiple memory spaces specified in memref type");
430 auto v = getToken().getUnsignedIntegerValue();
431 if (!v.hasValue())
432 return emitError("invalid memory space in memref type");
433 memorySpace = v.getValue();
434 consumeToken(Token::integer);
435 parsedMemorySpace = true;
436 } else {
437 // Parse affine map.
438 if (parsedMemorySpace)
439 return emitError("affine map after memory space in memref type");
440 auto* affineMap = parseAffineMapReference();
441 if (affineMap == nullptr)
442 return ParseFailure;
443 affineMapComposition.push_back(affineMap);
444 }
445 return ParseSuccess;
446 };
447
448 // Parse comma separated list of affine maps, followed by memory space.
449 if (parseCommaSeparatedList(Token::greater, parseElt,
450 /*allowEmptyList=*/false)) {
451 return nullptr;
452 }
453 // Check that MemRef type specifies at least one affine map in composition.
454 if (affineMapComposition.empty())
455 return (emitError("expected semi-affine-map in memref type"), nullptr);
456 if (!parsedMemorySpace)
457 return (emitError("expected memory space in memref type"), nullptr);
458
459 return MemRefType::get(dimensions, elementType, affineMapComposition,
460 memorySpace);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700461}
462
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700463/// Parse a function type.
464///
465/// function-type ::= type-list-parens `->` type-list
466///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700467Type *Parser::parseFunctionType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700468 assert(getToken().is(Token::l_paren));
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700469
Chris Lattnerf7e22732018-06-22 22:03:48 -0700470 SmallVector<Type*, 4> arguments;
471 if (parseTypeList(arguments))
472 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700473
474 if (!consumeIf(Token::arrow))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700475 return (emitError("expected '->' in function type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700476
Chris Lattnerf7e22732018-06-22 22:03:48 -0700477 SmallVector<Type*, 4> results;
478 if (parseTypeList(results))
479 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700480
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700481 return builder.getFunctionType(arguments, results);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700482}
483
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700484/// Parse an arbitrary type.
485///
486/// type ::= primitive-type
487/// | vector-type
488/// | tensor-type
489/// | memref-type
490/// | function-type
491/// element-type ::= primitive-type | vector-type
492///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700493Type *Parser::parseType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700494 switch (getToken().getKind()) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700495 case Token::kw_memref: return parseMemRefType();
496 case Token::kw_tensor: return parseTensorType();
497 case Token::kw_vector: return parseVectorType();
498 case Token::l_paren: return parseFunctionType();
499 default:
500 return parsePrimitiveType();
501 }
502}
503
504/// Parse a "type list", which is a singular type, or a parenthesized list of
505/// types.
506///
507/// type-list ::= type-list-parens | type
508/// type-list-parens ::= `(` `)`
509/// | `(` type (`,` type)* `)`
510///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700511ParseResult Parser::parseTypeList(SmallVectorImpl<Type*> &elements) {
512 auto parseElt = [&]() -> ParseResult {
513 auto elt = parseType();
514 elements.push_back(elt);
515 return elt ? ParseSuccess : ParseFailure;
516 };
517
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700518 // If there is no parens, then it must be a singular type.
519 if (!consumeIf(Token::l_paren))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700520 return parseElt();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700521
Chris Lattnerf7e22732018-06-22 22:03:48 -0700522 if (parseCommaSeparatedList(Token::r_paren, parseElt))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700523 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700524
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700525 return ParseSuccess;
526}
527
Chris Lattner4c95a502018-06-23 16:03:42 -0700528//===----------------------------------------------------------------------===//
Chris Lattner7121b802018-07-04 20:45:39 -0700529// Attribute parsing.
530//===----------------------------------------------------------------------===//
531
532
533/// Attribute parsing.
534///
535/// attribute-value ::= bool-literal
536/// | integer-literal
537/// | float-literal
538/// | string-literal
539/// | `[` (attribute-value (`,` attribute-value)*)? `]`
540///
541Attribute *Parser::parseAttribute() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700542 switch (getToken().getKind()) {
Chris Lattner7121b802018-07-04 20:45:39 -0700543 case Token::kw_true:
544 consumeToken(Token::kw_true);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700545 return builder.getBoolAttr(true);
Chris Lattner7121b802018-07-04 20:45:39 -0700546 case Token::kw_false:
547 consumeToken(Token::kw_false);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700548 return builder.getBoolAttr(false);
Chris Lattner7121b802018-07-04 20:45:39 -0700549
550 case Token::integer: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700551 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700552 if (!val.hasValue() || (int64_t)val.getValue() < 0)
553 return (emitError("integer too large for attribute"), nullptr);
554 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700555 return builder.getIntegerAttr((int64_t)val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700556 }
557
558 case Token::minus: {
559 consumeToken(Token::minus);
Chris Lattner48af7d12018-07-09 19:05:38 -0700560 if (getToken().is(Token::integer)) {
561 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700562 if (!val.hasValue() || (int64_t)-val.getValue() >= 0)
563 return (emitError("integer too large for attribute"), nullptr);
564 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700565 return builder.getIntegerAttr((int64_t)-val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700566 }
567
568 return (emitError("expected constant integer or floating point value"),
569 nullptr);
570 }
571
572 case Token::string: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700573 auto val = getToken().getStringValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700574 consumeToken(Token::string);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700575 return builder.getStringAttr(val);
Chris Lattner7121b802018-07-04 20:45:39 -0700576 }
577
578 case Token::l_bracket: {
579 consumeToken(Token::l_bracket);
580 SmallVector<Attribute*, 4> elements;
581
582 auto parseElt = [&]() -> ParseResult {
583 elements.push_back(parseAttribute());
584 return elements.back() ? ParseSuccess : ParseFailure;
585 };
586
587 if (parseCommaSeparatedList(Token::r_bracket, parseElt))
588 return nullptr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700589 return builder.getArrayAttr(elements);
Chris Lattner7121b802018-07-04 20:45:39 -0700590 }
591 default:
MLIR Teamb61885d2018-07-18 16:29:21 -0700592 // Try to parse affine map reference.
593 auto* affineMap = parseAffineMapReference();
594 if (affineMap != nullptr)
595 return builder.getAffineMapAttr(affineMap);
596
Chris Lattner7121b802018-07-04 20:45:39 -0700597 // TODO: Handle floating point.
598 return (emitError("expected constant attribute value"), nullptr);
599 }
600}
601
Chris Lattner7121b802018-07-04 20:45:39 -0700602/// Attribute dictionary.
603///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700604/// attribute-dict ::= `{` `}`
605/// | `{` attribute-entry (`,` attribute-entry)* `}`
606/// attribute-entry ::= bare-id `:` attribute-value
Chris Lattner7121b802018-07-04 20:45:39 -0700607///
608ParseResult Parser::parseAttributeDict(
609 SmallVectorImpl<NamedAttribute> &attributes) {
610 consumeToken(Token::l_brace);
611
612 auto parseElt = [&]() -> ParseResult {
613 // We allow keywords as attribute names.
Chris Lattner48af7d12018-07-09 19:05:38 -0700614 if (getToken().isNot(Token::bare_identifier, Token::inttype) &&
615 !getToken().isKeyword())
Chris Lattner7121b802018-07-04 20:45:39 -0700616 return emitError("expected attribute name");
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700617 auto nameId = builder.getIdentifier(getTokenSpelling());
Chris Lattner7121b802018-07-04 20:45:39 -0700618 consumeToken();
619
620 if (!consumeIf(Token::colon))
621 return emitError("expected ':' in attribute list");
622
623 auto attr = parseAttribute();
624 if (!attr) return ParseFailure;
625
626 attributes.push_back({nameId, attr});
627 return ParseSuccess;
628 };
629
630 if (parseCommaSeparatedList(Token::r_brace, parseElt))
631 return ParseFailure;
632
633 return ParseSuccess;
634}
635
636//===----------------------------------------------------------------------===//
MLIR Teamf85a6262018-06-27 11:03:08 -0700637// Polyhedral structures.
638//===----------------------------------------------------------------------===//
639
Chris Lattner2e595eb2018-07-10 10:08:27 -0700640/// Lower precedence ops (all at the same precedence level). LNoOp is false in
641/// the boolean sense.
642enum AffineLowPrecOp {
643 /// Null value.
644 LNoOp,
645 Add,
646 Sub
647};
MLIR Teamf85a6262018-06-27 11:03:08 -0700648
Chris Lattner2e595eb2018-07-10 10:08:27 -0700649/// Higher precedence ops - all at the same precedence level. HNoOp is false in
650/// the boolean sense.
651enum AffineHighPrecOp {
652 /// Null value.
653 HNoOp,
654 Mul,
655 FloorDiv,
656 CeilDiv,
657 Mod
658};
Chris Lattner7121b802018-07-04 20:45:39 -0700659
Chris Lattner2e595eb2018-07-10 10:08:27 -0700660namespace {
661/// This is a specialized parser for AffineMap's, maintaining the state
662/// transient to their bodies.
663class AffineMapParser : public Parser {
664public:
665 explicit AffineMapParser(ParserState &state) : Parser(state) {}
Chris Lattner7121b802018-07-04 20:45:39 -0700666
Chris Lattner2e595eb2018-07-10 10:08:27 -0700667 AffineMap *parseAffineMapInline();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700668
Chris Lattner2e595eb2018-07-10 10:08:27 -0700669private:
670 unsigned getNumDims() const { return dims.size(); }
671 unsigned getNumSymbols() const { return symbols.size(); }
MLIR Teamf85a6262018-06-27 11:03:08 -0700672
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700673 /// Returns true if the only identifiers the parser accepts in affine
674 /// expressions are symbolic identifiers.
675 bool isPureSymbolic() const { return pureSymbolic; }
676 void setSymbolicParsing(bool val) { pureSymbolic = val; }
677
Chris Lattner2e595eb2018-07-10 10:08:27 -0700678 // Binary affine op parsing.
679 AffineLowPrecOp consumeIfLowPrecOp();
680 AffineHighPrecOp consumeIfHighPrecOp();
MLIR Teamf85a6262018-06-27 11:03:08 -0700681
Chris Lattner2e595eb2018-07-10 10:08:27 -0700682 // Identifier lists for polyhedral structures.
683 ParseResult parseDimIdList();
684 ParseResult parseSymbolIdList();
685 ParseResult parseDimOrSymbolId(bool isDim);
686
687 AffineExpr *parseAffineExpr();
688 AffineExpr *parseParentheticalExpr();
689 AffineExpr *parseNegateExpression(AffineExpr *lhs);
690 AffineExpr *parseIntegerExpr();
691 AffineExpr *parseBareIdExpr();
692
693 AffineExpr *getBinaryAffineOpExpr(AffineHighPrecOp op, AffineExpr *lhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700694 AffineExpr *rhs, SMLoc opLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700695 AffineExpr *getBinaryAffineOpExpr(AffineLowPrecOp op, AffineExpr *lhs,
696 AffineExpr *rhs);
697 AffineExpr *parseAffineOperandExpr(AffineExpr *lhs);
698 AffineExpr *parseAffineLowPrecOpExpr(AffineExpr *llhs,
699 AffineLowPrecOp llhsOp);
700 AffineExpr *parseAffineHighPrecOpExpr(AffineExpr *llhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700701 AffineHighPrecOp llhsOp,
702 SMLoc llhsOpLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700703
704private:
705 // TODO(bondhugula): could just use an vector/ArrayRef and scan the numbers.
706 llvm::StringMap<unsigned> dims;
707 llvm::StringMap<unsigned> symbols;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700708 /// True if the parser should allow only symbolic identifiers in affine
709 /// expressions.
710 bool pureSymbolic = false;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700711};
712} // end anonymous namespace
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700713
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700714/// Create an affine binary high precedence op expression (mul's, div's, mod).
715/// opLoc is the location of the op token to be used to report errors
716/// for non-conforming expressions.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700717AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineHighPrecOp op,
718 AffineExpr *lhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700719 AffineExpr *rhs, SMLoc opLoc) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700720 // TODO: make the error location info accurate.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700721 switch (op) {
722 case Mul:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700723 if (!lhs->isSymbolicOrConstant() && !rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700724 emitError(opLoc, "non-affine expression: at least one of the multiply "
725 "operands has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700726 return nullptr;
727 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700728 return builder.getMulExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700729 case FloorDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700730 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700731 emitError(opLoc, "non-affine expression: right operand of floordiv "
732 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700733 return nullptr;
734 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700735 return builder.getFloorDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700736 case CeilDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700737 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700738 emitError(opLoc, "non-affine expression: right operand of ceildiv "
739 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700740 return nullptr;
741 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700742 return builder.getCeilDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700743 case Mod:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700744 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700745 emitError(opLoc, "non-affine expression: right operand of mod "
746 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700747 return nullptr;
748 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700749 return builder.getModExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700750 case HNoOp:
751 llvm_unreachable("can't create affine expression for null high prec op");
752 return nullptr;
753 }
754}
755
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700756/// Create an affine binary low precedence op expression (add, sub).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700757AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineLowPrecOp op,
758 AffineExpr *lhs,
759 AffineExpr *rhs) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700760 switch (op) {
761 case AffineLowPrecOp::Add:
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700762 return builder.getAddExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700763 case AffineLowPrecOp::Sub:
Uday Bondhugulac1faf662018-07-19 14:08:50 -0700764 return builder.getAddExpr(
765 lhs, builder.getMulExpr(rhs, builder.getConstantExpr(-1)));
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700766 case AffineLowPrecOp::LNoOp:
767 llvm_unreachable("can't create affine expression for null low prec op");
768 return nullptr;
769 }
770}
771
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700772/// Consume this token if it is a lower precedence affine op (there are only two
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700773/// precedence levels).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700774AffineLowPrecOp AffineMapParser::consumeIfLowPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700775 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700776 case Token::plus:
777 consumeToken(Token::plus);
778 return AffineLowPrecOp::Add;
779 case Token::minus:
780 consumeToken(Token::minus);
781 return AffineLowPrecOp::Sub;
782 default:
783 return AffineLowPrecOp::LNoOp;
784 }
785}
786
787/// Consume this token if it is a higher precedence affine op (there are only
788/// two precedence levels)
Chris Lattner2e595eb2018-07-10 10:08:27 -0700789AffineHighPrecOp AffineMapParser::consumeIfHighPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700790 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700791 case Token::star:
792 consumeToken(Token::star);
793 return Mul;
794 case Token::kw_floordiv:
795 consumeToken(Token::kw_floordiv);
796 return FloorDiv;
797 case Token::kw_ceildiv:
798 consumeToken(Token::kw_ceildiv);
799 return CeilDiv;
800 case Token::kw_mod:
801 consumeToken(Token::kw_mod);
802 return Mod;
803 default:
804 return HNoOp;
805 }
806}
807
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700808/// Parse a high precedence op expression list: mul, div, and mod are high
809/// precedence binary ops, i.e., parse a
810/// expr_1 op_1 expr_2 op_2 ... expr_n
811/// where op_1, op_2 are all a AffineHighPrecOp (mul, div, mod).
812/// All affine binary ops are left associative.
813/// Given llhs, returns (llhs llhsOp lhs) op rhs, or (lhs op rhs) if llhs is
814/// null. If no rhs can be found, returns (llhs llhsOp lhs) or lhs if llhs is
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700815/// null. llhsOpLoc is the location of the llhsOp token that will be used to
816/// report an error for non-conforming expressions.
817AffineExpr *AffineMapParser::parseAffineHighPrecOpExpr(AffineExpr *llhs,
818 AffineHighPrecOp llhsOp,
819 SMLoc llhsOpLoc) {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700820 AffineExpr *lhs = parseAffineOperandExpr(llhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700821 if (!lhs)
822 return nullptr;
823
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700824 // Found an LHS. Parse the remaining expression.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700825 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -0700826 if (AffineHighPrecOp op = consumeIfHighPrecOp()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700827 if (llhs) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700828 AffineExpr *expr = getBinaryAffineOpExpr(llhsOp, llhs, lhs, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700829 if (!expr)
830 return nullptr;
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700831 return parseAffineHighPrecOpExpr(expr, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700832 }
833 // No LLHS, get RHS
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700834 return parseAffineHighPrecOpExpr(lhs, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700835 }
836
837 // This is the last operand in this expression.
838 if (llhs)
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700839 return getBinaryAffineOpExpr(llhsOp, llhs, lhs, llhsOpLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700840
841 // No llhs, 'lhs' itself is the expression.
842 return lhs;
843}
844
845/// Parse an affine expression inside parentheses.
846///
847/// affine-expr ::= `(` affine-expr `)`
Chris Lattner2e595eb2018-07-10 10:08:27 -0700848AffineExpr *AffineMapParser::parseParentheticalExpr() {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700849 if (!consumeIf(Token::l_paren))
850 return (emitError("expected '('"), nullptr);
Chris Lattner48af7d12018-07-09 19:05:38 -0700851 if (getToken().is(Token::r_paren))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700852 return (emitError("no expression inside parentheses"), nullptr);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700853 auto *expr = parseAffineExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700854 if (!expr)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700855 return nullptr;
856 if (!consumeIf(Token::r_paren))
857 return (emitError("expected ')'"), nullptr);
858 return expr;
859}
860
861/// Parse the negation expression.
862///
863/// affine-expr ::= `-` affine-expr
Chris Lattner2e595eb2018-07-10 10:08:27 -0700864AffineExpr *AffineMapParser::parseNegateExpression(AffineExpr *lhs) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700865 if (!consumeIf(Token::minus))
866 return (emitError("expected '-'"), nullptr);
867
Chris Lattner2e595eb2018-07-10 10:08:27 -0700868 AffineExpr *operand = parseAffineOperandExpr(lhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700869 // Since negation has the highest precedence of all ops (including high
870 // precedence ops) but lower than parentheses, we are only going to use
871 // parseAffineOperandExpr instead of parseAffineExpr here.
872 if (!operand)
873 // Extra error message although parseAffineOperandExpr would have
874 // complained. Leads to a better diagnostic.
875 return (emitError("missing operand of negation"), nullptr);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700876 auto *minusOne = builder.getConstantExpr(-1);
877 return builder.getMulExpr(minusOne, operand);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700878}
879
880/// Parse a bare id that may appear in an affine expression.
881///
882/// affine-expr ::= bare-id
Chris Lattner2e595eb2018-07-10 10:08:27 -0700883AffineExpr *AffineMapParser::parseBareIdExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700884 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700885 return (emitError("expected bare identifier"), nullptr);
886
Chris Lattner48af7d12018-07-09 19:05:38 -0700887 StringRef sRef = getTokenSpelling();
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700888 // dims, symbols are all pairwise distinct.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700889 if (dims.count(sRef)) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700890 if (isPureSymbolic())
891 return (emitError("identifier used is not a symbolic identifier"),
892 nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700893 consumeToken(Token::bare_identifier);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700894 return builder.getDimExpr(dims.lookup(sRef));
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700895 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700896
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700897 if (symbols.count(sRef)) {
898 consumeToken(Token::bare_identifier);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700899 return builder.getSymbolExpr(symbols.lookup(sRef));
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700900 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700901
902 return (emitError("use of undeclared identifier"), nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700903}
904
905/// Parse a positive integral constant appearing in an affine expression.
906///
907/// affine-expr ::= integer-literal
Chris Lattner2e595eb2018-07-10 10:08:27 -0700908AffineExpr *AffineMapParser::parseIntegerExpr() {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700909 // No need to handle negative numbers separately here. They are naturally
910 // handled via the unary negation operator, although (FIXME) MININT_64 still
911 // not correctly handled.
Chris Lattner48af7d12018-07-09 19:05:38 -0700912 if (getToken().isNot(Token::integer))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700913 return (emitError("expected integer"), nullptr);
914
Chris Lattner48af7d12018-07-09 19:05:38 -0700915 auto val = getToken().getUInt64IntegerValue();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700916 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
917 return (emitError("constant too large for affineint"), nullptr);
918 }
919 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700920 return builder.getConstantExpr((int64_t)val.getValue());
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700921}
922
923/// Parses an expression that can be a valid operand of an affine expression.
Uday Bondhugula76345202018-07-09 13:47:52 -0700924/// lhs: if non-null, lhs is an affine expression that is the lhs of a binary
925/// operator, the rhs of which is being parsed. This is used to determine
926/// whether an error should be emitted for a missing right operand.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700927// Eg: for an expression without parentheses (like i + j + k + l), each
928// of the four identifiers is an operand. For i + j*k + l, j*k is not an
929// operand expression, it's an op expression and will be parsed via
930// parseAffineHighPrecOpExpression(). However, for i + (j*k) + -l, (j*k) and -l
931// are valid operands that will be parsed by this function.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700932AffineExpr *AffineMapParser::parseAffineOperandExpr(AffineExpr *lhs) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700933 switch (getToken().getKind()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700934 case Token::bare_identifier:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700935 return parseBareIdExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700936 case Token::integer:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700937 return parseIntegerExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700938 case Token::l_paren:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700939 return parseParentheticalExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700940 case Token::minus:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700941 return parseNegateExpression(lhs);
Uday Bondhugula76345202018-07-09 13:47:52 -0700942 case Token::kw_ceildiv:
943 case Token::kw_floordiv:
944 case Token::kw_mod:
945 case Token::plus:
946 case Token::star:
947 if (lhs)
948 emitError("missing right operand of binary operator");
949 else
950 emitError("missing left operand of binary operator");
951 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700952 default:
953 if (lhs)
Uday Bondhugula76345202018-07-09 13:47:52 -0700954 emitError("missing right operand of binary operator");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700955 else
956 emitError("expected affine expression");
957 return nullptr;
958 }
959}
960
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700961/// Parse affine expressions that are bare-id's, integer constants,
962/// parenthetical affine expressions, and affine op expressions that are a
963/// composition of those.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700964///
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700965/// All binary op's associate from left to right.
966///
967/// {add, sub} have lower precedence than {mul, div, and mod}.
968///
Uday Bondhugula76345202018-07-09 13:47:52 -0700969/// Add, sub'are themselves at the same precedence level. Mul, floordiv,
970/// ceildiv, and mod are at the same higher precedence level. Negation has
971/// higher precedence than any binary op.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700972///
973/// llhs: the affine expression appearing on the left of the one being parsed.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700974/// This function will return ((llhs llhsOp lhs) op rhs) if llhs is non null,
975/// and lhs op rhs otherwise; if there is no rhs, llhs llhsOp lhs is returned if
976/// llhs is non-null; otherwise lhs is returned. This is to deal with left
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700977/// associativity.
978///
979/// Eg: when the expression is e1 + e2*e3 + e4, with e1 as llhs, this function
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700980/// will return the affine expr equivalent of (e1 + (e2*e3)) + e4, where (e2*e3)
981/// will be parsed using parseAffineHighPrecOpExpr().
Chris Lattner2e595eb2018-07-10 10:08:27 -0700982AffineExpr *AffineMapParser::parseAffineLowPrecOpExpr(AffineExpr *llhs,
983 AffineLowPrecOp llhsOp) {
Uday Bondhugula76345202018-07-09 13:47:52 -0700984 AffineExpr *lhs;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700985 if (!(lhs = parseAffineOperandExpr(llhs)))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700986 return nullptr;
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700987
988 // Found an LHS. Deal with the ops.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700989 if (AffineLowPrecOp lOp = consumeIfLowPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700990 if (llhs) {
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700991 AffineExpr *sum = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700992 return parseAffineLowPrecOpExpr(sum, lOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700993 }
994 // No LLHS, get RHS and form the expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700995 return parseAffineLowPrecOpExpr(lhs, lOp);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700996 }
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700997 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -0700998 if (AffineHighPrecOp hOp = consumeIfHighPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700999 // We have a higher precedence op here. Get the rhs operand for the llhs
1000 // through parseAffineHighPrecOpExpr.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001001 AffineExpr *highRes = parseAffineHighPrecOpExpr(lhs, hOp, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001002 if (!highRes)
1003 return nullptr;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001004
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001005 // If llhs is null, the product forms the first operand of the yet to be
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001006 // found expression. If non-null, the op to associate with llhs is llhsOp.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001007 AffineExpr *expr =
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001008 llhs ? getBinaryAffineOpExpr(llhsOp, llhs, highRes) : highRes;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001009
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001010 // Recurse for subsequent low prec op's after the affine high prec op
1011 // expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001012 if (AffineLowPrecOp nextOp = consumeIfLowPrecOp())
1013 return parseAffineLowPrecOpExpr(expr, nextOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001014 return expr;
1015 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001016 // Last operand in the expression list.
1017 if (llhs)
1018 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
1019 // No llhs, 'lhs' itself is the expression.
1020 return lhs;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001021}
1022
1023/// Parse an affine expression.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001024/// affine-expr ::= `(` affine-expr `)`
1025/// | `-` affine-expr
1026/// | affine-expr `+` affine-expr
1027/// | affine-expr `-` affine-expr
1028/// | affine-expr `*` affine-expr
1029/// | affine-expr `floordiv` affine-expr
1030/// | affine-expr `ceildiv` affine-expr
1031/// | affine-expr `mod` affine-expr
1032/// | bare-id
1033/// | integer-literal
1034///
1035/// Additional conditions are checked depending on the production. For eg., one
1036/// of the operands for `*` has to be either constant/symbolic; the second
1037/// operand for floordiv, ceildiv, and mod has to be a positive integer.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001038AffineExpr *AffineMapParser::parseAffineExpr() {
1039 return parseAffineLowPrecOpExpr(nullptr, AffineLowPrecOp::LNoOp);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001040}
1041
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001042/// Parse a dim or symbol from the lists appearing before the actual expressions
Chris Lattner2e595eb2018-07-10 10:08:27 -07001043/// of the affine map. Update our state to store the dimensional/symbolic
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001044/// identifier. 'dim': whether it's the dim list or symbol list that is being
1045/// parsed.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001046ParseResult AffineMapParser::parseDimOrSymbolId(bool isDim) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001047 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001048 return emitError("expected bare identifier");
Chris Lattner48af7d12018-07-09 19:05:38 -07001049 auto sRef = getTokenSpelling();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001050 consumeToken(Token::bare_identifier);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001051 if (dims.count(sRef))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001052 return emitError("dimensional identifier name reused");
Chris Lattner2e595eb2018-07-10 10:08:27 -07001053 if (symbols.count(sRef))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001054 return emitError("symbolic identifier name reused");
Chris Lattner2e595eb2018-07-10 10:08:27 -07001055 if (isDim)
1056 dims.insert({sRef, dims.size()});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001057 else
Chris Lattner2e595eb2018-07-10 10:08:27 -07001058 symbols.insert({sRef, symbols.size()});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001059 return ParseSuccess;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001060}
1061
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001062/// Parse the list of symbolic identifiers to an affine map.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001063ParseResult AffineMapParser::parseSymbolIdList() {
1064 if (!consumeIf(Token::l_bracket))
1065 return emitError("expected '['");
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001066
Chris Lattner2e595eb2018-07-10 10:08:27 -07001067 auto parseElt = [&]() -> ParseResult { return parseDimOrSymbolId(false); };
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001068 return parseCommaSeparatedList(Token::r_bracket, parseElt);
1069}
1070
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001071/// Parse the list of dimensional identifiers to an affine map.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001072ParseResult AffineMapParser::parseDimIdList() {
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001073 if (!consumeIf(Token::l_paren))
1074 return emitError("expected '(' at start of dimensional identifiers list");
1075
Chris Lattner2e595eb2018-07-10 10:08:27 -07001076 auto parseElt = [&]() -> ParseResult { return parseDimOrSymbolId(true); };
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001077 return parseCommaSeparatedList(Token::r_paren, parseElt);
1078}
1079
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001080/// Parse an affine map definition.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001081///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001082/// affine-map-inline ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
1083/// (`size` `(` dim-size (`,` dim-size)* `)`)?
1084/// dim-size ::= affine-expr | `min` `(` affine-expr ( `,` affine-expr)+ `)`
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001085///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001086/// multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner2e595eb2018-07-10 10:08:27 -07001087AffineMap *AffineMapParser::parseAffineMapInline() {
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001088 // List of dimensional identifiers.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001089 if (parseDimIdList())
Chris Lattner7121b802018-07-04 20:45:39 -07001090 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001091
1092 // Symbols are optional.
Chris Lattner48af7d12018-07-09 19:05:38 -07001093 if (getToken().is(Token::l_bracket)) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001094 if (parseSymbolIdList())
Chris Lattner7121b802018-07-04 20:45:39 -07001095 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001096 }
1097 if (!consumeIf(Token::arrow)) {
Chris Lattner7121b802018-07-04 20:45:39 -07001098 return (emitError("expected '->' or '['"), nullptr);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001099 }
1100 if (!consumeIf(Token::l_paren)) {
1101 emitError("expected '(' at start of affine map range");
Chris Lattner7121b802018-07-04 20:45:39 -07001102 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001103 }
1104
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001105 SmallVector<AffineExpr *, 4> exprs;
1106 auto parseElt = [&]() -> ParseResult {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001107 auto *elt = parseAffineExpr();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001108 ParseResult res = elt ? ParseSuccess : ParseFailure;
1109 exprs.push_back(elt);
1110 return res;
1111 };
1112
1113 // Parse a multi-dimensional affine expression (a comma-separated list of 1-d
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001114 // affine expressions); the list cannot be empty.
1115 // Grammar: multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
1116 if (parseCommaSeparatedList(Token::r_paren, parseElt, false))
Chris Lattner7121b802018-07-04 20:45:39 -07001117 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001118
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001119 // Parse optional range sizes.
Uday Bondhugula1e500b42018-07-12 18:04:04 -07001120 // range-sizes ::= (`size` `(` dim-size (`,` dim-size)* `)`)?
1121 // dim-size ::= affine-expr | `min` `(` affine-expr (`,` affine-expr)+ `)`
1122 // TODO(bondhugula): support for min of several affine expressions.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001123 // TODO: check if sizes are non-negative whenever they are constant.
1124 SmallVector<AffineExpr *, 4> rangeSizes;
1125 if (consumeIf(Token::kw_size)) {
1126 // Location of the l_paren token (if it exists) for error reporting later.
1127 auto loc = getToken().getLoc();
1128 if (!consumeIf(Token::l_paren))
1129 return (emitError("expected '(' at start of affine map range"), nullptr);
1130
1131 auto parseRangeSize = [&]() -> ParseResult {
1132 auto *elt = parseAffineExpr();
1133 ParseResult res = elt ? ParseSuccess : ParseFailure;
1134 rangeSizes.push_back(elt);
1135 return res;
1136 };
1137
1138 setSymbolicParsing(true);
1139 if (parseCommaSeparatedList(Token::r_paren, parseRangeSize, false))
1140 return nullptr;
1141 if (exprs.size() > rangeSizes.size())
1142 return (emitError(loc, "fewer range sizes than range expressions"),
1143 nullptr);
1144 if (exprs.size() < rangeSizes.size())
1145 return (emitError(loc, "more range sizes than range expressions"),
1146 nullptr);
1147 }
1148
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001149 // Parsed a valid affine map.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001150 return builder.getAffineMap(dims.size(), symbols.size(), exprs, rangeSizes);
MLIR Teamf85a6262018-06-27 11:03:08 -07001151}
1152
Chris Lattner2e595eb2018-07-10 10:08:27 -07001153AffineMap *Parser::parseAffineMapInline() {
1154 return AffineMapParser(state).parseAffineMapInline();
1155}
1156
MLIR Team718c82f2018-07-16 09:45:22 -07001157AffineMap *Parser::parseAffineMapReference() {
1158 if (getToken().is(Token::hash_identifier)) {
1159 // Parse affine map identifier and verify that it exists.
1160 StringRef affineMapId = getTokenSpelling().drop_front();
1161 if (getState().affineMapDefinitions.count(affineMapId) == 0)
1162 return (emitError("undefined affine map id '" + affineMapId + "'"),
1163 nullptr);
1164 consumeToken(Token::hash_identifier);
1165 return getState().affineMapDefinitions[affineMapId];
1166 }
1167 // Try to parse inline affine map.
1168 return parseAffineMapInline();
1169}
1170
MLIR Teamf85a6262018-06-27 11:03:08 -07001171//===----------------------------------------------------------------------===//
Chris Lattner7f9cc272018-07-19 08:35:28 -07001172// FunctionParser
Chris Lattner4c95a502018-06-23 16:03:42 -07001173//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001174
Chris Lattner7f9cc272018-07-19 08:35:28 -07001175namespace {
1176/// This class contains parser state that is common across CFG and ML functions,
1177/// notably for dealing with operations and SSA values.
1178class FunctionParser : public Parser {
1179public:
1180 FunctionParser(ParserState &state) : Parser(state) {}
1181
1182 /// This represents a use of an SSA value in the program. This tracks
1183 /// location information in case this ends up being a use of an undefined
1184 /// value.
1185 typedef std::pair<StringRef, SMLoc> SSAUseInfo;
1186
1187 /// Given a reference to an SSA value and its type, return a reference. This
1188 /// returns null on failure.
1189 SSAValue *resolveSSAUse(SSAUseInfo useInfo, Type *type);
1190
1191 /// Register a definition of a value with the symbol table.
1192 ParseResult addDefinition(SSAUseInfo useInfo, SSAValue *value);
1193
1194 // SSA parsing productions.
1195 ParseResult parseSSAUse(SSAUseInfo &result);
1196 ParseResult parseOptionalSSAUseList(Token::Kind endToken,
1197 SmallVectorImpl<SSAUseInfo> &results);
1198 SSAValue *parseSSAUseAndType();
1199 ParseResult
1200 parseOptionalSSAUseAndTypeList(Token::Kind endToken,
1201 SmallVectorImpl<SSAValue *> &results);
1202
1203 // Operations
1204 ParseResult parseOperation(const CreateOperationFunction &createOpFunc);
1205
1206private:
1207 /// This keeps track of all of the SSA values we are tracking, indexed by
1208 /// their name (either an identifier or a number).
1209 llvm::StringMap<std::pair<SSAValue *, SMLoc>> values;
1210};
1211} // end anonymous namespace
1212
1213/// Given an unbound reference to an SSA value and its type, return a the value
1214/// it specifies. This returns null on failure.
1215SSAValue *FunctionParser::resolveSSAUse(SSAUseInfo useInfo, Type *type) {
1216 // If we have already seen a value of this name, return it.
1217 auto it = values.find(useInfo.first);
1218 if (it != values.end()) {
1219 // Check that the type matches the other uses.
1220 auto result = it->second.first;
1221 if (result->getType() == type)
1222 return result;
1223
1224 emitError(useInfo.second, "use of value '" + useInfo.first.str() +
1225 "' expects different type than prior uses");
1226 emitError(it->second.second, "prior use here");
1227 return nullptr;
1228 }
1229
1230 // Otherwise we have a forward reference.
1231 // TODO: Handle forward references.
1232 emitError(useInfo.second, "undeclared or forward reference");
1233 return nullptr;
1234}
1235
1236/// Register a definition of a value with the symbol table.
1237ParseResult FunctionParser::addDefinition(SSAUseInfo useInfo, SSAValue *value) {
1238
1239 // If this is the first definition of this thing, then we are trivially done.
1240 auto insertInfo = values.insert({useInfo.first, {value, useInfo.second}});
1241 if (insertInfo.second)
1242 return ParseSuccess;
1243
1244 // If we already had a value, replace it with the new one and remove the
1245 // placeholder, only if it was a forward ref.
1246 // TODO: Handle forward references.
1247 emitError(useInfo.second, "redefinition of SSA value " + useInfo.first.str());
1248 return ParseFailure;
1249}
1250
Chris Lattner78276e32018-07-07 15:48:26 -07001251/// Parse a SSA operand for an instruction or statement.
1252///
1253/// ssa-use ::= ssa-id | ssa-constant
Chris Lattner7f9cc272018-07-19 08:35:28 -07001254/// TODO: SSA Constants.
Chris Lattner78276e32018-07-07 15:48:26 -07001255///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001256ParseResult FunctionParser::parseSSAUse(SSAUseInfo &result) {
1257 result.first = getTokenSpelling();
1258 result.second = getToken().getLoc();
1259 if (!consumeIf(Token::percent_identifier))
1260 return emitError("expected SSA operand");
1261 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001262}
1263
1264/// Parse a (possibly empty) list of SSA operands.
1265///
1266/// ssa-use-list ::= ssa-use (`,` ssa-use)*
1267/// ssa-use-list-opt ::= ssa-use-list?
1268///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001269ParseResult
1270FunctionParser::parseOptionalSSAUseList(Token::Kind endToken,
1271 SmallVectorImpl<SSAUseInfo> &results) {
1272 return parseCommaSeparatedList(endToken, [&]() -> ParseResult {
1273 SSAUseInfo result;
1274 if (parseSSAUse(result))
1275 return ParseFailure;
1276 results.push_back(result);
1277 return ParseSuccess;
1278 });
Chris Lattner78276e32018-07-07 15:48:26 -07001279}
1280
1281/// Parse an SSA use with an associated type.
1282///
1283/// ssa-use-and-type ::= ssa-use `:` type
Chris Lattner7f9cc272018-07-19 08:35:28 -07001284SSAValue *FunctionParser::parseSSAUseAndType() {
1285 SSAUseInfo useInfo;
1286 if (parseSSAUse(useInfo))
1287 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001288
1289 if (!consumeIf(Token::colon))
Chris Lattner7f9cc272018-07-19 08:35:28 -07001290 return (emitError("expected ':' and type for SSA operand"), nullptr);
Chris Lattner78276e32018-07-07 15:48:26 -07001291
Chris Lattner7f9cc272018-07-19 08:35:28 -07001292 auto *type = parseType();
1293 if (!type)
1294 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001295
Chris Lattner7f9cc272018-07-19 08:35:28 -07001296 return resolveSSAUse(useInfo, type);
Chris Lattner78276e32018-07-07 15:48:26 -07001297}
1298
1299/// Parse a (possibly empty) list of SSA operands with types.
1300///
1301/// ssa-use-and-type-list ::= ssa-use-and-type (`,` ssa-use-and-type)*
1302///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001303ParseResult FunctionParser::parseOptionalSSAUseAndTypeList(
1304 Token::Kind endToken, SmallVectorImpl<SSAValue *> &results) {
1305 return parseCommaSeparatedList(endToken, [&]() -> ParseResult {
1306 if (auto *value = parseSSAUseAndType()) {
1307 results.push_back(value);
1308 return ParseSuccess;
1309 }
1310 return ParseFailure;
1311 });
Chris Lattner78276e32018-07-07 15:48:26 -07001312}
1313
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001314/// Parse the CFG or MLFunc operation.
1315///
1316/// TODO(clattner): This is a change from the MLIR spec as written, it is an
1317/// experiment that will eliminate "builtin" instructions as a thing.
1318///
1319/// operation ::=
1320/// (ssa-id `=`)? string '(' ssa-use-list? ')' attribute-dict?
1321/// `:` function-type
1322///
1323ParseResult
Chris Lattner7f9cc272018-07-19 08:35:28 -07001324FunctionParser::parseOperation(const CreateOperationFunction &createOpFunc) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001325 auto loc = getToken().getLoc();
1326
1327 StringRef resultID;
1328 if (getToken().is(Token::percent_identifier)) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001329 resultID = getTokenSpelling();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001330 consumeToken(Token::percent_identifier);
1331 if (!consumeIf(Token::equal))
1332 return emitError("expected '=' after SSA name");
1333 }
1334
1335 if (getToken().isNot(Token::string))
1336 return emitError("expected operation name in quotes");
1337
1338 auto name = getToken().getStringValue();
1339 if (name.empty())
1340 return emitError("empty operation name is invalid");
1341
1342 consumeToken(Token::string);
1343
1344 if (!consumeIf(Token::l_paren))
1345 return emitError("expected '(' to start operand list");
1346
1347 // Parse the operand list.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001348 SmallVector<SSAUseInfo, 8> operandInfos;
1349 parseOptionalSSAUseList(Token::r_paren, operandInfos);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001350
1351 SmallVector<NamedAttribute, 4> attributes;
1352 if (getToken().is(Token::l_brace)) {
1353 if (parseAttributeDict(attributes))
1354 return ParseFailure;
1355 }
1356
Chris Lattner3b2ef762018-07-18 15:31:25 -07001357 if (!consumeIf(Token::colon))
1358 return emitError("expected ':' followed by instruction type");
1359
1360 auto typeLoc = getToken().getLoc();
1361 auto type = parseType();
1362 if (!type)
1363 return ParseFailure;
1364 auto fnType = dyn_cast<FunctionType>(type);
1365 if (!fnType)
1366 return emitError(typeLoc, "expected function type");
1367
Chris Lattner7f9cc272018-07-19 08:35:28 -07001368 // Check that we have the right number of types for the operands.
1369 auto operandTypes = fnType->getInputs();
1370 if (operandTypes.size() != operandInfos.size()) {
1371 auto plural = "s"[operandInfos.size() == 1];
1372 return emitError(typeLoc, "expected " + llvm::utostr(operandInfos.size()) +
Chris Lattnerf8cce872018-07-20 09:28:54 -07001373 " operand type" + plural + " but had " +
Chris Lattner7f9cc272018-07-19 08:35:28 -07001374 llvm::utostr(operandTypes.size()));
1375 }
1376
1377 // Resolve all of the operands.
1378 SmallVector<SSAValue *, 8> operands;
1379 for (unsigned i = 0, e = operandInfos.size(); i != e; ++i) {
1380 operands.push_back(resolveSSAUse(operandInfos[i], operandTypes[i]));
1381 if (!operands.back())
1382 return ParseFailure;
1383 }
1384
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001385 auto nameId = builder.getIdentifier(name);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001386 auto op = createOpFunc(nameId, operands, fnType->getResults(), attributes);
1387 if (!op)
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001388 return ParseFailure;
1389
1390 // We just parsed an operation. If it is a recognized one, verify that it
1391 // is structurally as we expect. If not, produce an error with a reasonable
1392 // source location.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001393 if (auto *opInfo = op->getAbstractOperation(builder.getContext())) {
1394 if (auto error = opInfo->verifyInvariants(op))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001395 return emitError(loc, error);
1396 }
1397
Chris Lattner7f9cc272018-07-19 08:35:28 -07001398 // If the instruction had a name, register it.
1399 if (!resultID.empty()) {
1400 // FIXME: Add result infra to handle Stmt results as well to make this
1401 // generic.
1402 if (auto *inst = dyn_cast<OperationInst>(op)) {
Chris Lattnerf8cce872018-07-20 09:28:54 -07001403 if (inst->getNumResults() == 0)
Chris Lattner7f9cc272018-07-19 08:35:28 -07001404 return emitError(loc, "cannot name an operation with no results");
1405
Chris Lattnerf8cce872018-07-20 09:28:54 -07001406 addDefinition({resultID, loc}, inst->getResult(0));
Chris Lattner7f9cc272018-07-19 08:35:28 -07001407 }
1408 }
1409
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001410 return ParseSuccess;
1411}
Chris Lattnere79379a2018-06-22 10:39:19 -07001412
Chris Lattner48af7d12018-07-09 19:05:38 -07001413//===----------------------------------------------------------------------===//
1414// CFG Functions
1415//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001416
Chris Lattner4c95a502018-06-23 16:03:42 -07001417namespace {
Chris Lattner48af7d12018-07-09 19:05:38 -07001418/// This is a specialized parser for CFGFunction's, maintaining the state
1419/// transient to their bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001420class CFGFunctionParser : public FunctionParser {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001421public:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001422 CFGFunctionParser(ParserState &state, CFGFunction *function)
Chris Lattner7f9cc272018-07-19 08:35:28 -07001423 : FunctionParser(state), function(function), builder(function) {}
Chris Lattner2e595eb2018-07-10 10:08:27 -07001424
1425 ParseResult parseFunctionBody();
1426
1427private:
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001428 CFGFunction *function;
1429 llvm::StringMap<std::pair<BasicBlock*, SMLoc>> blocksByName;
Chris Lattner48af7d12018-07-09 19:05:38 -07001430
1431 /// This builder intentionally shadows the builder in the base class, with a
1432 /// more specific builder type.
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001433 CFGFuncBuilder builder;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001434
Chris Lattner4c95a502018-06-23 16:03:42 -07001435 /// Get the basic block with the specified name, creating it if it doesn't
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001436 /// already exist. The location specified is the point of use, which allows
1437 /// us to diagnose references to blocks that are not defined precisely.
1438 BasicBlock *getBlockNamed(StringRef name, SMLoc loc) {
1439 auto &blockAndLoc = blocksByName[name];
1440 if (!blockAndLoc.first) {
Chris Lattner3a467cc2018-07-01 20:28:00 -07001441 blockAndLoc.first = new BasicBlock();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001442 blockAndLoc.second = loc;
Chris Lattner4c95a502018-06-23 16:03:42 -07001443 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001444 return blockAndLoc.first;
Chris Lattner4c95a502018-06-23 16:03:42 -07001445 }
Chris Lattner48af7d12018-07-09 19:05:38 -07001446
Chris Lattner48af7d12018-07-09 19:05:38 -07001447 ParseResult parseBasicBlock();
1448 OperationInst *parseCFGOperation();
1449 TerminatorInst *parseTerminator();
Chris Lattner4c95a502018-06-23 16:03:42 -07001450};
1451} // end anonymous namespace
1452
Chris Lattner48af7d12018-07-09 19:05:38 -07001453ParseResult CFGFunctionParser::parseFunctionBody() {
1454 if (!consumeIf(Token::l_brace))
1455 return emitError("expected '{' in CFG function");
1456
1457 // Make sure we have at least one block.
1458 if (getToken().is(Token::r_brace))
1459 return emitError("CFG functions must have at least one basic block");
Chris Lattner4c95a502018-06-23 16:03:42 -07001460
1461 // Parse the list of blocks.
1462 while (!consumeIf(Token::r_brace))
Chris Lattner48af7d12018-07-09 19:05:38 -07001463 if (parseBasicBlock())
Chris Lattner4c95a502018-06-23 16:03:42 -07001464 return ParseFailure;
1465
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001466 // Verify that all referenced blocks were defined. Iteration over a
1467 // StringMap isn't determinstic, but this is good enough for our purposes.
Chris Lattner48af7d12018-07-09 19:05:38 -07001468 for (auto &elt : blocksByName) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001469 auto *bb = elt.second.first;
Chris Lattner3a467cc2018-07-01 20:28:00 -07001470 if (!bb->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001471 return emitError(elt.second.second,
1472 "reference to an undefined basic block '" +
1473 elt.first() + "'");
1474 }
1475
Chris Lattner48af7d12018-07-09 19:05:38 -07001476 getModule()->functionList.push_back(function);
Chris Lattner4c95a502018-06-23 16:03:42 -07001477 return ParseSuccess;
1478}
1479
1480/// Basic block declaration.
1481///
1482/// basic-block ::= bb-label instruction* terminator-stmt
1483/// bb-label ::= bb-id bb-arg-list? `:`
1484/// bb-id ::= bare-id
1485/// bb-arg-list ::= `(` ssa-id-and-type-list? `)`
1486///
Chris Lattner48af7d12018-07-09 19:05:38 -07001487ParseResult CFGFunctionParser::parseBasicBlock() {
1488 SMLoc nameLoc = getToken().getLoc();
1489 auto name = getTokenSpelling();
Chris Lattner4c95a502018-06-23 16:03:42 -07001490 if (!consumeIf(Token::bare_identifier))
1491 return emitError("expected basic block name");
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001492
Chris Lattner48af7d12018-07-09 19:05:38 -07001493 auto *block = getBlockNamed(name, nameLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001494
1495 // If this block has already been parsed, then this is a redefinition with the
1496 // same block name.
Chris Lattner3a467cc2018-07-01 20:28:00 -07001497 if (block->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001498 return emitError(nameLoc, "redefinition of block '" + name.str() + "'");
1499
Chris Lattner3a467cc2018-07-01 20:28:00 -07001500 // Add the block to the function.
Chris Lattner48af7d12018-07-09 19:05:38 -07001501 function->push_back(block);
Chris Lattner4c95a502018-06-23 16:03:42 -07001502
Chris Lattner78276e32018-07-07 15:48:26 -07001503 // If an argument list is present, parse it.
1504 if (consumeIf(Token::l_paren)) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001505 SmallVector<SSAValue *, 8> bbArgs;
1506 if (parseOptionalSSAUseAndTypeList(Token::r_paren, bbArgs))
Chris Lattner78276e32018-07-07 15:48:26 -07001507 return ParseFailure;
1508
1509 // TODO: attach it.
1510 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001511
1512 if (!consumeIf(Token::colon))
1513 return emitError("expected ':' after basic block name");
1514
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001515 // Set the insertion point to the block we want to insert new operations into.
Chris Lattner48af7d12018-07-09 19:05:38 -07001516 builder.setInsertionPoint(block);
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001517
Chris Lattner7f9cc272018-07-19 08:35:28 -07001518 auto createOpFunc = [&](Identifier name, ArrayRef<SSAValue *> operands,
1519 ArrayRef<Type *> resultTypes,
1520 ArrayRef<NamedAttribute> attrs) -> Operation * {
1521 SmallVector<CFGValue *, 8> cfgOperands;
1522 cfgOperands.reserve(operands.size());
1523 for (auto *op : operands)
1524 cfgOperands.push_back(cast<CFGValue>(op));
1525 return builder.createOperation(name, cfgOperands, resultTypes, attrs);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001526 };
1527
Chris Lattnered65a732018-06-28 20:45:33 -07001528 // Parse the list of operations that make up the body of the block.
Chris Lattner48af7d12018-07-09 19:05:38 -07001529 while (getToken().isNot(Token::kw_return, Token::kw_br)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001530 if (parseOperation(createOpFunc))
Chris Lattnered65a732018-06-28 20:45:33 -07001531 return ParseFailure;
1532 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001533
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001534 if (!parseTerminator())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001535 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07001536
1537 return ParseSuccess;
1538}
1539
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001540/// Parse the terminator instruction for a basic block.
1541///
1542/// terminator-stmt ::= `br` bb-id branch-use-list?
1543/// branch-use-list ::= `(` ssa-use-and-type-list? `)`
1544/// terminator-stmt ::=
1545/// `cond_br` ssa-use `,` bb-id branch-use-list? `,` bb-id branch-use-list?
1546/// terminator-stmt ::= `return` ssa-use-and-type-list?
1547///
Chris Lattner48af7d12018-07-09 19:05:38 -07001548TerminatorInst *CFGFunctionParser::parseTerminator() {
1549 switch (getToken().getKind()) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001550 default:
Chris Lattner3a467cc2018-07-01 20:28:00 -07001551 return (emitError("expected terminator at end of basic block"), nullptr);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001552
1553 case Token::kw_return:
1554 consumeToken(Token::kw_return);
Chris Lattner48af7d12018-07-09 19:05:38 -07001555 return builder.createReturnInst();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001556
1557 case Token::kw_br: {
1558 consumeToken(Token::kw_br);
Chris Lattner48af7d12018-07-09 19:05:38 -07001559 auto destBB = getBlockNamed(getTokenSpelling(), getToken().getLoc());
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001560 if (!consumeIf(Token::bare_identifier))
Chris Lattner3a467cc2018-07-01 20:28:00 -07001561 return (emitError("expected basic block name"), nullptr);
Chris Lattner48af7d12018-07-09 19:05:38 -07001562 return builder.createBranchInst(destBB);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001563 }
Chris Lattner78276e32018-07-07 15:48:26 -07001564 // TODO: cond_br.
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001565 }
1566}
1567
Chris Lattner48af7d12018-07-09 19:05:38 -07001568//===----------------------------------------------------------------------===//
1569// ML Functions
1570//===----------------------------------------------------------------------===//
1571
1572namespace {
1573/// Refined parser for MLFunction bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001574class MLFunctionParser : public FunctionParser {
Chris Lattner48af7d12018-07-09 19:05:38 -07001575public:
Chris Lattner48af7d12018-07-09 19:05:38 -07001576 MLFunctionParser(ParserState &state, MLFunction *function)
Chris Lattner7f9cc272018-07-19 08:35:28 -07001577 : FunctionParser(state), function(function), builder(function) {}
Chris Lattner48af7d12018-07-09 19:05:38 -07001578
1579 ParseResult parseFunctionBody();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001580
1581private:
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001582 MLFunction *function;
1583
1584 /// This builder intentionally shadows the builder in the base class, with a
1585 /// more specific builder type.
1586 MLFuncBuilder builder;
1587
1588 ParseResult parseForStmt();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001589 AffineConstantExpr *parseIntConstant();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001590 ParseResult parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001591 ParseResult parseElseClause(IfClause *elseClause);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001592 ParseResult parseStatements(StmtBlock *block);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001593 ParseResult parseStmtBlock(StmtBlock *block);
Chris Lattner48af7d12018-07-09 19:05:38 -07001594};
1595} // end anonymous namespace
1596
Chris Lattner48af7d12018-07-09 19:05:38 -07001597ParseResult MLFunctionParser::parseFunctionBody() {
1598 if (!consumeIf(Token::l_brace))
1599 return emitError("expected '{' in ML function");
1600
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001601 // Parse statements in this function
1602 if (parseStatements(function))
1603 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001604
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001605 if (!consumeIf(Token::kw_return))
1606 emitError("ML function must end with return statement");
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001607
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001608 // TODO: store return operands in the IR.
1609 SmallVector<SSAUseInfo, 4> dummyUseInfo;
1610 if (parseOptionalSSAUseList(Token::r_brace, dummyUseInfo))
1611 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001612
Chris Lattner48af7d12018-07-09 19:05:38 -07001613 getModule()->functionList.push_back(function);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001614
1615 return ParseSuccess;
1616}
1617
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001618/// For statement.
1619///
Chris Lattner48af7d12018-07-09 19:05:38 -07001620/// ml-for-stmt ::= `for` ssa-id `=` lower-bound `to` upper-bound
1621/// (`step` integer-literal)? `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001622///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001623ParseResult MLFunctionParser::parseForStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001624 consumeToken(Token::kw_for);
1625
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001626 // Parse induction variable
1627 if (getToken().isNot(Token::percent_identifier))
1628 return emitError("expected SSA identifier for the loop variable");
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001629
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001630 // TODO: create SSA value definition from name
1631 StringRef name = getTokenSpelling().drop_front();
1632 (void)name;
1633
1634 consumeToken(Token::percent_identifier);
1635
1636 if (!consumeIf(Token::equal))
1637 return emitError("expected =");
1638
1639 // Parse loop bounds
1640 AffineConstantExpr *lowerBound = parseIntConstant();
1641 if (!lowerBound)
1642 return ParseFailure;
1643
1644 if (!consumeIf(Token::kw_to))
1645 return emitError("expected 'to' between bounds");
1646
1647 AffineConstantExpr *upperBound = parseIntConstant();
1648 if (!upperBound)
1649 return ParseFailure;
1650
1651 // Parse step
1652 AffineConstantExpr *step = nullptr;
1653 if (consumeIf(Token::kw_step)) {
1654 step = parseIntConstant();
1655 if (!step)
1656 return ParseFailure;
1657 }
1658
1659 // Create for statement.
1660 ForStmt *stmt = builder.createFor(lowerBound, upperBound, step);
1661
1662 // If parsing of the for statement body fails,
1663 // MLIR contains for statement with those nested statements that have been
1664 // successfully parsed.
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001665 if (parseStmtBlock(static_cast<StmtBlock *>(stmt)))
1666 return ParseFailure;
1667
1668 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001669}
1670
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001671// This method is temporary workaround to parse simple loop bounds and
1672// step.
1673// TODO: remove this method once it's no longer used.
1674AffineConstantExpr *MLFunctionParser::parseIntConstant() {
1675 if (getToken().isNot(Token::integer))
1676 return (emitError("expected non-negative integer for now"), nullptr);
1677
1678 auto val = getToken().getUInt64IntegerValue();
1679 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
1680 return (emitError("constant too large for affineint"), nullptr);
1681 }
1682 consumeToken(Token::integer);
1683 return builder.getConstantExpr((int64_t)val.getValue());
1684}
1685
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001686/// If statement.
1687///
Chris Lattner48af7d12018-07-09 19:05:38 -07001688/// ml-if-head ::= `if` ml-if-cond `{` ml-stmt* `}`
1689/// | ml-if-head `else` `if` ml-if-cond `{` ml-stmt* `}`
1690/// ml-if-stmt ::= ml-if-head
1691/// | ml-if-head `else` `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001692///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001693ParseResult MLFunctionParser::parseIfStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001694 consumeToken(Token::kw_if);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001695 if (!consumeIf(Token::l_paren))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001696 return emitError("expected (");
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001697
1698 //TODO: parse condition
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001699
1700 if (!consumeIf(Token::r_paren))
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001701 return emitError("expected ')'");
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001702
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001703 IfStmt *ifStmt = builder.createIf();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001704 IfClause *thenClause = ifStmt->getThenClause();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001705
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001706 // When parsing of an if statement body fails, the IR contains
1707 // the if statement with the portion of the body that has been
1708 // successfully parsed.
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001709 if (parseStmtBlock(thenClause))
1710 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001711
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001712 if (consumeIf(Token::kw_else)) {
1713 IfClause *elseClause = ifStmt->createElseClause();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001714 if (parseElseClause(elseClause))
1715 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001716 }
1717
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001718 return ParseSuccess;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001719}
1720
1721ParseResult MLFunctionParser::parseElseClause(IfClause *elseClause) {
1722 if (getToken().is(Token::kw_if)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001723 builder.setInsertionPoint(elseClause);
1724 return parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001725 }
1726
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001727 return parseStmtBlock(elseClause);
1728}
1729
1730///
1731/// Parse a list of statements ending with `return` or `}`
1732///
1733ParseResult MLFunctionParser::parseStatements(StmtBlock *block) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001734 auto createOpFunc = [&](Identifier name, ArrayRef<SSAValue *> operands,
1735 ArrayRef<Type *> resultTypes,
1736 ArrayRef<NamedAttribute> attrs) -> Operation * {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001737 return builder.createOperation(name, attrs);
1738 };
1739
1740 builder.setInsertionPoint(block);
1741
1742 while (getToken().isNot(Token::kw_return, Token::r_brace)) {
1743 switch (getToken().getKind()) {
1744 default:
1745 if (parseOperation(createOpFunc))
1746 return ParseFailure;
1747 break;
1748 case Token::kw_for:
1749 if (parseForStmt())
1750 return ParseFailure;
1751 break;
1752 case Token::kw_if:
1753 if (parseIfStmt())
1754 return ParseFailure;
1755 break;
1756 } // end switch
1757 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001758
1759 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001760}
1761
1762///
1763/// Parse `{` ml-stmt* `}`
1764///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001765ParseResult MLFunctionParser::parseStmtBlock(StmtBlock *block) {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001766 if (!consumeIf(Token::l_brace))
1767 return emitError("expected '{' before statement list");
1768
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001769 if (parseStatements(block))
1770 return ParseFailure;
1771
1772 if (!consumeIf(Token::r_brace))
1773 return emitError("expected '}' at the end of the statement block");
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001774
1775 return ParseSuccess;
1776}
1777
Chris Lattner4c95a502018-06-23 16:03:42 -07001778//===----------------------------------------------------------------------===//
1779// Top-level entity parsing.
1780//===----------------------------------------------------------------------===//
1781
Chris Lattner2e595eb2018-07-10 10:08:27 -07001782namespace {
1783/// This parser handles entities that are only valid at the top level of the
1784/// file.
1785class ModuleParser : public Parser {
1786public:
1787 explicit ModuleParser(ParserState &state) : Parser(state) {}
1788
1789 ParseResult parseModule();
1790
1791private:
1792 ParseResult parseAffineMapDef();
1793
1794 // Functions.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001795 ParseResult parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
1796 SmallVectorImpl<StringRef> &argNames);
1797 ParseResult parseFunctionSignature(StringRef &name, FunctionType *&type,
1798 SmallVectorImpl<StringRef> *argNames);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001799 ParseResult parseExtFunc();
1800 ParseResult parseCFGFunc();
1801 ParseResult parseMLFunc();
1802};
1803} // end anonymous namespace
1804
1805/// Affine map declaration.
1806///
1807/// affine-map-def ::= affine-map-id `=` affine-map-inline
1808///
1809ParseResult ModuleParser::parseAffineMapDef() {
1810 assert(getToken().is(Token::hash_identifier));
1811
1812 StringRef affineMapId = getTokenSpelling().drop_front();
1813
1814 // Check for redefinitions.
1815 auto *&entry = getState().affineMapDefinitions[affineMapId];
1816 if (entry)
1817 return emitError("redefinition of affine map id '" + affineMapId + "'");
1818
1819 consumeToken(Token::hash_identifier);
1820
1821 // Parse the '='
1822 if (!consumeIf(Token::equal))
1823 return emitError("expected '=' in affine map outlined definition");
1824
1825 entry = parseAffineMapInline();
1826 if (!entry)
1827 return ParseFailure;
1828
Chris Lattner2e595eb2018-07-10 10:08:27 -07001829 return ParseSuccess;
1830}
1831
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001832/// Parse a (possibly empty) list of MLFunction arguments with types.
1833///
1834/// ml-argument ::= ssa-id `:` type
1835/// ml-argument-list ::= ml-argument (`,` ml-argument)* | /*empty*/
1836///
1837ParseResult
1838ModuleParser::parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
1839 SmallVectorImpl<StringRef> &argNames) {
1840 auto parseElt = [&]() -> ParseResult {
1841 // Parse argument name
1842 if (getToken().isNot(Token::percent_identifier))
1843 return emitError("expected SSA identifier");
1844
1845 StringRef name = getTokenSpelling().drop_front();
1846 consumeToken(Token::percent_identifier);
1847 argNames.push_back(name);
1848
1849 if (!consumeIf(Token::colon))
1850 return emitError("expected ':'");
1851
1852 // Parse argument type
1853 auto elt = parseType();
1854 if (!elt)
1855 return ParseFailure;
1856 argTypes.push_back(elt);
1857
1858 return ParseSuccess;
1859 };
1860
1861 if (!consumeIf(Token::l_paren))
1862 llvm_unreachable("expected '('");
1863
1864 return parseCommaSeparatedList(Token::r_paren, parseElt);
1865}
1866
Chris Lattner2e595eb2018-07-10 10:08:27 -07001867/// Parse a function signature, starting with a name and including the parameter
1868/// list.
1869///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001870/// argument-list ::= type (`,` type)* | /*empty*/ | ml-argument-list
Chris Lattner2e595eb2018-07-10 10:08:27 -07001871/// function-signature ::= function-id `(` argument-list `)` (`->` type-list)?
1872///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001873ParseResult
1874ModuleParser::parseFunctionSignature(StringRef &name, FunctionType *&type,
1875 SmallVectorImpl<StringRef> *argNames) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001876 if (getToken().isNot(Token::at_identifier))
1877 return emitError("expected a function identifier like '@foo'");
1878
1879 name = getTokenSpelling().drop_front();
1880 consumeToken(Token::at_identifier);
1881
1882 if (getToken().isNot(Token::l_paren))
1883 return emitError("expected '(' in function signature");
1884
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001885 SmallVector<Type *, 4> argTypes;
1886 ParseResult parseResult;
1887
1888 if (argNames)
1889 parseResult = parseMLArgumentList(argTypes, *argNames);
1890 else
1891 parseResult = parseTypeList(argTypes);
1892
1893 if (parseResult)
Chris Lattner2e595eb2018-07-10 10:08:27 -07001894 return ParseFailure;
1895
1896 // Parse the return type if present.
1897 SmallVector<Type *, 4> results;
1898 if (consumeIf(Token::arrow)) {
1899 if (parseTypeList(results))
1900 return ParseFailure;
1901 }
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001902 type = builder.getFunctionType(argTypes, results);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001903 return ParseSuccess;
1904}
1905
1906/// External function declarations.
1907///
1908/// ext-func ::= `extfunc` function-signature
1909///
1910ParseResult ModuleParser::parseExtFunc() {
1911 consumeToken(Token::kw_extfunc);
1912
1913 StringRef name;
1914 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001915 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07001916 return ParseFailure;
1917
1918 // Okay, the external function definition was parsed correctly.
1919 getModule()->functionList.push_back(new ExtFunction(name, type));
1920 return ParseSuccess;
1921}
1922
1923/// CFG function declarations.
1924///
1925/// cfg-func ::= `cfgfunc` function-signature `{` basic-block+ `}`
1926///
1927ParseResult ModuleParser::parseCFGFunc() {
1928 consumeToken(Token::kw_cfgfunc);
1929
1930 StringRef name;
1931 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001932 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07001933 return ParseFailure;
1934
1935 // Okay, the CFG function signature was parsed correctly, create the function.
1936 auto function = new CFGFunction(name, type);
1937
1938 return CFGFunctionParser(getState(), function).parseFunctionBody();
1939}
1940
1941/// ML function declarations.
1942///
1943/// ml-func ::= `mlfunc` ml-func-signature `{` ml-stmt* ml-return-stmt `}`
1944///
1945ParseResult ModuleParser::parseMLFunc() {
1946 consumeToken(Token::kw_mlfunc);
1947
1948 StringRef name;
1949 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001950 SmallVector<StringRef, 4> argNames;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001951 // FIXME: Parse ML function signature (args + types)
1952 // by passing pointer to SmallVector<identifier> into parseFunctionSignature
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001953
1954 if (parseFunctionSignature(name, type, &argNames))
Chris Lattner2e595eb2018-07-10 10:08:27 -07001955 return ParseFailure;
1956
1957 // Okay, the ML function signature was parsed correctly, create the function.
1958 auto function = new MLFunction(name, type);
1959
1960 return MLFunctionParser(getState(), function).parseFunctionBody();
1961}
1962
Chris Lattnere79379a2018-06-22 10:39:19 -07001963/// This is the top-level module parser.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001964ParseResult ModuleParser::parseModule() {
Chris Lattnere79379a2018-06-22 10:39:19 -07001965 while (1) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001966 switch (getToken().getKind()) {
Chris Lattnere79379a2018-06-22 10:39:19 -07001967 default:
1968 emitError("expected a top level entity");
Chris Lattner2e595eb2018-07-10 10:08:27 -07001969 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07001970
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001971 // If we got to the end of the file, then we're done.
Chris Lattnere79379a2018-06-22 10:39:19 -07001972 case Token::eof:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001973 return ParseSuccess;
Chris Lattnere79379a2018-06-22 10:39:19 -07001974
1975 // If we got an error token, then the lexer already emitted an error, just
1976 // stop. Someday we could introduce error recovery if there was demand for
1977 // it.
1978 case Token::error:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001979 return ParseFailure;
1980
1981 case Token::hash_identifier:
1982 if (parseAffineMapDef())
1983 return ParseFailure;
1984 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07001985
1986 case Token::kw_extfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001987 if (parseExtFunc())
1988 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07001989 break;
1990
Chris Lattner4c95a502018-06-23 16:03:42 -07001991 case Token::kw_cfgfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001992 if (parseCFGFunc())
1993 return ParseFailure;
MLIR Teamf85a6262018-06-27 11:03:08 -07001994 break;
Chris Lattner4c95a502018-06-23 16:03:42 -07001995
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001996 case Token::kw_mlfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001997 if (parseMLFunc())
1998 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001999 break;
2000
Uday Bondhugula015cbb12018-07-03 20:16:08 -07002001 // TODO: affine entity declarations, etc.
Chris Lattnere79379a2018-06-22 10:39:19 -07002002 }
2003 }
2004}
2005
2006//===----------------------------------------------------------------------===//
2007
Jacques Pienaar7b829702018-07-03 13:24:09 -07002008void mlir::defaultErrorReporter(const llvm::SMDiagnostic &error) {
2009 const auto &sourceMgr = *error.getSourceMgr();
2010 sourceMgr.PrintMessage(error.getLoc(), error.getKind(), error.getMessage());
2011}
2012
Chris Lattnere79379a2018-06-22 10:39:19 -07002013/// This parses the file specified by the indicated SourceMgr and returns an
2014/// MLIR module if it was valid. If not, it emits diagnostics and returns null.
Jacques Pienaar9c411be2018-06-24 19:17:35 -07002015Module *mlir::parseSourceFile(llvm::SourceMgr &sourceMgr, MLIRContext *context,
Jacques Pienaar7b829702018-07-03 13:24:09 -07002016 SMDiagnosticHandlerTy errorReporter) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002017 // This is the result module we are parsing into.
2018 std::unique_ptr<Module> module(new Module(context));
2019
2020 ParserState state(sourceMgr, module.get(),
Jacques Pienaar0bffd862018-07-11 13:26:23 -07002021 errorReporter ? errorReporter : defaultErrorReporter);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002022 if (ModuleParser(state).parseModule())
2023 return nullptr;
Chris Lattner21e67f62018-07-06 10:46:19 -07002024
2025 // Make sure the parse module has no other structural problems detected by the
2026 // verifier.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002027 module->verify();
2028 return module.release();
Chris Lattnere79379a2018-06-22 10:39:19 -07002029}