blob: c77f0f4456363f36984b3a7b3c21f13041402692 [file] [log] [blame]
Chris Lattnere79379a2018-06-22 10:39:19 -07001//===- Parser.cpp - MLIR Parser Implementation ----------------------------===//
2//
3// Copyright 2019 The MLIR Authors.
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16// =============================================================================
17//
18// This file implements the parser for the MLIR textual form.
19//
20//===----------------------------------------------------------------------===//
21
22#include "mlir/Parser.h"
23#include "Lexer.h"
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -070024#include "mlir/IR/AffineExpr.h"
MLIR Teamf85a6262018-06-27 11:03:08 -070025#include "mlir/IR/AffineMap.h"
Chris Lattner7121b802018-07-04 20:45:39 -070026#include "mlir/IR/Attributes.h"
Chris Lattner158e0a3e2018-07-08 20:51:38 -070027#include "mlir/IR/Builders.h"
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -070028#include "mlir/IR/MLFunction.h"
Chris Lattner21e67f62018-07-06 10:46:19 -070029#include "mlir/IR/Module.h"
Chris Lattner85ee1512018-07-25 11:15:20 -070030#include "mlir/IR/OpImplementation.h"
Chris Lattner21e67f62018-07-06 10:46:19 -070031#include "mlir/IR/OperationSet.h"
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -070032#include "mlir/IR/Statements.h"
Chris Lattnerf7e22732018-06-22 22:03:48 -070033#include "mlir/IR/Types.h"
James Molloyf0d2f442018-08-03 01:54:46 -070034#include "llvm/ADT/DenseMap.h"
35#include "llvm/Support/SourceMgr.h"
Chris Lattnere79379a2018-06-22 10:39:19 -070036using namespace mlir;
Chris Lattner4c95a502018-06-23 16:03:42 -070037using llvm::SMLoc;
James Molloy0ff71542018-07-23 16:56:32 -070038using llvm::SourceMgr;
Chris Lattnere79379a2018-06-22 10:39:19 -070039
Chris Lattnerf7e22732018-06-22 22:03:48 -070040/// Simple enum to make code read better in cases that would otherwise return a
41/// bool value. Failure is "true" in a boolean context.
James Molloy0ff71542018-07-23 16:56:32 -070042enum ParseResult { ParseSuccess, ParseFailure };
Chris Lattnere79379a2018-06-22 10:39:19 -070043
Chris Lattner48af7d12018-07-09 19:05:38 -070044namespace {
45class Parser;
46
47/// This class refers to all of the state maintained globally by the parser,
48/// such as the current lexer position etc. The Parser base class provides
49/// methods to access this.
50class ParserState {
Chris Lattnered65a732018-06-28 20:45:33 -070051public:
Chris Lattner2e595eb2018-07-10 10:08:27 -070052 ParserState(llvm::SourceMgr &sourceMgr, Module *module,
Chris Lattner48af7d12018-07-09 19:05:38 -070053 SMDiagnosticHandlerTy errorReporter)
Chris Lattner2e595eb2018-07-10 10:08:27 -070054 : context(module->getContext()), module(module),
55 lex(sourceMgr, errorReporter), curToken(lex.lexToken()),
Chris Lattner85ee1512018-07-25 11:15:20 -070056 errorReporter(errorReporter), operationSet(OperationSet::get(context)) {
57 }
Chris Lattner2e595eb2018-07-10 10:08:27 -070058
59 // A map from affine map identifier to AffineMap.
60 llvm::StringMap<AffineMap *> affineMapDefinitions;
Chris Lattnere79379a2018-06-22 10:39:19 -070061
Chris Lattnere79379a2018-06-22 10:39:19 -070062private:
Chris Lattner48af7d12018-07-09 19:05:38 -070063 ParserState(const ParserState &) = delete;
64 void operator=(const ParserState &) = delete;
65
66 friend class Parser;
67
68 // The context we're parsing into.
Chris Lattner2e595eb2018-07-10 10:08:27 -070069 MLIRContext *const context;
70
71 // This is the module we are parsing into.
72 Module *const module;
Chris Lattnerf7e22732018-06-22 22:03:48 -070073
74 // The lexer for the source file we're parsing.
Chris Lattnere79379a2018-06-22 10:39:19 -070075 Lexer lex;
76
77 // This is the next token that hasn't been consumed yet.
78 Token curToken;
79
Jacques Pienaar9c411be2018-06-24 19:17:35 -070080 // The diagnostic error reporter.
Chris Lattner2e595eb2018-07-10 10:08:27 -070081 SMDiagnosticHandlerTy const errorReporter;
Chris Lattner85ee1512018-07-25 11:15:20 -070082
83 // The active OperationSet we're parsing with.
84 OperationSet &operationSet;
Chris Lattner48af7d12018-07-09 19:05:38 -070085};
86} // end anonymous namespace
MLIR Teamf85a6262018-06-27 11:03:08 -070087
Chris Lattner48af7d12018-07-09 19:05:38 -070088namespace {
89
Chris Lattner7f9cc272018-07-19 08:35:28 -070090typedef std::function<Operation *(Identifier, ArrayRef<SSAValue *>,
91 ArrayRef<Type *>, ArrayRef<NamedAttribute>)>
Tatiana Shpeisman565b9642018-07-16 11:47:09 -070092 CreateOperationFunction;
93
Chris Lattner48af7d12018-07-09 19:05:38 -070094/// This class implement support for parsing global entities like types and
95/// shared entities like SSA names. It is intended to be subclassed by
96/// specialized subparsers that include state, e.g. when a local symbol table.
97class Parser {
98public:
Chris Lattner2e595eb2018-07-10 10:08:27 -070099 Builder builder;
Chris Lattner48af7d12018-07-09 19:05:38 -0700100
Chris Lattner2e595eb2018-07-10 10:08:27 -0700101 Parser(ParserState &state) : builder(state.context), state(state) {}
102
103 // Helper methods to get stuff from the parser-global state.
104 ParserState &getState() const { return state; }
Chris Lattner48af7d12018-07-09 19:05:38 -0700105 MLIRContext *getContext() const { return state.context; }
Chris Lattner2e595eb2018-07-10 10:08:27 -0700106 Module *getModule() { return state.module; }
Chris Lattner85ee1512018-07-25 11:15:20 -0700107 OperationSet &getOperationSet() const { return state.operationSet; }
Chris Lattner48af7d12018-07-09 19:05:38 -0700108
109 /// Return the current token the parser is inspecting.
110 const Token &getToken() const { return state.curToken; }
111 StringRef getTokenSpelling() const { return state.curToken.getSpelling(); }
Chris Lattnere79379a2018-06-22 10:39:19 -0700112
113 /// Emit an error and return failure.
Chris Lattner4c95a502018-06-23 16:03:42 -0700114 ParseResult emitError(const Twine &message) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700115 return emitError(state.curToken.getLoc(), message);
Chris Lattner4c95a502018-06-23 16:03:42 -0700116 }
117 ParseResult emitError(SMLoc loc, const Twine &message);
Chris Lattnere79379a2018-06-22 10:39:19 -0700118
119 /// Advance the current lexer onto the next token.
120 void consumeToken() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700121 assert(state.curToken.isNot(Token::eof, Token::error) &&
Chris Lattnere79379a2018-06-22 10:39:19 -0700122 "shouldn't advance past EOF or errors");
Chris Lattner48af7d12018-07-09 19:05:38 -0700123 state.curToken = state.lex.lexToken();
Chris Lattnere79379a2018-06-22 10:39:19 -0700124 }
125
126 /// Advance the current lexer onto the next token, asserting what the expected
127 /// current token is. This is preferred to the above method because it leads
128 /// to more self-documenting code with better checking.
Chris Lattner8da0c282018-06-29 11:15:56 -0700129 void consumeToken(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700130 assert(state.curToken.is(kind) && "consumed an unexpected token");
Chris Lattnere79379a2018-06-22 10:39:19 -0700131 consumeToken();
132 }
133
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700134 /// If the current token has the specified kind, consume it and return true.
135 /// If not, return false.
Chris Lattner8da0c282018-06-29 11:15:56 -0700136 bool consumeIf(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700137 if (state.curToken.isNot(kind))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700138 return false;
139 consumeToken(kind);
140 return true;
141 }
142
Chris Lattnerf7702a62018-07-23 17:30:01 -0700143 /// Consume the specified token if present and return success. On failure,
144 /// output a diagnostic and return failure.
145 ParseResult parseToken(Token::Kind expectedToken, const Twine &message);
146
Chris Lattner40746442018-07-21 14:32:09 -0700147 /// Parse a comma-separated list of elements up until the specified end token.
148 ParseResult
149 parseCommaSeparatedListUntil(Token::Kind rightToken,
150 const std::function<ParseResult()> &parseElement,
151 bool allowEmptyList = true);
152
153 /// Parse a comma separated list of elements that must have at least one entry
154 /// in it.
155 ParseResult
156 parseCommaSeparatedList(const std::function<ParseResult()> &parseElement);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700157
Chris Lattnerf7e22732018-06-22 22:03:48 -0700158 // We have two forms of parsing methods - those that return a non-null
159 // pointer on success, and those that return a ParseResult to indicate whether
160 // they returned a failure. The second class fills in by-reference arguments
161 // as the results of their action.
162
Chris Lattnere79379a2018-06-22 10:39:19 -0700163 // Type parsing.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700164 VectorType *parseVectorType();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700165 ParseResult parseDimensionListRanked(SmallVectorImpl<int> &dimensions);
Chris Lattnerf7e22732018-06-22 22:03:48 -0700166 Type *parseTensorType();
167 Type *parseMemRefType();
168 Type *parseFunctionType();
169 Type *parseType();
Chris Lattner1604e472018-07-23 08:42:19 -0700170 ParseResult parseTypeListNoParens(SmallVectorImpl<Type *> &elements);
James Molloy0ff71542018-07-23 16:56:32 -0700171 ParseResult parseTypeList(SmallVectorImpl<Type *> &elements);
Chris Lattnere79379a2018-06-22 10:39:19 -0700172
Chris Lattner7121b802018-07-04 20:45:39 -0700173 // Attribute parsing.
174 Attribute *parseAttribute();
175 ParseResult parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes);
176
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700177 // Polyhedral structures.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700178 AffineMap *parseAffineMapInline();
MLIR Team718c82f2018-07-16 09:45:22 -0700179 AffineMap *parseAffineMapReference();
MLIR Teamf85a6262018-06-27 11:03:08 -0700180
Chris Lattner48af7d12018-07-09 19:05:38 -0700181private:
182 // The Parser is subclassed and reinstantiated. Do not add additional
183 // non-trivial state here, add it to the ParserState class.
184 ParserState &state;
Chris Lattnere79379a2018-06-22 10:39:19 -0700185};
186} // end anonymous namespace
187
188//===----------------------------------------------------------------------===//
189// Helper methods.
190//===----------------------------------------------------------------------===//
191
Chris Lattner4c95a502018-06-23 16:03:42 -0700192ParseResult Parser::emitError(SMLoc loc, const Twine &message) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700193 // If we hit a parse error in response to a lexer error, then the lexer
Jacques Pienaar9c411be2018-06-24 19:17:35 -0700194 // already reported the error.
Chris Lattner48af7d12018-07-09 19:05:38 -0700195 if (getToken().is(Token::error))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700196 return ParseFailure;
197
Chris Lattner48af7d12018-07-09 19:05:38 -0700198 auto &sourceMgr = state.lex.getSourceMgr();
199 state.errorReporter(sourceMgr.GetMessage(loc, SourceMgr::DK_Error, message));
Chris Lattnere79379a2018-06-22 10:39:19 -0700200 return ParseFailure;
201}
202
Chris Lattnerf7702a62018-07-23 17:30:01 -0700203/// Consume the specified token if present and return success. On failure,
204/// output a diagnostic and return failure.
205ParseResult Parser::parseToken(Token::Kind expectedToken,
206 const Twine &message) {
207 if (consumeIf(expectedToken))
208 return ParseSuccess;
209 return emitError(message);
210}
211
Chris Lattner40746442018-07-21 14:32:09 -0700212/// Parse a comma separated list of elements that must have at least one entry
213/// in it.
214ParseResult Parser::parseCommaSeparatedList(
215 const std::function<ParseResult()> &parseElement) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700216 // Non-empty case starts with an element.
217 if (parseElement())
218 return ParseFailure;
219
220 // Otherwise we have a list of comma separated elements.
221 while (consumeIf(Token::comma)) {
222 if (parseElement())
223 return ParseFailure;
224 }
Chris Lattner40746442018-07-21 14:32:09 -0700225 return ParseSuccess;
226}
227
228/// Parse a comma-separated list of elements, terminated with an arbitrary
229/// token. This allows empty lists if allowEmptyList is true.
230///
231/// abstract-list ::= rightToken // if allowEmptyList == true
232/// abstract-list ::= element (',' element)* rightToken
233///
234ParseResult Parser::parseCommaSeparatedListUntil(
235 Token::Kind rightToken, const std::function<ParseResult()> &parseElement,
236 bool allowEmptyList) {
237 // Handle the empty case.
238 if (getToken().is(rightToken)) {
239 if (!allowEmptyList)
240 return emitError("expected list element");
241 consumeToken(rightToken);
242 return ParseSuccess;
243 }
244
Chris Lattnerf7702a62018-07-23 17:30:01 -0700245 if (parseCommaSeparatedList(parseElement) ||
246 parseToken(rightToken, "expected ',' or '" +
247 Token::getTokenSpelling(rightToken) + "'"))
Chris Lattner40746442018-07-21 14:32:09 -0700248 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700249
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700250 return ParseSuccess;
251}
Chris Lattnere79379a2018-06-22 10:39:19 -0700252
253//===----------------------------------------------------------------------===//
254// Type Parsing
255//===----------------------------------------------------------------------===//
256
Chris Lattnerc3251192018-07-27 13:09:58 -0700257/// Parse an arbitrary type.
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700258///
Chris Lattnerc3251192018-07-27 13:09:58 -0700259/// type ::= integer-type
260/// | float-type
261/// | other-type
262/// | vector-type
263/// | tensor-type
264/// | memref-type
265/// | function-type
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700266///
Chris Lattnerc3251192018-07-27 13:09:58 -0700267/// float-type ::= `f16` | `bf16` | `f32` | `f64`
268/// other-type ::= `affineint` | `tf_control`
269///
270Type *Parser::parseType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700271 switch (getToken().getKind()) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700272 default:
273 return (emitError("expected type"), nullptr);
Chris Lattnerc3251192018-07-27 13:09:58 -0700274 case Token::kw_memref:
275 return parseMemRefType();
276 case Token::kw_tensor:
277 return parseTensorType();
278 case Token::kw_vector:
279 return parseVectorType();
280 case Token::l_paren:
281 return parseFunctionType();
282 // integer-type
283 case Token::inttype: {
284 auto width = getToken().getIntTypeBitwidth();
285 if (!width.hasValue())
286 return (emitError("invalid integer width"), nullptr);
287 consumeToken(Token::inttype);
288 return builder.getIntegerType(width.getValue());
289 }
290
291 // float-type
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700292 case Token::kw_bf16:
293 consumeToken(Token::kw_bf16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700294 return builder.getBF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700295 case Token::kw_f16:
296 consumeToken(Token::kw_f16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700297 return builder.getF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700298 case Token::kw_f32:
299 consumeToken(Token::kw_f32);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700300 return builder.getF32Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700301 case Token::kw_f64:
302 consumeToken(Token::kw_f64);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700303 return builder.getF64Type();
Chris Lattnerc3251192018-07-27 13:09:58 -0700304
305 // other-type
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700306 case Token::kw_affineint:
307 consumeToken(Token::kw_affineint);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700308 return builder.getAffineIntType();
Jacques Pienaarc0d69302018-07-27 11:07:12 -0700309 case Token::kw_tf_control:
310 consumeToken(Token::kw_tf_control);
311 return builder.getTFControlType();
James Molloy72b0cbe2018-08-01 12:55:27 -0700312 case Token::kw_tf_string:
313 consumeToken(Token::kw_tf_string);
314 return builder.getTFStringType();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700315 }
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700316}
317
318/// Parse a vector type.
319///
320/// vector-type ::= `vector` `<` const-dimension-list primitive-type `>`
321/// const-dimension-list ::= (integer-literal `x`)+
322///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700323VectorType *Parser::parseVectorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700324 consumeToken(Token::kw_vector);
325
Chris Lattnerf7702a62018-07-23 17:30:01 -0700326 if (parseToken(Token::less, "expected '<' in vector type"))
327 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700328
Chris Lattner48af7d12018-07-09 19:05:38 -0700329 if (getToken().isNot(Token::integer))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700330 return (emitError("expected dimension size in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700331
332 SmallVector<unsigned, 4> dimensions;
Chris Lattner48af7d12018-07-09 19:05:38 -0700333 while (getToken().is(Token::integer)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700334 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700335 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700336 if (!dimension.hasValue())
Chris Lattnerf7e22732018-06-22 22:03:48 -0700337 return (emitError("invalid dimension in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700338 dimensions.push_back(dimension.getValue());
339
340 consumeToken(Token::integer);
341
342 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700343 if (getToken().isNot(Token::bare_identifier) ||
344 getTokenSpelling()[0] != 'x')
Chris Lattnerf7e22732018-06-22 22:03:48 -0700345 return (emitError("expected 'x' in vector dimension list"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700346
347 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700348 if (getTokenSpelling().size() != 1)
349 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700350
351 // Consume the 'x'.
352 consumeToken(Token::bare_identifier);
353 }
354
355 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700356 auto typeLoc = getToken().getLoc();
357 auto *elementType = parseType();
358 if (!elementType || parseToken(Token::greater, "expected '>' in vector type"))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700359 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700360
Chris Lattnerc3251192018-07-27 13:09:58 -0700361 if (!isa<FloatType>(elementType) && !isa<IntegerType>(elementType))
362 return (emitError(typeLoc, "invalid vector element type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700363
Chris Lattnerf7e22732018-06-22 22:03:48 -0700364 return VectorType::get(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700365}
366
367/// Parse a dimension list of a tensor or memref type. This populates the
368/// dimension list, returning -1 for the '?' dimensions.
369///
370/// dimension-list-ranked ::= (dimension `x`)*
371/// dimension ::= `?` | integer-literal
372///
373ParseResult Parser::parseDimensionListRanked(SmallVectorImpl<int> &dimensions) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700374 while (getToken().isAny(Token::integer, Token::question)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700375 if (consumeIf(Token::question)) {
376 dimensions.push_back(-1);
377 } else {
378 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700379 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700380 if (!dimension.hasValue() || (int)dimension.getValue() < 0)
381 return emitError("invalid dimension");
382 dimensions.push_back((int)dimension.getValue());
383 consumeToken(Token::integer);
384 }
385
386 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700387 if (getToken().isNot(Token::bare_identifier) ||
388 getTokenSpelling()[0] != 'x')
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700389 return emitError("expected 'x' in dimension list");
390
391 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700392 if (getTokenSpelling().size() != 1)
393 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700394
395 // Consume the 'x'.
396 consumeToken(Token::bare_identifier);
397 }
398
399 return ParseSuccess;
400}
401
402/// Parse a tensor type.
403///
404/// tensor-type ::= `tensor` `<` dimension-list element-type `>`
405/// dimension-list ::= dimension-list-ranked | `??`
406///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700407Type *Parser::parseTensorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700408 consumeToken(Token::kw_tensor);
409
Chris Lattnerf7702a62018-07-23 17:30:01 -0700410 if (parseToken(Token::less, "expected '<' in tensor type"))
411 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700412
413 bool isUnranked;
414 SmallVector<int, 4> dimensions;
415
416 if (consumeIf(Token::questionquestion)) {
417 isUnranked = true;
418 } else {
419 isUnranked = false;
420 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700421 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700422 }
423
424 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700425 auto typeLoc = getToken().getLoc();
426 auto *elementType = parseType();
427 if (!elementType || parseToken(Token::greater, "expected '>' in tensor type"))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700428 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700429
Chris Lattnerc3251192018-07-27 13:09:58 -0700430 if (!isa<IntegerType>(elementType) && !isa<FloatType>(elementType) &&
431 !isa<VectorType>(elementType))
432 return (emitError(typeLoc, "invalid tensor element type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700433
MLIR Team355ec862018-06-23 18:09:09 -0700434 if (isUnranked)
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700435 return builder.getTensorType(elementType);
436 return builder.getTensorType(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700437}
438
439/// Parse a memref type.
440///
441/// memref-type ::= `memref` `<` dimension-list-ranked element-type
442/// (`,` semi-affine-map-composition)? (`,` memory-space)? `>`
443///
444/// semi-affine-map-composition ::= (semi-affine-map `,` )* semi-affine-map
445/// memory-space ::= integer-literal /* | TODO: address-space-id */
446///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700447Type *Parser::parseMemRefType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700448 consumeToken(Token::kw_memref);
449
Chris Lattnerf7702a62018-07-23 17:30:01 -0700450 if (parseToken(Token::less, "expected '<' in memref type"))
451 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700452
453 SmallVector<int, 4> dimensions;
454 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700455 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700456
457 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700458 auto typeLoc = getToken().getLoc();
459 auto *elementType = parseType();
Chris Lattnerf7e22732018-06-22 22:03:48 -0700460 if (!elementType)
461 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700462
Chris Lattnerc3251192018-07-27 13:09:58 -0700463 if (!isa<IntegerType>(elementType) && !isa<FloatType>(elementType) &&
464 !isa<VectorType>(elementType))
465 return (emitError(typeLoc, "invalid memref element type"), nullptr);
466
MLIR Team718c82f2018-07-16 09:45:22 -0700467 // Parse semi-affine-map-composition.
James Molloy0ff71542018-07-23 16:56:32 -0700468 SmallVector<AffineMap *, 2> affineMapComposition;
Chris Lattner413db6a2018-07-25 12:55:50 -0700469 unsigned memorySpace = 0;
MLIR Team718c82f2018-07-16 09:45:22 -0700470 bool parsedMemorySpace = false;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700471
MLIR Team718c82f2018-07-16 09:45:22 -0700472 auto parseElt = [&]() -> ParseResult {
473 if (getToken().is(Token::integer)) {
474 // Parse memory space.
475 if (parsedMemorySpace)
476 return emitError("multiple memory spaces specified in memref type");
477 auto v = getToken().getUnsignedIntegerValue();
478 if (!v.hasValue())
479 return emitError("invalid memory space in memref type");
480 memorySpace = v.getValue();
481 consumeToken(Token::integer);
482 parsedMemorySpace = true;
483 } else {
484 // Parse affine map.
485 if (parsedMemorySpace)
486 return emitError("affine map after memory space in memref type");
James Molloy0ff71542018-07-23 16:56:32 -0700487 auto *affineMap = parseAffineMapReference();
MLIR Team718c82f2018-07-16 09:45:22 -0700488 if (affineMap == nullptr)
489 return ParseFailure;
490 affineMapComposition.push_back(affineMap);
491 }
492 return ParseSuccess;
493 };
494
Chris Lattner413db6a2018-07-25 12:55:50 -0700495 // Parse a list of mappings and address space if present.
496 if (consumeIf(Token::comma)) {
497 // Parse comma separated list of affine maps, followed by memory space.
498 if (parseCommaSeparatedListUntil(Token::greater, parseElt,
499 /*allowEmptyList=*/false)) {
500 return nullptr;
501 }
502 } else {
503 if (parseToken(Token::greater, "expected ',' or '>' in memref type"))
504 return nullptr;
MLIR Team718c82f2018-07-16 09:45:22 -0700505 }
MLIR Team718c82f2018-07-16 09:45:22 -0700506
507 return MemRefType::get(dimensions, elementType, affineMapComposition,
508 memorySpace);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700509}
510
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700511/// Parse a function type.
512///
513/// function-type ::= type-list-parens `->` type-list
514///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700515Type *Parser::parseFunctionType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700516 assert(getToken().is(Token::l_paren));
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700517
Chris Lattnerf7702a62018-07-23 17:30:01 -0700518 SmallVector<Type *, 4> arguments, results;
519 if (parseTypeList(arguments) ||
520 parseToken(Token::arrow, "expected '->' in function type") ||
521 parseTypeList(results))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700522 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700523
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700524 return builder.getFunctionType(arguments, results);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700525}
526
Chris Lattner1604e472018-07-23 08:42:19 -0700527/// Parse a list of types without an enclosing parenthesis. The list must have
528/// at least one member.
529///
530/// type-list-no-parens ::= type (`,` type)*
531///
532ParseResult Parser::parseTypeListNoParens(SmallVectorImpl<Type *> &elements) {
533 auto parseElt = [&]() -> ParseResult {
534 auto elt = parseType();
535 elements.push_back(elt);
536 return elt ? ParseSuccess : ParseFailure;
537 };
538
539 return parseCommaSeparatedList(parseElt);
540}
541
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700542/// Parse a "type list", which is a singular type, or a parenthesized list of
543/// types.
544///
545/// type-list ::= type-list-parens | type
546/// type-list-parens ::= `(` `)`
Chris Lattner1604e472018-07-23 08:42:19 -0700547/// | `(` type-list-no-parens `)`
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700548///
James Molloy0ff71542018-07-23 16:56:32 -0700549ParseResult Parser::parseTypeList(SmallVectorImpl<Type *> &elements) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700550 auto parseElt = [&]() -> ParseResult {
551 auto elt = parseType();
552 elements.push_back(elt);
553 return elt ? ParseSuccess : ParseFailure;
554 };
555
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700556 // If there is no parens, then it must be a singular type.
557 if (!consumeIf(Token::l_paren))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700558 return parseElt();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700559
Chris Lattner40746442018-07-21 14:32:09 -0700560 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700561 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700562
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700563 return ParseSuccess;
564}
565
Chris Lattner4c95a502018-06-23 16:03:42 -0700566//===----------------------------------------------------------------------===//
Chris Lattner7121b802018-07-04 20:45:39 -0700567// Attribute parsing.
568//===----------------------------------------------------------------------===//
569
Chris Lattner7121b802018-07-04 20:45:39 -0700570/// Attribute parsing.
571///
572/// attribute-value ::= bool-literal
573/// | integer-literal
574/// | float-literal
575/// | string-literal
James Molloyf0d2f442018-08-03 01:54:46 -0700576/// | type
Chris Lattner7121b802018-07-04 20:45:39 -0700577/// | `[` (attribute-value (`,` attribute-value)*)? `]`
578///
579Attribute *Parser::parseAttribute() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700580 switch (getToken().getKind()) {
Chris Lattner7121b802018-07-04 20:45:39 -0700581 case Token::kw_true:
582 consumeToken(Token::kw_true);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700583 return builder.getBoolAttr(true);
Chris Lattner7121b802018-07-04 20:45:39 -0700584 case Token::kw_false:
585 consumeToken(Token::kw_false);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700586 return builder.getBoolAttr(false);
Chris Lattner7121b802018-07-04 20:45:39 -0700587
Jacques Pienaar84491092018-07-31 17:15:15 -0700588 case Token::floatliteral: {
589 auto val = getToken().getFloatingPointValue();
590 if (!val.hasValue())
591 return (emitError("floating point value too large for attribute"),
592 nullptr);
593 consumeToken(Token::floatliteral);
594 return builder.getFloatAttr(val.getValue());
595 }
Chris Lattner7121b802018-07-04 20:45:39 -0700596 case Token::integer: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700597 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700598 if (!val.hasValue() || (int64_t)val.getValue() < 0)
599 return (emitError("integer too large for attribute"), nullptr);
600 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700601 return builder.getIntegerAttr((int64_t)val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700602 }
603
604 case Token::minus: {
605 consumeToken(Token::minus);
Chris Lattner48af7d12018-07-09 19:05:38 -0700606 if (getToken().is(Token::integer)) {
607 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700608 if (!val.hasValue() || (int64_t)-val.getValue() >= 0)
609 return (emitError("integer too large for attribute"), nullptr);
610 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700611 return builder.getIntegerAttr((int64_t)-val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700612 }
Jacques Pienaar84491092018-07-31 17:15:15 -0700613 if (getToken().is(Token::floatliteral)) {
614 auto val = getToken().getFloatingPointValue();
615 if (!val.hasValue())
616 return (emitError("floating point value too large for attribute"),
617 nullptr);
618 consumeToken(Token::floatliteral);
619 return builder.getFloatAttr(-val.getValue());
620 }
Chris Lattner7121b802018-07-04 20:45:39 -0700621
622 return (emitError("expected constant integer or floating point value"),
623 nullptr);
624 }
625
626 case Token::string: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700627 auto val = getToken().getStringValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700628 consumeToken(Token::string);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700629 return builder.getStringAttr(val);
Chris Lattner7121b802018-07-04 20:45:39 -0700630 }
631
Chris Lattner85ee1512018-07-25 11:15:20 -0700632 case Token::l_square: {
633 consumeToken(Token::l_square);
James Molloy0ff71542018-07-23 16:56:32 -0700634 SmallVector<Attribute *, 4> elements;
Chris Lattner7121b802018-07-04 20:45:39 -0700635
636 auto parseElt = [&]() -> ParseResult {
637 elements.push_back(parseAttribute());
638 return elements.back() ? ParseSuccess : ParseFailure;
639 };
640
Chris Lattner85ee1512018-07-25 11:15:20 -0700641 if (parseCommaSeparatedListUntil(Token::r_square, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700642 return nullptr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700643 return builder.getArrayAttr(elements);
Chris Lattner7121b802018-07-04 20:45:39 -0700644 }
James Molloyf0d2f442018-08-03 01:54:46 -0700645 case Token::hash_identifier:
646 case Token::l_paren: {
MLIR Teamb61885d2018-07-18 16:29:21 -0700647 // Try to parse affine map reference.
James Molloyf0d2f442018-08-03 01:54:46 -0700648 if (auto *affineMap = parseAffineMapReference())
MLIR Teamb61885d2018-07-18 16:29:21 -0700649 return builder.getAffineMapAttr(affineMap);
Chris Lattner7121b802018-07-04 20:45:39 -0700650 return (emitError("expected constant attribute value"), nullptr);
651 }
James Molloyf0d2f442018-08-03 01:54:46 -0700652 default: {
653 if (Type *type = parseType())
654 return builder.getTypeAttr(type);
655 return nullptr;
656 }
657 }
Chris Lattner7121b802018-07-04 20:45:39 -0700658}
659
Chris Lattner7121b802018-07-04 20:45:39 -0700660/// Attribute dictionary.
661///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700662/// attribute-dict ::= `{` `}`
663/// | `{` attribute-entry (`,` attribute-entry)* `}`
664/// attribute-entry ::= bare-id `:` attribute-value
Chris Lattner7121b802018-07-04 20:45:39 -0700665///
James Molloy0ff71542018-07-23 16:56:32 -0700666ParseResult
667Parser::parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes) {
Chris Lattner7121b802018-07-04 20:45:39 -0700668 consumeToken(Token::l_brace);
669
670 auto parseElt = [&]() -> ParseResult {
671 // We allow keywords as attribute names.
Chris Lattner48af7d12018-07-09 19:05:38 -0700672 if (getToken().isNot(Token::bare_identifier, Token::inttype) &&
673 !getToken().isKeyword())
Chris Lattner7121b802018-07-04 20:45:39 -0700674 return emitError("expected attribute name");
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700675 auto nameId = builder.getIdentifier(getTokenSpelling());
Chris Lattner7121b802018-07-04 20:45:39 -0700676 consumeToken();
677
Chris Lattnerf7702a62018-07-23 17:30:01 -0700678 if (parseToken(Token::colon, "expected ':' in attribute list"))
679 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700680
681 auto attr = parseAttribute();
James Molloy0ff71542018-07-23 16:56:32 -0700682 if (!attr)
683 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700684
685 attributes.push_back({nameId, attr});
686 return ParseSuccess;
687 };
688
Chris Lattner40746442018-07-21 14:32:09 -0700689 if (parseCommaSeparatedListUntil(Token::r_brace, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700690 return ParseFailure;
691
692 return ParseSuccess;
693}
694
695//===----------------------------------------------------------------------===//
MLIR Teamf85a6262018-06-27 11:03:08 -0700696// Polyhedral structures.
697//===----------------------------------------------------------------------===//
698
Chris Lattner2e595eb2018-07-10 10:08:27 -0700699/// Lower precedence ops (all at the same precedence level). LNoOp is false in
700/// the boolean sense.
701enum AffineLowPrecOp {
702 /// Null value.
703 LNoOp,
704 Add,
705 Sub
706};
MLIR Teamf85a6262018-06-27 11:03:08 -0700707
Chris Lattner2e595eb2018-07-10 10:08:27 -0700708/// Higher precedence ops - all at the same precedence level. HNoOp is false in
709/// the boolean sense.
710enum AffineHighPrecOp {
711 /// Null value.
712 HNoOp,
713 Mul,
714 FloorDiv,
715 CeilDiv,
716 Mod
717};
Chris Lattner7121b802018-07-04 20:45:39 -0700718
Chris Lattner2e595eb2018-07-10 10:08:27 -0700719namespace {
720/// This is a specialized parser for AffineMap's, maintaining the state
721/// transient to their bodies.
722class AffineMapParser : public Parser {
723public:
724 explicit AffineMapParser(ParserState &state) : Parser(state) {}
Chris Lattner7121b802018-07-04 20:45:39 -0700725
Chris Lattner2e595eb2018-07-10 10:08:27 -0700726 AffineMap *parseAffineMapInline();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700727
Chris Lattner2e595eb2018-07-10 10:08:27 -0700728private:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700729 // Binary affine op parsing.
730 AffineLowPrecOp consumeIfLowPrecOp();
731 AffineHighPrecOp consumeIfHighPrecOp();
MLIR Teamf85a6262018-06-27 11:03:08 -0700732
Chris Lattner2e595eb2018-07-10 10:08:27 -0700733 // Identifier lists for polyhedral structures.
Chris Lattner413db6a2018-07-25 12:55:50 -0700734 ParseResult parseDimIdList(unsigned &numDims);
735 ParseResult parseSymbolIdList(unsigned &numSymbols);
736 ParseResult parseIdentifierDefinition(AffineExpr *idExpr);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700737
738 AffineExpr *parseAffineExpr();
739 AffineExpr *parseParentheticalExpr();
740 AffineExpr *parseNegateExpression(AffineExpr *lhs);
741 AffineExpr *parseIntegerExpr();
742 AffineExpr *parseBareIdExpr();
743
744 AffineExpr *getBinaryAffineOpExpr(AffineHighPrecOp op, AffineExpr *lhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700745 AffineExpr *rhs, SMLoc opLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700746 AffineExpr *getBinaryAffineOpExpr(AffineLowPrecOp op, AffineExpr *lhs,
747 AffineExpr *rhs);
748 AffineExpr *parseAffineOperandExpr(AffineExpr *lhs);
749 AffineExpr *parseAffineLowPrecOpExpr(AffineExpr *llhs,
750 AffineLowPrecOp llhsOp);
751 AffineExpr *parseAffineHighPrecOpExpr(AffineExpr *llhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700752 AffineHighPrecOp llhsOp,
753 SMLoc llhsOpLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700754
755private:
Chris Lattner413db6a2018-07-25 12:55:50 -0700756 SmallVector<std::pair<StringRef, AffineExpr *>, 4> dimsAndSymbols;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700757};
758} // end anonymous namespace
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700759
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700760/// Create an affine binary high precedence op expression (mul's, div's, mod).
761/// opLoc is the location of the op token to be used to report errors
762/// for non-conforming expressions.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700763AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineHighPrecOp op,
764 AffineExpr *lhs,
Chris Lattner40746442018-07-21 14:32:09 -0700765 AffineExpr *rhs,
766 SMLoc opLoc) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700767 // TODO: make the error location info accurate.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700768 switch (op) {
769 case Mul:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700770 if (!lhs->isSymbolicOrConstant() && !rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700771 emitError(opLoc, "non-affine expression: at least one of the multiply "
772 "operands has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700773 return nullptr;
774 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700775 return builder.getMulExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700776 case FloorDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700777 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700778 emitError(opLoc, "non-affine expression: right operand of floordiv "
779 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700780 return nullptr;
781 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700782 return builder.getFloorDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700783 case CeilDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700784 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700785 emitError(opLoc, "non-affine expression: right operand of ceildiv "
786 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700787 return nullptr;
788 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700789 return builder.getCeilDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700790 case Mod:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700791 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700792 emitError(opLoc, "non-affine expression: right operand of mod "
793 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700794 return nullptr;
795 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700796 return builder.getModExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700797 case HNoOp:
798 llvm_unreachable("can't create affine expression for null high prec op");
799 return nullptr;
800 }
801}
802
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700803/// Create an affine binary low precedence op expression (add, sub).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700804AffineExpr *AffineMapParser::getBinaryAffineOpExpr(AffineLowPrecOp op,
805 AffineExpr *lhs,
806 AffineExpr *rhs) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700807 switch (op) {
808 case AffineLowPrecOp::Add:
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700809 return builder.getAddExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700810 case AffineLowPrecOp::Sub:
Uday Bondhugulac1faf662018-07-19 14:08:50 -0700811 return builder.getAddExpr(
812 lhs, builder.getMulExpr(rhs, builder.getConstantExpr(-1)));
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700813 case AffineLowPrecOp::LNoOp:
814 llvm_unreachable("can't create affine expression for null low prec op");
815 return nullptr;
816 }
817}
818
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700819/// Consume this token if it is a lower precedence affine op (there are only two
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700820/// precedence levels).
Chris Lattner2e595eb2018-07-10 10:08:27 -0700821AffineLowPrecOp AffineMapParser::consumeIfLowPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700822 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700823 case Token::plus:
824 consumeToken(Token::plus);
825 return AffineLowPrecOp::Add;
826 case Token::minus:
827 consumeToken(Token::minus);
828 return AffineLowPrecOp::Sub;
829 default:
830 return AffineLowPrecOp::LNoOp;
831 }
832}
833
834/// Consume this token if it is a higher precedence affine op (there are only
835/// two precedence levels)
Chris Lattner2e595eb2018-07-10 10:08:27 -0700836AffineHighPrecOp AffineMapParser::consumeIfHighPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700837 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700838 case Token::star:
839 consumeToken(Token::star);
840 return Mul;
841 case Token::kw_floordiv:
842 consumeToken(Token::kw_floordiv);
843 return FloorDiv;
844 case Token::kw_ceildiv:
845 consumeToken(Token::kw_ceildiv);
846 return CeilDiv;
847 case Token::kw_mod:
848 consumeToken(Token::kw_mod);
849 return Mod;
850 default:
851 return HNoOp;
852 }
853}
854
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700855/// Parse a high precedence op expression list: mul, div, and mod are high
856/// precedence binary ops, i.e., parse a
857/// expr_1 op_1 expr_2 op_2 ... expr_n
858/// where op_1, op_2 are all a AffineHighPrecOp (mul, div, mod).
859/// All affine binary ops are left associative.
860/// Given llhs, returns (llhs llhsOp lhs) op rhs, or (lhs op rhs) if llhs is
861/// null. If no rhs can be found, returns (llhs llhsOp lhs) or lhs if llhs is
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700862/// null. llhsOpLoc is the location of the llhsOp token that will be used to
863/// report an error for non-conforming expressions.
864AffineExpr *AffineMapParser::parseAffineHighPrecOpExpr(AffineExpr *llhs,
865 AffineHighPrecOp llhsOp,
866 SMLoc llhsOpLoc) {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700867 AffineExpr *lhs = parseAffineOperandExpr(llhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700868 if (!lhs)
869 return nullptr;
870
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700871 // Found an LHS. Parse the remaining expression.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700872 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -0700873 if (AffineHighPrecOp op = consumeIfHighPrecOp()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700874 if (llhs) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700875 AffineExpr *expr = getBinaryAffineOpExpr(llhsOp, llhs, lhs, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700876 if (!expr)
877 return nullptr;
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700878 return parseAffineHighPrecOpExpr(expr, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700879 }
880 // No LLHS, get RHS
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700881 return parseAffineHighPrecOpExpr(lhs, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700882 }
883
884 // This is the last operand in this expression.
885 if (llhs)
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700886 return getBinaryAffineOpExpr(llhsOp, llhs, lhs, llhsOpLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700887
888 // No llhs, 'lhs' itself is the expression.
889 return lhs;
890}
891
892/// Parse an affine expression inside parentheses.
893///
894/// affine-expr ::= `(` affine-expr `)`
Chris Lattner2e595eb2018-07-10 10:08:27 -0700895AffineExpr *AffineMapParser::parseParentheticalExpr() {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700896 if (parseToken(Token::l_paren, "expected '('"))
897 return nullptr;
Chris Lattner48af7d12018-07-09 19:05:38 -0700898 if (getToken().is(Token::r_paren))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700899 return (emitError("no expression inside parentheses"), nullptr);
Chris Lattnerf7702a62018-07-23 17:30:01 -0700900
Chris Lattner2e595eb2018-07-10 10:08:27 -0700901 auto *expr = parseAffineExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700902 if (!expr)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700903 return nullptr;
Chris Lattnerf7702a62018-07-23 17:30:01 -0700904 if (parseToken(Token::r_paren, "expected ')'"))
905 return nullptr;
906
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700907 return expr;
908}
909
910/// Parse the negation expression.
911///
912/// affine-expr ::= `-` affine-expr
Chris Lattner2e595eb2018-07-10 10:08:27 -0700913AffineExpr *AffineMapParser::parseNegateExpression(AffineExpr *lhs) {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700914 if (parseToken(Token::minus, "expected '-'"))
915 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700916
Chris Lattner2e595eb2018-07-10 10:08:27 -0700917 AffineExpr *operand = parseAffineOperandExpr(lhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700918 // Since negation has the highest precedence of all ops (including high
919 // precedence ops) but lower than parentheses, we are only going to use
920 // parseAffineOperandExpr instead of parseAffineExpr here.
921 if (!operand)
922 // Extra error message although parseAffineOperandExpr would have
923 // complained. Leads to a better diagnostic.
924 return (emitError("missing operand of negation"), nullptr);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700925 auto *minusOne = builder.getConstantExpr(-1);
926 return builder.getMulExpr(minusOne, operand);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700927}
928
929/// Parse a bare id that may appear in an affine expression.
930///
931/// affine-expr ::= bare-id
Chris Lattner2e595eb2018-07-10 10:08:27 -0700932AffineExpr *AffineMapParser::parseBareIdExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700933 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700934 return (emitError("expected bare identifier"), nullptr);
935
Chris Lattner48af7d12018-07-09 19:05:38 -0700936 StringRef sRef = getTokenSpelling();
Chris Lattner413db6a2018-07-25 12:55:50 -0700937 for (auto entry : dimsAndSymbols) {
Chris Lattnera8e47672018-07-25 14:08:16 -0700938 if (entry.first == sRef) {
939 consumeToken(Token::bare_identifier);
940 return entry.second;
941 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700942 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700943
944 return (emitError("use of undeclared identifier"), nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700945}
946
947/// Parse a positive integral constant appearing in an affine expression.
948///
949/// affine-expr ::= integer-literal
Chris Lattner2e595eb2018-07-10 10:08:27 -0700950AffineExpr *AffineMapParser::parseIntegerExpr() {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700951 // No need to handle negative numbers separately here. They are naturally
952 // handled via the unary negation operator, although (FIXME) MININT_64 still
953 // not correctly handled.
Chris Lattner48af7d12018-07-09 19:05:38 -0700954 if (getToken().isNot(Token::integer))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700955 return (emitError("expected integer"), nullptr);
956
Chris Lattner48af7d12018-07-09 19:05:38 -0700957 auto val = getToken().getUInt64IntegerValue();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700958 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
959 return (emitError("constant too large for affineint"), nullptr);
960 }
961 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700962 return builder.getConstantExpr((int64_t)val.getValue());
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700963}
964
965/// Parses an expression that can be a valid operand of an affine expression.
Uday Bondhugula76345202018-07-09 13:47:52 -0700966/// lhs: if non-null, lhs is an affine expression that is the lhs of a binary
967/// operator, the rhs of which is being parsed. This is used to determine
968/// whether an error should be emitted for a missing right operand.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700969// Eg: for an expression without parentheses (like i + j + k + l), each
970// of the four identifiers is an operand. For i + j*k + l, j*k is not an
971// operand expression, it's an op expression and will be parsed via
972// parseAffineHighPrecOpExpression(). However, for i + (j*k) + -l, (j*k) and -l
973// are valid operands that will be parsed by this function.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700974AffineExpr *AffineMapParser::parseAffineOperandExpr(AffineExpr *lhs) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700975 switch (getToken().getKind()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700976 case Token::bare_identifier:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700977 return parseBareIdExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700978 case Token::integer:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700979 return parseIntegerExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700980 case Token::l_paren:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700981 return parseParentheticalExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700982 case Token::minus:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700983 return parseNegateExpression(lhs);
Uday Bondhugula76345202018-07-09 13:47:52 -0700984 case Token::kw_ceildiv:
985 case Token::kw_floordiv:
986 case Token::kw_mod:
987 case Token::plus:
988 case Token::star:
989 if (lhs)
990 emitError("missing right operand of binary operator");
991 else
992 emitError("missing left operand of binary operator");
993 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700994 default:
995 if (lhs)
Uday Bondhugula76345202018-07-09 13:47:52 -0700996 emitError("missing right operand of binary operator");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700997 else
998 emitError("expected affine expression");
999 return nullptr;
1000 }
1001}
1002
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001003/// Parse affine expressions that are bare-id's, integer constants,
1004/// parenthetical affine expressions, and affine op expressions that are a
1005/// composition of those.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001006///
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001007/// All binary op's associate from left to right.
1008///
1009/// {add, sub} have lower precedence than {mul, div, and mod}.
1010///
Uday Bondhugula76345202018-07-09 13:47:52 -07001011/// Add, sub'are themselves at the same precedence level. Mul, floordiv,
1012/// ceildiv, and mod are at the same higher precedence level. Negation has
1013/// higher precedence than any binary op.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001014///
1015/// llhs: the affine expression appearing on the left of the one being parsed.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001016/// This function will return ((llhs llhsOp lhs) op rhs) if llhs is non null,
1017/// and lhs op rhs otherwise; if there is no rhs, llhs llhsOp lhs is returned if
1018/// llhs is non-null; otherwise lhs is returned. This is to deal with left
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001019/// associativity.
1020///
1021/// Eg: when the expression is e1 + e2*e3 + e4, with e1 as llhs, this function
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001022/// will return the affine expr equivalent of (e1 + (e2*e3)) + e4, where (e2*e3)
1023/// will be parsed using parseAffineHighPrecOpExpr().
Chris Lattner2e595eb2018-07-10 10:08:27 -07001024AffineExpr *AffineMapParser::parseAffineLowPrecOpExpr(AffineExpr *llhs,
1025 AffineLowPrecOp llhsOp) {
Uday Bondhugula76345202018-07-09 13:47:52 -07001026 AffineExpr *lhs;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001027 if (!(lhs = parseAffineOperandExpr(llhs)))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001028 return nullptr;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001029
1030 // Found an LHS. Deal with the ops.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001031 if (AffineLowPrecOp lOp = consumeIfLowPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001032 if (llhs) {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001033 AffineExpr *sum = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001034 return parseAffineLowPrecOpExpr(sum, lOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001035 }
1036 // No LLHS, get RHS and form the expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001037 return parseAffineLowPrecOpExpr(lhs, lOp);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001038 }
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001039 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07001040 if (AffineHighPrecOp hOp = consumeIfHighPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001041 // We have a higher precedence op here. Get the rhs operand for the llhs
1042 // through parseAffineHighPrecOpExpr.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001043 AffineExpr *highRes = parseAffineHighPrecOpExpr(lhs, hOp, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001044 if (!highRes)
1045 return nullptr;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001046
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001047 // If llhs is null, the product forms the first operand of the yet to be
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001048 // found expression. If non-null, the op to associate with llhs is llhsOp.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001049 AffineExpr *expr =
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001050 llhs ? getBinaryAffineOpExpr(llhsOp, llhs, highRes) : highRes;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001051
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001052 // Recurse for subsequent low prec op's after the affine high prec op
1053 // expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001054 if (AffineLowPrecOp nextOp = consumeIfLowPrecOp())
1055 return parseAffineLowPrecOpExpr(expr, nextOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001056 return expr;
1057 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001058 // Last operand in the expression list.
1059 if (llhs)
1060 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
1061 // No llhs, 'lhs' itself is the expression.
1062 return lhs;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001063}
1064
1065/// Parse an affine expression.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001066/// affine-expr ::= `(` affine-expr `)`
1067/// | `-` affine-expr
1068/// | affine-expr `+` affine-expr
1069/// | affine-expr `-` affine-expr
1070/// | affine-expr `*` affine-expr
1071/// | affine-expr `floordiv` affine-expr
1072/// | affine-expr `ceildiv` affine-expr
1073/// | affine-expr `mod` affine-expr
1074/// | bare-id
1075/// | integer-literal
1076///
1077/// Additional conditions are checked depending on the production. For eg., one
1078/// of the operands for `*` has to be either constant/symbolic; the second
1079/// operand for floordiv, ceildiv, and mod has to be a positive integer.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001080AffineExpr *AffineMapParser::parseAffineExpr() {
1081 return parseAffineLowPrecOpExpr(nullptr, AffineLowPrecOp::LNoOp);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001082}
1083
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001084/// Parse a dim or symbol from the lists appearing before the actual expressions
Chris Lattner2e595eb2018-07-10 10:08:27 -07001085/// of the affine map. Update our state to store the dimensional/symbolic
Chris Lattner413db6a2018-07-25 12:55:50 -07001086/// identifier.
1087ParseResult AffineMapParser::parseIdentifierDefinition(AffineExpr *idExpr) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001088 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001089 return emitError("expected bare identifier");
Chris Lattner413db6a2018-07-25 12:55:50 -07001090
1091 auto name = getTokenSpelling();
1092 for (auto entry : dimsAndSymbols) {
1093 if (entry.first == name)
1094 return emitError("redefinition of identifier '" + Twine(name) + "'");
1095 }
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001096 consumeToken(Token::bare_identifier);
Chris Lattner413db6a2018-07-25 12:55:50 -07001097
1098 dimsAndSymbols.push_back({name, idExpr});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001099 return ParseSuccess;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001100}
1101
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001102/// Parse the list of symbolic identifiers to an affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001103ParseResult AffineMapParser::parseSymbolIdList(unsigned &numSymbols) {
1104 consumeToken(Token::l_square);
1105 auto parseElt = [&]() -> ParseResult {
1106 auto *symbol = AffineSymbolExpr::get(numSymbols++, getContext());
1107 return parseIdentifierDefinition(symbol);
1108 };
Chris Lattner85ee1512018-07-25 11:15:20 -07001109 return parseCommaSeparatedListUntil(Token::r_square, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001110}
1111
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001112/// Parse the list of dimensional identifiers to an affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001113ParseResult AffineMapParser::parseDimIdList(unsigned &numDims) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07001114 if (parseToken(Token::l_paren,
1115 "expected '(' at start of dimensional identifiers list"))
1116 return ParseFailure;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001117
Chris Lattner413db6a2018-07-25 12:55:50 -07001118 auto parseElt = [&]() -> ParseResult {
1119 auto *dimension = AffineDimExpr::get(numDims++, getContext());
1120 return parseIdentifierDefinition(dimension);
1121 };
Chris Lattner40746442018-07-21 14:32:09 -07001122 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001123}
1124
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001125/// Parse an affine map definition.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001126///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001127/// affine-map-inline ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
1128/// (`size` `(` dim-size (`,` dim-size)* `)`)?
1129/// dim-size ::= affine-expr | `min` `(` affine-expr ( `,` affine-expr)+ `)`
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001130///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001131/// multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner2e595eb2018-07-10 10:08:27 -07001132AffineMap *AffineMapParser::parseAffineMapInline() {
Chris Lattner413db6a2018-07-25 12:55:50 -07001133 unsigned numDims = 0, numSymbols = 0;
1134
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001135 // List of dimensional identifiers.
Chris Lattner413db6a2018-07-25 12:55:50 -07001136 if (parseDimIdList(numDims))
Chris Lattner7121b802018-07-04 20:45:39 -07001137 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001138
1139 // Symbols are optional.
Chris Lattner85ee1512018-07-25 11:15:20 -07001140 if (getToken().is(Token::l_square)) {
Chris Lattner413db6a2018-07-25 12:55:50 -07001141 if (parseSymbolIdList(numSymbols))
Chris Lattner7121b802018-07-04 20:45:39 -07001142 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001143 }
Chris Lattnerf7702a62018-07-23 17:30:01 -07001144
1145 if (parseToken(Token::arrow, "expected '->' or '['") ||
1146 parseToken(Token::l_paren, "expected '(' at start of affine map range"))
Chris Lattner7121b802018-07-04 20:45:39 -07001147 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001148
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001149 SmallVector<AffineExpr *, 4> exprs;
1150 auto parseElt = [&]() -> ParseResult {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001151 auto *elt = parseAffineExpr();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001152 ParseResult res = elt ? ParseSuccess : ParseFailure;
1153 exprs.push_back(elt);
1154 return res;
1155 };
1156
1157 // Parse a multi-dimensional affine expression (a comma-separated list of 1-d
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001158 // affine expressions); the list cannot be empty.
1159 // Grammar: multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner40746442018-07-21 14:32:09 -07001160 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt, false))
Chris Lattner7121b802018-07-04 20:45:39 -07001161 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001162
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001163 // Parse optional range sizes.
Uday Bondhugula1e500b42018-07-12 18:04:04 -07001164 // range-sizes ::= (`size` `(` dim-size (`,` dim-size)* `)`)?
1165 // dim-size ::= affine-expr | `min` `(` affine-expr (`,` affine-expr)+ `)`
1166 // TODO(bondhugula): support for min of several affine expressions.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001167 // TODO: check if sizes are non-negative whenever they are constant.
1168 SmallVector<AffineExpr *, 4> rangeSizes;
1169 if (consumeIf(Token::kw_size)) {
1170 // Location of the l_paren token (if it exists) for error reporting later.
1171 auto loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001172 if (parseToken(Token::l_paren, "expected '(' at start of affine map range"))
1173 return nullptr;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001174
1175 auto parseRangeSize = [&]() -> ParseResult {
Chris Lattner413db6a2018-07-25 12:55:50 -07001176 auto loc = getToken().getLoc();
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001177 auto *elt = parseAffineExpr();
Chris Lattner413db6a2018-07-25 12:55:50 -07001178 if (!elt)
1179 return ParseFailure;
1180
1181 if (!elt->isSymbolicOrConstant())
1182 return emitError(loc,
1183 "size expressions cannot refer to dimension values");
1184
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001185 rangeSizes.push_back(elt);
Chris Lattner413db6a2018-07-25 12:55:50 -07001186 return ParseSuccess;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001187 };
1188
Chris Lattner40746442018-07-21 14:32:09 -07001189 if (parseCommaSeparatedListUntil(Token::r_paren, parseRangeSize, false))
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001190 return nullptr;
1191 if (exprs.size() > rangeSizes.size())
1192 return (emitError(loc, "fewer range sizes than range expressions"),
1193 nullptr);
1194 if (exprs.size() < rangeSizes.size())
1195 return (emitError(loc, "more range sizes than range expressions"),
1196 nullptr);
1197 }
1198
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001199 // Parsed a valid affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001200 return builder.getAffineMap(numDims, numSymbols, exprs, rangeSizes);
MLIR Teamf85a6262018-06-27 11:03:08 -07001201}
1202
Chris Lattner2e595eb2018-07-10 10:08:27 -07001203AffineMap *Parser::parseAffineMapInline() {
1204 return AffineMapParser(state).parseAffineMapInline();
1205}
1206
MLIR Team718c82f2018-07-16 09:45:22 -07001207AffineMap *Parser::parseAffineMapReference() {
1208 if (getToken().is(Token::hash_identifier)) {
1209 // Parse affine map identifier and verify that it exists.
1210 StringRef affineMapId = getTokenSpelling().drop_front();
1211 if (getState().affineMapDefinitions.count(affineMapId) == 0)
1212 return (emitError("undefined affine map id '" + affineMapId + "'"),
1213 nullptr);
1214 consumeToken(Token::hash_identifier);
1215 return getState().affineMapDefinitions[affineMapId];
1216 }
1217 // Try to parse inline affine map.
1218 return parseAffineMapInline();
1219}
1220
MLIR Teamf85a6262018-06-27 11:03:08 -07001221//===----------------------------------------------------------------------===//
Chris Lattner7f9cc272018-07-19 08:35:28 -07001222// FunctionParser
Chris Lattner4c95a502018-06-23 16:03:42 -07001223//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001224
Chris Lattner7f9cc272018-07-19 08:35:28 -07001225namespace {
1226/// This class contains parser state that is common across CFG and ML functions,
1227/// notably for dealing with operations and SSA values.
1228class FunctionParser : public Parser {
1229public:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001230 enum class Kind { CFGFunc, MLFunc };
1231
1232 Kind getKind() const { return kind; }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001233
Chris Lattner6119d382018-07-20 18:41:34 -07001234 /// After the function is finished parsing, this function checks to see if
1235 /// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001236 ParseResult finalizeFunction(Function *func, SMLoc loc);
Chris Lattner6119d382018-07-20 18:41:34 -07001237
1238 /// This represents a use of an SSA value in the program. The first two
1239 /// entries in the tuple are the name and result number of a reference. The
1240 /// third is the location of the reference, which is used in case this ends up
1241 /// being a use of an undefined value.
1242 struct SSAUseInfo {
1243 StringRef name; // Value name, e.g. %42 or %abc
1244 unsigned number; // Number, specified with #12
1245 SMLoc loc; // Location of first definition or use.
1246 };
Chris Lattner7f9cc272018-07-19 08:35:28 -07001247
1248 /// Given a reference to an SSA value and its type, return a reference. This
1249 /// returns null on failure.
1250 SSAValue *resolveSSAUse(SSAUseInfo useInfo, Type *type);
1251
1252 /// Register a definition of a value with the symbol table.
1253 ParseResult addDefinition(SSAUseInfo useInfo, SSAValue *value);
1254
1255 // SSA parsing productions.
1256 ParseResult parseSSAUse(SSAUseInfo &result);
Chris Lattner40746442018-07-21 14:32:09 -07001257 ParseResult parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results);
James Molloy61a656c2018-07-22 15:45:24 -07001258
1259 template <typename ResultType>
1260 ResultType parseSSADefOrUseAndType(
1261 const std::function<ResultType(SSAUseInfo, Type *)> &action);
1262
1263 SSAValue *parseSSAUseAndType() {
1264 return parseSSADefOrUseAndType<SSAValue *>(
1265 [&](SSAUseInfo useInfo, Type *type) -> SSAValue * {
1266 return resolveSSAUse(useInfo, type);
1267 });
1268 }
Chris Lattner40746442018-07-21 14:32:09 -07001269
1270 template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001271 ParseResult
Chris Lattner2c402672018-07-23 11:56:17 -07001272 parseOptionalSSAUseAndTypeList(SmallVectorImpl<ValueTy *> &results,
1273 bool isParenthesized);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001274
1275 // Operations
1276 ParseResult parseOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner85ee1512018-07-25 11:15:20 -07001277 Operation *parseVerboseOperation(const CreateOperationFunction &createOpFunc);
1278 Operation *parseCustomOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001279
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001280protected:
1281 FunctionParser(ParserState &state, Kind kind) : Parser(state), kind(kind) {}
1282
Chris Lattner7f9cc272018-07-19 08:35:28 -07001283private:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001284 /// Kind indicates if this is CFG or ML function parser.
1285 Kind kind;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001286 /// This keeps track of all of the SSA values we are tracking, indexed by
Chris Lattner6119d382018-07-20 18:41:34 -07001287 /// their name. This has one entry per result number.
1288 llvm::StringMap<SmallVector<std::pair<SSAValue *, SMLoc>, 1>> values;
1289
1290 /// These are all of the placeholders we've made along with the location of
1291 /// their first reference, to allow checking for use of undefined values.
1292 DenseMap<SSAValue *, SMLoc> forwardReferencePlaceholders;
1293
1294 SSAValue *createForwardReferencePlaceholder(SMLoc loc, Type *type);
1295
1296 /// Return true if this is a forward reference.
1297 bool isForwardReferencePlaceholder(SSAValue *value) {
1298 return forwardReferencePlaceholders.count(value);
1299 }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001300};
1301} // end anonymous namespace
1302
Chris Lattner6119d382018-07-20 18:41:34 -07001303/// Create and remember a new placeholder for a forward reference.
1304SSAValue *FunctionParser::createForwardReferencePlaceholder(SMLoc loc,
1305 Type *type) {
1306 // Forward references are always created as instructions, even in ML
1307 // functions, because we just need something with a def/use chain.
1308 //
1309 // We create these placeholders as having an empty name, which we know cannot
1310 // be created through normal user input, allowing us to distinguish them.
1311 auto name = Identifier::get("placeholder", getContext());
1312 auto *inst = OperationInst::create(name, /*operands*/ {}, type, /*attrs*/ {},
1313 getContext());
1314 forwardReferencePlaceholders[inst->getResult(0)] = loc;
1315 return inst->getResult(0);
1316}
1317
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001318/// Given an unbound reference to an SSA value and its type, return the value
Chris Lattner7f9cc272018-07-19 08:35:28 -07001319/// it specifies. This returns null on failure.
1320SSAValue *FunctionParser::resolveSSAUse(SSAUseInfo useInfo, Type *type) {
Chris Lattner6119d382018-07-20 18:41:34 -07001321 auto &entries = values[useInfo.name];
1322
Chris Lattner7f9cc272018-07-19 08:35:28 -07001323 // If we have already seen a value of this name, return it.
Chris Lattner6119d382018-07-20 18:41:34 -07001324 if (useInfo.number < entries.size() && entries[useInfo.number].first) {
1325 auto *result = entries[useInfo.number].first;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001326 // Check that the type matches the other uses.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001327 if (result->getType() == type)
1328 return result;
1329
Chris Lattner6119d382018-07-20 18:41:34 -07001330 emitError(useInfo.loc, "use of value '" + useInfo.name.str() +
1331 "' expects different type than prior uses");
1332 emitError(entries[useInfo.number].second, "prior use here");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001333 return nullptr;
1334 }
1335
Chris Lattner6119d382018-07-20 18:41:34 -07001336 // Make sure we have enough slots for this.
1337 if (entries.size() <= useInfo.number)
1338 entries.resize(useInfo.number + 1);
1339
1340 // If the value has already been defined and this is an overly large result
1341 // number, diagnose that.
1342 if (entries[0].first && !isForwardReferencePlaceholder(entries[0].first))
1343 return (emitError(useInfo.loc, "reference to invalid result number"),
1344 nullptr);
1345
Tatiana Shpeismand880b352018-07-31 23:14:16 -07001346 // Otherwise, this is a forward reference. If we are in ML function return
1347 // an error. In CFG function, create a placeholder and remember
1348 // that we did so.
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001349 if (getKind() == Kind::MLFunc)
1350 return (
1351 emitError(useInfo.loc, "use of undefined SSA value " + useInfo.name),
1352 nullptr);
1353
Chris Lattner6119d382018-07-20 18:41:34 -07001354 auto *result = createForwardReferencePlaceholder(useInfo.loc, type);
1355 entries[useInfo.number].first = result;
1356 entries[useInfo.number].second = useInfo.loc;
1357 return result;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001358}
1359
1360/// Register a definition of a value with the symbol table.
1361ParseResult FunctionParser::addDefinition(SSAUseInfo useInfo, SSAValue *value) {
Chris Lattner6119d382018-07-20 18:41:34 -07001362 auto &entries = values[useInfo.name];
Chris Lattner7f9cc272018-07-19 08:35:28 -07001363
Chris Lattner6119d382018-07-20 18:41:34 -07001364 // Make sure there is a slot for this value.
1365 if (entries.size() <= useInfo.number)
1366 entries.resize(useInfo.number + 1);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001367
Chris Lattner6119d382018-07-20 18:41:34 -07001368 // If we already have an entry for this, check to see if it was a definition
1369 // or a forward reference.
1370 if (auto *existing = entries[useInfo.number].first) {
1371 if (!isForwardReferencePlaceholder(existing)) {
1372 emitError(useInfo.loc,
1373 "redefinition of SSA value '" + useInfo.name + "'");
1374 return emitError(entries[useInfo.number].second,
1375 "previously defined here");
1376 }
1377
1378 // If it was a forward reference, update everything that used it to use the
1379 // actual definition instead, delete the forward ref, and remove it from our
1380 // set of forward references we track.
1381 existing->replaceAllUsesWith(value);
1382 existing->getDefiningInst()->destroy();
1383 forwardReferencePlaceholders.erase(existing);
1384 }
1385
1386 entries[useInfo.number].first = value;
1387 entries[useInfo.number].second = useInfo.loc;
1388 return ParseSuccess;
1389}
1390
1391/// After the function is finished parsing, this function checks to see if
1392/// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001393ParseResult FunctionParser::finalizeFunction(Function *func, SMLoc loc) {
Chris Lattner6119d382018-07-20 18:41:34 -07001394 // Check for any forward references that are left. If we find any, error out.
1395 if (!forwardReferencePlaceholders.empty()) {
1396 SmallVector<std::pair<const char *, SSAValue *>, 4> errors;
1397 // Iteration over the map isn't determinstic, so sort by source location.
1398 for (auto entry : forwardReferencePlaceholders)
1399 errors.push_back({entry.second.getPointer(), entry.first});
1400 llvm::array_pod_sort(errors.begin(), errors.end());
1401
1402 for (auto entry : errors)
1403 emitError(SMLoc::getFromPointer(entry.first),
1404 "use of undeclared SSA value name");
1405 return ParseFailure;
1406 }
1407
Chris Lattner40746442018-07-21 14:32:09 -07001408 // Run the verifier on this function. If an error is detected, report it.
1409 std::string errorString;
1410 if (func->verify(&errorString))
1411 return emitError(loc, errorString);
1412
Chris Lattner6119d382018-07-20 18:41:34 -07001413 return ParseSuccess;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001414}
1415
Chris Lattner78276e32018-07-07 15:48:26 -07001416/// Parse a SSA operand for an instruction or statement.
1417///
James Molloy61a656c2018-07-22 15:45:24 -07001418/// ssa-use ::= ssa-id
Chris Lattner78276e32018-07-07 15:48:26 -07001419///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001420ParseResult FunctionParser::parseSSAUse(SSAUseInfo &result) {
Chris Lattner6119d382018-07-20 18:41:34 -07001421 result.name = getTokenSpelling();
1422 result.number = 0;
1423 result.loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001424 if (parseToken(Token::percent_identifier, "expected SSA operand"))
1425 return ParseFailure;
Chris Lattner6119d382018-07-20 18:41:34 -07001426
1427 // If we have an affine map ID, it is a result number.
1428 if (getToken().is(Token::hash_identifier)) {
1429 if (auto value = getToken().getHashIdentifierNumber())
1430 result.number = value.getValue();
1431 else
1432 return emitError("invalid SSA value result number");
1433 consumeToken(Token::hash_identifier);
1434 }
1435
Chris Lattner7f9cc272018-07-19 08:35:28 -07001436 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001437}
1438
1439/// Parse a (possibly empty) list of SSA operands.
1440///
1441/// ssa-use-list ::= ssa-use (`,` ssa-use)*
1442/// ssa-use-list-opt ::= ssa-use-list?
1443///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001444ParseResult
Chris Lattner40746442018-07-21 14:32:09 -07001445FunctionParser::parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results) {
Chris Lattner85ee1512018-07-25 11:15:20 -07001446 if (getToken().isNot(Token::percent_identifier))
Chris Lattner40746442018-07-21 14:32:09 -07001447 return ParseSuccess;
1448 return parseCommaSeparatedList([&]() -> ParseResult {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001449 SSAUseInfo result;
1450 if (parseSSAUse(result))
1451 return ParseFailure;
1452 results.push_back(result);
1453 return ParseSuccess;
1454 });
Chris Lattner78276e32018-07-07 15:48:26 -07001455}
1456
1457/// Parse an SSA use with an associated type.
1458///
1459/// ssa-use-and-type ::= ssa-use `:` type
James Molloy61a656c2018-07-22 15:45:24 -07001460template <typename ResultType>
1461ResultType FunctionParser::parseSSADefOrUseAndType(
1462 const std::function<ResultType(SSAUseInfo, Type *)> &action) {
Chris Lattner78276e32018-07-07 15:48:26 -07001463
Chris Lattnerf7702a62018-07-23 17:30:01 -07001464 SSAUseInfo useInfo;
1465 if (parseSSAUse(useInfo) ||
1466 parseToken(Token::colon, "expected ':' and type for SSA operand"))
1467 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001468
Chris Lattner7f9cc272018-07-19 08:35:28 -07001469 auto *type = parseType();
1470 if (!type)
1471 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001472
James Molloy61a656c2018-07-22 15:45:24 -07001473 return action(useInfo, type);
Chris Lattner78276e32018-07-07 15:48:26 -07001474}
1475
Chris Lattner2c402672018-07-23 11:56:17 -07001476/// Parse a (possibly empty) list of SSA operands, followed by a colon, then
1477/// followed by a type list. If hasParens is true, then the operands are
1478/// surrounded by parens.
Chris Lattner78276e32018-07-07 15:48:26 -07001479///
Chris Lattner2c402672018-07-23 11:56:17 -07001480/// ssa-use-and-type-list[parens]
1481/// ::= `(` ssa-use-list `)` ':' type-list-no-parens
1482///
1483/// ssa-use-and-type-list[!parens]
1484/// ::= ssa-use-list ':' type-list-no-parens
Chris Lattner78276e32018-07-07 15:48:26 -07001485///
Chris Lattner40746442018-07-21 14:32:09 -07001486template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001487ParseResult FunctionParser::parseOptionalSSAUseAndTypeList(
Chris Lattner2c402672018-07-23 11:56:17 -07001488 SmallVectorImpl<ValueTy *> &results, bool isParenthesized) {
1489
1490 // If we are in the parenthesized form and no paren exists, then we succeed
1491 // with an empty list.
1492 if (isParenthesized && !consumeIf(Token::l_paren))
Chris Lattner40746442018-07-21 14:32:09 -07001493 return ParseSuccess;
1494
Chris Lattner2c402672018-07-23 11:56:17 -07001495 SmallVector<SSAUseInfo, 4> valueIDs;
1496 if (parseOptionalSSAUseList(valueIDs))
Chris Lattner7f9cc272018-07-19 08:35:28 -07001497 return ParseFailure;
Chris Lattner2c402672018-07-23 11:56:17 -07001498
1499 if (isParenthesized && !consumeIf(Token::r_paren))
1500 return emitError("expected ')' in operand list");
1501
1502 // If there were no operands, then there is no colon or type lists.
1503 if (valueIDs.empty())
1504 return ParseSuccess;
1505
Chris Lattner2c402672018-07-23 11:56:17 -07001506 SmallVector<Type *, 4> types;
Chris Lattnerf7702a62018-07-23 17:30:01 -07001507 if (parseToken(Token::colon, "expected ':' in operand list") ||
1508 parseTypeListNoParens(types))
Chris Lattner2c402672018-07-23 11:56:17 -07001509 return ParseFailure;
1510
1511 if (valueIDs.size() != types.size())
1512 return emitError("expected " + Twine(valueIDs.size()) +
1513 " types to match operand list");
1514
1515 results.reserve(valueIDs.size());
1516 for (unsigned i = 0, e = valueIDs.size(); i != e; ++i) {
1517 if (auto *value = resolveSSAUse(valueIDs[i], types[i]))
1518 results.push_back(cast<ValueTy>(value));
1519 else
1520 return ParseFailure;
1521 }
1522
1523 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001524}
1525
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001526/// Parse the CFG or MLFunc operation.
1527///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001528/// operation ::=
1529/// (ssa-id `=`)? string '(' ssa-use-list? ')' attribute-dict?
1530/// `:` function-type
1531///
1532ParseResult
Chris Lattner7f9cc272018-07-19 08:35:28 -07001533FunctionParser::parseOperation(const CreateOperationFunction &createOpFunc) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001534 auto loc = getToken().getLoc();
1535
1536 StringRef resultID;
1537 if (getToken().is(Token::percent_identifier)) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001538 resultID = getTokenSpelling();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001539 consumeToken(Token::percent_identifier);
Chris Lattnerf7702a62018-07-23 17:30:01 -07001540 if (parseToken(Token::equal, "expected '=' after SSA name"))
1541 return ParseFailure;
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001542 }
1543
Chris Lattner85ee1512018-07-25 11:15:20 -07001544 Operation *op;
1545 if (getToken().is(Token::bare_identifier) || getToken().isKeyword())
1546 op = parseCustomOperation(createOpFunc);
1547 else if (getToken().is(Token::string))
1548 op = parseVerboseOperation(createOpFunc);
1549 else
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001550 return emitError("expected operation name in quotes");
1551
Chris Lattner85ee1512018-07-25 11:15:20 -07001552 // If parsing of the basic operation failed, then this whole thing fails.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001553 if (!op)
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001554 return ParseFailure;
1555
1556 // We just parsed an operation. If it is a recognized one, verify that it
1557 // is structurally as we expect. If not, produce an error with a reasonable
1558 // source location.
Chris Lattner95865062018-08-01 10:18:59 -07001559 if (auto *opInfo = op->getAbstractOperation()) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001560 if (auto error = opInfo->verifyInvariants(op))
Chris Lattner9361fb32018-07-24 08:34:58 -07001561 return emitError(loc, Twine("'") + op->getName().str() + "' op " + error);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001562 }
1563
Chris Lattner7f9cc272018-07-19 08:35:28 -07001564 // If the instruction had a name, register it.
1565 if (!resultID.empty()) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001566 if (op->getNumResults() == 0)
1567 return emitError(loc, "cannot name an operation with no results");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001568
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001569 for (unsigned i = 0, e = op->getNumResults(); i != e; ++i)
1570 addDefinition({resultID, i, loc}, op->getResult(i));
Chris Lattner7f9cc272018-07-19 08:35:28 -07001571 }
1572
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001573 return ParseSuccess;
1574}
Chris Lattnere79379a2018-06-22 10:39:19 -07001575
Chris Lattner85ee1512018-07-25 11:15:20 -07001576Operation *FunctionParser::parseVerboseOperation(
1577 const CreateOperationFunction &createOpFunc) {
1578 auto name = getToken().getStringValue();
1579 if (name.empty())
1580 return (emitError("empty operation name is invalid"), nullptr);
1581
1582 consumeToken(Token::string);
1583
1584 // Parse the operand list.
1585 SmallVector<SSAUseInfo, 8> operandInfos;
1586
1587 if (parseToken(Token::l_paren, "expected '(' to start operand list") ||
1588 parseOptionalSSAUseList(operandInfos) ||
1589 parseToken(Token::r_paren, "expected ')' to end operand list")) {
1590 return nullptr;
1591 }
1592
1593 SmallVector<NamedAttribute, 4> attributes;
1594 if (getToken().is(Token::l_brace)) {
1595 if (parseAttributeDict(attributes))
1596 return nullptr;
1597 }
1598
1599 if (parseToken(Token::colon, "expected ':' followed by instruction type"))
1600 return nullptr;
1601
1602 auto typeLoc = getToken().getLoc();
1603 auto type = parseType();
1604 if (!type)
1605 return nullptr;
1606 auto fnType = dyn_cast<FunctionType>(type);
1607 if (!fnType)
1608 return (emitError(typeLoc, "expected function type"), nullptr);
1609
1610 // Check that we have the right number of types for the operands.
1611 auto operandTypes = fnType->getInputs();
1612 if (operandTypes.size() != operandInfos.size()) {
1613 auto plural = "s"[operandInfos.size() == 1];
1614 return (emitError(typeLoc, "expected " + llvm::utostr(operandInfos.size()) +
1615 " operand type" + plural + " but had " +
1616 llvm::utostr(operandTypes.size())),
1617 nullptr);
1618 }
1619
1620 // Resolve all of the operands.
1621 SmallVector<SSAValue *, 8> operands;
1622 for (unsigned i = 0, e = operandInfos.size(); i != e; ++i) {
1623 operands.push_back(resolveSSAUse(operandInfos[i], operandTypes[i]));
1624 if (!operands.back())
1625 return nullptr;
1626 }
1627
1628 auto nameId = builder.getIdentifier(name);
1629 return createOpFunc(nameId, operands, fnType->getResults(), attributes);
1630}
1631
1632namespace {
1633class CustomOpAsmParser : public OpAsmParser {
1634public:
1635 CustomOpAsmParser(SMLoc nameLoc, StringRef opName, FunctionParser &parser)
1636 : nameLoc(nameLoc), opName(opName), parser(parser) {}
1637
1638 /// This is an internal helper to parser a colon, we don't want to expose
1639 /// this to clients.
1640 bool internalParseColon(llvm::SMLoc *loc) {
1641 if (loc)
1642 *loc = parser.getToken().getLoc();
1643 return parser.parseToken(Token::colon, "expected ':'");
1644 }
1645
1646 //===--------------------------------------------------------------------===//
1647 // High level parsing methods.
1648 //===--------------------------------------------------------------------===//
1649
1650 bool parseComma(llvm::SMLoc *loc = nullptr) override {
1651 if (loc)
1652 *loc = parser.getToken().getLoc();
1653 return parser.parseToken(Token::comma, "expected ','");
1654 }
1655
1656 bool parseColonType(Type *&result, llvm::SMLoc *loc = nullptr) override {
1657 return internalParseColon(loc) || !(result = parser.parseType());
1658 }
1659
1660 bool parseColonTypeList(SmallVectorImpl<Type *> &result,
1661 llvm::SMLoc *loc = nullptr) override {
1662 if (internalParseColon(loc))
1663 return true;
1664
1665 do {
1666 if (auto *type = parser.parseType())
1667 result.push_back(type);
1668 else
1669 return true;
1670
1671 } while (parser.consumeIf(Token::comma));
1672 return false;
1673 }
1674
Chris Lattner85cf26d2018-08-02 16:54:36 -07001675 /// Parse an arbitrary attribute and return it in result. This also adds the
1676 /// attribute to the specified attribute list with the specified name. this
1677 /// captures the location of the attribute in 'loc' if it is non-null.
1678 bool parseAttribute(Attribute *&result, const char *attrName,
1679 SmallVectorImpl<NamedAttribute> &attrs,
1680 llvm::SMLoc *loc = nullptr) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001681 if (loc)
1682 *loc = parser.getToken().getLoc();
1683 result = parser.parseAttribute();
Chris Lattner85cf26d2018-08-02 16:54:36 -07001684 if (!result)
1685 return true;
1686
1687 attrs.push_back(
1688 NamedAttribute(parser.builder.getIdentifier(attrName), result));
1689 return false;
1690 }
1691
1692 /// If a named attribute list is present, parse is into result.
1693 bool parseOptionalAttributeDict(SmallVectorImpl<NamedAttribute> &result,
1694 llvm::SMLoc *loc = nullptr) override {
1695 if (parser.getToken().isNot(Token::l_brace))
1696 return false;
1697 if (loc)
1698 *loc = parser.getToken().getLoc();
1699 return parser.parseAttributeDict(result) == ParseFailure;
Chris Lattner85ee1512018-07-25 11:15:20 -07001700 }
1701
1702 bool parseOperand(OperandType &result) override {
1703 FunctionParser::SSAUseInfo useInfo;
1704 if (parser.parseSSAUse(useInfo))
1705 return true;
1706
1707 result = {useInfo.loc, useInfo.name, useInfo.number};
1708 return false;
1709 }
1710
1711 bool parseOperandList(SmallVectorImpl<OperandType> &result,
1712 int requiredOperandCount = -1,
Chris Lattner85cf26d2018-08-02 16:54:36 -07001713 Delimiter delimiter = Delimiter::None) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001714 auto startLoc = parser.getToken().getLoc();
1715
Chris Lattner85cf26d2018-08-02 16:54:36 -07001716 // Handle delimiters.
1717 switch (delimiter) {
1718 case Delimiter::None:
Chris Lattner85ee1512018-07-25 11:15:20 -07001719 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001720 case Delimiter::OptionalParen:
Chris Lattner3164ae62018-07-28 09:36:25 -07001721 if (parser.getToken().isNot(Token::l_paren))
1722 return false;
1723 LLVM_FALLTHROUGH;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001724 case Delimiter::Paren:
Chris Lattner85ee1512018-07-25 11:15:20 -07001725 if (parser.parseToken(Token::l_paren, "expected '(' in operand list"))
1726 return true;
1727 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001728 case Delimiter::OptionalSquare:
Chris Lattner3164ae62018-07-28 09:36:25 -07001729 if (parser.getToken().isNot(Token::l_square))
1730 return false;
1731 LLVM_FALLTHROUGH;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001732 case Delimiter::Square:
Chris Lattner85ee1512018-07-25 11:15:20 -07001733 if (parser.parseToken(Token::l_square, "expected '[' in operand list"))
1734 return true;
1735 break;
1736 }
1737
1738 // Check for zero operands.
1739 if (parser.getToken().is(Token::percent_identifier)) {
1740 do {
1741 OperandType operand;
1742 if (parseOperand(operand))
1743 return true;
1744 result.push_back(operand);
1745 } while (parser.consumeIf(Token::comma));
1746 }
1747
Chris Lattner85cf26d2018-08-02 16:54:36 -07001748 // Handle delimiters. If we reach here, the optional delimiters were
Chris Lattner3164ae62018-07-28 09:36:25 -07001749 // present, so we need to parse their closing one.
Chris Lattner85cf26d2018-08-02 16:54:36 -07001750 switch (delimiter) {
1751 case Delimiter::None:
Chris Lattner85ee1512018-07-25 11:15:20 -07001752 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001753 case Delimiter::OptionalParen:
1754 case Delimiter::Paren:
Chris Lattner85ee1512018-07-25 11:15:20 -07001755 if (parser.parseToken(Token::r_paren, "expected ')' in operand list"))
1756 return true;
1757 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001758 case Delimiter::OptionalSquare:
1759 case Delimiter::Square:
Chris Lattner85ee1512018-07-25 11:15:20 -07001760 if (parser.parseToken(Token::r_square, "expected ']' in operand list"))
1761 return true;
1762 break;
1763 }
1764
1765 if (requiredOperandCount != -1 && result.size() != requiredOperandCount)
1766 emitError(startLoc,
1767 "expected " + Twine(requiredOperandCount) + " operands");
1768 return false;
1769 }
1770
1771 //===--------------------------------------------------------------------===//
1772 // Methods for interacting with the parser
1773 //===--------------------------------------------------------------------===//
1774
1775 Builder &getBuilder() const override { return parser.builder; }
1776
1777 llvm::SMLoc getNameLoc() const override { return nameLoc; }
1778
1779 bool resolveOperand(OperandType operand, Type *type,
1780 SSAValue *&result) override {
1781 FunctionParser::SSAUseInfo operandInfo = {operand.name, operand.number,
1782 operand.location};
1783 result = parser.resolveSSAUse(operandInfo, type);
1784 return result == nullptr;
1785 }
1786
1787 /// Emit a diagnostic at the specified location.
1788 void emitError(llvm::SMLoc loc, const Twine &message) override {
1789 parser.emitError(loc, "custom op '" + Twine(opName) + "' " + message);
1790 emittedError = true;
1791 }
1792
1793 bool didEmitError() const { return emittedError; }
1794
1795private:
1796 SMLoc nameLoc;
1797 StringRef opName;
1798 FunctionParser &parser;
1799 bool emittedError = false;
1800};
1801} // end anonymous namespace.
1802
1803Operation *FunctionParser::parseCustomOperation(
1804 const CreateOperationFunction &createOpFunc) {
1805 auto opLoc = getToken().getLoc();
1806 auto opName = getTokenSpelling();
1807 CustomOpAsmParser opAsmParser(opLoc, opName, *this);
1808
1809 auto *opDefinition = getOperationSet().lookup(opName);
1810 if (!opDefinition) {
1811 opAsmParser.emitError(opLoc, "is unknown");
1812 return nullptr;
1813 }
1814
1815 consumeToken();
1816
1817 // Have the op implementation take a crack and parsing this.
1818 auto result = opDefinition->parseAssembly(&opAsmParser);
1819
1820 // If it emitted an error, we failed.
1821 if (opAsmParser.didEmitError())
1822 return nullptr;
1823
1824 // Otherwise, we succeeded. Use the state it parsed as our op information.
1825 auto nameId = builder.getIdentifier(opName);
1826 return createOpFunc(nameId, result.operands, result.types, result.attributes);
1827}
1828
Chris Lattner48af7d12018-07-09 19:05:38 -07001829//===----------------------------------------------------------------------===//
1830// CFG Functions
1831//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001832
Chris Lattner4c95a502018-06-23 16:03:42 -07001833namespace {
Chris Lattner48af7d12018-07-09 19:05:38 -07001834/// This is a specialized parser for CFGFunction's, maintaining the state
1835/// transient to their bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001836class CFGFunctionParser : public FunctionParser {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001837public:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001838 CFGFunctionParser(ParserState &state, CFGFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001839 : FunctionParser(state, Kind::CFGFunc), function(function),
1840 builder(function) {}
Chris Lattner2e595eb2018-07-10 10:08:27 -07001841
1842 ParseResult parseFunctionBody();
1843
1844private:
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001845 CFGFunction *function;
James Molloy0ff71542018-07-23 16:56:32 -07001846 llvm::StringMap<std::pair<BasicBlock *, SMLoc>> blocksByName;
Chris Lattner48af7d12018-07-09 19:05:38 -07001847
1848 /// This builder intentionally shadows the builder in the base class, with a
1849 /// more specific builder type.
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001850 CFGFuncBuilder builder;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001851
Chris Lattner4c95a502018-06-23 16:03:42 -07001852 /// Get the basic block with the specified name, creating it if it doesn't
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001853 /// already exist. The location specified is the point of use, which allows
1854 /// us to diagnose references to blocks that are not defined precisely.
1855 BasicBlock *getBlockNamed(StringRef name, SMLoc loc) {
1856 auto &blockAndLoc = blocksByName[name];
1857 if (!blockAndLoc.first) {
Chris Lattner3a467cc2018-07-01 20:28:00 -07001858 blockAndLoc.first = new BasicBlock();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001859 blockAndLoc.second = loc;
Chris Lattner4c95a502018-06-23 16:03:42 -07001860 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001861 return blockAndLoc.first;
Chris Lattner4c95a502018-06-23 16:03:42 -07001862 }
Chris Lattner48af7d12018-07-09 19:05:38 -07001863
James Molloy61a656c2018-07-22 15:45:24 -07001864 ParseResult
1865 parseOptionalBasicBlockArgList(SmallVectorImpl<BBArgument *> &results,
1866 BasicBlock *owner);
James Molloy4f788372018-07-24 15:01:27 -07001867 ParseResult parseBranchBlockAndUseList(BasicBlock *&block,
1868 SmallVectorImpl<CFGValue *> &values);
James Molloy61a656c2018-07-22 15:45:24 -07001869
Chris Lattner48af7d12018-07-09 19:05:38 -07001870 ParseResult parseBasicBlock();
1871 OperationInst *parseCFGOperation();
1872 TerminatorInst *parseTerminator();
Chris Lattner4c95a502018-06-23 16:03:42 -07001873};
1874} // end anonymous namespace
1875
James Molloy61a656c2018-07-22 15:45:24 -07001876/// Parse a (possibly empty) list of SSA operands with types as basic block
Chris Lattner2c402672018-07-23 11:56:17 -07001877/// arguments.
James Molloy61a656c2018-07-22 15:45:24 -07001878///
1879/// ssa-id-and-type-list ::= ssa-id-and-type (`,` ssa-id-and-type)*
1880///
1881ParseResult CFGFunctionParser::parseOptionalBasicBlockArgList(
1882 SmallVectorImpl<BBArgument *> &results, BasicBlock *owner) {
1883 if (getToken().is(Token::r_brace))
1884 return ParseSuccess;
1885
1886 return parseCommaSeparatedList([&]() -> ParseResult {
1887 auto type = parseSSADefOrUseAndType<Type *>(
1888 [&](SSAUseInfo useInfo, Type *type) -> Type * {
1889 BBArgument *arg = owner->addArgument(type);
1890 if (addDefinition(useInfo, arg) == ParseFailure)
1891 return nullptr;
1892 return type;
1893 });
1894 return type ? ParseSuccess : ParseFailure;
1895 });
1896}
1897
Chris Lattner48af7d12018-07-09 19:05:38 -07001898ParseResult CFGFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07001899 auto braceLoc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001900 if (parseToken(Token::l_brace, "expected '{' in CFG function"))
1901 return ParseFailure;
Chris Lattner48af7d12018-07-09 19:05:38 -07001902
1903 // Make sure we have at least one block.
1904 if (getToken().is(Token::r_brace))
1905 return emitError("CFG functions must have at least one basic block");
Chris Lattner4c95a502018-06-23 16:03:42 -07001906
1907 // Parse the list of blocks.
1908 while (!consumeIf(Token::r_brace))
Chris Lattner48af7d12018-07-09 19:05:38 -07001909 if (parseBasicBlock())
Chris Lattner4c95a502018-06-23 16:03:42 -07001910 return ParseFailure;
1911
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001912 // Verify that all referenced blocks were defined. Iteration over a
1913 // StringMap isn't determinstic, but this is good enough for our purposes.
Chris Lattner48af7d12018-07-09 19:05:38 -07001914 for (auto &elt : blocksByName) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001915 auto *bb = elt.second.first;
Chris Lattner3a467cc2018-07-01 20:28:00 -07001916 if (!bb->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001917 return emitError(elt.second.second,
James Molloy0ff71542018-07-23 16:56:32 -07001918 "reference to an undefined basic block '" + elt.first() +
1919 "'");
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001920 }
1921
Chris Lattnera8e47672018-07-25 14:08:16 -07001922 getModule()->getFunctions().push_back(function);
Chris Lattner6119d382018-07-20 18:41:34 -07001923
Chris Lattner40746442018-07-21 14:32:09 -07001924 return finalizeFunction(function, braceLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001925}
1926
1927/// Basic block declaration.
1928///
1929/// basic-block ::= bb-label instruction* terminator-stmt
1930/// bb-label ::= bb-id bb-arg-list? `:`
1931/// bb-id ::= bare-id
1932/// bb-arg-list ::= `(` ssa-id-and-type-list? `)`
1933///
Chris Lattner48af7d12018-07-09 19:05:38 -07001934ParseResult CFGFunctionParser::parseBasicBlock() {
1935 SMLoc nameLoc = getToken().getLoc();
1936 auto name = getTokenSpelling();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001937 if (parseToken(Token::bare_identifier, "expected basic block name"))
1938 return ParseFailure;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001939
Chris Lattner48af7d12018-07-09 19:05:38 -07001940 auto *block = getBlockNamed(name, nameLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07001941
1942 // If this block has already been parsed, then this is a redefinition with the
1943 // same block name.
Chris Lattner3a467cc2018-07-01 20:28:00 -07001944 if (block->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001945 return emitError(nameLoc, "redefinition of block '" + name.str() + "'");
1946
Chris Lattner78276e32018-07-07 15:48:26 -07001947 // If an argument list is present, parse it.
1948 if (consumeIf(Token::l_paren)) {
James Molloy61a656c2018-07-22 15:45:24 -07001949 SmallVector<BBArgument *, 8> bbArgs;
Chris Lattnerf7702a62018-07-23 17:30:01 -07001950 if (parseOptionalBasicBlockArgList(bbArgs, block) ||
1951 parseToken(Token::r_paren, "expected ')' to end argument list"))
Chris Lattner78276e32018-07-07 15:48:26 -07001952 return ParseFailure;
Chris Lattner78276e32018-07-07 15:48:26 -07001953 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001954
James Molloy61a656c2018-07-22 15:45:24 -07001955 // Add the block to the function.
1956 function->push_back(block);
1957
Chris Lattnerf7702a62018-07-23 17:30:01 -07001958 if (parseToken(Token::colon, "expected ':' after basic block name"))
1959 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07001960
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001961 // Set the insertion point to the block we want to insert new operations into.
Chris Lattner48af7d12018-07-09 19:05:38 -07001962 builder.setInsertionPoint(block);
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001963
Chris Lattner7f9cc272018-07-19 08:35:28 -07001964 auto createOpFunc = [&](Identifier name, ArrayRef<SSAValue *> operands,
1965 ArrayRef<Type *> resultTypes,
1966 ArrayRef<NamedAttribute> attrs) -> Operation * {
1967 SmallVector<CFGValue *, 8> cfgOperands;
1968 cfgOperands.reserve(operands.size());
1969 for (auto *op : operands)
1970 cfgOperands.push_back(cast<CFGValue>(op));
1971 return builder.createOperation(name, cfgOperands, resultTypes, attrs);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001972 };
1973
Chris Lattnered65a732018-06-28 20:45:33 -07001974 // Parse the list of operations that make up the body of the block.
James Molloy4f788372018-07-24 15:01:27 -07001975 while (getToken().isNot(Token::kw_return, Token::kw_br, Token::kw_cond_br)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001976 if (parseOperation(createOpFunc))
Chris Lattnered65a732018-06-28 20:45:33 -07001977 return ParseFailure;
1978 }
Chris Lattner4c95a502018-06-23 16:03:42 -07001979
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001980 if (!parseTerminator())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001981 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07001982
1983 return ParseSuccess;
1984}
1985
James Molloy4f788372018-07-24 15:01:27 -07001986ParseResult CFGFunctionParser::parseBranchBlockAndUseList(
1987 BasicBlock *&block, SmallVectorImpl<CFGValue *> &values) {
1988 block = getBlockNamed(getTokenSpelling(), getToken().getLoc());
1989 if (parseToken(Token::bare_identifier, "expected basic block name"))
1990 return ParseFailure;
1991
1992 if (!consumeIf(Token::l_paren))
1993 return ParseSuccess;
1994 if (parseOptionalSSAUseAndTypeList(values, /*isParenthesized*/ false) ||
1995 parseToken(Token::r_paren, "expected ')' to close argument list"))
1996 return ParseFailure;
1997 return ParseSuccess;
1998}
1999
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002000/// Parse the terminator instruction for a basic block.
2001///
2002/// terminator-stmt ::= `br` bb-id branch-use-list?
Chris Lattner1604e472018-07-23 08:42:19 -07002003/// branch-use-list ::= `(` ssa-use-list `)` ':' type-list-no-parens
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002004/// terminator-stmt ::=
2005/// `cond_br` ssa-use `,` bb-id branch-use-list? `,` bb-id branch-use-list?
2006/// terminator-stmt ::= `return` ssa-use-and-type-list?
2007///
Chris Lattner48af7d12018-07-09 19:05:38 -07002008TerminatorInst *CFGFunctionParser::parseTerminator() {
2009 switch (getToken().getKind()) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002010 default:
Chris Lattner3a467cc2018-07-01 20:28:00 -07002011 return (emitError("expected terminator at end of basic block"), nullptr);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002012
Chris Lattner40746442018-07-21 14:32:09 -07002013 case Token::kw_return: {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002014 consumeToken(Token::kw_return);
Chris Lattner40746442018-07-21 14:32:09 -07002015
Chris Lattner2c402672018-07-23 11:56:17 -07002016 // Parse any operands.
2017 SmallVector<CFGValue *, 8> operands;
2018 if (parseOptionalSSAUseAndTypeList(operands, /*isParenthesized*/ false))
2019 return nullptr;
2020 return builder.createReturnInst(operands);
Chris Lattner40746442018-07-21 14:32:09 -07002021 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002022
2023 case Token::kw_br: {
2024 consumeToken(Token::kw_br);
James Molloy4f788372018-07-24 15:01:27 -07002025 BasicBlock *destBB;
2026 SmallVector<CFGValue *, 4> values;
2027 if (parseBranchBlockAndUseList(destBB, values))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002028 return nullptr;
Chris Lattner1604e472018-07-23 08:42:19 -07002029 auto branch = builder.createBranchInst(destBB);
James Molloy4f788372018-07-24 15:01:27 -07002030 branch->addOperands(values);
Chris Lattner1604e472018-07-23 08:42:19 -07002031 return branch;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002032 }
James Molloy4f788372018-07-24 15:01:27 -07002033
2034 case Token::kw_cond_br: {
2035 consumeToken(Token::kw_cond_br);
2036 SSAUseInfo ssaUse;
2037 if (parseSSAUse(ssaUse))
2038 return nullptr;
2039 auto *cond = resolveSSAUse(ssaUse, builder.getIntegerType(1));
2040 if (!cond)
2041 return (emitError("expected type was boolean (i1)"), nullptr);
2042 if (parseToken(Token::comma, "expected ',' in conditional branch"))
2043 return nullptr;
2044
2045 BasicBlock *trueBlock;
2046 SmallVector<CFGValue *, 4> trueOperands;
2047 if (parseBranchBlockAndUseList(trueBlock, trueOperands))
2048 return nullptr;
2049
2050 if (parseToken(Token::comma, "expected ',' in conditional branch"))
2051 return nullptr;
2052
2053 BasicBlock *falseBlock;
2054 SmallVector<CFGValue *, 4> falseOperands;
2055 if (parseBranchBlockAndUseList(falseBlock, falseOperands))
2056 return nullptr;
2057
2058 auto branch = builder.createCondBranchInst(cast<CFGValue>(cond), trueBlock,
2059 falseBlock);
2060 branch->addTrueOperands(trueOperands);
2061 branch->addFalseOperands(falseOperands);
2062 return branch;
2063 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002064 }
2065}
2066
Chris Lattner48af7d12018-07-09 19:05:38 -07002067//===----------------------------------------------------------------------===//
2068// ML Functions
2069//===----------------------------------------------------------------------===//
2070
2071namespace {
2072/// Refined parser for MLFunction bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07002073class MLFunctionParser : public FunctionParser {
Chris Lattner48af7d12018-07-09 19:05:38 -07002074public:
Chris Lattner48af7d12018-07-09 19:05:38 -07002075 MLFunctionParser(ParserState &state, MLFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07002076 : FunctionParser(state, Kind::MLFunc), function(function),
2077 builder(function) {}
Chris Lattner48af7d12018-07-09 19:05:38 -07002078
2079 ParseResult parseFunctionBody();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002080
2081private:
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002082 MLFunction *function;
2083
2084 /// This builder intentionally shadows the builder in the base class, with a
2085 /// more specific builder type.
2086 MLFuncBuilder builder;
2087
2088 ParseResult parseForStmt();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002089 AffineConstantExpr *parseIntConstant();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002090 ParseResult parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002091 ParseResult parseElseClause(IfClause *elseClause);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002092 ParseResult parseStatements(StmtBlock *block);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002093 ParseResult parseStmtBlock(StmtBlock *block);
Chris Lattner48af7d12018-07-09 19:05:38 -07002094};
2095} // end anonymous namespace
2096
Chris Lattner48af7d12018-07-09 19:05:38 -07002097ParseResult MLFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07002098 auto braceLoc = getToken().getLoc();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002099 // Parse statements in this function
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002100
Chris Lattnerf7702a62018-07-23 17:30:01 -07002101 if (parseToken(Token::l_brace, "expected '{' in ML function") ||
2102 parseStatements(function)) {
2103 return ParseFailure;
2104 }
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002105
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002106 // TODO: store return operands in the IR.
2107 SmallVector<SSAUseInfo, 4> dummyUseInfo;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002108
Chris Lattnerf7702a62018-07-23 17:30:01 -07002109 if (parseToken(Token::kw_return,
2110 "ML function must end with return statement") ||
2111 parseOptionalSSAUseList(dummyUseInfo) ||
2112 parseToken(Token::r_brace, "expected '}' to end mlfunc"))
2113 return ParseFailure;
Chris Lattner40746442018-07-21 14:32:09 -07002114
Chris Lattnera8e47672018-07-25 14:08:16 -07002115 getModule()->getFunctions().push_back(function);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002116
Chris Lattner40746442018-07-21 14:32:09 -07002117 return finalizeFunction(function, braceLoc);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002118}
2119
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002120/// For statement.
2121///
Chris Lattner48af7d12018-07-09 19:05:38 -07002122/// ml-for-stmt ::= `for` ssa-id `=` lower-bound `to` upper-bound
2123/// (`step` integer-literal)? `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002124///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002125ParseResult MLFunctionParser::parseForStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002126 consumeToken(Token::kw_for);
2127
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002128 // Parse induction variable
2129 if (getToken().isNot(Token::percent_identifier))
2130 return emitError("expected SSA identifier for the loop variable");
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002131
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002132 auto loc = getToken().getLoc();
Tatiana Shpeismand880b352018-07-31 23:14:16 -07002133 StringRef inductionVariableName = getTokenSpelling();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002134 consumeToken(Token::percent_identifier);
2135
Chris Lattnerf7702a62018-07-23 17:30:01 -07002136 if (parseToken(Token::equal, "expected ="))
2137 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002138
2139 // Parse loop bounds
2140 AffineConstantExpr *lowerBound = parseIntConstant();
2141 if (!lowerBound)
2142 return ParseFailure;
2143
Chris Lattnerf7702a62018-07-23 17:30:01 -07002144 if (parseToken(Token::kw_to, "expected 'to' between bounds"))
2145 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002146
2147 AffineConstantExpr *upperBound = parseIntConstant();
2148 if (!upperBound)
2149 return ParseFailure;
2150
2151 // Parse step
2152 AffineConstantExpr *step = nullptr;
2153 if (consumeIf(Token::kw_step)) {
2154 step = parseIntConstant();
2155 if (!step)
2156 return ParseFailure;
2157 }
2158
2159 // Create for statement.
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002160 ForStmt *forStmt = builder.createFor(lowerBound, upperBound, step);
2161
2162 // Create SSA value definition for the induction variable.
Tatiana Shpeismanc9c4b342018-07-31 07:40:14 -07002163 addDefinition({inductionVariableName, 0, loc}, forStmt);
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002164
2165 // If parsing of the for statement body fails,
2166 // MLIR contains for statement with those nested statements that have been
2167 // successfully parsed.
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002168 if (parseStmtBlock(forStmt))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002169 return ParseFailure;
2170
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002171 // Reset insertion point to the current block.
2172 builder.setInsertionPoint(forStmt->getBlock());
2173
Tatiana Shpeismand880b352018-07-31 23:14:16 -07002174 // TODO: remove definition of the induction variable.
2175
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002176 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002177}
2178
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002179// This method is temporary workaround to parse simple loop bounds and
2180// step.
2181// TODO: remove this method once it's no longer used.
2182AffineConstantExpr *MLFunctionParser::parseIntConstant() {
2183 if (getToken().isNot(Token::integer))
2184 return (emitError("expected non-negative integer for now"), nullptr);
2185
2186 auto val = getToken().getUInt64IntegerValue();
2187 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
2188 return (emitError("constant too large for affineint"), nullptr);
2189 }
2190 consumeToken(Token::integer);
2191 return builder.getConstantExpr((int64_t)val.getValue());
2192}
2193
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002194/// If statement.
2195///
Chris Lattner48af7d12018-07-09 19:05:38 -07002196/// ml-if-head ::= `if` ml-if-cond `{` ml-stmt* `}`
2197/// | ml-if-head `else` `if` ml-if-cond `{` ml-stmt* `}`
2198/// ml-if-stmt ::= ml-if-head
2199/// | ml-if-head `else` `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002200///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002201ParseResult MLFunctionParser::parseIfStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002202 consumeToken(Token::kw_if);
Chris Lattnerf7702a62018-07-23 17:30:01 -07002203 if (parseToken(Token::l_paren, "expected ("))
2204 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002205
James Molloy0ff71542018-07-23 16:56:32 -07002206 // TODO: parse condition
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002207
Chris Lattnerf7702a62018-07-23 17:30:01 -07002208 if (parseToken(Token::r_paren, "expected )"))
2209 return ParseFailure;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002210
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002211 IfStmt *ifStmt = builder.createIf();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002212 IfClause *thenClause = ifStmt->getThenClause();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002213
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002214 // When parsing of an if statement body fails, the IR contains
2215 // the if statement with the portion of the body that has been
2216 // successfully parsed.
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002217 if (parseStmtBlock(thenClause))
2218 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002219
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002220 if (consumeIf(Token::kw_else)) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002221 auto *elseClause = ifStmt->createElseClause();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002222 if (parseElseClause(elseClause))
2223 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002224 }
2225
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002226 // Reset insertion point to the current block.
2227 builder.setInsertionPoint(ifStmt->getBlock());
2228
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002229 return ParseSuccess;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002230}
2231
2232ParseResult MLFunctionParser::parseElseClause(IfClause *elseClause) {
2233 if (getToken().is(Token::kw_if)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002234 builder.setInsertionPoint(elseClause);
2235 return parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002236 }
2237
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002238 return parseStmtBlock(elseClause);
2239}
2240
2241///
2242/// Parse a list of statements ending with `return` or `}`
2243///
2244ParseResult MLFunctionParser::parseStatements(StmtBlock *block) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07002245 auto createOpFunc = [&](Identifier name, ArrayRef<SSAValue *> operands,
2246 ArrayRef<Type *> resultTypes,
2247 ArrayRef<NamedAttribute> attrs) -> Operation * {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07002248 SmallVector<MLValue *, 8> stmtOperands;
2249 stmtOperands.reserve(operands.size());
2250 for (auto *op : operands)
2251 stmtOperands.push_back(cast<MLValue>(op));
2252 return builder.createOperation(name, stmtOperands, resultTypes, attrs);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002253 };
2254
2255 builder.setInsertionPoint(block);
2256
2257 while (getToken().isNot(Token::kw_return, Token::r_brace)) {
2258 switch (getToken().getKind()) {
2259 default:
2260 if (parseOperation(createOpFunc))
2261 return ParseFailure;
2262 break;
2263 case Token::kw_for:
2264 if (parseForStmt())
2265 return ParseFailure;
2266 break;
2267 case Token::kw_if:
2268 if (parseIfStmt())
2269 return ParseFailure;
2270 break;
2271 } // end switch
2272 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002273
2274 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002275}
2276
2277///
2278/// Parse `{` ml-stmt* `}`
2279///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002280ParseResult MLFunctionParser::parseStmtBlock(StmtBlock *block) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002281 if (parseToken(Token::l_brace, "expected '{' before statement list") ||
2282 parseStatements(block) ||
2283 parseToken(Token::r_brace,
2284 "expected '}' at the end of the statement block"))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002285 return ParseFailure;
2286
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002287 return ParseSuccess;
2288}
2289
Chris Lattner4c95a502018-06-23 16:03:42 -07002290//===----------------------------------------------------------------------===//
2291// Top-level entity parsing.
2292//===----------------------------------------------------------------------===//
2293
Chris Lattner2e595eb2018-07-10 10:08:27 -07002294namespace {
2295/// This parser handles entities that are only valid at the top level of the
2296/// file.
2297class ModuleParser : public Parser {
2298public:
2299 explicit ModuleParser(ParserState &state) : Parser(state) {}
2300
2301 ParseResult parseModule();
2302
2303private:
2304 ParseResult parseAffineMapDef();
2305
2306 // Functions.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002307 ParseResult parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2308 SmallVectorImpl<StringRef> &argNames);
2309 ParseResult parseFunctionSignature(StringRef &name, FunctionType *&type,
2310 SmallVectorImpl<StringRef> *argNames);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002311 ParseResult parseExtFunc();
2312 ParseResult parseCFGFunc();
2313 ParseResult parseMLFunc();
2314};
2315} // end anonymous namespace
2316
2317/// Affine map declaration.
2318///
2319/// affine-map-def ::= affine-map-id `=` affine-map-inline
2320///
2321ParseResult ModuleParser::parseAffineMapDef() {
2322 assert(getToken().is(Token::hash_identifier));
2323
2324 StringRef affineMapId = getTokenSpelling().drop_front();
2325
2326 // Check for redefinitions.
2327 auto *&entry = getState().affineMapDefinitions[affineMapId];
2328 if (entry)
2329 return emitError("redefinition of affine map id '" + affineMapId + "'");
2330
2331 consumeToken(Token::hash_identifier);
2332
2333 // Parse the '='
Chris Lattnerf7702a62018-07-23 17:30:01 -07002334 if (parseToken(Token::equal,
2335 "expected '=' in affine map outlined definition"))
2336 return ParseFailure;
Chris Lattner2e595eb2018-07-10 10:08:27 -07002337
2338 entry = parseAffineMapInline();
2339 if (!entry)
2340 return ParseFailure;
2341
Chris Lattner2e595eb2018-07-10 10:08:27 -07002342 return ParseSuccess;
2343}
2344
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002345/// Parse a (possibly empty) list of MLFunction arguments with types.
2346///
2347/// ml-argument ::= ssa-id `:` type
2348/// ml-argument-list ::= ml-argument (`,` ml-argument)* | /*empty*/
2349///
2350ParseResult
2351ModuleParser::parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2352 SmallVectorImpl<StringRef> &argNames) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002353 consumeToken(Token::l_paren);
2354
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002355 auto parseElt = [&]() -> ParseResult {
2356 // Parse argument name
2357 if (getToken().isNot(Token::percent_identifier))
2358 return emitError("expected SSA identifier");
2359
2360 StringRef name = getTokenSpelling().drop_front();
2361 consumeToken(Token::percent_identifier);
2362 argNames.push_back(name);
2363
Chris Lattnerf7702a62018-07-23 17:30:01 -07002364 if (parseToken(Token::colon, "expected ':'"))
2365 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002366
2367 // Parse argument type
2368 auto elt = parseType();
2369 if (!elt)
2370 return ParseFailure;
2371 argTypes.push_back(elt);
2372
2373 return ParseSuccess;
2374 };
2375
Chris Lattner40746442018-07-21 14:32:09 -07002376 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002377}
2378
Chris Lattner2e595eb2018-07-10 10:08:27 -07002379/// Parse a function signature, starting with a name and including the parameter
2380/// list.
2381///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002382/// argument-list ::= type (`,` type)* | /*empty*/ | ml-argument-list
Chris Lattner2e595eb2018-07-10 10:08:27 -07002383/// function-signature ::= function-id `(` argument-list `)` (`->` type-list)?
2384///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002385ParseResult
2386ModuleParser::parseFunctionSignature(StringRef &name, FunctionType *&type,
2387 SmallVectorImpl<StringRef> *argNames) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002388 if (getToken().isNot(Token::at_identifier))
2389 return emitError("expected a function identifier like '@foo'");
2390
2391 name = getTokenSpelling().drop_front();
2392 consumeToken(Token::at_identifier);
2393
2394 if (getToken().isNot(Token::l_paren))
2395 return emitError("expected '(' in function signature");
2396
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002397 SmallVector<Type *, 4> argTypes;
2398 ParseResult parseResult;
2399
2400 if (argNames)
2401 parseResult = parseMLArgumentList(argTypes, *argNames);
2402 else
2403 parseResult = parseTypeList(argTypes);
2404
2405 if (parseResult)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002406 return ParseFailure;
2407
2408 // Parse the return type if present.
2409 SmallVector<Type *, 4> results;
2410 if (consumeIf(Token::arrow)) {
2411 if (parseTypeList(results))
2412 return ParseFailure;
2413 }
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002414 type = builder.getFunctionType(argTypes, results);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002415 return ParseSuccess;
2416}
2417
2418/// External function declarations.
2419///
2420/// ext-func ::= `extfunc` function-signature
2421///
2422ParseResult ModuleParser::parseExtFunc() {
2423 consumeToken(Token::kw_extfunc);
2424
2425 StringRef name;
2426 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002427 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002428 return ParseFailure;
2429
2430 // Okay, the external function definition was parsed correctly.
Chris Lattnera8e47672018-07-25 14:08:16 -07002431 getModule()->getFunctions().push_back(new ExtFunction(name, type));
Chris Lattner2e595eb2018-07-10 10:08:27 -07002432 return ParseSuccess;
2433}
2434
2435/// CFG function declarations.
2436///
2437/// cfg-func ::= `cfgfunc` function-signature `{` basic-block+ `}`
2438///
2439ParseResult ModuleParser::parseCFGFunc() {
2440 consumeToken(Token::kw_cfgfunc);
2441
2442 StringRef name;
2443 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002444 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002445 return ParseFailure;
2446
2447 // Okay, the CFG function signature was parsed correctly, create the function.
2448 auto function = new CFGFunction(name, type);
2449
2450 return CFGFunctionParser(getState(), function).parseFunctionBody();
2451}
2452
2453/// ML function declarations.
2454///
2455/// ml-func ::= `mlfunc` ml-func-signature `{` ml-stmt* ml-return-stmt `}`
2456///
2457ParseResult ModuleParser::parseMLFunc() {
2458 consumeToken(Token::kw_mlfunc);
2459
2460 StringRef name;
2461 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002462 SmallVector<StringRef, 4> argNames;
Chris Lattner2e595eb2018-07-10 10:08:27 -07002463 // FIXME: Parse ML function signature (args + types)
2464 // by passing pointer to SmallVector<identifier> into parseFunctionSignature
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002465
2466 if (parseFunctionSignature(name, type, &argNames))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002467 return ParseFailure;
2468
2469 // Okay, the ML function signature was parsed correctly, create the function.
2470 auto function = new MLFunction(name, type);
2471
2472 return MLFunctionParser(getState(), function).parseFunctionBody();
2473}
2474
Chris Lattnere79379a2018-06-22 10:39:19 -07002475/// This is the top-level module parser.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002476ParseResult ModuleParser::parseModule() {
Chris Lattnere79379a2018-06-22 10:39:19 -07002477 while (1) {
Chris Lattner48af7d12018-07-09 19:05:38 -07002478 switch (getToken().getKind()) {
Chris Lattnere79379a2018-06-22 10:39:19 -07002479 default:
2480 emitError("expected a top level entity");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002481 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002482
Uday Bondhugula015cbb12018-07-03 20:16:08 -07002483 // If we got to the end of the file, then we're done.
Chris Lattnere79379a2018-06-22 10:39:19 -07002484 case Token::eof:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002485 return ParseSuccess;
Chris Lattnere79379a2018-06-22 10:39:19 -07002486
2487 // If we got an error token, then the lexer already emitted an error, just
2488 // stop. Someday we could introduce error recovery if there was demand for
2489 // it.
2490 case Token::error:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002491 return ParseFailure;
2492
2493 case Token::hash_identifier:
2494 if (parseAffineMapDef())
2495 return ParseFailure;
2496 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002497
2498 case Token::kw_extfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002499 if (parseExtFunc())
2500 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002501 break;
2502
Chris Lattner4c95a502018-06-23 16:03:42 -07002503 case Token::kw_cfgfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002504 if (parseCFGFunc())
2505 return ParseFailure;
MLIR Teamf85a6262018-06-27 11:03:08 -07002506 break;
Chris Lattner4c95a502018-06-23 16:03:42 -07002507
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002508 case Token::kw_mlfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002509 if (parseMLFunc())
2510 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002511 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002512 }
2513 }
2514}
2515
2516//===----------------------------------------------------------------------===//
2517
Jacques Pienaar7b829702018-07-03 13:24:09 -07002518void mlir::defaultErrorReporter(const llvm::SMDiagnostic &error) {
2519 const auto &sourceMgr = *error.getSourceMgr();
2520 sourceMgr.PrintMessage(error.getLoc(), error.getKind(), error.getMessage());
2521}
2522
Chris Lattnere79379a2018-06-22 10:39:19 -07002523/// This parses the file specified by the indicated SourceMgr and returns an
2524/// MLIR module if it was valid. If not, it emits diagnostics and returns null.
Jacques Pienaar9c411be2018-06-24 19:17:35 -07002525Module *mlir::parseSourceFile(llvm::SourceMgr &sourceMgr, MLIRContext *context,
Jacques Pienaar7b829702018-07-03 13:24:09 -07002526 SMDiagnosticHandlerTy errorReporter) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002527 // This is the result module we are parsing into.
2528 std::unique_ptr<Module> module(new Module(context));
2529
2530 ParserState state(sourceMgr, module.get(),
Jacques Pienaar0bffd862018-07-11 13:26:23 -07002531 errorReporter ? errorReporter : defaultErrorReporter);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002532 if (ModuleParser(state).parseModule())
2533 return nullptr;
Chris Lattner21e67f62018-07-06 10:46:19 -07002534
2535 // Make sure the parse module has no other structural problems detected by the
2536 // verifier.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002537 module->verify();
2538 return module.release();
Chris Lattnere79379a2018-06-22 10:39:19 -07002539}