blob: d220787d616ddf123f2d814d8ae143c54e07c3c6 [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 Lattner3b2ef762018-07-18 15:31:25 -070087typedef std::function<Operation *(Identifier, ArrayRef<Type *>,
88 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 Lattner78276e32018-07-07 15:48:26 -0700168 // SSA
169 ParseResult parseSSAUse();
170 ParseResult parseOptionalSSAUseList(Token::Kind endToken);
171 ParseResult parseSSAUseAndType();
172 ParseResult parseOptionalSSAUseAndTypeList(Token::Kind endToken);
173
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700174 // Operations
175 ParseResult parseOperation(const CreateOperationFunction &createOpFunc);
176
Chris Lattner48af7d12018-07-09 19:05:38 -0700177private:
178 // The Parser is subclassed and reinstantiated. Do not add additional
179 // non-trivial state here, add it to the ParserState class.
180 ParserState &state;
Chris Lattnere79379a2018-06-22 10:39:19 -0700181};
182} // end anonymous namespace
183
184//===----------------------------------------------------------------------===//
185// Helper methods.
186//===----------------------------------------------------------------------===//
187
Chris Lattner4c95a502018-06-23 16:03:42 -0700188ParseResult Parser::emitError(SMLoc loc, const Twine &message) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700189 // If we hit a parse error in response to a lexer error, then the lexer
Jacques Pienaar9c411be2018-06-24 19:17:35 -0700190 // already reported the error.
Chris Lattner48af7d12018-07-09 19:05:38 -0700191 if (getToken().is(Token::error))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700192 return ParseFailure;
193
Chris Lattner48af7d12018-07-09 19:05:38 -0700194 auto &sourceMgr = state.lex.getSourceMgr();
195 state.errorReporter(sourceMgr.GetMessage(loc, SourceMgr::DK_Error, message));
Chris Lattnere79379a2018-06-22 10:39:19 -0700196 return ParseFailure;
197}
198
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700199/// Parse a comma-separated list of elements, terminated with an arbitrary
200/// token. This allows empty lists if allowEmptyList is true.
201///
202/// abstract-list ::= rightToken // if allowEmptyList == true
203/// abstract-list ::= element (',' element)* rightToken
204///
205ParseResult Parser::
Chris Lattner8da0c282018-06-29 11:15:56 -0700206parseCommaSeparatedList(Token::Kind rightToken,
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700207 const std::function<ParseResult()> &parseElement,
208 bool allowEmptyList) {
209 // Handle the empty case.
Chris Lattner48af7d12018-07-09 19:05:38 -0700210 if (getToken().is(rightToken)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700211 if (!allowEmptyList)
212 return emitError("expected list element");
213 consumeToken(rightToken);
214 return ParseSuccess;
215 }
216
217 // Non-empty case starts with an element.
218 if (parseElement())
219 return ParseFailure;
220
221 // Otherwise we have a list of comma separated elements.
222 while (consumeIf(Token::comma)) {
223 if (parseElement())
224 return ParseFailure;
225 }
226
227 // Consume the end character.
228 if (!consumeIf(rightToken))
Chris Lattner8da0c282018-06-29 11:15:56 -0700229 return emitError("expected ',' or '" + Token::getTokenSpelling(rightToken) +
230 "'");
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700231
232 return ParseSuccess;
233}
Chris Lattnere79379a2018-06-22 10:39:19 -0700234
235//===----------------------------------------------------------------------===//
236// Type Parsing
237//===----------------------------------------------------------------------===//
238
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700239/// Parse the low-level fixed dtypes in the system.
240///
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700241/// primitive-type ::= `f16` | `bf16` | `f32` | `f64`
242/// primitive-type ::= integer-type
243/// primitive-type ::= `affineint`
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700244///
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700245Type *Parser::parsePrimitiveType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700246 switch (getToken().getKind()) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700247 default:
248 return (emitError("expected type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700249 case Token::kw_bf16:
250 consumeToken(Token::kw_bf16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700251 return builder.getBF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700252 case Token::kw_f16:
253 consumeToken(Token::kw_f16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700254 return builder.getF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700255 case Token::kw_f32:
256 consumeToken(Token::kw_f32);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700257 return builder.getF32Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700258 case Token::kw_f64:
259 consumeToken(Token::kw_f64);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700260 return builder.getF64Type();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700261 case Token::kw_affineint:
262 consumeToken(Token::kw_affineint);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700263 return builder.getAffineIntType();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700264 case Token::inttype: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700265 auto width = getToken().getIntTypeBitwidth();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700266 if (!width.hasValue())
267 return (emitError("invalid integer width"), nullptr);
268 consumeToken(Token::inttype);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700269 return builder.getIntegerType(width.getValue());
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700270 }
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700271 }
272}
273
274/// Parse the element type of a tensor or memref type.
275///
276/// element-type ::= primitive-type | vector-type
277///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700278Type *Parser::parseElementType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700279 if (getToken().is(Token::kw_vector))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700280 return parseVectorType();
281
282 return parsePrimitiveType();
283}
284
285/// Parse a vector type.
286///
287/// vector-type ::= `vector` `<` const-dimension-list primitive-type `>`
288/// const-dimension-list ::= (integer-literal `x`)+
289///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700290VectorType *Parser::parseVectorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700291 consumeToken(Token::kw_vector);
292
293 if (!consumeIf(Token::less))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700294 return (emitError("expected '<' in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700295
Chris Lattner48af7d12018-07-09 19:05:38 -0700296 if (getToken().isNot(Token::integer))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700297 return (emitError("expected dimension size in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700298
299 SmallVector<unsigned, 4> dimensions;
Chris Lattner48af7d12018-07-09 19:05:38 -0700300 while (getToken().is(Token::integer)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700301 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700302 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700303 if (!dimension.hasValue())
Chris Lattnerf7e22732018-06-22 22:03:48 -0700304 return (emitError("invalid dimension in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700305 dimensions.push_back(dimension.getValue());
306
307 consumeToken(Token::integer);
308
309 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700310 if (getToken().isNot(Token::bare_identifier) ||
311 getTokenSpelling()[0] != 'x')
Chris Lattnerf7e22732018-06-22 22:03:48 -0700312 return (emitError("expected 'x' in vector dimension list"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700313
314 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700315 if (getTokenSpelling().size() != 1)
316 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700317
318 // Consume the 'x'.
319 consumeToken(Token::bare_identifier);
320 }
321
322 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700323 auto *elementType = parsePrimitiveType();
324 if (!elementType)
325 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700326
327 if (!consumeIf(Token::greater))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700328 return (emitError("expected '>' in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700329
Chris Lattnerf7e22732018-06-22 22:03:48 -0700330 return VectorType::get(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700331}
332
333/// Parse a dimension list of a tensor or memref type. This populates the
334/// dimension list, returning -1 for the '?' dimensions.
335///
336/// dimension-list-ranked ::= (dimension `x`)*
337/// dimension ::= `?` | integer-literal
338///
339ParseResult Parser::parseDimensionListRanked(SmallVectorImpl<int> &dimensions) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700340 while (getToken().isAny(Token::integer, Token::question)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700341 if (consumeIf(Token::question)) {
342 dimensions.push_back(-1);
343 } else {
344 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700345 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700346 if (!dimension.hasValue() || (int)dimension.getValue() < 0)
347 return emitError("invalid dimension");
348 dimensions.push_back((int)dimension.getValue());
349 consumeToken(Token::integer);
350 }
351
352 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700353 if (getToken().isNot(Token::bare_identifier) ||
354 getTokenSpelling()[0] != 'x')
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700355 return emitError("expected 'x' in dimension list");
356
357 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700358 if (getTokenSpelling().size() != 1)
359 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700360
361 // Consume the 'x'.
362 consumeToken(Token::bare_identifier);
363 }
364
365 return ParseSuccess;
366}
367
368/// Parse a tensor type.
369///
370/// tensor-type ::= `tensor` `<` dimension-list element-type `>`
371/// dimension-list ::= dimension-list-ranked | `??`
372///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700373Type *Parser::parseTensorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700374 consumeToken(Token::kw_tensor);
375
376 if (!consumeIf(Token::less))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700377 return (emitError("expected '<' in tensor type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700378
379 bool isUnranked;
380 SmallVector<int, 4> dimensions;
381
382 if (consumeIf(Token::questionquestion)) {
383 isUnranked = true;
384 } else {
385 isUnranked = false;
386 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700387 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700388 }
389
390 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700391 auto elementType = parseElementType();
392 if (!elementType)
393 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700394
395 if (!consumeIf(Token::greater))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700396 return (emitError("expected '>' in tensor type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700397
MLIR Team355ec862018-06-23 18:09:09 -0700398 if (isUnranked)
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700399 return builder.getTensorType(elementType);
400 return builder.getTensorType(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700401}
402
403/// Parse a memref type.
404///
405/// memref-type ::= `memref` `<` dimension-list-ranked element-type
406/// (`,` semi-affine-map-composition)? (`,` memory-space)? `>`
407///
408/// semi-affine-map-composition ::= (semi-affine-map `,` )* semi-affine-map
409/// memory-space ::= integer-literal /* | TODO: address-space-id */
410///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700411Type *Parser::parseMemRefType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700412 consumeToken(Token::kw_memref);
413
414 if (!consumeIf(Token::less))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700415 return (emitError("expected '<' in memref type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700416
417 SmallVector<int, 4> dimensions;
418 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700419 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700420
421 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700422 auto elementType = parseElementType();
423 if (!elementType)
424 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700425
MLIR Team718c82f2018-07-16 09:45:22 -0700426 if (!consumeIf(Token::comma))
427 return (emitError("expected ',' in memref type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700428
MLIR Team718c82f2018-07-16 09:45:22 -0700429 // Parse semi-affine-map-composition.
430 SmallVector<AffineMap*, 2> affineMapComposition;
431 unsigned memorySpace;
432 bool parsedMemorySpace = false;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700433
MLIR Team718c82f2018-07-16 09:45:22 -0700434 auto parseElt = [&]() -> ParseResult {
435 if (getToken().is(Token::integer)) {
436 // Parse memory space.
437 if (parsedMemorySpace)
438 return emitError("multiple memory spaces specified in memref type");
439 auto v = getToken().getUnsignedIntegerValue();
440 if (!v.hasValue())
441 return emitError("invalid memory space in memref type");
442 memorySpace = v.getValue();
443 consumeToken(Token::integer);
444 parsedMemorySpace = true;
445 } else {
446 // Parse affine map.
447 if (parsedMemorySpace)
448 return emitError("affine map after memory space in memref type");
449 auto* affineMap = parseAffineMapReference();
450 if (affineMap == nullptr)
451 return ParseFailure;
452 affineMapComposition.push_back(affineMap);
453 }
454 return ParseSuccess;
455 };
456
457 // Parse comma separated list of affine maps, followed by memory space.
458 if (parseCommaSeparatedList(Token::greater, parseElt,
459 /*allowEmptyList=*/false)) {
460 return nullptr;
461 }
462 // Check that MemRef type specifies at least one affine map in composition.
463 if (affineMapComposition.empty())
464 return (emitError("expected semi-affine-map in memref type"), nullptr);
465 if (!parsedMemorySpace)
466 return (emitError("expected memory space in memref type"), nullptr);
467
468 return MemRefType::get(dimensions, elementType, affineMapComposition,
469 memorySpace);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700470}
471
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700472/// Parse a function type.
473///
474/// function-type ::= type-list-parens `->` type-list
475///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700476Type *Parser::parseFunctionType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700477 assert(getToken().is(Token::l_paren));
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700478
Chris Lattnerf7e22732018-06-22 22:03:48 -0700479 SmallVector<Type*, 4> arguments;
480 if (parseTypeList(arguments))
481 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700482
483 if (!consumeIf(Token::arrow))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700484 return (emitError("expected '->' in function type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700485
Chris Lattnerf7e22732018-06-22 22:03:48 -0700486 SmallVector<Type*, 4> results;
487 if (parseTypeList(results))
488 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700489
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700490 return builder.getFunctionType(arguments, results);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700491}
492
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700493/// Parse an arbitrary type.
494///
495/// type ::= primitive-type
496/// | vector-type
497/// | tensor-type
498/// | memref-type
499/// | function-type
500/// element-type ::= primitive-type | vector-type
501///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700502Type *Parser::parseType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700503 switch (getToken().getKind()) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700504 case Token::kw_memref: return parseMemRefType();
505 case Token::kw_tensor: return parseTensorType();
506 case Token::kw_vector: return parseVectorType();
507 case Token::l_paren: return parseFunctionType();
508 default:
509 return parsePrimitiveType();
510 }
511}
512
513/// Parse a "type list", which is a singular type, or a parenthesized list of
514/// types.
515///
516/// type-list ::= type-list-parens | type
517/// type-list-parens ::= `(` `)`
518/// | `(` type (`,` type)* `)`
519///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700520ParseResult Parser::parseTypeList(SmallVectorImpl<Type*> &elements) {
521 auto parseElt = [&]() -> ParseResult {
522 auto elt = parseType();
523 elements.push_back(elt);
524 return elt ? ParseSuccess : ParseFailure;
525 };
526
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700527 // If there is no parens, then it must be a singular type.
528 if (!consumeIf(Token::l_paren))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700529 return parseElt();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700530
Chris Lattnerf7e22732018-06-22 22:03:48 -0700531 if (parseCommaSeparatedList(Token::r_paren, parseElt))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700532 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700533
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700534 return ParseSuccess;
535}
536
Chris Lattner4c95a502018-06-23 16:03:42 -0700537//===----------------------------------------------------------------------===//
Chris Lattner7121b802018-07-04 20:45:39 -0700538// Attribute parsing.
539//===----------------------------------------------------------------------===//
540
541
542/// Attribute parsing.
543///
544/// attribute-value ::= bool-literal
545/// | integer-literal
546/// | float-literal
547/// | string-literal
548/// | `[` (attribute-value (`,` attribute-value)*)? `]`
549///
550Attribute *Parser::parseAttribute() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700551 switch (getToken().getKind()) {
Chris Lattner7121b802018-07-04 20:45:39 -0700552 case Token::kw_true:
553 consumeToken(Token::kw_true);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700554 return builder.getBoolAttr(true);
Chris Lattner7121b802018-07-04 20:45:39 -0700555 case Token::kw_false:
556 consumeToken(Token::kw_false);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700557 return builder.getBoolAttr(false);
Chris Lattner7121b802018-07-04 20:45:39 -0700558
559 case Token::integer: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700560 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700561 if (!val.hasValue() || (int64_t)val.getValue() < 0)
562 return (emitError("integer too large for attribute"), nullptr);
563 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700564 return builder.getIntegerAttr((int64_t)val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700565 }
566
567 case Token::minus: {
568 consumeToken(Token::minus);
Chris Lattner48af7d12018-07-09 19:05:38 -0700569 if (getToken().is(Token::integer)) {
570 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700571 if (!val.hasValue() || (int64_t)-val.getValue() >= 0)
572 return (emitError("integer too large for attribute"), nullptr);
573 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700574 return builder.getIntegerAttr((int64_t)-val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700575 }
576
577 return (emitError("expected constant integer or floating point value"),
578 nullptr);
579 }
580
581 case Token::string: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700582 auto val = getToken().getStringValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700583 consumeToken(Token::string);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700584 return builder.getStringAttr(val);
Chris Lattner7121b802018-07-04 20:45:39 -0700585 }
586
587 case Token::l_bracket: {
588 consumeToken(Token::l_bracket);
589 SmallVector<Attribute*, 4> elements;
590
591 auto parseElt = [&]() -> ParseResult {
592 elements.push_back(parseAttribute());
593 return elements.back() ? ParseSuccess : ParseFailure;
594 };
595
596 if (parseCommaSeparatedList(Token::r_bracket, parseElt))
597 return nullptr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700598 return builder.getArrayAttr(elements);
Chris Lattner7121b802018-07-04 20:45:39 -0700599 }
600 default:
MLIR Teamb61885d2018-07-18 16:29:21 -0700601 // Try to parse affine map reference.
602 auto* affineMap = parseAffineMapReference();
603 if (affineMap != nullptr)
604 return builder.getAffineMapAttr(affineMap);
605
Chris Lattner7121b802018-07-04 20:45:39 -0700606 // TODO: Handle floating point.
607 return (emitError("expected constant attribute value"), nullptr);
608 }
609}
610
Chris Lattner7121b802018-07-04 20:45:39 -0700611/// Attribute dictionary.
612///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700613/// attribute-dict ::= `{` `}`
614/// | `{` attribute-entry (`,` attribute-entry)* `}`
615/// attribute-entry ::= bare-id `:` attribute-value
Chris Lattner7121b802018-07-04 20:45:39 -0700616///
617ParseResult Parser::parseAttributeDict(
618 SmallVectorImpl<NamedAttribute> &attributes) {
619 consumeToken(Token::l_brace);
620
621 auto parseElt = [&]() -> ParseResult {
622 // We allow keywords as attribute names.
Chris Lattner48af7d12018-07-09 19:05:38 -0700623 if (getToken().isNot(Token::bare_identifier, Token::inttype) &&
624 !getToken().isKeyword())
Chris Lattner7121b802018-07-04 20:45:39 -0700625 return emitError("expected attribute name");
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700626 auto nameId = builder.getIdentifier(getTokenSpelling());
Chris Lattner7121b802018-07-04 20:45:39 -0700627 consumeToken();
628
629 if (!consumeIf(Token::colon))
630 return emitError("expected ':' in attribute list");
631
632 auto attr = parseAttribute();
633 if (!attr) return ParseFailure;
634
635 attributes.push_back({nameId, attr});
636 return ParseSuccess;
637 };
638
639 if (parseCommaSeparatedList(Token::r_brace, parseElt))
640 return ParseFailure;
641
642 return ParseSuccess;
643}
644
645//===----------------------------------------------------------------------===//
MLIR Teamf85a6262018-06-27 11:03:08 -0700646// Polyhedral structures.
647//===----------------------------------------------------------------------===//
648
Chris Lattner2e595eb2018-07-10 10:08:27 -0700649/// Lower precedence ops (all at the same precedence level). LNoOp is false in
650/// the boolean sense.
651enum AffineLowPrecOp {
652 /// Null value.
653 LNoOp,
654 Add,
655 Sub
656};
MLIR Teamf85a6262018-06-27 11:03:08 -0700657
Chris Lattner2e595eb2018-07-10 10:08:27 -0700658/// Higher precedence ops - all at the same precedence level. HNoOp is false in
659/// the boolean sense.
660enum AffineHighPrecOp {
661 /// Null value.
662 HNoOp,
663 Mul,
664 FloorDiv,
665 CeilDiv,
666 Mod
667};
Chris Lattner7121b802018-07-04 20:45:39 -0700668
Chris Lattner2e595eb2018-07-10 10:08:27 -0700669namespace {
670/// This is a specialized parser for AffineMap's, maintaining the state
671/// transient to their bodies.
672class AffineMapParser : public Parser {
673public:
674 explicit AffineMapParser(ParserState &state) : Parser(state) {}
Chris Lattner7121b802018-07-04 20:45:39 -0700675
Chris Lattner2e595eb2018-07-10 10:08:27 -0700676 AffineMap *parseAffineMapInline();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700677
Chris Lattner2e595eb2018-07-10 10:08:27 -0700678private:
679 unsigned getNumDims() const { return dims.size(); }
680 unsigned getNumSymbols() const { return symbols.size(); }
MLIR Teamf85a6262018-06-27 11:03:08 -0700681
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700682 /// Returns true if the only identifiers the parser accepts in affine
683 /// expressions are symbolic identifiers.
684 bool isPureSymbolic() const { return pureSymbolic; }
685 void setSymbolicParsing(bool val) { pureSymbolic = val; }
686
Chris Lattner2e595eb2018-07-10 10:08:27 -0700687 // Binary affine op parsing.
688 AffineLowPrecOp consumeIfLowPrecOp();
689 AffineHighPrecOp consumeIfHighPrecOp();
MLIR Teamf85a6262018-06-27 11:03:08 -0700690
Chris Lattner2e595eb2018-07-10 10:08:27 -0700691 // Identifier lists for polyhedral structures.
692 ParseResult parseDimIdList();
693 ParseResult parseSymbolIdList();
694 ParseResult parseDimOrSymbolId(bool isDim);
695
696 AffineExpr *parseAffineExpr();
697 AffineExpr *parseParentheticalExpr();
698 AffineExpr *parseNegateExpression(AffineExpr *lhs);
699 AffineExpr *parseIntegerExpr();
700 AffineExpr *parseBareIdExpr();
701
702 AffineExpr *getBinaryAffineOpExpr(AffineHighPrecOp op, AffineExpr *lhs,
703 AffineExpr *rhs);
704 AffineExpr *getBinaryAffineOpExpr(AffineLowPrecOp op, AffineExpr *lhs,
705 AffineExpr *rhs);
706 AffineExpr *parseAffineOperandExpr(AffineExpr *lhs);
707 AffineExpr *parseAffineLowPrecOpExpr(AffineExpr *llhs,
708 AffineLowPrecOp llhsOp);
709 AffineExpr *parseAffineHighPrecOpExpr(AffineExpr *llhs,
710 AffineHighPrecOp llhsOp);
711
712private:
713 // TODO(bondhugula): could just use an vector/ArrayRef and scan the numbers.
714 llvm::StringMap<unsigned> dims;
715 llvm::StringMap<unsigned> symbols;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700716 /// True if the parser should allow only symbolic identifiers in affine
717 /// expressions.
718 bool pureSymbolic = false;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700719};
720} // end anonymous namespace
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700721
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700722/// Create an affine binary high precedence op expression (mul's, div's, mod)
Chris Lattner2e595eb2018-07-10 10:08:27 -0700723AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineHighPrecOp op,
724 AffineExpr *lhs,
725 AffineExpr *rhs) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700726 // TODO: make the error location info accurate.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700727 switch (op) {
728 case Mul:
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700729 if (!lhs->isSymbolic() && !rhs->isSymbolic()) {
730 emitError("non-affine expression: at least one of the multiply "
731 "operands has to be either a constant or symbolic");
732 return nullptr;
733 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700734 return builder.getMulExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700735 case FloorDiv:
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700736 if (!rhs->isSymbolic()) {
737 emitError("non-affine expression: right operand of floordiv "
738 "has to be either a constant or symbolic");
739 return nullptr;
740 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700741 return builder.getFloorDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700742 case CeilDiv:
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700743 if (!rhs->isSymbolic()) {
744 emitError("non-affine expression: right operand of ceildiv "
745 "has to be either a constant or symbolic");
746 return nullptr;
747 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700748 return builder.getCeilDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700749 case Mod:
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700750 if (!rhs->isSymbolic()) {
751 emitError("non-affine expression: right operand of mod "
752 "has to be either a constant or symbolic");
753 return nullptr;
754 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700755 return builder.getModExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700756 case HNoOp:
757 llvm_unreachable("can't create affine expression for null high prec op");
758 return nullptr;
759 }
760}
761
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700762/// Create an affine binary low precedence op expression (add, sub).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700763AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineLowPrecOp op,
764 AffineExpr *lhs,
765 AffineExpr *rhs) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700766 switch (op) {
767 case AffineLowPrecOp::Add:
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700768 return builder.getAddExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700769 case AffineLowPrecOp::Sub:
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700770 return builder.getSubExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700771 case AffineLowPrecOp::LNoOp:
772 llvm_unreachable("can't create affine expression for null low prec op");
773 return nullptr;
774 }
775}
776
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700777/// Consume this token if it is a lower precedence affine op (there are only two
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700778/// precedence levels).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700779AffineLowPrecOp AffineMapParser::consumeIfLowPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700780 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700781 case Token::plus:
782 consumeToken(Token::plus);
783 return AffineLowPrecOp::Add;
784 case Token::minus:
785 consumeToken(Token::minus);
786 return AffineLowPrecOp::Sub;
787 default:
788 return AffineLowPrecOp::LNoOp;
789 }
790}
791
792/// Consume this token if it is a higher precedence affine op (there are only
793/// two precedence levels)
Chris Lattner2e595eb2018-07-10 10:08:27 -0700794AffineHighPrecOp AffineMapParser::consumeIfHighPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700795 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700796 case Token::star:
797 consumeToken(Token::star);
798 return Mul;
799 case Token::kw_floordiv:
800 consumeToken(Token::kw_floordiv);
801 return FloorDiv;
802 case Token::kw_ceildiv:
803 consumeToken(Token::kw_ceildiv);
804 return CeilDiv;
805 case Token::kw_mod:
806 consumeToken(Token::kw_mod);
807 return Mod;
808 default:
809 return HNoOp;
810 }
811}
812
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700813/// Parse a high precedence op expression list: mul, div, and mod are high
814/// precedence binary ops, i.e., parse a
815/// expr_1 op_1 expr_2 op_2 ... expr_n
816/// where op_1, op_2 are all a AffineHighPrecOp (mul, div, mod).
817/// All affine binary ops are left associative.
818/// Given llhs, returns (llhs llhsOp lhs) op rhs, or (lhs op rhs) if llhs is
819/// null. If no rhs can be found, returns (llhs llhsOp lhs) or lhs if llhs is
820/// null.
821AffineExpr *
Chris Lattner2e595eb2018-07-10 10:08:27 -0700822AffineMapParser::parseAffineHighPrecOpExpr(AffineExpr *llhs,
823 AffineHighPrecOp llhsOp) {
824 AffineExpr *lhs = parseAffineOperandExpr(llhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700825 if (!lhs)
826 return nullptr;
827
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700828 // Found an LHS. Parse the remaining expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700829 if (AffineHighPrecOp op = consumeIfHighPrecOp()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700830 if (llhs) {
831 AffineExpr *expr = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
832 if (!expr)
833 return nullptr;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700834 return parseAffineHighPrecOpExpr(expr, op);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700835 }
836 // No LLHS, get RHS
Chris Lattner2e595eb2018-07-10 10:08:27 -0700837 return parseAffineHighPrecOpExpr(lhs, op);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700838 }
839
840 // This is the last operand in this expression.
841 if (llhs)
842 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
843
844 // No llhs, 'lhs' itself is the expression.
845 return lhs;
846}
847
848/// Parse an affine expression inside parentheses.
849///
850/// affine-expr ::= `(` affine-expr `)`
Chris Lattner2e595eb2018-07-10 10:08:27 -0700851AffineExpr *AffineMapParser::parseParentheticalExpr() {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700852 if (!consumeIf(Token::l_paren))
853 return (emitError("expected '('"), nullptr);
Chris Lattner48af7d12018-07-09 19:05:38 -0700854 if (getToken().is(Token::r_paren))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700855 return (emitError("no expression inside parentheses"), nullptr);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700856 auto *expr = parseAffineExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700857 if (!expr)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700858 return nullptr;
859 if (!consumeIf(Token::r_paren))
860 return (emitError("expected ')'"), nullptr);
861 return expr;
862}
863
864/// Parse the negation expression.
865///
866/// affine-expr ::= `-` affine-expr
Chris Lattner2e595eb2018-07-10 10:08:27 -0700867AffineExpr *AffineMapParser::parseNegateExpression(AffineExpr *lhs) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700868 if (!consumeIf(Token::minus))
869 return (emitError("expected '-'"), nullptr);
870
Chris Lattner2e595eb2018-07-10 10:08:27 -0700871 AffineExpr *operand = parseAffineOperandExpr(lhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700872 // Since negation has the highest precedence of all ops (including high
873 // precedence ops) but lower than parentheses, we are only going to use
874 // parseAffineOperandExpr instead of parseAffineExpr here.
875 if (!operand)
876 // Extra error message although parseAffineOperandExpr would have
877 // complained. Leads to a better diagnostic.
878 return (emitError("missing operand of negation"), nullptr);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700879 auto *minusOne = builder.getConstantExpr(-1);
880 return builder.getMulExpr(minusOne, operand);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700881}
882
883/// Parse a bare id that may appear in an affine expression.
884///
885/// affine-expr ::= bare-id
Chris Lattner2e595eb2018-07-10 10:08:27 -0700886AffineExpr *AffineMapParser::parseBareIdExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700887 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700888 return (emitError("expected bare identifier"), nullptr);
889
Chris Lattner48af7d12018-07-09 19:05:38 -0700890 StringRef sRef = getTokenSpelling();
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700891 // dims, symbols are all pairwise distinct.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700892 if (dims.count(sRef)) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700893 if (isPureSymbolic())
894 return (emitError("identifier used is not a symbolic identifier"),
895 nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700896 consumeToken(Token::bare_identifier);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700897 return builder.getDimExpr(dims.lookup(sRef));
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700898 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700899
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700900 if (symbols.count(sRef)) {
901 consumeToken(Token::bare_identifier);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700902 return builder.getSymbolExpr(symbols.lookup(sRef));
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700903 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700904
905 return (emitError("use of undeclared identifier"), nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700906}
907
908/// Parse a positive integral constant appearing in an affine expression.
909///
910/// affine-expr ::= integer-literal
Chris Lattner2e595eb2018-07-10 10:08:27 -0700911AffineExpr *AffineMapParser::parseIntegerExpr() {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700912 // No need to handle negative numbers separately here. They are naturally
913 // handled via the unary negation operator, although (FIXME) MININT_64 still
914 // not correctly handled.
Chris Lattner48af7d12018-07-09 19:05:38 -0700915 if (getToken().isNot(Token::integer))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700916 return (emitError("expected integer"), nullptr);
917
Chris Lattner48af7d12018-07-09 19:05:38 -0700918 auto val = getToken().getUInt64IntegerValue();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700919 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
920 return (emitError("constant too large for affineint"), nullptr);
921 }
922 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700923 return builder.getConstantExpr((int64_t)val.getValue());
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700924}
925
926/// Parses an expression that can be a valid operand of an affine expression.
Uday Bondhugula76345202018-07-09 13:47:52 -0700927/// lhs: if non-null, lhs is an affine expression that is the lhs of a binary
928/// operator, the rhs of which is being parsed. This is used to determine
929/// whether an error should be emitted for a missing right operand.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700930// Eg: for an expression without parentheses (like i + j + k + l), each
931// of the four identifiers is an operand. For i + j*k + l, j*k is not an
932// operand expression, it's an op expression and will be parsed via
933// parseAffineHighPrecOpExpression(). However, for i + (j*k) + -l, (j*k) and -l
934// are valid operands that will be parsed by this function.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700935AffineExpr *AffineMapParser::parseAffineOperandExpr(AffineExpr *lhs) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700936 switch (getToken().getKind()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700937 case Token::bare_identifier:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700938 return parseBareIdExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700939 case Token::integer:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700940 return parseIntegerExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700941 case Token::l_paren:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700942 return parseParentheticalExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700943 case Token::minus:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700944 return parseNegateExpression(lhs);
Uday Bondhugula76345202018-07-09 13:47:52 -0700945 case Token::kw_ceildiv:
946 case Token::kw_floordiv:
947 case Token::kw_mod:
948 case Token::plus:
949 case Token::star:
950 if (lhs)
951 emitError("missing right operand of binary operator");
952 else
953 emitError("missing left operand of binary operator");
954 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700955 default:
956 if (lhs)
Uday Bondhugula76345202018-07-09 13:47:52 -0700957 emitError("missing right operand of binary operator");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700958 else
959 emitError("expected affine expression");
960 return nullptr;
961 }
962}
963
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700964/// Parse affine expressions that are bare-id's, integer constants,
965/// parenthetical affine expressions, and affine op expressions that are a
966/// composition of those.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700967///
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700968/// All binary op's associate from left to right.
969///
970/// {add, sub} have lower precedence than {mul, div, and mod}.
971///
Uday Bondhugula76345202018-07-09 13:47:52 -0700972/// Add, sub'are themselves at the same precedence level. Mul, floordiv,
973/// ceildiv, and mod are at the same higher precedence level. Negation has
974/// higher precedence than any binary op.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700975///
976/// llhs: the affine expression appearing on the left of the one being parsed.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700977/// This function will return ((llhs llhsOp lhs) op rhs) if llhs is non null,
978/// and lhs op rhs otherwise; if there is no rhs, llhs llhsOp lhs is returned if
979/// llhs is non-null; otherwise lhs is returned. This is to deal with left
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700980/// associativity.
981///
982/// Eg: when the expression is e1 + e2*e3 + e4, with e1 as llhs, this function
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700983/// will return the affine expr equivalent of (e1 + (e2*e3)) + e4, where (e2*e3)
984/// will be parsed using parseAffineHighPrecOpExpr().
Chris Lattner2e595eb2018-07-10 10:08:27 -0700985AffineExpr *AffineMapParser::parseAffineLowPrecOpExpr(AffineExpr *llhs,
986 AffineLowPrecOp llhsOp) {
Uday Bondhugula76345202018-07-09 13:47:52 -0700987 AffineExpr *lhs;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700988 if (!(lhs = parseAffineOperandExpr(llhs)))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700989 return nullptr;
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700990
991 // Found an LHS. Deal with the ops.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700992 if (AffineLowPrecOp lOp = consumeIfLowPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700993 if (llhs) {
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700994 AffineExpr *sum = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700995 return parseAffineLowPrecOpExpr(sum, lOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700996 }
997 // No LLHS, get RHS and form the expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700998 return parseAffineLowPrecOpExpr(lhs, lOp);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700999 }
Chris Lattner2e595eb2018-07-10 10:08:27 -07001000 if (AffineHighPrecOp hOp = consumeIfHighPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001001 // We have a higher precedence op here. Get the rhs operand for the llhs
1002 // through parseAffineHighPrecOpExpr.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001003 AffineExpr *highRes = parseAffineHighPrecOpExpr(lhs, hOp);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001004 if (!highRes)
1005 return nullptr;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001006
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001007 // If llhs is null, the product forms the first operand of the yet to be
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001008 // found expression. If non-null, the op to associate with llhs is llhsOp.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001009 AffineExpr *expr =
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001010 llhs ? getBinaryAffineOpExpr(llhsOp, llhs, highRes) : highRes;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001011
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001012 // Recurse for subsequent low prec op's after the affine high prec op
1013 // expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001014 if (AffineLowPrecOp nextOp = consumeIfLowPrecOp())
1015 return parseAffineLowPrecOpExpr(expr, nextOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001016 return expr;
1017 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001018 // Last operand in the expression list.
1019 if (llhs)
1020 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
1021 // No llhs, 'lhs' itself is the expression.
1022 return lhs;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001023}
1024
1025/// Parse an affine expression.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001026/// affine-expr ::= `(` affine-expr `)`
1027/// | `-` affine-expr
1028/// | affine-expr `+` affine-expr
1029/// | affine-expr `-` affine-expr
1030/// | affine-expr `*` affine-expr
1031/// | affine-expr `floordiv` affine-expr
1032/// | affine-expr `ceildiv` affine-expr
1033/// | affine-expr `mod` affine-expr
1034/// | bare-id
1035/// | integer-literal
1036///
1037/// Additional conditions are checked depending on the production. For eg., one
1038/// of the operands for `*` has to be either constant/symbolic; the second
1039/// operand for floordiv, ceildiv, and mod has to be a positive integer.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001040AffineExpr *AffineMapParser::parseAffineExpr() {
1041 return parseAffineLowPrecOpExpr(nullptr, AffineLowPrecOp::LNoOp);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001042}
1043
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001044/// Parse a dim or symbol from the lists appearing before the actual expressions
Chris Lattner2e595eb2018-07-10 10:08:27 -07001045/// of the affine map. Update our state to store the dimensional/symbolic
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001046/// identifier. 'dim': whether it's the dim list or symbol list that is being
1047/// parsed.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001048ParseResult AffineMapParser::parseDimOrSymbolId(bool isDim) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001049 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001050 return emitError("expected bare identifier");
Chris Lattner48af7d12018-07-09 19:05:38 -07001051 auto sRef = getTokenSpelling();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001052 consumeToken(Token::bare_identifier);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001053 if (dims.count(sRef))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001054 return emitError("dimensional identifier name reused");
Chris Lattner2e595eb2018-07-10 10:08:27 -07001055 if (symbols.count(sRef))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001056 return emitError("symbolic identifier name reused");
Chris Lattner2e595eb2018-07-10 10:08:27 -07001057 if (isDim)
1058 dims.insert({sRef, dims.size()});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001059 else
Chris Lattner2e595eb2018-07-10 10:08:27 -07001060 symbols.insert({sRef, symbols.size()});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001061 return ParseSuccess;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001062}
1063
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001064/// Parse the list of symbolic identifiers to an affine map.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001065ParseResult AffineMapParser::parseSymbolIdList() {
1066 if (!consumeIf(Token::l_bracket))
1067 return emitError("expected '['");
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001068
Chris Lattner2e595eb2018-07-10 10:08:27 -07001069 auto parseElt = [&]() -> ParseResult { return parseDimOrSymbolId(false); };
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001070 return parseCommaSeparatedList(Token::r_bracket, parseElt);
1071}
1072
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001073/// Parse the list of dimensional identifiers to an affine map.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001074ParseResult AffineMapParser::parseDimIdList() {
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001075 if (!consumeIf(Token::l_paren))
1076 return emitError("expected '(' at start of dimensional identifiers list");
1077
Chris Lattner2e595eb2018-07-10 10:08:27 -07001078 auto parseElt = [&]() -> ParseResult { return parseDimOrSymbolId(true); };
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001079 return parseCommaSeparatedList(Token::r_paren, parseElt);
1080}
1081
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001082/// Parse an affine map definition.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001083///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001084/// affine-map-inline ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
1085/// (`size` `(` dim-size (`,` dim-size)* `)`)?
1086/// dim-size ::= affine-expr | `min` `(` affine-expr ( `,` affine-expr)+ `)`
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001087///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001088/// multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner2e595eb2018-07-10 10:08:27 -07001089AffineMap *AffineMapParser::parseAffineMapInline() {
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001090 // List of dimensional identifiers.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001091 if (parseDimIdList())
Chris Lattner7121b802018-07-04 20:45:39 -07001092 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001093
1094 // Symbols are optional.
Chris Lattner48af7d12018-07-09 19:05:38 -07001095 if (getToken().is(Token::l_bracket)) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001096 if (parseSymbolIdList())
Chris Lattner7121b802018-07-04 20:45:39 -07001097 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001098 }
1099 if (!consumeIf(Token::arrow)) {
Chris Lattner7121b802018-07-04 20:45:39 -07001100 return (emitError("expected '->' or '['"), nullptr);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001101 }
1102 if (!consumeIf(Token::l_paren)) {
1103 emitError("expected '(' at start of affine map range");
Chris Lattner7121b802018-07-04 20:45:39 -07001104 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001105 }
1106
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001107 SmallVector<AffineExpr *, 4> exprs;
1108 auto parseElt = [&]() -> ParseResult {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001109 auto *elt = parseAffineExpr();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001110 ParseResult res = elt ? ParseSuccess : ParseFailure;
1111 exprs.push_back(elt);
1112 return res;
1113 };
1114
1115 // Parse a multi-dimensional affine expression (a comma-separated list of 1-d
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001116 // affine expressions); the list cannot be empty.
1117 // Grammar: multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
1118 if (parseCommaSeparatedList(Token::r_paren, parseElt, false))
Chris Lattner7121b802018-07-04 20:45:39 -07001119 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001120
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001121 // Parse optional range sizes.
Uday Bondhugula1e500b42018-07-12 18:04:04 -07001122 // range-sizes ::= (`size` `(` dim-size (`,` dim-size)* `)`)?
1123 // dim-size ::= affine-expr | `min` `(` affine-expr (`,` affine-expr)+ `)`
1124 // TODO(bondhugula): support for min of several affine expressions.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001125 // TODO: check if sizes are non-negative whenever they are constant.
1126 SmallVector<AffineExpr *, 4> rangeSizes;
1127 if (consumeIf(Token::kw_size)) {
1128 // Location of the l_paren token (if it exists) for error reporting later.
1129 auto loc = getToken().getLoc();
1130 if (!consumeIf(Token::l_paren))
1131 return (emitError("expected '(' at start of affine map range"), nullptr);
1132
1133 auto parseRangeSize = [&]() -> ParseResult {
1134 auto *elt = parseAffineExpr();
1135 ParseResult res = elt ? ParseSuccess : ParseFailure;
1136 rangeSizes.push_back(elt);
1137 return res;
1138 };
1139
1140 setSymbolicParsing(true);
1141 if (parseCommaSeparatedList(Token::r_paren, parseRangeSize, false))
1142 return nullptr;
1143 if (exprs.size() > rangeSizes.size())
1144 return (emitError(loc, "fewer range sizes than range expressions"),
1145 nullptr);
1146 if (exprs.size() < rangeSizes.size())
1147 return (emitError(loc, "more range sizes than range expressions"),
1148 nullptr);
1149 }
1150
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001151 // Parsed a valid affine map.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001152 return builder.getAffineMap(dims.size(), symbols.size(), exprs, rangeSizes);
MLIR Teamf85a6262018-06-27 11:03:08 -07001153}
1154
Chris Lattner2e595eb2018-07-10 10:08:27 -07001155AffineMap *Parser::parseAffineMapInline() {
1156 return AffineMapParser(state).parseAffineMapInline();
1157}
1158
MLIR Team718c82f2018-07-16 09:45:22 -07001159AffineMap *Parser::parseAffineMapReference() {
1160 if (getToken().is(Token::hash_identifier)) {
1161 // Parse affine map identifier and verify that it exists.
1162 StringRef affineMapId = getTokenSpelling().drop_front();
1163 if (getState().affineMapDefinitions.count(affineMapId) == 0)
1164 return (emitError("undefined affine map id '" + affineMapId + "'"),
1165 nullptr);
1166 consumeToken(Token::hash_identifier);
1167 return getState().affineMapDefinitions[affineMapId];
1168 }
1169 // Try to parse inline affine map.
1170 return parseAffineMapInline();
1171}
1172
MLIR Teamf85a6262018-06-27 11:03:08 -07001173//===----------------------------------------------------------------------===//
Chris Lattner78276e32018-07-07 15:48:26 -07001174// SSA
Chris Lattner4c95a502018-06-23 16:03:42 -07001175//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001176
Chris Lattner78276e32018-07-07 15:48:26 -07001177/// Parse a SSA operand for an instruction or statement.
1178///
1179/// ssa-use ::= ssa-id | ssa-constant
1180///
1181ParseResult Parser::parseSSAUse() {
Chris Lattner48af7d12018-07-09 19:05:38 -07001182 if (getToken().is(Token::percent_identifier)) {
1183 StringRef name = getTokenSpelling().drop_front();
Chris Lattner78276e32018-07-07 15:48:26 -07001184 consumeToken(Token::percent_identifier);
1185 // TODO: Return this use.
1186 (void)name;
1187 return ParseSuccess;
1188 }
1189
1190 // TODO: Parse SSA constants.
1191
1192 return emitError("expected SSA operand");
1193}
1194
1195/// Parse a (possibly empty) list of SSA operands.
1196///
1197/// ssa-use-list ::= ssa-use (`,` ssa-use)*
1198/// ssa-use-list-opt ::= ssa-use-list?
1199///
1200ParseResult Parser::parseOptionalSSAUseList(Token::Kind endToken) {
1201 // TODO: Build and return this.
1202 return parseCommaSeparatedList(
1203 endToken, [&]() -> ParseResult { return parseSSAUse(); });
1204}
1205
1206/// Parse an SSA use with an associated type.
1207///
1208/// ssa-use-and-type ::= ssa-use `:` type
1209ParseResult Parser::parseSSAUseAndType() {
1210 if (parseSSAUse())
1211 return ParseFailure;
1212
1213 if (!consumeIf(Token::colon))
1214 return emitError("expected ':' and type for SSA operand");
1215
1216 if (!parseType())
1217 return ParseFailure;
1218
1219 return ParseSuccess;
1220}
1221
1222/// Parse a (possibly empty) list of SSA operands with types.
1223///
1224/// ssa-use-and-type-list ::= ssa-use-and-type (`,` ssa-use-and-type)*
1225///
1226ParseResult Parser::parseOptionalSSAUseAndTypeList(Token::Kind endToken) {
1227 // TODO: Build and return this.
1228 return parseCommaSeparatedList(
1229 endToken, [&]() -> ParseResult { return parseSSAUseAndType(); });
1230}
1231
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001232//===----------------------------------------------------------------------===//
1233// Operations
1234//===----------------------------------------------------------------------===//
1235
1236/// Parse the CFG or MLFunc operation.
1237///
1238/// TODO(clattner): This is a change from the MLIR spec as written, it is an
1239/// experiment that will eliminate "builtin" instructions as a thing.
1240///
1241/// operation ::=
1242/// (ssa-id `=`)? string '(' ssa-use-list? ')' attribute-dict?
1243/// `:` function-type
1244///
1245ParseResult
1246Parser::parseOperation(const CreateOperationFunction &createOpFunc) {
1247 auto loc = getToken().getLoc();
1248
1249 StringRef resultID;
1250 if (getToken().is(Token::percent_identifier)) {
1251 resultID = getTokenSpelling().drop_front();
1252 consumeToken(Token::percent_identifier);
1253 if (!consumeIf(Token::equal))
1254 return emitError("expected '=' after SSA name");
1255 }
1256
1257 if (getToken().isNot(Token::string))
1258 return emitError("expected operation name in quotes");
1259
1260 auto name = getToken().getStringValue();
1261 if (name.empty())
1262 return emitError("empty operation name is invalid");
1263
1264 consumeToken(Token::string);
1265
1266 if (!consumeIf(Token::l_paren))
1267 return emitError("expected '(' to start operand list");
1268
1269 // Parse the operand list.
1270 parseOptionalSSAUseList(Token::r_paren);
1271
1272 SmallVector<NamedAttribute, 4> attributes;
1273 if (getToken().is(Token::l_brace)) {
1274 if (parseAttributeDict(attributes))
1275 return ParseFailure;
1276 }
1277
Chris Lattner3b2ef762018-07-18 15:31:25 -07001278 if (!consumeIf(Token::colon))
1279 return emitError("expected ':' followed by instruction type");
1280
1281 auto typeLoc = getToken().getLoc();
1282 auto type = parseType();
1283 if (!type)
1284 return ParseFailure;
1285 auto fnType = dyn_cast<FunctionType>(type);
1286 if (!fnType)
1287 return emitError(typeLoc, "expected function type");
1288
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001289 // TODO: Don't drop result name and operand names on the floor.
1290 auto nameId = builder.getIdentifier(name);
1291
Chris Lattner3b2ef762018-07-18 15:31:25 -07001292 auto oper = createOpFunc(nameId, fnType->getResults(), attributes);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001293
1294 if (!oper)
1295 return ParseFailure;
1296
1297 // We just parsed an operation. If it is a recognized one, verify that it
1298 // is structurally as we expect. If not, produce an error with a reasonable
1299 // source location.
1300 if (auto *opInfo = oper->getAbstractOperation(builder.getContext())) {
1301 if (auto error = opInfo->verifyInvariants(oper))
1302 return emitError(loc, error);
1303 }
1304
1305 return ParseSuccess;
1306}
Chris Lattnere79379a2018-06-22 10:39:19 -07001307
Chris Lattner48af7d12018-07-09 19:05:38 -07001308//===----------------------------------------------------------------------===//
1309// CFG Functions
1310//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001311
Chris Lattner4c95a502018-06-23 16:03:42 -07001312namespace {
Chris Lattner48af7d12018-07-09 19:05:38 -07001313/// This is a specialized parser for CFGFunction's, maintaining the state
1314/// transient to their bodies.
1315class CFGFunctionParser : public Parser {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001316public:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001317 CFGFunctionParser(ParserState &state, CFGFunction *function)
1318 : Parser(state), function(function), builder(function) {}
1319
1320 ParseResult parseFunctionBody();
1321
1322private:
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001323 CFGFunction *function;
1324 llvm::StringMap<std::pair<BasicBlock*, SMLoc>> blocksByName;
Chris Lattner48af7d12018-07-09 19:05:38 -07001325
1326 /// This builder intentionally shadows the builder in the base class, with a
1327 /// more specific builder type.
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001328 CFGFuncBuilder builder;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001329
Chris Lattner4c95a502018-06-23 16:03:42 -07001330 /// Get the basic block with the specified name, creating it if it doesn't
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001331 /// already exist. The location specified is the point of use, which allows
1332 /// us to diagnose references to blocks that are not defined precisely.
1333 BasicBlock *getBlockNamed(StringRef name, SMLoc loc) {
1334 auto &blockAndLoc = blocksByName[name];
1335 if (!blockAndLoc.first) {
Chris Lattner3a467cc2018-07-01 20:28:00 -07001336 blockAndLoc.first = new BasicBlock();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001337 blockAndLoc.second = loc;
Chris Lattner4c95a502018-06-23 16:03:42 -07001338 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001339 return blockAndLoc.first;
Chris Lattner4c95a502018-06-23 16:03:42 -07001340 }
Chris Lattner48af7d12018-07-09 19:05:38 -07001341
Chris Lattner48af7d12018-07-09 19:05:38 -07001342 ParseResult parseBasicBlock();
1343 OperationInst *parseCFGOperation();
1344 TerminatorInst *parseTerminator();
Chris Lattner4c95a502018-06-23 16:03:42 -07001345};
1346} // end anonymous namespace
1347
Chris Lattner48af7d12018-07-09 19:05:38 -07001348ParseResult CFGFunctionParser::parseFunctionBody() {
1349 if (!consumeIf(Token::l_brace))
1350 return emitError("expected '{' in CFG function");
1351
1352 // Make sure we have at least one block.
1353 if (getToken().is(Token::r_brace))
1354 return emitError("CFG functions must have at least one basic block");
Chris Lattner4c95a502018-06-23 16:03:42 -07001355
1356 // Parse the list of blocks.
1357 while (!consumeIf(Token::r_brace))
Chris Lattner48af7d12018-07-09 19:05:38 -07001358 if (parseBasicBlock())
Chris Lattner4c95a502018-06-23 16:03:42 -07001359 return ParseFailure;
1360
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001361 // Verify that all referenced blocks were defined. Iteration over a
1362 // StringMap isn't determinstic, but this is good enough for our purposes.
Chris Lattner48af7d12018-07-09 19:05:38 -07001363 for (auto &elt : blocksByName) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001364 auto *bb = elt.second.first;
Chris Lattner3a467cc2018-07-01 20:28:00 -07001365 if (!bb->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001366 return emitError(elt.second.second,
1367 "reference to an undefined basic block '" +
1368 elt.first() + "'");
1369 }
1370
Chris Lattner48af7d12018-07-09 19:05:38 -07001371 getModule()->functionList.push_back(function);
Chris Lattner4c95a502018-06-23 16:03:42 -07001372 return ParseSuccess;
1373}
1374
1375/// Basic block declaration.
1376///
1377/// basic-block ::= bb-label instruction* terminator-stmt
1378/// bb-label ::= bb-id bb-arg-list? `:`
1379/// bb-id ::= bare-id
1380/// bb-arg-list ::= `(` ssa-id-and-type-list? `)`
1381///
Chris Lattner48af7d12018-07-09 19:05:38 -07001382ParseResult CFGFunctionParser::parseBasicBlock() {
1383 SMLoc nameLoc = getToken().getLoc();
1384 auto name = getTokenSpelling();
Chris Lattner4c95a502018-06-23 16:03:42 -07001385 if (!consumeIf(Token::bare_identifier))
1386 return emitError("expected basic block name");
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001387
Chris Lattner48af7d12018-07-09 19:05:38 -07001388 auto *block = getBlockNamed(name, nameLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001389
1390 // If this block has already been parsed, then this is a redefinition with the
1391 // same block name.
Chris Lattner3a467cc2018-07-01 20:28:00 -07001392 if (block->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001393 return emitError(nameLoc, "redefinition of block '" + name.str() + "'");
1394
Chris Lattner3a467cc2018-07-01 20:28:00 -07001395 // Add the block to the function.
Chris Lattner48af7d12018-07-09 19:05:38 -07001396 function->push_back(block);
Chris Lattner4c95a502018-06-23 16:03:42 -07001397
Chris Lattner78276e32018-07-07 15:48:26 -07001398 // If an argument list is present, parse it.
1399 if (consumeIf(Token::l_paren)) {
1400 if (parseOptionalSSAUseAndTypeList(Token::r_paren))
1401 return ParseFailure;
1402
1403 // TODO: attach it.
1404 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001405
1406 if (!consumeIf(Token::colon))
1407 return emitError("expected ':' after basic block name");
1408
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001409 // Set the insertion point to the block we want to insert new operations into.
Chris Lattner48af7d12018-07-09 19:05:38 -07001410 builder.setInsertionPoint(block);
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001411
Chris Lattner3b2ef762018-07-18 15:31:25 -07001412 auto createOpFunc = [this](Identifier name, ArrayRef<Type *> resultTypes,
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001413 ArrayRef<NamedAttribute> attrs) -> Operation * {
Chris Lattner3b2ef762018-07-18 15:31:25 -07001414 return builder.createOperation(name, {}, resultTypes, attrs);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001415 };
1416
Chris Lattnered65a732018-06-28 20:45:33 -07001417 // Parse the list of operations that make up the body of the block.
Chris Lattner48af7d12018-07-09 19:05:38 -07001418 while (getToken().isNot(Token::kw_return, Token::kw_br)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001419 if (parseOperation(createOpFunc))
Chris Lattnered65a732018-06-28 20:45:33 -07001420 return ParseFailure;
1421 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001422
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001423 if (!parseTerminator())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001424 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07001425
1426 return ParseSuccess;
1427}
1428
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001429/// Parse the terminator instruction for a basic block.
1430///
1431/// terminator-stmt ::= `br` bb-id branch-use-list?
1432/// branch-use-list ::= `(` ssa-use-and-type-list? `)`
1433/// terminator-stmt ::=
1434/// `cond_br` ssa-use `,` bb-id branch-use-list? `,` bb-id branch-use-list?
1435/// terminator-stmt ::= `return` ssa-use-and-type-list?
1436///
Chris Lattner48af7d12018-07-09 19:05:38 -07001437TerminatorInst *CFGFunctionParser::parseTerminator() {
1438 switch (getToken().getKind()) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001439 default:
Chris Lattner3a467cc2018-07-01 20:28:00 -07001440 return (emitError("expected terminator at end of basic block"), nullptr);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001441
1442 case Token::kw_return:
1443 consumeToken(Token::kw_return);
Chris Lattner48af7d12018-07-09 19:05:38 -07001444 return builder.createReturnInst();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001445
1446 case Token::kw_br: {
1447 consumeToken(Token::kw_br);
Chris Lattner48af7d12018-07-09 19:05:38 -07001448 auto destBB = getBlockNamed(getTokenSpelling(), getToken().getLoc());
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001449 if (!consumeIf(Token::bare_identifier))
Chris Lattner3a467cc2018-07-01 20:28:00 -07001450 return (emitError("expected basic block name"), nullptr);
Chris Lattner48af7d12018-07-09 19:05:38 -07001451 return builder.createBranchInst(destBB);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001452 }
Chris Lattner78276e32018-07-07 15:48:26 -07001453 // TODO: cond_br.
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001454 }
1455}
1456
Chris Lattner48af7d12018-07-09 19:05:38 -07001457//===----------------------------------------------------------------------===//
1458// ML Functions
1459//===----------------------------------------------------------------------===//
1460
1461namespace {
1462/// Refined parser for MLFunction bodies.
1463class MLFunctionParser : public Parser {
1464public:
Chris Lattner48af7d12018-07-09 19:05:38 -07001465 MLFunctionParser(ParserState &state, MLFunction *function)
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001466 : Parser(state), function(function), builder(function) {}
Chris Lattner48af7d12018-07-09 19:05:38 -07001467
1468 ParseResult parseFunctionBody();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001469
1470private:
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001471 MLFunction *function;
1472
1473 /// This builder intentionally shadows the builder in the base class, with a
1474 /// more specific builder type.
1475 MLFuncBuilder builder;
1476
1477 ParseResult parseForStmt();
1478 ParseResult parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001479 ParseResult parseElseClause(IfClause *elseClause);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001480 ParseResult parseStatements(StmtBlock *block);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001481 ParseResult parseStmtBlock(StmtBlock *block);
Chris Lattner48af7d12018-07-09 19:05:38 -07001482};
1483} // end anonymous namespace
1484
Chris Lattner48af7d12018-07-09 19:05:38 -07001485ParseResult MLFunctionParser::parseFunctionBody() {
1486 if (!consumeIf(Token::l_brace))
1487 return emitError("expected '{' in ML function");
1488
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001489 // Parse statements in this function
1490 if (parseStatements(function))
1491 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001492
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001493 if (!consumeIf(Token::kw_return))
1494 emitError("ML function must end with return statement");
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001495 // TODO: parse return statement operands
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001496
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001497 if (!consumeIf(Token::r_brace))
1498 emitError("expected '}' in ML function");
1499
Chris Lattner48af7d12018-07-09 19:05:38 -07001500 getModule()->functionList.push_back(function);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001501
1502 return ParseSuccess;
1503}
1504
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001505/// For statement.
1506///
Chris Lattner48af7d12018-07-09 19:05:38 -07001507/// ml-for-stmt ::= `for` ssa-id `=` lower-bound `to` upper-bound
1508/// (`step` integer-literal)? `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001509///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001510ParseResult MLFunctionParser::parseForStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001511 consumeToken(Token::kw_for);
1512
1513 //TODO: parse loop header
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001514 ForStmt *stmt = builder.createFor();
1515
1516 // If parsing of the for statement body fails
1517 // MLIR contains for statement with successfully parsed nested statements
1518 if (parseStmtBlock(static_cast<StmtBlock *>(stmt)))
1519 return ParseFailure;
1520
1521 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001522}
1523
1524/// If statement.
1525///
Chris Lattner48af7d12018-07-09 19:05:38 -07001526/// ml-if-head ::= `if` ml-if-cond `{` ml-stmt* `}`
1527/// | ml-if-head `else` `if` ml-if-cond `{` ml-stmt* `}`
1528/// ml-if-stmt ::= ml-if-head
1529/// | ml-if-head `else` `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001530///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001531ParseResult MLFunctionParser::parseIfStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001532 consumeToken(Token::kw_if);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001533 if (!consumeIf(Token::l_paren))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001534 return emitError("expected (");
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001535
1536 //TODO: parse condition
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001537
1538 if (!consumeIf(Token::r_paren))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001539 return emitError("expected )");
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001540
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001541 IfStmt *ifStmt = builder.createIf();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001542 IfClause *thenClause = ifStmt->getThenClause();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001543
1544 // If parsing of the then or optional else clause fails MLIR contains
1545 // if statement with successfully parsed nested statements.
1546 if (parseStmtBlock(thenClause))
1547 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001548
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001549 if (consumeIf(Token::kw_else)) {
1550 IfClause *elseClause = ifStmt->createElseClause();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001551 if (parseElseClause(elseClause))
1552 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001553 }
1554
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001555 return ParseSuccess;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001556}
1557
1558ParseResult MLFunctionParser::parseElseClause(IfClause *elseClause) {
1559 if (getToken().is(Token::kw_if)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001560 builder.setInsertionPoint(elseClause);
1561 return parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001562 }
1563
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001564 return parseStmtBlock(elseClause);
1565}
1566
1567///
1568/// Parse a list of statements ending with `return` or `}`
1569///
1570ParseResult MLFunctionParser::parseStatements(StmtBlock *block) {
Chris Lattner3b2ef762018-07-18 15:31:25 -07001571 auto createOpFunc = [this](Identifier name, ArrayRef<Type *> resultTypes,
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001572 ArrayRef<NamedAttribute> attrs) -> Operation * {
1573 return builder.createOperation(name, attrs);
1574 };
1575
1576 builder.setInsertionPoint(block);
1577
1578 while (getToken().isNot(Token::kw_return, Token::r_brace)) {
1579 switch (getToken().getKind()) {
1580 default:
1581 if (parseOperation(createOpFunc))
1582 return ParseFailure;
1583 break;
1584 case Token::kw_for:
1585 if (parseForStmt())
1586 return ParseFailure;
1587 break;
1588 case Token::kw_if:
1589 if (parseIfStmt())
1590 return ParseFailure;
1591 break;
1592 } // end switch
1593 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001594
1595 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001596}
1597
1598///
1599/// Parse `{` ml-stmt* `}`
1600///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001601ParseResult MLFunctionParser::parseStmtBlock(StmtBlock *block) {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001602 if (!consumeIf(Token::l_brace))
1603 return emitError("expected '{' before statement list");
1604
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001605 if (parseStatements(block))
1606 return ParseFailure;
1607
1608 if (!consumeIf(Token::r_brace))
1609 return emitError("expected '}' at the end of the statement block");
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001610
1611 return ParseSuccess;
1612}
1613
Chris Lattner4c95a502018-06-23 16:03:42 -07001614//===----------------------------------------------------------------------===//
1615// Top-level entity parsing.
1616//===----------------------------------------------------------------------===//
1617
Chris Lattner2e595eb2018-07-10 10:08:27 -07001618namespace {
1619/// This parser handles entities that are only valid at the top level of the
1620/// file.
1621class ModuleParser : public Parser {
1622public:
1623 explicit ModuleParser(ParserState &state) : Parser(state) {}
1624
1625 ParseResult parseModule();
1626
1627private:
1628 ParseResult parseAffineMapDef();
1629
1630 // Functions.
1631 ParseResult parseFunctionSignature(StringRef &name, FunctionType *&type);
1632 ParseResult parseExtFunc();
1633 ParseResult parseCFGFunc();
1634 ParseResult parseMLFunc();
1635};
1636} // end anonymous namespace
1637
1638/// Affine map declaration.
1639///
1640/// affine-map-def ::= affine-map-id `=` affine-map-inline
1641///
1642ParseResult ModuleParser::parseAffineMapDef() {
1643 assert(getToken().is(Token::hash_identifier));
1644
1645 StringRef affineMapId = getTokenSpelling().drop_front();
1646
1647 // Check for redefinitions.
1648 auto *&entry = getState().affineMapDefinitions[affineMapId];
1649 if (entry)
1650 return emitError("redefinition of affine map id '" + affineMapId + "'");
1651
1652 consumeToken(Token::hash_identifier);
1653
1654 // Parse the '='
1655 if (!consumeIf(Token::equal))
1656 return emitError("expected '=' in affine map outlined definition");
1657
1658 entry = parseAffineMapInline();
1659 if (!entry)
1660 return ParseFailure;
1661
Chris Lattner2e595eb2018-07-10 10:08:27 -07001662 return ParseSuccess;
1663}
1664
1665/// Parse a function signature, starting with a name and including the parameter
1666/// list.
1667///
1668/// argument-list ::= type (`,` type)* | /*empty*/
1669/// function-signature ::= function-id `(` argument-list `)` (`->` type-list)?
1670///
1671ParseResult ModuleParser::parseFunctionSignature(StringRef &name,
1672 FunctionType *&type) {
1673 if (getToken().isNot(Token::at_identifier))
1674 return emitError("expected a function identifier like '@foo'");
1675
1676 name = getTokenSpelling().drop_front();
1677 consumeToken(Token::at_identifier);
1678
1679 if (getToken().isNot(Token::l_paren))
1680 return emitError("expected '(' in function signature");
1681
1682 SmallVector<Type *, 4> arguments;
1683 if (parseTypeList(arguments))
1684 return ParseFailure;
1685
1686 // Parse the return type if present.
1687 SmallVector<Type *, 4> results;
1688 if (consumeIf(Token::arrow)) {
1689 if (parseTypeList(results))
1690 return ParseFailure;
1691 }
1692 type = builder.getFunctionType(arguments, results);
1693 return ParseSuccess;
1694}
1695
1696/// External function declarations.
1697///
1698/// ext-func ::= `extfunc` function-signature
1699///
1700ParseResult ModuleParser::parseExtFunc() {
1701 consumeToken(Token::kw_extfunc);
1702
1703 StringRef name;
1704 FunctionType *type = nullptr;
1705 if (parseFunctionSignature(name, type))
1706 return ParseFailure;
1707
1708 // Okay, the external function definition was parsed correctly.
1709 getModule()->functionList.push_back(new ExtFunction(name, type));
1710 return ParseSuccess;
1711}
1712
1713/// CFG function declarations.
1714///
1715/// cfg-func ::= `cfgfunc` function-signature `{` basic-block+ `}`
1716///
1717ParseResult ModuleParser::parseCFGFunc() {
1718 consumeToken(Token::kw_cfgfunc);
1719
1720 StringRef name;
1721 FunctionType *type = nullptr;
1722 if (parseFunctionSignature(name, type))
1723 return ParseFailure;
1724
1725 // Okay, the CFG function signature was parsed correctly, create the function.
1726 auto function = new CFGFunction(name, type);
1727
1728 return CFGFunctionParser(getState(), function).parseFunctionBody();
1729}
1730
1731/// ML function declarations.
1732///
1733/// ml-func ::= `mlfunc` ml-func-signature `{` ml-stmt* ml-return-stmt `}`
1734///
1735ParseResult ModuleParser::parseMLFunc() {
1736 consumeToken(Token::kw_mlfunc);
1737
1738 StringRef name;
1739 FunctionType *type = nullptr;
1740
1741 // FIXME: Parse ML function signature (args + types)
1742 // by passing pointer to SmallVector<identifier> into parseFunctionSignature
1743 if (parseFunctionSignature(name, type))
1744 return ParseFailure;
1745
1746 // Okay, the ML function signature was parsed correctly, create the function.
1747 auto function = new MLFunction(name, type);
1748
1749 return MLFunctionParser(getState(), function).parseFunctionBody();
1750}
1751
Chris Lattnere79379a2018-06-22 10:39:19 -07001752/// This is the top-level module parser.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001753ParseResult ModuleParser::parseModule() {
Chris Lattnere79379a2018-06-22 10:39:19 -07001754 while (1) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001755 switch (getToken().getKind()) {
Chris Lattnere79379a2018-06-22 10:39:19 -07001756 default:
1757 emitError("expected a top level entity");
Chris Lattner2e595eb2018-07-10 10:08:27 -07001758 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07001759
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001760 // If we got to the end of the file, then we're done.
Chris Lattnere79379a2018-06-22 10:39:19 -07001761 case Token::eof:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001762 return ParseSuccess;
Chris Lattnere79379a2018-06-22 10:39:19 -07001763
1764 // If we got an error token, then the lexer already emitted an error, just
1765 // stop. Someday we could introduce error recovery if there was demand for
1766 // it.
1767 case Token::error:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001768 return ParseFailure;
1769
1770 case Token::hash_identifier:
1771 if (parseAffineMapDef())
1772 return ParseFailure;
1773 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07001774
1775 case Token::kw_extfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001776 if (parseExtFunc())
1777 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07001778 break;
1779
Chris Lattner4c95a502018-06-23 16:03:42 -07001780 case Token::kw_cfgfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001781 if (parseCFGFunc())
1782 return ParseFailure;
MLIR Teamf85a6262018-06-27 11:03:08 -07001783 break;
Chris Lattner4c95a502018-06-23 16:03:42 -07001784
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001785 case Token::kw_mlfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001786 if (parseMLFunc())
1787 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001788 break;
1789
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001790 // TODO: affine entity declarations, etc.
Chris Lattnere79379a2018-06-22 10:39:19 -07001791 }
1792 }
1793}
1794
1795//===----------------------------------------------------------------------===//
1796
Jacques Pienaar7b829702018-07-03 13:24:09 -07001797void mlir::defaultErrorReporter(const llvm::SMDiagnostic &error) {
1798 const auto &sourceMgr = *error.getSourceMgr();
1799 sourceMgr.PrintMessage(error.getLoc(), error.getKind(), error.getMessage());
1800}
1801
Chris Lattnere79379a2018-06-22 10:39:19 -07001802/// This parses the file specified by the indicated SourceMgr and returns an
1803/// MLIR module if it was valid. If not, it emits diagnostics and returns null.
Jacques Pienaar9c411be2018-06-24 19:17:35 -07001804Module *mlir::parseSourceFile(llvm::SourceMgr &sourceMgr, MLIRContext *context,
Jacques Pienaar7b829702018-07-03 13:24:09 -07001805 SMDiagnosticHandlerTy errorReporter) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001806 // This is the result module we are parsing into.
1807 std::unique_ptr<Module> module(new Module(context));
1808
1809 ParserState state(sourceMgr, module.get(),
Jacques Pienaar0bffd862018-07-11 13:26:23 -07001810 errorReporter ? errorReporter : defaultErrorReporter);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001811 if (ModuleParser(state).parseModule())
1812 return nullptr;
Chris Lattner21e67f62018-07-06 10:46:19 -07001813
1814 // Make sure the parse module has no other structural problems detected by the
1815 // verifier.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001816 module->verify();
1817 return module.release();
Chris Lattnere79379a2018-06-22 10:39:19 -07001818}