blob: dc7e8b7a2a1b3c8e0574dc9d3963a5277c428708 [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
Chris Lattner1628fa02018-08-23 14:32:25 -0700123 /// Encode the specified source location information into an attribute for
124 /// attachment to the IR.
125 Attribute *getEncodedSourceLocation(llvm::SMLoc loc);
126
Chris Lattnere79379a2018-06-22 10:39:19 -0700127 /// Emit an error and return failure.
Chris Lattner4c95a502018-06-23 16:03:42 -0700128 ParseResult emitError(const Twine &message) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700129 return emitError(state.curToken.getLoc(), message);
Chris Lattner4c95a502018-06-23 16:03:42 -0700130 }
131 ParseResult emitError(SMLoc loc, const Twine &message);
Chris Lattnere79379a2018-06-22 10:39:19 -0700132
133 /// Advance the current lexer onto the next token.
134 void consumeToken() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700135 assert(state.curToken.isNot(Token::eof, Token::error) &&
Chris Lattnere79379a2018-06-22 10:39:19 -0700136 "shouldn't advance past EOF or errors");
Chris Lattner48af7d12018-07-09 19:05:38 -0700137 state.curToken = state.lex.lexToken();
Chris Lattnere79379a2018-06-22 10:39:19 -0700138 }
139
140 /// Advance the current lexer onto the next token, asserting what the expected
141 /// current token is. This is preferred to the above method because it leads
142 /// to more self-documenting code with better checking.
Chris Lattner8da0c282018-06-29 11:15:56 -0700143 void consumeToken(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700144 assert(state.curToken.is(kind) && "consumed an unexpected token");
Chris Lattnere79379a2018-06-22 10:39:19 -0700145 consumeToken();
146 }
147
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700148 /// If the current token has the specified kind, consume it and return true.
149 /// If not, return false.
Chris Lattner8da0c282018-06-29 11:15:56 -0700150 bool consumeIf(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700151 if (state.curToken.isNot(kind))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700152 return false;
153 consumeToken(kind);
154 return true;
155 }
156
Chris Lattnerf7702a62018-07-23 17:30:01 -0700157 /// Consume the specified token if present and return success. On failure,
158 /// output a diagnostic and return failure.
159 ParseResult parseToken(Token::Kind expectedToken, const Twine &message);
160
Chris Lattner40746442018-07-21 14:32:09 -0700161 /// Parse a comma-separated list of elements up until the specified end token.
162 ParseResult
163 parseCommaSeparatedListUntil(Token::Kind rightToken,
164 const std::function<ParseResult()> &parseElement,
165 bool allowEmptyList = true);
166
167 /// Parse a comma separated list of elements that must have at least one entry
168 /// in it.
169 ParseResult
170 parseCommaSeparatedList(const std::function<ParseResult()> &parseElement);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700171
Chris Lattnerf7e22732018-06-22 22:03:48 -0700172 // We have two forms of parsing methods - those that return a non-null
173 // pointer on success, and those that return a ParseResult to indicate whether
174 // they returned a failure. The second class fills in by-reference arguments
175 // as the results of their action.
176
Chris Lattnere79379a2018-06-22 10:39:19 -0700177 // Type parsing.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700178 VectorType *parseVectorType();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700179 ParseResult parseDimensionListRanked(SmallVectorImpl<int> &dimensions);
Chris Lattnerf7e22732018-06-22 22:03:48 -0700180 Type *parseTensorType();
181 Type *parseMemRefType();
182 Type *parseFunctionType();
183 Type *parseType();
Chris Lattner1604e472018-07-23 08:42:19 -0700184 ParseResult parseTypeListNoParens(SmallVectorImpl<Type *> &elements);
James Molloy0ff71542018-07-23 16:56:32 -0700185 ParseResult parseTypeList(SmallVectorImpl<Type *> &elements);
Chris Lattnere79379a2018-06-22 10:39:19 -0700186
Chris Lattner7121b802018-07-04 20:45:39 -0700187 // Attribute parsing.
Chris Lattner1aa46322018-08-21 17:55:22 -0700188 Function *resolveFunctionReference(StringRef nameStr, SMLoc nameLoc,
189 FunctionType *type);
Chris Lattner7121b802018-07-04 20:45:39 -0700190 Attribute *parseAttribute();
191 ParseResult parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes);
192
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700193 // Polyhedral structures.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700194 AffineMap *parseAffineMapInline();
MLIR Team718c82f2018-07-16 09:45:22 -0700195 AffineMap *parseAffineMapReference();
Uday Bondhugulabc535622018-08-07 14:24:38 -0700196 IntegerSet *parseIntegerSetInline();
197 IntegerSet *parseIntegerSetReference();
MLIR Teamf85a6262018-06-27 11:03:08 -0700198
Chris Lattner48af7d12018-07-09 19:05:38 -0700199private:
200 // The Parser is subclassed and reinstantiated. Do not add additional
201 // non-trivial state here, add it to the ParserState class.
202 ParserState &state;
Chris Lattnere79379a2018-06-22 10:39:19 -0700203};
204} // end anonymous namespace
205
206//===----------------------------------------------------------------------===//
207// Helper methods.
208//===----------------------------------------------------------------------===//
209
Chris Lattner1628fa02018-08-23 14:32:25 -0700210/// Encode the specified source location information into an attribute for
211/// attachment to the IR.
212Attribute *Parser::getEncodedSourceLocation(llvm::SMLoc loc) {
213 // TODO(clattner): Switch to an more structured form that includes
214 // file/line/column instead of just byte offset in the file. This will
215 // eliminate this block of low level code poking at the SourceMgr directly.
216 auto &sourceMgr = getSourceMgr();
217 auto fileID = sourceMgr.FindBufferContainingLoc(loc);
218
219 auto *srcBuffer = sourceMgr.getMemoryBuffer(fileID);
220 unsigned locationEncoding = loc.getPointer() - srcBuffer->getBufferStart();
221 return builder.getIntegerAttr(locationEncoding);
222}
223
Chris Lattner4c95a502018-06-23 16:03:42 -0700224ParseResult Parser::emitError(SMLoc loc, const Twine &message) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700225 // If we hit a parse error in response to a lexer error, then the lexer
Jacques Pienaar9c411be2018-06-24 19:17:35 -0700226 // already reported the error.
Chris Lattner48af7d12018-07-09 19:05:38 -0700227 if (getToken().is(Token::error))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700228 return ParseFailure;
229
Chris Lattner48af7d12018-07-09 19:05:38 -0700230 auto &sourceMgr = state.lex.getSourceMgr();
231 state.errorReporter(sourceMgr.GetMessage(loc, SourceMgr::DK_Error, message));
Chris Lattnere79379a2018-06-22 10:39:19 -0700232 return ParseFailure;
233}
234
Chris Lattnerf7702a62018-07-23 17:30:01 -0700235/// Consume the specified token if present and return success. On failure,
236/// output a diagnostic and return failure.
237ParseResult Parser::parseToken(Token::Kind expectedToken,
238 const Twine &message) {
239 if (consumeIf(expectedToken))
240 return ParseSuccess;
241 return emitError(message);
242}
243
Chris Lattner40746442018-07-21 14:32:09 -0700244/// Parse a comma separated list of elements that must have at least one entry
245/// in it.
246ParseResult Parser::parseCommaSeparatedList(
247 const std::function<ParseResult()> &parseElement) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700248 // Non-empty case starts with an element.
249 if (parseElement())
250 return ParseFailure;
251
252 // Otherwise we have a list of comma separated elements.
253 while (consumeIf(Token::comma)) {
254 if (parseElement())
255 return ParseFailure;
256 }
Chris Lattner40746442018-07-21 14:32:09 -0700257 return ParseSuccess;
258}
259
260/// Parse a comma-separated list of elements, terminated with an arbitrary
261/// token. This allows empty lists if allowEmptyList is true.
262///
263/// abstract-list ::= rightToken // if allowEmptyList == true
264/// abstract-list ::= element (',' element)* rightToken
265///
266ParseResult Parser::parseCommaSeparatedListUntil(
267 Token::Kind rightToken, const std::function<ParseResult()> &parseElement,
268 bool allowEmptyList) {
269 // Handle the empty case.
270 if (getToken().is(rightToken)) {
271 if (!allowEmptyList)
272 return emitError("expected list element");
273 consumeToken(rightToken);
274 return ParseSuccess;
275 }
276
Chris Lattnerf7702a62018-07-23 17:30:01 -0700277 if (parseCommaSeparatedList(parseElement) ||
278 parseToken(rightToken, "expected ',' or '" +
279 Token::getTokenSpelling(rightToken) + "'"))
Chris Lattner40746442018-07-21 14:32:09 -0700280 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700281
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700282 return ParseSuccess;
283}
Chris Lattnere79379a2018-06-22 10:39:19 -0700284
285//===----------------------------------------------------------------------===//
286// Type Parsing
287//===----------------------------------------------------------------------===//
288
Chris Lattnerc3251192018-07-27 13:09:58 -0700289/// Parse an arbitrary type.
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700290///
Chris Lattnerc3251192018-07-27 13:09:58 -0700291/// type ::= integer-type
292/// | float-type
293/// | other-type
294/// | vector-type
295/// | tensor-type
296/// | memref-type
297/// | function-type
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700298///
Chris Lattnerc3251192018-07-27 13:09:58 -0700299/// float-type ::= `f16` | `bf16` | `f32` | `f64`
300/// other-type ::= `affineint` | `tf_control`
301///
302Type *Parser::parseType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700303 switch (getToken().getKind()) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700304 default:
305 return (emitError("expected type"), nullptr);
Chris Lattnerc3251192018-07-27 13:09:58 -0700306 case Token::kw_memref:
307 return parseMemRefType();
308 case Token::kw_tensor:
309 return parseTensorType();
310 case Token::kw_vector:
311 return parseVectorType();
312 case Token::l_paren:
313 return parseFunctionType();
314 // integer-type
315 case Token::inttype: {
316 auto width = getToken().getIntTypeBitwidth();
317 if (!width.hasValue())
318 return (emitError("invalid integer width"), nullptr);
319 consumeToken(Token::inttype);
320 return builder.getIntegerType(width.getValue());
321 }
322
323 // float-type
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700324 case Token::kw_bf16:
325 consumeToken(Token::kw_bf16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700326 return builder.getBF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700327 case Token::kw_f16:
328 consumeToken(Token::kw_f16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700329 return builder.getF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700330 case Token::kw_f32:
331 consumeToken(Token::kw_f32);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700332 return builder.getF32Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700333 case Token::kw_f64:
334 consumeToken(Token::kw_f64);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700335 return builder.getF64Type();
Chris Lattnerc3251192018-07-27 13:09:58 -0700336
337 // other-type
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700338 case Token::kw_affineint:
339 consumeToken(Token::kw_affineint);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700340 return builder.getAffineIntType();
Jacques Pienaarc0d69302018-07-27 11:07:12 -0700341 case Token::kw_tf_control:
342 consumeToken(Token::kw_tf_control);
343 return builder.getTFControlType();
James Molloy72b0cbe2018-08-01 12:55:27 -0700344 case Token::kw_tf_string:
345 consumeToken(Token::kw_tf_string);
346 return builder.getTFStringType();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700347 }
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700348}
349
350/// Parse a vector type.
351///
352/// vector-type ::= `vector` `<` const-dimension-list primitive-type `>`
353/// const-dimension-list ::= (integer-literal `x`)+
354///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700355VectorType *Parser::parseVectorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700356 consumeToken(Token::kw_vector);
357
Chris Lattnerf7702a62018-07-23 17:30:01 -0700358 if (parseToken(Token::less, "expected '<' in vector type"))
359 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700360
Chris Lattner48af7d12018-07-09 19:05:38 -0700361 if (getToken().isNot(Token::integer))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700362 return (emitError("expected dimension size in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700363
364 SmallVector<unsigned, 4> dimensions;
Chris Lattner48af7d12018-07-09 19:05:38 -0700365 while (getToken().is(Token::integer)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700366 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700367 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700368 if (!dimension.hasValue())
Chris Lattnerf7e22732018-06-22 22:03:48 -0700369 return (emitError("invalid dimension in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700370 dimensions.push_back(dimension.getValue());
371
372 consumeToken(Token::integer);
373
374 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700375 if (getToken().isNot(Token::bare_identifier) ||
376 getTokenSpelling()[0] != 'x')
Chris Lattnerf7e22732018-06-22 22:03:48 -0700377 return (emitError("expected 'x' in vector dimension list"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700378
379 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700380 if (getTokenSpelling().size() != 1)
381 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700382
383 // Consume the 'x'.
384 consumeToken(Token::bare_identifier);
385 }
386
387 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700388 auto typeLoc = getToken().getLoc();
389 auto *elementType = parseType();
390 if (!elementType || parseToken(Token::greater, "expected '>' in vector type"))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700391 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700392
Chris Lattnerc3251192018-07-27 13:09:58 -0700393 if (!isa<FloatType>(elementType) && !isa<IntegerType>(elementType))
394 return (emitError(typeLoc, "invalid vector element type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700395
Chris Lattnerf7e22732018-06-22 22:03:48 -0700396 return VectorType::get(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700397}
398
399/// Parse a dimension list of a tensor or memref type. This populates the
400/// dimension list, returning -1 for the '?' dimensions.
401///
402/// dimension-list-ranked ::= (dimension `x`)*
403/// dimension ::= `?` | integer-literal
404///
405ParseResult Parser::parseDimensionListRanked(SmallVectorImpl<int> &dimensions) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700406 while (getToken().isAny(Token::integer, Token::question)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700407 if (consumeIf(Token::question)) {
408 dimensions.push_back(-1);
409 } else {
410 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700411 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700412 if (!dimension.hasValue() || (int)dimension.getValue() < 0)
413 return emitError("invalid dimension");
414 dimensions.push_back((int)dimension.getValue());
415 consumeToken(Token::integer);
416 }
417
418 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700419 if (getToken().isNot(Token::bare_identifier) ||
420 getTokenSpelling()[0] != 'x')
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700421 return emitError("expected 'x' in dimension list");
422
423 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700424 if (getTokenSpelling().size() != 1)
425 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700426
427 // Consume the 'x'.
428 consumeToken(Token::bare_identifier);
429 }
430
431 return ParseSuccess;
432}
433
434/// Parse a tensor type.
435///
436/// tensor-type ::= `tensor` `<` dimension-list element-type `>`
437/// dimension-list ::= dimension-list-ranked | `??`
438///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700439Type *Parser::parseTensorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700440 consumeToken(Token::kw_tensor);
441
Chris Lattnerf7702a62018-07-23 17:30:01 -0700442 if (parseToken(Token::less, "expected '<' in tensor type"))
443 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700444
445 bool isUnranked;
446 SmallVector<int, 4> dimensions;
447
448 if (consumeIf(Token::questionquestion)) {
449 isUnranked = true;
450 } else {
451 isUnranked = false;
452 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700453 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700454 }
455
456 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700457 auto typeLoc = getToken().getLoc();
458 auto *elementType = parseType();
459 if (!elementType || parseToken(Token::greater, "expected '>' in tensor type"))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700460 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700461
Chris Lattnerc3251192018-07-27 13:09:58 -0700462 if (!isa<IntegerType>(elementType) && !isa<FloatType>(elementType) &&
463 !isa<VectorType>(elementType))
464 return (emitError(typeLoc, "invalid tensor element type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700465
MLIR Team355ec862018-06-23 18:09:09 -0700466 if (isUnranked)
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700467 return builder.getTensorType(elementType);
468 return builder.getTensorType(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700469}
470
471/// Parse a memref type.
472///
473/// memref-type ::= `memref` `<` dimension-list-ranked element-type
474/// (`,` semi-affine-map-composition)? (`,` memory-space)? `>`
475///
476/// semi-affine-map-composition ::= (semi-affine-map `,` )* semi-affine-map
477/// memory-space ::= integer-literal /* | TODO: address-space-id */
478///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700479Type *Parser::parseMemRefType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700480 consumeToken(Token::kw_memref);
481
Chris Lattnerf7702a62018-07-23 17:30:01 -0700482 if (parseToken(Token::less, "expected '<' in memref type"))
483 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700484
485 SmallVector<int, 4> dimensions;
486 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700487 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700488
489 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700490 auto typeLoc = getToken().getLoc();
491 auto *elementType = parseType();
Chris Lattnerf7e22732018-06-22 22:03:48 -0700492 if (!elementType)
493 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700494
Chris Lattnerc3251192018-07-27 13:09:58 -0700495 if (!isa<IntegerType>(elementType) && !isa<FloatType>(elementType) &&
496 !isa<VectorType>(elementType))
497 return (emitError(typeLoc, "invalid memref element type"), nullptr);
498
MLIR Team718c82f2018-07-16 09:45:22 -0700499 // Parse semi-affine-map-composition.
James Molloy0ff71542018-07-23 16:56:32 -0700500 SmallVector<AffineMap *, 2> affineMapComposition;
Chris Lattner413db6a2018-07-25 12:55:50 -0700501 unsigned memorySpace = 0;
MLIR Team718c82f2018-07-16 09:45:22 -0700502 bool parsedMemorySpace = false;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700503
MLIR Team718c82f2018-07-16 09:45:22 -0700504 auto parseElt = [&]() -> ParseResult {
505 if (getToken().is(Token::integer)) {
506 // Parse memory space.
507 if (parsedMemorySpace)
508 return emitError("multiple memory spaces specified in memref type");
509 auto v = getToken().getUnsignedIntegerValue();
510 if (!v.hasValue())
511 return emitError("invalid memory space in memref type");
512 memorySpace = v.getValue();
513 consumeToken(Token::integer);
514 parsedMemorySpace = true;
515 } else {
516 // Parse affine map.
517 if (parsedMemorySpace)
518 return emitError("affine map after memory space in memref type");
James Molloy0ff71542018-07-23 16:56:32 -0700519 auto *affineMap = parseAffineMapReference();
MLIR Team718c82f2018-07-16 09:45:22 -0700520 if (affineMap == nullptr)
521 return ParseFailure;
522 affineMapComposition.push_back(affineMap);
523 }
524 return ParseSuccess;
525 };
526
Chris Lattner413db6a2018-07-25 12:55:50 -0700527 // Parse a list of mappings and address space if present.
528 if (consumeIf(Token::comma)) {
529 // Parse comma separated list of affine maps, followed by memory space.
530 if (parseCommaSeparatedListUntil(Token::greater, parseElt,
531 /*allowEmptyList=*/false)) {
532 return nullptr;
533 }
534 } else {
535 if (parseToken(Token::greater, "expected ',' or '>' in memref type"))
536 return nullptr;
MLIR Team718c82f2018-07-16 09:45:22 -0700537 }
MLIR Team718c82f2018-07-16 09:45:22 -0700538
539 return MemRefType::get(dimensions, elementType, affineMapComposition,
540 memorySpace);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700541}
542
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700543/// Parse a function type.
544///
545/// function-type ::= type-list-parens `->` type-list
546///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700547Type *Parser::parseFunctionType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700548 assert(getToken().is(Token::l_paren));
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700549
Chris Lattnerf7702a62018-07-23 17:30:01 -0700550 SmallVector<Type *, 4> arguments, results;
551 if (parseTypeList(arguments) ||
552 parseToken(Token::arrow, "expected '->' in function type") ||
553 parseTypeList(results))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700554 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700555
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700556 return builder.getFunctionType(arguments, results);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700557}
558
Chris Lattner1604e472018-07-23 08:42:19 -0700559/// Parse a list of types without an enclosing parenthesis. The list must have
560/// at least one member.
561///
562/// type-list-no-parens ::= type (`,` type)*
563///
564ParseResult Parser::parseTypeListNoParens(SmallVectorImpl<Type *> &elements) {
565 auto parseElt = [&]() -> ParseResult {
566 auto elt = parseType();
567 elements.push_back(elt);
568 return elt ? ParseSuccess : ParseFailure;
569 };
570
571 return parseCommaSeparatedList(parseElt);
572}
573
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700574/// Parse a "type list", which is a singular type, or a parenthesized list of
575/// types.
576///
577/// type-list ::= type-list-parens | type
578/// type-list-parens ::= `(` `)`
Chris Lattner1604e472018-07-23 08:42:19 -0700579/// | `(` type-list-no-parens `)`
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700580///
James Molloy0ff71542018-07-23 16:56:32 -0700581ParseResult Parser::parseTypeList(SmallVectorImpl<Type *> &elements) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700582 auto parseElt = [&]() -> ParseResult {
583 auto elt = parseType();
584 elements.push_back(elt);
585 return elt ? ParseSuccess : ParseFailure;
586 };
587
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700588 // If there is no parens, then it must be a singular type.
589 if (!consumeIf(Token::l_paren))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700590 return parseElt();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700591
Chris Lattner40746442018-07-21 14:32:09 -0700592 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700593 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700594
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700595 return ParseSuccess;
596}
597
Chris Lattner4c95a502018-06-23 16:03:42 -0700598//===----------------------------------------------------------------------===//
Chris Lattner7121b802018-07-04 20:45:39 -0700599// Attribute parsing.
600//===----------------------------------------------------------------------===//
601
Chris Lattner1aa46322018-08-21 17:55:22 -0700602/// Given a parsed reference to a function name like @foo and a type that it
603/// corresponds to, resolve it to a concrete function object (possibly
604/// synthesizing a forward reference) or emit an error and return null on
605/// failure.
606Function *Parser::resolveFunctionReference(StringRef nameStr, SMLoc nameLoc,
607 FunctionType *type) {
608 Identifier name = builder.getIdentifier(nameStr.drop_front());
609
610 // See if the function has already been defined in the module.
611 Function *function = getModule()->getNamedFunction(name);
612
613 // If not, get or create a forward reference to one.
614 if (!function) {
615 auto &entry = state.functionForwardRefs[name];
616 if (!entry.first) {
617 entry.first = new ExtFunction(name, type);
618 entry.second = nameLoc;
619 }
620 function = entry.first;
621 }
622
623 if (function->getType() != type)
624 return (emitError(nameLoc, "reference to function with mismatched type"),
625 nullptr);
626 return function;
627}
628
Chris Lattner7121b802018-07-04 20:45:39 -0700629/// Attribute parsing.
630///
631/// attribute-value ::= bool-literal
632/// | integer-literal
633/// | float-literal
634/// | string-literal
James Molloyf0d2f442018-08-03 01:54:46 -0700635/// | type
Chris Lattner7121b802018-07-04 20:45:39 -0700636/// | `[` (attribute-value (`,` attribute-value)*)? `]`
Chris Lattner4613d9e2018-08-19 21:17:22 -0700637/// | function-id `:` function-type
Chris Lattner7121b802018-07-04 20:45:39 -0700638///
639Attribute *Parser::parseAttribute() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700640 switch (getToken().getKind()) {
Chris Lattner7121b802018-07-04 20:45:39 -0700641 case Token::kw_true:
642 consumeToken(Token::kw_true);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700643 return builder.getBoolAttr(true);
Chris Lattner7121b802018-07-04 20:45:39 -0700644 case Token::kw_false:
645 consumeToken(Token::kw_false);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700646 return builder.getBoolAttr(false);
Chris Lattner7121b802018-07-04 20:45:39 -0700647
Jacques Pienaar84491092018-07-31 17:15:15 -0700648 case Token::floatliteral: {
649 auto val = getToken().getFloatingPointValue();
650 if (!val.hasValue())
651 return (emitError("floating point value too large for attribute"),
652 nullptr);
653 consumeToken(Token::floatliteral);
654 return builder.getFloatAttr(val.getValue());
655 }
Chris Lattner7121b802018-07-04 20:45:39 -0700656 case Token::integer: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700657 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700658 if (!val.hasValue() || (int64_t)val.getValue() < 0)
659 return (emitError("integer too large for attribute"), nullptr);
660 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700661 return builder.getIntegerAttr((int64_t)val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700662 }
663
664 case Token::minus: {
665 consumeToken(Token::minus);
Chris Lattner48af7d12018-07-09 19:05:38 -0700666 if (getToken().is(Token::integer)) {
667 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700668 if (!val.hasValue() || (int64_t)-val.getValue() >= 0)
669 return (emitError("integer too large for attribute"), nullptr);
670 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700671 return builder.getIntegerAttr((int64_t)-val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700672 }
Jacques Pienaar84491092018-07-31 17:15:15 -0700673 if (getToken().is(Token::floatliteral)) {
674 auto val = getToken().getFloatingPointValue();
675 if (!val.hasValue())
676 return (emitError("floating point value too large for attribute"),
677 nullptr);
678 consumeToken(Token::floatliteral);
679 return builder.getFloatAttr(-val.getValue());
680 }
Chris Lattner7121b802018-07-04 20:45:39 -0700681
682 return (emitError("expected constant integer or floating point value"),
683 nullptr);
684 }
685
686 case Token::string: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700687 auto val = getToken().getStringValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700688 consumeToken(Token::string);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700689 return builder.getStringAttr(val);
Chris Lattner7121b802018-07-04 20:45:39 -0700690 }
691
Chris Lattner85ee1512018-07-25 11:15:20 -0700692 case Token::l_square: {
693 consumeToken(Token::l_square);
James Molloy0ff71542018-07-23 16:56:32 -0700694 SmallVector<Attribute *, 4> elements;
Chris Lattner7121b802018-07-04 20:45:39 -0700695
696 auto parseElt = [&]() -> ParseResult {
697 elements.push_back(parseAttribute());
698 return elements.back() ? ParseSuccess : ParseFailure;
699 };
700
Chris Lattner85ee1512018-07-25 11:15:20 -0700701 if (parseCommaSeparatedListUntil(Token::r_square, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700702 return nullptr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700703 return builder.getArrayAttr(elements);
Chris Lattner7121b802018-07-04 20:45:39 -0700704 }
James Molloyf0d2f442018-08-03 01:54:46 -0700705 case Token::hash_identifier:
706 case Token::l_paren: {
MLIR Teamb61885d2018-07-18 16:29:21 -0700707 // Try to parse affine map reference.
James Molloyf0d2f442018-08-03 01:54:46 -0700708 if (auto *affineMap = parseAffineMapReference())
MLIR Teamb61885d2018-07-18 16:29:21 -0700709 return builder.getAffineMapAttr(affineMap);
Chris Lattner7121b802018-07-04 20:45:39 -0700710 return (emitError("expected constant attribute value"), nullptr);
711 }
Chris Lattner4613d9e2018-08-19 21:17:22 -0700712
713 case Token::at_identifier: {
714 auto nameLoc = getToken().getLoc();
Chris Lattner1aa46322018-08-21 17:55:22 -0700715 auto nameStr = getTokenSpelling();
Chris Lattner4613d9e2018-08-19 21:17:22 -0700716 consumeToken(Token::at_identifier);
717
718 if (parseToken(Token::colon, "expected ':' and function type"))
719 return nullptr;
720 auto typeLoc = getToken().getLoc();
721 Type *type = parseType();
722 if (!type)
723 return nullptr;
Chris Lattner1aa46322018-08-21 17:55:22 -0700724 auto *fnType = dyn_cast<FunctionType>(type);
Chris Lattner4613d9e2018-08-19 21:17:22 -0700725 if (!fnType)
726 return (emitError(typeLoc, "expected function type"), nullptr);
727
Chris Lattner1aa46322018-08-21 17:55:22 -0700728 auto *function = resolveFunctionReference(nameStr, nameLoc, fnType);
729 return function ? builder.getFunctionAttr(function) : nullptr;
Chris Lattner4613d9e2018-08-19 21:17:22 -0700730 }
731
James Molloyf0d2f442018-08-03 01:54:46 -0700732 default: {
733 if (Type *type = parseType())
734 return builder.getTypeAttr(type);
735 return nullptr;
736 }
737 }
Chris Lattner7121b802018-07-04 20:45:39 -0700738}
739
Chris Lattner7121b802018-07-04 20:45:39 -0700740/// Attribute dictionary.
741///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700742/// attribute-dict ::= `{` `}`
743/// | `{` attribute-entry (`,` attribute-entry)* `}`
744/// attribute-entry ::= bare-id `:` attribute-value
Chris Lattner7121b802018-07-04 20:45:39 -0700745///
James Molloy0ff71542018-07-23 16:56:32 -0700746ParseResult
747Parser::parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes) {
Chris Lattner7121b802018-07-04 20:45:39 -0700748 consumeToken(Token::l_brace);
749
750 auto parseElt = [&]() -> ParseResult {
751 // We allow keywords as attribute names.
Chris Lattner48af7d12018-07-09 19:05:38 -0700752 if (getToken().isNot(Token::bare_identifier, Token::inttype) &&
753 !getToken().isKeyword())
Chris Lattner7121b802018-07-04 20:45:39 -0700754 return emitError("expected attribute name");
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700755 auto nameId = builder.getIdentifier(getTokenSpelling());
Chris Lattner7121b802018-07-04 20:45:39 -0700756 consumeToken();
757
Chris Lattnerf7702a62018-07-23 17:30:01 -0700758 if (parseToken(Token::colon, "expected ':' in attribute list"))
759 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700760
761 auto attr = parseAttribute();
James Molloy0ff71542018-07-23 16:56:32 -0700762 if (!attr)
763 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700764
765 attributes.push_back({nameId, attr});
766 return ParseSuccess;
767 };
768
Chris Lattner40746442018-07-21 14:32:09 -0700769 if (parseCommaSeparatedListUntil(Token::r_brace, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700770 return ParseFailure;
771
772 return ParseSuccess;
773}
774
775//===----------------------------------------------------------------------===//
MLIR Teamf85a6262018-06-27 11:03:08 -0700776// Polyhedral structures.
777//===----------------------------------------------------------------------===//
778
Chris Lattner2e595eb2018-07-10 10:08:27 -0700779/// Lower precedence ops (all at the same precedence level). LNoOp is false in
780/// the boolean sense.
781enum AffineLowPrecOp {
782 /// Null value.
783 LNoOp,
784 Add,
785 Sub
786};
MLIR Teamf85a6262018-06-27 11:03:08 -0700787
Chris Lattner2e595eb2018-07-10 10:08:27 -0700788/// Higher precedence ops - all at the same precedence level. HNoOp is false in
789/// the boolean sense.
790enum AffineHighPrecOp {
791 /// Null value.
792 HNoOp,
793 Mul,
794 FloorDiv,
795 CeilDiv,
796 Mod
797};
Chris Lattner7121b802018-07-04 20:45:39 -0700798
Chris Lattner2e595eb2018-07-10 10:08:27 -0700799namespace {
Uday Bondhugulabc535622018-08-07 14:24:38 -0700800/// This is a specialized parser for affine structures (affine maps, affine
801/// expressions, and integer sets), maintaining the state transient to their
802/// bodies.
803class AffineParser : public Parser {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700804public:
Uday Bondhugulabc535622018-08-07 14:24:38 -0700805 explicit AffineParser(ParserState &state) : Parser(state) {}
Chris Lattner7121b802018-07-04 20:45:39 -0700806
Chris Lattner2e595eb2018-07-10 10:08:27 -0700807 AffineMap *parseAffineMapInline();
Uday Bondhugulabc535622018-08-07 14:24:38 -0700808 IntegerSet *parseIntegerSetInline();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700809
Chris Lattner2e595eb2018-07-10 10:08:27 -0700810private:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700811 // Binary affine op parsing.
812 AffineLowPrecOp consumeIfLowPrecOp();
813 AffineHighPrecOp consumeIfHighPrecOp();
MLIR Teamf85a6262018-06-27 11:03:08 -0700814
Chris Lattner2e595eb2018-07-10 10:08:27 -0700815 // Identifier lists for polyhedral structures.
Chris Lattner413db6a2018-07-25 12:55:50 -0700816 ParseResult parseDimIdList(unsigned &numDims);
817 ParseResult parseSymbolIdList(unsigned &numSymbols);
818 ParseResult parseIdentifierDefinition(AffineExpr *idExpr);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700819
820 AffineExpr *parseAffineExpr();
821 AffineExpr *parseParentheticalExpr();
822 AffineExpr *parseNegateExpression(AffineExpr *lhs);
823 AffineExpr *parseIntegerExpr();
824 AffineExpr *parseBareIdExpr();
825
826 AffineExpr *getBinaryAffineOpExpr(AffineHighPrecOp op, AffineExpr *lhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700827 AffineExpr *rhs, SMLoc opLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700828 AffineExpr *getBinaryAffineOpExpr(AffineLowPrecOp op, AffineExpr *lhs,
829 AffineExpr *rhs);
830 AffineExpr *parseAffineOperandExpr(AffineExpr *lhs);
831 AffineExpr *parseAffineLowPrecOpExpr(AffineExpr *llhs,
832 AffineLowPrecOp llhsOp);
833 AffineExpr *parseAffineHighPrecOpExpr(AffineExpr *llhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700834 AffineHighPrecOp llhsOp,
835 SMLoc llhsOpLoc);
Uday Bondhugulabc535622018-08-07 14:24:38 -0700836 AffineExpr *parseAffineConstraint(bool *isEq);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700837
838private:
Chris Lattner413db6a2018-07-25 12:55:50 -0700839 SmallVector<std::pair<StringRef, AffineExpr *>, 4> dimsAndSymbols;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700840};
841} // end anonymous namespace
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700842
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700843/// Create an affine binary high precedence op expression (mul's, div's, mod).
844/// opLoc is the location of the op token to be used to report errors
845/// for non-conforming expressions.
Uday Bondhugulabc535622018-08-07 14:24:38 -0700846AffineExpr *AffineParser::getBinaryAffineOpExpr(AffineHighPrecOp op,
847 AffineExpr *lhs,
848 AffineExpr *rhs, SMLoc opLoc) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700849 // TODO: make the error location info accurate.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700850 switch (op) {
851 case Mul:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700852 if (!lhs->isSymbolicOrConstant() && !rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700853 emitError(opLoc, "non-affine expression: at least one of the multiply "
854 "operands has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700855 return nullptr;
856 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700857 return builder.getMulExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700858 case FloorDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700859 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700860 emitError(opLoc, "non-affine expression: right operand of floordiv "
861 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700862 return nullptr;
863 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700864 return builder.getFloorDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700865 case CeilDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700866 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700867 emitError(opLoc, "non-affine expression: right operand of ceildiv "
868 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700869 return nullptr;
870 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700871 return builder.getCeilDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700872 case Mod:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700873 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700874 emitError(opLoc, "non-affine expression: right operand of mod "
875 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700876 return nullptr;
877 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700878 return builder.getModExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700879 case HNoOp:
880 llvm_unreachable("can't create affine expression for null high prec op");
881 return nullptr;
882 }
883}
884
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700885/// Create an affine binary low precedence op expression (add, sub).
Uday Bondhugulabc535622018-08-07 14:24:38 -0700886AffineExpr *AffineParser::getBinaryAffineOpExpr(AffineLowPrecOp op,
887 AffineExpr *lhs,
888 AffineExpr *rhs) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700889 switch (op) {
890 case AffineLowPrecOp::Add:
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700891 return builder.getAddExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700892 case AffineLowPrecOp::Sub:
Uday Bondhugulac1faf662018-07-19 14:08:50 -0700893 return builder.getAddExpr(
894 lhs, builder.getMulExpr(rhs, builder.getConstantExpr(-1)));
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700895 case AffineLowPrecOp::LNoOp:
896 llvm_unreachable("can't create affine expression for null low prec op");
897 return nullptr;
898 }
899}
900
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700901/// Consume this token if it is a lower precedence affine op (there are only two
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700902/// precedence levels).
Uday Bondhugulabc535622018-08-07 14:24:38 -0700903AffineLowPrecOp AffineParser::consumeIfLowPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700904 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700905 case Token::plus:
906 consumeToken(Token::plus);
907 return AffineLowPrecOp::Add;
908 case Token::minus:
909 consumeToken(Token::minus);
910 return AffineLowPrecOp::Sub;
911 default:
912 return AffineLowPrecOp::LNoOp;
913 }
914}
915
916/// Consume this token if it is a higher precedence affine op (there are only
917/// two precedence levels)
Uday Bondhugulabc535622018-08-07 14:24:38 -0700918AffineHighPrecOp AffineParser::consumeIfHighPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700919 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700920 case Token::star:
921 consumeToken(Token::star);
922 return Mul;
923 case Token::kw_floordiv:
924 consumeToken(Token::kw_floordiv);
925 return FloorDiv;
926 case Token::kw_ceildiv:
927 consumeToken(Token::kw_ceildiv);
928 return CeilDiv;
929 case Token::kw_mod:
930 consumeToken(Token::kw_mod);
931 return Mod;
932 default:
933 return HNoOp;
934 }
935}
936
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700937/// Parse a high precedence op expression list: mul, div, and mod are high
938/// precedence binary ops, i.e., parse a
939/// expr_1 op_1 expr_2 op_2 ... expr_n
940/// where op_1, op_2 are all a AffineHighPrecOp (mul, div, mod).
941/// All affine binary ops are left associative.
942/// Given llhs, returns (llhs llhsOp lhs) op rhs, or (lhs op rhs) if llhs is
943/// null. If no rhs can be found, returns (llhs llhsOp lhs) or lhs if llhs is
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700944/// null. llhsOpLoc is the location of the llhsOp token that will be used to
945/// report an error for non-conforming expressions.
Uday Bondhugulabc535622018-08-07 14:24:38 -0700946AffineExpr *AffineParser::parseAffineHighPrecOpExpr(AffineExpr *llhs,
947 AffineHighPrecOp llhsOp,
948 SMLoc llhsOpLoc) {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700949 AffineExpr *lhs = parseAffineOperandExpr(llhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700950 if (!lhs)
951 return nullptr;
952
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700953 // Found an LHS. Parse the remaining expression.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700954 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -0700955 if (AffineHighPrecOp op = consumeIfHighPrecOp()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700956 if (llhs) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700957 AffineExpr *expr = getBinaryAffineOpExpr(llhsOp, llhs, lhs, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700958 if (!expr)
959 return nullptr;
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700960 return parseAffineHighPrecOpExpr(expr, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700961 }
962 // No LLHS, get RHS
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700963 return parseAffineHighPrecOpExpr(lhs, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700964 }
965
966 // This is the last operand in this expression.
967 if (llhs)
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700968 return getBinaryAffineOpExpr(llhsOp, llhs, lhs, llhsOpLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700969
970 // No llhs, 'lhs' itself is the expression.
971 return lhs;
972}
973
974/// Parse an affine expression inside parentheses.
975///
976/// affine-expr ::= `(` affine-expr `)`
Uday Bondhugulabc535622018-08-07 14:24:38 -0700977AffineExpr *AffineParser::parseParentheticalExpr() {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700978 if (parseToken(Token::l_paren, "expected '('"))
979 return nullptr;
Chris Lattner48af7d12018-07-09 19:05:38 -0700980 if (getToken().is(Token::r_paren))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700981 return (emitError("no expression inside parentheses"), nullptr);
Chris Lattnerf7702a62018-07-23 17:30:01 -0700982
Chris Lattner2e595eb2018-07-10 10:08:27 -0700983 auto *expr = parseAffineExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700984 if (!expr)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700985 return nullptr;
Chris Lattnerf7702a62018-07-23 17:30:01 -0700986 if (parseToken(Token::r_paren, "expected ')'"))
987 return nullptr;
988
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700989 return expr;
990}
991
992/// Parse the negation expression.
993///
994/// affine-expr ::= `-` affine-expr
Uday Bondhugulabc535622018-08-07 14:24:38 -0700995AffineExpr *AffineParser::parseNegateExpression(AffineExpr *lhs) {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700996 if (parseToken(Token::minus, "expected '-'"))
997 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700998
Chris Lattner2e595eb2018-07-10 10:08:27 -0700999 AffineExpr *operand = parseAffineOperandExpr(lhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001000 // Since negation has the highest precedence of all ops (including high
1001 // precedence ops) but lower than parentheses, we are only going to use
1002 // parseAffineOperandExpr instead of parseAffineExpr here.
1003 if (!operand)
1004 // Extra error message although parseAffineOperandExpr would have
1005 // complained. Leads to a better diagnostic.
1006 return (emitError("missing operand of negation"), nullptr);
Chris Lattner1ac20cb2018-07-10 10:59:53 -07001007 auto *minusOne = builder.getConstantExpr(-1);
1008 return builder.getMulExpr(minusOne, operand);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001009}
1010
1011/// Parse a bare id that may appear in an affine expression.
1012///
1013/// affine-expr ::= bare-id
Uday Bondhugulabc535622018-08-07 14:24:38 -07001014AffineExpr *AffineParser::parseBareIdExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -07001015 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001016 return (emitError("expected bare identifier"), nullptr);
1017
Chris Lattner48af7d12018-07-09 19:05:38 -07001018 StringRef sRef = getTokenSpelling();
Chris Lattner413db6a2018-07-25 12:55:50 -07001019 for (auto entry : dimsAndSymbols) {
Chris Lattnera8e47672018-07-25 14:08:16 -07001020 if (entry.first == sRef) {
1021 consumeToken(Token::bare_identifier);
1022 return entry.second;
1023 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001024 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001025
1026 return (emitError("use of undeclared identifier"), nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001027}
1028
1029/// Parse a positive integral constant appearing in an affine expression.
1030///
1031/// affine-expr ::= integer-literal
Uday Bondhugulabc535622018-08-07 14:24:38 -07001032AffineExpr *AffineParser::parseIntegerExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -07001033 auto val = getToken().getUInt64IntegerValue();
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07001034 if (!val.hasValue() || (int64_t)val.getValue() < 0)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001035 return (emitError("constant too large for affineint"), nullptr);
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07001036
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001037 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -07001038 return builder.getConstantExpr((int64_t)val.getValue());
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001039}
1040
1041/// Parses an expression that can be a valid operand of an affine expression.
Uday Bondhugula76345202018-07-09 13:47:52 -07001042/// lhs: if non-null, lhs is an affine expression that is the lhs of a binary
1043/// operator, the rhs of which is being parsed. This is used to determine
1044/// whether an error should be emitted for a missing right operand.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001045// Eg: for an expression without parentheses (like i + j + k + l), each
1046// of the four identifiers is an operand. For i + j*k + l, j*k is not an
1047// operand expression, it's an op expression and will be parsed via
1048// parseAffineHighPrecOpExpression(). However, for i + (j*k) + -l, (j*k) and -l
1049// are valid operands that will be parsed by this function.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001050AffineExpr *AffineParser::parseAffineOperandExpr(AffineExpr *lhs) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001051 switch (getToken().getKind()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001052 case Token::bare_identifier:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001053 return parseBareIdExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001054 case Token::integer:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001055 return parseIntegerExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001056 case Token::l_paren:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001057 return parseParentheticalExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001058 case Token::minus:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001059 return parseNegateExpression(lhs);
Uday Bondhugula76345202018-07-09 13:47:52 -07001060 case Token::kw_ceildiv:
1061 case Token::kw_floordiv:
1062 case Token::kw_mod:
1063 case Token::plus:
1064 case Token::star:
1065 if (lhs)
1066 emitError("missing right operand of binary operator");
1067 else
1068 emitError("missing left operand of binary operator");
1069 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001070 default:
1071 if (lhs)
Uday Bondhugula76345202018-07-09 13:47:52 -07001072 emitError("missing right operand of binary operator");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001073 else
1074 emitError("expected affine expression");
1075 return nullptr;
1076 }
1077}
1078
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001079/// Parse affine expressions that are bare-id's, integer constants,
1080/// parenthetical affine expressions, and affine op expressions that are a
1081/// composition of those.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001082///
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001083/// All binary op's associate from left to right.
1084///
1085/// {add, sub} have lower precedence than {mul, div, and mod}.
1086///
Uday Bondhugula76345202018-07-09 13:47:52 -07001087/// Add, sub'are themselves at the same precedence level. Mul, floordiv,
1088/// ceildiv, and mod are at the same higher precedence level. Negation has
1089/// higher precedence than any binary op.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001090///
1091/// llhs: the affine expression appearing on the left of the one being parsed.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001092/// This function will return ((llhs llhsOp lhs) op rhs) if llhs is non null,
1093/// and lhs op rhs otherwise; if there is no rhs, llhs llhsOp lhs is returned if
1094/// llhs is non-null; otherwise lhs is returned. This is to deal with left
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001095/// associativity.
1096///
1097/// Eg: when the expression is e1 + e2*e3 + e4, with e1 as llhs, this function
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001098/// will return the affine expr equivalent of (e1 + (e2*e3)) + e4, where (e2*e3)
1099/// will be parsed using parseAffineHighPrecOpExpr().
Uday Bondhugulabc535622018-08-07 14:24:38 -07001100AffineExpr *AffineParser::parseAffineLowPrecOpExpr(AffineExpr *llhs,
1101 AffineLowPrecOp llhsOp) {
Uday Bondhugula76345202018-07-09 13:47:52 -07001102 AffineExpr *lhs;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001103 if (!(lhs = parseAffineOperandExpr(llhs)))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001104 return nullptr;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001105
1106 // Found an LHS. Deal with the ops.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001107 if (AffineLowPrecOp lOp = consumeIfLowPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001108 if (llhs) {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001109 AffineExpr *sum = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001110 return parseAffineLowPrecOpExpr(sum, lOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001111 }
1112 // No LLHS, get RHS and form the expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001113 return parseAffineLowPrecOpExpr(lhs, lOp);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001114 }
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001115 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07001116 if (AffineHighPrecOp hOp = consumeIfHighPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001117 // We have a higher precedence op here. Get the rhs operand for the llhs
1118 // through parseAffineHighPrecOpExpr.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001119 AffineExpr *highRes = parseAffineHighPrecOpExpr(lhs, hOp, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001120 if (!highRes)
1121 return nullptr;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001122
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001123 // If llhs is null, the product forms the first operand of the yet to be
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001124 // found expression. If non-null, the op to associate with llhs is llhsOp.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001125 AffineExpr *expr =
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001126 llhs ? getBinaryAffineOpExpr(llhsOp, llhs, highRes) : highRes;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001127
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001128 // Recurse for subsequent low prec op's after the affine high prec op
1129 // expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001130 if (AffineLowPrecOp nextOp = consumeIfLowPrecOp())
1131 return parseAffineLowPrecOpExpr(expr, nextOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001132 return expr;
1133 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001134 // Last operand in the expression list.
1135 if (llhs)
1136 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
1137 // No llhs, 'lhs' itself is the expression.
1138 return lhs;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001139}
1140
1141/// Parse an affine expression.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001142/// affine-expr ::= `(` affine-expr `)`
1143/// | `-` affine-expr
1144/// | affine-expr `+` affine-expr
1145/// | affine-expr `-` affine-expr
1146/// | affine-expr `*` affine-expr
1147/// | affine-expr `floordiv` affine-expr
1148/// | affine-expr `ceildiv` affine-expr
1149/// | affine-expr `mod` affine-expr
1150/// | bare-id
1151/// | integer-literal
1152///
1153/// Additional conditions are checked depending on the production. For eg., one
1154/// of the operands for `*` has to be either constant/symbolic; the second
1155/// operand for floordiv, ceildiv, and mod has to be a positive integer.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001156AffineExpr *AffineParser::parseAffineExpr() {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001157 return parseAffineLowPrecOpExpr(nullptr, AffineLowPrecOp::LNoOp);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001158}
1159
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001160/// Parse a dim or symbol from the lists appearing before the actual expressions
Chris Lattner2e595eb2018-07-10 10:08:27 -07001161/// of the affine map. Update our state to store the dimensional/symbolic
Chris Lattner413db6a2018-07-25 12:55:50 -07001162/// identifier.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001163ParseResult AffineParser::parseIdentifierDefinition(AffineExpr *idExpr) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001164 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001165 return emitError("expected bare identifier");
Chris Lattner413db6a2018-07-25 12:55:50 -07001166
1167 auto name = getTokenSpelling();
1168 for (auto entry : dimsAndSymbols) {
1169 if (entry.first == name)
1170 return emitError("redefinition of identifier '" + Twine(name) + "'");
1171 }
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001172 consumeToken(Token::bare_identifier);
Chris Lattner413db6a2018-07-25 12:55:50 -07001173
1174 dimsAndSymbols.push_back({name, idExpr});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001175 return ParseSuccess;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001176}
1177
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001178/// Parse the list of symbolic identifiers to an affine map.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001179ParseResult AffineParser::parseSymbolIdList(unsigned &numSymbols) {
Chris Lattner413db6a2018-07-25 12:55:50 -07001180 consumeToken(Token::l_square);
1181 auto parseElt = [&]() -> ParseResult {
1182 auto *symbol = AffineSymbolExpr::get(numSymbols++, getContext());
1183 return parseIdentifierDefinition(symbol);
1184 };
Chris Lattner85ee1512018-07-25 11:15:20 -07001185 return parseCommaSeparatedListUntil(Token::r_square, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001186}
1187
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001188/// Parse the list of dimensional identifiers to an affine map.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001189ParseResult AffineParser::parseDimIdList(unsigned &numDims) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07001190 if (parseToken(Token::l_paren,
1191 "expected '(' at start of dimensional identifiers list"))
1192 return ParseFailure;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001193
Chris Lattner413db6a2018-07-25 12:55:50 -07001194 auto parseElt = [&]() -> ParseResult {
1195 auto *dimension = AffineDimExpr::get(numDims++, getContext());
1196 return parseIdentifierDefinition(dimension);
1197 };
Chris Lattner40746442018-07-21 14:32:09 -07001198 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001199}
1200
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001201/// Parse an affine map definition.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001202///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001203/// affine-map-inline ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
1204/// (`size` `(` dim-size (`,` dim-size)* `)`)?
1205/// dim-size ::= affine-expr | `min` `(` affine-expr ( `,` affine-expr)+ `)`
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001206///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001207/// multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Uday Bondhugulabc535622018-08-07 14:24:38 -07001208AffineMap *AffineParser::parseAffineMapInline() {
Chris Lattner413db6a2018-07-25 12:55:50 -07001209 unsigned numDims = 0, numSymbols = 0;
1210
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001211 // List of dimensional identifiers.
Chris Lattner413db6a2018-07-25 12:55:50 -07001212 if (parseDimIdList(numDims))
Chris Lattner7121b802018-07-04 20:45:39 -07001213 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001214
1215 // Symbols are optional.
Chris Lattner85ee1512018-07-25 11:15:20 -07001216 if (getToken().is(Token::l_square)) {
Chris Lattner413db6a2018-07-25 12:55:50 -07001217 if (parseSymbolIdList(numSymbols))
Chris Lattner7121b802018-07-04 20:45:39 -07001218 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001219 }
Chris Lattnerf7702a62018-07-23 17:30:01 -07001220
1221 if (parseToken(Token::arrow, "expected '->' or '['") ||
1222 parseToken(Token::l_paren, "expected '(' at start of affine map range"))
Chris Lattner7121b802018-07-04 20:45:39 -07001223 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001224
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001225 SmallVector<AffineExpr *, 4> exprs;
1226 auto parseElt = [&]() -> ParseResult {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001227 auto *elt = parseAffineExpr();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001228 ParseResult res = elt ? ParseSuccess : ParseFailure;
1229 exprs.push_back(elt);
1230 return res;
1231 };
1232
1233 // Parse a multi-dimensional affine expression (a comma-separated list of 1-d
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001234 // affine expressions); the list cannot be empty.
1235 // Grammar: multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner40746442018-07-21 14:32:09 -07001236 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt, false))
Chris Lattner7121b802018-07-04 20:45:39 -07001237 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001238
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001239 // Parse optional range sizes.
Uday Bondhugula1e500b42018-07-12 18:04:04 -07001240 // range-sizes ::= (`size` `(` dim-size (`,` dim-size)* `)`)?
1241 // dim-size ::= affine-expr | `min` `(` affine-expr (`,` affine-expr)+ `)`
1242 // TODO(bondhugula): support for min of several affine expressions.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001243 // TODO: check if sizes are non-negative whenever they are constant.
1244 SmallVector<AffineExpr *, 4> rangeSizes;
1245 if (consumeIf(Token::kw_size)) {
1246 // Location of the l_paren token (if it exists) for error reporting later.
1247 auto loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001248 if (parseToken(Token::l_paren, "expected '(' at start of affine map range"))
1249 return nullptr;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001250
1251 auto parseRangeSize = [&]() -> ParseResult {
Chris Lattner413db6a2018-07-25 12:55:50 -07001252 auto loc = getToken().getLoc();
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001253 auto *elt = parseAffineExpr();
Chris Lattner413db6a2018-07-25 12:55:50 -07001254 if (!elt)
1255 return ParseFailure;
1256
1257 if (!elt->isSymbolicOrConstant())
1258 return emitError(loc,
1259 "size expressions cannot refer to dimension values");
1260
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001261 rangeSizes.push_back(elt);
Chris Lattner413db6a2018-07-25 12:55:50 -07001262 return ParseSuccess;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001263 };
1264
Chris Lattner40746442018-07-21 14:32:09 -07001265 if (parseCommaSeparatedListUntil(Token::r_paren, parseRangeSize, false))
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001266 return nullptr;
1267 if (exprs.size() > rangeSizes.size())
1268 return (emitError(loc, "fewer range sizes than range expressions"),
1269 nullptr);
1270 if (exprs.size() < rangeSizes.size())
1271 return (emitError(loc, "more range sizes than range expressions"),
1272 nullptr);
1273 }
1274
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001275 // Parsed a valid affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001276 return builder.getAffineMap(numDims, numSymbols, exprs, rangeSizes);
MLIR Teamf85a6262018-06-27 11:03:08 -07001277}
1278
Chris Lattner2e595eb2018-07-10 10:08:27 -07001279AffineMap *Parser::parseAffineMapInline() {
Uday Bondhugulabc535622018-08-07 14:24:38 -07001280 return AffineParser(state).parseAffineMapInline();
Chris Lattner2e595eb2018-07-10 10:08:27 -07001281}
1282
MLIR Team718c82f2018-07-16 09:45:22 -07001283AffineMap *Parser::parseAffineMapReference() {
1284 if (getToken().is(Token::hash_identifier)) {
1285 // Parse affine map identifier and verify that it exists.
1286 StringRef affineMapId = getTokenSpelling().drop_front();
1287 if (getState().affineMapDefinitions.count(affineMapId) == 0)
1288 return (emitError("undefined affine map id '" + affineMapId + "'"),
1289 nullptr);
1290 consumeToken(Token::hash_identifier);
1291 return getState().affineMapDefinitions[affineMapId];
1292 }
1293 // Try to parse inline affine map.
1294 return parseAffineMapInline();
1295}
1296
MLIR Teamf85a6262018-06-27 11:03:08 -07001297//===----------------------------------------------------------------------===//
Chris Lattner7f9cc272018-07-19 08:35:28 -07001298// FunctionParser
Chris Lattner4c95a502018-06-23 16:03:42 -07001299//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001300
Chris Lattner7f9cc272018-07-19 08:35:28 -07001301namespace {
1302/// This class contains parser state that is common across CFG and ML functions,
1303/// notably for dealing with operations and SSA values.
1304class FunctionParser : public Parser {
1305public:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001306 enum class Kind { CFGFunc, MLFunc };
1307
1308 Kind getKind() const { return kind; }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001309
Chris Lattner6119d382018-07-20 18:41:34 -07001310 /// After the function is finished parsing, this function checks to see if
1311 /// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001312 ParseResult finalizeFunction(Function *func, SMLoc loc);
Chris Lattner6119d382018-07-20 18:41:34 -07001313
1314 /// This represents a use of an SSA value in the program. The first two
1315 /// entries in the tuple are the name and result number of a reference. The
1316 /// third is the location of the reference, which is used in case this ends up
1317 /// being a use of an undefined value.
1318 struct SSAUseInfo {
1319 StringRef name; // Value name, e.g. %42 or %abc
1320 unsigned number; // Number, specified with #12
1321 SMLoc loc; // Location of first definition or use.
1322 };
Chris Lattner7f9cc272018-07-19 08:35:28 -07001323
1324 /// Given a reference to an SSA value and its type, return a reference. This
1325 /// returns null on failure.
1326 SSAValue *resolveSSAUse(SSAUseInfo useInfo, Type *type);
1327
1328 /// Register a definition of a value with the symbol table.
1329 ParseResult addDefinition(SSAUseInfo useInfo, SSAValue *value);
1330
1331 // SSA parsing productions.
1332 ParseResult parseSSAUse(SSAUseInfo &result);
Chris Lattner40746442018-07-21 14:32:09 -07001333 ParseResult parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results);
James Molloy61a656c2018-07-22 15:45:24 -07001334
1335 template <typename ResultType>
1336 ResultType parseSSADefOrUseAndType(
1337 const std::function<ResultType(SSAUseInfo, Type *)> &action);
1338
1339 SSAValue *parseSSAUseAndType() {
1340 return parseSSADefOrUseAndType<SSAValue *>(
1341 [&](SSAUseInfo useInfo, Type *type) -> SSAValue * {
1342 return resolveSSAUse(useInfo, type);
1343 });
1344 }
Chris Lattner40746442018-07-21 14:32:09 -07001345
1346 template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001347 ParseResult
Chris Lattner2c402672018-07-23 11:56:17 -07001348 parseOptionalSSAUseAndTypeList(SmallVectorImpl<ValueTy *> &results,
1349 bool isParenthesized);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001350
1351 // Operations
1352 ParseResult parseOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner85ee1512018-07-25 11:15:20 -07001353 Operation *parseVerboseOperation(const CreateOperationFunction &createOpFunc);
1354 Operation *parseCustomOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001355
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001356protected:
1357 FunctionParser(ParserState &state, Kind kind) : Parser(state), kind(kind) {}
1358
Chris Lattner7f9cc272018-07-19 08:35:28 -07001359private:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001360 /// Kind indicates if this is CFG or ML function parser.
1361 Kind kind;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001362 /// This keeps track of all of the SSA values we are tracking, indexed by
Chris Lattner6119d382018-07-20 18:41:34 -07001363 /// their name. This has one entry per result number.
1364 llvm::StringMap<SmallVector<std::pair<SSAValue *, SMLoc>, 1>> values;
1365
1366 /// These are all of the placeholders we've made along with the location of
1367 /// their first reference, to allow checking for use of undefined values.
1368 DenseMap<SSAValue *, SMLoc> forwardReferencePlaceholders;
1369
1370 SSAValue *createForwardReferencePlaceholder(SMLoc loc, Type *type);
1371
1372 /// Return true if this is a forward reference.
1373 bool isForwardReferencePlaceholder(SSAValue *value) {
1374 return forwardReferencePlaceholders.count(value);
1375 }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001376};
1377} // end anonymous namespace
1378
Chris Lattner6119d382018-07-20 18:41:34 -07001379/// Create and remember a new placeholder for a forward reference.
1380SSAValue *FunctionParser::createForwardReferencePlaceholder(SMLoc loc,
1381 Type *type) {
1382 // Forward references are always created as instructions, even in ML
1383 // functions, because we just need something with a def/use chain.
1384 //
1385 // We create these placeholders as having an empty name, which we know cannot
1386 // be created through normal user input, allowing us to distinguish them.
1387 auto name = Identifier::get("placeholder", getContext());
Chris Lattner1628fa02018-08-23 14:32:25 -07001388 auto *inst =
1389 // FIXME(clattner): encode the location into the placeholder instead of
1390 // into the forwardReferencePlaceholders map!
1391 OperationInst::create(/*location=*/nullptr, name, /*operands=*/{}, type,
1392 /*attrs=*/{}, getContext());
Chris Lattner6119d382018-07-20 18:41:34 -07001393 forwardReferencePlaceholders[inst->getResult(0)] = loc;
1394 return inst->getResult(0);
1395}
1396
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001397/// Given an unbound reference to an SSA value and its type, return the value
Chris Lattner7f9cc272018-07-19 08:35:28 -07001398/// it specifies. This returns null on failure.
1399SSAValue *FunctionParser::resolveSSAUse(SSAUseInfo useInfo, Type *type) {
Chris Lattner6119d382018-07-20 18:41:34 -07001400 auto &entries = values[useInfo.name];
1401
Chris Lattner7f9cc272018-07-19 08:35:28 -07001402 // If we have already seen a value of this name, return it.
Chris Lattner6119d382018-07-20 18:41:34 -07001403 if (useInfo.number < entries.size() && entries[useInfo.number].first) {
1404 auto *result = entries[useInfo.number].first;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001405 // Check that the type matches the other uses.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001406 if (result->getType() == type)
1407 return result;
1408
Chris Lattner6119d382018-07-20 18:41:34 -07001409 emitError(useInfo.loc, "use of value '" + useInfo.name.str() +
1410 "' expects different type than prior uses");
1411 emitError(entries[useInfo.number].second, "prior use here");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001412 return nullptr;
1413 }
1414
Chris Lattner6119d382018-07-20 18:41:34 -07001415 // Make sure we have enough slots for this.
1416 if (entries.size() <= useInfo.number)
1417 entries.resize(useInfo.number + 1);
1418
1419 // If the value has already been defined and this is an overly large result
1420 // number, diagnose that.
1421 if (entries[0].first && !isForwardReferencePlaceholder(entries[0].first))
1422 return (emitError(useInfo.loc, "reference to invalid result number"),
1423 nullptr);
1424
Tatiana Shpeismand880b352018-07-31 23:14:16 -07001425 // Otherwise, this is a forward reference. If we are in ML function return
1426 // an error. In CFG function, create a placeholder and remember
1427 // that we did so.
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001428 if (getKind() == Kind::MLFunc)
1429 return (
1430 emitError(useInfo.loc, "use of undefined SSA value " + useInfo.name),
1431 nullptr);
1432
Chris Lattner6119d382018-07-20 18:41:34 -07001433 auto *result = createForwardReferencePlaceholder(useInfo.loc, type);
1434 entries[useInfo.number].first = result;
1435 entries[useInfo.number].second = useInfo.loc;
1436 return result;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001437}
1438
1439/// Register a definition of a value with the symbol table.
1440ParseResult FunctionParser::addDefinition(SSAUseInfo useInfo, SSAValue *value) {
Chris Lattner6119d382018-07-20 18:41:34 -07001441 auto &entries = values[useInfo.name];
Chris Lattner7f9cc272018-07-19 08:35:28 -07001442
Chris Lattner6119d382018-07-20 18:41:34 -07001443 // Make sure there is a slot for this value.
1444 if (entries.size() <= useInfo.number)
1445 entries.resize(useInfo.number + 1);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001446
Chris Lattner6119d382018-07-20 18:41:34 -07001447 // If we already have an entry for this, check to see if it was a definition
1448 // or a forward reference.
1449 if (auto *existing = entries[useInfo.number].first) {
1450 if (!isForwardReferencePlaceholder(existing)) {
1451 emitError(useInfo.loc,
1452 "redefinition of SSA value '" + useInfo.name + "'");
1453 return emitError(entries[useInfo.number].second,
1454 "previously defined here");
1455 }
1456
1457 // If it was a forward reference, update everything that used it to use the
1458 // actual definition instead, delete the forward ref, and remove it from our
1459 // set of forward references we track.
1460 existing->replaceAllUsesWith(value);
1461 existing->getDefiningInst()->destroy();
1462 forwardReferencePlaceholders.erase(existing);
1463 }
1464
1465 entries[useInfo.number].first = value;
1466 entries[useInfo.number].second = useInfo.loc;
1467 return ParseSuccess;
1468}
1469
1470/// After the function is finished parsing, this function checks to see if
1471/// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001472ParseResult FunctionParser::finalizeFunction(Function *func, SMLoc loc) {
Chris Lattner6119d382018-07-20 18:41:34 -07001473 // Check for any forward references that are left. If we find any, error out.
1474 if (!forwardReferencePlaceholders.empty()) {
1475 SmallVector<std::pair<const char *, SSAValue *>, 4> errors;
1476 // Iteration over the map isn't determinstic, so sort by source location.
1477 for (auto entry : forwardReferencePlaceholders)
1478 errors.push_back({entry.second.getPointer(), entry.first});
1479 llvm::array_pod_sort(errors.begin(), errors.end());
1480
1481 for (auto entry : errors)
1482 emitError(SMLoc::getFromPointer(entry.first),
1483 "use of undeclared SSA value name");
1484 return ParseFailure;
1485 }
1486
1487 return ParseSuccess;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001488}
1489
Chris Lattner78276e32018-07-07 15:48:26 -07001490/// Parse a SSA operand for an instruction or statement.
1491///
James Molloy61a656c2018-07-22 15:45:24 -07001492/// ssa-use ::= ssa-id
Chris Lattner78276e32018-07-07 15:48:26 -07001493///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001494ParseResult FunctionParser::parseSSAUse(SSAUseInfo &result) {
Chris Lattner6119d382018-07-20 18:41:34 -07001495 result.name = getTokenSpelling();
1496 result.number = 0;
1497 result.loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001498 if (parseToken(Token::percent_identifier, "expected SSA operand"))
1499 return ParseFailure;
Chris Lattner6119d382018-07-20 18:41:34 -07001500
1501 // If we have an affine map ID, it is a result number.
1502 if (getToken().is(Token::hash_identifier)) {
1503 if (auto value = getToken().getHashIdentifierNumber())
1504 result.number = value.getValue();
1505 else
1506 return emitError("invalid SSA value result number");
1507 consumeToken(Token::hash_identifier);
1508 }
1509
Chris Lattner7f9cc272018-07-19 08:35:28 -07001510 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001511}
1512
1513/// Parse a (possibly empty) list of SSA operands.
1514///
1515/// ssa-use-list ::= ssa-use (`,` ssa-use)*
1516/// ssa-use-list-opt ::= ssa-use-list?
1517///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001518ParseResult
Chris Lattner40746442018-07-21 14:32:09 -07001519FunctionParser::parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results) {
Chris Lattner85ee1512018-07-25 11:15:20 -07001520 if (getToken().isNot(Token::percent_identifier))
Chris Lattner40746442018-07-21 14:32:09 -07001521 return ParseSuccess;
1522 return parseCommaSeparatedList([&]() -> ParseResult {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001523 SSAUseInfo result;
1524 if (parseSSAUse(result))
1525 return ParseFailure;
1526 results.push_back(result);
1527 return ParseSuccess;
1528 });
Chris Lattner78276e32018-07-07 15:48:26 -07001529}
1530
1531/// Parse an SSA use with an associated type.
1532///
1533/// ssa-use-and-type ::= ssa-use `:` type
James Molloy61a656c2018-07-22 15:45:24 -07001534template <typename ResultType>
1535ResultType FunctionParser::parseSSADefOrUseAndType(
1536 const std::function<ResultType(SSAUseInfo, Type *)> &action) {
Chris Lattner78276e32018-07-07 15:48:26 -07001537
Chris Lattnerf7702a62018-07-23 17:30:01 -07001538 SSAUseInfo useInfo;
1539 if (parseSSAUse(useInfo) ||
1540 parseToken(Token::colon, "expected ':' and type for SSA operand"))
1541 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001542
Chris Lattner7f9cc272018-07-19 08:35:28 -07001543 auto *type = parseType();
1544 if (!type)
1545 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001546
James Molloy61a656c2018-07-22 15:45:24 -07001547 return action(useInfo, type);
Chris Lattner78276e32018-07-07 15:48:26 -07001548}
1549
Chris Lattner2c402672018-07-23 11:56:17 -07001550/// Parse a (possibly empty) list of SSA operands, followed by a colon, then
1551/// followed by a type list. If hasParens is true, then the operands are
1552/// surrounded by parens.
Chris Lattner78276e32018-07-07 15:48:26 -07001553///
Chris Lattner2c402672018-07-23 11:56:17 -07001554/// ssa-use-and-type-list[parens]
1555/// ::= `(` ssa-use-list `)` ':' type-list-no-parens
1556///
1557/// ssa-use-and-type-list[!parens]
1558/// ::= ssa-use-list ':' type-list-no-parens
Chris Lattner78276e32018-07-07 15:48:26 -07001559///
Chris Lattner40746442018-07-21 14:32:09 -07001560template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001561ParseResult FunctionParser::parseOptionalSSAUseAndTypeList(
Chris Lattner2c402672018-07-23 11:56:17 -07001562 SmallVectorImpl<ValueTy *> &results, bool isParenthesized) {
1563
1564 // If we are in the parenthesized form and no paren exists, then we succeed
1565 // with an empty list.
1566 if (isParenthesized && !consumeIf(Token::l_paren))
Chris Lattner40746442018-07-21 14:32:09 -07001567 return ParseSuccess;
1568
Chris Lattner2c402672018-07-23 11:56:17 -07001569 SmallVector<SSAUseInfo, 4> valueIDs;
1570 if (parseOptionalSSAUseList(valueIDs))
Chris Lattner7f9cc272018-07-19 08:35:28 -07001571 return ParseFailure;
Chris Lattner2c402672018-07-23 11:56:17 -07001572
1573 if (isParenthesized && !consumeIf(Token::r_paren))
1574 return emitError("expected ')' in operand list");
1575
1576 // If there were no operands, then there is no colon or type lists.
1577 if (valueIDs.empty())
1578 return ParseSuccess;
1579
Chris Lattner2c402672018-07-23 11:56:17 -07001580 SmallVector<Type *, 4> types;
Chris Lattnerf7702a62018-07-23 17:30:01 -07001581 if (parseToken(Token::colon, "expected ':' in operand list") ||
1582 parseTypeListNoParens(types))
Chris Lattner2c402672018-07-23 11:56:17 -07001583 return ParseFailure;
1584
1585 if (valueIDs.size() != types.size())
1586 return emitError("expected " + Twine(valueIDs.size()) +
1587 " types to match operand list");
1588
1589 results.reserve(valueIDs.size());
1590 for (unsigned i = 0, e = valueIDs.size(); i != e; ++i) {
1591 if (auto *value = resolveSSAUse(valueIDs[i], types[i]))
1592 results.push_back(cast<ValueTy>(value));
1593 else
1594 return ParseFailure;
1595 }
1596
1597 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001598}
1599
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001600/// Parse the CFG or MLFunc operation.
1601///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001602/// operation ::=
1603/// (ssa-id `=`)? string '(' ssa-use-list? ')' attribute-dict?
1604/// `:` function-type
1605///
1606ParseResult
Chris Lattner7f9cc272018-07-19 08:35:28 -07001607FunctionParser::parseOperation(const CreateOperationFunction &createOpFunc) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001608 auto loc = getToken().getLoc();
1609
1610 StringRef resultID;
1611 if (getToken().is(Token::percent_identifier)) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001612 resultID = getTokenSpelling();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001613 consumeToken(Token::percent_identifier);
Chris Lattnerf7702a62018-07-23 17:30:01 -07001614 if (parseToken(Token::equal, "expected '=' after SSA name"))
1615 return ParseFailure;
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001616 }
1617
Chris Lattner85ee1512018-07-25 11:15:20 -07001618 Operation *op;
1619 if (getToken().is(Token::bare_identifier) || getToken().isKeyword())
1620 op = parseCustomOperation(createOpFunc);
1621 else if (getToken().is(Token::string))
1622 op = parseVerboseOperation(createOpFunc);
1623 else
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001624 return emitError("expected operation name in quotes");
1625
Chris Lattner85ee1512018-07-25 11:15:20 -07001626 // If parsing of the basic operation failed, then this whole thing fails.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001627 if (!op)
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001628 return ParseFailure;
1629
1630 // We just parsed an operation. If it is a recognized one, verify that it
1631 // is structurally as we expect. If not, produce an error with a reasonable
1632 // source location.
Chris Lattner95865062018-08-01 10:18:59 -07001633 if (auto *opInfo = op->getAbstractOperation()) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001634 if (auto error = opInfo->verifyInvariants(op))
Chris Lattner9361fb32018-07-24 08:34:58 -07001635 return emitError(loc, Twine("'") + op->getName().str() + "' op " + error);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001636 }
1637
Chris Lattner7f9cc272018-07-19 08:35:28 -07001638 // If the instruction had a name, register it.
1639 if (!resultID.empty()) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001640 if (op->getNumResults() == 0)
1641 return emitError(loc, "cannot name an operation with no results");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001642
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001643 for (unsigned i = 0, e = op->getNumResults(); i != e; ++i)
Chris Lattner2b97d502018-08-06 14:19:46 -07001644 if (addDefinition({resultID, i, loc}, op->getResult(i)))
1645 return ParseFailure;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001646 }
1647
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001648 return ParseSuccess;
1649}
Chris Lattnere79379a2018-06-22 10:39:19 -07001650
Chris Lattner85ee1512018-07-25 11:15:20 -07001651Operation *FunctionParser::parseVerboseOperation(
1652 const CreateOperationFunction &createOpFunc) {
Chris Lattner1628fa02018-08-23 14:32:25 -07001653
1654 // Get location information for the operation.
1655 auto *srcLocation = getEncodedSourceLocation(getToken().getLoc());
1656
Chris Lattner85ee1512018-07-25 11:15:20 -07001657 auto name = getToken().getStringValue();
1658 if (name.empty())
1659 return (emitError("empty operation name is invalid"), nullptr);
1660
1661 consumeToken(Token::string);
1662
Chris Lattner1628fa02018-08-23 14:32:25 -07001663 OperationState result(builder.getContext(), srcLocation, name);
Chris Lattner992a1272018-08-07 12:02:37 -07001664
Chris Lattner85ee1512018-07-25 11:15:20 -07001665 // Parse the operand list.
1666 SmallVector<SSAUseInfo, 8> operandInfos;
1667
1668 if (parseToken(Token::l_paren, "expected '(' to start operand list") ||
1669 parseOptionalSSAUseList(operandInfos) ||
1670 parseToken(Token::r_paren, "expected ')' to end operand list")) {
1671 return nullptr;
1672 }
1673
Chris Lattner85ee1512018-07-25 11:15:20 -07001674 if (getToken().is(Token::l_brace)) {
Chris Lattner992a1272018-08-07 12:02:37 -07001675 if (parseAttributeDict(result.attributes))
Chris Lattner85ee1512018-07-25 11:15:20 -07001676 return nullptr;
1677 }
1678
1679 if (parseToken(Token::colon, "expected ':' followed by instruction type"))
1680 return nullptr;
1681
1682 auto typeLoc = getToken().getLoc();
1683 auto type = parseType();
1684 if (!type)
1685 return nullptr;
1686 auto fnType = dyn_cast<FunctionType>(type);
1687 if (!fnType)
1688 return (emitError(typeLoc, "expected function type"), nullptr);
1689
Chris Lattner1eb77482018-08-22 19:25:49 -07001690 result.addTypes(fnType->getResults());
Chris Lattner992a1272018-08-07 12:02:37 -07001691
Chris Lattner85ee1512018-07-25 11:15:20 -07001692 // Check that we have the right number of types for the operands.
1693 auto operandTypes = fnType->getInputs();
1694 if (operandTypes.size() != operandInfos.size()) {
1695 auto plural = "s"[operandInfos.size() == 1];
1696 return (emitError(typeLoc, "expected " + llvm::utostr(operandInfos.size()) +
1697 " operand type" + plural + " but had " +
1698 llvm::utostr(operandTypes.size())),
1699 nullptr);
1700 }
1701
1702 // Resolve all of the operands.
Chris Lattner85ee1512018-07-25 11:15:20 -07001703 for (unsigned i = 0, e = operandInfos.size(); i != e; ++i) {
Chris Lattner992a1272018-08-07 12:02:37 -07001704 result.operands.push_back(resolveSSAUse(operandInfos[i], operandTypes[i]));
1705 if (!result.operands.back())
Chris Lattner85ee1512018-07-25 11:15:20 -07001706 return nullptr;
1707 }
1708
Chris Lattner992a1272018-08-07 12:02:37 -07001709 return createOpFunc(result);
Chris Lattner85ee1512018-07-25 11:15:20 -07001710}
1711
1712namespace {
1713class CustomOpAsmParser : public OpAsmParser {
1714public:
1715 CustomOpAsmParser(SMLoc nameLoc, StringRef opName, FunctionParser &parser)
1716 : nameLoc(nameLoc), opName(opName), parser(parser) {}
1717
Chris Lattner85ee1512018-07-25 11:15:20 -07001718 //===--------------------------------------------------------------------===//
1719 // High level parsing methods.
1720 //===--------------------------------------------------------------------===//
1721
Chris Lattner1aa46322018-08-21 17:55:22 -07001722 bool getCurrentLocation(llvm::SMLoc *loc) override {
1723 *loc = parser.getToken().getLoc();
1724 return false;
1725 }
Chris Lattner091a6b52018-08-23 14:58:27 -07001726 bool parseComma() override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001727 return parser.parseToken(Token::comma, "expected ','");
1728 }
1729
Chris Lattner091a6b52018-08-23 14:58:27 -07001730 bool parseColonType(Type *&result) override {
1731 return parser.parseToken(Token::colon, "expected ':'") ||
1732 !(result = parser.parseType());
Chris Lattner85ee1512018-07-25 11:15:20 -07001733 }
1734
Chris Lattner091a6b52018-08-23 14:58:27 -07001735 bool parseColonTypeList(SmallVectorImpl<Type *> &result) override {
1736 if (parser.parseToken(Token::colon, "expected ':'"))
Chris Lattner85ee1512018-07-25 11:15:20 -07001737 return true;
1738
1739 do {
1740 if (auto *type = parser.parseType())
1741 result.push_back(type);
1742 else
1743 return true;
1744
1745 } while (parser.consumeIf(Token::comma));
1746 return false;
1747 }
1748
Chris Lattner85cf26d2018-08-02 16:54:36 -07001749 /// Parse an arbitrary attribute and return it in result. This also adds the
1750 /// attribute to the specified attribute list with the specified name. this
1751 /// captures the location of the attribute in 'loc' if it is non-null.
1752 bool parseAttribute(Attribute *&result, const char *attrName,
Chris Lattner091a6b52018-08-23 14:58:27 -07001753 SmallVectorImpl<NamedAttribute> &attrs) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001754 result = parser.parseAttribute();
Chris Lattner85cf26d2018-08-02 16:54:36 -07001755 if (!result)
1756 return true;
1757
1758 attrs.push_back(
1759 NamedAttribute(parser.builder.getIdentifier(attrName), result));
1760 return false;
1761 }
1762
1763 /// If a named attribute list is present, parse is into result.
Chris Lattner091a6b52018-08-23 14:58:27 -07001764 bool
1765 parseOptionalAttributeDict(SmallVectorImpl<NamedAttribute> &result) override {
Chris Lattner85cf26d2018-08-02 16:54:36 -07001766 if (parser.getToken().isNot(Token::l_brace))
1767 return false;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001768 return parser.parseAttributeDict(result) == ParseFailure;
Chris Lattner85ee1512018-07-25 11:15:20 -07001769 }
1770
Chris Lattner1aa46322018-08-21 17:55:22 -07001771 /// Parse a function name like '@foo' and return the name in a form that can
1772 /// be passed to resolveFunctionName when a function type is available.
1773 virtual bool parseFunctionName(StringRef &result, llvm::SMLoc &loc) {
1774 loc = parser.getToken().getLoc();
1775
1776 if (parser.getToken().isNot(Token::at_identifier))
1777 return emitError(loc, "expected function name");
1778
1779 result = parser.getTokenSpelling();
1780 parser.consumeToken(Token::at_identifier);
1781 return false;
1782 }
1783
Chris Lattner85ee1512018-07-25 11:15:20 -07001784 bool parseOperand(OperandType &result) override {
1785 FunctionParser::SSAUseInfo useInfo;
1786 if (parser.parseSSAUse(useInfo))
1787 return true;
1788
1789 result = {useInfo.loc, useInfo.name, useInfo.number};
1790 return false;
1791 }
1792
1793 bool parseOperandList(SmallVectorImpl<OperandType> &result,
1794 int requiredOperandCount = -1,
Chris Lattner85cf26d2018-08-02 16:54:36 -07001795 Delimiter delimiter = Delimiter::None) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001796 auto startLoc = parser.getToken().getLoc();
1797
Chris Lattner85cf26d2018-08-02 16:54:36 -07001798 // Handle delimiters.
1799 switch (delimiter) {
1800 case Delimiter::None:
Chris Lattner85ee1512018-07-25 11:15:20 -07001801 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001802 case Delimiter::OptionalParen:
Chris Lattner3164ae62018-07-28 09:36:25 -07001803 if (parser.getToken().isNot(Token::l_paren))
1804 return false;
1805 LLVM_FALLTHROUGH;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001806 case Delimiter::Paren:
Chris Lattner85ee1512018-07-25 11:15:20 -07001807 if (parser.parseToken(Token::l_paren, "expected '(' in operand list"))
1808 return true;
1809 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001810 case Delimiter::OptionalSquare:
Chris Lattner3164ae62018-07-28 09:36:25 -07001811 if (parser.getToken().isNot(Token::l_square))
1812 return false;
1813 LLVM_FALLTHROUGH;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001814 case Delimiter::Square:
Chris Lattner85ee1512018-07-25 11:15:20 -07001815 if (parser.parseToken(Token::l_square, "expected '[' in operand list"))
1816 return true;
1817 break;
1818 }
1819
1820 // Check for zero operands.
1821 if (parser.getToken().is(Token::percent_identifier)) {
1822 do {
1823 OperandType operand;
1824 if (parseOperand(operand))
1825 return true;
1826 result.push_back(operand);
1827 } while (parser.consumeIf(Token::comma));
1828 }
1829
Chris Lattner85cf26d2018-08-02 16:54:36 -07001830 // Handle delimiters. If we reach here, the optional delimiters were
Chris Lattner3164ae62018-07-28 09:36:25 -07001831 // present, so we need to parse their closing one.
Chris Lattner85cf26d2018-08-02 16:54:36 -07001832 switch (delimiter) {
1833 case Delimiter::None:
Chris Lattner85ee1512018-07-25 11:15:20 -07001834 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001835 case Delimiter::OptionalParen:
1836 case Delimiter::Paren:
Chris Lattner85ee1512018-07-25 11:15:20 -07001837 if (parser.parseToken(Token::r_paren, "expected ')' in operand list"))
1838 return true;
1839 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001840 case Delimiter::OptionalSquare:
1841 case Delimiter::Square:
Chris Lattner85ee1512018-07-25 11:15:20 -07001842 if (parser.parseToken(Token::r_square, "expected ']' in operand list"))
1843 return true;
1844 break;
1845 }
1846
1847 if (requiredOperandCount != -1 && result.size() != requiredOperandCount)
1848 emitError(startLoc,
1849 "expected " + Twine(requiredOperandCount) + " operands");
1850 return false;
1851 }
1852
Chris Lattner1aa46322018-08-21 17:55:22 -07001853 /// Resolve a parse function name and a type into a function reference.
1854 virtual bool resolveFunctionName(StringRef name, FunctionType *type,
1855 llvm::SMLoc loc, Function *&result) {
1856 result = parser.resolveFunctionReference(name, loc, type);
1857 return result == nullptr;
1858 }
1859
Chris Lattner85ee1512018-07-25 11:15:20 -07001860 //===--------------------------------------------------------------------===//
1861 // Methods for interacting with the parser
1862 //===--------------------------------------------------------------------===//
1863
1864 Builder &getBuilder() const override { return parser.builder; }
1865
1866 llvm::SMLoc getNameLoc() const override { return nameLoc; }
1867
Chris Lattner1aa46322018-08-21 17:55:22 -07001868 bool resolveOperand(const OperandType &operand, Type *type,
Chris Lattner8bdbebf2018-08-08 11:02:58 -07001869 SmallVectorImpl<SSAValue *> &result) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001870 FunctionParser::SSAUseInfo operandInfo = {operand.name, operand.number,
1871 operand.location};
Chris Lattner8bdbebf2018-08-08 11:02:58 -07001872 if (auto *value = parser.resolveSSAUse(operandInfo, type)) {
1873 result.push_back(value);
1874 return false;
1875 }
1876 return true;
Chris Lattner85ee1512018-07-25 11:15:20 -07001877 }
1878
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001879 /// Emit a diagnostic at the specified location and return true.
1880 bool emitError(llvm::SMLoc loc, const Twine &message) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001881 parser.emitError(loc, "custom op '" + Twine(opName) + "' " + message);
1882 emittedError = true;
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001883 return true;
Chris Lattner85ee1512018-07-25 11:15:20 -07001884 }
1885
1886 bool didEmitError() const { return emittedError; }
1887
1888private:
1889 SMLoc nameLoc;
1890 StringRef opName;
1891 FunctionParser &parser;
1892 bool emittedError = false;
1893};
1894} // end anonymous namespace.
1895
1896Operation *FunctionParser::parseCustomOperation(
1897 const CreateOperationFunction &createOpFunc) {
1898 auto opLoc = getToken().getLoc();
1899 auto opName = getTokenSpelling();
1900 CustomOpAsmParser opAsmParser(opLoc, opName, *this);
1901
1902 auto *opDefinition = getOperationSet().lookup(opName);
1903 if (!opDefinition) {
1904 opAsmParser.emitError(opLoc, "is unknown");
1905 return nullptr;
1906 }
1907
1908 consumeToken();
1909
Chris Lattner1aa46322018-08-21 17:55:22 -07001910 // If the custom op parser crashes, produce some indication to help debugging.
1911 std::string opNameStr = opName.str();
1912 llvm::PrettyStackTraceFormat fmt("MLIR Parser: custom op parser '%s'",
1913 opNameStr.c_str());
1914
Chris Lattner1628fa02018-08-23 14:32:25 -07001915 // Get location information for the operation.
1916 auto *srcLocation = getEncodedSourceLocation(opLoc);
1917
Chris Lattner85ee1512018-07-25 11:15:20 -07001918 // Have the op implementation take a crack and parsing this.
Chris Lattner1628fa02018-08-23 14:32:25 -07001919 OperationState opState(builder.getContext(), srcLocation, 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();
Chris Lattner48af7d12018-07-09 19:05:38 -07001973 TerminatorInst *parseTerminator();
Chris Lattner4c95a502018-06-23 16:03:42 -07001974};
1975} // end anonymous namespace
1976
James Molloy61a656c2018-07-22 15:45:24 -07001977/// Parse a (possibly empty) list of SSA operands with types as basic block
Chris Lattner2c402672018-07-23 11:56:17 -07001978/// arguments.
James Molloy61a656c2018-07-22 15:45:24 -07001979///
1980/// ssa-id-and-type-list ::= ssa-id-and-type (`,` ssa-id-and-type)*
1981///
1982ParseResult CFGFunctionParser::parseOptionalBasicBlockArgList(
1983 SmallVectorImpl<BBArgument *> &results, BasicBlock *owner) {
1984 if (getToken().is(Token::r_brace))
1985 return ParseSuccess;
1986
1987 return parseCommaSeparatedList([&]() -> ParseResult {
1988 auto type = parseSSADefOrUseAndType<Type *>(
1989 [&](SSAUseInfo useInfo, Type *type) -> Type * {
1990 BBArgument *arg = owner->addArgument(type);
Chris Lattner2b97d502018-08-06 14:19:46 -07001991 if (addDefinition(useInfo, arg))
James Molloy61a656c2018-07-22 15:45:24 -07001992 return nullptr;
1993 return type;
1994 });
1995 return type ? ParseSuccess : ParseFailure;
1996 });
1997}
1998
Chris Lattner48af7d12018-07-09 19:05:38 -07001999ParseResult CFGFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07002000 auto braceLoc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07002001 if (parseToken(Token::l_brace, "expected '{' in CFG function"))
2002 return ParseFailure;
Chris Lattner48af7d12018-07-09 19:05:38 -07002003
2004 // Make sure we have at least one block.
2005 if (getToken().is(Token::r_brace))
2006 return emitError("CFG functions must have at least one basic block");
Chris Lattner4c95a502018-06-23 16:03:42 -07002007
2008 // Parse the list of blocks.
2009 while (!consumeIf(Token::r_brace))
Chris Lattner48af7d12018-07-09 19:05:38 -07002010 if (parseBasicBlock())
Chris Lattner4c95a502018-06-23 16:03:42 -07002011 return ParseFailure;
2012
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002013 // Verify that all referenced blocks were defined. Iteration over a
2014 // StringMap isn't determinstic, but this is good enough for our purposes.
Chris Lattner48af7d12018-07-09 19:05:38 -07002015 for (auto &elt : blocksByName) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002016 auto *bb = elt.second.first;
Chris Lattner3a467cc2018-07-01 20:28:00 -07002017 if (!bb->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002018 return emitError(elt.second.second,
James Molloy0ff71542018-07-23 16:56:32 -07002019 "reference to an undefined basic block '" + elt.first() +
2020 "'");
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002021 }
2022
Chris Lattner40746442018-07-21 14:32:09 -07002023 return finalizeFunction(function, braceLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07002024}
2025
2026/// Basic block declaration.
2027///
2028/// basic-block ::= bb-label instruction* terminator-stmt
2029/// bb-label ::= bb-id bb-arg-list? `:`
2030/// bb-id ::= bare-id
2031/// bb-arg-list ::= `(` ssa-id-and-type-list? `)`
2032///
Chris Lattner48af7d12018-07-09 19:05:38 -07002033ParseResult CFGFunctionParser::parseBasicBlock() {
2034 SMLoc nameLoc = getToken().getLoc();
2035 auto name = getTokenSpelling();
Chris Lattnerf7702a62018-07-23 17:30:01 -07002036 if (parseToken(Token::bare_identifier, "expected basic block name"))
2037 return ParseFailure;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002038
Chris Lattner48af7d12018-07-09 19:05:38 -07002039 auto *block = getBlockNamed(name, nameLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07002040
2041 // If this block has already been parsed, then this is a redefinition with the
2042 // same block name.
Chris Lattner3a467cc2018-07-01 20:28:00 -07002043 if (block->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002044 return emitError(nameLoc, "redefinition of block '" + name.str() + "'");
2045
Chris Lattner78276e32018-07-07 15:48:26 -07002046 // If an argument list is present, parse it.
2047 if (consumeIf(Token::l_paren)) {
James Molloy61a656c2018-07-22 15:45:24 -07002048 SmallVector<BBArgument *, 8> bbArgs;
Chris Lattnerf7702a62018-07-23 17:30:01 -07002049 if (parseOptionalBasicBlockArgList(bbArgs, block) ||
2050 parseToken(Token::r_paren, "expected ')' to end argument list"))
Chris Lattner78276e32018-07-07 15:48:26 -07002051 return ParseFailure;
Chris Lattner78276e32018-07-07 15:48:26 -07002052 }
Chris Lattner4c95a502018-06-23 16:03:42 -07002053
James Molloy61a656c2018-07-22 15:45:24 -07002054 // Add the block to the function.
2055 function->push_back(block);
2056
Chris Lattnerf7702a62018-07-23 17:30:01 -07002057 if (parseToken(Token::colon, "expected ':' after basic block name"))
2058 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07002059
Chris Lattner158e0a3e2018-07-08 20:51:38 -07002060 // Set the insertion point to the block we want to insert new operations into.
Chris Lattner48af7d12018-07-09 19:05:38 -07002061 builder.setInsertionPoint(block);
Chris Lattner158e0a3e2018-07-08 20:51:38 -07002062
Chris Lattner992a1272018-08-07 12:02:37 -07002063 auto createOpFunc = [&](const OperationState &result) -> Operation * {
2064 return builder.createOperation(result);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002065 };
2066
Chris Lattnered65a732018-06-28 20:45:33 -07002067 // Parse the list of operations that make up the body of the block.
James Molloy4f788372018-07-24 15:01:27 -07002068 while (getToken().isNot(Token::kw_return, Token::kw_br, Token::kw_cond_br)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002069 if (parseOperation(createOpFunc))
Chris Lattnered65a732018-06-28 20:45:33 -07002070 return ParseFailure;
2071 }
Chris Lattner4c95a502018-06-23 16:03:42 -07002072
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002073 if (!parseTerminator())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002074 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07002075
2076 return ParseSuccess;
2077}
2078
James Molloy4f788372018-07-24 15:01:27 -07002079ParseResult CFGFunctionParser::parseBranchBlockAndUseList(
2080 BasicBlock *&block, SmallVectorImpl<CFGValue *> &values) {
2081 block = getBlockNamed(getTokenSpelling(), getToken().getLoc());
2082 if (parseToken(Token::bare_identifier, "expected basic block name"))
2083 return ParseFailure;
2084
2085 if (!consumeIf(Token::l_paren))
2086 return ParseSuccess;
2087 if (parseOptionalSSAUseAndTypeList(values, /*isParenthesized*/ false) ||
2088 parseToken(Token::r_paren, "expected ')' to close argument list"))
2089 return ParseFailure;
2090 return ParseSuccess;
2091}
2092
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002093/// Parse the terminator instruction for a basic block.
2094///
2095/// terminator-stmt ::= `br` bb-id branch-use-list?
Chris Lattner1604e472018-07-23 08:42:19 -07002096/// branch-use-list ::= `(` ssa-use-list `)` ':' type-list-no-parens
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002097/// terminator-stmt ::=
2098/// `cond_br` ssa-use `,` bb-id branch-use-list? `,` bb-id branch-use-list?
2099/// terminator-stmt ::= `return` ssa-use-and-type-list?
2100///
Chris Lattner48af7d12018-07-09 19:05:38 -07002101TerminatorInst *CFGFunctionParser::parseTerminator() {
Chris Lattner1628fa02018-08-23 14:32:25 -07002102 auto loc = getToken().getLoc();
2103
Chris Lattner48af7d12018-07-09 19:05:38 -07002104 switch (getToken().getKind()) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002105 default:
Chris Lattner3a467cc2018-07-01 20:28:00 -07002106 return (emitError("expected terminator at end of basic block"), nullptr);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002107
Chris Lattner40746442018-07-21 14:32:09 -07002108 case Token::kw_return: {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002109 consumeToken(Token::kw_return);
Chris Lattner40746442018-07-21 14:32:09 -07002110
Chris Lattner2c402672018-07-23 11:56:17 -07002111 // Parse any operands.
2112 SmallVector<CFGValue *, 8> operands;
2113 if (parseOptionalSSAUseAndTypeList(operands, /*isParenthesized*/ false))
2114 return nullptr;
Chris Lattner091a6b52018-08-23 14:58:27 -07002115 return builder.createReturn(getEncodedSourceLocation(loc), operands);
Chris Lattner40746442018-07-21 14:32:09 -07002116 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002117
2118 case Token::kw_br: {
2119 consumeToken(Token::kw_br);
James Molloy4f788372018-07-24 15:01:27 -07002120 BasicBlock *destBB;
2121 SmallVector<CFGValue *, 4> values;
2122 if (parseBranchBlockAndUseList(destBB, values))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002123 return nullptr;
Chris Lattner091a6b52018-08-23 14:58:27 -07002124 auto branch = builder.createBranch(getEncodedSourceLocation(loc), destBB);
James Molloy4f788372018-07-24 15:01:27 -07002125 branch->addOperands(values);
Chris Lattner1604e472018-07-23 08:42:19 -07002126 return branch;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002127 }
James Molloy4f788372018-07-24 15:01:27 -07002128
2129 case Token::kw_cond_br: {
2130 consumeToken(Token::kw_cond_br);
2131 SSAUseInfo ssaUse;
2132 if (parseSSAUse(ssaUse))
2133 return nullptr;
2134 auto *cond = resolveSSAUse(ssaUse, builder.getIntegerType(1));
2135 if (!cond)
2136 return (emitError("expected type was boolean (i1)"), nullptr);
2137 if (parseToken(Token::comma, "expected ',' in conditional branch"))
2138 return nullptr;
2139
2140 BasicBlock *trueBlock;
2141 SmallVector<CFGValue *, 4> trueOperands;
2142 if (parseBranchBlockAndUseList(trueBlock, trueOperands))
2143 return nullptr;
2144
2145 if (parseToken(Token::comma, "expected ',' in conditional branch"))
2146 return nullptr;
2147
2148 BasicBlock *falseBlock;
2149 SmallVector<CFGValue *, 4> falseOperands;
2150 if (parseBranchBlockAndUseList(falseBlock, falseOperands))
2151 return nullptr;
2152
Chris Lattner091a6b52018-08-23 14:58:27 -07002153 auto branch =
2154 builder.createCondBranch(getEncodedSourceLocation(loc),
2155 cast<CFGValue>(cond), trueBlock, falseBlock);
James Molloy4f788372018-07-24 15:01:27 -07002156 branch->addTrueOperands(trueOperands);
2157 branch->addFalseOperands(falseOperands);
2158 return branch;
2159 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002160 }
2161}
2162
Chris Lattner48af7d12018-07-09 19:05:38 -07002163//===----------------------------------------------------------------------===//
2164// ML Functions
2165//===----------------------------------------------------------------------===//
2166
2167namespace {
2168/// Refined parser for MLFunction bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07002169class MLFunctionParser : public FunctionParser {
Chris Lattner48af7d12018-07-09 19:05:38 -07002170public:
Chris Lattner48af7d12018-07-09 19:05:38 -07002171 MLFunctionParser(ParserState &state, MLFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07002172 : FunctionParser(state, Kind::MLFunc), function(function),
Chris Lattnere787b322018-08-08 11:14:57 -07002173 builder(function, function->end()) {}
Chris Lattner48af7d12018-07-09 19:05:38 -07002174
2175 ParseResult parseFunctionBody();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002176
2177private:
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002178 MLFunction *function;
2179
2180 /// This builder intentionally shadows the builder in the base class, with a
2181 /// more specific builder type.
2182 MLFuncBuilder builder;
2183
2184 ParseResult parseForStmt();
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002185 ParseResult parseIntConstant(int64_t &val);
2186 ParseResult parseDimAndSymbolList(SmallVectorImpl<MLValue *> &operands,
2187 const AffineMap *map);
2188 ParseResult parseBound(SmallVectorImpl<MLValue *> &operands, AffineMap *&map,
2189 bool isLower);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002190 ParseResult parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002191 ParseResult parseElseClause(IfClause *elseClause);
Uday Bondhugulabc535622018-08-07 14:24:38 -07002192 IntegerSet *parseCondition();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002193 ParseResult parseStatements(StmtBlock *block);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002194 ParseResult parseStmtBlock(StmtBlock *block);
Chris Lattner48af7d12018-07-09 19:05:38 -07002195};
2196} // end anonymous namespace
2197
Chris Lattner48af7d12018-07-09 19:05:38 -07002198ParseResult MLFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07002199 auto braceLoc = getToken().getLoc();
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002200
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002201 // Parse statements in this function.
2202 if (parseStmtBlock(function))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002203 return ParseFailure;
Chris Lattner40746442018-07-21 14:32:09 -07002204
Chris Lattner40746442018-07-21 14:32:09 -07002205 return finalizeFunction(function, braceLoc);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002206}
2207
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002208/// For statement.
2209///
Chris Lattner48af7d12018-07-09 19:05:38 -07002210/// ml-for-stmt ::= `for` ssa-id `=` lower-bound `to` upper-bound
2211/// (`step` integer-literal)? `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002212///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002213ParseResult MLFunctionParser::parseForStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002214 consumeToken(Token::kw_for);
2215
Uday Bondhugula67701712018-08-21 16:01:23 -07002216 // Parse induction variable.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002217 if (getToken().isNot(Token::percent_identifier))
2218 return emitError("expected SSA identifier for the loop variable");
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002219
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002220 auto loc = getToken().getLoc();
Tatiana Shpeismand880b352018-07-31 23:14:16 -07002221 StringRef inductionVariableName = getTokenSpelling();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002222 consumeToken(Token::percent_identifier);
2223
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002224 if (parseToken(Token::equal, "expected '='"))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002225 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002226
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002227 // Parse lower bound.
2228 SmallVector<MLValue *, 4> lbOperands;
2229 AffineMap *lbMap = nullptr;
2230 if (parseBound(lbOperands, lbMap, /*isLower*/ true))
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002231 return ParseFailure;
2232
Chris Lattnerf7702a62018-07-23 17:30:01 -07002233 if (parseToken(Token::kw_to, "expected 'to' between bounds"))
2234 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002235
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002236 // Parse upper bound.
2237 SmallVector<MLValue *, 4> ubOperands;
2238 AffineMap *ubMap = nullptr;
2239 if (parseBound(ubOperands, ubMap, /*isLower*/ false))
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002240 return ParseFailure;
2241
Uday Bondhugula67701712018-08-21 16:01:23 -07002242 // Parse step.
2243 int64_t step = 1;
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002244 if (consumeIf(Token::kw_step) && parseIntConstant(step))
2245 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002246
2247 // Create for statement.
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002248 ForStmt *forStmt =
2249 builder.createFor(getEncodedSourceLocation(loc), lbOperands, lbMap,
2250 ubOperands, ubMap, step);
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002251
2252 // Create SSA value definition for the induction variable.
Chris Lattner2b97d502018-08-06 14:19:46 -07002253 if (addDefinition({inductionVariableName, 0, loc}, forStmt))
2254 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002255
2256 // If parsing of the for statement body fails,
2257 // MLIR contains for statement with those nested statements that have been
2258 // successfully parsed.
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002259 if (parseStmtBlock(forStmt))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002260 return ParseFailure;
2261
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002262 // Reset insertion point to the current block.
Chris Lattnere787b322018-08-08 11:14:57 -07002263 builder.setInsertionPointToEnd(forStmt->getBlock());
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002264
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002265 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002266}
2267
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002268/// Parse integer constant as affine constant expression.
2269ParseResult MLFunctionParser::parseIntConstant(int64_t &val) {
2270 bool negate = consumeIf(Token::minus);
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002271
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002272 if (getToken().isNot(Token::integer))
2273 return emitError("expected integer");
2274
2275 auto uval = getToken().getUInt64IntegerValue();
2276
2277 if (!uval.hasValue() || (int64_t)uval.getValue() < 0) {
2278 return emitError("bound or step is too large for affineint");
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002279 }
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002280
2281 val = (int64_t)uval.getValue();
2282 if (negate)
2283 val = -val;
2284 consumeToken();
2285
2286 return ParseSuccess;
2287}
2288
2289/// Dimensions and symbol use list.
2290///
2291/// dim-use-list ::= `(` ssa-use-list? `)`
2292/// symbol-use-list ::= `[` ssa-use-list? `]`
2293/// dim-and-symbol-use-list ::= dim-use-list symbol-use-list?
2294///
2295ParseResult
2296MLFunctionParser::parseDimAndSymbolList(SmallVectorImpl<MLValue *> &operands,
2297 const AffineMap *map) {
2298 if (parseToken(Token::l_paren, "expected '('"))
2299 return ParseFailure;
2300
2301 SmallVector<SSAUseInfo, 4> opInfo;
2302 parseOptionalSSAUseList(opInfo);
2303
2304 if (parseToken(Token::r_paren, "expected ')'"))
2305 return ParseFailure;
2306
2307 if (map->getNumDims() != opInfo.size())
2308 return emitError("dim operand count and affine map dim count must match");
2309
2310 if (consumeIf(Token::l_square)) {
2311 parseOptionalSSAUseList(opInfo);
2312 if (parseToken(Token::r_square, "expected ']'"))
2313 return ParseFailure;
2314 }
2315
2316 if (map->getNumOperands() != opInfo.size())
2317 return emitError(
2318 "symbol operand count and affine map symbol count must match");
2319
2320 // Resolve SSA uses.
2321 Type *affineIntType = builder.getAffineIntType();
2322 unsigned numDims = map->getNumDims();
2323 for (unsigned i = 0, e = opInfo.size(); i != e; ++i) {
2324 SSAValue *sval = resolveSSAUse(opInfo[i], affineIntType);
2325 if (!sval)
2326 return ParseFailure;
2327
2328 auto *v = cast<MLValue>(sval);
2329 if (i < numDims && !v->isValidDim())
2330 return emitError(opInfo[i].loc, "value '" + opInfo[i].name.str() +
2331 "' cannot be used as dimension id");
2332 if (i >= numDims && !v->isValidSymbol())
2333 return emitError(opInfo[i].loc, "value '" + opInfo[i].name.str() +
2334 "' cannot be used as symbol");
2335 operands.push_back(v);
2336 }
2337
2338 return ParseSuccess;
2339}
2340
2341// Loop bound.
2342///
2343/// lower-bound ::= `max`? affine-map dim-and-symbol-use-list | shorthand-bound
2344/// upper-bound ::= `min`? affine-map dim-and-symbol-use-list | shorthand-bound
2345/// shorthand-bound ::= ssa-id | `-`? integer-literal
2346///
2347ParseResult MLFunctionParser::parseBound(SmallVectorImpl<MLValue *> &operands,
2348 AffineMap *&map, bool isLower) {
2349 // 'min' / 'max' prefixes are syntactic sugar. Ignore them.
2350 if (isLower)
2351 consumeIf(Token::kw_max);
2352 else
2353 consumeIf(Token::kw_min);
2354
2355 // Parse full form - affine map followed by dim and symbol list.
2356 if (getToken().isAny(Token::hash_identifier, Token::l_paren)) {
2357 map = parseAffineMapReference();
2358 if (!map)
2359 return ParseFailure;
2360
2361 if (parseDimAndSymbolList(operands, map))
2362 return ParseFailure;
2363 return ParseSuccess;
2364 }
2365
2366 // Parse shorthand form.
2367 if (getToken().isAny(Token::minus, Token::integer)) {
2368 int64_t val;
2369 if (!parseIntConstant(val)) {
2370 map = builder.getConstantMap(val);
2371 return ParseSuccess;
2372 }
2373 return ParseFailure;
2374 }
2375
2376 // Parse ssa-id as identity map.
2377 SSAUseInfo opInfo;
2378 if (parseSSAUse(opInfo))
2379 return ParseFailure;
2380
2381 // TODO: improve error message when SSA value is not an affine integer.
2382 // Currently it is 'use of value ... expects different type than prior uses'
2383 if (auto *value = resolveSSAUse(opInfo, builder.getAffineIntType()))
2384 operands.push_back(cast<MLValue>(value));
2385 else
2386 return ParseFailure;
2387
2388 // Create an identity map using dim id for an induction variable and
2389 // symbol otherwise. This representation is optimized for storage.
2390 // Analysis passes may expand it into a multi-dimensional map if desired.
2391 if (isa<ForStmt>(operands[0]))
2392 map = builder.getDimIdentityMap();
2393 else
2394 map = builder.getSymbolIdentityMap();
2395
2396 return ParseSuccess;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002397}
2398
Uday Bondhugulabc535622018-08-07 14:24:38 -07002399/// Parse condition.
2400IntegerSet *MLFunctionParser::parseCondition() {
2401 return parseIntegerSetReference();
2402
2403 // TODO: Parse operands to the integer set.
2404}
2405
2406/// Parse an affine constraint.
2407/// affine-constraint ::= affine-expr `>=` `0`
2408/// | affine-expr `==` `0`
2409///
2410/// isEq is set to true if the parsed constraint is an equality, false if it is
2411/// an inequality (greater than or equal).
2412///
2413AffineExpr *AffineParser::parseAffineConstraint(bool *isEq) {
2414 AffineExpr *expr = parseAffineExpr();
2415 if (!expr)
2416 return nullptr;
2417
2418 if (consumeIf(Token::greater) && consumeIf(Token::equal) &&
2419 getToken().is(Token::integer)) {
2420 auto dim = getToken().getUnsignedIntegerValue();
2421 if (dim.hasValue() && dim.getValue() == 0) {
2422 consumeToken(Token::integer);
2423 *isEq = false;
2424 return expr;
2425 }
2426 return (emitError("expected '0' after '>='"), nullptr);
2427 }
2428
2429 if (consumeIf(Token::equal) && consumeIf(Token::equal) &&
2430 getToken().is(Token::integer)) {
2431 auto dim = getToken().getUnsignedIntegerValue();
2432 if (dim.hasValue() && dim.getValue() == 0) {
2433 consumeToken(Token::integer);
2434 *isEq = true;
2435 return expr;
2436 }
2437 return (emitError("expected '0' after '=='"), nullptr);
2438 }
2439
2440 return (emitError("expected '== 0' or '>= 0' at end of affine constraint"),
2441 nullptr);
2442}
2443
2444/// Parse an integer set definition.
2445/// integer-set-inline
2446/// ::= dim-and-symbol-id-lists `:` affine-constraint-conjunction
2447/// affine-constraint-conjunction ::= /*empty*/
2448/// | affine-constraint (`,` affine-constraint)*
2449///
2450IntegerSet *AffineParser::parseIntegerSetInline() {
2451 unsigned numDims = 0, numSymbols = 0;
2452
2453 // List of dimensional identifiers.
2454 if (parseDimIdList(numDims))
2455 return nullptr;
2456
2457 // Symbols are optional.
2458 if (getToken().is(Token::l_square)) {
2459 if (parseSymbolIdList(numSymbols))
2460 return nullptr;
2461 }
2462
2463 if (parseToken(Token::colon, "expected ':' or '['") ||
2464 parseToken(Token::l_paren,
2465 "expected '(' at start of integer set constraint list"))
2466 return nullptr;
2467
2468 SmallVector<AffineExpr *, 4> constraints;
2469 SmallVector<bool, 4> isEqs;
2470 auto parseElt = [&]() -> ParseResult {
2471 bool isEq;
2472 auto *elt = parseAffineConstraint(&isEq);
2473 ParseResult res = elt ? ParseSuccess : ParseFailure;
2474 if (elt) {
2475 constraints.push_back(elt);
2476 isEqs.push_back(isEq);
2477 }
2478 return res;
2479 };
2480
2481 // Parse a list of affine constraints (comma-separated) .
2482 // Grammar: affine-constraint-conjunct ::= `(` affine-constraint (`,`
2483 // affine-constraint)* `)
2484 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt, true))
2485 return nullptr;
2486
2487 // Parsed a valid integer set.
2488 return builder.getIntegerSet(numDims, numSymbols, constraints, isEqs);
2489}
2490
2491IntegerSet *Parser::parseIntegerSetInline() {
2492 return AffineParser(state).parseIntegerSetInline();
2493}
2494
2495/// Parse a reference to an integer set.
2496/// integer-set ::= integer-set-id | integer-set-inline
2497/// integer-set-id ::= `@@` suffix-id
2498///
2499IntegerSet *Parser::parseIntegerSetReference() {
2500 if (getToken().is(Token::double_at_identifier)) {
2501 // Parse integer set identifier and verify that it exists.
2502 StringRef integerSetId = getTokenSpelling().drop_front(2);
2503 if (getState().integerSetDefinitions.count(integerSetId) == 0)
2504 return (emitError("undefined integer set id '" + integerSetId + "'"),
2505 nullptr);
2506 consumeToken(Token::double_at_identifier);
2507 return getState().integerSetDefinitions[integerSetId];
2508 }
2509 // Try to parse an inline integer set definition.
2510 return parseIntegerSetInline();
2511}
2512
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002513/// If statement.
2514///
Chris Lattner48af7d12018-07-09 19:05:38 -07002515/// ml-if-head ::= `if` ml-if-cond `{` ml-stmt* `}`
2516/// | ml-if-head `else` `if` ml-if-cond `{` ml-stmt* `}`
2517/// ml-if-stmt ::= ml-if-head
2518/// | ml-if-head `else` `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002519///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002520ParseResult MLFunctionParser::parseIfStmt() {
Chris Lattner1628fa02018-08-23 14:32:25 -07002521 auto loc = getToken().getLoc();
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002522 consumeToken(Token::kw_if);
Uday Bondhugulabc535622018-08-07 14:24:38 -07002523
2524 if (parseToken(Token::l_paren, "expected '('"))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002525 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002526
Uday Bondhugulabc535622018-08-07 14:24:38 -07002527 IntegerSet *condition = parseCondition();
2528 if (!condition)
Chris Lattnerf7702a62018-07-23 17:30:01 -07002529 return ParseFailure;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002530
Uday Bondhugulabc535622018-08-07 14:24:38 -07002531 if (parseToken(Token::r_paren, "expected ')'"))
2532 return ParseFailure;
2533
Chris Lattner1628fa02018-08-23 14:32:25 -07002534 IfStmt *ifStmt = builder.createIf(getEncodedSourceLocation(loc), condition);
Chris Lattnere787b322018-08-08 11:14:57 -07002535 IfClause *thenClause = ifStmt->getThen();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002536
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002537 // When parsing of an if statement body fails, the IR contains
2538 // the if statement with the portion of the body that has been
2539 // successfully parsed.
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002540 if (parseStmtBlock(thenClause))
2541 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002542
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002543 if (consumeIf(Token::kw_else)) {
Chris Lattnere787b322018-08-08 11:14:57 -07002544 auto *elseClause = ifStmt->createElse();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002545 if (parseElseClause(elseClause))
2546 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002547 }
2548
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002549 // Reset insertion point to the current block.
Chris Lattnere787b322018-08-08 11:14:57 -07002550 builder.setInsertionPointToEnd(ifStmt->getBlock());
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002551
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002552 return ParseSuccess;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002553}
2554
2555ParseResult MLFunctionParser::parseElseClause(IfClause *elseClause) {
2556 if (getToken().is(Token::kw_if)) {
Chris Lattnere787b322018-08-08 11:14:57 -07002557 builder.setInsertionPointToEnd(elseClause);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002558 return parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002559 }
2560
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002561 return parseStmtBlock(elseClause);
2562}
2563
2564///
2565/// Parse a list of statements ending with `return` or `}`
2566///
2567ParseResult MLFunctionParser::parseStatements(StmtBlock *block) {
Chris Lattner992a1272018-08-07 12:02:37 -07002568 auto createOpFunc = [&](const OperationState &state) -> Operation * {
2569 return builder.createOperation(state);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002570 };
2571
Chris Lattnere787b322018-08-08 11:14:57 -07002572 builder.setInsertionPointToEnd(block);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002573
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002574 // Parse statements till we see '}' or 'return'.
2575 // Return statement is parsed separately to emit a more intuitive error
2576 // when '}' is missing after the return statement.
2577 while (getToken().isNot(Token::r_brace, Token::kw_return)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002578 switch (getToken().getKind()) {
2579 default:
2580 if (parseOperation(createOpFunc))
2581 return ParseFailure;
2582 break;
2583 case Token::kw_for:
2584 if (parseForStmt())
2585 return ParseFailure;
2586 break;
2587 case Token::kw_if:
2588 if (parseIfStmt())
2589 return ParseFailure;
2590 break;
2591 } // end switch
2592 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002593
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002594 // Parse the return statement.
2595 if (getToken().is(Token::kw_return))
2596 if (parseOperation(createOpFunc))
2597 return ParseFailure;
2598
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002599 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002600}
2601
2602///
2603/// Parse `{` ml-stmt* `}`
2604///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002605ParseResult MLFunctionParser::parseStmtBlock(StmtBlock *block) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002606 if (parseToken(Token::l_brace, "expected '{' before statement list") ||
2607 parseStatements(block) ||
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002608 parseToken(Token::r_brace, "expected '}' after statement list"))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002609 return ParseFailure;
2610
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002611 return ParseSuccess;
2612}
2613
Chris Lattner4c95a502018-06-23 16:03:42 -07002614//===----------------------------------------------------------------------===//
2615// Top-level entity parsing.
2616//===----------------------------------------------------------------------===//
2617
Chris Lattner2e595eb2018-07-10 10:08:27 -07002618namespace {
2619/// This parser handles entities that are only valid at the top level of the
2620/// file.
2621class ModuleParser : public Parser {
2622public:
2623 explicit ModuleParser(ParserState &state) : Parser(state) {}
2624
2625 ParseResult parseModule();
2626
2627private:
Chris Lattner4613d9e2018-08-19 21:17:22 -07002628 ParseResult finalizeModule();
2629
Chris Lattner2e595eb2018-07-10 10:08:27 -07002630 ParseResult parseAffineMapDef();
Uday Bondhugulabc535622018-08-07 14:24:38 -07002631 ParseResult parseIntegerSetDef();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002632
2633 // Functions.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002634 ParseResult parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2635 SmallVectorImpl<StringRef> &argNames);
2636 ParseResult parseFunctionSignature(StringRef &name, FunctionType *&type,
2637 SmallVectorImpl<StringRef> *argNames);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002638 ParseResult parseExtFunc();
2639 ParseResult parseCFGFunc();
2640 ParseResult parseMLFunc();
2641};
2642} // end anonymous namespace
2643
2644/// Affine map declaration.
2645///
2646/// affine-map-def ::= affine-map-id `=` affine-map-inline
2647///
2648ParseResult ModuleParser::parseAffineMapDef() {
2649 assert(getToken().is(Token::hash_identifier));
2650
2651 StringRef affineMapId = getTokenSpelling().drop_front();
2652
2653 // Check for redefinitions.
Uday Bondhugulabc535622018-08-07 14:24:38 -07002654 auto **entry = &getState().affineMapDefinitions[affineMapId];
2655 if (*entry)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002656 return emitError("redefinition of affine map id '" + affineMapId + "'");
2657
2658 consumeToken(Token::hash_identifier);
2659
2660 // Parse the '='
Chris Lattnerf7702a62018-07-23 17:30:01 -07002661 if (parseToken(Token::equal,
2662 "expected '=' in affine map outlined definition"))
2663 return ParseFailure;
Chris Lattner2e595eb2018-07-10 10:08:27 -07002664
Uday Bondhugulabc535622018-08-07 14:24:38 -07002665 *entry = parseAffineMapInline();
2666 if (!*entry)
2667 return ParseFailure;
2668
2669 return ParseSuccess;
2670}
2671
2672/// Integer set declaration.
2673///
2674/// integer-set-decl ::= integer-set-id `=` integer-set-inline
2675///
2676ParseResult ModuleParser::parseIntegerSetDef() {
2677 assert(getToken().is(Token::double_at_identifier));
2678
2679 StringRef integerSetId = getTokenSpelling().drop_front(2);
2680
2681 // Check for redefinitions (a default entry is created if one doesn't exist)
2682 auto **entry = &getState().integerSetDefinitions[integerSetId];
2683 if (*entry)
2684 return emitError("redefinition of integer set id '" + integerSetId + "'");
2685
2686 consumeToken(Token::double_at_identifier);
2687
2688 // Parse the '='
2689 if (parseToken(Token::equal,
2690 "expected '=' in outlined integer set definition"))
2691 return ParseFailure;
2692
2693 *entry = parseIntegerSetInline();
2694 if (!*entry)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002695 return ParseFailure;
2696
Chris Lattner2e595eb2018-07-10 10:08:27 -07002697 return ParseSuccess;
2698}
2699
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002700/// Parse a (possibly empty) list of MLFunction arguments with types.
2701///
2702/// ml-argument ::= ssa-id `:` type
2703/// ml-argument-list ::= ml-argument (`,` ml-argument)* | /*empty*/
2704///
2705ParseResult
2706ModuleParser::parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2707 SmallVectorImpl<StringRef> &argNames) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002708 consumeToken(Token::l_paren);
2709
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002710 auto parseElt = [&]() -> ParseResult {
2711 // Parse argument name
2712 if (getToken().isNot(Token::percent_identifier))
2713 return emitError("expected SSA identifier");
2714
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002715 StringRef name = getTokenSpelling();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002716 consumeToken(Token::percent_identifier);
2717 argNames.push_back(name);
2718
Chris Lattnerf7702a62018-07-23 17:30:01 -07002719 if (parseToken(Token::colon, "expected ':'"))
2720 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002721
2722 // Parse argument type
2723 auto elt = parseType();
2724 if (!elt)
2725 return ParseFailure;
2726 argTypes.push_back(elt);
2727
2728 return ParseSuccess;
2729 };
2730
Chris Lattner40746442018-07-21 14:32:09 -07002731 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002732}
2733
Chris Lattner2e595eb2018-07-10 10:08:27 -07002734/// Parse a function signature, starting with a name and including the parameter
2735/// list.
2736///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002737/// argument-list ::= type (`,` type)* | /*empty*/ | ml-argument-list
Chris Lattner2e595eb2018-07-10 10:08:27 -07002738/// function-signature ::= function-id `(` argument-list `)` (`->` type-list)?
2739///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002740ParseResult
2741ModuleParser::parseFunctionSignature(StringRef &name, FunctionType *&type,
2742 SmallVectorImpl<StringRef> *argNames) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002743 if (getToken().isNot(Token::at_identifier))
2744 return emitError("expected a function identifier like '@foo'");
2745
2746 name = getTokenSpelling().drop_front();
2747 consumeToken(Token::at_identifier);
2748
2749 if (getToken().isNot(Token::l_paren))
2750 return emitError("expected '(' in function signature");
2751
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002752 SmallVector<Type *, 4> argTypes;
2753 ParseResult parseResult;
2754
2755 if (argNames)
2756 parseResult = parseMLArgumentList(argTypes, *argNames);
2757 else
2758 parseResult = parseTypeList(argTypes);
2759
2760 if (parseResult)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002761 return ParseFailure;
2762
2763 // Parse the return type if present.
2764 SmallVector<Type *, 4> results;
2765 if (consumeIf(Token::arrow)) {
2766 if (parseTypeList(results))
2767 return ParseFailure;
2768 }
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002769 type = builder.getFunctionType(argTypes, results);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002770 return ParseSuccess;
2771}
2772
2773/// External function declarations.
2774///
2775/// ext-func ::= `extfunc` function-signature
2776///
2777ParseResult ModuleParser::parseExtFunc() {
2778 consumeToken(Token::kw_extfunc);
Chris Lattner974a8762018-08-17 16:49:42 -07002779 auto loc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002780
2781 StringRef name;
2782 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002783 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002784 return ParseFailure;
2785
2786 // Okay, the external function definition was parsed correctly.
Chris Lattner974a8762018-08-17 16:49:42 -07002787 auto *function = new ExtFunction(name, type);
2788 getModule()->getFunctions().push_back(function);
2789
2790 // Verify no name collision / redefinition.
Chris Lattner4613d9e2018-08-19 21:17:22 -07002791 if (function->getName() != name)
Chris Lattner974a8762018-08-17 16:49:42 -07002792 return emitError(loc,
2793 "redefinition of function named '" + name.str() + "'");
2794
Chris Lattner2e595eb2018-07-10 10:08:27 -07002795 return ParseSuccess;
2796}
2797
2798/// CFG function declarations.
2799///
2800/// cfg-func ::= `cfgfunc` function-signature `{` basic-block+ `}`
2801///
2802ParseResult ModuleParser::parseCFGFunc() {
2803 consumeToken(Token::kw_cfgfunc);
Chris Lattner974a8762018-08-17 16:49:42 -07002804 auto loc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002805
2806 StringRef name;
2807 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002808 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002809 return ParseFailure;
2810
2811 // Okay, the CFG function signature was parsed correctly, create the function.
Chris Lattner974a8762018-08-17 16:49:42 -07002812 auto *function = new CFGFunction(name, type);
2813 getModule()->getFunctions().push_back(function);
2814
2815 // Verify no name collision / redefinition.
Chris Lattner4613d9e2018-08-19 21:17:22 -07002816 if (function->getName() != name)
Chris Lattner974a8762018-08-17 16:49:42 -07002817 return emitError(loc,
2818 "redefinition of function named '" + name.str() + "'");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002819
2820 return CFGFunctionParser(getState(), function).parseFunctionBody();
2821}
2822
2823/// ML function declarations.
2824///
2825/// ml-func ::= `mlfunc` ml-func-signature `{` ml-stmt* ml-return-stmt `}`
2826///
2827ParseResult ModuleParser::parseMLFunc() {
2828 consumeToken(Token::kw_mlfunc);
2829
2830 StringRef name;
2831 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002832 SmallVector<StringRef, 4> argNames;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002833
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002834 auto loc = getToken().getLoc();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002835 if (parseFunctionSignature(name, type, &argNames))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002836 return ParseFailure;
2837
2838 // Okay, the ML function signature was parsed correctly, create the function.
Chris Lattner974a8762018-08-17 16:49:42 -07002839 auto *function = MLFunction::create(name, type);
2840 getModule()->getFunctions().push_back(function);
2841
2842 // Verify no name collision / redefinition.
Chris Lattner4613d9e2018-08-19 21:17:22 -07002843 if (function->getName() != name)
Chris Lattner974a8762018-08-17 16:49:42 -07002844 return emitError(loc,
2845 "redefinition of function named '" + name.str() + "'");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002846
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002847 // Create the parser.
2848 auto parser = MLFunctionParser(getState(), function);
2849
2850 // Add definitions of the function arguments.
2851 for (unsigned i = 0, e = function->getNumArguments(); i != e; ++i) {
2852 if (parser.addDefinition({argNames[i], 0, loc}, function->getArgument(i)))
2853 return ParseFailure;
2854 }
2855
2856 return parser.parseFunctionBody();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002857}
2858
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002859/// Given an attribute that could refer to a function attribute in the remapping
2860/// table, walk it and rewrite it to use the mapped function. If it doesn't
2861/// refer to anything in the table, then it is returned unmodified.
2862static Attribute *
2863remapFunctionAttrs(Attribute *input,
2864 DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable,
2865 MLIRContext *context) {
2866 // Most attributes are trivially unrelated to function attributes, skip them
2867 // rapidly.
2868 if (!input->isOrContainsFunction())
2869 return input;
2870
2871 // If we have a function attribute, remap it.
2872 if (auto *fnAttr = dyn_cast<FunctionAttr>(input)) {
2873 auto it = remappingTable.find(fnAttr);
2874 return it != remappingTable.end() ? it->second : input;
2875 }
2876
2877 // Otherwise, we must have an array attribute, remap the elements.
2878 auto *arrayAttr = cast<ArrayAttr>(input);
2879 SmallVector<Attribute *, 8> remappedElts;
2880 bool anyChange = false;
2881 for (auto *elt : arrayAttr->getValue()) {
2882 auto *newElt = remapFunctionAttrs(elt, remappingTable, context);
2883 remappedElts.push_back(newElt);
2884 anyChange |= (elt != newElt);
2885 }
2886
2887 if (!anyChange)
2888 return input;
2889
2890 return ArrayAttr::get(remappedElts, context);
2891}
2892
2893/// Remap function attributes to resolve forward references to their actual
2894/// definition.
2895static void remapFunctionAttrsInOperation(
2896 Operation *op, DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable) {
2897 for (auto attr : op->getAttrs()) {
2898 // Do the remapping, if we got the same thing back, then it must contain
2899 // functions that aren't getting remapped.
2900 auto *newVal =
2901 remapFunctionAttrs(attr.second, remappingTable, op->getContext());
2902 if (newVal == attr.second)
2903 continue;
2904
2905 // Otherwise, replace the existing attribute with the new one. It is safe
2906 // to mutate the attribute list while we walk it because underlying
2907 // attribute lists are uniqued and immortal.
2908 op->setAttr(attr.first, newVal);
2909 }
2910}
2911
Chris Lattner4613d9e2018-08-19 21:17:22 -07002912/// Finish the end of module parsing - when the result is valid, do final
2913/// checking.
2914ParseResult ModuleParser::finalizeModule() {
2915
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002916 // Resolve all forward references, building a remapping table of attributes.
2917 DenseMap<FunctionAttr *, FunctionAttr *> remappingTable;
Chris Lattner4613d9e2018-08-19 21:17:22 -07002918 for (auto forwardRef : getState().functionForwardRefs) {
2919 auto name = forwardRef.first;
2920
2921 // Resolve the reference.
2922 auto *resolvedFunction = getModule()->getNamedFunction(name);
2923 if (!resolvedFunction)
2924 return emitError(forwardRef.second.second,
2925 "reference to undefined function '" + name.str() + "'");
2926
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002927 remappingTable[builder.getFunctionAttr(forwardRef.second.first)] =
2928 builder.getFunctionAttr(resolvedFunction);
Chris Lattner4613d9e2018-08-19 21:17:22 -07002929 }
2930
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002931 // If there was nothing to remap, then we're done.
2932 if (remappingTable.empty())
2933 return ParseSuccess;
2934
2935 // Otherwise, walk the entire module replacing uses of one attribute set with
2936 // the correct ones.
2937 for (auto &fn : *getModule()) {
2938 if (auto *cfgFn = dyn_cast<CFGFunction>(&fn)) {
2939 for (auto &bb : *cfgFn) {
2940 for (auto &inst : bb) {
2941 remapFunctionAttrsInOperation(&inst, remappingTable);
2942 }
2943 }
2944 }
2945
2946 // Otherwise, look at MLFunctions. We ignore ExtFunctions.
2947 auto *mlFn = dyn_cast<MLFunction>(&fn);
2948 if (!mlFn)
2949 continue;
2950
2951 struct MLFnWalker : public StmtWalker<MLFnWalker> {
2952 MLFnWalker(DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable)
2953 : remappingTable(remappingTable) {}
2954 void visitOperationStmt(OperationStmt *opStmt) {
2955 remapFunctionAttrsInOperation(opStmt, remappingTable);
2956 }
2957
2958 DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable;
2959 };
2960
2961 MLFnWalker(remappingTable).walk(mlFn);
2962 }
2963
2964 // Now that all references to the forward definition placeholders are
2965 // resolved, we can deallocate the placeholders.
2966 for (auto forwardRef : getState().functionForwardRefs)
2967 forwardRef.second.first->destroy();
Chris Lattner4613d9e2018-08-19 21:17:22 -07002968 return ParseSuccess;
2969}
2970
Chris Lattnere79379a2018-06-22 10:39:19 -07002971/// This is the top-level module parser.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002972ParseResult ModuleParser::parseModule() {
Chris Lattnere79379a2018-06-22 10:39:19 -07002973 while (1) {
Chris Lattner48af7d12018-07-09 19:05:38 -07002974 switch (getToken().getKind()) {
Chris Lattnere79379a2018-06-22 10:39:19 -07002975 default:
2976 emitError("expected a top level entity");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002977 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002978
Uday Bondhugula015cbb12018-07-03 20:16:08 -07002979 // If we got to the end of the file, then we're done.
Chris Lattnere79379a2018-06-22 10:39:19 -07002980 case Token::eof:
Chris Lattner4613d9e2018-08-19 21:17:22 -07002981 return finalizeModule();
Chris Lattnere79379a2018-06-22 10:39:19 -07002982
2983 // If we got an error token, then the lexer already emitted an error, just
2984 // stop. Someday we could introduce error recovery if there was demand for
2985 // it.
2986 case Token::error:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002987 return ParseFailure;
2988
2989 case Token::hash_identifier:
2990 if (parseAffineMapDef())
2991 return ParseFailure;
2992 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002993
Uday Bondhugulabc535622018-08-07 14:24:38 -07002994 case Token::double_at_identifier:
2995 if (parseIntegerSetDef())
2996 return ParseFailure;
2997 break;
2998
Chris Lattnere79379a2018-06-22 10:39:19 -07002999 case Token::kw_extfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07003000 if (parseExtFunc())
3001 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07003002 break;
3003
Chris Lattner4c95a502018-06-23 16:03:42 -07003004 case Token::kw_cfgfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07003005 if (parseCFGFunc())
3006 return ParseFailure;
MLIR Teamf85a6262018-06-27 11:03:08 -07003007 break;
Chris Lattner4c95a502018-06-23 16:03:42 -07003008
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07003009 case Token::kw_mlfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07003010 if (parseMLFunc())
3011 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07003012 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07003013 }
3014 }
3015}
3016
3017//===----------------------------------------------------------------------===//
3018
Jacques Pienaar7b829702018-07-03 13:24:09 -07003019void mlir::defaultErrorReporter(const llvm::SMDiagnostic &error) {
3020 const auto &sourceMgr = *error.getSourceMgr();
3021 sourceMgr.PrintMessage(error.getLoc(), error.getKind(), error.getMessage());
3022}
3023
Chris Lattnere79379a2018-06-22 10:39:19 -07003024/// This parses the file specified by the indicated SourceMgr and returns an
3025/// MLIR module if it was valid. If not, it emits diagnostics and returns null.
Jacques Pienaar9c411be2018-06-24 19:17:35 -07003026Module *mlir::parseSourceFile(llvm::SourceMgr &sourceMgr, MLIRContext *context,
Jacques Pienaar7b829702018-07-03 13:24:09 -07003027 SMDiagnosticHandlerTy errorReporter) {
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003028 if (!errorReporter)
3029 errorReporter = defaultErrorReporter;
3030
3031 // We are going to replace the context's handler and redirect it to use the
3032 // error reporter. Save the existing handler and reinstate it when we're
3033 // done.
3034 auto existingContextHandler = context->getDiagnosticHandler();
3035
3036 // Install a new handler that uses the error reporter.
3037 context->registerDiagnosticHandler([&](Attribute *location, StringRef message,
3038 MLIRContext::DiagnosticKind kind) {
3039 auto offset = cast<IntegerAttr>(location)->getValue();
3040 auto *mainBuffer = sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID());
3041 auto ptr = mainBuffer->getBufferStart() + offset;
3042 SourceMgr::DiagKind diagKind;
3043 switch (kind) {
3044 case MLIRContext::DiagnosticKind::Error:
3045 diagKind = SourceMgr::DK_Error;
3046 break;
3047 case MLIRContext::DiagnosticKind::Warning:
3048 diagKind = SourceMgr::DK_Warning;
3049 break;
3050 case MLIRContext::DiagnosticKind::Note:
3051 diagKind = SourceMgr::DK_Note;
3052 break;
3053 }
3054 errorReporter(
3055 sourceMgr.GetMessage(SMLoc::getFromPointer(ptr), diagKind, message));
3056 });
3057
Chris Lattner2e595eb2018-07-10 10:08:27 -07003058 // This is the result module we are parsing into.
3059 std::unique_ptr<Module> module(new Module(context));
3060
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003061 ParserState state(sourceMgr, module.get(), errorReporter);
3062 if (ModuleParser(state).parseModule()) {
3063 context->registerDiagnosticHandler(existingContextHandler);
Chris Lattner2e595eb2018-07-10 10:08:27 -07003064 return nullptr;
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003065 }
Chris Lattner21e67f62018-07-06 10:46:19 -07003066
3067 // Make sure the parse module has no other structural problems detected by the
3068 // verifier.
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003069 std::string errorResult;
3070 module->verify(&errorResult);
3071
3072 // We don't have location information for general verifier errors, so emit the
3073 // error on the first line.
3074 if (!errorResult.empty()) {
3075 auto *mainBuffer = sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID());
3076 errorReporter(sourceMgr.GetMessage(
3077 SMLoc::getFromPointer(mainBuffer->getBufferStart()),
3078 SourceMgr::DK_Error, errorResult));
3079 return nullptr;
3080 }
3081
3082 context->registerDiagnosticHandler(existingContextHandler);
Chris Lattner2e595eb2018-07-10 10:08:27 -07003083 return module.release();
Chris Lattnere79379a2018-06-22 10:39:19 -07003084}