blob: 62f4b992dea029981ac0b3655588674446c72638 [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"
Chris Lattnerf7e22732018-06-22 22:03:48 -070031#include "mlir/IR/Types.h"
Chris Lattnere79379a2018-06-22 10:39:19 -070032#include "llvm/Support/SourceMgr.h"
33using namespace mlir;
34using llvm::SourceMgr;
Chris Lattner4c95a502018-06-23 16:03:42 -070035using llvm::SMLoc;
Chris Lattnere79379a2018-06-22 10:39:19 -070036
37namespace {
Chris Lattner4c95a502018-06-23 16:03:42 -070038class CFGFunctionParserState;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -070039class AffineMapParserState;
Chris Lattner4c95a502018-06-23 16:03:42 -070040
Chris Lattnerf7e22732018-06-22 22:03:48 -070041/// Simple enum to make code read better in cases that would otherwise return a
42/// bool value. Failure is "true" in a boolean context.
Chris Lattnere79379a2018-06-22 10:39:19 -070043enum ParseResult {
44 ParseSuccess,
45 ParseFailure
46};
47
Uday Bondhugula015cbb12018-07-03 20:16:08 -070048/// Lower precedence ops (all at the same precedence level). LNoOp is false in
49/// the boolean sense.
50enum AffineLowPrecOp {
51 /// Null value.
52 LNoOp,
53 Add,
54 Sub
55};
56
57/// Higher precedence ops - all at the same precedence level. HNoOp is false in
58/// the boolean sense.
59enum AffineHighPrecOp {
60 /// Null value.
61 HNoOp,
62 Mul,
63 FloorDiv,
64 CeilDiv,
65 Mod
66};
67
Chris Lattnere79379a2018-06-22 10:39:19 -070068/// Main parser implementation.
69class Parser {
Chris Lattnered65a732018-06-28 20:45:33 -070070public:
Jacques Pienaar9c411be2018-06-24 19:17:35 -070071 Parser(llvm::SourceMgr &sourceMgr, MLIRContext *context,
Jacques Pienaar7b829702018-07-03 13:24:09 -070072 SMDiagnosticHandlerTy errorReporter)
Chris Lattner158e0a3e2018-07-08 20:51:38 -070073 : builder(context), lex(sourceMgr, errorReporter),
Jacques Pienaar7b829702018-07-03 13:24:09 -070074 curToken(lex.lexToken()), errorReporter(std::move(errorReporter)) {
Chris Lattner158e0a3e2018-07-08 20:51:38 -070075 module.reset(new Module(context));
Chris Lattnere79379a2018-06-22 10:39:19 -070076 }
77
78 Module *parseModule();
79private:
80 // State.
Chris Lattner158e0a3e2018-07-08 20:51:38 -070081 Builder builder;
Chris Lattnerf7e22732018-06-22 22:03:48 -070082
83 // The lexer for the source file we're parsing.
Chris Lattnere79379a2018-06-22 10:39:19 -070084 Lexer lex;
85
86 // This is the next token that hasn't been consumed yet.
87 Token curToken;
88
Jacques Pienaar9c411be2018-06-24 19:17:35 -070089 // The diagnostic error reporter.
Jacques Pienaar7b829702018-07-03 13:24:09 -070090 SMDiagnosticHandlerTy errorReporter;
Jacques Pienaar9c411be2018-06-24 19:17:35 -070091
Chris Lattnere79379a2018-06-22 10:39:19 -070092 // This is the result module we are parsing into.
93 std::unique_ptr<Module> module;
94
MLIR Teamf85a6262018-06-27 11:03:08 -070095 // A map from affine map identifier to AffineMap.
Chris Lattner7121b802018-07-04 20:45:39 -070096 llvm::StringMap<AffineMap*> affineMapDefinitions;
MLIR Teamf85a6262018-06-27 11:03:08 -070097
Chris Lattnere79379a2018-06-22 10:39:19 -070098private:
99 // Helper methods.
100
101 /// Emit an error and return failure.
Chris Lattner4c95a502018-06-23 16:03:42 -0700102 ParseResult emitError(const Twine &message) {
103 return emitError(curToken.getLoc(), message);
104 }
105 ParseResult emitError(SMLoc loc, const Twine &message);
Chris Lattnere79379a2018-06-22 10:39:19 -0700106
107 /// Advance the current lexer onto the next token.
108 void consumeToken() {
109 assert(curToken.isNot(Token::eof, Token::error) &&
110 "shouldn't advance past EOF or errors");
111 curToken = lex.lexToken();
112 }
113
114 /// Advance the current lexer onto the next token, asserting what the expected
115 /// current token is. This is preferred to the above method because it leads
116 /// to more self-documenting code with better checking.
Chris Lattner8da0c282018-06-29 11:15:56 -0700117 void consumeToken(Token::Kind kind) {
Chris Lattnere79379a2018-06-22 10:39:19 -0700118 assert(curToken.is(kind) && "consumed an unexpected token");
119 consumeToken();
120 }
121
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700122 /// If the current token has the specified kind, consume it and return true.
123 /// If not, return false.
Chris Lattner8da0c282018-06-29 11:15:56 -0700124 bool consumeIf(Token::Kind kind) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700125 if (curToken.isNot(kind))
126 return false;
127 consumeToken(kind);
128 return true;
129 }
130
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700131 // Binary affine op parsing
132 AffineLowPrecOp consumeIfLowPrecOp();
133 AffineHighPrecOp consumeIfHighPrecOp();
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 // Parsing identifiers' lists for polyhedral structures.
160 ParseResult parseDimIdList(AffineMapParserState &state);
161 ParseResult parseSymbolIdList(AffineMapParserState &state);
162 ParseResult parseDimOrSymbolId(AffineMapParserState &state, bool dim);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700163
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700164 // Polyhedral structures.
MLIR Teamf85a6262018-06-27 11:03:08 -0700165 ParseResult parseAffineMapDef();
Chris Lattner7121b802018-07-04 20:45:39 -0700166 AffineMap *parseAffineMapInline(StringRef mapId);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700167 AffineExpr *parseAffineExpr(const AffineMapParserState &state);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700168 AffineExpr *parseParentheticalExpr(const AffineMapParserState &state);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700169 AffineExpr *parseNegateExpression(AffineExpr *lhs,
170 const AffineMapParserState &state);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700171 AffineExpr *parseIntegerExpr(const AffineMapParserState &state);
172 AffineExpr *parseBareIdExpr(const AffineMapParserState &state);
173
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700174 AffineExpr *getBinaryAffineOpExpr(AffineHighPrecOp op, AffineExpr *lhs,
175 AffineExpr *rhs);
176 AffineExpr *getBinaryAffineOpExpr(AffineLowPrecOp op, AffineExpr *lhs,
177 AffineExpr *rhs);
178 AffineExpr *parseAffineOperandExpr(AffineExpr *lhs,
179 const AffineMapParserState &state);
180 AffineExpr *parseAffineLowPrecOpExpr(AffineExpr *llhs, AffineLowPrecOp llhsOp,
181 const AffineMapParserState &state);
182 AffineExpr *parseAffineHighPrecOpExpr(AffineExpr *llhs,
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700183 AffineHighPrecOp llhsOp,
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700184 const AffineMapParserState &state);
MLIR Teamf85a6262018-06-27 11:03:08 -0700185
Chris Lattner78276e32018-07-07 15:48:26 -0700186 // SSA
187 ParseResult parseSSAUse();
188 ParseResult parseOptionalSSAUseList(Token::Kind endToken);
189 ParseResult parseSSAUseAndType();
190 ParseResult parseOptionalSSAUseAndTypeList(Token::Kind endToken);
191
Chris Lattner4c95a502018-06-23 16:03:42 -0700192 // Functions.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700193 ParseResult parseFunctionSignature(StringRef &name, FunctionType *&type);
Chris Lattnere79379a2018-06-22 10:39:19 -0700194 ParseResult parseExtFunc();
Chris Lattner4c95a502018-06-23 16:03:42 -0700195 ParseResult parseCFGFunc();
196 ParseResult parseBasicBlock(CFGFunctionParserState &functionState);
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700197 Statement *parseStatement(ParentType parent);
Chris Lattnerf6d80a02018-06-24 11:18:29 -0700198
Chris Lattner3a467cc2018-07-01 20:28:00 -0700199 OperationInst *parseCFGOperation(CFGFunctionParserState &functionState);
200 TerminatorInst *parseTerminator(CFGFunctionParserState &functionState);
Chris Lattnered65a732018-06-28 20:45:33 -0700201
Chris Lattner78276e32018-07-07 15:48:26 -0700202 ParseResult parseMLFunc();
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -0700203 ForStmt *parseForStmt(ParentType parent);
204 IfStmt *parseIfStmt(ParentType parent);
205 ParseResult parseNestedStatements(NodeStmt *parent);
Chris Lattnere79379a2018-06-22 10:39:19 -0700206};
207} // end anonymous namespace
208
209//===----------------------------------------------------------------------===//
210// Helper methods.
211//===----------------------------------------------------------------------===//
212
Chris Lattner4c95a502018-06-23 16:03:42 -0700213ParseResult Parser::emitError(SMLoc loc, const Twine &message) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700214 // If we hit a parse error in response to a lexer error, then the lexer
Jacques Pienaar9c411be2018-06-24 19:17:35 -0700215 // already reported the error.
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700216 if (curToken.is(Token::error))
217 return ParseFailure;
218
Jacques Pienaar9c411be2018-06-24 19:17:35 -0700219 errorReporter(
220 lex.getSourceMgr().GetMessage(loc, SourceMgr::DK_Error, message));
Chris Lattnere79379a2018-06-22 10:39:19 -0700221 return ParseFailure;
222}
223
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700224/// Parse a comma-separated list of elements, terminated with an arbitrary
225/// token. This allows empty lists if allowEmptyList is true.
226///
227/// abstract-list ::= rightToken // if allowEmptyList == true
228/// abstract-list ::= element (',' element)* rightToken
229///
230ParseResult Parser::
Chris Lattner8da0c282018-06-29 11:15:56 -0700231parseCommaSeparatedList(Token::Kind rightToken,
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700232 const std::function<ParseResult()> &parseElement,
233 bool allowEmptyList) {
234 // Handle the empty case.
235 if (curToken.is(rightToken)) {
236 if (!allowEmptyList)
237 return emitError("expected list element");
238 consumeToken(rightToken);
239 return ParseSuccess;
240 }
241
242 // Non-empty case starts with an element.
243 if (parseElement())
244 return ParseFailure;
245
246 // Otherwise we have a list of comma separated elements.
247 while (consumeIf(Token::comma)) {
248 if (parseElement())
249 return ParseFailure;
250 }
251
252 // Consume the end character.
253 if (!consumeIf(rightToken))
Chris Lattner8da0c282018-06-29 11:15:56 -0700254 return emitError("expected ',' or '" + Token::getTokenSpelling(rightToken) +
255 "'");
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700256
257 return ParseSuccess;
258}
Chris Lattnere79379a2018-06-22 10:39:19 -0700259
260//===----------------------------------------------------------------------===//
261// Type Parsing
262//===----------------------------------------------------------------------===//
263
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700264/// Parse the low-level fixed dtypes in the system.
265///
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700266/// primitive-type ::= `f16` | `bf16` | `f32` | `f64`
267/// primitive-type ::= integer-type
268/// primitive-type ::= `affineint`
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700269///
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700270Type *Parser::parsePrimitiveType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700271 switch (curToken.getKind()) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700272 default:
273 return (emitError("expected type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700274 case Token::kw_bf16:
275 consumeToken(Token::kw_bf16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700276 return builder.getBF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700277 case Token::kw_f16:
278 consumeToken(Token::kw_f16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700279 return builder.getF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700280 case Token::kw_f32:
281 consumeToken(Token::kw_f32);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700282 return builder.getF32Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700283 case Token::kw_f64:
284 consumeToken(Token::kw_f64);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700285 return builder.getF64Type();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700286 case Token::kw_affineint:
287 consumeToken(Token::kw_affineint);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700288 return builder.getAffineIntType();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700289 case Token::inttype: {
290 auto width = curToken.getIntTypeBitwidth();
291 if (!width.hasValue())
292 return (emitError("invalid integer width"), nullptr);
293 consumeToken(Token::inttype);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700294 return builder.getIntegerType(width.getValue());
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700295 }
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700296 }
297}
298
299/// Parse the element type of a tensor or memref type.
300///
301/// element-type ::= primitive-type | vector-type
302///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700303Type *Parser::parseElementType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700304 if (curToken.is(Token::kw_vector))
305 return parseVectorType();
306
307 return parsePrimitiveType();
308}
309
310/// Parse a vector type.
311///
312/// vector-type ::= `vector` `<` const-dimension-list primitive-type `>`
313/// const-dimension-list ::= (integer-literal `x`)+
314///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700315VectorType *Parser::parseVectorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700316 consumeToken(Token::kw_vector);
317
318 if (!consumeIf(Token::less))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700319 return (emitError("expected '<' in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700320
321 if (curToken.isNot(Token::integer))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700322 return (emitError("expected dimension size in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700323
324 SmallVector<unsigned, 4> dimensions;
325 while (curToken.is(Token::integer)) {
326 // Make sure this integer value is in bound and valid.
327 auto dimension = curToken.getUnsignedIntegerValue();
328 if (!dimension.hasValue())
Chris Lattnerf7e22732018-06-22 22:03:48 -0700329 return (emitError("invalid dimension in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700330 dimensions.push_back(dimension.getValue());
331
332 consumeToken(Token::integer);
333
334 // Make sure we have an 'x' or something like 'xbf32'.
335 if (curToken.isNot(Token::bare_identifier) ||
336 curToken.getSpelling()[0] != 'x')
Chris Lattnerf7e22732018-06-22 22:03:48 -0700337 return (emitError("expected 'x' in vector dimension list"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700338
339 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
340 if (curToken.getSpelling().size() != 1)
341 lex.resetPointer(curToken.getSpelling().data()+1);
342
343 // Consume the 'x'.
344 consumeToken(Token::bare_identifier);
345 }
346
347 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700348 auto *elementType = parsePrimitiveType();
349 if (!elementType)
350 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700351
352 if (!consumeIf(Token::greater))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700353 return (emitError("expected '>' in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700354
Chris Lattnerf7e22732018-06-22 22:03:48 -0700355 return VectorType::get(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700356}
357
358/// Parse a dimension list of a tensor or memref type. This populates the
359/// dimension list, returning -1 for the '?' dimensions.
360///
361/// dimension-list-ranked ::= (dimension `x`)*
362/// dimension ::= `?` | integer-literal
363///
364ParseResult Parser::parseDimensionListRanked(SmallVectorImpl<int> &dimensions) {
365 while (curToken.isAny(Token::integer, Token::question)) {
366 if (consumeIf(Token::question)) {
367 dimensions.push_back(-1);
368 } else {
369 // Make sure this integer value is in bound and valid.
370 auto dimension = curToken.getUnsignedIntegerValue();
371 if (!dimension.hasValue() || (int)dimension.getValue() < 0)
372 return emitError("invalid dimension");
373 dimensions.push_back((int)dimension.getValue());
374 consumeToken(Token::integer);
375 }
376
377 // Make sure we have an 'x' or something like 'xbf32'.
378 if (curToken.isNot(Token::bare_identifier) ||
379 curToken.getSpelling()[0] != 'x')
380 return emitError("expected 'x' in dimension list");
381
382 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
383 if (curToken.getSpelling().size() != 1)
384 lex.resetPointer(curToken.getSpelling().data()+1);
385
386 // Consume the 'x'.
387 consumeToken(Token::bare_identifier);
388 }
389
390 return ParseSuccess;
391}
392
393/// Parse a tensor type.
394///
395/// tensor-type ::= `tensor` `<` dimension-list element-type `>`
396/// dimension-list ::= dimension-list-ranked | `??`
397///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700398Type *Parser::parseTensorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700399 consumeToken(Token::kw_tensor);
400
401 if (!consumeIf(Token::less))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700402 return (emitError("expected '<' in tensor type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700403
404 bool isUnranked;
405 SmallVector<int, 4> dimensions;
406
407 if (consumeIf(Token::questionquestion)) {
408 isUnranked = true;
409 } else {
410 isUnranked = false;
411 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700412 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700413 }
414
415 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700416 auto elementType = parseElementType();
417 if (!elementType)
418 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700419
420 if (!consumeIf(Token::greater))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700421 return (emitError("expected '>' in tensor type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700422
MLIR Team355ec862018-06-23 18:09:09 -0700423 if (isUnranked)
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700424 return builder.getTensorType(elementType);
425 return builder.getTensorType(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700426}
427
428/// Parse a memref type.
429///
430/// memref-type ::= `memref` `<` dimension-list-ranked element-type
431/// (`,` semi-affine-map-composition)? (`,` memory-space)? `>`
432///
433/// semi-affine-map-composition ::= (semi-affine-map `,` )* semi-affine-map
434/// memory-space ::= integer-literal /* | TODO: address-space-id */
435///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700436Type *Parser::parseMemRefType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700437 consumeToken(Token::kw_memref);
438
439 if (!consumeIf(Token::less))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700440 return (emitError("expected '<' in memref type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700441
442 SmallVector<int, 4> dimensions;
443 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700444 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700445
446 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700447 auto elementType = parseElementType();
448 if (!elementType)
449 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700450
451 // TODO: Parse semi-affine-map-composition.
452 // TODO: Parse memory-space.
453
454 if (!consumeIf(Token::greater))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700455 return (emitError("expected '>' in memref type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700456
Chris Lattnerf7e22732018-06-22 22:03:48 -0700457 // FIXME: Add an IR representation for memref types.
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700458 return builder.getIntegerType(1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700459}
460
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700461/// Parse a function type.
462///
463/// function-type ::= type-list-parens `->` type-list
464///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700465Type *Parser::parseFunctionType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700466 assert(curToken.is(Token::l_paren));
467
Chris Lattnerf7e22732018-06-22 22:03:48 -0700468 SmallVector<Type*, 4> arguments;
469 if (parseTypeList(arguments))
470 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700471
472 if (!consumeIf(Token::arrow))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700473 return (emitError("expected '->' in function type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700474
Chris Lattnerf7e22732018-06-22 22:03:48 -0700475 SmallVector<Type*, 4> results;
476 if (parseTypeList(results))
477 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700478
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700479 return builder.getFunctionType(arguments, results);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700480}
481
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700482/// Parse an arbitrary type.
483///
484/// type ::= primitive-type
485/// | vector-type
486/// | tensor-type
487/// | memref-type
488/// | function-type
489/// element-type ::= primitive-type | vector-type
490///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700491Type *Parser::parseType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700492 switch (curToken.getKind()) {
493 case Token::kw_memref: return parseMemRefType();
494 case Token::kw_tensor: return parseTensorType();
495 case Token::kw_vector: return parseVectorType();
496 case Token::l_paren: return parseFunctionType();
497 default:
498 return parsePrimitiveType();
499 }
500}
501
502/// Parse a "type list", which is a singular type, or a parenthesized list of
503/// types.
504///
505/// type-list ::= type-list-parens | type
506/// type-list-parens ::= `(` `)`
507/// | `(` type (`,` type)* `)`
508///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700509ParseResult Parser::parseTypeList(SmallVectorImpl<Type*> &elements) {
510 auto parseElt = [&]() -> ParseResult {
511 auto elt = parseType();
512 elements.push_back(elt);
513 return elt ? ParseSuccess : ParseFailure;
514 };
515
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700516 // If there is no parens, then it must be a singular type.
517 if (!consumeIf(Token::l_paren))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700518 return parseElt();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700519
Chris Lattnerf7e22732018-06-22 22:03:48 -0700520 if (parseCommaSeparatedList(Token::r_paren, parseElt))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700521 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700522
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700523 return ParseSuccess;
524}
525
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700526namespace {
527/// This class represents the transient parser state while parsing an affine
528/// expression.
529class AffineMapParserState {
530 public:
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700531 explicit AffineMapParserState() {}
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700532
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700533 void addDim(StringRef sRef) { dims.insert({sRef, dims.size()}); }
534 void addSymbol(StringRef sRef) { symbols.insert({sRef, symbols.size()}); }
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700535
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700536 unsigned getNumDims() const { return dims.size(); }
537 unsigned getNumSymbols() const { return symbols.size(); }
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700538
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700539 // TODO(bondhugula): could just use an vector/ArrayRef and scan the numbers.
540 const llvm::StringMap<unsigned> &getDims() const { return dims; }
541 const llvm::StringMap<unsigned> &getSymbols() const { return symbols; }
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700542
543 private:
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700544 llvm::StringMap<unsigned> dims;
545 llvm::StringMap<unsigned> symbols;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700546};
547} // end anonymous namespace
548
Chris Lattner4c95a502018-06-23 16:03:42 -0700549//===----------------------------------------------------------------------===//
Chris Lattner7121b802018-07-04 20:45:39 -0700550// Attribute parsing.
551//===----------------------------------------------------------------------===//
552
553
554/// Attribute parsing.
555///
556/// attribute-value ::= bool-literal
557/// | integer-literal
558/// | float-literal
559/// | string-literal
560/// | `[` (attribute-value (`,` attribute-value)*)? `]`
561///
562Attribute *Parser::parseAttribute() {
563 switch (curToken.getKind()) {
564 case Token::kw_true:
565 consumeToken(Token::kw_true);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700566 return BoolAttr::get(true, builder.getContext());
Chris Lattner7121b802018-07-04 20:45:39 -0700567 case Token::kw_false:
568 consumeToken(Token::kw_false);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700569 return BoolAttr::get(false, builder.getContext());
Chris Lattner7121b802018-07-04 20:45:39 -0700570
571 case Token::integer: {
572 auto val = curToken.getUInt64IntegerValue();
573 if (!val.hasValue() || (int64_t)val.getValue() < 0)
574 return (emitError("integer too large for attribute"), nullptr);
575 consumeToken(Token::integer);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700576 return IntegerAttr::get((int64_t)val.getValue(), builder.getContext());
Chris Lattner7121b802018-07-04 20:45:39 -0700577 }
578
579 case Token::minus: {
580 consumeToken(Token::minus);
581 if (curToken.is(Token::integer)) {
582 auto val = curToken.getUInt64IntegerValue();
583 if (!val.hasValue() || (int64_t)-val.getValue() >= 0)
584 return (emitError("integer too large for attribute"), nullptr);
585 consumeToken(Token::integer);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700586 return IntegerAttr::get((int64_t)-val.getValue(), builder.getContext());
Chris Lattner7121b802018-07-04 20:45:39 -0700587 }
588
589 return (emitError("expected constant integer or floating point value"),
590 nullptr);
591 }
592
593 case Token::string: {
594 auto val = curToken.getStringValue();
595 consumeToken(Token::string);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700596 return StringAttr::get(val, builder.getContext());
Chris Lattner7121b802018-07-04 20:45:39 -0700597 }
598
599 case Token::l_bracket: {
600 consumeToken(Token::l_bracket);
601 SmallVector<Attribute*, 4> elements;
602
603 auto parseElt = [&]() -> ParseResult {
604 elements.push_back(parseAttribute());
605 return elements.back() ? ParseSuccess : ParseFailure;
606 };
607
608 if (parseCommaSeparatedList(Token::r_bracket, parseElt))
609 return nullptr;
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700610 return ArrayAttr::get(elements, builder.getContext());
Chris Lattner7121b802018-07-04 20:45:39 -0700611 }
612 default:
613 // TODO: Handle floating point.
614 return (emitError("expected constant attribute value"), nullptr);
615 }
616}
617
Chris Lattner7121b802018-07-04 20:45:39 -0700618/// Attribute dictionary.
619///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700620/// attribute-dict ::= `{` `}`
621/// | `{` attribute-entry (`,` attribute-entry)* `}`
622/// attribute-entry ::= bare-id `:` attribute-value
Chris Lattner7121b802018-07-04 20:45:39 -0700623///
624ParseResult Parser::parseAttributeDict(
625 SmallVectorImpl<NamedAttribute> &attributes) {
626 consumeToken(Token::l_brace);
627
628 auto parseElt = [&]() -> ParseResult {
629 // We allow keywords as attribute names.
630 if (curToken.isNot(Token::bare_identifier, Token::inttype) &&
631 !curToken.isKeyword())
632 return emitError("expected attribute name");
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700633 auto nameId = Identifier::get(curToken.getSpelling(), builder.getContext());
Chris Lattner7121b802018-07-04 20:45:39 -0700634 consumeToken();
635
636 if (!consumeIf(Token::colon))
637 return emitError("expected ':' in attribute list");
638
639 auto attr = parseAttribute();
640 if (!attr) return ParseFailure;
641
642 attributes.push_back({nameId, attr});
643 return ParseSuccess;
644 };
645
646 if (parseCommaSeparatedList(Token::r_brace, parseElt))
647 return ParseFailure;
648
649 return ParseSuccess;
650}
651
652//===----------------------------------------------------------------------===//
MLIR Teamf85a6262018-06-27 11:03:08 -0700653// Polyhedral structures.
654//===----------------------------------------------------------------------===//
655
656/// Affine map declaration.
657///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700658/// affine-map-def ::= affine-map-id `=` affine-map-inline
MLIR Teamf85a6262018-06-27 11:03:08 -0700659///
660ParseResult Parser::parseAffineMapDef() {
Chris Lattner78276e32018-07-07 15:48:26 -0700661 assert(curToken.is(Token::hash_identifier));
MLIR Teamf85a6262018-06-27 11:03:08 -0700662
663 StringRef affineMapId = curToken.getSpelling().drop_front();
Chris Lattner7121b802018-07-04 20:45:39 -0700664
665 // Check for redefinitions.
666 auto *&entry = affineMapDefinitions[affineMapId];
667 if (entry)
668 return emitError("redefinition of affine map id '" + affineMapId + "'");
669
Chris Lattner78276e32018-07-07 15:48:26 -0700670 consumeToken(Token::hash_identifier);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700671
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700672 // Parse the '='
673 if (!consumeIf(Token::equal))
674 return emitError("expected '=' in affine map outlined definition");
MLIR Teamf85a6262018-06-27 11:03:08 -0700675
Chris Lattner7121b802018-07-04 20:45:39 -0700676 entry = parseAffineMapInline(affineMapId);
677 if (!entry)
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700678 return ParseFailure;
MLIR Teamf85a6262018-06-27 11:03:08 -0700679
Chris Lattner7121b802018-07-04 20:45:39 -0700680 module->affineMapList.push_back(entry);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700681 return ParseSuccess;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700682}
683
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700684/// Create an affine binary high precedence op expression (mul's, div's, mod)
685AffineExpr *Parser::getBinaryAffineOpExpr(AffineHighPrecOp op, AffineExpr *lhs,
686 AffineExpr *rhs) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700687 switch (op) {
688 case Mul:
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700689 if (!lhs->isSymbolic() && !rhs->isSymbolic()) {
690 emitError("non-affine expression: at least one of the multiply "
691 "operands has to be either a constant or symbolic");
692 return nullptr;
693 }
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700694 return AffineMulExpr::get(lhs, rhs, builder.getContext());
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700695 case FloorDiv:
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700696 if (!rhs->isSymbolic()) {
697 emitError("non-affine expression: right operand of floordiv "
698 "has to be either a constant or symbolic");
699 return nullptr;
700 }
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700701 return AffineFloorDivExpr::get(lhs, rhs, builder.getContext());
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700702 case CeilDiv:
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700703 if (!rhs->isSymbolic()) {
704 emitError("non-affine expression: right operand of ceildiv "
705 "has to be either a constant or symbolic");
706 return nullptr;
707 }
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700708 return AffineCeilDivExpr::get(lhs, rhs, builder.getContext());
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700709 case Mod:
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700710 if (!rhs->isSymbolic()) {
711 emitError("non-affine expression: right operand of mod "
712 "has to be either a constant or symbolic");
713 return nullptr;
714 }
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700715 return AffineModExpr::get(lhs, rhs, builder.getContext());
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700716 case HNoOp:
717 llvm_unreachable("can't create affine expression for null high prec op");
718 return nullptr;
719 }
720}
721
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700722/// Create an affine binary low precedence op expression (add, sub).
723AffineExpr *Parser::getBinaryAffineOpExpr(AffineLowPrecOp op, AffineExpr *lhs,
724 AffineExpr *rhs) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700725 switch (op) {
726 case AffineLowPrecOp::Add:
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700727 return AffineAddExpr::get(lhs, rhs, builder.getContext());
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700728 case AffineLowPrecOp::Sub:
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700729 return AffineSubExpr::get(lhs, rhs, builder.getContext());
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700730 case AffineLowPrecOp::LNoOp:
731 llvm_unreachable("can't create affine expression for null low prec op");
732 return nullptr;
733 }
734}
735
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700736/// Consume this token if it is a lower precedence affine op (there are only two
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700737/// precedence levels).
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700738AffineLowPrecOp Parser::consumeIfLowPrecOp() {
739 switch (curToken.getKind()) {
740 case Token::plus:
741 consumeToken(Token::plus);
742 return AffineLowPrecOp::Add;
743 case Token::minus:
744 consumeToken(Token::minus);
745 return AffineLowPrecOp::Sub;
746 default:
747 return AffineLowPrecOp::LNoOp;
748 }
749}
750
751/// Consume this token if it is a higher precedence affine op (there are only
752/// two precedence levels)
753AffineHighPrecOp Parser::consumeIfHighPrecOp() {
754 switch (curToken.getKind()) {
755 case Token::star:
756 consumeToken(Token::star);
757 return Mul;
758 case Token::kw_floordiv:
759 consumeToken(Token::kw_floordiv);
760 return FloorDiv;
761 case Token::kw_ceildiv:
762 consumeToken(Token::kw_ceildiv);
763 return CeilDiv;
764 case Token::kw_mod:
765 consumeToken(Token::kw_mod);
766 return Mod;
767 default:
768 return HNoOp;
769 }
770}
771
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700772/// Parse a high precedence op expression list: mul, div, and mod are high
773/// precedence binary ops, i.e., parse a
774/// expr_1 op_1 expr_2 op_2 ... expr_n
775/// where op_1, op_2 are all a AffineHighPrecOp (mul, div, mod).
776/// All affine binary ops are left associative.
777/// Given llhs, returns (llhs llhsOp lhs) op rhs, or (lhs op rhs) if llhs is
778/// null. If no rhs can be found, returns (llhs llhsOp lhs) or lhs if llhs is
779/// null.
780AffineExpr *
781Parser::parseAffineHighPrecOpExpr(AffineExpr *llhs, AffineHighPrecOp llhsOp,
782 const AffineMapParserState &state) {
783 AffineExpr *lhs = parseAffineOperandExpr(llhs, state);
784 if (!lhs)
785 return nullptr;
786
787 AffineHighPrecOp op = HNoOp;
788 // Found an LHS. Parse the remaining expression.
789 if ((op = consumeIfHighPrecOp())) {
790 if (llhs) {
791 AffineExpr *expr = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
792 if (!expr)
793 return nullptr;
794 return parseAffineHighPrecOpExpr(expr, op, state);
795 }
796 // No LLHS, get RHS
797 return parseAffineHighPrecOpExpr(lhs, op, state);
798 }
799
800 // This is the last operand in this expression.
801 if (llhs)
802 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
803
804 // No llhs, 'lhs' itself is the expression.
805 return lhs;
806}
807
808/// Parse an affine expression inside parentheses.
809///
810/// affine-expr ::= `(` affine-expr `)`
811AffineExpr *Parser::parseParentheticalExpr(const AffineMapParserState &state) {
812 if (!consumeIf(Token::l_paren))
813 return (emitError("expected '('"), nullptr);
814 if (curToken.is(Token::r_paren))
815 return (emitError("no expression inside parentheses"), nullptr);
816 auto *expr = parseAffineExpr(state);
817 if (!expr)
818 // Error would have been emitted by parseAffineExpr.
819 return nullptr;
820 if (!consumeIf(Token::r_paren))
821 return (emitError("expected ')'"), nullptr);
822 return expr;
823}
824
825/// Parse the negation expression.
826///
827/// affine-expr ::= `-` affine-expr
828AffineExpr *Parser::parseNegateExpression(AffineExpr *lhs,
829 const AffineMapParserState &state) {
830 if (!consumeIf(Token::minus))
831 return (emitError("expected '-'"), nullptr);
832
833 AffineExpr *operand = parseAffineOperandExpr(lhs, state);
834 // Since negation has the highest precedence of all ops (including high
835 // precedence ops) but lower than parentheses, we are only going to use
836 // parseAffineOperandExpr instead of parseAffineExpr here.
837 if (!operand)
838 // Extra error message although parseAffineOperandExpr would have
839 // complained. Leads to a better diagnostic.
840 return (emitError("missing operand of negation"), nullptr);
841 AffineConstantExpr *minusOne =
842 AffineConstantExpr::get(-1, builder.getContext());
843 return AffineMulExpr::get(minusOne, operand, builder.getContext());
844}
845
846/// Parse a bare id that may appear in an affine expression.
847///
848/// affine-expr ::= bare-id
849AffineExpr *Parser::parseBareIdExpr(const AffineMapParserState &state) {
850 if (curToken.isNot(Token::bare_identifier))
851 return (emitError("expected bare identifier"), nullptr);
852
853 StringRef sRef = curToken.getSpelling();
854 const auto &dims = state.getDims();
855 const auto &symbols = state.getSymbols();
856 if (dims.count(sRef)) {
857 consumeToken(Token::bare_identifier);
858 return AffineDimExpr::get(dims.lookup(sRef), builder.getContext());
859 }
860 if (symbols.count(sRef)) {
861 consumeToken(Token::bare_identifier);
862 return AffineSymbolExpr::get(symbols.lookup(sRef), builder.getContext());
863 }
864 return (emitError("identifier is neither dimensional nor symbolic"), nullptr);
865}
866
867/// Parse a positive integral constant appearing in an affine expression.
868///
869/// affine-expr ::= integer-literal
870AffineExpr *Parser::parseIntegerExpr(const AffineMapParserState &state) {
871 // No need to handle negative numbers separately here. They are naturally
872 // handled via the unary negation operator, although (FIXME) MININT_64 still
873 // not correctly handled.
874 if (curToken.isNot(Token::integer))
875 return (emitError("expected integer"), nullptr);
876
877 auto val = curToken.getUInt64IntegerValue();
878 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
879 return (emitError("constant too large for affineint"), nullptr);
880 }
881 consumeToken(Token::integer);
882 return AffineConstantExpr::get((int64_t)val.getValue(), builder.getContext());
883}
884
885/// Parses an expression that can be a valid operand of an affine expression.
Uday Bondhugula76345202018-07-09 13:47:52 -0700886/// lhs: if non-null, lhs is an affine expression that is the lhs of a binary
887/// operator, the rhs of which is being parsed. This is used to determine
888/// whether an error should be emitted for a missing right operand.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700889// Eg: for an expression without parentheses (like i + j + k + l), each
890// of the four identifiers is an operand. For i + j*k + l, j*k is not an
891// operand expression, it's an op expression and will be parsed via
892// parseAffineHighPrecOpExpression(). However, for i + (j*k) + -l, (j*k) and -l
893// are valid operands that will be parsed by this function.
894AffineExpr *Parser::parseAffineOperandExpr(AffineExpr *lhs,
895 const AffineMapParserState &state) {
896 switch (curToken.getKind()) {
897 case Token::bare_identifier:
898 return parseBareIdExpr(state);
899 case Token::integer:
900 return parseIntegerExpr(state);
901 case Token::l_paren:
902 return parseParentheticalExpr(state);
903 case Token::minus:
904 return parseNegateExpression(lhs, state);
Uday Bondhugula76345202018-07-09 13:47:52 -0700905 case Token::kw_ceildiv:
906 case Token::kw_floordiv:
907 case Token::kw_mod:
908 case Token::plus:
909 case Token::star:
910 if (lhs)
911 emitError("missing right operand of binary operator");
912 else
913 emitError("missing left operand of binary operator");
914 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700915 default:
916 if (lhs)
Uday Bondhugula76345202018-07-09 13:47:52 -0700917 emitError("missing right operand of binary operator");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700918 else
919 emitError("expected affine expression");
920 return nullptr;
921 }
922}
923
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700924/// Parse affine expressions that are bare-id's, integer constants,
925/// parenthetical affine expressions, and affine op expressions that are a
926/// composition of those.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700927///
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700928/// All binary op's associate from left to right.
929///
930/// {add, sub} have lower precedence than {mul, div, and mod}.
931///
Uday Bondhugula76345202018-07-09 13:47:52 -0700932/// Add, sub'are themselves at the same precedence level. Mul, floordiv,
933/// ceildiv, and mod are at the same higher precedence level. Negation has
934/// higher precedence than any binary op.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700935///
936/// llhs: the affine expression appearing on the left of the one being parsed.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700937/// This function will return ((llhs llhsOp lhs) op rhs) if llhs is non null,
938/// and lhs op rhs otherwise; if there is no rhs, llhs llhsOp lhs is returned if
939/// llhs is non-null; otherwise lhs is returned. This is to deal with left
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700940/// associativity.
941///
942/// Eg: when the expression is e1 + e2*e3 + e4, with e1 as llhs, this function
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700943/// will return the affine expr equivalent of (e1 + (e2*e3)) + e4, where (e2*e3)
944/// will be parsed using parseAffineHighPrecOpExpr().
945AffineExpr *
946Parser::parseAffineLowPrecOpExpr(AffineExpr *llhs, AffineLowPrecOp llhsOp,
947 const AffineMapParserState &state) {
Uday Bondhugula76345202018-07-09 13:47:52 -0700948 AffineExpr *lhs;
949 if (!(lhs = parseAffineOperandExpr(llhs, state)))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700950 return nullptr;
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700951
952 // Found an LHS. Deal with the ops.
953 AffineLowPrecOp lOp;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700954 AffineHighPrecOp hOp;
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700955 if ((lOp = consumeIfLowPrecOp())) {
956 if (llhs) {
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700957 AffineExpr *sum = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700958 return parseAffineLowPrecOpExpr(sum, lOp, state);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700959 }
960 // No LLHS, get RHS and form the expression.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700961 return parseAffineLowPrecOpExpr(lhs, lOp, state);
962 }
963 if ((hOp = consumeIfHighPrecOp())) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700964 // We have a higher precedence op here. Get the rhs operand for the llhs
965 // through parseAffineHighPrecOpExpr.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700966 AffineExpr *highRes = parseAffineHighPrecOpExpr(lhs, hOp, state);
967 if (!highRes)
968 return nullptr;
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700969 // If llhs is null, the product forms the first operand of the yet to be
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700970 // found expression. If non-null, the op to associate with llhs is llhsOp.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700971 AffineExpr *expr =
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700972 llhs ? getBinaryAffineOpExpr(llhsOp, llhs, highRes) : highRes;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700973 // Recurse for subsequent low prec op's after the affine high prec op
974 // expression.
975 AffineLowPrecOp nextOp;
976 if ((nextOp = consumeIfLowPrecOp()))
977 return parseAffineLowPrecOpExpr(expr, nextOp, state);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700978 return expr;
979 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700980 // Last operand in the expression list.
981 if (llhs)
982 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
983 // No llhs, 'lhs' itself is the expression.
984 return lhs;
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700985}
986
987/// Parse an affine expression.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700988/// affine-expr ::= `(` affine-expr `)`
989/// | `-` affine-expr
990/// | affine-expr `+` affine-expr
991/// | affine-expr `-` affine-expr
992/// | affine-expr `*` affine-expr
993/// | affine-expr `floordiv` affine-expr
994/// | affine-expr `ceildiv` affine-expr
995/// | affine-expr `mod` affine-expr
996/// | bare-id
997/// | integer-literal
998///
999/// Additional conditions are checked depending on the production. For eg., one
1000/// of the operands for `*` has to be either constant/symbolic; the second
1001/// operand for floordiv, ceildiv, and mod has to be a positive integer.
1002/// Use 'state' to check if valid identifiers appear in the expressoins.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001003AffineExpr *Parser::parseAffineExpr(const AffineMapParserState &state) {
Uday Bondhugula76345202018-07-09 13:47:52 -07001004 return parseAffineLowPrecOpExpr(nullptr, AffineLowPrecOp::LNoOp, state);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001005}
1006
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001007/// Parse a dim or symbol from the lists appearing before the actual expressions
1008/// of the affine map. Update state to store the dimensional/symbolic
1009/// identifier. 'dim': whether it's the dim list or symbol list that is being
1010/// parsed.
1011ParseResult Parser::parseDimOrSymbolId(AffineMapParserState &state, bool dim) {
1012 if (curToken.isNot(Token::bare_identifier))
1013 return emitError("expected bare identifier");
1014 auto sRef = curToken.getSpelling();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001015 consumeToken(Token::bare_identifier);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001016 if (state.getDims().count(sRef) == 1)
1017 return emitError("dimensional identifier name reused");
1018 if (state.getSymbols().count(sRef) == 1)
1019 return emitError("symbolic identifier name reused");
1020 if (dim)
1021 state.addDim(sRef);
1022 else
1023 state.addSymbol(sRef);
1024 return ParseSuccess;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001025}
1026
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001027/// Parse the list of symbolic identifiers to an affine map.
1028ParseResult Parser::parseSymbolIdList(AffineMapParserState &state) {
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001029 if (!consumeIf(Token::l_bracket)) return emitError("expected '['");
1030
1031 auto parseElt = [&]() -> ParseResult {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001032 return parseDimOrSymbolId(state, false);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001033 };
1034 return parseCommaSeparatedList(Token::r_bracket, parseElt);
1035}
1036
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001037/// Parse the list of dimensional identifiers to an affine map.
1038ParseResult Parser::parseDimIdList(AffineMapParserState &state) {
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001039 if (!consumeIf(Token::l_paren))
1040 return emitError("expected '(' at start of dimensional identifiers list");
1041
1042 auto parseElt = [&]() -> ParseResult {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001043 return parseDimOrSymbolId(state, true);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001044 };
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001045 return parseCommaSeparatedList(Token::r_paren, parseElt);
1046}
1047
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001048/// Parse an affine map definition.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001049///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001050/// affine-map-inline ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
1051/// (`size` `(` dim-size (`,` dim-size)* `)`)?
1052/// dim-size ::= affine-expr | `min` `(` affine-expr ( `,` affine-expr)+ `)`
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001053///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001054/// multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
1055// TODO(bondhugula): parse range size information.
Chris Lattner7121b802018-07-04 20:45:39 -07001056AffineMap *Parser::parseAffineMapInline(StringRef mapId) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001057 AffineMapParserState state;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001058
1059 // List of dimensional identifiers.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001060 if (parseDimIdList(state))
Chris Lattner7121b802018-07-04 20:45:39 -07001061 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001062
1063 // Symbols are optional.
1064 if (curToken.is(Token::l_bracket)) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001065 if (parseSymbolIdList(state))
Chris Lattner7121b802018-07-04 20:45:39 -07001066 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001067 }
1068 if (!consumeIf(Token::arrow)) {
Chris Lattner7121b802018-07-04 20:45:39 -07001069 return (emitError("expected '->' or '['"), nullptr);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001070 }
1071 if (!consumeIf(Token::l_paren)) {
1072 emitError("expected '(' at start of affine map range");
Chris Lattner7121b802018-07-04 20:45:39 -07001073 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001074 }
1075
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001076 SmallVector<AffineExpr *, 4> exprs;
1077 auto parseElt = [&]() -> ParseResult {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001078 auto *elt = parseAffineExpr(state);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001079 ParseResult res = elt ? ParseSuccess : ParseFailure;
1080 exprs.push_back(elt);
1081 return res;
1082 };
1083
1084 // Parse a multi-dimensional affine expression (a comma-separated list of 1-d
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001085 // affine expressions); the list cannot be empty.
1086 // Grammar: multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
1087 if (parseCommaSeparatedList(Token::r_paren, parseElt, false))
Chris Lattner7121b802018-07-04 20:45:39 -07001088 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001089
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001090 // Parsed a valid affine map.
Chris Lattner7121b802018-07-04 20:45:39 -07001091 return AffineMap::get(state.getNumDims(), state.getNumSymbols(), exprs,
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001092 builder.getContext());
MLIR Teamf85a6262018-06-27 11:03:08 -07001093}
1094
1095//===----------------------------------------------------------------------===//
Chris Lattner78276e32018-07-07 15:48:26 -07001096// SSA
Chris Lattner4c95a502018-06-23 16:03:42 -07001097//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001098
Chris Lattner78276e32018-07-07 15:48:26 -07001099/// Parse a SSA operand for an instruction or statement.
1100///
1101/// ssa-use ::= ssa-id | ssa-constant
1102///
1103ParseResult Parser::parseSSAUse() {
1104 if (curToken.is(Token::percent_identifier)) {
1105 StringRef name = curToken.getSpelling().drop_front();
1106 consumeToken(Token::percent_identifier);
1107 // TODO: Return this use.
1108 (void)name;
1109 return ParseSuccess;
1110 }
1111
1112 // TODO: Parse SSA constants.
1113
1114 return emitError("expected SSA operand");
1115}
1116
1117/// Parse a (possibly empty) list of SSA operands.
1118///
1119/// ssa-use-list ::= ssa-use (`,` ssa-use)*
1120/// ssa-use-list-opt ::= ssa-use-list?
1121///
1122ParseResult Parser::parseOptionalSSAUseList(Token::Kind endToken) {
1123 // TODO: Build and return this.
1124 return parseCommaSeparatedList(
1125 endToken, [&]() -> ParseResult { return parseSSAUse(); });
1126}
1127
1128/// Parse an SSA use with an associated type.
1129///
1130/// ssa-use-and-type ::= ssa-use `:` type
1131ParseResult Parser::parseSSAUseAndType() {
1132 if (parseSSAUse())
1133 return ParseFailure;
1134
1135 if (!consumeIf(Token::colon))
1136 return emitError("expected ':' and type for SSA operand");
1137
1138 if (!parseType())
1139 return ParseFailure;
1140
1141 return ParseSuccess;
1142}
1143
1144/// Parse a (possibly empty) list of SSA operands with types.
1145///
1146/// ssa-use-and-type-list ::= ssa-use-and-type (`,` ssa-use-and-type)*
1147///
1148ParseResult Parser::parseOptionalSSAUseAndTypeList(Token::Kind endToken) {
1149 // TODO: Build and return this.
1150 return parseCommaSeparatedList(
1151 endToken, [&]() -> ParseResult { return parseSSAUseAndType(); });
1152}
1153
1154//===----------------------------------------------------------------------===//
1155// Functions
1156//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001157
1158/// Parse a function signature, starting with a name and including the parameter
1159/// list.
1160///
1161/// argument-list ::= type (`,` type)* | /*empty*/
1162/// function-signature ::= function-id `(` argument-list `)` (`->` type-list)?
1163///
Chris Lattnerf7e22732018-06-22 22:03:48 -07001164ParseResult Parser::parseFunctionSignature(StringRef &name,
1165 FunctionType *&type) {
Chris Lattnere79379a2018-06-22 10:39:19 -07001166 if (curToken.isNot(Token::at_identifier))
1167 return emitError("expected a function identifier like '@foo'");
1168
1169 name = curToken.getSpelling().drop_front();
1170 consumeToken(Token::at_identifier);
1171
1172 if (curToken.isNot(Token::l_paren))
1173 return emitError("expected '(' in function signature");
Chris Lattnere79379a2018-06-22 10:39:19 -07001174
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001175 SmallVector<Type*, 4> arguments;
1176 if (parseTypeList(arguments))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -07001177 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07001178
Chris Lattnerbb8fafc2018-06-22 15:52:02 -07001179 // Parse the return type if present.
Chris Lattnerf7e22732018-06-22 22:03:48 -07001180 SmallVector<Type*, 4> results;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -07001181 if (consumeIf(Token::arrow)) {
Chris Lattnerf7e22732018-06-22 22:03:48 -07001182 if (parseTypeList(results))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -07001183 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -07001184 }
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001185 type = builder.getFunctionType(arguments, results);
Chris Lattnere79379a2018-06-22 10:39:19 -07001186 return ParseSuccess;
1187}
1188
Chris Lattnere79379a2018-06-22 10:39:19 -07001189/// External function declarations.
1190///
1191/// ext-func ::= `extfunc` function-signature
1192///
1193ParseResult Parser::parseExtFunc() {
1194 consumeToken(Token::kw_extfunc);
1195
1196 StringRef name;
Chris Lattnerf7e22732018-06-22 22:03:48 -07001197 FunctionType *type = nullptr;
1198 if (parseFunctionSignature(name, type))
Chris Lattnere79379a2018-06-22 10:39:19 -07001199 return ParseFailure;
1200
Chris Lattnere79379a2018-06-22 10:39:19 -07001201 // Okay, the external function definition was parsed correctly.
Chris Lattner4c95a502018-06-23 16:03:42 -07001202 module->functionList.push_back(new ExtFunction(name, type));
Chris Lattnere79379a2018-06-22 10:39:19 -07001203 return ParseSuccess;
1204}
1205
1206
Chris Lattner4c95a502018-06-23 16:03:42 -07001207namespace {
1208/// This class represents the transient parser state for the internals of a
1209/// function as we are parsing it, e.g. the names for basic blocks. It handles
1210/// forward references.
1211class CFGFunctionParserState {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001212public:
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001213 CFGFunction *function;
1214 llvm::StringMap<std::pair<BasicBlock*, SMLoc>> blocksByName;
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001215 CFGFuncBuilder builder;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001216
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001217 CFGFunctionParserState(CFGFunction *function)
1218 : function(function), builder(function) {}
Chris Lattner4c95a502018-06-23 16:03:42 -07001219
1220 /// Get the basic block with the specified name, creating it if it doesn't
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001221 /// already exist. The location specified is the point of use, which allows
1222 /// us to diagnose references to blocks that are not defined precisely.
1223 BasicBlock *getBlockNamed(StringRef name, SMLoc loc) {
1224 auto &blockAndLoc = blocksByName[name];
1225 if (!blockAndLoc.first) {
Chris Lattner3a467cc2018-07-01 20:28:00 -07001226 blockAndLoc.first = new BasicBlock();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001227 blockAndLoc.second = loc;
Chris Lattner4c95a502018-06-23 16:03:42 -07001228 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001229 return blockAndLoc.first;
Chris Lattner4c95a502018-06-23 16:03:42 -07001230 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001231};
1232} // end anonymous namespace
1233
1234
1235/// CFG function declarations.
1236///
1237/// cfg-func ::= `cfgfunc` function-signature `{` basic-block+ `}`
1238///
1239ParseResult Parser::parseCFGFunc() {
1240 consumeToken(Token::kw_cfgfunc);
1241
1242 StringRef name;
1243 FunctionType *type = nullptr;
1244 if (parseFunctionSignature(name, type))
1245 return ParseFailure;
1246
1247 if (!consumeIf(Token::l_brace))
1248 return emitError("expected '{' in CFG function");
1249
1250 // Okay, the CFG function signature was parsed correctly, create the function.
1251 auto function = new CFGFunction(name, type);
1252
1253 // Make sure we have at least one block.
1254 if (curToken.is(Token::r_brace))
1255 return emitError("CFG functions must have at least one basic block");
1256
1257 CFGFunctionParserState functionState(function);
1258
1259 // Parse the list of blocks.
1260 while (!consumeIf(Token::r_brace))
1261 if (parseBasicBlock(functionState))
1262 return ParseFailure;
1263
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001264 // Verify that all referenced blocks were defined. Iteration over a
1265 // StringMap isn't determinstic, but this is good enough for our purposes.
1266 for (auto &elt : functionState.blocksByName) {
1267 auto *bb = elt.second.first;
Chris Lattner3a467cc2018-07-01 20:28:00 -07001268 if (!bb->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001269 return emitError(elt.second.second,
1270 "reference to an undefined basic block '" +
1271 elt.first() + "'");
1272 }
1273
Chris Lattner4c95a502018-06-23 16:03:42 -07001274 module->functionList.push_back(function);
1275 return ParseSuccess;
1276}
1277
1278/// Basic block declaration.
1279///
1280/// basic-block ::= bb-label instruction* terminator-stmt
1281/// bb-label ::= bb-id bb-arg-list? `:`
1282/// bb-id ::= bare-id
1283/// bb-arg-list ::= `(` ssa-id-and-type-list? `)`
1284///
1285ParseResult Parser::parseBasicBlock(CFGFunctionParserState &functionState) {
1286 SMLoc nameLoc = curToken.getLoc();
1287 auto name = curToken.getSpelling();
1288 if (!consumeIf(Token::bare_identifier))
1289 return emitError("expected basic block name");
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001290
1291 auto block = functionState.getBlockNamed(name, nameLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001292
1293 // If this block has already been parsed, then this is a redefinition with the
1294 // same block name.
Chris Lattner3a467cc2018-07-01 20:28:00 -07001295 if (block->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001296 return emitError(nameLoc, "redefinition of block '" + name.str() + "'");
1297
Chris Lattner3a467cc2018-07-01 20:28:00 -07001298 // Add the block to the function.
1299 functionState.function->push_back(block);
Chris Lattner4c95a502018-06-23 16:03:42 -07001300
Chris Lattner78276e32018-07-07 15:48:26 -07001301 // If an argument list is present, parse it.
1302 if (consumeIf(Token::l_paren)) {
1303 if (parseOptionalSSAUseAndTypeList(Token::r_paren))
1304 return ParseFailure;
1305
1306 // TODO: attach it.
1307 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001308
1309 if (!consumeIf(Token::colon))
1310 return emitError("expected ':' after basic block name");
1311
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001312 // Set the insertion point to the block we want to insert new operations into.
1313 functionState.builder.setInsertionPoint(block);
1314
Chris Lattnered65a732018-06-28 20:45:33 -07001315 // Parse the list of operations that make up the body of the block.
1316 while (curToken.isNot(Token::kw_return, Token::kw_br)) {
Chris Lattner21e67f62018-07-06 10:46:19 -07001317 auto loc = curToken.getLoc();
Chris Lattner3a467cc2018-07-01 20:28:00 -07001318 auto *inst = parseCFGOperation(functionState);
1319 if (!inst)
Chris Lattnered65a732018-06-28 20:45:33 -07001320 return ParseFailure;
Chris Lattner3a467cc2018-07-01 20:28:00 -07001321
Chris Lattner21e67f62018-07-06 10:46:19 -07001322 // We just parsed an operation. If it is a recognized one, verify that it
1323 // is structurally as we expect. If not, produce an error with a reasonable
1324 // source location.
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001325 if (auto *opInfo = inst->getAbstractOperation(builder.getContext()))
Chris Lattner21e67f62018-07-06 10:46:19 -07001326 if (auto error = opInfo->verifyInvariants(inst))
1327 return emitError(loc, error);
Chris Lattnered65a732018-06-28 20:45:33 -07001328 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001329
Chris Lattner3a467cc2018-07-01 20:28:00 -07001330 auto *term = parseTerminator(functionState);
1331 if (!term)
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001332 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07001333
1334 return ParseSuccess;
1335}
1336
1337
Chris Lattnered65a732018-06-28 20:45:33 -07001338/// Parse the CFG operation.
1339///
1340/// TODO(clattner): This is a change from the MLIR spec as written, it is an
1341/// experiment that will eliminate "builtin" instructions as a thing.
1342///
1343/// cfg-operation ::=
1344/// (ssa-id `=`)? string '(' ssa-use-list? ')' attribute-dict?
1345/// `:` function-type
1346///
Chris Lattner3a467cc2018-07-01 20:28:00 -07001347OperationInst *Parser::
1348parseCFGOperation(CFGFunctionParserState &functionState) {
Chris Lattnered65a732018-06-28 20:45:33 -07001349
Chris Lattner78276e32018-07-07 15:48:26 -07001350 StringRef resultID;
1351 if (curToken.is(Token::percent_identifier)) {
1352 resultID = curToken.getSpelling().drop_front();
1353 consumeToken();
1354 if (!consumeIf(Token::equal))
1355 return (emitError("expected '=' after SSA name"), nullptr);
1356 }
Chris Lattnered65a732018-06-28 20:45:33 -07001357
1358 if (curToken.isNot(Token::string))
Chris Lattner3a467cc2018-07-01 20:28:00 -07001359 return (emitError("expected operation name in quotes"), nullptr);
Chris Lattnered65a732018-06-28 20:45:33 -07001360
1361 auto name = curToken.getStringValue();
1362 if (name.empty())
Chris Lattner3a467cc2018-07-01 20:28:00 -07001363 return (emitError("empty operation name is invalid"), nullptr);
Chris Lattnered65a732018-06-28 20:45:33 -07001364
1365 consumeToken(Token::string);
1366
1367 if (!consumeIf(Token::l_paren))
Chris Lattner7121b802018-07-04 20:45:39 -07001368 return (emitError("expected '(' to start operand list"), nullptr);
Chris Lattnered65a732018-06-28 20:45:33 -07001369
Chris Lattner78276e32018-07-07 15:48:26 -07001370 // Parse the operand list.
1371 parseOptionalSSAUseList(Token::r_paren);
Chris Lattner7121b802018-07-04 20:45:39 -07001372
1373 SmallVector<NamedAttribute, 4> attributes;
1374 if (curToken.is(Token::l_brace)) {
1375 if (parseAttributeDict(attributes))
1376 return nullptr;
1377 }
Chris Lattnered65a732018-06-28 20:45:33 -07001378
Chris Lattner78276e32018-07-07 15:48:26 -07001379 // TODO: Don't drop result name and operand names on the floor.
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001380 auto nameId = Identifier::get(name, builder.getContext());
1381 return functionState.builder.createOperation(nameId, attributes);
Chris Lattnered65a732018-06-28 20:45:33 -07001382}
1383
1384
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001385/// Parse the terminator instruction for a basic block.
1386///
1387/// terminator-stmt ::= `br` bb-id branch-use-list?
1388/// branch-use-list ::= `(` ssa-use-and-type-list? `)`
1389/// terminator-stmt ::=
1390/// `cond_br` ssa-use `,` bb-id branch-use-list? `,` bb-id branch-use-list?
1391/// terminator-stmt ::= `return` ssa-use-and-type-list?
1392///
Chris Lattner3a467cc2018-07-01 20:28:00 -07001393TerminatorInst *Parser::parseTerminator(CFGFunctionParserState &functionState) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001394 switch (curToken.getKind()) {
1395 default:
Chris Lattner3a467cc2018-07-01 20:28:00 -07001396 return (emitError("expected terminator at end of basic block"), nullptr);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001397
1398 case Token::kw_return:
1399 consumeToken(Token::kw_return);
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001400 return functionState.builder.createReturnInst();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001401
1402 case Token::kw_br: {
1403 consumeToken(Token::kw_br);
1404 auto destBB = functionState.getBlockNamed(curToken.getSpelling(),
1405 curToken.getLoc());
1406 if (!consumeIf(Token::bare_identifier))
Chris Lattner3a467cc2018-07-01 20:28:00 -07001407 return (emitError("expected basic block name"), nullptr);
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001408 return functionState.builder.createBranchInst(destBB);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001409 }
Chris Lattner78276e32018-07-07 15:48:26 -07001410 // TODO: cond_br.
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001411 }
1412}
1413
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001414/// ML function declarations.
1415///
1416/// ml-func ::= `mlfunc` ml-func-signature `{` ml-stmt* ml-return-stmt `}`
1417///
1418ParseResult Parser::parseMLFunc() {
1419 consumeToken(Token::kw_mlfunc);
1420
1421 StringRef name;
1422 FunctionType *type = nullptr;
1423
1424 // FIXME: Parse ML function signature (args + types)
1425 // by passing pointer to SmallVector<identifier> into parseFunctionSignature
1426 if (parseFunctionSignature(name, type))
1427 return ParseFailure;
1428
1429 if (!consumeIf(Token::l_brace))
1430 return emitError("expected '{' in ML function");
1431
1432 // Okay, the ML function signature was parsed correctly, create the function.
1433 auto function = new MLFunction(name, type);
1434
1435 // Make sure we have at least one statement.
1436 if (curToken.is(Token::r_brace))
1437 return emitError("ML function must end with return statement");
1438
1439 // Parse the list of instructions.
1440 while (!consumeIf(Token::kw_return)) {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001441 auto *stmt = parseStatement(function);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001442 if (!stmt)
1443 return ParseFailure;
1444 function->stmtList.push_back(stmt);
1445 }
1446
1447 // TODO: parse return statement operands
1448 if (!consumeIf(Token::r_brace))
1449 emitError("expected '}' in ML function");
1450
1451 module->functionList.push_back(function);
1452
1453 return ParseSuccess;
1454}
1455
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001456/// Statement.
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001457///
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001458/// ml-stmt ::= instruction | ml-for-stmt | ml-if-stmt
1459/// TODO: fix terminology in MLSpec document. ML functions
1460/// contain operation statements, not instructions.
1461///
1462Statement * Parser::parseStatement(ParentType parent) {
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001463 switch (curToken.getKind()) {
1464 default:
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001465 //TODO: parse OperationStmt
1466 return (emitError("expected statement"), nullptr);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001467
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001468 case Token::kw_for:
1469 return parseForStmt(parent);
1470
1471 case Token::kw_if:
1472 return parseIfStmt(parent);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001473 }
1474}
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001475
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07001476/// For statement.
1477///
1478/// ml-for-stmt ::= `for` ssa-id `=` lower-bound `to` upper-bound
1479/// (`step` integer-literal)? `{` ml-stmt* `}`
1480///
1481ForStmt * Parser::parseForStmt(ParentType parent) {
1482 consumeToken(Token::kw_for);
1483
1484 //TODO: parse loop header
1485 ForStmt *stmt = new ForStmt(parent);
1486 if (parseNestedStatements(stmt)) {
1487 delete stmt;
1488 return nullptr;
1489 }
1490 return stmt;
1491}
1492
1493/// If statement.
1494///
1495/// ml-if-head ::= `if` ml-if-cond `{` ml-stmt* `}`
1496/// | ml-if-head `else` `if` ml-if-cond `{` ml-stmt* `}`
1497/// ml-if-stmt ::= ml-if-head
1498/// | ml-if-head `else` `{` ml-stmt* `}`
1499///
1500IfStmt * Parser::parseIfStmt(PointerUnion<MLFunction *, NodeStmt *> parent) {
1501 consumeToken(Token::kw_if);
1502
1503 //TODO: parse condition
1504 IfStmt *stmt = new IfStmt(parent);
1505 if (parseNestedStatements(stmt)) {
1506 delete stmt;
1507 return nullptr;
1508 }
1509
1510 int clauseNum = 0;
1511 while (consumeIf(Token::kw_else)) {
1512 if (consumeIf(Token::kw_if)) {
1513 //TODO: parse condition
1514 }
1515 ElseClause * clause = new ElseClause(stmt, clauseNum);
1516 ++clauseNum;
1517 if (parseNestedStatements(clause)) {
1518 delete clause;
1519 return nullptr;
1520 }
1521 }
1522
1523 return stmt;
1524}
1525
1526///
1527/// Parse `{` ml-stmt* `}`
1528///
1529ParseResult Parser::parseNestedStatements(NodeStmt *parent) {
1530 if (!consumeIf(Token::l_brace))
1531 return emitError("expected '{' before statement list");
1532
1533 if (consumeIf(Token::r_brace)) {
1534 // TODO: parse OperationStmt
1535 return ParseSuccess;
1536 }
1537
1538 while (!consumeIf(Token::r_brace)) {
1539 auto *stmt = parseStatement(parent);
1540 if (!stmt)
1541 return ParseFailure;
1542 parent->children.push_back(stmt);
1543 }
1544
1545 return ParseSuccess;
1546}
1547
Chris Lattner4c95a502018-06-23 16:03:42 -07001548//===----------------------------------------------------------------------===//
1549// Top-level entity parsing.
1550//===----------------------------------------------------------------------===//
1551
Chris Lattnere79379a2018-06-22 10:39:19 -07001552/// This is the top-level module parser.
1553Module *Parser::parseModule() {
1554 while (1) {
1555 switch (curToken.getKind()) {
1556 default:
1557 emitError("expected a top level entity");
1558 return nullptr;
1559
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001560 // If we got to the end of the file, then we're done.
Chris Lattnere79379a2018-06-22 10:39:19 -07001561 case Token::eof:
1562 return module.release();
1563
1564 // If we got an error token, then the lexer already emitted an error, just
1565 // stop. Someday we could introduce error recovery if there was demand for
1566 // it.
1567 case Token::error:
1568 return nullptr;
1569
1570 case Token::kw_extfunc:
Chris Lattner4c95a502018-06-23 16:03:42 -07001571 if (parseExtFunc()) return nullptr;
Chris Lattnere79379a2018-06-22 10:39:19 -07001572 break;
1573
Chris Lattner4c95a502018-06-23 16:03:42 -07001574 case Token::kw_cfgfunc:
1575 if (parseCFGFunc()) return nullptr;
1576 break;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001577
Chris Lattner78276e32018-07-07 15:48:26 -07001578 case Token::hash_identifier:
MLIR Teamf85a6262018-06-27 11:03:08 -07001579 if (parseAffineMapDef()) return nullptr;
1580 break;
Chris Lattner4c95a502018-06-23 16:03:42 -07001581
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07001582 case Token::kw_mlfunc:
1583 if (parseMLFunc()) return nullptr;
1584 break;
1585
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001586 // TODO: affine entity declarations, etc.
Chris Lattnere79379a2018-06-22 10:39:19 -07001587 }
1588 }
1589}
1590
1591//===----------------------------------------------------------------------===//
1592
Jacques Pienaar7b829702018-07-03 13:24:09 -07001593void mlir::defaultErrorReporter(const llvm::SMDiagnostic &error) {
1594 const auto &sourceMgr = *error.getSourceMgr();
1595 sourceMgr.PrintMessage(error.getLoc(), error.getKind(), error.getMessage());
1596}
1597
Chris Lattnere79379a2018-06-22 10:39:19 -07001598/// This parses the file specified by the indicated SourceMgr and returns an
1599/// MLIR module if it was valid. If not, it emits diagnostics and returns null.
Jacques Pienaar9c411be2018-06-24 19:17:35 -07001600Module *mlir::parseSourceFile(llvm::SourceMgr &sourceMgr, MLIRContext *context,
Jacques Pienaar7b829702018-07-03 13:24:09 -07001601 SMDiagnosticHandlerTy errorReporter) {
Chris Lattner21e67f62018-07-06 10:46:19 -07001602 auto *result =
1603 Parser(sourceMgr, context,
1604 errorReporter ? std::move(errorReporter) : defaultErrorReporter)
1605 .parseModule();
1606
1607 // Make sure the parse module has no other structural problems detected by the
1608 // verifier.
1609 if (result)
1610 result->verify();
1611 return result;
Chris Lattnere79379a2018-06-22 10:39:19 -07001612}