blob: d89c62e04bdb2f5892228d56f146395304b6ee16 [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"
James Molloyf0d2f442018-08-03 01:54:46 -070034#include "llvm/ADT/DenseMap.h"
35#include "llvm/Support/SourceMgr.h"
Chris Lattnere79379a2018-06-22 10:39:19 -070036using 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 Lattner992a1272018-08-07 12:02:37 -070090typedef std::function<Operation *(const OperationState &)>
Tatiana Shpeisman565b9642018-07-16 11:47:09 -070091 CreateOperationFunction;
92
Chris Lattner48af7d12018-07-09 19:05:38 -070093/// This class implement support for parsing global entities like types and
94/// shared entities like SSA names. It is intended to be subclassed by
95/// specialized subparsers that include state, e.g. when a local symbol table.
96class Parser {
97public:
Chris Lattner2e595eb2018-07-10 10:08:27 -070098 Builder builder;
Chris Lattner48af7d12018-07-09 19:05:38 -070099
Chris Lattner2e595eb2018-07-10 10:08:27 -0700100 Parser(ParserState &state) : builder(state.context), state(state) {}
101
102 // Helper methods to get stuff from the parser-global state.
103 ParserState &getState() const { return state; }
Chris Lattner48af7d12018-07-09 19:05:38 -0700104 MLIRContext *getContext() const { return state.context; }
Chris Lattner2e595eb2018-07-10 10:08:27 -0700105 Module *getModule() { return state.module; }
Chris Lattner85ee1512018-07-25 11:15:20 -0700106 OperationSet &getOperationSet() const { return state.operationSet; }
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700107 llvm::SourceMgr &getSourceMgr() { return state.lex.getSourceMgr(); }
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 Lattnerf7e22732018-06-22 22:03:48 -0700164 VectorType *parseVectorType();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700165 ParseResult parseDimensionListRanked(SmallVectorImpl<int> &dimensions);
Chris Lattnerf7e22732018-06-22 22:03:48 -0700166 Type *parseTensorType();
167 Type *parseMemRefType();
168 Type *parseFunctionType();
169 Type *parseType();
Chris Lattner1604e472018-07-23 08:42:19 -0700170 ParseResult parseTypeListNoParens(SmallVectorImpl<Type *> &elements);
James Molloy0ff71542018-07-23 16:56:32 -0700171 ParseResult parseTypeList(SmallVectorImpl<Type *> &elements);
Chris Lattnere79379a2018-06-22 10:39:19 -0700172
Chris Lattner7121b802018-07-04 20:45:39 -0700173 // Attribute parsing.
174 Attribute *parseAttribute();
175 ParseResult parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes);
176
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700177 // Polyhedral structures.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700178 AffineMap *parseAffineMapInline();
MLIR Team718c82f2018-07-16 09:45:22 -0700179 AffineMap *parseAffineMapReference();
MLIR Teamf85a6262018-06-27 11:03:08 -0700180
Chris Lattner48af7d12018-07-09 19:05:38 -0700181private:
182 // The Parser is subclassed and reinstantiated. Do not add additional
183 // non-trivial state here, add it to the ParserState class.
184 ParserState &state;
Chris Lattnere79379a2018-06-22 10:39:19 -0700185};
186} // end anonymous namespace
187
188//===----------------------------------------------------------------------===//
189// Helper methods.
190//===----------------------------------------------------------------------===//
191
Chris Lattner4c95a502018-06-23 16:03:42 -0700192ParseResult Parser::emitError(SMLoc loc, const Twine &message) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700193 // If we hit a parse error in response to a lexer error, then the lexer
Jacques Pienaar9c411be2018-06-24 19:17:35 -0700194 // already reported the error.
Chris Lattner48af7d12018-07-09 19:05:38 -0700195 if (getToken().is(Token::error))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700196 return ParseFailure;
197
Chris Lattner48af7d12018-07-09 19:05:38 -0700198 auto &sourceMgr = state.lex.getSourceMgr();
199 state.errorReporter(sourceMgr.GetMessage(loc, SourceMgr::DK_Error, message));
Chris Lattnere79379a2018-06-22 10:39:19 -0700200 return ParseFailure;
201}
202
Chris Lattnerf7702a62018-07-23 17:30:01 -0700203/// Consume the specified token if present and return success. On failure,
204/// output a diagnostic and return failure.
205ParseResult Parser::parseToken(Token::Kind expectedToken,
206 const Twine &message) {
207 if (consumeIf(expectedToken))
208 return ParseSuccess;
209 return emitError(message);
210}
211
Chris Lattner40746442018-07-21 14:32:09 -0700212/// Parse a comma separated list of elements that must have at least one entry
213/// in it.
214ParseResult Parser::parseCommaSeparatedList(
215 const std::function<ParseResult()> &parseElement) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700216 // Non-empty case starts with an element.
217 if (parseElement())
218 return ParseFailure;
219
220 // Otherwise we have a list of comma separated elements.
221 while (consumeIf(Token::comma)) {
222 if (parseElement())
223 return ParseFailure;
224 }
Chris Lattner40746442018-07-21 14:32:09 -0700225 return ParseSuccess;
226}
227
228/// Parse a comma-separated list of elements, terminated with an arbitrary
229/// token. This allows empty lists if allowEmptyList is true.
230///
231/// abstract-list ::= rightToken // if allowEmptyList == true
232/// abstract-list ::= element (',' element)* rightToken
233///
234ParseResult Parser::parseCommaSeparatedListUntil(
235 Token::Kind rightToken, const std::function<ParseResult()> &parseElement,
236 bool allowEmptyList) {
237 // Handle the empty case.
238 if (getToken().is(rightToken)) {
239 if (!allowEmptyList)
240 return emitError("expected list element");
241 consumeToken(rightToken);
242 return ParseSuccess;
243 }
244
Chris Lattnerf7702a62018-07-23 17:30:01 -0700245 if (parseCommaSeparatedList(parseElement) ||
246 parseToken(rightToken, "expected ',' or '" +
247 Token::getTokenSpelling(rightToken) + "'"))
Chris Lattner40746442018-07-21 14:32:09 -0700248 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700249
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700250 return ParseSuccess;
251}
Chris Lattnere79379a2018-06-22 10:39:19 -0700252
253//===----------------------------------------------------------------------===//
254// Type Parsing
255//===----------------------------------------------------------------------===//
256
Chris Lattnerc3251192018-07-27 13:09:58 -0700257/// Parse an arbitrary type.
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700258///
Chris Lattnerc3251192018-07-27 13:09:58 -0700259/// type ::= integer-type
260/// | float-type
261/// | other-type
262/// | vector-type
263/// | tensor-type
264/// | memref-type
265/// | function-type
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700266///
Chris Lattnerc3251192018-07-27 13:09:58 -0700267/// float-type ::= `f16` | `bf16` | `f32` | `f64`
268/// other-type ::= `affineint` | `tf_control`
269///
270Type *Parser::parseType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700271 switch (getToken().getKind()) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700272 default:
273 return (emitError("expected type"), nullptr);
Chris Lattnerc3251192018-07-27 13:09:58 -0700274 case Token::kw_memref:
275 return parseMemRefType();
276 case Token::kw_tensor:
277 return parseTensorType();
278 case Token::kw_vector:
279 return parseVectorType();
280 case Token::l_paren:
281 return parseFunctionType();
282 // integer-type
283 case Token::inttype: {
284 auto width = getToken().getIntTypeBitwidth();
285 if (!width.hasValue())
286 return (emitError("invalid integer width"), nullptr);
287 consumeToken(Token::inttype);
288 return builder.getIntegerType(width.getValue());
289 }
290
291 // float-type
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700292 case Token::kw_bf16:
293 consumeToken(Token::kw_bf16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700294 return builder.getBF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700295 case Token::kw_f16:
296 consumeToken(Token::kw_f16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700297 return builder.getF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700298 case Token::kw_f32:
299 consumeToken(Token::kw_f32);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700300 return builder.getF32Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700301 case Token::kw_f64:
302 consumeToken(Token::kw_f64);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700303 return builder.getF64Type();
Chris Lattnerc3251192018-07-27 13:09:58 -0700304
305 // other-type
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700306 case Token::kw_affineint:
307 consumeToken(Token::kw_affineint);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700308 return builder.getAffineIntType();
Jacques Pienaarc0d69302018-07-27 11:07:12 -0700309 case Token::kw_tf_control:
310 consumeToken(Token::kw_tf_control);
311 return builder.getTFControlType();
James Molloy72b0cbe2018-08-01 12:55:27 -0700312 case Token::kw_tf_string:
313 consumeToken(Token::kw_tf_string);
314 return builder.getTFStringType();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700315 }
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700316}
317
318/// Parse a vector type.
319///
320/// vector-type ::= `vector` `<` const-dimension-list primitive-type `>`
321/// const-dimension-list ::= (integer-literal `x`)+
322///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700323VectorType *Parser::parseVectorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700324 consumeToken(Token::kw_vector);
325
Chris Lattnerf7702a62018-07-23 17:30:01 -0700326 if (parseToken(Token::less, "expected '<' in vector type"))
327 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700328
Chris Lattner48af7d12018-07-09 19:05:38 -0700329 if (getToken().isNot(Token::integer))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700330 return (emitError("expected dimension size in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700331
332 SmallVector<unsigned, 4> dimensions;
Chris Lattner48af7d12018-07-09 19:05:38 -0700333 while (getToken().is(Token::integer)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700334 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700335 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700336 if (!dimension.hasValue())
Chris Lattnerf7e22732018-06-22 22:03:48 -0700337 return (emitError("invalid dimension in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700338 dimensions.push_back(dimension.getValue());
339
340 consumeToken(Token::integer);
341
342 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700343 if (getToken().isNot(Token::bare_identifier) ||
344 getTokenSpelling()[0] != 'x')
Chris Lattnerf7e22732018-06-22 22:03:48 -0700345 return (emitError("expected 'x' in vector dimension list"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700346
347 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700348 if (getTokenSpelling().size() != 1)
349 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700350
351 // Consume the 'x'.
352 consumeToken(Token::bare_identifier);
353 }
354
355 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700356 auto typeLoc = getToken().getLoc();
357 auto *elementType = parseType();
358 if (!elementType || parseToken(Token::greater, "expected '>' in vector type"))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700359 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700360
Chris Lattnerc3251192018-07-27 13:09:58 -0700361 if (!isa<FloatType>(elementType) && !isa<IntegerType>(elementType))
362 return (emitError(typeLoc, "invalid vector element type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700363
Chris Lattnerf7e22732018-06-22 22:03:48 -0700364 return VectorType::get(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700365}
366
367/// Parse a dimension list of a tensor or memref type. This populates the
368/// dimension list, returning -1 for the '?' dimensions.
369///
370/// dimension-list-ranked ::= (dimension `x`)*
371/// dimension ::= `?` | integer-literal
372///
373ParseResult Parser::parseDimensionListRanked(SmallVectorImpl<int> &dimensions) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700374 while (getToken().isAny(Token::integer, Token::question)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700375 if (consumeIf(Token::question)) {
376 dimensions.push_back(-1);
377 } else {
378 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700379 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700380 if (!dimension.hasValue() || (int)dimension.getValue() < 0)
381 return emitError("invalid dimension");
382 dimensions.push_back((int)dimension.getValue());
383 consumeToken(Token::integer);
384 }
385
386 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700387 if (getToken().isNot(Token::bare_identifier) ||
388 getTokenSpelling()[0] != 'x')
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700389 return emitError("expected 'x' in dimension list");
390
391 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700392 if (getTokenSpelling().size() != 1)
393 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700394
395 // Consume the 'x'.
396 consumeToken(Token::bare_identifier);
397 }
398
399 return ParseSuccess;
400}
401
402/// Parse a tensor type.
403///
404/// tensor-type ::= `tensor` `<` dimension-list element-type `>`
405/// dimension-list ::= dimension-list-ranked | `??`
406///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700407Type *Parser::parseTensorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700408 consumeToken(Token::kw_tensor);
409
Chris Lattnerf7702a62018-07-23 17:30:01 -0700410 if (parseToken(Token::less, "expected '<' in tensor type"))
411 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700412
413 bool isUnranked;
414 SmallVector<int, 4> dimensions;
415
416 if (consumeIf(Token::questionquestion)) {
417 isUnranked = true;
418 } else {
419 isUnranked = false;
420 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700421 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700422 }
423
424 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700425 auto typeLoc = getToken().getLoc();
426 auto *elementType = parseType();
427 if (!elementType || parseToken(Token::greater, "expected '>' in tensor type"))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700428 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700429
Chris Lattnerc3251192018-07-27 13:09:58 -0700430 if (!isa<IntegerType>(elementType) && !isa<FloatType>(elementType) &&
431 !isa<VectorType>(elementType))
432 return (emitError(typeLoc, "invalid tensor element type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700433
MLIR Team355ec862018-06-23 18:09:09 -0700434 if (isUnranked)
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700435 return builder.getTensorType(elementType);
436 return builder.getTensorType(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700437}
438
439/// Parse a memref type.
440///
441/// memref-type ::= `memref` `<` dimension-list-ranked element-type
442/// (`,` semi-affine-map-composition)? (`,` memory-space)? `>`
443///
444/// semi-affine-map-composition ::= (semi-affine-map `,` )* semi-affine-map
445/// memory-space ::= integer-literal /* | TODO: address-space-id */
446///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700447Type *Parser::parseMemRefType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700448 consumeToken(Token::kw_memref);
449
Chris Lattnerf7702a62018-07-23 17:30:01 -0700450 if (parseToken(Token::less, "expected '<' in memref type"))
451 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700452
453 SmallVector<int, 4> dimensions;
454 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700455 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700456
457 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700458 auto typeLoc = getToken().getLoc();
459 auto *elementType = parseType();
Chris Lattnerf7e22732018-06-22 22:03:48 -0700460 if (!elementType)
461 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700462
Chris Lattnerc3251192018-07-27 13:09:58 -0700463 if (!isa<IntegerType>(elementType) && !isa<FloatType>(elementType) &&
464 !isa<VectorType>(elementType))
465 return (emitError(typeLoc, "invalid memref element type"), nullptr);
466
MLIR Team718c82f2018-07-16 09:45:22 -0700467 // Parse semi-affine-map-composition.
James Molloy0ff71542018-07-23 16:56:32 -0700468 SmallVector<AffineMap *, 2> affineMapComposition;
Chris Lattner413db6a2018-07-25 12:55:50 -0700469 unsigned memorySpace = 0;
MLIR Team718c82f2018-07-16 09:45:22 -0700470 bool parsedMemorySpace = false;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700471
MLIR Team718c82f2018-07-16 09:45:22 -0700472 auto parseElt = [&]() -> ParseResult {
473 if (getToken().is(Token::integer)) {
474 // Parse memory space.
475 if (parsedMemorySpace)
476 return emitError("multiple memory spaces specified in memref type");
477 auto v = getToken().getUnsignedIntegerValue();
478 if (!v.hasValue())
479 return emitError("invalid memory space in memref type");
480 memorySpace = v.getValue();
481 consumeToken(Token::integer);
482 parsedMemorySpace = true;
483 } else {
484 // Parse affine map.
485 if (parsedMemorySpace)
486 return emitError("affine map after memory space in memref type");
James Molloy0ff71542018-07-23 16:56:32 -0700487 auto *affineMap = parseAffineMapReference();
MLIR Team718c82f2018-07-16 09:45:22 -0700488 if (affineMap == nullptr)
489 return ParseFailure;
490 affineMapComposition.push_back(affineMap);
491 }
492 return ParseSuccess;
493 };
494
Chris Lattner413db6a2018-07-25 12:55:50 -0700495 // Parse a list of mappings and address space if present.
496 if (consumeIf(Token::comma)) {
497 // Parse comma separated list of affine maps, followed by memory space.
498 if (parseCommaSeparatedListUntil(Token::greater, parseElt,
499 /*allowEmptyList=*/false)) {
500 return nullptr;
501 }
502 } else {
503 if (parseToken(Token::greater, "expected ',' or '>' in memref type"))
504 return nullptr;
MLIR Team718c82f2018-07-16 09:45:22 -0700505 }
MLIR Team718c82f2018-07-16 09:45:22 -0700506
507 return MemRefType::get(dimensions, elementType, affineMapComposition,
508 memorySpace);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700509}
510
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700511/// Parse a function type.
512///
513/// function-type ::= type-list-parens `->` type-list
514///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700515Type *Parser::parseFunctionType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700516 assert(getToken().is(Token::l_paren));
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700517
Chris Lattnerf7702a62018-07-23 17:30:01 -0700518 SmallVector<Type *, 4> arguments, results;
519 if (parseTypeList(arguments) ||
520 parseToken(Token::arrow, "expected '->' in function type") ||
521 parseTypeList(results))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700522 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700523
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700524 return builder.getFunctionType(arguments, results);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700525}
526
Chris Lattner1604e472018-07-23 08:42:19 -0700527/// Parse a list of types without an enclosing parenthesis. The list must have
528/// at least one member.
529///
530/// type-list-no-parens ::= type (`,` type)*
531///
532ParseResult Parser::parseTypeListNoParens(SmallVectorImpl<Type *> &elements) {
533 auto parseElt = [&]() -> ParseResult {
534 auto elt = parseType();
535 elements.push_back(elt);
536 return elt ? ParseSuccess : ParseFailure;
537 };
538
539 return parseCommaSeparatedList(parseElt);
540}
541
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700542/// Parse a "type list", which is a singular type, or a parenthesized list of
543/// types.
544///
545/// type-list ::= type-list-parens | type
546/// type-list-parens ::= `(` `)`
Chris Lattner1604e472018-07-23 08:42:19 -0700547/// | `(` type-list-no-parens `)`
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700548///
James Molloy0ff71542018-07-23 16:56:32 -0700549ParseResult Parser::parseTypeList(SmallVectorImpl<Type *> &elements) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700550 auto parseElt = [&]() -> ParseResult {
551 auto elt = parseType();
552 elements.push_back(elt);
553 return elt ? ParseSuccess : ParseFailure;
554 };
555
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700556 // If there is no parens, then it must be a singular type.
557 if (!consumeIf(Token::l_paren))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700558 return parseElt();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700559
Chris Lattner40746442018-07-21 14:32:09 -0700560 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700561 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700562
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700563 return ParseSuccess;
564}
565
Chris Lattner4c95a502018-06-23 16:03:42 -0700566//===----------------------------------------------------------------------===//
Chris Lattner7121b802018-07-04 20:45:39 -0700567// Attribute parsing.
568//===----------------------------------------------------------------------===//
569
Chris Lattner7121b802018-07-04 20:45:39 -0700570/// Attribute parsing.
571///
572/// attribute-value ::= bool-literal
573/// | integer-literal
574/// | float-literal
575/// | string-literal
James Molloyf0d2f442018-08-03 01:54:46 -0700576/// | type
Chris Lattner7121b802018-07-04 20:45:39 -0700577/// | `[` (attribute-value (`,` attribute-value)*)? `]`
578///
579Attribute *Parser::parseAttribute() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700580 switch (getToken().getKind()) {
Chris Lattner7121b802018-07-04 20:45:39 -0700581 case Token::kw_true:
582 consumeToken(Token::kw_true);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700583 return builder.getBoolAttr(true);
Chris Lattner7121b802018-07-04 20:45:39 -0700584 case Token::kw_false:
585 consumeToken(Token::kw_false);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700586 return builder.getBoolAttr(false);
Chris Lattner7121b802018-07-04 20:45:39 -0700587
Jacques Pienaar84491092018-07-31 17:15:15 -0700588 case Token::floatliteral: {
589 auto val = getToken().getFloatingPointValue();
590 if (!val.hasValue())
591 return (emitError("floating point value too large for attribute"),
592 nullptr);
593 consumeToken(Token::floatliteral);
594 return builder.getFloatAttr(val.getValue());
595 }
Chris Lattner7121b802018-07-04 20:45:39 -0700596 case Token::integer: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700597 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700598 if (!val.hasValue() || (int64_t)val.getValue() < 0)
599 return (emitError("integer too large for attribute"), nullptr);
600 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700601 return builder.getIntegerAttr((int64_t)val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700602 }
603
604 case Token::minus: {
605 consumeToken(Token::minus);
Chris Lattner48af7d12018-07-09 19:05:38 -0700606 if (getToken().is(Token::integer)) {
607 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700608 if (!val.hasValue() || (int64_t)-val.getValue() >= 0)
609 return (emitError("integer too large for attribute"), nullptr);
610 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700611 return builder.getIntegerAttr((int64_t)-val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700612 }
Jacques Pienaar84491092018-07-31 17:15:15 -0700613 if (getToken().is(Token::floatliteral)) {
614 auto val = getToken().getFloatingPointValue();
615 if (!val.hasValue())
616 return (emitError("floating point value too large for attribute"),
617 nullptr);
618 consumeToken(Token::floatliteral);
619 return builder.getFloatAttr(-val.getValue());
620 }
Chris Lattner7121b802018-07-04 20:45:39 -0700621
622 return (emitError("expected constant integer or floating point value"),
623 nullptr);
624 }
625
626 case Token::string: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700627 auto val = getToken().getStringValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700628 consumeToken(Token::string);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700629 return builder.getStringAttr(val);
Chris Lattner7121b802018-07-04 20:45:39 -0700630 }
631
Chris Lattner85ee1512018-07-25 11:15:20 -0700632 case Token::l_square: {
633 consumeToken(Token::l_square);
James Molloy0ff71542018-07-23 16:56:32 -0700634 SmallVector<Attribute *, 4> elements;
Chris Lattner7121b802018-07-04 20:45:39 -0700635
636 auto parseElt = [&]() -> ParseResult {
637 elements.push_back(parseAttribute());
638 return elements.back() ? ParseSuccess : ParseFailure;
639 };
640
Chris Lattner85ee1512018-07-25 11:15:20 -0700641 if (parseCommaSeparatedListUntil(Token::r_square, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700642 return nullptr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700643 return builder.getArrayAttr(elements);
Chris Lattner7121b802018-07-04 20:45:39 -0700644 }
James Molloyf0d2f442018-08-03 01:54:46 -0700645 case Token::hash_identifier:
646 case Token::l_paren: {
MLIR Teamb61885d2018-07-18 16:29:21 -0700647 // Try to parse affine map reference.
James Molloyf0d2f442018-08-03 01:54:46 -0700648 if (auto *affineMap = parseAffineMapReference())
MLIR Teamb61885d2018-07-18 16:29:21 -0700649 return builder.getAffineMapAttr(affineMap);
Chris Lattner7121b802018-07-04 20:45:39 -0700650 return (emitError("expected constant attribute value"), nullptr);
651 }
James Molloyf0d2f442018-08-03 01:54:46 -0700652 default: {
653 if (Type *type = parseType())
654 return builder.getTypeAttr(type);
655 return nullptr;
656 }
657 }
Chris Lattner7121b802018-07-04 20:45:39 -0700658}
659
Chris Lattner7121b802018-07-04 20:45:39 -0700660/// Attribute dictionary.
661///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700662/// attribute-dict ::= `{` `}`
663/// | `{` attribute-entry (`,` attribute-entry)* `}`
664/// attribute-entry ::= bare-id `:` attribute-value
Chris Lattner7121b802018-07-04 20:45:39 -0700665///
James Molloy0ff71542018-07-23 16:56:32 -0700666ParseResult
667Parser::parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes) {
Chris Lattner7121b802018-07-04 20:45:39 -0700668 consumeToken(Token::l_brace);
669
670 auto parseElt = [&]() -> ParseResult {
671 // We allow keywords as attribute names.
Chris Lattner48af7d12018-07-09 19:05:38 -0700672 if (getToken().isNot(Token::bare_identifier, Token::inttype) &&
673 !getToken().isKeyword())
Chris Lattner7121b802018-07-04 20:45:39 -0700674 return emitError("expected attribute name");
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700675 auto nameId = builder.getIdentifier(getTokenSpelling());
Chris Lattner7121b802018-07-04 20:45:39 -0700676 consumeToken();
677
Chris Lattnerf7702a62018-07-23 17:30:01 -0700678 if (parseToken(Token::colon, "expected ':' in attribute list"))
679 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700680
681 auto attr = parseAttribute();
James Molloy0ff71542018-07-23 16:56:32 -0700682 if (!attr)
683 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700684
685 attributes.push_back({nameId, attr});
686 return ParseSuccess;
687 };
688
Chris Lattner40746442018-07-21 14:32:09 -0700689 if (parseCommaSeparatedListUntil(Token::r_brace, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700690 return ParseFailure;
691
692 return ParseSuccess;
693}
694
695//===----------------------------------------------------------------------===//
MLIR Teamf85a6262018-06-27 11:03:08 -0700696// Polyhedral structures.
697//===----------------------------------------------------------------------===//
698
Chris Lattner2e595eb2018-07-10 10:08:27 -0700699/// Lower precedence ops (all at the same precedence level). LNoOp is false in
700/// the boolean sense.
701enum AffineLowPrecOp {
702 /// Null value.
703 LNoOp,
704 Add,
705 Sub
706};
MLIR Teamf85a6262018-06-27 11:03:08 -0700707
Chris Lattner2e595eb2018-07-10 10:08:27 -0700708/// Higher precedence ops - all at the same precedence level. HNoOp is false in
709/// the boolean sense.
710enum AffineHighPrecOp {
711 /// Null value.
712 HNoOp,
713 Mul,
714 FloorDiv,
715 CeilDiv,
716 Mod
717};
Chris Lattner7121b802018-07-04 20:45:39 -0700718
Chris Lattner2e595eb2018-07-10 10:08:27 -0700719namespace {
720/// This is a specialized parser for AffineMap's, maintaining the state
721/// transient to their bodies.
722class AffineMapParser : public Parser {
723public:
724 explicit AffineMapParser(ParserState &state) : Parser(state) {}
Chris Lattner7121b802018-07-04 20:45:39 -0700725
Chris Lattner2e595eb2018-07-10 10:08:27 -0700726 AffineMap *parseAffineMapInline();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700727
Chris Lattner2e595eb2018-07-10 10:08:27 -0700728private:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700729 // Binary affine op parsing.
730 AffineLowPrecOp consumeIfLowPrecOp();
731 AffineHighPrecOp consumeIfHighPrecOp();
MLIR Teamf85a6262018-06-27 11:03:08 -0700732
Chris Lattner2e595eb2018-07-10 10:08:27 -0700733 // Identifier lists for polyhedral structures.
Chris Lattner413db6a2018-07-25 12:55:50 -0700734 ParseResult parseDimIdList(unsigned &numDims);
735 ParseResult parseSymbolIdList(unsigned &numSymbols);
736 ParseResult parseIdentifierDefinition(AffineExpr *idExpr);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700737
738 AffineExpr *parseAffineExpr();
739 AffineExpr *parseParentheticalExpr();
740 AffineExpr *parseNegateExpression(AffineExpr *lhs);
741 AffineExpr *parseIntegerExpr();
742 AffineExpr *parseBareIdExpr();
743
744 AffineExpr *getBinaryAffineOpExpr(AffineHighPrecOp op, AffineExpr *lhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700745 AffineExpr *rhs, SMLoc opLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700746 AffineExpr *getBinaryAffineOpExpr(AffineLowPrecOp op, AffineExpr *lhs,
747 AffineExpr *rhs);
748 AffineExpr *parseAffineOperandExpr(AffineExpr *lhs);
749 AffineExpr *parseAffineLowPrecOpExpr(AffineExpr *llhs,
750 AffineLowPrecOp llhsOp);
751 AffineExpr *parseAffineHighPrecOpExpr(AffineExpr *llhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700752 AffineHighPrecOp llhsOp,
753 SMLoc llhsOpLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700754
755private:
Chris Lattner413db6a2018-07-25 12:55:50 -0700756 SmallVector<std::pair<StringRef, AffineExpr *>, 4> dimsAndSymbols;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700757};
758} // end anonymous namespace
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700759
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700760/// Create an affine binary high precedence op expression (mul's, div's, mod).
761/// opLoc is the location of the op token to be used to report errors
762/// for non-conforming expressions.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700763AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineHighPrecOp op,
764 AffineExpr *lhs,
Chris Lattner40746442018-07-21 14:32:09 -0700765 AffineExpr *rhs,
766 SMLoc opLoc) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700767 // TODO: make the error location info accurate.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700768 switch (op) {
769 case Mul:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700770 if (!lhs->isSymbolicOrConstant() && !rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700771 emitError(opLoc, "non-affine expression: at least one of the multiply "
772 "operands has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700773 return nullptr;
774 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700775 return builder.getMulExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700776 case FloorDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700777 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700778 emitError(opLoc, "non-affine expression: right operand of floordiv "
779 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700780 return nullptr;
781 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700782 return builder.getFloorDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700783 case CeilDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700784 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700785 emitError(opLoc, "non-affine expression: right operand of ceildiv "
786 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700787 return nullptr;
788 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700789 return builder.getCeilDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700790 case Mod:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700791 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700792 emitError(opLoc, "non-affine expression: right operand of mod "
793 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700794 return nullptr;
795 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700796 return builder.getModExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700797 case HNoOp:
798 llvm_unreachable("can't create affine expression for null high prec op");
799 return nullptr;
800 }
801}
802
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700803/// Create an affine binary low precedence op expression (add, sub).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700804AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineLowPrecOp op,
805 AffineExpr *lhs,
806 AffineExpr *rhs) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700807 switch (op) {
808 case AffineLowPrecOp::Add:
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700809 return builder.getAddExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700810 case AffineLowPrecOp::Sub:
Uday Bondhugulac1faf662018-07-19 14:08:50 -0700811 return builder.getAddExpr(
812 lhs, builder.getMulExpr(rhs, builder.getConstantExpr(-1)));
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700813 case AffineLowPrecOp::LNoOp:
814 llvm_unreachable("can't create affine expression for null low prec op");
815 return nullptr;
816 }
817}
818
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700819/// Consume this token if it is a lower precedence affine op (there are only two
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700820/// precedence levels).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700821AffineLowPrecOp AffineMapParser::consumeIfLowPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700822 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700823 case Token::plus:
824 consumeToken(Token::plus);
825 return AffineLowPrecOp::Add;
826 case Token::minus:
827 consumeToken(Token::minus);
828 return AffineLowPrecOp::Sub;
829 default:
830 return AffineLowPrecOp::LNoOp;
831 }
832}
833
834/// Consume this token if it is a higher precedence affine op (there are only
835/// two precedence levels)
Chris Lattner2e595eb2018-07-10 10:08:27 -0700836AffineHighPrecOp AffineMapParser::consumeIfHighPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700837 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700838 case Token::star:
839 consumeToken(Token::star);
840 return Mul;
841 case Token::kw_floordiv:
842 consumeToken(Token::kw_floordiv);
843 return FloorDiv;
844 case Token::kw_ceildiv:
845 consumeToken(Token::kw_ceildiv);
846 return CeilDiv;
847 case Token::kw_mod:
848 consumeToken(Token::kw_mod);
849 return Mod;
850 default:
851 return HNoOp;
852 }
853}
854
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700855/// Parse a high precedence op expression list: mul, div, and mod are high
856/// precedence binary ops, i.e., parse a
857/// expr_1 op_1 expr_2 op_2 ... expr_n
858/// where op_1, op_2 are all a AffineHighPrecOp (mul, div, mod).
859/// All affine binary ops are left associative.
860/// Given llhs, returns (llhs llhsOp lhs) op rhs, or (lhs op rhs) if llhs is
861/// null. If no rhs can be found, returns (llhs llhsOp lhs) or lhs if llhs is
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700862/// null. llhsOpLoc is the location of the llhsOp token that will be used to
863/// report an error for non-conforming expressions.
864AffineExpr *AffineMapParser::parseAffineHighPrecOpExpr(AffineExpr *llhs,
865 AffineHighPrecOp llhsOp,
866 SMLoc llhsOpLoc) {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700867 AffineExpr *lhs = parseAffineOperandExpr(llhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700868 if (!lhs)
869 return nullptr;
870
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700871 // Found an LHS. Parse the remaining expression.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700872 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -0700873 if (AffineHighPrecOp op = consumeIfHighPrecOp()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700874 if (llhs) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700875 AffineExpr *expr = getBinaryAffineOpExpr(llhsOp, llhs, lhs, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700876 if (!expr)
877 return nullptr;
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700878 return parseAffineHighPrecOpExpr(expr, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700879 }
880 // No LLHS, get RHS
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700881 return parseAffineHighPrecOpExpr(lhs, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700882 }
883
884 // This is the last operand in this expression.
885 if (llhs)
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700886 return getBinaryAffineOpExpr(llhsOp, llhs, lhs, llhsOpLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700887
888 // No llhs, 'lhs' itself is the expression.
889 return lhs;
890}
891
892/// Parse an affine expression inside parentheses.
893///
894/// affine-expr ::= `(` affine-expr `)`
Chris Lattner2e595eb2018-07-10 10:08:27 -0700895AffineExpr *AffineMapParser::parseParentheticalExpr() {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700896 if (parseToken(Token::l_paren, "expected '('"))
897 return nullptr;
Chris Lattner48af7d12018-07-09 19:05:38 -0700898 if (getToken().is(Token::r_paren))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700899 return (emitError("no expression inside parentheses"), nullptr);
Chris Lattnerf7702a62018-07-23 17:30:01 -0700900
Chris Lattner2e595eb2018-07-10 10:08:27 -0700901 auto *expr = parseAffineExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700902 if (!expr)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700903 return nullptr;
Chris Lattnerf7702a62018-07-23 17:30:01 -0700904 if (parseToken(Token::r_paren, "expected ')'"))
905 return nullptr;
906
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700907 return expr;
908}
909
910/// Parse the negation expression.
911///
912/// affine-expr ::= `-` affine-expr
Chris Lattner2e595eb2018-07-10 10:08:27 -0700913AffineExpr *AffineMapParser::parseNegateExpression(AffineExpr *lhs) {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700914 if (parseToken(Token::minus, "expected '-'"))
915 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700916
Chris Lattner2e595eb2018-07-10 10:08:27 -0700917 AffineExpr *operand = parseAffineOperandExpr(lhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700918 // Since negation has the highest precedence of all ops (including high
919 // precedence ops) but lower than parentheses, we are only going to use
920 // parseAffineOperandExpr instead of parseAffineExpr here.
921 if (!operand)
922 // Extra error message although parseAffineOperandExpr would have
923 // complained. Leads to a better diagnostic.
924 return (emitError("missing operand of negation"), nullptr);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700925 auto *minusOne = builder.getConstantExpr(-1);
926 return builder.getMulExpr(minusOne, operand);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700927}
928
929/// Parse a bare id that may appear in an affine expression.
930///
931/// affine-expr ::= bare-id
Chris Lattner2e595eb2018-07-10 10:08:27 -0700932AffineExpr *AffineMapParser::parseBareIdExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700933 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700934 return (emitError("expected bare identifier"), nullptr);
935
Chris Lattner48af7d12018-07-09 19:05:38 -0700936 StringRef sRef = getTokenSpelling();
Chris Lattner413db6a2018-07-25 12:55:50 -0700937 for (auto entry : dimsAndSymbols) {
Chris Lattnera8e47672018-07-25 14:08:16 -0700938 if (entry.first == sRef) {
939 consumeToken(Token::bare_identifier);
940 return entry.second;
941 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700942 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700943
944 return (emitError("use of undeclared identifier"), nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700945}
946
947/// Parse a positive integral constant appearing in an affine expression.
948///
949/// affine-expr ::= integer-literal
Chris Lattner2e595eb2018-07-10 10:08:27 -0700950AffineExpr *AffineMapParser::parseIntegerExpr() {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700951 // No need to handle negative numbers separately here. They are naturally
952 // handled via the unary negation operator, although (FIXME) MININT_64 still
953 // not correctly handled.
Chris Lattner48af7d12018-07-09 19:05:38 -0700954 if (getToken().isNot(Token::integer))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700955 return (emitError("expected integer"), nullptr);
956
Chris Lattner48af7d12018-07-09 19:05:38 -0700957 auto val = getToken().getUInt64IntegerValue();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700958 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
959 return (emitError("constant too large for affineint"), nullptr);
960 }
961 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700962 return builder.getConstantExpr((int64_t)val.getValue());
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700963}
964
965/// Parses an expression that can be a valid operand of an affine expression.
Uday Bondhugula76345202018-07-09 13:47:52 -0700966/// lhs: if non-null, lhs is an affine expression that is the lhs of a binary
967/// operator, the rhs of which is being parsed. This is used to determine
968/// whether an error should be emitted for a missing right operand.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700969// Eg: for an expression without parentheses (like i + j + k + l), each
970// of the four identifiers is an operand. For i + j*k + l, j*k is not an
971// operand expression, it's an op expression and will be parsed via
972// parseAffineHighPrecOpExpression(). However, for i + (j*k) + -l, (j*k) and -l
973// are valid operands that will be parsed by this function.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700974AffineExpr *AffineMapParser::parseAffineOperandExpr(AffineExpr *lhs) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700975 switch (getToken().getKind()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700976 case Token::bare_identifier:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700977 return parseBareIdExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700978 case Token::integer:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700979 return parseIntegerExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700980 case Token::l_paren:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700981 return parseParentheticalExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700982 case Token::minus:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700983 return parseNegateExpression(lhs);
Uday Bondhugula76345202018-07-09 13:47:52 -0700984 case Token::kw_ceildiv:
985 case Token::kw_floordiv:
986 case Token::kw_mod:
987 case Token::plus:
988 case Token::star:
989 if (lhs)
990 emitError("missing right operand of binary operator");
991 else
992 emitError("missing left operand of binary operator");
993 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700994 default:
995 if (lhs)
Uday Bondhugula76345202018-07-09 13:47:52 -0700996 emitError("missing right operand of binary operator");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700997 else
998 emitError("expected affine expression");
999 return nullptr;
1000 }
1001}
1002
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001003/// Parse affine expressions that are bare-id's, integer constants,
1004/// parenthetical affine expressions, and affine op expressions that are a
1005/// composition of those.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001006///
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001007/// All binary op's associate from left to right.
1008///
1009/// {add, sub} have lower precedence than {mul, div, and mod}.
1010///
Uday Bondhugula76345202018-07-09 13:47:52 -07001011/// Add, sub'are themselves at the same precedence level. Mul, floordiv,
1012/// ceildiv, and mod are at the same higher precedence level. Negation has
1013/// higher precedence than any binary op.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001014///
1015/// llhs: the affine expression appearing on the left of the one being parsed.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001016/// This function will return ((llhs llhsOp lhs) op rhs) if llhs is non null,
1017/// and lhs op rhs otherwise; if there is no rhs, llhs llhsOp lhs is returned if
1018/// llhs is non-null; otherwise lhs is returned. This is to deal with left
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001019/// associativity.
1020///
1021/// Eg: when the expression is e1 + e2*e3 + e4, with e1 as llhs, this function
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001022/// will return the affine expr equivalent of (e1 + (e2*e3)) + e4, where (e2*e3)
1023/// will be parsed using parseAffineHighPrecOpExpr().
Chris Lattner2e595eb2018-07-10 10:08:27 -07001024AffineExpr *AffineMapParser::parseAffineLowPrecOpExpr(AffineExpr *llhs,
1025 AffineLowPrecOp llhsOp) {
Uday Bondhugula76345202018-07-09 13:47:52 -07001026 AffineExpr *lhs;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001027 if (!(lhs = parseAffineOperandExpr(llhs)))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001028 return nullptr;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001029
1030 // Found an LHS. Deal with the ops.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001031 if (AffineLowPrecOp lOp = consumeIfLowPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001032 if (llhs) {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001033 AffineExpr *sum = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001034 return parseAffineLowPrecOpExpr(sum, lOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001035 }
1036 // No LLHS, get RHS and form the expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001037 return parseAffineLowPrecOpExpr(lhs, lOp);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001038 }
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001039 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07001040 if (AffineHighPrecOp hOp = consumeIfHighPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001041 // We have a higher precedence op here. Get the rhs operand for the llhs
1042 // through parseAffineHighPrecOpExpr.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001043 AffineExpr *highRes = parseAffineHighPrecOpExpr(lhs, hOp, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001044 if (!highRes)
1045 return nullptr;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001046
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001047 // If llhs is null, the product forms the first operand of the yet to be
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001048 // found expression. If non-null, the op to associate with llhs is llhsOp.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001049 AffineExpr *expr =
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001050 llhs ? getBinaryAffineOpExpr(llhsOp, llhs, highRes) : highRes;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001051
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001052 // Recurse for subsequent low prec op's after the affine high prec op
1053 // expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001054 if (AffineLowPrecOp nextOp = consumeIfLowPrecOp())
1055 return parseAffineLowPrecOpExpr(expr, nextOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001056 return expr;
1057 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001058 // Last operand in the expression list.
1059 if (llhs)
1060 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
1061 // No llhs, 'lhs' itself is the expression.
1062 return lhs;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001063}
1064
1065/// Parse an affine expression.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001066/// affine-expr ::= `(` affine-expr `)`
1067/// | `-` affine-expr
1068/// | affine-expr `+` affine-expr
1069/// | affine-expr `-` affine-expr
1070/// | affine-expr `*` affine-expr
1071/// | affine-expr `floordiv` affine-expr
1072/// | affine-expr `ceildiv` affine-expr
1073/// | affine-expr `mod` affine-expr
1074/// | bare-id
1075/// | integer-literal
1076///
1077/// Additional conditions are checked depending on the production. For eg., one
1078/// of the operands for `*` has to be either constant/symbolic; the second
1079/// operand for floordiv, ceildiv, and mod has to be a positive integer.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001080AffineExpr *AffineMapParser::parseAffineExpr() {
1081 return parseAffineLowPrecOpExpr(nullptr, AffineLowPrecOp::LNoOp);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001082}
1083
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001084/// Parse a dim or symbol from the lists appearing before the actual expressions
Chris Lattner2e595eb2018-07-10 10:08:27 -07001085/// of the affine map. Update our state to store the dimensional/symbolic
Chris Lattner413db6a2018-07-25 12:55:50 -07001086/// identifier.
1087ParseResult AffineMapParser::parseIdentifierDefinition(AffineExpr *idExpr) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001088 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001089 return emitError("expected bare identifier");
Chris Lattner413db6a2018-07-25 12:55:50 -07001090
1091 auto name = getTokenSpelling();
1092 for (auto entry : dimsAndSymbols) {
1093 if (entry.first == name)
1094 return emitError("redefinition of identifier '" + Twine(name) + "'");
1095 }
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001096 consumeToken(Token::bare_identifier);
Chris Lattner413db6a2018-07-25 12:55:50 -07001097
1098 dimsAndSymbols.push_back({name, idExpr});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001099 return ParseSuccess;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001100}
1101
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001102/// Parse the list of symbolic identifiers to an affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001103ParseResult AffineMapParser::parseSymbolIdList(unsigned &numSymbols) {
1104 consumeToken(Token::l_square);
1105 auto parseElt = [&]() -> ParseResult {
1106 auto *symbol = AffineSymbolExpr::get(numSymbols++, getContext());
1107 return parseIdentifierDefinition(symbol);
1108 };
Chris Lattner85ee1512018-07-25 11:15:20 -07001109 return parseCommaSeparatedListUntil(Token::r_square, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001110}
1111
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001112/// Parse the list of dimensional identifiers to an affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001113ParseResult AffineMapParser::parseDimIdList(unsigned &numDims) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07001114 if (parseToken(Token::l_paren,
1115 "expected '(' at start of dimensional identifiers list"))
1116 return ParseFailure;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001117
Chris Lattner413db6a2018-07-25 12:55:50 -07001118 auto parseElt = [&]() -> ParseResult {
1119 auto *dimension = AffineDimExpr::get(numDims++, getContext());
1120 return parseIdentifierDefinition(dimension);
1121 };
Chris Lattner40746442018-07-21 14:32:09 -07001122 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001123}
1124
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001125/// Parse an affine map definition.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001126///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001127/// affine-map-inline ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
1128/// (`size` `(` dim-size (`,` dim-size)* `)`)?
1129/// dim-size ::= affine-expr | `min` `(` affine-expr ( `,` affine-expr)+ `)`
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001130///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001131/// multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner2e595eb2018-07-10 10:08:27 -07001132AffineMap *AffineMapParser::parseAffineMapInline() {
Chris Lattner413db6a2018-07-25 12:55:50 -07001133 unsigned numDims = 0, numSymbols = 0;
1134
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001135 // List of dimensional identifiers.
Chris Lattner413db6a2018-07-25 12:55:50 -07001136 if (parseDimIdList(numDims))
Chris Lattner7121b802018-07-04 20:45:39 -07001137 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001138
1139 // Symbols are optional.
Chris Lattner85ee1512018-07-25 11:15:20 -07001140 if (getToken().is(Token::l_square)) {
Chris Lattner413db6a2018-07-25 12:55:50 -07001141 if (parseSymbolIdList(numSymbols))
Chris Lattner7121b802018-07-04 20:45:39 -07001142 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001143 }
Chris Lattnerf7702a62018-07-23 17:30:01 -07001144
1145 if (parseToken(Token::arrow, "expected '->' or '['") ||
1146 parseToken(Token::l_paren, "expected '(' at start of affine map range"))
Chris Lattner7121b802018-07-04 20:45:39 -07001147 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001148
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001149 SmallVector<AffineExpr *, 4> exprs;
1150 auto parseElt = [&]() -> ParseResult {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001151 auto *elt = parseAffineExpr();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001152 ParseResult res = elt ? ParseSuccess : ParseFailure;
1153 exprs.push_back(elt);
1154 return res;
1155 };
1156
1157 // Parse a multi-dimensional affine expression (a comma-separated list of 1-d
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001158 // affine expressions); the list cannot be empty.
1159 // Grammar: multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner40746442018-07-21 14:32:09 -07001160 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt, false))
Chris Lattner7121b802018-07-04 20:45:39 -07001161 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001162
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001163 // Parse optional range sizes.
Uday Bondhugula1e500b42018-07-12 18:04:04 -07001164 // range-sizes ::= (`size` `(` dim-size (`,` dim-size)* `)`)?
1165 // dim-size ::= affine-expr | `min` `(` affine-expr (`,` affine-expr)+ `)`
1166 // TODO(bondhugula): support for min of several affine expressions.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001167 // TODO: check if sizes are non-negative whenever they are constant.
1168 SmallVector<AffineExpr *, 4> rangeSizes;
1169 if (consumeIf(Token::kw_size)) {
1170 // Location of the l_paren token (if it exists) for error reporting later.
1171 auto loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001172 if (parseToken(Token::l_paren, "expected '(' at start of affine map range"))
1173 return nullptr;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001174
1175 auto parseRangeSize = [&]() -> ParseResult {
Chris Lattner413db6a2018-07-25 12:55:50 -07001176 auto loc = getToken().getLoc();
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001177 auto *elt = parseAffineExpr();
Chris Lattner413db6a2018-07-25 12:55:50 -07001178 if (!elt)
1179 return ParseFailure;
1180
1181 if (!elt->isSymbolicOrConstant())
1182 return emitError(loc,
1183 "size expressions cannot refer to dimension values");
1184
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001185 rangeSizes.push_back(elt);
Chris Lattner413db6a2018-07-25 12:55:50 -07001186 return ParseSuccess;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001187 };
1188
Chris Lattner40746442018-07-21 14:32:09 -07001189 if (parseCommaSeparatedListUntil(Token::r_paren, parseRangeSize, false))
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001190 return nullptr;
1191 if (exprs.size() > rangeSizes.size())
1192 return (emitError(loc, "fewer range sizes than range expressions"),
1193 nullptr);
1194 if (exprs.size() < rangeSizes.size())
1195 return (emitError(loc, "more range sizes than range expressions"),
1196 nullptr);
1197 }
1198
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001199 // Parsed a valid affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001200 return builder.getAffineMap(numDims, numSymbols, exprs, rangeSizes);
MLIR Teamf85a6262018-06-27 11:03:08 -07001201}
1202
Chris Lattner2e595eb2018-07-10 10:08:27 -07001203AffineMap *Parser::parseAffineMapInline() {
1204 return AffineMapParser(state).parseAffineMapInline();
1205}
1206
MLIR Team718c82f2018-07-16 09:45:22 -07001207AffineMap *Parser::parseAffineMapReference() {
1208 if (getToken().is(Token::hash_identifier)) {
1209 // Parse affine map identifier and verify that it exists.
1210 StringRef affineMapId = getTokenSpelling().drop_front();
1211 if (getState().affineMapDefinitions.count(affineMapId) == 0)
1212 return (emitError("undefined affine map id '" + affineMapId + "'"),
1213 nullptr);
1214 consumeToken(Token::hash_identifier);
1215 return getState().affineMapDefinitions[affineMapId];
1216 }
1217 // Try to parse inline affine map.
1218 return parseAffineMapInline();
1219}
1220
MLIR Teamf85a6262018-06-27 11:03:08 -07001221//===----------------------------------------------------------------------===//
Chris Lattner7f9cc272018-07-19 08:35:28 -07001222// FunctionParser
Chris Lattner4c95a502018-06-23 16:03:42 -07001223//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001224
Chris Lattner7f9cc272018-07-19 08:35:28 -07001225namespace {
1226/// This class contains parser state that is common across CFG and ML functions,
1227/// notably for dealing with operations and SSA values.
1228class FunctionParser : public Parser {
1229public:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001230 enum class Kind { CFGFunc, MLFunc };
1231
1232 Kind getKind() const { return kind; }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001233
Chris Lattner6119d382018-07-20 18:41:34 -07001234 /// After the function is finished parsing, this function checks to see if
1235 /// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001236 ParseResult finalizeFunction(Function *func, SMLoc loc);
Chris Lattner6119d382018-07-20 18:41:34 -07001237
1238 /// This represents a use of an SSA value in the program. The first two
1239 /// entries in the tuple are the name and result number of a reference. The
1240 /// third is the location of the reference, which is used in case this ends up
1241 /// being a use of an undefined value.
1242 struct SSAUseInfo {
1243 StringRef name; // Value name, e.g. %42 or %abc
1244 unsigned number; // Number, specified with #12
1245 SMLoc loc; // Location of first definition or use.
1246 };
Chris Lattner7f9cc272018-07-19 08:35:28 -07001247
1248 /// Given a reference to an SSA value and its type, return a reference. This
1249 /// returns null on failure.
1250 SSAValue *resolveSSAUse(SSAUseInfo useInfo, Type *type);
1251
1252 /// Register a definition of a value with the symbol table.
1253 ParseResult addDefinition(SSAUseInfo useInfo, SSAValue *value);
1254
1255 // SSA parsing productions.
1256 ParseResult parseSSAUse(SSAUseInfo &result);
Chris Lattner40746442018-07-21 14:32:09 -07001257 ParseResult parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results);
James Molloy61a656c2018-07-22 15:45:24 -07001258
1259 template <typename ResultType>
1260 ResultType parseSSADefOrUseAndType(
1261 const std::function<ResultType(SSAUseInfo, Type *)> &action);
1262
1263 SSAValue *parseSSAUseAndType() {
1264 return parseSSADefOrUseAndType<SSAValue *>(
1265 [&](SSAUseInfo useInfo, Type *type) -> SSAValue * {
1266 return resolveSSAUse(useInfo, type);
1267 });
1268 }
Chris Lattner40746442018-07-21 14:32:09 -07001269
1270 template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001271 ParseResult
Chris Lattner2c402672018-07-23 11:56:17 -07001272 parseOptionalSSAUseAndTypeList(SmallVectorImpl<ValueTy *> &results,
1273 bool isParenthesized);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001274
1275 // Operations
1276 ParseResult parseOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner85ee1512018-07-25 11:15:20 -07001277 Operation *parseVerboseOperation(const CreateOperationFunction &createOpFunc);
1278 Operation *parseCustomOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001279
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001280protected:
1281 FunctionParser(ParserState &state, Kind kind) : Parser(state), kind(kind) {}
1282
Chris Lattner7f9cc272018-07-19 08:35:28 -07001283private:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001284 /// Kind indicates if this is CFG or ML function parser.
1285 Kind kind;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001286 /// This keeps track of all of the SSA values we are tracking, indexed by
Chris Lattner6119d382018-07-20 18:41:34 -07001287 /// their name. This has one entry per result number.
1288 llvm::StringMap<SmallVector<std::pair<SSAValue *, SMLoc>, 1>> values;
1289
1290 /// These are all of the placeholders we've made along with the location of
1291 /// their first reference, to allow checking for use of undefined values.
1292 DenseMap<SSAValue *, SMLoc> forwardReferencePlaceholders;
1293
1294 SSAValue *createForwardReferencePlaceholder(SMLoc loc, Type *type);
1295
1296 /// Return true if this is a forward reference.
1297 bool isForwardReferencePlaceholder(SSAValue *value) {
1298 return forwardReferencePlaceholders.count(value);
1299 }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001300};
1301} // end anonymous namespace
1302
Chris Lattner6119d382018-07-20 18:41:34 -07001303/// Create and remember a new placeholder for a forward reference.
1304SSAValue *FunctionParser::createForwardReferencePlaceholder(SMLoc loc,
1305 Type *type) {
1306 // Forward references are always created as instructions, even in ML
1307 // functions, because we just need something with a def/use chain.
1308 //
1309 // We create these placeholders as having an empty name, which we know cannot
1310 // be created through normal user input, allowing us to distinguish them.
1311 auto name = Identifier::get("placeholder", getContext());
1312 auto *inst = OperationInst::create(name, /*operands*/ {}, type, /*attrs*/ {},
1313 getContext());
1314 forwardReferencePlaceholders[inst->getResult(0)] = loc;
1315 return inst->getResult(0);
1316}
1317
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001318/// Given an unbound reference to an SSA value and its type, return the value
Chris Lattner7f9cc272018-07-19 08:35:28 -07001319/// it specifies. This returns null on failure.
1320SSAValue *FunctionParser::resolveSSAUse(SSAUseInfo useInfo, Type *type) {
Chris Lattner6119d382018-07-20 18:41:34 -07001321 auto &entries = values[useInfo.name];
1322
Chris Lattner7f9cc272018-07-19 08:35:28 -07001323 // If we have already seen a value of this name, return it.
Chris Lattner6119d382018-07-20 18:41:34 -07001324 if (useInfo.number < entries.size() && entries[useInfo.number].first) {
1325 auto *result = entries[useInfo.number].first;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001326 // Check that the type matches the other uses.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001327 if (result->getType() == type)
1328 return result;
1329
Chris Lattner6119d382018-07-20 18:41:34 -07001330 emitError(useInfo.loc, "use of value '" + useInfo.name.str() +
1331 "' expects different type than prior uses");
1332 emitError(entries[useInfo.number].second, "prior use here");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001333 return nullptr;
1334 }
1335
Chris Lattner6119d382018-07-20 18:41:34 -07001336 // Make sure we have enough slots for this.
1337 if (entries.size() <= useInfo.number)
1338 entries.resize(useInfo.number + 1);
1339
1340 // If the value has already been defined and this is an overly large result
1341 // number, diagnose that.
1342 if (entries[0].first && !isForwardReferencePlaceholder(entries[0].first))
1343 return (emitError(useInfo.loc, "reference to invalid result number"),
1344 nullptr);
1345
Tatiana Shpeismand880b352018-07-31 23:14:16 -07001346 // Otherwise, this is a forward reference. If we are in ML function return
1347 // an error. In CFG function, create a placeholder and remember
1348 // that we did so.
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001349 if (getKind() == Kind::MLFunc)
1350 return (
1351 emitError(useInfo.loc, "use of undefined SSA value " + useInfo.name),
1352 nullptr);
1353
Chris Lattner6119d382018-07-20 18:41:34 -07001354 auto *result = createForwardReferencePlaceholder(useInfo.loc, type);
1355 entries[useInfo.number].first = result;
1356 entries[useInfo.number].second = useInfo.loc;
1357 return result;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001358}
1359
1360/// Register a definition of a value with the symbol table.
1361ParseResult FunctionParser::addDefinition(SSAUseInfo useInfo, SSAValue *value) {
Chris Lattner6119d382018-07-20 18:41:34 -07001362 auto &entries = values[useInfo.name];
Chris Lattner7f9cc272018-07-19 08:35:28 -07001363
Chris Lattner6119d382018-07-20 18:41:34 -07001364 // Make sure there is a slot for this value.
1365 if (entries.size() <= useInfo.number)
1366 entries.resize(useInfo.number + 1);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001367
Chris Lattner6119d382018-07-20 18:41:34 -07001368 // If we already have an entry for this, check to see if it was a definition
1369 // or a forward reference.
1370 if (auto *existing = entries[useInfo.number].first) {
1371 if (!isForwardReferencePlaceholder(existing)) {
1372 emitError(useInfo.loc,
1373 "redefinition of SSA value '" + useInfo.name + "'");
1374 return emitError(entries[useInfo.number].second,
1375 "previously defined here");
1376 }
1377
1378 // If it was a forward reference, update everything that used it to use the
1379 // actual definition instead, delete the forward ref, and remove it from our
1380 // set of forward references we track.
1381 existing->replaceAllUsesWith(value);
1382 existing->getDefiningInst()->destroy();
1383 forwardReferencePlaceholders.erase(existing);
1384 }
1385
1386 entries[useInfo.number].first = value;
1387 entries[useInfo.number].second = useInfo.loc;
1388 return ParseSuccess;
1389}
1390
1391/// After the function is finished parsing, this function checks to see if
1392/// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001393ParseResult FunctionParser::finalizeFunction(Function *func, SMLoc loc) {
Chris Lattner6119d382018-07-20 18:41:34 -07001394 // Check for any forward references that are left. If we find any, error out.
1395 if (!forwardReferencePlaceholders.empty()) {
1396 SmallVector<std::pair<const char *, SSAValue *>, 4> errors;
1397 // Iteration over the map isn't determinstic, so sort by source location.
1398 for (auto entry : forwardReferencePlaceholders)
1399 errors.push_back({entry.second.getPointer(), entry.first});
1400 llvm::array_pod_sort(errors.begin(), errors.end());
1401
1402 for (auto entry : errors)
1403 emitError(SMLoc::getFromPointer(entry.first),
1404 "use of undeclared SSA value name");
1405 return ParseFailure;
1406 }
1407
Chris Lattner40746442018-07-21 14:32:09 -07001408 // Run the verifier on this function. If an error is detected, report it.
1409 std::string errorString;
1410 if (func->verify(&errorString))
1411 return emitError(loc, errorString);
1412
Chris Lattner6119d382018-07-20 18:41:34 -07001413 return ParseSuccess;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001414}
1415
Chris Lattner78276e32018-07-07 15:48:26 -07001416/// Parse a SSA operand for an instruction or statement.
1417///
James Molloy61a656c2018-07-22 15:45:24 -07001418/// ssa-use ::= ssa-id
Chris Lattner78276e32018-07-07 15:48:26 -07001419///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001420ParseResult FunctionParser::parseSSAUse(SSAUseInfo &result) {
Chris Lattner6119d382018-07-20 18:41:34 -07001421 result.name = getTokenSpelling();
1422 result.number = 0;
1423 result.loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001424 if (parseToken(Token::percent_identifier, "expected SSA operand"))
1425 return ParseFailure;
Chris Lattner6119d382018-07-20 18:41:34 -07001426
1427 // If we have an affine map ID, it is a result number.
1428 if (getToken().is(Token::hash_identifier)) {
1429 if (auto value = getToken().getHashIdentifierNumber())
1430 result.number = value.getValue();
1431 else
1432 return emitError("invalid SSA value result number");
1433 consumeToken(Token::hash_identifier);
1434 }
1435
Chris Lattner7f9cc272018-07-19 08:35:28 -07001436 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001437}
1438
1439/// Parse a (possibly empty) list of SSA operands.
1440///
1441/// ssa-use-list ::= ssa-use (`,` ssa-use)*
1442/// ssa-use-list-opt ::= ssa-use-list?
1443///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001444ParseResult
Chris Lattner40746442018-07-21 14:32:09 -07001445FunctionParser::parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results) {
Chris Lattner85ee1512018-07-25 11:15:20 -07001446 if (getToken().isNot(Token::percent_identifier))
Chris Lattner40746442018-07-21 14:32:09 -07001447 return ParseSuccess;
1448 return parseCommaSeparatedList([&]() -> ParseResult {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001449 SSAUseInfo result;
1450 if (parseSSAUse(result))
1451 return ParseFailure;
1452 results.push_back(result);
1453 return ParseSuccess;
1454 });
Chris Lattner78276e32018-07-07 15:48:26 -07001455}
1456
1457/// Parse an SSA use with an associated type.
1458///
1459/// ssa-use-and-type ::= ssa-use `:` type
James Molloy61a656c2018-07-22 15:45:24 -07001460template <typename ResultType>
1461ResultType FunctionParser::parseSSADefOrUseAndType(
1462 const std::function<ResultType(SSAUseInfo, Type *)> &action) {
Chris Lattner78276e32018-07-07 15:48:26 -07001463
Chris Lattnerf7702a62018-07-23 17:30:01 -07001464 SSAUseInfo useInfo;
1465 if (parseSSAUse(useInfo) ||
1466 parseToken(Token::colon, "expected ':' and type for SSA operand"))
1467 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001468
Chris Lattner7f9cc272018-07-19 08:35:28 -07001469 auto *type = parseType();
1470 if (!type)
1471 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001472
James Molloy61a656c2018-07-22 15:45:24 -07001473 return action(useInfo, type);
Chris Lattner78276e32018-07-07 15:48:26 -07001474}
1475
Chris Lattner2c402672018-07-23 11:56:17 -07001476/// Parse a (possibly empty) list of SSA operands, followed by a colon, then
1477/// followed by a type list. If hasParens is true, then the operands are
1478/// surrounded by parens.
Chris Lattner78276e32018-07-07 15:48:26 -07001479///
Chris Lattner2c402672018-07-23 11:56:17 -07001480/// ssa-use-and-type-list[parens]
1481/// ::= `(` ssa-use-list `)` ':' type-list-no-parens
1482///
1483/// ssa-use-and-type-list[!parens]
1484/// ::= ssa-use-list ':' type-list-no-parens
Chris Lattner78276e32018-07-07 15:48:26 -07001485///
Chris Lattner40746442018-07-21 14:32:09 -07001486template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001487ParseResult FunctionParser::parseOptionalSSAUseAndTypeList(
Chris Lattner2c402672018-07-23 11:56:17 -07001488 SmallVectorImpl<ValueTy *> &results, bool isParenthesized) {
1489
1490 // If we are in the parenthesized form and no paren exists, then we succeed
1491 // with an empty list.
1492 if (isParenthesized && !consumeIf(Token::l_paren))
Chris Lattner40746442018-07-21 14:32:09 -07001493 return ParseSuccess;
1494
Chris Lattner2c402672018-07-23 11:56:17 -07001495 SmallVector<SSAUseInfo, 4> valueIDs;
1496 if (parseOptionalSSAUseList(valueIDs))
Chris Lattner7f9cc272018-07-19 08:35:28 -07001497 return ParseFailure;
Chris Lattner2c402672018-07-23 11:56:17 -07001498
1499 if (isParenthesized && !consumeIf(Token::r_paren))
1500 return emitError("expected ')' in operand list");
1501
1502 // If there were no operands, then there is no colon or type lists.
1503 if (valueIDs.empty())
1504 return ParseSuccess;
1505
Chris Lattner2c402672018-07-23 11:56:17 -07001506 SmallVector<Type *, 4> types;
Chris Lattnerf7702a62018-07-23 17:30:01 -07001507 if (parseToken(Token::colon, "expected ':' in operand list") ||
1508 parseTypeListNoParens(types))
Chris Lattner2c402672018-07-23 11:56:17 -07001509 return ParseFailure;
1510
1511 if (valueIDs.size() != types.size())
1512 return emitError("expected " + Twine(valueIDs.size()) +
1513 " types to match operand list");
1514
1515 results.reserve(valueIDs.size());
1516 for (unsigned i = 0, e = valueIDs.size(); i != e; ++i) {
1517 if (auto *value = resolveSSAUse(valueIDs[i], types[i]))
1518 results.push_back(cast<ValueTy>(value));
1519 else
1520 return ParseFailure;
1521 }
1522
1523 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001524}
1525
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001526/// Parse the CFG or MLFunc operation.
1527///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001528/// operation ::=
1529/// (ssa-id `=`)? string '(' ssa-use-list? ')' attribute-dict?
1530/// `:` function-type
1531///
1532ParseResult
Chris Lattner7f9cc272018-07-19 08:35:28 -07001533FunctionParser::parseOperation(const CreateOperationFunction &createOpFunc) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001534 auto loc = getToken().getLoc();
1535
1536 StringRef resultID;
1537 if (getToken().is(Token::percent_identifier)) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001538 resultID = getTokenSpelling();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001539 consumeToken(Token::percent_identifier);
Chris Lattnerf7702a62018-07-23 17:30:01 -07001540 if (parseToken(Token::equal, "expected '=' after SSA name"))
1541 return ParseFailure;
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001542 }
1543
Chris Lattner85ee1512018-07-25 11:15:20 -07001544 Operation *op;
1545 if (getToken().is(Token::bare_identifier) || getToken().isKeyword())
1546 op = parseCustomOperation(createOpFunc);
1547 else if (getToken().is(Token::string))
1548 op = parseVerboseOperation(createOpFunc);
1549 else
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001550 return emitError("expected operation name in quotes");
1551
Chris Lattner85ee1512018-07-25 11:15:20 -07001552 // If parsing of the basic operation failed, then this whole thing fails.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001553 if (!op)
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001554 return ParseFailure;
1555
Chris Lattnerf7bdf952018-08-05 21:12:29 -07001556 // Apply location information to the instruction.
1557 // TODO(clattner): make this more principled. We shouldn't overwrite existing
1558 // location info, we should use a better serialized form, and we shouldn't
1559 // be using the :location attribute. This is also pretty inefficient.
1560 {
1561 auto &sourceMgr = getSourceMgr();
1562 auto fileID = sourceMgr.FindBufferContainingLoc(loc);
1563 auto *srcBuffer = sourceMgr.getMemoryBuffer(fileID);
1564 unsigned locationEncoding = loc.getPointer() - srcBuffer->getBufferStart();
1565 op->setAttr(builder.getIdentifier(":location"),
1566 builder.getIntegerAttr(locationEncoding));
1567 }
1568
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001569 // We just parsed an operation. If it is a recognized one, verify that it
1570 // is structurally as we expect. If not, produce an error with a reasonable
1571 // source location.
Chris Lattner95865062018-08-01 10:18:59 -07001572 if (auto *opInfo = op->getAbstractOperation()) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001573 if (auto error = opInfo->verifyInvariants(op))
Chris Lattner9361fb32018-07-24 08:34:58 -07001574 return emitError(loc, Twine("'") + op->getName().str() + "' op " + error);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001575 }
1576
Chris Lattner7f9cc272018-07-19 08:35:28 -07001577 // If the instruction had a name, register it.
1578 if (!resultID.empty()) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001579 if (op->getNumResults() == 0)
1580 return emitError(loc, "cannot name an operation with no results");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001581
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001582 for (unsigned i = 0, e = op->getNumResults(); i != e; ++i)
Chris Lattner2b97d502018-08-06 14:19:46 -07001583 if (addDefinition({resultID, i, loc}, op->getResult(i)))
1584 return ParseFailure;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001585 }
1586
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001587 return ParseSuccess;
1588}
Chris Lattnere79379a2018-06-22 10:39:19 -07001589
Chris Lattner85ee1512018-07-25 11:15:20 -07001590Operation *FunctionParser::parseVerboseOperation(
1591 const CreateOperationFunction &createOpFunc) {
1592 auto name = getToken().getStringValue();
1593 if (name.empty())
1594 return (emitError("empty operation name is invalid"), nullptr);
1595
1596 consumeToken(Token::string);
1597
Chris Lattner992a1272018-08-07 12:02:37 -07001598 OperationState result(builder.getIdentifier(name));
1599
Chris Lattner85ee1512018-07-25 11:15:20 -07001600 // Parse the operand list.
1601 SmallVector<SSAUseInfo, 8> operandInfos;
1602
1603 if (parseToken(Token::l_paren, "expected '(' to start operand list") ||
1604 parseOptionalSSAUseList(operandInfos) ||
1605 parseToken(Token::r_paren, "expected ')' to end operand list")) {
1606 return nullptr;
1607 }
1608
Chris Lattner85ee1512018-07-25 11:15:20 -07001609 if (getToken().is(Token::l_brace)) {
Chris Lattner992a1272018-08-07 12:02:37 -07001610 if (parseAttributeDict(result.attributes))
Chris Lattner85ee1512018-07-25 11:15:20 -07001611 return nullptr;
1612 }
1613
1614 if (parseToken(Token::colon, "expected ':' followed by instruction type"))
1615 return nullptr;
1616
1617 auto typeLoc = getToken().getLoc();
1618 auto type = parseType();
1619 if (!type)
1620 return nullptr;
1621 auto fnType = dyn_cast<FunctionType>(type);
1622 if (!fnType)
1623 return (emitError(typeLoc, "expected function type"), nullptr);
1624
Chris Lattner992a1272018-08-07 12:02:37 -07001625 result.types.append(fnType->getResults().begin(), fnType->getResults().end());
1626
Chris Lattner85ee1512018-07-25 11:15:20 -07001627 // Check that we have the right number of types for the operands.
1628 auto operandTypes = fnType->getInputs();
1629 if (operandTypes.size() != operandInfos.size()) {
1630 auto plural = "s"[operandInfos.size() == 1];
1631 return (emitError(typeLoc, "expected " + llvm::utostr(operandInfos.size()) +
1632 " operand type" + plural + " but had " +
1633 llvm::utostr(operandTypes.size())),
1634 nullptr);
1635 }
1636
1637 // Resolve all of the operands.
Chris Lattner85ee1512018-07-25 11:15:20 -07001638 for (unsigned i = 0, e = operandInfos.size(); i != e; ++i) {
Chris Lattner992a1272018-08-07 12:02:37 -07001639 result.operands.push_back(resolveSSAUse(operandInfos[i], operandTypes[i]));
1640 if (!result.operands.back())
Chris Lattner85ee1512018-07-25 11:15:20 -07001641 return nullptr;
1642 }
1643
Chris Lattner992a1272018-08-07 12:02:37 -07001644 return createOpFunc(result);
Chris Lattner85ee1512018-07-25 11:15:20 -07001645}
1646
1647namespace {
1648class CustomOpAsmParser : public OpAsmParser {
1649public:
1650 CustomOpAsmParser(SMLoc nameLoc, StringRef opName, FunctionParser &parser)
1651 : nameLoc(nameLoc), opName(opName), parser(parser) {}
1652
1653 /// This is an internal helper to parser a colon, we don't want to expose
1654 /// this to clients.
1655 bool internalParseColon(llvm::SMLoc *loc) {
1656 if (loc)
1657 *loc = parser.getToken().getLoc();
1658 return parser.parseToken(Token::colon, "expected ':'");
1659 }
1660
1661 //===--------------------------------------------------------------------===//
1662 // High level parsing methods.
1663 //===--------------------------------------------------------------------===//
1664
1665 bool parseComma(llvm::SMLoc *loc = nullptr) override {
1666 if (loc)
1667 *loc = parser.getToken().getLoc();
1668 return parser.parseToken(Token::comma, "expected ','");
1669 }
1670
1671 bool parseColonType(Type *&result, llvm::SMLoc *loc = nullptr) override {
1672 return internalParseColon(loc) || !(result = parser.parseType());
1673 }
1674
1675 bool parseColonTypeList(SmallVectorImpl<Type *> &result,
1676 llvm::SMLoc *loc = nullptr) override {
1677 if (internalParseColon(loc))
1678 return true;
1679
1680 do {
1681 if (auto *type = parser.parseType())
1682 result.push_back(type);
1683 else
1684 return true;
1685
1686 } while (parser.consumeIf(Token::comma));
1687 return false;
1688 }
1689
Chris Lattner85cf26d2018-08-02 16:54:36 -07001690 /// Parse an arbitrary attribute and return it in result. This also adds the
1691 /// attribute to the specified attribute list with the specified name. this
1692 /// captures the location of the attribute in 'loc' if it is non-null.
1693 bool parseAttribute(Attribute *&result, const char *attrName,
1694 SmallVectorImpl<NamedAttribute> &attrs,
1695 llvm::SMLoc *loc = nullptr) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001696 if (loc)
1697 *loc = parser.getToken().getLoc();
1698 result = parser.parseAttribute();
Chris Lattner85cf26d2018-08-02 16:54:36 -07001699 if (!result)
1700 return true;
1701
1702 attrs.push_back(
1703 NamedAttribute(parser.builder.getIdentifier(attrName), result));
1704 return false;
1705 }
1706
1707 /// If a named attribute list is present, parse is into result.
1708 bool parseOptionalAttributeDict(SmallVectorImpl<NamedAttribute> &result,
1709 llvm::SMLoc *loc = nullptr) override {
1710 if (parser.getToken().isNot(Token::l_brace))
1711 return false;
1712 if (loc)
1713 *loc = parser.getToken().getLoc();
1714 return parser.parseAttributeDict(result) == ParseFailure;
Chris Lattner85ee1512018-07-25 11:15:20 -07001715 }
1716
1717 bool parseOperand(OperandType &result) override {
1718 FunctionParser::SSAUseInfo useInfo;
1719 if (parser.parseSSAUse(useInfo))
1720 return true;
1721
1722 result = {useInfo.loc, useInfo.name, useInfo.number};
1723 return false;
1724 }
1725
1726 bool parseOperandList(SmallVectorImpl<OperandType> &result,
1727 int requiredOperandCount = -1,
Chris Lattner85cf26d2018-08-02 16:54:36 -07001728 Delimiter delimiter = Delimiter::None) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001729 auto startLoc = parser.getToken().getLoc();
1730
Chris Lattner85cf26d2018-08-02 16:54:36 -07001731 // Handle delimiters.
1732 switch (delimiter) {
1733 case Delimiter::None:
Chris Lattner85ee1512018-07-25 11:15:20 -07001734 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001735 case Delimiter::OptionalParen:
Chris Lattner3164ae62018-07-28 09:36:25 -07001736 if (parser.getToken().isNot(Token::l_paren))
1737 return false;
1738 LLVM_FALLTHROUGH;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001739 case Delimiter::Paren:
Chris Lattner85ee1512018-07-25 11:15:20 -07001740 if (parser.parseToken(Token::l_paren, "expected '(' in operand list"))
1741 return true;
1742 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001743 case Delimiter::OptionalSquare:
Chris Lattner3164ae62018-07-28 09:36:25 -07001744 if (parser.getToken().isNot(Token::l_square))
1745 return false;
1746 LLVM_FALLTHROUGH;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001747 case Delimiter::Square:
Chris Lattner85ee1512018-07-25 11:15:20 -07001748 if (parser.parseToken(Token::l_square, "expected '[' in operand list"))
1749 return true;
1750 break;
1751 }
1752
1753 // Check for zero operands.
1754 if (parser.getToken().is(Token::percent_identifier)) {
1755 do {
1756 OperandType operand;
1757 if (parseOperand(operand))
1758 return true;
1759 result.push_back(operand);
1760 } while (parser.consumeIf(Token::comma));
1761 }
1762
Chris Lattner85cf26d2018-08-02 16:54:36 -07001763 // Handle delimiters. If we reach here, the optional delimiters were
Chris Lattner3164ae62018-07-28 09:36:25 -07001764 // present, so we need to parse their closing one.
Chris Lattner85cf26d2018-08-02 16:54:36 -07001765 switch (delimiter) {
1766 case Delimiter::None:
Chris Lattner85ee1512018-07-25 11:15:20 -07001767 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001768 case Delimiter::OptionalParen:
1769 case Delimiter::Paren:
Chris Lattner85ee1512018-07-25 11:15:20 -07001770 if (parser.parseToken(Token::r_paren, "expected ')' in operand list"))
1771 return true;
1772 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001773 case Delimiter::OptionalSquare:
1774 case Delimiter::Square:
Chris Lattner85ee1512018-07-25 11:15:20 -07001775 if (parser.parseToken(Token::r_square, "expected ']' in operand list"))
1776 return true;
1777 break;
1778 }
1779
1780 if (requiredOperandCount != -1 && result.size() != requiredOperandCount)
1781 emitError(startLoc,
1782 "expected " + Twine(requiredOperandCount) + " operands");
1783 return false;
1784 }
1785
1786 //===--------------------------------------------------------------------===//
1787 // Methods for interacting with the parser
1788 //===--------------------------------------------------------------------===//
1789
1790 Builder &getBuilder() const override { return parser.builder; }
1791
1792 llvm::SMLoc getNameLoc() const override { return nameLoc; }
1793
1794 bool resolveOperand(OperandType operand, Type *type,
1795 SSAValue *&result) override {
1796 FunctionParser::SSAUseInfo operandInfo = {operand.name, operand.number,
1797 operand.location};
1798 result = parser.resolveSSAUse(operandInfo, type);
1799 return result == nullptr;
1800 }
1801
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001802 /// Emit a diagnostic at the specified location and return true.
1803 bool emitError(llvm::SMLoc loc, const Twine &message) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001804 parser.emitError(loc, "custom op '" + Twine(opName) + "' " + message);
1805 emittedError = true;
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001806 return true;
Chris Lattner85ee1512018-07-25 11:15:20 -07001807 }
1808
1809 bool didEmitError() const { return emittedError; }
1810
1811private:
1812 SMLoc nameLoc;
1813 StringRef opName;
1814 FunctionParser &parser;
1815 bool emittedError = false;
1816};
1817} // end anonymous namespace.
1818
1819Operation *FunctionParser::parseCustomOperation(
1820 const CreateOperationFunction &createOpFunc) {
1821 auto opLoc = getToken().getLoc();
1822 auto opName = getTokenSpelling();
1823 CustomOpAsmParser opAsmParser(opLoc, opName, *this);
1824
1825 auto *opDefinition = getOperationSet().lookup(opName);
1826 if (!opDefinition) {
1827 opAsmParser.emitError(opLoc, "is unknown");
1828 return nullptr;
1829 }
1830
1831 consumeToken();
1832
1833 // Have the op implementation take a crack and parsing this.
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001834 OperationState opState(builder.getIdentifier(opName));
1835 if (opDefinition->parseAssembly(&opAsmParser, &opState))
1836 return nullptr;
Chris Lattner85ee1512018-07-25 11:15:20 -07001837
1838 // If it emitted an error, we failed.
1839 if (opAsmParser.didEmitError())
1840 return nullptr;
1841
1842 // Otherwise, we succeeded. Use the state it parsed as our op information.
Chris Lattner992a1272018-08-07 12:02:37 -07001843 return createOpFunc(opState);
Chris Lattner85ee1512018-07-25 11:15:20 -07001844}
1845
Chris Lattner48af7d12018-07-09 19:05:38 -07001846//===----------------------------------------------------------------------===//
1847// CFG Functions
1848//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001849
Chris Lattner4c95a502018-06-23 16:03:42 -07001850namespace {
Chris Lattner48af7d12018-07-09 19:05:38 -07001851/// This is a specialized parser for CFGFunction's, maintaining the state
1852/// transient to their bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001853class CFGFunctionParser : public FunctionParser {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001854public:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001855 CFGFunctionParser(ParserState &state, CFGFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001856 : FunctionParser(state, Kind::CFGFunc), function(function),
1857 builder(function) {}
Chris Lattner2e595eb2018-07-10 10:08:27 -07001858
1859 ParseResult parseFunctionBody();
1860
1861private:
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001862 CFGFunction *function;
James Molloy0ff71542018-07-23 16:56:32 -07001863 llvm::StringMap<std::pair<BasicBlock *, SMLoc>> blocksByName;
Chris Lattner48af7d12018-07-09 19:05:38 -07001864
1865 /// This builder intentionally shadows the builder in the base class, with a
1866 /// more specific builder type.
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001867 CFGFuncBuilder builder;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001868
Chris Lattner4c95a502018-06-23 16:03:42 -07001869 /// Get the basic block with the specified name, creating it if it doesn't
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001870 /// already exist. The location specified is the point of use, which allows
1871 /// us to diagnose references to blocks that are not defined precisely.
1872 BasicBlock *getBlockNamed(StringRef name, SMLoc loc) {
1873 auto &blockAndLoc = blocksByName[name];
1874 if (!blockAndLoc.first) {
Chris Lattner3a467cc2018-07-01 20:28:00 -07001875 blockAndLoc.first = new BasicBlock();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001876 blockAndLoc.second = loc;
Chris Lattner4c95a502018-06-23 16:03:42 -07001877 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001878 return blockAndLoc.first;
Chris Lattner4c95a502018-06-23 16:03:42 -07001879 }
Chris Lattner48af7d12018-07-09 19:05:38 -07001880
James Molloy61a656c2018-07-22 15:45:24 -07001881 ParseResult
1882 parseOptionalBasicBlockArgList(SmallVectorImpl<BBArgument *> &results,
1883 BasicBlock *owner);
James Molloy4f788372018-07-24 15:01:27 -07001884 ParseResult parseBranchBlockAndUseList(BasicBlock *&block,
1885 SmallVectorImpl<CFGValue *> &values);
James Molloy61a656c2018-07-22 15:45:24 -07001886
Chris Lattner48af7d12018-07-09 19:05:38 -07001887 ParseResult parseBasicBlock();
1888 OperationInst *parseCFGOperation();
1889 TerminatorInst *parseTerminator();
Chris Lattner4c95a502018-06-23 16:03:42 -07001890};
1891} // end anonymous namespace
1892
James Molloy61a656c2018-07-22 15:45:24 -07001893/// Parse a (possibly empty) list of SSA operands with types as basic block
Chris Lattner2c402672018-07-23 11:56:17 -07001894/// arguments.
James Molloy61a656c2018-07-22 15:45:24 -07001895///
1896/// ssa-id-and-type-list ::= ssa-id-and-type (`,` ssa-id-and-type)*
1897///
1898ParseResult CFGFunctionParser::parseOptionalBasicBlockArgList(
1899 SmallVectorImpl<BBArgument *> &results, BasicBlock *owner) {
1900 if (getToken().is(Token::r_brace))
1901 return ParseSuccess;
1902
1903 return parseCommaSeparatedList([&]() -> ParseResult {
1904 auto type = parseSSADefOrUseAndType<Type *>(
1905 [&](SSAUseInfo useInfo, Type *type) -> Type * {
1906 BBArgument *arg = owner->addArgument(type);
Chris Lattner2b97d502018-08-06 14:19:46 -07001907 if (addDefinition(useInfo, arg))
James Molloy61a656c2018-07-22 15:45:24 -07001908 return nullptr;
1909 return type;
1910 });
1911 return type ? ParseSuccess : ParseFailure;
1912 });
1913}
1914
Chris Lattner48af7d12018-07-09 19:05:38 -07001915ParseResult CFGFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07001916 auto braceLoc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001917 if (parseToken(Token::l_brace, "expected '{' in CFG function"))
1918 return ParseFailure;
Chris Lattner48af7d12018-07-09 19:05:38 -07001919
1920 // Make sure we have at least one block.
1921 if (getToken().is(Token::r_brace))
1922 return emitError("CFG functions must have at least one basic block");
Chris Lattner4c95a502018-06-23 16:03:42 -07001923
1924 // Parse the list of blocks.
1925 while (!consumeIf(Token::r_brace))
Chris Lattner48af7d12018-07-09 19:05:38 -07001926 if (parseBasicBlock())
Chris Lattner4c95a502018-06-23 16:03:42 -07001927 return ParseFailure;
1928
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001929 // Verify that all referenced blocks were defined. Iteration over a
1930 // StringMap isn't determinstic, but this is good enough for our purposes.
Chris Lattner48af7d12018-07-09 19:05:38 -07001931 for (auto &elt : blocksByName) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001932 auto *bb = elt.second.first;
Chris Lattner3a467cc2018-07-01 20:28:00 -07001933 if (!bb->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001934 return emitError(elt.second.second,
James Molloy0ff71542018-07-23 16:56:32 -07001935 "reference to an undefined basic block '" + elt.first() +
1936 "'");
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001937 }
1938
Chris Lattnera8e47672018-07-25 14:08:16 -07001939 getModule()->getFunctions().push_back(function);
Chris Lattner6119d382018-07-20 18:41:34 -07001940
Chris Lattner40746442018-07-21 14:32:09 -07001941 return finalizeFunction(function, braceLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001942}
1943
1944/// Basic block declaration.
1945///
1946/// basic-block ::= bb-label instruction* terminator-stmt
1947/// bb-label ::= bb-id bb-arg-list? `:`
1948/// bb-id ::= bare-id
1949/// bb-arg-list ::= `(` ssa-id-and-type-list? `)`
1950///
Chris Lattner48af7d12018-07-09 19:05:38 -07001951ParseResult CFGFunctionParser::parseBasicBlock() {
1952 SMLoc nameLoc = getToken().getLoc();
1953 auto name = getTokenSpelling();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001954 if (parseToken(Token::bare_identifier, "expected basic block name"))
1955 return ParseFailure;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001956
Chris Lattner48af7d12018-07-09 19:05:38 -07001957 auto *block = getBlockNamed(name, nameLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001958
1959 // If this block has already been parsed, then this is a redefinition with the
1960 // same block name.
Chris Lattner3a467cc2018-07-01 20:28:00 -07001961 if (block->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001962 return emitError(nameLoc, "redefinition of block '" + name.str() + "'");
1963
Chris Lattner78276e32018-07-07 15:48:26 -07001964 // If an argument list is present, parse it.
1965 if (consumeIf(Token::l_paren)) {
James Molloy61a656c2018-07-22 15:45:24 -07001966 SmallVector<BBArgument *, 8> bbArgs;
Chris Lattnerf7702a62018-07-23 17:30:01 -07001967 if (parseOptionalBasicBlockArgList(bbArgs, block) ||
1968 parseToken(Token::r_paren, "expected ')' to end argument list"))
Chris Lattner78276e32018-07-07 15:48:26 -07001969 return ParseFailure;
Chris Lattner78276e32018-07-07 15:48:26 -07001970 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001971
James Molloy61a656c2018-07-22 15:45:24 -07001972 // Add the block to the function.
1973 function->push_back(block);
1974
Chris Lattnerf7702a62018-07-23 17:30:01 -07001975 if (parseToken(Token::colon, "expected ':' after basic block name"))
1976 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07001977
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001978 // Set the insertion point to the block we want to insert new operations into.
Chris Lattner48af7d12018-07-09 19:05:38 -07001979 builder.setInsertionPoint(block);
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001980
Chris Lattner992a1272018-08-07 12:02:37 -07001981 auto createOpFunc = [&](const OperationState &result) -> Operation * {
1982 return builder.createOperation(result);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001983 };
1984
Chris Lattnered65a732018-06-28 20:45:33 -07001985 // Parse the list of operations that make up the body of the block.
James Molloy4f788372018-07-24 15:01:27 -07001986 while (getToken().isNot(Token::kw_return, Token::kw_br, Token::kw_cond_br)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001987 if (parseOperation(createOpFunc))
Chris Lattnered65a732018-06-28 20:45:33 -07001988 return ParseFailure;
1989 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001990
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001991 if (!parseTerminator())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001992 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07001993
1994 return ParseSuccess;
1995}
1996
James Molloy4f788372018-07-24 15:01:27 -07001997ParseResult CFGFunctionParser::parseBranchBlockAndUseList(
1998 BasicBlock *&block, SmallVectorImpl<CFGValue *> &values) {
1999 block = getBlockNamed(getTokenSpelling(), getToken().getLoc());
2000 if (parseToken(Token::bare_identifier, "expected basic block name"))
2001 return ParseFailure;
2002
2003 if (!consumeIf(Token::l_paren))
2004 return ParseSuccess;
2005 if (parseOptionalSSAUseAndTypeList(values, /*isParenthesized*/ false) ||
2006 parseToken(Token::r_paren, "expected ')' to close argument list"))
2007 return ParseFailure;
2008 return ParseSuccess;
2009}
2010
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002011/// Parse the terminator instruction for a basic block.
2012///
2013/// terminator-stmt ::= `br` bb-id branch-use-list?
Chris Lattner1604e472018-07-23 08:42:19 -07002014/// branch-use-list ::= `(` ssa-use-list `)` ':' type-list-no-parens
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002015/// terminator-stmt ::=
2016/// `cond_br` ssa-use `,` bb-id branch-use-list? `,` bb-id branch-use-list?
2017/// terminator-stmt ::= `return` ssa-use-and-type-list?
2018///
Chris Lattner48af7d12018-07-09 19:05:38 -07002019TerminatorInst *CFGFunctionParser::parseTerminator() {
2020 switch (getToken().getKind()) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002021 default:
Chris Lattner3a467cc2018-07-01 20:28:00 -07002022 return (emitError("expected terminator at end of basic block"), nullptr);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002023
Chris Lattner40746442018-07-21 14:32:09 -07002024 case Token::kw_return: {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002025 consumeToken(Token::kw_return);
Chris Lattner40746442018-07-21 14:32:09 -07002026
Chris Lattner2c402672018-07-23 11:56:17 -07002027 // Parse any operands.
2028 SmallVector<CFGValue *, 8> operands;
2029 if (parseOptionalSSAUseAndTypeList(operands, /*isParenthesized*/ false))
2030 return nullptr;
2031 return builder.createReturnInst(operands);
Chris Lattner40746442018-07-21 14:32:09 -07002032 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002033
2034 case Token::kw_br: {
2035 consumeToken(Token::kw_br);
James Molloy4f788372018-07-24 15:01:27 -07002036 BasicBlock *destBB;
2037 SmallVector<CFGValue *, 4> values;
2038 if (parseBranchBlockAndUseList(destBB, values))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002039 return nullptr;
Chris Lattner1604e472018-07-23 08:42:19 -07002040 auto branch = builder.createBranchInst(destBB);
James Molloy4f788372018-07-24 15:01:27 -07002041 branch->addOperands(values);
Chris Lattner1604e472018-07-23 08:42:19 -07002042 return branch;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002043 }
James Molloy4f788372018-07-24 15:01:27 -07002044
2045 case Token::kw_cond_br: {
2046 consumeToken(Token::kw_cond_br);
2047 SSAUseInfo ssaUse;
2048 if (parseSSAUse(ssaUse))
2049 return nullptr;
2050 auto *cond = resolveSSAUse(ssaUse, builder.getIntegerType(1));
2051 if (!cond)
2052 return (emitError("expected type was boolean (i1)"), nullptr);
2053 if (parseToken(Token::comma, "expected ',' in conditional branch"))
2054 return nullptr;
2055
2056 BasicBlock *trueBlock;
2057 SmallVector<CFGValue *, 4> trueOperands;
2058 if (parseBranchBlockAndUseList(trueBlock, trueOperands))
2059 return nullptr;
2060
2061 if (parseToken(Token::comma, "expected ',' in conditional branch"))
2062 return nullptr;
2063
2064 BasicBlock *falseBlock;
2065 SmallVector<CFGValue *, 4> falseOperands;
2066 if (parseBranchBlockAndUseList(falseBlock, falseOperands))
2067 return nullptr;
2068
2069 auto branch = builder.createCondBranchInst(cast<CFGValue>(cond), trueBlock,
2070 falseBlock);
2071 branch->addTrueOperands(trueOperands);
2072 branch->addFalseOperands(falseOperands);
2073 return branch;
2074 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002075 }
2076}
2077
Chris Lattner48af7d12018-07-09 19:05:38 -07002078//===----------------------------------------------------------------------===//
2079// ML Functions
2080//===----------------------------------------------------------------------===//
2081
2082namespace {
2083/// Refined parser for MLFunction bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07002084class MLFunctionParser : public FunctionParser {
Chris Lattner48af7d12018-07-09 19:05:38 -07002085public:
Chris Lattner48af7d12018-07-09 19:05:38 -07002086 MLFunctionParser(ParserState &state, MLFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07002087 : FunctionParser(state, Kind::MLFunc), function(function),
2088 builder(function) {}
Chris Lattner48af7d12018-07-09 19:05:38 -07002089
2090 ParseResult parseFunctionBody();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002091
2092private:
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002093 MLFunction *function;
2094
2095 /// This builder intentionally shadows the builder in the base class, with a
2096 /// more specific builder type.
2097 MLFuncBuilder builder;
2098
2099 ParseResult parseForStmt();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002100 AffineConstantExpr *parseIntConstant();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002101 ParseResult parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002102 ParseResult parseElseClause(IfClause *elseClause);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002103 ParseResult parseStatements(StmtBlock *block);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002104 ParseResult parseStmtBlock(StmtBlock *block);
Chris Lattner48af7d12018-07-09 19:05:38 -07002105};
2106} // end anonymous namespace
2107
Chris Lattner48af7d12018-07-09 19:05:38 -07002108ParseResult MLFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07002109 auto braceLoc = getToken().getLoc();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002110 // Parse statements in this function
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002111
Chris Lattnerf7702a62018-07-23 17:30:01 -07002112 if (parseToken(Token::l_brace, "expected '{' in ML function") ||
2113 parseStatements(function)) {
2114 return ParseFailure;
2115 }
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002116
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002117 // TODO: store return operands in the IR.
2118 SmallVector<SSAUseInfo, 4> dummyUseInfo;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002119
Chris Lattnerf7702a62018-07-23 17:30:01 -07002120 if (parseToken(Token::kw_return,
2121 "ML function must end with return statement") ||
2122 parseOptionalSSAUseList(dummyUseInfo) ||
2123 parseToken(Token::r_brace, "expected '}' to end mlfunc"))
2124 return ParseFailure;
Chris Lattner40746442018-07-21 14:32:09 -07002125
Chris Lattnera8e47672018-07-25 14:08:16 -07002126 getModule()->getFunctions().push_back(function);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002127
Chris Lattner40746442018-07-21 14:32:09 -07002128 return finalizeFunction(function, braceLoc);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002129}
2130
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002131/// For statement.
2132///
Chris Lattner48af7d12018-07-09 19:05:38 -07002133/// ml-for-stmt ::= `for` ssa-id `=` lower-bound `to` upper-bound
2134/// (`step` integer-literal)? `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002135///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002136ParseResult MLFunctionParser::parseForStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002137 consumeToken(Token::kw_for);
2138
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002139 // Parse induction variable
2140 if (getToken().isNot(Token::percent_identifier))
2141 return emitError("expected SSA identifier for the loop variable");
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002142
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002143 auto loc = getToken().getLoc();
Tatiana Shpeismand880b352018-07-31 23:14:16 -07002144 StringRef inductionVariableName = getTokenSpelling();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002145 consumeToken(Token::percent_identifier);
2146
Chris Lattnerf7702a62018-07-23 17:30:01 -07002147 if (parseToken(Token::equal, "expected ="))
2148 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002149
2150 // Parse loop bounds
2151 AffineConstantExpr *lowerBound = parseIntConstant();
2152 if (!lowerBound)
2153 return ParseFailure;
2154
Chris Lattnerf7702a62018-07-23 17:30:01 -07002155 if (parseToken(Token::kw_to, "expected 'to' between bounds"))
2156 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002157
2158 AffineConstantExpr *upperBound = parseIntConstant();
2159 if (!upperBound)
2160 return ParseFailure;
2161
2162 // Parse step
2163 AffineConstantExpr *step = nullptr;
2164 if (consumeIf(Token::kw_step)) {
2165 step = parseIntConstant();
2166 if (!step)
2167 return ParseFailure;
2168 }
2169
2170 // Create for statement.
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002171 ForStmt *forStmt = builder.createFor(lowerBound, upperBound, step);
2172
2173 // Create SSA value definition for the induction variable.
Chris Lattner2b97d502018-08-06 14:19:46 -07002174 if (addDefinition({inductionVariableName, 0, loc}, forStmt))
2175 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002176
2177 // If parsing of the for statement body fails,
2178 // MLIR contains for statement with those nested statements that have been
2179 // successfully parsed.
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002180 if (parseStmtBlock(forStmt))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002181 return ParseFailure;
2182
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002183 // Reset insertion point to the current block.
2184 builder.setInsertionPoint(forStmt->getBlock());
2185
Tatiana Shpeismand880b352018-07-31 23:14:16 -07002186 // TODO: remove definition of the induction variable.
2187
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002188 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002189}
2190
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002191// This method is temporary workaround to parse simple loop bounds and
2192// step.
2193// TODO: remove this method once it's no longer used.
2194AffineConstantExpr *MLFunctionParser::parseIntConstant() {
2195 if (getToken().isNot(Token::integer))
2196 return (emitError("expected non-negative integer for now"), nullptr);
2197
2198 auto val = getToken().getUInt64IntegerValue();
2199 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
2200 return (emitError("constant too large for affineint"), nullptr);
2201 }
2202 consumeToken(Token::integer);
2203 return builder.getConstantExpr((int64_t)val.getValue());
2204}
2205
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002206/// If statement.
2207///
Chris Lattner48af7d12018-07-09 19:05:38 -07002208/// ml-if-head ::= `if` ml-if-cond `{` ml-stmt* `}`
2209/// | ml-if-head `else` `if` ml-if-cond `{` ml-stmt* `}`
2210/// ml-if-stmt ::= ml-if-head
2211/// | ml-if-head `else` `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002212///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002213ParseResult MLFunctionParser::parseIfStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002214 consumeToken(Token::kw_if);
Chris Lattnerf7702a62018-07-23 17:30:01 -07002215 if (parseToken(Token::l_paren, "expected ("))
2216 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002217
James Molloy0ff71542018-07-23 16:56:32 -07002218 // TODO: parse condition
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002219
Chris Lattnerf7702a62018-07-23 17:30:01 -07002220 if (parseToken(Token::r_paren, "expected )"))
2221 return ParseFailure;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002222
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002223 IfStmt *ifStmt = builder.createIf();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002224 IfClause *thenClause = ifStmt->getThenClause();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002225
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002226 // When parsing of an if statement body fails, the IR contains
2227 // the if statement with the portion of the body that has been
2228 // successfully parsed.
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002229 if (parseStmtBlock(thenClause))
2230 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002231
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002232 if (consumeIf(Token::kw_else)) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002233 auto *elseClause = ifStmt->createElseClause();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002234 if (parseElseClause(elseClause))
2235 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002236 }
2237
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002238 // Reset insertion point to the current block.
2239 builder.setInsertionPoint(ifStmt->getBlock());
2240
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002241 return ParseSuccess;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002242}
2243
2244ParseResult MLFunctionParser::parseElseClause(IfClause *elseClause) {
2245 if (getToken().is(Token::kw_if)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002246 builder.setInsertionPoint(elseClause);
2247 return parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002248 }
2249
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002250 return parseStmtBlock(elseClause);
2251}
2252
2253///
2254/// Parse a list of statements ending with `return` or `}`
2255///
2256ParseResult MLFunctionParser::parseStatements(StmtBlock *block) {
Chris Lattner992a1272018-08-07 12:02:37 -07002257 auto createOpFunc = [&](const OperationState &state) -> Operation * {
2258 return builder.createOperation(state);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002259 };
2260
2261 builder.setInsertionPoint(block);
2262
2263 while (getToken().isNot(Token::kw_return, Token::r_brace)) {
2264 switch (getToken().getKind()) {
2265 default:
2266 if (parseOperation(createOpFunc))
2267 return ParseFailure;
2268 break;
2269 case Token::kw_for:
2270 if (parseForStmt())
2271 return ParseFailure;
2272 break;
2273 case Token::kw_if:
2274 if (parseIfStmt())
2275 return ParseFailure;
2276 break;
2277 } // end switch
2278 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002279
2280 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002281}
2282
2283///
2284/// Parse `{` ml-stmt* `}`
2285///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002286ParseResult MLFunctionParser::parseStmtBlock(StmtBlock *block) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002287 if (parseToken(Token::l_brace, "expected '{' before statement list") ||
2288 parseStatements(block) ||
2289 parseToken(Token::r_brace,
2290 "expected '}' at the end of the statement block"))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002291 return ParseFailure;
2292
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002293 return ParseSuccess;
2294}
2295
Chris Lattner4c95a502018-06-23 16:03:42 -07002296//===----------------------------------------------------------------------===//
2297// Top-level entity parsing.
2298//===----------------------------------------------------------------------===//
2299
Chris Lattner2e595eb2018-07-10 10:08:27 -07002300namespace {
2301/// This parser handles entities that are only valid at the top level of the
2302/// file.
2303class ModuleParser : public Parser {
2304public:
2305 explicit ModuleParser(ParserState &state) : Parser(state) {}
2306
2307 ParseResult parseModule();
2308
2309private:
2310 ParseResult parseAffineMapDef();
2311
2312 // Functions.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002313 ParseResult parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2314 SmallVectorImpl<StringRef> &argNames);
2315 ParseResult parseFunctionSignature(StringRef &name, FunctionType *&type,
2316 SmallVectorImpl<StringRef> *argNames);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002317 ParseResult parseExtFunc();
2318 ParseResult parseCFGFunc();
2319 ParseResult parseMLFunc();
2320};
2321} // end anonymous namespace
2322
2323/// Affine map declaration.
2324///
2325/// affine-map-def ::= affine-map-id `=` affine-map-inline
2326///
2327ParseResult ModuleParser::parseAffineMapDef() {
2328 assert(getToken().is(Token::hash_identifier));
2329
2330 StringRef affineMapId = getTokenSpelling().drop_front();
2331
2332 // Check for redefinitions.
2333 auto *&entry = getState().affineMapDefinitions[affineMapId];
2334 if (entry)
2335 return emitError("redefinition of affine map id '" + affineMapId + "'");
2336
2337 consumeToken(Token::hash_identifier);
2338
2339 // Parse the '='
Chris Lattnerf7702a62018-07-23 17:30:01 -07002340 if (parseToken(Token::equal,
2341 "expected '=' in affine map outlined definition"))
2342 return ParseFailure;
Chris Lattner2e595eb2018-07-10 10:08:27 -07002343
2344 entry = parseAffineMapInline();
2345 if (!entry)
2346 return ParseFailure;
2347
Chris Lattner2e595eb2018-07-10 10:08:27 -07002348 return ParseSuccess;
2349}
2350
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002351/// Parse a (possibly empty) list of MLFunction arguments with types.
2352///
2353/// ml-argument ::= ssa-id `:` type
2354/// ml-argument-list ::= ml-argument (`,` ml-argument)* | /*empty*/
2355///
2356ParseResult
2357ModuleParser::parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2358 SmallVectorImpl<StringRef> &argNames) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002359 consumeToken(Token::l_paren);
2360
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002361 auto parseElt = [&]() -> ParseResult {
2362 // Parse argument name
2363 if (getToken().isNot(Token::percent_identifier))
2364 return emitError("expected SSA identifier");
2365
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002366 StringRef name = getTokenSpelling();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002367 consumeToken(Token::percent_identifier);
2368 argNames.push_back(name);
2369
Chris Lattnerf7702a62018-07-23 17:30:01 -07002370 if (parseToken(Token::colon, "expected ':'"))
2371 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002372
2373 // Parse argument type
2374 auto elt = parseType();
2375 if (!elt)
2376 return ParseFailure;
2377 argTypes.push_back(elt);
2378
2379 return ParseSuccess;
2380 };
2381
Chris Lattner40746442018-07-21 14:32:09 -07002382 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002383}
2384
Chris Lattner2e595eb2018-07-10 10:08:27 -07002385/// Parse a function signature, starting with a name and including the parameter
2386/// list.
2387///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002388/// argument-list ::= type (`,` type)* | /*empty*/ | ml-argument-list
Chris Lattner2e595eb2018-07-10 10:08:27 -07002389/// function-signature ::= function-id `(` argument-list `)` (`->` type-list)?
2390///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002391ParseResult
2392ModuleParser::parseFunctionSignature(StringRef &name, FunctionType *&type,
2393 SmallVectorImpl<StringRef> *argNames) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002394 if (getToken().isNot(Token::at_identifier))
2395 return emitError("expected a function identifier like '@foo'");
2396
2397 name = getTokenSpelling().drop_front();
2398 consumeToken(Token::at_identifier);
2399
2400 if (getToken().isNot(Token::l_paren))
2401 return emitError("expected '(' in function signature");
2402
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002403 SmallVector<Type *, 4> argTypes;
2404 ParseResult parseResult;
2405
2406 if (argNames)
2407 parseResult = parseMLArgumentList(argTypes, *argNames);
2408 else
2409 parseResult = parseTypeList(argTypes);
2410
2411 if (parseResult)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002412 return ParseFailure;
2413
2414 // Parse the return type if present.
2415 SmallVector<Type *, 4> results;
2416 if (consumeIf(Token::arrow)) {
2417 if (parseTypeList(results))
2418 return ParseFailure;
2419 }
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002420 type = builder.getFunctionType(argTypes, results);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002421 return ParseSuccess;
2422}
2423
2424/// External function declarations.
2425///
2426/// ext-func ::= `extfunc` function-signature
2427///
2428ParseResult ModuleParser::parseExtFunc() {
2429 consumeToken(Token::kw_extfunc);
2430
2431 StringRef name;
2432 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002433 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002434 return ParseFailure;
2435
2436 // Okay, the external function definition was parsed correctly.
Chris Lattnera8e47672018-07-25 14:08:16 -07002437 getModule()->getFunctions().push_back(new ExtFunction(name, type));
Chris Lattner2e595eb2018-07-10 10:08:27 -07002438 return ParseSuccess;
2439}
2440
2441/// CFG function declarations.
2442///
2443/// cfg-func ::= `cfgfunc` function-signature `{` basic-block+ `}`
2444///
2445ParseResult ModuleParser::parseCFGFunc() {
2446 consumeToken(Token::kw_cfgfunc);
2447
2448 StringRef name;
2449 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002450 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002451 return ParseFailure;
2452
2453 // Okay, the CFG function signature was parsed correctly, create the function.
2454 auto function = new CFGFunction(name, type);
2455
2456 return CFGFunctionParser(getState(), function).parseFunctionBody();
2457}
2458
2459/// ML function declarations.
2460///
2461/// ml-func ::= `mlfunc` ml-func-signature `{` ml-stmt* ml-return-stmt `}`
2462///
2463ParseResult ModuleParser::parseMLFunc() {
2464 consumeToken(Token::kw_mlfunc);
2465
2466 StringRef name;
2467 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002468 SmallVector<StringRef, 4> argNames;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002469
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002470 auto loc = getToken().getLoc();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002471 if (parseFunctionSignature(name, type, &argNames))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002472 return ParseFailure;
2473
2474 // Okay, the ML function signature was parsed correctly, create the function.
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002475 auto function = MLFunction::create(name, type);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002476
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002477 // Create the parser.
2478 auto parser = MLFunctionParser(getState(), function);
2479
2480 // Add definitions of the function arguments.
2481 for (unsigned i = 0, e = function->getNumArguments(); i != e; ++i) {
2482 if (parser.addDefinition({argNames[i], 0, loc}, function->getArgument(i)))
2483 return ParseFailure;
2484 }
2485
2486 return parser.parseFunctionBody();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002487}
2488
Chris Lattnere79379a2018-06-22 10:39:19 -07002489/// This is the top-level module parser.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002490ParseResult ModuleParser::parseModule() {
Chris Lattnere79379a2018-06-22 10:39:19 -07002491 while (1) {
Chris Lattner48af7d12018-07-09 19:05:38 -07002492 switch (getToken().getKind()) {
Chris Lattnere79379a2018-06-22 10:39:19 -07002493 default:
2494 emitError("expected a top level entity");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002495 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002496
Uday Bondhugula015cbb12018-07-03 20:16:08 -07002497 // If we got to the end of the file, then we're done.
Chris Lattnere79379a2018-06-22 10:39:19 -07002498 case Token::eof:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002499 return ParseSuccess;
Chris Lattnere79379a2018-06-22 10:39:19 -07002500
2501 // If we got an error token, then the lexer already emitted an error, just
2502 // stop. Someday we could introduce error recovery if there was demand for
2503 // it.
2504 case Token::error:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002505 return ParseFailure;
2506
2507 case Token::hash_identifier:
2508 if (parseAffineMapDef())
2509 return ParseFailure;
2510 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002511
2512 case Token::kw_extfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002513 if (parseExtFunc())
2514 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002515 break;
2516
Chris Lattner4c95a502018-06-23 16:03:42 -07002517 case Token::kw_cfgfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002518 if (parseCFGFunc())
2519 return ParseFailure;
MLIR Teamf85a6262018-06-27 11:03:08 -07002520 break;
Chris Lattner4c95a502018-06-23 16:03:42 -07002521
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002522 case Token::kw_mlfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002523 if (parseMLFunc())
2524 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002525 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002526 }
2527 }
2528}
2529
2530//===----------------------------------------------------------------------===//
2531
Jacques Pienaar7b829702018-07-03 13:24:09 -07002532void mlir::defaultErrorReporter(const llvm::SMDiagnostic &error) {
2533 const auto &sourceMgr = *error.getSourceMgr();
2534 sourceMgr.PrintMessage(error.getLoc(), error.getKind(), error.getMessage());
2535}
2536
Chris Lattnere79379a2018-06-22 10:39:19 -07002537/// This parses the file specified by the indicated SourceMgr and returns an
2538/// MLIR module if it was valid. If not, it emits diagnostics and returns null.
Jacques Pienaar9c411be2018-06-24 19:17:35 -07002539Module *mlir::parseSourceFile(llvm::SourceMgr &sourceMgr, MLIRContext *context,
Jacques Pienaar7b829702018-07-03 13:24:09 -07002540 SMDiagnosticHandlerTy errorReporter) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002541 // This is the result module we are parsing into.
2542 std::unique_ptr<Module> module(new Module(context));
2543
2544 ParserState state(sourceMgr, module.get(),
Jacques Pienaar0bffd862018-07-11 13:26:23 -07002545 errorReporter ? errorReporter : defaultErrorReporter);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002546 if (ModuleParser(state).parseModule())
2547 return nullptr;
Chris Lattner21e67f62018-07-06 10:46:19 -07002548
2549 // Make sure the parse module has no other structural problems detected by the
2550 // verifier.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002551 module->verify();
2552 return module.release();
Chris Lattnere79379a2018-06-22 10:39:19 -07002553}