blob: 093509037410aa09741429a75be3343f88f91d8c [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 Shpeismanc6aa35b2018-08-28 15:26:20 -070028#include "mlir/IR/IntegerSet.h"
Chris Lattnerfc647d52018-08-27 21:05:16 -070029#include "mlir/IR/Location.h"
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -070030#include "mlir/IR/MLFunction.h"
Chris Lattnerea5c3dc2018-08-21 08:42:19 -070031#include "mlir/IR/MLIRContext.h"
Chris Lattner21e67f62018-07-06 10:46:19 -070032#include "mlir/IR/Module.h"
Chris Lattner85ee1512018-07-25 11:15:20 -070033#include "mlir/IR/OpImplementation.h"
Chris Lattner21e67f62018-07-06 10:46:19 -070034#include "mlir/IR/OperationSet.h"
Chris Lattnerea5c3dc2018-08-21 08:42:19 -070035#include "mlir/IR/StmtVisitor.h"
Chris Lattnerf7e22732018-06-22 22:03:48 -070036#include "mlir/IR/Types.h"
James Molloyf0d2f442018-08-03 01:54:46 -070037#include "llvm/ADT/DenseMap.h"
Chris Lattner1aa46322018-08-21 17:55:22 -070038#include "llvm/Support/PrettyStackTrace.h"
James Molloyf0d2f442018-08-03 01:54:46 -070039#include "llvm/Support/SourceMgr.h"
Chris Lattnere79379a2018-06-22 10:39:19 -070040using namespace mlir;
Chris Lattner4c95a502018-06-23 16:03:42 -070041using llvm::SMLoc;
James Molloy0ff71542018-07-23 16:56:32 -070042using llvm::SourceMgr;
Chris Lattnere79379a2018-06-22 10:39:19 -070043
Chris Lattnerf7e22732018-06-22 22:03:48 -070044/// Simple enum to make code read better in cases that would otherwise return a
45/// bool value. Failure is "true" in a boolean context.
James Molloy0ff71542018-07-23 16:56:32 -070046enum ParseResult { ParseSuccess, ParseFailure };
Chris Lattnere79379a2018-06-22 10:39:19 -070047
Chris Lattnerfc647d52018-08-27 21:05:16 -070048/// Return a uniqued filename for the main file the specified SourceMgr is
49/// looking at.
50static UniquedFilename getUniquedFilename(llvm::SourceMgr &sourceMgr,
51 MLIRContext *context) {
52 auto *buffer = sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID());
53 return UniquedFilename::get(buffer->getBufferIdentifier(), context);
54}
55
Chris Lattner48af7d12018-07-09 19:05:38 -070056namespace {
57class Parser;
58
59/// This class refers to all of the state maintained globally by the parser,
60/// such as the current lexer position etc. The Parser base class provides
61/// methods to access this.
62class ParserState {
Chris Lattnered65a732018-06-28 20:45:33 -070063public:
Chris Lattner2e595eb2018-07-10 10:08:27 -070064 ParserState(llvm::SourceMgr &sourceMgr, Module *module,
Chris Lattner48af7d12018-07-09 19:05:38 -070065 SMDiagnosticHandlerTy errorReporter)
Chris Lattner2e595eb2018-07-10 10:08:27 -070066 : context(module->getContext()), module(module),
Chris Lattnerfc647d52018-08-27 21:05:16 -070067 filename(getUniquedFilename(sourceMgr, context)),
Chris Lattner2e595eb2018-07-10 10:08:27 -070068 lex(sourceMgr, errorReporter), curToken(lex.lexToken()),
Chris Lattner85ee1512018-07-25 11:15:20 -070069 errorReporter(errorReporter), operationSet(OperationSet::get(context)) {
70 }
Chris Lattner2e595eb2018-07-10 10:08:27 -070071
72 // A map from affine map identifier to AffineMap.
73 llvm::StringMap<AffineMap *> affineMapDefinitions;
Chris Lattner4613d9e2018-08-19 21:17:22 -070074
Uday Bondhugulabc535622018-08-07 14:24:38 -070075 // A map from integer set identifier to IntegerSet.
76 llvm::StringMap<IntegerSet *> integerSetDefinitions;
Chris Lattnere79379a2018-06-22 10:39:19 -070077
Chris Lattner4613d9e2018-08-19 21:17:22 -070078 // This keeps track of all forward references to functions along with the
79 // temporary function used to represent them and the location of the first
80 // reference.
81 llvm::DenseMap<Identifier, std::pair<Function *, SMLoc>> functionForwardRefs;
82
Chris Lattnere79379a2018-06-22 10:39:19 -070083private:
Chris Lattner48af7d12018-07-09 19:05:38 -070084 ParserState(const ParserState &) = delete;
85 void operator=(const ParserState &) = delete;
86
87 friend class Parser;
88
89 // The context we're parsing into.
Chris Lattner2e595eb2018-07-10 10:08:27 -070090 MLIRContext *const context;
91
92 // This is the module we are parsing into.
93 Module *const module;
Chris Lattnerf7e22732018-06-22 22:03:48 -070094
Chris Lattnerfc647d52018-08-27 21:05:16 -070095 /// The filename to use for location generation.
96 UniquedFilename filename;
97
Chris Lattnerf7e22732018-06-22 22:03:48 -070098 // The lexer for the source file we're parsing.
Chris Lattnere79379a2018-06-22 10:39:19 -070099 Lexer lex;
100
101 // This is the next token that hasn't been consumed yet.
102 Token curToken;
103
Jacques Pienaar9c411be2018-06-24 19:17:35 -0700104 // The diagnostic error reporter.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700105 SMDiagnosticHandlerTy const errorReporter;
Chris Lattner85ee1512018-07-25 11:15:20 -0700106
107 // The active OperationSet we're parsing with.
108 OperationSet &operationSet;
Chris Lattner48af7d12018-07-09 19:05:38 -0700109};
110} // end anonymous namespace
MLIR Teamf85a6262018-06-27 11:03:08 -0700111
Chris Lattner48af7d12018-07-09 19:05:38 -0700112namespace {
113
Chris Lattner992a1272018-08-07 12:02:37 -0700114typedef std::function<Operation *(const OperationState &)>
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700115 CreateOperationFunction;
116
Chris Lattner48af7d12018-07-09 19:05:38 -0700117/// This class implement support for parsing global entities like types and
118/// shared entities like SSA names. It is intended to be subclassed by
119/// specialized subparsers that include state, e.g. when a local symbol table.
120class Parser {
121public:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700122 Builder builder;
Chris Lattner48af7d12018-07-09 19:05:38 -0700123
Chris Lattner2e595eb2018-07-10 10:08:27 -0700124 Parser(ParserState &state) : builder(state.context), state(state) {}
125
126 // Helper methods to get stuff from the parser-global state.
127 ParserState &getState() const { return state; }
Chris Lattner48af7d12018-07-09 19:05:38 -0700128 MLIRContext *getContext() const { return state.context; }
Chris Lattner2e595eb2018-07-10 10:08:27 -0700129 Module *getModule() { return state.module; }
Chris Lattner85ee1512018-07-25 11:15:20 -0700130 OperationSet &getOperationSet() const { return state.operationSet; }
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700131 llvm::SourceMgr &getSourceMgr() { return state.lex.getSourceMgr(); }
Chris Lattner48af7d12018-07-09 19:05:38 -0700132
133 /// Return the current token the parser is inspecting.
134 const Token &getToken() const { return state.curToken; }
135 StringRef getTokenSpelling() const { return state.curToken.getSpelling(); }
Chris Lattnere79379a2018-06-22 10:39:19 -0700136
Chris Lattner1628fa02018-08-23 14:32:25 -0700137 /// Encode the specified source location information into an attribute for
138 /// attachment to the IR.
Chris Lattnerfc647d52018-08-27 21:05:16 -0700139 Location *getEncodedSourceLocation(llvm::SMLoc loc);
Chris Lattner1628fa02018-08-23 14:32:25 -0700140
Chris Lattnere79379a2018-06-22 10:39:19 -0700141 /// Emit an error and return failure.
Chris Lattner4c95a502018-06-23 16:03:42 -0700142 ParseResult emitError(const Twine &message) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700143 return emitError(state.curToken.getLoc(), message);
Chris Lattner4c95a502018-06-23 16:03:42 -0700144 }
145 ParseResult emitError(SMLoc loc, const Twine &message);
Chris Lattnere79379a2018-06-22 10:39:19 -0700146
147 /// Advance the current lexer onto the next token.
148 void consumeToken() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700149 assert(state.curToken.isNot(Token::eof, Token::error) &&
Chris Lattnere79379a2018-06-22 10:39:19 -0700150 "shouldn't advance past EOF or errors");
Chris Lattner48af7d12018-07-09 19:05:38 -0700151 state.curToken = state.lex.lexToken();
Chris Lattnere79379a2018-06-22 10:39:19 -0700152 }
153
154 /// Advance the current lexer onto the next token, asserting what the expected
155 /// current token is. This is preferred to the above method because it leads
156 /// to more self-documenting code with better checking.
Chris Lattner8da0c282018-06-29 11:15:56 -0700157 void consumeToken(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700158 assert(state.curToken.is(kind) && "consumed an unexpected token");
Chris Lattnere79379a2018-06-22 10:39:19 -0700159 consumeToken();
160 }
161
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700162 /// If the current token has the specified kind, consume it and return true.
163 /// If not, return false.
Chris Lattner8da0c282018-06-29 11:15:56 -0700164 bool consumeIf(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700165 if (state.curToken.isNot(kind))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700166 return false;
167 consumeToken(kind);
168 return true;
169 }
170
Chris Lattnerf7702a62018-07-23 17:30:01 -0700171 /// Consume the specified token if present and return success. On failure,
172 /// output a diagnostic and return failure.
173 ParseResult parseToken(Token::Kind expectedToken, const Twine &message);
174
Chris Lattner40746442018-07-21 14:32:09 -0700175 /// Parse a comma-separated list of elements up until the specified end token.
176 ParseResult
177 parseCommaSeparatedListUntil(Token::Kind rightToken,
178 const std::function<ParseResult()> &parseElement,
179 bool allowEmptyList = true);
180
181 /// Parse a comma separated list of elements that must have at least one entry
182 /// in it.
183 ParseResult
184 parseCommaSeparatedList(const std::function<ParseResult()> &parseElement);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700185
Chris Lattnerf7e22732018-06-22 22:03:48 -0700186 // We have two forms of parsing methods - those that return a non-null
187 // pointer on success, and those that return a ParseResult to indicate whether
188 // they returned a failure. The second class fills in by-reference arguments
189 // as the results of their action.
190
Chris Lattnere79379a2018-06-22 10:39:19 -0700191 // Type parsing.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700192 VectorType *parseVectorType();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700193 ParseResult parseDimensionListRanked(SmallVectorImpl<int> &dimensions);
Chris Lattnerf7e22732018-06-22 22:03:48 -0700194 Type *parseTensorType();
195 Type *parseMemRefType();
196 Type *parseFunctionType();
197 Type *parseType();
Chris Lattner1604e472018-07-23 08:42:19 -0700198 ParseResult parseTypeListNoParens(SmallVectorImpl<Type *> &elements);
James Molloy0ff71542018-07-23 16:56:32 -0700199 ParseResult parseTypeList(SmallVectorImpl<Type *> &elements);
Chris Lattnere79379a2018-06-22 10:39:19 -0700200
Chris Lattner7121b802018-07-04 20:45:39 -0700201 // Attribute parsing.
Chris Lattner1aa46322018-08-21 17:55:22 -0700202 Function *resolveFunctionReference(StringRef nameStr, SMLoc nameLoc,
203 FunctionType *type);
Chris Lattner7121b802018-07-04 20:45:39 -0700204 Attribute *parseAttribute();
205 ParseResult parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes);
206
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700207 // Polyhedral structures.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700208 AffineMap *parseAffineMapInline();
MLIR Team718c82f2018-07-16 09:45:22 -0700209 AffineMap *parseAffineMapReference();
Uday Bondhugulabc535622018-08-07 14:24:38 -0700210 IntegerSet *parseIntegerSetInline();
211 IntegerSet *parseIntegerSetReference();
MLIR Teamf85a6262018-06-27 11:03:08 -0700212
Chris Lattner48af7d12018-07-09 19:05:38 -0700213private:
214 // The Parser is subclassed and reinstantiated. Do not add additional
215 // non-trivial state here, add it to the ParserState class.
216 ParserState &state;
Chris Lattnere79379a2018-06-22 10:39:19 -0700217};
218} // end anonymous namespace
219
220//===----------------------------------------------------------------------===//
221// Helper methods.
222//===----------------------------------------------------------------------===//
223
Chris Lattner1628fa02018-08-23 14:32:25 -0700224/// Encode the specified source location information into an attribute for
225/// attachment to the IR.
Chris Lattnerfc647d52018-08-27 21:05:16 -0700226Location *Parser::getEncodedSourceLocation(llvm::SMLoc loc) {
Chris Lattner1628fa02018-08-23 14:32:25 -0700227 auto &sourceMgr = getSourceMgr();
Chris Lattnerfc647d52018-08-27 21:05:16 -0700228 auto lineAndColumn =
229 sourceMgr.getLineAndColumn(loc, sourceMgr.getMainFileID());
Chris Lattner1628fa02018-08-23 14:32:25 -0700230
Chris Lattnerfc647d52018-08-27 21:05:16 -0700231 return FileLineColLoc::get(state.filename, lineAndColumn.first,
232 lineAndColumn.second, getContext());
Chris Lattner1628fa02018-08-23 14:32:25 -0700233}
234
Chris Lattner4c95a502018-06-23 16:03:42 -0700235ParseResult Parser::emitError(SMLoc loc, const Twine &message) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700236 // If we hit a parse error in response to a lexer error, then the lexer
Jacques Pienaar9c411be2018-06-24 19:17:35 -0700237 // already reported the error.
Chris Lattner48af7d12018-07-09 19:05:38 -0700238 if (getToken().is(Token::error))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700239 return ParseFailure;
240
Chris Lattner48af7d12018-07-09 19:05:38 -0700241 auto &sourceMgr = state.lex.getSourceMgr();
242 state.errorReporter(sourceMgr.GetMessage(loc, SourceMgr::DK_Error, message));
Chris Lattnere79379a2018-06-22 10:39:19 -0700243 return ParseFailure;
244}
245
Chris Lattnerf7702a62018-07-23 17:30:01 -0700246/// Consume the specified token if present and return success. On failure,
247/// output a diagnostic and return failure.
248ParseResult Parser::parseToken(Token::Kind expectedToken,
249 const Twine &message) {
250 if (consumeIf(expectedToken))
251 return ParseSuccess;
252 return emitError(message);
253}
254
Chris Lattner40746442018-07-21 14:32:09 -0700255/// Parse a comma separated list of elements that must have at least one entry
256/// in it.
257ParseResult Parser::parseCommaSeparatedList(
258 const std::function<ParseResult()> &parseElement) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700259 // Non-empty case starts with an element.
260 if (parseElement())
261 return ParseFailure;
262
263 // Otherwise we have a list of comma separated elements.
264 while (consumeIf(Token::comma)) {
265 if (parseElement())
266 return ParseFailure;
267 }
Chris Lattner40746442018-07-21 14:32:09 -0700268 return ParseSuccess;
269}
270
271/// Parse a comma-separated list of elements, terminated with an arbitrary
272/// token. This allows empty lists if allowEmptyList is true.
273///
274/// abstract-list ::= rightToken // if allowEmptyList == true
275/// abstract-list ::= element (',' element)* rightToken
276///
277ParseResult Parser::parseCommaSeparatedListUntil(
278 Token::Kind rightToken, const std::function<ParseResult()> &parseElement,
279 bool allowEmptyList) {
280 // Handle the empty case.
281 if (getToken().is(rightToken)) {
282 if (!allowEmptyList)
283 return emitError("expected list element");
284 consumeToken(rightToken);
285 return ParseSuccess;
286 }
287
Chris Lattnerf7702a62018-07-23 17:30:01 -0700288 if (parseCommaSeparatedList(parseElement) ||
289 parseToken(rightToken, "expected ',' or '" +
290 Token::getTokenSpelling(rightToken) + "'"))
Chris Lattner40746442018-07-21 14:32:09 -0700291 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700292
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700293 return ParseSuccess;
294}
Chris Lattnere79379a2018-06-22 10:39:19 -0700295
296//===----------------------------------------------------------------------===//
297// Type Parsing
298//===----------------------------------------------------------------------===//
299
Chris Lattnerc3251192018-07-27 13:09:58 -0700300/// Parse an arbitrary type.
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700301///
Chris Lattnerc3251192018-07-27 13:09:58 -0700302/// type ::= integer-type
303/// | float-type
304/// | other-type
305/// | vector-type
306/// | tensor-type
307/// | memref-type
308/// | function-type
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700309///
Chris Lattnerc3251192018-07-27 13:09:58 -0700310/// float-type ::= `f16` | `bf16` | `f32` | `f64`
311/// other-type ::= `affineint` | `tf_control`
312///
313Type *Parser::parseType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700314 switch (getToken().getKind()) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700315 default:
316 return (emitError("expected type"), nullptr);
Chris Lattnerc3251192018-07-27 13:09:58 -0700317 case Token::kw_memref:
318 return parseMemRefType();
319 case Token::kw_tensor:
320 return parseTensorType();
321 case Token::kw_vector:
322 return parseVectorType();
323 case Token::l_paren:
324 return parseFunctionType();
325 // integer-type
326 case Token::inttype: {
327 auto width = getToken().getIntTypeBitwidth();
328 if (!width.hasValue())
329 return (emitError("invalid integer width"), nullptr);
Nicolas Vasilache1b8c0842018-08-27 10:26:15 -0700330 if (width > IntegerType::kMaxWidth)
331 return (emitError("integer bitwidth is limited to " +
332 Twine(IntegerType::kMaxWidth) + " bits"),
333 nullptr);
Chris Lattnerc3251192018-07-27 13:09:58 -0700334 consumeToken(Token::inttype);
335 return builder.getIntegerType(width.getValue());
336 }
337
338 // float-type
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700339 case Token::kw_bf16:
340 consumeToken(Token::kw_bf16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700341 return builder.getBF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700342 case Token::kw_f16:
343 consumeToken(Token::kw_f16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700344 return builder.getF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700345 case Token::kw_f32:
346 consumeToken(Token::kw_f32);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700347 return builder.getF32Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700348 case Token::kw_f64:
349 consumeToken(Token::kw_f64);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700350 return builder.getF64Type();
Chris Lattnerc3251192018-07-27 13:09:58 -0700351
352 // other-type
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700353 case Token::kw_affineint:
354 consumeToken(Token::kw_affineint);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700355 return builder.getAffineIntType();
Jacques Pienaarc0d69302018-07-27 11:07:12 -0700356 case Token::kw_tf_control:
357 consumeToken(Token::kw_tf_control);
358 return builder.getTFControlType();
James Molloy72b0cbe2018-08-01 12:55:27 -0700359 case Token::kw_tf_string:
360 consumeToken(Token::kw_tf_string);
361 return builder.getTFStringType();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700362 }
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700363}
364
365/// Parse a vector type.
366///
367/// vector-type ::= `vector` `<` const-dimension-list primitive-type `>`
368/// const-dimension-list ::= (integer-literal `x`)+
369///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700370VectorType *Parser::parseVectorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700371 consumeToken(Token::kw_vector);
372
Chris Lattnerf7702a62018-07-23 17:30:01 -0700373 if (parseToken(Token::less, "expected '<' in vector type"))
374 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700375
Chris Lattner48af7d12018-07-09 19:05:38 -0700376 if (getToken().isNot(Token::integer))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700377 return (emitError("expected dimension size in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700378
379 SmallVector<unsigned, 4> dimensions;
Chris Lattner48af7d12018-07-09 19:05:38 -0700380 while (getToken().is(Token::integer)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700381 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700382 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700383 if (!dimension.hasValue())
Chris Lattnerf7e22732018-06-22 22:03:48 -0700384 return (emitError("invalid dimension in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700385 dimensions.push_back(dimension.getValue());
386
387 consumeToken(Token::integer);
388
389 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700390 if (getToken().isNot(Token::bare_identifier) ||
391 getTokenSpelling()[0] != 'x')
Chris Lattnerf7e22732018-06-22 22:03:48 -0700392 return (emitError("expected 'x' in vector dimension list"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700393
394 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700395 if (getTokenSpelling().size() != 1)
396 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700397
398 // Consume the 'x'.
399 consumeToken(Token::bare_identifier);
400 }
401
402 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700403 auto typeLoc = getToken().getLoc();
404 auto *elementType = parseType();
405 if (!elementType || parseToken(Token::greater, "expected '>' in vector type"))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700406 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700407
Chris Lattnerc3251192018-07-27 13:09:58 -0700408 if (!isa<FloatType>(elementType) && !isa<IntegerType>(elementType))
409 return (emitError(typeLoc, "invalid vector element type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700410
Chris Lattnerf7e22732018-06-22 22:03:48 -0700411 return VectorType::get(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700412}
413
414/// Parse a dimension list of a tensor or memref type. This populates the
415/// dimension list, returning -1 for the '?' dimensions.
416///
417/// dimension-list-ranked ::= (dimension `x`)*
418/// dimension ::= `?` | integer-literal
419///
420ParseResult Parser::parseDimensionListRanked(SmallVectorImpl<int> &dimensions) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700421 while (getToken().isAny(Token::integer, Token::question)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700422 if (consumeIf(Token::question)) {
423 dimensions.push_back(-1);
424 } else {
425 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700426 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700427 if (!dimension.hasValue() || (int)dimension.getValue() < 0)
428 return emitError("invalid dimension");
429 dimensions.push_back((int)dimension.getValue());
430 consumeToken(Token::integer);
431 }
432
433 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700434 if (getToken().isNot(Token::bare_identifier) ||
435 getTokenSpelling()[0] != 'x')
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700436 return emitError("expected 'x' in dimension list");
437
438 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700439 if (getTokenSpelling().size() != 1)
440 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700441
442 // Consume the 'x'.
443 consumeToken(Token::bare_identifier);
444 }
445
446 return ParseSuccess;
447}
448
449/// Parse a tensor type.
450///
451/// tensor-type ::= `tensor` `<` dimension-list element-type `>`
452/// dimension-list ::= dimension-list-ranked | `??`
453///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700454Type *Parser::parseTensorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700455 consumeToken(Token::kw_tensor);
456
Chris Lattnerf7702a62018-07-23 17:30:01 -0700457 if (parseToken(Token::less, "expected '<' in tensor type"))
458 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700459
460 bool isUnranked;
461 SmallVector<int, 4> dimensions;
462
463 if (consumeIf(Token::questionquestion)) {
464 isUnranked = true;
465 } else {
466 isUnranked = false;
467 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700468 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700469 }
470
471 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700472 auto typeLoc = getToken().getLoc();
473 auto *elementType = parseType();
474 if (!elementType || parseToken(Token::greater, "expected '>' in tensor type"))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700475 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700476
Chris Lattnerc3251192018-07-27 13:09:58 -0700477 if (!isa<IntegerType>(elementType) && !isa<FloatType>(elementType) &&
478 !isa<VectorType>(elementType))
479 return (emitError(typeLoc, "invalid tensor element type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700480
MLIR Team355ec862018-06-23 18:09:09 -0700481 if (isUnranked)
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700482 return builder.getTensorType(elementType);
483 return builder.getTensorType(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700484}
485
486/// Parse a memref type.
487///
488/// memref-type ::= `memref` `<` dimension-list-ranked element-type
489/// (`,` semi-affine-map-composition)? (`,` memory-space)? `>`
490///
491/// semi-affine-map-composition ::= (semi-affine-map `,` )* semi-affine-map
492/// memory-space ::= integer-literal /* | TODO: address-space-id */
493///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700494Type *Parser::parseMemRefType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700495 consumeToken(Token::kw_memref);
496
Chris Lattnerf7702a62018-07-23 17:30:01 -0700497 if (parseToken(Token::less, "expected '<' in memref type"))
498 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700499
500 SmallVector<int, 4> dimensions;
501 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700502 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700503
504 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700505 auto typeLoc = getToken().getLoc();
506 auto *elementType = parseType();
Chris Lattnerf7e22732018-06-22 22:03:48 -0700507 if (!elementType)
508 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700509
Chris Lattnerc3251192018-07-27 13:09:58 -0700510 if (!isa<IntegerType>(elementType) && !isa<FloatType>(elementType) &&
511 !isa<VectorType>(elementType))
512 return (emitError(typeLoc, "invalid memref element type"), nullptr);
513
MLIR Team718c82f2018-07-16 09:45:22 -0700514 // Parse semi-affine-map-composition.
James Molloy0ff71542018-07-23 16:56:32 -0700515 SmallVector<AffineMap *, 2> affineMapComposition;
Chris Lattner413db6a2018-07-25 12:55:50 -0700516 unsigned memorySpace = 0;
MLIR Team718c82f2018-07-16 09:45:22 -0700517 bool parsedMemorySpace = false;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700518
MLIR Team718c82f2018-07-16 09:45:22 -0700519 auto parseElt = [&]() -> ParseResult {
520 if (getToken().is(Token::integer)) {
521 // Parse memory space.
522 if (parsedMemorySpace)
523 return emitError("multiple memory spaces specified in memref type");
524 auto v = getToken().getUnsignedIntegerValue();
525 if (!v.hasValue())
526 return emitError("invalid memory space in memref type");
527 memorySpace = v.getValue();
528 consumeToken(Token::integer);
529 parsedMemorySpace = true;
530 } else {
531 // Parse affine map.
532 if (parsedMemorySpace)
533 return emitError("affine map after memory space in memref type");
James Molloy0ff71542018-07-23 16:56:32 -0700534 auto *affineMap = parseAffineMapReference();
MLIR Team718c82f2018-07-16 09:45:22 -0700535 if (affineMap == nullptr)
536 return ParseFailure;
537 affineMapComposition.push_back(affineMap);
538 }
539 return ParseSuccess;
540 };
541
Chris Lattner413db6a2018-07-25 12:55:50 -0700542 // Parse a list of mappings and address space if present.
543 if (consumeIf(Token::comma)) {
544 // Parse comma separated list of affine maps, followed by memory space.
545 if (parseCommaSeparatedListUntil(Token::greater, parseElt,
546 /*allowEmptyList=*/false)) {
547 return nullptr;
548 }
549 } else {
550 if (parseToken(Token::greater, "expected ',' or '>' in memref type"))
551 return nullptr;
MLIR Team718c82f2018-07-16 09:45:22 -0700552 }
MLIR Team718c82f2018-07-16 09:45:22 -0700553
554 return MemRefType::get(dimensions, elementType, affineMapComposition,
555 memorySpace);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700556}
557
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700558/// Parse a function type.
559///
560/// function-type ::= type-list-parens `->` type-list
561///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700562Type *Parser::parseFunctionType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700563 assert(getToken().is(Token::l_paren));
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700564
Chris Lattnerf7702a62018-07-23 17:30:01 -0700565 SmallVector<Type *, 4> arguments, results;
566 if (parseTypeList(arguments) ||
567 parseToken(Token::arrow, "expected '->' in function type") ||
568 parseTypeList(results))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700569 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700570
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700571 return builder.getFunctionType(arguments, results);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700572}
573
Chris Lattner1604e472018-07-23 08:42:19 -0700574/// Parse a list of types without an enclosing parenthesis. The list must have
575/// at least one member.
576///
577/// type-list-no-parens ::= type (`,` type)*
578///
579ParseResult Parser::parseTypeListNoParens(SmallVectorImpl<Type *> &elements) {
580 auto parseElt = [&]() -> ParseResult {
581 auto elt = parseType();
582 elements.push_back(elt);
583 return elt ? ParseSuccess : ParseFailure;
584 };
585
586 return parseCommaSeparatedList(parseElt);
587}
588
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700589/// Parse a "type list", which is a singular type, or a parenthesized list of
590/// types.
591///
592/// type-list ::= type-list-parens | type
593/// type-list-parens ::= `(` `)`
Chris Lattner1604e472018-07-23 08:42:19 -0700594/// | `(` type-list-no-parens `)`
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700595///
James Molloy0ff71542018-07-23 16:56:32 -0700596ParseResult Parser::parseTypeList(SmallVectorImpl<Type *> &elements) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700597 auto parseElt = [&]() -> ParseResult {
598 auto elt = parseType();
599 elements.push_back(elt);
600 return elt ? ParseSuccess : ParseFailure;
601 };
602
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700603 // If there is no parens, then it must be a singular type.
604 if (!consumeIf(Token::l_paren))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700605 return parseElt();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700606
Chris Lattner40746442018-07-21 14:32:09 -0700607 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700608 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700609
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700610 return ParseSuccess;
611}
612
Chris Lattner4c95a502018-06-23 16:03:42 -0700613//===----------------------------------------------------------------------===//
Chris Lattner7121b802018-07-04 20:45:39 -0700614// Attribute parsing.
615//===----------------------------------------------------------------------===//
616
Chris Lattner1aa46322018-08-21 17:55:22 -0700617/// Given a parsed reference to a function name like @foo and a type that it
618/// corresponds to, resolve it to a concrete function object (possibly
619/// synthesizing a forward reference) or emit an error and return null on
620/// failure.
621Function *Parser::resolveFunctionReference(StringRef nameStr, SMLoc nameLoc,
622 FunctionType *type) {
623 Identifier name = builder.getIdentifier(nameStr.drop_front());
624
625 // See if the function has already been defined in the module.
626 Function *function = getModule()->getNamedFunction(name);
627
628 // If not, get or create a forward reference to one.
629 if (!function) {
630 auto &entry = state.functionForwardRefs[name];
631 if (!entry.first) {
632 entry.first = new ExtFunction(name, type);
633 entry.second = nameLoc;
634 }
635 function = entry.first;
636 }
637
638 if (function->getType() != type)
639 return (emitError(nameLoc, "reference to function with mismatched type"),
640 nullptr);
641 return function;
642}
643
Chris Lattner7121b802018-07-04 20:45:39 -0700644/// Attribute parsing.
645///
646/// attribute-value ::= bool-literal
647/// | integer-literal
648/// | float-literal
649/// | string-literal
James Molloyf0d2f442018-08-03 01:54:46 -0700650/// | type
Chris Lattner7121b802018-07-04 20:45:39 -0700651/// | `[` (attribute-value (`,` attribute-value)*)? `]`
Chris Lattner4613d9e2018-08-19 21:17:22 -0700652/// | function-id `:` function-type
Chris Lattner7121b802018-07-04 20:45:39 -0700653///
654Attribute *Parser::parseAttribute() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700655 switch (getToken().getKind()) {
Chris Lattner7121b802018-07-04 20:45:39 -0700656 case Token::kw_true:
657 consumeToken(Token::kw_true);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700658 return builder.getBoolAttr(true);
Chris Lattner7121b802018-07-04 20:45:39 -0700659 case Token::kw_false:
660 consumeToken(Token::kw_false);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700661 return builder.getBoolAttr(false);
Chris Lattner7121b802018-07-04 20:45:39 -0700662
Jacques Pienaar84491092018-07-31 17:15:15 -0700663 case Token::floatliteral: {
664 auto val = getToken().getFloatingPointValue();
665 if (!val.hasValue())
666 return (emitError("floating point value too large for attribute"),
667 nullptr);
668 consumeToken(Token::floatliteral);
669 return builder.getFloatAttr(val.getValue());
670 }
Chris Lattner7121b802018-07-04 20:45:39 -0700671 case Token::integer: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700672 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700673 if (!val.hasValue() || (int64_t)val.getValue() < 0)
674 return (emitError("integer too large for attribute"), nullptr);
675 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700676 return builder.getIntegerAttr((int64_t)val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700677 }
678
679 case Token::minus: {
680 consumeToken(Token::minus);
Chris Lattner48af7d12018-07-09 19:05:38 -0700681 if (getToken().is(Token::integer)) {
682 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700683 if (!val.hasValue() || (int64_t)-val.getValue() >= 0)
684 return (emitError("integer too large for attribute"), nullptr);
685 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700686 return builder.getIntegerAttr((int64_t)-val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700687 }
Jacques Pienaar84491092018-07-31 17:15:15 -0700688 if (getToken().is(Token::floatliteral)) {
689 auto val = getToken().getFloatingPointValue();
690 if (!val.hasValue())
691 return (emitError("floating point value too large for attribute"),
692 nullptr);
693 consumeToken(Token::floatliteral);
694 return builder.getFloatAttr(-val.getValue());
695 }
Chris Lattner7121b802018-07-04 20:45:39 -0700696
697 return (emitError("expected constant integer or floating point value"),
698 nullptr);
699 }
700
701 case Token::string: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700702 auto val = getToken().getStringValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700703 consumeToken(Token::string);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700704 return builder.getStringAttr(val);
Chris Lattner7121b802018-07-04 20:45:39 -0700705 }
706
Chris Lattner85ee1512018-07-25 11:15:20 -0700707 case Token::l_square: {
708 consumeToken(Token::l_square);
James Molloy0ff71542018-07-23 16:56:32 -0700709 SmallVector<Attribute *, 4> elements;
Chris Lattner7121b802018-07-04 20:45:39 -0700710
711 auto parseElt = [&]() -> ParseResult {
712 elements.push_back(parseAttribute());
713 return elements.back() ? ParseSuccess : ParseFailure;
714 };
715
Chris Lattner85ee1512018-07-25 11:15:20 -0700716 if (parseCommaSeparatedListUntil(Token::r_square, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700717 return nullptr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700718 return builder.getArrayAttr(elements);
Chris Lattner7121b802018-07-04 20:45:39 -0700719 }
James Molloyf0d2f442018-08-03 01:54:46 -0700720 case Token::hash_identifier:
721 case Token::l_paren: {
MLIR Teamb61885d2018-07-18 16:29:21 -0700722 // Try to parse affine map reference.
James Molloyf0d2f442018-08-03 01:54:46 -0700723 if (auto *affineMap = parseAffineMapReference())
MLIR Teamb61885d2018-07-18 16:29:21 -0700724 return builder.getAffineMapAttr(affineMap);
Chris Lattner7121b802018-07-04 20:45:39 -0700725 return (emitError("expected constant attribute value"), nullptr);
726 }
Chris Lattner4613d9e2018-08-19 21:17:22 -0700727
728 case Token::at_identifier: {
729 auto nameLoc = getToken().getLoc();
Chris Lattner1aa46322018-08-21 17:55:22 -0700730 auto nameStr = getTokenSpelling();
Chris Lattner4613d9e2018-08-19 21:17:22 -0700731 consumeToken(Token::at_identifier);
732
733 if (parseToken(Token::colon, "expected ':' and function type"))
734 return nullptr;
735 auto typeLoc = getToken().getLoc();
736 Type *type = parseType();
737 if (!type)
738 return nullptr;
Chris Lattner1aa46322018-08-21 17:55:22 -0700739 auto *fnType = dyn_cast<FunctionType>(type);
Chris Lattner4613d9e2018-08-19 21:17:22 -0700740 if (!fnType)
741 return (emitError(typeLoc, "expected function type"), nullptr);
742
Chris Lattner1aa46322018-08-21 17:55:22 -0700743 auto *function = resolveFunctionReference(nameStr, nameLoc, fnType);
744 return function ? builder.getFunctionAttr(function) : nullptr;
Chris Lattner4613d9e2018-08-19 21:17:22 -0700745 }
746
James Molloyf0d2f442018-08-03 01:54:46 -0700747 default: {
748 if (Type *type = parseType())
749 return builder.getTypeAttr(type);
750 return nullptr;
751 }
752 }
Chris Lattner7121b802018-07-04 20:45:39 -0700753}
754
Chris Lattner7121b802018-07-04 20:45:39 -0700755/// Attribute dictionary.
756///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700757/// attribute-dict ::= `{` `}`
758/// | `{` attribute-entry (`,` attribute-entry)* `}`
759/// attribute-entry ::= bare-id `:` attribute-value
Chris Lattner7121b802018-07-04 20:45:39 -0700760///
James Molloy0ff71542018-07-23 16:56:32 -0700761ParseResult
762Parser::parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes) {
Chris Lattner7121b802018-07-04 20:45:39 -0700763 consumeToken(Token::l_brace);
764
765 auto parseElt = [&]() -> ParseResult {
766 // We allow keywords as attribute names.
Chris Lattner48af7d12018-07-09 19:05:38 -0700767 if (getToken().isNot(Token::bare_identifier, Token::inttype) &&
768 !getToken().isKeyword())
Chris Lattner7121b802018-07-04 20:45:39 -0700769 return emitError("expected attribute name");
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700770 auto nameId = builder.getIdentifier(getTokenSpelling());
Chris Lattner7121b802018-07-04 20:45:39 -0700771 consumeToken();
772
Chris Lattnerf7702a62018-07-23 17:30:01 -0700773 if (parseToken(Token::colon, "expected ':' in attribute list"))
774 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700775
776 auto attr = parseAttribute();
James Molloy0ff71542018-07-23 16:56:32 -0700777 if (!attr)
778 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700779
780 attributes.push_back({nameId, attr});
781 return ParseSuccess;
782 };
783
Chris Lattner40746442018-07-21 14:32:09 -0700784 if (parseCommaSeparatedListUntil(Token::r_brace, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700785 return ParseFailure;
786
787 return ParseSuccess;
788}
789
790//===----------------------------------------------------------------------===//
MLIR Teamf85a6262018-06-27 11:03:08 -0700791// Polyhedral structures.
792//===----------------------------------------------------------------------===//
793
Chris Lattner2e595eb2018-07-10 10:08:27 -0700794/// Lower precedence ops (all at the same precedence level). LNoOp is false in
795/// the boolean sense.
796enum AffineLowPrecOp {
797 /// Null value.
798 LNoOp,
799 Add,
800 Sub
801};
MLIR Teamf85a6262018-06-27 11:03:08 -0700802
Chris Lattner2e595eb2018-07-10 10:08:27 -0700803/// Higher precedence ops - all at the same precedence level. HNoOp is false in
804/// the boolean sense.
805enum AffineHighPrecOp {
806 /// Null value.
807 HNoOp,
808 Mul,
809 FloorDiv,
810 CeilDiv,
811 Mod
812};
Chris Lattner7121b802018-07-04 20:45:39 -0700813
Chris Lattner2e595eb2018-07-10 10:08:27 -0700814namespace {
Uday Bondhugulabc535622018-08-07 14:24:38 -0700815/// This is a specialized parser for affine structures (affine maps, affine
816/// expressions, and integer sets), maintaining the state transient to their
817/// bodies.
818class AffineParser : public Parser {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700819public:
Uday Bondhugulabc535622018-08-07 14:24:38 -0700820 explicit AffineParser(ParserState &state) : Parser(state) {}
Chris Lattner7121b802018-07-04 20:45:39 -0700821
Chris Lattner2e595eb2018-07-10 10:08:27 -0700822 AffineMap *parseAffineMapInline();
Uday Bondhugulabc535622018-08-07 14:24:38 -0700823 IntegerSet *parseIntegerSetInline();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700824
Chris Lattner2e595eb2018-07-10 10:08:27 -0700825private:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700826 // Binary affine op parsing.
827 AffineLowPrecOp consumeIfLowPrecOp();
828 AffineHighPrecOp consumeIfHighPrecOp();
MLIR Teamf85a6262018-06-27 11:03:08 -0700829
Chris Lattner2e595eb2018-07-10 10:08:27 -0700830 // Identifier lists for polyhedral structures.
Chris Lattner413db6a2018-07-25 12:55:50 -0700831 ParseResult parseDimIdList(unsigned &numDims);
832 ParseResult parseSymbolIdList(unsigned &numSymbols);
833 ParseResult parseIdentifierDefinition(AffineExpr *idExpr);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700834
835 AffineExpr *parseAffineExpr();
836 AffineExpr *parseParentheticalExpr();
837 AffineExpr *parseNegateExpression(AffineExpr *lhs);
838 AffineExpr *parseIntegerExpr();
839 AffineExpr *parseBareIdExpr();
840
841 AffineExpr *getBinaryAffineOpExpr(AffineHighPrecOp op, AffineExpr *lhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700842 AffineExpr *rhs, SMLoc opLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700843 AffineExpr *getBinaryAffineOpExpr(AffineLowPrecOp op, AffineExpr *lhs,
844 AffineExpr *rhs);
845 AffineExpr *parseAffineOperandExpr(AffineExpr *lhs);
846 AffineExpr *parseAffineLowPrecOpExpr(AffineExpr *llhs,
847 AffineLowPrecOp llhsOp);
848 AffineExpr *parseAffineHighPrecOpExpr(AffineExpr *llhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700849 AffineHighPrecOp llhsOp,
850 SMLoc llhsOpLoc);
Uday Bondhugulabc535622018-08-07 14:24:38 -0700851 AffineExpr *parseAffineConstraint(bool *isEq);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700852
853private:
Chris Lattner413db6a2018-07-25 12:55:50 -0700854 SmallVector<std::pair<StringRef, AffineExpr *>, 4> dimsAndSymbols;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700855};
856} // end anonymous namespace
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700857
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700858/// Create an affine binary high precedence op expression (mul's, div's, mod).
859/// opLoc is the location of the op token to be used to report errors
860/// for non-conforming expressions.
Uday Bondhugulabc535622018-08-07 14:24:38 -0700861AffineExpr *AffineParser::getBinaryAffineOpExpr(AffineHighPrecOp op,
862 AffineExpr *lhs,
863 AffineExpr *rhs, SMLoc opLoc) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700864 // TODO: make the error location info accurate.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700865 switch (op) {
866 case Mul:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700867 if (!lhs->isSymbolicOrConstant() && !rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700868 emitError(opLoc, "non-affine expression: at least one of the multiply "
869 "operands has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700870 return nullptr;
871 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700872 return builder.getMulExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700873 case FloorDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700874 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700875 emitError(opLoc, "non-affine expression: right operand of floordiv "
876 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700877 return nullptr;
878 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700879 return builder.getFloorDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700880 case CeilDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700881 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700882 emitError(opLoc, "non-affine expression: right operand of ceildiv "
883 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700884 return nullptr;
885 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700886 return builder.getCeilDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700887 case Mod:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700888 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700889 emitError(opLoc, "non-affine expression: right operand of mod "
890 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700891 return nullptr;
892 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700893 return builder.getModExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700894 case HNoOp:
895 llvm_unreachable("can't create affine expression for null high prec op");
896 return nullptr;
897 }
898}
899
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700900/// Create an affine binary low precedence op expression (add, sub).
Uday Bondhugulabc535622018-08-07 14:24:38 -0700901AffineExpr *AffineParser::getBinaryAffineOpExpr(AffineLowPrecOp op,
902 AffineExpr *lhs,
903 AffineExpr *rhs) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700904 switch (op) {
905 case AffineLowPrecOp::Add:
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700906 return builder.getAddExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700907 case AffineLowPrecOp::Sub:
Uday Bondhugulac1faf662018-07-19 14:08:50 -0700908 return builder.getAddExpr(
909 lhs, builder.getMulExpr(rhs, builder.getConstantExpr(-1)));
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700910 case AffineLowPrecOp::LNoOp:
911 llvm_unreachable("can't create affine expression for null low prec op");
912 return nullptr;
913 }
914}
915
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700916/// Consume this token if it is a lower precedence affine op (there are only two
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700917/// precedence levels).
Uday Bondhugulabc535622018-08-07 14:24:38 -0700918AffineLowPrecOp AffineParser::consumeIfLowPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700919 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700920 case Token::plus:
921 consumeToken(Token::plus);
922 return AffineLowPrecOp::Add;
923 case Token::minus:
924 consumeToken(Token::minus);
925 return AffineLowPrecOp::Sub;
926 default:
927 return AffineLowPrecOp::LNoOp;
928 }
929}
930
931/// Consume this token if it is a higher precedence affine op (there are only
932/// two precedence levels)
Uday Bondhugulabc535622018-08-07 14:24:38 -0700933AffineHighPrecOp AffineParser::consumeIfHighPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700934 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700935 case Token::star:
936 consumeToken(Token::star);
937 return Mul;
938 case Token::kw_floordiv:
939 consumeToken(Token::kw_floordiv);
940 return FloorDiv;
941 case Token::kw_ceildiv:
942 consumeToken(Token::kw_ceildiv);
943 return CeilDiv;
944 case Token::kw_mod:
945 consumeToken(Token::kw_mod);
946 return Mod;
947 default:
948 return HNoOp;
949 }
950}
951
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700952/// Parse a high precedence op expression list: mul, div, and mod are high
953/// precedence binary ops, i.e., parse a
954/// expr_1 op_1 expr_2 op_2 ... expr_n
955/// where op_1, op_2 are all a AffineHighPrecOp (mul, div, mod).
956/// All affine binary ops are left associative.
957/// Given llhs, returns (llhs llhsOp lhs) op rhs, or (lhs op rhs) if llhs is
958/// null. If no rhs can be found, returns (llhs llhsOp lhs) or lhs if llhs is
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700959/// null. llhsOpLoc is the location of the llhsOp token that will be used to
960/// report an error for non-conforming expressions.
Uday Bondhugulabc535622018-08-07 14:24:38 -0700961AffineExpr *AffineParser::parseAffineHighPrecOpExpr(AffineExpr *llhs,
962 AffineHighPrecOp llhsOp,
963 SMLoc llhsOpLoc) {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700964 AffineExpr *lhs = parseAffineOperandExpr(llhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700965 if (!lhs)
966 return nullptr;
967
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700968 // Found an LHS. Parse the remaining expression.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700969 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -0700970 if (AffineHighPrecOp op = consumeIfHighPrecOp()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700971 if (llhs) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700972 AffineExpr *expr = getBinaryAffineOpExpr(llhsOp, llhs, lhs, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700973 if (!expr)
974 return nullptr;
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700975 return parseAffineHighPrecOpExpr(expr, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700976 }
977 // No LLHS, get RHS
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700978 return parseAffineHighPrecOpExpr(lhs, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700979 }
980
981 // This is the last operand in this expression.
982 if (llhs)
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700983 return getBinaryAffineOpExpr(llhsOp, llhs, lhs, llhsOpLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700984
985 // No llhs, 'lhs' itself is the expression.
986 return lhs;
987}
988
989/// Parse an affine expression inside parentheses.
990///
991/// affine-expr ::= `(` affine-expr `)`
Uday Bondhugulabc535622018-08-07 14:24:38 -0700992AffineExpr *AffineParser::parseParentheticalExpr() {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700993 if (parseToken(Token::l_paren, "expected '('"))
994 return nullptr;
Chris Lattner48af7d12018-07-09 19:05:38 -0700995 if (getToken().is(Token::r_paren))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700996 return (emitError("no expression inside parentheses"), nullptr);
Chris Lattnerf7702a62018-07-23 17:30:01 -0700997
Chris Lattner2e595eb2018-07-10 10:08:27 -0700998 auto *expr = parseAffineExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700999 if (!expr)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001000 return nullptr;
Chris Lattnerf7702a62018-07-23 17:30:01 -07001001 if (parseToken(Token::r_paren, "expected ')'"))
1002 return nullptr;
1003
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001004 return expr;
1005}
1006
1007/// Parse the negation expression.
1008///
1009/// affine-expr ::= `-` affine-expr
Uday Bondhugulabc535622018-08-07 14:24:38 -07001010AffineExpr *AffineParser::parseNegateExpression(AffineExpr *lhs) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07001011 if (parseToken(Token::minus, "expected '-'"))
1012 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001013
Chris Lattner2e595eb2018-07-10 10:08:27 -07001014 AffineExpr *operand = parseAffineOperandExpr(lhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001015 // Since negation has the highest precedence of all ops (including high
1016 // precedence ops) but lower than parentheses, we are only going to use
1017 // parseAffineOperandExpr instead of parseAffineExpr here.
1018 if (!operand)
1019 // Extra error message although parseAffineOperandExpr would have
1020 // complained. Leads to a better diagnostic.
1021 return (emitError("missing operand of negation"), nullptr);
Chris Lattner1ac20cb2018-07-10 10:59:53 -07001022 auto *minusOne = builder.getConstantExpr(-1);
1023 return builder.getMulExpr(minusOne, operand);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001024}
1025
1026/// Parse a bare id that may appear in an affine expression.
1027///
1028/// affine-expr ::= bare-id
Uday Bondhugulabc535622018-08-07 14:24:38 -07001029AffineExpr *AffineParser::parseBareIdExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -07001030 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001031 return (emitError("expected bare identifier"), nullptr);
1032
Chris Lattner48af7d12018-07-09 19:05:38 -07001033 StringRef sRef = getTokenSpelling();
Chris Lattner413db6a2018-07-25 12:55:50 -07001034 for (auto entry : dimsAndSymbols) {
Chris Lattnera8e47672018-07-25 14:08:16 -07001035 if (entry.first == sRef) {
1036 consumeToken(Token::bare_identifier);
1037 return entry.second;
1038 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001039 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001040
1041 return (emitError("use of undeclared identifier"), nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001042}
1043
1044/// Parse a positive integral constant appearing in an affine expression.
1045///
1046/// affine-expr ::= integer-literal
Uday Bondhugulabc535622018-08-07 14:24:38 -07001047AffineExpr *AffineParser::parseIntegerExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -07001048 auto val = getToken().getUInt64IntegerValue();
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07001049 if (!val.hasValue() || (int64_t)val.getValue() < 0)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001050 return (emitError("constant too large for affineint"), nullptr);
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07001051
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001052 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -07001053 return builder.getConstantExpr((int64_t)val.getValue());
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001054}
1055
1056/// Parses an expression that can be a valid operand of an affine expression.
Uday Bondhugula76345202018-07-09 13:47:52 -07001057/// lhs: if non-null, lhs is an affine expression that is the lhs of a binary
1058/// operator, the rhs of which is being parsed. This is used to determine
1059/// whether an error should be emitted for a missing right operand.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001060// Eg: for an expression without parentheses (like i + j + k + l), each
1061// of the four identifiers is an operand. For i + j*k + l, j*k is not an
1062// operand expression, it's an op expression and will be parsed via
1063// parseAffineHighPrecOpExpression(). However, for i + (j*k) + -l, (j*k) and -l
1064// are valid operands that will be parsed by this function.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001065AffineExpr *AffineParser::parseAffineOperandExpr(AffineExpr *lhs) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001066 switch (getToken().getKind()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001067 case Token::bare_identifier:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001068 return parseBareIdExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001069 case Token::integer:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001070 return parseIntegerExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001071 case Token::l_paren:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001072 return parseParentheticalExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001073 case Token::minus:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001074 return parseNegateExpression(lhs);
Uday Bondhugula76345202018-07-09 13:47:52 -07001075 case Token::kw_ceildiv:
1076 case Token::kw_floordiv:
1077 case Token::kw_mod:
1078 case Token::plus:
1079 case Token::star:
1080 if (lhs)
1081 emitError("missing right operand of binary operator");
1082 else
1083 emitError("missing left operand of binary operator");
1084 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001085 default:
1086 if (lhs)
Uday Bondhugula76345202018-07-09 13:47:52 -07001087 emitError("missing right operand of binary operator");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001088 else
1089 emitError("expected affine expression");
1090 return nullptr;
1091 }
1092}
1093
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001094/// Parse affine expressions that are bare-id's, integer constants,
1095/// parenthetical affine expressions, and affine op expressions that are a
1096/// composition of those.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001097///
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001098/// All binary op's associate from left to right.
1099///
1100/// {add, sub} have lower precedence than {mul, div, and mod}.
1101///
Uday Bondhugula76345202018-07-09 13:47:52 -07001102/// Add, sub'are themselves at the same precedence level. Mul, floordiv,
1103/// ceildiv, and mod are at the same higher precedence level. Negation has
1104/// higher precedence than any binary op.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001105///
1106/// llhs: the affine expression appearing on the left of the one being parsed.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001107/// This function will return ((llhs llhsOp lhs) op rhs) if llhs is non null,
1108/// and lhs op rhs otherwise; if there is no rhs, llhs llhsOp lhs is returned if
1109/// llhs is non-null; otherwise lhs is returned. This is to deal with left
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001110/// associativity.
1111///
1112/// Eg: when the expression is e1 + e2*e3 + e4, with e1 as llhs, this function
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001113/// will return the affine expr equivalent of (e1 + (e2*e3)) + e4, where (e2*e3)
1114/// will be parsed using parseAffineHighPrecOpExpr().
Uday Bondhugulabc535622018-08-07 14:24:38 -07001115AffineExpr *AffineParser::parseAffineLowPrecOpExpr(AffineExpr *llhs,
1116 AffineLowPrecOp llhsOp) {
Uday Bondhugula76345202018-07-09 13:47:52 -07001117 AffineExpr *lhs;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001118 if (!(lhs = parseAffineOperandExpr(llhs)))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001119 return nullptr;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001120
1121 // Found an LHS. Deal with the ops.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001122 if (AffineLowPrecOp lOp = consumeIfLowPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001123 if (llhs) {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001124 AffineExpr *sum = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001125 return parseAffineLowPrecOpExpr(sum, lOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001126 }
1127 // No LLHS, get RHS and form the expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001128 return parseAffineLowPrecOpExpr(lhs, lOp);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001129 }
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001130 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07001131 if (AffineHighPrecOp hOp = consumeIfHighPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001132 // We have a higher precedence op here. Get the rhs operand for the llhs
1133 // through parseAffineHighPrecOpExpr.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001134 AffineExpr *highRes = parseAffineHighPrecOpExpr(lhs, hOp, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001135 if (!highRes)
1136 return nullptr;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001137
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001138 // If llhs is null, the product forms the first operand of the yet to be
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001139 // found expression. If non-null, the op to associate with llhs is llhsOp.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001140 AffineExpr *expr =
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001141 llhs ? getBinaryAffineOpExpr(llhsOp, llhs, highRes) : highRes;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001142
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001143 // Recurse for subsequent low prec op's after the affine high prec op
1144 // expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001145 if (AffineLowPrecOp nextOp = consumeIfLowPrecOp())
1146 return parseAffineLowPrecOpExpr(expr, nextOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001147 return expr;
1148 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001149 // Last operand in the expression list.
1150 if (llhs)
1151 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
1152 // No llhs, 'lhs' itself is the expression.
1153 return lhs;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001154}
1155
1156/// Parse an affine expression.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001157/// affine-expr ::= `(` affine-expr `)`
1158/// | `-` affine-expr
1159/// | affine-expr `+` affine-expr
1160/// | affine-expr `-` affine-expr
1161/// | affine-expr `*` affine-expr
1162/// | affine-expr `floordiv` affine-expr
1163/// | affine-expr `ceildiv` affine-expr
1164/// | affine-expr `mod` affine-expr
1165/// | bare-id
1166/// | integer-literal
1167///
1168/// Additional conditions are checked depending on the production. For eg., one
1169/// of the operands for `*` has to be either constant/symbolic; the second
1170/// operand for floordiv, ceildiv, and mod has to be a positive integer.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001171AffineExpr *AffineParser::parseAffineExpr() {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001172 return parseAffineLowPrecOpExpr(nullptr, AffineLowPrecOp::LNoOp);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001173}
1174
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001175/// Parse a dim or symbol from the lists appearing before the actual expressions
Chris Lattner2e595eb2018-07-10 10:08:27 -07001176/// of the affine map. Update our state to store the dimensional/symbolic
Chris Lattner413db6a2018-07-25 12:55:50 -07001177/// identifier.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001178ParseResult AffineParser::parseIdentifierDefinition(AffineExpr *idExpr) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001179 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001180 return emitError("expected bare identifier");
Chris Lattner413db6a2018-07-25 12:55:50 -07001181
1182 auto name = getTokenSpelling();
1183 for (auto entry : dimsAndSymbols) {
1184 if (entry.first == name)
1185 return emitError("redefinition of identifier '" + Twine(name) + "'");
1186 }
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001187 consumeToken(Token::bare_identifier);
Chris Lattner413db6a2018-07-25 12:55:50 -07001188
1189 dimsAndSymbols.push_back({name, idExpr});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001190 return ParseSuccess;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001191}
1192
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001193/// Parse the list of symbolic identifiers to an affine map.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001194ParseResult AffineParser::parseSymbolIdList(unsigned &numSymbols) {
Chris Lattner413db6a2018-07-25 12:55:50 -07001195 consumeToken(Token::l_square);
1196 auto parseElt = [&]() -> ParseResult {
1197 auto *symbol = AffineSymbolExpr::get(numSymbols++, getContext());
1198 return parseIdentifierDefinition(symbol);
1199 };
Chris Lattner85ee1512018-07-25 11:15:20 -07001200 return parseCommaSeparatedListUntil(Token::r_square, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001201}
1202
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001203/// Parse the list of dimensional identifiers to an affine map.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001204ParseResult AffineParser::parseDimIdList(unsigned &numDims) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07001205 if (parseToken(Token::l_paren,
1206 "expected '(' at start of dimensional identifiers list"))
1207 return ParseFailure;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001208
Chris Lattner413db6a2018-07-25 12:55:50 -07001209 auto parseElt = [&]() -> ParseResult {
1210 auto *dimension = AffineDimExpr::get(numDims++, getContext());
1211 return parseIdentifierDefinition(dimension);
1212 };
Chris Lattner40746442018-07-21 14:32:09 -07001213 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001214}
1215
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001216/// Parse an affine map definition.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001217///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001218/// affine-map-inline ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
1219/// (`size` `(` dim-size (`,` dim-size)* `)`)?
1220/// dim-size ::= affine-expr | `min` `(` affine-expr ( `,` affine-expr)+ `)`
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001221///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001222/// multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Uday Bondhugulabc535622018-08-07 14:24:38 -07001223AffineMap *AffineParser::parseAffineMapInline() {
Chris Lattner413db6a2018-07-25 12:55:50 -07001224 unsigned numDims = 0, numSymbols = 0;
1225
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001226 // List of dimensional identifiers.
Chris Lattner413db6a2018-07-25 12:55:50 -07001227 if (parseDimIdList(numDims))
Chris Lattner7121b802018-07-04 20:45:39 -07001228 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001229
1230 // Symbols are optional.
Chris Lattner85ee1512018-07-25 11:15:20 -07001231 if (getToken().is(Token::l_square)) {
Chris Lattner413db6a2018-07-25 12:55:50 -07001232 if (parseSymbolIdList(numSymbols))
Chris Lattner7121b802018-07-04 20:45:39 -07001233 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001234 }
Chris Lattnerf7702a62018-07-23 17:30:01 -07001235
1236 if (parseToken(Token::arrow, "expected '->' or '['") ||
1237 parseToken(Token::l_paren, "expected '(' at start of affine map range"))
Chris Lattner7121b802018-07-04 20:45:39 -07001238 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001239
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001240 SmallVector<AffineExpr *, 4> exprs;
1241 auto parseElt = [&]() -> ParseResult {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001242 auto *elt = parseAffineExpr();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001243 ParseResult res = elt ? ParseSuccess : ParseFailure;
1244 exprs.push_back(elt);
1245 return res;
1246 };
1247
1248 // Parse a multi-dimensional affine expression (a comma-separated list of 1-d
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001249 // affine expressions); the list cannot be empty.
1250 // Grammar: multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner40746442018-07-21 14:32:09 -07001251 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt, false))
Chris Lattner7121b802018-07-04 20:45:39 -07001252 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001253
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001254 // Parse optional range sizes.
Uday Bondhugula1e500b42018-07-12 18:04:04 -07001255 // range-sizes ::= (`size` `(` dim-size (`,` dim-size)* `)`)?
1256 // dim-size ::= affine-expr | `min` `(` affine-expr (`,` affine-expr)+ `)`
1257 // TODO(bondhugula): support for min of several affine expressions.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001258 // TODO: check if sizes are non-negative whenever they are constant.
1259 SmallVector<AffineExpr *, 4> rangeSizes;
1260 if (consumeIf(Token::kw_size)) {
1261 // Location of the l_paren token (if it exists) for error reporting later.
1262 auto loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001263 if (parseToken(Token::l_paren, "expected '(' at start of affine map range"))
1264 return nullptr;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001265
1266 auto parseRangeSize = [&]() -> ParseResult {
Chris Lattner413db6a2018-07-25 12:55:50 -07001267 auto loc = getToken().getLoc();
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001268 auto *elt = parseAffineExpr();
Chris Lattner413db6a2018-07-25 12:55:50 -07001269 if (!elt)
1270 return ParseFailure;
1271
1272 if (!elt->isSymbolicOrConstant())
1273 return emitError(loc,
1274 "size expressions cannot refer to dimension values");
1275
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001276 rangeSizes.push_back(elt);
Chris Lattner413db6a2018-07-25 12:55:50 -07001277 return ParseSuccess;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001278 };
1279
Chris Lattner40746442018-07-21 14:32:09 -07001280 if (parseCommaSeparatedListUntil(Token::r_paren, parseRangeSize, false))
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001281 return nullptr;
1282 if (exprs.size() > rangeSizes.size())
1283 return (emitError(loc, "fewer range sizes than range expressions"),
1284 nullptr);
1285 if (exprs.size() < rangeSizes.size())
1286 return (emitError(loc, "more range sizes than range expressions"),
1287 nullptr);
1288 }
1289
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001290 // Parsed a valid affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001291 return builder.getAffineMap(numDims, numSymbols, exprs, rangeSizes);
MLIR Teamf85a6262018-06-27 11:03:08 -07001292}
1293
Chris Lattner2e595eb2018-07-10 10:08:27 -07001294AffineMap *Parser::parseAffineMapInline() {
Uday Bondhugulabc535622018-08-07 14:24:38 -07001295 return AffineParser(state).parseAffineMapInline();
Chris Lattner2e595eb2018-07-10 10:08:27 -07001296}
1297
MLIR Team718c82f2018-07-16 09:45:22 -07001298AffineMap *Parser::parseAffineMapReference() {
1299 if (getToken().is(Token::hash_identifier)) {
1300 // Parse affine map identifier and verify that it exists.
1301 StringRef affineMapId = getTokenSpelling().drop_front();
1302 if (getState().affineMapDefinitions.count(affineMapId) == 0)
1303 return (emitError("undefined affine map id '" + affineMapId + "'"),
1304 nullptr);
1305 consumeToken(Token::hash_identifier);
1306 return getState().affineMapDefinitions[affineMapId];
1307 }
1308 // Try to parse inline affine map.
1309 return parseAffineMapInline();
1310}
1311
MLIR Teamf85a6262018-06-27 11:03:08 -07001312//===----------------------------------------------------------------------===//
Chris Lattner7f9cc272018-07-19 08:35:28 -07001313// FunctionParser
Chris Lattner4c95a502018-06-23 16:03:42 -07001314//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001315
Chris Lattner7f9cc272018-07-19 08:35:28 -07001316namespace {
1317/// This class contains parser state that is common across CFG and ML functions,
1318/// notably for dealing with operations and SSA values.
1319class FunctionParser : public Parser {
1320public:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001321 enum class Kind { CFGFunc, MLFunc };
1322
1323 Kind getKind() const { return kind; }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001324
Chris Lattner6119d382018-07-20 18:41:34 -07001325 /// After the function is finished parsing, this function checks to see if
1326 /// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001327 ParseResult finalizeFunction(Function *func, SMLoc loc);
Chris Lattner6119d382018-07-20 18:41:34 -07001328
1329 /// This represents a use of an SSA value in the program. The first two
1330 /// entries in the tuple are the name and result number of a reference. The
1331 /// third is the location of the reference, which is used in case this ends up
1332 /// being a use of an undefined value.
1333 struct SSAUseInfo {
1334 StringRef name; // Value name, e.g. %42 or %abc
1335 unsigned number; // Number, specified with #12
1336 SMLoc loc; // Location of first definition or use.
1337 };
Chris Lattner7f9cc272018-07-19 08:35:28 -07001338
1339 /// Given a reference to an SSA value and its type, return a reference. This
1340 /// returns null on failure.
1341 SSAValue *resolveSSAUse(SSAUseInfo useInfo, Type *type);
1342
1343 /// Register a definition of a value with the symbol table.
1344 ParseResult addDefinition(SSAUseInfo useInfo, SSAValue *value);
1345
1346 // SSA parsing productions.
1347 ParseResult parseSSAUse(SSAUseInfo &result);
Chris Lattner40746442018-07-21 14:32:09 -07001348 ParseResult parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results);
James Molloy61a656c2018-07-22 15:45:24 -07001349
1350 template <typename ResultType>
1351 ResultType parseSSADefOrUseAndType(
1352 const std::function<ResultType(SSAUseInfo, Type *)> &action);
1353
1354 SSAValue *parseSSAUseAndType() {
1355 return parseSSADefOrUseAndType<SSAValue *>(
1356 [&](SSAUseInfo useInfo, Type *type) -> SSAValue * {
1357 return resolveSSAUse(useInfo, type);
1358 });
1359 }
Chris Lattner40746442018-07-21 14:32:09 -07001360
1361 template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001362 ParseResult
Chris Lattner2c402672018-07-23 11:56:17 -07001363 parseOptionalSSAUseAndTypeList(SmallVectorImpl<ValueTy *> &results,
1364 bool isParenthesized);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001365
1366 // Operations
1367 ParseResult parseOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner85ee1512018-07-25 11:15:20 -07001368 Operation *parseVerboseOperation(const CreateOperationFunction &createOpFunc);
1369 Operation *parseCustomOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001370
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001371protected:
1372 FunctionParser(ParserState &state, Kind kind) : Parser(state), kind(kind) {}
1373
Chris Lattner7f9cc272018-07-19 08:35:28 -07001374private:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001375 /// Kind indicates if this is CFG or ML function parser.
1376 Kind kind;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001377 /// This keeps track of all of the SSA values we are tracking, indexed by
Chris Lattner6119d382018-07-20 18:41:34 -07001378 /// their name. This has one entry per result number.
1379 llvm::StringMap<SmallVector<std::pair<SSAValue *, SMLoc>, 1>> values;
1380
1381 /// These are all of the placeholders we've made along with the location of
1382 /// their first reference, to allow checking for use of undefined values.
1383 DenseMap<SSAValue *, SMLoc> forwardReferencePlaceholders;
1384
1385 SSAValue *createForwardReferencePlaceholder(SMLoc loc, Type *type);
1386
1387 /// Return true if this is a forward reference.
1388 bool isForwardReferencePlaceholder(SSAValue *value) {
1389 return forwardReferencePlaceholders.count(value);
1390 }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001391};
1392} // end anonymous namespace
1393
Chris Lattner6119d382018-07-20 18:41:34 -07001394/// Create and remember a new placeholder for a forward reference.
1395SSAValue *FunctionParser::createForwardReferencePlaceholder(SMLoc loc,
1396 Type *type) {
1397 // Forward references are always created as instructions, even in ML
1398 // functions, because we just need something with a def/use chain.
1399 //
1400 // We create these placeholders as having an empty name, which we know cannot
1401 // be created through normal user input, allowing us to distinguish them.
1402 auto name = Identifier::get("placeholder", getContext());
Chris Lattnerfc647d52018-08-27 21:05:16 -07001403 auto *inst = OperationInst::create(getEncodedSourceLocation(loc), name,
1404 /*operands=*/{}, type,
1405 /*attributes=*/{}, getContext());
Chris Lattner6119d382018-07-20 18:41:34 -07001406 forwardReferencePlaceholders[inst->getResult(0)] = loc;
1407 return inst->getResult(0);
1408}
1409
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001410/// Given an unbound reference to an SSA value and its type, return the value
Chris Lattner7f9cc272018-07-19 08:35:28 -07001411/// it specifies. This returns null on failure.
1412SSAValue *FunctionParser::resolveSSAUse(SSAUseInfo useInfo, Type *type) {
Chris Lattner6119d382018-07-20 18:41:34 -07001413 auto &entries = values[useInfo.name];
1414
Chris Lattner7f9cc272018-07-19 08:35:28 -07001415 // If we have already seen a value of this name, return it.
Chris Lattner6119d382018-07-20 18:41:34 -07001416 if (useInfo.number < entries.size() && entries[useInfo.number].first) {
1417 auto *result = entries[useInfo.number].first;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001418 // Check that the type matches the other uses.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001419 if (result->getType() == type)
1420 return result;
1421
Chris Lattner6119d382018-07-20 18:41:34 -07001422 emitError(useInfo.loc, "use of value '" + useInfo.name.str() +
1423 "' expects different type than prior uses");
1424 emitError(entries[useInfo.number].second, "prior use here");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001425 return nullptr;
1426 }
1427
Chris Lattner6119d382018-07-20 18:41:34 -07001428 // Make sure we have enough slots for this.
1429 if (entries.size() <= useInfo.number)
1430 entries.resize(useInfo.number + 1);
1431
1432 // If the value has already been defined and this is an overly large result
1433 // number, diagnose that.
1434 if (entries[0].first && !isForwardReferencePlaceholder(entries[0].first))
1435 return (emitError(useInfo.loc, "reference to invalid result number"),
1436 nullptr);
1437
Tatiana Shpeismand880b352018-07-31 23:14:16 -07001438 // Otherwise, this is a forward reference. If we are in ML function return
1439 // an error. In CFG function, create a placeholder and remember
1440 // that we did so.
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001441 if (getKind() == Kind::MLFunc)
1442 return (
1443 emitError(useInfo.loc, "use of undefined SSA value " + useInfo.name),
1444 nullptr);
1445
Chris Lattner6119d382018-07-20 18:41:34 -07001446 auto *result = createForwardReferencePlaceholder(useInfo.loc, type);
1447 entries[useInfo.number].first = result;
1448 entries[useInfo.number].second = useInfo.loc;
1449 return result;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001450}
1451
1452/// Register a definition of a value with the symbol table.
1453ParseResult FunctionParser::addDefinition(SSAUseInfo useInfo, SSAValue *value) {
Chris Lattner6119d382018-07-20 18:41:34 -07001454 auto &entries = values[useInfo.name];
Chris Lattner7f9cc272018-07-19 08:35:28 -07001455
Chris Lattner6119d382018-07-20 18:41:34 -07001456 // Make sure there is a slot for this value.
1457 if (entries.size() <= useInfo.number)
1458 entries.resize(useInfo.number + 1);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001459
Chris Lattner6119d382018-07-20 18:41:34 -07001460 // If we already have an entry for this, check to see if it was a definition
1461 // or a forward reference.
1462 if (auto *existing = entries[useInfo.number].first) {
1463 if (!isForwardReferencePlaceholder(existing)) {
1464 emitError(useInfo.loc,
1465 "redefinition of SSA value '" + useInfo.name + "'");
1466 return emitError(entries[useInfo.number].second,
1467 "previously defined here");
1468 }
1469
1470 // If it was a forward reference, update everything that used it to use the
1471 // actual definition instead, delete the forward ref, and remove it from our
1472 // set of forward references we track.
1473 existing->replaceAllUsesWith(value);
1474 existing->getDefiningInst()->destroy();
1475 forwardReferencePlaceholders.erase(existing);
1476 }
1477
1478 entries[useInfo.number].first = value;
1479 entries[useInfo.number].second = useInfo.loc;
1480 return ParseSuccess;
1481}
1482
1483/// After the function is finished parsing, this function checks to see if
1484/// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001485ParseResult FunctionParser::finalizeFunction(Function *func, SMLoc loc) {
Chris Lattner6119d382018-07-20 18:41:34 -07001486 // Check for any forward references that are left. If we find any, error out.
1487 if (!forwardReferencePlaceholders.empty()) {
1488 SmallVector<std::pair<const char *, SSAValue *>, 4> errors;
1489 // Iteration over the map isn't determinstic, so sort by source location.
1490 for (auto entry : forwardReferencePlaceholders)
1491 errors.push_back({entry.second.getPointer(), entry.first});
1492 llvm::array_pod_sort(errors.begin(), errors.end());
1493
1494 for (auto entry : errors)
1495 emitError(SMLoc::getFromPointer(entry.first),
1496 "use of undeclared SSA value name");
1497 return ParseFailure;
1498 }
1499
1500 return ParseSuccess;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001501}
1502
Chris Lattner78276e32018-07-07 15:48:26 -07001503/// Parse a SSA operand for an instruction or statement.
1504///
James Molloy61a656c2018-07-22 15:45:24 -07001505/// ssa-use ::= ssa-id
Chris Lattner78276e32018-07-07 15:48:26 -07001506///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001507ParseResult FunctionParser::parseSSAUse(SSAUseInfo &result) {
Chris Lattner6119d382018-07-20 18:41:34 -07001508 result.name = getTokenSpelling();
1509 result.number = 0;
1510 result.loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001511 if (parseToken(Token::percent_identifier, "expected SSA operand"))
1512 return ParseFailure;
Chris Lattner6119d382018-07-20 18:41:34 -07001513
1514 // If we have an affine map ID, it is a result number.
1515 if (getToken().is(Token::hash_identifier)) {
1516 if (auto value = getToken().getHashIdentifierNumber())
1517 result.number = value.getValue();
1518 else
1519 return emitError("invalid SSA value result number");
1520 consumeToken(Token::hash_identifier);
1521 }
1522
Chris Lattner7f9cc272018-07-19 08:35:28 -07001523 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001524}
1525
1526/// Parse a (possibly empty) list of SSA operands.
1527///
1528/// ssa-use-list ::= ssa-use (`,` ssa-use)*
1529/// ssa-use-list-opt ::= ssa-use-list?
1530///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001531ParseResult
Chris Lattner40746442018-07-21 14:32:09 -07001532FunctionParser::parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results) {
Chris Lattner85ee1512018-07-25 11:15:20 -07001533 if (getToken().isNot(Token::percent_identifier))
Chris Lattner40746442018-07-21 14:32:09 -07001534 return ParseSuccess;
1535 return parseCommaSeparatedList([&]() -> ParseResult {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001536 SSAUseInfo result;
1537 if (parseSSAUse(result))
1538 return ParseFailure;
1539 results.push_back(result);
1540 return ParseSuccess;
1541 });
Chris Lattner78276e32018-07-07 15:48:26 -07001542}
1543
1544/// Parse an SSA use with an associated type.
1545///
1546/// ssa-use-and-type ::= ssa-use `:` type
James Molloy61a656c2018-07-22 15:45:24 -07001547template <typename ResultType>
1548ResultType FunctionParser::parseSSADefOrUseAndType(
1549 const std::function<ResultType(SSAUseInfo, Type *)> &action) {
Chris Lattner78276e32018-07-07 15:48:26 -07001550
Chris Lattnerf7702a62018-07-23 17:30:01 -07001551 SSAUseInfo useInfo;
1552 if (parseSSAUse(useInfo) ||
1553 parseToken(Token::colon, "expected ':' and type for SSA operand"))
1554 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001555
Chris Lattner7f9cc272018-07-19 08:35:28 -07001556 auto *type = parseType();
1557 if (!type)
1558 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001559
James Molloy61a656c2018-07-22 15:45:24 -07001560 return action(useInfo, type);
Chris Lattner78276e32018-07-07 15:48:26 -07001561}
1562
Chris Lattner2c402672018-07-23 11:56:17 -07001563/// Parse a (possibly empty) list of SSA operands, followed by a colon, then
1564/// followed by a type list. If hasParens is true, then the operands are
1565/// surrounded by parens.
Chris Lattner78276e32018-07-07 15:48:26 -07001566///
Chris Lattner2c402672018-07-23 11:56:17 -07001567/// ssa-use-and-type-list[parens]
1568/// ::= `(` ssa-use-list `)` ':' type-list-no-parens
1569///
1570/// ssa-use-and-type-list[!parens]
1571/// ::= ssa-use-list ':' type-list-no-parens
Chris Lattner78276e32018-07-07 15:48:26 -07001572///
Chris Lattner40746442018-07-21 14:32:09 -07001573template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001574ParseResult FunctionParser::parseOptionalSSAUseAndTypeList(
Chris Lattner2c402672018-07-23 11:56:17 -07001575 SmallVectorImpl<ValueTy *> &results, bool isParenthesized) {
1576
1577 // If we are in the parenthesized form and no paren exists, then we succeed
1578 // with an empty list.
1579 if (isParenthesized && !consumeIf(Token::l_paren))
Chris Lattner40746442018-07-21 14:32:09 -07001580 return ParseSuccess;
1581
Chris Lattner2c402672018-07-23 11:56:17 -07001582 SmallVector<SSAUseInfo, 4> valueIDs;
1583 if (parseOptionalSSAUseList(valueIDs))
Chris Lattner7f9cc272018-07-19 08:35:28 -07001584 return ParseFailure;
Chris Lattner2c402672018-07-23 11:56:17 -07001585
1586 if (isParenthesized && !consumeIf(Token::r_paren))
1587 return emitError("expected ')' in operand list");
1588
1589 // If there were no operands, then there is no colon or type lists.
1590 if (valueIDs.empty())
1591 return ParseSuccess;
1592
Chris Lattner2c402672018-07-23 11:56:17 -07001593 SmallVector<Type *, 4> types;
Chris Lattnerf7702a62018-07-23 17:30:01 -07001594 if (parseToken(Token::colon, "expected ':' in operand list") ||
1595 parseTypeListNoParens(types))
Chris Lattner2c402672018-07-23 11:56:17 -07001596 return ParseFailure;
1597
1598 if (valueIDs.size() != types.size())
1599 return emitError("expected " + Twine(valueIDs.size()) +
1600 " types to match operand list");
1601
1602 results.reserve(valueIDs.size());
1603 for (unsigned i = 0, e = valueIDs.size(); i != e; ++i) {
1604 if (auto *value = resolveSSAUse(valueIDs[i], types[i]))
1605 results.push_back(cast<ValueTy>(value));
1606 else
1607 return ParseFailure;
1608 }
1609
1610 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001611}
1612
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001613/// Parse the CFG or MLFunc operation.
1614///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001615/// operation ::=
1616/// (ssa-id `=`)? string '(' ssa-use-list? ')' attribute-dict?
1617/// `:` function-type
1618///
1619ParseResult
Chris Lattner7f9cc272018-07-19 08:35:28 -07001620FunctionParser::parseOperation(const CreateOperationFunction &createOpFunc) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001621 auto loc = getToken().getLoc();
1622
1623 StringRef resultID;
1624 if (getToken().is(Token::percent_identifier)) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001625 resultID = getTokenSpelling();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001626 consumeToken(Token::percent_identifier);
Chris Lattnerf7702a62018-07-23 17:30:01 -07001627 if (parseToken(Token::equal, "expected '=' after SSA name"))
1628 return ParseFailure;
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001629 }
1630
Chris Lattner85ee1512018-07-25 11:15:20 -07001631 Operation *op;
1632 if (getToken().is(Token::bare_identifier) || getToken().isKeyword())
1633 op = parseCustomOperation(createOpFunc);
1634 else if (getToken().is(Token::string))
1635 op = parseVerboseOperation(createOpFunc);
1636 else
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001637 return emitError("expected operation name in quotes");
1638
Chris Lattner85ee1512018-07-25 11:15:20 -07001639 // If parsing of the basic operation failed, then this whole thing fails.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001640 if (!op)
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001641 return ParseFailure;
1642
1643 // We just parsed an operation. If it is a recognized one, verify that it
1644 // is structurally as we expect. If not, produce an error with a reasonable
1645 // source location.
Chris Lattner95865062018-08-01 10:18:59 -07001646 if (auto *opInfo = op->getAbstractOperation()) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001647 if (auto error = opInfo->verifyInvariants(op))
Chris Lattner9361fb32018-07-24 08:34:58 -07001648 return emitError(loc, Twine("'") + op->getName().str() + "' op " + error);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001649 }
1650
Chris Lattner7f9cc272018-07-19 08:35:28 -07001651 // If the instruction had a name, register it.
1652 if (!resultID.empty()) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001653 if (op->getNumResults() == 0)
1654 return emitError(loc, "cannot name an operation with no results");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001655
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001656 for (unsigned i = 0, e = op->getNumResults(); i != e; ++i)
Chris Lattner2b97d502018-08-06 14:19:46 -07001657 if (addDefinition({resultID, i, loc}, op->getResult(i)))
1658 return ParseFailure;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001659 }
1660
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001661 return ParseSuccess;
1662}
Chris Lattnere79379a2018-06-22 10:39:19 -07001663
Chris Lattner85ee1512018-07-25 11:15:20 -07001664Operation *FunctionParser::parseVerboseOperation(
1665 const CreateOperationFunction &createOpFunc) {
Chris Lattner1628fa02018-08-23 14:32:25 -07001666
1667 // Get location information for the operation.
1668 auto *srcLocation = getEncodedSourceLocation(getToken().getLoc());
1669
Chris Lattner85ee1512018-07-25 11:15:20 -07001670 auto name = getToken().getStringValue();
1671 if (name.empty())
1672 return (emitError("empty operation name is invalid"), nullptr);
1673
1674 consumeToken(Token::string);
1675
Chris Lattner1628fa02018-08-23 14:32:25 -07001676 OperationState result(builder.getContext(), srcLocation, name);
Chris Lattner992a1272018-08-07 12:02:37 -07001677
Chris Lattner85ee1512018-07-25 11:15:20 -07001678 // Parse the operand list.
1679 SmallVector<SSAUseInfo, 8> operandInfos;
1680
1681 if (parseToken(Token::l_paren, "expected '(' to start operand list") ||
1682 parseOptionalSSAUseList(operandInfos) ||
1683 parseToken(Token::r_paren, "expected ')' to end operand list")) {
1684 return nullptr;
1685 }
1686
Chris Lattner85ee1512018-07-25 11:15:20 -07001687 if (getToken().is(Token::l_brace)) {
Chris Lattner992a1272018-08-07 12:02:37 -07001688 if (parseAttributeDict(result.attributes))
Chris Lattner85ee1512018-07-25 11:15:20 -07001689 return nullptr;
1690 }
1691
1692 if (parseToken(Token::colon, "expected ':' followed by instruction type"))
1693 return nullptr;
1694
1695 auto typeLoc = getToken().getLoc();
1696 auto type = parseType();
1697 if (!type)
1698 return nullptr;
1699 auto fnType = dyn_cast<FunctionType>(type);
1700 if (!fnType)
1701 return (emitError(typeLoc, "expected function type"), nullptr);
1702
Chris Lattner1eb77482018-08-22 19:25:49 -07001703 result.addTypes(fnType->getResults());
Chris Lattner992a1272018-08-07 12:02:37 -07001704
Chris Lattner85ee1512018-07-25 11:15:20 -07001705 // Check that we have the right number of types for the operands.
1706 auto operandTypes = fnType->getInputs();
1707 if (operandTypes.size() != operandInfos.size()) {
1708 auto plural = "s"[operandInfos.size() == 1];
1709 return (emitError(typeLoc, "expected " + llvm::utostr(operandInfos.size()) +
1710 " operand type" + plural + " but had " +
1711 llvm::utostr(operandTypes.size())),
1712 nullptr);
1713 }
1714
1715 // Resolve all of the operands.
Chris Lattner85ee1512018-07-25 11:15:20 -07001716 for (unsigned i = 0, e = operandInfos.size(); i != e; ++i) {
Chris Lattner992a1272018-08-07 12:02:37 -07001717 result.operands.push_back(resolveSSAUse(operandInfos[i], operandTypes[i]));
1718 if (!result.operands.back())
Chris Lattner85ee1512018-07-25 11:15:20 -07001719 return nullptr;
1720 }
1721
Chris Lattner992a1272018-08-07 12:02:37 -07001722 return createOpFunc(result);
Chris Lattner85ee1512018-07-25 11:15:20 -07001723}
1724
1725namespace {
1726class CustomOpAsmParser : public OpAsmParser {
1727public:
1728 CustomOpAsmParser(SMLoc nameLoc, StringRef opName, FunctionParser &parser)
1729 : nameLoc(nameLoc), opName(opName), parser(parser) {}
1730
Chris Lattner85ee1512018-07-25 11:15:20 -07001731 //===--------------------------------------------------------------------===//
1732 // High level parsing methods.
1733 //===--------------------------------------------------------------------===//
1734
Chris Lattner1aa46322018-08-21 17:55:22 -07001735 bool getCurrentLocation(llvm::SMLoc *loc) override {
1736 *loc = parser.getToken().getLoc();
1737 return false;
1738 }
Chris Lattner091a6b52018-08-23 14:58:27 -07001739 bool parseComma() override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001740 return parser.parseToken(Token::comma, "expected ','");
1741 }
1742
Chris Lattner091a6b52018-08-23 14:58:27 -07001743 bool parseColonType(Type *&result) override {
1744 return parser.parseToken(Token::colon, "expected ':'") ||
1745 !(result = parser.parseType());
Chris Lattner85ee1512018-07-25 11:15:20 -07001746 }
1747
Chris Lattner091a6b52018-08-23 14:58:27 -07001748 bool parseColonTypeList(SmallVectorImpl<Type *> &result) override {
1749 if (parser.parseToken(Token::colon, "expected ':'"))
Chris Lattner85ee1512018-07-25 11:15:20 -07001750 return true;
1751
1752 do {
1753 if (auto *type = parser.parseType())
1754 result.push_back(type);
1755 else
1756 return true;
1757
1758 } while (parser.consumeIf(Token::comma));
1759 return false;
1760 }
1761
Chris Lattner85cf26d2018-08-02 16:54:36 -07001762 /// Parse an arbitrary attribute and return it in result. This also adds the
1763 /// attribute to the specified attribute list with the specified name. this
1764 /// captures the location of the attribute in 'loc' if it is non-null.
1765 bool parseAttribute(Attribute *&result, const char *attrName,
Chris Lattner091a6b52018-08-23 14:58:27 -07001766 SmallVectorImpl<NamedAttribute> &attrs) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001767 result = parser.parseAttribute();
Chris Lattner85cf26d2018-08-02 16:54:36 -07001768 if (!result)
1769 return true;
1770
1771 attrs.push_back(
1772 NamedAttribute(parser.builder.getIdentifier(attrName), result));
1773 return false;
1774 }
1775
1776 /// If a named attribute list is present, parse is into result.
Chris Lattner091a6b52018-08-23 14:58:27 -07001777 bool
1778 parseOptionalAttributeDict(SmallVectorImpl<NamedAttribute> &result) override {
Chris Lattner85cf26d2018-08-02 16:54:36 -07001779 if (parser.getToken().isNot(Token::l_brace))
1780 return false;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001781 return parser.parseAttributeDict(result) == ParseFailure;
Chris Lattner85ee1512018-07-25 11:15:20 -07001782 }
1783
Chris Lattner1aa46322018-08-21 17:55:22 -07001784 /// Parse a function name like '@foo' and return the name in a form that can
1785 /// be passed to resolveFunctionName when a function type is available.
1786 virtual bool parseFunctionName(StringRef &result, llvm::SMLoc &loc) {
1787 loc = parser.getToken().getLoc();
1788
1789 if (parser.getToken().isNot(Token::at_identifier))
1790 return emitError(loc, "expected function name");
1791
1792 result = parser.getTokenSpelling();
1793 parser.consumeToken(Token::at_identifier);
1794 return false;
1795 }
1796
Chris Lattner85ee1512018-07-25 11:15:20 -07001797 bool parseOperand(OperandType &result) override {
1798 FunctionParser::SSAUseInfo useInfo;
1799 if (parser.parseSSAUse(useInfo))
1800 return true;
1801
1802 result = {useInfo.loc, useInfo.name, useInfo.number};
1803 return false;
1804 }
1805
1806 bool parseOperandList(SmallVectorImpl<OperandType> &result,
1807 int requiredOperandCount = -1,
Chris Lattner85cf26d2018-08-02 16:54:36 -07001808 Delimiter delimiter = Delimiter::None) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001809 auto startLoc = parser.getToken().getLoc();
1810
Chris Lattner85cf26d2018-08-02 16:54:36 -07001811 // Handle delimiters.
1812 switch (delimiter) {
1813 case Delimiter::None:
Chris Lattner85ee1512018-07-25 11:15:20 -07001814 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001815 case Delimiter::OptionalParen:
Chris Lattner3164ae62018-07-28 09:36:25 -07001816 if (parser.getToken().isNot(Token::l_paren))
1817 return false;
1818 LLVM_FALLTHROUGH;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001819 case Delimiter::Paren:
Chris Lattner85ee1512018-07-25 11:15:20 -07001820 if (parser.parseToken(Token::l_paren, "expected '(' in operand list"))
1821 return true;
1822 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001823 case Delimiter::OptionalSquare:
Chris Lattner3164ae62018-07-28 09:36:25 -07001824 if (parser.getToken().isNot(Token::l_square))
1825 return false;
1826 LLVM_FALLTHROUGH;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001827 case Delimiter::Square:
Chris Lattner85ee1512018-07-25 11:15:20 -07001828 if (parser.parseToken(Token::l_square, "expected '[' in operand list"))
1829 return true;
1830 break;
1831 }
1832
1833 // Check for zero operands.
1834 if (parser.getToken().is(Token::percent_identifier)) {
1835 do {
1836 OperandType operand;
1837 if (parseOperand(operand))
1838 return true;
1839 result.push_back(operand);
1840 } while (parser.consumeIf(Token::comma));
1841 }
1842
Chris Lattner85cf26d2018-08-02 16:54:36 -07001843 // Handle delimiters. If we reach here, the optional delimiters were
Chris Lattner3164ae62018-07-28 09:36:25 -07001844 // present, so we need to parse their closing one.
Chris Lattner85cf26d2018-08-02 16:54:36 -07001845 switch (delimiter) {
1846 case Delimiter::None:
Chris Lattner85ee1512018-07-25 11:15:20 -07001847 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001848 case Delimiter::OptionalParen:
1849 case Delimiter::Paren:
Chris Lattner85ee1512018-07-25 11:15:20 -07001850 if (parser.parseToken(Token::r_paren, "expected ')' in operand list"))
1851 return true;
1852 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001853 case Delimiter::OptionalSquare:
1854 case Delimiter::Square:
Chris Lattner85ee1512018-07-25 11:15:20 -07001855 if (parser.parseToken(Token::r_square, "expected ']' in operand list"))
1856 return true;
1857 break;
1858 }
1859
1860 if (requiredOperandCount != -1 && result.size() != requiredOperandCount)
1861 emitError(startLoc,
1862 "expected " + Twine(requiredOperandCount) + " operands");
1863 return false;
1864 }
1865
Chris Lattner1aa46322018-08-21 17:55:22 -07001866 /// Resolve a parse function name and a type into a function reference.
1867 virtual bool resolveFunctionName(StringRef name, FunctionType *type,
1868 llvm::SMLoc loc, Function *&result) {
1869 result = parser.resolveFunctionReference(name, loc, type);
1870 return result == nullptr;
1871 }
1872
Chris Lattner85ee1512018-07-25 11:15:20 -07001873 //===--------------------------------------------------------------------===//
1874 // Methods for interacting with the parser
1875 //===--------------------------------------------------------------------===//
1876
1877 Builder &getBuilder() const override { return parser.builder; }
1878
1879 llvm::SMLoc getNameLoc() const override { return nameLoc; }
1880
Chris Lattner1aa46322018-08-21 17:55:22 -07001881 bool resolveOperand(const OperandType &operand, Type *type,
Chris Lattner8bdbebf2018-08-08 11:02:58 -07001882 SmallVectorImpl<SSAValue *> &result) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001883 FunctionParser::SSAUseInfo operandInfo = {operand.name, operand.number,
1884 operand.location};
Chris Lattner8bdbebf2018-08-08 11:02:58 -07001885 if (auto *value = parser.resolveSSAUse(operandInfo, type)) {
1886 result.push_back(value);
1887 return false;
1888 }
1889 return true;
Chris Lattner85ee1512018-07-25 11:15:20 -07001890 }
1891
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001892 /// Emit a diagnostic at the specified location and return true.
1893 bool emitError(llvm::SMLoc loc, const Twine &message) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001894 parser.emitError(loc, "custom op '" + Twine(opName) + "' " + message);
1895 emittedError = true;
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001896 return true;
Chris Lattner85ee1512018-07-25 11:15:20 -07001897 }
1898
1899 bool didEmitError() const { return emittedError; }
1900
1901private:
1902 SMLoc nameLoc;
1903 StringRef opName;
1904 FunctionParser &parser;
1905 bool emittedError = false;
1906};
1907} // end anonymous namespace.
1908
1909Operation *FunctionParser::parseCustomOperation(
1910 const CreateOperationFunction &createOpFunc) {
1911 auto opLoc = getToken().getLoc();
1912 auto opName = getTokenSpelling();
1913 CustomOpAsmParser opAsmParser(opLoc, opName, *this);
1914
1915 auto *opDefinition = getOperationSet().lookup(opName);
1916 if (!opDefinition) {
1917 opAsmParser.emitError(opLoc, "is unknown");
1918 return nullptr;
1919 }
1920
1921 consumeToken();
1922
Chris Lattner1aa46322018-08-21 17:55:22 -07001923 // If the custom op parser crashes, produce some indication to help debugging.
1924 std::string opNameStr = opName.str();
1925 llvm::PrettyStackTraceFormat fmt("MLIR Parser: custom op parser '%s'",
1926 opNameStr.c_str());
1927
Chris Lattner1628fa02018-08-23 14:32:25 -07001928 // Get location information for the operation.
1929 auto *srcLocation = getEncodedSourceLocation(opLoc);
1930
Chris Lattner85ee1512018-07-25 11:15:20 -07001931 // Have the op implementation take a crack and parsing this.
Chris Lattner1628fa02018-08-23 14:32:25 -07001932 OperationState opState(builder.getContext(), srcLocation, opName);
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001933 if (opDefinition->parseAssembly(&opAsmParser, &opState))
1934 return nullptr;
Chris Lattner85ee1512018-07-25 11:15:20 -07001935
1936 // If it emitted an error, we failed.
1937 if (opAsmParser.didEmitError())
1938 return nullptr;
1939
1940 // Otherwise, we succeeded. Use the state it parsed as our op information.
Chris Lattner992a1272018-08-07 12:02:37 -07001941 return createOpFunc(opState);
Chris Lattner85ee1512018-07-25 11:15:20 -07001942}
1943
Chris Lattner48af7d12018-07-09 19:05:38 -07001944//===----------------------------------------------------------------------===//
1945// CFG Functions
1946//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001947
Chris Lattner4c95a502018-06-23 16:03:42 -07001948namespace {
Chris Lattner48af7d12018-07-09 19:05:38 -07001949/// This is a specialized parser for CFGFunction's, maintaining the state
1950/// transient to their bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001951class CFGFunctionParser : public FunctionParser {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001952public:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001953 CFGFunctionParser(ParserState &state, CFGFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001954 : FunctionParser(state, Kind::CFGFunc), function(function),
1955 builder(function) {}
Chris Lattner2e595eb2018-07-10 10:08:27 -07001956
1957 ParseResult parseFunctionBody();
1958
1959private:
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001960 CFGFunction *function;
James Molloy0ff71542018-07-23 16:56:32 -07001961 llvm::StringMap<std::pair<BasicBlock *, SMLoc>> blocksByName;
Chris Lattner48af7d12018-07-09 19:05:38 -07001962
1963 /// This builder intentionally shadows the builder in the base class, with a
1964 /// more specific builder type.
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001965 CFGFuncBuilder builder;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001966
Chris Lattner4c95a502018-06-23 16:03:42 -07001967 /// Get the basic block with the specified name, creating it if it doesn't
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001968 /// already exist. The location specified is the point of use, which allows
1969 /// us to diagnose references to blocks that are not defined precisely.
1970 BasicBlock *getBlockNamed(StringRef name, SMLoc loc) {
1971 auto &blockAndLoc = blocksByName[name];
1972 if (!blockAndLoc.first) {
Chris Lattner3a467cc2018-07-01 20:28:00 -07001973 blockAndLoc.first = new BasicBlock();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001974 blockAndLoc.second = loc;
Chris Lattner4c95a502018-06-23 16:03:42 -07001975 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001976 return blockAndLoc.first;
Chris Lattner4c95a502018-06-23 16:03:42 -07001977 }
Chris Lattner48af7d12018-07-09 19:05:38 -07001978
James Molloy61a656c2018-07-22 15:45:24 -07001979 ParseResult
1980 parseOptionalBasicBlockArgList(SmallVectorImpl<BBArgument *> &results,
1981 BasicBlock *owner);
James Molloy4f788372018-07-24 15:01:27 -07001982 ParseResult parseBranchBlockAndUseList(BasicBlock *&block,
1983 SmallVectorImpl<CFGValue *> &values);
James Molloy61a656c2018-07-22 15:45:24 -07001984
Chris Lattner48af7d12018-07-09 19:05:38 -07001985 ParseResult parseBasicBlock();
Chris Lattner48af7d12018-07-09 19:05:38 -07001986 TerminatorInst *parseTerminator();
Chris Lattner4c95a502018-06-23 16:03:42 -07001987};
1988} // end anonymous namespace
1989
James Molloy61a656c2018-07-22 15:45:24 -07001990/// Parse a (possibly empty) list of SSA operands with types as basic block
Chris Lattner2c402672018-07-23 11:56:17 -07001991/// arguments.
James Molloy61a656c2018-07-22 15:45:24 -07001992///
1993/// ssa-id-and-type-list ::= ssa-id-and-type (`,` ssa-id-and-type)*
1994///
1995ParseResult CFGFunctionParser::parseOptionalBasicBlockArgList(
1996 SmallVectorImpl<BBArgument *> &results, BasicBlock *owner) {
1997 if (getToken().is(Token::r_brace))
1998 return ParseSuccess;
1999
2000 return parseCommaSeparatedList([&]() -> ParseResult {
2001 auto type = parseSSADefOrUseAndType<Type *>(
2002 [&](SSAUseInfo useInfo, Type *type) -> Type * {
2003 BBArgument *arg = owner->addArgument(type);
Chris Lattner2b97d502018-08-06 14:19:46 -07002004 if (addDefinition(useInfo, arg))
James Molloy61a656c2018-07-22 15:45:24 -07002005 return nullptr;
2006 return type;
2007 });
2008 return type ? ParseSuccess : ParseFailure;
2009 });
2010}
2011
Chris Lattner48af7d12018-07-09 19:05:38 -07002012ParseResult CFGFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07002013 auto braceLoc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07002014 if (parseToken(Token::l_brace, "expected '{' in CFG function"))
2015 return ParseFailure;
Chris Lattner48af7d12018-07-09 19:05:38 -07002016
2017 // Make sure we have at least one block.
2018 if (getToken().is(Token::r_brace))
2019 return emitError("CFG functions must have at least one basic block");
Chris Lattner4c95a502018-06-23 16:03:42 -07002020
2021 // Parse the list of blocks.
2022 while (!consumeIf(Token::r_brace))
Chris Lattner48af7d12018-07-09 19:05:38 -07002023 if (parseBasicBlock())
Chris Lattner4c95a502018-06-23 16:03:42 -07002024 return ParseFailure;
2025
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002026 // Verify that all referenced blocks were defined. Iteration over a
2027 // StringMap isn't determinstic, but this is good enough for our purposes.
Chris Lattner48af7d12018-07-09 19:05:38 -07002028 for (auto &elt : blocksByName) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002029 auto *bb = elt.second.first;
Chris Lattner3a467cc2018-07-01 20:28:00 -07002030 if (!bb->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002031 return emitError(elt.second.second,
James Molloy0ff71542018-07-23 16:56:32 -07002032 "reference to an undefined basic block '" + elt.first() +
2033 "'");
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002034 }
2035
Chris Lattner40746442018-07-21 14:32:09 -07002036 return finalizeFunction(function, braceLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07002037}
2038
2039/// Basic block declaration.
2040///
2041/// basic-block ::= bb-label instruction* terminator-stmt
2042/// bb-label ::= bb-id bb-arg-list? `:`
2043/// bb-id ::= bare-id
2044/// bb-arg-list ::= `(` ssa-id-and-type-list? `)`
2045///
Chris Lattner48af7d12018-07-09 19:05:38 -07002046ParseResult CFGFunctionParser::parseBasicBlock() {
2047 SMLoc nameLoc = getToken().getLoc();
2048 auto name = getTokenSpelling();
Chris Lattnerf7702a62018-07-23 17:30:01 -07002049 if (parseToken(Token::bare_identifier, "expected basic block name"))
2050 return ParseFailure;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002051
Chris Lattner48af7d12018-07-09 19:05:38 -07002052 auto *block = getBlockNamed(name, nameLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07002053
2054 // If this block has already been parsed, then this is a redefinition with the
2055 // same block name.
Chris Lattner3a467cc2018-07-01 20:28:00 -07002056 if (block->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002057 return emitError(nameLoc, "redefinition of block '" + name.str() + "'");
2058
Chris Lattner78276e32018-07-07 15:48:26 -07002059 // If an argument list is present, parse it.
2060 if (consumeIf(Token::l_paren)) {
James Molloy61a656c2018-07-22 15:45:24 -07002061 SmallVector<BBArgument *, 8> bbArgs;
Chris Lattnerf7702a62018-07-23 17:30:01 -07002062 if (parseOptionalBasicBlockArgList(bbArgs, block) ||
2063 parseToken(Token::r_paren, "expected ')' to end argument list"))
Chris Lattner78276e32018-07-07 15:48:26 -07002064 return ParseFailure;
Chris Lattner78276e32018-07-07 15:48:26 -07002065 }
Chris Lattner4c95a502018-06-23 16:03:42 -07002066
James Molloy61a656c2018-07-22 15:45:24 -07002067 // Add the block to the function.
2068 function->push_back(block);
2069
Chris Lattnerf7702a62018-07-23 17:30:01 -07002070 if (parseToken(Token::colon, "expected ':' after basic block name"))
2071 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07002072
Chris Lattner158e0a3e2018-07-08 20:51:38 -07002073 // Set the insertion point to the block we want to insert new operations into.
Chris Lattner48af7d12018-07-09 19:05:38 -07002074 builder.setInsertionPoint(block);
Chris Lattner158e0a3e2018-07-08 20:51:38 -07002075
Chris Lattner992a1272018-08-07 12:02:37 -07002076 auto createOpFunc = [&](const OperationState &result) -> Operation * {
2077 return builder.createOperation(result);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002078 };
2079
Chris Lattnered65a732018-06-28 20:45:33 -07002080 // Parse the list of operations that make up the body of the block.
James Molloy4f788372018-07-24 15:01:27 -07002081 while (getToken().isNot(Token::kw_return, Token::kw_br, Token::kw_cond_br)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002082 if (parseOperation(createOpFunc))
Chris Lattnered65a732018-06-28 20:45:33 -07002083 return ParseFailure;
2084 }
Chris Lattner4c95a502018-06-23 16:03:42 -07002085
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002086 if (!parseTerminator())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002087 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07002088
2089 return ParseSuccess;
2090}
2091
James Molloy4f788372018-07-24 15:01:27 -07002092ParseResult CFGFunctionParser::parseBranchBlockAndUseList(
2093 BasicBlock *&block, SmallVectorImpl<CFGValue *> &values) {
2094 block = getBlockNamed(getTokenSpelling(), getToken().getLoc());
2095 if (parseToken(Token::bare_identifier, "expected basic block name"))
2096 return ParseFailure;
2097
2098 if (!consumeIf(Token::l_paren))
2099 return ParseSuccess;
2100 if (parseOptionalSSAUseAndTypeList(values, /*isParenthesized*/ false) ||
2101 parseToken(Token::r_paren, "expected ')' to close argument list"))
2102 return ParseFailure;
2103 return ParseSuccess;
2104}
2105
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002106/// Parse the terminator instruction for a basic block.
2107///
2108/// terminator-stmt ::= `br` bb-id branch-use-list?
Chris Lattner1604e472018-07-23 08:42:19 -07002109/// branch-use-list ::= `(` ssa-use-list `)` ':' type-list-no-parens
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002110/// terminator-stmt ::=
2111/// `cond_br` ssa-use `,` bb-id branch-use-list? `,` bb-id branch-use-list?
2112/// terminator-stmt ::= `return` ssa-use-and-type-list?
2113///
Chris Lattner48af7d12018-07-09 19:05:38 -07002114TerminatorInst *CFGFunctionParser::parseTerminator() {
Chris Lattner1628fa02018-08-23 14:32:25 -07002115 auto loc = getToken().getLoc();
2116
Chris Lattner48af7d12018-07-09 19:05:38 -07002117 switch (getToken().getKind()) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002118 default:
Chris Lattner3a467cc2018-07-01 20:28:00 -07002119 return (emitError("expected terminator at end of basic block"), nullptr);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002120
Chris Lattner40746442018-07-21 14:32:09 -07002121 case Token::kw_return: {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002122 consumeToken(Token::kw_return);
Chris Lattner40746442018-07-21 14:32:09 -07002123
Chris Lattner2c402672018-07-23 11:56:17 -07002124 // Parse any operands.
2125 SmallVector<CFGValue *, 8> operands;
2126 if (parseOptionalSSAUseAndTypeList(operands, /*isParenthesized*/ false))
2127 return nullptr;
Chris Lattner091a6b52018-08-23 14:58:27 -07002128 return builder.createReturn(getEncodedSourceLocation(loc), operands);
Chris Lattner40746442018-07-21 14:32:09 -07002129 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002130
2131 case Token::kw_br: {
2132 consumeToken(Token::kw_br);
James Molloy4f788372018-07-24 15:01:27 -07002133 BasicBlock *destBB;
2134 SmallVector<CFGValue *, 4> values;
2135 if (parseBranchBlockAndUseList(destBB, values))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002136 return nullptr;
Chris Lattner091a6b52018-08-23 14:58:27 -07002137 auto branch = builder.createBranch(getEncodedSourceLocation(loc), destBB);
James Molloy4f788372018-07-24 15:01:27 -07002138 branch->addOperands(values);
Chris Lattner1604e472018-07-23 08:42:19 -07002139 return branch;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002140 }
James Molloy4f788372018-07-24 15:01:27 -07002141
2142 case Token::kw_cond_br: {
2143 consumeToken(Token::kw_cond_br);
2144 SSAUseInfo ssaUse;
2145 if (parseSSAUse(ssaUse))
2146 return nullptr;
2147 auto *cond = resolveSSAUse(ssaUse, builder.getIntegerType(1));
2148 if (!cond)
2149 return (emitError("expected type was boolean (i1)"), nullptr);
2150 if (parseToken(Token::comma, "expected ',' in conditional branch"))
2151 return nullptr;
2152
2153 BasicBlock *trueBlock;
2154 SmallVector<CFGValue *, 4> trueOperands;
2155 if (parseBranchBlockAndUseList(trueBlock, trueOperands))
2156 return nullptr;
2157
2158 if (parseToken(Token::comma, "expected ',' in conditional branch"))
2159 return nullptr;
2160
2161 BasicBlock *falseBlock;
2162 SmallVector<CFGValue *, 4> falseOperands;
2163 if (parseBranchBlockAndUseList(falseBlock, falseOperands))
2164 return nullptr;
2165
Chris Lattner091a6b52018-08-23 14:58:27 -07002166 auto branch =
2167 builder.createCondBranch(getEncodedSourceLocation(loc),
2168 cast<CFGValue>(cond), trueBlock, falseBlock);
James Molloy4f788372018-07-24 15:01:27 -07002169 branch->addTrueOperands(trueOperands);
2170 branch->addFalseOperands(falseOperands);
2171 return branch;
2172 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002173 }
2174}
2175
Chris Lattner48af7d12018-07-09 19:05:38 -07002176//===----------------------------------------------------------------------===//
2177// ML Functions
2178//===----------------------------------------------------------------------===//
2179
2180namespace {
2181/// Refined parser for MLFunction bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07002182class MLFunctionParser : public FunctionParser {
Chris Lattner48af7d12018-07-09 19:05:38 -07002183public:
Chris Lattner48af7d12018-07-09 19:05:38 -07002184 MLFunctionParser(ParserState &state, MLFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07002185 : FunctionParser(state, Kind::MLFunc), function(function),
Chris Lattnere787b322018-08-08 11:14:57 -07002186 builder(function, function->end()) {}
Chris Lattner48af7d12018-07-09 19:05:38 -07002187
2188 ParseResult parseFunctionBody();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002189
2190private:
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002191 MLFunction *function;
2192
2193 /// This builder intentionally shadows the builder in the base class, with a
2194 /// more specific builder type.
2195 MLFuncBuilder builder;
2196
2197 ParseResult parseForStmt();
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002198 ParseResult parseIntConstant(int64_t &val);
2199 ParseResult parseDimAndSymbolList(SmallVectorImpl<MLValue *> &operands,
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002200 unsigned numDims, unsigned numOperands,
2201 const char *affineStructName);
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002202 ParseResult parseBound(SmallVectorImpl<MLValue *> &operands, AffineMap *&map,
2203 bool isLower);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002204 ParseResult parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002205 ParseResult parseElseClause(IfClause *elseClause);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002206 ParseResult parseStatements(StmtBlock *block);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002207 ParseResult parseStmtBlock(StmtBlock *block);
Chris Lattner48af7d12018-07-09 19:05:38 -07002208};
2209} // end anonymous namespace
2210
Chris Lattner48af7d12018-07-09 19:05:38 -07002211ParseResult MLFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07002212 auto braceLoc = getToken().getLoc();
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002213
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002214 // Parse statements in this function.
2215 if (parseStmtBlock(function))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002216 return ParseFailure;
Chris Lattner40746442018-07-21 14:32:09 -07002217
Chris Lattner40746442018-07-21 14:32:09 -07002218 return finalizeFunction(function, braceLoc);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002219}
2220
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002221/// For statement.
2222///
Chris Lattner48af7d12018-07-09 19:05:38 -07002223/// ml-for-stmt ::= `for` ssa-id `=` lower-bound `to` upper-bound
2224/// (`step` integer-literal)? `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002225///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002226ParseResult MLFunctionParser::parseForStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002227 consumeToken(Token::kw_for);
2228
Uday Bondhugula67701712018-08-21 16:01:23 -07002229 // Parse induction variable.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002230 if (getToken().isNot(Token::percent_identifier))
2231 return emitError("expected SSA identifier for the loop variable");
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002232
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002233 auto loc = getToken().getLoc();
Tatiana Shpeismand880b352018-07-31 23:14:16 -07002234 StringRef inductionVariableName = getTokenSpelling();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002235 consumeToken(Token::percent_identifier);
2236
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002237 if (parseToken(Token::equal, "expected '='"))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002238 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002239
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002240 // Parse lower bound.
2241 SmallVector<MLValue *, 4> lbOperands;
2242 AffineMap *lbMap = nullptr;
2243 if (parseBound(lbOperands, lbMap, /*isLower*/ true))
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002244 return ParseFailure;
2245
Chris Lattnerf7702a62018-07-23 17:30:01 -07002246 if (parseToken(Token::kw_to, "expected 'to' between bounds"))
2247 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002248
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002249 // Parse upper bound.
2250 SmallVector<MLValue *, 4> ubOperands;
2251 AffineMap *ubMap = nullptr;
2252 if (parseBound(ubOperands, ubMap, /*isLower*/ false))
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002253 return ParseFailure;
2254
Uday Bondhugula67701712018-08-21 16:01:23 -07002255 // Parse step.
2256 int64_t step = 1;
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002257 if (consumeIf(Token::kw_step) && parseIntConstant(step))
2258 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002259
2260 // Create for statement.
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002261 ForStmt *forStmt =
2262 builder.createFor(getEncodedSourceLocation(loc), lbOperands, lbMap,
2263 ubOperands, ubMap, step);
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002264
2265 // Create SSA value definition for the induction variable.
Chris Lattner2b97d502018-08-06 14:19:46 -07002266 if (addDefinition({inductionVariableName, 0, loc}, forStmt))
2267 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002268
2269 // If parsing of the for statement body fails,
2270 // MLIR contains for statement with those nested statements that have been
2271 // successfully parsed.
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002272 if (parseStmtBlock(forStmt))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002273 return ParseFailure;
2274
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002275 // Reset insertion point to the current block.
Chris Lattnere787b322018-08-08 11:14:57 -07002276 builder.setInsertionPointToEnd(forStmt->getBlock());
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002277
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002278 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002279}
2280
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002281/// Parse integer constant as affine constant expression.
2282ParseResult MLFunctionParser::parseIntConstant(int64_t &val) {
2283 bool negate = consumeIf(Token::minus);
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002284
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002285 if (getToken().isNot(Token::integer))
2286 return emitError("expected integer");
2287
2288 auto uval = getToken().getUInt64IntegerValue();
2289
2290 if (!uval.hasValue() || (int64_t)uval.getValue() < 0) {
2291 return emitError("bound or step is too large for affineint");
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002292 }
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002293
2294 val = (int64_t)uval.getValue();
2295 if (negate)
2296 val = -val;
2297 consumeToken();
2298
2299 return ParseSuccess;
2300}
2301
2302/// Dimensions and symbol use list.
2303///
2304/// dim-use-list ::= `(` ssa-use-list? `)`
2305/// symbol-use-list ::= `[` ssa-use-list? `]`
2306/// dim-and-symbol-use-list ::= dim-use-list symbol-use-list?
2307///
2308ParseResult
2309MLFunctionParser::parseDimAndSymbolList(SmallVectorImpl<MLValue *> &operands,
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002310 unsigned numDims, unsigned numOperands,
2311 const char *affineStructName) {
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002312 if (parseToken(Token::l_paren, "expected '('"))
2313 return ParseFailure;
2314
2315 SmallVector<SSAUseInfo, 4> opInfo;
2316 parseOptionalSSAUseList(opInfo);
2317
2318 if (parseToken(Token::r_paren, "expected ')'"))
2319 return ParseFailure;
2320
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002321 if (numDims != opInfo.size())
2322 return emitError("dim operand count and " + Twine(affineStructName) +
2323 " dim count must match");
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002324
2325 if (consumeIf(Token::l_square)) {
2326 parseOptionalSSAUseList(opInfo);
2327 if (parseToken(Token::r_square, "expected ']'"))
2328 return ParseFailure;
2329 }
2330
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002331 if (numOperands != opInfo.size())
2332 return emitError("symbol operand count and " + Twine(affineStructName) +
2333 " symbol count must match");
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002334
2335 // Resolve SSA uses.
2336 Type *affineIntType = builder.getAffineIntType();
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002337 for (unsigned i = 0, e = opInfo.size(); i != e; ++i) {
2338 SSAValue *sval = resolveSSAUse(opInfo[i], affineIntType);
2339 if (!sval)
2340 return ParseFailure;
2341
2342 auto *v = cast<MLValue>(sval);
2343 if (i < numDims && !v->isValidDim())
2344 return emitError(opInfo[i].loc, "value '" + opInfo[i].name.str() +
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002345 "' cannot be used as a dimension id");
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002346 if (i >= numDims && !v->isValidSymbol())
2347 return emitError(opInfo[i].loc, "value '" + opInfo[i].name.str() +
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002348 "' cannot be used as a symbol");
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002349 operands.push_back(v);
2350 }
2351
2352 return ParseSuccess;
2353}
2354
2355// Loop bound.
2356///
2357/// lower-bound ::= `max`? affine-map dim-and-symbol-use-list | shorthand-bound
2358/// upper-bound ::= `min`? affine-map dim-and-symbol-use-list | shorthand-bound
2359/// shorthand-bound ::= ssa-id | `-`? integer-literal
2360///
2361ParseResult MLFunctionParser::parseBound(SmallVectorImpl<MLValue *> &operands,
2362 AffineMap *&map, bool isLower) {
2363 // 'min' / 'max' prefixes are syntactic sugar. Ignore them.
2364 if (isLower)
2365 consumeIf(Token::kw_max);
2366 else
2367 consumeIf(Token::kw_min);
2368
2369 // Parse full form - affine map followed by dim and symbol list.
2370 if (getToken().isAny(Token::hash_identifier, Token::l_paren)) {
2371 map = parseAffineMapReference();
2372 if (!map)
2373 return ParseFailure;
2374
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002375 if (parseDimAndSymbolList(operands, map->getNumDims(),
2376 map->getNumOperands(), "affine map"))
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002377 return ParseFailure;
2378 return ParseSuccess;
2379 }
2380
2381 // Parse shorthand form.
2382 if (getToken().isAny(Token::minus, Token::integer)) {
2383 int64_t val;
2384 if (!parseIntConstant(val)) {
2385 map = builder.getConstantMap(val);
2386 return ParseSuccess;
2387 }
2388 return ParseFailure;
2389 }
2390
2391 // Parse ssa-id as identity map.
2392 SSAUseInfo opInfo;
2393 if (parseSSAUse(opInfo))
2394 return ParseFailure;
2395
2396 // TODO: improve error message when SSA value is not an affine integer.
2397 // Currently it is 'use of value ... expects different type than prior uses'
2398 if (auto *value = resolveSSAUse(opInfo, builder.getAffineIntType()))
2399 operands.push_back(cast<MLValue>(value));
2400 else
2401 return ParseFailure;
2402
2403 // Create an identity map using dim id for an induction variable and
2404 // symbol otherwise. This representation is optimized for storage.
2405 // Analysis passes may expand it into a multi-dimensional map if desired.
2406 if (isa<ForStmt>(operands[0]))
2407 map = builder.getDimIdentityMap();
2408 else
2409 map = builder.getSymbolIdentityMap();
2410
2411 return ParseSuccess;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002412}
2413
Uday Bondhugulabc535622018-08-07 14:24:38 -07002414/// Parse an affine constraint.
2415/// affine-constraint ::= affine-expr `>=` `0`
2416/// | affine-expr `==` `0`
2417///
2418/// isEq is set to true if the parsed constraint is an equality, false if it is
2419/// an inequality (greater than or equal).
2420///
2421AffineExpr *AffineParser::parseAffineConstraint(bool *isEq) {
2422 AffineExpr *expr = parseAffineExpr();
2423 if (!expr)
2424 return nullptr;
2425
2426 if (consumeIf(Token::greater) && consumeIf(Token::equal) &&
2427 getToken().is(Token::integer)) {
2428 auto dim = getToken().getUnsignedIntegerValue();
2429 if (dim.hasValue() && dim.getValue() == 0) {
2430 consumeToken(Token::integer);
2431 *isEq = false;
2432 return expr;
2433 }
2434 return (emitError("expected '0' after '>='"), nullptr);
2435 }
2436
2437 if (consumeIf(Token::equal) && consumeIf(Token::equal) &&
2438 getToken().is(Token::integer)) {
2439 auto dim = getToken().getUnsignedIntegerValue();
2440 if (dim.hasValue() && dim.getValue() == 0) {
2441 consumeToken(Token::integer);
2442 *isEq = true;
2443 return expr;
2444 }
2445 return (emitError("expected '0' after '=='"), nullptr);
2446 }
2447
2448 return (emitError("expected '== 0' or '>= 0' at end of affine constraint"),
2449 nullptr);
2450}
2451
2452/// Parse an integer set definition.
2453/// integer-set-inline
2454/// ::= dim-and-symbol-id-lists `:` affine-constraint-conjunction
2455/// affine-constraint-conjunction ::= /*empty*/
2456/// | affine-constraint (`,` affine-constraint)*
2457///
2458IntegerSet *AffineParser::parseIntegerSetInline() {
2459 unsigned numDims = 0, numSymbols = 0;
2460
2461 // List of dimensional identifiers.
2462 if (parseDimIdList(numDims))
2463 return nullptr;
2464
2465 // Symbols are optional.
2466 if (getToken().is(Token::l_square)) {
2467 if (parseSymbolIdList(numSymbols))
2468 return nullptr;
2469 }
2470
2471 if (parseToken(Token::colon, "expected ':' or '['") ||
2472 parseToken(Token::l_paren,
2473 "expected '(' at start of integer set constraint list"))
2474 return nullptr;
2475
2476 SmallVector<AffineExpr *, 4> constraints;
2477 SmallVector<bool, 4> isEqs;
2478 auto parseElt = [&]() -> ParseResult {
2479 bool isEq;
2480 auto *elt = parseAffineConstraint(&isEq);
2481 ParseResult res = elt ? ParseSuccess : ParseFailure;
2482 if (elt) {
2483 constraints.push_back(elt);
2484 isEqs.push_back(isEq);
2485 }
2486 return res;
2487 };
2488
2489 // Parse a list of affine constraints (comma-separated) .
2490 // Grammar: affine-constraint-conjunct ::= `(` affine-constraint (`,`
2491 // affine-constraint)* `)
2492 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt, true))
2493 return nullptr;
2494
2495 // Parsed a valid integer set.
2496 return builder.getIntegerSet(numDims, numSymbols, constraints, isEqs);
2497}
2498
2499IntegerSet *Parser::parseIntegerSetInline() {
2500 return AffineParser(state).parseIntegerSetInline();
2501}
2502
2503/// Parse a reference to an integer set.
2504/// integer-set ::= integer-set-id | integer-set-inline
2505/// integer-set-id ::= `@@` suffix-id
2506///
2507IntegerSet *Parser::parseIntegerSetReference() {
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002508 // TODO: change '@@' integer set prefix to '#'.
Uday Bondhugulabc535622018-08-07 14:24:38 -07002509 if (getToken().is(Token::double_at_identifier)) {
2510 // Parse integer set identifier and verify that it exists.
2511 StringRef integerSetId = getTokenSpelling().drop_front(2);
2512 if (getState().integerSetDefinitions.count(integerSetId) == 0)
2513 return (emitError("undefined integer set id '" + integerSetId + "'"),
2514 nullptr);
2515 consumeToken(Token::double_at_identifier);
2516 return getState().integerSetDefinitions[integerSetId];
2517 }
2518 // Try to parse an inline integer set definition.
2519 return parseIntegerSetInline();
2520}
2521
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002522/// If statement.
2523///
Chris Lattner48af7d12018-07-09 19:05:38 -07002524/// ml-if-head ::= `if` ml-if-cond `{` ml-stmt* `}`
2525/// | ml-if-head `else` `if` ml-if-cond `{` ml-stmt* `}`
2526/// ml-if-stmt ::= ml-if-head
2527/// | ml-if-head `else` `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002528///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002529ParseResult MLFunctionParser::parseIfStmt() {
Chris Lattner1628fa02018-08-23 14:32:25 -07002530 auto loc = getToken().getLoc();
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002531 consumeToken(Token::kw_if);
Uday Bondhugulabc535622018-08-07 14:24:38 -07002532
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002533 IntegerSet *set = parseIntegerSetReference();
2534 if (!set)
Chris Lattnerf7702a62018-07-23 17:30:01 -07002535 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002536
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002537 SmallVector<MLValue *, 4> operands;
2538 if (parseDimAndSymbolList(operands, set->getNumDims(), set->getNumOperands(),
2539 "integer set"))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002540 return ParseFailure;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002541
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002542 IfStmt *ifStmt =
2543 builder.createIf(getEncodedSourceLocation(loc), operands, set);
Uday Bondhugulabc535622018-08-07 14:24:38 -07002544
Chris Lattnere787b322018-08-08 11:14:57 -07002545 IfClause *thenClause = ifStmt->getThen();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002546
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002547 // When parsing of an if statement body fails, the IR contains
2548 // the if statement with the portion of the body that has been
2549 // successfully parsed.
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002550 if (parseStmtBlock(thenClause))
2551 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002552
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002553 if (consumeIf(Token::kw_else)) {
Chris Lattnere787b322018-08-08 11:14:57 -07002554 auto *elseClause = ifStmt->createElse();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002555 if (parseElseClause(elseClause))
2556 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002557 }
2558
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002559 // Reset insertion point to the current block.
Chris Lattnere787b322018-08-08 11:14:57 -07002560 builder.setInsertionPointToEnd(ifStmt->getBlock());
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002561
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002562 return ParseSuccess;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002563}
2564
2565ParseResult MLFunctionParser::parseElseClause(IfClause *elseClause) {
2566 if (getToken().is(Token::kw_if)) {
Chris Lattnere787b322018-08-08 11:14:57 -07002567 builder.setInsertionPointToEnd(elseClause);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002568 return parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002569 }
2570
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002571 return parseStmtBlock(elseClause);
2572}
2573
2574///
2575/// Parse a list of statements ending with `return` or `}`
2576///
2577ParseResult MLFunctionParser::parseStatements(StmtBlock *block) {
Chris Lattner992a1272018-08-07 12:02:37 -07002578 auto createOpFunc = [&](const OperationState &state) -> Operation * {
2579 return builder.createOperation(state);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002580 };
2581
Chris Lattnere787b322018-08-08 11:14:57 -07002582 builder.setInsertionPointToEnd(block);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002583
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002584 // Parse statements till we see '}' or 'return'.
2585 // Return statement is parsed separately to emit a more intuitive error
2586 // when '}' is missing after the return statement.
2587 while (getToken().isNot(Token::r_brace, Token::kw_return)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002588 switch (getToken().getKind()) {
2589 default:
2590 if (parseOperation(createOpFunc))
2591 return ParseFailure;
2592 break;
2593 case Token::kw_for:
2594 if (parseForStmt())
2595 return ParseFailure;
2596 break;
2597 case Token::kw_if:
2598 if (parseIfStmt())
2599 return ParseFailure;
2600 break;
2601 } // end switch
2602 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002603
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002604 // Parse the return statement.
2605 if (getToken().is(Token::kw_return))
2606 if (parseOperation(createOpFunc))
2607 return ParseFailure;
2608
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002609 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002610}
2611
2612///
2613/// Parse `{` ml-stmt* `}`
2614///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002615ParseResult MLFunctionParser::parseStmtBlock(StmtBlock *block) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002616 if (parseToken(Token::l_brace, "expected '{' before statement list") ||
2617 parseStatements(block) ||
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002618 parseToken(Token::r_brace, "expected '}' after statement list"))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002619 return ParseFailure;
2620
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002621 return ParseSuccess;
2622}
2623
Chris Lattner4c95a502018-06-23 16:03:42 -07002624//===----------------------------------------------------------------------===//
2625// Top-level entity parsing.
2626//===----------------------------------------------------------------------===//
2627
Chris Lattner2e595eb2018-07-10 10:08:27 -07002628namespace {
2629/// This parser handles entities that are only valid at the top level of the
2630/// file.
2631class ModuleParser : public Parser {
2632public:
2633 explicit ModuleParser(ParserState &state) : Parser(state) {}
2634
2635 ParseResult parseModule();
2636
2637private:
Chris Lattner4613d9e2018-08-19 21:17:22 -07002638 ParseResult finalizeModule();
2639
Chris Lattner2e595eb2018-07-10 10:08:27 -07002640 ParseResult parseAffineMapDef();
Uday Bondhugulabc535622018-08-07 14:24:38 -07002641 ParseResult parseIntegerSetDef();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002642
2643 // Functions.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002644 ParseResult parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2645 SmallVectorImpl<StringRef> &argNames);
2646 ParseResult parseFunctionSignature(StringRef &name, FunctionType *&type,
2647 SmallVectorImpl<StringRef> *argNames);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002648 ParseResult parseExtFunc();
2649 ParseResult parseCFGFunc();
2650 ParseResult parseMLFunc();
2651};
2652} // end anonymous namespace
2653
2654/// Affine map declaration.
2655///
2656/// affine-map-def ::= affine-map-id `=` affine-map-inline
2657///
2658ParseResult ModuleParser::parseAffineMapDef() {
2659 assert(getToken().is(Token::hash_identifier));
2660
2661 StringRef affineMapId = getTokenSpelling().drop_front();
2662
2663 // Check for redefinitions.
Nicolas Vasilache97298152018-08-27 10:10:42 -07002664 auto *&entry = getState().affineMapDefinitions[affineMapId];
2665 if (entry)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002666 return emitError("redefinition of affine map id '" + affineMapId + "'");
2667
2668 consumeToken(Token::hash_identifier);
2669
2670 // Parse the '='
Chris Lattnerf7702a62018-07-23 17:30:01 -07002671 if (parseToken(Token::equal,
2672 "expected '=' in affine map outlined definition"))
2673 return ParseFailure;
Chris Lattner2e595eb2018-07-10 10:08:27 -07002674
Nicolas Vasilache97298152018-08-27 10:10:42 -07002675 entry = parseAffineMapInline();
2676 if (!entry)
Uday Bondhugulabc535622018-08-07 14:24:38 -07002677 return ParseFailure;
2678
2679 return ParseSuccess;
2680}
2681
2682/// Integer set declaration.
2683///
2684/// integer-set-decl ::= integer-set-id `=` integer-set-inline
2685///
2686ParseResult ModuleParser::parseIntegerSetDef() {
2687 assert(getToken().is(Token::double_at_identifier));
2688
2689 StringRef integerSetId = getTokenSpelling().drop_front(2);
2690
2691 // Check for redefinitions (a default entry is created if one doesn't exist)
Nicolas Vasilache97298152018-08-27 10:10:42 -07002692 auto *&entry = getState().integerSetDefinitions[integerSetId];
2693 if (entry)
Uday Bondhugulabc535622018-08-07 14:24:38 -07002694 return emitError("redefinition of integer set id '" + integerSetId + "'");
2695
2696 consumeToken(Token::double_at_identifier);
2697
2698 // Parse the '='
2699 if (parseToken(Token::equal,
2700 "expected '=' in outlined integer set definition"))
2701 return ParseFailure;
2702
Nicolas Vasilache97298152018-08-27 10:10:42 -07002703 entry = parseIntegerSetInline();
2704 if (!entry)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002705 return ParseFailure;
2706
Chris Lattner2e595eb2018-07-10 10:08:27 -07002707 return ParseSuccess;
2708}
2709
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002710/// Parse a (possibly empty) list of MLFunction arguments with types.
2711///
2712/// ml-argument ::= ssa-id `:` type
2713/// ml-argument-list ::= ml-argument (`,` ml-argument)* | /*empty*/
2714///
2715ParseResult
2716ModuleParser::parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2717 SmallVectorImpl<StringRef> &argNames) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002718 consumeToken(Token::l_paren);
2719
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002720 auto parseElt = [&]() -> ParseResult {
2721 // Parse argument name
2722 if (getToken().isNot(Token::percent_identifier))
2723 return emitError("expected SSA identifier");
2724
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002725 StringRef name = getTokenSpelling();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002726 consumeToken(Token::percent_identifier);
2727 argNames.push_back(name);
2728
Chris Lattnerf7702a62018-07-23 17:30:01 -07002729 if (parseToken(Token::colon, "expected ':'"))
2730 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002731
2732 // Parse argument type
2733 auto elt = parseType();
2734 if (!elt)
2735 return ParseFailure;
2736 argTypes.push_back(elt);
2737
2738 return ParseSuccess;
2739 };
2740
Chris Lattner40746442018-07-21 14:32:09 -07002741 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002742}
2743
Chris Lattner2e595eb2018-07-10 10:08:27 -07002744/// Parse a function signature, starting with a name and including the parameter
2745/// list.
2746///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002747/// argument-list ::= type (`,` type)* | /*empty*/ | ml-argument-list
Chris Lattner2e595eb2018-07-10 10:08:27 -07002748/// function-signature ::= function-id `(` argument-list `)` (`->` type-list)?
2749///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002750ParseResult
2751ModuleParser::parseFunctionSignature(StringRef &name, FunctionType *&type,
2752 SmallVectorImpl<StringRef> *argNames) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002753 if (getToken().isNot(Token::at_identifier))
2754 return emitError("expected a function identifier like '@foo'");
2755
2756 name = getTokenSpelling().drop_front();
2757 consumeToken(Token::at_identifier);
2758
2759 if (getToken().isNot(Token::l_paren))
2760 return emitError("expected '(' in function signature");
2761
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002762 SmallVector<Type *, 4> argTypes;
2763 ParseResult parseResult;
2764
2765 if (argNames)
2766 parseResult = parseMLArgumentList(argTypes, *argNames);
2767 else
2768 parseResult = parseTypeList(argTypes);
2769
2770 if (parseResult)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002771 return ParseFailure;
2772
2773 // Parse the return type if present.
2774 SmallVector<Type *, 4> results;
2775 if (consumeIf(Token::arrow)) {
2776 if (parseTypeList(results))
2777 return ParseFailure;
2778 }
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002779 type = builder.getFunctionType(argTypes, results);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002780 return ParseSuccess;
2781}
2782
2783/// External function declarations.
2784///
2785/// ext-func ::= `extfunc` function-signature
2786///
2787ParseResult ModuleParser::parseExtFunc() {
2788 consumeToken(Token::kw_extfunc);
Chris Lattner974a8762018-08-17 16:49:42 -07002789 auto loc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002790
2791 StringRef name;
2792 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002793 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002794 return ParseFailure;
2795
2796 // Okay, the external function definition was parsed correctly.
Chris Lattner974a8762018-08-17 16:49:42 -07002797 auto *function = new ExtFunction(name, type);
2798 getModule()->getFunctions().push_back(function);
2799
2800 // Verify no name collision / redefinition.
Chris Lattner4613d9e2018-08-19 21:17:22 -07002801 if (function->getName() != name)
Chris Lattner974a8762018-08-17 16:49:42 -07002802 return emitError(loc,
2803 "redefinition of function named '" + name.str() + "'");
2804
Chris Lattner2e595eb2018-07-10 10:08:27 -07002805 return ParseSuccess;
2806}
2807
2808/// CFG function declarations.
2809///
2810/// cfg-func ::= `cfgfunc` function-signature `{` basic-block+ `}`
2811///
2812ParseResult ModuleParser::parseCFGFunc() {
2813 consumeToken(Token::kw_cfgfunc);
Chris Lattner974a8762018-08-17 16:49:42 -07002814 auto loc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002815
2816 StringRef name;
2817 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002818 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002819 return ParseFailure;
2820
2821 // Okay, the CFG function signature was parsed correctly, create the function.
Chris Lattner974a8762018-08-17 16:49:42 -07002822 auto *function = new CFGFunction(name, type);
2823 getModule()->getFunctions().push_back(function);
2824
2825 // Verify no name collision / redefinition.
Chris Lattner4613d9e2018-08-19 21:17:22 -07002826 if (function->getName() != name)
Chris Lattner974a8762018-08-17 16:49:42 -07002827 return emitError(loc,
2828 "redefinition of function named '" + name.str() + "'");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002829
2830 return CFGFunctionParser(getState(), function).parseFunctionBody();
2831}
2832
2833/// ML function declarations.
2834///
2835/// ml-func ::= `mlfunc` ml-func-signature `{` ml-stmt* ml-return-stmt `}`
2836///
2837ParseResult ModuleParser::parseMLFunc() {
2838 consumeToken(Token::kw_mlfunc);
2839
2840 StringRef name;
2841 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002842 SmallVector<StringRef, 4> argNames;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002843
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002844 auto loc = getToken().getLoc();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002845 if (parseFunctionSignature(name, type, &argNames))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002846 return ParseFailure;
2847
2848 // Okay, the ML function signature was parsed correctly, create the function.
Chris Lattner974a8762018-08-17 16:49:42 -07002849 auto *function = MLFunction::create(name, type);
2850 getModule()->getFunctions().push_back(function);
2851
2852 // Verify no name collision / redefinition.
Chris Lattner4613d9e2018-08-19 21:17:22 -07002853 if (function->getName() != name)
Chris Lattner974a8762018-08-17 16:49:42 -07002854 return emitError(loc,
2855 "redefinition of function named '" + name.str() + "'");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002856
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002857 // Create the parser.
2858 auto parser = MLFunctionParser(getState(), function);
2859
2860 // Add definitions of the function arguments.
2861 for (unsigned i = 0, e = function->getNumArguments(); i != e; ++i) {
2862 if (parser.addDefinition({argNames[i], 0, loc}, function->getArgument(i)))
2863 return ParseFailure;
2864 }
2865
2866 return parser.parseFunctionBody();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002867}
2868
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002869/// Given an attribute that could refer to a function attribute in the remapping
2870/// table, walk it and rewrite it to use the mapped function. If it doesn't
2871/// refer to anything in the table, then it is returned unmodified.
2872static Attribute *
2873remapFunctionAttrs(Attribute *input,
2874 DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable,
2875 MLIRContext *context) {
2876 // Most attributes are trivially unrelated to function attributes, skip them
2877 // rapidly.
2878 if (!input->isOrContainsFunction())
2879 return input;
2880
2881 // If we have a function attribute, remap it.
2882 if (auto *fnAttr = dyn_cast<FunctionAttr>(input)) {
2883 auto it = remappingTable.find(fnAttr);
2884 return it != remappingTable.end() ? it->second : input;
2885 }
2886
2887 // Otherwise, we must have an array attribute, remap the elements.
2888 auto *arrayAttr = cast<ArrayAttr>(input);
2889 SmallVector<Attribute *, 8> remappedElts;
2890 bool anyChange = false;
2891 for (auto *elt : arrayAttr->getValue()) {
2892 auto *newElt = remapFunctionAttrs(elt, remappingTable, context);
2893 remappedElts.push_back(newElt);
2894 anyChange |= (elt != newElt);
2895 }
2896
2897 if (!anyChange)
2898 return input;
2899
2900 return ArrayAttr::get(remappedElts, context);
2901}
2902
2903/// Remap function attributes to resolve forward references to their actual
2904/// definition.
2905static void remapFunctionAttrsInOperation(
2906 Operation *op, DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable) {
2907 for (auto attr : op->getAttrs()) {
2908 // Do the remapping, if we got the same thing back, then it must contain
2909 // functions that aren't getting remapped.
2910 auto *newVal =
2911 remapFunctionAttrs(attr.second, remappingTable, op->getContext());
2912 if (newVal == attr.second)
2913 continue;
2914
2915 // Otherwise, replace the existing attribute with the new one. It is safe
2916 // to mutate the attribute list while we walk it because underlying
2917 // attribute lists are uniqued and immortal.
2918 op->setAttr(attr.first, newVal);
2919 }
2920}
2921
Chris Lattner4613d9e2018-08-19 21:17:22 -07002922/// Finish the end of module parsing - when the result is valid, do final
2923/// checking.
2924ParseResult ModuleParser::finalizeModule() {
2925
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002926 // Resolve all forward references, building a remapping table of attributes.
2927 DenseMap<FunctionAttr *, FunctionAttr *> remappingTable;
Chris Lattner4613d9e2018-08-19 21:17:22 -07002928 for (auto forwardRef : getState().functionForwardRefs) {
2929 auto name = forwardRef.first;
2930
2931 // Resolve the reference.
2932 auto *resolvedFunction = getModule()->getNamedFunction(name);
2933 if (!resolvedFunction)
2934 return emitError(forwardRef.second.second,
2935 "reference to undefined function '" + name.str() + "'");
2936
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002937 remappingTable[builder.getFunctionAttr(forwardRef.second.first)] =
2938 builder.getFunctionAttr(resolvedFunction);
Chris Lattner4613d9e2018-08-19 21:17:22 -07002939 }
2940
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002941 // If there was nothing to remap, then we're done.
2942 if (remappingTable.empty())
2943 return ParseSuccess;
2944
2945 // Otherwise, walk the entire module replacing uses of one attribute set with
2946 // the correct ones.
2947 for (auto &fn : *getModule()) {
2948 if (auto *cfgFn = dyn_cast<CFGFunction>(&fn)) {
2949 for (auto &bb : *cfgFn) {
2950 for (auto &inst : bb) {
2951 remapFunctionAttrsInOperation(&inst, remappingTable);
2952 }
2953 }
2954 }
2955
2956 // Otherwise, look at MLFunctions. We ignore ExtFunctions.
2957 auto *mlFn = dyn_cast<MLFunction>(&fn);
2958 if (!mlFn)
2959 continue;
2960
2961 struct MLFnWalker : public StmtWalker<MLFnWalker> {
2962 MLFnWalker(DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable)
2963 : remappingTable(remappingTable) {}
2964 void visitOperationStmt(OperationStmt *opStmt) {
2965 remapFunctionAttrsInOperation(opStmt, remappingTable);
2966 }
2967
2968 DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable;
2969 };
2970
2971 MLFnWalker(remappingTable).walk(mlFn);
2972 }
2973
2974 // Now that all references to the forward definition placeholders are
2975 // resolved, we can deallocate the placeholders.
2976 for (auto forwardRef : getState().functionForwardRefs)
2977 forwardRef.second.first->destroy();
Chris Lattner4613d9e2018-08-19 21:17:22 -07002978 return ParseSuccess;
2979}
2980
Chris Lattnere79379a2018-06-22 10:39:19 -07002981/// This is the top-level module parser.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002982ParseResult ModuleParser::parseModule() {
Chris Lattnere79379a2018-06-22 10:39:19 -07002983 while (1) {
Chris Lattner48af7d12018-07-09 19:05:38 -07002984 switch (getToken().getKind()) {
Chris Lattnere79379a2018-06-22 10:39:19 -07002985 default:
2986 emitError("expected a top level entity");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002987 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002988
Uday Bondhugula015cbb12018-07-03 20:16:08 -07002989 // If we got to the end of the file, then we're done.
Chris Lattnere79379a2018-06-22 10:39:19 -07002990 case Token::eof:
Chris Lattner4613d9e2018-08-19 21:17:22 -07002991 return finalizeModule();
Chris Lattnere79379a2018-06-22 10:39:19 -07002992
2993 // If we got an error token, then the lexer already emitted an error, just
2994 // stop. Someday we could introduce error recovery if there was demand for
2995 // it.
2996 case Token::error:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002997 return ParseFailure;
2998
2999 case Token::hash_identifier:
3000 if (parseAffineMapDef())
3001 return ParseFailure;
3002 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07003003
Uday Bondhugulabc535622018-08-07 14:24:38 -07003004 case Token::double_at_identifier:
3005 if (parseIntegerSetDef())
3006 return ParseFailure;
3007 break;
3008
Chris Lattnere79379a2018-06-22 10:39:19 -07003009 case Token::kw_extfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07003010 if (parseExtFunc())
3011 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07003012 break;
3013
Chris Lattner4c95a502018-06-23 16:03:42 -07003014 case Token::kw_cfgfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07003015 if (parseCFGFunc())
3016 return ParseFailure;
MLIR Teamf85a6262018-06-27 11:03:08 -07003017 break;
Chris Lattner4c95a502018-06-23 16:03:42 -07003018
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07003019 case Token::kw_mlfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07003020 if (parseMLFunc())
3021 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07003022 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07003023 }
3024 }
3025}
3026
3027//===----------------------------------------------------------------------===//
3028
Jacques Pienaar7b829702018-07-03 13:24:09 -07003029void mlir::defaultErrorReporter(const llvm::SMDiagnostic &error) {
3030 const auto &sourceMgr = *error.getSourceMgr();
3031 sourceMgr.PrintMessage(error.getLoc(), error.getKind(), error.getMessage());
3032}
3033
Chris Lattnere79379a2018-06-22 10:39:19 -07003034/// This parses the file specified by the indicated SourceMgr and returns an
3035/// MLIR module if it was valid. If not, it emits diagnostics and returns null.
Jacques Pienaar9c411be2018-06-24 19:17:35 -07003036Module *mlir::parseSourceFile(llvm::SourceMgr &sourceMgr, MLIRContext *context,
Jacques Pienaar7b829702018-07-03 13:24:09 -07003037 SMDiagnosticHandlerTy errorReporter) {
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003038 if (!errorReporter)
3039 errorReporter = defaultErrorReporter;
3040
3041 // We are going to replace the context's handler and redirect it to use the
3042 // error reporter. Save the existing handler and reinstate it when we're
3043 // done.
3044 auto existingContextHandler = context->getDiagnosticHandler();
3045
3046 // Install a new handler that uses the error reporter.
Chris Lattnerfc647d52018-08-27 21:05:16 -07003047 context->registerDiagnosticHandler([&](Location *location, StringRef message,
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003048 MLIRContext::DiagnosticKind kind) {
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003049 SourceMgr::DiagKind diagKind;
3050 switch (kind) {
3051 case MLIRContext::DiagnosticKind::Error:
3052 diagKind = SourceMgr::DK_Error;
3053 break;
3054 case MLIRContext::DiagnosticKind::Warning:
3055 diagKind = SourceMgr::DK_Warning;
3056 break;
3057 case MLIRContext::DiagnosticKind::Note:
3058 diagKind = SourceMgr::DK_Note;
3059 break;
3060 }
Chris Lattnerfc647d52018-08-27 21:05:16 -07003061
3062 StringRef filename;
3063 unsigned line = 0, column = 0;
3064 if (auto fileLoc = dyn_cast<FileLineColLoc>(location)) {
3065 filename = fileLoc->getFilename();
3066 line = fileLoc->getLine();
3067 column = fileLoc->getColumn();
3068 }
3069
3070 auto diag = llvm::SMDiagnostic(sourceMgr, SMLoc(), filename, line, column,
3071 diagKind, message, /*LineStr=*/StringRef(),
3072 /*Ranges=*/{}, /*FixIts=*/{});
3073
3074 errorReporter(diag);
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003075 });
3076
Chris Lattner2e595eb2018-07-10 10:08:27 -07003077 // This is the result module we are parsing into.
3078 std::unique_ptr<Module> module(new Module(context));
3079
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003080 ParserState state(sourceMgr, module.get(), errorReporter);
3081 if (ModuleParser(state).parseModule()) {
3082 context->registerDiagnosticHandler(existingContextHandler);
Chris Lattner2e595eb2018-07-10 10:08:27 -07003083 return nullptr;
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003084 }
Chris Lattner21e67f62018-07-06 10:46:19 -07003085
3086 // Make sure the parse module has no other structural problems detected by the
3087 // verifier.
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003088 std::string errorResult;
3089 module->verify(&errorResult);
3090
3091 // We don't have location information for general verifier errors, so emit the
3092 // error on the first line.
3093 if (!errorResult.empty()) {
3094 auto *mainBuffer = sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID());
3095 errorReporter(sourceMgr.GetMessage(
3096 SMLoc::getFromPointer(mainBuffer->getBufferStart()),
3097 SourceMgr::DK_Error, errorResult));
3098 return nullptr;
3099 }
3100
3101 context->registerDiagnosticHandler(existingContextHandler);
Chris Lattner2e595eb2018-07-10 10:08:27 -07003102 return module.release();
Chris Lattnere79379a2018-06-22 10:39:19 -07003103}