blob: 1de8a52da3fe3f9df0008a93c979f362b05b9b61 [file] [log] [blame]
Chris Lattnere79379a2018-06-22 10:39:19 -07001//===- Parser.cpp - MLIR Parser Implementation ----------------------------===//
2//
3// Copyright 2019 The MLIR Authors.
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16// =============================================================================
17//
18// This file implements the parser for the MLIR textual form.
19//
20//===----------------------------------------------------------------------===//
21
22#include "mlir/Parser.h"
23#include "Lexer.h"
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -070024#include "mlir/IR/AffineExpr.h"
MLIR Teamf85a6262018-06-27 11:03:08 -070025#include "mlir/IR/AffineMap.h"
Chris Lattner7121b802018-07-04 20:45:39 -070026#include "mlir/IR/Attributes.h"
Chris Lattner158e0a3e2018-07-08 20:51:38 -070027#include "mlir/IR/Builders.h"
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -070028#include "mlir/IR/IntegerSet.h"
Chris Lattnerfc647d52018-08-27 21:05:16 -070029#include "mlir/IR/Location.h"
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -070030#include "mlir/IR/MLFunction.h"
Chris Lattnerea5c3dc2018-08-21 08:42:19 -070031#include "mlir/IR/MLIRContext.h"
Chris Lattner21e67f62018-07-06 10:46:19 -070032#include "mlir/IR/Module.h"
Chris Lattner85ee1512018-07-25 11:15:20 -070033#include "mlir/IR/OpImplementation.h"
Chris Lattner21e67f62018-07-06 10:46:19 -070034#include "mlir/IR/OperationSet.h"
Chris Lattnerea5c3dc2018-08-21 08:42:19 -070035#include "mlir/IR/StmtVisitor.h"
Chris Lattnerf7e22732018-06-22 22:03:48 -070036#include "mlir/IR/Types.h"
James Molloyf0d2f442018-08-03 01:54:46 -070037#include "llvm/ADT/DenseMap.h"
Chris Lattner1aa46322018-08-21 17:55:22 -070038#include "llvm/Support/PrettyStackTrace.h"
James Molloyf0d2f442018-08-03 01:54:46 -070039#include "llvm/Support/SourceMgr.h"
Chris Lattnere79379a2018-06-22 10:39:19 -070040using namespace mlir;
Chris Lattner4c95a502018-06-23 16:03:42 -070041using llvm::SMLoc;
James Molloy0ff71542018-07-23 16:56:32 -070042using llvm::SourceMgr;
Chris Lattnere79379a2018-06-22 10:39:19 -070043
Chris Lattnerf7e22732018-06-22 22:03:48 -070044/// Simple enum to make code read better in cases that would otherwise return a
45/// bool value. Failure is "true" in a boolean context.
James Molloy0ff71542018-07-23 16:56:32 -070046enum ParseResult { ParseSuccess, ParseFailure };
Chris Lattnere79379a2018-06-22 10:39:19 -070047
Chris Lattner48af7d12018-07-09 19:05:38 -070048namespace {
49class Parser;
50
51/// This class refers to all of the state maintained globally by the parser,
52/// such as the current lexer position etc. The Parser base class provides
53/// methods to access this.
54class ParserState {
Chris Lattnered65a732018-06-28 20:45:33 -070055public:
Chris Lattner7879f842018-09-02 22:01:45 -070056 ParserState(llvm::SourceMgr &sourceMgr, Module *module)
57 : context(module->getContext()), module(module), lex(sourceMgr, context),
58 curToken(lex.lexToken()), operationSet(OperationSet::get(context)) {}
Chris Lattner2e595eb2018-07-10 10:08:27 -070059
60 // A map from affine map identifier to AffineMap.
61 llvm::StringMap<AffineMap *> affineMapDefinitions;
Chris Lattner4613d9e2018-08-19 21:17:22 -070062
Uday Bondhugulabc535622018-08-07 14:24:38 -070063 // A map from integer set identifier to IntegerSet.
64 llvm::StringMap<IntegerSet *> integerSetDefinitions;
Chris Lattnere79379a2018-06-22 10:39:19 -070065
Chris Lattner4613d9e2018-08-19 21:17:22 -070066 // This keeps track of all forward references to functions along with the
67 // temporary function used to represent them and the location of the first
68 // reference.
69 llvm::DenseMap<Identifier, std::pair<Function *, SMLoc>> functionForwardRefs;
70
Chris Lattnere79379a2018-06-22 10:39:19 -070071private:
Chris Lattner48af7d12018-07-09 19:05:38 -070072 ParserState(const ParserState &) = delete;
73 void operator=(const ParserState &) = delete;
74
75 friend class Parser;
76
77 // The context we're parsing into.
Chris Lattner2e595eb2018-07-10 10:08:27 -070078 MLIRContext *const context;
79
80 // This is the module we are parsing into.
81 Module *const module;
Chris Lattnerf7e22732018-06-22 22:03:48 -070082
83 // The lexer for the source file we're parsing.
Chris Lattnere79379a2018-06-22 10:39:19 -070084 Lexer lex;
85
86 // This is the next token that hasn't been consumed yet.
87 Token curToken;
88
Chris Lattner85ee1512018-07-25 11:15:20 -070089 // The active OperationSet we're parsing with.
90 OperationSet &operationSet;
Chris Lattner48af7d12018-07-09 19:05:38 -070091};
92} // end anonymous namespace
MLIR Teamf85a6262018-06-27 11:03:08 -070093
Chris Lattner48af7d12018-07-09 19:05:38 -070094namespace {
95
Chris Lattner992a1272018-08-07 12:02:37 -070096typedef std::function<Operation *(const OperationState &)>
Tatiana Shpeisman565b9642018-07-16 11:47:09 -070097 CreateOperationFunction;
98
Chris Lattner48af7d12018-07-09 19:05:38 -070099/// This class implement support for parsing global entities like types and
100/// shared entities like SSA names. It is intended to be subclassed by
101/// specialized subparsers that include state, e.g. when a local symbol table.
102class Parser {
103public:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700104 Builder builder;
Chris Lattner48af7d12018-07-09 19:05:38 -0700105
Chris Lattner2e595eb2018-07-10 10:08:27 -0700106 Parser(ParserState &state) : builder(state.context), state(state) {}
107
108 // Helper methods to get stuff from the parser-global state.
109 ParserState &getState() const { return state; }
Chris Lattner48af7d12018-07-09 19:05:38 -0700110 MLIRContext *getContext() const { return state.context; }
Chris Lattner2e595eb2018-07-10 10:08:27 -0700111 Module *getModule() { return state.module; }
Chris Lattner85ee1512018-07-25 11:15:20 -0700112 OperationSet &getOperationSet() const { return state.operationSet; }
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700113 llvm::SourceMgr &getSourceMgr() { return state.lex.getSourceMgr(); }
Chris Lattner48af7d12018-07-09 19:05:38 -0700114
115 /// Return the current token the parser is inspecting.
116 const Token &getToken() const { return state.curToken; }
117 StringRef getTokenSpelling() const { return state.curToken.getSpelling(); }
Chris Lattnere79379a2018-06-22 10:39:19 -0700118
Chris Lattner1628fa02018-08-23 14:32:25 -0700119 /// Encode the specified source location information into an attribute for
120 /// attachment to the IR.
Chris Lattner7879f842018-09-02 22:01:45 -0700121 Location *getEncodedSourceLocation(llvm::SMLoc loc) {
122 return state.lex.getEncodedSourceLocation(loc);
123 }
Chris Lattner1628fa02018-08-23 14:32:25 -0700124
Chris Lattnere79379a2018-06-22 10:39:19 -0700125 /// Emit an error and return failure.
Chris Lattner4c95a502018-06-23 16:03:42 -0700126 ParseResult emitError(const Twine &message) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700127 return emitError(state.curToken.getLoc(), message);
Chris Lattner4c95a502018-06-23 16:03:42 -0700128 }
129 ParseResult emitError(SMLoc loc, const Twine &message);
Chris Lattnere79379a2018-06-22 10:39:19 -0700130
131 /// Advance the current lexer onto the next token.
132 void consumeToken() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700133 assert(state.curToken.isNot(Token::eof, Token::error) &&
Chris Lattnere79379a2018-06-22 10:39:19 -0700134 "shouldn't advance past EOF or errors");
Chris Lattner48af7d12018-07-09 19:05:38 -0700135 state.curToken = state.lex.lexToken();
Chris Lattnere79379a2018-06-22 10:39:19 -0700136 }
137
138 /// Advance the current lexer onto the next token, asserting what the expected
139 /// current token is. This is preferred to the above method because it leads
140 /// to more self-documenting code with better checking.
Chris Lattner8da0c282018-06-29 11:15:56 -0700141 void consumeToken(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700142 assert(state.curToken.is(kind) && "consumed an unexpected token");
Chris Lattnere79379a2018-06-22 10:39:19 -0700143 consumeToken();
144 }
145
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700146 /// If the current token has the specified kind, consume it and return true.
147 /// If not, return false.
Chris Lattner8da0c282018-06-29 11:15:56 -0700148 bool consumeIf(Token::Kind kind) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700149 if (state.curToken.isNot(kind))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700150 return false;
151 consumeToken(kind);
152 return true;
153 }
154
Chris Lattnerf7702a62018-07-23 17:30:01 -0700155 /// Consume the specified token if present and return success. On failure,
156 /// output a diagnostic and return failure.
157 ParseResult parseToken(Token::Kind expectedToken, const Twine &message);
158
Chris Lattner40746442018-07-21 14:32:09 -0700159 /// Parse a comma-separated list of elements up until the specified end token.
160 ParseResult
161 parseCommaSeparatedListUntil(Token::Kind rightToken,
162 const std::function<ParseResult()> &parseElement,
163 bool allowEmptyList = true);
164
165 /// Parse a comma separated list of elements that must have at least one entry
166 /// in it.
167 ParseResult
168 parseCommaSeparatedList(const std::function<ParseResult()> &parseElement);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700169
Chris Lattnerf7e22732018-06-22 22:03:48 -0700170 // We have two forms of parsing methods - those that return a non-null
171 // pointer on success, and those that return a ParseResult to indicate whether
172 // they returned a failure. The second class fills in by-reference arguments
173 // as the results of their action.
174
Chris Lattnere79379a2018-06-22 10:39:19 -0700175 // Type parsing.
Chris Lattnerf7e22732018-06-22 22:03:48 -0700176 VectorType *parseVectorType();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700177 ParseResult parseDimensionListRanked(SmallVectorImpl<int> &dimensions);
Chris Lattnerf7e22732018-06-22 22:03:48 -0700178 Type *parseTensorType();
179 Type *parseMemRefType();
180 Type *parseFunctionType();
181 Type *parseType();
Chris Lattner1604e472018-07-23 08:42:19 -0700182 ParseResult parseTypeListNoParens(SmallVectorImpl<Type *> &elements);
James Molloy0ff71542018-07-23 16:56:32 -0700183 ParseResult parseTypeList(SmallVectorImpl<Type *> &elements);
Chris Lattnere79379a2018-06-22 10:39:19 -0700184
Chris Lattner7121b802018-07-04 20:45:39 -0700185 // Attribute parsing.
Chris Lattner1aa46322018-08-21 17:55:22 -0700186 Function *resolveFunctionReference(StringRef nameStr, SMLoc nameLoc,
187 FunctionType *type);
Chris Lattner7121b802018-07-04 20:45:39 -0700188 Attribute *parseAttribute();
189 ParseResult parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes);
190
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700191 // Polyhedral structures.
Chris Lattner2e595eb2018-07-10 10:08:27 -0700192 AffineMap *parseAffineMapInline();
MLIR Team718c82f2018-07-16 09:45:22 -0700193 AffineMap *parseAffineMapReference();
Uday Bondhugulabc535622018-08-07 14:24:38 -0700194 IntegerSet *parseIntegerSetInline();
195 IntegerSet *parseIntegerSetReference();
MLIR Teamf85a6262018-06-27 11:03:08 -0700196
Chris Lattner48af7d12018-07-09 19:05:38 -0700197private:
198 // The Parser is subclassed and reinstantiated. Do not add additional
199 // non-trivial state here, add it to the ParserState class.
200 ParserState &state;
Chris Lattnere79379a2018-06-22 10:39:19 -0700201};
202} // end anonymous namespace
203
204//===----------------------------------------------------------------------===//
205// Helper methods.
206//===----------------------------------------------------------------------===//
207
Chris Lattner4c95a502018-06-23 16:03:42 -0700208ParseResult Parser::emitError(SMLoc loc, const Twine &message) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700209 // If we hit a parse error in response to a lexer error, then the lexer
Jacques Pienaar9c411be2018-06-24 19:17:35 -0700210 // already reported the error.
Chris Lattner48af7d12018-07-09 19:05:38 -0700211 if (getToken().is(Token::error))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700212 return ParseFailure;
213
Chris Lattner7879f842018-09-02 22:01:45 -0700214 getContext()->emitDiagnostic(getEncodedSourceLocation(loc), message,
215 MLIRContext::DiagnosticKind::Error);
Chris Lattnere79379a2018-06-22 10:39:19 -0700216 return ParseFailure;
217}
218
Chris Lattnerf7702a62018-07-23 17:30:01 -0700219/// Consume the specified token if present and return success. On failure,
220/// output a diagnostic and return failure.
221ParseResult Parser::parseToken(Token::Kind expectedToken,
222 const Twine &message) {
223 if (consumeIf(expectedToken))
224 return ParseSuccess;
225 return emitError(message);
226}
227
Chris Lattner40746442018-07-21 14:32:09 -0700228/// Parse a comma separated list of elements that must have at least one entry
229/// in it.
230ParseResult Parser::parseCommaSeparatedList(
231 const std::function<ParseResult()> &parseElement) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700232 // Non-empty case starts with an element.
233 if (parseElement())
234 return ParseFailure;
235
236 // Otherwise we have a list of comma separated elements.
237 while (consumeIf(Token::comma)) {
238 if (parseElement())
239 return ParseFailure;
240 }
Chris Lattner40746442018-07-21 14:32:09 -0700241 return ParseSuccess;
242}
243
244/// Parse a comma-separated list of elements, terminated with an arbitrary
245/// token. This allows empty lists if allowEmptyList is true.
246///
247/// abstract-list ::= rightToken // if allowEmptyList == true
248/// abstract-list ::= element (',' element)* rightToken
249///
250ParseResult Parser::parseCommaSeparatedListUntil(
251 Token::Kind rightToken, const std::function<ParseResult()> &parseElement,
252 bool allowEmptyList) {
253 // Handle the empty case.
254 if (getToken().is(rightToken)) {
255 if (!allowEmptyList)
256 return emitError("expected list element");
257 consumeToken(rightToken);
258 return ParseSuccess;
259 }
260
Chris Lattnerf7702a62018-07-23 17:30:01 -0700261 if (parseCommaSeparatedList(parseElement) ||
262 parseToken(rightToken, "expected ',' or '" +
263 Token::getTokenSpelling(rightToken) + "'"))
Chris Lattner40746442018-07-21 14:32:09 -0700264 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700265
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700266 return ParseSuccess;
267}
Chris Lattnere79379a2018-06-22 10:39:19 -0700268
269//===----------------------------------------------------------------------===//
270// Type Parsing
271//===----------------------------------------------------------------------===//
272
Chris Lattnerc3251192018-07-27 13:09:58 -0700273/// Parse an arbitrary type.
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700274///
Chris Lattnerc3251192018-07-27 13:09:58 -0700275/// type ::= integer-type
276/// | float-type
277/// | other-type
278/// | vector-type
279/// | tensor-type
280/// | memref-type
281/// | function-type
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700282///
Chris Lattnerc3251192018-07-27 13:09:58 -0700283/// float-type ::= `f16` | `bf16` | `f32` | `f64`
284/// other-type ::= `affineint` | `tf_control`
285///
286Type *Parser::parseType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700287 switch (getToken().getKind()) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700288 default:
289 return (emitError("expected type"), nullptr);
Chris Lattnerc3251192018-07-27 13:09:58 -0700290 case Token::kw_memref:
291 return parseMemRefType();
292 case Token::kw_tensor:
293 return parseTensorType();
294 case Token::kw_vector:
295 return parseVectorType();
296 case Token::l_paren:
297 return parseFunctionType();
298 // integer-type
299 case Token::inttype: {
300 auto width = getToken().getIntTypeBitwidth();
301 if (!width.hasValue())
302 return (emitError("invalid integer width"), nullptr);
Nicolas Vasilache1b8c0842018-08-27 10:26:15 -0700303 if (width > IntegerType::kMaxWidth)
304 return (emitError("integer bitwidth is limited to " +
305 Twine(IntegerType::kMaxWidth) + " bits"),
306 nullptr);
Chris Lattnerc3251192018-07-27 13:09:58 -0700307 consumeToken(Token::inttype);
308 return builder.getIntegerType(width.getValue());
309 }
310
311 // float-type
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700312 case Token::kw_bf16:
313 consumeToken(Token::kw_bf16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700314 return builder.getBF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700315 case Token::kw_f16:
316 consumeToken(Token::kw_f16);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700317 return builder.getF16Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700318 case Token::kw_f32:
319 consumeToken(Token::kw_f32);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700320 return builder.getF32Type();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700321 case Token::kw_f64:
322 consumeToken(Token::kw_f64);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700323 return builder.getF64Type();
Chris Lattnerc3251192018-07-27 13:09:58 -0700324
325 // other-type
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700326 case Token::kw_affineint:
327 consumeToken(Token::kw_affineint);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700328 return builder.getAffineIntType();
Jacques Pienaarc0d69302018-07-27 11:07:12 -0700329 case Token::kw_tf_control:
330 consumeToken(Token::kw_tf_control);
331 return builder.getTFControlType();
James Molloy72b0cbe2018-08-01 12:55:27 -0700332 case Token::kw_tf_string:
333 consumeToken(Token::kw_tf_string);
334 return builder.getTFStringType();
Chris Lattnerf958bbe2018-06-29 22:08:05 -0700335 }
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700336}
337
338/// Parse a vector type.
339///
340/// vector-type ::= `vector` `<` const-dimension-list primitive-type `>`
341/// const-dimension-list ::= (integer-literal `x`)+
342///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700343VectorType *Parser::parseVectorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700344 consumeToken(Token::kw_vector);
345
Chris Lattnerf7702a62018-07-23 17:30:01 -0700346 if (parseToken(Token::less, "expected '<' in vector type"))
347 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700348
Chris Lattner48af7d12018-07-09 19:05:38 -0700349 if (getToken().isNot(Token::integer))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700350 return (emitError("expected dimension size in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700351
352 SmallVector<unsigned, 4> dimensions;
Chris Lattner48af7d12018-07-09 19:05:38 -0700353 while (getToken().is(Token::integer)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700354 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700355 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700356 if (!dimension.hasValue())
Chris Lattnerf7e22732018-06-22 22:03:48 -0700357 return (emitError("invalid dimension in vector type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700358 dimensions.push_back(dimension.getValue());
359
360 consumeToken(Token::integer);
361
362 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700363 if (getToken().isNot(Token::bare_identifier) ||
364 getTokenSpelling()[0] != 'x')
Chris Lattnerf7e22732018-06-22 22:03:48 -0700365 return (emitError("expected 'x' in vector dimension list"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700366
367 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700368 if (getTokenSpelling().size() != 1)
369 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700370
371 // Consume the 'x'.
372 consumeToken(Token::bare_identifier);
373 }
374
375 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700376 auto typeLoc = getToken().getLoc();
377 auto *elementType = parseType();
378 if (!elementType || parseToken(Token::greater, "expected '>' in vector type"))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700379 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700380
Chris Lattnerc3251192018-07-27 13:09:58 -0700381 if (!isa<FloatType>(elementType) && !isa<IntegerType>(elementType))
382 return (emitError(typeLoc, "invalid vector element type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700383
Chris Lattnerf7e22732018-06-22 22:03:48 -0700384 return VectorType::get(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700385}
386
387/// Parse a dimension list of a tensor or memref type. This populates the
388/// dimension list, returning -1 for the '?' dimensions.
389///
390/// dimension-list-ranked ::= (dimension `x`)*
391/// dimension ::= `?` | integer-literal
392///
393ParseResult Parser::parseDimensionListRanked(SmallVectorImpl<int> &dimensions) {
Chris Lattner48af7d12018-07-09 19:05:38 -0700394 while (getToken().isAny(Token::integer, Token::question)) {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700395 if (consumeIf(Token::question)) {
396 dimensions.push_back(-1);
397 } else {
398 // Make sure this integer value is in bound and valid.
Chris Lattner48af7d12018-07-09 19:05:38 -0700399 auto dimension = getToken().getUnsignedIntegerValue();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700400 if (!dimension.hasValue() || (int)dimension.getValue() < 0)
401 return emitError("invalid dimension");
402 dimensions.push_back((int)dimension.getValue());
403 consumeToken(Token::integer);
404 }
405
406 // Make sure we have an 'x' or something like 'xbf32'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700407 if (getToken().isNot(Token::bare_identifier) ||
408 getTokenSpelling()[0] != 'x')
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700409 return emitError("expected 'x' in dimension list");
410
411 // If we had a prefix of 'x', lex the next token immediately after the 'x'.
Chris Lattner48af7d12018-07-09 19:05:38 -0700412 if (getTokenSpelling().size() != 1)
413 state.lex.resetPointer(getTokenSpelling().data() + 1);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700414
415 // Consume the 'x'.
416 consumeToken(Token::bare_identifier);
417 }
418
419 return ParseSuccess;
420}
421
422/// Parse a tensor type.
423///
424/// tensor-type ::= `tensor` `<` dimension-list element-type `>`
425/// dimension-list ::= dimension-list-ranked | `??`
426///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700427Type *Parser::parseTensorType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700428 consumeToken(Token::kw_tensor);
429
Chris Lattnerf7702a62018-07-23 17:30:01 -0700430 if (parseToken(Token::less, "expected '<' in tensor type"))
431 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700432
433 bool isUnranked;
434 SmallVector<int, 4> dimensions;
435
436 if (consumeIf(Token::questionquestion)) {
437 isUnranked = true;
438 } else {
439 isUnranked = false;
440 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700441 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700442 }
443
444 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700445 auto typeLoc = getToken().getLoc();
446 auto *elementType = parseType();
447 if (!elementType || parseToken(Token::greater, "expected '>' in tensor type"))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700448 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700449
Chris Lattnerc3251192018-07-27 13:09:58 -0700450 if (!isa<IntegerType>(elementType) && !isa<FloatType>(elementType) &&
451 !isa<VectorType>(elementType))
452 return (emitError(typeLoc, "invalid tensor element type"), nullptr);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700453
MLIR Team355ec862018-06-23 18:09:09 -0700454 if (isUnranked)
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700455 return builder.getTensorType(elementType);
456 return builder.getTensorType(dimensions, elementType);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700457}
458
459/// Parse a memref type.
460///
461/// memref-type ::= `memref` `<` dimension-list-ranked element-type
462/// (`,` semi-affine-map-composition)? (`,` memory-space)? `>`
463///
464/// semi-affine-map-composition ::= (semi-affine-map `,` )* semi-affine-map
465/// memory-space ::= integer-literal /* | TODO: address-space-id */
466///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700467Type *Parser::parseMemRefType() {
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700468 consumeToken(Token::kw_memref);
469
Chris Lattnerf7702a62018-07-23 17:30:01 -0700470 if (parseToken(Token::less, "expected '<' in memref type"))
471 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700472
473 SmallVector<int, 4> dimensions;
474 if (parseDimensionListRanked(dimensions))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700475 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700476
477 // Parse the element type.
Chris Lattnerc3251192018-07-27 13:09:58 -0700478 auto typeLoc = getToken().getLoc();
479 auto *elementType = parseType();
Chris Lattnerf7e22732018-06-22 22:03:48 -0700480 if (!elementType)
481 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700482
Chris Lattnerc3251192018-07-27 13:09:58 -0700483 if (!isa<IntegerType>(elementType) && !isa<FloatType>(elementType) &&
484 !isa<VectorType>(elementType))
485 return (emitError(typeLoc, "invalid memref element type"), nullptr);
486
MLIR Team718c82f2018-07-16 09:45:22 -0700487 // Parse semi-affine-map-composition.
James Molloy0ff71542018-07-23 16:56:32 -0700488 SmallVector<AffineMap *, 2> affineMapComposition;
Chris Lattner413db6a2018-07-25 12:55:50 -0700489 unsigned memorySpace = 0;
MLIR Team718c82f2018-07-16 09:45:22 -0700490 bool parsedMemorySpace = false;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700491
MLIR Team718c82f2018-07-16 09:45:22 -0700492 auto parseElt = [&]() -> ParseResult {
493 if (getToken().is(Token::integer)) {
494 // Parse memory space.
495 if (parsedMemorySpace)
496 return emitError("multiple memory spaces specified in memref type");
497 auto v = getToken().getUnsignedIntegerValue();
498 if (!v.hasValue())
499 return emitError("invalid memory space in memref type");
500 memorySpace = v.getValue();
501 consumeToken(Token::integer);
502 parsedMemorySpace = true;
503 } else {
504 // Parse affine map.
505 if (parsedMemorySpace)
506 return emitError("affine map after memory space in memref type");
James Molloy0ff71542018-07-23 16:56:32 -0700507 auto *affineMap = parseAffineMapReference();
MLIR Team718c82f2018-07-16 09:45:22 -0700508 if (affineMap == nullptr)
509 return ParseFailure;
510 affineMapComposition.push_back(affineMap);
511 }
512 return ParseSuccess;
513 };
514
Chris Lattner413db6a2018-07-25 12:55:50 -0700515 // Parse a list of mappings and address space if present.
516 if (consumeIf(Token::comma)) {
517 // Parse comma separated list of affine maps, followed by memory space.
518 if (parseCommaSeparatedListUntil(Token::greater, parseElt,
519 /*allowEmptyList=*/false)) {
520 return nullptr;
521 }
522 } else {
523 if (parseToken(Token::greater, "expected ',' or '>' in memref type"))
524 return nullptr;
MLIR Team718c82f2018-07-16 09:45:22 -0700525 }
MLIR Team718c82f2018-07-16 09:45:22 -0700526
527 return MemRefType::get(dimensions, elementType, affineMapComposition,
528 memorySpace);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700529}
530
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700531/// Parse a function type.
532///
533/// function-type ::= type-list-parens `->` type-list
534///
Chris Lattnerf7e22732018-06-22 22:03:48 -0700535Type *Parser::parseFunctionType() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700536 assert(getToken().is(Token::l_paren));
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700537
Chris Lattnerf7702a62018-07-23 17:30:01 -0700538 SmallVector<Type *, 4> arguments, results;
539 if (parseTypeList(arguments) ||
540 parseToken(Token::arrow, "expected '->' in function type") ||
541 parseTypeList(results))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700542 return nullptr;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700543
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700544 return builder.getFunctionType(arguments, results);
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700545}
546
Chris Lattner1604e472018-07-23 08:42:19 -0700547/// Parse a list of types without an enclosing parenthesis. The list must have
548/// at least one member.
549///
550/// type-list-no-parens ::= type (`,` type)*
551///
552ParseResult Parser::parseTypeListNoParens(SmallVectorImpl<Type *> &elements) {
553 auto parseElt = [&]() -> ParseResult {
554 auto elt = parseType();
555 elements.push_back(elt);
556 return elt ? ParseSuccess : ParseFailure;
557 };
558
559 return parseCommaSeparatedList(parseElt);
560}
561
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700562/// Parse a "type list", which is a singular type, or a parenthesized list of
563/// types.
564///
565/// type-list ::= type-list-parens | type
566/// type-list-parens ::= `(` `)`
Chris Lattner1604e472018-07-23 08:42:19 -0700567/// | `(` type-list-no-parens `)`
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700568///
James Molloy0ff71542018-07-23 16:56:32 -0700569ParseResult Parser::parseTypeList(SmallVectorImpl<Type *> &elements) {
Chris Lattnerf7e22732018-06-22 22:03:48 -0700570 auto parseElt = [&]() -> ParseResult {
571 auto elt = parseType();
572 elements.push_back(elt);
573 return elt ? ParseSuccess : ParseFailure;
574 };
575
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700576 // If there is no parens, then it must be a singular type.
577 if (!consumeIf(Token::l_paren))
Chris Lattnerf7e22732018-06-22 22:03:48 -0700578 return parseElt();
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700579
Chris Lattner40746442018-07-21 14:32:09 -0700580 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt))
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700581 return ParseFailure;
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700582
Chris Lattnerbb8fafc2018-06-22 15:52:02 -0700583 return ParseSuccess;
584}
585
Chris Lattner4c95a502018-06-23 16:03:42 -0700586//===----------------------------------------------------------------------===//
Chris Lattner7121b802018-07-04 20:45:39 -0700587// Attribute parsing.
588//===----------------------------------------------------------------------===//
589
Chris Lattner1aa46322018-08-21 17:55:22 -0700590/// Given a parsed reference to a function name like @foo and a type that it
591/// corresponds to, resolve it to a concrete function object (possibly
592/// synthesizing a forward reference) or emit an error and return null on
593/// failure.
594Function *Parser::resolveFunctionReference(StringRef nameStr, SMLoc nameLoc,
595 FunctionType *type) {
596 Identifier name = builder.getIdentifier(nameStr.drop_front());
597
598 // See if the function has already been defined in the module.
599 Function *function = getModule()->getNamedFunction(name);
600
601 // If not, get or create a forward reference to one.
602 if (!function) {
603 auto &entry = state.functionForwardRefs[name];
604 if (!entry.first) {
605 entry.first = new ExtFunction(name, type);
606 entry.second = nameLoc;
607 }
608 function = entry.first;
609 }
610
611 if (function->getType() != type)
612 return (emitError(nameLoc, "reference to function with mismatched type"),
613 nullptr);
614 return function;
615}
616
Chris Lattner7121b802018-07-04 20:45:39 -0700617/// Attribute parsing.
618///
619/// attribute-value ::= bool-literal
620/// | integer-literal
621/// | float-literal
622/// | string-literal
James Molloyf0d2f442018-08-03 01:54:46 -0700623/// | type
Chris Lattner7121b802018-07-04 20:45:39 -0700624/// | `[` (attribute-value (`,` attribute-value)*)? `]`
Chris Lattner4613d9e2018-08-19 21:17:22 -0700625/// | function-id `:` function-type
Chris Lattner7121b802018-07-04 20:45:39 -0700626///
627Attribute *Parser::parseAttribute() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700628 switch (getToken().getKind()) {
Chris Lattner7121b802018-07-04 20:45:39 -0700629 case Token::kw_true:
630 consumeToken(Token::kw_true);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700631 return builder.getBoolAttr(true);
Chris Lattner7121b802018-07-04 20:45:39 -0700632 case Token::kw_false:
633 consumeToken(Token::kw_false);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700634 return builder.getBoolAttr(false);
Chris Lattner7121b802018-07-04 20:45:39 -0700635
Jacques Pienaar84491092018-07-31 17:15:15 -0700636 case Token::floatliteral: {
637 auto val = getToken().getFloatingPointValue();
638 if (!val.hasValue())
639 return (emitError("floating point value too large for attribute"),
640 nullptr);
641 consumeToken(Token::floatliteral);
642 return builder.getFloatAttr(val.getValue());
643 }
Chris Lattner7121b802018-07-04 20:45:39 -0700644 case Token::integer: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700645 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700646 if (!val.hasValue() || (int64_t)val.getValue() < 0)
647 return (emitError("integer too large for attribute"), nullptr);
648 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700649 return builder.getIntegerAttr((int64_t)val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700650 }
651
652 case Token::minus: {
653 consumeToken(Token::minus);
Chris Lattner48af7d12018-07-09 19:05:38 -0700654 if (getToken().is(Token::integer)) {
655 auto val = getToken().getUInt64IntegerValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700656 if (!val.hasValue() || (int64_t)-val.getValue() >= 0)
657 return (emitError("integer too large for attribute"), nullptr);
658 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700659 return builder.getIntegerAttr((int64_t)-val.getValue());
Chris Lattner7121b802018-07-04 20:45:39 -0700660 }
Jacques Pienaar84491092018-07-31 17:15:15 -0700661 if (getToken().is(Token::floatliteral)) {
662 auto val = getToken().getFloatingPointValue();
663 if (!val.hasValue())
664 return (emitError("floating point value too large for attribute"),
665 nullptr);
666 consumeToken(Token::floatliteral);
667 return builder.getFloatAttr(-val.getValue());
668 }
Chris Lattner7121b802018-07-04 20:45:39 -0700669
670 return (emitError("expected constant integer or floating point value"),
671 nullptr);
672 }
673
674 case Token::string: {
Chris Lattner48af7d12018-07-09 19:05:38 -0700675 auto val = getToken().getStringValue();
Chris Lattner7121b802018-07-04 20:45:39 -0700676 consumeToken(Token::string);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700677 return builder.getStringAttr(val);
Chris Lattner7121b802018-07-04 20:45:39 -0700678 }
679
Chris Lattner85ee1512018-07-25 11:15:20 -0700680 case Token::l_square: {
681 consumeToken(Token::l_square);
James Molloy0ff71542018-07-23 16:56:32 -0700682 SmallVector<Attribute *, 4> elements;
Chris Lattner7121b802018-07-04 20:45:39 -0700683
684 auto parseElt = [&]() -> ParseResult {
685 elements.push_back(parseAttribute());
686 return elements.back() ? ParseSuccess : ParseFailure;
687 };
688
Chris Lattner85ee1512018-07-25 11:15:20 -0700689 if (parseCommaSeparatedListUntil(Token::r_square, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700690 return nullptr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700691 return builder.getArrayAttr(elements);
Chris Lattner7121b802018-07-04 20:45:39 -0700692 }
James Molloyf0d2f442018-08-03 01:54:46 -0700693 case Token::hash_identifier:
694 case Token::l_paren: {
MLIR Teamb61885d2018-07-18 16:29:21 -0700695 // Try to parse affine map reference.
James Molloyf0d2f442018-08-03 01:54:46 -0700696 if (auto *affineMap = parseAffineMapReference())
MLIR Teamb61885d2018-07-18 16:29:21 -0700697 return builder.getAffineMapAttr(affineMap);
Chris Lattner7121b802018-07-04 20:45:39 -0700698 return (emitError("expected constant attribute value"), nullptr);
699 }
Chris Lattner4613d9e2018-08-19 21:17:22 -0700700
701 case Token::at_identifier: {
702 auto nameLoc = getToken().getLoc();
Chris Lattner1aa46322018-08-21 17:55:22 -0700703 auto nameStr = getTokenSpelling();
Chris Lattner4613d9e2018-08-19 21:17:22 -0700704 consumeToken(Token::at_identifier);
705
706 if (parseToken(Token::colon, "expected ':' and function type"))
707 return nullptr;
708 auto typeLoc = getToken().getLoc();
709 Type *type = parseType();
710 if (!type)
711 return nullptr;
Chris Lattner1aa46322018-08-21 17:55:22 -0700712 auto *fnType = dyn_cast<FunctionType>(type);
Chris Lattner4613d9e2018-08-19 21:17:22 -0700713 if (!fnType)
714 return (emitError(typeLoc, "expected function type"), nullptr);
715
Chris Lattner1aa46322018-08-21 17:55:22 -0700716 auto *function = resolveFunctionReference(nameStr, nameLoc, fnType);
717 return function ? builder.getFunctionAttr(function) : nullptr;
Chris Lattner4613d9e2018-08-19 21:17:22 -0700718 }
719
James Molloyf0d2f442018-08-03 01:54:46 -0700720 default: {
721 if (Type *type = parseType())
722 return builder.getTypeAttr(type);
723 return nullptr;
724 }
725 }
Chris Lattner7121b802018-07-04 20:45:39 -0700726}
727
Chris Lattner7121b802018-07-04 20:45:39 -0700728/// Attribute dictionary.
729///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700730/// attribute-dict ::= `{` `}`
731/// | `{` attribute-entry (`,` attribute-entry)* `}`
732/// attribute-entry ::= bare-id `:` attribute-value
Chris Lattner7121b802018-07-04 20:45:39 -0700733///
James Molloy0ff71542018-07-23 16:56:32 -0700734ParseResult
735Parser::parseAttributeDict(SmallVectorImpl<NamedAttribute> &attributes) {
Chris Lattner7121b802018-07-04 20:45:39 -0700736 consumeToken(Token::l_brace);
737
738 auto parseElt = [&]() -> ParseResult {
739 // We allow keywords as attribute names.
Chris Lattner48af7d12018-07-09 19:05:38 -0700740 if (getToken().isNot(Token::bare_identifier, Token::inttype) &&
741 !getToken().isKeyword())
Chris Lattner7121b802018-07-04 20:45:39 -0700742 return emitError("expected attribute name");
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700743 auto nameId = builder.getIdentifier(getTokenSpelling());
Chris Lattner7121b802018-07-04 20:45:39 -0700744 consumeToken();
745
Chris Lattnerf7702a62018-07-23 17:30:01 -0700746 if (parseToken(Token::colon, "expected ':' in attribute list"))
747 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700748
749 auto attr = parseAttribute();
James Molloy0ff71542018-07-23 16:56:32 -0700750 if (!attr)
751 return ParseFailure;
Chris Lattner7121b802018-07-04 20:45:39 -0700752
753 attributes.push_back({nameId, attr});
754 return ParseSuccess;
755 };
756
Chris Lattner40746442018-07-21 14:32:09 -0700757 if (parseCommaSeparatedListUntil(Token::r_brace, parseElt))
Chris Lattner7121b802018-07-04 20:45:39 -0700758 return ParseFailure;
759
760 return ParseSuccess;
761}
762
763//===----------------------------------------------------------------------===//
MLIR Teamf85a6262018-06-27 11:03:08 -0700764// Polyhedral structures.
765//===----------------------------------------------------------------------===//
766
Chris Lattner2e595eb2018-07-10 10:08:27 -0700767/// Lower precedence ops (all at the same precedence level). LNoOp is false in
768/// the boolean sense.
769enum AffineLowPrecOp {
770 /// Null value.
771 LNoOp,
772 Add,
773 Sub
774};
MLIR Teamf85a6262018-06-27 11:03:08 -0700775
Chris Lattner2e595eb2018-07-10 10:08:27 -0700776/// Higher precedence ops - all at the same precedence level. HNoOp is false in
777/// the boolean sense.
778enum AffineHighPrecOp {
779 /// Null value.
780 HNoOp,
781 Mul,
782 FloorDiv,
783 CeilDiv,
784 Mod
785};
Chris Lattner7121b802018-07-04 20:45:39 -0700786
Chris Lattner2e595eb2018-07-10 10:08:27 -0700787namespace {
Uday Bondhugulabc535622018-08-07 14:24:38 -0700788/// This is a specialized parser for affine structures (affine maps, affine
789/// expressions, and integer sets), maintaining the state transient to their
790/// bodies.
791class AffineParser : public Parser {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700792public:
Uday Bondhugulabc535622018-08-07 14:24:38 -0700793 explicit AffineParser(ParserState &state) : Parser(state) {}
Chris Lattner7121b802018-07-04 20:45:39 -0700794
Chris Lattner2e595eb2018-07-10 10:08:27 -0700795 AffineMap *parseAffineMapInline();
Uday Bondhugulabc535622018-08-07 14:24:38 -0700796 IntegerSet *parseIntegerSetInline();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700797
Chris Lattner2e595eb2018-07-10 10:08:27 -0700798private:
Chris Lattner2e595eb2018-07-10 10:08:27 -0700799 // Binary affine op parsing.
800 AffineLowPrecOp consumeIfLowPrecOp();
801 AffineHighPrecOp consumeIfHighPrecOp();
MLIR Teamf85a6262018-06-27 11:03:08 -0700802
Chris Lattner2e595eb2018-07-10 10:08:27 -0700803 // Identifier lists for polyhedral structures.
Chris Lattner413db6a2018-07-25 12:55:50 -0700804 ParseResult parseDimIdList(unsigned &numDims);
805 ParseResult parseSymbolIdList(unsigned &numSymbols);
806 ParseResult parseIdentifierDefinition(AffineExpr *idExpr);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700807
808 AffineExpr *parseAffineExpr();
809 AffineExpr *parseParentheticalExpr();
810 AffineExpr *parseNegateExpression(AffineExpr *lhs);
811 AffineExpr *parseIntegerExpr();
812 AffineExpr *parseBareIdExpr();
813
814 AffineExpr *getBinaryAffineOpExpr(AffineHighPrecOp op, AffineExpr *lhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700815 AffineExpr *rhs, SMLoc opLoc);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700816 AffineExpr *getBinaryAffineOpExpr(AffineLowPrecOp op, AffineExpr *lhs,
817 AffineExpr *rhs);
818 AffineExpr *parseAffineOperandExpr(AffineExpr *lhs);
819 AffineExpr *parseAffineLowPrecOpExpr(AffineExpr *llhs,
820 AffineLowPrecOp llhsOp);
821 AffineExpr *parseAffineHighPrecOpExpr(AffineExpr *llhs,
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700822 AffineHighPrecOp llhsOp,
823 SMLoc llhsOpLoc);
Uday Bondhugulabc535622018-08-07 14:24:38 -0700824 AffineExpr *parseAffineConstraint(bool *isEq);
Chris Lattner2e595eb2018-07-10 10:08:27 -0700825
826private:
Chris Lattner413db6a2018-07-25 12:55:50 -0700827 SmallVector<std::pair<StringRef, AffineExpr *>, 4> dimsAndSymbols;
Chris Lattner2e595eb2018-07-10 10:08:27 -0700828};
829} // end anonymous namespace
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -0700830
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700831/// Create an affine binary high precedence op expression (mul's, div's, mod).
832/// opLoc is the location of the op token to be used to report errors
833/// for non-conforming expressions.
Uday Bondhugulabc535622018-08-07 14:24:38 -0700834AffineExpr *AffineParser::getBinaryAffineOpExpr(AffineHighPrecOp op,
835 AffineExpr *lhs,
836 AffineExpr *rhs, SMLoc opLoc) {
Uday Bondhugula0115dbb2018-07-11 21:31:07 -0700837 // TODO: make the error location info accurate.
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700838 switch (op) {
839 case Mul:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700840 if (!lhs->isSymbolicOrConstant() && !rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700841 emitError(opLoc, "non-affine expression: at least one of the multiply "
842 "operands has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700843 return nullptr;
844 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700845 return builder.getMulExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700846 case FloorDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700847 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700848 emitError(opLoc, "non-affine expression: right operand of floordiv "
849 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700850 return nullptr;
851 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700852 return builder.getFloorDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700853 case CeilDiv:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700854 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700855 emitError(opLoc, "non-affine expression: right operand of ceildiv "
856 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700857 return nullptr;
858 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700859 return builder.getCeilDivExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700860 case Mod:
Uday Bondhugulacbe4cca2018-07-19 13:07:16 -0700861 if (!rhs->isSymbolicOrConstant()) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700862 emitError(opLoc, "non-affine expression: right operand of mod "
863 "has to be either a constant or symbolic");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700864 return nullptr;
865 }
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700866 return builder.getModExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700867 case HNoOp:
868 llvm_unreachable("can't create affine expression for null high prec op");
869 return nullptr;
870 }
871}
872
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700873/// Create an affine binary low precedence op expression (add, sub).
Uday Bondhugulabc535622018-08-07 14:24:38 -0700874AffineExpr *AffineParser::getBinaryAffineOpExpr(AffineLowPrecOp op,
875 AffineExpr *lhs,
876 AffineExpr *rhs) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700877 switch (op) {
878 case AffineLowPrecOp::Add:
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700879 return builder.getAddExpr(lhs, rhs);
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700880 case AffineLowPrecOp::Sub:
Uday Bondhugulac1faf662018-07-19 14:08:50 -0700881 return builder.getAddExpr(
882 lhs, builder.getMulExpr(rhs, builder.getConstantExpr(-1)));
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700883 case AffineLowPrecOp::LNoOp:
884 llvm_unreachable("can't create affine expression for null low prec op");
885 return nullptr;
886 }
887}
888
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700889/// Consume this token if it is a lower precedence affine op (there are only two
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700890/// precedence levels).
Uday Bondhugulabc535622018-08-07 14:24:38 -0700891AffineLowPrecOp AffineParser::consumeIfLowPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700892 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700893 case Token::plus:
894 consumeToken(Token::plus);
895 return AffineLowPrecOp::Add;
896 case Token::minus:
897 consumeToken(Token::minus);
898 return AffineLowPrecOp::Sub;
899 default:
900 return AffineLowPrecOp::LNoOp;
901 }
902}
903
904/// Consume this token if it is a higher precedence affine op (there are only
905/// two precedence levels)
Uday Bondhugulabc535622018-08-07 14:24:38 -0700906AffineHighPrecOp AffineParser::consumeIfHighPrecOp() {
Chris Lattner48af7d12018-07-09 19:05:38 -0700907 switch (getToken().getKind()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -0700908 case Token::star:
909 consumeToken(Token::star);
910 return Mul;
911 case Token::kw_floordiv:
912 consumeToken(Token::kw_floordiv);
913 return FloorDiv;
914 case Token::kw_ceildiv:
915 consumeToken(Token::kw_ceildiv);
916 return CeilDiv;
917 case Token::kw_mod:
918 consumeToken(Token::kw_mod);
919 return Mod;
920 default:
921 return HNoOp;
922 }
923}
924
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700925/// Parse a high precedence op expression list: mul, div, and mod are high
926/// precedence binary ops, i.e., parse a
927/// expr_1 op_1 expr_2 op_2 ... expr_n
928/// where op_1, op_2 are all a AffineHighPrecOp (mul, div, mod).
929/// All affine binary ops are left associative.
930/// Given llhs, returns (llhs llhsOp lhs) op rhs, or (lhs op rhs) if llhs is
931/// null. If no rhs can be found, returns (llhs llhsOp lhs) or lhs if llhs is
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700932/// null. llhsOpLoc is the location of the llhsOp token that will be used to
933/// report an error for non-conforming expressions.
Uday Bondhugulabc535622018-08-07 14:24:38 -0700934AffineExpr *AffineParser::parseAffineHighPrecOpExpr(AffineExpr *llhs,
935 AffineHighPrecOp llhsOp,
936 SMLoc llhsOpLoc) {
Chris Lattner2e595eb2018-07-10 10:08:27 -0700937 AffineExpr *lhs = parseAffineOperandExpr(llhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700938 if (!lhs)
939 return nullptr;
940
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700941 // Found an LHS. Parse the remaining expression.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700942 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -0700943 if (AffineHighPrecOp op = consumeIfHighPrecOp()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700944 if (llhs) {
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700945 AffineExpr *expr = getBinaryAffineOpExpr(llhsOp, llhs, lhs, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700946 if (!expr)
947 return nullptr;
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700948 return parseAffineHighPrecOpExpr(expr, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700949 }
950 // No LLHS, get RHS
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700951 return parseAffineHighPrecOpExpr(lhs, op, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700952 }
953
954 // This is the last operand in this expression.
955 if (llhs)
Uday Bondhugula851b8fd2018-07-20 14:57:21 -0700956 return getBinaryAffineOpExpr(llhsOp, llhs, lhs, llhsOpLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700957
958 // No llhs, 'lhs' itself is the expression.
959 return lhs;
960}
961
962/// Parse an affine expression inside parentheses.
963///
964/// affine-expr ::= `(` affine-expr `)`
Uday Bondhugulabc535622018-08-07 14:24:38 -0700965AffineExpr *AffineParser::parseParentheticalExpr() {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700966 if (parseToken(Token::l_paren, "expected '('"))
967 return nullptr;
Chris Lattner48af7d12018-07-09 19:05:38 -0700968 if (getToken().is(Token::r_paren))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700969 return (emitError("no expression inside parentheses"), nullptr);
Chris Lattnerf7702a62018-07-23 17:30:01 -0700970
Chris Lattner2e595eb2018-07-10 10:08:27 -0700971 auto *expr = parseAffineExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700972 if (!expr)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700973 return nullptr;
Chris Lattnerf7702a62018-07-23 17:30:01 -0700974 if (parseToken(Token::r_paren, "expected ')'"))
975 return nullptr;
976
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700977 return expr;
978}
979
980/// Parse the negation expression.
981///
982/// affine-expr ::= `-` affine-expr
Uday Bondhugulabc535622018-08-07 14:24:38 -0700983AffineExpr *AffineParser::parseNegateExpression(AffineExpr *lhs) {
Chris Lattnerf7702a62018-07-23 17:30:01 -0700984 if (parseToken(Token::minus, "expected '-'"))
985 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700986
Chris Lattner2e595eb2018-07-10 10:08:27 -0700987 AffineExpr *operand = parseAffineOperandExpr(lhs);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700988 // Since negation has the highest precedence of all ops (including high
989 // precedence ops) but lower than parentheses, we are only going to use
990 // parseAffineOperandExpr instead of parseAffineExpr here.
991 if (!operand)
992 // Extra error message although parseAffineOperandExpr would have
993 // complained. Leads to a better diagnostic.
994 return (emitError("missing operand of negation"), nullptr);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700995 auto *minusOne = builder.getConstantExpr(-1);
996 return builder.getMulExpr(minusOne, operand);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -0700997}
998
999/// Parse a bare id that may appear in an affine expression.
1000///
1001/// affine-expr ::= bare-id
Uday Bondhugulabc535622018-08-07 14:24:38 -07001002AffineExpr *AffineParser::parseBareIdExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -07001003 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001004 return (emitError("expected bare identifier"), nullptr);
1005
Chris Lattner48af7d12018-07-09 19:05:38 -07001006 StringRef sRef = getTokenSpelling();
Chris Lattner413db6a2018-07-25 12:55:50 -07001007 for (auto entry : dimsAndSymbols) {
Chris Lattnera8e47672018-07-25 14:08:16 -07001008 if (entry.first == sRef) {
1009 consumeToken(Token::bare_identifier);
1010 return entry.second;
1011 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001012 }
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001013
1014 return (emitError("use of undeclared identifier"), nullptr);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001015}
1016
1017/// Parse a positive integral constant appearing in an affine expression.
1018///
1019/// affine-expr ::= integer-literal
Uday Bondhugulabc535622018-08-07 14:24:38 -07001020AffineExpr *AffineParser::parseIntegerExpr() {
Chris Lattner48af7d12018-07-09 19:05:38 -07001021 auto val = getToken().getUInt64IntegerValue();
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07001022 if (!val.hasValue() || (int64_t)val.getValue() < 0)
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001023 return (emitError("constant too large for affineint"), nullptr);
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07001024
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001025 consumeToken(Token::integer);
Chris Lattner1ac20cb2018-07-10 10:59:53 -07001026 return builder.getConstantExpr((int64_t)val.getValue());
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001027}
1028
1029/// Parses an expression that can be a valid operand of an affine expression.
Uday Bondhugula76345202018-07-09 13:47:52 -07001030/// lhs: if non-null, lhs is an affine expression that is the lhs of a binary
1031/// operator, the rhs of which is being parsed. This is used to determine
1032/// whether an error should be emitted for a missing right operand.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001033// Eg: for an expression without parentheses (like i + j + k + l), each
1034// of the four identifiers is an operand. For i + j*k + l, j*k is not an
1035// operand expression, it's an op expression and will be parsed via
1036// parseAffineHighPrecOpExpression(). However, for i + (j*k) + -l, (j*k) and -l
1037// are valid operands that will be parsed by this function.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001038AffineExpr *AffineParser::parseAffineOperandExpr(AffineExpr *lhs) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001039 switch (getToken().getKind()) {
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001040 case Token::bare_identifier:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001041 return parseBareIdExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001042 case Token::integer:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001043 return parseIntegerExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001044 case Token::l_paren:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001045 return parseParentheticalExpr();
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001046 case Token::minus:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001047 return parseNegateExpression(lhs);
Uday Bondhugula76345202018-07-09 13:47:52 -07001048 case Token::kw_ceildiv:
1049 case Token::kw_floordiv:
1050 case Token::kw_mod:
1051 case Token::plus:
1052 case Token::star:
1053 if (lhs)
1054 emitError("missing right operand of binary operator");
1055 else
1056 emitError("missing left operand of binary operator");
1057 return nullptr;
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001058 default:
1059 if (lhs)
Uday Bondhugula76345202018-07-09 13:47:52 -07001060 emitError("missing right operand of binary operator");
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001061 else
1062 emitError("expected affine expression");
1063 return nullptr;
1064 }
1065}
1066
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001067/// Parse affine expressions that are bare-id's, integer constants,
1068/// parenthetical affine expressions, and affine op expressions that are a
1069/// composition of those.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001070///
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001071/// All binary op's associate from left to right.
1072///
1073/// {add, sub} have lower precedence than {mul, div, and mod}.
1074///
Uday Bondhugula76345202018-07-09 13:47:52 -07001075/// Add, sub'are themselves at the same precedence level. Mul, floordiv,
1076/// ceildiv, and mod are at the same higher precedence level. Negation has
1077/// higher precedence than any binary op.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001078///
1079/// llhs: the affine expression appearing on the left of the one being parsed.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001080/// This function will return ((llhs llhsOp lhs) op rhs) if llhs is non null,
1081/// and lhs op rhs otherwise; if there is no rhs, llhs llhsOp lhs is returned if
1082/// llhs is non-null; otherwise lhs is returned. This is to deal with left
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001083/// associativity.
1084///
1085/// Eg: when the expression is e1 + e2*e3 + e4, with e1 as llhs, this function
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001086/// will return the affine expr equivalent of (e1 + (e2*e3)) + e4, where (e2*e3)
1087/// will be parsed using parseAffineHighPrecOpExpr().
Uday Bondhugulabc535622018-08-07 14:24:38 -07001088AffineExpr *AffineParser::parseAffineLowPrecOpExpr(AffineExpr *llhs,
1089 AffineLowPrecOp llhsOp) {
Uday Bondhugula76345202018-07-09 13:47:52 -07001090 AffineExpr *lhs;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001091 if (!(lhs = parseAffineOperandExpr(llhs)))
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001092 return nullptr;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001093
1094 // Found an LHS. Deal with the ops.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001095 if (AffineLowPrecOp lOp = consumeIfLowPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001096 if (llhs) {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001097 AffineExpr *sum = getBinaryAffineOpExpr(llhsOp, llhs, lhs);
Chris Lattner2e595eb2018-07-10 10:08:27 -07001098 return parseAffineLowPrecOpExpr(sum, lOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001099 }
1100 // No LLHS, get RHS and form the expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001101 return parseAffineLowPrecOpExpr(lhs, lOp);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001102 }
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001103 auto opLoc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07001104 if (AffineHighPrecOp hOp = consumeIfHighPrecOp()) {
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001105 // We have a higher precedence op here. Get the rhs operand for the llhs
1106 // through parseAffineHighPrecOpExpr.
Uday Bondhugula851b8fd2018-07-20 14:57:21 -07001107 AffineExpr *highRes = parseAffineHighPrecOpExpr(lhs, hOp, opLoc);
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001108 if (!highRes)
1109 return nullptr;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001110
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001111 // If llhs is null, the product forms the first operand of the yet to be
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001112 // found expression. If non-null, the op to associate with llhs is llhsOp.
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001113 AffineExpr *expr =
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001114 llhs ? getBinaryAffineOpExpr(llhsOp, llhs, highRes) : highRes;
Chris Lattner2e595eb2018-07-10 10:08:27 -07001115
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001116 // Recurse for subsequent low prec op's after the affine high prec op
1117 // expression.
Chris Lattner2e595eb2018-07-10 10:08:27 -07001118 if (AffineLowPrecOp nextOp = consumeIfLowPrecOp())
1119 return parseAffineLowPrecOpExpr(expr, nextOp);
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001120 return expr;
1121 }
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001122 // Last operand in the expression list.
1123 if (llhs)
1124 return getBinaryAffineOpExpr(llhsOp, llhs, lhs);
1125 // No llhs, 'lhs' itself is the expression.
1126 return lhs;
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001127}
1128
1129/// Parse an affine expression.
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001130/// affine-expr ::= `(` affine-expr `)`
1131/// | `-` affine-expr
1132/// | affine-expr `+` affine-expr
1133/// | affine-expr `-` affine-expr
1134/// | affine-expr `*` affine-expr
1135/// | affine-expr `floordiv` affine-expr
1136/// | affine-expr `ceildiv` affine-expr
1137/// | affine-expr `mod` affine-expr
1138/// | bare-id
1139/// | integer-literal
1140///
1141/// Additional conditions are checked depending on the production. For eg., one
1142/// of the operands for `*` has to be either constant/symbolic; the second
1143/// operand for floordiv, ceildiv, and mod has to be a positive integer.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001144AffineExpr *AffineParser::parseAffineExpr() {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001145 return parseAffineLowPrecOpExpr(nullptr, AffineLowPrecOp::LNoOp);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001146}
1147
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001148/// Parse a dim or symbol from the lists appearing before the actual expressions
Chris Lattner2e595eb2018-07-10 10:08:27 -07001149/// of the affine map. Update our state to store the dimensional/symbolic
Chris Lattner413db6a2018-07-25 12:55:50 -07001150/// identifier.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001151ParseResult AffineParser::parseIdentifierDefinition(AffineExpr *idExpr) {
Chris Lattner48af7d12018-07-09 19:05:38 -07001152 if (getToken().isNot(Token::bare_identifier))
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001153 return emitError("expected bare identifier");
Chris Lattner413db6a2018-07-25 12:55:50 -07001154
1155 auto name = getTokenSpelling();
1156 for (auto entry : dimsAndSymbols) {
1157 if (entry.first == name)
1158 return emitError("redefinition of identifier '" + Twine(name) + "'");
1159 }
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001160 consumeToken(Token::bare_identifier);
Chris Lattner413db6a2018-07-25 12:55:50 -07001161
1162 dimsAndSymbols.push_back({name, idExpr});
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001163 return ParseSuccess;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001164}
1165
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001166/// Parse the list of symbolic identifiers to an affine map.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001167ParseResult AffineParser::parseSymbolIdList(unsigned &numSymbols) {
Chris Lattner413db6a2018-07-25 12:55:50 -07001168 consumeToken(Token::l_square);
1169 auto parseElt = [&]() -> ParseResult {
1170 auto *symbol = AffineSymbolExpr::get(numSymbols++, getContext());
1171 return parseIdentifierDefinition(symbol);
1172 };
Chris Lattner85ee1512018-07-25 11:15:20 -07001173 return parseCommaSeparatedListUntil(Token::r_square, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001174}
1175
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001176/// Parse the list of dimensional identifiers to an affine map.
Uday Bondhugulabc535622018-08-07 14:24:38 -07001177ParseResult AffineParser::parseDimIdList(unsigned &numDims) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07001178 if (parseToken(Token::l_paren,
1179 "expected '(' at start of dimensional identifiers list"))
1180 return ParseFailure;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001181
Chris Lattner413db6a2018-07-25 12:55:50 -07001182 auto parseElt = [&]() -> ParseResult {
1183 auto *dimension = AffineDimExpr::get(numDims++, getContext());
1184 return parseIdentifierDefinition(dimension);
1185 };
Chris Lattner40746442018-07-21 14:32:09 -07001186 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001187}
1188
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001189/// Parse an affine map definition.
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001190///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001191/// affine-map-inline ::= dim-and-symbol-id-lists `->` multi-dim-affine-expr
1192/// (`size` `(` dim-size (`,` dim-size)* `)`)?
1193/// dim-size ::= affine-expr | `min` `(` affine-expr ( `,` affine-expr)+ `)`
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001194///
Uday Bondhugula3934d4d2018-07-09 09:00:25 -07001195/// multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Uday Bondhugulabc535622018-08-07 14:24:38 -07001196AffineMap *AffineParser::parseAffineMapInline() {
Chris Lattner413db6a2018-07-25 12:55:50 -07001197 unsigned numDims = 0, numSymbols = 0;
1198
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001199 // List of dimensional identifiers.
Chris Lattner413db6a2018-07-25 12:55:50 -07001200 if (parseDimIdList(numDims))
Chris Lattner7121b802018-07-04 20:45:39 -07001201 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001202
1203 // Symbols are optional.
Chris Lattner85ee1512018-07-25 11:15:20 -07001204 if (getToken().is(Token::l_square)) {
Chris Lattner413db6a2018-07-25 12:55:50 -07001205 if (parseSymbolIdList(numSymbols))
Chris Lattner7121b802018-07-04 20:45:39 -07001206 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001207 }
Chris Lattnerf7702a62018-07-23 17:30:01 -07001208
1209 if (parseToken(Token::arrow, "expected '->' or '['") ||
1210 parseToken(Token::l_paren, "expected '(' at start of affine map range"))
Chris Lattner7121b802018-07-04 20:45:39 -07001211 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001212
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001213 SmallVector<AffineExpr *, 4> exprs;
1214 auto parseElt = [&]() -> ParseResult {
Chris Lattner2e595eb2018-07-10 10:08:27 -07001215 auto *elt = parseAffineExpr();
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001216 ParseResult res = elt ? ParseSuccess : ParseFailure;
1217 exprs.push_back(elt);
1218 return res;
1219 };
1220
1221 // Parse a multi-dimensional affine expression (a comma-separated list of 1-d
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001222 // affine expressions); the list cannot be empty.
1223 // Grammar: multi-dim-affine-expr ::= `(` affine-expr (`,` affine-expr)* `)
Chris Lattner40746442018-07-21 14:32:09 -07001224 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt, false))
Chris Lattner7121b802018-07-04 20:45:39 -07001225 return nullptr;
Uday Bondhugulafaf37dd2018-06-29 18:09:29 -07001226
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001227 // Parse optional range sizes.
Uday Bondhugula1e500b42018-07-12 18:04:04 -07001228 // range-sizes ::= (`size` `(` dim-size (`,` dim-size)* `)`)?
1229 // dim-size ::= affine-expr | `min` `(` affine-expr (`,` affine-expr)+ `)`
1230 // TODO(bondhugula): support for min of several affine expressions.
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001231 // TODO: check if sizes are non-negative whenever they are constant.
1232 SmallVector<AffineExpr *, 4> rangeSizes;
1233 if (consumeIf(Token::kw_size)) {
1234 // Location of the l_paren token (if it exists) for error reporting later.
1235 auto loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001236 if (parseToken(Token::l_paren, "expected '(' at start of affine map range"))
1237 return nullptr;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001238
1239 auto parseRangeSize = [&]() -> ParseResult {
Chris Lattner413db6a2018-07-25 12:55:50 -07001240 auto loc = getToken().getLoc();
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001241 auto *elt = parseAffineExpr();
Chris Lattner413db6a2018-07-25 12:55:50 -07001242 if (!elt)
1243 return ParseFailure;
1244
1245 if (!elt->isSymbolicOrConstant())
1246 return emitError(loc,
1247 "size expressions cannot refer to dimension values");
1248
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001249 rangeSizes.push_back(elt);
Chris Lattner413db6a2018-07-25 12:55:50 -07001250 return ParseSuccess;
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001251 };
1252
Chris Lattner40746442018-07-21 14:32:09 -07001253 if (parseCommaSeparatedListUntil(Token::r_paren, parseRangeSize, false))
Uday Bondhugula0115dbb2018-07-11 21:31:07 -07001254 return nullptr;
1255 if (exprs.size() > rangeSizes.size())
1256 return (emitError(loc, "fewer range sizes than range expressions"),
1257 nullptr);
1258 if (exprs.size() < rangeSizes.size())
1259 return (emitError(loc, "more range sizes than range expressions"),
1260 nullptr);
1261 }
1262
Uday Bondhugula015cbb12018-07-03 20:16:08 -07001263 // Parsed a valid affine map.
Chris Lattner413db6a2018-07-25 12:55:50 -07001264 return builder.getAffineMap(numDims, numSymbols, exprs, rangeSizes);
MLIR Teamf85a6262018-06-27 11:03:08 -07001265}
1266
Chris Lattner2e595eb2018-07-10 10:08:27 -07001267AffineMap *Parser::parseAffineMapInline() {
Uday Bondhugulabc535622018-08-07 14:24:38 -07001268 return AffineParser(state).parseAffineMapInline();
Chris Lattner2e595eb2018-07-10 10:08:27 -07001269}
1270
MLIR Team718c82f2018-07-16 09:45:22 -07001271AffineMap *Parser::parseAffineMapReference() {
1272 if (getToken().is(Token::hash_identifier)) {
1273 // Parse affine map identifier and verify that it exists.
1274 StringRef affineMapId = getTokenSpelling().drop_front();
1275 if (getState().affineMapDefinitions.count(affineMapId) == 0)
1276 return (emitError("undefined affine map id '" + affineMapId + "'"),
1277 nullptr);
1278 consumeToken(Token::hash_identifier);
1279 return getState().affineMapDefinitions[affineMapId];
1280 }
1281 // Try to parse inline affine map.
1282 return parseAffineMapInline();
1283}
1284
MLIR Teamf85a6262018-06-27 11:03:08 -07001285//===----------------------------------------------------------------------===//
Chris Lattner7f9cc272018-07-19 08:35:28 -07001286// FunctionParser
Chris Lattner4c95a502018-06-23 16:03:42 -07001287//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001288
Chris Lattner7f9cc272018-07-19 08:35:28 -07001289namespace {
1290/// This class contains parser state that is common across CFG and ML functions,
1291/// notably for dealing with operations and SSA values.
1292class FunctionParser : public Parser {
1293public:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001294 enum class Kind { CFGFunc, MLFunc };
1295
1296 Kind getKind() const { return kind; }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001297
Chris Lattner6119d382018-07-20 18:41:34 -07001298 /// After the function is finished parsing, this function checks to see if
1299 /// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001300 ParseResult finalizeFunction(Function *func, SMLoc loc);
Chris Lattner6119d382018-07-20 18:41:34 -07001301
1302 /// This represents a use of an SSA value in the program. The first two
1303 /// entries in the tuple are the name and result number of a reference. The
1304 /// third is the location of the reference, which is used in case this ends up
1305 /// being a use of an undefined value.
1306 struct SSAUseInfo {
1307 StringRef name; // Value name, e.g. %42 or %abc
1308 unsigned number; // Number, specified with #12
1309 SMLoc loc; // Location of first definition or use.
1310 };
Chris Lattner7f9cc272018-07-19 08:35:28 -07001311
1312 /// Given a reference to an SSA value and its type, return a reference. This
1313 /// returns null on failure.
1314 SSAValue *resolveSSAUse(SSAUseInfo useInfo, Type *type);
1315
1316 /// Register a definition of a value with the symbol table.
1317 ParseResult addDefinition(SSAUseInfo useInfo, SSAValue *value);
1318
1319 // SSA parsing productions.
1320 ParseResult parseSSAUse(SSAUseInfo &result);
Chris Lattner40746442018-07-21 14:32:09 -07001321 ParseResult parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results);
James Molloy61a656c2018-07-22 15:45:24 -07001322
1323 template <typename ResultType>
1324 ResultType parseSSADefOrUseAndType(
1325 const std::function<ResultType(SSAUseInfo, Type *)> &action);
1326
1327 SSAValue *parseSSAUseAndType() {
1328 return parseSSADefOrUseAndType<SSAValue *>(
1329 [&](SSAUseInfo useInfo, Type *type) -> SSAValue * {
1330 return resolveSSAUse(useInfo, type);
1331 });
1332 }
Chris Lattner40746442018-07-21 14:32:09 -07001333
1334 template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001335 ParseResult
Chris Lattner2c402672018-07-23 11:56:17 -07001336 parseOptionalSSAUseAndTypeList(SmallVectorImpl<ValueTy *> &results,
1337 bool isParenthesized);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001338
1339 // Operations
1340 ParseResult parseOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner85ee1512018-07-25 11:15:20 -07001341 Operation *parseVerboseOperation(const CreateOperationFunction &createOpFunc);
1342 Operation *parseCustomOperation(const CreateOperationFunction &createOpFunc);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001343
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001344protected:
1345 FunctionParser(ParserState &state, Kind kind) : Parser(state), kind(kind) {}
1346
Chris Lattner7f9cc272018-07-19 08:35:28 -07001347private:
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001348 /// Kind indicates if this is CFG or ML function parser.
1349 Kind kind;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001350 /// This keeps track of all of the SSA values we are tracking, indexed by
Chris Lattner6119d382018-07-20 18:41:34 -07001351 /// their name. This has one entry per result number.
1352 llvm::StringMap<SmallVector<std::pair<SSAValue *, SMLoc>, 1>> values;
1353
1354 /// These are all of the placeholders we've made along with the location of
1355 /// their first reference, to allow checking for use of undefined values.
1356 DenseMap<SSAValue *, SMLoc> forwardReferencePlaceholders;
1357
1358 SSAValue *createForwardReferencePlaceholder(SMLoc loc, Type *type);
1359
1360 /// Return true if this is a forward reference.
1361 bool isForwardReferencePlaceholder(SSAValue *value) {
1362 return forwardReferencePlaceholders.count(value);
1363 }
Chris Lattner7f9cc272018-07-19 08:35:28 -07001364};
1365} // end anonymous namespace
1366
Chris Lattner6119d382018-07-20 18:41:34 -07001367/// Create and remember a new placeholder for a forward reference.
1368SSAValue *FunctionParser::createForwardReferencePlaceholder(SMLoc loc,
1369 Type *type) {
1370 // Forward references are always created as instructions, even in ML
1371 // functions, because we just need something with a def/use chain.
1372 //
1373 // We create these placeholders as having an empty name, which we know cannot
1374 // be created through normal user input, allowing us to distinguish them.
1375 auto name = Identifier::get("placeholder", getContext());
Chris Lattnerfc647d52018-08-27 21:05:16 -07001376 auto *inst = OperationInst::create(getEncodedSourceLocation(loc), name,
1377 /*operands=*/{}, type,
1378 /*attributes=*/{}, getContext());
Chris Lattner6119d382018-07-20 18:41:34 -07001379 forwardReferencePlaceholders[inst->getResult(0)] = loc;
1380 return inst->getResult(0);
1381}
1382
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001383/// Given an unbound reference to an SSA value and its type, return the value
Chris Lattner7f9cc272018-07-19 08:35:28 -07001384/// it specifies. This returns null on failure.
1385SSAValue *FunctionParser::resolveSSAUse(SSAUseInfo useInfo, Type *type) {
Chris Lattner6119d382018-07-20 18:41:34 -07001386 auto &entries = values[useInfo.name];
1387
Chris Lattner7f9cc272018-07-19 08:35:28 -07001388 // If we have already seen a value of this name, return it.
Chris Lattner6119d382018-07-20 18:41:34 -07001389 if (useInfo.number < entries.size() && entries[useInfo.number].first) {
1390 auto *result = entries[useInfo.number].first;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001391 // Check that the type matches the other uses.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001392 if (result->getType() == type)
1393 return result;
1394
Chris Lattner6119d382018-07-20 18:41:34 -07001395 emitError(useInfo.loc, "use of value '" + useInfo.name.str() +
1396 "' expects different type than prior uses");
1397 emitError(entries[useInfo.number].second, "prior use here");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001398 return nullptr;
1399 }
1400
Chris Lattner6119d382018-07-20 18:41:34 -07001401 // Make sure we have enough slots for this.
1402 if (entries.size() <= useInfo.number)
1403 entries.resize(useInfo.number + 1);
1404
1405 // If the value has already been defined and this is an overly large result
1406 // number, diagnose that.
1407 if (entries[0].first && !isForwardReferencePlaceholder(entries[0].first))
1408 return (emitError(useInfo.loc, "reference to invalid result number"),
1409 nullptr);
1410
Tatiana Shpeismand880b352018-07-31 23:14:16 -07001411 // Otherwise, this is a forward reference. If we are in ML function return
1412 // an error. In CFG function, create a placeholder and remember
1413 // that we did so.
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001414 if (getKind() == Kind::MLFunc)
1415 return (
1416 emitError(useInfo.loc, "use of undefined SSA value " + useInfo.name),
1417 nullptr);
1418
Chris Lattner6119d382018-07-20 18:41:34 -07001419 auto *result = createForwardReferencePlaceholder(useInfo.loc, type);
1420 entries[useInfo.number].first = result;
1421 entries[useInfo.number].second = useInfo.loc;
1422 return result;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001423}
1424
1425/// Register a definition of a value with the symbol table.
1426ParseResult FunctionParser::addDefinition(SSAUseInfo useInfo, SSAValue *value) {
Chris Lattner6119d382018-07-20 18:41:34 -07001427 auto &entries = values[useInfo.name];
Chris Lattner7f9cc272018-07-19 08:35:28 -07001428
Chris Lattner6119d382018-07-20 18:41:34 -07001429 // Make sure there is a slot for this value.
1430 if (entries.size() <= useInfo.number)
1431 entries.resize(useInfo.number + 1);
Chris Lattner7f9cc272018-07-19 08:35:28 -07001432
Chris Lattner6119d382018-07-20 18:41:34 -07001433 // If we already have an entry for this, check to see if it was a definition
1434 // or a forward reference.
1435 if (auto *existing = entries[useInfo.number].first) {
1436 if (!isForwardReferencePlaceholder(existing)) {
1437 emitError(useInfo.loc,
1438 "redefinition of SSA value '" + useInfo.name + "'");
1439 return emitError(entries[useInfo.number].second,
1440 "previously defined here");
1441 }
1442
1443 // If it was a forward reference, update everything that used it to use the
1444 // actual definition instead, delete the forward ref, and remove it from our
1445 // set of forward references we track.
1446 existing->replaceAllUsesWith(value);
1447 existing->getDefiningInst()->destroy();
1448 forwardReferencePlaceholders.erase(existing);
1449 }
1450
1451 entries[useInfo.number].first = value;
1452 entries[useInfo.number].second = useInfo.loc;
1453 return ParseSuccess;
1454}
1455
1456/// After the function is finished parsing, this function checks to see if
1457/// there are any remaining issues.
Chris Lattner40746442018-07-21 14:32:09 -07001458ParseResult FunctionParser::finalizeFunction(Function *func, SMLoc loc) {
Chris Lattner6119d382018-07-20 18:41:34 -07001459 // Check for any forward references that are left. If we find any, error out.
1460 if (!forwardReferencePlaceholders.empty()) {
1461 SmallVector<std::pair<const char *, SSAValue *>, 4> errors;
1462 // Iteration over the map isn't determinstic, so sort by source location.
1463 for (auto entry : forwardReferencePlaceholders)
1464 errors.push_back({entry.second.getPointer(), entry.first});
1465 llvm::array_pod_sort(errors.begin(), errors.end());
1466
1467 for (auto entry : errors)
1468 emitError(SMLoc::getFromPointer(entry.first),
1469 "use of undeclared SSA value name");
1470 return ParseFailure;
1471 }
1472
1473 return ParseSuccess;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001474}
1475
Chris Lattner78276e32018-07-07 15:48:26 -07001476/// Parse a SSA operand for an instruction or statement.
1477///
James Molloy61a656c2018-07-22 15:45:24 -07001478/// ssa-use ::= ssa-id
Chris Lattner78276e32018-07-07 15:48:26 -07001479///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001480ParseResult FunctionParser::parseSSAUse(SSAUseInfo &result) {
Chris Lattner6119d382018-07-20 18:41:34 -07001481 result.name = getTokenSpelling();
1482 result.number = 0;
1483 result.loc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001484 if (parseToken(Token::percent_identifier, "expected SSA operand"))
1485 return ParseFailure;
Chris Lattner6119d382018-07-20 18:41:34 -07001486
1487 // If we have an affine map ID, it is a result number.
1488 if (getToken().is(Token::hash_identifier)) {
1489 if (auto value = getToken().getHashIdentifierNumber())
1490 result.number = value.getValue();
1491 else
1492 return emitError("invalid SSA value result number");
1493 consumeToken(Token::hash_identifier);
1494 }
1495
Chris Lattner7f9cc272018-07-19 08:35:28 -07001496 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001497}
1498
1499/// Parse a (possibly empty) list of SSA operands.
1500///
1501/// ssa-use-list ::= ssa-use (`,` ssa-use)*
1502/// ssa-use-list-opt ::= ssa-use-list?
1503///
Chris Lattner7f9cc272018-07-19 08:35:28 -07001504ParseResult
Chris Lattner40746442018-07-21 14:32:09 -07001505FunctionParser::parseOptionalSSAUseList(SmallVectorImpl<SSAUseInfo> &results) {
Chris Lattner85ee1512018-07-25 11:15:20 -07001506 if (getToken().isNot(Token::percent_identifier))
Chris Lattner40746442018-07-21 14:32:09 -07001507 return ParseSuccess;
1508 return parseCommaSeparatedList([&]() -> ParseResult {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001509 SSAUseInfo result;
1510 if (parseSSAUse(result))
1511 return ParseFailure;
1512 results.push_back(result);
1513 return ParseSuccess;
1514 });
Chris Lattner78276e32018-07-07 15:48:26 -07001515}
1516
1517/// Parse an SSA use with an associated type.
1518///
1519/// ssa-use-and-type ::= ssa-use `:` type
James Molloy61a656c2018-07-22 15:45:24 -07001520template <typename ResultType>
1521ResultType FunctionParser::parseSSADefOrUseAndType(
1522 const std::function<ResultType(SSAUseInfo, Type *)> &action) {
Chris Lattner78276e32018-07-07 15:48:26 -07001523
Chris Lattnerf7702a62018-07-23 17:30:01 -07001524 SSAUseInfo useInfo;
1525 if (parseSSAUse(useInfo) ||
1526 parseToken(Token::colon, "expected ':' and type for SSA operand"))
1527 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001528
Chris Lattner7f9cc272018-07-19 08:35:28 -07001529 auto *type = parseType();
1530 if (!type)
1531 return nullptr;
Chris Lattner78276e32018-07-07 15:48:26 -07001532
James Molloy61a656c2018-07-22 15:45:24 -07001533 return action(useInfo, type);
Chris Lattner78276e32018-07-07 15:48:26 -07001534}
1535
Chris Lattner2c402672018-07-23 11:56:17 -07001536/// Parse a (possibly empty) list of SSA operands, followed by a colon, then
1537/// followed by a type list. If hasParens is true, then the operands are
1538/// surrounded by parens.
Chris Lattner78276e32018-07-07 15:48:26 -07001539///
Chris Lattner2c402672018-07-23 11:56:17 -07001540/// ssa-use-and-type-list[parens]
1541/// ::= `(` ssa-use-list `)` ':' type-list-no-parens
1542///
1543/// ssa-use-and-type-list[!parens]
1544/// ::= ssa-use-list ':' type-list-no-parens
Chris Lattner78276e32018-07-07 15:48:26 -07001545///
Chris Lattner40746442018-07-21 14:32:09 -07001546template <typename ValueTy>
Chris Lattner7f9cc272018-07-19 08:35:28 -07001547ParseResult FunctionParser::parseOptionalSSAUseAndTypeList(
Chris Lattner2c402672018-07-23 11:56:17 -07001548 SmallVectorImpl<ValueTy *> &results, bool isParenthesized) {
1549
1550 // If we are in the parenthesized form and no paren exists, then we succeed
1551 // with an empty list.
1552 if (isParenthesized && !consumeIf(Token::l_paren))
Chris Lattner40746442018-07-21 14:32:09 -07001553 return ParseSuccess;
1554
Chris Lattner2c402672018-07-23 11:56:17 -07001555 SmallVector<SSAUseInfo, 4> valueIDs;
1556 if (parseOptionalSSAUseList(valueIDs))
Chris Lattner7f9cc272018-07-19 08:35:28 -07001557 return ParseFailure;
Chris Lattner2c402672018-07-23 11:56:17 -07001558
1559 if (isParenthesized && !consumeIf(Token::r_paren))
1560 return emitError("expected ')' in operand list");
1561
1562 // If there were no operands, then there is no colon or type lists.
1563 if (valueIDs.empty())
1564 return ParseSuccess;
1565
Chris Lattner2c402672018-07-23 11:56:17 -07001566 SmallVector<Type *, 4> types;
Chris Lattnerf7702a62018-07-23 17:30:01 -07001567 if (parseToken(Token::colon, "expected ':' in operand list") ||
1568 parseTypeListNoParens(types))
Chris Lattner2c402672018-07-23 11:56:17 -07001569 return ParseFailure;
1570
1571 if (valueIDs.size() != types.size())
1572 return emitError("expected " + Twine(valueIDs.size()) +
1573 " types to match operand list");
1574
1575 results.reserve(valueIDs.size());
1576 for (unsigned i = 0, e = valueIDs.size(); i != e; ++i) {
1577 if (auto *value = resolveSSAUse(valueIDs[i], types[i]))
1578 results.push_back(cast<ValueTy>(value));
1579 else
1580 return ParseFailure;
1581 }
1582
1583 return ParseSuccess;
Chris Lattner78276e32018-07-07 15:48:26 -07001584}
1585
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001586/// Parse the CFG or MLFunc operation.
1587///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001588/// operation ::=
1589/// (ssa-id `=`)? string '(' ssa-use-list? ')' attribute-dict?
1590/// `:` function-type
1591///
1592ParseResult
Chris Lattner7f9cc272018-07-19 08:35:28 -07001593FunctionParser::parseOperation(const CreateOperationFunction &createOpFunc) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001594 auto loc = getToken().getLoc();
1595
1596 StringRef resultID;
1597 if (getToken().is(Token::percent_identifier)) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001598 resultID = getTokenSpelling();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001599 consumeToken(Token::percent_identifier);
Chris Lattnerf7702a62018-07-23 17:30:01 -07001600 if (parseToken(Token::equal, "expected '=' after SSA name"))
1601 return ParseFailure;
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001602 }
1603
Chris Lattner85ee1512018-07-25 11:15:20 -07001604 Operation *op;
1605 if (getToken().is(Token::bare_identifier) || getToken().isKeyword())
1606 op = parseCustomOperation(createOpFunc);
1607 else if (getToken().is(Token::string))
1608 op = parseVerboseOperation(createOpFunc);
1609 else
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001610 return emitError("expected operation name in quotes");
1611
Chris Lattner85ee1512018-07-25 11:15:20 -07001612 // If parsing of the basic operation failed, then this whole thing fails.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001613 if (!op)
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001614 return ParseFailure;
1615
1616 // We just parsed an operation. If it is a recognized one, verify that it
1617 // is structurally as we expect. If not, produce an error with a reasonable
1618 // source location.
Chris Lattner95865062018-08-01 10:18:59 -07001619 if (auto *opInfo = op->getAbstractOperation()) {
Chris Lattner7f9cc272018-07-19 08:35:28 -07001620 if (auto error = opInfo->verifyInvariants(op))
Chris Lattner9361fb32018-07-24 08:34:58 -07001621 return emitError(loc, Twine("'") + op->getName().str() + "' op " + error);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001622 }
1623
Chris Lattner7f9cc272018-07-19 08:35:28 -07001624 // If the instruction had a name, register it.
1625 if (!resultID.empty()) {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001626 if (op->getNumResults() == 0)
1627 return emitError(loc, "cannot name an operation with no results");
Chris Lattner7f9cc272018-07-19 08:35:28 -07001628
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001629 for (unsigned i = 0, e = op->getNumResults(); i != e; ++i)
Chris Lattner2b97d502018-08-06 14:19:46 -07001630 if (addDefinition({resultID, i, loc}, op->getResult(i)))
1631 return ParseFailure;
Chris Lattner7f9cc272018-07-19 08:35:28 -07001632 }
1633
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07001634 return ParseSuccess;
1635}
Chris Lattnere79379a2018-06-22 10:39:19 -07001636
Chris Lattner85ee1512018-07-25 11:15:20 -07001637Operation *FunctionParser::parseVerboseOperation(
1638 const CreateOperationFunction &createOpFunc) {
Chris Lattner1628fa02018-08-23 14:32:25 -07001639
1640 // Get location information for the operation.
1641 auto *srcLocation = getEncodedSourceLocation(getToken().getLoc());
1642
Chris Lattner85ee1512018-07-25 11:15:20 -07001643 auto name = getToken().getStringValue();
1644 if (name.empty())
1645 return (emitError("empty operation name is invalid"), nullptr);
1646
1647 consumeToken(Token::string);
1648
Chris Lattner1628fa02018-08-23 14:32:25 -07001649 OperationState result(builder.getContext(), srcLocation, name);
Chris Lattner992a1272018-08-07 12:02:37 -07001650
Chris Lattner85ee1512018-07-25 11:15:20 -07001651 // Parse the operand list.
1652 SmallVector<SSAUseInfo, 8> operandInfos;
1653
1654 if (parseToken(Token::l_paren, "expected '(' to start operand list") ||
1655 parseOptionalSSAUseList(operandInfos) ||
1656 parseToken(Token::r_paren, "expected ')' to end operand list")) {
1657 return nullptr;
1658 }
1659
Chris Lattner85ee1512018-07-25 11:15:20 -07001660 if (getToken().is(Token::l_brace)) {
Chris Lattner992a1272018-08-07 12:02:37 -07001661 if (parseAttributeDict(result.attributes))
Chris Lattner85ee1512018-07-25 11:15:20 -07001662 return nullptr;
1663 }
1664
1665 if (parseToken(Token::colon, "expected ':' followed by instruction type"))
1666 return nullptr;
1667
1668 auto typeLoc = getToken().getLoc();
1669 auto type = parseType();
1670 if (!type)
1671 return nullptr;
1672 auto fnType = dyn_cast<FunctionType>(type);
1673 if (!fnType)
1674 return (emitError(typeLoc, "expected function type"), nullptr);
1675
Chris Lattner1eb77482018-08-22 19:25:49 -07001676 result.addTypes(fnType->getResults());
Chris Lattner992a1272018-08-07 12:02:37 -07001677
Chris Lattner85ee1512018-07-25 11:15:20 -07001678 // Check that we have the right number of types for the operands.
1679 auto operandTypes = fnType->getInputs();
1680 if (operandTypes.size() != operandInfos.size()) {
1681 auto plural = "s"[operandInfos.size() == 1];
1682 return (emitError(typeLoc, "expected " + llvm::utostr(operandInfos.size()) +
1683 " operand type" + plural + " but had " +
1684 llvm::utostr(operandTypes.size())),
1685 nullptr);
1686 }
1687
1688 // Resolve all of the operands.
Chris Lattner85ee1512018-07-25 11:15:20 -07001689 for (unsigned i = 0, e = operandInfos.size(); i != e; ++i) {
Chris Lattner992a1272018-08-07 12:02:37 -07001690 result.operands.push_back(resolveSSAUse(operandInfos[i], operandTypes[i]));
1691 if (!result.operands.back())
Chris Lattner85ee1512018-07-25 11:15:20 -07001692 return nullptr;
1693 }
1694
Chris Lattner992a1272018-08-07 12:02:37 -07001695 return createOpFunc(result);
Chris Lattner85ee1512018-07-25 11:15:20 -07001696}
1697
1698namespace {
1699class CustomOpAsmParser : public OpAsmParser {
1700public:
1701 CustomOpAsmParser(SMLoc nameLoc, StringRef opName, FunctionParser &parser)
1702 : nameLoc(nameLoc), opName(opName), parser(parser) {}
1703
Chris Lattner85ee1512018-07-25 11:15:20 -07001704 //===--------------------------------------------------------------------===//
1705 // High level parsing methods.
1706 //===--------------------------------------------------------------------===//
1707
Chris Lattner1aa46322018-08-21 17:55:22 -07001708 bool getCurrentLocation(llvm::SMLoc *loc) override {
1709 *loc = parser.getToken().getLoc();
1710 return false;
1711 }
Chris Lattner091a6b52018-08-23 14:58:27 -07001712 bool parseComma() override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001713 return parser.parseToken(Token::comma, "expected ','");
1714 }
1715
Chris Lattner091a6b52018-08-23 14:58:27 -07001716 bool parseColonType(Type *&result) override {
1717 return parser.parseToken(Token::colon, "expected ':'") ||
1718 !(result = parser.parseType());
Chris Lattner85ee1512018-07-25 11:15:20 -07001719 }
1720
Chris Lattner091a6b52018-08-23 14:58:27 -07001721 bool parseColonTypeList(SmallVectorImpl<Type *> &result) override {
1722 if (parser.parseToken(Token::colon, "expected ':'"))
Chris Lattner85ee1512018-07-25 11:15:20 -07001723 return true;
1724
1725 do {
1726 if (auto *type = parser.parseType())
1727 result.push_back(type);
1728 else
1729 return true;
1730
1731 } while (parser.consumeIf(Token::comma));
1732 return false;
1733 }
1734
Chris Lattner85cf26d2018-08-02 16:54:36 -07001735 /// Parse an arbitrary attribute and return it in result. This also adds the
1736 /// attribute to the specified attribute list with the specified name. this
1737 /// captures the location of the attribute in 'loc' if it is non-null.
1738 bool parseAttribute(Attribute *&result, const char *attrName,
Chris Lattner091a6b52018-08-23 14:58:27 -07001739 SmallVectorImpl<NamedAttribute> &attrs) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001740 result = parser.parseAttribute();
Chris Lattner85cf26d2018-08-02 16:54:36 -07001741 if (!result)
1742 return true;
1743
1744 attrs.push_back(
1745 NamedAttribute(parser.builder.getIdentifier(attrName), result));
1746 return false;
1747 }
1748
1749 /// If a named attribute list is present, parse is into result.
Chris Lattner091a6b52018-08-23 14:58:27 -07001750 bool
1751 parseOptionalAttributeDict(SmallVectorImpl<NamedAttribute> &result) override {
Chris Lattner85cf26d2018-08-02 16:54:36 -07001752 if (parser.getToken().isNot(Token::l_brace))
1753 return false;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001754 return parser.parseAttributeDict(result) == ParseFailure;
Chris Lattner85ee1512018-07-25 11:15:20 -07001755 }
1756
Chris Lattner1aa46322018-08-21 17:55:22 -07001757 /// Parse a function name like '@foo' and return the name in a form that can
1758 /// be passed to resolveFunctionName when a function type is available.
1759 virtual bool parseFunctionName(StringRef &result, llvm::SMLoc &loc) {
1760 loc = parser.getToken().getLoc();
1761
1762 if (parser.getToken().isNot(Token::at_identifier))
1763 return emitError(loc, "expected function name");
1764
1765 result = parser.getTokenSpelling();
1766 parser.consumeToken(Token::at_identifier);
1767 return false;
1768 }
1769
Chris Lattner85ee1512018-07-25 11:15:20 -07001770 bool parseOperand(OperandType &result) override {
1771 FunctionParser::SSAUseInfo useInfo;
1772 if (parser.parseSSAUse(useInfo))
1773 return true;
1774
1775 result = {useInfo.loc, useInfo.name, useInfo.number};
1776 return false;
1777 }
1778
1779 bool parseOperandList(SmallVectorImpl<OperandType> &result,
1780 int requiredOperandCount = -1,
Chris Lattner85cf26d2018-08-02 16:54:36 -07001781 Delimiter delimiter = Delimiter::None) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001782 auto startLoc = parser.getToken().getLoc();
1783
Chris Lattner85cf26d2018-08-02 16:54:36 -07001784 // Handle delimiters.
1785 switch (delimiter) {
1786 case Delimiter::None:
Chris Lattner85ee1512018-07-25 11:15:20 -07001787 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001788 case Delimiter::OptionalParen:
Chris Lattner3164ae62018-07-28 09:36:25 -07001789 if (parser.getToken().isNot(Token::l_paren))
1790 return false;
1791 LLVM_FALLTHROUGH;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001792 case Delimiter::Paren:
Chris Lattner85ee1512018-07-25 11:15:20 -07001793 if (parser.parseToken(Token::l_paren, "expected '(' in operand list"))
1794 return true;
1795 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001796 case Delimiter::OptionalSquare:
Chris Lattner3164ae62018-07-28 09:36:25 -07001797 if (parser.getToken().isNot(Token::l_square))
1798 return false;
1799 LLVM_FALLTHROUGH;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001800 case Delimiter::Square:
Chris Lattner85ee1512018-07-25 11:15:20 -07001801 if (parser.parseToken(Token::l_square, "expected '[' in operand list"))
1802 return true;
1803 break;
1804 }
1805
1806 // Check for zero operands.
1807 if (parser.getToken().is(Token::percent_identifier)) {
1808 do {
1809 OperandType operand;
1810 if (parseOperand(operand))
1811 return true;
1812 result.push_back(operand);
1813 } while (parser.consumeIf(Token::comma));
1814 }
1815
Chris Lattner85cf26d2018-08-02 16:54:36 -07001816 // Handle delimiters. If we reach here, the optional delimiters were
Chris Lattner3164ae62018-07-28 09:36:25 -07001817 // present, so we need to parse their closing one.
Chris Lattner85cf26d2018-08-02 16:54:36 -07001818 switch (delimiter) {
1819 case Delimiter::None:
Chris Lattner85ee1512018-07-25 11:15:20 -07001820 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001821 case Delimiter::OptionalParen:
1822 case Delimiter::Paren:
Chris Lattner85ee1512018-07-25 11:15:20 -07001823 if (parser.parseToken(Token::r_paren, "expected ')' in operand list"))
1824 return true;
1825 break;
Chris Lattner85cf26d2018-08-02 16:54:36 -07001826 case Delimiter::OptionalSquare:
1827 case Delimiter::Square:
Chris Lattner85ee1512018-07-25 11:15:20 -07001828 if (parser.parseToken(Token::r_square, "expected ']' in operand list"))
1829 return true;
1830 break;
1831 }
1832
1833 if (requiredOperandCount != -1 && result.size() != requiredOperandCount)
1834 emitError(startLoc,
1835 "expected " + Twine(requiredOperandCount) + " operands");
1836 return false;
1837 }
1838
Chris Lattner1aa46322018-08-21 17:55:22 -07001839 /// Resolve a parse function name and a type into a function reference.
1840 virtual bool resolveFunctionName(StringRef name, FunctionType *type,
1841 llvm::SMLoc loc, Function *&result) {
1842 result = parser.resolveFunctionReference(name, loc, type);
1843 return result == nullptr;
1844 }
1845
Chris Lattner85ee1512018-07-25 11:15:20 -07001846 //===--------------------------------------------------------------------===//
1847 // Methods for interacting with the parser
1848 //===--------------------------------------------------------------------===//
1849
1850 Builder &getBuilder() const override { return parser.builder; }
1851
1852 llvm::SMLoc getNameLoc() const override { return nameLoc; }
1853
Chris Lattner1aa46322018-08-21 17:55:22 -07001854 bool resolveOperand(const OperandType &operand, Type *type,
Chris Lattner8bdbebf2018-08-08 11:02:58 -07001855 SmallVectorImpl<SSAValue *> &result) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001856 FunctionParser::SSAUseInfo operandInfo = {operand.name, operand.number,
1857 operand.location};
Chris Lattner8bdbebf2018-08-08 11:02:58 -07001858 if (auto *value = parser.resolveSSAUse(operandInfo, type)) {
1859 result.push_back(value);
1860 return false;
1861 }
1862 return true;
Chris Lattner85ee1512018-07-25 11:15:20 -07001863 }
1864
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001865 /// Emit a diagnostic at the specified location and return true.
1866 bool emitError(llvm::SMLoc loc, const Twine &message) override {
Chris Lattner85ee1512018-07-25 11:15:20 -07001867 parser.emitError(loc, "custom op '" + Twine(opName) + "' " + message);
1868 emittedError = true;
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001869 return true;
Chris Lattner85ee1512018-07-25 11:15:20 -07001870 }
1871
1872 bool didEmitError() const { return emittedError; }
1873
1874private:
1875 SMLoc nameLoc;
1876 StringRef opName;
1877 FunctionParser &parser;
1878 bool emittedError = false;
1879};
1880} // end anonymous namespace.
1881
1882Operation *FunctionParser::parseCustomOperation(
1883 const CreateOperationFunction &createOpFunc) {
1884 auto opLoc = getToken().getLoc();
1885 auto opName = getTokenSpelling();
1886 CustomOpAsmParser opAsmParser(opLoc, opName, *this);
1887
1888 auto *opDefinition = getOperationSet().lookup(opName);
1889 if (!opDefinition) {
1890 opAsmParser.emitError(opLoc, "is unknown");
1891 return nullptr;
1892 }
1893
1894 consumeToken();
1895
Chris Lattner1aa46322018-08-21 17:55:22 -07001896 // If the custom op parser crashes, produce some indication to help debugging.
1897 std::string opNameStr = opName.str();
1898 llvm::PrettyStackTraceFormat fmt("MLIR Parser: custom op parser '%s'",
1899 opNameStr.c_str());
1900
Chris Lattner1628fa02018-08-23 14:32:25 -07001901 // Get location information for the operation.
1902 auto *srcLocation = getEncodedSourceLocation(opLoc);
1903
Chris Lattner85ee1512018-07-25 11:15:20 -07001904 // Have the op implementation take a crack and parsing this.
Chris Lattner1628fa02018-08-23 14:32:25 -07001905 OperationState opState(builder.getContext(), srcLocation, opName);
Chris Lattnereed6c4d2018-08-07 09:12:35 -07001906 if (opDefinition->parseAssembly(&opAsmParser, &opState))
1907 return nullptr;
Chris Lattner85ee1512018-07-25 11:15:20 -07001908
1909 // If it emitted an error, we failed.
1910 if (opAsmParser.didEmitError())
1911 return nullptr;
1912
1913 // Otherwise, we succeeded. Use the state it parsed as our op information.
Chris Lattner992a1272018-08-07 12:02:37 -07001914 return createOpFunc(opState);
Chris Lattner85ee1512018-07-25 11:15:20 -07001915}
1916
Chris Lattner48af7d12018-07-09 19:05:38 -07001917//===----------------------------------------------------------------------===//
1918// CFG Functions
1919//===----------------------------------------------------------------------===//
Chris Lattnere79379a2018-06-22 10:39:19 -07001920
Chris Lattner4c95a502018-06-23 16:03:42 -07001921namespace {
Chris Lattner48af7d12018-07-09 19:05:38 -07001922/// This is a specialized parser for CFGFunction's, maintaining the state
1923/// transient to their bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07001924class CFGFunctionParser : public FunctionParser {
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001925public:
Chris Lattner2e595eb2018-07-10 10:08:27 -07001926 CFGFunctionParser(ParserState &state, CFGFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07001927 : FunctionParser(state, Kind::CFGFunc), function(function),
1928 builder(function) {}
Chris Lattner2e595eb2018-07-10 10:08:27 -07001929
1930 ParseResult parseFunctionBody();
1931
1932private:
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001933 CFGFunction *function;
James Molloy0ff71542018-07-23 16:56:32 -07001934 llvm::StringMap<std::pair<BasicBlock *, SMLoc>> blocksByName;
Chris Lattner48af7d12018-07-09 19:05:38 -07001935
1936 /// This builder intentionally shadows the builder in the base class, with a
1937 /// more specific builder type.
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001938 CFGFuncBuilder builder;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001939
Chris Lattner4c95a502018-06-23 16:03:42 -07001940 /// Get the basic block with the specified name, creating it if it doesn't
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001941 /// already exist. The location specified is the point of use, which allows
1942 /// us to diagnose references to blocks that are not defined precisely.
1943 BasicBlock *getBlockNamed(StringRef name, SMLoc loc) {
1944 auto &blockAndLoc = blocksByName[name];
1945 if (!blockAndLoc.first) {
Chris Lattner3a467cc2018-07-01 20:28:00 -07001946 blockAndLoc.first = new BasicBlock();
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001947 blockAndLoc.second = loc;
Chris Lattner4c95a502018-06-23 16:03:42 -07001948 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001949 return blockAndLoc.first;
Chris Lattner4c95a502018-06-23 16:03:42 -07001950 }
Chris Lattner48af7d12018-07-09 19:05:38 -07001951
James Molloy61a656c2018-07-22 15:45:24 -07001952 ParseResult
1953 parseOptionalBasicBlockArgList(SmallVectorImpl<BBArgument *> &results,
1954 BasicBlock *owner);
James Molloy4f788372018-07-24 15:01:27 -07001955 ParseResult parseBranchBlockAndUseList(BasicBlock *&block,
1956 SmallVectorImpl<CFGValue *> &values);
James Molloy61a656c2018-07-22 15:45:24 -07001957
Chris Lattner48af7d12018-07-09 19:05:38 -07001958 ParseResult parseBasicBlock();
Chris Lattner48af7d12018-07-09 19:05:38 -07001959 TerminatorInst *parseTerminator();
Chris Lattner4c95a502018-06-23 16:03:42 -07001960};
1961} // end anonymous namespace
1962
James Molloy61a656c2018-07-22 15:45:24 -07001963/// Parse a (possibly empty) list of SSA operands with types as basic block
Chris Lattner2c402672018-07-23 11:56:17 -07001964/// arguments.
James Molloy61a656c2018-07-22 15:45:24 -07001965///
1966/// ssa-id-and-type-list ::= ssa-id-and-type (`,` ssa-id-and-type)*
1967///
1968ParseResult CFGFunctionParser::parseOptionalBasicBlockArgList(
1969 SmallVectorImpl<BBArgument *> &results, BasicBlock *owner) {
1970 if (getToken().is(Token::r_brace))
1971 return ParseSuccess;
1972
1973 return parseCommaSeparatedList([&]() -> ParseResult {
1974 auto type = parseSSADefOrUseAndType<Type *>(
1975 [&](SSAUseInfo useInfo, Type *type) -> Type * {
1976 BBArgument *arg = owner->addArgument(type);
Chris Lattner2b97d502018-08-06 14:19:46 -07001977 if (addDefinition(useInfo, arg))
James Molloy61a656c2018-07-22 15:45:24 -07001978 return nullptr;
1979 return type;
1980 });
1981 return type ? ParseSuccess : ParseFailure;
1982 });
1983}
1984
Chris Lattner48af7d12018-07-09 19:05:38 -07001985ParseResult CFGFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07001986 auto braceLoc = getToken().getLoc();
Chris Lattnerf7702a62018-07-23 17:30:01 -07001987 if (parseToken(Token::l_brace, "expected '{' in CFG function"))
1988 return ParseFailure;
Chris Lattner48af7d12018-07-09 19:05:38 -07001989
1990 // Make sure we have at least one block.
1991 if (getToken().is(Token::r_brace))
1992 return emitError("CFG functions must have at least one basic block");
Chris Lattner4c95a502018-06-23 16:03:42 -07001993
1994 // Parse the list of blocks.
1995 while (!consumeIf(Token::r_brace))
Chris Lattner48af7d12018-07-09 19:05:38 -07001996 if (parseBasicBlock())
Chris Lattner4c95a502018-06-23 16:03:42 -07001997 return ParseFailure;
1998
Chris Lattnerf6d80a02018-06-24 11:18:29 -07001999 // Verify that all referenced blocks were defined. Iteration over a
2000 // StringMap isn't determinstic, but this is good enough for our purposes.
Chris Lattner48af7d12018-07-09 19:05:38 -07002001 for (auto &elt : blocksByName) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002002 auto *bb = elt.second.first;
Chris Lattner3a467cc2018-07-01 20:28:00 -07002003 if (!bb->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002004 return emitError(elt.second.second,
James Molloy0ff71542018-07-23 16:56:32 -07002005 "reference to an undefined basic block '" + elt.first() +
2006 "'");
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002007 }
2008
Chris Lattner40746442018-07-21 14:32:09 -07002009 return finalizeFunction(function, braceLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07002010}
2011
2012/// Basic block declaration.
2013///
2014/// basic-block ::= bb-label instruction* terminator-stmt
2015/// bb-label ::= bb-id bb-arg-list? `:`
2016/// bb-id ::= bare-id
2017/// bb-arg-list ::= `(` ssa-id-and-type-list? `)`
2018///
Chris Lattner48af7d12018-07-09 19:05:38 -07002019ParseResult CFGFunctionParser::parseBasicBlock() {
2020 SMLoc nameLoc = getToken().getLoc();
2021 auto name = getTokenSpelling();
Chris Lattnerf7702a62018-07-23 17:30:01 -07002022 if (parseToken(Token::bare_identifier, "expected basic block name"))
2023 return ParseFailure;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002024
Chris Lattner48af7d12018-07-09 19:05:38 -07002025 auto *block = getBlockNamed(name, nameLoc);
Chris Lattner4c95a502018-06-23 16:03:42 -07002026
2027 // If this block has already been parsed, then this is a redefinition with the
2028 // same block name.
Chris Lattner3a467cc2018-07-01 20:28:00 -07002029 if (block->getFunction())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002030 return emitError(nameLoc, "redefinition of block '" + name.str() + "'");
2031
Chris Lattner78276e32018-07-07 15:48:26 -07002032 // If an argument list is present, parse it.
2033 if (consumeIf(Token::l_paren)) {
James Molloy61a656c2018-07-22 15:45:24 -07002034 SmallVector<BBArgument *, 8> bbArgs;
Chris Lattnerf7702a62018-07-23 17:30:01 -07002035 if (parseOptionalBasicBlockArgList(bbArgs, block) ||
2036 parseToken(Token::r_paren, "expected ')' to end argument list"))
Chris Lattner78276e32018-07-07 15:48:26 -07002037 return ParseFailure;
Chris Lattner78276e32018-07-07 15:48:26 -07002038 }
Chris Lattner4c95a502018-06-23 16:03:42 -07002039
James Molloy61a656c2018-07-22 15:45:24 -07002040 // Add the block to the function.
2041 function->push_back(block);
2042
Chris Lattnerf7702a62018-07-23 17:30:01 -07002043 if (parseToken(Token::colon, "expected ':' after basic block name"))
2044 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07002045
Chris Lattner158e0a3e2018-07-08 20:51:38 -07002046 // Set the insertion point to the block we want to insert new operations into.
Chris Lattner48af7d12018-07-09 19:05:38 -07002047 builder.setInsertionPoint(block);
Chris Lattner158e0a3e2018-07-08 20:51:38 -07002048
Chris Lattner992a1272018-08-07 12:02:37 -07002049 auto createOpFunc = [&](const OperationState &result) -> Operation * {
2050 return builder.createOperation(result);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002051 };
2052
Chris Lattnered65a732018-06-28 20:45:33 -07002053 // Parse the list of operations that make up the body of the block.
James Molloy4f788372018-07-24 15:01:27 -07002054 while (getToken().isNot(Token::kw_return, Token::kw_br, Token::kw_cond_br)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002055 if (parseOperation(createOpFunc))
Chris Lattnered65a732018-06-28 20:45:33 -07002056 return ParseFailure;
2057 }
Chris Lattner4c95a502018-06-23 16:03:42 -07002058
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002059 if (!parseTerminator())
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002060 return ParseFailure;
Chris Lattner4c95a502018-06-23 16:03:42 -07002061
2062 return ParseSuccess;
2063}
2064
James Molloy4f788372018-07-24 15:01:27 -07002065ParseResult CFGFunctionParser::parseBranchBlockAndUseList(
2066 BasicBlock *&block, SmallVectorImpl<CFGValue *> &values) {
2067 block = getBlockNamed(getTokenSpelling(), getToken().getLoc());
2068 if (parseToken(Token::bare_identifier, "expected basic block name"))
2069 return ParseFailure;
2070
2071 if (!consumeIf(Token::l_paren))
2072 return ParseSuccess;
2073 if (parseOptionalSSAUseAndTypeList(values, /*isParenthesized*/ false) ||
2074 parseToken(Token::r_paren, "expected ')' to close argument list"))
2075 return ParseFailure;
2076 return ParseSuccess;
2077}
2078
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002079/// Parse the terminator instruction for a basic block.
2080///
2081/// terminator-stmt ::= `br` bb-id branch-use-list?
Chris Lattner1604e472018-07-23 08:42:19 -07002082/// branch-use-list ::= `(` ssa-use-list `)` ':' type-list-no-parens
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002083/// terminator-stmt ::=
2084/// `cond_br` ssa-use `,` bb-id branch-use-list? `,` bb-id branch-use-list?
2085/// terminator-stmt ::= `return` ssa-use-and-type-list?
2086///
Chris Lattner48af7d12018-07-09 19:05:38 -07002087TerminatorInst *CFGFunctionParser::parseTerminator() {
Chris Lattner1628fa02018-08-23 14:32:25 -07002088 auto loc = getToken().getLoc();
2089
Chris Lattner48af7d12018-07-09 19:05:38 -07002090 switch (getToken().getKind()) {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002091 default:
Chris Lattner3a467cc2018-07-01 20:28:00 -07002092 return (emitError("expected terminator at end of basic block"), nullptr);
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002093
Chris Lattner40746442018-07-21 14:32:09 -07002094 case Token::kw_return: {
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002095 consumeToken(Token::kw_return);
Chris Lattner40746442018-07-21 14:32:09 -07002096
Chris Lattner2c402672018-07-23 11:56:17 -07002097 // Parse any operands.
2098 SmallVector<CFGValue *, 8> operands;
2099 if (parseOptionalSSAUseAndTypeList(operands, /*isParenthesized*/ false))
2100 return nullptr;
Chris Lattner091a6b52018-08-23 14:58:27 -07002101 return builder.createReturn(getEncodedSourceLocation(loc), operands);
Chris Lattner40746442018-07-21 14:32:09 -07002102 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002103
2104 case Token::kw_br: {
2105 consumeToken(Token::kw_br);
James Molloy4f788372018-07-24 15:01:27 -07002106 BasicBlock *destBB;
2107 SmallVector<CFGValue *, 4> values;
2108 if (parseBranchBlockAndUseList(destBB, values))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002109 return nullptr;
Chris Lattner091a6b52018-08-23 14:58:27 -07002110 auto branch = builder.createBranch(getEncodedSourceLocation(loc), destBB);
James Molloy4f788372018-07-24 15:01:27 -07002111 branch->addOperands(values);
Chris Lattner1604e472018-07-23 08:42:19 -07002112 return branch;
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002113 }
James Molloy4f788372018-07-24 15:01:27 -07002114
2115 case Token::kw_cond_br: {
2116 consumeToken(Token::kw_cond_br);
2117 SSAUseInfo ssaUse;
2118 if (parseSSAUse(ssaUse))
2119 return nullptr;
2120 auto *cond = resolveSSAUse(ssaUse, builder.getIntegerType(1));
2121 if (!cond)
2122 return (emitError("expected type was boolean (i1)"), nullptr);
2123 if (parseToken(Token::comma, "expected ',' in conditional branch"))
2124 return nullptr;
2125
2126 BasicBlock *trueBlock;
2127 SmallVector<CFGValue *, 4> trueOperands;
2128 if (parseBranchBlockAndUseList(trueBlock, trueOperands))
2129 return nullptr;
2130
2131 if (parseToken(Token::comma, "expected ',' in conditional branch"))
2132 return nullptr;
2133
2134 BasicBlock *falseBlock;
2135 SmallVector<CFGValue *, 4> falseOperands;
2136 if (parseBranchBlockAndUseList(falseBlock, falseOperands))
2137 return nullptr;
2138
Chris Lattner091a6b52018-08-23 14:58:27 -07002139 auto branch =
2140 builder.createCondBranch(getEncodedSourceLocation(loc),
2141 cast<CFGValue>(cond), trueBlock, falseBlock);
James Molloy4f788372018-07-24 15:01:27 -07002142 branch->addTrueOperands(trueOperands);
2143 branch->addFalseOperands(falseOperands);
2144 return branch;
2145 }
Chris Lattnerf6d80a02018-06-24 11:18:29 -07002146 }
2147}
2148
Chris Lattner48af7d12018-07-09 19:05:38 -07002149//===----------------------------------------------------------------------===//
2150// ML Functions
2151//===----------------------------------------------------------------------===//
2152
2153namespace {
2154/// Refined parser for MLFunction bodies.
Chris Lattner7f9cc272018-07-19 08:35:28 -07002155class MLFunctionParser : public FunctionParser {
Chris Lattner48af7d12018-07-09 19:05:38 -07002156public:
Chris Lattner48af7d12018-07-09 19:05:38 -07002157 MLFunctionParser(ParserState &state, MLFunction *function)
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -07002158 : FunctionParser(state, Kind::MLFunc), function(function),
Chris Lattnere787b322018-08-08 11:14:57 -07002159 builder(function, function->end()) {}
Chris Lattner48af7d12018-07-09 19:05:38 -07002160
2161 ParseResult parseFunctionBody();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002162
2163private:
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002164 MLFunction *function;
2165
2166 /// This builder intentionally shadows the builder in the base class, with a
2167 /// more specific builder type.
2168 MLFuncBuilder builder;
2169
2170 ParseResult parseForStmt();
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002171 ParseResult parseIntConstant(int64_t &val);
2172 ParseResult parseDimAndSymbolList(SmallVectorImpl<MLValue *> &operands,
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002173 unsigned numDims, unsigned numOperands,
2174 const char *affineStructName);
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002175 ParseResult parseBound(SmallVectorImpl<MLValue *> &operands, AffineMap *&map,
2176 bool isLower);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002177 ParseResult parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002178 ParseResult parseElseClause(IfClause *elseClause);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002179 ParseResult parseStatements(StmtBlock *block);
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002180 ParseResult parseStmtBlock(StmtBlock *block);
Chris Lattner48af7d12018-07-09 19:05:38 -07002181};
2182} // end anonymous namespace
2183
Chris Lattner48af7d12018-07-09 19:05:38 -07002184ParseResult MLFunctionParser::parseFunctionBody() {
Chris Lattner40746442018-07-21 14:32:09 -07002185 auto braceLoc = getToken().getLoc();
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002186
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002187 // Parse statements in this function.
2188 if (parseStmtBlock(function))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002189 return ParseFailure;
Chris Lattner40746442018-07-21 14:32:09 -07002190
Chris Lattner40746442018-07-21 14:32:09 -07002191 return finalizeFunction(function, braceLoc);
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002192}
2193
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002194/// For statement.
2195///
Chris Lattner48af7d12018-07-09 19:05:38 -07002196/// ml-for-stmt ::= `for` ssa-id `=` lower-bound `to` upper-bound
2197/// (`step` integer-literal)? `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002198///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002199ParseResult MLFunctionParser::parseForStmt() {
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002200 consumeToken(Token::kw_for);
2201
Uday Bondhugula67701712018-08-21 16:01:23 -07002202 // Parse induction variable.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002203 if (getToken().isNot(Token::percent_identifier))
2204 return emitError("expected SSA identifier for the loop variable");
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002205
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002206 auto loc = getToken().getLoc();
Tatiana Shpeismand880b352018-07-31 23:14:16 -07002207 StringRef inductionVariableName = getTokenSpelling();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002208 consumeToken(Token::percent_identifier);
2209
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002210 if (parseToken(Token::equal, "expected '='"))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002211 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002212
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002213 // Parse lower bound.
2214 SmallVector<MLValue *, 4> lbOperands;
2215 AffineMap *lbMap = nullptr;
2216 if (parseBound(lbOperands, lbMap, /*isLower*/ true))
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002217 return ParseFailure;
2218
Chris Lattnerf7702a62018-07-23 17:30:01 -07002219 if (parseToken(Token::kw_to, "expected 'to' between bounds"))
2220 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002221
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002222 // Parse upper bound.
2223 SmallVector<MLValue *, 4> ubOperands;
2224 AffineMap *ubMap = nullptr;
2225 if (parseBound(ubOperands, ubMap, /*isLower*/ false))
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002226 return ParseFailure;
2227
Uday Bondhugula67701712018-08-21 16:01:23 -07002228 // Parse step.
2229 int64_t step = 1;
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002230 if (consumeIf(Token::kw_step) && parseIntConstant(step))
2231 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002232
2233 // Create for statement.
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002234 ForStmt *forStmt =
2235 builder.createFor(getEncodedSourceLocation(loc), lbOperands, lbMap,
2236 ubOperands, ubMap, step);
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002237
2238 // Create SSA value definition for the induction variable.
Chris Lattner2b97d502018-08-06 14:19:46 -07002239 if (addDefinition({inductionVariableName, 0, loc}, forStmt))
2240 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002241
2242 // If parsing of the for statement body fails,
2243 // MLIR contains for statement with those nested statements that have been
2244 // successfully parsed.
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002245 if (parseStmtBlock(forStmt))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002246 return ParseFailure;
2247
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002248 // Reset insertion point to the current block.
Chris Lattnere787b322018-08-08 11:14:57 -07002249 builder.setInsertionPointToEnd(forStmt->getBlock());
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002250
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002251 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002252}
2253
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002254/// Parse integer constant as affine constant expression.
2255ParseResult MLFunctionParser::parseIntConstant(int64_t &val) {
2256 bool negate = consumeIf(Token::minus);
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002257
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002258 if (getToken().isNot(Token::integer))
2259 return emitError("expected integer");
2260
2261 auto uval = getToken().getUInt64IntegerValue();
2262
2263 if (!uval.hasValue() || (int64_t)uval.getValue() < 0) {
2264 return emitError("bound or step is too large for affineint");
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002265 }
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002266
2267 val = (int64_t)uval.getValue();
2268 if (negate)
2269 val = -val;
2270 consumeToken();
2271
2272 return ParseSuccess;
2273}
2274
2275/// Dimensions and symbol use list.
2276///
2277/// dim-use-list ::= `(` ssa-use-list? `)`
2278/// symbol-use-list ::= `[` ssa-use-list? `]`
2279/// dim-and-symbol-use-list ::= dim-use-list symbol-use-list?
2280///
2281ParseResult
2282MLFunctionParser::parseDimAndSymbolList(SmallVectorImpl<MLValue *> &operands,
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002283 unsigned numDims, unsigned numOperands,
2284 const char *affineStructName) {
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002285 if (parseToken(Token::l_paren, "expected '('"))
2286 return ParseFailure;
2287
2288 SmallVector<SSAUseInfo, 4> opInfo;
2289 parseOptionalSSAUseList(opInfo);
2290
2291 if (parseToken(Token::r_paren, "expected ')'"))
2292 return ParseFailure;
2293
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002294 if (numDims != opInfo.size())
2295 return emitError("dim operand count and " + Twine(affineStructName) +
2296 " dim count must match");
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002297
2298 if (consumeIf(Token::l_square)) {
2299 parseOptionalSSAUseList(opInfo);
2300 if (parseToken(Token::r_square, "expected ']'"))
2301 return ParseFailure;
2302 }
2303
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002304 if (numOperands != opInfo.size())
2305 return emitError("symbol operand count and " + Twine(affineStructName) +
2306 " symbol count must match");
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002307
2308 // Resolve SSA uses.
2309 Type *affineIntType = builder.getAffineIntType();
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002310 for (unsigned i = 0, e = opInfo.size(); i != e; ++i) {
2311 SSAValue *sval = resolveSSAUse(opInfo[i], affineIntType);
2312 if (!sval)
2313 return ParseFailure;
2314
2315 auto *v = cast<MLValue>(sval);
2316 if (i < numDims && !v->isValidDim())
2317 return emitError(opInfo[i].loc, "value '" + opInfo[i].name.str() +
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002318 "' cannot be used as a dimension id");
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002319 if (i >= numDims && !v->isValidSymbol())
2320 return emitError(opInfo[i].loc, "value '" + opInfo[i].name.str() +
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002321 "' cannot be used as a symbol");
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002322 operands.push_back(v);
2323 }
2324
2325 return ParseSuccess;
2326}
2327
2328// Loop bound.
2329///
2330/// lower-bound ::= `max`? affine-map dim-and-symbol-use-list | shorthand-bound
2331/// upper-bound ::= `min`? affine-map dim-and-symbol-use-list | shorthand-bound
2332/// shorthand-bound ::= ssa-id | `-`? integer-literal
2333///
2334ParseResult MLFunctionParser::parseBound(SmallVectorImpl<MLValue *> &operands,
2335 AffineMap *&map, bool isLower) {
2336 // 'min' / 'max' prefixes are syntactic sugar. Ignore them.
2337 if (isLower)
2338 consumeIf(Token::kw_max);
2339 else
2340 consumeIf(Token::kw_min);
2341
2342 // Parse full form - affine map followed by dim and symbol list.
2343 if (getToken().isAny(Token::hash_identifier, Token::l_paren)) {
2344 map = parseAffineMapReference();
2345 if (!map)
2346 return ParseFailure;
2347
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002348 if (parseDimAndSymbolList(operands, map->getNumDims(),
2349 map->getNumOperands(), "affine map"))
Tatiana Shpeismande8829f2018-08-24 23:38:14 -07002350 return ParseFailure;
2351 return ParseSuccess;
2352 }
2353
2354 // Parse shorthand form.
2355 if (getToken().isAny(Token::minus, Token::integer)) {
2356 int64_t val;
2357 if (!parseIntConstant(val)) {
2358 map = builder.getConstantMap(val);
2359 return ParseSuccess;
2360 }
2361 return ParseFailure;
2362 }
2363
2364 // Parse ssa-id as identity map.
2365 SSAUseInfo opInfo;
2366 if (parseSSAUse(opInfo))
2367 return ParseFailure;
2368
2369 // TODO: improve error message when SSA value is not an affine integer.
2370 // Currently it is 'use of value ... expects different type than prior uses'
2371 if (auto *value = resolveSSAUse(opInfo, builder.getAffineIntType()))
2372 operands.push_back(cast<MLValue>(value));
2373 else
2374 return ParseFailure;
2375
2376 // Create an identity map using dim id for an induction variable and
2377 // symbol otherwise. This representation is optimized for storage.
2378 // Analysis passes may expand it into a multi-dimensional map if desired.
2379 if (isa<ForStmt>(operands[0]))
2380 map = builder.getDimIdentityMap();
2381 else
2382 map = builder.getSymbolIdentityMap();
2383
2384 return ParseSuccess;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002385}
2386
Uday Bondhugulabc535622018-08-07 14:24:38 -07002387/// Parse an affine constraint.
2388/// affine-constraint ::= affine-expr `>=` `0`
2389/// | affine-expr `==` `0`
2390///
2391/// isEq is set to true if the parsed constraint is an equality, false if it is
2392/// an inequality (greater than or equal).
2393///
2394AffineExpr *AffineParser::parseAffineConstraint(bool *isEq) {
2395 AffineExpr *expr = parseAffineExpr();
2396 if (!expr)
2397 return nullptr;
2398
2399 if (consumeIf(Token::greater) && consumeIf(Token::equal) &&
2400 getToken().is(Token::integer)) {
2401 auto dim = getToken().getUnsignedIntegerValue();
2402 if (dim.hasValue() && dim.getValue() == 0) {
2403 consumeToken(Token::integer);
2404 *isEq = false;
2405 return expr;
2406 }
2407 return (emitError("expected '0' after '>='"), nullptr);
2408 }
2409
2410 if (consumeIf(Token::equal) && consumeIf(Token::equal) &&
2411 getToken().is(Token::integer)) {
2412 auto dim = getToken().getUnsignedIntegerValue();
2413 if (dim.hasValue() && dim.getValue() == 0) {
2414 consumeToken(Token::integer);
2415 *isEq = true;
2416 return expr;
2417 }
2418 return (emitError("expected '0' after '=='"), nullptr);
2419 }
2420
2421 return (emitError("expected '== 0' or '>= 0' at end of affine constraint"),
2422 nullptr);
2423}
2424
2425/// Parse an integer set definition.
2426/// integer-set-inline
2427/// ::= dim-and-symbol-id-lists `:` affine-constraint-conjunction
2428/// affine-constraint-conjunction ::= /*empty*/
2429/// | affine-constraint (`,` affine-constraint)*
2430///
2431IntegerSet *AffineParser::parseIntegerSetInline() {
2432 unsigned numDims = 0, numSymbols = 0;
2433
2434 // List of dimensional identifiers.
2435 if (parseDimIdList(numDims))
2436 return nullptr;
2437
2438 // Symbols are optional.
2439 if (getToken().is(Token::l_square)) {
2440 if (parseSymbolIdList(numSymbols))
2441 return nullptr;
2442 }
2443
2444 if (parseToken(Token::colon, "expected ':' or '['") ||
2445 parseToken(Token::l_paren,
2446 "expected '(' at start of integer set constraint list"))
2447 return nullptr;
2448
2449 SmallVector<AffineExpr *, 4> constraints;
2450 SmallVector<bool, 4> isEqs;
2451 auto parseElt = [&]() -> ParseResult {
2452 bool isEq;
2453 auto *elt = parseAffineConstraint(&isEq);
2454 ParseResult res = elt ? ParseSuccess : ParseFailure;
2455 if (elt) {
2456 constraints.push_back(elt);
2457 isEqs.push_back(isEq);
2458 }
2459 return res;
2460 };
2461
2462 // Parse a list of affine constraints (comma-separated) .
2463 // Grammar: affine-constraint-conjunct ::= `(` affine-constraint (`,`
2464 // affine-constraint)* `)
2465 if (parseCommaSeparatedListUntil(Token::r_paren, parseElt, true))
2466 return nullptr;
2467
2468 // Parsed a valid integer set.
2469 return builder.getIntegerSet(numDims, numSymbols, constraints, isEqs);
2470}
2471
2472IntegerSet *Parser::parseIntegerSetInline() {
2473 return AffineParser(state).parseIntegerSetInline();
2474}
2475
2476/// Parse a reference to an integer set.
2477/// integer-set ::= integer-set-id | integer-set-inline
2478/// integer-set-id ::= `@@` suffix-id
2479///
2480IntegerSet *Parser::parseIntegerSetReference() {
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002481 // TODO: change '@@' integer set prefix to '#'.
Uday Bondhugulabc535622018-08-07 14:24:38 -07002482 if (getToken().is(Token::double_at_identifier)) {
2483 // Parse integer set identifier and verify that it exists.
2484 StringRef integerSetId = getTokenSpelling().drop_front(2);
2485 if (getState().integerSetDefinitions.count(integerSetId) == 0)
2486 return (emitError("undefined integer set id '" + integerSetId + "'"),
2487 nullptr);
2488 consumeToken(Token::double_at_identifier);
2489 return getState().integerSetDefinitions[integerSetId];
2490 }
2491 // Try to parse an inline integer set definition.
2492 return parseIntegerSetInline();
2493}
2494
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002495/// If statement.
2496///
Chris Lattner48af7d12018-07-09 19:05:38 -07002497/// ml-if-head ::= `if` ml-if-cond `{` ml-stmt* `}`
2498/// | ml-if-head `else` `if` ml-if-cond `{` ml-stmt* `}`
2499/// ml-if-stmt ::= ml-if-head
2500/// | ml-if-head `else` `{` ml-stmt* `}`
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002501///
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002502ParseResult MLFunctionParser::parseIfStmt() {
Chris Lattner1628fa02018-08-23 14:32:25 -07002503 auto loc = getToken().getLoc();
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002504 consumeToken(Token::kw_if);
Uday Bondhugulabc535622018-08-07 14:24:38 -07002505
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002506 IntegerSet *set = parseIntegerSetReference();
2507 if (!set)
Chris Lattnerf7702a62018-07-23 17:30:01 -07002508 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002509
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002510 SmallVector<MLValue *, 4> operands;
2511 if (parseDimAndSymbolList(operands, set->getNumDims(), set->getNumOperands(),
2512 "integer set"))
Chris Lattnerf7702a62018-07-23 17:30:01 -07002513 return ParseFailure;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002514
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -07002515 IfStmt *ifStmt =
2516 builder.createIf(getEncodedSourceLocation(loc), operands, set);
Uday Bondhugulabc535622018-08-07 14:24:38 -07002517
Chris Lattnere787b322018-08-08 11:14:57 -07002518 IfClause *thenClause = ifStmt->getThen();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002519
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002520 // When parsing of an if statement body fails, the IR contains
2521 // the if statement with the portion of the body that has been
2522 // successfully parsed.
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002523 if (parseStmtBlock(thenClause))
2524 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002525
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002526 if (consumeIf(Token::kw_else)) {
Chris Lattnere787b322018-08-08 11:14:57 -07002527 auto *elseClause = ifStmt->createElse();
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002528 if (parseElseClause(elseClause))
2529 return ParseFailure;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002530 }
2531
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002532 // Reset insertion point to the current block.
Chris Lattnere787b322018-08-08 11:14:57 -07002533 builder.setInsertionPointToEnd(ifStmt->getBlock());
Tatiana Shpeisman3838db72018-07-30 15:18:10 -07002534
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002535 return ParseSuccess;
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002536}
2537
2538ParseResult MLFunctionParser::parseElseClause(IfClause *elseClause) {
2539 if (getToken().is(Token::kw_if)) {
Chris Lattnere787b322018-08-08 11:14:57 -07002540 builder.setInsertionPointToEnd(elseClause);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002541 return parseIfStmt();
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002542 }
2543
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002544 return parseStmtBlock(elseClause);
2545}
2546
2547///
2548/// Parse a list of statements ending with `return` or `}`
2549///
2550ParseResult MLFunctionParser::parseStatements(StmtBlock *block) {
Chris Lattner992a1272018-08-07 12:02:37 -07002551 auto createOpFunc = [&](const OperationState &state) -> Operation * {
2552 return builder.createOperation(state);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002553 };
2554
Chris Lattnere787b322018-08-08 11:14:57 -07002555 builder.setInsertionPointToEnd(block);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002556
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002557 // Parse statements till we see '}' or 'return'.
2558 // Return statement is parsed separately to emit a more intuitive error
2559 // when '}' is missing after the return statement.
2560 while (getToken().isNot(Token::r_brace, Token::kw_return)) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002561 switch (getToken().getKind()) {
2562 default:
2563 if (parseOperation(createOpFunc))
2564 return ParseFailure;
2565 break;
2566 case Token::kw_for:
2567 if (parseForStmt())
2568 return ParseFailure;
2569 break;
2570 case Token::kw_if:
2571 if (parseIfStmt())
2572 return ParseFailure;
2573 break;
2574 } // end switch
2575 }
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002576
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002577 // Parse the return statement.
2578 if (getToken().is(Token::kw_return))
2579 if (parseOperation(createOpFunc))
2580 return ParseFailure;
2581
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002582 return ParseSuccess;
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002583}
2584
2585///
2586/// Parse `{` ml-stmt* `}`
2587///
Tatiana Shpeisman1bcfe982018-07-13 13:03:13 -07002588ParseResult MLFunctionParser::parseStmtBlock(StmtBlock *block) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002589 if (parseToken(Token::l_brace, "expected '{' before statement list") ||
2590 parseStatements(block) ||
Tatiana Shpeismand9b1d862018-08-09 12:28:58 -07002591 parseToken(Token::r_brace, "expected '}' after statement list"))
Tatiana Shpeisman565b9642018-07-16 11:47:09 -07002592 return ParseFailure;
2593
Tatiana Shpeismanbf079c92018-07-03 17:51:28 -07002594 return ParseSuccess;
2595}
2596
Chris Lattner4c95a502018-06-23 16:03:42 -07002597//===----------------------------------------------------------------------===//
2598// Top-level entity parsing.
2599//===----------------------------------------------------------------------===//
2600
Chris Lattner2e595eb2018-07-10 10:08:27 -07002601namespace {
2602/// This parser handles entities that are only valid at the top level of the
2603/// file.
2604class ModuleParser : public Parser {
2605public:
2606 explicit ModuleParser(ParserState &state) : Parser(state) {}
2607
2608 ParseResult parseModule();
2609
2610private:
Chris Lattner4613d9e2018-08-19 21:17:22 -07002611 ParseResult finalizeModule();
2612
Chris Lattner2e595eb2018-07-10 10:08:27 -07002613 ParseResult parseAffineMapDef();
Uday Bondhugulabc535622018-08-07 14:24:38 -07002614 ParseResult parseIntegerSetDef();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002615
2616 // Functions.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002617 ParseResult parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2618 SmallVectorImpl<StringRef> &argNames);
2619 ParseResult parseFunctionSignature(StringRef &name, FunctionType *&type,
2620 SmallVectorImpl<StringRef> *argNames);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002621 ParseResult parseExtFunc();
2622 ParseResult parseCFGFunc();
2623 ParseResult parseMLFunc();
2624};
2625} // end anonymous namespace
2626
2627/// Affine map declaration.
2628///
2629/// affine-map-def ::= affine-map-id `=` affine-map-inline
2630///
2631ParseResult ModuleParser::parseAffineMapDef() {
2632 assert(getToken().is(Token::hash_identifier));
2633
2634 StringRef affineMapId = getTokenSpelling().drop_front();
2635
2636 // Check for redefinitions.
Nicolas Vasilache97298152018-08-27 10:10:42 -07002637 auto *&entry = getState().affineMapDefinitions[affineMapId];
2638 if (entry)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002639 return emitError("redefinition of affine map id '" + affineMapId + "'");
2640
2641 consumeToken(Token::hash_identifier);
2642
2643 // Parse the '='
Chris Lattnerf7702a62018-07-23 17:30:01 -07002644 if (parseToken(Token::equal,
2645 "expected '=' in affine map outlined definition"))
2646 return ParseFailure;
Chris Lattner2e595eb2018-07-10 10:08:27 -07002647
Nicolas Vasilache97298152018-08-27 10:10:42 -07002648 entry = parseAffineMapInline();
2649 if (!entry)
Uday Bondhugulabc535622018-08-07 14:24:38 -07002650 return ParseFailure;
2651
2652 return ParseSuccess;
2653}
2654
2655/// Integer set declaration.
2656///
2657/// integer-set-decl ::= integer-set-id `=` integer-set-inline
2658///
2659ParseResult ModuleParser::parseIntegerSetDef() {
2660 assert(getToken().is(Token::double_at_identifier));
2661
2662 StringRef integerSetId = getTokenSpelling().drop_front(2);
2663
2664 // Check for redefinitions (a default entry is created if one doesn't exist)
Nicolas Vasilache97298152018-08-27 10:10:42 -07002665 auto *&entry = getState().integerSetDefinitions[integerSetId];
2666 if (entry)
Uday Bondhugulabc535622018-08-07 14:24:38 -07002667 return emitError("redefinition of integer set id '" + integerSetId + "'");
2668
2669 consumeToken(Token::double_at_identifier);
2670
2671 // Parse the '='
2672 if (parseToken(Token::equal,
2673 "expected '=' in outlined integer set definition"))
2674 return ParseFailure;
2675
Nicolas Vasilache97298152018-08-27 10:10:42 -07002676 entry = parseIntegerSetInline();
2677 if (!entry)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002678 return ParseFailure;
2679
Chris Lattner2e595eb2018-07-10 10:08:27 -07002680 return ParseSuccess;
2681}
2682
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002683/// Parse a (possibly empty) list of MLFunction arguments with types.
2684///
2685/// ml-argument ::= ssa-id `:` type
2686/// ml-argument-list ::= ml-argument (`,` ml-argument)* | /*empty*/
2687///
2688ParseResult
2689ModuleParser::parseMLArgumentList(SmallVectorImpl<Type *> &argTypes,
2690 SmallVectorImpl<StringRef> &argNames) {
Chris Lattnerf7702a62018-07-23 17:30:01 -07002691 consumeToken(Token::l_paren);
2692
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002693 auto parseElt = [&]() -> ParseResult {
2694 // Parse argument name
2695 if (getToken().isNot(Token::percent_identifier))
2696 return emitError("expected SSA identifier");
2697
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002698 StringRef name = getTokenSpelling();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002699 consumeToken(Token::percent_identifier);
2700 argNames.push_back(name);
2701
Chris Lattnerf7702a62018-07-23 17:30:01 -07002702 if (parseToken(Token::colon, "expected ':'"))
2703 return ParseFailure;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002704
2705 // Parse argument type
2706 auto elt = parseType();
2707 if (!elt)
2708 return ParseFailure;
2709 argTypes.push_back(elt);
2710
2711 return ParseSuccess;
2712 };
2713
Chris Lattner40746442018-07-21 14:32:09 -07002714 return parseCommaSeparatedListUntil(Token::r_paren, parseElt);
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002715}
2716
Chris Lattner2e595eb2018-07-10 10:08:27 -07002717/// Parse a function signature, starting with a name and including the parameter
2718/// list.
2719///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002720/// argument-list ::= type (`,` type)* | /*empty*/ | ml-argument-list
Chris Lattner2e595eb2018-07-10 10:08:27 -07002721/// function-signature ::= function-id `(` argument-list `)` (`->` type-list)?
2722///
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002723ParseResult
2724ModuleParser::parseFunctionSignature(StringRef &name, FunctionType *&type,
2725 SmallVectorImpl<StringRef> *argNames) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07002726 if (getToken().isNot(Token::at_identifier))
2727 return emitError("expected a function identifier like '@foo'");
2728
2729 name = getTokenSpelling().drop_front();
2730 consumeToken(Token::at_identifier);
2731
2732 if (getToken().isNot(Token::l_paren))
2733 return emitError("expected '(' in function signature");
2734
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002735 SmallVector<Type *, 4> argTypes;
2736 ParseResult parseResult;
2737
2738 if (argNames)
2739 parseResult = parseMLArgumentList(argTypes, *argNames);
2740 else
2741 parseResult = parseTypeList(argTypes);
2742
2743 if (parseResult)
Chris Lattner2e595eb2018-07-10 10:08:27 -07002744 return ParseFailure;
2745
2746 // Parse the return type if present.
2747 SmallVector<Type *, 4> results;
2748 if (consumeIf(Token::arrow)) {
2749 if (parseTypeList(results))
2750 return ParseFailure;
2751 }
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002752 type = builder.getFunctionType(argTypes, results);
Chris Lattner2e595eb2018-07-10 10:08:27 -07002753 return ParseSuccess;
2754}
2755
2756/// External function declarations.
2757///
2758/// ext-func ::= `extfunc` function-signature
2759///
2760ParseResult ModuleParser::parseExtFunc() {
2761 consumeToken(Token::kw_extfunc);
Chris Lattner974a8762018-08-17 16:49:42 -07002762 auto loc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002763
2764 StringRef name;
2765 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002766 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002767 return ParseFailure;
2768
2769 // Okay, the external function definition was parsed correctly.
Chris Lattner974a8762018-08-17 16:49:42 -07002770 auto *function = new ExtFunction(name, type);
2771 getModule()->getFunctions().push_back(function);
2772
2773 // Verify no name collision / redefinition.
Chris Lattner4613d9e2018-08-19 21:17:22 -07002774 if (function->getName() != name)
Chris Lattner974a8762018-08-17 16:49:42 -07002775 return emitError(loc,
2776 "redefinition of function named '" + name.str() + "'");
2777
Chris Lattner2e595eb2018-07-10 10:08:27 -07002778 return ParseSuccess;
2779}
2780
2781/// CFG function declarations.
2782///
2783/// cfg-func ::= `cfgfunc` function-signature `{` basic-block+ `}`
2784///
2785ParseResult ModuleParser::parseCFGFunc() {
2786 consumeToken(Token::kw_cfgfunc);
Chris Lattner974a8762018-08-17 16:49:42 -07002787 auto loc = getToken().getLoc();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002788
2789 StringRef name;
2790 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002791 if (parseFunctionSignature(name, type, /*arguments*/ nullptr))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002792 return ParseFailure;
2793
2794 // Okay, the CFG function signature was parsed correctly, create the function.
Chris Lattner974a8762018-08-17 16:49:42 -07002795 auto *function = new CFGFunction(name, type);
2796 getModule()->getFunctions().push_back(function);
2797
2798 // Verify no name collision / redefinition.
Chris Lattner4613d9e2018-08-19 21:17:22 -07002799 if (function->getName() != name)
Chris Lattner974a8762018-08-17 16:49:42 -07002800 return emitError(loc,
2801 "redefinition of function named '" + name.str() + "'");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002802
2803 return CFGFunctionParser(getState(), function).parseFunctionBody();
2804}
2805
2806/// ML function declarations.
2807///
2808/// ml-func ::= `mlfunc` ml-func-signature `{` ml-stmt* ml-return-stmt `}`
2809///
2810ParseResult ModuleParser::parseMLFunc() {
2811 consumeToken(Token::kw_mlfunc);
2812
2813 StringRef name;
2814 FunctionType *type = nullptr;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002815 SmallVector<StringRef, 4> argNames;
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002816
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002817 auto loc = getToken().getLoc();
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -07002818 if (parseFunctionSignature(name, type, &argNames))
Chris Lattner2e595eb2018-07-10 10:08:27 -07002819 return ParseFailure;
2820
2821 // Okay, the ML function signature was parsed correctly, create the function.
Chris Lattner974a8762018-08-17 16:49:42 -07002822 auto *function = MLFunction::create(name, type);
2823 getModule()->getFunctions().push_back(function);
2824
2825 // Verify no name collision / redefinition.
Chris Lattner4613d9e2018-08-19 21:17:22 -07002826 if (function->getName() != name)
Chris Lattner974a8762018-08-17 16:49:42 -07002827 return emitError(loc,
2828 "redefinition of function named '" + name.str() + "'");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002829
Tatiana Shpeismanbc3c7492018-08-06 11:54:39 -07002830 // Create the parser.
2831 auto parser = MLFunctionParser(getState(), function);
2832
2833 // Add definitions of the function arguments.
2834 for (unsigned i = 0, e = function->getNumArguments(); i != e; ++i) {
2835 if (parser.addDefinition({argNames[i], 0, loc}, function->getArgument(i)))
2836 return ParseFailure;
2837 }
2838
2839 return parser.parseFunctionBody();
Chris Lattner2e595eb2018-07-10 10:08:27 -07002840}
2841
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002842/// Given an attribute that could refer to a function attribute in the remapping
2843/// table, walk it and rewrite it to use the mapped function. If it doesn't
2844/// refer to anything in the table, then it is returned unmodified.
2845static Attribute *
2846remapFunctionAttrs(Attribute *input,
2847 DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable,
2848 MLIRContext *context) {
2849 // Most attributes are trivially unrelated to function attributes, skip them
2850 // rapidly.
2851 if (!input->isOrContainsFunction())
2852 return input;
2853
2854 // If we have a function attribute, remap it.
2855 if (auto *fnAttr = dyn_cast<FunctionAttr>(input)) {
2856 auto it = remappingTable.find(fnAttr);
2857 return it != remappingTable.end() ? it->second : input;
2858 }
2859
2860 // Otherwise, we must have an array attribute, remap the elements.
2861 auto *arrayAttr = cast<ArrayAttr>(input);
2862 SmallVector<Attribute *, 8> remappedElts;
2863 bool anyChange = false;
2864 for (auto *elt : arrayAttr->getValue()) {
2865 auto *newElt = remapFunctionAttrs(elt, remappingTable, context);
2866 remappedElts.push_back(newElt);
2867 anyChange |= (elt != newElt);
2868 }
2869
2870 if (!anyChange)
2871 return input;
2872
2873 return ArrayAttr::get(remappedElts, context);
2874}
2875
2876/// Remap function attributes to resolve forward references to their actual
2877/// definition.
2878static void remapFunctionAttrsInOperation(
2879 Operation *op, DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable) {
2880 for (auto attr : op->getAttrs()) {
2881 // Do the remapping, if we got the same thing back, then it must contain
2882 // functions that aren't getting remapped.
2883 auto *newVal =
2884 remapFunctionAttrs(attr.second, remappingTable, op->getContext());
2885 if (newVal == attr.second)
2886 continue;
2887
2888 // Otherwise, replace the existing attribute with the new one. It is safe
2889 // to mutate the attribute list while we walk it because underlying
2890 // attribute lists are uniqued and immortal.
2891 op->setAttr(attr.first, newVal);
2892 }
2893}
2894
Chris Lattner4613d9e2018-08-19 21:17:22 -07002895/// Finish the end of module parsing - when the result is valid, do final
2896/// checking.
2897ParseResult ModuleParser::finalizeModule() {
2898
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002899 // Resolve all forward references, building a remapping table of attributes.
2900 DenseMap<FunctionAttr *, FunctionAttr *> remappingTable;
Chris Lattner4613d9e2018-08-19 21:17:22 -07002901 for (auto forwardRef : getState().functionForwardRefs) {
2902 auto name = forwardRef.first;
2903
2904 // Resolve the reference.
2905 auto *resolvedFunction = getModule()->getNamedFunction(name);
2906 if (!resolvedFunction)
2907 return emitError(forwardRef.second.second,
2908 "reference to undefined function '" + name.str() + "'");
2909
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002910 remappingTable[builder.getFunctionAttr(forwardRef.second.first)] =
2911 builder.getFunctionAttr(resolvedFunction);
Chris Lattner4613d9e2018-08-19 21:17:22 -07002912 }
2913
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07002914 // If there was nothing to remap, then we're done.
2915 if (remappingTable.empty())
2916 return ParseSuccess;
2917
2918 // Otherwise, walk the entire module replacing uses of one attribute set with
2919 // the correct ones.
2920 for (auto &fn : *getModule()) {
2921 if (auto *cfgFn = dyn_cast<CFGFunction>(&fn)) {
2922 for (auto &bb : *cfgFn) {
2923 for (auto &inst : bb) {
2924 remapFunctionAttrsInOperation(&inst, remappingTable);
2925 }
2926 }
2927 }
2928
2929 // Otherwise, look at MLFunctions. We ignore ExtFunctions.
2930 auto *mlFn = dyn_cast<MLFunction>(&fn);
2931 if (!mlFn)
2932 continue;
2933
2934 struct MLFnWalker : public StmtWalker<MLFnWalker> {
2935 MLFnWalker(DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable)
2936 : remappingTable(remappingTable) {}
2937 void visitOperationStmt(OperationStmt *opStmt) {
2938 remapFunctionAttrsInOperation(opStmt, remappingTable);
2939 }
2940
2941 DenseMap<FunctionAttr *, FunctionAttr *> &remappingTable;
2942 };
2943
2944 MLFnWalker(remappingTable).walk(mlFn);
2945 }
2946
2947 // Now that all references to the forward definition placeholders are
2948 // resolved, we can deallocate the placeholders.
2949 for (auto forwardRef : getState().functionForwardRefs)
2950 forwardRef.second.first->destroy();
Chris Lattner4613d9e2018-08-19 21:17:22 -07002951 return ParseSuccess;
2952}
2953
Chris Lattnere79379a2018-06-22 10:39:19 -07002954/// This is the top-level module parser.
Chris Lattner2e595eb2018-07-10 10:08:27 -07002955ParseResult ModuleParser::parseModule() {
Chris Lattnere79379a2018-06-22 10:39:19 -07002956 while (1) {
Chris Lattner48af7d12018-07-09 19:05:38 -07002957 switch (getToken().getKind()) {
Chris Lattnere79379a2018-06-22 10:39:19 -07002958 default:
2959 emitError("expected a top level entity");
Chris Lattner2e595eb2018-07-10 10:08:27 -07002960 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002961
Uday Bondhugula015cbb12018-07-03 20:16:08 -07002962 // If we got to the end of the file, then we're done.
Chris Lattnere79379a2018-06-22 10:39:19 -07002963 case Token::eof:
Chris Lattner4613d9e2018-08-19 21:17:22 -07002964 return finalizeModule();
Chris Lattnere79379a2018-06-22 10:39:19 -07002965
2966 // If we got an error token, then the lexer already emitted an error, just
2967 // stop. Someday we could introduce error recovery if there was demand for
2968 // it.
2969 case Token::error:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002970 return ParseFailure;
2971
2972 case Token::hash_identifier:
2973 if (parseAffineMapDef())
2974 return ParseFailure;
2975 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002976
Uday Bondhugulabc535622018-08-07 14:24:38 -07002977 case Token::double_at_identifier:
2978 if (parseIntegerSetDef())
2979 return ParseFailure;
2980 break;
2981
Chris Lattnere79379a2018-06-22 10:39:19 -07002982 case Token::kw_extfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002983 if (parseExtFunc())
2984 return ParseFailure;
Chris Lattnere79379a2018-06-22 10:39:19 -07002985 break;
2986
Chris Lattner4c95a502018-06-23 16:03:42 -07002987 case Token::kw_cfgfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002988 if (parseCFGFunc())
2989 return ParseFailure;
MLIR Teamf85a6262018-06-27 11:03:08 -07002990 break;
Chris Lattner4c95a502018-06-23 16:03:42 -07002991
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002992 case Token::kw_mlfunc:
Chris Lattner2e595eb2018-07-10 10:08:27 -07002993 if (parseMLFunc())
2994 return ParseFailure;
Tatiana Shpeismanc96b5872018-06-28 17:02:32 -07002995 break;
Chris Lattnere79379a2018-06-22 10:39:19 -07002996 }
2997 }
2998}
2999
3000//===----------------------------------------------------------------------===//
3001
3002/// This parses the file specified by the indicated SourceMgr and returns an
3003/// MLIR module if it was valid. If not, it emits diagnostics and returns null.
Chris Lattner7879f842018-09-02 22:01:45 -07003004Module *mlir::parseSourceFile(llvm::SourceMgr &sourceMgr,
3005 MLIRContext *context) {
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003006
Chris Lattner2e595eb2018-07-10 10:08:27 -07003007 // This is the result module we are parsing into.
3008 std::unique_ptr<Module> module(new Module(context));
3009
Chris Lattner7879f842018-09-02 22:01:45 -07003010 ParserState state(sourceMgr, module.get());
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003011 if (ModuleParser(state).parseModule()) {
Chris Lattner2e595eb2018-07-10 10:08:27 -07003012 return nullptr;
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003013 }
Chris Lattner21e67f62018-07-06 10:46:19 -07003014
3015 // Make sure the parse module has no other structural problems detected by the
3016 // verifier.
Chris Lattner7879f842018-09-02 22:01:45 -07003017 //
3018 // TODO(clattner): The verifier should always emit diagnostics when we have
3019 // more location information available. We shouldn't need this hook.
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003020 std::string errorResult;
3021 module->verify(&errorResult);
3022
3023 // We don't have location information for general verifier errors, so emit the
Chris Lattner7879f842018-09-02 22:01:45 -07003024 // error with an unknown location.
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003025 if (!errorResult.empty()) {
Chris Lattner7879f842018-09-02 22:01:45 -07003026 context->emitDiagnostic(UnknownLoc::get(context), errorResult,
3027 MLIRContext::DiagnosticKind::Error);
Chris Lattnerea5c3dc2018-08-21 08:42:19 -07003028 return nullptr;
3029 }
3030
Chris Lattner2e595eb2018-07-10 10:08:27 -07003031 return module.release();
Chris Lattnere79379a2018-06-22 10:39:19 -07003032}