blob: de82e45f1f2f9329cd440fc632d25c9270e2e882 [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 Lattnerea5c3dc2018-08-21 08:42:19 -070029#include "mlir/IR/MLIRContext.h"
Chris Lattner21e67f62018-07-06 10:46:19 -070030#include "mlir/IR/Module.h"
Chris Lattner85ee1512018-07-25 11:15:20 -070031#include "mlir/IR/OpImplementation.h"
Chris Lattner21e67f62018-07-06 10:46:19 -070032#include "mlir/IR/OperationSet.h"
Chris Lattnerea5c3dc2018-08-21 08:42:19 -070033#include "mlir/IR/StmtVisitor.h"
Chris Lattnerf7e22732018-06-22 22:03:48 -070034#include "mlir/IR/Types.h"
James Molloyf0d2f442018-08-03 01:54:46 -070035#include "llvm/ADT/DenseMap.h"
Chris Lattner1aa46322018-08-21 17:55:22 -070036#include "llvm/Support/PrettyStackTrace.h"
James Molloyf0d2f442018-08-03 01:54:46 -070037#include "llvm/Support/SourceMgr.h"
Chris Lattnere79379a2018-06-22 10:39:19 -070038using namespace mlir;
Chris Lattner4c95a502018-06-23 16:03:42 -070039using llvm::SMLoc;
James Molloy0ff71542018-07-23 16:56:32 -070040using llvm::SourceMgr;
Chris Lattnere79379a2018-06-22 10:39:19 -070041
Chris Lattnerf7e22732018-06-22 22:03:48 -070042/// Simple enum to make code read better in cases that would otherwise return a
43/// bool value. Failure is "true" in a boolean context.
James Molloy0ff71542018-07-23 16:56:32 -070044enum ParseResult { ParseSuccess, ParseFailure };
Chris Lattnere79379a2018-06-22 10:39:19 -070045
Chris Lattner48af7d12018-07-09 19:05:38 -070046namespace {
47class Parser;
48
49/// This class refers to all of the state maintained globally by the parser,
50/// such as the current lexer position etc. The Parser base class provides
51/// methods to access this.
52class ParserState {
Chris Lattnered65a732018-06-28 20:45:33 -070053public:
Chris Lattner2e595eb2018-07-10 10:08:27 -070054 ParserState(llvm::SourceMgr &sourceMgr, Module *module,
Chris Lattner48af7d12018-07-09 19:05:38 -070055 SMDiagnosticHandlerTy errorReporter)
Chris Lattner2e595eb2018-07-10 10:08:27 -070056 : context(module->getContext()), module(module),
57 lex(sourceMgr, errorReporter), curToken(lex.lexToken()),
Chris Lattner85ee1512018-07-25 11:15:20 -070058 errorReporter(errorReporter), operationSet(OperationSet::get(context)) {
59 }
Chris Lattner2e595eb2018-07-10 10:08:27 -070060
61 // A map from affine map identifier to AffineMap.
62 llvm::StringMap<AffineMap *> affineMapDefinitions;
Chris Lattner4613d9e2018-08-19 21:17:22 -070063
Uday Bondhugulabc535622018-08-07 14:24:38 -070064 // A map from integer set identifier to IntegerSet.
65 llvm::StringMap<IntegerSet *> integerSetDefinitions;
Chris Lattnere79379a2018-06-22 10:39:19 -070066
Chris Lattner4613d9e2018-08-19 21:17:22 -070067 // This keeps track of all forward references to functions along with the
68 // temporary function used to represent them and the location of the first
69 // reference.
70 llvm::DenseMap<Identifier, std::pair<Function *, SMLoc>> functionForwardRefs;
71
Chris Lattnere79379a2018-06-22 10:39:19 -070072private:
Chris Lattner48af7d12018-07-09 19:05:38 -070073 ParserState(const ParserState &) = delete;
74 void operator=(const ParserState &) = delete;
75
76 friend class Parser;
77
78 // The context we're parsing into.
Chris Lattner2e595eb2018-07-10 10:08:27 -070079 MLIRContext *const context;
80
81 // This is the module we are parsing into.
82 Module *const module;
Chris Lattnerf7e22732018-06-22 22:03:48 -070083
84 // The lexer for the source file we're parsing.
Chris Lattnere79379a2018-06-22 10:39:19 -070085 Lexer lex;
86
87 // This is the next token that hasn't been consumed yet.
88 Token curToken;
89
Jacques Pienaar9c411be2018-06-24 19:17:35 -070090 // The diagnostic error reporter.
Chris Lattner2e595eb2018-07-10 10:08:27 -070091 SMDiagnosticHandlerTy const errorReporter;
Chris Lattner85ee1512018-07-25 11:15:20 -070092
93 // The active OperationSet we're parsing with.
94 OperationSet &operationSet;
Chris Lattner48af7d12018-07-09 19:05:38 -070095};
96} // end anonymous namespace
MLIR Teamf85a6262018-06-27 11:03:08 -070097
Chris Lattner48af7d12018-07-09 19:05:38 -070098namespace {
99
Chris Lattner992a1272018-08-07 12:02:37 -0700100typedef std::function<Operation *(const OperationState &)>
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700101 CreateOperationFunction;
102
Chris Lattner48af7d12018-07-09 19:05:38 -0700103/// This class implement support for parsing global entities like types and
104/// shared entities like SSA names. It is intended to be subclassed by
105/// specialized subparsers that include state, e.g. when a local symbol table.
106class Parser {
107public:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700108 Builder builder;
Chris Lattner48af7d12018-07-09 19:05:38 -0700109
Chris Lattner2e595eb2018-07-10 10:08:27 -0700110 Parser(ParserState &state) : builder(state.context), state(state) {}
111
112 // Helper methods to get stuff from the parser-global state.
113 ParserState &getState() const { return state; }
Chris Lattner48af7d12018-07-09 19:05:38 -0700114 MLIRContext *getContext() const { return state.context; }
Chris Lattner2e595eb2018-07-10 10:08:27 -0700115 Module *getModule() { return state.module; }
Chris Lattner85ee1512018-07-25 11:15:20 -0700116 OperationSet &getOperationSet() const { return state.operationSet; }
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700117 llvm::SourceMgr &getSourceMgr() { return state.lex.getSourceMgr(); }
Chris Lattner48af7d12018-07-09 19:05:38 -0700118
119 /// Return the current token the parser is inspecting.
120 const Token &getToken() const { return state.curToken; }
121 StringRef getTokenSpelling() const { return state.curToken.getSpelling(); }
Chris Lattnere79379a2018-06-22 10:39:19 -0700122
123 /// Emit an error and return failure.
Chris Lattner4c95a502018-06-23 16:03:42 -0700124 ParseResult emitError(const Twine &message) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700125 return emitError(state.curToken.getLoc(), message);
Chris Lattner4c95a502018-06-23 16:03:42 -0700126 }
127 ParseResult emitError(SMLoc loc, const Twine &message);
Chris Lattnere79379a2018-06-22 10:39:19 -0700128
129 /// Advance the current lexer onto the next token.
130 void consumeToken() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700131 assert(state.curToken.isNot(Token::eof, Token::error) &&
Chris Lattnere79379a2018-06-22 10:39:19 -0700132 "shouldn't advance past EOF or errors");
Chris Lattner48af7d12018-07-09 19:05:38 -0700133 state.curToken = state.lex.lexToken();
Chris Lattnere79379a2018-06-22 10:39:19 -0700134 }
135
136 /// Advance the current lexer onto the next token, asserting what the expected
137 /// current token is. This is preferred to the above method because it leads
138 /// to more self-documenting code with better checking.
Chris Lattner8da0c282018-06-29 11:15:56 -0700139 void consumeToken(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700140 assert(state.curToken.is(kind) && "consumed an unexpected token");
Chris Lattnere79379a2018-06-22 10:39:19 -0700141 consumeToken();
142 }
143
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700144 /// If the current token has the specified kind, consume it and return true.
145 /// If not, return false.
Chris Lattner8da0c282018-06-29 11:15:56 -0700146 bool consumeIf(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700147 if (state.curToken.isNot(kind))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700148 return false;
149 consumeToken(kind);
150 return true;
151 }
152
Chris Lattnerf7702a62018-07-23 17:30:01 -0700153 /// Consume the specified token if present and return success. On failure,
154 /// output a diagnostic and return failure.
155 ParseResult parseToken(Token::Kind expectedToken, const Twine &message);
156
Chris Lattner40746442018-07-21 14:32:09 -0700157 /// Parse a comma-separated list of elements up until the specified end token.
158 ParseResult
159 parseCommaSeparatedListUntil(Token::Kind rightToken,
160 const std::function<ParseResult()> &parseElement,
161 bool allowEmptyList = true);
162
163 /// Parse a comma separated list of elements that must have at least one entry
164 /// in it.
165 ParseResult
166 parseCommaSeparatedList(const std::function<ParseResult()> &parseElement);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700167
Chris Lattnerf7e22732018-06-22 22:03:48 -0700168 // We have two forms of parsing methods - those that return a non-null
169 // pointer on success, and those that return a ParseResult to indicate whether
170 // they returned a failure. The second class fills in by-reference arguments
171 // as the results of their action.
172
Chris Lattnere79379a2018-06-22 10:39:19 -0700173 // Type parsing.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700174 VectorType *parseVectorType();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700175 ParseResult parseDimensionListRanked(SmallVectorImpl<int> &dimensions);
Chris Lattnerf7e22732018-06-22 22:03:48 -0700176 Type *parseTensorType();
177 Type *parseMemRefType();
178 Type *parseFunctionType();
179 Type *parseType();
Chris Lattner1604e472018-07-23 08:42:19 -0700180 ParseResult parseTypeListNoParens(SmallVectorImpl<Type *> &elements);
James Molloy0ff71542018-07-23 16:56:32 -0700181 ParseResult parseTypeList(SmallVectorImpl<Type *> &elements);
Chris Lattnere79379a2018-06-22 10:39:19 -0700182
Chris Lattner7121b802018-07-04 20:45:39 -0700183 // Attribute parsing.
Chris Lattner1aa46322018-08-21 17:55:22 -0700184 Function *resolveFunctionReference(StringRef nameStr, SMLoc nameLoc,
185 FunctionType *type);
Chris Lattner7121b802018-07-04 20:45:39 -0700186 Attribute *parseAttribute();
187 ParseResult parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes);
188
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700189 // Polyhedral structures.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700190 AffineMap *parseAffineMapInline();
MLIR Team718c82f2018-07-16 09:45:22 -0700191 AffineMap *parseAffineMapReference();
Uday Bondhugulabc535622018-08-07 14:24:38 -0700192 IntegerSet *parseIntegerSetInline();
193 IntegerSet *parseIntegerSetReference();
MLIR Teamf85a6262018-06-27 11:03:08 -0700194
Chris Lattner48af7d12018-07-09 19:05:38 -0700195private:
196 // The Parser is subclassed and reinstantiated. Do not add additional
197 // non-trivial state here, add it to the ParserState class.
198 ParserState &state;
Chris Lattnere79379a2018-06-22 10:39:19 -0700199};
200} // end anonymous namespace
201
202//===----------------------------------------------------------------------===//
203// Helper methods.
204//===----------------------------------------------------------------------===//
205
Chris Lattner4c95a502018-06-23 16:03:42 -0700206ParseResult Parser::emitError(SMLoc loc, const Twine &message) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700207 // If we hit a parse error in response to a lexer error, then the lexer
Jacques Pienaar9c411be2018-06-24 19:17:35 -0700208 // already reported the error.
Chris Lattner48af7d12018-07-09 19:05:38 -0700209 if (getToken().is(Token::error))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700210 return ParseFailure;
211
Chris Lattner48af7d12018-07-09 19:05:38 -0700212 auto &sourceMgr = state.lex.getSourceMgr();
213 state.errorReporter(sourceMgr.GetMessage(loc, SourceMgr::DK_Error, message));
Chris Lattnere79379a2018-06-22 10:39:19 -0700214 return ParseFailure;
215}
216
Chris Lattnerf7702a62018-07-23 17:30:01 -0700217/// Consume the specified token if present and return success. On failure,
218/// output a diagnostic and return failure.
219ParseResult Parser::parseToken(Token::Kind expectedToken,
220 const Twine &message) {
221 if (consumeIf(expectedToken))
222 return ParseSuccess;
223 return emitError(message);
224}
225
Chris Lattner40746442018-07-21 14:32:09 -0700226/// Parse a comma separated list of elements that must have at least one entry
227/// in it.
228ParseResult Parser::parseCommaSeparatedList(
229 const std::function<ParseResult()> &parseElement) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700230 // Non-empty case starts with an element.
231 if (parseElement())
232 return ParseFailure;
233
234 // Otherwise we have a list of comma separated elements.
235 while (consumeIf(Token::comma)) {
236 if (parseElement())
237 return ParseFailure;
238 }
Chris Lattner40746442018-07-21 14:32:09 -0700239 return ParseSuccess;
240}
241
242/// Parse a comma-separated list of elements, terminated with an arbitrary
243/// token. This allows empty lists if allowEmptyList is true.
244///
245/// abstract-list ::= rightToken // if allowEmptyList == true
246/// abstract-list ::= element (',' element)* rightToken
247///
248ParseResult Parser::parseCommaSeparatedListUntil(
249 Token::Kind rightToken, const std::function<ParseResult()> &parseElement,
250 bool allowEmptyList) {
251 // Handle the empty case.
252 if (getToken().is(rightToken)) {
253 if (!allowEmptyList)
254 return emitError("expected list element");
255 consumeToken(rightToken);
256 return ParseSuccess;
257 }
258
Chris Lattnerf7702a62018-07-23 17:30:01 -0700259 if (parseCommaSeparatedList(parseElement) ||
260 parseToken(rightToken, "expected ',' or '" +
261 Token::getTokenSpelling(rightToken) + "'"))
Chris Lattner40746442018-07-21 14:32:09 -0700262 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700263
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700264 return ParseSuccess;
265}
Chris Lattnere79379a2018-06-22 10:39:19 -0700266
267//===----------------------------------------------------------------------===//
268// Type Parsing
269//===----------------------------------------------------------------------===//
270
Chris Lattnerc3251192018-07-27 13:09:58 -0700271/// Parse an arbitrary type.
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700272///
Chris Lattnerc3251192018-07-27 13:09:58 -0700273/// type ::= integer-type
274/// | float-type
275/// | other-type
276/// | vector-type
277/// | tensor-type
278/// | memref-type
279/// | function-type
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700280///
Chris Lattnerc3251192018-07-27 13:09:58 -0700281/// float-type ::= `f16` | `bf16` | `f32` | `f64`
282/// other-type ::= `affineint` | `tf_control`
283///
284Type *Parser::parseType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700285 switch (getToken().getKind()) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700286 default:
287 return (emitError("expected type"), nullptr);
Chris Lattnerc3251192018-07-27 13:09:58 -0700288 case Token::kw_memref:
289 return parseMemRefType();
290 case Token::kw_tensor:
291 return parseTensorType();
292 case Token::kw_vector:
293 return parseVectorType();
294 case Token::l_paren:
295 return parseFunctionType();
296 // integer-type
297 case Token::inttype: {
298 auto width = getToken().getIntTypeBitwidth();
299 if (!width.hasValue())
300 return (emitError("invalid integer width"), nullptr);
301 consumeToken(Token::inttype);
302 return builder.getIntegerType(width.getValue());
303 }
304
305 // float-type
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700306 case Token::kw_bf16:
307 consumeToken(Token::kw_bf16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700308 return builder.getBF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700309 case Token::kw_f16:
310 consumeToken(Token::kw_f16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700311 return builder.getF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700312 case Token::kw_f32:
313 consumeToken(Token::kw_f32);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700314 return builder.getF32Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700315 case Token::kw_f64:
316 consumeToken(Token::kw_f64);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700317 return builder.getF64Type();
Chris Lattnerc3251192018-07-27 13:09:58 -0700318
319 // other-type
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700320 case Token::kw_affineint:
321 consumeToken(Token::kw_affineint);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700322 return builder.getAffineIntType();
Jacques Pienaarc0d69302018-07-27 11:07:12 -0700323 case Token::kw_tf_control:
324 consumeToken(Token::kw_tf_control);
325 return builder.getTFControlType();
James Molloy72b0cbe2018-08-01 12:55:27 -0700326 case Token::kw_tf_string:
327 consumeToken(Token::kw_tf_string);
328 return builder.getTFStringType();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700329 }
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700330}
331
332/// Parse a vector type.
333///
334/// vector-type ::= `vector` `<` const-dimension-list primitive-type `>`
335/// const-dimension-list ::= (integer-literal `x`)+
336///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700337VectorType *Parser::parseVectorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700338 consumeToken(Token::kw_vector);
339
Chris Lattnerf7702a62018-07-23 17:30:01 -0700340 if (parseToken(Token::less, "expected '<' in vector type"))
341 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700342
Chris Lattner48af7d12018-07-09 19:05:38 -0700343 if (getToken().isNot(Token::integer))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700344 return (emitError("expected dimension size in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700345
346 SmallVector<unsigned, 4> dimensions;
Chris Lattner48af7d12018-07-09 19:05:38 -0700347 while (getToken().is(Token::integer)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700348 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700349 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700350 if (!dimension.hasValue())
Chris Lattnerf7e22732018-06-22 22:03:48 -0700351 return (emitError("invalid dimension in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700352 dimensions.push_back(dimension.getValue());
353
354 consumeToken(Token::integer);
355
356 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700357 if (getToken().isNot(Token::bare_identifier) ||
358 getTokenSpelling()[0] != 'x')
Chris Lattnerf7e22732018-06-22 22:03:48 -0700359 return (emitError("expected 'x' in vector dimension list"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700360
361 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700362 if (getTokenSpelling().size() != 1)
363 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700364
365 // Consume the 'x'.
366 consumeToken(Token::bare_identifier);
367 }
368
369 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700370 auto typeLoc = getToken().getLoc();
371 auto *elementType = parseType();
372 if (!elementType || parseToken(Token::greater, "expected '>' in vector type"))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700373 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700374
Chris Lattnerc3251192018-07-27 13:09:58 -0700375 if (!isa<FloatType>(elementType) && !isa<IntegerType>(elementType))
376 return (emitError(typeLoc, "invalid vector element type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700377
Chris Lattnerf7e22732018-06-22 22:03:48 -0700378 return VectorType::get(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700379}
380
381/// Parse a dimension list of a tensor or memref type. This populates the
382/// dimension list, returning -1 for the '?' dimensions.
383///
384/// dimension-list-ranked ::= (dimension `x`)*
385/// dimension ::= `?` | integer-literal
386///
387ParseResult Parser::parseDimensionListRanked(SmallVectorImpl<int> &dimensions) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700388 while (getToken().isAny(Token::integer, Token::question)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700389 if (consumeIf(Token::question)) {
390 dimensions.push_back(-1);
391 } else {
392 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700393 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700394 if (!dimension.hasValue() || (int)dimension.getValue() < 0)
395 return emitError("invalid dimension");
396 dimensions.push_back((int)dimension.getValue());
397 consumeToken(Token::integer);
398 }
399
400 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700401 if (getToken().isNot(Token::bare_identifier) ||
402 getTokenSpelling()[0] != 'x')
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700403 return emitError("expected 'x' in dimension list");
404
405 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700406 if (getTokenSpelling().size() != 1)
407 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700408
409 // Consume the 'x'.
410 consumeToken(Token::bare_identifier);
411 }
412
413 return ParseSuccess;
414}
415
416/// Parse a tensor type.
417///
418/// tensor-type ::= `tensor` `<` dimension-list element-type `>`
419/// dimension-list ::= dimension-list-ranked | `??`
420///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700421Type *Parser::parseTensorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700422 consumeToken(Token::kw_tensor);
423
Chris Lattnerf7702a62018-07-23 17:30:01 -0700424 if (parseToken(Token::less, "expected '<' in tensor type"))
425 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700426
427 bool isUnranked;
428 SmallVector<int, 4> dimensions;
429
430 if (consumeIf(Token::questionquestion)) {
431 isUnranked = true;
432 } else {
433 isUnranked = false;
434 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700435 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700436 }
437
438 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700439 auto typeLoc = getToken().getLoc();
440 auto *elementType = parseType();
441 if (!elementType || parseToken(Token::greater, "expected '>' in tensor type"))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700442 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700443
Chris Lattnerc3251192018-07-27 13:09:58 -0700444 if (!isa<IntegerType>(elementType) && !isa<FloatType>(elementType) &&
445 !isa<VectorType>(elementType))
446 return (emitError(typeLoc, "invalid tensor element type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700447
MLIR Team355ec862018-06-23 18:09:09 -0700448 if (isUnranked)
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700449 return builder.getTensorType(elementType);
450 return builder.getTensorType(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700451}
452
453/// Parse a memref type.
454///
455/// memref-type ::= `memref` `<` dimension-list-ranked element-type
456/// (`,` semi-affine-map-composition)? (`,` memory-space)? `>`
457///
458/// semi-affine-map-composition ::= (semi-affine-map `,` )* semi-affine-map
459/// memory-space ::= integer-literal /* | TODO: address-space-id */
460///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700461Type *Parser::parseMemRefType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700462 consumeToken(Token::kw_memref);
463
Chris Lattnerf7702a62018-07-23 17:30:01 -0700464 if (parseToken(Token::less, "expected '<' in memref type"))
465 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700466
467 SmallVector<int, 4> dimensions;
468 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700469 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700470
471 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700472 auto typeLoc = getToken().getLoc();
473 auto *elementType = parseType();
Chris Lattnerf7e22732018-06-22 22:03:48 -0700474 if (!elementType)
475 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700476
Chris Lattnerc3251192018-07-27 13:09:58 -0700477 if (!isa<IntegerType>(elementType) && !isa<FloatType>(elementType) &&
478 !isa<VectorType>(elementType))
479 return (emitError(typeLoc, "invalid memref element type"), nullptr);
480
MLIR Team718c82f2018-07-16 09:45:22 -0700481 // Parse semi-affine-map-composition.
James Molloy0ff71542018-07-23 16:56:32 -0700482 SmallVector<AffineMap *, 2> affineMapComposition;
Chris Lattner413db6a2018-07-25 12:55:50 -0700483 unsigned memorySpace = 0;
MLIR Team718c82f2018-07-16 09:45:22 -0700484 bool parsedMemorySpace = false;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700485
MLIR Team718c82f2018-07-16 09:45:22 -0700486 auto parseElt = [&]() -> ParseResult {
487 if (getToken().is(Token::integer)) {
488 // Parse memory space.
489 if (parsedMemorySpace)
490 return emitError("multiple memory spaces specified in memref type");
491 auto v = getToken().getUnsignedIntegerValue();
492 if (!v.hasValue())
493 return emitError("invalid memory space in memref type");
494 memorySpace = v.getValue();
495 consumeToken(Token::integer);
496 parsedMemorySpace = true;
497 } else {
498 // Parse affine map.
499 if (parsedMemorySpace)
500 return emitError("affine map after memory space in memref type");
James Molloy0ff71542018-07-23 16:56:32 -0700501 auto *affineMap = parseAffineMapReference();
MLIR Team718c82f2018-07-16 09:45:22 -0700502 if (affineMap == nullptr)
503 return ParseFailure;
504 affineMapComposition.push_back(affineMap);
505 }
506 return ParseSuccess;
507 };
508
Chris Lattner413db6a2018-07-25 12:55:50 -0700509 // Parse a list of mappings and address space if present.
510 if (consumeIf(Token::comma)) {
511 // Parse comma separated list of affine maps, followed by memory space.
512 if (parseCommaSeparatedListUntil(Token::greater, parseElt,
513 /*allowEmptyList=*/false)) {
514 return nullptr;
515 }
516 } else {
517 if (parseToken(Token::greater, "expected ',' or '>' in memref type"))
518 return nullptr;
MLIR Team718c82f2018-07-16 09:45:22 -0700519 }
MLIR Team718c82f2018-07-16 09:45:22 -0700520
521 return MemRefType::get(dimensions, elementType, affineMapComposition,
522 memorySpace);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700523}
524
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700525/// Parse a function type.
526///
527/// function-type ::= type-list-parens `->` type-list
528///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700529Type *Parser::parseFunctionType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700530 assert(getToken().is(Token::l_paren));
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700531
Chris Lattnerf7702a62018-07-23 17:30:01 -0700532 SmallVector<Type *, 4> arguments, results;
533 if (parseTypeList(arguments) ||
534 parseToken(Token::arrow, "expected '->' in function type") ||
535 parseTypeList(results))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700536 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700537
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700538 return builder.getFunctionType(arguments, results);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700539}
540
Chris Lattner1604e472018-07-23 08:42:19 -0700541/// Parse a list of types without an enclosing parenthesis. The list must have
542/// at least one member.
543///
544/// type-list-no-parens ::= type (`,` type)*
545///
546ParseResult Parser::parseTypeListNoParens(SmallVectorImpl<Type *> &elements) {
547 auto parseElt = [&]() -> ParseResult {
548 auto elt = parseType();
549 elements.push_back(elt);
550 return elt ? ParseSuccess : ParseFailure;
551 };
552
553 return parseCommaSeparatedList(parseElt);
554}
555
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700556/// Parse a "type list", which is a singular type, or a parenthesized list of
557/// types.
558///
559/// type-list ::= type-list-parens | type
560/// type-list-parens ::= `(` `)`
Chris Lattner1604e472018-07-23 08:42:19 -0700561/// | `(` type-list-no-parens `)`
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700562///
James Molloy0ff71542018-07-23 16:56:32 -0700563ParseResult Parser::parseTypeList(SmallVectorImpl<Type *> &elements) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700564 auto parseElt = [&]() -> ParseResult {
565 auto elt = parseType();
566 elements.push_back(elt);
567 return elt ? ParseSuccess : ParseFailure;
568 };
569
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700570 // If there is no parens, then it must be a singular type.
571 if (!consumeIf(Token::l_paren))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700572 return parseElt();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700573
Chris Lattner40746442018-07-21 14:32:09 -0700574 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700575 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700576
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700577 return ParseSuccess;
578}
579
Chris Lattner4c95a502018-06-23 16:03:42 -0700580//===----------------------------------------------------------------------===//
Chris Lattner7121b802018-07-04 20:45:39 -0700581// Attribute parsing.
582//===----------------------------------------------------------------------===//
583
Chris Lattner1aa46322018-08-21 17:55:22 -0700584/// Given a parsed reference to a function name like @foo and a type that it
585/// corresponds to, resolve it to a concrete function object (possibly
586/// synthesizing a forward reference) or emit an error and return null on
587/// failure.
588Function *Parser::resolveFunctionReference(StringRef nameStr, SMLoc nameLoc,
589 FunctionType *type) {
590 Identifier name = builder.getIdentifier(nameStr.drop_front());
591
592 // See if the function has already been defined in the module.
593 Function *function = getModule()->getNamedFunction(name);
594
595 // If not, get or create a forward reference to one.
596 if (!function) {
597 auto &entry = state.functionForwardRefs[name];
598 if (!entry.first) {
599 entry.first = new ExtFunction(name, type);
600 entry.second = nameLoc;
601 }
602 function = entry.first;
603 }
604
605 if (function->getType() != type)
606 return (emitError(nameLoc, "reference to function with mismatched type"),
607 nullptr);
608 return function;
609}
610
Chris Lattner7121b802018-07-04 20:45:39 -0700611/// Attribute parsing.
612///
613/// attribute-value ::= bool-literal
614/// | integer-literal
615/// | float-literal
616/// | string-literal
James Molloyf0d2f442018-08-03 01:54:46 -0700617/// | type
Chris Lattner7121b802018-07-04 20:45:39 -0700618/// | `[` (attribute-value (`,` attribute-value)*)? `]`
Chris Lattner4613d9e2018-08-19 21:17:22 -0700619/// | function-id `:` function-type
Chris Lattner7121b802018-07-04 20:45:39 -0700620///
621Attribute *Parser::parseAttribute() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700622 switch (getToken().getKind()) {
Chris Lattner7121b802018-07-04 20:45:39 -0700623 case Token::kw_true:
624 consumeToken(Token::kw_true);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700625 return builder.getBoolAttr(true);
Chris Lattner7121b802018-07-04 20:45:39 -0700626 case Token::kw_false:
627 consumeToken(Token::kw_false);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700628 return builder.getBoolAttr(false);
Chris Lattner7121b802018-07-04 20:45:39 -0700629
Jacques Pienaar84491092018-07-31 17:15:15 -0700630 case Token::floatliteral: {
631 auto val = getToken().getFloatingPointValue();
632 if (!val.hasValue())
633 return (emitError("floating point value too large for attribute"),
634 nullptr);
635 consumeToken(Token::floatliteral);
636 return builder.getFloatAttr(val.getValue());
637 }
Chris Lattner7121b802018-07-04 20:45:39 -0700638 case Token::integer: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700639 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700640 if (!val.hasValue() || (int64_t)val.getValue() < 0)
641 return (emitError("integer too large for attribute"), nullptr);
642 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700643 return builder.getIntegerAttr((int64_t)val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700644 }
645
646 case Token::minus: {
647 consumeToken(Token::minus);
Chris Lattner48af7d12018-07-09 19:05:38 -0700648 if (getToken().is(Token::integer)) {
649 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700650 if (!val.hasValue() || (int64_t)-val.getValue() >= 0)
651 return (emitError("integer too large for attribute"), nullptr);
652 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700653 return builder.getIntegerAttr((int64_t)-val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700654 }
Jacques Pienaar84491092018-07-31 17:15:15 -0700655 if (getToken().is(Token::floatliteral)) {
656 auto val = getToken().getFloatingPointValue();
657 if (!val.hasValue())
658 return (emitError("floating point value too large for attribute"),
659 nullptr);
660 consumeToken(Token::floatliteral);
661 return builder.getFloatAttr(-val.getValue());
662 }
Chris Lattner7121b802018-07-04 20:45:39 -0700663
664 return (emitError("expected constant integer or floating point value"),
665 nullptr);
666 }
667
668 case Token::string: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700669 auto val = getToken().getStringValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700670 consumeToken(Token::string);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700671 return builder.getStringAttr(val);
Chris Lattner7121b802018-07-04 20:45:39 -0700672 }
673
Chris Lattner85ee1512018-07-25 11:15:20 -0700674 case Token::l_square: {
675 consumeToken(Token::l_square);
James Molloy0ff71542018-07-23 16:56:32 -0700676 SmallVector<Attribute *, 4> elements;
Chris Lattner7121b802018-07-04 20:45:39 -0700677
678 auto parseElt = [&]() -> ParseResult {
679 elements.push_back(parseAttribute());
680 return elements.back() ? ParseSuccess : ParseFailure;
681 };
682
Chris Lattner85ee1512018-07-25 11:15:20 -0700683 if (parseCommaSeparatedListUntil(Token::r_square, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700684 return nullptr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700685 return builder.getArrayAttr(elements);
Chris Lattner7121b802018-07-04 20:45:39 -0700686 }
James Molloyf0d2f442018-08-03 01:54:46 -0700687 case Token::hash_identifier:
688 case Token::l_paren: {
MLIR Teamb61885d2018-07-18 16:29:21 -0700689 // Try to parse affine map reference.
James Molloyf0d2f442018-08-03 01:54:46 -0700690 if (auto *affineMap = parseAffineMapReference())
MLIR Teamb61885d2018-07-18 16:29:21 -0700691 return builder.getAffineMapAttr(affineMap);
Chris Lattner7121b802018-07-04 20:45:39 -0700692 return (emitError("expected constant attribute value"), nullptr);
693 }
Chris Lattner4613d9e2018-08-19 21:17:22 -0700694
695 case Token::at_identifier: {
696 auto nameLoc = getToken().getLoc();
Chris Lattner1aa46322018-08-21 17:55:22 -0700697 auto nameStr = getTokenSpelling();
Chris Lattner4613d9e2018-08-19 21:17:22 -0700698 consumeToken(Token::at_identifier);
699
700 if (parseToken(Token::colon, "expected ':' and function type"))
701 return nullptr;
702 auto typeLoc = getToken().getLoc();
703 Type *type = parseType();
704 if (!type)
705 return nullptr;
Chris Lattner1aa46322018-08-21 17:55:22 -0700706 auto *fnType = dyn_cast<FunctionType>(type);
Chris Lattner4613d9e2018-08-19 21:17:22 -0700707 if (!fnType)
708 return (emitError(typeLoc, "expected function type"), nullptr);
709
Chris Lattner1aa46322018-08-21 17:55:22 -0700710 auto *function = resolveFunctionReference(nameStr, nameLoc, fnType);
711 return function ? builder.getFunctionAttr(function) : nullptr;
Chris Lattner4613d9e2018-08-19 21:17:22 -0700712 }
713
James Molloyf0d2f442018-08-03 01:54:46 -0700714 default: {
715 if (Type *type = parseType())
716 return builder.getTypeAttr(type);
717 return nullptr;
718 }
719 }
Chris Lattner7121b802018-07-04 20:45:39 -0700720}
721
Chris Lattner7121b802018-07-04 20:45:39 -0700722/// Attribute dictionary.
723///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700724/// attribute-dict ::= `{` `}`
725/// | `{` attribute-entry (`,` attribute-entry)* `}`
726/// attribute-entry ::= bare-id `:` attribute-value
Chris Lattner7121b802018-07-04 20:45:39 -0700727///
James Molloy0ff71542018-07-23 16:56:32 -0700728ParseResult
729Parser::parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes) {
Chris Lattner7121b802018-07-04 20:45:39 -0700730 consumeToken(Token::l_brace);
731
732 auto parseElt = [&]() -> ParseResult {
733 // We allow keywords as attribute names.
Chris Lattner48af7d12018-07-09 19:05:38 -0700734 if (getToken().isNot(Token::bare_identifier, Token::inttype) &&
735 !getToken().isKeyword())
Chris Lattner7121b802018-07-04 20:45:39 -0700736 return emitError("expected attribute name");
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700737 auto nameId = builder.getIdentifier(getTokenSpelling());
Chris Lattner7121b802018-07-04 20:45:39 -0700738 consumeToken();
739
Chris Lattnerf7702a62018-07-23 17:30:01 -0700740 if (parseToken(Token::colon, "expected ':' in attribute list"))
741 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700742
743 auto attr = parseAttribute();
James Molloy0ff71542018-07-23 16:56:32 -0700744 if (!attr)
745 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700746
747 attributes.push_back({nameId, attr});
748 return ParseSuccess;
749 };
750
Chris Lattner40746442018-07-21 14:32:09 -0700751 if (parseCommaSeparatedListUntil(Token::r_brace, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700752 return ParseFailure;
753
754 return ParseSuccess;
755}
756
757//===----------------------------------------------------------------------===//
MLIR Teamf85a6262018-06-27 11:03:08 -0700758// Polyhedral structures.
759//===----------------------------------------------------------------------===//
760
Chris Lattner2e595eb2018-07-10 10:08:27 -0700761/// Lower precedence ops (all at the same precedence level). LNoOp is false in
762/// the boolean sense.
763enum AffineLowPrecOp {
764 /// Null value.
765 LNoOp,
766 Add,
767 Sub
768};
MLIR Teamf85a6262018-06-27 11:03:08 -0700769
Chris Lattner2e595eb2018-07-10 10:08:27 -0700770/// Higher precedence ops - all at the same precedence level. HNoOp is false in
771/// the boolean sense.
772enum AffineHighPrecOp {
773 /// Null value.
774 HNoOp,
775 Mul,
776 FloorDiv,
777 CeilDiv,
778 Mod
779};
Chris Lattner7121b802018-07-04 20:45:39 -0700780
Chris Lattner2e595eb2018-07-10 10:08:27 -0700781namespace {
Uday Bondhugulabc535622018-08-07 14:24:38 -0700782/// This is a specialized parser for affine structures (affine maps, affine
783/// expressions, and integer sets), maintaining the state transient to their
784/// bodies.
785class AffineParser : public Parser {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700786public:
Uday Bondhugulabc535622018-08-07 14:24:38 -0700787 explicit AffineParser(ParserState &state) : Parser(state) {}
Chris Lattner7121b802018-07-04 20:45:39 -0700788
Chris Lattner2e595eb2018-07-10 10:08:27 -0700789 AffineMap *parseAffineMapInline();
Uday Bondhugulabc535622018-08-07 14:24:38 -0700790 IntegerSet *parseIntegerSetInline();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700791
Chris Lattner2e595eb2018-07-10 10:08:27 -0700792private:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700793 // Binary affine op parsing.
794 AffineLowPrecOp consumeIfLowPrecOp();
795 AffineHighPrecOp consumeIfHighPrecOp();
MLIR Teamf85a6262018-06-27 11:03:08 -0700796
Chris Lattner2e595eb2018-07-10 10:08:27 -0700797 // Identifier lists for polyhedral structures.
Chris Lattner413db6a2018-07-25 12:55:50 -0700798 ParseResult parseDimIdList(unsigned &numDims);
799 ParseResult parseSymbolIdList(unsigned &numSymbols);
800 ParseResult parseIdentifierDefinition(AffineExpr *idExpr);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700801
802 AffineExpr *parseAffineExpr();
803 AffineExpr *parseParentheticalExpr();
804 AffineExpr *parseNegateExpression(AffineExpr *lhs);
805 AffineExpr *parseIntegerExpr();
806 AffineExpr *parseBareIdExpr();
807
808 AffineExpr *getBinaryAffineOpExpr(AffineHighPrecOp op, AffineExpr *lhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700809 AffineExpr *rhs, SMLoc opLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700810 AffineExpr *getBinaryAffineOpExpr(AffineLowPrecOp op, AffineExpr *lhs,
811 AffineExpr *rhs);
812 AffineExpr *parseAffineOperandExpr(AffineExpr *lhs);
813 AffineExpr *parseAffineLowPrecOpExpr(AffineExpr *llhs,
814 AffineLowPrecOp llhsOp);
815 AffineExpr *parseAffineHighPrecOpExpr(AffineExpr *llhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700816 AffineHighPrecOp llhsOp,
817 SMLoc llhsOpLoc);
Uday Bondhugulabc535622018-08-07 14:24:38 -0700818 AffineExpr *parseAffineConstraint(bool *isEq);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700819
820private:
Chris Lattner413db6a2018-07-25 12:55:50 -0700821 SmallVector<std::pair<StringRef, AffineExpr *>, 4> dimsAndSymbols;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700822};
823} // end anonymous namespace
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700824
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700825/// Create an affine binary high precedence op expression (mul's, div's, mod).
826/// opLoc is the location of the op token to be used to report errors
827/// for non-conforming expressions.
Uday Bondhugulabc535622018-08-07 14:24:38 -0700828AffineExpr *AffineParser::getBinaryAffineOpExpr(AffineHighPrecOp op,
829 AffineExpr *lhs,
830 AffineExpr *rhs, SMLoc opLoc) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700831 // TODO: make the error location info accurate.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700832 switch (op) {
833 case Mul:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700834 if (!lhs->isSymbolicOrConstant() && !rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700835 emitError(opLoc, "non-affine expression: at least one of the multiply "
836 "operands has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700837 return nullptr;
838 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700839 return builder.getMulExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700840 case FloorDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700841 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700842 emitError(opLoc, "non-affine expression: right operand of floordiv "
843 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700844 return nullptr;
845 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700846 return builder.getFloorDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700847 case CeilDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700848 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700849 emitError(opLoc, "non-affine expression: right operand of ceildiv "
850 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700851 return nullptr;
852 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700853 return builder.getCeilDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700854 case Mod:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700855 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700856 emitError(opLoc, "non-affine expression: right operand of mod "
857 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700858 return nullptr;
859 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700860 return builder.getModExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700861 case HNoOp:
862 llvm_unreachable("can't create affine expression for null high prec op");
863 return nullptr;
864 }
865}
866
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700867/// Create an affine binary low precedence op expression (add, sub).
Uday Bondhugulabc535622018-08-07 14:24:38 -0700868AffineExpr *AffineParser::getBinaryAffineOpExpr(AffineLowPrecOp op,
869 AffineExpr *lhs,
870 AffineExpr *rhs) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700871 switch (op) {
872 case AffineLowPrecOp::Add:
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700873 return builder.getAddExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700874 case AffineLowPrecOp::Sub:
Uday Bondhugulac1faf662018-07-19 14:08:50 -0700875 return builder.getAddExpr(
876 lhs, builder.getMulExpr(rhs, builder.getConstantExpr(-1)));
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700877 case AffineLowPrecOp::LNoOp:
878 llvm_unreachable("can't create affine expression for null low prec op");
879 return nullptr;
880 }
881}
882
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700883/// Consume this token if it is a lower precedence affine op (there are only two
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700884/// precedence levels).
Uday Bondhugulabc535622018-08-07 14:24:38 -0700885AffineLowPrecOp AffineParser::consumeIfLowPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700886 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700887 case Token::plus:
888 consumeToken(Token::plus);
889 return AffineLowPrecOp::Add;
890 case Token::minus:
891 consumeToken(Token::minus);
892 return AffineLowPrecOp::Sub;
893 default:
894 return AffineLowPrecOp::LNoOp;
895 }
896}
897
898/// Consume this token if it is a higher precedence affine op (there are only
899/// two precedence levels)
Uday Bondhugulabc535622018-08-07 14:24:38 -0700900AffineHighPrecOp AffineParser::consumeIfHighPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700901 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700902 case Token::star:
903 consumeToken(Token::star);
904 return Mul;
905 case Token::kw_floordiv:
906 consumeToken(Token::kw_floordiv);
907 return FloorDiv;
908 case Token::kw_ceildiv:
909 consumeToken(Token::kw_ceildiv);
910 return CeilDiv;
911 case Token::kw_mod:
912 consumeToken(Token::kw_mod);
913 return Mod;
914 default:
915 return HNoOp;
916 }
917}
918
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700919/// Parse a high precedence op expression list: mul, div, and mod are high
920/// precedence binary ops, i.e., parse a
921/// expr_1 op_1 expr_2 op_2 ... expr_n
922/// where op_1, op_2 are all a AffineHighPrecOp (mul, div, mod).
923/// All affine binary ops are left associative.
924/// Given llhs, returns (llhs llhsOp lhs) op rhs, or (lhs op rhs) if llhs is
925/// null. If no rhs can be found, returns (llhs llhsOp lhs) or lhs if llhs is
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700926/// null. llhsOpLoc is the location of the llhsOp token that will be used to
927/// report an error for non-conforming expressions.
Uday Bondhugulabc535622018-08-07 14:24:38 -0700928AffineExpr *AffineParser::parseAffineHighPrecOpExpr(AffineExpr *llhs,
929 AffineHighPrecOp llhsOp,
930 SMLoc llhsOpLoc) {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700931 AffineExpr *lhs = parseAffineOperandExpr(llhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700932 if (!lhs)
933 return nullptr;
934
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700935 // Found an LHS. Parse the remaining expression.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700936 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -0700937 if (AffineHighPrecOp op = consumeIfHighPrecOp()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700938 if (llhs) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700939 AffineExpr *expr = getBinaryAffineOpExpr(llhsOp, llhs, lhs, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700940 if (!expr)
941 return nullptr;
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700942 return parseAffineHighPrecOpExpr(expr, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700943 }
944 // No LLHS, get RHS
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700945 return parseAffineHighPrecOpExpr(lhs, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700946 }
947
948 // This is the last operand in this expression.
949 if (llhs)
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700950 return getBinaryAffineOpExpr(llhsOp, llhs, lhs, llhsOpLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700951
952 // No llhs, 'lhs' itself is the expression.
953 return lhs;
954}
955
956/// Parse an affine expression inside parentheses.
957///
958/// affine-expr ::= `(` affine-expr `)`
Uday Bondhugulabc535622018-08-07 14:24:38 -0700959AffineExpr *AffineParser::parseParentheticalExpr() {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700960 if (parseToken(Token::l_paren, "expected '('"))
961 return nullptr;
Chris Lattner48af7d12018-07-09 19:05:38 -0700962 if (getToken().is(Token::r_paren))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700963 return (emitError("no expression inside parentheses"), nullptr);
Chris Lattnerf7702a62018-07-23 17:30:01 -0700964
Chris Lattner2e595eb2018-07-10 10:08:27 -0700965 auto *expr = parseAffineExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700966 if (!expr)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700967 return nullptr;
Chris Lattnerf7702a62018-07-23 17:30:01 -0700968 if (parseToken(Token::r_paren, "expected ')'"))
969 return nullptr;
970
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700971 return expr;
972}
973
974/// Parse the negation expression.
975///
976/// affine-expr ::= `-` affine-expr
Uday Bondhugulabc535622018-08-07 14:24:38 -0700977AffineExpr *AffineParser::parseNegateExpression(AffineExpr *lhs) {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700978 if (parseToken(Token::minus, "expected '-'"))
979 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700980
Chris Lattner2e595eb2018-07-10 10:08:27 -0700981 AffineExpr *operand = parseAffineOperandExpr(lhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700982 // Since negation has the highest precedence of all ops (including high
983 // precedence ops) but lower than parentheses, we are only going to use
984 // parseAffineOperandExpr instead of parseAffineExpr here.
985 if (!operand)
986 // Extra error message although parseAffineOperandExpr would have
987 // complained. Leads to a better diagnostic.
988 return (emitError("missing operand of negation"), nullptr);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700989 auto *minusOne = builder.getConstantExpr(-1);
990 return builder.getMulExpr(minusOne, operand);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700991}
992
993/// Parse a bare id that may appear in an affine expression.
994///
995/// affine-expr ::= bare-id
Uday Bondhugulabc535622018-08-07 14:24:38 -0700996AffineExpr *AffineParser::parseBareIdExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700997 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700998 return (emitError("expected bare identifier"), nullptr);
999
Chris Lattner48af7d12018-07-09 19:05:38 -07001000 StringRef sRef = getTokenSpelling();
Chris Lattner413db6a2018-07-25 12:55:50 -07001001 for (auto entry : dimsAndSymbols) {
Chris Lattnera8e47672018-07-25 14:08:16 -07001002 if (entry.first == sRef) {
1003 consumeToken(Token::bare_identifier);
1004 return entry.second;
1005 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001006 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001007
1008 return (emitError("use of undeclared identifier"), nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001009}
1010
1011/// Parse a positive integral constant appearing in an affine expression.
1012///
1013/// affine-expr ::= integer-literal
Uday Bondhugulabc535622018-08-07 14:24:38 -07001014AffineExpr *AffineParser::parseIntegerExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -07001015 auto val = getToken().getUInt64IntegerValue();
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07001016 if (!val.hasValue() || (int64_t)val.getValue() < 0)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001017 return (emitError("constant too large for affineint"), nullptr);
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07001018
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001019 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -07001020 return builder.getConstantExpr((int64_t)val.getValue());
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001021}
1022
1023/// Parses an expression that can be a valid operand of an affine expression.
Uday Bondhugula76345202018-07-09 13:47:52 -07001024/// lhs: if non-null, lhs is an affine expression that is the lhs of a binary
1025/// operator, the rhs of which is being parsed. This is used to determine
1026/// whether an error should be emitted for a missing right operand.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001027// Eg: for an expression without parentheses (like i + j + k + l), each
1028// of the four identifiers is an operand. For i + j*k + l, j*k is not an
1029// operand expression, it's an op expression and will be parsed via
1030// parseAffineHighPrecOpExpression(). However, for i + (j*k) + -l, (j*k) and -l
1031// are valid operands that will be parsed by this function.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001032AffineExpr *AffineParser::parseAffineOperandExpr(AffineExpr *lhs) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001033 switch (getToken().getKind()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001034 case Token::bare_identifier:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001035 return parseBareIdExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001036 case Token::integer:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001037 return parseIntegerExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001038 case Token::l_paren:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001039 return parseParentheticalExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001040 case Token::minus:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001041 return parseNegateExpression(lhs);
Uday Bondhugula76345202018-07-09 13:47:52 -07001042 case Token::kw_ceildiv:
1043 case Token::kw_floordiv:
1044 case Token::kw_mod:
1045 case Token::plus:
1046 case Token::star:
1047 if (lhs)
1048 emitError("missing right operand of binary operator");
1049 else
1050 emitError("missing left operand of binary operator");
1051 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001052 default:
1053 if (lhs)
Uday Bondhugula76345202018-07-09 13:47:52 -07001054 emitError("missing right operand of binary operator");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001055 else
1056 emitError("expected affine expression");
1057 return nullptr;
1058 }
1059}
1060
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001061/// Parse affine expressions that are bare-id's, integer constants,
1062/// parenthetical affine expressions, and affine op expressions that are a
1063/// composition of those.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001064///
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001065/// All binary op's associate from left to right.
1066///
1067/// {add, sub} have lower precedence than {mul, div, and mod}.
1068///
Uday Bondhugula76345202018-07-09 13:47:52 -07001069/// Add, sub'are themselves at the same precedence level. Mul, floordiv,
1070/// ceildiv, and mod are at the same higher precedence level. Negation has
1071/// higher precedence than any binary op.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001072///
1073/// llhs: the affine expression appearing on the left of the one being parsed.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001074/// This function will return ((llhs llhsOp lhs) op rhs) if llhs is non null,
1075/// and lhs op rhs otherwise; if there is no rhs, llhs llhsOp lhs is returned if
1076/// llhs is non-null; otherwise lhs is returned. This is to deal with left
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001077/// associativity.
1078///
1079/// Eg: when the expression is e1 + e2*e3 + e4, with e1 as llhs, this function
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001080/// will return the affine expr equivalent of (e1 + (e2*e3)) + e4, where (e2*e3)
1081/// will be parsed using parseAffineHighPrecOpExpr().
Uday Bondhugulabc535622018-08-07 14:24:38 -07001082AffineExpr *AffineParser::parseAffineLowPrecOpExpr(AffineExpr *llhs,
1083 AffineLowPrecOp llhsOp) {
Uday Bondhugula76345202018-07-09 13:47:52 -07001084 AffineExpr *lhs;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001085 if (!(lhs = parseAffineOperandExpr(llhs)))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001086 return nullptr;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001087
1088 // Found an LHS. Deal with the ops.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001089 if (AffineLowPrecOp lOp = consumeIfLowPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001090 if (llhs) {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001091 AffineExpr *sum = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001092 return parseAffineLowPrecOpExpr(sum, lOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001093 }
1094 // No LLHS, get RHS and form the expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001095 return parseAffineLowPrecOpExpr(lhs, lOp);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001096 }
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001097 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07001098 if (AffineHighPrecOp hOp = consumeIfHighPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001099 // We have a higher precedence op here. Get the rhs operand for the llhs
1100 // through parseAffineHighPrecOpExpr.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001101 AffineExpr *highRes = parseAffineHighPrecOpExpr(lhs, hOp, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001102 if (!highRes)
1103 return nullptr;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001104
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001105 // If llhs is null, the product forms the first operand of the yet to be
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001106 // found expression. If non-null, the op to associate with llhs is llhsOp.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001107 AffineExpr *expr =
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001108 llhs ? getBinaryAffineOpExpr(llhsOp, llhs, highRes) : highRes;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001109
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001110 // Recurse for subsequent low prec op's after the affine high prec op
1111 // expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001112 if (AffineLowPrecOp nextOp = consumeIfLowPrecOp())
1113 return parseAffineLowPrecOpExpr(expr, nextOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001114 return expr;
1115 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001116 // Last operand in the expression list.
1117 if (llhs)
1118 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
1119 // No llhs, 'lhs' itself is the expression.
1120 return lhs;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001121}
1122
1123/// Parse an affine expression.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001124/// affine-expr ::= `(` affine-expr `)`
1125/// | `-` affine-expr
1126/// | affine-expr `+` affine-expr
1127/// | affine-expr `-` affine-expr
1128/// | affine-expr `*` affine-expr
1129/// | affine-expr `floordiv` affine-expr
1130/// | affine-expr `ceildiv` affine-expr
1131/// | affine-expr `mod` affine-expr
1132/// | bare-id
1133/// | integer-literal
1134///
1135/// Additional conditions are checked depending on the production. For eg., one
1136/// of the operands for `*` has to be either constant/symbolic; the second
1137/// operand for floordiv, ceildiv, and mod has to be a positive integer.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001138AffineExpr *AffineParser::parseAffineExpr() {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001139 return parseAffineLowPrecOpExpr(nullptr, AffineLowPrecOp::LNoOp);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001140}
1141
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001142/// Parse a dim or symbol from the lists appearing before the actual expressions
Chris Lattner2e595eb2018-07-10 10:08:27 -07001143/// of the affine map. Update our state to store the dimensional/symbolic
Chris Lattner413db6a2018-07-25 12:55:50 -07001144/// identifier.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001145ParseResult AffineParser::parseIdentifierDefinition(AffineExpr *idExpr) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001146 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001147 return emitError("expected bare identifier");
Chris Lattner413db6a2018-07-25 12:55:50 -07001148
1149 auto name = getTokenSpelling();
1150 for (auto entry : dimsAndSymbols) {
1151 if (entry.first == name)
1152 return emitError("redefinition of identifier '" + Twine(name) + "'");
1153 }
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001154 consumeToken(Token::bare_identifier);
Chris Lattner413db6a2018-07-25 12:55:50 -07001155
1156 dimsAndSymbols.push_back({name, idExpr});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001157 return ParseSuccess;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001158}
1159
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001160/// Parse the list of symbolic identifiers to an affine map.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001161ParseResult AffineParser::parseSymbolIdList(unsigned &numSymbols) {
Chris Lattner413db6a2018-07-25 12:55:50 -07001162 consumeToken(Token::l_square);
1163 auto parseElt = [&]() -> ParseResult {
1164 auto *symbol = AffineSymbolExpr::get(numSymbols++, getContext());
1165 return parseIdentifierDefinition(symbol);
1166 };
Chris Lattner85ee1512018-07-25 11:15:20 -07001167 return parseCommaSeparatedListUntil(Token::r_square, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001168}
1169
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001170/// Parse the list of dimensional identifiers to an affine map.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001171ParseResult AffineParser::parseDimIdList(unsigned &numDims) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07001172 if (parseToken(Token::l_paren,
1173 "expected '(' at start of dimensional identifiers list"))
1174 return ParseFailure;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001175
Chris Lattner413db6a2018-07-25 12:55:50 -07001176 auto parseElt = [&]() -> ParseResult {
1177 auto *dimension = AffineDimExpr::get(numDims++, getContext());
1178 return parseIdentifierDefinition(dimension);
1179 };
Chris Lattner40746442018-07-21 14:32:09 -07001180 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001181}
1182
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001183/// Parse an affine map definition.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001184///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001185/// affine-map-inline ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
1186/// (`size` `(` dim-size (`,` dim-size)* `)`)?
1187/// dim-size ::= affine-expr | `min` `(` affine-expr ( `,` affine-expr)+ `)`
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001188///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001189/// multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Uday Bondhugulabc535622018-08-07 14:24:38 -07001190AffineMap *AffineParser::parseAffineMapInline() {
Chris Lattner413db6a2018-07-25 12:55:50 -07001191 unsigned numDims = 0, numSymbols = 0;
1192
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001193 // List of dimensional identifiers.
Chris Lattner413db6a2018-07-25 12:55:50 -07001194 if (parseDimIdList(numDims))
Chris Lattner7121b802018-07-04 20:45:39 -07001195 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001196
1197 // Symbols are optional.
Chris Lattner85ee1512018-07-25 11:15:20 -07001198 if (getToken().is(Token::l_square)) {
Chris Lattner413db6a2018-07-25 12:55:50 -07001199 if (parseSymbolIdList(numSymbols))
Chris Lattner7121b802018-07-04 20:45:39 -07001200 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001201 }
Chris Lattnerf7702a62018-07-23 17:30:01 -07001202
1203 if (parseToken(Token::arrow, "expected '->' or '['") ||
1204 parseToken(Token::l_paren, "expected '(' at start of affine map range"))
Chris Lattner7121b802018-07-04 20:45:39 -07001205 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001206
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001207 SmallVector<AffineExpr *, 4> exprs;
1208 auto parseElt = [&]() -> ParseResult {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001209 auto *elt = parseAffineExpr();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001210 ParseResult res = elt ? ParseSuccess : ParseFailure;
1211 exprs.push_back(elt);
1212 return res;
1213 };
1214
1215 // Parse a multi-dimensional affine expression (a comma-separated list of 1-d
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001216 // affine expressions); the list cannot be empty.
1217 // Grammar: multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner40746442018-07-21 14:32:09 -07001218 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt, false))
Chris Lattner7121b802018-07-04 20:45:39 -07001219 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001220
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001221 // Parse optional range sizes.
Uday Bondhugula1e500b42018-07-12 18:04:04 -07001222 // range-sizes ::= (`size` `(` dim-size (`,` dim-size)* `)`)?
1223 // dim-size ::= affine-expr | `min` `(` affine-expr (`,` affine-expr)+ `)`
1224 // TODO(bondhugula): support for min of several affine expressions.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001225 // TODO: check if sizes are non-negative whenever they are constant.
1226 SmallVector<AffineExpr *, 4> rangeSizes;
1227 if (consumeIf(Token::kw_size)) {
1228 // Location of the l_paren token (if it exists) for error reporting later.
1229 auto loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001230 if (parseToken(Token::l_paren, "expected '(' at start of affine map range"))
1231 return nullptr;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001232
1233 auto parseRangeSize = [&]() -> ParseResult {
Chris Lattner413db6a2018-07-25 12:55:50 -07001234 auto loc = getToken().getLoc();
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001235 auto *elt = parseAffineExpr();
Chris Lattner413db6a2018-07-25 12:55:50 -07001236 if (!elt)
1237 return ParseFailure;
1238
1239 if (!elt->isSymbolicOrConstant())
1240 return emitError(loc,
1241 "size expressions cannot refer to dimension values");
1242
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001243 rangeSizes.push_back(elt);
Chris Lattner413db6a2018-07-25 12:55:50 -07001244 return ParseSuccess;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001245 };
1246
Chris Lattner40746442018-07-21 14:32:09 -07001247 if (parseCommaSeparatedListUntil(Token::r_paren, parseRangeSize, false))
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001248 return nullptr;
1249 if (exprs.size() > rangeSizes.size())
1250 return (emitError(loc, "fewer range sizes than range expressions"),
1251 nullptr);
1252 if (exprs.size() < rangeSizes.size())
1253 return (emitError(loc, "more range sizes than range expressions"),
1254 nullptr);
1255 }
1256
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001257 // Parsed a valid affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001258 return builder.getAffineMap(numDims, numSymbols, exprs, rangeSizes);
MLIR Teamf85a6262018-06-27 11:03:08 -07001259}
1260
Chris Lattner2e595eb2018-07-10 10:08:27 -07001261AffineMap *Parser::parseAffineMapInline() {
Uday Bondhugulabc535622018-08-07 14:24:38 -07001262 return AffineParser(state).parseAffineMapInline();
Chris Lattner2e595eb2018-07-10 10:08:27 -07001263}
1264
MLIR Team718c82f2018-07-16 09:45:22 -07001265AffineMap *Parser::parseAffineMapReference() {
1266 if (getToken().is(Token::hash_identifier)) {
1267 // Parse affine map identifier and verify that it exists.
1268 StringRef affineMapId = getTokenSpelling().drop_front();
1269 if (getState().affineMapDefinitions.count(affineMapId) == 0)
1270 return (emitError("undefined affine map id '" + affineMapId + "'"),
1271 nullptr);
1272 consumeToken(Token::hash_identifier);
1273 return getState().affineMapDefinitions[affineMapId];
1274 }
1275 // Try to parse inline affine map.
1276 return parseAffineMapInline();
1277}
1278
MLIR Teamf85a6262018-06-27 11:03:08 -07001279//===----------------------------------------------------------------------===//
Chris Lattner7f9cc272018-07-19 08:35:28 -07001280// FunctionParser
Chris Lattner4c95a502018-06-23 16:03:42 -07001281//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001282
Chris Lattner7f9cc272018-07-19 08:35:28 -07001283namespace {
1284/// This class contains parser state that is common across CFG and ML functions,
1285/// notably for dealing with operations and SSA values.
1286class FunctionParser : public Parser {
1287public:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001288 enum class Kind { CFGFunc, MLFunc };
1289
1290 Kind getKind() const { return kind; }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001291
Chris Lattner6119d382018-07-20 18:41:34 -07001292 /// After the function is finished parsing, this function checks to see if
1293 /// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001294 ParseResult finalizeFunction(Function *func, SMLoc loc);
Chris Lattner6119d382018-07-20 18:41:34 -07001295
1296 /// This represents a use of an SSA value in the program. The first two
1297 /// entries in the tuple are the name and result number of a reference. The
1298 /// third is the location of the reference, which is used in case this ends up
1299 /// being a use of an undefined value.
1300 struct SSAUseInfo {
1301 StringRef name; // Value name, e.g. %42 or %abc
1302 unsigned number; // Number, specified with #12
1303 SMLoc loc; // Location of first definition or use.
1304 };
Chris Lattner7f9cc272018-07-19 08:35:28 -07001305
1306 /// Given a reference to an SSA value and its type, return a reference. This
1307 /// returns null on failure.
1308 SSAValue *resolveSSAUse(SSAUseInfo useInfo, Type *type);
1309
1310 /// Register a definition of a value with the symbol table.
1311 ParseResult addDefinition(SSAUseInfo useInfo, SSAValue *value);
1312
1313 // SSA parsing productions.
1314 ParseResult parseSSAUse(SSAUseInfo &result);
Chris Lattner40746442018-07-21 14:32:09 -07001315 ParseResult parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results);
James Molloy61a656c2018-07-22 15:45:24 -07001316
1317 template <typename ResultType>
1318 ResultType parseSSADefOrUseAndType(
1319 const std::function<ResultType(SSAUseInfo, Type *)> &action);
1320
1321 SSAValue *parseSSAUseAndType() {
1322 return parseSSADefOrUseAndType<SSAValue *>(
1323 [&](SSAUseInfo useInfo, Type *type) -> SSAValue * {
1324 return resolveSSAUse(useInfo, type);
1325 });
1326 }
Chris Lattner40746442018-07-21 14:32:09 -07001327
1328 template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001329 ParseResult
Chris Lattner2c402672018-07-23 11:56:17 -07001330 parseOptionalSSAUseAndTypeList(SmallVectorImpl<ValueTy *> &results,
1331 bool isParenthesized);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001332
1333 // Operations
1334 ParseResult parseOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner85ee1512018-07-25 11:15:20 -07001335 Operation *parseVerboseOperation(const CreateOperationFunction &createOpFunc);
1336 Operation *parseCustomOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001337
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001338protected:
1339 FunctionParser(ParserState &state, Kind kind) : Parser(state), kind(kind) {}
1340
Chris Lattner7f9cc272018-07-19 08:35:28 -07001341private:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001342 /// Kind indicates if this is CFG or ML function parser.
1343 Kind kind;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001344 /// This keeps track of all of the SSA values we are tracking, indexed by
Chris Lattner6119d382018-07-20 18:41:34 -07001345 /// their name. This has one entry per result number.
1346 llvm::StringMap<SmallVector<std::pair<SSAValue *, SMLoc>, 1>> values;
1347
1348 /// These are all of the placeholders we've made along with the location of
1349 /// their first reference, to allow checking for use of undefined values.
1350 DenseMap<SSAValue *, SMLoc> forwardReferencePlaceholders;
1351
1352 SSAValue *createForwardReferencePlaceholder(SMLoc loc, Type *type);
1353
1354 /// Return true if this is a forward reference.
1355 bool isForwardReferencePlaceholder(SSAValue *value) {
1356 return forwardReferencePlaceholders.count(value);
1357 }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001358};
1359} // end anonymous namespace
1360
Chris Lattner6119d382018-07-20 18:41:34 -07001361/// Create and remember a new placeholder for a forward reference.
1362SSAValue *FunctionParser::createForwardReferencePlaceholder(SMLoc loc,
1363 Type *type) {
1364 // Forward references are always created as instructions, even in ML
1365 // functions, because we just need something with a def/use chain.
1366 //
1367 // We create these placeholders as having an empty name, which we know cannot
1368 // be created through normal user input, allowing us to distinguish them.
1369 auto name = Identifier::get("placeholder", getContext());
1370 auto *inst = OperationInst::create(name, /*operands*/ {}, type, /*attrs*/ {},
1371 getContext());
1372 forwardReferencePlaceholders[inst->getResult(0)] = loc;
1373 return inst->getResult(0);
1374}
1375
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001376/// Given an unbound reference to an SSA value and its type, return the value
Chris Lattner7f9cc272018-07-19 08:35:28 -07001377/// it specifies. This returns null on failure.
1378SSAValue *FunctionParser::resolveSSAUse(SSAUseInfo useInfo, Type *type) {
Chris Lattner6119d382018-07-20 18:41:34 -07001379 auto &entries = values[useInfo.name];
1380
Chris Lattner7f9cc272018-07-19 08:35:28 -07001381 // If we have already seen a value of this name, return it.
Chris Lattner6119d382018-07-20 18:41:34 -07001382 if (useInfo.number < entries.size() && entries[useInfo.number].first) {
1383 auto *result = entries[useInfo.number].first;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001384 // Check that the type matches the other uses.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001385 if (result->getType() == type)
1386 return result;
1387
Chris Lattner6119d382018-07-20 18:41:34 -07001388 emitError(useInfo.loc, "use of value '" + useInfo.name.str() +
1389 "' expects different type than prior uses");
1390 emitError(entries[useInfo.number].second, "prior use here");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001391 return nullptr;
1392 }
1393
Chris Lattner6119d382018-07-20 18:41:34 -07001394 // Make sure we have enough slots for this.
1395 if (entries.size() <= useInfo.number)
1396 entries.resize(useInfo.number + 1);
1397
1398 // If the value has already been defined and this is an overly large result
1399 // number, diagnose that.
1400 if (entries[0].first && !isForwardReferencePlaceholder(entries[0].first))
1401 return (emitError(useInfo.loc, "reference to invalid result number"),
1402 nullptr);
1403
Tatiana Shpeismand880b352018-07-31 23:14:16 -07001404 // Otherwise, this is a forward reference. If we are in ML function return
1405 // an error. In CFG function, create a placeholder and remember
1406 // that we did so.
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001407 if (getKind() == Kind::MLFunc)
1408 return (
1409 emitError(useInfo.loc, "use of undefined SSA value " + useInfo.name),
1410 nullptr);
1411
Chris Lattner6119d382018-07-20 18:41:34 -07001412 auto *result = createForwardReferencePlaceholder(useInfo.loc, type);
1413 entries[useInfo.number].first = result;
1414 entries[useInfo.number].second = useInfo.loc;
1415 return result;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001416}
1417
1418/// Register a definition of a value with the symbol table.
1419ParseResult FunctionParser::addDefinition(SSAUseInfo useInfo, SSAValue *value) {
Chris Lattner6119d382018-07-20 18:41:34 -07001420 auto &entries = values[useInfo.name];
Chris Lattner7f9cc272018-07-19 08:35:28 -07001421
Chris Lattner6119d382018-07-20 18:41:34 -07001422 // Make sure there is a slot for this value.
1423 if (entries.size() <= useInfo.number)
1424 entries.resize(useInfo.number + 1);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001425
Chris Lattner6119d382018-07-20 18:41:34 -07001426 // If we already have an entry for this, check to see if it was a definition
1427 // or a forward reference.
1428 if (auto *existing = entries[useInfo.number].first) {
1429 if (!isForwardReferencePlaceholder(existing)) {
1430 emitError(useInfo.loc,
1431 "redefinition of SSA value '" + useInfo.name + "'");
1432 return emitError(entries[useInfo.number].second,
1433 "previously defined here");
1434 }
1435
1436 // If it was a forward reference, update everything that used it to use the
1437 // actual definition instead, delete the forward ref, and remove it from our
1438 // set of forward references we track.
1439 existing->replaceAllUsesWith(value);
1440 existing->getDefiningInst()->destroy();
1441 forwardReferencePlaceholders.erase(existing);
1442 }
1443
1444 entries[useInfo.number].first = value;
1445 entries[useInfo.number].second = useInfo.loc;
1446 return ParseSuccess;
1447}
1448
1449/// After the function is finished parsing, this function checks to see if
1450/// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001451ParseResult FunctionParser::finalizeFunction(Function *func, SMLoc loc) {
Chris Lattner6119d382018-07-20 18:41:34 -07001452 // Check for any forward references that are left. If we find any, error out.
1453 if (!forwardReferencePlaceholders.empty()) {
1454 SmallVector<std::pair<const char *, SSAValue *>, 4> errors;
1455 // Iteration over the map isn't determinstic, so sort by source location.
1456 for (auto entry : forwardReferencePlaceholders)
1457 errors.push_back({entry.second.getPointer(), entry.first});
1458 llvm::array_pod_sort(errors.begin(), errors.end());
1459
1460 for (auto entry : errors)
1461 emitError(SMLoc::getFromPointer(entry.first),
1462 "use of undeclared SSA value name");
1463 return ParseFailure;
1464 }
1465
1466 return ParseSuccess;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001467}
1468
Chris Lattner78276e32018-07-07 15:48:26 -07001469/// Parse a SSA operand for an instruction or statement.
1470///
James Molloy61a656c2018-07-22 15:45:24 -07001471/// ssa-use ::= ssa-id
Chris Lattner78276e32018-07-07 15:48:26 -07001472///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001473ParseResult FunctionParser::parseSSAUse(SSAUseInfo &result) {
Chris Lattner6119d382018-07-20 18:41:34 -07001474 result.name = getTokenSpelling();
1475 result.number = 0;
1476 result.loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001477 if (parseToken(Token::percent_identifier, "expected SSA operand"))
1478 return ParseFailure;
Chris Lattner6119d382018-07-20 18:41:34 -07001479
1480 // If we have an affine map ID, it is a result number.
1481 if (getToken().is(Token::hash_identifier)) {
1482 if (auto value = getToken().getHashIdentifierNumber())
1483 result.number = value.getValue();
1484 else
1485 return emitError("invalid SSA value result number");
1486 consumeToken(Token::hash_identifier);
1487 }
1488
Chris Lattner7f9cc272018-07-19 08:35:28 -07001489 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001490}
1491
1492/// Parse a (possibly empty) list of SSA operands.
1493///
1494/// ssa-use-list ::= ssa-use (`,` ssa-use)*
1495/// ssa-use-list-opt ::= ssa-use-list?
1496///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001497ParseResult
Chris Lattner40746442018-07-21 14:32:09 -07001498FunctionParser::parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results) {
Chris Lattner85ee1512018-07-25 11:15:20 -07001499 if (getToken().isNot(Token::percent_identifier))
Chris Lattner40746442018-07-21 14:32:09 -07001500 return ParseSuccess;
1501 return parseCommaSeparatedList([&]() -> ParseResult {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001502 SSAUseInfo result;
1503 if (parseSSAUse(result))
1504 return ParseFailure;
1505 results.push_back(result);
1506 return ParseSuccess;
1507 });
Chris Lattner78276e32018-07-07 15:48:26 -07001508}
1509
1510/// Parse an SSA use with an associated type.
1511///
1512/// ssa-use-and-type ::= ssa-use `:` type
James Molloy61a656c2018-07-22 15:45:24 -07001513template <typename ResultType>
1514ResultType FunctionParser::parseSSADefOrUseAndType(
1515 const std::function<ResultType(SSAUseInfo, Type *)> &action) {
Chris Lattner78276e32018-07-07 15:48:26 -07001516
Chris Lattnerf7702a62018-07-23 17:30:01 -07001517 SSAUseInfo useInfo;
1518 if (parseSSAUse(useInfo) ||
1519 parseToken(Token::colon, "expected ':' and type for SSA operand"))
1520 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001521
Chris Lattner7f9cc272018-07-19 08:35:28 -07001522 auto *type = parseType();
1523 if (!type)
1524 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001525
James Molloy61a656c2018-07-22 15:45:24 -07001526 return action(useInfo, type);
Chris Lattner78276e32018-07-07 15:48:26 -07001527}
1528
Chris Lattner2c402672018-07-23 11:56:17 -07001529/// Parse a (possibly empty) list of SSA operands, followed by a colon, then
1530/// followed by a type list. If hasParens is true, then the operands are
1531/// surrounded by parens.
Chris Lattner78276e32018-07-07 15:48:26 -07001532///
Chris Lattner2c402672018-07-23 11:56:17 -07001533/// ssa-use-and-type-list[parens]
1534/// ::= `(` ssa-use-list `)` ':' type-list-no-parens
1535///
1536/// ssa-use-and-type-list[!parens]
1537/// ::= ssa-use-list ':' type-list-no-parens
Chris Lattner78276e32018-07-07 15:48:26 -07001538///
Chris Lattner40746442018-07-21 14:32:09 -07001539template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001540ParseResult FunctionParser::parseOptionalSSAUseAndTypeList(
Chris Lattner2c402672018-07-23 11:56:17 -07001541 SmallVectorImpl<ValueTy *> &results, bool isParenthesized) {
1542
1543 // If we are in the parenthesized form and no paren exists, then we succeed
1544 // with an empty list.
1545 if (isParenthesized && !consumeIf(Token::l_paren))
Chris Lattner40746442018-07-21 14:32:09 -07001546 return ParseSuccess;
1547
Chris Lattner2c402672018-07-23 11:56:17 -07001548 SmallVector<SSAUseInfo, 4> valueIDs;
1549 if (parseOptionalSSAUseList(valueIDs))
Chris Lattner7f9cc272018-07-19 08:35:28 -07001550 return ParseFailure;
Chris Lattner2c402672018-07-23 11:56:17 -07001551
1552 if (isParenthesized && !consumeIf(Token::r_paren))
1553 return emitError("expected ')' in operand list");
1554
1555 // If there were no operands, then there is no colon or type lists.
1556 if (valueIDs.empty())
1557 return ParseSuccess;
1558
Chris Lattner2c402672018-07-23 11:56:17 -07001559 SmallVector<Type *, 4> types;
Chris Lattnerf7702a62018-07-23 17:30:01 -07001560 if (parseToken(Token::colon, "expected ':' in operand list") ||
1561 parseTypeListNoParens(types))
Chris Lattner2c402672018-07-23 11:56:17 -07001562 return ParseFailure;
1563
1564 if (valueIDs.size() != types.size())
1565 return emitError("expected " + Twine(valueIDs.size()) +
1566 " types to match operand list");
1567
1568 results.reserve(valueIDs.size());
1569 for (unsigned i = 0, e = valueIDs.size(); i != e; ++i) {
1570 if (auto *value = resolveSSAUse(valueIDs[i], types[i]))
1571 results.push_back(cast<ValueTy>(value));
1572 else
1573 return ParseFailure;
1574 }
1575
1576 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001577}
1578
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001579/// Parse the CFG or MLFunc operation.
1580///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001581/// operation ::=
1582/// (ssa-id `=`)? string '(' ssa-use-list? ')' attribute-dict?
1583/// `:` function-type
1584///
1585ParseResult
Chris Lattner7f9cc272018-07-19 08:35:28 -07001586FunctionParser::parseOperation(const CreateOperationFunction &createOpFunc) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001587 auto loc = getToken().getLoc();
1588
1589 StringRef resultID;
1590 if (getToken().is(Token::percent_identifier)) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001591 resultID = getTokenSpelling();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001592 consumeToken(Token::percent_identifier);
Chris Lattnerf7702a62018-07-23 17:30:01 -07001593 if (parseToken(Token::equal, "expected '=' after SSA name"))
1594 return ParseFailure;
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001595 }
1596
Chris Lattner85ee1512018-07-25 11:15:20 -07001597 Operation *op;
1598 if (getToken().is(Token::bare_identifier) || getToken().isKeyword())
1599 op = parseCustomOperation(createOpFunc);
1600 else if (getToken().is(Token::string))
1601 op = parseVerboseOperation(createOpFunc);
1602 else
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001603 return emitError("expected operation name in quotes");
1604
Chris Lattner85ee1512018-07-25 11:15:20 -07001605 // If parsing of the basic operation failed, then this whole thing fails.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001606 if (!op)
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001607 return ParseFailure;
1608
Chris Lattnerf7bdf952018-08-05 21:12:29 -07001609 // Apply location information to the instruction.
1610 // TODO(clattner): make this more principled. We shouldn't overwrite existing
1611 // location info, we should use a better serialized form, and we shouldn't
1612 // be using the :location attribute. This is also pretty inefficient.
1613 {
1614 auto &sourceMgr = getSourceMgr();
1615 auto fileID = sourceMgr.FindBufferContainingLoc(loc);
1616 auto *srcBuffer = sourceMgr.getMemoryBuffer(fileID);
1617 unsigned locationEncoding = loc.getPointer() - srcBuffer->getBufferStart();
1618 op->setAttr(builder.getIdentifier(":location"),
1619 builder.getIntegerAttr(locationEncoding));
1620 }
1621
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001622 // We just parsed an operation. If it is a recognized one, verify that it
1623 // is structurally as we expect. If not, produce an error with a reasonable
1624 // source location.
Chris Lattner95865062018-08-01 10:18:59 -07001625 if (auto *opInfo = op->getAbstractOperation()) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001626 if (auto error = opInfo->verifyInvariants(op))
Chris Lattner9361fb32018-07-24 08:34:58 -07001627 return emitError(loc, Twine("'") + op->getName().str() + "' op " + error);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001628 }
1629
Chris Lattner7f9cc272018-07-19 08:35:28 -07001630 // If the instruction had a name, register it.
1631 if (!resultID.empty()) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001632 if (op->getNumResults() == 0)
1633 return emitError(loc, "cannot name an operation with no results");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001634
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001635 for (unsigned i = 0, e = op->getNumResults(); i != e; ++i)
Chris Lattner2b97d502018-08-06 14:19:46 -07001636 if (addDefinition({resultID, i, loc}, op->getResult(i)))
1637 return ParseFailure;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001638 }
1639
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001640 return ParseSuccess;
1641}
Chris Lattnere79379a2018-06-22 10:39:19 -07001642
Chris Lattner85ee1512018-07-25 11:15:20 -07001643Operation *FunctionParser::parseVerboseOperation(
1644 const CreateOperationFunction &createOpFunc) {
1645 auto name = getToken().getStringValue();
1646 if (name.empty())
1647 return (emitError("empty operation name is invalid"), nullptr);
1648
1649 consumeToken(Token::string);
1650
Chris Lattner1eb77482018-08-22 19:25:49 -07001651 OperationState result(builder.getContext(), name);
Chris Lattner992a1272018-08-07 12:02:37 -07001652
Chris Lattner85ee1512018-07-25 11:15:20 -07001653 // Parse the operand list.
1654 SmallVector<SSAUseInfo, 8> operandInfos;
1655
1656 if (parseToken(Token::l_paren, "expected '(' to start operand list") ||
1657 parseOptionalSSAUseList(operandInfos) ||
1658 parseToken(Token::r_paren, "expected ')' to end operand list")) {
1659 return nullptr;
1660 }
1661
Chris Lattner85ee1512018-07-25 11:15:20 -07001662 if (getToken().is(Token::l_brace)) {
Chris Lattner992a1272018-08-07 12:02:37 -07001663 if (parseAttributeDict(result.attributes))
Chris Lattner85ee1512018-07-25 11:15:20 -07001664 return nullptr;
1665 }
1666
1667 if (parseToken(Token::colon, "expected ':' followed by instruction type"))
1668 return nullptr;
1669
1670 auto typeLoc = getToken().getLoc();
1671 auto type = parseType();
1672 if (!type)
1673 return nullptr;
1674 auto fnType = dyn_cast<FunctionType>(type);
1675 if (!fnType)
1676 return (emitError(typeLoc, "expected function type"), nullptr);
1677
Chris Lattner1eb77482018-08-22 19:25:49 -07001678 result.addTypes(fnType->getResults());
Chris Lattner992a1272018-08-07 12:02:37 -07001679
Chris Lattner85ee1512018-07-25 11:15:20 -07001680 // Check that we have the right number of types for the operands.
1681 auto operandTypes = fnType->getInputs();
1682 if (operandTypes.size() != operandInfos.size()) {
1683 auto plural = "s"[operandInfos.size() == 1];
1684 return (emitError(typeLoc, "expected " + llvm::utostr(operandInfos.size()) +
1685 " operand type" + plural + " but had " +
1686 llvm::utostr(operandTypes.size())),
1687 nullptr);
1688 }
1689
1690 // Resolve all of the operands.
Chris Lattner85ee1512018-07-25 11:15:20 -07001691 for (unsigned i = 0, e = operandInfos.size(); i != e; ++i) {
Chris Lattner992a1272018-08-07 12:02:37 -07001692 result.operands.push_back(resolveSSAUse(operandInfos[i], operandTypes[i]));
1693 if (!result.operands.back())
Chris Lattner85ee1512018-07-25 11:15:20 -07001694 return nullptr;
1695 }
1696
Chris Lattner992a1272018-08-07 12:02:37 -07001697 return createOpFunc(result);
Chris Lattner85ee1512018-07-25 11:15:20 -07001698}
1699
1700namespace {
1701class CustomOpAsmParser : public OpAsmParser {
1702public:
1703 CustomOpAsmParser(SMLoc nameLoc, StringRef opName, FunctionParser &parser)
1704 : nameLoc(nameLoc), opName(opName), parser(parser) {}
1705
1706 /// This is an internal helper to parser a colon, we don't want to expose
1707 /// this to clients.
1708 bool internalParseColon(llvm::SMLoc *loc) {
1709 if (loc)
1710 *loc = parser.getToken().getLoc();
1711 return parser.parseToken(Token::colon, "expected ':'");
1712 }
1713
1714 //===--------------------------------------------------------------------===//
1715 // High level parsing methods.
1716 //===--------------------------------------------------------------------===//
1717
Chris Lattner1aa46322018-08-21 17:55:22 -07001718 bool getCurrentLocation(llvm::SMLoc *loc) override {
1719 *loc = parser.getToken().getLoc();
1720 return false;
1721 }
Chris Lattner85ee1512018-07-25 11:15:20 -07001722 bool parseComma(llvm::SMLoc *loc = nullptr) override {
1723 if (loc)
1724 *loc = parser.getToken().getLoc();
1725 return parser.parseToken(Token::comma, "expected ','");
1726 }
1727
1728 bool parseColonType(Type *&result, llvm::SMLoc *loc = nullptr) override {
1729 return internalParseColon(loc) || !(result = parser.parseType());
1730 }
1731
1732 bool parseColonTypeList(SmallVectorImpl<Type *> &result,
1733 llvm::SMLoc *loc = nullptr) override {
1734 if (internalParseColon(loc))
1735 return true;
1736
1737 do {
1738 if (auto *type = parser.parseType())
1739 result.push_back(type);
1740 else
1741 return true;
1742
1743 } while (parser.consumeIf(Token::comma));
1744 return false;
1745 }
1746
Chris Lattner85cf26d2018-08-02 16:54:36 -07001747 /// Parse an arbitrary attribute and return it in result. This also adds the
1748 /// attribute to the specified attribute list with the specified name. this
1749 /// captures the location of the attribute in 'loc' if it is non-null.
1750 bool parseAttribute(Attribute *&result, const char *attrName,
1751 SmallVectorImpl<NamedAttribute> &attrs,
1752 llvm::SMLoc *loc = nullptr) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001753 if (loc)
1754 *loc = parser.getToken().getLoc();
1755 result = parser.parseAttribute();
Chris Lattner85cf26d2018-08-02 16:54:36 -07001756 if (!result)
1757 return true;
1758
1759 attrs.push_back(
1760 NamedAttribute(parser.builder.getIdentifier(attrName), result));
1761 return false;
1762 }
1763
1764 /// If a named attribute list is present, parse is into result.
1765 bool parseOptionalAttributeDict(SmallVectorImpl<NamedAttribute> &result,
1766 llvm::SMLoc *loc = nullptr) override {
1767 if (parser.getToken().isNot(Token::l_brace))
1768 return false;
1769 if (loc)
1770 *loc = parser.getToken().getLoc();
1771 return parser.parseAttributeDict(result) == ParseFailure;
Chris Lattner85ee1512018-07-25 11:15:20 -07001772 }
1773
Chris Lattner1aa46322018-08-21 17:55:22 -07001774 /// Parse a function name like '@foo' and return the name in a form that can
1775 /// be passed to resolveFunctionName when a function type is available.
1776 virtual bool parseFunctionName(StringRef &result, llvm::SMLoc &loc) {
1777 loc = parser.getToken().getLoc();
1778
1779 if (parser.getToken().isNot(Token::at_identifier))
1780 return emitError(loc, "expected function name");
1781
1782 result = parser.getTokenSpelling();
1783 parser.consumeToken(Token::at_identifier);
1784 return false;
1785 }
1786
Chris Lattner85ee1512018-07-25 11:15:20 -07001787 bool parseOperand(OperandType &result) override {
1788 FunctionParser::SSAUseInfo useInfo;
1789 if (parser.parseSSAUse(useInfo))
1790 return true;
1791
1792 result = {useInfo.loc, useInfo.name, useInfo.number};
1793 return false;
1794 }
1795
1796 bool parseOperandList(SmallVectorImpl<OperandType> &result,
1797 int requiredOperandCount = -1,
Chris Lattner85cf26d2018-08-02 16:54:36 -07001798 Delimiter delimiter = Delimiter::None) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001799 auto startLoc = parser.getToken().getLoc();
1800
Chris Lattner85cf26d2018-08-02 16:54:36 -07001801 // Handle delimiters.
1802 switch (delimiter) {
1803 case Delimiter::None:
Chris Lattner85ee1512018-07-25 11:15:20 -07001804 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001805 case Delimiter::OptionalParen:
Chris Lattner3164ae62018-07-28 09:36:25 -07001806 if (parser.getToken().isNot(Token::l_paren))
1807 return false;
1808 LLVM_FALLTHROUGH;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001809 case Delimiter::Paren:
Chris Lattner85ee1512018-07-25 11:15:20 -07001810 if (parser.parseToken(Token::l_paren, "expected '(' in operand list"))
1811 return true;
1812 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001813 case Delimiter::OptionalSquare:
Chris Lattner3164ae62018-07-28 09:36:25 -07001814 if (parser.getToken().isNot(Token::l_square))
1815 return false;
1816 LLVM_FALLTHROUGH;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001817 case Delimiter::Square:
Chris Lattner85ee1512018-07-25 11:15:20 -07001818 if (parser.parseToken(Token::l_square, "expected '[' in operand list"))
1819 return true;
1820 break;
1821 }
1822
1823 // Check for zero operands.
1824 if (parser.getToken().is(Token::percent_identifier)) {
1825 do {
1826 OperandType operand;
1827 if (parseOperand(operand))
1828 return true;
1829 result.push_back(operand);
1830 } while (parser.consumeIf(Token::comma));
1831 }
1832
Chris Lattner85cf26d2018-08-02 16:54:36 -07001833 // Handle delimiters. If we reach here, the optional delimiters were
Chris Lattner3164ae62018-07-28 09:36:25 -07001834 // present, so we need to parse their closing one.
Chris Lattner85cf26d2018-08-02 16:54:36 -07001835 switch (delimiter) {
1836 case Delimiter::None:
Chris Lattner85ee1512018-07-25 11:15:20 -07001837 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001838 case Delimiter::OptionalParen:
1839 case Delimiter::Paren:
Chris Lattner85ee1512018-07-25 11:15:20 -07001840 if (parser.parseToken(Token::r_paren, "expected ')' in operand list"))
1841 return true;
1842 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001843 case Delimiter::OptionalSquare:
1844 case Delimiter::Square:
Chris Lattner85ee1512018-07-25 11:15:20 -07001845 if (parser.parseToken(Token::r_square, "expected ']' in operand list"))
1846 return true;
1847 break;
1848 }
1849
1850 if (requiredOperandCount != -1 && result.size() != requiredOperandCount)
1851 emitError(startLoc,
1852 "expected " + Twine(requiredOperandCount) + " operands");
1853 return false;
1854 }
1855
Chris Lattner1aa46322018-08-21 17:55:22 -07001856 /// Resolve a parse function name and a type into a function reference.
1857 virtual bool resolveFunctionName(StringRef name, FunctionType *type,
1858 llvm::SMLoc loc, Function *&result) {
1859 result = parser.resolveFunctionReference(name, loc, type);
1860 return result == nullptr;
1861 }
1862
Chris Lattner85ee1512018-07-25 11:15:20 -07001863 //===--------------------------------------------------------------------===//
1864 // Methods for interacting with the parser
1865 //===--------------------------------------------------------------------===//
1866
1867 Builder &getBuilder() const override { return parser.builder; }
1868
1869 llvm::SMLoc getNameLoc() const override { return nameLoc; }
1870
Chris Lattner1aa46322018-08-21 17:55:22 -07001871 bool resolveOperand(const OperandType &operand, Type *type,
Chris Lattner8bdbebf2018-08-08 11:02:58 -07001872 SmallVectorImpl<SSAValue *> &result) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001873 FunctionParser::SSAUseInfo operandInfo = {operand.name, operand.number,
1874 operand.location};
Chris Lattner8bdbebf2018-08-08 11:02:58 -07001875 if (auto *value = parser.resolveSSAUse(operandInfo, type)) {
1876 result.push_back(value);
1877 return false;
1878 }
1879 return true;
Chris Lattner85ee1512018-07-25 11:15:20 -07001880 }
1881
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001882 /// Emit a diagnostic at the specified location and return true.
1883 bool emitError(llvm::SMLoc loc, const Twine &message) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001884 parser.emitError(loc, "custom op '" + Twine(opName) + "' " + message);
1885 emittedError = true;
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001886 return true;
Chris Lattner85ee1512018-07-25 11:15:20 -07001887 }
1888
1889 bool didEmitError() const { return emittedError; }
1890
1891private:
1892 SMLoc nameLoc;
1893 StringRef opName;
1894 FunctionParser &parser;
1895 bool emittedError = false;
1896};
1897} // end anonymous namespace.
1898
1899Operation *FunctionParser::parseCustomOperation(
1900 const CreateOperationFunction &createOpFunc) {
1901 auto opLoc = getToken().getLoc();
1902 auto opName = getTokenSpelling();
1903 CustomOpAsmParser opAsmParser(opLoc, opName, *this);
1904
1905 auto *opDefinition = getOperationSet().lookup(opName);
1906 if (!opDefinition) {
1907 opAsmParser.emitError(opLoc, "is unknown");
1908 return nullptr;
1909 }
1910
1911 consumeToken();
1912
Chris Lattner1aa46322018-08-21 17:55:22 -07001913 // If the custom op parser crashes, produce some indication to help debugging.
1914 std::string opNameStr = opName.str();
1915 llvm::PrettyStackTraceFormat fmt("MLIR Parser: custom op parser '%s'",
1916 opNameStr.c_str());
1917
Chris Lattner85ee1512018-07-25 11:15:20 -07001918 // Have the op implementation take a crack and parsing this.
Chris Lattner1eb77482018-08-22 19:25:49 -07001919 OperationState opState(builder.getContext(), opName);
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001920 if (opDefinition->parseAssembly(&opAsmParser, &opState))
1921 return nullptr;
Chris Lattner85ee1512018-07-25 11:15:20 -07001922
1923 // If it emitted an error, we failed.
1924 if (opAsmParser.didEmitError())
1925 return nullptr;
1926
1927 // Otherwise, we succeeded. Use the state it parsed as our op information.
Chris Lattner992a1272018-08-07 12:02:37 -07001928 return createOpFunc(opState);
Chris Lattner85ee1512018-07-25 11:15:20 -07001929}
1930
Chris Lattner48af7d12018-07-09 19:05:38 -07001931//===----------------------------------------------------------------------===//
1932// CFG Functions
1933//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001934
Chris Lattner4c95a502018-06-23 16:03:42 -07001935namespace {
Chris Lattner48af7d12018-07-09 19:05:38 -07001936/// This is a specialized parser for CFGFunction's, maintaining the state
1937/// transient to their bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001938class CFGFunctionParser : public FunctionParser {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001939public:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001940 CFGFunctionParser(ParserState &state, CFGFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001941 : FunctionParser(state, Kind::CFGFunc), function(function),
1942 builder(function) {}
Chris Lattner2e595eb2018-07-10 10:08:27 -07001943
1944 ParseResult parseFunctionBody();
1945
1946private:
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001947 CFGFunction *function;
James Molloy0ff71542018-07-23 16:56:32 -07001948 llvm::StringMap<std::pair<BasicBlock *, SMLoc>> blocksByName;
Chris Lattner48af7d12018-07-09 19:05:38 -07001949
1950 /// This builder intentionally shadows the builder in the base class, with a
1951 /// more specific builder type.
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001952 CFGFuncBuilder builder;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001953
Chris Lattner4c95a502018-06-23 16:03:42 -07001954 /// Get the basic block with the specified name, creating it if it doesn't
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001955 /// already exist. The location specified is the point of use, which allows
1956 /// us to diagnose references to blocks that are not defined precisely.
1957 BasicBlock *getBlockNamed(StringRef name, SMLoc loc) {
1958 auto &blockAndLoc = blocksByName[name];
1959 if (!blockAndLoc.first) {
Chris Lattner3a467cc2018-07-01 20:28:00 -07001960 blockAndLoc.first = new BasicBlock();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001961 blockAndLoc.second = loc;
Chris Lattner4c95a502018-06-23 16:03:42 -07001962 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001963 return blockAndLoc.first;
Chris Lattner4c95a502018-06-23 16:03:42 -07001964 }
Chris Lattner48af7d12018-07-09 19:05:38 -07001965
James Molloy61a656c2018-07-22 15:45:24 -07001966 ParseResult
1967 parseOptionalBasicBlockArgList(SmallVectorImpl<BBArgument *> &results,
1968 BasicBlock *owner);
James Molloy4f788372018-07-24 15:01:27 -07001969 ParseResult parseBranchBlockAndUseList(BasicBlock *&block,
1970 SmallVectorImpl<CFGValue *> &values);
James Molloy61a656c2018-07-22 15:45:24 -07001971
Chris Lattner48af7d12018-07-09 19:05:38 -07001972 ParseResult parseBasicBlock();
1973 OperationInst *parseCFGOperation();
1974 TerminatorInst *parseTerminator();
Chris Lattner4c95a502018-06-23 16:03:42 -07001975};
1976} // end anonymous namespace
1977
James Molloy61a656c2018-07-22 15:45:24 -07001978/// Parse a (possibly empty) list of SSA operands with types as basic block
Chris Lattner2c402672018-07-23 11:56:17 -07001979/// arguments.
James Molloy61a656c2018-07-22 15:45:24 -07001980///
1981/// ssa-id-and-type-list ::= ssa-id-and-type (`,` ssa-id-and-type)*
1982///
1983ParseResult CFGFunctionParser::parseOptionalBasicBlockArgList(
1984 SmallVectorImpl<BBArgument *> &results, BasicBlock *owner) {
1985 if (getToken().is(Token::r_brace))
1986 return ParseSuccess;
1987
1988 return parseCommaSeparatedList([&]() -> ParseResult {
1989 auto type = parseSSADefOrUseAndType<Type *>(
1990 [&](SSAUseInfo useInfo, Type *type) -> Type * {
1991 BBArgument *arg = owner->addArgument(type);
Chris Lattner2b97d502018-08-06 14:19:46 -07001992 if (addDefinition(useInfo, arg))
James Molloy61a656c2018-07-22 15:45:24 -07001993 return nullptr;
1994 return type;
1995 });
1996 return type ? ParseSuccess : ParseFailure;
1997 });
1998}
1999
Chris Lattner48af7d12018-07-09 19:05:38 -07002000ParseResult CFGFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07002001 auto braceLoc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07002002 if (parseToken(Token::l_brace, "expected '{' in CFG function"))
2003 return ParseFailure;
Chris Lattner48af7d12018-07-09 19:05:38 -07002004
2005 // Make sure we have at least one block.
2006 if (getToken().is(Token::r_brace))
2007 return emitError("CFG functions must have at least one basic block");
Chris Lattner4c95a502018-06-23 16:03:42 -07002008
2009 // Parse the list of blocks.
2010 while (!consumeIf(Token::r_brace))
Chris Lattner48af7d12018-07-09 19:05:38 -07002011 if (parseBasicBlock())
Chris Lattner4c95a502018-06-23 16:03:42 -07002012 return ParseFailure;
2013
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002014 // Verify that all referenced blocks were defined. Iteration over a
2015 // StringMap isn't determinstic, but this is good enough for our purposes.
Chris Lattner48af7d12018-07-09 19:05:38 -07002016 for (auto &elt : blocksByName) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002017 auto *bb = elt.second.first;
Chris Lattner3a467cc2018-07-01 20:28:00 -07002018 if (!bb->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002019 return emitError(elt.second.second,
James Molloy0ff71542018-07-23 16:56:32 -07002020 "reference to an undefined basic block '" + elt.first() +
2021 "'");
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002022 }
2023
Chris Lattner40746442018-07-21 14:32:09 -07002024 return finalizeFunction(function, braceLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07002025}
2026
2027/// Basic block declaration.
2028///
2029/// basic-block ::= bb-label instruction* terminator-stmt
2030/// bb-label ::= bb-id bb-arg-list? `:`
2031/// bb-id ::= bare-id
2032/// bb-arg-list ::= `(` ssa-id-and-type-list? `)`
2033///
Chris Lattner48af7d12018-07-09 19:05:38 -07002034ParseResult CFGFunctionParser::parseBasicBlock() {
2035 SMLoc nameLoc = getToken().getLoc();
2036 auto name = getTokenSpelling();
Chris Lattnerf7702a62018-07-23 17:30:01 -07002037 if (parseToken(Token::bare_identifier, "expected basic block name"))
2038 return ParseFailure;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002039
Chris Lattner48af7d12018-07-09 19:05:38 -07002040 auto *block = getBlockNamed(name, nameLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07002041
2042 // If this block has already been parsed, then this is a redefinition with the
2043 // same block name.
Chris Lattner3a467cc2018-07-01 20:28:00 -07002044 if (block->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002045 return emitError(nameLoc, "redefinition of block '" + name.str() + "'");
2046
Chris Lattner78276e32018-07-07 15:48:26 -07002047 // If an argument list is present, parse it.
2048 if (consumeIf(Token::l_paren)) {
James Molloy61a656c2018-07-22 15:45:24 -07002049 SmallVector<BBArgument *, 8> bbArgs;
Chris Lattnerf7702a62018-07-23 17:30:01 -07002050 if (parseOptionalBasicBlockArgList(bbArgs, block) ||
2051 parseToken(Token::r_paren, "expected ')' to end argument list"))
Chris Lattner78276e32018-07-07 15:48:26 -07002052 return ParseFailure;
Chris Lattner78276e32018-07-07 15:48:26 -07002053 }
Chris Lattner4c95a502018-06-23 16:03:42 -07002054
James Molloy61a656c2018-07-22 15:45:24 -07002055 // Add the block to the function.
2056 function->push_back(block);
2057
Chris Lattnerf7702a62018-07-23 17:30:01 -07002058 if (parseToken(Token::colon, "expected ':' after basic block name"))
2059 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07002060
Chris Lattner158e0a3e2018-07-08 20:51:38 -07002061 // Set the insertion point to the block we want to insert new operations into.
Chris Lattner48af7d12018-07-09 19:05:38 -07002062 builder.setInsertionPoint(block);
Chris Lattner158e0a3e2018-07-08 20:51:38 -07002063
Chris Lattner992a1272018-08-07 12:02:37 -07002064 auto createOpFunc = [&](const OperationState &result) -> Operation * {
2065 return builder.createOperation(result);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002066 };
2067
Chris Lattnered65a732018-06-28 20:45:33 -07002068 // Parse the list of operations that make up the body of the block.
James Molloy4f788372018-07-24 15:01:27 -07002069 while (getToken().isNot(Token::kw_return, Token::kw_br, Token::kw_cond_br)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002070 if (parseOperation(createOpFunc))
Chris Lattnered65a732018-06-28 20:45:33 -07002071 return ParseFailure;
2072 }
Chris Lattner4c95a502018-06-23 16:03:42 -07002073
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002074 if (!parseTerminator())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002075 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07002076
2077 return ParseSuccess;
2078}
2079
James Molloy4f788372018-07-24 15:01:27 -07002080ParseResult CFGFunctionParser::parseBranchBlockAndUseList(
2081 BasicBlock *&block, SmallVectorImpl<CFGValue *> &values) {
2082 block = getBlockNamed(getTokenSpelling(), getToken().getLoc());
2083 if (parseToken(Token::bare_identifier, "expected basic block name"))
2084 return ParseFailure;
2085
2086 if (!consumeIf(Token::l_paren))
2087 return ParseSuccess;
2088 if (parseOptionalSSAUseAndTypeList(values, /*isParenthesized*/ false) ||
2089 parseToken(Token::r_paren, "expected ')' to close argument list"))
2090 return ParseFailure;
2091 return ParseSuccess;
2092}
2093
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002094/// Parse the terminator instruction for a basic block.
2095///
2096/// terminator-stmt ::= `br` bb-id branch-use-list?
Chris Lattner1604e472018-07-23 08:42:19 -07002097/// branch-use-list ::= `(` ssa-use-list `)` ':' type-list-no-parens
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002098/// terminator-stmt ::=
2099/// `cond_br` ssa-use `,` bb-id branch-use-list? `,` bb-id branch-use-list?
2100/// terminator-stmt ::= `return` ssa-use-and-type-list?
2101///
Chris Lattner48af7d12018-07-09 19:05:38 -07002102TerminatorInst *CFGFunctionParser::parseTerminator() {
2103 switch (getToken().getKind()) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002104 default:
Chris Lattner3a467cc2018-07-01 20:28:00 -07002105 return (emitError("expected terminator at end of basic block"), nullptr);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002106
Chris Lattner40746442018-07-21 14:32:09 -07002107 case Token::kw_return: {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002108 consumeToken(Token::kw_return);
Chris Lattner40746442018-07-21 14:32:09 -07002109
Chris Lattner2c402672018-07-23 11:56:17 -07002110 // Parse any operands.
2111 SmallVector<CFGValue *, 8> operands;
2112 if (parseOptionalSSAUseAndTypeList(operands, /*isParenthesized*/ false))
2113 return nullptr;
2114 return builder.createReturnInst(operands);
Chris Lattner40746442018-07-21 14:32:09 -07002115 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002116
2117 case Token::kw_br: {
2118 consumeToken(Token::kw_br);
James Molloy4f788372018-07-24 15:01:27 -07002119 BasicBlock *destBB;
2120 SmallVector<CFGValue *, 4> values;
2121 if (parseBranchBlockAndUseList(destBB, values))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002122 return nullptr;
Chris Lattner1604e472018-07-23 08:42:19 -07002123 auto branch = builder.createBranchInst(destBB);
James Molloy4f788372018-07-24 15:01:27 -07002124 branch->addOperands(values);
Chris Lattner1604e472018-07-23 08:42:19 -07002125 return branch;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002126 }
James Molloy4f788372018-07-24 15:01:27 -07002127
2128 case Token::kw_cond_br: {
2129 consumeToken(Token::kw_cond_br);
2130 SSAUseInfo ssaUse;
2131 if (parseSSAUse(ssaUse))
2132 return nullptr;
2133 auto *cond = resolveSSAUse(ssaUse, builder.getIntegerType(1));
2134 if (!cond)
2135 return (emitError("expected type was boolean (i1)"), nullptr);
2136 if (parseToken(Token::comma, "expected ',' in conditional branch"))
2137 return nullptr;
2138
2139 BasicBlock *trueBlock;
2140 SmallVector<CFGValue *, 4> trueOperands;
2141 if (parseBranchBlockAndUseList(trueBlock, trueOperands))
2142 return nullptr;
2143
2144 if (parseToken(Token::comma, "expected ',' in conditional branch"))
2145 return nullptr;
2146
2147 BasicBlock *falseBlock;
2148 SmallVector<CFGValue *, 4> falseOperands;
2149 if (parseBranchBlockAndUseList(falseBlock, falseOperands))
2150 return nullptr;
2151
2152 auto branch = builder.createCondBranchInst(cast<CFGValue>(cond), trueBlock,
2153 falseBlock);
2154 branch->addTrueOperands(trueOperands);
2155 branch->addFalseOperands(falseOperands);
2156 return branch;
2157 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002158 }
2159}
2160
Chris Lattner48af7d12018-07-09 19:05:38 -07002161//===----------------------------------------------------------------------===//
2162// ML Functions
2163//===----------------------------------------------------------------------===//
2164
2165namespace {
2166/// Refined parser for MLFunction bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07002167class MLFunctionParser : public FunctionParser {
Chris Lattner48af7d12018-07-09 19:05:38 -07002168public:
Chris Lattner48af7d12018-07-09 19:05:38 -07002169 MLFunctionParser(ParserState &state, MLFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07002170 : FunctionParser(state, Kind::MLFunc), function(function),
Chris Lattnere787b322018-08-08 11:14:57 -07002171 builder(function, function->end()) {}
Chris Lattner48af7d12018-07-09 19:05:38 -07002172
2173 ParseResult parseFunctionBody();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002174
2175private:
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002176 MLFunction *function;
2177
2178 /// This builder intentionally shadows the builder in the base class, with a
2179 /// more specific builder type.
2180 MLFuncBuilder builder;
2181
2182 ParseResult parseForStmt();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002183 AffineConstantExpr *parseIntConstant();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002184 ParseResult parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002185 ParseResult parseElseClause(IfClause *elseClause);
Uday Bondhugulabc535622018-08-07 14:24:38 -07002186 IntegerSet *parseCondition();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002187 ParseResult parseStatements(StmtBlock *block);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002188 ParseResult parseStmtBlock(StmtBlock *block);
Chris Lattner48af7d12018-07-09 19:05:38 -07002189};
2190} // end anonymous namespace
2191
Chris Lattner48af7d12018-07-09 19:05:38 -07002192ParseResult MLFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07002193 auto braceLoc = getToken().getLoc();
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002194
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002195 // Parse statements in this function.
2196 if (parseStmtBlock(function))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002197 return ParseFailure;
Chris Lattner40746442018-07-21 14:32:09 -07002198
Chris Lattner40746442018-07-21 14:32:09 -07002199 return finalizeFunction(function, braceLoc);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002200}
2201
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002202/// For statement.
2203///
Chris Lattner48af7d12018-07-09 19:05:38 -07002204/// ml-for-stmt ::= `for` ssa-id `=` lower-bound `to` upper-bound
2205/// (`step` integer-literal)? `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002206///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002207ParseResult MLFunctionParser::parseForStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002208 consumeToken(Token::kw_for);
2209
Uday Bondhugula67701712018-08-21 16:01:23 -07002210 // Parse induction variable.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002211 if (getToken().isNot(Token::percent_identifier))
2212 return emitError("expected SSA identifier for the loop variable");
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002213
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002214 auto loc = getToken().getLoc();
Tatiana Shpeismand880b352018-07-31 23:14:16 -07002215 StringRef inductionVariableName = getTokenSpelling();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002216 consumeToken(Token::percent_identifier);
2217
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002218 if (parseToken(Token::equal, "expected '='"))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002219 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002220
Uday Bondhugula67701712018-08-21 16:01:23 -07002221 // Parse loop bounds.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002222 AffineConstantExpr *lowerBound = parseIntConstant();
2223 if (!lowerBound)
2224 return ParseFailure;
2225
Chris Lattnerf7702a62018-07-23 17:30:01 -07002226 if (parseToken(Token::kw_to, "expected 'to' between bounds"))
2227 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002228
2229 AffineConstantExpr *upperBound = parseIntConstant();
2230 if (!upperBound)
2231 return ParseFailure;
2232
Uday Bondhugula67701712018-08-21 16:01:23 -07002233 // Parse step.
2234 int64_t step = 1;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002235 if (consumeIf(Token::kw_step)) {
Uday Bondhugula67701712018-08-21 16:01:23 -07002236 AffineConstantExpr *stepExpr = parseIntConstant();
2237 if (!stepExpr)
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002238 return ParseFailure;
Uday Bondhugula67701712018-08-21 16:01:23 -07002239 step = stepExpr->getValue();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002240 }
2241
2242 // Create for statement.
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002243 ForStmt *forStmt = builder.createFor(lowerBound, upperBound, step);
2244
2245 // Create SSA value definition for the induction variable.
Chris Lattner2b97d502018-08-06 14:19:46 -07002246 if (addDefinition({inductionVariableName, 0, loc}, forStmt))
2247 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002248
2249 // If parsing of the for statement body fails,
2250 // MLIR contains for statement with those nested statements that have been
2251 // successfully parsed.
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002252 if (parseStmtBlock(forStmt))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002253 return ParseFailure;
2254
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002255 // Reset insertion point to the current block.
Chris Lattnere787b322018-08-08 11:14:57 -07002256 builder.setInsertionPointToEnd(forStmt->getBlock());
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002257 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002258}
2259
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002260// This method is temporary workaround to parse simple loop bounds and
2261// step.
2262// TODO: remove this method once it's no longer used.
2263AffineConstantExpr *MLFunctionParser::parseIntConstant() {
2264 if (getToken().isNot(Token::integer))
2265 return (emitError("expected non-negative integer for now"), nullptr);
2266
2267 auto val = getToken().getUInt64IntegerValue();
2268 if (!val.hasValue() || (int64_t)val.getValue() < 0) {
2269 return (emitError("constant too large for affineint"), nullptr);
2270 }
2271 consumeToken(Token::integer);
2272 return builder.getConstantExpr((int64_t)val.getValue());
2273}
2274
Uday Bondhugulabc535622018-08-07 14:24:38 -07002275/// Parse condition.
2276IntegerSet *MLFunctionParser::parseCondition() {
2277 return parseIntegerSetReference();
2278
2279 // TODO: Parse operands to the integer set.
2280}
2281
2282/// Parse an affine constraint.
2283/// affine-constraint ::= affine-expr `>=` `0`
2284/// | affine-expr `==` `0`
2285///
2286/// isEq is set to true if the parsed constraint is an equality, false if it is
2287/// an inequality (greater than or equal).
2288///
2289AffineExpr *AffineParser::parseAffineConstraint(bool *isEq) {
2290 AffineExpr *expr = parseAffineExpr();
2291 if (!expr)
2292 return nullptr;
2293
2294 if (consumeIf(Token::greater) && consumeIf(Token::equal) &&
2295 getToken().is(Token::integer)) {
2296 auto dim = getToken().getUnsignedIntegerValue();
2297 if (dim.hasValue() && dim.getValue() == 0) {
2298 consumeToken(Token::integer);
2299 *isEq = false;
2300 return expr;
2301 }
2302 return (emitError("expected '0' after '>='"), nullptr);
2303 }
2304
2305 if (consumeIf(Token::equal) && consumeIf(Token::equal) &&
2306 getToken().is(Token::integer)) {
2307 auto dim = getToken().getUnsignedIntegerValue();
2308 if (dim.hasValue() && dim.getValue() == 0) {
2309 consumeToken(Token::integer);
2310 *isEq = true;
2311 return expr;
2312 }
2313 return (emitError("expected '0' after '=='"), nullptr);
2314 }
2315
2316 return (emitError("expected '== 0' or '>= 0' at end of affine constraint"),
2317 nullptr);
2318}
2319
2320/// Parse an integer set definition.
2321/// integer-set-inline
2322/// ::= dim-and-symbol-id-lists `:` affine-constraint-conjunction
2323/// affine-constraint-conjunction ::= /*empty*/
2324/// | affine-constraint (`,` affine-constraint)*
2325///
2326IntegerSet *AffineParser::parseIntegerSetInline() {
2327 unsigned numDims = 0, numSymbols = 0;
2328
2329 // List of dimensional identifiers.
2330 if (parseDimIdList(numDims))
2331 return nullptr;
2332
2333 // Symbols are optional.
2334 if (getToken().is(Token::l_square)) {
2335 if (parseSymbolIdList(numSymbols))
2336 return nullptr;
2337 }
2338
2339 if (parseToken(Token::colon, "expected ':' or '['") ||
2340 parseToken(Token::l_paren,
2341 "expected '(' at start of integer set constraint list"))
2342 return nullptr;
2343
2344 SmallVector<AffineExpr *, 4> constraints;
2345 SmallVector<bool, 4> isEqs;
2346 auto parseElt = [&]() -> ParseResult {
2347 bool isEq;
2348 auto *elt = parseAffineConstraint(&isEq);
2349 ParseResult res = elt ? ParseSuccess : ParseFailure;
2350 if (elt) {
2351 constraints.push_back(elt);
2352 isEqs.push_back(isEq);
2353 }
2354 return res;
2355 };
2356
2357 // Parse a list of affine constraints (comma-separated) .
2358 // Grammar: affine-constraint-conjunct ::= `(` affine-constraint (`,`
2359 // affine-constraint)* `)
2360 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt, true))
2361 return nullptr;
2362
2363 // Parsed a valid integer set.
2364 return builder.getIntegerSet(numDims, numSymbols, constraints, isEqs);
2365}
2366
2367IntegerSet *Parser::parseIntegerSetInline() {
2368 return AffineParser(state).parseIntegerSetInline();
2369}
2370
2371/// Parse a reference to an integer set.
2372/// integer-set ::= integer-set-id | integer-set-inline
2373/// integer-set-id ::= `@@` suffix-id
2374///
2375IntegerSet *Parser::parseIntegerSetReference() {
2376 if (getToken().is(Token::double_at_identifier)) {
2377 // Parse integer set identifier and verify that it exists.
2378 StringRef integerSetId = getTokenSpelling().drop_front(2);
2379 if (getState().integerSetDefinitions.count(integerSetId) == 0)
2380 return (emitError("undefined integer set id '" + integerSetId + "'"),
2381 nullptr);
2382 consumeToken(Token::double_at_identifier);
2383 return getState().integerSetDefinitions[integerSetId];
2384 }
2385 // Try to parse an inline integer set definition.
2386 return parseIntegerSetInline();
2387}
2388
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002389/// If statement.
2390///
Chris Lattner48af7d12018-07-09 19:05:38 -07002391/// ml-if-head ::= `if` ml-if-cond `{` ml-stmt* `}`
2392/// | ml-if-head `else` `if` ml-if-cond `{` ml-stmt* `}`
2393/// ml-if-stmt ::= ml-if-head
2394/// | ml-if-head `else` `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002395///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002396ParseResult MLFunctionParser::parseIfStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002397 consumeToken(Token::kw_if);
Uday Bondhugulabc535622018-08-07 14:24:38 -07002398
2399 if (parseToken(Token::l_paren, "expected '('"))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002400 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002401
Uday Bondhugulabc535622018-08-07 14:24:38 -07002402 IntegerSet *condition = parseCondition();
2403 if (!condition)
Chris Lattnerf7702a62018-07-23 17:30:01 -07002404 return ParseFailure;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002405
Uday Bondhugulabc535622018-08-07 14:24:38 -07002406 if (parseToken(Token::r_paren, "expected ')'"))
2407 return ParseFailure;
2408
2409 IfStmt *ifStmt = builder.createIf(condition);
Chris Lattnere787b322018-08-08 11:14:57 -07002410 IfClause *thenClause = ifStmt->getThen();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002411
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002412 // When parsing of an if statement body fails, the IR contains
2413 // the if statement with the portion of the body that has been
2414 // successfully parsed.
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002415 if (parseStmtBlock(thenClause))
2416 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002417
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002418 if (consumeIf(Token::kw_else)) {
Chris Lattnere787b322018-08-08 11:14:57 -07002419 auto *elseClause = ifStmt->createElse();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002420 if (parseElseClause(elseClause))
2421 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002422 }
2423
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002424 // Reset insertion point to the current block.
Chris Lattnere787b322018-08-08 11:14:57 -07002425 builder.setInsertionPointToEnd(ifStmt->getBlock());
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002426
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002427 return ParseSuccess;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002428}
2429
2430ParseResult MLFunctionParser::parseElseClause(IfClause *elseClause) {
2431 if (getToken().is(Token::kw_if)) {
Chris Lattnere787b322018-08-08 11:14:57 -07002432 builder.setInsertionPointToEnd(elseClause);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002433 return parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002434 }
2435
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002436 return parseStmtBlock(elseClause);
2437}
2438
2439///
2440/// Parse a list of statements ending with `return` or `}`
2441///
2442ParseResult MLFunctionParser::parseStatements(StmtBlock *block) {
Chris Lattner992a1272018-08-07 12:02:37 -07002443 auto createOpFunc = [&](const OperationState &state) -> Operation * {
2444 return builder.createOperation(state);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002445 };
2446
Chris Lattnere787b322018-08-08 11:14:57 -07002447 builder.setInsertionPointToEnd(block);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002448
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002449 // Parse statements till we see '}' or 'return'.
2450 // Return statement is parsed separately to emit a more intuitive error
2451 // when '}' is missing after the return statement.
2452 while (getToken().isNot(Token::r_brace, Token::kw_return)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002453 switch (getToken().getKind()) {
2454 default:
2455 if (parseOperation(createOpFunc))
2456 return ParseFailure;
2457 break;
2458 case Token::kw_for:
2459 if (parseForStmt())
2460 return ParseFailure;
2461 break;
2462 case Token::kw_if:
2463 if (parseIfStmt())
2464 return ParseFailure;
2465 break;
2466 } // end switch
2467 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002468
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002469 // Parse the return statement.
2470 if (getToken().is(Token::kw_return))
2471 if (parseOperation(createOpFunc))
2472 return ParseFailure;
2473
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002474 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002475}
2476
2477///
2478/// Parse `{` ml-stmt* `}`
2479///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002480ParseResult MLFunctionParser::parseStmtBlock(StmtBlock *block) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002481 if (parseToken(Token::l_brace, "expected '{' before statement list") ||
2482 parseStatements(block) ||
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002483 parseToken(Token::r_brace, "expected '}' after statement list"))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002484 return ParseFailure;
2485
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002486 return ParseSuccess;
2487}
2488
Chris Lattner4c95a502018-06-23 16:03:42 -07002489//===----------------------------------------------------------------------===//
2490// Top-level entity parsing.
2491//===----------------------------------------------------------------------===//
2492
Chris Lattner2e595eb2018-07-10 10:08:27 -07002493namespace {
2494/// This parser handles entities that are only valid at the top level of the
2495/// file.
2496class ModuleParser : public Parser {
2497public:
2498 explicit ModuleParser(ParserState &state) : Parser(state) {}
2499
2500 ParseResult parseModule();
2501
2502private:
Chris Lattner4613d9e2018-08-19 21:17:22 -07002503 ParseResult finalizeModule();
2504
Chris Lattner2e595eb2018-07-10 10:08:27 -07002505 ParseResult parseAffineMapDef();
Uday Bondhugulabc535622018-08-07 14:24:38 -07002506 ParseResult parseIntegerSetDef();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002507
2508 // Functions.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002509 ParseResult parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2510 SmallVectorImpl<StringRef> &argNames);
2511 ParseResult parseFunctionSignature(StringRef &name, FunctionType *&type,
2512 SmallVectorImpl<StringRef> *argNames);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002513 ParseResult parseExtFunc();
2514 ParseResult parseCFGFunc();
2515 ParseResult parseMLFunc();
2516};
2517} // end anonymous namespace
2518
2519/// Affine map declaration.
2520///
2521/// affine-map-def ::= affine-map-id `=` affine-map-inline
2522///
2523ParseResult ModuleParser::parseAffineMapDef() {
2524 assert(getToken().is(Token::hash_identifier));
2525
2526 StringRef affineMapId = getTokenSpelling().drop_front();
2527
2528 // Check for redefinitions.
Uday Bondhugulabc535622018-08-07 14:24:38 -07002529 auto **entry = &getState().affineMapDefinitions[affineMapId];
2530 if (*entry)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002531 return emitError("redefinition of affine map id '" + affineMapId + "'");
2532
2533 consumeToken(Token::hash_identifier);
2534
2535 // Parse the '='
Chris Lattnerf7702a62018-07-23 17:30:01 -07002536 if (parseToken(Token::equal,
2537 "expected '=' in affine map outlined definition"))
2538 return ParseFailure;
Chris Lattner2e595eb2018-07-10 10:08:27 -07002539
Uday Bondhugulabc535622018-08-07 14:24:38 -07002540 *entry = parseAffineMapInline();
2541 if (!*entry)
2542 return ParseFailure;
2543
2544 return ParseSuccess;
2545}
2546
2547/// Integer set declaration.
2548///
2549/// integer-set-decl ::= integer-set-id `=` integer-set-inline
2550///
2551ParseResult ModuleParser::parseIntegerSetDef() {
2552 assert(getToken().is(Token::double_at_identifier));
2553
2554 StringRef integerSetId = getTokenSpelling().drop_front(2);
2555
2556 // Check for redefinitions (a default entry is created if one doesn't exist)
2557 auto **entry = &getState().integerSetDefinitions[integerSetId];
2558 if (*entry)
2559 return emitError("redefinition of integer set id '" + integerSetId + "'");
2560
2561 consumeToken(Token::double_at_identifier);
2562
2563 // Parse the '='
2564 if (parseToken(Token::equal,
2565 "expected '=' in outlined integer set definition"))
2566 return ParseFailure;
2567
2568 *entry = parseIntegerSetInline();
2569 if (!*entry)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002570 return ParseFailure;
2571
Chris Lattner2e595eb2018-07-10 10:08:27 -07002572 return ParseSuccess;
2573}
2574
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002575/// Parse a (possibly empty) list of MLFunction arguments with types.
2576///
2577/// ml-argument ::= ssa-id `:` type
2578/// ml-argument-list ::= ml-argument (`,` ml-argument)* | /*empty*/
2579///
2580ParseResult
2581ModuleParser::parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2582 SmallVectorImpl<StringRef> &argNames) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002583 consumeToken(Token::l_paren);
2584
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002585 auto parseElt = [&]() -> ParseResult {
2586 // Parse argument name
2587 if (getToken().isNot(Token::percent_identifier))
2588 return emitError("expected SSA identifier");
2589
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002590 StringRef name = getTokenSpelling();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002591 consumeToken(Token::percent_identifier);
2592 argNames.push_back(name);
2593
Chris Lattnerf7702a62018-07-23 17:30:01 -07002594 if (parseToken(Token::colon, "expected ':'"))
2595 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002596
2597 // Parse argument type
2598 auto elt = parseType();
2599 if (!elt)
2600 return ParseFailure;
2601 argTypes.push_back(elt);
2602
2603 return ParseSuccess;
2604 };
2605
Chris Lattner40746442018-07-21 14:32:09 -07002606 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002607}
2608
Chris Lattner2e595eb2018-07-10 10:08:27 -07002609/// Parse a function signature, starting with a name and including the parameter
2610/// list.
2611///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002612/// argument-list ::= type (`,` type)* | /*empty*/ | ml-argument-list
Chris Lattner2e595eb2018-07-10 10:08:27 -07002613/// function-signature ::= function-id `(` argument-list `)` (`->` type-list)?
2614///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002615ParseResult
2616ModuleParser::parseFunctionSignature(StringRef &name, FunctionType *&type,
2617 SmallVectorImpl<StringRef> *argNames) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002618 if (getToken().isNot(Token::at_identifier))
2619 return emitError("expected a function identifier like '@foo'");
2620
2621 name = getTokenSpelling().drop_front();
2622 consumeToken(Token::at_identifier);
2623
2624 if (getToken().isNot(Token::l_paren))
2625 return emitError("expected '(' in function signature");
2626
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002627 SmallVector<Type *, 4> argTypes;
2628 ParseResult parseResult;
2629
2630 if (argNames)
2631 parseResult = parseMLArgumentList(argTypes, *argNames);
2632 else
2633 parseResult = parseTypeList(argTypes);
2634
2635 if (parseResult)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002636 return ParseFailure;
2637
2638 // Parse the return type if present.
2639 SmallVector<Type *, 4> results;
2640 if (consumeIf(Token::arrow)) {
2641 if (parseTypeList(results))
2642 return ParseFailure;
2643 }
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002644 type = builder.getFunctionType(argTypes, results);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002645 return ParseSuccess;
2646}
2647
2648/// External function declarations.
2649///
2650/// ext-func ::= `extfunc` function-signature
2651///
2652ParseResult ModuleParser::parseExtFunc() {
2653 consumeToken(Token::kw_extfunc);
Chris Lattner974a8762018-08-17 16:49:42 -07002654 auto loc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002655
2656 StringRef name;
2657 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002658 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002659 return ParseFailure;
2660
2661 // Okay, the external function definition was parsed correctly.
Chris Lattner974a8762018-08-17 16:49:42 -07002662 auto *function = new ExtFunction(name, type);
2663 getModule()->getFunctions().push_back(function);
2664
2665 // Verify no name collision / redefinition.
Chris Lattner4613d9e2018-08-19 21:17:22 -07002666 if (function->getName() != name)
Chris Lattner974a8762018-08-17 16:49:42 -07002667 return emitError(loc,
2668 "redefinition of function named '" + name.str() + "'");
2669
Chris Lattner2e595eb2018-07-10 10:08:27 -07002670 return ParseSuccess;
2671}
2672
2673/// CFG function declarations.
2674///
2675/// cfg-func ::= `cfgfunc` function-signature `{` basic-block+ `}`
2676///
2677ParseResult ModuleParser::parseCFGFunc() {
2678 consumeToken(Token::kw_cfgfunc);
Chris Lattner974a8762018-08-17 16:49:42 -07002679 auto loc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002680
2681 StringRef name;
2682 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002683 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002684 return ParseFailure;
2685
2686 // Okay, the CFG function signature was parsed correctly, create the function.
Chris Lattner974a8762018-08-17 16:49:42 -07002687 auto *function = new CFGFunction(name, type);
2688 getModule()->getFunctions().push_back(function);
2689
2690 // Verify no name collision / redefinition.
Chris Lattner4613d9e2018-08-19 21:17:22 -07002691 if (function->getName() != name)
Chris Lattner974a8762018-08-17 16:49:42 -07002692 return emitError(loc,
2693 "redefinition of function named '" + name.str() + "'");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002694
2695 return CFGFunctionParser(getState(), function).parseFunctionBody();
2696}
2697
2698/// ML function declarations.
2699///
2700/// ml-func ::= `mlfunc` ml-func-signature `{` ml-stmt* ml-return-stmt `}`
2701///
2702ParseResult ModuleParser::parseMLFunc() {
2703 consumeToken(Token::kw_mlfunc);
2704
2705 StringRef name;
2706 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002707 SmallVector<StringRef, 4> argNames;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002708
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002709 auto loc = getToken().getLoc();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002710 if (parseFunctionSignature(name, type, &argNames))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002711 return ParseFailure;
2712
2713 // Okay, the ML function signature was parsed correctly, create the function.
Chris Lattner974a8762018-08-17 16:49:42 -07002714 auto *function = MLFunction::create(name, type);
2715 getModule()->getFunctions().push_back(function);
2716
2717 // Verify no name collision / redefinition.
Chris Lattner4613d9e2018-08-19 21:17:22 -07002718 if (function->getName() != name)
Chris Lattner974a8762018-08-17 16:49:42 -07002719 return emitError(loc,
2720 "redefinition of function named '" + name.str() + "'");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002721
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002722 // Create the parser.
2723 auto parser = MLFunctionParser(getState(), function);
2724
2725 // Add definitions of the function arguments.
2726 for (unsigned i = 0, e = function->getNumArguments(); i != e; ++i) {
2727 if (parser.addDefinition({argNames[i], 0, loc}, function->getArgument(i)))
2728 return ParseFailure;
2729 }
2730
2731 return parser.parseFunctionBody();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002732}
2733
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002734/// Given an attribute that could refer to a function attribute in the remapping
2735/// table, walk it and rewrite it to use the mapped function. If it doesn't
2736/// refer to anything in the table, then it is returned unmodified.
2737static Attribute *
2738remapFunctionAttrs(Attribute *input,
2739 DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable,
2740 MLIRContext *context) {
2741 // Most attributes are trivially unrelated to function attributes, skip them
2742 // rapidly.
2743 if (!input->isOrContainsFunction())
2744 return input;
2745
2746 // If we have a function attribute, remap it.
2747 if (auto *fnAttr = dyn_cast<FunctionAttr>(input)) {
2748 auto it = remappingTable.find(fnAttr);
2749 return it != remappingTable.end() ? it->second : input;
2750 }
2751
2752 // Otherwise, we must have an array attribute, remap the elements.
2753 auto *arrayAttr = cast<ArrayAttr>(input);
2754 SmallVector<Attribute *, 8> remappedElts;
2755 bool anyChange = false;
2756 for (auto *elt : arrayAttr->getValue()) {
2757 auto *newElt = remapFunctionAttrs(elt, remappingTable, context);
2758 remappedElts.push_back(newElt);
2759 anyChange |= (elt != newElt);
2760 }
2761
2762 if (!anyChange)
2763 return input;
2764
2765 return ArrayAttr::get(remappedElts, context);
2766}
2767
2768/// Remap function attributes to resolve forward references to their actual
2769/// definition.
2770static void remapFunctionAttrsInOperation(
2771 Operation *op, DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable) {
2772 for (auto attr : op->getAttrs()) {
2773 // Do the remapping, if we got the same thing back, then it must contain
2774 // functions that aren't getting remapped.
2775 auto *newVal =
2776 remapFunctionAttrs(attr.second, remappingTable, op->getContext());
2777 if (newVal == attr.second)
2778 continue;
2779
2780 // Otherwise, replace the existing attribute with the new one. It is safe
2781 // to mutate the attribute list while we walk it because underlying
2782 // attribute lists are uniqued and immortal.
2783 op->setAttr(attr.first, newVal);
2784 }
2785}
2786
Chris Lattner4613d9e2018-08-19 21:17:22 -07002787/// Finish the end of module parsing - when the result is valid, do final
2788/// checking.
2789ParseResult ModuleParser::finalizeModule() {
2790
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002791 // Resolve all forward references, building a remapping table of attributes.
2792 DenseMap<FunctionAttr *, FunctionAttr *> remappingTable;
Chris Lattner4613d9e2018-08-19 21:17:22 -07002793 for (auto forwardRef : getState().functionForwardRefs) {
2794 auto name = forwardRef.first;
2795
2796 // Resolve the reference.
2797 auto *resolvedFunction = getModule()->getNamedFunction(name);
2798 if (!resolvedFunction)
2799 return emitError(forwardRef.second.second,
2800 "reference to undefined function '" + name.str() + "'");
2801
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002802 remappingTable[builder.getFunctionAttr(forwardRef.second.first)] =
2803 builder.getFunctionAttr(resolvedFunction);
Chris Lattner4613d9e2018-08-19 21:17:22 -07002804 }
2805
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002806 // If there was nothing to remap, then we're done.
2807 if (remappingTable.empty())
2808 return ParseSuccess;
2809
2810 // Otherwise, walk the entire module replacing uses of one attribute set with
2811 // the correct ones.
2812 for (auto &fn : *getModule()) {
2813 if (auto *cfgFn = dyn_cast<CFGFunction>(&fn)) {
2814 for (auto &bb : *cfgFn) {
2815 for (auto &inst : bb) {
2816 remapFunctionAttrsInOperation(&inst, remappingTable);
2817 }
2818 }
2819 }
2820
2821 // Otherwise, look at MLFunctions. We ignore ExtFunctions.
2822 auto *mlFn = dyn_cast<MLFunction>(&fn);
2823 if (!mlFn)
2824 continue;
2825
2826 struct MLFnWalker : public StmtWalker<MLFnWalker> {
2827 MLFnWalker(DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable)
2828 : remappingTable(remappingTable) {}
2829 void visitOperationStmt(OperationStmt *opStmt) {
2830 remapFunctionAttrsInOperation(opStmt, remappingTable);
2831 }
2832
2833 DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable;
2834 };
2835
2836 MLFnWalker(remappingTable).walk(mlFn);
2837 }
2838
2839 // Now that all references to the forward definition placeholders are
2840 // resolved, we can deallocate the placeholders.
2841 for (auto forwardRef : getState().functionForwardRefs)
2842 forwardRef.second.first->destroy();
Chris Lattner4613d9e2018-08-19 21:17:22 -07002843 return ParseSuccess;
2844}
2845
Chris Lattnere79379a2018-06-22 10:39:19 -07002846/// This is the top-level module parser.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002847ParseResult ModuleParser::parseModule() {
Chris Lattnere79379a2018-06-22 10:39:19 -07002848 while (1) {
Chris Lattner48af7d12018-07-09 19:05:38 -07002849 switch (getToken().getKind()) {
Chris Lattnere79379a2018-06-22 10:39:19 -07002850 default:
2851 emitError("expected a top level entity");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002852 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002853
Uday Bondhugula015cbb12018-07-03 20:16:08 -07002854 // If we got to the end of the file, then we're done.
Chris Lattnere79379a2018-06-22 10:39:19 -07002855 case Token::eof:
Chris Lattner4613d9e2018-08-19 21:17:22 -07002856 return finalizeModule();
Chris Lattnere79379a2018-06-22 10:39:19 -07002857
2858 // If we got an error token, then the lexer already emitted an error, just
2859 // stop. Someday we could introduce error recovery if there was demand for
2860 // it.
2861 case Token::error:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002862 return ParseFailure;
2863
2864 case Token::hash_identifier:
2865 if (parseAffineMapDef())
2866 return ParseFailure;
2867 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002868
Uday Bondhugulabc535622018-08-07 14:24:38 -07002869 case Token::double_at_identifier:
2870 if (parseIntegerSetDef())
2871 return ParseFailure;
2872 break;
2873
Chris Lattnere79379a2018-06-22 10:39:19 -07002874 case Token::kw_extfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002875 if (parseExtFunc())
2876 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002877 break;
2878
Chris Lattner4c95a502018-06-23 16:03:42 -07002879 case Token::kw_cfgfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002880 if (parseCFGFunc())
2881 return ParseFailure;
MLIR Teamf85a6262018-06-27 11:03:08 -07002882 break;
Chris Lattner4c95a502018-06-23 16:03:42 -07002883
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002884 case Token::kw_mlfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002885 if (parseMLFunc())
2886 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002887 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002888 }
2889 }
2890}
2891
2892//===----------------------------------------------------------------------===//
2893
Jacques Pienaar7b829702018-07-03 13:24:09 -07002894void mlir::defaultErrorReporter(const llvm::SMDiagnostic &error) {
2895 const auto &sourceMgr = *error.getSourceMgr();
2896 sourceMgr.PrintMessage(error.getLoc(), error.getKind(), error.getMessage());
2897}
2898
Chris Lattnere79379a2018-06-22 10:39:19 -07002899/// This parses the file specified by the indicated SourceMgr and returns an
2900/// MLIR module if it was valid. If not, it emits diagnostics and returns null.
Jacques Pienaar9c411be2018-06-24 19:17:35 -07002901Module *mlir::parseSourceFile(llvm::SourceMgr &sourceMgr, MLIRContext *context,
Jacques Pienaar7b829702018-07-03 13:24:09 -07002902 SMDiagnosticHandlerTy errorReporter) {
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002903 if (!errorReporter)
2904 errorReporter = defaultErrorReporter;
2905
2906 // We are going to replace the context's handler and redirect it to use the
2907 // error reporter. Save the existing handler and reinstate it when we're
2908 // done.
2909 auto existingContextHandler = context->getDiagnosticHandler();
2910
2911 // Install a new handler that uses the error reporter.
2912 context->registerDiagnosticHandler([&](Attribute *location, StringRef message,
2913 MLIRContext::DiagnosticKind kind) {
2914 auto offset = cast<IntegerAttr>(location)->getValue();
2915 auto *mainBuffer = sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID());
2916 auto ptr = mainBuffer->getBufferStart() + offset;
2917 SourceMgr::DiagKind diagKind;
2918 switch (kind) {
2919 case MLIRContext::DiagnosticKind::Error:
2920 diagKind = SourceMgr::DK_Error;
2921 break;
2922 case MLIRContext::DiagnosticKind::Warning:
2923 diagKind = SourceMgr::DK_Warning;
2924 break;
2925 case MLIRContext::DiagnosticKind::Note:
2926 diagKind = SourceMgr::DK_Note;
2927 break;
2928 }
2929 errorReporter(
2930 sourceMgr.GetMessage(SMLoc::getFromPointer(ptr), diagKind, message));
2931 });
2932
Chris Lattner2e595eb2018-07-10 10:08:27 -07002933 // This is the result module we are parsing into.
2934 std::unique_ptr<Module> module(new Module(context));
2935
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002936 ParserState state(sourceMgr, module.get(), errorReporter);
2937 if (ModuleParser(state).parseModule()) {
2938 context->registerDiagnosticHandler(existingContextHandler);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002939 return nullptr;
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002940 }
Chris Lattner21e67f62018-07-06 10:46:19 -07002941
2942 // Make sure the parse module has no other structural problems detected by the
2943 // verifier.
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002944 std::string errorResult;
2945 module->verify(&errorResult);
2946
2947 // We don't have location information for general verifier errors, so emit the
2948 // error on the first line.
2949 if (!errorResult.empty()) {
2950 auto *mainBuffer = sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID());
2951 errorReporter(sourceMgr.GetMessage(
2952 SMLoc::getFromPointer(mainBuffer->getBufferStart()),
2953 SourceMgr::DK_Error, errorResult));
2954 return nullptr;
2955 }
2956
2957 context->registerDiagnosticHandler(existingContextHandler);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002958 return module.release();
Chris Lattnere79379a2018-06-22 10:39:19 -07002959}