blob: bc26bdac87e0d4f4d7c7abb368a3ae1c5b79fcc6 [file] [log] [blame]
Chris Lattnere79379a2018-06-22 10:39:19 -07001//===- Parser.cpp - MLIR Parser Implementation ----------------------------===//
2//
3// Copyright 2019 The MLIR Authors.
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16// =============================================================================
17//
18// This file implements the parser for the MLIR textual form.
19//
20//===----------------------------------------------------------------------===//
21
22#include "mlir/Parser.h"
23#include "Lexer.h"
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -070024#include "mlir/IR/AffineExpr.h"
MLIR Teamf85a6262018-06-27 11:03:08 -070025#include "mlir/IR/AffineMap.h"
Chris Lattner7121b802018-07-04 20:45:39 -070026#include "mlir/IR/Attributes.h"
Chris Lattner158e0a3e2018-07-08 20:51:38 -070027#include "mlir/IR/Builders.h"
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -070028#include "mlir/IR/MLFunction.h"
Chris Lattner21e67f62018-07-06 10:46:19 -070029#include "mlir/IR/Module.h"
30#include "mlir/IR/OperationSet.h"
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -070031#include "mlir/IR/Statements.h"
Chris Lattnerf7e22732018-06-22 22:03:48 -070032#include "mlir/IR/Types.h"
Chris Lattner6119d382018-07-20 18:41:34 -070033#include "llvm/ADT/DenseMap.h"
Chris Lattnere79379a2018-06-22 10:39:19 -070034#include "llvm/Support/SourceMgr.h"
35using namespace mlir;
36using llvm::SourceMgr;
Chris Lattner4c95a502018-06-23 16:03:42 -070037using llvm::SMLoc;
Chris Lattnere79379a2018-06-22 10:39:19 -070038
Chris Lattnerf7e22732018-06-22 22:03:48 -070039/// Simple enum to make code read better in cases that would otherwise return a
40/// bool value. Failure is "true" in a boolean context.
Chris Lattnere79379a2018-06-22 10:39:19 -070041enum ParseResult {
42 ParseSuccess,
43 ParseFailure
44};
45
Chris Lattner48af7d12018-07-09 19:05:38 -070046namespace {
47class Parser;
48
49/// This class refers to all of the state maintained globally by the parser,
50/// such as the current lexer position etc. The Parser base class provides
51/// methods to access this.
52class ParserState {
Chris Lattnered65a732018-06-28 20:45:33 -070053public:
Chris Lattner2e595eb2018-07-10 10:08:27 -070054 ParserState(llvm::SourceMgr &sourceMgr, Module *module,
Chris Lattner48af7d12018-07-09 19:05:38 -070055 SMDiagnosticHandlerTy errorReporter)
Chris Lattner2e595eb2018-07-10 10:08:27 -070056 : context(module->getContext()), module(module),
57 lex(sourceMgr, errorReporter), curToken(lex.lexToken()),
Jacques Pienaard4c784e2018-07-11 00:07:36 -070058 errorReporter(errorReporter) {}
Chris Lattner2e595eb2018-07-10 10:08:27 -070059
60 // A map from affine map identifier to AffineMap.
61 llvm::StringMap<AffineMap *> affineMapDefinitions;
Chris Lattnere79379a2018-06-22 10:39:19 -070062
Chris Lattnere79379a2018-06-22 10:39:19 -070063private:
Chris Lattner48af7d12018-07-09 19:05:38 -070064 ParserState(const ParserState &) = delete;
65 void operator=(const ParserState &) = delete;
66
67 friend class Parser;
68
69 // The context we're parsing into.
Chris Lattner2e595eb2018-07-10 10:08:27 -070070 MLIRContext *const context;
71
72 // This is the module we are parsing into.
73 Module *const module;
Chris Lattnerf7e22732018-06-22 22:03:48 -070074
75 // The lexer for the source file we're parsing.
Chris Lattnere79379a2018-06-22 10:39:19 -070076 Lexer lex;
77
78 // This is the next token that hasn't been consumed yet.
79 Token curToken;
80
Jacques Pienaar9c411be2018-06-24 19:17:35 -070081 // The diagnostic error reporter.
Chris Lattner2e595eb2018-07-10 10:08:27 -070082 SMDiagnosticHandlerTy const errorReporter;
Chris Lattner48af7d12018-07-09 19:05:38 -070083};
84} // end anonymous namespace
MLIR Teamf85a6262018-06-27 11:03:08 -070085
Chris Lattner48af7d12018-07-09 19:05:38 -070086namespace {
87
Chris Lattner7f9cc272018-07-19 08:35:28 -070088typedef std::function<Operation *(Identifier, ArrayRef<SSAValue *>,
89 ArrayRef<Type *>, ArrayRef<NamedAttribute>)>
Tatiana Shpeisman565b9642018-07-16 11:47:09 -070090 CreateOperationFunction;
91
Chris Lattner48af7d12018-07-09 19:05:38 -070092/// This class implement support for parsing global entities like types and
93/// shared entities like SSA names. It is intended to be subclassed by
94/// specialized subparsers that include state, e.g. when a local symbol table.
95class Parser {
96public:
Chris Lattner2e595eb2018-07-10 10:08:27 -070097 Builder builder;
Chris Lattner48af7d12018-07-09 19:05:38 -070098
Chris Lattner2e595eb2018-07-10 10:08:27 -070099 Parser(ParserState &state) : builder(state.context), state(state) {}
100
101 // Helper methods to get stuff from the parser-global state.
102 ParserState &getState() const { return state; }
Chris Lattner48af7d12018-07-09 19:05:38 -0700103 MLIRContext *getContext() const { return state.context; }
Chris Lattner2e595eb2018-07-10 10:08:27 -0700104 Module *getModule() { return state.module; }
Chris Lattner48af7d12018-07-09 19:05:38 -0700105
106 /// Return the current token the parser is inspecting.
107 const Token &getToken() const { return state.curToken; }
108 StringRef getTokenSpelling() const { return state.curToken.getSpelling(); }
Chris Lattnere79379a2018-06-22 10:39:19 -0700109
110 /// Emit an error and return failure.
Chris Lattner4c95a502018-06-23 16:03:42 -0700111 ParseResult emitError(const Twine &message) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700112 return emitError(state.curToken.getLoc(), message);
Chris Lattner4c95a502018-06-23 16:03:42 -0700113 }
114 ParseResult emitError(SMLoc loc, const Twine &message);
Chris Lattnere79379a2018-06-22 10:39:19 -0700115
116 /// Advance the current lexer onto the next token.
117 void consumeToken() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700118 assert(state.curToken.isNot(Token::eof, Token::error) &&
Chris Lattnere79379a2018-06-22 10:39:19 -0700119 "shouldn't advance past EOF or errors");
Chris Lattner48af7d12018-07-09 19:05:38 -0700120 state.curToken = state.lex.lexToken();
Chris Lattnere79379a2018-06-22 10:39:19 -0700121 }
122
123 /// Advance the current lexer onto the next token, asserting what the expected
124 /// current token is. This is preferred to the above method because it leads
125 /// to more self-documenting code with better checking.
Chris Lattner8da0c282018-06-29 11:15:56 -0700126 void consumeToken(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700127 assert(state.curToken.is(kind) && "consumed an unexpected token");
Chris Lattnere79379a2018-06-22 10:39:19 -0700128 consumeToken();
129 }
130
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700131 /// If the current token has the specified kind, consume it and return true.
132 /// If not, return false.
Chris Lattner8da0c282018-06-29 11:15:56 -0700133 bool consumeIf(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700134 if (state.curToken.isNot(kind))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700135 return false;
136 consumeToken(kind);
137 return true;
138 }
139
Chris Lattner40746442018-07-21 14:32:09 -0700140 /// Parse a comma-separated list of elements up until the specified end token.
141 ParseResult
142 parseCommaSeparatedListUntil(Token::Kind rightToken,
143 const std::function<ParseResult()> &parseElement,
144 bool allowEmptyList = true);
145
146 /// Parse a comma separated list of elements that must have at least one entry
147 /// in it.
148 ParseResult
149 parseCommaSeparatedList(const std::function<ParseResult()> &parseElement);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700150
Chris Lattnerf7e22732018-06-22 22:03:48 -0700151 // We have two forms of parsing methods - those that return a non-null
152 // pointer on success, and those that return a ParseResult to indicate whether
153 // they returned a failure. The second class fills in by-reference arguments
154 // as the results of their action.
155
Chris Lattnere79379a2018-06-22 10:39:19 -0700156 // Type parsing.
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700157 Type *parsePrimitiveType();
Chris Lattnerf7e22732018-06-22 22:03:48 -0700158 Type *parseElementType();
159 VectorType *parseVectorType();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700160 ParseResult parseDimensionListRanked(SmallVectorImpl<int> &dimensions);
Chris Lattnerf7e22732018-06-22 22:03:48 -0700161 Type *parseTensorType();
162 Type *parseMemRefType();
163 Type *parseFunctionType();
164 Type *parseType();
165 ParseResult parseTypeList(SmallVectorImpl<Type*> &elements);
Chris Lattnere79379a2018-06-22 10:39:19 -0700166
Chris Lattner7121b802018-07-04 20:45:39 -0700167 // Attribute parsing.
168 Attribute *parseAttribute();
169 ParseResult parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes);
170
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700171 // Polyhedral structures.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700172 AffineMap *parseAffineMapInline();
MLIR Team718c82f2018-07-16 09:45:22 -0700173 AffineMap *parseAffineMapReference();
MLIR Teamf85a6262018-06-27 11:03:08 -0700174
Chris Lattner48af7d12018-07-09 19:05:38 -0700175private:
176 // The Parser is subclassed and reinstantiated. Do not add additional
177 // non-trivial state here, add it to the ParserState class.
178 ParserState &state;
Chris Lattnere79379a2018-06-22 10:39:19 -0700179};
180} // end anonymous namespace
181
182//===----------------------------------------------------------------------===//
183// Helper methods.
184//===----------------------------------------------------------------------===//
185
Chris Lattner4c95a502018-06-23 16:03:42 -0700186ParseResult Parser::emitError(SMLoc loc, const Twine &message) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700187 // If we hit a parse error in response to a lexer error, then the lexer
Jacques Pienaar9c411be2018-06-24 19:17:35 -0700188 // already reported the error.
Chris Lattner48af7d12018-07-09 19:05:38 -0700189 if (getToken().is(Token::error))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700190 return ParseFailure;
191
Chris Lattner48af7d12018-07-09 19:05:38 -0700192 auto &sourceMgr = state.lex.getSourceMgr();
193 state.errorReporter(sourceMgr.GetMessage(loc, SourceMgr::DK_Error, message));
Chris Lattnere79379a2018-06-22 10:39:19 -0700194 return ParseFailure;
195}
196
Chris Lattner40746442018-07-21 14:32:09 -0700197/// Parse a comma separated list of elements that must have at least one entry
198/// in it.
199ParseResult Parser::parseCommaSeparatedList(
200 const std::function<ParseResult()> &parseElement) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700201 // Non-empty case starts with an element.
202 if (parseElement())
203 return ParseFailure;
204
205 // Otherwise we have a list of comma separated elements.
206 while (consumeIf(Token::comma)) {
207 if (parseElement())
208 return ParseFailure;
209 }
Chris Lattner40746442018-07-21 14:32:09 -0700210 return ParseSuccess;
211}
212
213/// Parse a comma-separated list of elements, terminated with an arbitrary
214/// token. This allows empty lists if allowEmptyList is true.
215///
216/// abstract-list ::= rightToken // if allowEmptyList == true
217/// abstract-list ::= element (',' element)* rightToken
218///
219ParseResult Parser::parseCommaSeparatedListUntil(
220 Token::Kind rightToken, const std::function<ParseResult()> &parseElement,
221 bool allowEmptyList) {
222 // Handle the empty case.
223 if (getToken().is(rightToken)) {
224 if (!allowEmptyList)
225 return emitError("expected list element");
226 consumeToken(rightToken);
227 return ParseSuccess;
228 }
229
230 if (parseCommaSeparatedList(parseElement))
231 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700232
233 // Consume the end character.
234 if (!consumeIf(rightToken))
Chris Lattner8da0c282018-06-29 11:15:56 -0700235 return emitError("expected ',' or '" + Token::getTokenSpelling(rightToken) +
236 "'");
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700237
238 return ParseSuccess;
239}
Chris Lattnere79379a2018-06-22 10:39:19 -0700240
241//===----------------------------------------------------------------------===//
242// Type Parsing
243//===----------------------------------------------------------------------===//
244
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700245/// Parse the low-level fixed dtypes in the system.
246///
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700247/// primitive-type ::= `f16` | `bf16` | `f32` | `f64`
248/// primitive-type ::= integer-type
249/// primitive-type ::= `affineint`
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700250///
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700251Type *Parser::parsePrimitiveType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700252 switch (getToken().getKind()) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700253 default:
254 return (emitError("expected type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700255 case Token::kw_bf16:
256 consumeToken(Token::kw_bf16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700257 return builder.getBF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700258 case Token::kw_f16:
259 consumeToken(Token::kw_f16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700260 return builder.getF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700261 case Token::kw_f32:
262 consumeToken(Token::kw_f32);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700263 return builder.getF32Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700264 case Token::kw_f64:
265 consumeToken(Token::kw_f64);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700266 return builder.getF64Type();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700267 case Token::kw_affineint:
268 consumeToken(Token::kw_affineint);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700269 return builder.getAffineIntType();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700270 case Token::inttype: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700271 auto width = getToken().getIntTypeBitwidth();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700272 if (!width.hasValue())
273 return (emitError("invalid integer width"), nullptr);
274 consumeToken(Token::inttype);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700275 return builder.getIntegerType(width.getValue());
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700276 }
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700277 }
278}
279
280/// Parse the element type of a tensor or memref type.
281///
282/// element-type ::= primitive-type | vector-type
283///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700284Type *Parser::parseElementType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700285 if (getToken().is(Token::kw_vector))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700286 return parseVectorType();
287
288 return parsePrimitiveType();
289}
290
291/// Parse a vector type.
292///
293/// vector-type ::= `vector` `<` const-dimension-list primitive-type `>`
294/// const-dimension-list ::= (integer-literal `x`)+
295///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700296VectorType *Parser::parseVectorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700297 consumeToken(Token::kw_vector);
298
299 if (!consumeIf(Token::less))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700300 return (emitError("expected '<' in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700301
Chris Lattner48af7d12018-07-09 19:05:38 -0700302 if (getToken().isNot(Token::integer))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700303 return (emitError("expected dimension size in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700304
305 SmallVector<unsigned, 4> dimensions;
Chris Lattner48af7d12018-07-09 19:05:38 -0700306 while (getToken().is(Token::integer)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700307 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700308 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700309 if (!dimension.hasValue())
Chris Lattnerf7e22732018-06-22 22:03:48 -0700310 return (emitError("invalid dimension in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700311 dimensions.push_back(dimension.getValue());
312
313 consumeToken(Token::integer);
314
315 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700316 if (getToken().isNot(Token::bare_identifier) ||
317 getTokenSpelling()[0] != 'x')
Chris Lattnerf7e22732018-06-22 22:03:48 -0700318 return (emitError("expected 'x' in vector dimension list"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700319
320 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700321 if (getTokenSpelling().size() != 1)
322 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700323
324 // Consume the 'x'.
325 consumeToken(Token::bare_identifier);
326 }
327
328 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700329 auto *elementType = parsePrimitiveType();
330 if (!elementType)
331 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700332
333 if (!consumeIf(Token::greater))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700334 return (emitError("expected '>' in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700335
Chris Lattnerf7e22732018-06-22 22:03:48 -0700336 return VectorType::get(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700337}
338
339/// Parse a dimension list of a tensor or memref type. This populates the
340/// dimension list, returning -1 for the '?' dimensions.
341///
342/// dimension-list-ranked ::= (dimension `x`)*
343/// dimension ::= `?` | integer-literal
344///
345ParseResult Parser::parseDimensionListRanked(SmallVectorImpl<int> &dimensions) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700346 while (getToken().isAny(Token::integer, Token::question)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700347 if (consumeIf(Token::question)) {
348 dimensions.push_back(-1);
349 } else {
350 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700351 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700352 if (!dimension.hasValue() || (int)dimension.getValue() < 0)
353 return emitError("invalid dimension");
354 dimensions.push_back((int)dimension.getValue());
355 consumeToken(Token::integer);
356 }
357
358 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700359 if (getToken().isNot(Token::bare_identifier) ||
360 getTokenSpelling()[0] != 'x')
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700361 return emitError("expected 'x' in dimension list");
362
363 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700364 if (getTokenSpelling().size() != 1)
365 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700366
367 // Consume the 'x'.
368 consumeToken(Token::bare_identifier);
369 }
370
371 return ParseSuccess;
372}
373
374/// Parse a tensor type.
375///
376/// tensor-type ::= `tensor` `<` dimension-list element-type `>`
377/// dimension-list ::= dimension-list-ranked | `??`
378///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700379Type *Parser::parseTensorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700380 consumeToken(Token::kw_tensor);
381
382 if (!consumeIf(Token::less))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700383 return (emitError("expected '<' in tensor type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700384
385 bool isUnranked;
386 SmallVector<int, 4> dimensions;
387
388 if (consumeIf(Token::questionquestion)) {
389 isUnranked = true;
390 } else {
391 isUnranked = false;
392 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700393 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700394 }
395
396 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700397 auto elementType = parseElementType();
398 if (!elementType)
399 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700400
401 if (!consumeIf(Token::greater))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700402 return (emitError("expected '>' in tensor type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700403
MLIR Team355ec862018-06-23 18:09:09 -0700404 if (isUnranked)
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700405 return builder.getTensorType(elementType);
406 return builder.getTensorType(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700407}
408
409/// Parse a memref type.
410///
411/// memref-type ::= `memref` `<` dimension-list-ranked element-type
412/// (`,` semi-affine-map-composition)? (`,` memory-space)? `>`
413///
414/// semi-affine-map-composition ::= (semi-affine-map `,` )* semi-affine-map
415/// memory-space ::= integer-literal /* | TODO: address-space-id */
416///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700417Type *Parser::parseMemRefType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700418 consumeToken(Token::kw_memref);
419
420 if (!consumeIf(Token::less))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700421 return (emitError("expected '<' in memref type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700422
423 SmallVector<int, 4> dimensions;
424 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700425 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700426
427 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700428 auto elementType = parseElementType();
429 if (!elementType)
430 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700431
MLIR Team718c82f2018-07-16 09:45:22 -0700432 if (!consumeIf(Token::comma))
433 return (emitError("expected ',' in memref type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700434
MLIR Team718c82f2018-07-16 09:45:22 -0700435 // Parse semi-affine-map-composition.
436 SmallVector<AffineMap*, 2> affineMapComposition;
437 unsigned memorySpace;
438 bool parsedMemorySpace = false;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700439
MLIR Team718c82f2018-07-16 09:45:22 -0700440 auto parseElt = [&]() -> ParseResult {
441 if (getToken().is(Token::integer)) {
442 // Parse memory space.
443 if (parsedMemorySpace)
444 return emitError("multiple memory spaces specified in memref type");
445 auto v = getToken().getUnsignedIntegerValue();
446 if (!v.hasValue())
447 return emitError("invalid memory space in memref type");
448 memorySpace = v.getValue();
449 consumeToken(Token::integer);
450 parsedMemorySpace = true;
451 } else {
452 // Parse affine map.
453 if (parsedMemorySpace)
454 return emitError("affine map after memory space in memref type");
455 auto* affineMap = parseAffineMapReference();
456 if (affineMap == nullptr)
457 return ParseFailure;
458 affineMapComposition.push_back(affineMap);
459 }
460 return ParseSuccess;
461 };
462
463 // Parse comma separated list of affine maps, followed by memory space.
Chris Lattner40746442018-07-21 14:32:09 -0700464 if (parseCommaSeparatedListUntil(Token::greater, parseElt,
465 /*allowEmptyList=*/false)) {
MLIR Team718c82f2018-07-16 09:45:22 -0700466 return nullptr;
467 }
468 // Check that MemRef type specifies at least one affine map in composition.
469 if (affineMapComposition.empty())
470 return (emitError("expected semi-affine-map in memref type"), nullptr);
471 if (!parsedMemorySpace)
472 return (emitError("expected memory space in memref type"), nullptr);
473
474 return MemRefType::get(dimensions, elementType, affineMapComposition,
475 memorySpace);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700476}
477
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700478/// Parse a function type.
479///
480/// function-type ::= type-list-parens `->` type-list
481///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700482Type *Parser::parseFunctionType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700483 assert(getToken().is(Token::l_paren));
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700484
Chris Lattnerf7e22732018-06-22 22:03:48 -0700485 SmallVector<Type*, 4> arguments;
486 if (parseTypeList(arguments))
487 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700488
489 if (!consumeIf(Token::arrow))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700490 return (emitError("expected '->' in function type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700491
Chris Lattnerf7e22732018-06-22 22:03:48 -0700492 SmallVector<Type*, 4> results;
493 if (parseTypeList(results))
494 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700495
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700496 return builder.getFunctionType(arguments, results);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700497}
498
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700499/// Parse an arbitrary type.
500///
501/// type ::= primitive-type
502/// | vector-type
503/// | tensor-type
504/// | memref-type
505/// | function-type
506/// element-type ::= primitive-type | vector-type
507///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700508Type *Parser::parseType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700509 switch (getToken().getKind()) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700510 case Token::kw_memref: return parseMemRefType();
511 case Token::kw_tensor: return parseTensorType();
512 case Token::kw_vector: return parseVectorType();
513 case Token::l_paren: return parseFunctionType();
514 default:
515 return parsePrimitiveType();
516 }
517}
518
519/// Parse a "type list", which is a singular type, or a parenthesized list of
520/// types.
521///
522/// type-list ::= type-list-parens | type
523/// type-list-parens ::= `(` `)`
524/// | `(` type (`,` type)* `)`
525///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700526ParseResult Parser::parseTypeList(SmallVectorImpl<Type*> &elements) {
527 auto parseElt = [&]() -> ParseResult {
528 auto elt = parseType();
529 elements.push_back(elt);
530 return elt ? ParseSuccess : ParseFailure;
531 };
532
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700533 // If there is no parens, then it must be a singular type.
534 if (!consumeIf(Token::l_paren))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700535 return parseElt();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700536
Chris Lattner40746442018-07-21 14:32:09 -0700537 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700538 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700539
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700540 return ParseSuccess;
541}
542
Chris Lattner4c95a502018-06-23 16:03:42 -0700543//===----------------------------------------------------------------------===//
Chris Lattner7121b802018-07-04 20:45:39 -0700544// Attribute parsing.
545//===----------------------------------------------------------------------===//
546
547
548/// Attribute parsing.
549///
550/// attribute-value ::= bool-literal
551/// | integer-literal
552/// | float-literal
553/// | string-literal
554/// | `[` (attribute-value (`,` attribute-value)*)? `]`
555///
556Attribute *Parser::parseAttribute() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700557 switch (getToken().getKind()) {
Chris Lattner7121b802018-07-04 20:45:39 -0700558 case Token::kw_true:
559 consumeToken(Token::kw_true);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700560 return builder.getBoolAttr(true);
Chris Lattner7121b802018-07-04 20:45:39 -0700561 case Token::kw_false:
562 consumeToken(Token::kw_false);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700563 return builder.getBoolAttr(false);
Chris Lattner7121b802018-07-04 20:45:39 -0700564
565 case Token::integer: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700566 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700567 if (!val.hasValue() || (int64_t)val.getValue() < 0)
568 return (emitError("integer too large for attribute"), nullptr);
569 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700570 return builder.getIntegerAttr((int64_t)val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700571 }
572
573 case Token::minus: {
574 consumeToken(Token::minus);
Chris Lattner48af7d12018-07-09 19:05:38 -0700575 if (getToken().is(Token::integer)) {
576 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700577 if (!val.hasValue() || (int64_t)-val.getValue() >= 0)
578 return (emitError("integer too large for attribute"), nullptr);
579 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700580 return builder.getIntegerAttr((int64_t)-val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700581 }
582
583 return (emitError("expected constant integer or floating point value"),
584 nullptr);
585 }
586
587 case Token::string: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700588 auto val = getToken().getStringValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700589 consumeToken(Token::string);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700590 return builder.getStringAttr(val);
Chris Lattner7121b802018-07-04 20:45:39 -0700591 }
592
593 case Token::l_bracket: {
594 consumeToken(Token::l_bracket);
595 SmallVector<Attribute*, 4> elements;
596
597 auto parseElt = [&]() -> ParseResult {
598 elements.push_back(parseAttribute());
599 return elements.back() ? ParseSuccess : ParseFailure;
600 };
601
Chris Lattner40746442018-07-21 14:32:09 -0700602 if (parseCommaSeparatedListUntil(Token::r_bracket, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700603 return nullptr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700604 return builder.getArrayAttr(elements);
Chris Lattner7121b802018-07-04 20:45:39 -0700605 }
606 default:
MLIR Teamb61885d2018-07-18 16:29:21 -0700607 // Try to parse affine map reference.
608 auto* affineMap = parseAffineMapReference();
609 if (affineMap != nullptr)
610 return builder.getAffineMapAttr(affineMap);
611
Chris Lattner7121b802018-07-04 20:45:39 -0700612 // TODO: Handle floating point.
613 return (emitError("expected constant attribute value"), nullptr);
614 }
615}
616
Chris Lattner7121b802018-07-04 20:45:39 -0700617/// Attribute dictionary.
618///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700619/// attribute-dict ::= `{` `}`
620/// | `{` attribute-entry (`,` attribute-entry)* `}`
621/// attribute-entry ::= bare-id `:` attribute-value
Chris Lattner7121b802018-07-04 20:45:39 -0700622///
623ParseResult Parser::parseAttributeDict(
624 SmallVectorImpl<NamedAttribute> &attributes) {
625 consumeToken(Token::l_brace);
626
627 auto parseElt = [&]() -> ParseResult {
628 // We allow keywords as attribute names.
Chris Lattner48af7d12018-07-09 19:05:38 -0700629 if (getToken().isNot(Token::bare_identifier, Token::inttype) &&
630 !getToken().isKeyword())
Chris Lattner7121b802018-07-04 20:45:39 -0700631 return emitError("expected attribute name");
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700632 auto nameId = builder.getIdentifier(getTokenSpelling());
Chris Lattner7121b802018-07-04 20:45:39 -0700633 consumeToken();
634
635 if (!consumeIf(Token::colon))
636 return emitError("expected ':' in attribute list");
637
638 auto attr = parseAttribute();
639 if (!attr) return ParseFailure;
640
641 attributes.push_back({nameId, attr});
642 return ParseSuccess;
643 };
644
Chris Lattner40746442018-07-21 14:32:09 -0700645 if (parseCommaSeparatedListUntil(Token::r_brace, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700646 return ParseFailure;
647
648 return ParseSuccess;
649}
650
651//===----------------------------------------------------------------------===//
MLIR Teamf85a6262018-06-27 11:03:08 -0700652// Polyhedral structures.
653//===----------------------------------------------------------------------===//
654
Chris Lattner2e595eb2018-07-10 10:08:27 -0700655/// Lower precedence ops (all at the same precedence level). LNoOp is false in
656/// the boolean sense.
657enum AffineLowPrecOp {
658 /// Null value.
659 LNoOp,
660 Add,
661 Sub
662};
MLIR Teamf85a6262018-06-27 11:03:08 -0700663
Chris Lattner2e595eb2018-07-10 10:08:27 -0700664/// Higher precedence ops - all at the same precedence level. HNoOp is false in
665/// the boolean sense.
666enum AffineHighPrecOp {
667 /// Null value.
668 HNoOp,
669 Mul,
670 FloorDiv,
671 CeilDiv,
672 Mod
673};
Chris Lattner7121b802018-07-04 20:45:39 -0700674
Chris Lattner2e595eb2018-07-10 10:08:27 -0700675namespace {
676/// This is a specialized parser for AffineMap's, maintaining the state
677/// transient to their bodies.
678class AffineMapParser : public Parser {
679public:
680 explicit AffineMapParser(ParserState &state) : Parser(state) {}
Chris Lattner7121b802018-07-04 20:45:39 -0700681
Chris Lattner2e595eb2018-07-10 10:08:27 -0700682 AffineMap *parseAffineMapInline();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700683
Chris Lattner2e595eb2018-07-10 10:08:27 -0700684private:
685 unsigned getNumDims() const { return dims.size(); }
686 unsigned getNumSymbols() const { return symbols.size(); }
MLIR Teamf85a6262018-06-27 11:03:08 -0700687
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700688 /// Returns true if the only identifiers the parser accepts in affine
689 /// expressions are symbolic identifiers.
690 bool isPureSymbolic() const { return pureSymbolic; }
691 void setSymbolicParsing(bool val) { pureSymbolic = val; }
692
Chris Lattner2e595eb2018-07-10 10:08:27 -0700693 // Binary affine op parsing.
694 AffineLowPrecOp consumeIfLowPrecOp();
695 AffineHighPrecOp consumeIfHighPrecOp();
MLIR Teamf85a6262018-06-27 11:03:08 -0700696
Chris Lattner2e595eb2018-07-10 10:08:27 -0700697 // Identifier lists for polyhedral structures.
698 ParseResult parseDimIdList();
699 ParseResult parseSymbolIdList();
700 ParseResult parseDimOrSymbolId(bool isDim);
701
702 AffineExpr *parseAffineExpr();
703 AffineExpr *parseParentheticalExpr();
704 AffineExpr *parseNegateExpression(AffineExpr *lhs);
705 AffineExpr *parseIntegerExpr();
706 AffineExpr *parseBareIdExpr();
707
708 AffineExpr *getBinaryAffineOpExpr(AffineHighPrecOp op, AffineExpr *lhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700709 AffineExpr *rhs, SMLoc opLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700710 AffineExpr *getBinaryAffineOpExpr(AffineLowPrecOp op, AffineExpr *lhs,
711 AffineExpr *rhs);
712 AffineExpr *parseAffineOperandExpr(AffineExpr *lhs);
713 AffineExpr *parseAffineLowPrecOpExpr(AffineExpr *llhs,
714 AffineLowPrecOp llhsOp);
715 AffineExpr *parseAffineHighPrecOpExpr(AffineExpr *llhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700716 AffineHighPrecOp llhsOp,
717 SMLoc llhsOpLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700718
719private:
720 // TODO(bondhugula): could just use an vector/ArrayRef and scan the numbers.
721 llvm::StringMap<unsigned> dims;
722 llvm::StringMap<unsigned> symbols;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700723 /// True if the parser should allow only symbolic identifiers in affine
724 /// expressions.
725 bool pureSymbolic = false;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700726};
727} // end anonymous namespace
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700728
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700729/// Create an affine binary high precedence op expression (mul's, div's, mod).
730/// opLoc is the location of the op token to be used to report errors
731/// for non-conforming expressions.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700732AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineHighPrecOp op,
733 AffineExpr *lhs,
Chris Lattner40746442018-07-21 14:32:09 -0700734 AffineExpr *rhs,
735 SMLoc opLoc) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700736 // TODO: make the error location info accurate.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700737 switch (op) {
738 case Mul:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700739 if (!lhs->isSymbolicOrConstant() && !rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700740 emitError(opLoc, "non-affine expression: at least one of the multiply "
741 "operands has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700742 return nullptr;
743 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700744 return builder.getMulExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700745 case FloorDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700746 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700747 emitError(opLoc, "non-affine expression: right operand of floordiv "
748 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700749 return nullptr;
750 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700751 return builder.getFloorDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700752 case CeilDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700753 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700754 emitError(opLoc, "non-affine expression: right operand of ceildiv "
755 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700756 return nullptr;
757 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700758 return builder.getCeilDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700759 case Mod:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700760 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700761 emitError(opLoc, "non-affine expression: right operand of mod "
762 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700763 return nullptr;
764 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700765 return builder.getModExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700766 case HNoOp:
767 llvm_unreachable("can't create affine expression for null high prec op");
768 return nullptr;
769 }
770}
771
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700772/// Create an affine binary low precedence op expression (add, sub).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700773AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineLowPrecOp op,
774 AffineExpr *lhs,
775 AffineExpr *rhs) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700776 switch (op) {
777 case AffineLowPrecOp::Add:
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700778 return builder.getAddExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700779 case AffineLowPrecOp::Sub:
Uday Bondhugulac1faf662018-07-19 14:08:50 -0700780 return builder.getAddExpr(
781 lhs, builder.getMulExpr(rhs, builder.getConstantExpr(-1)));
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700782 case AffineLowPrecOp::LNoOp:
783 llvm_unreachable("can't create affine expression for null low prec op");
784 return nullptr;
785 }
786}
787
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700788/// Consume this token if it is a lower precedence affine op (there are only two
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700789/// precedence levels).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700790AffineLowPrecOp AffineMapParser::consumeIfLowPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700791 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700792 case Token::plus:
793 consumeToken(Token::plus);
794 return AffineLowPrecOp::Add;
795 case Token::minus:
796 consumeToken(Token::minus);
797 return AffineLowPrecOp::Sub;
798 default:
799 return AffineLowPrecOp::LNoOp;
800 }
801}
802
803/// Consume this token if it is a higher precedence affine op (there are only
804/// two precedence levels)
Chris Lattner2e595eb2018-07-10 10:08:27 -0700805AffineHighPrecOp AffineMapParser::consumeIfHighPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700806 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700807 case Token::star:
808 consumeToken(Token::star);
809 return Mul;
810 case Token::kw_floordiv:
811 consumeToken(Token::kw_floordiv);
812 return FloorDiv;
813 case Token::kw_ceildiv:
814 consumeToken(Token::kw_ceildiv);
815 return CeilDiv;
816 case Token::kw_mod:
817 consumeToken(Token::kw_mod);
818 return Mod;
819 default:
820 return HNoOp;
821 }
822}
823
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700824/// Parse a high precedence op expression list: mul, div, and mod are high
825/// precedence binary ops, i.e., parse a
826/// expr_1 op_1 expr_2 op_2 ... expr_n
827/// where op_1, op_2 are all a AffineHighPrecOp (mul, div, mod).
828/// All affine binary ops are left associative.
829/// Given llhs, returns (llhs llhsOp lhs) op rhs, or (lhs op rhs) if llhs is
830/// null. If no rhs can be found, returns (llhs llhsOp lhs) or lhs if llhs is
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700831/// null. llhsOpLoc is the location of the llhsOp token that will be used to
832/// report an error for non-conforming expressions.
833AffineExpr *AffineMapParser::parseAffineHighPrecOpExpr(AffineExpr *llhs,
834 AffineHighPrecOp llhsOp,
835 SMLoc llhsOpLoc) {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700836 AffineExpr *lhs = parseAffineOperandExpr(llhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700837 if (!lhs)
838 return nullptr;
839
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700840 // Found an LHS. Parse the remaining expression.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700841 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -0700842 if (AffineHighPrecOp op = consumeIfHighPrecOp()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700843 if (llhs) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700844 AffineExpr *expr = getBinaryAffineOpExpr(llhsOp, llhs, lhs, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700845 if (!expr)
846 return nullptr;
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700847 return parseAffineHighPrecOpExpr(expr, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700848 }
849 // No LLHS, get RHS
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700850 return parseAffineHighPrecOpExpr(lhs, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700851 }
852
853 // This is the last operand in this expression.
854 if (llhs)
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700855 return getBinaryAffineOpExpr(llhsOp, llhs, lhs, llhsOpLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700856
857 // No llhs, 'lhs' itself is the expression.
858 return lhs;
859}
860
861/// Parse an affine expression inside parentheses.
862///
863/// affine-expr ::= `(` affine-expr `)`
Chris Lattner2e595eb2018-07-10 10:08:27 -0700864AffineExpr *AffineMapParser::parseParentheticalExpr() {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700865 if (!consumeIf(Token::l_paren))
866 return (emitError("expected '('"), nullptr);
Chris Lattner48af7d12018-07-09 19:05:38 -0700867 if (getToken().is(Token::r_paren))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700868 return (emitError("no expression inside parentheses"), nullptr);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700869 auto *expr = parseAffineExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700870 if (!expr)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700871 return nullptr;
872 if (!consumeIf(Token::r_paren))
873 return (emitError("expected ')'"), nullptr);
874 return expr;
875}
876
877/// Parse the negation expression.
878///
879/// affine-expr ::= `-` affine-expr
Chris Lattner2e595eb2018-07-10 10:08:27 -0700880AffineExpr *AffineMapParser::parseNegateExpression(AffineExpr *lhs) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700881 if (!consumeIf(Token::minus))
882 return (emitError("expected '-'"), nullptr);
883
Chris Lattner2e595eb2018-07-10 10:08:27 -0700884 AffineExpr *operand = parseAffineOperandExpr(lhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700885 // Since negation has the highest precedence of all ops (including high
886 // precedence ops) but lower than parentheses, we are only going to use
887 // parseAffineOperandExpr instead of parseAffineExpr here.
888 if (!operand)
889 // Extra error message although parseAffineOperandExpr would have
890 // complained. Leads to a better diagnostic.
891 return (emitError("missing operand of negation"), nullptr);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700892 auto *minusOne = builder.getConstantExpr(-1);
893 return builder.getMulExpr(minusOne, operand);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700894}
895
896/// Parse a bare id that may appear in an affine expression.
897///
898/// affine-expr ::= bare-id
Chris Lattner2e595eb2018-07-10 10:08:27 -0700899AffineExpr *AffineMapParser::parseBareIdExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700900 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700901 return (emitError("expected bare identifier"), nullptr);
902
Chris Lattner48af7d12018-07-09 19:05:38 -0700903 StringRef sRef = getTokenSpelling();
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700904 // dims, symbols are all pairwise distinct.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700905 if (dims.count(sRef)) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700906 if (isPureSymbolic())
907 return (emitError("identifier used is not a symbolic identifier"),
908 nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700909 consumeToken(Token::bare_identifier);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700910 return builder.getDimExpr(dims.lookup(sRef));
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700911 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700912
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700913 if (symbols.count(sRef)) {
914 consumeToken(Token::bare_identifier);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700915 return builder.getSymbolExpr(symbols.lookup(sRef));
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700916 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700917
918 return (emitError("use of undeclared identifier"), nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700919}
920
921/// Parse a positive integral constant appearing in an affine expression.
922///
923/// affine-expr ::= integer-literal
Chris Lattner2e595eb2018-07-10 10:08:27 -0700924AffineExpr *AffineMapParser::parseIntegerExpr() {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700925 // No need to handle negative numbers separately here. They are naturally
926 // handled via the unary negation operator, although (FIXME) MININT_64 still
927 // not correctly handled.
Chris Lattner48af7d12018-07-09 19:05:38 -0700928 if (getToken().isNot(Token::integer))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700929 return (emitError("expected integer"), nullptr);
930
Chris Lattner48af7d12018-07-09 19:05:38 -0700931 auto val = getToken().getUInt64IntegerValue();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700932 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
933 return (emitError("constant too large for affineint"), nullptr);
934 }
935 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700936 return builder.getConstantExpr((int64_t)val.getValue());
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700937}
938
939/// Parses an expression that can be a valid operand of an affine expression.
Uday Bondhugula76345202018-07-09 13:47:52 -0700940/// lhs: if non-null, lhs is an affine expression that is the lhs of a binary
941/// operator, the rhs of which is being parsed. This is used to determine
942/// whether an error should be emitted for a missing right operand.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700943// Eg: for an expression without parentheses (like i + j + k + l), each
944// of the four identifiers is an operand. For i + j*k + l, j*k is not an
945// operand expression, it's an op expression and will be parsed via
946// parseAffineHighPrecOpExpression(). However, for i + (j*k) + -l, (j*k) and -l
947// are valid operands that will be parsed by this function.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700948AffineExpr *AffineMapParser::parseAffineOperandExpr(AffineExpr *lhs) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700949 switch (getToken().getKind()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700950 case Token::bare_identifier:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700951 return parseBareIdExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700952 case Token::integer:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700953 return parseIntegerExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700954 case Token::l_paren:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700955 return parseParentheticalExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700956 case Token::minus:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700957 return parseNegateExpression(lhs);
Uday Bondhugula76345202018-07-09 13:47:52 -0700958 case Token::kw_ceildiv:
959 case Token::kw_floordiv:
960 case Token::kw_mod:
961 case Token::plus:
962 case Token::star:
963 if (lhs)
964 emitError("missing right operand of binary operator");
965 else
966 emitError("missing left operand of binary operator");
967 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700968 default:
969 if (lhs)
Uday Bondhugula76345202018-07-09 13:47:52 -0700970 emitError("missing right operand of binary operator");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700971 else
972 emitError("expected affine expression");
973 return nullptr;
974 }
975}
976
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700977/// Parse affine expressions that are bare-id's, integer constants,
978/// parenthetical affine expressions, and affine op expressions that are a
979/// composition of those.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700980///
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700981/// All binary op's associate from left to right.
982///
983/// {add, sub} have lower precedence than {mul, div, and mod}.
984///
Uday Bondhugula76345202018-07-09 13:47:52 -0700985/// Add, sub'are themselves at the same precedence level. Mul, floordiv,
986/// ceildiv, and mod are at the same higher precedence level. Negation has
987/// higher precedence than any binary op.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700988///
989/// llhs: the affine expression appearing on the left of the one being parsed.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700990/// This function will return ((llhs llhsOp lhs) op rhs) if llhs is non null,
991/// and lhs op rhs otherwise; if there is no rhs, llhs llhsOp lhs is returned if
992/// llhs is non-null; otherwise lhs is returned. This is to deal with left
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700993/// associativity.
994///
995/// Eg: when the expression is e1 + e2*e3 + e4, with e1 as llhs, this function
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700996/// will return the affine expr equivalent of (e1 + (e2*e3)) + e4, where (e2*e3)
997/// will be parsed using parseAffineHighPrecOpExpr().
Chris Lattner2e595eb2018-07-10 10:08:27 -0700998AffineExpr *AffineMapParser::parseAffineLowPrecOpExpr(AffineExpr *llhs,
999 AffineLowPrecOp llhsOp) {
Uday Bondhugula76345202018-07-09 13:47:52 -07001000 AffineExpr *lhs;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001001 if (!(lhs = parseAffineOperandExpr(llhs)))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001002 return nullptr;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001003
1004 // Found an LHS. Deal with the ops.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001005 if (AffineLowPrecOp lOp = consumeIfLowPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001006 if (llhs) {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001007 AffineExpr *sum = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001008 return parseAffineLowPrecOpExpr(sum, lOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001009 }
1010 // No LLHS, get RHS and form the expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001011 return parseAffineLowPrecOpExpr(lhs, lOp);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001012 }
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001013 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07001014 if (AffineHighPrecOp hOp = consumeIfHighPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001015 // We have a higher precedence op here. Get the rhs operand for the llhs
1016 // through parseAffineHighPrecOpExpr.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001017 AffineExpr *highRes = parseAffineHighPrecOpExpr(lhs, hOp, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001018 if (!highRes)
1019 return nullptr;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001020
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001021 // If llhs is null, the product forms the first operand of the yet to be
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001022 // found expression. If non-null, the op to associate with llhs is llhsOp.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001023 AffineExpr *expr =
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001024 llhs ? getBinaryAffineOpExpr(llhsOp, llhs, highRes) : highRes;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001025
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001026 // Recurse for subsequent low prec op's after the affine high prec op
1027 // expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001028 if (AffineLowPrecOp nextOp = consumeIfLowPrecOp())
1029 return parseAffineLowPrecOpExpr(expr, nextOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001030 return expr;
1031 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001032 // Last operand in the expression list.
1033 if (llhs)
1034 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
1035 // No llhs, 'lhs' itself is the expression.
1036 return lhs;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001037}
1038
1039/// Parse an affine expression.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001040/// affine-expr ::= `(` affine-expr `)`
1041/// | `-` affine-expr
1042/// | affine-expr `+` affine-expr
1043/// | affine-expr `-` affine-expr
1044/// | affine-expr `*` affine-expr
1045/// | affine-expr `floordiv` affine-expr
1046/// | affine-expr `ceildiv` affine-expr
1047/// | affine-expr `mod` affine-expr
1048/// | bare-id
1049/// | integer-literal
1050///
1051/// Additional conditions are checked depending on the production. For eg., one
1052/// of the operands for `*` has to be either constant/symbolic; the second
1053/// operand for floordiv, ceildiv, and mod has to be a positive integer.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001054AffineExpr *AffineMapParser::parseAffineExpr() {
1055 return parseAffineLowPrecOpExpr(nullptr, AffineLowPrecOp::LNoOp);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001056}
1057
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001058/// Parse a dim or symbol from the lists appearing before the actual expressions
Chris Lattner2e595eb2018-07-10 10:08:27 -07001059/// of the affine map. Update our state to store the dimensional/symbolic
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001060/// identifier. 'dim': whether it's the dim list or symbol list that is being
1061/// parsed.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001062ParseResult AffineMapParser::parseDimOrSymbolId(bool isDim) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001063 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001064 return emitError("expected bare identifier");
Chris Lattner48af7d12018-07-09 19:05:38 -07001065 auto sRef = getTokenSpelling();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001066 consumeToken(Token::bare_identifier);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001067 if (dims.count(sRef))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001068 return emitError("dimensional identifier name reused");
Chris Lattner2e595eb2018-07-10 10:08:27 -07001069 if (symbols.count(sRef))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001070 return emitError("symbolic identifier name reused");
Chris Lattner2e595eb2018-07-10 10:08:27 -07001071 if (isDim)
1072 dims.insert({sRef, dims.size()});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001073 else
Chris Lattner2e595eb2018-07-10 10:08:27 -07001074 symbols.insert({sRef, symbols.size()});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001075 return ParseSuccess;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001076}
1077
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001078/// Parse the list of symbolic identifiers to an affine map.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001079ParseResult AffineMapParser::parseSymbolIdList() {
1080 if (!consumeIf(Token::l_bracket))
1081 return emitError("expected '['");
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001082
Chris Lattner2e595eb2018-07-10 10:08:27 -07001083 auto parseElt = [&]() -> ParseResult { return parseDimOrSymbolId(false); };
Chris Lattner40746442018-07-21 14:32:09 -07001084 return parseCommaSeparatedListUntil(Token::r_bracket, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001085}
1086
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001087/// Parse the list of dimensional identifiers to an affine map.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001088ParseResult AffineMapParser::parseDimIdList() {
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001089 if (!consumeIf(Token::l_paren))
1090 return emitError("expected '(' at start of dimensional identifiers list");
1091
Chris Lattner2e595eb2018-07-10 10:08:27 -07001092 auto parseElt = [&]() -> ParseResult { return parseDimOrSymbolId(true); };
Chris Lattner40746442018-07-21 14:32:09 -07001093 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001094}
1095
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001096/// Parse an affine map definition.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001097///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001098/// affine-map-inline ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
1099/// (`size` `(` dim-size (`,` dim-size)* `)`)?
1100/// dim-size ::= affine-expr | `min` `(` affine-expr ( `,` affine-expr)+ `)`
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001101///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001102/// multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner2e595eb2018-07-10 10:08:27 -07001103AffineMap *AffineMapParser::parseAffineMapInline() {
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001104 // List of dimensional identifiers.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001105 if (parseDimIdList())
Chris Lattner7121b802018-07-04 20:45:39 -07001106 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001107
1108 // Symbols are optional.
Chris Lattner48af7d12018-07-09 19:05:38 -07001109 if (getToken().is(Token::l_bracket)) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001110 if (parseSymbolIdList())
Chris Lattner7121b802018-07-04 20:45:39 -07001111 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001112 }
1113 if (!consumeIf(Token::arrow)) {
Chris Lattner7121b802018-07-04 20:45:39 -07001114 return (emitError("expected '->' or '['"), nullptr);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001115 }
1116 if (!consumeIf(Token::l_paren)) {
1117 emitError("expected '(' at start of affine map range");
Chris Lattner7121b802018-07-04 20:45:39 -07001118 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001119 }
1120
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001121 SmallVector<AffineExpr *, 4> exprs;
1122 auto parseElt = [&]() -> ParseResult {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001123 auto *elt = parseAffineExpr();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001124 ParseResult res = elt ? ParseSuccess : ParseFailure;
1125 exprs.push_back(elt);
1126 return res;
1127 };
1128
1129 // Parse a multi-dimensional affine expression (a comma-separated list of 1-d
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001130 // affine expressions); the list cannot be empty.
1131 // Grammar: multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner40746442018-07-21 14:32:09 -07001132 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt, false))
Chris Lattner7121b802018-07-04 20:45:39 -07001133 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001134
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001135 // Parse optional range sizes.
Uday Bondhugula1e500b42018-07-12 18:04:04 -07001136 // range-sizes ::= (`size` `(` dim-size (`,` dim-size)* `)`)?
1137 // dim-size ::= affine-expr | `min` `(` affine-expr (`,` affine-expr)+ `)`
1138 // TODO(bondhugula): support for min of several affine expressions.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001139 // TODO: check if sizes are non-negative whenever they are constant.
1140 SmallVector<AffineExpr *, 4> rangeSizes;
1141 if (consumeIf(Token::kw_size)) {
1142 // Location of the l_paren token (if it exists) for error reporting later.
1143 auto loc = getToken().getLoc();
1144 if (!consumeIf(Token::l_paren))
1145 return (emitError("expected '(' at start of affine map range"), nullptr);
1146
1147 auto parseRangeSize = [&]() -> ParseResult {
1148 auto *elt = parseAffineExpr();
1149 ParseResult res = elt ? ParseSuccess : ParseFailure;
1150 rangeSizes.push_back(elt);
1151 return res;
1152 };
1153
1154 setSymbolicParsing(true);
Chris Lattner40746442018-07-21 14:32:09 -07001155 if (parseCommaSeparatedListUntil(Token::r_paren, parseRangeSize, false))
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001156 return nullptr;
1157 if (exprs.size() > rangeSizes.size())
1158 return (emitError(loc, "fewer range sizes than range expressions"),
1159 nullptr);
1160 if (exprs.size() < rangeSizes.size())
1161 return (emitError(loc, "more range sizes than range expressions"),
1162 nullptr);
1163 }
1164
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001165 // Parsed a valid affine map.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001166 return builder.getAffineMap(dims.size(), symbols.size(), exprs, rangeSizes);
MLIR Teamf85a6262018-06-27 11:03:08 -07001167}
1168
Chris Lattner2e595eb2018-07-10 10:08:27 -07001169AffineMap *Parser::parseAffineMapInline() {
1170 return AffineMapParser(state).parseAffineMapInline();
1171}
1172
MLIR Team718c82f2018-07-16 09:45:22 -07001173AffineMap *Parser::parseAffineMapReference() {
1174 if (getToken().is(Token::hash_identifier)) {
1175 // Parse affine map identifier and verify that it exists.
1176 StringRef affineMapId = getTokenSpelling().drop_front();
1177 if (getState().affineMapDefinitions.count(affineMapId) == 0)
1178 return (emitError("undefined affine map id '" + affineMapId + "'"),
1179 nullptr);
1180 consumeToken(Token::hash_identifier);
1181 return getState().affineMapDefinitions[affineMapId];
1182 }
1183 // Try to parse inline affine map.
1184 return parseAffineMapInline();
1185}
1186
MLIR Teamf85a6262018-06-27 11:03:08 -07001187//===----------------------------------------------------------------------===//
Chris Lattner7f9cc272018-07-19 08:35:28 -07001188// FunctionParser
Chris Lattner4c95a502018-06-23 16:03:42 -07001189//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001190
Chris Lattner7f9cc272018-07-19 08:35:28 -07001191namespace {
1192/// This class contains parser state that is common across CFG and ML functions,
1193/// notably for dealing with operations and SSA values.
1194class FunctionParser : public Parser {
1195public:
1196 FunctionParser(ParserState &state) : Parser(state) {}
1197
Chris Lattner6119d382018-07-20 18:41:34 -07001198 /// After the function is finished parsing, this function checks to see if
1199 /// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001200 ParseResult finalizeFunction(Function *func, SMLoc loc);
Chris Lattner6119d382018-07-20 18:41:34 -07001201
1202 /// This represents a use of an SSA value in the program. The first two
1203 /// entries in the tuple are the name and result number of a reference. The
1204 /// third is the location of the reference, which is used in case this ends up
1205 /// being a use of an undefined value.
1206 struct SSAUseInfo {
1207 StringRef name; // Value name, e.g. %42 or %abc
1208 unsigned number; // Number, specified with #12
1209 SMLoc loc; // Location of first definition or use.
1210 };
Chris Lattner7f9cc272018-07-19 08:35:28 -07001211
1212 /// Given a reference to an SSA value and its type, return a reference. This
1213 /// returns null on failure.
1214 SSAValue *resolveSSAUse(SSAUseInfo useInfo, Type *type);
1215
1216 /// Register a definition of a value with the symbol table.
1217 ParseResult addDefinition(SSAUseInfo useInfo, SSAValue *value);
1218
1219 // SSA parsing productions.
1220 ParseResult parseSSAUse(SSAUseInfo &result);
Chris Lattner40746442018-07-21 14:32:09 -07001221 ParseResult parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results);
James Molloy61a656c2018-07-22 15:45:24 -07001222
1223 template <typename ResultType>
1224 ResultType parseSSADefOrUseAndType(
1225 const std::function<ResultType(SSAUseInfo, Type *)> &action);
1226
1227 SSAValue *parseSSAUseAndType() {
1228 return parseSSADefOrUseAndType<SSAValue *>(
1229 [&](SSAUseInfo useInfo, Type *type) -> SSAValue * {
1230 return resolveSSAUse(useInfo, type);
1231 });
1232 }
Chris Lattner40746442018-07-21 14:32:09 -07001233
1234 template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001235 ParseResult
Chris Lattner40746442018-07-21 14:32:09 -07001236 parseOptionalSSAUseAndTypeList(SmallVectorImpl<ValueTy *> &results);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001237
1238 // Operations
1239 ParseResult parseOperation(const CreateOperationFunction &createOpFunc);
1240
1241private:
1242 /// This keeps track of all of the SSA values we are tracking, indexed by
Chris Lattner6119d382018-07-20 18:41:34 -07001243 /// their name. This has one entry per result number.
1244 llvm::StringMap<SmallVector<std::pair<SSAValue *, SMLoc>, 1>> values;
1245
1246 /// These are all of the placeholders we've made along with the location of
1247 /// their first reference, to allow checking for use of undefined values.
1248 DenseMap<SSAValue *, SMLoc> forwardReferencePlaceholders;
1249
1250 SSAValue *createForwardReferencePlaceholder(SMLoc loc, Type *type);
1251
1252 /// Return true if this is a forward reference.
1253 bool isForwardReferencePlaceholder(SSAValue *value) {
1254 return forwardReferencePlaceholders.count(value);
1255 }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001256};
1257} // end anonymous namespace
1258
Chris Lattner6119d382018-07-20 18:41:34 -07001259/// Create and remember a new placeholder for a forward reference.
1260SSAValue *FunctionParser::createForwardReferencePlaceholder(SMLoc loc,
1261 Type *type) {
1262 // Forward references are always created as instructions, even in ML
1263 // functions, because we just need something with a def/use chain.
1264 //
1265 // We create these placeholders as having an empty name, which we know cannot
1266 // be created through normal user input, allowing us to distinguish them.
1267 auto name = Identifier::get("placeholder", getContext());
1268 auto *inst = OperationInst::create(name, /*operands*/ {}, type, /*attrs*/ {},
1269 getContext());
1270 forwardReferencePlaceholders[inst->getResult(0)] = loc;
1271 return inst->getResult(0);
1272}
1273
Chris Lattner7f9cc272018-07-19 08:35:28 -07001274/// Given an unbound reference to an SSA value and its type, return a the value
1275/// it specifies. This returns null on failure.
1276SSAValue *FunctionParser::resolveSSAUse(SSAUseInfo useInfo, Type *type) {
Chris Lattner6119d382018-07-20 18:41:34 -07001277 auto &entries = values[useInfo.name];
1278
Chris Lattner7f9cc272018-07-19 08:35:28 -07001279 // If we have already seen a value of this name, return it.
Chris Lattner6119d382018-07-20 18:41:34 -07001280 if (useInfo.number < entries.size() && entries[useInfo.number].first) {
1281 auto *result = entries[useInfo.number].first;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001282 // Check that the type matches the other uses.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001283 if (result->getType() == type)
1284 return result;
1285
Chris Lattner6119d382018-07-20 18:41:34 -07001286 emitError(useInfo.loc, "use of value '" + useInfo.name.str() +
1287 "' expects different type than prior uses");
1288 emitError(entries[useInfo.number].second, "prior use here");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001289 return nullptr;
1290 }
1291
Chris Lattner6119d382018-07-20 18:41:34 -07001292 // Make sure we have enough slots for this.
1293 if (entries.size() <= useInfo.number)
1294 entries.resize(useInfo.number + 1);
1295
1296 // If the value has already been defined and this is an overly large result
1297 // number, diagnose that.
1298 if (entries[0].first && !isForwardReferencePlaceholder(entries[0].first))
1299 return (emitError(useInfo.loc, "reference to invalid result number"),
1300 nullptr);
1301
1302 // Otherwise, this is a forward reference. Create a placeholder and remember
1303 // that we did so.
1304 auto *result = createForwardReferencePlaceholder(useInfo.loc, type);
1305 entries[useInfo.number].first = result;
1306 entries[useInfo.number].second = useInfo.loc;
1307 return result;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001308}
1309
1310/// Register a definition of a value with the symbol table.
1311ParseResult FunctionParser::addDefinition(SSAUseInfo useInfo, SSAValue *value) {
Chris Lattner6119d382018-07-20 18:41:34 -07001312 auto &entries = values[useInfo.name];
Chris Lattner7f9cc272018-07-19 08:35:28 -07001313
Chris Lattner6119d382018-07-20 18:41:34 -07001314 // Make sure there is a slot for this value.
1315 if (entries.size() <= useInfo.number)
1316 entries.resize(useInfo.number + 1);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001317
Chris Lattner6119d382018-07-20 18:41:34 -07001318 // If we already have an entry for this, check to see if it was a definition
1319 // or a forward reference.
1320 if (auto *existing = entries[useInfo.number].first) {
1321 if (!isForwardReferencePlaceholder(existing)) {
1322 emitError(useInfo.loc,
1323 "redefinition of SSA value '" + useInfo.name + "'");
1324 return emitError(entries[useInfo.number].second,
1325 "previously defined here");
1326 }
1327
1328 // If it was a forward reference, update everything that used it to use the
1329 // actual definition instead, delete the forward ref, and remove it from our
1330 // set of forward references we track.
1331 existing->replaceAllUsesWith(value);
1332 existing->getDefiningInst()->destroy();
1333 forwardReferencePlaceholders.erase(existing);
1334 }
1335
1336 entries[useInfo.number].first = value;
1337 entries[useInfo.number].second = useInfo.loc;
1338 return ParseSuccess;
1339}
1340
1341/// After the function is finished parsing, this function checks to see if
1342/// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001343ParseResult FunctionParser::finalizeFunction(Function *func, SMLoc loc) {
Chris Lattner6119d382018-07-20 18:41:34 -07001344 // Check for any forward references that are left. If we find any, error out.
1345 if (!forwardReferencePlaceholders.empty()) {
1346 SmallVector<std::pair<const char *, SSAValue *>, 4> errors;
1347 // Iteration over the map isn't determinstic, so sort by source location.
1348 for (auto entry : forwardReferencePlaceholders)
1349 errors.push_back({entry.second.getPointer(), entry.first});
1350 llvm::array_pod_sort(errors.begin(), errors.end());
1351
1352 for (auto entry : errors)
1353 emitError(SMLoc::getFromPointer(entry.first),
1354 "use of undeclared SSA value name");
1355 return ParseFailure;
1356 }
1357
Chris Lattner40746442018-07-21 14:32:09 -07001358 // Run the verifier on this function. If an error is detected, report it.
1359 std::string errorString;
1360 if (func->verify(&errorString))
1361 return emitError(loc, errorString);
1362
Chris Lattner6119d382018-07-20 18:41:34 -07001363 return ParseSuccess;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001364}
1365
Chris Lattner78276e32018-07-07 15:48:26 -07001366/// Parse a SSA operand for an instruction or statement.
1367///
James Molloy61a656c2018-07-22 15:45:24 -07001368/// ssa-use ::= ssa-id
Chris Lattner78276e32018-07-07 15:48:26 -07001369///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001370ParseResult FunctionParser::parseSSAUse(SSAUseInfo &result) {
Chris Lattner6119d382018-07-20 18:41:34 -07001371 result.name = getTokenSpelling();
1372 result.number = 0;
1373 result.loc = getToken().getLoc();
Chris Lattner7f9cc272018-07-19 08:35:28 -07001374 if (!consumeIf(Token::percent_identifier))
1375 return emitError("expected SSA operand");
Chris Lattner6119d382018-07-20 18:41:34 -07001376
1377 // If we have an affine map ID, it is a result number.
1378 if (getToken().is(Token::hash_identifier)) {
1379 if (auto value = getToken().getHashIdentifierNumber())
1380 result.number = value.getValue();
1381 else
1382 return emitError("invalid SSA value result number");
1383 consumeToken(Token::hash_identifier);
1384 }
1385
Chris Lattner7f9cc272018-07-19 08:35:28 -07001386 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001387}
1388
1389/// Parse a (possibly empty) list of SSA operands.
1390///
1391/// ssa-use-list ::= ssa-use (`,` ssa-use)*
1392/// ssa-use-list-opt ::= ssa-use-list?
1393///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001394ParseResult
Chris Lattner40746442018-07-21 14:32:09 -07001395FunctionParser::parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results) {
1396 if (!getToken().is(Token::percent_identifier))
1397 return ParseSuccess;
1398 return parseCommaSeparatedList([&]() -> ParseResult {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001399 SSAUseInfo result;
1400 if (parseSSAUse(result))
1401 return ParseFailure;
1402 results.push_back(result);
1403 return ParseSuccess;
1404 });
Chris Lattner78276e32018-07-07 15:48:26 -07001405}
1406
1407/// Parse an SSA use with an associated type.
1408///
1409/// ssa-use-and-type ::= ssa-use `:` type
James Molloy61a656c2018-07-22 15:45:24 -07001410template <typename ResultType>
1411ResultType FunctionParser::parseSSADefOrUseAndType(
1412 const std::function<ResultType(SSAUseInfo, Type *)> &action) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001413 SSAUseInfo useInfo;
1414 if (parseSSAUse(useInfo))
1415 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001416
1417 if (!consumeIf(Token::colon))
Chris Lattner7f9cc272018-07-19 08:35:28 -07001418 return (emitError("expected ':' and type for SSA operand"), nullptr);
Chris Lattner78276e32018-07-07 15:48:26 -07001419
Chris Lattner7f9cc272018-07-19 08:35:28 -07001420 auto *type = parseType();
1421 if (!type)
1422 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001423
James Molloy61a656c2018-07-22 15:45:24 -07001424 return action(useInfo, type);
Chris Lattner78276e32018-07-07 15:48:26 -07001425}
1426
1427/// Parse a (possibly empty) list of SSA operands with types.
1428///
1429/// ssa-use-and-type-list ::= ssa-use-and-type (`,` ssa-use-and-type)*
1430///
Chris Lattner40746442018-07-21 14:32:09 -07001431template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001432ParseResult FunctionParser::parseOptionalSSAUseAndTypeList(
Chris Lattner40746442018-07-21 14:32:09 -07001433 SmallVectorImpl<ValueTy *> &results) {
1434 if (getToken().isNot(Token::percent_identifier))
1435 return ParseSuccess;
1436
1437 return parseCommaSeparatedList([&]() -> ParseResult {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001438 if (auto *value = parseSSAUseAndType()) {
Chris Lattner40746442018-07-21 14:32:09 -07001439 results.push_back(cast<ValueTy>(value));
Chris Lattner7f9cc272018-07-19 08:35:28 -07001440 return ParseSuccess;
1441 }
1442 return ParseFailure;
1443 });
Chris Lattner78276e32018-07-07 15:48:26 -07001444}
1445
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001446/// Parse the CFG or MLFunc operation.
1447///
1448/// TODO(clattner): This is a change from the MLIR spec as written, it is an
1449/// experiment that will eliminate "builtin" instructions as a thing.
1450///
1451/// operation ::=
1452/// (ssa-id `=`)? string '(' ssa-use-list? ')' attribute-dict?
1453/// `:` function-type
1454///
1455ParseResult
Chris Lattner7f9cc272018-07-19 08:35:28 -07001456FunctionParser::parseOperation(const CreateOperationFunction &createOpFunc) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001457 auto loc = getToken().getLoc();
1458
1459 StringRef resultID;
1460 if (getToken().is(Token::percent_identifier)) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001461 resultID = getTokenSpelling();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001462 consumeToken(Token::percent_identifier);
1463 if (!consumeIf(Token::equal))
1464 return emitError("expected '=' after SSA name");
1465 }
1466
1467 if (getToken().isNot(Token::string))
1468 return emitError("expected operation name in quotes");
1469
1470 auto name = getToken().getStringValue();
1471 if (name.empty())
1472 return emitError("empty operation name is invalid");
1473
1474 consumeToken(Token::string);
1475
1476 if (!consumeIf(Token::l_paren))
1477 return emitError("expected '(' to start operand list");
1478
1479 // Parse the operand list.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001480 SmallVector<SSAUseInfo, 8> operandInfos;
Chris Lattner40746442018-07-21 14:32:09 -07001481 if (parseOptionalSSAUseList(operandInfos))
1482 return ParseFailure;
1483
1484 if (!consumeIf(Token::r_paren))
1485 return emitError("expected ')' to end operand list");
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001486
1487 SmallVector<NamedAttribute, 4> attributes;
1488 if (getToken().is(Token::l_brace)) {
1489 if (parseAttributeDict(attributes))
1490 return ParseFailure;
1491 }
1492
Chris Lattner3b2ef762018-07-18 15:31:25 -07001493 if (!consumeIf(Token::colon))
1494 return emitError("expected ':' followed by instruction type");
1495
1496 auto typeLoc = getToken().getLoc();
1497 auto type = parseType();
1498 if (!type)
1499 return ParseFailure;
1500 auto fnType = dyn_cast<FunctionType>(type);
1501 if (!fnType)
1502 return emitError(typeLoc, "expected function type");
1503
Chris Lattner7f9cc272018-07-19 08:35:28 -07001504 // Check that we have the right number of types for the operands.
1505 auto operandTypes = fnType->getInputs();
1506 if (operandTypes.size() != operandInfos.size()) {
1507 auto plural = "s"[operandInfos.size() == 1];
1508 return emitError(typeLoc, "expected " + llvm::utostr(operandInfos.size()) +
Chris Lattnerf8cce872018-07-20 09:28:54 -07001509 " operand type" + plural + " but had " +
Chris Lattner7f9cc272018-07-19 08:35:28 -07001510 llvm::utostr(operandTypes.size()));
1511 }
1512
1513 // Resolve all of the operands.
1514 SmallVector<SSAValue *, 8> operands;
1515 for (unsigned i = 0, e = operandInfos.size(); i != e; ++i) {
1516 operands.push_back(resolveSSAUse(operandInfos[i], operandTypes[i]));
1517 if (!operands.back())
1518 return ParseFailure;
1519 }
1520
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001521 auto nameId = builder.getIdentifier(name);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001522 auto op = createOpFunc(nameId, operands, fnType->getResults(), attributes);
1523 if (!op)
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001524 return ParseFailure;
1525
1526 // We just parsed an operation. If it is a recognized one, verify that it
1527 // is structurally as we expect. If not, produce an error with a reasonable
1528 // source location.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001529 if (auto *opInfo = op->getAbstractOperation(builder.getContext())) {
1530 if (auto error = opInfo->verifyInvariants(op))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001531 return emitError(loc, error);
1532 }
1533
Chris Lattner7f9cc272018-07-19 08:35:28 -07001534 // If the instruction had a name, register it.
1535 if (!resultID.empty()) {
1536 // FIXME: Add result infra to handle Stmt results as well to make this
1537 // generic.
1538 if (auto *inst = dyn_cast<OperationInst>(op)) {
Chris Lattnerf8cce872018-07-20 09:28:54 -07001539 if (inst->getNumResults() == 0)
Chris Lattner7f9cc272018-07-19 08:35:28 -07001540 return emitError(loc, "cannot name an operation with no results");
1541
Chris Lattner6119d382018-07-20 18:41:34 -07001542 for (unsigned i = 0, e = inst->getNumResults(); i != e; ++i)
1543 addDefinition({resultID, i, loc}, inst->getResult(i));
Chris Lattner7f9cc272018-07-19 08:35:28 -07001544 }
1545 }
1546
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001547 return ParseSuccess;
1548}
Chris Lattnere79379a2018-06-22 10:39:19 -07001549
Chris Lattner48af7d12018-07-09 19:05:38 -07001550//===----------------------------------------------------------------------===//
1551// CFG Functions
1552//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001553
Chris Lattner4c95a502018-06-23 16:03:42 -07001554namespace {
Chris Lattner48af7d12018-07-09 19:05:38 -07001555/// This is a specialized parser for CFGFunction's, maintaining the state
1556/// transient to their bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001557class CFGFunctionParser : public FunctionParser {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001558public:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001559 CFGFunctionParser(ParserState &state, CFGFunction *function)
Chris Lattner7f9cc272018-07-19 08:35:28 -07001560 : FunctionParser(state), function(function), builder(function) {}
Chris Lattner2e595eb2018-07-10 10:08:27 -07001561
1562 ParseResult parseFunctionBody();
1563
1564private:
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001565 CFGFunction *function;
1566 llvm::StringMap<std::pair<BasicBlock*, SMLoc>> blocksByName;
Chris Lattner48af7d12018-07-09 19:05:38 -07001567
1568 /// This builder intentionally shadows the builder in the base class, with a
1569 /// more specific builder type.
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001570 CFGFuncBuilder builder;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001571
Chris Lattner4c95a502018-06-23 16:03:42 -07001572 /// Get the basic block with the specified name, creating it if it doesn't
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001573 /// already exist. The location specified is the point of use, which allows
1574 /// us to diagnose references to blocks that are not defined precisely.
1575 BasicBlock *getBlockNamed(StringRef name, SMLoc loc) {
1576 auto &blockAndLoc = blocksByName[name];
1577 if (!blockAndLoc.first) {
Chris Lattner3a467cc2018-07-01 20:28:00 -07001578 blockAndLoc.first = new BasicBlock();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001579 blockAndLoc.second = loc;
Chris Lattner4c95a502018-06-23 16:03:42 -07001580 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001581 return blockAndLoc.first;
Chris Lattner4c95a502018-06-23 16:03:42 -07001582 }
Chris Lattner48af7d12018-07-09 19:05:38 -07001583
James Molloy61a656c2018-07-22 15:45:24 -07001584 ParseResult
1585 parseOptionalBasicBlockArgList(SmallVectorImpl<BBArgument *> &results,
1586 BasicBlock *owner);
1587
Chris Lattner48af7d12018-07-09 19:05:38 -07001588 ParseResult parseBasicBlock();
1589 OperationInst *parseCFGOperation();
1590 TerminatorInst *parseTerminator();
Chris Lattner4c95a502018-06-23 16:03:42 -07001591};
1592} // end anonymous namespace
1593
James Molloy61a656c2018-07-22 15:45:24 -07001594/// Parse a (possibly empty) list of SSA operands with types as basic block
1595/// arguments. Unlike parseOptionalSsaUseAndTypeList the SSA IDs are treated as
1596/// defs, not uses.
1597///
1598/// ssa-id-and-type-list ::= ssa-id-and-type (`,` ssa-id-and-type)*
1599///
1600ParseResult CFGFunctionParser::parseOptionalBasicBlockArgList(
1601 SmallVectorImpl<BBArgument *> &results, BasicBlock *owner) {
1602 if (getToken().is(Token::r_brace))
1603 return ParseSuccess;
1604
1605 return parseCommaSeparatedList([&]() -> ParseResult {
1606 auto type = parseSSADefOrUseAndType<Type *>(
1607 [&](SSAUseInfo useInfo, Type *type) -> Type * {
1608 BBArgument *arg = owner->addArgument(type);
1609 if (addDefinition(useInfo, arg) == ParseFailure)
1610 return nullptr;
1611 return type;
1612 });
1613 return type ? ParseSuccess : ParseFailure;
1614 });
1615}
1616
Chris Lattner48af7d12018-07-09 19:05:38 -07001617ParseResult CFGFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07001618 auto braceLoc = getToken().getLoc();
Chris Lattner48af7d12018-07-09 19:05:38 -07001619 if (!consumeIf(Token::l_brace))
1620 return emitError("expected '{' in CFG function");
1621
1622 // Make sure we have at least one block.
1623 if (getToken().is(Token::r_brace))
1624 return emitError("CFG functions must have at least one basic block");
Chris Lattner4c95a502018-06-23 16:03:42 -07001625
1626 // Parse the list of blocks.
1627 while (!consumeIf(Token::r_brace))
Chris Lattner48af7d12018-07-09 19:05:38 -07001628 if (parseBasicBlock())
Chris Lattner4c95a502018-06-23 16:03:42 -07001629 return ParseFailure;
1630
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001631 // Verify that all referenced blocks were defined. Iteration over a
1632 // StringMap isn't determinstic, but this is good enough for our purposes.
Chris Lattner48af7d12018-07-09 19:05:38 -07001633 for (auto &elt : blocksByName) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001634 auto *bb = elt.second.first;
Chris Lattner3a467cc2018-07-01 20:28:00 -07001635 if (!bb->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001636 return emitError(elt.second.second,
1637 "reference to an undefined basic block '" +
1638 elt.first() + "'");
1639 }
1640
Chris Lattner48af7d12018-07-09 19:05:38 -07001641 getModule()->functionList.push_back(function);
Chris Lattner6119d382018-07-20 18:41:34 -07001642
Chris Lattner40746442018-07-21 14:32:09 -07001643 return finalizeFunction(function, braceLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001644}
1645
1646/// Basic block declaration.
1647///
1648/// basic-block ::= bb-label instruction* terminator-stmt
1649/// bb-label ::= bb-id bb-arg-list? `:`
1650/// bb-id ::= bare-id
1651/// bb-arg-list ::= `(` ssa-id-and-type-list? `)`
1652///
Chris Lattner48af7d12018-07-09 19:05:38 -07001653ParseResult CFGFunctionParser::parseBasicBlock() {
1654 SMLoc nameLoc = getToken().getLoc();
1655 auto name = getTokenSpelling();
Chris Lattner4c95a502018-06-23 16:03:42 -07001656 if (!consumeIf(Token::bare_identifier))
1657 return emitError("expected basic block name");
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001658
Chris Lattner48af7d12018-07-09 19:05:38 -07001659 auto *block = getBlockNamed(name, nameLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001660
1661 // If this block has already been parsed, then this is a redefinition with the
1662 // same block name.
Chris Lattner3a467cc2018-07-01 20:28:00 -07001663 if (block->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001664 return emitError(nameLoc, "redefinition of block '" + name.str() + "'");
1665
Chris Lattner78276e32018-07-07 15:48:26 -07001666 // If an argument list is present, parse it.
1667 if (consumeIf(Token::l_paren)) {
James Molloy61a656c2018-07-22 15:45:24 -07001668 SmallVector<BBArgument *, 8> bbArgs;
1669 if (parseOptionalBasicBlockArgList(bbArgs, block))
Chris Lattner78276e32018-07-07 15:48:26 -07001670 return ParseFailure;
Chris Lattner40746442018-07-21 14:32:09 -07001671 if (!consumeIf(Token::r_paren))
1672 return emitError("expected ')' to end argument list");
Chris Lattner78276e32018-07-07 15:48:26 -07001673 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001674
James Molloy61a656c2018-07-22 15:45:24 -07001675 // Add the block to the function.
1676 function->push_back(block);
1677
Chris Lattner4c95a502018-06-23 16:03:42 -07001678 if (!consumeIf(Token::colon))
1679 return emitError("expected ':' after basic block name");
1680
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001681 // Set the insertion point to the block we want to insert new operations into.
Chris Lattner48af7d12018-07-09 19:05:38 -07001682 builder.setInsertionPoint(block);
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001683
Chris Lattner7f9cc272018-07-19 08:35:28 -07001684 auto createOpFunc = [&](Identifier name, ArrayRef<SSAValue *> operands,
1685 ArrayRef<Type *> resultTypes,
1686 ArrayRef<NamedAttribute> attrs) -> Operation * {
1687 SmallVector<CFGValue *, 8> cfgOperands;
1688 cfgOperands.reserve(operands.size());
1689 for (auto *op : operands)
1690 cfgOperands.push_back(cast<CFGValue>(op));
1691 return builder.createOperation(name, cfgOperands, resultTypes, attrs);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001692 };
1693
Chris Lattnered65a732018-06-28 20:45:33 -07001694 // Parse the list of operations that make up the body of the block.
Chris Lattner48af7d12018-07-09 19:05:38 -07001695 while (getToken().isNot(Token::kw_return, Token::kw_br)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001696 if (parseOperation(createOpFunc))
Chris Lattnered65a732018-06-28 20:45:33 -07001697 return ParseFailure;
1698 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001699
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001700 if (!parseTerminator())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001701 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07001702
1703 return ParseSuccess;
1704}
1705
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001706/// Parse the terminator instruction for a basic block.
1707///
1708/// terminator-stmt ::= `br` bb-id branch-use-list?
1709/// branch-use-list ::= `(` ssa-use-and-type-list? `)`
1710/// terminator-stmt ::=
1711/// `cond_br` ssa-use `,` bb-id branch-use-list? `,` bb-id branch-use-list?
1712/// terminator-stmt ::= `return` ssa-use-and-type-list?
1713///
Chris Lattner48af7d12018-07-09 19:05:38 -07001714TerminatorInst *CFGFunctionParser::parseTerminator() {
1715 switch (getToken().getKind()) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001716 default:
Chris Lattner3a467cc2018-07-01 20:28:00 -07001717 return (emitError("expected terminator at end of basic block"), nullptr);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001718
Chris Lattner40746442018-07-21 14:32:09 -07001719 case Token::kw_return: {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001720 consumeToken(Token::kw_return);
Chris Lattner40746442018-07-21 14:32:09 -07001721 SmallVector<CFGValue *, 8> results;
1722 if (parseOptionalSSAUseAndTypeList(results))
1723 return nullptr;
1724
1725 return builder.createReturnInst(results);
1726 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001727
1728 case Token::kw_br: {
1729 consumeToken(Token::kw_br);
Chris Lattner48af7d12018-07-09 19:05:38 -07001730 auto destBB = getBlockNamed(getTokenSpelling(), getToken().getLoc());
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001731 if (!consumeIf(Token::bare_identifier))
Chris Lattner3a467cc2018-07-01 20:28:00 -07001732 return (emitError("expected basic block name"), nullptr);
Chris Lattner48af7d12018-07-09 19:05:38 -07001733 return builder.createBranchInst(destBB);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001734 }
Chris Lattner78276e32018-07-07 15:48:26 -07001735 // TODO: cond_br.
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001736 }
1737}
1738
Chris Lattner48af7d12018-07-09 19:05:38 -07001739//===----------------------------------------------------------------------===//
1740// ML Functions
1741//===----------------------------------------------------------------------===//
1742
1743namespace {
1744/// Refined parser for MLFunction bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001745class MLFunctionParser : public FunctionParser {
Chris Lattner48af7d12018-07-09 19:05:38 -07001746public:
Chris Lattner48af7d12018-07-09 19:05:38 -07001747 MLFunctionParser(ParserState &state, MLFunction *function)
Chris Lattner7f9cc272018-07-19 08:35:28 -07001748 : FunctionParser(state), function(function), builder(function) {}
Chris Lattner48af7d12018-07-09 19:05:38 -07001749
1750 ParseResult parseFunctionBody();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001751
1752private:
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001753 MLFunction *function;
1754
1755 /// This builder intentionally shadows the builder in the base class, with a
1756 /// more specific builder type.
1757 MLFuncBuilder builder;
1758
1759 ParseResult parseForStmt();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001760 AffineConstantExpr *parseIntConstant();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001761 ParseResult parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001762 ParseResult parseElseClause(IfClause *elseClause);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001763 ParseResult parseStatements(StmtBlock *block);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001764 ParseResult parseStmtBlock(StmtBlock *block);
Chris Lattner48af7d12018-07-09 19:05:38 -07001765};
1766} // end anonymous namespace
1767
Chris Lattner48af7d12018-07-09 19:05:38 -07001768ParseResult MLFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07001769 auto braceLoc = getToken().getLoc();
Chris Lattner48af7d12018-07-09 19:05:38 -07001770 if (!consumeIf(Token::l_brace))
1771 return emitError("expected '{' in ML function");
1772
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001773 // Parse statements in this function
1774 if (parseStatements(function))
1775 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001776
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001777 if (!consumeIf(Token::kw_return))
1778 emitError("ML function must end with return statement");
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001779
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001780 // TODO: store return operands in the IR.
1781 SmallVector<SSAUseInfo, 4> dummyUseInfo;
Chris Lattner40746442018-07-21 14:32:09 -07001782 if (parseOptionalSSAUseList(dummyUseInfo))
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001783 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001784
Chris Lattner40746442018-07-21 14:32:09 -07001785 if (!consumeIf(Token::r_brace))
1786 return emitError("expected '}' to end mlfunc");
1787
Chris Lattner48af7d12018-07-09 19:05:38 -07001788 getModule()->functionList.push_back(function);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001789
Chris Lattner40746442018-07-21 14:32:09 -07001790 return finalizeFunction(function, braceLoc);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001791}
1792
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001793/// For statement.
1794///
Chris Lattner48af7d12018-07-09 19:05:38 -07001795/// ml-for-stmt ::= `for` ssa-id `=` lower-bound `to` upper-bound
1796/// (`step` integer-literal)? `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001797///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001798ParseResult MLFunctionParser::parseForStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001799 consumeToken(Token::kw_for);
1800
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001801 // Parse induction variable
1802 if (getToken().isNot(Token::percent_identifier))
1803 return emitError("expected SSA identifier for the loop variable");
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001804
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001805 // TODO: create SSA value definition from name
1806 StringRef name = getTokenSpelling().drop_front();
1807 (void)name;
1808
1809 consumeToken(Token::percent_identifier);
1810
1811 if (!consumeIf(Token::equal))
1812 return emitError("expected =");
1813
1814 // Parse loop bounds
1815 AffineConstantExpr *lowerBound = parseIntConstant();
1816 if (!lowerBound)
1817 return ParseFailure;
1818
1819 if (!consumeIf(Token::kw_to))
1820 return emitError("expected 'to' between bounds");
1821
1822 AffineConstantExpr *upperBound = parseIntConstant();
1823 if (!upperBound)
1824 return ParseFailure;
1825
1826 // Parse step
1827 AffineConstantExpr *step = nullptr;
1828 if (consumeIf(Token::kw_step)) {
1829 step = parseIntConstant();
1830 if (!step)
1831 return ParseFailure;
1832 }
1833
1834 // Create for statement.
1835 ForStmt *stmt = builder.createFor(lowerBound, upperBound, step);
1836
1837 // If parsing of the for statement body fails,
1838 // MLIR contains for statement with those nested statements that have been
1839 // successfully parsed.
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001840 if (parseStmtBlock(static_cast<StmtBlock *>(stmt)))
1841 return ParseFailure;
1842
1843 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001844}
1845
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001846// This method is temporary workaround to parse simple loop bounds and
1847// step.
1848// TODO: remove this method once it's no longer used.
1849AffineConstantExpr *MLFunctionParser::parseIntConstant() {
1850 if (getToken().isNot(Token::integer))
1851 return (emitError("expected non-negative integer for now"), nullptr);
1852
1853 auto val = getToken().getUInt64IntegerValue();
1854 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
1855 return (emitError("constant too large for affineint"), nullptr);
1856 }
1857 consumeToken(Token::integer);
1858 return builder.getConstantExpr((int64_t)val.getValue());
1859}
1860
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001861/// If statement.
1862///
Chris Lattner48af7d12018-07-09 19:05:38 -07001863/// ml-if-head ::= `if` ml-if-cond `{` ml-stmt* `}`
1864/// | ml-if-head `else` `if` ml-if-cond `{` ml-stmt* `}`
1865/// ml-if-stmt ::= ml-if-head
1866/// | ml-if-head `else` `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001867///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001868ParseResult MLFunctionParser::parseIfStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001869 consumeToken(Token::kw_if);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001870 if (!consumeIf(Token::l_paren))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001871 return emitError("expected (");
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001872
1873 //TODO: parse condition
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001874
1875 if (!consumeIf(Token::r_paren))
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001876 return emitError("expected ')'");
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001877
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001878 IfStmt *ifStmt = builder.createIf();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001879 IfClause *thenClause = ifStmt->getThenClause();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001880
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001881 // When parsing of an if statement body fails, the IR contains
1882 // the if statement with the portion of the body that has been
1883 // successfully parsed.
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001884 if (parseStmtBlock(thenClause))
1885 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001886
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001887 if (consumeIf(Token::kw_else)) {
1888 IfClause *elseClause = ifStmt->createElseClause();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001889 if (parseElseClause(elseClause))
1890 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001891 }
1892
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001893 return ParseSuccess;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001894}
1895
1896ParseResult MLFunctionParser::parseElseClause(IfClause *elseClause) {
1897 if (getToken().is(Token::kw_if)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001898 builder.setInsertionPoint(elseClause);
1899 return parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001900 }
1901
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001902 return parseStmtBlock(elseClause);
1903}
1904
1905///
1906/// Parse a list of statements ending with `return` or `}`
1907///
1908ParseResult MLFunctionParser::parseStatements(StmtBlock *block) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001909 auto createOpFunc = [&](Identifier name, ArrayRef<SSAValue *> operands,
1910 ArrayRef<Type *> resultTypes,
1911 ArrayRef<NamedAttribute> attrs) -> Operation * {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001912 return builder.createOperation(name, attrs);
1913 };
1914
1915 builder.setInsertionPoint(block);
1916
1917 while (getToken().isNot(Token::kw_return, Token::r_brace)) {
1918 switch (getToken().getKind()) {
1919 default:
1920 if (parseOperation(createOpFunc))
1921 return ParseFailure;
1922 break;
1923 case Token::kw_for:
1924 if (parseForStmt())
1925 return ParseFailure;
1926 break;
1927 case Token::kw_if:
1928 if (parseIfStmt())
1929 return ParseFailure;
1930 break;
1931 } // end switch
1932 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001933
1934 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001935}
1936
1937///
1938/// Parse `{` ml-stmt* `}`
1939///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001940ParseResult MLFunctionParser::parseStmtBlock(StmtBlock *block) {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001941 if (!consumeIf(Token::l_brace))
1942 return emitError("expected '{' before statement list");
1943
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001944 if (parseStatements(block))
1945 return ParseFailure;
1946
1947 if (!consumeIf(Token::r_brace))
1948 return emitError("expected '}' at the end of the statement block");
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001949
1950 return ParseSuccess;
1951}
1952
Chris Lattner4c95a502018-06-23 16:03:42 -07001953//===----------------------------------------------------------------------===//
1954// Top-level entity parsing.
1955//===----------------------------------------------------------------------===//
1956
Chris Lattner2e595eb2018-07-10 10:08:27 -07001957namespace {
1958/// This parser handles entities that are only valid at the top level of the
1959/// file.
1960class ModuleParser : public Parser {
1961public:
1962 explicit ModuleParser(ParserState &state) : Parser(state) {}
1963
1964 ParseResult parseModule();
1965
1966private:
1967 ParseResult parseAffineMapDef();
1968
1969 // Functions.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001970 ParseResult parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
1971 SmallVectorImpl<StringRef> &argNames);
1972 ParseResult parseFunctionSignature(StringRef &name, FunctionType *&type,
1973 SmallVectorImpl<StringRef> *argNames);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001974 ParseResult parseExtFunc();
1975 ParseResult parseCFGFunc();
1976 ParseResult parseMLFunc();
1977};
1978} // end anonymous namespace
1979
1980/// Affine map declaration.
1981///
1982/// affine-map-def ::= affine-map-id `=` affine-map-inline
1983///
1984ParseResult ModuleParser::parseAffineMapDef() {
1985 assert(getToken().is(Token::hash_identifier));
1986
1987 StringRef affineMapId = getTokenSpelling().drop_front();
1988
1989 // Check for redefinitions.
1990 auto *&entry = getState().affineMapDefinitions[affineMapId];
1991 if (entry)
1992 return emitError("redefinition of affine map id '" + affineMapId + "'");
1993
1994 consumeToken(Token::hash_identifier);
1995
1996 // Parse the '='
1997 if (!consumeIf(Token::equal))
1998 return emitError("expected '=' in affine map outlined definition");
1999
2000 entry = parseAffineMapInline();
2001 if (!entry)
2002 return ParseFailure;
2003
Chris Lattner2e595eb2018-07-10 10:08:27 -07002004 return ParseSuccess;
2005}
2006
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002007/// Parse a (possibly empty) list of MLFunction arguments with types.
2008///
2009/// ml-argument ::= ssa-id `:` type
2010/// ml-argument-list ::= ml-argument (`,` ml-argument)* | /*empty*/
2011///
2012ParseResult
2013ModuleParser::parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2014 SmallVectorImpl<StringRef> &argNames) {
2015 auto parseElt = [&]() -> ParseResult {
2016 // Parse argument name
2017 if (getToken().isNot(Token::percent_identifier))
2018 return emitError("expected SSA identifier");
2019
2020 StringRef name = getTokenSpelling().drop_front();
2021 consumeToken(Token::percent_identifier);
2022 argNames.push_back(name);
2023
2024 if (!consumeIf(Token::colon))
2025 return emitError("expected ':'");
2026
2027 // Parse argument type
2028 auto elt = parseType();
2029 if (!elt)
2030 return ParseFailure;
2031 argTypes.push_back(elt);
2032
2033 return ParseSuccess;
2034 };
2035
2036 if (!consumeIf(Token::l_paren))
2037 llvm_unreachable("expected '('");
2038
Chris Lattner40746442018-07-21 14:32:09 -07002039 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002040}
2041
Chris Lattner2e595eb2018-07-10 10:08:27 -07002042/// Parse a function signature, starting with a name and including the parameter
2043/// list.
2044///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002045/// argument-list ::= type (`,` type)* | /*empty*/ | ml-argument-list
Chris Lattner2e595eb2018-07-10 10:08:27 -07002046/// function-signature ::= function-id `(` argument-list `)` (`->` type-list)?
2047///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002048ParseResult
2049ModuleParser::parseFunctionSignature(StringRef &name, FunctionType *&type,
2050 SmallVectorImpl<StringRef> *argNames) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002051 if (getToken().isNot(Token::at_identifier))
2052 return emitError("expected a function identifier like '@foo'");
2053
2054 name = getTokenSpelling().drop_front();
2055 consumeToken(Token::at_identifier);
2056
2057 if (getToken().isNot(Token::l_paren))
2058 return emitError("expected '(' in function signature");
2059
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002060 SmallVector<Type *, 4> argTypes;
2061 ParseResult parseResult;
2062
2063 if (argNames)
2064 parseResult = parseMLArgumentList(argTypes, *argNames);
2065 else
2066 parseResult = parseTypeList(argTypes);
2067
2068 if (parseResult)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002069 return ParseFailure;
2070
2071 // Parse the return type if present.
2072 SmallVector<Type *, 4> results;
2073 if (consumeIf(Token::arrow)) {
2074 if (parseTypeList(results))
2075 return ParseFailure;
2076 }
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002077 type = builder.getFunctionType(argTypes, results);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002078 return ParseSuccess;
2079}
2080
2081/// External function declarations.
2082///
2083/// ext-func ::= `extfunc` function-signature
2084///
2085ParseResult ModuleParser::parseExtFunc() {
2086 consumeToken(Token::kw_extfunc);
2087
2088 StringRef name;
2089 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002090 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002091 return ParseFailure;
2092
2093 // Okay, the external function definition was parsed correctly.
2094 getModule()->functionList.push_back(new ExtFunction(name, type));
2095 return ParseSuccess;
2096}
2097
2098/// CFG function declarations.
2099///
2100/// cfg-func ::= `cfgfunc` function-signature `{` basic-block+ `}`
2101///
2102ParseResult ModuleParser::parseCFGFunc() {
2103 consumeToken(Token::kw_cfgfunc);
2104
2105 StringRef name;
2106 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002107 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002108 return ParseFailure;
2109
2110 // Okay, the CFG function signature was parsed correctly, create the function.
2111 auto function = new CFGFunction(name, type);
2112
2113 return CFGFunctionParser(getState(), function).parseFunctionBody();
2114}
2115
2116/// ML function declarations.
2117///
2118/// ml-func ::= `mlfunc` ml-func-signature `{` ml-stmt* ml-return-stmt `}`
2119///
2120ParseResult ModuleParser::parseMLFunc() {
2121 consumeToken(Token::kw_mlfunc);
2122
2123 StringRef name;
2124 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002125 SmallVector<StringRef, 4> argNames;
Chris Lattner2e595eb2018-07-10 10:08:27 -07002126 // FIXME: Parse ML function signature (args + types)
2127 // by passing pointer to SmallVector<identifier> into parseFunctionSignature
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002128
2129 if (parseFunctionSignature(name, type, &argNames))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002130 return ParseFailure;
2131
2132 // Okay, the ML function signature was parsed correctly, create the function.
2133 auto function = new MLFunction(name, type);
2134
2135 return MLFunctionParser(getState(), function).parseFunctionBody();
2136}
2137
Chris Lattnere79379a2018-06-22 10:39:19 -07002138/// This is the top-level module parser.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002139ParseResult ModuleParser::parseModule() {
Chris Lattnere79379a2018-06-22 10:39:19 -07002140 while (1) {
Chris Lattner48af7d12018-07-09 19:05:38 -07002141 switch (getToken().getKind()) {
Chris Lattnere79379a2018-06-22 10:39:19 -07002142 default:
2143 emitError("expected a top level entity");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002144 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002145
Uday Bondhugula015cbb12018-07-03 20:16:08 -07002146 // If we got to the end of the file, then we're done.
Chris Lattnere79379a2018-06-22 10:39:19 -07002147 case Token::eof:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002148 return ParseSuccess;
Chris Lattnere79379a2018-06-22 10:39:19 -07002149
2150 // If we got an error token, then the lexer already emitted an error, just
2151 // stop. Someday we could introduce error recovery if there was demand for
2152 // it.
2153 case Token::error:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002154 return ParseFailure;
2155
2156 case Token::hash_identifier:
2157 if (parseAffineMapDef())
2158 return ParseFailure;
2159 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002160
2161 case Token::kw_extfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002162 if (parseExtFunc())
2163 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002164 break;
2165
Chris Lattner4c95a502018-06-23 16:03:42 -07002166 case Token::kw_cfgfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002167 if (parseCFGFunc())
2168 return ParseFailure;
MLIR Teamf85a6262018-06-27 11:03:08 -07002169 break;
Chris Lattner4c95a502018-06-23 16:03:42 -07002170
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002171 case Token::kw_mlfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002172 if (parseMLFunc())
2173 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002174 break;
2175
Uday Bondhugula015cbb12018-07-03 20:16:08 -07002176 // TODO: affine entity declarations, etc.
Chris Lattnere79379a2018-06-22 10:39:19 -07002177 }
2178 }
2179}
2180
2181//===----------------------------------------------------------------------===//
2182
Jacques Pienaar7b829702018-07-03 13:24:09 -07002183void mlir::defaultErrorReporter(const llvm::SMDiagnostic &error) {
2184 const auto &sourceMgr = *error.getSourceMgr();
2185 sourceMgr.PrintMessage(error.getLoc(), error.getKind(), error.getMessage());
2186}
2187
Chris Lattnere79379a2018-06-22 10:39:19 -07002188/// This parses the file specified by the indicated SourceMgr and returns an
2189/// MLIR module if it was valid. If not, it emits diagnostics and returns null.
Jacques Pienaar9c411be2018-06-24 19:17:35 -07002190Module *mlir::parseSourceFile(llvm::SourceMgr &sourceMgr, MLIRContext *context,
Jacques Pienaar7b829702018-07-03 13:24:09 -07002191 SMDiagnosticHandlerTy errorReporter) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002192 // This is the result module we are parsing into.
2193 std::unique_ptr<Module> module(new Module(context));
2194
2195 ParserState state(sourceMgr, module.get(),
Jacques Pienaar0bffd862018-07-11 13:26:23 -07002196 errorReporter ? errorReporter : defaultErrorReporter);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002197 if (ModuleParser(state).parseModule())
2198 return nullptr;
Chris Lattner21e67f62018-07-06 10:46:19 -07002199
2200 // Make sure the parse module has no other structural problems detected by the
2201 // verifier.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002202 module->verify();
2203 return module.release();
Chris Lattnere79379a2018-06-22 10:39:19 -07002204}