blob: 1f37356acd70afb2f4ccfeebe5573a8674ff55a4 [file] [log] [blame]
Chris Lattnere79379a2018-06-22 10:39:19 -07001//===- Parser.cpp - MLIR Parser Implementation ----------------------------===//
2//
3// Copyright 2019 The MLIR Authors.
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16// =============================================================================
17//
18// This file implements the parser for the MLIR textual form.
19//
20//===----------------------------------------------------------------------===//
21
22#include "mlir/Parser.h"
23#include "Lexer.h"
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -070024#include "mlir/IR/AffineExpr.h"
MLIR Teamf85a6262018-06-27 11:03:08 -070025#include "mlir/IR/AffineMap.h"
Chris Lattner7121b802018-07-04 20:45:39 -070026#include "mlir/IR/Attributes.h"
Chris Lattner158e0a3e2018-07-08 20:51:38 -070027#include "mlir/IR/Builders.h"
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -070028#include "mlir/IR/MLFunction.h"
Chris Lattner21e67f62018-07-06 10:46:19 -070029#include "mlir/IR/Module.h"
30#include "mlir/IR/OperationSet.h"
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -070031#include "mlir/IR/Statements.h"
Chris Lattnerf7e22732018-06-22 22:03:48 -070032#include "mlir/IR/Types.h"
Chris Lattner6119d382018-07-20 18:41:34 -070033#include "llvm/ADT/DenseMap.h"
Chris Lattnere79379a2018-06-22 10:39:19 -070034#include "llvm/Support/SourceMgr.h"
35using namespace mlir;
36using llvm::SourceMgr;
Chris Lattner4c95a502018-06-23 16:03:42 -070037using llvm::SMLoc;
Chris Lattnere79379a2018-06-22 10:39:19 -070038
Chris Lattnerf7e22732018-06-22 22:03:48 -070039/// Simple enum to make code read better in cases that would otherwise return a
40/// bool value. Failure is "true" in a boolean context.
Chris Lattnere79379a2018-06-22 10:39:19 -070041enum ParseResult {
42 ParseSuccess,
43 ParseFailure
44};
45
Chris Lattner48af7d12018-07-09 19:05:38 -070046namespace {
47class Parser;
48
49/// This class refers to all of the state maintained globally by the parser,
50/// such as the current lexer position etc. The Parser base class provides
51/// methods to access this.
52class ParserState {
Chris Lattnered65a732018-06-28 20:45:33 -070053public:
Chris Lattner2e595eb2018-07-10 10:08:27 -070054 ParserState(llvm::SourceMgr &sourceMgr, Module *module,
Chris Lattner48af7d12018-07-09 19:05:38 -070055 SMDiagnosticHandlerTy errorReporter)
Chris Lattner2e595eb2018-07-10 10:08:27 -070056 : context(module->getContext()), module(module),
57 lex(sourceMgr, errorReporter), curToken(lex.lexToken()),
Jacques Pienaard4c784e2018-07-11 00:07:36 -070058 errorReporter(errorReporter) {}
Chris Lattner2e595eb2018-07-10 10:08:27 -070059
60 // A map from affine map identifier to AffineMap.
61 llvm::StringMap<AffineMap *> affineMapDefinitions;
Chris Lattnere79379a2018-06-22 10:39:19 -070062
Chris Lattnere79379a2018-06-22 10:39:19 -070063private:
Chris Lattner48af7d12018-07-09 19:05:38 -070064 ParserState(const ParserState &) = delete;
65 void operator=(const ParserState &) = delete;
66
67 friend class Parser;
68
69 // The context we're parsing into.
Chris Lattner2e595eb2018-07-10 10:08:27 -070070 MLIRContext *const context;
71
72 // This is the module we are parsing into.
73 Module *const module;
Chris Lattnerf7e22732018-06-22 22:03:48 -070074
75 // The lexer for the source file we're parsing.
Chris Lattnere79379a2018-06-22 10:39:19 -070076 Lexer lex;
77
78 // This is the next token that hasn't been consumed yet.
79 Token curToken;
80
Jacques Pienaar9c411be2018-06-24 19:17:35 -070081 // The diagnostic error reporter.
Chris Lattner2e595eb2018-07-10 10:08:27 -070082 SMDiagnosticHandlerTy const errorReporter;
Chris Lattner48af7d12018-07-09 19:05:38 -070083};
84} // end anonymous namespace
MLIR Teamf85a6262018-06-27 11:03:08 -070085
Chris Lattner48af7d12018-07-09 19:05:38 -070086namespace {
87
Chris Lattner7f9cc272018-07-19 08:35:28 -070088typedef std::function<Operation *(Identifier, ArrayRef<SSAValue *>,
89 ArrayRef<Type *>, ArrayRef<NamedAttribute>)>
Tatiana Shpeisman565b9642018-07-16 11:47:09 -070090 CreateOperationFunction;
91
Chris Lattner48af7d12018-07-09 19:05:38 -070092/// This class implement support for parsing global entities like types and
93/// shared entities like SSA names. It is intended to be subclassed by
94/// specialized subparsers that include state, e.g. when a local symbol table.
95class Parser {
96public:
Chris Lattner2e595eb2018-07-10 10:08:27 -070097 Builder builder;
Chris Lattner48af7d12018-07-09 19:05:38 -070098
Chris Lattner2e595eb2018-07-10 10:08:27 -070099 Parser(ParserState &state) : builder(state.context), state(state) {}
100
101 // Helper methods to get stuff from the parser-global state.
102 ParserState &getState() const { return state; }
Chris Lattner48af7d12018-07-09 19:05:38 -0700103 MLIRContext *getContext() const { return state.context; }
Chris Lattner2e595eb2018-07-10 10:08:27 -0700104 Module *getModule() { return state.module; }
Chris Lattner48af7d12018-07-09 19:05:38 -0700105
106 /// Return the current token the parser is inspecting.
107 const Token &getToken() const { return state.curToken; }
108 StringRef getTokenSpelling() const { return state.curToken.getSpelling(); }
Chris Lattnere79379a2018-06-22 10:39:19 -0700109
110 /// Emit an error and return failure.
Chris Lattner4c95a502018-06-23 16:03:42 -0700111 ParseResult emitError(const Twine &message) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700112 return emitError(state.curToken.getLoc(), message);
Chris Lattner4c95a502018-06-23 16:03:42 -0700113 }
114 ParseResult emitError(SMLoc loc, const Twine &message);
Chris Lattnere79379a2018-06-22 10:39:19 -0700115
116 /// Advance the current lexer onto the next token.
117 void consumeToken() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700118 assert(state.curToken.isNot(Token::eof, Token::error) &&
Chris Lattnere79379a2018-06-22 10:39:19 -0700119 "shouldn't advance past EOF or errors");
Chris Lattner48af7d12018-07-09 19:05:38 -0700120 state.curToken = state.lex.lexToken();
Chris Lattnere79379a2018-06-22 10:39:19 -0700121 }
122
123 /// Advance the current lexer onto the next token, asserting what the expected
124 /// current token is. This is preferred to the above method because it leads
125 /// to more self-documenting code with better checking.
Chris Lattner8da0c282018-06-29 11:15:56 -0700126 void consumeToken(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700127 assert(state.curToken.is(kind) && "consumed an unexpected token");
Chris Lattnere79379a2018-06-22 10:39:19 -0700128 consumeToken();
129 }
130
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700131 /// If the current token has the specified kind, consume it and return true.
132 /// If not, return false.
Chris Lattner8da0c282018-06-29 11:15:56 -0700133 bool consumeIf(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700134 if (state.curToken.isNot(kind))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700135 return false;
136 consumeToken(kind);
137 return true;
138 }
139
Chris Lattner40746442018-07-21 14:32:09 -0700140 /// Parse a comma-separated list of elements up until the specified end token.
141 ParseResult
142 parseCommaSeparatedListUntil(Token::Kind rightToken,
143 const std::function<ParseResult()> &parseElement,
144 bool allowEmptyList = true);
145
146 /// Parse a comma separated list of elements that must have at least one entry
147 /// in it.
148 ParseResult
149 parseCommaSeparatedList(const std::function<ParseResult()> &parseElement);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700150
Chris Lattnerf7e22732018-06-22 22:03:48 -0700151 // We have two forms of parsing methods - those that return a non-null
152 // pointer on success, and those that return a ParseResult to indicate whether
153 // they returned a failure. The second class fills in by-reference arguments
154 // as the results of their action.
155
Chris Lattnere79379a2018-06-22 10:39:19 -0700156 // Type parsing.
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700157 Type *parsePrimitiveType();
Chris Lattnerf7e22732018-06-22 22:03:48 -0700158 Type *parseElementType();
159 VectorType *parseVectorType();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700160 ParseResult parseDimensionListRanked(SmallVectorImpl<int> &dimensions);
Chris Lattnerf7e22732018-06-22 22:03:48 -0700161 Type *parseTensorType();
162 Type *parseMemRefType();
163 Type *parseFunctionType();
164 Type *parseType();
Chris Lattner1604e472018-07-23 08:42:19 -0700165 ParseResult parseTypeListNoParens(SmallVectorImpl<Type *> &elements);
Chris Lattnerf7e22732018-06-22 22:03:48 -0700166 ParseResult parseTypeList(SmallVectorImpl<Type*> &elements);
Chris Lattnere79379a2018-06-22 10:39:19 -0700167
Chris Lattner7121b802018-07-04 20:45:39 -0700168 // Attribute parsing.
169 Attribute *parseAttribute();
170 ParseResult parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes);
171
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700172 // Polyhedral structures.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700173 AffineMap *parseAffineMapInline();
MLIR Team718c82f2018-07-16 09:45:22 -0700174 AffineMap *parseAffineMapReference();
MLIR Teamf85a6262018-06-27 11:03:08 -0700175
Chris Lattner48af7d12018-07-09 19:05:38 -0700176private:
177 // The Parser is subclassed and reinstantiated. Do not add additional
178 // non-trivial state here, add it to the ParserState class.
179 ParserState &state;
Chris Lattnere79379a2018-06-22 10:39:19 -0700180};
181} // end anonymous namespace
182
183//===----------------------------------------------------------------------===//
184// Helper methods.
185//===----------------------------------------------------------------------===//
186
Chris Lattner4c95a502018-06-23 16:03:42 -0700187ParseResult Parser::emitError(SMLoc loc, const Twine &message) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700188 // If we hit a parse error in response to a lexer error, then the lexer
Jacques Pienaar9c411be2018-06-24 19:17:35 -0700189 // already reported the error.
Chris Lattner48af7d12018-07-09 19:05:38 -0700190 if (getToken().is(Token::error))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700191 return ParseFailure;
192
Chris Lattner48af7d12018-07-09 19:05:38 -0700193 auto &sourceMgr = state.lex.getSourceMgr();
194 state.errorReporter(sourceMgr.GetMessage(loc, SourceMgr::DK_Error, message));
Chris Lattnere79379a2018-06-22 10:39:19 -0700195 return ParseFailure;
196}
197
Chris Lattner40746442018-07-21 14:32:09 -0700198/// Parse a comma separated list of elements that must have at least one entry
199/// in it.
200ParseResult Parser::parseCommaSeparatedList(
201 const std::function<ParseResult()> &parseElement) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700202 // Non-empty case starts with an element.
203 if (parseElement())
204 return ParseFailure;
205
206 // Otherwise we have a list of comma separated elements.
207 while (consumeIf(Token::comma)) {
208 if (parseElement())
209 return ParseFailure;
210 }
Chris Lattner40746442018-07-21 14:32:09 -0700211 return ParseSuccess;
212}
213
214/// Parse a comma-separated list of elements, terminated with an arbitrary
215/// token. This allows empty lists if allowEmptyList is true.
216///
217/// abstract-list ::= rightToken // if allowEmptyList == true
218/// abstract-list ::= element (',' element)* rightToken
219///
220ParseResult Parser::parseCommaSeparatedListUntil(
221 Token::Kind rightToken, const std::function<ParseResult()> &parseElement,
222 bool allowEmptyList) {
223 // Handle the empty case.
224 if (getToken().is(rightToken)) {
225 if (!allowEmptyList)
226 return emitError("expected list element");
227 consumeToken(rightToken);
228 return ParseSuccess;
229 }
230
231 if (parseCommaSeparatedList(parseElement))
232 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700233
234 // Consume the end character.
235 if (!consumeIf(rightToken))
Chris Lattner8da0c282018-06-29 11:15:56 -0700236 return emitError("expected ',' or '" + Token::getTokenSpelling(rightToken) +
237 "'");
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700238
239 return ParseSuccess;
240}
Chris Lattnere79379a2018-06-22 10:39:19 -0700241
242//===----------------------------------------------------------------------===//
243// Type Parsing
244//===----------------------------------------------------------------------===//
245
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700246/// Parse the low-level fixed dtypes in the system.
247///
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700248/// primitive-type ::= `f16` | `bf16` | `f32` | `f64`
249/// primitive-type ::= integer-type
250/// primitive-type ::= `affineint`
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700251///
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700252Type *Parser::parsePrimitiveType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700253 switch (getToken().getKind()) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700254 default:
255 return (emitError("expected type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700256 case Token::kw_bf16:
257 consumeToken(Token::kw_bf16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700258 return builder.getBF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700259 case Token::kw_f16:
260 consumeToken(Token::kw_f16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700261 return builder.getF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700262 case Token::kw_f32:
263 consumeToken(Token::kw_f32);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700264 return builder.getF32Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700265 case Token::kw_f64:
266 consumeToken(Token::kw_f64);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700267 return builder.getF64Type();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700268 case Token::kw_affineint:
269 consumeToken(Token::kw_affineint);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700270 return builder.getAffineIntType();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700271 case Token::inttype: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700272 auto width = getToken().getIntTypeBitwidth();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700273 if (!width.hasValue())
274 return (emitError("invalid integer width"), nullptr);
275 consumeToken(Token::inttype);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700276 return builder.getIntegerType(width.getValue());
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700277 }
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700278 }
279}
280
281/// Parse the element type of a tensor or memref type.
282///
283/// element-type ::= primitive-type | vector-type
284///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700285Type *Parser::parseElementType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700286 if (getToken().is(Token::kw_vector))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700287 return parseVectorType();
288
289 return parsePrimitiveType();
290}
291
292/// Parse a vector type.
293///
294/// vector-type ::= `vector` `<` const-dimension-list primitive-type `>`
295/// const-dimension-list ::= (integer-literal `x`)+
296///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700297VectorType *Parser::parseVectorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700298 consumeToken(Token::kw_vector);
299
300 if (!consumeIf(Token::less))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700301 return (emitError("expected '<' in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700302
Chris Lattner48af7d12018-07-09 19:05:38 -0700303 if (getToken().isNot(Token::integer))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700304 return (emitError("expected dimension size in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700305
306 SmallVector<unsigned, 4> dimensions;
Chris Lattner48af7d12018-07-09 19:05:38 -0700307 while (getToken().is(Token::integer)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700308 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700309 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700310 if (!dimension.hasValue())
Chris Lattnerf7e22732018-06-22 22:03:48 -0700311 return (emitError("invalid dimension in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700312 dimensions.push_back(dimension.getValue());
313
314 consumeToken(Token::integer);
315
316 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700317 if (getToken().isNot(Token::bare_identifier) ||
318 getTokenSpelling()[0] != 'x')
Chris Lattnerf7e22732018-06-22 22:03:48 -0700319 return (emitError("expected 'x' in vector dimension list"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700320
321 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700322 if (getTokenSpelling().size() != 1)
323 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700324
325 // Consume the 'x'.
326 consumeToken(Token::bare_identifier);
327 }
328
329 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700330 auto *elementType = parsePrimitiveType();
331 if (!elementType)
332 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700333
334 if (!consumeIf(Token::greater))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700335 return (emitError("expected '>' in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700336
Chris Lattnerf7e22732018-06-22 22:03:48 -0700337 return VectorType::get(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700338}
339
340/// Parse a dimension list of a tensor or memref type. This populates the
341/// dimension list, returning -1 for the '?' dimensions.
342///
343/// dimension-list-ranked ::= (dimension `x`)*
344/// dimension ::= `?` | integer-literal
345///
346ParseResult Parser::parseDimensionListRanked(SmallVectorImpl<int> &dimensions) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700347 while (getToken().isAny(Token::integer, Token::question)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700348 if (consumeIf(Token::question)) {
349 dimensions.push_back(-1);
350 } else {
351 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700352 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700353 if (!dimension.hasValue() || (int)dimension.getValue() < 0)
354 return emitError("invalid dimension");
355 dimensions.push_back((int)dimension.getValue());
356 consumeToken(Token::integer);
357 }
358
359 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700360 if (getToken().isNot(Token::bare_identifier) ||
361 getTokenSpelling()[0] != 'x')
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700362 return emitError("expected 'x' in dimension list");
363
364 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700365 if (getTokenSpelling().size() != 1)
366 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700367
368 // Consume the 'x'.
369 consumeToken(Token::bare_identifier);
370 }
371
372 return ParseSuccess;
373}
374
375/// Parse a tensor type.
376///
377/// tensor-type ::= `tensor` `<` dimension-list element-type `>`
378/// dimension-list ::= dimension-list-ranked | `??`
379///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700380Type *Parser::parseTensorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700381 consumeToken(Token::kw_tensor);
382
383 if (!consumeIf(Token::less))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700384 return (emitError("expected '<' in tensor type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700385
386 bool isUnranked;
387 SmallVector<int, 4> dimensions;
388
389 if (consumeIf(Token::questionquestion)) {
390 isUnranked = true;
391 } else {
392 isUnranked = false;
393 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700394 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700395 }
396
397 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700398 auto elementType = parseElementType();
399 if (!elementType)
400 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700401
402 if (!consumeIf(Token::greater))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700403 return (emitError("expected '>' in tensor type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700404
MLIR Team355ec862018-06-23 18:09:09 -0700405 if (isUnranked)
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700406 return builder.getTensorType(elementType);
407 return builder.getTensorType(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700408}
409
410/// Parse a memref type.
411///
412/// memref-type ::= `memref` `<` dimension-list-ranked element-type
413/// (`,` semi-affine-map-composition)? (`,` memory-space)? `>`
414///
415/// semi-affine-map-composition ::= (semi-affine-map `,` )* semi-affine-map
416/// memory-space ::= integer-literal /* | TODO: address-space-id */
417///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700418Type *Parser::parseMemRefType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700419 consumeToken(Token::kw_memref);
420
421 if (!consumeIf(Token::less))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700422 return (emitError("expected '<' in memref type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700423
424 SmallVector<int, 4> dimensions;
425 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700426 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700427
428 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700429 auto elementType = parseElementType();
430 if (!elementType)
431 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700432
MLIR Team718c82f2018-07-16 09:45:22 -0700433 if (!consumeIf(Token::comma))
434 return (emitError("expected ',' in memref type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700435
MLIR Team718c82f2018-07-16 09:45:22 -0700436 // Parse semi-affine-map-composition.
437 SmallVector<AffineMap*, 2> affineMapComposition;
438 unsigned memorySpace;
439 bool parsedMemorySpace = false;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700440
MLIR Team718c82f2018-07-16 09:45:22 -0700441 auto parseElt = [&]() -> ParseResult {
442 if (getToken().is(Token::integer)) {
443 // Parse memory space.
444 if (parsedMemorySpace)
445 return emitError("multiple memory spaces specified in memref type");
446 auto v = getToken().getUnsignedIntegerValue();
447 if (!v.hasValue())
448 return emitError("invalid memory space in memref type");
449 memorySpace = v.getValue();
450 consumeToken(Token::integer);
451 parsedMemorySpace = true;
452 } else {
453 // Parse affine map.
454 if (parsedMemorySpace)
455 return emitError("affine map after memory space in memref type");
456 auto* affineMap = parseAffineMapReference();
457 if (affineMap == nullptr)
458 return ParseFailure;
459 affineMapComposition.push_back(affineMap);
460 }
461 return ParseSuccess;
462 };
463
464 // Parse comma separated list of affine maps, followed by memory space.
Chris Lattner40746442018-07-21 14:32:09 -0700465 if (parseCommaSeparatedListUntil(Token::greater, parseElt,
466 /*allowEmptyList=*/false)) {
MLIR Team718c82f2018-07-16 09:45:22 -0700467 return nullptr;
468 }
469 // Check that MemRef type specifies at least one affine map in composition.
470 if (affineMapComposition.empty())
471 return (emitError("expected semi-affine-map in memref type"), nullptr);
472 if (!parsedMemorySpace)
473 return (emitError("expected memory space in memref type"), nullptr);
474
475 return MemRefType::get(dimensions, elementType, affineMapComposition,
476 memorySpace);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700477}
478
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700479/// Parse a function type.
480///
481/// function-type ::= type-list-parens `->` type-list
482///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700483Type *Parser::parseFunctionType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700484 assert(getToken().is(Token::l_paren));
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700485
Chris Lattnerf7e22732018-06-22 22:03:48 -0700486 SmallVector<Type*, 4> arguments;
487 if (parseTypeList(arguments))
488 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700489
490 if (!consumeIf(Token::arrow))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700491 return (emitError("expected '->' in function type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700492
Chris Lattnerf7e22732018-06-22 22:03:48 -0700493 SmallVector<Type*, 4> results;
494 if (parseTypeList(results))
495 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700496
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700497 return builder.getFunctionType(arguments, results);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700498}
499
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700500/// Parse an arbitrary type.
501///
502/// type ::= primitive-type
503/// | vector-type
504/// | tensor-type
505/// | memref-type
506/// | function-type
507/// element-type ::= primitive-type | vector-type
508///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700509Type *Parser::parseType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700510 switch (getToken().getKind()) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700511 case Token::kw_memref: return parseMemRefType();
512 case Token::kw_tensor: return parseTensorType();
513 case Token::kw_vector: return parseVectorType();
514 case Token::l_paren: return parseFunctionType();
515 default:
516 return parsePrimitiveType();
517 }
518}
519
Chris Lattner1604e472018-07-23 08:42:19 -0700520/// Parse a list of types without an enclosing parenthesis. The list must have
521/// at least one member.
522///
523/// type-list-no-parens ::= type (`,` type)*
524///
525ParseResult Parser::parseTypeListNoParens(SmallVectorImpl<Type *> &elements) {
526 auto parseElt = [&]() -> ParseResult {
527 auto elt = parseType();
528 elements.push_back(elt);
529 return elt ? ParseSuccess : ParseFailure;
530 };
531
532 return parseCommaSeparatedList(parseElt);
533}
534
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700535/// Parse a "type list", which is a singular type, or a parenthesized list of
536/// types.
537///
538/// type-list ::= type-list-parens | type
539/// type-list-parens ::= `(` `)`
Chris Lattner1604e472018-07-23 08:42:19 -0700540/// | `(` type-list-no-parens `)`
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700541///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700542ParseResult Parser::parseTypeList(SmallVectorImpl<Type*> &elements) {
543 auto parseElt = [&]() -> ParseResult {
544 auto elt = parseType();
545 elements.push_back(elt);
546 return elt ? ParseSuccess : ParseFailure;
547 };
548
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700549 // If there is no parens, then it must be a singular type.
550 if (!consumeIf(Token::l_paren))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700551 return parseElt();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700552
Chris Lattner40746442018-07-21 14:32:09 -0700553 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700554 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700555
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700556 return ParseSuccess;
557}
558
Chris Lattner4c95a502018-06-23 16:03:42 -0700559//===----------------------------------------------------------------------===//
Chris Lattner7121b802018-07-04 20:45:39 -0700560// Attribute parsing.
561//===----------------------------------------------------------------------===//
562
563
564/// Attribute parsing.
565///
566/// attribute-value ::= bool-literal
567/// | integer-literal
568/// | float-literal
569/// | string-literal
570/// | `[` (attribute-value (`,` attribute-value)*)? `]`
571///
572Attribute *Parser::parseAttribute() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700573 switch (getToken().getKind()) {
Chris Lattner7121b802018-07-04 20:45:39 -0700574 case Token::kw_true:
575 consumeToken(Token::kw_true);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700576 return builder.getBoolAttr(true);
Chris Lattner7121b802018-07-04 20:45:39 -0700577 case Token::kw_false:
578 consumeToken(Token::kw_false);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700579 return builder.getBoolAttr(false);
Chris Lattner7121b802018-07-04 20:45:39 -0700580
581 case Token::integer: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700582 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700583 if (!val.hasValue() || (int64_t)val.getValue() < 0)
584 return (emitError("integer too large for attribute"), nullptr);
585 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700586 return builder.getIntegerAttr((int64_t)val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700587 }
588
589 case Token::minus: {
590 consumeToken(Token::minus);
Chris Lattner48af7d12018-07-09 19:05:38 -0700591 if (getToken().is(Token::integer)) {
592 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700593 if (!val.hasValue() || (int64_t)-val.getValue() >= 0)
594 return (emitError("integer too large for attribute"), nullptr);
595 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700596 return builder.getIntegerAttr((int64_t)-val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700597 }
598
599 return (emitError("expected constant integer or floating point value"),
600 nullptr);
601 }
602
603 case Token::string: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700604 auto val = getToken().getStringValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700605 consumeToken(Token::string);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700606 return builder.getStringAttr(val);
Chris Lattner7121b802018-07-04 20:45:39 -0700607 }
608
609 case Token::l_bracket: {
610 consumeToken(Token::l_bracket);
611 SmallVector<Attribute*, 4> elements;
612
613 auto parseElt = [&]() -> ParseResult {
614 elements.push_back(parseAttribute());
615 return elements.back() ? ParseSuccess : ParseFailure;
616 };
617
Chris Lattner40746442018-07-21 14:32:09 -0700618 if (parseCommaSeparatedListUntil(Token::r_bracket, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700619 return nullptr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700620 return builder.getArrayAttr(elements);
Chris Lattner7121b802018-07-04 20:45:39 -0700621 }
622 default:
MLIR Teamb61885d2018-07-18 16:29:21 -0700623 // Try to parse affine map reference.
624 auto* affineMap = parseAffineMapReference();
625 if (affineMap != nullptr)
626 return builder.getAffineMapAttr(affineMap);
627
Chris Lattner7121b802018-07-04 20:45:39 -0700628 // TODO: Handle floating point.
629 return (emitError("expected constant attribute value"), nullptr);
630 }
631}
632
Chris Lattner7121b802018-07-04 20:45:39 -0700633/// Attribute dictionary.
634///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700635/// attribute-dict ::= `{` `}`
636/// | `{` attribute-entry (`,` attribute-entry)* `}`
637/// attribute-entry ::= bare-id `:` attribute-value
Chris Lattner7121b802018-07-04 20:45:39 -0700638///
639ParseResult Parser::parseAttributeDict(
640 SmallVectorImpl<NamedAttribute> &attributes) {
641 consumeToken(Token::l_brace);
642
643 auto parseElt = [&]() -> ParseResult {
644 // We allow keywords as attribute names.
Chris Lattner48af7d12018-07-09 19:05:38 -0700645 if (getToken().isNot(Token::bare_identifier, Token::inttype) &&
646 !getToken().isKeyword())
Chris Lattner7121b802018-07-04 20:45:39 -0700647 return emitError("expected attribute name");
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700648 auto nameId = builder.getIdentifier(getTokenSpelling());
Chris Lattner7121b802018-07-04 20:45:39 -0700649 consumeToken();
650
651 if (!consumeIf(Token::colon))
652 return emitError("expected ':' in attribute list");
653
654 auto attr = parseAttribute();
655 if (!attr) return ParseFailure;
656
657 attributes.push_back({nameId, attr});
658 return ParseSuccess;
659 };
660
Chris Lattner40746442018-07-21 14:32:09 -0700661 if (parseCommaSeparatedListUntil(Token::r_brace, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700662 return ParseFailure;
663
664 return ParseSuccess;
665}
666
667//===----------------------------------------------------------------------===//
MLIR Teamf85a6262018-06-27 11:03:08 -0700668// Polyhedral structures.
669//===----------------------------------------------------------------------===//
670
Chris Lattner2e595eb2018-07-10 10:08:27 -0700671/// Lower precedence ops (all at the same precedence level). LNoOp is false in
672/// the boolean sense.
673enum AffineLowPrecOp {
674 /// Null value.
675 LNoOp,
676 Add,
677 Sub
678};
MLIR Teamf85a6262018-06-27 11:03:08 -0700679
Chris Lattner2e595eb2018-07-10 10:08:27 -0700680/// Higher precedence ops - all at the same precedence level. HNoOp is false in
681/// the boolean sense.
682enum AffineHighPrecOp {
683 /// Null value.
684 HNoOp,
685 Mul,
686 FloorDiv,
687 CeilDiv,
688 Mod
689};
Chris Lattner7121b802018-07-04 20:45:39 -0700690
Chris Lattner2e595eb2018-07-10 10:08:27 -0700691namespace {
692/// This is a specialized parser for AffineMap's, maintaining the state
693/// transient to their bodies.
694class AffineMapParser : public Parser {
695public:
696 explicit AffineMapParser(ParserState &state) : Parser(state) {}
Chris Lattner7121b802018-07-04 20:45:39 -0700697
Chris Lattner2e595eb2018-07-10 10:08:27 -0700698 AffineMap *parseAffineMapInline();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700699
Chris Lattner2e595eb2018-07-10 10:08:27 -0700700private:
701 unsigned getNumDims() const { return dims.size(); }
702 unsigned getNumSymbols() const { return symbols.size(); }
MLIR Teamf85a6262018-06-27 11:03:08 -0700703
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700704 /// Returns true if the only identifiers the parser accepts in affine
705 /// expressions are symbolic identifiers.
706 bool isPureSymbolic() const { return pureSymbolic; }
707 void setSymbolicParsing(bool val) { pureSymbolic = val; }
708
Chris Lattner2e595eb2018-07-10 10:08:27 -0700709 // Binary affine op parsing.
710 AffineLowPrecOp consumeIfLowPrecOp();
711 AffineHighPrecOp consumeIfHighPrecOp();
MLIR Teamf85a6262018-06-27 11:03:08 -0700712
Chris Lattner2e595eb2018-07-10 10:08:27 -0700713 // Identifier lists for polyhedral structures.
714 ParseResult parseDimIdList();
715 ParseResult parseSymbolIdList();
716 ParseResult parseDimOrSymbolId(bool isDim);
717
718 AffineExpr *parseAffineExpr();
719 AffineExpr *parseParentheticalExpr();
720 AffineExpr *parseNegateExpression(AffineExpr *lhs);
721 AffineExpr *parseIntegerExpr();
722 AffineExpr *parseBareIdExpr();
723
724 AffineExpr *getBinaryAffineOpExpr(AffineHighPrecOp op, AffineExpr *lhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700725 AffineExpr *rhs, SMLoc opLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700726 AffineExpr *getBinaryAffineOpExpr(AffineLowPrecOp op, AffineExpr *lhs,
727 AffineExpr *rhs);
728 AffineExpr *parseAffineOperandExpr(AffineExpr *lhs);
729 AffineExpr *parseAffineLowPrecOpExpr(AffineExpr *llhs,
730 AffineLowPrecOp llhsOp);
731 AffineExpr *parseAffineHighPrecOpExpr(AffineExpr *llhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700732 AffineHighPrecOp llhsOp,
733 SMLoc llhsOpLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700734
735private:
736 // TODO(bondhugula): could just use an vector/ArrayRef and scan the numbers.
737 llvm::StringMap<unsigned> dims;
738 llvm::StringMap<unsigned> symbols;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700739 /// True if the parser should allow only symbolic identifiers in affine
740 /// expressions.
741 bool pureSymbolic = false;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700742};
743} // end anonymous namespace
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700744
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700745/// Create an affine binary high precedence op expression (mul's, div's, mod).
746/// opLoc is the location of the op token to be used to report errors
747/// for non-conforming expressions.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700748AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineHighPrecOp op,
749 AffineExpr *lhs,
Chris Lattner40746442018-07-21 14:32:09 -0700750 AffineExpr *rhs,
751 SMLoc opLoc) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700752 // TODO: make the error location info accurate.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700753 switch (op) {
754 case Mul:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700755 if (!lhs->isSymbolicOrConstant() && !rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700756 emitError(opLoc, "non-affine expression: at least one of the multiply "
757 "operands has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700758 return nullptr;
759 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700760 return builder.getMulExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700761 case FloorDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700762 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700763 emitError(opLoc, "non-affine expression: right operand of floordiv "
764 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700765 return nullptr;
766 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700767 return builder.getFloorDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700768 case CeilDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700769 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700770 emitError(opLoc, "non-affine expression: right operand of ceildiv "
771 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700772 return nullptr;
773 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700774 return builder.getCeilDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700775 case Mod:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700776 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700777 emitError(opLoc, "non-affine expression: right operand of mod "
778 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700779 return nullptr;
780 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700781 return builder.getModExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700782 case HNoOp:
783 llvm_unreachable("can't create affine expression for null high prec op");
784 return nullptr;
785 }
786}
787
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700788/// Create an affine binary low precedence op expression (add, sub).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700789AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineLowPrecOp op,
790 AffineExpr *lhs,
791 AffineExpr *rhs) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700792 switch (op) {
793 case AffineLowPrecOp::Add:
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700794 return builder.getAddExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700795 case AffineLowPrecOp::Sub:
Uday Bondhugulac1faf662018-07-19 14:08:50 -0700796 return builder.getAddExpr(
797 lhs, builder.getMulExpr(rhs, builder.getConstantExpr(-1)));
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700798 case AffineLowPrecOp::LNoOp:
799 llvm_unreachable("can't create affine expression for null low prec op");
800 return nullptr;
801 }
802}
803
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700804/// Consume this token if it is a lower precedence affine op (there are only two
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700805/// precedence levels).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700806AffineLowPrecOp AffineMapParser::consumeIfLowPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700807 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700808 case Token::plus:
809 consumeToken(Token::plus);
810 return AffineLowPrecOp::Add;
811 case Token::minus:
812 consumeToken(Token::minus);
813 return AffineLowPrecOp::Sub;
814 default:
815 return AffineLowPrecOp::LNoOp;
816 }
817}
818
819/// Consume this token if it is a higher precedence affine op (there are only
820/// two precedence levels)
Chris Lattner2e595eb2018-07-10 10:08:27 -0700821AffineHighPrecOp AffineMapParser::consumeIfHighPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700822 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700823 case Token::star:
824 consumeToken(Token::star);
825 return Mul;
826 case Token::kw_floordiv:
827 consumeToken(Token::kw_floordiv);
828 return FloorDiv;
829 case Token::kw_ceildiv:
830 consumeToken(Token::kw_ceildiv);
831 return CeilDiv;
832 case Token::kw_mod:
833 consumeToken(Token::kw_mod);
834 return Mod;
835 default:
836 return HNoOp;
837 }
838}
839
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700840/// Parse a high precedence op expression list: mul, div, and mod are high
841/// precedence binary ops, i.e., parse a
842/// expr_1 op_1 expr_2 op_2 ... expr_n
843/// where op_1, op_2 are all a AffineHighPrecOp (mul, div, mod).
844/// All affine binary ops are left associative.
845/// Given llhs, returns (llhs llhsOp lhs) op rhs, or (lhs op rhs) if llhs is
846/// null. If no rhs can be found, returns (llhs llhsOp lhs) or lhs if llhs is
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700847/// null. llhsOpLoc is the location of the llhsOp token that will be used to
848/// report an error for non-conforming expressions.
849AffineExpr *AffineMapParser::parseAffineHighPrecOpExpr(AffineExpr *llhs,
850 AffineHighPrecOp llhsOp,
851 SMLoc llhsOpLoc) {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700852 AffineExpr *lhs = parseAffineOperandExpr(llhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700853 if (!lhs)
854 return nullptr;
855
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700856 // Found an LHS. Parse the remaining expression.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700857 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -0700858 if (AffineHighPrecOp op = consumeIfHighPrecOp()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700859 if (llhs) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700860 AffineExpr *expr = getBinaryAffineOpExpr(llhsOp, llhs, lhs, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700861 if (!expr)
862 return nullptr;
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700863 return parseAffineHighPrecOpExpr(expr, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700864 }
865 // No LLHS, get RHS
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700866 return parseAffineHighPrecOpExpr(lhs, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700867 }
868
869 // This is the last operand in this expression.
870 if (llhs)
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700871 return getBinaryAffineOpExpr(llhsOp, llhs, lhs, llhsOpLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700872
873 // No llhs, 'lhs' itself is the expression.
874 return lhs;
875}
876
877/// Parse an affine expression inside parentheses.
878///
879/// affine-expr ::= `(` affine-expr `)`
Chris Lattner2e595eb2018-07-10 10:08:27 -0700880AffineExpr *AffineMapParser::parseParentheticalExpr() {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700881 if (!consumeIf(Token::l_paren))
882 return (emitError("expected '('"), nullptr);
Chris Lattner48af7d12018-07-09 19:05:38 -0700883 if (getToken().is(Token::r_paren))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700884 return (emitError("no expression inside parentheses"), nullptr);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700885 auto *expr = parseAffineExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700886 if (!expr)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700887 return nullptr;
888 if (!consumeIf(Token::r_paren))
889 return (emitError("expected ')'"), nullptr);
890 return expr;
891}
892
893/// Parse the negation expression.
894///
895/// affine-expr ::= `-` affine-expr
Chris Lattner2e595eb2018-07-10 10:08:27 -0700896AffineExpr *AffineMapParser::parseNegateExpression(AffineExpr *lhs) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700897 if (!consumeIf(Token::minus))
898 return (emitError("expected '-'"), nullptr);
899
Chris Lattner2e595eb2018-07-10 10:08:27 -0700900 AffineExpr *operand = parseAffineOperandExpr(lhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700901 // Since negation has the highest precedence of all ops (including high
902 // precedence ops) but lower than parentheses, we are only going to use
903 // parseAffineOperandExpr instead of parseAffineExpr here.
904 if (!operand)
905 // Extra error message although parseAffineOperandExpr would have
906 // complained. Leads to a better diagnostic.
907 return (emitError("missing operand of negation"), nullptr);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700908 auto *minusOne = builder.getConstantExpr(-1);
909 return builder.getMulExpr(minusOne, operand);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700910}
911
912/// Parse a bare id that may appear in an affine expression.
913///
914/// affine-expr ::= bare-id
Chris Lattner2e595eb2018-07-10 10:08:27 -0700915AffineExpr *AffineMapParser::parseBareIdExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700916 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700917 return (emitError("expected bare identifier"), nullptr);
918
Chris Lattner48af7d12018-07-09 19:05:38 -0700919 StringRef sRef = getTokenSpelling();
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700920 // dims, symbols are all pairwise distinct.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700921 if (dims.count(sRef)) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700922 if (isPureSymbolic())
923 return (emitError("identifier used is not a symbolic identifier"),
924 nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700925 consumeToken(Token::bare_identifier);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700926 return builder.getDimExpr(dims.lookup(sRef));
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700927 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700928
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700929 if (symbols.count(sRef)) {
930 consumeToken(Token::bare_identifier);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700931 return builder.getSymbolExpr(symbols.lookup(sRef));
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700932 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700933
934 return (emitError("use of undeclared identifier"), nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700935}
936
937/// Parse a positive integral constant appearing in an affine expression.
938///
939/// affine-expr ::= integer-literal
Chris Lattner2e595eb2018-07-10 10:08:27 -0700940AffineExpr *AffineMapParser::parseIntegerExpr() {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700941 // No need to handle negative numbers separately here. They are naturally
942 // handled via the unary negation operator, although (FIXME) MININT_64 still
943 // not correctly handled.
Chris Lattner48af7d12018-07-09 19:05:38 -0700944 if (getToken().isNot(Token::integer))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700945 return (emitError("expected integer"), nullptr);
946
Chris Lattner48af7d12018-07-09 19:05:38 -0700947 auto val = getToken().getUInt64IntegerValue();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700948 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
949 return (emitError("constant too large for affineint"), nullptr);
950 }
951 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700952 return builder.getConstantExpr((int64_t)val.getValue());
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700953}
954
955/// Parses an expression that can be a valid operand of an affine expression.
Uday Bondhugula76345202018-07-09 13:47:52 -0700956/// lhs: if non-null, lhs is an affine expression that is the lhs of a binary
957/// operator, the rhs of which is being parsed. This is used to determine
958/// whether an error should be emitted for a missing right operand.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700959// Eg: for an expression without parentheses (like i + j + k + l), each
960// of the four identifiers is an operand. For i + j*k + l, j*k is not an
961// operand expression, it's an op expression and will be parsed via
962// parseAffineHighPrecOpExpression(). However, for i + (j*k) + -l, (j*k) and -l
963// are valid operands that will be parsed by this function.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700964AffineExpr *AffineMapParser::parseAffineOperandExpr(AffineExpr *lhs) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700965 switch (getToken().getKind()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700966 case Token::bare_identifier:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700967 return parseBareIdExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700968 case Token::integer:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700969 return parseIntegerExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700970 case Token::l_paren:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700971 return parseParentheticalExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700972 case Token::minus:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700973 return parseNegateExpression(lhs);
Uday Bondhugula76345202018-07-09 13:47:52 -0700974 case Token::kw_ceildiv:
975 case Token::kw_floordiv:
976 case Token::kw_mod:
977 case Token::plus:
978 case Token::star:
979 if (lhs)
980 emitError("missing right operand of binary operator");
981 else
982 emitError("missing left operand of binary operator");
983 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700984 default:
985 if (lhs)
Uday Bondhugula76345202018-07-09 13:47:52 -0700986 emitError("missing right operand of binary operator");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700987 else
988 emitError("expected affine expression");
989 return nullptr;
990 }
991}
992
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700993/// Parse affine expressions that are bare-id's, integer constants,
994/// parenthetical affine expressions, and affine op expressions that are a
995/// composition of those.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700996///
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700997/// All binary op's associate from left to right.
998///
999/// {add, sub} have lower precedence than {mul, div, and mod}.
1000///
Uday Bondhugula76345202018-07-09 13:47:52 -07001001/// Add, sub'are themselves at the same precedence level. Mul, floordiv,
1002/// ceildiv, and mod are at the same higher precedence level. Negation has
1003/// higher precedence than any binary op.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001004///
1005/// llhs: the affine expression appearing on the left of the one being parsed.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001006/// This function will return ((llhs llhsOp lhs) op rhs) if llhs is non null,
1007/// and lhs op rhs otherwise; if there is no rhs, llhs llhsOp lhs is returned if
1008/// llhs is non-null; otherwise lhs is returned. This is to deal with left
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001009/// associativity.
1010///
1011/// Eg: when the expression is e1 + e2*e3 + e4, with e1 as llhs, this function
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001012/// will return the affine expr equivalent of (e1 + (e2*e3)) + e4, where (e2*e3)
1013/// will be parsed using parseAffineHighPrecOpExpr().
Chris Lattner2e595eb2018-07-10 10:08:27 -07001014AffineExpr *AffineMapParser::parseAffineLowPrecOpExpr(AffineExpr *llhs,
1015 AffineLowPrecOp llhsOp) {
Uday Bondhugula76345202018-07-09 13:47:52 -07001016 AffineExpr *lhs;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001017 if (!(lhs = parseAffineOperandExpr(llhs)))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001018 return nullptr;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001019
1020 // Found an LHS. Deal with the ops.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001021 if (AffineLowPrecOp lOp = consumeIfLowPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001022 if (llhs) {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001023 AffineExpr *sum = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001024 return parseAffineLowPrecOpExpr(sum, lOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001025 }
1026 // No LLHS, get RHS and form the expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001027 return parseAffineLowPrecOpExpr(lhs, lOp);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001028 }
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001029 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07001030 if (AffineHighPrecOp hOp = consumeIfHighPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001031 // We have a higher precedence op here. Get the rhs operand for the llhs
1032 // through parseAffineHighPrecOpExpr.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001033 AffineExpr *highRes = parseAffineHighPrecOpExpr(lhs, hOp, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001034 if (!highRes)
1035 return nullptr;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001036
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001037 // If llhs is null, the product forms the first operand of the yet to be
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001038 // found expression. If non-null, the op to associate with llhs is llhsOp.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001039 AffineExpr *expr =
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001040 llhs ? getBinaryAffineOpExpr(llhsOp, llhs, highRes) : highRes;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001041
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001042 // Recurse for subsequent low prec op's after the affine high prec op
1043 // expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001044 if (AffineLowPrecOp nextOp = consumeIfLowPrecOp())
1045 return parseAffineLowPrecOpExpr(expr, nextOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001046 return expr;
1047 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001048 // Last operand in the expression list.
1049 if (llhs)
1050 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
1051 // No llhs, 'lhs' itself is the expression.
1052 return lhs;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001053}
1054
1055/// Parse an affine expression.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001056/// affine-expr ::= `(` affine-expr `)`
1057/// | `-` affine-expr
1058/// | affine-expr `+` affine-expr
1059/// | affine-expr `-` affine-expr
1060/// | affine-expr `*` affine-expr
1061/// | affine-expr `floordiv` affine-expr
1062/// | affine-expr `ceildiv` affine-expr
1063/// | affine-expr `mod` affine-expr
1064/// | bare-id
1065/// | integer-literal
1066///
1067/// Additional conditions are checked depending on the production. For eg., one
1068/// of the operands for `*` has to be either constant/symbolic; the second
1069/// operand for floordiv, ceildiv, and mod has to be a positive integer.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001070AffineExpr *AffineMapParser::parseAffineExpr() {
1071 return parseAffineLowPrecOpExpr(nullptr, AffineLowPrecOp::LNoOp);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001072}
1073
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001074/// Parse a dim or symbol from the lists appearing before the actual expressions
Chris Lattner2e595eb2018-07-10 10:08:27 -07001075/// of the affine map. Update our state to store the dimensional/symbolic
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001076/// identifier. 'dim': whether it's the dim list or symbol list that is being
1077/// parsed.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001078ParseResult AffineMapParser::parseDimOrSymbolId(bool isDim) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001079 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001080 return emitError("expected bare identifier");
Chris Lattner48af7d12018-07-09 19:05:38 -07001081 auto sRef = getTokenSpelling();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001082 consumeToken(Token::bare_identifier);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001083 if (dims.count(sRef))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001084 return emitError("dimensional identifier name reused");
Chris Lattner2e595eb2018-07-10 10:08:27 -07001085 if (symbols.count(sRef))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001086 return emitError("symbolic identifier name reused");
Chris Lattner2e595eb2018-07-10 10:08:27 -07001087 if (isDim)
1088 dims.insert({sRef, dims.size()});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001089 else
Chris Lattner2e595eb2018-07-10 10:08:27 -07001090 symbols.insert({sRef, symbols.size()});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001091 return ParseSuccess;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001092}
1093
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001094/// Parse the list of symbolic identifiers to an affine map.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001095ParseResult AffineMapParser::parseSymbolIdList() {
1096 if (!consumeIf(Token::l_bracket))
1097 return emitError("expected '['");
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001098
Chris Lattner2e595eb2018-07-10 10:08:27 -07001099 auto parseElt = [&]() -> ParseResult { return parseDimOrSymbolId(false); };
Chris Lattner40746442018-07-21 14:32:09 -07001100 return parseCommaSeparatedListUntil(Token::r_bracket, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001101}
1102
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001103/// Parse the list of dimensional identifiers to an affine map.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001104ParseResult AffineMapParser::parseDimIdList() {
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001105 if (!consumeIf(Token::l_paren))
1106 return emitError("expected '(' at start of dimensional identifiers list");
1107
Chris Lattner2e595eb2018-07-10 10:08:27 -07001108 auto parseElt = [&]() -> ParseResult { return parseDimOrSymbolId(true); };
Chris Lattner40746442018-07-21 14:32:09 -07001109 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001110}
1111
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001112/// Parse an affine map definition.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001113///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001114/// affine-map-inline ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
1115/// (`size` `(` dim-size (`,` dim-size)* `)`)?
1116/// dim-size ::= affine-expr | `min` `(` affine-expr ( `,` affine-expr)+ `)`
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001117///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001118/// multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner2e595eb2018-07-10 10:08:27 -07001119AffineMap *AffineMapParser::parseAffineMapInline() {
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001120 // List of dimensional identifiers.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001121 if (parseDimIdList())
Chris Lattner7121b802018-07-04 20:45:39 -07001122 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001123
1124 // Symbols are optional.
Chris Lattner48af7d12018-07-09 19:05:38 -07001125 if (getToken().is(Token::l_bracket)) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001126 if (parseSymbolIdList())
Chris Lattner7121b802018-07-04 20:45:39 -07001127 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001128 }
1129 if (!consumeIf(Token::arrow)) {
Chris Lattner7121b802018-07-04 20:45:39 -07001130 return (emitError("expected '->' or '['"), nullptr);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001131 }
1132 if (!consumeIf(Token::l_paren)) {
1133 emitError("expected '(' at start of affine map range");
Chris Lattner7121b802018-07-04 20:45:39 -07001134 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001135 }
1136
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001137 SmallVector<AffineExpr *, 4> exprs;
1138 auto parseElt = [&]() -> ParseResult {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001139 auto *elt = parseAffineExpr();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001140 ParseResult res = elt ? ParseSuccess : ParseFailure;
1141 exprs.push_back(elt);
1142 return res;
1143 };
1144
1145 // Parse a multi-dimensional affine expression (a comma-separated list of 1-d
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001146 // affine expressions); the list cannot be empty.
1147 // Grammar: multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner40746442018-07-21 14:32:09 -07001148 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt, false))
Chris Lattner7121b802018-07-04 20:45:39 -07001149 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001150
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001151 // Parse optional range sizes.
Uday Bondhugula1e500b42018-07-12 18:04:04 -07001152 // range-sizes ::= (`size` `(` dim-size (`,` dim-size)* `)`)?
1153 // dim-size ::= affine-expr | `min` `(` affine-expr (`,` affine-expr)+ `)`
1154 // TODO(bondhugula): support for min of several affine expressions.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001155 // TODO: check if sizes are non-negative whenever they are constant.
1156 SmallVector<AffineExpr *, 4> rangeSizes;
1157 if (consumeIf(Token::kw_size)) {
1158 // Location of the l_paren token (if it exists) for error reporting later.
1159 auto loc = getToken().getLoc();
1160 if (!consumeIf(Token::l_paren))
1161 return (emitError("expected '(' at start of affine map range"), nullptr);
1162
1163 auto parseRangeSize = [&]() -> ParseResult {
1164 auto *elt = parseAffineExpr();
1165 ParseResult res = elt ? ParseSuccess : ParseFailure;
1166 rangeSizes.push_back(elt);
1167 return res;
1168 };
1169
1170 setSymbolicParsing(true);
Chris Lattner40746442018-07-21 14:32:09 -07001171 if (parseCommaSeparatedListUntil(Token::r_paren, parseRangeSize, false))
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001172 return nullptr;
1173 if (exprs.size() > rangeSizes.size())
1174 return (emitError(loc, "fewer range sizes than range expressions"),
1175 nullptr);
1176 if (exprs.size() < rangeSizes.size())
1177 return (emitError(loc, "more range sizes than range expressions"),
1178 nullptr);
1179 }
1180
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001181 // Parsed a valid affine map.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001182 return builder.getAffineMap(dims.size(), symbols.size(), exprs, rangeSizes);
MLIR Teamf85a6262018-06-27 11:03:08 -07001183}
1184
Chris Lattner2e595eb2018-07-10 10:08:27 -07001185AffineMap *Parser::parseAffineMapInline() {
1186 return AffineMapParser(state).parseAffineMapInline();
1187}
1188
MLIR Team718c82f2018-07-16 09:45:22 -07001189AffineMap *Parser::parseAffineMapReference() {
1190 if (getToken().is(Token::hash_identifier)) {
1191 // Parse affine map identifier and verify that it exists.
1192 StringRef affineMapId = getTokenSpelling().drop_front();
1193 if (getState().affineMapDefinitions.count(affineMapId) == 0)
1194 return (emitError("undefined affine map id '" + affineMapId + "'"),
1195 nullptr);
1196 consumeToken(Token::hash_identifier);
1197 return getState().affineMapDefinitions[affineMapId];
1198 }
1199 // Try to parse inline affine map.
1200 return parseAffineMapInline();
1201}
1202
MLIR Teamf85a6262018-06-27 11:03:08 -07001203//===----------------------------------------------------------------------===//
Chris Lattner7f9cc272018-07-19 08:35:28 -07001204// FunctionParser
Chris Lattner4c95a502018-06-23 16:03:42 -07001205//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001206
Chris Lattner7f9cc272018-07-19 08:35:28 -07001207namespace {
1208/// This class contains parser state that is common across CFG and ML functions,
1209/// notably for dealing with operations and SSA values.
1210class FunctionParser : public Parser {
1211public:
1212 FunctionParser(ParserState &state) : Parser(state) {}
1213
Chris Lattner6119d382018-07-20 18:41:34 -07001214 /// After the function is finished parsing, this function checks to see if
1215 /// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001216 ParseResult finalizeFunction(Function *func, SMLoc loc);
Chris Lattner6119d382018-07-20 18:41:34 -07001217
1218 /// This represents a use of an SSA value in the program. The first two
1219 /// entries in the tuple are the name and result number of a reference. The
1220 /// third is the location of the reference, which is used in case this ends up
1221 /// being a use of an undefined value.
1222 struct SSAUseInfo {
1223 StringRef name; // Value name, e.g. %42 or %abc
1224 unsigned number; // Number, specified with #12
1225 SMLoc loc; // Location of first definition or use.
1226 };
Chris Lattner7f9cc272018-07-19 08:35:28 -07001227
1228 /// Given a reference to an SSA value and its type, return a reference. This
1229 /// returns null on failure.
1230 SSAValue *resolveSSAUse(SSAUseInfo useInfo, Type *type);
1231
1232 /// Register a definition of a value with the symbol table.
1233 ParseResult addDefinition(SSAUseInfo useInfo, SSAValue *value);
1234
1235 // SSA parsing productions.
1236 ParseResult parseSSAUse(SSAUseInfo &result);
Chris Lattner40746442018-07-21 14:32:09 -07001237 ParseResult parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results);
James Molloy61a656c2018-07-22 15:45:24 -07001238
1239 template <typename ResultType>
1240 ResultType parseSSADefOrUseAndType(
1241 const std::function<ResultType(SSAUseInfo, Type *)> &action);
1242
1243 SSAValue *parseSSAUseAndType() {
1244 return parseSSADefOrUseAndType<SSAValue *>(
1245 [&](SSAUseInfo useInfo, Type *type) -> SSAValue * {
1246 return resolveSSAUse(useInfo, type);
1247 });
1248 }
Chris Lattner40746442018-07-21 14:32:09 -07001249
1250 template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001251 ParseResult
Chris Lattner2c402672018-07-23 11:56:17 -07001252 parseOptionalSSAUseAndTypeList(SmallVectorImpl<ValueTy *> &results,
1253 bool isParenthesized);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001254
1255 // Operations
1256 ParseResult parseOperation(const CreateOperationFunction &createOpFunc);
1257
1258private:
1259 /// This keeps track of all of the SSA values we are tracking, indexed by
Chris Lattner6119d382018-07-20 18:41:34 -07001260 /// their name. This has one entry per result number.
1261 llvm::StringMap<SmallVector<std::pair<SSAValue *, SMLoc>, 1>> values;
1262
1263 /// These are all of the placeholders we've made along with the location of
1264 /// their first reference, to allow checking for use of undefined values.
1265 DenseMap<SSAValue *, SMLoc> forwardReferencePlaceholders;
1266
1267 SSAValue *createForwardReferencePlaceholder(SMLoc loc, Type *type);
1268
1269 /// Return true if this is a forward reference.
1270 bool isForwardReferencePlaceholder(SSAValue *value) {
1271 return forwardReferencePlaceholders.count(value);
1272 }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001273};
1274} // end anonymous namespace
1275
Chris Lattner6119d382018-07-20 18:41:34 -07001276/// Create and remember a new placeholder for a forward reference.
1277SSAValue *FunctionParser::createForwardReferencePlaceholder(SMLoc loc,
1278 Type *type) {
1279 // Forward references are always created as instructions, even in ML
1280 // functions, because we just need something with a def/use chain.
1281 //
1282 // We create these placeholders as having an empty name, which we know cannot
1283 // be created through normal user input, allowing us to distinguish them.
1284 auto name = Identifier::get("placeholder", getContext());
1285 auto *inst = OperationInst::create(name, /*operands*/ {}, type, /*attrs*/ {},
1286 getContext());
1287 forwardReferencePlaceholders[inst->getResult(0)] = loc;
1288 return inst->getResult(0);
1289}
1290
Chris Lattner7f9cc272018-07-19 08:35:28 -07001291/// Given an unbound reference to an SSA value and its type, return a the value
1292/// it specifies. This returns null on failure.
1293SSAValue *FunctionParser::resolveSSAUse(SSAUseInfo useInfo, Type *type) {
Chris Lattner6119d382018-07-20 18:41:34 -07001294 auto &entries = values[useInfo.name];
1295
Chris Lattner7f9cc272018-07-19 08:35:28 -07001296 // If we have already seen a value of this name, return it.
Chris Lattner6119d382018-07-20 18:41:34 -07001297 if (useInfo.number < entries.size() && entries[useInfo.number].first) {
1298 auto *result = entries[useInfo.number].first;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001299 // Check that the type matches the other uses.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001300 if (result->getType() == type)
1301 return result;
1302
Chris Lattner6119d382018-07-20 18:41:34 -07001303 emitError(useInfo.loc, "use of value '" + useInfo.name.str() +
1304 "' expects different type than prior uses");
1305 emitError(entries[useInfo.number].second, "prior use here");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001306 return nullptr;
1307 }
1308
Chris Lattner6119d382018-07-20 18:41:34 -07001309 // Make sure we have enough slots for this.
1310 if (entries.size() <= useInfo.number)
1311 entries.resize(useInfo.number + 1);
1312
1313 // If the value has already been defined and this is an overly large result
1314 // number, diagnose that.
1315 if (entries[0].first && !isForwardReferencePlaceholder(entries[0].first))
1316 return (emitError(useInfo.loc, "reference to invalid result number"),
1317 nullptr);
1318
1319 // Otherwise, this is a forward reference. Create a placeholder and remember
1320 // that we did so.
1321 auto *result = createForwardReferencePlaceholder(useInfo.loc, type);
1322 entries[useInfo.number].first = result;
1323 entries[useInfo.number].second = useInfo.loc;
1324 return result;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001325}
1326
1327/// Register a definition of a value with the symbol table.
1328ParseResult FunctionParser::addDefinition(SSAUseInfo useInfo, SSAValue *value) {
Chris Lattner6119d382018-07-20 18:41:34 -07001329 auto &entries = values[useInfo.name];
Chris Lattner7f9cc272018-07-19 08:35:28 -07001330
Chris Lattner6119d382018-07-20 18:41:34 -07001331 // Make sure there is a slot for this value.
1332 if (entries.size() <= useInfo.number)
1333 entries.resize(useInfo.number + 1);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001334
Chris Lattner6119d382018-07-20 18:41:34 -07001335 // If we already have an entry for this, check to see if it was a definition
1336 // or a forward reference.
1337 if (auto *existing = entries[useInfo.number].first) {
1338 if (!isForwardReferencePlaceholder(existing)) {
1339 emitError(useInfo.loc,
1340 "redefinition of SSA value '" + useInfo.name + "'");
1341 return emitError(entries[useInfo.number].second,
1342 "previously defined here");
1343 }
1344
1345 // If it was a forward reference, update everything that used it to use the
1346 // actual definition instead, delete the forward ref, and remove it from our
1347 // set of forward references we track.
1348 existing->replaceAllUsesWith(value);
1349 existing->getDefiningInst()->destroy();
1350 forwardReferencePlaceholders.erase(existing);
1351 }
1352
1353 entries[useInfo.number].first = value;
1354 entries[useInfo.number].second = useInfo.loc;
1355 return ParseSuccess;
1356}
1357
1358/// After the function is finished parsing, this function checks to see if
1359/// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001360ParseResult FunctionParser::finalizeFunction(Function *func, SMLoc loc) {
Chris Lattner6119d382018-07-20 18:41:34 -07001361 // Check for any forward references that are left. If we find any, error out.
1362 if (!forwardReferencePlaceholders.empty()) {
1363 SmallVector<std::pair<const char *, SSAValue *>, 4> errors;
1364 // Iteration over the map isn't determinstic, so sort by source location.
1365 for (auto entry : forwardReferencePlaceholders)
1366 errors.push_back({entry.second.getPointer(), entry.first});
1367 llvm::array_pod_sort(errors.begin(), errors.end());
1368
1369 for (auto entry : errors)
1370 emitError(SMLoc::getFromPointer(entry.first),
1371 "use of undeclared SSA value name");
1372 return ParseFailure;
1373 }
1374
Chris Lattner40746442018-07-21 14:32:09 -07001375 // Run the verifier on this function. If an error is detected, report it.
1376 std::string errorString;
1377 if (func->verify(&errorString))
1378 return emitError(loc, errorString);
1379
Chris Lattner6119d382018-07-20 18:41:34 -07001380 return ParseSuccess;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001381}
1382
Chris Lattner78276e32018-07-07 15:48:26 -07001383/// Parse a SSA operand for an instruction or statement.
1384///
James Molloy61a656c2018-07-22 15:45:24 -07001385/// ssa-use ::= ssa-id
Chris Lattner78276e32018-07-07 15:48:26 -07001386///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001387ParseResult FunctionParser::parseSSAUse(SSAUseInfo &result) {
Chris Lattner6119d382018-07-20 18:41:34 -07001388 result.name = getTokenSpelling();
1389 result.number = 0;
1390 result.loc = getToken().getLoc();
Chris Lattner7f9cc272018-07-19 08:35:28 -07001391 if (!consumeIf(Token::percent_identifier))
1392 return emitError("expected SSA operand");
Chris Lattner6119d382018-07-20 18:41:34 -07001393
1394 // If we have an affine map ID, it is a result number.
1395 if (getToken().is(Token::hash_identifier)) {
1396 if (auto value = getToken().getHashIdentifierNumber())
1397 result.number = value.getValue();
1398 else
1399 return emitError("invalid SSA value result number");
1400 consumeToken(Token::hash_identifier);
1401 }
1402
Chris Lattner7f9cc272018-07-19 08:35:28 -07001403 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001404}
1405
1406/// Parse a (possibly empty) list of SSA operands.
1407///
1408/// ssa-use-list ::= ssa-use (`,` ssa-use)*
1409/// ssa-use-list-opt ::= ssa-use-list?
1410///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001411ParseResult
Chris Lattner40746442018-07-21 14:32:09 -07001412FunctionParser::parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results) {
1413 if (!getToken().is(Token::percent_identifier))
1414 return ParseSuccess;
1415 return parseCommaSeparatedList([&]() -> ParseResult {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001416 SSAUseInfo result;
1417 if (parseSSAUse(result))
1418 return ParseFailure;
1419 results.push_back(result);
1420 return ParseSuccess;
1421 });
Chris Lattner78276e32018-07-07 15:48:26 -07001422}
1423
1424/// Parse an SSA use with an associated type.
1425///
1426/// ssa-use-and-type ::= ssa-use `:` type
James Molloy61a656c2018-07-22 15:45:24 -07001427template <typename ResultType>
1428ResultType FunctionParser::parseSSADefOrUseAndType(
1429 const std::function<ResultType(SSAUseInfo, Type *)> &action) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001430 SSAUseInfo useInfo;
1431 if (parseSSAUse(useInfo))
1432 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001433
1434 if (!consumeIf(Token::colon))
Chris Lattner7f9cc272018-07-19 08:35:28 -07001435 return (emitError("expected ':' and type for SSA operand"), nullptr);
Chris Lattner78276e32018-07-07 15:48:26 -07001436
Chris Lattner7f9cc272018-07-19 08:35:28 -07001437 auto *type = parseType();
1438 if (!type)
1439 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001440
James Molloy61a656c2018-07-22 15:45:24 -07001441 return action(useInfo, type);
Chris Lattner78276e32018-07-07 15:48:26 -07001442}
1443
Chris Lattner2c402672018-07-23 11:56:17 -07001444/// Parse a (possibly empty) list of SSA operands, followed by a colon, then
1445/// followed by a type list. If hasParens is true, then the operands are
1446/// surrounded by parens.
Chris Lattner78276e32018-07-07 15:48:26 -07001447///
Chris Lattner2c402672018-07-23 11:56:17 -07001448/// ssa-use-and-type-list[parens]
1449/// ::= `(` ssa-use-list `)` ':' type-list-no-parens
1450///
1451/// ssa-use-and-type-list[!parens]
1452/// ::= ssa-use-list ':' type-list-no-parens
Chris Lattner78276e32018-07-07 15:48:26 -07001453///
Chris Lattner40746442018-07-21 14:32:09 -07001454template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001455ParseResult FunctionParser::parseOptionalSSAUseAndTypeList(
Chris Lattner2c402672018-07-23 11:56:17 -07001456 SmallVectorImpl<ValueTy *> &results, bool isParenthesized) {
1457
1458 // If we are in the parenthesized form and no paren exists, then we succeed
1459 // with an empty list.
1460 if (isParenthesized && !consumeIf(Token::l_paren))
Chris Lattner40746442018-07-21 14:32:09 -07001461 return ParseSuccess;
1462
Chris Lattner2c402672018-07-23 11:56:17 -07001463 SmallVector<SSAUseInfo, 4> valueIDs;
1464 if (parseOptionalSSAUseList(valueIDs))
Chris Lattner7f9cc272018-07-19 08:35:28 -07001465 return ParseFailure;
Chris Lattner2c402672018-07-23 11:56:17 -07001466
1467 if (isParenthesized && !consumeIf(Token::r_paren))
1468 return emitError("expected ')' in operand list");
1469
1470 // If there were no operands, then there is no colon or type lists.
1471 if (valueIDs.empty())
1472 return ParseSuccess;
1473
1474 if (!consumeIf(Token::colon))
1475 return emitError("expected ':' in operand list");
1476
1477 SmallVector<Type *, 4> types;
1478 if (parseTypeListNoParens(types))
1479 return ParseFailure;
1480
1481 if (valueIDs.size() != types.size())
1482 return emitError("expected " + Twine(valueIDs.size()) +
1483 " types to match operand list");
1484
1485 results.reserve(valueIDs.size());
1486 for (unsigned i = 0, e = valueIDs.size(); i != e; ++i) {
1487 if (auto *value = resolveSSAUse(valueIDs[i], types[i]))
1488 results.push_back(cast<ValueTy>(value));
1489 else
1490 return ParseFailure;
1491 }
1492
1493 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001494}
1495
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001496/// Parse the CFG or MLFunc operation.
1497///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001498/// operation ::=
1499/// (ssa-id `=`)? string '(' ssa-use-list? ')' attribute-dict?
1500/// `:` function-type
1501///
1502ParseResult
Chris Lattner7f9cc272018-07-19 08:35:28 -07001503FunctionParser::parseOperation(const CreateOperationFunction &createOpFunc) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001504 auto loc = getToken().getLoc();
1505
1506 StringRef resultID;
1507 if (getToken().is(Token::percent_identifier)) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001508 resultID = getTokenSpelling();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001509 consumeToken(Token::percent_identifier);
1510 if (!consumeIf(Token::equal))
1511 return emitError("expected '=' after SSA name");
1512 }
1513
1514 if (getToken().isNot(Token::string))
1515 return emitError("expected operation name in quotes");
1516
1517 auto name = getToken().getStringValue();
1518 if (name.empty())
1519 return emitError("empty operation name is invalid");
1520
1521 consumeToken(Token::string);
1522
1523 if (!consumeIf(Token::l_paren))
1524 return emitError("expected '(' to start operand list");
1525
1526 // Parse the operand list.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001527 SmallVector<SSAUseInfo, 8> operandInfos;
Chris Lattner40746442018-07-21 14:32:09 -07001528 if (parseOptionalSSAUseList(operandInfos))
1529 return ParseFailure;
1530
1531 if (!consumeIf(Token::r_paren))
1532 return emitError("expected ')' to end operand list");
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001533
1534 SmallVector<NamedAttribute, 4> attributes;
1535 if (getToken().is(Token::l_brace)) {
1536 if (parseAttributeDict(attributes))
1537 return ParseFailure;
1538 }
1539
Chris Lattner3b2ef762018-07-18 15:31:25 -07001540 if (!consumeIf(Token::colon))
1541 return emitError("expected ':' followed by instruction type");
1542
1543 auto typeLoc = getToken().getLoc();
1544 auto type = parseType();
1545 if (!type)
1546 return ParseFailure;
1547 auto fnType = dyn_cast<FunctionType>(type);
1548 if (!fnType)
1549 return emitError(typeLoc, "expected function type");
1550
Chris Lattner7f9cc272018-07-19 08:35:28 -07001551 // Check that we have the right number of types for the operands.
1552 auto operandTypes = fnType->getInputs();
1553 if (operandTypes.size() != operandInfos.size()) {
1554 auto plural = "s"[operandInfos.size() == 1];
1555 return emitError(typeLoc, "expected " + llvm::utostr(operandInfos.size()) +
Chris Lattnerf8cce872018-07-20 09:28:54 -07001556 " operand type" + plural + " but had " +
Chris Lattner7f9cc272018-07-19 08:35:28 -07001557 llvm::utostr(operandTypes.size()));
1558 }
1559
1560 // Resolve all of the operands.
1561 SmallVector<SSAValue *, 8> operands;
1562 for (unsigned i = 0, e = operandInfos.size(); i != e; ++i) {
1563 operands.push_back(resolveSSAUse(operandInfos[i], operandTypes[i]));
1564 if (!operands.back())
1565 return ParseFailure;
1566 }
1567
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001568 auto nameId = builder.getIdentifier(name);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001569 auto op = createOpFunc(nameId, operands, fnType->getResults(), attributes);
1570 if (!op)
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001571 return ParseFailure;
1572
1573 // We just parsed an operation. If it is a recognized one, verify that it
1574 // is structurally as we expect. If not, produce an error with a reasonable
1575 // source location.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001576 if (auto *opInfo = op->getAbstractOperation(builder.getContext())) {
1577 if (auto error = opInfo->verifyInvariants(op))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001578 return emitError(loc, error);
1579 }
1580
Chris Lattner7f9cc272018-07-19 08:35:28 -07001581 // If the instruction had a name, register it.
1582 if (!resultID.empty()) {
1583 // FIXME: Add result infra to handle Stmt results as well to make this
1584 // generic.
1585 if (auto *inst = dyn_cast<OperationInst>(op)) {
Chris Lattnerf8cce872018-07-20 09:28:54 -07001586 if (inst->getNumResults() == 0)
Chris Lattner7f9cc272018-07-19 08:35:28 -07001587 return emitError(loc, "cannot name an operation with no results");
1588
Chris Lattner6119d382018-07-20 18:41:34 -07001589 for (unsigned i = 0, e = inst->getNumResults(); i != e; ++i)
1590 addDefinition({resultID, i, loc}, inst->getResult(i));
Chris Lattner7f9cc272018-07-19 08:35:28 -07001591 }
1592 }
1593
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001594 return ParseSuccess;
1595}
Chris Lattnere79379a2018-06-22 10:39:19 -07001596
Chris Lattner48af7d12018-07-09 19:05:38 -07001597//===----------------------------------------------------------------------===//
1598// CFG Functions
1599//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001600
Chris Lattner4c95a502018-06-23 16:03:42 -07001601namespace {
Chris Lattner48af7d12018-07-09 19:05:38 -07001602/// This is a specialized parser for CFGFunction's, maintaining the state
1603/// transient to their bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001604class CFGFunctionParser : public FunctionParser {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001605public:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001606 CFGFunctionParser(ParserState &state, CFGFunction *function)
Chris Lattner7f9cc272018-07-19 08:35:28 -07001607 : FunctionParser(state), function(function), builder(function) {}
Chris Lattner2e595eb2018-07-10 10:08:27 -07001608
1609 ParseResult parseFunctionBody();
1610
1611private:
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001612 CFGFunction *function;
1613 llvm::StringMap<std::pair<BasicBlock*, SMLoc>> blocksByName;
Chris Lattner48af7d12018-07-09 19:05:38 -07001614
1615 /// This builder intentionally shadows the builder in the base class, with a
1616 /// more specific builder type.
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001617 CFGFuncBuilder builder;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001618
Chris Lattner4c95a502018-06-23 16:03:42 -07001619 /// Get the basic block with the specified name, creating it if it doesn't
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001620 /// already exist. The location specified is the point of use, which allows
1621 /// us to diagnose references to blocks that are not defined precisely.
1622 BasicBlock *getBlockNamed(StringRef name, SMLoc loc) {
1623 auto &blockAndLoc = blocksByName[name];
1624 if (!blockAndLoc.first) {
Chris Lattner3a467cc2018-07-01 20:28:00 -07001625 blockAndLoc.first = new BasicBlock();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001626 blockAndLoc.second = loc;
Chris Lattner4c95a502018-06-23 16:03:42 -07001627 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001628 return blockAndLoc.first;
Chris Lattner4c95a502018-06-23 16:03:42 -07001629 }
Chris Lattner48af7d12018-07-09 19:05:38 -07001630
James Molloy61a656c2018-07-22 15:45:24 -07001631 ParseResult
1632 parseOptionalBasicBlockArgList(SmallVectorImpl<BBArgument *> &results,
1633 BasicBlock *owner);
1634
Chris Lattner48af7d12018-07-09 19:05:38 -07001635 ParseResult parseBasicBlock();
1636 OperationInst *parseCFGOperation();
1637 TerminatorInst *parseTerminator();
Chris Lattner4c95a502018-06-23 16:03:42 -07001638};
1639} // end anonymous namespace
1640
James Molloy61a656c2018-07-22 15:45:24 -07001641/// Parse a (possibly empty) list of SSA operands with types as basic block
Chris Lattner2c402672018-07-23 11:56:17 -07001642/// arguments.
James Molloy61a656c2018-07-22 15:45:24 -07001643///
1644/// ssa-id-and-type-list ::= ssa-id-and-type (`,` ssa-id-and-type)*
1645///
1646ParseResult CFGFunctionParser::parseOptionalBasicBlockArgList(
1647 SmallVectorImpl<BBArgument *> &results, BasicBlock *owner) {
1648 if (getToken().is(Token::r_brace))
1649 return ParseSuccess;
1650
1651 return parseCommaSeparatedList([&]() -> ParseResult {
1652 auto type = parseSSADefOrUseAndType<Type *>(
1653 [&](SSAUseInfo useInfo, Type *type) -> Type * {
1654 BBArgument *arg = owner->addArgument(type);
1655 if (addDefinition(useInfo, arg) == ParseFailure)
1656 return nullptr;
1657 return type;
1658 });
1659 return type ? ParseSuccess : ParseFailure;
1660 });
1661}
1662
Chris Lattner48af7d12018-07-09 19:05:38 -07001663ParseResult CFGFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07001664 auto braceLoc = getToken().getLoc();
Chris Lattner48af7d12018-07-09 19:05:38 -07001665 if (!consumeIf(Token::l_brace))
1666 return emitError("expected '{' in CFG function");
1667
1668 // Make sure we have at least one block.
1669 if (getToken().is(Token::r_brace))
1670 return emitError("CFG functions must have at least one basic block");
Chris Lattner4c95a502018-06-23 16:03:42 -07001671
1672 // Parse the list of blocks.
1673 while (!consumeIf(Token::r_brace))
Chris Lattner48af7d12018-07-09 19:05:38 -07001674 if (parseBasicBlock())
Chris Lattner4c95a502018-06-23 16:03:42 -07001675 return ParseFailure;
1676
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001677 // Verify that all referenced blocks were defined. Iteration over a
1678 // StringMap isn't determinstic, but this is good enough for our purposes.
Chris Lattner48af7d12018-07-09 19:05:38 -07001679 for (auto &elt : blocksByName) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001680 auto *bb = elt.second.first;
Chris Lattner3a467cc2018-07-01 20:28:00 -07001681 if (!bb->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001682 return emitError(elt.second.second,
1683 "reference to an undefined basic block '" +
1684 elt.first() + "'");
1685 }
1686
Chris Lattner48af7d12018-07-09 19:05:38 -07001687 getModule()->functionList.push_back(function);
Chris Lattner6119d382018-07-20 18:41:34 -07001688
Chris Lattner40746442018-07-21 14:32:09 -07001689 return finalizeFunction(function, braceLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001690}
1691
1692/// Basic block declaration.
1693///
1694/// basic-block ::= bb-label instruction* terminator-stmt
1695/// bb-label ::= bb-id bb-arg-list? `:`
1696/// bb-id ::= bare-id
1697/// bb-arg-list ::= `(` ssa-id-and-type-list? `)`
1698///
Chris Lattner48af7d12018-07-09 19:05:38 -07001699ParseResult CFGFunctionParser::parseBasicBlock() {
1700 SMLoc nameLoc = getToken().getLoc();
1701 auto name = getTokenSpelling();
Chris Lattner4c95a502018-06-23 16:03:42 -07001702 if (!consumeIf(Token::bare_identifier))
1703 return emitError("expected basic block name");
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001704
Chris Lattner48af7d12018-07-09 19:05:38 -07001705 auto *block = getBlockNamed(name, nameLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001706
1707 // If this block has already been parsed, then this is a redefinition with the
1708 // same block name.
Chris Lattner3a467cc2018-07-01 20:28:00 -07001709 if (block->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001710 return emitError(nameLoc, "redefinition of block '" + name.str() + "'");
1711
Chris Lattner78276e32018-07-07 15:48:26 -07001712 // If an argument list is present, parse it.
1713 if (consumeIf(Token::l_paren)) {
James Molloy61a656c2018-07-22 15:45:24 -07001714 SmallVector<BBArgument *, 8> bbArgs;
1715 if (parseOptionalBasicBlockArgList(bbArgs, block))
Chris Lattner78276e32018-07-07 15:48:26 -07001716 return ParseFailure;
Chris Lattner40746442018-07-21 14:32:09 -07001717 if (!consumeIf(Token::r_paren))
1718 return emitError("expected ')' to end argument list");
Chris Lattner78276e32018-07-07 15:48:26 -07001719 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001720
James Molloy61a656c2018-07-22 15:45:24 -07001721 // Add the block to the function.
1722 function->push_back(block);
1723
Chris Lattner4c95a502018-06-23 16:03:42 -07001724 if (!consumeIf(Token::colon))
1725 return emitError("expected ':' after basic block name");
1726
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001727 // Set the insertion point to the block we want to insert new operations into.
Chris Lattner48af7d12018-07-09 19:05:38 -07001728 builder.setInsertionPoint(block);
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001729
Chris Lattner7f9cc272018-07-19 08:35:28 -07001730 auto createOpFunc = [&](Identifier name, ArrayRef<SSAValue *> operands,
1731 ArrayRef<Type *> resultTypes,
1732 ArrayRef<NamedAttribute> attrs) -> Operation * {
1733 SmallVector<CFGValue *, 8> cfgOperands;
1734 cfgOperands.reserve(operands.size());
1735 for (auto *op : operands)
1736 cfgOperands.push_back(cast<CFGValue>(op));
1737 return builder.createOperation(name, cfgOperands, resultTypes, attrs);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001738 };
1739
Chris Lattnered65a732018-06-28 20:45:33 -07001740 // Parse the list of operations that make up the body of the block.
Chris Lattner48af7d12018-07-09 19:05:38 -07001741 while (getToken().isNot(Token::kw_return, Token::kw_br)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001742 if (parseOperation(createOpFunc))
Chris Lattnered65a732018-06-28 20:45:33 -07001743 return ParseFailure;
1744 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001745
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001746 if (!parseTerminator())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001747 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07001748
1749 return ParseSuccess;
1750}
1751
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001752/// Parse the terminator instruction for a basic block.
1753///
1754/// terminator-stmt ::= `br` bb-id branch-use-list?
Chris Lattner1604e472018-07-23 08:42:19 -07001755/// branch-use-list ::= `(` ssa-use-list `)` ':' type-list-no-parens
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001756/// terminator-stmt ::=
1757/// `cond_br` ssa-use `,` bb-id branch-use-list? `,` bb-id branch-use-list?
1758/// terminator-stmt ::= `return` ssa-use-and-type-list?
1759///
Chris Lattner48af7d12018-07-09 19:05:38 -07001760TerminatorInst *CFGFunctionParser::parseTerminator() {
1761 switch (getToken().getKind()) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001762 default:
Chris Lattner3a467cc2018-07-01 20:28:00 -07001763 return (emitError("expected terminator at end of basic block"), nullptr);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001764
Chris Lattner40746442018-07-21 14:32:09 -07001765 case Token::kw_return: {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001766 consumeToken(Token::kw_return);
Chris Lattner40746442018-07-21 14:32:09 -07001767
Chris Lattner2c402672018-07-23 11:56:17 -07001768 // Parse any operands.
1769 SmallVector<CFGValue *, 8> operands;
1770 if (parseOptionalSSAUseAndTypeList(operands, /*isParenthesized*/ false))
1771 return nullptr;
1772 return builder.createReturnInst(operands);
Chris Lattner40746442018-07-21 14:32:09 -07001773 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001774
1775 case Token::kw_br: {
1776 consumeToken(Token::kw_br);
Chris Lattner48af7d12018-07-09 19:05:38 -07001777 auto destBB = getBlockNamed(getTokenSpelling(), getToken().getLoc());
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001778 if (!consumeIf(Token::bare_identifier))
Chris Lattner3a467cc2018-07-01 20:28:00 -07001779 return (emitError("expected basic block name"), nullptr);
Chris Lattner1604e472018-07-23 08:42:19 -07001780 auto branch = builder.createBranchInst(destBB);
1781
Chris Lattner2c402672018-07-23 11:56:17 -07001782 SmallVector<CFGValue *, 8> operands;
1783 if (parseOptionalSSAUseAndTypeList(operands, /*isParenthesized*/ true))
Chris Lattner1604e472018-07-23 08:42:19 -07001784 return nullptr;
Chris Lattner2c402672018-07-23 11:56:17 -07001785 branch->addOperands(operands);
Chris Lattner1604e472018-07-23 08:42:19 -07001786 return branch;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001787 }
Chris Lattner78276e32018-07-07 15:48:26 -07001788 // TODO: cond_br.
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001789 }
1790}
1791
Chris Lattner48af7d12018-07-09 19:05:38 -07001792//===----------------------------------------------------------------------===//
1793// ML Functions
1794//===----------------------------------------------------------------------===//
1795
1796namespace {
1797/// Refined parser for MLFunction bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001798class MLFunctionParser : public FunctionParser {
Chris Lattner48af7d12018-07-09 19:05:38 -07001799public:
Chris Lattner48af7d12018-07-09 19:05:38 -07001800 MLFunctionParser(ParserState &state, MLFunction *function)
Chris Lattner7f9cc272018-07-19 08:35:28 -07001801 : FunctionParser(state), function(function), builder(function) {}
Chris Lattner48af7d12018-07-09 19:05:38 -07001802
1803 ParseResult parseFunctionBody();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001804
1805private:
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001806 MLFunction *function;
1807
1808 /// This builder intentionally shadows the builder in the base class, with a
1809 /// more specific builder type.
1810 MLFuncBuilder builder;
1811
1812 ParseResult parseForStmt();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001813 AffineConstantExpr *parseIntConstant();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001814 ParseResult parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001815 ParseResult parseElseClause(IfClause *elseClause);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001816 ParseResult parseStatements(StmtBlock *block);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001817 ParseResult parseStmtBlock(StmtBlock *block);
Chris Lattner48af7d12018-07-09 19:05:38 -07001818};
1819} // end anonymous namespace
1820
Chris Lattner48af7d12018-07-09 19:05:38 -07001821ParseResult MLFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07001822 auto braceLoc = getToken().getLoc();
Chris Lattner48af7d12018-07-09 19:05:38 -07001823 if (!consumeIf(Token::l_brace))
1824 return emitError("expected '{' in ML function");
1825
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001826 // Parse statements in this function
1827 if (parseStatements(function))
1828 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001829
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001830 if (!consumeIf(Token::kw_return))
1831 emitError("ML function must end with return statement");
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001832
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001833 // TODO: store return operands in the IR.
1834 SmallVector<SSAUseInfo, 4> dummyUseInfo;
Chris Lattner40746442018-07-21 14:32:09 -07001835 if (parseOptionalSSAUseList(dummyUseInfo))
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001836 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001837
Chris Lattner40746442018-07-21 14:32:09 -07001838 if (!consumeIf(Token::r_brace))
1839 return emitError("expected '}' to end mlfunc");
1840
Chris Lattner48af7d12018-07-09 19:05:38 -07001841 getModule()->functionList.push_back(function);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001842
Chris Lattner40746442018-07-21 14:32:09 -07001843 return finalizeFunction(function, braceLoc);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001844}
1845
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001846/// For statement.
1847///
Chris Lattner48af7d12018-07-09 19:05:38 -07001848/// ml-for-stmt ::= `for` ssa-id `=` lower-bound `to` upper-bound
1849/// (`step` integer-literal)? `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001850///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001851ParseResult MLFunctionParser::parseForStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001852 consumeToken(Token::kw_for);
1853
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001854 // Parse induction variable
1855 if (getToken().isNot(Token::percent_identifier))
1856 return emitError("expected SSA identifier for the loop variable");
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001857
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001858 // TODO: create SSA value definition from name
1859 StringRef name = getTokenSpelling().drop_front();
1860 (void)name;
1861
1862 consumeToken(Token::percent_identifier);
1863
1864 if (!consumeIf(Token::equal))
1865 return emitError("expected =");
1866
1867 // Parse loop bounds
1868 AffineConstantExpr *lowerBound = parseIntConstant();
1869 if (!lowerBound)
1870 return ParseFailure;
1871
1872 if (!consumeIf(Token::kw_to))
1873 return emitError("expected 'to' between bounds");
1874
1875 AffineConstantExpr *upperBound = parseIntConstant();
1876 if (!upperBound)
1877 return ParseFailure;
1878
1879 // Parse step
1880 AffineConstantExpr *step = nullptr;
1881 if (consumeIf(Token::kw_step)) {
1882 step = parseIntConstant();
1883 if (!step)
1884 return ParseFailure;
1885 }
1886
1887 // Create for statement.
1888 ForStmt *stmt = builder.createFor(lowerBound, upperBound, step);
1889
1890 // If parsing of the for statement body fails,
1891 // MLIR contains for statement with those nested statements that have been
1892 // successfully parsed.
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001893 if (parseStmtBlock(static_cast<StmtBlock *>(stmt)))
1894 return ParseFailure;
1895
1896 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001897}
1898
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001899// This method is temporary workaround to parse simple loop bounds and
1900// step.
1901// TODO: remove this method once it's no longer used.
1902AffineConstantExpr *MLFunctionParser::parseIntConstant() {
1903 if (getToken().isNot(Token::integer))
1904 return (emitError("expected non-negative integer for now"), nullptr);
1905
1906 auto val = getToken().getUInt64IntegerValue();
1907 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
1908 return (emitError("constant too large for affineint"), nullptr);
1909 }
1910 consumeToken(Token::integer);
1911 return builder.getConstantExpr((int64_t)val.getValue());
1912}
1913
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001914/// If statement.
1915///
Chris Lattner48af7d12018-07-09 19:05:38 -07001916/// ml-if-head ::= `if` ml-if-cond `{` ml-stmt* `}`
1917/// | ml-if-head `else` `if` ml-if-cond `{` ml-stmt* `}`
1918/// ml-if-stmt ::= ml-if-head
1919/// | ml-if-head `else` `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001920///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001921ParseResult MLFunctionParser::parseIfStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001922 consumeToken(Token::kw_if);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001923 if (!consumeIf(Token::l_paren))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001924 return emitError("expected (");
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001925
1926 //TODO: parse condition
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001927
1928 if (!consumeIf(Token::r_paren))
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001929 return emitError("expected ')'");
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001930
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001931 IfStmt *ifStmt = builder.createIf();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001932 IfClause *thenClause = ifStmt->getThenClause();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001933
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07001934 // When parsing of an if statement body fails, the IR contains
1935 // the if statement with the portion of the body that has been
1936 // successfully parsed.
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001937 if (parseStmtBlock(thenClause))
1938 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001939
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001940 if (consumeIf(Token::kw_else)) {
1941 IfClause *elseClause = ifStmt->createElseClause();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001942 if (parseElseClause(elseClause))
1943 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001944 }
1945
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001946 return ParseSuccess;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001947}
1948
1949ParseResult MLFunctionParser::parseElseClause(IfClause *elseClause) {
1950 if (getToken().is(Token::kw_if)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001951 builder.setInsertionPoint(elseClause);
1952 return parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001953 }
1954
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001955 return parseStmtBlock(elseClause);
1956}
1957
1958///
1959/// Parse a list of statements ending with `return` or `}`
1960///
1961ParseResult MLFunctionParser::parseStatements(StmtBlock *block) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001962 auto createOpFunc = [&](Identifier name, ArrayRef<SSAValue *> operands,
1963 ArrayRef<Type *> resultTypes,
1964 ArrayRef<NamedAttribute> attrs) -> Operation * {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001965 return builder.createOperation(name, attrs);
1966 };
1967
1968 builder.setInsertionPoint(block);
1969
1970 while (getToken().isNot(Token::kw_return, Token::r_brace)) {
1971 switch (getToken().getKind()) {
1972 default:
1973 if (parseOperation(createOpFunc))
1974 return ParseFailure;
1975 break;
1976 case Token::kw_for:
1977 if (parseForStmt())
1978 return ParseFailure;
1979 break;
1980 case Token::kw_if:
1981 if (parseIfStmt())
1982 return ParseFailure;
1983 break;
1984 } // end switch
1985 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001986
1987 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001988}
1989
1990///
1991/// Parse `{` ml-stmt* `}`
1992///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001993ParseResult MLFunctionParser::parseStmtBlock(StmtBlock *block) {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001994 if (!consumeIf(Token::l_brace))
1995 return emitError("expected '{' before statement list");
1996
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001997 if (parseStatements(block))
1998 return ParseFailure;
1999
2000 if (!consumeIf(Token::r_brace))
2001 return emitError("expected '}' at the end of the statement block");
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002002
2003 return ParseSuccess;
2004}
2005
Chris Lattner4c95a502018-06-23 16:03:42 -07002006//===----------------------------------------------------------------------===//
2007// Top-level entity parsing.
2008//===----------------------------------------------------------------------===//
2009
Chris Lattner2e595eb2018-07-10 10:08:27 -07002010namespace {
2011/// This parser handles entities that are only valid at the top level of the
2012/// file.
2013class ModuleParser : public Parser {
2014public:
2015 explicit ModuleParser(ParserState &state) : Parser(state) {}
2016
2017 ParseResult parseModule();
2018
2019private:
2020 ParseResult parseAffineMapDef();
2021
2022 // Functions.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002023 ParseResult parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2024 SmallVectorImpl<StringRef> &argNames);
2025 ParseResult parseFunctionSignature(StringRef &name, FunctionType *&type,
2026 SmallVectorImpl<StringRef> *argNames);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002027 ParseResult parseExtFunc();
2028 ParseResult parseCFGFunc();
2029 ParseResult parseMLFunc();
2030};
2031} // end anonymous namespace
2032
2033/// Affine map declaration.
2034///
2035/// affine-map-def ::= affine-map-id `=` affine-map-inline
2036///
2037ParseResult ModuleParser::parseAffineMapDef() {
2038 assert(getToken().is(Token::hash_identifier));
2039
2040 StringRef affineMapId = getTokenSpelling().drop_front();
2041
2042 // Check for redefinitions.
2043 auto *&entry = getState().affineMapDefinitions[affineMapId];
2044 if (entry)
2045 return emitError("redefinition of affine map id '" + affineMapId + "'");
2046
2047 consumeToken(Token::hash_identifier);
2048
2049 // Parse the '='
2050 if (!consumeIf(Token::equal))
2051 return emitError("expected '=' in affine map outlined definition");
2052
2053 entry = parseAffineMapInline();
2054 if (!entry)
2055 return ParseFailure;
2056
Chris Lattner2e595eb2018-07-10 10:08:27 -07002057 return ParseSuccess;
2058}
2059
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002060/// Parse a (possibly empty) list of MLFunction arguments with types.
2061///
2062/// ml-argument ::= ssa-id `:` type
2063/// ml-argument-list ::= ml-argument (`,` ml-argument)* | /*empty*/
2064///
2065ParseResult
2066ModuleParser::parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2067 SmallVectorImpl<StringRef> &argNames) {
2068 auto parseElt = [&]() -> ParseResult {
2069 // Parse argument name
2070 if (getToken().isNot(Token::percent_identifier))
2071 return emitError("expected SSA identifier");
2072
2073 StringRef name = getTokenSpelling().drop_front();
2074 consumeToken(Token::percent_identifier);
2075 argNames.push_back(name);
2076
2077 if (!consumeIf(Token::colon))
2078 return emitError("expected ':'");
2079
2080 // Parse argument type
2081 auto elt = parseType();
2082 if (!elt)
2083 return ParseFailure;
2084 argTypes.push_back(elt);
2085
2086 return ParseSuccess;
2087 };
2088
2089 if (!consumeIf(Token::l_paren))
2090 llvm_unreachable("expected '('");
2091
Chris Lattner40746442018-07-21 14:32:09 -07002092 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002093}
2094
Chris Lattner2e595eb2018-07-10 10:08:27 -07002095/// Parse a function signature, starting with a name and including the parameter
2096/// list.
2097///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002098/// argument-list ::= type (`,` type)* | /*empty*/ | ml-argument-list
Chris Lattner2e595eb2018-07-10 10:08:27 -07002099/// function-signature ::= function-id `(` argument-list `)` (`->` type-list)?
2100///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002101ParseResult
2102ModuleParser::parseFunctionSignature(StringRef &name, FunctionType *&type,
2103 SmallVectorImpl<StringRef> *argNames) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002104 if (getToken().isNot(Token::at_identifier))
2105 return emitError("expected a function identifier like '@foo'");
2106
2107 name = getTokenSpelling().drop_front();
2108 consumeToken(Token::at_identifier);
2109
2110 if (getToken().isNot(Token::l_paren))
2111 return emitError("expected '(' in function signature");
2112
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002113 SmallVector<Type *, 4> argTypes;
2114 ParseResult parseResult;
2115
2116 if (argNames)
2117 parseResult = parseMLArgumentList(argTypes, *argNames);
2118 else
2119 parseResult = parseTypeList(argTypes);
2120
2121 if (parseResult)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002122 return ParseFailure;
2123
2124 // Parse the return type if present.
2125 SmallVector<Type *, 4> results;
2126 if (consumeIf(Token::arrow)) {
2127 if (parseTypeList(results))
2128 return ParseFailure;
2129 }
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002130 type = builder.getFunctionType(argTypes, results);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002131 return ParseSuccess;
2132}
2133
2134/// External function declarations.
2135///
2136/// ext-func ::= `extfunc` function-signature
2137///
2138ParseResult ModuleParser::parseExtFunc() {
2139 consumeToken(Token::kw_extfunc);
2140
2141 StringRef name;
2142 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002143 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002144 return ParseFailure;
2145
2146 // Okay, the external function definition was parsed correctly.
2147 getModule()->functionList.push_back(new ExtFunction(name, type));
2148 return ParseSuccess;
2149}
2150
2151/// CFG function declarations.
2152///
2153/// cfg-func ::= `cfgfunc` function-signature `{` basic-block+ `}`
2154///
2155ParseResult ModuleParser::parseCFGFunc() {
2156 consumeToken(Token::kw_cfgfunc);
2157
2158 StringRef name;
2159 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002160 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002161 return ParseFailure;
2162
2163 // Okay, the CFG function signature was parsed correctly, create the function.
2164 auto function = new CFGFunction(name, type);
2165
2166 return CFGFunctionParser(getState(), function).parseFunctionBody();
2167}
2168
2169/// ML function declarations.
2170///
2171/// ml-func ::= `mlfunc` ml-func-signature `{` ml-stmt* ml-return-stmt `}`
2172///
2173ParseResult ModuleParser::parseMLFunc() {
2174 consumeToken(Token::kw_mlfunc);
2175
2176 StringRef name;
2177 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002178 SmallVector<StringRef, 4> argNames;
Chris Lattner2e595eb2018-07-10 10:08:27 -07002179 // FIXME: Parse ML function signature (args + types)
2180 // by passing pointer to SmallVector<identifier> into parseFunctionSignature
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002181
2182 if (parseFunctionSignature(name, type, &argNames))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002183 return ParseFailure;
2184
2185 // Okay, the ML function signature was parsed correctly, create the function.
2186 auto function = new MLFunction(name, type);
2187
2188 return MLFunctionParser(getState(), function).parseFunctionBody();
2189}
2190
Chris Lattnere79379a2018-06-22 10:39:19 -07002191/// This is the top-level module parser.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002192ParseResult ModuleParser::parseModule() {
Chris Lattnere79379a2018-06-22 10:39:19 -07002193 while (1) {
Chris Lattner48af7d12018-07-09 19:05:38 -07002194 switch (getToken().getKind()) {
Chris Lattnere79379a2018-06-22 10:39:19 -07002195 default:
2196 emitError("expected a top level entity");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002197 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002198
Uday Bondhugula015cbb12018-07-03 20:16:08 -07002199 // If we got to the end of the file, then we're done.
Chris Lattnere79379a2018-06-22 10:39:19 -07002200 case Token::eof:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002201 return ParseSuccess;
Chris Lattnere79379a2018-06-22 10:39:19 -07002202
2203 // If we got an error token, then the lexer already emitted an error, just
2204 // stop. Someday we could introduce error recovery if there was demand for
2205 // it.
2206 case Token::error:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002207 return ParseFailure;
2208
2209 case Token::hash_identifier:
2210 if (parseAffineMapDef())
2211 return ParseFailure;
2212 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002213
2214 case Token::kw_extfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002215 if (parseExtFunc())
2216 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002217 break;
2218
Chris Lattner4c95a502018-06-23 16:03:42 -07002219 case Token::kw_cfgfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002220 if (parseCFGFunc())
2221 return ParseFailure;
MLIR Teamf85a6262018-06-27 11:03:08 -07002222 break;
Chris Lattner4c95a502018-06-23 16:03:42 -07002223
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002224 case Token::kw_mlfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002225 if (parseMLFunc())
2226 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002227 break;
2228
Uday Bondhugula015cbb12018-07-03 20:16:08 -07002229 // TODO: affine entity declarations, etc.
Chris Lattnere79379a2018-06-22 10:39:19 -07002230 }
2231 }
2232}
2233
2234//===----------------------------------------------------------------------===//
2235
Jacques Pienaar7b829702018-07-03 13:24:09 -07002236void mlir::defaultErrorReporter(const llvm::SMDiagnostic &error) {
2237 const auto &sourceMgr = *error.getSourceMgr();
2238 sourceMgr.PrintMessage(error.getLoc(), error.getKind(), error.getMessage());
2239}
2240
Chris Lattnere79379a2018-06-22 10:39:19 -07002241/// This parses the file specified by the indicated SourceMgr and returns an
2242/// MLIR module if it was valid. If not, it emits diagnostics and returns null.
Jacques Pienaar9c411be2018-06-24 19:17:35 -07002243Module *mlir::parseSourceFile(llvm::SourceMgr &sourceMgr, MLIRContext *context,
Jacques Pienaar7b829702018-07-03 13:24:09 -07002244 SMDiagnosticHandlerTy errorReporter) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002245 // This is the result module we are parsing into.
2246 std::unique_ptr<Module> module(new Module(context));
2247
2248 ParserState state(sourceMgr, module.get(),
Jacques Pienaar0bffd862018-07-11 13:26:23 -07002249 errorReporter ? errorReporter : defaultErrorReporter);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002250 if (ModuleParser(state).parseModule())
2251 return nullptr;
Chris Lattner21e67f62018-07-06 10:46:19 -07002252
2253 // Make sure the parse module has no other structural problems detected by the
2254 // verifier.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002255 module->verify();
2256 return module.release();
Chris Lattnere79379a2018-06-22 10:39:19 -07002257}