blob: c146a93455ed36ab86e928af822ba9f9e0196c2c [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"
Jacques Pienaar84491092018-07-31 17:15:15 -070024#include "llvm/ADT/DenseMap.h"
25#include "llvm/Support/SourceMgr.h"
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -070026#include "mlir/IR/AffineExpr.h"
MLIR Teamf85a6262018-06-27 11:03:08 -070027#include "mlir/IR/AffineMap.h"
Chris Lattner7121b802018-07-04 20:45:39 -070028#include "mlir/IR/Attributes.h"
Chris Lattner158e0a3e2018-07-08 20:51:38 -070029#include "mlir/IR/Builders.h"
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -070030#include "mlir/IR/MLFunction.h"
Chris Lattner21e67f62018-07-06 10:46:19 -070031#include "mlir/IR/Module.h"
Chris Lattner85ee1512018-07-25 11:15:20 -070032#include "mlir/IR/OpImplementation.h"
Chris Lattner21e67f62018-07-06 10:46:19 -070033#include "mlir/IR/OperationSet.h"
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -070034#include "mlir/IR/Statements.h"
Chris Lattnerf7e22732018-06-22 22:03:48 -070035#include "mlir/IR/Types.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 Lattner48af7d12018-07-09 19:05:38 -0700108
109 /// Return the current token the parser is inspecting.
110 const Token &getToken() const { return state.curToken; }
111 StringRef getTokenSpelling() const { return state.curToken.getSpelling(); }
Chris Lattnere79379a2018-06-22 10:39:19 -0700112
113 /// Emit an error and return failure.
Chris Lattner4c95a502018-06-23 16:03:42 -0700114 ParseResult emitError(const Twine &message) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700115 return emitError(state.curToken.getLoc(), message);
Chris Lattner4c95a502018-06-23 16:03:42 -0700116 }
117 ParseResult emitError(SMLoc loc, const Twine &message);
Chris Lattnere79379a2018-06-22 10:39:19 -0700118
119 /// Advance the current lexer onto the next token.
120 void consumeToken() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700121 assert(state.curToken.isNot(Token::eof, Token::error) &&
Chris Lattnere79379a2018-06-22 10:39:19 -0700122 "shouldn't advance past EOF or errors");
Chris Lattner48af7d12018-07-09 19:05:38 -0700123 state.curToken = state.lex.lexToken();
Chris Lattnere79379a2018-06-22 10:39:19 -0700124 }
125
126 /// Advance the current lexer onto the next token, asserting what the expected
127 /// current token is. This is preferred to the above method because it leads
128 /// to more self-documenting code with better checking.
Chris Lattner8da0c282018-06-29 11:15:56 -0700129 void consumeToken(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700130 assert(state.curToken.is(kind) && "consumed an unexpected token");
Chris Lattnere79379a2018-06-22 10:39:19 -0700131 consumeToken();
132 }
133
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700134 /// If the current token has the specified kind, consume it and return true.
135 /// If not, return false.
Chris Lattner8da0c282018-06-29 11:15:56 -0700136 bool consumeIf(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700137 if (state.curToken.isNot(kind))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700138 return false;
139 consumeToken(kind);
140 return true;
141 }
142
Chris Lattnerf7702a62018-07-23 17:30:01 -0700143 /// Consume the specified token if present and return success. On failure,
144 /// output a diagnostic and return failure.
145 ParseResult parseToken(Token::Kind expectedToken, const Twine &message);
146
Chris Lattner40746442018-07-21 14:32:09 -0700147 /// Parse a comma-separated list of elements up until the specified end token.
148 ParseResult
149 parseCommaSeparatedListUntil(Token::Kind rightToken,
150 const std::function<ParseResult()> &parseElement,
151 bool allowEmptyList = true);
152
153 /// Parse a comma separated list of elements that must have at least one entry
154 /// in it.
155 ParseResult
156 parseCommaSeparatedList(const std::function<ParseResult()> &parseElement);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700157
Chris Lattnerf7e22732018-06-22 22:03:48 -0700158 // We have two forms of parsing methods - those that return a non-null
159 // pointer on success, and those that return a ParseResult to indicate whether
160 // they returned a failure. The second class fills in by-reference arguments
161 // as the results of their action.
162
Chris Lattnere79379a2018-06-22 10:39:19 -0700163 // Type parsing.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700164 VectorType *parseVectorType();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700165 ParseResult parseDimensionListRanked(SmallVectorImpl<int> &dimensions);
Chris Lattnerf7e22732018-06-22 22:03:48 -0700166 Type *parseTensorType();
167 Type *parseMemRefType();
168 Type *parseFunctionType();
169 Type *parseType();
Chris Lattner1604e472018-07-23 08:42:19 -0700170 ParseResult parseTypeListNoParens(SmallVectorImpl<Type *> &elements);
James Molloy0ff71542018-07-23 16:56:32 -0700171 ParseResult parseTypeList(SmallVectorImpl<Type *> &elements);
Chris Lattnere79379a2018-06-22 10:39:19 -0700172
Chris Lattner7121b802018-07-04 20:45:39 -0700173 // Attribute parsing.
174 Attribute *parseAttribute();
175 ParseResult parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes);
176
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700177 // Polyhedral structures.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700178 AffineMap *parseAffineMapInline();
MLIR Team718c82f2018-07-16 09:45:22 -0700179 AffineMap *parseAffineMapReference();
MLIR Teamf85a6262018-06-27 11:03:08 -0700180
Chris Lattner48af7d12018-07-09 19:05:38 -0700181private:
182 // The Parser is subclassed and reinstantiated. Do not add additional
183 // non-trivial state here, add it to the ParserState class.
184 ParserState &state;
Chris Lattnere79379a2018-06-22 10:39:19 -0700185};
186} // end anonymous namespace
187
188//===----------------------------------------------------------------------===//
189// Helper methods.
190//===----------------------------------------------------------------------===//
191
Chris Lattner4c95a502018-06-23 16:03:42 -0700192ParseResult Parser::emitError(SMLoc loc, const Twine &message) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700193 // If we hit a parse error in response to a lexer error, then the lexer
Jacques Pienaar9c411be2018-06-24 19:17:35 -0700194 // already reported the error.
Chris Lattner48af7d12018-07-09 19:05:38 -0700195 if (getToken().is(Token::error))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700196 return ParseFailure;
197
Chris Lattner48af7d12018-07-09 19:05:38 -0700198 auto &sourceMgr = state.lex.getSourceMgr();
199 state.errorReporter(sourceMgr.GetMessage(loc, SourceMgr::DK_Error, message));
Chris Lattnere79379a2018-06-22 10:39:19 -0700200 return ParseFailure;
201}
202
Chris Lattnerf7702a62018-07-23 17:30:01 -0700203/// Consume the specified token if present and return success. On failure,
204/// output a diagnostic and return failure.
205ParseResult Parser::parseToken(Token::Kind expectedToken,
206 const Twine &message) {
207 if (consumeIf(expectedToken))
208 return ParseSuccess;
209 return emitError(message);
210}
211
Chris Lattner40746442018-07-21 14:32:09 -0700212/// Parse a comma separated list of elements that must have at least one entry
213/// in it.
214ParseResult Parser::parseCommaSeparatedList(
215 const std::function<ParseResult()> &parseElement) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700216 // Non-empty case starts with an element.
217 if (parseElement())
218 return ParseFailure;
219
220 // Otherwise we have a list of comma separated elements.
221 while (consumeIf(Token::comma)) {
222 if (parseElement())
223 return ParseFailure;
224 }
Chris Lattner40746442018-07-21 14:32:09 -0700225 return ParseSuccess;
226}
227
228/// Parse a comma-separated list of elements, terminated with an arbitrary
229/// token. This allows empty lists if allowEmptyList is true.
230///
231/// abstract-list ::= rightToken // if allowEmptyList == true
232/// abstract-list ::= element (',' element)* rightToken
233///
234ParseResult Parser::parseCommaSeparatedListUntil(
235 Token::Kind rightToken, const std::function<ParseResult()> &parseElement,
236 bool allowEmptyList) {
237 // Handle the empty case.
238 if (getToken().is(rightToken)) {
239 if (!allowEmptyList)
240 return emitError("expected list element");
241 consumeToken(rightToken);
242 return ParseSuccess;
243 }
244
Chris Lattnerf7702a62018-07-23 17:30:01 -0700245 if (parseCommaSeparatedList(parseElement) ||
246 parseToken(rightToken, "expected ',' or '" +
247 Token::getTokenSpelling(rightToken) + "'"))
Chris Lattner40746442018-07-21 14:32:09 -0700248 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700249
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700250 return ParseSuccess;
251}
Chris Lattnere79379a2018-06-22 10:39:19 -0700252
253//===----------------------------------------------------------------------===//
254// Type Parsing
255//===----------------------------------------------------------------------===//
256
Chris Lattnerc3251192018-07-27 13:09:58 -0700257/// Parse an arbitrary type.
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700258///
Chris Lattnerc3251192018-07-27 13:09:58 -0700259/// type ::= integer-type
260/// | float-type
261/// | other-type
262/// | vector-type
263/// | tensor-type
264/// | memref-type
265/// | function-type
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700266///
Chris Lattnerc3251192018-07-27 13:09:58 -0700267/// float-type ::= `f16` | `bf16` | `f32` | `f64`
268/// other-type ::= `affineint` | `tf_control`
269///
270Type *Parser::parseType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700271 switch (getToken().getKind()) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700272 default:
273 return (emitError("expected type"), nullptr);
Chris Lattnerc3251192018-07-27 13:09:58 -0700274 case Token::kw_memref:
275 return parseMemRefType();
276 case Token::kw_tensor:
277 return parseTensorType();
278 case Token::kw_vector:
279 return parseVectorType();
280 case Token::l_paren:
281 return parseFunctionType();
282 // integer-type
283 case Token::inttype: {
284 auto width = getToken().getIntTypeBitwidth();
285 if (!width.hasValue())
286 return (emitError("invalid integer width"), nullptr);
287 consumeToken(Token::inttype);
288 return builder.getIntegerType(width.getValue());
289 }
290
291 // float-type
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700292 case Token::kw_bf16:
293 consumeToken(Token::kw_bf16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700294 return builder.getBF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700295 case Token::kw_f16:
296 consumeToken(Token::kw_f16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700297 return builder.getF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700298 case Token::kw_f32:
299 consumeToken(Token::kw_f32);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700300 return builder.getF32Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700301 case Token::kw_f64:
302 consumeToken(Token::kw_f64);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700303 return builder.getF64Type();
Chris Lattnerc3251192018-07-27 13:09:58 -0700304
305 // other-type
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700306 case Token::kw_affineint:
307 consumeToken(Token::kw_affineint);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700308 return builder.getAffineIntType();
Jacques Pienaarc0d69302018-07-27 11:07:12 -0700309 case Token::kw_tf_control:
310 consumeToken(Token::kw_tf_control);
311 return builder.getTFControlType();
James Molloy72b0cbe2018-08-01 12:55:27 -0700312 case Token::kw_tf_string:
313 consumeToken(Token::kw_tf_string);
314 return builder.getTFStringType();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700315 }
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700316}
317
318/// Parse a vector type.
319///
320/// vector-type ::= `vector` `<` const-dimension-list primitive-type `>`
321/// const-dimension-list ::= (integer-literal `x`)+
322///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700323VectorType *Parser::parseVectorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700324 consumeToken(Token::kw_vector);
325
Chris Lattnerf7702a62018-07-23 17:30:01 -0700326 if (parseToken(Token::less, "expected '<' in vector type"))
327 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700328
Chris Lattner48af7d12018-07-09 19:05:38 -0700329 if (getToken().isNot(Token::integer))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700330 return (emitError("expected dimension size in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700331
332 SmallVector<unsigned, 4> dimensions;
Chris Lattner48af7d12018-07-09 19:05:38 -0700333 while (getToken().is(Token::integer)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700334 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700335 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700336 if (!dimension.hasValue())
Chris Lattnerf7e22732018-06-22 22:03:48 -0700337 return (emitError("invalid dimension in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700338 dimensions.push_back(dimension.getValue());
339
340 consumeToken(Token::integer);
341
342 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700343 if (getToken().isNot(Token::bare_identifier) ||
344 getTokenSpelling()[0] != 'x')
Chris Lattnerf7e22732018-06-22 22:03:48 -0700345 return (emitError("expected 'x' in vector dimension list"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700346
347 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700348 if (getTokenSpelling().size() != 1)
349 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700350
351 // Consume the 'x'.
352 consumeToken(Token::bare_identifier);
353 }
354
355 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700356 auto typeLoc = getToken().getLoc();
357 auto *elementType = parseType();
358 if (!elementType || parseToken(Token::greater, "expected '>' in vector type"))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700359 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700360
Chris Lattnerc3251192018-07-27 13:09:58 -0700361 if (!isa<FloatType>(elementType) && !isa<IntegerType>(elementType))
362 return (emitError(typeLoc, "invalid vector element type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700363
Chris Lattnerf7e22732018-06-22 22:03:48 -0700364 return VectorType::get(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700365}
366
367/// Parse a dimension list of a tensor or memref type. This populates the
368/// dimension list, returning -1 for the '?' dimensions.
369///
370/// dimension-list-ranked ::= (dimension `x`)*
371/// dimension ::= `?` | integer-literal
372///
373ParseResult Parser::parseDimensionListRanked(SmallVectorImpl<int> &dimensions) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700374 while (getToken().isAny(Token::integer, Token::question)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700375 if (consumeIf(Token::question)) {
376 dimensions.push_back(-1);
377 } else {
378 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700379 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700380 if (!dimension.hasValue() || (int)dimension.getValue() < 0)
381 return emitError("invalid dimension");
382 dimensions.push_back((int)dimension.getValue());
383 consumeToken(Token::integer);
384 }
385
386 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700387 if (getToken().isNot(Token::bare_identifier) ||
388 getTokenSpelling()[0] != 'x')
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700389 return emitError("expected 'x' in dimension list");
390
391 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700392 if (getTokenSpelling().size() != 1)
393 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700394
395 // Consume the 'x'.
396 consumeToken(Token::bare_identifier);
397 }
398
399 return ParseSuccess;
400}
401
402/// Parse a tensor type.
403///
404/// tensor-type ::= `tensor` `<` dimension-list element-type `>`
405/// dimension-list ::= dimension-list-ranked | `??`
406///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700407Type *Parser::parseTensorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700408 consumeToken(Token::kw_tensor);
409
Chris Lattnerf7702a62018-07-23 17:30:01 -0700410 if (parseToken(Token::less, "expected '<' in tensor type"))
411 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700412
413 bool isUnranked;
414 SmallVector<int, 4> dimensions;
415
416 if (consumeIf(Token::questionquestion)) {
417 isUnranked = true;
418 } else {
419 isUnranked = false;
420 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700421 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700422 }
423
424 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700425 auto typeLoc = getToken().getLoc();
426 auto *elementType = parseType();
427 if (!elementType || parseToken(Token::greater, "expected '>' in tensor type"))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700428 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700429
Chris Lattnerc3251192018-07-27 13:09:58 -0700430 if (!isa<IntegerType>(elementType) && !isa<FloatType>(elementType) &&
431 !isa<VectorType>(elementType))
432 return (emitError(typeLoc, "invalid tensor element type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700433
MLIR Team355ec862018-06-23 18:09:09 -0700434 if (isUnranked)
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700435 return builder.getTensorType(elementType);
436 return builder.getTensorType(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700437}
438
439/// Parse a memref type.
440///
441/// memref-type ::= `memref` `<` dimension-list-ranked element-type
442/// (`,` semi-affine-map-composition)? (`,` memory-space)? `>`
443///
444/// semi-affine-map-composition ::= (semi-affine-map `,` )* semi-affine-map
445/// memory-space ::= integer-literal /* | TODO: address-space-id */
446///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700447Type *Parser::parseMemRefType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700448 consumeToken(Token::kw_memref);
449
Chris Lattnerf7702a62018-07-23 17:30:01 -0700450 if (parseToken(Token::less, "expected '<' in memref type"))
451 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700452
453 SmallVector<int, 4> dimensions;
454 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700455 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700456
457 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700458 auto typeLoc = getToken().getLoc();
459 auto *elementType = parseType();
Chris Lattnerf7e22732018-06-22 22:03:48 -0700460 if (!elementType)
461 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700462
Chris Lattnerc3251192018-07-27 13:09:58 -0700463 if (!isa<IntegerType>(elementType) && !isa<FloatType>(elementType) &&
464 !isa<VectorType>(elementType))
465 return (emitError(typeLoc, "invalid memref element type"), nullptr);
466
MLIR Team718c82f2018-07-16 09:45:22 -0700467 // Parse semi-affine-map-composition.
James Molloy0ff71542018-07-23 16:56:32 -0700468 SmallVector<AffineMap *, 2> affineMapComposition;
Chris Lattner413db6a2018-07-25 12:55:50 -0700469 unsigned memorySpace = 0;
MLIR Team718c82f2018-07-16 09:45:22 -0700470 bool parsedMemorySpace = false;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700471
MLIR Team718c82f2018-07-16 09:45:22 -0700472 auto parseElt = [&]() -> ParseResult {
473 if (getToken().is(Token::integer)) {
474 // Parse memory space.
475 if (parsedMemorySpace)
476 return emitError("multiple memory spaces specified in memref type");
477 auto v = getToken().getUnsignedIntegerValue();
478 if (!v.hasValue())
479 return emitError("invalid memory space in memref type");
480 memorySpace = v.getValue();
481 consumeToken(Token::integer);
482 parsedMemorySpace = true;
483 } else {
484 // Parse affine map.
485 if (parsedMemorySpace)
486 return emitError("affine map after memory space in memref type");
James Molloy0ff71542018-07-23 16:56:32 -0700487 auto *affineMap = parseAffineMapReference();
MLIR Team718c82f2018-07-16 09:45:22 -0700488 if (affineMap == nullptr)
489 return ParseFailure;
490 affineMapComposition.push_back(affineMap);
491 }
492 return ParseSuccess;
493 };
494
Chris Lattner413db6a2018-07-25 12:55:50 -0700495 // Parse a list of mappings and address space if present.
496 if (consumeIf(Token::comma)) {
497 // Parse comma separated list of affine maps, followed by memory space.
498 if (parseCommaSeparatedListUntil(Token::greater, parseElt,
499 /*allowEmptyList=*/false)) {
500 return nullptr;
501 }
502 } else {
503 if (parseToken(Token::greater, "expected ',' or '>' in memref type"))
504 return nullptr;
MLIR Team718c82f2018-07-16 09:45:22 -0700505 }
MLIR Team718c82f2018-07-16 09:45:22 -0700506
507 return MemRefType::get(dimensions, elementType, affineMapComposition,
508 memorySpace);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700509}
510
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700511/// Parse a function type.
512///
513/// function-type ::= type-list-parens `->` type-list
514///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700515Type *Parser::parseFunctionType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700516 assert(getToken().is(Token::l_paren));
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700517
Chris Lattnerf7702a62018-07-23 17:30:01 -0700518 SmallVector<Type *, 4> arguments, results;
519 if (parseTypeList(arguments) ||
520 parseToken(Token::arrow, "expected '->' in function type") ||
521 parseTypeList(results))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700522 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700523
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700524 return builder.getFunctionType(arguments, results);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700525}
526
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700527
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
577/// | `[` (attribute-value (`,` attribute-value)*)? `]`
578///
579Attribute *Parser::parseAttribute() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700580 switch (getToken().getKind()) {
Chris Lattner7121b802018-07-04 20:45:39 -0700581 case Token::kw_true:
582 consumeToken(Token::kw_true);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700583 return builder.getBoolAttr(true);
Chris Lattner7121b802018-07-04 20:45:39 -0700584 case Token::kw_false:
585 consumeToken(Token::kw_false);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700586 return builder.getBoolAttr(false);
Chris Lattner7121b802018-07-04 20:45:39 -0700587
Jacques Pienaar84491092018-07-31 17:15:15 -0700588 case Token::floatliteral: {
589 auto val = getToken().getFloatingPointValue();
590 if (!val.hasValue())
591 return (emitError("floating point value too large for attribute"),
592 nullptr);
593 consumeToken(Token::floatliteral);
594 return builder.getFloatAttr(val.getValue());
595 }
Chris Lattner7121b802018-07-04 20:45:39 -0700596 case Token::integer: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700597 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700598 if (!val.hasValue() || (int64_t)val.getValue() < 0)
599 return (emitError("integer too large for attribute"), nullptr);
600 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700601 return builder.getIntegerAttr((int64_t)val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700602 }
603
604 case Token::minus: {
605 consumeToken(Token::minus);
Chris Lattner48af7d12018-07-09 19:05:38 -0700606 if (getToken().is(Token::integer)) {
607 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700608 if (!val.hasValue() || (int64_t)-val.getValue() >= 0)
609 return (emitError("integer too large for attribute"), nullptr);
610 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700611 return builder.getIntegerAttr((int64_t)-val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700612 }
Jacques Pienaar84491092018-07-31 17:15:15 -0700613 if (getToken().is(Token::floatliteral)) {
614 auto val = getToken().getFloatingPointValue();
615 if (!val.hasValue())
616 return (emitError("floating point value too large for attribute"),
617 nullptr);
618 consumeToken(Token::floatliteral);
619 return builder.getFloatAttr(-val.getValue());
620 }
Chris Lattner7121b802018-07-04 20:45:39 -0700621
622 return (emitError("expected constant integer or floating point value"),
623 nullptr);
624 }
625
626 case Token::string: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700627 auto val = getToken().getStringValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700628 consumeToken(Token::string);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700629 return builder.getStringAttr(val);
Chris Lattner7121b802018-07-04 20:45:39 -0700630 }
631
Chris Lattner85ee1512018-07-25 11:15:20 -0700632 case Token::l_square: {
633 consumeToken(Token::l_square);
James Molloy0ff71542018-07-23 16:56:32 -0700634 SmallVector<Attribute *, 4> elements;
Chris Lattner7121b802018-07-04 20:45:39 -0700635
636 auto parseElt = [&]() -> ParseResult {
637 elements.push_back(parseAttribute());
638 return elements.back() ? ParseSuccess : ParseFailure;
639 };
640
Chris Lattner85ee1512018-07-25 11:15:20 -0700641 if (parseCommaSeparatedListUntil(Token::r_square, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700642 return nullptr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700643 return builder.getArrayAttr(elements);
Chris Lattner7121b802018-07-04 20:45:39 -0700644 }
645 default:
MLIR Teamb61885d2018-07-18 16:29:21 -0700646 // Try to parse affine map reference.
James Molloy0ff71542018-07-23 16:56:32 -0700647 auto *affineMap = parseAffineMapReference();
MLIR Teamb61885d2018-07-18 16:29:21 -0700648 if (affineMap != nullptr)
649 return builder.getAffineMapAttr(affineMap);
650
Chris Lattner7121b802018-07-04 20:45:39 -0700651 return (emitError("expected constant attribute value"), nullptr);
652 }
653}
654
Chris Lattner7121b802018-07-04 20:45:39 -0700655/// Attribute dictionary.
656///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700657/// attribute-dict ::= `{` `}`
658/// | `{` attribute-entry (`,` attribute-entry)* `}`
659/// attribute-entry ::= bare-id `:` attribute-value
Chris Lattner7121b802018-07-04 20:45:39 -0700660///
James Molloy0ff71542018-07-23 16:56:32 -0700661ParseResult
662Parser::parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes) {
Chris Lattner7121b802018-07-04 20:45:39 -0700663 consumeToken(Token::l_brace);
664
665 auto parseElt = [&]() -> ParseResult {
666 // We allow keywords as attribute names.
Chris Lattner48af7d12018-07-09 19:05:38 -0700667 if (getToken().isNot(Token::bare_identifier, Token::inttype) &&
668 !getToken().isKeyword())
Chris Lattner7121b802018-07-04 20:45:39 -0700669 return emitError("expected attribute name");
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700670 auto nameId = builder.getIdentifier(getTokenSpelling());
Chris Lattner7121b802018-07-04 20:45:39 -0700671 consumeToken();
672
Chris Lattnerf7702a62018-07-23 17:30:01 -0700673 if (parseToken(Token::colon, "expected ':' in attribute list"))
674 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700675
676 auto attr = parseAttribute();
James Molloy0ff71542018-07-23 16:56:32 -0700677 if (!attr)
678 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700679
680 attributes.push_back({nameId, attr});
681 return ParseSuccess;
682 };
683
Chris Lattner40746442018-07-21 14:32:09 -0700684 if (parseCommaSeparatedListUntil(Token::r_brace, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700685 return ParseFailure;
686
687 return ParseSuccess;
688}
689
690//===----------------------------------------------------------------------===//
MLIR Teamf85a6262018-06-27 11:03:08 -0700691// Polyhedral structures.
692//===----------------------------------------------------------------------===//
693
Chris Lattner2e595eb2018-07-10 10:08:27 -0700694/// Lower precedence ops (all at the same precedence level). LNoOp is false in
695/// the boolean sense.
696enum AffineLowPrecOp {
697 /// Null value.
698 LNoOp,
699 Add,
700 Sub
701};
MLIR Teamf85a6262018-06-27 11:03:08 -0700702
Chris Lattner2e595eb2018-07-10 10:08:27 -0700703/// Higher precedence ops - all at the same precedence level. HNoOp is false in
704/// the boolean sense.
705enum AffineHighPrecOp {
706 /// Null value.
707 HNoOp,
708 Mul,
709 FloorDiv,
710 CeilDiv,
711 Mod
712};
Chris Lattner7121b802018-07-04 20:45:39 -0700713
Chris Lattner2e595eb2018-07-10 10:08:27 -0700714namespace {
715/// This is a specialized parser for AffineMap's, maintaining the state
716/// transient to their bodies.
717class AffineMapParser : public Parser {
718public:
719 explicit AffineMapParser(ParserState &state) : Parser(state) {}
Chris Lattner7121b802018-07-04 20:45:39 -0700720
Chris Lattner2e595eb2018-07-10 10:08:27 -0700721 AffineMap *parseAffineMapInline();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700722
Chris Lattner2e595eb2018-07-10 10:08:27 -0700723private:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700724 // Binary affine op parsing.
725 AffineLowPrecOp consumeIfLowPrecOp();
726 AffineHighPrecOp consumeIfHighPrecOp();
MLIR Teamf85a6262018-06-27 11:03:08 -0700727
Chris Lattner2e595eb2018-07-10 10:08:27 -0700728 // Identifier lists for polyhedral structures.
Chris Lattner413db6a2018-07-25 12:55:50 -0700729 ParseResult parseDimIdList(unsigned &numDims);
730 ParseResult parseSymbolIdList(unsigned &numSymbols);
731 ParseResult parseIdentifierDefinition(AffineExpr *idExpr);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700732
733 AffineExpr *parseAffineExpr();
734 AffineExpr *parseParentheticalExpr();
735 AffineExpr *parseNegateExpression(AffineExpr *lhs);
736 AffineExpr *parseIntegerExpr();
737 AffineExpr *parseBareIdExpr();
738
739 AffineExpr *getBinaryAffineOpExpr(AffineHighPrecOp op, AffineExpr *lhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700740 AffineExpr *rhs, SMLoc opLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700741 AffineExpr *getBinaryAffineOpExpr(AffineLowPrecOp op, AffineExpr *lhs,
742 AffineExpr *rhs);
743 AffineExpr *parseAffineOperandExpr(AffineExpr *lhs);
744 AffineExpr *parseAffineLowPrecOpExpr(AffineExpr *llhs,
745 AffineLowPrecOp llhsOp);
746 AffineExpr *parseAffineHighPrecOpExpr(AffineExpr *llhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700747 AffineHighPrecOp llhsOp,
748 SMLoc llhsOpLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700749
750private:
Chris Lattner413db6a2018-07-25 12:55:50 -0700751 SmallVector<std::pair<StringRef, AffineExpr *>, 4> dimsAndSymbols;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700752};
753} // end anonymous namespace
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700754
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700755/// Create an affine binary high precedence op expression (mul's, div's, mod).
756/// opLoc is the location of the op token to be used to report errors
757/// for non-conforming expressions.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700758AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineHighPrecOp op,
759 AffineExpr *lhs,
Chris Lattner40746442018-07-21 14:32:09 -0700760 AffineExpr *rhs,
761 SMLoc opLoc) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700762 // TODO: make the error location info accurate.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700763 switch (op) {
764 case Mul:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700765 if (!lhs->isSymbolicOrConstant() && !rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700766 emitError(opLoc, "non-affine expression: at least one of the multiply "
767 "operands has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700768 return nullptr;
769 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700770 return builder.getMulExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700771 case FloorDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700772 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700773 emitError(opLoc, "non-affine expression: right operand of floordiv "
774 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700775 return nullptr;
776 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700777 return builder.getFloorDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700778 case CeilDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700779 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700780 emitError(opLoc, "non-affine expression: right operand of ceildiv "
781 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700782 return nullptr;
783 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700784 return builder.getCeilDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700785 case Mod:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700786 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700787 emitError(opLoc, "non-affine expression: right operand of mod "
788 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700789 return nullptr;
790 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700791 return builder.getModExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700792 case HNoOp:
793 llvm_unreachable("can't create affine expression for null high prec op");
794 return nullptr;
795 }
796}
797
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700798/// Create an affine binary low precedence op expression (add, sub).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700799AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineLowPrecOp op,
800 AffineExpr *lhs,
801 AffineExpr *rhs) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700802 switch (op) {
803 case AffineLowPrecOp::Add:
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700804 return builder.getAddExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700805 case AffineLowPrecOp::Sub:
Uday Bondhugulac1faf662018-07-19 14:08:50 -0700806 return builder.getAddExpr(
807 lhs, builder.getMulExpr(rhs, builder.getConstantExpr(-1)));
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700808 case AffineLowPrecOp::LNoOp:
809 llvm_unreachable("can't create affine expression for null low prec op");
810 return nullptr;
811 }
812}
813
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700814/// Consume this token if it is a lower precedence affine op (there are only two
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700815/// precedence levels).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700816AffineLowPrecOp AffineMapParser::consumeIfLowPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700817 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700818 case Token::plus:
819 consumeToken(Token::plus);
820 return AffineLowPrecOp::Add;
821 case Token::minus:
822 consumeToken(Token::minus);
823 return AffineLowPrecOp::Sub;
824 default:
825 return AffineLowPrecOp::LNoOp;
826 }
827}
828
829/// Consume this token if it is a higher precedence affine op (there are only
830/// two precedence levels)
Chris Lattner2e595eb2018-07-10 10:08:27 -0700831AffineHighPrecOp AffineMapParser::consumeIfHighPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700832 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700833 case Token::star:
834 consumeToken(Token::star);
835 return Mul;
836 case Token::kw_floordiv:
837 consumeToken(Token::kw_floordiv);
838 return FloorDiv;
839 case Token::kw_ceildiv:
840 consumeToken(Token::kw_ceildiv);
841 return CeilDiv;
842 case Token::kw_mod:
843 consumeToken(Token::kw_mod);
844 return Mod;
845 default:
846 return HNoOp;
847 }
848}
849
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700850/// Parse a high precedence op expression list: mul, div, and mod are high
851/// precedence binary ops, i.e., parse a
852/// expr_1 op_1 expr_2 op_2 ... expr_n
853/// where op_1, op_2 are all a AffineHighPrecOp (mul, div, mod).
854/// All affine binary ops are left associative.
855/// Given llhs, returns (llhs llhsOp lhs) op rhs, or (lhs op rhs) if llhs is
856/// null. If no rhs can be found, returns (llhs llhsOp lhs) or lhs if llhs is
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700857/// null. llhsOpLoc is the location of the llhsOp token that will be used to
858/// report an error for non-conforming expressions.
859AffineExpr *AffineMapParser::parseAffineHighPrecOpExpr(AffineExpr *llhs,
860 AffineHighPrecOp llhsOp,
861 SMLoc llhsOpLoc) {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700862 AffineExpr *lhs = parseAffineOperandExpr(llhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700863 if (!lhs)
864 return nullptr;
865
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700866 // Found an LHS. Parse the remaining expression.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700867 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -0700868 if (AffineHighPrecOp op = consumeIfHighPrecOp()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700869 if (llhs) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700870 AffineExpr *expr = getBinaryAffineOpExpr(llhsOp, llhs, lhs, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700871 if (!expr)
872 return nullptr;
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700873 return parseAffineHighPrecOpExpr(expr, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700874 }
875 // No LLHS, get RHS
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700876 return parseAffineHighPrecOpExpr(lhs, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700877 }
878
879 // This is the last operand in this expression.
880 if (llhs)
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700881 return getBinaryAffineOpExpr(llhsOp, llhs, lhs, llhsOpLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700882
883 // No llhs, 'lhs' itself is the expression.
884 return lhs;
885}
886
887/// Parse an affine expression inside parentheses.
888///
889/// affine-expr ::= `(` affine-expr `)`
Chris Lattner2e595eb2018-07-10 10:08:27 -0700890AffineExpr *AffineMapParser::parseParentheticalExpr() {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700891 if (parseToken(Token::l_paren, "expected '('"))
892 return nullptr;
Chris Lattner48af7d12018-07-09 19:05:38 -0700893 if (getToken().is(Token::r_paren))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700894 return (emitError("no expression inside parentheses"), nullptr);
Chris Lattnerf7702a62018-07-23 17:30:01 -0700895
Chris Lattner2e595eb2018-07-10 10:08:27 -0700896 auto *expr = parseAffineExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700897 if (!expr)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700898 return nullptr;
Chris Lattnerf7702a62018-07-23 17:30:01 -0700899 if (parseToken(Token::r_paren, "expected ')'"))
900 return nullptr;
901
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700902 return expr;
903}
904
905/// Parse the negation expression.
906///
907/// affine-expr ::= `-` affine-expr
Chris Lattner2e595eb2018-07-10 10:08:27 -0700908AffineExpr *AffineMapParser::parseNegateExpression(AffineExpr *lhs) {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700909 if (parseToken(Token::minus, "expected '-'"))
910 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700911
Chris Lattner2e595eb2018-07-10 10:08:27 -0700912 AffineExpr *operand = parseAffineOperandExpr(lhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700913 // Since negation has the highest precedence of all ops (including high
914 // precedence ops) but lower than parentheses, we are only going to use
915 // parseAffineOperandExpr instead of parseAffineExpr here.
916 if (!operand)
917 // Extra error message although parseAffineOperandExpr would have
918 // complained. Leads to a better diagnostic.
919 return (emitError("missing operand of negation"), nullptr);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700920 auto *minusOne = builder.getConstantExpr(-1);
921 return builder.getMulExpr(minusOne, operand);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700922}
923
924/// Parse a bare id that may appear in an affine expression.
925///
926/// affine-expr ::= bare-id
Chris Lattner2e595eb2018-07-10 10:08:27 -0700927AffineExpr *AffineMapParser::parseBareIdExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700928 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700929 return (emitError("expected bare identifier"), nullptr);
930
Chris Lattner48af7d12018-07-09 19:05:38 -0700931 StringRef sRef = getTokenSpelling();
Chris Lattner413db6a2018-07-25 12:55:50 -0700932 for (auto entry : dimsAndSymbols) {
Chris Lattnera8e47672018-07-25 14:08:16 -0700933 if (entry.first == sRef) {
934 consumeToken(Token::bare_identifier);
935 return entry.second;
936 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700937 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700938
939 return (emitError("use of undeclared identifier"), nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700940}
941
942/// Parse a positive integral constant appearing in an affine expression.
943///
944/// affine-expr ::= integer-literal
Chris Lattner2e595eb2018-07-10 10:08:27 -0700945AffineExpr *AffineMapParser::parseIntegerExpr() {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700946 // No need to handle negative numbers separately here. They are naturally
947 // handled via the unary negation operator, although (FIXME) MININT_64 still
948 // not correctly handled.
Chris Lattner48af7d12018-07-09 19:05:38 -0700949 if (getToken().isNot(Token::integer))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700950 return (emitError("expected integer"), nullptr);
951
Chris Lattner48af7d12018-07-09 19:05:38 -0700952 auto val = getToken().getUInt64IntegerValue();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700953 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
954 return (emitError("constant too large for affineint"), nullptr);
955 }
956 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700957 return builder.getConstantExpr((int64_t)val.getValue());
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700958}
959
960/// Parses an expression that can be a valid operand of an affine expression.
Uday Bondhugula76345202018-07-09 13:47:52 -0700961/// lhs: if non-null, lhs is an affine expression that is the lhs of a binary
962/// operator, the rhs of which is being parsed. This is used to determine
963/// whether an error should be emitted for a missing right operand.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700964// Eg: for an expression without parentheses (like i + j + k + l), each
965// of the four identifiers is an operand. For i + j*k + l, j*k is not an
966// operand expression, it's an op expression and will be parsed via
967// parseAffineHighPrecOpExpression(). However, for i + (j*k) + -l, (j*k) and -l
968// are valid operands that will be parsed by this function.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700969AffineExpr *AffineMapParser::parseAffineOperandExpr(AffineExpr *lhs) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700970 switch (getToken().getKind()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700971 case Token::bare_identifier:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700972 return parseBareIdExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700973 case Token::integer:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700974 return parseIntegerExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700975 case Token::l_paren:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700976 return parseParentheticalExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700977 case Token::minus:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700978 return parseNegateExpression(lhs);
Uday Bondhugula76345202018-07-09 13:47:52 -0700979 case Token::kw_ceildiv:
980 case Token::kw_floordiv:
981 case Token::kw_mod:
982 case Token::plus:
983 case Token::star:
984 if (lhs)
985 emitError("missing right operand of binary operator");
986 else
987 emitError("missing left operand of binary operator");
988 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700989 default:
990 if (lhs)
Uday Bondhugula76345202018-07-09 13:47:52 -0700991 emitError("missing right operand of binary operator");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700992 else
993 emitError("expected affine expression");
994 return nullptr;
995 }
996}
997
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700998/// Parse affine expressions that are bare-id's, integer constants,
999/// parenthetical affine expressions, and affine op expressions that are a
1000/// composition of those.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001001///
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001002/// All binary op's associate from left to right.
1003///
1004/// {add, sub} have lower precedence than {mul, div, and mod}.
1005///
Uday Bondhugula76345202018-07-09 13:47:52 -07001006/// Add, sub'are themselves at the same precedence level. Mul, floordiv,
1007/// ceildiv, and mod are at the same higher precedence level. Negation has
1008/// higher precedence than any binary op.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001009///
1010/// llhs: the affine expression appearing on the left of the one being parsed.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001011/// This function will return ((llhs llhsOp lhs) op rhs) if llhs is non null,
1012/// and lhs op rhs otherwise; if there is no rhs, llhs llhsOp lhs is returned if
1013/// llhs is non-null; otherwise lhs is returned. This is to deal with left
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001014/// associativity.
1015///
1016/// Eg: when the expression is e1 + e2*e3 + e4, with e1 as llhs, this function
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001017/// will return the affine expr equivalent of (e1 + (e2*e3)) + e4, where (e2*e3)
1018/// will be parsed using parseAffineHighPrecOpExpr().
Chris Lattner2e595eb2018-07-10 10:08:27 -07001019AffineExpr *AffineMapParser::parseAffineLowPrecOpExpr(AffineExpr *llhs,
1020 AffineLowPrecOp llhsOp) {
Uday Bondhugula76345202018-07-09 13:47:52 -07001021 AffineExpr *lhs;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001022 if (!(lhs = parseAffineOperandExpr(llhs)))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001023 return nullptr;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001024
1025 // Found an LHS. Deal with the ops.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001026 if (AffineLowPrecOp lOp = consumeIfLowPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001027 if (llhs) {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001028 AffineExpr *sum = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001029 return parseAffineLowPrecOpExpr(sum, lOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001030 }
1031 // No LLHS, get RHS and form the expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001032 return parseAffineLowPrecOpExpr(lhs, lOp);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001033 }
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001034 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07001035 if (AffineHighPrecOp hOp = consumeIfHighPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001036 // We have a higher precedence op here. Get the rhs operand for the llhs
1037 // through parseAffineHighPrecOpExpr.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001038 AffineExpr *highRes = parseAffineHighPrecOpExpr(lhs, hOp, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001039 if (!highRes)
1040 return nullptr;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001041
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001042 // If llhs is null, the product forms the first operand of the yet to be
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001043 // found expression. If non-null, the op to associate with llhs is llhsOp.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001044 AffineExpr *expr =
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001045 llhs ? getBinaryAffineOpExpr(llhsOp, llhs, highRes) : highRes;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001046
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001047 // Recurse for subsequent low prec op's after the affine high prec op
1048 // expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001049 if (AffineLowPrecOp nextOp = consumeIfLowPrecOp())
1050 return parseAffineLowPrecOpExpr(expr, nextOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001051 return expr;
1052 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001053 // Last operand in the expression list.
1054 if (llhs)
1055 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
1056 // No llhs, 'lhs' itself is the expression.
1057 return lhs;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001058}
1059
1060/// Parse an affine expression.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001061/// affine-expr ::= `(` affine-expr `)`
1062/// | `-` affine-expr
1063/// | affine-expr `+` affine-expr
1064/// | affine-expr `-` affine-expr
1065/// | affine-expr `*` affine-expr
1066/// | affine-expr `floordiv` affine-expr
1067/// | affine-expr `ceildiv` affine-expr
1068/// | affine-expr `mod` affine-expr
1069/// | bare-id
1070/// | integer-literal
1071///
1072/// Additional conditions are checked depending on the production. For eg., one
1073/// of the operands for `*` has to be either constant/symbolic; the second
1074/// operand for floordiv, ceildiv, and mod has to be a positive integer.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001075AffineExpr *AffineMapParser::parseAffineExpr() {
1076 return parseAffineLowPrecOpExpr(nullptr, AffineLowPrecOp::LNoOp);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001077}
1078
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001079/// Parse a dim or symbol from the lists appearing before the actual expressions
Chris Lattner2e595eb2018-07-10 10:08:27 -07001080/// of the affine map. Update our state to store the dimensional/symbolic
Chris Lattner413db6a2018-07-25 12:55:50 -07001081/// identifier.
1082ParseResult AffineMapParser::parseIdentifierDefinition(AffineExpr *idExpr) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001083 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001084 return emitError("expected bare identifier");
Chris Lattner413db6a2018-07-25 12:55:50 -07001085
1086 auto name = getTokenSpelling();
1087 for (auto entry : dimsAndSymbols) {
1088 if (entry.first == name)
1089 return emitError("redefinition of identifier '" + Twine(name) + "'");
1090 }
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001091 consumeToken(Token::bare_identifier);
Chris Lattner413db6a2018-07-25 12:55:50 -07001092
1093 dimsAndSymbols.push_back({name, idExpr});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001094 return ParseSuccess;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001095}
1096
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001097/// Parse the list of symbolic identifiers to an affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001098ParseResult AffineMapParser::parseSymbolIdList(unsigned &numSymbols) {
1099 consumeToken(Token::l_square);
1100 auto parseElt = [&]() -> ParseResult {
1101 auto *symbol = AffineSymbolExpr::get(numSymbols++, getContext());
1102 return parseIdentifierDefinition(symbol);
1103 };
Chris Lattner85ee1512018-07-25 11:15:20 -07001104 return parseCommaSeparatedListUntil(Token::r_square, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001105}
1106
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001107/// Parse the list of dimensional identifiers to an affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001108ParseResult AffineMapParser::parseDimIdList(unsigned &numDims) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07001109 if (parseToken(Token::l_paren,
1110 "expected '(' at start of dimensional identifiers list"))
1111 return ParseFailure;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001112
Chris Lattner413db6a2018-07-25 12:55:50 -07001113 auto parseElt = [&]() -> ParseResult {
1114 auto *dimension = AffineDimExpr::get(numDims++, getContext());
1115 return parseIdentifierDefinition(dimension);
1116 };
Chris Lattner40746442018-07-21 14:32:09 -07001117 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001118}
1119
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001120/// Parse an affine map definition.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001121///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001122/// affine-map-inline ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
1123/// (`size` `(` dim-size (`,` dim-size)* `)`)?
1124/// dim-size ::= affine-expr | `min` `(` affine-expr ( `,` affine-expr)+ `)`
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001125///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001126/// multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner2e595eb2018-07-10 10:08:27 -07001127AffineMap *AffineMapParser::parseAffineMapInline() {
Chris Lattner413db6a2018-07-25 12:55:50 -07001128 unsigned numDims = 0, numSymbols = 0;
1129
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001130 // List of dimensional identifiers.
Chris Lattner413db6a2018-07-25 12:55:50 -07001131 if (parseDimIdList(numDims))
Chris Lattner7121b802018-07-04 20:45:39 -07001132 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001133
1134 // Symbols are optional.
Chris Lattner85ee1512018-07-25 11:15:20 -07001135 if (getToken().is(Token::l_square)) {
Chris Lattner413db6a2018-07-25 12:55:50 -07001136 if (parseSymbolIdList(numSymbols))
Chris Lattner7121b802018-07-04 20:45:39 -07001137 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001138 }
Chris Lattnerf7702a62018-07-23 17:30:01 -07001139
1140 if (parseToken(Token::arrow, "expected '->' or '['") ||
1141 parseToken(Token::l_paren, "expected '(' at start of affine map range"))
Chris Lattner7121b802018-07-04 20:45:39 -07001142 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001143
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001144 SmallVector<AffineExpr *, 4> exprs;
1145 auto parseElt = [&]() -> ParseResult {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001146 auto *elt = parseAffineExpr();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001147 ParseResult res = elt ? ParseSuccess : ParseFailure;
1148 exprs.push_back(elt);
1149 return res;
1150 };
1151
1152 // Parse a multi-dimensional affine expression (a comma-separated list of 1-d
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001153 // affine expressions); the list cannot be empty.
1154 // Grammar: multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner40746442018-07-21 14:32:09 -07001155 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt, false))
Chris Lattner7121b802018-07-04 20:45:39 -07001156 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001157
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001158 // Parse optional range sizes.
Uday Bondhugula1e500b42018-07-12 18:04:04 -07001159 // range-sizes ::= (`size` `(` dim-size (`,` dim-size)* `)`)?
1160 // dim-size ::= affine-expr | `min` `(` affine-expr (`,` affine-expr)+ `)`
1161 // TODO(bondhugula): support for min of several affine expressions.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001162 // TODO: check if sizes are non-negative whenever they are constant.
1163 SmallVector<AffineExpr *, 4> rangeSizes;
1164 if (consumeIf(Token::kw_size)) {
1165 // Location of the l_paren token (if it exists) for error reporting later.
1166 auto loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001167 if (parseToken(Token::l_paren, "expected '(' at start of affine map range"))
1168 return nullptr;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001169
1170 auto parseRangeSize = [&]() -> ParseResult {
Chris Lattner413db6a2018-07-25 12:55:50 -07001171 auto loc = getToken().getLoc();
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001172 auto *elt = parseAffineExpr();
Chris Lattner413db6a2018-07-25 12:55:50 -07001173 if (!elt)
1174 return ParseFailure;
1175
1176 if (!elt->isSymbolicOrConstant())
1177 return emitError(loc,
1178 "size expressions cannot refer to dimension values");
1179
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001180 rangeSizes.push_back(elt);
Chris Lattner413db6a2018-07-25 12:55:50 -07001181 return ParseSuccess;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001182 };
1183
Chris Lattner40746442018-07-21 14:32:09 -07001184 if (parseCommaSeparatedListUntil(Token::r_paren, parseRangeSize, false))
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001185 return nullptr;
1186 if (exprs.size() > rangeSizes.size())
1187 return (emitError(loc, "fewer range sizes than range expressions"),
1188 nullptr);
1189 if (exprs.size() < rangeSizes.size())
1190 return (emitError(loc, "more range sizes than range expressions"),
1191 nullptr);
1192 }
1193
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001194 // Parsed a valid affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001195 return builder.getAffineMap(numDims, numSymbols, exprs, rangeSizes);
MLIR Teamf85a6262018-06-27 11:03:08 -07001196}
1197
Chris Lattner2e595eb2018-07-10 10:08:27 -07001198AffineMap *Parser::parseAffineMapInline() {
1199 return AffineMapParser(state).parseAffineMapInline();
1200}
1201
MLIR Team718c82f2018-07-16 09:45:22 -07001202AffineMap *Parser::parseAffineMapReference() {
1203 if (getToken().is(Token::hash_identifier)) {
1204 // Parse affine map identifier and verify that it exists.
1205 StringRef affineMapId = getTokenSpelling().drop_front();
1206 if (getState().affineMapDefinitions.count(affineMapId) == 0)
1207 return (emitError("undefined affine map id '" + affineMapId + "'"),
1208 nullptr);
1209 consumeToken(Token::hash_identifier);
1210 return getState().affineMapDefinitions[affineMapId];
1211 }
1212 // Try to parse inline affine map.
1213 return parseAffineMapInline();
1214}
1215
MLIR Teamf85a6262018-06-27 11:03:08 -07001216//===----------------------------------------------------------------------===//
Chris Lattner7f9cc272018-07-19 08:35:28 -07001217// FunctionParser
Chris Lattner4c95a502018-06-23 16:03:42 -07001218//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001219
Chris Lattner7f9cc272018-07-19 08:35:28 -07001220namespace {
1221/// This class contains parser state that is common across CFG and ML functions,
1222/// notably for dealing with operations and SSA values.
1223class FunctionParser : public Parser {
1224public:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001225 enum class Kind { CFGFunc, MLFunc };
1226
1227 Kind getKind() const { return kind; }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001228
Chris Lattner6119d382018-07-20 18:41:34 -07001229 /// After the function is finished parsing, this function checks to see if
1230 /// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001231 ParseResult finalizeFunction(Function *func, SMLoc loc);
Chris Lattner6119d382018-07-20 18:41:34 -07001232
1233 /// This represents a use of an SSA value in the program. The first two
1234 /// entries in the tuple are the name and result number of a reference. The
1235 /// third is the location of the reference, which is used in case this ends up
1236 /// being a use of an undefined value.
1237 struct SSAUseInfo {
1238 StringRef name; // Value name, e.g. %42 or %abc
1239 unsigned number; // Number, specified with #12
1240 SMLoc loc; // Location of first definition or use.
1241 };
Chris Lattner7f9cc272018-07-19 08:35:28 -07001242
1243 /// Given a reference to an SSA value and its type, return a reference. This
1244 /// returns null on failure.
1245 SSAValue *resolveSSAUse(SSAUseInfo useInfo, Type *type);
1246
1247 /// Register a definition of a value with the symbol table.
1248 ParseResult addDefinition(SSAUseInfo useInfo, SSAValue *value);
1249
1250 // SSA parsing productions.
1251 ParseResult parseSSAUse(SSAUseInfo &result);
Chris Lattner40746442018-07-21 14:32:09 -07001252 ParseResult parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results);
James Molloy61a656c2018-07-22 15:45:24 -07001253
1254 template <typename ResultType>
1255 ResultType parseSSADefOrUseAndType(
1256 const std::function<ResultType(SSAUseInfo, Type *)> &action);
1257
1258 SSAValue *parseSSAUseAndType() {
1259 return parseSSADefOrUseAndType<SSAValue *>(
1260 [&](SSAUseInfo useInfo, Type *type) -> SSAValue * {
1261 return resolveSSAUse(useInfo, type);
1262 });
1263 }
Chris Lattner40746442018-07-21 14:32:09 -07001264
1265 template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001266 ParseResult
Chris Lattner2c402672018-07-23 11:56:17 -07001267 parseOptionalSSAUseAndTypeList(SmallVectorImpl<ValueTy *> &results,
1268 bool isParenthesized);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001269
1270 // Operations
1271 ParseResult parseOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner85ee1512018-07-25 11:15:20 -07001272 Operation *parseVerboseOperation(const CreateOperationFunction &createOpFunc);
1273 Operation *parseCustomOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001274
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001275protected:
1276 FunctionParser(ParserState &state, Kind kind) : Parser(state), kind(kind) {}
1277
Chris Lattner7f9cc272018-07-19 08:35:28 -07001278private:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001279 /// Kind indicates if this is CFG or ML function parser.
1280 Kind kind;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001281 /// This keeps track of all of the SSA values we are tracking, indexed by
Chris Lattner6119d382018-07-20 18:41:34 -07001282 /// their name. This has one entry per result number.
1283 llvm::StringMap<SmallVector<std::pair<SSAValue *, SMLoc>, 1>> values;
1284
1285 /// These are all of the placeholders we've made along with the location of
1286 /// their first reference, to allow checking for use of undefined values.
1287 DenseMap<SSAValue *, SMLoc> forwardReferencePlaceholders;
1288
1289 SSAValue *createForwardReferencePlaceholder(SMLoc loc, Type *type);
1290
1291 /// Return true if this is a forward reference.
1292 bool isForwardReferencePlaceholder(SSAValue *value) {
1293 return forwardReferencePlaceholders.count(value);
1294 }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001295};
1296} // end anonymous namespace
1297
Chris Lattner6119d382018-07-20 18:41:34 -07001298/// Create and remember a new placeholder for a forward reference.
1299SSAValue *FunctionParser::createForwardReferencePlaceholder(SMLoc loc,
1300 Type *type) {
1301 // Forward references are always created as instructions, even in ML
1302 // functions, because we just need something with a def/use chain.
1303 //
1304 // We create these placeholders as having an empty name, which we know cannot
1305 // be created through normal user input, allowing us to distinguish them.
1306 auto name = Identifier::get("placeholder", getContext());
1307 auto *inst = OperationInst::create(name, /*operands*/ {}, type, /*attrs*/ {},
1308 getContext());
1309 forwardReferencePlaceholders[inst->getResult(0)] = loc;
1310 return inst->getResult(0);
1311}
1312
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001313/// Given an unbound reference to an SSA value and its type, return the value
Chris Lattner7f9cc272018-07-19 08:35:28 -07001314/// it specifies. This returns null on failure.
1315SSAValue *FunctionParser::resolveSSAUse(SSAUseInfo useInfo, Type *type) {
Chris Lattner6119d382018-07-20 18:41:34 -07001316 auto &entries = values[useInfo.name];
1317
Chris Lattner7f9cc272018-07-19 08:35:28 -07001318 // If we have already seen a value of this name, return it.
Chris Lattner6119d382018-07-20 18:41:34 -07001319 if (useInfo.number < entries.size() && entries[useInfo.number].first) {
1320 auto *result = entries[useInfo.number].first;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001321 // Check that the type matches the other uses.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001322 if (result->getType() == type)
1323 return result;
1324
Chris Lattner6119d382018-07-20 18:41:34 -07001325 emitError(useInfo.loc, "use of value '" + useInfo.name.str() +
1326 "' expects different type than prior uses");
1327 emitError(entries[useInfo.number].second, "prior use here");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001328 return nullptr;
1329 }
1330
Chris Lattner6119d382018-07-20 18:41:34 -07001331 // Make sure we have enough slots for this.
1332 if (entries.size() <= useInfo.number)
1333 entries.resize(useInfo.number + 1);
1334
1335 // If the value has already been defined and this is an overly large result
1336 // number, diagnose that.
1337 if (entries[0].first && !isForwardReferencePlaceholder(entries[0].first))
1338 return (emitError(useInfo.loc, "reference to invalid result number"),
1339 nullptr);
1340
Tatiana Shpeismand880b352018-07-31 23:14:16 -07001341 // Otherwise, this is a forward reference. If we are in ML function return
1342 // an error. In CFG function, create a placeholder and remember
1343 // that we did so.
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001344 if (getKind() == Kind::MLFunc)
1345 return (
1346 emitError(useInfo.loc, "use of undefined SSA value " + useInfo.name),
1347 nullptr);
1348
Chris Lattner6119d382018-07-20 18:41:34 -07001349 auto *result = createForwardReferencePlaceholder(useInfo.loc, type);
1350 entries[useInfo.number].first = result;
1351 entries[useInfo.number].second = useInfo.loc;
1352 return result;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001353}
1354
1355/// Register a definition of a value with the symbol table.
1356ParseResult FunctionParser::addDefinition(SSAUseInfo useInfo, SSAValue *value) {
Chris Lattner6119d382018-07-20 18:41:34 -07001357 auto &entries = values[useInfo.name];
Chris Lattner7f9cc272018-07-19 08:35:28 -07001358
Chris Lattner6119d382018-07-20 18:41:34 -07001359 // Make sure there is a slot for this value.
1360 if (entries.size() <= useInfo.number)
1361 entries.resize(useInfo.number + 1);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001362
Chris Lattner6119d382018-07-20 18:41:34 -07001363 // If we already have an entry for this, check to see if it was a definition
1364 // or a forward reference.
1365 if (auto *existing = entries[useInfo.number].first) {
1366 if (!isForwardReferencePlaceholder(existing)) {
1367 emitError(useInfo.loc,
1368 "redefinition of SSA value '" + useInfo.name + "'");
1369 return emitError(entries[useInfo.number].second,
1370 "previously defined here");
1371 }
1372
1373 // If it was a forward reference, update everything that used it to use the
1374 // actual definition instead, delete the forward ref, and remove it from our
1375 // set of forward references we track.
1376 existing->replaceAllUsesWith(value);
1377 existing->getDefiningInst()->destroy();
1378 forwardReferencePlaceholders.erase(existing);
1379 }
1380
1381 entries[useInfo.number].first = value;
1382 entries[useInfo.number].second = useInfo.loc;
1383 return ParseSuccess;
1384}
1385
1386/// After the function is finished parsing, this function checks to see if
1387/// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001388ParseResult FunctionParser::finalizeFunction(Function *func, SMLoc loc) {
Chris Lattner6119d382018-07-20 18:41:34 -07001389 // Check for any forward references that are left. If we find any, error out.
1390 if (!forwardReferencePlaceholders.empty()) {
1391 SmallVector<std::pair<const char *, SSAValue *>, 4> errors;
1392 // Iteration over the map isn't determinstic, so sort by source location.
1393 for (auto entry : forwardReferencePlaceholders)
1394 errors.push_back({entry.second.getPointer(), entry.first});
1395 llvm::array_pod_sort(errors.begin(), errors.end());
1396
1397 for (auto entry : errors)
1398 emitError(SMLoc::getFromPointer(entry.first),
1399 "use of undeclared SSA value name");
1400 return ParseFailure;
1401 }
1402
Chris Lattner40746442018-07-21 14:32:09 -07001403 // Run the verifier on this function. If an error is detected, report it.
1404 std::string errorString;
1405 if (func->verify(&errorString))
1406 return emitError(loc, errorString);
1407
Chris Lattner6119d382018-07-20 18:41:34 -07001408 return ParseSuccess;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001409}
1410
Chris Lattner78276e32018-07-07 15:48:26 -07001411/// Parse a SSA operand for an instruction or statement.
1412///
James Molloy61a656c2018-07-22 15:45:24 -07001413/// ssa-use ::= ssa-id
Chris Lattner78276e32018-07-07 15:48:26 -07001414///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001415ParseResult FunctionParser::parseSSAUse(SSAUseInfo &result) {
Chris Lattner6119d382018-07-20 18:41:34 -07001416 result.name = getTokenSpelling();
1417 result.number = 0;
1418 result.loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001419 if (parseToken(Token::percent_identifier, "expected SSA operand"))
1420 return ParseFailure;
Chris Lattner6119d382018-07-20 18:41:34 -07001421
1422 // If we have an affine map ID, it is a result number.
1423 if (getToken().is(Token::hash_identifier)) {
1424 if (auto value = getToken().getHashIdentifierNumber())
1425 result.number = value.getValue();
1426 else
1427 return emitError("invalid SSA value result number");
1428 consumeToken(Token::hash_identifier);
1429 }
1430
Chris Lattner7f9cc272018-07-19 08:35:28 -07001431 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001432}
1433
1434/// Parse a (possibly empty) list of SSA operands.
1435///
1436/// ssa-use-list ::= ssa-use (`,` ssa-use)*
1437/// ssa-use-list-opt ::= ssa-use-list?
1438///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001439ParseResult
Chris Lattner40746442018-07-21 14:32:09 -07001440FunctionParser::parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results) {
Chris Lattner85ee1512018-07-25 11:15:20 -07001441 if (getToken().isNot(Token::percent_identifier))
Chris Lattner40746442018-07-21 14:32:09 -07001442 return ParseSuccess;
1443 return parseCommaSeparatedList([&]() -> ParseResult {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001444 SSAUseInfo result;
1445 if (parseSSAUse(result))
1446 return ParseFailure;
1447 results.push_back(result);
1448 return ParseSuccess;
1449 });
Chris Lattner78276e32018-07-07 15:48:26 -07001450}
1451
1452/// Parse an SSA use with an associated type.
1453///
1454/// ssa-use-and-type ::= ssa-use `:` type
James Molloy61a656c2018-07-22 15:45:24 -07001455template <typename ResultType>
1456ResultType FunctionParser::parseSSADefOrUseAndType(
1457 const std::function<ResultType(SSAUseInfo, Type *)> &action) {
Chris Lattner78276e32018-07-07 15:48:26 -07001458
Chris Lattnerf7702a62018-07-23 17:30:01 -07001459 SSAUseInfo useInfo;
1460 if (parseSSAUse(useInfo) ||
1461 parseToken(Token::colon, "expected ':' and type for SSA operand"))
1462 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001463
Chris Lattner7f9cc272018-07-19 08:35:28 -07001464 auto *type = parseType();
1465 if (!type)
1466 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001467
James Molloy61a656c2018-07-22 15:45:24 -07001468 return action(useInfo, type);
Chris Lattner78276e32018-07-07 15:48:26 -07001469}
1470
Chris Lattner2c402672018-07-23 11:56:17 -07001471/// Parse a (possibly empty) list of SSA operands, followed by a colon, then
1472/// followed by a type list. If hasParens is true, then the operands are
1473/// surrounded by parens.
Chris Lattner78276e32018-07-07 15:48:26 -07001474///
Chris Lattner2c402672018-07-23 11:56:17 -07001475/// ssa-use-and-type-list[parens]
1476/// ::= `(` ssa-use-list `)` ':' type-list-no-parens
1477///
1478/// ssa-use-and-type-list[!parens]
1479/// ::= ssa-use-list ':' type-list-no-parens
Chris Lattner78276e32018-07-07 15:48:26 -07001480///
Chris Lattner40746442018-07-21 14:32:09 -07001481template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001482ParseResult FunctionParser::parseOptionalSSAUseAndTypeList(
Chris Lattner2c402672018-07-23 11:56:17 -07001483 SmallVectorImpl<ValueTy *> &results, bool isParenthesized) {
1484
1485 // If we are in the parenthesized form and no paren exists, then we succeed
1486 // with an empty list.
1487 if (isParenthesized && !consumeIf(Token::l_paren))
Chris Lattner40746442018-07-21 14:32:09 -07001488 return ParseSuccess;
1489
Chris Lattner2c402672018-07-23 11:56:17 -07001490 SmallVector<SSAUseInfo, 4> valueIDs;
1491 if (parseOptionalSSAUseList(valueIDs))
Chris Lattner7f9cc272018-07-19 08:35:28 -07001492 return ParseFailure;
Chris Lattner2c402672018-07-23 11:56:17 -07001493
1494 if (isParenthesized && !consumeIf(Token::r_paren))
1495 return emitError("expected ')' in operand list");
1496
1497 // If there were no operands, then there is no colon or type lists.
1498 if (valueIDs.empty())
1499 return ParseSuccess;
1500
Chris Lattner2c402672018-07-23 11:56:17 -07001501 SmallVector<Type *, 4> types;
Chris Lattnerf7702a62018-07-23 17:30:01 -07001502 if (parseToken(Token::colon, "expected ':' in operand list") ||
1503 parseTypeListNoParens(types))
Chris Lattner2c402672018-07-23 11:56:17 -07001504 return ParseFailure;
1505
1506 if (valueIDs.size() != types.size())
1507 return emitError("expected " + Twine(valueIDs.size()) +
1508 " types to match operand list");
1509
1510 results.reserve(valueIDs.size());
1511 for (unsigned i = 0, e = valueIDs.size(); i != e; ++i) {
1512 if (auto *value = resolveSSAUse(valueIDs[i], types[i]))
1513 results.push_back(cast<ValueTy>(value));
1514 else
1515 return ParseFailure;
1516 }
1517
1518 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001519}
1520
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001521/// Parse the CFG or MLFunc operation.
1522///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001523/// operation ::=
1524/// (ssa-id `=`)? string '(' ssa-use-list? ')' attribute-dict?
1525/// `:` function-type
1526///
1527ParseResult
Chris Lattner7f9cc272018-07-19 08:35:28 -07001528FunctionParser::parseOperation(const CreateOperationFunction &createOpFunc) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001529 auto loc = getToken().getLoc();
1530
1531 StringRef resultID;
1532 if (getToken().is(Token::percent_identifier)) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001533 resultID = getTokenSpelling();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001534 consumeToken(Token::percent_identifier);
Chris Lattnerf7702a62018-07-23 17:30:01 -07001535 if (parseToken(Token::equal, "expected '=' after SSA name"))
1536 return ParseFailure;
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001537 }
1538
Chris Lattner85ee1512018-07-25 11:15:20 -07001539 Operation *op;
1540 if (getToken().is(Token::bare_identifier) || getToken().isKeyword())
1541 op = parseCustomOperation(createOpFunc);
1542 else if (getToken().is(Token::string))
1543 op = parseVerboseOperation(createOpFunc);
1544 else
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001545 return emitError("expected operation name in quotes");
1546
Chris Lattner85ee1512018-07-25 11:15:20 -07001547 // If parsing of the basic operation failed, then this whole thing fails.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001548 if (!op)
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001549 return ParseFailure;
1550
1551 // We just parsed an operation. If it is a recognized one, verify that it
1552 // is structurally as we expect. If not, produce an error with a reasonable
1553 // source location.
Chris Lattner95865062018-08-01 10:18:59 -07001554 if (auto *opInfo = op->getAbstractOperation()) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001555 if (auto error = opInfo->verifyInvariants(op))
Chris Lattner9361fb32018-07-24 08:34:58 -07001556 return emitError(loc, Twine("'") + op->getName().str() + "' op " + error);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001557 }
1558
Chris Lattner7f9cc272018-07-19 08:35:28 -07001559 // If the instruction had a name, register it.
1560 if (!resultID.empty()) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001561 if (op->getNumResults() == 0)
1562 return emitError(loc, "cannot name an operation with no results");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001563
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001564 for (unsigned i = 0, e = op->getNumResults(); i != e; ++i)
1565 addDefinition({resultID, i, loc}, op->getResult(i));
Chris Lattner7f9cc272018-07-19 08:35:28 -07001566 }
1567
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001568 return ParseSuccess;
1569}
Chris Lattnere79379a2018-06-22 10:39:19 -07001570
Chris Lattner85ee1512018-07-25 11:15:20 -07001571Operation *FunctionParser::parseVerboseOperation(
1572 const CreateOperationFunction &createOpFunc) {
1573 auto name = getToken().getStringValue();
1574 if (name.empty())
1575 return (emitError("empty operation name is invalid"), nullptr);
1576
1577 consumeToken(Token::string);
1578
1579 // Parse the operand list.
1580 SmallVector<SSAUseInfo, 8> operandInfos;
1581
1582 if (parseToken(Token::l_paren, "expected '(' to start operand list") ||
1583 parseOptionalSSAUseList(operandInfos) ||
1584 parseToken(Token::r_paren, "expected ')' to end operand list")) {
1585 return nullptr;
1586 }
1587
1588 SmallVector<NamedAttribute, 4> attributes;
1589 if (getToken().is(Token::l_brace)) {
1590 if (parseAttributeDict(attributes))
1591 return nullptr;
1592 }
1593
1594 if (parseToken(Token::colon, "expected ':' followed by instruction type"))
1595 return nullptr;
1596
1597 auto typeLoc = getToken().getLoc();
1598 auto type = parseType();
1599 if (!type)
1600 return nullptr;
1601 auto fnType = dyn_cast<FunctionType>(type);
1602 if (!fnType)
1603 return (emitError(typeLoc, "expected function type"), nullptr);
1604
1605 // Check that we have the right number of types for the operands.
1606 auto operandTypes = fnType->getInputs();
1607 if (operandTypes.size() != operandInfos.size()) {
1608 auto plural = "s"[operandInfos.size() == 1];
1609 return (emitError(typeLoc, "expected " + llvm::utostr(operandInfos.size()) +
1610 " operand type" + plural + " but had " +
1611 llvm::utostr(operandTypes.size())),
1612 nullptr);
1613 }
1614
1615 // Resolve all of the operands.
1616 SmallVector<SSAValue *, 8> operands;
1617 for (unsigned i = 0, e = operandInfos.size(); i != e; ++i) {
1618 operands.push_back(resolveSSAUse(operandInfos[i], operandTypes[i]));
1619 if (!operands.back())
1620 return nullptr;
1621 }
1622
1623 auto nameId = builder.getIdentifier(name);
1624 return createOpFunc(nameId, operands, fnType->getResults(), attributes);
1625}
1626
1627namespace {
1628class CustomOpAsmParser : public OpAsmParser {
1629public:
1630 CustomOpAsmParser(SMLoc nameLoc, StringRef opName, FunctionParser &parser)
1631 : nameLoc(nameLoc), opName(opName), parser(parser) {}
1632
1633 /// This is an internal helper to parser a colon, we don't want to expose
1634 /// this to clients.
1635 bool internalParseColon(llvm::SMLoc *loc) {
1636 if (loc)
1637 *loc = parser.getToken().getLoc();
1638 return parser.parseToken(Token::colon, "expected ':'");
1639 }
1640
1641 //===--------------------------------------------------------------------===//
1642 // High level parsing methods.
1643 //===--------------------------------------------------------------------===//
1644
1645 bool parseComma(llvm::SMLoc *loc = nullptr) override {
1646 if (loc)
1647 *loc = parser.getToken().getLoc();
1648 return parser.parseToken(Token::comma, "expected ','");
1649 }
1650
1651 bool parseColonType(Type *&result, llvm::SMLoc *loc = nullptr) override {
1652 return internalParseColon(loc) || !(result = parser.parseType());
1653 }
1654
1655 bool parseColonTypeList(SmallVectorImpl<Type *> &result,
1656 llvm::SMLoc *loc = nullptr) override {
1657 if (internalParseColon(loc))
1658 return true;
1659
1660 do {
1661 if (auto *type = parser.parseType())
1662 result.push_back(type);
1663 else
1664 return true;
1665
1666 } while (parser.consumeIf(Token::comma));
1667 return false;
1668 }
1669
Chris Lattner85cf26d2018-08-02 16:54:36 -07001670 /// Parse an arbitrary attribute and return it in result. This also adds the
1671 /// attribute to the specified attribute list with the specified name. this
1672 /// captures the location of the attribute in 'loc' if it is non-null.
1673 bool parseAttribute(Attribute *&result, const char *attrName,
1674 SmallVectorImpl<NamedAttribute> &attrs,
1675 llvm::SMLoc *loc = nullptr) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001676 if (loc)
1677 *loc = parser.getToken().getLoc();
1678 result = parser.parseAttribute();
Chris Lattner85cf26d2018-08-02 16:54:36 -07001679 if (!result)
1680 return true;
1681
1682 attrs.push_back(
1683 NamedAttribute(parser.builder.getIdentifier(attrName), result));
1684 return false;
1685 }
1686
1687 /// If a named attribute list is present, parse is into result.
1688 bool parseOptionalAttributeDict(SmallVectorImpl<NamedAttribute> &result,
1689 llvm::SMLoc *loc = nullptr) override {
1690 if (parser.getToken().isNot(Token::l_brace))
1691 return false;
1692 if (loc)
1693 *loc = parser.getToken().getLoc();
1694 return parser.parseAttributeDict(result) == ParseFailure;
Chris Lattner85ee1512018-07-25 11:15:20 -07001695 }
1696
1697 bool parseOperand(OperandType &result) override {
1698 FunctionParser::SSAUseInfo useInfo;
1699 if (parser.parseSSAUse(useInfo))
1700 return true;
1701
1702 result = {useInfo.loc, useInfo.name, useInfo.number};
1703 return false;
1704 }
1705
1706 bool parseOperandList(SmallVectorImpl<OperandType> &result,
1707 int requiredOperandCount = -1,
Chris Lattner85cf26d2018-08-02 16:54:36 -07001708 Delimiter delimiter = Delimiter::None) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001709 auto startLoc = parser.getToken().getLoc();
1710
Chris Lattner85cf26d2018-08-02 16:54:36 -07001711 // Handle delimiters.
1712 switch (delimiter) {
1713 case Delimiter::None:
Chris Lattner85ee1512018-07-25 11:15:20 -07001714 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001715 case Delimiter::OptionalParen:
Chris Lattner3164ae62018-07-28 09:36:25 -07001716 if (parser.getToken().isNot(Token::l_paren))
1717 return false;
1718 LLVM_FALLTHROUGH;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001719 case Delimiter::Paren:
Chris Lattner85ee1512018-07-25 11:15:20 -07001720 if (parser.parseToken(Token::l_paren, "expected '(' in operand list"))
1721 return true;
1722 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001723 case Delimiter::OptionalSquare:
Chris Lattner3164ae62018-07-28 09:36:25 -07001724 if (parser.getToken().isNot(Token::l_square))
1725 return false;
1726 LLVM_FALLTHROUGH;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001727 case Delimiter::Square:
Chris Lattner85ee1512018-07-25 11:15:20 -07001728 if (parser.parseToken(Token::l_square, "expected '[' in operand list"))
1729 return true;
1730 break;
1731 }
1732
1733 // Check for zero operands.
1734 if (parser.getToken().is(Token::percent_identifier)) {
1735 do {
1736 OperandType operand;
1737 if (parseOperand(operand))
1738 return true;
1739 result.push_back(operand);
1740 } while (parser.consumeIf(Token::comma));
1741 }
1742
Chris Lattner85cf26d2018-08-02 16:54:36 -07001743 // Handle delimiters. If we reach here, the optional delimiters were
Chris Lattner3164ae62018-07-28 09:36:25 -07001744 // present, so we need to parse their closing one.
Chris Lattner85cf26d2018-08-02 16:54:36 -07001745 switch (delimiter) {
1746 case Delimiter::None:
Chris Lattner85ee1512018-07-25 11:15:20 -07001747 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001748 case Delimiter::OptionalParen:
1749 case Delimiter::Paren:
Chris Lattner85ee1512018-07-25 11:15:20 -07001750 if (parser.parseToken(Token::r_paren, "expected ')' in operand list"))
1751 return true;
1752 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001753 case Delimiter::OptionalSquare:
1754 case Delimiter::Square:
Chris Lattner85ee1512018-07-25 11:15:20 -07001755 if (parser.parseToken(Token::r_square, "expected ']' in operand list"))
1756 return true;
1757 break;
1758 }
1759
1760 if (requiredOperandCount != -1 && result.size() != requiredOperandCount)
1761 emitError(startLoc,
1762 "expected " + Twine(requiredOperandCount) + " operands");
1763 return false;
1764 }
1765
1766 //===--------------------------------------------------------------------===//
1767 // Methods for interacting with the parser
1768 //===--------------------------------------------------------------------===//
1769
1770 Builder &getBuilder() const override { return parser.builder; }
1771
1772 llvm::SMLoc getNameLoc() const override { return nameLoc; }
1773
1774 bool resolveOperand(OperandType operand, Type *type,
1775 SSAValue *&result) override {
1776 FunctionParser::SSAUseInfo operandInfo = {operand.name, operand.number,
1777 operand.location};
1778 result = parser.resolveSSAUse(operandInfo, type);
1779 return result == nullptr;
1780 }
1781
1782 /// Emit a diagnostic at the specified location.
1783 void emitError(llvm::SMLoc loc, const Twine &message) override {
1784 parser.emitError(loc, "custom op '" + Twine(opName) + "' " + message);
1785 emittedError = true;
1786 }
1787
1788 bool didEmitError() const { return emittedError; }
1789
1790private:
1791 SMLoc nameLoc;
1792 StringRef opName;
1793 FunctionParser &parser;
1794 bool emittedError = false;
1795};
1796} // end anonymous namespace.
1797
1798Operation *FunctionParser::parseCustomOperation(
1799 const CreateOperationFunction &createOpFunc) {
1800 auto opLoc = getToken().getLoc();
1801 auto opName = getTokenSpelling();
1802 CustomOpAsmParser opAsmParser(opLoc, opName, *this);
1803
1804 auto *opDefinition = getOperationSet().lookup(opName);
1805 if (!opDefinition) {
1806 opAsmParser.emitError(opLoc, "is unknown");
1807 return nullptr;
1808 }
1809
1810 consumeToken();
1811
1812 // Have the op implementation take a crack and parsing this.
1813 auto result = opDefinition->parseAssembly(&opAsmParser);
1814
1815 // If it emitted an error, we failed.
1816 if (opAsmParser.didEmitError())
1817 return nullptr;
1818
1819 // Otherwise, we succeeded. Use the state it parsed as our op information.
1820 auto nameId = builder.getIdentifier(opName);
1821 return createOpFunc(nameId, result.operands, result.types, result.attributes);
1822}
1823
Chris Lattner48af7d12018-07-09 19:05:38 -07001824//===----------------------------------------------------------------------===//
1825// CFG Functions
1826//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001827
Chris Lattner4c95a502018-06-23 16:03:42 -07001828namespace {
Chris Lattner48af7d12018-07-09 19:05:38 -07001829/// This is a specialized parser for CFGFunction's, maintaining the state
1830/// transient to their bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001831class CFGFunctionParser : public FunctionParser {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001832public:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001833 CFGFunctionParser(ParserState &state, CFGFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001834 : FunctionParser(state, Kind::CFGFunc), function(function),
1835 builder(function) {}
Chris Lattner2e595eb2018-07-10 10:08:27 -07001836
1837 ParseResult parseFunctionBody();
1838
1839private:
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001840 CFGFunction *function;
James Molloy0ff71542018-07-23 16:56:32 -07001841 llvm::StringMap<std::pair<BasicBlock *, SMLoc>> blocksByName;
Chris Lattner48af7d12018-07-09 19:05:38 -07001842
1843 /// This builder intentionally shadows the builder in the base class, with a
1844 /// more specific builder type.
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001845 CFGFuncBuilder builder;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001846
Chris Lattner4c95a502018-06-23 16:03:42 -07001847 /// Get the basic block with the specified name, creating it if it doesn't
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001848 /// already exist. The location specified is the point of use, which allows
1849 /// us to diagnose references to blocks that are not defined precisely.
1850 BasicBlock *getBlockNamed(StringRef name, SMLoc loc) {
1851 auto &blockAndLoc = blocksByName[name];
1852 if (!blockAndLoc.first) {
Chris Lattner3a467cc2018-07-01 20:28:00 -07001853 blockAndLoc.first = new BasicBlock();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001854 blockAndLoc.second = loc;
Chris Lattner4c95a502018-06-23 16:03:42 -07001855 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001856 return blockAndLoc.first;
Chris Lattner4c95a502018-06-23 16:03:42 -07001857 }
Chris Lattner48af7d12018-07-09 19:05:38 -07001858
James Molloy61a656c2018-07-22 15:45:24 -07001859 ParseResult
1860 parseOptionalBasicBlockArgList(SmallVectorImpl<BBArgument *> &results,
1861 BasicBlock *owner);
James Molloy4f788372018-07-24 15:01:27 -07001862 ParseResult parseBranchBlockAndUseList(BasicBlock *&block,
1863 SmallVectorImpl<CFGValue *> &values);
James Molloy61a656c2018-07-22 15:45:24 -07001864
Chris Lattner48af7d12018-07-09 19:05:38 -07001865 ParseResult parseBasicBlock();
1866 OperationInst *parseCFGOperation();
1867 TerminatorInst *parseTerminator();
Chris Lattner4c95a502018-06-23 16:03:42 -07001868};
1869} // end anonymous namespace
1870
James Molloy61a656c2018-07-22 15:45:24 -07001871/// Parse a (possibly empty) list of SSA operands with types as basic block
Chris Lattner2c402672018-07-23 11:56:17 -07001872/// arguments.
James Molloy61a656c2018-07-22 15:45:24 -07001873///
1874/// ssa-id-and-type-list ::= ssa-id-and-type (`,` ssa-id-and-type)*
1875///
1876ParseResult CFGFunctionParser::parseOptionalBasicBlockArgList(
1877 SmallVectorImpl<BBArgument *> &results, BasicBlock *owner) {
1878 if (getToken().is(Token::r_brace))
1879 return ParseSuccess;
1880
1881 return parseCommaSeparatedList([&]() -> ParseResult {
1882 auto type = parseSSADefOrUseAndType<Type *>(
1883 [&](SSAUseInfo useInfo, Type *type) -> Type * {
1884 BBArgument *arg = owner->addArgument(type);
1885 if (addDefinition(useInfo, arg) == ParseFailure)
1886 return nullptr;
1887 return type;
1888 });
1889 return type ? ParseSuccess : ParseFailure;
1890 });
1891}
1892
Chris Lattner48af7d12018-07-09 19:05:38 -07001893ParseResult CFGFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07001894 auto braceLoc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001895 if (parseToken(Token::l_brace, "expected '{' in CFG function"))
1896 return ParseFailure;
Chris Lattner48af7d12018-07-09 19:05:38 -07001897
1898 // Make sure we have at least one block.
1899 if (getToken().is(Token::r_brace))
1900 return emitError("CFG functions must have at least one basic block");
Chris Lattner4c95a502018-06-23 16:03:42 -07001901
1902 // Parse the list of blocks.
1903 while (!consumeIf(Token::r_brace))
Chris Lattner48af7d12018-07-09 19:05:38 -07001904 if (parseBasicBlock())
Chris Lattner4c95a502018-06-23 16:03:42 -07001905 return ParseFailure;
1906
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001907 // Verify that all referenced blocks were defined. Iteration over a
1908 // StringMap isn't determinstic, but this is good enough for our purposes.
Chris Lattner48af7d12018-07-09 19:05:38 -07001909 for (auto &elt : blocksByName) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001910 auto *bb = elt.second.first;
Chris Lattner3a467cc2018-07-01 20:28:00 -07001911 if (!bb->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001912 return emitError(elt.second.second,
James Molloy0ff71542018-07-23 16:56:32 -07001913 "reference to an undefined basic block '" + elt.first() +
1914 "'");
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001915 }
1916
Chris Lattnera8e47672018-07-25 14:08:16 -07001917 getModule()->getFunctions().push_back(function);
Chris Lattner6119d382018-07-20 18:41:34 -07001918
Chris Lattner40746442018-07-21 14:32:09 -07001919 return finalizeFunction(function, braceLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001920}
1921
1922/// Basic block declaration.
1923///
1924/// basic-block ::= bb-label instruction* terminator-stmt
1925/// bb-label ::= bb-id bb-arg-list? `:`
1926/// bb-id ::= bare-id
1927/// bb-arg-list ::= `(` ssa-id-and-type-list? `)`
1928///
Chris Lattner48af7d12018-07-09 19:05:38 -07001929ParseResult CFGFunctionParser::parseBasicBlock() {
1930 SMLoc nameLoc = getToken().getLoc();
1931 auto name = getTokenSpelling();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001932 if (parseToken(Token::bare_identifier, "expected basic block name"))
1933 return ParseFailure;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001934
Chris Lattner48af7d12018-07-09 19:05:38 -07001935 auto *block = getBlockNamed(name, nameLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001936
1937 // If this block has already been parsed, then this is a redefinition with the
1938 // same block name.
Chris Lattner3a467cc2018-07-01 20:28:00 -07001939 if (block->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001940 return emitError(nameLoc, "redefinition of block '" + name.str() + "'");
1941
Chris Lattner78276e32018-07-07 15:48:26 -07001942 // If an argument list is present, parse it.
1943 if (consumeIf(Token::l_paren)) {
James Molloy61a656c2018-07-22 15:45:24 -07001944 SmallVector<BBArgument *, 8> bbArgs;
Chris Lattnerf7702a62018-07-23 17:30:01 -07001945 if (parseOptionalBasicBlockArgList(bbArgs, block) ||
1946 parseToken(Token::r_paren, "expected ')' to end argument list"))
Chris Lattner78276e32018-07-07 15:48:26 -07001947 return ParseFailure;
Chris Lattner78276e32018-07-07 15:48:26 -07001948 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001949
James Molloy61a656c2018-07-22 15:45:24 -07001950 // Add the block to the function.
1951 function->push_back(block);
1952
Chris Lattnerf7702a62018-07-23 17:30:01 -07001953 if (parseToken(Token::colon, "expected ':' after basic block name"))
1954 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07001955
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001956 // Set the insertion point to the block we want to insert new operations into.
Chris Lattner48af7d12018-07-09 19:05:38 -07001957 builder.setInsertionPoint(block);
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001958
Chris Lattner7f9cc272018-07-19 08:35:28 -07001959 auto createOpFunc = [&](Identifier name, ArrayRef<SSAValue *> operands,
1960 ArrayRef<Type *> resultTypes,
1961 ArrayRef<NamedAttribute> attrs) -> Operation * {
1962 SmallVector<CFGValue *, 8> cfgOperands;
1963 cfgOperands.reserve(operands.size());
1964 for (auto *op : operands)
1965 cfgOperands.push_back(cast<CFGValue>(op));
1966 return builder.createOperation(name, cfgOperands, resultTypes, attrs);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001967 };
1968
Chris Lattnered65a732018-06-28 20:45:33 -07001969 // Parse the list of operations that make up the body of the block.
James Molloy4f788372018-07-24 15:01:27 -07001970 while (getToken().isNot(Token::kw_return, Token::kw_br, Token::kw_cond_br)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001971 if (parseOperation(createOpFunc))
Chris Lattnered65a732018-06-28 20:45:33 -07001972 return ParseFailure;
1973 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001974
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001975 if (!parseTerminator())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001976 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07001977
1978 return ParseSuccess;
1979}
1980
James Molloy4f788372018-07-24 15:01:27 -07001981ParseResult CFGFunctionParser::parseBranchBlockAndUseList(
1982 BasicBlock *&block, SmallVectorImpl<CFGValue *> &values) {
1983 block = getBlockNamed(getTokenSpelling(), getToken().getLoc());
1984 if (parseToken(Token::bare_identifier, "expected basic block name"))
1985 return ParseFailure;
1986
1987 if (!consumeIf(Token::l_paren))
1988 return ParseSuccess;
1989 if (parseOptionalSSAUseAndTypeList(values, /*isParenthesized*/ false) ||
1990 parseToken(Token::r_paren, "expected ')' to close argument list"))
1991 return ParseFailure;
1992 return ParseSuccess;
1993}
1994
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001995/// Parse the terminator instruction for a basic block.
1996///
1997/// terminator-stmt ::= `br` bb-id branch-use-list?
Chris Lattner1604e472018-07-23 08:42:19 -07001998/// branch-use-list ::= `(` ssa-use-list `)` ':' type-list-no-parens
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001999/// terminator-stmt ::=
2000/// `cond_br` ssa-use `,` bb-id branch-use-list? `,` bb-id branch-use-list?
2001/// terminator-stmt ::= `return` ssa-use-and-type-list?
2002///
Chris Lattner48af7d12018-07-09 19:05:38 -07002003TerminatorInst *CFGFunctionParser::parseTerminator() {
2004 switch (getToken().getKind()) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002005 default:
Chris Lattner3a467cc2018-07-01 20:28:00 -07002006 return (emitError("expected terminator at end of basic block"), nullptr);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002007
Chris Lattner40746442018-07-21 14:32:09 -07002008 case Token::kw_return: {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002009 consumeToken(Token::kw_return);
Chris Lattner40746442018-07-21 14:32:09 -07002010
Chris Lattner2c402672018-07-23 11:56:17 -07002011 // Parse any operands.
2012 SmallVector<CFGValue *, 8> operands;
2013 if (parseOptionalSSAUseAndTypeList(operands, /*isParenthesized*/ false))
2014 return nullptr;
2015 return builder.createReturnInst(operands);
Chris Lattner40746442018-07-21 14:32:09 -07002016 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002017
2018 case Token::kw_br: {
2019 consumeToken(Token::kw_br);
James Molloy4f788372018-07-24 15:01:27 -07002020 BasicBlock *destBB;
2021 SmallVector<CFGValue *, 4> values;
2022 if (parseBranchBlockAndUseList(destBB, values))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002023 return nullptr;
Chris Lattner1604e472018-07-23 08:42:19 -07002024 auto branch = builder.createBranchInst(destBB);
James Molloy4f788372018-07-24 15:01:27 -07002025 branch->addOperands(values);
Chris Lattner1604e472018-07-23 08:42:19 -07002026 return branch;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002027 }
James Molloy4f788372018-07-24 15:01:27 -07002028
2029 case Token::kw_cond_br: {
2030 consumeToken(Token::kw_cond_br);
2031 SSAUseInfo ssaUse;
2032 if (parseSSAUse(ssaUse))
2033 return nullptr;
2034 auto *cond = resolveSSAUse(ssaUse, builder.getIntegerType(1));
2035 if (!cond)
2036 return (emitError("expected type was boolean (i1)"), nullptr);
2037 if (parseToken(Token::comma, "expected ',' in conditional branch"))
2038 return nullptr;
2039
2040 BasicBlock *trueBlock;
2041 SmallVector<CFGValue *, 4> trueOperands;
2042 if (parseBranchBlockAndUseList(trueBlock, trueOperands))
2043 return nullptr;
2044
2045 if (parseToken(Token::comma, "expected ',' in conditional branch"))
2046 return nullptr;
2047
2048 BasicBlock *falseBlock;
2049 SmallVector<CFGValue *, 4> falseOperands;
2050 if (parseBranchBlockAndUseList(falseBlock, falseOperands))
2051 return nullptr;
2052
2053 auto branch = builder.createCondBranchInst(cast<CFGValue>(cond), trueBlock,
2054 falseBlock);
2055 branch->addTrueOperands(trueOperands);
2056 branch->addFalseOperands(falseOperands);
2057 return branch;
2058 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002059 }
2060}
2061
Chris Lattner48af7d12018-07-09 19:05:38 -07002062//===----------------------------------------------------------------------===//
2063// ML Functions
2064//===----------------------------------------------------------------------===//
2065
2066namespace {
2067/// Refined parser for MLFunction bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07002068class MLFunctionParser : public FunctionParser {
Chris Lattner48af7d12018-07-09 19:05:38 -07002069public:
Chris Lattner48af7d12018-07-09 19:05:38 -07002070 MLFunctionParser(ParserState &state, MLFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07002071 : FunctionParser(state, Kind::MLFunc), function(function),
2072 builder(function) {}
Chris Lattner48af7d12018-07-09 19:05:38 -07002073
2074 ParseResult parseFunctionBody();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002075
2076private:
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002077 MLFunction *function;
2078
2079 /// This builder intentionally shadows the builder in the base class, with a
2080 /// more specific builder type.
2081 MLFuncBuilder builder;
2082
2083 ParseResult parseForStmt();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002084 AffineConstantExpr *parseIntConstant();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002085 ParseResult parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002086 ParseResult parseElseClause(IfClause *elseClause);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002087 ParseResult parseStatements(StmtBlock *block);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002088 ParseResult parseStmtBlock(StmtBlock *block);
Chris Lattner48af7d12018-07-09 19:05:38 -07002089};
2090} // end anonymous namespace
2091
Chris Lattner48af7d12018-07-09 19:05:38 -07002092ParseResult MLFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07002093 auto braceLoc = getToken().getLoc();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002094 // Parse statements in this function
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002095
Chris Lattnerf7702a62018-07-23 17:30:01 -07002096 if (parseToken(Token::l_brace, "expected '{' in ML function") ||
2097 parseStatements(function)) {
2098 return ParseFailure;
2099 }
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002100
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002101 // TODO: store return operands in the IR.
2102 SmallVector<SSAUseInfo, 4> dummyUseInfo;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002103
Chris Lattnerf7702a62018-07-23 17:30:01 -07002104 if (parseToken(Token::kw_return,
2105 "ML function must end with return statement") ||
2106 parseOptionalSSAUseList(dummyUseInfo) ||
2107 parseToken(Token::r_brace, "expected '}' to end mlfunc"))
2108 return ParseFailure;
Chris Lattner40746442018-07-21 14:32:09 -07002109
Chris Lattnera8e47672018-07-25 14:08:16 -07002110 getModule()->getFunctions().push_back(function);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002111
Chris Lattner40746442018-07-21 14:32:09 -07002112 return finalizeFunction(function, braceLoc);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002113}
2114
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002115/// For statement.
2116///
Chris Lattner48af7d12018-07-09 19:05:38 -07002117/// ml-for-stmt ::= `for` ssa-id `=` lower-bound `to` upper-bound
2118/// (`step` integer-literal)? `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002119///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002120ParseResult MLFunctionParser::parseForStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002121 consumeToken(Token::kw_for);
2122
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002123 // Parse induction variable
2124 if (getToken().isNot(Token::percent_identifier))
2125 return emitError("expected SSA identifier for the loop variable");
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002126
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002127 auto loc = getToken().getLoc();
Tatiana Shpeismand880b352018-07-31 23:14:16 -07002128 StringRef inductionVariableName = getTokenSpelling();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002129 consumeToken(Token::percent_identifier);
2130
Chris Lattnerf7702a62018-07-23 17:30:01 -07002131 if (parseToken(Token::equal, "expected ="))
2132 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002133
2134 // Parse loop bounds
2135 AffineConstantExpr *lowerBound = parseIntConstant();
2136 if (!lowerBound)
2137 return ParseFailure;
2138
Chris Lattnerf7702a62018-07-23 17:30:01 -07002139 if (parseToken(Token::kw_to, "expected 'to' between bounds"))
2140 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002141
2142 AffineConstantExpr *upperBound = parseIntConstant();
2143 if (!upperBound)
2144 return ParseFailure;
2145
2146 // Parse step
2147 AffineConstantExpr *step = nullptr;
2148 if (consumeIf(Token::kw_step)) {
2149 step = parseIntConstant();
2150 if (!step)
2151 return ParseFailure;
2152 }
2153
2154 // Create for statement.
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002155 ForStmt *forStmt = builder.createFor(lowerBound, upperBound, step);
2156
2157 // Create SSA value definition for the induction variable.
Tatiana Shpeismanc9c4b342018-07-31 07:40:14 -07002158 addDefinition({inductionVariableName, 0, loc}, forStmt);
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002159
2160 // If parsing of the for statement body fails,
2161 // MLIR contains for statement with those nested statements that have been
2162 // successfully parsed.
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002163 if (parseStmtBlock(forStmt))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002164 return ParseFailure;
2165
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002166 // Reset insertion point to the current block.
2167 builder.setInsertionPoint(forStmt->getBlock());
2168
Tatiana Shpeismand880b352018-07-31 23:14:16 -07002169 // TODO: remove definition of the induction variable.
2170
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002171 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002172}
2173
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002174// This method is temporary workaround to parse simple loop bounds and
2175// step.
2176// TODO: remove this method once it's no longer used.
2177AffineConstantExpr *MLFunctionParser::parseIntConstant() {
2178 if (getToken().isNot(Token::integer))
2179 return (emitError("expected non-negative integer for now"), nullptr);
2180
2181 auto val = getToken().getUInt64IntegerValue();
2182 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
2183 return (emitError("constant too large for affineint"), nullptr);
2184 }
2185 consumeToken(Token::integer);
2186 return builder.getConstantExpr((int64_t)val.getValue());
2187}
2188
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002189/// If statement.
2190///
Chris Lattner48af7d12018-07-09 19:05:38 -07002191/// ml-if-head ::= `if` ml-if-cond `{` ml-stmt* `}`
2192/// | ml-if-head `else` `if` ml-if-cond `{` ml-stmt* `}`
2193/// ml-if-stmt ::= ml-if-head
2194/// | ml-if-head `else` `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002195///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002196ParseResult MLFunctionParser::parseIfStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002197 consumeToken(Token::kw_if);
Chris Lattnerf7702a62018-07-23 17:30:01 -07002198 if (parseToken(Token::l_paren, "expected ("))
2199 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002200
James Molloy0ff71542018-07-23 16:56:32 -07002201 // TODO: parse condition
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002202
Chris Lattnerf7702a62018-07-23 17:30:01 -07002203 if (parseToken(Token::r_paren, "expected )"))
2204 return ParseFailure;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002205
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002206 IfStmt *ifStmt = builder.createIf();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002207 IfClause *thenClause = ifStmt->getThenClause();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002208
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002209 // When parsing of an if statement body fails, the IR contains
2210 // the if statement with the portion of the body that has been
2211 // successfully parsed.
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002212 if (parseStmtBlock(thenClause))
2213 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002214
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002215 if (consumeIf(Token::kw_else)) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002216 auto *elseClause = ifStmt->createElseClause();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002217 if (parseElseClause(elseClause))
2218 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002219 }
2220
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002221 // Reset insertion point to the current block.
2222 builder.setInsertionPoint(ifStmt->getBlock());
2223
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002224 return ParseSuccess;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002225}
2226
2227ParseResult MLFunctionParser::parseElseClause(IfClause *elseClause) {
2228 if (getToken().is(Token::kw_if)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002229 builder.setInsertionPoint(elseClause);
2230 return parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002231 }
2232
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002233 return parseStmtBlock(elseClause);
2234}
2235
2236///
2237/// Parse a list of statements ending with `return` or `}`
2238///
2239ParseResult MLFunctionParser::parseStatements(StmtBlock *block) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07002240 auto createOpFunc = [&](Identifier name, ArrayRef<SSAValue *> operands,
2241 ArrayRef<Type *> resultTypes,
2242 ArrayRef<NamedAttribute> attrs) -> Operation * {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07002243 SmallVector<MLValue *, 8> stmtOperands;
2244 stmtOperands.reserve(operands.size());
2245 for (auto *op : operands)
2246 stmtOperands.push_back(cast<MLValue>(op));
2247 return builder.createOperation(name, stmtOperands, resultTypes, attrs);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002248 };
2249
2250 builder.setInsertionPoint(block);
2251
2252 while (getToken().isNot(Token::kw_return, Token::r_brace)) {
2253 switch (getToken().getKind()) {
2254 default:
2255 if (parseOperation(createOpFunc))
2256 return ParseFailure;
2257 break;
2258 case Token::kw_for:
2259 if (parseForStmt())
2260 return ParseFailure;
2261 break;
2262 case Token::kw_if:
2263 if (parseIfStmt())
2264 return ParseFailure;
2265 break;
2266 } // end switch
2267 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002268
2269 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002270}
2271
2272///
2273/// Parse `{` ml-stmt* `}`
2274///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002275ParseResult MLFunctionParser::parseStmtBlock(StmtBlock *block) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002276 if (parseToken(Token::l_brace, "expected '{' before statement list") ||
2277 parseStatements(block) ||
2278 parseToken(Token::r_brace,
2279 "expected '}' at the end of the statement block"))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002280 return ParseFailure;
2281
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002282 return ParseSuccess;
2283}
2284
Chris Lattner4c95a502018-06-23 16:03:42 -07002285//===----------------------------------------------------------------------===//
2286// Top-level entity parsing.
2287//===----------------------------------------------------------------------===//
2288
Chris Lattner2e595eb2018-07-10 10:08:27 -07002289namespace {
2290/// This parser handles entities that are only valid at the top level of the
2291/// file.
2292class ModuleParser : public Parser {
2293public:
2294 explicit ModuleParser(ParserState &state) : Parser(state) {}
2295
2296 ParseResult parseModule();
2297
2298private:
2299 ParseResult parseAffineMapDef();
2300
2301 // Functions.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002302 ParseResult parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2303 SmallVectorImpl<StringRef> &argNames);
2304 ParseResult parseFunctionSignature(StringRef &name, FunctionType *&type,
2305 SmallVectorImpl<StringRef> *argNames);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002306 ParseResult parseExtFunc();
2307 ParseResult parseCFGFunc();
2308 ParseResult parseMLFunc();
2309};
2310} // end anonymous namespace
2311
2312/// Affine map declaration.
2313///
2314/// affine-map-def ::= affine-map-id `=` affine-map-inline
2315///
2316ParseResult ModuleParser::parseAffineMapDef() {
2317 assert(getToken().is(Token::hash_identifier));
2318
2319 StringRef affineMapId = getTokenSpelling().drop_front();
2320
2321 // Check for redefinitions.
2322 auto *&entry = getState().affineMapDefinitions[affineMapId];
2323 if (entry)
2324 return emitError("redefinition of affine map id '" + affineMapId + "'");
2325
2326 consumeToken(Token::hash_identifier);
2327
2328 // Parse the '='
Chris Lattnerf7702a62018-07-23 17:30:01 -07002329 if (parseToken(Token::equal,
2330 "expected '=' in affine map outlined definition"))
2331 return ParseFailure;
Chris Lattner2e595eb2018-07-10 10:08:27 -07002332
2333 entry = parseAffineMapInline();
2334 if (!entry)
2335 return ParseFailure;
2336
Chris Lattner2e595eb2018-07-10 10:08:27 -07002337 return ParseSuccess;
2338}
2339
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002340/// Parse a (possibly empty) list of MLFunction arguments with types.
2341///
2342/// ml-argument ::= ssa-id `:` type
2343/// ml-argument-list ::= ml-argument (`,` ml-argument)* | /*empty*/
2344///
2345ParseResult
2346ModuleParser::parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2347 SmallVectorImpl<StringRef> &argNames) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002348 consumeToken(Token::l_paren);
2349
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002350 auto parseElt = [&]() -> ParseResult {
2351 // Parse argument name
2352 if (getToken().isNot(Token::percent_identifier))
2353 return emitError("expected SSA identifier");
2354
2355 StringRef name = getTokenSpelling().drop_front();
2356 consumeToken(Token::percent_identifier);
2357 argNames.push_back(name);
2358
Chris Lattnerf7702a62018-07-23 17:30:01 -07002359 if (parseToken(Token::colon, "expected ':'"))
2360 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002361
2362 // Parse argument type
2363 auto elt = parseType();
2364 if (!elt)
2365 return ParseFailure;
2366 argTypes.push_back(elt);
2367
2368 return ParseSuccess;
2369 };
2370
Chris Lattner40746442018-07-21 14:32:09 -07002371 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002372}
2373
Chris Lattner2e595eb2018-07-10 10:08:27 -07002374/// Parse a function signature, starting with a name and including the parameter
2375/// list.
2376///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002377/// argument-list ::= type (`,` type)* | /*empty*/ | ml-argument-list
Chris Lattner2e595eb2018-07-10 10:08:27 -07002378/// function-signature ::= function-id `(` argument-list `)` (`->` type-list)?
2379///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002380ParseResult
2381ModuleParser::parseFunctionSignature(StringRef &name, FunctionType *&type,
2382 SmallVectorImpl<StringRef> *argNames) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002383 if (getToken().isNot(Token::at_identifier))
2384 return emitError("expected a function identifier like '@foo'");
2385
2386 name = getTokenSpelling().drop_front();
2387 consumeToken(Token::at_identifier);
2388
2389 if (getToken().isNot(Token::l_paren))
2390 return emitError("expected '(' in function signature");
2391
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002392 SmallVector<Type *, 4> argTypes;
2393 ParseResult parseResult;
2394
2395 if (argNames)
2396 parseResult = parseMLArgumentList(argTypes, *argNames);
2397 else
2398 parseResult = parseTypeList(argTypes);
2399
2400 if (parseResult)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002401 return ParseFailure;
2402
2403 // Parse the return type if present.
2404 SmallVector<Type *, 4> results;
2405 if (consumeIf(Token::arrow)) {
2406 if (parseTypeList(results))
2407 return ParseFailure;
2408 }
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002409 type = builder.getFunctionType(argTypes, results);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002410 return ParseSuccess;
2411}
2412
2413/// External function declarations.
2414///
2415/// ext-func ::= `extfunc` function-signature
2416///
2417ParseResult ModuleParser::parseExtFunc() {
2418 consumeToken(Token::kw_extfunc);
2419
2420 StringRef name;
2421 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002422 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002423 return ParseFailure;
2424
2425 // Okay, the external function definition was parsed correctly.
Chris Lattnera8e47672018-07-25 14:08:16 -07002426 getModule()->getFunctions().push_back(new ExtFunction(name, type));
Chris Lattner2e595eb2018-07-10 10:08:27 -07002427 return ParseSuccess;
2428}
2429
2430/// CFG function declarations.
2431///
2432/// cfg-func ::= `cfgfunc` function-signature `{` basic-block+ `}`
2433///
2434ParseResult ModuleParser::parseCFGFunc() {
2435 consumeToken(Token::kw_cfgfunc);
2436
2437 StringRef name;
2438 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002439 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002440 return ParseFailure;
2441
2442 // Okay, the CFG function signature was parsed correctly, create the function.
2443 auto function = new CFGFunction(name, type);
2444
2445 return CFGFunctionParser(getState(), function).parseFunctionBody();
2446}
2447
2448/// ML function declarations.
2449///
2450/// ml-func ::= `mlfunc` ml-func-signature `{` ml-stmt* ml-return-stmt `}`
2451///
2452ParseResult ModuleParser::parseMLFunc() {
2453 consumeToken(Token::kw_mlfunc);
2454
2455 StringRef name;
2456 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002457 SmallVector<StringRef, 4> argNames;
Chris Lattner2e595eb2018-07-10 10:08:27 -07002458 // FIXME: Parse ML function signature (args + types)
2459 // by passing pointer to SmallVector<identifier> into parseFunctionSignature
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002460
2461 if (parseFunctionSignature(name, type, &argNames))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002462 return ParseFailure;
2463
2464 // Okay, the ML function signature was parsed correctly, create the function.
2465 auto function = new MLFunction(name, type);
2466
2467 return MLFunctionParser(getState(), function).parseFunctionBody();
2468}
2469
Chris Lattnere79379a2018-06-22 10:39:19 -07002470/// This is the top-level module parser.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002471ParseResult ModuleParser::parseModule() {
Chris Lattnere79379a2018-06-22 10:39:19 -07002472 while (1) {
Chris Lattner48af7d12018-07-09 19:05:38 -07002473 switch (getToken().getKind()) {
Chris Lattnere79379a2018-06-22 10:39:19 -07002474 default:
2475 emitError("expected a top level entity");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002476 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002477
Uday Bondhugula015cbb12018-07-03 20:16:08 -07002478 // If we got to the end of the file, then we're done.
Chris Lattnere79379a2018-06-22 10:39:19 -07002479 case Token::eof:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002480 return ParseSuccess;
Chris Lattnere79379a2018-06-22 10:39:19 -07002481
2482 // If we got an error token, then the lexer already emitted an error, just
2483 // stop. Someday we could introduce error recovery if there was demand for
2484 // it.
2485 case Token::error:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002486 return ParseFailure;
2487
2488 case Token::hash_identifier:
2489 if (parseAffineMapDef())
2490 return ParseFailure;
2491 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002492
2493 case Token::kw_extfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002494 if (parseExtFunc())
2495 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002496 break;
2497
Chris Lattner4c95a502018-06-23 16:03:42 -07002498 case Token::kw_cfgfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002499 if (parseCFGFunc())
2500 return ParseFailure;
MLIR Teamf85a6262018-06-27 11:03:08 -07002501 break;
Chris Lattner4c95a502018-06-23 16:03:42 -07002502
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002503 case Token::kw_mlfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002504 if (parseMLFunc())
2505 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002506 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002507 }
2508 }
2509}
2510
2511//===----------------------------------------------------------------------===//
2512
Jacques Pienaar7b829702018-07-03 13:24:09 -07002513void mlir::defaultErrorReporter(const llvm::SMDiagnostic &error) {
2514 const auto &sourceMgr = *error.getSourceMgr();
2515 sourceMgr.PrintMessage(error.getLoc(), error.getKind(), error.getMessage());
2516}
2517
Chris Lattnere79379a2018-06-22 10:39:19 -07002518/// This parses the file specified by the indicated SourceMgr and returns an
2519/// MLIR module if it was valid. If not, it emits diagnostics and returns null.
Jacques Pienaar9c411be2018-06-24 19:17:35 -07002520Module *mlir::parseSourceFile(llvm::SourceMgr &sourceMgr, MLIRContext *context,
Jacques Pienaar7b829702018-07-03 13:24:09 -07002521 SMDiagnosticHandlerTy errorReporter) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002522 // This is the result module we are parsing into.
2523 std::unique_ptr<Module> module(new Module(context));
2524
2525 ParserState state(sourceMgr, module.get(),
Jacques Pienaar0bffd862018-07-11 13:26:23 -07002526 errorReporter ? errorReporter : defaultErrorReporter);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002527 if (ModuleParser(state).parseModule())
2528 return nullptr;
Chris Lattner21e67f62018-07-06 10:46:19 -07002529
2530 // Make sure the parse module has no other structural problems detected by the
2531 // verifier.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002532 module->verify();
2533 return module.release();
Chris Lattnere79379a2018-06-22 10:39:19 -07002534}