blob: b50e950678e073fdb4f4ab826e0d316fe2332f67 [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 Lattner7f9cc272018-07-19 08:35:28 -070090typedef std::function<Operation *(Identifier, ArrayRef<SSAValue *>,
91 ArrayRef<Type *>, ArrayRef<NamedAttribute>)>
Tatiana Shpeisman565b9642018-07-16 11:47:09 -070092 CreateOperationFunction;
93
Chris Lattner48af7d12018-07-09 19:05:38 -070094/// This class implement support for parsing global entities like types and
95/// shared entities like SSA names. It is intended to be subclassed by
96/// specialized subparsers that include state, e.g. when a local symbol table.
97class Parser {
98public:
Chris Lattner2e595eb2018-07-10 10:08:27 -070099 Builder builder;
Chris Lattner48af7d12018-07-09 19:05:38 -0700100
Chris Lattner2e595eb2018-07-10 10:08:27 -0700101 Parser(ParserState &state) : builder(state.context), state(state) {}
102
103 // Helper methods to get stuff from the parser-global state.
104 ParserState &getState() const { return state; }
Chris Lattner48af7d12018-07-09 19:05:38 -0700105 MLIRContext *getContext() const { return state.context; }
Chris Lattner2e595eb2018-07-10 10:08:27 -0700106 Module *getModule() { return state.module; }
Chris Lattner85ee1512018-07-25 11:15:20 -0700107 OperationSet &getOperationSet() const { return state.operationSet; }
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700108 llvm::SourceMgr &getSourceMgr() { return state.lex.getSourceMgr(); }
Chris Lattner48af7d12018-07-09 19:05:38 -0700109
110 /// Return the current token the parser is inspecting.
111 const Token &getToken() const { return state.curToken; }
112 StringRef getTokenSpelling() const { return state.curToken.getSpelling(); }
Chris Lattnere79379a2018-06-22 10:39:19 -0700113
114 /// Emit an error and return failure.
Chris Lattner4c95a502018-06-23 16:03:42 -0700115 ParseResult emitError(const Twine &message) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700116 return emitError(state.curToken.getLoc(), message);
Chris Lattner4c95a502018-06-23 16:03:42 -0700117 }
118 ParseResult emitError(SMLoc loc, const Twine &message);
Chris Lattnere79379a2018-06-22 10:39:19 -0700119
120 /// Advance the current lexer onto the next token.
121 void consumeToken() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700122 assert(state.curToken.isNot(Token::eof, Token::error) &&
Chris Lattnere79379a2018-06-22 10:39:19 -0700123 "shouldn't advance past EOF or errors");
Chris Lattner48af7d12018-07-09 19:05:38 -0700124 state.curToken = state.lex.lexToken();
Chris Lattnere79379a2018-06-22 10:39:19 -0700125 }
126
127 /// Advance the current lexer onto the next token, asserting what the expected
128 /// current token is. This is preferred to the above method because it leads
129 /// to more self-documenting code with better checking.
Chris Lattner8da0c282018-06-29 11:15:56 -0700130 void consumeToken(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700131 assert(state.curToken.is(kind) && "consumed an unexpected token");
Chris Lattnere79379a2018-06-22 10:39:19 -0700132 consumeToken();
133 }
134
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700135 /// If the current token has the specified kind, consume it and return true.
136 /// If not, return false.
Chris Lattner8da0c282018-06-29 11:15:56 -0700137 bool consumeIf(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700138 if (state.curToken.isNot(kind))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700139 return false;
140 consumeToken(kind);
141 return true;
142 }
143
Chris Lattnerf7702a62018-07-23 17:30:01 -0700144 /// Consume the specified token if present and return success. On failure,
145 /// output a diagnostic and return failure.
146 ParseResult parseToken(Token::Kind expectedToken, const Twine &message);
147
Chris Lattner40746442018-07-21 14:32:09 -0700148 /// Parse a comma-separated list of elements up until the specified end token.
149 ParseResult
150 parseCommaSeparatedListUntil(Token::Kind rightToken,
151 const std::function<ParseResult()> &parseElement,
152 bool allowEmptyList = true);
153
154 /// Parse a comma separated list of elements that must have at least one entry
155 /// in it.
156 ParseResult
157 parseCommaSeparatedList(const std::function<ParseResult()> &parseElement);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700158
Chris Lattnerf7e22732018-06-22 22:03:48 -0700159 // We have two forms of parsing methods - those that return a non-null
160 // pointer on success, and those that return a ParseResult to indicate whether
161 // they returned a failure. The second class fills in by-reference arguments
162 // as the results of their action.
163
Chris Lattnere79379a2018-06-22 10:39:19 -0700164 // Type parsing.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700165 VectorType *parseVectorType();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700166 ParseResult parseDimensionListRanked(SmallVectorImpl<int> &dimensions);
Chris Lattnerf7e22732018-06-22 22:03:48 -0700167 Type *parseTensorType();
168 Type *parseMemRefType();
169 Type *parseFunctionType();
170 Type *parseType();
Chris Lattner1604e472018-07-23 08:42:19 -0700171 ParseResult parseTypeListNoParens(SmallVectorImpl<Type *> &elements);
James Molloy0ff71542018-07-23 16:56:32 -0700172 ParseResult parseTypeList(SmallVectorImpl<Type *> &elements);
Chris Lattnere79379a2018-06-22 10:39:19 -0700173
Chris Lattner7121b802018-07-04 20:45:39 -0700174 // Attribute parsing.
175 Attribute *parseAttribute();
176 ParseResult parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes);
177
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700178 // Polyhedral structures.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700179 AffineMap *parseAffineMapInline();
MLIR Team718c82f2018-07-16 09:45:22 -0700180 AffineMap *parseAffineMapReference();
MLIR Teamf85a6262018-06-27 11:03:08 -0700181
Chris Lattner48af7d12018-07-09 19:05:38 -0700182private:
183 // The Parser is subclassed and reinstantiated. Do not add additional
184 // non-trivial state here, add it to the ParserState class.
185 ParserState &state;
Chris Lattnere79379a2018-06-22 10:39:19 -0700186};
187} // end anonymous namespace
188
189//===----------------------------------------------------------------------===//
190// Helper methods.
191//===----------------------------------------------------------------------===//
192
Chris Lattner4c95a502018-06-23 16:03:42 -0700193ParseResult Parser::emitError(SMLoc loc, const Twine &message) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700194 // If we hit a parse error in response to a lexer error, then the lexer
Jacques Pienaar9c411be2018-06-24 19:17:35 -0700195 // already reported the error.
Chris Lattner48af7d12018-07-09 19:05:38 -0700196 if (getToken().is(Token::error))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700197 return ParseFailure;
198
Chris Lattner48af7d12018-07-09 19:05:38 -0700199 auto &sourceMgr = state.lex.getSourceMgr();
200 state.errorReporter(sourceMgr.GetMessage(loc, SourceMgr::DK_Error, message));
Chris Lattnere79379a2018-06-22 10:39:19 -0700201 return ParseFailure;
202}
203
Chris Lattnerf7702a62018-07-23 17:30:01 -0700204/// Consume the specified token if present and return success. On failure,
205/// output a diagnostic and return failure.
206ParseResult Parser::parseToken(Token::Kind expectedToken,
207 const Twine &message) {
208 if (consumeIf(expectedToken))
209 return ParseSuccess;
210 return emitError(message);
211}
212
Chris Lattner40746442018-07-21 14:32:09 -0700213/// Parse a comma separated list of elements that must have at least one entry
214/// in it.
215ParseResult Parser::parseCommaSeparatedList(
216 const std::function<ParseResult()> &parseElement) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700217 // Non-empty case starts with an element.
218 if (parseElement())
219 return ParseFailure;
220
221 // Otherwise we have a list of comma separated elements.
222 while (consumeIf(Token::comma)) {
223 if (parseElement())
224 return ParseFailure;
225 }
Chris Lattner40746442018-07-21 14:32:09 -0700226 return ParseSuccess;
227}
228
229/// Parse a comma-separated list of elements, terminated with an arbitrary
230/// token. This allows empty lists if allowEmptyList is true.
231///
232/// abstract-list ::= rightToken // if allowEmptyList == true
233/// abstract-list ::= element (',' element)* rightToken
234///
235ParseResult Parser::parseCommaSeparatedListUntil(
236 Token::Kind rightToken, const std::function<ParseResult()> &parseElement,
237 bool allowEmptyList) {
238 // Handle the empty case.
239 if (getToken().is(rightToken)) {
240 if (!allowEmptyList)
241 return emitError("expected list element");
242 consumeToken(rightToken);
243 return ParseSuccess;
244 }
245
Chris Lattnerf7702a62018-07-23 17:30:01 -0700246 if (parseCommaSeparatedList(parseElement) ||
247 parseToken(rightToken, "expected ',' or '" +
248 Token::getTokenSpelling(rightToken) + "'"))
Chris Lattner40746442018-07-21 14:32:09 -0700249 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700250
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700251 return ParseSuccess;
252}
Chris Lattnere79379a2018-06-22 10:39:19 -0700253
254//===----------------------------------------------------------------------===//
255// Type Parsing
256//===----------------------------------------------------------------------===//
257
Chris Lattnerc3251192018-07-27 13:09:58 -0700258/// Parse an arbitrary type.
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700259///
Chris Lattnerc3251192018-07-27 13:09:58 -0700260/// type ::= integer-type
261/// | float-type
262/// | other-type
263/// | vector-type
264/// | tensor-type
265/// | memref-type
266/// | function-type
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700267///
Chris Lattnerc3251192018-07-27 13:09:58 -0700268/// float-type ::= `f16` | `bf16` | `f32` | `f64`
269/// other-type ::= `affineint` | `tf_control`
270///
271Type *Parser::parseType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700272 switch (getToken().getKind()) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700273 default:
274 return (emitError("expected type"), nullptr);
Chris Lattnerc3251192018-07-27 13:09:58 -0700275 case Token::kw_memref:
276 return parseMemRefType();
277 case Token::kw_tensor:
278 return parseTensorType();
279 case Token::kw_vector:
280 return parseVectorType();
281 case Token::l_paren:
282 return parseFunctionType();
283 // integer-type
284 case Token::inttype: {
285 auto width = getToken().getIntTypeBitwidth();
286 if (!width.hasValue())
287 return (emitError("invalid integer width"), nullptr);
288 consumeToken(Token::inttype);
289 return builder.getIntegerType(width.getValue());
290 }
291
292 // float-type
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700293 case Token::kw_bf16:
294 consumeToken(Token::kw_bf16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700295 return builder.getBF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700296 case Token::kw_f16:
297 consumeToken(Token::kw_f16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700298 return builder.getF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700299 case Token::kw_f32:
300 consumeToken(Token::kw_f32);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700301 return builder.getF32Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700302 case Token::kw_f64:
303 consumeToken(Token::kw_f64);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700304 return builder.getF64Type();
Chris Lattnerc3251192018-07-27 13:09:58 -0700305
306 // other-type
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700307 case Token::kw_affineint:
308 consumeToken(Token::kw_affineint);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700309 return builder.getAffineIntType();
Jacques Pienaarc0d69302018-07-27 11:07:12 -0700310 case Token::kw_tf_control:
311 consumeToken(Token::kw_tf_control);
312 return builder.getTFControlType();
James Molloy72b0cbe2018-08-01 12:55:27 -0700313 case Token::kw_tf_string:
314 consumeToken(Token::kw_tf_string);
315 return builder.getTFStringType();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700316 }
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700317}
318
319/// Parse a vector type.
320///
321/// vector-type ::= `vector` `<` const-dimension-list primitive-type `>`
322/// const-dimension-list ::= (integer-literal `x`)+
323///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700324VectorType *Parser::parseVectorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700325 consumeToken(Token::kw_vector);
326
Chris Lattnerf7702a62018-07-23 17:30:01 -0700327 if (parseToken(Token::less, "expected '<' in vector type"))
328 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700329
Chris Lattner48af7d12018-07-09 19:05:38 -0700330 if (getToken().isNot(Token::integer))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700331 return (emitError("expected dimension size in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700332
333 SmallVector<unsigned, 4> dimensions;
Chris Lattner48af7d12018-07-09 19:05:38 -0700334 while (getToken().is(Token::integer)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700335 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700336 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700337 if (!dimension.hasValue())
Chris Lattnerf7e22732018-06-22 22:03:48 -0700338 return (emitError("invalid dimension in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700339 dimensions.push_back(dimension.getValue());
340
341 consumeToken(Token::integer);
342
343 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700344 if (getToken().isNot(Token::bare_identifier) ||
345 getTokenSpelling()[0] != 'x')
Chris Lattnerf7e22732018-06-22 22:03:48 -0700346 return (emitError("expected 'x' in vector dimension list"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700347
348 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700349 if (getTokenSpelling().size() != 1)
350 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700351
352 // Consume the 'x'.
353 consumeToken(Token::bare_identifier);
354 }
355
356 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700357 auto typeLoc = getToken().getLoc();
358 auto *elementType = parseType();
359 if (!elementType || parseToken(Token::greater, "expected '>' in vector type"))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700360 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700361
Chris Lattnerc3251192018-07-27 13:09:58 -0700362 if (!isa<FloatType>(elementType) && !isa<IntegerType>(elementType))
363 return (emitError(typeLoc, "invalid vector element type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700364
Chris Lattnerf7e22732018-06-22 22:03:48 -0700365 return VectorType::get(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700366}
367
368/// Parse a dimension list of a tensor or memref type. This populates the
369/// dimension list, returning -1 for the '?' dimensions.
370///
371/// dimension-list-ranked ::= (dimension `x`)*
372/// dimension ::= `?` | integer-literal
373///
374ParseResult Parser::parseDimensionListRanked(SmallVectorImpl<int> &dimensions) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700375 while (getToken().isAny(Token::integer, Token::question)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700376 if (consumeIf(Token::question)) {
377 dimensions.push_back(-1);
378 } else {
379 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700380 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700381 if (!dimension.hasValue() || (int)dimension.getValue() < 0)
382 return emitError("invalid dimension");
383 dimensions.push_back((int)dimension.getValue());
384 consumeToken(Token::integer);
385 }
386
387 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700388 if (getToken().isNot(Token::bare_identifier) ||
389 getTokenSpelling()[0] != 'x')
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700390 return emitError("expected 'x' in dimension list");
391
392 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700393 if (getTokenSpelling().size() != 1)
394 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700395
396 // Consume the 'x'.
397 consumeToken(Token::bare_identifier);
398 }
399
400 return ParseSuccess;
401}
402
403/// Parse a tensor type.
404///
405/// tensor-type ::= `tensor` `<` dimension-list element-type `>`
406/// dimension-list ::= dimension-list-ranked | `??`
407///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700408Type *Parser::parseTensorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700409 consumeToken(Token::kw_tensor);
410
Chris Lattnerf7702a62018-07-23 17:30:01 -0700411 if (parseToken(Token::less, "expected '<' in tensor type"))
412 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700413
414 bool isUnranked;
415 SmallVector<int, 4> dimensions;
416
417 if (consumeIf(Token::questionquestion)) {
418 isUnranked = true;
419 } else {
420 isUnranked = false;
421 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700422 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700423 }
424
425 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700426 auto typeLoc = getToken().getLoc();
427 auto *elementType = parseType();
428 if (!elementType || parseToken(Token::greater, "expected '>' in tensor type"))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700429 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700430
Chris Lattnerc3251192018-07-27 13:09:58 -0700431 if (!isa<IntegerType>(elementType) && !isa<FloatType>(elementType) &&
432 !isa<VectorType>(elementType))
433 return (emitError(typeLoc, "invalid tensor element type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700434
MLIR Team355ec862018-06-23 18:09:09 -0700435 if (isUnranked)
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700436 return builder.getTensorType(elementType);
437 return builder.getTensorType(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700438}
439
440/// Parse a memref type.
441///
442/// memref-type ::= `memref` `<` dimension-list-ranked element-type
443/// (`,` semi-affine-map-composition)? (`,` memory-space)? `>`
444///
445/// semi-affine-map-composition ::= (semi-affine-map `,` )* semi-affine-map
446/// memory-space ::= integer-literal /* | TODO: address-space-id */
447///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700448Type *Parser::parseMemRefType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700449 consumeToken(Token::kw_memref);
450
Chris Lattnerf7702a62018-07-23 17:30:01 -0700451 if (parseToken(Token::less, "expected '<' in memref type"))
452 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700453
454 SmallVector<int, 4> dimensions;
455 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700456 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700457
458 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700459 auto typeLoc = getToken().getLoc();
460 auto *elementType = parseType();
Chris Lattnerf7e22732018-06-22 22:03:48 -0700461 if (!elementType)
462 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700463
Chris Lattnerc3251192018-07-27 13:09:58 -0700464 if (!isa<IntegerType>(elementType) && !isa<FloatType>(elementType) &&
465 !isa<VectorType>(elementType))
466 return (emitError(typeLoc, "invalid memref element type"), nullptr);
467
MLIR Team718c82f2018-07-16 09:45:22 -0700468 // Parse semi-affine-map-composition.
James Molloy0ff71542018-07-23 16:56:32 -0700469 SmallVector<AffineMap *, 2> affineMapComposition;
Chris Lattner413db6a2018-07-25 12:55:50 -0700470 unsigned memorySpace = 0;
MLIR Team718c82f2018-07-16 09:45:22 -0700471 bool parsedMemorySpace = false;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700472
MLIR Team718c82f2018-07-16 09:45:22 -0700473 auto parseElt = [&]() -> ParseResult {
474 if (getToken().is(Token::integer)) {
475 // Parse memory space.
476 if (parsedMemorySpace)
477 return emitError("multiple memory spaces specified in memref type");
478 auto v = getToken().getUnsignedIntegerValue();
479 if (!v.hasValue())
480 return emitError("invalid memory space in memref type");
481 memorySpace = v.getValue();
482 consumeToken(Token::integer);
483 parsedMemorySpace = true;
484 } else {
485 // Parse affine map.
486 if (parsedMemorySpace)
487 return emitError("affine map after memory space in memref type");
James Molloy0ff71542018-07-23 16:56:32 -0700488 auto *affineMap = parseAffineMapReference();
MLIR Team718c82f2018-07-16 09:45:22 -0700489 if (affineMap == nullptr)
490 return ParseFailure;
491 affineMapComposition.push_back(affineMap);
492 }
493 return ParseSuccess;
494 };
495
Chris Lattner413db6a2018-07-25 12:55:50 -0700496 // Parse a list of mappings and address space if present.
497 if (consumeIf(Token::comma)) {
498 // Parse comma separated list of affine maps, followed by memory space.
499 if (parseCommaSeparatedListUntil(Token::greater, parseElt,
500 /*allowEmptyList=*/false)) {
501 return nullptr;
502 }
503 } else {
504 if (parseToken(Token::greater, "expected ',' or '>' in memref type"))
505 return nullptr;
MLIR Team718c82f2018-07-16 09:45:22 -0700506 }
MLIR Team718c82f2018-07-16 09:45:22 -0700507
508 return MemRefType::get(dimensions, elementType, affineMapComposition,
509 memorySpace);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700510}
511
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700512/// Parse a function type.
513///
514/// function-type ::= type-list-parens `->` type-list
515///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700516Type *Parser::parseFunctionType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700517 assert(getToken().is(Token::l_paren));
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700518
Chris Lattnerf7702a62018-07-23 17:30:01 -0700519 SmallVector<Type *, 4> arguments, results;
520 if (parseTypeList(arguments) ||
521 parseToken(Token::arrow, "expected '->' in function type") ||
522 parseTypeList(results))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700523 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700524
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700525 return builder.getFunctionType(arguments, results);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700526}
527
Chris Lattner1604e472018-07-23 08:42:19 -0700528/// Parse a list of types without an enclosing parenthesis. The list must have
529/// at least one member.
530///
531/// type-list-no-parens ::= type (`,` type)*
532///
533ParseResult Parser::parseTypeListNoParens(SmallVectorImpl<Type *> &elements) {
534 auto parseElt = [&]() -> ParseResult {
535 auto elt = parseType();
536 elements.push_back(elt);
537 return elt ? ParseSuccess : ParseFailure;
538 };
539
540 return parseCommaSeparatedList(parseElt);
541}
542
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700543/// Parse a "type list", which is a singular type, or a parenthesized list of
544/// types.
545///
546/// type-list ::= type-list-parens | type
547/// type-list-parens ::= `(` `)`
Chris Lattner1604e472018-07-23 08:42:19 -0700548/// | `(` type-list-no-parens `)`
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700549///
James Molloy0ff71542018-07-23 16:56:32 -0700550ParseResult Parser::parseTypeList(SmallVectorImpl<Type *> &elements) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700551 auto parseElt = [&]() -> ParseResult {
552 auto elt = parseType();
553 elements.push_back(elt);
554 return elt ? ParseSuccess : ParseFailure;
555 };
556
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700557 // If there is no parens, then it must be a singular type.
558 if (!consumeIf(Token::l_paren))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700559 return parseElt();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700560
Chris Lattner40746442018-07-21 14:32:09 -0700561 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700562 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700563
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700564 return ParseSuccess;
565}
566
Chris Lattner4c95a502018-06-23 16:03:42 -0700567//===----------------------------------------------------------------------===//
Chris Lattner7121b802018-07-04 20:45:39 -0700568// Attribute parsing.
569//===----------------------------------------------------------------------===//
570
Chris Lattner7121b802018-07-04 20:45:39 -0700571/// Attribute parsing.
572///
573/// attribute-value ::= bool-literal
574/// | integer-literal
575/// | float-literal
576/// | string-literal
James Molloyf0d2f442018-08-03 01:54:46 -0700577/// | type
Chris Lattner7121b802018-07-04 20:45:39 -0700578/// | `[` (attribute-value (`,` attribute-value)*)? `]`
579///
580Attribute *Parser::parseAttribute() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700581 switch (getToken().getKind()) {
Chris Lattner7121b802018-07-04 20:45:39 -0700582 case Token::kw_true:
583 consumeToken(Token::kw_true);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700584 return builder.getBoolAttr(true);
Chris Lattner7121b802018-07-04 20:45:39 -0700585 case Token::kw_false:
586 consumeToken(Token::kw_false);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700587 return builder.getBoolAttr(false);
Chris Lattner7121b802018-07-04 20:45:39 -0700588
Jacques Pienaar84491092018-07-31 17:15:15 -0700589 case Token::floatliteral: {
590 auto val = getToken().getFloatingPointValue();
591 if (!val.hasValue())
592 return (emitError("floating point value too large for attribute"),
593 nullptr);
594 consumeToken(Token::floatliteral);
595 return builder.getFloatAttr(val.getValue());
596 }
Chris Lattner7121b802018-07-04 20:45:39 -0700597 case Token::integer: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700598 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700599 if (!val.hasValue() || (int64_t)val.getValue() < 0)
600 return (emitError("integer too large for attribute"), nullptr);
601 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700602 return builder.getIntegerAttr((int64_t)val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700603 }
604
605 case Token::minus: {
606 consumeToken(Token::minus);
Chris Lattner48af7d12018-07-09 19:05:38 -0700607 if (getToken().is(Token::integer)) {
608 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700609 if (!val.hasValue() || (int64_t)-val.getValue() >= 0)
610 return (emitError("integer too large for attribute"), nullptr);
611 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700612 return builder.getIntegerAttr((int64_t)-val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700613 }
Jacques Pienaar84491092018-07-31 17:15:15 -0700614 if (getToken().is(Token::floatliteral)) {
615 auto val = getToken().getFloatingPointValue();
616 if (!val.hasValue())
617 return (emitError("floating point value too large for attribute"),
618 nullptr);
619 consumeToken(Token::floatliteral);
620 return builder.getFloatAttr(-val.getValue());
621 }
Chris Lattner7121b802018-07-04 20:45:39 -0700622
623 return (emitError("expected constant integer or floating point value"),
624 nullptr);
625 }
626
627 case Token::string: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700628 auto val = getToken().getStringValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700629 consumeToken(Token::string);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700630 return builder.getStringAttr(val);
Chris Lattner7121b802018-07-04 20:45:39 -0700631 }
632
Chris Lattner85ee1512018-07-25 11:15:20 -0700633 case Token::l_square: {
634 consumeToken(Token::l_square);
James Molloy0ff71542018-07-23 16:56:32 -0700635 SmallVector<Attribute *, 4> elements;
Chris Lattner7121b802018-07-04 20:45:39 -0700636
637 auto parseElt = [&]() -> ParseResult {
638 elements.push_back(parseAttribute());
639 return elements.back() ? ParseSuccess : ParseFailure;
640 };
641
Chris Lattner85ee1512018-07-25 11:15:20 -0700642 if (parseCommaSeparatedListUntil(Token::r_square, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700643 return nullptr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700644 return builder.getArrayAttr(elements);
Chris Lattner7121b802018-07-04 20:45:39 -0700645 }
James Molloyf0d2f442018-08-03 01:54:46 -0700646 case Token::hash_identifier:
647 case Token::l_paren: {
MLIR Teamb61885d2018-07-18 16:29:21 -0700648 // Try to parse affine map reference.
James Molloyf0d2f442018-08-03 01:54:46 -0700649 if (auto *affineMap = parseAffineMapReference())
MLIR Teamb61885d2018-07-18 16:29:21 -0700650 return builder.getAffineMapAttr(affineMap);
Chris Lattner7121b802018-07-04 20:45:39 -0700651 return (emitError("expected constant attribute value"), nullptr);
652 }
James Molloyf0d2f442018-08-03 01:54:46 -0700653 default: {
654 if (Type *type = parseType())
655 return builder.getTypeAttr(type);
656 return nullptr;
657 }
658 }
Chris Lattner7121b802018-07-04 20:45:39 -0700659}
660
Chris Lattner7121b802018-07-04 20:45:39 -0700661/// Attribute dictionary.
662///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700663/// attribute-dict ::= `{` `}`
664/// | `{` attribute-entry (`,` attribute-entry)* `}`
665/// attribute-entry ::= bare-id `:` attribute-value
Chris Lattner7121b802018-07-04 20:45:39 -0700666///
James Molloy0ff71542018-07-23 16:56:32 -0700667ParseResult
668Parser::parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes) {
Chris Lattner7121b802018-07-04 20:45:39 -0700669 consumeToken(Token::l_brace);
670
671 auto parseElt = [&]() -> ParseResult {
672 // We allow keywords as attribute names.
Chris Lattner48af7d12018-07-09 19:05:38 -0700673 if (getToken().isNot(Token::bare_identifier, Token::inttype) &&
674 !getToken().isKeyword())
Chris Lattner7121b802018-07-04 20:45:39 -0700675 return emitError("expected attribute name");
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700676 auto nameId = builder.getIdentifier(getTokenSpelling());
Chris Lattner7121b802018-07-04 20:45:39 -0700677 consumeToken();
678
Chris Lattnerf7702a62018-07-23 17:30:01 -0700679 if (parseToken(Token::colon, "expected ':' in attribute list"))
680 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700681
682 auto attr = parseAttribute();
James Molloy0ff71542018-07-23 16:56:32 -0700683 if (!attr)
684 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700685
686 attributes.push_back({nameId, attr});
687 return ParseSuccess;
688 };
689
Chris Lattner40746442018-07-21 14:32:09 -0700690 if (parseCommaSeparatedListUntil(Token::r_brace, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700691 return ParseFailure;
692
693 return ParseSuccess;
694}
695
696//===----------------------------------------------------------------------===//
MLIR Teamf85a6262018-06-27 11:03:08 -0700697// Polyhedral structures.
698//===----------------------------------------------------------------------===//
699
Chris Lattner2e595eb2018-07-10 10:08:27 -0700700/// Lower precedence ops (all at the same precedence level). LNoOp is false in
701/// the boolean sense.
702enum AffineLowPrecOp {
703 /// Null value.
704 LNoOp,
705 Add,
706 Sub
707};
MLIR Teamf85a6262018-06-27 11:03:08 -0700708
Chris Lattner2e595eb2018-07-10 10:08:27 -0700709/// Higher precedence ops - all at the same precedence level. HNoOp is false in
710/// the boolean sense.
711enum AffineHighPrecOp {
712 /// Null value.
713 HNoOp,
714 Mul,
715 FloorDiv,
716 CeilDiv,
717 Mod
718};
Chris Lattner7121b802018-07-04 20:45:39 -0700719
Chris Lattner2e595eb2018-07-10 10:08:27 -0700720namespace {
721/// This is a specialized parser for AffineMap's, maintaining the state
722/// transient to their bodies.
723class AffineMapParser : public Parser {
724public:
725 explicit AffineMapParser(ParserState &state) : Parser(state) {}
Chris Lattner7121b802018-07-04 20:45:39 -0700726
Chris Lattner2e595eb2018-07-10 10:08:27 -0700727 AffineMap *parseAffineMapInline();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700728
Chris Lattner2e595eb2018-07-10 10:08:27 -0700729private:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700730 // Binary affine op parsing.
731 AffineLowPrecOp consumeIfLowPrecOp();
732 AffineHighPrecOp consumeIfHighPrecOp();
MLIR Teamf85a6262018-06-27 11:03:08 -0700733
Chris Lattner2e595eb2018-07-10 10:08:27 -0700734 // Identifier lists for polyhedral structures.
Chris Lattner413db6a2018-07-25 12:55:50 -0700735 ParseResult parseDimIdList(unsigned &numDims);
736 ParseResult parseSymbolIdList(unsigned &numSymbols);
737 ParseResult parseIdentifierDefinition(AffineExpr *idExpr);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700738
739 AffineExpr *parseAffineExpr();
740 AffineExpr *parseParentheticalExpr();
741 AffineExpr *parseNegateExpression(AffineExpr *lhs);
742 AffineExpr *parseIntegerExpr();
743 AffineExpr *parseBareIdExpr();
744
745 AffineExpr *getBinaryAffineOpExpr(AffineHighPrecOp op, AffineExpr *lhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700746 AffineExpr *rhs, SMLoc opLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700747 AffineExpr *getBinaryAffineOpExpr(AffineLowPrecOp op, AffineExpr *lhs,
748 AffineExpr *rhs);
749 AffineExpr *parseAffineOperandExpr(AffineExpr *lhs);
750 AffineExpr *parseAffineLowPrecOpExpr(AffineExpr *llhs,
751 AffineLowPrecOp llhsOp);
752 AffineExpr *parseAffineHighPrecOpExpr(AffineExpr *llhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700753 AffineHighPrecOp llhsOp,
754 SMLoc llhsOpLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700755
756private:
Chris Lattner413db6a2018-07-25 12:55:50 -0700757 SmallVector<std::pair<StringRef, AffineExpr *>, 4> dimsAndSymbols;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700758};
759} // end anonymous namespace
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700760
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700761/// Create an affine binary high precedence op expression (mul's, div's, mod).
762/// opLoc is the location of the op token to be used to report errors
763/// for non-conforming expressions.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700764AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineHighPrecOp op,
765 AffineExpr *lhs,
Chris Lattner40746442018-07-21 14:32:09 -0700766 AffineExpr *rhs,
767 SMLoc opLoc) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700768 // TODO: make the error location info accurate.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700769 switch (op) {
770 case Mul:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700771 if (!lhs->isSymbolicOrConstant() && !rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700772 emitError(opLoc, "non-affine expression: at least one of the multiply "
773 "operands has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700774 return nullptr;
775 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700776 return builder.getMulExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700777 case FloorDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700778 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700779 emitError(opLoc, "non-affine expression: right operand of floordiv "
780 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700781 return nullptr;
782 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700783 return builder.getFloorDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700784 case CeilDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700785 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700786 emitError(opLoc, "non-affine expression: right operand of ceildiv "
787 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700788 return nullptr;
789 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700790 return builder.getCeilDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700791 case Mod:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700792 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700793 emitError(opLoc, "non-affine expression: right operand of mod "
794 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700795 return nullptr;
796 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700797 return builder.getModExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700798 case HNoOp:
799 llvm_unreachable("can't create affine expression for null high prec op");
800 return nullptr;
801 }
802}
803
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700804/// Create an affine binary low precedence op expression (add, sub).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700805AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineLowPrecOp op,
806 AffineExpr *lhs,
807 AffineExpr *rhs) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700808 switch (op) {
809 case AffineLowPrecOp::Add:
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700810 return builder.getAddExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700811 case AffineLowPrecOp::Sub:
Uday Bondhugulac1faf662018-07-19 14:08:50 -0700812 return builder.getAddExpr(
813 lhs, builder.getMulExpr(rhs, builder.getConstantExpr(-1)));
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700814 case AffineLowPrecOp::LNoOp:
815 llvm_unreachable("can't create affine expression for null low prec op");
816 return nullptr;
817 }
818}
819
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700820/// Consume this token if it is a lower precedence affine op (there are only two
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700821/// precedence levels).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700822AffineLowPrecOp AffineMapParser::consumeIfLowPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700823 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700824 case Token::plus:
825 consumeToken(Token::plus);
826 return AffineLowPrecOp::Add;
827 case Token::minus:
828 consumeToken(Token::minus);
829 return AffineLowPrecOp::Sub;
830 default:
831 return AffineLowPrecOp::LNoOp;
832 }
833}
834
835/// Consume this token if it is a higher precedence affine op (there are only
836/// two precedence levels)
Chris Lattner2e595eb2018-07-10 10:08:27 -0700837AffineHighPrecOp AffineMapParser::consumeIfHighPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700838 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700839 case Token::star:
840 consumeToken(Token::star);
841 return Mul;
842 case Token::kw_floordiv:
843 consumeToken(Token::kw_floordiv);
844 return FloorDiv;
845 case Token::kw_ceildiv:
846 consumeToken(Token::kw_ceildiv);
847 return CeilDiv;
848 case Token::kw_mod:
849 consumeToken(Token::kw_mod);
850 return Mod;
851 default:
852 return HNoOp;
853 }
854}
855
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700856/// Parse a high precedence op expression list: mul, div, and mod are high
857/// precedence binary ops, i.e., parse a
858/// expr_1 op_1 expr_2 op_2 ... expr_n
859/// where op_1, op_2 are all a AffineHighPrecOp (mul, div, mod).
860/// All affine binary ops are left associative.
861/// Given llhs, returns (llhs llhsOp lhs) op rhs, or (lhs op rhs) if llhs is
862/// null. If no rhs can be found, returns (llhs llhsOp lhs) or lhs if llhs is
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700863/// null. llhsOpLoc is the location of the llhsOp token that will be used to
864/// report an error for non-conforming expressions.
865AffineExpr *AffineMapParser::parseAffineHighPrecOpExpr(AffineExpr *llhs,
866 AffineHighPrecOp llhsOp,
867 SMLoc llhsOpLoc) {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700868 AffineExpr *lhs = parseAffineOperandExpr(llhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700869 if (!lhs)
870 return nullptr;
871
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700872 // Found an LHS. Parse the remaining expression.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700873 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -0700874 if (AffineHighPrecOp op = consumeIfHighPrecOp()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700875 if (llhs) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700876 AffineExpr *expr = getBinaryAffineOpExpr(llhsOp, llhs, lhs, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700877 if (!expr)
878 return nullptr;
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700879 return parseAffineHighPrecOpExpr(expr, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700880 }
881 // No LLHS, get RHS
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700882 return parseAffineHighPrecOpExpr(lhs, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700883 }
884
885 // This is the last operand in this expression.
886 if (llhs)
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700887 return getBinaryAffineOpExpr(llhsOp, llhs, lhs, llhsOpLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700888
889 // No llhs, 'lhs' itself is the expression.
890 return lhs;
891}
892
893/// Parse an affine expression inside parentheses.
894///
895/// affine-expr ::= `(` affine-expr `)`
Chris Lattner2e595eb2018-07-10 10:08:27 -0700896AffineExpr *AffineMapParser::parseParentheticalExpr() {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700897 if (parseToken(Token::l_paren, "expected '('"))
898 return nullptr;
Chris Lattner48af7d12018-07-09 19:05:38 -0700899 if (getToken().is(Token::r_paren))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700900 return (emitError("no expression inside parentheses"), nullptr);
Chris Lattnerf7702a62018-07-23 17:30:01 -0700901
Chris Lattner2e595eb2018-07-10 10:08:27 -0700902 auto *expr = parseAffineExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700903 if (!expr)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700904 return nullptr;
Chris Lattnerf7702a62018-07-23 17:30:01 -0700905 if (parseToken(Token::r_paren, "expected ')'"))
906 return nullptr;
907
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700908 return expr;
909}
910
911/// Parse the negation expression.
912///
913/// affine-expr ::= `-` affine-expr
Chris Lattner2e595eb2018-07-10 10:08:27 -0700914AffineExpr *AffineMapParser::parseNegateExpression(AffineExpr *lhs) {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700915 if (parseToken(Token::minus, "expected '-'"))
916 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700917
Chris Lattner2e595eb2018-07-10 10:08:27 -0700918 AffineExpr *operand = parseAffineOperandExpr(lhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700919 // Since negation has the highest precedence of all ops (including high
920 // precedence ops) but lower than parentheses, we are only going to use
921 // parseAffineOperandExpr instead of parseAffineExpr here.
922 if (!operand)
923 // Extra error message although parseAffineOperandExpr would have
924 // complained. Leads to a better diagnostic.
925 return (emitError("missing operand of negation"), nullptr);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700926 auto *minusOne = builder.getConstantExpr(-1);
927 return builder.getMulExpr(minusOne, operand);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700928}
929
930/// Parse a bare id that may appear in an affine expression.
931///
932/// affine-expr ::= bare-id
Chris Lattner2e595eb2018-07-10 10:08:27 -0700933AffineExpr *AffineMapParser::parseBareIdExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700934 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700935 return (emitError("expected bare identifier"), nullptr);
936
Chris Lattner48af7d12018-07-09 19:05:38 -0700937 StringRef sRef = getTokenSpelling();
Chris Lattner413db6a2018-07-25 12:55:50 -0700938 for (auto entry : dimsAndSymbols) {
Chris Lattnera8e47672018-07-25 14:08:16 -0700939 if (entry.first == sRef) {
940 consumeToken(Token::bare_identifier);
941 return entry.second;
942 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700943 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700944
945 return (emitError("use of undeclared identifier"), nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700946}
947
948/// Parse a positive integral constant appearing in an affine expression.
949///
950/// affine-expr ::= integer-literal
Chris Lattner2e595eb2018-07-10 10:08:27 -0700951AffineExpr *AffineMapParser::parseIntegerExpr() {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700952 // No need to handle negative numbers separately here. They are naturally
953 // handled via the unary negation operator, although (FIXME) MININT_64 still
954 // not correctly handled.
Chris Lattner48af7d12018-07-09 19:05:38 -0700955 if (getToken().isNot(Token::integer))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700956 return (emitError("expected integer"), nullptr);
957
Chris Lattner48af7d12018-07-09 19:05:38 -0700958 auto val = getToken().getUInt64IntegerValue();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700959 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
960 return (emitError("constant too large for affineint"), nullptr);
961 }
962 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700963 return builder.getConstantExpr((int64_t)val.getValue());
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700964}
965
966/// Parses an expression that can be a valid operand of an affine expression.
Uday Bondhugula76345202018-07-09 13:47:52 -0700967/// lhs: if non-null, lhs is an affine expression that is the lhs of a binary
968/// operator, the rhs of which is being parsed. This is used to determine
969/// whether an error should be emitted for a missing right operand.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700970// Eg: for an expression without parentheses (like i + j + k + l), each
971// of the four identifiers is an operand. For i + j*k + l, j*k is not an
972// operand expression, it's an op expression and will be parsed via
973// parseAffineHighPrecOpExpression(). However, for i + (j*k) + -l, (j*k) and -l
974// are valid operands that will be parsed by this function.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700975AffineExpr *AffineMapParser::parseAffineOperandExpr(AffineExpr *lhs) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700976 switch (getToken().getKind()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700977 case Token::bare_identifier:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700978 return parseBareIdExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700979 case Token::integer:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700980 return parseIntegerExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700981 case Token::l_paren:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700982 return parseParentheticalExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700983 case Token::minus:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700984 return parseNegateExpression(lhs);
Uday Bondhugula76345202018-07-09 13:47:52 -0700985 case Token::kw_ceildiv:
986 case Token::kw_floordiv:
987 case Token::kw_mod:
988 case Token::plus:
989 case Token::star:
990 if (lhs)
991 emitError("missing right operand of binary operator");
992 else
993 emitError("missing left operand of binary operator");
994 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700995 default:
996 if (lhs)
Uday Bondhugula76345202018-07-09 13:47:52 -0700997 emitError("missing right operand of binary operator");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700998 else
999 emitError("expected affine expression");
1000 return nullptr;
1001 }
1002}
1003
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001004/// Parse affine expressions that are bare-id's, integer constants,
1005/// parenthetical affine expressions, and affine op expressions that are a
1006/// composition of those.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001007///
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001008/// All binary op's associate from left to right.
1009///
1010/// {add, sub} have lower precedence than {mul, div, and mod}.
1011///
Uday Bondhugula76345202018-07-09 13:47:52 -07001012/// Add, sub'are themselves at the same precedence level. Mul, floordiv,
1013/// ceildiv, and mod are at the same higher precedence level. Negation has
1014/// higher precedence than any binary op.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001015///
1016/// llhs: the affine expression appearing on the left of the one being parsed.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001017/// This function will return ((llhs llhsOp lhs) op rhs) if llhs is non null,
1018/// and lhs op rhs otherwise; if there is no rhs, llhs llhsOp lhs is returned if
1019/// llhs is non-null; otherwise lhs is returned. This is to deal with left
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001020/// associativity.
1021///
1022/// Eg: when the expression is e1 + e2*e3 + e4, with e1 as llhs, this function
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001023/// will return the affine expr equivalent of (e1 + (e2*e3)) + e4, where (e2*e3)
1024/// will be parsed using parseAffineHighPrecOpExpr().
Chris Lattner2e595eb2018-07-10 10:08:27 -07001025AffineExpr *AffineMapParser::parseAffineLowPrecOpExpr(AffineExpr *llhs,
1026 AffineLowPrecOp llhsOp) {
Uday Bondhugula76345202018-07-09 13:47:52 -07001027 AffineExpr *lhs;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001028 if (!(lhs = parseAffineOperandExpr(llhs)))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001029 return nullptr;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001030
1031 // Found an LHS. Deal with the ops.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001032 if (AffineLowPrecOp lOp = consumeIfLowPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001033 if (llhs) {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001034 AffineExpr *sum = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001035 return parseAffineLowPrecOpExpr(sum, lOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001036 }
1037 // No LLHS, get RHS and form the expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001038 return parseAffineLowPrecOpExpr(lhs, lOp);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001039 }
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001040 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07001041 if (AffineHighPrecOp hOp = consumeIfHighPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001042 // We have a higher precedence op here. Get the rhs operand for the llhs
1043 // through parseAffineHighPrecOpExpr.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001044 AffineExpr *highRes = parseAffineHighPrecOpExpr(lhs, hOp, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001045 if (!highRes)
1046 return nullptr;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001047
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001048 // If llhs is null, the product forms the first operand of the yet to be
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001049 // found expression. If non-null, the op to associate with llhs is llhsOp.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001050 AffineExpr *expr =
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001051 llhs ? getBinaryAffineOpExpr(llhsOp, llhs, highRes) : highRes;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001052
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001053 // Recurse for subsequent low prec op's after the affine high prec op
1054 // expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001055 if (AffineLowPrecOp nextOp = consumeIfLowPrecOp())
1056 return parseAffineLowPrecOpExpr(expr, nextOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001057 return expr;
1058 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001059 // Last operand in the expression list.
1060 if (llhs)
1061 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
1062 // No llhs, 'lhs' itself is the expression.
1063 return lhs;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001064}
1065
1066/// Parse an affine expression.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001067/// affine-expr ::= `(` affine-expr `)`
1068/// | `-` affine-expr
1069/// | affine-expr `+` affine-expr
1070/// | affine-expr `-` affine-expr
1071/// | affine-expr `*` affine-expr
1072/// | affine-expr `floordiv` affine-expr
1073/// | affine-expr `ceildiv` affine-expr
1074/// | affine-expr `mod` affine-expr
1075/// | bare-id
1076/// | integer-literal
1077///
1078/// Additional conditions are checked depending on the production. For eg., one
1079/// of the operands for `*` has to be either constant/symbolic; the second
1080/// operand for floordiv, ceildiv, and mod has to be a positive integer.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001081AffineExpr *AffineMapParser::parseAffineExpr() {
1082 return parseAffineLowPrecOpExpr(nullptr, AffineLowPrecOp::LNoOp);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001083}
1084
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001085/// Parse a dim or symbol from the lists appearing before the actual expressions
Chris Lattner2e595eb2018-07-10 10:08:27 -07001086/// of the affine map. Update our state to store the dimensional/symbolic
Chris Lattner413db6a2018-07-25 12:55:50 -07001087/// identifier.
1088ParseResult AffineMapParser::parseIdentifierDefinition(AffineExpr *idExpr) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001089 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001090 return emitError("expected bare identifier");
Chris Lattner413db6a2018-07-25 12:55:50 -07001091
1092 auto name = getTokenSpelling();
1093 for (auto entry : dimsAndSymbols) {
1094 if (entry.first == name)
1095 return emitError("redefinition of identifier '" + Twine(name) + "'");
1096 }
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001097 consumeToken(Token::bare_identifier);
Chris Lattner413db6a2018-07-25 12:55:50 -07001098
1099 dimsAndSymbols.push_back({name, idExpr});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001100 return ParseSuccess;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001101}
1102
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001103/// Parse the list of symbolic identifiers to an affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001104ParseResult AffineMapParser::parseSymbolIdList(unsigned &numSymbols) {
1105 consumeToken(Token::l_square);
1106 auto parseElt = [&]() -> ParseResult {
1107 auto *symbol = AffineSymbolExpr::get(numSymbols++, getContext());
1108 return parseIdentifierDefinition(symbol);
1109 };
Chris Lattner85ee1512018-07-25 11:15:20 -07001110 return parseCommaSeparatedListUntil(Token::r_square, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001111}
1112
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001113/// Parse the list of dimensional identifiers to an affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001114ParseResult AffineMapParser::parseDimIdList(unsigned &numDims) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07001115 if (parseToken(Token::l_paren,
1116 "expected '(' at start of dimensional identifiers list"))
1117 return ParseFailure;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001118
Chris Lattner413db6a2018-07-25 12:55:50 -07001119 auto parseElt = [&]() -> ParseResult {
1120 auto *dimension = AffineDimExpr::get(numDims++, getContext());
1121 return parseIdentifierDefinition(dimension);
1122 };
Chris Lattner40746442018-07-21 14:32:09 -07001123 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001124}
1125
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001126/// Parse an affine map definition.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001127///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001128/// affine-map-inline ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
1129/// (`size` `(` dim-size (`,` dim-size)* `)`)?
1130/// dim-size ::= affine-expr | `min` `(` affine-expr ( `,` affine-expr)+ `)`
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001131///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001132/// multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner2e595eb2018-07-10 10:08:27 -07001133AffineMap *AffineMapParser::parseAffineMapInline() {
Chris Lattner413db6a2018-07-25 12:55:50 -07001134 unsigned numDims = 0, numSymbols = 0;
1135
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001136 // List of dimensional identifiers.
Chris Lattner413db6a2018-07-25 12:55:50 -07001137 if (parseDimIdList(numDims))
Chris Lattner7121b802018-07-04 20:45:39 -07001138 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001139
1140 // Symbols are optional.
Chris Lattner85ee1512018-07-25 11:15:20 -07001141 if (getToken().is(Token::l_square)) {
Chris Lattner413db6a2018-07-25 12:55:50 -07001142 if (parseSymbolIdList(numSymbols))
Chris Lattner7121b802018-07-04 20:45:39 -07001143 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001144 }
Chris Lattnerf7702a62018-07-23 17:30:01 -07001145
1146 if (parseToken(Token::arrow, "expected '->' or '['") ||
1147 parseToken(Token::l_paren, "expected '(' at start of affine map range"))
Chris Lattner7121b802018-07-04 20:45:39 -07001148 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001149
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001150 SmallVector<AffineExpr *, 4> exprs;
1151 auto parseElt = [&]() -> ParseResult {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001152 auto *elt = parseAffineExpr();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001153 ParseResult res = elt ? ParseSuccess : ParseFailure;
1154 exprs.push_back(elt);
1155 return res;
1156 };
1157
1158 // Parse a multi-dimensional affine expression (a comma-separated list of 1-d
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001159 // affine expressions); the list cannot be empty.
1160 // Grammar: multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner40746442018-07-21 14:32:09 -07001161 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt, false))
Chris Lattner7121b802018-07-04 20:45:39 -07001162 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001163
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001164 // Parse optional range sizes.
Uday Bondhugula1e500b42018-07-12 18:04:04 -07001165 // range-sizes ::= (`size` `(` dim-size (`,` dim-size)* `)`)?
1166 // dim-size ::= affine-expr | `min` `(` affine-expr (`,` affine-expr)+ `)`
1167 // TODO(bondhugula): support for min of several affine expressions.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001168 // TODO: check if sizes are non-negative whenever they are constant.
1169 SmallVector<AffineExpr *, 4> rangeSizes;
1170 if (consumeIf(Token::kw_size)) {
1171 // Location of the l_paren token (if it exists) for error reporting later.
1172 auto loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001173 if (parseToken(Token::l_paren, "expected '(' at start of affine map range"))
1174 return nullptr;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001175
1176 auto parseRangeSize = [&]() -> ParseResult {
Chris Lattner413db6a2018-07-25 12:55:50 -07001177 auto loc = getToken().getLoc();
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001178 auto *elt = parseAffineExpr();
Chris Lattner413db6a2018-07-25 12:55:50 -07001179 if (!elt)
1180 return ParseFailure;
1181
1182 if (!elt->isSymbolicOrConstant())
1183 return emitError(loc,
1184 "size expressions cannot refer to dimension values");
1185
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001186 rangeSizes.push_back(elt);
Chris Lattner413db6a2018-07-25 12:55:50 -07001187 return ParseSuccess;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001188 };
1189
Chris Lattner40746442018-07-21 14:32:09 -07001190 if (parseCommaSeparatedListUntil(Token::r_paren, parseRangeSize, false))
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001191 return nullptr;
1192 if (exprs.size() > rangeSizes.size())
1193 return (emitError(loc, "fewer range sizes than range expressions"),
1194 nullptr);
1195 if (exprs.size() < rangeSizes.size())
1196 return (emitError(loc, "more range sizes than range expressions"),
1197 nullptr);
1198 }
1199
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001200 // Parsed a valid affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001201 return builder.getAffineMap(numDims, numSymbols, exprs, rangeSizes);
MLIR Teamf85a6262018-06-27 11:03:08 -07001202}
1203
Chris Lattner2e595eb2018-07-10 10:08:27 -07001204AffineMap *Parser::parseAffineMapInline() {
1205 return AffineMapParser(state).parseAffineMapInline();
1206}
1207
MLIR Team718c82f2018-07-16 09:45:22 -07001208AffineMap *Parser::parseAffineMapReference() {
1209 if (getToken().is(Token::hash_identifier)) {
1210 // Parse affine map identifier and verify that it exists.
1211 StringRef affineMapId = getTokenSpelling().drop_front();
1212 if (getState().affineMapDefinitions.count(affineMapId) == 0)
1213 return (emitError("undefined affine map id '" + affineMapId + "'"),
1214 nullptr);
1215 consumeToken(Token::hash_identifier);
1216 return getState().affineMapDefinitions[affineMapId];
1217 }
1218 // Try to parse inline affine map.
1219 return parseAffineMapInline();
1220}
1221
MLIR Teamf85a6262018-06-27 11:03:08 -07001222//===----------------------------------------------------------------------===//
Chris Lattner7f9cc272018-07-19 08:35:28 -07001223// FunctionParser
Chris Lattner4c95a502018-06-23 16:03:42 -07001224//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001225
Chris Lattner7f9cc272018-07-19 08:35:28 -07001226namespace {
1227/// This class contains parser state that is common across CFG and ML functions,
1228/// notably for dealing with operations and SSA values.
1229class FunctionParser : public Parser {
1230public:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001231 enum class Kind { CFGFunc, MLFunc };
1232
1233 Kind getKind() const { return kind; }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001234
Chris Lattner6119d382018-07-20 18:41:34 -07001235 /// After the function is finished parsing, this function checks to see if
1236 /// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001237 ParseResult finalizeFunction(Function *func, SMLoc loc);
Chris Lattner6119d382018-07-20 18:41:34 -07001238
1239 /// This represents a use of an SSA value in the program. The first two
1240 /// entries in the tuple are the name and result number of a reference. The
1241 /// third is the location of the reference, which is used in case this ends up
1242 /// being a use of an undefined value.
1243 struct SSAUseInfo {
1244 StringRef name; // Value name, e.g. %42 or %abc
1245 unsigned number; // Number, specified with #12
1246 SMLoc loc; // Location of first definition or use.
1247 };
Chris Lattner7f9cc272018-07-19 08:35:28 -07001248
1249 /// Given a reference to an SSA value and its type, return a reference. This
1250 /// returns null on failure.
1251 SSAValue *resolveSSAUse(SSAUseInfo useInfo, Type *type);
1252
1253 /// Register a definition of a value with the symbol table.
1254 ParseResult addDefinition(SSAUseInfo useInfo, SSAValue *value);
1255
1256 // SSA parsing productions.
1257 ParseResult parseSSAUse(SSAUseInfo &result);
Chris Lattner40746442018-07-21 14:32:09 -07001258 ParseResult parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results);
James Molloy61a656c2018-07-22 15:45:24 -07001259
1260 template <typename ResultType>
1261 ResultType parseSSADefOrUseAndType(
1262 const std::function<ResultType(SSAUseInfo, Type *)> &action);
1263
1264 SSAValue *parseSSAUseAndType() {
1265 return parseSSADefOrUseAndType<SSAValue *>(
1266 [&](SSAUseInfo useInfo, Type *type) -> SSAValue * {
1267 return resolveSSAUse(useInfo, type);
1268 });
1269 }
Chris Lattner40746442018-07-21 14:32:09 -07001270
1271 template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001272 ParseResult
Chris Lattner2c402672018-07-23 11:56:17 -07001273 parseOptionalSSAUseAndTypeList(SmallVectorImpl<ValueTy *> &results,
1274 bool isParenthesized);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001275
1276 // Operations
1277 ParseResult parseOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner85ee1512018-07-25 11:15:20 -07001278 Operation *parseVerboseOperation(const CreateOperationFunction &createOpFunc);
1279 Operation *parseCustomOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001280
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001281protected:
1282 FunctionParser(ParserState &state, Kind kind) : Parser(state), kind(kind) {}
1283
Chris Lattner7f9cc272018-07-19 08:35:28 -07001284private:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001285 /// Kind indicates if this is CFG or ML function parser.
1286 Kind kind;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001287 /// This keeps track of all of the SSA values we are tracking, indexed by
Chris Lattner6119d382018-07-20 18:41:34 -07001288 /// their name. This has one entry per result number.
1289 llvm::StringMap<SmallVector<std::pair<SSAValue *, SMLoc>, 1>> values;
1290
1291 /// These are all of the placeholders we've made along with the location of
1292 /// their first reference, to allow checking for use of undefined values.
1293 DenseMap<SSAValue *, SMLoc> forwardReferencePlaceholders;
1294
1295 SSAValue *createForwardReferencePlaceholder(SMLoc loc, Type *type);
1296
1297 /// Return true if this is a forward reference.
1298 bool isForwardReferencePlaceholder(SSAValue *value) {
1299 return forwardReferencePlaceholders.count(value);
1300 }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001301};
1302} // end anonymous namespace
1303
Chris Lattner6119d382018-07-20 18:41:34 -07001304/// Create and remember a new placeholder for a forward reference.
1305SSAValue *FunctionParser::createForwardReferencePlaceholder(SMLoc loc,
1306 Type *type) {
1307 // Forward references are always created as instructions, even in ML
1308 // functions, because we just need something with a def/use chain.
1309 //
1310 // We create these placeholders as having an empty name, which we know cannot
1311 // be created through normal user input, allowing us to distinguish them.
1312 auto name = Identifier::get("placeholder", getContext());
1313 auto *inst = OperationInst::create(name, /*operands*/ {}, type, /*attrs*/ {},
1314 getContext());
1315 forwardReferencePlaceholders[inst->getResult(0)] = loc;
1316 return inst->getResult(0);
1317}
1318
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001319/// Given an unbound reference to an SSA value and its type, return the value
Chris Lattner7f9cc272018-07-19 08:35:28 -07001320/// it specifies. This returns null on failure.
1321SSAValue *FunctionParser::resolveSSAUse(SSAUseInfo useInfo, Type *type) {
Chris Lattner6119d382018-07-20 18:41:34 -07001322 auto &entries = values[useInfo.name];
1323
Chris Lattner7f9cc272018-07-19 08:35:28 -07001324 // If we have already seen a value of this name, return it.
Chris Lattner6119d382018-07-20 18:41:34 -07001325 if (useInfo.number < entries.size() && entries[useInfo.number].first) {
1326 auto *result = entries[useInfo.number].first;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001327 // Check that the type matches the other uses.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001328 if (result->getType() == type)
1329 return result;
1330
Chris Lattner6119d382018-07-20 18:41:34 -07001331 emitError(useInfo.loc, "use of value '" + useInfo.name.str() +
1332 "' expects different type than prior uses");
1333 emitError(entries[useInfo.number].second, "prior use here");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001334 return nullptr;
1335 }
1336
Chris Lattner6119d382018-07-20 18:41:34 -07001337 // Make sure we have enough slots for this.
1338 if (entries.size() <= useInfo.number)
1339 entries.resize(useInfo.number + 1);
1340
1341 // If the value has already been defined and this is an overly large result
1342 // number, diagnose that.
1343 if (entries[0].first && !isForwardReferencePlaceholder(entries[0].first))
1344 return (emitError(useInfo.loc, "reference to invalid result number"),
1345 nullptr);
1346
Tatiana Shpeismand880b352018-07-31 23:14:16 -07001347 // Otherwise, this is a forward reference. If we are in ML function return
1348 // an error. In CFG function, create a placeholder and remember
1349 // that we did so.
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001350 if (getKind() == Kind::MLFunc)
1351 return (
1352 emitError(useInfo.loc, "use of undefined SSA value " + useInfo.name),
1353 nullptr);
1354
Chris Lattner6119d382018-07-20 18:41:34 -07001355 auto *result = createForwardReferencePlaceholder(useInfo.loc, type);
1356 entries[useInfo.number].first = result;
1357 entries[useInfo.number].second = useInfo.loc;
1358 return result;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001359}
1360
1361/// Register a definition of a value with the symbol table.
1362ParseResult FunctionParser::addDefinition(SSAUseInfo useInfo, SSAValue *value) {
Chris Lattner6119d382018-07-20 18:41:34 -07001363 auto &entries = values[useInfo.name];
Chris Lattner7f9cc272018-07-19 08:35:28 -07001364
Chris Lattner6119d382018-07-20 18:41:34 -07001365 // Make sure there is a slot for this value.
1366 if (entries.size() <= useInfo.number)
1367 entries.resize(useInfo.number + 1);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001368
Chris Lattner6119d382018-07-20 18:41:34 -07001369 // If we already have an entry for this, check to see if it was a definition
1370 // or a forward reference.
1371 if (auto *existing = entries[useInfo.number].first) {
1372 if (!isForwardReferencePlaceholder(existing)) {
1373 emitError(useInfo.loc,
1374 "redefinition of SSA value '" + useInfo.name + "'");
1375 return emitError(entries[useInfo.number].second,
1376 "previously defined here");
1377 }
1378
1379 // If it was a forward reference, update everything that used it to use the
1380 // actual definition instead, delete the forward ref, and remove it from our
1381 // set of forward references we track.
1382 existing->replaceAllUsesWith(value);
1383 existing->getDefiningInst()->destroy();
1384 forwardReferencePlaceholders.erase(existing);
1385 }
1386
1387 entries[useInfo.number].first = value;
1388 entries[useInfo.number].second = useInfo.loc;
1389 return ParseSuccess;
1390}
1391
1392/// After the function is finished parsing, this function checks to see if
1393/// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001394ParseResult FunctionParser::finalizeFunction(Function *func, SMLoc loc) {
Chris Lattner6119d382018-07-20 18:41:34 -07001395 // Check for any forward references that are left. If we find any, error out.
1396 if (!forwardReferencePlaceholders.empty()) {
1397 SmallVector<std::pair<const char *, SSAValue *>, 4> errors;
1398 // Iteration over the map isn't determinstic, so sort by source location.
1399 for (auto entry : forwardReferencePlaceholders)
1400 errors.push_back({entry.second.getPointer(), entry.first});
1401 llvm::array_pod_sort(errors.begin(), errors.end());
1402
1403 for (auto entry : errors)
1404 emitError(SMLoc::getFromPointer(entry.first),
1405 "use of undeclared SSA value name");
1406 return ParseFailure;
1407 }
1408
Chris Lattner40746442018-07-21 14:32:09 -07001409 // Run the verifier on this function. If an error is detected, report it.
1410 std::string errorString;
1411 if (func->verify(&errorString))
1412 return emitError(loc, errorString);
1413
Chris Lattner6119d382018-07-20 18:41:34 -07001414 return ParseSuccess;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001415}
1416
Chris Lattner78276e32018-07-07 15:48:26 -07001417/// Parse a SSA operand for an instruction or statement.
1418///
James Molloy61a656c2018-07-22 15:45:24 -07001419/// ssa-use ::= ssa-id
Chris Lattner78276e32018-07-07 15:48:26 -07001420///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001421ParseResult FunctionParser::parseSSAUse(SSAUseInfo &result) {
Chris Lattner6119d382018-07-20 18:41:34 -07001422 result.name = getTokenSpelling();
1423 result.number = 0;
1424 result.loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001425 if (parseToken(Token::percent_identifier, "expected SSA operand"))
1426 return ParseFailure;
Chris Lattner6119d382018-07-20 18:41:34 -07001427
1428 // If we have an affine map ID, it is a result number.
1429 if (getToken().is(Token::hash_identifier)) {
1430 if (auto value = getToken().getHashIdentifierNumber())
1431 result.number = value.getValue();
1432 else
1433 return emitError("invalid SSA value result number");
1434 consumeToken(Token::hash_identifier);
1435 }
1436
Chris Lattner7f9cc272018-07-19 08:35:28 -07001437 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001438}
1439
1440/// Parse a (possibly empty) list of SSA operands.
1441///
1442/// ssa-use-list ::= ssa-use (`,` ssa-use)*
1443/// ssa-use-list-opt ::= ssa-use-list?
1444///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001445ParseResult
Chris Lattner40746442018-07-21 14:32:09 -07001446FunctionParser::parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results) {
Chris Lattner85ee1512018-07-25 11:15:20 -07001447 if (getToken().isNot(Token::percent_identifier))
Chris Lattner40746442018-07-21 14:32:09 -07001448 return ParseSuccess;
1449 return parseCommaSeparatedList([&]() -> ParseResult {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001450 SSAUseInfo result;
1451 if (parseSSAUse(result))
1452 return ParseFailure;
1453 results.push_back(result);
1454 return ParseSuccess;
1455 });
Chris Lattner78276e32018-07-07 15:48:26 -07001456}
1457
1458/// Parse an SSA use with an associated type.
1459///
1460/// ssa-use-and-type ::= ssa-use `:` type
James Molloy61a656c2018-07-22 15:45:24 -07001461template <typename ResultType>
1462ResultType FunctionParser::parseSSADefOrUseAndType(
1463 const std::function<ResultType(SSAUseInfo, Type *)> &action) {
Chris Lattner78276e32018-07-07 15:48:26 -07001464
Chris Lattnerf7702a62018-07-23 17:30:01 -07001465 SSAUseInfo useInfo;
1466 if (parseSSAUse(useInfo) ||
1467 parseToken(Token::colon, "expected ':' and type for SSA operand"))
1468 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001469
Chris Lattner7f9cc272018-07-19 08:35:28 -07001470 auto *type = parseType();
1471 if (!type)
1472 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001473
James Molloy61a656c2018-07-22 15:45:24 -07001474 return action(useInfo, type);
Chris Lattner78276e32018-07-07 15:48:26 -07001475}
1476
Chris Lattner2c402672018-07-23 11:56:17 -07001477/// Parse a (possibly empty) list of SSA operands, followed by a colon, then
1478/// followed by a type list. If hasParens is true, then the operands are
1479/// surrounded by parens.
Chris Lattner78276e32018-07-07 15:48:26 -07001480///
Chris Lattner2c402672018-07-23 11:56:17 -07001481/// ssa-use-and-type-list[parens]
1482/// ::= `(` ssa-use-list `)` ':' type-list-no-parens
1483///
1484/// ssa-use-and-type-list[!parens]
1485/// ::= ssa-use-list ':' type-list-no-parens
Chris Lattner78276e32018-07-07 15:48:26 -07001486///
Chris Lattner40746442018-07-21 14:32:09 -07001487template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001488ParseResult FunctionParser::parseOptionalSSAUseAndTypeList(
Chris Lattner2c402672018-07-23 11:56:17 -07001489 SmallVectorImpl<ValueTy *> &results, bool isParenthesized) {
1490
1491 // If we are in the parenthesized form and no paren exists, then we succeed
1492 // with an empty list.
1493 if (isParenthesized && !consumeIf(Token::l_paren))
Chris Lattner40746442018-07-21 14:32:09 -07001494 return ParseSuccess;
1495
Chris Lattner2c402672018-07-23 11:56:17 -07001496 SmallVector<SSAUseInfo, 4> valueIDs;
1497 if (parseOptionalSSAUseList(valueIDs))
Chris Lattner7f9cc272018-07-19 08:35:28 -07001498 return ParseFailure;
Chris Lattner2c402672018-07-23 11:56:17 -07001499
1500 if (isParenthesized && !consumeIf(Token::r_paren))
1501 return emitError("expected ')' in operand list");
1502
1503 // If there were no operands, then there is no colon or type lists.
1504 if (valueIDs.empty())
1505 return ParseSuccess;
1506
Chris Lattner2c402672018-07-23 11:56:17 -07001507 SmallVector<Type *, 4> types;
Chris Lattnerf7702a62018-07-23 17:30:01 -07001508 if (parseToken(Token::colon, "expected ':' in operand list") ||
1509 parseTypeListNoParens(types))
Chris Lattner2c402672018-07-23 11:56:17 -07001510 return ParseFailure;
1511
1512 if (valueIDs.size() != types.size())
1513 return emitError("expected " + Twine(valueIDs.size()) +
1514 " types to match operand list");
1515
1516 results.reserve(valueIDs.size());
1517 for (unsigned i = 0, e = valueIDs.size(); i != e; ++i) {
1518 if (auto *value = resolveSSAUse(valueIDs[i], types[i]))
1519 results.push_back(cast<ValueTy>(value));
1520 else
1521 return ParseFailure;
1522 }
1523
1524 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001525}
1526
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001527/// Parse the CFG or MLFunc operation.
1528///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001529/// operation ::=
1530/// (ssa-id `=`)? string '(' ssa-use-list? ')' attribute-dict?
1531/// `:` function-type
1532///
1533ParseResult
Chris Lattner7f9cc272018-07-19 08:35:28 -07001534FunctionParser::parseOperation(const CreateOperationFunction &createOpFunc) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001535 auto loc = getToken().getLoc();
1536
1537 StringRef resultID;
1538 if (getToken().is(Token::percent_identifier)) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001539 resultID = getTokenSpelling();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001540 consumeToken(Token::percent_identifier);
Chris Lattnerf7702a62018-07-23 17:30:01 -07001541 if (parseToken(Token::equal, "expected '=' after SSA name"))
1542 return ParseFailure;
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001543 }
1544
Chris Lattner85ee1512018-07-25 11:15:20 -07001545 Operation *op;
1546 if (getToken().is(Token::bare_identifier) || getToken().isKeyword())
1547 op = parseCustomOperation(createOpFunc);
1548 else if (getToken().is(Token::string))
1549 op = parseVerboseOperation(createOpFunc);
1550 else
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001551 return emitError("expected operation name in quotes");
1552
Chris Lattner85ee1512018-07-25 11:15:20 -07001553 // If parsing of the basic operation failed, then this whole thing fails.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001554 if (!op)
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001555 return ParseFailure;
1556
Chris Lattnerf7bdf952018-08-05 21:12:29 -07001557 // Apply location information to the instruction.
1558 // TODO(clattner): make this more principled. We shouldn't overwrite existing
1559 // location info, we should use a better serialized form, and we shouldn't
1560 // be using the :location attribute. This is also pretty inefficient.
1561 {
1562 auto &sourceMgr = getSourceMgr();
1563 auto fileID = sourceMgr.FindBufferContainingLoc(loc);
1564 auto *srcBuffer = sourceMgr.getMemoryBuffer(fileID);
1565 unsigned locationEncoding = loc.getPointer() - srcBuffer->getBufferStart();
1566 op->setAttr(builder.getIdentifier(":location"),
1567 builder.getIntegerAttr(locationEncoding));
1568 }
1569
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001570 // We just parsed an operation. If it is a recognized one, verify that it
1571 // is structurally as we expect. If not, produce an error with a reasonable
1572 // source location.
Chris Lattner95865062018-08-01 10:18:59 -07001573 if (auto *opInfo = op->getAbstractOperation()) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001574 if (auto error = opInfo->verifyInvariants(op))
Chris Lattner9361fb32018-07-24 08:34:58 -07001575 return emitError(loc, Twine("'") + op->getName().str() + "' op " + error);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001576 }
1577
Chris Lattner7f9cc272018-07-19 08:35:28 -07001578 // If the instruction had a name, register it.
1579 if (!resultID.empty()) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001580 if (op->getNumResults() == 0)
1581 return emitError(loc, "cannot name an operation with no results");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001582
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001583 for (unsigned i = 0, e = op->getNumResults(); i != e; ++i)
Chris Lattner2b97d502018-08-06 14:19:46 -07001584 if (addDefinition({resultID, i, loc}, op->getResult(i)))
1585 return ParseFailure;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001586 }
1587
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001588 return ParseSuccess;
1589}
Chris Lattnere79379a2018-06-22 10:39:19 -07001590
Chris Lattner85ee1512018-07-25 11:15:20 -07001591Operation *FunctionParser::parseVerboseOperation(
1592 const CreateOperationFunction &createOpFunc) {
1593 auto name = getToken().getStringValue();
1594 if (name.empty())
1595 return (emitError("empty operation name is invalid"), nullptr);
1596
1597 consumeToken(Token::string);
1598
1599 // Parse the operand list.
1600 SmallVector<SSAUseInfo, 8> operandInfos;
1601
1602 if (parseToken(Token::l_paren, "expected '(' to start operand list") ||
1603 parseOptionalSSAUseList(operandInfos) ||
1604 parseToken(Token::r_paren, "expected ')' to end operand list")) {
1605 return nullptr;
1606 }
1607
1608 SmallVector<NamedAttribute, 4> attributes;
1609 if (getToken().is(Token::l_brace)) {
1610 if (parseAttributeDict(attributes))
1611 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
1625 // Check that we have the right number of types for the operands.
1626 auto operandTypes = fnType->getInputs();
1627 if (operandTypes.size() != operandInfos.size()) {
1628 auto plural = "s"[operandInfos.size() == 1];
1629 return (emitError(typeLoc, "expected " + llvm::utostr(operandInfos.size()) +
1630 " operand type" + plural + " but had " +
1631 llvm::utostr(operandTypes.size())),
1632 nullptr);
1633 }
1634
1635 // Resolve all of the operands.
1636 SmallVector<SSAValue *, 8> operands;
1637 for (unsigned i = 0, e = operandInfos.size(); i != e; ++i) {
1638 operands.push_back(resolveSSAUse(operandInfos[i], operandTypes[i]));
1639 if (!operands.back())
1640 return nullptr;
1641 }
1642
1643 auto nameId = builder.getIdentifier(name);
1644 return createOpFunc(nameId, operands, fnType->getResults(), attributes);
1645}
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
1802 /// Emit a diagnostic at the specified location.
1803 void emitError(llvm::SMLoc loc, const Twine &message) override {
1804 parser.emitError(loc, "custom op '" + Twine(opName) + "' " + message);
1805 emittedError = true;
1806 }
1807
1808 bool didEmitError() const { return emittedError; }
1809
1810private:
1811 SMLoc nameLoc;
1812 StringRef opName;
1813 FunctionParser &parser;
1814 bool emittedError = false;
1815};
1816} // end anonymous namespace.
1817
1818Operation *FunctionParser::parseCustomOperation(
1819 const CreateOperationFunction &createOpFunc) {
1820 auto opLoc = getToken().getLoc();
1821 auto opName = getTokenSpelling();
1822 CustomOpAsmParser opAsmParser(opLoc, opName, *this);
1823
1824 auto *opDefinition = getOperationSet().lookup(opName);
1825 if (!opDefinition) {
1826 opAsmParser.emitError(opLoc, "is unknown");
1827 return nullptr;
1828 }
1829
1830 consumeToken();
1831
1832 // Have the op implementation take a crack and parsing this.
1833 auto result = opDefinition->parseAssembly(&opAsmParser);
1834
1835 // If it emitted an error, we failed.
1836 if (opAsmParser.didEmitError())
1837 return nullptr;
1838
1839 // Otherwise, we succeeded. Use the state it parsed as our op information.
1840 auto nameId = builder.getIdentifier(opName);
1841 return createOpFunc(nameId, result.operands, result.types, result.attributes);
1842}
1843
Chris Lattner48af7d12018-07-09 19:05:38 -07001844//===----------------------------------------------------------------------===//
1845// CFG Functions
1846//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001847
Chris Lattner4c95a502018-06-23 16:03:42 -07001848namespace {
Chris Lattner48af7d12018-07-09 19:05:38 -07001849/// This is a specialized parser for CFGFunction's, maintaining the state
1850/// transient to their bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001851class CFGFunctionParser : public FunctionParser {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001852public:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001853 CFGFunctionParser(ParserState &state, CFGFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001854 : FunctionParser(state, Kind::CFGFunc), function(function),
1855 builder(function) {}
Chris Lattner2e595eb2018-07-10 10:08:27 -07001856
1857 ParseResult parseFunctionBody();
1858
1859private:
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001860 CFGFunction *function;
James Molloy0ff71542018-07-23 16:56:32 -07001861 llvm::StringMap<std::pair<BasicBlock *, SMLoc>> blocksByName;
Chris Lattner48af7d12018-07-09 19:05:38 -07001862
1863 /// This builder intentionally shadows the builder in the base class, with a
1864 /// more specific builder type.
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001865 CFGFuncBuilder builder;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001866
Chris Lattner4c95a502018-06-23 16:03:42 -07001867 /// Get the basic block with the specified name, creating it if it doesn't
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001868 /// already exist. The location specified is the point of use, which allows
1869 /// us to diagnose references to blocks that are not defined precisely.
1870 BasicBlock *getBlockNamed(StringRef name, SMLoc loc) {
1871 auto &blockAndLoc = blocksByName[name];
1872 if (!blockAndLoc.first) {
Chris Lattner3a467cc2018-07-01 20:28:00 -07001873 blockAndLoc.first = new BasicBlock();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001874 blockAndLoc.second = loc;
Chris Lattner4c95a502018-06-23 16:03:42 -07001875 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001876 return blockAndLoc.first;
Chris Lattner4c95a502018-06-23 16:03:42 -07001877 }
Chris Lattner48af7d12018-07-09 19:05:38 -07001878
James Molloy61a656c2018-07-22 15:45:24 -07001879 ParseResult
1880 parseOptionalBasicBlockArgList(SmallVectorImpl<BBArgument *> &results,
1881 BasicBlock *owner);
James Molloy4f788372018-07-24 15:01:27 -07001882 ParseResult parseBranchBlockAndUseList(BasicBlock *&block,
1883 SmallVectorImpl<CFGValue *> &values);
James Molloy61a656c2018-07-22 15:45:24 -07001884
Chris Lattner48af7d12018-07-09 19:05:38 -07001885 ParseResult parseBasicBlock();
1886 OperationInst *parseCFGOperation();
1887 TerminatorInst *parseTerminator();
Chris Lattner4c95a502018-06-23 16:03:42 -07001888};
1889} // end anonymous namespace
1890
James Molloy61a656c2018-07-22 15:45:24 -07001891/// Parse a (possibly empty) list of SSA operands with types as basic block
Chris Lattner2c402672018-07-23 11:56:17 -07001892/// arguments.
James Molloy61a656c2018-07-22 15:45:24 -07001893///
1894/// ssa-id-and-type-list ::= ssa-id-and-type (`,` ssa-id-and-type)*
1895///
1896ParseResult CFGFunctionParser::parseOptionalBasicBlockArgList(
1897 SmallVectorImpl<BBArgument *> &results, BasicBlock *owner) {
1898 if (getToken().is(Token::r_brace))
1899 return ParseSuccess;
1900
1901 return parseCommaSeparatedList([&]() -> ParseResult {
1902 auto type = parseSSADefOrUseAndType<Type *>(
1903 [&](SSAUseInfo useInfo, Type *type) -> Type * {
1904 BBArgument *arg = owner->addArgument(type);
Chris Lattner2b97d502018-08-06 14:19:46 -07001905 if (addDefinition(useInfo, arg))
James Molloy61a656c2018-07-22 15:45:24 -07001906 return nullptr;
1907 return type;
1908 });
1909 return type ? ParseSuccess : ParseFailure;
1910 });
1911}
1912
Chris Lattner48af7d12018-07-09 19:05:38 -07001913ParseResult CFGFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07001914 auto braceLoc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001915 if (parseToken(Token::l_brace, "expected '{' in CFG function"))
1916 return ParseFailure;
Chris Lattner48af7d12018-07-09 19:05:38 -07001917
1918 // Make sure we have at least one block.
1919 if (getToken().is(Token::r_brace))
1920 return emitError("CFG functions must have at least one basic block");
Chris Lattner4c95a502018-06-23 16:03:42 -07001921
1922 // Parse the list of blocks.
1923 while (!consumeIf(Token::r_brace))
Chris Lattner48af7d12018-07-09 19:05:38 -07001924 if (parseBasicBlock())
Chris Lattner4c95a502018-06-23 16:03:42 -07001925 return ParseFailure;
1926
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001927 // Verify that all referenced blocks were defined. Iteration over a
1928 // StringMap isn't determinstic, but this is good enough for our purposes.
Chris Lattner48af7d12018-07-09 19:05:38 -07001929 for (auto &elt : blocksByName) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001930 auto *bb = elt.second.first;
Chris Lattner3a467cc2018-07-01 20:28:00 -07001931 if (!bb->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001932 return emitError(elt.second.second,
James Molloy0ff71542018-07-23 16:56:32 -07001933 "reference to an undefined basic block '" + elt.first() +
1934 "'");
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001935 }
1936
Chris Lattnera8e47672018-07-25 14:08:16 -07001937 getModule()->getFunctions().push_back(function);
Chris Lattner6119d382018-07-20 18:41:34 -07001938
Chris Lattner40746442018-07-21 14:32:09 -07001939 return finalizeFunction(function, braceLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001940}
1941
1942/// Basic block declaration.
1943///
1944/// basic-block ::= bb-label instruction* terminator-stmt
1945/// bb-label ::= bb-id bb-arg-list? `:`
1946/// bb-id ::= bare-id
1947/// bb-arg-list ::= `(` ssa-id-and-type-list? `)`
1948///
Chris Lattner48af7d12018-07-09 19:05:38 -07001949ParseResult CFGFunctionParser::parseBasicBlock() {
1950 SMLoc nameLoc = getToken().getLoc();
1951 auto name = getTokenSpelling();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001952 if (parseToken(Token::bare_identifier, "expected basic block name"))
1953 return ParseFailure;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001954
Chris Lattner48af7d12018-07-09 19:05:38 -07001955 auto *block = getBlockNamed(name, nameLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001956
1957 // If this block has already been parsed, then this is a redefinition with the
1958 // same block name.
Chris Lattner3a467cc2018-07-01 20:28:00 -07001959 if (block->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001960 return emitError(nameLoc, "redefinition of block '" + name.str() + "'");
1961
Chris Lattner78276e32018-07-07 15:48:26 -07001962 // If an argument list is present, parse it.
1963 if (consumeIf(Token::l_paren)) {
James Molloy61a656c2018-07-22 15:45:24 -07001964 SmallVector<BBArgument *, 8> bbArgs;
Chris Lattnerf7702a62018-07-23 17:30:01 -07001965 if (parseOptionalBasicBlockArgList(bbArgs, block) ||
1966 parseToken(Token::r_paren, "expected ')' to end argument list"))
Chris Lattner78276e32018-07-07 15:48:26 -07001967 return ParseFailure;
Chris Lattner78276e32018-07-07 15:48:26 -07001968 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001969
James Molloy61a656c2018-07-22 15:45:24 -07001970 // Add the block to the function.
1971 function->push_back(block);
1972
Chris Lattnerf7702a62018-07-23 17:30:01 -07001973 if (parseToken(Token::colon, "expected ':' after basic block name"))
1974 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07001975
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001976 // Set the insertion point to the block we want to insert new operations into.
Chris Lattner48af7d12018-07-09 19:05:38 -07001977 builder.setInsertionPoint(block);
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001978
Chris Lattner7f9cc272018-07-19 08:35:28 -07001979 auto createOpFunc = [&](Identifier name, ArrayRef<SSAValue *> operands,
1980 ArrayRef<Type *> resultTypes,
1981 ArrayRef<NamedAttribute> attrs) -> Operation * {
1982 SmallVector<CFGValue *, 8> cfgOperands;
1983 cfgOperands.reserve(operands.size());
1984 for (auto *op : operands)
1985 cfgOperands.push_back(cast<CFGValue>(op));
1986 return builder.createOperation(name, cfgOperands, resultTypes, attrs);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001987 };
1988
Chris Lattnered65a732018-06-28 20:45:33 -07001989 // Parse the list of operations that make up the body of the block.
James Molloy4f788372018-07-24 15:01:27 -07001990 while (getToken().isNot(Token::kw_return, Token::kw_br, Token::kw_cond_br)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001991 if (parseOperation(createOpFunc))
Chris Lattnered65a732018-06-28 20:45:33 -07001992 return ParseFailure;
1993 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001994
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001995 if (!parseTerminator())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001996 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07001997
1998 return ParseSuccess;
1999}
2000
James Molloy4f788372018-07-24 15:01:27 -07002001ParseResult CFGFunctionParser::parseBranchBlockAndUseList(
2002 BasicBlock *&block, SmallVectorImpl<CFGValue *> &values) {
2003 block = getBlockNamed(getTokenSpelling(), getToken().getLoc());
2004 if (parseToken(Token::bare_identifier, "expected basic block name"))
2005 return ParseFailure;
2006
2007 if (!consumeIf(Token::l_paren))
2008 return ParseSuccess;
2009 if (parseOptionalSSAUseAndTypeList(values, /*isParenthesized*/ false) ||
2010 parseToken(Token::r_paren, "expected ')' to close argument list"))
2011 return ParseFailure;
2012 return ParseSuccess;
2013}
2014
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002015/// Parse the terminator instruction for a basic block.
2016///
2017/// terminator-stmt ::= `br` bb-id branch-use-list?
Chris Lattner1604e472018-07-23 08:42:19 -07002018/// branch-use-list ::= `(` ssa-use-list `)` ':' type-list-no-parens
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002019/// terminator-stmt ::=
2020/// `cond_br` ssa-use `,` bb-id branch-use-list? `,` bb-id branch-use-list?
2021/// terminator-stmt ::= `return` ssa-use-and-type-list?
2022///
Chris Lattner48af7d12018-07-09 19:05:38 -07002023TerminatorInst *CFGFunctionParser::parseTerminator() {
2024 switch (getToken().getKind()) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002025 default:
Chris Lattner3a467cc2018-07-01 20:28:00 -07002026 return (emitError("expected terminator at end of basic block"), nullptr);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002027
Chris Lattner40746442018-07-21 14:32:09 -07002028 case Token::kw_return: {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002029 consumeToken(Token::kw_return);
Chris Lattner40746442018-07-21 14:32:09 -07002030
Chris Lattner2c402672018-07-23 11:56:17 -07002031 // Parse any operands.
2032 SmallVector<CFGValue *, 8> operands;
2033 if (parseOptionalSSAUseAndTypeList(operands, /*isParenthesized*/ false))
2034 return nullptr;
2035 return builder.createReturnInst(operands);
Chris Lattner40746442018-07-21 14:32:09 -07002036 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002037
2038 case Token::kw_br: {
2039 consumeToken(Token::kw_br);
James Molloy4f788372018-07-24 15:01:27 -07002040 BasicBlock *destBB;
2041 SmallVector<CFGValue *, 4> values;
2042 if (parseBranchBlockAndUseList(destBB, values))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002043 return nullptr;
Chris Lattner1604e472018-07-23 08:42:19 -07002044 auto branch = builder.createBranchInst(destBB);
James Molloy4f788372018-07-24 15:01:27 -07002045 branch->addOperands(values);
Chris Lattner1604e472018-07-23 08:42:19 -07002046 return branch;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002047 }
James Molloy4f788372018-07-24 15:01:27 -07002048
2049 case Token::kw_cond_br: {
2050 consumeToken(Token::kw_cond_br);
2051 SSAUseInfo ssaUse;
2052 if (parseSSAUse(ssaUse))
2053 return nullptr;
2054 auto *cond = resolveSSAUse(ssaUse, builder.getIntegerType(1));
2055 if (!cond)
2056 return (emitError("expected type was boolean (i1)"), nullptr);
2057 if (parseToken(Token::comma, "expected ',' in conditional branch"))
2058 return nullptr;
2059
2060 BasicBlock *trueBlock;
2061 SmallVector<CFGValue *, 4> trueOperands;
2062 if (parseBranchBlockAndUseList(trueBlock, trueOperands))
2063 return nullptr;
2064
2065 if (parseToken(Token::comma, "expected ',' in conditional branch"))
2066 return nullptr;
2067
2068 BasicBlock *falseBlock;
2069 SmallVector<CFGValue *, 4> falseOperands;
2070 if (parseBranchBlockAndUseList(falseBlock, falseOperands))
2071 return nullptr;
2072
2073 auto branch = builder.createCondBranchInst(cast<CFGValue>(cond), trueBlock,
2074 falseBlock);
2075 branch->addTrueOperands(trueOperands);
2076 branch->addFalseOperands(falseOperands);
2077 return branch;
2078 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002079 }
2080}
2081
Chris Lattner48af7d12018-07-09 19:05:38 -07002082//===----------------------------------------------------------------------===//
2083// ML Functions
2084//===----------------------------------------------------------------------===//
2085
2086namespace {
2087/// Refined parser for MLFunction bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07002088class MLFunctionParser : public FunctionParser {
Chris Lattner48af7d12018-07-09 19:05:38 -07002089public:
Chris Lattner48af7d12018-07-09 19:05:38 -07002090 MLFunctionParser(ParserState &state, MLFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07002091 : FunctionParser(state, Kind::MLFunc), function(function),
2092 builder(function) {}
Chris Lattner48af7d12018-07-09 19:05:38 -07002093
2094 ParseResult parseFunctionBody();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002095
2096private:
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002097 MLFunction *function;
2098
2099 /// This builder intentionally shadows the builder in the base class, with a
2100 /// more specific builder type.
2101 MLFuncBuilder builder;
2102
2103 ParseResult parseForStmt();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002104 AffineConstantExpr *parseIntConstant();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002105 ParseResult parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002106 ParseResult parseElseClause(IfClause *elseClause);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002107 ParseResult parseStatements(StmtBlock *block);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002108 ParseResult parseStmtBlock(StmtBlock *block);
Chris Lattner48af7d12018-07-09 19:05:38 -07002109};
2110} // end anonymous namespace
2111
Chris Lattner48af7d12018-07-09 19:05:38 -07002112ParseResult MLFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07002113 auto braceLoc = getToken().getLoc();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002114 // Parse statements in this function
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002115
Chris Lattnerf7702a62018-07-23 17:30:01 -07002116 if (parseToken(Token::l_brace, "expected '{' in ML function") ||
2117 parseStatements(function)) {
2118 return ParseFailure;
2119 }
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002120
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002121 // TODO: store return operands in the IR.
2122 SmallVector<SSAUseInfo, 4> dummyUseInfo;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002123
Chris Lattnerf7702a62018-07-23 17:30:01 -07002124 if (parseToken(Token::kw_return,
2125 "ML function must end with return statement") ||
2126 parseOptionalSSAUseList(dummyUseInfo) ||
2127 parseToken(Token::r_brace, "expected '}' to end mlfunc"))
2128 return ParseFailure;
Chris Lattner40746442018-07-21 14:32:09 -07002129
Chris Lattnera8e47672018-07-25 14:08:16 -07002130 getModule()->getFunctions().push_back(function);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002131
Chris Lattner40746442018-07-21 14:32:09 -07002132 return finalizeFunction(function, braceLoc);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002133}
2134
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002135/// For statement.
2136///
Chris Lattner48af7d12018-07-09 19:05:38 -07002137/// ml-for-stmt ::= `for` ssa-id `=` lower-bound `to` upper-bound
2138/// (`step` integer-literal)? `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002139///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002140ParseResult MLFunctionParser::parseForStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002141 consumeToken(Token::kw_for);
2142
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002143 // Parse induction variable
2144 if (getToken().isNot(Token::percent_identifier))
2145 return emitError("expected SSA identifier for the loop variable");
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002146
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002147 auto loc = getToken().getLoc();
Tatiana Shpeismand880b352018-07-31 23:14:16 -07002148 StringRef inductionVariableName = getTokenSpelling();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002149 consumeToken(Token::percent_identifier);
2150
Chris Lattnerf7702a62018-07-23 17:30:01 -07002151 if (parseToken(Token::equal, "expected ="))
2152 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002153
2154 // Parse loop bounds
2155 AffineConstantExpr *lowerBound = parseIntConstant();
2156 if (!lowerBound)
2157 return ParseFailure;
2158
Chris Lattnerf7702a62018-07-23 17:30:01 -07002159 if (parseToken(Token::kw_to, "expected 'to' between bounds"))
2160 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002161
2162 AffineConstantExpr *upperBound = parseIntConstant();
2163 if (!upperBound)
2164 return ParseFailure;
2165
2166 // Parse step
2167 AffineConstantExpr *step = nullptr;
2168 if (consumeIf(Token::kw_step)) {
2169 step = parseIntConstant();
2170 if (!step)
2171 return ParseFailure;
2172 }
2173
2174 // Create for statement.
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002175 ForStmt *forStmt = builder.createFor(lowerBound, upperBound, step);
2176
2177 // Create SSA value definition for the induction variable.
Chris Lattner2b97d502018-08-06 14:19:46 -07002178 if (addDefinition({inductionVariableName, 0, loc}, forStmt))
2179 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002180
2181 // If parsing of the for statement body fails,
2182 // MLIR contains for statement with those nested statements that have been
2183 // successfully parsed.
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002184 if (parseStmtBlock(forStmt))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002185 return ParseFailure;
2186
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002187 // Reset insertion point to the current block.
2188 builder.setInsertionPoint(forStmt->getBlock());
2189
Tatiana Shpeismand880b352018-07-31 23:14:16 -07002190 // TODO: remove definition of the induction variable.
2191
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002192 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002193}
2194
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002195// This method is temporary workaround to parse simple loop bounds and
2196// step.
2197// TODO: remove this method once it's no longer used.
2198AffineConstantExpr *MLFunctionParser::parseIntConstant() {
2199 if (getToken().isNot(Token::integer))
2200 return (emitError("expected non-negative integer for now"), nullptr);
2201
2202 auto val = getToken().getUInt64IntegerValue();
2203 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
2204 return (emitError("constant too large for affineint"), nullptr);
2205 }
2206 consumeToken(Token::integer);
2207 return builder.getConstantExpr((int64_t)val.getValue());
2208}
2209
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002210/// If statement.
2211///
Chris Lattner48af7d12018-07-09 19:05:38 -07002212/// ml-if-head ::= `if` ml-if-cond `{` ml-stmt* `}`
2213/// | ml-if-head `else` `if` ml-if-cond `{` ml-stmt* `}`
2214/// ml-if-stmt ::= ml-if-head
2215/// | ml-if-head `else` `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002216///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002217ParseResult MLFunctionParser::parseIfStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002218 consumeToken(Token::kw_if);
Chris Lattnerf7702a62018-07-23 17:30:01 -07002219 if (parseToken(Token::l_paren, "expected ("))
2220 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002221
James Molloy0ff71542018-07-23 16:56:32 -07002222 // TODO: parse condition
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002223
Chris Lattnerf7702a62018-07-23 17:30:01 -07002224 if (parseToken(Token::r_paren, "expected )"))
2225 return ParseFailure;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002226
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002227 IfStmt *ifStmt = builder.createIf();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002228 IfClause *thenClause = ifStmt->getThenClause();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002229
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002230 // When parsing of an if statement body fails, the IR contains
2231 // the if statement with the portion of the body that has been
2232 // successfully parsed.
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002233 if (parseStmtBlock(thenClause))
2234 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002235
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002236 if (consumeIf(Token::kw_else)) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002237 auto *elseClause = ifStmt->createElseClause();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002238 if (parseElseClause(elseClause))
2239 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002240 }
2241
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002242 // Reset insertion point to the current block.
2243 builder.setInsertionPoint(ifStmt->getBlock());
2244
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002245 return ParseSuccess;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002246}
2247
2248ParseResult MLFunctionParser::parseElseClause(IfClause *elseClause) {
2249 if (getToken().is(Token::kw_if)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002250 builder.setInsertionPoint(elseClause);
2251 return parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002252 }
2253
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002254 return parseStmtBlock(elseClause);
2255}
2256
2257///
2258/// Parse a list of statements ending with `return` or `}`
2259///
2260ParseResult MLFunctionParser::parseStatements(StmtBlock *block) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07002261 auto createOpFunc = [&](Identifier name, ArrayRef<SSAValue *> operands,
2262 ArrayRef<Type *> resultTypes,
2263 ArrayRef<NamedAttribute> attrs) -> Operation * {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07002264 SmallVector<MLValue *, 8> stmtOperands;
2265 stmtOperands.reserve(operands.size());
2266 for (auto *op : operands)
2267 stmtOperands.push_back(cast<MLValue>(op));
2268 return builder.createOperation(name, stmtOperands, resultTypes, attrs);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002269 };
2270
2271 builder.setInsertionPoint(block);
2272
2273 while (getToken().isNot(Token::kw_return, Token::r_brace)) {
2274 switch (getToken().getKind()) {
2275 default:
2276 if (parseOperation(createOpFunc))
2277 return ParseFailure;
2278 break;
2279 case Token::kw_for:
2280 if (parseForStmt())
2281 return ParseFailure;
2282 break;
2283 case Token::kw_if:
2284 if (parseIfStmt())
2285 return ParseFailure;
2286 break;
2287 } // end switch
2288 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002289
2290 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002291}
2292
2293///
2294/// Parse `{` ml-stmt* `}`
2295///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002296ParseResult MLFunctionParser::parseStmtBlock(StmtBlock *block) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002297 if (parseToken(Token::l_brace, "expected '{' before statement list") ||
2298 parseStatements(block) ||
2299 parseToken(Token::r_brace,
2300 "expected '}' at the end of the statement block"))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002301 return ParseFailure;
2302
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002303 return ParseSuccess;
2304}
2305
Chris Lattner4c95a502018-06-23 16:03:42 -07002306//===----------------------------------------------------------------------===//
2307// Top-level entity parsing.
2308//===----------------------------------------------------------------------===//
2309
Chris Lattner2e595eb2018-07-10 10:08:27 -07002310namespace {
2311/// This parser handles entities that are only valid at the top level of the
2312/// file.
2313class ModuleParser : public Parser {
2314public:
2315 explicit ModuleParser(ParserState &state) : Parser(state) {}
2316
2317 ParseResult parseModule();
2318
2319private:
2320 ParseResult parseAffineMapDef();
2321
2322 // Functions.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002323 ParseResult parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2324 SmallVectorImpl<StringRef> &argNames);
2325 ParseResult parseFunctionSignature(StringRef &name, FunctionType *&type,
2326 SmallVectorImpl<StringRef> *argNames);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002327 ParseResult parseExtFunc();
2328 ParseResult parseCFGFunc();
2329 ParseResult parseMLFunc();
2330};
2331} // end anonymous namespace
2332
2333/// Affine map declaration.
2334///
2335/// affine-map-def ::= affine-map-id `=` affine-map-inline
2336///
2337ParseResult ModuleParser::parseAffineMapDef() {
2338 assert(getToken().is(Token::hash_identifier));
2339
2340 StringRef affineMapId = getTokenSpelling().drop_front();
2341
2342 // Check for redefinitions.
2343 auto *&entry = getState().affineMapDefinitions[affineMapId];
2344 if (entry)
2345 return emitError("redefinition of affine map id '" + affineMapId + "'");
2346
2347 consumeToken(Token::hash_identifier);
2348
2349 // Parse the '='
Chris Lattnerf7702a62018-07-23 17:30:01 -07002350 if (parseToken(Token::equal,
2351 "expected '=' in affine map outlined definition"))
2352 return ParseFailure;
Chris Lattner2e595eb2018-07-10 10:08:27 -07002353
2354 entry = parseAffineMapInline();
2355 if (!entry)
2356 return ParseFailure;
2357
Chris Lattner2e595eb2018-07-10 10:08:27 -07002358 return ParseSuccess;
2359}
2360
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002361/// Parse a (possibly empty) list of MLFunction arguments with types.
2362///
2363/// ml-argument ::= ssa-id `:` type
2364/// ml-argument-list ::= ml-argument (`,` ml-argument)* | /*empty*/
2365///
2366ParseResult
2367ModuleParser::parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2368 SmallVectorImpl<StringRef> &argNames) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002369 consumeToken(Token::l_paren);
2370
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002371 auto parseElt = [&]() -> ParseResult {
2372 // Parse argument name
2373 if (getToken().isNot(Token::percent_identifier))
2374 return emitError("expected SSA identifier");
2375
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002376 StringRef name = getTokenSpelling();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002377 consumeToken(Token::percent_identifier);
2378 argNames.push_back(name);
2379
Chris Lattnerf7702a62018-07-23 17:30:01 -07002380 if (parseToken(Token::colon, "expected ':'"))
2381 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002382
2383 // Parse argument type
2384 auto elt = parseType();
2385 if (!elt)
2386 return ParseFailure;
2387 argTypes.push_back(elt);
2388
2389 return ParseSuccess;
2390 };
2391
Chris Lattner40746442018-07-21 14:32:09 -07002392 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002393}
2394
Chris Lattner2e595eb2018-07-10 10:08:27 -07002395/// Parse a function signature, starting with a name and including the parameter
2396/// list.
2397///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002398/// argument-list ::= type (`,` type)* | /*empty*/ | ml-argument-list
Chris Lattner2e595eb2018-07-10 10:08:27 -07002399/// function-signature ::= function-id `(` argument-list `)` (`->` type-list)?
2400///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002401ParseResult
2402ModuleParser::parseFunctionSignature(StringRef &name, FunctionType *&type,
2403 SmallVectorImpl<StringRef> *argNames) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002404 if (getToken().isNot(Token::at_identifier))
2405 return emitError("expected a function identifier like '@foo'");
2406
2407 name = getTokenSpelling().drop_front();
2408 consumeToken(Token::at_identifier);
2409
2410 if (getToken().isNot(Token::l_paren))
2411 return emitError("expected '(' in function signature");
2412
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002413 SmallVector<Type *, 4> argTypes;
2414 ParseResult parseResult;
2415
2416 if (argNames)
2417 parseResult = parseMLArgumentList(argTypes, *argNames);
2418 else
2419 parseResult = parseTypeList(argTypes);
2420
2421 if (parseResult)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002422 return ParseFailure;
2423
2424 // Parse the return type if present.
2425 SmallVector<Type *, 4> results;
2426 if (consumeIf(Token::arrow)) {
2427 if (parseTypeList(results))
2428 return ParseFailure;
2429 }
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002430 type = builder.getFunctionType(argTypes, results);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002431 return ParseSuccess;
2432}
2433
2434/// External function declarations.
2435///
2436/// ext-func ::= `extfunc` function-signature
2437///
2438ParseResult ModuleParser::parseExtFunc() {
2439 consumeToken(Token::kw_extfunc);
2440
2441 StringRef name;
2442 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002443 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002444 return ParseFailure;
2445
2446 // Okay, the external function definition was parsed correctly.
Chris Lattnera8e47672018-07-25 14:08:16 -07002447 getModule()->getFunctions().push_back(new ExtFunction(name, type));
Chris Lattner2e595eb2018-07-10 10:08:27 -07002448 return ParseSuccess;
2449}
2450
2451/// CFG function declarations.
2452///
2453/// cfg-func ::= `cfgfunc` function-signature `{` basic-block+ `}`
2454///
2455ParseResult ModuleParser::parseCFGFunc() {
2456 consumeToken(Token::kw_cfgfunc);
2457
2458 StringRef name;
2459 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002460 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002461 return ParseFailure;
2462
2463 // Okay, the CFG function signature was parsed correctly, create the function.
2464 auto function = new CFGFunction(name, type);
2465
2466 return CFGFunctionParser(getState(), function).parseFunctionBody();
2467}
2468
2469/// ML function declarations.
2470///
2471/// ml-func ::= `mlfunc` ml-func-signature `{` ml-stmt* ml-return-stmt `}`
2472///
2473ParseResult ModuleParser::parseMLFunc() {
2474 consumeToken(Token::kw_mlfunc);
2475
2476 StringRef name;
2477 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002478 SmallVector<StringRef, 4> argNames;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002479
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002480 auto loc = getToken().getLoc();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002481 if (parseFunctionSignature(name, type, &argNames))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002482 return ParseFailure;
2483
2484 // Okay, the ML function signature was parsed correctly, create the function.
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002485 auto function = MLFunction::create(name, type);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002486
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002487 // Create the parser.
2488 auto parser = MLFunctionParser(getState(), function);
2489
2490 // Add definitions of the function arguments.
2491 for (unsigned i = 0, e = function->getNumArguments(); i != e; ++i) {
2492 if (parser.addDefinition({argNames[i], 0, loc}, function->getArgument(i)))
2493 return ParseFailure;
2494 }
2495
2496 return parser.parseFunctionBody();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002497}
2498
Chris Lattnere79379a2018-06-22 10:39:19 -07002499/// This is the top-level module parser.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002500ParseResult ModuleParser::parseModule() {
Chris Lattnere79379a2018-06-22 10:39:19 -07002501 while (1) {
Chris Lattner48af7d12018-07-09 19:05:38 -07002502 switch (getToken().getKind()) {
Chris Lattnere79379a2018-06-22 10:39:19 -07002503 default:
2504 emitError("expected a top level entity");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002505 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002506
Uday Bondhugula015cbb12018-07-03 20:16:08 -07002507 // If we got to the end of the file, then we're done.
Chris Lattnere79379a2018-06-22 10:39:19 -07002508 case Token::eof:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002509 return ParseSuccess;
Chris Lattnere79379a2018-06-22 10:39:19 -07002510
2511 // If we got an error token, then the lexer already emitted an error, just
2512 // stop. Someday we could introduce error recovery if there was demand for
2513 // it.
2514 case Token::error:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002515 return ParseFailure;
2516
2517 case Token::hash_identifier:
2518 if (parseAffineMapDef())
2519 return ParseFailure;
2520 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002521
2522 case Token::kw_extfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002523 if (parseExtFunc())
2524 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002525 break;
2526
Chris Lattner4c95a502018-06-23 16:03:42 -07002527 case Token::kw_cfgfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002528 if (parseCFGFunc())
2529 return ParseFailure;
MLIR Teamf85a6262018-06-27 11:03:08 -07002530 break;
Chris Lattner4c95a502018-06-23 16:03:42 -07002531
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002532 case Token::kw_mlfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002533 if (parseMLFunc())
2534 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002535 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002536 }
2537 }
2538}
2539
2540//===----------------------------------------------------------------------===//
2541
Jacques Pienaar7b829702018-07-03 13:24:09 -07002542void mlir::defaultErrorReporter(const llvm::SMDiagnostic &error) {
2543 const auto &sourceMgr = *error.getSourceMgr();
2544 sourceMgr.PrintMessage(error.getLoc(), error.getKind(), error.getMessage());
2545}
2546
Chris Lattnere79379a2018-06-22 10:39:19 -07002547/// This parses the file specified by the indicated SourceMgr and returns an
2548/// MLIR module if it was valid. If not, it emits diagnostics and returns null.
Jacques Pienaar9c411be2018-06-24 19:17:35 -07002549Module *mlir::parseSourceFile(llvm::SourceMgr &sourceMgr, MLIRContext *context,
Jacques Pienaar7b829702018-07-03 13:24:09 -07002550 SMDiagnosticHandlerTy errorReporter) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002551 // This is the result module we are parsing into.
2552 std::unique_ptr<Module> module(new Module(context));
2553
2554 ParserState state(sourceMgr, module.get(),
Jacques Pienaar0bffd862018-07-11 13:26:23 -07002555 errorReporter ? errorReporter : defaultErrorReporter);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002556 if (ModuleParser(state).parseModule())
2557 return nullptr;
Chris Lattner21e67f62018-07-06 10:46:19 -07002558
2559 // Make sure the parse module has no other structural problems detected by the
2560 // verifier.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002561 module->verify();
2562 return module.release();
Chris Lattnere79379a2018-06-22 10:39:19 -07002563}