blob: 1fd3432742e2270e509fb759c7efd8a29a5f59ce [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
MLIR Team718c82f2018-07-16 09:45:22 -0700140 ParseResult parseCommaSeparatedList(
141 Token::Kind rightToken,
142 const std::function<ParseResult()> &parseElement,
143 bool allowEmptyList = true);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700144
Chris Lattnerf7e22732018-06-22 22:03:48 -0700145 // We have two forms of parsing methods - those that return a non-null
146 // pointer on success, and those that return a ParseResult to indicate whether
147 // they returned a failure. The second class fills in by-reference arguments
148 // as the results of their action.
149
Chris Lattnere79379a2018-06-22 10:39:19 -0700150 // Type parsing.
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700151 Type *parsePrimitiveType();
Chris Lattnerf7e22732018-06-22 22:03:48 -0700152 Type *parseElementType();
153 VectorType *parseVectorType();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700154 ParseResult parseDimensionListRanked(SmallVectorImpl<int> &dimensions);
Chris Lattnerf7e22732018-06-22 22:03:48 -0700155 Type *parseTensorType();
156 Type *parseMemRefType();
157 Type *parseFunctionType();
158 Type *parseType();
159 ParseResult parseTypeList(SmallVectorImpl<Type*> &elements);
Chris Lattnere79379a2018-06-22 10:39:19 -0700160
Chris Lattner7121b802018-07-04 20:45:39 -0700161 // Attribute parsing.
162 Attribute *parseAttribute();
163 ParseResult parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes);
164
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700165 // Polyhedral structures.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700166 AffineMap *parseAffineMapInline();
MLIR Team718c82f2018-07-16 09:45:22 -0700167 AffineMap *parseAffineMapReference();
MLIR Teamf85a6262018-06-27 11:03:08 -0700168
Chris Lattner48af7d12018-07-09 19:05:38 -0700169private:
170 // The Parser is subclassed and reinstantiated. Do not add additional
171 // non-trivial state here, add it to the ParserState class.
172 ParserState &state;
Chris Lattnere79379a2018-06-22 10:39:19 -0700173};
174} // end anonymous namespace
175
176//===----------------------------------------------------------------------===//
177// Helper methods.
178//===----------------------------------------------------------------------===//
179
Chris Lattner4c95a502018-06-23 16:03:42 -0700180ParseResult Parser::emitError(SMLoc loc, const Twine &message) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700181 // If we hit a parse error in response to a lexer error, then the lexer
Jacques Pienaar9c411be2018-06-24 19:17:35 -0700182 // already reported the error.
Chris Lattner48af7d12018-07-09 19:05:38 -0700183 if (getToken().is(Token::error))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700184 return ParseFailure;
185
Chris Lattner48af7d12018-07-09 19:05:38 -0700186 auto &sourceMgr = state.lex.getSourceMgr();
187 state.errorReporter(sourceMgr.GetMessage(loc, SourceMgr::DK_Error, message));
Chris Lattnere79379a2018-06-22 10:39:19 -0700188 return ParseFailure;
189}
190
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700191/// Parse a comma-separated list of elements, terminated with an arbitrary
192/// token. This allows empty lists if allowEmptyList is true.
193///
194/// abstract-list ::= rightToken // if allowEmptyList == true
195/// abstract-list ::= element (',' element)* rightToken
196///
197ParseResult Parser::
Chris Lattner8da0c282018-06-29 11:15:56 -0700198parseCommaSeparatedList(Token::Kind rightToken,
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700199 const std::function<ParseResult()> &parseElement,
200 bool allowEmptyList) {
201 // Handle the empty case.
Chris Lattner48af7d12018-07-09 19:05:38 -0700202 if (getToken().is(rightToken)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700203 if (!allowEmptyList)
204 return emitError("expected list element");
205 consumeToken(rightToken);
206 return ParseSuccess;
207 }
208
209 // Non-empty case starts with an element.
210 if (parseElement())
211 return ParseFailure;
212
213 // Otherwise we have a list of comma separated elements.
214 while (consumeIf(Token::comma)) {
215 if (parseElement())
216 return ParseFailure;
217 }
218
219 // Consume the end character.
220 if (!consumeIf(rightToken))
Chris Lattner8da0c282018-06-29 11:15:56 -0700221 return emitError("expected ',' or '" + Token::getTokenSpelling(rightToken) +
222 "'");
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700223
224 return ParseSuccess;
225}
Chris Lattnere79379a2018-06-22 10:39:19 -0700226
227//===----------------------------------------------------------------------===//
228// Type Parsing
229//===----------------------------------------------------------------------===//
230
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700231/// Parse the low-level fixed dtypes in the system.
232///
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700233/// primitive-type ::= `f16` | `bf16` | `f32` | `f64`
234/// primitive-type ::= integer-type
235/// primitive-type ::= `affineint`
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700236///
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700237Type *Parser::parsePrimitiveType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700238 switch (getToken().getKind()) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700239 default:
240 return (emitError("expected type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700241 case Token::kw_bf16:
242 consumeToken(Token::kw_bf16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700243 return builder.getBF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700244 case Token::kw_f16:
245 consumeToken(Token::kw_f16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700246 return builder.getF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700247 case Token::kw_f32:
248 consumeToken(Token::kw_f32);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700249 return builder.getF32Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700250 case Token::kw_f64:
251 consumeToken(Token::kw_f64);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700252 return builder.getF64Type();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700253 case Token::kw_affineint:
254 consumeToken(Token::kw_affineint);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700255 return builder.getAffineIntType();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700256 case Token::inttype: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700257 auto width = getToken().getIntTypeBitwidth();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700258 if (!width.hasValue())
259 return (emitError("invalid integer width"), nullptr);
260 consumeToken(Token::inttype);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700261 return builder.getIntegerType(width.getValue());
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700262 }
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700263 }
264}
265
266/// Parse the element type of a tensor or memref type.
267///
268/// element-type ::= primitive-type | vector-type
269///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700270Type *Parser::parseElementType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700271 if (getToken().is(Token::kw_vector))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700272 return parseVectorType();
273
274 return parsePrimitiveType();
275}
276
277/// Parse a vector type.
278///
279/// vector-type ::= `vector` `<` const-dimension-list primitive-type `>`
280/// const-dimension-list ::= (integer-literal `x`)+
281///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700282VectorType *Parser::parseVectorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700283 consumeToken(Token::kw_vector);
284
285 if (!consumeIf(Token::less))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700286 return (emitError("expected '<' in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700287
Chris Lattner48af7d12018-07-09 19:05:38 -0700288 if (getToken().isNot(Token::integer))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700289 return (emitError("expected dimension size in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700290
291 SmallVector<unsigned, 4> dimensions;
Chris Lattner48af7d12018-07-09 19:05:38 -0700292 while (getToken().is(Token::integer)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700293 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700294 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700295 if (!dimension.hasValue())
Chris Lattnerf7e22732018-06-22 22:03:48 -0700296 return (emitError("invalid dimension in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700297 dimensions.push_back(dimension.getValue());
298
299 consumeToken(Token::integer);
300
301 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700302 if (getToken().isNot(Token::bare_identifier) ||
303 getTokenSpelling()[0] != 'x')
Chris Lattnerf7e22732018-06-22 22:03:48 -0700304 return (emitError("expected 'x' in vector dimension list"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700305
306 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700307 if (getTokenSpelling().size() != 1)
308 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700309
310 // Consume the 'x'.
311 consumeToken(Token::bare_identifier);
312 }
313
314 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700315 auto *elementType = parsePrimitiveType();
316 if (!elementType)
317 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700318
319 if (!consumeIf(Token::greater))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700320 return (emitError("expected '>' in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700321
Chris Lattnerf7e22732018-06-22 22:03:48 -0700322 return VectorType::get(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700323}
324
325/// Parse a dimension list of a tensor or memref type. This populates the
326/// dimension list, returning -1 for the '?' dimensions.
327///
328/// dimension-list-ranked ::= (dimension `x`)*
329/// dimension ::= `?` | integer-literal
330///
331ParseResult Parser::parseDimensionListRanked(SmallVectorImpl<int> &dimensions) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700332 while (getToken().isAny(Token::integer, Token::question)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700333 if (consumeIf(Token::question)) {
334 dimensions.push_back(-1);
335 } else {
336 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700337 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700338 if (!dimension.hasValue() || (int)dimension.getValue() < 0)
339 return emitError("invalid dimension");
340 dimensions.push_back((int)dimension.getValue());
341 consumeToken(Token::integer);
342 }
343
344 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700345 if (getToken().isNot(Token::bare_identifier) ||
346 getTokenSpelling()[0] != 'x')
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700347 return emitError("expected 'x' in dimension list");
348
349 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700350 if (getTokenSpelling().size() != 1)
351 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700352
353 // Consume the 'x'.
354 consumeToken(Token::bare_identifier);
355 }
356
357 return ParseSuccess;
358}
359
360/// Parse a tensor type.
361///
362/// tensor-type ::= `tensor` `<` dimension-list element-type `>`
363/// dimension-list ::= dimension-list-ranked | `??`
364///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700365Type *Parser::parseTensorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700366 consumeToken(Token::kw_tensor);
367
368 if (!consumeIf(Token::less))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700369 return (emitError("expected '<' in tensor type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700370
371 bool isUnranked;
372 SmallVector<int, 4> dimensions;
373
374 if (consumeIf(Token::questionquestion)) {
375 isUnranked = true;
376 } else {
377 isUnranked = false;
378 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700379 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700380 }
381
382 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700383 auto elementType = parseElementType();
384 if (!elementType)
385 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700386
387 if (!consumeIf(Token::greater))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700388 return (emitError("expected '>' in tensor type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700389
MLIR Team355ec862018-06-23 18:09:09 -0700390 if (isUnranked)
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700391 return builder.getTensorType(elementType);
392 return builder.getTensorType(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700393}
394
395/// Parse a memref type.
396///
397/// memref-type ::= `memref` `<` dimension-list-ranked element-type
398/// (`,` semi-affine-map-composition)? (`,` memory-space)? `>`
399///
400/// semi-affine-map-composition ::= (semi-affine-map `,` )* semi-affine-map
401/// memory-space ::= integer-literal /* | TODO: address-space-id */
402///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700403Type *Parser::parseMemRefType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700404 consumeToken(Token::kw_memref);
405
406 if (!consumeIf(Token::less))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700407 return (emitError("expected '<' in memref type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700408
409 SmallVector<int, 4> dimensions;
410 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700411 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700412
413 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700414 auto elementType = parseElementType();
415 if (!elementType)
416 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700417
MLIR Team718c82f2018-07-16 09:45:22 -0700418 if (!consumeIf(Token::comma))
419 return (emitError("expected ',' in memref type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700420
MLIR Team718c82f2018-07-16 09:45:22 -0700421 // Parse semi-affine-map-composition.
422 SmallVector<AffineMap*, 2> affineMapComposition;
423 unsigned memorySpace;
424 bool parsedMemorySpace = false;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700425
MLIR Team718c82f2018-07-16 09:45:22 -0700426 auto parseElt = [&]() -> ParseResult {
427 if (getToken().is(Token::integer)) {
428 // Parse memory space.
429 if (parsedMemorySpace)
430 return emitError("multiple memory spaces specified in memref type");
431 auto v = getToken().getUnsignedIntegerValue();
432 if (!v.hasValue())
433 return emitError("invalid memory space in memref type");
434 memorySpace = v.getValue();
435 consumeToken(Token::integer);
436 parsedMemorySpace = true;
437 } else {
438 // Parse affine map.
439 if (parsedMemorySpace)
440 return emitError("affine map after memory space in memref type");
441 auto* affineMap = parseAffineMapReference();
442 if (affineMap == nullptr)
443 return ParseFailure;
444 affineMapComposition.push_back(affineMap);
445 }
446 return ParseSuccess;
447 };
448
449 // Parse comma separated list of affine maps, followed by memory space.
450 if (parseCommaSeparatedList(Token::greater, parseElt,
451 /*allowEmptyList=*/false)) {
452 return nullptr;
453 }
454 // Check that MemRef type specifies at least one affine map in composition.
455 if (affineMapComposition.empty())
456 return (emitError("expected semi-affine-map in memref type"), nullptr);
457 if (!parsedMemorySpace)
458 return (emitError("expected memory space in memref type"), nullptr);
459
460 return MemRefType::get(dimensions, elementType, affineMapComposition,
461 memorySpace);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700462}
463
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700464/// Parse a function type.
465///
466/// function-type ::= type-list-parens `->` type-list
467///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700468Type *Parser::parseFunctionType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700469 assert(getToken().is(Token::l_paren));
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700470
Chris Lattnerf7e22732018-06-22 22:03:48 -0700471 SmallVector<Type*, 4> arguments;
472 if (parseTypeList(arguments))
473 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700474
475 if (!consumeIf(Token::arrow))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700476 return (emitError("expected '->' in function type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700477
Chris Lattnerf7e22732018-06-22 22:03:48 -0700478 SmallVector<Type*, 4> results;
479 if (parseTypeList(results))
480 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700481
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700482 return builder.getFunctionType(arguments, results);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700483}
484
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700485/// Parse an arbitrary type.
486///
487/// type ::= primitive-type
488/// | vector-type
489/// | tensor-type
490/// | memref-type
491/// | function-type
492/// element-type ::= primitive-type | vector-type
493///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700494Type *Parser::parseType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700495 switch (getToken().getKind()) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700496 case Token::kw_memref: return parseMemRefType();
497 case Token::kw_tensor: return parseTensorType();
498 case Token::kw_vector: return parseVectorType();
499 case Token::l_paren: return parseFunctionType();
500 default:
501 return parsePrimitiveType();
502 }
503}
504
505/// Parse a "type list", which is a singular type, or a parenthesized list of
506/// types.
507///
508/// type-list ::= type-list-parens | type
509/// type-list-parens ::= `(` `)`
510/// | `(` type (`,` type)* `)`
511///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700512ParseResult Parser::parseTypeList(SmallVectorImpl<Type*> &elements) {
513 auto parseElt = [&]() -> ParseResult {
514 auto elt = parseType();
515 elements.push_back(elt);
516 return elt ? ParseSuccess : ParseFailure;
517 };
518
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700519 // If there is no parens, then it must be a singular type.
520 if (!consumeIf(Token::l_paren))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700521 return parseElt();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700522
Chris Lattnerf7e22732018-06-22 22:03:48 -0700523 if (parseCommaSeparatedList(Token::r_paren, parseElt))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700524 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700525
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700526 return ParseSuccess;
527}
528
Chris Lattner4c95a502018-06-23 16:03:42 -0700529//===----------------------------------------------------------------------===//
Chris Lattner7121b802018-07-04 20:45:39 -0700530// Attribute parsing.
531//===----------------------------------------------------------------------===//
532
533
534/// Attribute parsing.
535///
536/// attribute-value ::= bool-literal
537/// | integer-literal
538/// | float-literal
539/// | string-literal
540/// | `[` (attribute-value (`,` attribute-value)*)? `]`
541///
542Attribute *Parser::parseAttribute() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700543 switch (getToken().getKind()) {
Chris Lattner7121b802018-07-04 20:45:39 -0700544 case Token::kw_true:
545 consumeToken(Token::kw_true);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700546 return builder.getBoolAttr(true);
Chris Lattner7121b802018-07-04 20:45:39 -0700547 case Token::kw_false:
548 consumeToken(Token::kw_false);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700549 return builder.getBoolAttr(false);
Chris Lattner7121b802018-07-04 20:45:39 -0700550
551 case Token::integer: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700552 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700553 if (!val.hasValue() || (int64_t)val.getValue() < 0)
554 return (emitError("integer too large for attribute"), nullptr);
555 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700556 return builder.getIntegerAttr((int64_t)val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700557 }
558
559 case Token::minus: {
560 consumeToken(Token::minus);
Chris Lattner48af7d12018-07-09 19:05:38 -0700561 if (getToken().is(Token::integer)) {
562 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700563 if (!val.hasValue() || (int64_t)-val.getValue() >= 0)
564 return (emitError("integer too large for attribute"), nullptr);
565 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700566 return builder.getIntegerAttr((int64_t)-val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700567 }
568
569 return (emitError("expected constant integer or floating point value"),
570 nullptr);
571 }
572
573 case Token::string: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700574 auto val = getToken().getStringValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700575 consumeToken(Token::string);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700576 return builder.getStringAttr(val);
Chris Lattner7121b802018-07-04 20:45:39 -0700577 }
578
579 case Token::l_bracket: {
580 consumeToken(Token::l_bracket);
581 SmallVector<Attribute*, 4> elements;
582
583 auto parseElt = [&]() -> ParseResult {
584 elements.push_back(parseAttribute());
585 return elements.back() ? ParseSuccess : ParseFailure;
586 };
587
588 if (parseCommaSeparatedList(Token::r_bracket, parseElt))
589 return nullptr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700590 return builder.getArrayAttr(elements);
Chris Lattner7121b802018-07-04 20:45:39 -0700591 }
592 default:
MLIR Teamb61885d2018-07-18 16:29:21 -0700593 // Try to parse affine map reference.
594 auto* affineMap = parseAffineMapReference();
595 if (affineMap != nullptr)
596 return builder.getAffineMapAttr(affineMap);
597
Chris Lattner7121b802018-07-04 20:45:39 -0700598 // TODO: Handle floating point.
599 return (emitError("expected constant attribute value"), nullptr);
600 }
601}
602
Chris Lattner7121b802018-07-04 20:45:39 -0700603/// Attribute dictionary.
604///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700605/// attribute-dict ::= `{` `}`
606/// | `{` attribute-entry (`,` attribute-entry)* `}`
607/// attribute-entry ::= bare-id `:` attribute-value
Chris Lattner7121b802018-07-04 20:45:39 -0700608///
609ParseResult Parser::parseAttributeDict(
610 SmallVectorImpl<NamedAttribute> &attributes) {
611 consumeToken(Token::l_brace);
612
613 auto parseElt = [&]() -> ParseResult {
614 // We allow keywords as attribute names.
Chris Lattner48af7d12018-07-09 19:05:38 -0700615 if (getToken().isNot(Token::bare_identifier, Token::inttype) &&
616 !getToken().isKeyword())
Chris Lattner7121b802018-07-04 20:45:39 -0700617 return emitError("expected attribute name");
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700618 auto nameId = builder.getIdentifier(getTokenSpelling());
Chris Lattner7121b802018-07-04 20:45:39 -0700619 consumeToken();
620
621 if (!consumeIf(Token::colon))
622 return emitError("expected ':' in attribute list");
623
624 auto attr = parseAttribute();
625 if (!attr) return ParseFailure;
626
627 attributes.push_back({nameId, attr});
628 return ParseSuccess;
629 };
630
631 if (parseCommaSeparatedList(Token::r_brace, parseElt))
632 return ParseFailure;
633
634 return ParseSuccess;
635}
636
637//===----------------------------------------------------------------------===//
MLIR Teamf85a6262018-06-27 11:03:08 -0700638// Polyhedral structures.
639//===----------------------------------------------------------------------===//
640
Chris Lattner2e595eb2018-07-10 10:08:27 -0700641/// Lower precedence ops (all at the same precedence level). LNoOp is false in
642/// the boolean sense.
643enum AffineLowPrecOp {
644 /// Null value.
645 LNoOp,
646 Add,
647 Sub
648};
MLIR Teamf85a6262018-06-27 11:03:08 -0700649
Chris Lattner2e595eb2018-07-10 10:08:27 -0700650/// Higher precedence ops - all at the same precedence level. HNoOp is false in
651/// the boolean sense.
652enum AffineHighPrecOp {
653 /// Null value.
654 HNoOp,
655 Mul,
656 FloorDiv,
657 CeilDiv,
658 Mod
659};
Chris Lattner7121b802018-07-04 20:45:39 -0700660
Chris Lattner2e595eb2018-07-10 10:08:27 -0700661namespace {
662/// This is a specialized parser for AffineMap's, maintaining the state
663/// transient to their bodies.
664class AffineMapParser : public Parser {
665public:
666 explicit AffineMapParser(ParserState &state) : Parser(state) {}
Chris Lattner7121b802018-07-04 20:45:39 -0700667
Chris Lattner2e595eb2018-07-10 10:08:27 -0700668 AffineMap *parseAffineMapInline();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700669
Chris Lattner2e595eb2018-07-10 10:08:27 -0700670private:
671 unsigned getNumDims() const { return dims.size(); }
672 unsigned getNumSymbols() const { return symbols.size(); }
MLIR Teamf85a6262018-06-27 11:03:08 -0700673
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700674 /// Returns true if the only identifiers the parser accepts in affine
675 /// expressions are symbolic identifiers.
676 bool isPureSymbolic() const { return pureSymbolic; }
677 void setSymbolicParsing(bool val) { pureSymbolic = val; }
678
Chris Lattner2e595eb2018-07-10 10:08:27 -0700679 // Binary affine op parsing.
680 AffineLowPrecOp consumeIfLowPrecOp();
681 AffineHighPrecOp consumeIfHighPrecOp();
MLIR Teamf85a6262018-06-27 11:03:08 -0700682
Chris Lattner2e595eb2018-07-10 10:08:27 -0700683 // Identifier lists for polyhedral structures.
684 ParseResult parseDimIdList();
685 ParseResult parseSymbolIdList();
686 ParseResult parseDimOrSymbolId(bool isDim);
687
688 AffineExpr *parseAffineExpr();
689 AffineExpr *parseParentheticalExpr();
690 AffineExpr *parseNegateExpression(AffineExpr *lhs);
691 AffineExpr *parseIntegerExpr();
692 AffineExpr *parseBareIdExpr();
693
694 AffineExpr *getBinaryAffineOpExpr(AffineHighPrecOp op, AffineExpr *lhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700695 AffineExpr *rhs, SMLoc opLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700696 AffineExpr *getBinaryAffineOpExpr(AffineLowPrecOp op, AffineExpr *lhs,
697 AffineExpr *rhs);
698 AffineExpr *parseAffineOperandExpr(AffineExpr *lhs);
699 AffineExpr *parseAffineLowPrecOpExpr(AffineExpr *llhs,
700 AffineLowPrecOp llhsOp);
701 AffineExpr *parseAffineHighPrecOpExpr(AffineExpr *llhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700702 AffineHighPrecOp llhsOp,
703 SMLoc llhsOpLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700704
705private:
706 // TODO(bondhugula): could just use an vector/ArrayRef and scan the numbers.
707 llvm::StringMap<unsigned> dims;
708 llvm::StringMap<unsigned> symbols;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700709 /// True if the parser should allow only symbolic identifiers in affine
710 /// expressions.
711 bool pureSymbolic = false;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700712};
713} // end anonymous namespace
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700714
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700715/// Create an affine binary high precedence op expression (mul's, div's, mod).
716/// opLoc is the location of the op token to be used to report errors
717/// for non-conforming expressions.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700718AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineHighPrecOp op,
719 AffineExpr *lhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700720 AffineExpr *rhs, SMLoc opLoc) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700721 // TODO: make the error location info accurate.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700722 switch (op) {
723 case Mul:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700724 if (!lhs->isSymbolicOrConstant() && !rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700725 emitError(opLoc, "non-affine expression: at least one of the multiply "
726 "operands has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700727 return nullptr;
728 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700729 return builder.getMulExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700730 case FloorDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700731 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700732 emitError(opLoc, "non-affine expression: right operand of floordiv "
733 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700734 return nullptr;
735 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700736 return builder.getFloorDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700737 case CeilDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700738 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700739 emitError(opLoc, "non-affine expression: right operand of ceildiv "
740 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700741 return nullptr;
742 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700743 return builder.getCeilDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700744 case Mod:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700745 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700746 emitError(opLoc, "non-affine expression: right operand of mod "
747 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700748 return nullptr;
749 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700750 return builder.getModExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700751 case HNoOp:
752 llvm_unreachable("can't create affine expression for null high prec op");
753 return nullptr;
754 }
755}
756
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700757/// Create an affine binary low precedence op expression (add, sub).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700758AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineLowPrecOp op,
759 AffineExpr *lhs,
760 AffineExpr *rhs) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700761 switch (op) {
762 case AffineLowPrecOp::Add:
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700763 return builder.getAddExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700764 case AffineLowPrecOp::Sub:
Uday Bondhugulac1faf662018-07-19 14:08:50 -0700765 return builder.getAddExpr(
766 lhs, builder.getMulExpr(rhs, builder.getConstantExpr(-1)));
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700767 case AffineLowPrecOp::LNoOp:
768 llvm_unreachable("can't create affine expression for null low prec op");
769 return nullptr;
770 }
771}
772
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700773/// Consume this token if it is a lower precedence affine op (there are only two
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700774/// precedence levels).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700775AffineLowPrecOp AffineMapParser::consumeIfLowPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700776 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700777 case Token::plus:
778 consumeToken(Token::plus);
779 return AffineLowPrecOp::Add;
780 case Token::minus:
781 consumeToken(Token::minus);
782 return AffineLowPrecOp::Sub;
783 default:
784 return AffineLowPrecOp::LNoOp;
785 }
786}
787
788/// Consume this token if it is a higher precedence affine op (there are only
789/// two precedence levels)
Chris Lattner2e595eb2018-07-10 10:08:27 -0700790AffineHighPrecOp AffineMapParser::consumeIfHighPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700791 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700792 case Token::star:
793 consumeToken(Token::star);
794 return Mul;
795 case Token::kw_floordiv:
796 consumeToken(Token::kw_floordiv);
797 return FloorDiv;
798 case Token::kw_ceildiv:
799 consumeToken(Token::kw_ceildiv);
800 return CeilDiv;
801 case Token::kw_mod:
802 consumeToken(Token::kw_mod);
803 return Mod;
804 default:
805 return HNoOp;
806 }
807}
808
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700809/// Parse a high precedence op expression list: mul, div, and mod are high
810/// precedence binary ops, i.e., parse a
811/// expr_1 op_1 expr_2 op_2 ... expr_n
812/// where op_1, op_2 are all a AffineHighPrecOp (mul, div, mod).
813/// All affine binary ops are left associative.
814/// Given llhs, returns (llhs llhsOp lhs) op rhs, or (lhs op rhs) if llhs is
815/// null. If no rhs can be found, returns (llhs llhsOp lhs) or lhs if llhs is
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700816/// null. llhsOpLoc is the location of the llhsOp token that will be used to
817/// report an error for non-conforming expressions.
818AffineExpr *AffineMapParser::parseAffineHighPrecOpExpr(AffineExpr *llhs,
819 AffineHighPrecOp llhsOp,
820 SMLoc llhsOpLoc) {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700821 AffineExpr *lhs = parseAffineOperandExpr(llhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700822 if (!lhs)
823 return nullptr;
824
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700825 // Found an LHS. Parse the remaining expression.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700826 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -0700827 if (AffineHighPrecOp op = consumeIfHighPrecOp()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700828 if (llhs) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700829 AffineExpr *expr = getBinaryAffineOpExpr(llhsOp, llhs, lhs, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700830 if (!expr)
831 return nullptr;
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700832 return parseAffineHighPrecOpExpr(expr, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700833 }
834 // No LLHS, get RHS
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700835 return parseAffineHighPrecOpExpr(lhs, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700836 }
837
838 // This is the last operand in this expression.
839 if (llhs)
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700840 return getBinaryAffineOpExpr(llhsOp, llhs, lhs, llhsOpLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700841
842 // No llhs, 'lhs' itself is the expression.
843 return lhs;
844}
845
846/// Parse an affine expression inside parentheses.
847///
848/// affine-expr ::= `(` affine-expr `)`
Chris Lattner2e595eb2018-07-10 10:08:27 -0700849AffineExpr *AffineMapParser::parseParentheticalExpr() {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700850 if (!consumeIf(Token::l_paren))
851 return (emitError("expected '('"), nullptr);
Chris Lattner48af7d12018-07-09 19:05:38 -0700852 if (getToken().is(Token::r_paren))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700853 return (emitError("no expression inside parentheses"), nullptr);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700854 auto *expr = parseAffineExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700855 if (!expr)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700856 return nullptr;
857 if (!consumeIf(Token::r_paren))
858 return (emitError("expected ')'"), nullptr);
859 return expr;
860}
861
862/// Parse the negation expression.
863///
864/// affine-expr ::= `-` affine-expr
Chris Lattner2e595eb2018-07-10 10:08:27 -0700865AffineExpr *AffineMapParser::parseNegateExpression(AffineExpr *lhs) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700866 if (!consumeIf(Token::minus))
867 return (emitError("expected '-'"), nullptr);
868
Chris Lattner2e595eb2018-07-10 10:08:27 -0700869 AffineExpr *operand = parseAffineOperandExpr(lhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700870 // Since negation has the highest precedence of all ops (including high
871 // precedence ops) but lower than parentheses, we are only going to use
872 // parseAffineOperandExpr instead of parseAffineExpr here.
873 if (!operand)
874 // Extra error message although parseAffineOperandExpr would have
875 // complained. Leads to a better diagnostic.
876 return (emitError("missing operand of negation"), nullptr);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700877 auto *minusOne = builder.getConstantExpr(-1);
878 return builder.getMulExpr(minusOne, operand);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700879}
880
881/// Parse a bare id that may appear in an affine expression.
882///
883/// affine-expr ::= bare-id
Chris Lattner2e595eb2018-07-10 10:08:27 -0700884AffineExpr *AffineMapParser::parseBareIdExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700885 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700886 return (emitError("expected bare identifier"), nullptr);
887
Chris Lattner48af7d12018-07-09 19:05:38 -0700888 StringRef sRef = getTokenSpelling();
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700889 // dims, symbols are all pairwise distinct.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700890 if (dims.count(sRef)) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700891 if (isPureSymbolic())
892 return (emitError("identifier used is not a symbolic identifier"),
893 nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700894 consumeToken(Token::bare_identifier);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700895 return builder.getDimExpr(dims.lookup(sRef));
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700896 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700897
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700898 if (symbols.count(sRef)) {
899 consumeToken(Token::bare_identifier);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700900 return builder.getSymbolExpr(symbols.lookup(sRef));
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700901 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700902
903 return (emitError("use of undeclared identifier"), nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700904}
905
906/// Parse a positive integral constant appearing in an affine expression.
907///
908/// affine-expr ::= integer-literal
Chris Lattner2e595eb2018-07-10 10:08:27 -0700909AffineExpr *AffineMapParser::parseIntegerExpr() {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700910 // No need to handle negative numbers separately here. They are naturally
911 // handled via the unary negation operator, although (FIXME) MININT_64 still
912 // not correctly handled.
Chris Lattner48af7d12018-07-09 19:05:38 -0700913 if (getToken().isNot(Token::integer))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700914 return (emitError("expected integer"), nullptr);
915
Chris Lattner48af7d12018-07-09 19:05:38 -0700916 auto val = getToken().getUInt64IntegerValue();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700917 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
918 return (emitError("constant too large for affineint"), nullptr);
919 }
920 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700921 return builder.getConstantExpr((int64_t)val.getValue());
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700922}
923
924/// Parses an expression that can be a valid operand of an affine expression.
Uday Bondhugula76345202018-07-09 13:47:52 -0700925/// lhs: if non-null, lhs is an affine expression that is the lhs of a binary
926/// operator, the rhs of which is being parsed. This is used to determine
927/// whether an error should be emitted for a missing right operand.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700928// Eg: for an expression without parentheses (like i + j + k + l), each
929// of the four identifiers is an operand. For i + j*k + l, j*k is not an
930// operand expression, it's an op expression and will be parsed via
931// parseAffineHighPrecOpExpression(). However, for i + (j*k) + -l, (j*k) and -l
932// are valid operands that will be parsed by this function.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700933AffineExpr *AffineMapParser::parseAffineOperandExpr(AffineExpr *lhs) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700934 switch (getToken().getKind()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700935 case Token::bare_identifier:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700936 return parseBareIdExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700937 case Token::integer:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700938 return parseIntegerExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700939 case Token::l_paren:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700940 return parseParentheticalExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700941 case Token::minus:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700942 return parseNegateExpression(lhs);
Uday Bondhugula76345202018-07-09 13:47:52 -0700943 case Token::kw_ceildiv:
944 case Token::kw_floordiv:
945 case Token::kw_mod:
946 case Token::plus:
947 case Token::star:
948 if (lhs)
949 emitError("missing right operand of binary operator");
950 else
951 emitError("missing left operand of binary operator");
952 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700953 default:
954 if (lhs)
Uday Bondhugula76345202018-07-09 13:47:52 -0700955 emitError("missing right operand of binary operator");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700956 else
957 emitError("expected affine expression");
958 return nullptr;
959 }
960}
961
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700962/// Parse affine expressions that are bare-id's, integer constants,
963/// parenthetical affine expressions, and affine op expressions that are a
964/// composition of those.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700965///
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700966/// All binary op's associate from left to right.
967///
968/// {add, sub} have lower precedence than {mul, div, and mod}.
969///
Uday Bondhugula76345202018-07-09 13:47:52 -0700970/// Add, sub'are themselves at the same precedence level. Mul, floordiv,
971/// ceildiv, and mod are at the same higher precedence level. Negation has
972/// higher precedence than any binary op.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700973///
974/// llhs: the affine expression appearing on the left of the one being parsed.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700975/// This function will return ((llhs llhsOp lhs) op rhs) if llhs is non null,
976/// and lhs op rhs otherwise; if there is no rhs, llhs llhsOp lhs is returned if
977/// llhs is non-null; otherwise lhs is returned. This is to deal with left
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700978/// associativity.
979///
980/// Eg: when the expression is e1 + e2*e3 + e4, with e1 as llhs, this function
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700981/// will return the affine expr equivalent of (e1 + (e2*e3)) + e4, where (e2*e3)
982/// will be parsed using parseAffineHighPrecOpExpr().
Chris Lattner2e595eb2018-07-10 10:08:27 -0700983AffineExpr *AffineMapParser::parseAffineLowPrecOpExpr(AffineExpr *llhs,
984 AffineLowPrecOp llhsOp) {
Uday Bondhugula76345202018-07-09 13:47:52 -0700985 AffineExpr *lhs;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700986 if (!(lhs = parseAffineOperandExpr(llhs)))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700987 return nullptr;
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700988
989 // Found an LHS. Deal with the ops.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700990 if (AffineLowPrecOp lOp = consumeIfLowPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700991 if (llhs) {
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700992 AffineExpr *sum = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700993 return parseAffineLowPrecOpExpr(sum, lOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700994 }
995 // No LLHS, get RHS and form the expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700996 return parseAffineLowPrecOpExpr(lhs, lOp);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700997 }
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700998 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -0700999 if (AffineHighPrecOp hOp = consumeIfHighPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001000 // We have a higher precedence op here. Get the rhs operand for the llhs
1001 // through parseAffineHighPrecOpExpr.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001002 AffineExpr *highRes = parseAffineHighPrecOpExpr(lhs, hOp, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001003 if (!highRes)
1004 return nullptr;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001005
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001006 // If llhs is null, the product forms the first operand of the yet to be
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001007 // found expression. If non-null, the op to associate with llhs is llhsOp.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001008 AffineExpr *expr =
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001009 llhs ? getBinaryAffineOpExpr(llhsOp, llhs, highRes) : highRes;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001010
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001011 // Recurse for subsequent low prec op's after the affine high prec op
1012 // expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001013 if (AffineLowPrecOp nextOp = consumeIfLowPrecOp())
1014 return parseAffineLowPrecOpExpr(expr, nextOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001015 return expr;
1016 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001017 // Last operand in the expression list.
1018 if (llhs)
1019 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
1020 // No llhs, 'lhs' itself is the expression.
1021 return lhs;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001022}
1023
1024/// Parse an affine expression.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001025/// affine-expr ::= `(` affine-expr `)`
1026/// | `-` affine-expr
1027/// | affine-expr `+` affine-expr
1028/// | affine-expr `-` affine-expr
1029/// | affine-expr `*` affine-expr
1030/// | affine-expr `floordiv` affine-expr
1031/// | affine-expr `ceildiv` affine-expr
1032/// | affine-expr `mod` affine-expr
1033/// | bare-id
1034/// | integer-literal
1035///
1036/// Additional conditions are checked depending on the production. For eg., one
1037/// of the operands for `*` has to be either constant/symbolic; the second
1038/// operand for floordiv, ceildiv, and mod has to be a positive integer.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001039AffineExpr *AffineMapParser::parseAffineExpr() {
1040 return parseAffineLowPrecOpExpr(nullptr, AffineLowPrecOp::LNoOp);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001041}
1042
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001043/// Parse a dim or symbol from the lists appearing before the actual expressions
Chris Lattner2e595eb2018-07-10 10:08:27 -07001044/// of the affine map. Update our state to store the dimensional/symbolic
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001045/// identifier. 'dim': whether it's the dim list or symbol list that is being
1046/// parsed.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001047ParseResult AffineMapParser::parseDimOrSymbolId(bool isDim) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001048 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001049 return emitError("expected bare identifier");
Chris Lattner48af7d12018-07-09 19:05:38 -07001050 auto sRef = getTokenSpelling();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001051 consumeToken(Token::bare_identifier);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001052 if (dims.count(sRef))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001053 return emitError("dimensional identifier name reused");
Chris Lattner2e595eb2018-07-10 10:08:27 -07001054 if (symbols.count(sRef))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001055 return emitError("symbolic identifier name reused");
Chris Lattner2e595eb2018-07-10 10:08:27 -07001056 if (isDim)
1057 dims.insert({sRef, dims.size()});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001058 else
Chris Lattner2e595eb2018-07-10 10:08:27 -07001059 symbols.insert({sRef, symbols.size()});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001060 return ParseSuccess;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001061}
1062
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001063/// Parse the list of symbolic identifiers to an affine map.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001064ParseResult AffineMapParser::parseSymbolIdList() {
1065 if (!consumeIf(Token::l_bracket))
1066 return emitError("expected '['");
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001067
Chris Lattner2e595eb2018-07-10 10:08:27 -07001068 auto parseElt = [&]() -> ParseResult { return parseDimOrSymbolId(false); };
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001069 return parseCommaSeparatedList(Token::r_bracket, parseElt);
1070}
1071
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001072/// Parse the list of dimensional identifiers to an affine map.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001073ParseResult AffineMapParser::parseDimIdList() {
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001074 if (!consumeIf(Token::l_paren))
1075 return emitError("expected '(' at start of dimensional identifiers list");
1076
Chris Lattner2e595eb2018-07-10 10:08:27 -07001077 auto parseElt = [&]() -> ParseResult { return parseDimOrSymbolId(true); };
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001078 return parseCommaSeparatedList(Token::r_paren, parseElt);
1079}
1080
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001081/// Parse an affine map definition.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001082///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001083/// affine-map-inline ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
1084/// (`size` `(` dim-size (`,` dim-size)* `)`)?
1085/// dim-size ::= affine-expr | `min` `(` affine-expr ( `,` affine-expr)+ `)`
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001086///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001087/// multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner2e595eb2018-07-10 10:08:27 -07001088AffineMap *AffineMapParser::parseAffineMapInline() {
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001089 // List of dimensional identifiers.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001090 if (parseDimIdList())
Chris Lattner7121b802018-07-04 20:45:39 -07001091 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001092
1093 // Symbols are optional.
Chris Lattner48af7d12018-07-09 19:05:38 -07001094 if (getToken().is(Token::l_bracket)) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001095 if (parseSymbolIdList())
Chris Lattner7121b802018-07-04 20:45:39 -07001096 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001097 }
1098 if (!consumeIf(Token::arrow)) {
Chris Lattner7121b802018-07-04 20:45:39 -07001099 return (emitError("expected '->' or '['"), nullptr);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001100 }
1101 if (!consumeIf(Token::l_paren)) {
1102 emitError("expected '(' at start of affine map range");
Chris Lattner7121b802018-07-04 20:45:39 -07001103 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001104 }
1105
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001106 SmallVector<AffineExpr *, 4> exprs;
1107 auto parseElt = [&]() -> ParseResult {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001108 auto *elt = parseAffineExpr();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001109 ParseResult res = elt ? ParseSuccess : ParseFailure;
1110 exprs.push_back(elt);
1111 return res;
1112 };
1113
1114 // Parse a multi-dimensional affine expression (a comma-separated list of 1-d
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001115 // affine expressions); the list cannot be empty.
1116 // Grammar: multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
1117 if (parseCommaSeparatedList(Token::r_paren, parseElt, false))
Chris Lattner7121b802018-07-04 20:45:39 -07001118 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001119
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001120 // Parse optional range sizes.
Uday Bondhugula1e500b42018-07-12 18:04:04 -07001121 // range-sizes ::= (`size` `(` dim-size (`,` dim-size)* `)`)?
1122 // dim-size ::= affine-expr | `min` `(` affine-expr (`,` affine-expr)+ `)`
1123 // TODO(bondhugula): support for min of several affine expressions.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001124 // TODO: check if sizes are non-negative whenever they are constant.
1125 SmallVector<AffineExpr *, 4> rangeSizes;
1126 if (consumeIf(Token::kw_size)) {
1127 // Location of the l_paren token (if it exists) for error reporting later.
1128 auto loc = getToken().getLoc();
1129 if (!consumeIf(Token::l_paren))
1130 return (emitError("expected '(' at start of affine map range"), nullptr);
1131
1132 auto parseRangeSize = [&]() -> ParseResult {
1133 auto *elt = parseAffineExpr();
1134 ParseResult res = elt ? ParseSuccess : ParseFailure;
1135 rangeSizes.push_back(elt);
1136 return res;
1137 };
1138
1139 setSymbolicParsing(true);
1140 if (parseCommaSeparatedList(Token::r_paren, parseRangeSize, false))
1141 return nullptr;
1142 if (exprs.size() > rangeSizes.size())
1143 return (emitError(loc, "fewer range sizes than range expressions"),
1144 nullptr);
1145 if (exprs.size() < rangeSizes.size())
1146 return (emitError(loc, "more range sizes than range expressions"),
1147 nullptr);
1148 }
1149
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001150 // Parsed a valid affine map.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001151 return builder.getAffineMap(dims.size(), symbols.size(), exprs, rangeSizes);
MLIR Teamf85a6262018-06-27 11:03:08 -07001152}
1153
Chris Lattner2e595eb2018-07-10 10:08:27 -07001154AffineMap *Parser::parseAffineMapInline() {
1155 return AffineMapParser(state).parseAffineMapInline();
1156}
1157
MLIR Team718c82f2018-07-16 09:45:22 -07001158AffineMap *Parser::parseAffineMapReference() {
1159 if (getToken().is(Token::hash_identifier)) {
1160 // Parse affine map identifier and verify that it exists.
1161 StringRef affineMapId = getTokenSpelling().drop_front();
1162 if (getState().affineMapDefinitions.count(affineMapId) == 0)
1163 return (emitError("undefined affine map id '" + affineMapId + "'"),
1164 nullptr);
1165 consumeToken(Token::hash_identifier);
1166 return getState().affineMapDefinitions[affineMapId];
1167 }
1168 // Try to parse inline affine map.
1169 return parseAffineMapInline();
1170}
1171
MLIR Teamf85a6262018-06-27 11:03:08 -07001172//===----------------------------------------------------------------------===//
Chris Lattner7f9cc272018-07-19 08:35:28 -07001173// FunctionParser
Chris Lattner4c95a502018-06-23 16:03:42 -07001174//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001175
Chris Lattner7f9cc272018-07-19 08:35:28 -07001176namespace {
1177/// This class contains parser state that is common across CFG and ML functions,
1178/// notably for dealing with operations and SSA values.
1179class FunctionParser : public Parser {
1180public:
1181 FunctionParser(ParserState &state) : Parser(state) {}
1182
Chris Lattner6119d382018-07-20 18:41:34 -07001183 /// After the function is finished parsing, this function checks to see if
1184 /// there are any remaining issues.
1185 ParseResult finalizeFunction();
1186
1187 /// This represents a use of an SSA value in the program. The first two
1188 /// entries in the tuple are the name and result number of a reference. The
1189 /// third is the location of the reference, which is used in case this ends up
1190 /// being a use of an undefined value.
1191 struct SSAUseInfo {
1192 StringRef name; // Value name, e.g. %42 or %abc
1193 unsigned number; // Number, specified with #12
1194 SMLoc loc; // Location of first definition or use.
1195 };
Chris Lattner7f9cc272018-07-19 08:35:28 -07001196
1197 /// Given a reference to an SSA value and its type, return a reference. This
1198 /// returns null on failure.
1199 SSAValue *resolveSSAUse(SSAUseInfo useInfo, Type *type);
1200
1201 /// Register a definition of a value with the symbol table.
1202 ParseResult addDefinition(SSAUseInfo useInfo, SSAValue *value);
1203
1204 // SSA parsing productions.
1205 ParseResult parseSSAUse(SSAUseInfo &result);
1206 ParseResult parseOptionalSSAUseList(Token::Kind endToken,
1207 SmallVectorImpl<SSAUseInfo> &results);
1208 SSAValue *parseSSAUseAndType();
1209 ParseResult
1210 parseOptionalSSAUseAndTypeList(Token::Kind endToken,
1211 SmallVectorImpl<SSAValue *> &results);
1212
1213 // Operations
1214 ParseResult parseOperation(const CreateOperationFunction &createOpFunc);
1215
1216private:
1217 /// This keeps track of all of the SSA values we are tracking, indexed by
Chris Lattner6119d382018-07-20 18:41:34 -07001218 /// their name. This has one entry per result number.
1219 llvm::StringMap<SmallVector<std::pair<SSAValue *, SMLoc>, 1>> values;
1220
1221 /// These are all of the placeholders we've made along with the location of
1222 /// their first reference, to allow checking for use of undefined values.
1223 DenseMap<SSAValue *, SMLoc> forwardReferencePlaceholders;
1224
1225 SSAValue *createForwardReferencePlaceholder(SMLoc loc, Type *type);
1226
1227 /// Return true if this is a forward reference.
1228 bool isForwardReferencePlaceholder(SSAValue *value) {
1229 return forwardReferencePlaceholders.count(value);
1230 }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001231};
1232} // end anonymous namespace
1233
Chris Lattner6119d382018-07-20 18:41:34 -07001234/// Create and remember a new placeholder for a forward reference.
1235SSAValue *FunctionParser::createForwardReferencePlaceholder(SMLoc loc,
1236 Type *type) {
1237 // Forward references are always created as instructions, even in ML
1238 // functions, because we just need something with a def/use chain.
1239 //
1240 // We create these placeholders as having an empty name, which we know cannot
1241 // be created through normal user input, allowing us to distinguish them.
1242 auto name = Identifier::get("placeholder", getContext());
1243 auto *inst = OperationInst::create(name, /*operands*/ {}, type, /*attrs*/ {},
1244 getContext());
1245 forwardReferencePlaceholders[inst->getResult(0)] = loc;
1246 return inst->getResult(0);
1247}
1248
Chris Lattner7f9cc272018-07-19 08:35:28 -07001249/// Given an unbound reference to an SSA value and its type, return a the value
1250/// it specifies. This returns null on failure.
1251SSAValue *FunctionParser::resolveSSAUse(SSAUseInfo useInfo, Type *type) {
Chris Lattner6119d382018-07-20 18:41:34 -07001252 auto &entries = values[useInfo.name];
1253
Chris Lattner7f9cc272018-07-19 08:35:28 -07001254 // If we have already seen a value of this name, return it.
Chris Lattner6119d382018-07-20 18:41:34 -07001255 if (useInfo.number < entries.size() && entries[useInfo.number].first) {
1256 auto *result = entries[useInfo.number].first;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001257 // Check that the type matches the other uses.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001258 if (result->getType() == type)
1259 return result;
1260
Chris Lattner6119d382018-07-20 18:41:34 -07001261 emitError(useInfo.loc, "use of value '" + useInfo.name.str() +
1262 "' expects different type than prior uses");
1263 emitError(entries[useInfo.number].second, "prior use here");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001264 return nullptr;
1265 }
1266
Chris Lattner6119d382018-07-20 18:41:34 -07001267 // Make sure we have enough slots for this.
1268 if (entries.size() <= useInfo.number)
1269 entries.resize(useInfo.number + 1);
1270
1271 // If the value has already been defined and this is an overly large result
1272 // number, diagnose that.
1273 if (entries[0].first && !isForwardReferencePlaceholder(entries[0].first))
1274 return (emitError(useInfo.loc, "reference to invalid result number"),
1275 nullptr);
1276
1277 // Otherwise, this is a forward reference. Create a placeholder and remember
1278 // that we did so.
1279 auto *result = createForwardReferencePlaceholder(useInfo.loc, type);
1280 entries[useInfo.number].first = result;
1281 entries[useInfo.number].second = useInfo.loc;
1282 return result;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001283}
1284
1285/// Register a definition of a value with the symbol table.
1286ParseResult FunctionParser::addDefinition(SSAUseInfo useInfo, SSAValue *value) {
Chris Lattner6119d382018-07-20 18:41:34 -07001287 auto &entries = values[useInfo.name];
Chris Lattner7f9cc272018-07-19 08:35:28 -07001288
Chris Lattner6119d382018-07-20 18:41:34 -07001289 // Make sure there is a slot for this value.
1290 if (entries.size() <= useInfo.number)
1291 entries.resize(useInfo.number + 1);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001292
Chris Lattner6119d382018-07-20 18:41:34 -07001293 // If we already have an entry for this, check to see if it was a definition
1294 // or a forward reference.
1295 if (auto *existing = entries[useInfo.number].first) {
1296 if (!isForwardReferencePlaceholder(existing)) {
1297 emitError(useInfo.loc,
1298 "redefinition of SSA value '" + useInfo.name + "'");
1299 return emitError(entries[useInfo.number].second,
1300 "previously defined here");
1301 }
1302
1303 // If it was a forward reference, update everything that used it to use the
1304 // actual definition instead, delete the forward ref, and remove it from our
1305 // set of forward references we track.
1306 existing->replaceAllUsesWith(value);
1307 existing->getDefiningInst()->destroy();
1308 forwardReferencePlaceholders.erase(existing);
1309 }
1310
1311 entries[useInfo.number].first = value;
1312 entries[useInfo.number].second = useInfo.loc;
1313 return ParseSuccess;
1314}
1315
1316/// After the function is finished parsing, this function checks to see if
1317/// there are any remaining issues.
1318ParseResult FunctionParser::finalizeFunction() {
1319 // Check for any forward references that are left. If we find any, error out.
1320 if (!forwardReferencePlaceholders.empty()) {
1321 SmallVector<std::pair<const char *, SSAValue *>, 4> errors;
1322 // Iteration over the map isn't determinstic, so sort by source location.
1323 for (auto entry : forwardReferencePlaceholders)
1324 errors.push_back({entry.second.getPointer(), entry.first});
1325 llvm::array_pod_sort(errors.begin(), errors.end());
1326
1327 for (auto entry : errors)
1328 emitError(SMLoc::getFromPointer(entry.first),
1329 "use of undeclared SSA value name");
1330 return ParseFailure;
1331 }
1332
1333 return ParseSuccess;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001334}
1335
Chris Lattner78276e32018-07-07 15:48:26 -07001336/// Parse a SSA operand for an instruction or statement.
1337///
1338/// ssa-use ::= ssa-id | ssa-constant
Chris Lattner7f9cc272018-07-19 08:35:28 -07001339/// TODO: SSA Constants.
Chris Lattner78276e32018-07-07 15:48:26 -07001340///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001341ParseResult FunctionParser::parseSSAUse(SSAUseInfo &result) {
Chris Lattner6119d382018-07-20 18:41:34 -07001342 result.name = getTokenSpelling();
1343 result.number = 0;
1344 result.loc = getToken().getLoc();
Chris Lattner7f9cc272018-07-19 08:35:28 -07001345 if (!consumeIf(Token::percent_identifier))
1346 return emitError("expected SSA operand");
Chris Lattner6119d382018-07-20 18:41:34 -07001347
1348 // If we have an affine map ID, it is a result number.
1349 if (getToken().is(Token::hash_identifier)) {
1350 if (auto value = getToken().getHashIdentifierNumber())
1351 result.number = value.getValue();
1352 else
1353 return emitError("invalid SSA value result number");
1354 consumeToken(Token::hash_identifier);
1355 }
1356
Chris Lattner7f9cc272018-07-19 08:35:28 -07001357 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001358}
1359
1360/// Parse a (possibly empty) list of SSA operands.
1361///
1362/// ssa-use-list ::= ssa-use (`,` ssa-use)*
1363/// ssa-use-list-opt ::= ssa-use-list?
1364///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001365ParseResult
1366FunctionParser::parseOptionalSSAUseList(Token::Kind endToken,
1367 SmallVectorImpl<SSAUseInfo> &results) {
1368 return parseCommaSeparatedList(endToken, [&]() -> ParseResult {
1369 SSAUseInfo result;
1370 if (parseSSAUse(result))
1371 return ParseFailure;
1372 results.push_back(result);
1373 return ParseSuccess;
1374 });
Chris Lattner78276e32018-07-07 15:48:26 -07001375}
1376
1377/// Parse an SSA use with an associated type.
1378///
1379/// ssa-use-and-type ::= ssa-use `:` type
Chris Lattner7f9cc272018-07-19 08:35:28 -07001380SSAValue *FunctionParser::parseSSAUseAndType() {
1381 SSAUseInfo useInfo;
1382 if (parseSSAUse(useInfo))
1383 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001384
1385 if (!consumeIf(Token::colon))
Chris Lattner7f9cc272018-07-19 08:35:28 -07001386 return (emitError("expected ':' and type for SSA operand"), nullptr);
Chris Lattner78276e32018-07-07 15:48:26 -07001387
Chris Lattner7f9cc272018-07-19 08:35:28 -07001388 auto *type = parseType();
1389 if (!type)
1390 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001391
Chris Lattner7f9cc272018-07-19 08:35:28 -07001392 return resolveSSAUse(useInfo, type);
Chris Lattner78276e32018-07-07 15:48:26 -07001393}
1394
1395/// Parse a (possibly empty) list of SSA operands with types.
1396///
1397/// ssa-use-and-type-list ::= ssa-use-and-type (`,` ssa-use-and-type)*
1398///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001399ParseResult FunctionParser::parseOptionalSSAUseAndTypeList(
1400 Token::Kind endToken, SmallVectorImpl<SSAValue *> &results) {
1401 return parseCommaSeparatedList(endToken, [&]() -> ParseResult {
1402 if (auto *value = parseSSAUseAndType()) {
1403 results.push_back(value);
1404 return ParseSuccess;
1405 }
1406 return ParseFailure;
1407 });
Chris Lattner78276e32018-07-07 15:48:26 -07001408}
1409
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001410/// Parse the CFG or MLFunc operation.
1411///
1412/// TODO(clattner): This is a change from the MLIR spec as written, it is an
1413/// experiment that will eliminate "builtin" instructions as a thing.
1414///
1415/// operation ::=
1416/// (ssa-id `=`)? string '(' ssa-use-list? ')' attribute-dict?
1417/// `:` function-type
1418///
1419ParseResult
Chris Lattner7f9cc272018-07-19 08:35:28 -07001420FunctionParser::parseOperation(const CreateOperationFunction &createOpFunc) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001421 auto loc = getToken().getLoc();
1422
1423 StringRef resultID;
1424 if (getToken().is(Token::percent_identifier)) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001425 resultID = getTokenSpelling();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001426 consumeToken(Token::percent_identifier);
1427 if (!consumeIf(Token::equal))
1428 return emitError("expected '=' after SSA name");
1429 }
1430
1431 if (getToken().isNot(Token::string))
1432 return emitError("expected operation name in quotes");
1433
1434 auto name = getToken().getStringValue();
1435 if (name.empty())
1436 return emitError("empty operation name is invalid");
1437
1438 consumeToken(Token::string);
1439
1440 if (!consumeIf(Token::l_paren))
1441 return emitError("expected '(' to start operand list");
1442
1443 // Parse the operand list.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001444 SmallVector<SSAUseInfo, 8> operandInfos;
1445 parseOptionalSSAUseList(Token::r_paren, operandInfos);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001446
1447 SmallVector<NamedAttribute, 4> attributes;
1448 if (getToken().is(Token::l_brace)) {
1449 if (parseAttributeDict(attributes))
1450 return ParseFailure;
1451 }
1452
Chris Lattner3b2ef762018-07-18 15:31:25 -07001453 if (!consumeIf(Token::colon))
1454 return emitError("expected ':' followed by instruction type");
1455
1456 auto typeLoc = getToken().getLoc();
1457 auto type = parseType();
1458 if (!type)
1459 return ParseFailure;
1460 auto fnType = dyn_cast<FunctionType>(type);
1461 if (!fnType)
1462 return emitError(typeLoc, "expected function type");
1463
Chris Lattner7f9cc272018-07-19 08:35:28 -07001464 // Check that we have the right number of types for the operands.
1465 auto operandTypes = fnType->getInputs();
1466 if (operandTypes.size() != operandInfos.size()) {
1467 auto plural = "s"[operandInfos.size() == 1];
1468 return emitError(typeLoc, "expected " + llvm::utostr(operandInfos.size()) +
Chris Lattnerf8cce872018-07-20 09:28:54 -07001469 " operand type" + plural + " but had " +
Chris Lattner7f9cc272018-07-19 08:35:28 -07001470 llvm::utostr(operandTypes.size()));
1471 }
1472
1473 // Resolve all of the operands.
1474 SmallVector<SSAValue *, 8> operands;
1475 for (unsigned i = 0, e = operandInfos.size(); i != e; ++i) {
1476 operands.push_back(resolveSSAUse(operandInfos[i], operandTypes[i]));
1477 if (!operands.back())
1478 return ParseFailure;
1479 }
1480
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001481 auto nameId = builder.getIdentifier(name);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001482 auto op = createOpFunc(nameId, operands, fnType->getResults(), attributes);
1483 if (!op)
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001484 return ParseFailure;
1485
1486 // We just parsed an operation. If it is a recognized one, verify that it
1487 // is structurally as we expect. If not, produce an error with a reasonable
1488 // source location.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001489 if (auto *opInfo = op->getAbstractOperation(builder.getContext())) {
1490 if (auto error = opInfo->verifyInvariants(op))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001491 return emitError(loc, error);
1492 }
1493
Chris Lattner7f9cc272018-07-19 08:35:28 -07001494 // If the instruction had a name, register it.
1495 if (!resultID.empty()) {
1496 // FIXME: Add result infra to handle Stmt results as well to make this
1497 // generic.
1498 if (auto *inst = dyn_cast<OperationInst>(op)) {
Chris Lattnerf8cce872018-07-20 09:28:54 -07001499 if (inst->getNumResults() == 0)
Chris Lattner7f9cc272018-07-19 08:35:28 -07001500 return emitError(loc, "cannot name an operation with no results");
1501
Chris Lattner6119d382018-07-20 18:41:34 -07001502 for (unsigned i = 0, e = inst->getNumResults(); i != e; ++i)
1503 addDefinition({resultID, i, loc}, inst->getResult(i));
Chris Lattner7f9cc272018-07-19 08:35:28 -07001504 }
1505 }
1506
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001507 return ParseSuccess;
1508}
Chris Lattnere79379a2018-06-22 10:39:19 -07001509
Chris Lattner48af7d12018-07-09 19:05:38 -07001510//===----------------------------------------------------------------------===//
1511// CFG Functions
1512//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001513
Chris Lattner4c95a502018-06-23 16:03:42 -07001514namespace {
Chris Lattner48af7d12018-07-09 19:05:38 -07001515/// This is a specialized parser for CFGFunction's, maintaining the state
1516/// transient to their bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001517class CFGFunctionParser : public FunctionParser {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001518public:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001519 CFGFunctionParser(ParserState &state, CFGFunction *function)
Chris Lattner7f9cc272018-07-19 08:35:28 -07001520 : FunctionParser(state), function(function), builder(function) {}
Chris Lattner2e595eb2018-07-10 10:08:27 -07001521
1522 ParseResult parseFunctionBody();
1523
1524private:
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001525 CFGFunction *function;
1526 llvm::StringMap<std::pair<BasicBlock*, SMLoc>> blocksByName;
Chris Lattner48af7d12018-07-09 19:05:38 -07001527
1528 /// This builder intentionally shadows the builder in the base class, with a
1529 /// more specific builder type.
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001530 CFGFuncBuilder builder;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001531
Chris Lattner4c95a502018-06-23 16:03:42 -07001532 /// Get the basic block with the specified name, creating it if it doesn't
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001533 /// already exist. The location specified is the point of use, which allows
1534 /// us to diagnose references to blocks that are not defined precisely.
1535 BasicBlock *getBlockNamed(StringRef name, SMLoc loc) {
1536 auto &blockAndLoc = blocksByName[name];
1537 if (!blockAndLoc.first) {
Chris Lattner3a467cc2018-07-01 20:28:00 -07001538 blockAndLoc.first = new BasicBlock();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001539 blockAndLoc.second = loc;
Chris Lattner4c95a502018-06-23 16:03:42 -07001540 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001541 return blockAndLoc.first;
Chris Lattner4c95a502018-06-23 16:03:42 -07001542 }
Chris Lattner48af7d12018-07-09 19:05:38 -07001543
Chris Lattner48af7d12018-07-09 19:05:38 -07001544 ParseResult parseBasicBlock();
1545 OperationInst *parseCFGOperation();
1546 TerminatorInst *parseTerminator();
Chris Lattner4c95a502018-06-23 16:03:42 -07001547};
1548} // end anonymous namespace
1549
Chris Lattner48af7d12018-07-09 19:05:38 -07001550ParseResult CFGFunctionParser::parseFunctionBody() {
1551 if (!consumeIf(Token::l_brace))
1552 return emitError("expected '{' in CFG function");
1553
1554 // Make sure we have at least one block.
1555 if (getToken().is(Token::r_brace))
1556 return emitError("CFG functions must have at least one basic block");
Chris Lattner4c95a502018-06-23 16:03:42 -07001557
1558 // Parse the list of blocks.
1559 while (!consumeIf(Token::r_brace))
Chris Lattner48af7d12018-07-09 19:05:38 -07001560 if (parseBasicBlock())
Chris Lattner4c95a502018-06-23 16:03:42 -07001561 return ParseFailure;
1562
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001563 // Verify that all referenced blocks were defined. Iteration over a
1564 // StringMap isn't determinstic, but this is good enough for our purposes.
Chris Lattner48af7d12018-07-09 19:05:38 -07001565 for (auto &elt : blocksByName) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001566 auto *bb = elt.second.first;
Chris Lattner3a467cc2018-07-01 20:28:00 -07001567 if (!bb->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001568 return emitError(elt.second.second,
1569 "reference to an undefined basic block '" +
1570 elt.first() + "'");
1571 }
1572
Chris Lattner48af7d12018-07-09 19:05:38 -07001573 getModule()->functionList.push_back(function);
Chris Lattner6119d382018-07-20 18:41:34 -07001574
1575 return finalizeFunction();
Chris Lattner4c95a502018-06-23 16:03:42 -07001576}
1577
1578/// Basic block declaration.
1579///
1580/// basic-block ::= bb-label instruction* terminator-stmt
1581/// bb-label ::= bb-id bb-arg-list? `:`
1582/// bb-id ::= bare-id
1583/// bb-arg-list ::= `(` ssa-id-and-type-list? `)`
1584///
Chris Lattner48af7d12018-07-09 19:05:38 -07001585ParseResult CFGFunctionParser::parseBasicBlock() {
1586 SMLoc nameLoc = getToken().getLoc();
1587 auto name = getTokenSpelling();
Chris Lattner4c95a502018-06-23 16:03:42 -07001588 if (!consumeIf(Token::bare_identifier))
1589 return emitError("expected basic block name");
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001590
Chris Lattner48af7d12018-07-09 19:05:38 -07001591 auto *block = getBlockNamed(name, nameLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001592
1593 // If this block has already been parsed, then this is a redefinition with the
1594 // same block name.
Chris Lattner3a467cc2018-07-01 20:28:00 -07001595 if (block->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001596 return emitError(nameLoc, "redefinition of block '" + name.str() + "'");
1597
Chris Lattner3a467cc2018-07-01 20:28:00 -07001598 // Add the block to the function.
Chris Lattner48af7d12018-07-09 19:05:38 -07001599 function->push_back(block);
Chris Lattner4c95a502018-06-23 16:03:42 -07001600
Chris Lattner78276e32018-07-07 15:48:26 -07001601 // If an argument list is present, parse it.
1602 if (consumeIf(Token::l_paren)) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001603 SmallVector<SSAValue *, 8> bbArgs;
1604 if (parseOptionalSSAUseAndTypeList(Token::r_paren, bbArgs))
Chris Lattner78276e32018-07-07 15:48:26 -07001605 return ParseFailure;
1606
1607 // TODO: attach it.
1608 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001609
1610 if (!consumeIf(Token::colon))
1611 return emitError("expected ':' after basic block name");
1612
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001613 // Set the insertion point to the block we want to insert new operations into.
Chris Lattner48af7d12018-07-09 19:05:38 -07001614 builder.setInsertionPoint(block);
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001615
Chris Lattner7f9cc272018-07-19 08:35:28 -07001616 auto createOpFunc = [&](Identifier name, ArrayRef<SSAValue *> operands,
1617 ArrayRef<Type *> resultTypes,
1618 ArrayRef<NamedAttribute> attrs) -> Operation * {
1619 SmallVector<CFGValue *, 8> cfgOperands;
1620 cfgOperands.reserve(operands.size());
1621 for (auto *op : operands)
1622 cfgOperands.push_back(cast<CFGValue>(op));
1623 return builder.createOperation(name, cfgOperands, resultTypes, attrs);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001624 };
1625
Chris Lattnered65a732018-06-28 20:45:33 -07001626 // Parse the list of operations that make up the body of the block.
Chris Lattner48af7d12018-07-09 19:05:38 -07001627 while (getToken().isNot(Token::kw_return, Token::kw_br)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001628 if (parseOperation(createOpFunc))
Chris Lattnered65a732018-06-28 20:45:33 -07001629 return ParseFailure;
1630 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001631
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001632 if (!parseTerminator())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001633 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07001634
1635 return ParseSuccess;
1636}
1637
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001638/// Parse the terminator instruction for a basic block.
1639///
1640/// terminator-stmt ::= `br` bb-id branch-use-list?
1641/// branch-use-list ::= `(` ssa-use-and-type-list? `)`
1642/// terminator-stmt ::=
1643/// `cond_br` ssa-use `,` bb-id branch-use-list? `,` bb-id branch-use-list?
1644/// terminator-stmt ::= `return` ssa-use-and-type-list?
1645///
Chris Lattner48af7d12018-07-09 19:05:38 -07001646TerminatorInst *CFGFunctionParser::parseTerminator() {
1647 switch (getToken().getKind()) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001648 default:
Chris Lattner3a467cc2018-07-01 20:28:00 -07001649 return (emitError("expected terminator at end of basic block"), nullptr);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001650
1651 case Token::kw_return:
1652 consumeToken(Token::kw_return);
Chris Lattner48af7d12018-07-09 19:05:38 -07001653 return builder.createReturnInst();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001654
1655 case Token::kw_br: {
1656 consumeToken(Token::kw_br);
Chris Lattner48af7d12018-07-09 19:05:38 -07001657 auto destBB = getBlockNamed(getTokenSpelling(), getToken().getLoc());
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001658 if (!consumeIf(Token::bare_identifier))
Chris Lattner3a467cc2018-07-01 20:28:00 -07001659 return (emitError("expected basic block name"), nullptr);
Chris Lattner48af7d12018-07-09 19:05:38 -07001660 return builder.createBranchInst(destBB);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001661 }
Chris Lattner78276e32018-07-07 15:48:26 -07001662 // TODO: cond_br.
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001663 }
1664}
1665
Chris Lattner48af7d12018-07-09 19:05:38 -07001666//===----------------------------------------------------------------------===//
1667// ML Functions
1668//===----------------------------------------------------------------------===//
1669
1670namespace {
1671/// Refined parser for MLFunction bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001672class MLFunctionParser : public FunctionParser {
Chris Lattner48af7d12018-07-09 19:05:38 -07001673public:
Chris Lattner48af7d12018-07-09 19:05:38 -07001674 MLFunctionParser(ParserState &state, MLFunction *function)
Chris Lattner7f9cc272018-07-19 08:35:28 -07001675 : FunctionParser(state), function(function), builder(function) {}
Chris Lattner48af7d12018-07-09 19:05:38 -07001676
1677 ParseResult parseFunctionBody();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001678
1679private:
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001680 MLFunction *function;
1681
1682 /// This builder intentionally shadows the builder in the base class, with a
1683 /// more specific builder type.
1684 MLFuncBuilder builder;
1685
1686 ParseResult parseForStmt();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001687 AffineConstantExpr *parseIntConstant();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001688 ParseResult parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001689 ParseResult parseElseClause(IfClause *elseClause);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001690 ParseResult parseStatements(StmtBlock *block);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001691 ParseResult parseStmtBlock(StmtBlock *block);
Chris Lattner48af7d12018-07-09 19:05:38 -07001692};
1693} // end anonymous namespace
1694
Chris Lattner48af7d12018-07-09 19:05:38 -07001695ParseResult MLFunctionParser::parseFunctionBody() {
1696 if (!consumeIf(Token::l_brace))
1697 return emitError("expected '{' in ML function");
1698
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001699 // Parse statements in this function
1700 if (parseStatements(function))
1701 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001702
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001703 if (!consumeIf(Token::kw_return))
1704 emitError("ML function must end with return statement");
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001705
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001706 // TODO: store return operands in the IR.
1707 SmallVector<SSAUseInfo, 4> dummyUseInfo;
1708 if (parseOptionalSSAUseList(Token::r_brace, dummyUseInfo))
1709 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001710
Chris Lattner48af7d12018-07-09 19:05:38 -07001711 getModule()->functionList.push_back(function);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001712
Chris Lattner6119d382018-07-20 18:41:34 -07001713 return finalizeFunction();
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001714}
1715
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001716/// For statement.
1717///
Chris Lattner48af7d12018-07-09 19:05:38 -07001718/// ml-for-stmt ::= `for` ssa-id `=` lower-bound `to` upper-bound
1719/// (`step` integer-literal)? `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001720///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001721ParseResult MLFunctionParser::parseForStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001722 consumeToken(Token::kw_for);
1723
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001724 // Parse induction variable
1725 if (getToken().isNot(Token::percent_identifier))
1726 return emitError("expected SSA identifier for the loop variable");
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001727
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001728 // TODO: create SSA value definition from name
1729 StringRef name = getTokenSpelling().drop_front();
1730 (void)name;
1731
1732 consumeToken(Token::percent_identifier);
1733
1734 if (!consumeIf(Token::equal))
1735 return emitError("expected =");
1736
1737 // Parse loop bounds
1738 AffineConstantExpr *lowerBound = parseIntConstant();
1739 if (!lowerBound)
1740 return ParseFailure;
1741
1742 if (!consumeIf(Token::kw_to))
1743 return emitError("expected 'to' between bounds");
1744
1745 AffineConstantExpr *upperBound = parseIntConstant();
1746 if (!upperBound)
1747 return ParseFailure;
1748
1749 // Parse step
1750 AffineConstantExpr *step = nullptr;
1751 if (consumeIf(Token::kw_step)) {
1752 step = parseIntConstant();
1753 if (!step)
1754 return ParseFailure;
1755 }
1756
1757 // Create for statement.
1758 ForStmt *stmt = builder.createFor(lowerBound, upperBound, step);
1759
1760 // If parsing of the for statement body fails,
1761 // MLIR contains for statement with those nested statements that have been
1762 // successfully parsed.
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001763 if (parseStmtBlock(static_cast<StmtBlock *>(stmt)))
1764 return ParseFailure;
1765
1766 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001767}
1768
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001769// This method is temporary workaround to parse simple loop bounds and
1770// step.
1771// TODO: remove this method once it's no longer used.
1772AffineConstantExpr *MLFunctionParser::parseIntConstant() {
1773 if (getToken().isNot(Token::integer))
1774 return (emitError("expected non-negative integer for now"), nullptr);
1775
1776 auto val = getToken().getUInt64IntegerValue();
1777 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
1778 return (emitError("constant too large for affineint"), nullptr);
1779 }
1780 consumeToken(Token::integer);
1781 return builder.getConstantExpr((int64_t)val.getValue());
1782}
1783
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001784/// If statement.
1785///
Chris Lattner48af7d12018-07-09 19:05:38 -07001786/// ml-if-head ::= `if` ml-if-cond `{` ml-stmt* `}`
1787/// | ml-if-head `else` `if` ml-if-cond `{` ml-stmt* `}`
1788/// ml-if-stmt ::= ml-if-head
1789/// | ml-if-head `else` `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001790///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001791ParseResult MLFunctionParser::parseIfStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001792 consumeToken(Token::kw_if);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001793 if (!consumeIf(Token::l_paren))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001794 return emitError("expected (");
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001795
1796 //TODO: parse condition
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001797
1798 if (!consumeIf(Token::r_paren))
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001799 return emitError("expected ')'");
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001800
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001801 IfStmt *ifStmt = builder.createIf();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001802 IfClause *thenClause = ifStmt->getThenClause();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001803
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001804 // When parsing of an if statement body fails, the IR contains
1805 // the if statement with the portion of the body that has been
1806 // successfully parsed.
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001807 if (parseStmtBlock(thenClause))
1808 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001809
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001810 if (consumeIf(Token::kw_else)) {
1811 IfClause *elseClause = ifStmt->createElseClause();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001812 if (parseElseClause(elseClause))
1813 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001814 }
1815
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001816 return ParseSuccess;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001817}
1818
1819ParseResult MLFunctionParser::parseElseClause(IfClause *elseClause) {
1820 if (getToken().is(Token::kw_if)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001821 builder.setInsertionPoint(elseClause);
1822 return parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001823 }
1824
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001825 return parseStmtBlock(elseClause);
1826}
1827
1828///
1829/// Parse a list of statements ending with `return` or `}`
1830///
1831ParseResult MLFunctionParser::parseStatements(StmtBlock *block) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001832 auto createOpFunc = [&](Identifier name, ArrayRef<SSAValue *> operands,
1833 ArrayRef<Type *> resultTypes,
1834 ArrayRef<NamedAttribute> attrs) -> Operation * {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001835 return builder.createOperation(name, attrs);
1836 };
1837
1838 builder.setInsertionPoint(block);
1839
1840 while (getToken().isNot(Token::kw_return, Token::r_brace)) {
1841 switch (getToken().getKind()) {
1842 default:
1843 if (parseOperation(createOpFunc))
1844 return ParseFailure;
1845 break;
1846 case Token::kw_for:
1847 if (parseForStmt())
1848 return ParseFailure;
1849 break;
1850 case Token::kw_if:
1851 if (parseIfStmt())
1852 return ParseFailure;
1853 break;
1854 } // end switch
1855 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001856
1857 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001858}
1859
1860///
1861/// Parse `{` ml-stmt* `}`
1862///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001863ParseResult MLFunctionParser::parseStmtBlock(StmtBlock *block) {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001864 if (!consumeIf(Token::l_brace))
1865 return emitError("expected '{' before statement list");
1866
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001867 if (parseStatements(block))
1868 return ParseFailure;
1869
1870 if (!consumeIf(Token::r_brace))
1871 return emitError("expected '}' at the end of the statement block");
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001872
1873 return ParseSuccess;
1874}
1875
Chris Lattner4c95a502018-06-23 16:03:42 -07001876//===----------------------------------------------------------------------===//
1877// Top-level entity parsing.
1878//===----------------------------------------------------------------------===//
1879
Chris Lattner2e595eb2018-07-10 10:08:27 -07001880namespace {
1881/// This parser handles entities that are only valid at the top level of the
1882/// file.
1883class ModuleParser : public Parser {
1884public:
1885 explicit ModuleParser(ParserState &state) : Parser(state) {}
1886
1887 ParseResult parseModule();
1888
1889private:
1890 ParseResult parseAffineMapDef();
1891
1892 // Functions.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001893 ParseResult parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
1894 SmallVectorImpl<StringRef> &argNames);
1895 ParseResult parseFunctionSignature(StringRef &name, FunctionType *&type,
1896 SmallVectorImpl<StringRef> *argNames);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001897 ParseResult parseExtFunc();
1898 ParseResult parseCFGFunc();
1899 ParseResult parseMLFunc();
1900};
1901} // end anonymous namespace
1902
1903/// Affine map declaration.
1904///
1905/// affine-map-def ::= affine-map-id `=` affine-map-inline
1906///
1907ParseResult ModuleParser::parseAffineMapDef() {
1908 assert(getToken().is(Token::hash_identifier));
1909
1910 StringRef affineMapId = getTokenSpelling().drop_front();
1911
1912 // Check for redefinitions.
1913 auto *&entry = getState().affineMapDefinitions[affineMapId];
1914 if (entry)
1915 return emitError("redefinition of affine map id '" + affineMapId + "'");
1916
1917 consumeToken(Token::hash_identifier);
1918
1919 // Parse the '='
1920 if (!consumeIf(Token::equal))
1921 return emitError("expected '=' in affine map outlined definition");
1922
1923 entry = parseAffineMapInline();
1924 if (!entry)
1925 return ParseFailure;
1926
Chris Lattner2e595eb2018-07-10 10:08:27 -07001927 return ParseSuccess;
1928}
1929
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001930/// Parse a (possibly empty) list of MLFunction arguments with types.
1931///
1932/// ml-argument ::= ssa-id `:` type
1933/// ml-argument-list ::= ml-argument (`,` ml-argument)* | /*empty*/
1934///
1935ParseResult
1936ModuleParser::parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
1937 SmallVectorImpl<StringRef> &argNames) {
1938 auto parseElt = [&]() -> ParseResult {
1939 // Parse argument name
1940 if (getToken().isNot(Token::percent_identifier))
1941 return emitError("expected SSA identifier");
1942
1943 StringRef name = getTokenSpelling().drop_front();
1944 consumeToken(Token::percent_identifier);
1945 argNames.push_back(name);
1946
1947 if (!consumeIf(Token::colon))
1948 return emitError("expected ':'");
1949
1950 // Parse argument type
1951 auto elt = parseType();
1952 if (!elt)
1953 return ParseFailure;
1954 argTypes.push_back(elt);
1955
1956 return ParseSuccess;
1957 };
1958
1959 if (!consumeIf(Token::l_paren))
1960 llvm_unreachable("expected '('");
1961
1962 return parseCommaSeparatedList(Token::r_paren, parseElt);
1963}
1964
Chris Lattner2e595eb2018-07-10 10:08:27 -07001965/// Parse a function signature, starting with a name and including the parameter
1966/// list.
1967///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001968/// argument-list ::= type (`,` type)* | /*empty*/ | ml-argument-list
Chris Lattner2e595eb2018-07-10 10:08:27 -07001969/// function-signature ::= function-id `(` argument-list `)` (`->` type-list)?
1970///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001971ParseResult
1972ModuleParser::parseFunctionSignature(StringRef &name, FunctionType *&type,
1973 SmallVectorImpl<StringRef> *argNames) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001974 if (getToken().isNot(Token::at_identifier))
1975 return emitError("expected a function identifier like '@foo'");
1976
1977 name = getTokenSpelling().drop_front();
1978 consumeToken(Token::at_identifier);
1979
1980 if (getToken().isNot(Token::l_paren))
1981 return emitError("expected '(' in function signature");
1982
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001983 SmallVector<Type *, 4> argTypes;
1984 ParseResult parseResult;
1985
1986 if (argNames)
1987 parseResult = parseMLArgumentList(argTypes, *argNames);
1988 else
1989 parseResult = parseTypeList(argTypes);
1990
1991 if (parseResult)
Chris Lattner2e595eb2018-07-10 10:08:27 -07001992 return ParseFailure;
1993
1994 // Parse the return type if present.
1995 SmallVector<Type *, 4> results;
1996 if (consumeIf(Token::arrow)) {
1997 if (parseTypeList(results))
1998 return ParseFailure;
1999 }
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002000 type = builder.getFunctionType(argTypes, results);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002001 return ParseSuccess;
2002}
2003
2004/// External function declarations.
2005///
2006/// ext-func ::= `extfunc` function-signature
2007///
2008ParseResult ModuleParser::parseExtFunc() {
2009 consumeToken(Token::kw_extfunc);
2010
2011 StringRef name;
2012 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002013 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002014 return ParseFailure;
2015
2016 // Okay, the external function definition was parsed correctly.
2017 getModule()->functionList.push_back(new ExtFunction(name, type));
2018 return ParseSuccess;
2019}
2020
2021/// CFG function declarations.
2022///
2023/// cfg-func ::= `cfgfunc` function-signature `{` basic-block+ `}`
2024///
2025ParseResult ModuleParser::parseCFGFunc() {
2026 consumeToken(Token::kw_cfgfunc);
2027
2028 StringRef name;
2029 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002030 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002031 return ParseFailure;
2032
2033 // Okay, the CFG function signature was parsed correctly, create the function.
2034 auto function = new CFGFunction(name, type);
2035
2036 return CFGFunctionParser(getState(), function).parseFunctionBody();
2037}
2038
2039/// ML function declarations.
2040///
2041/// ml-func ::= `mlfunc` ml-func-signature `{` ml-stmt* ml-return-stmt `}`
2042///
2043ParseResult ModuleParser::parseMLFunc() {
2044 consumeToken(Token::kw_mlfunc);
2045
2046 StringRef name;
2047 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002048 SmallVector<StringRef, 4> argNames;
Chris Lattner2e595eb2018-07-10 10:08:27 -07002049 // FIXME: Parse ML function signature (args + types)
2050 // by passing pointer to SmallVector<identifier> into parseFunctionSignature
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002051
2052 if (parseFunctionSignature(name, type, &argNames))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002053 return ParseFailure;
2054
2055 // Okay, the ML function signature was parsed correctly, create the function.
2056 auto function = new MLFunction(name, type);
2057
2058 return MLFunctionParser(getState(), function).parseFunctionBody();
2059}
2060
Chris Lattnere79379a2018-06-22 10:39:19 -07002061/// This is the top-level module parser.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002062ParseResult ModuleParser::parseModule() {
Chris Lattnere79379a2018-06-22 10:39:19 -07002063 while (1) {
Chris Lattner48af7d12018-07-09 19:05:38 -07002064 switch (getToken().getKind()) {
Chris Lattnere79379a2018-06-22 10:39:19 -07002065 default:
2066 emitError("expected a top level entity");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002067 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002068
Uday Bondhugula015cbb12018-07-03 20:16:08 -07002069 // If we got to the end of the file, then we're done.
Chris Lattnere79379a2018-06-22 10:39:19 -07002070 case Token::eof:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002071 return ParseSuccess;
Chris Lattnere79379a2018-06-22 10:39:19 -07002072
2073 // If we got an error token, then the lexer already emitted an error, just
2074 // stop. Someday we could introduce error recovery if there was demand for
2075 // it.
2076 case Token::error:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002077 return ParseFailure;
2078
2079 case Token::hash_identifier:
2080 if (parseAffineMapDef())
2081 return ParseFailure;
2082 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002083
2084 case Token::kw_extfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002085 if (parseExtFunc())
2086 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002087 break;
2088
Chris Lattner4c95a502018-06-23 16:03:42 -07002089 case Token::kw_cfgfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002090 if (parseCFGFunc())
2091 return ParseFailure;
MLIR Teamf85a6262018-06-27 11:03:08 -07002092 break;
Chris Lattner4c95a502018-06-23 16:03:42 -07002093
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002094 case Token::kw_mlfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002095 if (parseMLFunc())
2096 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002097 break;
2098
Uday Bondhugula015cbb12018-07-03 20:16:08 -07002099 // TODO: affine entity declarations, etc.
Chris Lattnere79379a2018-06-22 10:39:19 -07002100 }
2101 }
2102}
2103
2104//===----------------------------------------------------------------------===//
2105
Jacques Pienaar7b829702018-07-03 13:24:09 -07002106void mlir::defaultErrorReporter(const llvm::SMDiagnostic &error) {
2107 const auto &sourceMgr = *error.getSourceMgr();
2108 sourceMgr.PrintMessage(error.getLoc(), error.getKind(), error.getMessage());
2109}
2110
Chris Lattnere79379a2018-06-22 10:39:19 -07002111/// This parses the file specified by the indicated SourceMgr and returns an
2112/// MLIR module if it was valid. If not, it emits diagnostics and returns null.
Jacques Pienaar9c411be2018-06-24 19:17:35 -07002113Module *mlir::parseSourceFile(llvm::SourceMgr &sourceMgr, MLIRContext *context,
Jacques Pienaar7b829702018-07-03 13:24:09 -07002114 SMDiagnosticHandlerTy errorReporter) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002115 // This is the result module we are parsing into.
2116 std::unique_ptr<Module> module(new Module(context));
2117
2118 ParserState state(sourceMgr, module.get(),
Jacques Pienaar0bffd862018-07-11 13:26:23 -07002119 errorReporter ? errorReporter : defaultErrorReporter);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002120 if (ModuleParser(state).parseModule())
2121 return nullptr;
Chris Lattner21e67f62018-07-06 10:46:19 -07002122
2123 // Make sure the parse module has no other structural problems detected by the
2124 // verifier.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002125 module->verify();
2126 return module.release();
Chris Lattnere79379a2018-06-22 10:39:19 -07002127}