blob: ebeb19616a4433743c6950735f46a5120da16948 [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"
Chris Lattnerfc647d52018-08-27 21:05:16 -070028#include "mlir/IR/Location.h"
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -070029#include "mlir/IR/MLFunction.h"
Chris Lattnerea5c3dc2018-08-21 08:42:19 -070030#include "mlir/IR/MLIRContext.h"
Chris Lattner21e67f62018-07-06 10:46:19 -070031#include "mlir/IR/Module.h"
Chris Lattner85ee1512018-07-25 11:15:20 -070032#include "mlir/IR/OpImplementation.h"
Chris Lattner21e67f62018-07-06 10:46:19 -070033#include "mlir/IR/OperationSet.h"
Chris Lattnerea5c3dc2018-08-21 08:42:19 -070034#include "mlir/IR/StmtVisitor.h"
Chris Lattnerf7e22732018-06-22 22:03:48 -070035#include "mlir/IR/Types.h"
James Molloyf0d2f442018-08-03 01:54:46 -070036#include "llvm/ADT/DenseMap.h"
Chris Lattner1aa46322018-08-21 17:55:22 -070037#include "llvm/Support/PrettyStackTrace.h"
James Molloyf0d2f442018-08-03 01:54:46 -070038#include "llvm/Support/SourceMgr.h"
Chris Lattnere79379a2018-06-22 10:39:19 -070039using namespace mlir;
Chris Lattner4c95a502018-06-23 16:03:42 -070040using llvm::SMLoc;
James Molloy0ff71542018-07-23 16:56:32 -070041using llvm::SourceMgr;
Chris Lattnere79379a2018-06-22 10:39:19 -070042
Chris Lattnerf7e22732018-06-22 22:03:48 -070043/// Simple enum to make code read better in cases that would otherwise return a
44/// bool value. Failure is "true" in a boolean context.
James Molloy0ff71542018-07-23 16:56:32 -070045enum ParseResult { ParseSuccess, ParseFailure };
Chris Lattnere79379a2018-06-22 10:39:19 -070046
Chris Lattnerfc647d52018-08-27 21:05:16 -070047/// Return a uniqued filename for the main file the specified SourceMgr is
48/// looking at.
49static UniquedFilename getUniquedFilename(llvm::SourceMgr &sourceMgr,
50 MLIRContext *context) {
51 auto *buffer = sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID());
52 return UniquedFilename::get(buffer->getBufferIdentifier(), context);
53}
54
Chris Lattner48af7d12018-07-09 19:05:38 -070055namespace {
56class Parser;
57
58/// This class refers to all of the state maintained globally by the parser,
59/// such as the current lexer position etc. The Parser base class provides
60/// methods to access this.
61class ParserState {
Chris Lattnered65a732018-06-28 20:45:33 -070062public:
Chris Lattner2e595eb2018-07-10 10:08:27 -070063 ParserState(llvm::SourceMgr &sourceMgr, Module *module,
Chris Lattner48af7d12018-07-09 19:05:38 -070064 SMDiagnosticHandlerTy errorReporter)
Chris Lattner2e595eb2018-07-10 10:08:27 -070065 : context(module->getContext()), module(module),
Chris Lattnerfc647d52018-08-27 21:05:16 -070066 filename(getUniquedFilename(sourceMgr, context)),
Chris Lattner2e595eb2018-07-10 10:08:27 -070067 lex(sourceMgr, errorReporter), curToken(lex.lexToken()),
Chris Lattner85ee1512018-07-25 11:15:20 -070068 errorReporter(errorReporter), operationSet(OperationSet::get(context)) {
69 }
Chris Lattner2e595eb2018-07-10 10:08:27 -070070
71 // A map from affine map identifier to AffineMap.
72 llvm::StringMap<AffineMap *> affineMapDefinitions;
Chris Lattner4613d9e2018-08-19 21:17:22 -070073
Uday Bondhugulabc535622018-08-07 14:24:38 -070074 // A map from integer set identifier to IntegerSet.
75 llvm::StringMap<IntegerSet *> integerSetDefinitions;
Chris Lattnere79379a2018-06-22 10:39:19 -070076
Chris Lattner4613d9e2018-08-19 21:17:22 -070077 // This keeps track of all forward references to functions along with the
78 // temporary function used to represent them and the location of the first
79 // reference.
80 llvm::DenseMap<Identifier, std::pair<Function *, SMLoc>> functionForwardRefs;
81
Chris Lattnere79379a2018-06-22 10:39:19 -070082private:
Chris Lattner48af7d12018-07-09 19:05:38 -070083 ParserState(const ParserState &) = delete;
84 void operator=(const ParserState &) = delete;
85
86 friend class Parser;
87
88 // The context we're parsing into.
Chris Lattner2e595eb2018-07-10 10:08:27 -070089 MLIRContext *const context;
90
91 // This is the module we are parsing into.
92 Module *const module;
Chris Lattnerf7e22732018-06-22 22:03:48 -070093
Chris Lattnerfc647d52018-08-27 21:05:16 -070094 /// The filename to use for location generation.
95 UniquedFilename filename;
96
Chris Lattnerf7e22732018-06-22 22:03:48 -070097 // The lexer for the source file we're parsing.
Chris Lattnere79379a2018-06-22 10:39:19 -070098 Lexer lex;
99
100 // This is the next token that hasn't been consumed yet.
101 Token curToken;
102
Jacques Pienaar9c411be2018-06-24 19:17:35 -0700103 // The diagnostic error reporter.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700104 SMDiagnosticHandlerTy const errorReporter;
Chris Lattner85ee1512018-07-25 11:15:20 -0700105
106 // The active OperationSet we're parsing with.
107 OperationSet &operationSet;
Chris Lattner48af7d12018-07-09 19:05:38 -0700108};
109} // end anonymous namespace
MLIR Teamf85a6262018-06-27 11:03:08 -0700110
Chris Lattner48af7d12018-07-09 19:05:38 -0700111namespace {
112
Chris Lattner992a1272018-08-07 12:02:37 -0700113typedef std::function<Operation *(const OperationState &)>
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700114 CreateOperationFunction;
115
Chris Lattner48af7d12018-07-09 19:05:38 -0700116/// This class implement support for parsing global entities like types and
117/// shared entities like SSA names. It is intended to be subclassed by
118/// specialized subparsers that include state, e.g. when a local symbol table.
119class Parser {
120public:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700121 Builder builder;
Chris Lattner48af7d12018-07-09 19:05:38 -0700122
Chris Lattner2e595eb2018-07-10 10:08:27 -0700123 Parser(ParserState &state) : builder(state.context), state(state) {}
124
125 // Helper methods to get stuff from the parser-global state.
126 ParserState &getState() const { return state; }
Chris Lattner48af7d12018-07-09 19:05:38 -0700127 MLIRContext *getContext() const { return state.context; }
Chris Lattner2e595eb2018-07-10 10:08:27 -0700128 Module *getModule() { return state.module; }
Chris Lattner85ee1512018-07-25 11:15:20 -0700129 OperationSet &getOperationSet() const { return state.operationSet; }
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700130 llvm::SourceMgr &getSourceMgr() { return state.lex.getSourceMgr(); }
Chris Lattner48af7d12018-07-09 19:05:38 -0700131
132 /// Return the current token the parser is inspecting.
133 const Token &getToken() const { return state.curToken; }
134 StringRef getTokenSpelling() const { return state.curToken.getSpelling(); }
Chris Lattnere79379a2018-06-22 10:39:19 -0700135
Chris Lattner1628fa02018-08-23 14:32:25 -0700136 /// Encode the specified source location information into an attribute for
137 /// attachment to the IR.
Chris Lattnerfc647d52018-08-27 21:05:16 -0700138 Location *getEncodedSourceLocation(llvm::SMLoc loc);
Chris Lattner1628fa02018-08-23 14:32:25 -0700139
Chris Lattnere79379a2018-06-22 10:39:19 -0700140 /// Emit an error and return failure.
Chris Lattner4c95a502018-06-23 16:03:42 -0700141 ParseResult emitError(const Twine &message) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700142 return emitError(state.curToken.getLoc(), message);
Chris Lattner4c95a502018-06-23 16:03:42 -0700143 }
144 ParseResult emitError(SMLoc loc, const Twine &message);
Chris Lattnere79379a2018-06-22 10:39:19 -0700145
146 /// Advance the current lexer onto the next token.
147 void consumeToken() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700148 assert(state.curToken.isNot(Token::eof, Token::error) &&
Chris Lattnere79379a2018-06-22 10:39:19 -0700149 "shouldn't advance past EOF or errors");
Chris Lattner48af7d12018-07-09 19:05:38 -0700150 state.curToken = state.lex.lexToken();
Chris Lattnere79379a2018-06-22 10:39:19 -0700151 }
152
153 /// Advance the current lexer onto the next token, asserting what the expected
154 /// current token is. This is preferred to the above method because it leads
155 /// to more self-documenting code with better checking.
Chris Lattner8da0c282018-06-29 11:15:56 -0700156 void consumeToken(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700157 assert(state.curToken.is(kind) && "consumed an unexpected token");
Chris Lattnere79379a2018-06-22 10:39:19 -0700158 consumeToken();
159 }
160
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700161 /// If the current token has the specified kind, consume it and return true.
162 /// If not, return false.
Chris Lattner8da0c282018-06-29 11:15:56 -0700163 bool consumeIf(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700164 if (state.curToken.isNot(kind))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700165 return false;
166 consumeToken(kind);
167 return true;
168 }
169
Chris Lattnerf7702a62018-07-23 17:30:01 -0700170 /// Consume the specified token if present and return success. On failure,
171 /// output a diagnostic and return failure.
172 ParseResult parseToken(Token::Kind expectedToken, const Twine &message);
173
Chris Lattner40746442018-07-21 14:32:09 -0700174 /// Parse a comma-separated list of elements up until the specified end token.
175 ParseResult
176 parseCommaSeparatedListUntil(Token::Kind rightToken,
177 const std::function<ParseResult()> &parseElement,
178 bool allowEmptyList = true);
179
180 /// Parse a comma separated list of elements that must have at least one entry
181 /// in it.
182 ParseResult
183 parseCommaSeparatedList(const std::function<ParseResult()> &parseElement);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700184
Chris Lattnerf7e22732018-06-22 22:03:48 -0700185 // We have two forms of parsing methods - those that return a non-null
186 // pointer on success, and those that return a ParseResult to indicate whether
187 // they returned a failure. The second class fills in by-reference arguments
188 // as the results of their action.
189
Chris Lattnere79379a2018-06-22 10:39:19 -0700190 // Type parsing.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700191 VectorType *parseVectorType();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700192 ParseResult parseDimensionListRanked(SmallVectorImpl<int> &dimensions);
Chris Lattnerf7e22732018-06-22 22:03:48 -0700193 Type *parseTensorType();
194 Type *parseMemRefType();
195 Type *parseFunctionType();
196 Type *parseType();
Chris Lattner1604e472018-07-23 08:42:19 -0700197 ParseResult parseTypeListNoParens(SmallVectorImpl<Type *> &elements);
James Molloy0ff71542018-07-23 16:56:32 -0700198 ParseResult parseTypeList(SmallVectorImpl<Type *> &elements);
Chris Lattnere79379a2018-06-22 10:39:19 -0700199
Chris Lattner7121b802018-07-04 20:45:39 -0700200 // Attribute parsing.
Chris Lattner1aa46322018-08-21 17:55:22 -0700201 Function *resolveFunctionReference(StringRef nameStr, SMLoc nameLoc,
202 FunctionType *type);
Chris Lattner7121b802018-07-04 20:45:39 -0700203 Attribute *parseAttribute();
204 ParseResult parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes);
205
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700206 // Polyhedral structures.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700207 AffineMap *parseAffineMapInline();
MLIR Team718c82f2018-07-16 09:45:22 -0700208 AffineMap *parseAffineMapReference();
Uday Bondhugulabc535622018-08-07 14:24:38 -0700209 IntegerSet *parseIntegerSetInline();
210 IntegerSet *parseIntegerSetReference();
MLIR Teamf85a6262018-06-27 11:03:08 -0700211
Chris Lattner48af7d12018-07-09 19:05:38 -0700212private:
213 // The Parser is subclassed and reinstantiated. Do not add additional
214 // non-trivial state here, add it to the ParserState class.
215 ParserState &state;
Chris Lattnere79379a2018-06-22 10:39:19 -0700216};
217} // end anonymous namespace
218
219//===----------------------------------------------------------------------===//
220// Helper methods.
221//===----------------------------------------------------------------------===//
222
Chris Lattner1628fa02018-08-23 14:32:25 -0700223/// Encode the specified source location information into an attribute for
224/// attachment to the IR.
Chris Lattnerfc647d52018-08-27 21:05:16 -0700225Location *Parser::getEncodedSourceLocation(llvm::SMLoc loc) {
Chris Lattner1628fa02018-08-23 14:32:25 -0700226 auto &sourceMgr = getSourceMgr();
Chris Lattnerfc647d52018-08-27 21:05:16 -0700227 auto lineAndColumn =
228 sourceMgr.getLineAndColumn(loc, sourceMgr.getMainFileID());
Chris Lattner1628fa02018-08-23 14:32:25 -0700229
Chris Lattnerfc647d52018-08-27 21:05:16 -0700230 return FileLineColLoc::get(state.filename, lineAndColumn.first,
231 lineAndColumn.second, getContext());
Chris Lattner1628fa02018-08-23 14:32:25 -0700232}
233
Chris Lattner4c95a502018-06-23 16:03:42 -0700234ParseResult Parser::emitError(SMLoc loc, const Twine &message) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700235 // If we hit a parse error in response to a lexer error, then the lexer
Jacques Pienaar9c411be2018-06-24 19:17:35 -0700236 // already reported the error.
Chris Lattner48af7d12018-07-09 19:05:38 -0700237 if (getToken().is(Token::error))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700238 return ParseFailure;
239
Chris Lattner48af7d12018-07-09 19:05:38 -0700240 auto &sourceMgr = state.lex.getSourceMgr();
241 state.errorReporter(sourceMgr.GetMessage(loc, SourceMgr::DK_Error, message));
Chris Lattnere79379a2018-06-22 10:39:19 -0700242 return ParseFailure;
243}
244
Chris Lattnerf7702a62018-07-23 17:30:01 -0700245/// Consume the specified token if present and return success. On failure,
246/// output a diagnostic and return failure.
247ParseResult Parser::parseToken(Token::Kind expectedToken,
248 const Twine &message) {
249 if (consumeIf(expectedToken))
250 return ParseSuccess;
251 return emitError(message);
252}
253
Chris Lattner40746442018-07-21 14:32:09 -0700254/// Parse a comma separated list of elements that must have at least one entry
255/// in it.
256ParseResult Parser::parseCommaSeparatedList(
257 const std::function<ParseResult()> &parseElement) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700258 // Non-empty case starts with an element.
259 if (parseElement())
260 return ParseFailure;
261
262 // Otherwise we have a list of comma separated elements.
263 while (consumeIf(Token::comma)) {
264 if (parseElement())
265 return ParseFailure;
266 }
Chris Lattner40746442018-07-21 14:32:09 -0700267 return ParseSuccess;
268}
269
270/// Parse a comma-separated list of elements, terminated with an arbitrary
271/// token. This allows empty lists if allowEmptyList is true.
272///
273/// abstract-list ::= rightToken // if allowEmptyList == true
274/// abstract-list ::= element (',' element)* rightToken
275///
276ParseResult Parser::parseCommaSeparatedListUntil(
277 Token::Kind rightToken, const std::function<ParseResult()> &parseElement,
278 bool allowEmptyList) {
279 // Handle the empty case.
280 if (getToken().is(rightToken)) {
281 if (!allowEmptyList)
282 return emitError("expected list element");
283 consumeToken(rightToken);
284 return ParseSuccess;
285 }
286
Chris Lattnerf7702a62018-07-23 17:30:01 -0700287 if (parseCommaSeparatedList(parseElement) ||
288 parseToken(rightToken, "expected ',' or '" +
289 Token::getTokenSpelling(rightToken) + "'"))
Chris Lattner40746442018-07-21 14:32:09 -0700290 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700291
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700292 return ParseSuccess;
293}
Chris Lattnere79379a2018-06-22 10:39:19 -0700294
295//===----------------------------------------------------------------------===//
296// Type Parsing
297//===----------------------------------------------------------------------===//
298
Chris Lattnerc3251192018-07-27 13:09:58 -0700299/// Parse an arbitrary type.
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700300///
Chris Lattnerc3251192018-07-27 13:09:58 -0700301/// type ::= integer-type
302/// | float-type
303/// | other-type
304/// | vector-type
305/// | tensor-type
306/// | memref-type
307/// | function-type
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700308///
Chris Lattnerc3251192018-07-27 13:09:58 -0700309/// float-type ::= `f16` | `bf16` | `f32` | `f64`
310/// other-type ::= `affineint` | `tf_control`
311///
312Type *Parser::parseType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700313 switch (getToken().getKind()) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700314 default:
315 return (emitError("expected type"), nullptr);
Chris Lattnerc3251192018-07-27 13:09:58 -0700316 case Token::kw_memref:
317 return parseMemRefType();
318 case Token::kw_tensor:
319 return parseTensorType();
320 case Token::kw_vector:
321 return parseVectorType();
322 case Token::l_paren:
323 return parseFunctionType();
324 // integer-type
325 case Token::inttype: {
326 auto width = getToken().getIntTypeBitwidth();
327 if (!width.hasValue())
328 return (emitError("invalid integer width"), nullptr);
Nicolas Vasilache1b8c0842018-08-27 10:26:15 -0700329 if (width > IntegerType::kMaxWidth)
330 return (emitError("integer bitwidth is limited to " +
331 Twine(IntegerType::kMaxWidth) + " bits"),
332 nullptr);
Chris Lattnerc3251192018-07-27 13:09:58 -0700333 consumeToken(Token::inttype);
334 return builder.getIntegerType(width.getValue());
335 }
336
337 // float-type
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700338 case Token::kw_bf16:
339 consumeToken(Token::kw_bf16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700340 return builder.getBF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700341 case Token::kw_f16:
342 consumeToken(Token::kw_f16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700343 return builder.getF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700344 case Token::kw_f32:
345 consumeToken(Token::kw_f32);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700346 return builder.getF32Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700347 case Token::kw_f64:
348 consumeToken(Token::kw_f64);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700349 return builder.getF64Type();
Chris Lattnerc3251192018-07-27 13:09:58 -0700350
351 // other-type
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700352 case Token::kw_affineint:
353 consumeToken(Token::kw_affineint);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700354 return builder.getAffineIntType();
Jacques Pienaarc0d69302018-07-27 11:07:12 -0700355 case Token::kw_tf_control:
356 consumeToken(Token::kw_tf_control);
357 return builder.getTFControlType();
James Molloy72b0cbe2018-08-01 12:55:27 -0700358 case Token::kw_tf_string:
359 consumeToken(Token::kw_tf_string);
360 return builder.getTFStringType();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700361 }
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700362}
363
364/// Parse a vector type.
365///
366/// vector-type ::= `vector` `<` const-dimension-list primitive-type `>`
367/// const-dimension-list ::= (integer-literal `x`)+
368///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700369VectorType *Parser::parseVectorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700370 consumeToken(Token::kw_vector);
371
Chris Lattnerf7702a62018-07-23 17:30:01 -0700372 if (parseToken(Token::less, "expected '<' in vector type"))
373 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700374
Chris Lattner48af7d12018-07-09 19:05:38 -0700375 if (getToken().isNot(Token::integer))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700376 return (emitError("expected dimension size in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700377
378 SmallVector<unsigned, 4> dimensions;
Chris Lattner48af7d12018-07-09 19:05:38 -0700379 while (getToken().is(Token::integer)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700380 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700381 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700382 if (!dimension.hasValue())
Chris Lattnerf7e22732018-06-22 22:03:48 -0700383 return (emitError("invalid dimension in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700384 dimensions.push_back(dimension.getValue());
385
386 consumeToken(Token::integer);
387
388 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700389 if (getToken().isNot(Token::bare_identifier) ||
390 getTokenSpelling()[0] != 'x')
Chris Lattnerf7e22732018-06-22 22:03:48 -0700391 return (emitError("expected 'x' in vector dimension list"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700392
393 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700394 if (getTokenSpelling().size() != 1)
395 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700396
397 // Consume the 'x'.
398 consumeToken(Token::bare_identifier);
399 }
400
401 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700402 auto typeLoc = getToken().getLoc();
403 auto *elementType = parseType();
404 if (!elementType || parseToken(Token::greater, "expected '>' in vector type"))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700405 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700406
Chris Lattnerc3251192018-07-27 13:09:58 -0700407 if (!isa<FloatType>(elementType) && !isa<IntegerType>(elementType))
408 return (emitError(typeLoc, "invalid vector element type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700409
Chris Lattnerf7e22732018-06-22 22:03:48 -0700410 return VectorType::get(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700411}
412
413/// Parse a dimension list of a tensor or memref type. This populates the
414/// dimension list, returning -1 for the '?' dimensions.
415///
416/// dimension-list-ranked ::= (dimension `x`)*
417/// dimension ::= `?` | integer-literal
418///
419ParseResult Parser::parseDimensionListRanked(SmallVectorImpl<int> &dimensions) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700420 while (getToken().isAny(Token::integer, Token::question)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700421 if (consumeIf(Token::question)) {
422 dimensions.push_back(-1);
423 } else {
424 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700425 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700426 if (!dimension.hasValue() || (int)dimension.getValue() < 0)
427 return emitError("invalid dimension");
428 dimensions.push_back((int)dimension.getValue());
429 consumeToken(Token::integer);
430 }
431
432 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700433 if (getToken().isNot(Token::bare_identifier) ||
434 getTokenSpelling()[0] != 'x')
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700435 return emitError("expected 'x' in dimension list");
436
437 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700438 if (getTokenSpelling().size() != 1)
439 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700440
441 // Consume the 'x'.
442 consumeToken(Token::bare_identifier);
443 }
444
445 return ParseSuccess;
446}
447
448/// Parse a tensor type.
449///
450/// tensor-type ::= `tensor` `<` dimension-list element-type `>`
451/// dimension-list ::= dimension-list-ranked | `??`
452///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700453Type *Parser::parseTensorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700454 consumeToken(Token::kw_tensor);
455
Chris Lattnerf7702a62018-07-23 17:30:01 -0700456 if (parseToken(Token::less, "expected '<' in tensor type"))
457 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700458
459 bool isUnranked;
460 SmallVector<int, 4> dimensions;
461
462 if (consumeIf(Token::questionquestion)) {
463 isUnranked = true;
464 } else {
465 isUnranked = false;
466 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700467 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700468 }
469
470 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700471 auto typeLoc = getToken().getLoc();
472 auto *elementType = parseType();
473 if (!elementType || parseToken(Token::greater, "expected '>' in tensor type"))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700474 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700475
Chris Lattnerc3251192018-07-27 13:09:58 -0700476 if (!isa<IntegerType>(elementType) && !isa<FloatType>(elementType) &&
477 !isa<VectorType>(elementType))
478 return (emitError(typeLoc, "invalid tensor element type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700479
MLIR Team355ec862018-06-23 18:09:09 -0700480 if (isUnranked)
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700481 return builder.getTensorType(elementType);
482 return builder.getTensorType(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700483}
484
485/// Parse a memref type.
486///
487/// memref-type ::= `memref` `<` dimension-list-ranked element-type
488/// (`,` semi-affine-map-composition)? (`,` memory-space)? `>`
489///
490/// semi-affine-map-composition ::= (semi-affine-map `,` )* semi-affine-map
491/// memory-space ::= integer-literal /* | TODO: address-space-id */
492///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700493Type *Parser::parseMemRefType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700494 consumeToken(Token::kw_memref);
495
Chris Lattnerf7702a62018-07-23 17:30:01 -0700496 if (parseToken(Token::less, "expected '<' in memref type"))
497 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700498
499 SmallVector<int, 4> dimensions;
500 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700501 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700502
503 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700504 auto typeLoc = getToken().getLoc();
505 auto *elementType = parseType();
Chris Lattnerf7e22732018-06-22 22:03:48 -0700506 if (!elementType)
507 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700508
Chris Lattnerc3251192018-07-27 13:09:58 -0700509 if (!isa<IntegerType>(elementType) && !isa<FloatType>(elementType) &&
510 !isa<VectorType>(elementType))
511 return (emitError(typeLoc, "invalid memref element type"), nullptr);
512
MLIR Team718c82f2018-07-16 09:45:22 -0700513 // Parse semi-affine-map-composition.
James Molloy0ff71542018-07-23 16:56:32 -0700514 SmallVector<AffineMap *, 2> affineMapComposition;
Chris Lattner413db6a2018-07-25 12:55:50 -0700515 unsigned memorySpace = 0;
MLIR Team718c82f2018-07-16 09:45:22 -0700516 bool parsedMemorySpace = false;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700517
MLIR Team718c82f2018-07-16 09:45:22 -0700518 auto parseElt = [&]() -> ParseResult {
519 if (getToken().is(Token::integer)) {
520 // Parse memory space.
521 if (parsedMemorySpace)
522 return emitError("multiple memory spaces specified in memref type");
523 auto v = getToken().getUnsignedIntegerValue();
524 if (!v.hasValue())
525 return emitError("invalid memory space in memref type");
526 memorySpace = v.getValue();
527 consumeToken(Token::integer);
528 parsedMemorySpace = true;
529 } else {
530 // Parse affine map.
531 if (parsedMemorySpace)
532 return emitError("affine map after memory space in memref type");
James Molloy0ff71542018-07-23 16:56:32 -0700533 auto *affineMap = parseAffineMapReference();
MLIR Team718c82f2018-07-16 09:45:22 -0700534 if (affineMap == nullptr)
535 return ParseFailure;
536 affineMapComposition.push_back(affineMap);
537 }
538 return ParseSuccess;
539 };
540
Chris Lattner413db6a2018-07-25 12:55:50 -0700541 // Parse a list of mappings and address space if present.
542 if (consumeIf(Token::comma)) {
543 // Parse comma separated list of affine maps, followed by memory space.
544 if (parseCommaSeparatedListUntil(Token::greater, parseElt,
545 /*allowEmptyList=*/false)) {
546 return nullptr;
547 }
548 } else {
549 if (parseToken(Token::greater, "expected ',' or '>' in memref type"))
550 return nullptr;
MLIR Team718c82f2018-07-16 09:45:22 -0700551 }
MLIR Team718c82f2018-07-16 09:45:22 -0700552
553 return MemRefType::get(dimensions, elementType, affineMapComposition,
554 memorySpace);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700555}
556
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700557/// Parse a function type.
558///
559/// function-type ::= type-list-parens `->` type-list
560///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700561Type *Parser::parseFunctionType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700562 assert(getToken().is(Token::l_paren));
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700563
Chris Lattnerf7702a62018-07-23 17:30:01 -0700564 SmallVector<Type *, 4> arguments, results;
565 if (parseTypeList(arguments) ||
566 parseToken(Token::arrow, "expected '->' in function type") ||
567 parseTypeList(results))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700568 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700569
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700570 return builder.getFunctionType(arguments, results);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700571}
572
Chris Lattner1604e472018-07-23 08:42:19 -0700573/// Parse a list of types without an enclosing parenthesis. The list must have
574/// at least one member.
575///
576/// type-list-no-parens ::= type (`,` type)*
577///
578ParseResult Parser::parseTypeListNoParens(SmallVectorImpl<Type *> &elements) {
579 auto parseElt = [&]() -> ParseResult {
580 auto elt = parseType();
581 elements.push_back(elt);
582 return elt ? ParseSuccess : ParseFailure;
583 };
584
585 return parseCommaSeparatedList(parseElt);
586}
587
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700588/// Parse a "type list", which is a singular type, or a parenthesized list of
589/// types.
590///
591/// type-list ::= type-list-parens | type
592/// type-list-parens ::= `(` `)`
Chris Lattner1604e472018-07-23 08:42:19 -0700593/// | `(` type-list-no-parens `)`
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700594///
James Molloy0ff71542018-07-23 16:56:32 -0700595ParseResult Parser::parseTypeList(SmallVectorImpl<Type *> &elements) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700596 auto parseElt = [&]() -> ParseResult {
597 auto elt = parseType();
598 elements.push_back(elt);
599 return elt ? ParseSuccess : ParseFailure;
600 };
601
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700602 // If there is no parens, then it must be a singular type.
603 if (!consumeIf(Token::l_paren))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700604 return parseElt();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700605
Chris Lattner40746442018-07-21 14:32:09 -0700606 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700607 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700608
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700609 return ParseSuccess;
610}
611
Chris Lattner4c95a502018-06-23 16:03:42 -0700612//===----------------------------------------------------------------------===//
Chris Lattner7121b802018-07-04 20:45:39 -0700613// Attribute parsing.
614//===----------------------------------------------------------------------===//
615
Chris Lattner1aa46322018-08-21 17:55:22 -0700616/// Given a parsed reference to a function name like @foo and a type that it
617/// corresponds to, resolve it to a concrete function object (possibly
618/// synthesizing a forward reference) or emit an error and return null on
619/// failure.
620Function *Parser::resolveFunctionReference(StringRef nameStr, SMLoc nameLoc,
621 FunctionType *type) {
622 Identifier name = builder.getIdentifier(nameStr.drop_front());
623
624 // See if the function has already been defined in the module.
625 Function *function = getModule()->getNamedFunction(name);
626
627 // If not, get or create a forward reference to one.
628 if (!function) {
629 auto &entry = state.functionForwardRefs[name];
630 if (!entry.first) {
631 entry.first = new ExtFunction(name, type);
632 entry.second = nameLoc;
633 }
634 function = entry.first;
635 }
636
637 if (function->getType() != type)
638 return (emitError(nameLoc, "reference to function with mismatched type"),
639 nullptr);
640 return function;
641}
642
Chris Lattner7121b802018-07-04 20:45:39 -0700643/// Attribute parsing.
644///
645/// attribute-value ::= bool-literal
646/// | integer-literal
647/// | float-literal
648/// | string-literal
James Molloyf0d2f442018-08-03 01:54:46 -0700649/// | type
Chris Lattner7121b802018-07-04 20:45:39 -0700650/// | `[` (attribute-value (`,` attribute-value)*)? `]`
Chris Lattner4613d9e2018-08-19 21:17:22 -0700651/// | function-id `:` function-type
Chris Lattner7121b802018-07-04 20:45:39 -0700652///
653Attribute *Parser::parseAttribute() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700654 switch (getToken().getKind()) {
Chris Lattner7121b802018-07-04 20:45:39 -0700655 case Token::kw_true:
656 consumeToken(Token::kw_true);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700657 return builder.getBoolAttr(true);
Chris Lattner7121b802018-07-04 20:45:39 -0700658 case Token::kw_false:
659 consumeToken(Token::kw_false);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700660 return builder.getBoolAttr(false);
Chris Lattner7121b802018-07-04 20:45:39 -0700661
Jacques Pienaar84491092018-07-31 17:15:15 -0700662 case Token::floatliteral: {
663 auto val = getToken().getFloatingPointValue();
664 if (!val.hasValue())
665 return (emitError("floating point value too large for attribute"),
666 nullptr);
667 consumeToken(Token::floatliteral);
668 return builder.getFloatAttr(val.getValue());
669 }
Chris Lattner7121b802018-07-04 20:45:39 -0700670 case Token::integer: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700671 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700672 if (!val.hasValue() || (int64_t)val.getValue() < 0)
673 return (emitError("integer too large for attribute"), nullptr);
674 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700675 return builder.getIntegerAttr((int64_t)val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700676 }
677
678 case Token::minus: {
679 consumeToken(Token::minus);
Chris Lattner48af7d12018-07-09 19:05:38 -0700680 if (getToken().is(Token::integer)) {
681 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700682 if (!val.hasValue() || (int64_t)-val.getValue() >= 0)
683 return (emitError("integer too large for attribute"), nullptr);
684 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700685 return builder.getIntegerAttr((int64_t)-val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700686 }
Jacques Pienaar84491092018-07-31 17:15:15 -0700687 if (getToken().is(Token::floatliteral)) {
688 auto val = getToken().getFloatingPointValue();
689 if (!val.hasValue())
690 return (emitError("floating point value too large for attribute"),
691 nullptr);
692 consumeToken(Token::floatliteral);
693 return builder.getFloatAttr(-val.getValue());
694 }
Chris Lattner7121b802018-07-04 20:45:39 -0700695
696 return (emitError("expected constant integer or floating point value"),
697 nullptr);
698 }
699
700 case Token::string: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700701 auto val = getToken().getStringValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700702 consumeToken(Token::string);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700703 return builder.getStringAttr(val);
Chris Lattner7121b802018-07-04 20:45:39 -0700704 }
705
Chris Lattner85ee1512018-07-25 11:15:20 -0700706 case Token::l_square: {
707 consumeToken(Token::l_square);
James Molloy0ff71542018-07-23 16:56:32 -0700708 SmallVector<Attribute *, 4> elements;
Chris Lattner7121b802018-07-04 20:45:39 -0700709
710 auto parseElt = [&]() -> ParseResult {
711 elements.push_back(parseAttribute());
712 return elements.back() ? ParseSuccess : ParseFailure;
713 };
714
Chris Lattner85ee1512018-07-25 11:15:20 -0700715 if (parseCommaSeparatedListUntil(Token::r_square, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700716 return nullptr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700717 return builder.getArrayAttr(elements);
Chris Lattner7121b802018-07-04 20:45:39 -0700718 }
James Molloyf0d2f442018-08-03 01:54:46 -0700719 case Token::hash_identifier:
720 case Token::l_paren: {
MLIR Teamb61885d2018-07-18 16:29:21 -0700721 // Try to parse affine map reference.
James Molloyf0d2f442018-08-03 01:54:46 -0700722 if (auto *affineMap = parseAffineMapReference())
MLIR Teamb61885d2018-07-18 16:29:21 -0700723 return builder.getAffineMapAttr(affineMap);
Chris Lattner7121b802018-07-04 20:45:39 -0700724 return (emitError("expected constant attribute value"), nullptr);
725 }
Chris Lattner4613d9e2018-08-19 21:17:22 -0700726
727 case Token::at_identifier: {
728 auto nameLoc = getToken().getLoc();
Chris Lattner1aa46322018-08-21 17:55:22 -0700729 auto nameStr = getTokenSpelling();
Chris Lattner4613d9e2018-08-19 21:17:22 -0700730 consumeToken(Token::at_identifier);
731
732 if (parseToken(Token::colon, "expected ':' and function type"))
733 return nullptr;
734 auto typeLoc = getToken().getLoc();
735 Type *type = parseType();
736 if (!type)
737 return nullptr;
Chris Lattner1aa46322018-08-21 17:55:22 -0700738 auto *fnType = dyn_cast<FunctionType>(type);
Chris Lattner4613d9e2018-08-19 21:17:22 -0700739 if (!fnType)
740 return (emitError(typeLoc, "expected function type"), nullptr);
741
Chris Lattner1aa46322018-08-21 17:55:22 -0700742 auto *function = resolveFunctionReference(nameStr, nameLoc, fnType);
743 return function ? builder.getFunctionAttr(function) : nullptr;
Chris Lattner4613d9e2018-08-19 21:17:22 -0700744 }
745
James Molloyf0d2f442018-08-03 01:54:46 -0700746 default: {
747 if (Type *type = parseType())
748 return builder.getTypeAttr(type);
749 return nullptr;
750 }
751 }
Chris Lattner7121b802018-07-04 20:45:39 -0700752}
753
Chris Lattner7121b802018-07-04 20:45:39 -0700754/// Attribute dictionary.
755///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700756/// attribute-dict ::= `{` `}`
757/// | `{` attribute-entry (`,` attribute-entry)* `}`
758/// attribute-entry ::= bare-id `:` attribute-value
Chris Lattner7121b802018-07-04 20:45:39 -0700759///
James Molloy0ff71542018-07-23 16:56:32 -0700760ParseResult
761Parser::parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes) {
Chris Lattner7121b802018-07-04 20:45:39 -0700762 consumeToken(Token::l_brace);
763
764 auto parseElt = [&]() -> ParseResult {
765 // We allow keywords as attribute names.
Chris Lattner48af7d12018-07-09 19:05:38 -0700766 if (getToken().isNot(Token::bare_identifier, Token::inttype) &&
767 !getToken().isKeyword())
Chris Lattner7121b802018-07-04 20:45:39 -0700768 return emitError("expected attribute name");
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700769 auto nameId = builder.getIdentifier(getTokenSpelling());
Chris Lattner7121b802018-07-04 20:45:39 -0700770 consumeToken();
771
Chris Lattnerf7702a62018-07-23 17:30:01 -0700772 if (parseToken(Token::colon, "expected ':' in attribute list"))
773 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700774
775 auto attr = parseAttribute();
James Molloy0ff71542018-07-23 16:56:32 -0700776 if (!attr)
777 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700778
779 attributes.push_back({nameId, attr});
780 return ParseSuccess;
781 };
782
Chris Lattner40746442018-07-21 14:32:09 -0700783 if (parseCommaSeparatedListUntil(Token::r_brace, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700784 return ParseFailure;
785
786 return ParseSuccess;
787}
788
789//===----------------------------------------------------------------------===//
MLIR Teamf85a6262018-06-27 11:03:08 -0700790// Polyhedral structures.
791//===----------------------------------------------------------------------===//
792
Chris Lattner2e595eb2018-07-10 10:08:27 -0700793/// Lower precedence ops (all at the same precedence level). LNoOp is false in
794/// the boolean sense.
795enum AffineLowPrecOp {
796 /// Null value.
797 LNoOp,
798 Add,
799 Sub
800};
MLIR Teamf85a6262018-06-27 11:03:08 -0700801
Chris Lattner2e595eb2018-07-10 10:08:27 -0700802/// Higher precedence ops - all at the same precedence level. HNoOp is false in
803/// the boolean sense.
804enum AffineHighPrecOp {
805 /// Null value.
806 HNoOp,
807 Mul,
808 FloorDiv,
809 CeilDiv,
810 Mod
811};
Chris Lattner7121b802018-07-04 20:45:39 -0700812
Chris Lattner2e595eb2018-07-10 10:08:27 -0700813namespace {
Uday Bondhugulabc535622018-08-07 14:24:38 -0700814/// This is a specialized parser for affine structures (affine maps, affine
815/// expressions, and integer sets), maintaining the state transient to their
816/// bodies.
817class AffineParser : public Parser {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700818public:
Uday Bondhugulabc535622018-08-07 14:24:38 -0700819 explicit AffineParser(ParserState &state) : Parser(state) {}
Chris Lattner7121b802018-07-04 20:45:39 -0700820
Chris Lattner2e595eb2018-07-10 10:08:27 -0700821 AffineMap *parseAffineMapInline();
Uday Bondhugulabc535622018-08-07 14:24:38 -0700822 IntegerSet *parseIntegerSetInline();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700823
Chris Lattner2e595eb2018-07-10 10:08:27 -0700824private:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700825 // Binary affine op parsing.
826 AffineLowPrecOp consumeIfLowPrecOp();
827 AffineHighPrecOp consumeIfHighPrecOp();
MLIR Teamf85a6262018-06-27 11:03:08 -0700828
Chris Lattner2e595eb2018-07-10 10:08:27 -0700829 // Identifier lists for polyhedral structures.
Chris Lattner413db6a2018-07-25 12:55:50 -0700830 ParseResult parseDimIdList(unsigned &numDims);
831 ParseResult parseSymbolIdList(unsigned &numSymbols);
832 ParseResult parseIdentifierDefinition(AffineExpr *idExpr);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700833
834 AffineExpr *parseAffineExpr();
835 AffineExpr *parseParentheticalExpr();
836 AffineExpr *parseNegateExpression(AffineExpr *lhs);
837 AffineExpr *parseIntegerExpr();
838 AffineExpr *parseBareIdExpr();
839
840 AffineExpr *getBinaryAffineOpExpr(AffineHighPrecOp op, AffineExpr *lhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700841 AffineExpr *rhs, SMLoc opLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700842 AffineExpr *getBinaryAffineOpExpr(AffineLowPrecOp op, AffineExpr *lhs,
843 AffineExpr *rhs);
844 AffineExpr *parseAffineOperandExpr(AffineExpr *lhs);
845 AffineExpr *parseAffineLowPrecOpExpr(AffineExpr *llhs,
846 AffineLowPrecOp llhsOp);
847 AffineExpr *parseAffineHighPrecOpExpr(AffineExpr *llhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700848 AffineHighPrecOp llhsOp,
849 SMLoc llhsOpLoc);
Uday Bondhugulabc535622018-08-07 14:24:38 -0700850 AffineExpr *parseAffineConstraint(bool *isEq);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700851
852private:
Chris Lattner413db6a2018-07-25 12:55:50 -0700853 SmallVector<std::pair<StringRef, AffineExpr *>, 4> dimsAndSymbols;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700854};
855} // end anonymous namespace
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700856
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700857/// Create an affine binary high precedence op expression (mul's, div's, mod).
858/// opLoc is the location of the op token to be used to report errors
859/// for non-conforming expressions.
Uday Bondhugulabc535622018-08-07 14:24:38 -0700860AffineExpr *AffineParser::getBinaryAffineOpExpr(AffineHighPrecOp op,
861 AffineExpr *lhs,
862 AffineExpr *rhs, SMLoc opLoc) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700863 // TODO: make the error location info accurate.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700864 switch (op) {
865 case Mul:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700866 if (!lhs->isSymbolicOrConstant() && !rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700867 emitError(opLoc, "non-affine expression: at least one of the multiply "
868 "operands has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700869 return nullptr;
870 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700871 return builder.getMulExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700872 case FloorDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700873 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700874 emitError(opLoc, "non-affine expression: right operand of floordiv "
875 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700876 return nullptr;
877 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700878 return builder.getFloorDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700879 case CeilDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700880 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700881 emitError(opLoc, "non-affine expression: right operand of ceildiv "
882 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700883 return nullptr;
884 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700885 return builder.getCeilDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700886 case Mod:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700887 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700888 emitError(opLoc, "non-affine expression: right operand of mod "
889 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700890 return nullptr;
891 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700892 return builder.getModExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700893 case HNoOp:
894 llvm_unreachable("can't create affine expression for null high prec op");
895 return nullptr;
896 }
897}
898
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700899/// Create an affine binary low precedence op expression (add, sub).
Uday Bondhugulabc535622018-08-07 14:24:38 -0700900AffineExpr *AffineParser::getBinaryAffineOpExpr(AffineLowPrecOp op,
901 AffineExpr *lhs,
902 AffineExpr *rhs) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700903 switch (op) {
904 case AffineLowPrecOp::Add:
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700905 return builder.getAddExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700906 case AffineLowPrecOp::Sub:
Uday Bondhugulac1faf662018-07-19 14:08:50 -0700907 return builder.getAddExpr(
908 lhs, builder.getMulExpr(rhs, builder.getConstantExpr(-1)));
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700909 case AffineLowPrecOp::LNoOp:
910 llvm_unreachable("can't create affine expression for null low prec op");
911 return nullptr;
912 }
913}
914
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700915/// Consume this token if it is a lower precedence affine op (there are only two
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700916/// precedence levels).
Uday Bondhugulabc535622018-08-07 14:24:38 -0700917AffineLowPrecOp AffineParser::consumeIfLowPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700918 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700919 case Token::plus:
920 consumeToken(Token::plus);
921 return AffineLowPrecOp::Add;
922 case Token::minus:
923 consumeToken(Token::minus);
924 return AffineLowPrecOp::Sub;
925 default:
926 return AffineLowPrecOp::LNoOp;
927 }
928}
929
930/// Consume this token if it is a higher precedence affine op (there are only
931/// two precedence levels)
Uday Bondhugulabc535622018-08-07 14:24:38 -0700932AffineHighPrecOp AffineParser::consumeIfHighPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700933 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700934 case Token::star:
935 consumeToken(Token::star);
936 return Mul;
937 case Token::kw_floordiv:
938 consumeToken(Token::kw_floordiv);
939 return FloorDiv;
940 case Token::kw_ceildiv:
941 consumeToken(Token::kw_ceildiv);
942 return CeilDiv;
943 case Token::kw_mod:
944 consumeToken(Token::kw_mod);
945 return Mod;
946 default:
947 return HNoOp;
948 }
949}
950
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700951/// Parse a high precedence op expression list: mul, div, and mod are high
952/// precedence binary ops, i.e., parse a
953/// expr_1 op_1 expr_2 op_2 ... expr_n
954/// where op_1, op_2 are all a AffineHighPrecOp (mul, div, mod).
955/// All affine binary ops are left associative.
956/// Given llhs, returns (llhs llhsOp lhs) op rhs, or (lhs op rhs) if llhs is
957/// null. If no rhs can be found, returns (llhs llhsOp lhs) or lhs if llhs is
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700958/// null. llhsOpLoc is the location of the llhsOp token that will be used to
959/// report an error for non-conforming expressions.
Uday Bondhugulabc535622018-08-07 14:24:38 -0700960AffineExpr *AffineParser::parseAffineHighPrecOpExpr(AffineExpr *llhs,
961 AffineHighPrecOp llhsOp,
962 SMLoc llhsOpLoc) {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700963 AffineExpr *lhs = parseAffineOperandExpr(llhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700964 if (!lhs)
965 return nullptr;
966
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700967 // Found an LHS. Parse the remaining expression.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700968 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -0700969 if (AffineHighPrecOp op = consumeIfHighPrecOp()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700970 if (llhs) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700971 AffineExpr *expr = getBinaryAffineOpExpr(llhsOp, llhs, lhs, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700972 if (!expr)
973 return nullptr;
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700974 return parseAffineHighPrecOpExpr(expr, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700975 }
976 // No LLHS, get RHS
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700977 return parseAffineHighPrecOpExpr(lhs, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700978 }
979
980 // This is the last operand in this expression.
981 if (llhs)
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700982 return getBinaryAffineOpExpr(llhsOp, llhs, lhs, llhsOpLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700983
984 // No llhs, 'lhs' itself is the expression.
985 return lhs;
986}
987
988/// Parse an affine expression inside parentheses.
989///
990/// affine-expr ::= `(` affine-expr `)`
Uday Bondhugulabc535622018-08-07 14:24:38 -0700991AffineExpr *AffineParser::parseParentheticalExpr() {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700992 if (parseToken(Token::l_paren, "expected '('"))
993 return nullptr;
Chris Lattner48af7d12018-07-09 19:05:38 -0700994 if (getToken().is(Token::r_paren))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700995 return (emitError("no expression inside parentheses"), nullptr);
Chris Lattnerf7702a62018-07-23 17:30:01 -0700996
Chris Lattner2e595eb2018-07-10 10:08:27 -0700997 auto *expr = parseAffineExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700998 if (!expr)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700999 return nullptr;
Chris Lattnerf7702a62018-07-23 17:30:01 -07001000 if (parseToken(Token::r_paren, "expected ')'"))
1001 return nullptr;
1002
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001003 return expr;
1004}
1005
1006/// Parse the negation expression.
1007///
1008/// affine-expr ::= `-` affine-expr
Uday Bondhugulabc535622018-08-07 14:24:38 -07001009AffineExpr *AffineParser::parseNegateExpression(AffineExpr *lhs) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07001010 if (parseToken(Token::minus, "expected '-'"))
1011 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001012
Chris Lattner2e595eb2018-07-10 10:08:27 -07001013 AffineExpr *operand = parseAffineOperandExpr(lhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001014 // Since negation has the highest precedence of all ops (including high
1015 // precedence ops) but lower than parentheses, we are only going to use
1016 // parseAffineOperandExpr instead of parseAffineExpr here.
1017 if (!operand)
1018 // Extra error message although parseAffineOperandExpr would have
1019 // complained. Leads to a better diagnostic.
1020 return (emitError("missing operand of negation"), nullptr);
Chris Lattner1ac20cb2018-07-10 10:59:53 -07001021 auto *minusOne = builder.getConstantExpr(-1);
1022 return builder.getMulExpr(minusOne, operand);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001023}
1024
1025/// Parse a bare id that may appear in an affine expression.
1026///
1027/// affine-expr ::= bare-id
Uday Bondhugulabc535622018-08-07 14:24:38 -07001028AffineExpr *AffineParser::parseBareIdExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -07001029 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001030 return (emitError("expected bare identifier"), nullptr);
1031
Chris Lattner48af7d12018-07-09 19:05:38 -07001032 StringRef sRef = getTokenSpelling();
Chris Lattner413db6a2018-07-25 12:55:50 -07001033 for (auto entry : dimsAndSymbols) {
Chris Lattnera8e47672018-07-25 14:08:16 -07001034 if (entry.first == sRef) {
1035 consumeToken(Token::bare_identifier);
1036 return entry.second;
1037 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001038 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001039
1040 return (emitError("use of undeclared identifier"), nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001041}
1042
1043/// Parse a positive integral constant appearing in an affine expression.
1044///
1045/// affine-expr ::= integer-literal
Uday Bondhugulabc535622018-08-07 14:24:38 -07001046AffineExpr *AffineParser::parseIntegerExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -07001047 auto val = getToken().getUInt64IntegerValue();
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07001048 if (!val.hasValue() || (int64_t)val.getValue() < 0)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001049 return (emitError("constant too large for affineint"), nullptr);
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07001050
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001051 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -07001052 return builder.getConstantExpr((int64_t)val.getValue());
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001053}
1054
1055/// Parses an expression that can be a valid operand of an affine expression.
Uday Bondhugula76345202018-07-09 13:47:52 -07001056/// lhs: if non-null, lhs is an affine expression that is the lhs of a binary
1057/// operator, the rhs of which is being parsed. This is used to determine
1058/// whether an error should be emitted for a missing right operand.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001059// Eg: for an expression without parentheses (like i + j + k + l), each
1060// of the four identifiers is an operand. For i + j*k + l, j*k is not an
1061// operand expression, it's an op expression and will be parsed via
1062// parseAffineHighPrecOpExpression(). However, for i + (j*k) + -l, (j*k) and -l
1063// are valid operands that will be parsed by this function.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001064AffineExpr *AffineParser::parseAffineOperandExpr(AffineExpr *lhs) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001065 switch (getToken().getKind()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001066 case Token::bare_identifier:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001067 return parseBareIdExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001068 case Token::integer:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001069 return parseIntegerExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001070 case Token::l_paren:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001071 return parseParentheticalExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001072 case Token::minus:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001073 return parseNegateExpression(lhs);
Uday Bondhugula76345202018-07-09 13:47:52 -07001074 case Token::kw_ceildiv:
1075 case Token::kw_floordiv:
1076 case Token::kw_mod:
1077 case Token::plus:
1078 case Token::star:
1079 if (lhs)
1080 emitError("missing right operand of binary operator");
1081 else
1082 emitError("missing left operand of binary operator");
1083 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001084 default:
1085 if (lhs)
Uday Bondhugula76345202018-07-09 13:47:52 -07001086 emitError("missing right operand of binary operator");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001087 else
1088 emitError("expected affine expression");
1089 return nullptr;
1090 }
1091}
1092
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001093/// Parse affine expressions that are bare-id's, integer constants,
1094/// parenthetical affine expressions, and affine op expressions that are a
1095/// composition of those.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001096///
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001097/// All binary op's associate from left to right.
1098///
1099/// {add, sub} have lower precedence than {mul, div, and mod}.
1100///
Uday Bondhugula76345202018-07-09 13:47:52 -07001101/// Add, sub'are themselves at the same precedence level. Mul, floordiv,
1102/// ceildiv, and mod are at the same higher precedence level. Negation has
1103/// higher precedence than any binary op.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001104///
1105/// llhs: the affine expression appearing on the left of the one being parsed.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001106/// This function will return ((llhs llhsOp lhs) op rhs) if llhs is non null,
1107/// and lhs op rhs otherwise; if there is no rhs, llhs llhsOp lhs is returned if
1108/// llhs is non-null; otherwise lhs is returned. This is to deal with left
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001109/// associativity.
1110///
1111/// Eg: when the expression is e1 + e2*e3 + e4, with e1 as llhs, this function
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001112/// will return the affine expr equivalent of (e1 + (e2*e3)) + e4, where (e2*e3)
1113/// will be parsed using parseAffineHighPrecOpExpr().
Uday Bondhugulabc535622018-08-07 14:24:38 -07001114AffineExpr *AffineParser::parseAffineLowPrecOpExpr(AffineExpr *llhs,
1115 AffineLowPrecOp llhsOp) {
Uday Bondhugula76345202018-07-09 13:47:52 -07001116 AffineExpr *lhs;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001117 if (!(lhs = parseAffineOperandExpr(llhs)))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001118 return nullptr;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001119
1120 // Found an LHS. Deal with the ops.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001121 if (AffineLowPrecOp lOp = consumeIfLowPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001122 if (llhs) {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001123 AffineExpr *sum = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001124 return parseAffineLowPrecOpExpr(sum, lOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001125 }
1126 // No LLHS, get RHS and form the expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001127 return parseAffineLowPrecOpExpr(lhs, lOp);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001128 }
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001129 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07001130 if (AffineHighPrecOp hOp = consumeIfHighPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001131 // We have a higher precedence op here. Get the rhs operand for the llhs
1132 // through parseAffineHighPrecOpExpr.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001133 AffineExpr *highRes = parseAffineHighPrecOpExpr(lhs, hOp, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001134 if (!highRes)
1135 return nullptr;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001136
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001137 // If llhs is null, the product forms the first operand of the yet to be
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001138 // found expression. If non-null, the op to associate with llhs is llhsOp.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001139 AffineExpr *expr =
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001140 llhs ? getBinaryAffineOpExpr(llhsOp, llhs, highRes) : highRes;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001141
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001142 // Recurse for subsequent low prec op's after the affine high prec op
1143 // expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001144 if (AffineLowPrecOp nextOp = consumeIfLowPrecOp())
1145 return parseAffineLowPrecOpExpr(expr, nextOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001146 return expr;
1147 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001148 // Last operand in the expression list.
1149 if (llhs)
1150 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
1151 // No llhs, 'lhs' itself is the expression.
1152 return lhs;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001153}
1154
1155/// Parse an affine expression.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001156/// affine-expr ::= `(` affine-expr `)`
1157/// | `-` affine-expr
1158/// | affine-expr `+` affine-expr
1159/// | affine-expr `-` affine-expr
1160/// | affine-expr `*` affine-expr
1161/// | affine-expr `floordiv` affine-expr
1162/// | affine-expr `ceildiv` affine-expr
1163/// | affine-expr `mod` affine-expr
1164/// | bare-id
1165/// | integer-literal
1166///
1167/// Additional conditions are checked depending on the production. For eg., one
1168/// of the operands for `*` has to be either constant/symbolic; the second
1169/// operand for floordiv, ceildiv, and mod has to be a positive integer.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001170AffineExpr *AffineParser::parseAffineExpr() {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001171 return parseAffineLowPrecOpExpr(nullptr, AffineLowPrecOp::LNoOp);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001172}
1173
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001174/// Parse a dim or symbol from the lists appearing before the actual expressions
Chris Lattner2e595eb2018-07-10 10:08:27 -07001175/// of the affine map. Update our state to store the dimensional/symbolic
Chris Lattner413db6a2018-07-25 12:55:50 -07001176/// identifier.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001177ParseResult AffineParser::parseIdentifierDefinition(AffineExpr *idExpr) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001178 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001179 return emitError("expected bare identifier");
Chris Lattner413db6a2018-07-25 12:55:50 -07001180
1181 auto name = getTokenSpelling();
1182 for (auto entry : dimsAndSymbols) {
1183 if (entry.first == name)
1184 return emitError("redefinition of identifier '" + Twine(name) + "'");
1185 }
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001186 consumeToken(Token::bare_identifier);
Chris Lattner413db6a2018-07-25 12:55:50 -07001187
1188 dimsAndSymbols.push_back({name, idExpr});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001189 return ParseSuccess;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001190}
1191
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001192/// Parse the list of symbolic identifiers to an affine map.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001193ParseResult AffineParser::parseSymbolIdList(unsigned &numSymbols) {
Chris Lattner413db6a2018-07-25 12:55:50 -07001194 consumeToken(Token::l_square);
1195 auto parseElt = [&]() -> ParseResult {
1196 auto *symbol = AffineSymbolExpr::get(numSymbols++, getContext());
1197 return parseIdentifierDefinition(symbol);
1198 };
Chris Lattner85ee1512018-07-25 11:15:20 -07001199 return parseCommaSeparatedListUntil(Token::r_square, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001200}
1201
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001202/// Parse the list of dimensional identifiers to an affine map.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001203ParseResult AffineParser::parseDimIdList(unsigned &numDims) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07001204 if (parseToken(Token::l_paren,
1205 "expected '(' at start of dimensional identifiers list"))
1206 return ParseFailure;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001207
Chris Lattner413db6a2018-07-25 12:55:50 -07001208 auto parseElt = [&]() -> ParseResult {
1209 auto *dimension = AffineDimExpr::get(numDims++, getContext());
1210 return parseIdentifierDefinition(dimension);
1211 };
Chris Lattner40746442018-07-21 14:32:09 -07001212 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001213}
1214
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001215/// Parse an affine map definition.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001216///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001217/// affine-map-inline ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
1218/// (`size` `(` dim-size (`,` dim-size)* `)`)?
1219/// dim-size ::= affine-expr | `min` `(` affine-expr ( `,` affine-expr)+ `)`
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001220///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001221/// multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Uday Bondhugulabc535622018-08-07 14:24:38 -07001222AffineMap *AffineParser::parseAffineMapInline() {
Chris Lattner413db6a2018-07-25 12:55:50 -07001223 unsigned numDims = 0, numSymbols = 0;
1224
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001225 // List of dimensional identifiers.
Chris Lattner413db6a2018-07-25 12:55:50 -07001226 if (parseDimIdList(numDims))
Chris Lattner7121b802018-07-04 20:45:39 -07001227 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001228
1229 // Symbols are optional.
Chris Lattner85ee1512018-07-25 11:15:20 -07001230 if (getToken().is(Token::l_square)) {
Chris Lattner413db6a2018-07-25 12:55:50 -07001231 if (parseSymbolIdList(numSymbols))
Chris Lattner7121b802018-07-04 20:45:39 -07001232 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001233 }
Chris Lattnerf7702a62018-07-23 17:30:01 -07001234
1235 if (parseToken(Token::arrow, "expected '->' or '['") ||
1236 parseToken(Token::l_paren, "expected '(' at start of affine map range"))
Chris Lattner7121b802018-07-04 20:45:39 -07001237 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001238
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001239 SmallVector<AffineExpr *, 4> exprs;
1240 auto parseElt = [&]() -> ParseResult {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001241 auto *elt = parseAffineExpr();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001242 ParseResult res = elt ? ParseSuccess : ParseFailure;
1243 exprs.push_back(elt);
1244 return res;
1245 };
1246
1247 // Parse a multi-dimensional affine expression (a comma-separated list of 1-d
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001248 // affine expressions); the list cannot be empty.
1249 // Grammar: multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner40746442018-07-21 14:32:09 -07001250 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt, false))
Chris Lattner7121b802018-07-04 20:45:39 -07001251 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001252
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001253 // Parse optional range sizes.
Uday Bondhugula1e500b42018-07-12 18:04:04 -07001254 // range-sizes ::= (`size` `(` dim-size (`,` dim-size)* `)`)?
1255 // dim-size ::= affine-expr | `min` `(` affine-expr (`,` affine-expr)+ `)`
1256 // TODO(bondhugula): support for min of several affine expressions.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001257 // TODO: check if sizes are non-negative whenever they are constant.
1258 SmallVector<AffineExpr *, 4> rangeSizes;
1259 if (consumeIf(Token::kw_size)) {
1260 // Location of the l_paren token (if it exists) for error reporting later.
1261 auto loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001262 if (parseToken(Token::l_paren, "expected '(' at start of affine map range"))
1263 return nullptr;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001264
1265 auto parseRangeSize = [&]() -> ParseResult {
Chris Lattner413db6a2018-07-25 12:55:50 -07001266 auto loc = getToken().getLoc();
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001267 auto *elt = parseAffineExpr();
Chris Lattner413db6a2018-07-25 12:55:50 -07001268 if (!elt)
1269 return ParseFailure;
1270
1271 if (!elt->isSymbolicOrConstant())
1272 return emitError(loc,
1273 "size expressions cannot refer to dimension values");
1274
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001275 rangeSizes.push_back(elt);
Chris Lattner413db6a2018-07-25 12:55:50 -07001276 return ParseSuccess;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001277 };
1278
Chris Lattner40746442018-07-21 14:32:09 -07001279 if (parseCommaSeparatedListUntil(Token::r_paren, parseRangeSize, false))
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001280 return nullptr;
1281 if (exprs.size() > rangeSizes.size())
1282 return (emitError(loc, "fewer range sizes than range expressions"),
1283 nullptr);
1284 if (exprs.size() < rangeSizes.size())
1285 return (emitError(loc, "more range sizes than range expressions"),
1286 nullptr);
1287 }
1288
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001289 // Parsed a valid affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001290 return builder.getAffineMap(numDims, numSymbols, exprs, rangeSizes);
MLIR Teamf85a6262018-06-27 11:03:08 -07001291}
1292
Chris Lattner2e595eb2018-07-10 10:08:27 -07001293AffineMap *Parser::parseAffineMapInline() {
Uday Bondhugulabc535622018-08-07 14:24:38 -07001294 return AffineParser(state).parseAffineMapInline();
Chris Lattner2e595eb2018-07-10 10:08:27 -07001295}
1296
MLIR Team718c82f2018-07-16 09:45:22 -07001297AffineMap *Parser::parseAffineMapReference() {
1298 if (getToken().is(Token::hash_identifier)) {
1299 // Parse affine map identifier and verify that it exists.
1300 StringRef affineMapId = getTokenSpelling().drop_front();
1301 if (getState().affineMapDefinitions.count(affineMapId) == 0)
1302 return (emitError("undefined affine map id '" + affineMapId + "'"),
1303 nullptr);
1304 consumeToken(Token::hash_identifier);
1305 return getState().affineMapDefinitions[affineMapId];
1306 }
1307 // Try to parse inline affine map.
1308 return parseAffineMapInline();
1309}
1310
MLIR Teamf85a6262018-06-27 11:03:08 -07001311//===----------------------------------------------------------------------===//
Chris Lattner7f9cc272018-07-19 08:35:28 -07001312// FunctionParser
Chris Lattner4c95a502018-06-23 16:03:42 -07001313//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001314
Chris Lattner7f9cc272018-07-19 08:35:28 -07001315namespace {
1316/// This class contains parser state that is common across CFG and ML functions,
1317/// notably for dealing with operations and SSA values.
1318class FunctionParser : public Parser {
1319public:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001320 enum class Kind { CFGFunc, MLFunc };
1321
1322 Kind getKind() const { return kind; }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001323
Chris Lattner6119d382018-07-20 18:41:34 -07001324 /// After the function is finished parsing, this function checks to see if
1325 /// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001326 ParseResult finalizeFunction(Function *func, SMLoc loc);
Chris Lattner6119d382018-07-20 18:41:34 -07001327
1328 /// This represents a use of an SSA value in the program. The first two
1329 /// entries in the tuple are the name and result number of a reference. The
1330 /// third is the location of the reference, which is used in case this ends up
1331 /// being a use of an undefined value.
1332 struct SSAUseInfo {
1333 StringRef name; // Value name, e.g. %42 or %abc
1334 unsigned number; // Number, specified with #12
1335 SMLoc loc; // Location of first definition or use.
1336 };
Chris Lattner7f9cc272018-07-19 08:35:28 -07001337
1338 /// Given a reference to an SSA value and its type, return a reference. This
1339 /// returns null on failure.
1340 SSAValue *resolveSSAUse(SSAUseInfo useInfo, Type *type);
1341
1342 /// Register a definition of a value with the symbol table.
1343 ParseResult addDefinition(SSAUseInfo useInfo, SSAValue *value);
1344
1345 // SSA parsing productions.
1346 ParseResult parseSSAUse(SSAUseInfo &result);
Chris Lattner40746442018-07-21 14:32:09 -07001347 ParseResult parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results);
James Molloy61a656c2018-07-22 15:45:24 -07001348
1349 template <typename ResultType>
1350 ResultType parseSSADefOrUseAndType(
1351 const std::function<ResultType(SSAUseInfo, Type *)> &action);
1352
1353 SSAValue *parseSSAUseAndType() {
1354 return parseSSADefOrUseAndType<SSAValue *>(
1355 [&](SSAUseInfo useInfo, Type *type) -> SSAValue * {
1356 return resolveSSAUse(useInfo, type);
1357 });
1358 }
Chris Lattner40746442018-07-21 14:32:09 -07001359
1360 template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001361 ParseResult
Chris Lattner2c402672018-07-23 11:56:17 -07001362 parseOptionalSSAUseAndTypeList(SmallVectorImpl<ValueTy *> &results,
1363 bool isParenthesized);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001364
1365 // Operations
1366 ParseResult parseOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner85ee1512018-07-25 11:15:20 -07001367 Operation *parseVerboseOperation(const CreateOperationFunction &createOpFunc);
1368 Operation *parseCustomOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001369
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001370protected:
1371 FunctionParser(ParserState &state, Kind kind) : Parser(state), kind(kind) {}
1372
Chris Lattner7f9cc272018-07-19 08:35:28 -07001373private:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001374 /// Kind indicates if this is CFG or ML function parser.
1375 Kind kind;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001376 /// This keeps track of all of the SSA values we are tracking, indexed by
Chris Lattner6119d382018-07-20 18:41:34 -07001377 /// their name. This has one entry per result number.
1378 llvm::StringMap<SmallVector<std::pair<SSAValue *, SMLoc>, 1>> values;
1379
1380 /// These are all of the placeholders we've made along with the location of
1381 /// their first reference, to allow checking for use of undefined values.
1382 DenseMap<SSAValue *, SMLoc> forwardReferencePlaceholders;
1383
1384 SSAValue *createForwardReferencePlaceholder(SMLoc loc, Type *type);
1385
1386 /// Return true if this is a forward reference.
1387 bool isForwardReferencePlaceholder(SSAValue *value) {
1388 return forwardReferencePlaceholders.count(value);
1389 }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001390};
1391} // end anonymous namespace
1392
Chris Lattner6119d382018-07-20 18:41:34 -07001393/// Create and remember a new placeholder for a forward reference.
1394SSAValue *FunctionParser::createForwardReferencePlaceholder(SMLoc loc,
1395 Type *type) {
1396 // Forward references are always created as instructions, even in ML
1397 // functions, because we just need something with a def/use chain.
1398 //
1399 // We create these placeholders as having an empty name, which we know cannot
1400 // be created through normal user input, allowing us to distinguish them.
1401 auto name = Identifier::get("placeholder", getContext());
Chris Lattnerfc647d52018-08-27 21:05:16 -07001402 auto *inst = OperationInst::create(getEncodedSourceLocation(loc), name,
1403 /*operands=*/{}, type,
1404 /*attributes=*/{}, getContext());
Chris Lattner6119d382018-07-20 18:41:34 -07001405 forwardReferencePlaceholders[inst->getResult(0)] = loc;
1406 return inst->getResult(0);
1407}
1408
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001409/// Given an unbound reference to an SSA value and its type, return the value
Chris Lattner7f9cc272018-07-19 08:35:28 -07001410/// it specifies. This returns null on failure.
1411SSAValue *FunctionParser::resolveSSAUse(SSAUseInfo useInfo, Type *type) {
Chris Lattner6119d382018-07-20 18:41:34 -07001412 auto &entries = values[useInfo.name];
1413
Chris Lattner7f9cc272018-07-19 08:35:28 -07001414 // If we have already seen a value of this name, return it.
Chris Lattner6119d382018-07-20 18:41:34 -07001415 if (useInfo.number < entries.size() && entries[useInfo.number].first) {
1416 auto *result = entries[useInfo.number].first;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001417 // Check that the type matches the other uses.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001418 if (result->getType() == type)
1419 return result;
1420
Chris Lattner6119d382018-07-20 18:41:34 -07001421 emitError(useInfo.loc, "use of value '" + useInfo.name.str() +
1422 "' expects different type than prior uses");
1423 emitError(entries[useInfo.number].second, "prior use here");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001424 return nullptr;
1425 }
1426
Chris Lattner6119d382018-07-20 18:41:34 -07001427 // Make sure we have enough slots for this.
1428 if (entries.size() <= useInfo.number)
1429 entries.resize(useInfo.number + 1);
1430
1431 // If the value has already been defined and this is an overly large result
1432 // number, diagnose that.
1433 if (entries[0].first && !isForwardReferencePlaceholder(entries[0].first))
1434 return (emitError(useInfo.loc, "reference to invalid result number"),
1435 nullptr);
1436
Tatiana Shpeismand880b352018-07-31 23:14:16 -07001437 // Otherwise, this is a forward reference. If we are in ML function return
1438 // an error. In CFG function, create a placeholder and remember
1439 // that we did so.
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001440 if (getKind() == Kind::MLFunc)
1441 return (
1442 emitError(useInfo.loc, "use of undefined SSA value " + useInfo.name),
1443 nullptr);
1444
Chris Lattner6119d382018-07-20 18:41:34 -07001445 auto *result = createForwardReferencePlaceholder(useInfo.loc, type);
1446 entries[useInfo.number].first = result;
1447 entries[useInfo.number].second = useInfo.loc;
1448 return result;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001449}
1450
1451/// Register a definition of a value with the symbol table.
1452ParseResult FunctionParser::addDefinition(SSAUseInfo useInfo, SSAValue *value) {
Chris Lattner6119d382018-07-20 18:41:34 -07001453 auto &entries = values[useInfo.name];
Chris Lattner7f9cc272018-07-19 08:35:28 -07001454
Chris Lattner6119d382018-07-20 18:41:34 -07001455 // Make sure there is a slot for this value.
1456 if (entries.size() <= useInfo.number)
1457 entries.resize(useInfo.number + 1);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001458
Chris Lattner6119d382018-07-20 18:41:34 -07001459 // If we already have an entry for this, check to see if it was a definition
1460 // or a forward reference.
1461 if (auto *existing = entries[useInfo.number].first) {
1462 if (!isForwardReferencePlaceholder(existing)) {
1463 emitError(useInfo.loc,
1464 "redefinition of SSA value '" + useInfo.name + "'");
1465 return emitError(entries[useInfo.number].second,
1466 "previously defined here");
1467 }
1468
1469 // If it was a forward reference, update everything that used it to use the
1470 // actual definition instead, delete the forward ref, and remove it from our
1471 // set of forward references we track.
1472 existing->replaceAllUsesWith(value);
1473 existing->getDefiningInst()->destroy();
1474 forwardReferencePlaceholders.erase(existing);
1475 }
1476
1477 entries[useInfo.number].first = value;
1478 entries[useInfo.number].second = useInfo.loc;
1479 return ParseSuccess;
1480}
1481
1482/// After the function is finished parsing, this function checks to see if
1483/// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001484ParseResult FunctionParser::finalizeFunction(Function *func, SMLoc loc) {
Chris Lattner6119d382018-07-20 18:41:34 -07001485 // Check for any forward references that are left. If we find any, error out.
1486 if (!forwardReferencePlaceholders.empty()) {
1487 SmallVector<std::pair<const char *, SSAValue *>, 4> errors;
1488 // Iteration over the map isn't determinstic, so sort by source location.
1489 for (auto entry : forwardReferencePlaceholders)
1490 errors.push_back({entry.second.getPointer(), entry.first});
1491 llvm::array_pod_sort(errors.begin(), errors.end());
1492
1493 for (auto entry : errors)
1494 emitError(SMLoc::getFromPointer(entry.first),
1495 "use of undeclared SSA value name");
1496 return ParseFailure;
1497 }
1498
1499 return ParseSuccess;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001500}
1501
Chris Lattner78276e32018-07-07 15:48:26 -07001502/// Parse a SSA operand for an instruction or statement.
1503///
James Molloy61a656c2018-07-22 15:45:24 -07001504/// ssa-use ::= ssa-id
Chris Lattner78276e32018-07-07 15:48:26 -07001505///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001506ParseResult FunctionParser::parseSSAUse(SSAUseInfo &result) {
Chris Lattner6119d382018-07-20 18:41:34 -07001507 result.name = getTokenSpelling();
1508 result.number = 0;
1509 result.loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001510 if (parseToken(Token::percent_identifier, "expected SSA operand"))
1511 return ParseFailure;
Chris Lattner6119d382018-07-20 18:41:34 -07001512
1513 // If we have an affine map ID, it is a result number.
1514 if (getToken().is(Token::hash_identifier)) {
1515 if (auto value = getToken().getHashIdentifierNumber())
1516 result.number = value.getValue();
1517 else
1518 return emitError("invalid SSA value result number");
1519 consumeToken(Token::hash_identifier);
1520 }
1521
Chris Lattner7f9cc272018-07-19 08:35:28 -07001522 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001523}
1524
1525/// Parse a (possibly empty) list of SSA operands.
1526///
1527/// ssa-use-list ::= ssa-use (`,` ssa-use)*
1528/// ssa-use-list-opt ::= ssa-use-list?
1529///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001530ParseResult
Chris Lattner40746442018-07-21 14:32:09 -07001531FunctionParser::parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results) {
Chris Lattner85ee1512018-07-25 11:15:20 -07001532 if (getToken().isNot(Token::percent_identifier))
Chris Lattner40746442018-07-21 14:32:09 -07001533 return ParseSuccess;
1534 return parseCommaSeparatedList([&]() -> ParseResult {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001535 SSAUseInfo result;
1536 if (parseSSAUse(result))
1537 return ParseFailure;
1538 results.push_back(result);
1539 return ParseSuccess;
1540 });
Chris Lattner78276e32018-07-07 15:48:26 -07001541}
1542
1543/// Parse an SSA use with an associated type.
1544///
1545/// ssa-use-and-type ::= ssa-use `:` type
James Molloy61a656c2018-07-22 15:45:24 -07001546template <typename ResultType>
1547ResultType FunctionParser::parseSSADefOrUseAndType(
1548 const std::function<ResultType(SSAUseInfo, Type *)> &action) {
Chris Lattner78276e32018-07-07 15:48:26 -07001549
Chris Lattnerf7702a62018-07-23 17:30:01 -07001550 SSAUseInfo useInfo;
1551 if (parseSSAUse(useInfo) ||
1552 parseToken(Token::colon, "expected ':' and type for SSA operand"))
1553 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001554
Chris Lattner7f9cc272018-07-19 08:35:28 -07001555 auto *type = parseType();
1556 if (!type)
1557 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001558
James Molloy61a656c2018-07-22 15:45:24 -07001559 return action(useInfo, type);
Chris Lattner78276e32018-07-07 15:48:26 -07001560}
1561
Chris Lattner2c402672018-07-23 11:56:17 -07001562/// Parse a (possibly empty) list of SSA operands, followed by a colon, then
1563/// followed by a type list. If hasParens is true, then the operands are
1564/// surrounded by parens.
Chris Lattner78276e32018-07-07 15:48:26 -07001565///
Chris Lattner2c402672018-07-23 11:56:17 -07001566/// ssa-use-and-type-list[parens]
1567/// ::= `(` ssa-use-list `)` ':' type-list-no-parens
1568///
1569/// ssa-use-and-type-list[!parens]
1570/// ::= ssa-use-list ':' type-list-no-parens
Chris Lattner78276e32018-07-07 15:48:26 -07001571///
Chris Lattner40746442018-07-21 14:32:09 -07001572template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001573ParseResult FunctionParser::parseOptionalSSAUseAndTypeList(
Chris Lattner2c402672018-07-23 11:56:17 -07001574 SmallVectorImpl<ValueTy *> &results, bool isParenthesized) {
1575
1576 // If we are in the parenthesized form and no paren exists, then we succeed
1577 // with an empty list.
1578 if (isParenthesized && !consumeIf(Token::l_paren))
Chris Lattner40746442018-07-21 14:32:09 -07001579 return ParseSuccess;
1580
Chris Lattner2c402672018-07-23 11:56:17 -07001581 SmallVector<SSAUseInfo, 4> valueIDs;
1582 if (parseOptionalSSAUseList(valueIDs))
Chris Lattner7f9cc272018-07-19 08:35:28 -07001583 return ParseFailure;
Chris Lattner2c402672018-07-23 11:56:17 -07001584
1585 if (isParenthesized && !consumeIf(Token::r_paren))
1586 return emitError("expected ')' in operand list");
1587
1588 // If there were no operands, then there is no colon or type lists.
1589 if (valueIDs.empty())
1590 return ParseSuccess;
1591
Chris Lattner2c402672018-07-23 11:56:17 -07001592 SmallVector<Type *, 4> types;
Chris Lattnerf7702a62018-07-23 17:30:01 -07001593 if (parseToken(Token::colon, "expected ':' in operand list") ||
1594 parseTypeListNoParens(types))
Chris Lattner2c402672018-07-23 11:56:17 -07001595 return ParseFailure;
1596
1597 if (valueIDs.size() != types.size())
1598 return emitError("expected " + Twine(valueIDs.size()) +
1599 " types to match operand list");
1600
1601 results.reserve(valueIDs.size());
1602 for (unsigned i = 0, e = valueIDs.size(); i != e; ++i) {
1603 if (auto *value = resolveSSAUse(valueIDs[i], types[i]))
1604 results.push_back(cast<ValueTy>(value));
1605 else
1606 return ParseFailure;
1607 }
1608
1609 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001610}
1611
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001612/// Parse the CFG or MLFunc operation.
1613///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001614/// operation ::=
1615/// (ssa-id `=`)? string '(' ssa-use-list? ')' attribute-dict?
1616/// `:` function-type
1617///
1618ParseResult
Chris Lattner7f9cc272018-07-19 08:35:28 -07001619FunctionParser::parseOperation(const CreateOperationFunction &createOpFunc) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001620 auto loc = getToken().getLoc();
1621
1622 StringRef resultID;
1623 if (getToken().is(Token::percent_identifier)) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001624 resultID = getTokenSpelling();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001625 consumeToken(Token::percent_identifier);
Chris Lattnerf7702a62018-07-23 17:30:01 -07001626 if (parseToken(Token::equal, "expected '=' after SSA name"))
1627 return ParseFailure;
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001628 }
1629
Chris Lattner85ee1512018-07-25 11:15:20 -07001630 Operation *op;
1631 if (getToken().is(Token::bare_identifier) || getToken().isKeyword())
1632 op = parseCustomOperation(createOpFunc);
1633 else if (getToken().is(Token::string))
1634 op = parseVerboseOperation(createOpFunc);
1635 else
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001636 return emitError("expected operation name in quotes");
1637
Chris Lattner85ee1512018-07-25 11:15:20 -07001638 // If parsing of the basic operation failed, then this whole thing fails.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001639 if (!op)
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001640 return ParseFailure;
1641
1642 // We just parsed an operation. If it is a recognized one, verify that it
1643 // is structurally as we expect. If not, produce an error with a reasonable
1644 // source location.
Chris Lattner95865062018-08-01 10:18:59 -07001645 if (auto *opInfo = op->getAbstractOperation()) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001646 if (auto error = opInfo->verifyInvariants(op))
Chris Lattner9361fb32018-07-24 08:34:58 -07001647 return emitError(loc, Twine("'") + op->getName().str() + "' op " + error);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001648 }
1649
Chris Lattner7f9cc272018-07-19 08:35:28 -07001650 // If the instruction had a name, register it.
1651 if (!resultID.empty()) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001652 if (op->getNumResults() == 0)
1653 return emitError(loc, "cannot name an operation with no results");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001654
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001655 for (unsigned i = 0, e = op->getNumResults(); i != e; ++i)
Chris Lattner2b97d502018-08-06 14:19:46 -07001656 if (addDefinition({resultID, i, loc}, op->getResult(i)))
1657 return ParseFailure;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001658 }
1659
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001660 return ParseSuccess;
1661}
Chris Lattnere79379a2018-06-22 10:39:19 -07001662
Chris Lattner85ee1512018-07-25 11:15:20 -07001663Operation *FunctionParser::parseVerboseOperation(
1664 const CreateOperationFunction &createOpFunc) {
Chris Lattner1628fa02018-08-23 14:32:25 -07001665
1666 // Get location information for the operation.
1667 auto *srcLocation = getEncodedSourceLocation(getToken().getLoc());
1668
Chris Lattner85ee1512018-07-25 11:15:20 -07001669 auto name = getToken().getStringValue();
1670 if (name.empty())
1671 return (emitError("empty operation name is invalid"), nullptr);
1672
1673 consumeToken(Token::string);
1674
Chris Lattner1628fa02018-08-23 14:32:25 -07001675 OperationState result(builder.getContext(), srcLocation, name);
Chris Lattner992a1272018-08-07 12:02:37 -07001676
Chris Lattner85ee1512018-07-25 11:15:20 -07001677 // Parse the operand list.
1678 SmallVector<SSAUseInfo, 8> operandInfos;
1679
1680 if (parseToken(Token::l_paren, "expected '(' to start operand list") ||
1681 parseOptionalSSAUseList(operandInfos) ||
1682 parseToken(Token::r_paren, "expected ')' to end operand list")) {
1683 return nullptr;
1684 }
1685
Chris Lattner85ee1512018-07-25 11:15:20 -07001686 if (getToken().is(Token::l_brace)) {
Chris Lattner992a1272018-08-07 12:02:37 -07001687 if (parseAttributeDict(result.attributes))
Chris Lattner85ee1512018-07-25 11:15:20 -07001688 return nullptr;
1689 }
1690
1691 if (parseToken(Token::colon, "expected ':' followed by instruction type"))
1692 return nullptr;
1693
1694 auto typeLoc = getToken().getLoc();
1695 auto type = parseType();
1696 if (!type)
1697 return nullptr;
1698 auto fnType = dyn_cast<FunctionType>(type);
1699 if (!fnType)
1700 return (emitError(typeLoc, "expected function type"), nullptr);
1701
Chris Lattner1eb77482018-08-22 19:25:49 -07001702 result.addTypes(fnType->getResults());
Chris Lattner992a1272018-08-07 12:02:37 -07001703
Chris Lattner85ee1512018-07-25 11:15:20 -07001704 // Check that we have the right number of types for the operands.
1705 auto operandTypes = fnType->getInputs();
1706 if (operandTypes.size() != operandInfos.size()) {
1707 auto plural = "s"[operandInfos.size() == 1];
1708 return (emitError(typeLoc, "expected " + llvm::utostr(operandInfos.size()) +
1709 " operand type" + plural + " but had " +
1710 llvm::utostr(operandTypes.size())),
1711 nullptr);
1712 }
1713
1714 // Resolve all of the operands.
Chris Lattner85ee1512018-07-25 11:15:20 -07001715 for (unsigned i = 0, e = operandInfos.size(); i != e; ++i) {
Chris Lattner992a1272018-08-07 12:02:37 -07001716 result.operands.push_back(resolveSSAUse(operandInfos[i], operandTypes[i]));
1717 if (!result.operands.back())
Chris Lattner85ee1512018-07-25 11:15:20 -07001718 return nullptr;
1719 }
1720
Chris Lattner992a1272018-08-07 12:02:37 -07001721 return createOpFunc(result);
Chris Lattner85ee1512018-07-25 11:15:20 -07001722}
1723
1724namespace {
1725class CustomOpAsmParser : public OpAsmParser {
1726public:
1727 CustomOpAsmParser(SMLoc nameLoc, StringRef opName, FunctionParser &parser)
1728 : nameLoc(nameLoc), opName(opName), parser(parser) {}
1729
Chris Lattner85ee1512018-07-25 11:15:20 -07001730 //===--------------------------------------------------------------------===//
1731 // High level parsing methods.
1732 //===--------------------------------------------------------------------===//
1733
Chris Lattner1aa46322018-08-21 17:55:22 -07001734 bool getCurrentLocation(llvm::SMLoc *loc) override {
1735 *loc = parser.getToken().getLoc();
1736 return false;
1737 }
Chris Lattner091a6b52018-08-23 14:58:27 -07001738 bool parseComma() override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001739 return parser.parseToken(Token::comma, "expected ','");
1740 }
1741
Chris Lattner091a6b52018-08-23 14:58:27 -07001742 bool parseColonType(Type *&result) override {
1743 return parser.parseToken(Token::colon, "expected ':'") ||
1744 !(result = parser.parseType());
Chris Lattner85ee1512018-07-25 11:15:20 -07001745 }
1746
Chris Lattner091a6b52018-08-23 14:58:27 -07001747 bool parseColonTypeList(SmallVectorImpl<Type *> &result) override {
1748 if (parser.parseToken(Token::colon, "expected ':'"))
Chris Lattner85ee1512018-07-25 11:15:20 -07001749 return true;
1750
1751 do {
1752 if (auto *type = parser.parseType())
1753 result.push_back(type);
1754 else
1755 return true;
1756
1757 } while (parser.consumeIf(Token::comma));
1758 return false;
1759 }
1760
Chris Lattner85cf26d2018-08-02 16:54:36 -07001761 /// Parse an arbitrary attribute and return it in result. This also adds the
1762 /// attribute to the specified attribute list with the specified name. this
1763 /// captures the location of the attribute in 'loc' if it is non-null.
1764 bool parseAttribute(Attribute *&result, const char *attrName,
Chris Lattner091a6b52018-08-23 14:58:27 -07001765 SmallVectorImpl<NamedAttribute> &attrs) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001766 result = parser.parseAttribute();
Chris Lattner85cf26d2018-08-02 16:54:36 -07001767 if (!result)
1768 return true;
1769
1770 attrs.push_back(
1771 NamedAttribute(parser.builder.getIdentifier(attrName), result));
1772 return false;
1773 }
1774
1775 /// If a named attribute list is present, parse is into result.
Chris Lattner091a6b52018-08-23 14:58:27 -07001776 bool
1777 parseOptionalAttributeDict(SmallVectorImpl<NamedAttribute> &result) override {
Chris Lattner85cf26d2018-08-02 16:54:36 -07001778 if (parser.getToken().isNot(Token::l_brace))
1779 return false;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001780 return parser.parseAttributeDict(result) == ParseFailure;
Chris Lattner85ee1512018-07-25 11:15:20 -07001781 }
1782
Chris Lattner1aa46322018-08-21 17:55:22 -07001783 /// Parse a function name like '@foo' and return the name in a form that can
1784 /// be passed to resolveFunctionName when a function type is available.
1785 virtual bool parseFunctionName(StringRef &result, llvm::SMLoc &loc) {
1786 loc = parser.getToken().getLoc();
1787
1788 if (parser.getToken().isNot(Token::at_identifier))
1789 return emitError(loc, "expected function name");
1790
1791 result = parser.getTokenSpelling();
1792 parser.consumeToken(Token::at_identifier);
1793 return false;
1794 }
1795
Chris Lattner85ee1512018-07-25 11:15:20 -07001796 bool parseOperand(OperandType &result) override {
1797 FunctionParser::SSAUseInfo useInfo;
1798 if (parser.parseSSAUse(useInfo))
1799 return true;
1800
1801 result = {useInfo.loc, useInfo.name, useInfo.number};
1802 return false;
1803 }
1804
1805 bool parseOperandList(SmallVectorImpl<OperandType> &result,
1806 int requiredOperandCount = -1,
Chris Lattner85cf26d2018-08-02 16:54:36 -07001807 Delimiter delimiter = Delimiter::None) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001808 auto startLoc = parser.getToken().getLoc();
1809
Chris Lattner85cf26d2018-08-02 16:54:36 -07001810 // Handle delimiters.
1811 switch (delimiter) {
1812 case Delimiter::None:
Chris Lattner85ee1512018-07-25 11:15:20 -07001813 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001814 case Delimiter::OptionalParen:
Chris Lattner3164ae62018-07-28 09:36:25 -07001815 if (parser.getToken().isNot(Token::l_paren))
1816 return false;
1817 LLVM_FALLTHROUGH;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001818 case Delimiter::Paren:
Chris Lattner85ee1512018-07-25 11:15:20 -07001819 if (parser.parseToken(Token::l_paren, "expected '(' in operand list"))
1820 return true;
1821 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001822 case Delimiter::OptionalSquare:
Chris Lattner3164ae62018-07-28 09:36:25 -07001823 if (parser.getToken().isNot(Token::l_square))
1824 return false;
1825 LLVM_FALLTHROUGH;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001826 case Delimiter::Square:
Chris Lattner85ee1512018-07-25 11:15:20 -07001827 if (parser.parseToken(Token::l_square, "expected '[' in operand list"))
1828 return true;
1829 break;
1830 }
1831
1832 // Check for zero operands.
1833 if (parser.getToken().is(Token::percent_identifier)) {
1834 do {
1835 OperandType operand;
1836 if (parseOperand(operand))
1837 return true;
1838 result.push_back(operand);
1839 } while (parser.consumeIf(Token::comma));
1840 }
1841
Chris Lattner85cf26d2018-08-02 16:54:36 -07001842 // Handle delimiters. If we reach here, the optional delimiters were
Chris Lattner3164ae62018-07-28 09:36:25 -07001843 // present, so we need to parse their closing one.
Chris Lattner85cf26d2018-08-02 16:54:36 -07001844 switch (delimiter) {
1845 case Delimiter::None:
Chris Lattner85ee1512018-07-25 11:15:20 -07001846 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001847 case Delimiter::OptionalParen:
1848 case Delimiter::Paren:
Chris Lattner85ee1512018-07-25 11:15:20 -07001849 if (parser.parseToken(Token::r_paren, "expected ')' in operand list"))
1850 return true;
1851 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001852 case Delimiter::OptionalSquare:
1853 case Delimiter::Square:
Chris Lattner85ee1512018-07-25 11:15:20 -07001854 if (parser.parseToken(Token::r_square, "expected ']' in operand list"))
1855 return true;
1856 break;
1857 }
1858
1859 if (requiredOperandCount != -1 && result.size() != requiredOperandCount)
1860 emitError(startLoc,
1861 "expected " + Twine(requiredOperandCount) + " operands");
1862 return false;
1863 }
1864
Chris Lattner1aa46322018-08-21 17:55:22 -07001865 /// Resolve a parse function name and a type into a function reference.
1866 virtual bool resolveFunctionName(StringRef name, FunctionType *type,
1867 llvm::SMLoc loc, Function *&result) {
1868 result = parser.resolveFunctionReference(name, loc, type);
1869 return result == nullptr;
1870 }
1871
Chris Lattner85ee1512018-07-25 11:15:20 -07001872 //===--------------------------------------------------------------------===//
1873 // Methods for interacting with the parser
1874 //===--------------------------------------------------------------------===//
1875
1876 Builder &getBuilder() const override { return parser.builder; }
1877
1878 llvm::SMLoc getNameLoc() const override { return nameLoc; }
1879
Chris Lattner1aa46322018-08-21 17:55:22 -07001880 bool resolveOperand(const OperandType &operand, Type *type,
Chris Lattner8bdbebf2018-08-08 11:02:58 -07001881 SmallVectorImpl<SSAValue *> &result) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001882 FunctionParser::SSAUseInfo operandInfo = {operand.name, operand.number,
1883 operand.location};
Chris Lattner8bdbebf2018-08-08 11:02:58 -07001884 if (auto *value = parser.resolveSSAUse(operandInfo, type)) {
1885 result.push_back(value);
1886 return false;
1887 }
1888 return true;
Chris Lattner85ee1512018-07-25 11:15:20 -07001889 }
1890
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001891 /// Emit a diagnostic at the specified location and return true.
1892 bool emitError(llvm::SMLoc loc, const Twine &message) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001893 parser.emitError(loc, "custom op '" + Twine(opName) + "' " + message);
1894 emittedError = true;
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001895 return true;
Chris Lattner85ee1512018-07-25 11:15:20 -07001896 }
1897
1898 bool didEmitError() const { return emittedError; }
1899
1900private:
1901 SMLoc nameLoc;
1902 StringRef opName;
1903 FunctionParser &parser;
1904 bool emittedError = false;
1905};
1906} // end anonymous namespace.
1907
1908Operation *FunctionParser::parseCustomOperation(
1909 const CreateOperationFunction &createOpFunc) {
1910 auto opLoc = getToken().getLoc();
1911 auto opName = getTokenSpelling();
1912 CustomOpAsmParser opAsmParser(opLoc, opName, *this);
1913
1914 auto *opDefinition = getOperationSet().lookup(opName);
1915 if (!opDefinition) {
1916 opAsmParser.emitError(opLoc, "is unknown");
1917 return nullptr;
1918 }
1919
1920 consumeToken();
1921
Chris Lattner1aa46322018-08-21 17:55:22 -07001922 // If the custom op parser crashes, produce some indication to help debugging.
1923 std::string opNameStr = opName.str();
1924 llvm::PrettyStackTraceFormat fmt("MLIR Parser: custom op parser '%s'",
1925 opNameStr.c_str());
1926
Chris Lattner1628fa02018-08-23 14:32:25 -07001927 // Get location information for the operation.
1928 auto *srcLocation = getEncodedSourceLocation(opLoc);
1929
Chris Lattner85ee1512018-07-25 11:15:20 -07001930 // Have the op implementation take a crack and parsing this.
Chris Lattner1628fa02018-08-23 14:32:25 -07001931 OperationState opState(builder.getContext(), srcLocation, opName);
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001932 if (opDefinition->parseAssembly(&opAsmParser, &opState))
1933 return nullptr;
Chris Lattner85ee1512018-07-25 11:15:20 -07001934
1935 // If it emitted an error, we failed.
1936 if (opAsmParser.didEmitError())
1937 return nullptr;
1938
1939 // Otherwise, we succeeded. Use the state it parsed as our op information.
Chris Lattner992a1272018-08-07 12:02:37 -07001940 return createOpFunc(opState);
Chris Lattner85ee1512018-07-25 11:15:20 -07001941}
1942
Chris Lattner48af7d12018-07-09 19:05:38 -07001943//===----------------------------------------------------------------------===//
1944// CFG Functions
1945//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001946
Chris Lattner4c95a502018-06-23 16:03:42 -07001947namespace {
Chris Lattner48af7d12018-07-09 19:05:38 -07001948/// This is a specialized parser for CFGFunction's, maintaining the state
1949/// transient to their bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001950class CFGFunctionParser : public FunctionParser {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001951public:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001952 CFGFunctionParser(ParserState &state, CFGFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001953 : FunctionParser(state, Kind::CFGFunc), function(function),
1954 builder(function) {}
Chris Lattner2e595eb2018-07-10 10:08:27 -07001955
1956 ParseResult parseFunctionBody();
1957
1958private:
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001959 CFGFunction *function;
James Molloy0ff71542018-07-23 16:56:32 -07001960 llvm::StringMap<std::pair<BasicBlock *, SMLoc>> blocksByName;
Chris Lattner48af7d12018-07-09 19:05:38 -07001961
1962 /// This builder intentionally shadows the builder in the base class, with a
1963 /// more specific builder type.
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001964 CFGFuncBuilder builder;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001965
Chris Lattner4c95a502018-06-23 16:03:42 -07001966 /// Get the basic block with the specified name, creating it if it doesn't
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001967 /// already exist. The location specified is the point of use, which allows
1968 /// us to diagnose references to blocks that are not defined precisely.
1969 BasicBlock *getBlockNamed(StringRef name, SMLoc loc) {
1970 auto &blockAndLoc = blocksByName[name];
1971 if (!blockAndLoc.first) {
Chris Lattner3a467cc2018-07-01 20:28:00 -07001972 blockAndLoc.first = new BasicBlock();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001973 blockAndLoc.second = loc;
Chris Lattner4c95a502018-06-23 16:03:42 -07001974 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001975 return blockAndLoc.first;
Chris Lattner4c95a502018-06-23 16:03:42 -07001976 }
Chris Lattner48af7d12018-07-09 19:05:38 -07001977
James Molloy61a656c2018-07-22 15:45:24 -07001978 ParseResult
1979 parseOptionalBasicBlockArgList(SmallVectorImpl<BBArgument *> &results,
1980 BasicBlock *owner);
James Molloy4f788372018-07-24 15:01:27 -07001981 ParseResult parseBranchBlockAndUseList(BasicBlock *&block,
1982 SmallVectorImpl<CFGValue *> &values);
James Molloy61a656c2018-07-22 15:45:24 -07001983
Chris Lattner48af7d12018-07-09 19:05:38 -07001984 ParseResult parseBasicBlock();
Chris Lattner48af7d12018-07-09 19:05:38 -07001985 TerminatorInst *parseTerminator();
Chris Lattner4c95a502018-06-23 16:03:42 -07001986};
1987} // end anonymous namespace
1988
James Molloy61a656c2018-07-22 15:45:24 -07001989/// Parse a (possibly empty) list of SSA operands with types as basic block
Chris Lattner2c402672018-07-23 11:56:17 -07001990/// arguments.
James Molloy61a656c2018-07-22 15:45:24 -07001991///
1992/// ssa-id-and-type-list ::= ssa-id-and-type (`,` ssa-id-and-type)*
1993///
1994ParseResult CFGFunctionParser::parseOptionalBasicBlockArgList(
1995 SmallVectorImpl<BBArgument *> &results, BasicBlock *owner) {
1996 if (getToken().is(Token::r_brace))
1997 return ParseSuccess;
1998
1999 return parseCommaSeparatedList([&]() -> ParseResult {
2000 auto type = parseSSADefOrUseAndType<Type *>(
2001 [&](SSAUseInfo useInfo, Type *type) -> Type * {
2002 BBArgument *arg = owner->addArgument(type);
Chris Lattner2b97d502018-08-06 14:19:46 -07002003 if (addDefinition(useInfo, arg))
James Molloy61a656c2018-07-22 15:45:24 -07002004 return nullptr;
2005 return type;
2006 });
2007 return type ? ParseSuccess : ParseFailure;
2008 });
2009}
2010
Chris Lattner48af7d12018-07-09 19:05:38 -07002011ParseResult CFGFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07002012 auto braceLoc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07002013 if (parseToken(Token::l_brace, "expected '{' in CFG function"))
2014 return ParseFailure;
Chris Lattner48af7d12018-07-09 19:05:38 -07002015
2016 // Make sure we have at least one block.
2017 if (getToken().is(Token::r_brace))
2018 return emitError("CFG functions must have at least one basic block");
Chris Lattner4c95a502018-06-23 16:03:42 -07002019
2020 // Parse the list of blocks.
2021 while (!consumeIf(Token::r_brace))
Chris Lattner48af7d12018-07-09 19:05:38 -07002022 if (parseBasicBlock())
Chris Lattner4c95a502018-06-23 16:03:42 -07002023 return ParseFailure;
2024
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002025 // Verify that all referenced blocks were defined. Iteration over a
2026 // StringMap isn't determinstic, but this is good enough for our purposes.
Chris Lattner48af7d12018-07-09 19:05:38 -07002027 for (auto &elt : blocksByName) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002028 auto *bb = elt.second.first;
Chris Lattner3a467cc2018-07-01 20:28:00 -07002029 if (!bb->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002030 return emitError(elt.second.second,
James Molloy0ff71542018-07-23 16:56:32 -07002031 "reference to an undefined basic block '" + elt.first() +
2032 "'");
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002033 }
2034
Chris Lattner40746442018-07-21 14:32:09 -07002035 return finalizeFunction(function, braceLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07002036}
2037
2038/// Basic block declaration.
2039///
2040/// basic-block ::= bb-label instruction* terminator-stmt
2041/// bb-label ::= bb-id bb-arg-list? `:`
2042/// bb-id ::= bare-id
2043/// bb-arg-list ::= `(` ssa-id-and-type-list? `)`
2044///
Chris Lattner48af7d12018-07-09 19:05:38 -07002045ParseResult CFGFunctionParser::parseBasicBlock() {
2046 SMLoc nameLoc = getToken().getLoc();
2047 auto name = getTokenSpelling();
Chris Lattnerf7702a62018-07-23 17:30:01 -07002048 if (parseToken(Token::bare_identifier, "expected basic block name"))
2049 return ParseFailure;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002050
Chris Lattner48af7d12018-07-09 19:05:38 -07002051 auto *block = getBlockNamed(name, nameLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07002052
2053 // If this block has already been parsed, then this is a redefinition with the
2054 // same block name.
Chris Lattner3a467cc2018-07-01 20:28:00 -07002055 if (block->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002056 return emitError(nameLoc, "redefinition of block '" + name.str() + "'");
2057
Chris Lattner78276e32018-07-07 15:48:26 -07002058 // If an argument list is present, parse it.
2059 if (consumeIf(Token::l_paren)) {
James Molloy61a656c2018-07-22 15:45:24 -07002060 SmallVector<BBArgument *, 8> bbArgs;
Chris Lattnerf7702a62018-07-23 17:30:01 -07002061 if (parseOptionalBasicBlockArgList(bbArgs, block) ||
2062 parseToken(Token::r_paren, "expected ')' to end argument list"))
Chris Lattner78276e32018-07-07 15:48:26 -07002063 return ParseFailure;
Chris Lattner78276e32018-07-07 15:48:26 -07002064 }
Chris Lattner4c95a502018-06-23 16:03:42 -07002065
James Molloy61a656c2018-07-22 15:45:24 -07002066 // Add the block to the function.
2067 function->push_back(block);
2068
Chris Lattnerf7702a62018-07-23 17:30:01 -07002069 if (parseToken(Token::colon, "expected ':' after basic block name"))
2070 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07002071
Chris Lattner158e0a3e2018-07-08 20:51:38 -07002072 // Set the insertion point to the block we want to insert new operations into.
Chris Lattner48af7d12018-07-09 19:05:38 -07002073 builder.setInsertionPoint(block);
Chris Lattner158e0a3e2018-07-08 20:51:38 -07002074
Chris Lattner992a1272018-08-07 12:02:37 -07002075 auto createOpFunc = [&](const OperationState &result) -> Operation * {
2076 return builder.createOperation(result);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002077 };
2078
Chris Lattnered65a732018-06-28 20:45:33 -07002079 // Parse the list of operations that make up the body of the block.
James Molloy4f788372018-07-24 15:01:27 -07002080 while (getToken().isNot(Token::kw_return, Token::kw_br, Token::kw_cond_br)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002081 if (parseOperation(createOpFunc))
Chris Lattnered65a732018-06-28 20:45:33 -07002082 return ParseFailure;
2083 }
Chris Lattner4c95a502018-06-23 16:03:42 -07002084
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002085 if (!parseTerminator())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002086 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07002087
2088 return ParseSuccess;
2089}
2090
James Molloy4f788372018-07-24 15:01:27 -07002091ParseResult CFGFunctionParser::parseBranchBlockAndUseList(
2092 BasicBlock *&block, SmallVectorImpl<CFGValue *> &values) {
2093 block = getBlockNamed(getTokenSpelling(), getToken().getLoc());
2094 if (parseToken(Token::bare_identifier, "expected basic block name"))
2095 return ParseFailure;
2096
2097 if (!consumeIf(Token::l_paren))
2098 return ParseSuccess;
2099 if (parseOptionalSSAUseAndTypeList(values, /*isParenthesized*/ false) ||
2100 parseToken(Token::r_paren, "expected ')' to close argument list"))
2101 return ParseFailure;
2102 return ParseSuccess;
2103}
2104
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002105/// Parse the terminator instruction for a basic block.
2106///
2107/// terminator-stmt ::= `br` bb-id branch-use-list?
Chris Lattner1604e472018-07-23 08:42:19 -07002108/// branch-use-list ::= `(` ssa-use-list `)` ':' type-list-no-parens
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002109/// terminator-stmt ::=
2110/// `cond_br` ssa-use `,` bb-id branch-use-list? `,` bb-id branch-use-list?
2111/// terminator-stmt ::= `return` ssa-use-and-type-list?
2112///
Chris Lattner48af7d12018-07-09 19:05:38 -07002113TerminatorInst *CFGFunctionParser::parseTerminator() {
Chris Lattner1628fa02018-08-23 14:32:25 -07002114 auto loc = getToken().getLoc();
2115
Chris Lattner48af7d12018-07-09 19:05:38 -07002116 switch (getToken().getKind()) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002117 default:
Chris Lattner3a467cc2018-07-01 20:28:00 -07002118 return (emitError("expected terminator at end of basic block"), nullptr);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002119
Chris Lattner40746442018-07-21 14:32:09 -07002120 case Token::kw_return: {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002121 consumeToken(Token::kw_return);
Chris Lattner40746442018-07-21 14:32:09 -07002122
Chris Lattner2c402672018-07-23 11:56:17 -07002123 // Parse any operands.
2124 SmallVector<CFGValue *, 8> operands;
2125 if (parseOptionalSSAUseAndTypeList(operands, /*isParenthesized*/ false))
2126 return nullptr;
Chris Lattner091a6b52018-08-23 14:58:27 -07002127 return builder.createReturn(getEncodedSourceLocation(loc), operands);
Chris Lattner40746442018-07-21 14:32:09 -07002128 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002129
2130 case Token::kw_br: {
2131 consumeToken(Token::kw_br);
James Molloy4f788372018-07-24 15:01:27 -07002132 BasicBlock *destBB;
2133 SmallVector<CFGValue *, 4> values;
2134 if (parseBranchBlockAndUseList(destBB, values))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002135 return nullptr;
Chris Lattner091a6b52018-08-23 14:58:27 -07002136 auto branch = builder.createBranch(getEncodedSourceLocation(loc), destBB);
James Molloy4f788372018-07-24 15:01:27 -07002137 branch->addOperands(values);
Chris Lattner1604e472018-07-23 08:42:19 -07002138 return branch;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002139 }
James Molloy4f788372018-07-24 15:01:27 -07002140
2141 case Token::kw_cond_br: {
2142 consumeToken(Token::kw_cond_br);
2143 SSAUseInfo ssaUse;
2144 if (parseSSAUse(ssaUse))
2145 return nullptr;
2146 auto *cond = resolveSSAUse(ssaUse, builder.getIntegerType(1));
2147 if (!cond)
2148 return (emitError("expected type was boolean (i1)"), nullptr);
2149 if (parseToken(Token::comma, "expected ',' in conditional branch"))
2150 return nullptr;
2151
2152 BasicBlock *trueBlock;
2153 SmallVector<CFGValue *, 4> trueOperands;
2154 if (parseBranchBlockAndUseList(trueBlock, trueOperands))
2155 return nullptr;
2156
2157 if (parseToken(Token::comma, "expected ',' in conditional branch"))
2158 return nullptr;
2159
2160 BasicBlock *falseBlock;
2161 SmallVector<CFGValue *, 4> falseOperands;
2162 if (parseBranchBlockAndUseList(falseBlock, falseOperands))
2163 return nullptr;
2164
Chris Lattner091a6b52018-08-23 14:58:27 -07002165 auto branch =
2166 builder.createCondBranch(getEncodedSourceLocation(loc),
2167 cast<CFGValue>(cond), trueBlock, falseBlock);
James Molloy4f788372018-07-24 15:01:27 -07002168 branch->addTrueOperands(trueOperands);
2169 branch->addFalseOperands(falseOperands);
2170 return branch;
2171 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002172 }
2173}
2174
Chris Lattner48af7d12018-07-09 19:05:38 -07002175//===----------------------------------------------------------------------===//
2176// ML Functions
2177//===----------------------------------------------------------------------===//
2178
2179namespace {
2180/// Refined parser for MLFunction bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07002181class MLFunctionParser : public FunctionParser {
Chris Lattner48af7d12018-07-09 19:05:38 -07002182public:
Chris Lattner48af7d12018-07-09 19:05:38 -07002183 MLFunctionParser(ParserState &state, MLFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07002184 : FunctionParser(state, Kind::MLFunc), function(function),
Chris Lattnere787b322018-08-08 11:14:57 -07002185 builder(function, function->end()) {}
Chris Lattner48af7d12018-07-09 19:05:38 -07002186
2187 ParseResult parseFunctionBody();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002188
2189private:
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002190 MLFunction *function;
2191
2192 /// This builder intentionally shadows the builder in the base class, with a
2193 /// more specific builder type.
2194 MLFuncBuilder builder;
2195
2196 ParseResult parseForStmt();
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002197 ParseResult parseIntConstant(int64_t &val);
2198 ParseResult parseDimAndSymbolList(SmallVectorImpl<MLValue *> &operands,
2199 const AffineMap *map);
2200 ParseResult parseBound(SmallVectorImpl<MLValue *> &operands, AffineMap *&map,
2201 bool isLower);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002202 ParseResult parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002203 ParseResult parseElseClause(IfClause *elseClause);
Uday Bondhugulabc535622018-08-07 14:24:38 -07002204 IntegerSet *parseCondition();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002205 ParseResult parseStatements(StmtBlock *block);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002206 ParseResult parseStmtBlock(StmtBlock *block);
Chris Lattner48af7d12018-07-09 19:05:38 -07002207};
2208} // end anonymous namespace
2209
Chris Lattner48af7d12018-07-09 19:05:38 -07002210ParseResult MLFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07002211 auto braceLoc = getToken().getLoc();
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002212
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002213 // Parse statements in this function.
2214 if (parseStmtBlock(function))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002215 return ParseFailure;
Chris Lattner40746442018-07-21 14:32:09 -07002216
Chris Lattner40746442018-07-21 14:32:09 -07002217 return finalizeFunction(function, braceLoc);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002218}
2219
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002220/// For statement.
2221///
Chris Lattner48af7d12018-07-09 19:05:38 -07002222/// ml-for-stmt ::= `for` ssa-id `=` lower-bound `to` upper-bound
2223/// (`step` integer-literal)? `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002224///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002225ParseResult MLFunctionParser::parseForStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002226 consumeToken(Token::kw_for);
2227
Uday Bondhugula67701712018-08-21 16:01:23 -07002228 // Parse induction variable.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002229 if (getToken().isNot(Token::percent_identifier))
2230 return emitError("expected SSA identifier for the loop variable");
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002231
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002232 auto loc = getToken().getLoc();
Tatiana Shpeismand880b352018-07-31 23:14:16 -07002233 StringRef inductionVariableName = getTokenSpelling();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002234 consumeToken(Token::percent_identifier);
2235
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002236 if (parseToken(Token::equal, "expected '='"))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002237 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002238
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002239 // Parse lower bound.
2240 SmallVector<MLValue *, 4> lbOperands;
2241 AffineMap *lbMap = nullptr;
2242 if (parseBound(lbOperands, lbMap, /*isLower*/ true))
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002243 return ParseFailure;
2244
Chris Lattnerf7702a62018-07-23 17:30:01 -07002245 if (parseToken(Token::kw_to, "expected 'to' between bounds"))
2246 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002247
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002248 // Parse upper bound.
2249 SmallVector<MLValue *, 4> ubOperands;
2250 AffineMap *ubMap = nullptr;
2251 if (parseBound(ubOperands, ubMap, /*isLower*/ false))
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002252 return ParseFailure;
2253
Uday Bondhugula67701712018-08-21 16:01:23 -07002254 // Parse step.
2255 int64_t step = 1;
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002256 if (consumeIf(Token::kw_step) && parseIntConstant(step))
2257 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002258
2259 // Create for statement.
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002260 ForStmt *forStmt =
2261 builder.createFor(getEncodedSourceLocation(loc), lbOperands, lbMap,
2262 ubOperands, ubMap, step);
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002263
2264 // Create SSA value definition for the induction variable.
Chris Lattner2b97d502018-08-06 14:19:46 -07002265 if (addDefinition({inductionVariableName, 0, loc}, forStmt))
2266 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002267
2268 // If parsing of the for statement body fails,
2269 // MLIR contains for statement with those nested statements that have been
2270 // successfully parsed.
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002271 if (parseStmtBlock(forStmt))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002272 return ParseFailure;
2273
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002274 // Reset insertion point to the current block.
Chris Lattnere787b322018-08-08 11:14:57 -07002275 builder.setInsertionPointToEnd(forStmt->getBlock());
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002276
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002277 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002278}
2279
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002280/// Parse integer constant as affine constant expression.
2281ParseResult MLFunctionParser::parseIntConstant(int64_t &val) {
2282 bool negate = consumeIf(Token::minus);
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002283
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002284 if (getToken().isNot(Token::integer))
2285 return emitError("expected integer");
2286
2287 auto uval = getToken().getUInt64IntegerValue();
2288
2289 if (!uval.hasValue() || (int64_t)uval.getValue() < 0) {
2290 return emitError("bound or step is too large for affineint");
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002291 }
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002292
2293 val = (int64_t)uval.getValue();
2294 if (negate)
2295 val = -val;
2296 consumeToken();
2297
2298 return ParseSuccess;
2299}
2300
2301/// Dimensions and symbol use list.
2302///
2303/// dim-use-list ::= `(` ssa-use-list? `)`
2304/// symbol-use-list ::= `[` ssa-use-list? `]`
2305/// dim-and-symbol-use-list ::= dim-use-list symbol-use-list?
2306///
2307ParseResult
2308MLFunctionParser::parseDimAndSymbolList(SmallVectorImpl<MLValue *> &operands,
2309 const AffineMap *map) {
2310 if (parseToken(Token::l_paren, "expected '('"))
2311 return ParseFailure;
2312
2313 SmallVector<SSAUseInfo, 4> opInfo;
2314 parseOptionalSSAUseList(opInfo);
2315
2316 if (parseToken(Token::r_paren, "expected ')'"))
2317 return ParseFailure;
2318
2319 if (map->getNumDims() != opInfo.size())
2320 return emitError("dim operand count and affine map dim count must match");
2321
2322 if (consumeIf(Token::l_square)) {
2323 parseOptionalSSAUseList(opInfo);
2324 if (parseToken(Token::r_square, "expected ']'"))
2325 return ParseFailure;
2326 }
2327
2328 if (map->getNumOperands() != opInfo.size())
2329 return emitError(
2330 "symbol operand count and affine map symbol count must match");
2331
2332 // Resolve SSA uses.
2333 Type *affineIntType = builder.getAffineIntType();
2334 unsigned numDims = map->getNumDims();
2335 for (unsigned i = 0, e = opInfo.size(); i != e; ++i) {
2336 SSAValue *sval = resolveSSAUse(opInfo[i], affineIntType);
2337 if (!sval)
2338 return ParseFailure;
2339
2340 auto *v = cast<MLValue>(sval);
2341 if (i < numDims && !v->isValidDim())
2342 return emitError(opInfo[i].loc, "value '" + opInfo[i].name.str() +
2343 "' cannot be used as dimension id");
2344 if (i >= numDims && !v->isValidSymbol())
2345 return emitError(opInfo[i].loc, "value '" + opInfo[i].name.str() +
2346 "' cannot be used as symbol");
2347 operands.push_back(v);
2348 }
2349
2350 return ParseSuccess;
2351}
2352
2353// Loop bound.
2354///
2355/// lower-bound ::= `max`? affine-map dim-and-symbol-use-list | shorthand-bound
2356/// upper-bound ::= `min`? affine-map dim-and-symbol-use-list | shorthand-bound
2357/// shorthand-bound ::= ssa-id | `-`? integer-literal
2358///
2359ParseResult MLFunctionParser::parseBound(SmallVectorImpl<MLValue *> &operands,
2360 AffineMap *&map, bool isLower) {
2361 // 'min' / 'max' prefixes are syntactic sugar. Ignore them.
2362 if (isLower)
2363 consumeIf(Token::kw_max);
2364 else
2365 consumeIf(Token::kw_min);
2366
2367 // Parse full form - affine map followed by dim and symbol list.
2368 if (getToken().isAny(Token::hash_identifier, Token::l_paren)) {
2369 map = parseAffineMapReference();
2370 if (!map)
2371 return ParseFailure;
2372
2373 if (parseDimAndSymbolList(operands, map))
2374 return ParseFailure;
2375 return ParseSuccess;
2376 }
2377
2378 // Parse shorthand form.
2379 if (getToken().isAny(Token::minus, Token::integer)) {
2380 int64_t val;
2381 if (!parseIntConstant(val)) {
2382 map = builder.getConstantMap(val);
2383 return ParseSuccess;
2384 }
2385 return ParseFailure;
2386 }
2387
2388 // Parse ssa-id as identity map.
2389 SSAUseInfo opInfo;
2390 if (parseSSAUse(opInfo))
2391 return ParseFailure;
2392
2393 // TODO: improve error message when SSA value is not an affine integer.
2394 // Currently it is 'use of value ... expects different type than prior uses'
2395 if (auto *value = resolveSSAUse(opInfo, builder.getAffineIntType()))
2396 operands.push_back(cast<MLValue>(value));
2397 else
2398 return ParseFailure;
2399
2400 // Create an identity map using dim id for an induction variable and
2401 // symbol otherwise. This representation is optimized for storage.
2402 // Analysis passes may expand it into a multi-dimensional map if desired.
2403 if (isa<ForStmt>(operands[0]))
2404 map = builder.getDimIdentityMap();
2405 else
2406 map = builder.getSymbolIdentityMap();
2407
2408 return ParseSuccess;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002409}
2410
Uday Bondhugulabc535622018-08-07 14:24:38 -07002411/// Parse condition.
2412IntegerSet *MLFunctionParser::parseCondition() {
2413 return parseIntegerSetReference();
2414
2415 // TODO: Parse operands to the integer set.
2416}
2417
2418/// Parse an affine constraint.
2419/// affine-constraint ::= affine-expr `>=` `0`
2420/// | affine-expr `==` `0`
2421///
2422/// isEq is set to true if the parsed constraint is an equality, false if it is
2423/// an inequality (greater than or equal).
2424///
2425AffineExpr *AffineParser::parseAffineConstraint(bool *isEq) {
2426 AffineExpr *expr = parseAffineExpr();
2427 if (!expr)
2428 return nullptr;
2429
2430 if (consumeIf(Token::greater) && consumeIf(Token::equal) &&
2431 getToken().is(Token::integer)) {
2432 auto dim = getToken().getUnsignedIntegerValue();
2433 if (dim.hasValue() && dim.getValue() == 0) {
2434 consumeToken(Token::integer);
2435 *isEq = false;
2436 return expr;
2437 }
2438 return (emitError("expected '0' after '>='"), nullptr);
2439 }
2440
2441 if (consumeIf(Token::equal) && consumeIf(Token::equal) &&
2442 getToken().is(Token::integer)) {
2443 auto dim = getToken().getUnsignedIntegerValue();
2444 if (dim.hasValue() && dim.getValue() == 0) {
2445 consumeToken(Token::integer);
2446 *isEq = true;
2447 return expr;
2448 }
2449 return (emitError("expected '0' after '=='"), nullptr);
2450 }
2451
2452 return (emitError("expected '== 0' or '>= 0' at end of affine constraint"),
2453 nullptr);
2454}
2455
2456/// Parse an integer set definition.
2457/// integer-set-inline
2458/// ::= dim-and-symbol-id-lists `:` affine-constraint-conjunction
2459/// affine-constraint-conjunction ::= /*empty*/
2460/// | affine-constraint (`,` affine-constraint)*
2461///
2462IntegerSet *AffineParser::parseIntegerSetInline() {
2463 unsigned numDims = 0, numSymbols = 0;
2464
2465 // List of dimensional identifiers.
2466 if (parseDimIdList(numDims))
2467 return nullptr;
2468
2469 // Symbols are optional.
2470 if (getToken().is(Token::l_square)) {
2471 if (parseSymbolIdList(numSymbols))
2472 return nullptr;
2473 }
2474
2475 if (parseToken(Token::colon, "expected ':' or '['") ||
2476 parseToken(Token::l_paren,
2477 "expected '(' at start of integer set constraint list"))
2478 return nullptr;
2479
2480 SmallVector<AffineExpr *, 4> constraints;
2481 SmallVector<bool, 4> isEqs;
2482 auto parseElt = [&]() -> ParseResult {
2483 bool isEq;
2484 auto *elt = parseAffineConstraint(&isEq);
2485 ParseResult res = elt ? ParseSuccess : ParseFailure;
2486 if (elt) {
2487 constraints.push_back(elt);
2488 isEqs.push_back(isEq);
2489 }
2490 return res;
2491 };
2492
2493 // Parse a list of affine constraints (comma-separated) .
2494 // Grammar: affine-constraint-conjunct ::= `(` affine-constraint (`,`
2495 // affine-constraint)* `)
2496 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt, true))
2497 return nullptr;
2498
2499 // Parsed a valid integer set.
2500 return builder.getIntegerSet(numDims, numSymbols, constraints, isEqs);
2501}
2502
2503IntegerSet *Parser::parseIntegerSetInline() {
2504 return AffineParser(state).parseIntegerSetInline();
2505}
2506
2507/// Parse a reference to an integer set.
2508/// integer-set ::= integer-set-id | integer-set-inline
2509/// integer-set-id ::= `@@` suffix-id
2510///
2511IntegerSet *Parser::parseIntegerSetReference() {
2512 if (getToken().is(Token::double_at_identifier)) {
2513 // Parse integer set identifier and verify that it exists.
2514 StringRef integerSetId = getTokenSpelling().drop_front(2);
2515 if (getState().integerSetDefinitions.count(integerSetId) == 0)
2516 return (emitError("undefined integer set id '" + integerSetId + "'"),
2517 nullptr);
2518 consumeToken(Token::double_at_identifier);
2519 return getState().integerSetDefinitions[integerSetId];
2520 }
2521 // Try to parse an inline integer set definition.
2522 return parseIntegerSetInline();
2523}
2524
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002525/// If statement.
2526///
Chris Lattner48af7d12018-07-09 19:05:38 -07002527/// ml-if-head ::= `if` ml-if-cond `{` ml-stmt* `}`
2528/// | ml-if-head `else` `if` ml-if-cond `{` ml-stmt* `}`
2529/// ml-if-stmt ::= ml-if-head
2530/// | ml-if-head `else` `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002531///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002532ParseResult MLFunctionParser::parseIfStmt() {
Chris Lattner1628fa02018-08-23 14:32:25 -07002533 auto loc = getToken().getLoc();
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002534 consumeToken(Token::kw_if);
Uday Bondhugulabc535622018-08-07 14:24:38 -07002535
2536 if (parseToken(Token::l_paren, "expected '('"))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002537 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002538
Uday Bondhugulabc535622018-08-07 14:24:38 -07002539 IntegerSet *condition = parseCondition();
2540 if (!condition)
Chris Lattnerf7702a62018-07-23 17:30:01 -07002541 return ParseFailure;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002542
Uday Bondhugulabc535622018-08-07 14:24:38 -07002543 if (parseToken(Token::r_paren, "expected ')'"))
2544 return ParseFailure;
2545
Chris Lattner1628fa02018-08-23 14:32:25 -07002546 IfStmt *ifStmt = builder.createIf(getEncodedSourceLocation(loc), condition);
Chris Lattnere787b322018-08-08 11:14:57 -07002547 IfClause *thenClause = ifStmt->getThen();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002548
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002549 // When parsing of an if statement body fails, the IR contains
2550 // the if statement with the portion of the body that has been
2551 // successfully parsed.
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002552 if (parseStmtBlock(thenClause))
2553 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002554
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002555 if (consumeIf(Token::kw_else)) {
Chris Lattnere787b322018-08-08 11:14:57 -07002556 auto *elseClause = ifStmt->createElse();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002557 if (parseElseClause(elseClause))
2558 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002559 }
2560
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002561 // Reset insertion point to the current block.
Chris Lattnere787b322018-08-08 11:14:57 -07002562 builder.setInsertionPointToEnd(ifStmt->getBlock());
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002563
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002564 return ParseSuccess;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002565}
2566
2567ParseResult MLFunctionParser::parseElseClause(IfClause *elseClause) {
2568 if (getToken().is(Token::kw_if)) {
Chris Lattnere787b322018-08-08 11:14:57 -07002569 builder.setInsertionPointToEnd(elseClause);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002570 return parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002571 }
2572
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002573 return parseStmtBlock(elseClause);
2574}
2575
2576///
2577/// Parse a list of statements ending with `return` or `}`
2578///
2579ParseResult MLFunctionParser::parseStatements(StmtBlock *block) {
Chris Lattner992a1272018-08-07 12:02:37 -07002580 auto createOpFunc = [&](const OperationState &state) -> Operation * {
2581 return builder.createOperation(state);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002582 };
2583
Chris Lattnere787b322018-08-08 11:14:57 -07002584 builder.setInsertionPointToEnd(block);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002585
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002586 // Parse statements till we see '}' or 'return'.
2587 // Return statement is parsed separately to emit a more intuitive error
2588 // when '}' is missing after the return statement.
2589 while (getToken().isNot(Token::r_brace, Token::kw_return)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002590 switch (getToken().getKind()) {
2591 default:
2592 if (parseOperation(createOpFunc))
2593 return ParseFailure;
2594 break;
2595 case Token::kw_for:
2596 if (parseForStmt())
2597 return ParseFailure;
2598 break;
2599 case Token::kw_if:
2600 if (parseIfStmt())
2601 return ParseFailure;
2602 break;
2603 } // end switch
2604 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002605
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002606 // Parse the return statement.
2607 if (getToken().is(Token::kw_return))
2608 if (parseOperation(createOpFunc))
2609 return ParseFailure;
2610
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002611 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002612}
2613
2614///
2615/// Parse `{` ml-stmt* `}`
2616///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002617ParseResult MLFunctionParser::parseStmtBlock(StmtBlock *block) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002618 if (parseToken(Token::l_brace, "expected '{' before statement list") ||
2619 parseStatements(block) ||
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002620 parseToken(Token::r_brace, "expected '}' after statement list"))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002621 return ParseFailure;
2622
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002623 return ParseSuccess;
2624}
2625
Chris Lattner4c95a502018-06-23 16:03:42 -07002626//===----------------------------------------------------------------------===//
2627// Top-level entity parsing.
2628//===----------------------------------------------------------------------===//
2629
Chris Lattner2e595eb2018-07-10 10:08:27 -07002630namespace {
2631/// This parser handles entities that are only valid at the top level of the
2632/// file.
2633class ModuleParser : public Parser {
2634public:
2635 explicit ModuleParser(ParserState &state) : Parser(state) {}
2636
2637 ParseResult parseModule();
2638
2639private:
Chris Lattner4613d9e2018-08-19 21:17:22 -07002640 ParseResult finalizeModule();
2641
Chris Lattner2e595eb2018-07-10 10:08:27 -07002642 ParseResult parseAffineMapDef();
Uday Bondhugulabc535622018-08-07 14:24:38 -07002643 ParseResult parseIntegerSetDef();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002644
2645 // Functions.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002646 ParseResult parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2647 SmallVectorImpl<StringRef> &argNames);
2648 ParseResult parseFunctionSignature(StringRef &name, FunctionType *&type,
2649 SmallVectorImpl<StringRef> *argNames);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002650 ParseResult parseExtFunc();
2651 ParseResult parseCFGFunc();
2652 ParseResult parseMLFunc();
2653};
2654} // end anonymous namespace
2655
2656/// Affine map declaration.
2657///
2658/// affine-map-def ::= affine-map-id `=` affine-map-inline
2659///
2660ParseResult ModuleParser::parseAffineMapDef() {
2661 assert(getToken().is(Token::hash_identifier));
2662
2663 StringRef affineMapId = getTokenSpelling().drop_front();
2664
2665 // Check for redefinitions.
Nicolas Vasilache97298152018-08-27 10:10:42 -07002666 auto *&entry = getState().affineMapDefinitions[affineMapId];
2667 if (entry)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002668 return emitError("redefinition of affine map id '" + affineMapId + "'");
2669
2670 consumeToken(Token::hash_identifier);
2671
2672 // Parse the '='
Chris Lattnerf7702a62018-07-23 17:30:01 -07002673 if (parseToken(Token::equal,
2674 "expected '=' in affine map outlined definition"))
2675 return ParseFailure;
Chris Lattner2e595eb2018-07-10 10:08:27 -07002676
Nicolas Vasilache97298152018-08-27 10:10:42 -07002677 entry = parseAffineMapInline();
2678 if (!entry)
Uday Bondhugulabc535622018-08-07 14:24:38 -07002679 return ParseFailure;
2680
2681 return ParseSuccess;
2682}
2683
2684/// Integer set declaration.
2685///
2686/// integer-set-decl ::= integer-set-id `=` integer-set-inline
2687///
2688ParseResult ModuleParser::parseIntegerSetDef() {
2689 assert(getToken().is(Token::double_at_identifier));
2690
2691 StringRef integerSetId = getTokenSpelling().drop_front(2);
2692
2693 // Check for redefinitions (a default entry is created if one doesn't exist)
Nicolas Vasilache97298152018-08-27 10:10:42 -07002694 auto *&entry = getState().integerSetDefinitions[integerSetId];
2695 if (entry)
Uday Bondhugulabc535622018-08-07 14:24:38 -07002696 return emitError("redefinition of integer set id '" + integerSetId + "'");
2697
2698 consumeToken(Token::double_at_identifier);
2699
2700 // Parse the '='
2701 if (parseToken(Token::equal,
2702 "expected '=' in outlined integer set definition"))
2703 return ParseFailure;
2704
Nicolas Vasilache97298152018-08-27 10:10:42 -07002705 entry = parseIntegerSetInline();
2706 if (!entry)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002707 return ParseFailure;
2708
Chris Lattner2e595eb2018-07-10 10:08:27 -07002709 return ParseSuccess;
2710}
2711
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002712/// Parse a (possibly empty) list of MLFunction arguments with types.
2713///
2714/// ml-argument ::= ssa-id `:` type
2715/// ml-argument-list ::= ml-argument (`,` ml-argument)* | /*empty*/
2716///
2717ParseResult
2718ModuleParser::parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2719 SmallVectorImpl<StringRef> &argNames) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002720 consumeToken(Token::l_paren);
2721
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002722 auto parseElt = [&]() -> ParseResult {
2723 // Parse argument name
2724 if (getToken().isNot(Token::percent_identifier))
2725 return emitError("expected SSA identifier");
2726
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002727 StringRef name = getTokenSpelling();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002728 consumeToken(Token::percent_identifier);
2729 argNames.push_back(name);
2730
Chris Lattnerf7702a62018-07-23 17:30:01 -07002731 if (parseToken(Token::colon, "expected ':'"))
2732 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002733
2734 // Parse argument type
2735 auto elt = parseType();
2736 if (!elt)
2737 return ParseFailure;
2738 argTypes.push_back(elt);
2739
2740 return ParseSuccess;
2741 };
2742
Chris Lattner40746442018-07-21 14:32:09 -07002743 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002744}
2745
Chris Lattner2e595eb2018-07-10 10:08:27 -07002746/// Parse a function signature, starting with a name and including the parameter
2747/// list.
2748///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002749/// argument-list ::= type (`,` type)* | /*empty*/ | ml-argument-list
Chris Lattner2e595eb2018-07-10 10:08:27 -07002750/// function-signature ::= function-id `(` argument-list `)` (`->` type-list)?
2751///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002752ParseResult
2753ModuleParser::parseFunctionSignature(StringRef &name, FunctionType *&type,
2754 SmallVectorImpl<StringRef> *argNames) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002755 if (getToken().isNot(Token::at_identifier))
2756 return emitError("expected a function identifier like '@foo'");
2757
2758 name = getTokenSpelling().drop_front();
2759 consumeToken(Token::at_identifier);
2760
2761 if (getToken().isNot(Token::l_paren))
2762 return emitError("expected '(' in function signature");
2763
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002764 SmallVector<Type *, 4> argTypes;
2765 ParseResult parseResult;
2766
2767 if (argNames)
2768 parseResult = parseMLArgumentList(argTypes, *argNames);
2769 else
2770 parseResult = parseTypeList(argTypes);
2771
2772 if (parseResult)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002773 return ParseFailure;
2774
2775 // Parse the return type if present.
2776 SmallVector<Type *, 4> results;
2777 if (consumeIf(Token::arrow)) {
2778 if (parseTypeList(results))
2779 return ParseFailure;
2780 }
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002781 type = builder.getFunctionType(argTypes, results);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002782 return ParseSuccess;
2783}
2784
2785/// External function declarations.
2786///
2787/// ext-func ::= `extfunc` function-signature
2788///
2789ParseResult ModuleParser::parseExtFunc() {
2790 consumeToken(Token::kw_extfunc);
Chris Lattner974a8762018-08-17 16:49:42 -07002791 auto loc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002792
2793 StringRef name;
2794 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002795 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002796 return ParseFailure;
2797
2798 // Okay, the external function definition was parsed correctly.
Chris Lattner974a8762018-08-17 16:49:42 -07002799 auto *function = new ExtFunction(name, type);
2800 getModule()->getFunctions().push_back(function);
2801
2802 // Verify no name collision / redefinition.
Chris Lattner4613d9e2018-08-19 21:17:22 -07002803 if (function->getName() != name)
Chris Lattner974a8762018-08-17 16:49:42 -07002804 return emitError(loc,
2805 "redefinition of function named '" + name.str() + "'");
2806
Chris Lattner2e595eb2018-07-10 10:08:27 -07002807 return ParseSuccess;
2808}
2809
2810/// CFG function declarations.
2811///
2812/// cfg-func ::= `cfgfunc` function-signature `{` basic-block+ `}`
2813///
2814ParseResult ModuleParser::parseCFGFunc() {
2815 consumeToken(Token::kw_cfgfunc);
Chris Lattner974a8762018-08-17 16:49:42 -07002816 auto loc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002817
2818 StringRef name;
2819 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002820 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002821 return ParseFailure;
2822
2823 // Okay, the CFG function signature was parsed correctly, create the function.
Chris Lattner974a8762018-08-17 16:49:42 -07002824 auto *function = new CFGFunction(name, type);
2825 getModule()->getFunctions().push_back(function);
2826
2827 // Verify no name collision / redefinition.
Chris Lattner4613d9e2018-08-19 21:17:22 -07002828 if (function->getName() != name)
Chris Lattner974a8762018-08-17 16:49:42 -07002829 return emitError(loc,
2830 "redefinition of function named '" + name.str() + "'");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002831
2832 return CFGFunctionParser(getState(), function).parseFunctionBody();
2833}
2834
2835/// ML function declarations.
2836///
2837/// ml-func ::= `mlfunc` ml-func-signature `{` ml-stmt* ml-return-stmt `}`
2838///
2839ParseResult ModuleParser::parseMLFunc() {
2840 consumeToken(Token::kw_mlfunc);
2841
2842 StringRef name;
2843 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002844 SmallVector<StringRef, 4> argNames;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002845
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002846 auto loc = getToken().getLoc();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002847 if (parseFunctionSignature(name, type, &argNames))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002848 return ParseFailure;
2849
2850 // Okay, the ML function signature was parsed correctly, create the function.
Chris Lattner974a8762018-08-17 16:49:42 -07002851 auto *function = MLFunction::create(name, type);
2852 getModule()->getFunctions().push_back(function);
2853
2854 // Verify no name collision / redefinition.
Chris Lattner4613d9e2018-08-19 21:17:22 -07002855 if (function->getName() != name)
Chris Lattner974a8762018-08-17 16:49:42 -07002856 return emitError(loc,
2857 "redefinition of function named '" + name.str() + "'");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002858
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002859 // Create the parser.
2860 auto parser = MLFunctionParser(getState(), function);
2861
2862 // Add definitions of the function arguments.
2863 for (unsigned i = 0, e = function->getNumArguments(); i != e; ++i) {
2864 if (parser.addDefinition({argNames[i], 0, loc}, function->getArgument(i)))
2865 return ParseFailure;
2866 }
2867
2868 return parser.parseFunctionBody();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002869}
2870
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002871/// Given an attribute that could refer to a function attribute in the remapping
2872/// table, walk it and rewrite it to use the mapped function. If it doesn't
2873/// refer to anything in the table, then it is returned unmodified.
2874static Attribute *
2875remapFunctionAttrs(Attribute *input,
2876 DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable,
2877 MLIRContext *context) {
2878 // Most attributes are trivially unrelated to function attributes, skip them
2879 // rapidly.
2880 if (!input->isOrContainsFunction())
2881 return input;
2882
2883 // If we have a function attribute, remap it.
2884 if (auto *fnAttr = dyn_cast<FunctionAttr>(input)) {
2885 auto it = remappingTable.find(fnAttr);
2886 return it != remappingTable.end() ? it->second : input;
2887 }
2888
2889 // Otherwise, we must have an array attribute, remap the elements.
2890 auto *arrayAttr = cast<ArrayAttr>(input);
2891 SmallVector<Attribute *, 8> remappedElts;
2892 bool anyChange = false;
2893 for (auto *elt : arrayAttr->getValue()) {
2894 auto *newElt = remapFunctionAttrs(elt, remappingTable, context);
2895 remappedElts.push_back(newElt);
2896 anyChange |= (elt != newElt);
2897 }
2898
2899 if (!anyChange)
2900 return input;
2901
2902 return ArrayAttr::get(remappedElts, context);
2903}
2904
2905/// Remap function attributes to resolve forward references to their actual
2906/// definition.
2907static void remapFunctionAttrsInOperation(
2908 Operation *op, DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable) {
2909 for (auto attr : op->getAttrs()) {
2910 // Do the remapping, if we got the same thing back, then it must contain
2911 // functions that aren't getting remapped.
2912 auto *newVal =
2913 remapFunctionAttrs(attr.second, remappingTable, op->getContext());
2914 if (newVal == attr.second)
2915 continue;
2916
2917 // Otherwise, replace the existing attribute with the new one. It is safe
2918 // to mutate the attribute list while we walk it because underlying
2919 // attribute lists are uniqued and immortal.
2920 op->setAttr(attr.first, newVal);
2921 }
2922}
2923
Chris Lattner4613d9e2018-08-19 21:17:22 -07002924/// Finish the end of module parsing - when the result is valid, do final
2925/// checking.
2926ParseResult ModuleParser::finalizeModule() {
2927
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002928 // Resolve all forward references, building a remapping table of attributes.
2929 DenseMap<FunctionAttr *, FunctionAttr *> remappingTable;
Chris Lattner4613d9e2018-08-19 21:17:22 -07002930 for (auto forwardRef : getState().functionForwardRefs) {
2931 auto name = forwardRef.first;
2932
2933 // Resolve the reference.
2934 auto *resolvedFunction = getModule()->getNamedFunction(name);
2935 if (!resolvedFunction)
2936 return emitError(forwardRef.second.second,
2937 "reference to undefined function '" + name.str() + "'");
2938
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002939 remappingTable[builder.getFunctionAttr(forwardRef.second.first)] =
2940 builder.getFunctionAttr(resolvedFunction);
Chris Lattner4613d9e2018-08-19 21:17:22 -07002941 }
2942
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002943 // If there was nothing to remap, then we're done.
2944 if (remappingTable.empty())
2945 return ParseSuccess;
2946
2947 // Otherwise, walk the entire module replacing uses of one attribute set with
2948 // the correct ones.
2949 for (auto &fn : *getModule()) {
2950 if (auto *cfgFn = dyn_cast<CFGFunction>(&fn)) {
2951 for (auto &bb : *cfgFn) {
2952 for (auto &inst : bb) {
2953 remapFunctionAttrsInOperation(&inst, remappingTable);
2954 }
2955 }
2956 }
2957
2958 // Otherwise, look at MLFunctions. We ignore ExtFunctions.
2959 auto *mlFn = dyn_cast<MLFunction>(&fn);
2960 if (!mlFn)
2961 continue;
2962
2963 struct MLFnWalker : public StmtWalker<MLFnWalker> {
2964 MLFnWalker(DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable)
2965 : remappingTable(remappingTable) {}
2966 void visitOperationStmt(OperationStmt *opStmt) {
2967 remapFunctionAttrsInOperation(opStmt, remappingTable);
2968 }
2969
2970 DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable;
2971 };
2972
2973 MLFnWalker(remappingTable).walk(mlFn);
2974 }
2975
2976 // Now that all references to the forward definition placeholders are
2977 // resolved, we can deallocate the placeholders.
2978 for (auto forwardRef : getState().functionForwardRefs)
2979 forwardRef.second.first->destroy();
Chris Lattner4613d9e2018-08-19 21:17:22 -07002980 return ParseSuccess;
2981}
2982
Chris Lattnere79379a2018-06-22 10:39:19 -07002983/// This is the top-level module parser.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002984ParseResult ModuleParser::parseModule() {
Chris Lattnere79379a2018-06-22 10:39:19 -07002985 while (1) {
Chris Lattner48af7d12018-07-09 19:05:38 -07002986 switch (getToken().getKind()) {
Chris Lattnere79379a2018-06-22 10:39:19 -07002987 default:
2988 emitError("expected a top level entity");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002989 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002990
Uday Bondhugula015cbb12018-07-03 20:16:08 -07002991 // If we got to the end of the file, then we're done.
Chris Lattnere79379a2018-06-22 10:39:19 -07002992 case Token::eof:
Chris Lattner4613d9e2018-08-19 21:17:22 -07002993 return finalizeModule();
Chris Lattnere79379a2018-06-22 10:39:19 -07002994
2995 // If we got an error token, then the lexer already emitted an error, just
2996 // stop. Someday we could introduce error recovery if there was demand for
2997 // it.
2998 case Token::error:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002999 return ParseFailure;
3000
3001 case Token::hash_identifier:
3002 if (parseAffineMapDef())
3003 return ParseFailure;
3004 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07003005
Uday Bondhugulabc535622018-08-07 14:24:38 -07003006 case Token::double_at_identifier:
3007 if (parseIntegerSetDef())
3008 return ParseFailure;
3009 break;
3010
Chris Lattnere79379a2018-06-22 10:39:19 -07003011 case Token::kw_extfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07003012 if (parseExtFunc())
3013 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07003014 break;
3015
Chris Lattner4c95a502018-06-23 16:03:42 -07003016 case Token::kw_cfgfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07003017 if (parseCFGFunc())
3018 return ParseFailure;
MLIR Teamf85a6262018-06-27 11:03:08 -07003019 break;
Chris Lattner4c95a502018-06-23 16:03:42 -07003020
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07003021 case Token::kw_mlfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07003022 if (parseMLFunc())
3023 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07003024 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07003025 }
3026 }
3027}
3028
3029//===----------------------------------------------------------------------===//
3030
Jacques Pienaar7b829702018-07-03 13:24:09 -07003031void mlir::defaultErrorReporter(const llvm::SMDiagnostic &error) {
3032 const auto &sourceMgr = *error.getSourceMgr();
3033 sourceMgr.PrintMessage(error.getLoc(), error.getKind(), error.getMessage());
3034}
3035
Chris Lattnere79379a2018-06-22 10:39:19 -07003036/// This parses the file specified by the indicated SourceMgr and returns an
3037/// MLIR module if it was valid. If not, it emits diagnostics and returns null.
Jacques Pienaar9c411be2018-06-24 19:17:35 -07003038Module *mlir::parseSourceFile(llvm::SourceMgr &sourceMgr, MLIRContext *context,
Jacques Pienaar7b829702018-07-03 13:24:09 -07003039 SMDiagnosticHandlerTy errorReporter) {
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003040 if (!errorReporter)
3041 errorReporter = defaultErrorReporter;
3042
3043 // We are going to replace the context's handler and redirect it to use the
3044 // error reporter. Save the existing handler and reinstate it when we're
3045 // done.
3046 auto existingContextHandler = context->getDiagnosticHandler();
3047
3048 // Install a new handler that uses the error reporter.
Chris Lattnerfc647d52018-08-27 21:05:16 -07003049 context->registerDiagnosticHandler([&](Location *location, StringRef message,
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003050 MLIRContext::DiagnosticKind kind) {
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003051 SourceMgr::DiagKind diagKind;
3052 switch (kind) {
3053 case MLIRContext::DiagnosticKind::Error:
3054 diagKind = SourceMgr::DK_Error;
3055 break;
3056 case MLIRContext::DiagnosticKind::Warning:
3057 diagKind = SourceMgr::DK_Warning;
3058 break;
3059 case MLIRContext::DiagnosticKind::Note:
3060 diagKind = SourceMgr::DK_Note;
3061 break;
3062 }
Chris Lattnerfc647d52018-08-27 21:05:16 -07003063
3064 StringRef filename;
3065 unsigned line = 0, column = 0;
3066 if (auto fileLoc = dyn_cast<FileLineColLoc>(location)) {
3067 filename = fileLoc->getFilename();
3068 line = fileLoc->getLine();
3069 column = fileLoc->getColumn();
3070 }
3071
3072 auto diag = llvm::SMDiagnostic(sourceMgr, SMLoc(), filename, line, column,
3073 diagKind, message, /*LineStr=*/StringRef(),
3074 /*Ranges=*/{}, /*FixIts=*/{});
3075
3076 errorReporter(diag);
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003077 });
3078
Chris Lattner2e595eb2018-07-10 10:08:27 -07003079 // This is the result module we are parsing into.
3080 std::unique_ptr<Module> module(new Module(context));
3081
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003082 ParserState state(sourceMgr, module.get(), errorReporter);
3083 if (ModuleParser(state).parseModule()) {
3084 context->registerDiagnosticHandler(existingContextHandler);
Chris Lattner2e595eb2018-07-10 10:08:27 -07003085 return nullptr;
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003086 }
Chris Lattner21e67f62018-07-06 10:46:19 -07003087
3088 // Make sure the parse module has no other structural problems detected by the
3089 // verifier.
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003090 std::string errorResult;
3091 module->verify(&errorResult);
3092
3093 // We don't have location information for general verifier errors, so emit the
3094 // error on the first line.
3095 if (!errorResult.empty()) {
3096 auto *mainBuffer = sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID());
3097 errorReporter(sourceMgr.GetMessage(
3098 SMLoc::getFromPointer(mainBuffer->getBufferStart()),
3099 SourceMgr::DK_Error, errorResult));
3100 return nullptr;
3101 }
3102
3103 context->registerDiagnosticHandler(existingContextHandler);
Chris Lattner2e595eb2018-07-10 10:08:27 -07003104 return module.release();
Chris Lattnere79379a2018-06-22 10:39:19 -07003105}