blob: 55fd26043850df8610eaa77b862a3412ee3e170c [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"
Chris Lattner85ee1512018-07-25 11:15:20 -070030#include "mlir/IR/OpImplementation.h"
Chris Lattner21e67f62018-07-06 10:46:19 -070031#include "mlir/IR/OperationSet.h"
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -070032#include "mlir/IR/Statements.h"
Chris Lattnerf7e22732018-06-22 22:03:48 -070033#include "mlir/IR/Types.h"
Chris Lattner6119d382018-07-20 18:41:34 -070034#include "llvm/ADT/DenseMap.h"
Chris Lattnere79379a2018-06-22 10:39:19 -070035#include "llvm/Support/SourceMgr.h"
36using namespace mlir;
Chris Lattner4c95a502018-06-23 16:03:42 -070037using llvm::SMLoc;
James Molloy0ff71542018-07-23 16:56:32 -070038using llvm::SourceMgr;
Chris Lattnere79379a2018-06-22 10:39:19 -070039
Chris Lattnerf7e22732018-06-22 22:03:48 -070040/// Simple enum to make code read better in cases that would otherwise return a
41/// bool value. Failure is "true" in a boolean context.
James Molloy0ff71542018-07-23 16:56:32 -070042enum ParseResult { ParseSuccess, ParseFailure };
Chris Lattnere79379a2018-06-22 10:39:19 -070043
Chris Lattner48af7d12018-07-09 19:05:38 -070044namespace {
45class Parser;
46
47/// This class refers to all of the state maintained globally by the parser,
48/// such as the current lexer position etc. The Parser base class provides
49/// methods to access this.
50class ParserState {
Chris Lattnered65a732018-06-28 20:45:33 -070051public:
Chris Lattner2e595eb2018-07-10 10:08:27 -070052 ParserState(llvm::SourceMgr &sourceMgr, Module *module,
Chris Lattner48af7d12018-07-09 19:05:38 -070053 SMDiagnosticHandlerTy errorReporter)
Chris Lattner2e595eb2018-07-10 10:08:27 -070054 : context(module->getContext()), module(module),
55 lex(sourceMgr, errorReporter), curToken(lex.lexToken()),
Chris Lattner85ee1512018-07-25 11:15:20 -070056 errorReporter(errorReporter), operationSet(OperationSet::get(context)) {
57 }
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 Lattner85ee1512018-07-25 11:15:20 -070082
83 // The active OperationSet we're parsing with.
84 OperationSet &operationSet;
Chris Lattner48af7d12018-07-09 19:05:38 -070085};
86} // end anonymous namespace
MLIR Teamf85a6262018-06-27 11:03:08 -070087
Chris Lattner48af7d12018-07-09 19:05:38 -070088namespace {
89
Chris Lattner7f9cc272018-07-19 08:35:28 -070090typedef std::function<Operation *(Identifier, ArrayRef<SSAValue *>,
91 ArrayRef<Type *>, ArrayRef<NamedAttribute>)>
Tatiana Shpeisman565b9642018-07-16 11:47:09 -070092 CreateOperationFunction;
93
Chris Lattner48af7d12018-07-09 19:05:38 -070094/// This class implement support for parsing global entities like types and
95/// shared entities like SSA names. It is intended to be subclassed by
96/// specialized subparsers that include state, e.g. when a local symbol table.
97class Parser {
98public:
Chris Lattner2e595eb2018-07-10 10:08:27 -070099 Builder builder;
Chris Lattner48af7d12018-07-09 19:05:38 -0700100
Chris Lattner2e595eb2018-07-10 10:08:27 -0700101 Parser(ParserState &state) : builder(state.context), state(state) {}
102
103 // Helper methods to get stuff from the parser-global state.
104 ParserState &getState() const { return state; }
Chris Lattner48af7d12018-07-09 19:05:38 -0700105 MLIRContext *getContext() const { return state.context; }
Chris Lattner2e595eb2018-07-10 10:08:27 -0700106 Module *getModule() { return state.module; }
Chris Lattner85ee1512018-07-25 11:15:20 -0700107 OperationSet &getOperationSet() const { return state.operationSet; }
Chris Lattner48af7d12018-07-09 19:05:38 -0700108
109 /// Return the current token the parser is inspecting.
110 const Token &getToken() const { return state.curToken; }
111 StringRef getTokenSpelling() const { return state.curToken.getSpelling(); }
Chris Lattnere79379a2018-06-22 10:39:19 -0700112
113 /// Emit an error and return failure.
Chris Lattner4c95a502018-06-23 16:03:42 -0700114 ParseResult emitError(const Twine &message) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700115 return emitError(state.curToken.getLoc(), message);
Chris Lattner4c95a502018-06-23 16:03:42 -0700116 }
117 ParseResult emitError(SMLoc loc, const Twine &message);
Chris Lattnere79379a2018-06-22 10:39:19 -0700118
119 /// Advance the current lexer onto the next token.
120 void consumeToken() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700121 assert(state.curToken.isNot(Token::eof, Token::error) &&
Chris Lattnere79379a2018-06-22 10:39:19 -0700122 "shouldn't advance past EOF or errors");
Chris Lattner48af7d12018-07-09 19:05:38 -0700123 state.curToken = state.lex.lexToken();
Chris Lattnere79379a2018-06-22 10:39:19 -0700124 }
125
126 /// Advance the current lexer onto the next token, asserting what the expected
127 /// current token is. This is preferred to the above method because it leads
128 /// to more self-documenting code with better checking.
Chris Lattner8da0c282018-06-29 11:15:56 -0700129 void consumeToken(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700130 assert(state.curToken.is(kind) && "consumed an unexpected token");
Chris Lattnere79379a2018-06-22 10:39:19 -0700131 consumeToken();
132 }
133
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700134 /// If the current token has the specified kind, consume it and return true.
135 /// If not, return false.
Chris Lattner8da0c282018-06-29 11:15:56 -0700136 bool consumeIf(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700137 if (state.curToken.isNot(kind))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700138 return false;
139 consumeToken(kind);
140 return true;
141 }
142
Chris Lattnerf7702a62018-07-23 17:30:01 -0700143 /// Consume the specified token if present and return success. On failure,
144 /// output a diagnostic and return failure.
145 ParseResult parseToken(Token::Kind expectedToken, const Twine &message);
146
Chris Lattner40746442018-07-21 14:32:09 -0700147 /// Parse a comma-separated list of elements up until the specified end token.
148 ParseResult
149 parseCommaSeparatedListUntil(Token::Kind rightToken,
150 const std::function<ParseResult()> &parseElement,
151 bool allowEmptyList = true);
152
153 /// Parse a comma separated list of elements that must have at least one entry
154 /// in it.
155 ParseResult
156 parseCommaSeparatedList(const std::function<ParseResult()> &parseElement);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700157
Chris Lattnerf7e22732018-06-22 22:03:48 -0700158 // We have two forms of parsing methods - those that return a non-null
159 // pointer on success, and those that return a ParseResult to indicate whether
160 // they returned a failure. The second class fills in by-reference arguments
161 // as the results of their action.
162
Chris Lattnere79379a2018-06-22 10:39:19 -0700163 // Type parsing.
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700164 Type *parsePrimitiveType();
Chris Lattnerf7e22732018-06-22 22:03:48 -0700165 Type *parseElementType();
166 VectorType *parseVectorType();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700167 ParseResult parseDimensionListRanked(SmallVectorImpl<int> &dimensions);
Chris Lattnerf7e22732018-06-22 22:03:48 -0700168 Type *parseTensorType();
169 Type *parseMemRefType();
170 Type *parseFunctionType();
171 Type *parseType();
Chris Lattner1604e472018-07-23 08:42:19 -0700172 ParseResult parseTypeListNoParens(SmallVectorImpl<Type *> &elements);
James Molloy0ff71542018-07-23 16:56:32 -0700173 ParseResult parseTypeList(SmallVectorImpl<Type *> &elements);
Chris Lattnere79379a2018-06-22 10:39:19 -0700174
Chris Lattner7121b802018-07-04 20:45:39 -0700175 // Attribute parsing.
176 Attribute *parseAttribute();
177 ParseResult parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes);
178
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700179 // Polyhedral structures.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700180 AffineMap *parseAffineMapInline();
MLIR Team718c82f2018-07-16 09:45:22 -0700181 AffineMap *parseAffineMapReference();
MLIR Teamf85a6262018-06-27 11:03:08 -0700182
Chris Lattner48af7d12018-07-09 19:05:38 -0700183private:
184 // The Parser is subclassed and reinstantiated. Do not add additional
185 // non-trivial state here, add it to the ParserState class.
186 ParserState &state;
Chris Lattnere79379a2018-06-22 10:39:19 -0700187};
188} // end anonymous namespace
189
190//===----------------------------------------------------------------------===//
191// Helper methods.
192//===----------------------------------------------------------------------===//
193
Chris Lattner4c95a502018-06-23 16:03:42 -0700194ParseResult Parser::emitError(SMLoc loc, const Twine &message) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700195 // If we hit a parse error in response to a lexer error, then the lexer
Jacques Pienaar9c411be2018-06-24 19:17:35 -0700196 // already reported the error.
Chris Lattner48af7d12018-07-09 19:05:38 -0700197 if (getToken().is(Token::error))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700198 return ParseFailure;
199
Chris Lattner48af7d12018-07-09 19:05:38 -0700200 auto &sourceMgr = state.lex.getSourceMgr();
201 state.errorReporter(sourceMgr.GetMessage(loc, SourceMgr::DK_Error, message));
Chris Lattnere79379a2018-06-22 10:39:19 -0700202 return ParseFailure;
203}
204
Chris Lattnerf7702a62018-07-23 17:30:01 -0700205/// Consume the specified token if present and return success. On failure,
206/// output a diagnostic and return failure.
207ParseResult Parser::parseToken(Token::Kind expectedToken,
208 const Twine &message) {
209 if (consumeIf(expectedToken))
210 return ParseSuccess;
211 return emitError(message);
212}
213
Chris Lattner40746442018-07-21 14:32:09 -0700214/// Parse a comma separated list of elements that must have at least one entry
215/// in it.
216ParseResult Parser::parseCommaSeparatedList(
217 const std::function<ParseResult()> &parseElement) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700218 // Non-empty case starts with an element.
219 if (parseElement())
220 return ParseFailure;
221
222 // Otherwise we have a list of comma separated elements.
223 while (consumeIf(Token::comma)) {
224 if (parseElement())
225 return ParseFailure;
226 }
Chris Lattner40746442018-07-21 14:32:09 -0700227 return ParseSuccess;
228}
229
230/// Parse a comma-separated list of elements, terminated with an arbitrary
231/// token. This allows empty lists if allowEmptyList is true.
232///
233/// abstract-list ::= rightToken // if allowEmptyList == true
234/// abstract-list ::= element (',' element)* rightToken
235///
236ParseResult Parser::parseCommaSeparatedListUntil(
237 Token::Kind rightToken, const std::function<ParseResult()> &parseElement,
238 bool allowEmptyList) {
239 // Handle the empty case.
240 if (getToken().is(rightToken)) {
241 if (!allowEmptyList)
242 return emitError("expected list element");
243 consumeToken(rightToken);
244 return ParseSuccess;
245 }
246
Chris Lattnerf7702a62018-07-23 17:30:01 -0700247 if (parseCommaSeparatedList(parseElement) ||
248 parseToken(rightToken, "expected ',' or '" +
249 Token::getTokenSpelling(rightToken) + "'"))
Chris Lattner40746442018-07-21 14:32:09 -0700250 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700251
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700252 return ParseSuccess;
253}
Chris Lattnere79379a2018-06-22 10:39:19 -0700254
255//===----------------------------------------------------------------------===//
256// Type Parsing
257//===----------------------------------------------------------------------===//
258
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700259/// Parse the low-level fixed dtypes in the system.
260///
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700261/// primitive-type ::= `f16` | `bf16` | `f32` | `f64`
262/// primitive-type ::= integer-type
263/// primitive-type ::= `affineint`
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700264///
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700265Type *Parser::parsePrimitiveType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700266 switch (getToken().getKind()) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700267 default:
268 return (emitError("expected type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700269 case Token::kw_bf16:
270 consumeToken(Token::kw_bf16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700271 return builder.getBF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700272 case Token::kw_f16:
273 consumeToken(Token::kw_f16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700274 return builder.getF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700275 case Token::kw_f32:
276 consumeToken(Token::kw_f32);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700277 return builder.getF32Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700278 case Token::kw_f64:
279 consumeToken(Token::kw_f64);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700280 return builder.getF64Type();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700281 case Token::kw_affineint:
282 consumeToken(Token::kw_affineint);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700283 return builder.getAffineIntType();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700284 case Token::inttype: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700285 auto width = getToken().getIntTypeBitwidth();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700286 if (!width.hasValue())
287 return (emitError("invalid integer width"), nullptr);
288 consumeToken(Token::inttype);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700289 return builder.getIntegerType(width.getValue());
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700290 }
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700291 }
292}
293
294/// Parse the element type of a tensor or memref type.
295///
296/// element-type ::= primitive-type | vector-type
297///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700298Type *Parser::parseElementType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700299 if (getToken().is(Token::kw_vector))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700300 return parseVectorType();
301
302 return parsePrimitiveType();
303}
304
305/// Parse a vector type.
306///
307/// vector-type ::= `vector` `<` const-dimension-list primitive-type `>`
308/// const-dimension-list ::= (integer-literal `x`)+
309///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700310VectorType *Parser::parseVectorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700311 consumeToken(Token::kw_vector);
312
Chris Lattnerf7702a62018-07-23 17:30:01 -0700313 if (parseToken(Token::less, "expected '<' in vector type"))
314 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700315
Chris Lattner48af7d12018-07-09 19:05:38 -0700316 if (getToken().isNot(Token::integer))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700317 return (emitError("expected dimension size in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700318
319 SmallVector<unsigned, 4> dimensions;
Chris Lattner48af7d12018-07-09 19:05:38 -0700320 while (getToken().is(Token::integer)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700321 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700322 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700323 if (!dimension.hasValue())
Chris Lattnerf7e22732018-06-22 22:03:48 -0700324 return (emitError("invalid dimension in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700325 dimensions.push_back(dimension.getValue());
326
327 consumeToken(Token::integer);
328
329 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700330 if (getToken().isNot(Token::bare_identifier) ||
331 getTokenSpelling()[0] != 'x')
Chris Lattnerf7e22732018-06-22 22:03:48 -0700332 return (emitError("expected 'x' in vector dimension list"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700333
334 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700335 if (getTokenSpelling().size() != 1)
336 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700337
338 // Consume the 'x'.
339 consumeToken(Token::bare_identifier);
340 }
341
342 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700343 auto *elementType = parsePrimitiveType();
344 if (!elementType)
345 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700346
Chris Lattnerf7702a62018-07-23 17:30:01 -0700347 if (parseToken(Token::greater, "expected '>' in vector type"))
348 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700349
Chris Lattnerf7e22732018-06-22 22:03:48 -0700350 return VectorType::get(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700351}
352
353/// Parse a dimension list of a tensor or memref type. This populates the
354/// dimension list, returning -1 for the '?' dimensions.
355///
356/// dimension-list-ranked ::= (dimension `x`)*
357/// dimension ::= `?` | integer-literal
358///
359ParseResult Parser::parseDimensionListRanked(SmallVectorImpl<int> &dimensions) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700360 while (getToken().isAny(Token::integer, Token::question)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700361 if (consumeIf(Token::question)) {
362 dimensions.push_back(-1);
363 } else {
364 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700365 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700366 if (!dimension.hasValue() || (int)dimension.getValue() < 0)
367 return emitError("invalid dimension");
368 dimensions.push_back((int)dimension.getValue());
369 consumeToken(Token::integer);
370 }
371
372 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700373 if (getToken().isNot(Token::bare_identifier) ||
374 getTokenSpelling()[0] != 'x')
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700375 return emitError("expected 'x' in dimension list");
376
377 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700378 if (getTokenSpelling().size() != 1)
379 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700380
381 // Consume the 'x'.
382 consumeToken(Token::bare_identifier);
383 }
384
385 return ParseSuccess;
386}
387
388/// Parse a tensor type.
389///
390/// tensor-type ::= `tensor` `<` dimension-list element-type `>`
391/// dimension-list ::= dimension-list-ranked | `??`
392///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700393Type *Parser::parseTensorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700394 consumeToken(Token::kw_tensor);
395
Chris Lattnerf7702a62018-07-23 17:30:01 -0700396 if (parseToken(Token::less, "expected '<' in tensor type"))
397 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700398
399 bool isUnranked;
400 SmallVector<int, 4> dimensions;
401
402 if (consumeIf(Token::questionquestion)) {
403 isUnranked = true;
404 } else {
405 isUnranked = false;
406 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700407 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700408 }
409
410 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700411 auto elementType = parseElementType();
412 if (!elementType)
413 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700414
Chris Lattnerf7702a62018-07-23 17:30:01 -0700415 if (parseToken(Token::greater, "expected '>' in tensor type"))
416 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700417
MLIR Team355ec862018-06-23 18:09:09 -0700418 if (isUnranked)
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700419 return builder.getTensorType(elementType);
420 return builder.getTensorType(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700421}
422
423/// Parse a memref type.
424///
425/// memref-type ::= `memref` `<` dimension-list-ranked element-type
426/// (`,` semi-affine-map-composition)? (`,` memory-space)? `>`
427///
428/// semi-affine-map-composition ::= (semi-affine-map `,` )* semi-affine-map
429/// memory-space ::= integer-literal /* | TODO: address-space-id */
430///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700431Type *Parser::parseMemRefType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700432 consumeToken(Token::kw_memref);
433
Chris Lattnerf7702a62018-07-23 17:30:01 -0700434 if (parseToken(Token::less, "expected '<' in memref type"))
435 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700436
437 SmallVector<int, 4> dimensions;
438 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700439 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700440
441 // Parse the element type.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700442 auto elementType = parseElementType();
443 if (!elementType)
444 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700445
MLIR Team718c82f2018-07-16 09:45:22 -0700446 // Parse semi-affine-map-composition.
James Molloy0ff71542018-07-23 16:56:32 -0700447 SmallVector<AffineMap *, 2> affineMapComposition;
Chris Lattner413db6a2018-07-25 12:55:50 -0700448 unsigned memorySpace = 0;
MLIR Team718c82f2018-07-16 09:45:22 -0700449 bool parsedMemorySpace = false;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700450
MLIR Team718c82f2018-07-16 09:45:22 -0700451 auto parseElt = [&]() -> ParseResult {
452 if (getToken().is(Token::integer)) {
453 // Parse memory space.
454 if (parsedMemorySpace)
455 return emitError("multiple memory spaces specified in memref type");
456 auto v = getToken().getUnsignedIntegerValue();
457 if (!v.hasValue())
458 return emitError("invalid memory space in memref type");
459 memorySpace = v.getValue();
460 consumeToken(Token::integer);
461 parsedMemorySpace = true;
462 } else {
463 // Parse affine map.
464 if (parsedMemorySpace)
465 return emitError("affine map after memory space in memref type");
James Molloy0ff71542018-07-23 16:56:32 -0700466 auto *affineMap = parseAffineMapReference();
MLIR Team718c82f2018-07-16 09:45:22 -0700467 if (affineMap == nullptr)
468 return ParseFailure;
469 affineMapComposition.push_back(affineMap);
470 }
471 return ParseSuccess;
472 };
473
Chris Lattner413db6a2018-07-25 12:55:50 -0700474 // Parse a list of mappings and address space if present.
475 if (consumeIf(Token::comma)) {
476 // Parse comma separated list of affine maps, followed by memory space.
477 if (parseCommaSeparatedListUntil(Token::greater, parseElt,
478 /*allowEmptyList=*/false)) {
479 return nullptr;
480 }
481 } else {
482 if (parseToken(Token::greater, "expected ',' or '>' in memref type"))
483 return nullptr;
MLIR Team718c82f2018-07-16 09:45:22 -0700484 }
MLIR Team718c82f2018-07-16 09:45:22 -0700485
486 return MemRefType::get(dimensions, elementType, affineMapComposition,
487 memorySpace);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700488}
489
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700490/// Parse a function type.
491///
492/// function-type ::= type-list-parens `->` type-list
493///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700494Type *Parser::parseFunctionType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700495 assert(getToken().is(Token::l_paren));
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700496
Chris Lattnerf7702a62018-07-23 17:30:01 -0700497 SmallVector<Type *, 4> arguments, results;
498 if (parseTypeList(arguments) ||
499 parseToken(Token::arrow, "expected '->' in function type") ||
500 parseTypeList(results))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700501 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700502
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700503 return builder.getFunctionType(arguments, results);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700504}
505
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700506/// Parse an arbitrary type.
507///
508/// type ::= primitive-type
509/// | vector-type
510/// | tensor-type
511/// | memref-type
512/// | function-type
513/// element-type ::= primitive-type | vector-type
514///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700515Type *Parser::parseType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700516 switch (getToken().getKind()) {
James Molloy0ff71542018-07-23 16:56:32 -0700517 case Token::kw_memref:
518 return parseMemRefType();
519 case Token::kw_tensor:
520 return parseTensorType();
521 case Token::kw_vector:
522 return parseVectorType();
523 case Token::l_paren:
524 return parseFunctionType();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700525 default:
526 return parsePrimitiveType();
527 }
528}
529
Chris Lattner1604e472018-07-23 08:42:19 -0700530/// Parse a list of types without an enclosing parenthesis. The list must have
531/// at least one member.
532///
533/// type-list-no-parens ::= type (`,` type)*
534///
535ParseResult Parser::parseTypeListNoParens(SmallVectorImpl<Type *> &elements) {
536 auto parseElt = [&]() -> ParseResult {
537 auto elt = parseType();
538 elements.push_back(elt);
539 return elt ? ParseSuccess : ParseFailure;
540 };
541
542 return parseCommaSeparatedList(parseElt);
543}
544
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700545/// Parse a "type list", which is a singular type, or a parenthesized list of
546/// types.
547///
548/// type-list ::= type-list-parens | type
549/// type-list-parens ::= `(` `)`
Chris Lattner1604e472018-07-23 08:42:19 -0700550/// | `(` type-list-no-parens `)`
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700551///
James Molloy0ff71542018-07-23 16:56:32 -0700552ParseResult Parser::parseTypeList(SmallVectorImpl<Type *> &elements) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700553 auto parseElt = [&]() -> ParseResult {
554 auto elt = parseType();
555 elements.push_back(elt);
556 return elt ? ParseSuccess : ParseFailure;
557 };
558
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700559 // If there is no parens, then it must be a singular type.
560 if (!consumeIf(Token::l_paren))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700561 return parseElt();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700562
Chris Lattner40746442018-07-21 14:32:09 -0700563 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700564 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700565
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700566 return ParseSuccess;
567}
568
Chris Lattner4c95a502018-06-23 16:03:42 -0700569//===----------------------------------------------------------------------===//
Chris Lattner7121b802018-07-04 20:45:39 -0700570// Attribute parsing.
571//===----------------------------------------------------------------------===//
572
Chris Lattner7121b802018-07-04 20:45:39 -0700573/// Attribute parsing.
574///
575/// attribute-value ::= bool-literal
576/// | integer-literal
577/// | float-literal
578/// | string-literal
579/// | `[` (attribute-value (`,` attribute-value)*)? `]`
580///
581Attribute *Parser::parseAttribute() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700582 switch (getToken().getKind()) {
Chris Lattner7121b802018-07-04 20:45:39 -0700583 case Token::kw_true:
584 consumeToken(Token::kw_true);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700585 return builder.getBoolAttr(true);
Chris Lattner7121b802018-07-04 20:45:39 -0700586 case Token::kw_false:
587 consumeToken(Token::kw_false);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700588 return builder.getBoolAttr(false);
Chris Lattner7121b802018-07-04 20:45:39 -0700589
590 case Token::integer: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700591 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700592 if (!val.hasValue() || (int64_t)val.getValue() < 0)
593 return (emitError("integer too large for attribute"), nullptr);
594 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700595 return builder.getIntegerAttr((int64_t)val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700596 }
597
598 case Token::minus: {
599 consumeToken(Token::minus);
Chris Lattner48af7d12018-07-09 19:05:38 -0700600 if (getToken().is(Token::integer)) {
601 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700602 if (!val.hasValue() || (int64_t)-val.getValue() >= 0)
603 return (emitError("integer too large for attribute"), nullptr);
604 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700605 return builder.getIntegerAttr((int64_t)-val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700606 }
607
608 return (emitError("expected constant integer or floating point value"),
609 nullptr);
610 }
611
612 case Token::string: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700613 auto val = getToken().getStringValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700614 consumeToken(Token::string);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700615 return builder.getStringAttr(val);
Chris Lattner7121b802018-07-04 20:45:39 -0700616 }
617
Chris Lattner85ee1512018-07-25 11:15:20 -0700618 case Token::l_square: {
619 consumeToken(Token::l_square);
James Molloy0ff71542018-07-23 16:56:32 -0700620 SmallVector<Attribute *, 4> elements;
Chris Lattner7121b802018-07-04 20:45:39 -0700621
622 auto parseElt = [&]() -> ParseResult {
623 elements.push_back(parseAttribute());
624 return elements.back() ? ParseSuccess : ParseFailure;
625 };
626
Chris Lattner85ee1512018-07-25 11:15:20 -0700627 if (parseCommaSeparatedListUntil(Token::r_square, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700628 return nullptr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700629 return builder.getArrayAttr(elements);
Chris Lattner7121b802018-07-04 20:45:39 -0700630 }
631 default:
MLIR Teamb61885d2018-07-18 16:29:21 -0700632 // Try to parse affine map reference.
James Molloy0ff71542018-07-23 16:56:32 -0700633 auto *affineMap = parseAffineMapReference();
MLIR Teamb61885d2018-07-18 16:29:21 -0700634 if (affineMap != nullptr)
635 return builder.getAffineMapAttr(affineMap);
636
Chris Lattner7121b802018-07-04 20:45:39 -0700637 // TODO: Handle floating point.
638 return (emitError("expected constant attribute value"), nullptr);
639 }
640}
641
Chris Lattner7121b802018-07-04 20:45:39 -0700642/// Attribute dictionary.
643///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700644/// attribute-dict ::= `{` `}`
645/// | `{` attribute-entry (`,` attribute-entry)* `}`
646/// attribute-entry ::= bare-id `:` attribute-value
Chris Lattner7121b802018-07-04 20:45:39 -0700647///
James Molloy0ff71542018-07-23 16:56:32 -0700648ParseResult
649Parser::parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes) {
Chris Lattner7121b802018-07-04 20:45:39 -0700650 consumeToken(Token::l_brace);
651
652 auto parseElt = [&]() -> ParseResult {
653 // We allow keywords as attribute names.
Chris Lattner48af7d12018-07-09 19:05:38 -0700654 if (getToken().isNot(Token::bare_identifier, Token::inttype) &&
655 !getToken().isKeyword())
Chris Lattner7121b802018-07-04 20:45:39 -0700656 return emitError("expected attribute name");
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700657 auto nameId = builder.getIdentifier(getTokenSpelling());
Chris Lattner7121b802018-07-04 20:45:39 -0700658 consumeToken();
659
Chris Lattnerf7702a62018-07-23 17:30:01 -0700660 if (parseToken(Token::colon, "expected ':' in attribute list"))
661 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700662
663 auto attr = parseAttribute();
James Molloy0ff71542018-07-23 16:56:32 -0700664 if (!attr)
665 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700666
667 attributes.push_back({nameId, attr});
668 return ParseSuccess;
669 };
670
Chris Lattner40746442018-07-21 14:32:09 -0700671 if (parseCommaSeparatedListUntil(Token::r_brace, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700672 return ParseFailure;
673
674 return ParseSuccess;
675}
676
677//===----------------------------------------------------------------------===//
MLIR Teamf85a6262018-06-27 11:03:08 -0700678// Polyhedral structures.
679//===----------------------------------------------------------------------===//
680
Chris Lattner2e595eb2018-07-10 10:08:27 -0700681/// Lower precedence ops (all at the same precedence level). LNoOp is false in
682/// the boolean sense.
683enum AffineLowPrecOp {
684 /// Null value.
685 LNoOp,
686 Add,
687 Sub
688};
MLIR Teamf85a6262018-06-27 11:03:08 -0700689
Chris Lattner2e595eb2018-07-10 10:08:27 -0700690/// Higher precedence ops - all at the same precedence level. HNoOp is false in
691/// the boolean sense.
692enum AffineHighPrecOp {
693 /// Null value.
694 HNoOp,
695 Mul,
696 FloorDiv,
697 CeilDiv,
698 Mod
699};
Chris Lattner7121b802018-07-04 20:45:39 -0700700
Chris Lattner2e595eb2018-07-10 10:08:27 -0700701namespace {
702/// This is a specialized parser for AffineMap's, maintaining the state
703/// transient to their bodies.
704class AffineMapParser : public Parser {
705public:
706 explicit AffineMapParser(ParserState &state) : Parser(state) {}
Chris Lattner7121b802018-07-04 20:45:39 -0700707
Chris Lattner2e595eb2018-07-10 10:08:27 -0700708 AffineMap *parseAffineMapInline();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700709
Chris Lattner2e595eb2018-07-10 10:08:27 -0700710private:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700711 // Binary affine op parsing.
712 AffineLowPrecOp consumeIfLowPrecOp();
713 AffineHighPrecOp consumeIfHighPrecOp();
MLIR Teamf85a6262018-06-27 11:03:08 -0700714
Chris Lattner2e595eb2018-07-10 10:08:27 -0700715 // Identifier lists for polyhedral structures.
Chris Lattner413db6a2018-07-25 12:55:50 -0700716 ParseResult parseDimIdList(unsigned &numDims);
717 ParseResult parseSymbolIdList(unsigned &numSymbols);
718 ParseResult parseIdentifierDefinition(AffineExpr *idExpr);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700719
720 AffineExpr *parseAffineExpr();
721 AffineExpr *parseParentheticalExpr();
722 AffineExpr *parseNegateExpression(AffineExpr *lhs);
723 AffineExpr *parseIntegerExpr();
724 AffineExpr *parseBareIdExpr();
725
726 AffineExpr *getBinaryAffineOpExpr(AffineHighPrecOp op, AffineExpr *lhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700727 AffineExpr *rhs, SMLoc opLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700728 AffineExpr *getBinaryAffineOpExpr(AffineLowPrecOp op, AffineExpr *lhs,
729 AffineExpr *rhs);
730 AffineExpr *parseAffineOperandExpr(AffineExpr *lhs);
731 AffineExpr *parseAffineLowPrecOpExpr(AffineExpr *llhs,
732 AffineLowPrecOp llhsOp);
733 AffineExpr *parseAffineHighPrecOpExpr(AffineExpr *llhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700734 AffineHighPrecOp llhsOp,
735 SMLoc llhsOpLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700736
737private:
Chris Lattner413db6a2018-07-25 12:55:50 -0700738 SmallVector<std::pair<StringRef, AffineExpr *>, 4> dimsAndSymbols;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700739};
740} // end anonymous namespace
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700741
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700742/// Create an affine binary high precedence op expression (mul's, div's, mod).
743/// opLoc is the location of the op token to be used to report errors
744/// for non-conforming expressions.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700745AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineHighPrecOp op,
746 AffineExpr *lhs,
Chris Lattner40746442018-07-21 14:32:09 -0700747 AffineExpr *rhs,
748 SMLoc opLoc) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700749 // TODO: make the error location info accurate.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700750 switch (op) {
751 case Mul:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700752 if (!lhs->isSymbolicOrConstant() && !rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700753 emitError(opLoc, "non-affine expression: at least one of the multiply "
754 "operands has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700755 return nullptr;
756 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700757 return builder.getMulExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700758 case FloorDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700759 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700760 emitError(opLoc, "non-affine expression: right operand of floordiv "
761 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700762 return nullptr;
763 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700764 return builder.getFloorDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700765 case CeilDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700766 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700767 emitError(opLoc, "non-affine expression: right operand of ceildiv "
768 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700769 return nullptr;
770 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700771 return builder.getCeilDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700772 case Mod:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700773 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700774 emitError(opLoc, "non-affine expression: right operand of mod "
775 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700776 return nullptr;
777 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700778 return builder.getModExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700779 case HNoOp:
780 llvm_unreachable("can't create affine expression for null high prec op");
781 return nullptr;
782 }
783}
784
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700785/// Create an affine binary low precedence op expression (add, sub).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700786AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineLowPrecOp op,
787 AffineExpr *lhs,
788 AffineExpr *rhs) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700789 switch (op) {
790 case AffineLowPrecOp::Add:
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700791 return builder.getAddExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700792 case AffineLowPrecOp::Sub:
Uday Bondhugulac1faf662018-07-19 14:08:50 -0700793 return builder.getAddExpr(
794 lhs, builder.getMulExpr(rhs, builder.getConstantExpr(-1)));
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700795 case AffineLowPrecOp::LNoOp:
796 llvm_unreachable("can't create affine expression for null low prec op");
797 return nullptr;
798 }
799}
800
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700801/// Consume this token if it is a lower precedence affine op (there are only two
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700802/// precedence levels).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700803AffineLowPrecOp AffineMapParser::consumeIfLowPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700804 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700805 case Token::plus:
806 consumeToken(Token::plus);
807 return AffineLowPrecOp::Add;
808 case Token::minus:
809 consumeToken(Token::minus);
810 return AffineLowPrecOp::Sub;
811 default:
812 return AffineLowPrecOp::LNoOp;
813 }
814}
815
816/// Consume this token if it is a higher precedence affine op (there are only
817/// two precedence levels)
Chris Lattner2e595eb2018-07-10 10:08:27 -0700818AffineHighPrecOp AffineMapParser::consumeIfHighPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700819 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700820 case Token::star:
821 consumeToken(Token::star);
822 return Mul;
823 case Token::kw_floordiv:
824 consumeToken(Token::kw_floordiv);
825 return FloorDiv;
826 case Token::kw_ceildiv:
827 consumeToken(Token::kw_ceildiv);
828 return CeilDiv;
829 case Token::kw_mod:
830 consumeToken(Token::kw_mod);
831 return Mod;
832 default:
833 return HNoOp;
834 }
835}
836
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700837/// Parse a high precedence op expression list: mul, div, and mod are high
838/// precedence binary ops, i.e., parse a
839/// expr_1 op_1 expr_2 op_2 ... expr_n
840/// where op_1, op_2 are all a AffineHighPrecOp (mul, div, mod).
841/// All affine binary ops are left associative.
842/// Given llhs, returns (llhs llhsOp lhs) op rhs, or (lhs op rhs) if llhs is
843/// null. If no rhs can be found, returns (llhs llhsOp lhs) or lhs if llhs is
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700844/// null. llhsOpLoc is the location of the llhsOp token that will be used to
845/// report an error for non-conforming expressions.
846AffineExpr *AffineMapParser::parseAffineHighPrecOpExpr(AffineExpr *llhs,
847 AffineHighPrecOp llhsOp,
848 SMLoc llhsOpLoc) {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700849 AffineExpr *lhs = parseAffineOperandExpr(llhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700850 if (!lhs)
851 return nullptr;
852
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700853 // Found an LHS. Parse the remaining expression.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700854 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -0700855 if (AffineHighPrecOp op = consumeIfHighPrecOp()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700856 if (llhs) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700857 AffineExpr *expr = getBinaryAffineOpExpr(llhsOp, llhs, lhs, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700858 if (!expr)
859 return nullptr;
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700860 return parseAffineHighPrecOpExpr(expr, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700861 }
862 // No LLHS, get RHS
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700863 return parseAffineHighPrecOpExpr(lhs, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700864 }
865
866 // This is the last operand in this expression.
867 if (llhs)
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700868 return getBinaryAffineOpExpr(llhsOp, llhs, lhs, llhsOpLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700869
870 // No llhs, 'lhs' itself is the expression.
871 return lhs;
872}
873
874/// Parse an affine expression inside parentheses.
875///
876/// affine-expr ::= `(` affine-expr `)`
Chris Lattner2e595eb2018-07-10 10:08:27 -0700877AffineExpr *AffineMapParser::parseParentheticalExpr() {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700878 if (parseToken(Token::l_paren, "expected '('"))
879 return nullptr;
Chris Lattner48af7d12018-07-09 19:05:38 -0700880 if (getToken().is(Token::r_paren))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700881 return (emitError("no expression inside parentheses"), nullptr);
Chris Lattnerf7702a62018-07-23 17:30:01 -0700882
Chris Lattner2e595eb2018-07-10 10:08:27 -0700883 auto *expr = parseAffineExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700884 if (!expr)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700885 return nullptr;
Chris Lattnerf7702a62018-07-23 17:30:01 -0700886 if (parseToken(Token::r_paren, "expected ')'"))
887 return nullptr;
888
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700889 return expr;
890}
891
892/// Parse the negation expression.
893///
894/// affine-expr ::= `-` affine-expr
Chris Lattner2e595eb2018-07-10 10:08:27 -0700895AffineExpr *AffineMapParser::parseNegateExpression(AffineExpr *lhs) {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700896 if (parseToken(Token::minus, "expected '-'"))
897 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700898
Chris Lattner2e595eb2018-07-10 10:08:27 -0700899 AffineExpr *operand = parseAffineOperandExpr(lhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700900 // Since negation has the highest precedence of all ops (including high
901 // precedence ops) but lower than parentheses, we are only going to use
902 // parseAffineOperandExpr instead of parseAffineExpr here.
903 if (!operand)
904 // Extra error message although parseAffineOperandExpr would have
905 // complained. Leads to a better diagnostic.
906 return (emitError("missing operand of negation"), nullptr);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700907 auto *minusOne = builder.getConstantExpr(-1);
908 return builder.getMulExpr(minusOne, operand);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700909}
910
911/// Parse a bare id that may appear in an affine expression.
912///
913/// affine-expr ::= bare-id
Chris Lattner2e595eb2018-07-10 10:08:27 -0700914AffineExpr *AffineMapParser::parseBareIdExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700915 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700916 return (emitError("expected bare identifier"), nullptr);
917
Chris Lattner48af7d12018-07-09 19:05:38 -0700918 StringRef sRef = getTokenSpelling();
Chris Lattner413db6a2018-07-25 12:55:50 -0700919 for (auto entry : dimsAndSymbols) {
920 if (entry.first != sRef)
921 continue;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700922
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700923 consumeToken(Token::bare_identifier);
Chris Lattner413db6a2018-07-25 12:55:50 -0700924 return entry.second;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700925 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700926
927 return (emitError("use of undeclared identifier"), nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700928}
929
930/// Parse a positive integral constant appearing in an affine expression.
931///
932/// affine-expr ::= integer-literal
Chris Lattner2e595eb2018-07-10 10:08:27 -0700933AffineExpr *AffineMapParser::parseIntegerExpr() {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700934 // No need to handle negative numbers separately here. They are naturally
935 // handled via the unary negation operator, although (FIXME) MININT_64 still
936 // not correctly handled.
Chris Lattner48af7d12018-07-09 19:05:38 -0700937 if (getToken().isNot(Token::integer))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700938 return (emitError("expected integer"), nullptr);
939
Chris Lattner48af7d12018-07-09 19:05:38 -0700940 auto val = getToken().getUInt64IntegerValue();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700941 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
942 return (emitError("constant too large for affineint"), nullptr);
943 }
944 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700945 return builder.getConstantExpr((int64_t)val.getValue());
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700946}
947
948/// Parses an expression that can be a valid operand of an affine expression.
Uday Bondhugula76345202018-07-09 13:47:52 -0700949/// lhs: if non-null, lhs is an affine expression that is the lhs of a binary
950/// operator, the rhs of which is being parsed. This is used to determine
951/// whether an error should be emitted for a missing right operand.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700952// Eg: for an expression without parentheses (like i + j + k + l), each
953// of the four identifiers is an operand. For i + j*k + l, j*k is not an
954// operand expression, it's an op expression and will be parsed via
955// parseAffineHighPrecOpExpression(). However, for i + (j*k) + -l, (j*k) and -l
956// are valid operands that will be parsed by this function.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700957AffineExpr *AffineMapParser::parseAffineOperandExpr(AffineExpr *lhs) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700958 switch (getToken().getKind()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700959 case Token::bare_identifier:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700960 return parseBareIdExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700961 case Token::integer:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700962 return parseIntegerExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700963 case Token::l_paren:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700964 return parseParentheticalExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700965 case Token::minus:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700966 return parseNegateExpression(lhs);
Uday Bondhugula76345202018-07-09 13:47:52 -0700967 case Token::kw_ceildiv:
968 case Token::kw_floordiv:
969 case Token::kw_mod:
970 case Token::plus:
971 case Token::star:
972 if (lhs)
973 emitError("missing right operand of binary operator");
974 else
975 emitError("missing left operand of binary operator");
976 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700977 default:
978 if (lhs)
Uday Bondhugula76345202018-07-09 13:47:52 -0700979 emitError("missing right operand of binary operator");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700980 else
981 emitError("expected affine expression");
982 return nullptr;
983 }
984}
985
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700986/// Parse affine expressions that are bare-id's, integer constants,
987/// parenthetical affine expressions, and affine op expressions that are a
988/// composition of those.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700989///
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700990/// All binary op's associate from left to right.
991///
992/// {add, sub} have lower precedence than {mul, div, and mod}.
993///
Uday Bondhugula76345202018-07-09 13:47:52 -0700994/// Add, sub'are themselves at the same precedence level. Mul, floordiv,
995/// ceildiv, and mod are at the same higher precedence level. Negation has
996/// higher precedence than any binary op.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700997///
998/// llhs: the affine expression appearing on the left of the one being parsed.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700999/// This function will return ((llhs llhsOp lhs) op rhs) if llhs is non null,
1000/// and lhs op rhs otherwise; if there is no rhs, llhs llhsOp lhs is returned if
1001/// llhs is non-null; otherwise lhs is returned. This is to deal with left
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001002/// associativity.
1003///
1004/// Eg: when the expression is e1 + e2*e3 + e4, with e1 as llhs, this function
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001005/// will return the affine expr equivalent of (e1 + (e2*e3)) + e4, where (e2*e3)
1006/// will be parsed using parseAffineHighPrecOpExpr().
Chris Lattner2e595eb2018-07-10 10:08:27 -07001007AffineExpr *AffineMapParser::parseAffineLowPrecOpExpr(AffineExpr *llhs,
1008 AffineLowPrecOp llhsOp) {
Uday Bondhugula76345202018-07-09 13:47:52 -07001009 AffineExpr *lhs;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001010 if (!(lhs = parseAffineOperandExpr(llhs)))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001011 return nullptr;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001012
1013 // Found an LHS. Deal with the ops.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001014 if (AffineLowPrecOp lOp = consumeIfLowPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001015 if (llhs) {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001016 AffineExpr *sum = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001017 return parseAffineLowPrecOpExpr(sum, lOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001018 }
1019 // No LLHS, get RHS and form the expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001020 return parseAffineLowPrecOpExpr(lhs, lOp);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001021 }
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001022 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07001023 if (AffineHighPrecOp hOp = consumeIfHighPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001024 // We have a higher precedence op here. Get the rhs operand for the llhs
1025 // through parseAffineHighPrecOpExpr.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001026 AffineExpr *highRes = parseAffineHighPrecOpExpr(lhs, hOp, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001027 if (!highRes)
1028 return nullptr;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001029
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001030 // If llhs is null, the product forms the first operand of the yet to be
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001031 // found expression. If non-null, the op to associate with llhs is llhsOp.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001032 AffineExpr *expr =
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001033 llhs ? getBinaryAffineOpExpr(llhsOp, llhs, highRes) : highRes;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001034
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001035 // Recurse for subsequent low prec op's after the affine high prec op
1036 // expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001037 if (AffineLowPrecOp nextOp = consumeIfLowPrecOp())
1038 return parseAffineLowPrecOpExpr(expr, nextOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001039 return expr;
1040 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001041 // Last operand in the expression list.
1042 if (llhs)
1043 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
1044 // No llhs, 'lhs' itself is the expression.
1045 return lhs;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001046}
1047
1048/// Parse an affine expression.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001049/// affine-expr ::= `(` affine-expr `)`
1050/// | `-` affine-expr
1051/// | affine-expr `+` affine-expr
1052/// | affine-expr `-` affine-expr
1053/// | affine-expr `*` affine-expr
1054/// | affine-expr `floordiv` affine-expr
1055/// | affine-expr `ceildiv` affine-expr
1056/// | affine-expr `mod` affine-expr
1057/// | bare-id
1058/// | integer-literal
1059///
1060/// Additional conditions are checked depending on the production. For eg., one
1061/// of the operands for `*` has to be either constant/symbolic; the second
1062/// operand for floordiv, ceildiv, and mod has to be a positive integer.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001063AffineExpr *AffineMapParser::parseAffineExpr() {
1064 return parseAffineLowPrecOpExpr(nullptr, AffineLowPrecOp::LNoOp);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001065}
1066
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001067/// Parse a dim or symbol from the lists appearing before the actual expressions
Chris Lattner2e595eb2018-07-10 10:08:27 -07001068/// of the affine map. Update our state to store the dimensional/symbolic
Chris Lattner413db6a2018-07-25 12:55:50 -07001069/// identifier.
1070ParseResult AffineMapParser::parseIdentifierDefinition(AffineExpr *idExpr) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001071 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001072 return emitError("expected bare identifier");
Chris Lattner413db6a2018-07-25 12:55:50 -07001073
1074 auto name = getTokenSpelling();
1075 for (auto entry : dimsAndSymbols) {
1076 if (entry.first == name)
1077 return emitError("redefinition of identifier '" + Twine(name) + "'");
1078 }
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001079 consumeToken(Token::bare_identifier);
Chris Lattner413db6a2018-07-25 12:55:50 -07001080
1081 dimsAndSymbols.push_back({name, idExpr});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001082 return ParseSuccess;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001083}
1084
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001085/// Parse the list of symbolic identifiers to an affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001086ParseResult AffineMapParser::parseSymbolIdList(unsigned &numSymbols) {
1087 consumeToken(Token::l_square);
1088 auto parseElt = [&]() -> ParseResult {
1089 auto *symbol = AffineSymbolExpr::get(numSymbols++, getContext());
1090 return parseIdentifierDefinition(symbol);
1091 };
Chris Lattner85ee1512018-07-25 11:15:20 -07001092 return parseCommaSeparatedListUntil(Token::r_square, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001093}
1094
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001095/// Parse the list of dimensional identifiers to an affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001096ParseResult AffineMapParser::parseDimIdList(unsigned &numDims) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07001097 if (parseToken(Token::l_paren,
1098 "expected '(' at start of dimensional identifiers list"))
1099 return ParseFailure;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001100
Chris Lattner413db6a2018-07-25 12:55:50 -07001101 auto parseElt = [&]() -> ParseResult {
1102 auto *dimension = AffineDimExpr::get(numDims++, getContext());
1103 return parseIdentifierDefinition(dimension);
1104 };
Chris Lattner40746442018-07-21 14:32:09 -07001105 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001106}
1107
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001108/// Parse an affine map definition.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001109///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001110/// affine-map-inline ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
1111/// (`size` `(` dim-size (`,` dim-size)* `)`)?
1112/// dim-size ::= affine-expr | `min` `(` affine-expr ( `,` affine-expr)+ `)`
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001113///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001114/// multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner2e595eb2018-07-10 10:08:27 -07001115AffineMap *AffineMapParser::parseAffineMapInline() {
Chris Lattner413db6a2018-07-25 12:55:50 -07001116 unsigned numDims = 0, numSymbols = 0;
1117
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001118 // List of dimensional identifiers.
Chris Lattner413db6a2018-07-25 12:55:50 -07001119 if (parseDimIdList(numDims))
Chris Lattner7121b802018-07-04 20:45:39 -07001120 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001121
1122 // Symbols are optional.
Chris Lattner85ee1512018-07-25 11:15:20 -07001123 if (getToken().is(Token::l_square)) {
Chris Lattner413db6a2018-07-25 12:55:50 -07001124 if (parseSymbolIdList(numSymbols))
Chris Lattner7121b802018-07-04 20:45:39 -07001125 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001126 }
Chris Lattnerf7702a62018-07-23 17:30:01 -07001127
1128 if (parseToken(Token::arrow, "expected '->' or '['") ||
1129 parseToken(Token::l_paren, "expected '(' at start of affine map range"))
Chris Lattner7121b802018-07-04 20:45:39 -07001130 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001131
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001132 SmallVector<AffineExpr *, 4> exprs;
1133 auto parseElt = [&]() -> ParseResult {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001134 auto *elt = parseAffineExpr();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001135 ParseResult res = elt ? ParseSuccess : ParseFailure;
1136 exprs.push_back(elt);
1137 return res;
1138 };
1139
1140 // Parse a multi-dimensional affine expression (a comma-separated list of 1-d
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001141 // affine expressions); the list cannot be empty.
1142 // Grammar: multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner40746442018-07-21 14:32:09 -07001143 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt, false))
Chris Lattner7121b802018-07-04 20:45:39 -07001144 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001145
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001146 // Parse optional range sizes.
Uday Bondhugula1e500b42018-07-12 18:04:04 -07001147 // range-sizes ::= (`size` `(` dim-size (`,` dim-size)* `)`)?
1148 // dim-size ::= affine-expr | `min` `(` affine-expr (`,` affine-expr)+ `)`
1149 // TODO(bondhugula): support for min of several affine expressions.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001150 // TODO: check if sizes are non-negative whenever they are constant.
1151 SmallVector<AffineExpr *, 4> rangeSizes;
1152 if (consumeIf(Token::kw_size)) {
1153 // Location of the l_paren token (if it exists) for error reporting later.
1154 auto loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001155 if (parseToken(Token::l_paren, "expected '(' at start of affine map range"))
1156 return nullptr;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001157
1158 auto parseRangeSize = [&]() -> ParseResult {
Chris Lattner413db6a2018-07-25 12:55:50 -07001159 auto loc = getToken().getLoc();
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001160 auto *elt = parseAffineExpr();
Chris Lattner413db6a2018-07-25 12:55:50 -07001161 if (!elt)
1162 return ParseFailure;
1163
1164 if (!elt->isSymbolicOrConstant())
1165 return emitError(loc,
1166 "size expressions cannot refer to dimension values");
1167
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001168 rangeSizes.push_back(elt);
Chris Lattner413db6a2018-07-25 12:55:50 -07001169 return ParseSuccess;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001170 };
1171
Chris Lattner40746442018-07-21 14:32:09 -07001172 if (parseCommaSeparatedListUntil(Token::r_paren, parseRangeSize, false))
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001173 return nullptr;
1174 if (exprs.size() > rangeSizes.size())
1175 return (emitError(loc, "fewer range sizes than range expressions"),
1176 nullptr);
1177 if (exprs.size() < rangeSizes.size())
1178 return (emitError(loc, "more range sizes than range expressions"),
1179 nullptr);
1180 }
1181
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001182 // Parsed a valid affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001183 return builder.getAffineMap(numDims, numSymbols, exprs, rangeSizes);
MLIR Teamf85a6262018-06-27 11:03:08 -07001184}
1185
Chris Lattner2e595eb2018-07-10 10:08:27 -07001186AffineMap *Parser::parseAffineMapInline() {
1187 return AffineMapParser(state).parseAffineMapInline();
1188}
1189
MLIR Team718c82f2018-07-16 09:45:22 -07001190AffineMap *Parser::parseAffineMapReference() {
1191 if (getToken().is(Token::hash_identifier)) {
1192 // Parse affine map identifier and verify that it exists.
1193 StringRef affineMapId = getTokenSpelling().drop_front();
1194 if (getState().affineMapDefinitions.count(affineMapId) == 0)
1195 return (emitError("undefined affine map id '" + affineMapId + "'"),
1196 nullptr);
1197 consumeToken(Token::hash_identifier);
1198 return getState().affineMapDefinitions[affineMapId];
1199 }
1200 // Try to parse inline affine map.
1201 return parseAffineMapInline();
1202}
1203
MLIR Teamf85a6262018-06-27 11:03:08 -07001204//===----------------------------------------------------------------------===//
Chris Lattner7f9cc272018-07-19 08:35:28 -07001205// FunctionParser
Chris Lattner4c95a502018-06-23 16:03:42 -07001206//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001207
Chris Lattner7f9cc272018-07-19 08:35:28 -07001208namespace {
1209/// This class contains parser state that is common across CFG and ML functions,
1210/// notably for dealing with operations and SSA values.
1211class FunctionParser : public Parser {
1212public:
1213 FunctionParser(ParserState &state) : Parser(state) {}
1214
Chris Lattner6119d382018-07-20 18:41:34 -07001215 /// After the function is finished parsing, this function checks to see if
1216 /// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001217 ParseResult finalizeFunction(Function *func, SMLoc loc);
Chris Lattner6119d382018-07-20 18:41:34 -07001218
1219 /// This represents a use of an SSA value in the program. The first two
1220 /// entries in the tuple are the name and result number of a reference. The
1221 /// third is the location of the reference, which is used in case this ends up
1222 /// being a use of an undefined value.
1223 struct SSAUseInfo {
1224 StringRef name; // Value name, e.g. %42 or %abc
1225 unsigned number; // Number, specified with #12
1226 SMLoc loc; // Location of first definition or use.
1227 };
Chris Lattner7f9cc272018-07-19 08:35:28 -07001228
1229 /// Given a reference to an SSA value and its type, return a reference. This
1230 /// returns null on failure.
1231 SSAValue *resolveSSAUse(SSAUseInfo useInfo, Type *type);
1232
1233 /// Register a definition of a value with the symbol table.
1234 ParseResult addDefinition(SSAUseInfo useInfo, SSAValue *value);
1235
1236 // SSA parsing productions.
1237 ParseResult parseSSAUse(SSAUseInfo &result);
Chris Lattner40746442018-07-21 14:32:09 -07001238 ParseResult parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results);
James Molloy61a656c2018-07-22 15:45:24 -07001239
1240 template <typename ResultType>
1241 ResultType parseSSADefOrUseAndType(
1242 const std::function<ResultType(SSAUseInfo, Type *)> &action);
1243
1244 SSAValue *parseSSAUseAndType() {
1245 return parseSSADefOrUseAndType<SSAValue *>(
1246 [&](SSAUseInfo useInfo, Type *type) -> SSAValue * {
1247 return resolveSSAUse(useInfo, type);
1248 });
1249 }
Chris Lattner40746442018-07-21 14:32:09 -07001250
1251 template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001252 ParseResult
Chris Lattner2c402672018-07-23 11:56:17 -07001253 parseOptionalSSAUseAndTypeList(SmallVectorImpl<ValueTy *> &results,
1254 bool isParenthesized);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001255
1256 // Operations
1257 ParseResult parseOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner85ee1512018-07-25 11:15:20 -07001258 Operation *parseVerboseOperation(const CreateOperationFunction &createOpFunc);
1259 Operation *parseCustomOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001260
1261private:
1262 /// This keeps track of all of the SSA values we are tracking, indexed by
Chris Lattner6119d382018-07-20 18:41:34 -07001263 /// their name. This has one entry per result number.
1264 llvm::StringMap<SmallVector<std::pair<SSAValue *, SMLoc>, 1>> values;
1265
1266 /// These are all of the placeholders we've made along with the location of
1267 /// their first reference, to allow checking for use of undefined values.
1268 DenseMap<SSAValue *, SMLoc> forwardReferencePlaceholders;
1269
1270 SSAValue *createForwardReferencePlaceholder(SMLoc loc, Type *type);
1271
1272 /// Return true if this is a forward reference.
1273 bool isForwardReferencePlaceholder(SSAValue *value) {
1274 return forwardReferencePlaceholders.count(value);
1275 }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001276};
1277} // end anonymous namespace
1278
Chris Lattner6119d382018-07-20 18:41:34 -07001279/// Create and remember a new placeholder for a forward reference.
1280SSAValue *FunctionParser::createForwardReferencePlaceholder(SMLoc loc,
1281 Type *type) {
1282 // Forward references are always created as instructions, even in ML
1283 // functions, because we just need something with a def/use chain.
1284 //
1285 // We create these placeholders as having an empty name, which we know cannot
1286 // be created through normal user input, allowing us to distinguish them.
1287 auto name = Identifier::get("placeholder", getContext());
1288 auto *inst = OperationInst::create(name, /*operands*/ {}, type, /*attrs*/ {},
1289 getContext());
1290 forwardReferencePlaceholders[inst->getResult(0)] = loc;
1291 return inst->getResult(0);
1292}
1293
Chris Lattner7f9cc272018-07-19 08:35:28 -07001294/// Given an unbound reference to an SSA value and its type, return a the value
1295/// it specifies. This returns null on failure.
1296SSAValue *FunctionParser::resolveSSAUse(SSAUseInfo useInfo, Type *type) {
Chris Lattner6119d382018-07-20 18:41:34 -07001297 auto &entries = values[useInfo.name];
1298
Chris Lattner7f9cc272018-07-19 08:35:28 -07001299 // If we have already seen a value of this name, return it.
Chris Lattner6119d382018-07-20 18:41:34 -07001300 if (useInfo.number < entries.size() && entries[useInfo.number].first) {
1301 auto *result = entries[useInfo.number].first;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001302 // Check that the type matches the other uses.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001303 if (result->getType() == type)
1304 return result;
1305
Chris Lattner6119d382018-07-20 18:41:34 -07001306 emitError(useInfo.loc, "use of value '" + useInfo.name.str() +
1307 "' expects different type than prior uses");
1308 emitError(entries[useInfo.number].second, "prior use here");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001309 return nullptr;
1310 }
1311
Chris Lattner6119d382018-07-20 18:41:34 -07001312 // Make sure we have enough slots for this.
1313 if (entries.size() <= useInfo.number)
1314 entries.resize(useInfo.number + 1);
1315
1316 // If the value has already been defined and this is an overly large result
1317 // number, diagnose that.
1318 if (entries[0].first && !isForwardReferencePlaceholder(entries[0].first))
1319 return (emitError(useInfo.loc, "reference to invalid result number"),
1320 nullptr);
1321
1322 // Otherwise, this is a forward reference. Create a placeholder and remember
1323 // that we did so.
1324 auto *result = createForwardReferencePlaceholder(useInfo.loc, type);
1325 entries[useInfo.number].first = result;
1326 entries[useInfo.number].second = useInfo.loc;
1327 return result;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001328}
1329
1330/// Register a definition of a value with the symbol table.
1331ParseResult FunctionParser::addDefinition(SSAUseInfo useInfo, SSAValue *value) {
Chris Lattner6119d382018-07-20 18:41:34 -07001332 auto &entries = values[useInfo.name];
Chris Lattner7f9cc272018-07-19 08:35:28 -07001333
Chris Lattner6119d382018-07-20 18:41:34 -07001334 // Make sure there is a slot for this value.
1335 if (entries.size() <= useInfo.number)
1336 entries.resize(useInfo.number + 1);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001337
Chris Lattner6119d382018-07-20 18:41:34 -07001338 // If we already have an entry for this, check to see if it was a definition
1339 // or a forward reference.
1340 if (auto *existing = entries[useInfo.number].first) {
1341 if (!isForwardReferencePlaceholder(existing)) {
1342 emitError(useInfo.loc,
1343 "redefinition of SSA value '" + useInfo.name + "'");
1344 return emitError(entries[useInfo.number].second,
1345 "previously defined here");
1346 }
1347
1348 // If it was a forward reference, update everything that used it to use the
1349 // actual definition instead, delete the forward ref, and remove it from our
1350 // set of forward references we track.
1351 existing->replaceAllUsesWith(value);
1352 existing->getDefiningInst()->destroy();
1353 forwardReferencePlaceholders.erase(existing);
1354 }
1355
1356 entries[useInfo.number].first = value;
1357 entries[useInfo.number].second = useInfo.loc;
1358 return ParseSuccess;
1359}
1360
1361/// After the function is finished parsing, this function checks to see if
1362/// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001363ParseResult FunctionParser::finalizeFunction(Function *func, SMLoc loc) {
Chris Lattner6119d382018-07-20 18:41:34 -07001364 // Check for any forward references that are left. If we find any, error out.
1365 if (!forwardReferencePlaceholders.empty()) {
1366 SmallVector<std::pair<const char *, SSAValue *>, 4> errors;
1367 // Iteration over the map isn't determinstic, so sort by source location.
1368 for (auto entry : forwardReferencePlaceholders)
1369 errors.push_back({entry.second.getPointer(), entry.first});
1370 llvm::array_pod_sort(errors.begin(), errors.end());
1371
1372 for (auto entry : errors)
1373 emitError(SMLoc::getFromPointer(entry.first),
1374 "use of undeclared SSA value name");
1375 return ParseFailure;
1376 }
1377
Chris Lattner40746442018-07-21 14:32:09 -07001378 // Run the verifier on this function. If an error is detected, report it.
1379 std::string errorString;
1380 if (func->verify(&errorString))
1381 return emitError(loc, errorString);
1382
Chris Lattner6119d382018-07-20 18:41:34 -07001383 return ParseSuccess;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001384}
1385
Chris Lattner78276e32018-07-07 15:48:26 -07001386/// Parse a SSA operand for an instruction or statement.
1387///
James Molloy61a656c2018-07-22 15:45:24 -07001388/// ssa-use ::= ssa-id
Chris Lattner78276e32018-07-07 15:48:26 -07001389///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001390ParseResult FunctionParser::parseSSAUse(SSAUseInfo &result) {
Chris Lattner6119d382018-07-20 18:41:34 -07001391 result.name = getTokenSpelling();
1392 result.number = 0;
1393 result.loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001394 if (parseToken(Token::percent_identifier, "expected SSA operand"))
1395 return ParseFailure;
Chris Lattner6119d382018-07-20 18:41:34 -07001396
1397 // If we have an affine map ID, it is a result number.
1398 if (getToken().is(Token::hash_identifier)) {
1399 if (auto value = getToken().getHashIdentifierNumber())
1400 result.number = value.getValue();
1401 else
1402 return emitError("invalid SSA value result number");
1403 consumeToken(Token::hash_identifier);
1404 }
1405
Chris Lattner7f9cc272018-07-19 08:35:28 -07001406 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001407}
1408
1409/// Parse a (possibly empty) list of SSA operands.
1410///
1411/// ssa-use-list ::= ssa-use (`,` ssa-use)*
1412/// ssa-use-list-opt ::= ssa-use-list?
1413///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001414ParseResult
Chris Lattner40746442018-07-21 14:32:09 -07001415FunctionParser::parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results) {
Chris Lattner85ee1512018-07-25 11:15:20 -07001416 if (getToken().isNot(Token::percent_identifier))
Chris Lattner40746442018-07-21 14:32:09 -07001417 return ParseSuccess;
1418 return parseCommaSeparatedList([&]() -> ParseResult {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001419 SSAUseInfo result;
1420 if (parseSSAUse(result))
1421 return ParseFailure;
1422 results.push_back(result);
1423 return ParseSuccess;
1424 });
Chris Lattner78276e32018-07-07 15:48:26 -07001425}
1426
1427/// Parse an SSA use with an associated type.
1428///
1429/// ssa-use-and-type ::= ssa-use `:` type
James Molloy61a656c2018-07-22 15:45:24 -07001430template <typename ResultType>
1431ResultType FunctionParser::parseSSADefOrUseAndType(
1432 const std::function<ResultType(SSAUseInfo, Type *)> &action) {
Chris Lattner78276e32018-07-07 15:48:26 -07001433
Chris Lattnerf7702a62018-07-23 17:30:01 -07001434 SSAUseInfo useInfo;
1435 if (parseSSAUse(useInfo) ||
1436 parseToken(Token::colon, "expected ':' and type for SSA operand"))
1437 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001438
Chris Lattner7f9cc272018-07-19 08:35:28 -07001439 auto *type = parseType();
1440 if (!type)
1441 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001442
James Molloy61a656c2018-07-22 15:45:24 -07001443 return action(useInfo, type);
Chris Lattner78276e32018-07-07 15:48:26 -07001444}
1445
Chris Lattner2c402672018-07-23 11:56:17 -07001446/// Parse a (possibly empty) list of SSA operands, followed by a colon, then
1447/// followed by a type list. If hasParens is true, then the operands are
1448/// surrounded by parens.
Chris Lattner78276e32018-07-07 15:48:26 -07001449///
Chris Lattner2c402672018-07-23 11:56:17 -07001450/// ssa-use-and-type-list[parens]
1451/// ::= `(` ssa-use-list `)` ':' type-list-no-parens
1452///
1453/// ssa-use-and-type-list[!parens]
1454/// ::= ssa-use-list ':' type-list-no-parens
Chris Lattner78276e32018-07-07 15:48:26 -07001455///
Chris Lattner40746442018-07-21 14:32:09 -07001456template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001457ParseResult FunctionParser::parseOptionalSSAUseAndTypeList(
Chris Lattner2c402672018-07-23 11:56:17 -07001458 SmallVectorImpl<ValueTy *> &results, bool isParenthesized) {
1459
1460 // If we are in the parenthesized form and no paren exists, then we succeed
1461 // with an empty list.
1462 if (isParenthesized && !consumeIf(Token::l_paren))
Chris Lattner40746442018-07-21 14:32:09 -07001463 return ParseSuccess;
1464
Chris Lattner2c402672018-07-23 11:56:17 -07001465 SmallVector<SSAUseInfo, 4> valueIDs;
1466 if (parseOptionalSSAUseList(valueIDs))
Chris Lattner7f9cc272018-07-19 08:35:28 -07001467 return ParseFailure;
Chris Lattner2c402672018-07-23 11:56:17 -07001468
1469 if (isParenthesized && !consumeIf(Token::r_paren))
1470 return emitError("expected ')' in operand list");
1471
1472 // If there were no operands, then there is no colon or type lists.
1473 if (valueIDs.empty())
1474 return ParseSuccess;
1475
Chris Lattner2c402672018-07-23 11:56:17 -07001476 SmallVector<Type *, 4> types;
Chris Lattnerf7702a62018-07-23 17:30:01 -07001477 if (parseToken(Token::colon, "expected ':' in operand list") ||
1478 parseTypeListNoParens(types))
Chris Lattner2c402672018-07-23 11:56:17 -07001479 return ParseFailure;
1480
1481 if (valueIDs.size() != types.size())
1482 return emitError("expected " + Twine(valueIDs.size()) +
1483 " types to match operand list");
1484
1485 results.reserve(valueIDs.size());
1486 for (unsigned i = 0, e = valueIDs.size(); i != e; ++i) {
1487 if (auto *value = resolveSSAUse(valueIDs[i], types[i]))
1488 results.push_back(cast<ValueTy>(value));
1489 else
1490 return ParseFailure;
1491 }
1492
1493 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001494}
1495
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001496/// Parse the CFG or MLFunc operation.
1497///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001498/// operation ::=
1499/// (ssa-id `=`)? string '(' ssa-use-list? ')' attribute-dict?
1500/// `:` function-type
1501///
1502ParseResult
Chris Lattner7f9cc272018-07-19 08:35:28 -07001503FunctionParser::parseOperation(const CreateOperationFunction &createOpFunc) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001504 auto loc = getToken().getLoc();
1505
1506 StringRef resultID;
1507 if (getToken().is(Token::percent_identifier)) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001508 resultID = getTokenSpelling();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001509 consumeToken(Token::percent_identifier);
Chris Lattnerf7702a62018-07-23 17:30:01 -07001510 if (parseToken(Token::equal, "expected '=' after SSA name"))
1511 return ParseFailure;
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001512 }
1513
Chris Lattner85ee1512018-07-25 11:15:20 -07001514 Operation *op;
1515 if (getToken().is(Token::bare_identifier) || getToken().isKeyword())
1516 op = parseCustomOperation(createOpFunc);
1517 else if (getToken().is(Token::string))
1518 op = parseVerboseOperation(createOpFunc);
1519 else
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001520 return emitError("expected operation name in quotes");
1521
Chris Lattner85ee1512018-07-25 11:15:20 -07001522 // If parsing of the basic operation failed, then this whole thing fails.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001523 if (!op)
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001524 return ParseFailure;
1525
1526 // We just parsed an operation. If it is a recognized one, verify that it
1527 // is structurally as we expect. If not, produce an error with a reasonable
1528 // source location.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001529 if (auto *opInfo = op->getAbstractOperation(builder.getContext())) {
1530 if (auto error = opInfo->verifyInvariants(op))
Chris Lattner9361fb32018-07-24 08:34:58 -07001531 return emitError(loc, Twine("'") + op->getName().str() + "' op " + error);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001532 }
1533
Chris Lattner7f9cc272018-07-19 08:35:28 -07001534 // If the instruction had a name, register it.
1535 if (!resultID.empty()) {
1536 // FIXME: Add result infra to handle Stmt results as well to make this
1537 // generic.
1538 if (auto *inst = dyn_cast<OperationInst>(op)) {
Chris Lattnerf8cce872018-07-20 09:28:54 -07001539 if (inst->getNumResults() == 0)
Chris Lattner7f9cc272018-07-19 08:35:28 -07001540 return emitError(loc, "cannot name an operation with no results");
1541
Chris Lattner6119d382018-07-20 18:41:34 -07001542 for (unsigned i = 0, e = inst->getNumResults(); i != e; ++i)
1543 addDefinition({resultID, i, loc}, inst->getResult(i));
Chris Lattner7f9cc272018-07-19 08:35:28 -07001544 }
1545 }
1546
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001547 return ParseSuccess;
1548}
Chris Lattnere79379a2018-06-22 10:39:19 -07001549
Chris Lattner85ee1512018-07-25 11:15:20 -07001550Operation *FunctionParser::parseVerboseOperation(
1551 const CreateOperationFunction &createOpFunc) {
1552 auto name = getToken().getStringValue();
1553 if (name.empty())
1554 return (emitError("empty operation name is invalid"), nullptr);
1555
1556 consumeToken(Token::string);
1557
1558 // Parse the operand list.
1559 SmallVector<SSAUseInfo, 8> operandInfos;
1560
1561 if (parseToken(Token::l_paren, "expected '(' to start operand list") ||
1562 parseOptionalSSAUseList(operandInfos) ||
1563 parseToken(Token::r_paren, "expected ')' to end operand list")) {
1564 return nullptr;
1565 }
1566
1567 SmallVector<NamedAttribute, 4> attributes;
1568 if (getToken().is(Token::l_brace)) {
1569 if (parseAttributeDict(attributes))
1570 return nullptr;
1571 }
1572
1573 if (parseToken(Token::colon, "expected ':' followed by instruction type"))
1574 return nullptr;
1575
1576 auto typeLoc = getToken().getLoc();
1577 auto type = parseType();
1578 if (!type)
1579 return nullptr;
1580 auto fnType = dyn_cast<FunctionType>(type);
1581 if (!fnType)
1582 return (emitError(typeLoc, "expected function type"), nullptr);
1583
1584 // Check that we have the right number of types for the operands.
1585 auto operandTypes = fnType->getInputs();
1586 if (operandTypes.size() != operandInfos.size()) {
1587 auto plural = "s"[operandInfos.size() == 1];
1588 return (emitError(typeLoc, "expected " + llvm::utostr(operandInfos.size()) +
1589 " operand type" + plural + " but had " +
1590 llvm::utostr(operandTypes.size())),
1591 nullptr);
1592 }
1593
1594 // Resolve all of the operands.
1595 SmallVector<SSAValue *, 8> operands;
1596 for (unsigned i = 0, e = operandInfos.size(); i != e; ++i) {
1597 operands.push_back(resolveSSAUse(operandInfos[i], operandTypes[i]));
1598 if (!operands.back())
1599 return nullptr;
1600 }
1601
1602 auto nameId = builder.getIdentifier(name);
1603 return createOpFunc(nameId, operands, fnType->getResults(), attributes);
1604}
1605
1606namespace {
1607class CustomOpAsmParser : public OpAsmParser {
1608public:
1609 CustomOpAsmParser(SMLoc nameLoc, StringRef opName, FunctionParser &parser)
1610 : nameLoc(nameLoc), opName(opName), parser(parser) {}
1611
1612 /// This is an internal helper to parser a colon, we don't want to expose
1613 /// this to clients.
1614 bool internalParseColon(llvm::SMLoc *loc) {
1615 if (loc)
1616 *loc = parser.getToken().getLoc();
1617 return parser.parseToken(Token::colon, "expected ':'");
1618 }
1619
1620 //===--------------------------------------------------------------------===//
1621 // High level parsing methods.
1622 //===--------------------------------------------------------------------===//
1623
1624 bool parseComma(llvm::SMLoc *loc = nullptr) override {
1625 if (loc)
1626 *loc = parser.getToken().getLoc();
1627 return parser.parseToken(Token::comma, "expected ','");
1628 }
1629
1630 bool parseColonType(Type *&result, llvm::SMLoc *loc = nullptr) override {
1631 return internalParseColon(loc) || !(result = parser.parseType());
1632 }
1633
1634 bool parseColonTypeList(SmallVectorImpl<Type *> &result,
1635 llvm::SMLoc *loc = nullptr) override {
1636 if (internalParseColon(loc))
1637 return true;
1638
1639 do {
1640 if (auto *type = parser.parseType())
1641 result.push_back(type);
1642 else
1643 return true;
1644
1645 } while (parser.consumeIf(Token::comma));
1646 return false;
1647 }
1648
1649 bool parseAttribute(Attribute *&result, llvm::SMLoc *loc = nullptr) override {
1650 if (loc)
1651 *loc = parser.getToken().getLoc();
1652 result = parser.parseAttribute();
1653 return result == nullptr;
1654 }
1655
1656 bool parseOperand(OperandType &result) override {
1657 FunctionParser::SSAUseInfo useInfo;
1658 if (parser.parseSSAUse(useInfo))
1659 return true;
1660
1661 result = {useInfo.loc, useInfo.name, useInfo.number};
1662 return false;
1663 }
1664
1665 bool parseOperandList(SmallVectorImpl<OperandType> &result,
1666 int requiredOperandCount = -1,
1667 Delimeter delimeter = Delimeter::NoDelimeter) override {
1668 auto startLoc = parser.getToken().getLoc();
1669
1670 // Handle delimeters.
1671 switch (delimeter) {
1672 case Delimeter::NoDelimeter:
1673 break;
1674 case Delimeter::ParenDelimeter:
1675 if (parser.parseToken(Token::l_paren, "expected '(' in operand list"))
1676 return true;
1677 break;
1678 case Delimeter::SquareDelimeter:
1679 if (parser.parseToken(Token::l_square, "expected '[' in operand list"))
1680 return true;
1681 break;
1682 }
1683
1684 // Check for zero operands.
1685 if (parser.getToken().is(Token::percent_identifier)) {
1686 do {
1687 OperandType operand;
1688 if (parseOperand(operand))
1689 return true;
1690 result.push_back(operand);
1691 } while (parser.consumeIf(Token::comma));
1692 }
1693
1694 // Handle delimeters.
1695 switch (delimeter) {
1696 case Delimeter::NoDelimeter:
1697 break;
1698 case Delimeter::ParenDelimeter:
1699 if (parser.parseToken(Token::r_paren, "expected ')' in operand list"))
1700 return true;
1701 break;
1702 case Delimeter::SquareDelimeter:
1703 if (parser.parseToken(Token::r_square, "expected ']' in operand list"))
1704 return true;
1705 break;
1706 }
1707
1708 if (requiredOperandCount != -1 && result.size() != requiredOperandCount)
1709 emitError(startLoc,
1710 "expected " + Twine(requiredOperandCount) + " operands");
1711 return false;
1712 }
1713
1714 //===--------------------------------------------------------------------===//
1715 // Methods for interacting with the parser
1716 //===--------------------------------------------------------------------===//
1717
1718 Builder &getBuilder() const override { return parser.builder; }
1719
1720 llvm::SMLoc getNameLoc() const override { return nameLoc; }
1721
1722 bool resolveOperand(OperandType operand, Type *type,
1723 SSAValue *&result) override {
1724 FunctionParser::SSAUseInfo operandInfo = {operand.name, operand.number,
1725 operand.location};
1726 result = parser.resolveSSAUse(operandInfo, type);
1727 return result == nullptr;
1728 }
1729
1730 /// Emit a diagnostic at the specified location.
1731 void emitError(llvm::SMLoc loc, const Twine &message) override {
1732 parser.emitError(loc, "custom op '" + Twine(opName) + "' " + message);
1733 emittedError = true;
1734 }
1735
1736 bool didEmitError() const { return emittedError; }
1737
1738private:
1739 SMLoc nameLoc;
1740 StringRef opName;
1741 FunctionParser &parser;
1742 bool emittedError = false;
1743};
1744} // end anonymous namespace.
1745
1746Operation *FunctionParser::parseCustomOperation(
1747 const CreateOperationFunction &createOpFunc) {
1748 auto opLoc = getToken().getLoc();
1749 auto opName = getTokenSpelling();
1750 CustomOpAsmParser opAsmParser(opLoc, opName, *this);
1751
1752 auto *opDefinition = getOperationSet().lookup(opName);
1753 if (!opDefinition) {
1754 opAsmParser.emitError(opLoc, "is unknown");
1755 return nullptr;
1756 }
1757
1758 consumeToken();
1759
1760 // Have the op implementation take a crack and parsing this.
1761 auto result = opDefinition->parseAssembly(&opAsmParser);
1762
1763 // If it emitted an error, we failed.
1764 if (opAsmParser.didEmitError())
1765 return nullptr;
1766
1767 // Otherwise, we succeeded. Use the state it parsed as our op information.
1768 auto nameId = builder.getIdentifier(opName);
1769 return createOpFunc(nameId, result.operands, result.types, result.attributes);
1770}
1771
Chris Lattner48af7d12018-07-09 19:05:38 -07001772//===----------------------------------------------------------------------===//
1773// CFG Functions
1774//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001775
Chris Lattner4c95a502018-06-23 16:03:42 -07001776namespace {
Chris Lattner48af7d12018-07-09 19:05:38 -07001777/// This is a specialized parser for CFGFunction's, maintaining the state
1778/// transient to their bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001779class CFGFunctionParser : public FunctionParser {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001780public:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001781 CFGFunctionParser(ParserState &state, CFGFunction *function)
Chris Lattner7f9cc272018-07-19 08:35:28 -07001782 : FunctionParser(state), function(function), builder(function) {}
Chris Lattner2e595eb2018-07-10 10:08:27 -07001783
1784 ParseResult parseFunctionBody();
1785
1786private:
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001787 CFGFunction *function;
James Molloy0ff71542018-07-23 16:56:32 -07001788 llvm::StringMap<std::pair<BasicBlock *, SMLoc>> blocksByName;
Chris Lattner48af7d12018-07-09 19:05:38 -07001789
1790 /// This builder intentionally shadows the builder in the base class, with a
1791 /// more specific builder type.
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001792 CFGFuncBuilder builder;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001793
Chris Lattner4c95a502018-06-23 16:03:42 -07001794 /// Get the basic block with the specified name, creating it if it doesn't
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001795 /// already exist. The location specified is the point of use, which allows
1796 /// us to diagnose references to blocks that are not defined precisely.
1797 BasicBlock *getBlockNamed(StringRef name, SMLoc loc) {
1798 auto &blockAndLoc = blocksByName[name];
1799 if (!blockAndLoc.first) {
Chris Lattner3a467cc2018-07-01 20:28:00 -07001800 blockAndLoc.first = new BasicBlock();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001801 blockAndLoc.second = loc;
Chris Lattner4c95a502018-06-23 16:03:42 -07001802 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001803 return blockAndLoc.first;
Chris Lattner4c95a502018-06-23 16:03:42 -07001804 }
Chris Lattner48af7d12018-07-09 19:05:38 -07001805
James Molloy61a656c2018-07-22 15:45:24 -07001806 ParseResult
1807 parseOptionalBasicBlockArgList(SmallVectorImpl<BBArgument *> &results,
1808 BasicBlock *owner);
James Molloy4f788372018-07-24 15:01:27 -07001809 ParseResult parseBranchBlockAndUseList(BasicBlock *&block,
1810 SmallVectorImpl<CFGValue *> &values);
James Molloy61a656c2018-07-22 15:45:24 -07001811
Chris Lattner48af7d12018-07-09 19:05:38 -07001812 ParseResult parseBasicBlock();
1813 OperationInst *parseCFGOperation();
1814 TerminatorInst *parseTerminator();
Chris Lattner4c95a502018-06-23 16:03:42 -07001815};
1816} // end anonymous namespace
1817
James Molloy61a656c2018-07-22 15:45:24 -07001818/// Parse a (possibly empty) list of SSA operands with types as basic block
Chris Lattner2c402672018-07-23 11:56:17 -07001819/// arguments.
James Molloy61a656c2018-07-22 15:45:24 -07001820///
1821/// ssa-id-and-type-list ::= ssa-id-and-type (`,` ssa-id-and-type)*
1822///
1823ParseResult CFGFunctionParser::parseOptionalBasicBlockArgList(
1824 SmallVectorImpl<BBArgument *> &results, BasicBlock *owner) {
1825 if (getToken().is(Token::r_brace))
1826 return ParseSuccess;
1827
1828 return parseCommaSeparatedList([&]() -> ParseResult {
1829 auto type = parseSSADefOrUseAndType<Type *>(
1830 [&](SSAUseInfo useInfo, Type *type) -> Type * {
1831 BBArgument *arg = owner->addArgument(type);
1832 if (addDefinition(useInfo, arg) == ParseFailure)
1833 return nullptr;
1834 return type;
1835 });
1836 return type ? ParseSuccess : ParseFailure;
1837 });
1838}
1839
Chris Lattner48af7d12018-07-09 19:05:38 -07001840ParseResult CFGFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07001841 auto braceLoc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001842 if (parseToken(Token::l_brace, "expected '{' in CFG function"))
1843 return ParseFailure;
Chris Lattner48af7d12018-07-09 19:05:38 -07001844
1845 // Make sure we have at least one block.
1846 if (getToken().is(Token::r_brace))
1847 return emitError("CFG functions must have at least one basic block");
Chris Lattner4c95a502018-06-23 16:03:42 -07001848
1849 // Parse the list of blocks.
1850 while (!consumeIf(Token::r_brace))
Chris Lattner48af7d12018-07-09 19:05:38 -07001851 if (parseBasicBlock())
Chris Lattner4c95a502018-06-23 16:03:42 -07001852 return ParseFailure;
1853
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001854 // Verify that all referenced blocks were defined. Iteration over a
1855 // StringMap isn't determinstic, but this is good enough for our purposes.
Chris Lattner48af7d12018-07-09 19:05:38 -07001856 for (auto &elt : blocksByName) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001857 auto *bb = elt.second.first;
Chris Lattner3a467cc2018-07-01 20:28:00 -07001858 if (!bb->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001859 return emitError(elt.second.second,
James Molloy0ff71542018-07-23 16:56:32 -07001860 "reference to an undefined basic block '" + elt.first() +
1861 "'");
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001862 }
1863
Chris Lattner48af7d12018-07-09 19:05:38 -07001864 getModule()->functionList.push_back(function);
Chris Lattner6119d382018-07-20 18:41:34 -07001865
Chris Lattner40746442018-07-21 14:32:09 -07001866 return finalizeFunction(function, braceLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001867}
1868
1869/// Basic block declaration.
1870///
1871/// basic-block ::= bb-label instruction* terminator-stmt
1872/// bb-label ::= bb-id bb-arg-list? `:`
1873/// bb-id ::= bare-id
1874/// bb-arg-list ::= `(` ssa-id-and-type-list? `)`
1875///
Chris Lattner48af7d12018-07-09 19:05:38 -07001876ParseResult CFGFunctionParser::parseBasicBlock() {
1877 SMLoc nameLoc = getToken().getLoc();
1878 auto name = getTokenSpelling();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001879 if (parseToken(Token::bare_identifier, "expected basic block name"))
1880 return ParseFailure;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001881
Chris Lattner48af7d12018-07-09 19:05:38 -07001882 auto *block = getBlockNamed(name, nameLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001883
1884 // If this block has already been parsed, then this is a redefinition with the
1885 // same block name.
Chris Lattner3a467cc2018-07-01 20:28:00 -07001886 if (block->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001887 return emitError(nameLoc, "redefinition of block '" + name.str() + "'");
1888
Chris Lattner78276e32018-07-07 15:48:26 -07001889 // If an argument list is present, parse it.
1890 if (consumeIf(Token::l_paren)) {
James Molloy61a656c2018-07-22 15:45:24 -07001891 SmallVector<BBArgument *, 8> bbArgs;
Chris Lattnerf7702a62018-07-23 17:30:01 -07001892 if (parseOptionalBasicBlockArgList(bbArgs, block) ||
1893 parseToken(Token::r_paren, "expected ')' to end argument list"))
Chris Lattner78276e32018-07-07 15:48:26 -07001894 return ParseFailure;
Chris Lattner78276e32018-07-07 15:48:26 -07001895 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001896
James Molloy61a656c2018-07-22 15:45:24 -07001897 // Add the block to the function.
1898 function->push_back(block);
1899
Chris Lattnerf7702a62018-07-23 17:30:01 -07001900 if (parseToken(Token::colon, "expected ':' after basic block name"))
1901 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07001902
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001903 // Set the insertion point to the block we want to insert new operations into.
Chris Lattner48af7d12018-07-09 19:05:38 -07001904 builder.setInsertionPoint(block);
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001905
Chris Lattner7f9cc272018-07-19 08:35:28 -07001906 auto createOpFunc = [&](Identifier name, ArrayRef<SSAValue *> operands,
1907 ArrayRef<Type *> resultTypes,
1908 ArrayRef<NamedAttribute> attrs) -> Operation * {
1909 SmallVector<CFGValue *, 8> cfgOperands;
1910 cfgOperands.reserve(operands.size());
1911 for (auto *op : operands)
1912 cfgOperands.push_back(cast<CFGValue>(op));
1913 return builder.createOperation(name, cfgOperands, resultTypes, attrs);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001914 };
1915
Chris Lattnered65a732018-06-28 20:45:33 -07001916 // Parse the list of operations that make up the body of the block.
James Molloy4f788372018-07-24 15:01:27 -07001917 while (getToken().isNot(Token::kw_return, Token::kw_br, Token::kw_cond_br)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001918 if (parseOperation(createOpFunc))
Chris Lattnered65a732018-06-28 20:45:33 -07001919 return ParseFailure;
1920 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001921
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001922 if (!parseTerminator())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001923 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07001924
1925 return ParseSuccess;
1926}
1927
James Molloy4f788372018-07-24 15:01:27 -07001928ParseResult CFGFunctionParser::parseBranchBlockAndUseList(
1929 BasicBlock *&block, SmallVectorImpl<CFGValue *> &values) {
1930 block = getBlockNamed(getTokenSpelling(), getToken().getLoc());
1931 if (parseToken(Token::bare_identifier, "expected basic block name"))
1932 return ParseFailure;
1933
1934 if (!consumeIf(Token::l_paren))
1935 return ParseSuccess;
1936 if (parseOptionalSSAUseAndTypeList(values, /*isParenthesized*/ false) ||
1937 parseToken(Token::r_paren, "expected ')' to close argument list"))
1938 return ParseFailure;
1939 return ParseSuccess;
1940}
1941
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001942/// Parse the terminator instruction for a basic block.
1943///
1944/// terminator-stmt ::= `br` bb-id branch-use-list?
Chris Lattner1604e472018-07-23 08:42:19 -07001945/// branch-use-list ::= `(` ssa-use-list `)` ':' type-list-no-parens
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001946/// terminator-stmt ::=
1947/// `cond_br` ssa-use `,` bb-id branch-use-list? `,` bb-id branch-use-list?
1948/// terminator-stmt ::= `return` ssa-use-and-type-list?
1949///
Chris Lattner48af7d12018-07-09 19:05:38 -07001950TerminatorInst *CFGFunctionParser::parseTerminator() {
1951 switch (getToken().getKind()) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001952 default:
Chris Lattner3a467cc2018-07-01 20:28:00 -07001953 return (emitError("expected terminator at end of basic block"), nullptr);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001954
Chris Lattner40746442018-07-21 14:32:09 -07001955 case Token::kw_return: {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001956 consumeToken(Token::kw_return);
Chris Lattner40746442018-07-21 14:32:09 -07001957
Chris Lattner2c402672018-07-23 11:56:17 -07001958 // Parse any operands.
1959 SmallVector<CFGValue *, 8> operands;
1960 if (parseOptionalSSAUseAndTypeList(operands, /*isParenthesized*/ false))
1961 return nullptr;
1962 return builder.createReturnInst(operands);
Chris Lattner40746442018-07-21 14:32:09 -07001963 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001964
1965 case Token::kw_br: {
1966 consumeToken(Token::kw_br);
James Molloy4f788372018-07-24 15:01:27 -07001967 BasicBlock *destBB;
1968 SmallVector<CFGValue *, 4> values;
1969 if (parseBranchBlockAndUseList(destBB, values))
Chris Lattnerf7702a62018-07-23 17:30:01 -07001970 return nullptr;
Chris Lattner1604e472018-07-23 08:42:19 -07001971 auto branch = builder.createBranchInst(destBB);
James Molloy4f788372018-07-24 15:01:27 -07001972 branch->addOperands(values);
Chris Lattner1604e472018-07-23 08:42:19 -07001973 return branch;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001974 }
James Molloy4f788372018-07-24 15:01:27 -07001975
1976 case Token::kw_cond_br: {
1977 consumeToken(Token::kw_cond_br);
1978 SSAUseInfo ssaUse;
1979 if (parseSSAUse(ssaUse))
1980 return nullptr;
1981 auto *cond = resolveSSAUse(ssaUse, builder.getIntegerType(1));
1982 if (!cond)
1983 return (emitError("expected type was boolean (i1)"), nullptr);
1984 if (parseToken(Token::comma, "expected ',' in conditional branch"))
1985 return nullptr;
1986
1987 BasicBlock *trueBlock;
1988 SmallVector<CFGValue *, 4> trueOperands;
1989 if (parseBranchBlockAndUseList(trueBlock, trueOperands))
1990 return nullptr;
1991
1992 if (parseToken(Token::comma, "expected ',' in conditional branch"))
1993 return nullptr;
1994
1995 BasicBlock *falseBlock;
1996 SmallVector<CFGValue *, 4> falseOperands;
1997 if (parseBranchBlockAndUseList(falseBlock, falseOperands))
1998 return nullptr;
1999
2000 auto branch = builder.createCondBranchInst(cast<CFGValue>(cond), trueBlock,
2001 falseBlock);
2002 branch->addTrueOperands(trueOperands);
2003 branch->addFalseOperands(falseOperands);
2004 return branch;
2005 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002006 }
2007}
2008
Chris Lattner48af7d12018-07-09 19:05:38 -07002009//===----------------------------------------------------------------------===//
2010// ML Functions
2011//===----------------------------------------------------------------------===//
2012
2013namespace {
2014/// Refined parser for MLFunction bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07002015class MLFunctionParser : public FunctionParser {
Chris Lattner48af7d12018-07-09 19:05:38 -07002016public:
Chris Lattner48af7d12018-07-09 19:05:38 -07002017 MLFunctionParser(ParserState &state, MLFunction *function)
Chris Lattner7f9cc272018-07-19 08:35:28 -07002018 : FunctionParser(state), function(function), builder(function) {}
Chris Lattner48af7d12018-07-09 19:05:38 -07002019
2020 ParseResult parseFunctionBody();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002021
2022private:
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002023 MLFunction *function;
2024
2025 /// This builder intentionally shadows the builder in the base class, with a
2026 /// more specific builder type.
2027 MLFuncBuilder builder;
2028
2029 ParseResult parseForStmt();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002030 AffineConstantExpr *parseIntConstant();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002031 ParseResult parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002032 ParseResult parseElseClause(IfClause *elseClause);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002033 ParseResult parseStatements(StmtBlock *block);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002034 ParseResult parseStmtBlock(StmtBlock *block);
Chris Lattner48af7d12018-07-09 19:05:38 -07002035};
2036} // end anonymous namespace
2037
Chris Lattner48af7d12018-07-09 19:05:38 -07002038ParseResult MLFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07002039 auto braceLoc = getToken().getLoc();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002040 // Parse statements in this function
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002041
Chris Lattnerf7702a62018-07-23 17:30:01 -07002042 if (parseToken(Token::l_brace, "expected '{' in ML function") ||
2043 parseStatements(function)) {
2044 return ParseFailure;
2045 }
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002046
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002047 // TODO: store return operands in the IR.
2048 SmallVector<SSAUseInfo, 4> dummyUseInfo;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002049
Chris Lattnerf7702a62018-07-23 17:30:01 -07002050 if (parseToken(Token::kw_return,
2051 "ML function must end with return statement") ||
2052 parseOptionalSSAUseList(dummyUseInfo) ||
2053 parseToken(Token::r_brace, "expected '}' to end mlfunc"))
2054 return ParseFailure;
Chris Lattner40746442018-07-21 14:32:09 -07002055
Chris Lattner48af7d12018-07-09 19:05:38 -07002056 getModule()->functionList.push_back(function);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002057
Chris Lattner40746442018-07-21 14:32:09 -07002058 return finalizeFunction(function, braceLoc);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002059}
2060
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002061/// For statement.
2062///
Chris Lattner48af7d12018-07-09 19:05:38 -07002063/// ml-for-stmt ::= `for` ssa-id `=` lower-bound `to` upper-bound
2064/// (`step` integer-literal)? `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002065///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002066ParseResult MLFunctionParser::parseForStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002067 consumeToken(Token::kw_for);
2068
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002069 // Parse induction variable
2070 if (getToken().isNot(Token::percent_identifier))
2071 return emitError("expected SSA identifier for the loop variable");
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002072
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002073 // TODO: create SSA value definition from name
2074 StringRef name = getTokenSpelling().drop_front();
2075 (void)name;
2076
2077 consumeToken(Token::percent_identifier);
2078
Chris Lattnerf7702a62018-07-23 17:30:01 -07002079 if (parseToken(Token::equal, "expected ="))
2080 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002081
2082 // Parse loop bounds
2083 AffineConstantExpr *lowerBound = parseIntConstant();
2084 if (!lowerBound)
2085 return ParseFailure;
2086
Chris Lattnerf7702a62018-07-23 17:30:01 -07002087 if (parseToken(Token::kw_to, "expected 'to' between bounds"))
2088 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002089
2090 AffineConstantExpr *upperBound = parseIntConstant();
2091 if (!upperBound)
2092 return ParseFailure;
2093
2094 // Parse step
2095 AffineConstantExpr *step = nullptr;
2096 if (consumeIf(Token::kw_step)) {
2097 step = parseIntConstant();
2098 if (!step)
2099 return ParseFailure;
2100 }
2101
2102 // Create for statement.
2103 ForStmt *stmt = builder.createFor(lowerBound, upperBound, step);
2104
2105 // If parsing of the for statement body fails,
2106 // MLIR contains for statement with those nested statements that have been
2107 // successfully parsed.
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002108 if (parseStmtBlock(static_cast<StmtBlock *>(stmt)))
2109 return ParseFailure;
2110
2111 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002112}
2113
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002114// This method is temporary workaround to parse simple loop bounds and
2115// step.
2116// TODO: remove this method once it's no longer used.
2117AffineConstantExpr *MLFunctionParser::parseIntConstant() {
2118 if (getToken().isNot(Token::integer))
2119 return (emitError("expected non-negative integer for now"), nullptr);
2120
2121 auto val = getToken().getUInt64IntegerValue();
2122 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
2123 return (emitError("constant too large for affineint"), nullptr);
2124 }
2125 consumeToken(Token::integer);
2126 return builder.getConstantExpr((int64_t)val.getValue());
2127}
2128
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002129/// If statement.
2130///
Chris Lattner48af7d12018-07-09 19:05:38 -07002131/// ml-if-head ::= `if` ml-if-cond `{` ml-stmt* `}`
2132/// | ml-if-head `else` `if` ml-if-cond `{` ml-stmt* `}`
2133/// ml-if-stmt ::= ml-if-head
2134/// | ml-if-head `else` `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002135///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002136ParseResult MLFunctionParser::parseIfStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002137 consumeToken(Token::kw_if);
Chris Lattnerf7702a62018-07-23 17:30:01 -07002138 if (parseToken(Token::l_paren, "expected ("))
2139 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002140
James Molloy0ff71542018-07-23 16:56:32 -07002141 // TODO: parse condition
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002142
Chris Lattnerf7702a62018-07-23 17:30:01 -07002143 if (parseToken(Token::r_paren, "expected )"))
2144 return ParseFailure;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002145
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002146 IfStmt *ifStmt = builder.createIf();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002147 IfClause *thenClause = ifStmt->getThenClause();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002148
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002149 // When parsing of an if statement body fails, the IR contains
2150 // the if statement with the portion of the body that has been
2151 // successfully parsed.
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002152 if (parseStmtBlock(thenClause))
2153 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002154
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002155 if (consumeIf(Token::kw_else)) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002156 auto *elseClause = ifStmt->createElseClause();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002157 if (parseElseClause(elseClause))
2158 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002159 }
2160
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002161 return ParseSuccess;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002162}
2163
2164ParseResult MLFunctionParser::parseElseClause(IfClause *elseClause) {
2165 if (getToken().is(Token::kw_if)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002166 builder.setInsertionPoint(elseClause);
2167 return parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002168 }
2169
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002170 return parseStmtBlock(elseClause);
2171}
2172
2173///
2174/// Parse a list of statements ending with `return` or `}`
2175///
2176ParseResult MLFunctionParser::parseStatements(StmtBlock *block) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07002177 auto createOpFunc = [&](Identifier name, ArrayRef<SSAValue *> operands,
2178 ArrayRef<Type *> resultTypes,
2179 ArrayRef<NamedAttribute> attrs) -> Operation * {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002180 return builder.createOperation(name, attrs);
2181 };
2182
2183 builder.setInsertionPoint(block);
2184
2185 while (getToken().isNot(Token::kw_return, Token::r_brace)) {
2186 switch (getToken().getKind()) {
2187 default:
2188 if (parseOperation(createOpFunc))
2189 return ParseFailure;
2190 break;
2191 case Token::kw_for:
2192 if (parseForStmt())
2193 return ParseFailure;
2194 break;
2195 case Token::kw_if:
2196 if (parseIfStmt())
2197 return ParseFailure;
2198 break;
2199 } // end switch
2200 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002201
2202 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002203}
2204
2205///
2206/// Parse `{` ml-stmt* `}`
2207///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002208ParseResult MLFunctionParser::parseStmtBlock(StmtBlock *block) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002209 if (parseToken(Token::l_brace, "expected '{' before statement list") ||
2210 parseStatements(block) ||
2211 parseToken(Token::r_brace,
2212 "expected '}' at the end of the statement block"))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002213 return ParseFailure;
2214
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002215 return ParseSuccess;
2216}
2217
Chris Lattner4c95a502018-06-23 16:03:42 -07002218//===----------------------------------------------------------------------===//
2219// Top-level entity parsing.
2220//===----------------------------------------------------------------------===//
2221
Chris Lattner2e595eb2018-07-10 10:08:27 -07002222namespace {
2223/// This parser handles entities that are only valid at the top level of the
2224/// file.
2225class ModuleParser : public Parser {
2226public:
2227 explicit ModuleParser(ParserState &state) : Parser(state) {}
2228
2229 ParseResult parseModule();
2230
2231private:
2232 ParseResult parseAffineMapDef();
2233
2234 // Functions.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002235 ParseResult parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2236 SmallVectorImpl<StringRef> &argNames);
2237 ParseResult parseFunctionSignature(StringRef &name, FunctionType *&type,
2238 SmallVectorImpl<StringRef> *argNames);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002239 ParseResult parseExtFunc();
2240 ParseResult parseCFGFunc();
2241 ParseResult parseMLFunc();
2242};
2243} // end anonymous namespace
2244
2245/// Affine map declaration.
2246///
2247/// affine-map-def ::= affine-map-id `=` affine-map-inline
2248///
2249ParseResult ModuleParser::parseAffineMapDef() {
2250 assert(getToken().is(Token::hash_identifier));
2251
2252 StringRef affineMapId = getTokenSpelling().drop_front();
2253
2254 // Check for redefinitions.
2255 auto *&entry = getState().affineMapDefinitions[affineMapId];
2256 if (entry)
2257 return emitError("redefinition of affine map id '" + affineMapId + "'");
2258
2259 consumeToken(Token::hash_identifier);
2260
2261 // Parse the '='
Chris Lattnerf7702a62018-07-23 17:30:01 -07002262 if (parseToken(Token::equal,
2263 "expected '=' in affine map outlined definition"))
2264 return ParseFailure;
Chris Lattner2e595eb2018-07-10 10:08:27 -07002265
2266 entry = parseAffineMapInline();
2267 if (!entry)
2268 return ParseFailure;
2269
Chris Lattner2e595eb2018-07-10 10:08:27 -07002270 return ParseSuccess;
2271}
2272
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002273/// Parse a (possibly empty) list of MLFunction arguments with types.
2274///
2275/// ml-argument ::= ssa-id `:` type
2276/// ml-argument-list ::= ml-argument (`,` ml-argument)* | /*empty*/
2277///
2278ParseResult
2279ModuleParser::parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2280 SmallVectorImpl<StringRef> &argNames) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002281 consumeToken(Token::l_paren);
2282
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002283 auto parseElt = [&]() -> ParseResult {
2284 // Parse argument name
2285 if (getToken().isNot(Token::percent_identifier))
2286 return emitError("expected SSA identifier");
2287
2288 StringRef name = getTokenSpelling().drop_front();
2289 consumeToken(Token::percent_identifier);
2290 argNames.push_back(name);
2291
Chris Lattnerf7702a62018-07-23 17:30:01 -07002292 if (parseToken(Token::colon, "expected ':'"))
2293 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002294
2295 // Parse argument type
2296 auto elt = parseType();
2297 if (!elt)
2298 return ParseFailure;
2299 argTypes.push_back(elt);
2300
2301 return ParseSuccess;
2302 };
2303
Chris Lattner40746442018-07-21 14:32:09 -07002304 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002305}
2306
Chris Lattner2e595eb2018-07-10 10:08:27 -07002307/// Parse a function signature, starting with a name and including the parameter
2308/// list.
2309///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002310/// argument-list ::= type (`,` type)* | /*empty*/ | ml-argument-list
Chris Lattner2e595eb2018-07-10 10:08:27 -07002311/// function-signature ::= function-id `(` argument-list `)` (`->` type-list)?
2312///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002313ParseResult
2314ModuleParser::parseFunctionSignature(StringRef &name, FunctionType *&type,
2315 SmallVectorImpl<StringRef> *argNames) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002316 if (getToken().isNot(Token::at_identifier))
2317 return emitError("expected a function identifier like '@foo'");
2318
2319 name = getTokenSpelling().drop_front();
2320 consumeToken(Token::at_identifier);
2321
2322 if (getToken().isNot(Token::l_paren))
2323 return emitError("expected '(' in function signature");
2324
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002325 SmallVector<Type *, 4> argTypes;
2326 ParseResult parseResult;
2327
2328 if (argNames)
2329 parseResult = parseMLArgumentList(argTypes, *argNames);
2330 else
2331 parseResult = parseTypeList(argTypes);
2332
2333 if (parseResult)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002334 return ParseFailure;
2335
2336 // Parse the return type if present.
2337 SmallVector<Type *, 4> results;
2338 if (consumeIf(Token::arrow)) {
2339 if (parseTypeList(results))
2340 return ParseFailure;
2341 }
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002342 type = builder.getFunctionType(argTypes, results);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002343 return ParseSuccess;
2344}
2345
2346/// External function declarations.
2347///
2348/// ext-func ::= `extfunc` function-signature
2349///
2350ParseResult ModuleParser::parseExtFunc() {
2351 consumeToken(Token::kw_extfunc);
2352
2353 StringRef name;
2354 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002355 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002356 return ParseFailure;
2357
2358 // Okay, the external function definition was parsed correctly.
2359 getModule()->functionList.push_back(new ExtFunction(name, type));
2360 return ParseSuccess;
2361}
2362
2363/// CFG function declarations.
2364///
2365/// cfg-func ::= `cfgfunc` function-signature `{` basic-block+ `}`
2366///
2367ParseResult ModuleParser::parseCFGFunc() {
2368 consumeToken(Token::kw_cfgfunc);
2369
2370 StringRef name;
2371 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002372 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002373 return ParseFailure;
2374
2375 // Okay, the CFG function signature was parsed correctly, create the function.
2376 auto function = new CFGFunction(name, type);
2377
2378 return CFGFunctionParser(getState(), function).parseFunctionBody();
2379}
2380
2381/// ML function declarations.
2382///
2383/// ml-func ::= `mlfunc` ml-func-signature `{` ml-stmt* ml-return-stmt `}`
2384///
2385ParseResult ModuleParser::parseMLFunc() {
2386 consumeToken(Token::kw_mlfunc);
2387
2388 StringRef name;
2389 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002390 SmallVector<StringRef, 4> argNames;
Chris Lattner2e595eb2018-07-10 10:08:27 -07002391 // FIXME: Parse ML function signature (args + types)
2392 // by passing pointer to SmallVector<identifier> into parseFunctionSignature
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002393
2394 if (parseFunctionSignature(name, type, &argNames))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002395 return ParseFailure;
2396
2397 // Okay, the ML function signature was parsed correctly, create the function.
2398 auto function = new MLFunction(name, type);
2399
2400 return MLFunctionParser(getState(), function).parseFunctionBody();
2401}
2402
Chris Lattnere79379a2018-06-22 10:39:19 -07002403/// This is the top-level module parser.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002404ParseResult ModuleParser::parseModule() {
Chris Lattnere79379a2018-06-22 10:39:19 -07002405 while (1) {
Chris Lattner48af7d12018-07-09 19:05:38 -07002406 switch (getToken().getKind()) {
Chris Lattnere79379a2018-06-22 10:39:19 -07002407 default:
2408 emitError("expected a top level entity");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002409 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002410
Uday Bondhugula015cbb12018-07-03 20:16:08 -07002411 // If we got to the end of the file, then we're done.
Chris Lattnere79379a2018-06-22 10:39:19 -07002412 case Token::eof:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002413 return ParseSuccess;
Chris Lattnere79379a2018-06-22 10:39:19 -07002414
2415 // If we got an error token, then the lexer already emitted an error, just
2416 // stop. Someday we could introduce error recovery if there was demand for
2417 // it.
2418 case Token::error:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002419 return ParseFailure;
2420
2421 case Token::hash_identifier:
2422 if (parseAffineMapDef())
2423 return ParseFailure;
2424 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002425
2426 case Token::kw_extfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002427 if (parseExtFunc())
2428 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002429 break;
2430
Chris Lattner4c95a502018-06-23 16:03:42 -07002431 case Token::kw_cfgfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002432 if (parseCFGFunc())
2433 return ParseFailure;
MLIR Teamf85a6262018-06-27 11:03:08 -07002434 break;
Chris Lattner4c95a502018-06-23 16:03:42 -07002435
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002436 case Token::kw_mlfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002437 if (parseMLFunc())
2438 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002439 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002440 }
2441 }
2442}
2443
2444//===----------------------------------------------------------------------===//
2445
Jacques Pienaar7b829702018-07-03 13:24:09 -07002446void mlir::defaultErrorReporter(const llvm::SMDiagnostic &error) {
2447 const auto &sourceMgr = *error.getSourceMgr();
2448 sourceMgr.PrintMessage(error.getLoc(), error.getKind(), error.getMessage());
2449}
2450
Chris Lattnere79379a2018-06-22 10:39:19 -07002451/// This parses the file specified by the indicated SourceMgr and returns an
2452/// MLIR module if it was valid. If not, it emits diagnostics and returns null.
Jacques Pienaar9c411be2018-06-24 19:17:35 -07002453Module *mlir::parseSourceFile(llvm::SourceMgr &sourceMgr, MLIRContext *context,
Jacques Pienaar7b829702018-07-03 13:24:09 -07002454 SMDiagnosticHandlerTy errorReporter) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002455 // This is the result module we are parsing into.
2456 std::unique_ptr<Module> module(new Module(context));
2457
2458 ParserState state(sourceMgr, module.get(),
Jacques Pienaar0bffd862018-07-11 13:26:23 -07002459 errorReporter ? errorReporter : defaultErrorReporter);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002460 if (ModuleParser(state).parseModule())
2461 return nullptr;
Chris Lattner21e67f62018-07-06 10:46:19 -07002462
2463 // Make sure the parse module has no other structural problems detected by the
2464 // verifier.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002465 module->verify();
2466 return module.release();
Chris Lattnere79379a2018-06-22 10:39:19 -07002467}