blob: e1d184d1ed313e3af221b133c4b9e232cd3042d0 [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
Chris Lattner8da0c282018-06-29 11:15:56 -0700135 ParseResult parseCommaSeparatedList(Token::Kind rightToken,
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700136 const std::function<ParseResult()> &parseElement,
137 bool allowEmptyList = true);
138
Chris Lattnerf7e22732018-06-22 22:03:48 -0700139 // We have two forms of parsing methods - those that return a non-null
140 // pointer on success, and those that return a ParseResult to indicate whether
141 // they returned a failure. The second class fills in by-reference arguments
142 // as the results of their action.
143
Chris Lattnere79379a2018-06-22 10:39:19 -0700144 // Type parsing.
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700145 Type *parsePrimitiveType();
Chris Lattnerf7e22732018-06-22 22:03:48 -0700146 Type *parseElementType();
147 VectorType *parseVectorType();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700148 ParseResult parseDimensionListRanked(SmallVectorImpl<int> &dimensions);
Chris Lattnerf7e22732018-06-22 22:03:48 -0700149 Type *parseTensorType();
150 Type *parseMemRefType();
151 Type *parseFunctionType();
152 Type *parseType();
153 ParseResult parseTypeList(SmallVectorImpl<Type*> &elements);
Chris Lattnere79379a2018-06-22 10:39:19 -0700154
Chris Lattner7121b802018-07-04 20:45:39 -0700155 // Attribute parsing.
156 Attribute *parseAttribute();
157 ParseResult parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes);
158
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700159 // Polyhedral structures.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700160 AffineMap *parseAffineMapInline();
MLIR Teamf85a6262018-06-27 11:03:08 -0700161
Chris Lattner78276e32018-07-07 15:48:26 -0700162 // SSA
163 ParseResult parseSSAUse();
164 ParseResult parseOptionalSSAUseList(Token::Kind endToken);
165 ParseResult parseSSAUseAndType();
166 ParseResult parseOptionalSSAUseAndTypeList(Token::Kind endToken);
167
Chris Lattner48af7d12018-07-09 19:05:38 -0700168private:
169 // The Parser is subclassed and reinstantiated. Do not add additional
170 // non-trivial state here, add it to the ParserState class.
171 ParserState &state;
Chris Lattnere79379a2018-06-22 10:39:19 -0700172};
173} // end anonymous namespace
174
175//===----------------------------------------------------------------------===//
176// Helper methods.
177//===----------------------------------------------------------------------===//
178
Chris Lattner4c95a502018-06-23 16:03:42 -0700179ParseResult Parser::emitError(SMLoc loc, const Twine &message) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700180 // If we hit a parse error in response to a lexer error, then the lexer
Jacques Pienaar9c411be2018-06-24 19:17:35 -0700181 // already reported the error.
Chris Lattner48af7d12018-07-09 19:05:38 -0700182 if (getToken().is(Token::error))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700183 return ParseFailure;
184
Chris Lattner48af7d12018-07-09 19:05:38 -0700185 auto &sourceMgr = state.lex.getSourceMgr();
186 state.errorReporter(sourceMgr.GetMessage(loc, SourceMgr::DK_Error, message));
Chris Lattnere79379a2018-06-22 10:39:19 -0700187 return ParseFailure;
188}
189
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700190/// Parse a comma-separated list of elements, terminated with an arbitrary
191/// token. This allows empty lists if allowEmptyList is true.
192///
193/// abstract-list ::= rightToken // if allowEmptyList == true
194/// abstract-list ::= element (',' element)* rightToken
195///
196ParseResult Parser::
Chris Lattner8da0c282018-06-29 11:15:56 -0700197parseCommaSeparatedList(Token::Kind rightToken,
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700198 const std::function<ParseResult()> &parseElement,
199 bool allowEmptyList) {
200 // Handle the empty case.
Chris Lattner48af7d12018-07-09 19:05:38 -0700201 if (getToken().is(rightToken)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700202 if (!allowEmptyList)
203 return emitError("expected list element");
204 consumeToken(rightToken);
205 return ParseSuccess;
206 }
207
208 // Non-empty case starts with an element.
209 if (parseElement())
210 return ParseFailure;
211
212 // Otherwise we have a list of comma separated elements.
213 while (consumeIf(Token::comma)) {
214 if (parseElement())
215 return ParseFailure;
216 }
217
218 // Consume the end character.
219 if (!consumeIf(rightToken))
Chris Lattner8da0c282018-06-29 11:15:56 -0700220 return emitError("expected ',' or '" + Token::getTokenSpelling(rightToken) +
221 "'");
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700222
223 return ParseSuccess;
224}
Chris Lattnere79379a2018-06-22 10:39:19 -0700225
226//===----------------------------------------------------------------------===//
227// Type Parsing
228//===----------------------------------------------------------------------===//
229
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700230/// Parse the low-level fixed dtypes in the system.
231///
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700232/// primitive-type ::= `f16` | `bf16` | `f32` | `f64`
233/// primitive-type ::= integer-type
234/// primitive-type ::= `affineint`
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700235///
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700236Type *Parser::parsePrimitiveType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700237 switch (getToken().getKind()) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700238 default:
239 return (emitError("expected type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700240 case Token::kw_bf16:
241 consumeToken(Token::kw_bf16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700242 return builder.getBF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700243 case Token::kw_f16:
244 consumeToken(Token::kw_f16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700245 return builder.getF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700246 case Token::kw_f32:
247 consumeToken(Token::kw_f32);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700248 return builder.getF32Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700249 case Token::kw_f64:
250 consumeToken(Token::kw_f64);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700251 return builder.getF64Type();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700252 case Token::kw_affineint:
253 consumeToken(Token::kw_affineint);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700254 return builder.getAffineIntType();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700255 case Token::inttype: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700256 auto width = getToken().getIntTypeBitwidth();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700257 if (!width.hasValue())
258 return (emitError("invalid integer width"), nullptr);
259 consumeToken(Token::inttype);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700260 return builder.getIntegerType(width.getValue());
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700261 }
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700262 }
263}
264
265/// Parse the element type of a tensor or memref type.
266///
267/// element-type ::= primitive-type | vector-type
268///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700269Type *Parser::parseElementType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700270 if (getToken().is(Token::kw_vector))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700271 return parseVectorType();
272
273 return parsePrimitiveType();
274}
275
276/// Parse a vector type.
277///
278/// vector-type ::= `vector` `<` const-dimension-list primitive-type `>`
279/// const-dimension-list ::= (integer-literal `x`)+
280///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700281VectorType *Parser::parseVectorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700282 consumeToken(Token::kw_vector);
283
284 if (!consumeIf(Token::less))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700285 return (emitError("expected '<' in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700286
Chris Lattner48af7d12018-07-09 19:05:38 -0700287 if (getToken().isNot(Token::integer))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700288 return (emitError("expected dimension size in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700289
290 SmallVector<unsigned, 4> dimensions;
Chris Lattner48af7d12018-07-09 19:05:38 -0700291 while (getToken().is(Token::integer)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700292 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700293 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700294 if (!dimension.hasValue())
Chris Lattnerf7e22732018-06-22 22:03:48 -0700295 return (emitError("invalid dimension in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700296 dimensions.push_back(dimension.getValue());
297
298 consumeToken(Token::integer);
299
300 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700301 if (getToken().isNot(Token::bare_identifier) ||
302 getTokenSpelling()[0] != 'x')
Chris Lattnerf7e22732018-06-22 22:03:48 -0700303 return (emitError("expected 'x' in vector dimension list"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700304
305 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700306 if (getTokenSpelling().size() != 1)
307 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700308
309 // Consume the 'x'.
310 consumeToken(Token::bare_identifier);
311 }
312
313 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700314 auto *elementType = parsePrimitiveType();
315 if (!elementType)
316 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700317
318 if (!consumeIf(Token::greater))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700319 return (emitError("expected '>' in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700320
Chris Lattnerf7e22732018-06-22 22:03:48 -0700321 return VectorType::get(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700322}
323
324/// Parse a dimension list of a tensor or memref type. This populates the
325/// dimension list, returning -1 for the '?' dimensions.
326///
327/// dimension-list-ranked ::= (dimension `x`)*
328/// dimension ::= `?` | integer-literal
329///
330ParseResult Parser::parseDimensionListRanked(SmallVectorImpl<int> &dimensions) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700331 while (getToken().isAny(Token::integer, Token::question)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700332 if (consumeIf(Token::question)) {
333 dimensions.push_back(-1);
334 } else {
335 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700336 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700337 if (!dimension.hasValue() || (int)dimension.getValue() < 0)
338 return emitError("invalid dimension");
339 dimensions.push_back((int)dimension.getValue());
340 consumeToken(Token::integer);
341 }
342
343 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700344 if (getToken().isNot(Token::bare_identifier) ||
345 getTokenSpelling()[0] != 'x')
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700346 return emitError("expected 'x' in dimension list");
347
348 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700349 if (getTokenSpelling().size() != 1)
350 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700351
352 // Consume the 'x'.
353 consumeToken(Token::bare_identifier);
354 }
355
356 return ParseSuccess;
357}
358
359/// Parse a tensor type.
360///
361/// tensor-type ::= `tensor` `<` dimension-list element-type `>`
362/// dimension-list ::= dimension-list-ranked | `??`
363///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700364Type *Parser::parseTensorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700365 consumeToken(Token::kw_tensor);
366
367 if (!consumeIf(Token::less))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700368 return (emitError("expected '<' in tensor type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700369
370 bool isUnranked;
371 SmallVector<int, 4> dimensions;
372
373 if (consumeIf(Token::questionquestion)) {
374 isUnranked = true;
375 } else {
376 isUnranked = false;
377 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700378 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700379 }
380
381 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700382 auto elementType = parseElementType();
383 if (!elementType)
384 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700385
386 if (!consumeIf(Token::greater))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700387 return (emitError("expected '>' in tensor type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700388
MLIR Team355ec862018-06-23 18:09:09 -0700389 if (isUnranked)
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700390 return builder.getTensorType(elementType);
391 return builder.getTensorType(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700392}
393
394/// Parse a memref type.
395///
396/// memref-type ::= `memref` `<` dimension-list-ranked element-type
397/// (`,` semi-affine-map-composition)? (`,` memory-space)? `>`
398///
399/// semi-affine-map-composition ::= (semi-affine-map `,` )* semi-affine-map
400/// memory-space ::= integer-literal /* | TODO: address-space-id */
401///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700402Type *Parser::parseMemRefType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700403 consumeToken(Token::kw_memref);
404
405 if (!consumeIf(Token::less))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700406 return (emitError("expected '<' in memref type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700407
408 SmallVector<int, 4> dimensions;
409 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700410 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700411
412 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700413 auto elementType = parseElementType();
414 if (!elementType)
415 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700416
417 // TODO: Parse semi-affine-map-composition.
418 // TODO: Parse memory-space.
419
420 if (!consumeIf(Token::greater))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700421 return (emitError("expected '>' in memref type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700422
Chris Lattnerf7e22732018-06-22 22:03:48 -0700423 // FIXME: Add an IR representation for memref types.
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700424 return builder.getIntegerType(1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700425}
426
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700427/// Parse a function type.
428///
429/// function-type ::= type-list-parens `->` type-list
430///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700431Type *Parser::parseFunctionType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700432 assert(getToken().is(Token::l_paren));
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700433
Chris Lattnerf7e22732018-06-22 22:03:48 -0700434 SmallVector<Type*, 4> arguments;
435 if (parseTypeList(arguments))
436 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700437
438 if (!consumeIf(Token::arrow))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700439 return (emitError("expected '->' in function type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700440
Chris Lattnerf7e22732018-06-22 22:03:48 -0700441 SmallVector<Type*, 4> results;
442 if (parseTypeList(results))
443 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700444
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700445 return builder.getFunctionType(arguments, results);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700446}
447
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700448/// Parse an arbitrary type.
449///
450/// type ::= primitive-type
451/// | vector-type
452/// | tensor-type
453/// | memref-type
454/// | function-type
455/// element-type ::= primitive-type | vector-type
456///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700457Type *Parser::parseType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700458 switch (getToken().getKind()) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700459 case Token::kw_memref: return parseMemRefType();
460 case Token::kw_tensor: return parseTensorType();
461 case Token::kw_vector: return parseVectorType();
462 case Token::l_paren: return parseFunctionType();
463 default:
464 return parsePrimitiveType();
465 }
466}
467
468/// Parse a "type list", which is a singular type, or a parenthesized list of
469/// types.
470///
471/// type-list ::= type-list-parens | type
472/// type-list-parens ::= `(` `)`
473/// | `(` type (`,` type)* `)`
474///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700475ParseResult Parser::parseTypeList(SmallVectorImpl<Type*> &elements) {
476 auto parseElt = [&]() -> ParseResult {
477 auto elt = parseType();
478 elements.push_back(elt);
479 return elt ? ParseSuccess : ParseFailure;
480 };
481
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700482 // If there is no parens, then it must be a singular type.
483 if (!consumeIf(Token::l_paren))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700484 return parseElt();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700485
Chris Lattnerf7e22732018-06-22 22:03:48 -0700486 if (parseCommaSeparatedList(Token::r_paren, parseElt))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700487 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700488
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700489 return ParseSuccess;
490}
491
Chris Lattner4c95a502018-06-23 16:03:42 -0700492//===----------------------------------------------------------------------===//
Chris Lattner7121b802018-07-04 20:45:39 -0700493// Attribute parsing.
494//===----------------------------------------------------------------------===//
495
496
497/// Attribute parsing.
498///
499/// attribute-value ::= bool-literal
500/// | integer-literal
501/// | float-literal
502/// | string-literal
503/// | `[` (attribute-value (`,` attribute-value)*)? `]`
504///
505Attribute *Parser::parseAttribute() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700506 switch (getToken().getKind()) {
Chris Lattner7121b802018-07-04 20:45:39 -0700507 case Token::kw_true:
508 consumeToken(Token::kw_true);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700509 return builder.getBoolAttr(true);
Chris Lattner7121b802018-07-04 20:45:39 -0700510 case Token::kw_false:
511 consumeToken(Token::kw_false);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700512 return builder.getBoolAttr(false);
Chris Lattner7121b802018-07-04 20:45:39 -0700513
514 case Token::integer: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700515 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700516 if (!val.hasValue() || (int64_t)val.getValue() < 0)
517 return (emitError("integer too large for attribute"), nullptr);
518 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700519 return builder.getIntegerAttr((int64_t)val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700520 }
521
522 case Token::minus: {
523 consumeToken(Token::minus);
Chris Lattner48af7d12018-07-09 19:05:38 -0700524 if (getToken().is(Token::integer)) {
525 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700526 if (!val.hasValue() || (int64_t)-val.getValue() >= 0)
527 return (emitError("integer too large for attribute"), nullptr);
528 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700529 return builder.getIntegerAttr((int64_t)-val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700530 }
531
532 return (emitError("expected constant integer or floating point value"),
533 nullptr);
534 }
535
536 case Token::string: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700537 auto val = getToken().getStringValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700538 consumeToken(Token::string);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700539 return builder.getStringAttr(val);
Chris Lattner7121b802018-07-04 20:45:39 -0700540 }
541
542 case Token::l_bracket: {
543 consumeToken(Token::l_bracket);
544 SmallVector<Attribute*, 4> elements;
545
546 auto parseElt = [&]() -> ParseResult {
547 elements.push_back(parseAttribute());
548 return elements.back() ? ParseSuccess : ParseFailure;
549 };
550
551 if (parseCommaSeparatedList(Token::r_bracket, parseElt))
552 return nullptr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700553 return builder.getArrayAttr(elements);
Chris Lattner7121b802018-07-04 20:45:39 -0700554 }
555 default:
556 // TODO: Handle floating point.
557 return (emitError("expected constant attribute value"), nullptr);
558 }
559}
560
Chris Lattner7121b802018-07-04 20:45:39 -0700561/// Attribute dictionary.
562///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700563/// attribute-dict ::= `{` `}`
564/// | `{` attribute-entry (`,` attribute-entry)* `}`
565/// attribute-entry ::= bare-id `:` attribute-value
Chris Lattner7121b802018-07-04 20:45:39 -0700566///
567ParseResult Parser::parseAttributeDict(
568 SmallVectorImpl<NamedAttribute> &attributes) {
569 consumeToken(Token::l_brace);
570
571 auto parseElt = [&]() -> ParseResult {
572 // We allow keywords as attribute names.
Chris Lattner48af7d12018-07-09 19:05:38 -0700573 if (getToken().isNot(Token::bare_identifier, Token::inttype) &&
574 !getToken().isKeyword())
Chris Lattner7121b802018-07-04 20:45:39 -0700575 return emitError("expected attribute name");
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700576 auto nameId = builder.getIdentifier(getTokenSpelling());
Chris Lattner7121b802018-07-04 20:45:39 -0700577 consumeToken();
578
579 if (!consumeIf(Token::colon))
580 return emitError("expected ':' in attribute list");
581
582 auto attr = parseAttribute();
583 if (!attr) return ParseFailure;
584
585 attributes.push_back({nameId, attr});
586 return ParseSuccess;
587 };
588
589 if (parseCommaSeparatedList(Token::r_brace, parseElt))
590 return ParseFailure;
591
592 return ParseSuccess;
593}
594
595//===----------------------------------------------------------------------===//
MLIR Teamf85a6262018-06-27 11:03:08 -0700596// Polyhedral structures.
597//===----------------------------------------------------------------------===//
598
Chris Lattner2e595eb2018-07-10 10:08:27 -0700599/// Lower precedence ops (all at the same precedence level). LNoOp is false in
600/// the boolean sense.
601enum AffineLowPrecOp {
602 /// Null value.
603 LNoOp,
604 Add,
605 Sub
606};
MLIR Teamf85a6262018-06-27 11:03:08 -0700607
Chris Lattner2e595eb2018-07-10 10:08:27 -0700608/// Higher precedence ops - all at the same precedence level. HNoOp is false in
609/// the boolean sense.
610enum AffineHighPrecOp {
611 /// Null value.
612 HNoOp,
613 Mul,
614 FloorDiv,
615 CeilDiv,
616 Mod
617};
Chris Lattner7121b802018-07-04 20:45:39 -0700618
Chris Lattner2e595eb2018-07-10 10:08:27 -0700619namespace {
620/// This is a specialized parser for AffineMap's, maintaining the state
621/// transient to their bodies.
622class AffineMapParser : public Parser {
623public:
624 explicit AffineMapParser(ParserState &state) : Parser(state) {}
Chris Lattner7121b802018-07-04 20:45:39 -0700625
Chris Lattner2e595eb2018-07-10 10:08:27 -0700626 AffineMap *parseAffineMapInline();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700627
Chris Lattner2e595eb2018-07-10 10:08:27 -0700628private:
629 unsigned getNumDims() const { return dims.size(); }
630 unsigned getNumSymbols() const { return symbols.size(); }
MLIR Teamf85a6262018-06-27 11:03:08 -0700631
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700632 /// Returns true if the only identifiers the parser accepts in affine
633 /// expressions are symbolic identifiers.
634 bool isPureSymbolic() const { return pureSymbolic; }
635 void setSymbolicParsing(bool val) { pureSymbolic = val; }
636
Chris Lattner2e595eb2018-07-10 10:08:27 -0700637 // Binary affine op parsing.
638 AffineLowPrecOp consumeIfLowPrecOp();
639 AffineHighPrecOp consumeIfHighPrecOp();
MLIR Teamf85a6262018-06-27 11:03:08 -0700640
Chris Lattner2e595eb2018-07-10 10:08:27 -0700641 // Identifier lists for polyhedral structures.
642 ParseResult parseDimIdList();
643 ParseResult parseSymbolIdList();
644 ParseResult parseDimOrSymbolId(bool isDim);
645
646 AffineExpr *parseAffineExpr();
647 AffineExpr *parseParentheticalExpr();
648 AffineExpr *parseNegateExpression(AffineExpr *lhs);
649 AffineExpr *parseIntegerExpr();
650 AffineExpr *parseBareIdExpr();
651
652 AffineExpr *getBinaryAffineOpExpr(AffineHighPrecOp op, AffineExpr *lhs,
653 AffineExpr *rhs);
654 AffineExpr *getBinaryAffineOpExpr(AffineLowPrecOp op, AffineExpr *lhs,
655 AffineExpr *rhs);
656 AffineExpr *parseAffineOperandExpr(AffineExpr *lhs);
657 AffineExpr *parseAffineLowPrecOpExpr(AffineExpr *llhs,
658 AffineLowPrecOp llhsOp);
659 AffineExpr *parseAffineHighPrecOpExpr(AffineExpr *llhs,
660 AffineHighPrecOp llhsOp);
661
662private:
663 // TODO(bondhugula): could just use an vector/ArrayRef and scan the numbers.
664 llvm::StringMap<unsigned> dims;
665 llvm::StringMap<unsigned> symbols;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700666 /// True if the parser should allow only symbolic identifiers in affine
667 /// expressions.
668 bool pureSymbolic = false;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700669};
670} // end anonymous namespace
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700671
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700672/// Create an affine binary high precedence op expression (mul's, div's, mod)
Chris Lattner2e595eb2018-07-10 10:08:27 -0700673AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineHighPrecOp op,
674 AffineExpr *lhs,
675 AffineExpr *rhs) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700676 // TODO: make the error location info accurate.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700677 switch (op) {
678 case Mul:
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700679 if (!lhs->isSymbolic() && !rhs->isSymbolic()) {
680 emitError("non-affine expression: at least one of the multiply "
681 "operands has to be either a constant or symbolic");
682 return nullptr;
683 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700684 return builder.getMulExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700685 case FloorDiv:
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700686 if (!rhs->isSymbolic()) {
687 emitError("non-affine expression: right operand of floordiv "
688 "has to be either a constant or symbolic");
689 return nullptr;
690 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700691 return builder.getFloorDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700692 case CeilDiv:
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700693 if (!rhs->isSymbolic()) {
694 emitError("non-affine expression: right operand of ceildiv "
695 "has to be either a constant or symbolic");
696 return nullptr;
697 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700698 return builder.getCeilDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700699 case Mod:
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700700 if (!rhs->isSymbolic()) {
701 emitError("non-affine expression: right operand of mod "
702 "has to be either a constant or symbolic");
703 return nullptr;
704 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700705 return builder.getModExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700706 case HNoOp:
707 llvm_unreachable("can't create affine expression for null high prec op");
708 return nullptr;
709 }
710}
711
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700712/// Create an affine binary low precedence op expression (add, sub).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700713AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineLowPrecOp op,
714 AffineExpr *lhs,
715 AffineExpr *rhs) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700716 switch (op) {
717 case AffineLowPrecOp::Add:
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700718 return builder.getAddExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700719 case AffineLowPrecOp::Sub:
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700720 return builder.getSubExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700721 case AffineLowPrecOp::LNoOp:
722 llvm_unreachable("can't create affine expression for null low prec op");
723 return nullptr;
724 }
725}
726
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700727/// Consume this token if it is a lower precedence affine op (there are only two
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700728/// precedence levels).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700729AffineLowPrecOp AffineMapParser::consumeIfLowPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700730 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700731 case Token::plus:
732 consumeToken(Token::plus);
733 return AffineLowPrecOp::Add;
734 case Token::minus:
735 consumeToken(Token::minus);
736 return AffineLowPrecOp::Sub;
737 default:
738 return AffineLowPrecOp::LNoOp;
739 }
740}
741
742/// Consume this token if it is a higher precedence affine op (there are only
743/// two precedence levels)
Chris Lattner2e595eb2018-07-10 10:08:27 -0700744AffineHighPrecOp AffineMapParser::consumeIfHighPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700745 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700746 case Token::star:
747 consumeToken(Token::star);
748 return Mul;
749 case Token::kw_floordiv:
750 consumeToken(Token::kw_floordiv);
751 return FloorDiv;
752 case Token::kw_ceildiv:
753 consumeToken(Token::kw_ceildiv);
754 return CeilDiv;
755 case Token::kw_mod:
756 consumeToken(Token::kw_mod);
757 return Mod;
758 default:
759 return HNoOp;
760 }
761}
762
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700763/// Parse a high precedence op expression list: mul, div, and mod are high
764/// precedence binary ops, i.e., parse a
765/// expr_1 op_1 expr_2 op_2 ... expr_n
766/// where op_1, op_2 are all a AffineHighPrecOp (mul, div, mod).
767/// All affine binary ops are left associative.
768/// Given llhs, returns (llhs llhsOp lhs) op rhs, or (lhs op rhs) if llhs is
769/// null. If no rhs can be found, returns (llhs llhsOp lhs) or lhs if llhs is
770/// null.
771AffineExpr *
Chris Lattner2e595eb2018-07-10 10:08:27 -0700772AffineMapParser::parseAffineHighPrecOpExpr(AffineExpr *llhs,
773 AffineHighPrecOp llhsOp) {
774 AffineExpr *lhs = parseAffineOperandExpr(llhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700775 if (!lhs)
776 return nullptr;
777
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700778 // Found an LHS. Parse the remaining expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700779 if (AffineHighPrecOp op = consumeIfHighPrecOp()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700780 if (llhs) {
781 AffineExpr *expr = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
782 if (!expr)
783 return nullptr;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700784 return parseAffineHighPrecOpExpr(expr, op);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700785 }
786 // No LLHS, get RHS
Chris Lattner2e595eb2018-07-10 10:08:27 -0700787 return parseAffineHighPrecOpExpr(lhs, op);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700788 }
789
790 // This is the last operand in this expression.
791 if (llhs)
792 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
793
794 // No llhs, 'lhs' itself is the expression.
795 return lhs;
796}
797
798/// Parse an affine expression inside parentheses.
799///
800/// affine-expr ::= `(` affine-expr `)`
Chris Lattner2e595eb2018-07-10 10:08:27 -0700801AffineExpr *AffineMapParser::parseParentheticalExpr() {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700802 if (!consumeIf(Token::l_paren))
803 return (emitError("expected '('"), nullptr);
Chris Lattner48af7d12018-07-09 19:05:38 -0700804 if (getToken().is(Token::r_paren))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700805 return (emitError("no expression inside parentheses"), nullptr);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700806 auto *expr = parseAffineExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700807 if (!expr)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700808 return nullptr;
809 if (!consumeIf(Token::r_paren))
810 return (emitError("expected ')'"), nullptr);
811 return expr;
812}
813
814/// Parse the negation expression.
815///
816/// affine-expr ::= `-` affine-expr
Chris Lattner2e595eb2018-07-10 10:08:27 -0700817AffineExpr *AffineMapParser::parseNegateExpression(AffineExpr *lhs) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700818 if (!consumeIf(Token::minus))
819 return (emitError("expected '-'"), nullptr);
820
Chris Lattner2e595eb2018-07-10 10:08:27 -0700821 AffineExpr *operand = parseAffineOperandExpr(lhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700822 // Since negation has the highest precedence of all ops (including high
823 // precedence ops) but lower than parentheses, we are only going to use
824 // parseAffineOperandExpr instead of parseAffineExpr here.
825 if (!operand)
826 // Extra error message although parseAffineOperandExpr would have
827 // complained. Leads to a better diagnostic.
828 return (emitError("missing operand of negation"), nullptr);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700829 auto *minusOne = builder.getConstantExpr(-1);
830 return builder.getMulExpr(minusOne, operand);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700831}
832
833/// Parse a bare id that may appear in an affine expression.
834///
835/// affine-expr ::= bare-id
Chris Lattner2e595eb2018-07-10 10:08:27 -0700836AffineExpr *AffineMapParser::parseBareIdExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700837 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700838 return (emitError("expected bare identifier"), nullptr);
839
Chris Lattner48af7d12018-07-09 19:05:38 -0700840 StringRef sRef = getTokenSpelling();
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700841 // dims, symbols are all pairwise distinct.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700842 if (dims.count(sRef)) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700843 if (isPureSymbolic())
844 return (emitError("identifier used is not a symbolic identifier"),
845 nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700846 consumeToken(Token::bare_identifier);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700847 return builder.getDimExpr(dims.lookup(sRef));
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700848 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700849
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700850 if (symbols.count(sRef)) {
851 consumeToken(Token::bare_identifier);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700852 return builder.getSymbolExpr(symbols.lookup(sRef));
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700853 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700854
855 return (emitError("use of undeclared identifier"), nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700856}
857
858/// Parse a positive integral constant appearing in an affine expression.
859///
860/// affine-expr ::= integer-literal
Chris Lattner2e595eb2018-07-10 10:08:27 -0700861AffineExpr *AffineMapParser::parseIntegerExpr() {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700862 // No need to handle negative numbers separately here. They are naturally
863 // handled via the unary negation operator, although (FIXME) MININT_64 still
864 // not correctly handled.
Chris Lattner48af7d12018-07-09 19:05:38 -0700865 if (getToken().isNot(Token::integer))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700866 return (emitError("expected integer"), nullptr);
867
Chris Lattner48af7d12018-07-09 19:05:38 -0700868 auto val = getToken().getUInt64IntegerValue();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700869 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
870 return (emitError("constant too large for affineint"), nullptr);
871 }
872 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700873 return builder.getConstantExpr((int64_t)val.getValue());
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700874}
875
876/// Parses an expression that can be a valid operand of an affine expression.
Uday Bondhugula76345202018-07-09 13:47:52 -0700877/// lhs: if non-null, lhs is an affine expression that is the lhs of a binary
878/// operator, the rhs of which is being parsed. This is used to determine
879/// whether an error should be emitted for a missing right operand.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700880// Eg: for an expression without parentheses (like i + j + k + l), each
881// of the four identifiers is an operand. For i + j*k + l, j*k is not an
882// operand expression, it's an op expression and will be parsed via
883// parseAffineHighPrecOpExpression(). However, for i + (j*k) + -l, (j*k) and -l
884// are valid operands that will be parsed by this function.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700885AffineExpr *AffineMapParser::parseAffineOperandExpr(AffineExpr *lhs) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700886 switch (getToken().getKind()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700887 case Token::bare_identifier:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700888 return parseBareIdExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700889 case Token::integer:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700890 return parseIntegerExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700891 case Token::l_paren:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700892 return parseParentheticalExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700893 case Token::minus:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700894 return parseNegateExpression(lhs);
Uday Bondhugula76345202018-07-09 13:47:52 -0700895 case Token::kw_ceildiv:
896 case Token::kw_floordiv:
897 case Token::kw_mod:
898 case Token::plus:
899 case Token::star:
900 if (lhs)
901 emitError("missing right operand of binary operator");
902 else
903 emitError("missing left operand of binary operator");
904 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700905 default:
906 if (lhs)
Uday Bondhugula76345202018-07-09 13:47:52 -0700907 emitError("missing right operand of binary operator");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700908 else
909 emitError("expected affine expression");
910 return nullptr;
911 }
912}
913
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700914/// Parse affine expressions that are bare-id's, integer constants,
915/// parenthetical affine expressions, and affine op expressions that are a
916/// composition of those.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700917///
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700918/// All binary op's associate from left to right.
919///
920/// {add, sub} have lower precedence than {mul, div, and mod}.
921///
Uday Bondhugula76345202018-07-09 13:47:52 -0700922/// Add, sub'are themselves at the same precedence level. Mul, floordiv,
923/// ceildiv, and mod are at the same higher precedence level. Negation has
924/// higher precedence than any binary op.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700925///
926/// llhs: the affine expression appearing on the left of the one being parsed.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700927/// This function will return ((llhs llhsOp lhs) op rhs) if llhs is non null,
928/// and lhs op rhs otherwise; if there is no rhs, llhs llhsOp lhs is returned if
929/// llhs is non-null; otherwise lhs is returned. This is to deal with left
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700930/// associativity.
931///
932/// Eg: when the expression is e1 + e2*e3 + e4, with e1 as llhs, this function
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700933/// will return the affine expr equivalent of (e1 + (e2*e3)) + e4, where (e2*e3)
934/// will be parsed using parseAffineHighPrecOpExpr().
Chris Lattner2e595eb2018-07-10 10:08:27 -0700935AffineExpr *AffineMapParser::parseAffineLowPrecOpExpr(AffineExpr *llhs,
936 AffineLowPrecOp llhsOp) {
Uday Bondhugula76345202018-07-09 13:47:52 -0700937 AffineExpr *lhs;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700938 if (!(lhs = parseAffineOperandExpr(llhs)))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700939 return nullptr;
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700940
941 // Found an LHS. Deal with the ops.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700942 if (AffineLowPrecOp lOp = consumeIfLowPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700943 if (llhs) {
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700944 AffineExpr *sum = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700945 return parseAffineLowPrecOpExpr(sum, lOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700946 }
947 // No LLHS, get RHS and form the expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700948 return parseAffineLowPrecOpExpr(lhs, lOp);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700949 }
Chris Lattner2e595eb2018-07-10 10:08:27 -0700950 if (AffineHighPrecOp hOp = consumeIfHighPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700951 // We have a higher precedence op here. Get the rhs operand for the llhs
952 // through parseAffineHighPrecOpExpr.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700953 AffineExpr *highRes = parseAffineHighPrecOpExpr(lhs, hOp);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700954 if (!highRes)
955 return nullptr;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700956
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700957 // If llhs is null, the product forms the first operand of the yet to be
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700958 // found expression. If non-null, the op to associate with llhs is llhsOp.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700959 AffineExpr *expr =
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700960 llhs ? getBinaryAffineOpExpr(llhsOp, llhs, highRes) : highRes;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700961
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700962 // Recurse for subsequent low prec op's after the affine high prec op
963 // expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700964 if (AffineLowPrecOp nextOp = consumeIfLowPrecOp())
965 return parseAffineLowPrecOpExpr(expr, nextOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700966 return expr;
967 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700968 // Last operand in the expression list.
969 if (llhs)
970 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
971 // No llhs, 'lhs' itself is the expression.
972 return lhs;
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700973}
974
975/// Parse an affine expression.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700976/// affine-expr ::= `(` affine-expr `)`
977/// | `-` affine-expr
978/// | affine-expr `+` affine-expr
979/// | affine-expr `-` affine-expr
980/// | affine-expr `*` affine-expr
981/// | affine-expr `floordiv` affine-expr
982/// | affine-expr `ceildiv` affine-expr
983/// | affine-expr `mod` affine-expr
984/// | bare-id
985/// | integer-literal
986///
987/// Additional conditions are checked depending on the production. For eg., one
988/// of the operands for `*` has to be either constant/symbolic; the second
989/// operand for floordiv, ceildiv, and mod has to be a positive integer.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700990AffineExpr *AffineMapParser::parseAffineExpr() {
991 return parseAffineLowPrecOpExpr(nullptr, AffineLowPrecOp::LNoOp);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700992}
993
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700994/// Parse a dim or symbol from the lists appearing before the actual expressions
Chris Lattner2e595eb2018-07-10 10:08:27 -0700995/// of the affine map. Update our state to store the dimensional/symbolic
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700996/// identifier. 'dim': whether it's the dim list or symbol list that is being
997/// parsed.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700998ParseResult AffineMapParser::parseDimOrSymbolId(bool isDim) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700999 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001000 return emitError("expected bare identifier");
Chris Lattner48af7d12018-07-09 19:05:38 -07001001 auto sRef = getTokenSpelling();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001002 consumeToken(Token::bare_identifier);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001003 if (dims.count(sRef))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001004 return emitError("dimensional identifier name reused");
Chris Lattner2e595eb2018-07-10 10:08:27 -07001005 if (symbols.count(sRef))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001006 return emitError("symbolic identifier name reused");
Chris Lattner2e595eb2018-07-10 10:08:27 -07001007 if (isDim)
1008 dims.insert({sRef, dims.size()});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001009 else
Chris Lattner2e595eb2018-07-10 10:08:27 -07001010 symbols.insert({sRef, symbols.size()});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001011 return ParseSuccess;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001012}
1013
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001014/// Parse the list of symbolic identifiers to an affine map.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001015ParseResult AffineMapParser::parseSymbolIdList() {
1016 if (!consumeIf(Token::l_bracket))
1017 return emitError("expected '['");
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001018
Chris Lattner2e595eb2018-07-10 10:08:27 -07001019 auto parseElt = [&]() -> ParseResult { return parseDimOrSymbolId(false); };
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001020 return parseCommaSeparatedList(Token::r_bracket, parseElt);
1021}
1022
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001023/// Parse the list of dimensional identifiers to an affine map.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001024ParseResult AffineMapParser::parseDimIdList() {
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001025 if (!consumeIf(Token::l_paren))
1026 return emitError("expected '(' at start of dimensional identifiers list");
1027
Chris Lattner2e595eb2018-07-10 10:08:27 -07001028 auto parseElt = [&]() -> ParseResult { return parseDimOrSymbolId(true); };
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001029 return parseCommaSeparatedList(Token::r_paren, parseElt);
1030}
1031
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001032/// Parse an affine map definition.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001033///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001034/// affine-map-inline ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
1035/// (`size` `(` dim-size (`,` dim-size)* `)`)?
1036/// dim-size ::= affine-expr | `min` `(` affine-expr ( `,` affine-expr)+ `)`
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001037///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001038/// multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner2e595eb2018-07-10 10:08:27 -07001039AffineMap *AffineMapParser::parseAffineMapInline() {
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001040 // List of dimensional identifiers.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001041 if (parseDimIdList())
Chris Lattner7121b802018-07-04 20:45:39 -07001042 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001043
1044 // Symbols are optional.
Chris Lattner48af7d12018-07-09 19:05:38 -07001045 if (getToken().is(Token::l_bracket)) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001046 if (parseSymbolIdList())
Chris Lattner7121b802018-07-04 20:45:39 -07001047 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001048 }
1049 if (!consumeIf(Token::arrow)) {
Chris Lattner7121b802018-07-04 20:45:39 -07001050 return (emitError("expected '->' or '['"), nullptr);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001051 }
1052 if (!consumeIf(Token::l_paren)) {
1053 emitError("expected '(' at start of affine map range");
Chris Lattner7121b802018-07-04 20:45:39 -07001054 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001055 }
1056
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001057 SmallVector<AffineExpr *, 4> exprs;
1058 auto parseElt = [&]() -> ParseResult {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001059 auto *elt = parseAffineExpr();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001060 ParseResult res = elt ? ParseSuccess : ParseFailure;
1061 exprs.push_back(elt);
1062 return res;
1063 };
1064
1065 // Parse a multi-dimensional affine expression (a comma-separated list of 1-d
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001066 // affine expressions); the list cannot be empty.
1067 // Grammar: multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
1068 if (parseCommaSeparatedList(Token::r_paren, parseElt, false))
Chris Lattner7121b802018-07-04 20:45:39 -07001069 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001070
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001071 // Parse optional range sizes.
Uday Bondhugula1e500b42018-07-12 18:04:04 -07001072 // range-sizes ::= (`size` `(` dim-size (`,` dim-size)* `)`)?
1073 // dim-size ::= affine-expr | `min` `(` affine-expr (`,` affine-expr)+ `)`
1074 // TODO(bondhugula): support for min of several affine expressions.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001075 // TODO: check if sizes are non-negative whenever they are constant.
1076 SmallVector<AffineExpr *, 4> rangeSizes;
1077 if (consumeIf(Token::kw_size)) {
1078 // Location of the l_paren token (if it exists) for error reporting later.
1079 auto loc = getToken().getLoc();
1080 if (!consumeIf(Token::l_paren))
1081 return (emitError("expected '(' at start of affine map range"), nullptr);
1082
1083 auto parseRangeSize = [&]() -> ParseResult {
1084 auto *elt = parseAffineExpr();
1085 ParseResult res = elt ? ParseSuccess : ParseFailure;
1086 rangeSizes.push_back(elt);
1087 return res;
1088 };
1089
1090 setSymbolicParsing(true);
1091 if (parseCommaSeparatedList(Token::r_paren, parseRangeSize, false))
1092 return nullptr;
1093 if (exprs.size() > rangeSizes.size())
1094 return (emitError(loc, "fewer range sizes than range expressions"),
1095 nullptr);
1096 if (exprs.size() < rangeSizes.size())
1097 return (emitError(loc, "more range sizes than range expressions"),
1098 nullptr);
1099 }
1100
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001101 // Parsed a valid affine map.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001102 return builder.getAffineMap(dims.size(), symbols.size(), exprs, rangeSizes);
MLIR Teamf85a6262018-06-27 11:03:08 -07001103}
1104
Chris Lattner2e595eb2018-07-10 10:08:27 -07001105AffineMap *Parser::parseAffineMapInline() {
1106 return AffineMapParser(state).parseAffineMapInline();
1107}
1108
MLIR Teamf85a6262018-06-27 11:03:08 -07001109//===----------------------------------------------------------------------===//
Chris Lattner78276e32018-07-07 15:48:26 -07001110// SSA
Chris Lattner4c95a502018-06-23 16:03:42 -07001111//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001112
Chris Lattner78276e32018-07-07 15:48:26 -07001113/// Parse a SSA operand for an instruction or statement.
1114///
1115/// ssa-use ::= ssa-id | ssa-constant
1116///
1117ParseResult Parser::parseSSAUse() {
Chris Lattner48af7d12018-07-09 19:05:38 -07001118 if (getToken().is(Token::percent_identifier)) {
1119 StringRef name = getTokenSpelling().drop_front();
Chris Lattner78276e32018-07-07 15:48:26 -07001120 consumeToken(Token::percent_identifier);
1121 // TODO: Return this use.
1122 (void)name;
1123 return ParseSuccess;
1124 }
1125
1126 // TODO: Parse SSA constants.
1127
1128 return emitError("expected SSA operand");
1129}
1130
1131/// Parse a (possibly empty) list of SSA operands.
1132///
1133/// ssa-use-list ::= ssa-use (`,` ssa-use)*
1134/// ssa-use-list-opt ::= ssa-use-list?
1135///
1136ParseResult Parser::parseOptionalSSAUseList(Token::Kind endToken) {
1137 // TODO: Build and return this.
1138 return parseCommaSeparatedList(
1139 endToken, [&]() -> ParseResult { return parseSSAUse(); });
1140}
1141
1142/// Parse an SSA use with an associated type.
1143///
1144/// ssa-use-and-type ::= ssa-use `:` type
1145ParseResult Parser::parseSSAUseAndType() {
1146 if (parseSSAUse())
1147 return ParseFailure;
1148
1149 if (!consumeIf(Token::colon))
1150 return emitError("expected ':' and type for SSA operand");
1151
1152 if (!parseType())
1153 return ParseFailure;
1154
1155 return ParseSuccess;
1156}
1157
1158/// Parse a (possibly empty) list of SSA operands with types.
1159///
1160/// ssa-use-and-type-list ::= ssa-use-and-type (`,` ssa-use-and-type)*
1161///
1162ParseResult Parser::parseOptionalSSAUseAndTypeList(Token::Kind endToken) {
1163 // TODO: Build and return this.
1164 return parseCommaSeparatedList(
1165 endToken, [&]() -> ParseResult { return parseSSAUseAndType(); });
1166}
1167
Chris Lattnere79379a2018-06-22 10:39:19 -07001168
Chris Lattner48af7d12018-07-09 19:05:38 -07001169//===----------------------------------------------------------------------===//
1170// CFG Functions
1171//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001172
Chris Lattner4c95a502018-06-23 16:03:42 -07001173namespace {
Chris Lattner48af7d12018-07-09 19:05:38 -07001174/// This is a specialized parser for CFGFunction's, maintaining the state
1175/// transient to their bodies.
1176class CFGFunctionParser : public Parser {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001177public:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001178 CFGFunctionParser(ParserState &state, CFGFunction *function)
1179 : Parser(state), function(function), builder(function) {}
1180
1181 ParseResult parseFunctionBody();
1182
1183private:
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001184 CFGFunction *function;
1185 llvm::StringMap<std::pair<BasicBlock*, SMLoc>> blocksByName;
Chris Lattner48af7d12018-07-09 19:05:38 -07001186
1187 /// This builder intentionally shadows the builder in the base class, with a
1188 /// more specific builder type.
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001189 CFGFuncBuilder builder;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001190
Chris Lattner4c95a502018-06-23 16:03:42 -07001191 /// Get the basic block with the specified name, creating it if it doesn't
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001192 /// already exist. The location specified is the point of use, which allows
1193 /// us to diagnose references to blocks that are not defined precisely.
1194 BasicBlock *getBlockNamed(StringRef name, SMLoc loc) {
1195 auto &blockAndLoc = blocksByName[name];
1196 if (!blockAndLoc.first) {
Chris Lattner3a467cc2018-07-01 20:28:00 -07001197 blockAndLoc.first = new BasicBlock();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001198 blockAndLoc.second = loc;
Chris Lattner4c95a502018-06-23 16:03:42 -07001199 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001200 return blockAndLoc.first;
Chris Lattner4c95a502018-06-23 16:03:42 -07001201 }
Chris Lattner48af7d12018-07-09 19:05:38 -07001202
Chris Lattner48af7d12018-07-09 19:05:38 -07001203 ParseResult parseBasicBlock();
1204 OperationInst *parseCFGOperation();
1205 TerminatorInst *parseTerminator();
Chris Lattner4c95a502018-06-23 16:03:42 -07001206};
1207} // end anonymous namespace
1208
Chris Lattner48af7d12018-07-09 19:05:38 -07001209ParseResult CFGFunctionParser::parseFunctionBody() {
1210 if (!consumeIf(Token::l_brace))
1211 return emitError("expected '{' in CFG function");
1212
1213 // Make sure we have at least one block.
1214 if (getToken().is(Token::r_brace))
1215 return emitError("CFG functions must have at least one basic block");
Chris Lattner4c95a502018-06-23 16:03:42 -07001216
1217 // Parse the list of blocks.
1218 while (!consumeIf(Token::r_brace))
Chris Lattner48af7d12018-07-09 19:05:38 -07001219 if (parseBasicBlock())
Chris Lattner4c95a502018-06-23 16:03:42 -07001220 return ParseFailure;
1221
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001222 // Verify that all referenced blocks were defined. Iteration over a
1223 // StringMap isn't determinstic, but this is good enough for our purposes.
Chris Lattner48af7d12018-07-09 19:05:38 -07001224 for (auto &elt : blocksByName) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001225 auto *bb = elt.second.first;
Chris Lattner3a467cc2018-07-01 20:28:00 -07001226 if (!bb->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001227 return emitError(elt.second.second,
1228 "reference to an undefined basic block '" +
1229 elt.first() + "'");
1230 }
1231
Chris Lattner48af7d12018-07-09 19:05:38 -07001232 getModule()->functionList.push_back(function);
Chris Lattner4c95a502018-06-23 16:03:42 -07001233 return ParseSuccess;
1234}
1235
1236/// Basic block declaration.
1237///
1238/// basic-block ::= bb-label instruction* terminator-stmt
1239/// bb-label ::= bb-id bb-arg-list? `:`
1240/// bb-id ::= bare-id
1241/// bb-arg-list ::= `(` ssa-id-and-type-list? `)`
1242///
Chris Lattner48af7d12018-07-09 19:05:38 -07001243ParseResult CFGFunctionParser::parseBasicBlock() {
1244 SMLoc nameLoc = getToken().getLoc();
1245 auto name = getTokenSpelling();
Chris Lattner4c95a502018-06-23 16:03:42 -07001246 if (!consumeIf(Token::bare_identifier))
1247 return emitError("expected basic block name");
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001248
Chris Lattner48af7d12018-07-09 19:05:38 -07001249 auto *block = getBlockNamed(name, nameLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001250
1251 // If this block has already been parsed, then this is a redefinition with the
1252 // same block name.
Chris Lattner3a467cc2018-07-01 20:28:00 -07001253 if (block->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001254 return emitError(nameLoc, "redefinition of block '" + name.str() + "'");
1255
Chris Lattner3a467cc2018-07-01 20:28:00 -07001256 // Add the block to the function.
Chris Lattner48af7d12018-07-09 19:05:38 -07001257 function->push_back(block);
Chris Lattner4c95a502018-06-23 16:03:42 -07001258
Chris Lattner78276e32018-07-07 15:48:26 -07001259 // If an argument list is present, parse it.
1260 if (consumeIf(Token::l_paren)) {
1261 if (parseOptionalSSAUseAndTypeList(Token::r_paren))
1262 return ParseFailure;
1263
1264 // TODO: attach it.
1265 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001266
1267 if (!consumeIf(Token::colon))
1268 return emitError("expected ':' after basic block name");
1269
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001270 // Set the insertion point to the block we want to insert new operations into.
Chris Lattner48af7d12018-07-09 19:05:38 -07001271 builder.setInsertionPoint(block);
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001272
Chris Lattnered65a732018-06-28 20:45:33 -07001273 // Parse the list of operations that make up the body of the block.
Chris Lattner48af7d12018-07-09 19:05:38 -07001274 while (getToken().isNot(Token::kw_return, Token::kw_br)) {
1275 auto loc = getToken().getLoc();
1276 auto *inst = parseCFGOperation();
Chris Lattner3a467cc2018-07-01 20:28:00 -07001277 if (!inst)
Chris Lattnered65a732018-06-28 20:45:33 -07001278 return ParseFailure;
Chris Lattner3a467cc2018-07-01 20:28:00 -07001279
Chris Lattner21e67f62018-07-06 10:46:19 -07001280 // We just parsed an operation. If it is a recognized one, verify that it
1281 // is structurally as we expect. If not, produce an error with a reasonable
1282 // source location.
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001283 if (auto *opInfo = inst->getAbstractOperation(builder.getContext()))
Chris Lattner21e67f62018-07-06 10:46:19 -07001284 if (auto error = opInfo->verifyInvariants(inst))
1285 return emitError(loc, error);
Chris Lattnered65a732018-06-28 20:45:33 -07001286 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001287
Chris Lattner48af7d12018-07-09 19:05:38 -07001288 auto *term = parseTerminator();
Chris Lattner3a467cc2018-07-01 20:28:00 -07001289 if (!term)
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001290 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07001291
1292 return ParseSuccess;
1293}
1294
Chris Lattnered65a732018-06-28 20:45:33 -07001295/// Parse the CFG operation.
1296///
1297/// TODO(clattner): This is a change from the MLIR spec as written, it is an
1298/// experiment that will eliminate "builtin" instructions as a thing.
1299///
1300/// cfg-operation ::=
1301/// (ssa-id `=`)? string '(' ssa-use-list? ')' attribute-dict?
1302/// `:` function-type
1303///
Chris Lattner48af7d12018-07-09 19:05:38 -07001304OperationInst *CFGFunctionParser::parseCFGOperation() {
Chris Lattner78276e32018-07-07 15:48:26 -07001305 StringRef resultID;
Chris Lattner48af7d12018-07-09 19:05:38 -07001306 if (getToken().is(Token::percent_identifier)) {
1307 resultID = getTokenSpelling().drop_front();
Chris Lattner78276e32018-07-07 15:48:26 -07001308 consumeToken();
1309 if (!consumeIf(Token::equal))
1310 return (emitError("expected '=' after SSA name"), nullptr);
1311 }
Chris Lattnered65a732018-06-28 20:45:33 -07001312
Chris Lattner48af7d12018-07-09 19:05:38 -07001313 if (getToken().isNot(Token::string))
Chris Lattner3a467cc2018-07-01 20:28:00 -07001314 return (emitError("expected operation name in quotes"), nullptr);
Chris Lattnered65a732018-06-28 20:45:33 -07001315
Chris Lattner48af7d12018-07-09 19:05:38 -07001316 auto name = getToken().getStringValue();
Chris Lattnered65a732018-06-28 20:45:33 -07001317 if (name.empty())
Chris Lattner3a467cc2018-07-01 20:28:00 -07001318 return (emitError("empty operation name is invalid"), nullptr);
Chris Lattnered65a732018-06-28 20:45:33 -07001319
1320 consumeToken(Token::string);
1321
1322 if (!consumeIf(Token::l_paren))
Chris Lattner7121b802018-07-04 20:45:39 -07001323 return (emitError("expected '(' to start operand list"), nullptr);
Chris Lattnered65a732018-06-28 20:45:33 -07001324
Chris Lattner78276e32018-07-07 15:48:26 -07001325 // Parse the operand list.
1326 parseOptionalSSAUseList(Token::r_paren);
Chris Lattner7121b802018-07-04 20:45:39 -07001327
1328 SmallVector<NamedAttribute, 4> attributes;
Chris Lattner48af7d12018-07-09 19:05:38 -07001329 if (getToken().is(Token::l_brace)) {
Chris Lattner7121b802018-07-04 20:45:39 -07001330 if (parseAttributeDict(attributes))
1331 return nullptr;
1332 }
Chris Lattnered65a732018-06-28 20:45:33 -07001333
Chris Lattner78276e32018-07-07 15:48:26 -07001334 // TODO: Don't drop result name and operand names on the floor.
Chris Lattner1ac20cb2018-07-10 10:59:53 -07001335 auto nameId = builder.getIdentifier(name);
Chris Lattner48af7d12018-07-09 19:05:38 -07001336 return builder.createOperation(nameId, attributes);
Chris Lattnered65a732018-06-28 20:45:33 -07001337}
1338
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001339/// Parse the terminator instruction for a basic block.
1340///
1341/// terminator-stmt ::= `br` bb-id branch-use-list?
1342/// branch-use-list ::= `(` ssa-use-and-type-list? `)`
1343/// terminator-stmt ::=
1344/// `cond_br` ssa-use `,` bb-id branch-use-list? `,` bb-id branch-use-list?
1345/// terminator-stmt ::= `return` ssa-use-and-type-list?
1346///
Chris Lattner48af7d12018-07-09 19:05:38 -07001347TerminatorInst *CFGFunctionParser::parseTerminator() {
1348 switch (getToken().getKind()) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001349 default:
Chris Lattner3a467cc2018-07-01 20:28:00 -07001350 return (emitError("expected terminator at end of basic block"), nullptr);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001351
1352 case Token::kw_return:
1353 consumeToken(Token::kw_return);
Chris Lattner48af7d12018-07-09 19:05:38 -07001354 return builder.createReturnInst();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001355
1356 case Token::kw_br: {
1357 consumeToken(Token::kw_br);
Chris Lattner48af7d12018-07-09 19:05:38 -07001358 auto destBB = getBlockNamed(getTokenSpelling(), getToken().getLoc());
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001359 if (!consumeIf(Token::bare_identifier))
Chris Lattner3a467cc2018-07-01 20:28:00 -07001360 return (emitError("expected basic block name"), nullptr);
Chris Lattner48af7d12018-07-09 19:05:38 -07001361 return builder.createBranchInst(destBB);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001362 }
Chris Lattner78276e32018-07-07 15:48:26 -07001363 // TODO: cond_br.
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001364 }
1365}
1366
Chris Lattner48af7d12018-07-09 19:05:38 -07001367//===----------------------------------------------------------------------===//
1368// ML Functions
1369//===----------------------------------------------------------------------===//
1370
1371namespace {
1372/// Refined parser for MLFunction bodies.
1373class MLFunctionParser : public Parser {
1374public:
1375 MLFunction *function;
1376
1377 /// This builder intentionally shadows the builder in the base class, with a
1378 /// more specific builder type.
1379 // TODO: MLFuncBuilder builder;
1380
1381 MLFunctionParser(ParserState &state, MLFunction *function)
1382 : Parser(state), function(function) {}
1383
1384 ParseResult parseFunctionBody();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001385
1386private:
1387 Statement *parseStatement();
1388 ForStmt *parseForStmt();
1389 IfStmt *parseIfStmt();
1390 ParseResult parseElseClause(IfClause *elseClause);
1391 ParseResult parseStmtBlock(StmtBlock *block);
Chris Lattner48af7d12018-07-09 19:05:38 -07001392};
1393} // end anonymous namespace
1394
Chris Lattner48af7d12018-07-09 19:05:38 -07001395ParseResult MLFunctionParser::parseFunctionBody() {
1396 if (!consumeIf(Token::l_brace))
1397 return emitError("expected '{' in ML function");
1398
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001399 // Make sure we have at least one statement.
Chris Lattner48af7d12018-07-09 19:05:38 -07001400 if (getToken().is(Token::r_brace))
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001401 return emitError("ML function must end with return statement");
1402
1403 // Parse the list of instructions.
1404 while (!consumeIf(Token::kw_return)) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001405 auto *stmt = parseStatement();
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001406 if (!stmt)
1407 return ParseFailure;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001408 function->push_back(stmt);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001409 }
1410
1411 // TODO: parse return statement operands
1412 if (!consumeIf(Token::r_brace))
1413 emitError("expected '}' in ML function");
1414
Chris Lattner48af7d12018-07-09 19:05:38 -07001415 getModule()->functionList.push_back(function);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001416
1417 return ParseSuccess;
1418}
1419
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001420/// Statement.
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001421///
Chris Lattner48af7d12018-07-09 19:05:38 -07001422/// ml-stmt ::= instruction | ml-for-stmt | ml-if-stmt
1423///
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001424/// TODO: fix terminology in MLSpec document. ML functions
1425/// contain operation statements, not instructions.
1426///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001427Statement *MLFunctionParser::parseStatement() {
Chris Lattner48af7d12018-07-09 19:05:38 -07001428 switch (getToken().getKind()) {
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001429 default:
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001430 //TODO: parse OperationStmt
1431 return (emitError("expected statement"), nullptr);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001432
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001433 case Token::kw_for:
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001434 return parseForStmt();
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001435
1436 case Token::kw_if:
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001437 return parseIfStmt();
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001438 }
1439}
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001440
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001441/// For statement.
1442///
Chris Lattner48af7d12018-07-09 19:05:38 -07001443/// ml-for-stmt ::= `for` ssa-id `=` lower-bound `to` upper-bound
1444/// (`step` integer-literal)? `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001445///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001446ForStmt *MLFunctionParser::parseForStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001447 consumeToken(Token::kw_for);
1448
1449 //TODO: parse loop header
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001450 ForStmt *stmt = new ForStmt();
1451 if (parseStmtBlock(static_cast<StmtBlock *>(stmt))) {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001452 delete stmt;
1453 return nullptr;
1454 }
1455 return stmt;
1456}
1457
1458/// If statement.
1459///
Chris Lattner48af7d12018-07-09 19:05:38 -07001460/// ml-if-head ::= `if` ml-if-cond `{` ml-stmt* `}`
1461/// | ml-if-head `else` `if` ml-if-cond `{` ml-stmt* `}`
1462/// ml-if-stmt ::= ml-if-head
1463/// | ml-if-head `else` `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001464///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001465IfStmt *MLFunctionParser::parseIfStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001466 consumeToken(Token::kw_if);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001467 if (!consumeIf(Token::l_paren))
1468 return (emitError("expected ("), nullptr);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001469
1470 //TODO: parse condition
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001471
1472 if (!consumeIf(Token::r_paren))
1473 return (emitError("expected )"), nullptr);
1474
1475 IfStmt *ifStmt = new IfStmt();
1476 IfClause *thenClause = ifStmt->getThenClause();
1477 if (parseStmtBlock(thenClause)) {
1478 delete ifStmt;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001479 return nullptr;
1480 }
1481
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001482 if (consumeIf(Token::kw_else)) {
1483 IfClause *elseClause = ifStmt->createElseClause();
1484 if (parseElseClause(elseClause)) {
1485 delete ifStmt;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001486 return nullptr;
1487 }
1488 }
1489
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001490 return ifStmt;
1491}
1492
1493ParseResult MLFunctionParser::parseElseClause(IfClause *elseClause) {
1494 if (getToken().is(Token::kw_if)) {
1495 IfStmt *nextIf = parseIfStmt();
1496 if (!nextIf)
1497 return ParseFailure;
1498 elseClause->push_back(nextIf);
1499 return ParseSuccess;
1500 }
1501
1502 if (parseStmtBlock(elseClause))
1503 return ParseFailure;
1504
1505 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001506}
1507
1508///
1509/// Parse `{` ml-stmt* `}`
1510///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001511ParseResult MLFunctionParser::parseStmtBlock(StmtBlock *block) {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001512 if (!consumeIf(Token::l_brace))
1513 return emitError("expected '{' before statement list");
1514
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001515 while (!consumeIf(Token::r_brace)) {
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001516 auto *stmt = parseStatement();
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001517 if (!stmt)
1518 return ParseFailure;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07001519 block->push_back(stmt);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001520 }
1521
1522 return ParseSuccess;
1523}
1524
Chris Lattner4c95a502018-06-23 16:03:42 -07001525//===----------------------------------------------------------------------===//
1526// Top-level entity parsing.
1527//===----------------------------------------------------------------------===//
1528
Chris Lattner2e595eb2018-07-10 10:08:27 -07001529namespace {
1530/// This parser handles entities that are only valid at the top level of the
1531/// file.
1532class ModuleParser : public Parser {
1533public:
1534 explicit ModuleParser(ParserState &state) : Parser(state) {}
1535
1536 ParseResult parseModule();
1537
1538private:
1539 ParseResult parseAffineMapDef();
1540
1541 // Functions.
1542 ParseResult parseFunctionSignature(StringRef &name, FunctionType *&type);
1543 ParseResult parseExtFunc();
1544 ParseResult parseCFGFunc();
1545 ParseResult parseMLFunc();
1546};
1547} // end anonymous namespace
1548
1549/// Affine map declaration.
1550///
1551/// affine-map-def ::= affine-map-id `=` affine-map-inline
1552///
1553ParseResult ModuleParser::parseAffineMapDef() {
1554 assert(getToken().is(Token::hash_identifier));
1555
1556 StringRef affineMapId = getTokenSpelling().drop_front();
1557
1558 // Check for redefinitions.
1559 auto *&entry = getState().affineMapDefinitions[affineMapId];
1560 if (entry)
1561 return emitError("redefinition of affine map id '" + affineMapId + "'");
1562
1563 consumeToken(Token::hash_identifier);
1564
1565 // Parse the '='
1566 if (!consumeIf(Token::equal))
1567 return emitError("expected '=' in affine map outlined definition");
1568
1569 entry = parseAffineMapInline();
1570 if (!entry)
1571 return ParseFailure;
1572
1573 getModule()->affineMapList.push_back(entry);
1574 return ParseSuccess;
1575}
1576
1577/// Parse a function signature, starting with a name and including the parameter
1578/// list.
1579///
1580/// argument-list ::= type (`,` type)* | /*empty*/
1581/// function-signature ::= function-id `(` argument-list `)` (`->` type-list)?
1582///
1583ParseResult ModuleParser::parseFunctionSignature(StringRef &name,
1584 FunctionType *&type) {
1585 if (getToken().isNot(Token::at_identifier))
1586 return emitError("expected a function identifier like '@foo'");
1587
1588 name = getTokenSpelling().drop_front();
1589 consumeToken(Token::at_identifier);
1590
1591 if (getToken().isNot(Token::l_paren))
1592 return emitError("expected '(' in function signature");
1593
1594 SmallVector<Type *, 4> arguments;
1595 if (parseTypeList(arguments))
1596 return ParseFailure;
1597
1598 // Parse the return type if present.
1599 SmallVector<Type *, 4> results;
1600 if (consumeIf(Token::arrow)) {
1601 if (parseTypeList(results))
1602 return ParseFailure;
1603 }
1604 type = builder.getFunctionType(arguments, results);
1605 return ParseSuccess;
1606}
1607
1608/// External function declarations.
1609///
1610/// ext-func ::= `extfunc` function-signature
1611///
1612ParseResult ModuleParser::parseExtFunc() {
1613 consumeToken(Token::kw_extfunc);
1614
1615 StringRef name;
1616 FunctionType *type = nullptr;
1617 if (parseFunctionSignature(name, type))
1618 return ParseFailure;
1619
1620 // Okay, the external function definition was parsed correctly.
1621 getModule()->functionList.push_back(new ExtFunction(name, type));
1622 return ParseSuccess;
1623}
1624
1625/// CFG function declarations.
1626///
1627/// cfg-func ::= `cfgfunc` function-signature `{` basic-block+ `}`
1628///
1629ParseResult ModuleParser::parseCFGFunc() {
1630 consumeToken(Token::kw_cfgfunc);
1631
1632 StringRef name;
1633 FunctionType *type = nullptr;
1634 if (parseFunctionSignature(name, type))
1635 return ParseFailure;
1636
1637 // Okay, the CFG function signature was parsed correctly, create the function.
1638 auto function = new CFGFunction(name, type);
1639
1640 return CFGFunctionParser(getState(), function).parseFunctionBody();
1641}
1642
1643/// ML function declarations.
1644///
1645/// ml-func ::= `mlfunc` ml-func-signature `{` ml-stmt* ml-return-stmt `}`
1646///
1647ParseResult ModuleParser::parseMLFunc() {
1648 consumeToken(Token::kw_mlfunc);
1649
1650 StringRef name;
1651 FunctionType *type = nullptr;
1652
1653 // FIXME: Parse ML function signature (args + types)
1654 // by passing pointer to SmallVector<identifier> into parseFunctionSignature
1655 if (parseFunctionSignature(name, type))
1656 return ParseFailure;
1657
1658 // Okay, the ML function signature was parsed correctly, create the function.
1659 auto function = new MLFunction(name, type);
1660
1661 return MLFunctionParser(getState(), function).parseFunctionBody();
1662}
1663
Chris Lattnere79379a2018-06-22 10:39:19 -07001664/// This is the top-level module parser.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001665ParseResult ModuleParser::parseModule() {
Chris Lattnere79379a2018-06-22 10:39:19 -07001666 while (1) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001667 switch (getToken().getKind()) {
Chris Lattnere79379a2018-06-22 10:39:19 -07001668 default:
1669 emitError("expected a top level entity");
Chris Lattner2e595eb2018-07-10 10:08:27 -07001670 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07001671
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001672 // If we got to the end of the file, then we're done.
Chris Lattnere79379a2018-06-22 10:39:19 -07001673 case Token::eof:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001674 return ParseSuccess;
Chris Lattnere79379a2018-06-22 10:39:19 -07001675
1676 // If we got an error token, then the lexer already emitted an error, just
1677 // stop. Someday we could introduce error recovery if there was demand for
1678 // it.
1679 case Token::error:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001680 return ParseFailure;
1681
1682 case Token::hash_identifier:
1683 if (parseAffineMapDef())
1684 return ParseFailure;
1685 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07001686
1687 case Token::kw_extfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001688 if (parseExtFunc())
1689 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07001690 break;
1691
Chris Lattner4c95a502018-06-23 16:03:42 -07001692 case Token::kw_cfgfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001693 if (parseCFGFunc())
1694 return ParseFailure;
MLIR Teamf85a6262018-06-27 11:03:08 -07001695 break;
Chris Lattner4c95a502018-06-23 16:03:42 -07001696
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001697 case Token::kw_mlfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001698 if (parseMLFunc())
1699 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001700 break;
1701
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001702 // TODO: affine entity declarations, etc.
Chris Lattnere79379a2018-06-22 10:39:19 -07001703 }
1704 }
1705}
1706
1707//===----------------------------------------------------------------------===//
1708
Jacques Pienaar7b829702018-07-03 13:24:09 -07001709void mlir::defaultErrorReporter(const llvm::SMDiagnostic &error) {
1710 const auto &sourceMgr = *error.getSourceMgr();
1711 sourceMgr.PrintMessage(error.getLoc(), error.getKind(), error.getMessage());
1712}
1713
Chris Lattnere79379a2018-06-22 10:39:19 -07001714/// This parses the file specified by the indicated SourceMgr and returns an
1715/// MLIR module if it was valid. If not, it emits diagnostics and returns null.
Jacques Pienaar9c411be2018-06-24 19:17:35 -07001716Module *mlir::parseSourceFile(llvm::SourceMgr &sourceMgr, MLIRContext *context,
Jacques Pienaar7b829702018-07-03 13:24:09 -07001717 SMDiagnosticHandlerTy errorReporter) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001718 // This is the result module we are parsing into.
1719 std::unique_ptr<Module> module(new Module(context));
1720
1721 ParserState state(sourceMgr, module.get(),
Jacques Pienaar0bffd862018-07-11 13:26:23 -07001722 errorReporter ? errorReporter : defaultErrorReporter);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001723 if (ModuleParser(state).parseModule())
1724 return nullptr;
Chris Lattner21e67f62018-07-06 10:46:19 -07001725
1726 // Make sure the parse module has no other structural problems detected by the
1727 // verifier.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001728 module->verify();
1729 return module.release();
Chris Lattnere79379a2018-06-22 10:39:19 -07001730}