blob: 626b92f32d7cc4dcef370dcdcb34e587ba3f52d1 [file] [log] [blame]
Chris Lattnere79379a2018-06-22 10:39:19 -07001//===- Parser.cpp - MLIR Parser Implementation ----------------------------===//
2//
3// Copyright 2019 The MLIR Authors.
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16// =============================================================================
17//
18// This file implements the parser for the MLIR textual form.
19//
20//===----------------------------------------------------------------------===//
21
22#include "mlir/Parser.h"
23#include "Lexer.h"
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -070024#include "mlir/IR/AffineExpr.h"
MLIR Teamf85a6262018-06-27 11:03:08 -070025#include "mlir/IR/AffineMap.h"
Chris Lattner7121b802018-07-04 20:45:39 -070026#include "mlir/IR/Attributes.h"
Chris Lattner158e0a3e2018-07-08 20:51:38 -070027#include "mlir/IR/Builders.h"
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -070028#include "mlir/IR/MLFunction.h"
Chris Lattner21e67f62018-07-06 10:46:19 -070029#include "mlir/IR/Module.h"
30#include "mlir/IR/OperationSet.h"
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -070031#include "mlir/IR/Statements.h"
Chris Lattnerf7e22732018-06-22 22:03:48 -070032#include "mlir/IR/Types.h"
Chris Lattnere79379a2018-06-22 10:39:19 -070033#include "llvm/Support/SourceMgr.h"
34using namespace mlir;
35using llvm::SourceMgr;
Chris Lattner4c95a502018-06-23 16:03:42 -070036using llvm::SMLoc;
Chris Lattnere79379a2018-06-22 10:39:19 -070037
Chris Lattnerf7e22732018-06-22 22:03:48 -070038/// Simple enum to make code read better in cases that would otherwise return a
39/// bool value. Failure is "true" in a boolean context.
Chris Lattnere79379a2018-06-22 10:39:19 -070040enum ParseResult {
41 ParseSuccess,
42 ParseFailure
43};
44
Chris Lattner48af7d12018-07-09 19:05:38 -070045namespace {
46class Parser;
47
48/// This class refers to all of the state maintained globally by the parser,
49/// such as the current lexer position etc. The Parser base class provides
50/// methods to access this.
51class ParserState {
Chris Lattnered65a732018-06-28 20:45:33 -070052public:
Chris Lattner2e595eb2018-07-10 10:08:27 -070053 ParserState(llvm::SourceMgr &sourceMgr, Module *module,
Chris Lattner48af7d12018-07-09 19:05:38 -070054 SMDiagnosticHandlerTy errorReporter)
Chris Lattner2e595eb2018-07-10 10:08:27 -070055 : context(module->getContext()), module(module),
56 lex(sourceMgr, errorReporter), curToken(lex.lexToken()),
Jacques Pienaard4c784e2018-07-11 00:07:36 -070057 errorReporter(errorReporter) {}
Chris Lattner2e595eb2018-07-10 10:08:27 -070058
59 // A map from affine map identifier to AffineMap.
60 llvm::StringMap<AffineMap *> affineMapDefinitions;
Chris Lattnere79379a2018-06-22 10:39:19 -070061
Chris Lattnere79379a2018-06-22 10:39:19 -070062private:
Chris Lattner48af7d12018-07-09 19:05:38 -070063 ParserState(const ParserState &) = delete;
64 void operator=(const ParserState &) = delete;
65
66 friend class Parser;
67
68 // The context we're parsing into.
Chris Lattner2e595eb2018-07-10 10:08:27 -070069 MLIRContext *const context;
70
71 // This is the module we are parsing into.
72 Module *const module;
Chris Lattnerf7e22732018-06-22 22:03:48 -070073
74 // The lexer for the source file we're parsing.
Chris Lattnere79379a2018-06-22 10:39:19 -070075 Lexer lex;
76
77 // This is the next token that hasn't been consumed yet.
78 Token curToken;
79
Jacques Pienaar9c411be2018-06-24 19:17:35 -070080 // The diagnostic error reporter.
Chris Lattner2e595eb2018-07-10 10:08:27 -070081 SMDiagnosticHandlerTy const errorReporter;
Chris Lattner48af7d12018-07-09 19:05:38 -070082};
83} // end anonymous namespace
MLIR Teamf85a6262018-06-27 11:03:08 -070084
Chris Lattner48af7d12018-07-09 19:05:38 -070085namespace {
86
87/// This class implement support for parsing global entities like types and
88/// shared entities like SSA names. It is intended to be subclassed by
89/// specialized subparsers that include state, e.g. when a local symbol table.
90class Parser {
91public:
Chris Lattner2e595eb2018-07-10 10:08:27 -070092 Builder builder;
Chris Lattner48af7d12018-07-09 19:05:38 -070093
Chris Lattner2e595eb2018-07-10 10:08:27 -070094 Parser(ParserState &state) : builder(state.context), state(state) {}
95
96 // Helper methods to get stuff from the parser-global state.
97 ParserState &getState() const { return state; }
Chris Lattner48af7d12018-07-09 19:05:38 -070098 MLIRContext *getContext() const { return state.context; }
Chris Lattner2e595eb2018-07-10 10:08:27 -070099 Module *getModule() { return state.module; }
Chris Lattner48af7d12018-07-09 19:05:38 -0700100
101 /// Return the current token the parser is inspecting.
102 const Token &getToken() const { return state.curToken; }
103 StringRef getTokenSpelling() const { return state.curToken.getSpelling(); }
Chris Lattnere79379a2018-06-22 10:39:19 -0700104
105 /// Emit an error and return failure.
Chris Lattner4c95a502018-06-23 16:03:42 -0700106 ParseResult emitError(const Twine &message) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700107 return emitError(state.curToken.getLoc(), message);
Chris Lattner4c95a502018-06-23 16:03:42 -0700108 }
109 ParseResult emitError(SMLoc loc, const Twine &message);
Chris Lattnere79379a2018-06-22 10:39:19 -0700110
111 /// Advance the current lexer onto the next token.
112 void consumeToken() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700113 assert(state.curToken.isNot(Token::eof, Token::error) &&
Chris Lattnere79379a2018-06-22 10:39:19 -0700114 "shouldn't advance past EOF or errors");
Chris Lattner48af7d12018-07-09 19:05:38 -0700115 state.curToken = state.lex.lexToken();
Chris Lattnere79379a2018-06-22 10:39:19 -0700116 }
117
118 /// Advance the current lexer onto the next token, asserting what the expected
119 /// current token is. This is preferred to the above method because it leads
120 /// to more self-documenting code with better checking.
Chris Lattner8da0c282018-06-29 11:15:56 -0700121 void consumeToken(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700122 assert(state.curToken.is(kind) && "consumed an unexpected token");
Chris Lattnere79379a2018-06-22 10:39:19 -0700123 consumeToken();
124 }
125
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700126 /// If the current token has the specified kind, consume it and return true.
127 /// If not, return false.
Chris Lattner8da0c282018-06-29 11:15:56 -0700128 bool consumeIf(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700129 if (state.curToken.isNot(kind))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700130 return false;
131 consumeToken(kind);
132 return true;
133 }
134
MLIR Team718c82f2018-07-16 09:45:22 -0700135 ParseResult parseCommaSeparatedList(
136 Token::Kind rightToken,
137 const std::function<ParseResult()> &parseElement,
138 bool allowEmptyList = true);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700139
Chris Lattnerf7e22732018-06-22 22:03:48 -0700140 // We have two forms of parsing methods - those that return a non-null
141 // pointer on success, and those that return a ParseResult to indicate whether
142 // they returned a failure. The second class fills in by-reference arguments
143 // as the results of their action.
144
Chris Lattnere79379a2018-06-22 10:39:19 -0700145 // Type parsing.
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700146 Type *parsePrimitiveType();
Chris Lattnerf7e22732018-06-22 22:03:48 -0700147 Type *parseElementType();
148 VectorType *parseVectorType();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700149 ParseResult parseDimensionListRanked(SmallVectorImpl<int> &dimensions);
Chris Lattnerf7e22732018-06-22 22:03:48 -0700150 Type *parseTensorType();
151 Type *parseMemRefType();
152 Type *parseFunctionType();
153 Type *parseType();
154 ParseResult parseTypeList(SmallVectorImpl<Type*> &elements);
Chris Lattnere79379a2018-06-22 10:39:19 -0700155
Chris Lattner7121b802018-07-04 20:45:39 -0700156 // Attribute parsing.
157 Attribute *parseAttribute();
158 ParseResult parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes);
159
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700160 // Polyhedral structures.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700161 AffineMap *parseAffineMapInline();
MLIR Team718c82f2018-07-16 09:45:22 -0700162 AffineMap *parseAffineMapReference();
MLIR Teamf85a6262018-06-27 11:03:08 -0700163
Chris Lattner78276e32018-07-07 15:48:26 -0700164 // SSA
165 ParseResult parseSSAUse();
166 ParseResult parseOptionalSSAUseList(Token::Kind endToken);
167 ParseResult parseSSAUseAndType();
168 ParseResult parseOptionalSSAUseAndTypeList(Token::Kind endToken);
169
Chris Lattner48af7d12018-07-09 19:05:38 -0700170private:
171 // The Parser is subclassed and reinstantiated. Do not add additional
172 // non-trivial state here, add it to the ParserState class.
173 ParserState &state;
Chris Lattnere79379a2018-06-22 10:39:19 -0700174};
175} // end anonymous namespace
176
177//===----------------------------------------------------------------------===//
178// Helper methods.
179//===----------------------------------------------------------------------===//
180
Chris Lattner4c95a502018-06-23 16:03:42 -0700181ParseResult Parser::emitError(SMLoc loc, const Twine &message) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700182 // If we hit a parse error in response to a lexer error, then the lexer
Jacques Pienaar9c411be2018-06-24 19:17:35 -0700183 // already reported the error.
Chris Lattner48af7d12018-07-09 19:05:38 -0700184 if (getToken().is(Token::error))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700185 return ParseFailure;
186
Chris Lattner48af7d12018-07-09 19:05:38 -0700187 auto &sourceMgr = state.lex.getSourceMgr();
188 state.errorReporter(sourceMgr.GetMessage(loc, SourceMgr::DK_Error, message));
Chris Lattnere79379a2018-06-22 10:39:19 -0700189 return ParseFailure;
190}
191
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700192/// Parse a comma-separated list of elements, terminated with an arbitrary
193/// token. This allows empty lists if allowEmptyList is true.
194///
195/// abstract-list ::= rightToken // if allowEmptyList == true
196/// abstract-list ::= element (',' element)* rightToken
197///
198ParseResult Parser::
Chris Lattner8da0c282018-06-29 11:15:56 -0700199parseCommaSeparatedList(Token::Kind rightToken,
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700200 const std::function<ParseResult()> &parseElement,
201 bool allowEmptyList) {
202 // Handle the empty case.
Chris Lattner48af7d12018-07-09 19:05:38 -0700203 if (getToken().is(rightToken)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700204 if (!allowEmptyList)
205 return emitError("expected list element");
206 consumeToken(rightToken);
207 return ParseSuccess;
208 }
209
210 // Non-empty case starts with an element.
211 if (parseElement())
212 return ParseFailure;
213
214 // Otherwise we have a list of comma separated elements.
215 while (consumeIf(Token::comma)) {
216 if (parseElement())
217 return ParseFailure;
218 }
219
220 // Consume the end character.
221 if (!consumeIf(rightToken))
Chris Lattner8da0c282018-06-29 11:15:56 -0700222 return emitError("expected ',' or '" + Token::getTokenSpelling(rightToken) +
223 "'");
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700224
225 return ParseSuccess;
226}
Chris Lattnere79379a2018-06-22 10:39:19 -0700227
228//===----------------------------------------------------------------------===//
229// Type Parsing
230//===----------------------------------------------------------------------===//
231
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700232/// Parse the low-level fixed dtypes in the system.
233///
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700234/// primitive-type ::= `f16` | `bf16` | `f32` | `f64`
235/// primitive-type ::= integer-type
236/// primitive-type ::= `affineint`
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700237///
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700238Type *Parser::parsePrimitiveType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700239 switch (getToken().getKind()) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700240 default:
241 return (emitError("expected type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700242 case Token::kw_bf16:
243 consumeToken(Token::kw_bf16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700244 return builder.getBF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700245 case Token::kw_f16:
246 consumeToken(Token::kw_f16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700247 return builder.getF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700248 case Token::kw_f32:
249 consumeToken(Token::kw_f32);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700250 return builder.getF32Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700251 case Token::kw_f64:
252 consumeToken(Token::kw_f64);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700253 return builder.getF64Type();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700254 case Token::kw_affineint:
255 consumeToken(Token::kw_affineint);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700256 return builder.getAffineIntType();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700257 case Token::inttype: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700258 auto width = getToken().getIntTypeBitwidth();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700259 if (!width.hasValue())
260 return (emitError("invalid integer width"), nullptr);
261 consumeToken(Token::inttype);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700262 return builder.getIntegerType(width.getValue());
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700263 }
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700264 }
265}
266
267/// Parse the element type of a tensor or memref type.
268///
269/// element-type ::= primitive-type | vector-type
270///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700271Type *Parser::parseElementType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700272 if (getToken().is(Token::kw_vector))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700273 return parseVectorType();
274
275 return parsePrimitiveType();
276}
277
278/// Parse a vector type.
279///
280/// vector-type ::= `vector` `<` const-dimension-list primitive-type `>`
281/// const-dimension-list ::= (integer-literal `x`)+
282///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700283VectorType *Parser::parseVectorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700284 consumeToken(Token::kw_vector);
285
286 if (!consumeIf(Token::less))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700287 return (emitError("expected '<' in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700288
Chris Lattner48af7d12018-07-09 19:05:38 -0700289 if (getToken().isNot(Token::integer))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700290 return (emitError("expected dimension size in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700291
292 SmallVector<unsigned, 4> dimensions;
Chris Lattner48af7d12018-07-09 19:05:38 -0700293 while (getToken().is(Token::integer)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700294 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700295 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700296 if (!dimension.hasValue())
Chris Lattnerf7e22732018-06-22 22:03:48 -0700297 return (emitError("invalid dimension in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700298 dimensions.push_back(dimension.getValue());
299
300 consumeToken(Token::integer);
301
302 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700303 if (getToken().isNot(Token::bare_identifier) ||
304 getTokenSpelling()[0] != 'x')
Chris Lattnerf7e22732018-06-22 22:03:48 -0700305 return (emitError("expected 'x' in vector dimension list"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700306
307 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700308 if (getTokenSpelling().size() != 1)
309 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700310
311 // Consume the 'x'.
312 consumeToken(Token::bare_identifier);
313 }
314
315 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700316 auto *elementType = parsePrimitiveType();
317 if (!elementType)
318 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700319
320 if (!consumeIf(Token::greater))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700321 return (emitError("expected '>' in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700322
Chris Lattnerf7e22732018-06-22 22:03:48 -0700323 return VectorType::get(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700324}
325
326/// Parse a dimension list of a tensor or memref type. This populates the
327/// dimension list, returning -1 for the '?' dimensions.
328///
329/// dimension-list-ranked ::= (dimension `x`)*
330/// dimension ::= `?` | integer-literal
331///
332ParseResult Parser::parseDimensionListRanked(SmallVectorImpl<int> &dimensions) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700333 while (getToken().isAny(Token::integer, Token::question)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700334 if (consumeIf(Token::question)) {
335 dimensions.push_back(-1);
336 } else {
337 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700338 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700339 if (!dimension.hasValue() || (int)dimension.getValue() < 0)
340 return emitError("invalid dimension");
341 dimensions.push_back((int)dimension.getValue());
342 consumeToken(Token::integer);
343 }
344
345 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700346 if (getToken().isNot(Token::bare_identifier) ||
347 getTokenSpelling()[0] != 'x')
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700348 return emitError("expected 'x' in dimension list");
349
350 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700351 if (getTokenSpelling().size() != 1)
352 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700353
354 // Consume the 'x'.
355 consumeToken(Token::bare_identifier);
356 }
357
358 return ParseSuccess;
359}
360
361/// Parse a tensor type.
362///
363/// tensor-type ::= `tensor` `<` dimension-list element-type `>`
364/// dimension-list ::= dimension-list-ranked | `??`
365///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700366Type *Parser::parseTensorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700367 consumeToken(Token::kw_tensor);
368
369 if (!consumeIf(Token::less))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700370 return (emitError("expected '<' in tensor type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700371
372 bool isUnranked;
373 SmallVector<int, 4> dimensions;
374
375 if (consumeIf(Token::questionquestion)) {
376 isUnranked = true;
377 } else {
378 isUnranked = false;
379 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700380 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700381 }
382
383 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700384 auto elementType = parseElementType();
385 if (!elementType)
386 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700387
388 if (!consumeIf(Token::greater))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700389 return (emitError("expected '>' in tensor type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700390
MLIR Team355ec862018-06-23 18:09:09 -0700391 if (isUnranked)
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700392 return builder.getTensorType(elementType);
393 return builder.getTensorType(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700394}
395
396/// Parse a memref type.
397///
398/// memref-type ::= `memref` `<` dimension-list-ranked element-type
399/// (`,` semi-affine-map-composition)? (`,` memory-space)? `>`
400///
401/// semi-affine-map-composition ::= (semi-affine-map `,` )* semi-affine-map
402/// memory-space ::= integer-literal /* | TODO: address-space-id */
403///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700404Type *Parser::parseMemRefType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700405 consumeToken(Token::kw_memref);
406
407 if (!consumeIf(Token::less))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700408 return (emitError("expected '<' in memref type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700409
410 SmallVector<int, 4> dimensions;
411 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700412 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700413
414 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700415 auto elementType = parseElementType();
416 if (!elementType)
417 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700418
MLIR Team718c82f2018-07-16 09:45:22 -0700419 if (!consumeIf(Token::comma))
420 return (emitError("expected ',' in memref type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700421
MLIR Team718c82f2018-07-16 09:45:22 -0700422 // Parse semi-affine-map-composition.
423 SmallVector<AffineMap*, 2> affineMapComposition;
424 unsigned memorySpace;
425 bool parsedMemorySpace = false;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700426
MLIR Team718c82f2018-07-16 09:45:22 -0700427 auto parseElt = [&]() -> ParseResult {
428 if (getToken().is(Token::integer)) {
429 // Parse memory space.
430 if (parsedMemorySpace)
431 return emitError("multiple memory spaces specified in memref type");
432 auto v = getToken().getUnsignedIntegerValue();
433 if (!v.hasValue())
434 return emitError("invalid memory space in memref type");
435 memorySpace = v.getValue();
436 consumeToken(Token::integer);
437 parsedMemorySpace = true;
438 } else {
439 // Parse affine map.
440 if (parsedMemorySpace)
441 return emitError("affine map after memory space in memref type");
442 auto* affineMap = parseAffineMapReference();
443 if (affineMap == nullptr)
444 return ParseFailure;
445 affineMapComposition.push_back(affineMap);
446 }
447 return ParseSuccess;
448 };
449
450 // Parse comma separated list of affine maps, followed by memory space.
451 if (parseCommaSeparatedList(Token::greater, parseElt,
452 /*allowEmptyList=*/false)) {
453 return nullptr;
454 }
455 // Check that MemRef type specifies at least one affine map in composition.
456 if (affineMapComposition.empty())
457 return (emitError("expected semi-affine-map in memref type"), nullptr);
458 if (!parsedMemorySpace)
459 return (emitError("expected memory space in memref type"), nullptr);
460
461 return MemRefType::get(dimensions, elementType, affineMapComposition,
462 memorySpace);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700463}
464
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700465/// Parse a function type.
466///
467/// function-type ::= type-list-parens `->` type-list
468///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700469Type *Parser::parseFunctionType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700470 assert(getToken().is(Token::l_paren));
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700471
Chris Lattnerf7e22732018-06-22 22:03:48 -0700472 SmallVector<Type*, 4> arguments;
473 if (parseTypeList(arguments))
474 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700475
476 if (!consumeIf(Token::arrow))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700477 return (emitError("expected '->' in function type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700478
Chris Lattnerf7e22732018-06-22 22:03:48 -0700479 SmallVector<Type*, 4> results;
480 if (parseTypeList(results))
481 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700482
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700483 return builder.getFunctionType(arguments, results);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700484}
485
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700486/// Parse an arbitrary type.
487///
488/// type ::= primitive-type
489/// | vector-type
490/// | tensor-type
491/// | memref-type
492/// | function-type
493/// element-type ::= primitive-type | vector-type
494///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700495Type *Parser::parseType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700496 switch (getToken().getKind()) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700497 case Token::kw_memref: return parseMemRefType();
498 case Token::kw_tensor: return parseTensorType();
499 case Token::kw_vector: return parseVectorType();
500 case Token::l_paren: return parseFunctionType();
501 default:
502 return parsePrimitiveType();
503 }
504}
505
506/// Parse a "type list", which is a singular type, or a parenthesized list of
507/// types.
508///
509/// type-list ::= type-list-parens | type
510/// type-list-parens ::= `(` `)`
511/// | `(` type (`,` type)* `)`
512///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700513ParseResult Parser::parseTypeList(SmallVectorImpl<Type*> &elements) {
514 auto parseElt = [&]() -> ParseResult {
515 auto elt = parseType();
516 elements.push_back(elt);
517 return elt ? ParseSuccess : ParseFailure;
518 };
519
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700520 // If there is no parens, then it must be a singular type.
521 if (!consumeIf(Token::l_paren))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700522 return parseElt();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700523
Chris Lattnerf7e22732018-06-22 22:03:48 -0700524 if (parseCommaSeparatedList(Token::r_paren, parseElt))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700525 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700526
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700527 return ParseSuccess;
528}
529
Chris Lattner4c95a502018-06-23 16:03:42 -0700530//===----------------------------------------------------------------------===//
Chris Lattner7121b802018-07-04 20:45:39 -0700531// Attribute parsing.
532//===----------------------------------------------------------------------===//
533
534
535/// Attribute parsing.
536///
537/// attribute-value ::= bool-literal
538/// | integer-literal
539/// | float-literal
540/// | string-literal
541/// | `[` (attribute-value (`,` attribute-value)*)? `]`
542///
543Attribute *Parser::parseAttribute() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700544 switch (getToken().getKind()) {
Chris Lattner7121b802018-07-04 20:45:39 -0700545 case Token::kw_true:
546 consumeToken(Token::kw_true);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700547 return builder.getBoolAttr(true);
Chris Lattner7121b802018-07-04 20:45:39 -0700548 case Token::kw_false:
549 consumeToken(Token::kw_false);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700550 return builder.getBoolAttr(false);
Chris Lattner7121b802018-07-04 20:45:39 -0700551
552 case Token::integer: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700553 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700554 if (!val.hasValue() || (int64_t)val.getValue() < 0)
555 return (emitError("integer too large for attribute"), nullptr);
556 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700557 return builder.getIntegerAttr((int64_t)val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700558 }
559
560 case Token::minus: {
561 consumeToken(Token::minus);
Chris Lattner48af7d12018-07-09 19:05:38 -0700562 if (getToken().is(Token::integer)) {
563 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700564 if (!val.hasValue() || (int64_t)-val.getValue() >= 0)
565 return (emitError("integer too large for attribute"), nullptr);
566 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700567 return builder.getIntegerAttr((int64_t)-val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700568 }
569
570 return (emitError("expected constant integer or floating point value"),
571 nullptr);
572 }
573
574 case Token::string: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700575 auto val = getToken().getStringValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700576 consumeToken(Token::string);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700577 return builder.getStringAttr(val);
Chris Lattner7121b802018-07-04 20:45:39 -0700578 }
579
580 case Token::l_bracket: {
581 consumeToken(Token::l_bracket);
582 SmallVector<Attribute*, 4> elements;
583
584 auto parseElt = [&]() -> ParseResult {
585 elements.push_back(parseAttribute());
586 return elements.back() ? ParseSuccess : ParseFailure;
587 };
588
589 if (parseCommaSeparatedList(Token::r_bracket, parseElt))
590 return nullptr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700591 return builder.getArrayAttr(elements);
Chris Lattner7121b802018-07-04 20:45:39 -0700592 }
593 default:
594 // TODO: Handle floating point.
595 return (emitError("expected constant attribute value"), nullptr);
596 }
597}
598
Chris Lattner7121b802018-07-04 20:45:39 -0700599/// Attribute dictionary.
600///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700601/// attribute-dict ::= `{` `}`
602/// | `{` attribute-entry (`,` attribute-entry)* `}`
603/// attribute-entry ::= bare-id `:` attribute-value
Chris Lattner7121b802018-07-04 20:45:39 -0700604///
605ParseResult Parser::parseAttributeDict(
606 SmallVectorImpl<NamedAttribute> &attributes) {
607 consumeToken(Token::l_brace);
608
609 auto parseElt = [&]() -> ParseResult {
610 // We allow keywords as attribute names.
Chris Lattner48af7d12018-07-09 19:05:38 -0700611 if (getToken().isNot(Token::bare_identifier, Token::inttype) &&
612 !getToken().isKeyword())
Chris Lattner7121b802018-07-04 20:45:39 -0700613 return emitError("expected attribute name");
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700614 auto nameId = builder.getIdentifier(getTokenSpelling());
Chris Lattner7121b802018-07-04 20:45:39 -0700615 consumeToken();
616
617 if (!consumeIf(Token::colon))
618 return emitError("expected ':' in attribute list");
619
620 auto attr = parseAttribute();
621 if (!attr) return ParseFailure;
622
623 attributes.push_back({nameId, attr});
624 return ParseSuccess;
625 };
626
627 if (parseCommaSeparatedList(Token::r_brace, parseElt))
628 return ParseFailure;
629
630 return ParseSuccess;
631}
632
633//===----------------------------------------------------------------------===//
MLIR Teamf85a6262018-06-27 11:03:08 -0700634// Polyhedral structures.
635//===----------------------------------------------------------------------===//
636
Chris Lattner2e595eb2018-07-10 10:08:27 -0700637/// Lower precedence ops (all at the same precedence level). LNoOp is false in
638/// the boolean sense.
639enum AffineLowPrecOp {
640 /// Null value.
641 LNoOp,
642 Add,
643 Sub
644};
MLIR Teamf85a6262018-06-27 11:03:08 -0700645
Chris Lattner2e595eb2018-07-10 10:08:27 -0700646/// Higher precedence ops - all at the same precedence level. HNoOp is false in
647/// the boolean sense.
648enum AffineHighPrecOp {
649 /// Null value.
650 HNoOp,
651 Mul,
652 FloorDiv,
653 CeilDiv,
654 Mod
655};
Chris Lattner7121b802018-07-04 20:45:39 -0700656
Chris Lattner2e595eb2018-07-10 10:08:27 -0700657namespace {
658/// This is a specialized parser for AffineMap's, maintaining the state
659/// transient to their bodies.
660class AffineMapParser : public Parser {
661public:
662 explicit AffineMapParser(ParserState &state) : Parser(state) {}
Chris Lattner7121b802018-07-04 20:45:39 -0700663
Chris Lattner2e595eb2018-07-10 10:08:27 -0700664 AffineMap *parseAffineMapInline();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700665
Chris Lattner2e595eb2018-07-10 10:08:27 -0700666private:
667 unsigned getNumDims() const { return dims.size(); }
668 unsigned getNumSymbols() const { return symbols.size(); }
MLIR Teamf85a6262018-06-27 11:03:08 -0700669
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700670 /// Returns true if the only identifiers the parser accepts in affine
671 /// expressions are symbolic identifiers.
672 bool isPureSymbolic() const { return pureSymbolic; }
673 void setSymbolicParsing(bool val) { pureSymbolic = val; }
674
Chris Lattner2e595eb2018-07-10 10:08:27 -0700675 // Binary affine op parsing.
676 AffineLowPrecOp consumeIfLowPrecOp();
677 AffineHighPrecOp consumeIfHighPrecOp();
MLIR Teamf85a6262018-06-27 11:03:08 -0700678
Chris Lattner2e595eb2018-07-10 10:08:27 -0700679 // Identifier lists for polyhedral structures.
680 ParseResult parseDimIdList();
681 ParseResult parseSymbolIdList();
682 ParseResult parseDimOrSymbolId(bool isDim);
683
684 AffineExpr *parseAffineExpr();
685 AffineExpr *parseParentheticalExpr();
686 AffineExpr *parseNegateExpression(AffineExpr *lhs);
687 AffineExpr *parseIntegerExpr();
688 AffineExpr *parseBareIdExpr();
689
690 AffineExpr *getBinaryAffineOpExpr(AffineHighPrecOp op, AffineExpr *lhs,
691 AffineExpr *rhs);
692 AffineExpr *getBinaryAffineOpExpr(AffineLowPrecOp op, AffineExpr *lhs,
693 AffineExpr *rhs);
694 AffineExpr *parseAffineOperandExpr(AffineExpr *lhs);
695 AffineExpr *parseAffineLowPrecOpExpr(AffineExpr *llhs,
696 AffineLowPrecOp llhsOp);
697 AffineExpr *parseAffineHighPrecOpExpr(AffineExpr *llhs,
698 AffineHighPrecOp llhsOp);
699
700private:
701 // TODO(bondhugula): could just use an vector/ArrayRef and scan the numbers.
702 llvm::StringMap<unsigned> dims;
703 llvm::StringMap<unsigned> symbols;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700704 /// True if the parser should allow only symbolic identifiers in affine
705 /// expressions.
706 bool pureSymbolic = false;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700707};
708} // end anonymous namespace
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700709
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700710/// Create an affine binary high precedence op expression (mul's, div's, mod)
Chris Lattner2e595eb2018-07-10 10:08:27 -0700711AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineHighPrecOp op,
712 AffineExpr *lhs,
713 AffineExpr *rhs) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700714 // TODO: make the error location info accurate.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700715 switch (op) {
716 case Mul:
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700717 if (!lhs->isSymbolic() && !rhs->isSymbolic()) {
718 emitError("non-affine expression: at least one of the multiply "
719 "operands has to be either a constant or symbolic");
720 return nullptr;
721 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700722 return builder.getMulExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700723 case FloorDiv:
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700724 if (!rhs->isSymbolic()) {
725 emitError("non-affine expression: right operand of floordiv "
726 "has to be either a constant or symbolic");
727 return nullptr;
728 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700729 return builder.getFloorDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700730 case CeilDiv:
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700731 if (!rhs->isSymbolic()) {
732 emitError("non-affine expression: right operand of ceildiv "
733 "has to be either a constant or symbolic");
734 return nullptr;
735 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700736 return builder.getCeilDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700737 case Mod:
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700738 if (!rhs->isSymbolic()) {
739 emitError("non-affine expression: right operand of mod "
740 "has to be either a constant or symbolic");
741 return nullptr;
742 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700743 return builder.getModExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700744 case HNoOp:
745 llvm_unreachable("can't create affine expression for null high prec op");
746 return nullptr;
747 }
748}
749
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700750/// Create an affine binary low precedence op expression (add, sub).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700751AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineLowPrecOp op,
752 AffineExpr *lhs,
753 AffineExpr *rhs) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700754 switch (op) {
755 case AffineLowPrecOp::Add:
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700756 return builder.getAddExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700757 case AffineLowPrecOp::Sub:
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700758 return builder.getSubExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700759 case AffineLowPrecOp::LNoOp:
760 llvm_unreachable("can't create affine expression for null low prec op");
761 return nullptr;
762 }
763}
764
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700765/// Consume this token if it is a lower precedence affine op (there are only two
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700766/// precedence levels).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700767AffineLowPrecOp AffineMapParser::consumeIfLowPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700768 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700769 case Token::plus:
770 consumeToken(Token::plus);
771 return AffineLowPrecOp::Add;
772 case Token::minus:
773 consumeToken(Token::minus);
774 return AffineLowPrecOp::Sub;
775 default:
776 return AffineLowPrecOp::LNoOp;
777 }
778}
779
780/// Consume this token if it is a higher precedence affine op (there are only
781/// two precedence levels)
Chris Lattner2e595eb2018-07-10 10:08:27 -0700782AffineHighPrecOp AffineMapParser::consumeIfHighPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700783 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700784 case Token::star:
785 consumeToken(Token::star);
786 return Mul;
787 case Token::kw_floordiv:
788 consumeToken(Token::kw_floordiv);
789 return FloorDiv;
790 case Token::kw_ceildiv:
791 consumeToken(Token::kw_ceildiv);
792 return CeilDiv;
793 case Token::kw_mod:
794 consumeToken(Token::kw_mod);
795 return Mod;
796 default:
797 return HNoOp;
798 }
799}
800
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700801/// Parse a high precedence op expression list: mul, div, and mod are high
802/// precedence binary ops, i.e., parse a
803/// expr_1 op_1 expr_2 op_2 ... expr_n
804/// where op_1, op_2 are all a AffineHighPrecOp (mul, div, mod).
805/// All affine binary ops are left associative.
806/// Given llhs, returns (llhs llhsOp lhs) op rhs, or (lhs op rhs) if llhs is
807/// null. If no rhs can be found, returns (llhs llhsOp lhs) or lhs if llhs is
808/// null.
809AffineExpr *
Chris Lattner2e595eb2018-07-10 10:08:27 -0700810AffineMapParser::parseAffineHighPrecOpExpr(AffineExpr *llhs,
811 AffineHighPrecOp llhsOp) {
812 AffineExpr *lhs = parseAffineOperandExpr(llhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700813 if (!lhs)
814 return nullptr;
815
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700816 // Found an LHS. Parse the remaining expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700817 if (AffineHighPrecOp op = consumeIfHighPrecOp()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700818 if (llhs) {
819 AffineExpr *expr = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
820 if (!expr)
821 return nullptr;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700822 return parseAffineHighPrecOpExpr(expr, op);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700823 }
824 // No LLHS, get RHS
Chris Lattner2e595eb2018-07-10 10:08:27 -0700825 return parseAffineHighPrecOpExpr(lhs, op);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700826 }
827
828 // This is the last operand in this expression.
829 if (llhs)
830 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
831
832 // No llhs, 'lhs' itself is the expression.
833 return lhs;
834}
835
836/// Parse an affine expression inside parentheses.
837///
838/// affine-expr ::= `(` affine-expr `)`
Chris Lattner2e595eb2018-07-10 10:08:27 -0700839AffineExpr *AffineMapParser::parseParentheticalExpr() {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700840 if (!consumeIf(Token::l_paren))
841 return (emitError("expected '('"), nullptr);
Chris Lattner48af7d12018-07-09 19:05:38 -0700842 if (getToken().is(Token::r_paren))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700843 return (emitError("no expression inside parentheses"), nullptr);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700844 auto *expr = parseAffineExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700845 if (!expr)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700846 return nullptr;
847 if (!consumeIf(Token::r_paren))
848 return (emitError("expected ')'"), nullptr);
849 return expr;
850}
851
852/// Parse the negation expression.
853///
854/// affine-expr ::= `-` affine-expr
Chris Lattner2e595eb2018-07-10 10:08:27 -0700855AffineExpr *AffineMapParser::parseNegateExpression(AffineExpr *lhs) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700856 if (!consumeIf(Token::minus))
857 return (emitError("expected '-'"), nullptr);
858
Chris Lattner2e595eb2018-07-10 10:08:27 -0700859 AffineExpr *operand = parseAffineOperandExpr(lhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700860 // Since negation has the highest precedence of all ops (including high
861 // precedence ops) but lower than parentheses, we are only going to use
862 // parseAffineOperandExpr instead of parseAffineExpr here.
863 if (!operand)
864 // Extra error message although parseAffineOperandExpr would have
865 // complained. Leads to a better diagnostic.
866 return (emitError("missing operand of negation"), nullptr);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700867 auto *minusOne = builder.getConstantExpr(-1);
868 return builder.getMulExpr(minusOne, operand);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700869}
870
871/// Parse a bare id that may appear in an affine expression.
872///
873/// affine-expr ::= bare-id
Chris Lattner2e595eb2018-07-10 10:08:27 -0700874AffineExpr *AffineMapParser::parseBareIdExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700875 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700876 return (emitError("expected bare identifier"), nullptr);
877
Chris Lattner48af7d12018-07-09 19:05:38 -0700878 StringRef sRef = getTokenSpelling();
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700879 // dims, symbols are all pairwise distinct.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700880 if (dims.count(sRef)) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700881 if (isPureSymbolic())
882 return (emitError("identifier used is not a symbolic identifier"),
883 nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700884 consumeToken(Token::bare_identifier);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700885 return builder.getDimExpr(dims.lookup(sRef));
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700886 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700887
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700888 if (symbols.count(sRef)) {
889 consumeToken(Token::bare_identifier);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700890 return builder.getSymbolExpr(symbols.lookup(sRef));
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700891 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700892
893 return (emitError("use of undeclared identifier"), nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700894}
895
896/// Parse a positive integral constant appearing in an affine expression.
897///
898/// affine-expr ::= integer-literal
Chris Lattner2e595eb2018-07-10 10:08:27 -0700899AffineExpr *AffineMapParser::parseIntegerExpr() {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700900 // No need to handle negative numbers separately here. They are naturally
901 // handled via the unary negation operator, although (FIXME) MININT_64 still
902 // not correctly handled.
Chris Lattner48af7d12018-07-09 19:05:38 -0700903 if (getToken().isNot(Token::integer))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700904 return (emitError("expected integer"), nullptr);
905
Chris Lattner48af7d12018-07-09 19:05:38 -0700906 auto val = getToken().getUInt64IntegerValue();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700907 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
908 return (emitError("constant too large for affineint"), nullptr);
909 }
910 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700911 return builder.getConstantExpr((int64_t)val.getValue());
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700912}
913
914/// Parses an expression that can be a valid operand of an affine expression.
Uday Bondhugula76345202018-07-09 13:47:52 -0700915/// lhs: if non-null, lhs is an affine expression that is the lhs of a binary
916/// operator, the rhs of which is being parsed. This is used to determine
917/// whether an error should be emitted for a missing right operand.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700918// Eg: for an expression without parentheses (like i + j + k + l), each
919// of the four identifiers is an operand. For i + j*k + l, j*k is not an
920// operand expression, it's an op expression and will be parsed via
921// parseAffineHighPrecOpExpression(). However, for i + (j*k) + -l, (j*k) and -l
922// are valid operands that will be parsed by this function.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700923AffineExpr *AffineMapParser::parseAffineOperandExpr(AffineExpr *lhs) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700924 switch (getToken().getKind()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700925 case Token::bare_identifier:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700926 return parseBareIdExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700927 case Token::integer:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700928 return parseIntegerExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700929 case Token::l_paren:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700930 return parseParentheticalExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700931 case Token::minus:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700932 return parseNegateExpression(lhs);
Uday Bondhugula76345202018-07-09 13:47:52 -0700933 case Token::kw_ceildiv:
934 case Token::kw_floordiv:
935 case Token::kw_mod:
936 case Token::plus:
937 case Token::star:
938 if (lhs)
939 emitError("missing right operand of binary operator");
940 else
941 emitError("missing left operand of binary operator");
942 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700943 default:
944 if (lhs)
Uday Bondhugula76345202018-07-09 13:47:52 -0700945 emitError("missing right operand of binary operator");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700946 else
947 emitError("expected affine expression");
948 return nullptr;
949 }
950}
951
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700952/// Parse affine expressions that are bare-id's, integer constants,
953/// parenthetical affine expressions, and affine op expressions that are a
954/// composition of those.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700955///
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700956/// All binary op's associate from left to right.
957///
958/// {add, sub} have lower precedence than {mul, div, and mod}.
959///
Uday Bondhugula76345202018-07-09 13:47:52 -0700960/// Add, sub'are themselves at the same precedence level. Mul, floordiv,
961/// ceildiv, and mod are at the same higher precedence level. Negation has
962/// higher precedence than any binary op.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700963///
964/// llhs: the affine expression appearing on the left of the one being parsed.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700965/// This function will return ((llhs llhsOp lhs) op rhs) if llhs is non null,
966/// and lhs op rhs otherwise; if there is no rhs, llhs llhsOp lhs is returned if
967/// llhs is non-null; otherwise lhs is returned. This is to deal with left
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700968/// associativity.
969///
970/// Eg: when the expression is e1 + e2*e3 + e4, with e1 as llhs, this function
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700971/// will return the affine expr equivalent of (e1 + (e2*e3)) + e4, where (e2*e3)
972/// will be parsed using parseAffineHighPrecOpExpr().
Chris Lattner2e595eb2018-07-10 10:08:27 -0700973AffineExpr *AffineMapParser::parseAffineLowPrecOpExpr(AffineExpr *llhs,
974 AffineLowPrecOp llhsOp) {
Uday Bondhugula76345202018-07-09 13:47:52 -0700975 AffineExpr *lhs;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700976 if (!(lhs = parseAffineOperandExpr(llhs)))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700977 return nullptr;
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700978
979 // Found an LHS. Deal with the ops.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700980 if (AffineLowPrecOp lOp = consumeIfLowPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700981 if (llhs) {
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700982 AffineExpr *sum = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700983 return parseAffineLowPrecOpExpr(sum, lOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700984 }
985 // No LLHS, get RHS and form the expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700986 return parseAffineLowPrecOpExpr(lhs, lOp);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700987 }
Chris Lattner2e595eb2018-07-10 10:08:27 -0700988 if (AffineHighPrecOp hOp = consumeIfHighPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700989 // We have a higher precedence op here. Get the rhs operand for the llhs
990 // through parseAffineHighPrecOpExpr.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700991 AffineExpr *highRes = parseAffineHighPrecOpExpr(lhs, hOp);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700992 if (!highRes)
993 return nullptr;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700994
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700995 // If llhs is null, the product forms the first operand of the yet to be
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700996 // found expression. If non-null, the op to associate with llhs is llhsOp.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700997 AffineExpr *expr =
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700998 llhs ? getBinaryAffineOpExpr(llhsOp, llhs, highRes) : highRes;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700999
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001000 // Recurse for subsequent low prec op's after the affine high prec op
1001 // expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001002 if (AffineLowPrecOp nextOp = consumeIfLowPrecOp())
1003 return parseAffineLowPrecOpExpr(expr, nextOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001004 return expr;
1005 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001006 // Last operand in the expression list.
1007 if (llhs)
1008 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
1009 // No llhs, 'lhs' itself is the expression.
1010 return lhs;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001011}
1012
1013/// Parse an affine expression.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001014/// affine-expr ::= `(` affine-expr `)`
1015/// | `-` affine-expr
1016/// | affine-expr `+` affine-expr
1017/// | affine-expr `-` affine-expr
1018/// | affine-expr `*` affine-expr
1019/// | affine-expr `floordiv` affine-expr
1020/// | affine-expr `ceildiv` affine-expr
1021/// | affine-expr `mod` affine-expr
1022/// | bare-id
1023/// | integer-literal
1024///
1025/// Additional conditions are checked depending on the production. For eg., one
1026/// of the operands for `*` has to be either constant/symbolic; the second
1027/// operand for floordiv, ceildiv, and mod has to be a positive integer.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001028AffineExpr *AffineMapParser::parseAffineExpr() {
1029 return parseAffineLowPrecOpExpr(nullptr, AffineLowPrecOp::LNoOp);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001030}
1031
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001032/// Parse a dim or symbol from the lists appearing before the actual expressions
Chris Lattner2e595eb2018-07-10 10:08:27 -07001033/// of the affine map. Update our state to store the dimensional/symbolic
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001034/// identifier. 'dim': whether it's the dim list or symbol list that is being
1035/// parsed.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001036ParseResult AffineMapParser::parseDimOrSymbolId(bool isDim) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001037 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001038 return emitError("expected bare identifier");
Chris Lattner48af7d12018-07-09 19:05:38 -07001039 auto sRef = getTokenSpelling();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001040 consumeToken(Token::bare_identifier);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001041 if (dims.count(sRef))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001042 return emitError("dimensional identifier name reused");
Chris Lattner2e595eb2018-07-10 10:08:27 -07001043 if (symbols.count(sRef))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001044 return emitError("symbolic identifier name reused");
Chris Lattner2e595eb2018-07-10 10:08:27 -07001045 if (isDim)
1046 dims.insert({sRef, dims.size()});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001047 else
Chris Lattner2e595eb2018-07-10 10:08:27 -07001048 symbols.insert({sRef, symbols.size()});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001049 return ParseSuccess;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001050}
1051
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001052/// Parse the list of symbolic identifiers to an affine map.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001053ParseResult AffineMapParser::parseSymbolIdList() {
1054 if (!consumeIf(Token::l_bracket))
1055 return emitError("expected '['");
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001056
Chris Lattner2e595eb2018-07-10 10:08:27 -07001057 auto parseElt = [&]() -> ParseResult { return parseDimOrSymbolId(false); };
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001058 return parseCommaSeparatedList(Token::r_bracket, parseElt);
1059}
1060
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001061/// Parse the list of dimensional identifiers to an affine map.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001062ParseResult AffineMapParser::parseDimIdList() {
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001063 if (!consumeIf(Token::l_paren))
1064 return emitError("expected '(' at start of dimensional identifiers list");
1065
Chris Lattner2e595eb2018-07-10 10:08:27 -07001066 auto parseElt = [&]() -> ParseResult { return parseDimOrSymbolId(true); };
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001067 return parseCommaSeparatedList(Token::r_paren, parseElt);
1068}
1069
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001070/// Parse an affine map definition.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001071///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001072/// affine-map-inline ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
1073/// (`size` `(` dim-size (`,` dim-size)* `)`)?
1074/// dim-size ::= affine-expr | `min` `(` affine-expr ( `,` affine-expr)+ `)`
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001075///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001076/// multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner2e595eb2018-07-10 10:08:27 -07001077AffineMap *AffineMapParser::parseAffineMapInline() {
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001078 // List of dimensional identifiers.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001079 if (parseDimIdList())
Chris Lattner7121b802018-07-04 20:45:39 -07001080 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001081
1082 // Symbols are optional.
Chris Lattner48af7d12018-07-09 19:05:38 -07001083 if (getToken().is(Token::l_bracket)) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001084 if (parseSymbolIdList())
Chris Lattner7121b802018-07-04 20:45:39 -07001085 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001086 }
1087 if (!consumeIf(Token::arrow)) {
Chris Lattner7121b802018-07-04 20:45:39 -07001088 return (emitError("expected '->' or '['"), nullptr);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001089 }
1090 if (!consumeIf(Token::l_paren)) {
1091 emitError("expected '(' at start of affine map range");
Chris Lattner7121b802018-07-04 20:45:39 -07001092 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001093 }
1094
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001095 SmallVector<AffineExpr *, 4> exprs;
1096 auto parseElt = [&]() -> ParseResult {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001097 auto *elt = parseAffineExpr();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001098 ParseResult res = elt ? ParseSuccess : ParseFailure;
1099 exprs.push_back(elt);
1100 return res;
1101 };
1102
1103 // Parse a multi-dimensional affine expression (a comma-separated list of 1-d
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001104 // affine expressions); the list cannot be empty.
1105 // Grammar: multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
1106 if (parseCommaSeparatedList(Token::r_paren, parseElt, false))
Chris Lattner7121b802018-07-04 20:45:39 -07001107 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001108
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001109 // Parse optional range sizes.
Uday Bondhugula1e500b42018-07-12 18:04:04 -07001110 // range-sizes ::= (`size` `(` dim-size (`,` dim-size)* `)`)?
1111 // dim-size ::= affine-expr | `min` `(` affine-expr (`,` affine-expr)+ `)`
1112 // TODO(bondhugula): support for min of several affine expressions.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001113 // TODO: check if sizes are non-negative whenever they are constant.
1114 SmallVector<AffineExpr *, 4> rangeSizes;
1115 if (consumeIf(Token::kw_size)) {
1116 // Location of the l_paren token (if it exists) for error reporting later.
1117 auto loc = getToken().getLoc();
1118 if (!consumeIf(Token::l_paren))
1119 return (emitError("expected '(' at start of affine map range"), nullptr);
1120
1121 auto parseRangeSize = [&]() -> ParseResult {
1122 auto *elt = parseAffineExpr();
1123 ParseResult res = elt ? ParseSuccess : ParseFailure;
1124 rangeSizes.push_back(elt);
1125 return res;
1126 };
1127
1128 setSymbolicParsing(true);
1129 if (parseCommaSeparatedList(Token::r_paren, parseRangeSize, false))
1130 return nullptr;
1131 if (exprs.size() > rangeSizes.size())
1132 return (emitError(loc, "fewer range sizes than range expressions"),
1133 nullptr);
1134 if (exprs.size() < rangeSizes.size())
1135 return (emitError(loc, "more range sizes than range expressions"),
1136 nullptr);
1137 }
1138
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001139 // Parsed a valid affine map.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001140 return builder.getAffineMap(dims.size(), symbols.size(), exprs, rangeSizes);
MLIR Teamf85a6262018-06-27 11:03:08 -07001141}
1142
Chris Lattner2e595eb2018-07-10 10:08:27 -07001143AffineMap *Parser::parseAffineMapInline() {
1144 return AffineMapParser(state).parseAffineMapInline();
1145}
1146
MLIR Team718c82f2018-07-16 09:45:22 -07001147AffineMap *Parser::parseAffineMapReference() {
1148 if (getToken().is(Token::hash_identifier)) {
1149 // Parse affine map identifier and verify that it exists.
1150 StringRef affineMapId = getTokenSpelling().drop_front();
1151 if (getState().affineMapDefinitions.count(affineMapId) == 0)
1152 return (emitError("undefined affine map id '" + affineMapId + "'"),
1153 nullptr);
1154 consumeToken(Token::hash_identifier);
1155 return getState().affineMapDefinitions[affineMapId];
1156 }
1157 // Try to parse inline affine map.
1158 return parseAffineMapInline();
1159}
1160
MLIR Teamf85a6262018-06-27 11:03:08 -07001161//===----------------------------------------------------------------------===//
Chris Lattner78276e32018-07-07 15:48:26 -07001162// SSA
Chris Lattner4c95a502018-06-23 16:03:42 -07001163//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001164
Chris Lattner78276e32018-07-07 15:48:26 -07001165/// Parse a SSA operand for an instruction or statement.
1166///
1167/// ssa-use ::= ssa-id | ssa-constant
1168///
1169ParseResult Parser::parseSSAUse() {
Chris Lattner48af7d12018-07-09 19:05:38 -07001170 if (getToken().is(Token::percent_identifier)) {
1171 StringRef name = getTokenSpelling().drop_front();
Chris Lattner78276e32018-07-07 15:48:26 -07001172 consumeToken(Token::percent_identifier);
1173 // TODO: Return this use.
1174 (void)name;
1175 return ParseSuccess;
1176 }
1177
1178 // TODO: Parse SSA constants.
1179
1180 return emitError("expected SSA operand");
1181}
1182
1183/// Parse a (possibly empty) list of SSA operands.
1184///
1185/// ssa-use-list ::= ssa-use (`,` ssa-use)*
1186/// ssa-use-list-opt ::= ssa-use-list?
1187///
1188ParseResult Parser::parseOptionalSSAUseList(Token::Kind endToken) {
1189 // TODO: Build and return this.
1190 return parseCommaSeparatedList(
1191 endToken, [&]() -> ParseResult { return parseSSAUse(); });
1192}
1193
1194/// Parse an SSA use with an associated type.
1195///
1196/// ssa-use-and-type ::= ssa-use `:` type
1197ParseResult Parser::parseSSAUseAndType() {
1198 if (parseSSAUse())
1199 return ParseFailure;
1200
1201 if (!consumeIf(Token::colon))
1202 return emitError("expected ':' and type for SSA operand");
1203
1204 if (!parseType())
1205 return ParseFailure;
1206
1207 return ParseSuccess;
1208}
1209
1210/// Parse a (possibly empty) list of SSA operands with types.
1211///
1212/// ssa-use-and-type-list ::= ssa-use-and-type (`,` ssa-use-and-type)*
1213///
1214ParseResult Parser::parseOptionalSSAUseAndTypeList(Token::Kind endToken) {
1215 // TODO: Build and return this.
1216 return parseCommaSeparatedList(
1217 endToken, [&]() -> ParseResult { return parseSSAUseAndType(); });
1218}
1219
Chris Lattnere79379a2018-06-22 10:39:19 -07001220
Chris Lattner48af7d12018-07-09 19:05:38 -07001221//===----------------------------------------------------------------------===//
1222// CFG Functions
1223//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001224
Chris Lattner4c95a502018-06-23 16:03:42 -07001225namespace {
Chris Lattner48af7d12018-07-09 19:05:38 -07001226/// This is a specialized parser for CFGFunction's, maintaining the state
1227/// transient to their bodies.
1228class CFGFunctionParser : public Parser {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001229public:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001230 CFGFunctionParser(ParserState &state, CFGFunction *function)
1231 : Parser(state), function(function), builder(function) {}
1232
1233 ParseResult parseFunctionBody();
1234
1235private:
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001236 CFGFunction *function;
1237 llvm::StringMap<std::pair<BasicBlock*, SMLoc>> blocksByName;
Chris Lattner48af7d12018-07-09 19:05:38 -07001238
1239 /// This builder intentionally shadows the builder in the base class, with a
1240 /// more specific builder type.
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001241 CFGFuncBuilder builder;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001242
Chris Lattner4c95a502018-06-23 16:03:42 -07001243 /// Get the basic block with the specified name, creating it if it doesn't
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001244 /// already exist. The location specified is the point of use, which allows
1245 /// us to diagnose references to blocks that are not defined precisely.
1246 BasicBlock *getBlockNamed(StringRef name, SMLoc loc) {
1247 auto &blockAndLoc = blocksByName[name];
1248 if (!blockAndLoc.first) {
Chris Lattner3a467cc2018-07-01 20:28:00 -07001249 blockAndLoc.first = new BasicBlock();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001250 blockAndLoc.second = loc;
Chris Lattner4c95a502018-06-23 16:03:42 -07001251 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001252 return blockAndLoc.first;
Chris Lattner4c95a502018-06-23 16:03:42 -07001253 }
Chris Lattner48af7d12018-07-09 19:05:38 -07001254
Chris Lattner48af7d12018-07-09 19:05:38 -07001255 ParseResult parseBasicBlock();
1256 OperationInst *parseCFGOperation();
1257 TerminatorInst *parseTerminator();
Chris Lattner4c95a502018-06-23 16:03:42 -07001258};
1259} // end anonymous namespace
1260
Chris Lattner48af7d12018-07-09 19:05:38 -07001261ParseResult CFGFunctionParser::parseFunctionBody() {
1262 if (!consumeIf(Token::l_brace))
1263 return emitError("expected '{' in CFG function");
1264
1265 // Make sure we have at least one block.
1266 if (getToken().is(Token::r_brace))
1267 return emitError("CFG functions must have at least one basic block");
Chris Lattner4c95a502018-06-23 16:03:42 -07001268
1269 // Parse the list of blocks.
1270 while (!consumeIf(Token::r_brace))
Chris Lattner48af7d12018-07-09 19:05:38 -07001271 if (parseBasicBlock())
Chris Lattner4c95a502018-06-23 16:03:42 -07001272 return ParseFailure;
1273
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001274 // Verify that all referenced blocks were defined. Iteration over a
1275 // StringMap isn't determinstic, but this is good enough for our purposes.
Chris Lattner48af7d12018-07-09 19:05:38 -07001276 for (auto &elt : blocksByName) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001277 auto *bb = elt.second.first;
Chris Lattner3a467cc2018-07-01 20:28:00 -07001278 if (!bb->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001279 return emitError(elt.second.second,
1280 "reference to an undefined basic block '" +
1281 elt.first() + "'");
1282 }
1283
Chris Lattner48af7d12018-07-09 19:05:38 -07001284 getModule()->functionList.push_back(function);
Chris Lattner4c95a502018-06-23 16:03:42 -07001285 return ParseSuccess;
1286}
1287
1288/// Basic block declaration.
1289///
1290/// basic-block ::= bb-label instruction* terminator-stmt
1291/// bb-label ::= bb-id bb-arg-list? `:`
1292/// bb-id ::= bare-id
1293/// bb-arg-list ::= `(` ssa-id-and-type-list? `)`
1294///
Chris Lattner48af7d12018-07-09 19:05:38 -07001295ParseResult CFGFunctionParser::parseBasicBlock() {
1296 SMLoc nameLoc = getToken().getLoc();
1297 auto name = getTokenSpelling();
Chris Lattner4c95a502018-06-23 16:03:42 -07001298 if (!consumeIf(Token::bare_identifier))
1299 return emitError("expected basic block name");
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001300
Chris Lattner48af7d12018-07-09 19:05:38 -07001301 auto *block = getBlockNamed(name, nameLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001302
1303 // If this block has already been parsed, then this is a redefinition with the
1304 // same block name.
Chris Lattner3a467cc2018-07-01 20:28:00 -07001305 if (block->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001306 return emitError(nameLoc, "redefinition of block '" + name.str() + "'");
1307
Chris Lattner3a467cc2018-07-01 20:28:00 -07001308 // Add the block to the function.
Chris Lattner48af7d12018-07-09 19:05:38 -07001309 function->push_back(block);
Chris Lattner4c95a502018-06-23 16:03:42 -07001310
Chris Lattner78276e32018-07-07 15:48:26 -07001311 // If an argument list is present, parse it.
1312 if (consumeIf(Token::l_paren)) {
1313 if (parseOptionalSSAUseAndTypeList(Token::r_paren))
1314 return ParseFailure;
1315
1316 // TODO: attach it.
1317 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001318
1319 if (!consumeIf(Token::colon))
1320 return emitError("expected ':' after basic block name");
1321
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001322 // Set the insertion point to the block we want to insert new operations into.
Chris Lattner48af7d12018-07-09 19:05:38 -07001323 builder.setInsertionPoint(block);
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001324
Chris Lattnered65a732018-06-28 20:45:33 -07001325 // Parse the list of operations that make up the body of the block.
Chris Lattner48af7d12018-07-09 19:05:38 -07001326 while (getToken().isNot(Token::kw_return, Token::kw_br)) {
1327 auto loc = getToken().getLoc();
1328 auto *inst = parseCFGOperation();
Chris Lattner3a467cc2018-07-01 20:28:00 -07001329 if (!inst)
Chris Lattnered65a732018-06-28 20:45:33 -07001330 return ParseFailure;
Chris Lattner3a467cc2018-07-01 20:28:00 -07001331
Chris Lattner21e67f62018-07-06 10:46:19 -07001332 // We just parsed an operation. If it is a recognized one, verify that it
1333 // is structurally as we expect. If not, produce an error with a reasonable
1334 // source location.
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001335 if (auto *opInfo = inst->getAbstractOperation(builder.getContext()))
Chris Lattner21e67f62018-07-06 10:46:19 -07001336 if (auto error = opInfo->verifyInvariants(inst))
1337 return emitError(loc, error);
Chris Lattnered65a732018-06-28 20:45:33 -07001338 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001339
Chris Lattner48af7d12018-07-09 19:05:38 -07001340 auto *term = parseTerminator();
Chris Lattner3a467cc2018-07-01 20:28:00 -07001341 if (!term)
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001342 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07001343
1344 return ParseSuccess;
1345}
1346
Chris Lattnered65a732018-06-28 20:45:33 -07001347/// Parse the CFG operation.
1348///
1349/// TODO(clattner): This is a change from the MLIR spec as written, it is an
1350/// experiment that will eliminate "builtin" instructions as a thing.
1351///
1352/// cfg-operation ::=
1353/// (ssa-id `=`)? string '(' ssa-use-list? ')' attribute-dict?
1354/// `:` function-type
1355///
Chris Lattner48af7d12018-07-09 19:05:38 -07001356OperationInst *CFGFunctionParser::parseCFGOperation() {
Chris Lattner78276e32018-07-07 15:48:26 -07001357 StringRef resultID;
Chris Lattner48af7d12018-07-09 19:05:38 -07001358 if (getToken().is(Token::percent_identifier)) {
1359 resultID = getTokenSpelling().drop_front();
Chris Lattner78276e32018-07-07 15:48:26 -07001360 consumeToken();
1361 if (!consumeIf(Token::equal))
1362 return (emitError("expected '=' after SSA name"), nullptr);
1363 }
Chris Lattnered65a732018-06-28 20:45:33 -07001364
Chris Lattner48af7d12018-07-09 19:05:38 -07001365 if (getToken().isNot(Token::string))
Chris Lattner3a467cc2018-07-01 20:28:00 -07001366 return (emitError("expected operation name in quotes"), nullptr);
Chris Lattnered65a732018-06-28 20:45:33 -07001367
Chris Lattner48af7d12018-07-09 19:05:38 -07001368 auto name = getToken().getStringValue();
Chris Lattnered65a732018-06-28 20:45:33 -07001369 if (name.empty())
Chris Lattner3a467cc2018-07-01 20:28:00 -07001370 return (emitError("empty operation name is invalid"), nullptr);
Chris Lattnered65a732018-06-28 20:45:33 -07001371
1372 consumeToken(Token::string);
1373
1374 if (!consumeIf(Token::l_paren))
Chris Lattner7121b802018-07-04 20:45:39 -07001375 return (emitError("expected '(' to start operand list"), nullptr);
Chris Lattnered65a732018-06-28 20:45:33 -07001376
Chris Lattner78276e32018-07-07 15:48:26 -07001377 // Parse the operand list.
1378 parseOptionalSSAUseList(Token::r_paren);
Chris Lattner7121b802018-07-04 20:45:39 -07001379
1380 SmallVector<NamedAttribute, 4> attributes;
Chris Lattner48af7d12018-07-09 19:05:38 -07001381 if (getToken().is(Token::l_brace)) {
Chris Lattner7121b802018-07-04 20:45:39 -07001382 if (parseAttributeDict(attributes))
1383 return nullptr;
1384 }
Chris Lattnered65a732018-06-28 20:45:33 -07001385
Chris Lattner78276e32018-07-07 15:48:26 -07001386 // TODO: Don't drop result name and operand names on the floor.
Chris Lattner1ac20cb2018-07-10 10:59:53 -07001387 auto nameId = builder.getIdentifier(name);
Chris Lattner48af7d12018-07-09 19:05:38 -07001388 return builder.createOperation(nameId, attributes);
Chris Lattnered65a732018-06-28 20:45:33 -07001389}
1390
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001391/// Parse the terminator instruction for a basic block.
1392///
1393/// terminator-stmt ::= `br` bb-id branch-use-list?
1394/// branch-use-list ::= `(` ssa-use-and-type-list? `)`
1395/// terminator-stmt ::=
1396/// `cond_br` ssa-use `,` bb-id branch-use-list? `,` bb-id branch-use-list?
1397/// terminator-stmt ::= `return` ssa-use-and-type-list?
1398///
Chris Lattner48af7d12018-07-09 19:05:38 -07001399TerminatorInst *CFGFunctionParser::parseTerminator() {
1400 switch (getToken().getKind()) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001401 default:
Chris Lattner3a467cc2018-07-01 20:28:00 -07001402 return (emitError("expected terminator at end of basic block"), nullptr);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001403
1404 case Token::kw_return:
1405 consumeToken(Token::kw_return);
Chris Lattner48af7d12018-07-09 19:05:38 -07001406 return builder.createReturnInst();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001407
1408 case Token::kw_br: {
1409 consumeToken(Token::kw_br);
Chris Lattner48af7d12018-07-09 19:05:38 -07001410 auto destBB = getBlockNamed(getTokenSpelling(), getToken().getLoc());
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001411 if (!consumeIf(Token::bare_identifier))
Chris Lattner3a467cc2018-07-01 20:28:00 -07001412 return (emitError("expected basic block name"), nullptr);
Chris Lattner48af7d12018-07-09 19:05:38 -07001413 return builder.createBranchInst(destBB);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001414 }
Chris Lattner78276e32018-07-07 15:48:26 -07001415 // TODO: cond_br.
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001416 }
1417}
1418
Chris Lattner48af7d12018-07-09 19:05:38 -07001419//===----------------------------------------------------------------------===//
1420// ML Functions
1421//===----------------------------------------------------------------------===//
1422
1423namespace {
1424/// Refined parser for MLFunction bodies.
1425class MLFunctionParser : public Parser {
1426public:
1427 MLFunction *function;
1428
1429 /// This builder intentionally shadows the builder in the base class, with a
1430 /// more specific builder type.
1431 // TODO: MLFuncBuilder builder;
1432
1433 MLFunctionParser(ParserState &state, MLFunction *function)
1434 : Parser(state), function(function) {}
1435
1436 ParseResult parseFunctionBody();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001437
1438private:
1439 Statement *parseStatement();
1440 ForStmt *parseForStmt();
1441 IfStmt *parseIfStmt();
1442 ParseResult parseElseClause(IfClause *elseClause);
1443 ParseResult parseStmtBlock(StmtBlock *block);
Chris Lattner48af7d12018-07-09 19:05:38 -07001444};
1445} // end anonymous namespace
1446
Chris Lattner48af7d12018-07-09 19:05:38 -07001447ParseResult MLFunctionParser::parseFunctionBody() {
1448 if (!consumeIf(Token::l_brace))
1449 return emitError("expected '{' in ML function");
1450
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001451 // Make sure we have at least one statement.
Chris Lattner48af7d12018-07-09 19:05:38 -07001452 if (getToken().is(Token::r_brace))
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001453 return emitError("ML function must end with return statement");
1454
1455 // Parse the list of instructions.
1456 while (!consumeIf(Token::kw_return)) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001457 auto *stmt = parseStatement();
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001458 if (!stmt)
1459 return ParseFailure;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001460 function->push_back(stmt);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001461 }
1462
1463 // TODO: parse return statement operands
1464 if (!consumeIf(Token::r_brace))
1465 emitError("expected '}' in ML function");
1466
Chris Lattner48af7d12018-07-09 19:05:38 -07001467 getModule()->functionList.push_back(function);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001468
1469 return ParseSuccess;
1470}
1471
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001472/// Statement.
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001473///
Chris Lattner48af7d12018-07-09 19:05:38 -07001474/// ml-stmt ::= instruction | ml-for-stmt | ml-if-stmt
1475///
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001476/// TODO: fix terminology in MLSpec document. ML functions
1477/// contain operation statements, not instructions.
1478///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001479Statement *MLFunctionParser::parseStatement() {
Chris Lattner48af7d12018-07-09 19:05:38 -07001480 switch (getToken().getKind()) {
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001481 default:
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001482 //TODO: parse OperationStmt
1483 return (emitError("expected statement"), nullptr);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001484
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001485 case Token::kw_for:
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001486 return parseForStmt();
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001487
1488 case Token::kw_if:
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001489 return parseIfStmt();
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001490 }
1491}
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001492
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001493/// For statement.
1494///
Chris Lattner48af7d12018-07-09 19:05:38 -07001495/// ml-for-stmt ::= `for` ssa-id `=` lower-bound `to` upper-bound
1496/// (`step` integer-literal)? `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001497///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001498ForStmt *MLFunctionParser::parseForStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001499 consumeToken(Token::kw_for);
1500
1501 //TODO: parse loop header
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001502 ForStmt *stmt = new ForStmt();
1503 if (parseStmtBlock(static_cast<StmtBlock *>(stmt))) {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001504 delete stmt;
1505 return nullptr;
1506 }
1507 return stmt;
1508}
1509
1510/// If statement.
1511///
Chris Lattner48af7d12018-07-09 19:05:38 -07001512/// ml-if-head ::= `if` ml-if-cond `{` ml-stmt* `}`
1513/// | ml-if-head `else` `if` ml-if-cond `{` ml-stmt* `}`
1514/// ml-if-stmt ::= ml-if-head
1515/// | ml-if-head `else` `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001516///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001517IfStmt *MLFunctionParser::parseIfStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001518 consumeToken(Token::kw_if);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001519 if (!consumeIf(Token::l_paren))
1520 return (emitError("expected ("), nullptr);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001521
1522 //TODO: parse condition
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001523
1524 if (!consumeIf(Token::r_paren))
1525 return (emitError("expected )"), nullptr);
1526
1527 IfStmt *ifStmt = new IfStmt();
1528 IfClause *thenClause = ifStmt->getThenClause();
1529 if (parseStmtBlock(thenClause)) {
1530 delete ifStmt;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001531 return nullptr;
1532 }
1533
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001534 if (consumeIf(Token::kw_else)) {
1535 IfClause *elseClause = ifStmt->createElseClause();
1536 if (parseElseClause(elseClause)) {
1537 delete ifStmt;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001538 return nullptr;
1539 }
1540 }
1541
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001542 return ifStmt;
1543}
1544
1545ParseResult MLFunctionParser::parseElseClause(IfClause *elseClause) {
1546 if (getToken().is(Token::kw_if)) {
1547 IfStmt *nextIf = parseIfStmt();
1548 if (!nextIf)
1549 return ParseFailure;
1550 elseClause->push_back(nextIf);
1551 return ParseSuccess;
1552 }
1553
1554 if (parseStmtBlock(elseClause))
1555 return ParseFailure;
1556
1557 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001558}
1559
1560///
1561/// Parse `{` ml-stmt* `}`
1562///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001563ParseResult MLFunctionParser::parseStmtBlock(StmtBlock *block) {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001564 if (!consumeIf(Token::l_brace))
1565 return emitError("expected '{' before statement list");
1566
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001567 while (!consumeIf(Token::r_brace)) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001568 auto *stmt = parseStatement();
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001569 if (!stmt)
1570 return ParseFailure;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001571 block->push_back(stmt);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001572 }
1573
1574 return ParseSuccess;
1575}
1576
Chris Lattner4c95a502018-06-23 16:03:42 -07001577//===----------------------------------------------------------------------===//
1578// Top-level entity parsing.
1579//===----------------------------------------------------------------------===//
1580
Chris Lattner2e595eb2018-07-10 10:08:27 -07001581namespace {
1582/// This parser handles entities that are only valid at the top level of the
1583/// file.
1584class ModuleParser : public Parser {
1585public:
1586 explicit ModuleParser(ParserState &state) : Parser(state) {}
1587
1588 ParseResult parseModule();
1589
1590private:
1591 ParseResult parseAffineMapDef();
1592
1593 // Functions.
1594 ParseResult parseFunctionSignature(StringRef &name, FunctionType *&type);
1595 ParseResult parseExtFunc();
1596 ParseResult parseCFGFunc();
1597 ParseResult parseMLFunc();
1598};
1599} // end anonymous namespace
1600
1601/// Affine map declaration.
1602///
1603/// affine-map-def ::= affine-map-id `=` affine-map-inline
1604///
1605ParseResult ModuleParser::parseAffineMapDef() {
1606 assert(getToken().is(Token::hash_identifier));
1607
1608 StringRef affineMapId = getTokenSpelling().drop_front();
1609
1610 // Check for redefinitions.
1611 auto *&entry = getState().affineMapDefinitions[affineMapId];
1612 if (entry)
1613 return emitError("redefinition of affine map id '" + affineMapId + "'");
1614
1615 consumeToken(Token::hash_identifier);
1616
1617 // Parse the '='
1618 if (!consumeIf(Token::equal))
1619 return emitError("expected '=' in affine map outlined definition");
1620
1621 entry = parseAffineMapInline();
1622 if (!entry)
1623 return ParseFailure;
1624
1625 getModule()->affineMapList.push_back(entry);
1626 return ParseSuccess;
1627}
1628
1629/// Parse a function signature, starting with a name and including the parameter
1630/// list.
1631///
1632/// argument-list ::= type (`,` type)* | /*empty*/
1633/// function-signature ::= function-id `(` argument-list `)` (`->` type-list)?
1634///
1635ParseResult ModuleParser::parseFunctionSignature(StringRef &name,
1636 FunctionType *&type) {
1637 if (getToken().isNot(Token::at_identifier))
1638 return emitError("expected a function identifier like '@foo'");
1639
1640 name = getTokenSpelling().drop_front();
1641 consumeToken(Token::at_identifier);
1642
1643 if (getToken().isNot(Token::l_paren))
1644 return emitError("expected '(' in function signature");
1645
1646 SmallVector<Type *, 4> arguments;
1647 if (parseTypeList(arguments))
1648 return ParseFailure;
1649
1650 // Parse the return type if present.
1651 SmallVector<Type *, 4> results;
1652 if (consumeIf(Token::arrow)) {
1653 if (parseTypeList(results))
1654 return ParseFailure;
1655 }
1656 type = builder.getFunctionType(arguments, results);
1657 return ParseSuccess;
1658}
1659
1660/// External function declarations.
1661///
1662/// ext-func ::= `extfunc` function-signature
1663///
1664ParseResult ModuleParser::parseExtFunc() {
1665 consumeToken(Token::kw_extfunc);
1666
1667 StringRef name;
1668 FunctionType *type = nullptr;
1669 if (parseFunctionSignature(name, type))
1670 return ParseFailure;
1671
1672 // Okay, the external function definition was parsed correctly.
1673 getModule()->functionList.push_back(new ExtFunction(name, type));
1674 return ParseSuccess;
1675}
1676
1677/// CFG function declarations.
1678///
1679/// cfg-func ::= `cfgfunc` function-signature `{` basic-block+ `}`
1680///
1681ParseResult ModuleParser::parseCFGFunc() {
1682 consumeToken(Token::kw_cfgfunc);
1683
1684 StringRef name;
1685 FunctionType *type = nullptr;
1686 if (parseFunctionSignature(name, type))
1687 return ParseFailure;
1688
1689 // Okay, the CFG function signature was parsed correctly, create the function.
1690 auto function = new CFGFunction(name, type);
1691
1692 return CFGFunctionParser(getState(), function).parseFunctionBody();
1693}
1694
1695/// ML function declarations.
1696///
1697/// ml-func ::= `mlfunc` ml-func-signature `{` ml-stmt* ml-return-stmt `}`
1698///
1699ParseResult ModuleParser::parseMLFunc() {
1700 consumeToken(Token::kw_mlfunc);
1701
1702 StringRef name;
1703 FunctionType *type = nullptr;
1704
1705 // FIXME: Parse ML function signature (args + types)
1706 // by passing pointer to SmallVector<identifier> into parseFunctionSignature
1707 if (parseFunctionSignature(name, type))
1708 return ParseFailure;
1709
1710 // Okay, the ML function signature was parsed correctly, create the function.
1711 auto function = new MLFunction(name, type);
1712
1713 return MLFunctionParser(getState(), function).parseFunctionBody();
1714}
1715
Chris Lattnere79379a2018-06-22 10:39:19 -07001716/// This is the top-level module parser.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001717ParseResult ModuleParser::parseModule() {
Chris Lattnere79379a2018-06-22 10:39:19 -07001718 while (1) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001719 switch (getToken().getKind()) {
Chris Lattnere79379a2018-06-22 10:39:19 -07001720 default:
1721 emitError("expected a top level entity");
Chris Lattner2e595eb2018-07-10 10:08:27 -07001722 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07001723
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001724 // If we got to the end of the file, then we're done.
Chris Lattnere79379a2018-06-22 10:39:19 -07001725 case Token::eof:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001726 return ParseSuccess;
Chris Lattnere79379a2018-06-22 10:39:19 -07001727
1728 // If we got an error token, then the lexer already emitted an error, just
1729 // stop. Someday we could introduce error recovery if there was demand for
1730 // it.
1731 case Token::error:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001732 return ParseFailure;
1733
1734 case Token::hash_identifier:
1735 if (parseAffineMapDef())
1736 return ParseFailure;
1737 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07001738
1739 case Token::kw_extfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001740 if (parseExtFunc())
1741 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07001742 break;
1743
Chris Lattner4c95a502018-06-23 16:03:42 -07001744 case Token::kw_cfgfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001745 if (parseCFGFunc())
1746 return ParseFailure;
MLIR Teamf85a6262018-06-27 11:03:08 -07001747 break;
Chris Lattner4c95a502018-06-23 16:03:42 -07001748
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001749 case Token::kw_mlfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001750 if (parseMLFunc())
1751 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001752 break;
1753
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001754 // TODO: affine entity declarations, etc.
Chris Lattnere79379a2018-06-22 10:39:19 -07001755 }
1756 }
1757}
1758
1759//===----------------------------------------------------------------------===//
1760
Jacques Pienaar7b829702018-07-03 13:24:09 -07001761void mlir::defaultErrorReporter(const llvm::SMDiagnostic &error) {
1762 const auto &sourceMgr = *error.getSourceMgr();
1763 sourceMgr.PrintMessage(error.getLoc(), error.getKind(), error.getMessage());
1764}
1765
Chris Lattnere79379a2018-06-22 10:39:19 -07001766/// This parses the file specified by the indicated SourceMgr and returns an
1767/// MLIR module if it was valid. If not, it emits diagnostics and returns null.
Jacques Pienaar9c411be2018-06-24 19:17:35 -07001768Module *mlir::parseSourceFile(llvm::SourceMgr &sourceMgr, MLIRContext *context,
Jacques Pienaar7b829702018-07-03 13:24:09 -07001769 SMDiagnosticHandlerTy errorReporter) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001770 // This is the result module we are parsing into.
1771 std::unique_ptr<Module> module(new Module(context));
1772
1773 ParserState state(sourceMgr, module.get(),
Jacques Pienaar0bffd862018-07-11 13:26:23 -07001774 errorReporter ? errorReporter : defaultErrorReporter);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001775 if (ModuleParser(state).parseModule())
1776 return nullptr;
Chris Lattner21e67f62018-07-06 10:46:19 -07001777
1778 // Make sure the parse module has no other structural problems detected by the
1779 // verifier.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001780 module->verify();
1781 return module.release();
Chris Lattnere79379a2018-06-22 10:39:19 -07001782}